Compare commits
12 Commits
ljy/master
...
main
Author | SHA1 | Date |
---|---|---|
|
36b076f987 | |
|
895bfcbeaf | |
|
7f654625aa | |
|
864f926f2e | |
|
69b4bf86bd | |
|
48f4020fc8 | |
|
0eb12b4df9 | |
|
77238c3d03 | |
|
7e006acaa6 | |
|
2065389094 | |
|
4972dcaf4d | |
|
c7043dbdb1 |
|
@ -5,7 +5,6 @@ VITE_API_PREFIX = '/dev-api'
|
||||||
# 接口地址
|
# 接口地址
|
||||||
# VITE_API_BASE_URL = 'http://pms.dtyx.net:9158/'
|
# VITE_API_BASE_URL = 'http://pms.dtyx.net:9158/'
|
||||||
VITE_API_BASE_URL = 'http://localhost:8888/'
|
VITE_API_BASE_URL = 'http://localhost:8888/'
|
||||||
# VITE_API_BASE_URL = 'http://10.18.34.213:8888/'
|
|
||||||
|
|
||||||
# 接口地址 (WebSocket)
|
# 接口地址 (WebSocket)
|
||||||
VITE_API_WS_URL = 'ws://localhost:8000'
|
VITE_API_WS_URL = 'ws://localhost:8000'
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
import http from '@/utils/http'
|
||||||
|
|
||||||
|
const { request } = http
|
||||||
|
|
||||||
|
// 文件信息
|
||||||
|
export interface KnowledgeFile {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
size: string
|
||||||
|
type: string
|
||||||
|
uploadTime: string
|
||||||
|
}
|
||||||
|
|
||||||
|
// 文件夹信息
|
||||||
|
export interface KnowledgeFolder {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
children?: KnowledgeFolder[]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取文件夹树
|
||||||
|
export function getFolderTreeApi() {
|
||||||
|
return request<KnowledgeFolder[]>({
|
||||||
|
url: '/knowledge/folders',
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取文件列表(按文件夹)
|
||||||
|
export function getFilesApi(folderId: string) {
|
||||||
|
return request<KnowledgeFile[]>({
|
||||||
|
url: '/knowledge/files',
|
||||||
|
method: 'get',
|
||||||
|
params: { folderId },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建文件夹
|
||||||
|
export function createFolderApi(data: { name: string; parentId?: string }) {
|
||||||
|
return request({
|
||||||
|
url: '/knowledge/create-folder',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除文件
|
||||||
|
export function deleteFileApi(fileId: string) {
|
||||||
|
return request({
|
||||||
|
url: `/knowledge/delete-file/${fileId}`,
|
||||||
|
method: 'delete',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下载文件
|
||||||
|
export function downloadFileApi(fileId: string) {
|
||||||
|
return request<Blob>({
|
||||||
|
url: `/knowledge/download/${fileId}`,
|
||||||
|
method: 'get',
|
||||||
|
responseType: 'blob',
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
import http from '@/utils/http'
|
||||||
|
import type * as T from '@/types/equipment.d'
|
||||||
|
|
||||||
|
const BASE_URL = '/equipment'
|
||||||
|
|
||||||
|
/** @desc 分页查询设备列表 */
|
||||||
|
export function pageEquipment(query: T.EquipmentPageQuery) {
|
||||||
|
return http.get<T.EquipmentResp[]>(`${BASE_URL}/page`, query)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @desc 查询设备列表 */
|
||||||
|
export function listEquipment(query?: T.EquipmentPageQuery) {
|
||||||
|
return http.get<T.EquipmentResp[]>(`${BASE_URL}/list`, query)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @desc 查询设备详情 */
|
||||||
|
export function getEquipmentDetail(equipmentId: string) {
|
||||||
|
return http.get<T.EquipmentResp>(`${BASE_URL}/detail/${equipmentId}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @desc 新增设备 */
|
||||||
|
export function createEquipment(data: T.EquipmentReq) {
|
||||||
|
return http.post(`${BASE_URL}`, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @desc 更新设备 */
|
||||||
|
export function updateEquipment(equipmentId: string, data: T.EquipmentReq) {
|
||||||
|
return http.put(`${BASE_URL}/${equipmentId}`, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @desc 删除设备 */
|
||||||
|
export function deleteEquipment(equipmentId: string) {
|
||||||
|
return http.del(`${BASE_URL}/${equipmentId}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @desc 设备状态变更 */
|
||||||
|
export function changeEquipmentStatus(equipmentId: string, status: string) {
|
||||||
|
return http.put(`${BASE_URL}/${equipmentId}/status`, { status })
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @desc 设备分配 */
|
||||||
|
export function assignEquipment(equipmentId: string, userId: string) {
|
||||||
|
return http.put(`${BASE_URL}/${equipmentId}/assign`, { userId })
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @desc 设备归还 */
|
||||||
|
export function returnEquipment(equipmentId: string) {
|
||||||
|
return http.put(`${BASE_URL}/${equipmentId}/return`)
|
||||||
|
}
|
|
@ -0,0 +1,277 @@
|
||||||
|
/**
|
||||||
|
* 设备列表查询请求
|
||||||
|
*/
|
||||||
|
export interface EquipmentListReq {
|
||||||
|
/** 最低价格 */
|
||||||
|
minPrice?: number
|
||||||
|
/** 最高价格 */
|
||||||
|
maxPrice?: number
|
||||||
|
/** 设备名称 */
|
||||||
|
equipmentName?: string
|
||||||
|
/** 设备类型 */
|
||||||
|
equipmentType?: string
|
||||||
|
/** 设备状态 */
|
||||||
|
equipmentStatus?: string
|
||||||
|
/** 设备序列号 */
|
||||||
|
equipmentSn?: string
|
||||||
|
/** 资产编号 */
|
||||||
|
assetCode?: string
|
||||||
|
/** 品牌 */
|
||||||
|
brand?: string
|
||||||
|
/** 位置状态 */
|
||||||
|
locationStatus?: string
|
||||||
|
/** 健康状态 */
|
||||||
|
healthStatus?: string
|
||||||
|
/** 负责人 */
|
||||||
|
responsiblePerson?: string
|
||||||
|
/** 使用状态 */
|
||||||
|
useStatus?: string
|
||||||
|
/** 项目ID */
|
||||||
|
projectId?: string
|
||||||
|
/** 使用人ID */
|
||||||
|
userId?: string
|
||||||
|
/** 设备型号 */
|
||||||
|
equipmentModel?: string
|
||||||
|
/** 配置规格/参数 */
|
||||||
|
specification?: string
|
||||||
|
/** 设备当前物理位置 */
|
||||||
|
physicalLocation?: string
|
||||||
|
/** 供应商名称 */
|
||||||
|
supplierName?: string
|
||||||
|
/** 采购订单号 */
|
||||||
|
purchaseOrder?: string
|
||||||
|
/** 维护人员 */
|
||||||
|
maintenancePerson?: string
|
||||||
|
/** 次户号 */
|
||||||
|
accountNumber?: string
|
||||||
|
/** 数量 */
|
||||||
|
quantity?: number
|
||||||
|
/** 单价 */
|
||||||
|
unitPrice?: number
|
||||||
|
/** 总价 */
|
||||||
|
totalPrice?: number
|
||||||
|
/** 盘点依据 */
|
||||||
|
inventoryBasis?: string
|
||||||
|
/** 动态记录 */
|
||||||
|
dynamicRecord?: string
|
||||||
|
/** 资产备注 */
|
||||||
|
assetRemark?: string
|
||||||
|
/** 采购时间开始 */
|
||||||
|
purchaseTimeStart?: string
|
||||||
|
/** 采购时间结束 */
|
||||||
|
purchaseTimeEnd?: string
|
||||||
|
/** 入库时间开始 */
|
||||||
|
inStockTimeStart?: string
|
||||||
|
/** 入库时间结束 */
|
||||||
|
inStockTimeEnd?: string
|
||||||
|
/** 启用时间开始 */
|
||||||
|
activationTimeStart?: string
|
||||||
|
/** 启用时间结束 */
|
||||||
|
activationTimeEnd?: string
|
||||||
|
/** 当前页码 */
|
||||||
|
pageNum?: number
|
||||||
|
/** 每页大小 */
|
||||||
|
pageSize?: number
|
||||||
|
/** 排序字段 */
|
||||||
|
orderBy?: string
|
||||||
|
/** 排序方向 */
|
||||||
|
orderDirection?: string
|
||||||
|
/** 页码 */
|
||||||
|
page?: number
|
||||||
|
/** 库存条码 */
|
||||||
|
inventoryBarcode?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页响应格式
|
||||||
|
*/
|
||||||
|
export interface PageResult<T> {
|
||||||
|
code: number
|
||||||
|
msg: string
|
||||||
|
rows: T[]
|
||||||
|
total: number
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备信息响应
|
||||||
|
*/
|
||||||
|
export interface EquipmentResp {
|
||||||
|
/** 设备ID */
|
||||||
|
equipmentId: string
|
||||||
|
/** 资产编号 */
|
||||||
|
assetCode?: string
|
||||||
|
/** 设备名称 */
|
||||||
|
equipmentName: string
|
||||||
|
/** 设备类型 */
|
||||||
|
equipmentType: string
|
||||||
|
/** 设备类型描述 */
|
||||||
|
equipmentTypeLabel?: string
|
||||||
|
/** 设备型号 */
|
||||||
|
equipmentModel: string
|
||||||
|
/** 设备SN */
|
||||||
|
equipmentSn: string
|
||||||
|
/** 品牌 */
|
||||||
|
brand?: string
|
||||||
|
/** 配置规格/参数 */
|
||||||
|
specification?: string
|
||||||
|
/** 设备状态 */
|
||||||
|
equipmentStatus: string
|
||||||
|
/** 设备状态描述 */
|
||||||
|
equipmentStatusLabel?: string
|
||||||
|
/** 使用状态 */
|
||||||
|
useStatus: string
|
||||||
|
/** 位置状态 */
|
||||||
|
locationStatus?: string
|
||||||
|
/** 位置状态描述 */
|
||||||
|
locationStatusLabel?: string
|
||||||
|
/** 设备当前物理位置 */
|
||||||
|
physicalLocation?: string
|
||||||
|
/** 负责人 */
|
||||||
|
responsiblePerson?: string
|
||||||
|
/** 健康状态 */
|
||||||
|
healthStatus?: string
|
||||||
|
/** 健康状态描述 */
|
||||||
|
healthStatusLabel?: string
|
||||||
|
/** 采购时间 */
|
||||||
|
purchaseTime?: string
|
||||||
|
/** 入库时间 */
|
||||||
|
inStockTime?: string
|
||||||
|
/** 启用时间 */
|
||||||
|
activationTime?: string
|
||||||
|
/** 预计报废时间 */
|
||||||
|
expectedScrapTime?: string
|
||||||
|
/** 实际报废时间 */
|
||||||
|
actualScrapTime?: string
|
||||||
|
/** 状态变更时间 */
|
||||||
|
statusChangeTime?: string
|
||||||
|
/** 采购订单 */
|
||||||
|
purchaseOrder?: string
|
||||||
|
/** 供应商名称 */
|
||||||
|
supplierName?: string
|
||||||
|
/** 采购价格 */
|
||||||
|
purchasePrice?: number
|
||||||
|
/** 当前净值 */
|
||||||
|
currentNetValue?: number
|
||||||
|
/** 折旧方法 */
|
||||||
|
depreciationMethod?: string
|
||||||
|
/** 折旧年限 */
|
||||||
|
depreciationYears?: number
|
||||||
|
/** 残值 */
|
||||||
|
salvageValue?: number
|
||||||
|
/** 保修截止日期 */
|
||||||
|
warrantyExpireDate?: string
|
||||||
|
/** 上次维护日期 */
|
||||||
|
lastMaintenanceDate?: string
|
||||||
|
/** 下次维护日期 */
|
||||||
|
nextMaintenanceDate?: string
|
||||||
|
/** 维护人员 */
|
||||||
|
maintenancePerson?: string
|
||||||
|
/** 库存条码 */
|
||||||
|
inventoryBarcode?: string
|
||||||
|
/** 资产备注 */
|
||||||
|
assetRemark?: string
|
||||||
|
/** 项目ID */
|
||||||
|
projectId?: string
|
||||||
|
/** 项目名称 */
|
||||||
|
projectName?: string
|
||||||
|
/** 使用人ID */
|
||||||
|
userId?: string
|
||||||
|
/** 使用人 */
|
||||||
|
name?: string
|
||||||
|
/** 创建时间 */
|
||||||
|
createTime?: string
|
||||||
|
/** 更新时间 */
|
||||||
|
updateTime?: string
|
||||||
|
/** 次户号 */
|
||||||
|
accountNumber?: string
|
||||||
|
/** 数量 */
|
||||||
|
quantity?: number
|
||||||
|
/** 单价 */
|
||||||
|
unitPrice?: number
|
||||||
|
/** 总价 */
|
||||||
|
totalPrice?: number
|
||||||
|
/** 盘点依据 */
|
||||||
|
inventoryBasis?: string
|
||||||
|
/** 动态记录 */
|
||||||
|
dynamicRecord?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备请求
|
||||||
|
*/
|
||||||
|
export interface EquipmentReq {
|
||||||
|
/** 设备名称 */
|
||||||
|
equipmentName: string
|
||||||
|
/** 设备型号 */
|
||||||
|
equipmentModel: string
|
||||||
|
/** 设备类型 */
|
||||||
|
equipmentType: string
|
||||||
|
/** 设备状态 */
|
||||||
|
equipmentStatus: string
|
||||||
|
/** 使用状态 */
|
||||||
|
useStatus: string
|
||||||
|
/** 设备序列号 */
|
||||||
|
equipmentSn: string
|
||||||
|
/** 资产编号 */
|
||||||
|
assetCode?: string
|
||||||
|
/** 品牌 */
|
||||||
|
brand?: string
|
||||||
|
/** 配置规格/参数 */
|
||||||
|
specification?: string
|
||||||
|
/** 位置状态 */
|
||||||
|
locationStatus?: string
|
||||||
|
/** 设备当前物理位置 */
|
||||||
|
physicalLocation?: string
|
||||||
|
/** 负责人 */
|
||||||
|
responsiblePerson?: string
|
||||||
|
/** 健康状态 */
|
||||||
|
healthStatus?: string
|
||||||
|
/** 采购时间 */
|
||||||
|
purchaseTime?: string
|
||||||
|
/** 入库时间 */
|
||||||
|
inStockTime?: string
|
||||||
|
/** 启用时间 */
|
||||||
|
activationTime?: string
|
||||||
|
/** 预计报废时间 */
|
||||||
|
expectedScrapTime?: string
|
||||||
|
/** 实际报废时间 */
|
||||||
|
actualScrapTime?: string
|
||||||
|
/** 采购订单 */
|
||||||
|
purchaseOrder?: string
|
||||||
|
/** 供应商名称 */
|
||||||
|
supplierName?: string
|
||||||
|
/** 采购价格 */
|
||||||
|
purchasePrice?: number
|
||||||
|
/** 当前净值 */
|
||||||
|
currentNetValue?: number
|
||||||
|
/** 折旧方法 */
|
||||||
|
depreciationMethod?: string
|
||||||
|
/** 折旧年限 */
|
||||||
|
depreciationYears?: number
|
||||||
|
/** 残值 */
|
||||||
|
salvageValue?: number
|
||||||
|
/** 保修截止日期 */
|
||||||
|
warrantyExpireDate?: string
|
||||||
|
/** 上次维护日期 */
|
||||||
|
lastMaintenanceDate?: string
|
||||||
|
/** 下次维护日期 */
|
||||||
|
nextMaintenanceDate?: string
|
||||||
|
/** 维护人员 */
|
||||||
|
maintenancePerson?: string
|
||||||
|
/** 库存条码 */
|
||||||
|
inventoryBarcode?: string
|
||||||
|
/** 资产备注 */
|
||||||
|
assetRemark?: string
|
||||||
|
/** 次户号 */
|
||||||
|
accountNumber?: string
|
||||||
|
/** 数量 */
|
||||||
|
quantity?: number
|
||||||
|
/** 单价 */
|
||||||
|
unitPrice?: number
|
||||||
|
/** 总价 */
|
||||||
|
totalPrice?: number
|
||||||
|
/** 盘点依据 */
|
||||||
|
inventoryBasis?: string
|
||||||
|
/** 动态记录 */
|
||||||
|
dynamicRecord?: string
|
||||||
|
}
|
|
@ -26,53 +26,52 @@ export const systemRoutes: RouteRecordRaw[] = [
|
||||||
// }
|
// }
|
||||||
// ],
|
// ],
|
||||||
// },
|
// },
|
||||||
{
|
// {
|
||||||
path: '/regulation',
|
// path: '/regulation',
|
||||||
name: 'Regulation',
|
// name: 'Regulation',
|
||||||
component: Layout,
|
// component: Layout,
|
||||||
redirect: '/regulation/system-regulation',
|
// redirect: '/regulation/system-regulation',
|
||||||
meta: { title: '制度管理', icon: 'file-text', hidden: false, sort: 1.5 },
|
// meta: { title: '制度管理', icon: 'file-text', hidden: false, sort: 1.5 },
|
||||||
children: [
|
// children: [
|
||||||
{
|
// {
|
||||||
path: '/regulation/system-regulation',
|
// path: '/regulation/system-regulation',
|
||||||
name: 'SystemRegulation',
|
// name: 'SystemRegulation',
|
||||||
component: () => import('@/views/regulation/repository.vue'),
|
// component: () => import('@/views/regulation/repository.vue'),
|
||||||
meta: { title: '制度公告', icon: 'file-text', hidden: false },
|
// meta: { title: '制度公告', icon: 'file-text', hidden: false },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
path: '/regulation/process-management',
|
// path: '/regulation/process-management',
|
||||||
name: 'ProcessManagement',
|
// name: 'ProcessManagement',
|
||||||
component: () => import('@/views/regulation/confirm.vue'),
|
// component: () => import('@/views/regulation/confirm.vue'),
|
||||||
meta: { title: '制度公示', icon: 'workflow', hidden: false },
|
// meta: { title: '制度公示', icon: 'workflow', hidden: false },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
path: '/regulation/proposal',
|
// path: '/regulation/proposal',
|
||||||
name: 'RegulationProposal',
|
// name: 'RegulationProposal',
|
||||||
component: () => import('@/views/regulation/proposal/index.vue'),
|
// component: () => import('@/views/regulation/proposal/index.vue'),
|
||||||
meta: { title: '制度提案', icon: 'edit', hidden: false },
|
// meta: { title: '制度提案', icon: 'edit', hidden: false },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
path: '/regulation/type',
|
// path: '/regulation/type',
|
||||||
name: 'RegulationType',
|
// name: 'RegulationType',
|
||||||
component: () => import('@/views/regulation/type/index.vue'),
|
// component: () => import('@/views/regulation/type/index.vue'),
|
||||||
meta: { title: '制度类型', icon: 'tag', hidden: false },
|
// meta: { title: '制度类型', icon: 'tag', hidden: false },
|
||||||
},
|
// },
|
||||||
|
// ],
|
||||||
],
|
// },
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '/organization',
|
path: '/organization',
|
||||||
name: 'Organization',
|
name: 'Organization',
|
||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: '/organization/dept',
|
redirect: '/organization/dept',
|
||||||
meta: { title: '组织架构', icon: 'user-group', hidden: false, sort: 2 },
|
meta: { title: '企业管理', icon: 'user-group', hidden: false, sort: 2 },
|
||||||
children: [
|
children: [
|
||||||
{
|
// {
|
||||||
path: '/organization/user',
|
// path: '/organization/user',
|
||||||
name: 'OrganizationUser',
|
// name: 'OrganizationUser',
|
||||||
component: () => import('@/views/system/user/index.vue'),
|
// component: () => import('@/views/system/user/index.vue'),
|
||||||
meta: { title: '用户管理', icon: 'user', hidden: false, sort: 2.25 },
|
// meta: { title: '用户管理', icon: 'user', hidden: false, sort: 2.25 },
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
path: '/organization/dept',
|
path: '/organization/dept',
|
||||||
name: 'OrganizationDept',
|
name: 'OrganizationDept',
|
||||||
|
@ -85,6 +84,39 @@ export const systemRoutes: RouteRecordRaw[] = [
|
||||||
component: () => import('@/views/system/post/index.vue'),
|
component: () => import('@/views/system/post/index.vue'),
|
||||||
meta: { title: '岗位管理', icon: 'nav', hidden: false, sort: 2.75 },
|
meta: { title: '岗位管理', icon: 'nav', hidden: false, sort: 2.75 },
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/regulation',
|
||||||
|
name: 'Regulation',
|
||||||
|
// component: Layout,
|
||||||
|
redirect: '/regulation/system-regulation',
|
||||||
|
meta: { title: '制度管理', icon: 'file-text', hidden: false, sort: 1.5 },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '/regulation/system-regulation',
|
||||||
|
name: 'SystemRegulation',
|
||||||
|
component: () => import('@/views/regulation/repository.vue'),
|
||||||
|
meta: { title: '制度公告', icon: 'file-text', hidden: false },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/regulation/process-management',
|
||||||
|
name: 'ProcessManagement',
|
||||||
|
component: () => import('@/views/regulation/confirm.vue'),
|
||||||
|
meta: { title: '制度公示', icon: 'workflow', hidden: false },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/regulation/proposal',
|
||||||
|
name: 'RegulationProposal',
|
||||||
|
component: () => import('@/views/regulation/proposal/index.vue'),
|
||||||
|
meta: { title: '制度提案', icon: 'edit', hidden: false },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/regulation/type',
|
||||||
|
name: 'RegulationType',
|
||||||
|
component: () => import('@/views/regulation/type/index.vue'),
|
||||||
|
meta: { title: '制度类型', icon: 'tag', hidden: false },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
// {
|
// {
|
||||||
// path: '/organization/hr/workload',
|
// path: '/organization/hr/workload',
|
||||||
// name: 'HRWorkload',
|
// name: 'HRWorkload',
|
||||||
|
@ -501,99 +533,86 @@ export const systemRoutes: RouteRecordRaw[] = [
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/project-management',
|
path: '/project-marketing',
|
||||||
name: 'ProjectManagement',
|
name: 'Projectmarketing',
|
||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: '/project-management/project-template/project-management',
|
redirect: '/project-marketing/project-marketing',
|
||||||
meta: { title: '项目管理', icon: 'apps', hidden: false, sort: 4 },
|
meta: { title: '营销管理', icon: 'file-text', hidden: false, sort: 3 },
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '/project-management/contract/project-source',
|
path: '/project-marketing/contract/revenue-contract2',
|
||||||
name: 'ProjectSource',
|
name: 'RevenueContract2',
|
||||||
|
component: () => import('@/views/default/error/404.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '市场营销(N)',
|
||||||
|
icon: 'dollar',
|
||||||
|
hidden: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/project-marketing/contract/procurement-business',
|
||||||
|
name: 'ProcurementBusiness',
|
||||||
component: () => import('@/components/ParentView/index.vue'),
|
component: () => import('@/components/ParentView/index.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
title: '项目来源',
|
title: '招采业务',
|
||||||
icon: 'dollar',
|
icon: 'dollar',
|
||||||
hidden: false,
|
hidden: false,
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '/project-management/contract/procurement-business',
|
path: '/project-marketing/project-template/tender-documents',
|
||||||
name: 'ProcurementBusiness',
|
name: 'TenderDocuments',
|
||||||
component: () => import('@/components/ParentView/index.vue'),
|
component: () => import('@/views/project-management/bidding/tender-documents/index.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
title: '招采业务',
|
title: '招标文件',
|
||||||
icon: 'dollar',
|
icon: 'file-text',
|
||||||
hidden: false,
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '/project-management/project-template/tender-documents',
|
|
||||||
name: 'TenderDocuments',
|
|
||||||
component: () => import('@/views/project-management/bidding/tender-documents/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '招标文件',
|
|
||||||
icon: 'file-text',
|
|
||||||
hidden: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/project-management/project-template/bid-documents',
|
|
||||||
name: 'BidDocuments',
|
|
||||||
component: () => import('@/views/project-management/bidding/bid-documents/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '投标文件',
|
|
||||||
icon: 'file-text',
|
|
||||||
hidden: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/project-management/project-template/award-notice',
|
|
||||||
name: 'AwardNotice',
|
|
||||||
component: () => import('@/views/project-management/bidding/award-notice/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '中标通知书',
|
|
||||||
icon: 'trophy',
|
|
||||||
hidden: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/project-management/project-template/information-retrieval',
|
|
||||||
name: 'InformationRetrieval',
|
|
||||||
component: () => import ('@/views/project-management/bidding/information-retrieval/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '信息检索(N)',
|
|
||||||
icon: 'trophy',
|
|
||||||
hidden: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/project-management/contract/revenue-contract2',
|
|
||||||
name: 'RevenueContract2',
|
|
||||||
component: () => import('@/views/default/error/404.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '市场营销(N)',
|
|
||||||
icon: 'dollar',
|
|
||||||
hidden: false,
|
hidden: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/project-management/project-source/privateproject',
|
path: '/project-marketing/project-template/bid-documents',
|
||||||
name: 'PrivateProject',
|
name: 'BidDocuments',
|
||||||
component: () => import('@/views/default/error/404.vue'),
|
component: () => import('@/views/project-management/bidding/bid-documents/index.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
title: '自建项目(N)',
|
title: '投标文件',
|
||||||
icon: 'dollar',
|
icon: 'file-text',
|
||||||
|
hidden: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/project-marketing/project-template/award-notice',
|
||||||
|
name: 'AwardNotice',
|
||||||
|
component: () => import('@/views/project-management/bidding/award-notice/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '中标通知书',
|
||||||
|
icon: 'trophy',
|
||||||
|
hidden: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/project-marketing/project-template/information-retrieval',
|
||||||
|
name: 'InformationRetrieval',
|
||||||
|
component: () => import ('@/views/project-management/bidding/information-retrieval/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '信息检索(N)',
|
||||||
|
icon: 'trophy',
|
||||||
hidden: false,
|
hidden: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/project-marketing/order-management/order-management',
|
||||||
|
name: 'OrderManagement',
|
||||||
|
component: () => import('@/views/project-management/order-management/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '订单管理',
|
||||||
|
icon: 'file-text',
|
||||||
|
hidden: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
{ path: '/project-management/contract', name: 'ProjectContract', component: () => import('@/components/ParentView/index.vue'), redirect: '/project-management/contract/revenue-contract', meta: {
|
{ path: '/project-management/contract', name: 'ProjectContract', component: () => import('@/components/ParentView/index.vue'), redirect: '/project-management/contract/revenue-contract', meta: {
|
||||||
title: '项目合同',
|
title: '合同管理',
|
||||||
icon: 'file-text',
|
icon: 'file-text',
|
||||||
hidden: false,
|
hidden: false,
|
||||||
}, children: [
|
}, children: [
|
||||||
|
@ -628,6 +647,136 @@ export const systemRoutes: RouteRecordRaw[] = [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
] },
|
] },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/project-management',
|
||||||
|
name: 'ProjectManagement',
|
||||||
|
component: Layout,
|
||||||
|
redirect: '/project-management/project-template/project-management',
|
||||||
|
meta: { title: '项目管理', icon: 'apps', hidden: false, sort: 4 },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '/project-management/contract/project-source',
|
||||||
|
name: 'ProjectSource',
|
||||||
|
component: () => import('@/components/ParentView/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '项目来源',
|
||||||
|
icon: 'dollar',
|
||||||
|
hidden: false,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
// {
|
||||||
|
// path: '/project-management/contract/procurement-business',
|
||||||
|
// name: 'ProcurementBusiness',
|
||||||
|
// component: () => import('@/components/ParentView/index.vue'),
|
||||||
|
// meta: {
|
||||||
|
// title: '招采业务',
|
||||||
|
// icon: 'dollar',
|
||||||
|
// hidden: false,
|
||||||
|
// },
|
||||||
|
// children: [
|
||||||
|
// {
|
||||||
|
// path: '/project-management/project-template/tender-documents',
|
||||||
|
// name: 'TenderDocuments',
|
||||||
|
// component: () => import('@/views/project-management/bidding/tender-documents/index.vue'),
|
||||||
|
// meta: {
|
||||||
|
// title: '招标文件',
|
||||||
|
// icon: 'file-text',
|
||||||
|
// hidden: false,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/project-management/project-template/bid-documents',
|
||||||
|
// name: 'BidDocuments',
|
||||||
|
// component: () => import('@/views/project-management/bidding/bid-documents/index.vue'),
|
||||||
|
// meta: {
|
||||||
|
// title: '投标文件',
|
||||||
|
// icon: 'file-text',
|
||||||
|
// hidden: false,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/project-management/project-template/award-notice',
|
||||||
|
// name: 'AwardNotice',
|
||||||
|
// component: () => import('@/views/project-management/bidding/award-notice/index.vue'),
|
||||||
|
// meta: {
|
||||||
|
// title: '中标通知书',
|
||||||
|
// icon: 'trophy',
|
||||||
|
// hidden: false,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/project-management/project-template/information-retrieval',
|
||||||
|
// name: 'InformationRetrieval',
|
||||||
|
// component: () => import ('@/views/project-management/bidding/information-retrieval/index.vue'),
|
||||||
|
// meta: {
|
||||||
|
// title: '信息检索(N)',
|
||||||
|
// icon: 'trophy',
|
||||||
|
// hidden: false,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
//
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/project-management/contract/revenue-contract2',
|
||||||
|
// name: 'RevenueContract2',
|
||||||
|
// component: () => import('@/views/default/error/404.vue'),
|
||||||
|
// meta: {
|
||||||
|
// title: '市场营销(N)',
|
||||||
|
// icon: 'dollar',
|
||||||
|
// hidden: false,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
path: '/project-management/project-source/privateproject',
|
||||||
|
name: 'PrivateProject',
|
||||||
|
component: () => import('@/views/default/error/404.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '自建项目(N)',
|
||||||
|
icon: 'dollar',
|
||||||
|
hidden: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// { path: '/project-management/contract', name: 'ProjectContract', component: () => import('@/components/ParentView/index.vue'), redirect: '/project-management/contract/revenue-contract', meta: {
|
||||||
|
// title: '项目合同',
|
||||||
|
// icon: 'file-text',
|
||||||
|
// hidden: false,
|
||||||
|
// }, children: [
|
||||||
|
// {
|
||||||
|
// path: '/project-management/contract/revenue-contract',
|
||||||
|
// name: 'RevenueContract',
|
||||||
|
// component: () => import('@/views/project-management/contract/revenue-contract/index.vue'),
|
||||||
|
// meta: {
|
||||||
|
// title: '收入合同',
|
||||||
|
// icon: 'dollar',
|
||||||
|
// hidden: false,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/project-management/contract/expense-contract',
|
||||||
|
// name: 'ExpenseContract',
|
||||||
|
// component: () => import('@/views/project-management/contract/expense-contract/index.vue'),
|
||||||
|
// meta: {
|
||||||
|
// title: '支出合同',
|
||||||
|
// icon: 'credit-card',
|
||||||
|
// hidden: false,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/project-management/contract/cost-management',
|
||||||
|
// name: 'CostManagement',
|
||||||
|
// component: () => import('@/views/project-management/contract/cost-management/index.vue'),
|
||||||
|
// meta: {
|
||||||
|
// title: '成本费用',
|
||||||
|
// icon: 'bar-chart',
|
||||||
|
// hidden: false,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// ] },
|
||||||
{
|
{
|
||||||
path: '/project-management/project-template/project-aproval',
|
path: '/project-management/project-template/project-aproval',
|
||||||
name: 'ProjectTemplate',
|
name: 'ProjectTemplate',
|
||||||
|
@ -703,6 +852,26 @@ export const systemRoutes: RouteRecordRaw[] = [
|
||||||
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
// 添加商务知识库
|
||||||
|
{
|
||||||
|
path: '/bussiness-knowledge',
|
||||||
|
name: 'bussinesskonwledge',
|
||||||
|
component: Layout,
|
||||||
|
redirect: '/bussiness-knowledge/data',
|
||||||
|
meta: { title: '商务资料知识库', icon: 'message', hidden: false, sort: 6 },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '/bussiness-konwledge/data',
|
||||||
|
name: 'bussiness-knowledge',
|
||||||
|
component: () => import('@/views/bussiness-data/bussiness.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '商务数据库信息',
|
||||||
|
icon: 'info-circle',
|
||||||
|
hidden: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'project-management/project-implementation/',
|
path: 'project-management/project-implementation/',
|
||||||
name: 'Project-Implementation',
|
name: 'Project-Implementation',
|
||||||
|
@ -1016,30 +1185,30 @@ export const systemRoutes: RouteRecordRaw[] = [
|
||||||
// }
|
// }
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
path: '/user/profile',
|
// path: '/user/profile',
|
||||||
name: 'UserProfile',
|
// name: 'UserProfile',
|
||||||
component: Layout,
|
// component: Layout,
|
||||||
redirect: '/user/profile',
|
// redirect: '/user/profile',
|
||||||
meta: {
|
// meta: {
|
||||||
title: '个人中心',
|
// title: '个人中心',
|
||||||
icon: 'user',
|
// icon: 'user',
|
||||||
hidden: false,
|
// hidden: false,
|
||||||
sort: 100,
|
// sort: 100,
|
||||||
},
|
// },
|
||||||
children: [
|
// children: [
|
||||||
{
|
// {
|
||||||
path: '/user/profile',
|
// path: '/user/profile',
|
||||||
name: 'UserProfile',
|
// name: 'UsersProfile',
|
||||||
component: () => import('@/views/user/profile/index.vue'),
|
// component: () => import('@/views/user/profile/index.vue'),
|
||||||
meta: {
|
// meta: {
|
||||||
title: '个人中心',
|
// title: '个人中心',
|
||||||
icon: 'user',
|
// icon: 'user',
|
||||||
hidden: false,
|
// hidden: false,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
path: '/enterprise-settings',
|
path: '/enterprise-settings',
|
||||||
name: 'EnterpriseSettings',
|
name: 'EnterpriseSettings',
|
||||||
|
|
|
@ -149,6 +149,20 @@ const storeSetup = () => {
|
||||||
isHidden: false,
|
isHidden: false,
|
||||||
sort: 3,
|
sort: 3,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 1070,
|
||||||
|
parentId: 1000,
|
||||||
|
title: '个人中心',
|
||||||
|
type: 2,
|
||||||
|
path: '/user/profile',
|
||||||
|
name: 'UserProfile',
|
||||||
|
component: 'user/profile/index',
|
||||||
|
icon: 'user',
|
||||||
|
isExternal: false,
|
||||||
|
isCache: false,
|
||||||
|
isHidden: false,
|
||||||
|
sort: 4,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}]
|
}]
|
||||||
// 使用已转换的数据生成路由
|
// 使用已转换的数据生成路由
|
||||||
|
|
|
@ -0,0 +1,179 @@
|
||||||
|
export interface EquipmentPageQuery {
|
||||||
|
equipmentName?: string
|
||||||
|
equipmentType?: string
|
||||||
|
equipmentStatus?: string
|
||||||
|
equipmentSn?: string
|
||||||
|
assetCode?: string
|
||||||
|
brand?: string
|
||||||
|
locationStatus?: string
|
||||||
|
healthStatus?: string
|
||||||
|
responsiblePerson?: string
|
||||||
|
useStatus?: string
|
||||||
|
projectId?: string
|
||||||
|
userId?: string
|
||||||
|
equipmentModel?: string
|
||||||
|
specification?: string
|
||||||
|
physicalLocation?: string
|
||||||
|
supplierName?: string
|
||||||
|
maintenancePerson?: string
|
||||||
|
inventoryBarcode?: string
|
||||||
|
assetRemark?: string
|
||||||
|
// 新增搜索字段
|
||||||
|
usingDepartment?: string
|
||||||
|
invoice?: string
|
||||||
|
barcode?: string
|
||||||
|
importer?: string
|
||||||
|
page?: number
|
||||||
|
pageSize?: number
|
||||||
|
orderBy?: string
|
||||||
|
orderDirection?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EquipmentReq {
|
||||||
|
equipmentName: string
|
||||||
|
equipmentModel: string
|
||||||
|
equipmentType: string
|
||||||
|
equipmentStatus: string
|
||||||
|
useStatus: string
|
||||||
|
equipmentSn: string
|
||||||
|
assetCode?: string
|
||||||
|
brand?: string
|
||||||
|
specification?: string
|
||||||
|
locationStatus?: string
|
||||||
|
physicalLocation?: string
|
||||||
|
responsiblePerson?: string
|
||||||
|
healthStatus?: string
|
||||||
|
purchaseTime?: string
|
||||||
|
inStockTime?: string
|
||||||
|
activationTime?: string
|
||||||
|
expectedScrapTime?: string
|
||||||
|
actualScrapTime?: string
|
||||||
|
statusChangeTime?: string
|
||||||
|
purchaseOrder?: string
|
||||||
|
supplierName?: string
|
||||||
|
purchasePrice?: number
|
||||||
|
currentNetValue?: number
|
||||||
|
depreciationMethod?: string
|
||||||
|
depreciationYears?: number
|
||||||
|
salvageValue?: number
|
||||||
|
warrantyExpireDate?: string
|
||||||
|
lastMaintenanceDate?: string
|
||||||
|
nextMaintenanceDate?: string
|
||||||
|
maintenancePerson?: string
|
||||||
|
inventoryBarcode?: string
|
||||||
|
assetRemark?: string
|
||||||
|
// 新增字段
|
||||||
|
usingDepartment?: string
|
||||||
|
borrowingTime?: string
|
||||||
|
returnTime?: string
|
||||||
|
outStockTime?: string
|
||||||
|
totalUsageTime?: string
|
||||||
|
depreciationRate?: number
|
||||||
|
depreciationMethodDesc?: string
|
||||||
|
invoice?: string
|
||||||
|
invoiceStatus?: string
|
||||||
|
attachments?: string
|
||||||
|
photos?: string
|
||||||
|
barcode?: string
|
||||||
|
importer?: string
|
||||||
|
inventoryTimeStatus1?: string
|
||||||
|
inventoryTimeStatus2?: string
|
||||||
|
inventoryTimeStatus3?: string
|
||||||
|
inventoryCheckTimeStatus1?: string
|
||||||
|
inventoryCheckTimeStatus2?: string
|
||||||
|
inventoryCheckTimeStatus3?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EquipmentResp {
|
||||||
|
equipmentId: string
|
||||||
|
assetCode?: string
|
||||||
|
equipmentName: string
|
||||||
|
equipmentType: string
|
||||||
|
equipmentTypeLabel?: string
|
||||||
|
equipmentModel: string
|
||||||
|
equipmentSn: string
|
||||||
|
brand?: string
|
||||||
|
specification?: string
|
||||||
|
equipmentStatus: string
|
||||||
|
equipmentStatusLabel?: string
|
||||||
|
useStatus: string
|
||||||
|
locationStatus?: string
|
||||||
|
locationStatusLabel?: string
|
||||||
|
physicalLocation?: string
|
||||||
|
responsiblePerson?: string
|
||||||
|
healthStatus?: string
|
||||||
|
healthStatusLabel?: string
|
||||||
|
purchaseTime?: string
|
||||||
|
inStockTime?: string
|
||||||
|
activationTime?: string
|
||||||
|
expectedScrapTime?: string
|
||||||
|
actualScrapTime?: string
|
||||||
|
statusChangeTime?: string
|
||||||
|
purchaseOrder?: string
|
||||||
|
supplierName?: string
|
||||||
|
purchasePrice?: number
|
||||||
|
currentNetValue?: number
|
||||||
|
depreciationMethod?: string
|
||||||
|
depreciationYears?: number
|
||||||
|
salvageValue?: number
|
||||||
|
warrantyExpireDate?: string
|
||||||
|
lastMaintenanceDate?: string
|
||||||
|
nextMaintenanceDate?: string
|
||||||
|
maintenancePerson?: string
|
||||||
|
inventoryBarcode?: string
|
||||||
|
assetRemark?: string
|
||||||
|
// 新增字段
|
||||||
|
usingDepartment?: string
|
||||||
|
borrowingTime?: string
|
||||||
|
returnTime?: string
|
||||||
|
outStockTime?: string
|
||||||
|
totalUsageTime?: string
|
||||||
|
depreciationRate?: number
|
||||||
|
depreciationMethodDesc?: string
|
||||||
|
invoice?: string
|
||||||
|
invoiceStatus?: string
|
||||||
|
attachments?: string
|
||||||
|
photos?: string
|
||||||
|
barcode?: string
|
||||||
|
importer?: string
|
||||||
|
inventoryTimeStatus1?: string
|
||||||
|
inventoryTimeStatus2?: string
|
||||||
|
inventoryTimeStatus3?: string
|
||||||
|
inventoryCheckTimeStatus1?: string
|
||||||
|
inventoryCheckTimeStatus2?: string
|
||||||
|
inventoryCheckTimeStatus3?: string
|
||||||
|
projectId?: string
|
||||||
|
projectName?: string
|
||||||
|
userId?: string
|
||||||
|
name?: string
|
||||||
|
createTime?: string
|
||||||
|
updateTime?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EquipmentTypeOption {
|
||||||
|
label: string
|
||||||
|
value: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EquipmentStatusOption {
|
||||||
|
label: string
|
||||||
|
value: string
|
||||||
|
color: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LocationStatusOption {
|
||||||
|
label: string
|
||||||
|
value: string
|
||||||
|
color: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HealthStatusOption {
|
||||||
|
label: string
|
||||||
|
value: string
|
||||||
|
color: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DepreciationMethodOption {
|
||||||
|
label: string
|
||||||
|
value: string
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -73,7 +73,7 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import type { BiddingDetail } from './types'
|
import type { BiddingDetail } from '../types'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
visible: boolean
|
visible: boolean
|
||||||
|
|
|
@ -0,0 +1,344 @@
|
||||||
|
<template>
|
||||||
|
<div class="project-table-container">
|
||||||
|
<a-table
|
||||||
|
:data="data"
|
||||||
|
:columns="columns"
|
||||||
|
:loading="loading"
|
||||||
|
:pagination="false"
|
||||||
|
:scroll="{ x: '100%', y: '100%' }"
|
||||||
|
row-key="id"
|
||||||
|
:stripe="false"
|
||||||
|
size="large"
|
||||||
|
>
|
||||||
|
<!-- 招标项目 -->
|
||||||
|
<template #projectName="{ record }">
|
||||||
|
<div class="project-name">
|
||||||
|
<span class="name-text">{{ record.projectName }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 招标单位 -->
|
||||||
|
<template #biddingUnit="{ record }">
|
||||||
|
<span class="bidding-unit">{{ record.biddingUnit }}</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 预算金额 -->
|
||||||
|
<template #budgetAmount="{ record }">
|
||||||
|
<span class="budget-text">{{ record.budgetAmount }}</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 截止时间 -->
|
||||||
|
<template #deadline="{ record }">
|
||||||
|
<span class="date-text">{{ record.deadline }}</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 爬取时间 -->
|
||||||
|
<template #crawlingTime="{ record }">
|
||||||
|
<span class="date-text">{{ record.crawlingTime }}</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 来源平台 -->
|
||||||
|
<template #sourcePlatform="{ record }">
|
||||||
|
<span class="source-text">{{ record.sourcePlatform }}</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 招标文件 -->
|
||||||
|
<template #biddingDocuments="{ record }">
|
||||||
|
<span class="doc-text">{{ record.biddingDocuments }}</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 状态 -->
|
||||||
|
<template #status="{ record }">
|
||||||
|
<a-tag :color="getStatusColor(record.status)">
|
||||||
|
{{ getStatusText(record.status) }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 操作 -->
|
||||||
|
<template #action="{ record }">
|
||||||
|
<div class="action-buttons">
|
||||||
|
<a-button size="small" @click="handleView(record)">
|
||||||
|
详情
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
@click="handleEnter(record)"
|
||||||
|
>
|
||||||
|
报名
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import type { TableColumnData } from '@arco-design/web-vue'
|
||||||
|
import type { ProjectData } from '../types'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
data: ProjectData[]
|
||||||
|
loading?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Emits {
|
||||||
|
(e: 'view', project: ProjectData): void
|
||||||
|
(e: 'enter', project: ProjectData): void
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
loading: false
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits<Emits>()
|
||||||
|
|
||||||
|
// 表格列配置
|
||||||
|
const columns: TableColumnData[] = [
|
||||||
|
{
|
||||||
|
title: '招标项目',
|
||||||
|
dataIndex: 'projectName',
|
||||||
|
slotName: 'projectName',
|
||||||
|
width: 300,
|
||||||
|
ellipsis: true,
|
||||||
|
tooltip: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '招标单位',
|
||||||
|
dataIndex: ' biddingUnit',
|
||||||
|
slotName: 'biddingUnit',
|
||||||
|
width: 120,
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '预算金额',
|
||||||
|
dataIndex: 'budgetAmount',
|
||||||
|
slotName: 'budgetAmount',
|
||||||
|
width: 120,
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '截止时间',
|
||||||
|
dataIndex: 'deadline',
|
||||||
|
slotName: 'deadline',
|
||||||
|
width: 150,
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '爬取时间',
|
||||||
|
dataIndex: 'crawlingTime',
|
||||||
|
slotName: 'crawlingTime',
|
||||||
|
width: 150,
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '来源平台',
|
||||||
|
dataIndex: 'sourcePlatform',
|
||||||
|
slotName: 'sourcePlatform',
|
||||||
|
width: 150,
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '招标文件',
|
||||||
|
dataIndex: ' biddingDocuments',
|
||||||
|
slotName: 'biddingDocuments',
|
||||||
|
width: 150,
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '状态',
|
||||||
|
dataIndex: 'status',
|
||||||
|
slotName: 'status',
|
||||||
|
width: 120,
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
dataIndex: 'action',
|
||||||
|
slotName: 'action',
|
||||||
|
width: 150,
|
||||||
|
align: 'center',
|
||||||
|
fixed: 'right'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
// 获取状态颜色
|
||||||
|
const getStatusColor = (status: string) => {
|
||||||
|
const colorMap: Record<string, string> = {
|
||||||
|
'not_started': 'gray',
|
||||||
|
'in_progress': 'blue',
|
||||||
|
'completed': 'green',
|
||||||
|
'paused': 'orange',
|
||||||
|
'cancelled': 'red'
|
||||||
|
}
|
||||||
|
return colorMap[status] || 'gray'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取状态文本
|
||||||
|
const getStatusText = (status: string) => {
|
||||||
|
const textMap: Record<string, string> = {
|
||||||
|
'not_started': '未开始',
|
||||||
|
'in_progress': '进行中',
|
||||||
|
'completed': '已完成',
|
||||||
|
'paused': '已暂停',
|
||||||
|
'cancelled': '已取消'
|
||||||
|
}
|
||||||
|
return textMap[status] || status
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取进度颜色
|
||||||
|
const getProgressColor = (progress: number) => {
|
||||||
|
if (progress === 0) return '#d9d9d9'
|
||||||
|
if (progress === 100) return '#52c41a'
|
||||||
|
if (progress >= 70) return '#1890ff'
|
||||||
|
if (progress >= 40) return '#faad14'
|
||||||
|
return '#ff4d4f'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 事件处理
|
||||||
|
const handleView = (record: ProjectData) => {
|
||||||
|
emit('view', record)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleEnter = (record: ProjectData) => {
|
||||||
|
emit('enter', record)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
.project-table-container {
|
||||||
|
height: 100%;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-name {
|
||||||
|
.name-text {
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.unit-count {
|
||||||
|
font-weight: 600;
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-text {
|
||||||
|
color: #666;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.progress-text {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #666;
|
||||||
|
font-weight: 500;
|
||||||
|
min-width: 35px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.arco-table) {
|
||||||
|
.arco-table-thead {
|
||||||
|
.arco-table-th {
|
||||||
|
background-color: #fafafa;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
border-bottom: 1px solid #e8e8e8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.arco-table-tbody {
|
||||||
|
.arco-table-tr {
|
||||||
|
&:hover {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.arco-table-td {
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
padding: 16px 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.arco-tag) {
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 2px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.arco-progress-line-outer) {
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.arco-progress-line-inner) {
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 状态标签样式
|
||||||
|
:deep(.arco-tag-gray) {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
border-color: #d9d9d9;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.arco-tag-blue) {
|
||||||
|
background-color: #e6f7ff;
|
||||||
|
border-color: #91d5ff;
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.arco-tag-green) {
|
||||||
|
background-color: #f6ffed;
|
||||||
|
border-color: #b7eb8f;
|
||||||
|
color: #52c41a;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.arco-tag-orange) {
|
||||||
|
background-color: #fff7e6;
|
||||||
|
border-color: #ffd591;
|
||||||
|
color: #fa8c16;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.arco-tag-red) {
|
||||||
|
background-color: #fff1f0;
|
||||||
|
border-color: #ffccc7;
|
||||||
|
color: #ff4d4f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 响应式处理
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
:deep(.arco-table-td) {
|
||||||
|
padding: 12px 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-buttons {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-container {
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
.progress-text {
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,415 @@
|
||||||
|
<template>
|
||||||
|
<GiPageLayout>
|
||||||
|
<div class="project-list-container">
|
||||||
|
<!-- 顶部搜索和操作区域 -->
|
||||||
|
<div class="header-section">
|
||||||
|
<div class="search-area">
|
||||||
|
<a-input-search
|
||||||
|
v-model="searchKeyword"
|
||||||
|
placeholder="搜索项目名称"
|
||||||
|
allow-clear
|
||||||
|
@search="handleSearch"
|
||||||
|
@clear="handleClear"
|
||||||
|
style="width: 300px"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="action-area">
|
||||||
|
<a-space>
|
||||||
|
<a-button type="primary" @click="startCrawler">
|
||||||
|
<template #icon><icon-play-arrow /></template>
|
||||||
|
开始爬虫
|
||||||
|
</a-button>
|
||||||
|
<a-button @click="refreshData">
|
||||||
|
<template #icon><icon-refresh /></template>
|
||||||
|
刷新数据
|
||||||
|
</a-button>
|
||||||
|
<a-button @click="exportData">
|
||||||
|
<template #icon><icon-download /></template>
|
||||||
|
导出数据
|
||||||
|
</a-button>
|
||||||
|
<a-button @click="openCrawlerSettings">
|
||||||
|
<template #icon><icon-settings /></template>
|
||||||
|
爬虫设置
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 选项卡区域 -->
|
||||||
|
<div class="tabs-section">
|
||||||
|
<a-tabs
|
||||||
|
v-model:active-key="activeTab"
|
||||||
|
type="line"
|
||||||
|
size="large"
|
||||||
|
@change="handleTabChange"
|
||||||
|
>
|
||||||
|
<a-tab-pane key="all" tab="信息检索" title="信息检索">
|
||||||
|
<ProjectTable
|
||||||
|
:data="pagedData"
|
||||||
|
:loading="loading"
|
||||||
|
@view="handleView"
|
||||||
|
@enter="handleEnter"
|
||||||
|
/>
|
||||||
|
<div class="pagination-wrapper">
|
||||||
|
<a-pagination
|
||||||
|
v-model:current="currentPage"
|
||||||
|
v-model:page-size="pageSize"
|
||||||
|
:total="totalItems"
|
||||||
|
show-total
|
||||||
|
show-jumper
|
||||||
|
show-page-size
|
||||||
|
:page-size-options="[10, 20, 50, 100]"
|
||||||
|
@change="handlePageChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="my" tab="投标响应" title="投标响应">
|
||||||
|
<ProjectTable
|
||||||
|
:data="myPagedData"
|
||||||
|
:loading="loading"
|
||||||
|
@view="handleView"
|
||||||
|
@enter="handleEnter"
|
||||||
|
/>
|
||||||
|
<div class="pagination-wrapper">
|
||||||
|
<a-pagination
|
||||||
|
v-model:current="myCurrentPage"
|
||||||
|
v-model:page-size="pageSize"
|
||||||
|
:total="myTotalItems"
|
||||||
|
show-total
|
||||||
|
show-jumper
|
||||||
|
show-page-size
|
||||||
|
:page-size-options="[10, 20, 50, 100]"
|
||||||
|
@change="handleMyPageChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
</div>
|
||||||
|
<CrawlerSettings
|
||||||
|
v-model:visible="crawlerSettingsVisible"
|
||||||
|
@save="handleSaveSettings"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</GiPageLayout>
|
||||||
|
<BiddingDetailModal
|
||||||
|
v-model:visible="detailVisible"
|
||||||
|
:detail="currentDetail"
|
||||||
|
:uploading="uploading"
|
||||||
|
@upload="handleUploadDocument"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive, computed, onMounted } from 'vue'
|
||||||
|
import { Message } from '@arco-design/web-vue'
|
||||||
|
import ProjectTable from './components/InformationTable.vue'
|
||||||
|
import CrawlerSettings from './components/CrawlerSettings.vue'
|
||||||
|
import BiddingDetailModal from './components/BiddingDetailModal.vue'
|
||||||
|
|
||||||
|
import type { ProjectData, TabKey,BiddingDetail } from './types'
|
||||||
|
import { ProjectStatus } from './types'
|
||||||
|
|
||||||
|
defineOptions({ name: 'ProjectList' })
|
||||||
|
|
||||||
|
// 响应式数据
|
||||||
|
const loading = ref(false)
|
||||||
|
const activeTab = ref<TabKey>('all')
|
||||||
|
const searchKeyword = ref('')
|
||||||
|
|
||||||
|
const crawlerSettingsVisible = ref(false)
|
||||||
|
|
||||||
|
// 分页相关数据
|
||||||
|
const currentPage = ref(1)
|
||||||
|
const myCurrentPage = ref(1)
|
||||||
|
const pageSize = ref(10)
|
||||||
|
|
||||||
|
// 添加状态
|
||||||
|
const detailVisible = ref(false)
|
||||||
|
const uploading = ref(false)
|
||||||
|
const currentDetail = ref<BiddingDetail>({
|
||||||
|
id: 0,
|
||||||
|
projectName: '',
|
||||||
|
biddingUnit: '',
|
||||||
|
budgetAmount: 0,
|
||||||
|
deadline: '',
|
||||||
|
crawlingTime: '',
|
||||||
|
projectLocation: '',
|
||||||
|
projectDuration: '',
|
||||||
|
biddingScope: '',
|
||||||
|
qualificationRequirements: '',
|
||||||
|
sourcePlatform: '',
|
||||||
|
biddingDocuments: '',
|
||||||
|
biddingContent: '',
|
||||||
|
contentItems: []
|
||||||
|
})
|
||||||
|
|
||||||
|
// 项目数据
|
||||||
|
const projectList = ref<ProjectData[]>([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
projectName: 'A风场2023年检查',
|
||||||
|
biddingUnit: 15,
|
||||||
|
budgetAmount:111,
|
||||||
|
deadline: '2023-10-01',
|
||||||
|
crawlingTime: '2023-12-31',
|
||||||
|
sourcePlatform:"中国招标投标网",
|
||||||
|
biddingDocuments:"333.pdf",
|
||||||
|
status: ProjectStatus.IN_PROGRESS,
|
||||||
|
manager: '张三',
|
||||||
|
isMyProject: true
|
||||||
|
},
|
||||||
|
// 添加更多示例数据用于测试分页
|
||||||
|
...Array.from({ length: 25 }, (_, i) => ({
|
||||||
|
id: i + 2,
|
||||||
|
projectName: `项目${i + 2}`,
|
||||||
|
biddingUnit: Math.floor(Math.random() * 20) + 1,
|
||||||
|
budgetAmount: Math.floor(Math.random() * 1000) + 100,
|
||||||
|
deadline: `2023-${(Math.floor(Math.random() * 12) + 1).toString().padStart(2, '0')}-${(Math.floor(Math.random() * 28) + 1).toString().padStart(2, '0')}`,
|
||||||
|
crawlingTime: `2023-${(Math.floor(Math.random() * 12) + 1).toString().padStart(2, '0')}-${(Math.floor(Math.random() * 28) + 1).toString().padStart(2, '0')}`,
|
||||||
|
sourcePlatform: "中国招标投标网",
|
||||||
|
biddingDocuments: `文档${i + 2}.pdf`,
|
||||||
|
status: Math.random() > 0.5 ? ProjectStatus.IN_PROGRESS : ProjectStatus.COMPLETED,
|
||||||
|
manager: ['张三', '李四', '王五'][Math.floor(Math.random() * 3)],
|
||||||
|
isMyProject: Math.random() > 0.7
|
||||||
|
}))
|
||||||
|
])
|
||||||
|
|
||||||
|
const handleSaveSettings = (settings: any) => {
|
||||||
|
console.log('Saved settings:', settings)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理查看详情
|
||||||
|
const handleView = (project: ProjectData) => {
|
||||||
|
// 这里应该根据项目ID获取详细数据,这里简化处理
|
||||||
|
currentDetail.value = {
|
||||||
|
id: project.id,
|
||||||
|
projectName: project.projectName,
|
||||||
|
biddingUnit: project.biddingUnit.toString(),
|
||||||
|
budgetAmount: project.budgetAmount,
|
||||||
|
deadline: project.deadline,
|
||||||
|
crawlingTime: project.crawlingTime,
|
||||||
|
projectLocation: '内蒙古自治区', // 示例数据
|
||||||
|
projectDuration: '6个月', // 示例数据
|
||||||
|
biddingScope: '风电场50台机组叶片检查服务', // 示例数据
|
||||||
|
qualificationRequirements: '具备风电叶片检查资质', // 示例数据
|
||||||
|
sourcePlatform: project.sourcePlatform,
|
||||||
|
biddingDocuments: project.biddingDocuments,
|
||||||
|
biddingContent: '本项目为某风电场2023年叶片检查服务采购,包括但不限于:',
|
||||||
|
contentItems: [
|
||||||
|
'叶片外观检查',
|
||||||
|
'无损检测',
|
||||||
|
'缺陷记录与评估',
|
||||||
|
'检查报告编制'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
detailVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算属性 - 根据搜索关键词过滤项目
|
||||||
|
const filteredProjects = computed(() => {
|
||||||
|
if (!searchKeyword.value) {
|
||||||
|
return projectList.value
|
||||||
|
}
|
||||||
|
return projectList.value.filter(project =>
|
||||||
|
project.projectName.toLowerCase().includes(searchKeyword.value.toLowerCase())
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 计算属性 - 我的项目
|
||||||
|
const myProjects = computed(() => {
|
||||||
|
return filteredProjects.value.filter(project => project.isMyProject)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 分页相关计算属性
|
||||||
|
const totalItems = computed(() => filteredProjects.value.length)
|
||||||
|
const myTotalItems = computed(() => myProjects.value.length)
|
||||||
|
|
||||||
|
const pagedData = computed(() => {
|
||||||
|
const start = (currentPage.value - 1) * pageSize.value
|
||||||
|
const end = start + pageSize.value
|
||||||
|
return filteredProjects.value.slice(start, end)
|
||||||
|
})
|
||||||
|
|
||||||
|
const myPagedData = computed(() => {
|
||||||
|
const start = (myCurrentPage.value - 1) * pageSize.value
|
||||||
|
const end = start + pageSize.value
|
||||||
|
return myProjects.value.slice(start, end)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 搜索处理
|
||||||
|
const handleSearch = (value: string) => {
|
||||||
|
searchKeyword.value = value
|
||||||
|
currentPage.value = 1 // 搜索时重置到第一页
|
||||||
|
myCurrentPage.value = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleClear = () => {
|
||||||
|
searchKeyword.value = ''
|
||||||
|
currentPage.value = 1 // 清空搜索时重置到第一页
|
||||||
|
myCurrentPage.value = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选项卡切换
|
||||||
|
const handleTabChange = (key: string) => {
|
||||||
|
activeTab.value = key as TabKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分页变化处理
|
||||||
|
const handlePageChange = (page: number) => {
|
||||||
|
currentPage.value = page
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleMyPageChange = (page: number) => {
|
||||||
|
myCurrentPage.value = page
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新数据
|
||||||
|
const refreshData = async () => {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
// 模拟API请求
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 800))
|
||||||
|
Message.success('数据已刷新')
|
||||||
|
} catch (error) {
|
||||||
|
Message.error('刷新失败')
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开始爬虫
|
||||||
|
const startCrawler = () => {
|
||||||
|
Message.info('开始爬虫任务')
|
||||||
|
// 这里添加爬虫启动逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出数据
|
||||||
|
const exportData = () => {
|
||||||
|
Message.info('导出数据')
|
||||||
|
// 这里添加数据导出逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开爬虫设置
|
||||||
|
const openCrawlerSettings = () => {
|
||||||
|
crawlerSettingsVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleUploadDocument = async (file: File) => {
|
||||||
|
uploading.value = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('file', file)
|
||||||
|
formData.append('projectId', currentDetail.value.id.toString())
|
||||||
|
|
||||||
|
// 替换为实际API调用
|
||||||
|
const response = await uploadBiddingDocument(formData)
|
||||||
|
|
||||||
|
Message.success('文件上传成功')
|
||||||
|
currentDetail.value.biddingDocuments = response.data.fileUrl
|
||||||
|
} catch (error) {
|
||||||
|
Message.error(`文件上传失败: ${error.message}`)
|
||||||
|
} finally {
|
||||||
|
uploading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模拟上传API
|
||||||
|
const uploadBiddingDocument = (formData: FormData) => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
const file = formData.get('file') as File
|
||||||
|
const projectId = formData.get('projectId')
|
||||||
|
const extension = file.name.split('.').pop()
|
||||||
|
resolve({
|
||||||
|
data: {
|
||||||
|
fileUrl: `https://your-api-domain.com/uploads/${projectId}.${extension}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, 1500)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// 初始化加载数据
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
.project-list-container {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-section {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
padding: 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-area {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-area {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs-section {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-wrapper {
|
||||||
|
margin-top: 16px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.arco-tabs-content) {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.arco-tabs-pane) {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.arco-tabs-nav-tab) {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.arco-tabs-nav-tab-list) {
|
||||||
|
padding: 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 响应式处理
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.header-section {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-area {
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-area {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,64 @@
|
||||||
|
// 项目状态枚举
|
||||||
|
export enum ProjectStatus {
|
||||||
|
NOT_STARTED = 'not_started',
|
||||||
|
IN_PROGRESS = 'in_progress',
|
||||||
|
COMPLETED = 'completed',
|
||||||
|
PAUSED = 'paused',
|
||||||
|
CANCELLED = 'cancelled'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 项目数据接口
|
||||||
|
export interface ProjectData {
|
||||||
|
id: number
|
||||||
|
projectName: string
|
||||||
|
unitCount: number
|
||||||
|
startDate: string
|
||||||
|
endDate: string
|
||||||
|
status: ProjectStatus
|
||||||
|
progress: number
|
||||||
|
manager: string
|
||||||
|
isMyProject: boolean
|
||||||
|
description?: string
|
||||||
|
location?: string
|
||||||
|
client?: string
|
||||||
|
budget?: number
|
||||||
|
team?: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选项卡类型
|
||||||
|
export type TabKey = 'all' | 'my' | 'pending'
|
||||||
|
|
||||||
|
// 项目筛选条件
|
||||||
|
export interface ProjectFilter {
|
||||||
|
keyword?: string
|
||||||
|
status?: ProjectStatus
|
||||||
|
manager?: string
|
||||||
|
dateRange?: [string, string]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 项目统计信息
|
||||||
|
export interface ProjectStats {
|
||||||
|
total: number
|
||||||
|
inProgress: number
|
||||||
|
completed: number
|
||||||
|
notStarted: number
|
||||||
|
myProjects: number
|
||||||
|
}
|
||||||
|
|
||||||
|
// 招标详情
|
||||||
|
export interface BiddingDetail {
|
||||||
|
id: number
|
||||||
|
projectName: string
|
||||||
|
biddingUnit: string
|
||||||
|
budgetAmount: number
|
||||||
|
deadline: string
|
||||||
|
crawlingTime: string
|
||||||
|
projectLocation: string
|
||||||
|
projectDuration: string
|
||||||
|
biddingScope: string
|
||||||
|
qualificationRequirements: string
|
||||||
|
sourcePlatform: string
|
||||||
|
biddingDocuments: string
|
||||||
|
biddingContent: string
|
||||||
|
contentItems?: string[]
|
||||||
|
}
|
|
@ -1,28 +1,28 @@
|
||||||
<template>
|
<template>
|
||||||
<GiPageLayout>
|
<GiPageLayout>
|
||||||
<GiTable
|
<GiTable
|
||||||
row-key="id"
|
row-key="contractId"
|
||||||
title="收入合同管理"
|
title="收入合同管理"
|
||||||
:data="dataList"
|
:data="dataList"
|
||||||
:columns="tableColumns"
|
:columns="tableColumns"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:scroll="{ x: '100%', y: '100%', minWidth: 1600 }"
|
:scroll="{ x: '100%', y: '100%', minWidth: 1600 }"
|
||||||
:pagination="pagination"
|
:pagination="pagination"
|
||||||
@page-change="onPageChange"
|
@page-change="onPageChange"
|
||||||
@page-size-change="onPageSizeChange"
|
@page-size-change="onPageSizeChange"
|
||||||
@refresh="search"
|
@refresh="search"
|
||||||
>
|
>
|
||||||
<template #top>
|
<template #top>
|
||||||
<GiForm
|
<GiForm
|
||||||
v-model="searchForm"
|
v-model="searchForm"
|
||||||
search
|
search
|
||||||
:columns="queryFormColumns"
|
:columns="queryFormColumns"
|
||||||
size="medium"
|
size="medium"
|
||||||
@search="search"
|
@search="search"
|
||||||
@reset="reset"
|
@reset="reset"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #toolbar-left>
|
<template #toolbar-left>
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-button type="primary" @click="openAddModal">
|
<a-button type="primary" @click="openAddModal">
|
||||||
|
@ -35,30 +35,35 @@
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- 合同状态 -->
|
<!-- 合同状态 -->
|
||||||
<template #status="{ record }">
|
<template #contractStatus="{ record }">
|
||||||
<a-tag :color="getStatusColor(record.status)">
|
<a-tag :color="getStatusColor(record.contractStatus)">
|
||||||
{{ getStatusText(record.status) }}
|
{{ getStatusText(record.contractStatus) }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- 合同金额 -->
|
<!-- 合同金额 -->
|
||||||
<template #contractAmount="{ record }">
|
<template #amount="{ record }">
|
||||||
<span class="font-medium text-green-600">¥{{ record.contractAmount.toLocaleString() }}万</span>
|
<span class="font-medium text-green-600">¥{{ record.amount.toLocaleString() }}万</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- 已收款金额 -->
|
<!-- 已收款金额 -->
|
||||||
<template #receivedAmount="{ record }">
|
<template #receivedAmount="{ record }">
|
||||||
<span class="font-medium text-blue-600">¥{{ record.receivedAmount.toLocaleString() }}万</span>
|
<span class="font-medium text-blue-600">¥{{ record.receivedAmount.toLocaleString() }}万</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<!-- 已结算金额 -->
|
||||||
|
<template #settlementAmount="{ record }">
|
||||||
|
<span class="font-medium text-orange-600">¥{{ record.settlementAmount.toLocaleString() }}万</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
<!-- 操作列 -->
|
<!-- 操作列 -->
|
||||||
<template #action="{ record }">
|
<template #action="{ record }">
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-link @click="viewDetail(record)">详情</a-link>
|
<a-link @click="viewDetail(record)">详情</a-link>
|
||||||
<a-link @click="editRecord(record)" v-if="record.status === 'draft'">编辑</a-link>
|
<a-link @click="editRecord(record)" v-if="record.contractStatus === 'draft'">编辑</a-link>
|
||||||
<a-link @click="approveContract(record)" v-if="record.status === 'pending'">审批</a-link>
|
<a-link @click="approveContract(record)" v-if="record.contractStatus === 'pending'">审批</a-link>
|
||||||
<a-link @click="viewPayment(record)">收款记录</a-link>
|
<a-link @click="viewPayment(record)">收款记录</a-link>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
|
@ -70,38 +75,38 @@
|
||||||
import { ref, reactive, onMounted } from 'vue'
|
import { ref, reactive, onMounted } from 'vue'
|
||||||
import { Message } from '@arco-design/web-vue'
|
import { Message } from '@arco-design/web-vue'
|
||||||
import type { TableColumnData } from '@arco-design/web-vue'
|
import type { TableColumnData } from '@arco-design/web-vue'
|
||||||
|
import { getContractList, type ContractQueryParams, type ContractData } from '@/apis/contract'
|
||||||
|
|
||||||
// 搜索表单
|
// 搜索表单
|
||||||
let searchForm = reactive({
|
let searchForm = reactive({
|
||||||
contractName: '',
|
code: '',
|
||||||
contractCode: '',
|
customer: '',
|
||||||
client: '',
|
contractStatus: '',
|
||||||
status: '',
|
|
||||||
signDate: '',
|
signDate: '',
|
||||||
page: 1,
|
page: 1,
|
||||||
size: 10
|
pageSize: 10
|
||||||
})
|
})
|
||||||
|
|
||||||
// 查询条件配置
|
// 查询条件配置
|
||||||
const queryFormColumns = [
|
const queryFormColumns = [
|
||||||
{
|
{
|
||||||
field: 'contractName',
|
field: 'code',
|
||||||
label: '合同名称',
|
label: '合同编号',
|
||||||
type: 'input' as const,
|
type: 'input' as const,
|
||||||
props: {
|
props: {
|
||||||
placeholder: '请输入合同名称'
|
placeholder: '请输入合同编号'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'client',
|
field: 'customer',
|
||||||
label: '客户',
|
label: '客户名称',
|
||||||
type: 'input' as const,
|
type: 'input' as const,
|
||||||
props: {
|
props: {
|
||||||
placeholder: '请输入客户名称'
|
placeholder: '请输入客户名称'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'status',
|
field: 'contractStatus',
|
||||||
label: '合同状态',
|
label: '合同状态',
|
||||||
type: 'select' as const,
|
type: 'select' as const,
|
||||||
props: {
|
props: {
|
||||||
|
@ -120,83 +125,33 @@ const queryFormColumns = [
|
||||||
|
|
||||||
// 表格列配置
|
// 表格列配置
|
||||||
const tableColumns: TableColumnData[] = [
|
const tableColumns: TableColumnData[] = [
|
||||||
{ title: '合同编号', dataIndex: 'contractCode', width: 150 },
|
{ title: '合同编号', dataIndex: 'code', width: 150 },
|
||||||
{ title: '合同名称', dataIndex: 'contractName', width: 250, ellipsis: true, tooltip: true },
|
{ title: '合同内容', dataIndex: 'contractText', width: 250, ellipsis: true, tooltip: true },
|
||||||
{ title: '客户名称', dataIndex: 'client', width: 200, ellipsis: true, tooltip: true },
|
{ title: '客户名称', dataIndex: 'customer', width: 200, ellipsis: true, tooltip: true },
|
||||||
{ title: '合同金额', dataIndex: 'contractAmount', slotName: 'contractAmount', width: 120 },
|
{ title: '合同金额', dataIndex: 'amount', slotName: 'amount', width: 120 },
|
||||||
{ title: '已收款金额', dataIndex: 'receivedAmount', slotName: 'receivedAmount', width: 120 },
|
{ title: '已收款金额', dataIndex: 'receivedAmount', slotName: 'receivedAmount', width: 120 },
|
||||||
{ title: '未收款金额', dataIndex: 'pendingAmount', width: 120 },
|
{ title: '已结算金额', dataIndex: 'settlementAmount', slotName: 'settlementAmount', width: 120 },
|
||||||
{ title: '签署日期', dataIndex: 'signDate', width: 120 },
|
{ title: '签订日期', dataIndex: 'signDate', width: 120 },
|
||||||
{ title: '开始日期', dataIndex: 'startDate', width: 120 },
|
{ title: '付款日期', dataIndex: 'paymentDate', width: 120 },
|
||||||
{ title: '结束日期', dataIndex: 'endDate', width: 120 },
|
{ title: '履约期限', dataIndex: 'performanceDeadline', width: 120 },
|
||||||
{ title: '合同状态', dataIndex: 'status', slotName: 'status', width: 100 },
|
{ title: '合同状态', dataIndex: 'contractStatus', slotName: 'contractStatus', width: 100 },
|
||||||
{ title: '项目经理', dataIndex: 'projectManager', width: 100 },
|
{ title: '业务员', dataIndex: 'salespersonName', width: 100 },
|
||||||
{ title: '销售经理', dataIndex: 'salesManager', width: 100 },
|
{ title: '部门', dataIndex: 'salespersonDeptName', width: 120 },
|
||||||
{ title: '完成进度', dataIndex: 'progress', width: 100 },
|
{ title: '项目名称', dataIndex: 'projectName', width: 200, ellipsis: true, tooltip: true },
|
||||||
{ title: '备注', dataIndex: 'remark', width: 200, ellipsis: true, tooltip: true },
|
{ title: '产品或服务', dataIndex: 'productService', width: 200, ellipsis: true, tooltip: true },
|
||||||
|
{ title: '期限', dataIndex: 'duration', width: 100 },
|
||||||
|
{ title: '备注', dataIndex: 'notes', width: 200, ellipsis: true, tooltip: true },
|
||||||
{ title: '操作', slotName: 'action', width: 200, fixed: 'right' }
|
{ title: '操作', slotName: 'action', width: 200, fixed: 'right' }
|
||||||
]
|
]
|
||||||
|
|
||||||
// 数据状态
|
// 数据状态
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const dataList = ref([
|
const dataList = ref<ContractData[]>([])
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
contractCode: 'RC2024001',
|
|
||||||
contractName: '华能新能源风电场叶片检测服务合同',
|
|
||||||
client: '华能新能源股份有限公司',
|
|
||||||
contractAmount: 320,
|
|
||||||
receivedAmount: 192,
|
|
||||||
pendingAmount: 128,
|
|
||||||
signDate: '2024-02-20',
|
|
||||||
startDate: '2024-03-01',
|
|
||||||
endDate: '2024-04-30',
|
|
||||||
status: 'executing',
|
|
||||||
projectManager: '张项目经理',
|
|
||||||
salesManager: '李销售经理',
|
|
||||||
progress: '60%',
|
|
||||||
remark: '项目进展顺利,客户满意度高'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
contractCode: 'RC2024002',
|
|
||||||
contractName: '大唐风电场防雷检测项目合同',
|
|
||||||
client: '大唐新能源股份有限公司',
|
|
||||||
contractAmount: 268,
|
|
||||||
receivedAmount: 134,
|
|
||||||
pendingAmount: 134,
|
|
||||||
signDate: '2024-02-25',
|
|
||||||
startDate: '2024-03-05',
|
|
||||||
endDate: '2024-04-20',
|
|
||||||
status: 'executing',
|
|
||||||
projectManager: '王项目经理',
|
|
||||||
salesManager: '赵销售经理',
|
|
||||||
progress: '45%',
|
|
||||||
remark: '按计划执行中'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
contractCode: 'RC2024003',
|
|
||||||
contractName: '中广核风电场设备维护服务合同',
|
|
||||||
client: '中广核新能源投资有限公司',
|
|
||||||
contractAmount: 450,
|
|
||||||
receivedAmount: 450,
|
|
||||||
pendingAmount: 0,
|
|
||||||
signDate: '2024-01-15',
|
|
||||||
startDate: '2024-01-20',
|
|
||||||
endDate: '2024-01-31',
|
|
||||||
status: 'completed',
|
|
||||||
projectManager: '刘项目经理',
|
|
||||||
salesManager: '孙销售经理',
|
|
||||||
progress: '100%',
|
|
||||||
remark: '项目已完成,客户验收通过'
|
|
||||||
}
|
|
||||||
])
|
|
||||||
|
|
||||||
const pagination = reactive({
|
const pagination = reactive({
|
||||||
current: 1,
|
current: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
total: 3,
|
total: 0,
|
||||||
showTotal: true,
|
showTotal: true,
|
||||||
showPageSize: true
|
showPageSize: true
|
||||||
})
|
})
|
||||||
|
@ -230,20 +185,38 @@ const getStatusText = (status: string) => {
|
||||||
// 搜索和重置
|
// 搜索和重置
|
||||||
const search = async () => {
|
const search = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
setTimeout(() => {
|
try {
|
||||||
|
const params: ContractQueryParams = {
|
||||||
|
...searchForm,
|
||||||
|
type: 'revenue', // 只查询收入合同
|
||||||
|
page: searchForm.page,
|
||||||
|
pageSize: searchForm.pageSize
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await getContractList(params)
|
||||||
|
|
||||||
|
if (response.code === 0) {
|
||||||
|
dataList.value = response.rows || []
|
||||||
|
pagination.total = response.total || 0
|
||||||
|
} else {
|
||||||
|
Message.error(response.msg || '获取合同列表失败')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取合同列表失败:', error)
|
||||||
|
Message.error('获取合同列表失败')
|
||||||
|
} finally {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}, 1000)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
Object.assign(searchForm, {
|
Object.assign(searchForm, {
|
||||||
contractName: '',
|
code: '',
|
||||||
contractCode: '',
|
customer: '',
|
||||||
client: '',
|
contractStatus: '',
|
||||||
status: '',
|
|
||||||
signDate: '',
|
signDate: '',
|
||||||
page: 1,
|
page: 1,
|
||||||
size: 10
|
pageSize: 10
|
||||||
})
|
})
|
||||||
pagination.current = 1
|
pagination.current = 1
|
||||||
search()
|
search()
|
||||||
|
@ -257,7 +230,7 @@ const onPageChange = (page: number) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const onPageSizeChange = (size: number) => {
|
const onPageSizeChange = (size: number) => {
|
||||||
searchForm.size = size
|
searchForm.pageSize = size
|
||||||
searchForm.page = 1
|
searchForm.page = 1
|
||||||
pagination.pageSize = size
|
pagination.pageSize = size
|
||||||
pagination.current = 1
|
pagination.current = 1
|
||||||
|
@ -273,20 +246,20 @@ const exportContract = () => {
|
||||||
Message.info('导出合同功能开发中...')
|
Message.info('导出合同功能开发中...')
|
||||||
}
|
}
|
||||||
|
|
||||||
const viewDetail = (record: any) => {
|
const viewDetail = (record: ContractData) => {
|
||||||
Message.info(`查看合同详情: ${record.contractName}`)
|
Message.info(`查看合同详情: ${record.contractText}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const editRecord = (record: any) => {
|
const editRecord = (record: ContractData) => {
|
||||||
Message.info(`编辑合同: ${record.contractName}`)
|
Message.info(`编辑合同: ${record.contractText}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const approveContract = (record: any) => {
|
const approveContract = (record: ContractData) => {
|
||||||
Message.info(`审批合同: ${record.contractName}`)
|
Message.info(`审批合同: ${record.contractText}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const viewPayment = (record: any) => {
|
const viewPayment = (record: ContractData) => {
|
||||||
Message.info(`查看收款记录: ${record.contractName}`)
|
Message.info(`查看收款记录: ${record.contractText}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
|
||||||
|
</style>
|
|
@ -22,21 +22,6 @@
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="提案类型">
|
|
||||||
<a-select
|
|
||||||
v-model="searchForm.type"
|
|
||||||
placeholder="请选择类型"
|
|
||||||
allow-clear
|
|
||||||
style="width: 150px"
|
|
||||||
>
|
|
||||||
<a-option value="">全部</a-option>
|
|
||||||
<a-option value="管理规范">管理规范</a-option>
|
|
||||||
<a-option value="操作流程">操作流程</a-option>
|
|
||||||
<a-option value="安全制度">安全制度</a-option>
|
|
||||||
<a-option value="其他">其他</a-option>
|
|
||||||
</a-select>
|
|
||||||
</a-form-item>
|
|
||||||
|
|
||||||
<a-form-item label="状态">
|
<a-form-item label="状态">
|
||||||
<a-select
|
<a-select
|
||||||
v-model="searchForm.status"
|
v-model="searchForm.status"
|
||||||
|
@ -45,8 +30,8 @@
|
||||||
style="width: 150px"
|
style="width: 150px"
|
||||||
>
|
>
|
||||||
<a-option value="">全部</a-option>
|
<a-option value="">全部</a-option>
|
||||||
<a-option value="PUBLISHED">已公示</a-option>
|
<a-option value="PUBLISHED">已公告</a-option>
|
||||||
<a-option value="APPROVED">已通过</a-option>
|
<a-option value="APPROVED">已公示</a-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
|
@ -183,7 +168,6 @@ const columns = [
|
||||||
const searchForm = reactive({
|
const searchForm = reactive({
|
||||||
title: '',
|
title: '',
|
||||||
proposer: '',
|
proposer: '',
|
||||||
type: '',
|
|
||||||
status: ''
|
status: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -213,22 +197,19 @@ const regulationStore = useRegulationStore()
|
||||||
// 获取状态颜色
|
// 获取状态颜色
|
||||||
const getStatusColor = (status: RegulationStatus) => {
|
const getStatusColor = (status: RegulationStatus) => {
|
||||||
const colors = {
|
const colors = {
|
||||||
[RegulationStatus.DRAFT]: 'blue',
|
|
||||||
[RegulationStatus.PUBLISHED]: 'purple',
|
[RegulationStatus.PUBLISHED]: 'purple',
|
||||||
[RegulationStatus.APPROVED]: 'green',
|
[RegulationStatus.APPROVED]: 'green',
|
||||||
}
|
}
|
||||||
return colors[status] || 'blue'
|
return colors[status] || 'purple'
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取状态文本
|
// 获取状态文本
|
||||||
const getStatusText = (status: RegulationStatus) => {
|
const getStatusText = (status: RegulationStatus) => {
|
||||||
const texts = {
|
const texts = {
|
||||||
[RegulationStatus.DRAFT]: '草稿',
|
|
||||||
[RegulationStatus.PUBLISHED]: '已公告',
|
[RegulationStatus.PUBLISHED]: '已公告',
|
||||||
[RegulationStatus.APPROVED]: '已公示',
|
[RegulationStatus.APPROVED]: '已公示',
|
||||||
|
|
||||||
}
|
}
|
||||||
return texts[status] || '草稿'
|
return texts[status] || '已公告'
|
||||||
}
|
}
|
||||||
|
|
||||||
// 格式化日期
|
// 格式化日期
|
||||||
|
@ -268,21 +249,56 @@ const getLevelText = (level: RegulationLevel) => {
|
||||||
const getTableData = async () => {
|
const getTableData = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
const response = await regulationApi.getRegulationList({
|
// 构建请求参数
|
||||||
|
const requestParams: any = {
|
||||||
page: pagination.current,
|
page: pagination.current,
|
||||||
size: pagination.pageSize,
|
size: pagination.pageSize,
|
||||||
title: searchForm.title || undefined,
|
title: searchForm.title || undefined,
|
||||||
proposer: searchForm.proposer || undefined,
|
proposer: searchForm.proposer || undefined
|
||||||
type: searchForm.type || undefined,
|
}
|
||||||
status: searchForm.status || undefined
|
|
||||||
})
|
|
||||||
|
|
||||||
if (response.status === 200) {
|
if (searchForm.status) {
|
||||||
tableData.value = response.data.records
|
// 用户选择了特定状态
|
||||||
pagination.total = response.data.total
|
requestParams.status = searchForm.status
|
||||||
pagination.current = response.data.current
|
const response = await regulationApi.getRegulationList(requestParams)
|
||||||
|
|
||||||
|
if (response.status === 200) {
|
||||||
|
tableData.value = response.data.records
|
||||||
|
pagination.total = response.data.total
|
||||||
|
pagination.current = response.data.current
|
||||||
|
} else {
|
||||||
|
Message.error('搜索失败')
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Message.error('搜索失败')
|
// 用户没有选择状态,默认显示已公示和已公告的提案
|
||||||
|
// 分别查询已公告和已公示的提案
|
||||||
|
const [publishedResponse, approvedResponse] = await Promise.all([
|
||||||
|
regulationApi.getRegulationList({
|
||||||
|
...requestParams,
|
||||||
|
status: RegulationStatus.PUBLISHED
|
||||||
|
}),
|
||||||
|
regulationApi.getRegulationList({
|
||||||
|
...requestParams,
|
||||||
|
status: RegulationStatus.APPROVED
|
||||||
|
})
|
||||||
|
])
|
||||||
|
|
||||||
|
if (publishedResponse.status === 200 && approvedResponse.status === 200) {
|
||||||
|
// 合并两个结果
|
||||||
|
const allRecords = [
|
||||||
|
...publishedResponse.data.records,
|
||||||
|
...approvedResponse.data.records
|
||||||
|
]
|
||||||
|
|
||||||
|
// 按创建时间排序
|
||||||
|
allRecords.sort((a, b) => new Date(b.createTime).getTime() - new Date(a.createTime).getTime())
|
||||||
|
|
||||||
|
tableData.value = allRecords
|
||||||
|
pagination.total = allRecords.length
|
||||||
|
pagination.current = 1
|
||||||
|
} else {
|
||||||
|
Message.error('搜索失败')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('搜索制度公示失败:', error)
|
console.error('搜索制度公示失败:', error)
|
||||||
|
@ -303,7 +319,6 @@ const reset = () => {
|
||||||
Object.assign(searchForm, {
|
Object.assign(searchForm, {
|
||||||
title: '',
|
title: '',
|
||||||
proposer: '',
|
proposer: '',
|
||||||
type: '',
|
|
||||||
status: ''
|
status: ''
|
||||||
})
|
})
|
||||||
pagination.current = 1
|
pagination.current = 1
|
||||||
|
|
|
@ -31,21 +31,6 @@
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="提案类型">
|
|
||||||
<a-select
|
|
||||||
v-model="searchForm.type"
|
|
||||||
placeholder="请选择类型"
|
|
||||||
allow-clear
|
|
||||||
style="width: 150px"
|
|
||||||
>
|
|
||||||
<a-option value="">全部</a-option>
|
|
||||||
<a-option value="管理规范">管理规范</a-option>
|
|
||||||
<a-option value="操作流程">操作流程</a-option>
|
|
||||||
<a-option value="安全制度">安全制度</a-option>
|
|
||||||
<a-option value="其他">其他</a-option>
|
|
||||||
</a-select>
|
|
||||||
</a-form-item>
|
|
||||||
|
|
||||||
<a-form-item label="状态">
|
<a-form-item label="状态">
|
||||||
<a-select
|
<a-select
|
||||||
v-model="searchForm.status"
|
v-model="searchForm.status"
|
||||||
|
@ -352,7 +337,6 @@ const columns = [
|
||||||
const searchForm = reactive({
|
const searchForm = reactive({
|
||||||
title: '',
|
title: '',
|
||||||
proposer: '',
|
proposer: '',
|
||||||
type: '',
|
|
||||||
status: ''
|
status: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -484,7 +468,6 @@ const getTableData = async () => {
|
||||||
size: pagination.pageSize,
|
size: pagination.pageSize,
|
||||||
title: searchForm.title || undefined,
|
title: searchForm.title || undefined,
|
||||||
proposer: searchForm.proposer || undefined,
|
proposer: searchForm.proposer || undefined,
|
||||||
type: searchForm.type || undefined,
|
|
||||||
status: searchForm.status || undefined
|
status: searchForm.status || undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -514,7 +497,6 @@ const reset = () => {
|
||||||
Object.assign(searchForm, {
|
Object.assign(searchForm, {
|
||||||
title: '',
|
title: '',
|
||||||
proposer: '',
|
proposer: '',
|
||||||
type: '',
|
|
||||||
status: ''
|
status: ''
|
||||||
})
|
})
|
||||||
pagination.current = 1
|
pagination.current = 1
|
||||||
|
|
|
@ -30,8 +30,8 @@
|
||||||
style="width: 150px"
|
style="width: 150px"
|
||||||
>
|
>
|
||||||
<a-option value="">全部</a-option>
|
<a-option value="">全部</a-option>
|
||||||
<a-option value="confirmed">已确认</a-option>
|
<a-option value="CONFIRMED">已确认</a-option>
|
||||||
<a-option value="pending">待确认</a-option>
|
<a-option value="PENDING">待确认</a-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
|
@ -64,8 +64,8 @@
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</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' ? '已确认' : '待确认' }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -96,6 +96,11 @@
|
||||||
<span>公示人: {{ currentRegulation.createByName }}</span>
|
<span>公示人: {{ currentRegulation.createByName }}</span>
|
||||||
<span>公示时间: {{ currentRegulation.publishTime }}</span>
|
<span>公示时间: {{ currentRegulation.publishTime }}</span>
|
||||||
<span>生效日期: {{ currentRegulation.effectiveTime }}</span>
|
<span>生效日期: {{ currentRegulation.effectiveTime }}</span>
|
||||||
|
<span>确认状态:
|
||||||
|
<a-tag :color="currentRegulation.confirmStatus === 'CONFIRMED' ? 'green' : 'orange'">
|
||||||
|
{{ currentRegulation.confirmStatus === 'CONFIRMED' ? '已确认' : '待确认' }}
|
||||||
|
</a-tag>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -118,9 +123,20 @@
|
||||||
<a-divider />
|
<a-divider />
|
||||||
|
|
||||||
<div class="detail-footer">
|
<div class="detail-footer">
|
||||||
<a-button type="primary" @click="handleConfirm(currentRegulation)">
|
<a-button
|
||||||
确认知晓并遵守
|
v-if="currentRegulation.confirmStatus !== 'CONFIRMED'"
|
||||||
</a-button>
|
type="primary"
|
||||||
|
@click="handleConfirm(currentRegulation)"
|
||||||
|
>
|
||||||
|
确认知晓并遵守
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
v-else
|
||||||
|
type="primary"
|
||||||
|
disabled
|
||||||
|
>
|
||||||
|
已确认知晓
|
||||||
|
</a-button>
|
||||||
<a-button @click="handleDownload(currentRegulation)">
|
<a-button @click="handleDownload(currentRegulation)">
|
||||||
下载制度文件
|
下载制度文件
|
||||||
</a-button>
|
</a-button>
|
||||||
|
@ -216,10 +232,20 @@ const getTableData = async () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
tableData.value = response.data.records
|
|
||||||
|
|
||||||
|
// 确保每个记录都有 confirmStatus 字段
|
||||||
|
const records = response.data.records.map((record: any) => ({
|
||||||
|
...record,
|
||||||
|
confirmStatus: record.confirmStatus || 'PENDING'
|
||||||
|
}))
|
||||||
|
|
||||||
|
tableData.value = records
|
||||||
pagination.pageSize = response.data.size
|
pagination.pageSize = response.data.size
|
||||||
pagination.current = response.data.current
|
pagination.current = response.data.current
|
||||||
pagination.total = response.data.total
|
pagination.total = response.data.total
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Message.error('搜索失败')
|
Message.error('搜索失败')
|
||||||
}
|
}
|
||||||
|
@ -311,11 +337,16 @@ const submitConfirm = async () => {
|
||||||
Message.success('确认成功,您已承诺遵守该制度')
|
Message.success('确认成功,您已承诺遵守该制度')
|
||||||
confirmModalVisible.value = false
|
confirmModalVisible.value = false
|
||||||
|
|
||||||
// 更新本地数据状态
|
// 立即刷新数据,确保状态同步
|
||||||
const index = tableData.value.findIndex(item => item.regulationId === currentRegulation.value.regulationId)
|
await getTableData()
|
||||||
if (index !== -1) {
|
|
||||||
tableData.value[index].confirmStatus = 'confirmed'
|
// 如果详情弹窗是打开的,也更新详情弹窗中的数据
|
||||||
}
|
if (detailModalVisible.value && currentRegulation.value) {
|
||||||
|
const updatedRecord = tableData.value.find(item => item.regulationId === currentRegulation.value.regulationId)
|
||||||
|
if (updatedRecord) {
|
||||||
|
currentRegulation.value = updatedRecord
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('确认失败:', error)
|
console.error('确认失败:', error)
|
||||||
|
|
|
@ -0,0 +1,313 @@
|
||||||
|
<template>
|
||||||
|
<div class="device-detail-container">
|
||||||
|
<a-card title="设备基本信息">
|
||||||
|
<a-descriptions :data="basicInfo" layout="vertical" bordered />
|
||||||
|
</a-card>
|
||||||
|
|
||||||
|
<a-card title="设备状态信息" style="margin-top: 16px">
|
||||||
|
<a-descriptions :data="statusInfo" layout="vertical" bordered />
|
||||||
|
</a-card>
|
||||||
|
|
||||||
|
<a-card title="设备详细信息" style="margin-top: 16px">
|
||||||
|
<a-tabs>
|
||||||
|
<a-tab-pane key="maintenance" tab="维护记录">
|
||||||
|
<div class="maintenance-section">
|
||||||
|
<a-button type="primary" @click="handleAddMaintenance">
|
||||||
|
添加维护记录
|
||||||
|
</a-button>
|
||||||
|
<a-divider />
|
||||||
|
<a-table :data="maintenanceRecords" :columns="maintenanceColumns" row-key="id" size="small" />
|
||||||
|
</div>
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="usage" tab="使用记录">
|
||||||
|
<div class="usage-section">
|
||||||
|
<a-table :data="usageRecords" :columns="usageColumns" row-key="id" size="small" />
|
||||||
|
</div>
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="location" tab="位置变更">
|
||||||
|
<div class="location-section">
|
||||||
|
<a-table :data="locationRecords" :columns="locationColumns" row-key="id" size="small" />
|
||||||
|
</div>
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="files" tab="相关文件">
|
||||||
|
<div class="files-section">
|
||||||
|
<a-upload
|
||||||
|
:file-list="fileList"
|
||||||
|
:custom-request="handleFileUpload"
|
||||||
|
:show-upload-list="{ showPreviewIcon: true, showRemoveIcon: true }"
|
||||||
|
>
|
||||||
|
<a-button>
|
||||||
|
<template #icon>
|
||||||
|
<IconUpload />
|
||||||
|
</template>
|
||||||
|
上传文件
|
||||||
|
</a-button>
|
||||||
|
</a-upload>
|
||||||
|
</div>
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
</a-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { onMounted, ref } from 'vue'
|
||||||
|
import { useRoute } from 'vue-router'
|
||||||
|
import { IconUpload } from '@arco-design/web-vue/es/icon'
|
||||||
|
import { getEquipmentDetail } from '@/apis/equipment'
|
||||||
|
import type { EquipmentResp } from '@/types/equipment.d'
|
||||||
|
|
||||||
|
defineOptions({ name: 'DeviceDetail' })
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const deviceId = route.params.id as string
|
||||||
|
|
||||||
|
// 设备基本信息
|
||||||
|
const basicInfo = ref([
|
||||||
|
{ label: '设备名称', value: '' },
|
||||||
|
{ label: '设备类型', value: '' },
|
||||||
|
{ label: '设备型号', value: '' },
|
||||||
|
{ label: '序列号', value: '' },
|
||||||
|
{ label: '品牌', value: '' },
|
||||||
|
{ label: '资产编号', value: '' },
|
||||||
|
{ label: '负责人', value: '' },
|
||||||
|
{ label: '物理位置', value: '' },
|
||||||
|
{ label: '配置规格', value: '' },
|
||||||
|
{ label: '备注', value: '' },
|
||||||
|
])
|
||||||
|
|
||||||
|
// 设备状态信息
|
||||||
|
const statusInfo = ref([
|
||||||
|
{ label: '设备状态', value: '' },
|
||||||
|
{ label: '使用状态', value: '' },
|
||||||
|
{ label: '位置状态', value: '' },
|
||||||
|
{ label: '健康状态', value: '' },
|
||||||
|
{ label: '当前使用人', value: '' },
|
||||||
|
{ label: '所属项目', value: '' },
|
||||||
|
{ label: '创建时间', value: '' },
|
||||||
|
{ label: '更新时间', value: '' },
|
||||||
|
])
|
||||||
|
|
||||||
|
// 维护记录
|
||||||
|
const maintenanceRecords = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
maintenanceType: '定期保养',
|
||||||
|
maintenancePerson: '张师傅',
|
||||||
|
maintenanceTime: '2024-06-01 10:00:00',
|
||||||
|
description: '更换机油,检查设备运行状态',
|
||||||
|
cost: 500,
|
||||||
|
status: '已完成',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
maintenanceType: '故障维修',
|
||||||
|
maintenancePerson: '李师傅',
|
||||||
|
maintenanceTime: '2024-05-15 14:30:00',
|
||||||
|
description: '修复传感器故障',
|
||||||
|
cost: 1200,
|
||||||
|
status: '已完成',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const maintenanceColumns = [
|
||||||
|
{ title: '维护类型', dataIndex: 'maintenanceType', key: 'maintenanceType' },
|
||||||
|
{ title: '维护人员', dataIndex: 'maintenancePerson', key: 'maintenancePerson' },
|
||||||
|
{ title: '维护时间', dataIndex: 'maintenanceTime', key: 'maintenanceTime' },
|
||||||
|
{ title: '维护描述', dataIndex: 'description', key: 'description' },
|
||||||
|
{ title: '维护费用', dataIndex: 'cost', key: 'cost' },
|
||||||
|
{ title: '状态', dataIndex: 'status', key: 'status' },
|
||||||
|
]
|
||||||
|
|
||||||
|
// 使用记录
|
||||||
|
const usageRecords = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
userName: '张三',
|
||||||
|
projectName: '项目A',
|
||||||
|
startTime: '2024-06-01 09:00:00',
|
||||||
|
endTime: '2024-06-01 18:00:00',
|
||||||
|
usagePurpose: '现场检测',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
userName: '李四',
|
||||||
|
projectName: '项目B',
|
||||||
|
startTime: '2024-05-30 08:00:00',
|
||||||
|
endTime: '2024-05-30 17:00:00',
|
||||||
|
usagePurpose: '安全巡检',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const usageColumns = [
|
||||||
|
{ title: '使用人', dataIndex: 'userName', key: 'userName' },
|
||||||
|
{ title: '项目名称', dataIndex: 'projectName', key: 'projectName' },
|
||||||
|
{ title: '开始时间', dataIndex: 'startTime', key: 'startTime' },
|
||||||
|
{ title: '结束时间', dataIndex: 'endTime', key: 'endTime' },
|
||||||
|
{ title: '使用目的', dataIndex: 'usagePurpose', key: 'usagePurpose' },
|
||||||
|
]
|
||||||
|
|
||||||
|
// 位置变更记录
|
||||||
|
const locationRecords = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
oldLocation: '仓库A',
|
||||||
|
newLocation: '现场B',
|
||||||
|
changeTime: '2024-06-01 08:00:00',
|
||||||
|
changeReason: '项目需要',
|
||||||
|
operator: '管理员',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
oldLocation: '现场B',
|
||||||
|
newLocation: '仓库A',
|
||||||
|
changeTime: '2024-05-30 18:00:00',
|
||||||
|
changeReason: '项目结束',
|
||||||
|
operator: '管理员',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const locationColumns = [
|
||||||
|
{ title: '原位置', dataIndex: 'oldLocation', key: 'oldLocation' },
|
||||||
|
{ title: '新位置', dataIndex: 'newLocation', key: 'newLocation' },
|
||||||
|
{ title: '变更时间', dataIndex: 'changeTime', key: 'changeTime' },
|
||||||
|
{ title: '变更原因', dataIndex: 'changeReason', key: 'changeReason' },
|
||||||
|
{ title: '操作人', dataIndex: 'operator', key: 'operator' },
|
||||||
|
]
|
||||||
|
|
||||||
|
// 文件列表
|
||||||
|
const fileList = ref([
|
||||||
|
{
|
||||||
|
uid: '1',
|
||||||
|
name: '设备说明书.pdf',
|
||||||
|
status: 'done',
|
||||||
|
url: 'https://example.com/manual.pdf',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uid: '2',
|
||||||
|
name: '维护记录.xlsx',
|
||||||
|
status: 'done',
|
||||||
|
url: 'https://example.com/maintenance.xlsx',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
// 获取设备类型文本
|
||||||
|
const getEquipmentTypeText = (type: string) => {
|
||||||
|
const typeMap: Record<string, string> = {
|
||||||
|
1: '检测设备',
|
||||||
|
2: '安全设备',
|
||||||
|
3: '车辆',
|
||||||
|
}
|
||||||
|
return typeMap[type] || type
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取设备状态文本
|
||||||
|
const getEquipmentStatusText = (status: string) => {
|
||||||
|
const statusMap: Record<string, string> = {
|
||||||
|
normal: '正常',
|
||||||
|
maintenance: '维修中',
|
||||||
|
scrapped: '报废',
|
||||||
|
}
|
||||||
|
return statusMap[status] || status
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取使用状态文本
|
||||||
|
const getUseStatusText = (status: string) => {
|
||||||
|
return status === '1' ? '使用中' : '空闲'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取位置状态文本
|
||||||
|
const getLocationStatusText = (status: string) => {
|
||||||
|
const statusMap: Record<string, string> = {
|
||||||
|
in_stock: '库存中',
|
||||||
|
allocated: '已分配',
|
||||||
|
repair: '维修中',
|
||||||
|
scrap: '待报废',
|
||||||
|
scrapped: '已报废',
|
||||||
|
borrowed: '外借中',
|
||||||
|
lost: '丢失',
|
||||||
|
}
|
||||||
|
return statusMap[status] || status
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取健康状态文本
|
||||||
|
const getHealthStatusText = (status: string) => {
|
||||||
|
const statusMap: Record<string, string> = {
|
||||||
|
excellent: '优秀',
|
||||||
|
good: '良好',
|
||||||
|
normal: '一般',
|
||||||
|
poor: '较差',
|
||||||
|
bad: '差',
|
||||||
|
}
|
||||||
|
return statusMap[status] || status
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载设备详情
|
||||||
|
const loadDeviceDetail = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getEquipmentDetail(deviceId)
|
||||||
|
const device = res.data as EquipmentResp
|
||||||
|
|
||||||
|
// 更新基本信息
|
||||||
|
basicInfo.value = [
|
||||||
|
{ label: '设备名称', value: device.equipmentName },
|
||||||
|
{ label: '设备类型', value: getEquipmentTypeText(device.equipmentType) },
|
||||||
|
{ label: '设备型号', value: device.equipmentModel },
|
||||||
|
{ label: '序列号', value: device.equipmentSn },
|
||||||
|
{ label: '品牌', value: device.brand || '-' },
|
||||||
|
{ label: '资产编号', value: device.assetCode || '-' },
|
||||||
|
{ label: '负责人', value: device.responsiblePerson || '-' },
|
||||||
|
{ label: '物理位置', value: device.physicalLocation || '-' },
|
||||||
|
{ label: '配置规格', value: device.specification || '-' },
|
||||||
|
{ label: '备注', value: device.assetRemark || '-' },
|
||||||
|
]
|
||||||
|
|
||||||
|
// 更新状态信息
|
||||||
|
statusInfo.value = [
|
||||||
|
{ label: '设备状态', value: getEquipmentStatusText(device.equipmentStatus) },
|
||||||
|
{ label: '使用状态', value: getUseStatusText(device.useStatus) },
|
||||||
|
{ label: '位置状态', value: getLocationStatusText(device.locationStatus || '') },
|
||||||
|
{ label: '健康状态', value: getHealthStatusText(device.healthStatus || '') },
|
||||||
|
{ label: '当前使用人', value: device.name || '-' },
|
||||||
|
{ label: '所属项目', value: device.projectName || '-' },
|
||||||
|
{ label: '创建时间', value: device.createTime || '-' },
|
||||||
|
{ label: '更新时间', value: device.updateTime || '-' },
|
||||||
|
]
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载设备详情失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加维护记录
|
||||||
|
const handleAddMaintenance = () => {
|
||||||
|
// TODO: 实现添加维护记录的逻辑
|
||||||
|
console.log('添加维护记录')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 文件上传处理
|
||||||
|
const handleFileUpload = (options: any) => {
|
||||||
|
// TODO: 实现文件上传逻辑
|
||||||
|
console.log('文件上传:', options)
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (deviceId) {
|
||||||
|
loadDeviceDetail()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.device-detail-container {
|
||||||
|
padding: 16px;
|
||||||
|
background: #f5f5f5;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.maintenance-section,
|
||||||
|
.usage-section,
|
||||||
|
.location-section,
|
||||||
|
.files-section {
|
||||||
|
padding: 16px 0;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -29,7 +29,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="info-item">
|
<div class="info-item">
|
||||||
<div class="info-label">所属部门</div>
|
<div class="info-label">所属部门</div>
|
||||||
<div class="info-value">{{ primaryInfo?.department || '技术部' }}</div>
|
<div class="info-value">{{ primaryInfo?.deptName || '技术部' }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-item">
|
<div class="info-item">
|
||||||
<div class="info-label">直接上级岗位</div>
|
<div class="info-label">直接上级岗位</div>
|
||||||
|
@ -52,7 +52,7 @@
|
||||||
<div class="info-value">{{ primaryInfo?.location || '上海/远程' }}</div>
|
<div class="info-value">{{ primaryInfo?.location || '上海/远程' }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 岗位目的 -->
|
<!-- 岗位目的 -->
|
||||||
<div class="section-title">岗位目的</div>
|
<div class="section-title">岗位目的</div>
|
||||||
<div class="content-container">
|
<div class="content-container">
|
||||||
|
@ -68,18 +68,18 @@
|
||||||
<div class="section-title">主要职责与工作任务</div>
|
<div class="section-title">主要职责与工作任务</div>
|
||||||
<div class="content-container">
|
<div class="content-container">
|
||||||
<ul>
|
<ul>
|
||||||
<li v-for="(task, idx) in (primaryInfo?.tasks || ['负责XXX产品的需求分析、架构设计、核心模块编码和单元测试。','制定并执行季度社交媒体营销计划,提升品牌曝光度和用户互动率。'])" :key="idx">{{ task }}</li>
|
<li v-for="(task, idx) in (primaryInfo?.tasks || ['负责XXX产品的需求分析、架构设计、核心模块编码和单元测试。', '制定并执行季度社交媒体营销计划,提升品牌曝光度和用户互动率。'])" :key="idx">{{ task }}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 工作权限 -->
|
<!-- 工作权限 -->
|
||||||
<div class="section-title">工作权限</div>
|
<div class="section-title">工作权限</div>
|
||||||
<div class="content-container">
|
<div class="content-container">
|
||||||
<ul>
|
<ul>
|
||||||
<li v-for="(perm, idx) in (primaryInfo?.permissions || ['有权审批部门内5000元以下的采购申请。','有权对项目团队成员的工作任务进行分配和调整。'])" :key="idx">{{ perm }}</li>
|
<li v-for="(perm, idx) in (primaryInfo?.permissions || ['有权审批部门内5000元以下的采购申请。', '有权对项目团队成员的工作任务进行分配和调整。'])" :key="idx">{{ perm }}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 汇报关系 -->
|
<!-- 汇报关系 -->
|
||||||
<div class="section-title">汇报关系</div>
|
<div class="section-title">汇报关系</div>
|
||||||
<div class="info-grid">
|
<div class="info-grid">
|
||||||
|
@ -167,7 +167,7 @@
|
||||||
<div class="content-container">
|
<div class="content-container">
|
||||||
<div class="content-text">{{ primaryInfo?.performance || '根据项目按时交付率、代码质量、产品性能指标提升情况进行评估。' }}</div>
|
<div class="content-text">{{ primaryInfo?.performance || '根据项目按时交付率、代码质量、产品性能指标提升情况进行评估。' }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 薪酬范围 -->
|
<!-- 薪酬范围 -->
|
||||||
<div class="section-title">薪酬范围</div>
|
<div class="section-title">薪酬范围</div>
|
||||||
<div class="content-container">
|
<div class="content-container">
|
||||||
|
@ -184,7 +184,7 @@
|
||||||
<div class="content-container">
|
<div class="content-container">
|
||||||
<div class="content-text">{{ primaryInfo?.culture || '客户第一、创新、诚信、合作' }}</div>
|
<div class="content-text">{{ primaryInfo?.culture || '客户第一、创新、诚信、合作' }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 职业发展路径 -->
|
<!-- 职业发展路径 -->
|
||||||
<div class="section-title">职业发展路径</div>
|
<div class="section-title">职业发展路径</div>
|
||||||
<div class="content-container">
|
<div class="content-container">
|
||||||
|
@ -244,7 +244,7 @@ const getDetail = async (id: string) => {
|
||||||
id: data.postId ?? data.id ?? '10001',
|
id: data.postId ?? data.id ?? '10001',
|
||||||
name: data.postName ?? data.name ?? '-',
|
name: data.postName ?? data.name ?? '-',
|
||||||
status: data.status,
|
status: data.status,
|
||||||
department: data.department ?? '技术部',
|
department: data.department ?? data.deptName ?? '技术部',
|
||||||
superior: data.superior ?? '技术总监',
|
superior: data.superior ?? '技术总监',
|
||||||
level: data.level ?? 'P5',
|
level: data.level ?? 'P5',
|
||||||
version: data.version ?? '2024-06-01 / V1.0',
|
version: data.version ?? '2024-06-01 / V1.0',
|
||||||
|
@ -252,11 +252,11 @@ const getDetail = async (id: string) => {
|
||||||
summary: data.summary ?? '负责公司核心产品开发,支撑业务增长。',
|
summary: data.summary ?? '负责公司核心产品开发,支撑业务增长。',
|
||||||
tasks: data.tasks ?? [
|
tasks: data.tasks ?? [
|
||||||
'负责XXX产品的需求分析、架构设计、核心模块编码和单元测试。',
|
'负责XXX产品的需求分析、架构设计、核心模块编码和单元测试。',
|
||||||
'制定并执行季度社交媒体营销计划,提升品牌曝光度和用户互动率。'
|
'制定并执行季度社交媒体营销计划,提升品牌曝光度和用户互动率。',
|
||||||
],
|
],
|
||||||
permissions: data.permissions ?? [
|
permissions: data.permissions ?? [
|
||||||
'有权审批部门内5000元以下的采购申请。',
|
'有权审批部门内5000元以下的采购申请。',
|
||||||
'有权对项目团队成员的工作任务进行分配和调整。'
|
'有权对项目团队成员的工作任务进行分配和调整。',
|
||||||
],
|
],
|
||||||
subordinates: data.subordinates ?? '无',
|
subordinates: data.subordinates ?? '无',
|
||||||
collaboration: data.collaboration ?? '与产品部、销售部、客服部紧密合作',
|
collaboration: data.collaboration ?? '与产品部、销售部、客服部紧密合作',
|
||||||
|
|
Loading…
Reference in New Issue