vue2-client 1.13.5 → 1.13.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +107 -107
- package/src/base-client/components/his/XHDescriptions/XHDescriptions.vue +154 -86
- package/src/base-client/components/his/XHDescriptions/index.md +40 -105
- package/src/base-client/components/his/XHisEditor/XHisEditor.vue +3 -3
- package/src/base-client/components/his/XSelect/XSelect.vue +4 -0
package/package.json
CHANGED
|
@@ -1,107 +1,107 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "vue2-client",
|
|
3
|
-
"version": "1.13.
|
|
4
|
-
"private": false,
|
|
5
|
-
"scripts": {
|
|
6
|
-
"serve": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve --no-eslint",
|
|
7
|
-
"serve:gaslink": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve --no-eslint --mode gaslink",
|
|
8
|
-
"serve:revenue": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve --no-eslint --mode revenue",
|
|
9
|
-
"serve:liuli": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve --no-eslint --mode liuli",
|
|
10
|
-
"serve:scada": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve --no-eslint --mode scada",
|
|
11
|
-
"serve:iot": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve --no-eslint --mode iot",
|
|
12
|
-
"serve:his": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve --no-eslint --mode his",
|
|
13
|
-
"mac-serve": "vue-cli-service serve --no-eslint --mode his",
|
|
14
|
-
"build": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service build",
|
|
15
|
-
"test:unit": "vue-cli-service test:unit",
|
|
16
|
-
"lint": "vue-cli-service lint",
|
|
17
|
-
"build:preview": "vue-cli-service build --mode preview",
|
|
18
|
-
"lint:nofix": "vue-cli-service lint --no-fix",
|
|
19
|
-
"test": "jest"
|
|
20
|
-
},
|
|
21
|
-
"dependencies": {
|
|
22
|
-
"@afwenming123/vue-easy-tree": "^1.0.1",
|
|
23
|
-
"@afwenming123/vue-plugin-hiprint": "^0.0.70",
|
|
24
|
-
"@amap/amap-jsapi-loader": "^1.0.1",
|
|
25
|
-
"@antv/data-set": "^0.11.8",
|
|
26
|
-
"@antv/g2plot": "^2.4.31",
|
|
27
|
-
"@hufe921/canvas-editor": "^0.9.49",
|
|
28
|
-
"@microsoft/fetch-event-source": "^2.0.1",
|
|
29
|
-
"@vue/babel-preset-jsx": "^1.4.0",
|
|
30
|
-
"animate.css": "^4.1.1",
|
|
31
|
-
"ant-design-vue": "^1.7.8",
|
|
32
|
-
"axios": "^0.27.2",
|
|
33
|
-
"clipboard": "^2.0.11",
|
|
34
|
-
"core-js": "^3.33.0",
|
|
35
|
-
"crypto-js": "^4.1.1",
|
|
36
|
-
"date-fns": "^2.29.3",
|
|
37
|
-
"default-passive-events": "^2.0.0",
|
|
38
|
-
"dotenv": "^16.3.1",
|
|
39
|
-
"echarts": "^5.5.0",
|
|
40
|
-
"enquire.js": "^2.1.6",
|
|
41
|
-
"file-saver": "^2.0.5",
|
|
42
|
-
"highlight.js": "^11.7.0",
|
|
43
|
-
"html2canvas": "^1.4.1",
|
|
44
|
-
"js-base64": "^3.7.5",
|
|
45
|
-
"js-cookie": "^2.2.1",
|
|
46
|
-
"jsencrypt": "^3.3.2",
|
|
47
|
-
"jspdf": "^2.5.1",
|
|
48
|
-
"lodash.clonedeep": "^4.5.0",
|
|
49
|
-
"lodash.debounce": "^4",
|
|
50
|
-
"lodash.get": "^4.4.2",
|
|
51
|
-
"marked": "^4",
|
|
52
|
-
"mockjs": "^1.1.0",
|
|
53
|
-
"nprogress": "^0.2.0",
|
|
54
|
-
"qs": "^6.11.2",
|
|
55
|
-
"regenerator-runtime": "^0.14.0",
|
|
56
|
-
"videojs-contrib-hls": "^5.15.0",
|
|
57
|
-
"viser-vue": "^2.4.8",
|
|
58
|
-
"vue": "^2.7.14",
|
|
59
|
-
"vue-codemirror": "4.0.6",
|
|
60
|
-
"vue-draggable-resizable": "^2",
|
|
61
|
-
"vue-i18n": "^8.28.2",
|
|
62
|
-
"vue-json-viewer": "^2.2.22",
|
|
63
|
-
"vue-router": "^3.6.5",
|
|
64
|
-
"vue-video-player": "^5.0.2",
|
|
65
|
-
"vue-virtual-scroller": "^1.1.2",
|
|
66
|
-
"vuedraggable": "^2.24.3",
|
|
67
|
-
"vuex": "^3.6.2",
|
|
68
|
-
"xlsx": "0.18.5"
|
|
69
|
-
},
|
|
70
|
-
"devDependencies": {
|
|
71
|
-
"@ant-design/colors": "^7.0.0",
|
|
72
|
-
"@babel/core": "^7.22.20",
|
|
73
|
-
"@babel/eslint-parser": "^7.22.15",
|
|
74
|
-
"@babel/preset-env": "^7.22.20",
|
|
75
|
-
"@vue/cli-plugin-babel": "^5.0.8",
|
|
76
|
-
"@vue/cli-plugin-eslint": "^5.0.8",
|
|
77
|
-
"@vue/cli-service": "^5.0.8",
|
|
78
|
-
"@vue/eslint-config-standard": "^8.0.1",
|
|
79
|
-
"@vue/test-utils": "^1.3.6",
|
|
80
|
-
"babel-plugin-transform-remove-console": "^6.9.4",
|
|
81
|
-
"compression-webpack-plugin": "^10.0.0",
|
|
82
|
-
"css-minimizer-webpack-plugin": "^5.0.1",
|
|
83
|
-
"deepmerge": "^4.3.1",
|
|
84
|
-
"eslint": "^8.51.0",
|
|
85
|
-
"eslint-plugin-vue": "^9.17.0",
|
|
86
|
-
"fast-deep-equal": "^3.1.3",
|
|
87
|
-
"ignore-loader": "^0.1.2",
|
|
88
|
-
"jest": "^29.7.0",
|
|
89
|
-
"jest-environment-jsdom": "^29.7.0",
|
|
90
|
-
"jest-transform-stub": "^2.0.0",
|
|
91
|
-
"less-loader": "^6.2.0",
|
|
92
|
-
"script-loader": "^0.7.2",
|
|
93
|
-
"style-resources-loader": "^1.5.0",
|
|
94
|
-
"vue-cli-plugin-style-resources-loader": "^0.1.5",
|
|
95
|
-
"vue-jest": "^4.0.1",
|
|
96
|
-
"vue-template-compiler": "^2.7.14",
|
|
97
|
-
"webpack": "^5.88.2",
|
|
98
|
-
"webpack-theme-color-replacer": "^1.4.7",
|
|
99
|
-
"whatwg-fetch": "^3.6.19"
|
|
100
|
-
},
|
|
101
|
-
"browserslist": [
|
|
102
|
-
"> 1%",
|
|
103
|
-
"last 2 versions",
|
|
104
|
-
"not dead",
|
|
105
|
-
"not ie 11"
|
|
106
|
-
]
|
|
107
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "vue2-client",
|
|
3
|
+
"version": "1.13.6",
|
|
4
|
+
"private": false,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"serve": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve --no-eslint",
|
|
7
|
+
"serve:gaslink": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve --no-eslint --mode gaslink",
|
|
8
|
+
"serve:revenue": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve --no-eslint --mode revenue",
|
|
9
|
+
"serve:liuli": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve --no-eslint --mode liuli",
|
|
10
|
+
"serve:scada": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve --no-eslint --mode scada",
|
|
11
|
+
"serve:iot": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve --no-eslint --mode iot",
|
|
12
|
+
"serve:his": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve --no-eslint --mode his",
|
|
13
|
+
"mac-serve": "vue-cli-service serve --no-eslint --mode his",
|
|
14
|
+
"build": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service build",
|
|
15
|
+
"test:unit": "vue-cli-service test:unit",
|
|
16
|
+
"lint": "vue-cli-service lint",
|
|
17
|
+
"build:preview": "vue-cli-service build --mode preview",
|
|
18
|
+
"lint:nofix": "vue-cli-service lint --no-fix",
|
|
19
|
+
"test": "jest"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@afwenming123/vue-easy-tree": "^1.0.1",
|
|
23
|
+
"@afwenming123/vue-plugin-hiprint": "^0.0.70",
|
|
24
|
+
"@amap/amap-jsapi-loader": "^1.0.1",
|
|
25
|
+
"@antv/data-set": "^0.11.8",
|
|
26
|
+
"@antv/g2plot": "^2.4.31",
|
|
27
|
+
"@hufe921/canvas-editor": "^0.9.49",
|
|
28
|
+
"@microsoft/fetch-event-source": "^2.0.1",
|
|
29
|
+
"@vue/babel-preset-jsx": "^1.4.0",
|
|
30
|
+
"animate.css": "^4.1.1",
|
|
31
|
+
"ant-design-vue": "^1.7.8",
|
|
32
|
+
"axios": "^0.27.2",
|
|
33
|
+
"clipboard": "^2.0.11",
|
|
34
|
+
"core-js": "^3.33.0",
|
|
35
|
+
"crypto-js": "^4.1.1",
|
|
36
|
+
"date-fns": "^2.29.3",
|
|
37
|
+
"default-passive-events": "^2.0.0",
|
|
38
|
+
"dotenv": "^16.3.1",
|
|
39
|
+
"echarts": "^5.5.0",
|
|
40
|
+
"enquire.js": "^2.1.6",
|
|
41
|
+
"file-saver": "^2.0.5",
|
|
42
|
+
"highlight.js": "^11.7.0",
|
|
43
|
+
"html2canvas": "^1.4.1",
|
|
44
|
+
"js-base64": "^3.7.5",
|
|
45
|
+
"js-cookie": "^2.2.1",
|
|
46
|
+
"jsencrypt": "^3.3.2",
|
|
47
|
+
"jspdf": "^2.5.1",
|
|
48
|
+
"lodash.clonedeep": "^4.5.0",
|
|
49
|
+
"lodash.debounce": "^4",
|
|
50
|
+
"lodash.get": "^4.4.2",
|
|
51
|
+
"marked": "^4",
|
|
52
|
+
"mockjs": "^1.1.0",
|
|
53
|
+
"nprogress": "^0.2.0",
|
|
54
|
+
"qs": "^6.11.2",
|
|
55
|
+
"regenerator-runtime": "^0.14.0",
|
|
56
|
+
"videojs-contrib-hls": "^5.15.0",
|
|
57
|
+
"viser-vue": "^2.4.8",
|
|
58
|
+
"vue": "^2.7.14",
|
|
59
|
+
"vue-codemirror": "4.0.6",
|
|
60
|
+
"vue-draggable-resizable": "^2",
|
|
61
|
+
"vue-i18n": "^8.28.2",
|
|
62
|
+
"vue-json-viewer": "^2.2.22",
|
|
63
|
+
"vue-router": "^3.6.5",
|
|
64
|
+
"vue-video-player": "^5.0.2",
|
|
65
|
+
"vue-virtual-scroller": "^1.1.2",
|
|
66
|
+
"vuedraggable": "^2.24.3",
|
|
67
|
+
"vuex": "^3.6.2",
|
|
68
|
+
"xlsx": "0.18.5"
|
|
69
|
+
},
|
|
70
|
+
"devDependencies": {
|
|
71
|
+
"@ant-design/colors": "^7.0.0",
|
|
72
|
+
"@babel/core": "^7.22.20",
|
|
73
|
+
"@babel/eslint-parser": "^7.22.15",
|
|
74
|
+
"@babel/preset-env": "^7.22.20",
|
|
75
|
+
"@vue/cli-plugin-babel": "^5.0.8",
|
|
76
|
+
"@vue/cli-plugin-eslint": "^5.0.8",
|
|
77
|
+
"@vue/cli-service": "^5.0.8",
|
|
78
|
+
"@vue/eslint-config-standard": "^8.0.1",
|
|
79
|
+
"@vue/test-utils": "^1.3.6",
|
|
80
|
+
"babel-plugin-transform-remove-console": "^6.9.4",
|
|
81
|
+
"compression-webpack-plugin": "^10.0.0",
|
|
82
|
+
"css-minimizer-webpack-plugin": "^5.0.1",
|
|
83
|
+
"deepmerge": "^4.3.1",
|
|
84
|
+
"eslint": "^8.51.0",
|
|
85
|
+
"eslint-plugin-vue": "^9.17.0",
|
|
86
|
+
"fast-deep-equal": "^3.1.3",
|
|
87
|
+
"ignore-loader": "^0.1.2",
|
|
88
|
+
"jest": "^29.7.0",
|
|
89
|
+
"jest-environment-jsdom": "^29.7.0",
|
|
90
|
+
"jest-transform-stub": "^2.0.0",
|
|
91
|
+
"less-loader": "^6.2.0",
|
|
92
|
+
"script-loader": "^0.7.2",
|
|
93
|
+
"style-resources-loader": "^1.5.0",
|
|
94
|
+
"vue-cli-plugin-style-resources-loader": "^0.1.5",
|
|
95
|
+
"vue-jest": "^4.0.1",
|
|
96
|
+
"vue-template-compiler": "^2.7.14",
|
|
97
|
+
"webpack": "^5.88.2",
|
|
98
|
+
"webpack-theme-color-replacer": "^1.4.7",
|
|
99
|
+
"whatwg-fetch": "^3.6.19"
|
|
100
|
+
},
|
|
101
|
+
"browserslist": [
|
|
102
|
+
"> 1%",
|
|
103
|
+
"last 2 versions",
|
|
104
|
+
"not dead",
|
|
105
|
+
"not ie 11"
|
|
106
|
+
]
|
|
107
|
+
}
|
|
@@ -12,19 +12,74 @@
|
|
|
12
12
|
</a-button>
|
|
13
13
|
</div>
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
<
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
15
|
+
<!-- 当有 layout 配置时使用 a-descriptions -->
|
|
16
|
+
<template v-if="config?.layout">
|
|
17
|
+
<a-descriptions
|
|
18
|
+
:column="config.layout"
|
|
19
|
+
:size="config?.style?.size"
|
|
20
|
+
:bordered="config?.style?.bordered"
|
|
21
|
+
layout="horizontal">
|
|
22
|
+
<template v-if="data">
|
|
23
|
+
<!-- 显示前N个标签 -->
|
|
24
|
+
<a-descriptions-item
|
|
25
|
+
v-for="(item) in visibleItems"
|
|
26
|
+
:key="item.field"
|
|
27
|
+
:colon="item.colon !== false"
|
|
28
|
+
v-if="data[item.field] !== null && data[item.field] !== undefined && (!showAllItems || showAllItems && !hiddenItems.some(i => i.field === item.field))">
|
|
29
|
+
<template #label>
|
|
30
|
+
<div :class="['label-wrapper', { 'with-avatar': item.showAvatar }]">
|
|
31
|
+
<a-avatar
|
|
32
|
+
v-if="item.showAvatar"
|
|
33
|
+
:size="item.avatar.size"
|
|
34
|
+
:icon="item.avatar.icon"
|
|
35
|
+
:style="{ background: item.avatar.background }"
|
|
36
|
+
/>
|
|
37
|
+
<span class="label-text">{{ item.label }}</span>
|
|
38
|
+
</div>
|
|
39
|
+
</template>
|
|
40
|
+
<div class="content-wrapper">
|
|
41
|
+
{{ data[item.field] }}
|
|
42
|
+
</div>
|
|
43
|
+
</a-descriptions-item>
|
|
44
|
+
|
|
45
|
+
<!-- 展开后显示剩余标签 -->
|
|
46
|
+
<template v-if="showAllItems">
|
|
47
|
+
<a-descriptions-item
|
|
48
|
+
v-for="item in hiddenItems"
|
|
49
|
+
:key="item.field"
|
|
50
|
+
:colon="item.colon !== false"
|
|
51
|
+
v-if="data[item.field] !== null && data[item.field] !== undefined">
|
|
52
|
+
<template #label>
|
|
53
|
+
<div :class="['label-wrapper', { 'with-avatar': item.showAvatar }]">
|
|
54
|
+
<a-avatar
|
|
55
|
+
v-if="item.showAvatar"
|
|
56
|
+
:size="item.avatar.size"
|
|
57
|
+
:icon="item.avatar.icon"
|
|
58
|
+
:style="{ background: item.avatar.background }"
|
|
59
|
+
/>
|
|
60
|
+
<span class="label-text">{{ item.label }}</span>
|
|
61
|
+
</div>
|
|
62
|
+
</template>
|
|
63
|
+
<div class="content-wrapper">
|
|
64
|
+
{{ data[item.field] }}
|
|
65
|
+
</div>
|
|
66
|
+
</a-descriptions-item>
|
|
67
|
+
</template>
|
|
68
|
+
</template>
|
|
69
|
+
</a-descriptions>
|
|
70
|
+
</template>
|
|
71
|
+
|
|
72
|
+
<!-- 当没有 layout 配置时使用自适应布局 -->
|
|
73
|
+
<template v-else>
|
|
74
|
+
<div class="flex-descriptions">
|
|
75
|
+
<template v-if="data">
|
|
76
|
+
<!-- 显示可见的标签 -->
|
|
77
|
+
<div
|
|
78
|
+
v-for="(item) in visibleItems"
|
|
79
|
+
:key="item.field"
|
|
80
|
+
class="description-item"
|
|
81
|
+
v-if="data[item.field] !== null && data[item.field] !== undefined"
|
|
82
|
+
>
|
|
28
83
|
<div :class="['label-wrapper', { 'with-avatar': item.showAvatar }]">
|
|
29
84
|
<a-avatar
|
|
30
85
|
v-if="item.showAvatar"
|
|
@@ -32,22 +87,21 @@
|
|
|
32
87
|
:icon="item.avatar.icon"
|
|
33
88
|
:style="{ background: item.avatar.background }"
|
|
34
89
|
/>
|
|
35
|
-
<span class="label-text">{{ item.label }}
|
|
90
|
+
<span class="label-text">{{ item.label }}:</span>
|
|
91
|
+
</div>
|
|
92
|
+
<div class="content-wrapper">
|
|
93
|
+
{{ data[item.field] }}
|
|
36
94
|
</div>
|
|
37
|
-
</template>
|
|
38
|
-
<div class="content-wrapper">
|
|
39
|
-
{{ data[item.field] }}
|
|
40
95
|
</div>
|
|
41
|
-
</a-descriptions-item>
|
|
42
96
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
97
|
+
<!-- 展开后显示的内容 -->
|
|
98
|
+
<template v-if="showAllItems">
|
|
99
|
+
<div
|
|
100
|
+
v-for="item in hiddenItems"
|
|
101
|
+
:key="item.field"
|
|
102
|
+
class="description-item"
|
|
103
|
+
v-if="data[item.field] !== null && data[item.field] !== undefined"
|
|
104
|
+
>
|
|
51
105
|
<div :class="['label-wrapper', { 'with-avatar': item.showAvatar }]">
|
|
52
106
|
<a-avatar
|
|
53
107
|
v-if="item.showAvatar"
|
|
@@ -55,19 +109,20 @@
|
|
|
55
109
|
:icon="item.avatar.icon"
|
|
56
110
|
:style="{ background: item.avatar.background }"
|
|
57
111
|
/>
|
|
58
|
-
<span class="label-text">{{ item.label }}
|
|
112
|
+
<span class="label-text">{{ item.label }}:</span>
|
|
113
|
+
</div>
|
|
114
|
+
<div class="content-wrapper">
|
|
115
|
+
{{ data[item.field] }}
|
|
59
116
|
</div>
|
|
60
|
-
</template>
|
|
61
|
-
<div class="content-wrapper">
|
|
62
|
-
{{ data[item.field] }}
|
|
63
117
|
</div>
|
|
64
|
-
</
|
|
118
|
+
</template>
|
|
65
119
|
</template>
|
|
66
|
-
</
|
|
67
|
-
</
|
|
120
|
+
</div>
|
|
121
|
+
</template>
|
|
68
122
|
</div>
|
|
69
123
|
</div>
|
|
70
124
|
</template>
|
|
125
|
+
|
|
71
126
|
<script>
|
|
72
127
|
import { getConfigByName, runLogic } from '@vue2-client/services/api/common'
|
|
73
128
|
|
|
@@ -95,20 +150,14 @@ export default {
|
|
|
95
150
|
computed: {
|
|
96
151
|
// 获取详情按钮应该显示在第几个标签后
|
|
97
152
|
detailsAfterIndex () {
|
|
98
|
-
// 只有明确配置了detailsConfig且设置了showAfterIndex时才使用配置值
|
|
99
|
-
// 否则返回一个很大的值,使所有字段都显示
|
|
100
153
|
return this.config?.detailsConfig?.showAfterIndex || 999
|
|
101
154
|
},
|
|
102
155
|
// 判断是否有更多标签需要显示
|
|
103
156
|
hasMoreItems () {
|
|
104
|
-
// 只有明确配置了detailsConfig时才显示详情按钮
|
|
105
157
|
if (!this.config?.detailsConfig) return false
|
|
106
|
-
// 如果没有数据或没有配置项,不显示详情按钮
|
|
107
158
|
if (!this.data || !this.config?.items || !Array.isArray(this.config.items)) return false
|
|
108
|
-
// 获取隐藏项索引
|
|
109
159
|
const hiddenStartIndex = this.detailsAfterIndex || 0
|
|
110
160
|
if (hiddenStartIndex >= this.config.items.length) return false
|
|
111
|
-
// 检查隐藏的项中是否有非空值
|
|
112
161
|
for (let i = hiddenStartIndex; i < this.config.items.length; i++) {
|
|
113
162
|
const item = this.config.items[i]
|
|
114
163
|
if (item && item.field && this.data[item.field] !== null && this.data[item.field] !== undefined) {
|
|
@@ -120,31 +169,15 @@ export default {
|
|
|
120
169
|
// 获取应该显示的标签
|
|
121
170
|
visibleItems () {
|
|
122
171
|
if (!this.config?.items) return []
|
|
123
|
-
|
|
124
|
-
if (
|
|
125
|
-
// 如果没有配置detailsConfig,直接显示所有项
|
|
126
|
-
return this.config.items
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
if (this.showAllItems) {
|
|
130
|
-
// 如果已经展开,也返回前N项,后面的项目会通过hiddenItems显示
|
|
131
|
-
return this.config.items.slice(0, this.detailsAfterIndex)
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// 否则显示前N项
|
|
172
|
+
if (!this.config?.detailsConfig) return this.config.items
|
|
173
|
+
if (this.showAllItems) return this.config.items.slice(0, this.detailsAfterIndex)
|
|
135
174
|
return this.config.items.slice(0, this.detailsAfterIndex)
|
|
136
175
|
},
|
|
137
|
-
//
|
|
176
|
+
// 获取隐藏的标签(保持原有逻辑)
|
|
138
177
|
hiddenItems () {
|
|
139
178
|
if (!this.config?.items) return []
|
|
140
|
-
if (!this.config?.detailsConfig) return []
|
|
179
|
+
if (!this.config?.detailsConfig) return []
|
|
141
180
|
return this.config.items.slice(this.detailsAfterIndex)
|
|
142
|
-
},
|
|
143
|
-
// 获取有效的visible项目数量(排除null值)
|
|
144
|
-
validVisibleItemsCount () {
|
|
145
|
-
if (!this.config?.items || !this.data) return 0
|
|
146
|
-
const items = this.visibleItems
|
|
147
|
-
return items.filter(item => this.data[item.field] !== null && this.data[item.field] !== undefined).length
|
|
148
181
|
}
|
|
149
182
|
},
|
|
150
183
|
created () {
|
|
@@ -153,7 +186,7 @@ export default {
|
|
|
153
186
|
methods: {
|
|
154
187
|
async getData (data) {
|
|
155
188
|
this.data = null
|
|
156
|
-
this.showAllItems = false
|
|
189
|
+
this.showAllItems = false
|
|
157
190
|
getConfigByName(data, 'af-his', res => {
|
|
158
191
|
this.config = res
|
|
159
192
|
console.log(this.config)
|
|
@@ -163,7 +196,6 @@ export default {
|
|
|
163
196
|
})
|
|
164
197
|
})
|
|
165
198
|
},
|
|
166
|
-
// 切换详情显示状态
|
|
167
199
|
toggleDetails () {
|
|
168
200
|
this.showAllItems = !this.showAllItems
|
|
169
201
|
}
|
|
@@ -185,30 +217,45 @@ export default {
|
|
|
185
217
|
background: #fff;
|
|
186
218
|
padding: 12px;
|
|
187
219
|
border-radius: 4px;
|
|
220
|
+
width: 100%;
|
|
188
221
|
}
|
|
189
222
|
|
|
190
223
|
.descriptions-container {
|
|
191
|
-
position: relative;
|
|
224
|
+
position: relative;
|
|
225
|
+
width: 100%;
|
|
226
|
+
padding-right: 80px; /* 为按钮预留空间 */
|
|
192
227
|
}
|
|
193
228
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
229
|
+
/* 自适应布局样式 */
|
|
230
|
+
.flex-descriptions {
|
|
231
|
+
display: flex;
|
|
232
|
+
flex-wrap: wrap;
|
|
233
|
+
gap: 8px 24px;
|
|
234
|
+
width: 100%;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.description-item {
|
|
238
|
+
display: inline-flex;
|
|
239
|
+
align-items: center;
|
|
199
240
|
padding: 4px 8px;
|
|
200
241
|
border-radius: 4px;
|
|
201
|
-
background-color
|
|
242
|
+
transition: background-color 0.3s;
|
|
243
|
+
white-space: nowrap;
|
|
244
|
+
flex: 0 1 auto;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
.description-item:hover {
|
|
248
|
+
background-color: rgba(0, 0, 0, 0.02);
|
|
202
249
|
}
|
|
203
250
|
|
|
251
|
+
/* 共用样式 */
|
|
204
252
|
.label-wrapper {
|
|
205
253
|
display: flex;
|
|
206
254
|
align-items: center;
|
|
255
|
+
gap: 8px;
|
|
256
|
+
color: rgba(0, 0, 0, 0.65);
|
|
257
|
+
font-size: v-bind('config?.style?.fontSize');
|
|
207
258
|
white-space: nowrap;
|
|
208
|
-
line-height: 24px;
|
|
209
|
-
position: relative;
|
|
210
|
-
padding: 0;
|
|
211
|
-
margin: 0;
|
|
212
259
|
}
|
|
213
260
|
|
|
214
261
|
.label-wrapper.with-avatar {
|
|
@@ -216,15 +263,32 @@ export default {
|
|
|
216
263
|
}
|
|
217
264
|
|
|
218
265
|
.label-text {
|
|
266
|
+
white-space: nowrap;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
.content-wrapper {
|
|
219
270
|
display: inline-flex;
|
|
220
271
|
align-items: center;
|
|
272
|
+
margin-left: 4px;
|
|
273
|
+
font-size: v-bind('config?.style?.fontSize');
|
|
274
|
+
color: rgba(0, 0, 0, 0.85);
|
|
275
|
+
max-width: 300px;
|
|
276
|
+
overflow: hidden;
|
|
277
|
+
text-overflow: ellipsis;
|
|
278
|
+
white-space: nowrap;
|
|
221
279
|
}
|
|
222
280
|
|
|
223
|
-
.
|
|
224
|
-
|
|
281
|
+
.detail-button-wrapper {
|
|
282
|
+
position: absolute;
|
|
283
|
+
right: 0;
|
|
284
|
+
top: 0;
|
|
285
|
+
z-index: 10;
|
|
286
|
+
padding: 4px 8px;
|
|
225
287
|
white-space: nowrap;
|
|
288
|
+
background-color: #fff;
|
|
226
289
|
}
|
|
227
290
|
|
|
291
|
+
/* Ant Design 描述列表样式覆盖 */
|
|
228
292
|
:deep(.ant-descriptions-row) {
|
|
229
293
|
display: flex;
|
|
230
294
|
flex-direction: row;
|
|
@@ -276,23 +340,11 @@ export default {
|
|
|
276
340
|
padding: 0 !important;
|
|
277
341
|
}
|
|
278
342
|
|
|
279
|
-
/* 移除 Ant Design 的默认样式 */
|
|
280
|
-
:deep(.ant-descriptions-item-container),
|
|
281
|
-
:deep(.ant-descriptions-item-label),
|
|
282
|
-
:deep(.ant-descriptions-item-content),
|
|
283
|
-
:deep(.ant-descriptions-item-colon) {
|
|
284
|
-
box-sizing: border-box !important;
|
|
285
|
-
border-spacing: 0 !important;
|
|
286
|
-
border-collapse: collapse !important;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
/* 添加悬停效果 */
|
|
290
343
|
:deep(.ant-descriptions-item-container:hover) {
|
|
291
344
|
background-color: rgba(0, 0, 0, 0.02);
|
|
292
345
|
border-radius: 4px;
|
|
293
346
|
}
|
|
294
347
|
|
|
295
|
-
/* 添加详情按钮样式 */
|
|
296
348
|
:deep(.ant-btn-link) {
|
|
297
349
|
padding: 0;
|
|
298
350
|
height: auto;
|
|
@@ -303,4 +355,20 @@ export default {
|
|
|
303
355
|
color: #1890ff;
|
|
304
356
|
background: transparent;
|
|
305
357
|
}
|
|
358
|
+
|
|
359
|
+
/* 响应式调整 */
|
|
360
|
+
@media screen and (max-width: 768px) {
|
|
361
|
+
.content-wrapper {
|
|
362
|
+
max-width: 200px;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
@media screen and (max-width: 576px) {
|
|
367
|
+
.content-wrapper {
|
|
368
|
+
max-width: 150px;
|
|
369
|
+
}
|
|
370
|
+
.flex-descriptions {
|
|
371
|
+
gap: 4px 12px;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
306
374
|
</style>
|
|
@@ -4,21 +4,21 @@
|
|
|
4
4
|
|
|
5
5
|
`XHDescriptions` 是一个基于 Ant Design Vue 的描述列表组件封装,专用于显示患者基本信息。该组件具有以下特点:
|
|
6
6
|
|
|
7
|
-
-
|
|
7
|
+
- 支持两种布局模式:响应式列数布局和自适应流式布局
|
|
8
8
|
- 支持折叠/展开功能,控制信息的显示量
|
|
9
9
|
- 支持自定义样式和头像
|
|
10
|
-
- 自动隐藏值为 null、undefined的字段
|
|
10
|
+
- 自动隐藏值为 null、undefined 的字段
|
|
11
11
|
- 右上角悬浮"详情/收起"按钮,布局更整洁
|
|
12
12
|
|
|
13
13
|
## 配置说明
|
|
14
14
|
|
|
15
15
|
组件通过 JSON 配置文件进行配置,主要包含以下部分:
|
|
16
16
|
|
|
17
|
-
### 1. 布局配置 (layout)
|
|
17
|
+
### 1. 布局配置 (layout,可选)
|
|
18
18
|
|
|
19
19
|
```json
|
|
20
20
|
"layout": {
|
|
21
|
-
"xl": 4,
|
|
21
|
+
"xl": 4,
|
|
22
22
|
"md": 3,
|
|
23
23
|
"sm": 2,
|
|
24
24
|
"lg": 4,
|
|
@@ -27,24 +27,21 @@
|
|
|
27
27
|
}
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
-
|
|
30
|
+
- 可选配置,用于设置固定列数布局模式
|
|
31
|
+
- 当配置了 layout 时,使用 Ant Design 的 Descriptions 组件布局
|
|
31
32
|
- 键名对应不同的屏幕尺寸(xs, sm, md, lg, xl, xxl)
|
|
32
33
|
- 值为每行显示的列数
|
|
33
|
-
-
|
|
34
|
+
- 如果不配置 layout,则使用自适应流式布局
|
|
34
35
|
|
|
35
36
|
### 2. 样式配置 (style)
|
|
36
37
|
|
|
37
38
|
```json
|
|
38
39
|
"style": {
|
|
39
|
-
"
|
|
40
|
-
"fontSize": "14px",
|
|
41
|
-
"bordered": false
|
|
40
|
+
"fontSize": "14px"
|
|
42
41
|
}
|
|
43
42
|
```
|
|
44
43
|
|
|
45
|
-
- `size`: 设置尺寸,可选值为 "default", "middle", "small"
|
|
46
44
|
- `fontSize`: 控制文字大小
|
|
47
|
-
- `bordered`: 是否显示边框
|
|
48
45
|
|
|
49
46
|
### 3. 字段配置 (items)
|
|
50
47
|
|
|
@@ -52,19 +49,13 @@
|
|
|
52
49
|
"items": [
|
|
53
50
|
{
|
|
54
51
|
"field": "patientName",
|
|
55
|
-
"style": {
|
|
56
|
-
"minHeight": "24px",
|
|
57
|
-
"width": "120px",
|
|
58
|
-
"minWidth": "100px",
|
|
59
|
-
"height": "24px"
|
|
60
|
-
},
|
|
61
52
|
"label": "患者",
|
|
53
|
+
"showAvatar": true,
|
|
62
54
|
"avatar": {
|
|
63
55
|
"size": 20,
|
|
64
56
|
"background": "#5D5C5C",
|
|
65
57
|
"icon": "user"
|
|
66
|
-
}
|
|
67
|
-
"showAvatar": true
|
|
58
|
+
}
|
|
68
59
|
}
|
|
69
60
|
]
|
|
70
61
|
```
|
|
@@ -73,7 +64,6 @@
|
|
|
73
64
|
|
|
74
65
|
- `field`: 字段名,用于从数据源获取值
|
|
75
66
|
- `label`: 显示的标签名
|
|
76
|
-
- `style`: 控制字段的样式(宽度、高度等)
|
|
77
67
|
- `showAvatar`: 是否显示头像
|
|
78
68
|
- `avatar`: 头像配置(仅当 showAvatar 为 true 时有效)
|
|
79
69
|
- `size`: 头像大小
|
|
@@ -86,17 +76,18 @@
|
|
|
86
76
|
"detailsConfig": {
|
|
87
77
|
"buttonText": "详细",
|
|
88
78
|
"buttonType": "link",
|
|
89
|
-
"showAfterIndex":
|
|
79
|
+
"showAfterIndex": 6
|
|
90
80
|
}
|
|
91
81
|
```
|
|
92
82
|
|
|
93
83
|
- `buttonText`: 详情按钮显示的文本
|
|
94
84
|
- `buttonType`: 按钮类型,可选值为 "default", "primary", "dashed", "link" 等
|
|
95
85
|
- `showAfterIndex`: 控制在显示多少个字段后显示详情按钮
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
86
|
+
|
|
87
|
+
**重要说明**:
|
|
88
|
+
- 只有明确配置了 `detailsConfig` 对象时,才会启用折叠功能
|
|
89
|
+
- 如果没有配置 `detailsConfig`,将直接显示所有字段,不会出现详情按钮
|
|
90
|
+
- 如果配置了 `detailsConfig` 但字段总数少于或等于 `showAfterIndex`,则不会显示详情按钮
|
|
100
91
|
|
|
101
92
|
### 5. 其他配置
|
|
102
93
|
|
|
@@ -132,56 +123,32 @@ export default {
|
|
|
132
123
|
|
|
133
124
|
```vue
|
|
134
125
|
<template>
|
|
135
|
-
<XHDescriptions
|
|
136
|
-
queryParamsName="patientBasicInfoConfig"
|
|
137
|
-
:parameter="{ patientId: '123456' }"
|
|
126
|
+
<XHDescriptions
|
|
127
|
+
queryParamsName="patientBasicInfoConfig"
|
|
128
|
+
:parameter="{ patientId: '123456' }"
|
|
138
129
|
/>
|
|
139
130
|
</template>
|
|
140
131
|
```
|
|
141
132
|
|
|
142
133
|
## 特殊说明
|
|
143
134
|
|
|
144
|
-
1.
|
|
145
|
-
-
|
|
146
|
-
-
|
|
147
|
-
-
|
|
135
|
+
1. **布局模式**:
|
|
136
|
+
- 配置了 `layout` 时:使用固定列数布局,每行显示指定数量的列
|
|
137
|
+
- 未配置 `layout` 时:使用自适应流式布局,根据内容自动换行
|
|
138
|
+
- 两种模式下详情按钮都固定在右上角
|
|
148
139
|
|
|
149
140
|
2. **折叠/展开功能**:
|
|
150
141
|
- 折叠功能只在明确配置了 `detailsConfig` 对象时启用
|
|
151
|
-
- 没有配置 `detailsConfig`
|
|
142
|
+
- 没有配置 `detailsConfig` 时,会直接显示所有字段
|
|
152
143
|
- 详情按钮会悬浮在组件右上角,点击可展开/收起全部字段
|
|
153
|
-
- 按钮显示"详情"或"收起",会根据当前状态自动切换
|
|
154
144
|
|
|
155
145
|
3. **空值处理**:
|
|
156
|
-
- 当字段值为 `null`、`undefined`
|
|
146
|
+
- 当字段值为 `null`、`undefined` 时,该字段不会显示
|
|
157
147
|
- 折叠功能会忽略空值的字段,只有有值的隐藏字段才会触发显示详情按钮
|
|
158
|
-
- 这个特性可以用于根据数据动态控制字段的显示,无需修改配置
|
|
159
|
-
|
|
160
|
-
4. **字段重复问题处理**:
|
|
161
|
-
- 组件已经优化处理了展开时的字段重复显示问题
|
|
162
|
-
- 采用智能过滤机制,确保同一字段不会在多个位置显示
|
|
163
|
-
|
|
164
|
-
## 配置优化建议
|
|
165
|
-
|
|
166
|
-
1. **字段数量**:
|
|
167
|
-
- 建议将最重要、最常用的信息放在前 `showAfterIndex` 个位置
|
|
168
|
-
- 避免配置过多字段,通常不建议超过 20 个字段
|
|
169
|
-
- 如有大量相关字段,考虑拆分为多个不同的描述组件
|
|
170
|
-
|
|
171
|
-
2. **布局优化**:
|
|
172
|
-
- 根据字段的宽度调整 `layout` 配置
|
|
173
|
-
- 较宽的字段(如地址、证件号等)可能需要更多的列宽
|
|
174
|
-
- 建议在大屏幕下(xl, xxl)不要超过 4-5 列
|
|
175
|
-
|
|
176
|
-
3. **样式设置**:
|
|
177
|
-
- 为了统一视觉效果,建议所有相似的描述组件使用统一的样式设置
|
|
178
|
-
- 字段宽度设置合理的 `minWidth`,确保在各种屏幕下显示正常
|
|
179
148
|
|
|
180
149
|
## 配置示例
|
|
181
150
|
|
|
182
|
-
###
|
|
183
|
-
|
|
184
|
-
以下配置将启用折叠功能,只显示前6个字段,其余字段需点击"详细"按钮查看:
|
|
151
|
+
### 固定列数布局示例
|
|
185
152
|
|
|
186
153
|
```json
|
|
187
154
|
{
|
|
@@ -189,14 +156,12 @@ export default {
|
|
|
189
156
|
"xl": 4,
|
|
190
157
|
"md": 3,
|
|
191
158
|
"sm": 2,
|
|
192
|
-
"lg":
|
|
159
|
+
"lg": 4,
|
|
193
160
|
"xs": 1,
|
|
194
161
|
"xxl": 5
|
|
195
162
|
},
|
|
196
163
|
"style": {
|
|
197
|
-
"
|
|
198
|
-
"fontSize": "14px",
|
|
199
|
-
"bordered": false
|
|
164
|
+
"fontSize": "14px"
|
|
200
165
|
},
|
|
201
166
|
"items": [
|
|
202
167
|
{
|
|
@@ -216,67 +181,37 @@ export default {
|
|
|
216
181
|
{
|
|
217
182
|
"field": "diagnosisNo",
|
|
218
183
|
"label": "诊号"
|
|
219
|
-
},
|
|
220
|
-
{
|
|
221
|
-
"field": "gender",
|
|
222
|
-
"label": "性别"
|
|
223
|
-
},
|
|
224
|
-
{
|
|
225
|
-
"field": "age",
|
|
226
|
-
"label": "年龄"
|
|
227
|
-
},
|
|
228
|
-
{
|
|
229
|
-
"field": "diagnosis",
|
|
230
|
-
"label": "诊断"
|
|
231
|
-
},
|
|
232
|
-
{
|
|
233
|
-
"field": "phone_no",
|
|
234
|
-
"label": "电话号码"
|
|
235
|
-
},
|
|
236
|
-
{
|
|
237
|
-
"field": "identification_no",
|
|
238
|
-
"label": "身份证号"
|
|
239
|
-
},
|
|
240
|
-
{
|
|
241
|
-
"field": "allergies",
|
|
242
|
-
"label": "过敏史"
|
|
243
184
|
}
|
|
244
185
|
// ... 更多字段
|
|
245
186
|
],
|
|
246
187
|
"detailsConfig": {
|
|
247
188
|
"buttonText": "详细",
|
|
248
189
|
"buttonType": "link",
|
|
249
|
-
"showAfterIndex": 6
|
|
190
|
+
"showAfterIndex": 6
|
|
250
191
|
},
|
|
251
192
|
"logicName": "patientBasicInfoLogic",
|
|
252
193
|
"serverName": "af-his"
|
|
253
194
|
}
|
|
254
195
|
```
|
|
255
196
|
|
|
256
|
-
###
|
|
257
|
-
|
|
258
|
-
如果不希望使用折叠功能,希望一次性显示所有字段,只需要移除 `detailsConfig` 对象:
|
|
197
|
+
### 自适应流式布局示例
|
|
259
198
|
|
|
260
199
|
```json
|
|
261
200
|
{
|
|
262
|
-
"layout": {
|
|
263
|
-
"xl": 4,
|
|
264
|
-
"md": 3,
|
|
265
|
-
"sm": 2,
|
|
266
|
-
"lg": 3,
|
|
267
|
-
"xs": 1,
|
|
268
|
-
"xxl": 5
|
|
269
|
-
},
|
|
270
201
|
"style": {
|
|
271
|
-
"
|
|
272
|
-
"fontSize": "14px",
|
|
273
|
-
"bordered": false
|
|
202
|
+
"fontSize": "14px"
|
|
274
203
|
},
|
|
275
204
|
"items": [
|
|
276
|
-
|
|
205
|
+
{
|
|
206
|
+
"field": "patientName",
|
|
207
|
+
"label": "患者"
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"field": "patientType",
|
|
211
|
+
"label": "类别"
|
|
212
|
+
}
|
|
277
213
|
],
|
|
278
214
|
"logicName": "patientBasicInfoLogic",
|
|
279
215
|
"serverName": "af-his"
|
|
280
|
-
// 没有 detailsConfig,将直接显示所有字段
|
|
281
216
|
}
|
|
282
|
-
```
|
|
217
|
+
```
|
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
>
|
|
15
15
|
<a-select-option v-for="item of resListCp" :key="item.value" :value="item.value">{{ item.label }}</a-select-option>
|
|
16
16
|
</a-select>
|
|
17
|
-
<template v-if="this.modeType !== 'readonly' && this.resId !== -1"
|
|
18
|
-
<a-button icon="plus" @click="addRes"
|
|
19
|
-
</template
|
|
17
|
+
<!-- <template v-if="this.modeType !== 'readonly' && this.resId !== -1">-->
|
|
18
|
+
<!-- <a-button icon="plus" @click="addRes"/>-->
|
|
19
|
+
<!-- </template>-->
|
|
20
20
|
</template>
|
|
21
21
|
<a-radio-group
|
|
22
22
|
v-show="showModeChoose"
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
style="width: 150px"
|
|
7
7
|
:allowClear="true"
|
|
8
8
|
:showSearch="true"
|
|
9
|
+
:filter-option="filterOption"
|
|
9
10
|
@change="handleChange"
|
|
10
11
|
>
|
|
11
12
|
<a-select-option v-for="(item, index) in data" :key="index" :value="item.value">
|
|
@@ -53,6 +54,9 @@ export default {
|
|
|
53
54
|
this.selectedValue = value === '' ? undefined : value
|
|
54
55
|
this.$emit('change', this.selectedValue)
|
|
55
56
|
},
|
|
57
|
+
filterOption (input, option) {
|
|
58
|
+
return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
|
59
|
+
}
|
|
56
60
|
},
|
|
57
61
|
watch: {
|
|
58
62
|
selectedValue (val) {
|