af-mobile-client-vue3 1.3.95 → 1.3.97
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 +1 -1
- package/src/components/core/XMultiSelect/index.vue +41 -1
- package/src/components/core/XSelect/index.vue +238 -148
- package/src/components/data/XCellList/index.vue +1 -1
- package/src/components/data/XFormItem/index.vue +151 -3
- package/src/views/component/XCellListView/index.vue +2 -78
package/package.json
CHANGED
|
@@ -34,6 +34,14 @@ const props = defineProps({
|
|
|
34
34
|
type: Boolean,
|
|
35
35
|
default: true,
|
|
36
36
|
},
|
|
37
|
+
lazyLoad: { // 是否启用懒加载
|
|
38
|
+
type: String,
|
|
39
|
+
default: 'false',
|
|
40
|
+
},
|
|
41
|
+
onSearch: { // 懒加载时的搜索函数
|
|
42
|
+
type: Function,
|
|
43
|
+
default: null,
|
|
44
|
+
},
|
|
37
45
|
})
|
|
38
46
|
const emits = defineEmits(['input', 'confirm', 'change', 'cancel'])
|
|
39
47
|
const show = ref(false)
|
|
@@ -44,7 +52,24 @@ const checkedAll = ref(false)
|
|
|
44
52
|
const resultValue = defineModel()
|
|
45
53
|
const checkboxGroup = ref()
|
|
46
54
|
const checkboxes = ref()
|
|
55
|
+
const isLoading = ref(false)
|
|
47
56
|
function search(val) {
|
|
57
|
+
// 如果是懒加载模式
|
|
58
|
+
if (props.lazyLoad && props.lazyLoad === 'true' && props.onSearch) {
|
|
59
|
+
isLoading.value = true
|
|
60
|
+
// 调用父组件传递的搜索函数
|
|
61
|
+
props.onSearch(val).then((results) => {
|
|
62
|
+
columnsData.value = results || []
|
|
63
|
+
isLoading.value = false
|
|
64
|
+
}).catch((error) => {
|
|
65
|
+
console.error('懒加载搜索失败:', error)
|
|
66
|
+
columnsData.value = []
|
|
67
|
+
isLoading.value = false
|
|
68
|
+
})
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// 普通搜索模式
|
|
48
73
|
if (val) {
|
|
49
74
|
columnsData.value = props.columns.filter((item) => {
|
|
50
75
|
return item[props.option.text].includes(val)
|
|
@@ -140,7 +165,12 @@ const resultLabel = computed(() => {
|
|
|
140
165
|
@update:model-value="search"
|
|
141
166
|
@cancel="search"
|
|
142
167
|
/>
|
|
143
|
-
<div class="
|
|
168
|
+
<div v-if="isLoading" class="loading-container">
|
|
169
|
+
<div class="loading-text">
|
|
170
|
+
搜索中...
|
|
171
|
+
</div>
|
|
172
|
+
</div>
|
|
173
|
+
<div v-else class="x-multi-select-checkbox-group">
|
|
144
174
|
<VanCell title="全选">
|
|
145
175
|
<template #right-icon>
|
|
146
176
|
<VanCheckbox v-model="checkedAll" name="all" @click="toggleAll" />
|
|
@@ -185,6 +215,16 @@ const resultLabel = computed(() => {
|
|
|
185
215
|
padding: 0 16px;
|
|
186
216
|
}
|
|
187
217
|
}
|
|
218
|
+
.loading-container {
|
|
219
|
+
display: flex;
|
|
220
|
+
justify-content: center;
|
|
221
|
+
align-items: center;
|
|
222
|
+
height: 200px;
|
|
223
|
+
}
|
|
224
|
+
.loading-text {
|
|
225
|
+
color: #969799;
|
|
226
|
+
font-size: 14px;
|
|
227
|
+
}
|
|
188
228
|
//.van-popup {
|
|
189
229
|
// border-radius: 20px 20px 0 0;
|
|
190
230
|
//}
|
|
@@ -1,148 +1,238 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import {
|
|
3
|
-
Field as VanField,
|
|
4
|
-
Picker as VanPicker,
|
|
5
|
-
Popup as VanPopup,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
//
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
function
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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, defineEmits, defineModel, defineProps, onBeforeMount, ref, watch } from 'vue'
|
|
9
|
+
|
|
10
|
+
const props = defineProps({
|
|
11
|
+
columns: {
|
|
12
|
+
type: Array,
|
|
13
|
+
default() {
|
|
14
|
+
return []
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
option: {
|
|
18
|
+
type: Object,
|
|
19
|
+
default() {
|
|
20
|
+
return { text: 'label', value: 'value', children: 'children' }
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
offOption: { // 关闭option配置key-value;当数据是非集合的数组的时候,开启
|
|
24
|
+
type: Boolean,
|
|
25
|
+
default: false,
|
|
26
|
+
},
|
|
27
|
+
border: { // 是否展示边框
|
|
28
|
+
type: Boolean,
|
|
29
|
+
default: false,
|
|
30
|
+
},
|
|
31
|
+
lazyLoad: { // 是否启用懒加载
|
|
32
|
+
type: String,
|
|
33
|
+
default: 'false',
|
|
34
|
+
},
|
|
35
|
+
onSearch: { // 懒加载时的搜索函数
|
|
36
|
+
type: Function,
|
|
37
|
+
default: null,
|
|
38
|
+
},
|
|
39
|
+
})
|
|
40
|
+
const emits = defineEmits(['confirm', 'change', 'cancel', 'input'])
|
|
41
|
+
const show = ref(false)
|
|
42
|
+
const resultValue = defineModel()
|
|
43
|
+
const columnsData = ref([])
|
|
44
|
+
const selectedOption = ref([])
|
|
45
|
+
const searchValue = ref('')
|
|
46
|
+
const filteredColumns = ref([])
|
|
47
|
+
const isLoading = ref(false)
|
|
48
|
+
|
|
49
|
+
// 转换空children为空字符串
|
|
50
|
+
function transformColumns(data) {
|
|
51
|
+
return data.map((item) => {
|
|
52
|
+
if (item.children && item.children.length === 0) {
|
|
53
|
+
return {
|
|
54
|
+
...item,
|
|
55
|
+
children: '',
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else if (item.children && item.children.length !== 0) {
|
|
59
|
+
return { ...item, children: transformColumns(item.children) }
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
return { ...item }
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// 搜索过滤函数
|
|
68
|
+
function handleSearch(value) {
|
|
69
|
+
// 确保 value 是字符串
|
|
70
|
+
const searchText = typeof value === 'string' ? value : value?.target?.value || ''
|
|
71
|
+
searchValue.value = searchText
|
|
72
|
+
|
|
73
|
+
// 如果是懒加载模式
|
|
74
|
+
if (props.lazyLoad && props.lazyLoad === 'true' && props.onSearch) {
|
|
75
|
+
if (!searchText) {
|
|
76
|
+
filteredColumns.value = []
|
|
77
|
+
return
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
isLoading.value = true
|
|
81
|
+
// 调用父组件传递的搜索函数
|
|
82
|
+
props.onSearch(searchText).then((results) => {
|
|
83
|
+
filteredColumns.value = transformColumns(results || [])
|
|
84
|
+
isLoading.value = false
|
|
85
|
+
}).catch((error) => {
|
|
86
|
+
console.error('懒加载搜索失败:', error)
|
|
87
|
+
filteredColumns.value = []
|
|
88
|
+
isLoading.value = false
|
|
89
|
+
})
|
|
90
|
+
return
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// 普通搜索模式
|
|
94
|
+
if (!searchText) {
|
|
95
|
+
filteredColumns.value = columnsData.value
|
|
96
|
+
return
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const searchTextLower = searchText.toLowerCase()
|
|
100
|
+
|
|
101
|
+
filteredColumns.value = columnsData.value.filter((item) => {
|
|
102
|
+
const text = props.offOption ? item : item[props.option.text]
|
|
103
|
+
return text?.toString().toLowerCase().includes(searchTextLower)
|
|
104
|
+
})
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// 清空搜索
|
|
108
|
+
function handleSearchClear() {
|
|
109
|
+
searchValue.value = ''
|
|
110
|
+
if (props.lazyLoad) {
|
|
111
|
+
// 懒加载模式:清空搜索时重新获取初始数据
|
|
112
|
+
if (props.onSearch) {
|
|
113
|
+
props.onSearch('').then((results) => {
|
|
114
|
+
filteredColumns.value = transformColumns(results || [])
|
|
115
|
+
}).catch((error) => {
|
|
116
|
+
console.error('清空搜索后数据加载失败:', error)
|
|
117
|
+
filteredColumns.value = []
|
|
118
|
+
})
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
filteredColumns.value = columnsData.value
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
onBeforeMount(() => {
|
|
127
|
+
columnsData.value = transformColumns(props.columns)
|
|
128
|
+
filteredColumns.value = columnsData.value
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
const resultLabel = computed({
|
|
132
|
+
get() {
|
|
133
|
+
if (!resultValue.value)
|
|
134
|
+
return ''
|
|
135
|
+
const res = props.columns.filter((item) => {
|
|
136
|
+
const data = props.offOption ? item : item[props.option.value]
|
|
137
|
+
return data === resultValue.value
|
|
138
|
+
})
|
|
139
|
+
return res.length ? (props.offOption ? res[0] : res[0][props.option.text]) : ''
|
|
140
|
+
},
|
|
141
|
+
set() {
|
|
142
|
+
|
|
143
|
+
},
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
function onConfirm(value, _index) {
|
|
147
|
+
resultValue.value = props.offOption ? value.selectedValues : value.selectedValues[0]
|
|
148
|
+
// resultValue.value = value.selectedValues
|
|
149
|
+
selectedOption.value = value.selectedOptions
|
|
150
|
+
show.value = !show.value
|
|
151
|
+
emits('confirm', value.selectedValues[0], value.selectedOptions)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function change(val, index) {
|
|
155
|
+
emits('change', val, index, resultValue.value)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function cancel(val, index) {
|
|
159
|
+
show.value = !show.value
|
|
160
|
+
emits('cancel', val, index, resultValue.value)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function showPopu(disabled) {
|
|
164
|
+
if (disabled !== undefined && disabled !== false)
|
|
165
|
+
return false
|
|
166
|
+
columnsData.value = transformColumns(props.columns)
|
|
167
|
+
filteredColumns.value = columnsData.value
|
|
168
|
+
searchValue.value = '' // 重置搜索
|
|
169
|
+
show.value = !show.value
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
watch(() => resultValue, (newVal, _oldVal) => {
|
|
173
|
+
columnsData.value = transformColumns(props.columns)
|
|
174
|
+
filteredColumns.value = columnsData.value
|
|
175
|
+
emits('input', newVal)
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
// 监听 columns 变化
|
|
179
|
+
watch(() => props.columns, () => {
|
|
180
|
+
columnsData.value = transformColumns(props.columns)
|
|
181
|
+
filteredColumns.value = columnsData.value
|
|
182
|
+
searchValue.value = ''
|
|
183
|
+
}, { deep: true })
|
|
184
|
+
</script>
|
|
185
|
+
|
|
186
|
+
<template>
|
|
187
|
+
<VanField
|
|
188
|
+
v-model="resultLabel"
|
|
189
|
+
v-bind="$attrs"
|
|
190
|
+
readonly
|
|
191
|
+
:is-link="true"
|
|
192
|
+
:border="props.border"
|
|
193
|
+
@click="showPopu($attrs.readonly)"
|
|
194
|
+
/>
|
|
195
|
+
<VanPopup v-model:show="show" position="bottom">
|
|
196
|
+
<div class="x-select-popup">
|
|
197
|
+
<!-- 搜索框 -->
|
|
198
|
+
<VanSearch
|
|
199
|
+
v-model="searchValue"
|
|
200
|
+
placeholder="搜索"
|
|
201
|
+
@clear="handleSearchClear"
|
|
202
|
+
@input="handleSearch"
|
|
203
|
+
/>
|
|
204
|
+
|
|
205
|
+
<!-- 选择器 -->
|
|
206
|
+
<div v-if="isLoading" class="loading-container">
|
|
207
|
+
<div class="loading-text">
|
|
208
|
+
搜索中...
|
|
209
|
+
</div>
|
|
210
|
+
</div>
|
|
211
|
+
<VanPicker
|
|
212
|
+
v-else
|
|
213
|
+
v-bind="$attrs"
|
|
214
|
+
:columns="filteredColumns"
|
|
215
|
+
:columns-field-names="props.option"
|
|
216
|
+
show-toolbar
|
|
217
|
+
:value-key="props.option.text"
|
|
218
|
+
@cancel="cancel"
|
|
219
|
+
@confirm="onConfirm"
|
|
220
|
+
@change="change"
|
|
221
|
+
/>
|
|
222
|
+
</div>
|
|
223
|
+
</VanPopup>
|
|
224
|
+
</template>
|
|
225
|
+
|
|
226
|
+
<style scoped>
|
|
227
|
+
.loading-container {
|
|
228
|
+
display: flex;
|
|
229
|
+
justify-content: center;
|
|
230
|
+
align-items: center;
|
|
231
|
+
height: 200px;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.loading-text {
|
|
235
|
+
color: #969799;
|
|
236
|
+
font-size: 14px;
|
|
237
|
+
}
|
|
238
|
+
</style>
|
|
@@ -11,11 +11,13 @@ import { post } from '@af-mobile-client-vue3/services/restTools'
|
|
|
11
11
|
import { searchToListOption, searchToOption } from '@af-mobile-client-vue3/services/v3Api'
|
|
12
12
|
import { useUserStore } from '@af-mobile-client-vue3/stores/modules/user'
|
|
13
13
|
import { getDict } from '@af-mobile-client-vue3/utils/dictUtil'
|
|
14
|
+
import { mobileUtil } from '@af-mobile-client-vue3/utils/mobileUtil'
|
|
14
15
|
import { executeStrFunctionByContext } from '@af-mobile-client-vue3/utils/runEvalFunction'
|
|
15
16
|
import { areaList } from '@vant/area-data'
|
|
16
17
|
import dayjs from 'dayjs/esm/index'
|
|
17
18
|
import { debounce } from 'lodash-es'
|
|
18
19
|
import {
|
|
20
|
+
showToast,
|
|
19
21
|
Area as VanArea,
|
|
20
22
|
Button as VanButton,
|
|
21
23
|
Calendar as VanCalendar,
|
|
@@ -167,6 +169,8 @@ const showArea = ref(false)
|
|
|
167
169
|
const errorMessage = ref('')
|
|
168
170
|
const showTreeSelect = ref(false)
|
|
169
171
|
const treeValue = ref('')
|
|
172
|
+
// 懒加载 最后检索版本
|
|
173
|
+
let lastFetchId = ref(0)
|
|
170
174
|
|
|
171
175
|
// 登录信息 (可以在配置的动态函数中使用 this.setupState 获取到当前组件内的全部函数和变量 例:this.setupState.userState)
|
|
172
176
|
const userState = useUserStore().getLogin()
|
|
@@ -914,6 +918,136 @@ function findOptionInTree(options, value) {
|
|
|
914
918
|
|
|
915
919
|
return null
|
|
916
920
|
}
|
|
921
|
+
|
|
922
|
+
// 懒加载搜索函数
|
|
923
|
+
async function handleLazySearch(searchText: string) {
|
|
924
|
+
if (!attr.keyName || typeof attr.keyName !== 'string') {
|
|
925
|
+
return []
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
try {
|
|
929
|
+
// 如果是 search@ 类型的数据源
|
|
930
|
+
if (attr.keyName.includes('search@')) {
|
|
931
|
+
let source = attr.keyName.substring(7)
|
|
932
|
+
const userid = currUser.value
|
|
933
|
+
let roleName = 'roleName'
|
|
934
|
+
|
|
935
|
+
if (source.startsWith('根据角色[') && source.endsWith(']获取人员')) {
|
|
936
|
+
const startIndex = source.indexOf('[') + 1
|
|
937
|
+
const endIndex = source.indexOf(']', startIndex)
|
|
938
|
+
roleName = source.substring(startIndex, endIndex)
|
|
939
|
+
source = '根据角色获取人员'
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
const searchData = {
|
|
943
|
+
source,
|
|
944
|
+
userid,
|
|
945
|
+
roleName,
|
|
946
|
+
searchText, // 添加搜索关键词
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
return new Promise((resolve) => {
|
|
950
|
+
if (attr.type === 'select' || attr.type === 'checkbox') {
|
|
951
|
+
searchToListOption(searchData, (res) => {
|
|
952
|
+
// 根据搜索关键词过滤结果
|
|
953
|
+
const filtered = res.filter((item) => {
|
|
954
|
+
const text = item[columnsField.value.text] || item.label || ''
|
|
955
|
+
return text.toString().toLowerCase().includes(searchText.toLowerCase())
|
|
956
|
+
})
|
|
957
|
+
resolve(filtered)
|
|
958
|
+
})
|
|
959
|
+
}
|
|
960
|
+
else {
|
|
961
|
+
searchToOption(searchData, (res) => {
|
|
962
|
+
const filtered = res.filter((item) => {
|
|
963
|
+
const text = item[columnsField.value.text] || item.label || ''
|
|
964
|
+
return text.toString().toLowerCase().includes(searchText.toLowerCase())
|
|
965
|
+
})
|
|
966
|
+
resolve(filtered)
|
|
967
|
+
})
|
|
968
|
+
}
|
|
969
|
+
})
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
// logic 数据源
|
|
973
|
+
if (attr.keyName.includes('logic@')) {
|
|
974
|
+
const logicName = attr.keyName.substring(6)
|
|
975
|
+
const value = { word: searchText, ...userInfo.value }
|
|
976
|
+
|
|
977
|
+
// 调用logic前设置参数
|
|
978
|
+
if (getDataParams && getDataParams[attr.model]) {
|
|
979
|
+
Object.assign(value, getDataParams[attr.model])
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
lastFetchId.value ++
|
|
983
|
+
const fetchId = this.lastFetchId
|
|
984
|
+
// 根据搜索关键词过滤结果
|
|
985
|
+
const results = await runLogic(logicName, value, serviceName) as any
|
|
986
|
+
if (fetchId !== lastFetchId.value) {
|
|
987
|
+
return
|
|
988
|
+
}
|
|
989
|
+
if (searchText) {
|
|
990
|
+
return results.filter((item) => {
|
|
991
|
+
const text = item[columnsField.value.text] || item.label || ''
|
|
992
|
+
return text.toString().toLowerCase().includes(searchText.toLowerCase())
|
|
993
|
+
})
|
|
994
|
+
}
|
|
995
|
+
return results
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
// 自定义 js 函数
|
|
999
|
+
if (attr.keyName.includes('async ') || attr.keyName.includes('function ')) {
|
|
1000
|
+
const results = await executeStrFunctionByContext(currInst, attr.keyName, [
|
|
1001
|
+
{ ...props.form, searchText },
|
|
1002
|
+
runLogic,
|
|
1003
|
+
props.mode,
|
|
1004
|
+
getConfigByNameAsync,
|
|
1005
|
+
post,
|
|
1006
|
+
])
|
|
1007
|
+
// 根据搜索关键词过滤结果
|
|
1008
|
+
return results.filter((item) => {
|
|
1009
|
+
const text = item[columnsField.value.text] || item.label || ''
|
|
1010
|
+
return text.toString().toLowerCase().includes(searchText.toLowerCase())
|
|
1011
|
+
})
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
return []
|
|
1015
|
+
}
|
|
1016
|
+
catch (error) {
|
|
1017
|
+
console.error('懒加载搜索失败:', error)
|
|
1018
|
+
return []
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
// 扫码/NFC
|
|
1023
|
+
function scanCodeOrNfc(attr) {
|
|
1024
|
+
if (attr.type === 'scanCode') {
|
|
1025
|
+
// 扫码逻辑
|
|
1026
|
+
mobileUtil.execute({
|
|
1027
|
+
funcName: 'scanBarcode',
|
|
1028
|
+
param: {},
|
|
1029
|
+
callbackFunc: (res: any) => {
|
|
1030
|
+
console.log('让我看看你扫码结果:--', res)
|
|
1031
|
+
if (res && res.status === 'success') {
|
|
1032
|
+
if (res.data.status && res.data.status === 'cancelled') {
|
|
1033
|
+
showToast(res.data?.message || '扫码已取消')
|
|
1034
|
+
return
|
|
1035
|
+
}
|
|
1036
|
+
modelData.value = res.data?.rawValue
|
|
1037
|
+
showToast('扫码成功')
|
|
1038
|
+
}
|
|
1039
|
+
else {
|
|
1040
|
+
showToast('扫码失败')
|
|
1041
|
+
}
|
|
1042
|
+
},
|
|
1043
|
+
})
|
|
1044
|
+
}
|
|
1045
|
+
else if (attr.type === 'nfc') {
|
|
1046
|
+
// NFC逻辑
|
|
1047
|
+
console.log('--------NFC功能即将开发--------')
|
|
1048
|
+
showToast('NFC功能即将开发')
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
917
1051
|
</script>
|
|
918
1052
|
|
|
919
1053
|
<template>
|
|
@@ -983,7 +1117,7 @@ function findOptionInTree(options, value) {
|
|
|
983
1117
|
</VanField>
|
|
984
1118
|
<!-- 下拉 -->
|
|
985
1119
|
<XMultiSelect
|
|
986
|
-
v-if="attr.showMode === 'select' && mode === '查询'"
|
|
1120
|
+
v-if="(!attr.showMode || attr.showMode === 'select') && mode === '查询'"
|
|
987
1121
|
v-model="modelData"
|
|
988
1122
|
:label="labelData"
|
|
989
1123
|
:readonly="readonly"
|
|
@@ -993,6 +1127,8 @@ function findOptionInTree(options, value) {
|
|
|
993
1127
|
:option="attr.option ? attr.option : columnsField"
|
|
994
1128
|
:rules="[{ required: attr.rule.required === 'true', message: `请选择${attr.name}` }]"
|
|
995
1129
|
:required="attr.rule.required === 'true'"
|
|
1130
|
+
:lazy-load="attr.lazyLoad"
|
|
1131
|
+
:on-search="attr.lazyLoad ? handleLazySearch : null"
|
|
996
1132
|
/>
|
|
997
1133
|
</template>
|
|
998
1134
|
|
|
@@ -1297,6 +1433,8 @@ function findOptionInTree(options, value) {
|
|
|
1297
1433
|
:option="attr.option ? attr.option : columnsField"
|
|
1298
1434
|
:rules="[{ required: attr.rule.required === 'true', message: `请选择${attr.name}` }]"
|
|
1299
1435
|
:required="attr.rule.required === 'true'"
|
|
1436
|
+
:lazy-load="attr.lazyLoad"
|
|
1437
|
+
:on-search="attr.lazyLoad ? handleLazySearch : null"
|
|
1300
1438
|
/>
|
|
1301
1439
|
|
|
1302
1440
|
<!-- 文本区域 -->
|
|
@@ -1319,7 +1457,7 @@ function findOptionInTree(options, value) {
|
|
|
1319
1457
|
|
|
1320
1458
|
<!-- 文本输入框 -->
|
|
1321
1459
|
<VanField
|
|
1322
|
-
v-if="(attr.type === 'input' || attr.type === 'intervalPicker') && showItem"
|
|
1460
|
+
v-if="(attr.type === 'input' || attr.type === 'intervalPicker' || attr.type === 'scanCode' || attr.type === 'nfc') && showItem"
|
|
1323
1461
|
v-model="(modelData as string)"
|
|
1324
1462
|
style="align-items: center"
|
|
1325
1463
|
:label="labelData"
|
|
@@ -1346,7 +1484,7 @@ function findOptionInTree(options, value) {
|
|
|
1346
1484
|
@blur="() => formTypeCheck(attr, modelData as string)"
|
|
1347
1485
|
>
|
|
1348
1486
|
<VanButton
|
|
1349
|
-
v-if="!props.formReadonly && attr.inputOnAfterName && attr.inputOnAfterFunc && !attr.inputOnAfterName.includes('|')"
|
|
1487
|
+
v-if="(attr.type === 'input' || attr.type === 'intervalPicker') && !props.formReadonly && attr.inputOnAfterName && attr.inputOnAfterFunc && !attr.inputOnAfterName.includes('|')"
|
|
1350
1488
|
class="action-btn"
|
|
1351
1489
|
round
|
|
1352
1490
|
type="primary"
|
|
@@ -1355,6 +1493,16 @@ function findOptionInTree(options, value) {
|
|
|
1355
1493
|
>
|
|
1356
1494
|
{{ attr.inputOnAfterName }}
|
|
1357
1495
|
</VanButton>
|
|
1496
|
+
<VanButton
|
|
1497
|
+
v-if="(attr.type === 'scanCode' || attr.type === 'nfc') && !props.formReadonly"
|
|
1498
|
+
class="action-btn"
|
|
1499
|
+
round
|
|
1500
|
+
type="primary"
|
|
1501
|
+
size="small"
|
|
1502
|
+
@click="scanCodeOrNfc(attr)"
|
|
1503
|
+
>
|
|
1504
|
+
{{ attr.type === 'scanCode' ? '扫码' : 'NFC' }}
|
|
1505
|
+
</VanButton>
|
|
1358
1506
|
</template>
|
|
1359
1507
|
</VanField>
|
|
1360
1508
|
|
|
@@ -12,84 +12,8 @@ const router = useRouter()
|
|
|
12
12
|
// const idKey = ref('o_id')
|
|
13
13
|
|
|
14
14
|
// 简易crud表单测试
|
|
15
|
-
const configName = ref('
|
|
16
|
-
const serviceName = ref('af-
|
|
17
|
-
|
|
18
|
-
// 资源权限测试
|
|
19
|
-
// const configName = ref('crud_sources_test')
|
|
20
|
-
// const serviceName = ref('af-system')
|
|
21
|
-
|
|
22
|
-
// 实际业务测试
|
|
23
|
-
// const configName = ref('lngChargeAuditMobileCRUD')
|
|
24
|
-
// const serviceName = ref('af-gaslink')
|
|
25
|
-
|
|
26
|
-
// 跳转到详情页面
|
|
27
|
-
// function toDetail(item) {
|
|
28
|
-
// router.push({
|
|
29
|
-
// name: 'XCellDetailView',
|
|
30
|
-
// params: { id: item[idKey.value] }, // 如果使用命名路由,推荐使用路由参数而不是直接构建 URL
|
|
31
|
-
// query: {
|
|
32
|
-
// operName: item[operNameKey.value],
|
|
33
|
-
// method:item[methodKey.value],
|
|
34
|
-
// requestMethod:item[requestMethodKey.value],
|
|
35
|
-
// operatorType:item[operatorTypeKey.value],
|
|
36
|
-
// operUrl:item[operUrlKey.value],
|
|
37
|
-
// operIp:item[operIpKey.value],
|
|
38
|
-
// costTime:item[costTimeKey.value],
|
|
39
|
-
// operTime:item[operTimeKey.value],
|
|
40
|
-
//
|
|
41
|
-
// title: item[titleKey.value],
|
|
42
|
-
// businessType: item[businessTypeKey.value],
|
|
43
|
-
// status:item[statusKey.value]
|
|
44
|
-
// }
|
|
45
|
-
// })
|
|
46
|
-
// }
|
|
47
|
-
|
|
48
|
-
// 跳转到表单——以表单组来渲染纯表单
|
|
49
|
-
// function toDetail(item) {
|
|
50
|
-
// router.push({
|
|
51
|
-
// name: 'XFormGroupView',
|
|
52
|
-
// query: {
|
|
53
|
-
// id: item[idKey.value],
|
|
54
|
-
// // id: item.rr_id,
|
|
55
|
-
// // o_id: item.o_id,
|
|
56
|
-
// },
|
|
57
|
-
// })
|
|
58
|
-
// }
|
|
59
|
-
|
|
60
|
-
// 新增功能
|
|
61
|
-
// function addOption(totalCount) {
|
|
62
|
-
// router.push({
|
|
63
|
-
// name: 'XFormView',
|
|
64
|
-
// params: { id: totalCount, openid: totalCount },
|
|
65
|
-
// query: {
|
|
66
|
-
// configName: configName.value,
|
|
67
|
-
// serviceName: serviceName.value,
|
|
68
|
-
// mode: '新增',
|
|
69
|
-
// },
|
|
70
|
-
// })
|
|
71
|
-
// }
|
|
72
|
-
|
|
73
|
-
// 修改功能
|
|
74
|
-
// function updateRow(result) {
|
|
75
|
-
// router.push({
|
|
76
|
-
// name: 'XFormView',
|
|
77
|
-
// params: { id: result.o_id, openid: result.o_id },
|
|
78
|
-
// query: {
|
|
79
|
-
// configName: configName.value,
|
|
80
|
-
// serviceName: serviceName.value,
|
|
81
|
-
// mode: '修改',
|
|
82
|
-
// },
|
|
83
|
-
// })
|
|
84
|
-
// }
|
|
85
|
-
|
|
86
|
-
// 删除功能
|
|
87
|
-
// function deleteRow(result) {
|
|
88
|
-
// emit('deleteRow', result.o_id)
|
|
89
|
-
// }
|
|
90
|
-
// const fixQueryForm = ref({
|
|
91
|
-
// f_operator_id: '487184754014158848',
|
|
92
|
-
// })
|
|
15
|
+
const configName = ref('ceshiCRUD')
|
|
16
|
+
const serviceName = ref('af-linepatrol')
|
|
93
17
|
</script>
|
|
94
18
|
|
|
95
19
|
<template>
|