347 lines
8.9 KiB
Vue
347 lines
8.9 KiB
Vue
<script lang="ts" setup>
|
||
import FormItemTip from "@/components/FormItemTip/index.vue";
|
||
import cskbEditor from '@/components/Editor/cskb.vue'
|
||
import {FormInstance, FormRules} from "element-plus";
|
||
import {addCsKb} from "@/api/system/cskb";
|
||
import modal from "@/plugins/modal";
|
||
|
||
const formRef = ref<FormInstance>()
|
||
const router = useRouter();
|
||
const form = ref({
|
||
"title": "",
|
||
"category": "",
|
||
"content": "",
|
||
"sort": 1,
|
||
"status": "1",
|
||
"buttons": []
|
||
})
|
||
// ========= 表单校验 rules =========
|
||
const rules: FormRules = {
|
||
title: [
|
||
{required: true, message: '请输入问题标题', trigger: 'blur'},
|
||
{max: 30, message: '标题最多30个字符', trigger: 'blur'}
|
||
],
|
||
category: [
|
||
{required: true, message: '请选择问题分类', trigger: 'change'}
|
||
],
|
||
content: [
|
||
{required: true, message: '请填写回复内容', trigger: 'blur'}
|
||
],
|
||
sort: [
|
||
{required: true, message: '请输入排序号', trigger: 'blur'},
|
||
{type: 'number', min: 0, message: '排序号不能小于0', trigger: 'blur'}
|
||
]
|
||
}
|
||
const actions = {
|
||
resolved: {"buttonCode": "resolved", "label": "已解决", "sort": 1, value: 'resolved'},
|
||
transfer_human: {"buttonCode": "transfer_human", "label": "转人工", "sort": 2, value: 'transfer_human'},
|
||
}
|
||
|
||
|
||
function handleBack() {
|
||
router.replace({
|
||
path: "/conversation/cskbList"
|
||
})
|
||
}
|
||
|
||
async function submit(isEnable = false) {
|
||
if (!formRef.value) return
|
||
console.log(form.value)
|
||
await formRef.value.validate((valid) => {
|
||
if (valid) {
|
||
// isEnable=true 代表保存并启用
|
||
form.value.buttons = form.value.buttons.map(item => {
|
||
return actions[item]
|
||
})
|
||
addCsKb(form.value).then(() => {
|
||
modal.msgSuccess('添加成功')
|
||
if (isEnable) {
|
||
handleBack()
|
||
}
|
||
})
|
||
}
|
||
})
|
||
}
|
||
|
||
function reset() {
|
||
form.value = {
|
||
"title": "",
|
||
"category": "",
|
||
"content": "",
|
||
"sort": 1,
|
||
"status": "1",
|
||
"buttons": []
|
||
}
|
||
}
|
||
|
||
</script>
|
||
|
||
<template>
|
||
<div class="edit">
|
||
<div class="flex justify-between" style="padding-top: 22px">
|
||
<pagecrumb></pagecrumb>
|
||
<el-button plain type="info" @click="handleBack"> 返回知识库管理</el-button>
|
||
</div>
|
||
<div class="tipBox">
|
||
<div class="tip1">新增的知识条目保存后需要「启用」才会在 APP 端展示
|
||
</div>
|
||
<div class="tip2">回复内容支持有序步骤与图片,建议控制在 200 字以内,便于用户快速阅读。
|
||
</div>
|
||
</div>
|
||
<!-- form -->
|
||
<section class="commonCard">
|
||
<div class="flex justify-between flex-items-center">
|
||
<card-nav subTitle="配置问题标题、分类与标准回复话术" title="新增知识条目"></card-nav>
|
||
<div class="unSave">
|
||
<i class="square"></i>
|
||
<span>未保存</span>
|
||
</div>
|
||
</div>
|
||
<div class="formbox">
|
||
<el-form ref="formRef" :model="form" :rules="rules" label-position="top">
|
||
<div class="title">
|
||
基础信息
|
||
</div>
|
||
<el-row :gutter="24">
|
||
<el-col :span="12">
|
||
<FormItemTip
|
||
v-model.trim="form.title"
|
||
:inputAttrs="{ placeholder: '请输入问题标题,如「连不上 Wi-Fi」', showWordLimit:true ,maxlength:30}"
|
||
label="问题标题"
|
||
prop="title"
|
||
tip="建议使用用户口语化问法,便于模糊匹配"
|
||
>
|
||
</FormItemTip>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<FormItemTip
|
||
v-model.trim="form.category"
|
||
:inputAttrs="{ placeholder: '请选择问题分类', maxlength:30}"
|
||
label="问题分类"
|
||
prop="category"
|
||
>
|
||
</FormItemTip>
|
||
</el-col>
|
||
</el-row>
|
||
<el-row :gutter="24">
|
||
<el-col :span="24">
|
||
<FormItemTip
|
||
label="回复内容"
|
||
prop="content"
|
||
type="default"
|
||
>
|
||
<template #default>
|
||
<cskbEditor v-model="form.content" :simple-toolbar="true" style="width: 100%"></cskbEditor>
|
||
</template>
|
||
</FormItemTip>
|
||
</el-col>
|
||
</el-row>
|
||
<div class="title">
|
||
关联与排序
|
||
</div>
|
||
<el-row :gutter="24">
|
||
<el-col :span="12">
|
||
<FormItemTip
|
||
v-model="form.buttons"
|
||
:radio-options="Object.values(actions)"
|
||
label="关联快捷按钮"
|
||
prop="buttons"
|
||
tip="回复气泡下方展示的引导按钮,可多选"
|
||
type="checkBox"
|
||
>
|
||
</FormItemTip>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<FormItemTip
|
||
v-model.number="form.sort"
|
||
:inputAttrs="{ placeholder: '请输入排序'}"
|
||
label="排序号"
|
||
prop="sort"
|
||
tip="决定该条目在 APP 常见问题列表中的展示顺序"
|
||
type="inputNumber"
|
||
>
|
||
<template #suffix>越小越靠前</template>
|
||
</FormItemTip>
|
||
</el-col>
|
||
</el-row>
|
||
<el-row :gutter="24">
|
||
<el-col :span="12">
|
||
<FormItemTip
|
||
v-model="form.status"
|
||
:inputAttrs="{
|
||
activeValue: '1',
|
||
inactiveValue: '0',
|
||
}"
|
||
label="启用状态"
|
||
tip="关闭则保存为草稿,仅后台可见"
|
||
type="switch"
|
||
>
|
||
<template #switchRight>
|
||
<span
|
||
style="color: rgba(17, 24, 39, 1);font-size: 13px;font-weight: bolder">启用后立即在APP端展示</span>
|
||
</template>
|
||
</FormItemTip>
|
||
</el-col>
|
||
</el-row>
|
||
</el-form>
|
||
</div>
|
||
</section>
|
||
<div class="footer">
|
||
<div class="footer-tip">标题、分类与回复内容为必填项;排序号越小展示越靠前</div>
|
||
<div>
|
||
<el-button @click="reset">取消</el-button>
|
||
<el-button plain type="primary" @click="submit(false)">保存并继续新增</el-button>
|
||
<el-button type="primary" @click="submit(true)">保存并启用</el-button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<style lang="scss" scoped>
|
||
.edit {
|
||
overflow: hidden;
|
||
overflow-y: auto;
|
||
min-height: 100%;
|
||
padding-bottom: 50px;
|
||
|
||
.tipBox {
|
||
margin-top: 16px;
|
||
background-color: rgba(239, 246, 255, 1);
|
||
border: 1px solid rgba(219, 234, 254, 1);
|
||
padding: 13px 53px;
|
||
|
||
.tip1 {
|
||
line-height: 18px;
|
||
color: rgba(30, 64, 175, 1);
|
||
font-size: 13px;
|
||
}
|
||
|
||
.tip2 {
|
||
line-height: 16px;
|
||
color: rgba(59, 130, 246, 1);
|
||
font-size: 12px;
|
||
}
|
||
}
|
||
|
||
.customerInfoBox {
|
||
margin-top: 16px;
|
||
|
||
.infoBox {
|
||
.customer-Img {
|
||
width: 73px;
|
||
height: 72px;
|
||
border-radius: 50%;
|
||
margin-right: 24px;
|
||
}
|
||
|
||
.userName {
|
||
height: 26px;
|
||
line-height: 26px;
|
||
font-weight: bold;
|
||
color: rgba(17, 24, 39, 1);
|
||
font-size: 22px;
|
||
}
|
||
|
||
.circle {
|
||
display: block;
|
||
width: 7px;
|
||
height: 6px;
|
||
border-radius: 3px;
|
||
margin-right: 6px;
|
||
background-color: rgba(22, 163, 74, 1);
|
||
}
|
||
}
|
||
|
||
.subInfoBox {
|
||
line-height: 20px;
|
||
color: rgba(107, 114, 128, 1);
|
||
font-size: 13px;
|
||
text-align: left;
|
||
|
||
.dat {
|
||
margin: 0 1px;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
.subTitle {
|
||
line-height: 14px;
|
||
color: rgba(156, 163, 175, 1);
|
||
font-size: 12px;
|
||
text-align: left;
|
||
}
|
||
|
||
|
||
.unSave {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 79px;
|
||
height: 28px;
|
||
background-color: rgba(248, 250, 252, 1);
|
||
border: 1px solid rgba(241, 245, 249, 1);
|
||
|
||
.square {
|
||
display: block;
|
||
width: 8px;
|
||
height: 6px;
|
||
margin-right: 8px;
|
||
background-color: rgba(148, 163, 184, 1);
|
||
}
|
||
|
||
span {
|
||
height: 14px;
|
||
line-height: 14px;
|
||
color: rgba(107, 114, 128, 1);
|
||
font-size: 12px;
|
||
}
|
||
}
|
||
|
||
.formbox {
|
||
margin-top: 46px;
|
||
|
||
.title {
|
||
line-height: 16px;
|
||
color: rgba(55, 65, 81, 1);
|
||
font-size: 13px;
|
||
text-align: left;
|
||
margin: 24px 0;
|
||
font-weight: bold;
|
||
}
|
||
}
|
||
|
||
.footer {
|
||
margin-top: 27px;
|
||
text-align: right;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
|
||
.footer-tip {
|
||
line-height: 14px;
|
||
color: rgba(107, 114, 128, 1);
|
||
font-size: 12px;
|
||
text-align: left;
|
||
}
|
||
|
||
&:deep(.el-button) {
|
||
padding: 14px 25px;
|
||
min-height: 44px;
|
||
border-radius: 0;
|
||
border: 1px solid rgba(226, 232, 240, 1);
|
||
|
||
|
||
&.el-button--primary.is-plain {
|
||
color: #2563EB;
|
||
}
|
||
}
|
||
|
||
.el-button + .el-button {
|
||
margin-left: 21px;
|
||
}
|
||
}
|
||
}
|
||
|
||
</style>
|