机器人回复补调用编码;集拼报价条带字段写到下一行,业务员落中文名。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
linmianxun
2026-10-06 13:41:12 +08:00
co-authored by Cursor
parent 58df358577
commit 177dd0b25f
22 changed files with 1934 additions and 210 deletions
@@ -2,6 +2,7 @@
/**
* 机器人回复语:对接主账 /inquiry/botReply。
* 分类壳用本地元数据;条目内容全部来自库。
* 调用编码仅展示/预置,本期不向智能体下发。
*/
import { onMounted, reactive, ref } from "vue";
import { message } from "ant-design-vue";
@@ -21,12 +22,14 @@ import AdminModal from "/@/views/inquiry/components/AdminModal.vue";
const categories = ref<ReplyCategory[]>(emptyCategories());
const loading = ref(false);
const totalCount = ref(0);
const modalOpen = ref(false);
const editing = ref<{ categoryId: string; item: ReplyItem | null }>({
categoryId: "",
item: null,
});
const form = reactive({
replyCode: "",
trigger: "",
text: "",
enabled: true,
@@ -52,6 +55,7 @@ function groupByCategory(list: any[]) {
if (row.categoryTitle) cat.title = row.categoryTitle;
cat.items.push({
id: String(row.id),
replyCode: row.replyCode || "",
trigger: row.triggerScene || "",
text: row.replyText || "",
enabled: row.enabled === 1 || row.enabled === true,
@@ -64,7 +68,14 @@ async function loadList() {
loading.value = true;
try {
const res: any = await getReplyListAll();
const list = Array.isArray(res) ? res : res?.result || res?.records || [];
const list = Array.isArray(res)
? res
: Array.isArray(res?.result)
? res.result
: Array.isArray(res?.records)
? res.records
: [];
totalCount.value = list.length;
categories.value = groupByCategory(list as any[]);
} catch (e: any) {
message.error(e?.message || "加载回复语失败");
@@ -93,13 +104,14 @@ async function toggle(item: ReplyItem) {
function openCreate(categoryId?: string) {
editing.value = { categoryId: categoryId || categories.value[0]?.id || "inquiring", item: null };
Object.assign(form, { trigger: "", text: "", enabled: true });
Object.assign(form, { replyCode: "", trigger: "", text: "", enabled: true });
modalOpen.value = true;
}
function openEdit(categoryId: string, item: ReplyItem) {
editing.value = { categoryId, item };
Object.assign(form, {
replyCode: item.replyCode || "",
trigger: item.trigger,
text: item.text,
enabled: item.enabled,
@@ -114,7 +126,7 @@ async function save() {
}
const cat = categories.value.find((c) => c.id === editing.value.categoryId);
if (!cat) return;
const body = {
const body: Record<string, any> = {
id: editing.value.item?.id,
categoryCode: cat.id,
categoryTitle: cat.title,
@@ -122,6 +134,11 @@ async function save() {
replyText: form.text.trim(),
enabled: form.enabled ? 1 : 0,
};
if (editing.value.item?.replyCode) {
body.replyCode = editing.value.item.replyCode;
} else if (form.replyCode.trim()) {
body.replyCode = form.replyCode.trim();
}
try {
await saveReply(body, Boolean(editing.value.item));
message.success(editing.value.item ? "话术已更新" : "话术已添加");
@@ -141,6 +158,7 @@ async function save() {
</Teleport>
<div v-if="loading" style="padding: 24px; color: #94a3b8">加载中…</div>
<p v-else class="reply-total">共 {{ totalCount }} 条(按现网整理表应为 51 条;事件异常本期无条目)</p>
<article v-for="cat in categories" :key="cat.id" class="reply-category">
<div style="display: flex; align-items: center; justify-content: space-between">
@@ -154,6 +172,7 @@ async function save() {
<div v-for="item in cat.items" :key="item.id" class="reply-item">
<div style="min-width: 0">
<div class="reply-meta">触发:{{ item.trigger }}</div>
<div v-if="item.replyCode" class="reply-meta">调用编码:{{ item.replyCode }}</div>
<div class="reply-text">{{ item.text }}</div>
</div>
<div style="display: flex; align-items: center; gap: 8px; flex-shrink: 0">
@@ -172,7 +191,7 @@ async function save() {
<AdminModal
v-model:open="modalOpen"
:title="editing.item ? '编辑话术' : '添加话术'"
size="md"
size="lg"
ok-text="保存"
@ok="save"
>
@@ -182,13 +201,28 @@ async function save() {
<option v-for="c in categories" :key="c.id" :value="c.id">{{ c.title }}</option>
</select>
</div>
<div class="form-row">
<label class="lbl">调用编码</label>
<input
v-model="form.replyCode"
class="field"
type="text"
:disabled="Boolean(editing.item?.replyCode)"
placeholder="如 lost.ask_reason;已有编码不可改"
/>
</div>
<div class="form-row">
<label class="lbl">触发条件 <span class="req">*</span></label>
<input v-model="form.trigger" class="field" type="text" />
</div>
<div class="form-row">
<div class="form-row form-row-tall">
<label class="lbl">回复正文 <span class="req">*</span></label>
<textarea v-model="form.text" class="field" rows="5" placeholder="支持 {{ticket_no}} 等变量" />
<textarea
v-model="form.text"
class="field field-tall"
rows="12"
placeholder="支持 {{ticket_no}} 等变量"
/>
</div>
<div class="form-row">
<label class="lbl">状态</label>
@@ -201,6 +235,22 @@ async function save() {
</template>
<style scoped>
.reply-total {
margin: 0;
font-size: 12px;
font-weight: 700;
color: #667085;
}
.form-row-tall {
align-items: start;
}
textarea.field-tall {
height: 240px !important;
min-height: 240px !important;
padding: 8px 10px !important;
line-height: 1.5 !important;
resize: vertical;
}
.check-line {
display: inline-flex;
align-items: center;