feat(web): AI 工作台会话与文档卡片渲染增强

- aiConversationHtmlRenderer 识别单据记录类表格并渲染为卡片列表,新增删除申请单详情的禁用占位链接
- aiWorkbenchConversationStore 增加草稿删除后会话链接失效处理,避免点击已删除单据跳转
- aiApplicationPreviewActions 调整提交/草稿调用路径,PersonalWorkbenchAiMode 接入新的会话存储与渲染
- ConfirmDialog/TravelRequestDeleteDialog/useAppShell/AppShellRouteView 配套适配,同步更新相关前端测试
This commit is contained in:
caoxiaozhu
2026-06-20 21:44:16 +08:00
parent 81e990ab72
commit 0cda750ff0
19 changed files with 734 additions and 92 deletions

View File

@@ -1140,8 +1140,11 @@ function canShowInlineSuggestedActions(message = {}) {
function isInlineSuggestedActionDisabled(action = {}, message = {}) {
const actionType = String(action?.action_type || '').trim()
return (
[AI_APPLICATION_ACTION_SAVE_DRAFT, AI_APPLICATION_ACTION_SUBMIT].includes(actionType) &&
isApplicationPreviewEstimatePending(message)
Boolean(action?.disabled) ||
(
[AI_APPLICATION_ACTION_SAVE_DRAFT, AI_APPLICATION_ACTION_SUBMIT].includes(actionType) &&
isApplicationPreviewEstimatePending(message)
)
)
}
@@ -1267,8 +1270,21 @@ function normalizeInlineApplicationResultTableCell(value, fallback = '-') {
}
function buildInlineApplicationActionDetailHref(reference = '') {
const value = String(reference || '').trim()
return value ? `${AI_APPLICATION_DETAIL_HREF_PREFIX}${encodeURIComponent(value)}` : ''
const source = reference && typeof reference === 'object' ? reference : { reference }
const claimId = String(source.claimId || source.claim_id || source.id || '').trim()
const claimNo = String(source.claimNo || source.claim_no || source.documentNo || source.document_no || '').trim()
const fallback = String(source.reference || '').trim()
if (claimId || claimNo) {
const params = new URLSearchParams()
if (claimId) {
params.set('claim_id', claimId)
}
if (claimNo) {
params.set('claim_no', claimNo)
}
return `${AI_APPLICATION_DETAIL_HREF_PREFIX}${encodeURIComponent(params.toString())}`
}
return fallback ? `${AI_APPLICATION_DETAIL_HREF_PREFIX}${encodeURIComponent(fallback)}` : ''
}
function resolveInlineApplicationActionDocumentInfo(draftPayload = {}) {
@@ -1293,7 +1309,7 @@ function resolveInlineApplicationActionDocumentInfo(draftPayload = {}) {
function buildInlineApplicationResultTable(draftPayload = {}, options = {}) {
const info = resolveInlineApplicationActionDocumentInfo(draftPayload)
const reference = info.claimNo || info.claimId
const href = buildInlineApplicationActionDetailHref(reference)
const href = buildInlineApplicationActionDetailHref(info)
const actionText = href ? `[查看](${href})` : '-'
return [
'| 单据类型 | 单据编号 | 单据状态 | 当前节点 | 操作 |',
@@ -1945,22 +1961,40 @@ function parseAiApplicationDetailHref(href = '') {
if (!encodedReference) {
return null
}
let reference = ''
try {
const reference = decodeURIComponent(encodedReference).trim()
return reference ? { reference } : null
reference = decodeURIComponent(encodedReference).trim()
} catch {
return { reference: encodedReference }
reference = encodedReference.trim()
}
if (!reference) {
return null
}
const params = new URLSearchParams(reference)
const claimId = String(params.get('claim_id') || '').trim()
const claimNo = String(params.get('claim_no') || '').trim()
if (claimId || claimNo) {
return {
reference: claimNo || claimId,
claimId,
claimNo
}
}
return { reference }
}
function buildAiDocumentDetailRequest(detailReference = {}) {
const reference = String(detailReference.reference || '').trim()
const isApplication = /^APP?-/i.test(reference)
const claimId = String(detailReference.claimId || detailReference.claim_id || '').trim()
const claimNo = String(detailReference.claimNo || detailReference.claim_no || '').trim()
const lookupReference = claimId || reference
const displayReference = claimNo || reference
const isApplication = /^APP?-/i.test(displayReference) || Boolean(claimId || claimNo)
return {
id: reference,
claimId: reference,
claimNo: reference,
documentNo: reference,
id: lookupReference,
claimId: claimId || reference,
claimNo: claimNo || reference,
documentNo: displayReference,
documentType: isApplication ? 'application' : 'reimbursement',
documentTypeCode: isApplication ? 'application' : 'reimbursement',
detailLookupOnly: true,
@@ -2371,7 +2405,11 @@ function handleInlineSuggestedAction(action = {}, sourceMessage = null) {
if (actionType === 'open_application_detail') {
const claimNo = String(actionPayload.claim_no || actionPayload.claimNo || '').trim()
const claimId = String(actionPayload.claim_id || actionPayload.claimId || '').trim()
emit('open-document', buildAiDocumentDetailRequest({ reference: claimNo || claimId }))
emit('open-document', buildAiDocumentDetailRequest({
reference: claimNo || claimId,
claimId,
claimNo
}))
return
}
if (actionPayload.steward_confirm_flow && actionPayload.flow_id === 'travel_reimbursement') {

View File

@@ -321,6 +321,55 @@ function handleCancel() {
max-height: min(420px, calc(100dvh - 292px));
}
.shared-confirm-card--destructive {
width: min(420px, calc(100vw - 40px));
gap: 12px;
padding: 20px 22px;
border-color: rgba(var(--danger-rgb), 0.16);
border-radius: 6px;
background:
linear-gradient(180deg, rgba(255, 255, 255, 0.99), rgba(248, 250, 252, 0.97));
box-shadow:
0 18px 42px rgba(15, 23, 42, 0.16),
0 1px 0 rgba(255, 255, 255, 0.92) inset;
}
.shared-confirm-card--destructive .shared-confirm-badge {
min-height: 24px;
padding: 0 9px;
font-size: 11px;
font-weight: 850;
}
.shared-confirm-card--destructive h4 {
font-size: 19px;
line-height: 1.42;
font-weight: 850;
}
.shared-confirm-card--destructive p {
max-width: 34em;
color: #64748b;
font-size: 13px;
line-height: 1.65;
}
.shared-confirm-card--destructive .shared-confirm-actions {
gap: 8px;
padding-top: 2px;
}
.shared-confirm-card--destructive .shared-confirm-btn {
min-width: 112px;
min-height: 38px;
border-radius: 6px;
font-size: 13px;
}
.shared-confirm-card--destructive .shared-confirm-btn.confirm.danger {
box-shadow: 0 10px 20px rgba(var(--danger-rgb), 0.18);
}
.shared-confirm-card--compact h4 {
font-size: 15px;
line-height: 1.35;

View File

@@ -5,6 +5,8 @@
badge-tone="danger"
:title="title"
:description="description"
size="destructive"
actions-align="end"
cancel-text="取消"
confirm-text="确认删除"
busy-text="删除中..."