Files
inquiry_robot/inquiry-backend/src/views/inquiry/systemSetting/index.vue
T

237 lines
6.4 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 setup>
/**
* 超时响应:响应超时小时配置。
* 海运 / 空运 / 陆运同页自上而下分块展示,只允许改超时小时;无增删、无 Tab。
* 「编码」= timeoutCode,每条唯一(如 sea_sales / land_hk_express),供智能体单码调用;只读。
* roleCode(销售/产品)仅为角色维度,可重复,不是调用主键。
* 陆运产品运输分类 5 项(与线路解耦);不展示线路类别。
* 数据来自主账 inq_response_timeout;本页不做工单超时判定。
*/
import { computed, onMounted, ref } from 'vue';
import { message } from 'ant-design-vue';
import {
getTimeoutListAll,
saveTimeoutHours,
} from '/@/views/inquiry/systemSetting/systemSetting.api';
import { usePermission } from '/@/hooks/web/usePermission';
import { InquiryBtnPerm } from '/@/views/inquiry/shared/inquiryPagePerms';
const { hasPermission } = usePermission();
const canEditTimeout = () => hasPermission(InquiryBtnPerm.timeoutEdit);
/** 分块顺序:海运 → 空运 → 陆运(产品确认同页分块) */
const MODE_BLOCKS = [
{ code: 'SEA', title: '海运' },
{ code: 'AIR', title: '空运' },
{ code: 'LAND', title: '陆运' },
];
const ROLE_LABEL = {
sales: '销售',
product: '产品',
air_route: '航线',
};
const rows = ref([]);
const loading = ref(false);
const savingId = ref('');
/** 编辑中的草稿小时数(按 id),失焦或回车时提交 */
const draftHours = ref({});
/** 按运输方式分组,块内按 sort_no 排 */
const blocks = computed(() =>
MODE_BLOCKS.map((b) => ({
...b,
rows: rows.value
.filter((r) => r.transportMode === b.code)
.sort((a, c) => (a.sortNo || 0) - (c.sortNo || 0)),
})),
);
function roleLabel(code) {
return ROLE_LABEL[code] || code;
}
function displayOrDash(v) {
const s = (v || '').trim();
return s || '—';
}
/** 唯一业务编码;缺省时提示需迁移 */
function timeoutCodeOf(row) {
const c = String(row.timeoutCode || '').trim();
return c || '—';
}
async function loadList() {
loading.value = true;
try {
const res = await getTimeoutListAll();
const list = Array.isArray(res) ? res : res?.result || res?.records || [];
rows.value = list.map((r) => ({
...r,
timeoutHours: Number(r.timeoutHours ?? 0),
}));
const next = {};
for (const r of rows.value) {
next[r.id] = r.timeoutHours;
}
draftHours.value = next;
} catch (e) {
message.error(e?.message || '加载超时配置失败');
} finally {
loading.value = false;
}
}
onMounted(() => loadList());
function onHoursInput(id, raw) {
const n = Number(raw);
draftHours.value[id] = Number.isFinite(n) && n >= 0 ? n : 0;
}
async function commitHours(row) {
const hours = draftHours.value[row.id];
if (hours == null || !Number.isFinite(hours) || hours < 0) {
message.warning('超时小时须为 ≥0 的数字,支持小数');
draftHours.value[row.id] = row.timeoutHours;
return;
}
if (hours === row.timeoutHours) {
return;
}
savingId.value = row.id;
try {
await saveTimeoutHours(row.id, hours);
row.timeoutHours = hours;
message.success('已保存');
} catch (e) {
message.error(e?.message || '保存失败');
draftHours.value[row.id] = row.timeoutHours;
} finally {
savingId.value = '';
}
}
</script>
<template>
<div class="sys-setting-page">
<div class="toolbar-bar">
<span class="hint">固定规则,仅可改超时小时(支持小数,0=不监测);编码唯一只读,供智能体调用;失焦或回车保存</span>
</div>
<div v-if="loading" style="padding: 24px; color: #94a3b8">加载中…</div>
<template v-else>
<section v-for="block in blocks" :key="block.code" class="section-card mode-block">
<div class="section-card-header">
<div class="section-card-title">{{ block.title }}</div>
</div>
<div class="table-wrap">
<table class="data-table">
<thead>
<tr>
<th style="width: 88px">角色</th>
<th style="width: 160px" title="每条唯一;智能体用此码取超时小时">编码</th>
<th>运输分类</th>
<th style="width: 140px">超时设置(小时)</th>
</tr>
</thead>
<tbody>
<tr v-if="!block.rows.length">
<td colspan="4" style="color: #94a3b8">暂无配置</td>
</tr>
<tr v-for="row in block.rows" :key="row.id">
<td>{{ roleLabel(row.roleCode) }}</td>
<td>
<code class="role-code" :title="'智能体调用编码:' + timeoutCodeOf(row)">{{
timeoutCodeOf(row)
}}</code>
</td>
<td>{{ displayOrDash(row.transportType) }}</td>
<td>
<div class="hours-cell">
<input
class="field hours-input"
type="number"
min="0"
step="0.01"
:value="draftHours[row.id]"
:disabled="!canEditTimeout() || savingId === row.id"
@input="onHoursInput(row.id, $event.target.value)"
@blur="commitHours(row)"
@keydown.enter.prevent="commitHours(row)"
/>
<span class="hours-unit">h</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</section>
</template>
</div>
</template>
<style scoped>
.sys-setting-page {
display: flex;
flex-direction: column;
gap: 12px;
}
.toolbar-bar {
display: flex;
justify-content: flex-end;
align-items: center;
}
.hint {
font-size: 11px;
color: #94a3b8;
font-weight: 500;
}
.mode-block {
margin: 0;
}
.mode-block .table-wrap {
border: none;
border-radius: 0;
box-shadow: none;
}
.hours-cell {
display: inline-flex;
align-items: center;
gap: 6px;
}
.hours-input {
width: 88px;
min-height: 32px;
padding: 4px 8px;
}
.hours-unit {
font-size: 11px;
color: #667085;
font-weight: 600;
}
.role-code {
display: inline-block;
padding: 2px 6px;
border-radius: 4px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
font-size: 11px;
font-weight: 600;
color: #344054;
background: #f2f4f7;
border: 1px solid #e4e7ec;
}
</style>