From 1e5302ee641096e0f9708dfa429bba9ebd397803 Mon Sep 17 00:00:00 2001 From: fhysy <1149505133@qq.com> Date: Wed, 13 Aug 2025 12:01:08 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E4=BA=A7=E5=93=81?= =?UTF-8?q?=E8=AF=A6=E6=83=85=E9=A1=B5=E9=9D=A2,=E5=AE=8C=E6=88=90?= =?UTF-8?q?=E8=AE=BE=E5=A4=87=E9=85=8D=E7=BD=AE=E4=BF=A1=E6=81=AF=E9=A1=B5?= =?UTF-8?q?=E5=92=8C=E5=8F=82=E6=95=B0=E9=85=8D=E7=BD=AE=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加产品详情页面路由和访问权限 - 实现产品基本信息展示和编辑功能 - 增加产品参数编辑功能 - 实现产品状态变更和配置应用 - 添加设备数量统计和跳转功能 --- apps/web-antd/src/api/device/product/index.ts | 30 ++ .../src/api/device/product/model.d.ts | 10 + apps/web-antd/src/router/access.ts | 6 + apps/web-antd/src/store/index.ts | 1 + apps/web-antd/src/store/product.ts | 92 ++++++ .../web-antd/src/views/device/product/data.ts | 10 + .../product/detail/components/BasicInfo.vue | 269 ++++++++++++++++ .../detail/components/ProductParamDrawer.vue | 297 ++++++++++++++++++ .../src/views/device/product/detail/index.vue | 219 +++++++++++++ .../src/views/device/product/index.vue | 19 ++ .../src/views/operations/network/index.vue | 34 +- .../src/views/operations/protocol/data.ts | 2 +- .../src/views/operations/protocol/index.vue | 10 +- 13 files changed, 970 insertions(+), 29 deletions(-) create mode 100644 apps/web-antd/src/store/product.ts create mode 100644 apps/web-antd/src/views/device/product/detail/components/BasicInfo.vue create mode 100644 apps/web-antd/src/views/device/product/detail/components/ProductParamDrawer.vue create mode 100644 apps/web-antd/src/views/device/product/detail/index.vue diff --git a/apps/web-antd/src/api/device/product/index.ts b/apps/web-antd/src/api/device/product/index.ts index 75515ab..4765ea8 100644 --- a/apps/web-antd/src/api/device/product/index.ts +++ b/apps/web-antd/src/api/device/product/index.ts @@ -52,6 +52,24 @@ export function productUpdate(data: ProductForm) { return requestClient.putWithMsg('/device/product', data); } +/** + * 更新设备产品(部分) + * @param data + * @returns void + */ +export function productUpdateById(id: ID, data: ProductForm) { + return requestClient.putWithMsg(`/device/product/${id}`, data); +} + +/** + * 更新设备产品状态 + * @param data + * @returns void + */ +export function productUpdateStatus(data: ProductForm) { + return requestClient.putWithMsg('/device/product/enable', data); +} + /** * 删除设备产品 * @param id id @@ -60,3 +78,15 @@ export function productUpdate(data: ProductForm) { export function productRemove(id: ID | IDS) { return requestClient.deleteWithMsg(`/device/product/${id}`); } + +/** + * 查询产品存储策略列表 + * @param params + * @returns 产品存储策略列表 + */ +export function getPoliciesList(params?: any) { + return requestClient.get>( + '/device/product/storage/policies', + { params }, + ); +} diff --git a/apps/web-antd/src/api/device/product/model.d.ts b/apps/web-antd/src/api/device/product/model.d.ts index 0cae991..e4a248b 100644 --- a/apps/web-antd/src/api/device/product/model.d.ts +++ b/apps/web-antd/src/api/device/product/model.d.ts @@ -65,6 +65,11 @@ export interface ProductVO { * 存储策略配置 */ storePolicyConf: string; + + /** + * 产品参数 + */ + productParam?: string; } export interface ProductForm extends BaseEntity { @@ -132,6 +137,11 @@ export interface ProductForm extends BaseEntity { * 存储策略配置 */ storePolicyConf?: string; + + /** + * 产品参数 + */ + productParam?: string; } export interface ProductQuery extends PageQuery { diff --git a/apps/web-antd/src/router/access.ts b/apps/web-antd/src/router/access.ts index aea6399..dab9a73 100644 --- a/apps/web-antd/src/router/access.ts +++ b/apps/web-antd/src/router/access.ts @@ -31,6 +31,12 @@ const routeMetaMapping: Record> = { activePath: '/system/role', requireHomeRedirect: true, }, + + '/device/product/detail/:id': { + activePath: '/device/product', + requireHomeRedirect: true, + }, + '/system/oss-config/index': { activePath: '/system/oss', requireHomeRedirect: true, diff --git a/apps/web-antd/src/store/index.ts b/apps/web-antd/src/store/index.ts index 7750334..f52e0db 100644 --- a/apps/web-antd/src/store/index.ts +++ b/apps/web-antd/src/store/index.ts @@ -1,2 +1,3 @@ export * from './auth'; export * from './notify'; +export * from './product'; diff --git a/apps/web-antd/src/store/product.ts b/apps/web-antd/src/store/product.ts new file mode 100644 index 0000000..aa2f409 --- /dev/null +++ b/apps/web-antd/src/store/product.ts @@ -0,0 +1,92 @@ +import type { ProductVO } from '#/api/device/product/model'; + +import { defineStore } from 'pinia'; + +import { productInfo } from '#/api/device/product'; + +export interface ProductDetailState { + current: Partial; + detail: Partial; + tabActiveKey: string; + deviceCount: number; +} + +export const useProductStore = defineStore('product', { + state: (): ProductDetailState => ({ + current: {}, + detail: {}, + tabActiveKey: 'BasicInfo', + deviceCount: 0, + }), + + getters: { + getCurrentProduct: (state) => state.current, + getDetailProduct: (state) => state.detail, + getTabActiveKey: (state) => state.tabActiveKey, + getDeviceCount: (state) => state.deviceCount, + }, + + actions: { + /** + * 设置当前产品信息 + */ + setCurrent(current: Partial) { + this.current = current; + this.detail = current; + }, + + /** + * 获取产品详情 + */ + async getDetail(id: number | string) { + try { + const resp = await productInfo(id); + if (resp) { + this.current = { + ...this.current, + ...resp, + }; + this.detail = resp; + } + } catch (error) { + console.error('获取产品详情失败:', error); + } + }, + + /** + * 刷新产品信息和设备数量 + */ + async refresh(id: number | string) { + await this.getDetail(id); + // TODO: 这里需要添加获取设备数量的 API 调用 + // const res = await getDeviceNumber({ productId: id }); + // if (res) { + // this.deviceCount = res; + // } + }, + + /** + * 设置选中的 tab + */ + setTabActiveKey(key: string) { + this.tabActiveKey = key; + }, + + /** + * 设置设备数量 + */ + setDeviceCount(count: number) { + this.deviceCount = count; + }, + + /** + * 重置状态 + */ + reset() { + this.current = {}; + this.detail = {}; + this.tabActiveKey = 'BasicInfo'; + this.deviceCount = 0; + }, + }, +}); diff --git a/apps/web-antd/src/views/device/product/data.ts b/apps/web-antd/src/views/device/product/data.ts index 271da7b..2794bcd 100644 --- a/apps/web-antd/src/views/device/product/data.ts +++ b/apps/web-antd/src/views/device/product/data.ts @@ -6,6 +6,11 @@ import { h } from 'vue'; import { deviceTypeOptions, enabledOptions } from '#/constants/dicts'; export const querySchema: FormSchemaGetter = () => [ + { + component: 'Input', + fieldName: 'productKey', + label: '产品编码', + }, { component: 'Input', fieldName: 'productName', @@ -53,9 +58,14 @@ export const columns: VxeGridProps['columns'] = [ title: '产品名称', field: 'productName', }, + { + title: '产品分类', + field: 'categoryName', + }, { title: '设备类型', field: 'deviceType', + slots: { default: 'deviceType' }, }, { title: '启用状态', diff --git a/apps/web-antd/src/views/device/product/detail/components/BasicInfo.vue b/apps/web-antd/src/views/device/product/detail/components/BasicInfo.vue new file mode 100644 index 0000000..c0d34c4 --- /dev/null +++ b/apps/web-antd/src/views/device/product/detail/components/BasicInfo.vue @@ -0,0 +1,269 @@ + + + + + diff --git a/apps/web-antd/src/views/device/product/detail/components/ProductParamDrawer.vue b/apps/web-antd/src/views/device/product/detail/components/ProductParamDrawer.vue new file mode 100644 index 0000000..a909769 --- /dev/null +++ b/apps/web-antd/src/views/device/product/detail/components/ProductParamDrawer.vue @@ -0,0 +1,297 @@ + + + + + diff --git a/apps/web-antd/src/views/device/product/detail/index.vue b/apps/web-antd/src/views/device/product/detail/index.vue new file mode 100644 index 0000000..54ec2e7 --- /dev/null +++ b/apps/web-antd/src/views/device/product/detail/index.vue @@ -0,0 +1,219 @@ + + + + + diff --git a/apps/web-antd/src/views/device/product/index.vue b/apps/web-antd/src/views/device/product/index.vue index ec3d1b5..0478286 100644 --- a/apps/web-antd/src/views/device/product/index.vue +++ b/apps/web-antd/src/views/device/product/index.vue @@ -4,6 +4,8 @@ import type { VbenFormProps } from '@vben/common-ui'; import type { VxeGridProps } from '#/adapter/vxe-table'; import type { ProductForm } from '#/api/device/product/model'; +import { useRouter } from 'vue-router'; + import { Page, useVbenDrawer } from '@vben/common-ui'; import { getVxePopupContainer } from '@vben/utils'; @@ -16,6 +18,8 @@ import { productRemove, } from '#/api/device/product'; import { productCategoryTreeList } from '#/api/device/productCategory'; +import { deviceTypeOptions } from '#/constants/dicts'; +import { useProductStore } from '#/store/product'; import { commonDownloadExcel } from '#/utils/file/download'; import { columns, querySchema } from './data'; @@ -40,6 +44,8 @@ const formOptions: VbenFormProps = { // ], // ], }; +const router = useRouter(); +const productStore = useProductStore(); const gridOptions: VxeGridProps = { checkboxConfig: { @@ -111,6 +117,11 @@ function handleAdd() { } async function handleView(row: Required) { + // 保存产品信息到 store + productStore.setCurrent(row); + // 设置默认选中的 tab + productStore.setTabActiveKey('BasicInfo'); + // 跳转到详情页 router.push(`/device/product/detail/${row.id}`); } @@ -179,6 +190,14 @@ function handleDownloadExcel() { +