vue2-client 1.20.20 → 1.20.21

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue2-client",
3
- "version": "1.20.20",
3
+ "version": "1.20.21",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "serve": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve --no-eslint",
@@ -2,32 +2,51 @@
2
2
  <a-card :bordered="false">
3
3
  <x-form-table
4
4
  title="示例表单"
5
- :queryParamsName="queryParamsName"
5
+ queryParamsName="scanCodeAndNFCRUD"
6
6
  :fixedAddForm="fixedAddForm"
7
7
  :externalSelectedRowKeys="selectedKeys"
8
+ :defaultPageSize="100"
9
+ :pageSizeArray="['100','200']"
8
10
  @action="action"
9
11
  @selectRow="selectRow"
10
12
  @columnClick="columnClick"
11
13
  @ceshi="ceshi"
12
- @rowDblClick="rowDblClick"
13
- :defaultPageSize="5"
14
- serviceName="af-revenue"
14
+ @startService="startService"
15
+ serviceName="af-safecheck"
15
16
  ref="xFormTable"
16
17
  :reserveSpaceForButtons="true"
17
- @addFormSubmit="addFormSubmit"
18
- ></x-form-table>
18
+ >
19
+ </x-form-table>
20
+ <a-modal
21
+ v-model="formModalVisible"
22
+ title="工单回访"
23
+ :zIndex="1002"
24
+ width="50vw"
25
+ :destroy-on-close="true"
26
+ @cancel="formModalVisible = false"
27
+ @ok="ok"
28
+ >
29
+ <x-add-native-form
30
+ ref="xForm"
31
+ />
32
+ </a-modal>
33
+ <button @click="backDealData">提交</button>
19
34
  </a-card>
20
35
  </template>
21
36
 
22
37
  <script>
23
38
  import XFormTable from '@vue2-client/base-client/components/common/XFormTable/XFormTable.vue'
39
+ import XAddNativeForm from '@vue2-client/base-client/components/common/XAddNativeForm/XAddNativeForm.vue'
24
40
  import { microDispatch } from '@vue2-client/utils/microAppUtils'
