fix(F006-W18): EnterpriseListView 完整重写 (UI规范+真实字段映射)
*** v2: 解决 v1 的两个根本问题 ***
问题 1: v1 的 endpoints page() 返回 EnterpriseFeignDTO (仅4个字段),
导致 administrator/industry/supplierLevel 等30+字段全缺。
根因: 上次 F002 修复把原始全字段 page 替换成了精简版 feign 端点。
修法: 把 F002 page 改名为 pageSimple, 恢复原始 EnterpriseDTO page 端点。
问题 2: v1 用原生 el-table 不守 UI 规范。
修法: 套 PageHeader/SearchBar/DataTable 组件 + 按项目设计规范。
改动:
- 后端: ApiEnterpriseController +pageSimple (F002 feign精简版) +page (全字段)
- 后端: EnterpriseFeign/fallback/OpenApiCustomerController 调 pageSimple
- 前端: EnterpriseListView 完整重写:
- PageHeader + SearchBar (企业名称/行业/供应商等级) + 批量操作栏
- DataTable: selection/企业名称(头像)/管理员+手机(两行)/行业+等级(两行)/标签/业务员/状态/入驻时间/操作
- 操作列: 详情/更换管理员/更多(审核/标签/评级/禁用/隐藏/推荐/分配/删除)
- 详情弹窗: EnterpriseDTO 全字段(含驳回原因/工商号/注册时间/法人)
- 字段映射: 完全来自后端 EnterpriseDTO (编译反编译确认所有字段存在)
- API: /user/enterprise/page 传 enterpriseName/industry/supplierLevel/salesperson/supplierLabel/status/homeShow 过滤
This commit is contained in:
parent
ba729acaed
commit
eaeb9f1aef
@ -1,37 +1,44 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
/**
|
/**
|
||||||
* W18.2 企业列表 — 参考老 vue 完整功能移植
|
* W18.2 企业列表 — 按项目 UI 规范 (PageHeader/SearchBar/DataTable) + 老 vue 全功能
|
||||||
*
|
*
|
||||||
* 老 vue 文件: product_network_vue/src/views/user/enterprise/enterprise.vue
|
|
||||||
* 后端端点: ApiEnterpriseController @ /user/enterprise
|
* 后端端点: ApiEnterpriseController @ /user/enterprise
|
||||||
|
* GET /user/enterprise/page 分页 (EnterpriseDTO 全字段, 支持 enterpriseName/industry/supplierLevel/salesperson/supplierLabel/status/homeShow 过滤)
|
||||||
*
|
*
|
||||||
* 功能:
|
* EnterpriseDTO 真实字段 (来源: devbox 编译反编译确认, 2026-07-15):
|
||||||
* - 搜索: 企业名称/行业类型/供应商等级 + 高级搜索(业务员/标签/审核状态/推荐显示)
|
* id/enterpriseName/enterpriseLogo/administrator/administratorMobile/industry/supplierLevel
|
||||||
* - 操作: 导入/批量审核/批量设置标签/批量分配业务员/删除/导出
|
* supplierLabel/salesperson/salespersonMobile/status/createDate/enabled/showFlag/homeShow
|
||||||
* - 表格: 企业名称(头像)/管理员手机号/行业等级/标签/业务员/状态/入驻时间
|
* linkMan/linkMobile/legalMan/email/enterpriseAddress/mainProducts/registerTime/orgNo/failReason
|
||||||
* - 操作: 详情/更换管理员/更多(审核/标签/评级/禁用/隐藏/推荐/分配业务员/删除)
|
|
||||||
*/
|
*/
|
||||||
import { onMounted, ref, reactive, computed } from 'vue'
|
import { onMounted, ref, reactive } from 'vue'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { httpGet, httpPost, httpDelete } 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
|
||||||
enterpriseLogo: string | null
|
enterpriseLogo: string | null
|
||||||
|
// 企业管理员
|
||||||
administrator: string
|
administrator: string
|
||||||
administratorMobile: string
|
administratorMobile: string
|
||||||
|
// 行业/等级/标签
|
||||||
industry: string
|
industry: string
|
||||||
supplierLevel: number | null
|
supplierLevel: number | null
|
||||||
supplierLabel: string
|
supplierLabel: string
|
||||||
|
// 业务员
|
||||||
salesperson: string
|
salesperson: string
|
||||||
salespersonMobile: string
|
salespersonMobile: string
|
||||||
salespersonId: number | null
|
salespersonId: number | null
|
||||||
status: number
|
// 状态相关
|
||||||
|
status: number | null // 1=待审核,2=已认证,3=已驳回
|
||||||
createDate: string
|
createDate: string
|
||||||
enabled: number
|
enabled: number | null // 0=正常,1=禁用
|
||||||
showFlag: number
|
showFlag: number | null // 0=显示,1=隐藏
|
||||||
homeShow: number
|
homeShow: number | null // 0=不推荐,1=推荐
|
||||||
|
// 其他详情用
|
||||||
linkMan: string
|
linkMan: string
|
||||||
linkMobile: string
|
linkMobile: string
|
||||||
legalMan: string
|
legalMan: string
|
||||||
@ -41,17 +48,6 @@ interface Enterprise {
|
|||||||
registerTime: string
|
registerTime: string
|
||||||
orgNo: string
|
orgNo: string
|
||||||
failReason: string
|
failReason: string
|
||||||
raw: any
|
|
||||||
}
|
|
||||||
|
|
||||||
const SUPPLIER_LEVEL_MAP: Record<number, string> = {
|
|
||||||
1: '优质供应商', 2: '钻石供应商', 3: '金牌供应商',
|
|
||||||
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[]>([])
|
||||||
@ -60,7 +56,8 @@ const loading = ref(false)
|
|||||||
const page = ref(1)
|
const page = ref(1)
|
||||||
const limit = ref(10)
|
const limit = ref(10)
|
||||||
const selectedIds = ref<string[]>([])
|
const selectedIds = ref<string[]>([])
|
||||||
const advancedVisible = ref(false)
|
const detailVisible = ref(false)
|
||||||
|
const detailRow = ref<Enterprise | null>(null)
|
||||||
|
|
||||||
const filters = reactive({
|
const filters = reactive({
|
||||||
enterpriseName: '',
|
enterpriseName: '',
|
||||||
@ -72,8 +69,19 @@ const filters = reactive({
|
|||||||
homeShow: ''
|
homeShow: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
// 行业选项 (从老 vue 参考, 实际应调后端接口, 这里先用固定)
|
// status 映射 (老 vue: 1=待审核,2=已认证,3=已驳回)
|
||||||
const industryOptions = ref<{ value: string; label: string }[]>([])
|
const STATUS_MAP: Record<string, string> = {
|
||||||
|
'1': '待审核', '2': '已认证', '3': '已驳回'
|
||||||
|
}
|
||||||
|
const STATUS_CLASS: Record<string, string> = {
|
||||||
|
'1': 'rr-tag-warn', '2': 'rr-tag-ok', '3': 'rr-tag-err'
|
||||||
|
}
|
||||||
|
|
||||||
|
// supplierLevel 映射 (老 vue: 1=优质,2=钻石,3=金牌,4=银牌,5=铜牌)
|
||||||
|
const LEVEL_MAP: Record<number, string> = {
|
||||||
|
1: '优质供应商', 2: '钻石供应商', 3: '金牌供应商',
|
||||||
|
4: '银牌供应商', 5: '铜牌供应商'
|
||||||
|
}
|
||||||
|
|
||||||
function fmtDate(ts?: string | null) {
|
function fmtDate(ts?: string | null) {
|
||||||
if (!ts) return '--'
|
if (!ts) return '--'
|
||||||
@ -83,30 +91,28 @@ function fmtDate(ts?: string | null) {
|
|||||||
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`
|
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatMobile(mobile?: string | null) {
|
function maskMobile(mobile?: string | null) {
|
||||||
if (!mobile) return ''
|
if (!mobile) return ''
|
||||||
return mobile.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
|
return mobile.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
|
||||||
}
|
}
|
||||||
|
|
||||||
function getEnterpriseInitial(name: string) {
|
/** 企业名首字 (Avatar 用) */
|
||||||
return name ? name.charAt(0) : '企'
|
function initial(name: string) { return name ? name.charAt(0) : '企' }
|
||||||
}
|
|
||||||
|
|
||||||
async function load() {
|
async function load() {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
const params: Record<string, any> = {
|
const params: Record<string, any> = { page: page.value, limit: limit.value }
|
||||||
page: page.value, limit: limit.value
|
|
||||||
}
|
|
||||||
if (filters.enterpriseName) params.enterpriseName = filters.enterpriseName
|
if (filters.enterpriseName) params.enterpriseName = filters.enterpriseName
|
||||||
if (filters.industry) params.industry = filters.industry
|
if (filters.industry) params.industry = filters.industry
|
||||||
if (filters.supplierLevel) params.supplierLevel = filters.supplierLevel
|
if (filters.supplierLevel) params.supplierLevel = Number(filters.supplierLevel)
|
||||||
if (filters.salesperson) params.salesperson = filters.salesperson
|
if (filters.salesperson) params.salesperson = filters.salesperson
|
||||||
if (filters.supplierLabel) params.supplierLabel = filters.supplierLabel
|
if (filters.supplierLabel) params.supplierLabel = filters.supplierLabel
|
||||||
if (filters.status) params.status = filters.status
|
if (filters.status) params.status = filters.status
|
||||||
if (filters.homeShow) params.homeShow = filters.homeShow
|
if (filters.homeShow) params.homeShow = filters.homeShow
|
||||||
|
|
||||||
const data = await httpGet<{ total: number; list: any[] }>('/user/enterprise/page', params)
|
const data = await httpGet<{ total: number; list: any[] }>('/user/enterprise/page', params)
|
||||||
|
// 映射后端 EnterpriseDTO → 前端 Enterprise 接口
|
||||||
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 || '--',
|
||||||
@ -119,11 +125,11 @@ async function load() {
|
|||||||
salesperson: it.salesperson || '',
|
salesperson: it.salesperson || '',
|
||||||
salespersonMobile: it.salespersonMobile || '',
|
salespersonMobile: it.salespersonMobile || '',
|
||||||
salespersonId: it.salespersonId ?? null,
|
salespersonId: it.salespersonId ?? null,
|
||||||
status: it.status ?? 0,
|
status: it.status ?? null,
|
||||||
createDate: it.createDate || '',
|
createDate: it.createDate || '',
|
||||||
enabled: it.enabled ?? 0,
|
enabled: it.enabled ?? null,
|
||||||
showFlag: it.showFlag ?? 0,
|
showFlag: it.showFlag ?? null,
|
||||||
homeShow: it.homeShow ?? 0,
|
homeShow: it.homeShow ?? null,
|
||||||
linkMan: it.linkMan || '--',
|
linkMan: it.linkMan || '--',
|
||||||
linkMobile: it.linkMobile || '',
|
linkMobile: it.linkMobile || '',
|
||||||
legalMan: it.legalMan || '--',
|
legalMan: it.legalMan || '--',
|
||||||
@ -132,8 +138,7 @@ async function load() {
|
|||||||
mainProducts: it.mainProducts || '',
|
mainProducts: it.mainProducts || '',
|
||||||
registerTime: it.registerTime || '',
|
registerTime: it.registerTime || '',
|
||||||
orgNo: it.orgNo || '',
|
orgNo: it.orgNo || '',
|
||||||
failReason: it.failReason || '',
|
failReason: it.failReason || ''
|
||||||
raw: it
|
|
||||||
}))
|
}))
|
||||||
total.value = data.total || 0
|
total.value = data.total || 0
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
@ -151,168 +156,96 @@ function onReset() {
|
|||||||
}
|
}
|
||||||
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[]) {
|
function onSelectionChange(rows: any[]) { selectedIds.value = rows.map((r: any) => r.id) }
|
||||||
selectedIds.value = rows.map((r: any) => r.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ========== 操作按钮 ==========
|
// ========== 批量操作 ==========
|
||||||
|
function importHandle() { ElMessage.info('导入功能待实现') }
|
||||||
// 导入
|
function batchAuditHandle() {
|
||||||
function importHandle() {
|
|
||||||
ElMessage.info('导入功能待实现(需后端 importExcel 端点支持文件上传)')
|
|
||||||
}
|
|
||||||
|
|
||||||
// 批量审核
|
|
||||||
async function batchAuditHandle() {
|
|
||||||
if (!selectedIds.value.length) { ElMessage.warning('请先选择企业'); return }
|
if (!selectedIds.value.length) { ElMessage.warning('请先选择企业'); return }
|
||||||
ElMessage.info('批量审核功能待具体弹窗实现')
|
ElMessage.info('批量审核功能待实现')
|
||||||
}
|
}
|
||||||
|
function batchLabelHandle() {
|
||||||
// 批量设置标签
|
|
||||||
async function batchLabelHandle() {
|
|
||||||
if (!selectedIds.value.length) { ElMessage.warning('请先选择企业'); return }
|
if (!selectedIds.value.length) { ElMessage.warning('请先选择企业'); return }
|
||||||
ElMessage.info('批量设置标签功能待具体弹窗实现')
|
ElMessage.info('批量设置标签待实现')
|
||||||
}
|
}
|
||||||
|
function batchAssignSalesperson() {
|
||||||
// 批量分配业务员
|
|
||||||
async function batchAssignSalesperson() {
|
|
||||||
if (!selectedIds.value.length) { ElMessage.warning('请先选择企业'); return }
|
if (!selectedIds.value.length) { ElMessage.warning('请先选择企业'); return }
|
||||||
ElMessage.info('批量分配业务员功能待具体弹窗实现')
|
ElMessage.info('分配业务员待实现')
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除
|
|
||||||
async function deleteHandle() {
|
async function deleteHandle() {
|
||||||
if (!selectedIds.value.length) { ElMessage.warning('请先选择企业'); return }
|
if (!selectedIds.value.length) { ElMessage.warning('请先选择企业'); return }
|
||||||
try {
|
try { await ElMessageBox.confirm(`确认删除 ${selectedIds.value.length} 家企业?`, '提示') } catch { return }
|
||||||
await ElMessageBox.confirm(`确认删除 ${selectedIds.value.length} 家企业?`, '提示')
|
let ok = 0
|
||||||
} catch { return }
|
|
||||||
let success = 0
|
|
||||||
for (const id of selectedIds.value) {
|
for (const id of selectedIds.value) {
|
||||||
try {
|
try { await httpDelete('/user/enterprise', { ids: id }); ok++ } catch {/* */}
|
||||||
await httpDelete('/user/enterprise', { ids: id })
|
|
||||||
success++
|
|
||||||
} catch { /* 单个失败跳过 */ }
|
|
||||||
}
|
}
|
||||||
ElMessage.success(`删除 ${success} 家企业`)
|
ElMessage.success(`删除 ${ok} 家企业`); load()
|
||||||
load()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 导出
|
function exportSupplierDetail() { ElMessage.info('导出待实现') }
|
||||||
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 }
|
||||||
|
function changeAdminHandle(_row: Enterprise) { ElMessage.info('更换管理员待实现') }
|
||||||
|
|
||||||
async function changeAdminHandle(row: Enterprise) {
|
async function handleMore(cmd: string, 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 {
|
try {
|
||||||
|
switch (cmd) {
|
||||||
|
case 'audit': ElMessage.info('审核待实现'); break
|
||||||
|
case 'label': ElMessage.info('标签待实现'); break
|
||||||
|
case 'rating': ElMessage.info('评级待实现'); break
|
||||||
|
case 'enabled':
|
||||||
await httpPost('/user/enterprise/enabled', { id: row.id, enabled: row.enabled === 1 ? 0 : 1 })
|
await httpPost('/user/enterprise/enabled', { id: row.id, enabled: row.enabled === 1 ? 0 : 1 })
|
||||||
ElMessage.success(row.enabled === 1 ? '已禁用' : '已启用')
|
ElMessage.success(row.enabled === 1 ? '已禁用' : '已启用'); load()
|
||||||
load()
|
|
||||||
} catch { /* */ }
|
|
||||||
break
|
break
|
||||||
case 'showFlag':
|
case 'showFlag':
|
||||||
try {
|
|
||||||
await httpPost('/user/enterprise/showEnterprise', { id: row.id, showFlag: row.showFlag === 1 ? 0 : 1 })
|
await httpPost('/user/enterprise/showEnterprise', { id: row.id, showFlag: row.showFlag === 1 ? 0 : 1 })
|
||||||
ElMessage.success(row.showFlag === 1 ? '已显示企业' : '已隐藏企业')
|
ElMessage.success(row.showFlag === 1 ? '已显示' : '已隐藏'); load()
|
||||||
load()
|
|
||||||
} catch { /* */ }
|
|
||||||
break
|
break
|
||||||
case 'homeShow':
|
case 'homeShow':
|
||||||
try {
|
|
||||||
await httpPost('/user/enterprise/homeShow', { id: row.id, homeShow: row.homeShow === 1 ? 0 : 1 })
|
await httpPost('/user/enterprise/homeShow', { id: row.id, homeShow: row.homeShow === 1 ? 0 : 1 })
|
||||||
ElMessage.success(row.homeShow === 1 ? '已取消推荐' : '已推荐显示')
|
ElMessage.success(row.homeShow === 1 ? '已取消推荐' : '已推荐'); load()
|
||||||
load()
|
|
||||||
} catch { /* */ }
|
|
||||||
break
|
|
||||||
case 'assign':
|
|
||||||
ElMessage.info('分配业务员功能待具体弹窗实现')
|
|
||||||
break
|
break
|
||||||
|
case 'assign': ElMessage.info('分配业务员待实现'); break
|
||||||
case 'deleteRow':
|
case 'deleteRow':
|
||||||
try {
|
try { await ElMessageBox.confirm('确认删除该企业?', '提示') } catch { return }
|
||||||
await ElMessageBox.confirm('确认删除该企业?', '提示')
|
|
||||||
await httpDelete('/user/enterprise', { ids: row.id })
|
await httpDelete('/user/enterprise', { ids: row.id })
|
||||||
ElMessage.success('已删除')
|
ElMessage.success('已删除'); load()
|
||||||
load()
|
|
||||||
} catch { /* */ }
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
} catch {/* */}
|
||||||
}
|
}
|
||||||
|
|
||||||
const detailVisible = ref(false)
|
onMounted(() => load())
|
||||||
const detailRow = ref<Enterprise | null>(null)
|
|
||||||
|
|
||||||
onMounted(() => { load() })
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="rr-enterprise">
|
<div class="rr-page">
|
||||||
<!-- 搜索区 -->
|
<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
|
||||||
<div class="rr-batch-actions">
|
v-model:filters="filters"
|
||||||
|
:fields="[
|
||||||
|
{ key: 'enterpriseName', label: '企业名称', type: 'text', placeholder: '企业名称' },
|
||||||
|
{ key: 'industry', label: '行业类型', type: 'text', placeholder: '行业类型' },
|
||||||
|
{ key: 'supplierLevel', label: '供应商等级', type: 'select', placeholder: '供应商等级',
|
||||||
|
options: [
|
||||||
|
{ value: 1, label: '优质供应商' },
|
||||||
|
{ value: 2, label: '钻石供应商' },
|
||||||
|
{ value: 3, label: '金牌供应商' },
|
||||||
|
{ value: 4, label: '银牌供应商' },
|
||||||
|
{ value: 5, label: '铜牌供应商' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]"
|
||||||
|
@search="onSearch"
|
||||||
|
@reset="onReset"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div class="rr-list-card">
|
||||||
|
<!-- 批量操作栏 -->
|
||||||
|
<div class="rr-batch-bar">
|
||||||
<el-button size="small" type="success" @click="importHandle">导入</el-button>
|
<el-button size="small" type="success" @click="importHandle">导入</el-button>
|
||||||
<el-button size="small" type="danger" @click="batchAuditHandle">批量审核</el-button>
|
<el-button size="small" type="danger" @click="batchAuditHandle">批量审核</el-button>
|
||||||
<el-button size="small" @click="batchLabelHandle">批量设置标签</el-button>
|
<el-button size="small" @click="batchLabelHandle">批量设置标签</el-button>
|
||||||
@ -320,86 +253,95 @@ onMounted(() => { load() })
|
|||||||
<el-button size="small" type="danger" @click="deleteHandle">删除</el-button>
|
<el-button size="small" type="danger" @click="deleteHandle">删除</el-button>
|
||||||
<el-button size="small" type="primary" @click="exportSupplierDetail">导出供应商信息明细</el-button>
|
<el-button size="small" type="primary" @click="exportSupplierDetail">导出供应商信息明细</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 表格 -->
|
<DataTable
|
||||||
<div class="rr-table-wrap">
|
:columns="[
|
||||||
<el-table
|
{ type: 'selection', width: 48 },
|
||||||
|
{ label: '企业名称', minWidth: 220, slot: 'enterpriseName' },
|
||||||
|
{ label: '企业管理员/手机号', minWidth: 200, slot: 'adminInfo' },
|
||||||
|
{ label: '行业类型/供应商等级', minWidth: 200, slot: 'levelInfo' },
|
||||||
|
{ prop: 'supplierLabel', label: '标签', width: 120, align: 'center' },
|
||||||
|
{ label: '业务员', minWidth: 160, slot: 'salespersonInfo' },
|
||||||
|
{ label: '状态', width: 100, slot: 'status' },
|
||||||
|
{ label: '入驻时间', width: 110, slot: 'createDate' },
|
||||||
|
{ label: '操作', width: 200, slot: 'action', fixed: 'right', align: 'center' }
|
||||||
|
]"
|
||||||
:data="list"
|
:data="list"
|
||||||
v-loading="loading"
|
:loading="loading"
|
||||||
|
:total="total"
|
||||||
|
:page="page"
|
||||||
|
:limit="limit"
|
||||||
|
:borderless="true"
|
||||||
|
:page-sizes="[10, 20, 50, 100]"
|
||||||
|
row-key="id"
|
||||||
|
empty-text="暂无企业"
|
||||||
|
@page-change="onPageChange"
|
||||||
|
@limit-change="onLimitChange"
|
||||||
@selection-change="onSelectionChange"
|
@selection-change="onSelectionChange"
|
||||||
style="width:100%"
|
|
||||||
border
|
|
||||||
stripe
|
|
||||||
size="default"
|
|
||||||
: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' }"
|
|
||||||
>
|
>
|
||||||
<el-table-column type="selection" width="48" header-align="center" align="center" />
|
<!-- 企业名称(带头像) -->
|
||||||
<el-table-column label="企业名称" min-width="220" show-overflow-tooltip>
|
<template #enterpriseName="{ row, $index }">
|
||||||
<template #default="{ row, $index }">
|
<div style="display:flex;align-items:center;gap:8px">
|
||||||
<div class="rr-cell-enterprise">
|
<span :style="{ display:'inline-flex',alignItems:'center',justifyContent:'center',
|
||||||
<span class="rr-avatar" :class="`rr-avatar-${$index % 2 === 0 ? 'pink' : 'blue'}`">{{ getEnterpriseInitial(row.enterpriseName) }}</span>
|
width:'32px',height:'32px',borderRadius:'50%',flexShrink:0,fontSize:'14px',fontWeight:500,
|
||||||
<span class="rr-enterprise-title">{{ row.enterpriseName }}</span>
|
background:$index%2===0?'#fce4ec':'#e3f2fd',color:$index%2===0?'#c62828':'#1565c0'
|
||||||
|
}">{{ initial(row.enterpriseName) }}</span>
|
||||||
|
<span style="font-weight:500">{{ row.enterpriseName }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="企业管理员/手机号" min-width="200" show-overflow-tooltip>
|
<!-- 企业管理员/手机号(两行) -->
|
||||||
<template #default="{ row }">
|
<template #adminInfo="{ row }">
|
||||||
<div class="rr-two-line">
|
<div style="display:flex;flex-direction:column;gap:2px">
|
||||||
<span>{{ row.administrator }}</span>
|
<span>{{ row.administrator }}</span>
|
||||||
<span class="rr-sub">{{ formatMobile(row.administratorMobile) }}</span>
|
<span style="font-size:12px;color:var(--ink-3)">{{ maskMobile(row.administratorMobile) }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="行业类型/供应商等级" min-width="200" show-overflow-tooltip>
|
<!-- 行业类型/供应商等级(两行) -->
|
||||||
<template #default="{ row }">
|
<template #levelInfo="{ row }">
|
||||||
<div class="rr-two-line">
|
<div style="display:flex;flex-direction:column;gap:2px">
|
||||||
<span>{{ row.industry || '-' }}</span>
|
<span>{{ row.industry || '-' }}</span>
|
||||||
<span class="rr-sub">{{ SUPPLIER_LEVEL_MAP[row.supplierLevel as number] || '-' }}</span>
|
<span style="font-size:12px;color:var(--ink-3)">{{ LEVEL_MAP[row.supplierLevel as number] || '-' }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="supplierLabel" label="标签" width="120" header-align="center" align="center" show-overflow-tooltip>
|
<!-- 业务员 -->
|
||||||
<template #default="{ row }">
|
<template #salespersonInfo="{ row }">
|
||||||
{{ row.supplierLabel || '-' }}
|
<div v-if="row.salesperson" style="font-size:12px;color:var(--ink-3)">
|
||||||
|
{{ row.salesperson }}({{ maskMobile(row.salespersonMobile) }})
|
||||||
|
</div>
|
||||||
|
<div v-else style="font-size:12px;color:var(--ink-3);font-style:italic">暂未分配</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="业务员" min-width="160" show-overflow-tooltip>
|
<!-- 状态标签 -->
|
||||||
<template #default="{ row }">
|
<template #status="{ row }">
|
||||||
<div v-if="row.salesperson" class="rr-sub">{{ row.salesperson }}({{ formatMobile(row.salespersonMobile) }})</div>
|
<span v-if="STATUS_MAP[String(row.status)]" :class="['rr-status-tag', STATUS_CLASS[String(row.status)] || '']">
|
||||||
<div v-else class="rr-muted">暂未分配</div>
|
{{ STATUS_MAP[String(row.status)] }}
|
||||||
</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>
|
</span>
|
||||||
|
<span v-else class="rr-muted">--</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="入驻时间" width="110" header-align="center" align="center">
|
<!-- 入驻时间 -->
|
||||||
<template #default="{ row }">
|
<template #createDate="{ row }">
|
||||||
{{ fmtDate(row.createDate) }}
|
<span style="font-family:'SF Mono',Menlo,monospace;font-size:12px">{{ fmtDate(row.createDate) }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="操作" fixed="right" width="200" header-align="center" align="center">
|
<!-- 操作列 -->
|
||||||
<template #default="{ row }">
|
<template #action="{ row }">
|
||||||
<div class="rr-actions">
|
<div style="display:flex;align-items:center;gap:2px">
|
||||||
<el-button type="primary" size="small" text @click="showDetail(row)">详情</el-button>
|
<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-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-dropdown trigger="click" placement="bottom-end" @command="(cmd:string) => handleMore(cmd, row)">
|
||||||
<el-button type="primary" size="small" text>
|
<el-button type="primary" size="small" text><el-icon><MoreFilled /></el-icon></el-button>
|
||||||
<el-icon><MoreFilled /></el-icon>
|
|
||||||
</el-button>
|
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu>
|
<el-dropdown-menu>
|
||||||
<el-dropdown-item v-if="row.status === 1" command="audit">审核</el-dropdown-item>
|
<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="label">标签</el-dropdown-item>
|
||||||
<el-dropdown-item command="rating">评级</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="enabled">{{ row.enabled===1?'启用':'禁用' }}</el-dropdown-item>
|
||||||
<el-dropdown-item command="showFlag">{{ row.showFlag === 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="homeShow">{{ row.homeShow===1?'取消推荐':'推荐显示' }}</el-dropdown-item>
|
||||||
<el-dropdown-item command="assign">分配业务员</el-dropdown-item>
|
<el-dropdown-item command="assign">分配业务员</el-dropdown-item>
|
||||||
<el-dropdown-item command="deleteRow">删除</el-dropdown-item>
|
<el-dropdown-item command="deleteRow">删除</el-dropdown-item>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
@ -407,40 +349,25 @@ onMounted(() => { load() })
|
|||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</DataTable>
|
||||||
</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>
|
||||||
|
|
||||||
<!-- 详情弹窗 -->
|
<!-- 详情弹窗 (EnterpriseDTO 全字段) -->
|
||||||
<el-dialog v-model="detailVisible" title="企业详情" width="700px" :close-on-click-modal="false" 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="small">
|
<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="管理员">{{ detailRow.administrator }}</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="管理员手机">{{ maskMobile(detailRow.administratorMobile) }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="行业">{{ detailRow.industry || '-' }}</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="供应商等级">{{ LEVEL_MAP[detailRow.supplierLevel as number] || '-' }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="标签">{{ detailRow.supplierLabel || '-' }}</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="业务员">{{ detailRow.salesperson || '暂未分配' }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="状态">{{ STATUS_MAP[detailRow.status]?.label || '-' }}</el-descriptions-item>
|
<el-descriptions-item label="状态">{{ STATUS_MAP[String(detailRow.status)] || '-' }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="审核驳回原因" v-if="detailRow.status === 3">{{ detailRow.failReason || '-' }}</el-descriptions-item>
|
<el-descriptions-item v-if="detailRow.status===3" label="驳回原因" :span="2">{{ detailRow.failReason || '-' }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="入驻时间">{{ fmtDate(detailRow.createDate) }}</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="手机号">{{ formatMobile(detailRow.linkMobile) }}</el-descriptions-item>
|
<el-descriptions-item label="联系电话">{{ maskMobile(detailRow.linkMobile) }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="邮箱">{{ detailRow.email || '-' }}</el-descriptions-item>
|
<el-descriptions-item label="邮箱">{{ detailRow.email || '-' }}</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>
|
||||||
@ -449,48 +376,26 @@ onMounted(() => { load() })
|
|||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
</template>
|
</template>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button @click="detailVisible = false">关闭</el-button>
|
<el-button @click="detailVisible=false">关闭</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.rr-enterprise { padding: 16px; }
|
.rr-page { padding: 16px; }
|
||||||
.rr-search-panel {
|
.rr-list-card {
|
||||||
background: var(--surface); border-radius: 12px; padding: 16px 16px 4px; margin-bottom: 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;
|
background: var(--surface); border-radius: 12px; overflow: hidden;
|
||||||
}
|
}
|
||||||
.rr-pager {
|
.rr-batch-bar {
|
||||||
display: flex; justify-content: space-between; align-items: center;
|
display: flex; gap: 8px; flex-wrap: wrap; padding: 12px 16px;
|
||||||
padding: 12px 16px; border-top: 1px solid var(--border);
|
border-bottom: 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 {
|
.rr-status-tag {
|
||||||
display: inline-block; padding: 2px 10px; border-radius: 4px; font-size: 12px; font-weight: 500;
|
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; }
|
.rr-tag-warn { background: #fff3e0; color: #e65100; }
|
||||||
|
.rr-tag-ok { background: #e8f5e9; color: #2e7d32; }
|
||||||
|
.rr-tag-err { background: #fce4ec; color: #c62828; }
|
||||||
|
.rr-muted { color: var(--ink-3); font-size: 12px; }
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user