接龙调整
This commit is contained in:
parent
66955f9ac7
commit
510d12282f
101
src/api/base/jlApi.ts
Normal file
101
src/api/base/jlApi.ts
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
// 接龙相关API接口
|
||||||
|
import { get, post } from "@/utils/request";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据年级ID和班级ID查询学生及家长信息
|
||||||
|
*/
|
||||||
|
export const mobilejlstudentListApi = async (params: any) => {
|
||||||
|
return await get("/mobile/jl/studentList", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据年级ID、关联年级名称ID和学生ID查询家长接龙信息
|
||||||
|
*/
|
||||||
|
export const mobilejllistApi = async (params: any) => {
|
||||||
|
const res = await get("/mobile/jl/list", params);
|
||||||
|
return res.result;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据jlId查询接龙列表数据
|
||||||
|
*/
|
||||||
|
export const getByJlIdApi = async (params: any) => {
|
||||||
|
const res = await get("/mobile/jl/getByJlId", params);
|
||||||
|
return res.result;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接龙统计API
|
||||||
|
*/
|
||||||
|
export const getJlStatisticsApi = async (params: any) => {
|
||||||
|
const res = await get("/mobile/jl/statistics", params);
|
||||||
|
return res.result;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID获取接龙详情
|
||||||
|
*/
|
||||||
|
export const jlFindByIdApi = async (params: { id: string }) => {
|
||||||
|
return await get("/api/jl/findById", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存接龙(新增/编辑)
|
||||||
|
*/
|
||||||
|
export const jlSaveApi = async (params: any) => {
|
||||||
|
return await post("/api/jl/save", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据接龙ID查询接龙执行情况(学生列表)
|
||||||
|
*/
|
||||||
|
export const jlzxFindByJlParamsApi = async (params: {
|
||||||
|
jlId: string;
|
||||||
|
njId?: string;
|
||||||
|
njmcId?: string;
|
||||||
|
bjId?: string;
|
||||||
|
}) => {
|
||||||
|
return await get("/api/jlzx/findByJlParams", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存接龙消息推送
|
||||||
|
*/
|
||||||
|
export const xxtsSaveByJlzxParamsApi = async (params: { jlId: string }) => {
|
||||||
|
return await post("/api/xxts/saveByJlzxParams", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取班级列表API
|
||||||
|
*/
|
||||||
|
export const getClassListApi = async () => {
|
||||||
|
const res = await get("/api/bj/findAll");
|
||||||
|
return res.result;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取班级详情统计API
|
||||||
|
*/
|
||||||
|
export const getClassDetailApi = async (params: { jlId: string; njId: string }) => {
|
||||||
|
const res = await get("/mobile/jl/classDetail", params);
|
||||||
|
return res.result;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取接龙人员名单API
|
||||||
|
*/
|
||||||
|
export const getPersonnelListApi = async (params: { jlId: string; type: string; bjId?: string; njId?: string }) => {
|
||||||
|
const res = await get("/mobile/jl/personnelList", params);
|
||||||
|
return res.result;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 直接推送消息API(跳过验证和状态更新)
|
||||||
|
*/
|
||||||
|
export const pushMessageApi = async (params: {
|
||||||
|
jlId: string;
|
||||||
|
njId?: string;
|
||||||
|
bjId?: string;
|
||||||
|
}) => {
|
||||||
|
return await post("/api/jlzx/pushMessage", params);
|
||||||
|
};
|
||||||
@ -128,20 +128,6 @@ export const ksccKmFindByKsccIdApi = async (params: any) => {
|
|||||||
return await get("/api/kscc/findKsccKmmcById", params);
|
return await get("/api/kscc/findKsccKmmcById", params);
|
||||||
};
|
};
|
||||||
|
|
||||||
//根据年级ID和班级ID查询学生及家长信息
|
|
||||||
export const mobilejlstudentListApi = async (params: any) => {
|
|
||||||
return await get("/mobile/jl/studentList", params);
|
|
||||||
};
|
|
||||||
//根据年级ID、关联年级名称ID和学生ID查询家长接龙信息
|
|
||||||
export const mobilejllistApi = async (params: any) => {
|
|
||||||
const res = await get("/mobile/jl/list", params);
|
|
||||||
return res.result;
|
|
||||||
};
|
|
||||||
//根据jlId查询接龙列表数据
|
|
||||||
export const getByJlIdApi = async (params: any) => {
|
|
||||||
const res = await get("/mobile/jl/getByJlId", params);
|
|
||||||
return res.result;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 提交点名信息
|
// 提交点名信息
|
||||||
export const jsdXkdmListApi = async (params: any) => {
|
export const jsdXkdmListApi = async (params: any) => {
|
||||||
@ -236,31 +222,6 @@ export const getJsPjGzlApi = async () => {
|
|||||||
return await get("/api/comConfig/getJsPjGzl");
|
return await get("/api/comConfig/getJsPjGzl");
|
||||||
};
|
};
|
||||||
|
|
||||||
// 接龙相关API
|
|
||||||
// 根据ID获取接龙详情
|
|
||||||
export const jlFindByIdApi = async (params: { id: string }) => {
|
|
||||||
return await get("/api/jl/findById", params);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 保存接龙(新增/编辑)
|
|
||||||
export const jlSaveApi = async (params: any) => {
|
|
||||||
return await post("/api/jl/save", params);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 根据接龙ID查询接龙执行情况(学生列表)
|
|
||||||
export const jlzxFindByJlParamsApi = async (params: {
|
|
||||||
jlId: string;
|
|
||||||
njId?: string;
|
|
||||||
njmcId?: string;
|
|
||||||
bjId?: string;
|
|
||||||
}) => {
|
|
||||||
return await get("/api/jlzx/findByJlParams", params);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 保存接龙消息推送
|
|
||||||
export const xxtsSaveByJlzxParamsApi = async (params: { jlId: string }) => {
|
|
||||||
return await post("/api/xxts/saveByJlzxParams", params);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前学期和周次
|
* 获取当前学期和周次
|
||||||
|
|||||||
820
src/pages.json
820
src/pages.json
@ -493,6 +493,34 @@
|
|||||||
"enablePullDownRefresh": false
|
"enablePullDownRefresh": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/view/analysis/jl/statistics",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "接龙情况",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/view/analysis/jl/classDetail",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "班级详情",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/view/analysis/jl/personnelList",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "人员名单",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/view/analysis/jl/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "接龙统计",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/view/routine/RengJiaoRengZhi/index",
|
"path": "pages/view/routine/RengJiaoRengZhi/index",
|
||||||
"style": {
|
"style": {
|
||||||
@ -790,3 +818,795 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/hr/teacherProfile/ExperienceInfo",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "学习及工作经历",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/hr/teacherProfile/FamilyInfo",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "家庭成员情况",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/hr/teacherProfile/EmergencyContact",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "紧急联系人",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/routine/JiFenPingJia/PersonalHonor",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "个人荣誉",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/routine/JiFenPingJia/PublicClassAwards",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "公开课获奖",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/hr/teacherProfile/RecordMaterials",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "备案资料",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/hr/salarySlip/detail",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "工资条详情",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/homeSchool/parentAddressBook/index",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "家长通讯录",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/homeSchool/parentAddressBook/detail",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "学生详情",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/notice/index",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "发布接龙",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/notice/detail",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "接龙详情",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/notice/publish",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "接龙推送",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/notice/push-list",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "推送清单",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/notice/selectStudents",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "选择学生",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/routine/RengJiaoRengZhi/index",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "任教任职",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/routine/GongZuoLiang/index",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "工作量",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/routine/xk/xkList",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "选课列表",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/routine/xk/xkkcDetail",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "选课课程详情"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/routine/xk/dmIndex",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "点名选课列表"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/routine/xk/dm",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "学生点名",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/routine/xk/dmList",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "点名列表",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/routine/xk/dmXsList",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "点名学生列表",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/routine/xk/tf/detail",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "选课退费详情",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/routine/xk/tf/sp",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "选课退费审批",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/routine/kefuxuncha/xcRecord",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "选课巡查记录"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/routine/kefuxuncha/kyRecord",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "课业巡查记录"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/base/xs/qj/sp",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "学生请假审批",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/base/xs/qj/detail",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "学生请假详情",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/analysis/xs/studentArchive",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "学生档案",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/analysis/xk/xkCourse",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "课程明单",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/analysis/xk/xkList",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "选课清单",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/analysis/xk/dmStatistics",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "点名统计",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/analysis/xk/dmXkList",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "点名选课列表",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/routine/qd/index",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "签到发布"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/routine/qd/publish",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "新增签到"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/routine/qd/push-list",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "推送清单"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/routine/qd/detail",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "签到详情"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/routine/qd/selectTeachers",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "选择教师"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/routine/qd/qr-code",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "签到二维码",
|
||||||
|
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/routine/qd/confirm",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "确认签到",
|
||||||
|
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/routine/JiaoXueZiYuan/add-resource",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "上传资源",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false,
|
||||||
|
|
||||||
|
"navigationBarBackgroundColor": "#ffffff",
|
||||||
|
|
||||||
|
"navigationBarTextStyle": "black",
|
||||||
|
|
||||||
|
"backgroundColor": "#f4f5f7"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/routine/jc/bzList",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "就餐标准列表"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/routine/jc/index",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "就餐点名"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/routine/jc/detail",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "就餐点名详情"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/quantitativeAssessment/assessment/assessment",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "考核评价",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/quantitativeAssessment/casualShot/casualShot",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "随手拍",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/quantitativeAssessment/distribute/distribute",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "分配",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/quantitativeAssessment/index/index",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "量化考核首页",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/quantitativeAssessment/index/details",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "量化考核详情",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/quantitativeAssessment/quantitativeSummary/quantitativeSummary",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "量化汇总",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/quantitativeAssessment/index/noticeAnnouncement",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "通知公告",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "pages/view/quantitativeAssessment/index/playPage",
|
||||||
|
|
||||||
|
"style": {
|
||||||
|
|
||||||
|
"navigationBarTitleText": "播放页面",
|
||||||
|
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
],
|
||||||
|
|
||||||
|
"globalStyle": {
|
||||||
|
|
||||||
|
"navigationBarTextStyle": "black",
|
||||||
|
|
||||||
|
"navigationBarTitleText": "uni-app",
|
||||||
|
|
||||||
|
"navigationBarBackgroundColor": "#fff",
|
||||||
|
|
||||||
|
"backgroundColor": "#F8F8F8",
|
||||||
|
|
||||||
|
"orientation": "portrait",
|
||||||
|
|
||||||
|
"navigationStyle": "custom",
|
||||||
|
|
||||||
|
"app-plus": {
|
||||||
|
|
||||||
|
"background": "#efeff4",
|
||||||
|
|
||||||
|
"titleView": false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
"tabBar": {
|
||||||
|
|
||||||
|
"selectedColor": "#447ade",
|
||||||
|
|
||||||
|
"color": "#999999",
|
||||||
|
|
||||||
|
"borderStyle": "black",
|
||||||
|
|
||||||
|
"backgroundColor": "#ffffff",
|
||||||
|
|
||||||
|
"list": [
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"text": "消息",
|
||||||
|
|
||||||
|
"pagePath": "pages/base/message/index",
|
||||||
|
|
||||||
|
"iconPath": "static/tabBar/x1.png",
|
||||||
|
|
||||||
|
"selectedIconPath": "static/tabBar/1.png"
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"text": "自助服务",
|
||||||
|
|
||||||
|
"pagePath": "pages/base/service/index",
|
||||||
|
|
||||||
|
"iconPath": "static/tabBar/x2.png",
|
||||||
|
|
||||||
|
"selectedIconPath": "static/tabBar/2.png"
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
"text": "我的",
|
||||||
|
|
||||||
|
"pagePath": "pages/base/mine/index",
|
||||||
|
|
||||||
|
"iconPath": "static/tabBar/x3.png",
|
||||||
|
|
||||||
|
"selectedIconPath": "static/tabBar/3.png"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -320,6 +320,14 @@ const sections = reactive<Section[]>([
|
|||||||
permissionKey: "routine-bjjl", // 发布接龙权限编码
|
permissionKey: "routine-bjjl", // 发布接龙权限编码
|
||||||
path: "/pages/view/notice/index",
|
path: "/pages/view/notice/index",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: "r13",
|
||||||
|
icon: "jltj",
|
||||||
|
text: "接龙统计",
|
||||||
|
show: true,
|
||||||
|
permissionKey: "routine-jltj", // 接龙统计权限编码
|
||||||
|
path: "/pages/view/analysis/jl/index",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: "hs4",
|
id: "hs4",
|
||||||
icon: "xsda",
|
icon: "xsda",
|
||||||
|
|||||||
290
src/pages/view/analysis/jl/classDetail.vue
Normal file
290
src/pages/view/analysis/jl/classDetail.vue
Normal file
@ -0,0 +1,290 @@
|
|||||||
|
<!-- src/pages/view/analysis/jl/classDetail.vue -->
|
||||||
|
<template>
|
||||||
|
<view class="class-detail-page">
|
||||||
|
<!-- 顶部标题 -->
|
||||||
|
<view class="page-header">
|
||||||
|
<text class="page-title">{{ njmc }} - 班级接龙完成情况</text>
|
||||||
|
<text class="refresh-btn" @click="refreshData">刷新</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 班级统计列表 -->
|
||||||
|
<view class="class-list">
|
||||||
|
<view
|
||||||
|
class="class-item"
|
||||||
|
v-for="classItem in classStats"
|
||||||
|
:key="classItem.bj_id"
|
||||||
|
>
|
||||||
|
<view class="class-header">
|
||||||
|
<text class="class-name">{{ classItem.bjmc }}</text>
|
||||||
|
<text class="completion-rate">{{ calculateCompletionRate(classItem) }}%</text>
|
||||||
|
</view>
|
||||||
|
<view class="class-stats">
|
||||||
|
<view class="stat-item">
|
||||||
|
<text class="stat-label">总人数</text>
|
||||||
|
<text class="stat-value">{{ classItem.jlts }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="stat-item" @click="handlePersonnelClick(classItem, 'yjl')">
|
||||||
|
<text class="stat-label">已接龙</text>
|
||||||
|
<text class="stat-value success">{{ classItem.yjl }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="stat-item" @click="handlePersonnelClick(classItem, 'wjl')">
|
||||||
|
<text class="stat-label">未接龙</text>
|
||||||
|
<text class="stat-value danger">{{ classItem.wjl }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="stat-item" @click="handlePersonnelClick(classItem, 'wgz')">
|
||||||
|
<text class="stat-label">未关注</text>
|
||||||
|
<text class="stat-value warning">{{ classItem.wgz }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 空状态 -->
|
||||||
|
<view class="empty-state" v-if="classStats.length === 0">
|
||||||
|
<text class="empty-text">暂无班级数据</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { onLoad } from '@dcloudio/uni-app'
|
||||||
|
import { getClassDetailApi, getPersonnelListApi } from '@/api/base/jlApi'
|
||||||
|
|
||||||
|
interface ClassStats {
|
||||||
|
nj_id: string;
|
||||||
|
njmc: string;
|
||||||
|
bj_id: string;
|
||||||
|
bjmc: string;
|
||||||
|
yjl: number;
|
||||||
|
wjl: number;
|
||||||
|
wgz: number;
|
||||||
|
jlts: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const jlId = ref('')
|
||||||
|
const njId = ref('')
|
||||||
|
const njmc = ref('')
|
||||||
|
const classStats = ref<ClassStats[]>([])
|
||||||
|
|
||||||
|
// 计算完成率
|
||||||
|
const calculateCompletionRate = (classItem: ClassStats) => {
|
||||||
|
if (classItem.jlts === 0) return 0
|
||||||
|
return Math.round((classItem.yjl / classItem.jlts) * 100)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新数据
|
||||||
|
const refreshData = async () => {
|
||||||
|
await loadClassDetailData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理人员列表点击事件
|
||||||
|
const handlePersonnelClick = async (classItem: ClassStats, type: string) => {
|
||||||
|
try {
|
||||||
|
uni.showLoading({ title: '加载中...' })
|
||||||
|
|
||||||
|
const result = await getPersonnelListApi({
|
||||||
|
jlId: jlId.value,
|
||||||
|
type: type,
|
||||||
|
njId: njId.value,
|
||||||
|
bjId: classItem.bj_id
|
||||||
|
})
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
// 这里可以根据需要处理返回的人员列表数据
|
||||||
|
// 比如跳转到人员列表页面或显示弹窗
|
||||||
|
console.log('人员列表数据:', result)
|
||||||
|
|
||||||
|
// 根据类型设置页面标题
|
||||||
|
let title = ''
|
||||||
|
switch (type) {
|
||||||
|
case 'yjl':
|
||||||
|
title = '已接龙人员'
|
||||||
|
break
|
||||||
|
case 'wjl':
|
||||||
|
title = '未接龙人员'
|
||||||
|
break
|
||||||
|
case 'wgz':
|
||||||
|
title = '未关注人员'
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
title = '人员列表'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转到人员列表页面
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages/view/analysis/jl/personnelList?jlId=${jlId.value}&type=${type}&njId=${njId.value}&bjId=${classItem.bj_id}&njmc=${encodeURIComponent(njmc.value)}&title=${encodeURIComponent(title)}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载人员列表失败:', error)
|
||||||
|
uni.showToast({
|
||||||
|
title: '加载失败',
|
||||||
|
icon: 'error'
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
|
uni.hideLoading()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载班级详情数据
|
||||||
|
const loadClassDetailData = async () => {
|
||||||
|
try {
|
||||||
|
uni.showLoading({ title: '加载中...' })
|
||||||
|
|
||||||
|
const result = await getClassDetailApi({
|
||||||
|
jlId: jlId.value,
|
||||||
|
njId: njId.value
|
||||||
|
})
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
classStats.value = result
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载班级详情数据失败:', error)
|
||||||
|
uni.showToast({
|
||||||
|
title: '加载失败',
|
||||||
|
icon: 'error'
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
|
uni.hideLoading()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onLoad((options) => {
|
||||||
|
if (options.jlId && options.njId && options.njmc) {
|
||||||
|
jlId.value = options.jlId
|
||||||
|
njId.value = options.njId
|
||||||
|
njmc.value = decodeURIComponent(options.njmc)
|
||||||
|
loadClassDetailData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.class-detail-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 16px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.refresh-btn {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #1890ff;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border: 1px solid #1890ff;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.class-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.class-item {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 16px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.class-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
padding-bottom: 12px;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.class-name {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.completion-rate {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #1890ff;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.class-stats {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-item {
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-label {
|
||||||
|
display: block;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #666;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-value {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
|
||||||
|
&.success {
|
||||||
|
color: #52c41a;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.danger {
|
||||||
|
color: #ff4d4f;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.warning {
|
||||||
|
color: #faad14;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-state {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 200px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
341
src/pages/view/analysis/jl/index.vue
Normal file
341
src/pages/view/analysis/jl/index.vue
Normal file
@ -0,0 +1,341 @@
|
|||||||
|
<!-- src/pages/view/analysis/jl/index.vue -->
|
||||||
|
<template>
|
||||||
|
<view class="jl-list-page">
|
||||||
|
<!-- 列表内容 -->
|
||||||
|
<BasicListLayout @register="register" v-model="dataList">
|
||||||
|
<template v-slot="{ data }">
|
||||||
|
<view class="jl-card" @click="goToStatistics(data.id)">
|
||||||
|
<view class="card-header">
|
||||||
|
<text class="jl-title">{{ data.jlmc }}</text>
|
||||||
|
<text class="jl-status" :class="getStatusClass(data.jlStatus)">
|
||||||
|
{{ getStatusText(data.jlStatus) }}
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
<view class="card-body">
|
||||||
|
<image
|
||||||
|
v-if="data.jlfm"
|
||||||
|
:src="imagUrl(data.jlfm)"
|
||||||
|
mode="aspectFill"
|
||||||
|
class="cover-thumbnail"
|
||||||
|
></image>
|
||||||
|
<rich-text class="jl-excerpt" :nodes="data.jlms"></rich-text>
|
||||||
|
</view>
|
||||||
|
<view class="card-footer">
|
||||||
|
<text class="footer-item">发布者: {{ data.jsxm || '未知' }}</text>
|
||||||
|
<text class="footer-item">{{ formatTime(data.jlFbtime) }}</text>
|
||||||
|
<text class="footer-item" v-if="data.bjmc"
|
||||||
|
>范围: {{ data.njmc + data.bjmc }}</text
|
||||||
|
>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<template #bottom>
|
||||||
|
<view class="flex-row items-center pb-10 pt-5">
|
||||||
|
<u-button
|
||||||
|
text="新增接龙"
|
||||||
|
class="mx-15"
|
||||||
|
type="primary"
|
||||||
|
@click="goToPublish"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</BasicListLayout>
|
||||||
|
<!-- 用uniqueList渲染 -->
|
||||||
|
<template v-for="item in uniqueList" :key="item.id">
|
||||||
|
<!-- 这里可以加自定义渲染内容做二次验证 -->
|
||||||
|
</template>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useLayout } from "@/components/BasicListLayout/hooks/useLayout";
|
||||||
|
import { mobilejllistApi } from "@/api/base/jlApi";
|
||||||
|
import { imagUrl } from "@/utils";
|
||||||
|
import { computed, watch } from "vue";
|
||||||
|
import { onShow } from "@dcloudio/uni-app";
|
||||||
|
|
||||||
|
interface JlItem {
|
||||||
|
id: string;
|
||||||
|
jlmc: string; // 接龙名称
|
||||||
|
jlms: string; // 接龙描述
|
||||||
|
jlStatus: string; // 发布状态:A待推送,B暂存,C已推送
|
||||||
|
jlFbr: string; // 发布人
|
||||||
|
jlFbtime: string; // 发布时间
|
||||||
|
jlfm: string; // 接龙封面
|
||||||
|
njmc: string;
|
||||||
|
bjmc: string; // 班级名称
|
||||||
|
jlkstime: string; // 接龙开始时间
|
||||||
|
jljstime: string; // 接龙结束时间
|
||||||
|
jsxm?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用 BasicListLayout
|
||||||
|
const [register, { reload }] = useLayout({
|
||||||
|
api: mobilejllistApi, // 必须提供 api,即使使用了 query
|
||||||
|
componentProps: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 兜底去重逻辑
|
||||||
|
const dataList = ref<JlItem[]>([]);
|
||||||
|
const uniqueList = computed(() => {
|
||||||
|
const map = new Map();
|
||||||
|
(dataList.value || []).forEach(item => {
|
||||||
|
if (item && item.id != null) map.set(String(item.id), item);
|
||||||
|
});
|
||||||
|
return Array.from(map.values());
|
||||||
|
});
|
||||||
|
|
||||||
|
// 日志:每次dataList变化时打印
|
||||||
|
watch(dataList, (val) => {
|
||||||
|
// 监听数据变化
|
||||||
|
});
|
||||||
|
|
||||||
|
// 跳转到发布页
|
||||||
|
const goToPublish = () => {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: "/pages/view/notice/publish",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 跳转到接龙统计页
|
||||||
|
const goToStatistics = (jlId: string) => {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages/view/analysis/jl/statistics?jlId=${jlId}`,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 根据状态获取对应的 CSS 类
|
||||||
|
const getStatusClass = (status: string) => {
|
||||||
|
if (status === "A") return "status-published";
|
||||||
|
if (status === "B") return "status-draft";
|
||||||
|
return "status-ended";
|
||||||
|
};
|
||||||
|
|
||||||
|
// 根据状态获取状态文字
|
||||||
|
const getStatusText = (status: string) => {
|
||||||
|
if (status === "A") return "待推送";
|
||||||
|
if (status === "B") return "暂存";
|
||||||
|
return "已推送";
|
||||||
|
};
|
||||||
|
|
||||||
|
// 格式化时间
|
||||||
|
const formatTime = (timeStr: string) => {
|
||||||
|
if (!timeStr) return "";
|
||||||
|
const date = new Date(timeStr);
|
||||||
|
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(
|
||||||
|
2,
|
||||||
|
"0"
|
||||||
|
)}-${String(date.getDate()).padStart(2, "0")}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
onShow(() => {
|
||||||
|
reload();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.jl-list-page {
|
||||||
|
position: relative;
|
||||||
|
min-height: 100vh;
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
padding: 12px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jl-card {
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 16px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: translateY(1px);
|
||||||
|
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.12);
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 4px;
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: flex-start;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
gap: 12px;
|
||||||
|
|
||||||
|
.jl-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #2c3e50;
|
||||||
|
flex: 1;
|
||||||
|
line-height: 1.4;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jl-status {
|
||||||
|
font-size: 11px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 12px;
|
||||||
|
color: #fff;
|
||||||
|
white-space: nowrap;
|
||||||
|
flex-shrink: 0;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
|
||||||
|
&.status-published {
|
||||||
|
background: linear-gradient(135deg, #ff6b6b 0%, #ee5a52 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.status-draft {
|
||||||
|
background: linear-gradient(135deg, #ffa726 0%, #ff9800 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.status-ended {
|
||||||
|
background: linear-gradient(135deg, #66bb6a 0%, #4caf50 100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-body {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
|
||||||
|
.cover-thumbnail {
|
||||||
|
width: 80px;
|
||||||
|
height: 60px;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-right: 12px;
|
||||||
|
float: left;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jl-excerpt {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #5a6c7d;
|
||||||
|
line-height: 1.6;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 3;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-footer {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px 16px;
|
||||||
|
align-items: center;
|
||||||
|
padding-top: 12px;
|
||||||
|
border-top: 1px solid #f0f0f0;
|
||||||
|
|
||||||
|
.footer-item {
|
||||||
|
white-space: nowrap;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #7f8c8d;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
max-width: 180px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
width: 4px;
|
||||||
|
height: 4px;
|
||||||
|
background-color: #bdc3c7;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-right: 6px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 底部按钮区域优化
|
||||||
|
.white-bg-color {
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
border-radius: 16px;
|
||||||
|
margin: 16px 12px;
|
||||||
|
padding: 16px;
|
||||||
|
box-shadow: 0 4px 16px rgba(102, 126, 234, 0.3);
|
||||||
|
|
||||||
|
.flex-row {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.u-button {
|
||||||
|
background: rgba(255, 255, 255, 0.9);
|
||||||
|
color: #667eea;
|
||||||
|
border: none;
|
||||||
|
font-weight: 600;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background: rgba(255, 255, 255, 1);
|
||||||
|
transform: translateY(1px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 响应式优化
|
||||||
|
@media (max-width: 375px) {
|
||||||
|
.jl-list-page {
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jl-card {
|
||||||
|
padding: 12px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-header .jl-title {
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-footer .footer-item {
|
||||||
|
max-width: 150px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载动画
|
||||||
|
.jl-card {
|
||||||
|
animation: fadeInUp 0.3s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeInUp {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(20px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
437
src/pages/view/analysis/jl/personnelList.vue
Normal file
437
src/pages/view/analysis/jl/personnelList.vue
Normal file
@ -0,0 +1,437 @@
|
|||||||
|
<!-- src/pages/view/analysis/jl/personnelList.vue -->
|
||||||
|
<template>
|
||||||
|
<view class="personnel-list-page">
|
||||||
|
<!-- 页面头部 -->
|
||||||
|
<view class="page-header">
|
||||||
|
<text class="page-title">{{ pageTitle }}</text>
|
||||||
|
<text class="refresh-btn" @click="refreshData">刷新</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 筛选信息 -->
|
||||||
|
<view class="filter-info" v-if="njId && njmc">
|
||||||
|
<text class="filter-text">{{ njmc }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 人员列表 -->
|
||||||
|
<view class="personnel-list">
|
||||||
|
<view
|
||||||
|
class="personnel-item"
|
||||||
|
v-for="personnel in personnelList"
|
||||||
|
:key="personnel.id"
|
||||||
|
>
|
||||||
|
<view class="personnel-main-info">
|
||||||
|
<text class="personnel-name">{{ personnel.xm }}</text>
|
||||||
|
<text class="personnel-class">{{ personnel.njmc }}{{ personnel.bjmc }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="personnel-status">
|
||||||
|
<view class="status-tag" :class="getStatusClass()">
|
||||||
|
{{ getStatusText() }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 空状态 -->
|
||||||
|
<view class="empty-state" v-if="personnelList.length === 0 && !isLoading">
|
||||||
|
<text class="empty-text">暂无人员数据</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 加载状态 -->
|
||||||
|
<view class="loading-state" v-if="isLoading">
|
||||||
|
<text class="loading-text">加载中...</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 信息推送按钮 - 只在未接龙时显示 -->
|
||||||
|
<view class="push-button-container" v-if="type === 'wjl' && personnelList.length > 0">
|
||||||
|
<button class="push-button" @click="handlePushMessage">信息推送</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { onLoad } from '@dcloudio/uni-app'
|
||||||
|
import { getPersonnelListApi, pushMessageApi } from '@/api/base/jlApi'
|
||||||
|
|
||||||
|
interface Personnel {
|
||||||
|
id: string;
|
||||||
|
xm: string;
|
||||||
|
njmc: string;
|
||||||
|
bjmc: string;
|
||||||
|
jlts: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const jlId = ref('')
|
||||||
|
const type = ref('')
|
||||||
|
const pageTitle = ref('')
|
||||||
|
const bjId = ref('')
|
||||||
|
const njId = ref('')
|
||||||
|
const njmc = ref('')
|
||||||
|
const personnelList = ref<Personnel[]>([])
|
||||||
|
const isLoading = ref(false)
|
||||||
|
|
||||||
|
// 获取状态样式类
|
||||||
|
const getStatusClass = () => {
|
||||||
|
switch (type.value) {
|
||||||
|
case 'yjl':
|
||||||
|
return 'completed'
|
||||||
|
case 'wjl':
|
||||||
|
return 'pending'
|
||||||
|
case 'wgz':
|
||||||
|
return 'unfollowed'
|
||||||
|
default:
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取状态文本
|
||||||
|
const getStatusText = () => {
|
||||||
|
switch (type.value) {
|
||||||
|
case 'yjl':
|
||||||
|
return '已接龙'
|
||||||
|
case 'wjl':
|
||||||
|
return '未接龙'
|
||||||
|
case 'wgz':
|
||||||
|
return '未关注'
|
||||||
|
default:
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新数据
|
||||||
|
const refreshData = async () => {
|
||||||
|
await loadPersonnelData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理信息推送
|
||||||
|
const handlePushMessage = async () => {
|
||||||
|
try {
|
||||||
|
uni.showModal({
|
||||||
|
title: '确认推送',
|
||||||
|
content: `确定要对 ${personnelList.value.length} 名未接龙人员进行信息推送吗?`,
|
||||||
|
success: async (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
await pushMessage()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.error('推送确认失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行信息推送
|
||||||
|
const pushMessage = async () => {
|
||||||
|
try {
|
||||||
|
uni.showLoading({ title: '推送中...' })
|
||||||
|
|
||||||
|
const params: any = {
|
||||||
|
jlId: jlId.value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果指定了年级,添加年级参数
|
||||||
|
if (njId.value) {
|
||||||
|
params.njId = njId.value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果指定了班级,添加班级参数
|
||||||
|
if (bjId.value) {
|
||||||
|
params.bjId = bjId.value
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('推送API参数:', params)
|
||||||
|
|
||||||
|
const result = await pushMessageApi(params)
|
||||||
|
|
||||||
|
if (result && result.resultCode === 1) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '推送成功',
|
||||||
|
icon: 'success'
|
||||||
|
})
|
||||||
|
|
||||||
|
// 延迟关闭当前页面
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.navigateBack({
|
||||||
|
delta: 1
|
||||||
|
})
|
||||||
|
}, 1500)
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: result?.message || '推送失败',
|
||||||
|
icon: 'error'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('推送失败:', error)
|
||||||
|
uni.showToast({
|
||||||
|
title: '推送失败',
|
||||||
|
icon: 'error'
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
|
uni.hideLoading()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载人员数据
|
||||||
|
const loadPersonnelData = async () => {
|
||||||
|
try {
|
||||||
|
isLoading.value = true
|
||||||
|
|
||||||
|
const params: any = {
|
||||||
|
jlId: jlId.value,
|
||||||
|
type: type.value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果指定了班级,添加班级参数
|
||||||
|
if (bjId.value) {
|
||||||
|
params.bjId = bjId.value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果指定了年级,添加年级参数
|
||||||
|
if (njId.value) {
|
||||||
|
params.njId = njId.value
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('调用API参数:', params)
|
||||||
|
|
||||||
|
const result = await getPersonnelListApi(params)
|
||||||
|
|
||||||
|
console.log('API返回结果:', result)
|
||||||
|
|
||||||
|
// 检查返回的数据结构
|
||||||
|
if (result) {
|
||||||
|
if (Array.isArray(result)) {
|
||||||
|
// 如果直接返回数组
|
||||||
|
personnelList.value = result
|
||||||
|
console.log('设置人员列表数据(数组):', personnelList.value)
|
||||||
|
} else if (result.result && Array.isArray(result.result)) {
|
||||||
|
// 如果返回的是 {result: [...]} 格式
|
||||||
|
personnelList.value = result.result
|
||||||
|
console.log('设置人员列表数据(对象):', personnelList.value)
|
||||||
|
} else {
|
||||||
|
console.log('数据格式不正确:', result)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('没有获取到人员数据')
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载人员数据失败:', error)
|
||||||
|
uni.showToast({
|
||||||
|
title: '加载失败',
|
||||||
|
icon: 'error'
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
|
isLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onLoad((options) => {
|
||||||
|
console.log('personnelList onLoad options:', options)
|
||||||
|
|
||||||
|
if (options.jlId && options.type) {
|
||||||
|
jlId.value = options.jlId
|
||||||
|
type.value = options.type
|
||||||
|
|
||||||
|
// 设置页面标题
|
||||||
|
if (options.title) {
|
||||||
|
pageTitle.value = decodeURIComponent(options.title)
|
||||||
|
} else {
|
||||||
|
// 根据类型设置默认标题
|
||||||
|
switch (options.type) {
|
||||||
|
case 'yjl':
|
||||||
|
pageTitle.value = '已接龙人员'
|
||||||
|
break
|
||||||
|
case 'wjl':
|
||||||
|
pageTitle.value = '未接龙人员'
|
||||||
|
break
|
||||||
|
case 'wgz':
|
||||||
|
pageTitle.value = '未关注人员'
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
pageTitle.value = '人员列表'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置班级信息
|
||||||
|
if (options.bjId) {
|
||||||
|
bjId.value = options.bjId
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置年级信息
|
||||||
|
if (options.njId) {
|
||||||
|
njId.value = options.njId
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.njmc) {
|
||||||
|
njmc.value = decodeURIComponent(options.njmc)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('设置后的参数:', {
|
||||||
|
jlId: jlId.value,
|
||||||
|
type: type.value,
|
||||||
|
pageTitle: pageTitle.value,
|
||||||
|
bjId: bjId.value,
|
||||||
|
njId: njId.value,
|
||||||
|
njmc: njmc.value
|
||||||
|
})
|
||||||
|
|
||||||
|
loadPersonnelData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.personnel-list-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 16px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.refresh-btn {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #1890ff;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border: 1px solid #1890ff;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-info {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 12px 16px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #1890ff;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.personnel-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.personnel-item {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 16px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.personnel-main-info {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.personnel-name {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.personnel-class {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.personnel-status {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-tag {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 4px 12px;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
|
||||||
|
&.completed {
|
||||||
|
background-color: #e1f3d8;
|
||||||
|
color: #67c23a;
|
||||||
|
border: 1px solid #b3e19d;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.pending {
|
||||||
|
background-color: #fef0f0;
|
||||||
|
color: #f56c6c;
|
||||||
|
border: 1px solid #fbc4c4;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.unfollowed {
|
||||||
|
background-color: #fff7e6;
|
||||||
|
color: #faad14;
|
||||||
|
border: 1px solid #ffd591;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-state,
|
||||||
|
.loading-state {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 200px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-text,
|
||||||
|
.loading-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.push-button-container {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 16px;
|
||||||
|
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.push-button {
|
||||||
|
width: 100%;
|
||||||
|
height: 44px;
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background-color: #096dd9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
410
src/pages/view/analysis/jl/statistics.vue
Normal file
410
src/pages/view/analysis/jl/statistics.vue
Normal file
@ -0,0 +1,410 @@
|
|||||||
|
<!-- src/pages/view/analysis/jl/statistics.vue -->
|
||||||
|
<template>
|
||||||
|
<view class="statistics-page">
|
||||||
|
<!-- 顶部导航 -->
|
||||||
|
<view class="nav-tabs">
|
||||||
|
<view
|
||||||
|
class="nav-tab"
|
||||||
|
:class="{ active: activeTab === 'completion' }"
|
||||||
|
@click="switchTab('completion')"
|
||||||
|
>
|
||||||
|
完成情况
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
class="nav-tab"
|
||||||
|
:class="{ active: activeTab === 'details' }"
|
||||||
|
@click="switchTab('details')"
|
||||||
|
>
|
||||||
|
接龙详情
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 接龙完成情况 -->
|
||||||
|
<view class="completion-card" v-if="activeTab === 'completion'">
|
||||||
|
<view class="card-header">
|
||||||
|
<text class="card-title">接龙完成情况</text>
|
||||||
|
<text class="refresh-btn" @click="refreshData">刷新</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 全部年级统计 -->
|
||||||
|
<view class="total-stats" v-if="totalStats">
|
||||||
|
<view class="stats-item">
|
||||||
|
<text class="stats-label">总人数</text>
|
||||||
|
<text class="stats-value">{{ totalStats.jltsall }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="stats-item clickable" @click="goToPersonnelList('yjl', '已接龙人员')">
|
||||||
|
<text class="stats-label">已接龙</text>
|
||||||
|
<text class="stats-value success">{{ totalStats.yjl }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="stats-item clickable" @click="goToPersonnelList('wjl', '未接龙人员')">
|
||||||
|
<text class="stats-label">未接龙</text>
|
||||||
|
<text class="stats-value danger">{{ totalStats.wjl }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="stats-item clickable" @click="goToPersonnelList('wgz', '未关注人员')">
|
||||||
|
<text class="stats-label">未关注</text>
|
||||||
|
<text class="stats-value warning">{{ totalStats.wgz }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 各年级统计 -->
|
||||||
|
<view class="grade-stats" v-for="grade in gradeStats" :key="grade.nj_id">
|
||||||
|
<view class="grade-header">
|
||||||
|
<text class="grade-name">{{ grade.njmc }}</text>
|
||||||
|
<view class="grade-right">
|
||||||
|
<text class="completion-rate">{{ calculateCompletionRate(grade) }}%</text>
|
||||||
|
<text class="detail-arrow" @click="goToClassDetail(grade.nj_id, grade.njmc)">></text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="grade-details">
|
||||||
|
<view class="detail-item">
|
||||||
|
<text class="detail-label">总人数</text>
|
||||||
|
<text class="detail-value">{{ grade.jltsall }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="detail-item clickable" @click="goToPersonnelList('yjl', '已接龙人员', grade.nj_id, grade.njmc)">
|
||||||
|
<text class="detail-label">已接龙</text>
|
||||||
|
<text class="detail-value success">{{ grade.yjl }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="detail-item clickable" @click="goToPersonnelList('wjl', '未接龙人员', grade.nj_id, grade.njmc)">
|
||||||
|
<text class="detail-label">未接龙</text>
|
||||||
|
<text class="detail-value danger">{{ grade.wjl }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="detail-item clickable" @click="goToPersonnelList('wgz', '未关注人员', grade.nj_id, grade.njmc)">
|
||||||
|
<text class="detail-label">未关注</text>
|
||||||
|
<text class="detail-value warning">{{ grade.wgz }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 接龙详情 -->
|
||||||
|
<view class="details-card" v-if="activeTab === 'details'">
|
||||||
|
<text class="card-title">接龙详情</text>
|
||||||
|
<!-- 这里可以添加接龙详情内容 -->
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, onMounted, computed } from 'vue'
|
||||||
|
import { onLoad } from '@dcloudio/uni-app'
|
||||||
|
import { getJlStatisticsApi } from '@/api/base/jlApi'
|
||||||
|
|
||||||
|
interface TotalStats {
|
||||||
|
yjl: number; // 已接龙
|
||||||
|
wjl: number; // 未接龙
|
||||||
|
wgz: number; // 未关注
|
||||||
|
jltsall: number; // 总人数
|
||||||
|
}
|
||||||
|
|
||||||
|
interface GradeStats {
|
||||||
|
nj_id: string;
|
||||||
|
njmc: string;
|
||||||
|
yjl: number;
|
||||||
|
wjl: number;
|
||||||
|
wgz: number;
|
||||||
|
jltsall: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const activeTab = ref('completion')
|
||||||
|
const jlId = ref('')
|
||||||
|
const totalStats = ref<TotalStats | null>(null)
|
||||||
|
const gradeStats = ref<GradeStats[]>([])
|
||||||
|
|
||||||
|
// 切换标签页
|
||||||
|
const switchTab = (tab: string) => {
|
||||||
|
activeTab.value = tab
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算完成率
|
||||||
|
const calculateCompletionRate = (grade: GradeStats) => {
|
||||||
|
if (grade.jltsall === 0) return 0
|
||||||
|
return Math.round((grade.yjl / grade.jltsall) * 100)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新数据
|
||||||
|
const refreshData = async () => {
|
||||||
|
await loadStatisticsData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转到班级详情页面
|
||||||
|
const goToClassDetail = (njId: string, njmc: string) => {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages/view/analysis/jl/classDetail?jlId=${jlId.value}&njId=${njId}&njmc=${encodeURIComponent(njmc)}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转到接龙人员名单页面
|
||||||
|
const goToPersonnelList = (type: string, title: string, njId?: string, njmc?: string) => {
|
||||||
|
let url = `/pages/view/analysis/jl/personnelList?jlId=${jlId.value}&type=${type}&title=${encodeURIComponent(title)}`
|
||||||
|
|
||||||
|
// 如果指定了年级,则添加年级参数
|
||||||
|
if (njId && njmc) {
|
||||||
|
url += `&njId=${njId}&njmc=${encodeURIComponent(njmc)}`
|
||||||
|
}
|
||||||
|
|
||||||
|
uni.navigateTo({ url })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载统计数据
|
||||||
|
const loadStatisticsData = async () => {
|
||||||
|
try {
|
||||||
|
uni.showLoading({ title: '加载中...' })
|
||||||
|
|
||||||
|
// 使用all类型一次性获取全部统计
|
||||||
|
const result = await getJlStatisticsApi({
|
||||||
|
jlId: jlId.value,
|
||||||
|
type: 'all'
|
||||||
|
})
|
||||||
|
|
||||||
|
if (result.totalStats) {
|
||||||
|
// 设置全部年级统计
|
||||||
|
totalStats.value = result.totalStats
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.gradeStats) {
|
||||||
|
// 设置各年级统计
|
||||||
|
gradeStats.value = result.gradeStats
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载统计数据失败:', error)
|
||||||
|
uni.showToast({
|
||||||
|
title: '加载失败',
|
||||||
|
icon: 'error'
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
|
uni.hideLoading()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
onLoad((options) => {
|
||||||
|
if (options.jlId) {
|
||||||
|
jlId.value = options.jlId
|
||||||
|
loadStatisticsData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.statistics-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tabs {
|
||||||
|
display: flex;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 12px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
padding: 4px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tab {
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
padding: 12px 0;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #666;
|
||||||
|
border-radius: 8px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-color: #1890ff;
|
||||||
|
color: #fff;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.completion-card,
|
||||||
|
.details-card {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 16px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.refresh-btn {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #1890ff;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border: 1px solid #1890ff;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.total-stats {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 16px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-item {
|
||||||
|
text-align: center;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
min-height: 60px;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
&.clickable {
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 8px;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
background-color: #f0f8ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-label {
|
||||||
|
display: block;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #666;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-value {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
|
||||||
|
&.success {
|
||||||
|
color: #52c41a;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.danger {
|
||||||
|
color: #ff4d4f;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.warning {
|
||||||
|
color: #faad14;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade-stats {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 12px 16px;
|
||||||
|
background-color: #fafafa;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade-right {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade-name {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.completion-rate {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #1890ff;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-arrow {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #999;
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: color 0.3s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.grade-details {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 12px 16px;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-item {
|
||||||
|
text-align: center;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
min-height: 50px;
|
||||||
|
justify-content: center;
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
|
||||||
|
&.clickable {
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 8px;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
background-color: #f0f8ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-label {
|
||||||
|
display: block;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #666;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-value {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
|
||||||
|
&.success {
|
||||||
|
color: #52c41a;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.danger {
|
||||||
|
color: #ff4d4f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
@ -129,7 +129,7 @@ const [register, { setValue, getValue }] = useForm({
|
|||||||
field: "fileUrl",
|
field: "fileUrl",
|
||||||
label: "上传附件",
|
label: "上传附件",
|
||||||
component: "BasicUpload",
|
component: "BasicUpload",
|
||||||
required: true,
|
required: false,
|
||||||
itemProps: {
|
itemProps: {
|
||||||
labelPosition: "top",
|
labelPosition: "top",
|
||||||
},
|
},
|
||||||
|
|||||||
@ -182,7 +182,8 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, computed, watch, onMounted } from "vue";
|
import { ref, computed, watch, onMounted } from "vue";
|
||||||
import { onLoad } from "@dcloudio/uni-app";
|
import { onLoad } from "@dcloudio/uni-app";
|
||||||
import { getByJlIdApi, jlzxFindByJlParamsApi, findAllNjBjTree } from "@/api/base/server";
|
import { getByJlIdApi, jlzxFindByJlParamsApi } from "@/api/base/jlApi";
|
||||||
|
import { findAllNjBjTree } from "@/api/base/server";
|
||||||
import { imagUrl } from "@/utils";
|
import { imagUrl } from "@/utils";
|
||||||
import { BASE_IMAGE_URL } from "@/config";
|
import { BASE_IMAGE_URL } from "@/config";
|
||||||
import BasicTree from '@/components/BasicTree/Tree.vue';
|
import BasicTree from '@/components/BasicTree/Tree.vue';
|
||||||
|
|||||||
@ -67,7 +67,7 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useLayout } from "@/components/BasicListLayout/hooks/useLayout";
|
import { useLayout } from "@/components/BasicListLayout/hooks/useLayout";
|
||||||
import { mobilejllistApi } from "@/api/base/server";
|
import { mobilejllistApi } from "@/api/base/jlApi";
|
||||||
import { imagUrl } from "@/utils";
|
import { imagUrl } from "@/utils";
|
||||||
import { computed, watch } from "vue";
|
import { computed, watch } from "vue";
|
||||||
import { onShow } from "@dcloudio/uni-app";
|
import { onShow } from "@dcloudio/uni-app";
|
||||||
@ -136,6 +136,7 @@ const goToPush = (jlId: string) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// 根据状态获取对应的 CSS 类
|
// 根据状态获取对应的 CSS 类
|
||||||
const getStatusClass = (status: string) => {
|
const getStatusClass = (status: string) => {
|
||||||
if (status === "A") return "status-published";
|
if (status === "A") return "status-published";
|
||||||
|
|||||||
@ -240,7 +240,8 @@ import CustomUpload from "/src/components/BasicUpload/CustomUpload.vue";
|
|||||||
import BasicTree from "@/components/BasicTree/Tree.vue";
|
import BasicTree from "@/components/BasicTree/Tree.vue";
|
||||||
import { attachmentUpload } from "@/api/system/upload";
|
import { attachmentUpload } from "@/api/system/upload";
|
||||||
import { imagUrl } from "@/utils";
|
import { imagUrl } from "@/utils";
|
||||||
import { findAllNjBjTree, mobilejlstudentListApi, jlFindByIdApi, jlSaveApi } from "@/api/base/server";
|
import { mobilejlstudentListApi, jlFindByIdApi, jlSaveApi } from "@/api/base/jlApi";
|
||||||
|
import { findAllNjBjTree } from "@/api/base/server";
|
||||||
import { useUserStore } from "@/store/modules/user";
|
import { useUserStore } from "@/store/modules/user";
|
||||||
|
|
||||||
interface Attachment {
|
interface Attachment {
|
||||||
|
|||||||
@ -52,7 +52,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { onLoad } from "@dcloudio/uni-app";
|
import { onLoad } from "@dcloudio/uni-app";
|
||||||
import { jlzxFindByJlParamsApi, xxtsSaveByJlzxParamsApi } from "@/api/base/server";
|
import { jlzxFindByJlParamsApi, xxtsSaveByJlzxParamsApi } from "@/api/base/jlApi";
|
||||||
|
|
||||||
// 统一接口返回类型声明
|
// 统一接口返回类型声明
|
||||||
interface ApiResponse<T = any> {
|
interface ApiResponse<T = any> {
|
||||||
|
|||||||
@ -30,8 +30,8 @@
|
|||||||
<!-- 第一行:上课周期、开课年级 -->
|
<!-- 第一行:上课周期、开课年级 -->
|
||||||
<view class="course-info-row">
|
<view class="course-info-row">
|
||||||
<view class="course-info-item">
|
<view class="course-info-item">
|
||||||
<view class="info-label">上课周期:</view>
|
<view class="info-label">上课时间:</view>
|
||||||
<view class="info-data">{{ xkkc.skzqmc }}</view>
|
<view class="info-data study-time">{{ xkkc.studyTime }}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="course-info-item">
|
<view class="course-info-item">
|
||||||
<view class="info-label">开课年级:</view>
|
<view class="info-label">开课年级:</view>
|
||||||
@ -283,6 +283,7 @@ const loadXcCourseList = async (pbData: any) => {
|
|||||||
skzqmc: item.skzqmc || '每周',
|
skzqmc: item.skzqmc || '每周',
|
||||||
skkstime: item.skkstime,
|
skkstime: item.skkstime,
|
||||||
skjstime: item.skjstime,
|
skjstime: item.skjstime,
|
||||||
|
studyTime: item.studyTime, // 添加上课时间字段
|
||||||
kcdd: item.kcdd || '暂无',
|
kcdd: item.kcdd || '暂无',
|
||||||
njname: item.njname || '暂无',
|
njname: item.njname || '暂无',
|
||||||
hasNum: item.hasNum || 0,
|
hasNum: item.hasNum || 0,
|
||||||
@ -304,6 +305,7 @@ const loadXcCourseList = async (pbData: any) => {
|
|||||||
skzqmc: item.skzqmc || '每周',
|
skzqmc: item.skzqmc || '每周',
|
||||||
skkstime: item.skkstime,
|
skkstime: item.skkstime,
|
||||||
skjstime: item.skjstime,
|
skjstime: item.skjstime,
|
||||||
|
studyTime: item.studyTime, // 添加上课时间字段
|
||||||
kcdd: item.kcdd || '暂无',
|
kcdd: item.kcdd || '暂无',
|
||||||
njname: item.njname || '暂无',
|
njname: item.njname || '暂无',
|
||||||
hasNum: item.hasNum || 0,
|
hasNum: item.hasNum || 0,
|
||||||
@ -722,7 +724,7 @@ onBeforeUnmount(() => {
|
|||||||
color: #666;
|
color: #666;
|
||||||
flex: 0 0 70px;
|
flex: 0 0 70px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
margin-right: 5px;
|
margin-right: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.info-data {
|
.info-data {
|
||||||
@ -730,6 +732,13 @@ onBeforeUnmount(() => {
|
|||||||
color: #333;
|
color: #333;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
|
|
||||||
|
// 上课时间不换行
|
||||||
|
&.study-time {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,21 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<!-- 巡查时间信息 -->
|
||||||
|
<view class="inspection-time-info" v-if="xkkc.skkstime && xkkc.skjstime">
|
||||||
|
<view class="time-item">
|
||||||
|
<u-icon name="clock" color="#4080ff" size="16"></u-icon>
|
||||||
|
<text class="time-label">巡查时间:</text>
|
||||||
|
<text class="time-value">{{ xkkc.skkstime }} - {{ xkkc.skjstime }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 巡查时间状态 -->
|
||||||
|
<view class="inspection-status" v-if="!canInspect">
|
||||||
|
<u-icon name="clock" color="#ff9900" size="16"></u-icon>
|
||||||
|
<text class="status-text">{{ inspectionStatusText }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- 代课老师选择 -->
|
<!-- 代课老师选择 -->
|
||||||
<view class="teacher-selection-info">
|
<view class="teacher-selection-info">
|
||||||
<view class="teacher-item">
|
<view class="teacher-item">
|
||||||
@ -42,7 +57,7 @@
|
|||||||
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view>
|
<view v-if="canInspect">
|
||||||
<!-- 点名情况 -->
|
<!-- 点名情况 -->
|
||||||
<view class="section mx-15 mb-15">
|
<view class="section mx-15 mb-15">
|
||||||
<view class="section-title-bar">
|
<view class="section-title-bar">
|
||||||
@ -214,7 +229,10 @@
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
<template #bottom>
|
<template #bottom>
|
||||||
<view class="submit-btn-wrap py-10 px-20 bg-white">
|
<view
|
||||||
|
v-if="canInspect"
|
||||||
|
class="submit-btn-wrap py-10 px-20 bg-white"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
class="submit-btn"
|
class="submit-btn"
|
||||||
:class="{ 'submit-btn-disabled': isSubmitting }"
|
:class="{ 'submit-btn-disabled': isSubmitting }"
|
||||||
@ -330,6 +348,7 @@ const videoList = ref<VideoItem[]>([]);
|
|||||||
|
|
||||||
// 巡查状态相关
|
// 巡查状态相关
|
||||||
const inspectionStatusText = ref("");
|
const inspectionStatusText = ref("");
|
||||||
|
const canInspect = ref(true); // 是否可以巡查
|
||||||
|
|
||||||
// 点名数据
|
// 点名数据
|
||||||
const rollCallData = ref({
|
const rollCallData = ref({
|
||||||
@ -487,36 +506,55 @@ const previewImage = (index: number) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 检查巡查时间
|
// 检查巡查时间 - 验证当前时间是否在巡查时间范围内
|
||||||
const checkInspectionTime = () => {
|
const checkInspectionTime = () => {
|
||||||
const currentTime = now;
|
const skkstime = xkkc.value.skkstime;
|
||||||
let wDay = currentTime.day();
|
const skjstime = xkkc.value.skjstime;
|
||||||
if (wDay === 0) {
|
|
||||||
wDay = 7;
|
|
||||||
}
|
|
||||||
let mDay = currentTime.date();
|
|
||||||
let xcFlag = false;
|
|
||||||
let msg = "";
|
|
||||||
|
|
||||||
// 判断周期
|
// 如果没有设置巡查时间,直接允许巡查
|
||||||
switch (xkkc.value.skzqlx) {
|
if (!skkstime || !skjstime) {
|
||||||
case "每天":
|
canInspect.value = true;
|
||||||
xcFlag = true;
|
inspectionStatusText.value = "可以巡查";
|
||||||
msg = "可以巡查";
|
return;
|
||||||
break;
|
|
||||||
case "每周":
|
|
||||||
const daysOfWeek = xkkc.value.skzq.split(",").map(Number);
|
|
||||||
xcFlag = daysOfWeek.includes(wDay);
|
|
||||||
msg = xcFlag ? "可以巡查" : "没到巡查日期";
|
|
||||||
break;
|
|
||||||
case "每月":
|
|
||||||
const daysOfMonth = xkkc.value.skzq.split(",").map(Number);
|
|
||||||
xcFlag = daysOfMonth.includes(mDay);
|
|
||||||
msg = xcFlag ? "可以巡查" : "没到巡查日期";
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return { xcFlag, msg };
|
// 获取当前时间
|
||||||
|
const currentTime = now.format("HH:mm:ss");
|
||||||
|
|
||||||
|
// 将时间字符串转换为可比较的格式
|
||||||
|
const currentTimeMinutes = timeToMinutes(currentTime);
|
||||||
|
const startTimeMinutes = timeToMinutes(skkstime);
|
||||||
|
const endTimeMinutes = timeToMinutes(skjstime);
|
||||||
|
|
||||||
|
// 检查当前时间是否在巡查时间范围内
|
||||||
|
if (currentTimeMinutes < startTimeMinutes) {
|
||||||
|
canInspect.value = false;
|
||||||
|
inspectionStatusText.value = `还未到巡查时间,无法巡查(巡查时间:${skkstime} - ${skjstime})`;
|
||||||
|
} else if (currentTimeMinutes > endTimeMinutes) {
|
||||||
|
canInspect.value = false;
|
||||||
|
inspectionStatusText.value = `巡查时间已结束,无法巡查(巡查时间:${skkstime} - ${skjstime})`;
|
||||||
|
} else {
|
||||||
|
canInspect.value = true;
|
||||||
|
inspectionStatusText.value = `可以巡查(巡查时间:${skkstime} - ${skjstime})`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 将时间字符串转换为分钟数,便于比较
|
||||||
|
const timeToMinutes = (timeStr: string) => {
|
||||||
|
if (!timeStr || !timeStr.includes(':')) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const parts = timeStr.split(':');
|
||||||
|
if (parts.length !== 3) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const hours = parseInt(parts[0], 10) || 0;
|
||||||
|
const minutes = parseInt(parts[1], 10) || 0;
|
||||||
|
const seconds = parseInt(parts[2], 10) || 0;
|
||||||
|
|
||||||
|
return hours * 60 + minutes + seconds / 60;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 提交数据
|
// 提交数据
|
||||||
@ -531,11 +569,12 @@ const submit = async () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查巡查时间
|
// 重新检查巡查时间(防止时间在页面加载后发生变化)
|
||||||
const { xcFlag, msg } = checkInspectionTime();
|
checkInspectionTime();
|
||||||
if (!xcFlag) {
|
|
||||||
|
if (!canInspect.value) {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: msg,
|
title: inspectionStatusText.value,
|
||||||
icon: "none",
|
icon: "none",
|
||||||
duration: 2000,
|
duration: 2000,
|
||||||
});
|
});
|
||||||
@ -642,6 +681,7 @@ const getVideoUrls = () => {
|
|||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await loadRollCallData(); // 加载点名数据
|
await loadRollCallData(); // 加载点名数据
|
||||||
await loadCheckItems(); // 加载巡查项目
|
await loadCheckItems(); // 加载巡查项目
|
||||||
|
checkInspectionTime(); // 检查巡查时间
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -696,6 +736,48 @@ onMounted(async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.inspection-time-info {
|
||||||
|
margin-top: 15px;
|
||||||
|
padding: 10px 15px;
|
||||||
|
background-color: #f0f8ff;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #d6e4ff;
|
||||||
|
|
||||||
|
.time-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.time-label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-value {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #4080ff;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.inspection-status {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 15px;
|
||||||
|
padding: 10px 15px;
|
||||||
|
background-color: #fffbe6;
|
||||||
|
border: 1px solid #ffe58f;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: #faad14;
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
|
.status-text {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.teacher-selection-info {
|
.teacher-selection-info {
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
padding: 10px 15px;
|
padding: 10px 15px;
|
||||||
|
|||||||
273
src/pages/view/rw/detail.vue
Normal file
273
src/pages/view/rw/detail.vue
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
<!-- src/pages/base/message/detail.vue -->
|
||||||
|
<template>
|
||||||
|
<view class="message-detail-page">
|
||||||
|
<view v-if="isLoading" class="loading-indicator">加载中...</view>
|
||||||
|
<view v-else class="detail-content">
|
||||||
|
<view class="detail-header">
|
||||||
|
<view class="title-tag-row">
|
||||||
|
<text class="detail-title">{{ rw.rwmc }}</text>
|
||||||
|
<view class="tag" :class="rw.tagType">{{ rw.tagText }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="detail-meta">
|
||||||
|
<text>{{ rw.rwkstime }}</text>
|
||||||
|
<!-- <text>{{ messageDetail.timeAgo }}</text>-->
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="detail-body">
|
||||||
|
<BasicForm :schema="schema" v-model="formData">
|
||||||
|
|
||||||
|
</BasicForm>
|
||||||
|
</view>
|
||||||
|
<view class="detail-footer" v-if="rwzxqds.length==0">
|
||||||
|
<button type="primary" class="action-button" @click="saveRwZx">处理</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- <view v-else class="empty-state">消息详情未找到</view>-->
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {ref} from 'vue';
|
||||||
|
import {onLoad} from '@dcloudio/uni-app';
|
||||||
|
import {rwFindInfoByRwId, rwflFindRwlxsByRwId, rwzxExecutedInfoByRwIdAndJsApi, rwzxSaveApi} from "@/api/base/server";
|
||||||
|
import {useForm} from "@/components/BasicForm/hooks/useForm";
|
||||||
|
import {navigateBack, showToast} from "@/utils/uniapp";
|
||||||
|
import {useUserStore} from "@/store/modules/user";
|
||||||
|
|
||||||
|
interface MessageDetail {
|
||||||
|
id: string; // Assuming an ID is passed or can be derived
|
||||||
|
title: string;
|
||||||
|
desc: string;
|
||||||
|
date: string;
|
||||||
|
timeAgo: string;
|
||||||
|
tagText: string;
|
||||||
|
tagType: string;
|
||||||
|
// Add other fields as necessary
|
||||||
|
}
|
||||||
|
|
||||||
|
const formData: any = ref({})
|
||||||
|
const messageId = ref<string>('');
|
||||||
|
const messageDetail = ref<MessageDetail | null>({
|
||||||
|
id: 'todo1',
|
||||||
|
title: '教务通知 (待办)',
|
||||||
|
desc: '学校召开期初教学准备会议暨首次教学工作例会. 会议强调了新学期的教学重点和要求,请各位老师认真准备。',
|
||||||
|
date: '2025-02-17',
|
||||||
|
timeAgo: '8 mins 前',
|
||||||
|
tagText: '通知',
|
||||||
|
tagType: 'notice',
|
||||||
|
likes: 6,
|
||||||
|
comments: 12
|
||||||
|
});
|
||||||
|
const isLoading = ref(false);
|
||||||
|
const rwflx: any = ref([])
|
||||||
|
const rw = ref({})
|
||||||
|
const schema = reactive<FormsSchema[]>([])
|
||||||
|
const {getUser} = useUserStore()
|
||||||
|
|
||||||
|
async function saveRwZx() {
|
||||||
|
const result = [];
|
||||||
|
for (let i = 0; i < rwflx.value.length; i++) {
|
||||||
|
console.log(44, rwflx.value[i].id, formData.value[rwflx.value[i].id])
|
||||||
|
if (rwflx.value[i].rwbs && (!formData.value[rwflx.value[i].id] || formData.value[rwflx.value[i].id] == "")) {
|
||||||
|
showToast("请填写必填项!")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
result.push({
|
||||||
|
rwlxId: rwflx.value[i].id,
|
||||||
|
rwzxqdtx: formData.value[rwflx.value[i].id],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
await rwzxSaveApi({
|
||||||
|
mobile: getUser.mobile,
|
||||||
|
rwId: rw.value.id,
|
||||||
|
rwzxqdDtos: result
|
||||||
|
})
|
||||||
|
showToast("操作成功!");
|
||||||
|
uni.navigateBack({delta: 1})
|
||||||
|
}
|
||||||
|
|
||||||
|
const rwzxqds = ref([])
|
||||||
|
onLoad(async (options) => {
|
||||||
|
if (options && options.id) {
|
||||||
|
const {result} = await rwFindInfoByRwId({
|
||||||
|
rwId: options.id
|
||||||
|
});
|
||||||
|
rwflx.value = result.rwlxes;
|
||||||
|
rw.value = result;
|
||||||
|
for (let i = 0; i < rwflx.value.length; i++) {
|
||||||
|
if (rwflx.value[i].rwfl == "sctp" || rwflx.value[i].rwfl == "scsp" || rwflx.value[i].rwfl == "scwd") {
|
||||||
|
schema.push({
|
||||||
|
field: `${rwflx.value[i].id}`,
|
||||||
|
label: `${rwflx.value[i].rwbt}`,
|
||||||
|
component: "BasicUpload",
|
||||||
|
required: rwflx.value[i].rwbs,
|
||||||
|
componentProps: {}
|
||||||
|
})
|
||||||
|
} else if (rwflx.value[i].rwfl == "text") {
|
||||||
|
schema.push({
|
||||||
|
field: `${rwflx.value[i].id}`,
|
||||||
|
label: `${rwflx.value[i].rwbt}`,
|
||||||
|
component: "BasicInput",
|
||||||
|
required: rwflx.value[i].rwbs,
|
||||||
|
itemProps: {
|
||||||
|
labelPosition: "top",
|
||||||
|
},
|
||||||
|
componentProps: {
|
||||||
|
type: "textarea",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} else if (rwflx.value[i].rwfl == "dxsx" || rwflx.value[i].rwfl == "dxxz") {
|
||||||
|
let options = rwflx.value[i].remark.split(";");
|
||||||
|
let range = [];
|
||||||
|
for (let i = 0; i < options.length; i++) {
|
||||||
|
range.push({
|
||||||
|
name: options[i]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
schema.push({
|
||||||
|
field: `${rwflx.value[i].id}`,
|
||||||
|
label: `${rwflx.value[i].rwbt}`,
|
||||||
|
component: "BasicPicker",
|
||||||
|
required: rwflx.value[i].rwbs,
|
||||||
|
itemProps: {
|
||||||
|
labelPosition: "top",
|
||||||
|
},
|
||||||
|
componentProps: {
|
||||||
|
range: range,
|
||||||
|
rangeKey: "name",
|
||||||
|
savaKey: "name",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const res = await rwzxExecutedInfoByRwIdAndJsApi({
|
||||||
|
rwId: options.id,
|
||||||
|
mobile: getUser.mobile
|
||||||
|
});
|
||||||
|
if (res && res.result && res.result.length) {
|
||||||
|
rwzxqds.value = res.result;
|
||||||
|
const showData = {};
|
||||||
|
for (let i = 0; i < rwzxqds.value.length; i++) {
|
||||||
|
showData[rwzxqds.value[i].rwlxId] = rwzxqds.value[i].rwzxqdtx;
|
||||||
|
}
|
||||||
|
formData.value = showData;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error('Message ID/Data is missing!');
|
||||||
|
uni.showToast({title: '加载失败,缺少信息', icon: 'none'});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.message-detail-page {
|
||||||
|
background-color: #f4f5f7;
|
||||||
|
min-height: 100vh;
|
||||||
|
padding: 15px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-indicator,
|
||||||
|
.empty-state {
|
||||||
|
text-align: center;
|
||||||
|
color: #999;
|
||||||
|
padding: 40px 15px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-content {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 20px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-header {
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
padding-bottom: 15px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
.title-tag-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: flex-start; // Align items to the top
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
flex: 1; // Allow title to take available space
|
||||||
|
margin-right: 10px; // Space between title and tag
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag { // Reuse tag styles from index page if possible, or define here
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #ffffff;
|
||||||
|
white-space: nowrap;
|
||||||
|
flex-shrink: 0; // Prevent tag from shrinking
|
||||||
|
|
||||||
|
&.notice {
|
||||||
|
background-color: #447ade;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.task {
|
||||||
|
background-color: #19be6b;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.approval {
|
||||||
|
background-color: #ff9f0a;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.submit {
|
||||||
|
background-color: #8e8e93;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.detail-meta {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
|
||||||
|
text {
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-body {
|
||||||
|
margin-bottom: 40px;
|
||||||
|
|
||||||
|
.detail-desc {
|
||||||
|
font-size: 15px;
|
||||||
|
color: #555;
|
||||||
|
line-height: 1.7;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-footer {
|
||||||
|
// text-align: center; // Removed center alignment
|
||||||
|
// Add margin if needed, e.g., margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Style for the action button
|
||||||
|
.action-button {
|
||||||
|
width: 100%; // Make button full width
|
||||||
|
height: 44px; // Standard button height
|
||||||
|
line-height: 44px; // Match height for vertical centering
|
||||||
|
font-size: 16px; // Slightly larger font
|
||||||
|
font-weight: 500; // Medium weight
|
||||||
|
border-radius: 8px; // Consistent border radius
|
||||||
|
margin-top: 20px; // Add space above the button
|
||||||
|
// Ensure primary color is applied correctly (uni-app default should work)
|
||||||
|
// background-color: #447ade;
|
||||||
|
// color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
273
src/pages/view/rw/index.vue
Normal file
273
src/pages/view/rw/index.vue
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
<!-- src/pages/base/message/detail.vue -->
|
||||||
|
<template>
|
||||||
|
<view class="message-detail-page">
|
||||||
|
<view v-if="isLoading" class="loading-indicator">加载中...</view>
|
||||||
|
<view v-else class="detail-content">
|
||||||
|
<view class="detail-header">
|
||||||
|
<view class="title-tag-row">
|
||||||
|
<text class="detail-title">{{ rw.rwmc }}</text>
|
||||||
|
<view class="tag" :class="rw.tagType">{{ rw.tagText }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="detail-meta">
|
||||||
|
<text>{{ rw.rwkstime }}</text>
|
||||||
|
<!-- <text>{{ messageDetail.timeAgo }}</text>-->
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="detail-body">
|
||||||
|
<BasicForm :schema="schema" v-model="formData">
|
||||||
|
|
||||||
|
</BasicForm>
|
||||||
|
</view>
|
||||||
|
<view class="detail-footer" v-if="rwzxqds.length==0">
|
||||||
|
<button type="primary" class="action-button" @click="saveRwZx">处理</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- <view v-else class="empty-state">消息详情未找到</view>-->
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {ref} from 'vue';
|
||||||
|
import {onLoad} from '@dcloudio/uni-app';
|
||||||
|
import {rwFindInfoByRwId, rwflFindRwlxsByRwId, rwzxExecutedInfoByRwIdAndJsApi, rwzxSaveApi} from "@/api/base/server";
|
||||||
|
import {useForm} from "@/components/BasicForm/hooks/useForm";
|
||||||
|
import {navigateBack, showToast} from "@/utils/uniapp";
|
||||||
|
import {useUserStore} from "@/store/modules/user";
|
||||||
|
|
||||||
|
interface MessageDetail {
|
||||||
|
id: string; // Assuming an ID is passed or can be derived
|
||||||
|
title: string;
|
||||||
|
desc: string;
|
||||||
|
date: string;
|
||||||
|
timeAgo: string;
|
||||||
|
tagText: string;
|
||||||
|
tagType: string;
|
||||||
|
// Add other fields as necessary
|
||||||
|
}
|
||||||
|
|
||||||
|
const formData: any = ref({})
|
||||||
|
const messageId = ref<string>('');
|
||||||
|
const messageDetail = ref<MessageDetail | null>({
|
||||||
|
id: 'todo1',
|
||||||
|
title: '教务通知 (待办)',
|
||||||
|
desc: '学校召开期初教学准备会议暨首次教学工作例会. 会议强调了新学期的教学重点和要求,请各位老师认真准备。',
|
||||||
|
date: '2025-02-17',
|
||||||
|
timeAgo: '8 mins 前',
|
||||||
|
tagText: '通知',
|
||||||
|
tagType: 'notice',
|
||||||
|
likes: 6,
|
||||||
|
comments: 12
|
||||||
|
});
|
||||||
|
const isLoading = ref(false);
|
||||||
|
const rwflx: any = ref([])
|
||||||
|
const rw = ref({})
|
||||||
|
const schema = reactive<FormsSchema[]>([])
|
||||||
|
const {getUser} = useUserStore()
|
||||||
|
|
||||||
|
async function saveRwZx() {
|
||||||
|
const result = [];
|
||||||
|
for (let i = 0; i < rwflx.value.length; i++) {
|
||||||
|
console.log(44, rwflx.value[i].id, formData.value[rwflx.value[i].id])
|
||||||
|
if (rwflx.value[i].rwbs && (!formData.value[rwflx.value[i].id] || formData.value[rwflx.value[i].id] == "")) {
|
||||||
|
showToast("请填写必填项!")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
result.push({
|
||||||
|
rwlxId: rwflx.value[i].id,
|
||||||
|
rwzxqdtx: formData.value[rwflx.value[i].id],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
await rwzxSaveApi({
|
||||||
|
mobile: getUser.mobile,
|
||||||
|
rwId: rw.value.id,
|
||||||
|
rwzxqdDtos: result
|
||||||
|
})
|
||||||
|
showToast("操作成功!");
|
||||||
|
uni.navigateBack({delta: 1})
|
||||||
|
}
|
||||||
|
|
||||||
|
const rwzxqds = ref([])
|
||||||
|
onLoad(async (options) => {
|
||||||
|
if (options && options.id) {
|
||||||
|
const {result} = await rwFindInfoByRwId({
|
||||||
|
rwId: options.id
|
||||||
|
});
|
||||||
|
rwflx.value = result.rwlxes;
|
||||||
|
rw.value = result;
|
||||||
|
for (let i = 0; i < rwflx.value.length; i++) {
|
||||||
|
if (rwflx.value[i].rwfl == "sctp" || rwflx.value[i].rwfl == "scsp" || rwflx.value[i].rwfl == "scwd") {
|
||||||
|
schema.push({
|
||||||
|
field: `${rwflx.value[i].id}`,
|
||||||
|
label: `${rwflx.value[i].rwbt}`,
|
||||||
|
component: "BasicUpload",
|
||||||
|
required: rwflx.value[i].rwbs,
|
||||||
|
componentProps: {}
|
||||||
|
})
|
||||||
|
} else if (rwflx.value[i].rwfl == "text") {
|
||||||
|
schema.push({
|
||||||
|
field: `${rwflx.value[i].id}`,
|
||||||
|
label: `${rwflx.value[i].rwbt}`,
|
||||||
|
component: "BasicInput",
|
||||||
|
required: rwflx.value[i].rwbs,
|
||||||
|
itemProps: {
|
||||||
|
labelPosition: "top",
|
||||||
|
},
|
||||||
|
componentProps: {
|
||||||
|
type: "textarea",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} else if (rwflx.value[i].rwfl == "dxsx" || rwflx.value[i].rwfl == "dxxz") {
|
||||||
|
let options = rwflx.value[i].remark.split(";");
|
||||||
|
let range = [];
|
||||||
|
for (let i = 0; i < options.length; i++) {
|
||||||
|
range.push({
|
||||||
|
name: options[i]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
schema.push({
|
||||||
|
field: `${rwflx.value[i].id}`,
|
||||||
|
label: `${rwflx.value[i].rwbt}`,
|
||||||
|
component: "BasicPicker",
|
||||||
|
required: rwflx.value[i].rwbs,
|
||||||
|
itemProps: {
|
||||||
|
labelPosition: "top",
|
||||||
|
},
|
||||||
|
componentProps: {
|
||||||
|
range: range,
|
||||||
|
rangeKey: "name",
|
||||||
|
savaKey: "name",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const res = await rwzxExecutedInfoByRwIdAndJsApi({
|
||||||
|
rwId: options.id,
|
||||||
|
mobile: getUser.mobile
|
||||||
|
});
|
||||||
|
if (res && res.result && res.result.length) {
|
||||||
|
rwzxqds.value = res.result;
|
||||||
|
const showData = {};
|
||||||
|
for (let i = 0; i < rwzxqds.value.length; i++) {
|
||||||
|
showData[rwzxqds.value[i].rwlxId] = rwzxqds.value[i].rwzxqdtx;
|
||||||
|
}
|
||||||
|
formData.value = showData;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error('Message ID/Data is missing!');
|
||||||
|
uni.showToast({title: '加载失败,缺少信息', icon: 'none'});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.message-detail-page {
|
||||||
|
background-color: #f4f5f7;
|
||||||
|
min-height: 100vh;
|
||||||
|
padding: 15px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-indicator,
|
||||||
|
.empty-state {
|
||||||
|
text-align: center;
|
||||||
|
color: #999;
|
||||||
|
padding: 40px 15px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-content {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 20px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-header {
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
padding-bottom: 15px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
.title-tag-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: flex-start; // Align items to the top
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
flex: 1; // Allow title to take available space
|
||||||
|
margin-right: 10px; // Space between title and tag
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag { // Reuse tag styles from index page if possible, or define here
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #ffffff;
|
||||||
|
white-space: nowrap;
|
||||||
|
flex-shrink: 0; // Prevent tag from shrinking
|
||||||
|
|
||||||
|
&.notice {
|
||||||
|
background-color: #447ade;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.task {
|
||||||
|
background-color: #19be6b;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.approval {
|
||||||
|
background-color: #ff9f0a;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.submit {
|
||||||
|
background-color: #8e8e93;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.detail-meta {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
|
||||||
|
text {
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-body {
|
||||||
|
margin-bottom: 40px;
|
||||||
|
|
||||||
|
.detail-desc {
|
||||||
|
font-size: 15px;
|
||||||
|
color: #555;
|
||||||
|
line-height: 1.7;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-footer {
|
||||||
|
// text-align: center; // Removed center alignment
|
||||||
|
// Add margin if needed, e.g., margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Style for the action button
|
||||||
|
.action-button {
|
||||||
|
width: 100%; // Make button full width
|
||||||
|
height: 44px; // Standard button height
|
||||||
|
line-height: 44px; // Match height for vertical centering
|
||||||
|
font-size: 16px; // Slightly larger font
|
||||||
|
font-weight: 500; // Medium weight
|
||||||
|
border-radius: 8px; // Consistent border radius
|
||||||
|
margin-top: 20px; // Add space above the button
|
||||||
|
// Ensure primary color is applied correctly (uni-app default should work)
|
||||||
|
// background-color: #447ade;
|
||||||
|
// color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
BIN
src/static/base/home/jltj.png
Normal file
BIN
src/static/base/home/jltj.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
Loading…
x
Reference in New Issue
Block a user