<template>
|
<Card>
|
<template style="position: relative">
|
<div class="header-title">
|
<div class="header-title-left">
|
<img src="@/assets/public/headercard.png" />
|
<span>项目课题方案信息</span>
|
</div>
|
</div>
|
<el-form
|
ref="form"
|
:model="form"
|
:rules="rules"
|
inline
|
label-position="top"
|
style="margin-top: 38px"
|
>
|
<el-form-item prop="projectName" label="项目课题方案名称">
|
<el-input v-model="form.projectName" placeholder="请输入" />
|
</el-form-item>
|
<el-form-item prop="projectStage" label="项目阶段">
|
<el-select v-model="form.projectStage" placeholder="请选择">
|
<el-option label="实验室开发阶段" :value="1" />
|
<el-option label="中式试验阶段" :value="2" />
|
<el-option label="生产验证试验阶段" :value="3" />
|
</el-select>
|
</el-form-item>
|
<el-form-item prop="projectCode" label="项目课题方案编号">
|
<el-input v-model="form.projectCode" placeholder="请输入" disabled />
|
</el-form-item>
|
</el-form>
|
<div class="header-title">
|
<div class="header-title-left">
|
<img src="@/assets/public/headercard.png" />
|
<div>一 、实验目的</div>
|
</div>
|
</div>
|
<AiEditor
|
ref="purposeEditor"
|
:value="editorContents.experimentObjective"
|
height="200px"
|
placeholder="请输入实验目的..."
|
/>
|
<div class="header-title">
|
<div class="header-title-left">
|
<img src="@/assets/public/headercard.png" />
|
<div>二 、实验拆料和设备</div>
|
</div>
|
</div>
|
<div class="item-title">
|
<span>1.实验材料</span>
|
</div>
|
<AiEditor
|
ref="materialEditor"
|
:value="editorContents.experimentMaterial"
|
height="200px"
|
placeholder="请输入实验材料..."
|
/>
|
<div class="item-title">
|
<span>2.实验设备</span>
|
</div>
|
<AiEditor
|
ref="equipmentEditor"
|
:value="editorContents.experimentDevice"
|
height="200px"
|
placeholder="请输入实验设备..."
|
/>
|
<div class="header-title">
|
<div class="header-title-left">
|
<img src="@/assets/public/headercard.png" />
|
<div>三 、检测方法及开发</div>
|
</div>
|
</div>
|
<AiEditor
|
ref="methodEditor"
|
:value="editorContents.experimentTestMethod"
|
height="200px"
|
placeholder="请输入检测方法及开发..."
|
/>
|
<div class="header-title">
|
<div class="header-title-left">
|
<img src="@/assets/public/headercard.png" />
|
<div>四 、实验步骤</div>
|
</div>
|
</div>
|
<AiEditor
|
ref="stepsEditor"
|
:value="editorContents.experimentProcedure"
|
height="200px"
|
placeholder="请输入实验步骤..."
|
/>
|
<div class="header-title">
|
<div class="header-title-left">
|
<img src="@/assets/public/headercard.png" />
|
<div>五 、数据采集及分析</div>
|
</div>
|
</div>
|
<AiEditor
|
ref="dataAnalysisEditor"
|
:value="editorContents.dataAcquisition"
|
height="200px"
|
placeholder="请输入数据采集及分析..."
|
/>
|
<div class="header-title">
|
<div class="header-title-left">
|
<img src="@/assets/public/headercard.png" />
|
<div>六 、结果评估</div>
|
</div>
|
</div>
|
<AiEditor
|
ref="evaluationEditor"
|
:value="editorContents.resultEvaluation"
|
height="200px"
|
placeholder="请输入结果评估..."
|
/>
|
<div class="header-title">
|
<div class="header-title-left">
|
<img src="@/assets/public/headercard.png" />
|
<span>注意事项</span>
|
</div>
|
</div>
|
<AiEditor
|
ref="notesEditor"
|
:value="editorContents.precautions"
|
height="200px"
|
placeholder="请输入注意事项..."
|
/>
|
<div class="add-project-footer">
|
<el-button type="primary" class="save-btn" @click="handleSave"
|
>保存</el-button
|
>
|
<el-button @click="handleSaveDraft">存草稿</el-button>
|
</div>
|
</template>
|
<SelectMember ref="selectMember" />
|
</Card>
|
</template>
|
|
<script>
|
import AiEditor from "@/components/AiEditor";
|
import { addProposal, updateProposal, getDetailById } from "./service";
|
import { mapState } from "vuex";
|
|
export default {
|
name: "AddProject",
|
components: {
|
AiEditor,
|
},
|
data() {
|
return {
|
id: "", // 用于编辑时存储id
|
form: {
|
projectName: "",
|
projectStage: "",
|
projectCode: "",
|
experimentObjective: "",
|
experimentMaterial: "",
|
experimentDevice: "",
|
experimentTestMethod: "",
|
experimentProcedure: "",
|
dataAcquisition: "",
|
resultEvaluation: "",
|
precautions: "",
|
auditStatus: 1, // 默认为审批中
|
},
|
editorContents: {
|
experimentObjective: "",
|
experimentMaterial: "",
|
experimentDevice: "",
|
experimentTestMethod: "",
|
experimentProcedure: "",
|
dataAcquisition: "",
|
resultEvaluation: "",
|
precautions: "",
|
},
|
rules: {
|
projectName: [
|
{
|
required: true,
|
message: "请输入项目课题方案名称",
|
trigger: "blur",
|
},
|
],
|
projectStage: [
|
{ required: true, message: "请选择项目阶段", trigger: "change" },
|
],
|
experimentObjective: [
|
{ required: true, message: "请输入实验目的", trigger: "blur" },
|
],
|
experimentMaterial: [
|
{ required: true, message: "请输入实验材料", trigger: "blur" },
|
],
|
experimentDevice: [
|
{ required: true, message: "请输入实验设备", trigger: "blur" },
|
],
|
experimentTestMethod: [
|
{ required: true, message: "请输入检测方法及开发", trigger: "blur" },
|
],
|
experimentProcedure: [
|
{ required: true, message: "请输入实验步骤", trigger: "blur" },
|
],
|
dataAcquisition: [
|
{ required: true, message: "请输入数据采集及分析", trigger: "blur" },
|
],
|
resultEvaluation: [
|
{ required: true, message: "请输入结果评估", trigger: "blur" },
|
],
|
// precautions: [
|
// { required: true, message: "请输入注意事项", trigger: "blur" },
|
// ],
|
},
|
};
|
},
|
computed: {
|
...mapState(["tagList", "isFold"]),
|
},
|
methods: {
|
// 获取所有编辑器的内容
|
getAllEditorContent() {
|
return {
|
experimentObjective: this.$refs.purposeEditor.getContent(),
|
experimentMaterial: this.$refs.materialEditor.getContent(),
|
experimentDevice: this.$refs.equipmentEditor.getContent(),
|
experimentTestMethod: this.$refs.methodEditor.getContent(),
|
experimentProcedure: this.$refs.stepsEditor.getContent(),
|
dataAcquisition: this.$refs.dataAnalysisEditor.getContent(),
|
resultEvaluation: this.$refs.evaluationEditor.getContent(),
|
precautions: this.$refs.notesEditor.getContent(),
|
};
|
},
|
// 统一处理方法
|
handleSubmit(type) {
|
this.$refs.form.validate((valid) => {
|
if (valid) {
|
// 获取所有编辑器内容
|
const editorContents = this.getAllEditorContent();
|
|
// 检查编辑器内容是否为空
|
const emptyFields = [];
|
console.log("editorContents", editorContents);
|
|
// 判断内容是否为空(排除<p></p>)
|
const isEmptyContent = (content) => {
|
return (
|
!content || content === "<p></p>" || content.trim() === "<p></p>"
|
);
|
};
|
|
if (isEmptyContent(editorContents.experimentObjective))
|
emptyFields.push("实验目的");
|
if (isEmptyContent(editorContents.experimentMaterial))
|
emptyFields.push("实验材料");
|
if (isEmptyContent(editorContents.experimentDevice))
|
emptyFields.push("实验设备");
|
if (isEmptyContent(editorContents.experimentTestMethod))
|
emptyFields.push("检测方法及开发");
|
if (isEmptyContent(editorContents.experimentProcedure))
|
emptyFields.push("实验步骤");
|
if (isEmptyContent(editorContents.dataAcquisition))
|
emptyFields.push("数据采集及分析");
|
if (isEmptyContent(editorContents.resultEvaluation))
|
emptyFields.push("结果评估");
|
// if (isEmptyContent(editorContents.precautions)) emptyFields.push('注意事项')
|
|
if (emptyFields.length > 0) {
|
this.$message.warning(`请填写${emptyFields.join("、")}`);
|
return false;
|
}
|
|
const formData = {
|
...this.form,
|
...editorContents,
|
auditStatus: type === "draft" ? -1 : 1, // 草稿箱:-1, 审批中:1
|
};
|
|
const request = this.id ? updateProposal : addProposal;
|
if (this.id) {
|
formData.id = this.id;
|
}
|
|
console.log("请求参数:", {
|
formData,
|
});
|
|
request(formData)
|
.then((res) => {
|
console.log("接口返回:", res);
|
if (res.code === 200) {
|
const successMsg =
|
type === "draft"
|
? "草稿保存成功"
|
: this.id
|
? "更新成功"
|
: "保存成功";
|
this.$message.success(successMsg);
|
this.$router.back();
|
this.$store.commit(
|
"SET_TAGLIST",
|
this.tagList.filter((item) => item.path !== this.$route.path)
|
);
|
} else {
|
const errorMsg =
|
type === "draft"
|
? "草稿保存失败"
|
: this.id
|
? "更新失败"
|
: "保存失败";
|
this.$message.error(res.msg || errorMsg);
|
}
|
})
|
.catch((err) => {
|
console.error("接口错误:", err);
|
const errorMsg =
|
type === "draft"
|
? "草稿保存失败"
|
: this.id
|
? "更新失败"
|
: "保存失败";
|
this.$message.error(errorMsg);
|
});
|
} else {
|
this.$message.warning("请填写必填项");
|
return false;
|
}
|
});
|
},
|
// 保存
|
handleSave() {
|
this.handleSubmit("save");
|
},
|
// 保存草稿
|
handleSaveDraft() {
|
this.handleSubmit("draft");
|
},
|
// 获取详情
|
getDetail() {
|
if (this.id) {
|
console.log("获取详情参数:", { id: this.id });
|
getDetailById({ id: this.id })
|
.then((res) => {
|
console.log("详情接口返回:", res);
|
if (res) {
|
const data = res;
|
// 设置表单数据
|
this.form = {
|
projectName: data.projectName,
|
projectStage: data.projectStage,
|
projectCode: data.projectCode,
|
auditStatus: data.auditStatus,
|
};
|
// 设置编辑器内容
|
this.editorContents = {
|
experimentObjective: data.experimentObjective,
|
experimentMaterial: data.experimentMaterial,
|
experimentDevice: data.experimentDevice,
|
experimentTestMethod: data.experimentTestMethod,
|
experimentProcedure: data.experimentProcedure,
|
dataAcquisition: data.dataAcquisition,
|
resultEvaluation: data.resultEvaluation,
|
precautions: data.precautions,
|
};
|
}
|
})
|
.catch((err) => {
|
console.error("获取详情失败:", err);
|
});
|
}
|
},
|
},
|
created() {
|
// 从路由参数中获取id
|
this.id = this.$route.query.id;
|
if (this.id) {
|
this.getDetail();
|
}
|
},
|
};
|
</script>
|
|
<style scoped lang="less">
|
.el-form--inline .el-form-item {
|
margin-right: 83px;
|
}
|
|
.header-title {
|
display: flex;
|
align-items: center;
|
flex-wrap: wrap;
|
gap: 13px;
|
|
.header-title-left {
|
display: flex;
|
align-items: center;
|
gap: 13px;
|
margin-top: 38px;
|
|
img {
|
width: 12px;
|
height: 19px;
|
}
|
|
div {
|
flex-shrink: 0;
|
font-weight: bold;
|
font-size: 18px;
|
color: #222222;
|
line-height: 27px;
|
font-family: "Source Han Sans CN Bold Bold";
|
|
&:before {
|
content: "*";
|
color: #f56c6c;
|
margin-right: 4px;
|
}
|
}
|
span {
|
flex-shrink: 0;
|
font-weight: bold;
|
font-size: 18px;
|
color: #222222;
|
line-height: 27px;
|
font-family: "Source Han Sans CN Bold Bold";
|
}
|
}
|
.header-title-left :first-child {
|
margin-top: 0;
|
}
|
}
|
|
.item-title {
|
padding-left: 25px;
|
|
span {
|
flex-shrink: 0;
|
font-weight: bold;
|
font-size: 14px;
|
color: #222222;
|
line-height: 27px;
|
font-family: "Source Han Sans CN Bold Bold";
|
margin: 18px 0;
|
|
&:before {
|
content: "*";
|
color: #f56c6c;
|
margin-right: 4px;
|
}
|
}
|
}
|
.header-title:first-child {
|
.header-title-left {
|
margin-top: 0;
|
}
|
}
|
|
.add-project-footer {
|
margin-top: 43px;
|
button {
|
width: 220px;
|
}
|
.save-btn {
|
margin-right: 20px;
|
}
|
}
|
|
.ai-editor-container {
|
width: 75%;
|
margin: 20px 0;
|
border: 1px solid #dcdfe6;
|
border-radius: 4px;
|
background: #fff;
|
}
|
</style>
|