41
+ import {getConfigByNameAsync, runLogic} from '@vue2-client/services/api/common'
42
+
25
43
  export default {
26
44
  name: 'Demo',
27
45
  components: {
28
- XFormTable
46
+ XFormTable,
47
+ XAddNativeForm,
29
48
  },
30
- data() {
49
+ data () {
31
50
  return {
32
51
  // 查询配置文件名
33
52
  queryParamsName: 'ceshiCRUD',
@@ -43,26 +62,32 @@ export default {
43
62
  selectedKeys: [],
44
63
  selected: {
45
64
  keys: [],
46
- rows: []
47
- }
65
+ rows: [],
66
+ },
67
+ formModalVisible: false,
48
68
  }
49
69
  },
50
-
51
70
  methods: {
52
- handleCustomQuery() {
53
- this.$refs.xFormTable.queryTable({
54
- uf_f_alias: 'XianFeng',
55
- uf_f_card_id: '10500030'
71
+ backDealData () {
72
+ this.$refs.xFormTable.$refs.xForm.backDealData().then(data => {
73
+ console.log('backDealData', data)
74
+ console.log('selected', this.$refs.xFormTable.$refs.xForm?.form)
56
75
  })
57
76
  },
58
- rowDblClick(record) {
59
- console.log('rowDblClick', record)
60
- },
61
77
  // input框 行編輯參數傳遞
62
- ceshi(...args) {
78
+ ceshi (...args) {
63
79
  // attr, value, currentRecord, currentIndex, nextRecord, nextIndex
64
- const [attr, value, currentRecord, currentIndex, nextRecord, nextIndex] = args
65
- console.log('ceshi', attr, value, currentRecord, currentIndex, nextRecord, nextIndex)
80
+ const [attr, value, currentRecord, currentIndex, nextRecord, nextIndex] =
81
+ args
82
+ console.log(
83
+ 'ceshi',
84
+ attr,
85
+ value,
86
+ currentRecord,
87
+ currentIndex,
88
+ nextRecord,
89
+ nextIndex
90
+ )
66
91
  // 示例:当按下 Enter 键且有下一行时,跳转到下一行的同一列
67
92
  // 可以在这里执行业务逻辑(例如:保存数据)
68
93
  console.log('当前行:', currentIndex, '下一行:', nextIndex)
@@ -73,44 +98,61 @@ export default {
73
98
  // 跳转到下一行的同一列
74
99
  this.$refs.xFormTable.$refs.xTable.focusInput(nextIndex, attr.model)
75
100
  },
76
- test() {
101
+ test () {
77
102
  this.$refs.xFormTable.setTableData([])
78
103
  },
79
- defaultF() {
104
+ defaultF () {
80
105
  this.$refs.xFormTable.setTableSize('default')
81
106
  },
82
- middleF() {
107
+ middleF () {
83
108
  this.$refs.xFormTable.setTableSize('middle')
84
109
  },
85
- smallF() {
110
+ smallF () {
86
111
  this.$refs.xFormTable.setTableSize('small')
87
112
  },
88
- columnClick(key, value, record) {
113
+ columnClick (key, value, record) {
89
114
  microDispatch({
90
115
  type: 'v3route',
91
116
  path: '/bingliguanli/dianzibingliluru',
92
- props: { selected: arguments[0].his_f_admission_id }
117
+ props: { selected: arguments[0].his_f_admission_id },
93
118
  })
94
119
  },
95
- action(record, id, actionType) {
96
- this.detailVisible = true
97
- console.log('触发了详情操作', record, id, actionType)
120
+ startService (record, id, actionType) {
121
+ getConfigByNameAsync('测试Form', 'af-safecheck').then(config => {
122
+ this.formModalVisible = true
123
+ this.$nextTick(
124
+ () => {
125
+ this.formModalVisible = true
126
+ this.$refs.xForm.init({
127
+ formItems: config.formJson,
128
+ title: '工单回访',
129
+ businessType: '新增',
130
+ ...config,
131
+ modifyModelData: { data: { id: 1 } },
132
+ })
133
+ })
134
+ })
135
+ // this.detailVisible = true
136
+ // console.log('触发了详情操作', record, id, actionType)
137
+ },
138
+ async ok () {
139
+ const res = await this.$refs.xForm.asyncSubmit()
140
+ await runLogic('ceshwewei', res.realForm)
98
141
  },
99
- onClose() {
142
+ onClose () {
100
143
  this.detailVisible = false
101
144
  // 关闭详情之后重新查询表单
102
145
  this.$refs.xFormTable.refreshTable(true)
103
146
  },
104
- selectRow(selectedRowKeys, selectedRows) {
147
+ selectRow (selectedRowKeys, selectedRows) {
105
148
  this.selected = {
106
149
  keys: selectedRowKeys,
107
- rows: selectedRows
150
+ rows: selectedRows,
108
151
  }
152
+ console.log('selectedDemo', this.selected)
109
153
  },
110
- addFormSubmit(params, callback){
111
- callback()
112
- }
113
- }
154
+ },
155
+ computed: {},
114
156
  }
115
157
  </script>
116
158
 
@@ -79,9 +79,9 @@
79
79
  >
80
80
  <!-- 有 fileId 时通过 img 展示加载中/错误/图片 -->
81
81
  <template v-if="photo.fileId">
82
- <a-spin v-if="getThumbState(photo.fileId) === 'loading'" size="small" />
83
- <a-icon v-else-if="getThumbState(photo.fileId) === 'error'" type="picture" class="thumb-error-icon" />
84
- <img v-else :src="thumbUrlMap[photo.fileId]" :alt="photo.title || '照片'" />
82
+ <a-spin v-if="getThumbState(photo) === 'loading'" size="small" />
83
+ <a-icon v-else-if="getThumbState(photo) === 'error'" type="picture" class="thumb-error-icon" />
84
+ <img v-else :src="thumbUrlMap[thumbCacheKey(photo)]" :alt="photo.title || '照片'" />
85
85
  </template>
86
86
  <!-- 直接有 url 时展示 -->
87
87
  <img v-else-if="photo.url" :src="photo.url" :alt="photo.title || '照片'" />
@@ -162,7 +162,8 @@ export default {
162
162
  if (!this.currentPhoto) return ''
163
163
  if (this.currentPhoto.url) return this.currentPhoto.url
164
164
  if (this.currentPhoto.fileId) {
165
- return this.thumbUrlMap[this.currentPhoto.fileId] || ''
165
+ const key = this.thumbCacheKey(this.currentPhoto)
166
+ return this.thumbUrlMap[key] || ''
166
167
  }
167
168
  return ''
168
169
  },
@@ -184,37 +185,61 @@ export default {
184
185
  */
185
186
  preloadThumbnails () {
186
187
  if (!this.checkItems || !this.injectedServiceName) return
188
+ this.thumbUrlMap = {}
189
+ this.thumbStateMap = {}
187
190
  this.checkItems.forEach(category => {
188
191
  if (!category.items) return
189
192
  category.items.forEach(item => {
190
193
  if (!item.photos) return
191
194
  item.photos.forEach(photo => {
192
- if (photo.fileId && !this.thumbStateMap[photo.fileId]) {
193
- this.loadThumb(photo.fileId)
194
- }
195
+ if (photo.fileId) this.loadThumb(photo)
195
196
  })
196
197
  })
197
198
  })
198
199
  },
199
200
 
200
- async loadThumb (fileId) {
201
- this.$set(this.thumbStateMap, fileId, 'loading')
201
+ /**
202
+ * 缩略图缓存必须用字符串键。若用对象作 fileId,JS 会统一变成 "[object Object]",导致所有缩略图共用一张图。
203
+ * 优先使用业务侧已生成的 photo.id,其次从 fileId 上解析 id。
204
+ */
205
+ thumbCacheKey (photo) {
206
+ if (!photo) return ''
207
+ if (photo.id != null && photo.id !== '') return String(photo.id)
208
+ const raw = photo.fileId
209
+ if (raw == null || raw === '') return ''
210
+ if (typeof raw !== 'object') return String(raw)
211
+ const id = raw.id ?? raw.f_id
212
+ if (id != null && typeof id !== 'object') return String(id)
213
+ return JSON.stringify(raw)
214
+ },
215
+
216
+ async loadThumb (photo) {
217
+ const key = this.thumbCacheKey(photo)
218
+ if (!key || !photo.fileId) return
219
+ if (this.thumbStateMap[key] === 'loading' || this.thumbStateMap[key] === 'done') return
220
+ this.$set(this.thumbStateMap, key, 'loading')
202
221
  try {
203
222
  const svc = createFileImageService({ serviceName: this.injectedServiceName })
204
- const url = await svc.getImageUrl(fileId)
205
- this.$set(this.thumbUrlMap, fileId, url)
206
- this.$set(this.thumbStateMap, fileId, 'done')
207
- } catch {
208
- this.$set(this.thumbStateMap, fileId, 'error')
223
+ const url = await svc.getImageUrl(photo.fileId)
224
+ if (this.thumbStateMap[key] === 'loading') {
225
+ this.$set(this.thumbUrlMap, key, url)
226
+ this.$set(this.thumbStateMap, key, 'done')
227
+ }
228
+ } catch (e) {
229
+ console.warn(`[CheckItems] 加载缩略图失败 key=${key}:`, e.message)
230
+ if (this.thumbStateMap[key] === 'loading') {
231
+ this.$set(this.thumbStateMap, key, 'error')
232
+ }
209
233
  }
210
234
  },
211
235
 
212
- getThumbState (fileId) {
213
- return this.thumbStateMap[fileId] || 'loading'
236
+ getThumbState (photo) {
237
+ const key = this.thumbCacheKey(photo)
238
+ return this.thumbStateMap[key] || 'loading'
214
239
  },
215
240
 
216
241
  getPhotoKey (photo, index) {
217
- return photo.fileId || photo.id || index
242
+ return this.thumbCacheKey(photo) || photo.id || index
218
243
  },
219
244
 
220
245
  /**
@@ -112,6 +112,7 @@
112
112
 
113
113
  <script>
114
114
  import { FileImageGroup } from '@vue2-client/base-client/components/common/FileImage'
115
+ import { getConfigByNameAsync } from '@vue2-client/services/api/common'
115
116
 
116
117
  export default {
117
118
  name: 'HazardPhotos',
@@ -127,7 +128,51 @@ export default {
127
128
  default: () => []
128
129
  }
129
130
  },
131
+ data () {
132
+ return {
133
+ hazardLevelConfig: []
134
+ }
135
+ },
130
136
  methods: {
137
+ /**
138
+ * 加载隐患等级配置
139
+ */
140
+ async loadHazardLevelConfig () {
141
+ try {
142
+ const config = await getConfigByNameAsync('riskLevelConfig', 'af-system')
143
+ this.hazardLevelConfig = config?.riskLevel || []
144
+ } catch (e) {
145
+ console.warn('[HazardPhotos] 加载隐患等级配置失败:', e)
146
+ this.hazardLevelConfig = []
147
+ }
148
+ },
149
+
150
+ /**
151
+ * 获取隐患等级文本
152
+ * 优先使用 hazardLevelConfig(格式: [{value: "紧急隐患", result: "级别4"}, ...])
153
+ * 如果配置为空则使用默认映射
154
+ */
155
+ getHazardLevelText (level) {
156
+ // 优先使用配置的映射
157
+ if (this.hazardLevelConfig && this.hazardLevelConfig.length > 0) {
158
+ const item = this.hazardLevelConfig.find(r => r.value === level)
159
+ if (item) return item.result || level
160
+ }
161
+ // 配置为空时使用默认映射
162
+ const textMap = {
163
+ 紧急隐患: '紧急隐患',
164
+ 重大隐患: '重大隐患',
165
+ 中等隐患: '中等隐患',
166
+ 一般隐患: '一般隐患',
167
+ 其他隐患: '其他隐患',
168
+ urgent: '紧急隐患',
169
+ major: '重大隐患',
170
+ medium: '中等隐患',
171
+ minor: '一般隐患'
172
+ }
173
+ return textMap[level] || '其他隐患'
174
+ },
175
+
131
176
  /**
132
177
  * 获取Ant Design Vue Tag颜色
133
178
  */
@@ -161,32 +206,16 @@ export default {
161
206
  minor: 'info-circle'
162
207
  }
163
208
  return iconMap[level] || 'warning'
164
- },
165
-
166
- /**
167
- * 获取隐患等级文本
168
- */
169
- getHazardLevelText (level) {
170
- const textMap = {
171
- 紧急隐患: '紧急隐患',
172
- 重大隐患: '重大隐患',
173
- 中等隐患: '中等隐患',
174
- 一般隐患: '一般隐患',
175
- 其他隐患: '其他隐患',
176
- urgent: '紧急隐患',
177
- major: '重大隐患',
178
- medium: '中等隐患',
179
- minor: '一般隐患'
180
- }
181
- return textMap[level] || '其他隐患'
182
209
  }
210
+ },
211
+ mounted() {
212
+ this.loadHazardLevelConfig()
183
213
  }
184
214
  }
185
215
  </script>
186
216
 
187
217
  <style lang="less" scoped>
188
218
  .hazard-photos {
189
- border: 1px solid #f0f0f0;
190
219
  border-radius: 8px;
191
220
  background: white;
192
221
  height: 100%;
@@ -424,9 +424,10 @@ class InspectionService {
424
424
  if (Array.isArray(item.value)) {
425
425
  item.value.forEach((pd, i) => {
426
426
  if (typeof pd === 'object' && (pd.id || pd.url)) {
427
+ const fileId = pd.id || pd
427
428
  photos.push({
428
429
  id: pd.id || `${item.itemname}_files_${i + 1}`,
429
- fileId: pd,
430
+ fileId,
430
431
  url: pd.url,
431
432
  title: item.itemname,
432
433
  description: pd.f_real_name || `${item.itemname} (${i + 1}/${item.value.length})`
@@ -436,9 +437,10 @@ class InspectionService {
436
437
  }
437
438
  } else if (Array.isArray(item.f_defect_paths) && item.f_defect_paths.length) {
438
439
  item.f_defect_paths.forEach((pd, i) => {
440
+ const fileId = typeof pd === 'object' ? (pd.id || pd) : pd
439
441
  photos.push({
440
- id: typeof pd === 'object' ? pd.id : pd,
441
- fileId: pd,
442
+ id: typeof pd === 'object' ? (pd.id || i) : pd,
443
+ fileId,
442
444
  title: item.itemname,
443
445
  description: `${item.itemname} - 隐患照片 ${i + 1}`
444
446
  })