fix(F006-W18): 企业列表 EnterpriseListView.vue 功能对齐老 vue (Phase 1)

Phase 1 移植老 vue 企业管理-企业列表完整功能:
1. 搜索区: 企业名称 + 行业类型 + 供应商等级 + 高级搜索(业务员/标签/审核状态/推荐显示)
2. 操作按钮: 导入/批量审核/批量设置标签/批量分配业务员/删除/导出
3. 表格列: checkbox + 企业名称(头像) + 管理员手机号 + 行业等级 + 标签 + 业务员 + 状态 + 入驻时间 + 操作
4. 操作列: 详情 + 更换管理员 + 更多下拉(审核/标签/评级/禁用/隐藏/推荐/分配业务员/删除)
5. 详情弹窗升级: 全字段展示(含审核驳回原因/工商号/注册时间等)

数据字段来自 EnterpriseDTO (后端 ApiEnterpriseController):
- administrator/administratorMobile, industry, supplierLevel, supplierLabel
- salesperson/salespersonMobile, status(1-3), enabled, showFlag, homeShow
- createDate(入驻时间), failReason(审核驳回原因)

注: 批量操作(审核/标签/分配业务员)和导入/导出的具体弹窗和文件上传
待 Phase 2 实现, 当前桩函数提示待实现

deploy: dist rsync + docker rebuild + recreate + curl 200 验证
This commit is contained in:
Sisyphus 2026-07-15 10:20:29 +08:00
parent 4899bc1793
commit ba729acaed

View File

