Merge remote-tracking branch 'origin/devlopment' into devlopment

This commit is contained in:
Maple 2025-08-07 14:14:50 +08:00
commit 946c965935
11 changed files with 434 additions and 132 deletions

View File

@ -17,7 +17,7 @@ import type {
RenameFileParams RenameFileParams
} from './type' } from './type'
const { request } = http const { request, requestRaw } = http
// 导出类型定义 // 导出类型定义
export type { export type {
@ -108,7 +108,7 @@ export function uploadFileApi(
const formData = new FormData() const formData = new FormData()
formData.append('file', file) formData.append('file', file)
return request({ return requestRaw({
url: '/businessData/file/add', url: '/businessData/file/add',
method: 'post', method: 'post',
params: { params: {
@ -120,7 +120,16 @@ export function uploadFileApi(
headers: { headers: {
'Content-Type': 'multipart/form-data' 'Content-Type': 'multipart/form-data'
} }
}) }).then(response => response.data)
.catch(error => {
// 确保错误不会抛出,而是返回一个错误对象
console.error('上传文件API错误:', error)
return {
code: 500,
msg: error.message || '上传失败',
success: false
}
})
} }
// 下载文件 // 下载文件

View File

@ -34,6 +34,7 @@ export const regulationApi = {
level: string level: string
remark?: string remark?: string
createBy?: string createBy?: string
createByName?: string
}) => { }) => {
return http.post('/regulation/proposal', data) return http.post('/regulation/proposal', data)
}, },

View File

@ -45,6 +45,7 @@ export interface CreateProposalRequest {
level: RegulationLevel level: RegulationLevel
remark?: string remark?: string
createBy?: string createBy?: string
createByName?: string
} }
// 分页参数接口 // 分页参数接口

View File

