staging #23

Merged
hy merged 38 commits from staging into master 2025-10-14 11:13:16 +08:00
13 changed files with 305 additions and 129 deletions
Showing only changes of commit cf856c98f7 - Show all commits

View File

@ -286,24 +286,39 @@ export interface ConditionalModel {
}
/** 搜索条件 */
export interface SearchConditions {
export class SearchConditions {
/**
*
*/
constructor() {
this.show = true;
this.showPage = true;
this.PageIndex = 0;
this.PageSize = 20;
this.OrderBy = "Id";
this.OrderByType = 1;
this.defaultConditions = [];
this.Conditions = [];
}
/** 是否显示搜索 */
show: boolean;
show?: boolean;
/** 显示分页器 */
showPage?:boolean;
/** 当前页码 */
PageIndex: number;
PageIndex?: number;
/** 每页大小 */
PageSize: number;
PageSize?: number;
/** 排序字段 */
OrderBy: string;
OrderBy?: string;
/**
* @tips 0:升序 1:降序
* @默认 = 1
*/
OrderByType?: 0 | 1;
/** 默认查询条件 */
defaultConditions: ConditionalModel[];
defaultConditions?: ConditionalModel[];
/** 查询条件 */
Conditions: any[];
Conditions?: any[];
}
/** 表格配置 */
@ -345,6 +360,9 @@ export function intTableData(tValue: TableConfig): TableConfig {
if (!tValue.pageData) tValue.pageData = { total: 0 };
if (tValue.operationTop === undefined) tValue.operationTop = true;
//分页查询配置
tValue.search= { ...new SearchConditions(), ...tValue.search };
// 处理 column 的属性
for (const key in tValue.column) {
tValue.column[key] = { ...new TableColumn(), ...tValue.column[key] };

View File

@ -429,39 +429,6 @@ function fetchPagedData() {
<el-button type="default" @click="searchReload()">重置</el-button>
</el-form-item>
</el-form>
<div class="dialog-container">
<el-dialog
v-if="dialog.visible"
v-model="dialog.visible"
:class="dialog.title ? '' : 'noHeader'"
:title="dialog.title"
:width="dialog.width"
:close-on-click-modal="false"
:close-on-press-escape="dialog.close"
:before-close="tableClose"
append-to-body
>
<hTableEdit
v-if="dialog.edit.visible"
:id="dialog.edit.id"
:tableData="table"
:row="dialog.edit.row"
:tagData="dialog.edit.tagData"
@handlePagedCallback="handleAddCallback"
/>
<component
:is="dialog.custom.component"
v-if="dialog.custom.visible"
:style="{ height: 'calc( ' + dialog.custom.height + ' - 84px )' }"
:iscomponent="true"
:custom="dialog.custom.custom"
:CancelCallback="handleAddCallback"
:data="dialog.custom.data"
@handlePagedCallback="handleAddCallback"
/>
</el-dialog>
</div>
</div>
<div v-if="table.operationTop" class="toolbar-container">
@ -484,7 +451,6 @@ function fetchPagedData() {
:data="table.data"
:border="table.border"
:highlight-current-row="true"
style="width: 100%"
:row-key="rowKeyFun"
@selection-change="handleSelectionChange"
@sort-change="sortChange"
@ -563,6 +529,7 @@ function fetchPagedData() {
</el-table-column>
</el-table>
<div
v-if="table.search.showPage"
style="
padding-top: 15px;
display: flex;
@ -580,6 +547,40 @@ function fetchPagedData() {
@current-change="pageIndexChange"
/>
</div>
<div class="dialog-container">
<el-dialog
v-if="dialog.visible"
v-model="dialog.visible"
:class="dialog.title ? '' : 'noHeader'"
:title="dialog.title"
:width="dialog.width"
:close-on-click-modal="false"
:close-on-press-escape="dialog.close"
:before-close="tableClose"
class="max-w-[95vw] overflow-x-auto"
append-to-body
>
<hTableEdit
v-if="dialog.edit.visible"
:id="dialog.edit.id"
:tableData="table"
:row="dialog.edit.row"
:tagData="dialog.edit.tagData"
@handlePagedCallback="handleAddCallback"
/>
<component
:is="dialog.custom.component"
v-if="dialog.custom.visible"
:style="{ height: 'calc( ' + dialog.custom.height + ' - 84px )' }"
:iscomponent="true"
:custom="dialog.custom.custom"
:CancelCallback="handleAddCallback"
:data="dialog.custom.data"
@handlePagedCallback="handleAddCallback"
/>
</el-dialog>
</div>
</div>
</template>

View File

@ -86,6 +86,7 @@ const tableData: TableConfig = intTableData({
grade: {
label: "年级",
width: "100px",
custom: (row) => row.gradeLevel + row.gradeYear + "届",
search: new TableColumnSearch(true),
},
className: {

View File

@ -31,12 +31,7 @@ const tableData: TableConfig = intTableData({
search: {
//
show: true,
PageIndex: 0,
PageSize: 20,
OrderBy: "Id", //
OrderByType: 1, //
defaultConditions: [], //
Conditions: [],
PageSize: 999,
},
operationColumn: true, //
operationColumnData: [
@ -47,7 +42,7 @@ const tableData: TableConfig = intTableData({
btnType: "custom",
btnStyle: "primary",
custom: {
title: "考试学生班级详情", // title
title: "考试班级详情", // title
src: "exam/classExamRecord", //
width: "1600px", //
height: "800px", //
@ -64,6 +59,7 @@ const tableData: TableConfig = intTableData({
grade: {
label: "年级",
width: "120px",
custom: (row) => row.gradeLevel + row.gradeYear + "届",
search: new TableColumnSearch(true),
},
className: {
@ -90,7 +86,6 @@ const tableData: TableConfig = intTableData({
},
onLineRanking: {
label: "重本率排名",
width: "100px",
},
},
data: [],

View File

@ -36,7 +36,7 @@ const tableData: TableConfig = intTableData({
//
show: true,
PageIndex: 0,
PageSize: 20,
PageSize: 999,
OrderByType: 1, //
OrderBy: "Id", //
defaultConditions: [
@ -85,7 +85,8 @@ const tableData: TableConfig = intTableData({
},
grade: {
label: "年级",
width: "60px",
width: "90px",
custom: (row) => row.gradeLevel + row.gradeYear + "届",
search: new TableColumnSearch(true),
},
@ -104,24 +105,23 @@ const tableData: TableConfig = intTableData({
},
maxScore: {
label: "最高分[赋分]",
width: "140px",
width: "130px",
},
minScore: {
label: "最低分[赋分]",
width: "140px",
width: "130px",
},
average: {
label: "总平均分[赋分]",
custom: (row) => `${Math.round(row.average)}`,
width: "140px",
width: "130px",
},
average1: {
label: "资源校平均分[赋分]",
width: "160px",
width: "100px",
},
averageRank: {
label: "总平均分排名",
width: "110px",
},
rank: {
label: "远端平均/资源校平均",

View File

@ -110,14 +110,27 @@ const tableData: TableConfig = intTableData({
rules: ruleRequired,
},
},
grade: {
gradeLevel: {
label: "年级",
width: "100px",
type: "dropdown",
custom: (row) => row.gradeLevel + row.gradeYear + "届",
search: new TableColumnSearch(true),
edit: {
add: true,
edit: false,
rules: ruleRequiredGrade,
rules: ruleRequired,
},
},
gradeYear: {
label: "毕业年份",
width: "100px",
show: false,
search: new TableColumnSearch(true),
edit: {
add: true,
edit: false,
rules: ruleRequiredNumber,
},
},
testPaperType: {
@ -162,7 +175,7 @@ const tableData: TableConfig = intTableData({
},
startTime: {
label: "考试时间",
width: "210px",
width: "180px",
type: "datetime",
custom: (row) => row.startTime?.replace("T", " ").substring(0, 10) ?? "",
search: new TableColumnSearch(true),
@ -197,7 +210,8 @@ const showTable = ref(false);
onMounted(async () => {
//
// tableData.column.level.setting.datasource = (await getenum("GradeEnum")).data;
tableData.column.gradeLevel.setting.datasource =
(await getenum("GradeLevelEnum")).data.map(s=>{return {value : s.text,text:s.text}});
tableData.column.testPaperType.setting.datasource = (
await getenum("TestPaperTypeEnum")

View File

@ -31,8 +31,8 @@ const tableData: TableConfig = intTableData({
search: {
//
show: true,
PageIndex: 0,
PageSize: 60,
showPage: false,
PageSize: 9999,
OrderBy: "AssignRanking", //
OrderByType: 0,
defaultConditions: [
@ -153,7 +153,7 @@ const exam = props.data[0];
<div>
<div class="p-[10px] text-[1.5rem]">
<strong>学校</strong>{{ exam.schoolName }}&nbsp;&nbsp; <strong>年级</strong
>{{ exam.gradeLevel + exam.gradeYear }}&nbsp;&nbsp; <strong>班级</strong
>{{ exam.gradeLevel + exam.gradeYear }}&nbsp;&nbsp; <strong>班级</strong
>{{ exam.className }}&nbsp;&nbsp; <strong>考试名称</strong
>{{ exam.examName }}&nbsp;&nbsp;
<!-- <strong>考试类型</strong>{{exam.className}}&nbsp;&nbsp;

View File

@ -32,8 +32,9 @@ const tableData: TableConfig = intTableData({
search: {
//
show: true,
showPage:false,
PageIndex: 0,
PageSize: 999,
PageSize: 9999,
OrderBy: "Id", //
OrderByType: 1,
defaultConditions: [

View File

@ -109,7 +109,9 @@
<div class="subjectTagEnableDiv">
<el-tag v-if="position.enable === false" type="info">已禁用</el-tag>
<el-tag>{{ position.schoolName || "-" }}</el-tag>
<el-tag type="success">{{ position.grade || "-" }}</el-tag>
<el-tag type="success">{{
position.graduationYear ? position.graduationYear + "届" : "-"
}}</el-tag>
<el-tag type="primary" class="classTag">{{
position.className || "-"
}}</el-tag>

View File

@ -159,7 +159,7 @@
<el-table-column prop="studentId" label="职务" width="120" />
<el-table-column label="任教信息">
<el-table-column label="任教信息" min-width="500">
<template #default="scope">
<div
v-for="(position, index) in scope.row.positions"
@ -171,7 +171,6 @@
<el-tag type="info">{{
position.graduationYear ? position.graduationYear + "届" : "-"
}}</el-tag>
<el-tag type="info">{{ position.grade || "-" }}</el-tag>
<el-tag type="info">{{ position.className || "-" }}</el-tag>
<el-tag type="info">{{ position.subjectName || "-" }}</el-tag>
<el-tag type="info">{{ position.name || "-" }}</el-tag>

View File

@ -28,8 +28,13 @@
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="年级" prop="baseInfo.grade">
<el-select v-model="form.baseInfo.grade" placeholder="请选择年级" clearable>
<el-form-item label="年级" prop="baseInfo.gradeLevel">
<el-select
v-model="form.baseInfo.gradeLevel"
placeholder="请年级"
clearable
style="width: 120px"
>
<el-option
v-for="g in gradeOptions"
:key="g.value"
@ -37,6 +42,12 @@
:value="g.value"
/>
</el-select>
<el-input-number
style="width: 120px"
v-model="form.baseInfo.gradeYear"
:min="2020"
:max="2100"
/>
</el-form-item>
</el-col>
<el-col :span="12">
@ -69,6 +80,25 @@
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="预计解决时间" prop="baseInfo.endTime">
<el-date-picker
v-model="form.baseInfo.endTime"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选预计解决时间"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<div>
提示:到期前<span class="text-yellow-500">{3}</span>会黄色警告, 小于<span
class="text-red-500"
>{1}</span
>红色警告
</div>
</el-col>
</el-row>
<el-divider>基础工作</el-divider>
@ -198,13 +228,11 @@ const getSchoolBusinessPeopleList = () => {
};
getSchoolDataFn();
getSchoolBusinessPeopleList();
const gradeOptions = [
{ label: "初一", value: "初一" },
{ label: "初二", value: "初二" },
{ label: "初三", value: "初三" },
{ label: "高一", value: "高一" },
{ label: "高二", value: "高二" },
{ label: "高三", value: "高三" },
{ label: "高", value: "高" },
{ label: "初", value: "初" },
{ label: "小", value: "小" },
];
type FeedbackKey = "leaders" | "classroom" | "equipment" | "students" | "others";
@ -215,8 +243,10 @@ interface FeedbackItem {
interface FormModel {
baseInfo: {
school?: string;
grade?: string;
gradeYear?: number;
gradeLevel?: string;
date?: string;
endTime?: string;
people: string[];
};
work: {
@ -231,7 +261,8 @@ interface FormModel {
const form = reactive<FormModel>({
baseInfo: {
school: undefined,
grade: undefined,
gradeLevel: "高",
gradeYear: 2025,
date: undefined,
people: [],
},
@ -263,7 +294,7 @@ watch(
);
const rules: FormRules = {
"baseInfo.school": [{ required: true, message: "请选择学校", trigger: "change" }],
"baseInfo.grade": [{ required: true, message: "请选择年级", trigger: "change" }],
"baseInfo.gradeLevel": [{ required: true, message: "请选择年级", trigger: "change" }],
"baseInfo.date": [{ required: true, message: "请选择赴校时间", trigger: "change" }],
"baseInfo.people": [
{ required: true, message: "请选择赴校人员", trigger: "change" },
@ -412,9 +443,9 @@ async function onSubmit() {
id: 0, //id0
schoolId: form.baseInfo.school,
schoolName: schoolOptions.value.find((i) => i.value == form.baseInfo.school).label,
grade: form.baseInfo.grade,
//
gradeLevel: "",
gradeLevel: form.baseInfo.gradeLevel,
gradeYear: form.baseInfo.gradeYear,
schoolBusinessUser: form.baseInfo.people,
startTime: form.baseInfo.date,
isDiscussion: form.work.talk,
@ -445,7 +476,7 @@ async function onSubmit() {
function resetForm() {
form.baseInfo.school = undefined;
form.baseInfo.grade = undefined;
form.baseInfo.gradeLevel = undefined;
form.baseInfo.date = undefined;
form.baseInfo.people = [];
form.work.talk = false;

View File

@ -29,7 +29,7 @@
{{ safeDetail.schoolName || safeDetail.school || "-" }}
</el-descriptions-item>
<el-descriptions-item label="年级">
{{ safeDetail.grade || safeDetail.gradeLevel || "-" }}
{{ safeDetail.gradeLevel + safeDetail.gradeYear }}
</el-descriptions-item>
<el-descriptions-item label="赴校人员">
{{
@ -41,6 +41,10 @@
<el-descriptions-item label="赴校时间">
{{ safeDetail.startTimeStr || safeDetail.startTime }}
</el-descriptions-item>
<el-descriptions-item label="预计完结时间">
{{ safeDetail.endTime != null ? safeDetail.endTime.split("T")[0] : "--" }}
</el-descriptions-item>
</el-descriptions>
<el-divider />
@ -76,34 +80,63 @@
<span> 未解决问题{{ unresolvedCount }} </span>
</div>
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
<el-tab-pane
v-for="(i, idx) in sortData(safeDetail.feedbackQuestions || [])"
:key="idx"
:label="'问题' + (idx + 1) + (i.solution ? '(✅已解决)' : '(未解决)')"
:name="idx"
>
<el-tab-pane v-for="(i, idx) in questions" :key="idx" :name="idx">
<template #label>
<span class="custom-tabs-label" :class="i.solution ? `text-[#67c23a]` : ``">
<span>问题{{ idx + 1 }}</span>
<el-icon>
<Select v-if="i.solution" />
</el-icon>
</span>
</template>
<div style="font-size: 12px; margin-bottom: 4px">
<span>问题类型</span> <span>{{ queType[i.questionType] }}</span>
</div>
<div style="padding: 10px; background-color: #f3f3f3">
{{ i.question }}
</div>
<div v-if="i.solution" style="font-size: 12px; margin-top: 10px">
<span> 解决时间{{ i.endTimeStr || i.endTime }} </span>
<div
v-for="(rec, rIdx) in i.recordArr || []"
:key="rIdx"
style="margin-top: 10px"
>
<div>
执行记录{{ rIdx + 1 }}{{ rec.operator || "" }} {{ rec.executionTimeStr }}
</div>
<div style="padding: 5px; background-color: #f3f3f3">
{{ rec.executionRecords }}
</div>
</div>
<div v-if="i.solution" style="font-size: 12px; margin-top: 20px">
<span class="text-amber-400 font-bold">
解决时间{{ i.endTimeStr || i.endTime }}
</span>
<div style="padding: 10px; background-color: #f3f3f3">
{{ i.solution }}
</div>
</div>
<div v-else class="mt-1.5">
<el-button
v-show="!isDetail"
type="text"
v-else
link
:disabled="i.solution"
style="margin-top: 5px; font-size: 12px"
class="markTitle"
@click="addQRecord(i)"
>
添加执行记录
</el-button>
<el-button
v-show="!isDetail"
link
style="margin-top: 5px; font-size: 12px"
class="markTitle"
@click="markTitle(i)"
>
标记已解决
</el-button>
</div>
</el-tab-pane>
</el-tabs>
<el-divider />
@ -128,7 +161,7 @@
<!-- 添加按钮区域 -->
<div style="margin-top: 5px; display: flex; gap: 20px">
<el-button
type="text"
link
style="margin-top: 5px; font-size: 12px"
class="markTitle"
v-show="!isDetail"
@ -139,8 +172,10 @@
<el-button
style="margin-top: 5px; font-size: 12px"
class="markTitle"
type="text"
link
v-show="!isDetail"
:disabled="unresolvedCount != 0"
title="请先解决所有问题后再添加完结情况"
@click="addFinish"
>
{{ finishRecord ? "修改完结情况" : "添加完结情况" }}
@ -160,7 +195,7 @@
border-radius: 4px;
"
>
<div style="font-weight: bold; color: #409eff">
<div style="font-weight: bold; color: #67c23a">
执行记录{{ index + 1 }}{{ record.operator }} {{ record.time }}
</div>
<div style="margin-top: 5px; white-space: pre-wrap">
@ -180,9 +215,7 @@
border: 1px solid #b3d8ff;
"
>
<div style="font-weight: bold; color: #a69400">
完结情况{{ finishRecord.time }}
</div>
<div class="text-amber-400 font-bold">完结情况{{ finishRecord.time }}</div>
<div style="margin-top: 5px; white-space: pre-wrap">
{{ finishRecord.content }}
</div>
@ -230,7 +263,7 @@
</template>
<script setup lang="ts" name="EditModal">
import { ref, reactive, computed, defineProps, defineEmits, watch } from "vue";
import { ref, reactive, computed, defineProps, defineEmits, watch, onMounted } from "vue";
import type { FormInstance, FormRules, TabsPaneContext } from "element-plus";
import { ElMessage } from "element-plus";
import { getSchoolData } from "@/api/userCenter";
@ -238,13 +271,23 @@ import { getSchoolBusinessPeopleListApi, addOrEditApi } from "@/api/toschoolinfo
import { setFips } from "crypto";
import { useUserStoreHook } from "@/store/modules/user";
import { isAllEmpty } from "@pureadmin/utils";
import { Select, CloseBold } from "@element-plus/icons-vue";
const activeName = ref<any>(0);
onMounted(() => {
console.log("onMounted ");
questions = ref(sortData(safeDetail.value.feedbackQuestions));
});
const handleClick = (tab: TabsPaneContext, event: Event) => {
console.log(tab.props.name, event);
activeName.value = tab.props.name;
};
const gradeOptions = [
{ label: "高", value: "高" },
{ label: "初", value: "初" },
{ label: "小", value: "小" },
];
const props = defineProps<{
visible: boolean;
detailData: any;
@ -305,6 +348,7 @@ const operationContentLabel = computed(() => {
case "markSolved":
return "解决情况";
case "addRecord":
case "addQRecord":
return "执行记录";
case "addFinish":
return "完结情况";
@ -345,10 +389,12 @@ const queType = {
* 获取未解决问题数量
* @param data
*/
const handleUnHandleQust = (data: Array<any>) => {
const handleUnHandleQust = (data: Array<any>): number => {
return (data || []).filter((i) => !i?.solution).length;
};
const sortData = (data: Array<any>) => {
if (data == null || data.length == 0) return [];
const categorizedData = [
...data
.filter((item) => item.questionType === 1)
@ -373,6 +419,7 @@ const statusText = computed(() => (safeDetail.value?.solutionEnd ? "已完结" :
const statusType = computed(() =>
safeDetail.value?.solutionEnd ? "success" : "warning"
);
let questions = ref(sortData(safeDetail.value.feedbackQuestions));
const solutionText = computed({
get: () => safeDetail.value?.solutionRecord?.solution || "",
set: (value: string) => {
@ -388,6 +435,7 @@ const unresolvedCount = computed(() => {
const list = (safeDetail.value?.feedbackQuestions as any[]) || [];
return list.filter((item) => !item?.solution).length;
});
const markTitle = (data: any) => {
console.log("标记已解决", data);
operationType.value = "markSolved";
@ -398,6 +446,14 @@ const markTitle = (data: any) => {
operationFormRef.value?.clearValidate();
operationDialogVisible.value = true;
};
const addQRecord = (data: any) => {
console.log("添加问题执行记录", data);
operationType.value = "addQRecord";
currentMarkedQuestion.value = data;
//
operationFormRef.value?.clearValidate();
operationDialogVisible.value = true;
};
const addRecord = () => {
console.log("添加执行记录");
operationType.value = "addRecord";
@ -433,7 +489,11 @@ const closeOperationDialog = () => {
//
currentMarkedQuestion.value = null;
};
const userName = computed(() => {
return isAllEmpty(useUserStoreHook()?.nickName)
? useUserStoreHook()?.userName
: useUserStoreHook()?.nickName;
});
const confirmOperation = async () => {
if (!operationFormRef.value) return;
@ -441,9 +501,21 @@ const confirmOperation = async () => {
await operationFormRef.value.validate();
const { operationTime, operationContent } = operationForm;
//
switch (operationType.value) {
case "addQRecord":
//
if (currentMarkedQuestion.value) {
if (currentMarkedQuestion.value.recordArr == undefined) {
currentMarkedQuestion.value.recordArr = [];
}
currentMarkedQuestion.value.recordArr.push({
executionTime: operationTime,
executionRecords: operationContent,
operator: userName.value,
});
}
break;
case "addRecord":
//
executionRecords.value.push({
@ -454,11 +526,7 @@ const confirmOperation = async () => {
if (!props.detailData.solutionRecord) props.detailData.solutionRecord = {} as any;
if (!Array.isArray(props.detailData.solutionRecord.record))
props.detailData.solutionRecord.record = [];
const userName = computed(() => {
return isAllEmpty(useUserStoreHook()?.nickName)
? useUserStoreHook()?.userName
: useUserStoreHook()?.nickName;
});
props.detailData.solutionRecord.record.push({
executionTime: operationTime,
executionRecords: operationContent,
@ -532,6 +600,14 @@ function onClickSave() {
</script>
<style scoped lang="scss">
.custom-tabs-label .el-icon {
vertical-align: middle;
}
.custom-tabs-label span {
vertical-align: middle;
margin-left: 4px;
}
.modal-header {
display: flex;
align-items: center;
@ -555,7 +631,6 @@ function onClickSave() {
}
.markTitle:hover {
text-decoration: underline;
cursor: pointer;
user-select: none;
}
</style>

View File

@ -23,7 +23,7 @@
v-model="query.grade"
placeholder="请选择年级"
clearable
style="width: 140px"
style="width: 120px"
>
<el-option
v-for="g in gradeOptions"
@ -31,7 +31,8 @@
:label="g.label"
:value="g.value"
/>
</el-select>
</el-select >
<el-input-number v-show="query.grade" v-model="query.gradeYear" :min="2020" :max="2100"/>
</el-form-item>
<el-form-item label="赴校人员">
<el-select
@ -88,7 +89,12 @@
<el-button type="info" @click="downLoadTpl">下载模版</el-button>
</div>
<!-- 表格区域 -->
<el-table :data="listData" style="width: 100%" :max-height="500">
<el-table
:data="listData"
style="width: 100%"
:max-height="500"
:row-class-name="tableRowClassName"
>
<el-table-column label="操作" width="200">
<template #default="{ row }">
<!-- <el-button size="small" type="danger" plain @click="onDelete(row)"
@ -127,9 +133,17 @@
</el-tag>
</template>
</el-table-column>
<el-table-column prop="grade" label="年级" min-width="100" />
<el-table-column label="年级" min-width="100" >
<template #default="{ row }">
{{ row.gradeLevel+row.gradeYear }}
</template>
</el-table-column>
<el-table-column prop="people" label="赴校人员" min-width="120" />
<el-table-column prop="times" label="赴校时间" min-width="140" />
<el-table-column label="赴校时间/解决时间" min-width="140">
<template #default="{ row }">
{{ row.times }}{{ row.endTime ? " / " + row.endTime : "" }}
</template>
</el-table-column>
<el-table-column prop="feedbackTotals" label="反馈问题数量" min-width="140" />
<el-table-column prop="solveTotals" label="解决问题数量" min-width="140" />
@ -155,6 +169,7 @@
<!-- 跟进 -->
<EditModal
v-model:visible="isShowEditModal"
v-if="isShowEditModal"
:editModalLoading="editModalLoading"
:detailData="detailData"
:isDetail="isDetail"
@ -187,6 +202,7 @@ interface TableItem {
people: string;
canOperate: boolean; //
times: string; // YYYY-MM-DD
endTime: string; //
feedbackTotals: number;
solveTotals: number;
solutionEnd: boolean; // true: , false:
@ -196,6 +212,20 @@ interface TableItem {
const schoolOptions = ref([]);
const peopleOptions = ref([]);
const isDetail = ref(false);
const tableRowClassName = ({ row, rowIndex }: { row: any; rowIndex: number }) => {
if (row.endTime == null || row.endTime == "" || row.solutionEnd) return "";
const nD = new Date();
const d = new Date(row.endTime + " ");
const daysDiff = Math.floor((d.getTime() - nD.getTime()) / (1000 * 60 * 60 * 24));
if (daysDiff >= 2) {
return "warning-row";
} else if (daysDiff < 2) {
return "error-row";
}
return "";
};
/**
* 获取学校下拉数据
*/
@ -236,12 +266,9 @@ onMounted(() => {
});
const gradeOptions = [
{ label: "初一", value: "初一" },
{ label: "初二", value: "初二" },
{ label: "初三", value: "初三" },
{ label: "高一", value: "高一" },
{ label: "高二", value: "高二" },
{ label: "高三", value: "高三" },
{ label: "高", value: "高" },
{ label: "初", value: "初" },
{ label: "小", value: "小" },
];
/**
* 新建赴校信息提交
@ -283,6 +310,7 @@ const addOrEdit = () => {
const query = reactive({
school: "" as string | undefined,
grade: "" as string | undefined,
gradeYear: 2025 as number ,
people: "" as string | undefined,
solutionEnd: undefined,
times: [] as string[],
@ -309,8 +337,11 @@ function mapApiItemToRow(item: any): TableItem {
id: item.id,
school: item.schoolName || "",
grade: item.grade || "",
gradeYear: item.gradeYear || "",
gradeLevel: item.gradeLevel || "",
people: peopleArr.join(""),
times: start,
endTime: item.endTime ? dayjs(item.endTime).format("YYYY-MM-DD") : "",
canOperate: item.canOperate || false, //
feedbackTotals: Number(item.feedbackCount) || 0,
solveTotals: Number(item.solveFeedbackCount) || 0,
@ -326,7 +357,7 @@ async function loadList() {
orderBy: "startTime",
};
if (query.school) payload.schoolId = query.school;
if (query.grade) payload.grade = query.grade;
if (query.grade && query.gradeYear) payload.grade = query.grade+query.gradeYear;
if (query.people) {
payload.UserName = query.people;
}
@ -401,12 +432,12 @@ function onDelete(row: TableItem) {
*/
function onDetailOrFollow(row: TableItem, disabled = false) {
isDetail.value = disabled;
isShowEditModal.value = true;
editModalLoading.value = true;
getSchoolBusinessDetailApi(row.id)
.then((res) => {
if (res.code === 200 && res.data) {
detailData.value = res.data;
isShowEditModal.value = true;
}
})
.finally(() => {
@ -504,4 +535,12 @@ function downLoadTpl() {
justify-content: center;
margin-top: 12px;
}
:deep(.el-table .warning-row) {
--el-table-tr-bg-color: rgb(253, 246, 236);
}
:deep(.el-table .error-row) {
--el-table-tr-bg-color: rgb(255, 227, 227);
}
</style>