Files
smarthome/src/views/system/cskb/add.vue
Zy 2ccce95d44 10/10
1. 设备管理界面完成
2. 用户管理界面完成
3. 会话列表完成
2026-10-10 17:02:31 +08:00

347 lines
8.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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>