af-mobile-client-vue3 1.3.12 → 1.3.13

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.
Files changed (270) hide show
  1. package/.claude/settings.local.json +10 -0
  2. package/.cursorrules +60 -60
  3. package/.editorconfig +9 -9
  4. package/.env +10 -10
  5. package/.env.development +1 -1
  6. package/.env.production +1 -1
  7. package/.node-version +1 -1
  8. package/.vscode/extensions.json +12 -12
  9. package/.vscode/settings.json +66 -66
  10. package/CLAUDE.md +189 -184
  11. package/README.md +182 -181
  12. package/af-example-mobile-vue-web.iml +9 -9
  13. package/build/vite/index.ts +98 -98
  14. package/build/vite/optimize.ts +34 -34
  15. package/build/vite/vconsole.ts +47 -47
  16. package/commitlint.config.ts +32 -32
  17. package/compress.js +36 -36
  18. package/eslint.config.ts +30 -30
  19. package/index.html +23 -23
  20. package/mock/data.ts +20 -20
  21. package/mock/index.ts +7 -7
  22. package/mock/modules/prose.mock.ts +13 -13
  23. package/mock/modules/user.mock.ts +152 -152
  24. package/mock/util.ts +19 -19
  25. package/netlify.toml +12 -12
  26. package/package.json +114 -114
  27. package/postcss.config.ts +27 -27
  28. package/public/favicon.svg +4 -4
  29. package/public/safari-pinned-tab.svg +4 -4
  30. package/scripts/verifyCommit.js +19 -19
  31. package/src/App.vue +79 -79
  32. package/src/api/mock/index.ts +30 -30
  33. package/src/api/user/index.ts +40 -40
  34. package/src/assets/img/user/login/background-shadow-1.svg +20 -20
  35. package/src/assets/img/user/login/logo-background.svg +20 -20
  36. package/src/bootstrap.ts +26 -26
  37. package/src/components/core/BeautifulLoading/index.vue +52 -52
  38. package/src/components/core/ImageUploader/index.vue +244 -244
  39. package/src/components/core/NavBar/index.vue +53 -53
  40. package/src/components/core/Tabbar/index.vue +32 -32
  41. package/src/components/core/Uploader/index.vue +124 -124
  42. package/src/components/core/XGridDropOption/index.vue +154 -156
  43. package/src/components/core/XMultiSelect/index.vue +183 -183
  44. package/src/components/core/XSelect/index.vue +149 -149
  45. package/src/components/data/InfoDisplay/index.vue +132 -0
  46. package/src/components/data/UserDetail/api.ts +24 -0
  47. package/src/components/data/UserDetail/index.vue +539 -0
  48. package/src/components/data/UserDetail/recordEntries.ts +159 -0
  49. package/src/components/data/UserDetail/types.ts +26 -0
  50. package/src/components/data/XBadge/index.vue +82 -82
  51. package/src/components/data/XCellDetail/index.vue +105 -105
  52. package/src/components/data/XCellList/XCellList.md +313 -313
  53. package/src/components/data/XCellList/index.vue +1075 -1075
  54. package/src/components/data/XCellListFilter/QrScanner/index.vue +207 -207
  55. package/src/components/data/XCellListFilter/QrScanner/startScanAnimation.ts +53 -53
  56. package/src/components/data/XCellListFilter/VpnRecognition/index.vue +119 -119
  57. package/src/components/data/XCellListFilter/index.vue +705 -705
  58. package/src/components/data/XForm/index.vue +659 -659
  59. package/src/components/data/XFormGroup/doc/DeviceForm.vue +122 -122
  60. package/src/components/data/XFormGroup/doc/FormGroupDemo.vue +56 -56
  61. package/src/components/data/XFormGroup/doc/README.md +286 -273
  62. package/src/components/data/XFormGroup/doc/UserForm.vue +102 -102
  63. package/src/components/data/XFormGroup/index.vue +240 -240
  64. package/src/components/data/XFormItem/index.vue +1310 -1310
  65. package/src/components/data/XOlMap/README.md +227 -227
  66. package/src/components/data/XOlMap/XLocationPicker/index.vue +226 -225
  67. package/src/components/data/XOlMap/index.vue +1490 -1490
  68. package/src/components/data/XOlMap/types.ts +149 -149
  69. package/src/components/data/XOlMap/utils/wgs84ToGcj02.js +154 -154
  70. package/src/components/data/XReportForm/DateTimeSecondsPicker.vue +208 -208
  71. package/src/components/data/XReportForm/XReportFormJsonRender.vue +220 -220
  72. package/src/components/data/XReportForm/index.vue +1393 -1393
  73. package/src/components/data/XReportGrid/XAddReport/XAddReport.vue +198 -198
  74. package/src/components/data/XReportGrid/XAddReport/index.js +3 -3
  75. package/src/components/data/XReportGrid/XAddReport/index.md +53 -52
  76. package/src/components/data/XReportGrid/XAddReport/index.ts +10 -10
  77. package/src/components/data/XReportGrid/XReport.vue +960 -960
  78. package/src/components/data/XReportGrid/XReportDemo.vue +33 -33
  79. package/src/components/data/XReportGrid/XReportDesign.vue +597 -597
  80. package/src/components/data/XReportGrid/XReportDrawer/XReportDrawer.vue +148 -148
  81. package/src/components/data/XReportGrid/XReportDrawer/index.js +3 -3
  82. package/src/components/data/XReportGrid/XReportDrawer/index.ts +10 -10
  83. package/src/components/data/XReportGrid/XReportJsonRender.vue +399 -399
  84. package/src/components/data/XReportGrid/XReportTrGroup.vue +592 -592
  85. package/src/components/data/XReportGrid/index.md +46 -42
  86. package/src/components/data/XReportGrid/print.js +184 -184
  87. package/src/components/data/XSignature/index.vue +284 -285
  88. package/src/components/data/XTag/index.vue +10 -10
  89. package/src/components/layout/NormalDataLayout/index.vue +69 -69
  90. package/src/components/layout/TabBarLayout/index.vue +40 -40
  91. package/src/composables/dark.ts +5 -5
  92. package/src/config/routes.ts +9 -9
  93. package/src/constants/index.ts +2 -2
  94. package/src/enums/requestEnum.ts +25 -25
  95. package/src/expression/ExpressionRunner.ts +28 -28
  96. package/src/expression/TestExpression.ts +510 -510
  97. package/src/expression/core/Delegate.ts +116 -116
  98. package/src/expression/core/Expression.ts +1359 -1359
  99. package/src/expression/core/Program.ts +985 -985
  100. package/src/expression/core/Token.ts +29 -29
  101. package/src/expression/enums/ExpressionType.ts +81 -81
  102. package/src/expression/enums/TokenType.ts +11 -11
  103. package/src/expression/exception/BreakWayException.ts +2 -2
  104. package/src/expression/exception/ContinueWayException.ts +2 -2
  105. package/src/expression/exception/ExpressionException.ts +29 -29
  106. package/src/expression/exception/ReturnWayException.ts +14 -14
  107. package/src/expression/exception/ServiceException.ts +22 -22
  108. package/src/expression/instances/JSONArray.ts +52 -52
  109. package/src/expression/instances/JSONObject.ts +118 -118
  110. package/src/expression/instances/LogicConsole.ts +31 -31
  111. package/src/font-style/font.css +4 -4
  112. package/src/hooks/useBoolean.ts +26 -0
  113. package/src/hooks/useCommon.ts +9 -9
  114. package/src/hooks/useLogin.ts +97 -97
  115. package/src/icons/svg/check-in.svg +32 -32
  116. package/src/icons/svg/dark.svg +4 -4
  117. package/src/icons/svg/github.svg +4 -4
  118. package/src/icons/svg/light.svg +4 -4
  119. package/src/icons/svg/link.svg +4 -4
  120. package/src/icons/svgo.yml +22 -22
  121. package/src/layout/GridView/index.vue +16 -16
  122. package/src/layout/PageLayout.vue +9 -9
  123. package/src/layout/SingleLayout.vue +9 -9
  124. package/src/locales/en-US.json +128 -128
  125. package/src/locales/zh-CN.json +128 -128
  126. package/src/logic/LogicRunner.ts +67 -67
  127. package/src/logic/TestLogic.ts +13 -13
  128. package/src/logic/plugins/common/DateTools.ts +35 -35
  129. package/src/logic/plugins/common/VueTools.ts +30 -30
  130. package/src/logic/plugins/index.ts +7 -7
  131. package/src/main.ts +44 -44
  132. package/src/plugins/AppData.ts +38 -38
  133. package/src/plugins/GetLoginInfoService.ts +10 -10
  134. package/src/plugins/collectIcons.ts +10 -0
  135. package/src/plugins/index.ts +11 -11
  136. package/src/router/README.md +8 -8
  137. package/src/router/guards.ts +59 -59
  138. package/src/router/index.ts +35 -35
  139. package/src/router/invoiceRoutes.ts +33 -33
  140. package/src/router/routes.ts +341 -177
  141. package/src/router/types.ts +7 -7
  142. package/src/services/api/Login.ts +6 -6
  143. package/src/services/api/common.ts +109 -109
  144. package/src/services/api/index.ts +7 -7
  145. package/src/services/api/manage.ts +8 -8
  146. package/src/services/api/search.ts +16 -16
  147. package/src/services/api/user.ts +17 -17
  148. package/src/services/restTools.ts +56 -56
  149. package/src/services/v3Api.ts +147 -147
  150. package/src/stores/index.ts +11 -11
  151. package/src/stores/modules/counter.ts +19 -19
  152. package/src/stores/modules/routeCache.ts +23 -23
  153. package/src/stores/modules/setting.ts +76 -76
  154. package/src/stores/modules/user.ts +235 -235
  155. package/src/stores/mutation-type.ts +7 -7
  156. package/src/styles/app.less +36 -36
  157. package/src/styles/login.less +109 -109
  158. package/src/styles/var.less +16 -16
  159. package/src/types/env.d.ts +16 -16
  160. package/src/types/settings.ts +1 -1
  161. package/src/types/vue-router.d.ts +9 -9
  162. package/src/utils/Storage.ts +124 -124
  163. package/src/utils/authority-utils.ts +84 -84
  164. package/src/utils/common.ts +41 -41
  165. package/src/utils/crypto.ts +39 -39
  166. package/src/utils/dataUtil.ts +42 -42
  167. package/src/utils/dictUtil.ts +52 -52
  168. package/src/utils/http/index.ts +199 -199
  169. package/src/utils/i18n.ts +72 -72
  170. package/src/utils/indexedDB.ts +195 -195
  171. package/src/utils/inline-px-to-vw.ts +28 -28
  172. package/src/utils/mobileUtil.ts +34 -34
  173. package/src/utils/progress.ts +19 -19
  174. package/src/utils/routerUtil.ts +271 -271
  175. package/src/utils/runEvalFunction.ts +13 -13
  176. package/src/utils/secureStorage.ts +71 -71
  177. package/src/utils/set-page-title.ts +5 -5
  178. package/src/utils/validate.ts +6 -6
  179. package/src/utils/wechatUtil.ts +9 -9
  180. package/src/views/chat/index.vue +153 -153
  181. package/src/views/common/LoadError.vue +63 -63
  182. package/src/views/common/NotFound.vue +67 -67
  183. package/src/views/component/EvaluateRecordView/index.vue +40 -40
  184. package/src/views/component/IconifyView/index.vue +504 -507
  185. package/src/views/component/UserDetailView/UserDetailPage.vue +77 -0
  186. package/src/views/component/UserDetailView/index.vue +224 -0
  187. package/src/views/component/XCellDetailView/index.vue +217 -217
  188. package/src/views/component/XCellListView/index.vue +108 -157
  189. package/src/views/component/XFormAppraiseView/index.vue +174 -174
  190. package/src/views/component/XFormGroupView/index.vue +78 -82
  191. package/src/views/component/XFormView/index.vue +27 -27
  192. package/src/views/component/XOlMapView/XLocationPicker/index.vue +118 -118
  193. package/src/views/component/XOlMapView/index.vue +434 -434
  194. package/src/views/component/XOlMapView/testData.ts +64 -64
  195. package/src/views/component/XReportFormIframeView/index.vue +47 -47
  196. package/src/views/component/XReportFormView/index.vue +13 -13
  197. package/src/views/component/XReportGridView/index.vue +17 -17
  198. package/src/views/component/XRequestView/index.vue +234 -234
  199. package/src/views/component/XSignatureView/index.vue +50 -50
  200. package/src/views/component/index.vue +181 -177
  201. package/src/views/component/menu.vue +117 -117
  202. package/src/views/component/notice.vue +46 -46
  203. package/src/views/component/topNav.vue +36 -36
  204. package/src/views/invoiceShow/index.vue +61 -61
  205. package/src/views/user/login/ForgetPasswordForm.vue +94 -94
  206. package/src/views/user/login/LoginForm.vue +346 -346
  207. package/src/views/user/login/LoginTitle.vue +76 -76
  208. package/src/views/user/login/LoginWave.vue +109 -109
  209. package/src/views/user/login/index.vue +22 -22
  210. package/src/views/user/my/comm/ModifyPassword.vue +346 -346
  211. package/src/views/user/my/index.vue +340 -340
  212. package/src/views/userRecords/AbnormalAlarmRecords.vue +21 -0
  213. package/src/views/userRecords/CardReplacementRecords.vue +21 -0
  214. package/src/views/userRecords/ChangeRecords.vue +19 -0
  215. package/src/views/userRecords/CommandViewRecords.vue +20 -0
  216. package/src/views/userRecords/GasCompensationRecords.vue +20 -0
  217. package/src/views/userRecords/InstrumentCollectionRecords.vue +21 -0
  218. package/src/views/userRecords/MeterRecords.vue +20 -0
  219. package/src/views/userRecords/OperateRecords.vue +51 -0
  220. package/src/views/userRecords/OtherChargeRecords.vue +19 -0
  221. package/src/views/userRecords/PaymentRecords.vue +28 -0
  222. package/src/views/userRecords/PriceAdjustmentRecords.vue +19 -0
  223. package/src/views/userRecords/ReplacementRecords.vue +19 -0
  224. package/src/views/userRecords/SafetyRecords.vue +19 -0
  225. package/src/views/userRecords/TransactionRecords.vue +21 -0
  226. package/src/views/userRecords/TransferRecords.vue +19 -0
  227. package/src/views/userRecords/operateRecordDetail/index.vue +316 -0
  228. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/AddUserDetail.vue +124 -0
  229. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/AdvanceDeliveryDetail.vue +88 -0
  230. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/AutoAccountsCancelDetail.vue +205 -0
  231. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/AutoAccountsDetail.vue +192 -0
  232. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/BankDkDetail.vue +192 -0
  233. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/BankPayDetail.vue +192 -0
  234. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/BlacklistDetail.vue +153 -0
  235. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/CancellationDetail.vue +101 -0
  236. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/CardMeterCenterCancelDetail.vue +127 -0
  237. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/CardMeterCenterDetail.vue +153 -0
  238. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/CardOverUserDetail.vue +153 -0
  239. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/ChangeMeterCancelDetail.vue +166 -0
  240. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/ChangeMeterDetail.vue +205 -0
  241. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/DisableManageDetail.vue +127 -0
  242. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/EnableManageDetail.vue +114 -0
  243. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/FaZheChangeDetail.vue +124 -0
  244. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/FeeDeductionDetail.vue +153 -0
  245. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/GasPriceChangeDetail.vue +126 -0
  246. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/InputtorChangeDetail.vue +126 -0
  247. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/IotMeterCenterCancelDetail.vue +114 -0
  248. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/IotMeterCenterDetail.vue +127 -0
  249. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/IotOpenDetail.vue +88 -0
  250. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/MachineCardDetail.vue +101 -0
  251. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/MachineMeterCenterCancelDetail.vue +218 -0
  252. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/MachineMeterCenterDetail.vue +153 -0
  253. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/OffGasAddGasDetail.vue +140 -0
  254. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/OtherChargeCancelDetail.vue +127 -0
  255. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/OtherChargeDetail.vue +114 -0
  256. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/OverUserChangeDetail.vue +127 -0
  257. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/ReBillDetail.vue +127 -0
  258. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/RefundDetail.vue +114 -0
  259. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/ReplaceCardManageCancelDetail.vue +127 -0
  260. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/ReplaceCardManageDetail.vue +114 -0
  261. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/SaleCardGasDetail.vue +140 -0
  262. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/TransferManageCancelDetail.vue +152 -0
  263. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/TransferManageDetail.vue +178 -0
  264. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/UserChangeDetail.vue +123 -0
  265. package/src/views/userRecords/operateRecordDetail/operateRecordDetails/WechatPayDetail.vue +192 -0
  266. package/src/views/userRecords/types.ts +66 -0
  267. package/tsconfig.json +39 -39
  268. package/uno.config.ts +82 -78
  269. package/vite.config.ts +118 -118
  270. package/src/views/component/XFormGroupView/xformgroup222.vue +0 -97
