diff --git a/src/api/kb/category.ts b/src/api/kb/category.ts new file mode 100644 index 0000000..bb9a59d --- /dev/null +++ b/src/api/kb/category.ts @@ -0,0 +1,93 @@ +import { request } from "@/api/request"; + +/** 分类类型 */ +export interface Category { + id: number; + created_at: string; + updated_at: string; + name: string; + description: string; + type: string; + icon: string; + color: string; + parent_id: number; + level: number; + path: string; + sort_order: number; + status: string; + creator_id: number; + creator_name: string; + doc_count: number; + faq_count: number; + metadata: string | null; + remarks: string; +} + +/** API响应包装类型 */ +export interface ApiResponse { + code: number; + message: string; + data: T; +} + +/** 创建分类请求参数 */ +export interface CreateCategoryParams { + name: string; + description?: string; + type?: string; + icon?: string; + color?: string; + parent_id?: number; + sort_order?: number; + remarks?: string; +} + +/** 更新分类请求参数 */ +export interface UpdateCategoryParams { + id: number; + name?: string; + description?: string; + icon?: string; + color?: string; + sort_order?: number; + status?: string; + remarks?: string; +} + +/** 获取分类列表参数 */ +export interface FetchCategoryListParams { + type?: string; + parent_id?: number; +} + +/** 创建分类 */ +export const createCategory = (data: CreateCategoryParams) => { + return request.post>("/Kb/v1/category/create", data); +}; + +/** 更新分类 */ +export const updateCategory = (data: UpdateCategoryParams) => { + return request.post>("/Kb/v1/category/update", data); +}; + +/** 删除分类 */ +export const deleteCategory = (id: number) => { + return request.delete>(`/Kb/v1/category/${id}`); +}; + +/** 获取分类详情 */ +export const fetchCategoryDetail = (id: number) => { + return request.get>(`/Kb/v1/category/${id}`); +}; + +/** 获取分类列表 */ +export const fetchCategoryList = (params?: FetchCategoryListParams) => { + return request.get>("/Kb/v1/category/list", { params }); +}; + +/** 获取分类树 */ +export const fetchCategoryTree = (type?: string) => { + return request.get>("/Kb/v1/category/tree", { + params: type ? { type } : undefined, + }); +}; \ No newline at end of file diff --git a/src/api/kb/document.ts b/src/api/kb/document.ts new file mode 100644 index 0000000..16fcf31 --- /dev/null +++ b/src/api/kb/document.ts @@ -0,0 +1,212 @@ +import { request } from "@/api/request"; + +/** 文档状态 */ +export type DocumentStatus = 'draft' | 'published' | 'reviewed' | 'rejected'; + +/** 文档类型 */ +export type DocumentType = 'common' | 'guide' | 'solution' | 'troubleshoot' | 'process' | 'technical'; + +/** 文档接口类型 */ +export interface Document { + id: number; + created_at: string; + updated_at: string; + doc_no: string; + title: string; + description: string; + content: string; + type: DocumentType; + status: DocumentStatus; + category_id: number; + sub_category: string; + author_id: number; + author_name: string; + reviewer_id: number; + reviewer_name: string; + reviewed_at: string | null; + published_at: string | null; + publisher_id: number; + view_count: number; + like_count: number; + comment_count: number; + download_count: number; + version: string; + version_notes: string; + tags: string; + attachments: string | null; + related_docs: string | null; + metadata: string | null; + keywords: string; + remarks: string; + is_favorited?: boolean; +} + +/** API响应包装类型 */ +export interface ApiResponse { + code: number; + message: string; + data: T; +} + +/** 分页响应类型 */ +export interface PaginatedResponse { + total: number; + page: number; + page_size: number; + data: T[]; +} + +/** 创建文档请求参数 */ +export interface CreateDocumentParams { + title: string; + description?: string; + content: string; + type?: DocumentType; + category_id?: number; + sub_category?: string; + keywords?: string; + tags?: string; + remarks?: string; +} + +/** 更新文档请求参数 */ +export interface UpdateDocumentParams { + id: number; + title?: string; + description?: string; + content?: string; + type?: DocumentType; + category_id?: number; + sub_category?: string; + keywords?: string; + tags?: string; + remarks?: string; +} + +/** 获取文档列表参数 */ +export interface FetchDocumentListParams { + page?: number; + page_size?: number; + keyword?: string; + type?: DocumentType; + status?: DocumentStatus; + category_id?: number; +} + +/** 文档类型选项 */ +export const documentTypeOptions = [ + { label: '通用文档', value: 'common' }, + { label: '操作指南', value: 'guide' }, + { label: '解决方案', value: 'solution' }, + { label: '故障排查', value: 'troubleshoot' }, + { label: '流程规范', value: 'process' }, + { label: '技术文档', value: 'technical' }, +]; + +/** 文档状态选项 */ +export const documentStatusOptions = [ + { label: '草稿', value: 'draft' }, + { label: '已发布', value: 'published' }, + { label: '已审核', value: 'reviewed' }, + { label: '未通过审核', value: 'rejected' }, +]; + +/** 获取文档状态文本 */ +export const getDocumentStatusText = (status: DocumentStatus): string => { + const statusMap: Record = { + draft: '草稿', + published: '已发布', + reviewed: '已审核', + rejected: '未通过审核', + }; + return statusMap[status] || status; +}; + +/** 获取文档状态颜色 */ +export const getDocumentStatusColor = (status: DocumentStatus): string => { + const colorMap: Record = { + draft: 'gray', + published: 'blue', + reviewed: 'green', + rejected: 'red', + }; + return colorMap[status] || 'gray'; +}; + +/** 获取文档类型文本 */ +export const getDocumentTypeText = (type: DocumentType): string => { + const typeMap: Record = { + common: '通用文档', + guide: '操作指南', + solution: '解决方案', + troubleshoot: '故障排查', + process: '流程规范', + technical: '技术文档', + }; + return typeMap[type] || type; +}; + +/** 创建文档 */ +export const createDocument = (data: CreateDocumentParams) => { + return request.post>("/Kb/v1/document/create", data); +}; + +/** 更新文档 */ +export const updateDocument = (data: UpdateDocumentParams) => { + return request.post>("/Kb/v1/document/update", data); +}; + +/** 删除文档(移入回收站) */ +export const deleteDocument = (id: number) => { + return request.delete>(`/Kb/v1/document/${id}`); +}; + +/** 获取文档详情 */ +export const fetchDocumentDetail = (id: number) => { + return request.get>(`/Kb/v1/document/${id}`); +}; + +/** 获取文档列表 */ +export const fetchDocumentList = (params?: FetchDocumentListParams) => { + return request.get>>("/Kb/v1/document/list", { params }); +}; + +/** 发布文档 */ +export const publishDocument = (id: number) => { + return request.post>("/Kb/v1/document/publish", { id }); +}; + +/** 移入回收站 */ +export const moveToTrash = (id: number) => { + return request.post>("/Kb/v1/trash/move", { id, type: 'document' }); +}; + +/** 获取我的文档列表(由我创建的所有文档) */ +export const fetchMyDocumentList = (params?: FetchDocumentListParams) => { + return request.get>>("/Kb/v1/review/publish/list", { params }); +}; + +/** 获取已审核通过的文档列表 */ +export const fetchApprovedDocumentList = (params?: FetchDocumentListParams) => { + return request.get>>("/Kb/v1/review/approved/list", { params }); +}; + +/** 收藏文档 */ +export const favoriteDocument = (id: number) => { + return request.post>("/Kb/v1/favorite/create", { resource_type: 'document', resource_id: id }); +}; + +/** 取消收藏文档 */ +export const unfavoriteDocument = (id: number) => { + return request.delete>("/Kb/v1/favorite/delete", { data: { resource_type: 'document', resource_id: id } }); +}; + +/** 检查文档是否已收藏 */ +export const checkFavorite = (id: number) => { + return request.get>(`/Kb/v1/favorite/check`, { params: { resource_type: 'document', resource_id: id } }); +}; + +/** 下载文档 */ +export const downloadDocument = (id: number) => { + return request.get(`/Kb/v1/document/${id}/download`, { responseType: 'blob' }); +}; \ No newline at end of file diff --git a/src/api/kb/trash.ts b/src/api/kb/trash.ts new file mode 100644 index 0000000..268a308 --- /dev/null +++ b/src/api/kb/trash.ts @@ -0,0 +1,88 @@ +import { request } from "@/api/request"; + +/** API响应包装类型 */ +export interface ApiResponse { + code: number; + message: string; + data: T; +} + +/** 分页响应类型 */ +export interface PaginatedResponse { + total: number; + page: number; + page_size: number; + data: T[]; +} + +/** 回收站记录 */ +export interface TrashRecord { + id: number; + created_at: string; + updated_at: string; + resource_type: 'document' | 'faq'; + resource_id: number; + resource_name: string; + deleted_by: number; + deleted_name: string; + deleted_time: string; + delete_reason: string; + original_data: string; + remarks: string; +} + +/** 获取回收站列表参数 */ +export interface FetchTrashListParams { + page?: number; + page_size?: number; + resource_type?: 'document' | 'faq'; +} + +/** 恢复资源请求参数 */ +export interface RestoreTrashParams { + id: number; +} + +/** 彻底删除请求参数 */ +export interface DeleteTrashParams { + id: number; +} + +/** 资源类型选项 */ +export const resourceTypeOptions = [ + { label: '文档', value: 'document' }, + { label: '常见问题', value: 'faq' }, +]; + +/** 获取资源类型文本 */ +export const getResourceTypeText = (type: string): string => { + const typeMap: Record = { + document: '文档', + faq: '常见问题', + }; + return typeMap[type] || type; +}; + +/** 获取资源类型颜色 */ +export const getResourceTypeColor = (type: string): string => { + const colorMap: Record = { + document: 'blue', + faq: 'green', + }; + return colorMap[type] || 'gray'; +}; + +/** 获取回收站列表 */ +export const fetchTrashList = (params?: FetchTrashListParams) => { + return request.get>>("/Kb/v1/trash/list", { params }); +}; + +/** 恢复资源 */ +export const restoreTrash = (data: RestoreTrashParams) => { + return request.post>("/Kb/v1/trash/restore", data); +}; + +/** 彻底删除 */ +export const deleteTrash = (data: DeleteTrashParams) => { + return request.post>("/Kb/v1/trash/delete", data); +}; diff --git a/src/api/ops/asset.ts b/src/api/ops/asset.ts new file mode 100644 index 0000000..1f37b68 --- /dev/null +++ b/src/api/ops/asset.ts @@ -0,0 +1,139 @@ +import { request } from "@/api/request"; + +/** 资产状态枚举 */ +export enum AssetStatus { + IN_USE = 'in_use', // 在用 + IDLE = 'idle', // 闲置 + MAINTAIN = 'maintain', // 维修中 + SCRAP = 'scrap', // 待报废 + DISPOSED = 'disposed', // 已报废 +} + +/** 资产状态选项 */ +export const assetStatusOptions = [ + { label: '在用', value: AssetStatus.IN_USE }, + { label: '闲置', value: AssetStatus.IDLE }, + { label: '维修中', value: AssetStatus.MAINTAIN }, + { label: '待报废', value: AssetStatus.SCRAP }, + { label: '已报废', value: AssetStatus.DISPOSED }, +]; + +/** 获取资产状态文本 */ +export const getAssetStatusText = (status: string) => { + const item = assetStatusOptions.find(opt => opt.value === status); + return item?.label || status; +}; + +/** 获取资产状态颜色 */ +export const getAssetStatusColor = (status: string) => { + const colorMap: Record = { + [AssetStatus.IN_USE]: 'green', + [AssetStatus.IDLE]: 'blue', + [AssetStatus.MAINTAIN]: 'orange', + [AssetStatus.SCRAP]: 'red', + [AssetStatus.DISPOSED]: 'gray', + }; + return colorMap[status] || 'gray'; +}; + +/** 资产列表查询参数 */ +export interface AssetListParams { + page?: number; + page_size?: number; + keyword?: string; + status?: string; + category_id?: number; + supplier_id?: number; + datacenter_id?: number; + department?: string; + sort?: string; + order?: string; +} + +/** 资产表单数据 */ +export interface AssetForm { + id?: number; + asset_name: string; + asset_code: string; + category_id?: number; + model?: string; + manufacturer?: string; + serial_number?: string; + purchase_date?: string; + original_value?: number; + supplier_id?: number; + warranty_period?: string; + warranty_expiry?: string; + department?: string; + user?: string; + status?: string; + location?: string; + datacenter_id?: number; + floor_id?: number; + rack_id?: number; + unit_start?: number; + unit_end?: number; + qr_code?: string; + rfid_tag?: string; + asset_tag?: string; + specifications?: string; + description?: string; + remarks?: string; +} + +/** 获取资产列表(分页) */ +export const fetchAssetList = (data?: AssetListParams) => { + return request.post("/Assets/v1/asset/list", data || {}); +}; + +/** 获取资产详情 */ +export const fetchAssetDetail = (id: number) => { + return request.get(`/Assets/v1/asset/detail/${id}`); +}; + +/** 创建资产 */ +export const createAsset = (data: AssetForm) => { + return request.post("/Assets/v1/asset/create", data); +}; + +/** 更新资产 */ +export const updateAsset = (data: AssetForm) => { + return request.put("/Assets/v1/asset/update", data); +}; + +/** 删除资产 */ +export const deleteAsset = (id: number) => { + return request.delete(`/Assets/v1/asset/delete/${id}`); +}; + +/** 导出资产 */ +export const exportAssets = (keyword?: string) => { + const params: any = {}; + if (keyword) params.keyword = keyword; + return request.get("/Assets/v1/asset/export", { params }); +}; + +/** 获取资产分类列表(下拉) */ +export const fetchCategoryOptions = () => { + return request.get("/Assets/v1/category/all"); +}; + +/** 获取供应商列表(下拉) */ +export const fetchSupplierOptions = () => { + return request.get("/Assets/v1/supplier/all"); +}; + +/** 获取数据中心列表(下拉) */ +export const fetchDatacenterOptions = () => { + return request.get("/Assets/v1/datacenter/list"); +}; + +/** 根据数据中心获取楼层列表 */ +export const fetchFloorOptions = (datacenterId: number) => { + return request.get(`/Assets/v1/datacenter/${datacenterId}`); +}; + +/** 获取机柜列表(下拉) */ +export const fetchRackOptions = (params?: { datacenter_id?: number; floor_id?: number }) => { + return request.post("/Assets/v1/rack/list", params || {}); +}; \ No newline at end of file diff --git a/src/api/ops/assetCategory.ts b/src/api/ops/assetCategory.ts new file mode 100644 index 0000000..a051cf0 --- /dev/null +++ b/src/api/ops/assetCategory.ts @@ -0,0 +1,46 @@ +import { request } from "@/api/request"; + +/** 获取资产分类列表(分页) */ +export const fetchCategoryList = (data?: { + page?: number; + page_size?: number; + keyword?: string; + parent_id?: number; +}) => { + return request.post("/Assets/v1/category/list", data || {}); +}; + +/** 获取资产分类详情 */ +export const fetchCategoryDetail = (id: number) => { + return request.get(`/Assets/v1/category/detail/${id}`); +}; + +/** 创建资产分类 */ +export const createCategory = (data: any) => { + return request.post("/Assets/v1/category/create", data); +}; + +/** 更新资产分类 */ +export const updateCategory = (data: any) => { + return request.put("/Assets/v1/category/update", data); +}; + +/** 删除资产分类 */ +export const deleteCategory = (id: number) => { + return request.delete(`/Assets/v1/category/delete/${id}`); +}; + +/** 获取所有资产分类(用于下拉选择) */ +export const fetchAllCategories = () => { + return request.get("/Assets/v1/category/all"); +}; + +/** 获取资产分类树形结构 */ +export const fetchCategoryTree = () => { + return request.get("/Assets/v1/category/tree"); +}; + +/** 获取指定分类的子分类列表 */ +export const fetchCategoryChildren = (id: number) => { + return request.get(`/Assets/v1/category/children/${id}`); +}; diff --git a/src/api/ops/supplier.ts b/src/api/ops/supplier.ts new file mode 100644 index 0000000..9f05e8a --- /dev/null +++ b/src/api/ops/supplier.ts @@ -0,0 +1,40 @@ +import { request } from "@/api/request"; + +/** 获取供应商列表(分页) */ +export const fetchSupplierList = (data?: { + page?: number; + page_size?: number; + keyword?: string; + status?: string; + enabled?: boolean; +}) => { + return request.post("/Assets/v1/supplier/list", data || {}); +}; + +/** 获取供应商详情 */ +export const fetchSupplierDetail = (id: number) => { + return request.get(`/Assets/v1/supplier/detail/${id}`); +}; + +/** 创建供应商 */ +export const createSupplier = (data: any) => { + return request.post("/Assets/v1/supplier/create", data); +}; + +/** 更新供应商 */ +export const updateSupplier = (data: any) => { + return request.put("/Assets/v1/supplier/update", data); +}; + +/** 删除供应商 */ +export const deleteSupplier = (id: number) => { + return request.delete(`/Assets/v1/supplier/delete/${id}`); +}; + +/** 获取所有供应商(用于下拉选择) */ +export const fetchAllSuppliers = (keyword?: string, status?: string) => { + const params: any = {}; + if (keyword) params.keyword = keyword; + if (status) params.status = status; + return request.get("/Assets/v1/supplier/all", { params }); +}; \ No newline at end of file diff --git a/src/router/routes/modules/ops.ts b/src/router/routes/modules/ops.ts index 0cc058c..e5090b7 100644 --- a/src/router/routes/modules/ops.ts +++ b/src/router/routes/modules/ops.ts @@ -83,6 +83,46 @@ const OPS: AppRouteRecordRaw = { roles: ['*'], }, }, + { + path: 'assets/device', + name: 'AssetsDevice', + component: () => import('@/views/ops/pages/assets/device/index.vue'), + meta: { + locale: '设备管理', + requiresAuth: true, + roles: ['*'], + }, + }, + { + path: 'assets/supplier', + name: 'AssetsSupplier', + component: () => import('@/views/ops/pages/assets/supplier/index.vue'), + meta: { + locale: '供应商管理', + requiresAuth: true, + roles: ['*'], + }, + }, + { + path: 'assets/classify', + name: 'AssetsClassify', + component: () => import('@/views/ops/pages/assets/classify/index.vue'), + meta: { + locale: '资产分类', + requiresAuth: true, + roles: ['*'], + }, + }, + { + path: 'kb/items', + name: 'KbItems', + component: () => import('@/views/ops/pages/kb/items/index.vue'), + meta: { + locale: '知识库文档', + requiresAuth: true, + roles: ['*'], + }, + }, ], } diff --git a/src/views/ops/pages/assets/classify/components/CategoryDetailDialog.vue b/src/views/ops/pages/assets/classify/components/CategoryDetailDialog.vue new file mode 100644 index 0000000..b9c4ba7 --- /dev/null +++ b/src/views/ops/pages/assets/classify/components/CategoryDetailDialog.vue @@ -0,0 +1,165 @@ + + + + + + + diff --git a/src/views/ops/pages/assets/classify/components/CategoryFormDialog.vue b/src/views/ops/pages/assets/classify/components/CategoryFormDialog.vue new file mode 100644 index 0000000..b716e74 --- /dev/null +++ b/src/views/ops/pages/assets/classify/components/CategoryFormDialog.vue @@ -0,0 +1,385 @@ + + + + + + + diff --git a/src/views/ops/pages/assets/classify/index.vue b/src/views/ops/pages/assets/classify/index.vue new file mode 100644 index 0000000..b99c778 --- /dev/null +++ b/src/views/ops/pages/assets/classify/index.vue @@ -0,0 +1,387 @@ + + + + + + + diff --git a/src/views/ops/pages/assets/device/components/DeviceDetailDialog.vue b/src/views/ops/pages/assets/device/components/DeviceDetailDialog.vue new file mode 100644 index 0000000..f1c37d2 --- /dev/null +++ b/src/views/ops/pages/assets/device/components/DeviceDetailDialog.vue @@ -0,0 +1,233 @@ + + + + + + + \ No newline at end of file diff --git a/src/views/ops/pages/assets/device/components/DeviceFormDialog.vue b/src/views/ops/pages/assets/device/components/DeviceFormDialog.vue new file mode 100644 index 0000000..e48bb2e --- /dev/null +++ b/src/views/ops/pages/assets/device/components/DeviceFormDialog.vue @@ -0,0 +1,687 @@ + + + + + + + \ No newline at end of file diff --git a/src/views/ops/pages/assets/device/index.vue b/src/views/ops/pages/assets/device/index.vue new file mode 100644 index 0000000..e345a1e --- /dev/null +++ b/src/views/ops/pages/assets/device/index.vue @@ -0,0 +1,400 @@ + + + + + + + \ No newline at end of file diff --git a/src/views/ops/pages/assets/supplier/components/SupplierDetailDialog.vue b/src/views/ops/pages/assets/supplier/components/SupplierDetailDialog.vue new file mode 100644 index 0000000..44cf614 --- /dev/null +++ b/src/views/ops/pages/assets/supplier/components/SupplierDetailDialog.vue @@ -0,0 +1,275 @@ + + + + + + + \ No newline at end of file diff --git a/src/views/ops/pages/assets/supplier/components/SupplierFormDialog.vue b/src/views/ops/pages/assets/supplier/components/SupplierFormDialog.vue new file mode 100644 index 0000000..b071012 --- /dev/null +++ b/src/views/ops/pages/assets/supplier/components/SupplierFormDialog.vue @@ -0,0 +1,464 @@ + + + + + + + \ No newline at end of file diff --git a/src/views/ops/pages/assets/supplier/index.vue b/src/views/ops/pages/assets/supplier/index.vue new file mode 100644 index 0000000..36c6643 --- /dev/null +++ b/src/views/ops/pages/assets/supplier/index.vue @@ -0,0 +1,384 @@ + + + + + + + \ No newline at end of file diff --git a/src/views/ops/pages/dc/pc/components/QuickConfigDialog.vue b/src/views/ops/pages/dc/pc/components/QuickConfigDialog.vue new file mode 100644 index 0000000..6e26b54 --- /dev/null +++ b/src/views/ops/pages/dc/pc/components/QuickConfigDialog.vue @@ -0,0 +1,90 @@ + + + diff --git a/src/views/ops/pages/dc/pc/config/columns.ts b/src/views/ops/pages/dc/pc/config/columns.ts index 16e567c..85dbc6b 100644 --- a/src/views/ops/pages/dc/pc/config/columns.ts +++ b/src/views/ops/pages/dc/pc/config/columns.ts @@ -74,7 +74,7 @@ export const columns = [ { dataIndex: 'actions', title: '操作', - width: 100, + width: 180, fixed: 'right' as const, slotName: 'actions', }, diff --git a/src/views/ops/pages/dc/pc/index.vue b/src/views/ops/pages/dc/pc/index.vue index 517febf..b08a17c 100644 --- a/src/views/ops/pages/dc/pc/index.vue +++ b/src/views/ops/pages/dc/pc/index.vue @@ -99,46 +99,59 @@ - + @@ -149,6 +162,13 @@ @success="handleFormSuccess" /> + + + @@ -163,7 +183,8 @@ import { IconDesktop, IconDelete, IconRefresh, - IconEye + IconEye, + IconSettings } from '@arco-design/web-vue/es/icon' import type { FormItem } from '@/components/search-form/types' import SearchTable from '@/components/search-table/index.vue' @@ -174,6 +195,7 @@ import { deletePC, } from '@/api/ops/pc' import ServerFormDialog from './components/ServerFormDialog.vue' +import QuickConfigDialog from './components/QuickConfigDialog.vue' import ServerDetail from './components/ServerDetail.vue' const router = useRouter() @@ -313,6 +335,7 @@ const formModel = ref({ }) const formDialogVisible = ref(false) +const quickConfigVisible = ref(false) const currentRecord = ref(null) const pagination = reactive({ @@ -440,6 +463,12 @@ const handleAdd = () => { formDialogVisible.value = true } +// 快捷配置 +const handleQuickConfig = (record: any) => { + currentRecord.value = record + quickConfigVisible.value = true +} + // 编辑PC const handleEdit = (record: any) => { currentRecord.value = record diff --git a/src/views/ops/pages/dc/server/config/columns.ts b/src/views/ops/pages/dc/server/config/columns.ts index 3db83b3..e835509 100644 --- a/src/views/ops/pages/dc/server/config/columns.ts +++ b/src/views/ops/pages/dc/server/config/columns.ts @@ -85,7 +85,7 @@ export const columns = [ { dataIndex: 'actions', title: '操作', - width: 100, + width: 180, fixed: 'right' as const, slotName: 'actions', }, diff --git a/src/views/ops/pages/dc/server/index.vue b/src/views/ops/pages/dc/server/index.vue index 43c9ab2..4435c7c 100644 --- a/src/views/ops/pages/dc/server/index.vue +++ b/src/views/ops/pages/dc/server/index.vue @@ -108,44 +108,57 @@ @@ -155,6 +168,13 @@ :record="currentRecord" @success="handleFormSuccess" /> + + + @@ -169,12 +189,14 @@ import { IconDesktop, IconDelete, IconRefresh, - IconEye + IconEye, + IconSettings } from '@arco-design/web-vue/es/icon' import type { FormItem } from '@/components/search-form/types' import SearchTable from '@/components/search-table/index.vue' import { searchFormConfig } from './config/search-form' import ServerFormDialog from '../pc/components/ServerFormDialog.vue' +import QuickConfigDialog from '../pc/components/QuickConfigDialog.vue' import { columns as columnsConfig } from './config/columns' import { fetchServerList, @@ -391,6 +413,7 @@ const mockServerData = [ const loading = ref(false) const tableData = ref([]) const formDialogVisible = ref(false) +const quickConfigVisible = ref(false) const currentRecord = ref(null) const formModel = ref({ keyword: '', @@ -524,6 +547,12 @@ const handleAdd = () => { formDialogVisible.value = true } +// 快捷配置 +const handleQuickConfig = (record: any) => { + currentRecord.value = record + quickConfigVisible.value = true +} + // 编辑服务器 const handleEdit = (record: any) => { currentRecord.value = record diff --git a/src/views/ops/pages/kb/items/components/index.ts b/src/views/ops/pages/kb/items/components/index.ts new file mode 100644 index 0000000..430a5ee --- /dev/null +++ b/src/views/ops/pages/kb/items/components/index.ts @@ -0,0 +1,2 @@ +export { default as DocumentDetailDrawer } from './DocumentDetailDrawer.vue' +export { default as DocumentFormModal } from './DocumentFormModal.vue' \ No newline at end of file diff --git a/src/views/ops/pages/kb/items/config/columns.ts b/src/views/ops/pages/kb/items/config/columns.ts new file mode 100644 index 0000000..d940692 --- /dev/null +++ b/src/views/ops/pages/kb/items/config/columns.ts @@ -0,0 +1,92 @@ +/** + * 表格列配置 - 知识库文档 + */ +import type { TableColumnData } from '@arco-design/web-vue/es/table/interface' +import { getDocumentStatusText, getDocumentStatusColor, getDocumentTypeText } from './options' + +export const getColumns = (): TableColumnData[] => [ + { + title: '序号', + dataIndex: 'index', + slotName: 'index', + width: 60, + align: 'center', + }, + { + title: '文档编号', + dataIndex: 'doc_no', + width: 150, + ellipsis: true, + tooltip: true, + }, + { + title: '文档标题', + dataIndex: 'title', + width: 200, + ellipsis: true, + tooltip: true, + }, + { + title: '文档类型', + dataIndex: 'type', + slotName: 'type', + width: 120, + align: 'center', + }, + { + title: '分类', + dataIndex: 'category_name', + width: 120, + ellipsis: true, + tooltip: true, + }, + { + title: '作者', + dataIndex: 'author_name', + width: 100, + ellipsis: true, + tooltip: true, + }, + { + title: '审核人', + dataIndex: 'reviewer_name', + width: 100, + ellipsis: true, + tooltip: true, + }, + { + title: '发布时间', + dataIndex: 'published_at', + slotName: 'published_at', + width: 160, + align: 'center', + }, + { + title: '版本号', + dataIndex: 'version', + width: 80, + align: 'center', + }, + { + title: '浏览次数', + dataIndex: 'view_count', + width: 90, + align: 'center', + }, + { + title: '文档状态', + dataIndex: 'status', + slotName: 'status', + width: 110, + align: 'center', + fixed: 'right', + }, + { + title: '操作', + dataIndex: 'operation', + slotName: 'operation', + width: 200, + align: 'center', + fixed: 'right', + }, +] \ No newline at end of file diff --git a/src/views/ops/pages/kb/items/config/filters.ts b/src/views/ops/pages/kb/items/config/filters.ts new file mode 100644 index 0000000..82ef5df --- /dev/null +++ b/src/views/ops/pages/kb/items/config/filters.ts @@ -0,0 +1,31 @@ +/** + * 筛选项配置 - 知识库文档 + */ +import type { FormItem } from '@/components/search-form/types' +import { documentTypeOptions, documentStatusOptions } from './options' + +export const getFilters = (): FormItem[] => [ + { + label: '关键词', + field: 'keyword', + type: 'input', + placeholder: '搜索文档标题、描述或关键字', + span: 6, + }, + { + label: '文档类型', + field: 'type', + type: 'select', + placeholder: '请选择文档类型', + options: documentTypeOptions, + span: 4, + }, + { + label: '文档状态', + field: 'status', + type: 'select', + placeholder: '请选择文档状态', + options: documentStatusOptions, + span: 4, + }, +] \ No newline at end of file diff --git a/src/views/ops/pages/kb/items/config/options.ts b/src/views/ops/pages/kb/items/config/options.ts new file mode 100644 index 0000000..4e3ea39 --- /dev/null +++ b/src/views/ops/pages/kb/items/config/options.ts @@ -0,0 +1,62 @@ +/** + * 选项配置 - 知识库文档 + */ + +// 文档类型选项 +export const documentTypeOptions = [ + { label: '通用文档', value: 'common' }, + { label: '操作指南', value: 'guide' }, + { label: '解决方案', value: 'solution' }, + { label: '故障排查', value: 'troubleshoot' }, + { label: '流程规范', value: 'process' }, + { label: '技术文档', value: 'technical' }, +]; + +// 文档状态选项 +export const documentStatusOptions = [ + { label: '草稿', value: 'draft' }, + { label: '已发布', value: 'published' }, + { label: '已审核', value: 'reviewed' }, + { label: '未通过审核', value: 'rejected' }, +]; + +// 列表类型选项 +export const listTypeOptions = [ + { label: '我的', value: 'mine' }, + { label: '全部', value: 'all' }, +]; + +// 获取文档状态文本 +export const getDocumentStatusText = (status: string): string => { + const statusMap: Record = { + draft: '草稿', + published: '已发布', + reviewed: '已审核', + rejected: '未通过审核', + }; + return statusMap[status] || status; +}; + +// 获取文档状态颜色 +export const getDocumentStatusColor = (status: string): string => { + const colorMap: Record = { + draft: 'gray', + published: 'blue', + reviewed: 'green', + rejected: 'red', + }; + return colorMap[status] || 'gray'; +}; + +// 获取文档类型文本 +export const getDocumentTypeText = (type: string): string => { + const typeMap: Record = { + common: '通用文档', + guide: '操作指南', + solution: '解决方案', + troubleshoot: '故障排查', + process: '流程规范', + technical: '技术文档', + }; + return typeMap[type] || type; +}; \ No newline at end of file diff --git a/src/views/ops/pages/kb/items/index.vue b/src/views/ops/pages/kb/items/index.vue new file mode 100644 index 0000000..b33646d --- /dev/null +++ b/src/views/ops/pages/kb/items/index.vue @@ -0,0 +1,1088 @@ + + + + + + + \ No newline at end of file diff --git a/src/views/ops/pages/kb/recycle/index.vue b/src/views/ops/pages/kb/recycle/index.vue new file mode 100644 index 0000000..8d872fb --- /dev/null +++ b/src/views/ops/pages/kb/recycle/index.vue @@ -0,0 +1,350 @@ + + + + + diff --git a/src/views/ops/pages/kb/review/index.vue b/src/views/ops/pages/kb/review/index.vue new file mode 100644 index 0000000..e69de29 diff --git a/src/views/ops/pages/kb/tags/components/CategoryFormDialog.vue b/src/views/ops/pages/kb/tags/components/CategoryFormDialog.vue new file mode 100644 index 0000000..903c206 --- /dev/null +++ b/src/views/ops/pages/kb/tags/components/CategoryFormDialog.vue @@ -0,0 +1,324 @@ + + + + + + + \ No newline at end of file diff --git a/src/views/ops/pages/kb/tags/index.vue b/src/views/ops/pages/kb/tags/index.vue new file mode 100644 index 0000000..0dd685a --- /dev/null +++ b/src/views/ops/pages/kb/tags/index.vue @@ -0,0 +1,283 @@ + + + + + + + \ No newline at end of file diff --git a/src/views/ops/pages/report/history/components/MetricsSummaryPanel.vue b/src/views/ops/pages/report/history/components/MetricsSummaryPanel.vue index 9ee33e2..f6837ee 100644 --- a/src/views/ops/pages/report/history/components/MetricsSummaryPanel.vue +++ b/src/views/ops/pages/report/history/components/MetricsSummaryPanel.vue @@ -1,113 +1,62 @@