@ -161,6 +161,32 @@ const requestNative = async <T = unknown>(config: AxiosRequestConfig): Promise<A
.catch((err: { msg: string }) => Promise.reject(err)) .catch((err: { msg: string }) => Promise.reject(err))
} }
// 完全绕过拦截器的请求方法
const requestRaw = async <T = unknown>(config: AxiosRequestConfig): Promise<AxiosResponse> => {
// 创建一个新的axios实例不包含拦截器
const rawAxios = axios.create({
baseURL: import.meta.env.VITE_API_PREFIX ?? import.meta.env.VITE_API_BASE_URL,
timeout: 30 * 1000,
})
// 只添加请求拦截器来设置token不添加响应拦截器
rawAxios.interceptors.request.use(
(config: AxiosRequestConfig) => {
const token = getToken()
if (token) {
if (!config.headers) {
config.headers = {}
}
config.headers.Authorization = `${token}`
}
return config
},
(error) => Promise.reject(error),
)
return rawAxios.request<T>(config)
}
const createRequest = (method: string) => { const createRequest = (method: string) => {
return <T = any>(url: string, params?: object, config?: AxiosRequestConfig): Promise<ApiRes<T>> => { return <T = any>(url: string, params?: object, config?: AxiosRequestConfig): Promise<ApiRes<T>> => {
return request({ return request({
@ -196,5 +222,6 @@ export default {
del: createRequest('delete'), del: createRequest('delete'),
request, request,
requestNative, requestNative,
requestRaw,
download, download,
} }

View File

@ -64,34 +64,37 @@
@click="handleFolderClick(folder.id)" @click="handleFolderClick(folder.id)"
:tooltip="sidebarCollapsed ? folder.name : ''" :tooltip="sidebarCollapsed ? folder.name : ''"
> >
<div class="folder-icon-wrapper"> <!-- 第一行文件夹图标和名称 -->
<IconFolder class="folder-icon" :style="{ color: folderColor }" /> <div class="folder-main-info">
<div class="folder-icon-wrapper">
<IconFolder class="folder-icon" :style="{ color: folderColor }" />
</div>
<span v-if="!sidebarCollapsed" class="folder-name">{{ folder.name }}</span>
</div> </div>
<span v-if="!sidebarCollapsed">{{ folder.name }}</span>
<!-- 文件夹操作按钮 --> <!-- 第二行文件夹操作按钮 -->
<div v-if="!sidebarCollapsed" class="folder-actions"> <div v-if="!sidebarCollapsed" class="folder-actions-row">
<a-button <a-button
type="text" type="text"
shape="circle" shape="circle"
size="small" size="small"
@click.stop="handleRenameFolder(folder, folder.id, folder.name)" @click.stop="handleRenameFolder(folder, folder.id, folder.name)"
tooltip="重命名" tooltip="重命名"
class="action-btn" class="action-btn"
> >
<icon-edit /> <icon-edit />
</a-button> </a-button>
<a-button <a-button
type="text" type="text"
shape="circle" shape="circle"
size="small" size="small"
@click.stop="handleDeleteFolder(folder)" @click.stop="handleDeleteFolder(folder)"
tooltip="删除" tooltip="删除"
status="danger" status="danger"
class="action-btn" class="action-btn"
> >
<icon-delete /> <icon-delete />
</a-button> </a-button>
</div> </div>
</a-list-item> </a-list-item>
</a-list> </a-list>
@ -610,6 +613,10 @@ const canUpload = computed(() => {
return hasFiles.value && !uploading.value && uploadForm.folderId; return hasFiles.value && !uploading.value && uploadForm.folderId;
}); });
//
const searchKeyword = ref('');
const searchTimeout = ref(null);
// //
const initData = async () => { const initData = async () => {
try { try {
@ -688,10 +695,6 @@ const handlePageSizeChange = (current, size) => {
initData(); initData();
}; };
//
const searchKeyword = ref('');
const searchTimeout = ref(null);
const handleFolderSearch = () => { const handleFolderSearch = () => {
console.log('=== 执行搜索 ==='); console.log('=== 执行搜索 ===');
console.log('搜索关键词:', searchKeyword.value); console.log('搜索关键词:', searchKeyword.value);
@ -1111,9 +1114,6 @@ const handleUploadSubmit = async () => {
!file.error && file.status !== 'removed' && file.status !== 'canceled' !file.error && file.status !== 'removed' && file.status !== 'canceled'
); );
console.log('提交上传 - 所有文件:', fileListTemp.value);
console.log('提交上传 - 有效文件:', validFiles);
if (validFiles.length === 0) { if (validFiles.length === 0) {
Message.warning('请选择有效的文件'); Message.warning('请选择有效的文件');
return; return;
@ -1126,16 +1126,15 @@ const handleUploadSubmit = async () => {
} }
uploading.value = true; uploading.value = true;
let successCount = 0; let hasError = false;
let totalFiles = validFiles.length; let hasFileExists = false;
try { for (const fileItem of validFiles) {
for (const fileItem of validFiles) {
// File // File
const realFile = fileItem.originFileObj || fileItem; const realFile = fileItem.originFileObj || fileItem;
if (!realFile) { if (!realFile) {
fileItem.error = '文件数据无效'; hasError = true;
continue; continue;
} }
@ -1146,56 +1145,50 @@ const handleUploadSubmit = async () => {
const source = axios.CancelToken.source(); const source = axios.CancelToken.source();
cancelTokens.value[fileItem.uid] = source; cancelTokens.value[fileItem.uid] = source;
try { // API
// API const result = await uploadFileApi(
const result = await uploadFileApi( realFile,
realFile, Number(uploadForm.folderId),
Number(uploadForm.folderId), (progressEvent) => {
(progressEvent) => { if (progressEvent.lengthComputable) {
if (progressEvent.lengthComputable) { fileItem.percent = Math.round((progressEvent.loaded / progressEvent.total) * 100);
fileItem.percent = Math.round((progressEvent.loaded / progressEvent.total) * 100); }
} },
}, source.token
source.token );
);
//
// if (result.code === 200) {
if (result.code === 0 && result.success) { fileItem.status = 'success';
fileItem.status = 'success'; fileItem.percent = 100;
fileItem.percent = 100; } else if (result.code === 400 && result.msg && result.msg.includes('已存在')) {
successCount++; //
} else { fileItem.status = 'error';
fileItem.status = 'error'; fileItem.error = '文件已存在';
fileItem.error = result.msg || '上传失败'; hasFileExists = true;
} } else {
} catch (error) { fileItem.status = 'error';
if (!axios.isCancel(error)) { fileItem.error = result.msg || '上传失败';
fileItem.status = 'error'; hasError = true;
fileItem.error = error.message || '上传失败';
}
} }
} }
// //
if (successCount === totalFiles) { if (hasFileExists && !hasError) {
Message.success('所有文件上传成功'); Message.warning('文件已存在');
resetUpload(); } else if (hasError) {
Message.error('上传失败');
} else {
Message.success('上传成功');
// //
if (currentFolderId.value === uploadForm.folderId) { if (currentFolderId.value === uploadForm.folderId) {
loadFiles(currentFolderId.value); loadFiles(currentFolderId.value);
} }
} else if (successCount >= 0) {
Message.warning(`${successCount}/${totalFiles} 个文件上传成功`);
resetUpload();
} else {
Message.error('所有文件上传失败');
} }
} catch (error) {
console.error('上传过程出错:', error); resetUpload();
Message.error('上传过程出错');
} finally { uploading.value = false;
uploading.value = false;
}
}; };
// //
@ -1431,7 +1424,7 @@ onMounted(() => {
.folder-content { .folder-content {
padding: 16px 0; padding: 16px 0;
height: calc(100vh - 280px); /* 为底部分页控件留出空间 */ height: calc(100vh - 320px); /* 为底部分页控件留出更多空间,因为文件夹项现在更高 */
overflow-y: auto; overflow-y: auto;
scrollbar-width: thin; scrollbar-width: thin;
background: rgba(255, 255, 255, 0.6); background: rgba(255, 255, 255, 0.6);
@ -1471,7 +1464,8 @@ onMounted(() => {
transition: all 0.3s ease; transition: all 0.3s ease;
position: relative; position: relative;
display: flex; display: flex;
align-items: center; flex-direction: column;
align-items: flex-start;
border: 1px solid transparent; border: 1px solid transparent;
&:hover { &:hover {
@ -1490,17 +1484,35 @@ onMounted(() => {
} }
} }
/* 文件夹操作按钮样式 */ /* 文件夹主要信息样式 */
.folder-actions { .folder-main-info {
display: none; display: flex;
gap: 6px; align-items: center;
width: 100%;
margin-bottom: 8px;
}
.folder-name {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-left: 12px; margin-left: 12px;
font-size: 14px;
font-weight: 500;
}
/* 文件夹操作按钮样式 */
.folder-actions-row {
display: flex;
gap: 6px;
width: 100%;
justify-content: flex-end;
opacity: 0; opacity: 0;
transition: opacity 0.3s ease; transition: opacity 0.3s ease;
} }
.folder-list-item:hover .folder-actions { .folder-list-item:hover .folder-actions-row {
display: flex;
opacity: 1; opacity: 1;
} }
@ -1518,13 +1530,7 @@ onMounted(() => {
} }
} }
.folder-list-item span { /* 删除旧的span样式因为现在使用.folder-name */
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-right: 8px;
}
/* 顶部导航样式 */ /* 顶部导航样式 */
.file-header { .file-header {
@ -2128,7 +2134,7 @@ onMounted(() => {
} }
/* 确保在折叠状态下不显示操作按钮 */ /* 确保在折叠状态下不显示操作按钮 */
:deep(.folder-sidebar.collapsed) .folder-actions { :deep(.folder-sidebar.collapsed) .folder-actions-row {
display: none; display: none;
} }

View File

@ -63,6 +63,10 @@
共找到 <strong>{{ pagination.total }}</strong> 条记录 共找到 <strong>{{ pagination.total }}</strong> 条记录
</span> </span>
</template> </template>
<template #regulationType="{ record }">
{{ getRegulationTypeName(record.regulationType) }}
</template>
<template #status="{ record }"> <template #status="{ record }">
<a-tag :color="getStatusColor(record.status)"> <a-tag :color="getStatusColor(record.status)">
{{ getStatusText(record.status) }} {{ getStatusText(record.status) }}
@ -105,7 +109,7 @@
<h3>{{ currentProposal.title }}</h3> <h3>{{ currentProposal.title }}</h3>
<div class="detail-meta"> <div class="detail-meta">
<span>提案人: {{ currentProposal.createByName }}</span> <span>提案人: {{ currentProposal.createByName }}</span>
<span>提案类型: {{ currentProposal.regulationType }}</span> <span>提案类型: {{ getRegulationTypeName(currentProposal.regulationType) }}</span>
<span>适用范围: {{ currentProposal.scope }}</span> <span>适用范围: {{ currentProposal.scope }}</span>
<span>级别: <a-tag :color="getLevelColor(currentProposal.level)">{{ getLevelText(currentProposal.level) }}</a-tag></span> <span>级别: <a-tag :color="getLevelColor(currentProposal.level)">{{ getLevelText(currentProposal.level) }}</a-tag></span>
<span>创建时间: {{ formatDate(currentProposal.createTime) }}</span> <span>创建时间: {{ formatDate(currentProposal.createTime) }}</span>
@ -157,7 +161,7 @@ defineOptions({ name: 'ProcessManagement' })
const columns = [ const columns = [
{ title: '提案标题', dataIndex: 'title', key: 'title', width: 200 }, { title: '提案标题', dataIndex: 'title', key: 'title', width: 200 },
{ title: '提案人', dataIndex: 'createByName', key: 'createByName', width: 120 }, { title: '提案人', dataIndex: 'createByName', key: 'createByName', width: 120 },
{ title: '提案类型', dataIndex: 'regulationType', key: 'regulationType', width: 120 }, { title: '提案类型', dataIndex: 'regulationType', key: 'regulationType', slotName: 'regulationType', width: 120 },
{ title: '状态', dataIndex: 'status', key: 'status', slotName: 'status', width: 100 }, { title: '状态', dataIndex: 'status', key: 'status', slotName: 'status', width: 100 },
{ title: '级别', dataIndex: 'level', key: 'level', slotName: 'level', width: 80 }, { title: '级别', dataIndex: 'level', key: 'level', slotName: 'level', width: 80 },
{ title: '创建时间', dataIndex: 'createTime', key: 'createTime', width: 180 }, { title: '创建时间', dataIndex: 'createTime', key: 'createTime', width: 180 },
@ -194,6 +198,9 @@ const currentUser = ref('管理者') // 从用户认证系统获取当前用户I
// store // store
const regulationStore = useRegulationStore() const regulationStore = useRegulationStore()
//
const regulationTypes = ref<RegulationType[]>([])
// //
const getStatusColor = (status: RegulationStatus) => { const getStatusColor = (status: RegulationStatus) => {
const colors = { const colors = {
@ -245,6 +252,24 @@ const getLevelText = (level: RegulationLevel) => {
return texts[level] || '中' return texts[level] || '中'
} }
// ID
const getRegulationTypeName = (typeId: string) => {
const type = regulationTypes.value.find(t => t.typeId === typeId)
return type ? type.typeName : typeId
}
//
const getRegulationTypes = async () => {
try {
const response = await regulationApi.searchRegulationTypes()
if (response.status === 200) {
regulationTypes.value = response.data.records || response.data
}
} catch (error) {
console.error('获取制度类型列表失败:', error)
}
}
// - 使 // - 使
const getTableData = async () => { const getTableData = async () => {
loading.value = true loading.value = true
@ -345,6 +370,7 @@ const handlePageSizeChange = (pageSize: number) => {
onMounted(() => { onMounted(() => {
getTableData() getTableData()
getRegulationTypes()
}) })
</script> </script>

View File

@ -41,6 +41,7 @@
<a-option value="">全部</a-option> <a-option value="">全部</a-option>
<a-option value="DRAFT">草稿</a-option> <a-option value="DRAFT">草稿</a-option>
<a-option value="PUBLISHED">已公告</a-option> <a-option value="PUBLISHED">已公告</a-option>
<a-option value="APPROVED">已公示</a-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
@ -78,6 +79,10 @@
</a-tag> </a-tag>
</template> </template>
<template #regulationType="{ record }">
{{ getRegulationTypeName(record.regulationType) }}
</template>
<template #level="{ record }"> <template #level="{ record }">
<a-tag :color="getLevelColor(record.level)"> <a-tag :color="getLevelColor(record.level)">
{{ getLevelText(record.level) }} {{ getLevelText(record.level) }}
@ -165,7 +170,7 @@
<a-option <a-option
v-for="type in regulationTypes" v-for="type in regulationTypes"
:key="type.typeId" :key="type.typeId"
:value="type.typeName" :value="type.typeId"
:disabled="type.isEnabled === '0'" :disabled="type.isEnabled === '0'"
> >
{{ type.typeName }} {{ type.typeName }}
@ -236,7 +241,7 @@
<h3>{{ currentProposal.title }}</h3> <h3>{{ currentProposal.title }}</h3>
<div class="detail-meta"> <div class="detail-meta">
<span>提案人: {{ currentProposal.createByName }}</span> <span>提案人: {{ currentProposal.createByName }}</span>
<span>提案类型: {{ currentProposal.regulationType }}</span> <span>提案类型: {{ getRegulationTypeName(currentProposal.regulationType) }}</span>
<span>适用范围: {{ currentProposal.scope }}</span> <span>适用范围: {{ currentProposal.scope }}</span>
<span>级别: <a-tag :color="getLevelColor(currentProposal.level)">{{ getLevelText(currentProposal.level) }}</a-tag></span> <span>级别: <a-tag :color="getLevelColor(currentProposal.level)">{{ getLevelText(currentProposal.level) }}</a-tag></span>
<span>创建时间: {{ formatDate(currentProposal.createTime) }}</span> <span>创建时间: {{ formatDate(currentProposal.createTime) }}</span>
@ -326,7 +331,7 @@ defineOptions({ name: 'RegulationProposal' })
const columns = [ const columns = [
{ title: '提案标题', dataIndex: 'title', key: 'title', width: 220 }, { title: '提案标题', dataIndex: 'title', key: 'title', width: 220 },
{ title: '提案人', dataIndex: 'createByName', key: 'createByName', width: 130 }, { title: '提案人', dataIndex: 'createByName', key: 'createByName', width: 130 },
{ title: '提案类型', dataIndex: 'regulationType', key: 'regulationType', width: 130 }, { title: '提案类型', dataIndex: 'regulationType', key: 'regulationType', slotName: 'regulationType', width: 130 },
{ title: '状态', dataIndex: 'status', key: 'status', slotName: 'status', width: 110 }, { title: '状态', dataIndex: 'status', key: 'status', slotName: 'status', width: 110 },
{ title: '级别', dataIndex: 'level', key: 'level', slotName: 'level', width: 90 }, { title: '级别', dataIndex: 'level', key: 'level', slotName: 'level', width: 90 },
{ title: '创建时间', dataIndex: 'createTime', key: 'createTime', width: 200 }, { title: '创建时间', dataIndex: 'createTime', key: 'createTime', width: 200 },
@ -447,6 +452,12 @@ const getLevelText = (level: RegulationLevel) => {
return texts[level] || '中' return texts[level] || '中'
} }
// ID
const getRegulationTypeName = (typeId: string) => {
const type = regulationTypes.value.find(t => t.typeId === typeId)
return type ? type.typeName : typeId
}
// //
const getRegulationTypes = async () => { const getRegulationTypes = async () => {
try { try {
@ -606,6 +617,7 @@ const handleSubmit = async () => {
scope: formData.scope, scope: formData.scope,
level: formData.level, level: formData.level,
remark: formData.remark, remark: formData.remark,
createBy: currentUser.value,
createByName: currentUser.value createByName: currentUser.value
} }
console.log('新增提案数据:', createData) console.log('新增提案数据:', createData)

View File

@ -63,6 +63,10 @@
共找到 <strong>{{ pagination.total }}</strong> 条记录 共找到 <strong>{{ pagination.total }}</strong> 条记录
</span> </span>
</template> </template>
<template #regulationType="{ record }">
{{ getRegulationTypeName(record.regulationType) }}
</template>
<template #confirmStatus="{ record }"> <template #confirmStatus="{ record }">
<a-tag :color="record.confirmStatus === 'CONFIRMED' ? 'green' : 'orange'"> <a-tag :color="record.confirmStatus === 'CONFIRMED' ? 'green' : 'orange'">
{{ record.confirmStatus === 'CONFIRMED' ? '已确认' : '待确认' }} {{ record.confirmStatus === 'CONFIRMED' ? '已确认' : '待确认' }}
@ -170,7 +174,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, onMounted } from 'vue' import { ref, reactive, onMounted } from 'vue'
import type { Regulation } from '@/apis/regulation/type' import type { Regulation, RegulationType } from '@/apis/regulation/type'
import { Message } from '@arco-design/web-vue' import { Message } from '@arco-design/web-vue'
import { IconSearch, IconRefresh } from '@arco-design/web-vue/es/icon' import { IconSearch, IconRefresh } from '@arco-design/web-vue/es/icon'
import { useRegulationStore } from '@/stores/modules/regulation' import { useRegulationStore } from '@/stores/modules/regulation'
@ -182,7 +186,7 @@ defineOptions({ name: 'SystemRegulation' })
// //
const columns = [ const columns = [
{ title: '制度名称', dataIndex: 'title', key: 'title' }, { title: '制度名称', dataIndex: 'title', key: 'title' },
{ title: '制度类型', dataIndex: 'regulationType', key: 'regulationType' }, { title: '制度类型', dataIndex: 'regulationType', key: 'regulationType', slotName: 'regulationType' },
{ title: '公示人', dataIndex: 'createByName', key: 'createByName' }, { title: '公示人', dataIndex: 'createByName', key: 'createByName' },
{ title: '公示时间', dataIndex: 'publishTime', key: 'publishTime' }, { title: '公示时间', dataIndex: 'publishTime', key: 'publishTime' },
{ title: '生效日期', dataIndex: 'effectiveTime', key: 'effectiveTime' }, { title: '生效日期', dataIndex: 'effectiveTime', key: 'effectiveTime' },
@ -218,6 +222,27 @@ const agreeTerms = ref(false)
// store // store
const regulationStore = useRegulationStore() const regulationStore = useRegulationStore()
//
const regulationTypes = ref<RegulationType[]>([])
// ID
const getRegulationTypeName = (typeId: string) => {
const type = regulationTypes.value.find(t => t.typeId === typeId)
return type ? type.typeName : typeId
}
//
const getRegulationTypes = async () => {
try {
const response = await regulationApi.searchRegulationTypes()
if (response.status === 200) {
regulationTypes.value = response.data.records || response.data
}
} catch (error) {
console.error('获取制度类型列表失败:', error)
}
}
// - 使 // - 使
const getTableData = async () => { const getTableData = async () => {
loading.value = true loading.value = true
@ -356,6 +381,7 @@ const submitConfirm = async () => {
onMounted(() => { onMounted(() => {
getTableData() getTableData()
getRegulationTypes()
}) })
</script> </script>

View File

@ -32,6 +32,21 @@
<div class="tab-content"> <div class="tab-content">
<!-- 基本信息 --> <!-- 基本信息 -->
<div v-show="activeTab === 'basic'"> <div v-show="activeTab === 'basic'">
<!-- 测试数据按钮 -->
<div v-if="!isView" class="test-data-section">
<div class="test-data-header">
<span class="test-data-title">🧪 测试数据</span>
<span class="test-data-desc">点击按钮快速填入测试数据方便功能测试</span>
</div>
<a-button
type="primary"
size="small"
@click="fillTestData"
>
📝 填入测试数据
</a-button>
</div>
<a-row :gutter="16"> <a-row :gutter="16">
<a-col :span="12"> <a-col :span="12">
<a-form-item label="设备名称" field="equipmentName"> <a-form-item label="设备名称" field="equipmentName">
@ -173,10 +188,10 @@
<a-form-item label="总价" field="totalPrice"> <a-form-item label="总价" field="totalPrice">
<a-input-number <a-input-number
v-model="formData.totalPrice" v-model="formData.totalPrice"
placeholder="请输入总价" placeholder="自动计算"
:precision="2" :precision="2"
:min="0" :min="0"
:disabled="isView" :disabled="true"
style="width: 100%" style="width: 100%"
/> />
</a-form-item> </a-form-item>
@ -219,6 +234,8 @@
:disabled="isView" :disabled="isView"
show-time show-time
style="width: 100%" style="width: 100%"
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
/> />
</a-form-item> </a-form-item>
</a-col> </a-col>
@ -230,6 +247,8 @@
:disabled="isView" :disabled="isView"
show-time show-time
style="width: 100%" style="width: 100%"
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
/> />
</a-form-item> </a-form-item>
</a-col> </a-col>
@ -244,6 +263,8 @@
:disabled="isView" :disabled="isView"
show-time show-time
style="width: 100%" style="width: 100%"
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
/> />
</a-form-item> </a-form-item>
</a-col> </a-col>
@ -253,7 +274,10 @@
v-model="formData.expectedScrapTime" v-model="formData.expectedScrapTime"
placeholder="请选择预计报废时间" placeholder="请选择预计报废时间"
:disabled="isView" :disabled="isView"
show-time
style="width: 100%" style="width: 100%"
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
/> />
</a-form-item> </a-form-item>
</a-col> </a-col>
@ -306,7 +330,10 @@
v-model="formData.warrantyExpireDate" v-model="formData.warrantyExpireDate"
placeholder="请选择保修截止日期" placeholder="请选择保修截止日期"
:disabled="isView" :disabled="isView"
show-time
style="width: 100%" style="width: 100%"
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
/> />
</a-form-item> </a-form-item>
</a-col> </a-col>
@ -418,7 +445,10 @@
v-model="formData.lastMaintenanceDate" v-model="formData.lastMaintenanceDate"
placeholder="请选择上次维护日期" placeholder="请选择上次维护日期"
:disabled="isView" :disabled="isView"
show-time
style="width: 100%" style="width: 100%"
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
/> />
</a-form-item> </a-form-item>
</a-col> </a-col>
@ -428,7 +458,10 @@
v-model="formData.nextMaintenanceDate" v-model="formData.nextMaintenanceDate"
placeholder="请选择下次维护日期" placeholder="请选择下次维护日期"
:disabled="isView" :disabled="isView"
show-time
style="width: 100%" style="width: 100%"
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
/> />
</a-form-item> </a-form-item>
</a-col> </a-col>
@ -596,9 +629,8 @@ const equipmentTypeOptions = [
const equipmentStatusOptions = [ const equipmentStatusOptions = [
{ label: '正常', value: 'normal' }, { label: '正常', value: 'normal' },
{ label: '维修中', value: 'repair' }, { label: '维修中', value: 'repair' },
{ label: '已报废', value: 'scrap' }, { label: '保养中', value: 'maintain' },
{ label: '闲置', value: 'idle' }, { label: '报废', value: 'scrap' },
{ label: '丢失', value: 'lost' },
] ]
const useStatusOptions = [ const useStatusOptions = [
@ -607,13 +639,14 @@ const useStatusOptions = [
] ]
const locationStatusOptions = [ const locationStatusOptions = [
{ label: '未入库', value: 'not_in_stock' },
{ label: '库存中', value: 'in_stock' }, { label: '库存中', value: 'in_stock' },
{ label: '使用中', value: 'in_use' }, { label: '已分配', value: 'allocated' },
{ label: '维修中', value: 'repair' }, { label: '维修中', value: 'repair' },
{ label: '待报废', value: 'scrap' },
{ label: '已报废', value: 'scrapped' }, { label: '已报废', value: 'scrapped' },
{ label: '外借中', value: 'on_loan' }, { label: '外借中', value: 'borrowed' },
{ label: '丢失', value: 'lost' }, { label: '丢失', value: 'lost' },
{ label: '闲置', value: 'idle' },
] ]
const healthStatusOptions = [ const healthStatusOptions = [
@ -650,6 +683,15 @@ watch(() => props.visible, (newVal) => {
} }
}) })
//
watch([() => formData.unitPrice, () => formData.quantity], ([newUnitPrice, newQuantity]) => {
if (newUnitPrice && newQuantity) {
formData.totalPrice = Number((newUnitPrice * newQuantity).toFixed(2))
} else {
formData.totalPrice = undefined
}
})
// //
const initFormData = () => { const initFormData = () => {
if (props.procurementData) { if (props.procurementData) {
@ -709,7 +751,7 @@ const resetForm = () => {
assetCode: '', assetCode: '',
brand: '', brand: '',
specification: '', specification: '',
locationStatus: '', locationStatus: 'not_in_stock', // ""
physicalLocation: '', physicalLocation: '',
responsiblePerson: '', responsiblePerson: '',
healthStatus: '', healthStatus: '',
@ -765,6 +807,107 @@ const handleSubmit = async () => {
} }
} }
//
const fillTestData = () => {
//
const now = new Date()
const currentTime = now.toISOString().slice(0, 19).replace('T', ' ')
//
const futureDate = new Date(now.getTime() + 365 * 24 * 60 * 60 * 1000) //
const futureTime = futureDate.toISOString().slice(0, 19).replace('T', ' ')
//
const pastDate = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000) // 30
const pastTime = pastDate.toISOString().slice(0, 19).replace('T', ' ')
// 7
const inStockDate = new Date(pastDate.getTime() + 7 * 24 * 60 * 60 * 1000)
const inStockTime = inStockDate.toISOString().slice(0, 19).replace('T', ' ')
// 3
const activationDate = new Date(inStockDate.getTime() + 3 * 24 * 60 * 60 * 1000)
const activationTime = activationDate.toISOString().slice(0, 19).replace('T', ' ')
// 2
const warrantyDate = new Date(pastDate.getTime() + 2 * 365 * 24 * 60 * 60 * 1000)
const warrantyTime = warrantyDate.toISOString().slice(0, 19).replace('T', ' ')
//
const lastMaintenanceDate = new Date(now.getTime() - 15 * 24 * 60 * 60 * 1000) // 15
const lastMaintenanceTime = lastMaintenanceDate.toISOString().slice(0, 19).replace('T', ' ')
const nextMaintenanceDate = new Date(now.getTime() + 15 * 24 * 60 * 60 * 1000) // 15
const nextMaintenanceTime = nextMaintenanceDate.toISOString().slice(0, 19).replace('T', ' ')
//
const randomSn = 'SN' + Math.random().toString(36).substr(2, 8).toUpperCase()
//
const randomAssetCode = 'ZC' + Math.random().toString(36).substr(2, 6).toUpperCase()
//
const randomPurchaseOrder = 'PO' + Math.random().toString(36).substr(2, 8).toUpperCase()
//
const randomBarcode = 'BC' + Math.random().toString(36).substr(2, 10).toUpperCase()
//
const randomAccountNumber = 'AC' + Math.random().toString(36).substr(2, 6).toUpperCase()
//
formData.unitPrice = 8999.00
formData.quantity = 2
Object.assign(formData, {
//
equipmentName: '高清工业相机系统',
equipmentModel: 'IC-2000Pro',
equipmentType: 'detection',
equipmentSn: randomSn,
brand: '海康威视',
assetCode: randomAssetCode,
specification: '分辨率4K帧率60fps接口USB3.0支持AI识别防水等级IP67',
//
purchaseOrder: randomPurchaseOrder,
supplierName: '海康威视官方旗舰店',
// quantity unitPrice totalPrice
purchasePrice: 17998.00,
currentNetValue: 17998.00,
depreciationMethod: 'straight_line',
depreciationYears: 5,
salvageValue: 899.90,
//
purchaseTime: pastTime,
inStockTime: inStockTime,
activationTime: activationTime,
expectedScrapTime: futureTime,
warrantyExpireDate: warrantyTime,
lastMaintenanceDate: lastMaintenanceTime,
nextMaintenanceDate: nextMaintenanceTime,
//
equipmentStatus: 'normal',
useStatus: '1',
locationStatus: 'in_stock',
healthStatus: 'excellent',
responsiblePerson: '张工程师',
maintenancePerson: '李维护员',
physicalLocation: 'A区-3楼-设备间-01号柜',
inventoryBarcode: randomBarcode,
//
accountNumber: randomAccountNumber,
inventoryBasis: '月度盘点',
dynamicRecord: '设备运行正常,定期维护保养,性能稳定,满足生产需求。',
assetRemark: '重要检测设备,需定期校准,专人负责维护。',
})
Message.success('测试数据已填入!')
}
// //
const handleCancel = () => { const handleCancel = () => {
emit('update:visible', false) emit('update:visible', false)
@ -845,6 +988,52 @@ const handleCancel = () => {
} }
} }
//
.test-data-section {
background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%);
border: 1px solid #bae6fd;
border-radius: 8px;
padding: 12px 16px;
margin-bottom: 20px;
.test-data-header {
display: flex;
flex-direction: column;
margin-bottom: 12px;
.test-data-title {
font-weight: 600;
color: #1e40af;
font-size: 14px;
margin-bottom: 4px;
}
.test-data-desc {
color: #64748b;
font-size: 12px;
line-height: 1.4;
}
}
.arco-btn {
background: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%);
border: none;
color: white;
font-weight: 500;
box-shadow: 0 2px 4px rgba(59, 130, 246, 0.3);
transition: all 0.3s ease;
&:hover {
transform: translateY(-1px);
box-shadow: 0 4px 8px rgba(59, 130, 246, 0.4);
}
&:active {
transform: translateY(0);
}
}
}
// //
@media (max-width: 768px) { @media (max-width: 768px) {
.tab-navigation { .tab-navigation {
@ -861,5 +1050,10 @@ const handleCancel = () => {
} }
} }
} }
.test-data-section {
padding: 8px 12px;
margin-bottom: 16px;
}
} }
</style> </style>

View File

@ -93,9 +93,8 @@
> >
<a-option value="normal">正常</a-option> <a-option value="normal">正常</a-option>
<a-option value="repair">维修中</a-option> <a-option value="repair">维修中</a-option>
<a-option value="scrap">已报废</a-option> <a-option value="maintain">保养中</a-option>
<a-option value="idle">闲置</a-option> <a-option value="scrap">报废</a-option>
<a-option value="lost">丢失</a-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
</a-col> </a-col>
@ -106,13 +105,14 @@
placeholder="请选择位置状态" placeholder="请选择位置状态"
allow-clear allow-clear
> >
<a-option value="not_in_stock">未入库</a-option>
<a-option value="in_stock">库存中</a-option> <a-option value="in_stock">库存中</a-option>
<a-option value="in_use">使用中</a-option> <a-option value="allocated">已分配</a-option>
<a-option value="repair">维修中</a-option> <a-option value="repair">维修中</a-option>
<a-option value="scrap">待报废</a-option>
<a-option value="scrapped">已报废</a-option> <a-option value="scrapped">已报废</a-option>
<a-option value="on_loan">外借中</a-option> <a-option value="borrowed">外借中</a-option>
<a-option value="lost">丢失</a-option> <a-option value="lost">丢失</a-option>
<a-option value="idle">闲置</a-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
</a-col> </a-col>

View File

@ -360,9 +360,8 @@ const getEquipmentStatusColor = (status: string) => {
const colorMap: Record<string, string> = { const colorMap: Record<string, string> = {
normal: 'green', normal: 'green',
repair: 'orange', repair: 'orange',
maintain: 'blue',
scrap: 'red', scrap: 'red',
idle: 'blue',
lost: 'gray',
} }
return colorMap[status] || 'blue' return colorMap[status] || 'blue'
} }
@ -372,9 +371,8 @@ const getEquipmentStatusText = (status: string) => {
const textMap: Record<string, string> = { const textMap: Record<string, string> = {
normal: '正常', normal: '正常',
repair: '维修中', repair: '维修中',
scrap: '已报废', maintain: '保养中',
idle: '闲置', scrap: '报废',
lost: '丢失',
} }
return textMap[status] || '未知' return textMap[status] || '未知'
} }
@ -382,13 +380,14 @@ const getEquipmentStatusText = (status: string) => {
// //
const getLocationStatusColor = (status: string) => { const getLocationStatusColor = (status: string) => {
const colorMap: Record<string, string> = { const colorMap: Record<string, string> = {
not_in_stock: 'gray',
in_stock: 'blue', in_stock: 'blue',
in_use: 'green', allocated: 'green',
repair: 'orange', repair: 'orange',
scrap: 'red',
scrapped: 'red', scrapped: 'red',
on_loan: 'purple', borrowed: 'purple',
lost: 'gray', lost: 'gray',
idle: 'cyan',
} }
return colorMap[status] || 'blue' return colorMap[status] || 'blue'
} }
@ -396,13 +395,14 @@ const getLocationStatusColor = (status: string) => {
// //
const getLocationStatusText = (status: string) => { const getLocationStatusText = (status: string) => {
const textMap: Record<string, string> = { const textMap: Record<string, string> = {
not_in_stock: '未入库',
in_stock: '库存中', in_stock: '库存中',
in_use: '使用中', allocated: '已分配',
repair: '维修中', repair: '维修中',
scrap: '待报废',
scrapped: '已报废', scrapped: '已报废',
on_loan: '外借中', borrowed: '外借中',
lost: '丢失', lost: '丢失',
idle: '闲置',
} }
return textMap[status] || '未知' return textMap[status] || '未知'
} }