From 96d1d38a8badd46bde904875b11ce127d3534dde Mon Sep 17 00:00:00 2001 From: hebo Date: Wed, 24 Dec 2025 19:45:48 +0800 Subject: [PATCH] =?UTF-8?q?=E7=94=9F=E6=97=A5=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 37 +- package.json | 4 +- scripts/update-version.js | 47 + src/api/base/wjApi.ts | 76 + .../ImageVideoUpload/ImageVideoUpload.vue | 1285 ++++++++++++ src/components/ImageVideoUpload/index.ts | 7 + src/components/ImageVideoUpload/types.ts | 156 ++ src/pages.json | 8 +- src/pages/base/wj/indexwb.vue | 1761 +++++++++++++++++ src/utils/filePreview.ts | 49 + vite.config.ts | 12 + 11 files changed, 3437 insertions(+), 5 deletions(-) create mode 100644 scripts/update-version.js create mode 100644 src/api/base/wjApi.ts create mode 100644 src/components/ImageVideoUpload/ImageVideoUpload.vue create mode 100644 src/components/ImageVideoUpload/index.ts create mode 100644 src/components/ImageVideoUpload/types.ts create mode 100644 src/pages/base/wj/indexwb.vue create mode 100644 src/utils/filePreview.ts diff --git a/index.html b/index.html index c405e45..d3bb385 100644 --- a/index.html +++ b/index.html @@ -2,13 +2,46 @@ + + + + + + diff --git a/package.json b/package.json index df5943a..0339bb7 100644 --- a/package.json +++ b/package.json @@ -22,8 +22,8 @@ "build:app-android": "uni build -p app-android", "build:app-ios": "uni build -p app-ios", "build:custom": "uni build -p", - "build:h5": "uni build", - "build:h5:ssr": "uni build --ssr", + "build:h5": "node scripts/update-version.js && uni build", + "build:h5:ssr": "node scripts/update-version.js && uni build --ssr", "build:mp-alipay": "uni build -p mp-alipay", "build:mp-baidu": "uni build -p mp-baidu", "build:mp-kuaishou": "uni build -p mp-kuaishou", diff --git a/scripts/update-version.js b/scripts/update-version.js new file mode 100644 index 0000000..f5d0811 --- /dev/null +++ b/scripts/update-version.js @@ -0,0 +1,47 @@ +const fs = require('fs'); +const path = require('path'); + +// 生成版本号(格式:YYYYMMDD-HHmmss) +function generateVersion() { + const now = new Date(); + const year = now.getFullYear(); + const month = String(now.getMonth() + 1).padStart(2, '0'); + const day = String(now.getDate()).padStart(2, '0'); + const hours = String(now.getHours()).padStart(2, '0'); + const minutes = String(now.getMinutes()).padStart(2, '0'); + const seconds = String(now.getSeconds()).padStart(2, '0'); + return `${year}${month}${day}-${hours}${minutes}${seconds}`; +} + +// 更新 index.html 中的版本号 +function updateVersion() { + const htmlPath = path.join(__dirname, '../index.html'); + + if (!fs.existsSync(htmlPath)) { + console.error('❌ index.html 文件不存在:', htmlPath); + process.exit(1); + } + + let html = fs.readFileSync(htmlPath, 'utf8'); + const version = generateVersion(); + + // 替换版本号 + if (html.includes('/, + `` + ); + } else { + // 如果不存在版本号 meta 标签,在 charset 后面添加 + html = html.replace( + //, + `\n \n ` + ); + } + + fs.writeFileSync(htmlPath, html, 'utf8'); + console.log(`✅ 版本号已更新为: ${version}`); +} + +updateVersion(); + diff --git a/src/api/base/wjApi.ts b/src/api/base/wjApi.ts new file mode 100644 index 0000000..714ea7e --- /dev/null +++ b/src/api/base/wjApi.ts @@ -0,0 +1,76 @@ +import { get, post } from "@/utils/request"; + +/** + * 问卷相关API + */ + +/** + * 根据ID获取问卷详情(包含验证权限) + */ +export const questionnaireFindByIdApi = async (params: { id: string }) => { + return await get(`/api/questionnaire/findById?id=${params.id}`); +}; + +/** + * 验证问卷填写权限 + */ +export const questionnaireCheckPermissionApi = async (params: { questionnaireId: string }) => { + return await post("/api/questionnaire/checkPermission", params); +}; + +/** + * 获取问卷列表(分页) + */ +export const questionnaireFindPageApi = async (params: any) => { + return await get("/api/questionnaire/findPage", params); +}; + +/** + * 获取问卷题目列表 + */ +export const questionnaireQuestionFindPageApi = async (params: any) => { + return await get("/api/questionnaireQuestion/findPage", params); +}; + +/** + * 保存问卷答案 + */ +export const questionnaireAnswerSaveApi = async (params: any) => { + return await post("/api/questionnaireAnswer/save", params); +}; + +/** + * 查询用户是否已填写问卷 + */ +export const questionnaireAnswerFindByUserApi = async (params: { questionnaireId: string }) => { + return await get("/api/questionnaireAnswer/findByUser", params); +}; + +/** + * 获取问卷填写人列表(分页) + */ +export const questionnaireAnswerFindPageApi = async (params: any) => { + return await get("/api/questionnaireAnswer/findPage", params); +}; + +/** + * 根据问卷ID获取填写人列表(按问卷ID和提交用户ID分组) + */ +export const questionnaireAnswerFindUserListApi = async (params: { questionnaireId: string }) => { + return await get("/api/questionnaireAnswer/findUserListByQuestionnaireId", params); +}; + +/** + * 根据问卷ID和用户ID获取问卷填写详情 + */ +export const questionnaireAnswerFindDetailApi = async (params: { questionnaireId: string, userId?: string, answerId?: string }) => { + return await get("/api/questionnaireAnswer/findDetail", params); +}; + +/** + * 使用AI分析问卷内容 + */ +export const questionnaireAnalyzeWithAIApi = async (params: any) => { + return await post("/api/questionnaireAnswer/analyzeWithAI", params); +}; + diff --git a/src/components/ImageVideoUpload/ImageVideoUpload.vue b/src/components/ImageVideoUpload/ImageVideoUpload.vue new file mode 100644 index 0000000..4ca4d14 --- /dev/null +++ b/src/components/ImageVideoUpload/ImageVideoUpload.vue @@ -0,0 +1,1285 @@ + + + + + + diff --git a/src/components/ImageVideoUpload/index.ts b/src/components/ImageVideoUpload/index.ts new file mode 100644 index 0000000..fcf56e1 --- /dev/null +++ b/src/components/ImageVideoUpload/index.ts @@ -0,0 +1,7 @@ +// 导出组件和类型 +export { default as ImageVideoUpload } from './ImageVideoUpload.vue' +export * from './types' + +// 默认导出 +export { default } from './ImageVideoUpload.vue' + diff --git a/src/components/ImageVideoUpload/types.ts b/src/components/ImageVideoUpload/types.ts new file mode 100644 index 0000000..1ef4420 --- /dev/null +++ b/src/components/ImageVideoUpload/types.ts @@ -0,0 +1,156 @@ +// 图片项接口 +export interface ImageItem { + tempPath?: string // 临时路径(用于预览) + url?: string // 服务器路径(上传成功后) + name?: string // 文件名(临时文件名或服务器文件名) + originalName?: string // 原始文件名(用户选择的真实文件名) + originalPath?: string // 原始路径(用于调试) + isCompressed?: boolean // 是否已压缩 +} + +// 视频项接口 +export interface VideoItem { + tempPath?: string // 临时路径(用于预览) + url?: string // 服务器路径(上传成功后) + name?: string // 文件名(临时文件名或服务器文件名) + originalName?: string // 原始文件名(用户选择的真实文件名) + duration?: number // 视频时长(秒) + size?: number // 文件大小(字节) + thumbnail?: string // 缩略图路径 +} + +// 文件项接口 +export interface FileItem { + tempPath?: string // 临时路径(用于预览) + url?: string // 服务器路径(上传成功后) + name?: string // 文件名(临时文件名或服务器文件名) + originalName?: string // 原始文件名(用户选择的真实文件名) + type?: string // 文件类型(image/video/audio/document等) + size?: number // 文件大小(字节) + extension?: string // 文件扩展名 + mimeType?: string // MIME类型 +} + +// 压缩配置接口 +export interface CompressConfig { + image: { + quality: number // 压缩质量 (1-100) + maxWidth: number // 最大宽度 + maxHeight: number // 最大高度 + maxSize: number // 最大文件大小(字节) + minQuality: number // 最低压缩质量 + } + video: { + maxDuration: number // 最大时长(秒) + maxSize: number // 最大文件大小(字节) + quality: string // 视频质量 + } +} + +// 组件Props接口 +export interface ImageVideoUploadProps { + // 图片相关 + enableImage?: boolean + maxImageCount?: number + imageList?: ImageItem[] + + // 视频相关 + enableVideo?: boolean + maxVideoCount?: number + videoList?: VideoItem[] + + // 文件相关 + enableFile?: boolean + maxFileCount?: number + fileList?: FileItem[] + allowedFileTypes?: string[] // 允许的文件类型,如 ['pdf', 'doc', 'docx', 'mp3', 'wav'] + + // 压缩配置 + compressConfig?: CompressConfig + + // 上传配置 + autoUpload?: boolean + uploadApi?: (file: any) => Promise +} + +// 组件Emits接口 +export interface ImageVideoUploadEmits { + 'update:imageList': [images: ImageItem[]] + 'update:videoList': [videos: VideoItem[]] + 'update:fileList': [files: FileItem[]] + 'image-upload-success': [image: ImageItem, index: number] + 'image-upload-error': [error: any, index: number] + 'video-upload-success': [video: VideoItem, index: number] + 'video-upload-error': [error: any, index: number] + 'file-upload-success': [file: FileItem, index: number] + 'file-upload-error': [error: any, index: number] + 'upload-progress': [type: 'image' | 'video' | 'file', current: number, total: number] +} + +// 默认压缩配置 +export const DEFAULT_COMPRESS_CONFIG: CompressConfig = { + image: { + quality: 60, + maxWidth: 1280, + maxHeight: 720, + maxSize: 200 * 1024, // 200KB + minQuality: 20 + }, + video: { + maxDuration: 60, + maxSize: 10 * 1024 * 1024, // 10MB + quality: 'medium' + } +} + +// 预设压缩配置 +export const COMPRESS_PRESETS = { + // 高质量配置 + high: { + image: { + quality: 80, + maxWidth: 1920, + maxHeight: 1080, + maxSize: 500 * 1024, // 500KB + minQuality: 40 + }, + video: { + maxDuration: 60, + maxSize: 20 * 1024 * 1024, // 20MB + quality: 'high' + } + }, + + // 平衡配置 + medium: { + image: { + quality: 60, + maxWidth: 1280, + maxHeight: 720, + maxSize: 200 * 1024, // 200KB + minQuality: 20 + }, + video: { + maxDuration: 60, + maxSize: 10 * 1024 * 1024, // 10MB + quality: 'medium' + } + }, + + // 高压缩配置 + low: { + image: { + quality: 40, + maxWidth: 960, + maxHeight: 540, + maxSize: 100 * 1024, // 100KB + minQuality: 15 + }, + video: { + maxDuration: 30, + maxSize: 5 * 1024 * 1024, // 5MB + quality: 'low' + } + } +} + diff --git a/src/pages.json b/src/pages.json index 162f32f..05769a3 100644 --- a/src/pages.json +++ b/src/pages.json @@ -150,7 +150,13 @@ "enablePullDownRefresh": false } }, - + { + "path": "pages/base/wj/indexwb", + "style": { + "navigationBarTitleText": "家长问卷", + "enablePullDownRefresh": false + } + }, { "path": "pages/base/xk/index", "style": { diff --git a/src/pages/base/wj/indexwb.vue b/src/pages/base/wj/indexwb.vue new file mode 100644 index 0000000..027619c --- /dev/null +++ b/src/pages/base/wj/indexwb.vue @@ -0,0 +1,1761 @@ +