提交 8a4a00d6 authored 作者: lidongxu's avatar lidongxu

feat(display_schedule): 修改:AP 执行上报_陈列和档期计划_表格列宽度更合理

上级 89998429
......@@ -25,7 +25,7 @@ export * from './monitor/job'
export * from './monitor/jobLog'
export * from './monitor/online'
export * from './monitor/server'
export * from './promotion/display'
export * from './promotion/display_schedule'
export * from './promotion/plan'
export * from './promotion/task'
export * from './scm/logistics_receipt'
......
......@@ -4,7 +4,7 @@ export function getDisplayList(params) {
return request({
url: '/operation/sales/ap_display/query/page',
params
});
})
}
// 填报-陈列计划
......@@ -17,3 +17,22 @@ export function submitDisplayPlan(data) {
}
});
}
// 获取档期计划列表
export function getDisplayScheduleList(params) {
return request({
url: '/operation/sales/ap_promotion/query/page',
params
})
}
// 填报-档期计划
export function submitDisplaySchedulePlan(data) {
return request({
url: `/operation/sales/ap_promotion/core/${data.id}`,
method: 'PUT',
data: {
promotion: data
}
});
}
......@@ -126,7 +126,7 @@ aside {
// 全局样式
// 容器
.app-container {
padding: 30px;
padding: 10px;
height: 100%;
// 内容区域
......@@ -134,7 +134,7 @@ aside {
width: 100%;
height: 100%;
background-color: var(--el-bg-color-overlay);
padding: 20px;
padding: 10px;
display: flex;
flex-direction: column;
}
......
......@@ -19,7 +19,7 @@
icon="Refresh"
@click="refresh()" />
</el-tooltip>
<el-tooltip class="item"
<el-tooltip class="item "
effect="dark"
content="显隐列"
placement="top"
......@@ -31,7 +31,8 @@
<el-dropdown trigger="click"
:hide-on-click="false"
style="padding-left: 12px"
v-if="showColumnsType == 'checkbox'">
v-if="showColumnsType == 'checkbox'"
class="columns-dropdown">
<el-button circle
icon="Menu" />
<template #dropdown>
......@@ -50,7 +51,8 @@
<el-dropdown trigger="click"
:hide-on-click="false"
style="padding-left: 12px"
v-if="showColumnsType == 'tree'">
v-if="showColumnsType == 'tree'"
>
<el-button circle
icon="Menu" />
<template #dropdown>
......
......@@ -7,699 +7,67 @@
@tab-click="handleClickTabs">
<el-tab-pane label="陈列计划"
name="陈列计划">
<el-row>
<el-form-item label="操作类型">
<el-radio-group v-model="operation"
@change="checkTableColumns">
<el-radio-button label="全部列"
value="全部列" />
<el-radio-button label="填报列"
value="填报列" />
</el-radio-group>
</el-form-item>
<right-toolbar v-model:showSearch="showSearch"
@queryTable="getTableList()"
:columns="chooseColumns"
:showColumnsType="operation === '全部列' ? 'tree' : 'checkbox'"
:defaultCheckedKeys="visibleProps">
</right-toolbar>
</el-row>
<!-- 筛选列组的按钮 -->
<el-table :data="tableData"
height="100%"
border
:scroll-x="'max-content'"
class="auto-fit-header-table"
fit
v-loading="isLoading">
<el-table-column v-for="col in tableColumns"
:label="col.label"
align="center"
:min-width="getColumnMinWidth(col)"
show-overflow-tooltip>
<template #header="{ column }">
<!-- 只为特定列添加问号图标 -->
<span class="formula-column">
{{ column.label }}
<el-tooltip v-if="col.type === 'formula'"
:content="col.formulaStr"
placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
</span>
</template>
<template #default="{ row }">
<div v-if="col.type === 'select'">
<!-- 实际主货架-数量(要根据实际主货架-形式不为空时才可以选择否则为 0) -->
<div v-if="col.prop === 'actualMainShelfQty'">
<el-select :disabled="!row.actualMainShelfType"
v-model="row[col.prop]"
placeholder="请选择"
clearable
@change="submitChange(row, col)">
<el-option v-for="item in col.options"
:key="item.value"
:label="item.label"
:value="item.value" />
</el-select>
</div>
<el-select v-else
v-model="row[col.prop]"
placeholder="请选择"
clearable
@change="submitChange(row, col)">
<el-option v-for="item in col.options"
:key="item.value"
:label="item.label"
:value="item.value" />
</el-select>
</div>
<!-- 公式计算 -->
<div v-else-if="col.type === 'formula'">
{{ col.func(row) }}
</div>
<!-- 输入框 -->
<div v-else-if="col.type === 'input'">
<el-input v-model="row[col.prop]"
placeholder="请输入"
@input="submitChange(row, col)" />
</div>
<!-- 为其他类型或未定义类型提供默认显示 -->
<div v-else>
{{ row[col.prop] || '-' }}
</div>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<pagination :total="total"
v-model:page="params.pageNum"
v-model:limit="params.pageSize"
@pagination="getTableList" />
<Display />
</el-tab-pane>
<el-tab-pane label="档期计划"
name="档期计划">Config</el-tab-pane>
name="档期计划">
<Schedule />
</el-tab-pane>
</el-tabs>
</div>
</div>
</template>
<script setup>
import { getDisplayList, submitDisplayPlan } from '@/api'
import Display from './tabs/display.vue'
import Schedule from './tabs/schedule.vue'
const activeName = ref('陈列计划');
const handleClickTabs = (tab) => {
activeName.value = tab.name;
}
/*************** 操作类型 ***************/
const operation = ref('全部列');
// 全部列
const baseColumns = ref([
{
label: "基础信息",
children: [{ label: "销售大区", prop: "regionName", visible: true, type: 'string' },
{ label: "销售战区", prop: "districtName", visible: true, type: 'string' },
{ label: "经销商-省份", prop: "dealerProvince", visible: true, type: 'string' },
{ label: "经销商-城市", prop: "dealerCity", visible: true, type: 'string' },
{ label: "经销商-代码", prop: "dealerCode", visible: true, type: 'string' },
{ label: "经销商名称", prop: "dealerName", visible: true, type: 'string' },
{ label: "经销商-类型", prop: "dealerType", visible: true, type: 'string' },
{ label: "开户日期", prop: "openingDate", visible: true, type: 'string' },
{ label: "闭户日期", prop: "closingDate", visible: true, type: 'string' },
{ label: "大区总监", prop: "regionManager", visible: true, type: 'string' },
{ label: "战区经理", prop: "districtManager", visible: true, type: 'string' },
{ label: "城市经理", prop: "cityManager", visible: true, type: 'string' },
{ label: "门店编码", prop: "storeCode", visible: true, type: 'string' },
{ label: "门店名称", prop: "storeName", visible: true, type: 'string' },
{ label: "门店-省份", prop: "storeProvince", visible: true, type: 'string' },
{ label: "门店-城市", prop: "storeCity", visible: true, type: 'string' },
{ label: "系统名称", prop: "lineName", visible: true, type: 'string' },
{ label: "系统类型", prop: "lineType", visible: true, type: 'string' },
{ label: "渠道大类", prop: "channelDl", visible: true, type: 'string' },
{ label: "渠道小类", prop: "channelXl", visible: true, type: 'string' },
{ label: "门店类型", prop: "storeType", visible: true, type: 'string' },
{ label: "系统业态", prop: "systemFormat", visible: true, type: 'string' },
{ label: "门店面积", prop: "storeArea", visible: true, type: 'string' },
{ label: "门店分级(销量坎级)", prop: "storeLevel", visible: true, type: 'string' },
{ label: "门店地址", prop: "storeAddress", visible: true, type: 'string' },
{ label: "品项数", prop: "productCount", visible: true, type: 'string' }],
prop: 'baseColumns',
visible: true
},
{
label: "大业态测试",
children: [
{ label: "大业态测试-动销模型", prop: "lfSalesModel", visible: true, type: 'string' },
{ label: "大业态测试-月均POS", prop: "lfMonthlyPos", visible: true, type: 'string' },
],
prop: 'lfColumns',
visible: true
},
{
label: "费用计划",
prop: 'fpColumns',
children: [
{ label: "计划主货架-形式", prop: "plannedMainShelfType", visible: true, type: 'string' },
{ label: "计划主货架-数量", prop: "plannedMainShelfQty", visible: true, type: 'string' },
{ label: "计划主货架-单个费用", prop: "plannedMainShelfUnitCost", visible: true, type: 'string' },
{ label: "计划主货架-总费用", prop: "plannedMainShelfTotalCost", visible: true, type: 'string' },
{
label: "实际主货架-形式",
prop: "actualMainShelfType",
visible: true,
type: 'select',
options: [
{ label: '4纵', value: '4纵' },
{ label: '5纵', value: '5纵' },
{ label: '6纵', value: '6纵' },
{ label: '7纵', value: '7纵' },
{ label: '8纵及以上', value: '8纵及以上' }
]
},
{
label: "实际主货架-数量",
prop: "actualMainShelfQty",
visible: true,
type: 'select',
options: [
{ label: '1', value: 1 },
{ label: '2', value: 2 }
]
},
{
label: "实际主货架-是否执行",
prop: "actualMainShelfExecuted",
visible: true,
type: 'formula', // 公式
func: (row) => {
row.actualMainShelfExecuted = ((parseInt(row.actualMainShelfType) >= parseInt(row.plannedMainShelfType)) && (parseInt(row.actualMainShelfQty) >= parseInt(row.plannedMainShelfQty))) ? '是' : '否';
return row.actualMainShelfExecuted;
},
formulaStr: '公式:(实际主货架形式 >= 计划主货架形式)并且(实际主货架数量 >= 计划主货架数量)',
},
{ label: "计划端架-数量", prop: "plannedEndCapQty", visible: true },
{ label: "计划端架-总费用", prop: "plannedEndCapTotalCost", visible: true },
{ label: "计划端架-单个费用", prop: "plannedEndCapUnitCost", visible: true },
{
label: "实际端架-数量",
prop: "actualEndCapQty",
visible: true,
type: 'select',
options: [
{ label: '0', value: 0 },
{ label: '0.5', value: 0.5 },
{ label: '1', value: 1 },
{ label: '2', value: 2 }
]
},
{
label: "实际端架-是否执行",
prop: "actualEndCapExecuted",
visible: true,
type: 'formula', // 公式
func: (row) => {
row.actualEndCapExecuted = ((parseFloat(row.actualEndCapQty) >= parseFloat(row.plannedEndCapQty))) ? '是' : '否';
return row.actualEndCapExecuted;
},
formulaStr: '公式:(实际端架数量 >= 计划端架数量)',
},
{
label: "计划地堆-平米数(㎡)",
prop: "plannedFloorStackArea",
visible: true
},
{ label: "计划地堆-数量", prop: "plannedFloorStackQty", visible: true },
{ label: "计划主题地堆-是否", prop: "plannedThemedFloorStack", visible: true },
{ label: "计划地堆-总费用", prop: "plannedFloorStackTotalCost", visible: true },
{ label: "计划折算1㎡-单个费用", prop: "plannedFloorStackUnitCostPerSqm", visible: true },
{
label: "实际地堆-平米数(㎡)",
prop: "actualFloorStackArea",
visible: true,
type: 'select',
options: [
{ label: '0', value: 0 },
{ label: '0.5', value: 0.5 },
{ label: '0.8', value: 0.8 },
{ label: '1', value: 1 },
{ label: '2', value: 2 },
{ label: '3', value: 3 },
{ label: '4', value: 4 },
]
},
{
label: "实际地堆-数量",
prop: "actualFloorStackQty",
visible: true,
type: 'select',
options: [
{ label: '0', value: 0 },
{ label: '1', value: 1 },
{ label: '2', value: 2 },
{ label: '3', value: 3 }
]
},
{
label: "实际主题地堆-是否",
prop: "actualThemedFloorStack",
visible: true,
type: 'select',
options: [
{ label: '是', value: '是' },
{ label: '否', value: '否' },
]
},
{
label: "实际地堆是否执行",
prop: "actualFloorStackExecuted",
visible: true,
type: 'formula', // 公式
func: (row) => {
row.actualFloorStackExecuted = ((parseFloat(row.actualFloorStackArea) >= parseFloat(row.plannedFloorStackArea)) && (parseInt(row.actualFloorStackQty) >= parseInt(row.plannedFloorStackQty))) ? '是' : '否';
return row.actualFloorStackExecuted;
},
formulaStr: '公式:(实际地堆平米数 >= 计划地堆平米数)并且(实际地堆数量 >= 计划地堆数量)',
},
{ label: "计划多点陈列-数量+形式", prop: "plannedMultiDisplay", visible: true },
{ label: "计划多点陈列-总费用", prop: "plannedMultiDisplayTotalCost", visible: true },
{
label: "实际多点陈列-数量+形式",
prop: "actualMultiDisplay",
visible: true,
type: 'input',
func: (row) => {
// 没有输入内容时,则是否执行设置为否
row.actualMultiDisplayExecuted = !row.actualMultiDisplay ? '否' : '是'
}
},
{
label: "实际多点陈列-是否执行",
prop: "actualMultiDisplayExecuted",
visible: true,
type: 'select',
options: [
{ label: '是', value: '是' },
{ label: '否', value: '否' },
]
},
{ label: "合计费用-费用", prop: "totalCost", visible: true },
{ label: "合计费用-费率", prop: "totalCostRate", visible: true },
{
label: "常规陈列是否执行",
prop: "regularDisplayExecuted",
visible: true,
type: 'formula', // 公式
func: (row) => {
// 实际主货架-是否执行 && 实际端架-是否执行 && 实际地堆-是否执行 && 实际多点陈列-是否执行
row.regularDisplayExecuted = (row.actualMainShelfExecuted === '是' && row.actualEndCapExecuted === '是' && row.actualFloorStackExecuted === '是' && row.actualMultiDisplayExecuted === '是') ? '是' : '否';
return row.regularDisplayExecuted;
}
},
{ label: "综合标签-拜访辅助列", prop: "visitAssistTag", visible: true },
{ label: "付费陈列- 是否", prop: "paidDisplay", visible: true },
{ label: "当月拜访目标", prop: "monthlyVisitTarget", visible: true },
{ label: "当月是否拜访", prop: "monthlyVisited", visible: true }
],
visible: true
}
// ...baseColumns.value,
// ...lfColumns.value,
// ...fpColumns.value
]);
// 填报列
const fillColumns = ref([
{ label: "系统名称", prop: "lineName", visible: true, type: 'string' },
{ label: "门店编码", prop: "storeCode", visible: true },
{ label: "门店名称", prop: "storeName", visible: true },
{ label: "计划主货架-形式", prop: "plannedMainShelfType", visible: true, type: 'string' },
{ label: "计划主货架-数量", prop: "plannedMainShelfQty", visible: true, type: 'string' },
{
label: "实际主货架-形式",
prop: "actualMainShelfType",
visible: true,
type: 'select',
options: [
{ label: '4纵', value: '4纵' },
{ label: '5纵', value: '5纵' },
{ label: '6纵', value: '6纵' },
{ label: '7纵', value: '7纵' },
{ label: '8纵及以上', value: '8纵及以上' }
]
},
{
label: "实际主货架-数量",
prop: "actualMainShelfQty",
visible: true,
type: 'select',
options: [
{ label: '1', value: 1 },
{ label: '2', value: 2 }
]
},
{
label: "实际主货架-是否执行",
prop: "actualMainShelfExecuted",
visible: true,
type: 'formula', // 公式
func: (row) => {
row.actualMainShelfExecuted = ((parseInt(row.actualMainShelfType) >= parseInt(row.plannedMainShelfType)) && (parseInt(row.actualMainShelfQty) >= parseInt(row.plannedMainShelfQty))) ? '是' : '否';
return row.actualMainShelfExecuted;
},
formulaStr: '公式:(实际主货架形式 >= 计划主货架形式)并且(实际主货架数量 >= 计划主货架数量)',
},
{ label: "计划端架-数量", prop: "plannedEndCapQty", visible: true },
{
label: "实际端架-数量",
prop: "actualEndCapQty",
visible: true,
type: 'select',
options: [
{ label: '0', value: 0 },
{ label: '0.5', value: 0.5 },
{ label: '1', value: 1 },
{ label: '2', value: 2 }
]
},
{
label: "实际端架-是否执行",
prop: "actualEndCapExecuted",
visible: true,
type: 'formula', // 公式
func: (row) => {
row.actualEndCapExecuted = ((parseFloat(row.actualEndCapQty) >= parseFloat(row.plannedEndCapQty))) ? '是' : '否';
return row.actualEndCapExecuted;
},
formulaStr: '公式:(实际端架数量 >= 计划端架数量)',
},
{
label: "计划地堆-平米数(㎡)",
prop: "plannedFloorStackArea",
visible: true
},
{ label: "计划地堆-数量", prop: "plannedFloorStackQty", visible: true },
{ label: "计划主题地堆-是否", prop: "plannedThemedFloorStack", visible: true },
{
label: "实际地堆-平米数(㎡)",
prop: "actualFloorStackArea",
visible: true,
type: 'select',
options: [
{ label: '0', value: 0 },
{ label: '0.5', value: 0.5 },
{ label: '0.8', value: 0.8 },
{ label: '1', value: 1 },
{ label: '2', value: 2 },
{ label: '3', value: 3 },
{ label: '4', value: 4 },
]
},
{
label: "实际地堆-数量",
prop: "actualFloorStackQty",
visible: true,
type: 'select',
options: [
{ label: '0', value: 0 },
{ label: '1', value: 1 },
{ label: '2', value: 2 },
{ label: '3', value: 3 }
]
},
{
label: "实际主题地堆-是否",
prop: "actualThemedFloorStack",
visible: true,
type: 'select',
options: [
{ label: '是', value: '是' },
{ label: '否', value: '否' },
]
},
{
label: "实际地堆是否执行",
prop: "actualFloorStackExecuted",
visible: true,
type: 'formula', // 公式
func: (row) => {
row.actualFloorStackExecuted = ((parseFloat(row.actualFloorStackArea) >= parseFloat(row.plannedFloorStackArea)) && (parseInt(row.actualFloorStackQty) >= parseInt(row.plannedFloorStackQty))) ? '是' : '否';
return row.actualFloorStackExecuted;
},
formulaStr: '公式:(实际地堆平米数 >= 计划地堆平米数)并且(实际地堆数量 >= 计划地堆数量)',
},
{ label: "计划多点陈列-数量+形式", prop: "plannedMultiDisplay", visible: true },
{ label: "计划多点陈列-总费用", prop: "plannedMultiDisplayTotalCost", visible: true },
{
label: "实际多点陈列-数量+形式",
prop: "actualMultiDisplay",
visible: true,
type: 'input',
func: (row) => {
// 没有输入内容时,则是否执行设置为否
row.actualMultiDisplayExecuted = !row.actualMultiDisplay ? '否' : '是'
}
},
{
label: "实际多点陈列-是否执行",
prop: "actualMultiDisplayExecuted",
visible: true,
type: 'select',
options: [
{ label: '是', value: '是' },
{ label: '否', value: '否' },
]
},
{ label: "合计费用-费用", prop: "totalCost", visible: true },
{ label: "合计费用-费率", prop: "totalCostRate", visible: true },
{
label: "常规陈列是否执行",
prop: "regularDisplayExecuted",
visible: true,
type: 'formula', // 公式
func: (row) => {
// 实际主货架-是否执行 && 实际端架-是否执行 && 实际地堆-是否执行 && 实际多点陈列-是否执行
row.regularDisplayExecuted = (row.actualMainShelfExecuted === '是' && row.actualEndCapExecuted === '是' && row.actualFloorStackExecuted === '是' && row.actualMultiDisplayExecuted === '是') ? '是' : '否';
return row.regularDisplayExecuted;
},
formulaStr: '公式:(实际主货架是否执行 = 是)并且(实际端架是否执行 = 是)并且(实际地堆是否执行 = 是)并且(实际多点陈列是否执行 = 是)',
}
])
// 表格列数据
const tableColumns = ref([])
// 右上角工具选择列
const chooseColumns = ref([])
// 计算列具体数据
const checkTableColumns = () => {
if (operation.value === '全部列') {
chooseColumns.value = baseColumns.value
tableColumns.value = baseColumns.value.flatMap(item => {
if (item.children) {
// 在扁平化时就过滤掉 visible 为 false 的列
return item.children.filter(child => child.visible);
}
// 如果是没有 children 的单元素,也检查其 visible 属性
return item.visible ? item : [];
}).filter(Boolean); // 过滤掉空数组项
} else if (operation.value === '填报列') {
chooseColumns.value = fillColumns.value
tableColumns.value = fillColumns.value.filter(item => item.visible);
}
}
checkTableColumns()
// 选择列默认选中哪些
const visibleProps = computed(() => {
// 分情况返回
return tableColumns.value.flatMap(item => {
if (item.children) {
return item.children.map(child => child.prop);
}
return item.prop;
});
});
// 监听chooseColumns变化,当列的visible属性改变时重新计算tableColumns
watch(
() => chooseColumns.value,
() => {
// 不需要重新赋值,只需要重新计算tableColumns
checkTableColumns();
},
{ deep: true }
);
// 提交变更
const submitChange = async (row, col) => {
// 有个类型输入框的需要调用 func
if (col.type === 'input') {
col.func(row)
}
await submitDisplayPlan({
id: row.sadId,
[col.prop]: row[col.prop]
})
// 这些提交变化的,同时会影响公式计算的,需要把公式计算的字段列结果,一起发给后台
// 主货架
if (['actualMainShelfType', 'actualMainShelfQty'].includes(col.prop)) {
await submitDisplayPlan({
id: row.sadId,
actualMainShelfExecuted: row.actualMainShelfExecuted,
})
}
// 端架
if (['actualEndCapQty'].includes(col.prop)) {
await submitDisplayPlan({
id: row.sadId,
actualEndCapExecuted: row.actualEndCapExecuted,
})
}
// 地堆
if (['actualFloorStackArea', 'actualFloorStackQty'].includes(col.prop)) {
await submitDisplayPlan({
id: row.sadId,
actualFloorStackExecuted: row.actualFloorStackExecuted,
})
}
// 常规陈列是否执行
await submitDisplayPlan({
id: row.sadId,
regularDisplayExecuted: row.regularDisplayExecuted,
})
}
// 表格数据
const tableData = ref([])
const isLoading = ref(true)
const params = reactive({
pageNum: 1,
pageSize: 10,
})
const total = ref(0)
// 筛选工具
const showSearch = ref(true);
const getTableList = async () => {
isLoading.value = true
const res = await getDisplayList({
...params
})
tableData.value = res.data.rows
total.value = res.data.total
isLoading.value = false
}
getTableList()
// 列宽度
const getColumnMinWidth = (column) => {
// 根据列名或属性判断合适的最小宽度
const widthMap = {
// 短文本列
'dealerProvince': 100,
'dealerCity': 100,
'storeProvince': 100,
'storeCity': 100,
'openingDate': 120,
'closingDate': 120,
'monthlyVisitTarget': 80,
// 中等长度文本列
'regionName': 120,
'districtName': 120,
'dealerType': 120,
'lineName': 140,
'lineType': 120,
'channelDl': 120,
'channelXl': 120,
'storeType': 120,
'systemFormat': 120,
'monthlyVisitTarget': 120,
// 长文本列
'dealerName': 200,
'storeName': 220,
'storeAddress': 300,
'visitAssistTag': 180,
'storeLevel': 170,
'plannedFloorStackArea': 170,
'plannedFloorStackUnitCostPerSqm': 170,
'actualFloorStackArea': 170,
'actualMultiDisplay': 190,
'plannedMultiDisplay': 190,
'actualMultiDisplayExecuted': 170,
'actualMainShelfExecuted': 190,
};
return widthMap[column.prop] || 150; // 默认宽度
};
</script>
<style scoped
lang="scss">
.container {
.app-container {
padding: 10px;
.el-tabs {
height: 100%;
display: flex;
flex-direction: column-reverse;
.container {
padding: 10px;
.el-tabs__content {
display: flex;
flex-direction: column;
.el-tabs {
height: 100%;
display: flex;
flex-direction: column-reverse;
.el-tab-pane {
height: 100%;
.el-tabs__content {
display: flex;
flex-direction: column;
}
.formula-column {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
.el-icon {
margin-left: 2px;
.el-tab-pane {
height: 100%;
display: flex;
flex-direction: column;
}
}
}
}
.el-form-item {
align-items: center;
}
.auto-fit-header-table {
width: 100%;
--el-table-header-cell-text-color: #333;
--el-table-header-cell-padding: 0 .4267rem;
/* 列头内边距(可调整) */
.formula-column {
display: flex;
justify-content: center;
align-items: center;
.el-table__header th.el-table__cell {
white-space: nowrap;
/* 禁止列头文本换行 */
text-overflow: clip;
/* 溢出不隐藏(若想隐藏用 ellipsis,但需配合 overflow: hidden) */
overflow: visible;
/* 允许内容撑满(避免文本被截断) */
}
/* 保持原有的单元格样式,但优化内容显示 */
.el-table__body td.el-table__cell {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
.el-icon {
margin-left: 2px;
}
}
}
}
/* 优化超长文本的显示效果 */
.cell {
padding: 0 .2133rem;
.el-form-item {
align-items: center;
}
/* 表格内下拉框 */
.el-select {
width: 100% !important;
}
}
}
</style>
\ No newline at end of file
<template>
<el-row>
<el-form-item label="操作类型">
<el-radio-group v-model="operation"
@change="checkTableColumns">
<el-radio-button label="全部列"
value="全部列" />
<el-radio-button label="填报列"
value="填报列" />
</el-radio-group>
</el-form-item>
<right-toolbar v-model:showSearch="showSearch"
@queryTable="getTableList()"
:columns="chooseColumns"
:showColumnsType="operation === '全部列' ? 'tree' : 'checkbox'"
:defaultCheckedKeys="visibleProps">
</right-toolbar>
</el-row>
<!-- 筛选列组的按钮 -->
<el-table :data="tableData"
height="100%"
border
:scroll-x="'max-content'"
class="auto-fit-header-table"
fit
v-loading="isLoading">
<el-table-column v-for="col in tableColumns"
:label="col.label"
align="center"
:min-width="getColumnMinWidth(col)"
show-overflow-tooltip>
<template #header="{ column }">
<!-- 只为特定列添加问号图标 -->
<span class="formula-column">
{{ column.label }}
<el-tooltip v-if="col.type === 'formula'"
:content="col.formulaStr"
placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
</span>
</template>
<template #default="{ row }">
<div v-if="col.type === 'select'">
<!-- 实际主货架-数量(要根据实际主货架-形式不为空时才可以选择否则为 0) -->
<div v-if="col.prop === 'actualMainShelfQty'">
<el-select :disabled="!row.actualMainShelfType"
v-model="row[col.prop]"
placeholder="请选择"
clearable
@change="submitChange(row, col)">
<el-option v-for="item in col.options"
:key="item.value"
:label="item.label"
:value="item.value" />
</el-select>
</div>
<el-select v-else
v-model="row[col.prop]"
placeholder="请选择"
clearable
@change="submitChange(row, col)">
<el-option v-for="item in col.options"
:key="item.value"
:label="item.label"
:value="item.value" />
</el-select>
</div>
<!-- 公式计算 -->
<div v-else-if="col.type === 'formula'">
{{ col.func(row) }}
</div>
<!-- 输入框 -->
<div v-else-if="col.type === 'input'">
<el-input v-model="row[col.prop]"
placeholder="请输入"
@input="submitChange(row, col)" />
</div>
<!-- 为其他类型或未定义类型提供默认显示 -->
<div v-else>
<div class="ellipsis-text"
style="max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
{{ formatterTableData(row, col) }}
</div>
</div>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<pagination :total="total"
v-model:page="params.pageNum"
v-model:limit="params.pageSize"
@pagination="getTableList" />
</template>
<script setup>
import { getDisplayList, submitDisplayPlan } from '@/api'
import { parseTime } from '@/utils'
const activeName = ref('陈列计划');
const handleClickTabs = (tab) => {
activeName.value = tab.name;
}
/*************** 操作类型 ***************/
const operation = ref('全部列');
// 全部列
const baseColumns = ref([
{
label: "基础信息",
children: [
{ label: "销售大区", prop: "regionName", visible: true, type: 'string' },
{ label: "销售战区", prop: "districtName", visible: true, type: 'string' },
{ label: "经销商-省份", prop: "dealerProvince", visible: true, type: 'string' },
{ label: "经销商-城市", prop: "dealerCity", visible: true, type: 'string' },
{ label: "经销商-代码", prop: "dealerCode", visible: true, type: 'string' },
{ label: "经销商名称", prop: "dealerName", visible: true, type: 'string' },
{ label: "经销商-类型", prop: "dealerType", visible: true, type: 'string' },
{ label: "开户日期", prop: "openingDate", visible: true, type: 'string' },
{ label: "闭户日期", prop: "closingDate", visible: true, type: 'string' },
{ label: "大区总监", prop: "regionManager", visible: true, type: 'string' },
{ label: "战区经理", prop: "districtManager", visible: true, type: 'string' },
{ label: "城市经理", prop: "cityManager", visible: true, type: 'string' },
{ label: "门店编码", prop: "storeCode", visible: true, type: 'string' },
{ label: "门店名称", prop: "storeName", visible: true, type: 'string' },
{ label: "门店-省份", prop: "storeProvince", visible: true, type: 'string' },
{ label: "门店-城市", prop: "storeCity", visible: true, type: 'string' },
{ label: "系统名称", prop: "lineName", visible: true, type: 'string' },
{ label: "系统类型", prop: "lineType", visible: true, type: 'string' },
{ label: "渠道大类", prop: "channelDl", visible: true, type: 'string' },
{ label: "渠道小类", prop: "channelXl", visible: true, type: 'string' },
{ label: "门店类型", prop: "storeType", visible: true, type: 'string' },
{ label: "系统业态", prop: "systemFormat", visible: true, type: 'string' },
{ label: "门店面积", prop: "storeArea", visible: true, type: 'string' },
{ label: "门店分级(销量坎级)", prop: "storeLevel", visible: true, type: 'string' },
{ label: "门店地址", prop: "storeAddress", visible: true, type: 'string' },
{ label: "品项数", prop: "productCount", visible: true, type: 'string' }
],
prop: 'baseColumns',
visible: true
},
{
label: "大业态测试",
children: [
{ label: "大业态测试-动销模型", prop: "lfSalesModel", visible: true, type: 'string' },
{ label: "大业态测试-月均POS", prop: "lfMonthlyPos", visible: true, type: 'string' },
],
prop: 'lfColumns',
visible: true
},
{
label: "费用计划",
prop: 'fpColumns',
children: [
{ label: "计划主货架-形式", prop: "plannedMainShelfType", visible: true, type: 'string' },
{ label: "计划主货架-数量", prop: "plannedMainShelfQty", visible: true, type: 'string' },
{ label: "计划主货架-单个费用", prop: "plannedMainShelfUnitCost", visible: true, type: 'string' },
{ label: "计划主货架-总费用", prop: "plannedMainShelfTotalCost", visible: true, type: 'string' },
{
label: "实际主货架-形式",
prop: "actualMainShelfType",
visible: true,
type: 'select',
options: [
{ label: '4纵', value: '4纵' },
{ label: '5纵', value: '5纵' },
{ label: '6纵', value: '6纵' },
{ label: '7纵', value: '7纵' },
{ label: '8纵及以上', value: '8纵及以上' }
]
},
{
label: "实际主货架-数量",
prop: "actualMainShelfQty",
visible: true,
type: 'select',
options: [
{ label: '1', value: 1 },
{ label: '2', value: 2 }
]
},
{
label: "实际主货架-是否执行",
prop: "actualMainShelfExecuted",
visible: true,
type: 'formula', // 公式
func: (row) => {
row.actualMainShelfExecuted = ((parseInt(row.actualMainShelfType) >= parseInt(row.plannedMainShelfType)) && (parseInt(row.actualMainShelfQty) >= parseInt(row.plannedMainShelfQty))) ? '是' : '否';
return row.actualMainShelfExecuted;
},
formulaStr: '公式:(实际主货架形式 >= 计划主货架形式)并且(实际主货架数量 >= 计划主货架数量)',
},
{ label: "计划端架-数量", prop: "plannedEndCapQty", visible: true },
{ label: "计划端架-总费用", prop: "plannedEndCapTotalCost", visible: true },
{ label: "计划端架-单个费用", prop: "plannedEndCapUnitCost", visible: true },
{
label: "实际端架-数量",
prop: "actualEndCapQty",
visible: true,
type: 'select',
options: [
{ label: '0', value: 0 },
{ label: '0.5', value: 0.5 },
{ label: '1', value: 1 },
{ label: '2', value: 2 }
]
},
{
label: "实际端架-是否执行",
prop: "actualEndCapExecuted",
visible: true,
type: 'formula', // 公式
func: (row) => {
row.actualEndCapExecuted = ((parseFloat(row.actualEndCapQty) >= parseFloat(row.plannedEndCapQty))) ? '是' : '否';
return row.actualEndCapExecuted;
},
formulaStr: '公式:(实际端架数量 >= 计划端架数量)',
},
{
label: "计划地堆-平米数(㎡)",
prop: "plannedFloorStackArea",
visible: true
},
{ label: "计划地堆-数量", prop: "plannedFloorStackQty", visible: true },
{ label: "计划主题地堆-是否", prop: "plannedThemedFloorStack", visible: true },
{ label: "计划地堆-总费用", prop: "plannedFloorStackTotalCost", visible: true },
{ label: "计划折算1㎡-单个费用", prop: "plannedFloorStackUnitCostPerSqm", visible: true },
{
label: "实际地堆-平米数(㎡)",
prop: "actualFloorStackArea",
visible: true,
type: 'select',
options: [
{ label: '0', value: 0 },
{ label: '0.5', value: 0.5 },
{ label: '0.8', value: 0.8 },
{ label: '1', value: 1 },
{ label: '2', value: 2 },
{ label: '3', value: 3 },
{ label: '4', value: 4 },
]
},
{
label: "实际地堆-数量",
prop: "actualFloorStackQty",
visible: true,
type: 'select',
options: [
{ label: '0', value: 0 },
{ label: '1', value: 1 },
{ label: '2', value: 2 },
{ label: '3', value: 3 }
]
},
{
label: "实际主题地堆-是否",
prop: "actualThemedFloorStack",
visible: true,
type: 'select',
options: [
{ label: '是', value: '是' },
{ label: '否', value: '否' },
]
},
{
label: "实际地堆是否执行",
prop: "actualFloorStackExecuted",
visible: true,
type: 'formula', // 公式
func: (row) => {
row.actualFloorStackExecuted = ((parseFloat(row.actualFloorStackArea) >= parseFloat(row.plannedFloorStackArea)) && (parseInt(row.actualFloorStackQty) >= parseInt(row.plannedFloorStackQty))) ? '是' : '否';
return row.actualFloorStackExecuted;
},
formulaStr: '公式:(实际地堆平米数 >= 计划地堆平米数)并且(实际地堆数量 >= 计划地堆数量)',
},
{ label: "计划多点陈列-数量+形式", prop: "plannedMultiDisplay", visible: true },
{ label: "计划多点陈列-总费用", prop: "plannedMultiDisplayTotalCost", visible: true },
{
label: "实际多点陈列-数量+形式",
prop: "actualMultiDisplay",
visible: true,
type: 'input',
func: (row) => {
// 没有输入内容时,则是否执行设置为否
row.actualMultiDisplayExecuted = !row.actualMultiDisplay ? '否' : '是'
}
},
{
label: "实际多点陈列-是否执行",
prop: "actualMultiDisplayExecuted",
visible: true,
type: 'select',
options: [
{ label: '是', value: '是' },
{ label: '否', value: '否' },
]
},
{ label: "合计费用-费用", prop: "totalCost", visible: true },
{ label: "合计费用-费率", prop: "totalCostRate", visible: true },
{
label: "常规陈列是否执行",
prop: "regularDisplayExecuted",
visible: true,
type: 'formula', // 公式
func: (row) => {
// 实际主货架-是否执行 && 实际端架-是否执行 && 实际地堆-是否执行 && 实际多点陈列-是否执行
row.regularDisplayExecuted = (row.actualMainShelfExecuted === '是' && row.actualEndCapExecuted === '是' && row.actualFloorStackExecuted === '是' && row.actualMultiDisplayExecuted === '是') ? '是' : '否';
return row.regularDisplayExecuted;
}
},
{ label: "综合标签-拜访辅助列", prop: "visitAssistTag", visible: true },
{ label: "付费陈列- 是否", prop: "paidDisplay", visible: true },
{ label: "当月拜访目标", prop: "monthlyVisitTarget", visible: true },
{ label: "当月是否拜访", prop: "monthlyVisited", visible: true }
],
visible: true
}
// ...baseColumns.value,
// ...lfColumns.value,
// ...fpColumns.value
]);
// 填报列
const fillColumns = ref([
{ label: "系统名称", prop: "lineName", visible: true, type: 'string' },
{ label: "门店编码", prop: "storeCode", visible: true },
{ label: "门店名称", prop: "storeName", visible: true },
{ label: "计划主货架-形式", prop: "plannedMainShelfType", visible: true, type: 'string' },
{ label: "计划主货架-数量", prop: "plannedMainShelfQty", visible: true, type: 'string' },
{
label: "实际主货架-形式",
prop: "actualMainShelfType",
visible: true,
type: 'select',
options: [
{ label: '4纵', value: '4纵' },
{ label: '5纵', value: '5纵' },
{ label: '6纵', value: '6纵' },
{ label: '7纵', value: '7纵' },
{ label: '8纵及以上', value: '8纵及以上' }
]
},
{
label: "实际主货架-数量",
prop: "actualMainShelfQty",
visible: true,
type: 'select',
options: [
{ label: '1', value: 1 },
{ label: '2', value: 2 }
]
},
{
label: "实际主货架-是否执行",
prop: "actualMainShelfExecuted",
visible: true,
type: 'formula', // 公式
func: (row) => {
row.actualMainShelfExecuted = ((parseInt(row.actualMainShelfType) >= parseInt(row.plannedMainShelfType)) && (parseInt(row.actualMainShelfQty) >= parseInt(row.plannedMainShelfQty))) ? '是' : '否';
return row.actualMainShelfExecuted;
},
formulaStr: '公式:(实际主货架形式 >= 计划主货架形式)并且(实际主货架数量 >= 计划主货架数量)',
},
{ label: "计划端架-数量", prop: "plannedEndCapQty", visible: true },
{
label: "实际端架-数量",
prop: "actualEndCapQty",
visible: true,
type: 'select',
options: [
{ label: '0', value: 0 },
{ label: '0.5', value: 0.5 },
{ label: '1', value: 1 },
{ label: '2', value: 2 }
]
},
{
label: "实际端架-是否执行",
prop: "actualEndCapExecuted",
visible: true,
type: 'formula', // 公式
func: (row) => {
row.actualEndCapExecuted = ((parseFloat(row.actualEndCapQty) >= parseFloat(row.plannedEndCapQty))) ? '是' : '否';
return row.actualEndCapExecuted;
},
formulaStr: '公式:(实际端架数量 >= 计划端架数量)',
},
{
label: "计划地堆-平米数(㎡)",
prop: "plannedFloorStackArea",
visible: true
},
{ label: "计划地堆-数量", prop: "plannedFloorStackQty", visible: true },
{ label: "计划主题地堆-是否", prop: "plannedThemedFloorStack", visible: true },
{
label: "实际地堆-平米数(㎡)",
prop: "actualFloorStackArea",
visible: true,
type: 'select',
options: [
{ label: '0', value: 0 },
{ label: '0.5', value: 0.5 },
{ label: '0.8', value: 0.8 },
{ label: '1', value: 1 },
{ label: '2', value: 2 },
{ label: '3', value: 3 },
{ label: '4', value: 4 },
]
},
{
label: "实际地堆-数量",
prop: "actualFloorStackQty",
visible: true,
type: 'select',
options: [
{ label: '0', value: 0 },
{ label: '1', value: 1 },
{ label: '2', value: 2 },
{ label: '3', value: 3 }
]
},
{
label: "实际主题地堆-是否",
prop: "actualThemedFloorStack",
visible: true,
type: 'select',
options: [
{ label: '是', value: '是' },
{ label: '否', value: '否' },
]
},
{
label: "实际地堆是否执行",
prop: "actualFloorStackExecuted",
visible: true,
type: 'formula', // 公式
func: (row) => {
row.actualFloorStackExecuted = ((parseFloat(row.actualFloorStackArea) >= parseFloat(row.plannedFloorStackArea)) && (parseInt(row.actualFloorStackQty) >= parseInt(row.plannedFloorStackQty))) ? '是' : '否';
return row.actualFloorStackExecuted;
},
formulaStr: '公式:(实际地堆平米数 >= 计划地堆平米数)并且(实际地堆数量 >= 计划地堆数量)',
},
{ label: "计划多点陈列-数量+形式", prop: "plannedMultiDisplay", visible: true },
{ label: "计划多点陈列-总费用", prop: "plannedMultiDisplayTotalCost", visible: true },
{
label: "实际多点陈列-数量+形式",
prop: "actualMultiDisplay",
visible: true,
type: 'input',
func: (row) => {
// 没有输入内容时,则是否执行设置为否
row.actualMultiDisplayExecuted = !row.actualMultiDisplay ? '否' : '是'
}
},
{
label: "实际多点陈列-是否执行",
prop: "actualMultiDisplayExecuted",
visible: true,
type: 'select',
options: [
{ label: '是', value: '是' },
{ label: '否', value: '否' },
]
},
{ label: "合计费用-费用", prop: "totalCost", visible: true },
{ label: "合计费用-费率", prop: "totalCostRate", visible: true },
{
label: "常规陈列是否执行",
prop: "regularDisplayExecuted",
visible: true,
type: 'formula', // 公式
func: (row) => {
// 实际主货架-是否执行 && 实际端架-是否执行 && 实际地堆-是否执行 && 实际多点陈列-是否执行
row.regularDisplayExecuted = (row.actualMainShelfExecuted === '是' && row.actualEndCapExecuted === '是' && row.actualFloorStackExecuted === '是' && row.actualMultiDisplayExecuted === '是') ? '是' : '否';
return row.regularDisplayExecuted;
},
formulaStr: '公式:(实际主货架是否执行 = 是)并且(实际端架是否执行 = 是)并且(实际地堆是否执行 = 是)并且(实际多点陈列是否执行 = 是)',
}
])
// 表格列数据
const tableColumns = ref([])
// 右上角工具选择列
const chooseColumns = ref([])
// 计算列具体数据
const checkTableColumns = () => {
if (operation.value === '全部列') {
chooseColumns.value = baseColumns.value
tableColumns.value = baseColumns.value.flatMap(item => {
if (item.children) {
// 在扁平化时就过滤掉 visible 为 false 的列
return item.children.filter(child => child.visible);
}
// 如果是没有 children 的单元素,也检查其 visible 属性
return item.visible ? item : [];
}).filter(Boolean); // 过滤掉空数组项
} else if (operation.value === '填报列') {
chooseColumns.value = fillColumns.value
tableColumns.value = fillColumns.value.filter(item => item.visible);
}
}
checkTableColumns()
// 选择列默认选中哪些
const visibleProps = computed(() => {
// 分情况返回
return tableColumns.value.flatMap(item => {
if (item.children) {
return item.children.map(child => child.prop);
}
return item.prop;
});
});
// 监听chooseColumns变化,当列的visible属性改变时重新计算tableColumns
watch(
() => chooseColumns.value,
() => {
// 不需要重新赋值,只需要重新计算tableColumns
checkTableColumns();
},
{ deep: true }
);
// 提交变更
const submitChange = async (row, col) => {
// 有个类型输入框的需要调用 func
if (col.type === 'input') {
col.func(row)
}
await submitDisplayPlan({
id: row.sadId,
[col.prop]: row[col.prop]
})
// 这些提交变化的,同时会影响公式计算的,需要把公式计算的字段列结果,一起发给后台
// 主货架
if (['actualMainShelfType', 'actualMainShelfQty'].includes(col.prop)) {
await submitDisplayPlan({
id: row.sadId,
actualMainShelfExecuted: row.actualMainShelfExecuted,
})
}
// 端架
if (['actualEndCapQty'].includes(col.prop)) {
await submitDisplayPlan({
id: row.sadId,
actualEndCapExecuted: row.actualEndCapExecuted,
})
}
// 地堆
if (['actualFloorStackArea', 'actualFloorStackQty'].includes(col.prop)) {
await submitDisplayPlan({
id: row.sadId,
actualFloorStackExecuted: row.actualFloorStackExecuted,
})
}
// 常规陈列是否执行
await submitDisplayPlan({
id: row.sadId,
regularDisplayExecuted: row.regularDisplayExecuted,
})
}
// 表格数据
const tableData = ref([])
const isLoading = ref(true)
const params = reactive({
pageNum: 1,
pageSize: 10,
})
const total = ref(0)
// 筛选工具
const showSearch = ref(true);
const getTableList = async () => {
isLoading.value = true
const res = await getDisplayList({
...params
})
tableData.value = res.data.rows
total.value = res.data.total
isLoading.value = false
}
getTableList()
// 列宽度
const getColumnMinWidth = (column) => {
// 根据列名或属性判断合适的最小宽度
const widthMap = {
'regionName': 85,
'districtName': 85,
'dealerProvince': 100,
'dealerCity': 100,
'dealerCode': 100,
'dealerName': 210,
'dealerType': 140,
'openingDate': 100,
'closingDate': 100,
'regionManager': 85,
'districtManager': 85,
'cityManager': 85,
'storeCode': 100,
'storeName': 120,
'storeProvince': 85,
'storeCity': 85,
'lineName': 85,
'lineType': 85,
'channelDl': 85,
'channelXl': 135,
'storeType': 85,
'systemFormat': 85,
'storeArea': 85,
'storeLevel': 160,
'storeAddress': 250,
'productCount': 75,
'lfSalesModel': 150,
'lfMonthlyPos': 150,
'plannedMainShelfType': 125,
'plannedMainShelfQty': 125,
'plannedMainShelfUnitCost': 150,
'plannedMainShelfTotalCost': 140,
'actualMainShelfType': 125,
'actualMainShelfQty': 125,
'actualMainShelfExecuted': 165,
'plannedEndCapQty': 110,
'plannedEndCapTotalCost': 125,
'plannedEndCapUnitCost': 135,
'actualEndCapQty': 110,
'actualEndCapExecuted': 150,
'plannedFloorStackArea': 165,
'plannedFloorStackQty': 110,
'plannedThemedFloorStack': 135,
'plannedFloorStackTotalCost': 125,
'plannedFloorStackUnitCostPerSqm': 155,
'actualFloorStackArea': 165,
'actualFloorStackQty': 110,
'actualThemedFloorStack': 135,
'actualFloorStackExecuted': 145,
'plannedMultiDisplay': 170,
'plannedMultiDisplayTotalCost': 150,
'actualMultiDisplay': 170,
'actualMultiDisplayExecuted': 165,
'totalCost': 110,
'totalCostRate': 110,
'regularDisplayExecuted': 145,
'visitAssistTag': 155,
'paidDisplay': 115,
'monthlyVisitTarget': 105,
'monthlyVisited': 105
};
return widthMap[column.prop]; // 默认宽度
};
// 格式化函数
const formatterTableData = (row, col) => {
if (col.prop === 'openingDate' || col.prop === 'closingDate') {
return parseTime(row[col.prop], '{y}-{m}-{d}')
}
return row[col.prop] || '-'
}
</script>
<style scoped
lang="scss">
.container {
.el-tabs {
height: 100%;
display: flex;
flex-direction: column-reverse;
.el-tabs__content {
display: flex;
flex-direction: column;
height: 100%;
.el-tab-pane {
height: 100%;
display: flex;
flex-direction: column;
.pagination-container {
margin: 10px;
}
}
.formula-column {
display: flex;
justify-content: center;
align-items: center;
.el-icon {
margin-left: 2px;
}
}
}
}
.el-form-item {
align-items: center;
}
.auto-fit-header-table {
width: 100%;
--el-table-header-cell-text-color: #333;
--el-table-header-cell-padding: 0 .4267rem;
/* 列头内边距(可调整) */
.el-table__header th.el-table__cell {
white-space: nowrap;
/* 禁止列头文本换行 */
text-overflow: clip;
/* 溢出不隐藏(若想隐藏用 ellipsis,但需配合 overflow: hidden) */
overflow: visible;
/* 允许内容撑满(避免文本被截断) */
}
/* 保持原有的单元格样式,但优化内容显示 */
.el-table__body td.el-table__cell {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
/* 优化超长文本的显示效果 */
.cell {
padding: 0 .2133rem;
}
/* 表格内下拉框 */
.el-select {
width: 100% !important;
}
}
}
</style>
\ No newline at end of file
<template>
<el-row>
<el-form-item label="操作类型">
<el-radio-group v-model="operation"
@change="checkTableColumns">
<el-radio-button label="全部列"
value="全部列" />
<el-radio-button label="填报列"
value="填报列" />
</el-radio-group>
</el-form-item>
<right-toolbar v-model:showSearch="showSearch"
@queryTable="getTableList()"
:columns="chooseColumns"
:showColumnsType="operation === '全部列' ? 'tree' : 'checkbox'"
:defaultCheckedKeys="visibleProps">
</right-toolbar>
</el-row>
<!-- 筛选列组的按钮 -->
<el-table :data="tableData"
height="100%"
border
:scroll-x="'max-content'"
class="auto-fit-header-table"
fit
v-loading="isLoading">
<el-table-column v-for="col in tableColumns"
:label="col.label"
align="center"
:min-width="getColumnMinWidth(col)"
show-overflow-tooltip>
<template #header="{ column }">
<!-- 只为特定列添加问号图标 -->
<span class="formula-column">
{{ column.label }}
<el-tooltip v-if="col.type === 'formula'"
:content="col.formulaStr"
placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
</span>
</template>
<template #default="{ row }">
<div v-if="col.type === 'select'">
<!-- 实际主货架-数量(要根据实际主货架-形式不为空时才可以选择否则为 0) -->
<div v-if="col.prop === 'actualMainShelfQty'">
<el-select :disabled="!row.actualMainShelfType"
v-model="row[col.prop]"
placeholder="请选择"
clearable
@change="submitChange(row, col)">
<el-option v-for="item in col.options"
:key="item.value"
:label="item.label"
:value="item.value" />
</el-select>
</div>
<el-select v-else
v-model="row[col.prop]"
placeholder="请选择"
clearable
@change="submitChange(row, col)">
<el-option v-for="item in col.options"
:key="item.value"
:label="item.label"
:value="item.value" />
</el-select>
</div>
<!-- 公式计算 -->
<div v-else-if="col.type === 'formula'">
{{ col.func(row) }}
</div>
<!-- 输入框 -->
<div v-else-if="col.type === 'input'">
<el-input v-model="row[col.prop]"
placeholder="请输入"
:type="col.format === 'number' ? 'number' : 'text'"
@input="submitChange(row, col)" />
</div>
<!-- 日期选择 -->
<div v-else-if="col.type === 'date'">
<el-date-picker v-model="row[col.prop]"
type="date"
:format="col.format"
placeholder="请选择日期"
@change="submitChange(row, col)" />
</div>
<!-- 为其他类型或未定义类型提供默认显示 -->
<div v-else>
<div class="ellipsis-text"
style="max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
{{ formatterTableData(row, col) }}
</div>
</div>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<pagination :total="total"
v-model:page="params.pageNum"
v-model:limit="params.pageSize"
@pagination="getTableList" />
</template>
<script setup>
import { getDisplayScheduleList, submitDisplaySchedulePlan } from '@/api'
import { parseTime } from '@/utils'
/*************** 操作类型 ***************/
const operation = ref('全部列');
// 全部列
const baseColumns = ref([
{
label: "基础信息",
children: [
{ "label": "销售大区", "prop": "regionName", visible: true },
{ "label": "销售战区", "prop": "districtName", visible: true },
{ "label": "经销商-省份", "prop": "dealerProvince", visible: true },
{ "label": "经销商-城市", "prop": "dealerCity", visible: true },
{ "label": "经销商-代码", "prop": "dealerCode", visible: true },
{ "label": "经销商名称", "prop": "dealerName", visible: true },
{ "label": "经销商类型", "prop": "dealerType", visible: true },
{ "label": "开户日期", "prop": "openingDate", visible: true },
{ "label": "闭户日期", "prop": "closingDate", visible: true },
{ "label": "大区总监", "prop": "regionManager", visible: true },
{ "label": "战区经理", "prop": "districtManager", visible: true },
{ "label": "城市经理", "prop": "cityManager", visible: true },
{ "label": "系统名称", "prop": "lineName", visible: true },
{ "label": "系统类型", "prop": "lineType", visible: true },
{ "label": "渠道大类", "prop": "channelDl", visible: true },
{ "label": "渠道小类", "prop": "channelXl", visible: true },
{ "label": "系统业态", "prop": "lineLf", visible: true },
{ "label": "门店数", "prop": "storeCount", visible: true }
],
prop: 'baseColumns',
visible: true
},
{
label: "档期基础信息",
children: [
{ "label": "档期执行月份", "prop": "promotionExecutionMonth", visible: true },
{ "label": "档期计划-促销规格", "prop": "plannedPromotionSpec", visible: true },
{ "label": "档期计划-促销口味", "prop": "plannedPromotionFlavor", visible: true },
{
"label": "档期执行-促销规格",
"prop": "actualPromotionSpec",
visible: true,
type: 'select',
options: [
{ label: '虎皮105g', value: '虎皮105g' },
{ label: '虎皮210g', value: '虎皮210g' },
{ label: '去骨72g', value: '去骨72g' },
{ label: '去骨138g', value: '去骨138g' },
{ label: '小鸡腿80g', value: '小鸡腿80g' },
{ label: '老卤95g', value: '老卤95g' },
{ label: '鸡肉豆堡', value: '鸡肉豆堡' },
{ label: '牛肉豆堡', value: '牛肉豆堡' },
]
},
{
"label": "档期执行-促销口味",
"prop": "actualPromotionFlavor",
visible: true,
type: 'input'
},
{
"label": "档期规格是否执行",
"prop": "specExecutionStatus",
visible: true,
type: 'formula',
func: (row) => {
row.specExecutionStatus = row.plannedPromotionSpec === row.actualPromotionSpec ? '是' : '否';
return row.specExecutionStatus;
},
formulaStr: '公式:(档期计划促销规格 = 档期执行促销规格)',
},
],
prop: 'scheduleInfo',
visible: true
},
{
label: "合计费用",
prop: 'totalCostParent',
children: [
{ "label": "合计费用", "prop": "totalCost", visible: true },
{ "label": "合计费率", "prop": "totalCostRate", visible: true },
],
visible: true
},
{
label: "促销计划",
prop: 'promotionPlan',
children: [
{ "label": "计划-档期形式", "prop": "plannedPromotionFormat", visible: true },
{ "label": "计划-核销方式", "prop": "plannedVerificationMethod", visible: true },
{ "label": "计划-档期规则", "prop": "plannedPromotionRules", visible: true },
{ "label": "计划-档期前补差天数", "prop": "plannedPrePromotionAdjustDays", visible: true },
{ "label": "计划-档期后补差天数", "prop": "plannedPostPromotionAdjustDays", visible: true },
{
"label": "计划-档期开始时间",
"prop": "plannedPromotionStartDate",
visible: true
},
{
"label": "实际-档期开始时间",
"prop": "actualPromotionStartDate",
visible: true,
type: 'date',
format: 'MM-DD'
},
{ "label": "计划-档期结束时间", "prop": "plannedPromotionEndDate", visible: true },
{
"label": "实际-档期结束时间",
"prop": "actualPromotionEndDate",
visible: true,
type: 'date',
format: 'MM-DD'
},
{
"label": "档期是否开展",
"prop": "promotionImplementationStatus",
visible: true,
type: 'formula',
func: (row) => {
row.promotionImplementationStatus = row.actualPromotionStartDate && row.actualPromotionEndDate ? '是' : '否';
return row.promotionImplementationStatus;
},
formulaStr: '公式:(实际档期开始时间不为空,并且实际档期结束时间不为空)',
},
{
"label": "时间是否执行",
"prop": "timeExecutionStatus",
visible: true,
type: 'formula',
func: (row) => {
row.timeExecutionStatus = (row.actualPromotionStartDate === row.plannedPromotionStartDate) && (row.actualPromotionEndDate === row.plannedPromotionEndDate) ? '是' : '否';
return row.timeExecutionStatus;
},
formulaStr: '公式:(实际档期开始时间 = 计划档期开始时间,并且实际档期结束时间 = 计划档期结束时间)',
},
{ "label": "计划-补差开始时间", "prop": "plannedAdjustmentStartDate", visible: true },
{ "label": "计划-补差结束时间", "prop": "plannedAdjustmentEndDate", visible: true },
{ "label": "计划促销机制", "prop": "plannedPromotionMechanism", visible: true },
{
"label": "实际促销机制",
"prop": "actualPromotionMechanism",
visible: true,
type: 'input'
},
{
"label": "促销机制是否执行",
"prop": "promotionMechanismExecutionStatus",
visible: true,
type: 'select',
options: [
{ label: '是', value: '是' },
{ label: '否', value: '否' },
]
},
{ "label": "预估袋数", "prop": "estimatedBagCount", visible: true },
{
"label": "档期备货量(袋)",
"prop": "promotionStockQuantity",
visible: true,
type: 'input',
format: 'number',
},
{ "label": "单包厂价(单包)", "prop": "unitFactoryPrice", visible: true },
{ "label": "正常供价(单包)", "prop": "normalSupplyPrice", visible: true },
{ "label": "日常零售价(单包)", "prop": "regularRetailPrice", visible: true },
{ "label": "计划促销售价(单包)", "prop": "plannedPromotionPrice", visible: true },
{
"label": "实际促销售价(单包)",
"prop": "actualPromotionPrice",
visible: true,
type: 'input',
format: 'number',
},
{
"label": "促销价是否执行",
"prop": "promotionPriceExecutionStatus", visible: true,
type: 'formula',
func: (row) => {
row.promotionPriceExecutionStatus = row.plannedPromotionPrice == row.actualPromotionPrice ? '是' : '否';
return row.promotionPriceExecutionStatus;
},
formulaStr: '公式:(计划促销售价 = 实际促销售价)',
},
{ "label": "正常经销商毛利现状", "prop": "normalDealerMarginStatus", visible: true },
{ "label": "系统前台毛利保证", "prop": "systemFrontendMarginGuarantee", visible: true },
{ "label": "系统后台毛利保证", "prop": "systemBackendMarginGuarantee", visible: true },
{ "label": "系统促销毛利保证", "prop": "systemPromotionMarginGuarantee", visible: true },
{ "label": "经销商毛利保证", "prop": "dealerMarginGuarantee", visible: true },
{ "label": "单袋补差金额(费用)", "prop": "unitBagAdjustmentAmount", visible: true },
{ "label": "补差费比(%)", "prop": "adjustmentCostRatio", visible: true },
{ "label": "整体补差(费用)", "prop": "totalAdjustmentCost", visible: true },
{
"label": "档期是否执行",
"prop": "promotionExecutionStatus",
visible: true,
type: 'formula',
func: (row) => {
// 促销价是否执行,促销机制是否执行,促销规格是否执行,档期是否开展
row.promotionExecutionStatus = row.promotionPriceExecutionStatus == '是' && row.promotionMechanismExecutionStatus == '是' && row.specExecutionStatus == '是' && row.promotionImplementationStatus == '是' ? '是' : '否';
return row.promotionExecutionStatus;
},
formulaStr: '公式:(促销价是否执行 = 是,并且促销机制是否执行 = 是,并且促销规格是否执行 = 是,并且档期是否开展 = 是)',
},
],
visible: true
}, {
label: "海报计划",
prop: 'posterPlan',
children: [
{ "label": "计划-海报形式", "prop": "plannedPosterFormat", visible: true },
{ "label": "计划-海报费用", "prop": "plannedPosterCost", visible: true },
{
"label": "实际-海报形式",
"prop": "actualPosterFormat",
visible: true,
type: 'select',
options: [
{ label: '电子', value: '电子' },
{ label: '纸制', value: '纸制' }
]
},
{
"label": "海报是否执行",
"prop": "posterExecutionStatus",
visible: true,
type: 'formula',
func: (row) => {
row.posterExecutionStatus = row.plannedPosterFormat == row.actualPosterFormat ? '是' : '否';
return row.posterExecutionStatus;
},
formulaStr: '公式:(计划海报形式 = 实际海报形式)',
},
],
visible: true
},
{
label: "档期陈列",
prop: 'displayPlan',
children: [
{ "label": "门店数", "prop": "storeCountInt", visible: true },
{ "label": "店均费用", "prop": "averageStoreCost", visible: true },
{ "label": "费用", "prop": "cost", visible: true },
],
visible: true
}
]);
// 填报列
const fillColumns = ref([
{ "label": "档期计划-促销规格", "prop": "plannedPromotionSpec", visible: true },
{ "label": "档期计划-促销口味", "prop": "plannedPromotionFlavor", visible: true }, {
"label": "档期执行-促销规格",
"prop": "actualPromotionSpec",
visible: true,
type: 'select',
options: [
{ label: '虎皮105g', value: '虎皮105g' },
{ label: '虎皮210g', value: '虎皮210g' },
{ label: '去骨72g', value: '去骨72g' },
{ label: '去骨138g', value: '去骨138g' },
{ label: '小鸡腿80g', value: '小鸡腿80g' },
{ label: '老卤95g', value: '老卤95g' },
{ label: '鸡肉豆堡', value: '鸡肉豆堡' },
{ label: '牛肉豆堡', value: '牛肉豆堡' },
]
},
{
"label": "档期执行-促销口味",
"prop": "actualPromotionFlavor",
visible: true,
type: 'input'
},
{
"label": "档期规格是否执行",
"prop": "specExecutionStatus",
visible: true,
type: 'formula',
func: (row) => {
row.specExecutionStatus = row.plannedPromotionSpec === row.actualPromotionSpec ? '是' : '否';
return row.specExecutionStatus;
},
formulaStr: '公式:(档期计划促销规格 = 档期执行促销规格)',
}, {
"label": "计划-档期开始时间",
"prop": "plannedPromotionStartDate",
visible: true
},
{
"label": "实际-档期开始时间",
"prop": "actualPromotionStartDate",
visible: true,
type: 'date',
format: 'MM-DD'
},
{ "label": "计划-档期结束时间", "prop": "plannedPromotionEndDate", visible: true },
{
"label": "实际-档期结束时间",
"prop": "actualPromotionEndDate",
visible: true,
type: 'date',
format: 'MM-DD'
},
{
"label": "档期是否开展",
"prop": "promotionImplementationStatus",
visible: true,
type: 'formula',
func: (row) => {
row.promotionImplementationStatus = row.actualPromotionStartDate && row.actualPromotionEndDate ? '是' : '否';
return row.promotionImplementationStatus;
},
formulaStr: '公式:(实际档期开始时间不为空,并且实际档期结束时间不为空)',
},
{
"label": "时间是否执行",
"prop": "timeExecutionStatus",
visible: true,
type: 'formula',
func: (row) => {
row.timeExecutionStatus = (row.actualPromotionStartDate === row.plannedPromotionStartDate) && (row.actualPromotionEndDate === row.plannedPromotionEndDate) ? '是' : '否';
return row.timeExecutionStatus;
},
formulaStr: '公式:(实际档期开始时间 = 计划档期开始时间,并且实际档期结束时间 = 计划档期结束时间)',
},
{ "label": "计划促销机制", "prop": "plannedPromotionMechanism", visible: true },
{
"label": "实际促销机制",
"prop": "actualPromotionMechanism",
visible: true,
type: 'input'
},
{
"label": "促销机制是否执行",
"prop": "promotionMechanismExecutionStatus",
visible: true,
type: 'select',
options: [
{ label: '是', value: '是' },
{ label: '否', value: '否' },
]
},
{ "label": "预估袋数", "prop": "estimatedBagCount", visible: true },
{
"label": "档期备货量(袋)",
"prop": "promotionStockQuantity",
visible: true,
type: 'input',
format: 'number',
}, { "label": "计划促销售价(单包)", "prop": "plannedPromotionPrice", visible: true },
{
"label": "实际促销售价(单包)",
"prop": "actualPromotionPrice",
visible: true,
type: 'input',
format: 'number',
},
{
"label": "促销价是否执行",
"prop": "promotionPriceExecutionStatus", visible: true,
type: 'formula',
func: (row) => {
row.promotionPriceExecutionStatus = row.plannedPromotionPrice == row.actualPromotionPrice ? '是' : '否';
return row.promotionPriceExecutionStatus;
},
formulaStr: '公式:(计划促销售价 = 实际促销售价)',
}, {
"label": "档期是否执行",
"prop": "promotionExecutionStatus",
visible: true,
type: 'formula',
func: (row) => {
// 促销价是否执行,促销机制是否执行,促销规格是否执行,档期是否开展
row.promotionExecutionStatus = row.promotionPriceExecutionStatus == '是' && row.promotionMechanismExecutionStatus == '是' && row.specExecutionStatus == '是' && row.promotionImplementationStatus == '是' ? '是' : '否';
return row.promotionExecutionStatus;
},
formulaStr: '公式:(促销价是否执行 = 是,并且促销机制是否执行 = 是,并且促销规格是否执行 = 是,并且档期是否开展 = 是)',
}, { "label": "计划-海报形式", "prop": "plannedPosterFormat", visible: true }, {
"label": "实际-海报形式",
"prop": "actualPosterFormat",
visible: true,
type: 'select',
options: [
{ label: '电子', value: '电子' },
{ label: '纸制', value: '纸制' }
]
},
{
"label": "海报是否执行",
"prop": "posterExecutionStatus",
visible: true,
type: 'formula',
func: (row) => {
row.posterExecutionStatus = row.plannedPosterFormat == row.actualPosterFormat ? '是' : '否';
return row.posterExecutionStatus;
},
formulaStr: '公式:(计划海报形式 = 实际海报形式)',
},
])
// 表格列数据
const tableColumns = ref([])
// 右上角工具选择列
const chooseColumns = ref([])
// 计算列具体数据
const checkTableColumns = () => {
if (operation.value === '全部列') {
chooseColumns.value = baseColumns.value
tableColumns.value = baseColumns.value.flatMap(item => {
if (item.children) {
// 在扁平化时就过滤掉 visible 为 false 的列
return item.children.filter(child => child.visible);
}
// 如果是没有 children 的单元素,也检查其 visible 属性
return item.visible ? item : [];
}).filter(Boolean); // 过滤掉空数组项
} else if (operation.value === '填报列') {
chooseColumns.value = fillColumns.value
tableColumns.value = fillColumns.value.filter(item => item.visible);
}
}
checkTableColumns()
// 选择列默认选中哪些
const visibleProps = computed(() => {
// 分情况返回
return tableColumns.value.flatMap(item => {
if (item.children) {
return item.children.map(child => child.prop);
}
return item.prop;
});
});
// 监听chooseColumns变化,当列的visible属性改变时重新计算tableColumns
watch(
() => chooseColumns.value,
() => {
// 不需要重新赋值,只需要重新计算tableColumns
checkTableColumns();
},
{ deep: true }
);
// 提交变更
const submitChange = async (row, col) => {
// 如果是 实际促销售价(单包),保留 2 位小数
if (col.prop === 'actualPromotionPrice') {
row[col.prop] = parseFloat(parseFloat(row[col.prop]).toFixed(2))
}
await submitDisplaySchedulePlan({
id: row.sapId,
[col.prop]: row[col.prop]
})
// 这些提交变化的,同时会影响公式计算的,需要把公式计算的字段列结果,一起发给后台
// 档期规格是否执行:计划规格和执行规格
if (['plannedPromotionSpec', 'actualPromotionSpec'].includes(col.prop)) {
await submitDisplaySchedulePlan({
id: row.sapId,
specExecutionStatus: row.specExecutionStatus,
})
}
// 档期是否开展:实际档期开始和结束
if (['actualPromotionStartDate', 'actualPromotionEndDate'].includes(col.prop)) {
await submitDisplaySchedulePlan({
id: row.sapId,
promotionImplementationStatus: row.promotionImplementationStatus,
})
}
// 档期是否执行:实际开始和计划开始时间,实际结束时间和计划结束时间
if (['actualPromotionStartDate', 'plannedPromotionStartDate', 'actualPromotionEndDate', 'plannedPromotionEndDate'].includes(col.prop)) {
await submitDisplaySchedulePlan({
id: row.sapId,
timeExecutionStatus: row.timeExecutionStatus,
})
}
// 促销价是否执行:根据计划和实际促销价
if (['actualPromotionPrice', 'plannedPromotionPrice'].includes(col.prop)) {
await submitDisplaySchedulePlan({
id: row.sapId,
promotionPriceExecutionStatus: row.promotionPriceExecutionStatus,
})
}
// 海报是否执行
if (['plannedPosterFormat', 'actualPosterFormat'].includes(col.prop)) {
await submitDisplaySchedulePlan({
id: row.sapId,
posterExecutionStatus: row.posterExecutionStatus,
})
}
// 档期计划是否执行
await submitDisplaySchedulePlan({
id: row.sapId,
promotionExecutionStatus: row.promotionExecutionStatus,
})
}
// 表格数据
const tableData = ref([])
const isLoading = ref(true)
const params = reactive({
pageNum: 1,
pageSize: 10,
})
const total = ref(0)
// 筛选工具
const showSearch = ref(true);
const getTableList = async () => {
isLoading.value = true
const res = await getDisplayScheduleList({
...params
})
tableData.value = res.data.rows
total.value = res.data.total
isLoading.value = false
}
getTableList()
// 列宽度
const getColumnMinWidth = (column) => {
// 根据列名或属性判断合适的最小宽度
const widthMap = {
'regionName': 85,
'districtName': 85,
'dealerProvince': 100,
'dealerCity': 100,
'dealerCode': 100,
'dealerName': 210,
'dealerType': 110,
'openingDate': 100,
'closingDate': 100,
'regionManager': 85,
'districtManager': 85,
'cityManager': 85,
'lineName': 85,
'lineType': 85,
'channelDl': 85,
'channelXl': 135,
'lineLf': 85,
'storeCount': 70,
'promotionExecutionMonth': 105,
'plannedPromotionSpec': 135,
'plannedPromotionFlavor': 135,
'actualPromotionSpec': 135,
'actualPromotionFlavor': 135,
'specExecutionStatus': 145,
'totalCost': 100,
'totalCostRate': 80,
'plannedPromotionFormat': 110,
'plannedVerificationMethod': 110,
'plannedPromotionRules': 110,
'plannedPrePromotionAdjustDays': 150,
'plannedPostPromotionAdjustDays': 150,
'plannedPromotionStartDate': 135,
'actualPromotionStartDate': 135,
'plannedPromotionEndDate': 135,
'actualPromotionEndDate': 135,
'promotionImplementationStatus': 120,
'timeExecutionStatus': 120,
'plannedAdjustmentStartDate': 135,
'plannedAdjustmentEndDate': 135,
'plannedPromotionMechanism': 110,
'actualPromotionMechanism': 110,
'promotionMechanismExecutionStatus': 130,
'estimatedBagCount': 85,
'promotionStockQuantity': 130,
'unitFactoryPrice': 130,
'normalSupplyPrice': 130,
'regularRetailPrice': 145,
'plannedPromotionPrice': 160,
'actualPromotionPrice': 160,
'promotionPriceExecutionStatus': 135,
'normalDealerMarginStatus': 145,
'systemFrontendMarginGuarantee': 130,
'systemBackendMarginGuarantee': 130,
'systemPromotionMarginGuarantee': 130,
'dealerMarginGuarantee': 120,
'unitBagAdjustmentAmount': 160,
'adjustmentCostRatio': 120,
'totalAdjustmentCost': 130,
'promotionExecutionStatus': 120,
'plannedPosterFormat': 110,
'plannedPosterCost': 110,
'actualPosterFormat': 110,
'posterExecutionStatus': 120,
'storeCountInt': 70,
'averageStoreCost': 110,
'cost': 110
};
return widthMap[column.prop] || 150; // 默认宽度
};
// 格式化函数
const formatterTableData = (row, col) => {
if (col.prop === 'openingDate' || col.prop === 'plannedAdjustmentStartDate' || col.prop === 'plannedAdjustmentEndDate') {
return parseTime(row[col.prop], '{y}-{m}-{d}')
} else if (col.prop === 'plannedPromotionStartDate' || col.prop === 'actualPromotionStartDate' || col.prop === 'plannedPromotionEndDate' || col.prop === 'actualPromotionEndDate') {
return parseTime(row[col.prop], '{m}-{d}')
} else if (col.prop === 'totalCostRate' || col.prop === 'adjustmentCostRatio') {
return `${(row[col.prop]).toFixed(2)}%`
}
return row[col.prop] || '-'
}
</script>
<style scoped
lang="scss">
.container {
.el-tabs {
height: 100%;
display: flex;
flex-direction: column-reverse;
.el-tabs__content {
display: flex;
flex-direction: column;
height: 100%;
.el-tab-pane {
height: 100%;
display: flex;
flex-direction: column;
.pagination-container {
margin: 10px;
}
}
.formula-column {
display: flex;
justify-content: center;
align-items: center;
.el-icon {
margin-left: 2px;
}
}
}
}
.el-form-item {
align-items: center;
}
.auto-fit-header-table {
width: 100%;
--el-table-header-cell-text-color: #333;
--el-table-header-cell-padding: 0 .4267rem;
/* 列头内边距(可调整) */
.el-table__header th.el-table__cell {
white-space: nowrap;
/* 禁止列头文本换行 */
text-overflow: clip;
/* 溢出不隐藏(若想隐藏用 ellipsis,但需配合 overflow: hidden) */
overflow: visible;
/* 允许内容撑满(避免文本被截断) */
}
/* 保持原有的单元格样式,但优化内容显示 */
.el-table__body td.el-table__cell {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
/* 优化超长文本的显示效果 */
.cell {
padding: 0 .2133rem;
}
/* 表格内下拉框 */
.el-select {
width: 100% !important;
}
}
}
::v-deep(.el-date-editor) {
width: 100%;
}
</style>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论