af-mobile-client-vue3 1.0.71 → 1.0.72

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.
@@ -42,6 +42,7 @@ const colFieldNames = {
42
42
  text: 'title',
43
43
  value: 'value',
44
44
  }
45
+
45
46
  // 查询条件参数 !!!!!建议最后点击确认的时候完成这个的整理
46
47
  const conditionParams = ref({})
47
48
 
@@ -139,7 +140,7 @@ onMounted(() => {
139
140
  </div>
140
141
  </VanCol>
141
142
  </VanRow>
142
- <XFormItem v-model="conditionParams[item.model]" :attr="item" :show-label="false" />
143
+ <XFormItem v-model="conditionParams[item.model]" :form='conditionParams' :attr="item" :show-label="false" />
143
144
  </template>
144
145
  </div>
145
146
  <div class="operations-panel">
@@ -4,9 +4,11 @@ import {
4
4
  CellGroup as VanCellGroup,
5
5
  Form as VanForm,
6
6
  } from 'vant'
7
+ import { useRoute } from 'vue-router'
7
8
  import type { FormInstance } from 'vant'
8
9
  import { computed, defineEmits, defineProps, onBeforeMount, reactive, ref, watch } from 'vue'
9
10
  import XFormItem from '@af-mobile-client-vue3/components/data/XFormItem/index.vue'
11
+ import NormalDataLayout from "@af-mobile-client-vue3/components/layout/NormalDataLayout/index.vue";
10
12
 
11
13
  interface FormItem {
12
14
  addOrEdit: string
@@ -34,6 +36,7 @@ const props = withDefaults(defineProps<{
34
36
  mode: '查询',
35
37
  submitButton: true,
36
38
  })
39
+ const route = useRoute()
37
40
  const emits = defineEmits(['onSubmit'])
38
41
  const formRef = ref<FormInstance>()
39
42
  const myFormItems = ref<FormItem[]>([])
@@ -141,11 +144,12 @@ defineExpose({ init, form, formGroupName, validate })
141
144
  </VanCellGroup>
142
145
  <div v-if="props.submitButton" style="margin: 16px;">
143
146
  <VanButton round block type="primary" native-type="submit">
144
- {{ props.groupFormItems.btnName ? props.groupFormItems.btnName : '提交' }}
147
+ {{ props.groupFormItems?.btnName ? props.groupFormItems.btnName : '提交' }}
145
148
  </VanButton>
146
149
  <slot />
147
150
  </div>
148
151
  </VanForm>
152
+
149
153
  </template>
150
154
 
151
155
  <style scoped>
@@ -26,7 +26,9 @@ import XGridDropOption from '@af-mobile-client-vue3/components/core/XGridDropOpt
26
26
  import type { Numeric } from 'vant/es/utils'
27
27
  import { getDict } from '@af-mobile-client-vue3/utils/dictUtil'
28
28
  import { executeStrFunctionByContext } from '@af-mobile-client-vue3/utils/runEvalFunction'
29
+ import { type UserInfo, useUserStore } from '@af-mobile-client-vue3/stores/modules/user'
29
30
  import { debounce } from 'lodash-es'
31
+ import { searchToListOption, searchToOption } from '@af-mobile-client-vue3/services/v3Api'
30
32
 
31
33
  const props = defineProps({
32
34
  attr: {
@@ -82,6 +84,10 @@ const props = defineProps({
82
84
 
83
85
  })
84
86
 
87
+ // 判断并初始化防抖函数
88
+ let debouncedUserLinkFunc: Function | null = null;
89
+ let debouncedDepLinkFunc: Function | null = null;
90
+
85
91
  const emits = defineEmits(['update:modelValue'])
86
92
  const { attr, form, mode, serviceName, getDataParams, columnsField } = props
87
93
  const calendarShow = ref(false)
@@ -94,6 +100,7 @@ const showPicker = ref(false)
94
100
  const showDatePicker = ref(false)
95
101
  const showTimePicker = ref(false)
96
102
  const showArea = ref(false)
103
+ const currUser = computed(() => userState.f.resources.id)
97
104
  // 是否展示当前项
98
105
  const showItem = ref(true)
99
106
 
@@ -169,6 +176,12 @@ onBeforeMount(() => {
169
176
  init()
170
177
  showFormItemFunc()
171
178
  dataChangeFunc()
179
+ if (attr?.keyName?.toString()?.startsWith('search@根据表单项[') && attr?.keyName?.toString().endsWith(']联动人员')) {
180
+ debouncedUserLinkFunc = debounce(() => updateResOptions('人员'), 200)
181
+ }
182
+ if (attr?.keyName?.toString()?.startsWith('search@根据表单项[') && attr?.keyName?.toString().endsWith(']联动部门')) {
183
+ debouncedDepLinkFunc = debounce(() => updateResOptions('部门'), 200)
184
+ }
172
185
  })
173
186
  // 是否展示表单左侧label文字
174
187
  const labelData = computed(() => {
@@ -186,6 +199,7 @@ const placeholder = computed(() => {
186
199
  return attr.placeholder ? attr.placeholder : `请选择${attr.name}`
187
200
  })
188
201
  // 登录信息 (可以在配置的动态函数中使用 this.setupState 获取到当前组件内的全部函数和变量 例:this.setupState.userState)
202
+ const userState = useUserStore().getLogin()
189
203
 
190
204
  const formatDate = date => `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`
191
205
 
@@ -208,13 +222,64 @@ function init() {
208
222
  if (result)
209
223
  option.value = result
210
224
  }, serviceName)
211
- }
212
- else {
225
+ } else if (attr.keyName && attr.keyName.includes('search@')) {
226
+ let source = attr.keyName.substring(7)
227
+ const userid = currUser.value
228
+ let roleName = 'roleName'
229
+ if (source.startsWith('根据角色[') && source.endsWith(']获取人员')) {
230
+ const startIndex = source.indexOf('[') + 1
231
+ const endIndex = source.indexOf(']',startIndex)
232
+ roleName = source.substring(startIndex, endIndex)
233
+ source = '根据角色获取人员'
234
+ }
235
+ const searchData = { source, userid, roleName }
236
+ if (source.startsWith('根据表单项[') && source.endsWith(']联动人员')) {
237
+ updateResOptions('人员')
238
+ } else if (source.startsWith('根据表单项[') && source.endsWith(']联动部门')) {
239
+ updateResOptions('部门')
240
+ } else if (attr.type === 'select' || attr.type === 'checkbox') {
241
+ searchToListOption(searchData,res => getDataCallback(res))
242
+ } else {
243
+ searchToOption(searchData,res => getDataCallback(res))
244
+ }
245
+ } else {
213
246
  initRadioValue()
214
247
  }
215
248
  }
216
249
  }
217
250
 
251
+ function getDataCallback (res) {
252
+ option.value = res
253
+ if (attr.type === 'radio') {
254
+ initRadioValue()
255
+ }
256
+ }
257
+
258
+ async function updateResOptions (type) {
259
+ if (attr?.keyName?.toString()?.startsWith('search@根据表单项[') && attr?.keyName?.toString()?.endsWith(`]联动${type}`)){
260
+ const searchData = {source: `获取${type}`, userid: currUser.value}
261
+ const startIndex = attr.keyName.indexOf('[') + 1
262
+ const endIndex = attr.keyName.indexOf(']',startIndex)
263
+ const formModel = attr.keyName.substring(startIndex, endIndex).replace('.','_')
264
+ // console.log(form)
265
+ const formModelData = form[formModel]
266
+ if (formModel?.length && formModelData?.length){
267
+ await searchToListOption(searchData,res => {
268
+ // console.log(res)
269
+ // console.log(form)
270
+ getDataCallback(res.filter(h => {
271
+ return formModelData['0'] === h.f_organization_id || formModelData['0'] === h.f_department_id || formModelData['0'] === h.parentid
272
+ // if (formModel.indexOf('org') > -1) {
273
+ // return formModelData?.includes(h.orgid || h.f_organization_id || h.parentid)
274
+ // } else {
275
+ // return formModelData?.includes(h?.parentid)
276
+ // }
277
+ }))
278
+ })
279
+ }
280
+ }
281
+ }
282
+
218
283
  function initRadioValue() {
219
284
  if ((mode === '新增' || mode === '修改') && attr.type === 'radio' && !localValue.value) {
220
285
  if (attr.keys && attr.keys.length > 0)
@@ -278,9 +343,17 @@ function updateFile(files, _index) {
278
343
  emits('update:modelValue', localValue.value)
279
344
  }
280
345
  // 监听表单发生变化后触发展示函数
281
- watch(form, (_oldVal, _newVal) => {
346
+ watch( () => form, (_oldVal, _newVal) => {
282
347
  showFormItemFunc()
283
- })
348
+ // 数据源来自人员联动时更新数据
349
+ if (attr?.keyName?.toString()?.startsWith('search@根据表单项[') && attr?.keyName?.toString().endsWith(']联动人员')) {
350
+ debouncedUserLinkFunc()
351
+ }
352
+ // 数据源来自部门联动时更新数据
353
+ if (attr?.keyName?.toString()?.startsWith('search@根据表单项[') && attr?.keyName?.toString().endsWith(']联动部门')) {
354
+ debouncedDepLinkFunc()
355
+ }
356
+ }, {deep: true})
284
357
  </script>
285
358
 
286
359
  <template>
@@ -12,6 +12,7 @@ import NotFound from '@af-mobile-client-vue3/views/common/NotFound.vue'
12
12
  import SingleLayout from '@af-mobile-client-vue3/layout/SingleLayout.vue'
13
13
  import XFormGroupView from '@af-mobile-client-vue3/views/component/XFormGroupView/index.vue'
14
14
  import XSignatureView from '@af-mobile-client-vue3/views/component/XSignatureView/index.vue'
15
+ import XForm from '@af-mobile-client-vue3/components/data/XForm/index.vue'
15
16
 
16
17
  const routes: Array<RouteRecordRaw> = [
17
18
  {
@@ -25,6 +26,18 @@ const routes: Array<RouteRecordRaw> = [
25
26
  name: 'XReportFormIframeView',
26
27
  component: XReportFormIframeView,
27
28
  },
29
+ {
30
+ path: '/Components/XForm',
31
+ name: 'XForm',
32
+ component: XForm,
33
+ props: route => ({
34
+ groupFormItems: JSON.parse(decodeURIComponent(route.query.groupFormItems as string)),
35
+ serviceName: route.query.serviceName,
36
+ formData: JSON.parse(decodeURIComponent(route.query.formData as string)),
37
+ mode: route.query.mode,
38
+ }),
39
+ meta:{ title: '新增/修改表单' }
40
+ },
28
41
  ],
29
42
  },
30
43
  {
@@ -58,6 +71,18 @@ const routes: Array<RouteRecordRaw> = [
58
71
  name: 'XReportFormView',
59
72
  component: XReportFormView,
60
73
  },
74
+ // {
75
+ // path: '/Components/XForm',
76
+ // name: 'XForm',
77
+ // component: XForm,
78
+ // props: route => ({
79
+ // groupFormItems: JSON.parse(decodeURIComponent(route.query.groupFormItems as string)),
80
+ // serviceName: route.query.serviceName,
81
+ // formData: JSON.parse(decodeURIComponent(route.query.formData as string)),
82
+ // mode: route.query.mode,
83
+ // }),
84
+ // meta:{ title: '新增/修改表单' }
85
+ // },
61
86
  {
62
87
  path: '/Component/XFormView/:id/:openid',
63
88
  name: 'XFormView',
@@ -0,0 +1,136 @@
1
+ import { METHOD, request } from '@af-mobile-client-vue3/utils/http/index'
2
+ import { runLogic } from '@af-mobile-client-vue3/services/api/common'
3
+
4
+ function getLeafNodes (nodes) {
5
+ // console.log(nodes)
6
+ // 确保 nodes 是数组
7
+ const nodeArray = Array.isArray(nodes) ? nodes : [nodes]
8
+ return nodeArray.reduce((leaves, node) => {
9
+ if (node.children && node.children.length) {
10
+ // 递归处理子节点并合并结果
11
+ leaves.push(...getLeafNodes(node.children))
12
+ } else {
13
+ // 当前节点是叶子节点时,直接加入结果
14
+ leaves.push(node)
15
+ }
16
+ return leaves
17
+ }, [])
18
+ }
19
+
20
+ function getLeafNodesByCondition (type, nodes, parent = null) {
21
+ // console.log('nodes------',nodes)
22
+ // 确保 nodes 是数组
23
+ const nodeArray = Array.isArray(nodes) ? nodes : [nodes]
24
+
25
+ return nodeArray.reduce((leaves, node) => {
26
+ const isValidNode = node.resourcetype === type && node.name !== '组织机构'
27
+ const updatedParent = node.name === '组织机构' ? null : node.name
28
+
29
+ if (node.children && node.children.length) {
30
+ // 当前节点符合条件时,加入叶子节点列表
31
+ if (isValidNode && node.resourcetype === 'organization') {
32
+ leaves.push({
33
+ ...node,
34
+ name: parent ? `${node.name}` : node.name,
35
+ children: [],
36
+ })
37
+ }
38
+ if (isValidNode && node.resourcetype === 'department') {
39
+ leaves.push({
40
+ ...node,
41
+ name: parent ? `${node.name}-${parent}` : node.name,
42
+ children: [],
43
+ })
44
+ }
45
+ // 递归处理子节点
46
+ leaves.push(...getLeafNodesByCondition(type, node.children, updatedParent))
47
+ } else if (isValidNode) {
48
+ // 无子节点但符合条件时,直接加入叶子节点列表
49
+ if (node.resourcetype === 'organization'){
50
+ leaves.push({
51
+ ...node,
52
+ name: parent ? `${node.name}-${parent}` : node.name,
53
+ })
54
+ }else if (node.resourcetype === 'department' && !nodeArray.includes(node.name)) {
55
+ // console.log('数组',nodeArray.includes(node.name))
56
+ leaves.push({
57
+ ...node,
58
+ name: parent ? `${node.name}-${parent}` : node.name,
59
+ })
60
+ }
61
+ }
62
+ return leaves
63
+ }, [])
64
+ }
65
+
66
+ function transformData (inputData) {
67
+ function transform (node) {
68
+ return {
69
+ label: node.name,
70
+ value: node.id,
71
+ f_organization_id: node.f_organization_id,
72
+ f_department_id: node.f_department_id,
73
+ parentid: node.parentid,
74
+ orgid: node.orgid,
75
+ children: node.children ? node.children.map(transform) : []
76
+ }
77
+ }
78
+
79
+ return inputData.map(transform)
80
+ }
81
+
82
+ function getResData (params, toCallback) {
83
+ const data = { userId: params.userid, roleName: params.roleName }
84
+ if (params.source === '获取分公司') {
85
+ runLogic('getOrgBySearch', data, 'af-system').then(res => toCallback(res))
86
+ } else if (params.source === '获取部门') {
87
+ runLogic('getDepBySearch', data, 'af-system').then(res => toCallback(res))
88
+ } else if (params.source === '获取人员') {
89
+ runLogic('getUserBySearch', data, 'af-system').then(res => toCallback(res))
90
+ } else if (params.source === '根据角色获取人员') {
91
+ runLogic('getUserBySearchRole', data, 'af-system').then(res => toCallback(res))
92
+ } else {
93
+ return search(params).then(res => toCallback(res))
94
+ }
95
+ }
96
+
97
+ export async function searchToOption (params, callback) {
98
+ function toCallback (res) {
99
+ if (res.length) {
100
+ if (res[0].children && res[0].children.length) {
101
+ if (res[0].children[0].children) {
102
+ callback(transformData(res[0].children[0].children))
103
+ } else {
104
+ callback(transformData(res[0].children))
105
+ }
106
+ } else {
107
+ callback(res[0].children)
108
+ }
109
+ } else {
110
+ callback(res)
111
+ }
112
+ }
113
+
114
+ await getResData(params, toCallback)
115
+ }
116
+
117
+ export async function searchToListOption (params, callback) {
118
+ function toCallback (res) {
119
+ if (params.source.includes('人员')) {
120
+ // console.log('ren---------',res)
121
+ callback(transformData(getLeafNodes(res)))
122
+ } else {
123
+ const type = params.source.includes('公司') ? 'organization' : 'department'
124
+ // console.log('bumenpgonngsi',res)
125
+ callback(transformData(getLeafNodesByCondition(type, res)))
126
+ }
127
+ }
128
+
129
+ await getResData(params, toCallback)
130
+ }
131
+
132
+ export async function search (params) {
133
+ return request('/rs/search', METHOD.POST, params, params.config)
134
+ }
135
+
136
+ export default { searchToOption, search }
@@ -3,6 +3,7 @@ import { showToast } from 'vant'
3
3
  import { ContentTypeEnum, ResultEnum } from '@af-mobile-client-vue3/enums/requestEnum'
4
4
  import { ACCESS_TOKEN } from '@af-mobile-client-vue3/stores/mutation-type'
5
5
  import { useUserStore } from '@af-mobile-client-vue3/stores/modules/user'
6
+ import axios from 'axios'
6
7
 
7
8
  // 默认 axios 实例请求配置
8
9
  const configDefault = {
@@ -155,4 +156,37 @@ class Http {
155
156
  }
156
157
  }
157
158
 
159
+ const METHOD = {
160
+ GET: 'get',
161
+ POST: 'post',
162
+ PUT: 'put',
163
+ DELETE: 'delete'
164
+ }
165
+ /**
166
+ * axios请求
167
+ * @param url 请求地址
168
+ * @param method {METHOD} http method
169
+ * @param params 请求参数
170
+ * @param config
171
+ * @returns {Promise<AxiosResponse<T>>}
172
+ */
173
+ async function request (url, method, params, config) {
174
+ switch (method) {
175
+ case METHOD.GET:
176
+ return axios.get(url, { params, ...config })
177
+ case METHOD.POST:
178
+ return axios.post(url, params, config)
179
+ case METHOD.PUT:
180
+ return axios.put(url, params, config)
181
+ case METHOD.DELETE:
182
+ return axios.delete(url, { params, ...config })
183
+ default:
184
+ return axios.get(url, { params, ...config })
185
+ }
186
+ }
187
+
158
188
  export const http = new Http(configDefault)
189
+ export {
190
+ METHOD,
191
+ request,
192
+ }
@@ -10,7 +10,9 @@ const emit = defineEmits(['deleteRow'])
10
10
  const router = useRouter()
11
11
  // 获取默认值
12
12
  const idKey = ref('o_id')
13
- const configName = ref('crud_oper_log_manage')
13
+ // const configName = ref('crud_oper_log_manage')
14
+ // const serviceName = ref('af-system')
15
+ const configName = ref('crud_sources_test')
14
16
  const serviceName = ref('af-system')
15
17
 
16
18
  // 跳转到详情页面
@@ -84,8 +86,6 @@ function deleteRow(result) {
84
86
  :config-name="configName"
85
87
  :id-key="idKey"
86
88
  @to-detail="toDetail"
87
- @add-option="addOption"
88
- @update-row="updateRow"
89
89
  @delete-row="deleteRow"
90
90
  />
91
91
  </template>
@@ -3,13 +3,15 @@ import XFormGroup from '@af-mobile-client-vue3/components/data/XFormGroup/index.
3
3
  import NormalDataLayout from '@af-mobile-client-vue3/components/layout/NormalDataLayout/index.vue'
4
4
  import { onBeforeMount, ref } from 'vue'
5
5
  import { showDialog } from 'vant'
6
+ // import {runLogic} from "@af-mobile-client-vue3/services/api/common";
6
7
 
7
8
  // 纯表单
8
- const serviceName = ref('af-linepatrol')
9
+ // const configName = ref("计划下发Form")
10
+ // const serviceName = ref("af-linepatrol")
9
11
 
10
12
  // 表单组
11
- const configName = ref('lngChargeAuditMobileFormGroup')
12
- // const serviceName = ref("af-gaslink")
13
+ const configName = ref("lngChargeAuditMobileFormGroup")
14
+ const serviceName = ref("af-gaslink")
13
15
 
14
16
  const formData = ref({})
15
17
  function submit(_result) {
@@ -26,13 +28,13 @@ function submit(_result) {
26
28
  // }
27
29
 
28
30
  // 纯表单——数据
29
- function initComponents() {
30
- formData.value = { plan_name: 'af-llllll', plan_point: '1号点位', plan_single: '1号点位', plan_range: '2024-12-12' }
31
- }
31
+ // function initComponents() {
32
+ // formData.value = { plan_name: 'af-llllll', plan_point: '1号点位', plan_single: '1号点位', plan_range: '2024-12-12' }
33
+ // }
32
34
 
33
- onBeforeMount(() => {
34
- initComponents()
35
- })
35
+ // onBeforeMount(() => {
36
+ // initComponents()
37
+ // })
36
38
  </script>
37
39
 
38
40
  <template>
@@ -13,7 +13,6 @@ import { post } from '@af-mobile-client-vue3/services/restTools'
13
13
 
14
14
  const emit = defineEmits(['onSumbit'])
15
15
  const xForm = ref(null)
16
- const loading = ref(true)
17
16
  const id = ref(-1)
18
17
  const openid = ref('')
19
18
  const instance = getCurrentInstance()
@@ -41,10 +40,7 @@ const _currentEvaluate = {
41
40
  }
42
41
 
43
42
  // 组件挂载前获取数据
44
- onBeforeMount(() => {
45
- if (mode === '修改')
46
- getUpdateData()
47
-
43
+ onBeforeMount(async () => {
48
44
  if (instance) {
49
45
  id.value = route.params.id as unknown as number
50
46
  openid.value = route.params.openid as string
@@ -54,35 +50,20 @@ onBeforeMount(() => {
54
50
 
55
51
  // 组件初始化前的判断
56
52
  async function formInit() {
57
- if (id.value > 0) {
58
- // 先获取 myForm
59
- queryData()
60
- }
61
- else {
62
- // 没有id 直接提示用户不存在,返回上一级
63
- await showDialog({ message: '评价信息缺少参数,找不到对应评价信息' })
64
- history.back()
65
- }
66
- }
67
-
68
- // 获取配置信息
69
- function queryData() {
70
53
  getConfigByName(configName, (result) => {
71
54
  groupFormItems.value = result
72
55
  title.value = result.title
73
- if (xForm.value) {
74
- xForm.value.init({
75
- formItems: result,
76
- serviceName,
77
- getDataParams: {},
78
- formData: updateData.value ? updateData.value : null,
79
- })
80
- loading.value = false
81
- }
56
+ if (mode === '修改')
57
+ getUpdateData()
82
58
  xFormInit.value = true
83
59
  }, serviceName)
84
60
  }
85
61
 
62
+ // 获取配置信息
63
+ function queryData() {
64
+
65
+ }
66
+
86
67
  // 提交操作
87
68
  function onSubmit(params) {
88
69
  // const data = {
@@ -112,35 +93,18 @@ function onSubmit(params) {
112
93
  }
113
94
 
114
95
  // 查询需要修改的数据
115
- function getUpdateData() {
96
+ async function getUpdateData() {
116
97
  if (api.value && updateId) {
117
- post(api.value, updateId).then((res) => {
118
- loadUpdate.value = true
119
- updateData.value = res.data[0]
120
- }, (_) => {
121
- }).finally(() => {
122
- loadUpdate.value = false
123
- })
98
+ const res = await post(api.value, updateId)
99
+ updateData.value = res.data[0]
124
100
  }
125
101
  }
126
102
 
127
- function _onClickLeft(): void {
128
- history.back()
129
- }
130
103
  </script>
131
104
 
132
105
  <template>
133
- <!-- <VanNavBar -->
134
- <!-- title="XForm表单" -->
135
- <!-- left-text="返回" -->
136
- <!-- left-arrow -->
137
- <!-- @click-left="onClickLeft" -->
138
- <!-- /> -->
139
106
  <NormalDataLayout id="XFormView" title="XForm表单">
140
107
  <template #layout_content>
141
- <!-- <VanRow v-show="loading" justify="center"> -->
142
- <!-- <VanLoading type="spinner" color="#1989fa" /> -->
143
- <!-- </VanRow> -->
144
108
  <VanSpace direction="vertical" fill>
145
109
  <VanNavBar :title="title ? mode.concat(title) : null" />
146
110
  <XForm
@@ -148,7 +112,7 @@ function _onClickLeft(): void {
148
112
  ref="xForm"
149
113
  :group-form-items="JSON.parse(JSON.stringify(groupFormItems))"
150
114
  :service-name="serviceName"
151
- :form-data="updateData ? updateData : null"
115
+ :form-data="updateData"
152
116
  :mode="mode"
153
117
  style="margin-bottom: 14px;"
154
118
  @on-submit="onSubmit"