落地销售调价:按自然语言改价并单独记销售价,拉群和后台不再把调后价当成 TMS 原价。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -17,7 +17,7 @@ import ProtoIcon from "/@/views/inquiry/components/ProtoIcon.vue";
|
||||
import AdminModal from "/@/views/inquiry/components/AdminModal.vue";
|
||||
import AdminPagination from "/@/views/inquiry/components/AdminPagination.vue";
|
||||
|
||||
type TicketQuote = { source: string; price: string; highlight?: boolean };
|
||||
type TicketQuote = { source: string; price: string; time?: string; highlight?: boolean };
|
||||
type TicketAttach = { name: string; uploadedAt: string; uploader: string };
|
||||
type TicketTimeline = { status: string; remark: string; time: string };
|
||||
|
||||
@@ -93,6 +93,21 @@ function dash(v: any) {
|
||||
return s ? s : "-";
|
||||
}
|
||||
|
||||
/**
|
||||
* 后台报价来源:TMS标准报价 / 手工报价 / 销售调价。
|
||||
* 禁止把产品报价或销售调价再显示成 TMS。
|
||||
*/
|
||||
function quoteSourceLabel(q: any) {
|
||||
const src = String(q?.source ?? "").trim().toUpperCase();
|
||||
if (src === "SALES_ADJUST") return "销售调价";
|
||||
if (src === "PRODUCT") return "手工报价";
|
||||
if (src === "TMS") return "TMS标准报价";
|
||||
const label = String(q?.sourceLabel || q?.source || "").replace(/\s/g, "");
|
||||
if (label.includes("销售调价")) return "销售调价";
|
||||
if (label.includes("TMS")) return "TMS标准报价";
|
||||
return label && label !== "报价" ? "手工报价" : "报价";
|
||||
}
|
||||
|
||||
/**
|
||||
* 主账 inq_ticket_status_log.action 是内部码,禁止当备注展示。
|
||||
* transition 与「已报价」等 toStatus 重复,无用户备注时不再跟一段英文。
|
||||
@@ -101,6 +116,8 @@ const STATUS_LOG_ACTION_LABEL: Record<string, string> = {
|
||||
transition: "",
|
||||
retry: "系统重试",
|
||||
abnormal_handle: "异常已处理",
|
||||
quote_adjust: "销售调价",
|
||||
manual_quote: "手工报价",
|
||||
};
|
||||
|
||||
function isInternalActionCode(v: string) {
|
||||
@@ -239,8 +256,9 @@ function mapTicket(t: any, quotes: any[] = [], attachments: any[] = [], timeline
|
||||
demandTitle: reqLines[0] || "—",
|
||||
demandDetail: reqLines.slice(1).join("\n"),
|
||||
quotes: (quotes || []).map((q) => ({
|
||||
source: q.sourceLabel || q.source || "报价",
|
||||
source: quoteSourceLabel(q),
|
||||
price: q.priceText || "-",
|
||||
time: fmtTime(q.createTime),
|
||||
highlight: q.highlighted === 1 || q.highlighted === true,
|
||||
})),
|
||||
attachments: attachRows.map((a) => a.name),
|
||||
@@ -306,7 +324,7 @@ async function loadList() {
|
||||
const page = res?.records ? res : res?.result || {};
|
||||
const records = page.records || [];
|
||||
total.value = Number(page.total || records.length || 0);
|
||||
rows.value = (records as any[]).map((t) => mapTicket(t));
|
||||
rows.value = (records as any[]).map((t) => mapTicket(t, t.quotes || []));
|
||||
// 删减后当前页可能越界,回退到最后一页
|
||||
const maxPage = Math.max(1, Math.ceil(total.value / pageSize.value) || 1);
|
||||
if (pageNo.value > maxPage) {
|
||||
@@ -661,8 +679,8 @@ function refresh() {
|
||||
<div class="ticket-detail-item"><label>利润点</label><span>{{ current.profit }}</span></div>
|
||||
</div>
|
||||
<div v-if="current.quotes.length" class="ticket-detail-demand">
|
||||
<div v-for="q in current.quotes" :key="q.source + q.price" class="quote-row" style="margin-bottom: 6px">
|
||||
<div class="quote-source">{{ q.source }}</div>
|
||||
<div v-for="q in current.quotes" :key="q.source + q.price + (q.time || '')" class="quote-row" style="margin-bottom: 6px">
|
||||
<div class="quote-source">{{ q.source }}<span v-if="q.time && q.time !== '-'"> · {{ q.time }}</span></div>
|
||||
<div class="quote-price" :style="q.highlight ? { color: '#1d4ed8' } : undefined">{{ q.price }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user