You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

349 lines
11 KiB

4 months ago
<template>
<div>
<xy-dialog
ref="dialog"
:width="80"
:is-show.sync="isShow"
:type="'form'"
:title="type === 'add' ? '新增计划' : '编辑计划'"
:form="form"
:rules="rules"
@submit="submit"
>
<template v-slot:year>
<div class="xy-table-item">
<div class="xy-table-item-label" style="font-weight: bold">
<span style="color: red; font-weight: bold; padding-right: 4px;">*</span>计划年份
</div>
<div class="xy-table-item-content">
<el-date-picker
v-model="form.year"
type="year"
value-format="yyyy"
format="yyyy"
placeholder="请选择计划年份"
style="width: 100%;"
/>
</div>
</div>
</template>
<template v-slot:plan_system_id>
<div class="xy-table-item">
<div class="xy-table-item-label" style="font-weight: bold">
<span style="color: red; font-weight: bold; padding-right: 4px;">*</span>计划体系
</div>
<div class="xy-table-item-content">
<el-select v-model="form.plan_system_id" filterable clearable placeholder="请选择计划体系" style="width: 100%;">
<el-option
v-for="item in planSystemList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</div>
</div>
</template>
<template v-slot:course_type_id>
<div class="xy-table-item">
<div class="xy-table-item-label" style="font-weight: bold">
<span style="color: red; font-weight: bold; padding-right: 4px;">*</span>课程体系
</div>
<div class="xy-table-item-content">
<el-select v-model="form.course_type_id" filterable clearable placeholder="请选择课程体系" style="width: 100%;">
<el-option
v-for="item in courseTypesList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</div>
</div>
</template>
<template v-slot:course_name>
<div class="xy-table-item">
<div class="xy-table-item-label" style="font-weight: bold">
<span style="color: red; font-weight: bold; padding-right: 4px;">*</span>课程名称
</div>
<div class="xy-table-item-content">
<el-input v-model="form.course_name" placeholder="请输入课程名称" clearable style="width: 100%;" />
</div>
</div>
</template>
<template v-slot:details>
<div class="xy-table-item">
<div class="xy-table-item-label detail-label" style="font-weight: bold">
<span style="color: red; font-weight: bold; padding-right: 4px;">*</span>模块/期数
</div>
<div class="xy-table-item-content">
<div class="detail-wrap">
<div class="detail-toolbar">
<el-button type="primary" size="small" @click="addDetail"></el-button>
</div>
<el-table :data="form.details" border size="small" style="width: 100%;">
<el-table-column label="名称" min-width="180">
<template slot-scope="scope">
<el-input v-model="scope.row.name" placeholder="请输入模块/期数名称,非必填" size="small" />
</template>
</el-table-column>
<el-table-column label="月份" width="120">
<template slot-scope="scope">
<el-select v-model="scope.row.month" placeholder="月份" size="small" style="width: 100%;">
<el-option
v-for="item in monthOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
</el-table-column>
<el-table-column label="地点" min-width="180">
<template slot-scope="scope">
<el-select v-model="scope.row.location_id" filterable placeholder="请选择地点" size="small" style="width: 100%;">
<el-option
v-for="item in locationList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</template>
</el-table-column>
<el-table-column label="负责人" min-width="160">
<template slot-scope="scope">
<el-input v-model="scope.row.owner_name" placeholder="请输入负责人" size="small" />
</template>
</el-table-column>
<el-table-column label="操作" width="100" align="center">
<template slot-scope="scope">
<el-button type="danger" size="mini" @click="removeDetail(scope.$index)"></el-button>
</template>
</el-table-column>
</el-table>
<div class="detail-tip">至少保留一条模块/期数名称可不填月份地点负责人必填</div>
<div v-if="type === 'editor'" class="danger-actions">
<el-button type="danger" size="small" @click="handleDeletePlan"></el-button>
</div>
</div>
</div>
</div>
</template>
</xy-dialog>
</div>
</template>
<script>
import { showMockPlan as show, saveMockPlan as save, destroyMockPlan as destroy } from "../mockService.js";
const getCurrentYear = () => String(new Date().getFullYear());
const createDetail = () => ({
id: "",
name: "",
month: "",
location_id: "",
owner_name: "",
});
const getDefaultForm = () => ({
year: getCurrentYear(),
plan_system_id: "",
course_type_id: "",
course_name: "",
details: [createDetail()],
});
export default {
data() {
return {
isShow: false,
type: "add",
id: "",
courseTypesList: [],
planSystemList: [],
locationList: [],
form: getDefaultForm(),
rules: {
year: [{
required: true,
message: "请选择计划年份",
}],
plan_system_id: [{
required: true,
message: "请选择计划体系",
}],
course_type_id: [{
required: true,
message: "请选择课程体系",
}],
course_name: [{
required: true,
message: "请输入课程名称",
}],
},
monthOptions: Array.from({ length: 12 }, (_, index) => ({
value: index + 1,
label: `${index + 1}`,
})),
};
},
methods: {
addDetail() {
this.form.details.push(createDetail());
},
removeDetail(index) {
if (this.form.details.length === 1) {
this.$message.warning("模块/期数至少保留一条");
return;
}
this.form.details.splice(index, 1);
},
normalizeDetail(item) {
return {
id: item.id || "",
name: item.name || item.module_name || "",
month: item.month === 0 ? 0 : Number(item.month || ""),
location_id: item.location_id || item.location?.id || "",
owner_name: item.owner_name || item.owner || item.principal || "",
};
},
getDetailListFromResponse(res) {
const list = res.details || res.detail_list || res.modules || res.items || [];
if (!Array.isArray(list) || !list.length) {
return [createDetail()];
}
return list.map((item) => this.normalizeDetail(item));
},
validateDetails() {
if (!Array.isArray(this.form.details) || this.form.details.length === 0) {
this.$message.warning("请至少新增一条模块/期数");
return false;
}
for (let index = 0; index < this.form.details.length; index += 1) {
const item = this.form.details[index];
if (!item.month) {
this.$message.warning(`${index + 1} 条模块/期数未选择月份`);
return false;
}
if (!item.location_id) {
this.$message.warning(`${index + 1} 条模块/期数未选择地点`);
return false;
}
if (!item.owner_name) {
this.$message.warning(`${index + 1} 条模块/期数未填写负责人`);
return false;
}
}
return true;
},
submit() {
if (!this.validateDetails()) {
return;
}
const payload = {
id: this.type === "editor" ? this.id : "",
year: this.form.year,
plan_system_id: this.form.plan_system_id,
course_type_id: this.form.course_type_id,
course_name: this.form.course_name,
details: this.form.details.map((item) => ({
id: item.id || "",
name: item.name || "",
month: Number(item.month),
location_id: item.location_id,
owner_name: item.owner_name,
})),
};
save(payload).then(() => {
this.$message({
type: "success",
message: this.type === "add" ? "新增成功" : "编辑成功",
});
this.isShow = false;
this.$emit("refresh");
});
},
getDetail() {
show({ id: this.id }).then((res) => {
this.form = {
year: String(res.year || getCurrentYear()),
plan_system_id: res.plan_system_id || res.plan_system?.id || res.plan_system_detail?.id || "",
course_type_id: res.course_type_id || res.course_type?.id || res.type_detail?.id || "",
course_name: res.course_name || res.name || "",
details: this.getDetailListFromResponse(res),
};
});
},
handleDeletePlan() {
this.$confirm(
"删除该计划将删除所有的模块/期数,是否确认删除?",
"提示",
{
type: "warning",
confirmButtonText: "确定",
cancelButtonText: "取消",
}
).then(() => {
destroy({ id: this.id }).then(() => {
this.$message.success("删除成功");
this.isShow = false;
this.$emit("refresh");
});
}).catch(() => {});
},
resetForm() {
this.id = "";
this.form = getDefaultForm();
this.$refs.dialog.reset();
},
},
watch: {
isShow(newVal) {
if (newVal) {
if (this.type === "editor" && this.id) {
this.getDetail();
}
} else if (this.$refs.dialog) {
this.resetForm();
}
},
},
};
</script>
<style scoped lang="scss">
::v-deep .year,
::v-deep .plan_system_id,
::v-deep .course_type_id,
::v-deep .course_name,
::v-deep .details {
flex-basis: 100%;
}
.detail-label {
align-self: flex-start;
padding-top: 8px;
}
.detail-wrap {
width: 100%;
}
.detail-toolbar {
margin-bottom: 10px;
}
.detail-tip {
margin-top: 8px;
font-size: 12px;
color: #909399;
}
.danger-actions {
margin-top: 16px;
text-align: right;
}
</style>