af-mobile-client-vue3 1.2.39 → 1.2.40

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.
@@ -2,18 +2,20 @@
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 { defineEmits, defineProps, onBeforeMount, onMounted, ref, watch } from 'vue'
5
+ import { computed, defineEmits, defineProps, onBeforeMount, onMounted, ref, useSlots, watch } from 'vue'
6
6
 
7
7
  const props = withDefaults(defineProps<{
8
8
  configName?: string
9
9
  serviceName?: string
10
10
  groupFormData?: object
11
11
  mode?: string
12
+ isScrollspy?: boolean
12
13
  }>(), {
13
14
  configName: '',
14
15
  serviceName: undefined,
15
16
  groupFormData: () => ({}),
16
17
  mode: '查询',
18
+ isScrollspy: true,
17
19
  })
18
20
  const emit = defineEmits(['submit'])
19
21
 
@@ -22,6 +24,7 @@ interface Form {
22
24
  serviceName?: string
23
25
  groupFormData?: object
24
26
  mode?: string
27
+ isScrollspy?: boolean
25
28
  }
26
29
 
27
30
  const groupItems = ref([])
@@ -30,7 +33,17 @@ const submitGroup = ref(false)
30
33
  const submitSimple = ref(false)
31
34
  const isInit = ref(false)
32
35
  const initStatus = ref(false)
33
- const propsData = ref<Form>({})
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
+ })
34
47
 
35
48
  // 组件初始化函数
36
49
  function init(params: Form) {
@@ -47,7 +60,7 @@ function init(params: Form) {
47
60
  if (result?.groups) {
48
61
  groupItems.value = result.groups
49
62
  result.groups.forEach((group) => {
50
- if (!formData.value[group.groupName])
63
+ if (!formData.value[group.groupName] && group.formGroupType !== 'slot')
51
64
  formData.value[group.groupName] = {}
52
65
  if (group.showSubmitBtn)
53
66
  submitGroup.value = true
@@ -67,11 +80,39 @@ onBeforeMount(() => {
67
80
  if (!initStatus.value)
68
81
  init(props)
69
82
  })
70
- const xFormListRef = ref([])
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
+
71
104
  async function submit() {
72
105
  for (const res of xFormListRef.value) {
73
- await res.validate()
74
- formData.value[res.formGroupName] = res.form
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
+ }
75
116
  }
76
117
  emit('submit', formData.value)
77
118
  }
@@ -84,14 +125,14 @@ onMounted(() => {
84
125
  offsetTop.value = Number.parseInt(navBarHeight, 10) || 60 + 10
85
126
  })
86
127
 
87
- defineExpose({ init })
128
+ defineExpose({ init, removeRef, xFormListRef })
88
129
  </script>
89
130
 
90
131
  <template>
91
132
  <div v-if="isInit" id="x-form-group">
92
- <VanTabs scrollspy sticky :offset-top="offsetTop">
133
+ <VanTabs :scrollspy="propsData.isScrollspy" sticky :offset-top="offsetTop">
93
134
  <VanTab
94
- v-for="(item, index) in groupItems"
135
+ v-for="(item, index) in renderableGroupItems"
95
136
  :key="item.groupName ? (item.groupName + index) : index"
96
137
  :title="item.describe ? item.describe : item.tableName "
97
138
  >
@@ -99,17 +140,32 @@ defineExpose({ init })
99
140
  class="x-form-group-item"
100
141
  :class="{ 'is-last': index === groupItems.length - 1 }"
101
142
  >
102
- <XForm
103
- ref="xFormListRef"
104
- :is-group-form="true"
105
- :mode="props.mode"
106
- :group-form-items="item"
107
- :form-data="item.groupName ? formData[item.groupName] : formData"
108
- :form-name="item.groupName"
109
- :service-name="props.serviceName"
110
- :submit-button="submitSimple"
111
- @on-submit="submit"
112
- />
143
+ <div v-if="item.describe && propsData.isScrollspy && (item.groupName || item.slotName)" class="form-group-title">
144
+ <span class="form-group-bar" />
145
+ <span class="form-group-text">{{ item.describe }}</span>
146
+ </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>
113
169
  </div>
114
170
  </VanTab>
115
171
  </VanTabs>
@@ -140,4 +196,25 @@ defineExpose({ init })
140
196
  .x-form-group-item.is-last {
141
197
  min-height: calc(100vh - var(--van-nav-bar-height) - 40px);
142
198
  }
199
+ .form-group-title {
200
+ display: flex;
201
+ align-items: center;
202
+ padding-top: 12px;
203
+ background: none;
204
+ margin: 0 0 4px 0;
205
+ }
206
+ .form-group-bar {
207
+ width: 4px;
208
+ height: 20px;
209
+ background: #1989fa;
210
+ border-radius: 4px;
211
+ margin-right: 8px;
212
+ flex-shrink: 0;
213
+ }
214
+ .form-group-text {
215
+ font-weight: 600;
216
+ font-size: 15px;
217
+ color: #222;
218
+ letter-spacing: 0.5px;
219
+ }
143
220
  </style>
@@ -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
+ }