diff --git a/src/api/base/server.ts b/src/api/base/server.ts index d2a148a..31fa1ac 100644 --- a/src/api/base/server.ts +++ b/src/api/base/server.ts @@ -1,84 +1,91 @@ // 参数接口 // 响应接口 -import {get, post} from "@/utils/request"; +import { get, post } from "@/utils/request"; /** * 获取服务器时间 */ export const xqgwFindAllApi = async () => { - return await get("/api/xqgw/findAll"); + return await get("/api/xqgw/findAll"); }; export const xqxjFindAllApi = async () => { - return await get("/api/xqxj/findAll"); + return await get("/api/xqxj/findAll"); }; export const findAllNjBjTreeApi = async () => { - return await get("/api/nj/findAllNjBjTree"); + return await get("/api/nj/findAllNjBjTree"); }; export const kmFindAllApi = async () => { - return await get("/api/km/findAll"); + return await get("/api/km/findAll"); }; export const findAllXxXqNjTree = async () => { - return await get("/api/nj/findAllXxXqNjTree"); + return await get("/api/nj/findAllXxXqNjTree"); }; export const findAllNjBjTree = async () => { - return await get("/api/nj/findAllNjBjTree"); + return await get("/api/nj/findAllNjBjTree"); }; export const jsConfirmJsDataApi = async (params: any) => { - return await post("/api/js/confirmJsData", params); + return await post("/api/js/confirmJsData", params); }; export const jsdFindPageTaskApi = async (params: any) => { - return await get("/api/jsd/findPageTask", params); + return await get("/api/jsd/findPageTask", params); }; export const rwflFindRwlxsByRwId = async (params: any) => { - return await get("/api/rwlx/findRwlxsByRwId", params); -} + return await get("/api/rwlx/findRwlxsByRwId", params); +}; export const rwzxSaveApi = async (params: any) => { - return await post("/api/rwzx/save", params); + return await post("/api/rwzx/save", params); }; export const rwzxExecutedInfoByRwIdAndJsApi = async (params: any) => { - return await get("/api/rwzx/executedInfoByRwIdAndJs", params); + return await get("/api/rwzx/executedInfoByRwIdAndJs", params); }; - export const rwFindInfoByRwId = async (params: any) => { - return await get("/api/rw/findInfoByRwId", params); -} + return await get("/api/rw/findInfoByRwId", params); +}; export const fractionRuleApi = async () => { - return await get( - "/api/fractionRule/findAllByItemId?itemId=CDFDED2A704F46E2A4D7E8816968BD23" - ); + return await get( + "/api/fractionRule/findAllByItemId?itemId=CDFDED2A704F46E2A4D7E8816968BD23" + ); }; export const fractionRuleApi1 = async () => { - return await get( - "/api/fractionRule/findAllByItemId?itemId=B96A0FA22C414F71A3E1CDCA7E206B10" - ); + return await get( + "/api/fractionRule/findAllByItemId?itemId=B96A0FA22C414F71A3E1CDCA7E206B10" + ); }; // 查询教师信息 export const jsdfindJsByPhoneApi = async (params: any) => { - return await get("/api/js/findJsByPhone", params); + return await get("/api/js/findJsByPhone", params); }; // 选课列表 export const jsdXkListApi = async (params: any) => { - return await get("/mobile/js/xk/list", params); + return await get("/mobile/js/xk/list", params); }; // 选课列表 export const jsdXkkcSaveApi = async (params: any) => { - return await post("/api/xkkc/save", params); + return await post("/api/xkkc/save", params); }; // 选课学生列表 export const jsdXkXsListApi = async (params: any) => { - return await get("/mobile/js/xkxs/list", params); + return await get("/mobile/js/xkxs/list", params); +}; +export const mobilejlstudentListApi = async (params: any) => { + return await get("/mobile/jl/studentList", params); +}; + +export const mobilejllistApi = async (params: any) => { + const res = await get("/mobile/jl/list", params); + return res.result; }; // 提交点名信息 export const jsdXkdmListApi = async (params: any) => { - return await post("/mobile/js/xkdm/add", params); + return await post("/mobile/js/xkdm/add", params); }; // 获取待办列表 diff --git a/src/config.ts b/src/config.ts index f919987..bf5bbad 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,4 +1,5 @@ -const ip: string = "127.0.0.1:8897"; +// const ip: string = "192.168.239.1:8897"; +const ip: string = "yufangzc.com"; // const ip: string = "yufangzc.com"; const fwqip: string = "yufangzc.com"; //打包服务器接口代理标识 diff --git a/src/pages.json b/src/pages.json index 640bd24..4f18545 100644 --- a/src/pages.json +++ b/src/pages.json @@ -359,21 +359,21 @@ { "path": "pages/view/notice/index", "style": { - "navigationBarTitleText": "通知公告", + "navigationBarTitleText": "发布接龙", "enablePullDownRefresh": false } }, { "path": "pages/view/notice/detail", "style": { - "navigationBarTitleText": "通知详情", + "navigationBarTitleText": "接龙详情", "enablePullDownRefresh": false } }, { "path": "pages/view/notice/publish", "style": { - "navigationBarTitleText": "发布通知", + "navigationBarTitleText": "接龙推送", "enablePullDownRefresh": false } }, diff --git a/src/pages/base/service/index.vue b/src/pages/base/service/index.vue index 3f92ea2..1b830fd 100644 --- a/src/pages/base/service/index.vue +++ b/src/pages/base/service/index.vue @@ -206,7 +206,7 @@ const sections = reactive([ { id: "r7", icon: "file-text-fill-2", - text: "选课详情", + text: "课程介绍", show: true, path: "/pages/base/groupTeaching/xkList", }, @@ -218,6 +218,13 @@ const sections = reactive([ show: true, path: "/pages/base/groupTeaching/dmXkList", }, + { + id: "r8", + icon: "draftfill", + text: "发布接龙", + show: true, + path: "/pages/view/notice/index", + }, ], }, { diff --git a/src/pages/view/hr/teacherProfile/PositionInfo.vue b/src/pages/view/hr/teacherProfile/PositionInfo.vue index 549095a..ac7e5cb 100644 --- a/src/pages/view/hr/teacherProfile/PositionInfo.vue +++ b/src/pages/view/hr/teacherProfile/PositionInfo.vue @@ -226,29 +226,6 @@ if (getFile.rgqkList && getFile.rgqkList.length > 0) { }); } -// 手动触发计算所有项目的任岗年限 -const calculateAllPositionYears = () => { - education.xl.forEach((item: any, index: number) => { - if (item.value.gwrzkstime) { - const years = calculatePositionYears( - item.value.gwrzkstime, - item.value.gwrzjstime - ); - item.value.gwrznx = years; - console.log(`表单项${index}计算结果:`, { - gwrzkstime: item.value.gwrzkstime, - gwrzjstime: item.value.gwrzjstime, - gwrznx: years, - 是否为0: years === "0", - }); - } else { - // 没有开始时间时,清空任岗年限 - item.value.gwrznx = ""; - } - }); - forceUpdateKey.value++; -}; - function addEducation() { education.xl.push({ value: {} }); // 强制重新渲染 diff --git a/src/pages/view/notice/index.vue b/src/pages/view/notice/index.vue index 40e1574..0a1c254 100644 --- a/src/pages/view/notice/index.vue +++ b/src/pages/view/notice/index.vue @@ -1,120 +1,81 @@ @@ -183,6 +220,10 @@ import { ref, reactive, computed } from "vue"; import { onLoad } from "@dcloudio/uni-app"; import CustomUpload from "/src/components/BasicUpload/CustomUpload.vue"; +import BasicTree from "@/components/BasicTree/Tree.vue"; +import { attachmentUpload } from "@/api/system/upload"; +import { imagUrl } from "@/utils"; +import { findAllNjBjTree, mobilejlstudentListApi } from "@/api/base/server"; interface Attachment { name: string; @@ -200,6 +241,8 @@ interface FormData { targetClass: string; targetNames: string[]; targetStudentIds: string[]; + targetNjIds: string[]; // 年级ID数组 + targetBjIds: string[]; // 班级ID数组 signatureRequired: boolean; startTime: string; endTime: string; @@ -215,6 +258,8 @@ const formData = reactive({ targetClass: "", targetNames: [], targetStudentIds: [], + targetNjIds: [], + targetBjIds: [], signatureRequired: false, startTime: "", endTime: "", @@ -225,38 +270,40 @@ const signatureStatusText = computed(() => { return formData.signatureRequired ? "启用" : "不启用"; }); -const classList = ref([ - { id: "g1c1", name: "一年级1班" }, - { id: "g1c2", name: "一年级2班" }, - { id: "g1c3", name: "一年级3班" }, - { id: "g1c4", name: "一年级4班" }, - { id: "g1c5", name: "一年级5班" }, - { id: "g2c1", name: "二年级1班" }, - { id: "g2c2", name: "二年级2班" }, - { id: "g2c3", name: "二年级3班" }, - { id: "g3c1", name: "三年级1班" }, - { id: "g3c2", name: "三年级2班" }, - { id: "g3c3", name: "三年级3班" }, - { id: "g3c4", name: "三年级4班" }, - { id: "g4c1", name: "四年级1班" }, - { id: "g4c2", name: "四年级2班" }, - { id: "g5c1", name: "五年级1班" }, - { id: "g5c2", name: "五年级2班" }, - { id: "g5c3", name: "五年级3班" }, - { id: "g6c1", name: "六年级1班" }, - { id: "g6c2", name: "六年级2班" }, -]); +// 树形数据 +const treeData = ref([]); +const treeRef = ref(); -const combinedClassRange = computed(() => { - return classList.value.map((cls) => cls.name); +// 学生显示相关 +const maxDisplayCount = 24; // 最多显示24个学生(4行×6列) +const showStudentModal = ref(false); + +// 计算显示的学生名单(最多显示前24个) +const displayNames = computed(() => { + return formData.targetNames.slice(0, maxDisplayCount); }); -const selectedClassIndex = computed(() => { - const index = classList.value.findIndex( - (cls) => cls.name === formData.targetClass - ); - return index >= 0 ? index : 0; -}); +// 加载树形数据 +const loadTreeData = async () => { + try { + const res = await findAllNjBjTree(); + if (res.resultCode === 1 && res.result) { + // 转换数据格式以适配 BasicTree 组件 + treeData.value = res.result.map((item: any) => ({ + key: item.key, + title: item.title, + children: item.children || [], + })); + console.log("树形数据加载成功:", treeData.value); + } + } catch (error) { + console.error("加载树形数据失败:", error); + uni.showToast({ title: "加载班级数据失败", icon: "error" }); + } +}; + +// 在组件挂载时加载数据 +loadTreeData(); const fetchStudentsByClass = async (className: string): Promise => { console.log(`模拟获取班级 [${className}] 的学生列表...`); @@ -281,40 +328,42 @@ const fetchStudentsByClass = async (className: string): Promise => { return mockStudents; }; -onLoad((options) => { - if (options && options.id) { - noticeId.value = options.id; - uni.setNavigationBarTitle({ title: "编辑通知" }); - formData.title = "关于五一放假的通知 (编辑)"; - formData.content = "根据校历安排,现将2024年五一劳动节放假安排通知如下..."; - formData.targetClass = "二年级1班"; - formData.targetNames = ["张三", "李四"]; - formData.targetStudentIds = ["s201-mock", "s202-mock"]; - formData.signatureRequired = true; - formData.startTime = "2024-04-30 18:00:00"; - formData.endTime = "2024-05-05 23:59:59"; - if (formData.targetClass && noticeId.value) { - fetchStudentsByClass(formData.targetClass).then((students) => { - formData.targetNames = students; - }); - } - } else { - uni.setNavigationBarTitle({ title: "发布通知" }); - } -}); +onLoad((options) => {}); -const handleCoverSelected = (e: any) => { - console.log("选择封面 (CustomUpload):", e); +const handleCoverSelected = async (e: any) => { if (e.tempFilePaths && e.tempFilePaths.length > 0) { - formData.coverImage = e.tempFilePaths[0]; - console.log("封面临时路径:", formData.coverImage); + const tempFilePath = e.tempFilePaths[0]; + + try { + uni.showLoading({ title: "上传中..." }); + + // 直接使用 tempFilePath 作为 Blob 传给接口 + const uploadResult: any = await attachmentUpload(tempFilePath as any); + + if ( + uploadResult.resultCode === 1 && + uploadResult.result && + uploadResult.result.length > 0 + ) { + // 保存原始的 filePath(用于提交到服务器) + const originalPath = uploadResult.result[0].filePath; + formData.coverImage = originalPath; + uni.showToast({ title: "封面上传成功", icon: "success" }); + } else { + throw new Error("上传响应格式异常"); + } + } catch (error) { + uni.showToast({ title: "封面上传失败", icon: "error" }); + formData.coverImage = null; + } finally { + uni.hideLoading(); + } } else { console.error("无法从选择事件中获取封面路径:", e); } }; const handleCoverClosed = (field: string) => { - console.log(`删除封面 (CustomUpload): field=${field}`); if (field === "coverImage") { formData.coverImage = null; } @@ -324,47 +373,74 @@ const addAttachment = () => { uni.chooseFile({ count: 5, type: "all", - success: (res) => { + success: async (res) => { const tempFiles = res.tempFiles; if (Array.isArray(tempFiles) && tempFiles.length > 0) { - tempFiles.forEach((file: any) => { - let fileType = "file"; - const fileName = file.name || ""; - const fileExtension = fileName.split(".").pop()?.toLowerCase(); + uni.showLoading({ title: "上传中..." }); - if ( - ["png", "jpg", "jpeg", "gif", "bmp", "webp"].includes( - fileExtension || "" - ) - ) { - fileType = "image"; - } else if ( - ["mp4", "mov", "avi", "wmv", "flv"].includes(fileExtension || "") - ) { - fileType = "video"; - } else if ( - ["mp3", "wav", "aac", "ogg"].includes(fileExtension || "") - ) { - fileType = "audio"; + try { + for (const file of tempFiles) { + const fileInfo = file as any; // 强制类型转换避免类型检查错误 + let fileType = "file"; + const fileName = fileInfo.name || ""; + const fileExtension = fileName.split(".").pop()?.toLowerCase(); + + if ( + ["png", "jpg", "jpeg", "gif", "bmp", "webp"].includes( + fileExtension || "" + ) + ) { + fileType = "image"; + } else if ( + ["mp4", "mov", "avi", "wmv", "flv"].includes(fileExtension || "") + ) { + fileType = "video"; + } else if ( + ["mp3", "wav", "aac", "ogg"].includes(fileExtension || "") + ) { + fileType = "audio"; + } + + if ( + fileInfo.type && + typeof fileInfo.type === "string" && + (fileInfo.type.startsWith("image/") || + fileInfo.type.startsWith("video/") || + fileInfo.type.startsWith("audio/")) + ) { + fileType = fileInfo.type.split("/")[0]; + } + + // 直接使用文件路径作为 Blob 传给接口 + const uploadResult: any = await attachmentUpload( + fileInfo.path as any + ); + + if ( + uploadResult.resultCode === 1 && + uploadResult.result && + uploadResult.result.length > 0 + ) { + // 保存原始的 filePath(用于提交到服务器) + const originalPath = uploadResult.result[0].filePath; + formData.attachments.push({ + name: fileName, + type: fileType, + url: originalPath, // 保存原始路径 + size: fileInfo.size, + }); + } else { + uni.showToast({ title: `${fileName} 上传失败`, icon: "error" }); + } } - if ( - file.type && - typeof file.type === "string" && - (file.type.startsWith("image/") || - file.type.startsWith("video/") || - file.type.startsWith("audio/")) - ) { - fileType = file.type.split("/")[0]; - } - - formData.attachments.push({ - name: fileName, - type: fileType, - url: file.path, - size: file.size, - }); - }); + uni.showToast({ title: "附件上传完成", icon: "success" }); + } catch (error) { + console.error("附件上传失败:", error); + uni.showToast({ title: "附件上传失败", icon: "error" }); + } finally { + uni.hideLoading(); + } } else { console.log("未选择任何文件或返回结果异常,或 tempFiles 不是数组"); } @@ -391,38 +467,124 @@ const getAttachmentIcon = (type: string): string => { const previewAttachment = (attachment: Attachment) => { console.log("预览附件:", attachment); - uni.showToast({ title: `预览 ${attachment.name} 功能待实现`, icon: "none" }); + // 如果是图片类型,可以预览 + if (attachment.type === "image") { + const fullUrl = imagUrl(attachment.url); + uni.previewImage({ + urls: [fullUrl], + current: fullUrl, + }); + } else { + uni.showToast({ + title: `预览 ${attachment.name} 功能待实现`, + icon: "none", + }); + } }; -const onClassPickerChange = async (e: any) => { - const index = e.detail.value; - const selectedClass = classList.value[index]; - if (selectedClass && selectedClass.name !== formData.targetClass) { - formData.targetClass = selectedClass.name; +// 显示班级选择树 +const showClassTree = () => { + if (treeRef.value) { + treeRef.value._show(); + } +}; + +// 树形选择确认 +const onTreeConfirm = async (selectedItems: any[]) => { + console.log("选择的班级:", selectedItems); + if (selectedItems.length > 0) { + // 处理多选情况 + const classNames = selectedItems.map((item) => item.title); + formData.targetClass = classNames.join(", "); formData.targetNames = []; formData.targetStudentIds = []; + formData.targetNjIds = []; + formData.targetBjIds = []; + try { - const students = await fetchStudentsByClass(formData.targetClass); - formData.targetNames = students; + uni.showLoading({ title: "获取学生列表中..." }); + + // 提取年级ID和班级ID + const njIds: string[] = []; + const bjIds: string[] = []; + + selectedItems.forEach((item) => { + // 如果选择的是班级(有parents表示是班级) + if (item.parents && item.parents.length > 0) { + const njId = item.parents[0].key; // 年级ID:parents[0].key + const bjId = item.key; // 班级ID:item.key + njIds.push(njId); + bjIds.push(bjId); + console.log( + `选择班级: ${item.title}, 年级ID: ${njId}, 班级ID: ${bjId}` + ); + } + }); + + if (njIds.length > 0 && bjIds.length > 0) { + // 对年级ID去重 + const uniqueNjIds = [...new Set(njIds)]; + + // 保存选择的年级ID和班级ID到formData中 + formData.targetNjIds = uniqueNjIds; + formData.targetBjIds = bjIds; + + // 调用接口获取学生列表 + const params = { + njId: uniqueNjIds.join(","), + bjId: bjIds.join(","), + }; + + const response = await mobilejlstudentListApi(params); + + if (response && response.resultCode === 1 && response.result) { + // 提取学生姓名,尝试多个可能的字段名 + const studentNames = response.result.map( + (student: any) => + student.xsxm || + student.name || + student.studentName || + student.xm || + "未知姓名" + ); + formData.targetNames = studentNames; + formData.targetStudentIds = response.result.map( + (student: any) => + student.id || student.xsId || student.studentId || "" + ); + } else { + throw new Error("获取学生列表失败"); + } + } + + uni.hideLoading(); + uni.showToast({ + title: `已选择 ${selectedItems.length} 个班级`, + icon: "success", + }); } catch (error) { console.error("获取学生列表失败:", error); - uni.showToast({ title: "获取学生列表失败", icon: "none" }); + uni.hideLoading(); + uni.showToast({ title: "获取学生列表失败", icon: "error" }); + // 如果接口失败,使用模拟数据 + formData.targetNames = await fetchStudentsByClass(formData.targetClass); } } }; -const handleModifyNames = () => { - const selectedClassObj = classList.value.find( - (cls) => cls.name === formData.targetClass - ); - if (!selectedClassObj) { - uni.showToast({ title: "请先选择班级", icon: "none" }); - return; - } - const classId = selectedClassObj.id; - uni.navigateTo({ - url: `/pages/view/notice/selectStudents?classId=${classId}`, - }); +// 树形选择取消 +const onTreeCancel = () => { + console.log("取消选择班级"); +}; + +// 显示全部学生 +const showAllStudents = () => { + showStudentModal.value = true; +}; + +// 关闭学生弹窗 +const closeStudentModal = () => { + showStudentModal.value = false; }; const handleSignatureChange = (e: any) => { @@ -464,13 +626,25 @@ const previewNotice = () => { const publishNotice = () => { if (!validateForm()) return; - console.log("发布通知", formData); - uni.showLoading({ title: "发布中..." }); - setTimeout(() => { - uni.hideLoading(); - uni.showToast({ title: "发布成功 (模拟)", icon: "success" }); - uni.navigateBack(); - }, 1000); + + // 准备发布数据,包含年级ID和班级ID + const publishData = { + ...formData, + njIds: formData.targetNjIds.join(","), // 年级ID字符串 + bjIds: formData.targetBjIds.join(","), // 班级ID字符串 + }; + + console.log("发布通知数据:", publishData); + console.log("年级ID:", publishData.njIds); + console.log("班级ID:", publishData.bjIds); + + // TODO: 调用发布接口 + // uni.showLoading({ title: "发布中..." }); + // setTimeout(() => { + // uni.hideLoading(); + // uni.showToast({ title: "发布成功 (模拟)", icon: "success" }); + // uni.navigateBack(); + // }, 1000); }; @@ -496,10 +670,10 @@ const publishNotice = () => { } .form-container { - padding: 12px; + padding: 12px; box-sizing: border-box; /* Add padding-bottom if content gets hidden by bottom bar */ - /* padding-bottom: 70px; */ + /* padding-bottom: 70px; */ } .info-card { @@ -734,8 +908,7 @@ const publishNotice = () => { position: relative; min-height: 30px; - .name-tag, - .modify-btn { + .name-tag { font-size: 13px; padding: 5px 0; border-radius: 4px; @@ -746,29 +919,10 @@ const publishNotice = () => { flex-basis: calc((100% - 50px) / 6); height: 28px; line-height: 18px; - } - - .name-tag { background-color: #f4f4f5; color: #909399; } - .modify-btn { - background-color: #ecf5ff; - color: #409eff; - border: 1px solid #d9ecff; - padding: 0; - margin-left: 0; - margin-top: 0; - margin-bottom: 0; - &::after { - border: none; - } - display: flex; - justify-content: center; - align-items: center; - } - .loading-spinner { position: absolute; top: 5px; @@ -778,6 +932,26 @@ const publishNotice = () => { } } +.more-btn-container { + width: 100%; +} + +.more-btn-full { + width: 100%; + height: 35px; + background-color: #fff2e8; + color: #e6a23c; + border: 1px solid #f5dab1; + border-radius: 4px; + font-size: 14px; + &::after { + border: none; + } + &:active { + background-color: #ffecd1; + } +} + .list-item-card { padding: 0; .uni-datetime-picker, @@ -841,7 +1015,7 @@ const publishNotice = () => { display: flex; justify-content: space-around; align-items: center; - padding: 12px 15px; + padding: 12px 15px; background-color: #ffffff; border-top: 1px solid #e5e5e5; @@ -887,7 +1061,76 @@ const publishNotice = () => { } .target-class text.placeholder { - color: #909399; + color: #909399; } +/* 学生名单弹窗样式 */ +.student-modal-mask { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); + z-index: 9999; + display: flex; + justify-content: center; + align-items: center; +} + +.student-modal { + width: 90%; + max-height: 80%; + background-color: #ffffff; + border-radius: 8px; + overflow: hidden; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.student-modal-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 15px 20px; + border-bottom: 1px solid #f0f0f0; + background-color: #fafafa; +} + +.modal-title { + font-size: 16px; + font-weight: 500; + color: #303133; +} + +.student-count { + font-size: 14px; + color: #909399; +} + +.close-icon { + cursor: pointer; + padding: 5px; +} + +.student-modal-content { + max-height: 400px; + padding: 20px; +} + +.all-student-tags { + display: flex; + flex-wrap: wrap; + gap: 8px 10px; +} + +.student-tag { + font-size: 13px; + padding: 6px 12px; + border-radius: 4px; + text-align: center; + background-color: #f4f4f5; + color: #909399; + min-width: 60px; + box-sizing: border-box; +}