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

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

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