feat: 跟进弹窗功能开发中
This commit is contained in:
parent
528dcef08c
commit
73bd653e9d
|
|
@ -47,3 +47,12 @@ export function deleteSchoolBusinessApi(data: Array<string | number>) {
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @description 获取赴校人员下拉数据
|
||||||
|
* @return {object}
|
||||||
|
*/
|
||||||
|
export function getSchoolBusinessPeopleListApi(data: object) {
|
||||||
|
return http.request<Res<any>>("post", `/Admin/QueryCombo`, {
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
v-model="dialogVisible"
|
v-model="dialogVisible"
|
||||||
title="新建赴校信息"
|
title="新建赴校信息"
|
||||||
width="800px"
|
width="800px"
|
||||||
|
@close="onCancel"
|
||||||
align-center
|
align-center
|
||||||
>
|
>
|
||||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
|
<el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
|
||||||
|
|
@ -55,10 +56,21 @@
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="赴校人员" prop="baseInfo.people">
|
<el-form-item label="赴校人员" prop="baseInfo.people">
|
||||||
<el-input
|
<el-select
|
||||||
v-model="form.baseInfo.people"
|
v-model="form.baseInfo.people"
|
||||||
placeholder="请输入人员姓名,逗号分隔"
|
placeholder="请选择赴校人员"
|
||||||
/>
|
clearable
|
||||||
|
multiple
|
||||||
|
filterable
|
||||||
|
style="width: 100%"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="p in peopleOptions"
|
||||||
|
:key="p.value"
|
||||||
|
:label="p.text"
|
||||||
|
:value="p.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
@ -150,12 +162,20 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts" name="AddModal">
|
<script setup lang="ts" name="AddModal">
|
||||||
import { ref, reactive, computed } from "vue";
|
import { ref, reactive, computed, defineProps, defineEmits, watch } from "vue";
|
||||||
import type { FormInstance, FormRules } from "element-plus";
|
import type { FormInstance, FormRules } from "element-plus";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
|
import { getSchoolData } from "@/api/userCenter";
|
||||||
|
import {
|
||||||
|
getSchoolBusinessPeopleListApi,
|
||||||
|
addOrEditApi
|
||||||
|
} from "@/api/toschoolinfomanage";
|
||||||
const props = defineProps<{ visible: boolean }>();
|
const props = defineProps<{ visible: boolean }>();
|
||||||
const emit = defineEmits<{ (e: "update:visible", value: boolean): void }>();
|
// const emit = defineEmits<{ (e: "update:visible", value: boolean): void }>();
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: "update:visible", value: boolean): void;
|
||||||
|
(e: "handleReset"): void;
|
||||||
|
}>();
|
||||||
const dialogVisible = computed({
|
const dialogVisible = computed({
|
||||||
get: () => props.visible,
|
get: () => props.visible,
|
||||||
set: v => emit("update:visible", v)
|
set: v => emit("update:visible", v)
|
||||||
|
|
@ -166,17 +186,40 @@ function uid() {
|
||||||
return Math.random().toString(36).slice(2) + Date.now().toString(36);
|
return Math.random().toString(36).slice(2) + Date.now().toString(36);
|
||||||
}
|
}
|
||||||
|
|
||||||
const schoolOptions = ref([
|
const schoolOptions = ref([]);
|
||||||
{ label: "第一中学", value: "第一中学" },
|
const peopleOptions = ref([]);
|
||||||
{ label: "第二中学", value: "第二中学" },
|
const getSchoolDataFn = () => {
|
||||||
{ label: "实验中学", value: "实验中学" },
|
getSchoolData().then(res => {
|
||||||
{ label: "外国语学校", value: "外国语学校" }
|
if (res.code == 200) {
|
||||||
]);
|
schoolOptions.value = res.data.map((i: any) => ({
|
||||||
|
label: i.text,
|
||||||
|
value: i.value
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 获取赴校人员下拉数据
|
||||||
|
*/
|
||||||
|
const getSchoolBusinessPeopleList = () => {
|
||||||
|
getSchoolBusinessPeopleListApi({}).then((res: any) => {
|
||||||
|
if (res.code == 200) {
|
||||||
|
peopleOptions.value = (res.data || []).map(i => ({
|
||||||
|
label: i.text,
|
||||||
|
value: i.text
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
getSchoolDataFn();
|
||||||
|
getSchoolBusinessPeopleList();
|
||||||
const gradeOptions = [
|
const gradeOptions = [
|
||||||
|
{ label: "初一", value: "初一" },
|
||||||
|
{ label: "初二", value: "初二" },
|
||||||
|
{ label: "初三", value: "初三" },
|
||||||
{ label: "高一", value: "高一" },
|
{ label: "高一", value: "高一" },
|
||||||
{ label: "高二", value: "高二" },
|
{ label: "高二", value: "高二" },
|
||||||
{ label: "高三", value: "高三" },
|
{ label: "高三", value: "高三" }
|
||||||
{ label: "初三", value: "初三" }
|
|
||||||
];
|
];
|
||||||
|
|
||||||
type FeedbackKey =
|
type FeedbackKey =
|
||||||
|
|
@ -194,7 +237,7 @@ interface FormModel {
|
||||||
school?: string;
|
school?: string;
|
||||||
grade?: string;
|
grade?: string;
|
||||||
date?: string;
|
date?: string;
|
||||||
people: string;
|
people: string[];
|
||||||
};
|
};
|
||||||
work: {
|
work: {
|
||||||
talk: boolean;
|
talk: boolean;
|
||||||
|
|
@ -210,7 +253,7 @@ const form = reactive<FormModel>({
|
||||||
school: undefined,
|
school: undefined,
|
||||||
grade: undefined,
|
grade: undefined,
|
||||||
date: undefined,
|
date: undefined,
|
||||||
people: ""
|
people: []
|
||||||
},
|
},
|
||||||
work: {
|
work: {
|
||||||
talk: false,
|
talk: false,
|
||||||
|
|
@ -226,7 +269,18 @@ const form = reactive<FormModel>({
|
||||||
others: []
|
others: []
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
watch(
|
||||||
|
() => form.work.talk,
|
||||||
|
val => {
|
||||||
|
!val ? (form.work.talkDetail = "") : "";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
watch(
|
||||||
|
() => form.work.classMeeting,
|
||||||
|
val => {
|
||||||
|
!val ? (form.work.classMeetingDetail = "") : "";
|
||||||
|
}
|
||||||
|
);
|
||||||
const rules: FormRules = {
|
const rules: FormRules = {
|
||||||
"baseInfo.school": [
|
"baseInfo.school": [
|
||||||
{ required: true, message: "请选择学校", trigger: "change" }
|
{ required: true, message: "请选择学校", trigger: "change" }
|
||||||
|
|
@ -238,7 +292,13 @@ const rules: FormRules = {
|
||||||
{ required: true, message: "请选择赴校时间", trigger: "change" }
|
{ required: true, message: "请选择赴校时间", trigger: "change" }
|
||||||
],
|
],
|
||||||
"baseInfo.people": [
|
"baseInfo.people": [
|
||||||
{ required: true, message: "请输入赴校人员", trigger: "blur" }
|
{ required: true, message: "请选择赴校人员", trigger: "change" },
|
||||||
|
{
|
||||||
|
type: "array",
|
||||||
|
min: 1,
|
||||||
|
message: "请至少选择一名赴校人员",
|
||||||
|
trigger: "change"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -284,8 +344,86 @@ const submitting = ref(false);
|
||||||
|
|
||||||
function onCancel() {
|
function onCancel() {
|
||||||
dialogVisible.value = false;
|
dialogVisible.value = false;
|
||||||
|
formRef.value.resetFields();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 把表单数据处理成接口需要的结构
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
const handleFeedback = (data: any) => {
|
||||||
|
const processData = (items: any[], questionType: number) => {
|
||||||
|
return items.map((item, idx) => ({
|
||||||
|
question: item.text,
|
||||||
|
questionType,
|
||||||
|
sort: (idx + 1).toString()
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
let handledData = [];
|
||||||
|
|
||||||
|
if (data.leaders.length > 0)
|
||||||
|
handledData.push(...processData(data.leaders, 1));
|
||||||
|
if (data.classroom.length > 0)
|
||||||
|
handledData.push(...processData(data.classroom, 10));
|
||||||
|
if (data.equipment.length > 0)
|
||||||
|
handledData.push(...processData(data.equipment, 15));
|
||||||
|
if (data.students.length > 0)
|
||||||
|
handledData.push(...processData(data.students, 20));
|
||||||
|
if (data.others.length > 0)
|
||||||
|
handledData.push(...processData(data.others, 999));
|
||||||
|
|
||||||
|
return handledData;
|
||||||
|
};
|
||||||
|
let editParams = {
|
||||||
|
id: 0,
|
||||||
|
schoolId: 0,
|
||||||
|
schoolName: "string",
|
||||||
|
grade: "string",
|
||||||
|
gradeYear: 0,
|
||||||
|
gradeLevel: "string",
|
||||||
|
// 赴校人员
|
||||||
|
schoolBusinessUser: ["string"],
|
||||||
|
// 赴校时间
|
||||||
|
startTime: "2025-08-19T07:20:29.292Z",
|
||||||
|
// 备注
|
||||||
|
remark: "string",
|
||||||
|
// 反馈问题
|
||||||
|
feedbackQuestions: [
|
||||||
|
{
|
||||||
|
// 问题类型
|
||||||
|
questionType: 1,
|
||||||
|
// 排序
|
||||||
|
sort: "string",
|
||||||
|
// 问题描述
|
||||||
|
question: "string",
|
||||||
|
// 解决情况
|
||||||
|
solution: "string",
|
||||||
|
// 解决时间
|
||||||
|
endTime: "2025-08-19T07:20:29.292Z"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// 解决方案记录
|
||||||
|
solutionRecord: {
|
||||||
|
// 解决方案
|
||||||
|
solution: "string",
|
||||||
|
// 完结情况
|
||||||
|
endRecord: "string",
|
||||||
|
// 完结时间
|
||||||
|
endRecordTime: "string",
|
||||||
|
record: [
|
||||||
|
{
|
||||||
|
// 执行记录
|
||||||
|
executionRecords: "string",
|
||||||
|
// 执行时间
|
||||||
|
executionTime: "2025-08-19T07:20:29.292Z"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
// 座谈情况
|
||||||
|
discussion: "string",
|
||||||
|
// 班会情况
|
||||||
|
classMeeting: "string"
|
||||||
|
};
|
||||||
async function onSubmit() {
|
async function onSubmit() {
|
||||||
if (!formRef.value) return;
|
if (!formRef.value) return;
|
||||||
await formRef.value.validate(valid => {
|
await formRef.value.validate(valid => {
|
||||||
|
|
@ -293,13 +431,47 @@ async function onSubmit() {
|
||||||
// 新增:校验反馈问题不为空
|
// 新增:校验反馈问题不为空
|
||||||
if (!validateFeedbackNotEmpty()) return;
|
if (!validateFeedbackNotEmpty()) return;
|
||||||
submitting.value = true;
|
submitting.value = true;
|
||||||
setTimeout(() => {
|
console.log("Submit payload:", form);
|
||||||
submitting.value = false;
|
// enum FeedbackQuestionTypeEnum {
|
||||||
console.log("Submit payload:", JSON.parse(JSON.stringify(form)));
|
// 学校领导班子 = 1,
|
||||||
ElMessage.success("提交成功(已使用假数据)");
|
// 双师课堂 = 10,
|
||||||
dialogVisible.value = false;
|
// 设备 = 15,
|
||||||
resetForm();
|
// 学生 = 20,
|
||||||
}, 600);
|
// 其他 = 999
|
||||||
|
// }
|
||||||
|
let reqParams = {
|
||||||
|
id: 0, //id传0代表新增
|
||||||
|
schoolId: form.baseInfo.school,
|
||||||
|
schoolName: schoolOptions.value.find(i => i.value == form.baseInfo.school)
|
||||||
|
.label,
|
||||||
|
grade: form.baseInfo.grade,
|
||||||
|
// 固定传空字符串
|
||||||
|
gradeLevel: "",
|
||||||
|
schoolBusinessUser: form.baseInfo.people,
|
||||||
|
startTime: form.baseInfo.date,
|
||||||
|
isDiscussion: form.work.talk,
|
||||||
|
discussion: form.work.talkDetail,
|
||||||
|
isClassMeeting: form.work.classMeeting,
|
||||||
|
classMeeting: form.work.classMeetingDetail,
|
||||||
|
feedbackQuestions: handleFeedback(form.feedback)
|
||||||
|
};
|
||||||
|
// return;
|
||||||
|
console.log("提交数据", reqParams);
|
||||||
|
addOrEditApi(reqParams)
|
||||||
|
.then(res => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
ElMessage.success("提交成功");
|
||||||
|
dialogVisible.value = false;
|
||||||
|
resetForm();
|
||||||
|
formRef.value.resetFields();
|
||||||
|
emit("handleReset");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
submitting.value = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// }, 600);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -307,7 +479,7 @@ function resetForm() {
|
||||||
form.baseInfo.school = undefined;
|
form.baseInfo.school = undefined;
|
||||||
form.baseInfo.grade = undefined;
|
form.baseInfo.grade = undefined;
|
||||||
form.baseInfo.date = undefined;
|
form.baseInfo.date = undefined;
|
||||||
form.baseInfo.people = "";
|
form.baseInfo.people = [];
|
||||||
form.work.talk = false;
|
form.work.talk = false;
|
||||||
form.work.talkDetail = "";
|
form.work.talkDetail = "";
|
||||||
form.work.classMeeting = false;
|
form.work.classMeeting = false;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,224 @@
|
||||||
|
<!-- 跟进 -->
|
||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
v-model="dialogVisible"
|
||||||
|
title="跟进赴校信息"
|
||||||
|
width="800px"
|
||||||
|
@close="closeModal"
|
||||||
|
align-center
|
||||||
|
>
|
||||||
|
<div class="modal-header">
|
||||||
|
<div class="status-box">
|
||||||
|
<span>当前状态:</span>
|
||||||
|
<el-tag :type="statusType">{{ statusText }}</el-tag>
|
||||||
|
</div>
|
||||||
|
<div class="action-box">
|
||||||
|
<el-button @click="onClickCancel">取消</el-button>
|
||||||
|
<el-button type="primary" @click="onClickSave">保存</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-divider />
|
||||||
|
|
||||||
|
<el-descriptions title="基础信息" :column="2" border>
|
||||||
|
<el-descriptions-item label="学校">
|
||||||
|
{{ safeDetail.schoolName || safeDetail.school || "-" }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="年级">
|
||||||
|
{{ safeDetail.grade || safeDetail.gradeLevel || "-" }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="赴校人员">
|
||||||
|
{{
|
||||||
|
Array.isArray(safeDetail.schoolBusinessUser)
|
||||||
|
? safeDetail.schoolBusinessUser.join(",")
|
||||||
|
: safeDetail.schoolBusinessUser || "-"
|
||||||
|
}}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="赴校时间">
|
||||||
|
{{ safeDetail.startTime?.split("T")[0] }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
|
||||||
|
<el-divider />
|
||||||
|
|
||||||
|
<el-descriptions title="基础工作" :column="1" border>
|
||||||
|
<el-descriptions-item label="座谈">
|
||||||
|
<el-tag
|
||||||
|
:type="safeDetail.isDiscussion ? 'success' : 'info'"
|
||||||
|
style="margin-right: 8px"
|
||||||
|
>
|
||||||
|
{{ safeDetail.isDiscussion ? "已开展" : "未开展" }}
|
||||||
|
</el-tag>
|
||||||
|
<span>{{ safeDetail.discussion || "-" }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="班会">
|
||||||
|
<el-tag
|
||||||
|
:type="safeDetail.isClassMeeting ? 'success' : 'info'"
|
||||||
|
style="margin-right: 8px"
|
||||||
|
>
|
||||||
|
{{ safeDetail.isClassMeeting ? "已开展" : "未开展" }}
|
||||||
|
</el-tag>
|
||||||
|
<span>{{ safeDetail.classMeeting || "-" }}</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
<el-divider />
|
||||||
|
<el-descriptions title="反馈问题" :column="1" border> </el-descriptions>
|
||||||
|
<div style="display: flex; gap: 40px; margin-bottom: 5px">
|
||||||
|
<span> 问题总数:{{ safeDetail.feedbackQuestions?.length }} </span>
|
||||||
|
<span>
|
||||||
|
未解决问题:{{ handleUnHandleQust(safeDetail.feedbackQuestions) }}
|
||||||
|
</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"
|
||||||
|
>
|
||||||
|
<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">
|
||||||
|
<span> 解决情况 </span>
|
||||||
|
<div style="padding: 10px; background-color: #f3f3f3">
|
||||||
|
解决情况描述111111111111111
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
style="margin-top: 5px; font-size: 12px"
|
||||||
|
class="markTitle"
|
||||||
|
@click="markTitle"
|
||||||
|
>
|
||||||
|
标记已解决
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
<el-divider />
|
||||||
|
|
||||||
|
<!-- {{ safeDetail.feedbackQuestions }} -->
|
||||||
|
<!-- .............................................................. -->
|
||||||
|
<el-descriptions title="备注" :column="1" border> </el-descriptions>
|
||||||
|
<el-input
|
||||||
|
v-model="safeDetail.remark"
|
||||||
|
:rows="4"
|
||||||
|
type="textarea"
|
||||||
|
maxlength="1000"
|
||||||
|
:show-word-limit="true"
|
||||||
|
/>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="EditModal">
|
||||||
|
import { ref, reactive, computed, defineProps, defineEmits, watch } from "vue";
|
||||||
|
import type { FormInstance, FormRules, TabsPaneContext } from "element-plus";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import { getSchoolData } from "@/api/userCenter";
|
||||||
|
import {
|
||||||
|
getSchoolBusinessPeopleListApi,
|
||||||
|
addOrEditApi
|
||||||
|
} from "@/api/toschoolinfomanage";
|
||||||
|
import { setFips } from "crypto";
|
||||||
|
|
||||||
|
const activeName = ref(0);
|
||||||
|
|
||||||
|
const handleClick = (tab: TabsPaneContext, event: Event) => {
|
||||||
|
console.log(tab, event);
|
||||||
|
};
|
||||||
|
const props = defineProps<{ visible: boolean; detailData: any }>();
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: "update:visible", value: boolean): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const dialogVisible = computed({
|
||||||
|
get: () => props.visible,
|
||||||
|
set: v => emit("update:visible", v)
|
||||||
|
});
|
||||||
|
|
||||||
|
const closeModal = () => {
|
||||||
|
emit("update:visible", false);
|
||||||
|
};
|
||||||
|
const queType = {
|
||||||
|
1: "学校领导班子",
|
||||||
|
10: "双师课堂",
|
||||||
|
15: "设备",
|
||||||
|
20: "学生",
|
||||||
|
999: "其他"
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 获取未解决问题数量
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
const handleUnHandleQust = (data: Array<any>) => {
|
||||||
|
return (data || []).map(i => {
|
||||||
|
// 利用solution为空判断为未解决问题
|
||||||
|
return !i.solution;
|
||||||
|
}).length;
|
||||||
|
};
|
||||||
|
const sortData = (data: Array<any>) => {
|
||||||
|
const categorizedData = [
|
||||||
|
...data
|
||||||
|
.filter(item => item.questionType === 1)
|
||||||
|
.sort((a, b) => a.sort.localeCompare(b.sort)),
|
||||||
|
...data
|
||||||
|
.filter(item => item.questionType === 10)
|
||||||
|
.sort((a, b) => a.sort.localeCompare(b.sort)),
|
||||||
|
...data
|
||||||
|
.filter(item => item.questionType === 15)
|
||||||
|
.sort((a, b) => a.sort.localeCompare(b.sort)),
|
||||||
|
...data
|
||||||
|
.filter(item => item.questionType === 20)
|
||||||
|
.sort((a, b) => a.sort.localeCompare(b.sort)),
|
||||||
|
...data
|
||||||
|
.filter(item => item.questionType === 999)
|
||||||
|
.sort((a, b) => a.sort.localeCompare(b.sort))
|
||||||
|
];
|
||||||
|
return categorizedData;
|
||||||
|
};
|
||||||
|
const safeDetail = computed(() => props.detailData || {});
|
||||||
|
const statusText = computed(() =>
|
||||||
|
safeDetail.value?.solutionEnd ? "已完结" : "跟进中"
|
||||||
|
);
|
||||||
|
const statusType = computed(() =>
|
||||||
|
safeDetail.value?.solutionEnd ? "success" : "warning"
|
||||||
|
);
|
||||||
|
const markTitle = () => {
|
||||||
|
console.log("标记已解决");
|
||||||
|
};
|
||||||
|
function onClickCancel() {
|
||||||
|
console.log("取消");
|
||||||
|
}
|
||||||
|
function onClickSave() {
|
||||||
|
console.log("保存");
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.modal-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.status-box {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
.action-box {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
.markTitle {
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
|
.markTitle:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -34,22 +34,31 @@
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="赴校人员">
|
<el-form-item label="赴校人员">
|
||||||
<el-input
|
<el-select
|
||||||
v-model="query.people"
|
v-model="query.people"
|
||||||
placeholder="请输入人员"
|
placeholder="请选择赴校人员"
|
||||||
clearable
|
clearable
|
||||||
style="width: 180px"
|
multiple
|
||||||
/>
|
filterable
|
||||||
|
style="width: 300px"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="p in peopleOptions"
|
||||||
|
:key="p.value"
|
||||||
|
:label="p.text"
|
||||||
|
:value="p.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="状态">
|
<el-form-item label="状态">
|
||||||
<el-select
|
<el-select
|
||||||
v-model="query.status"
|
v-model="query.solutionEnd"
|
||||||
placeholder="请选择状态"
|
placeholder="请选择状态"
|
||||||
clearable
|
clearable
|
||||||
style="width: 140px"
|
style="width: 140px"
|
||||||
>
|
>
|
||||||
<el-option label="已完结" :value="1" />
|
<el-option label="已完结" :value="true" />
|
||||||
<el-option label="跟进中" :value="2" />
|
<el-option label="跟进中" :value="false" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="赴校时间">
|
<el-form-item label="赴校时间">
|
||||||
|
|
@ -93,21 +102,38 @@
|
||||||
/>
|
/>
|
||||||
<el-table-column label="状态" min-width="110">
|
<el-table-column label="状态" min-width="110">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-tag :type="row.status === 1 ? 'success' : 'warning'">
|
<el-tag :type="row.solutionEnd ? 'success' : 'warning'">
|
||||||
{{ row.status === 1 ? "已完结" : "跟进中" }}
|
{{ row.solutionEnd ? "已完结" : "跟进中" }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- <el-table-column prop="lastTime" label="最后跟进时间" min-width="160" /> -->
|
<!-- <el-table-column prop="lastTime" label="最后跟进时间" min-width="160" /> -->
|
||||||
<el-table-column label="操作" fixed="right" min-width="220">
|
<el-table-column label="操作" fixed="right" min-width="220">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-button size="small" type="danger" plain @click="onDelete(row)"
|
<!-- <el-button size="small" type="danger" plain @click="onDelete(row)"
|
||||||
>删除</el-button
|
>删除</el-button
|
||||||
|
> -->
|
||||||
|
<el-popconfirm
|
||||||
|
confirm-button-text="确定"
|
||||||
|
cancel-button-text="取消"
|
||||||
|
icon-color="#626AEF"
|
||||||
|
title="确定删除吗?"
|
||||||
|
@confirm="onDelete(row)"
|
||||||
>
|
>
|
||||||
|
<template #reference>
|
||||||
|
<el-button type="danger" size="small">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-popconfirm>
|
||||||
|
|
||||||
<el-button size="small" type="primary" plain @click="onDetail(row)"
|
<el-button size="small" type="primary" plain @click="onDetail(row)"
|
||||||
>详情</el-button
|
>详情</el-button
|
||||||
>
|
>
|
||||||
<el-button size="small" type="success" plain @click="onFollow(row)"
|
<el-button
|
||||||
|
v-if="!row.solutionEnd"
|
||||||
|
size="small"
|
||||||
|
type="success"
|
||||||
|
plain
|
||||||
|
@click="onFollow(row)"
|
||||||
>跟进</el-button
|
>跟进</el-button
|
||||||
>
|
>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -128,21 +154,26 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<AddModal v-model:visible="isShowAddModal" />
|
<!-- 新建 -->
|
||||||
|
<AddModal v-model:visible="isShowAddModal" @handleReset="handleReset" />
|
||||||
|
<!-- 跟进 -->
|
||||||
|
<EditModal v-model:visible="isShowEditModal" :detailData="detailData" />
|
||||||
</template>
|
</template>
|
||||||
<!-- 赴校信息管理菜单 -->
|
<!-- 赴校信息管理菜单 -->
|
||||||
<script setup lang="ts" name="Toschoolinfomanage">
|
<script setup lang="ts" name="Toschoolinfomanage">
|
||||||
import {
|
import {
|
||||||
addOrEditApi,
|
addOrEditApi,
|
||||||
getenumApi,
|
|
||||||
getPageListApi,
|
getPageListApi,
|
||||||
getSchoolBusinessDetailApi,
|
getSchoolBusinessDetailApi,
|
||||||
deleteSchoolBusinessApi
|
deleteSchoolBusinessApi,
|
||||||
|
getSchoolBusinessPeopleListApi
|
||||||
} from "@/api/toschoolinfomanage";
|
} from "@/api/toschoolinfomanage";
|
||||||
|
import { getSchoolData } from "@/api/userCenter";
|
||||||
import { ref, reactive, computed, onMounted } from "vue";
|
import { ref, reactive, computed, onMounted } from "vue";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import AddModal from "./addModal.vue";
|
import AddModal from "./addModal.vue";
|
||||||
|
import EditModal from "./editModal.vue";
|
||||||
import { message } from "@/utils/message";
|
import { message } from "@/utils/message";
|
||||||
interface TableItem {
|
interface TableItem {
|
||||||
id: number;
|
id: number;
|
||||||
|
|
@ -152,99 +183,97 @@ interface TableItem {
|
||||||
times: string; // YYYY-MM-DD
|
times: string; // YYYY-MM-DD
|
||||||
feedbackTotals: number;
|
feedbackTotals: number;
|
||||||
solveTotals: number;
|
solveTotals: number;
|
||||||
status: 1 | 2; // 1: 已完结, 2: 跟进中
|
solutionEnd: boolean; // true: 已完结, false: 跟进中
|
||||||
lastTime: string; // YYYY-MM-DD
|
lastTime: string; // YYYY-MM-DD
|
||||||
}
|
}
|
||||||
|
|
||||||
const schoolOptions = ref([
|
const schoolOptions = ref([]);
|
||||||
{ label: "第一中学", value: "第一中学" },
|
const peopleOptions = ref([]);
|
||||||
{ label: "第二中学", value: "第二中学" },
|
/**
|
||||||
{ label: "实验中学", value: "实验中学" },
|
* 获取学校下拉数据
|
||||||
{ label: "外国语学校", value: "外国语学校" }
|
*/
|
||||||
]);
|
const getSchoolDataFn = () => {
|
||||||
const isShowAddModal = ref(false);
|
getSchoolData().then(res => {
|
||||||
onMounted(() => {
|
if (res.code == 200) {
|
||||||
getenumApi({ TextName: "Name", ValueName: "Id" }).then(res => {
|
schoolOptions.value = res.data.map((i: any) => ({
|
||||||
if (res.code === 200) {
|
|
||||||
schoolOptions.value = res.data.map(i => ({
|
|
||||||
label: i.text,
|
label: i.text,
|
||||||
value: i.value
|
value: i.value
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 获取赴校人员下拉数据
|
||||||
|
*/
|
||||||
|
const getSchoolBusinessPeopleList = () => {
|
||||||
|
getSchoolBusinessPeopleListApi({}).then((res: any) => {
|
||||||
|
if (res.code == 200) {
|
||||||
|
peopleOptions.value = res.data || [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const isShowAddModal = ref(false);
|
||||||
|
const isShowEditModal = ref(false);
|
||||||
|
const detailData = ref({});
|
||||||
|
onMounted(() => {
|
||||||
// addOrEdit();
|
// addOrEdit();
|
||||||
loadList();
|
loadList();
|
||||||
|
getSchoolDataFn();
|
||||||
|
getSchoolBusinessPeopleList();
|
||||||
});
|
});
|
||||||
|
|
||||||
const gradeOptions = [
|
const gradeOptions = [
|
||||||
|
{ label: "初一", value: "初一" },
|
||||||
|
{ label: "初二", value: "初二" },
|
||||||
|
{ label: "初三", value: "初三" },
|
||||||
{ label: "高一", value: "高一" },
|
{ label: "高一", value: "高一" },
|
||||||
{ label: "高二", value: "高二" },
|
{ label: "高二", value: "高二" },
|
||||||
{ label: "高三", value: "高三" },
|
{ label: "高三", value: "高三" }
|
||||||
{ label: "初三", value: "初三" }
|
|
||||||
];
|
];
|
||||||
/**
|
/**
|
||||||
* 新建赴校信息提交
|
* 新建赴校信息提交
|
||||||
*/
|
*/
|
||||||
const addOrEdit = () => {
|
const addOrEdit = () => {
|
||||||
addOrEditApi(
|
addOrEditApi({
|
||||||
addOrEditApi({
|
id: 0, //id传0代表新增
|
||||||
id: 0,
|
schoolId: 10079,
|
||||||
schoolId: 708490619039814,
|
schoolName: "系统测试学校",
|
||||||
schoolName: "重庆测试学校",
|
grade: "初二",
|
||||||
grade: "初二",
|
gradeLevel: "",
|
||||||
schoolBusinessUser: ["向波4"],
|
schoolBusinessUser: ["刘德华123"],
|
||||||
startTime: "2025-08-20T07:28:38",
|
startTime: "2025-07-24T07:28:38",
|
||||||
// remark: "string",
|
// remark: "string",
|
||||||
feedbackQuestions: [
|
feedbackQuestions: [
|
||||||
{
|
{
|
||||||
endTime: null,
|
question: "xb测试反馈问题1(双师课堂)",
|
||||||
question: "xb测试反馈问题1(双师课堂)",
|
questionType: 10,
|
||||||
questionType: 10,
|
sort: "1111111111"
|
||||||
solution: "xb测试反馈问题1建议",
|
}
|
||||||
sort: "1"
|
// {
|
||||||
}
|
// question: "xb测试反馈问题2(设备)",
|
||||||
// {
|
// questionType: 15,
|
||||||
// endTime: null,
|
// sort: "2"
|
||||||
// question: "xb测试反馈问题2(设备)",
|
|
||||||
// questionType: 15,
|
|
||||||
// solution: "xb测试反馈问题2建议",
|
|
||||||
// sort: "2"
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// endTime: null,
|
|
||||||
// question: "xb测试反馈问题2(学生)",
|
|
||||||
// questionType: 20,
|
|
||||||
// solution: "xb测试反馈问题3建议",
|
|
||||||
// sort: "3"
|
|
||||||
// }
|
|
||||||
],
|
|
||||||
// solutionRecord: {
|
|
||||||
// solution: "string",
|
|
||||||
// endRecord: "string",
|
|
||||||
// record: [
|
|
||||||
// {
|
|
||||||
// executionRecords: "string",
|
|
||||||
// executionTime: "2025-08-18T08:31:52.716Z"
|
|
||||||
// }
|
|
||||||
// ]
|
|
||||||
// },
|
// },
|
||||||
// solutionEnd: true,
|
// {
|
||||||
isDiscussion: false,
|
// question: "xb测试反馈问题2(学生)",
|
||||||
discussion: "开展座谈座谈座谈座谈座谈座谈座谈座谈座谈座谈座谈座谈座谈",
|
// questionType: 20,
|
||||||
isClassMeeting: false,
|
// sort: "3"
|
||||||
classMeeting: "班会情况班会情况班会情况班会情况班会情况班会情况班会情况"
|
// }
|
||||||
})
|
],
|
||||||
);
|
isDiscussion: true,
|
||||||
|
discussion: "开展座谈座谈座谈座谈座谈座谈座谈座谈座谈座谈座谈座谈座谈",
|
||||||
|
isClassMeeting: true,
|
||||||
|
classMeeting: "班会情况班会情况班会情况班会情况班会情况班会情况班会情况"
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const query = reactive({
|
const query = reactive({
|
||||||
school: "" as string | undefined,
|
school: "" as string | undefined,
|
||||||
grade: "" as string | undefined,
|
grade: "" as string | undefined,
|
||||||
people: "",
|
people: [] as number[],
|
||||||
status: undefined as 1 | 2 | undefined,
|
solutionEnd: undefined,
|
||||||
times: [] as string[]
|
times: [] as string[]
|
||||||
});
|
});
|
||||||
|
|
||||||
const page = ref(1);
|
const page = ref(1);
|
||||||
const pageSize = ref(10);
|
const pageSize = ref(10);
|
||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
|
|
@ -275,7 +304,7 @@ function mapApiItemToRow(item: any): TableItem {
|
||||||
times: start,
|
times: start,
|
||||||
feedbackTotals: Number(item.feedbackCount) || 0,
|
feedbackTotals: Number(item.feedbackCount) || 0,
|
||||||
solveTotals: Number(item.solveFeedbackCount) || 0,
|
solveTotals: Number(item.solveFeedbackCount) || 0,
|
||||||
status: item.solutionEnd ? 1 : 2,
|
solutionEnd: item.solutionEnd,
|
||||||
lastTime: last
|
lastTime: last
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -288,12 +317,14 @@ async function loadList() {
|
||||||
};
|
};
|
||||||
if (query.school) payload.schoolId = query.school;
|
if (query.school) payload.schoolId = query.school;
|
||||||
if (query.grade) payload.grade = query.grade;
|
if (query.grade) payload.grade = query.grade;
|
||||||
if (query.people) payload.people = query.people.trim();
|
if (query.people && query.people.length > 0) {
|
||||||
if (typeof query.status !== "undefined")
|
payload.people = query.people.join(",");
|
||||||
payload.solutionEnd = query.status === 1;
|
}
|
||||||
|
if (typeof query.solutionEnd !== "undefined")
|
||||||
|
payload.solutionEnd = query.solutionEnd;
|
||||||
if (Array.isArray(query.times) && query.times.length === 2) {
|
if (Array.isArray(query.times) && query.times.length === 2) {
|
||||||
payload.startTimeBegin = query.times[0];
|
payload.startTime = query.times[0];
|
||||||
payload.startTimeEnd = query.times[1];
|
payload.endTime = query.times[1];
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const res = await getPageListApi(payload);
|
const res = await getPageListApi(payload);
|
||||||
|
|
@ -328,8 +359,8 @@ function handleSearch() {
|
||||||
function handleReset() {
|
function handleReset() {
|
||||||
query.school = "";
|
query.school = "";
|
||||||
query.grade = "";
|
query.grade = "";
|
||||||
query.people = "";
|
query.people = [];
|
||||||
query.status = undefined;
|
query.solutionEnd = undefined;
|
||||||
query.times = [];
|
query.times = [];
|
||||||
page.value = 1;
|
page.value = 1;
|
||||||
loadList();
|
loadList();
|
||||||
|
|
@ -369,6 +400,13 @@ function onDetail(row: TableItem) {
|
||||||
|
|
||||||
function onFollow(row: TableItem) {
|
function onFollow(row: TableItem) {
|
||||||
console.log(`跟进`);
|
console.log(`跟进`);
|
||||||
|
isShowEditModal.value = true;
|
||||||
|
detailData;
|
||||||
|
getSchoolBusinessDetailApi(row.id).then(res => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
detailData.value = res.data;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleAdd() {
|
function handleAdd() {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue