feat(questions): make brand questions the primary monitoring & template axis
- add /questions/combination-fill endpoint with AI-driven, IP-region-aware matrix fill - extract ip2region resolver from ops/app into shared/ipregion for cross-service use - thread question_id filter through dashboard composite, citation summary, and collect-now - switch template wizard from keyword inputs to brand-question selection (primary + supplemental) - pass brand_question and supplemental_questions through assist/title/outline prompts - add AiWaitingModal + 45s client timeout and request_timeout error mapping for long AI flows Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -53,7 +53,7 @@ const columns = computed<TableColumnsType<AIPointUsageLog>>(() => [
|
||||
title: t('aiPoints.table.points'),
|
||||
dataIndex: 'points',
|
||||
key: 'points',
|
||||
width: 110,
|
||||
width: 188,
|
||||
align: 'right',
|
||||
},
|
||||
{
|
||||
@@ -89,7 +89,7 @@ function handleTableChange(nextPage: number, nextPageSize: number): void {
|
||||
function getAIPointUsageTypeLabel(usageType: string): string {
|
||||
const key = `shell.aiUsageTypes.${usageType}`
|
||||
const label = t(key)
|
||||
return label === key ? usageType : label
|
||||
return label === key ? t('aiPoints.usageTypeFallback') : label
|
||||
}
|
||||
|
||||
function getAIPointStatusMeta(status: string): { label: string; color: string } {
|
||||
@@ -108,8 +108,48 @@ function getAIPointStatusMeta(status: string): { label: string; color: string }
|
||||
}
|
||||
}
|
||||
|
||||
function formatAIPointDelta(item: AIPointUsageLog): string {
|
||||
return item.status === 'refunded' ? `+${item.points}` : `-${item.points}`
|
||||
function getAIPointStatusHelp(status: string): string | null {
|
||||
switch (status) {
|
||||
case 'pending':
|
||||
return t('shell.aiUsagePendingHelp')
|
||||
case 'refunded':
|
||||
return t('aiPoints.refundedHelp')
|
||||
default:
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
function getAIPointAmountMeta(item: AIPointUsageLog): {
|
||||
primary: string
|
||||
detail: string
|
||||
tone: 'charge' | 'refund' | 'neutral'
|
||||
} {
|
||||
switch (item.status) {
|
||||
case 'refunded':
|
||||
return {
|
||||
primary: t('aiPoints.amount.netZero'),
|
||||
detail: t('aiPoints.amount.refundedFlow', { points: item.points }),
|
||||
tone: 'refund',
|
||||
}
|
||||
case 'pending':
|
||||
return {
|
||||
primary: `-${item.points}`,
|
||||
detail: t('aiPoints.amount.pendingFlow', { points: item.points }),
|
||||
tone: 'charge',
|
||||
}
|
||||
case 'completed':
|
||||
return {
|
||||
primary: `-${item.points}`,
|
||||
detail: t('aiPoints.amount.completedFlow', { points: item.points }),
|
||||
tone: 'charge',
|
||||
}
|
||||
default:
|
||||
return {
|
||||
primary: t('aiPoints.amount.zero'),
|
||||
detail: t('aiPoints.amount.failedFlow'),
|
||||
tone: 'neutral',
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -208,12 +248,13 @@ function formatAIPointDelta(item: AIPointUsageLog): string {
|
||||
</template>
|
||||
|
||||
<template v-else-if="column.key === 'points'">
|
||||
<span
|
||||
class="points-delta"
|
||||
:class="{ 'points-delta--refund': record.status === 'refunded' }"
|
||||
<div
|
||||
class="points-cell"
|
||||
:class="`points-cell--${getAIPointAmountMeta(record).tone}`"
|
||||
>
|
||||
{{ formatAIPointDelta(record) }}
|
||||
</span>
|
||||
<strong>{{ getAIPointAmountMeta(record).primary }}</strong>
|
||||
<span>{{ getAIPointAmountMeta(record).detail }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-else-if="column.key === 'request_chars'">
|
||||
@@ -229,7 +270,10 @@ function formatAIPointDelta(item: AIPointUsageLog): string {
|
||||
:bordered="false"
|
||||
>
|
||||
{{ getAIPointStatusMeta(record.status).label }}
|
||||
<a-tooltip v-if="record.status === 'pending'" :title="t('shell.aiUsagePendingHelp')">
|
||||
<a-tooltip
|
||||
v-if="getAIPointStatusHelp(record.status)"
|
||||
:title="getAIPointStatusHelp(record.status)"
|
||||
>
|
||||
<QuestionCircleOutlined class="status-help-icon" />
|
||||
</a-tooltip>
|
||||
</a-tag>
|
||||
@@ -397,15 +441,37 @@ function formatAIPointDelta(item: AIPointUsageLog): string {
|
||||
color: #cf1322 !important;
|
||||
}
|
||||
|
||||
.points-delta {
|
||||
.points-cell {
|
||||
display: grid;
|
||||
gap: 2px;
|
||||
justify-items: end;
|
||||
min-width: 132px;
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.points-cell strong {
|
||||
color: #cf1322;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.points-delta--refund {
|
||||
.points-cell span {
|
||||
color: #8c8c8c;
|
||||
font-size: 12px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.points-cell--refund strong {
|
||||
color: #595959;
|
||||
}
|
||||
|
||||
.points-cell--refund span {
|
||||
color: #389e0d;
|
||||
}
|
||||
|
||||
.points-cell--neutral strong {
|
||||
color: #595959;
|
||||
}
|
||||
|
||||
.status-tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
|
||||
Reference in New Issue
Block a user