From de7568b5256db4f39232a6b4a23307e8d41b5124 Mon Sep 17 00:00:00 2001 From: fhysy <1149505133@qq.com> Date: Fri, 8 Aug 2025 17:54:08 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E4=BA=A7=E5=93=81?= =?UTF-8?q?=E5=88=86=E7=B1=BB=E7=AE=A1=E7=90=86=E3=80=81=E4=BA=A7=E5=93=81?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加产品列表等接口 - 实现产品信息展示、编辑等功能 - 添加产品分类管理相关功能 --- .../public/images/device/device-card.png | Bin 0 -> 7357 bytes .../public/images/device/device-type-1.png | Bin 0 -> 1663 bytes .../public/images/device/device-type-2.png | Bin 0 -> 1751 bytes .../public/images/device/device-type-3.png | Bin 0 -> 1829 bytes apps/web-antd/src/api/device/product/index.ts | 61 +++++ .../src/api/device/product/model.d.ts | 204 ++++++++++++++++ .../src/api/device/productCategory/index.ts | 12 + apps/web-antd/src/constants/dicts/device.ts | 23 ++ apps/web-antd/src/constants/dicts/index.ts | 2 + .../dicts/operations.ts} | 7 +- apps/web-antd/src/router/access.ts | 1 - .../web-antd/src/views/device/product/data.ts | 158 +++++++++++++ .../src/views/device/product/index.vue | 220 ++++++++++++++++++ .../views/device/product/product-drawer.vue | 123 ++++++++++ 14 files changed, 806 insertions(+), 5 deletions(-) create mode 100644 apps/web-antd/public/images/device/device-card.png create mode 100644 apps/web-antd/public/images/device/device-type-1.png create mode 100644 apps/web-antd/public/images/device/device-type-2.png create mode 100644 apps/web-antd/public/images/device/device-type-3.png create mode 100644 apps/web-antd/src/api/device/product/index.ts create mode 100644 apps/web-antd/src/api/device/product/model.d.ts create mode 100644 apps/web-antd/src/constants/dicts/device.ts rename apps/web-antd/src/{views/operations/user.data.ts => constants/dicts/operations.ts} (88%) create mode 100644 apps/web-antd/src/views/device/product/data.ts create mode 100644 apps/web-antd/src/views/device/product/index.vue create mode 100644 apps/web-antd/src/views/device/product/product-drawer.vue diff --git a/apps/web-antd/public/images/device/device-card.png b/apps/web-antd/public/images/device/device-card.png new file mode 100644 index 0000000000000000000000000000000000000000..2eedfa20d56b65a31d9eef11e774f6ba55aebf28 GIT binary patch literal 7357 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 JPDHLkV1lh>2Lk{A literal 0 HcmV?d00001 diff --git a/apps/web-antd/public/images/device/device-type-2.png b/apps/web-antd/public/images/device/device-type-2.png new file mode 100644 index 0000000000000000000000000000000000000000..201579d159f7b014012bb1ad4206a41e85f11884 GIT binary patch literal 1751 zcmV;|1}OQ7P)>lXf00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yPi}-20(B;$+|i8ywFTk< zG81#R$H=!5sd20|##|ujI0aN^UK3P;;%J2lAQ!Am!58{AKtXN-ye zLJVrFmGeMEdIvBS6~#wC-B~-~cm-`d?-<4Jph6DHRT|R17Tq{PD{j z|G`E;2H)ncAeg(~0dGPKkEaD##kQr<&kB%LggCnJ?D}q9JUeO1a1DTPDL^YBdb_I| zU(M#+e$r;FYWVHrXTn3!rmZFD1mx*==I%qlo5TyT6dqYF#2fP1zd46LCKX8hq%AnI zW96E9<Tm!r{M7R zZgZepK%ouueK^bGgs$ME?}XvK7cgdk!_4rzkD-*ikDcpUwFM=9D+UnfHOOQD?KE^? zFjNT5k6Sz4fnvBmkZ)U&+pB=~GT=pY?hDVLmy|gNKytx0B)C()Yf@E%=HBS+=HV^cz z|1QVo&bk#T^Xdi9#st64YB*ab*pwmY@1*`xM!jha9ubc|fuKZ&cuYodp;c#Vfh+=b zWz`Xd2$iaXdfkCr07_ij{8MuX$I1%6n$R#-1=y4W*qnpDdPI9L8PwXA1|%_&1$5>K zlnB0I>rS7lpE@ z_{QqunTA}lKFym;)oxoLaYY(6oIof6B27tn&^oYk)3Eo;l|qs`sA&DgH5JI2xnwGi zIT@y#j6hc{NE8wvA2X-uimq|KU+2pZVHl!b4<@xorfWRtVZ1I#@<*{AL*C81U5I!Q z!+&t{!%AVnq)7JXghuKc?^@iOgHl@0cWc=w<^qQw&AAtOGxbJjdl^ zg;dDuFa&`S&ukdPS9XqaHb5CR*2gJyjt z8*3uYBV=q833=NfBpOqcZ2$!ZTmvIpdwh?6V{mVF$ZKZDjR6eY5qi+1_?Cd-fz1|n z7Mk8^E(a1ag!08%EKkoG7BN$55FZ8)pn)=4vGD+s!K{Dw_hjRd2Ac!VKAii*|IY}- zZh^UBo04hWtpDWQa&32_;bvgsn5*>~&ambf$c8e%GRTHnf_MPX6#6ho8gN9ew%nCl z^WiIUI>@<$L$Ld)mvPcgaIMozmg{XOGwHc-iWwP*}V7G|oW z90w!?W@ON}`1{&31JBMFboU12{)`N^T$s*J1|#PuVb9!+js2rjjaTovz5{YH^oeo= zMG2-V%cdyj2zn6JDOoG<@}AY7TU;=J$TjQK zpNO{QPR(0)$@CXWygwv(bhb)|vmrdzThe{b!nePigx6culV!Lha_*JXSTTs-4DTyU z`1>n&@$*0uq_X6z(e;3e1znu0*zN?b$3A9an7A~fep>+`=OS@LuX8Ri$UhIi)Olj* z^Va8@gO%Od(atnLBH!(;o)JqP0`6huGNP;z=s9&_c<8QZdAT+7|KPz31r6EVz5ziB}{05e}_6&J+=M_K`-0$CM^lLObewLrWFM3L8t2LG{G{b_jL)^*hZ-8_(~k&x^zM&7~>FSZMCRUlUa t>8E5>lKdHcp7s^QHM7A($3wVE`yZ;MIQ;Kn3ReIC002ovPDHLkV1j-|E#&|J literal 0 HcmV?d00001 diff --git a/apps/web-antd/public/images/device/device-type-3.png b/apps/web-antd/public/images/device/device-type-3.png new file mode 100644 index 0000000000000000000000000000000000000000..3561237e70b88989cb0079de46a2a1befb57fc15 GIT binary patch literal 1829 zcmV+=2io|FP)>lXf00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yP%hoiMphbX6EdD_V0Y_ zTl?(22~QEYd7o47<-v>AjpVsxB6Z#h50;O7|X0UIs?=A?#xSXPl+ z?EoDJ!~%rUxfd$L&ncxBs8C9okXNzSm@5(24Gjh+=+^mc`T8D#YO#wjOo zUsn#V`+nsPky~ig&H^dr41-l%tIDnSFLmB+<^G=uQuTqshyjI&oEc_+4K0KP(%Ktg z>F5TS{OymTb7%)-^cp8zH}|>$A13mq8UZ}t@5H}&BDffF)##HVu1!n^;|*>#(29Td zfHW}TY@?1BzN{`D^5_Z?;#>bQkh=58jQ(?$QwIg2dVu|mSRda!>%5VO@=rA3CF~P^ zz~eJ%zP1~vnW3v7-+CwaB?6rg6)Ms=*~p0JhH3CjKmFWM^aff8W@HM!`OP2x#XsA7 zZQIZaNdNAw=tuO!U$L95c~@RgrK1GW%U-O4=L(svwPKNvYM*v+80jy3+^kMtX(E|2A#jt^zoCo_&>o#zPo$ z>i3spzi{f>iW17IF+i%C|3a?FSG5Mh9ziR#6&0UxXO8h`8DmW_%>omE~{0q_l;Ks)x zd{p@=zHr7tJS>Q!Od{4CXf4B-niaPeYXDMV@TwqK+OJPD5Tw-kjN5PGlE-5| z3Qv02G<8JwrmIk5Bn4n`qXwV^z(uVzr6O-Oo5-7j%q{ajd|!=y{mqd43L%v)V@+f( z`!2jJqbE)v>cGx;xNPGzD=uk57^dxR*H$o1UzgFTGwH@Yx=X zXjCI#0wPihR`k3)@v1;XT*iq+&DgC*Q;-Gv+Ejcnc=_mjfKoAspc2M#uf`KmX6gZO zq{CLwwhtgcy)lNPciPgXsSsei*;q}P?=5oYdQoBcqzgB62!TBI%v=d^nO8=JP#rD# zpax;n@XTTHh~BD_+Q*jg!*zo1<2>3`WVjE5#WFIf$B0XD;I#N75!cn~v2k3?+bxPH z-dha?X|i4*gd7XVHccIcayyDB($55cfmfQ1pOT6hI0D?3>ajkt)zjIbvApV6RjLo0 zhO{WOF6ry(uoWW;sZE85bju)~L!`6{J5Zq|`U+<5`FQV71$2aK>Db62Wy@KK5xNu3 z4uF*$A^imC3^N8gQT2)q+WbHTo=(IklpEG2&_oM=Tcf~i~Un%q7chf0Zk!v;)@y;>v z!F^e>(e|3v?pusILc|3T?GvJ);lAbki~5S^@Q>|xYu2uWle+OS4{oP{KFs+1PQhTI zQGZ3;DR$~JFj=4I!--2B=^Fg5*aDIyWyFB9jeuV1r@`Y1x*}#Avr9n>vgL!V6zln52vFZBj`|oS6XI~Z9o@@qmZdkvR2=mp+JHd@rUp1UL6^r@7-KSke+GOPJ@OT0WfoKpgArI+}IDGC6Ih$DN&gLebU|9j$6&u5+v9PBip3KV_Q?nml@wm^(hF$(-XB3djfzPV+@ zR-(Q0kxfI_He@>Kso)F~cd?=6g91Di$W9>V0%=8ZX!OTck03s`7#*MT@Rad?2##oO TVX3|?00000NkvXXu0mjfVDV!8 literal 0 HcmV?d00001 diff --git a/apps/web-antd/src/api/device/product/index.ts b/apps/web-antd/src/api/device/product/index.ts new file mode 100644 index 0000000..542cbee --- /dev/null +++ b/apps/web-antd/src/api/device/product/index.ts @@ -0,0 +1,61 @@ +import type { ProductVO, ProductForm, ProductQuery } from './model'; + +import type { ID, IDS } from '#/api/common'; +import type { PageResult } from '#/api/common'; + +import { commonExport } from '#/api/helper'; +import { requestClient } from '#/api/request'; + +/** +* 查询设备产品列表 +* @param params +* @returns 设备产品列表 +*/ +export function productList(params?: ProductQuery) { + return requestClient.get>('/device/product/list', { params }); +} + +/** + * 导出设备产品列表 + * @param params + * @returns 设备产品列表 + */ +export function productExport(params?: ProductQuery) { + return commonExport('/device/product/export', params ?? {}); +} + +/** + * 查询设备产品详情 + * @param id id + * @returns 设备产品详情 + */ +export function productInfo(id: ID) { + return requestClient.get(`/device/product/${id}`); +} + +/** + * 新增设备产品 + * @param data + * @returns void + */ +export function productAdd(data: ProductForm) { + return requestClient.postWithMsg('/device/product', data); +} + +/** + * 更新设备产品 + * @param data + * @returns void + */ +export function productUpdate(data: ProductForm) { + return requestClient.putWithMsg('/device/product', data); +} + +/** + * 删除设备产品 + * @param id id + * @returns void + */ +export function productRemove(id: ID | IDS) { + return requestClient.deleteWithMsg(`/device/product/${id}`); +} diff --git a/apps/web-antd/src/api/device/product/model.d.ts b/apps/web-antd/src/api/device/product/model.d.ts new file mode 100644 index 0000000..6b27107 --- /dev/null +++ b/apps/web-antd/src/api/device/product/model.d.ts @@ -0,0 +1,204 @@ +import type { PageQuery, BaseEntity } from '#/api/common'; + +export interface ProductVO { + /** + * 编号 + */ + id: string | number; + + /** + * 产品名称 + */ + productName: string; + + /** + * 产品图片 + */ + imgId: string | number; + + /** + * 描述 + */ + description: string; + + /** + * 分类id + */ + categoryId: string | number; + + /** + * 协议id + */ + protocolId: string | number; + + /** + * 物模型 + */ + metadata: string; + + /** + * 设备类型 + */ + deviceType: string; + + /** + * 协议配置 + */ + protocolConf: string; + + /** + * 启用状态 0 禁用 + */ + enabled: string; + + /** + * 接入方式 + */ + provider: string | number; + + /** + * 存储策略 + */ + storePolicy: string; + + /** + * 存储策略配置 + */ + storePolicyConf: string; + +} + +export interface ProductForm extends BaseEntity { + /** + * 编号 + */ + id?: string | number; + + /** + * 产品名称 + */ + productName?: string; + + /** + * 产品图片 + */ + imgId?: string | number; + + /** + * 描述 + */ + description?: string; + + /** + * 分类id + */ + categoryId?: string | number; + + /** + * 协议id + */ + protocolId?: string | number; + + /** + * 物模型 + */ + metadata?: string; + + /** + * 设备类型 + */ + deviceType?: string; + + /** + * 协议配置 + */ + protocolConf?: string; + + /** + * 启用状态 0 禁用 + */ + enabled?: string; + + /** + * 接入方式 + */ + provider?: string | number; + + /** + * 存储策略 + */ + storePolicy?: string; + + /** + * 存储策略配置 + */ + storePolicyConf?: string; + +} + +export interface ProductQuery extends PageQuery { + /** + * 产品名称 + */ + productName?: string; + + /** + * 产品图片 + */ + imgId?: string | number; + + /** + * 描述 + */ + description?: string; + + /** + * 分类id + */ + categoryId?: string | number; + + /** + * 协议id + */ + protocolId?: string | number; + + /** + * 物模型 + */ + metadata?: string; + + /** + * 设备类型 + */ + deviceType?: string; + + /** + * 协议配置 + */ + protocolConf?: string; + + /** + * 启用状态 0 禁用 + */ + enabled?: string; + + /** + * 接入方式 + */ + provider?: string | number; + + /** + * 存储策略 + */ + storePolicy?: string; + + /** + * 存储策略配置 + */ + storePolicyConf?: string; + + /** + * 日期范围参数 + */ + params?: any; +} diff --git a/apps/web-antd/src/api/device/productCategory/index.ts b/apps/web-antd/src/api/device/productCategory/index.ts index 11e1319..b02c432 100644 --- a/apps/web-antd/src/api/device/productCategory/index.ts +++ b/apps/web-antd/src/api/device/productCategory/index.ts @@ -20,6 +20,18 @@ export function productCategoryList(params?: ProductCategoryQuery) { ); } +/** + * 查询产品分类列表 + * @param params + * @returns 产品分类列表 + */ +export function productCategoryTreeList(params?: ProductCategoryQuery) { + return requestClient.get( + `/device/productCategory/treeList`, + { params }, + ); +} + /** * 查询产品分类详情 * @param id id diff --git a/apps/web-antd/src/constants/dicts/device.ts b/apps/web-antd/src/constants/dicts/device.ts new file mode 100644 index 0000000..07cf9dd --- /dev/null +++ b/apps/web-antd/src/constants/dicts/device.ts @@ -0,0 +1,23 @@ +/* 运维字典 */ + +// 网络类型 +export const deviceTypeOptions = [ + { + label: '直连设备', + value: 'device', + iconUrl: './device/device-type-1.png', + tooltip: '直连物联网平台的设备', + }, + { + label: '网关子设备', + value: 'childrenDevice', + iconUrl: './device/device-type-2.png', + tooltip: '作为网关的子设备,由网关代理连接到物联网平台', + }, + { + label: '网关设备', + value: 'gateway', + iconUrl: './device/device-type-3.png', + tooltip: '能挂载子设备与平台进行通信的设备', + }, +]; diff --git a/apps/web-antd/src/constants/dicts/index.ts b/apps/web-antd/src/constants/dicts/index.ts index 4a20a4d..095224f 100644 --- a/apps/web-antd/src/constants/dicts/index.ts +++ b/apps/web-antd/src/constants/dicts/index.ts @@ -1,4 +1,6 @@ /* 本地字典 */ + +export * from './device'; export * from './operations'; // 启用状态 diff --git a/apps/web-antd/src/views/operations/user.data.ts b/apps/web-antd/src/constants/dicts/operations.ts similarity index 88% rename from apps/web-antd/src/views/operations/user.data.ts rename to apps/web-antd/src/constants/dicts/operations.ts index 5eb3d62..98f5b94 100644 --- a/apps/web-antd/src/views/operations/user.data.ts +++ b/apps/web-antd/src/constants/dicts/operations.ts @@ -1,3 +1,6 @@ +/* 运维字典 */ + +// 网络类型 export const networkTypeOptions = [ { label: 'MQTT客户端', @@ -16,7 +19,3 @@ export const networkTypeOptions = [ 'HTTP服务是一个简单的请求-响应的基于TCP的无状态协议。设备通过HTTP服务与平台进行灵活的短链接通信,仅支持设备和平台之间单对单的请求-响应模式', }, ]; -export const enabledOptions = [ - { label: '启用', value: '1' }, - { label: '禁用', value: '0' }, -]; diff --git a/apps/web-antd/src/router/access.ts b/apps/web-antd/src/router/access.ts index 5d2bd4b..aea6399 100644 --- a/apps/web-antd/src/router/access.ts +++ b/apps/web-antd/src/router/access.ts @@ -31,7 +31,6 @@ const routeMetaMapping: Record> = { activePath: '/system/role', requireHomeRedirect: true, }, - '/system/oss-config/index': { activePath: '/system/oss', requireHomeRedirect: true, diff --git a/apps/web-antd/src/views/device/product/data.ts b/apps/web-antd/src/views/device/product/data.ts new file mode 100644 index 0000000..271da7b --- /dev/null +++ b/apps/web-antd/src/views/device/product/data.ts @@ -0,0 +1,158 @@ +import type { FormSchemaGetter } from '#/adapter/form'; +import type { VxeGridProps } from '#/adapter/vxe-table'; + +import { h } from 'vue'; + +import { deviceTypeOptions, enabledOptions } from '#/constants/dicts'; + +export const querySchema: FormSchemaGetter = () => [ + { + component: 'Input', + fieldName: 'productName', + label: '产品名称', + }, + { + component: 'TreeSelect', + fieldName: 'categoryId', + componentProps: { + fieldNames: { children: 'children', label: 'label', value: 'id' }, + }, + label: '产品分类', + }, + { + component: 'Select', + componentProps: { + options: deviceTypeOptions, + }, + fieldName: 'deviceType', + label: '设备类型', + }, + { + component: 'Select', + componentProps: { + options: enabledOptions, + }, + fieldName: 'enabled', + label: '启用状态', + }, +]; + +// 需要使用i18n注意这里要改成getter形式 否则切换语言不会刷新 +// export const columns: () => VxeGridProps['columns'] = () => [ +export const columns: VxeGridProps['columns'] = [ + { type: 'checkbox', width: 60 }, + // { + // title: '编号', + // field: 'id', + // }, + { + title: '产品编码', + field: 'productKey', + }, + { + title: '产品名称', + field: 'productName', + }, + { + title: '设备类型', + field: 'deviceType', + }, + { + title: '启用状态', + field: 'enabled', + slots: { default: 'enabled' }, + }, + { + title: '描述', + field: 'description', + }, + { + field: 'action', + fixed: 'right', + slots: { default: 'action' }, + title: '操作', + width: 180, + }, +]; + +export const drawerSchema: FormSchemaGetter = () => [ + { + label: '编号', + fieldName: 'id', + component: 'Input', + dependencies: { + show: () => false, + triggerFields: [''], + }, + }, + { + label: '产品编码', + fieldName: 'productKey', + component: 'Input', + }, + { + label: '产品名称', + fieldName: 'productName', + component: 'Input', + rules: 'required', + }, + { + label: '产品图片', + fieldName: 'imgId', + component: 'ImageUpload', + componentProps: { + // accept: 'image/*', // 可选拓展名或者mime类型 ,拼接 + // maxCount: 1, // 最大上传文件数 默认为1 为1会绑定为string而非string[]类型 + }, + }, + { + component: 'TreeSelect', + fieldName: 'categoryId', + componentProps: { + fieldNames: { children: 'children', label: 'label', value: 'id' }, + }, + label: '产品分类', + }, + { + label: '设备类型', + fieldName: 'deviceType', + component: 'Select', + componentProps: { + options: deviceTypeOptions, + }, + rules: 'selectRequired', + renderComponentContent: () => { + return { + option: (option: any) => { + return h('div', { class: 'flex flex-col', title: option.tooltip }, [ + h('span', { class: 'font-medium text-blue-500' }, option.label), + h( + 'span', + { + class: 'text-[14px] text-black/25 truncate', + style: + 'max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;', + }, + option.tooltip, + ), + ]); + }, + }; + }, + }, + { + label: '描述', + fieldName: 'description', + component: 'Textarea', + }, + { + label: '启用状态', + fieldName: 'enabled', + component: 'Input', + defaultValue: '0', + dependencies: { + show: () => false, + triggerFields: [''], + }, + }, +]; diff --git a/apps/web-antd/src/views/device/product/index.vue b/apps/web-antd/src/views/device/product/index.vue new file mode 100644 index 0000000..ec3d1b5 --- /dev/null +++ b/apps/web-antd/src/views/device/product/index.vue @@ -0,0 +1,220 @@ + + + diff --git a/apps/web-antd/src/views/device/product/product-drawer.vue b/apps/web-antd/src/views/device/product/product-drawer.vue new file mode 100644 index 0000000..a8d76b8 --- /dev/null +++ b/apps/web-antd/src/views/device/product/product-drawer.vue @@ -0,0 +1,123 @@ + + +