lw-cdp-ui 1.0.58 → 1.0.60

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.
@@ -17,7 +17,13 @@
17
17
  v-if="!hideHandle(item)">
18
18
  <!-- 间隔标题 -->
19
19
  <div v-if="item.component == 'divider'"
20
- class="title-name">{{ item.label }}</div>
20
+ class="title-name">
21
+ {{ item.label }}
22
+ <el-tooltip v-if="item.tips"
23
+ :content="item.tips">
24
+ <el-icon><el-icon-question-filled /></el-icon>
25
+ </el-tooltip>
26
+ </div>
21
27
  <!-- 表单内容 -->
22
28
  <el-form-item v-else
23
29
  :prop="item?.options?.name ? `${item.name}.${item.options.name}` : item.name"
@@ -194,22 +200,32 @@
194
200
  v-bind="{
195
201
  min: item?.options?.min !== undefined ? item.options.min : null,
196
202
  max: item?.options?.max !== undefined ? item.options.max : null,
197
- step: item?.options?.step !== undefined ? item.options.step : null,
203
+ step: item?.options?.step !== undefined ? item.options.step : 1,
198
204
  precision: item?.options?.precision !== undefined ? item.options.precision : null,
199
205
  placeholder: item?.options?.placeholder || ''
200
206
  }"
201
- controls-position="right"></el-input-number>
207
+ controls-position="right">
208
+ <template v-if="item?.options?.suffix"
209
+ #suffix>
210
+ <span>{{item.options.suffix}}</span>
211
+ </template>
212
+ </el-input-number>
202
213
  </template>
203
214
  <template v-else>
204
215
  <el-input-number v-model="form[item.name]"
205
216
  v-bind="{
206
217
  min: item?.options?.min !== undefined ? item.options.min : null,
207
218
  max: item?.options?.max !== undefined ? item.options.max : null,
208
- step: item?.options?.step !== undefined ? item.options.step : null,
219
+ step: item?.options?.step !== undefined ? item.options.step : 1,
209
220
  precision: item?.options?.precision !== undefined ? item.options.precision : null,
210
221
  placeholder: item?.options?.placeholder || ''
211
222
  }"
212
- controls-position="right"></el-input-number>
223
+ controls-position="right">
224
+ <template v-if="item?.options?.suffix"
225
+ #suffix>
226
+ <span>{{item.options.suffix}}</span>
227
+ </template>
228
+ </el-input-number>
213
229
  </template>
214
230
 
215
231
  </template>
@@ -348,7 +364,7 @@ export default {
348
364
  }
349
365
  },
