af-mobile-client-vue3 1.2.40 → 1.2.41

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.2.40",
4
+ "version": "1.2.41",
5
5
  "packageManager": "pnpm@10.12.3",
6
6
  "description": "Vue + Vite component lib",
7
7
  "engines": {
@@ -2,7 +2,7 @@
2
2
  import XForm from '@af-mobile-client-vue3/components/data/XForm/index.vue'
3
3
  import { getConfigByName } from '@af-mobile-client-vue3/services/api/common'
4
4
  import { Button as VanButton, Tab as VanTab, Tabs as VanTabs } from 'vant'
5
- import { computed, defineEmits, defineProps, onBeforeMount, onMounted, ref, useSlots, watch } from 'vue'
5
+ import { defineEmits, defineProps, onBeforeMount, onMounted, ref, watch } from 'vue'
6
6
 
7
7
  const props = withDefaults(defineProps<{
8
8
  configName?: string
@@ -33,17 +33,7 @@ const submitGroup = ref(false)
33
33
  const submitSimple = ref(false)
34
34
  const isInit = ref(false)
35
35
  const initStatus = ref(false)
36
- const propsData = ref<Partial<Form>>({})
37
-
38
- const slots = useSlots()
39
- const renderableGroupItems = computed(() => {
40
- return groupItems.value.filter((item) => {
41
- if (item.formGroupType === 'slot') {
42
- return !!(item.slotName && slots[item.slotName])
43
- }
44
- return true
45
- })
46
- })
36
+ const propsData = ref<Form>({})
47
37
 
48
38
  // 组件初始化函数
49
39
  function init(params: Form) {
@@ -60,7 +50,7 @@ function init(params: Form) {
60
50
  if (result?.groups) {
61
51
  groupItems.value = result.groups
62
52
  result.groups.forEach((group) => {
63
- if (!formData.value[group.groupName] && group.formGroupType !== 'slot')
53
+ if (!formData.value[group.groupName])
64
54
  formData.value[group.groupName] = {}
65
55
  if (group.showSubmitBtn)
66
56
  submitGroup.value = true
@@ -80,39 +70,11 @@ onBeforeMount(() => {
80
70
  if (!initStatus.value)
81
71
  init(props)
82
72
  })
83
- interface XFormLike {
84
- validate: () => Promise<void>
85
- formGroupName?: string
86
- form?: any
87
- getFormData?: () => object
88
- }
89
- const xFormListRef = ref<XFormLike[]>([])
90
-
91
- // 注册表单实例,避免重复
92
- function setRef(refValue: XFormLike) {
93
- if (refValue && !xFormListRef.value.includes(refValue)) {
94
- xFormListRef.value.push(refValue)
95
- }
96
- }
97
- // 注销表单实例
98
- function removeRef(refValue: XFormLike) {
99
- const idx = xFormListRef.value.indexOf(refValue)
100
- if (idx !== -1)
101
- xFormListRef.value.splice(idx, 1)
102
- }
103
-
73
+ const xFormListRef = ref([])
104
74
  async function submit() {
105
75
  for (const res of xFormListRef.value) {
106
- try {
107
- await res.validate()
108
- if (res.formGroupName && typeof res.getFormData === 'function') {
109
- formData.value[res.formGroupName] = res.getFormData()
110
- }
111
- }
112
- catch (msg) {
113
- console.log('error:', msg)
114
- return
115
- }
76
+ await res.validate()
77
+ formData.value[res.formGroupName] = res.form
116
78
  }
117
79
  emit('submit', formData.value)
118
80
  }
@@ -125,14 +87,14 @@ onMounted(() => {
125
87
  offsetTop.value = Number.parseInt(navBarHeight, 10) || 60 + 10
126
88
  })
127
89
 
128
- defineExpose({ init, removeRef, xFormListRef })
90
+ defineExpose({ init })
129
91
  </script>
130
92
 
131
93
  <template>
132
94
  <div v-if="isInit" id="x-form-group">
133
95
  <VanTabs :scrollspy="propsData.isScrollspy" sticky :offset-top="offsetTop">
134
96
  <VanTab
135
- v-for="(item, index) in renderableGroupItems"
97
+ v-for="(item, index) in groupItems"
136
98
  :key="item.groupName ? (item.groupName + index) : index"
137
99
  :title="item.describe ? item.describe : item.tableName "
138
100
  >
@@ -144,28 +106,17 @@ defineExpose({ init, removeRef, xFormListRef })
144
106
  <span class="form-group-bar" />
145
107
  <span class="form-group-text">{{ item.describe }}</span>
146
108
  </div>
147
- <template v-if="item.formGroupType === 'slot'">
148
- <slot
149
- :name="item.slotName"
150
- :item="item"
151
- :form-data="item.groupName ? formData[item.groupName] : formData"
152
- :set-ref="setRef"
153
- :remove-ref="removeRef"
154
- />
155
- </template>
156
- <template v-else>
157
- <XForm
158
- ref="xFormListRef"
159
- :mode="props.mode"
160
- :is-group-form="true"
161
- :group-form-items="item"
162
- :form-data="item.groupName ? formData[item.groupName] : formData"
163
- :form-name="item.groupName"
164
- :service-name="props.serviceName"
165
- :submit-button="submitSimple"
166
- @on-submit="submit"
167
- />
168
- </template>
109
+ <XForm
110
+ ref="xFormListRef"
111
+ :is-group-form="true"
112
+ :mode="props.mode"
113
+ :group-form-items="item"
114
+ :form-data="item.groupName ? formData[item.groupName] : formData"
115
+ :form-name="item.groupName"
116
+ :service-name="props.serviceName"
117
+ :submit-button="submitSimple"
118
+ @on-submit="submit"
119
+ />
169
120
  </div>
170
121
  </VanTab>
171
122
  </VanTabs>
@@ -187,6 +187,27 @@ function getDefaultValue() {
187
187
  const getDefaultByType = () => {
188
188
  const def = mode !== '查询' ? attr.formDefault : attr.queryFormDefault
189
189
 
190
+ if (['treeSelect', 'select', 'checkbox'].includes(attr.type) && ['curOrgId', 'curDepId', 'curUserId'].includes(def)) {
191
+ if (def === 'curOrgId') {
192
+ if (attr.type === 'treeSelect') {
193
+ treeValue.value = userState.f.resources.orgs
194
+ }
195
+ return attr.type === 'select' ? userState.f.resources.orgid : [userState.f.resources.orgid]
196
+ }
197
+ if (def === 'curDepId') {
198
+ if (attr.type === 'treeSelect') {
199
+ treeValue.value = userState.f.resources.deps
200
+ }
201
+ return attr.type === 'select' ? userState.f.resources.depids : [userState.f.resources.depids]
202
+ }
203
+ if (def === 'curUserId') {
204
+ if (attr.type === 'treeSelect') {
205
+ treeValue.value = userState.f.resources.name
206
+ }
207
+ return attr.type === 'select' ? userState.f.resources.id : [userState.f.resources.id]
208
+ }
209
+ }
210
+
190
211
  // 数组类型默认值
191
212
  const arrayTypes = ['uploader', 'checkbox', 'file', 'area', 'image', 'treeSelect']
192
213
  if (arrayTypes.includes(attr.type)) {
@@ -716,10 +737,34 @@ defineExpose({
716
737
  reset,
717
738
  })
718
739
 
740
+ // 数据处理
741
+ function cleanEmptyChildren(options, fieldNames = { text: 'label', value: 'value', children: 'children' }) {
742
+ if (!Array.isArray(options))
743
+ return options
744
+
745
+ const childrenKey = fieldNames.children || 'children'
746
+
747
+ return options.map((option) => {
748
+ // 深拷贝选项,避免修改原始数据
749
+ const newOption = { ...option }
750
+
751
+ // 如果存在children属性且是空数组
752
+ if (newOption[childrenKey] && Array.isArray(newOption[childrenKey]) && newOption[childrenKey].length === 0) {
753
+ delete newOption[childrenKey]
754
+ }
755
+ // 如果存在children属性且非空,则递归处理
756
+ else if (newOption[childrenKey] && Array.isArray(newOption[childrenKey])) {
757
+ newOption[childrenKey] = cleanEmptyChildren(newOption[childrenKey], fieldNames)
758
+ }
759
+ return newOption
760
+ })
761
+ }
762
+
719
763
  // 级联选择完成事件
720
- function onTreeSelectFinish(value) {
721
- treeValue.value = value.value
722
- modelData.value = [value.value]
764
+ function onTreeSelectFinish({ selectedOptions }) {
765
+ const index = selectedOptions.length - 1
766
+ treeValue.value = selectedOptions[index].label
767
+ modelData.value = [selectedOptions[index].value]
723
768
  showTreeSelect.value = false
724
769
  }
725
770
 
@@ -1217,7 +1262,7 @@ function emitFunc(func, data) {
1217
1262
  overlay-class="date-picker-overlay"
1218
1263
  >
1219
1264
  <VanCascader
1220
- :options="option"
1265
+ :options="cleanEmptyChildren(option, attr.customFieldName ? attr.customFieldName : { text: 'label', value: 'value', children: 'children' })"
1221
1266
  :field-names="attr.customFieldName ? attr.customFieldName : { text: 'label', value: 'value', children: 'children' }"
1222
1267
  :title="attr.name"
1223
1268
  :closeable="true"
@@ -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
+ }