123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456 |
- <template>
- <div class="case-edit-container layout-pd">
- <el-card shadow="never" style="padding: 0 50px">
- <el-form :model="state.ruleForm" ref="ruleFormRef" label-width="120px" scroll-to-error>
- <el-row :gutter="35">
- <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="8">
- <el-skeleton :loading="state.loading" animated>
- <template #template>
- <el-form-item label="案例分类">
- <el-skeleton-item variant="h1" />
- </el-form-item>
- </template>
- <template #default>
- <el-form-item label="案例分类" prop="caseTypeId" :rules="[{ required: true, message: '请选择案例分类', trigger: 'change' }]">
- <VTreeDrop
- :data="state.typeData"
- checkable
- keyField="id"
- titleField="name"
- v-model="state.ruleForm.caseTypeId"
- @checked-change="selectType"
- :dropHeight="400"
- dropPlaceholder="案例分类"
- dropdownWidthFixed
- clearable
- searchPlaceholder="案例分类名称"
- checkedButtonText="查看已选"
- :show-footer="false"
- :cascade="false"
- >
- </VTreeDrop>
- </el-form-item>
- </template>
- </el-skeleton>
- </el-col>
- <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="8">
- <el-skeleton :loading="state.loading" animated>
- <template #template>
- <el-form-item>
- <template #label>
- <div style="height: 34px; display: flex; align-items: center">
- 失效时间
- <el-tooltip placement="top-start">
- <SvgIcon name="ele-QuestionFilled" size="18px" class="ml3" />
- <template #content> 不设置则代表永久有效;到达预设失效时间,案例将自动下架 </template>
- </el-tooltip>
- </div>
- </template>
- <el-skeleton-item variant="h1" />
- </el-form-item>
- </template>
- <template #default>
- <el-form-item label="失效时间" prop="expiredTime" :rules="[{ required: false, message: '请选择失效时间', trigger: 'change' }]">
- <template #label>
- <div style="height: 34px; display: flex; align-items: center">
- 失效时间
- <el-tooltip placement="top-start">
- <SvgIcon name="ele-QuestionFilled" size="18px" class="ml3" />
- <template #content> 不设置则代表永久有效;到达预设失效时间,案例将自动下架 </template>
- </el-tooltip>
- </div>
- </template>
- <el-date-picker
- v-model="state.ruleForm.expiredTime"
- type="datetime"
- placeholder="请选择失效时间"
- class="w100"
- value-format="YYYY-MM-DD[T]HH:mm:ss"
- :disabled-date="disabledDate"
- popper-class="no-atTheMoment"
- />
- </el-form-item>
- </template>
- </el-skeleton>
- </el-col>
- <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
- <el-skeleton :loading="state.loading" animated>
- <template #template>
- <el-form-item label="案例标题">
- <el-skeleton-item variant="h1" />
- </el-form-item>
- </template>
- <template #default>
- <el-form-item label="案例标题" prop="title" :rules="[{ required: true, validator: validatePassTitle, trigger: 'blur' }]">
- <el-input v-model="state.ruleForm.title" placeholder="请填写案例标题" clearable @blur="isRepeat('title')"></el-input>
- </el-form-item>
- </template>
- </el-skeleton>
- </el-col>
- <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
- <el-skeleton :loading="state.loading" animated>
- <template #template>
- <el-form-item label="案例摘要">
- <el-skeleton-item variant="h1" />
- </el-form-item>
- </template>
- <template #default>
- <el-form-item label="案例摘要" prop="abstract" :rules="[{ required: false, message: '请填写案例摘要', trigger: 'blur' }]">
- <el-input v-model="state.ruleForm.abstract" placeholder="请填写案例摘要" clearable></el-input>
- </el-form-item>
- </template>
- </el-skeleton>
- </el-col>
- <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
- <el-skeleton :loading="state.loading" animated>
- <template #template>
- <el-form-item label="关键词">
- <el-skeleton-item variant="h1" />
- </el-form-item>
- </template>
- <template #default>
- <el-form-item label="关键词" prop="keyword" :rules="[{ required: false, message: '请填写关键词', trigger: 'blur' }]">
- <el-input v-model="state.ruleForm.keyword" placeholder="请填写关键词" clearable></el-input>
- </el-form-item>
- </template>
- </el-skeleton>
- </el-col>
- <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
- <el-skeleton :loading="state.loading" animated>
- <template #template>
- <el-form-item label="关联工单">
- <el-skeleton-item variant="h1" />
- </el-form-item>
- </template>
- <template #default>
- <el-form-item label="关联工单" prop="keyword" :rules="[{ required: true, message: '请选择关联工单', trigger: 'change' }]">
- </el-form-item>
- </template>
- </el-skeleton>
- </el-col>
- <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
- <el-skeleton :loading="state.loading" animated>
- <template #template>
- <el-form-item label="关联知识">
- <el-skeleton-item variant="h1" />
- </el-form-item>
- </template>
- <template #default>
- <el-form-item label="关联知识" prop="keyword" :rules="[{ required: false, message: '请选择关联知识', trigger: 'blur' }]">
- </el-form-item>
- </template>
- </el-skeleton>
- </el-col>
- <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
- <el-skeleton :loading="state.loading" animated>
- <template #template>
- <el-form-item label="案例描述">
- <el-skeleton-item variant="h1" />
- </el-form-item>
- </template>
- <template #default>
- <el-form-item label="案例描述" prop="describe" :rules="[{ required: true, message: '请填写案例描述', trigger: 'blur' }]">
- <editor v-model:get-html="state.ruleForm.describe" placeholder="请填写案例描述" />
- </el-form-item>
- </template>
- </el-skeleton>
- </el-col>
- <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
- <el-skeleton :loading="state.loading" animated>
- <template #template>
- <el-form-item label="案例办理结果">
- <el-skeleton-item variant="h1" />
- </el-form-item>
- </template>
- <template #default>
- <el-form-item label="案例办理结果" prop="result" :rules="[{ required: true, message: '请填写案例办理结果', trigger: 'blur' }]">
- <editor v-model:get-html="state.ruleForm.result" placeholder="请填写案例办理结果" />
- </el-form-item>
- </template>
- </el-skeleton>
- </el-col>
- <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
- <el-skeleton :loading="state.loading" animated>
- <template #template>
- <el-form-item label="案例描述">
- <el-skeleton-item variant="h1" />
- </el-form-item>
- </template>
- <template #default>
- <el-form-item label="推荐理由" prop="reason" :rules="[{ required: false, message: '请填写推荐理由', trigger: 'blur' }]">
- <editor v-model:get-html="state.ruleForm.reason" placeholder="请填写推荐理由" />
- </el-form-item>
- </template>
- </el-skeleton>
- </el-col>
- <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
- <el-skeleton :loading="state.loading" animated>
- <template #template>
- <el-form-item label="是否设为热门案例" label-width="130px">
- <el-skeleton-item variant="h1" />
- </el-form-item>
- </template>
- <template #default>
- <el-form-item
- label-width="130px"
- label="是否设为热门案例"
- prop="isPopular"
- :rules="[{ required: false, message: '请选择是否设为热门案例', trigger: 'change' }]"
- >
- <el-radio-group v-model="state.ruleForm.isPopular">
- <el-radio :value="true">是</el-radio>
- <el-radio :value="false">否</el-radio>
- </el-radio-group>
- </el-form-item>
- </template>
- </el-skeleton>
- </el-col>
- <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
- <el-skeleton :loading="state.loading" animated>
- <template #template>
- <el-form-item label="附件">
- <el-skeleton-item variant="h1" />
- </el-form-item>
- </template>
- <template #default>
- <el-form-item label="附件" prop="files" :rules="[{ required: false, message: '请选择附件', trigger: 'change' }]">
- <annex-list
- name="案例附件"
- v-model="state.ruleForm.files"
- v-model:format="filesFormat"
- :businessId="state.ruleForm.id"
- classify="案例上传"
- />
- </el-form-item>
- </template>
- </el-skeleton>
- </el-col>
- <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
- <el-form-item>
- <el-button type="primary" @click="onSubmitReview(ruleFormRef)" :loading="state.loading">提交审核</el-button>
- <el-button class="default-button" @click="onPreview" :loading="state.loading">预览 </el-button>
- <el-button @click="onSaveOnly(ruleFormRef)" class="default-button" :loading="state.loading">保存为草稿</el-button>
- <el-button class="default-button" @click="onCancel" :loading="state.loading">取消 </el-button>
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
- </el-card>
- <!-- 删除或者更新提交审核 -->
- <edit-submit-audit ref="editSubmitAuditRef" @updateList="processSuccess" />
- </div>
- </template>
- <script setup lang="ts" name="caseEdit">
- import { defineAsyncComponent, onMounted, reactive, ref } from 'vue';
- import type { FormInstance } from 'element-plus';
- import { ElMessage } from 'element-plus';
- import mittBus from '@/utils/mitt';
- import { useRoute, useRouter } from 'vue-router';
- import { storeToRefs } from 'pinia';
- import { useUserInfo } from '@/stores/userInfo';
- import { Local } from '@/utils/storage';
- import other from '@/utils/other';
- import { throttle, transformFile } from '@/utils/tools';
- import { disabledDate } from '@/utils/constants';
- import { VTreeDrop } from '@wsfe/vue-tree';
- import { addCaseDraft, addCaseDraftAudit, caseDetail, caseRepeat, editCaseDraft } from '@/api/case';
- import { caseTreeList } from '@/api/case/type';
- // 引入组件
- const Editor = defineAsyncComponent(() => import('@/components/Editor/index.vue')); // 富文本编辑器
- const AnnexList = defineAsyncComponent(() => import('@/components/AnnexList/index.vue')); // 附件组件
- const EditSubmitAudit = defineAsyncComponent(() => import('@/views/case/index/components/Edit-submit-audit.vue')); // 删除或者更新 提交审核
- const stores = useUserInfo(); // 用户信息
- const { userInfos } = storeToRefs(stores); // 用户信息
- // 定义变量内容
- const state = reactive<any>({
- dialogVisible: false,
- ruleForm: {
- attribution: '中心案例库', // 案例归属
- files: [], // 附件
- content: '', // 内容
- title: null, // 标题
- keyword: null, // 关键词
- abstract: null, // 摘要
- expiredTime: null, // 失效时间
- isPopular: false, // 是否热门
- describe: '', // 案例描述
- result: '', // 案例办理结果
- reason: '', // 推荐理由
- },
- typeData: [], // 分类
- loading: false,
- });
- const ruleFormRef = ref<any>(); // 表单ref
- const validatePassTitle = (rule: any, value: any, callback: any) => {
- if (value === '' || value === null) {
- callback(new Error('请填写案例标题'));
- } else if (Repeat.value) {
- callback(new Error('有相似标题,请检查!'));
- } else {
- callback();
- }
- };
- // 校验标题/摘要/内容是否重复 根据输入标题检测出关键词填入
- const Repeat = ref<boolean>(false);
- const isRepeat = (type: string) => {
- if (state.ruleForm[type]) {
- caseRepeat({ [type]: state.ruleForm[type], id: state.ruleForm.id })
- .then((res: any) => {
- Repeat.value = res.result;
- ruleFormRef.value.validateField(type);
- })
- .catch(() => {
- state.ruleForm[type] = '';
- });
- }
- };
- // 默认配置
- const defaultContent = ref([
- {
- type: 'paragraph',
- children: [{ text: '', fontFamily: '仿宋', fontSize: '20px' }],
- lineHeight: '2',
- },
- ]);
- const selectType = (value: any) => {
- state.ruleForm.caseTypes = value.map((item: any) => {
- return { caseTypeName: item.name, caseTypeId: item.id, caseTypeSpliceName: item.spliceName };
- });
- state.ruleForm.caseTypeId = value.map((item: any) => item.id);
- ruleFormRef.value.validateField('caseTypeId');
- };
- // 提交审核
- const route = useRoute(); // 获取路由
- const router = useRouter(); // 路由跳转
- const filesFormat = ref<EmptyArrayType>([]); // 附件列表格式化
- const editSubmitAuditRef = ref<RefType>(); // 删除或者更新 提交审核
- const onSubmitReview = async (formEl: FormInstance | undefined) => {
- if (!formEl) return;
- await formEl.validate((valid: boolean) => {
- if (!valid) return;
- state.ruleForm.files = filesFormat.value;
- const submitObj = other.deepClone(state.ruleForm);
- Reflect.deleteProperty(submitObj, 'creationTime');
- //如果已经有ID 说明是已经提交过的数据 更新审核
- if (route.params.id) {
- editSubmitAuditRef.value.openDialog(submitObj, 'update');
- } else {
- state.loading = true;
- addCaseDraftAudit(submitObj)
- .then(() => {
- ElMessage.success('新增案例审核成功');
- processSuccess();
- })
- .catch(() => {
- state.loading = false;
- });
- state.loading = false;
- }
- });
- };
- // 流程提交成功
- const processSuccess = () => {
- // 关闭当前 tagsView
- mittBus.emit('onCurrentContextmenuClick', Object.assign({}, { contextMenuClickId: 1, ...route }));
- mittBus.emit('clearCache', 'caseManage');
- router.push({
- path: '/case/index',
- });
- };
- // 预览
- const onPreview = () => {
- if (route.params.id) {
- } else {
- state.ruleForm.creatorName = userInfos.value?.name ?? '';
- state.ruleForm.creationTime = new Date();
- state.ruleForm.creatorOrgName = userInfos.value?.orgName ?? '';
- }
- Local.set('casePreviewForm', state.ruleForm);
- router.push({
- name: 'casePreview',
- params: {
- tagsViewName: '案例预览',
- id: '0',
- },
- });
- };
- // 保存到草稿箱
- const onSaveOnly = throttle(async (formEl: FormInstance | undefined) => {
- if (!formEl) return;
- await formEl.validate((valid: boolean) => {
- if (!valid) return;
- state.loading = true;
- state.ruleForm.files = filesFormat.value;
- const submitObj = other.deepClone(state.ruleForm);
- Reflect.deleteProperty(submitObj, 'creationTime');
- if (route.params.id) {
- // 更新
- editCaseDraft(submitObj)
- .then(handleSuccess)
- .catch(() => {
- state.loading = false;
- });
- } else {
- // 新增
- addCaseDraft(submitObj)
- .then(handleSuccess)
- .catch(() => {
- state.loading = false;
- });
- }
- });
- }, 300);
- // 取消
- const onCancel = () => {
- state.loading = true;
- mittBus.emit('onCurrentContextmenuClick', Object.assign({}, { contextMenuClickId: 1, ...route }));
- mittBus.emit('clearCache', 'caseManage');
- router.push({
- path: '/case/index',
- });
- state.loading = false;
- };
- const handleSuccess = () => {
- state.loading = false;
- ElMessage.success('操作成功');
- // 关闭当前 tagsView
- mittBus.emit('onCurrentContextmenuClick', Object.assign({}, { contextMenuClickId: 1, ...route }));
- mittBus.emit('clearCache', 'caseManage');
- router.push({
- path: '/case/index',
- });
- };
- // 获取分类
- const getType = async () => {
- state.loading = true;
- try {
- const [typeDataRes] = await Promise.all([caseTreeList({ IsEnable: true })]);
- state.typeData = typeDataRes.result ?? [];
- state.loading = false;
- } catch (error) {
- console.log(error);
- state.loading = false;
- }
- };
- const editorRef = ref<RefType>();
- const getDetail = async () => {
- if (route.params.id) {
- const res: any = await caseDetail({ id: route.params.id }); //详情
- state.ruleForm = res.result ?? {};
- state.ruleForm.files = transformFile(state.ruleForm.files);
- state.ruleForm.caseTypeId = state.ruleForm.caseTypes?.map((item: any) => item.CaseTypeID);
- }
- };
- onMounted(async () => {
- await getType();
- await getDetail();
- });
- </script>
- <style lang="scss">
- .vtree-tree-drop__wrapper {
- width: 100%;
- }
- </style>
|