af-mobile-client-vue3 1.2.55 → 1.2.57

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.
@@ -1,42 +1,105 @@
1
1
  <script setup lang="ts">
2
+ // 组件顶部功能说明:本组件为表单视图,支持通过 setRef 注册自身到父组件
2
3
  import XForm from '@af-mobile-client-vue3/components/data/XForm/index.vue'
3
- import NormalDataLayout from '@af-mobile-client-vue3/components/layout/NormalDataLayout/index.vue'
4
- import { ref } from 'vue'
4
+ import { post } from '@af-mobile-client-vue3/services/restTools'
5
+ import { useUserStore } from '@af-mobile-client-vue3/stores/modules/user'
6
+ import dayjs from 'dayjs/esm/index'
7
+ import { showFailToast, showToast } from 'vant'
8
+ import {computed, defineExpose, defineProps, onMounted, onUnmounted, ref} from 'vue'
9
+ import { useRoute } from 'vue-router'
5
10
 
6
- const configName = ref('AddConstructionForm')
7
- const serviceName = ref('af-linepatrol')
11
+ const props = withDefaults(defineProps<{
12
+ setRef?: (refValue: any) => void
13
+ removeRef?: (refValue: any) => void
14
+ formGroupName?: string
15
+ }>(), {
16
+ setRef: () => {},
17
+ removeRef: () => {},
18
+ formGroupName: '',
19
+ })
20
+ const configName = ref('mobile_OtherChargeCancelForm')
21
+ const serviceName = ref('af-apply')
22
+ const route = useRoute()
23
+ const userInfo = useUserStore().getUserInfo()
24
+ const workflowId = computed(() => route.query.workflowid)
25
+ const formData = ref({
26
+ f_cancel_reason: '1111',
27
+ })
8
28
 
