提交 996665dd authored 作者: lidongxu's avatar lidongxu

Merge branch 'ap' into dev

<template>
<div class="flex-container">
<!-- 操作类型 -->
<el-row>
<el-form-item>
......@@ -18,8 +19,23 @@
:columns="chooseColumns"
:showColumnsType="operation === '展示模式' ? 'tree' : 'checkbox'"
:defaultCheckedKeys="visibleProps">
<!-- 添加自定义工具栏插槽 -->
<template #default>
<!-- 默认插槽内容,父组件可以覆盖 -->
<el-tooltip class="item"
effect="dark"
content="放大表格"
placement="top">
<el-button circle
icon="Rank"
@click="openTableDialog" />
</el-tooltip>
</template>
</right-toolbar>
</el-row>
<!-- 表格容器 - 用于DOM移动 -->
<div ref="tableContainer"
class="table-container">
<!-- 数据表格 -->
<el-table :data="tableData"
border
......@@ -64,9 +80,10 @@
{{ col.func(row) }}
</div>
<!-- 其他类型内容 -->
<div v-else>
<div cllass="fill-span-wrap"
v-else>
<!-- 正常显示 -->
<span>{{ row[col.prop] || '-' }}</span>
<span class="fill-span">{{ row[col.prop] || '-' }}</span>
</div>
</div>
<!-- 展示模式 -->
......@@ -81,6 +98,19 @@
v-model:page="params.pageNum"
v-model:limit="params.pageSize"
@pagination="getTableList" />
</div>
</div>
<!-- 表格弹窗 - 使用DOM移动而非复制 -->
<el-dialog v-model="showTableInDialog"
title="表格详情"
modal-class="table-dialog-modal"
fullscreen
:before-close="handleDialogClose">
<!-- 弹窗内的表格容器 -->
<div ref="dialogTableContainer"
class="dialog-table-container"></div>
</el-dialog>
</template>
<script setup>
......@@ -130,8 +160,8 @@ const emit = defineEmits(['updateColumns', 'getTableList', 'updateShowSearch'])
/*************** 工具栏 ***************/
// 切换平铺/填报模式
const operation = ref('展示模式');
// const operation = ref('填报模式');
// const operation = ref('展示模式');
const operation = ref('填报模式');
const tableRef = ref(null)
const checkTableColumns = async () => {
// 通知外面传入 tableColumns / chooseColumns 数据源
......@@ -157,11 +187,82 @@ watch(showSearch, (newVal) => {
const getTableList = () => {
emit('getTableList')
}
/************** 弹框控制 ***************/
// 控制表格弹框显隐
const tableContainer = ref(null) // 原始表格容器引用
const dialogTableContainer = ref(null) // 弹窗内表格容器引用
const showTableInDialog = ref(false)
// DOM移动需要的引用
let containerElement = null // 保存整个可移动容器
let originalParent = null // 保存原始父容器
// 打开表格弹窗并移动DOM
const openTableDialog = async () => {
// 保存容器元素和原始父容器引用
if (tableContainer.value) {
containerElement = tableContainer.value
originalParent = containerElement.parentElement
}
// 显示弹窗
showTableInDialog.value = true
// 等待弹窗渲染完成后移动DOM
await nextTick()
moveContentToDialog()
}
// 移动内容到弹窗
const moveContentToDialog = () => {
if (containerElement && dialogTableContainer.value) {
// 关键DOM移动操作 - 现在会移动整个容器(包含表格和分页器)
dialogTableContainer.value.appendChild(containerElement)
// 调整表格布局
nextTick(() => {
if (tableRef.value) {
tableRef.value.doLayout()
}
})
}
}
// 移动内容回原位
const moveContentBack = () => {
if (containerElement && originalParent) {
// 关键DOM移动操作
originalParent.appendChild(containerElement)
// 调整表格布局
nextTick(() => {
if (tableRef.value) {
tableRef.value.doLayout()
}
})
}
}
// 关闭弹窗
const handleDialogClose = () => {
// 先移动内容回原位
moveContentBack()
// 然后关闭弹窗
showTableInDialog.value = false
}
</script>
<style scoped
lang="scss">
/* 根容器设置为flex布局,占据整个可用空间 */
.flex-container {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
/* 工具栏 */
.el-row {
.el-form-item {
......@@ -174,10 +275,21 @@ const getTableList = () => {
}
}
}
}
/* 因为表格会被挪走,所以必须独立样式无法嵌套在别人内 */
/* 表格样式 */
.table-container {
flex: 1;
/* 这是关键,让表格容器自动占据剩余空间 */
display: flex;
flex-direction: column;
min-height: 0;
/* 解决flex子项内容溢出问题 */
/* overflow-y: scroll; */
.auto-fit-header-table {
height: 100%;
flex: 1;
/* 列样式 */
.column-style {
......@@ -214,19 +326,17 @@ const getTableList = () => {
white-space: nowrap;
}
.cell-style {
>div {
display: flex;
flex-direction: column;
align-items: flex-start;
align-items: center;
>span {
text-align: left;
text-indent: 5px;
display: inline-block;
width: 100%;
width: 80%;
background-color: #e1e2e6;
border-bottom: 1px solid #ebeef5;
}
......@@ -237,35 +347,33 @@ const getTableList = () => {
width: 100% !important;
padding: 10px;
::v-deep(.el-select__wrapper) {
/* 非 disabled 状态下的背景颜色 */
&.no-disabled ::v-deep(.el-select__wrapper) {
border: 4px solid var(--el-background-editor-cell) !important;
}
/* 非 disabled 状态下的背景颜色 */
/* &.no-disabled {
background-color: ;
} */
}
.el-input {
padding: 10px;
height: 32px !important;
/* box-sizing: content-box; */
padding: 0 10px;
width: 100%;
::v-deep(.el-input__wrapper) {
/* 非 disabled 状态下的背景颜色 */
&.no-disabled ::v-deep(.el-input__wrapper) {
border: 4px solid var(--el-background-editor-cell) !important;
}
/* &.no-disabled {
background-color: var(--el-background-editor-cell);
} */
}
.date-picker {
width: 100%;
padding: 10px;
&.no-disabled {
background-color: var(--el-background-editor-cell);
/* 非 disabled 状态下的背景颜色 */
&.no-disabled ::v-deep(.el-input__wrapper) {
border: 4px solid var(--el-background-editor-cell) !important;
}
::v-deep(.el-input) {
......@@ -274,6 +382,20 @@ const getTableList = () => {
}
}
}
/* 填充模式下的普通战士文字 */
.fill-span-wrap {
/* line-height: 1; */
.fill-span {
display: inline-block;
width: 80% !important;
/* 超出省略号 */
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
/* 填报模式-单元格 */
......@@ -296,4 +418,47 @@ const getTableList = () => {
.pagination-container {
margin: 10px;
}
}
</style>
<style lang="scss">
/* 表格弹窗 */
.table-dialog-modal {
padding: 0;
/* 关键:覆盖Element Plus对话框的默认最大宽度 */
.el-dialog {
width: 100% !important;
max-width: none !important;
margin: 0 !important;
height: 100vh;
display: flex;
flex-direction: column;
.el-dialog__body {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden !important;
.dialog-table-container {
flex: 1;
height: 100%;
.table-container {
flex: 1;
display: flex;
flex-direction: column;
height: 100%;
.pagination-container {
margin-left: auto;
}
}
}
}
}
}
</style>
\ No newline at end of file
......@@ -41,7 +41,8 @@ import Snack from './tabs/snack.vue'
import ThreeTwoSeconds from './tabs/three_two_seconds.vue'
import SixLittleDiamonds from './tabs/six_little_diamonds.vue'
const activeName = ref('常规陈列');
// const activeName = ref('常规陈列');
const activeName = ref('档期计划');
const handleClickTabs = (tab) => {
activeName.value = tab.name;
}
......
......@@ -34,32 +34,31 @@
{
label: "基础信息", // 类型标题(用于右上角控制显隐列)
children: [
{
label: '操作提示', // 列标题
prop: 'operationTip', // 列属性
visible: true, // 是否显示
type: 'string', // 列类型
fill: true, // 是否在填报模式显示
fixed: 'left', // 是否固定在左侧
width: 100, // 列宽度
onlyFill: true, // 只在填报列显示(展示模式不显示)
render: (_, row, col) => { // 列自定义渲染内容
return (
<div class="operation_tip_cell">
<p>计划</p>
<p>实际</p>
</div>
)
}
},
// {
// label: '操作提示', // 列标题
// prop: 'operationTip', // 列属性
// visible: true, // 是否显示
// type: 'string', // 列类型
// fill: true, // 是否在填报模式显示
// fixed: 'left', // 是否固定在左侧
// width: 100, // 列宽度
// onlyFill: true, // 只在填报列显示(展示模式不显示)
// render: (_, row, col) => { // 列自定义渲染内容
// return (
// <div class="operation_tip_cell">
// <p>计划</p>
// <p>实际</p>
// </div>
// )
// }
// },
{
label: '计划月份', // 列标题
prop: 'salesMonth', // 列属性
visible: true, // 是否显示
type: 'string', // 列类型
fill: true, // 是否为填报列
fixed: 'left', // 是否固定在左侧
width: 90
fill: false, // 是否为填报列
width: 100
},
{
"label": "销售大区",
......@@ -167,7 +166,7 @@
"type": "string",
"fill": true,
"width": 100,
fixed: 'left'
// fixed: 'left'
},
{
"label": "系统类型",
......@@ -372,11 +371,12 @@
// "width": 280
// },
{
"label": "计划端架 - 数量",
"label": "端架数量",
"subLabel": '计划',
"prop": "plannedEndCapQty",
"visible": true,
"type": "string",
"fill": false,
"fill": true,
"width": 140
},
// {
......@@ -388,7 +388,8 @@
// "width": 140
// },
{
"label": "实际端架 - 数量",
"label": "端架数量",
"subLabel": '实际',
"prop": "actualEndCapQty",
"visible": true,
"type": "select",
......@@ -414,7 +415,7 @@
render: (_, row, col) => {
return (
<div>
<span>{row[col.referenceKey] || '-'}</span>
{/* <span>{row[col.referenceKey] || '-'}</span> */}
<el-select modelValue={row[col.prop]}
onUpdate:modelValue={(value) => {
if (!value) {
......@@ -443,12 +444,13 @@
requestKey: ["actualEndCapExecuted", "promotionDisplayExecuted"]
},
{
"label": "实际端架 - 是否执行",
"label": "端架是否",
"subLabel": '按计划执行',
"prop": "actualEndCapExecuted",
"visible": true,
"type": "formula",
"fill": true,
"width": 160,
"width": 140,
func: (row) => {
// 如果计划端架数量为空则返回 '-'
if (!row.plannedEndCapQty) {
......@@ -461,21 +463,15 @@
formulaStr: "执行端架数量 >= 计划端架数量"
},
{
"label": "计划地堆 - 平米数(㎡)",
"label": "地堆平米数(㎡)",
"subLabel": '计划',
"prop": "plannedFloorStackArea",
"visible": true,
"type": "string",
"fill": false,
"width": 180
},
{
"label": "计划地堆 - 数量",
"prop": "plannedFloorStackQty",
"visible": true,
"type": "string",
"fill": false,
"fill": true,
"width": 140
},
// {
// "label": "计划地堆 - 费用",
// "prop": "plannedFloorStackTotalCost",
......@@ -485,12 +481,13 @@
// "width": 140
// },
{
"label": "实际地堆 - 平米数(㎡)",
"label": "地堆平米数(㎡)",
"subLabel": '实际',
"prop": "actualFloorStackArea",
"visible": true,
"type": "input",
"fill": true,
"width": 180,
"width": 140,
referenceKey: "plannedFloorStackArea",
// "options": [
// {
......@@ -529,7 +526,7 @@
render: (_, row, col) => {
return (
<div>
<span>{row[col.referenceKey] || '-'}</span>
{/* <span>{row[col.referenceKey] || '-'}</span> */}
<el-input modelValue={row[col.prop]}
onUpdate:modelValue={(value) => {
// 判断空字符串给 0
......@@ -550,7 +547,17 @@
requestKey: ["actualFloorStackExecuted", "promotionDisplayExecuted"]
},
{
"label": "实际地堆 - 数量",
"label": "地堆数量",
"subLabel": '计划',
"prop": "plannedFloorStackQty",
"visible": true,
"type": "string",
"fill": true,
"width": 140
},
{
"label": "地堆数量",
"subLabel": '实际',
"prop": "actualFloorStackQty",
"visible": true,
"type": "input",
......@@ -583,7 +590,7 @@
render: (_, row, col) => {
return (
<div>
<span>{row[col.referenceKey] || '-'}</span>
{/* <span>{row[col.referenceKey] || '-'}</span> */}
<el-input modelValue={row[col.prop]}
onUpdate:modelValue={(value) => {
const numValue = value === '' ? 0 : Number(value);
......@@ -603,12 +610,13 @@
requestKey: ["actualFloorStackExecuted", "promotionDisplayExecuted"]
},
{
"label": "实际地堆是否执行",
"label": "地堆是否",
"subLabel": '按计划执行',
"prop": "actualFloorStackExecuted",
"visible": true,
"type": "formula",
"fill": true,
"width": 150,
"width": 140,
func: (row) => {
// 如果计划端架数量为空则返回 '-'
if (!row.plannedFloorStackArea || !row.plannedFloorStackQty) {
......@@ -621,12 +629,13 @@
formulaStr: "执行平米数 >= 计划平米数,并且 执行地堆数量 >= 计划地堆数量"
},
{
"label": "计划其他陈列数量 + 形式",
"label": "其他陈列数量+形式",
"subLabel": '计划',
"prop": "plannedOtherDisplay",
"visible": true,
"type": "string",
"fill": false,
"width": 180
"fill": true,
"width": 140
},
// {
// "label": "计划其他陈列 - 总费用",
......@@ -637,7 +646,8 @@
// "width": 160
// },
{
"label": "实际其他陈列 - 数量 + 形式",
"label": "其他陈列数量+形式",
"subLabel": '实际',
"prop": "actualOtherDisplay",
"visible": true,
"type": "select",
......@@ -651,7 +661,7 @@
render: (_, row, col) => {
return (
<div>
<span>{row[col.referenceKey] || '-'}</span>
{/* <span>{row[col.referenceKey] || '-'}</span> */}
<el-select modelValue={row[col.prop]}
onUpdate:modelValue={(value) => {
row[col.prop] = value;
......@@ -676,12 +686,13 @@
requestKey: ["actualOtherDisplayExecuted", "promotionDisplayExecuted"]
},
{
"label": "实际其他陈列 - 是否执行",
"label": "其他陈列是否",
"subLabel": '按计划执行',
"prop": "actualOtherDisplayExecuted",
"visible": true,
"type": "formula",
"fill": true,
"width": 190,
"width": 140,
func: (row) => {
if (!row.plannedOtherDisplay) {
row.actualOtherDisplayExecuted = '-'
......@@ -828,7 +839,7 @@
const isLoading = ref(true)
let params = reactive({
pageNum: 1,
pageSize: 10,
pageSize: 20,
})
const total = ref(0)
......
......@@ -34,32 +34,31 @@
{
label: "基础信息",
children: [
{
label: '操作提示',
prop: 'operationTip', // 列属性
visible: true, // 是否显示
type: 'string', // 列类型
fill: true, // 是否为填报列
fixed: 'left', // 是否固定在左侧
width: 100,
onlyFill: true, // 只在填报列显示
render: (_, row, col) => {
return (
<div class="operation_tip_cell">
<p>计划</p>
<p>实际</p>
</div>
)
}
},
// {
// label: '操作提示',
// prop: 'operationTip', // 列属性
// visible: true, // 是否显示
// type: 'string', // 列类型
// fill: true, // 是否为填报列
// fixed: 'left', // 是否固定在左侧
// width: 100,
// onlyFill: true, // 只在填报列显示
// render: (_, row, col) => {
// return (
// <div class="operation_tip_cell">
// <p>计划</p>
// <p>实际</p>
// </div>
// )
// }
// },
{
label: '计划月份', // 列标题
prop: 'salesMonth', // 列属性
visible: true, // 是否显示
type: 'string', // 列类型
fill: true, // 是否为填报列
fixed: 'left', // 是否固定在左侧
width: 90
fill: false, // 是否为填报列
width: 100
},
{
label: '销售大区',
......@@ -225,15 +224,17 @@
label: "六小金刚批发挂网",
children: [
{
label: '计划执行-六小金刚批发挂网',
label: '六小金刚批发挂网',
subLabel: '计划',
prop: 'plannedGw6',
visible: true,
type: 'string',
fill: false,
width: 180
fill: true,
width: 210
},
{
label: '实际执行-六小金刚批发挂网',
label: '六小金刚批发挂网',
subLabel: '实际',
prop: 'actualGw6',
referenceKey: 'plannedGw6',
visible: true,
......@@ -247,8 +248,8 @@
// ],
render: (_, row, col) => {
return (
<div>
<span>{row[col.referenceKey] || '-'}</span>
<div style="padding: 10px 0;">
{/* <span>{row[col.referenceKey] || '-'}</span> */}
<el-input modelValue={row[col.prop]}
onUpdate:modelValue={(value) => {
const numValue = value === '' ? 0 : Number(value);
......@@ -266,7 +267,7 @@
)
},
fill: true,
width: 190
width: 210
},
{
label: '六小金刚批发挂网陈列费',
......@@ -277,7 +278,8 @@
width: 160
},
{
label: '六小金刚批发挂网-是否执行',
label: '六小金刚批发挂网是否',
subLabel: '按实际执行',
prop: 'gwExecuted6',
visible: true,
type: 'formula',
......@@ -357,7 +359,7 @@
const params = ref({
pageNum: 1,
pageSize: 10,
pageSize: 20,
})
const showFill = ref(true)
const getTableList = () => {
......
......@@ -33,32 +33,31 @@
{
label: "基础信息",
children: [
{
label: '操作提示',
prop: 'operationTip', // 列属性
visible: true, // 是否显示
type: 'string', // 列类型
fill: true, // 是否为填报列
fixed: 'left', // 是否固定在左侧
width: 100,
onlyFill: true, // 只在填报列显示
render: (_, row, col) => {
return (
<div class="operation_tip_cell">
<p>计划</p>
<p>实际</p>
</div>
)
}
},
// {
// label: '操作提示',
// prop: 'operationTip', // 列属性
// visible: true, // 是否显示
// type: 'string', // 列类型
// fill: true, // 是否为填报列
// fixed: 'left', // 是否固定在左侧
// width: 100,
// onlyFill: true, // 只在填报列显示
// render: (_, row, col) => {
// return (
// <div class="operation_tip_cell">
// <p>计划</p>
// <p>实际</p>
// </div>
// )
// }
// },
{
label: '计划月份', // 列标题
prop: 'salesMonth', // 列属性
visible: true, // 是否显示
type: 'string', // 列类型
fill: true, // 是否为填报列
fixed: 'left', // 是否固定在左侧
width: 90
fill: false, // 是否为填报列
width: 100
},
{
"label": "销售大区",
......@@ -250,15 +249,17 @@
"width": 280
},
{
"label": "计划 - 陈列形式",
"label": "陈列形式",
subLabel: '计划',
"prop": "plannedDisplay",
"visible": true,
"type": "string",
"fill": false,
"width": 140
"fill": true,
"width": 190
},
{
"label": "实际 - 陈列形式",
"label": "陈列形式",
subLabel: '实际',
"prop": "actualDisplay",
"visible": true,
"type": "input",
......@@ -276,7 +277,7 @@
render: (_, row, col) => {
return (
<div>
<span>{row[col.referenceKey] || '-'}</span>
{/* <span>{row[col.referenceKey] || '-'}</span> */}
<div style="width: 100%">
<el-select modelValue={row[col.prop]}
onUpdate:modelValue={(value) => {
......@@ -297,7 +298,7 @@
)
},
"fill": true,
"width": 160,
"width": 190,
// "options": [
// {
// "label": "端架",
......@@ -360,15 +361,17 @@
// formulaStr: "实际陈列形式 === 计划陈列形式"
// },
{
"label": "计划 - 端架数量(组)",
"label": "端架数量(组)",
subLabel: '计划',
"prop": "plannedEndCapQty",
"visible": true,
"type": "string",
"fill": false,
"width": 160
"fill": true,
"width": 190
},
{
"label": "实际 - 端架数量(组)",
"label": "端架数量(组)",
subLabel: '实际',
"prop": "actualEndCapQty",
"visible": true,
"type": "input",
......@@ -395,7 +398,6 @@
render: (_, row, col) => {
return (
<div>
<span>{row[col.referenceKey] || '-'}</span>
<div>
<el-input modelValue={row[col.prop]}
onUpdate:modelValue={(value) => {
......@@ -414,7 +416,7 @@
</div>
)
},
"width": 160,
"width": 190,
// requestKey: ["endCapQtyExecuted", "snackDisplayExecuted"]
requestKey: ["endCapQtyExecuted"]
},
......@@ -621,7 +623,7 @@
const isLoading = ref(true)
let params = reactive({
pageNum: 1,
pageSize: 10,
pageSize: 20,
})
const total = ref(0)
......
......@@ -37,32 +37,31 @@
{
label: "基础信息",
children: [
{
label: '操作提示',
prop: 'operationTip', // 列属性
visible: true, // 是否显示
type: 'string', // 列类型
fill: true, // 是否为填报列
fixed: 'left', // 是否固定在左侧
width: 100,
onlyFill: true, // 只在填报列显示
render: (_, row, col) => {
return (
<div class="operation_tip_cell">
<p>计划</p>
<p>实际</p>
</div>
)
}
},
// {
// label: '操作提示',
// prop: 'operationTip', // 列属性
// visible: true, // 是否显示
// type: 'string', // 列类型
// fill: true, // 是否为填报列
// fixed: 'left', // 是否固定在左侧
// width: 100,
// onlyFill: true, // 只在填报列显示
// render: (_, row, col) => {
// return (
// <div class="operation_tip_cell">
// <p>计划</p>
// <p>实际</p>
// </div>
// )
// }
// },
{
label: '计划月份', // 列标题
prop: 'salesMonth', // 列属性
visible: true, // 是否显示
type: 'string', // 列类型
fill: true, // 是否为填报列
fixed: 'left', // 是否固定在左侧
width: 90
fill: false, // 是否为填报列
width: 100
},
{
label: '销售大区',
......@@ -228,12 +227,13 @@
label: "60g挂条陈列",
children: [
{
label: '计划-60g挂条陈列数量',
label: '60g挂条陈列数量',
subLabel: '计划',
prop: 'plannedDisplayQty60',
visible: true,
type: 'string',
fill: false,
width: 160
fill: true,
width: 200
},
{
label: '60g挂条陈列费',
......@@ -244,17 +244,18 @@
width: 140
},
{
label: '实际-60g挂条陈列数量',
label: '60g挂条陈列数量',
subLabel: '实际',
prop: 'actualDisplayQty60',
referenceKey: 'plannedDisplayQty60',
visible: true,
type: 'input',
fill: true,
width: 160,
width: 200,
render: (_, row, col) => {
return (
<div>
<span>{row[col.referenceKey] || '-'}</span>
<div style="padding: 10px 0;">
{/* <span>{row[col.referenceKey] || '-'}</span> */}
<div>
<el-input
modelValue={row[col.prop]}
......@@ -278,7 +279,8 @@
},
// 60g挂条陈列-是否执行
{
label: '60g挂条陈列-是否执行',
label: '60g挂条陈列是否',
subLabel: '按计划执行',
prop: 'displayQtyExecuted60',
visible: true,
type: 'formula',
......@@ -358,7 +360,7 @@
const params = ref({
pageNum: 1,
pageSize: 10,
pageSize: 20,
})
const showFill = ref(true)
const getTableList = () => {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论