Merge branch 'master' of http://119.91.43.128:3001/sheng/mes-ui-d2
This commit is contained in:
@@ -17,20 +17,24 @@
|
|||||||
|---:|---|---|---|
|
|---:|---|---|---|
|
||||||
| 1 | 页面入口 | 从菜单进入“反向追溯”,或直接访问 `/data_middleground/basic_traceability/reverse_direction_traceability` | 页面正常打开,显示电池条码输入框、查询、导出、重置按钮和空态区域 |
|
| 1 | 页面入口 | 从菜单进入“反向追溯”,或直接访问 `/data_middleground/basic_traceability/reverse_direction_traceability` | 页面正常打开,显示电池条码输入框、查询、导出、重置按钮和空态区域 |
|
||||||
| 2 | 空输入查询 | 不输入电池条码,点击“查询” | 页面提示请输入电池条码,不发起有效查询 |
|
| 2 | 空输入查询 | 不输入电池条码,点击“查询” | 页面提示请输入电池条码,不发起有效查询 |
|
||||||
| 3 | 有效条码查询 | 输入存在追溯数据的电池条码,点击“查询” | 页面展示追溯节点树,节点包含物料名称、编码、批次、工序、时间、设备等信息 |
|
| 3 | 有效条码查询 | 输入存在追溯数据的电池条码,点击“查询” | 页面通过 relation-graph 展示追溯图谱,节点包含物料名称、编码、批次、工序、时间、设备等信息 |
|
||||||
| 4 | 无数据条码查询 | 输入不存在追溯数据的电池条码,点击“查询” | 页面保持空态或显示无节点,不出现脚本错误 |
|
| 4 | 无数据条码查询 | 输入不存在追溯数据的电池条码,点击“查询” | 页面保持空态或显示无节点,不出现脚本错误 |
|
||||||
| 5 | 横向/纵向切换 | 查询出数据后,切换“横向图谱”和“纵向图谱” | 追溯节点展示方向切换,页面不丢失数据 |
|
| 5 | 横向/纵向切换 | 查询出数据后,切换“横向图谱”和“纵向图谱” | 追溯节点展示方向切换,页面不丢失数据 |
|
||||||
| 6 | 物料编码定位 | 查询出数据后,输入某个节点的物料编码,点击定位确认 | 匹配节点高亮并滚动到可视区域 |
|
| 6 | 图谱拖拽与缩放 | 查询出数据后,在图谱空白区域拖拽,并使用鼠标滚轮缩放 | 图谱内容可以平移和缩放,节点不会被页面容器裁切 |
|
||||||
| 7 | 物料批次定位 | 输入某个节点的物料批次,点击定位确认 | 匹配节点高亮并滚动到可视区域 |
|
| 7 | 节点内容完整性 | 查看包含较多字段的节点,滚动节点内容区域 | 节点卡片外框完整显示,字段内容可在节点内部滚动查看 |
|
||||||
| 8 | 工序单元定位 | 输入某个制成品节点的工序单元编码,点击定位确认 | 匹配节点高亮并滚动到可视区域;不存在时提示未找到匹配节点 |
|
| 8 | 物料编码定位 | 查询出数据后,输入某个节点的物料编码,点击定位确认 | 匹配节点高亮并居中聚焦到可视区域 |
|
||||||
| 9 | 导出前校验 | 未输入电池条码时点击“导出” | 页面提示请输入电池条码 |
|
| 9 | 物料批次定位 | 输入某个节点的物料批次,点击定位确认 | 匹配节点高亮并居中聚焦到可视区域 |
|
||||||
| 10 | 查询前导出 | 输入电池条码但未查询出追溯树,点击“导出” | 页面提示请先查询追溯数据后再导出 |
|
| 10 | 工序单元定位 | 输入某个制成品节点的工序单元编码,点击定位确认 | 匹配节点高亮并居中聚焦到可视区域;不存在时提示未找到匹配节点 |
|
||||||
| 11 | 正常导出 | 查询出追溯树后点击“导出” | 调用导出接口,浏览器开始下载或打开导出文件 |
|
| 11 | 导出前校验 | 未输入电池条码时点击“导出” | 页面提示请输入电池条码 |
|
||||||
| 12 | 重置功能 | 查询出追溯树后点击“重置” | 输入框、追溯树、定位输入和高亮状态全部清空 |
|
| 12 | 查询前导出 | 输入电池条码但未查询出追溯树,点击“导出” | 页面提示请先查询追溯数据后再导出 |
|
||||||
| 13 | 国际化检查 | 切换中英文语言后重新进入页面 | 页面按钮、节点字段和提示文案随语言切换显示 |
|
| 13 | 正常导出 | 查询出追溯树后点击“导出” | 调用导出接口,浏览器开始下载或打开导出文件 |
|
||||||
|
| 14 | 重置功能 | 查询出追溯树后点击“重置” | 输入框、追溯树、定位输入和高亮状态全部清空 |
|
||||||
|
| 15 | 国际化检查 | 切换中英文语言后重新进入页面 | 页面按钮、节点字段和提示文案随语言切换显示 |
|
||||||
|
|
||||||
## 回归关注点
|
## 回归关注点
|
||||||
|
|
||||||
- 接口返回 `relation_graph.nodes` 或 `relation_graph.lines` 为空时页面不能报错。
|
- 接口返回 `relation_graph.nodes` 或 `relation_graph.lines` 为空时页面不能报错。
|
||||||
|
- 图谱必须使用 `relation-graph` 渲染,支持拖拽、缩放和定位聚焦。
|
||||||
|
- 节点字段较多时,节点卡片外框不应被裁切,内容应可在卡片内部滚动查看。
|
||||||
- 导出接口参数中的 `tree_list` 应为当前追溯树节点数组 JSON。
|
- 导出接口参数中的 `tree_list` 应为当前追溯树节点数组 JSON。
|
||||||
- 路由参数携带 `battery_id` 时,页面应能自动查询对应追溯数据。
|
- 路由参数携带 `battery_id` 时,页面应能自动查询对应追溯数据。
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"qs": "^6.11.0",
|
"qs": "^6.11.0",
|
||||||
"quill": "^1.3.7",
|
"quill": "^1.3.7",
|
||||||
|
"relation-graph": "2.2.11",
|
||||||
"screenfull": "^5.2.0",
|
"screenfull": "^5.2.0",
|
||||||
"sortablejs": "^1.15.0",
|
"sortablejs": "^1.15.0",
|
||||||
"ua-parser-js": "^0.8.1",
|
"ua-parser-js": "^0.8.1",
|
||||||
|
|||||||
51
pnpm-lock.yaml
generated
51
pnpm-lock.yaml
generated
@@ -83,6 +83,9 @@ importers:
|
|||||||
quill:
|
quill:
|
||||||
specifier: ^1.3.7
|
specifier: ^1.3.7
|
||||||
version: 1.3.7
|
version: 1.3.7
|
||||||
|
relation-graph:
|
||||||
|
specifier: 2.2.11
|
||||||
|
version: 2.2.11
|
||||||
screenfull:
|
screenfull:
|
||||||
specifier: ^5.2.0
|
specifier: ^5.2.0
|
||||||
version: 5.2.0
|
version: 5.2.0
|
||||||
@@ -1867,6 +1870,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==}
|
resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==}
|
||||||
engines: {node: 18 || 20 || >=22}
|
engines: {node: 18 || 20 || >=22}
|
||||||
|
|
||||||
|
base64-arraybuffer@1.0.2:
|
||||||
|
resolution: {integrity: sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==}
|
||||||
|
engines: {node: '>= 0.6.0'}
|
||||||
|
|
||||||
base64-js@1.5.1:
|
base64-js@1.5.1:
|
||||||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||||
|
|
||||||
@@ -2614,6 +2621,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==}
|
resolution: {integrity: sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==}
|
||||||
engines: {node: '>4'}
|
engines: {node: '>4'}
|
||||||
|
|
||||||
|
css-line-break@2.1.0:
|
||||||
|
resolution: {integrity: sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==}
|
||||||
|
|
||||||
css-loader@3.6.0:
|
css-loader@3.6.0:
|
||||||
resolution: {integrity: sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==}
|
resolution: {integrity: sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==}
|
||||||
engines: {node: '>= 8.9.0'}
|
engines: {node: '>= 8.9.0'}
|
||||||
@@ -3828,6 +3838,10 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
webpack: ^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0
|
webpack: ^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0
|
||||||
|
|
||||||
|
html2canvas@1.4.1:
|
||||||
|
resolution: {integrity: sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==}
|
||||||
|
engines: {node: '>=8.0.0'}
|
||||||
|
|
||||||
htmlparser2@3.10.1:
|
htmlparser2@3.10.1:
|
||||||
resolution: {integrity: sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==}
|
resolution: {integrity: sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==}
|
||||||
|
|
||||||
@@ -5793,6 +5807,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==}
|
resolution: {integrity: sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==}
|
||||||
engines: {node: '>= 0.10'}
|
engines: {node: '>= 0.10'}
|
||||||
|
|
||||||
|
relation-graph@2.2.11:
|
||||||
|
resolution: {integrity: sha512-k8jrZkkNYMIKqGN0g8ZHhqd0sP9RAvem6xw9UN9FD59TiVlKx1Vsvi7E/Kh9Z1tZGltdrPo0ZERsUn6Ydoc0Sw==}
|
||||||
|
|
||||||
remove-trailing-separator@1.1.0:
|
remove-trailing-separator@1.1.0:
|
||||||
resolution: {integrity: sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==}
|
resolution: {integrity: sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==}
|
||||||
|
|
||||||
@@ -6478,6 +6495,9 @@ packages:
|
|||||||
text-loader@0.0.1:
|
text-loader@0.0.1:
|
||||||
resolution: {integrity: sha512-y2GvBFB9hibaHBRWE9xQhdENU1KppXnM9DCf6NueYPB/lnNX8ZzP3JLs1R1p3ObItcs+y8DBiPwelkJf8txe+g==}
|
resolution: {integrity: sha512-y2GvBFB9hibaHBRWE9xQhdENU1KppXnM9DCf6NueYPB/lnNX8ZzP3JLs1R1p3ObItcs+y8DBiPwelkJf8txe+g==}
|
||||||
|
|
||||||
|
text-segmentation@1.0.3:
|
||||||
|
resolution: {integrity: sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==}
|
||||||
|
|
||||||
text-table@0.2.0:
|
text-table@0.2.0:
|
||||||
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
|
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
|
||||||
|
|
||||||
@@ -6802,6 +6822,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
|
resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
|
||||||
engines: {node: '>= 0.4.0'}
|
engines: {node: '>= 0.4.0'}
|
||||||
|
|
||||||
|
utrie@1.0.2:
|
||||||
|
resolution: {integrity: sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==}
|
||||||
|
|
||||||
uuid@3.4.0:
|
uuid@3.4.0:
|
||||||
resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==}
|
resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==}
|
||||||
deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.
|
deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.
|
||||||
@@ -8207,9 +8230,7 @@ snapshots:
|
|||||||
source-map: 0.6.1
|
source-map: 0.6.1
|
||||||
string-length: 2.0.0
|
string-length: 2.0.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- bufferutil
|
|
||||||
- supports-color
|
- supports-color
|
||||||
- utf-8-validate
|
|
||||||
|
|
||||||
'@jest/source-map@24.9.0':
|
'@jest/source-map@24.9.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -9546,6 +9567,8 @@ snapshots:
|
|||||||
|
|
||||||
balanced-match@4.0.4: {}
|
balanced-match@4.0.4: {}
|
||||||
|
|
||||||
|
base64-arraybuffer@1.0.2: {}
|
||||||
|
|
||||||
base64-js@1.5.1: {}
|
base64-js@1.5.1: {}
|
||||||
|
|
||||||
base@0.11.2:
|
base@0.11.2:
|
||||||
@@ -10332,6 +10355,10 @@ snapshots:
|
|||||||
postcss: 7.0.39
|
postcss: 7.0.39
|
||||||
timsort: 0.3.0
|
timsort: 0.3.0
|
||||||
|
|
||||||
|
css-line-break@2.1.0:
|
||||||
|
dependencies:
|
||||||
|
utrie: 1.0.2
|
||||||
|
|
||||||
css-loader@3.6.0(webpack@4.47.0):
|
css-loader@3.6.0(webpack@4.47.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
camelcase: 5.3.1
|
camelcase: 5.3.1
|
||||||
@@ -11819,6 +11846,11 @@ snapshots:
|
|||||||
util.promisify: 1.0.0
|
util.promisify: 1.0.0
|
||||||
webpack: 4.47.0
|
webpack: 4.47.0
|
||||||
|
|
||||||
|
html2canvas@1.4.1:
|
||||||
|
dependencies:
|
||||||
|
css-line-break: 2.1.0
|
||||||
|
text-segmentation: 1.0.3
|
||||||
|
|
||||||
htmlparser2@3.10.1:
|
htmlparser2@3.10.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
domelementtype: 1.3.1
|
domelementtype: 1.3.1
|
||||||
@@ -12466,9 +12498,7 @@ snapshots:
|
|||||||
pretty-format: 24.9.0
|
pretty-format: 24.9.0
|
||||||
throat: 4.1.0
|
throat: 4.1.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- bufferutil
|
|
||||||
- supports-color
|
- supports-color
|
||||||
- utf-8-validate
|
|
||||||
|
|
||||||
jest-leak-detector@24.9.0:
|
jest-leak-detector@24.9.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -14196,6 +14226,11 @@ snapshots:
|
|||||||
|
|
||||||
relateurl@0.2.7: {}
|
relateurl@0.2.7: {}
|
||||||
|
|
||||||
|
relation-graph@2.2.11:
|
||||||
|
dependencies:
|
||||||
|
html2canvas: 1.4.1
|
||||||
|
screenfull: 5.2.0
|
||||||
|
|
||||||
remove-trailing-separator@1.1.0: {}
|
remove-trailing-separator@1.1.0: {}
|
||||||
|
|
||||||
renderkid@2.0.7:
|
renderkid@2.0.7:
|
||||||
@@ -15016,6 +15051,10 @@ snapshots:
|
|||||||
|
|
||||||
text-loader@0.0.1: {}
|
text-loader@0.0.1: {}
|
||||||
|
|
||||||
|
text-segmentation@1.0.3:
|
||||||
|
dependencies:
|
||||||
|
utrie: 1.0.2
|
||||||
|
|
||||||
text-table@0.2.0: {}
|
text-table@0.2.0: {}
|
||||||
|
|
||||||
thenify-all@1.6.0:
|
thenify-all@1.6.0:
|
||||||
@@ -15366,6 +15405,10 @@ snapshots:
|
|||||||
|
|
||||||
utils-merge@1.0.1: {}
|
utils-merge@1.0.1: {}
|
||||||
|
|
||||||
|
utrie@1.0.2:
|
||||||
|
dependencies:
|
||||||
|
base64-arraybuffer: 1.0.2
|
||||||
|
|
||||||
uuid@3.4.0: {}
|
uuid@3.4.0: {}
|
||||||
|
|
||||||
uuid@8.3.2: {}
|
uuid@8.3.2: {}
|
||||||
|
|||||||
@@ -29,78 +29,79 @@
|
|||||||
|
|
||||||
<div v-loading="loading" class="traceability-page">
|
<div v-loading="loading" class="traceability-page">
|
||||||
<el-empty v-if="!hasGraph" :description="$t(key('enter_battery_id'))" />
|
<el-empty v-if="!hasGraph" :description="$t(key('enter_battery_id'))" />
|
||||||
<template v-else>
|
<RelationGraph
|
||||||
<div class="trace-toolbar">
|
v-else
|
||||||
<div class="trace-toolbar__group">
|
ref="graphRef"
|
||||||
<span class="toolbar-label">{{ $t(key('view_type')) }}</span>
|
class="trace-graph"
|
||||||
<el-radio-group v-model="viewType" size="mini">
|
:options="currentGraphOptions"
|
||||||
|
:on-node-click="onNodeClick"
|
||||||
|
>
|
||||||
|
<template #graph-plug>
|
||||||
|
<div class="trace-panel">
|
||||||
|
<div class="trace-panel__label">{{ $t(key('view_type')) }}:</div>
|
||||||
|
<el-radio-group v-model="currentCase" size="small" @change="renderGraph">
|
||||||
<el-radio-button label="horizontal">{{ $t(key('horizontal')) }}</el-radio-button>
|
<el-radio-button label="horizontal">{{ $t(key('horizontal')) }}</el-radio-button>
|
||||||
<el-radio-button label="vertical">{{ $t(key('vertical')) }}</el-radio-button>
|
<el-radio-button label="vertical">{{ $t(key('vertical')) }}</el-radio-button>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
|
|
||||||
|
<div class="trace-panel__label trace-panel__label--spaced">{{ $t(key('position')) }}:</div>
|
||||||
|
<div class="trace-panel__row">
|
||||||
|
<el-input v-model.trim="locator.item_code" size="small" clearable :placeholder="$t(key('enter_item_code'))" />
|
||||||
|
<el-button size="small" type="primary" @click="locateNode('item_code', locator.item_code)">
|
||||||
|
{{ $t(key('confirm_position')) }}
|
||||||
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="trace-toolbar__locate">
|
<div class="trace-panel__row">
|
||||||
<span class="toolbar-label">{{ $t(key('position')) }}</span>
|
<el-input v-model.trim="locator.item_batch" size="small" clearable :placeholder="$t(key('enter_item_batch'))" />
|
||||||
<el-input v-model.trim="locator.item_code" size="mini" clearable :placeholder="$t(key('enter_item_code'))" />
|
<el-button size="small" type="primary" @click="locateNode('item_batch', locator.item_batch)">
|
||||||
<el-button size="mini" type="primary" @click="locateNode('item_code', locator.item_code)">
|
|
||||||
{{ $t(key('confirm_position')) }}
|
|
||||||
</el-button>
|
|
||||||
<el-input v-model.trim="locator.item_batch" size="mini" clearable :placeholder="$t(key('enter_item_batch'))" />
|
|
||||||
<el-button size="mini" type="primary" @click="locateNode('item_batch', locator.item_batch)">
|
|
||||||
{{ $t(key('confirm_position')) }}
|
{{ $t(key('confirm_position')) }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
</div>
|
||||||
|
<div class="trace-panel__row">
|
||||||
<el-input
|
<el-input
|
||||||
v-model.trim="locator.workingsubclass_code"
|
v-model.trim="locator.workingsubclass_code"
|
||||||
size="mini"
|
size="small"
|
||||||
clearable
|
clearable
|
||||||
:placeholder="$t(key('enter_work_unit'))"
|
:placeholder="$t(key('enter_work_unit'))"
|
||||||
/>
|
/>
|
||||||
<el-button size="mini" type="primary" @click="locateNode('workingsubclass_code', locator.workingsubclass_code, true)">
|
<el-button size="small" type="primary" @click="locateNode('workingsubclass_code', locator.workingsubclass_code, true)">
|
||||||
{{ $t(key('confirm_position')) }}
|
{{ $t(key('confirm_position')) }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<div :class="['trace-tree-wrap', 'trace-tree-wrap--' + viewType]">
|
<template #node="{ node }">
|
||||||
<el-tree
|
<div class="trace-node" :class="{ 'is-active': activeNodeId === String(node.id) }">
|
||||||
ref="tree"
|
<div class="trace-node__tag">
|
||||||
class="trace-tree"
|
<el-tag type="warning" effect="dark" size="small">{{ node.data.type_name || '-' }}</el-tag>
|
||||||
:data="treeData"
|
|
||||||
node-key="id"
|
|
||||||
default-expand-all
|
|
||||||
:expand-on-click-node="false"
|
|
||||||
>
|
|
||||||
<template #default="{ data }">
|
|
||||||
<div :class="['trace-node', { 'is-active': activeNodeId === data.id }]" :data-node-id="data.id" @click="activeNodeId = data.id">
|
|
||||||
<div class="trace-node__title">
|
|
||||||
<el-tag size="mini" type="warning" effect="dark">{{ data.data.type_name || '-' }}</el-tag>
|
|
||||||
<strong>{{ data.text || data.id }}</strong>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="trace-node__title">{{ node.text || node.id }}</div>
|
||||||
<div class="trace-node__body">
|
<div class="trace-node__body">
|
||||||
<p>{{ $t(key('item_name')) }}: {{ data.data.item_name || '-' }}</p>
|
<div class="trace-node__line">{{ $t(key('item_name')) }}: {{ node.data.item_name || '-' }}</div>
|
||||||
<p>{{ $t(key('item_code')) }}: {{ data.data.item_code || '-' }}</p>
|
<div class="trace-node__line">{{ $t(key('item_code')) }}: {{ node.data.item_code || '-' }}</div>
|
||||||
<p>{{ $t(key('item_batch')) }}: {{ data.data.item_batch || '-' }}</p>
|
<div class="trace-node__line">{{ $t(key('item_batch')) }}: {{ node.data.item_batch || '-' }}</div>
|
||||||
<p>{{ $t(key('work_unit')) }}: {{ data.data.workingsubclass_code || '-' }}</p>
|
<div class="trace-node__line">{{ $t(key('work_unit')) }}: {{ node.data.workingsubclass_code || '-' }}</div>
|
||||||
<p>{{ $t(key('work_unit_name')) }}: {{ data.data.workingsubclass_name || '-' }}</p>
|
<div class="trace-node__line">{{ $t(key('work_unit_name')) }}: {{ node.data.workingsubclass_name || '-' }}</div>
|
||||||
<p>{{ $t(key('process_code')) }}: {{ data.data.process_code || '-' }}</p>
|
<div class="trace-node__line">{{ $t(key('process_code')) }}: {{ node.data.process_code || '-' }}</div>
|
||||||
<p>{{ $t(key('start_time')) }}: {{ data.data.start_time || '-' }}</p>
|
<div class="trace-node__line">{{ $t(key('start_time')) }}: {{ node.data.start_time || '-' }}</div>
|
||||||
<p>{{ $t(key('finish_time')) }}: {{ data.data.finish_time || '-' }}</p>
|
<div class="trace-node__line">{{ $t(key('finish_time')) }}: {{ node.data.finish_time || '-' }}</div>
|
||||||
<p>{{ $t(key('inspection_person')) }}: {{ data.data.inspection_person || '-' }}</p>
|
<div class="trace-node__line">{{ $t(key('inspection_person')) }}: {{ node.data.inspection_person || '-' }}</div>
|
||||||
<p>{{ $t(key('inspection_time')) }}: {{ data.data.inspection_time || '-' }}</p>
|
<div class="trace-node__line">{{ $t(key('inspection_time')) }}: {{ node.data.inspection_time || '-' }}</div>
|
||||||
<p>{{ $t(key('quality_person')) }}: {{ data.data.quality_person || '-' }}</p>
|
<div class="trace-node__line">{{ $t(key('quality_person')) }}: {{ node.data.quality_person || '-' }}</div>
|
||||||
<p>{{ $t(key('quality_time')) }}: {{ data.data.quality_time || '-' }}</p>
|
<div class="trace-node__line">{{ $t(key('quality_time')) }}: {{ node.data.quality_time || '-' }}</div>
|
||||||
<p>{{ $t(key('device_name')) }}: {{ data.data.device_name || '-' }}</p>
|
<div class="trace-node__line">{{ $t(key('device_name')) }}: {{ node.data.device_name || '-' }}</div>
|
||||||
<p>{{ $t(key('device_code')) }}: {{ data.data.device_code || '-' }}</p>
|
<div class="trace-node__line">{{ $t(key('device_code')) }}: {{ node.data.device_code || '-' }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-tree>
|
</RelationGraph>
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</div>
|
</div>
|
||||||
</d2-container>
|
</d2-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import RelationGraph from 'relation-graph'
|
||||||
import { i18nMixin } from '@/composables/useI18n'
|
import { i18nMixin } from '@/composables/useI18n'
|
||||||
import {
|
import {
|
||||||
exportBackwardTraceabilityTree,
|
exportBackwardTraceabilityTree,
|
||||||
@@ -109,6 +110,9 @@ import {
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'data-platform-traceability-backward',
|
name: 'data-platform-traceability-backward',
|
||||||
|
components: {
|
||||||
|
RelationGraph
|
||||||
|
},
|
||||||
mixins: [i18nMixin('page.data_platform.traceability.backward')],
|
mixins: [i18nMixin('page.data_platform.traceability.backward')],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
@@ -117,7 +121,7 @@ export default {
|
|||||||
battery_id: this.$route.params.battery_id || ''
|
battery_id: this.$route.params.battery_id || ''
|
||||||
},
|
},
|
||||||
traceData: {},
|
traceData: {},
|
||||||
viewType: 'horizontal',
|
currentCase: 'horizontal',
|
||||||
activeNodeId: '',
|
activeNodeId: '',
|
||||||
locator: {
|
locator: {
|
||||||
item_code: '',
|
item_code: '',
|
||||||
@@ -133,31 +137,85 @@ export default {
|
|||||||
hasGraph () {
|
hasGraph () {
|
||||||
return Array.isArray(this.graph.nodes) && this.graph.nodes.length > 0
|
return Array.isArray(this.graph.nodes) && this.graph.nodes.length > 0
|
||||||
},
|
},
|
||||||
treeData () {
|
horizontalOptions () {
|
||||||
if (!this.hasGraph) return []
|
return {
|
||||||
const nodeMap = new Map()
|
backgroundImageNoRepeat: true,
|
||||||
this.graph.nodes.forEach(node => {
|
defaultNodeBorderWidth: 0,
|
||||||
nodeMap.set(String(node.id), {
|
defaultLineShape: 3,
|
||||||
...node,
|
defaultNodeShape: 0,
|
||||||
id: String(node.id),
|
defaultJunctionPoint: 'tb',
|
||||||
data: node.data || {},
|
defaultNodeWidth: 330,
|
||||||
children: []
|
defaultNodeHeight: 430,
|
||||||
})
|
defaultFocusRootNode: false,
|
||||||
})
|
downloadImageFileName: this.downloadName,
|
||||||
const childIds = new Set()
|
defaultLineColor: 'rgba(0, 186, 189, 1)',
|
||||||
const lines = Array.isArray(this.graph.lines) ? this.graph.lines : []
|
defaultNodeColor: 'rgba(0, 206, 209, 1)',
|
||||||
lines.forEach(line => {
|
moveToCenterWhenResize: true,
|
||||||
const from = nodeMap.get(String(line.from))
|
defaultLineMarker: {
|
||||||
const to = nodeMap.get(String(line.to))
|
markerWidth: 12,
|
||||||
if (from && to) {
|
markerHeight: 12,
|
||||||
from.children.push(to)
|
refX: '10',
|
||||||
childIds.add(to.id)
|
refY: 6,
|
||||||
|
data: 'M2,2 L10,6 L2,10 L6,6 L2,2'
|
||||||
|
},
|
||||||
|
layouts: [
|
||||||
|
{
|
||||||
|
label: this.$t(this.key('center')),
|
||||||
|
layoutName: 'tree',
|
||||||
|
layoutClassName: 'seeks-layout-center',
|
||||||
|
centerOffset_x: 0,
|
||||||
|
centerOffset_y: 0,
|
||||||
|
distance_coefficient: 1,
|
||||||
|
layoutDirection: 'v',
|
||||||
|
from: 'top',
|
||||||
|
min_per_width: 560,
|
||||||
|
max_per_width: 1100,
|
||||||
|
min_per_height: 560,
|
||||||
|
max_per_height: 1100
|
||||||
}
|
}
|
||||||
})
|
]
|
||||||
const rootId = this.graph.rootId ? String(this.graph.rootId) : ''
|
}
|
||||||
const root = rootId && nodeMap.get(rootId)
|
},
|
||||||
if (root) return [root]
|
verticalOptions () {
|
||||||
return Array.from(nodeMap.values()).filter(node => !childIds.has(node.id))
|
return {
|
||||||
|
defaultNodeShape: 1,
|
||||||
|
defaultNodeBorderWidth: 0,
|
||||||
|
defaultNodeWidth: 330,
|
||||||
|
defaultNodeHeight: 430,
|
||||||
|
defaultLineShape: 3,
|
||||||
|
defaultJunctionPoint: 'lr',
|
||||||
|
defaultFocusRootNode: false,
|
||||||
|
downloadImageFileName: this.downloadName,
|
||||||
|
defaultLineColor: 'rgba(0, 186, 189, 1)',
|
||||||
|
defaultNodeColor: 'rgba(0, 206, 209, 1)',
|
||||||
|
moveToCenterWhenResize: true,
|
||||||
|
layout: {
|
||||||
|
label: this.$t(this.key('center')),
|
||||||
|
layoutName: 'tree',
|
||||||
|
layoutClassName: 'seeks-layout-center',
|
||||||
|
defaultNodeShape: 0,
|
||||||
|
defaultLineShape: 1,
|
||||||
|
from: 'left',
|
||||||
|
min_per_width: 660,
|
||||||
|
max_per_width: 1100,
|
||||||
|
min_per_height: 560,
|
||||||
|
max_per_height: 700
|
||||||
|
},
|
||||||
|
defaultLineMarker: {
|
||||||
|
markerWidth: 12,
|
||||||
|
markerHeight: 12,
|
||||||
|
refX: 6,
|
||||||
|
refY: 6,
|
||||||
|
data: 'M2,2 L10,6 L2,10 L6,6 L2,2'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
currentGraphOptions () {
|
||||||
|
return this.currentCase === 'horizontal' ? this.horizontalOptions : this.verticalOptions
|
||||||
|
},
|
||||||
|
downloadName () {
|
||||||
|
const firstNode = this.graph.nodes && this.graph.nodes[0]
|
||||||
|
return firstNode && firstNode.text ? firstNode.text : this.$t(this.key('reverse'))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
@@ -178,6 +236,7 @@ export default {
|
|||||||
this.traceData = data || {}
|
this.traceData = data || {}
|
||||||
const firstNode = this.graph.nodes && this.graph.nodes[0]
|
const firstNode = this.graph.nodes && this.graph.nodes[0]
|
||||||
this.activeNodeId = firstNode ? String(firstNode.id) : ''
|
this.activeNodeId = firstNode ? String(firstNode.id) : ''
|
||||||
|
this.$nextTick(this.renderGraph)
|
||||||
} finally {
|
} finally {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
}
|
}
|
||||||
@@ -192,10 +251,17 @@ export default {
|
|||||||
workingsubclass_code: ''
|
workingsubclass_code: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
renderGraph () {
|
||||||
|
if (!this.hasGraph || !this.$refs.graphRef) return
|
||||||
|
this.$refs.graphRef.setOptions(this.currentGraphOptions)
|
||||||
|
this.$refs.graphRef.setJsonData(this.graph)
|
||||||
|
},
|
||||||
|
onNodeClick (nodeObject) {
|
||||||
|
this.activeNodeId = String(nodeObject.id)
|
||||||
|
},
|
||||||
locateNode (field, value, onlyFinalProduct = false) {
|
locateNode (field, value, onlyFinalProduct = false) {
|
||||||
if (!value) return
|
if (!value || !this.hasGraph) return
|
||||||
const nodes = Array.isArray(this.graph.nodes) ? this.graph.nodes : []
|
const target = this.graph.nodes.find(node => {
|
||||||
const target = nodes.find(node => {
|
|
||||||
const data = node.data || {}
|
const data = node.data || {}
|
||||||
if (String(data[field] || '') !== String(value)) return false
|
if (String(data[field] || '') !== String(value)) return false
|
||||||
if (!onlyFinalProduct) return true
|
if (!onlyFinalProduct) return true
|
||||||
@@ -206,14 +272,11 @@ export default {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.activeNodeId = String(target.id)
|
this.activeNodeId = String(target.id)
|
||||||
if (this.$refs.tree) {
|
|
||||||
this.$refs.tree.setCurrentKey(this.activeNodeId)
|
|
||||||
}
|
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
const element = this.$el.querySelector(`[data-node-id="${this.activeNodeId}"]`)
|
const graphInstance = this.$refs.graphRef && this.$refs.graphRef.getInstance()
|
||||||
if (element && element.scrollIntoView) {
|
if (!graphInstance) return
|
||||||
element.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'center' })
|
graphInstance.setZoom(200)
|
||||||
}
|
graphInstance.focusNodeById(target.id)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
async exportTree () {
|
async exportTree () {
|
||||||
@@ -249,87 +312,96 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.traceability-page {
|
.traceability-page {
|
||||||
min-height: 560px;
|
height: calc(100vh - 170px);
|
||||||
|
min-height: 620px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.trace-toolbar {
|
.trace-graph {
|
||||||
display: flex;
|
width: 100%;
|
||||||
flex-wrap: wrap;
|
height: 100%;
|
||||||
gap: 10px 18px;
|
min-height: 620px;
|
||||||
align-items: center;
|
border: 1px solid #ebeef5;
|
||||||
margin-bottom: 12px;
|
background: #f7f9fb;
|
||||||
}
|
}
|
||||||
|
|
||||||
.trace-toolbar__group,
|
.trace-panel {
|
||||||
.trace-toolbar__locate {
|
position: absolute;
|
||||||
display: flex;
|
top: 12px;
|
||||||
flex-wrap: wrap;
|
left: 12px;
|
||||||
gap: 8px;
|
z-index: 20;
|
||||||
align-items: center;
|
width: 360px;
|
||||||
|
padding: 12px;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: rgba(255, 255, 255, 0.94);
|
||||||
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
.trace-toolbar__locate .el-input {
|
.trace-panel__label {
|
||||||
width: 190px;
|
margin-bottom: 8px;
|
||||||
}
|
|
||||||
|
|
||||||
.toolbar-label {
|
|
||||||
color: #606266;
|
color: #606266;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.trace-tree-wrap {
|
.trace-panel__label--spaced {
|
||||||
height: calc(100vh - 230px);
|
margin-top: 14px;
|
||||||
min-height: 520px;
|
|
||||||
overflow: auto;
|
|
||||||
border: 1px solid #ebeef5;
|
|
||||||
border-radius: 4px;
|
|
||||||
background: #f7f9fb;
|
|
||||||
padding: 12px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.trace-tree-wrap--horizontal {
|
.trace-panel__row {
|
||||||
::v-deep .el-tree-node__children {
|
display: grid;
|
||||||
display: flex;
|
grid-template-columns: minmax(0, 1fr) 92px;
|
||||||
flex-wrap: wrap;
|
gap: 8px;
|
||||||
gap: 8px 16px;
|
margin-top: 10px;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.trace-tree {
|
|
||||||
min-width: max-content;
|
|
||||||
background: transparent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.trace-node {
|
.trace-node {
|
||||||
width: 300px;
|
position: relative;
|
||||||
min-height: 300px;
|
width: 330px;
|
||||||
padding: 10px;
|
height: 410px;
|
||||||
margin: 8px 0;
|
padding: 28px 12px 12px;
|
||||||
border: 1px solid #dcdfe6;
|
|
||||||
border-radius: 4px;
|
|
||||||
background: #fff;
|
|
||||||
color: #303133;
|
color: #303133;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.trace-node.is-active {
|
.trace-node.is-active .trace-node__body {
|
||||||
border-color: #409eff;
|
border-color: #f56c6c;
|
||||||
box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.15);
|
box-shadow: 0 0 0 2px rgba(245, 108, 108, 0.18);
|
||||||
|
}
|
||||||
|
|
||||||
|
.trace-node__tag {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.trace-node__title {
|
.trace-node__title {
|
||||||
display: flex;
|
min-height: 22px;
|
||||||
gap: 8px;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
|
padding-right: 8px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.4;
|
||||||
|
word-break: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
.trace-node__body p {
|
.trace-node__body {
|
||||||
margin: 0;
|
height: 340px;
|
||||||
|
overflow: auto;
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #fff;
|
||||||
|
color: #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trace-node__line {
|
||||||
|
min-height: 24px;
|
||||||
padding: 4px 0;
|
padding: 4px 0;
|
||||||
border-bottom: 1px solid #f0f2f5;
|
border-bottom: 1px solid #efefef;
|
||||||
line-height: 1.35;
|
line-height: 1.4;
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
|
word-break: break-all;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user