9
- const formGroupAddConstruction = ref(null)
10
- function emitFunc(func, data) {
11
- console.log('>>>> func: ', func)
12
- console.log('>>>> data: ', data)
13
- if (func === 'selectAddress') {
14
- const add = 'ccss'
15
- // 设置单个字段
16
- formGroupAddConstruction.value?.setForm({ address: '你的字符串' })
29
+ const xFormRef = ref()
30
+ const aaa = ref({})
31
+ function submit(res: any) {
32
+ if (Number(res.charge_money) > Number(res.surplus_money)) {
33
+ showFailToast('收费金额不能大于未结金额!!')
34
+ return
17
35
  }
36
+ const saveData = {
37
+ f_payment_type: res.payment_type,
38
+ f_charge_money: res.charge_money,
39
+ f_amount_words: res.amount_words,
40
+ f_payment_method: res.payment_method,
41
+ f_actual_date: res.actual_date,
42
+ f_charge_status: '有效',
43
+ f_workflow_id: workflowId.value,
44
+ f_charge_collectors: userInfo.f_operator,
45
+ f_charge_collectors_id: userInfo.f_operatorid,
46
+ f_charge_date: dayjs().format('YYYY-MM-DD HH:mm:ss'),
47
+ f_filialeid: userInfo.f_orgid,
48
+ f_filiale: userInfo.f_orgname,
49
+ }
50
+ post('api/af-apply/entity/save/t_charge_record', saveData).then((_res) => {
51
+ showToast('提交成功!')
52
+ history.back()
53
+ })
54
+ }
55
+ function init() {
56
+ // runLogic('getApplyBusinessrecode', { f_workflow_id: 854 }, 'af-apply').then((res) => {
57
+ // // formData.value = res
58
+ // console.log('res==', res)
59
+ // }).catch((err) => {
60
+ //
61
+ // })
62
+ setTimeout(() => {
63
+ Object.assign(formData.value, { f_cancel_reason: '2222222' })
64
+ }, 5000)
65
+ }
66
+ function validate() {
67
+ // 调用 XForm 的 validate 方法
68
+ return xFormRef.value?.validate?.() ?? Promise.resolve()
18
69
  }
19
- function submit(data) {
20
- console.log('>>>> data: ', JSON.stringify(data))
70
+ function getFormData() {
71
+ console.log('自定义表单=====', xFormRef.value.getFormData())
72
+ // 获取 XForm 的表单数据
73
+ return xFormRef.value?.getFormData?.() ?? {}
21
74
  }
75
+ onMounted(() => {
76
+ init()
77
+ })
78
+ const exposeObj = { validate, getFormData, init, formGroupName: props.formGroupName }
79
+ defineExpose(exposeObj)
80
+ onMounted(() => {
81
+ props.setRef && props.setRef(exposeObj)
82
+ })
83
+ onUnmounted(() => {
84
+ props.removeRef && props.removeRef(exposeObj)
85
+ })
86
+ // watch(() => props.formData, (newVal) => {
87
+ // console.log('变更了===', newVal)
88
+ // if (newVal) {
89
+ // Object.assign(form, newVal)
90
+ // }
91
+ // })
22
92
  </script>
23
93
 
24
- <!-- workflowId -->
25
94
  <template>
26
- <NormalDataLayout id="XFormGroupView" title="纯表单">
27
- <template #layout_content>
28
- <XForm
29
- ref="formGroupAddConstruction"
30
- mode="新增"
31
- :config-name="configName"
32
- :service-name="serviceName"
33
- :param-logic-name-param="{ aa: 123 }"
34
- :form-data="{ f_project_name: 333 }"
35
- @x-form-item-emit-func="emitFunc"
36
- @on-submit="submit"
37
- />
38
- </template>
39
- </NormalDataLayout>
95
+ <XForm
96
+ ref="xFormRef"
97
+ mode="新增"
98
+ :config-name="configName"
99
+ :service-name="serviceName"
100
+ :form-data="formData"
101
+ @on-submit="submit"
102
+ />
40
103
  </template>
41
104
 
42
105
  <style scoped lang="less">
@@ -1,118 +1,118 @@
1
- <script setup lang="ts">
2
- import type { LocationResult } from '@af-mobile-client-vue3/components/data/XOlMap/types'
3
- import LocationPicker from '@af-mobile-client-vue3/components/data/XOlMap/XLocationPicker/index.vue'
4
- import NormalDataLayout from '@af-mobile-client-vue3/components/layout/NormalDataLayout/index.vue'
5
- import { showNotify } from 'vant'
6
- import { ref } from 'vue'
7
-
8
- const selectedLocation = ref<LocationResult>()
9
-
10
- // 处理位置选择
11
- function handleLocationConfirm(location: LocationResult) {
12
- // console.log('选择的位置:', location)
13
- // selectedLocation.value = location
14
- showNotify({ type: 'success', message: '位置已选择' })
15
- }
16
- </script>
17
-
18
- <template>
19
- <NormalDataLayout id="XLocationPicker" title="XOlMap地址选择器">
20
- <template #layout_content>
21
- <div class="location-picker-demo">
22
- <!-- 页面标题 -->
23
- <div class="page-header">
24
- <div class="title">
25
- 位置选择
26
- </div>
27
- </div>
28
-
29
- <!-- 选择结果展示 -->
30
- <div v-if="selectedLocation" class="location-result">
31
- <div class="label">
32
- 已选位置:
33
- </div>
34
- <div class="value">
35
- {{ selectedLocation.address }}
36
- </div>
37
- <div class="coordinates">
38
- 经度: {{ selectedLocation.longitude.toFixed(6) }},
39
- 纬度: {{ selectedLocation.latitude.toFixed(6) }}
40
- </div>
41
- </div>
42
-
43
- <!-- 地图组件 -->
44
- <div class="map-container">
45
- <LocationPicker
46
- v-model="selectedLocation"
47
- :default-center="[108.948024, 34.263161]"
48
- :default-zoom="12"
49
- @confirm="handleLocationConfirm"
50
- />
51
- </div>
52
- </div>
53
- </template>
54
- </NormalDataLayout>
55
- </template>
56
-
57
- <style scoped lang="less">
58
- .location-picker-demo {
59
- width: 100%;
60
- height: 100%;
61
- position: relative;
62
- display: flex;
63
- flex-direction: column;
64
- background-color: #f7f8fa;
65
- }
66
-
67
- .page-header {
68
- height: 44px;
69
- display: flex;
70
- align-items: center;
71
- justify-content: center;
72
- background: white;
73
- box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
74
- position: relative;
75
- z-index: 1;
76
-
77
- .title {
78
- font-size: 16px;
79
- color: #333;
80
- font-weight: 500;
81
- }
82
- }
83
-
84
- .location-result {
85
- background: white;
86
- padding: 12px 16px;
87
- margin: 10px;
88
- border-radius: 8px;
89
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
90
-
91
- .label {
92
- font-size: 14px;
93
- color: #666;
94
- margin-bottom: 4px;
95
- }
96
-
97
- .value {
98
- font-size: 16px;
99
- color: #333;
100
- margin-bottom: 8px;
101
- word-break: break-all;
102
- }
103
-
104
- .coordinates {
105
- font-size: 12px;
106
- color: #999;
107
- }
108
- }
109
-
110
- .map-container {
111
- flex: 1;
112
- position: relative;
113
- margin: 0 10px 10px 10px;
114
- border-radius: 8px;
115
- overflow: hidden;
116
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
117
- }
118
- </style>
1
+ <script setup lang="ts">
2
+ import type { LocationResult } from '@af-mobile-client-vue3/components/data/XOlMap/types'
3
+ import LocationPicker from '@af-mobile-client-vue3/components/data/XOlMap/XLocationPicker/index.vue'
4
+ import NormalDataLayout from '@af-mobile-client-vue3/components/layout/NormalDataLayout/index.vue'
5
+ import { showNotify } from 'vant'
6
+ import { ref } from 'vue'
7
+
8
+ const selectedLocation = ref<LocationResult>()
9
+
10
+ // 处理位置选择
11
+ function handleLocationConfirm(location: LocationResult) {
12
+ // console.log('选择的位置:', location)
13
+ // selectedLocation.value = location
14
+ showNotify({ type: 'success', message: '位置已选择' })
15
+ }
16
+ </script>
17
+
18
+ <template>
19
+ <NormalDataLayout id="XLocationPicker" title="XOlMap地址选择器">
20
+ <template #layout_content>
21
+ <div class="location-picker-demo">
22
+ <!-- 页面标题 -->
23
+ <div class="page-header">
24
+ <div class="title">
25
+ 位置选择
26
+ </div>
27
+ </div>
28
+
29
+ <!-- 选择结果展示 -->
30
+ <div v-if="selectedLocation" class="location-result">
31
+ <div class="label">
32
+ 已选位置:
33
+ </div>
34
+ <div class="value">
35
+ {{ selectedLocation.address }}
36
+ </div>
37
+ <div class="coordinates">
38
+ 经度: {{ selectedLocation.longitude.toFixed(6) }},
39
+ 纬度: {{ selectedLocation.latitude.toFixed(6) }}
40
+ </div>
41
+ </div>
42
+
43
+ <!-- 地图组件 -->
44
+ <div class="map-container">
45
+ <LocationPicker
46
+ v-model="selectedLocation"
47
+ :default-center="[108.948024, 34.263161]"
48
+ :default-zoom="12"
49
+ @confirm="handleLocationConfirm"
50
+ />
51
+ </div>
52
+ </div>
53
+ </template>
54
+ </NormalDataLayout>
55
+ </template>
56
+
57
+ <style scoped lang="less">
58
+ .location-picker-demo {
59
+ width: 100%;
60
+ height: 100%;
61
+ position: relative;
62
+ display: flex;
63
+ flex-direction: column;
64
+ background-color: #f7f8fa;
65
+ }
66
+
67
+ .page-header {
68
+ height: 44px;
69
+ display: flex;
70
+ align-items: center;
71
+ justify-content: center;
72
+ background: white;
73
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
74
+ position: relative;
75
+ z-index: 1;
76
+
77
+ .title {
78
+ font-size: 16px;
79
+ color: #333;
80
+ font-weight: 500;
81
+ }
82
+ }
83
+
84
+ .location-result {
85
+ background: white;
86
+ padding: 12px 16px;
87
+ margin: 10px;
88
+ border-radius: 8px;
89
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
90
+
91
+ .label {
92
+ font-size: 14px;
93
+ color: #666;
94
+ margin-bottom: 4px;
95
+ }
96
+
97
+ .value {
98
+ font-size: 16px;
99
+ color: #333;
100
+ margin-bottom: 8px;
101
+ word-break: break-all;
102
+ }
103
+
104
+ .coordinates {
105
+ font-size: 12px;
106
+ color: #999;
107
+ }
108
+ }
109
+
110
+ .map-container {
111
+ flex: 1;
112
+ position: relative;
113
+ margin: 0 10px 10px 10px;
114
+ border-radius: 8px;
115
+ overflow: hidden;
116
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
117
+ }
118
+ </style>
@@ -5,13 +5,14 @@ import GetAppDataService from '@af-mobile-client-vue3/plugins/AppData'
5
5
  import { getUserPermissions } from '@af-mobile-client-vue3/services/api/search'
6
6
  import { useSettingStore } from '@af-mobile-client-vue3/stores/modules/setting'
7
7
  import { useUserStore } from '@af-mobile-client-vue3/stores/modules/user'
8
- import { indexedDB } from '@af-mobile-client-vue3/utils/indexedDB'
9
8
  import { funcToRouter, loadRoutes } from '@af-mobile-client-vue3/utils/routerUtil'
9
+ import { secureStorageBatchWrite, secureStorageRead } from '@af-mobile-client-vue3/utils/secureStorage'
10
10
  import { isWechat } from '@af-mobile-client-vue3/utils/wechatUtil'
11
11
  import {
12
12
  closeToast,
13
13
  showDialog,
14
14
  showFailToast,
15
+ showLoadingToast,
15
16
  Switch,
16
17
  Button as VanButton,
17
18
  Col as VanCol,
@@ -102,6 +103,8 @@ function handleSubmit() {
102
103
  .then(async () => {
103
104
  try {
104
105
  loading.value = true
106
+ showLoadingToast('登录中...')
107
+ console.warn(setting)
105
108
  const data: any = await userState.Login({
106
109
  username: formData.username,
107
110
  password: formData.password,
@@ -158,6 +161,19 @@ function closeWindows() {
158
161
  }
159
162
 
160
163
  async function afterGeneral(result) {
164
+ // 排序 functions 及其嵌套的 children
165
+ if (result.functions && Array.isArray(result.functions)) {
166
+ // 对顶层菜单进行排序
167
+ result.functions.sort((a, b) => (a.position || 0) - (b.position || 0))
168
+
169
+ // 对每个菜单的子项进行排序
170
+ for (const item of result.functions) {
171
+ if (item.children && Array.isArray(item.children)) {
172
+ item.children.sort((a, b) => (a.position || 0) - (b.position || 0))
173
+ }
174
+ }
175
+ }
176
+
161
177
  const user: any = {
162
178
  ...result,
163
179
  username: result.ename,
@@ -172,8 +188,25 @@ async function afterGeneral(result) {
172
188
  userState.setRoles([{ id: 'admin', operation: ['add', 'edit', 'delete'] }])
173
189
  // 加载路由
174
190
  loadRoutes(funcToRouter(user.functions))
191
+
192
+ // 存储登录数据到本地缓存
193
+ secureStorageBatchWrite([
194
+ {
195
+ key: 'loginData',
196
+ value: {
197
+ username: formData.username,
198
+ password: formData.password,
199
+ rememberMe: rememberMe.value,
200
+ },
201
+ },
202
+ {
203
+ key: 'userData',
204
+ value: result,
205
+ },
206
+ ])
207
+
175
208
  // 每次重新登录时,清除indexedDB缓存
176
- indexedDB.clear()
209
+ // indexedDB.clear()
177
210
  }
178
211
  async function wxLoginFun() {
179
212
  await localStorage.setItem('wechatLoginPending', 'true')
@@ -221,6 +254,23 @@ onMounted(() => {
221
254
  localStorage.removeItem('wechatLoginPending')
222
255
  wxLoginFunContinue(code, state)
223
256
  }
257
+ try {
258
+ // 手机登录获取本地缓存的登录数据
259
+ secureStorageRead('loginData', (result: any) => {
260
+ if (result.status === 'success') {
261
+ const res = JSON.parse(result.data.value)
262
+ if (res.rememberMe) {
263
+ formData.username = res.username
264
+ formData.password = res.password
265
+ rememberMe.value = res.rememberMe
266
+ }
267
+ }
268
+ })
269
+ }
270
+ catch (e) {
271
+ console.debug('读取本地缓存失败', e)
272
+ // 未拿到跳过
273
+ }
224
274
  })
225
275
  </script>
226
276
 
package/vite.config.ts CHANGED
@@ -11,8 +11,8 @@ export default ({ mode }: ConfigEnv): UserConfig => {
11
11
 
12
12
  const appProxys = {}
13
13
 
14
- const v4Server = 'http://aote-office.8866.org:31567'
15
- const v3Server = 'http://aote-office.8866.org:31567'
14
+ const v4Server = 'http://192.168.50.67:31577'
15
+ const v3Server = 'https://wkf.qhgas.com'
16
16
  const OSSServerDev = 'http://192.168.50.67:30351'
17
17
  const geoserver = 'http://39.104.49.8:30372'
18
18
  // const OSSServerProd = 'http://192.168.50.67:31351'
@@ -1,70 +0,0 @@
1
- <script setup lang="ts">
2
- import XForm from '@af-mobile-client-vue3/components/data/XForm/index.vue'
3
- import NormalDataLayout from '@af-mobile-client-vue3/components/layout/NormalDataLayout/index.vue'
4
- import { getConfigByName } from '@af-mobile-client-vue3/services/api/common'
5
- import { onBeforeMount, ref, toRaw } from 'vue'
6
-
7
- const configName = ref('AddConstructionForm')
8
- const serviceName = ref('af-linepatrol')
9
- const formGroup = ref(null)
10
- const formConfig = ref(null)
11
- const submitSimple = ref(null)
12
- const isLoading = ref(true)
13
-
14
- function safeStringify(obj) {
15
- const seen = new WeakSet()
16
- return JSON.stringify(toRaw(obj), (key, val) => {
17
- if (typeof val === 'object' && val !== null) {
18
- if (seen.has(val))
19
- return
20
- seen.add(val)
21
- }
22
- return val
23
- }, 2)
24
- }
25
-
26
- function submit(result) {
27
- console.log('>>>> result: ', safeStringify(result))
28
- }
29
-
30
- function loadConfig() {
31
- return new Promise((resolve) => {
32
- getConfigByName(configName.value, (result) => {
33
- submitSimple.value = result.showSubmitBtn
34
- formConfig.value = result
35
- resolve(result)
36
- }, serviceName.value)
37
- })
38
- }
39
-
40
- onBeforeMount(async () => {
41
- try {
42
- await loadConfig()
43
- }
44
- finally {
45
- isLoading.value = false
46
- }
47
- })
48
- </script>
49
-
50
- <template>
51
- <NormalDataLayout id="XFormGroupView" title="纯表单">
52
- <template #layout_content>
53
- <van-loading v-if="isLoading" />
54
- <XForm
55
- v-else
56
- ref="formGroup"
57
- mode="查询"
58
- :service-name="serviceName"
59
- :group-form-items="formConfig"
60
- :form-data="{}"
61
- :form-name="formConfig?.groupName || '11111'"
62
- :submit-button="submitSimple"
63
- @on-submit="submit"
64
- />
65
- </template>
66
- </NormalDataLayout>
67
- </template>
68
-
69
- <style scoped lang="less">
70
- </style>