shinnosuke
2026-08-14 925ae2889d03adbf7d8f84ece394f32d5ab1fb70
fix: 优化核销失败提示与后台列表布局
3个文件已添加
12个文件已修改
179 ■■■■■ 已修改文件
rencaika_merchant/docs/pages/12-相机扫码.md 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rencaika_merchant/docs/pages/22-核销失败.md 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rencaika_merchant/docs/pages/README.md 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rencaika_merchant/docs/开发进度与注意事项.md 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rencaika_merchant/docs/项目接口对接说明.md 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rencaika_merchant/docs/项目说明.md 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rencaika_merchant/pages.json 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rencaika_merchant/pages/scan/scan.uvue 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rencaika_merchant/pages/verification-failure/verification-failure.uvue 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rencaika_merchant/static/icons/lucide/x-orange.svg 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
talent-card-admin/src/style.css 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
talent-card-admin/src/views/MerchantCreateView.vue 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
talent-card-admin/src/views/OrderDetailView.vue 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
talent-card-admin/src/views/ProductView.vue 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
talent-card-admin/src/views/TalentArticleManagementView.vue 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rencaika_merchant/docs/pages/12-相机扫码.md
@@ -17,13 +17,13 @@
| SC-002 | 原生层覆盖 | 扫描框、遮罩、返回按钮和状态卡使用 `cover-view` / `cover-image`。 | 已完成,待真机验证 |
| SC-003 | 扫码解析 | 扫码原文仅用于请求 `POST /api/merchant/verification/scan`,不写日志或持久缓存。 | 已接入 |
| SC-004 | 二次确认核销 | 解析成功后显示脱敏持卡人信息并要求确认;确认请求携带幂等键。 | 已接入 |
| SC-005 | 状态恢复 | 支持核验中、确认中、核销成功、失败重试、重新扫描和相机拒绝。 | 已完成 |
| SC-005 | 状态恢复 | 支持核验中、确认中、核销成功、普通失败重试、非当前商户独立失败页和相机拒绝。 | 已完成 |
| SC-006 | 返回 | 返回时取消当前请求并回到首页。 | 已完成 |
## 操作说明
1. 从首页进入相机扫码页,授权后将人才动态码置于扫描框内。
2. 扫码结果先由后台解析;解析失败可重试或重新扫描。
2. 扫码结果先由后台解析;非当前商户等商户范围错误进入独立失败结果页,其他解析失败可重试或重新扫描。
3. 解析成功后确认核销。成功后展示核销结果;失败时保留当前结果并可重试。
4. 点击左上角返回会取消当前请求并回到首页。
@@ -38,6 +38,7 @@
- [x] 首页扫码核销入口可跳转到相机扫码页。
- [x] 已实现扫描、服务端解析、二次确认、成功反馈和失败重试。
- [x] 非当前商户二维码使用独立核销失败页提示,返回后恢复扫码状态。
- [x] 扫码不会直接消耗动态码;仅确认成功才写入核销记录。
- [x] 重复确认通过幂等键返回同一次核销结果。
- [ ] 已真机验证相机授权、二维码识别、权限拒绝、原生层覆盖和网络重试。
rencaika_merchant/docs/pages/22-核销失败.md
New file
@@ -0,0 +1,36 @@
# 核销失败
## 基本信息
| 项目 | 内容 |
| --- | --- |
| 路由 | `/pages/verification-failure/verification-failure` |
| 页面目标 | 明确告知商户二维码无法在当前商户核销,并提供单一返回路径。 |
| 进入方式 | 相机扫码接口返回非当前商户相关的核销拒绝信息。 |
| 负责人/更新时间 | 待指定 / 2026-08-14 |
## 功能点
| 编号 | 功能 | 说明 | 当前状态 |
| --- | --- | --- | --- |
| VF-001 | 失败结果 | 独立展示“核销失败”和统一拒绝原因,不在相机页使用弹窗。 | 已完成 |
| VF-002 | 返回 | 顶部返回和页面“返回”按钮均回到扫码页,并恢复可扫描状态。 | 已完成 |
## 操作说明
1. 商户扫描不属于当前商户或不可核销的二维码。
2. 系统进入独立核销失败页,展示统一错误说明。
3. 点击顶部返回或页面“返回”按钮,回到相机页重新扫描。
## 异常处理
| 场景 | 用户可见提示 | 恢复方式 |
| --- | --- | --- |
| 无法返回扫码页 | 保持当前失败结果 | 自动返回商户端首页 |
## 验收清单
- [x] 页面结构与核销成功结果页保持一致。
- [x] 页面只保留“返回”主操作,不提供重试核销。
- [x] 返回扫码页后可重新扫描。
- [ ] 微信真机安全区、返回流程和视觉效果已验证。
rencaika_merchant/docs/pages/README.md
@@ -2,7 +2,7 @@
## 当前约定
截至 2026-08-12,商户端 `pages.json` 已注册 26 个页面,均已纳入操作说明。协议列表和协议详情共用 `08-商户协议.md`,因此当前共有 25 份页面说明。新增页面或既有页面交互发生变化时,必须同步更新:
截至 2026-08-14,商户端 `pages.json` 已注册 27 个页面。新增页面或既有页面交互发生变化时,必须同步更新:
- `docs/开发进度与注意事项.md`
- `docs/项目接口对接说明.md`
@@ -34,6 +34,7 @@
| 19 | 进件待审核 | `/pages/merchant-onboarding-pending/merchant-onboarding-pending` | 待审核结果与返回流程首版已完成 |
| 20 | 提现提交成功 | `/pages/withdrawal-success/withdrawal-success` | 提交结果与返回提现页流程已完成 |
| 21 | 结算管理 | `/pages/settlement-management/settlement-management` | 结算汇总、列表与导出已接入 |
| 22 | 核销失败 | `/pages/verification-failure/verification-failure` | 非当前商户二维码独立失败结果页已完成 |
- 文档编号必须唯一,页面目录、路由和文档标题应保持一致。
- 页面有多种业务状态时,可在同一说明中用“状态差异”说明,或增加明确命名的补充文档。
rencaika_merchant/docs/开发进度与注意事项.md
@@ -17,12 +17,12 @@
| uni-app X 工程骨架 | 已完成 | 使用 `.uvue` + `.uts`,已配置微信小程序目标。 |
| 微信小程序 AppID | 开发配置已应用 | 当前暂用人才端 `wx6ae2cadfea28fce1`;正式发布前必须替换为商户端独立 AppID。 |
| 请求与会话基础层 | 已完成首版 | 已建立 `config/api.uts`、`services/http.uts`、`services/session.uts` 和扫码业务服务,统一处理环境、请求头、超时、响应错误、`traceId` 与 401。 |
| 页面路由 | 已完成首版 | `pages.json` 已注册 26 个页面;页面源码和当前代码内跳转目标均存在,均为自定义导航样式。 |
| 页面路由 | 已完成首版 | `pages.json` 已注册 27 个页面;页面源码和当前代码内跳转目标均存在,均为自定义导航样式。 |
| 登录页视觉 | 已完成 | 已按设计稿实现欢迎区、插画、表单、协议和错误提示样式;密码框使用微信安全密码输入类型,避免 iOS 保存密码提示。 |
| 登录页演示流程 | 已完成 | 账号、密码和协议校验通过后直接进入首页;未接真实鉴权。 |
| 首页视觉 | 已完成 | 已实现经营汇总、统计卡、扫码核销主操作和底部导航。 |
| 首页数据 | 静态演示 | 当前展示设计示例数值,未接经营数据接口。 |
| 扫码核销 | 前端解析流程已完成 | 首页可进入原生后置相机扫码页;已读取真实扫码结果并调用统一服务,补齐核验中、成功、失败、重试、重新扫描和相机拒绝状态;后台联调与真机验证待完成。 |
| 扫码核销 | 前端解析流程已完成 | 首页可进入原生后置相机扫码页;已读取真实扫码结果并调用统一服务,补齐核验中、成功、普通失败重试、非当前商户独立失败页、重新扫描和相机拒绝状态;真机验证待完成。 |
| 订单管理 | 已接入订单列表 | 已接入团购、到店消费、免费入住订单的分页、稳定状态枚举、日期范围、脱敏字段、失败重试和开发演示数据开关;详情页仍沿用现有视觉结构。 |
| 待支付/已完成订单详情 | 已完成视觉与交互首版 | 已实现待支付、已完成两种状态、订单金额明细、人才权益信息与返回订单列表;团购已完成补齐撤销期限提示、二次确认、提交锁定和状态回退接口,待后台联调。 |
| 待核销订单详情 | 已完成视觉与静态交互首版 | 已实现商品摘要、订单金额明细、人才权益信息与固定确认核销操作。 |
@@ -122,6 +122,7 @@
| 2026-07-28 | 新增商户进件和进件待审核页面;提现入口根据未进件、待审核、审核通过三种状态分流,补齐企业/个人表单、日期与证件校验和敏感信息保护。HBuilderX 5.07 编译通过,共 21 个页面。 |
| 2026-07-28 | 新增提现提交成功页面;提现确认后替换填写页进入成功提醒,顶部返回和页面按钮均回到商户提现页。HBuilderX 5.07 微信小程序编译通过,共 22 个页面。 |
| 2026-08-12 | 新增商户中心结算管理页,接入后台现有商户结算统计接口,支持按日/月查看汇总、分页记录与 Excel 导出;补充页面路由、菜单入口和接口文档。 |
| 2026-08-14 | 商户端扫码核销新增独立失败结果页;非当前商户相关拒绝不再停留在相机页弹窗,返回后自动恢复扫码状态。 |
| 2026-07-28 | 团购已完成详情补齐撤销核销流程:已过后台结算周期时提示不可撤销,期限内二次确认后调用带幂等键的撤销接口,成功后按后端响应退回订单状态;到店消费仍不展示撤销操作。HBuilderX 5.07 微信小程序编译通过。 |
| 2026-07-28 | 集中优化可独立完成的 P1:订单状态改用稳定枚举并补齐按 ID 本地详情映射;商品路由携带商品/审核记录 ID,详情补齐表单绑定、校验、草稿与未保存提醒;登录协议入口接通;版本统一为 V1.0.0;缓存与会话分级清理;新增通用页面反馈组件。HBuilderX 5.07 微信小程序编译通过。 |
| 2026-07-28 | 集中优化可独立完成的 P2:首页、订单、商户中心统一使用动态安全区底部导航;新增一键静态检查/编译脚本、脱敏接口 Mock 契约、错误诊断与追踪编号复制;未引用图片移出运行时 `static/`。静态检查与 HBuilderX 5.07 微信小程序编译通过。 |
rencaika_merchant/docs/项目接口对接说明.md
@@ -125,7 +125,7 @@
1. 优先调用微信扫码能力,扫码结果只用于发起后端核验,不在客户端推导权益可用性。
2. 核销确认必须由服务端保证幂等;同一核销码重复提交应返回可识别的已处理结果。
3. 页面仅展示业务必要的脱敏用户信息,不缓存完整人才码、身份证号、手机号或订单敏感字段。
4. 扫码解析失败、已使用、已过期、无权限和网络超时均需给出明确且可恢复的提示。
4. 扫码解析失败、已使用、已过期、无权限和网络超时均需给出明确且可恢复的提示;非当前商户相关拒绝使用独立失败结果页,返回后恢复扫码。
5. 涉及金额、补贴和核销结果的所有最终判断均以后端返回为准。
## 统一异常处理要求
@@ -136,6 +136,7 @@
| 登录失效 | 清理会话并回登录页 | 重新登录 |
| 无门店权限 | 说明当前账号无可操作门店 | 联系管理员或切换账号 |
| 核销码无效/过期 | 显示具体原因,不显示成功态 | 重新扫码 |
| 二维码不属于当前商户 | 进入独立核销失败页并展示统一拒绝原因 | 点击“返回”后重新扫码 |
| 重复核销 | 显示已核销时间或记录入口 | 查看核销详情 |
| 服务端未知错误 | 显示通用失败提示并保留 `traceId` | 稍后重试或联系支持 |
rencaika_merchant/docs/项目说明.md
@@ -11,7 +11,7 @@
- [待处理事项](./待处理事项.md):本轮静态审计结论、上线阻塞、后端依赖和真机验收清单。
- [项目接口对接说明](./项目接口对接说明.md):建议接口边界、通用协议和异常处理要求。
- [开发进度与注意事项](./开发进度与注意事项.md):已完成页面、实现约定和更新记录。
- [页面操作说明索引](./pages/README.md):22 个注册页面对应的操作和验收说明。
- [页面操作说明索引](./pages/README.md):27 个注册页面的操作和验收说明索引。
## 技术框架
@@ -60,6 +60,7 @@
│  ├─ order-detail/order-detail.uvue # 待支付与已完成订单详情
│  ├─ verification-detail/verification-detail.uvue # 待核销订单详情
│  ├─ scan/scan.uvue                # 相机扫码核销
│  ├─ verification-failure/verification-failure.uvue # 核销失败结果
│  ├─ merchant/merchant.uvue        # 商户中心
│  ├─ withdrawal/withdrawal.uvue    # 商户提现
│  ├─ settlement-management/settlement-management.uvue # 结算管理
@@ -97,6 +98,7 @@
│  ├─ 经营数据总览
│  ├─ 扫码核销入口
│  │  └─ 相机扫码                       /pages/scan/scan
│  │     └─ 核销失败                     /pages/verification-failure/verification-failure
│  ├─ 订单管理                         /pages/orders/orders
│  │  ├─ 团购订单
│  │  │  └─ 待核销订单详情                  /pages/verification-detail/verification-detail
rencaika_merchant/pages.json
@@ -179,6 +179,14 @@
            }
        },
        {
            "path": "pages/verification-failure/verification-failure",
            "style": {
                "navigationStyle": "custom",
                "backgroundColor": "#F6F5F2",
                "disableScroll": true
            }
        },
        {
            "path": "pages/consume-input/consume-input",
            "style": {
                "navigationStyle": "custom",
rencaika_merchant/pages/scan/scan.uvue
@@ -36,6 +36,7 @@
    let lastScanResult = ''
    let openedManualConsumption = false
    let openedConfirmation = false
    let openedVerificationFailure = false
    let cancelVerificationRequest: (() => void) | null = null
    const cancelPendingRequest = () => {
@@ -51,8 +52,30 @@
        uni.navigateBack()
    }
    const isMerchantScopeFailure = (message: string): boolean => {
        return message.indexOf('当前商户') >= 0 || message.indexOf('本商户') >= 0
    }
    const openVerificationFailure = () => {
        openedVerificationFailure = true
        uni.navigateTo({
            url: '/pages/verification-failure/verification-failure',
            fail: () => {
                openedVerificationFailure = false
                scanState.value = 'error'
                statusTitle.value = '核销失败'
                statusMessage.value = '二维码已失效、不可核销或不属于当前商户'
                canRetryVerification.value = false
            }
        })
    }
    const showVerificationError = (error: HttpError) => {
        cancelVerificationRequest = null
        if (isMerchantScopeFailure(error.message)) {
            openVerificationFailure()
            return
        }
        scanState.value = 'error'
        statusTitle.value = error.code == 'STORE_CONTEXT_MISSING' ? '门店信息缺失' : '核验失败'
        statusMessage.value = error.message + (error.traceId.length > 0 ? '\n追踪号:' + error.traceId : '')
@@ -68,6 +91,10 @@
        cancelVerificationRequest = scanVerificationCode(rawResult, (result: VerificationScanResult, traceId: string) => {
            cancelVerificationRequest = null
            if (!result.canVerify) {
                if (isMerchantScopeFailure(result.message)) {
                    openVerificationFailure()
                    return
                }
                scanState.value = 'error'
                statusTitle.value = result.title
                statusMessage.value = result.message + (traceId.length > 0 ? '\n追踪号:' + traceId : '')
@@ -150,9 +177,10 @@
    })
    onShow(() => {
        if (!openedManualConsumption && !openedConfirmation) return
        if (!openedManualConsumption && !openedConfirmation && !openedVerificationFailure) return
        openedManualConsumption = false
        openedConfirmation = false
        openedVerificationFailure = false
        resetScanning()
    })
</script>
rencaika_merchant/pages/verification-failure/verification-failure.uvue
New file
@@ -0,0 +1,31 @@
<template>
    <view class="page">
        <view class="navigation-bar">
            <view class="back-button" @tap="goBack"><image class="back-icon" src="/static/icons/lucide/back-left.svg" mode="aspectFit"></image></view>
        </view>
        <view class="result-content">
            <view class="failure-shell"><image class="failure-icon" src="/static/icons/lucide/x-orange.svg" mode="aspectFit"></image></view>
            <text class="result-title">核销失败</text>
            <text class="result-message">二维码已失效、不可核销或不属于当前商户</text>
            <view class="return-button" @tap="goBack"><text>返回</text></view>
        </view>
    </view>
</template>
<script setup lang="uts">
    const goBack = () => uni.navigateBack({ delta: 1, fail: () => uni.reLaunch({ url: '/pages/index/index' }) })
</script>
<style>
    page { background-color: #F6F5F2; }
    .page { display: flex; width: 100%; height: 100vh; flex-direction: column; background-color: #F6F5F2; }
    .navigation-bar { display: flex; height: 176rpx; flex: none; justify-content: center; align-items: flex-end; padding-bottom: 26rpx; box-sizing: border-box; background-color: #FFFFFF; position: relative; }
    .back-button { display: flex; width: 72rpx; height: 72rpx; justify-content: center; align-items: center; position: absolute; left: 24rpx; bottom: 14rpx; }
    .back-icon { width: 38rpx; height: 38rpx; }
    .result-content { display: flex; flex: 1; padding: 222rpx 64rpx 0; flex-direction: column; align-items: center; box-sizing: border-box; }
    .failure-shell { display: flex; width: 144rpx; height: 144rpx; justify-content: center; align-items: center; border-width: 12rpx; border-style: solid; border-color: #FFD7C8; border-radius: 78rpx; background-color: #FFE9DF; box-sizing: border-box; }
    .failure-icon { width: 76rpx; height: 76rpx; }
    .result-title { margin-top: 38rpx; color: #273345; font-size: 32rpx; line-height: 45rpx; font-weight: 700; }
    .result-message { width: 540rpx; margin-top: 12rpx; color: #9AA6B8; font-size: 24rpx; line-height: 36rpx; text-align: center; }
    .return-button { display: flex; width: 216rpx; height: 68rpx; margin-top: 34rpx; justify-content: center; align-items: center; border-width: 1rpx; border-style: solid; border-color: #FFCCAA; border-radius: 36rpx; color: #FF6B3C; font-size: 25rpx; line-height: 35rpx; font-weight: 600; background-color: #FFF4E8; }
</style>
rencaika_merchant/static/icons/lucide/x-orange.svg
New file
@@ -0,0 +1,16 @@
<!-- @license lucide-static v0.468.0 - ISC -->
<svg
  class="lucide lucide-x"
  xmlns="http://www.w3.org/2000/svg"
  width="24"
  height="24"
  viewBox="0 0 24 24"
  fill="none"
  stroke="#FF6B2C"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
>
  <path d="M18 6 6 18" />
  <path d="m6 6 12 12" />
</svg>
talent-card-admin/src/style.css
@@ -334,6 +334,15 @@
  padding: 24px;
}
.admin-main > :not(.main-breadcrumb),
.admin-main .page-stack,
.admin-main .panel {
  box-sizing: border-box;
  width: 100%;
  min-width: 0;
  max-width: 100%;
}
.main-breadcrumb {
  display: flex;
  align-items: center;
@@ -492,6 +501,15 @@
.merchant-create-page {
  display: grid;
  gap: 14px;
}
.merchant-create-page > *,
.merchant-create-page .parking-address-table-wrapper,
.merchant-create-page .coupon-product-select-table,
.merchant-create-page .health-check-table-row > div {
  box-sizing: border-box;
  min-width: 0;
  max-width: 100%;
}
.merchant-create-tabs {
@@ -4699,6 +4717,8 @@
.el-table {
  --el-table-header-bg-color: #f8fafc;
  --el-table-header-text-color: #374151;
  width: 100%;
  max-width: 100%;
  border-radius: 8px;
}
talent-card-admin/src/views/MerchantCreateView.vue
@@ -2488,7 +2488,7 @@
                  <el-button type="primary" size="small" @click="markParkingLocation(row)">{{ row.latitude ? '已标点' : '未标点' }}</el-button>
                </template>
              </el-table-column>
              <el-table-column label="操作" width="100" align="center">
              <el-table-column label="操作" width="100" fixed="right" align="center">
                <template #default="{ $index }">
                  <el-button link type="danger" @click="removeParkingAddress($index)">删除</el-button>
                </template>
@@ -2537,7 +2537,7 @@
                  </el-checkbox-group>
                </template>
              </el-table-column>
              <el-table-column label="操作" min-width="160" align="center">
              <el-table-column label="操作" width="160" fixed="right" align="center">
                <template #default="{ $index, row }">
                  <el-button v-if="row.isNew || row.isEditing" link type="primary" @click="saveApprovalRow($index)">保存</el-button>
                  <el-button v-else link type="primary" @click="editApprovalRow($index)">编辑</el-button>
@@ -2558,7 +2558,7 @@
        <el-table :data="schoolAddresses" border>
          <el-table-column label="名称" prop="name" />
          <el-table-column label="地址" prop="address" />
          <el-table-column label="操作" width="120" align="center">
          <el-table-column label="操作" width="120" fixed="right" align="center">
            <template #default="{ $index }">
              <el-button link type="danger" @click="removeSchool($index)">删除</el-button>
              <el-button link type="primary" @click="openSchoolDialog($index)">详情</el-button>
@@ -2637,7 +2637,7 @@
            <el-table-column label="状态" min-width="90">
              <template #default="{ row }">{{ productAuditStatusText(row.auditStatus) }}</template>
            </el-table-column>
            <el-table-column label="操作" width="164" align="center">
            <el-table-column label="操作" width="164" fixed="right" align="center">
              <template #default="{ row }">
                <div class="merchant-products-operation">
                  <el-button link @click="editProduct(row)">编辑</el-button>
@@ -2794,7 +2794,7 @@
                    </el-checkbox-group>
                  </template>
                </el-table-column>
                <el-table-column label="操作" width="80" align="center">
                <el-table-column label="操作" width="80" fixed="right" align="center">
                  <template #default="{ $index }">
                    <el-button link type="primary" @click="removeHealthCheckItem($index)">删除</el-button>
                  </template>
@@ -2977,7 +2977,7 @@
            <el-table-column label="状态" min-width="90">
              <template #default="{ row }">{{ couponStatusText(row) }}</template>
            </el-table-column>
            <el-table-column label="操作" width="164" align="center">
            <el-table-column label="操作" width="164" fixed="right" align="center">
              <template #default="{ row }">
                <div class="merchant-coupons-operation">
                  <el-button link @click="editCoupon(row)">编辑</el-button>
talent-card-admin/src/views/OrderDetailView.vue
@@ -152,7 +152,7 @@
          <el-table-column label="商品金额" min-width="130" align="right">
            <template #default="{ row }">{{ money(row.amount) }}</template>
          </el-table-column>
          <el-table-column label="操作" width="100" align="center">
          <el-table-column label="操作" width="100" fixed="right" align="center">
            <template #default="{ row }">
              <el-button link type="primary" :disabled="!row.coverUrl" @click="previewImage(row.coverUrl)">查看</el-button>
            </template>
talent-card-admin/src/views/ProductView.vue
@@ -201,7 +201,7 @@
        <el-table-column label="状态" width="120" align="center">
          <template #default="{ row }">{{ auditStatusText(row.auditStatus) }}</template>
        </el-table-column>
        <el-table-column label="操作" width="180" align="center">
        <el-table-column label="操作" width="180" fixed="right" align="center">
          <template #default="{ row }">
            <el-button link type="primary" @click="viewDetail(row)">查看</el-button>
          </template>
talent-card-admin/src/views/TalentArticleManagementView.vue
@@ -66,7 +66,7 @@
        <el-table-column label="发布时间" width="170" align="center"><template #default="{ row }">{{ formatTime(row.publishTime) }}</template></el-table-column>
        <el-table-column prop="viewCount" label="观看数" width="100" align="center" />
        <el-table-column label="状态" width="100" align="center"><template #default="{ row }">{{ statusText(row.status) }}</template></el-table-column>
        <el-table-column label="操作" width="180" align="center"><template #default="{ row }"><el-button link type="primary" @click="toggleStatus(row)">{{ Number(row.status) === 1 ? '禁用' : '启用' }}</el-button><el-button link type="primary" @click="editArticle(row)">编辑</el-button></template></el-table-column>
        <el-table-column label="操作" width="180" fixed="right" align="center"><template #default="{ row }"><el-button link type="primary" @click="toggleStatus(row)">{{ Number(row.status) === 1 ? '禁用' : '启用' }}</el-button><el-button link type="primary" @click="editArticle(row)">编辑</el-button></template></el-table-column>
      </el-table>
      <div class="article-management-pagination"><el-pagination v-model:current-page="pagination.page" v-model:page-size="pagination.size" background layout="total, sizes, prev, pager, next" :page-sizes="[10, 20, 50]" :total="pagination.total" @change="load" /></div>
    </section>