This commit is contained in:
Mrx
2026-06-09 11:28:46 +08:00
parent c28f06411d
commit 9ef9ab4057
6 changed files with 106 additions and 15 deletions

View File

@@ -12,6 +12,12 @@
/> />
<div class="header-title"> <div class="header-title">
<img
v-if="logo"
class="header-logo"
:src="logo"
alt="天远数据 Logo"
/>
<h1 class="title-text">{{ title }}</h1> <h1 class="title-text">{{ title }}</h1>
<el-tag v-if="badge" :type="badgeType" size="small" class="badge-tag"> <el-tag v-if="badge" :type="badgeType" size="small" class="badge-tag">
{{ badge }} {{ badge }}
@@ -98,6 +104,10 @@ defineProps({
type: String, type: String,
required: true required: true
}, },
logo: {
type: String,
default: ''
},
badge: { badge: {
type: String, type: String,
default: '' default: ''
@@ -190,7 +200,14 @@ const handleUserCommand = async (command) => {
.header-title { .header-title {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 12px; gap: 10px;
}
.header-logo {
width: 32px;
height: 32px;
flex-shrink: 0;
object-fit: contain;
} }
.title-text { .title-text {

View File

@@ -9,6 +9,7 @@
<el-header class="el-header"> <el-header class="el-header">
<AppHeader <AppHeader
:title="headerTitle" :title="headerTitle"
:logo="headerLogo"
:badge="headerBadge" :badge="headerBadge"
:badge-type="headerBadgeType" :badge-type="headerBadgeType"
:theme="headerTheme" :theme="headerTheme"
@@ -52,6 +53,7 @@ import FloatingCustomerService from '@/components/common/FloatingCustomerService
import AppHeader from '@/components/layout/AppHeader.vue' import AppHeader from '@/components/layout/AppHeader.vue'
import AppSidebar from '@/components/layout/AppSidebar.vue' import AppSidebar from '@/components/layout/AppSidebar.vue'
import NotificationPanel from '@/components/layout/NotificationPanel.vue' import NotificationPanel from '@/components/layout/NotificationPanel.vue'
import headerLogo from '@/assets/logo.png'
import { isSubPortal } from '@/constants/portal' import { isSubPortal } from '@/constants/portal'
import { getCurrentPageCertificationConfig, getUserAccessibleMenuItems } from '@/constants/menu' import { getCurrentPageCertificationConfig, getUserAccessibleMenuItems } from '@/constants/menu'
import { useAppStore } from '@/stores/app' import { useAppStore } from '@/stores/app'
@@ -71,6 +73,7 @@ const headerTitle = computed(() => {
return isAdmin.value ? '天远数据控制台' : '天远数据控制台' return isAdmin.value ? '天远数据控制台' : '天远数据控制台'
}) })
const headerBadge = computed(() => { const headerBadge = computed(() => {
return isAdmin.value ? '管理员模式' : null return isAdmin.value ? '管理员模式' : null
}) })

View File

@@ -69,9 +69,9 @@
<el-table-column label="操作" width="240" fixed="right"> <el-table-column label="操作" width="240" fixed="right">
<template #default="{ row }"> <template #default="{ row }">
<el-button link type="primary" @click="openDetail(row.id)">查看详情</el-button> <el-button link type="primary" @click="openDetail(row.id)">查看详情</el-button>
<template v-if="canShowApproveReject(row)"> <template v-if="canShowApprove(row) || canShowReject(row)">
<el-button link type="success" @click="handleApprove(row)">通过</el-button> <el-button v-if="canShowApprove(row)" link type="success" @click="handleApprove(row)">通过</el-button>
<el-button link type="danger" @click="handleReject(row)">拒绝</el-button> <el-button v-if="canShowReject(row)" link type="danger" @click="handleReject(row)">拒绝</el-button>
</template> </template>
</template> </template>
</el-table-column> </el-table-column>
@@ -92,9 +92,9 @@
<div class="mobile-card-info"><span>统一代码</span>{{ row.unified_social_code || '-' }}</div> <div class="mobile-card-info"><span>统一代码</span>{{ row.unified_social_code || '-' }}</div>
<div class="mobile-card-actions"> <div class="mobile-card-actions">
<el-button type="primary" plain size="small" @click="openDetail(row.id)">查看详情</el-button> <el-button type="primary" plain size="small" @click="openDetail(row.id)">查看详情</el-button>
<template v-if="canShowApproveReject(row)"> <template v-if="canShowApprove(row) || canShowReject(row)">
<el-button type="success" plain size="small" @click="handleApprove(row)">通过</el-button> <el-button v-if="canShowApprove(row)" type="success" plain size="small" @click="handleApprove(row)">通过</el-button>
<el-button type="danger" plain size="small" @click="handleReject(row)">拒绝</el-button> <el-button v-if="canShowReject(row)" type="danger" plain size="small" @click="handleReject(row)">拒绝</el-button>
</template> </template>
</div> </div>
</article> </article>
@@ -125,9 +125,9 @@
<template #header> <template #header>
<span class="drawer-title">企业信息详情</span> <span class="drawer-title">企业信息详情</span>
<div class="drawer-actions"> <div class="drawer-actions">
<template v-if="detail && canShowApproveReject(detail)"> <template v-if="detail && (canShowApprove(detail) || canShowReject(detail))">
<el-button type="success" size="small" @click="approveFromDrawer">通过</el-button> <el-button v-if="canShowApprove(detail)" type="success" size="small" @click="approveFromDrawer">通过</el-button>
<el-button type="danger" size="small" @click="rejectFromDrawer">拒绝</el-button> <el-button v-if="canShowReject(detail)" type="danger" size="small" @click="rejectFromDrawer">拒绝</el-button>
</template> </template>
</div> </div>
</template> </template>
@@ -255,7 +255,7 @@
<script setup> <script setup>
import { certificationApi } from '@/api/index.js' import { certificationApi } from '@/api/index.js'
import { ElMessage } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
const loading = ref(false) const loading = ref(false)
const list = ref([]) const list = ref([])
@@ -333,12 +333,21 @@ function statusTagType(row) {
* 是否展示通过/拒绝:须当前认证为待审核,且本条提交记录为「校验通过」(verified)。 * 是否展示通过/拒绝:须当前认证为待审核,且本条提交记录为「校验通过」(verified)。
* 历史失败记录 (failed) 与认证状态无关字段共用同一 certification_status否则会误显按钮。 * 历史失败记录 (failed) 与认证状态无关字段共用同一 certification_status否则会误显按钮。
*/ */
function canShowApproveReject(row) { function canShowApprove(row) {
if (!row) return false if (!row) return false
if (row.certification_status !== 'info_pending_review') return false if (row.certification_status !== 'info_pending_review') return false
return row.status === 'verified' return row.status === 'verified'
} }
function canShowReject(row) {
if (!row) return false
const rejectableStatus =
row.certification_status === 'info_pending_review' ||
row.certification_status === 'info_submitted'
if (!rejectableStatus) return false
return row.status === 'verified'
}
// 判断是否可作为图片展示(含七牛云等无扩展名的 CDN URL // 判断是否可作为图片展示(含七牛云等无扩展名的 CDN URL
function isImageUrl(url) { function isImageUrl(url) {
if (!url || typeof url !== 'string') return false if (!url || typeof url !== 'string') return false
@@ -440,7 +449,27 @@ async function confirmApprove() {
pendingUserId.value = '' pendingUserId.value = ''
loadList() loadList()
} catch (e) { } catch (e) {
ElMessage.error(e?.message || '操作失败') const msg = e?.message || '操作失败'
if (msg.includes('生成企业认证链接失败')) {
const esignError = msg.replace(/^生成企业认证链接失败:\s*/, '')
try {
await ElMessageBox.confirm(
`企业认证链接生成失败:${esignError}\n\n请根据 e签宝 返回的错误信息填写拒绝原因并点击「拒绝」,以便用户修正后重新提交。`,
'无法通过审核',
{
type: 'warning',
confirmButtonText: '去填写拒绝原因',
cancelButtonText: '知道了'
}
)
rejectRemark.value = esignError
rejectDialogVisible.value = true
} catch {
// 用户点击「知道了」
}
} else {
ElMessage.error(msg)
}
} finally { } finally {
actionLoading.value = false actionLoading.value = false
} }

View File

@@ -14,6 +14,18 @@
</div> </div>
</template> </template>
<el-alert
v-if="showRejectionAlert"
type="error"
:closable="false"
show-icon
class="rejection-alert"
title="上次审核未通过"
>
<p class="rejection-message">{{ failureMessage }}</p>
<p class="rejection-hint">请根据以上原因修改企业信息后重新提交</p>
</el-alert>
<div class="enterprise-form"> <div class="enterprise-form">
<el-form <el-form
ref="enterpriseFormRef" ref="enterpriseFormRef"
@@ -383,9 +395,21 @@ const props = defineProps({
authorizedRepPhone: '', authorizedRepPhone: '',
authorizedRepIDImageURLs: [] authorizedRepIDImageURLs: []
}) })
},
certificationStatus: {
type: String,
default: ''
},
failureMessage: {
type: String,
default: ''
} }
}) })
const showRejectionAlert = computed(
() => props.certificationStatus === 'info_rejected' && !!props.failureMessage?.trim()
)
const emit = defineEmits(['submit']) const emit = defineEmits(['submit'])
const userStore = useUserStore() const userStore = useUserStore()
@@ -939,6 +963,22 @@ onUnmounted(() => {
overflow: hidden; overflow: hidden;
} }
.rejection-alert {
margin: 0 24px 16px;
}
.rejection-message {
margin: 0 0 4px;
line-height: 1.6;
white-space: pre-wrap;
}
.rejection-hint {
margin: 0;
font-size: 13px;
color: #909399;
}
/* 卡片头部 */ /* 卡片头部 */
.card-header { .card-header {
display: flex; display: flex;

View File

@@ -65,6 +65,8 @@
<EnterpriseInfo <EnterpriseInfo
v-if="currentStep === 'enterprise_info'" v-if="currentStep === 'enterprise_info'"
:form-data="enterpriseForm" :form-data="enterpriseForm"
:certification-status="certificationData?.status"
:failure-message="certificationData?.failure_message"
@submit="handleEnterpriseSubmit" @submit="handleEnterpriseSubmit"
/> />

View File

@@ -123,7 +123,7 @@ export default defineConfig({
}, },
server: { server: {
proxy: { proxy: {
// // 本地开发时将 /api/v1 的请求代理到 8080 端口 // 本地开发时将 /api/v1 的请求代理到 8080 端口
'/api/v1': { '/api/v1': {
target: 'http://localhost:8080', target: 'http://localhost:8080',
changeOrigin: true, changeOrigin: true,