提交 f552a6b9 authored 作者: lidongxu's avatar lidongxu

refactor(bi/product/index.vue): bi 商品管理重构完成-包括单屏幕适配

同上
上级 16c93ed7
...@@ -91,6 +91,7 @@ ...@@ -91,6 +91,7 @@
color: var(--el-color-primary) !important; color: var(--el-color-primary) !important;
} }
// 覆盖默认样式
.el-select { .el-select {
width: 215px; width: 215px;
} }
...@@ -98,3 +99,7 @@ ...@@ -98,3 +99,7 @@
.el-tabs { .el-tabs {
flex: 1; flex: 1;
} }
.el-form-item {
margin-bottom: 0;
}
...@@ -127,6 +127,10 @@ aside { ...@@ -127,6 +127,10 @@ aside {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
padding: 20px;
>div{
width: 100%;
}
} }
.components-container { .components-container {
......
<template> <template>
<el-col :span="hideSideBar ? colSpan : 0" <el-col :span="hideSideBar ? 0 : colSpan"
:xs="24" :xs="24"
class="col"
@click.native="cancelSel"> @click.native="cancelSel">
<div v-show="hideSideBar" <div v-show="!hideSideBar"
class="content"> class="content">
<div class="buttons_wrap"> <div class="buttons_wrap">
<!-- 扩展的按钮集合 --> <!-- 扩展的按钮 -->
<slot name="buttons"></slot> <slot name="buttons"></slot>
<el-input v-model="searchValue" <el-input v-model="searchValue"
:placeholder="placeholder" :placeholder="placeholder"
clearable clearable
prefix-icon="el-icon-search" /> prefix-icon="Search" />
</div> </div>
<div class="scroll" :class="{'row_gap': rowGap}"> <div class="scroll"
:class="{ 'row_gap': customOptions.rowGap }">
<el-tree :data="options" <el-tree :data="options"
v-loading="loading" v-loading="loading"
:props="defaultProps" :props="defaultProps"
:expand-on-click-node="false" :expand-on-click-node="false"
:filter-node-method="filterNode" :filter-node-method="filterNode"
ref="tree" ref="treeRef"
:node-key="nodeKey" :node-key="nodeKey"
highlight-current highlight-current
default default
...@@ -27,10 +27,12 @@ ...@@ -27,10 +27,12 @@
@node-click="handleNodeClick"> @node-click="handleNodeClick">
<template class="custom-tree-node" <template class="custom-tree-node"
v-slot="{ node, data }" v-slot="{ node, data }"
:style="{margin: rowGap * 3 + 'px !important'}"> :style="{ margin: rowGap + 'px !important' }">
<svg-icon v-if="showIcon" icon-class="tab" style="fill: #409eff; stroke: red; margin-right: 10px;"/> <svg-icon v-if="customOptions.showIcon"
icon-class="tab"
style="fill: #409eff; stroke: red; margin-right: 10px;" />
<span>{{ node.label }}</span> <span>{{ node.label }}</span>
<span v-if="showEditDel" <span v-if="customOptions.showTool"
class="edit_del"> class="edit_del">
<span style="margin-right: 10px;">创建人:{{ data.createBy }}</span> <span style="margin-right: 10px;">创建人:{{ data.createBy }}</span>
<i class="el-icon-edit" <i class="el-icon-edit"
...@@ -41,34 +43,35 @@ ...@@ -41,34 +43,35 @@
</template> </template>
</el-tree> </el-tree>
<!-- 分页 --> <!-- 分页 -->
<pagination v-if="isPagination" :total="total" v-model:page="queryParams.pageNum" <pagination v-if="customOptions.showPagination"
v-model:limit="queryParams.pageSize" @pagination="getPageList" /> :total="customOptions.total"
<!-- 折叠箭头 --> v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getPageList" />
<!-- 折叠分类侧边栏 -->
<div class="arrow" <div class="arrow"
@click="hideSideBar = false"> @click="hideSideBar = true">
<svg-icon icon-class="left-arrow" /> <svg-icon icon-class="left-arrow" />
</div> </div>
</div> </div>
</div> </div>
<!-- 表格折叠箭头 --> <!-- 展开分类侧边栏 -->
<div class="arrow" <div class="arrow"
v-show="!hideSideBar" v-show="hideSideBar"
@click="hideSideBar = !hideSideBar"> @click="hideSideBar = !hideSideBar">
<svg-icon icon-class="right-arrow" /> <svg-icon icon-class="right-arrow" />
</div> </div>
</el-col> </el-col>
</template> </template>
<script> <script setup>
export default { const props = defineProps({
name: "FlodSidebar",
props: {
// 树结构数据 // 树结构数据
options: { options: {
type: Array, type: Array,
required: true, required: true,
default: () => { default: () => {
return []; return []
} }
}, },
// 树结构主键 // 树结构主键
...@@ -78,136 +81,139 @@ export default { ...@@ -78,136 +81,139 @@ export default {
}, },
// 树结构使用字段 // 树结构使用字段
defaultProps: { defaultProps: {
type: Object, type: Object
default: () => {
return {};
}
}, },
// 默认展开哪些行 // 默认展开哪些行
defaultExpandList: { defaultExpandList: {
type: Array, type: Array
default: () => {
return [];
}
}, },
// 搜索占位符 // 搜索占位符
placeholder: { placeholder: {
type: String, type: String,
default: '' default: '搜索关键字'
},
// 加载状态
loading: {
type: Boolean,
default: false
}, },
// 选中某行数据对象 // 选中某行数据对象
value: { value: {
type: [Number, String] type: [Number, String],
default: ''
}, },
// 占 el-col 几份宽度 // el-col 宽度
colSpan: { colSpan: {
type: Number, type: Number,
default: 6 default: 6
}, },
// 左侧分类框右侧是否出现编辑和删除按钮 // 详细配置左侧分类框
showEditDel: { customOptions: {
type: Boolean, type: Object,
default: false default: () => ({
}, // 右侧工具是否显示
// 数据重载中 showTool: false,
loading: { // 左侧图表是否显示
type: Boolean, showIcon: false,
default: false // 行与行间隙
}, rowGap: 0,
// 是否展示图标 // 底部分页是否显示
showIcon: { showPagination: false,
type: Boolean, // 分页数据总条数
default: false total: 0
}, })
// 行之间的间隙
rowGap: {
type: Boolean,
default: false
},
// 开启分页
isPagination: {
type: Boolean,
default: false
},
// (若有分页功能)- 总数
total: {
type: Number,
default: 0
} }
}, })
data() {
return { // 隐藏左侧分类框
// 侧边栏展开与否 const hideSideBar = ref(false)
hideSideBar: true, // 搜索关键字
// 搜索关键字 const searchValue = ref('')
searchValue: '', // 上次点击的行对象-唯一值
// 上次点击的行对象-唯一值 const lastRowId = ref(null)
lastRowId: null, const lastRow = ref(null)
// 分页参数 // 分页参数
queryParams: { const queryParams = reactive({
pageNum: 1, pageNum: 1,
pageSize: 10 pageSize: 10
}, })
}; const treeRef = ref(null)
},
watch: { const emits = defineEmits(['update:modelValue', 'search', 'pageChange'])
// 根据名称筛选树
searchValue(val) { watch(searchValue, (val) => {
// 如果做了分页走网络搜索 if (!props.customOptions.showPagination) {
if (!this.isPagination) {
// 没有分页,用本地列表搜索 // 没有分页,用本地列表搜索
this.$refs.tree.filter(val); treeRef.value.filter(val);
} else { } else {
// 有分页,走外面搜索 // 有分页,走外面接口搜索
this.queryParams.searchKey = val queryParams.searchKey = val
this.$emit('pageChange', this.queryParams) emits('search', queryParams)
} }
}, })
value(val) {
this.$nextTick(() => { // 如果有 v-model 则设置默认选中值
this.$refs.tree.setCurrentKey(val) watch(() => props.value, (val) => {
this.lastRowId = val if (val) {
nextTick(() => {
treeRef.value.setCurrentKey(val)
lastRowId.value = val
}) })
} }
}, })
methods: {
// 空白位置-取消选中效果 // 点击空白位置-取消选中效果
cancelSel() { const cancelSel = () => {
// 刚才有过点击的某行 // 刚才有过点击的某行
if (this.lastRow) { if (lastRow.value) {
this.$refs.tree.setCurrentKey(null) treeRef.value.setCurrentKey(null)
this.lastRow = null lastRow.value = null
this.$emit('update:modelValue', '') emits('update:modelValue', '')
this.$emit('search') emits('search')
} }
}, }
// 点击某行
handleNodeClick(row) { // 点击某行
const handleNodeClick = (row) => {
// 当前点击和上次点击一样->取消 // 当前点击和上次点击一样->取消
if (this.lastRowId === row[this.nodeKey]) { if (lastRowId.value === row[props.nodeKey]) {
this.$refs.tree.setCurrentKey(null) treeRef.value.setCurrentKey(null)
this.lastRowId = null lastRowId.value = null
} else { } else {
this.lastRowId = row[this.nodeKey] lastRowId.value = row[props.nodeKey]
} }
this.$emit('update:modelValue', this.lastRowId ? row[this.nodeKey] : '') emits('update:modelValue', lastRowId.value ? row[props.nodeKey] : '')
this.$emit('search') emits('search')
}, }
// tree 筛选节点
filterNode(value, data) { // tree 筛选节点
const filterNode = (value, data) => {
if (!value) return true; if (!value) return true;
return data[this.defaultProps.label].indexOf(value) !== -1; return data[props.defaultProps.label].indexOf(value) !== -1;
}, }
// 分页逻辑触发
getPageList(){ // 分页逻辑触发
this.$emit('pageChange', this.queryParams) const getPageList = () => {
} emits('pageChange', queryParams)
} }
};
</script> </script>
<style scoped <style scoped
lang="scss"> lang="scss">
.el-col {
padding: 0 !important;
height: 100%;
.content {
height: 100%;
.buttons_wrap {
padding-right: 10px;
}
}
}
::v-deep(.custom-tree-node) { ::v-deep(.custom-tree-node) {
width: 100%; width: 100%;
padding-right: 20px; padding-right: 20px;
...@@ -222,17 +228,19 @@ export default { ...@@ -222,17 +228,19 @@ export default {
} }
} }
} }
/* 间距放大 */ /* 间距放大 */
::v-deep(.row_gap .el-tree-node .el-tree-node__content){ ::v-deep(.row_gap .el-tree-node .el-tree-node__content) {
padding: 10px 0; padding: 10px 0;
height: auto; height: auto;
} }
// el-tree 取消选中时背景还有个颜色去掉
/* el-tree 取消选中时背景还有个颜色去掉 */
::v-deep(.el-tree-node:focus>.el-tree-node__content) { ::v-deep(.el-tree-node:focus>.el-tree-node__content) {
background-color: transparent; background-color: transparent;
} }
// el-tree 选中时的背景色设置 /* el-tree 选中时的背景色设置 */
::v-deep(.el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content) { ::v-deep(.el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content) {
background-color: #edf6ff !important; background-color: #edf6ff !important;
} }
...@@ -241,8 +249,7 @@ export default { ...@@ -241,8 +249,7 @@ export default {
padding-right: 10px; padding-right: 10px;
} }
.col { .el-col {
height: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
transition: all .3s; transition: all .3s;
...@@ -260,6 +267,7 @@ export default { ...@@ -260,6 +267,7 @@ export default {
font-size: 12px; font-size: 12px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5); box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
background-color: white; background-color: white;
z-index: 2;
} }
.content { .content {
...@@ -277,19 +285,21 @@ export default { ...@@ -277,19 +285,21 @@ export default {
.scroll { .scroll {
flex: 1; flex: 1;
overflow-y: scroll; overflow-y: scroll;
display: flex;
flex-direction: column;
justify-content: space-between;
padding-bottom: 20px;
&::-webkit-scrollbar { /* 灰色滚动条背景 */
width: 0; &::-webkit-scrollbar-track {
background-color: transparent;
} }
/* &::-webkit-scrollbar {
width: 0;
} */
} }
// 向左折叠的箭头 /* 向左折叠的箭头 */
.arrow { .arrow {
right: 7.5px; right: -5px;
} }
& { & {
...@@ -299,7 +309,7 @@ export default { ...@@ -299,7 +309,7 @@ export default {
} }
::v-deep .el-input__suffix:last-of-type{ ::v-deep(.el-input__suffix:last-of-type) {
padding-right: 10px; padding-right: 10px;
} }
......
...@@ -41,7 +41,6 @@ function addIframe() { ...@@ -41,7 +41,6 @@ function addIframe() {
.app-main { .app-main {
/* 50= navbar 50 */ /* 50= navbar 50 */
min-height: calc(100vh - 50px); min-height: calc(100vh - 50px);
padding: 20px;
width: 100%; width: 100%;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
......
...@@ -108,7 +108,7 @@ function setLayout() { ...@@ -108,7 +108,7 @@ function setLayout() {
// 开启头部固定以后,main的高度需要设置为100vh // 开启头部固定以后,main的高度需要设置为100vh
.fixed-header+.app-main { .fixed-header+.app-main {
min-height: 100vh; min-height: 100vh;
padding-top: 50px + 20px; padding-top: 50px;
} }
...@@ -121,7 +121,7 @@ function setLayout() { ...@@ -121,7 +121,7 @@ function setLayout() {
} }
.fixed-header+.app-main { .fixed-header+.app-main {
padding-top: 84px + 20px; padding-top: 84px;
} }
} }
...@@ -137,4 +137,33 @@ function setLayout() { ...@@ -137,4 +137,33 @@ function setLayout() {
.mobile .fixed-header { .mobile .fixed-header {
width: 100%; width: 100%;
} }
// 有些页面高度固定就是 100 vh - 头部高度作为可视区域
// 例如:小 BI 分析中的商品管理页面,中间可用区域固定高度,不能撑开整个网页滚动
// 所以要动态计算高度
::v-deep() {
// 无头部固定,无头部 Tags-view
.client-fix-height {
// 头部导航 50,上下内边距 20
height: calc(100vh - 50px - 40px);
}
// 头部固定时
.fixed-header+.app-main {
.client-fix-height {
height: calc(100vh - 50px - 40px) !important;
}
}
// 有头部标签时
.hasTagsView {
.fixed-header+.app-main {
.client-fix-height {
height: calc(100vh - 50px - 34px - 40px) !important;
}
}
}
}
</style> </style>
\ No newline at end of file
...@@ -62,6 +62,7 @@ provide('activeName', activeName); ...@@ -62,6 +62,7 @@ provide('activeName', activeName);
flex-direction: column; flex-direction: column;
justify-content: space-around; justify-content: space-around;
width: 100%; width: 100%;
margin-top: 20px;
.chart{ .chart{
flex: 1; flex: 1;
......
<template> <template>
<div class="app-container"> <div class="app-container">
<el-row :gutter="20" <el-row :gutter="20"
class="row"> class="client-fix-height">
<!--商品分类--> <!--商品分类-->
<category-tree :options="seriesOptions" <category-tree :options="seriesOptions"
:defaultProps="defaultProps" :defaultProps="defaultProps"
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
@search="handleQuery" @search="handleQuery"
:colSpan="4"></category-tree> :colSpan="4"></category-tree>
<!--商品数据--> <!--商品数据-->
<el-col :span="18" <el-col :span="20"
:xs="24" :xs="24"
class="right_col"> class="right_col">
<el-form :model="queryParams" <el-form :model="queryParams"
...@@ -63,8 +63,7 @@ ...@@ -63,8 +63,7 @@
align="left" align="left"
key="prdCode" key="prdCode"
prop="prdCode" prop="prdCode"
v-if="columns[0].visible" v-if="columns[0].visible" />
width="150" />
<el-table-column label="商品名字" <el-table-column label="商品名字"
align="left" align="left"
key="prdName" key="prdName"
...@@ -76,20 +75,17 @@ ...@@ -76,20 +75,17 @@
key="series" key="series"
prop="series" prop="series"
v-if="columns[2].visible" v-if="columns[2].visible"
:show-overflow-tooltip="true" :show-overflow-tooltip="true" />
width="150" />
<el-table-column label="条码" <el-table-column label="条码"
align="left" align="left"
key="prdSpec" key="prdSpec"
prop="prdSpec" prop="prdSpec"
v-if="columns[3].visible" v-if="columns[3].visible"
:show-overflow-tooltip="true" :show-overflow-tooltip="true" />
width="180" />
<el-table-column label="售卖状态" <el-table-column label="售卖状态"
align="center" align="center"
key="saleStatus" key="saleStatus"
v-if="columns[4].visible" v-if="columns[4].visible">
width="80">
<template v-slot="scope"> <template v-slot="scope">
<el-switch v-model="scope.row.saleStatus" <el-switch v-model="scope.row.saleStatus"
active-value="1" active-value="1"
...@@ -99,18 +95,16 @@ ...@@ -99,18 +95,16 @@
</el-table-column> </el-table-column>
<el-table-column label="操作" <el-table-column label="操作"
align="center" align="center"
width="160"
class-name="small-padding fixed-width" class-name="small-padding fixed-width"
v-if="columns[5].visible"> v-if="columns[5].visible">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button size="mini" <el-button icon="el-icon-edit">修改</el-button>
type="text"
icon="el-icon-edit">修改</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<pagination v-show="total > 0" <pagination class="pagination"
v-show="total > 0"
:total="total" :total="total"
v-model:page="queryParams.pageNum" v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize" v-model:limit="queryParams.pageSize"
...@@ -182,7 +176,34 @@ getProductList() ...@@ -182,7 +176,34 @@ getProductList()
<style scoped <style scoped
lang="scss"> lang="scss">
::v-deep .row { .app-container {
>.el-row {
/* flex: 1; */
display: flex;
padding: 20px;
background-color: var(--el-bg-color-overlay);
.right_col {
flex: 1 !important;
transition: all .5s;
display: flex;
flex-direction: column;
height: 100%;
.pagination {
/* 没办法设置某个子元素单独在主轴排列方式,使用此方式可以 */
margin-top: auto;
}
&.el-col-20 {
width: 83.33333333%;
max-width: none;
}
}
}
}
/* ::v-deep .row {
height: 100%; height: 100%;
display: flex; display: flex;
...@@ -195,5 +216,5 @@ getProductList() ...@@ -195,5 +216,5 @@ getProductList()
} }
} }
} } */
</style> </style>
\ No newline at end of file
...@@ -608,9 +608,9 @@ init() ...@@ -608,9 +608,9 @@ init()
/* 套表 */ /* 套表 */
.excel_charts_item { .excel_charts_item {
background-color: var(--el-bg-color-overlay); background-color: var(--el-bg-color-overlay);
padding: 20px;
margin-top: 20px; margin-top: 20px;
width: 100%; width: 100%;
padding: 20px;
/* 图容器 */ /* 图容器 */
.echarts_wrap { .echarts_wrap {
...@@ -637,9 +637,6 @@ init() ...@@ -637,9 +637,6 @@ init()
margin-top: 0; margin-top: 0;
} }
.el-form-item {
margin-bottom: 0;
}
} }
/* 新增套表 */ /* 新增套表 */
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论