@@ -1,399 +1,399 @@
1
- <script setup lang="ts">
2
- import type { Ref } from 'vue'
3
- import Upload from '@af-mobile-client-vue3/components/core/Uploader/index.vue'
4
- import { Dialog as VanDialog } from 'vant'
5
- import { onBeforeMount, ref } from 'vue'
6
-
7
- interface JsonRenderConfig {
8
- data: Record<string, any>
9
- content: Array<{
10
- type: string
11
- customFunctionForLabel: string
12
- customFunctionForValue: string
13
- jsonArrayDataIndex?: string
14
- }>
15
- title?: {
16
- type: string
17
- value: string
18
- }
19
- style?: Record<string, string>
20
- }
21
-
22
- // Props
23
- const props = defineProps({
24
- config: {
25
- type: Object as () => JsonRenderConfig,
26
- required: true,
27
- },
28
- displayOnly: {
29
- type: Boolean,
30
- default: false,
31
- },
32
- noPadding: {
33
- type: Boolean,
34
- default: false,
35
- },
36
- noTopBorder: {
37
- type: Boolean,
38
- default: false,
39
- },
40
- showTitle: {
41
- type: Boolean,
42
- default: true,
43
- },
44
- imgPrefix: {
45
- type: String,
46
- default: '',
47
- },
48
- serverName: {
49
- type: String,
50
- default: 'af-system',
51
- },
52
- })
53
-
54
- // Emits
55
- const emit = defineEmits<{
56
- (e: 'updateImg', data: any): void
57
- (e: 'update:config', config: JsonRenderConfig): void
58
- }>()
59
-
60
- // 状态
61
- const showImgModal = ref(false)
62
- const showImageSrc = ref('')
63
- const receivedFunction: Ref<Array<{
64
- labelFunction: Function
65
- valueFunction: Function
66
- }>> = ref([])
67
-
68
- // Methods
69
- function checkImg(target: any[]) {
70
- if (!target)
71
- return []
72
- target.forEach((obj) => {
73
- if (obj.url === undefined)
74
- obj.url = obj.path
75
-
76
- if (obj.name === undefined) {
77
- const withOutEndFix = obj.url.split('.')[0]
78
- const temp = withOutEndFix.split('/')
79
- obj.name = temp[temp.length - 1]
80
- }
81
- if (obj.status === undefined)
82
- obj.status = 'done'
83
- })
84
- return target
85
- }
86
-
87
- function setImages(args: any[], item: any, config: any) {
88
- // 如果基础上传组件在初始化完成后,就调用emit了setImage,此时图片并没有变化,直接返回
89
- if (args[2] === 'created')
90
- return
91
-
92
- const result = {
93
- name: item.f_project,
94
- data: args[0],
95
- orignalData: config,
96
- }
97
- emit('updateImg', result)
98
- }
99
-
100
- function determineCellStyle(labelFunctionReturn: any, color = '#000', borderWidth = '1px') {
101
- if (labelFunctionReturn.style) {
102
- // 如果声明了边框颜色
103
- if (labelFunctionReturn.style.borderColor)
104
- color = labelFunctionReturn.style.borderColor
105
-
106
- // 如果声明了边框宽度
107
- if (labelFunctionReturn.style.borderWidth)
108
- borderWidth = labelFunctionReturn.style.borderWidth
109
- }
110
-
111
- // 正常边框单元格
112
- const withBorder = {
113
- border: `${borderWidth} solid ${color}`,
114
- padding: '8px',
115
- }
116
-
117
- // 仅没有上边框单元格
118
- const NoTopBorder = {
119
- borderTopStyle: 'none',
120
- borderLeft: `${borderWidth} solid ${color}`,
121
- borderRight: `${borderWidth} solid ${color}`,
122
- borderBottom: `${borderWidth} solid ${color}`,
123
- padding: '8px',
124
- }
125
-
126
- let result: any
127
- // 判断表头是否有声明的样式
128
- if (labelFunctionReturn.style !== undefined)
129
- result = props.noTopBorder ? { ...NoTopBorder, ...labelFunctionReturn.style } : { ...withBorder, ...labelFunctionReturn.style }
130
- else
131
- result = props.noTopBorder ? { ...NoTopBorder } : { ...withBorder }
132
-
133
- return result
134
- }
135
-
136
- function handleShowImgOk() {
137
- showImgModal.value = false
138
- showImageSrc.value = ''
139
- }
140
-
141
- function handleShowImgCancel() {
142
- showImgModal.value = false
143
- showImageSrc.value = ''
144
- }
145
-
146
- function openImgModal(img: string) {
147
- showImageSrc.value = img
148
- showImgModal.value = true
149
- }
150
-
151
- function formatImgName(imgSrc: string) {
152
- return imgSrc.split('/').pop() || ''
153
- }
154
-
155
- // 生命周期
156
- onBeforeMount(() => {
157
- // 遍历配置,将所有JSON传递的方法保存到一个数组中,并用index来一一对应
158
- for (let i = 0; i < props.config.content.length; i++) {
159
- receivedFunction.value.push({
160
- // eslint-disable-next-line no-new-func
161
- labelFunction: new Function(`return ${props.config.content[i].customFunctionForLabel}`)(),
162
- // eslint-disable-next-line no-new-func
163
- valueFunction: new Function(`return ${props.config.content[i].customFunctionForValue}`)(),
164
- })
165
- }
166
- })
167
- </script>
168
-
169
- <template>
170
- <div id="xreportjsonrender" :class="noPadding ? 'reportMainNoPadding' : 'reportMain'">
171
- <table class="reportTable" :style="config.style ? config.style : ''">
172
- <tbody class="'reportTable'">
173
- <!-- 标题 -->
174
- <tr v-if="showTitle && config.title.type && config.title.type !== ''">
175
- <td :class="noTopBorder ? 'tdWithNoTopBorder' : 'tdWithBorder'" colspan="12">
176
- <template v-if="config.title.type === 'titleKey'">
177
- {{ config.data[config.title.value] }}
178
- </template>
179
- <template v-else-if="config.title.type === 'titleValue'">
180
- {{ config.title.value }}
181
- </template>
182
- </td>
183
- </tr>
184
- <template v-for="(row, rowIndex) in config.content">
185
- <!-- 数据对象是一个Obj -->
186
- <template v-if="row.type === 'jsonKey'">
187
- <tr :key="rowIndex">
188
- <!-- 表头 -->
189
- <td
190
- :class="noTopBorder ? 'tdWithNoTopBorder' : 'tdWithBorder'"
191
- :style="determineCellStyle(receivedFunction[rowIndex].labelFunction(config, row))"
192
- colspan="6"
193
- >
194
- <template v-if="receivedFunction[rowIndex].labelFunction(config).type === 'key'">
195
- {{ config.data[receivedFunction[rowIndex].labelFunction(config).content] }}
196
- </template>
197
- <template v-else-if="receivedFunction[rowIndex].labelFunction(config).type === 'value'">
198
- {{ receivedFunction[rowIndex].labelFunction(config).content }}
199
- </template>
200
- </td>
201
- <!-- 内容 -->
202
- <td
203
- :class="noTopBorder ? 'tdWithNoTopBorder' : 'tdWithBorder'"
204
- :style="determineCellStyle(receivedFunction[rowIndex].valueFunction(config))"
205
- colspan="6"
206
- >
207
- <template v-if="displayOnly">
208
- <template v-if="receivedFunction[rowIndex].valueFunction(config).type === 'key'">
209
- {{ config.data[receivedFunction[rowIndex].valueFunction(config).content] }}
210
- </template>
211
- <template v-else-if="receivedFunction[rowIndex].valueFunction(config).type === 'value'">
212
- {{ receivedFunction[rowIndex].valueFunction(config).content }}
213
- </template>
214
- </template>
215
- <template v-else>
216
- <template v-if="receivedFunction[rowIndex].valueFunction(config).originalKey">
217
- <van-field
218
- :value="config.data[receivedFunction[rowIndex].valueFunction(config).originalKey]"
219
- @input="(val) => emit('update:config', { ...config, data: { ...config.data, [receivedFunction[rowIndex].valueFunction(config).originalKey]: val } })"
220
- />
221
- </template>
222
- <template v-else>
223
- <van-field
224
- :value="config.data[receivedFunction[rowIndex].valueFunction(config).content]"
225
- @input="(val) => emit('update:config', { ...config, data: { ...config.data, [receivedFunction[rowIndex].valueFunction(config).content]: val } })"
226
- />
227
- </template>
228
- </template>
229
- <template v-if="receivedFunction[rowIndex].valueFunction(config).type === 'img'">
230
- <template v-for="(img, imgIndex) in receivedFunction[rowIndex].valueFunction(config).content" :key="imgIndex">
231
- <span class="imgText">
232
- <van-icon type="link" />
233
- <span @click="openImgModal(img)">{{ formatImgName(img) }}</span>
234
- <br>
235
- </span>
236
- </template>
237
- </template>
238
- </td>
239
- </tr>
240
- </template>
241
- <!-- 数据对象是一个Array -->
242
- <template v-else-if="row.type === 'jsonArray'">
243
- <tr v-for="(item, jsonArrayItemIndex) in config.data[row.jsonArrayDataIndex]" :key="`${rowIndex}${jsonArrayItemIndex}`">
244
- <!-- 表头 -->
245
- <td
246
- :class="noTopBorder ? 'tdWithNoTopBorder' : 'tdWithBorder'"
247
- :style="determineCellStyle(receivedFunction[rowIndex].labelFunction(config, item))"
248
- colspan="6"
249
- >
250
- <template v-if="receivedFunction[rowIndex].labelFunction(config, item).type === 'key'">
251
- {{ item[receivedFunction[rowIndex].labelFunction(config, item).content] }}
252
- </template>
253
- <template v-if="receivedFunction[rowIndex].labelFunction(config, item).type === 'value'">
254
- {{ receivedFunction[rowIndex].labelFunction(config, item).content }}
255
- </template>
256
- </td>
257
- <!-- 内容 -->
258
- <td
259
- :class="noTopBorder ? 'tdWithNoTopBorder' : 'tdWithBorder'"
260
- :style="determineCellStyle(receivedFunction[rowIndex].valueFunction(config, item))"
261
- colspan="6"
262
- >
263
- <template v-if="displayOnly">
264
- <template v-if="receivedFunction[rowIndex].valueFunction(config, item).type === 'key'">
265
- {{ item[receivedFunction[rowIndex].valueFunction(config, item).content] }}
266
- </template>
267
- <template v-if="receivedFunction[rowIndex].valueFunction(config, item).type === 'value'">
268
- {{ receivedFunction[rowIndex].valueFunction(config, item).content }}
269
- </template>
270
- <template v-if="receivedFunction[rowIndex].valueFunction(config, item).type === 'imgs'">
271
- <template v-if="!item.imgs || item.imgs.length === 0">
272
- <p style="margin: auto">
273
-
274
- </p>
275
- </template>
276
- <template v-else>
277
- <template v-for="(img, imgIndex) in item.imgs" :key="imgIndex">
278
- <div>
279
- <img :src="img.path" style="max-width: 200px; max-height: 200px">
280
- <p style="margin: auto">
281
- {{ img.path.substring(img.path.lastIndexOf('/') + 1, img.path.lastIndexOf('.')) }}
282
- </p>
283
- </div>
284
- </template>
285
- </template>
286
- </template>
287
- </template>
288
- <template v-else>
289
- <template v-if="receivedFunction[rowIndex].valueFunction(config, item).originalKey">
290
- <template v-if="receivedFunction[rowIndex].valueFunction(config, item).type === 'imgs'">
291
- <Upload
292
- :model="{
293
- type: 'image',
294
- accept: ['*'],
295
- resUploadStock: 1,
296
- pathKey: 'cs',
297
- }"
298
- :outer-container-index="1"
299
- :img-prefix="imgPrefix"
300
- :service-name="serverName"
301
- :images="checkImg(item.imgs)"
302
- upload-style="simple"
303
- @set-files="(...args) => { setImages(args, item, config.data) }"
304
- />
305
- </template>
306
- <template v-else>
307
- <van-field
308
- :value="item[receivedFunction[rowIndex].valueFunction(config, item).originalKey]"
309
- @input="(val) => emit('update:config', { ...config, data: { ...config.data, [receivedFunction[rowIndex].valueFunction(config, item).originalKey]: val } })"
310
- />
311
- </template>
312
- </template>
313
- <template v-else>
314
- <van-field
315
- :value="item[receivedFunction[rowIndex].valueFunction(config, item).content]"
316
- @input="(val) => emit('update:config', { ...config, data: { ...config.data, [receivedFunction[rowIndex].valueFunction(config, item).content]: val } })"
317
- />
318
- </template>
319
- </template>
320
- </td>
321
- </tr>
322
- </template>
323
- </template>
324
- </tbody>
325
- </table>
326
- <!-- 图片展示弹框 -->
327
- <VanDialog
328
- v-model:show="showImgModal"
329
- title="图片"
330
- width="80%"
331
- :z-index="1001"
332
- @confirm="handleShowImgOk"
333
- @cancel="handleShowImgCancel"
334
- >
335
- <div style="width: 100%;display: flex;justify-content: center;align-items: center">
336
- <img :src="showImageSrc" alt="图片">
337
- </div>
338
- </VanDialog>
339
- </div>
340
- </template>
341
-
342
- <style scoped lang="less">
343
- .imgSrc {
344
- color: rgb(24, 144, 255);
345
- font-size: 0.9em;
346
- margin: auto;
347
- }
348
- .imgSrc:hover {
349
- color: rgba(24, 144, 255, 0.8);
350
- font-size: 0.9em;
351
- cursor: pointer;
352
- }
353
- .reportMain {
354
- text-align: center;
355
- margin: 0 auto;
356
- font-size: 16px;
357
- color: #000;
358
- background-color: #fff;
359
- border-radius: 8px;
360
- }
361
-
362
- .reportMainNoPadding {
363
- text-align: center;
364
- margin: 0 auto;
365
- font-size: 16px;
366
- color: #000;
367
- background-color: #fff;
368
- border-radius: 8px;
369
- }
370
-
371
- .reportTitle {
372
- font-weight: bold;
373
- }
374
-
375
- .reportTable {
376
- width: 100%;
377
- border-collapse: collapse;
378
- table-layout: fixed;
379
- word-break: break-all;
380
- }
381
-
382
- .tdWithBorder {
383
- border: 1px solid #000;
384
- padding: 8px;
385
- }
386
-
387
- .imgText:hover {
388
- color: rgb(24, 144, 255);
389
- cursor: pointer;
390
- }
391
-
392
- .tdWithNoTopBorder {
393
- border-top-style: none;
394
- border-left: 1px solid #000;
395
- border-right: 1px solid #000;
396
- border-bottom: 1px solid #000;
397
- padding: 8px;
398
- }
399
- </style>
1
+ <script setup lang="ts">
2
+ import type { Ref } from 'vue'
3
+ import Upload from '@af-mobile-client-vue3/components/core/Uploader/index.vue'
4
+ import { Dialog as VanDialog } from 'vant'
5
+ import { onBeforeMount, ref } from 'vue'
6
+
7
+ interface JsonRenderConfig {
8
+ data: Record<string, any>
9
+ content: Array<{
10
+ type: string
11
+ customFunctionForLabel: string
12
+ customFunctionForValue: string
13
+ jsonArrayDataIndex?: string
14
+ }>
15
+ title?: {
16
+ type: string
17
+ value: string
18
+ }
19
+ style?: Record<string, string>
20
+ }
21
+
22
+ // Props
23
+ const props = defineProps({
24
+ config: {
25
+ type: Object as () => JsonRenderConfig,
26
+ required: true,
27
+ },
28
+ displayOnly: {
29
+ type: Boolean,
30
+ default: false,
31
+ },
32
+ noPadding: {
33
+ type: Boolean,
34
+ default: false,
35
+ },
36
+ noTopBorder: {
37
+ type: Boolean,
38
+ default: false,
39
+ },
40
+ showTitle: {
41
+ type: Boolean,
42
+ default: true,
43
+ },
44
+ imgPrefix: {
45
+ type: String,
46
+ default: '',
47
+ },
48
+ serverName: {
49
+ type: String,
50
+ default: 'af-system',
51
+ },
52
+ })
53
+
54
+ // Emits
55
+ const emit = defineEmits<{
56
+ (e: 'updateImg', data: any): void
57
+ (e: 'update:config', config: JsonRenderConfig): void
58
+ }>()
59
+
60
+ // 状态
61
+ const showImgModal = ref(false)
62
+ const showImageSrc = ref('')
63
+ const receivedFunction: Ref<Array<{
64
+ labelFunction: Function
65
+ valueFunction: Function
66
+ }>> = ref([])
67
+
68
+ // Methods
69
+ function checkImg(target: any[]) {
70
+ if (!target)
71
+ return []
72
+ target.forEach((obj) => {
73
+ if (obj.url === undefined)
74
+ obj.url = obj.path
75
+
76
+ if (obj.name === undefined) {
77
+ const withOutEndFix = obj.url.split('.')[0]
78
+ const temp = withOutEndFix.split('/')
79
+ obj.name = temp[temp.length - 1]
80
+ }
81
+ if (obj.status === undefined)
82
+ obj.status = 'done'
83
+ })
84
+ return target
85
+ }
86
+
87
+ function setImages(args: any[], item: any, config: any) {
88
+ // 如果基础上传组件在初始化完成后,就调用emit了setImage,此时图片并没有变化,直接返回
89
+ if (args[2] === 'created')
90
+ return
91
+
92
+ const result = {
93
+ name: item.f_project,
94
+ data: args[0],
95
+ orignalData: config,
96
+ }
97
+ emit('updateImg', result)
98
+ }
99
+
100
+ function determineCellStyle(labelFunctionReturn: any, color = '#000', borderWidth = '1px') {
101
+ if (labelFunctionReturn.style) {
102
+ // 如果声明了边框颜色
103
+ if (labelFunctionReturn.style.borderColor)
104
+ color = labelFunctionReturn.style.borderColor
105
+
106
+ // 如果声明了边框宽度
107
+ if (labelFunctionReturn.style.borderWidth)
108
+ borderWidth = labelFunctionReturn.style.borderWidth
109
+ }
110
+
111
+ // 正常边框单元格
112
+ const withBorder = {
113
+ border: `${borderWidth} solid ${color}`,
114
+ padding: '8px',
115
+ }
116
+
117
+ // 仅没有上边框单元格
118
+ const NoTopBorder = {
119
+ borderTopStyle: 'none',
120
+ borderLeft: `${borderWidth} solid ${color}`,
121
+ borderRight: `${borderWidth} solid ${color}`,
122
+ borderBottom: `${borderWidth} solid ${color}`,
123
+ padding: '8px',
124
+ }
125
+
126
+ let result: any
127
+ // 判断表头是否有声明的样式
128
+ if (labelFunctionReturn.style !== undefined)
129
+ result = props.noTopBorder ? { ...NoTopBorder, ...labelFunctionReturn.style } : { ...withBorder, ...labelFunctionReturn.style }
130
+ else
131
+ result = props.noTopBorder ? { ...NoTopBorder } : { ...withBorder }
132
+
133
+ return result
134
+ }
135
+
136
+ function handleShowImgOk() {
137
+ showImgModal.value = false
138
+ showImageSrc.value = ''
139
+ }
140
+
141
+ function handleShowImgCancel() {
142
+ showImgModal.value = false
143
+ showImageSrc.value = ''
144
+ }
145
+
146
+ function openImgModal(img: string) {
147
+ showImageSrc.value = img
148
+ showImgModal.value = true
149
+ }
150
+
151
+ function formatImgName(imgSrc: string) {
152
+ return imgSrc.split('/').pop() || ''
153
+ }
154
+
155
+ // 生命周期
156
+ onBeforeMount(() => {
157
+ // 遍历配置,将所有JSON传递的方法保存到一个数组中,并用index来一一对应
158
+ for (let i = 0; i < props.config.content.length; i++) {
159
+ receivedFunction.value.push({
160
+ // eslint-disable-next-line no-new-func
161
+ labelFunction: new Function(`return ${props.config.content[i].customFunctionForLabel}`)(),
162
+ // eslint-disable-next-line no-new-func
163
+ valueFunction: new Function(`return ${props.config.content[i].customFunctionForValue}`)(),
164
+ })
165
+ }
166
+ })
167
+ </script>
168
+
169
+ <template>
170
+ <div id="xreportjsonrender" :class="noPadding ? 'reportMainNoPadding' : 'reportMain'">
171
+ <table class="reportTable" :style="config.style ? config.style : ''">
172
+ <tbody class="'reportTable'">
173
+ <!-- 标题 -->
174
+ <tr v-if="showTitle && config.title.type && config.title.type !== ''">
175
+ <td :class="noTopBorder ? 'tdWithNoTopBorder' : 'tdWithBorder'" colspan="12">
176
+ <template v-if="config.title.type === 'titleKey'">
177
+ {{ config.data[config.title.value] }}
178
+ </template>
179
+ <template v-else-if="config.title.type === 'titleValue'">
180
+ {{ config.title.value }}
181
+ </template>
182
+ </td>
183
+ </tr>
184
+ <template v-for="(row, rowIndex) in config.content">
185
+ <!-- 数据对象是一个Obj -->
186
+ <template v-if="row.type === 'jsonKey'">
187
+ <tr :key="rowIndex">
188
+ <!-- 表头 -->
189
+ <td
190
+ :class="noTopBorder ? 'tdWithNoTopBorder' : 'tdWithBorder'"
191
+ :style="determineCellStyle(receivedFunction[rowIndex].labelFunction(config, row))"
192
+ colspan="6"
193
+ >
194
+ <template v-if="receivedFunction[rowIndex].labelFunction(config).type === 'key'">
195
+ {{ config.data[receivedFunction[rowIndex].labelFunction(config).content] }}
196
+ </template>
197
+ <template v-else-if="receivedFunction[rowIndex].labelFunction(config).type === 'value'">
198
+ {{ receivedFunction[rowIndex].labelFunction(config).content }}
199
+ </template>
200
+ </td>
201
+ <!-- 内容 -->
202
+ <td
203
+ :class="noTopBorder ? 'tdWithNoTopBorder' : 'tdWithBorder'"
204
+ :style="determineCellStyle(receivedFunction[rowIndex].valueFunction(config))"
205
+ colspan="6"
206
+ >
207
+ <template v-if="displayOnly">
208
+ <template v-if="receivedFunction[rowIndex].valueFunction(config).type === 'key'">
209
+ {{ config.data[receivedFunction[rowIndex].valueFunction(config).content] }}
210
+ </template>
211
+ <template v-else-if="receivedFunction[rowIndex].valueFunction(config).type === 'value'">
212
+ {{ receivedFunction[rowIndex].valueFunction(config).content }}
213
+ </template>
214
+ </template>
215
+ <template v-else>
216
+ <template v-if="receivedFunction[rowIndex].valueFunction(config).originalKey">
217
+ <van-field
218
+ :value="config.data[receivedFunction[rowIndex].valueFunction(config).originalKey]"
219
+ @input="(val) => emit('update:config', { ...config, data: { ...config.data, [receivedFunction[rowIndex].valueFunction(config).originalKey]: val } })"
220
+ />
221
+ </template>
222
+ <template v-else>
223
+ <van-field
224
+ :value="config.data[receivedFunction[rowIndex].valueFunction(config).content]"
225
+ @input="(val) => emit('update:config', { ...config, data: { ...config.data, [receivedFunction[rowIndex].valueFunction(config).content]: val } })"
226
+ />
227
+ </template>
228
+ </template>
229
+ <template v-if="receivedFunction[rowIndex].valueFunction(config).type === 'img'">
230
+ <template v-for="(img, imgIndex) in receivedFunction[rowIndex].valueFunction(config).content" :key="imgIndex">
231
+ <span class="imgText">
232
+ <van-icon type="link" />
233
+ <span @click="openImgModal(img)">{{ formatImgName(img) }}</span>
234
+ <br>
235
+ </span>
236
+ </template>
237
+ </template>
238
+ </td>
239
+ </tr>
240
+ </template>
241
+ <!-- 数据对象是一个Array -->
242
+ <template v-else-if="row.type === 'jsonArray'">
243
+ <tr v-for="(item, jsonArrayItemIndex) in config.data[row.jsonArrayDataIndex]" :key="`${rowIndex}${jsonArrayItemIndex}`">
244
+ <!-- 表头 -->
245
+ <td
246
+ :class="noTopBorder ? 'tdWithNoTopBorder' : 'tdWithBorder'"
247
+ :style="determineCellStyle(receivedFunction[rowIndex].labelFunction(config, item))"
248
+ colspan="6"
249
+ >
250
+ <template v-if="receivedFunction[rowIndex].labelFunction(config, item).type === 'key'">
251
+ {{ item[receivedFunction[rowIndex].labelFunction(config, item).content] }}
252
+ </template>
253
+ <template v-if="receivedFunction[rowIndex].labelFunction(config, item).type === 'value'">
254
+ {{ receivedFunction[rowIndex].labelFunction(config, item).content }}
255
+ </template>
256
+ </td>
257
+ <!-- 内容 -->
258
+ <td
259
+ :class="noTopBorder ? 'tdWithNoTopBorder' : 'tdWithBorder'"
260
+ :style="determineCellStyle(receivedFunction[rowIndex].valueFunction(config, item))"
261
+ colspan="6"
262
+ >
263
+ <template v-if="displayOnly">
264
+ <template v-if="receivedFunction[rowIndex].valueFunction(config, item).type === 'key'">
265
+ {{ item[receivedFunction[rowIndex].valueFunction(config, item).content] }}
266
+ </template>
267
+ <template v-if="receivedFunction[rowIndex].valueFunction(config, item).type === 'value'">
268
+ {{ receivedFunction[rowIndex].valueFunction(config, item).content }}
269
+ </template>
270
+ <template v-if="receivedFunction[rowIndex].valueFunction(config, item).type === 'imgs'">
271
+ <template v-if="!item.imgs || item.imgs.length === 0">
272
+ <p style="margin: auto">
273
+
274
+ </p>
275
+ </template>
276
+ <template v-else>
277
+ <template v-for="(img, imgIndex) in item.imgs" :key="imgIndex">
278
+ <div>
279
+ <img :src="img.path" style="max-width: 200px; max-height: 200px">
280
+ <p style="margin: auto">
281
+ {{ img.path.substring(img.path.lastIndexOf('/') + 1, img.path.lastIndexOf('.')) }}
282
+ </p>
283
+ </div>
284
+ </template>
285
+ </template>
286
+ </template>
287
+ </template>
288
+ <template v-else>
289
+ <template v-if="receivedFunction[rowIndex].valueFunction(config, item).originalKey">
290
+ <template v-if="receivedFunction[rowIndex].valueFunction(config, item).type === 'imgs'">
291
+ <Upload
292
+ :model="{
293
+ type: 'image',
294
+ accept: ['*'],
295
+ resUploadStock: 1,
296
+ pathKey: 'cs',
297
+ }"
298
+ :outer-container-index="1"
299
+ :img-prefix="imgPrefix"
300
+ :service-name="serverName"
301
+ :images="checkImg(item.imgs)"
302
+ upload-style="simple"
303
+ @set-files="(...args) => { setImages(args, item, config.data) }"
304
+ />
305
+ </template>
306
+ <template v-else>
307
+ <van-field
308
+ :value="item[receivedFunction[rowIndex].valueFunction(config, item).originalKey]"
309
+ @input="(val) => emit('update:config', { ...config, data: { ...config.data, [receivedFunction[rowIndex].valueFunction(config, item).originalKey]: val } })"
310
+ />
311
+ </template>
312
+ </template>
313
+ <template v-else>
314
+ <van-field
315
+ :value="item[receivedFunction[rowIndex].valueFunction(config, item).content]"
316
+ @input="(val) => emit('update:config', { ...config, data: { ...config.data, [receivedFunction[rowIndex].valueFunction(config, item).content]: val } })"
317
+ />
318
+ </template>
319
+ </template>
320
+ </td>
321
+ </tr>
322
+ </template>
323
+ </template>
324
+ </tbody>
325
+ </table>
326
+ <!-- 图片展示弹框 -->
327
+ <VanDialog
328
+ v-model:show="showImgModal"
329
+ title="图片"
330
+ width="80%"
331
+ :z-index="1001"
332
+ @confirm="handleShowImgOk"
333
+ @cancel="handleShowImgCancel"
334
+ >
335
+ <div style="width: 100%;display: flex;justify-content: center;align-items: center">
336
+ <img :src="showImageSrc" alt="图片">
337
+ </div>
338
+ </VanDialog>
339
+ </div>
340
+ </template>
341
+
342
+ <style scoped lang="less">
343
+ .imgSrc {
344
+ color: rgb(24, 144, 255);
345
+ font-size: 0.9em;
346
+ margin: auto;
347
+ }
348
+ .imgSrc:hover {
349
+ color: rgba(24, 144, 255, 0.8);
350
+ font-size: 0.9em;
351
+ cursor: pointer;
352
+ }
353
+ .reportMain {
354
+ text-align: center;
355
+ margin: 0 auto;
356
+ font-size: 16px;
357
+ color: #000;
358
+ background-color: #fff;
359
+ border-radius: 8px;
360
+ }
361
+
362
+ .reportMainNoPadding {
363
+ text-align: center;
364
+ margin: 0 auto;
365
+ font-size: 16px;
366
+ color: #000;
367
+ background-color: #fff;
368
+ border-radius: 8px;
369
+ }
370
+
371
+ .reportTitle {
372
+ font-weight: bold;
373
+ }
374
+
375
+ .reportTable {
376
+ width: 100%;
377
+ border-collapse: collapse;
378
+ table-layout: fixed;
379
+ word-break: break-all;
380
+ }
381
+
382
+ .tdWithBorder {
383
+ border: 1px solid #000;
384
+ padding: 8px;
385
+ }
386
+
387
+ .imgText:hover {
388
+ color: rgb(24, 144, 255);
389
+ cursor: pointer;
390
+ }
391
+
392
+ .tdWithNoTopBorder {
393
+ border-top-style: none;
394
+ border-left: 1px solid #000;
395
+ border-right: 1px solid #000;
396
+ border-bottom: 1px solid #000;
397
+ padding: 8px;
398
+ }
399
+ </style>