diff --git a/src/api/base/pbApi.ts b/src/api/base/pbApi.ts index 7a8c71b..1910eff 100644 --- a/src/api/base/pbApi.ts +++ b/src/api/base/pbApi.ts @@ -56,6 +56,13 @@ export const getKyXcCourseListApi = async (params: any) => { return await get("/api/pb/getKyXcCourseList", params); }; +/** + * 就餐点名课程列表接口 + */ +export const getJcDmCourseListApi = async (params: any) => { + return await get("/api/pb/getJcDmCourseList", params); +}; + /** * 值周巡查接口 - 获取值周排班数据 */ diff --git a/src/api/base/zwApi.ts b/src/api/base/zwApi.ts index 059f0df..6b0e96c 100644 --- a/src/api/base/zwApi.ts +++ b/src/api/base/zwApi.ts @@ -23,3 +23,9 @@ export const findAllZw = () => { }; + + + + + + diff --git a/src/components/BasicXsPicker/index.vue b/src/components/BasicXsPicker/index.vue index 6ec33f8..54e5b93 100644 --- a/src/components/BasicXsPicker/index.vue +++ b/src/components/BasicXsPicker/index.vue @@ -2,7 +2,7 @@ {{ curStudentLabel || displayPlaceholder }} - + @@ -155,8 +155,6 @@ const setValueByData = (student: any) => { // 显示选择器弹窗 const showPicker = async () => { - console.log('🖱️ 用户点击学生选择器'); - // 设置用户选择标志 isUserSelecting.value = true; @@ -165,7 +163,6 @@ const showPicker = async () => { // 如果已经有学生数据,直接显示弹窗 if (studentList.value.length > 0) { - console.log('✅ 学生数据已存在,直接显示弹窗'); filteredStudentList.value = studentList.value; showPopup.value = true; return; @@ -173,27 +170,19 @@ const showPicker = async () => { // 如果正在加载中,不重复加载 if (isLoading.value) { - console.log('⏳ 正在加载中,请稍候'); return; } // 直接尝试从父组件获取班级信息 - console.log('📞 尝试从父组件获取班级信息'); - // 通过 emit 请求父组件提供班级信息 emit('getClassInfo'); // 延迟一下,给父组件时间处理 setTimeout(() => { - console.log('⏰ 延迟检查是否获取到班级信息'); - console.log('🔍 当前 props.classInfo:', props.classInfo); - // 如果 props.classInfo 有值,直接使用 if (props.classInfo && props.classInfo.njId && props.classInfo.bjId) { - console.log('✅ 发现 props.classInfo,直接加载学生数据'); loadStudentDataByClassInfo(props.classInfo); } else { - console.log('❌ 没有获取到班级信息,尝试直接调用API'); // 尝试直接调用API,使用默认的年级班级ID // 这里需要从全局状态或者其他地方获取班级信息 // 暂时先显示提示 @@ -207,28 +196,22 @@ const showPicker = async () => { // 暴露方法给父组件调用 const loadStudentDataByClassInfo = async (classInfo: any) => { - console.log('🔄 通过班级信息加载学生数据:', classInfo); - if (!classInfo || !classInfo.njId || !classInfo.bjId) { - console.log('⚠️ 班级信息不完整,清空学生数据'); clearStudentData(); return; } try { isLoading.value = true; - console.log('🚀 开始加载学生数据'); const params = { njId: classInfo.njId, bjIds: [classInfo.bjId] }; - console.log('📤 发送API请求,参数:', params); const res = await findStudentInfoByNjAndBjApi(params); if (res && res.result && res.result.length > 0) { - console.log('✅ 学生数据加载成功:', res.result); studentList.value = res.result; studentRange.value = res.result.map((item: any) => item.xm || ''); @@ -237,23 +220,17 @@ const loadStudentDataByClassInfo = async (classInfo: any) => { // 如果有默认值,设置选中项 if (props.modelValue) { - const index = studentList.value.findIndex((item: any) => item.id === props.modelValue); + const modelId = props.modelValue.id || props.modelValue.xsId || props.modelValue; + const index = studentList.value.findIndex((item: any) => item.id === modelId); if (index >= 0) { curIndex.value = index; curStudentLabel.value = studentRange.value[index]; } } else { // 没有默认值时,不设置 curIndex,保持弹窗打开状态 - console.log('🎯 不自动选择,等待用户手动选择'); curStudentLabel.value = ""; } - - // 如果弹窗已打开,显示学生列表 - if (showPopup.value) { - console.log('📋 弹窗已打开,显示学生列表'); - } } else { - console.log('⚠️ 没有找到学生数据'); clearStudentData(); } } catch (error) { @@ -266,35 +243,23 @@ const loadStudentDataByClassInfo = async (classInfo: any) => { // 直接设置学生数据的方法 const setStudentData = (data: any[]) => { - console.log('🔄 直接设置学生数据:', data?.length, '个学生'); - if (data && data.length > 0) { - console.log('✅ 设置学生数据成功'); studentList.value = data; studentRange.value = data.map((item: any) => item.xm || ''); // 更新过滤列表 filteredStudentList.value = studentList.value; - console.log('📋 学生选项列表:', studentRange.value.slice(0, 5)); // 只显示前5个选项 - // 如果有默认值,设置选中项 if (props.modelValue) { - const index = studentList.value.findIndex((item: any) => item.id === props.modelValue); + const modelId = props.modelValue.id || props.modelValue.xsId || props.modelValue; + const index = studentList.value.findIndex((item: any) => item.id === modelId); if (index >= 0) { curIndex.value = index; curStudentLabel.value = studentRange.value[index]; } } - - console.log('🎯 学生选择器状态更新完成:', { - studentListLength: studentList.value.length, - studentRangeLength: studentRange.value.length, - curIndex: curIndex.value, - curStudentLabel: curStudentLabel.value - }); } else { - console.log('⚠️ 学生数据为空,清空数据'); clearStudentData(); } }; @@ -313,35 +278,28 @@ const clearStudentData = () => { // 搜索输入处理 const onSearchInput = () => { - console.log('🔍 搜索关键词:', searchKeyword.value); filteredStudentList.value = filterStudents(studentList.value, searchKeyword.value); }; // 选择学生 const selectStudent = (student: any) => { - console.log('🎯 选择学生:', student); selectedStudent.value = student; }; // 取消操作 const handleCancel = () => { - console.log('❌ 取消选择'); showPopup.value = false; selectedStudent.value = null; }; // 确认选择 const handleConfirm = () => { - console.log('✅ 确认选择:', selectedStudent.value); - if (props.disabled) { - console.log('⏸️ 组件已禁用,跳过处理'); return; } if (selectedStudent.value) { const student = selectedStudent.value; - console.log('✅ 选中的学生:', student); curStudentLabel.value = student.xm; // 发送数据给父组件 @@ -360,18 +318,8 @@ const handleConfirm = () => { student: student }; - console.log('📤 发送给父组件的数据:', result); - console.log('🔍 学生数据字段映射:', { - 'student.id': student.id, - 'result.xsId': result.xsId, - 'student.xm': student.xm, - 'result.xsxm': result.xsxm, - 'result.studentName': result.studentName - }); emit("change", student); emit("update:modelValue", result); - } else { - console.log('❌ 未选择学生'); } // 关闭弹窗 @@ -381,22 +329,12 @@ const handleConfirm = () => { // 加载学生数据 const loadStudentData = async () => { - console.log('🔄 加载学生数据,年级班级:', { - njId: props.njId, - bjId: props.bjId, - njIds: props.njIds, - bjIds: props.bjIds, - autoLoad: props.autoLoad - }); - if (isLoading.value) { - console.log('⏳ 正在加载中,跳过'); return; } // 检查是否有年级班级信息 if (!props.njId && !props.bjId && (!props.njIds || props.njIds.length === 0) && (!props.bjIds || props.bjIds.length === 0)) { - console.log('⚠️ 没有年级班级信息,清空数据'); // 如果没有年级班级信息,清空学生列表并显示占位符 studentList.value = []; studentRange.value = []; @@ -407,7 +345,6 @@ const loadStudentData = async () => { return; } - console.log('🚀 开始加载学生数据'); isLoading.value = true; try { const params: any = {}; @@ -425,32 +362,31 @@ const loadStudentData = async () => { params.bjIds = props.bjIds; } - console.log('📤 发送API请求,参数:', params); const res = await findStudentInfoByNjAndBjApi(params); - console.log('📥 API响应:', res); studentList.value = res.result || []; if (studentList.value.length > 0) { - console.log('✅ 成功加载学生数据,数量:', studentList.value.length); studentRange.value = studentList.value.map((student: any) => student.xm); // 更新过滤列表 filteredStudentList.value = studentList.value; - console.log('📋 学生选项列表:', studentRange.value); - // 如果有默认值,设置默认选择 if (props.defaultValue) { - console.log('🎯 设置默认值:', props.defaultValue); setValueByData(props.defaultValue); + } else if (props.modelValue) { + const modelId = props.modelValue.id || props.modelValue.xsId || props.modelValue; + const index = studentList.value.findIndex((item: any) => item.id === modelId); + if (index >= 0) { + curIndex.value = index; + curStudentLabel.value = studentRange.value[index]; + } } else { - console.log('🎯 不自动选择,等待用户手动选择'); // 不自动选择第一个学生,让用户手动选择 // 不设置 curIndex,保持弹窗打开状态 curStudentLabel.value = ""; } } else { - console.log('❌ 没有加载到学生数据'); studentRange.value = []; filteredStudentList.value = []; curStudentLabel.value = ""; @@ -467,62 +403,41 @@ const loadStudentData = async () => { studentRange.value = []; } finally { isLoading.value = false; - console.log('🏁 loadStudentData 完成'); } }; // 监听 modelValue 变化 -watch(() => props.modelValue, (newVal) => { - if (newVal && newVal.id) { - setValueByData(newVal); +watch(() => props.modelValue, (newVal, oldVal) => { + if (newVal && (newVal.id || newVal.xsId)) { + // 如果学生列表已加载,立即设置回显 + if (studentList.value.length > 0) { + setValueByData(newVal); + } + // 学生列表未加载,等待 loadStudentData 完成后再设置 + } else if (!newVal) { + curStudentLabel.value = ""; } -}, { immediate: true }); +}, { immediate: true, deep: true }); // 监听年级班级变化,自动加载学生数据 watch([() => props.njId, () => props.bjId, () => props.njIds, () => props.bjIds], (newValues, oldValues) => { - console.log('👀 年级班级变化:', { - newValues, - oldValues, - autoLoad: props.autoLoad - }); - if (props.autoLoad) { - console.log('🔄 触发自动加载学生数据'); loadStudentData(); - } else { - console.log('⏸️ autoLoad 为 false,跳过加载'); } }, { immediate: true, deep: true }); // 监听 classInfo 变化,自动加载学生数据 watch(() => props.classInfo, (newClassInfo, oldClassInfo) => { - console.log('👀 classInfo 变化:', { - newClassInfo, - oldClassInfo - }); - if (newClassInfo && newClassInfo.njId && newClassInfo.bjId) { - console.log('🔄 通过 classInfo 加载学生数据'); loadStudentDataByClassInfo(newClassInfo); } else { - console.log('⚠️ classInfo 不完整,清空学生数据'); clearStudentData(); } }, { immediate: true, deep: true }); // 监听 studentData 变化,直接设置学生数据(参考 BasicPicker 的设计模式) watch(() => props.studentData, (newStudentData, oldStudentData) => { - console.log('👀 studentData 变化:', { - newStudentData, - oldStudentData, - newStudentDataLength: newStudentData?.length, - oldStudentDataLength: oldStudentData?.length - }); - if (newStudentData && newStudentData.length > 0) { - console.log('✅ 接收到学生数据,直接设置'); - console.log('📊 学生数据详情:', newStudentData.slice(0, 3)); // 只显示前3个学生 - // 直接设置数据,参考 BasicPicker 的模式 studentList.value = newStudentData; studentRange.value = newStudentData.map((item: any) => item.xm || ''); // 使用正确的字段名 xm @@ -530,11 +445,10 @@ watch(() => props.studentData, (newStudentData, oldStudentData) => { // 更新过滤列表 filteredStudentList.value = studentList.value; - console.log('📋 学生选项列表:', studentRange.value.slice(0, 5)); // 只显示前5个选项 - // 如果有默认值,设置选中项 if (props.modelValue) { - const index = studentList.value.findIndex((item: any) => item.id === props.modelValue); + const modelId = props.modelValue.id || props.modelValue.xsId || props.modelValue; + const index = studentList.value.findIndex((item: any) => item.id === modelId); if (index >= 0) { curIndex.value = index; curStudentLabel.value = studentRange.value[index]; @@ -543,43 +457,17 @@ watch(() => props.studentData, (newStudentData, oldStudentData) => { // 没有默认值时,不设置 curIndex,保持弹窗打开状态 curStudentLabel.value = ""; } - - console.log('🎯 学生选择器状态更新完成:', { - studentListLength: studentList.value.length, - studentRangeLength: studentRange.value.length, - curIndex: curIndex.value, - curStudentLabel: curStudentLabel.value - }); } else { - console.log('⚠️ 学生数据为空,清空数据'); clearStudentData(); } }, { immediate: true, deep: true }); // 监听 range 变化,直接设置学生数据(参考 BasicPicker 的设计模式) watch(() => props.range, (newRange, oldRange) => { - console.log('👀 range 变化:', { - newRange, - oldRange, - newRangeLength: newRange?.length, - oldRangeLength: oldRange?.length - }); - if (newRange && newRange.length > 0) { - console.log('✅ 接收到 range 数据,直接设置'); - // 直接设置数据,参考 BasicPicker 的模式 studentRange.value = newRange; - - console.log('📋 学生选项列表:', studentRange.value.slice(0, 5)); // 只显示前5个选项 - - console.log('🎯 学生选择器状态更新完成:', { - studentRangeLength: studentRange.value.length, - curIndex: curIndex.value, - curStudentLabel: curStudentLabel.value - }); } else { - console.log('⚠️ range 数据为空,清空数据'); clearStudentData(); } }, { immediate: true, deep: true }); @@ -612,49 +500,24 @@ defineExpose({ }); onMounted(() => { - console.log('🚀 组件已挂载,props:', { - njId: props.njId, - bjId: props.bjId, - autoLoad: props.autoLoad, - classInfo: props.classInfo, - studentData: props.studentData, - range: props.range, - studentDataLength: props.studentData?.length, - rangeLength: props.range?.length - }); if (props.autoLoad) { loadStudentData(); } }); - -// 监听 props 变化 -watch(() => [props.njId, props.bjId, props.njIds, props.bjIds], (newValues, oldValues) => { - console.log('🔍 Props 变化监听:', { - newValues, - oldValues, - props: { - njId: props.njId, - bjId: props.bjId, - njIds: props.njIds, - bjIds: props.bjIds - } - }); -}, { immediate: true, deep: true }); + diff --git a/src/pages/statistics/jlb/index.vue b/src/pages/statistics/jlb/index.vue new file mode 100644 index 0000000..373c215 --- /dev/null +++ b/src/pages/statistics/jlb/index.vue @@ -0,0 +1,496 @@ + + + + + diff --git a/src/pages/statistics/jlb/overview.vue b/src/pages/statistics/jlb/overview.vue new file mode 100644 index 0000000..cf63dbf --- /dev/null +++ b/src/pages/statistics/jlb/overview.vue @@ -0,0 +1,968 @@ + + + + + + diff --git a/src/pages/statistics/jlb/routine.vue b/src/pages/statistics/jlb/routine.vue new file mode 100644 index 0000000..be16289 --- /dev/null +++ b/src/pages/statistics/jlb/routine.vue @@ -0,0 +1,509 @@ + + + + + + diff --git a/src/pages/statistics/zb/index.vue b/src/pages/statistics/zb/index.vue new file mode 100644 index 0000000..f3f889f --- /dev/null +++ b/src/pages/statistics/zb/index.vue @@ -0,0 +1,102 @@ + + + + + + diff --git a/src/pages/statistics/zb/overview.vue b/src/pages/statistics/zb/overview.vue new file mode 100644 index 0000000..9999218 --- /dev/null +++ b/src/pages/statistics/zb/overview.vue @@ -0,0 +1,683 @@ + + + + + + diff --git a/src/pages/statistics/zb/pdfPreview.vue b/src/pages/statistics/zb/pdfPreview.vue new file mode 100644 index 0000000..89932b9 --- /dev/null +++ b/src/pages/statistics/zb/pdfPreview.vue @@ -0,0 +1,395 @@ + + + + + + diff --git a/src/pages/statistics/zb/report.vue b/src/pages/statistics/zb/report.vue new file mode 100644 index 0000000..0300f2c --- /dev/null +++ b/src/pages/statistics/zb/report.vue @@ -0,0 +1,1309 @@ + + + + + + diff --git a/src/pages/view/analysis/jl/statistics.vue b/src/pages/view/analysis/jl/statistics.vue index e831797..9deaf01 100644 --- a/src/pages/view/analysis/jl/statistics.vue +++ b/src/pages/view/analysis/jl/statistics.vue @@ -78,9 +78,71 @@ - - 接龙详情 - + + + + + + + + + {{ jlDetail.jlmc }} + + + + 接龙类型: + {{ jlDetail.jlType === 'select' ? '选择题接龙' : '普通接龙' }} + + + 发布人: + {{ jlDetail.jsxm }} + + + 开始时间: + {{ jlDetail.jlkstime }} + + + 结束时间: + {{ jlDetail.jljstime }} + + + 是否签名: + {{ jlDetail.mdqz === '1' ? '启用' : '不启用' }} + + + + + + + 接龙描述 + + + + + + 选项配置 + + + {{ option.key }}. + {{ option.value }} + + + + + + + 回执说明 + {{ jlDetail.mdhz }} + + + + + 附件 + + + {{ getFileName(jlDetail.jlfj) }} + + @@ -89,7 +151,8 @@ @@ -405,6 +550,132 @@ onLoad((options) => { &.danger { color: #ff4d4f; } + + &.warning { + color: #faad14; + } +} + +/* 接龙详情样式 */ +.details-card { + .detail-cover { + width: 100%; + margin-bottom: 16px; + + .cover-image { + width: 100%; + height: 200px; + border-radius: 8px; + display: block; + } + } + + .detail-section { + margin-bottom: 20px; + padding-bottom: 16px; + border-bottom: 1px solid #f0f0f0; + + &:last-child { + border-bottom: none; + margin-bottom: 0; + } + } + + .detail-title { + display: block; + font-size: 18px; + font-weight: bold; + color: #333; + margin-bottom: 12px; + line-height: 1.5; + } + + .detail-meta { + .meta-row { + display: flex; + margin-bottom: 8px; + line-height: 1.6; + + .meta-label { + font-size: 14px; + color: #666; + width: 80px; + flex-shrink: 0; + } + + .meta-value { + font-size: 14px; + color: #333; + flex: 1; + } + } + } + + .section-title { + display: block; + font-size: 15px; + font-weight: 600; + color: #333; + margin-bottom: 12px; + } + + .rich-content { + font-size: 14px; + color: #666; + line-height: 1.6; + } + + .section-content { + display: block; + font-size: 14px; + color: #666; + line-height: 1.6; + } + + .options-list { + .option-item-detail { + display: flex; + padding: 12px; + margin-bottom: 8px; + background-color: #f8f9fa; + border: 1px solid #e9ecef; + border-radius: 6px; + + .option-key { + font-size: 15px; + font-weight: bold; + color: #1890ff; + margin-right: 8px; + flex-shrink: 0; + } + + .option-value { + font-size: 14px; + color: #333; + flex: 1; + line-height: 1.6; + } + } + } + + .attachment-item { + display: flex; + align-items: center; + padding: 12px; + background-color: #f8f9fa; + border-radius: 6px; + cursor: pointer; + + .attachment-name { + font-size: 14px; + color: #1890ff; + margin-left: 8px; + } + + &:active { + background-color: #e6f7ff; + } + } } diff --git a/src/pages/view/notice/publish.vue b/src/pages/view/notice/publish.vue index 25e6891..1ca0247 100644 --- a/src/pages/view/notice/publish.vue +++ b/src/pages/view/notice/publish.vue @@ -115,12 +115,26 @@ + + + 接龙类型 + + {{ jlTypeText }} + + + + + - + 按名单签字 {{ signatureStatusText }} @@ -130,6 +144,48 @@ + + + + + 选项配置 + + + + + 暂无选项,请点击"添加选项" + + + + + + {{ option.key }}. + 序号: {{ option.sort }} + + + + + + + + @@ -281,6 +337,15 @@ interface FormData { startTime: string; endTime: string; mdhz: string; // 回执说明 + jlType: string; // 接龙类型 + jlOptions: string; // 选项配置JSON +} + +// 选项类型 +interface JlOption { + key: string; + value: string; + sort: number; } const noticeId = ref(null); @@ -306,13 +371,24 @@ const formData = reactive({ startTime: "", endTime: "", mdhz: "", // 新增回执说明字段 + jlType: "normal", // 接龙类型,默认为普通接龙 + jlOptions: "", // 选项配置JSON }); +// 选项列表 +const optionsList = ref([]); + const signatureOptions = ["启用" , "不启用"]; const signatureStatusText = computed(() => { return formData.signatureRequired ? "启用" : "不启用"; }); +// 接龙类型选项 +const jlTypeOptions = ["普通接龙", "选择题接龙"]; +const jlTypeText = computed(() => { + return formData.jlType === 'select' ? "选择题接龙" : "普通接龙"; +}); + // 树形数据 const treeData = ref([]); const treeRef = ref(); @@ -402,8 +478,13 @@ const resetForm = () => { startTime: "", endTime: "", mdhz: "", // 重置回执说明 + jlType: "normal", // 重置接龙类型 + jlOptions: "", // 重置选项配置 }); + // 重置选项列表 + optionsList.value = []; + // 重置发布状态 publishedJlId.value = null; isPublishing.value = false; @@ -444,6 +525,19 @@ const loadJlData = async (jlId: string) => { formData.endTime = jlData.jljstime || ""; formData.signatureRequired = jlData.mdqz === "1"; formData.mdhz = jlData.mdhz || ""; // 加载回执说明 + formData.jlType = jlData.jlType || "normal"; // 加载接龙类型 + formData.jlOptions = jlData.jlOptions || ""; // 加载选项配置 + + // 解析选项配置 + if (formData.jlType === 'select' && formData.jlOptions) { + try { + optionsList.value = JSON.parse(formData.jlOptions); + optionsList.value.sort((a, b) => (a.sort || 0) - (b.sort || 0)); + } catch (e) { + console.error('解析选项配置失败:', e); + optionsList.value = []; + } + } // 处理附件 if (jlData.jlfj) { @@ -802,6 +896,18 @@ const removeStudent = (index: number) => { uni.showToast({ title: "已移除学生", icon: "success" }); }; +// 接龙类型切换 +const handleJlTypeChange = (e: any) => { + const index = e.detail.value; + formData.jlType = index === 0 ? "normal" : "select"; + + // 切换到普通接龙时,清空选项 + if (formData.jlType === 'normal') { + optionsList.value = []; + formData.jlOptions = ""; + } +}; + const handleSignatureChange = (e: any) => { const index = e.detail.value; formData.signatureRequired = index == 0; // 修正:索引0是"启用",索引1是"不启用" @@ -816,6 +922,37 @@ const handleSignatureChange = (e: any) => { } }; +// 添加选项 +const addOption = () => { + const newKey = String.fromCharCode(65 + optionsList.value.length); // A, B, C... + optionsList.value.push({ + key: newKey, + value: '', + sort: optionsList.value.length + 1 + }); + updateOptionsJson(); +}; + +// 删除选项 +const removeOption = (index: number) => { + optionsList.value.splice(index, 1); + // 重新生成选项标识和排序 + optionsList.value.forEach((option, idx) => { + option.key = String.fromCharCode(65 + idx); + option.sort = idx + 1; + }); + updateOptionsJson(); +}; + +// 更新JSON字段 +const updateOptionsJson = () => { + if (optionsList.value.length > 0) { + formData.jlOptions = JSON.stringify(optionsList.value); + } else { + formData.jlOptions = ""; + } +}; + const validateForm = () => { // 标题校验 if (!formData.title || !formData.title.trim()) { @@ -832,6 +969,20 @@ const validateForm = () => { uni.showToast({ title: "请选择年级与班级", icon: "none" }); return false; } + // 选择题接龙必须配置选项 + if (formData.jlType === 'select') { + if (optionsList.value.length === 0) { + uni.showToast({ title: "选择题接龙至少需要添加一个选项", icon: "none" }); + return false; + } + // 检查选项内容是否为空 + for (let i = 0; i < optionsList.value.length; i++) { + if (!optionsList.value[i].value.trim()) { + uni.showToast({ title: `选项${optionsList.value[i].key}的内容不能为空`, icon: "none" }); + return false; + } + } + } // 开始时间不能为空 if (!formData.startTime) { uni.showToast({ title: "请选择开始时间", icon: "none" }); @@ -893,6 +1044,12 @@ const buildJlDto = (status: string) => { console.log("targetNjmcIds.join(','):", formData.targetNjmcIds.join(",")); console.log("=========================="); + // 处理选项配置 + let jlOptions = ""; + if (formData.jlType === 'select' && optionsList.value.length > 0) { + jlOptions = JSON.stringify(optionsList.value); + } + return { id: formData.id || "", // 接龙ID,新增时为空 jlmc: formData.title.trim(), // 接龙名称 @@ -903,6 +1060,8 @@ const buildJlDto = (status: string) => { jljstime: formatDate(formData.endTime), // 接龙结束时间,格式化为 yyyy-MM-dd HH:mm:ss mdqz: formData.signatureRequired ? "1" : "0", // 按名单签字:1启用,0不启用 mdhz: formData.mdhz || "", // 回执说明 + jlType: formData.jlType, // 接龙类型 + jlOptions: jlOptions, // 选项配置JSON njId: formData.targetNjIds.join(","), // 关联年级ID列表 njmcId: formData.targetNjmcIds.join(","), // 关联年级名称ID列表 bjId: formData.targetBjIds.join(","), // 关联班级ID列表 @@ -1657,4 +1816,109 @@ watch(() => formData.title, (newTitle) => { } } } + +/* 选项配置区域 */ +.options-config-section { + padding-top: 15px; + padding-bottom: 10px; + border-bottom: none !important; + + .options-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 15px; + + .form-label { + color: #333; + font-size: 15px; + font-weight: 500; + } + + .add-option-btn { + display: flex; + align-items: center; + gap: 4px; + padding: 4px 12px; + height: 28px; + line-height: 20px; + background-color: #ecf5ff; + color: #409eff; + border: 1px solid #b3d8ff; + border-radius: 14px; + font-size: 13px; + + &::after { + border: none; + } + + text { + line-height: 20px; + } + + &:active { + background-color: #d9ecff; + } + } + } + + .empty-options { + text-align: center; + padding: 30px 0; + color: #909399; + font-size: 14px; + } + + .option-item-mobile { + background-color: #f8f9fa; + border: 1px solid #e9ecef; + border-radius: 8px; + padding: 12px; + margin-bottom: 10px; + + .option-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 8px; + + .option-key-sort { + display: flex; + align-items: center; + gap: 10px; + + .option-key-label { + font-size: 16px; + font-weight: bold; + color: #409eff; + } + + .option-sort-label { + font-size: 12px; + color: #909399; + } + } + + .delete-icon { + cursor: pointer; + padding: 4px; + } + } + + .option-input { + margin-top: 5px; + } + + .option-input ::v-deep .uni-easyinput__content-textarea { + font-size: 14px !important; + color: #303133 !important; + padding: 8px !important; + background-color: #ffffff; + border: 1px solid #dcdfe6; + border-radius: 4px; + line-height: 1.5; + min-height: 60px; + } + } +} diff --git a/src/pages/view/quantitativeAssessment/assessment/assessment.vue b/src/pages/view/quantitativeAssessment/assessment/assessment.vue index acede9b..4560fb0 100644 --- a/src/pages/view/quantitativeAssessment/assessment/assessment.vue +++ b/src/pages/view/quantitativeAssessment/assessment/assessment.vue @@ -152,6 +152,7 @@ const loadTreeData = async () => { key: item.key, title: item.title, njmcId: item.njmcId, + bc: item.bc, children: item.children ? convertTreeData(item.children) : [], })); }; @@ -176,12 +177,33 @@ const onTreeConfirm = (selectedItems: any[]) => { // 如果选择的是班级(有parents表示是班级) if (selectedItem.parents && selectedItem.parents.length > 0) { - const parent = selectedItem.parents[0]; // 年级信息 - const nj = parent; // 年级信息 - const bj = selectedItem; // 班级信息 + const parent = selectedItem.parents[0]; // 年级信息(只包含key和title) - curNj.value = nj; - curBj.value = bj; + // 从 treeData 中查找完整的年级数据 + const fullNj = treeData.value.find((item: any) => item.key === parent.key); + + if (fullNj) { + curNj.value = { + key: fullNj.key, + title: fullNj.title, + njmcId: fullNj.njmcId || '' // 从完整数据中获取年级名称ID + }; + curBj.value = { + key: selectedItem.key, + title: selectedItem.title, + bc: `${fullNj.title}${selectedItem.title}` // 组合年级和班级名称,如"一年级3班" + }; + + console.log('选择班级信息:', { + curNj: curNj.value, + curBj: curBj.value + }); + } else { + uni.showToast({ + title: '获取年级信息失败', + icon: 'none' + }); + } } else { // 如果选择的是年级,清空班级选择 curNj.value = selectedItem; @@ -338,12 +360,23 @@ async function submit() { return; } + const submitData = { + itemList: itemList, + bjId: curBj.value.key, + njId: curNj.value.key, + njmcId: curNj.value.njmcId || '', + bc: curBj.value.bc || curBj.value.title || '' + }; + + console.log('提交数据:', submitData); + try { - await evaluationSaveApi({ - itemList: itemList, - bjId: curBj.value.key - }); + await evaluationSaveApi(submitData); showToast({title: "操作成功"}); + + // 触发量化考核列表刷新事件 + uni.$emit('refreshEvaluationList'); + // 重置选择 curNj.value = null; curBj.value = null; diff --git a/src/pages/view/quantitativeAssessment/casualShot/casualShot.vue b/src/pages/view/quantitativeAssessment/casualShot/casualShot.vue index d4a39fb..ba719a1 100644 --- a/src/pages/view/quantitativeAssessment/casualShot/casualShot.vue +++ b/src/pages/view/quantitativeAssessment/casualShot/casualShot.vue @@ -2,14 +2,14 @@ - + 用途 @@ -20,27 +20,25 @@ - + 年级班级 - + {{ classText || "请选择年级班级" }} - + - + 学生 - - - {{ form.studentName || '未选择' }} + + @@ -51,20 +49,19 @@ v-model="form.content" class="textarea" placeholder="请输入表扬内容" - :disabled="isViewMode" :maxlength="500" > - + 附件类型 @@ -84,13 +81,12 @@ :maxVideoCount="1" v-model:imageList="imageList" v-model:videoList="videoList" - :disabled="isViewMode" /> @@ -125,6 +121,7 @@ const { getData } = useDataStore(); // 表单数据 const form = ref({ + id: '', // 用于判断是新增还是修改 purpose: '表扬栏', content: '', scfj: '照片', @@ -151,9 +148,6 @@ const videoList = ref([]); const treeData = ref([]); const treeRef = ref(); -// 是否查看模式 -const isViewMode = ref(false); - // 选项配置 const purposeOptions = [ { value: '表扬栏', text: '表扬栏' }, @@ -246,16 +240,15 @@ const changeFileType = (type: string) => { form.value.scfj = type; }; -// 初始化表单数据(查看模式) +// 初始化表单数据(编辑模式回显) const initFormData = () => { - if (!getData._show) { - isViewMode.value = false; + if (!getData || !getData.id) { + // 没有数据,新增模式 return; } - isViewMode.value = true; - - // 基本信息 + // 有数据,编辑模式,回显数据 + form.value.id = getData.id || ''; form.value.purpose = getData.purpose || '表扬栏'; form.value.content = getData.content || ''; form.value.scfj = getData.scfj || '照片'; @@ -343,6 +336,11 @@ const handleSubmit = async () => { pic: fileUrls.join(',') }; + // 如果有 id,表示是修改操作,添加 id 到提交数据 + if (form.value.id) { + submitData.id = form.value.id; + } + // 添加班级信息(可选) if (classInfo.value.njId) { submitData.njId = classInfo.value.njId; @@ -359,7 +357,11 @@ const handleSubmit = async () => { } await readyToGoSaveApi(submitData); - showToast({ title: '操作成功' }); + showToast({ title: form.value.id ? '修改成功' : '新增成功' }); + + // 触发事件通知首页刷新随手拍列表 + uni.$emit('refreshSspList'); + navigateBack({ delta: 1 }); } catch (error) { showToast({ title: '提交失败', icon: 'error' }); @@ -383,6 +385,24 @@ onMounted(() => { padding: 30rpx; border-radius: 16rpx; box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04); + + &.form-item-row { + display: flex; + align-items: center; + gap: 24rpx; + + .label { + margin-bottom: 0; + flex-shrink: 0; + min-width: 120rpx; + } + + .selector, + .picker-wrapper, + .radio-group { + flex: 1; + } + } } .label { @@ -451,7 +471,6 @@ onMounted(() => { text { font-size: 28rpx; color: #333; - flex: 1; &.placeholder { color: #999; diff --git a/src/pages/view/quantitativeAssessment/index/details.vue b/src/pages/view/quantitativeAssessment/index/details.vue index 68942b8..8aff519 100644 --- a/src/pages/view/quantitativeAssessment/index/details.vue +++ b/src/pages/view/quantitativeAssessment/index/details.vue @@ -1,25 +1,47 @@ @@ -101,7 +104,7 @@ function getGradeName(citem: any) { // 获取检查项基础分:baseScore * 5 function getBaseScore(ditem: any) { const inspectItem = head.value.find(item => item.id === ditem.id); - if (inspectItem && inspectItem.baseScore) { + if (inspectItem && typeof inspectItem.baseScore === 'number') { return inspectItem.baseScore * 5; } return 0; @@ -112,11 +115,13 @@ function calculateItemScore(bitem: any, ditem: any) { if (bitem.itemScoreMap && bitem.itemScoreMap[ditem.id]) { // 找到对应的检查项获取baseScore const inspectItem = head.value.find(item => item.id === ditem.id); - if (inspectItem && inspectItem.baseScore) { + + if (inspectItem && typeof inspectItem.baseScore === 'number') { const baseScore = inspectItem.baseScore * 5; // 基础分 const deduction = bitem.itemScoreMap[ditem.id]; // 扣分项(负数) + const finalScore = baseScore + deduction; // 得分 = baseScore * 5 - 扣分项 - return baseScore + deduction; // deduction是负数,所以用加法 + return finalScore; // deduction是负数,所以用加法 } } return 0; @@ -128,7 +133,7 @@ function calculateTotalScore(bitem: any) { // 遍历所有检查项(从head中获取) head.value.forEach(item => { - if (item.id && item.baseScore) { + if (item.id && typeof item.baseScore === 'number') { const baseScore = item.baseScore * 5; // 基础分 let deduction = 0; // 扣分项 @@ -469,4 +474,50 @@ getWeekData() justify-content: center; align-items: center; } + +/* 加载遮罩层 */ +.loading-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.5); + display: flex; + justify-content: center; + align-items: center; + z-index: 9999; +} + +.loading-content { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + background-color: #fff; + padding: 60rpx; + border-radius: 20rpx; + box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.2); +} + +.loading-spinner { + width: 80rpx; + height: 80rpx; + border: 6rpx solid #f3f3f3; + border-top: 6rpx solid #4F46E5; + border-radius: 50%; + animation: spin 1s linear infinite; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +.loading-text { + margin-top: 30rpx; + color: #333; + font-size: 28rpx; + font-weight: 500; +} diff --git a/src/pages/view/routine/jc/components/completedList.vue b/src/pages/view/routine/jc/components/completedList.vue new file mode 100644 index 0000000..f0100fc --- /dev/null +++ b/src/pages/view/routine/jc/components/completedList.vue @@ -0,0 +1,416 @@ + + + + + + diff --git a/src/pages/view/routine/jc/components/pendingList.vue b/src/pages/view/routine/jc/components/pendingList.vue new file mode 100644 index 0000000..730a42c --- /dev/null +++ b/src/pages/view/routine/jc/components/pendingList.vue @@ -0,0 +1,384 @@ + + + + + + diff --git a/src/pages/view/routine/jc/components/dm.vue b/src/pages/view/routine/jc/dm.vue similarity index 74% rename from src/pages/view/routine/jc/components/dm.vue rename to src/pages/view/routine/jc/dm.vue index 973dc63..a40a7e3 100644 --- a/src/pages/view/routine/jc/components/dm.vue +++ b/src/pages/view/routine/jc/dm.vue @@ -1,16 +1,15 @@