diff --git a/src/components/BasicNjBjSelect/demo.vue b/src/components/BasicNjBjSelect/demo.vue index 4f83ca9..63c54a7 100644 --- a/src/components/BasicNjBjSelect/demo.vue +++ b/src/components/BasicNjBjSelect/demo.vue @@ -158,3 +158,9 @@ const setDefaultValue = () => { + + + + + + diff --git a/src/components/BasicNjBjSelect/index.vue b/src/components/BasicNjBjSelect/index.vue index e1b991c..e4e41dc 100644 --- a/src/components/BasicNjBjSelect/index.vue +++ b/src/components/BasicNjBjSelect/index.vue @@ -16,17 +16,17 @@ + 取消 {{ title }} - - 取消 - 确定 - + 确定 - - + + 加载中... + + {{ nj.title }} - @@ -68,7 +61,7 @@ v-if="nj.expanded" class="class-children" > - + + + 暂无数据 @@ -258,6 +253,14 @@ const displayText = computed(() => { return '' }) +// 获取选中数量 +const getSelectedCount = () => { + if (!props.modelValue) return 0 + const gradeCount = props.modelValue.selectedGrades?.length || 0 + const classCount = props.modelValue.selectedClasses?.length || 0 + return gradeCount + classCount +} + // 监听 modelValue 变化 watch(() => props.modelValue, (newVal) => { if (newVal) { @@ -522,36 +525,31 @@ onMounted(() => { flex-direction: column; .popup-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 15px 20px; + padding: 10px 15px; + background-color: #fff; border-bottom: 1px solid #eee; + display: flex; + justify-content: space-between; + align-items: center; flex-shrink: 0; + .cancel-btn { + font-size: 14px; + color: #666; + padding: 4px 8px; + } + .popup-title { font-size: 16px; - font-weight: 600; + font-weight: bold; color: #333; } - - .popup-actions { - display: flex; - gap: 20px; - - .action-btn { - font-size: 14px; - padding: 4px 8px; - - &.cancel-btn { - color: #999; - } - - &.confirm-btn { - color: #1890ff; - font-weight: 500; - } - } + + .confirm-btn { + font-size: 14px; + color: #409eff; + font-weight: 500; + padding: 4px 8px; } } @@ -564,7 +562,8 @@ onMounted(() => { .tree-scroll { flex: 1; background-color: #fff; - min-height: 0; + box-sizing: border-box; + overflow-y: auto; .tree-container { padding: 0; @@ -572,6 +571,10 @@ onMounted(() => { .tree-node { .tree-item { + display: flex; + align-items: center; + justify-content: space-between; + padding: 10px 15px; border-bottom: 1px solid #f0f0f0; &:last-child { @@ -587,13 +590,13 @@ onMounted(() => { border-bottom: 1px solid #e0e0e0; .tree-item-content { - padding: 5px 12px; display: flex; align-items: center; - min-height: 30px; + flex-grow: 1; + margin-right: 15px; .expand-icon { - margin-right: 5px; + margin-right: 10px; display: flex; align-items: center; justify-content: center; @@ -603,13 +606,13 @@ onMounted(() => { .grade-text { flex: 1; - font-size: 14px; - font-weight: 500; + font-size: 15px; color: #333; } - .grade-checkbox { - margin-left: 5px; + .grade-checkbox, + .grade-radio { + flex-shrink: 0; } } } @@ -618,26 +621,27 @@ onMounted(() => { background-color: #fff; .tree-item-content { - padding: 3px 12px 3px 26px; display: flex; align-items: center; - min-height: 26px; + flex-grow: 1; + margin-right: 15px; .class-indent { width: 10px; height: 1px; background-color: #e0e0e0; - margin-right: 5px; + margin-right: 10px; } .class-text { flex: 1; - font-size: 13px; - color: #666; + font-size: 15px; + color: #333; } - .class-checkbox { - margin-left: 5px; + .class-checkbox, + .class-radio { + flex-shrink: 0; } } } @@ -659,8 +663,7 @@ onMounted(() => { } .tree-item-content { - padding: 2px 12px 2px 26px; - min-height: 24px; + padding: 8px 15px 8px 26px; } } } @@ -668,6 +671,15 @@ onMounted(() => { } } } + + } + + .loading-indicator, + .empty-state { + text-align: center; + color: #999; + padding: 30px 15px; + font-size: 14px; } } diff --git a/src/components/ImageVideoUpload/ImageVideoUpload.vue b/src/components/ImageVideoUpload/ImageVideoUpload.vue new file mode 100644 index 0000000..b1553ce --- /dev/null +++ b/src/components/ImageVideoUpload/ImageVideoUpload.vue @@ -0,0 +1,845 @@ + + + + + diff --git a/src/components/ImageVideoUpload/README.md b/src/components/ImageVideoUpload/README.md new file mode 100644 index 0000000..0dd099e --- /dev/null +++ b/src/components/ImageVideoUpload/README.md @@ -0,0 +1,223 @@ +# ImageVideoUpload 图片视频上传组件 + +一个功能完整的图片和视频上传组件,支持压缩、预览、删除等功能。 + +## 功能特性 + +- ✅ 图片和视频上传 +- ✅ 智能图片压缩(支持H5和APP环境) +- ✅ 文件大小和时长限制 +- ✅ 预览功能 +- ✅ 删除功能 +- ✅ 上传进度显示 +- ✅ 自定义压缩配置 +- ✅ 自动上传或手动上传 +- ✅ 完整的事件回调 + +## 基本使用 + +```vue + + + +``` + +## Props 属性 + +| 属性名 | 类型 | 默认值 | 说明 | +|--------|------|--------|------| +| enableImage | boolean | true | 是否启用图片上传 | +| enableVideo | boolean | true | 是否启用视频上传 | +| maxImageCount | number | 5 | 最大图片数量 | +| maxVideoCount | number | 3 | 最大视频数量 | +| imageList | ImageItem[] | [] | 图片列表 | +| videoList | VideoItem[] | [] | 视频列表 | +| compressConfig | CompressConfig | 默认配置 | 压缩配置 | +| autoUpload | boolean | true | 是否自动上传 | +| uploadApi | Function | - | 上传API函数 | + +## Events 事件 + +| 事件名 | 参数 | 说明 | +|--------|------|------| +| update:imageList | images: ImageItem[] | 图片列表更新 | +| update:videoList | videos: VideoItem[] | 视频列表更新 | +| 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 | 视频上传失败 | +| upload-progress | type: 'image' \| 'video', current: number, total: number | 上传进度 | + +## 压缩配置 + +### 使用预设配置 + +```javascript +import { COMPRESS_PRESETS } from '@/components/ImageVideoUpload' + +// 高质量配置 +const highQualityConfig = COMPRESS_PRESETS.high + +// 平衡配置(默认) +const mediumConfig = COMPRESS_PRESETS.medium + +// 高压缩配置 +const lowQualityConfig = COMPRESS_PRESETS.low +``` + +### 自定义配置 + +```javascript +const customConfig = { + image: { + quality: 70, // 压缩质量 (1-100) + maxWidth: 1600, // 最大宽度 + maxHeight: 900, // 最大高度 + maxSize: 300 * 1024, // 最大文件大小 300KB + minQuality: 25 // 最低压缩质量 + }, + video: { + maxDuration: 45, // 最大时长45秒 + maxSize: 8 * 1024 * 1024, // 最大文件大小 8MB + quality: 'medium' // 视频质量 + } +} +``` + +## 高级用法 + +### 手动上传 + +```vue + + + +``` + +### 监听上传进度 + +```vue + + + +``` + +## 样式自定义 + +组件使用 scoped 样式,如需自定义样式,可以通过以下方式: + +```vue + +``` + +## 注意事项 + +1. **H5环境**:使用Canvas进行图片压缩 +2. **APP环境**:使用uni.compressImage进行压缩 +3. **文件大小**:建议根据实际需求调整压缩配置 +4. **上传API**:需要返回标准的响应格式 +5. **内存管理**:上传成功后会自动清理临时文件 + +## 响应格式要求 + +上传API需要返回以下格式的响应: + +```javascript +{ + resultCode: 1, // 1表示成功 + result: [ + { + filePath: "服务器文件路径" + } + ] +} +``` diff --git a/src/components/ImageVideoUpload/example.vue b/src/components/ImageVideoUpload/example.vue new file mode 100644 index 0000000..d913310 --- /dev/null +++ b/src/components/ImageVideoUpload/example.vue @@ -0,0 +1,65 @@ + + + + + diff --git a/src/components/ImageVideoUpload/index.ts b/src/components/ImageVideoUpload/index.ts new file mode 100644 index 0000000..2409d19 --- /dev/null +++ b/src/components/ImageVideoUpload/index.ts @@ -0,0 +1,6 @@ +// 导出组件和类型 +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..44cf045 --- /dev/null +++ b/src/components/ImageVideoUpload/types.ts @@ -0,0 +1,132 @@ +// 图片项接口 +export interface ImageItem { + tempPath?: string // 临时路径(用于预览) + url?: string // 服务器路径(上传成功后) + name?: string // 文件名 + originalPath?: string // 原始路径(用于调试) + isCompressed?: boolean // 是否已压缩 +} + +// 视频项接口 +export interface VideoItem { + tempPath?: string // 临时路径(用于预览) + url?: string // 服务器路径(上传成功后) + name?: string // 文件名 + duration?: number // 视频时长(秒) + size?: number // 文件大小(字节) + thumbnail?: string // 缩略图路径 +} + +// 压缩配置接口 +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[] + + // 压缩配置 + compressConfig?: CompressConfig + + // 上传配置 + autoUpload?: boolean + uploadApi?: (file: any) => Promise +} + +// 组件Emits接口 +export interface ImageVideoUploadEmits { + 'update:imageList': [images: ImageItem[]] + 'update:videoList': [videos: VideoItem[]] + '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] + 'upload-progress': [type: 'image' | 'video', 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/components/ImageVideoUpload/使用说明.md b/src/components/ImageVideoUpload/使用说明.md new file mode 100644 index 0000000..cc1b59e --- /dev/null +++ b/src/components/ImageVideoUpload/使用说明.md @@ -0,0 +1,204 @@ +# ImageVideoUpload 图片视频上传组件 + +## 组件位置 +`D:\code\zhxy-jsd\src\components\ImageVideoUpload\` + +## 文件结构 +``` +ImageVideoUpload/ +├── ImageVideoUpload.vue # 主组件文件 +├── types.ts # 类型定义 +├── index.ts # 导出文件 +├── example.vue # 使用示例 +├── README.md # 详细文档 +└── 使用说明.md # 中文说明 +``` + +## 快速使用 + +### 1. 基本用法 +```vue + + + +``` + +### 2. 完整配置 +```vue + + + +``` + +## 主要功能 + +### ✅ 图片功能 +- 拍照/相册选择 +- 智能压缩(H5/APP自适应) +- 预览功能 +- 删除功能 +- 压缩状态显示 + +### ✅ 视频功能 +- 拍摄/相册选择 +- 文件大小检查 +- 时长限制 +- 预览播放 +- 删除功能 + +### ✅ 压缩功能 +- 尺寸压缩(降低分辨率) +- 质量压缩(调整JPEG质量) +- 智能压缩(根据文件大小自动调整) +- 多级压缩(确保达到目标大小) + +## 压缩配置 + +### 预设配置 +```javascript +import { COMPRESS_PRESETS } from '@/components/ImageVideoUpload' + +// 高质量(文件较大) +const highConfig = COMPRESS_PRESETS.high + +// 平衡(推荐) +const mediumConfig = COMPRESS_PRESETS.medium + +// 高压缩(文件很小) +const lowConfig = COMPRESS_PRESETS.low +``` + +### 自定义配置 +```javascript +const customConfig = { + image: { + quality: 70, // 压缩质量 1-100 + maxWidth: 1600, // 最大宽度 + maxHeight: 900, // 最大高度 + maxSize: 300 * 1024, // 最大文件大小(字节) + minQuality: 25 // 最低压缩质量 + }, + video: { + maxDuration: 45, // 最大时长(秒) + maxSize: 8 * 1024 * 1024, // 最大文件大小(字节) + quality: 'medium' // 视频质量 + } +} +``` + +## 事件回调 + +```javascript +// 图片上传成功 +@image-upload-success="(image, index) => {}" + +// 图片上传失败 +@image-upload-error="(error, index) => {}" + +// 视频上传成功 +@video-upload-success="(video, index) => {}" + +// 视频上传失败 +@video-upload-error="(error, index) => {}" + +// 上传进度 +@upload-progress="(type, current, total) => {}" +``` + +## 在 xcXkkcDetail.vue 中的使用 + +原来的代码已经替换为: + +```vue + +``` + +## 注意事项 + +1. **环境兼容**:自动检测H5/APP环境,使用不同的压缩方案 +2. **文件大小**:建议根据实际需求调整压缩配置 +3. **上传API**:需要返回标准格式的响应 +4. **内存管理**:上传成功后自动清理临时文件 +5. **错误处理**:完善的错误处理和用户提示 + +## 响应格式要求 + +上传API需要返回: +```javascript +{ + resultCode: 1, // 1表示成功 + result: [ + { + filePath: "服务器文件路径" + } + ] +} +``` + +## 样式自定义 + +组件使用scoped样式,如需自定义: + +```css +/* 全局样式覆盖 */ +.image-video-upload .add-btn { + border-color: #007aff; +} +``` + +## 测试 + +可以运行 `example.vue` 来测试组件功能。 diff --git a/src/config.ts b/src/config.ts index a58b5aa..0b64be4 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,7 +1,9 @@ const ip: string = "127.0.0.1:8897"; -// const ip: string = "yufangzc.com"; -// const ip: string = "lzcxsx.cn"; -const fwqip: string = "lzcxsx.cn"; +const fwqip: string = "127.0.0.1:8897"; +//const ip: string = "lzcxsx.cn"; +//const fwqip: string = "lzcxsx.cn"; +//const ip: string = "zhxy.yufangzc.com";// +//const fwqip: string = "zhxy.yufangzc.com"; //打包服务器接口代理标识 const SERVERAGENT: string = "/jsd-api"; //本地代理url地址,配置了就启动代理,没配置就不启动代理 @@ -15,7 +17,7 @@ export const BASE_WS_URL: string = `wss://${ip}`; // export const BASE_IMAGE_URL: string = process.env.NODE_ENV == "development" ? `https://${ip}` : `https://${fwqip}`; export const BASE_IMAGE_URL = `https://${fwqip}`; // kkFileView预览服务地址 -export const KK_FILE_VIEW_URL: string = `http://${fwqip}:8891`; +export const KK_FILE_VIEW_URL: string = `https://${fwqip}/kkpro`; //存token的key export const AUTH_KEY: string = "satoken"; //token过期返回状态码 diff --git a/src/pages.json b/src/pages.json index 355cc1d..efce466 100644 --- a/src/pages.json +++ b/src/pages.json @@ -241,6 +241,13 @@ "enablePullDownRefresh": false } }, + { + "path": "pages/view/routine/ShiTangXunCha/edit", + "style": { + "navigationBarTitleText": "食堂巡查修改", + "enablePullDownRefresh": false + } + }, { "path": "pages/view/routine/JiFenPingJia/detail", "style": { diff --git a/src/pages/base/service/index.vue b/src/pages/base/service/index.vue index d2eda67..5b7c155 100644 --- a/src/pages/base/service/index.vue +++ b/src/pages/base/service/index.vue @@ -242,7 +242,7 @@ const sections = reactive([ { id: "r6", icon: "kfxc", - text: "课服巡查", + text: "教学巡查", show: true, permissionKey: "routine-kfxc", // 课服巡查权限编码 path: "/pages/view/routine/kefuxuncha/xcPbList", diff --git a/src/pages/view/homeSchool/BanJiKeBiao.vue b/src/pages/view/homeSchool/BanJiKeBiao.vue index b9487b9..cd14a9e 100644 --- a/src/pages/view/homeSchool/BanJiKeBiao.vue +++ b/src/pages/view/homeSchool/BanJiKeBiao.vue @@ -85,8 +85,12 @@ let bjId = ''; // 改变了年级班级 const changeNjBj = (nj: any, bj: any) => { bjId = bj.key; - selectDay(curRqIndex.value); - console.log(nj, bj); + console.log("班级选择变更:", { nj, bj, bjId }); + + // 重新加载当前日期的课表数据 + if (rqList.value.length > 0) { + selectDay(curRqIndex.value); + } }; // 这是当年的第几周 @@ -153,7 +157,8 @@ const selectWeek = (zc: any) => { // 关闭弹窗 closeWeekPicker(); - // 选中第一天 + // 重置为第一天并加载数据 + curRqIndex.value = 0; selectDay(0); }; @@ -163,9 +168,18 @@ const selectDay = (index: number) => { if (!rqList.value.length) { return; } + + console.log("查询课表参数:", { + jsId: "", + bjId: bjId || "", + xqId: xqId, + rq: rqList.value[index].rq, + zj: rqList.value[index].zj + }); + drpkkbApi({ jsId: "", // getJs.id, - bjId: bjId, + bjId: bjId || "", // 如果没有选择班级,传空字符串 xqId: xqId, rq: rqList.value[index].rq, // 用于查询代课信息 zj: rqList.value[index].zj @@ -173,14 +187,17 @@ const selectDay = (index: number) => { // 根据接口返回的result判断是否已报名 if (res && res.resultCode === 1) { sjList.value = res.result; + console.log("课表数据加载成功:", res.result); } else { // 接口调用成功但返回错误 - console.warn("检查报名状态接口返回错误:", res); + console.warn("课表接口返回错误:", res); + sjList.value = []; } }) .catch((error) => { // 接口调用失败 - console.error("调用检查报名状态接口失败:", error); + console.error("调用课表接口失败:", error); + sjList.value = []; }); }; @@ -194,17 +211,38 @@ const getCourseColorClass = (subject: string | undefined): string => { }; onMounted(async () => { - const res = await dqpkApi(); - const result = res.result; - dqZc = res.result.dqZc; - xqId = res.result.dqXq.id; - zcList.value = result.zcList; - sjList.value = result.sjList; - let zc = zcList.value.find((item:any) => item.djz === dqZc); - if (!zc) { - zc = zcList.value[0]; + try { + const res = await dqpkApi(); + const result = res.result; + dqZc = res.result.dqZc; + xqId = res.result.dqXq.id; + zcList.value = result.zcList; + sjList.value = result.sjList; + + // 1. 默认定位到当前周 + let zc = zcList.value.find((item:any) => item.djz === dqZc); + if (!zc) { + zc = zcList.value[0]; + } + + // 设置周次和日期 + Object.assign(curZc.value, zc); + Object.assign(rqList.value, curZc.value.drList); + + // 2. 默认定位到当前周几(周三) + const currentDayOfWeek = dayjs().day(); // 0=周日, 1=周一, ..., 6=周六 + const targetDayIndex = currentDayOfWeek === 0 ? 6 : currentDayOfWeek - 1; // 转换为1=周一, 7=周日的格式 + + // 确保索引在有效范围内 + const validDayIndex = Math.min(Math.max(targetDayIndex, 0), rqList.value.length - 1); + curRqIndex.value = validDayIndex; + + + // 自动加载当前日期的课表数据 + selectDay(validDayIndex); + } catch (error) { + console.error("初始化失败:", error); } - selectWeek(zc); }); @@ -380,6 +418,7 @@ onMounted(async () => { } } + .loading-overlay { position: absolute; top: 0; diff --git a/src/pages/view/routine/ShiTangXunCha/detail.vue b/src/pages/view/routine/ShiTangXunCha/detail.vue index cf8f9ba..be8f7f4 100644 --- a/src/pages/view/routine/ShiTangXunCha/detail.vue +++ b/src/pages/view/routine/ShiTangXunCha/detail.vue @@ -62,7 +62,7 @@ + + diff --git a/src/pages/view/routine/ShiTangXunCha/index.vue b/src/pages/view/routine/ShiTangXunCha/index.vue index 077c836..dcd777e 100644 --- a/src/pages/view/routine/ShiTangXunCha/index.vue +++ b/src/pages/view/routine/ShiTangXunCha/index.vue @@ -55,16 +55,30 @@ - + + + 提交人: {{ data.jsxm || '未知' }} 提交时间: {{ formatTime(data.tjtime) }} + + + 修改 + + @@ -170,6 +184,7 @@ const getHcList = async () => { // 跳转到详情页 const goToDetail = (hcId: string) => { + console.log('点击卡片,跳转详情页,ID:', hcId); uni.navigateTo({ url: `/pages/view/routine/ShiTangXunCha/detail?id=${hcId}`, }); @@ -182,6 +197,14 @@ const goToAdd = () => { }); }; +// 跳转到修改页 +const goToEdit = (hcId: string) => { + console.log('点击修改按钮,ID:', hcId); + uni.navigateTo({ + url: `/pages/view/routine/ShiTangXunCha/edit?id=${hcId}`, + }); +}; + // 格式化时间 const formatTime = (timeStr: string) => { if (!timeStr) return ""; @@ -200,6 +223,14 @@ const getImageUrl = (imagePath: string) => { return imagUrl(firstImage); }; +// 获取图片列表(最多3张) +const getImageList = (imagePath: string) => { + if (!imagePath) return []; + // 按逗号分割图片路径,最多取3张 + const imagePaths = imagePath.split(',').slice(0, 3); + return imagePaths.map(path => imagUrl(path.trim())); +}; + onShow(() => { getHcList(); }); @@ -371,12 +402,23 @@ onMounted(() => { } .image-preview { + display: flex; + gap: 8px; + flex-wrap: wrap; + margin-top: 8px; + + .preview-image-wrapper { + position: relative; + flex-shrink: 0; + } + .preview-image { width: 80px; height: 60px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); object-fit: cover; + display: block; } } } @@ -409,6 +451,36 @@ onMounted(() => { flex-shrink: 0; } } + + .footer-actions { + margin-left: auto; + flex-shrink: 0; + + .edit-btn { + background: linear-gradient(135deg, #28a745 0%, #20c997 100%); + border: none; + border-radius: 6px; + font-size: 12px; + font-weight: 500; + padding: 4px 12px; + min-width: 50px; + height: 28px; + box-shadow: 0 2px 6px rgba(40, 167, 69, 0.3); + position: relative; + z-index: 10; + display: flex; + align-items: center; + justify-content: center; + color: #ffffff; + cursor: pointer; + transition: all 0.2s ease; + + &:active { + transform: translateY(1px); + box-shadow: 0 1px 3px rgba(40, 167, 69, 0.4); + } + } + } } // 新增按钮 - 固定在底部 diff --git a/src/pages/view/routine/jc/components/dm.vue b/src/pages/view/routine/jc/components/dm.vue index ecd6143..a1e8c3b 100644 --- a/src/pages/view/routine/jc/components/dm.vue +++ b/src/pages/view/routine/jc/components/dm.vue @@ -3,22 +3,10 @@ 选择班级 - + + {{ selectedClassText || "请选择班级" }} + + ℹ️ @@ -38,16 +26,18 @@ ref="dmXsRef" /> - + - @@ -69,15 +59,30 @@ 提交点名 + + + \ No newline at end of file diff --git a/src/pages/view/routine/kefuxuncha/kyRecord.vue b/src/pages/view/routine/kefuxuncha/kyRecord.vue index 799ffec..a98af46 100644 --- a/src/pages/view/routine/kefuxuncha/kyRecord.vue +++ b/src/pages/view/routine/kefuxuncha/kyRecord.vue @@ -7,10 +7,18 @@ style="position: absolute" >