机器人显示名与站点标题可配;多段联运列表投影;协同群监听对账;工单附件落存;模板与工单后台补强

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
linmianxun
2026-10-19 09:41:59 +08:00
co-authored by Cursor
parent 277cdc1c28
commit 2b528758b4
119 changed files with 6760 additions and 3516 deletions
@@ -0,0 +1,186 @@
<script setup lang="ts">
/**
* 企微机器人显示名:挂在侧栏「系统配置」下,方便运营直接改 @ 名。
* 数据仍落 inq_bot_reply.reply_code=system.bot_display_name;智能体短缓存约 60 秒生效。
* 过渡期智能体仍认旧名「询价小助手」,本页只改对外当前名。
*/
import { onMounted, ref } from 'vue';
import { message } from 'ant-design-vue';
import { getReplyListAll, saveReply } from '/@/views/inquiry/botReply/botReply.api';
import { usePermission } from '/@/hooks/web/usePermission';
import { InquiryBtnPerm } from '/@/views/inquiry/shared/inquiryPagePerms';
const REPLY_CODE = 'system.bot_display_name';
const DEFAULT_NAME = '智报通AIQ';
const { hasPermission } = usePermission();
const canEdit = () => hasPermission(InquiryBtnPerm.replyEdit);
const loading = ref(false);
const saving = ref(false);
const rowId = ref('');
const displayName = ref(DEFAULT_NAME);
const enabled = ref(true);
async function load() {
loading.value = true;
try {
const res: any = await getReplyListAll();
const list = Array.isArray(res)
? res
: Array.isArray(res?.result)
? res.result
: Array.isArray(res?.records)
? res.records
: [];
const hit = list.find((r: any) => String(r.replyCode || '') === REPLY_CODE);
if (hit) {
rowId.value = String(hit.id || '');
displayName.value = String(hit.replyText || '').trim() || DEFAULT_NAME;
enabled.value = hit.enabled === 1 || hit.enabled === true;
} else {
rowId.value = '';
displayName.value = DEFAULT_NAME;
enabled.value = true;
}
} catch (e: any) {
message.error(e?.message || '加载显示名失败');
} finally {
loading.value = false;
}
}
async function save() {
const name = displayName.value.trim();
if (!name) {
message.warning('请填写机器人显示名');
return;
}
if (name.includes('@')) {
message.warning('只需填名字本身,不要带 @');
return;
}
saving.value = true;
try {
const body: Record<string, any> = {
categoryCode: 'system',
categoryTitle: '系统配置',
replyCode: REPLY_CODE,
triggerScene: '企微机器人显示名(@ 名)',
replyText: name,
enabled: enabled.value ? 1 : 0,
};
if (rowId.value) {
body.id = rowId.value;
}
await saveReply(body, Boolean(rowId.value));
message.success('已保存。智能体约 1 分钟内按新名出站;入站仍兼容旧名「询价小助手」。');
await load();
} catch (e: any) {
message.error(e?.message || '保存失败');
} finally {
saving.value = false;
}
}
onMounted(() => load());
</script>
<template>
<div class="bot-name-page">
<div v-if="loading" style="padding: 24px; color: #94a3b8">加载中…</div>
<template v-else>
<p class="hint">
销售在企微里 @ 的名字。改完后请同步在企微管理后台把应用显示名改成一致,否则人和系统会对不上。
</p>
<div class="card">
<div class="form-row">
<label class="lbl">当前显示名</label>
<input
v-model="displayName"
class="field"
type="text"
maxlength="32"
placeholder="如 智报通AIQ"
:disabled="!canEdit()"
/>
</div>
<div class="form-row">
<label class="lbl">调用编码</label>
<input class="field" type="text" :value="REPLY_CODE" disabled />
</div>
<div class="form-row">
<label class="lbl">状态</label>
<label class="check-line">
<input v-model="enabled" type="checkbox" :disabled="!canEdit()" />
<span>启用</span>
</label>
</div>
<div class="actions">
<button
v-if="canEdit()"
type="button"
class="btn btn-primary"
:disabled="saving"
@click="save"
>
{{ saving ? '保存中…' : '保存' }}
</button>
</div>
</div>
</template>
</div>
</template>
<style scoped>
.bot-name-page {
max-width: 560px;
}
.hint {
margin: 0 0 16px;
font-size: 12px;
line-height: 1.6;
color: #667085;
}
.card {
background: #fff;
border: 1px solid #e4e7ec;
border-radius: 12px;
padding: 20px;
}
.form-row {
display: grid;
grid-template-columns: 100px 1fr;
gap: 12px;
align-items: center;
margin-bottom: 14px;
}
.lbl {
font-size: 11px;
font-weight: 700;
color: #344054;
}
.field {
height: 34px;
border: 1px solid #d0d5dd;
border-radius: 8px;
padding: 0 10px;
font-size: 12px;
}
.field:disabled {
background: #f2f4f7;
color: #98a2b3;
}
.check-line {
display: inline-flex;
align-items: center;
gap: 8px;
font-size: 12px;
font-weight: 600;
color: #344054;
}
.actions {
margin-top: 8px;
padding-left: 112px;
}
</style>