af-mobile-client-vue3 1.6.49 → 1.6.51

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,7 +1,7 @@
1
1
  {
2
2
  "name": "af-mobile-client-vue3",
3
3
  "type": "module",
4
- "version": "1.6.49",
4
+ "version": "1.6.51",
5
5
  "packageManager": "pnpm@10.13.1",
6
6
  "description": "Vue + Vite component lib",
7
7
  "engines": {
@@ -149,52 +149,54 @@ const resultLabel = computed(() => {
149
149
  :is-link="$attrs.disabled === undefined"
150
150
  @click="showPopu($attrs.readonly)"
151
151
  />
152
- <VanPopup v-model:show="show" position="bottom">
153
- <div class="van-picker__toolbar">
154
- <button type="button" class="van-picker__cancel" @click="cancel">
155
- 取消
156
- </button>
157
- <div class="van-ellipsis van-picker__title">
158
- {{ $attrs.label }}
159
- </div>
160
- <button type="button" class="van-picker__confirm" @click="onConfirm">
161
- 确认
162
- </button>
163
- </div>
164
- <div class="x-multi-select-content">
165
- <VanSearch
166
- v-if="props.isSearch"
167
- v-model="searchVal"
168
- placeholder="搜索"
169
- @update:model-value="search"
170
- @cancel="search"
171
- />
172
- <div v-if="isLoading" class="loading-container">
173
- <div class="loading-text">
174
- 搜索中...
152
+ <VanPopup v-model:show="show" position="bottom" teleport="body" round>
153
+ <div class="x-multi-select-popup">
154
+ <div class="van-picker__toolbar">
155
+ <button type="button" class="van-picker__cancel" @click="cancel">
156
+ 取消
157
+ </button>
158
+ <div class="van-ellipsis van-picker__title">
159
+ {{ $attrs.label }}
175
160
  </div>
161
+ <button type="button" class="van-picker__confirm" @click="onConfirm">
162
+ 确认
163
+ </button>
176
164
  </div>
177
- <div v-else class="x-multi-select-checkbox-group">
178
- <VanCell title="全选">
179
- <template #right-icon>
180
- <VanCheckbox v-model="checkedAll" name="all" @click="toggleAll" />
181
- </template>
182
- </VanCell>
183
- <VanCheckboxGroup ref="checkboxGroup" v-model="checkboxValue" @change="change">
184
- <VanCellGroup>
185
- <VanCell
186
- v-for="(item, index) in columnsData"
187
- :key="item[props.option.value]"
188
- :title="item[props.option.text]"
189
- clickable
190
- @click="toggle(item, index)"
191
- >
192
- <template #right-icon>
193
- <VanCheckbox ref="checkboxes" :name="item[props.option.value]" @click.stop />
194
- </template>
195
- </VanCell>
196
- </VanCellGroup>
197
- </VanCheckboxGroup>
165
+ <div class="x-multi-select-content">
166
+ <VanSearch
167
+ v-if="props.isSearch"
168
+ v-model="searchVal"
169
+ placeholder="搜索"
170
+ @update:model-value="search"
171
+ @cancel="search"
172
+ />
173
+ <div v-if="isLoading" class="loading-container">
174
+ <div class="loading-text">
175
+ 搜索中...
176
+ </div>
177
+ </div>
178
+ <div v-else class="x-multi-select-checkbox-group">
179
+ <VanCell title="全选">
180
+ <template #right-icon>
181
+ <VanCheckbox v-model="checkedAll" name="all" @click="toggleAll" />
182
+ </template>
183
+ </VanCell>
184
+ <VanCheckboxGroup ref="checkboxGroup" v-model="checkboxValue" @change="change">
185
+ <VanCellGroup>
186
+ <VanCell
187
+ v-for="(item, index) in columnsData"
188
+ :key="item[props.option.value]"
189
+ :title="item[props.option.text]"
190
+ clickable
191
+ @click="toggle(item, index)"
192
+ >
193
+ <template #right-icon>
194
+ <VanCheckbox ref="checkboxes" :name="item[props.option.value]" @click.stop />
195
+ </template>
196
+ </VanCell>
197
+ </VanCellGroup>
198
+ </VanCheckboxGroup>
199
+ </div>
198
200
  </div>
199
201
  </div>
200
202
  </VanPopup>
@@ -213,12 +215,19 @@ const resultLabel = computed(() => {
213
215
  left: -8px;
214
216
  }
215
217
  .x-multi-select-content {
216
- max-height: 264px;
218
+ max-height: calc(70vh - 44px);
217
219
  overflow-y: auto;
218
220
  .x-multi-select-checkbox-group {
219
221
  padding: 0 16px;
220
222
  }
221
223
  }
224
+ .x-multi-select-popup {
225
+ max-height: 70vh;
226
+ padding-bottom: env(safe-area-inset-bottom);
227
+ overflow: hidden;
228
+ display: flex;
229
+ flex-direction: column;
230
+ }
222
231
  .loading-container {
223
232
  display: flex;
224
233
  justify-content: center;
@@ -197,7 +197,7 @@ onBeforeUnmount(() => {
197
197
  :border="props.border"
198
198
  @click="showPopu($attrs.readonly)"
199
199
  />
200
- <VanPopup v-model:show="show" position="bottom" teleport="body">
200
+ <VanPopup v-model:show="show" position="bottom" teleport="body" round>
201
201
  <div class="x-select-popup">
202
202
  <!-- 搜索框 -->
203
203
  <VanSearch
@@ -222,6 +222,23 @@ onBeforeUnmount(() => {
222
222
  </template>
223
223
 
224
224
  <style scoped>
225
+ .x-select-popup {
226
+ max-height: 70vh;
227
+ padding-bottom: env(safe-area-inset-bottom);
228
+ overflow: hidden;
229
+ display: flex;
230
+ flex-direction: column;
231
+ }
232
+
233
+ .x-select-popup :deep(.van-picker) {
234
+ flex: 1;
235
+ min-height: 0;
236
+ }
237
+
238
+ .x-select-popup :deep(.van-picker__columns) {
239
+ max-height: 40vh;
240
+ }
241
+
225
242
  .loading-container {
226
243
  display: flex;
227
244
  justify-content: center;
@@ -68,6 +68,15 @@ onMounted(buildPreviewUrl)
68
68
  position: relative;
69
69
  }
70
70
 
71
+ /* 透明遮罩:阻止 iframe 在点击悬浮按钮时抢夺事件 */
72
+ .preview-doc-container::after {
73
+ content: '';
74
+ position: absolute;
75
+ inset: 0;
76
+ z-index: 99;
77
+ pointer-events: none;
78
+ }
79
+
71
80
  .kk-loading {
72
81
  position: absolute;
73
82
  inset: 0;
@@ -111,7 +111,7 @@ defineExpose({ init, download: handleDownload })
111
111
  <div class="file-preview-root">
112
112
  <!-- 悬浮下载按钮,定位在预览区右上角 -->
113
113
  <div v-if="rawUrl && !loading" class="preview-download-btn">
114
- <VanButton size="small" type="primary" plain icon="down" @click="handleDownload">
114
+ <VanButton size="small" type="primary" plain icon="down" @pointerdown.stop="handleDownload">
115
115
  下载
116
116
  </VanButton>
117
117
  </div>
@@ -186,7 +186,8 @@ defineExpose({ init, download: handleDownload })
186
186
  position: absolute;
187
187
  top: 10px;
188
188
  right: 12px;
189
- z-index: 10;
189
+ z-index: 100;
190
+ pointer-events: all;
190
191
  }
191
192
 
192
193
  .preview-loading {
@@ -2,7 +2,7 @@
2
2
  import XBadge from '@af-mobile-client-vue3/components/data/XBadge/index.vue'
3
3
  import XCellListFilter from '@af-mobile-client-vue3/components/data/XCellListFilter/index.vue'
4
4
  import { isDark } from '@af-mobile-client-vue3/composables/dark'
5
- import { getConfigByName, query } from '@af-mobile-client-vue3/services/api/common'
5
+ import { getConfigByName, getConfigByNameWithoutIndexedDB, query } from '@af-mobile-client-vue3/services/api/common'
6
6
  import useUserStore from '@af-mobile-client-vue3/stores/modules/user'
7
7
  import { getRangeByType } from '@af-mobile-client-vue3/utils/queryFormDefaultRangePicker'
8
8
  import { executeStrFunctionByContext } from '@af-mobile-client-vue3/utils/runEvalFunction'
@@ -239,110 +239,126 @@ onBeforeMount(() => {
239
239
  initComponent()
240
240
  })
241
241
 
242
- // 组件初始化
243
- function initComponent() {
244
- getConfigByName(configName, (result) => {
245
- groupFormItems.value = result
246
-
247
- // 数据主键名称
248
- primaryKey.value = result.primaryKey
249
- tableColumns.value = JSON.parse(JSON.stringify(result.columnJson))
250
- rowKey = getPrimaryKeyName()
251
-
252
- // 行样式函数
253
- rowStyleFunction.value = result?.rowStyleFunction
254
-
255
- title.value = result?.title
256
- const isQuery = result.createdQuery
257
- for (let i = 0; i < result.columnJson.length; i++) {
258
- const item = result.columnJson[i]
259
- item.span = item.flexSpan
260
- if (item.slotType === 'badge')
261
- item.dictName = item.slotKeyMap
262
-
263
- if (item.mobileColumnType === 'mobile_header_column') {
264
- mainColumns.value.push(item)
265
- }
266
- else if (item.mobileColumnType === 'mobile_subtitle_column') {
267
- subTitleColumns.value.push(item)
268
- }
269
- else if (item.mobileColumnType === 'mobile_details_column') {
270
- detailColumns.value.push(item)
271
- }
272
- else if (item.mobileColumnType === 'mobile_footer_column') {
273
- footColumns.value.push(item)
274
- }
275
- else if (item.mobileColumnType === 'mobile_tag_column') {
276
- tagList.value.push(item)
277
- }
278
- else if (item.slotType === 'action' && item.actionArr) {
279
- for (let j = 0; j < item.actionArr.length; j++) {
280
- allActions.value.push({
281
- text: item.actionArr[j].text,
282
- func: item.actionArr[j].func,
283
- customFunction: item.actionArr[j].customFunction,
284
- })
285
- }
242
+ function applyConfig(result: any) {
243
+ groupFormItems.value = result
244
+
245
+ // 数据主键名称
246
+ primaryKey.value = result.primaryKey
247
+ tableColumns.value = JSON.parse(JSON.stringify(result.columnJson))
248
+ rowKey = getPrimaryKeyName()
249
+
250
+ // 行样式函数
251
+ rowStyleFunction.value = result?.rowStyleFunction
252
+
253
+ title.value = result?.title
254
+ const isQuery = result.createdQuery
255
+ for (let i = 0; i < result.columnJson.length; i++) {
256
+ const item = result.columnJson[i]
257
+ item.span = item.flexSpan
258
+ if (item.slotType === 'badge')
259
+ item.dictName = item.slotKeyMap
260
+
261
+ if (item.mobileColumnType === 'mobile_header_column') {
262
+ mainColumns.value.push(item)
263
+ }
264
+ else if (item.mobileColumnType === 'mobile_subtitle_column') {
265
+ subTitleColumns.value.push(item)
266
+ }
267
+ else if (item.mobileColumnType === 'mobile_details_column') {
268
+ detailColumns.value.push(item)
269
+ }
270
+ else if (item.mobileColumnType === 'mobile_footer_column') {
271
+ footColumns.value.push(item)
272
+ }
273
+ else if (item.mobileColumnType === 'mobile_tag_column') {
274
+ tagList.value.push(item)
275
+ }
276
+ else if (item.slotType === 'action' && item.actionArr) {
277
+ for (let j = 0; j < item.actionArr.length; j++) {
278
+ allActions.value.push({
279
+ text: item.actionArr[j].text,
280
+ func: item.actionArr[j].func,
281
+ customFunction: item.actionArr[j].customFunction,
282
+ })
286
283
  }
284
+ }
287
285
 
288
- if (item.mobileColumnType === 'mobile_header_column') {
289
- try {
290
- if (typeof item.btnIcon === 'string') {
291
- // 字符串 => 直接作为数组的一项
292
- btnList.value = [item.btnIcon]
293
- }
294
- else if (Array.isArray(item.btnIcon)) {
295
- // 已经是数组 => 直接赋值
296
- btnList.value = item.btnIcon
297
- }
298
- // 其他类型不处理
286
+ if (item.mobileColumnType === 'mobile_header_column') {
287
+ try {
288
+ if (typeof item.btnIcon === 'string') {
289
+ // 字符串 => 直接作为数组的一项
290
+ btnList.value = [item.btnIcon]
299
291
  }
300
- catch (e) {
301
- console.error('btnIcon 处理异常:', e)
292
+ else if (Array.isArray(item.btnIcon)) {
293
+ // 已经是数组 => 直接赋值
294
+ btnList.value = item.btnIcon
302
295
  }
296
+ // 其他类型不处理
303
297
  }
304
-
305
- if (result.showSortIcon && item.sortable) {
306
- orderList.value.push({
307
- title: item.title,
308
- value: item.dataIndex,
309
- })
298
+ catch (e) {
299
+ console.error('btnIcon 处理异常:', e)
310
300
  }
311
301
  }
312
- configContent.value = result
313
- // 扁平化 type=group groupItems,保持顺序
314
- const flatFormJson = []
315
- result.formJson.forEach((item) => {
316
- if (item.type === 'group' && Array.isArray(item.groupItems)) {
317
- item.groupItems.forEach((groupItem) => {
318
- if (!groupItem.isOnlyAddOrEdit) {
319
- flatFormJson.push(groupItem)
320
- }
321
- })
322
- }
323
- else {
324
- if (!item.isOnlyAddOrEdit && item.type !== 'group') {
325
- flatFormJson.push(item)
302
+
303
+ if (result.showSortIcon && item.sortable) {
304
+ orderList.value.push({
305
+ title: item.title,
306
+ value: item.dataIndex,
307
+ })
308
+ }
309
+ }
310
+ configContent.value = result
311
+ // 扁平化 type=group 的 groupItems,保持顺序
312
+ const flatFormJson = []
313
+ result.formJson.forEach((item) => {
314
+ if (item.type === 'group' && Array.isArray(item.groupItems)) {
315
+ item.groupItems.forEach((groupItem) => {
316
+ if (!groupItem.isOnlyAddOrEdit) {
317
+ flatFormJson.push(groupItem)
326
318
  }
319
+ })
320
+ }
321
+ else {
322
+ if (!item.isOnlyAddOrEdit && item.type !== 'group') {
323
+ flatFormJson.push(item)
327
324
  }
328
- })
329
- formQueryList.value = flatFormJson
330
- console.log('formQueryList', formQueryList.value)
331
- if (result.buttonState) {
332
- buttonState.value = result.buttonState
333
- buttonPermissions.value = result.buttonPermissions
334
- if (buttonState.value.edit && buttonState.value.edit === true && (filterButtonPermissions('edit').state === false || ((filterButtonPermissions('edit').state === true && userState.f.resources.f_role_name.includes((filterButtonPermissions('edit').roleStr))))))
335
- allActions.value.push({ text: '修改', func: 'update' })
336
- if (buttonState.value.delete && buttonState.value.delete === true && (filterButtonPermissions('delete').state === false || ((filterButtonPermissions('delete').state === true && userState.f.resources.f_role_name.includes((filterButtonPermissions('delete').roleStr))))))
337
- allActions.value.push({ text: '删除', func: 'delete' })
338
325
  }
339
- splitArrayAt(allActions.value, 3)
326
+ })
327
+ formQueryList.value = flatFormJson
328
+ console.log('formQueryList', formQueryList.value)
329
+ if (result.buttonState) {
330
+ buttonState.value = result.buttonState
331
+ buttonPermissions.value = result.buttonPermissions
332
+ if (buttonState.value.edit && buttonState.value.edit === true && (filterButtonPermissions('edit').state === false || ((filterButtonPermissions('edit').state === true && userState.f.resources.f_role_name.includes((filterButtonPermissions('edit').roleStr))))))
333
+ allActions.value.push({ text: '修改', func: 'update' })
334
+ if (buttonState.value.delete && buttonState.value.delete === true && (filterButtonPermissions('delete').state === false || ((filterButtonPermissions('delete').state === true && userState.f.resources.f_role_name.includes((filterButtonPermissions('delete').roleStr))))))
335
+ allActions.value.push({ text: '删除', func: 'delete' })
336
+ }
337
+ splitArrayAt(allActions.value, 3)
340
338
 
341
- // 初始化条件参数(从表单默认值中获取)
342
- initConditionParams(result.formJson, isQuery)
339
+ // 初始化条件参数(从表单默认值中获取)
340
+ initConditionParams(result.formJson, isQuery)
343
341
 
344
- // 自定义操作按钮
345
- editButtonStateData.value = result.editButtonStateData
342
+ // 自定义操作按钮
343
+ editButtonStateData.value = result.editButtonStateData
344
+ }
345
+
346
+ // 组件初始化
347
+ function initComponent() {
348
+ getConfigByName(configName, (result) => {
349
+ if (!result) {
350
+ getConfigByNameWithoutIndexedDB(configName, serviceName).then((res) => {
351
+ if (!res) {
352
+ isError.value = true
353
+ return
354
+ }
355
+ applyConfig(res)
356
+ }).catch(() => {
357
+ isError.value = true
358
+ })
359
+ return
360
+ }
361
+ applyConfig(result)
346
362
  }, serviceName)
347
363
  }
348
364
 
@@ -1,168 +1,186 @@
1
- <script setup lang="ts">
2
- import {
3
- Field as VanField,
4
- Picker as VanPicker,
5
- Popup as VanPopup,
6
- Search as VanSearch,
7
- } from 'vant'
8
- import { computed, inject, onMounted, ref } from 'vue'
9
-
10
- const workflowHandleWrap: any = inject('workflowHandleWrap')
11
-
12
- const showPicker = ref(false)
13
-
14
- const showMultiplePicker = ref(false)
15
-
16
- const branchChargePersons = ref({})
17
-
18
- const isInit = ref(false)
19
-
20
- // 用于 filterOption 的本地输入缓存(vant 不自带 filter)
21
- const filterKeyword = ref('')
22
-
23
- const customFieldName = {
24
- text: 'label',
25
- value: 'value',
26
- }
27
-
28
- const selectedNode = ref(undefined)
29
-
30
- const selectedOptions = computed(() => {
31
- if (!selectedNode.value) {
32
- return []
33
- }
34
- return filterOptions(selectedNode.value.chargePersonOptions)
35
- })
36
-
37
- onMounted(() => {
38
- isInit.value = false
39
- if (workflowHandleWrap.branchNodes.value) {
40
- // 初始化初始值
41
- for (const node of workflowHandleWrap.branchNodes.value) {
42
- branchChargePersons.value[node.stepId] = {
43
- handler: '',
44
- handlerId: '',
45
- }
46
- }
47
- }
48
- isInit.value = true
49
- })
50
-
51
- function setBranchPersonValue(stepId, value, options, selectedOptions) {
52
- if (!stepId)
53
- return
54
- if (!workflowHandleWrap.branchChargePersons.value) {
55
- workflowHandleWrap.branchChargePersons.value = {}
56
- }
57
- if (!workflowHandleWrap.branchChargePersons.value[stepId]) {
58
- workflowHandleWrap.branchChargePersons.value[stepId] = {}
59
- }
60
- if (workflowHandleWrap.branchChargePersons.value[stepId]) {
61
- branchChargePersons.value[stepId] = {
62
- handler: options.find(item => item.value === value)?.label,
63
- handlerId: value,
64
- }
65
- Object.assign(workflowHandleWrap.branchChargePersons.value[stepId], branchChargePersons.value[stepId])
66
- }
67
- workflowHandleWrap.checkedNextStepPerson.value = selectedOptions[0].value
68
- workflowHandleWrap.checkedNextStepPersonName.value = selectedOptions[0].label
69
- }
70
-
71
- function getBranchSelectionLabel() {
72
- if (workflowHandleWrap.needMultipleBranchSelection.value) {
73
- return '分支处理人'
74
- }
75
- else if (workflowHandleWrap.calculatedTargetNode.value) {
76
- return `${workflowHandleWrap.getStepNameByStepId(workflowHandleWrap.calculatedTargetNode.value)}处理人`
77
- }
78
- else {
79
- return '处理人'
80
- }
81
- }
82
-
83
- // vant 没有原生 filter-option,因此需要本地筛选
84
- function filterOptions(options) {
85
- if (!filterKeyword.value)
86
- return options
87
- return options.filter(option => option.label.toLowerCase().includes(filterKeyword.value.toLowerCase()))
88
- }
89
-
90
- // 搜索回调函数
91
- function search(val: string) {
92
- filterKeyword.value = val || ''
93
- }
94
- </script>
95
-
96
- <template>
97
- <div v-if="workflowHandleWrap.isNeedSelectPerson.value && isInit">
98
- <!-- 多分支选择 -->
99
- <template v-if="workflowHandleWrap.needMultipleBranchSelection.value && workflowHandleWrap.branchNodes.value.length > 0">
100
- <template v-for="node in workflowHandleWrap.branchNodes.value" :key="node.stepId">
101
- <VanField
102
- v-model="branchChargePersons[node.stepId].handler"
103
- :label="`${node.stepName}处理人`"
104
- is-link
105
- clickable
106
- required
107
- placeholder="请选择处理人"
108
- @click="selectedNode = node; showMultiplePicker = true;"
109
- />
110
- </template>
111
- <VanPopup v-model:show="showMultiplePicker" position="bottom">
112
- <!-- 搜索框 -->
113
- <VanSearch
114
- v-model="filterKeyword"
115
- placeholder="搜索"
116
- @clear="() => search('')"
117
- @update:model-value="search"
118
- />
119
- <VanPicker
120
- :columns="selectedOptions"
121
- :columns-field-names="customFieldName"
122
- value-key="label"
123
- @confirm="(val) => {
124
- setBranchPersonValue(selectedNode.stepId, val.selectedValues[0], selectedNode.chargePersonOptions, val.selectedOptions)
125
- showMultiplePicker = false;
126
- }"
127
- @cancel="showMultiplePicker = false;"
128
- />
129
- </VanPopup>
130
- </template>
131
-
132
- <!-- 单分支选择 -->
133
- <template v-else>
134
- <VanField
135
- v-model="workflowHandleWrap.checkedNextStepPersonName.value"
136
- :label="getBranchSelectionLabel()"
137
- label-width="auto"
138
- is-link
139
- clickable
140
- required
141
- placeholder="请选择处理人"
142
- @click="showPicker = true"
143
- />
144
- <VanPopup v-model:show="showPicker" position="bottom">
145
- <!-- 搜索框 -->
146
- <VanSearch
147
- v-model="filterKeyword"
148
- placeholder="搜索"
149
- @clear="() => search('')"
150
- @update:model-value="search"
151
- />
152
- <VanPicker
153
- :columns="filterOptions(workflowHandleWrap.nextStepPersonOptions.value)"
154
- :columns-field-names="customFieldName"
155
- @confirm="(val) => {
156
- setBranchPersonValue(workflowHandleWrap.calculatedTargetNode.value, val.selectedValues[0], workflowHandleWrap.nextStepPersonOptions.value, val.selectedOptions)
157
- showPicker = false;
158
- }"
159
- @cancel="showPicker = false;"
160
- />
161
- </VanPopup>
162
- </template>
163
- </div>
164
- </template>
165
-
166
- <style scoped>
167
- /* 保持你的样式或根据 vant 移动端自行优化 */
168
- </style>
1
+ <script setup lang="ts">
2
+ import {
3
+ Field as VanField,
4
+ Picker as VanPicker,
5
+ Popup as VanPopup,
6
+ Search as VanSearch,
7
+ } from 'vant'
8
+ import { computed, inject, onMounted, ref } from 'vue'
9
+
10
+ const workflowHandleWrap: any = inject('workflowHandleWrap')
11
+
12
+ const showPicker = ref(false)
13
+
14
+ const showMultiplePicker = ref(false)
15
+
16
+ const branchChargePersons = ref({})
17
+
18
+ const isInit = ref(false)
19
+
20
+ // 用于 filterOption 的本地输入缓存(vant 不自带 filter)
21
+ const filterKeyword = ref('')
22
+
23
+ const customFieldName = {
24
+ text: 'label',
25
+ value: 'value',
26
+ }
27
+
28
+ const selectedNode = ref(undefined)
29
+
30
+ const selectedOptions = computed(() => {
31
+ if (!selectedNode.value) {
32
+ return []
33
+ }
34
+ return filterOptions(selectedNode.value.chargePersonOptions)
35
+ })
36
+
37
+ onMounted(() => {
38
+ isInit.value = false
39
+ if (workflowHandleWrap.branchNodes.value) {
40
+ // 初始化初始值
41
+ for (const node of workflowHandleWrap.branchNodes.value) {
42
+ branchChargePersons.value[node.stepId] = {
43
+ handler: '',
44
+ handlerId: '',
45
+ }
46
+ }
47
+ }
48
+ isInit.value = true
49
+ })
50
+
51
+ function setBranchPersonValue(stepId, value, options, selectedOptions) {
52
+ if (!stepId)
53
+ return
54
+ if (!workflowHandleWrap.branchChargePersons.value) {
55
+ workflowHandleWrap.branchChargePersons.value = {}
56
+ }
57
+ if (!workflowHandleWrap.branchChargePersons.value[stepId]) {
58
+ workflowHandleWrap.branchChargePersons.value[stepId] = {}
59
+ }
60
+ if (workflowHandleWrap.branchChargePersons.value[stepId]) {
61
+ branchChargePersons.value[stepId] = {
62
+ handler: options.find(item => item.value === value)?.label,
63
+ handlerId: value,
64
+ }
65
+ Object.assign(workflowHandleWrap.branchChargePersons.value[stepId], branchChargePersons.value[stepId])
66
+ }
67
+ workflowHandleWrap.checkedNextStepPerson.value = selectedOptions[0].value
68
+ workflowHandleWrap.checkedNextStepPersonName.value = selectedOptions[0].label
69
+ }
70
+
71
+ function getBranchSelectionLabel() {
72
+ if (workflowHandleWrap.needMultipleBranchSelection.value) {
73
+ return '分支处理人'
74
+ }
75
+ else if (workflowHandleWrap.calculatedTargetNode.value) {
76
+ return `${workflowHandleWrap.getStepNameByStepId(workflowHandleWrap.calculatedTargetNode.value)}处理人`
77
+ }
78
+ else {
79
+ return '处理人'
80
+ }
81
+ }
82
+
83
+ // vant 没有原生 filter-option,因此需要本地筛选
84
+ function filterOptions(options) {
85
+ if (!filterKeyword.value)
86
+ return options
87
+ return options.filter(option => option.label.toLowerCase().includes(filterKeyword.value.toLowerCase()))
88
+ }
89
+
90
+ // 搜索回调函数
91
+ function search(val: string) {
92
+ filterKeyword.value = val || ''
93
+ }
94
+ </script>
95
+
96
+ <template>
97
+ <div v-if="workflowHandleWrap.isNeedSelectPerson.value && isInit">
98
+ <!-- 多分支选择 -->
99
+ <template v-if="workflowHandleWrap.needMultipleBranchSelection.value && workflowHandleWrap.branchNodes.value.length > 0">
100
+ <template v-for="node in workflowHandleWrap.branchNodes.value" :key="node.stepId">
101
+ <VanField
102
+ v-model="branchChargePersons[node.stepId].handler"
103
+ :label="`${node.stepName}处理人`"
104
+
105
+ clickable is-link required
106
+ placeholder="请选择处理人"
107
+ @click="selectedNode = node; showMultiplePicker = true;"
108
+ />
109
+ </template>
110
+ <VanPopup v-model:show="showMultiplePicker" position="bottom" teleport="body" round>
111
+ <div class="person-select-popup">
112
+ <VanSearch
113
+ v-model="filterKeyword"
114
+ placeholder="搜索"
115
+ @clear="() => search('')"
116
+ @update:model-value="search"
117
+ />
118
+ <VanPicker
119
+ show-toolbar
120
+ :columns="selectedOptions"
121
+ :columns-field-names="customFieldName"
122
+ value-key="label"
123
+ @confirm="(val) => {
124
+ setBranchPersonValue(selectedNode.stepId, val.selectedValues[0], selectedNode.chargePersonOptions, val.selectedOptions)
125
+ showMultiplePicker = false;
126
+ }"
127
+ @cancel="showMultiplePicker = false;"
128
+ />
129
+ </div>
130
+ </VanPopup>
131
+ </template>
132
+
133
+ <!-- 单分支选择 -->
134
+ <template v-else>
135
+ <VanField
136
+ v-model="workflowHandleWrap.checkedNextStepPersonName.value"
137
+ :label="getBranchSelectionLabel()"
138
+ label-width="auto"
139
+ is-link
140
+ clickable
141
+ required
142
+ placeholder="请选择处理人"
143
+ @click="showPicker = true"
144
+ />
145
+ <VanPopup v-model:show="showPicker" position="bottom" teleport="body" round>
146
+ <div class="person-select-popup">
147
+ <VanSearch
148
+ v-model="filterKeyword"
149
+ placeholder="搜索"
150
+ @clear="() => search('')"
151
+ @update:model-value="search"
152
+ />
153
+ <VanPicker
154
+ show-toolbar
155
+ :columns="filterOptions(workflowHandleWrap.nextStepPersonOptions.value)"
156
+ :columns-field-names="customFieldName"
157
+ @confirm="(val) => {
158
+ setBranchPersonValue(workflowHandleWrap.calculatedTargetNode.value, val.selectedValues[0], workflowHandleWrap.nextStepPersonOptions.value, val.selectedOptions)
159
+ showPicker = false;
160
+ }"
161
+ @cancel="showPicker = false;"
162
+ />
163
+ </div>
164
+ </VanPopup>
165
+ </template>
166
+ </div>
167
+ </template>
168
+
169
+ <style scoped>
170
+ .person-select-popup {
171
+ max-height: 70vh;
172
+ padding-bottom: env(safe-area-inset-bottom);
173
+ overflow: hidden;
174
+ display: flex;
175
+ flex-direction: column;
176
+ }
177
+
178
+ .person-select-popup :deep(.van-picker) {
179
+ flex: 1;
180
+ min-height: 0;
181
+ }
182
+
183
+ .person-select-popup :deep(.van-picker__columns) {
184
+ max-height: 40vh;
185
+ }
186
+ </style>
@@ -2,16 +2,17 @@
2
2
  import FilePreview from '@af-mobile-client-vue3/components/data/FilePreview/index.vue'
3
3
  import { onMounted, ref } from 'vue'
4
4
 
5
- const previewDocType = ref('docx')
5
+ const previewDocType = ref('xlsx')
6
6
  // /resource/af-revenue/word/62c684cd70ce4583aa1d6bf21164d465.doc
7
7
  // /resource/af-revenue/word/46a87ec0a05143f98061a1ba43f19ed2.docx
8
- const previewDocUrl = ref('/resource/af-revenue/word/62c684cd70ce4583aa1d6bf21164d465.doc')
8
+ // /resource/af-scada/excel/c284a70c064048369369f43fef405b4e.xlsx
9
+ const previewDocUrl = ref('/resource/af-scada/excel/c284a70c064048369369f43fef405b4e.xlsx')
9
10
 
10
11
  const filePreviewRef = ref<InstanceType<typeof FilePreview> | null>(null)
11
12
 
12
13
  onMounted(() => {
13
14
  filePreviewRef.value?.init({
14
- path: '/resource/af-revenue/word/62c684cd70ce4583aa1d6bf21164d465.doc',
15
+ path: '/resource/af-scada/excel/c284a70c064048369369f43fef405b4e.xlsx',
15
16
  })
16
17
  })
17
18
  </script>