af-mobile-client-vue3 1.4.11 → 1.4.13-cs

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.4.11",
4
+ "version": "1.4.13-cs",
5
5
  "packageManager": "pnpm@10.13.1",
6
6
  "description": "Vue + Vite component lib",
7
7
  "engines": {
package/postcss.config.ts CHANGED
@@ -13,15 +13,15 @@ const rootContainingBlockSelectorList = [
13
13
 
14
14
  export default {
15
15
  plugins: {
16
- autoprefixer: {},
16
+ 'autoprefixer': {},
17
17
 
18
18
  // https://github.com/wswmsword/postcss-mobile-forever
19
- // 'postcss-mobile-forever': {
20
- // appSelector: '#system-app',
21
- // viewportWidth: 375,
22
- // maxDisplayWidth: 800,
23
- // border: true,
24
- // rootContainingBlockSelectorList,
25
- // },
19
+ 'postcss-mobile-forever': {
20
+ appSelector: '#system-app',
21
+ viewportWidth: 375,
22
+ maxDisplayWidth: 800,
23
+ border: true,
24
+ rootContainingBlockSelectorList,
25
+ },
26
26
  },
27
27
  }
@@ -119,4 +119,4 @@ onUnmounted(() => {
119
119
  color: #ff976a;
120
120
  }
121
121
  }
122
- </style>
122
+ </style>
@@ -99,4 +99,4 @@ onUnmounted(() => {
99
99
  .user-form {
100
100
  padding: 16px;
101
101
  }
102
- </style>
102
+ </style>
@@ -37,7 +37,7 @@ import {
37
37
  Switch as VanSwitch,
38
38
  TimePicker as VanTimePicker,
39
39
  } from 'vant'
40
- import { computed, defineEmits, defineModel, defineProps, getCurrentInstance, onBeforeMount, ref, watch } from 'vue'
40
+ import { computed, defineEmits, defineModel, defineProps, getCurrentInstance, nextTick, onBeforeMount, ref, watch } from 'vue'
41
41
 
42
42
  const props = defineProps({
43
43
  attr: {
@@ -620,7 +620,7 @@ function onCalendarConfirm(values) {
620
620
  // js 函数作为数据源
621
621
  async function updateOptions() {
622
622
  if (attr.keyName && (attr.keyName.toString().includes('async ') || attr.keyName.toString().includes('function '))) {
623
- option.value = await executeStrFunctionByContext(currInst, attr.keyName, [props.form, runLogic, props.mode, getConfigByNameAsync, post])
623
+ option.value = await executeStrFunctionByContext(currInst, attr.keyName, [props.form, runLogic, props.mode, getConfigByNameAsync, post, userState.f.resources])
624
624
  }
625
625
  }
626
626
 
@@ -1,33 +1,33 @@
1
- <script setup lang="ts">
2
- import { onMounted, ref } from 'vue'
3
- import XReport from './XReport.vue'
4
-
5
- const mainRef = ref()
6
-
7
- onMounted(() => {
8
- // 初始化逻辑
9
- })
10
- </script>
11
-
12
- <template>
13
- <div id="test">
14
- <van-card :bordered="false">
15
- <XReport
16
- ref="mainRef"
17
- :use-oss-for-img="false"
18
- config-name="nurseWorkstationCover"
19
- server-name="af-his"
20
- :show-img-in-cell="true"
21
- :display-only="true"
22
- :edit-mode="false"
23
- :show-save-button="false"
24
- :no-padding="true"
25
- :dont-format="true"
26
- />
27
- </van-card>
28
- </div>
29
- </template>
30
-
31
- <style scoped>
32
-
33
- </style>
1
+ <script setup lang="ts">
2
+ import { onMounted, ref } from 'vue'
3
+ import XReport from './XReport.vue'
4
+
5
+ const mainRef = ref()
6
+
7
+ onMounted(() => {
8
+ // 初始化逻辑
9
+ })
10
+ </script>
11
+
12
+ <template>
13
+ <div id="test">
14
+ <van-card :bordered="false">
15
+ <XReport
16
+ ref="mainRef"
17
+ :use-oss-for-img="false"
18
+ config-name="nurseWorkstationCover"
19
+ server-name="af-his"
20
+ :show-img-in-cell="true"
21
+ :display-only="true"
22
+ :edit-mode="false"
23
+ :show-save-button="false"
24
+ :no-padding="true"
25
+ :dont-format="true"
26
+ />
27
+ </van-card>
28
+ </div>
29
+ </template>
30
+
31
+ <style scoped>
32
+
33
+ </style>
@@ -1,184 +1,184 @@
1
- // print.js
2
-
3
- export function printElement(elementToPrint) {
4
- // 创建一个新的浏览器窗口
5
- const printWindow = window.open('', '_blank', 'height=1024,width=768')
6
- // 设置新窗口的文档内容
7
- printWindow.document.write(`
8
- <html>
9
- <head>
10
- <title>Print</title>
11
- <style>
12
- @page {
13
- size: auto;
14
- margin: 0mm;
15
- }
16
- html, body {
17
- margin: 0;
18
- padding: 0;
19
- width: 100%;
20
- height: 100%;
21
- }
22
- #print-container {
23
- display: none
24
- }
25
- .img{
26
- width: 95%;
27
- height: 180px;
28
- object-fit: cover;
29
- }
30
- .reportMain {
31
- text-align: center;
32
- margin: 0 auto;
33
- font-size: 16px;
34
- color: #000;
35
- background-color: #fff;
36
- border-radius: 8px;
37
-
38
- .reportTitle {
39
- font-weight: bold;
40
- }
41
-
42
- .subTitle {
43
- display: flex;
44
- justify-content: space-between;
45
- margin-bottom: 1%;
46
-
47
- .subTitleItems {
48
- max-width: 30%;
49
- }
50
- }
51
-
52
- .inputsDiv {
53
- display: flex;
54
- justify-content: space-between;
55
- .inputsDivItem {
56
- display: flex;
57
- align-items: center;
58
- padding: 0 4px;
59
- white-space: nowrap;
60
- .inputsDivItemLabel {
61
- padding: 0 4px;
62
- }
63
- }
64
- }
65
-
66
- .reportTable {
67
- width: 100%;
68
- border-collapse: collapse;
69
- table-layout:fixed;
70
- word-break:break-all;
71
- text-align: center;
72
- }
73
- }
74
- .reportMainForDisplay {
75
- text-align: center;
76
- margin: 10% auto;
77
- font-size: 16px;
78
- color: #000;
79
- background-color: #fff;
80
- border-radius: 8px;
81
-
82
- .reportTitle {
83
- font-weight: bold;
84
- }
85
-
86
- .subTitle {
87
- display: flex;
88
- justify-content: space-between;
89
-
90
- .subTitleItems {
91
- max-width: 30%;
92
- }
93
- }
94
-
95
- .inputsDiv {
96
- display: flex;
97
- justify-content: space-around;
98
- .inputsDivItem {
99
- display: flex;
100
- align-items: center;
101
- padding: 0 4px;
102
- white-space: nowrap;
103
- .inputsDivItemLabel {
104
- padding: 0 4px;
105
- }
106
- }
107
- }
108
-
109
- .reportTable {
110
- width: 100%;
111
- border-collapse: collapse;
112
- table-layout:fixed;
113
- word-break:break-all;
114
- }
115
- }
116
- .reportMainNoPadding {
117
- text-align: center;
118
- margin: 0 auto;
119
- font-size: 16px;
120
- color: #000;
121
- background-color: #fff;
122
- border-radius: 8px;
123
-
124
- .reportTitle {
125
- font-weight: bold;
126
- }
127
-
128
- .subTitle {
129
- display: flex;
130
- justify-content: space-between;
131
-
132
- .subTitleItems {
133
- max-width: 30%;
134
- }
135
- }
136
-
137
- .inputsDiv {
138
- display: flex;
139
- justify-content: space-between;
140
- .inputsDivItem {
141
- display: flex;
142
- align-items: center;
143
- padding: 0 4px;
144
- white-space: nowrap;
145
- .inputsDivItemLabel {
146
- padding: 0 4px;
147
- }
148
- }
149
- }
150
-
151
- .reportTable {
152
- width: 100%;
153
- border-collapse: collapse;
154
- table-layout:fixed;
155
- word-break:break-all;
156
- }
157
- }
158
- .tools{
159
- position: fixed;
160
- right: 2%;
161
- text-align: right;
162
- width: 60%;
163
- cursor: pointer;
164
- .toolsItem{
165
- width: 15%;
166
- margin-right: 3%;
167
- display: inline-block;
168
- }
169
- }
170
- </style>
171
- </head>
172
- <body>
173
- <!-- 将需要打印的元素内容复制到新窗口中 -->
174
- ${elementToPrint.innerHTML}
175
- </body>
176
- </html>
177
- `)
178
- // 延迟执行打印,以确保新窗口的内容已加载完成
179
- printWindow.document.close() // 关闭文档流,确保内容完全加载
180
- setTimeout(() => {
181
- printWindow.print() // 调用打印方法
182
- printWindow.close()
183
- }, 500) // 延迟500毫秒后执行打印
184
- }
1
+ // print.js
2
+
3
+ export function printElement(elementToPrint) {
4
+ // 创建一个新的浏览器窗口
5
+ const printWindow = window.open('', '_blank', 'height=1024,width=768')
6
+ // 设置新窗口的文档内容
7
+ printWindow.document.write(`
8
+ <html>
9
+ <head>
10
+ <title>Print</title>
11
+ <style>
12
+ @page {
13
+ size: auto;
14
+ margin: 0mm;
15
+ }
16
+ html, body {
17
+ margin: 0;
18
+ padding: 0;
19
+ width: 100%;
20
+ height: 100%;
21
+ }
22
+ #print-container {
23
+ display: none
24
+ }
25
+ .img{
26
+ width: 95%;
27
+ height: 180px;
28
+ object-fit: cover;
29
+ }
30
+ .reportMain {
31
+ text-align: center;
32
+ margin: 0 auto;
33
+ font-size: 16px;
34
+ color: #000;
35
+ background-color: #fff;
36
+ border-radius: 8px;
37
+
38
+ .reportTitle {
39
+ font-weight: bold;
40
+ }
41
+
42
+ .subTitle {
43
+ display: flex;
44
+ justify-content: space-between;
45
+ margin-bottom: 1%;
46
+
47
+ .subTitleItems {
48
+ max-width: 30%;
49
+ }
50
+ }
51
+
52
+ .inputsDiv {
53
+ display: flex;
54
+ justify-content: space-between;
55
+ .inputsDivItem {
56
+ display: flex;
57
+ align-items: center;
58
+ padding: 0 4px;
59
+ white-space: nowrap;
60
+ .inputsDivItemLabel {
61
+ padding: 0 4px;
62
+ }
63
+ }
64
+ }
65
+
66
+ .reportTable {
67
+ width: 100%;
68
+ border-collapse: collapse;
69
+ table-layout:fixed;
70
+ word-break:break-all;
71
+ text-align: center;
72
+ }
73
+ }
74
+ .reportMainForDisplay {
75
+ text-align: center;
76
+ margin: 10% auto;
77
+ font-size: 16px;
78
+ color: #000;
79
+ background-color: #fff;
80
+ border-radius: 8px;
81
+
82
+ .reportTitle {
83
+ font-weight: bold;
84
+ }
85
+
86
+ .subTitle {
87
+ display: flex;
88
+ justify-content: space-between;
89
+
90
+ .subTitleItems {
91
+ max-width: 30%;
92
+ }
93
+ }
94
+
95
+ .inputsDiv {
96
+ display: flex;
97
+ justify-content: space-around;
98
+ .inputsDivItem {
99
+ display: flex;
100
+ align-items: center;
101
+ padding: 0 4px;
102
+ white-space: nowrap;
103
+ .inputsDivItemLabel {
104
+ padding: 0 4px;
105
+ }
106
+ }
107
+ }
108
+
109
+ .reportTable {
110
+ width: 100%;
111
+ border-collapse: collapse;
112
+ table-layout:fixed;
113
+ word-break:break-all;
114
+ }
115
+ }
116
+ .reportMainNoPadding {
117
+ text-align: center;
118
+ margin: 0 auto;
119
+ font-size: 16px;
120
+ color: #000;
121
+ background-color: #fff;
122
+ border-radius: 8px;
123
+
124
+ .reportTitle {
125
+ font-weight: bold;
126
+ }
127
+
128
+ .subTitle {
129
+ display: flex;
130
+ justify-content: space-between;
131
+
132
+ .subTitleItems {
133
+ max-width: 30%;
134
+ }
135
+ }
136
+
137
+ .inputsDiv {
138
+ display: flex;
139
+ justify-content: space-between;
140
+ .inputsDivItem {
141
+ display: flex;
142
+ align-items: center;
143
+ padding: 0 4px;
144
+ white-space: nowrap;
145
+ .inputsDivItemLabel {
146
+ padding: 0 4px;
147
+ }
148
+ }
149
+ }
150
+
151
+ .reportTable {
152
+ width: 100%;
153
+ border-collapse: collapse;
154
+ table-layout:fixed;
155
+ word-break:break-all;
156
+ }
157
+ }
158
+ .tools{
159
+ position: fixed;
160
+ right: 2%;
161
+ text-align: right;
162
+ width: 60%;
163
+ cursor: pointer;
164
+ .toolsItem{
165
+ width: 15%;
166
+ margin-right: 3%;
167
+ display: inline-block;
168
+ }
169
+ }
170
+ </style>
171
+ </head>
172
+ <body>
173
+ <!-- 将需要打印的元素内容复制到新窗口中 -->
174
+ ${elementToPrint.innerHTML}
175
+ </body>
176
+ </html>
177
+ `)
178
+ // 延迟执行打印,以确保新窗口的内容已加载完成
179
+ printWindow.document.close() // 关闭文档流,确保内容完全加载
180
+ setTimeout(() => {
181
+ printWindow.print() // 调用打印方法
182
+ printWindow.close()
183
+ }, 500) // 延迟500毫秒后执行打印
184
+ }
@@ -13,7 +13,7 @@ import ComponentView from '@af-mobile-client-vue3/views/component/index.vue'
13
13
  import UserDetailView from '@af-mobile-client-vue3/views/component/UserDetailView/index.vue'
14
14
  import UserDetailPage from '@af-mobile-client-vue3/views/component/UserDetailView/UserDetailPage.vue'
15
15
  import XCellDetailView from '@af-mobile-client-vue3/views/component/XCellDetailView/index.vue'
16
- import XCellListView from '@af-mobile-client-vue3/views/user/my/index.vue'
16
+ import XCellListView from '@af-mobile-client-vue3/views/component/XCellListView/index.vue'
17
17
  import XFormAppraiseView from '@af-mobile-client-vue3/views/component/XFormAppraiseView/index.vue'
18
18
  import XFormGroupView from '@af-mobile-client-vue3/views/component/XFormGroupView/index.vue'
19
19
  import XFormView from '@af-mobile-client-vue3/views/component/XFormView/index.vue'
@@ -19,6 +19,7 @@ import { getPlatformRoutePrefix } from '@af-mobile-client-vue3/types/platform'
19
19
  import crypto from '@af-mobile-client-vue3/utils/crypto'
20
20
  import { encryptUtil } from '@af-mobile-client-vue3/utils/EncryptUtil'
21
21
  import { indexedDB } from '@af-mobile-client-vue3/utils/indexedDB'
22
+ import { secureStorageWrite } from '@af-mobile-client-vue3/utils/secureStorage'
22
23
  import { createStorage } from '@af-mobile-client-vue3/utils/Storage'
23
24
  import { defineStore } from 'pinia'
24
25
  import { ref } from 'vue'
@@ -213,8 +214,10 @@ export const useUserStore = defineStore('app-user', () => {
213
214
  setToken(data.access_token)
214
215
  // 第三方教培系统鉴权兼容
215
216
  const LoginTicket = crypto.AESEncrypt(JSON.stringify(params), '3KMKqvgwR8ULbR8Z')
216
- if (data.session && useSettingStore().getSetting().requestEncrypt) {
217
- localStorage.setItem('v4-session-key', encryptUtil.RSADecrypt(data.session as string))
217
+ if (data.session && useSettingStore().getSetting()?.requestEncrypt) {
218
+ const k = encryptUtil.RSADecrypt(data.session as string)
219
+ localStorage.setItem('v4-session-key', k)
220
+ secureStorageWrite('v4-session-key', k)
218
221
  }
219
222
  Storage.set('LoginTicket', LoginTicket)
220
223
  }
@@ -294,6 +297,8 @@ export const useUserStore = defineStore('app-user', () => {
294
297
  Storage.remove(PLATFORM_TYPE)
295
298
  Storage.remove(EXTERNAL_USER_INFO)
296
299
  Storage.remove('LoginTicket')
300
+ localStorage.removeItem('v4-session-key')
301
+ secureStorageWrite('v4-session-key', '')
297
302
  await indexedDB.clearDB()
298
303
  await useSettingStore().init()
299
304
  try {
@@ -1,27 +1,27 @@
1
- // 时间工具:提供简单的日期时间格式化
2
-
3
- export function pad2(num: number): string {
4
- return num < 10 ? `0${num}` : `${num}`
5
- }
6
-
7
- /**
8
- * 按照简单占位符格式化当前时间
9
- * 支持占位:YYYY MM DD HH mm ss
10
- * @param format 默认 'YYYY-MM-DD HH:mm:ss'
11
- */
12
- export function formatNow(format: string = 'YYYY-MM-DD HH:mm:ss'): string {
13
- const d = new Date()
14
- const map: Record<string, string> = {
15
- YYYY: `${d.getFullYear()}`,
16
- MM: pad2(d.getMonth() + 1),
17
- DD: pad2(d.getDate()),
18
- HH: pad2(d.getHours()),
19
- mm: pad2(d.getMinutes()),
20
- ss: pad2(d.getSeconds()),
21
- }
22
- let out = format
23
- Object.keys(map).forEach((k) => {
24
- out = out.replace(new RegExp(k, 'g'), map[k])
25
- })
26
- return out
27
- }
1
+ // 时间工具:提供简单的日期时间格式化
2
+
3
+ export function pad2(num: number): string {
4
+ return num < 10 ? `0${num}` : `${num}`
5
+ }
6
+
7
+ /**
8
+ * 按照简单占位符格式化当前时间
9
+ * 支持占位:YYYY MM DD HH mm ss
10
+ * @param format 默认 'YYYY-MM-DD HH:mm:ss'
11
+ */
12
+ export function formatNow(format: string = 'YYYY-MM-DD HH:mm:ss'): string {
13
+ const d = new Date()
14
+ const map: Record<string, string> = {
15
+ YYYY: `${d.getFullYear()}`,
16
+ MM: pad2(d.getMonth() + 1),
17
+ DD: pad2(d.getDate()),
18
+ HH: pad2(d.getHours()),
19
+ mm: pad2(d.getMinutes()),
20
+ ss: pad2(d.getSeconds()),
21
+ }
22
+ let out = format
23
+ Object.keys(map).forEach((k) => {
24
+ out = out.replace(new RegExp(k, 'g'), map[k])
25
+ })
26
+ return out
27
+ }
@@ -5,10 +5,10 @@ import wx from 'weixin-js-sdk'
5
5
  export interface WechatConfig {
6
6
  debug: boolean
7
7
  appId: string
8
- timestamp: number
8
+ timestamp: string
9
9
  nonceStr: string
10
10
  signature: string
11
- jsApiList: any[]
11
+ jsApiList: string[]
12
12
  }
13
13
 
14
14
  // 微信扫码配置
@@ -63,10 +63,36 @@ export function configWechatSDK(config: WechatConfig): Promise<void> {
63
63
  })
64
64
  }
65
65
 
66
+ // 微信扫码
67
+ export function scanQRCode(config: WechatScanConfig): Promise<WechatScanResult> {
68
+ return new Promise((resolve, reject) => {
69
+ if (!isWechatBrowser()) {
70
+ reject(new Error('非微信环境,无法使用微信扫码'))
71
+ return
72
+ }
73
+
74
+ wx.scanQRCode({
75
+ needResult: config.needResult,
76
+ scanType: config.scanType,
77
+ success: (res: WechatScanResult) => {
78
+ console.log('微信扫码成功:', res)
79
+ resolve(res)
80
+ },
81
+ fail: (res: any) => {
82
+ console.error('微信扫码失败:', res)
83
+ reject(new Error(`微信扫码失败: ${res.errMsg}`))
84
+ },
85
+ cancel: () => {
86
+ reject(new Error('用户取消扫码'))
87
+ },
88
+ })
89
+ })
90
+ }
91
+
66
92
  // 获取微信签名(模拟)
67
93
  export async function getWechatSignature(url: string): Promise<{
68
94
  appId: string
69
- timestamp: number
95
+ timestamp: string
70
96
  nonceStr: string
71
97
  signature: string
72
98
  }> {
@@ -9,11 +9,11 @@ const emit = defineEmits(['deleteRow'])
9
9
  // 访问路由
10
10
  const router = useRouter()
11
11
  // 获取默认值
12
- // const idKey = ref('o_id')
12
+ const idKey = ref('o_id')
13
13
 
14
14
  // 简易crud表单测试
15
- const configName = ref('ceshiCRUD')
16
- const serviceName = ref('af-safecheck')
15
+ const configName = ref('mobile_instrumentManageCRUD')
16
+ const serviceName = ref('af-revenue')
17
17
 
18
18
  // 资源权限测试
19
19
  // const configName = ref('crud_sources_test')
@@ -83,17 +83,14 @@ const serviceName = ref('af-safecheck')
83
83
  // })
84
84
  // }
85
85
 
86
- // 删除功能
86
+ // // 删除功能
87
87
  // function deleteRow(result) {
88
88
  // emit('deleteRow', result.o_id)
89
89
  // }
90
- // const fixQueryForm = ref({
91
- // f_operator_id: '487184754014158848',
92
- // })
93
90
  </script>
94
91
 
95
92
  <template>
96
- <NormalDataLayout id="XCellListView" title="工作计划">
93
+ <NormalDataLayout id="XCellListView" title="测试">
97
94
  <template #layout_content>
98
95
  <XCellList
99
96
  :config-name="configName"
@@ -6,8 +6,8 @@ import { ref } from 'vue'
6
6
  import { useRoute } from 'vue-router'
7
7
 
8
8
  // 纯表单
9
- const configName = ref('appapplyuserinfoFormGroup')
10
- const serviceName = ref('af-apply')
9
+ const configName = ref('form_check_test')
10
+ const serviceName = ref('af-system')
11
11
 
12
12
  // const configName = ref("计划下发Form")
13
13
  // const serviceName = ref("af-linepatrol")
@@ -16,20 +16,16 @@ const serviceName = ref('af-apply')
16
16
  // const configName = ref('lngChargeAuditMobileFormGroup')
17
17
  // const serviceName = ref('af-gaslink')
18
18
 
19
- const formData = ref({ t_userinfo: { f_user_name: 111 } })
19
+ const formData = ref({})
20
20
  const formGroup = ref(null)
21
21
  const route = useRoute()
22
22
  const isInit = ref(false)
23
23
  function submit(_result) {
24
- showDialog({ message: '提交成功' })
25
- history.back()
26
- }
27
- const myXForm = ref([])
28
- function setRef(value: any) {
29
- console.log('myXForm', myXForm)
30
- formGroup.value.setRef(myXForm.value)
31
- console.log(formGroup)
24
+ showDialog({ message: '提交成功' }).then(() => {
25
+ history.back()
26
+ })
32
27
  }
28
+
33
29
  // 表单组——数据
34
30
  // function initComponents () {
35
31
  // runLogic('getlngChargeAuditMobileFormGroupData', {id: 29}, 'af-gaslink').then((res) => {
@@ -59,16 +55,11 @@ function setRef(value: any) {
59
55
  // onBeforeMount(() => {
60
56
  // initComponents()
61
57
  // })
62
- function a() {
63
- }
64
58
  </script>
65
59
 
66
60
  <template>
67
61
  <NormalDataLayout id="XFormGroupView" title="纯表单">
68
62
  <template #layout_content>
69
- <button @click="a">
70
- 修改
71
- </button>
72
63
  <!-- v-if="isInit" -->
73
64
  <XFormGroup
74
65
  ref="formGroup"
@@ -77,11 +68,7 @@ function a() {
77
68
  :group-form-data="formData"
78
69
  mode="新增"
79
70
  @submit="submit"
80
- >
81
- <!-- <template #device="{ setRef, removeRef, item, formData }">
82
- <XFormView :setRef="setRef" :formGroupName="'myXForm'"/>
83
- </template> -->
84
- </XFormGroup>
71
+ />
85
72
  </template>
86
73
  </NormalDataLayout>
87
74
  </template>
@@ -1,56 +1,36 @@
1
1
  <script setup lang="ts">
2
2
  import XForm from '@af-mobile-client-vue3/components/data/XForm/index.vue'
3
3
  import NormalDataLayout from '@af-mobile-client-vue3/components/layout/NormalDataLayout/index.vue'
4
- import { mobileUtil } from '@af-mobile-client-vue3/utils/mobileUtil'
5
4
  import { ref } from 'vue'
6
- import {
7
- showFailToast,
8
- showSuccessToast,
9
- Button as VanButton,
10
- CellGroup as VanCellGroup,
11
- Form as VanForm,
12
- } from 'vant'
13
5
 
14
- const configName = ref('lngSecurityChecktestForm')
15
- const serviceName = ref('af-safecheck')
16
- function aaa() {
17
- mobileUtil.execute({
18
- funcName: 'startNfcScan',
19
- param: { a: 1 },
20
- callbackFunc: (result) => {
21
- console.log('回调了test111', JSON.stringify(result))
22
- return 222
23
- },
24
- })
25
- }
26
- function bbb() {
27
- mobileUtil.execute({
28
- funcName: 'scanBarcode',
29
- param: { a: 1 },
30
- callbackFunc: (result) => {
31
- console.log('回调了test111', JSON.stringify(result))
32
- return 222
33
- },
34
- })
35
- }
6
+ const configName = ref('ceshiForm')
7
+ const serviceName = ref('af-system')
8
+
36
9
  const formGroupAddConstruction = ref(null)
10
+ const formData = ref({
11
+ 'YYYY': '2025-09-08 16:03:22',
12
+ 'YYYY-MM': '2025-09-08 16:03:22',
13
+ 'YYYY-MM-DD': '2025-09-08 16:03:22',
14
+ 'YYYY-MM-DDHH': '2025-09-08 16:03:22',
15
+ 'YYYY-MM-DDHHMM': '2025-09-08 16:03:22',
16
+ 'YYYY-MM-DDHHMMSS': '2025-09-08 16:03:22',
17
+ })
18
+
19
+ function onSubmit(data: any) {
20
+ console.warn('提交表单', data)
21
+ }
37
22
  </script>
38
23
 
39
24
  <template>
40
25
  <NormalDataLayout id="XFormGroupView" title="纯表单">
41
26
  <template #layout_content>
42
- <VanButton @click="aaa">
43
- 测试nfc
44
- </VanButton>
45
- <VanButton @click="bbb">
46
- 扫码
47
- </VanButton>
48
27
  <XForm
49
28
  ref="formGroupAddConstruction"
50
- mode="新增"
29
+ mode="修改"
51
30
  :config-name="configName"
52
31
  :service-name="serviceName"
53
- :form-readonly="false"
32
+ :form-data="formData"
33
+ @on-submit="onSubmit"
54
34
  />
55
35
  </template>
56
36
  </NormalDataLayout>
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://192.168.50.67:31567'
15
- const v3Server = 'http://192.168.50.67:31567'
14
+ const v4Server = 'http://117.35.109.162:31577'
15
+ const v3Server = 'http://117.35.109.162:31577'
16
16
  const OSSServerDev = 'http://192.168.50.67:30351'
17
17
  const geoserver = 'http://39.104.49.8:30372'
18
18
  const mockServer = 'http://127.0.0.1:8086'
@@ -64,6 +64,13 @@ export default ({ mode }: ConfigEnv): UserConfig => {
64
64
  changeOrigin: true,
65
65
  rewrite: path => path.replace(/^\/linepatrol\/geoserver/, '/geoserver'),
66
66
  },
67
+ // '/api/af-revenue': {
68
+ // // target: v4Server,
69
+ // rewrite: (path: string) => path.replace(/^\/api\/af-revenue\//, '/'),
70
+ // target: 'http://127.0.0.1:9026',
71
+ // ws: false,
72
+ // changeOrigin: true,
73
+ // },
67
74
  '/api': {
68
75
  // v3用
69
76
  // rewrite: (path: string) => path.replace(/^\/api\/af-system\//, '/rs/'),
@@ -1,53 +0,0 @@
1
- // mock/modules/prose.mock.ts
2
- import { defineMock } from "vite-plugin-mock-dev-server/helper";
3
-
4
- // mock/data.ts
5
- import { defineMockData } from "vite-plugin-mock-dev-server/helper";
6
- var data_default = defineMockData("proses", [
7
- "\u{1F516} \u8EB2\u5728\u67D0\u4E00\u65F6\u95F4\uFF0C\u60F3\u5FF5\u4E00\u6BB5\u65F6\u5149\u7684\u638C\u7EB9;\u8EB2\u5728\u67D0\u4E00\u5730\u70B9\uFF0C\u60F3\u5FF5\u4E00\u4E2A\u7AD9\u5728\u6765\u8DEF\u4E5F\u7AD9\u5728\u53BB\u8DEF\u7684\uFF0C\u8BA9\u6211\u7275\u6302\u7684\u4EBA\u3002",
8
- "\u{1F516} \u5929\u7A7A\u4E00\u78A7\u5982\u6D17\uFF0C\u707F\u70C2\u7684\u9633\u5149\u6B63\u4ECE\u5BC6\u5BC6\u7684\u677E\u9488\u7684\u7F1D\u9699\u95F4\u5C04\u4E0B\u6765\uFF0C\u5F62\u6210\u4E00\u675F\u675F\u7C97\u7C97\u7EC6\u7EC6\u7684\u5149\u67F1\uFF0C\u628A\u98D8\u8361\u7740\u8F7B\u7EB1\u822C\u8584\u96FE\u7684\u6797\u836B\u7167\u5F97\u901A\u4EAE\u3002",
9
- "\u{1F516} \u8FD9\u4E00\u6B21\u76F8\u9047\uFF0C\u7F8E\u5F97\u5F7B\u9AA8\uFF0C\u7F8E\u5F97\u9707\u98A4\uFF0C\u7F8E\u5F97\u5B64\u7EDD\uFF0C\u7F8E\u5F97\u60CA\u8273\u3002",
10
- "\u{1F516} \u6C89\u9ED8\u7684\u72B6\u6001\uFF0C\u80FD\u8BA9\u6211\u611F\u89C9\u5230\u547C\u5438\u7684\u81EA\u7531\u548C\u81EA\u5DF1\u539F\u6765\u5C31\u5904\u4E8E\u7684\u672C\u8272\u4F4D\u7F6E\u3002",
11
- "\u{1F516} \u9752\u6625\uFF0C\u662F\u4E00\u5305\u8C61\u5F81\u7740\u9633\u5149\u7684\u5411\u65E5\u8475\u79CD\u5B50\uFF0C\u5728\u73B0\u5728\u6D12\u4E0B\uFF0C\u5C31\u4F1A\u5728\u672A\u6765\u5F97\u5230\u6536\u83B7\uFF0C\u90A3\u4E00\u682A\u682A\u9971\u542B\u9752\u6625\u7684\u82B1\u6735\u3002",
12
- "\u{1F516} \u71D5\u5B50\u53BB\u4E86\uFF0C\u6709\u518D\u6765\u7684\u65F6\u5019;\u6768\u67F3\u67AF\u4E86\uFF0C\u6709\u518D\u9752\u7684\u65F6\u5019;\u6843\u82B1\u8C22\u4E86\uFF0C\u6709\u518D\u5F00\u7684\u65F6\u5019\u3002\u4F46\u662F\uFF0C\u806A\u660E\u7684\uFF0C\u4F60\u544A\u8BC9\u6211\uFF0C\u6211\u4EEC\u7684\u65E5\u5B50\u4E3A\u4EC0\u4E48\u4E00\u53BB\u4E0D\u590D\u8FD4\u5462?",
13
- "\u{1F516} \u6BD5\u4E1A\u4E86\uFF0C\u9752\u6625\u5728\u65E0\u5F62\u4E4B\u4E2D\u79BB\u53BB\uFF0C\u6211\u4EEC\u5373\u5C06\u7FFB\u5F00\u4EBA\u751F\u7684\u53E6\u4E00\u9875\u3002",
14
- "\u{1F516} \u6210\u957F\uFF0C\u662F\u6BCF\u4E2A\u5B69\u5B50\u7684\u6743\u529B\uFF0C\u4E5F\u662F\u4ED6\u4EEC\u5FC5\u7ECF\u7684\u5F81\u7A0B\uFF0C\u6216\u5E73\u5766\u3001\u6216\u5D0E\u5C96\uFF0C\u6709\u60B2\u6B22\uFF0C\u6709\u79BB\u5408\u3002",
15
- "\u{1F516} \u65E7\u65F6\u5149\u91CC\u7684\u4EBA\u548C\u4E8B\uFF0C\u7410\u788E\u800C\u96F6\u4E71\u3002\u6211\u7684\u8BB0\u5FC6\u5F88\u6A21\u7CCA\uFF0C\u597D\u50CF\u5927\u90E8\u5206\u90FD\u6210\u4E86\u4E00\u79CD\u6E29\u99A8\u7684\u7B26\u53F7\uFF0C\u9759\u9759\u7684\u6C89\u5728\u6211\u5FC3\u5E95\u3002",
16
- "\u{1F516} \u751F\u6D3B\u662F\u4E00\u90E8\u5927\u767E\u79D1\u5168\u4E66\uFF0C\u5305\u7F57\u4E07\u8C61;\u751F\u6D3B\u662F\u4E00\u628A\u516D\u5F26\u7434\uFF0C\u5F39\u594F\u51FA\u591A\u91CD\u7F8E\u5999\u7684\u65CB\u5F8B\uFF1A\u751F\u6D3B\u662F\u4E00\u5EA7\u98DE\u9A6C\u724C\u5927\u949F\uFF0C\u4E0A\u7D27\u53D1\u6761\uFF0C\u4FBF\u4F1A\u4F7F\u4EBA\u83B7\u5F97\u6D53\u7F29\u7684\u751F\u547D\u3002",
17
- "\u{1F516} \u6BD5\u4E1A\u4E86\uFF0C\u8EAB\u8FB9\u7684\u670B\u53CB\u4E00\u4E2A\u4E2A\u5404\u5954\u4E1C\u897F\uFF0C\u5F00\u59CB\u5B66\u4F1A\u81EA\u5DF1\u6491\u8D77\u751F\u547D\u7684\u6696\u8272\u3002",
18
- "\u{1F516} \u5DF2\u7ECF\u8D70\u5230\u5C3D\u5934\u7684\u4E1C\u897F\uFF0C\u91CD\u751F\u4E5F\u4E0D\u8FC7\u662F\u518D\u4E00\u6B21\u7684\u6D88\u4EA1\u3002\u5C31\u50CF\u6240\u6709\u7684\u5F00\u59CB\uFF0C\u5176\u5B9E\u90FD\u53EA\u662F\u4E00\u4E2A\u5199\u597D\u4E86\u7684\u7ED3\u5C40\u3002",
19
- "\u{1F516} \u4E0B\u5348\u8336\u7684\u82AC\u9999\u718F\u9676\u7740\u623F\u5185\u7684\u4EFB\u4F55\u4E00\u4E2A\u89D2\u843D\uFF0C\u5348\u540E\u7684\u9633\u5149\u900F\u8FC7\u7A97\u5E18\u7684\u95F4\u9699\u6D12\u5728\u6728\u5236\u7684\u684C\u9762\u4E0A\uFF0C\u4E00\u4EFD\u601D\u5FF5\u968F\u7740\u7EA2\u8336\u987A\u6ED1\u81F3\u5FC3\u4E2D\u3002",
20
- "\u{1F516} \u8FD9\u91CC\u518D\u4E0D\u662F\u6211\u4EEC\u7684\u6821\u56ED\uFF0C\u5F53\u6211\u4EEC\u5C31\u6B64\u79BB\u5F00\u6211\u4EEC\u7684\u9752\u8471\u5C81\u6708\u3002",
21
- "\u{1F516} \u5F88\u4E45\u627E\u4F60\uFF0C\u4E00\u76F4\u6CA1\u6709\u627E\u5230\uFF0C\u5FAE\u98CE\u5439\u8FC7\u7684\u65F6\u5019\uFF0C\u6211\u6DF1\u6DF1\u7684\u547C\u5438\uFF0C\u624D\u611F\u89C9\u5230\u4F60\u4E5F\u5728\u966A\u4F34\u7740\u6211\u547C\u5438\u3002"
22
- ]);
23
-
24
- // mock/util.ts
25
- var responseBody = {
26
- message: "",
27
- timestamp: 0,
28
- result: null,
29
- code: 0
30
- };
31
- function builder(data, message = "success", code = 0) {
32
- responseBody.result = data;
33
- if (message !== void 0 && message !== null)
34
- responseBody.message = message;
35
- if (code !== void 0 && code !== 0)
36
- responseBody.code = code;
37
- responseBody.timestamp = (/* @__PURE__ */ new Date()).getTime();
38
- return responseBody;
39
- }
40
-
41
- // mock/modules/prose.mock.ts
42
- var prose_mock_default = defineMock({
43
- url: "/api/prose",
44
- delay: 100,
45
- body: () => {
46
- const rand = Math.floor(Math.random() * data_default.value.length);
47
- const prose = data_default.value[rand];
48
- return builder(prose);
49
- }
50
- });
51
- export {
52
- prose_mock_default as default
53
- };
@@ -1,124 +0,0 @@
1
- # HomeApp Store 使用说明
2
-
3
- ## 概述
4
- `useHomeAppStore` 是一个专门用于管理首页应用列表的 Pinia store,与 `useSettingStore` 配合使用。
5
-
6
- ## 特性
7
- - 独立管理 `homeAppList` 数据
8
- - 提供完整的 CRUD 操作
9
- - 与 setting store 自动同步数据
10
- - 支持类型安全的 TypeScript 接口
11
-
12
- ## 基本使用
13
-
14
- ### 1. 导入和使用
15
- ```typescript
16
- import { useHomeAppStore } from '@/stores'
17
-
18
- const homeAppStore = useHomeAppStore()
19
- ```
20
-
21
- ### 2. 获取应用列表
22
- ```typescript
23
- // 获取所有应用
24
- const apps = homeAppStore.getHomeAppList()
25
-
26
- // 直接访问响应式数据
27
- const apps = homeAppStore.homeAppList
28
- ```
29
-
30
- ### 3. 添加应用
31
- ```typescript
32
- homeAppStore.addHomeApp({
33
- id: 'new-app',
34
- name: '新应用',
35
- icon: '/icon.png',
36
- url: 'https://example.com',
37
- description: '应用描述'
38
- })
39
- ```
40
-
41
- ### 4. 更新应用
42
- ```typescript
43
- homeAppStore.updateHomeApp('app-id', {
44
- name: '更新后的名称',
45
- description: '新的描述'
46
- })
47
- ```
48
-
49
- ### 5. 删除应用
50
- ```typescript
51
- homeAppStore.removeHomeApp('app-id')
52
- ```
53
-
54
- ### 6. 清空列表
55
- ```typescript
56
- homeAppStore.clearHomeAppList()
57
- ```
58
-
59
- ## 数据同步
60
-
61
- ### 自动同步
62
- - 当 `useSettingStore.init()` 被调用时,`homeAppList` 会自动同步到 `useHomeAppStore`
63
- - 无需手动同步,数据会自动保持一致
64
-
65
- ### 手动同步
66
- ```typescript
67
- import { useSettingStore, useHomeAppStore } from '@/stores'
68
-
69
- const settingStore = useSettingStore()
70
- const homeAppStore = useHomeAppStore()
71
-
72
- // 手动同步数据
73
- homeAppStore.setHomeAppList(settingStore.getSetting()?.homeAppList || [])
74
- ```
75
-
76
- ## 在组件中使用
77
-
78
- ### Vue 组件示例
79
- ```vue
80
- <template>
81
- <div class="home-apps">
82
- <div
83
- v-for="app in homeAppStore.homeAppList"
84
- :key="app.id"
85
- class="app-item"
86
- @click="openApp(app)"
87
- >
88
- <img :src="app.icon" :alt="app.name" />
89
- <span>{{ app.name }}</span>
90
- </div>
91
- </div>
92
- </template>
93
-
94
- <script setup lang="ts">
95
- import { useHomeAppStore } from '@/stores'
96
-
97
- const homeAppStore = useHomeAppStore()
98
-
99
- function openApp(app) {
100
- // 处理应用点击
101
- window.open(app.url, '_blank')
102
- }
103
- </script>
104
- ```
105
-
106
- ## 注意事项
107
-
108
- 1. **初始化顺序**:确保先调用 `useSettingStore.init()`,再使用 `useHomeAppStore`
109
- 2. **数据一致性**:两个 store 中的数据会自动保持同步
110
- 3. **类型安全**:使用 TypeScript 接口确保类型安全
111
- 4. **响应式**:所有数据都是响应式的,可以直接在模板中使用
112
-
113
- ## 接口定义
114
-
115
- ```typescript
116
- export interface HomeApp {
117
- id: string // 应用唯一标识
118
- name: string // 应用名称
119
- icon: string // 应用图标
120
- url: string // 应用链接
121
- description?: string // 应用描述(可选)
122
- [key: string]: any // 其他属性
123
- }
124
- ```
@@ -1,111 +0,0 @@
1
- /**
2
- * 加密相关类型定义
3
- */
4
-
5
- /**
6
- * 加密模式枚举
7
- */
8
- export enum CryptoMode {
9
- /** ECB模式 */
10
- ECB = 'ECB',
11
- /** CBC模式 */
12
- CBC = 'CBC',
13
- }
14
-
15
- /**
16
- * 填充方式枚举
17
- */
18
- export enum PaddingMode {
19
- /** PKCS7填充 */
20
- PKCS7 = 'Pkcs7',
21
- }
22
-
23
- /**
24
- * AES加密配置接口
25
- */
26
- export interface AESConfig {
27
- /** 加密模式 */
28
- mode: CryptoMode
29
- /** 填充方式 */
30
- padding: PaddingMode
31
- }
32
-
33
- /**
34
- * AES CBC模式加密结果接口
35
- */
36
- export interface AESCBCResult {
37
- /** IV的Base64编码 */
38
- iv: string
39
- /** 密文的Base64编码 */
40
- ciphertext: string
41
- /** 组合格式:IV:密文 */
42
- combined: string
43
- }
44
-
45
- /**
46
- * 加密工具类接口
47
- */
48
- export interface IEncryptUtil {
49
- /**
50
- * AES ECB模式加密
51
- * @param word 待加密的字符串
52
- * @param encryKey 加密密钥
53
- * @returns 加密后的字符串
54
- */
55
- AESEncrypt(word: string, encryKey: string): string
56
-
57
- /**
58
- * AES ECB模式解密
59
- * @param word 待解密的字符串
60
- * @param encryKey 解密密钥
61
- * @returns 解密后的数据(可能是字符串或对象)
62
- */
63
- AESDecrypt(word: string, encryKey: string): string | object
64
-
65
- /**
66
- * RSA加密
67
- * @param word 待加密的字符串
68
- * @returns 加密后的字符串
69
- */
70
- RSAEncrypt(word: string): string
71
-
72
- /**
73
- * RSA解密
74
- * @param word 待解密的字符串
75
- * @returns 解密后的对象
76
- */
77
- RSADecrypt(word: string): object
78
-
79
- /**
80
- * AES CBC模式加密
81
- * @param data 待加密的数据
82
- * @param cryptoKey 十六进制格式的加密密钥
83
- * @returns 组合格式的加密结果
84
- */
85
- AESEncryptCBC(data: any, cryptoKey: string): string
86
-
87
- /**
88
- * AES CBC模式解密
89
- * @param combinedText 格式:Base64(iv):Base64(ciphertext)
90
- * @param hexKey 十六进制格式的加密密钥
91
- * @returns 解密后的原始字符串
92
- */
93
- AESDecryptCBC(combinedText: string, hexKey: string): string
94
-
95
- /**
96
- * 安全的AES-CBC解密(失败时返回null)
97
- * @param combinedText 格式:Base64(iv):Base64(ciphertext)
98
- * @param hexKey 十六进制格式的密钥
99
- * @returns 解密后的字符串,失败时返回null
100
- */
101
- safeAESDecryptCBC(combinedText: string, hexKey: string): string | null
102
-
103
- /**
104
- * 智能响应解密
105
- * @param responseData 响应数据
106
- * @param sessionKey 会话密钥
107
- * @returns 解密后的数据,失败时返回原数据
108
- */
109
- decryptResponse(responseData: any, sessionKey: string): any
110
- }
111
-