生日调整
This commit is contained in:
parent
c79e037aab
commit
96d1d38a8b
37
index.html
37
index.html
@ -2,13 +2,46 @@
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<!-- 版本号:每次发布时自动更新 -->
|
||||
<meta name="version" content="20251209-154559">
|
||||
<!-- HTML文件不缓存,但允许静态资源缓存 -->
|
||||
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
|
||||
<meta http-equiv="Pragma" content="no-cache">
|
||||
<meta http-equiv="Expires" content="0">
|
||||
<script>
|
||||
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
|
||||
CSS.supports('top: constant(a)'))
|
||||
document.write(
|
||||
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
|
||||
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
|
||||
log=false
|
||||
(coverSupport ? ', viewport-fit=cover' : '') + '" />');
|
||||
var log = false;
|
||||
|
||||
// 版本检查:如果检测到新版本,清除缓存并刷新
|
||||
(function() {
|
||||
try {
|
||||
const currentVersion = document.querySelector('meta[name="version"]')?.getAttribute('content');
|
||||
const storedVersion = localStorage.getItem('app_version');
|
||||
|
||||
if (storedVersion && storedVersion !== currentVersion && currentVersion) {
|
||||
// 检测到新版本,清除所有缓存
|
||||
if ('caches' in window) {
|
||||
caches.keys().then(names => {
|
||||
names.forEach(name => caches.delete(name));
|
||||
});
|
||||
}
|
||||
// 更新版本号
|
||||
localStorage.setItem('app_version', currentVersion);
|
||||
// 强制刷新页面
|
||||
window.location.reload(true);
|
||||
} else if (currentVersion) {
|
||||
// 首次访问或版本相同,保存版本号
|
||||
localStorage.setItem('app_version', currentVersion);
|
||||
}
|
||||
} catch (e) {
|
||||
// 版本检查失败不影响页面加载
|
||||
console.warn('Version check failed:', e);
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
<title></title>
|
||||
<!--preload-links-->
|
||||
|
||||
@ -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",
|
||||
|
||||
47
scripts/update-version.js
Normal file
47
scripts/update-version.js
Normal file
@ -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('<meta name="version"')) {
|
||||
html = html.replace(
|
||||
/<meta name="version" content="[^"]*">/,
|
||||
`<meta name="version" content="${version}">`
|
||||
);
|
||||
} else {
|
||||
// 如果不存在版本号 meta 标签,在 charset 后面添加
|
||||
html = html.replace(
|
||||
/<meta charset="UTF-8"\/>/,
|
||||
`<meta charset="UTF-8"/>\n <!-- 版本号:每次发布时自动更新 -->\n <meta name="version" content="${version}">`
|
||||
);
|
||||
}
|
||||
|
||||
fs.writeFileSync(htmlPath, html, 'utf8');
|
||||
console.log(`✅ 版本号已更新为: ${version}`);
|
||||
}
|
||||
|
||||
updateVersion();
|
||||
|
||||
76
src/api/base/wjApi.ts
Normal file
76
src/api/base/wjApi.ts
Normal file
@ -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);
|
||||
};
|
||||
|
||||
1285
src/components/ImageVideoUpload/ImageVideoUpload.vue
Normal file
1285
src/components/ImageVideoUpload/ImageVideoUpload.vue
Normal file
File diff suppressed because it is too large
Load Diff
7
src/components/ImageVideoUpload/index.ts
Normal file
7
src/components/ImageVideoUpload/index.ts
Normal file
@ -0,0 +1,7 @@
|
||||
// 导出组件和类型
|
||||
export { default as ImageVideoUpload } from './ImageVideoUpload.vue'
|
||||
export * from './types'
|
||||
|
||||
// 默认导出
|
||||
export { default } from './ImageVideoUpload.vue'
|
||||
|
||||
156
src/components/ImageVideoUpload/types.ts
Normal file
156
src/components/ImageVideoUpload/types.ts
Normal file
@ -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<any>
|
||||
}
|
||||
|
||||
// 组件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'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -150,7 +150,13 @@
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "pages/base/wj/indexwb",
|
||||
"style": {
|
||||
"navigationBarTitleText": "家长问卷",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/base/xk/index",
|
||||
"style": {
|
||||
|
||||
1761
src/pages/base/wj/indexwb.vue
Normal file
1761
src/pages/base/wj/indexwb.vue
Normal file
File diff suppressed because it is too large
Load Diff
49
src/utils/filePreview.ts
Normal file
49
src/utils/filePreview.ts
Normal file
@ -0,0 +1,49 @@
|
||||
// 文件预览工具函数
|
||||
export const previewFile = (fileUrl: string, fileName: string, fileType: string) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const type = fileType.toLowerCase();
|
||||
|
||||
// 检查是否是压缩包文件,如果是则直接下载
|
||||
if (['zip', 'rar', '7z', 'tar', 'gz'].includes(type)) {
|
||||
uni.showToast({ title: '压缩包文件不支持预览,将为您下载', icon: 'none' });
|
||||
downloadFile(fileUrl, fileName).then(resolve).catch(resolve);
|
||||
return;
|
||||
}
|
||||
|
||||
// 使用 kkview 预览
|
||||
const previewUrl = fileUrl;
|
||||
const needLandscape = ['ppt', 'pptx'].includes(type);
|
||||
|
||||
// 打开预览页面
|
||||
uni.navigateTo({
|
||||
url: `/pages/base/view/index?url=${encodeURIComponent(previewUrl)}&name=${encodeURIComponent(fileName)}&landscape=${needLandscape}`,
|
||||
success: resolve,
|
||||
fail: reject
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// 下载文件
|
||||
const downloadFile = (fileUrl: string, fileName: string) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.downloadFile({
|
||||
url: fileUrl,
|
||||
success: (res) => {
|
||||
if (res.statusCode === 200) {
|
||||
uni.saveFile({
|
||||
tempFilePath: res.tempFilePath,
|
||||
success: (saveRes) => {
|
||||
uni.showToast({ title: '文件已保存', icon: 'success' });
|
||||
resolve(saveRes);
|
||||
},
|
||||
fail: reject
|
||||
});
|
||||
} else {
|
||||
reject(new Error('下载失败'));
|
||||
}
|
||||
},
|
||||
fail: reject
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@ -17,6 +17,18 @@ export default defineConfig({
|
||||
},
|
||||
port: 5139,
|
||||
},
|
||||
build: {
|
||||
// 确保文件名包含 hash,便于缓存失效控制
|
||||
rollupOptions: {
|
||||
output: {
|
||||
entryFileNames: `assets/[name]-[hash].js`,
|
||||
chunkFileNames: `assets/[name]-[hash].js`,
|
||||
assetFileNames: `assets/[name]-[hash].[ext]`,
|
||||
}
|
||||
},
|
||||
// 生成 manifest 方便版本追踪
|
||||
manifest: true,
|
||||
},
|
||||
plugins: [
|
||||
//c 为class 例如 class="wi-10"
|
||||
//w 为样式style 例如 width:10rpx
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user