350
366
  watch: {
351
- modelValue() {
367
+ modelValue(val, old) {
352
368
  if (this.hasConfig) {
353
369
  this.deepMerge(this.form, JSON.parse(JSON.stringify(this.modelValue)))
354
370
  }
@@ -0,0 +1,349 @@
1
+ <template>
2
+ <el-skeleton v-if="renderLoading || Object.keys(form).length==0"
3
+ animated />
4
+ <el-descriptions v-else
5
+ :column="config.column || 3"
6
+ :size="config.size">
7
+ <template v-for="(item, index) in config.formItems">
8
+ <template v-if="!hideHandle(item)">
9
+ <template v-if="item.component == 'divider'">
10
+ <el-descriptions-item :span="item.span || 24">
11
+ <template #label>
12
+ <span class="title-name">{{ item.label }}</span>
13
+ </template>
14
+ </el-descriptions-item>
15
+ </template>
16
+ <el-descriptions-item v-else
17
+ :span="item.span/(24/(config.column || 3))">
18
+ <template #label>
19
+ <span v-if="item.label"
20
+ class="title-item">
21
+ {{ item.label }}
22
+ <el-tooltip v-if="item.tips"
23
+ :content="item.tips">
24
+ <el-icon><el-icon-question-filled /></el-icon>
25
+ </el-tooltip>:
26
+ </span>
27
+ </template>
28
+ <!-- input -->
29
+ <template v-if="item.component=='input' || item.component=='number'">
30
+ <template v-if="item?.options?.name">
31
+ <textToPassword v-model="form[item.name][item.options.name]"
32
+ :password="item?.options?.password" />
33
+ </template>
34
+ <template v-else>
35
+ <textToPassword v-model="form[item.name]"
36
+ :password="item?.options?.password" />
37
+ </template>
38
+ </template>
39
+ <!-- upload -->
40
+ <template v-else-if="item.component=='upload'">
41
+ <el-col v-for="(_item, _index) in item.options.items"
42
+ :key="_index">
43
+ <template v-if="item.name">
44
+ <el-image style="width: 100px; height: 100px"
45
+ :src="form[item.name][_item.name]"
46
+ :fit="contain" />
47
+ </template>
48
+ <template v-else>
49
+ <el-image style="width: 100px; height: 100px"
50
+ :src="form[_item.name]"
51
+ :fit="contain" />
52
+ </template>
53
+
54
+ </el-col>
55
+ </template>
56
+ <!-- checkbox -->
57
+ <template v-else-if="item.component=='checkbox'">
58
+ <template v-if="item.name">
59
+ {{ form[item.name][_item.name] }}
60
+ </template>
61
+ <template v-else>
62
+ {{ form[_item.name] }}
63
+ </template>
64
+ </template>
65
+ <!-- checkboxGroup -->
66
+ <template v-else-if="item.component=='checkboxGroup'">
67
+ {{ form[item.name] }}
68
+ </template>
69
+ <!-- switch -->
70
+ <template v-else-if="item.component=='switch'">
71
+ <template v-if="item?.options?.name">
72
+ {{ form[item.name][item.options.name] ? item.options.true || '是' : item.options.false || '否' }}
73
+ </template>
74
+ <template v-else>
75
+ {{ form[item.name] ? item.options.true || '是' : item.options.false || '否' }}
76
+ </template>
77
+ </template>
78
+ <!-- select -->
79
+ <template
80
+ v-else-if="item.component=='select' || item.component=='radio'">
81
+ <template v-if="item?.options?.name">
82
+ {{getKeyToLabel(form[item.name][item.options.name], item.options.items)}}
83
+ </template>
84
+ <template v-else>
85
+ {{getKeyToLabel(form[item.name], item.options.items)}}
86
+ </template>
87
+ </template>
88
+ <!-- cascader -->
89
+ <template v-else-if="item.component=='cascader'">
90
+ <template v-if="item?.options?.name">
91
+ <el-cascader v-model="form[item.name][item.options.name]"
92
+ :options="item.options.items"
93
+ clearable></el-cascader>
94
+ </template>
95
+ <template v-else>
96
+ <el-cascader v-model="form[item.name]"
97
+ :options="item.options.items"
98
+ clearable></el-cascader>
99
+ </template>
100
+ </template>
101
+ <!-- date -->
102
+ <template v-else-if="item.component=='date'">
103
+ <template v-if="item?.options?.name">
104
+ {{ dayjs(form[item.name][item.options.name]).format(item.options.valueFormat || 'YYYY-MM-DD HH:mm:ss') }}
105
+
106
+ </template>
107
+ <template v-else>
108
+ {{ dayjs(form[item.name]).format(item.options.valueFormat || 'YYYY-MM-DD HH:mm:ss') }}
109
+ </template>
110
+
111
+ </template>
112
+ <!-- color -->
113
+ <template v-else-if="item.component=='color'">
114
+ <template v-if="item?.options?.name">
115
+ <el-color-picker disabled
116
+ v-model="form[item.name][item.options.name]" />
117
+ </template>
118
+ <template v-else>
119
+ <el-color-picker disabled
120
+ v-model="form[item.name]" />
121
+ </template>
122
+
123
+ </template>
124
+ <!-- rate -->
125
+ <template v-else-if="item.component=='rate'">
126
+ <template v-if="item?.options?.name">
127
+ <el-rate disabled
128
+ v-model="form[item.name][item.options.name]"></el-rate>
129
+ </template>
130
+ <template v-else>
131
+ <el-rate disabled
132
+ v-model="form[item.name]"></el-rate>
133
+ </template>
134
+ </template>
135
+ <!-- slider -->
136
+ <template v-else-if="item.component=='slider'">
137
+ <template v-if="item?.options?.name">
138
+ <el-slider disabled
139
+ v-model="form[item.name][item.options.name]"
140
+ :marks="item.options.marks"></el-slider>
141
+ </template>
142
+ <template v-else>
143
+ <el-slider disabled
144
+ v-model="form[item.name]"
145
+ :marks="item.options.marks"></el-slider>
146
+ </template>
147
+
148
+ </template>
149
+
150
+ <!-- tags -->
151
+ <template v-else-if="item.component=='tags'">
152
+ <div class="tags-list">
153
+ <template v-if="item?.options?.name">
154
+ <el-tag v-for="tag in form[item.name][item?.options?.name]"
155
+ :key="tag">
156
+ {{ tag }}
157
+ </el-tag>
158
+
159
+ </template>
160
+ <template v-else>
161
+ <el-tag v-for="tag in form[item.name]"
162
+ :key="tag">
163
+ {{ tag }}
164
+ </el-tag>
165
+ </template>
166
+
167
+ </div>
168
+ </template>
169
+
170
+ <!-- 没有组件是component值 就是插槽名称 -->
171
+ <template v-else>
172
+ <slot :name="item.component">
173
+ <el-tag type="danger">[{{item.component}}]
174
+ 没有这个默认组件也未自定义插槽内容</el-tag>
175
+ </slot>
176
+ </template>
177
+ <div v-if="item.message"
178
+ class="el-form-item-msg">{{item.message}}</div>
179
+ </el-descriptions-item>
180
+ </template>
181
+ </template>
182
+
183
+ </el-descriptions>
184
+ </template>
185
+
186
+ <script>
187
+ import lwUpload from '../lwUpload'
188
+ import textToPassword from './textToPassword'
189
+ import dayjs from 'dayjs'
190
+ export default {
191
+ components: {
192
+ lwUpload,
193
+ textToPassword
194
+ },
195
+ props: {
196
+ modelValue: { type: Object, default: () => { } },
197
+ config: { type: Object, default: () => { } },
198
+ loading: { type: Boolean, default: false },
199
+ isView: { type: Boolean, default: false },
200
+ },
201
+ data() {
202
+ return {
203
+ form: {},
204
+ tagValue: '',
205
+ tagVisible: false,
206
+ renderLoading: false
207
+ }
208
+ },
209
+ watch: {
210
+ modelValue() {
211
+ if (this.hasConfig) {
212
+ this.deepMerge(this.form, JSON.parse(JSON.stringify(this.modelValue)))
213
+ }
214
+ },
215
+ config() {
216
+ this.render()
217
+ },
218
+ form: {
219
+ handler(val) {
220
+ this.$emit("update:modelValue", val)
221
+ },
222
+ deep: true
223
+ }
224
+ },
225
+ computed: {
226
+ hasConfig() {
227
+ return Object.keys(this.config).length > 0
228
+ },
229
+ hasValue() {
230
+ return Object.keys(this.modelValue).length > 0
231
+ },
232
+
233
+ },
234
+ mounted() {
235
+ if (this.hasConfig) {
236
+ this.render()
237
+ }
238
+ },
239
+ methods: {
240
+ //构建form对象
241
+ render() {
242
+ this.form = {}
243
+ this.config.formItems.forEach((item) => {
244
+ if (item.component == 'checkbox' || item.component == 'upload') {
245
+ if (item.name) {
246
+ const value = {}
247
+ item.options.items.forEach((option) => {
248
+ value[option.name] = option.value
249
+ })
250
+ this.form[item.name] = value
251
+ } else if (item?.options?.items) {
252
+ item.options.items.forEach((option) => {
253
+ this.form[option.name] = option.value
254
+ })
255
+ }
256
+ } else {
257
+ if (item?.options?.name) {
258
+ if (!this.form[item.name]) {
259
+ this.form[item.name] = {}
260
+ }
261
+ this.form[item.name][item?.options?.name] = item.value
262
+ } else if (item.name) {
263
+ this.form[item.name] = item.value
264
+ }
265
+
266
+ }
267
+ })
268
+
269
+ if (this.hasValue) {
270
+ this.form = this.deepMerge(this.form, this.modelValue)
271
+ }
272
+ },
273
+ //合并深结构对象
274
+ deepMerge(obj1, obj2) {
275
+ for (let key in obj2) {
276
+ if (obj2.hasOwnProperty(key)) {
277
+ // 确保 obj1[key] 和 obj2[key] 不是 null 或 undefined
278
+ const isObj1Valid = obj1[key] !== null && obj1[key] !== undefined;
279
+ const isObj2Valid = obj2[key] !== null && obj2[key] !== undefined;
280
+
281
+ if (
282
+ isObj1Valid &&
283
+ typeof obj1[key] === "object" &&
284
+ !Array.isArray(obj1[key]) &&
285
+ isObj2Valid &&
286
+ typeof obj2[key] === "object" &&
287
+ !Array.isArray(obj2[key])
288
+ ) {
289
+ obj1[key] = this.deepMerge(obj1[key], obj2[key]);
290
+ } else {
291
+
292
+ if (isObj2Valid) {
293
+ obj1[key] = obj2[key];
294
+ } else if (!isObj2Valid) {
295
+ delete obj1[key];
296
+ }
297
+ }
298
+ }
299
+ }
300
+ return obj1;
301
+ },
302
+ //处理动态隐藏
303
+ hideHandle(item) {
304
+ if (typeof item.hideHandle === 'string') {
305
+ // eslint-disable-next-line no-eval
306
+ const exp = eval(item.hideHandle.replace(/\$/g, "this.form"))
307
+ return exp
308
+ } else if (typeof item.hideHandle === 'boolean') {
309
+ return item.hideHandle
310
+ }
311
+ return false
312
+ },
313
+ //处理动态必填
314
+ rulesHandle(item) {
315
+ if (item.requiredHandle) {
316
+ // eslint-disable-next-line no-eval
317
+ const exp = eval(item.requiredHandle.replace(/\$/g, "this.form"))
318
+ var requiredRule = item.rules.find(t => 'required' in t)
319
+ requiredRule.required = exp
320
+ }
321
+ return item.rules
322
+ },
323
+ // key to label
324
+ getKeyToLabel(val, items = []) {
325
+ let item = items.find(item => { return item.value == val })
326
+ return item?.label || '--'
327
+ },
328
+ dayjs: dayjs
329
+ }
330
+ }
331
+ </script>
332
+ <style lang="scss" scoped>
333
+ .button-new-tag {
334
+ margin-left: 10px;
335
+ }
336
+ .w-20 {
337
+ width: 100px;
338
+ margin-left: 10px;
339
+ }
340
+ .title-name {
341
+ font-size: 18px;
342
+ font-weight: bold;
343
+ margin-bottom: 10px;
344
+ }
345
+ .title-item {
346
+ color: #7c7c7c;
347
+ }
348
+
349
+ </style>
@@ -0,0 +1,49 @@
1
+ <template>
2
+ <span class="item-text">
3
+ <!-- 根据加密状态显示加密或解密后的文本 -->
4
+ <span>{{ isEncrypted ? encryptedText : modelValue }}</span>
5
+ <!-- 切换加密/解密按钮 -->
6
+ <el-button v-if="password"
7
+ link
8
+ type="primary"
9
+ icon="el-icon-view"
10
+ @click="toggleEncryption"></el-button>
11
+ </span>
12
+ </template>
13
+
14
+ <script>
15
+ export default {
16
+ props: {
17
+ modelValue: { type: String, default: '' }, // 传入的字符串
18
+ password: { type: Boolean, default: false }, // 是否需要加密显示
19
+ },
20
+ data() {
21
+ return {
22
+ isEncrypted: this.password, // 根据传入的 password 值初始化加密状态
23
+ };
24
+ },
25
+ computed: {
26
+ encryptedText() {
27
+ // 将输入字符串加密成 *,长度与原字符串相同
28
+ return "*".repeat(this.modelValue.length);
29
+ },
30
+ },
31
+ methods: {
32
+ toggleEncryption() {
33
+ // 切换加密和解密状态
34
+ this.isEncrypted = !this.isEncrypted;
35
+ // 如果是解密状态,可以更新父组件的值
36
+ if (!this.isEncrypted) {
37
+ this.$emit('update:modelValue', this.modelValue);
38
+ }
39
+ },
40
+ },
41
+ };
42
+ </script>
43
+ <style lang="scss" scoped>
44
+ .item-text {
45
+ display: inline-flex;
46
+ gap: 10px;
47
+ align-items: center;
48
+ }
49
+ </style>