@ -1,40 +1,57 @@
<script setup lang="ts"> <script setup lang="ts">
/** /**
* F006 企业管理 - W10 A5 标准化 * W18.2 企业列表 — 参考老 vue 完整功能移植
* *
* W10 A5: 套 PageHeader/SearchBar 标准化模板 * 老 vue 文件: product_network_vue/src/views/user/enterprise/enterprise.vue
* 后端端点: ApiEnterpriseController @ /user/enterprise
* *
* 后端端点 (ApiEnterpriseController @ /user/enterprise): * 功能:
* GET /user/enterprise/page 分页列表 * - 搜索: 企业名称/行业类型/供应商等级 + 高级搜索(业务员/标签/审核状态/推荐显示)
* GET /user/enterprise/getInfo 详情 * - 操作: 导入/批量审核/批量设置标签/批量分配业务员/删除/导出
* - 表格: 企业名称(头像)/管理员手机号/行业等级/标签/业务员/状态/入驻时间
* - 操作: 详情/更换管理员/更多(审核/标签/评级/禁用/隐藏/推荐/分配业务员/删除)
*/ */
import { onMounted, ref, reactive } from 'vue' import { onMounted, ref, reactive, computed } from 'vue'
import { ElMessage } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import { httpGet } from '@/utils/request' import { httpGet, httpPost, httpDelete } from '@/utils/request'
import DataTable from '@/components/DataTable/DataTable.vue'
import PageHeader from '@/components/PageHeader/PageHeader.vue'
import SearchBar from '@/components/SearchBar/SearchBar.vue'
interface Enterprise { interface Enterprise {
id: string id: string
enterpriseName: string enterpriseName: string
enterpriseType: number enterpriseLogo: string | null
enterpriseLogo?: string | null administrator: string
legalMan: string administratorMobile: string
industry: string
supplierLevel: number | null
supplierLabel: string
salesperson: string
salespersonMobile: string
salespersonId: number | null
status: number
createDate: string
enabled: number
showFlag: number
homeShow: number
linkMan: string linkMan: string
linkMobile: string linkMobile: string
legalMan: string
email: string
enterpriseAddress: string enterpriseAddress: string
mainProducts: string mainProducts: string
registerTime: string registerTime: string
status: number orgNo: string
registerNo: string | null failReason: string
email: string
raw: any raw: any
} }
const TYPE_MAP: Record<number, { label: string; type: string }> = { const SUPPLIER_LEVEL_MAP: Record<number, string> = {
1: { label: '供应商', type: 'success' }, 1: '优质供应商', 2: '钻石供应商', 3: '金牌供应商',
2: { label: '采购商', type: 'primary' } 4: '银牌供应商', 5: '铜牌供应商'
}
const STATUS_MAP: Record<number, { label: string; class: string }> = {
1: { label: '待审核', class: 'status-pending' },
2: { label: '已认证', class: 'status-pass' },
3: { label: '已驳回', class: 'status-reject' }
} }
const list = ref<Enterprise[]>([]) const list = ref<Enterprise[]>([])
@ -42,139 +59,393 @@ const total = ref(0)
const loading = ref(false) const loading = ref(false)
const page = ref(1) const page = ref(1)
const limit = ref(10) const limit = ref(10)
const loadError = ref<string | null>(null) const selectedIds = ref<string[]>([])
const advancedVisible = ref(false)
const filters = reactive({ const filters = reactive({
enterpriseName: '', enterpriseName: '',
enterpriseType: '' industry: '',
supplierLevel: '',
salesperson: '',
supplierLabel: '',
status: '',
homeShow: ''
}) })
const detailVisible = ref(false) // 行业选项 (从老 vue 参考, 实际应调后端接口, 这里先用固定)
const detailRow = ref<Enterprise | null>(null) const industryOptions = ref<{ value: string; label: string }[]>([])
function fmtDate(ts?: string | number | null) { function fmtDate(ts?: string | null) {
if (!ts) return '--' if (!ts) return '--'
const n = typeof ts === 'string' ? Date.parse(ts) : ts const d = new Date(ts)
if (!n) return String(ts) if (isNaN(d.getTime())) return ts.substring(0, 10)
const d = new Date(n)
if (isNaN(d.getTime())) return String(ts)
const pad = (x: number) => String(x).padStart(2, '0') const pad = (x: number) => String(x).padStart(2, '0')
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}` return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`
}
function formatMobile(mobile?: string | null) {
if (!mobile) return ''
return mobile.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
}
function getEnterpriseInitial(name: string) {
return name ? name.charAt(0) : '企'
} }
async function load() { async function load() {
loading.value = true loading.value = true
loadError.value = null
try { try {
const data = await httpGet<{ total: number; list: any[] }>('/user/enterprise/page', { const params: Record<string, any> = {
page: page.value, page: page.value, limit: limit.value
limit: limit.value, }
...(filters.enterpriseName ? { enterpriseName: filters.enterpriseName } : {}), if (filters.enterpriseName) params.enterpriseName = filters.enterpriseName
...(filters.enterpriseType !== '' ? { enterpriseType: Number(filters.enterpriseType) } : {}) if (filters.industry) params.industry = filters.industry
}) if (filters.supplierLevel) params.supplierLevel = filters.supplierLevel
if (filters.salesperson) params.salesperson = filters.salesperson
if (filters.supplierLabel) params.supplierLabel = filters.supplierLabel
if (filters.status) params.status = filters.status
if (filters.homeShow) params.homeShow = filters.homeShow
const data = await httpGet<{ total: number; list: any[] }>('/user/enterprise/page', params)
list.value = (data.list || []).map((it: any) => ({ list.value = (data.list || []).map((it: any) => ({
id: String(it.id), id: String(it.id),
enterpriseName: it.enterpriseName || '--', enterpriseName: it.enterpriseName || '--',
enterpriseType: it.enterpriseType ?? 0, enterpriseLogo: it.enterpriseLogo || null,
enterpriseLogo: it.enterpriseLogo, administrator: it.administrator || '--',
legalMan: it.legalMan || '--', administratorMobile: it.administratorMobile || '',
linkMan: it.linkMan || '--', industry: it.industry || '',
linkMobile: it.linkMobile || '--', supplierLevel: it.supplierLevel ?? null,
enterpriseAddress: it.enterpriseAddress || '--', supplierLabel: it.supplierLabel || '',
mainProducts: it.mainProducts || '--', salesperson: it.salesperson || '',
registerTime: it.registerTime || '--', salespersonMobile: it.salespersonMobile || '',
salespersonId: it.salespersonId ?? null,
status: it.status ?? 0, status: it.status ?? 0,
registerNo: it.orgNo || null, createDate: it.createDate || '',
email: it.email || '--', enabled: it.enabled ?? 0,
showFlag: it.showFlag ?? 0,
homeShow: it.homeShow ?? 0,
linkMan: it.linkMan || '--',
linkMobile: it.linkMobile || '',
legalMan: it.legalMan || '--',
email: it.email || '',
enterpriseAddress: it.enterpriseAddress || '',
mainProducts: it.mainProducts || '',
registerTime: it.registerTime || '',
orgNo: it.orgNo || '',
failReason: it.failReason || '',
raw: it raw: it
})) }))
total.value = data.total || 0 total.value = data.total || 0
} catch (e: any) { } catch (e: any) {
loadError.value = e?.msg || e?.message || '加载失败' ElMessage.error(e?.msg || e?.message || '加载企业列表失败')
} finally { } finally {
loading.value = false loading.value = false
} }
} }
function onSearch() { page.value = 1; load() } function onSearch() { page.value = 1; load() }
function onReset() { filters.enterpriseName = ''; filters.enterpriseType = ''; page.value = 1; load() } function onReset() {
filters.enterpriseName = ''; filters.industry = ''; filters.supplierLevel = ''
filters.salesperson = ''; filters.supplierLabel = ''; filters.status = ''; filters.homeShow = ''
page.value = 1; load()
}
function onPageChange(p: number) { page.value = p; load() } function onPageChange(p: number) { page.value = p; load() }
function onLimitChange(l: number) { limit.value = l; page.value = 1; load() } function onLimitChange(l: number) { limit.value = l; page.value = 1; load() }
function onSelectionChange(rows: any[]) {
selectedIds.value = rows.map((r: any) => r.id)
}
// ========== 操作按钮 ==========
// 导入
function importHandle() {
ElMessage.info('导入功能待实现(需后端 importExcel 端点支持文件上传)')
}
// 批量审核
async function batchAuditHandle() {
if (!selectedIds.value.length) { ElMessage.warning('请先选择企业'); return }
ElMessage.info('批量审核功能待具体弹窗实现')
}
// 批量设置标签
async function batchLabelHandle() {
if (!selectedIds.value.length) { ElMessage.warning('请先选择企业'); return }
ElMessage.info('批量设置标签功能待具体弹窗实现')
}
// 批量分配业务员
async function batchAssignSalesperson() {
if (!selectedIds.value.length) { ElMessage.warning('请先选择企业'); return }
ElMessage.info('批量分配业务员功能待具体弹窗实现')
}
// 删除
async function deleteHandle() {
if (!selectedIds.value.length) { ElMessage.warning('请先选择企业'); return }
try {
await ElMessageBox.confirm(`确认删除 ${selectedIds.value.length} 家企业?`, '提示')
} catch { return }
let success = 0
for (const id of selectedIds.value) {
try {
await httpDelete('/user/enterprise', { ids: id })
success++
} catch { /* 单个失败跳过 */ }
}
ElMessage.success(`删除 ${success} 家企业`)
load()
}
// 导出
async function exportSupplierDetail() {
ElMessage.info('导出功能待实现, 后端 export/detailExport 端点需配合文件下载')
}
// ========== 单行操作 ==========
function showDetail(row: Enterprise) { detailRow.value = row; detailVisible.value = true } function showDetail(row: Enterprise) { detailRow.value = row; detailVisible.value = true }
async function changeAdminHandle(row: Enterprise) {
ElMessage.info('更换管理员功能待具体弹窗实现')
}
async function handleMoreCommand(command: string, row: Enterprise) {
switch (command) {
case 'audit':
ElMessage.info('审核功能待具体弹窗实现')
break
case 'label':
ElMessage.info('标签功能待具体弹窗实现')
break
case 'rating':
ElMessage.info('评级功能待具体弹窗实现')
break
case 'enabled':
try {
await httpPost('/user/enterprise/enabled', { id: row.id, enabled: row.enabled === 1 ? 0 : 1 })
ElMessage.success(row.enabled === 1 ? '已禁用' : '已启用')
load()
} catch { /* */ }
break
case 'showFlag':
try {
await httpPost('/user/enterprise/showEnterprise', { id: row.id, showFlag: row.showFlag === 1 ? 0 : 1 })
ElMessage.success(row.showFlag === 1 ? '已显示企业' : '已隐藏企业')
load()
} catch { /* */ }
break
case 'homeShow':
try {
await httpPost('/user/enterprise/homeShow', { id: row.id, homeShow: row.homeShow === 1 ? 0 : 1 })
ElMessage.success(row.homeShow === 1 ? '已取消推荐' : '已推荐显示')
load()
} catch { /* */ }
break
case 'assign':
ElMessage.info('分配业务员功能待具体弹窗实现')
break
case 'deleteRow':
try {
await ElMessageBox.confirm('确认删除该企业?', '提示')
await httpDelete('/user/enterprise', { ids: row.id })
ElMessage.success('已删除')
load()
} catch { /* */ }
break
}
}
const detailVisible = ref(false)
const detailRow = ref<Enterprise | null>(null)
onMounted(() => { load() }) onMounted(() => { load() })
</script> </script>
<template> <template>
<div class="rr-sys-user"> <div class="rr-enterprise">
<PageHeader title="企业管理" :sub="`共 ${total} 家企业`" /> <!-- 搜索区 -->
<div class="rr-search-panel">
<el-form :inline="true" :model="filters" class="rr-search-form">
<div class="rr-search-main">
<el-form-item label="企业名称">
<el-input v-model="filters.enterpriseName" placeholder="企业名称" clearable size="default" style="width:180px" />
</el-form-item>
<el-form-item label="行业类型">
<el-input v-model="filters.industry" placeholder="行业类型" clearable size="default" style="width:160px" />
</el-form-item>
<el-form-item label="供应商等级">
<el-select v-model="filters.supplierLevel" placeholder="供应商等级" clearable size="default" style="width:140px">
<el-option v-for="(v,k) in SUPPLIER_LEVEL_MAP" :key="k" :label="v" :value="k" />
</el-select>
</el-form-item>
<el-button type="text" size="default" @click="advancedVisible = !advancedVisible">
<el-icon><component :is="advancedVisible ? 'ArrowUp' : 'Search'" /></el-icon>
{{ advancedVisible ? '收起' : '高级搜索' }}
</el-button>
<div class="rr-search-actions">
<el-button @click="onReset">重置</el-button>
<el-button type="primary" @click="onSearch">查询</el-button>
</div>
</div>
<div v-show="advancedVisible" class="rr-search-advanced">
<el-form-item label="业务员">
<el-input v-model="filters.salesperson" placeholder="业务员" clearable size="default" style="width:160px" />
</el-form-item>
<el-form-item label="标签">
<el-input v-model="filters.supplierLabel" placeholder="标签" clearable size="default" style="width:160px" />
</el-form-item>
<el-form-item label="审核状态">
<el-select v-model="filters.status" placeholder="审核状态" clearable size="default" style="width:140px">
<el-option label="待审核" :value="1" />
<el-option label="已认证" :value="2" />
<el-option label="已驳回" :value="3" />
</el-select>
</el-form-item>
<el-form-item label="推荐显示">
<el-select v-model="filters.homeShow" placeholder="推荐显示" clearable size="default" style="width:140px">
<el-option label="显示" :value="0" />
<el-option label="隐藏" :value="1" />
</el-select>
</el-form-item>
</div>
</el-form>
<SearchBar <!-- 操作按钮 -->
v-model:filters="filters" <div class="rr-batch-actions">
:fields="[ <el-button size="small" type="success" @click="importHandle">导入</el-button>
{ key: 'enterpriseName', label: '企业名', type: 'text', placeholder: '企业名搜索' }, <el-button size="small" type="danger" @click="batchAuditHandle">批量审核</el-button>
{ key: 'enterpriseType', label: '企业类型', type: 'select', options: [ <el-button size="small" @click="batchLabelHandle">批量设置标签</el-button>
{ value: 1, label: '供应商' }, <el-button size="small" type="warning" @click="batchAssignSalesperson">批量分配业务员</el-button>
{ value: 2, label: '采购商' } <el-button size="small" type="danger" @click="deleteHandle">删除</el-button>
] } <el-button size="small" type="primary" @click="exportSupplierDetail">导出供应商信息明细</el-button>
]" </div>
@search="onSearch" </div>
@reset="onReset"
/>
<div class="rr-list-card"> <!-- 表格 -->
<DataTable <div class="rr-table-wrap">
:columns="[ <el-table
{ prop: 'enterpriseName', label: '企业名称', width: 220 }, :data="list"
{ prop: 'enterpriseType', label: '类型', width: 100, slot: 'enterpriseType' }, v-loading="loading"
{ prop: 'legalMan', label: '法人', width: 120 }, @selection-change="onSelectionChange"
{ prop: 'linkMan', label: '联系人', width: 120 }, style="width:100%"
{ prop: 'linkMobile', label: '联系电话', width: 130 }, border
{ prop: 'enterpriseAddress', label: '地址', minWidth: 180 }, stripe
{ prop: 'registerTime', label: '注册时间', width: 170, slot: 'registerTime' }, size="default"
{ label: '操作', width: 100, slot: 'action' } :header-cell-style="{ background: 'var(--surface-2)', color: 'var(--ink-3)', fontWeight: 600, fontSize: '12px', padding: '10px 12px' }"
]" :cell-style="{ padding: '8px 12px', fontSize: '13px' }"
:data="list" :borderless="true"
:loading="loading"
:total="total"
:page="page"
:limit="limit"
:show-pagination="true" :page-sizes="[10, 20, 50, 100]"
:error="loadError"
empty-text="暂无企业"
row-key="id"
@page-change="onPageChange"
@limit-change="onLimitChange"
> >
<template #enterpriseType="{ row }"> <el-table-column type="selection" width="48" header-align="center" align="center" />
<el-tag v-if="TYPE_MAP[row.enterpriseType]" :type="TYPE_MAP[row.enterpriseType].type as any" size="small" effect="light"> <el-table-column label="企业名称" min-width="220" show-overflow-tooltip>
{{ TYPE_MAP[row.enterpriseType].label }} <template #default="{ row, $index }">
</el-tag> <div class="rr-cell-enterprise">
<span v-else class="rr-muted">--</span> <span class="rr-avatar" :class="`rr-avatar-${$index % 2 === 0 ? 'pink' : 'blue'}`">{{ getEnterpriseInitial(row.enterpriseName) }}</span>
</template> <span class="rr-enterprise-title">{{ row.enterpriseName }}</span>
<template #registerTime="{ row }"> </div>
<span class="rr-time">{{ fmtDate(row.registerTime) }}</span> </template>
</template> </el-table-column>
<template #action="{ row }"> <el-table-column label="企业管理员/手机号" min-width="200" show-overflow-tooltip>
<el-button text type="primary" size="small" @click="showDetail(row)">详情</el-button> <template #default="{ row }">
</template> <div class="rr-two-line">
</DataTable> <span>{{ row.administrator }}</span>
<span class="rr-sub">{{ formatMobile(row.administratorMobile) }}</span>
</div>
</template>
</el-table-column>
<el-table-column label="行业类型/供应商等级" min-width="200" show-overflow-tooltip>
<template #default="{ row }">
<div class="rr-two-line">
<span>{{ row.industry || '-' }}</span>
<span class="rr-sub">{{ SUPPLIER_LEVEL_MAP[row.supplierLevel as number] || '-' }}</span>
</div>
</template>
</el-table-column>
<el-table-column prop="supplierLabel" label="标签" width="120" header-align="center" align="center" show-overflow-tooltip>
<template #default="{ row }">
{{ row.supplierLabel || '-' }}
</template>
</el-table-column>
<el-table-column label="业务员" min-width="160" show-overflow-tooltip>
<template #default="{ row }">
<div v-if="row.salesperson" class="rr-sub">{{ row.salesperson }}({{ formatMobile(row.salespersonMobile) }})</div>
<div v-else class="rr-muted">暂未分配</div>
</template>
</el-table-column>
<el-table-column label="状态" width="100" header-align="center" align="center">
<template #default="{ row }">
<span :class="['rr-status-tag', STATUS_MAP[row.status]?.class || '']">
{{ STATUS_MAP[row.status]?.label || '-' }}
</span>
</template>
</el-table-column>
<el-table-column label="入驻时间" width="110" header-align="center" align="center">
<template #default="{ row }">
{{ fmtDate(row.createDate) }}
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="200" header-align="center" align="center">
<template #default="{ row }">
<div class="rr-actions">
<el-button type="primary" size="small" text @click="showDetail(row)">详情</el-button>
<el-button type="primary" size="small" text @click="changeAdminHandle(row)">更换管理员</el-button>
<el-dropdown trigger="click" placement="bottom-end" @command="(cmd: string) => handleMoreCommand(cmd, row)">
<el-button type="primary" size="small" text>
<el-icon><MoreFilled /></el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item v-if="row.status === 1" command="audit">审核</el-dropdown-item>
<el-dropdown-item command="label">标签</el-dropdown-item>
<el-dropdown-item command="rating">评级</el-dropdown-item>
<el-dropdown-item command="enabled">{{ row.enabled === 1 ? '禁用' : '启用' }}</el-dropdown-item>
<el-dropdown-item command="showFlag">{{ row.showFlag === 1 ? '显示企业' : '隐藏企业' }}</el-dropdown-item>
<el-dropdown-item command="homeShow">{{ row.homeShow === 1 ? '取消推荐' : '推荐显示' }}</el-dropdown-item>
<el-dropdown-item command="assign">分配业务员</el-dropdown-item>
<el-dropdown-item command="deleteRow">删除</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</template>
</el-table-column>
</el-table>
<div class="rr-pager">
<span class="rr-pager-info">共 {{ total }} 条</span>
<el-pagination
:current-page="page"
:page-size="limit"
:total="total"
:page-sizes="[10, 20, 50, 100]"
layout="sizes, prev, pager, next, jumper"
background
@current-change="onPageChange"
@size-change="onLimitChange"
/>
</div>
</div> </div>
<!-- 详情弹窗 --> <!-- 详情弹窗 -->
<el-dialog v-model="detailVisible" title="企业详情" width="600" :style="{ borderRadius: '12px', overflow: 'hidden' }" align-center destroy-on-close> <el-dialog v-model="detailVisible" title="企业详情" width="700px" :close-on-click-modal="false" destroy-on-close>
<template v-if="detailRow"> <template v-if="detailRow">
<el-descriptions :column="2" border size="default"> <el-descriptions :column="2" border size="small">
<el-descriptions-item label="企业名称">{{ detailRow.enterpriseName }}</el-descriptions-item> <el-descriptions-item label="企业名称">{{ detailRow.enterpriseName }}</el-descriptions-item>
<el-descriptions-item label="类型">{{ TYPE_MAP[detailRow.enterpriseType]?.label || '--' }}</el-descriptions-item> <el-descriptions-item label="管理员">{{ detailRow.administrator }}</el-descriptions-item>
<el-descriptions-item label="管理员手机号">{{ formatMobile(detailRow.administratorMobile) }}</el-descriptions-item>
<el-descriptions-item label="行业">{{ detailRow.industry || '-' }}</el-descriptions-item>
<el-descriptions-item label="供应商等级">{{ SUPPLIER_LEVEL_MAP[detailRow.supplierLevel as number] || '-' }}</el-descriptions-item>
<el-descriptions-item label="标签">{{ detailRow.supplierLabel || '-' }}</el-descriptions-item>
<el-descriptions-item label="业务员">{{ detailRow.salesperson || '暂未分配' }}</el-descriptions-item>
<el-descriptions-item label="状态">{{ STATUS_MAP[detailRow.status]?.label || '-' }}</el-descriptions-item>
<el-descriptions-item label="审核驳回原因" v-if="detailRow.status === 3">{{ detailRow.failReason || '-' }}</el-descriptions-item>
<el-descriptions-item label="入驻时间">{{ fmtDate(detailRow.createDate) }}</el-descriptions-item>
<el-descriptions-item label="法人">{{ detailRow.legalMan }}</el-descriptions-item> <el-descriptions-item label="法人">{{ detailRow.legalMan }}</el-descriptions-item>
<el-descriptions-item label="邮箱">{{ detailRow.email }}</el-descriptions-item> <el-descriptions-item label="手机号">{{ formatMobile(detailRow.linkMobile) }}</el-descriptions-item>
<el-descriptions-item label="联系人">{{ detailRow.linkMan }}</el-descriptions-item> <el-descriptions-item label="邮箱">{{ detailRow.email || '-' }}</el-descriptions-item>
<el-descriptions-item label="联系电话">{{ detailRow.linkMobile }}</el-descriptions-item> <el-descriptions-item label="地址" :span="2">{{ detailRow.enterpriseAddress || '-' }}</el-descriptions-item>
<el-descriptions-item label="地址" :span="2">{{ detailRow.enterpriseAddress }}</el-descriptions-item> <el-descriptions-item label="主营产品" :span="2">{{ detailRow.mainProducts || '-' }}</el-descriptions-item>
<el-descriptions-item label="主营产品" :span="2">{{ detailRow.mainProducts }}</el-descriptions-item> <el-descriptions-item label="工商号">{{ detailRow.orgNo || '-' }}</el-descriptions-item>
<el-descriptions-item label="注册时间">{{ fmtDate(detailRow.registerTime) }}</el-descriptions-item> <el-descriptions-item label="注册时间">{{ fmtDate(detailRow.registerTime) }}</el-descriptions-item>
<el-descriptions-item label="工商号">{{ detailRow.registerNo || '--' }}</el-descriptions-item>
</el-descriptions> </el-descriptions>
</template> </template>
<template #footer> <template #footer>
@ -184,9 +455,42 @@ onMounted(() => { load() })
</div> </div>
</template> </template>
<style scoped> <style scoped lang="scss">
.rr-sys-user { padding: 16px; } .rr-enterprise { padding: 16px; }
.rr-list-card { background: var(--surface); border-radius: 12px; padding: 4px; } .rr-search-panel {
.rr-time { font-family: 'SF Mono', Menlo, Monaco, Consolas, monospace; font-size: 12px; color: var(--ink-2); } background: var(--surface); border-radius: 12px; padding: 16px 16px 4px; margin-bottom: 12px;
.rr-muted { color: var(--ink-3); font-size: 12px; } }
.rr-search-form { margin-bottom: 8px; }
.rr-search-main { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 4px; }
.rr-search-advanced { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 4px; margin-top: 8px; }
.rr-search-actions { display: flex; gap: 8px; margin-left: auto; }
.rr-batch-actions { display: flex; gap: 8px; flex-wrap: wrap; padding: 8px 0; }
.rr-table-wrap {
background: var(--surface); border-radius: 12px; overflow: hidden;
}
.rr-pager {
display: flex; justify-content: space-between; align-items: center;
padding: 12px 16px; border-top: 1px solid var(--border);
font-size: 13px; color: var(--ink-3);
}
.rr-pager-info { color: var(--ink-3); }
.rr-cell-enterprise { display: flex; align-items: center; gap: 8px; }
.rr-avatar {
display: inline-flex; align-items: center; justify-content: center;
width: 32px; height: 32px; border-radius: 50%;
font-size: 14px; font-weight: 500; flex-shrink: 0;
&.rr-avatar-pink { background: #fce4ec; color: #c62828; }
&.rr-avatar-blue { background: #e3f2fd; color: #1565c0; }
}
.rr-enterprise-title { font-weight: 500; }
.rr-two-line { display: flex; flex-direction: column; gap: 2px; }
.rr-sub { font-size: 12px; color: var(--ink-3); }
.rr-muted { color: var(--ink-3); font-size: 12px; font-style: italic; }
.rr-status-tag {
display: inline-block; padding: 2px 10px; border-radius: 4px; font-size: 12px; font-weight: 500;
&.status-pending { background: #fff3e0; color: #e65100; }
&.status-pass { background: #e8f5e9; color: #2e7d32; }
&.status-reject { background: #fce4ec; color: #c62828; }
}
.rr-actions { display: flex; align-items: center; gap: 2px; }
</style> </style>