曾佳炜一次提交所有前端代码
This commit is contained in:
parent
3b0e3393d9
commit
3a0c40c068
2
.env
2
.env
@ -2,7 +2,7 @@
|
|||||||
VITE_APP_TITLE=区域云心电系统
|
VITE_APP_TITLE=区域云心电系统
|
||||||
|
|
||||||
# 项目本地运行端口号
|
# 项目本地运行端口号
|
||||||
VITE_PORT=8080
|
VITE_PORT=80
|
||||||
|
|
||||||
# open 运行 npm run dev 时自动打开浏览器
|
# open 运行 npm run dev 时自动打开浏览器
|
||||||
VITE_OPEN=true
|
VITE_OPEN=true
|
||||||
|
|||||||
6
.env.dev
6
.env.dev
@ -4,8 +4,8 @@ NODE_ENV=production
|
|||||||
VITE_DEV=false
|
VITE_DEV=false
|
||||||
|
|
||||||
# 请求路径 http://10.55.253.199:8073
|
# 请求路径 http://10.55.253.199:8073
|
||||||
VITE_BASE_URL='http://111.57.76.10:8072' #111服务器
|
#VITE_BASE_URL='http://111.57.76.10:8072' #111服务器
|
||||||
#VITE_BASE_URL='/adminecg' #222服务器
|
VITE_BASE_URL='/adminecg' #222服务器
|
||||||
# VITE_BASE_URL='/admin-api'
|
# VITE_BASE_URL='/admin-api'
|
||||||
|
|
||||||
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务
|
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务
|
||||||
@ -26,7 +26,7 @@ VITE_DROP_CONSOLE=false
|
|||||||
VITE_SOURCEMAP=true
|
VITE_SOURCEMAP=true
|
||||||
|
|
||||||
# 打包路径
|
# 打包路径
|
||||||
VITE_BASE_PATH=/ecg
|
VITE_BASE_PATH=/ecg #222服务器
|
||||||
|
|
||||||
# 输出路径
|
# 输出路径
|
||||||
VITE_OUT_DIR=dist
|
VITE_OUT_DIR=dist
|
||||||
|
|||||||
@ -4,7 +4,8 @@ NODE_ENV=production
|
|||||||
VITE_DEV=false
|
VITE_DEV=false
|
||||||
|
|
||||||
# 请求路径
|
# 请求路径
|
||||||
VITE_BASE_URL='http://114.55.171.231:48080'
|
#VITE_BASE_URL='http://114.55.171.231:48080'
|
||||||
|
VITE_BASE_URL='http://192.168.1.12:8072'
|
||||||
|
|
||||||
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务
|
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务
|
||||||
VITE_UPLOAD_TYPE=server
|
VITE_UPLOAD_TYPE=server
|
||||||
@ -12,7 +13,7 @@ VITE_UPLOAD_TYPE=server
|
|||||||
VITE_UPLOAD_URL='http://114.55.171.231:48080/admin-api/infra/file/upload'
|
VITE_UPLOAD_URL='http://114.55.171.231:48080/admin-api/infra/file/upload'
|
||||||
|
|
||||||
# 接口地址
|
# 接口地址
|
||||||
VITE_API_URL=/admin-api
|
VITE_API_URL=/adminecg/admin-api
|
||||||
|
|
||||||
# 是否删除debugger
|
# 是否删除debugger
|
||||||
VITE_DROP_DEBUGGER=false
|
VITE_DROP_DEBUGGER=false
|
||||||
|
|||||||
299
docs/examCache-usage.md
Normal file
299
docs/examCache-usage.md
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
# examCache 缓存系统使用指南
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
`examCache` 是一个基于 Pinia 的缓存系统,用于在页面间存储和获取 `examId`、`orgId` 等检查相关信息。该系统支持自动持久化到 localStorage,并具有缓存有效期管理功能。
|
||||||
|
|
||||||
|
## 特性
|
||||||
|
|
||||||
|
- ✅ 基于 Pinia 状态管理
|
||||||
|
- ✅ 自动持久化到 localStorage
|
||||||
|
- ✅ 缓存有效期管理(24小时)
|
||||||
|
- ✅ 支持从 URL 参数自动更新缓存
|
||||||
|
- ✅ TypeScript 类型支持
|
||||||
|
- ✅ 优雅的降级处理
|
||||||
|
|
||||||
|
## 安装和配置
|
||||||
|
|
||||||
|
### 1. 确保已安装依赖
|
||||||
|
|
||||||
|
项目已经安装了必要的依赖:
|
||||||
|
- `pinia`
|
||||||
|
- `pinia-plugin-persistedstate`
|
||||||
|
|
||||||
|
### 2. 缓存 Store 已配置
|
||||||
|
|
||||||
|
缓存 Store 位于 `src/store/modules/examCache.ts`,已在主 Store 中注册。
|
||||||
|
|
||||||
|
## 基本使用
|
||||||
|
|
||||||
|
### 1. 设置缓存
|
||||||
|
|
||||||
|
在页面跳转前设置缓存:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { useExamCacheStore } from '@/store/modules/examCache'
|
||||||
|
|
||||||
|
const examCacheStore = useExamCacheStore()
|
||||||
|
|
||||||
|
// 设置缓存
|
||||||
|
examCacheStore.setCache('EXAM001', 'ORG001', 'http://example.com/image.jpg')
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 获取缓存
|
||||||
|
|
||||||
|
在目标页面获取缓存:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { useExamCacheStore } from '@/store/modules/examCache'
|
||||||
|
|
||||||
|
const examCacheStore = useExamCacheStore()
|
||||||
|
|
||||||
|
// 获取有效的 examId 和 orgId
|
||||||
|
const examId = examCacheStore.getValidExamId
|
||||||
|
const orgId = examCacheStore.getValidOrgId
|
||||||
|
const imgUrl = examCacheStore.imgUrl
|
||||||
|
|
||||||
|
// 检查缓存是否有效
|
||||||
|
if (examCacheStore.isCacheValid) {
|
||||||
|
console.log('缓存有效,可以使用')
|
||||||
|
} else {
|
||||||
|
console.log('缓存已过期或不存在')
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 从 URL 参数更新缓存
|
||||||
|
|
||||||
|
当页面通过 URL 参数传递数据时,可以自动更新缓存:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { useExamCacheStore } from '@/store/modules/examCache'
|
||||||
|
import { useRoute } from 'vue-router'
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const examCacheStore = useExamCacheStore()
|
||||||
|
|
||||||
|
// 从路由参数更新缓存
|
||||||
|
examCacheStore.updateFromRoute(route.query)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 清除缓存
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { useExamCacheStore } from '@/store/modules/examCache'
|
||||||
|
|
||||||
|
const examCacheStore = useExamCacheStore()
|
||||||
|
|
||||||
|
// 清除缓存
|
||||||
|
examCacheStore.clearCache()
|
||||||
|
```
|
||||||
|
|
||||||
|
## 实际应用场景
|
||||||
|
|
||||||
|
### 场景1: ECGForm 页面跳转到 translate 页面
|
||||||
|
|
||||||
|
**在 ECGForm.vue 中:**
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 在跳转前设置缓存
|
||||||
|
const examCacheStore = useExamCacheStore()
|
||||||
|
examCacheStore.setCache(rowinfo.value.examId, rowinfo.value.orgId, imageUrl)
|
||||||
|
|
||||||
|
// 跳转到 translate 页面
|
||||||
|
router.push({
|
||||||
|
path: '/translate',
|
||||||
|
query: {
|
||||||
|
img: imageUrl,
|
||||||
|
examId: rowinfo.value.examId,
|
||||||
|
orgId: rowinfo.value.orgId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
**在 translate/index.vue 中:**
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { onMounted } from 'vue'
|
||||||
|
import { useRoute } from 'vue-router'
|
||||||
|
import { useExamCacheStore } from '@/store/modules/examCache'
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const examCacheStore = useExamCacheStore()
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// 优先从 URL 参数获取,如果没有则从缓存获取
|
||||||
|
const examId = (route.query.examId as string) || examCacheStore.getValidExamId
|
||||||
|
const orgId = (route.query.orgId as string) || examCacheStore.getValidOrgId
|
||||||
|
const imgUrl = (route.query.img as string) || examCacheStore.imgUrl
|
||||||
|
|
||||||
|
// 如果从 URL 参数获取到数据,更新缓存
|
||||||
|
if (route.query.examId || route.query.orgId || route.query.img) {
|
||||||
|
examCacheStore.updateFromRoute(route.query)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### 场景2: ukey.ts 中使用缓存
|
||||||
|
|
||||||
|
**修改 ukey.ts 中的 uploadPdf 函数:**
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { useExamCacheStore } from '@/store/modules/examCache'
|
||||||
|
|
||||||
|
const uploadPdf = async (byteArray: number[], filename: string = 'signed.pdf') => {
|
||||||
|
try {
|
||||||
|
const fileStream = byteArray.join(',')
|
||||||
|
|
||||||
|
// 获取缓存 store
|
||||||
|
const examCacheStore = useExamCacheStore()
|
||||||
|
|
||||||
|
// 优先从缓存获取 examId 和 orgId,如果没有则从 route.query 获取
|
||||||
|
const examId = examCacheStore.getValidExamId || (route.query.examId as string) || ''
|
||||||
|
const orgId = examCacheStore.getValidOrgId || (route.query.orgId as string) || ''
|
||||||
|
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('examId', examId)
|
||||||
|
formData.append('orgId', orgId)
|
||||||
|
// ... 其他代码
|
||||||
|
} catch (error) {
|
||||||
|
console.error('文件上传失败:', error)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## API 参考
|
||||||
|
|
||||||
|
### Store 状态
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface ExamCacheState {
|
||||||
|
examId: string // 检查编号
|
||||||
|
orgId: string // 机构编号
|
||||||
|
imgUrl: string // 图片地址
|
||||||
|
timestamp: number // 缓存时间戳
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Getters
|
||||||
|
|
||||||
|
- `isCacheValid`: 检查缓存是否有效(24小时内)
|
||||||
|
- `getValidExamId`: 获取有效的 examId
|
||||||
|
- `getValidOrgId`: 获取有效的 orgId
|
||||||
|
|
||||||
|
### Actions
|
||||||
|
|
||||||
|
- `setCache(examId: string, orgId: string, imgUrl?: string)`: 设置缓存
|
||||||
|
- `clearCache()`: 清除缓存
|
||||||
|
- `updateFromRoute(query: any)`: 从路由参数更新缓存
|
||||||
|
|
||||||
|
## 缓存策略
|
||||||
|
|
||||||
|
### 优先级顺序
|
||||||
|
|
||||||
|
1. **URL 参数** - 最高优先级
|
||||||
|
2. **缓存数据** - 次优先级
|
||||||
|
3. **空值** - 最低优先级
|
||||||
|
|
||||||
|
### 有效期管理
|
||||||
|
|
||||||
|
- 缓存有效期为 **24 小时**
|
||||||
|
- 过期后需要重新设置
|
||||||
|
- 时间戳不持久化,每次页面刷新后重新计算
|
||||||
|
|
||||||
|
### 持久化配置
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
persist: {
|
||||||
|
key: 'exam-cache',
|
||||||
|
storage: localStorage,
|
||||||
|
paths: ['examId', 'orgId', 'imgUrl'] // 只持久化这些字段
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 最佳实践
|
||||||
|
|
||||||
|
### 1. 在页面跳转前设置缓存
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 推荐:在跳转前设置缓存
|
||||||
|
const examCacheStore = useExamCacheStore()
|
||||||
|
examCacheStore.setCache(examId, orgId, imgUrl)
|
||||||
|
router.push({ path: '/target', query: { examId, orgId, img: imgUrl } })
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 在目标页面优先使用 URL 参数
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 推荐:优先使用 URL 参数,然后回退到缓存
|
||||||
|
const examId = (route.query.examId as string) || examCacheStore.getValidExamId
|
||||||
|
const orgId = (route.query.orgId as string) || examCacheStore.getValidOrgId
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 定期清理过期缓存
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 在应用启动时检查缓存有效性
|
||||||
|
const examCacheStore = useExamCacheStore()
|
||||||
|
if (!examCacheStore.isCacheValid) {
|
||||||
|
examCacheStore.clearCache()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 错误处理
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 添加错误处理
|
||||||
|
try {
|
||||||
|
const examId = examCacheStore.getValidExamId
|
||||||
|
if (!examId) {
|
||||||
|
throw new Error('未找到有效的检查编号')
|
||||||
|
}
|
||||||
|
// 使用 examId
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取缓存失败:', error)
|
||||||
|
// 处理错误
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. **缓存有效期**: 缓存有效期为 24 小时,过期后需要重新设置
|
||||||
|
2. **类型安全**: 使用 TypeScript 确保类型安全
|
||||||
|
3. **降级处理**: 始终提供降级方案,避免因缓存问题导致功能不可用
|
||||||
|
4. **调试**: 使用浏览器开发者工具查看 localStorage 中的缓存数据
|
||||||
|
5. **清理**: 在适当的时候清理过期缓存
|
||||||
|
|
||||||
|
## 故障排除
|
||||||
|
|
||||||
|
### 常见问题
|
||||||
|
|
||||||
|
1. **缓存不生效**
|
||||||
|
- 检查 Pinia 是否正确配置
|
||||||
|
- 检查 localStorage 是否可用
|
||||||
|
- 检查缓存是否已过期
|
||||||
|
|
||||||
|
2. **类型错误**
|
||||||
|
- 确保正确导入类型
|
||||||
|
- 检查 TypeScript 配置
|
||||||
|
|
||||||
|
3. **缓存数据丢失**
|
||||||
|
- 检查 localStorage 存储限制
|
||||||
|
- 检查浏览器隐私设置
|
||||||
|
|
||||||
|
### 调试方法
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 在浏览器控制台中调试
|
||||||
|
const examCacheStore = useExamCacheStore()
|
||||||
|
console.log('缓存状态:', {
|
||||||
|
examId: examCacheStore.examId,
|
||||||
|
orgId: examCacheStore.orgId,
|
||||||
|
imgUrl: examCacheStore.imgUrl,
|
||||||
|
timestamp: examCacheStore.timestamp,
|
||||||
|
isValid: examCacheStore.isCacheValid
|
||||||
|
})
|
||||||
|
|
||||||
|
// 查看 localStorage
|
||||||
|
console.log('localStorage:', localStorage.getItem('exam-cache'))
|
||||||
|
```
|
||||||
@ -14,6 +14,14 @@
|
|||||||
content="芋道管理系统 基于 vue3 + CompositionAPI + typescript + vite3 + element plus 的后台开源免费管理系统!"
|
content="芋道管理系统 基于 vue3 + CompositionAPI + typescript + vite3 + element plus 的后台开源免费管理系统!"
|
||||||
/>
|
/>
|
||||||
<title>%VITE_APP_TITLE%</title>
|
<title>%VITE_APP_TITLE%</title>
|
||||||
|
<script>
|
||||||
|
window.require = function(module) {
|
||||||
|
if (module === 'fs') return {};
|
||||||
|
if (module === 'path') return {};
|
||||||
|
if (module === 'crypto') return {};
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"i": "pnpm install",
|
"i": "pnpm install",
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
"local": "vite --mode local",
|
||||||
"dev-server": "vite --mode dev",
|
"dev-server": "vite --mode dev",
|
||||||
"ts:check": "vue-tsc --noEmit",
|
"ts:check": "vue-tsc --noEmit",
|
||||||
"build:local": "node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build",
|
"build:local": "node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build",
|
||||||
@ -52,7 +53,7 @@
|
|||||||
"highlight.js": "^11.9.0",
|
"highlight.js": "^11.9.0",
|
||||||
"html2canvas": "^1.4.1",
|
"html2canvas": "^1.4.1",
|
||||||
"jsencrypt": "^3.3.2",
|
"jsencrypt": "^3.3.2",
|
||||||
"jspdf": "^2.5.1",
|
"jspdf": "^2.5.2",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"min-dash": "^4.1.1",
|
"min-dash": "^4.1.1",
|
||||||
"mitt": "^3.0.1",
|
"mitt": "^3.0.1",
|
||||||
@ -68,6 +69,7 @@
|
|||||||
"vue-clipboard3": "^2.0.0",
|
"vue-clipboard3": "^2.0.0",
|
||||||
"vue-dompurify-html": "^4.1.4",
|
"vue-dompurify-html": "^4.1.4",
|
||||||
"vue-i18n": "9.10.2",
|
"vue-i18n": "9.10.2",
|
||||||
|
"vue-pdf-embed": "^2.1.2",
|
||||||
"vue-qrcode": "^2.2.2",
|
"vue-qrcode": "^2.2.2",
|
||||||
"vue-router": "^4.3.0",
|
"vue-router": "^4.3.0",
|
||||||
"vue-types": "^5.1.1",
|
"vue-types": "^5.1.1",
|
||||||
@ -101,6 +103,7 @@
|
|||||||
"bpmn-js": "8.9.0",
|
"bpmn-js": "8.9.0",
|
||||||
"bpmn-js-properties-panel": "0.46.0",
|
"bpmn-js-properties-panel": "0.46.0",
|
||||||
"consola": "^3.2.3",
|
"consola": "^3.2.3",
|
||||||
|
"esbuild": "^0.25.3",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-define-config": "^2.1.0",
|
"eslint-define-config": "^2.1.0",
|
||||||
@ -134,7 +137,7 @@
|
|||||||
"vite-plugin-progress": "^0.0.7",
|
"vite-plugin-progress": "^0.0.7",
|
||||||
"vite-plugin-purge-icons": "^0.10.0",
|
"vite-plugin-purge-icons": "^0.10.0",
|
||||||
"vite-plugin-svg-icons": "^2.0.1",
|
"vite-plugin-svg-icons": "^2.0.1",
|
||||||
"vite-plugin-top-level-await": "^1.3.1",
|
"vite-plugin-top-level-await": "^1.5.0",
|
||||||
"vue-eslint-parser": "^9.3.2",
|
"vue-eslint-parser": "^9.3.2",
|
||||||
"vue-tsc": "^1.8.27"
|
"vue-tsc": "^1.8.27"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -5,7 +5,7 @@ const originImageAddress = 'https://zzxmc.gw12320.com/ecgimage/'
|
|||||||
export const processImageApi = {
|
export const processImageApi = {
|
||||||
// const apiUrl = 'https://zzxmc.gw12320.com/processImage'
|
// const apiUrl = 'https://zzxmc.gw12320.com/processImage'
|
||||||
apiUrl222 : 'https://pacs.gw12320.com/adminecg/admin-api/tblist/ecganalysisparas/rpc-processImage', //222服务器
|
apiUrl222 : 'https://pacs.gw12320.com/adminecg/admin-api/tblist/ecganalysisparas/rpc-processImage', //222服务器
|
||||||
apiUrl111 : 'http://111.57.76.10:8072/admin-api/tblist/ecganalysisparas/rpc-processImage', //111服务器
|
apiUrl111 : 'http://192.168.1.12:8072/admin-api/tblist/ecganalysisparas/rpc-processImage', //111服务器
|
||||||
|
|
||||||
// const apiUrl = 'https://localhost:48080/admin-api/tblist/ecganalysisparas/rpc-processImage'
|
// const apiUrl = 'https://localhost:48080/admin-api/tblist/ecganalysisparas/rpc-processImage'
|
||||||
// const imageAddress = 'F://陕西省咸阳市礼泉县心电图FTP/ecgimage/'
|
// const imageAddress = 'F://陕西省咸阳市礼泉县心电图FTP/ecgimage/'
|
||||||
|
|||||||
@ -88,8 +88,8 @@ export const PatientexamlistApi = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 超声审核
|
// 超声审核
|
||||||
examine: async (id: String, doctorname: string, doctorid: string) => {
|
examine: async (id: String, doctorname: string, doctorid: string, ecgId: string, doctorDiagResult: string) => {
|
||||||
return await request.get({ url: `/tblist/patientexamlist/examine?id=${id}&doctorname=${doctorname}&doctorid=${doctorid}` })
|
return await request.get({ url: `/tblist/patientexamlist/examine?id=${id}&doctorname=${doctorname}&doctorid=${doctorid}&ecgid=${ecgId}&doctorDiagResult=${doctorDiagResult}` })
|
||||||
},
|
},
|
||||||
// dicom数据同步
|
// dicom数据同步
|
||||||
dicomDataSync: async () => {
|
dicomDataSync: async () => {
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
import 'virtual:uno.css'
|
import 'uno.css'
|
||||||
|
|||||||
85
src/store/modules/examCache.ts
Normal file
85
src/store/modules/examCache.ts
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
import { defineStore } from 'pinia'
|
||||||
|
|
||||||
|
interface ExamCacheState {
|
||||||
|
examId: string
|
||||||
|
orgId: string
|
||||||
|
imgUrl: string
|
||||||
|
timestamp: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useExamCacheStore = defineStore('examCache', {
|
||||||
|
state: (): ExamCacheState => ({
|
||||||
|
examId: '',
|
||||||
|
orgId: '',
|
||||||
|
imgUrl: '',
|
||||||
|
timestamp: 0
|
||||||
|
}),
|
||||||
|
|
||||||
|
getters: {
|
||||||
|
// 检查缓存是否有效(24小时内)
|
||||||
|
isCacheValid(state) {
|
||||||
|
const now = Date.now()
|
||||||
|
const cacheAge = now - state.timestamp
|
||||||
|
const maxAge = 24 * 60 * 60 * 1000 // 24小时
|
||||||
|
return state.timestamp > 0 && cacheAge < maxAge
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取有效的examId
|
||||||
|
getValidExamId(state) {
|
||||||
|
const now = Date.now()
|
||||||
|
const cacheAge = now - state.timestamp
|
||||||
|
const maxAge = 24 * 60 * 60 * 1000 // 24小时
|
||||||
|
const isValid = state.timestamp > 0 && cacheAge < maxAge
|
||||||
|
return state.examId && isValid ? state.examId : ''
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取有效的orgId
|
||||||
|
getValidOrgId(state) {
|
||||||
|
const now = Date.now()
|
||||||
|
const cacheAge = now - state.timestamp
|
||||||
|
const maxAge = 24 * 60 * 60 * 1000 // 24小时
|
||||||
|
const isValid = state.timestamp > 0 && cacheAge < maxAge
|
||||||
|
return state.orgId && isValid ? state.orgId : ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
// 设置缓存
|
||||||
|
setCache(examId: string, orgId: string, imgUrl: string = '') {
|
||||||
|
this.examId = examId
|
||||||
|
this.orgId = orgId
|
||||||
|
this.imgUrl = imgUrl
|
||||||
|
this.timestamp = Date.now()
|
||||||
|
},
|
||||||
|
|
||||||
|
// 清除缓存
|
||||||
|
clearCache() {
|
||||||
|
this.examId = ''
|
||||||
|
this.orgId = ''
|
||||||
|
this.imgUrl = ''
|
||||||
|
this.timestamp = 0
|
||||||
|
},
|
||||||
|
|
||||||
|
// 从URL参数更新缓存
|
||||||
|
updateFromRoute(query: any) {
|
||||||
|
if (query.examId) {
|
||||||
|
this.examId = query.examId
|
||||||
|
}
|
||||||
|
if (query.orgId) {
|
||||||
|
this.orgId = query.orgId
|
||||||
|
}
|
||||||
|
if (query.img) {
|
||||||
|
this.imgUrl = query.img
|
||||||
|
}
|
||||||
|
this.timestamp = Date.now()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 持久化配置
|
||||||
|
persist: {
|
||||||
|
key: 'exam-cache',
|
||||||
|
storage: localStorage,
|
||||||
|
// 只持久化examId和orgId,不持久化timestamp
|
||||||
|
paths: ['examId', 'orgId', 'imgUrl']
|
||||||
|
}
|
||||||
|
})
|
||||||
108
src/utils/examCacheExample.ts
Normal file
108
src/utils/examCacheExample.ts
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/**
|
||||||
|
* examCache 缓存系统使用示例
|
||||||
|
*
|
||||||
|
* 这个文件展示了如何在不同的页面中使用 examCache 来存储和获取 examId 和 orgId
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { useExamCacheStore } from '@/store/modules/examCache'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 示例1: 在页面A中设置缓存
|
||||||
|
*/
|
||||||
|
export const setExamCacheExample = () => {
|
||||||
|
const examCacheStore = useExamCacheStore()
|
||||||
|
|
||||||
|
// 设置缓存
|
||||||
|
examCacheStore.setCache('EXAM001', 'ORG001', 'http://example.com/image.jpg')
|
||||||
|
|
||||||
|
console.log('缓存已设置:', {
|
||||||
|
examId: examCacheStore.examId,
|
||||||
|
orgId: examCacheStore.orgId,
|
||||||
|
imgUrl: examCacheStore.imgUrl,
|
||||||
|
timestamp: examCacheStore.timestamp
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 示例2: 在页面B中获取缓存
|
||||||
|
*/
|
||||||
|
export const getExamCacheExample = () => {
|
||||||
|
const examCacheStore = useExamCacheStore()
|
||||||
|
|
||||||
|
// 获取有效的examId和orgId
|
||||||
|
const examId = examCacheStore.getValidExamId
|
||||||
|
const orgId = examCacheStore.getValidOrgId
|
||||||
|
const imgUrl = examCacheStore.imgUrl
|
||||||
|
|
||||||
|
console.log('从缓存获取:', { examId, orgId, imgUrl })
|
||||||
|
|
||||||
|
// 检查缓存是否有效
|
||||||
|
if (examCacheStore.isCacheValid) {
|
||||||
|
console.log('缓存有效,可以使用')
|
||||||
|
return { examId, orgId, imgUrl }
|
||||||
|
} else {
|
||||||
|
console.log('缓存已过期或不存在')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 示例3: 从URL参数更新缓存
|
||||||
|
*/
|
||||||
|
export const updateFromRouteExample = (query: any) => {
|
||||||
|
const examCacheStore = useExamCacheStore()
|
||||||
|
|
||||||
|
// 从路由参数更新缓存
|
||||||
|
examCacheStore.updateFromRoute(query)
|
||||||
|
|
||||||
|
console.log('缓存已从路由参数更新')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 示例4: 清除缓存
|
||||||
|
*/
|
||||||
|
export const clearCacheExample = () => {
|
||||||
|
const examCacheStore = useExamCacheStore()
|
||||||
|
|
||||||
|
// 清除缓存
|
||||||
|
examCacheStore.clearCache()
|
||||||
|
|
||||||
|
console.log('缓存已清除')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 示例5: 在Vue组件中使用
|
||||||
|
*/
|
||||||
|
export const useExamCacheInComponent = () => {
|
||||||
|
const examCacheStore = useExamCacheStore()
|
||||||
|
|
||||||
|
return {
|
||||||
|
// 获取缓存数据
|
||||||
|
examId: examCacheStore.getValidExamId,
|
||||||
|
orgId: examCacheStore.getValidOrgId,
|
||||||
|
imgUrl: examCacheStore.imgUrl,
|
||||||
|
isCacheValid: examCacheStore.isCacheValid,
|
||||||
|
|
||||||
|
// 缓存操作方法
|
||||||
|
setCache: examCacheStore.setCache,
|
||||||
|
clearCache: examCacheStore.clearCache,
|
||||||
|
updateFromRoute: examCacheStore.updateFromRoute
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用说明:
|
||||||
|
*
|
||||||
|
* 1. 在页面跳转前设置缓存:
|
||||||
|
* const examCacheStore = useExamCacheStore()
|
||||||
|
* examCacheStore.setCache(examId, orgId, imgUrl)
|
||||||
|
*
|
||||||
|
* 2. 在目标页面获取缓存:
|
||||||
|
* const examCacheStore = useExamCacheStore()
|
||||||
|
* const examId = examCacheStore.getValidExamId
|
||||||
|
* const orgId = examCacheStore.getValidOrgId
|
||||||
|
*
|
||||||
|
* 3. 缓存会自动持久化到localStorage,页面刷新后仍然可用
|
||||||
|
* 4. 缓存有效期为24小时,过期后需要重新设置
|
||||||
|
* 5. 如果URL参数中有examId/orgId,会优先使用URL参数,并自动更新缓存
|
||||||
|
*/
|
||||||
@ -1,5 +1,7 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
import request from "@/config/axios";
|
||||||
|
import { useExamCacheStore } from '@/store/modules/examCache'
|
||||||
|
const route = useRoute()
|
||||||
// 类型声明
|
// 类型声明
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
@ -10,45 +12,81 @@ declare global {
|
|||||||
// 动态加载 SDK
|
// 动态加载 SDK
|
||||||
export const loadUKeySdk = () => {
|
export const loadUKeySdk = () => {
|
||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
|
// 输出调试信息
|
||||||
|
// console.log('=== SDK 加载调试信息 ===')
|
||||||
|
// console.log('当前页面URL:', window.location.href)
|
||||||
|
// console.log('当前域名:', window.location.origin)
|
||||||
|
// console.log('当前路径:', window.location.pathname)
|
||||||
|
// console.log('当前协议:', window.location.protocol)
|
||||||
|
// console.log('当前主机:', window.location.host)
|
||||||
|
// console.log('当前端口:', window.location.port)
|
||||||
|
// console.log('完整域名:', window.location.hostname)
|
||||||
|
// console.log('========================')
|
||||||
|
|
||||||
// 如果已经加载过,直接返回
|
// 如果已经加载过,直接返回
|
||||||
if (window.QysUKeySdk) {
|
if (window.QysUKeySdk) {
|
||||||
resolve()
|
resolve()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const script = document.createElement('script')
|
// 尝试多个可能的路径
|
||||||
script.src = '/sdk.min.v1.0.0.js'
|
const possiblePaths = [
|
||||||
script.type = 'text/javascript'
|
'/sdk.min.v1.0.0.js',
|
||||||
|
'./sdk.min.v1.0.0.js',
|
||||||
let retryCount = 0
|
`${window.location.origin}/sdk.min.v1.0.0.js`,
|
||||||
const maxRetries = 10
|
'/ecg/sdk.min.v1.0.0.js',
|
||||||
const checkInterval = 100 // 100ms 检查一次
|
'./ecg/sdk.min.v1.0.0.js'
|
||||||
|
]
|
||||||
const checkSDK = () => {
|
|
||||||
if (window.QysUKeySdk) {
|
let currentPathIndex = 0
|
||||||
console.log('SDK 加载成功')
|
|
||||||
resolve()
|
const tryLoadScript = () => {
|
||||||
} else if (retryCount < maxRetries) {
|
if (currentPathIndex >= possiblePaths.length) {
|
||||||
retryCount++
|
reject(new Error('所有SDK路径都尝试失败,请检查SDK文件是否存在'))
|
||||||
console.log(`等待 SDK 初始化... (${retryCount}/${maxRetries})`)
|
return
|
||||||
setTimeout(checkSDK, checkInterval)
|
|
||||||
} else {
|
|
||||||
reject(new Error('SDK 加载失败:QysUKeySdk 未定义,请检查 SDK 文件是否正确'))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const script = document.createElement('script')
|
||||||
|
script.src = possiblePaths[currentPathIndex]
|
||||||
|
script.type = 'text/javascript'
|
||||||
|
|
||||||
|
let retryCount = 0
|
||||||
|
const maxRetries = 10
|
||||||
|
const checkInterval = 100 // 100ms 检查一次
|
||||||
|
|
||||||
|
const checkSDK = () => {
|
||||||
|
if (window.QysUKeySdk) {
|
||||||
|
console.log('SDK 加载成功,路径:', possiblePaths[currentPathIndex])
|
||||||
|
resolve()
|
||||||
|
} else if (retryCount < maxRetries) {
|
||||||
|
retryCount++
|
||||||
|
console.log(`等待 SDK 初始化... (${retryCount}/${maxRetries})`)
|
||||||
|
setTimeout(checkSDK, checkInterval)
|
||||||
|
} else {
|
||||||
|
// 当前路径失败,尝试下一个路径
|
||||||
|
console.log(`路径 ${possiblePaths[currentPathIndex]} 失败,尝试下一个路径`)
|
||||||
|
currentPathIndex++
|
||||||
|
tryLoadScript()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
script.onload = () => {
|
||||||
|
console.log('SDK 脚本加载完成,路径:', possiblePaths[currentPathIndex])
|
||||||
|
// 脚本加载完成后,给一点时间让 SDK 初始化
|
||||||
|
setTimeout(checkSDK, 50)
|
||||||
|
}
|
||||||
|
|
||||||
|
script.onerror = (error) => {
|
||||||
|
console.error('SDK 脚本加载失败,路径:', possiblePaths[currentPathIndex], error)
|
||||||
|
// 当前路径失败,尝试下一个路径
|
||||||
|
currentPathIndex++
|
||||||
|
tryLoadScript()
|
||||||
|
}
|
||||||
|
|
||||||
|
document.head.appendChild(script)
|
||||||
}
|
}
|
||||||
|
|
||||||
script.onload = () => {
|
tryLoadScript()
|
||||||
console.log('SDK 脚本加载完成,开始检查初始化状态')
|
|
||||||
// 脚本加载完成后,给一点时间让 SDK 初始化
|
|
||||||
setTimeout(checkSDK, 50)
|
|
||||||
}
|
|
||||||
|
|
||||||
script.onerror = (error) => {
|
|
||||||
console.error('SDK 脚本加载失败:', error)
|
|
||||||
reject(new Error('SDK 脚本加载失败:' + error))
|
|
||||||
}
|
|
||||||
|
|
||||||
document.head.appendChild(script)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,26 +103,39 @@ const downloadPdf = (data: any, filename: string = 'signed.pdf') => {
|
|||||||
URL.revokeObjectURL(url)
|
URL.revokeObjectURL(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
const uploadPdf = async (byteArray: number[], filename: string = 'signed.pdf') => {
|
const uploadPdf = async (byteArray: number[], filename) => {
|
||||||
// return
|
// return
|
||||||
try {
|
try {
|
||||||
// 将字节数组转换为逗号分隔的字符串
|
// 将字节数组转换为逗号分隔的字符串
|
||||||
const fileStream = byteArray.join(',');
|
const fileStream = byteArray.join(',');
|
||||||
|
|
||||||
|
// 获取缓存store
|
||||||
|
const examCacheStore = useExamCacheStore()
|
||||||
|
|
||||||
|
// 优先从缓存获取examId和orgId,如果没有则从route.query获取
|
||||||
|
const examId = examCacheStore.getValidExamId || (route.query.examId as string) || ''
|
||||||
|
const orgId = examCacheStore.getValidOrgId || (route.query.orgId as string) || ''
|
||||||
|
// console.log(examId,orgId)
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
|
formData.append('examId', examId);
|
||||||
|
formData.append('orgId', orgId);
|
||||||
formData.append('fileStream', fileStream);
|
formData.append('fileStream', fileStream);
|
||||||
formData.append('filename', filename);
|
formData.append('filename', filename??`examId=${examId}&orgId=${orgId}`);
|
||||||
formData.append('fileType', 'pdf');
|
formData.append('fileType', 'pdf');
|
||||||
formData.append('savePath', 'F:/陕西省咸阳市礼泉县心电图FTP/ecgimage/imgOcrAndProcess/');
|
formData.append('savePath', 'F:/陕西省咸阳市礼泉县心电图FTP/ecgimage/signature/');
|
||||||
|
|
||||||
const response = await fetch('https://zzxmc.gw12320.com/uploadFile', {
|
// const url = "http://localhost:58080/uploadFile"
|
||||||
|
// const url = 'http://zzxmc.gw12320.com/uploadFile'
|
||||||
|
/*const response = await fetch(url, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData
|
body: formData
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
const response = await request.post({url:`/tblist/ecganalysisparas/rpc-uploadPdf`,data:formData})
|
||||||
|
|
||||||
const result = await response.json();
|
// const result = await response.json();
|
||||||
console.log('上传结果:', result);
|
console.log('上传结果:', response);
|
||||||
return result;
|
return response;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('文件上传失败:', error);
|
console.error('文件上传失败:', error);
|
||||||
throw error;
|
throw error;
|
||||||
@ -97,13 +148,16 @@ export const getUKeySdk = () => {
|
|||||||
const sdk = new window.QysUKeySdk({
|
const sdk = new window.QysUKeySdk({
|
||||||
signCb: async function(file) {
|
signCb: async function(file) {
|
||||||
try {
|
try {
|
||||||
await uploadPdf(file[0].rawFileData)
|
console.log(file)
|
||||||
|
await uploadPdf(file[0].rawFileData,null)
|
||||||
|
|
||||||
console.log('签署完成,文件已上传到服务器', file);
|
console.log('签署完成,文件已上传到服务器', file);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('文件处理失败:', error)
|
console.error('文件处理失败:', error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
console.log(route)
|
||||||
return sdk
|
return sdk
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('创建 SDK 实例失败:', error)
|
console.error('创建 SDK 实例失败:', error)
|
||||||
|
|||||||
@ -602,6 +602,8 @@ import { processImageApi } from '@/api/processImage'
|
|||||||
import {encodeBase64} from "@/utils/base64"
|
import {encodeBase64} from "@/utils/base64"
|
||||||
import Dialog from "@/components/Dialog/src/Dialog.vue";
|
import Dialog from "@/components/Dialog/src/Dialog.vue";
|
||||||
import { log } from 'console'
|
import { log } from 'console'
|
||||||
|
import { useExamCacheStore } from '@/store/modules/examCache'
|
||||||
|
import { getConfig, getConfigKey } from '@/api/infra/config'
|
||||||
|
|
||||||
const { toClipboard } = useClipboard()
|
const { toClipboard } = useClipboard()
|
||||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||||
@ -737,36 +739,48 @@ const open = async (row: any) => {
|
|||||||
}
|
}
|
||||||
//审核功能
|
//审核功能
|
||||||
async function process() {
|
async function process() {
|
||||||
|
/* console.log(queryParams.value)
|
||||||
|
console.log(rowinfo.value)
|
||||||
|
return */
|
||||||
|
|
||||||
uKeyable.value=false
|
uKeyable.value=false
|
||||||
if (applyFormVO.value.reportstatus === '已分析') {
|
if (applyFormVO.value.reportstatus === '已分析') {
|
||||||
|
|
||||||
// 审核确认
|
// 审核确认
|
||||||
await message.delConfirm('是否进行审核操作', '审核')
|
await message.delConfirm('是否进行审核操作', '审核')
|
||||||
// uKeyable.value=true
|
// uKeyable.value=true
|
||||||
const response = await PatientexamlistApi.examine(keyid.value,Profilevo.value.doctorname,Profilevo.value.doctorID)
|
const response = await PatientexamlistApi.examine(keyid.value,Profilevo.value.doctorname,Profilevo.value.doctorID,queryParams.value.id,queryParams.value.doctorDiagResult)
|
||||||
|
|
||||||
if (response) {
|
if (response) {
|
||||||
|
console.log(response)
|
||||||
message.alertSuccess('审核成功')
|
message.alertSuccess('审核成功')
|
||||||
let data = Object.assign({},processImageApi.paramsList[rowinfo.value.orgName])
|
/* let data = Object.assign({},processImageApi.paramsList[rowinfo.value.orgName])
|
||||||
data.imagePath = queryParams.value.ecgJsonDataFilePath
|
data.imagePath = queryParams.value.ecgJsonDataFilePath
|
||||||
data.examId = rowinfo.value.examId
|
data.examId = rowinfo.value.examId
|
||||||
data.orgId = rowinfo.value.orgId
|
data.orgId = rowinfo.value.orgId
|
||||||
data.watermarkText = data.step + queryParams.value.doctorDiagResult
|
data.watermarkText = data.step + queryParams.value.doctorDiagResult
|
||||||
// console.log(data)
|
|
||||||
data.imagePath = processImageApi.urlToAddress(data.imagePath)
|
data.imagePath = processImageApi.urlToAddress(data.imagePath)
|
||||||
// const processResponse = await processImageApi.processImg(data,processImageApi.apiUrl111)
|
const processResponse = await processImageApi.processImg(data,processImageApi.apiUrl111) // 移动项目
|
||||||
const processResponse = await processImageApi.processImg(data,processImageApi.apiUrl222)
|
// const processResponse = await processImageApi.processImg(data,processImageApi.apiUrl222) // 礼泉县项目
|
||||||
// 1. 解析外层 JSON 的 data 字符串
|
// 1. 解析外层 JSON 的 data 字符串
|
||||||
const dataObj = JSON.parse(processResponse.data.data);
|
const dataObj = JSON.parse(processResponse.data.data);
|
||||||
|
|
||||||
// 2. 直接获取 updateSuccess 的值
|
// 2. 直接获取 updateSuccess 的值
|
||||||
const updateSuccess = dataObj.updateSuccess;
|
const updateSuccess = dataObj.updateSuccess; */
|
||||||
if (!updateSuccess){
|
|
||||||
message.warning('诊断图片生成异常')
|
// const imageUrl = processImageApi.addressToUrl(dataObj.imagePath)
|
||||||
}else{
|
// console.log(imageUrl)
|
||||||
const imageUrl = processImageApi.addressToUrl(dataObj.imagePath)
|
// 更新缓存
|
||||||
// 使用 window.open 打开新标签页
|
const examCacheStore = useExamCacheStore()
|
||||||
window.open(`/translate?img=${encodeURIComponent(imageUrl)}`, '_blank')
|
examCacheStore.setCache(rowinfo.value.examId, rowinfo.value.orgId, response)
|
||||||
}
|
|
||||||
|
// 使用 window.open 打开新标签页 仅222礼泉县需要开启
|
||||||
|
// window.open(`/translate?img=${encodeURIComponent(response)}`, '_blank')
|
||||||
|
const config = await getConfigKey("pdf.sign.key")
|
||||||
|
if(config == "1"){
|
||||||
|
router.push({path:'/translate',query:{img:response}})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
await getPatientexamlist(keyid.value)
|
await getPatientexamlist(keyid.value)
|
||||||
emit('success')
|
emit('success')
|
||||||
|
|||||||
@ -37,7 +37,7 @@ import { ref, onMounted, nextTick } from 'vue'
|
|||||||
import { loadUKeySdk, getUKeySdk } from '@/utils/ukey'
|
import { loadUKeySdk, getUKeySdk } from '@/utils/ukey'
|
||||||
import { ElLoading, ElMessage } from 'element-plus'
|
import { ElLoading, ElMessage } from 'element-plus'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { log } from 'console'
|
import request from '@/config/axios'
|
||||||
|
|
||||||
const ukeySdk = ref<any>(null)
|
const ukeySdk = ref<any>(null)
|
||||||
const container = ref<HTMLDivElement|null>(null)
|
const container = ref<HTMLDivElement|null>(null)
|
||||||
@ -49,12 +49,33 @@ import { log } from 'console'
|
|||||||
loading.value = true
|
loading.value = true
|
||||||
const pdfParam = route.query.img
|
const pdfParam = route.query.img
|
||||||
console.log('PDF参数:', pdfParam)
|
console.log('PDF参数:', pdfParam)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await loadUKeySdk()
|
// 尝试加载 SDK,最多重试 3 次
|
||||||
ukeySdk.value = getUKeySdk()
|
let sdkLoaded = false
|
||||||
if (!ukeySdk.value) {
|
for (let i = 0; i < 3; i++) {
|
||||||
throw new Error('SDK 初始化失败')
|
try {
|
||||||
|
console.log(`尝试加载 SDK (第 ${i + 1} 次)`)
|
||||||
|
await loadUKeySdk()
|
||||||
|
ukeySdk.value = getUKeySdk()
|
||||||
|
if (ukeySdk.value) {
|
||||||
|
sdkLoaded = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`第 ${i + 1} 次加载失败:`, error)
|
||||||
|
if (i === 2) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
// 等待 1 秒后重试
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 1000))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!sdkLoaded) {
|
||||||
|
throw new Error('SDK 初始化失败,请刷新页面重试')
|
||||||
|
}
|
||||||
|
|
||||||
ElMessage.success('SDK 加载成功')
|
ElMessage.success('SDK 加载成功')
|
||||||
|
|
||||||
// 如果有URL参数,使用URL参数;否则使用默认URL
|
// 如果有URL参数,使用URL参数;否则使用默认URL
|
||||||
@ -73,7 +94,7 @@ import { log } from 'console'
|
|||||||
})
|
})
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error('SDK加载失败:', error)
|
console.error('SDK加载失败:', error)
|
||||||
ElMessage.error(error.message || 'SDK 加载失败')
|
ElMessage.error(error.message || 'SDK 加载失败,请刷新页面重试')
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
@ -131,9 +152,17 @@ import { log } from 'console'
|
|||||||
console.log('开始设置loading状态')
|
console.log('开始设置loading状态')
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
console.log('开始获取PDF文件:', pdf)
|
// 转换PDF URL,使用代理路径
|
||||||
|
let pdfUrl = pdf
|
||||||
|
if (pdf.includes('zzxmc.gw12320.com')) {
|
||||||
|
// 将外部域名替换为代理路径
|
||||||
|
pdfUrl = pdf.replace('https://zzxmc.gw12320.com', '')
|
||||||
|
console.log('转换后的PDF URL:', pdfUrl)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('开始获取PDF文件:', pdfUrl)
|
||||||
// 获取 PDF 文件
|
// 获取 PDF 文件
|
||||||
const response = await axios.get(pdf, {
|
const response = await axios.get(pdfUrl, {
|
||||||
responseType: 'blob',
|
responseType: 'blob',
|
||||||
timeout: 30000, // 设置超时时间
|
timeout: 30000, // 设置超时时间
|
||||||
headers: {
|
headers: {
|
||||||
@ -141,7 +170,6 @@ import { log } from 'console'
|
|||||||
'Pragma': 'no-cache'
|
'Pragma': 'no-cache'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log('PDF文件获取成功,响应状态:', response.status)
|
console.log('PDF文件获取成功,响应状态:', response.status)
|
||||||
console.log('开始创建File对象')
|
console.log('开始创建File对象')
|
||||||
// 创建 File 对象
|
// 创建 File 对象
|
||||||
|
|||||||
@ -3,7 +3,12 @@ import { dateFormatter } from '@/utils/formatTime'
|
|||||||
import * as MailAccountApi from '@/api/system/mail/account'
|
import * as MailAccountApi from '@/api/system/mail/account'
|
||||||
|
|
||||||
// 邮箱账号的列表
|
// 邮箱账号的列表
|
||||||
const accountList = await MailAccountApi.getSimpleMailAccountList()
|
let accountList: any[] = []
|
||||||
|
|
||||||
|
// 初始化账号列表
|
||||||
|
const initAccountList = async () => {
|
||||||
|
accountList = await MailAccountApi.getSimpleMailAccountList()
|
||||||
|
}
|
||||||
|
|
||||||
// CrudSchema:https://doc.iocoder.cn/vue3/crud-schema/
|
// CrudSchema:https://doc.iocoder.cn/vue3/crud-schema/
|
||||||
const crudSchemas = reactive<CrudSchema[]>([
|
const crudSchemas = reactive<CrudSchema[]>([
|
||||||
@ -74,7 +79,12 @@ const crudSchemas = reactive<CrudSchema[]>([
|
|||||||
search: {
|
search: {
|
||||||
show: true,
|
show: true,
|
||||||
component: 'Select',
|
component: 'Select',
|
||||||
api: () => accountList,
|
api: async () => {
|
||||||
|
if (accountList.length === 0) {
|
||||||
|
await initAccountList()
|
||||||
|
}
|
||||||
|
return accountList
|
||||||
|
},
|
||||||
componentProps: {
|
componentProps: {
|
||||||
optionsAlias: {
|
optionsAlias: {
|
||||||
labelField: 'mail',
|
labelField: 'mail',
|
||||||
|
|||||||
@ -29,14 +29,21 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
|
|||||||
host: "0.0.0.0",
|
host: "0.0.0.0",
|
||||||
open: env.VITE_OPEN === 'true',
|
open: env.VITE_OPEN === 'true',
|
||||||
// 本地跨域代理. 目前注释的原因:暂时没有用途,server 端已经支持跨域
|
// 本地跨域代理. 目前注释的原因:暂时没有用途,server 端已经支持跨域
|
||||||
// proxy: {
|
proxy: {
|
||||||
// ['/admin-api']: {
|
['/admin-api']: {
|
||||||
// target: env.VITE_BASE_URL,
|
target: env.VITE_BASE_URL,
|
||||||
// ws: false,
|
ws: false,
|
||||||
// changeOrigin: true,
|
changeOrigin: true,
|
||||||
// rewrite: (path) => path.replace(new RegExp(`^/admin-api`), ''),
|
rewrite: (path) => path.replace(new RegExp(`^/admin-api`), ''),
|
||||||
// },
|
},
|
||||||
// },
|
// 添加PDF文件代理
|
||||||
|
['/ecgimage']: {
|
||||||
|
target: 'https://zzxmc.gw12320.com',
|
||||||
|
ws: false,
|
||||||
|
changeOrigin: true,
|
||||||
|
secure: false, // 如果是https可能需要设置为false
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
// 项目使用的vite插件。 单独提取到build/vite/plugin中管理
|
// 项目使用的vite插件。 单独提取到build/vite/plugin中管理
|
||||||
plugins: createVitePlugins(),
|
plugins: createVitePlugins(),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user