From 7f85623cb2b0855867c377ad2fd9e4392e1f4bf2 Mon Sep 17 00:00:00 2001 From: liub Date: Mon, 1 Sep 2025 17:27:11 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=BE=E5=A4=87=E5=88=86=E7=BB=84=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- .../equipmentManagement/devicegroup/index.ts | 421 ++++++ src/assets/images/searchIcon.png | Bin 0 -> 1355 bytes src/views/fys-equipment/group/index.vue | 1151 +++++++++++++++++ vite.config.ts | 6 +- 5 files changed, 1576 insertions(+), 4 deletions(-) create mode 100644 src/api/equipmentManagement/devicegroup/index.ts create mode 100644 src/assets/images/searchIcon.png create mode 100644 src/views/fys-equipment/group/index.vue diff --git a/package.json b/package.json index 7b9d0ee..1655330 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "unplugin-icons": "22.1.0", "unplugin-vue-components": "28.5.0", "unplugin-vue-setup-extend-plus": "1.0.1", - "vite": "6.3.2", + "vite": "^7.1.3", "vite-plugin-compression": "0.5.1", "vite-plugin-svg-icons-ng": "^1.4.0", "vite-plugin-vue-devtools": "7.7.5", diff --git a/src/api/equipmentManagement/devicegroup/index.ts b/src/api/equipmentManagement/devicegroup/index.ts new file mode 100644 index 0000000..a43d70c --- /dev/null +++ b/src/api/equipmentManagement/devicegroup/index.ts @@ -0,0 +1,421 @@ +import { func } from 'vue-types'; +import request from '@/utils/request'; +import { AxiosPromise } from 'axios'; + +//左侧节点的数据源 +function getTreeData(para : any) { + + + + let promise2 = new Promise((resolve, reject) => { + request({ + url: '/api/device/group/list', + method: 'get', + params: { + "createDept": null, + "createBy": null, + "createTime": "", + "updateBy": null, + "updateTime": "", + "params": { + "additionalProp1": "", + "additionalProp2": "", + "additionalProp3": "" + }, + "id": null, + "groupName": para, + "status": 1, + "parentId": null, + "fullPath": "", + "isDeleted": 0, + "pageNum": 1, + "pageSize": 99999 + } + }).then((res) => { + resolve(res); + }).catch((ex) => { + reject(ex); + }); + }); + + return new Promise((resolve, reject) => { + Promise.allSettled([ promise2]).then(res => { + debugger; + if (res[0].status == 'fulfilled') { + let json = res[0].value; + + + resolve(json.data); + } + }); + }); + +} +//节点搜索 +function treeNodeSearch(treeData, search = '', filed = 'groupName', childField = 'children') { + + + /** + * 对文本进行标准化处理(去除空格和转换为小写) + * @param {string} text - 需要处理的文本 + * @returns {string} 标准化后的文本 + */ + function normalizeText(text) { + return text.replace(/\s+/g, '').toLowerCase(); + } + + /** + * 收集所有末级元素的完整路径 + * @param {Array} nodes - 节点数组 + * @param {Array} currentPath - 当前路径 + * @param {Array} leafPaths - 存储末级元素路径的数组 + */ + function collectLeafPaths(nodes, currentPath, leafPaths, childField) { + if (!nodes || !nodes.length) return; + + for (let node of nodes) { + // 创建包含当前节点的新路径 + let newPath = [...currentPath, node]; + + // 检查是否为末级元素(没有children或children为空) + if (!node[childField] || !node[childField].length) { + leafPaths.push(newPath); + } else { + // 递归处理子节点 + collectLeafPaths(node[childField], newPath, leafPaths, childField); + } + } + } + + /** + * 检查路径上是否有任何节点匹配搜索条件 + * @param {Array} path - 节点路径数组 + * @param {string} searchTerm - 标准化后的搜索词 + * @returns {boolean} 是否匹配 + */ + function checkPathMatches(path, searchTerm, field) { + return path.some(node => + normalizeText(node[field]).includes(searchTerm) + ); + } + + /** + * 将路径数组转换为嵌套的层级结构 + * @param {Array} path - 节点路径数组 + * @returns {Object} 嵌套结构的节点 + */ + function buildHierarchy(path, childField) { + // 从最后一个节点开始向前构建 + let currentNode = { ...path[path.length - 1] }; + // 移除children属性(末级节点不应有children) + if (currentNode[childField]) delete currentNode[childField]; + + // 从倒数第二个节点开始向前遍历 + for (let i = path.length - 2; i >= 0; i--) { + let node = { ...path[i] }; + // 将当前节点作为子节点 + node[childField] = [currentNode]; + currentNode = node; + } + + return currentNode; + } + + + + + function mergeHierarchies(hierarchies) { + if (!hierarchies || hierarchies.length === 0) return []; + + // 使用Map存储相同txt的节点,key为txt + let nodeMap = new Map(); + + for (let node of hierarchies) { + let key = node.txt; + + if (nodeMap.has(key)) { + // 如果已存在相同txt的节点,合并它们的子节点 + let existingNode = nodeMap.get(key); + existingNode.child = mergeHierarchies([ + ...(existingNode.child || []), + ...(node.child || []) + ]); + } else { + // 如果不存在,直接添加到Map + nodeMap.set(key, { ...node }); + } + } + + // 将Map的值转换为数组并返回 + return Array.from(nodeMap.values()); + } + + /** + * 生成路径的唯一标识 + * @param {Object} node - 节点对象 + * @param {string} prefix - 前缀 + * @returns {string} 路径标识 + */ + function getPathKey(node, prefix = '', field, childField) { + let currentKey = prefix ? `${prefix}->${node[field]}` : node[field]; + if (node[childField] && node[childField].length) { + return getPathKey(node[childField][0], currentKey, field, childField); + } + return currentKey; + } + + /** + * 从末级元素开始向上搜索匹配的路径 + * @param {Array} data - 数据源数组 + * @param {string} keyword - 搜索关键词 + * @returns {Array} 匹配的层级结构数组,与原数据结构一致 + */ + function searchLabels(data, keyword, field, childField) { + if (!data || !Array.isArray(data)) { + return []; + + } + + if (!keyword) { + return data; + } + + // 标准化搜索关键词 + let searchTerm = normalizeText(keyword); + + // 收集所有末级元素的完整路径 + let leafPaths = []; + collectLeafPaths(data, [], leafPaths, childField); + + // 筛选出符合条件的路径 + let matchedPaths = leafPaths.filter(path => + checkPathMatches(path, searchTerm, field, childField) + ); + + // 将路径转换为嵌套结构 + let results = matchedPaths.map(path => buildHierarchy(path, childField)); + // 去重并返回结果 + return mergeHierarchies(results); + } + + let searchList = searchLabels(treeData, search, filed, childField); + + return searchList; +} + +//更新节点名称 +function updateTreeName(nodes, targetValue, newTxt, filed = 'groupName', childField = "children", valueFiled = "id") { + let updateTree=function(){ + for (let node of nodes) { + // 检查当前节点是否匹配value + if (node[valueFiled] === targetValue) { + node[filed] = newTxt; + return true; // 找到并更新,返回true + } + + // 如果有子节点,递归查找 + if (node[childField] && node[childField].length > 0) { + let found = updateTreeName(node[childField], targetValue, newTxt); + if (found) { + return true; // 在子节点中找到,返回true + } + } + } + return false; // 未找到匹配的节点 + } + + let requestUpdate=function(){ + let promise2 = new Promise((resolve, reject) => { + request({ + url: '/api/device/group', + method: 'put', + data: targetValue + }).then((res) => { + resolve(res); + }).catch((ex) => { + reject(ex); + }); + + + }); + return promise2; + } + + return requestUpdate(); +} + +//添加新节点 +function addTreeNode(nodes, newNode, targetValue, childField = "children", valueFiled = "id") { + + let updateTree = function () { + if (!targetValue) { + nodes.push(newNode); + return true; + } + for (let node of nodes) { + // 检查当前节点是否匹配value + if (node.value === targetValue) { + if (!node[childField]) { + node[childField] = []; + } + node[childField].push(newNode); + return true; // 找到并更新,返回true + } + + // 如果有子节点,递归查找 + if (node[childField] && node[childField].length > 0) { + let found = addTreeNode(node[childField], newNode, targetValue); + if (found) { + return true; // 在子节点中找到,返回true + } + } + } + return false; // 未找到匹配的节点 + } + + + let requestAddnode = function () { + let promise2 = new Promise((resolve, reject) => { + request({ + url: '/api/device/group', + method: 'post', + data: newNode + }).then((res) => { + resolve(res); + }).catch((ex) => { + reject(ex); + }); + + + }); + return promise2; + } + return requestAddnode(); + + +} + +//删除某个节点 +function delTreeNode(nodes, targetValue, childField = "children", valueFiled = "id") { + let updateTree = function () { + if (!targetValue) { + + return false; + } + for (let node of nodes) { + // 检查当前节点是否匹配value + if (node[valueFiled] === targetValue) { + let index = nodes.indexOf(node); + if (index > -1) { + nodes.splice(index, 1); + } + return true; + } + + // 如果有子节点,递归查找 + if (node[childField] && node[childField].length > 0) { + let found = delTreeNode(node[childField], targetValue); + if (found) { + return true; // 在子节点中找到,返回true + } + } + } + return false; // 未找到匹配的节点 + } + + let requestDel=function(){ + let promise2 = new Promise((resolve, reject) => { + request({ + url: '/api/device/group/'+targetValue, + method: 'delete', + + }).then((res) => { + resolve(res); + }).catch((ex) => { + reject(ex); + }); + + + }); + return promise2; + } + + return requestDel(); +} + +//获取某个节点的设备数据 +function getNodeDevice(para) { + + + + + let promise2 = new Promise((resolve, reject) => { + request({ + url: '/api/device', + method: 'get', + params:{ + "deviceStatus": 1, + "pageNum": para.pageIndex, + "pageSize": para.pageSize, + "groupId": para.nodeCode, + +} + }).then((res) => { + resolve(res); + }).catch((ex) => { + reject(ex); + }); + }); + + return new Promise((resolve, reject) => { + Promise.allSettled([promise2]).then(res => { + + if (res[0].status == 'fulfilled') { + debugger; + resolve(res[0].value); + } + }); + }); + +} + +//从分组中删除设备 +function groupDelDevice(groupid,deviceIds){ + return new Promise((resolve,reject)=>{ + request({ + url: '/api/device/group/groupUnbind/'+deviceIds, + method: 'get', + + }).then((res) => { + resolve(res); + }).catch((ex) => { + reject(ex); + }); + }); +} + +//将设备移动至分组 +function deviceMoveGroup(groupid,deviceIds){ + return new Promise((resolve,reject)=>{ + request({ + url: '/api/device/group/groupId/'+groupid+'/'+deviceIds, + method: 'get', + + }).then((res) => { + resolve(res); + }).catch((ex) => { + reject(ex); + }); + }); +} + +export default { + getTreeData: getTreeData, + treeNodeSearch: treeNodeSearch, + updateTreeName: updateTreeName, + addTreeNode: addTreeNode, + delTreeNode: delTreeNode, + getNodeDevice: getNodeDevice, + groupDelDevice:groupDelDevice, + deviceMoveGroup:deviceMoveGroup +} diff --git a/src/assets/images/searchIcon.png b/src/assets/images/searchIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..091659333d43230963a498fcb70ac79a85c88fc7 GIT binary patch literal 1355 zcmcIke@Gi=7{07kTYofKMqQWHSn8nAcHJr%ifPhH)Mkhq(k=`kwz$QySTb-fKN=Hf z%9_q~Df^iaF>Hgv6n1}vOqds9FkMECy^c|`+SStpF5O(##LMa>e%|fQ-AKkT{?|%*l2tOWlMH_ zZK?xH(of(_)PxGgOdw9=F^oKFF7GIeI5lZ$LIL) zjr>Hh(DCOIB3n}2K;L(w2^(L>$;UiB$Q=oCyWi%mug-RbvK20RFft(8Wt+W*njIQ* z%s{|7i9JK29oBv5XNlqEmGce61G(KfP`IwNBIcVFQ;-`q2Q`;t1H|K;*G`hy38dxphw)Mogaxi9Yeu=w=`&1^QiDLH73gCr zWO@1&?$3+YIi|U_;2-@FqK&@+gHUvUib6nX0s5=?W21bZC%?kLe3brTHBc7X`T;Ju zZRbU3JMIZfKxllfAHLCzr(Vkn>T=>C6LobIN5t zKsmO4lq!~?G0gT*GZI_NOx!h4t4aGpW{D3;|CCXgZ26q^&RTG(U*Sz%u@Pb^-TOhj z+!WM|d_;$SBvrJa`DWkdH__00ZcMP0T#{%n`ULkh zX%}!Kbb?I(*O$McobE?z=`v14fdoo~e&RgLV|zh8<1`Z(IHVZg^q_V0Ek3a_Vs~Jq iBWiC+_+Ru9uAXl%w!ZN){uc9-gw*Zbs_)t^jQs=u +
+
+
+
设备分组
+
新增
+
+ + +
+ + + +
+ + +
+ + +
+
+
+ + 添加设备 +
+
+
+
+ + +
+
+ +
高级筛选
+
+
+ + + +
+ +
+ + + + +
+ + 移动 + + 删除 +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + {{Status.confirm.text}} + + + + + + + + + + + + 确定 + + + 取消 + + + + + + + + +
+ + 确定 + + + 取消 + +
+ + +
+ +
+ + + + + + diff --git a/vite.config.ts b/vite.config.ts index 889ccd1..3565072 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -5,17 +5,17 @@ import path from 'path'; export default defineConfig(({ mode, command }) => { const env = loadEnv(mode, process.cwd()); - + // 参考eladmin-web的部署方式,使用相对路径 let basePath = '/'; - if (mode === 'production') { + if (mode === 'development') { // 生产环境:如果设置了上下文路径则使用,否则使用相对路径 basePath = env.VITE_APP_CONTEXT_PATH || './'; } else { // 开发环境:使用上下文路径或默认根路径 basePath = env.VITE_APP_CONTEXT_PATH || '/'; } - + return { // 部署生产环境和开发环境下的URL。 // 默认情况下,vite 会假设你的应用是被部署在一个域名的根路径上