style(refactor): 重构供应商管理页面布局与交互逻辑

1.  将原有单页表单式页面重构为左右分栏布局,左侧展示供应商列表,右侧展示详情/编辑/供货清单/异议标签页
2.  新增供应商选中默认逻辑,刷新页面保持选中状态
3.  补充供货清单、订单异议的列表展示与数据加载逻辑
4.  优化搜索、分页、新增编辑删除的交互流程与样式
This commit is contained in:
2026-05-30 19:56:34 +08:00
parent be3212cbdb
commit 18a71526dc
2 changed files with 801 additions and 75 deletions

View File

@@ -168,8 +168,8 @@ export default {
}
.supplier-name {
font-size: 14px;
font-weight: 600;
font-size: 8px;
font-weight: 200;
color: #303133;
margin-bottom: 4px;
line-height: 1.4;

View File

@@ -1,103 +1,829 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true">
<el-form-item label="供应商名称" prop="supplierName">
<el-input v-model="queryParams.supplierName" placeholder="请输入供应商名称" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete">删除</el-button>
</el-col>
</el-row>
<el-table v-loading="loading" :data="list" @selection-change="s => { this.multiple = !s.length; this.ids = s.map(r => r.supplierId) }">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="供应商名称" prop="supplierName" />
<el-table-column label="联系人" prop="contact" width="100" />
<el-table-column label="手机" prop="phone" width="130" />
<el-table-column label="邮箱" prop="email" />
<el-table-column label="地址" prop="address" :show-overflow-tooltip="true" />
<el-table-column label="状态" width="80">
<template slot-scope="scope">
<el-tag :type="scope.row.status === '0' ? 'success' : 'danger'">{{ scope.row.status === '0' ? '启用' : '禁用' }}</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="160">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
<div class="supplier-manage">
<!-- ====== 左侧面板供应商列表 ====== -->
<div class="left-panel">
<!-- Header -->
<div class="panel-header">
<span class="panel-title">供应商列表</span>
<div class="search-row">
<el-input
v-model="queryParams.supplierName"
placeholder="搜索供应商名称"
size="small"
prefix-icon="el-icon-search"
clearable
@keyup.enter.native="handleSearch"
/>
<el-button type="primary" size="small" icon="el-icon-search" @click="handleSearch" />
<el-button type="primary" size="small" icon="el-icon-plus" @click="handleAdd" />
</div>
</div>
<el-dialog :title="title" :visible.sync="open" width="580px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="90px">
<!-- Body: 列表 -->
<el-scrollbar class="list-scrollbar">
<div
v-for="item in list"
:key="item.supplierId"
class="supplier-item"
:class="{ active: currentSupplier && currentSupplier.supplierId === item.supplierId }"
@click="selectSupplier(item)"
>
<div class="item-left">
<div class="item-code">{{ formatCode(item.supplierId) }}</div>
<div class="item-name">{{ item.supplierName }}</div>
<div class="item-contact">
<span v-if="item.contact">{{ item.contact }}</span>
<span v-if="item.phone" class="contact-sep">/</span>
<span v-if="item.phone">{{ item.phone }}</span>
</div>
</div>
<div class="item-right">
<el-button
type="danger"
size="mini"
icon="el-icon-delete"
circle
@click.stop="handleDelete(item)"
/>
</div>
</div>
<div v-if="!list.length && !loading" class="empty-list">暂无数据</div>
</el-scrollbar>
<!-- Footer: 分页 -->
<div class="panel-footer">
<el-pagination
small
:total="total"
:page-size="queryParams.pageSize"
:current-page.sync="queryParams.pageNum"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</div>
<!-- ====== 右侧面板供应商详情 ====== -->
<div class="right-panel">
<template v-if="currentSupplier">
<el-tabs v-model="activeTab" class="detail-tabs">
<!-- Tab 1: 供应商详情只读 -->
<el-tab-pane label="供应商详情" name="detail">
<div class="detail-grid">
<div class="detail-row">
<span class="detail-label">供应商编号</span>
<span class="detail-value">{{ formatCode(currentSupplier.supplierId) }}</span>
</div>
<div class="detail-row">
<span class="detail-label">供应商名称</span>
<span class="detail-value">{{ currentSupplier.supplierName || '-' }}</span>
</div>
<div class="detail-row">
<span class="detail-label">联系人</span>
<span class="detail-value">{{ currentSupplier.contact || '-' }}</span>
</div>
<div class="detail-row">
<span class="detail-label">手机</span>
<span class="detail-value">{{ currentSupplier.phone || '-' }}</span>
</div>
<div class="detail-row">
<span class="detail-label">邮箱</span>
<span class="detail-value">{{ currentSupplier.email || '-' }}</span>
</div>
<div class="detail-row">
<span class="detail-label">地址</span>
<span class="detail-value">{{ currentSupplier.address || '-' }}</span>
</div>
<div class="detail-row">
<span class="detail-label">状态</span>
<span class="detail-value">
<el-tag :type="currentSupplier.status === '0' ? 'success' : 'danger'" size="small">
{{ currentSupplier.status === '0' ? '启用' : '禁用' }}
</el-tag>
</span>
</div>
</div>
</el-tab-pane>
<!-- Tab 2: 信息编辑 -->
<el-tab-pane label="信息编辑" name="edit">
<el-form ref="editForm" :model="editForm" :rules="editRules" label-width="100px" size="small" class="edit-form">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="供应商名称" prop="supplierName">
<el-input v-model="editForm.supplierName" placeholder="请输入供应商名称" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="联系人" prop="contact">
<el-input v-model="editForm.contact" placeholder="请输入联系人" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="手机" prop="phone">
<el-input v-model="editForm.phone" placeholder="请输入手机号" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="邮箱" prop="email">
<el-input v-model="editForm.email" placeholder="请输入邮箱" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="地址" prop="address">
<el-input v-model="editForm.address" placeholder="请输入地址" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="状态" prop="status">
<el-radio-group v-model="editForm.status">
<el-radio label="0">启用</el-radio>
<el-radio label="1">禁用</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-form-item>
<el-button type="primary" size="small" @click="handleSaveEdit">保存</el-button>
<el-button size="small" @click="resetEditForm">重置</el-button>
</el-form-item>
</el-form>
</el-tab-pane>
<!-- Tab 3: 供货清单 -->
<el-tab-pane label="供货清单" name="orders">
<div class="tab-content">
<el-table :data="orderList" v-loading="orderLoading" border size="small" style="width:100%">
<el-table-column label="采购单号" prop="poNo" min-width="150" />
<el-table-column label="供应商" prop="supplierName" min-width="140" />
<el-table-column label="采购标题" prop="rfqTitle" min-width="160" :show-overflow-tooltip="true" />
<el-table-column label="总金额" prop="totalAmount" width="120" align="right">
<template slot-scope="scope">
<span class="price-text">{{ scope.row.totalAmount ? '¥' + Number(scope.row.totalAmount).toLocaleString() : '-' }}</span>
</template>
</el-table-column>
<el-table-column label="交货日期" prop="deliveryDate" width="110" align="center" />
<el-table-column label="状态" width="90" align="center">
<template slot-scope="scope">
<el-tag :type="orderStatusType(scope.row.status)" size="small">{{ orderStatusText(scope.row.status) }}</el-tag>
</template>
</el-table-column>
</el-table>
<div v-if="!orderList.length && !orderLoading" class="table-empty">暂无供货记录</div>
</div>
</el-tab-pane>
<!-- Tab 4: 订单异议 -->
<el-tab-pane label="订单异议" name="objections">
<div class="tab-content">
<el-table :data="objectionList" v-loading="objectionLoading" border size="small" style="width:100%">
<el-table-column label="采购单号" prop="poNo" min-width="150" />
<el-table-column label="供应商" prop="supplierName" min-width="140" />
<el-table-column label="异议原因" prop="reason" min-width="200" :show-overflow-tooltip="true" />
<el-table-column label="状态" width="100" align="center">
<template slot-scope="scope">
<el-tag :type="objStatusType(scope.row.status)" size="small">{{ objStatusText(scope.row.status) }}</el-tag>
</template>
</el-table-column>
<el-table-column label="处理结果" prop="resolution" min-width="160" :show-overflow-tooltip="true" />
<el-table-column label="提交时间" prop="createTime" width="160" align="center" />
</el-table>
<div v-if="!objectionList.length && !objectionLoading" class="table-empty">暂无订单异议</div>
</div>
</el-tab-pane>
</el-tabs>
</template>
<!-- 未选中时占位 -->
<div v-else class="right-placeholder">
<i class="el-icon-document"></i>
<p>请从左侧选择一个供应商查看详情</p>
</div>
</div>
<!-- ====== 新增供应商弹窗 ====== -->
<el-dialog title="新增供应商" :visible.sync="addDialogOpen" width="580px" append-to-body @close="cancelAdd">
<el-form ref="addForm" :model="addForm" :rules="editRules" label-width="100px" size="small">
<el-form-item label="供应商名称" prop="supplierName">
<el-input v-model="form.supplierName" placeholder="请输入供应商名称" />
<el-input v-model="addForm.supplierName" placeholder="请输入供应商名称" />
</el-form-item>
<el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="联系人" prop="contact"><el-input v-model="form.contact" /></el-form-item>
<el-form-item label="联系人" prop="contact">
<el-input v-model="addForm.contact" placeholder="请输入联系人" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="手机" prop="phone"><el-input v-model="form.phone" /></el-form-item>
<el-form-item label="手机" prop="phone">
<el-input v-model="addForm.phone" placeholder="请输入手机号" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="邮箱" prop="email">
<el-input v-model="addForm.email" placeholder="请输入邮箱" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="地址" prop="address">
<el-input v-model="addForm.address" placeholder="请输入地址" />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="邮箱" prop="email"><el-input v-model="form.email" /></el-form-item>
<el-form-item label="地址" prop="address"><el-input v-model="form.address" /></el-form-item>
</el-form>
<div slot="footer">
<el-button @click="cancel">取消</el-button>
<el-button type="primary" @click="submitForm">确定</el-button>
<el-button @click="cancelAdd">取消</el-button>
<el-button type="primary" @click="submitAdd">确定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listSupplier, getSupplier, addSupplier, updateSupplier, delSupplier } from "@/api/bid/supplier";
import { listPurchaseorder } from "@/api/bid/purchaseorder";
import { listObjection } from "@/api/bid/objection";
export default {
name: "Supplier",
name: "SupplierManage",
data() {
return {
loading: false, multiple: true, total: 0, list: [], ids: [],
open: false, title: "",
queryParams: { pageNum: 1, pageSize: 10, supplierName: null },
form: {},
rules: { supplierName: [{ required: true, message: "供应商名称不能为空", trigger: "blur" }] }
// ---- 左侧列表 ----
loading: false,
list: [],
total: 0,
queryParams: {
pageNum: 1,
pageSize: 10,
supplierName: null
},
currentSupplier: null,
// ---- 右侧Tab ----
activeTab: "detail",
// ---- 编辑表单 ----
editForm: {},
editRules: {
supplierName: [
{ required: true, message: "供应商名称不能为空", trigger: "blur" }
]
},
// ---- 新增弹窗 ----
addDialogOpen: false,
addForm: {},
// ---- 供货清单 ----
orderLoading: false,
orderList: [],
// ---- 订单异议 ----
objectionLoading: false,
objectionList: []
};
},
created() { this.getList(); },
created() {
this.getList();
},
methods: {
/* ========== 左侧列表 ========== */
getList() {
this.loading = true;
listSupplier(this.queryParams).then(res => { this.list = res.rows; this.total = res.total; this.loading = false; });
},
handleQuery() { this.queryParams.pageNum = 1; this.getList(); },
resetQuery() { this.resetForm("queryForm"); this.handleQuery(); },
handleAdd() { this.form = { status: "0" }; this.open = true; this.title = "新增供应商"; },
handleUpdate(row) {
getSupplier(row.supplierId).then(res => { this.form = res.data; this.open = true; this.title = "修改供应商"; });
},
handleDelete(row) {
const ids = row.supplierId || this.ids.join(",");
this.$modal.confirm("确认删除?").then(() => delSupplier(ids)).then(() => { this.getList(); this.$modal.msgSuccess("删除成功"); });
},
cancel() { this.open = false; },
submitForm() {
this.$refs["form"].validate(valid => {
if (!valid) return;
const action = this.form.supplierId ? updateSupplier : addSupplier;
action(this.form).then(() => { this.$modal.msgSuccess("操作成功"); this.open = false; this.getList(); });
listSupplier(this.queryParams).then(res => {
this.list = res.rows || [];
this.total = res.total || 0;
this.loading = false;
// 默认选中第一条
if (this.list.length && !this.currentSupplier) {
this.selectSupplier(this.list[0]);
} else if (this.list.length && this.currentSupplier) {
// 刷新后保持选中(如果还在列表中)
const still = this.list.find(
s => s.supplierId === this.currentSupplier.supplierId
);
if (still) {
this.currentSupplier = still;
} else {
this.selectSupplier(this.list[0]);
}
} else {
this.currentSupplier = null;
this.orderList = [];
this.objectionList = [];
}
}).catch(() => {
this.loading = false;
});
},
handleSearch() {
this.queryParams.pageNum = 1;
this.getList();
},
handleSizeChange(size) {
this.queryParams.pageSize = size;
this.queryParams.pageNum = 1;
this.getList();
},
handleCurrentChange(page) {
this.queryParams.pageNum = page;
this.getList();
},
selectSupplier(item) {
this.currentSupplier = item;
this.activeTab = "detail";
// 初始化编辑表单
this.editForm = {
supplierId: item.supplierId,
supplierName: item.supplierName,
contact: item.contact,
phone: item.phone,
email: item.email,
address: item.address,
status: item.status || "0"
};
// 清空子列表
this.orderList = [];
this.objectionList = [];
},
formatCode(id) {
if (!id) return 'KLP--';
return 'KLP' + String(id).padStart(2, '0');
},
/* ========== 新增 ========== */
handleAdd() {
this.addForm = { status: "0" };
this.addDialogOpen = true;
},
cancelAdd() {
this.addDialogOpen = false;
this.addForm = {};
this.$refs.addForm && this.$refs.addForm.resetFields();
},
submitAdd() {
this.$refs.addForm.validate(valid => {
if (!valid) return;
addSupplier(this.addForm).then(() => {
this.$message.success("新增成功");
this.addDialogOpen = false;
this.addForm = {};
this.getList();
}).catch(err => {
this.$message.error("新增失败:" + (err.msg || "未知错误"));
});
});
},
/* ========== 删除 ========== */
handleDelete(row) {
this.$confirm("确认删除供应商【" + row.supplierName + "】?", "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
delSupplier(row.supplierId).then(() => {
this.$message.success("删除成功");
if (this.currentSupplier && this.currentSupplier.supplierId === row.supplierId) {
this.currentSupplier = null;
}
this.getList();
});
}).catch(() => {});
},
/* ========== 编辑保存 ========== */
handleSaveEdit() {
this.$refs.editForm.validate(valid => {
if (!valid) return;
updateSupplier(this.editForm).then(() => {
this.$message.success("保存成功");
// 刷新当前供应商数据
getSupplier(this.editForm.supplierId).then(res => {
this.currentSupplier = res.data;
this.editForm = {
supplierId: res.data.supplierId,
supplierName: res.data.supplierName,
contact: res.data.contact,
phone: res.data.phone,
email: res.data.email,
address: res.data.address,
status: res.data.status || "0"
};
});
}).catch(err => {
this.$message.error("保存失败:" + (err.msg || "未知错误"));
});
});
},
resetEditForm() {
if (this.currentSupplier) {
this.editForm = {
supplierId: this.currentSupplier.supplierId,
supplierName: this.currentSupplier.supplierName,
contact: this.currentSupplier.contact,
phone: this.currentSupplier.phone,
email: this.currentSupplier.email,
address: this.currentSupplier.address,
status: this.currentSupplier.status || "0"
};
}
this.$refs.editForm && this.$refs.editForm.resetFields();
},
/* ========== Tab: 供货清单 ========== */
loadOrders() {
if (!this.currentSupplier) return;
this.orderLoading = true;
listPurchaseorder({ supplierId: this.currentSupplier.supplierId, pageSize: 200 })
.then(res => {
this.orderList = res.rows || [];
this.orderLoading = false;
})
.catch(() => {
this.orderLoading = false;
});
},
orderStatusType(status) {
const map = { confirmed: "success", pending: "warning", cancelled: "danger", draft: "info" };
return map[status] || "info";
},
orderStatusText(status) {
const map = { confirmed: "已确认", pending: "待处理", cancelled: "已取消", draft: "草稿" };
return map[status] || status || "-";
},
/* ========== Tab: 订单异议 ========== */
loadObjections() {
if (!this.currentSupplier) return;
this.objectionLoading = true;
listObjection({ supplierId: this.currentSupplier.supplierId, pageSize: 200 })
.then(res => {
this.objectionList = res.rows || [];
this.objectionLoading = false;
})
.catch(() => {
this.objectionLoading = false;
});
},
objStatusType(status) {
const map = { resolved: "success", processing: "primary", pending: "warning", rejected: "danger" };
return map[status] || "info";
},
objStatusText(status) {
const map = { resolved: "已解决", processing: "处理中", pending: "待处理", rejected: "已拒绝" };
return map[status] || status || "-";
}
},
watch: {
activeTab(val) {
if (val === "orders" && !this.orderList.length) {
this.loadOrders();
}
if (val === "objections" && !this.objectionList.length) {
this.loadObjections();
}
},
currentSupplier() {
// 切换供应商时清除子列表
this.orderList = [];
this.objectionList = [];
// 如果当前在采购单或异议Tab自动加载
if (this.activeTab === "orders") {
this.$nextTick(() => this.loadOrders());
}
if (this.activeTab === "objections") {
this.$nextTick(() => this.loadObjections());
}
}
}
};
</script>
<style scoped>
/* ====== 整体布局 ====== */
.supplier-manage {
display: flex;
gap: 12px;
padding: 12px;
background: #f5f7fa;
min-height: calc(100vh - 84px);
align-items: flex-start;
}
/* ====== 左侧面板 ====== */
.left-panel {
width: 340px;
flex-shrink: 0;
background: #fff;
border-radius: 4px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
display: flex;
flex-direction: column;
height: calc(100vh - 108px);
}
.panel-header {
padding: 16px 16px 12px;
border-bottom: 1px solid #ebeef5;
}
.panel-title {
font-size: 14px;
color: #909399;
display: block;
margin-bottom: 10px;
}
.search-row {
display: flex;
gap: 6px;
}
.search-row .el-input {
flex: 1;
}
/* 列表滚动区 */
.list-scrollbar {
flex: 1;
overflow-y: auto;
}
/* 供应商列表项 */
.supplier-item {
display: flex;
align-items: center;
padding: 12px 16px;
border-bottom: 1px solid #ebeef5;
cursor: pointer;
transition: background-color 0.2s;
position: relative;
}
.supplier-item:hover {
background-color: #f5f7fa;
}
.supplier-item.active {
background-color: #ecf5ff;
border-left: 3px solid #409eff;
padding-left: 13px;
}
.item-left {
flex: 1;
min-width: 0;
}
.item-code {
font-size: 12px;
color: #909399;
margin-bottom: 2px;
}
.item-name {
font-size: 14px;
font-weight: bold;
color: #303133;
margin-bottom: 2px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.item-contact {
font-size: 12px;
color: #909399;
}
.contact-sep {
margin: 0 4px;
color: #dcdfe6;
}
.item-right {
flex-shrink: 0;
margin-left: 8px;
}
.empty-list {
text-align: center;
color: #c0c4cc;
padding: 40px 0;
font-size: 13px;
}
/* 底部分页(在 340px 面板内塞下 total+sizes+prev+pager+next+jumper */
.panel-footer {
padding: 4px 6px;
border-top: 1px solid #ebeef5;
flex-shrink: 0;
overflow: hidden;
}
.panel-footer .el-pagination {
display: flex;
justify-content: center;
align-items: center;
flex-wrap: nowrap;
font-size: 12px;
}
/* 总条数 */
.panel-footer .el-pagination >>> .el-pagination__total {
font-size: 11px;
color: #909399;
margin-right: 2px;
white-space: nowrap;
}
/* 每页条数下拉 */
.panel-footer .el-pagination >>> .el-pagination__sizes {
margin-right: 2px;
}
.panel-footer .el-pagination >>> .el-pagination__sizes .el-input--mini .el-input__inner {
font-size: 11px;
height: 22px;
line-height: 22px;
width: 50px;
padding: 0 18px 0 4px;
}
.panel-footer .el-pagination >>> .el-pagination__sizes .el-input .el-select__caret {
line-height: 22px;
font-size: 11px;
}
/* 翻页按钮 */
.panel-footer .el-pagination >>> .btn-prev,
.panel-footer .el-pagination >>> .btn-next {
min-width: 20px;
padding: 0;
}
.panel-footer .el-pagination >>> .btn-prev i,
.panel-footer .el-pagination >>> .btn-next i {
font-size: 11px;
}
/* 页码按钮 */
.panel-footer .el-pagination >>> .el-pager li {
min-width: 20px;
font-size: 11px;
padding: 0 1px;
}
/* 跳转区域 */
.panel-footer .el-pagination >>> .el-pagination__jump {
font-size: 11px;
color: #909399;
margin-left: 2px;
white-space: nowrap;
}
.panel-footer .el-pagination >>> .el-pagination__jump .el-input--mini {
width: auto;
}
.panel-footer .el-pagination >>> .el-pagination__jump .el-input__inner {
font-size: 11px;
height: 22px;
line-height: 22px;
width: 36px;
padding: 0 2px;
}
/* ====== 右侧面板 ====== */
.right-panel {
flex: 1;
background: #fff;
border-radius: 4px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
min-height: calc(100vh - 108px);
}
/* Tab 导航自定义 */
.detail-tabs >>> .el-tabs__header {
margin: 0;
padding: 0 16px;
background: #fafafa;
border-bottom: 1px solid #e4e7ed;
}
.detail-tabs >>> .el-tabs__item {
height: 40px;
line-height: 40px;
font-size: 13px;
color: #606266;
padding: 0 18px;
transition: all 0.2s;
}
.detail-tabs >>> .el-tabs__item.is-active {
color: #409eff;
background: #ecf5ff;
border-radius: 4px 4px 0 0;
font-weight: 500;
}
.detail-tabs >>> .el-tabs__item:hover {
color: #409eff;
}
.detail-tabs >>> .el-tabs__active-bar {
display: none;
}
.detail-tabs >>> .el-tabs__content {
padding: 20px 24px;
}
/* 详情网格(两列) */
.detail-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0 40px;
}
.detail-row {
display: flex;
align-items: center;
height: 40px;
line-height: 40px;
}
.detail-label {
width: 100px;
flex-shrink: 0;
color: #909399;
font-size: 13px;
}
.detail-value {
flex: 1;
color: #303133;
font-size: 13px;
min-width: 0;
word-break: break-word;
}
/* 编辑表单 */
.edit-form {
max-width: 640px;
}
/* 表格内容区 */
.tab-content {
min-height: 200px;
}
.table-empty {
text-align: center;
color: #c0c4cc;
padding: 40px 0;
font-size: 13px;
}
/* 价格 */
.price-text {
color: #f56c6c;
font-weight: 500;
}
/* 右侧占位 */
.right-placeholder {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: calc(100vh - 160px);
color: #c0c4cc;
}
.right-placeholder i {
font-size: 48px;
margin-bottom: 12px;
}
.right-placeholder p {
font-size: 14px;
margin: 0;
}
</style>