Compare commits

..

No commits in common. "fa1f075c0ade1e34a20ceb9799b9655d8d337cf5" and "366056dcac42a3d2975f093069cbe6955f0edfd6" have entirely different histories.

3 changed files with 25 additions and 22 deletions

View File

@ -32,8 +32,9 @@ interface ApplyResult {
customerName: string customerName: string
customerCode: string customerCode: string
appId: string appId: string
connectCode: string
appSecret: string appSecret: string
mcpEndpoint: string expireAt: string
} }
const props = defineProps<{ modelValue: boolean }>() const props = defineProps<{ modelValue: boolean }>()
@ -343,14 +344,14 @@ function notifyContact() {
<el-descriptions-item label="备注">{{ form.remark || '—' }}</el-descriptions-item> <el-descriptions-item label="备注">{{ form.remark || '—' }}</el-descriptions-item>
</el-descriptions> </el-descriptions>
<el-alert type="info" :closable="false" style="margin-top: 16px;"> <el-alert type="info" :closable="false" style="margin-top: 16px;">
后端将自动创建公司账号 + 生成 APIKey 后端将自动创建公司账号 + 生成 connect_code(2h 有效)
</el-alert> </el-alert>
</div> </div>
<!-- Step 3: 生成结果 --> <!-- Step 3: 生成结果 -->
<div v-if="step === 3 && result"> <div v-if="step === 3 && result">
<el-alert type="warning" :closable="false" style="margin-bottom: 16px;"> <el-alert type="warning" :closable="false" style="margin-bottom: 16px;">
请立即复制 MCP地址、appId 和 appSecret!关弹窗后 appSecret 无法再次查看 请立即复制 connectCode 和 appSecret!关弹窗后无法再次查看
</el-alert> </el-alert>
<p>已为 {{ result.length }} 个客户生成 APIKey:</p> <p>已为 {{ result.length }} 个客户生成 APIKey:</p>
<el-table :data="result" border class="rr-apply-table rr-result-table" size="small"> <el-table :data="result" border class="rr-apply-table rr-result-table" size="small">
@ -360,11 +361,12 @@ function notifyContact() {
<code class="rr-cell-code">{{ row.appId }}</code> <code class="rr-cell-code">{{ row.appId }}</code>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="mcpEndpoint" label="MCP地址" min-width="220" show-overflow-tooltip> <el-table-column prop="connectCode" label="ConnectCode" min-width="160" show-overflow-tooltip>
<template #default="{ row }"> <template #default="{ row }">
<code class="rr-cell-code">{{ row.mcpEndpoint || '—' }}</code> <code class="rr-cell-code rr-code-accent">{{ row.connectCode }}</code>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="expireAt" label="过期时间" width="100" show-overflow-tooltip />
<el-table-column label="AppSecret" min-width="200"> <el-table-column label="AppSecret" min-width="200">
<template #default="{ row }"> <template #default="{ row }">
<div class="rr-secret-cell"> <div class="rr-secret-cell">

View File

@ -362,9 +362,6 @@ onMounted(() => { load(); loadCustomers() })
> >
<el-descriptions v-if="currentRow" :column="1" border> <el-descriptions v-if="currentRow" :column="1" border>
<el-descriptions-item label="AppID">{{ currentRow.appId }}</el-descriptions-item> <el-descriptions-item label="AppID">{{ currentRow.appId }}</el-descriptions-item>
<el-descriptions-item label="MCP地址">
<code>{{ (currentRow as any).mcpEndpoint || '—' }}</code>
</el-descriptions-item>
<el-descriptions-item label="应用名称">{{ currentRow.appName }}</el-descriptions-item> <el-descriptions-item label="应用名称">{{ currentRow.appName }}</el-descriptions-item>
<el-descriptions-item label="客户名称">{{ currentRow.customerName || currentRow.customerCode || '—' }}</el-descriptions-item> <el-descriptions-item label="客户名称">{{ currentRow.customerName || currentRow.customerCode || '—' }}</el-descriptions-item>
<el-descriptions-item label="客户标识">{{ currentRow.customerCode }}</el-descriptions-item> <el-descriptions-item label="客户标识">{{ currentRow.customerCode }}</el-descriptions-item>
@ -428,17 +425,18 @@ onMounted(() => { load(); loadCustomers() })
<p style="margin-bottom: 6px; font-size: 13px; color: var(--ink-2);"> <p style="margin-bottom: 6px; font-size: 13px; color: var(--ink-2);">
新的 AppSecret: <span style="color: var(--ink-3); font-size: 12px;">(明文, 可直接选中复制)</span> 新的 AppSecret: <span style="color: var(--ink-3); font-size: 12px;">(明文, 可直接选中复制)</span>
</p> </p>
<div style="display: flex; gap: 8px; align-items: center;"> <el-input
<el-input v-model="newSecret"
v-model="newSecret" readonly
readonly type="text"
type="text" size="default"
size="default" style="font-family: ui-monospace, monospace;"
style="flex: 1; font-family: ui-monospace, monospace;" @focus="onSecretInputFocus"
@focus="onSecretInputFocus" >
/> <template #append>
<el-button type="primary" style="flex-shrink: 0;" @click="copyText(newSecret, 'AppSecret 已复制')">复制</el-button> <el-button type="primary" @click="copyText(newSecret, 'AppSecret 已复制')">复制</el-button>
</div> </template>
</el-input>
</div> </div>
<template #footer> <template #footer>
<el-button v-if="!newSecret" @click="resetSecretVisible = false">取消</el-button> <el-button v-if="!newSecret" @click="resetSecretVisible = false">取消</el-button>

View File

@ -39,9 +39,12 @@ http.interceptors.response.use(
const body = response.data as ApiEnvelope | undefined const body = response.data as ApiEnvelope | undefined
if (body && typeof body === 'object' && 'code' in body) { if (body && typeof body === 'object' && 'code' in body) {
if (body.code === 0) return response if (body.code === 0) return response
// 业务级 code:401 (如 /openapi/** 带 token 时 Spring Security 返未授权) // 业务错:401 token 过期 / 其它业务错
// 不清 token 不跳登录,只 reject 给调用方处理 if (body.code === 401 || body.code === 401000) {
// 真正的 token 过期走 error 拦截器 (HTTP status 401) handleAuthExpired()
return Promise.reject(body)
}
// 业务错(不弹 toast,留给调用方决定)
return Promise.reject(body) return Promise.reject(body)
} }
return response return response