af-mobile-client-vue3 1.6.56 → 1.6.58

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.6.56",
4
+ "version": "1.6.58",
5
5
  "packageManager": "pnpm@10.13.1",
6
6
  "description": "Vue + Vite component lib",
7
7
  "engines": {
@@ -0,0 +1,123 @@
1
+ 三方系统实现:
2
+ 前端框架:vue2.0+ element-ui
3
+ 后端框架:java Spring Boot
4
+ App框架:原生安卓框架+H5
5
+ 关系数据库:PostgreSQL(开源)
6
+ GIS开发组件:SuperMap(超图,国产),中城燃气所属集团提供超图平台服务
7
+ 时序数据库:Elasticsearch(存储坐标数据)
8
+ 消息中间件:rabbitmq
9
+ 文件服务器:minio
10
+ 缓存中间件:redis
11
+
12
+
13
+ # 第三方系统接入技术对接清单
14
+
15
+ ## 一、前端(micro-app子应用接入)
16
+
17
+ ### 1.1 第三方前端改造
18
+ - [ ] 第三方项目 Vue 版本升级(建议 Vue 2.7+)
19
+ - [ ] 第三方项目构建工具迁移至 Vite
20
+ - [ ] 第三方项目路由模式改为 history 模式
21
+ - [ ] 第三方项目添加 basename 配置
22
+ - [ ] 第三方项目实现 micro-app 生命周期钩子(bootstrap/mount/unmount)
23
+ - [ ] 第三方项目移除独立登录页,改为接收主应用传递的登录态
24
+ - [ ] 第三方项目样式隔离(避免与主应用样式冲突)
25
+
26
+ ### 1.2 主应用改造
27
+ - [ ] 主应用注册第三方子应用(microApps.ts 配置)
28
+ - [ ] 主应用创建第三方子应用渲染页面
29
+ - [ ] 主应用封装第三方 API 代理服务
30
+ - [ ] 主应用配置第三方子应用路由
31
+ - [ ] 主应用处理第三方子应用生命周期回调
32
+ - [ ] 主应用实现与第三方子应用的数据通信机制
33
+ - [ ] 主应用配置第三方子应用跨域策略
34
+
35
+ ### 1.3 第三方 API 代理
36
+ - [ ] 主应用封装第三方业务 API 代理方法
37
+ - [ ] 主应用封装第三方文件上传接口
38
+ - [ ] 主应用封装第三方数据查询接口
39
+ - [ ] 代理接口统一添加主系统 Token 认证
40
+ - [ ] 代理接口统一处理登录过期跳转
41
+
42
+ ---
43
+
44
+ ## 二、后端(鉴权相关)
45
+
46
+ ### 2.1 主系统后端改造
47
+ - [ ] 新增第三方系统白名单配置(系统编码、密钥、IP)
48
+ - [ ] 新增第三方用户 Token 绑定接口
49
+ - [ ] 新增第三方用户刷新 Token 接口
50
+ - [ ] 新增第三方用户信息查询接口
51
+ - [ ] 新增网关信任来源过滤器
52
+ - [ ] 网关层支持 X-Third-Party-User-Id 请求头识别
53
+
54
+ ### 2.2 API 网关/路由配置
55
+ - [ ] 配置第三方系统 API 路由转发规则
56
+ - [ ] 配置第三方静态资源路径映射
57
+ - [ ] 配置跨域访问策略
58
+
59
+ ---
60
+
61
+ ## 三、认证方案选择
62
+
63
+ ### 推荐方案:代理模式(第三方不改登录)
64
+ - [ ] 主应用前端统一管理 Token
65
+ - [ ] 第三方子应用通过主应用代理调用主系统 API
66
+ - [ ] 第三方登录完成后跳转主应用页面,由主应用注入登录态
67
+
68
+ ### 备选方案:Token 映射模式
69
+ - [ ] 主系统提供第三方 Token 换取接口
70
+ - [ ] 主系统维护第三方用户与本系统用户映射关系
71
+ - [ ] 第三方登录后自动调接口换取主系统 Token
72
+
73
+ ---
74
+
75
+ ## 四、数据对接
76
+
77
+ ### 4.1 用户数据
78
+ - [ ] 确定用户数据同步策略(共享表 / API 调用 / DB Link)
79
+ - [ ] 第三方用户与主系统用户绑定关系设计
80
+
81
+ ### 4.2 业务数据
82
+ - [ ] 梳理需要主系统提供的业务数据接口
83
+ - [ ] 梳理需要提供给第三方的业务数据接口
84
+
85
+ ### 4.3 文件服务
86
+ - [ ] 确认是否复用主系统 MinIO 文件服务
87
+ - [ ] 配置第三方文件上传白名单
88
+
89
+ ---
90
+
91
+ ## 五、GIS 地图对接(如需要)
92
+ - [ ] 确认 SuperMap 版本和接口规范
93
+ - [ ] 主应用封装地图加载组件
94
+ - [ ] 主应用与第三方子应用地图实例共享方案
95
+
96
+ ---
97
+
98
+ ## 六、联调测试
99
+ - [ ] 第三方子应用独立运行测试
100
+ - [ ] 第三方子应用嵌入主应用测试
101
+ - [ ] 第三方调用主系统 API 联调
102
+ - [ ] 主系统 Token 有效性验证
103
+ - [ ] 子应用间跳转和返回测试
104
+ - [ ] 登录态同步测试
105
+ - [ ] 性能测试(加载时间、内存占用)
106
+
107
+ ---
108
+
109
+ ## 七、部署上线
110
+ - [ ] 第三方子应用构建配置调整
111
+ - [ ] 生产环境域名解析配置
112
+ - [ ] Nginx / API 网关路由配置
113
+ - [ ] 主系统 API 跨域配置
114
+ - [ ] 第三方系统白名单生产配置
115
+
116
+ ---
117
+
118
+ ## 八、注意事项
119
+ - 第三方前端不能有独立的登录页面
120
+ - 第三方前端不能直接存储 Token
121
+ - 第三方前端所有 API 请求需通过主应用代理
122
+ - 需要确认第三方项目的具体版本和配置
123
+ - 需要确认双方 API 接口文档和数据字典
@@ -24,17 +24,36 @@ interface WatermarkConfig {
24
24
  blurThreshold?: string | number
25
25
  }
26
26
 
27
- const props = defineProps({
28
- imageList: Array<any>,
29
- outerIndex: { default: undefined },
30
- authority: { default: 'user' },
31
- uploadMode: { default: 'server' },
32
- attr: { type: Object as () => { addOrEdit?: string, acceptCount?: number, minAcceptCount?: number, uploadImage?: boolean, watermark?: WatermarkConfig, useType?: string }, default: () => ({}) },
33
- mode: { default: '新增' }, // 预览
34
- serviceName: { type: String, default: '' },
27
+ interface ImageUploaderProps {
28
+ imageList?: any[]
29
+ outerIndex?: number | undefined
30
+ authority?: string
31
+ uploadMode?: string
32
+ attr?: {
33
+ addOrEdit?: string
34
+ acceptCount?: number
35
+ minAcceptCount?: number
36
+ uploadImage?: boolean
37
+ watermark?: WatermarkConfig
38
+ useType?: string
39
+ }
40
+ mode?: string
41
+ serviceName?: string
42
+ readonly?: boolean
43
+ isAsyncUpload?: boolean
44
+ }
45
+
46
+ const props = withDefaults(defineProps<ImageUploaderProps>(), {
47
+ imageList: () => [],
48
+ outerIndex: undefined,
49
+ authority: 'user',
50
+ uploadMode: 'server',
51
+ attr: () => ({}),
52
+ mode: '新增',
53
+ serviceName: '',
35
54
  // 整体只读:只允许预览,禁止拍照/上传/删除
36
- readonly: { type: Boolean, default: false },
37
- isAsyncUpload: { type: Boolean, default: false },
55
+ readonly: false,
56
+ isAsyncUpload: false,
38
57
  })
39
58
  const emit = defineEmits(['updateFileList', 'updateAllFileList', 'photoQualityChange'])
40
59
 
@@ -51,9 +70,6 @@ const parentCommonId = (() => {
51
70
  }
52
71
  })()
53
72
 
54
- // 浏览器 / 微信内 H5:统一用隐藏 file input(与单独 camera input 行为等价,均为系统选图)
55
- // const fileInputRef = ref<HTMLInputElement | undefined>()
56
- const parentData: any = inject('provideParent')
57
73
  // 浏览器 / 微信内 H5:统一用隐藏 file input(与单独 camera input 行为等价,均为系统选图)
58
74
  const fileInputRef = ref<HTMLInputElement | undefined>()
59
75
 
@@ -19,10 +19,26 @@ const emit = defineEmits<{
19
19
  signatureComplete: [data: any]
20
20
  }>()
21
21
 
22
+ // 从父组件获取 commonId,仅读取字符串值,不持有父级 provideParent 对象
23
+ const parentCommonId = (() => {
24
+ try {
25
+ const parent = inject<any>('provideParent', undefined)
26
+ console.log('parent==', parent)
27
+ if (!parent) {
28
+ return ''
29
+ }
30
+ if (typeof parent.commonId === 'object' && parent.commonId && 'value' in parent.commonId) {
31
+ return String(parent.commonId.value ?? '')
32
+ }
33
+ return String(parent.commonId ?? '')
34
+ }
35
+ catch {
36
+ return ''
37
+ }
38
+ })()
22
39
  const signatureImage = ref<string>('')
23
40
  const rawBase64Data = ref<string>('') // 保存原始base64数据
24
41
  const hasSignature = ref(false)
25
- const parentData: any = inject('provideParent')
26
42
  const imageList = ref<Array<any>>(props.imageList ?? [])
27
43
  console.log('imageList', imageList.value)
28
44
  console.log('props.imageList', props.imageList)
@@ -79,7 +95,7 @@ function handleSignature() {
79
95
  f_operator: 'server',
80
96
  imgPath: result.data.filePath,
81
97
  urlPath: `/api/${import.meta.env.VITE_APP_SYSTEM_NAME}/resource/upload`,
82
- commonId: parentData?.commonId.value ?? '',
98
+ commonId: parentCommonId,
83
99
  }
84
100
  if (props.isAsyncUpload) {
85
101
  // 添加上传队列
@@ -10,38 +10,20 @@ import {
10
10
  } from 'vant'
11
11
  import { computed, onBeforeUnmount, ref, watch } from 'vue'
12
12
 
13
- const props = defineProps({
14
- columns: {
15
- type: Array,
16
- default() {
17
- return []
18
- },
19
- },
20
- selectValue: {
21
- type: Array,
22
- default() {
23
- return []
24
- },
25
- },
26
- option: {
27
- type: Object,
28
- default() {
29
- return { text: 'label', value: 'value' }
30
- },
31
- },
32
- // 是否支持搜索
33
- isSearch: {
34
- type: Boolean,
35
- default: true,
36
- },
37
- lazyLoad: { // 是否启用懒加载
38
- type: String,
39
- default: 'false',
40
- },
41
- onSearch: { // 懒加载时的搜索函数
42
- type: Function,
43
- default: null,
44
- },
13
+ const props = withDefaults(defineProps<{
14
+ columns?: any[]
15
+ selectValue?: any[]
16
+ option?: Record<string, string>
17
+ isSearch?: boolean // 是否支持搜索
18
+ lazyLoad?: string // 是否启用懒加载
19
+ onSearch?: ((searchValue: string) => Promise<any[]>) | null // 懒加载时的搜索函数
20
+ }>(), {
21
+ columns: () => [],
22
+ selectValue: () => [],
23
+ option: () => ({ text: 'label', value: 'value' }),
24
+ isSearch: true,
25
+ lazyLoad: 'false',
26
+ onSearch: null,
45
27
  })
46
28
  const emits = defineEmits(['input', 'confirm', 'change', 'cancel'])
47
29
  const show = ref(false)
@@ -130,6 +112,7 @@ const stopWatchCheckboxValue = watch(() => checkboxValue.value.length, (newVal,
130
112
 
131
113
  onBeforeUnmount(() => {
132
114
  stopWatchCheckboxValue()
115
+ show.value = false
133
116
  })
134
117
  const resultLabel = computed(() => {
135
118
  const res = props.columns.filter((item) => {
@@ -7,35 +7,20 @@ import {
7
7
  } from 'vant'
8
8
  import { computed, onBeforeMount, onBeforeUnmount, ref, watch } from 'vue'
9
9
 
10
- const props = defineProps({
11
- columns: {
12
- type: Array,
13
- default() {
14
- return []
15
- },
16
- },
17
- option: {
18
- type: Object,
19
- default() {
20
- return { text: 'label', value: 'value', children: 'children' }
21
- },
22
- },
23
- offOption: { // 关闭option配置key-value;当数据是非集合的数组的时候,开启
24
- type: Boolean,
25
- default: false,
26
- },
27
- border: { // 是否展示边框
28
- type: Boolean,
29
- default: false,
30
- },
31
- lazyLoad: { // 是否启用懒加载
32
- type: String,
33
- default: 'false',
34
- },
35
- onSearch: { // 懒加载时的搜索函数
36
- type: Function,
37
- default: null,
38
- },
10
+ const props = withDefaults(defineProps<{
11
+ columns?: any[]
12
+ option?: Record<string, string>
13
+ offOption?: boolean
14
+ border?: boolean
15
+ lazyLoad?: string
16
+ onSearch?: ((searchValue: string) => Promise<any[]>) | null
17
+ }>(), {
18
+ columns: () => [],
19
+ option: () => ({ text: 'label', value: 'value', children: 'children' }),
20
+ offOption: false,
21
+ border: false,
22
+ lazyLoad: 'false',
23
+ onSearch: null,
39
24
  })
40
25
  const emits = defineEmits(['confirm', 'change', 'cancel', 'input'])
41
26
  const show = ref(false)
@@ -107,6 +107,7 @@ const rules = reactive({})
107
107
  const myGetDataParams = ref({})
108
108
  const isKeyHandle = ref(false)
109
109
  const submitLoading = ref(false)
110
+ let navigateTimer: number | null = null
110
111
 
111
112
  // 配置相关状态
112
113
  const formConfig = ref<GroupFormItems | null>(null)
@@ -392,6 +393,10 @@ onBeforeUnmount(() => {
392
393
  stopWatchPreviewMapPoint?.()
393
394
  stopWatchFormData?.()
394
395
  stopWatchForm?.()
396
+ if (navigateTimer) {
397
+ window.clearTimeout(navigateTimer)
398
+ navigateTimer = null
399
+ }
395
400
  })
396
401
 
397
402
  // 支持函数调用方式初始化
@@ -696,7 +701,7 @@ async function onSubmit() {
696
701
  showFailToast('提交失败!!')
697
702
  }
698
703
  finally {
699
- setTimeout(() => {
704
+ navigateTimer = window.setTimeout(() => {
700
705
  history.back()
701
706
  }, 1000)
702
707
  }
@@ -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>