af-mobile-client-vue3 1.3.72 → 1.3.73

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.3.72",
4
+ "version": "1.3.73",
5
5
  "packageManager": "pnpm@10.13.1",
6
6
  "description": "Vue + Vite component lib",
7
7
  "engines": {
@@ -2,6 +2,7 @@
2
2
  // import cameraIcon from '@af-mobile-client-vue3/assets/img/component/camera.png'
3
3
  import { deleteFile, upload } from '@af-mobile-client-vue3/services/api/common'
4
4
  import { mobileUtil } from '@af-mobile-client-vue3/utils/mobileUtil'
5
+ import { formatNow } from '@af-mobile-client-vue3/utils/timeUtil'
5
6
  import {
6
7
  ActionSheet,
7
8
  Icon as VanIcon,
@@ -9,12 +10,21 @@ import {
9
10
  } from 'vant'
10
11
  import { ref } from 'vue'
11
12
 
13
+ interface WatermarkConfig {
14
+ fontSize?: number | string
15
+ color?: string
16
+ alpha?: number
17
+ userName?: string
18
+ format?: string
19
+ customLines?: string[]
20
+ }
21
+
12
22
  const props = defineProps({
13
23
  imageList: Array<any>,
14
24
  outerIndex: { default: undefined },
15
25
  authority: { default: 'user' },
16
26
  uploadMode: { default: 'server' },
17
- attr: { type: Object as () => { addOrEdit?: string, acceptCount?: number, uploadImage?: boolean }, default: () => ({}) },
27
+ attr: { type: Object as () => { addOrEdit?: string, acceptCount?: number, uploadImage?: boolean, watermark?: WatermarkConfig }, default: () => ({}) },
18
28
  mode: { default: '新增' }, // 预览
19
29
  // 整体只读:只允许预览,禁止拍照/上传/删除
20
30
  readonly: { type: Boolean, default: false },
@@ -103,6 +113,20 @@ function uploadFileViaHttp(file: File, previewUrl: string, temp: any) {
103
113
  })
104
114
  }
105
115
 
116
+ function buildWatermarkText() {
117
+ const wm = (props.attr as any)?.watermark ?? {}
118
+ const user = wm.userName ?? ''
119
+ const time = formatNow(wm.format || 'YYYY-MM-DD HH:mm:ss')
120
+ const lines: string[] = []
121
+ if (user)
122
+ lines.push(`拍摄人:${user}`)
123
+ if (time)
124
+ lines.push(`拍摄时间:${time}`)
125
+ if (Array.isArray(wm.customLines) && wm.customLines.length > 0)
126
+ lines.push(...wm.customLines.filter((v: any) => typeof v === 'string' && v !== ''))
127
+ return lines.join('\n')
128
+ }
129
+
106
130
  function handleBrowserFiles(files: FileList | null) {
107
131
  if (!files || files.length === 0)
108
132
  return
@@ -125,7 +149,22 @@ function handleBrowserFiles(files: FileList | null) {
125
149
  function triggerCamera() {
126
150
  mobileUtil.execute({
127
151
  funcName: 'takePicture',
128
- param: {},
152
+ param: (() => {
153
+ const param: any = {}
154
+ const watermark = (props.attr as any)?.watermark
155
+ if (watermark) {
156
+ const txt = buildWatermarkText()
157
+ if (txt)
158
+ param.watermark = txt
159
+ if (watermark.fontSize !== undefined && String(watermark.fontSize) !== '')
160
+ param.watermarkFontSize = watermark.fontSize
161
+ if (watermark.color)
162
+ param.watermarkColor = watermark.color
163
+ if (watermark.alpha !== undefined && String(watermark.alpha) !== '')
164
+ param.watermarkAlpha = watermark.alpha
165
+ }
166
+ return param
167
+ })(),
129
168
  callbackFunc: (result: any) => {
130
169
  if (result.status === 'success') {
131
170
  handlePhotoUpload(result.data)
@@ -64,6 +64,8 @@ const props = withDefaults(defineProps<{
64
64
  formReadonly?: boolean
65
65
  // 控制上传——异步/同步
66
66
  isAsyncUpload?: boolean
67
+ // 可选:自定义水印内容数组(将拼接在组件默认行之后)
68
+ watermarkCustomLines?: string[]
67
69
  }>(), {
68
70
  configName: undefined,
69
71
  groupTitle: undefined,
@@ -78,6 +80,7 @@ const props = withDefaults(defineProps<{
78
80
  isGroupForm: false,
79
81
  formReadonly: false,
80
82
  isAsyncUpload: false,
83
+ watermarkCustomLines: () => [],
81
84
  })
82
85
 
83
86
  const emits = defineEmits(['onSubmit', 'xFormItemEmitFunc'])
@@ -99,6 +102,8 @@ const formConfig = ref<GroupFormItems | null>(null)
99
102
  const formGroupName = ref<string>('default')
100
103
  const myServiceName = ref('')
101
104
  const tableName = ref('')
105
+ // 水印基础配置(从配置中心加载)
106
+ const watermarkBaseConfig = ref<any | null>(null)
102
107
 
103
108
  // 计算属性(获取全部表单项信息)
104
109
  const realJsonData = computed(() => {
@@ -179,6 +184,11 @@ async function initializeForm() {
179
184
  console.warn('未提供配置名称或表单配置,等待 init 函数调用')
180
185
  resetForm()
181
186
  }
187
+
188
+ // 按需加载水印配置
189
+ await loadWatermarkConfig()
190
+ // 应用水印到图片类表单项
191
+ applyWatermarkToItems()
182
192
  }
183
193
  catch (error) {
184
194
  console.error('表单初始化失败:', error)
@@ -319,7 +329,7 @@ onBeforeMount(() => {
319
329
  })
320
330
 
321
331
  // 支持函数调用方式初始化
322
- function init(params: InitParams) {
332
+ async function init(params: InitParams) {
323
333
  const {
324
334
  formItems,
325
335
  formData = {},
@@ -332,7 +342,7 @@ function init(params: InitParams) {
332
342
  try {
333
343
  if (props.configName) {
334
344
  // 通过 props 中的配置名称初始化
335
- loadFormConfig()
345
+ await loadFormConfig()
336
346
  }
337
347
  else if (formItems) {
338
348
  // 直接使用传入的配置初始化
@@ -344,6 +354,7 @@ function init(params: InitParams) {
344
354
  if (formItems.tableName) {
345
355
  tableName.value = formItems.tableName.split(' ')[0] || ''
346
356
  }
357
+ applyWatermarkToItems()
347
358
  }
348
359
  else {
349
360
  console.warn('init 函数调用时既没有 props.configName 也没有 formItems')
@@ -359,6 +370,36 @@ function init(params: InitParams) {
359
370
  }
360
371
  }
361
372
 
373
+ // 加载水印基础配置
374
+ async function loadWatermarkConfig(configName?: string): Promise<void> {
375
+ return new Promise((resolve) => {
376
+ getConfigByName('PhotoWatermarkConfig', (result) => {
377
+ watermarkBaseConfig.value = result || null
378
+ resolve()
379
+ }, props.serviceName)
380
+ })
381
+ }
382
+
383
+ // 将水印配置应用到图片/文件类表单项(attr.type === 'image' | 'file')
384
+ function applyWatermarkToItems() {
385
+ if (!formConfig.value || !Array.isArray(formConfig.value.formJson))
386
+ return
387
+ const userName = userStore.getUserInfo()?.name
388
+ const base = watermarkBaseConfig.value
389
+ const baseWatermark = base?.watermark ?? base ?? {}
390
+
391
+ formConfig.value.formJson = formConfig.value.formJson.map((item: any) => {
392
+ if (item && (item.type === 'image' || item.type === 'file')) {
393
+ item.watermark = {
394
+ ...baseWatermark,
395
+ userName,
396
+ customLines: props.watermarkCustomLines,
397
+ }
398
+ }
399
+ return item
400
+ })
401
+ }
402
+
362
403
  function loadParamLogicNameData(paramLogicName) {
363
404
  // 如果有 paramLogicName,自动请求并赋值
364
405
  if (paramLogicName && (!props.formData || (props.formData && Object.keys(props.formData).length === 0))) {
@@ -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>
@@ -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
+ }