Commit b70b0db0 by 潘际乾

首页小组件

parent 5745c00b
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -7,6 +7,12 @@ const UserContext={ ...@@ -7,6 +7,12 @@ const UserContext={
menu:[], menu:[],
state:"LOGOUT", state:"LOGOUT",
token:"", token:"",
homeCellsSetting: {
defaultCells: [],
cellRows: 0,
cellCols: 0,
cellNames: []
}
}, },
mutations:{ mutations:{
setLoginInfo(state,info){ setLoginInfo(state,info){
...@@ -30,6 +36,15 @@ const UserContext={ ...@@ -30,6 +36,15 @@ const UserContext={
}, },
setMenu(state, menu) { setMenu(state, menu) {
state.menu = menu; state.menu = menu;
},
setHomeCellsSetting(state, setting) {
state.homeCellsSetting.cellRows = setting.cellRows
state.homeCellsSetting.cellCols = setting.cellCols
state.homeCellsSetting.cellNames = setting.cellNames
localStorage.setItem(`cells-setting-${state.userId}`, JSON.stringify(setting));
},
setHomeDefaultCells(state, cells) {
state.homeCellsSetting.defaultCells = cells;
} }
} }
} }
......
<template> <template>
<div class="home-cell" id="customerAnalyse"> <CellWrapper title="大客户分析" :cellContentHeight="cellContentHeight">
<CellHeaderVue title="大客户分析"> <template v-slot:header>
<span class="el-icon-refresh" title="刷新"></span> <span class="el-icon-refresh" title="刷新"></span>
<span class="el-icon-more" title="操作"></span> <span class="el-icon-more" title="操作"></span>
</CellHeaderVue> </template>
<div class="cell-content">
<div class="chart-container">
<div class="chart-operate"> <div class="chart-operate">
<i class="el-icon-arrow-up"></i> <i class="el-icon-arrow-up"></i>
<i class="el-icon-arrow-down"></i> <i class="el-icon-arrow-down"></i>
</div> </div>
<div id="chartWrapper"> <div class="chartWrapper">
<div id="chart"></div> <div class="chart"></div>
</div>
</div> </div>
</div> </div>
</CellWrapper>
</template> </template>
<script> <script>
import CellHeaderVue from "./common/CellHeader.vue"; import CellWrapper from "../common/CellWrapper.vue";
import * as echarts from "echarts"; import * as echarts from "echarts";
export default { export default {
name: "CustomerAnalyse", name: "CustomerAnalyse",
components: { CellHeaderVue }, props: ["cellContentHeight"],
components: { CellWrapper },
data() { data() {
return { return {
echartInstance: null, echartInstance: null,
}; };
}, },
mounted() { mounted() {
this.echartInstance = echarts.init(document.getElementById("chart")); this.$nextTick(() => {
this.loadCharts() this.loadCharts();
this.loadChartsBind = this.loadCharts.bind(this) this.loadChartsBind = this.loadCharts.bind(this);
window.addEventListener('resize', this.loadChartsBind) window.addEventListener("resize", this.loadChartsBind);
});
}, },
methods: { methods: {
loadCharts() { loadCharts() {
this.echartInstance.clear() if (this.echartInstance) {
this.echartInstance.dispose();
}
this.echartInstance = echarts.init(
this.$el.querySelector(".chart-container .chartWrapper .chart")
);
const option = { const option = {
title: { title: {
// text: "Test Demo", // text: "Test Demo",
...@@ -93,32 +101,29 @@ export default { ...@@ -93,32 +101,29 @@ export default {
}, },
}, },
destroyed() { destroyed() {
window.removeEventListener('resize', this.loadChartsBind) window.removeEventListener("resize", this.loadChartsBind);
} },
}; };
</script> </script>
<style scoped> <style scoped>
#customerAnalyse .cell-content { .chart-container {
height: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
padding: 0 5px; padding: 0 5px;
} }
#customerAnalyse .cell-content .chart-operate { .chart-operate {
margin-left: 20px; margin-left: 20px;
height: 20px; height: 20px;
} }
#customerAnalyse .cell-content .chart-operate i { .chart-operate i {
cursor: pointer; cursor: pointer;
} }
#customerAnalyse .cell-content #chartWrapper { .chartWrapper {
/* width: 98%; */
/* height: calc(100% - 50px); */
/* height: 200px; */
/* margin: 0 auto; */
flex: 1; flex: 1;
} }
#customerAnalyse .cell-content #chartWrapper #chart { .chartWrapper .chart {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
......
<template> <template>
<div class="home-cell" id="hall"> <CellWrapper title="电子大厅" :cellContentHeight="cellContentHeight">
<CellHeaderVue title="电子大厅"> <template v-slot:header>
<span class="el-icon-refresh" title="刷新"></span> <span class="el-icon-refresh" title="刷新"></span>
<span class="el-icon-more" title="操作"></span> <span class="el-icon-more" title="操作"></span>
</CellHeaderVue> </template>
<div class="cell-content">
<div class="card-wrapper">
<div class="card-item" v-for="(item, idx) in itemList" :key="idx"> <div class="card-item" v-for="(item, idx) in itemList" :key="idx">
<div class="dept-name"> <div class="dept-name">
<div <div
...@@ -25,15 +26,16 @@ ...@@ -25,15 +26,16 @@
</div> </div>
</div> </div>
</div> </div>
</div> </CellWrapper>
</template> </template>
<script> <script>
import CellHeaderVue from "./common/CellHeader.vue"; import CellWrapper from "../common/CellWrapper.vue";
export default { export default {
name: "Hall", name: "Hall",
components: { CellHeaderVue }, props: ['cellContentHeight'],
components: { CellWrapper },
data() { data() {
return { return {
itemList: [ itemList: [
...@@ -64,15 +66,14 @@ export default { ...@@ -64,15 +66,14 @@ export default {
</script> </script>
<style scoped> <style scoped>
#hall .cell-content { .card-wrapper {
height: 100%;
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
}
#hall .cell-content {
justify-content: space-around; justify-content: space-around;
align-items: center; align-items: center;
} }
#hall .cell-content .card-item { .card-item {
width: 45%; width: 45%;
height: 45%; height: 45%;
background-color: #e6e8ef; background-color: #e6e8ef;
......
<template> <template>
<div class="home-cell" id="noticeAnnouncement"> <CellWrapper title="通知公告" :cellContentHeight="cellContentHeight">
<CellHeaderVue title="通知公告"> <template v-slot:header>
<span class="el-icon-refresh" title="刷新"></span> <span class="el-icon-refresh" title="刷新"></span>
<span class="el-icon-more" title="操作"></span> <span class="el-icon-more" title="操作"></span>
</CellHeaderVue> </template>
<el-scrollbar :style="{ height: cellScrollHeight + 'px' }"> <div class="notice-container">
<div class="cell-content"> <el-scrollbar style="height: 100%;">
<div class="notice-item" v-for="(item, idx) in noticeList" :key="idx"> <div class="notice-item" v-for="(item, idx) in noticeList" :key="idx">
<div class="notice-title" :class="{ active: idx === 0 }"> <div class="notice-title" :class="{ active: idx === 0 }">
<a :href="item.url" target="_blank" rel="noopener noreferrer"> <a :href="item.url" target="_blank" rel="noopener noreferrer">
...@@ -17,26 +17,22 @@ ...@@ -17,26 +17,22 @@
{{ item.date }} {{ item.date }}
</div> </div>
</div> </div>
</div>
</el-scrollbar> </el-scrollbar>
</div> </div>
</CellWrapper>
</template> </template>
<script> <script>
import CellHeaderVue from "./common/CellHeader.vue"; import CellWrapper from "../common/CellWrapper.vue";
export default { export default {
name: "NoticeAnnouncement", name: "NoticeAnnouncement",
components: { CellHeaderVue }, props: ['cellContentHeight'],
props: { components: { CellWrapper },
cellScrollHeight: {
type: Number,
required: true,
},
},
data() { data() {
return { return {
noticeList: [ noticeList: [],
testData: [
{ {
title: "中国国际货物和服务贸易数据(BPM6,2015年以后)", title: "中国国际货物和服务贸易数据(BPM6,2015年以后)",
url: "https://www.safe.gov.cn/safe/2018/0427/8886.html", url: "https://www.safe.gov.cn/safe/2018/0427/8886.html",
...@@ -102,40 +98,67 @@ export default { ...@@ -102,40 +98,67 @@ export default {
url: "https://www.safe.gov.cn/safe/2021/0720/19437.html", url: "https://www.safe.gov.cn/safe/2021/0720/19437.html",
date: "2021-07-20", date: "2021-07-20",
}, },
{
title: "现行有效外汇管理主要法规目录(截至2021年6月30日)...",
url: "https://www.safe.gov.cn/safe/2021/0720/19437.html",
date: "2021-07-20",
},
{
title: "现行有效外汇管理主要法规目录(截至2021年6月30日)...",
url: "https://www.safe.gov.cn/safe/2021/0720/19437.html",
date: "2021-07-20",
},
{
title: "现行有效外汇管理主要法规目录(截至2021年6月30日)...",
url: "https://www.safe.gov.cn/safe/2021/0720/19437.html",
date: "2021-07-20",
},
], ],
}; };
}, },
mounted() {
this.$nextTick(() => {
this.loadNoticeData();
});
},
methods: {
loadNoticeData() {
// 查询加载数据
this.noticeList = this.testData;
},
},
}; };
</script> </script>
<style scoped> <style scoped>
/* 通知公告 */ .notice-container {
#noticeAnnouncement .cell-content { height: 100%;
margin: 0 20px; margin: 0 20px;
box-sizing: border-box;
} }
#noticeAnnouncement .cell-content .notice-item { .notice-item {
width: 100%; width: 100%;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
margin-bottom: 5px; margin-bottom: 5px;
font-size: 15px; font-size: 15px;
} }
#noticeAnnouncement .cell-content .notice-item .notice-title { .notice-item .notice-title {
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
max-width: 75%; max-width: 75%;
} }
#noticeAnnouncement .cell-content .notice-item .notice-title a { .notice-item .notice-title a {
color: #4e4e4e; color: #4e4e4e;
text-decoration: none; text-decoration: none;
} }
#noticeAnnouncement .cell-content .notice-item .notice-title::before { .notice-item .notice-title::before {
content: ""; content: "";
display: inline-block; display: inline-block;
width: 8px; width: 8px;
} }
#noticeAnnouncement .cell-content .notice-item .notice-title.active::before { .notice-item .notice-title.active::before {
content: ""; content: "";
background: rgb(255, 0, 0); background: rgb(255, 0, 0);
display: inline-block; display: inline-block;
...@@ -146,7 +169,7 @@ export default { ...@@ -146,7 +169,7 @@ export default {
margin-right: 2px; margin-right: 2px;
margin-bottom: 2px; margin-bottom: 2px;
} }
#noticeAnnouncement .cell-content .notice-item .notice-date { .notice-item .notice-date {
/* width: 20%; */ /* width: 20%; */
margin-right: 6px; margin-right: 6px;
} }
......
<template> <template>
<div class="home-cell" id="quickSearch"> <CellWrapper title="快速查询" :cellContentHeight="cellContentHeight">
<CellHeaderVue title="快速查询"> <template v-slot:header>
<span class="el-icon-setting" title="设置" @click="openSetting"></span> <span class="el-icon-setting" title="设置" @click="openSetting"></span>
</CellHeaderVue> </template>
<quick <quick
ref="quick" ref="quick"
:cellScrollHeight="cellScrollHeight"
quickType="search" quickType="search"
:cellContentHeight="cellContentHeight"
></quick> ></quick>
</div> </CellWrapper>
</template> </template>
<script> <script>
import CellHeaderVue from "./common/CellHeader.vue"; import CellWrapper from "../common/CellWrapper.vue";
import quick from "./common/quick.vue"; import quick from "../common/quick.vue";
import defaultQuickSearchItems from "./common/defaultQuickSearchItems.js"; import defaultQuickSearchItems from "../common/defaultQuickSearchItems.js";
export default { export default {
name: "QuickSearch", name: "QuickSearch",
components: { CellHeaderVue, quick }, components: { CellWrapper, quick },
props: { props: {
cellScrollHeight: { cellContentHeight: {
type: Number, type: Number,
required: true, required: true,
}, },
......
<template> <template>
<div class="home-cell" id="quickVisit"> <CellWrapper title="快速访问" :cellContentHeight="cellContentHeight">
<CellHeaderVue title="快速访问"> <template v-slot:header>
<span class="el-icon-setting" title="设置" @click="openSetting"></span> <span class="el-icon-setting" title="设置" @click="openSetting"></span>
</CellHeaderVue> </template>
<quick <quick
ref="quick" ref="quick"
:cellScrollHeight="cellScrollHeight"
quickType="visit" quickType="visit"
:cellContentHeight="cellContentHeight"
></quick> ></quick>
</div> </CellWrapper>
</template> </template>
<script> <script>
import CellHeaderVue from "./common/CellHeader.vue"; import CellWrapper from "../common/CellWrapper.vue";
import quick from "./common/quick.vue"; import quick from "../common/quick.vue";
import defaultVisitItems from "./common/defaultQuickVisitItems.js"; import defaultVisitItems from "../common/defaultQuickVisitItems.js";
export default { export default {
name: "QuickVisit", name: "QuickVisit",
components: { CellHeaderVue, quick }, components: { CellWrapper, quick },
props: { props: {
cellScrollHeight: { cellContentHeight: {
type: Number, type: Number,
required: true, required: true,
}, },
......
<template> <template>
<div class="home-cell"> <CellWrapper title="任务统计" :cellContentHeight="cellContentHeight">
<CellHeaderVue title="任务统计"> <template v-slot:header>
<span class="el-icon-refresh" title="刷新"></span> <span class="el-icon-refresh" title="刷新"></span>
<span class="el-icon-more" title="操作"></span> <span class="el-icon-more" title="操作"></span>
</CellHeaderVue> </template>
<div class="cell-content">
<div class="statistics-container">
<div class="task-stat-display total"> <div class="task-stat-display total">
<div class="display-wrapper"> <div class="display-wrapper">
<div <div
...@@ -43,16 +44,17 @@ ...@@ -43,16 +44,17 @@
</div> </div>
</div> </div>
</div> </div>
</div> </CellWrapper>
</template> </template>
<script> <script>
import CellHeaderVue from "./common/CellHeader.vue"; import CellWrapper from "../common/CellWrapper.vue";
import { all } from "~/service/report"; import { all } from "~/service/report";
export default { export default {
name: "TaskStatistics", name: "TaskStatistics",
components: { CellHeaderVue }, props: ["cellContentHeight"],
components: { CellWrapper },
data() { data() {
return { return {
total: [ total: [
...@@ -84,20 +86,21 @@ export default { ...@@ -84,20 +86,21 @@ export default {
}; };
}, },
created() { created() {
all().then(res => { all().then((res) => {
console.log(res); console.log(res);
}) });
} },
}; };
</script> </script>
<style scoped> <style scoped>
.cell-content { .statistics-container {
height: 100%;
padding: 0px 8px; padding: 0px 8px;
} }
.task-stat-display { .task-stat-display {
height: 25%; height: 25%;
max-height: 90px; /* max-height: 90px; */
display: flex; display: flex;
justify-content: space-around; justify-content: space-around;
color: #f3f3f3; color: #f3f3f3;
...@@ -176,7 +179,7 @@ export default { ...@@ -176,7 +179,7 @@ export default {
border-right: 0; border-right: 0;
} }
.task-sign { .task-sign {
height: 12%; height: 12.5%;
display: flex; display: flex;
align-items: center; align-items: center;
padding-left: 15px; padding-left: 15px;
......
...@@ -9,12 +9,7 @@ ...@@ -9,12 +9,7 @@
<script> <script>
export default { export default {
props: { props: ['title'],
title: {
type: String,
required: true,
},
},
}; };
</script> </script>
......
<template>
<div class="home-cell">
<CellHeader :title="title">
<slot name="header"></slot>
</CellHeader>
<div class="cell-content" :style="{ height: cellContentHeight + 'px' }">
<slot></slot>
</div>
</div>
</template>
<script>
import CellHeader from "./CellHeader.vue";
export default {
name: "CellWrapper",
components: { CellHeader },
props: {
title: {
type: String,
required: true,
},
cellContentHeight: {
type: Number,
required: true,
},
},
data() {
return {};
},
};
</script>
<style scoped>
.home-cell {
background-color: #ffffff;
box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
border-radius: 8px;
padding-bottom: 10px;
}
.home-cell::before {
display: table;
content: "";
}
.home-cell >>> .el-scrollbar__wrap {
overflow-y: scroll;
overflow-x: auto;
}
</style>
\ No newline at end of file
<template> <template>
<el-scrollbar :style="{ height: cellScrollHeight + 'px' }"> <el-scrollbar style="height: 100%">
<div class="cell-content">
<router-link <router-link
v-for="(item, index) in quickVisitItem" v-for="(item, index) in quickVisitItem"
:key="index" :key="index"
...@@ -8,7 +7,7 @@ ...@@ -8,7 +7,7 @@
> >
<div <div
class="content-wrapper" class="content-wrapper"
:style="{ height: Math.floor(cellScrollHeight * 0.3) + 'px' }" :style="{ height: Math.floor(cellContentHeight * 0.33) + 'px' }"
> >
<div class="visit-item-wrapper"> <div class="visit-item-wrapper">
<div class="visit-item"> <div class="visit-item">
...@@ -18,9 +17,13 @@ ...@@ -18,9 +17,13 @@
</div> </div>
</div> </div>
</router-link> </router-link>
</div>
<el-dialog :visible="visible" title="设置" :before-close="handleClose"> <el-dialog
:visible="visible"
title="设置"
width="60%"
:before-close="handleClose"
>
<div style="text-align: center"> <div style="text-align: center">
<el-transfer <el-transfer
style="text-align: left; display: inline-block" style="text-align: left; display: inline-block"
...@@ -49,14 +52,14 @@ import icons from "./icons.js"; ...@@ -49,14 +52,14 @@ import icons from "./icons.js";
export default { export default {
props: { props: {
cellScrollHeight: {
type: Number,
required: true,
},
quickType: { quickType: {
type: String, type: String,
required: true, required: true,
} },
cellContentHeight: {
type: Number,
required: true,
},
}, },
data() { data() {
return { return {
...@@ -71,7 +74,7 @@ export default { ...@@ -71,7 +74,7 @@ export default {
this.$nextTick(() => { this.$nextTick(() => {
this.init(); this.init();
this.generateVisitItems(this.getCachedVisitItems()); this.generateVisitItems(this.getCachedVisitItems());
}) });
}, },
methods: { methods: {
init() { init() {
...@@ -79,27 +82,29 @@ export default { ...@@ -79,27 +82,29 @@ export default {
this.getAllAvailableItems(this.$store.state.UserContext.menu, arr); this.getAllAvailableItems(this.$store.state.UserContext.menu, arr);
this.allAvailableItems = arr; this.allAvailableItems = arr;
this.transferData = arr.map((item) => { this.transferData = arr.map((item) => {
const ps = item.path.split("/") const ps = item.path.split("/");
return { return {
key: item.path, key: item.path,
label: `${ps[ps.length - 1]} - ${item.name}` , label: `${ps[ps.length - 1]} - ${item.name}`,
}; };
}); });
}, },
getCachedVisitItems() { getCachedVisitItems() {
const userId = this.$store.state.UserContext.userId;
const data = localStorage.getItem( const data = localStorage.getItem(
`quick-${this.quickType}-${userId.toLowerCase() === "zl" ? "admin" : "normal"}` `quick-${this.quickType}-${this.getUserRole()}`
); );
return JSON.parse(data); return JSON.parse(data);
}, },
setCachedVisitItems(data) { setCachedVisitItems(data) {
const userId = this.$store.state.UserContext.userId;
localStorage.setItem( localStorage.setItem(
`quick-${this.quickType}-${userId.toLowerCase() === "zl" ? "admin" : "normal"}`, `quick-${this.quickType}-${this.getUserRole()}`,
JSON.stringify(data) JSON.stringify(data)
); );
}, },
getUserRole() {
const userId = this.$store.state.UserContext.userId;
return userId.toLowerCase() === "zl" ? "admin" : "normal";
},
generateVisitItems(keys) { generateVisitItems(keys) {
const res = []; const res = [];
for (let i = 0; i < keys.length; i++) { for (let i = 0; i < keys.length; i++) {
...@@ -144,50 +149,43 @@ export default { ...@@ -144,50 +149,43 @@ export default {
} }
}, },
}, },
} };
</script> </script>
<style scoped> <style scoped>
.cell-content {
/* display: flex;
flex-wrap: wrap; */
}
.content-wrapper { .content-wrapper {
display: inline-block; display: inline-block;
width: 33%; width: 33.33%;
/* height: 30%; */ /* height: 30%; */
} }
.cell-content .visit-item-wrapper { .visit-item-wrapper {
display: flex; display: flex;
height: 100%; height: 100%;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
.cell-content .visit-item { .visit-item {
/* padding-bottom: 16px; */ /* padding-bottom: 16px; */
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
cursor: pointer; cursor: pointer;
} }
.cell-content .visit-item i { .visit-item i {
color: #0088ff; color: #0088ff;
font-size: 36px; font-size: 36px;
} }
.cell-content .visit-item span { .visit-item span {
color: #303133; color: #303133;
font-size: 14px; font-size: 14px;
margin-top: 10px; margin-top: 10px;
} }
/* .cell-content .visit-item:hover i { .visit-item:hover span {
color: var(--themecolor);
} */
.cell-content .visit-item:hover span {
color: var(--themecolor); color: var(--themecolor);
} }
.el-scrollbar >>> .el-transfer-panel { .el-scrollbar >>> .el-transfer-panel {
width: 300px; width: 300px;
height: 600px; height: 400px;
} }
.el-scrollbar >>> .el-checkbox-group.el-transfer-panel__list { .el-scrollbar >>> .el-checkbox-group.el-transfer-panel__list {
height: 500px; height: 500px;
......
export const cellDataDefinition = [
{
title: "快速访问",
name: "QuickVisit",
description: "交易快速访问入口",
},
{
title: "任务统计",
name: "TaskStatistics",
description: "任务的数量统计",
},
{
title: "通知公告",
name: "NoticeAnnouncement",
description: "最新的通知公告",
},
{ title: "电子大厅", name: "Hall", description: "电子大厅" },
{
title: "大客户分析",
name: "CustomerAnalyse",
description: "客户数据分析",
},
{
title: "快速查询",
name: "QuickSearch",
description: "交易快速查询入口",
},
];
<template> <template>
<div class="eContainer-home"> <div class="eContainer-home">
<QuickVisitVue :cellScrollHeight="cellScrollHeight"></QuickVisitVue> <c-row
<TaskStatisticsVue></TaskStatisticsVue> :gutter="10"
<NoticeAnnouncementVue :cellScrollHeight="cellScrollHeight" ></NoticeAnnouncementVue> v-for="cRow in cellRows"
<HallVue></HallVue> :key="cRow"
<CustomerAnalyseVue></CustomerAnalyseVue> >
<QuickSearchVue :cellScrollHeight="cellScrollHeight"></QuickSearchVue> <c-col
:span="24 / cellCols"
v-for="cCol in cellCols"
:key="cCol"
>
<component
v-if="getComponentName([cRow - 1], [cCol - 1])"
v-bind:is="getComponentName([cRow - 1], [cCol - 1])"
:cellContentHeight="cellContentHeight"
></component>
</c-col>
</c-row>
</div> </div>
</template> </template>
<script> <script>
import QuickVisitVue from "./cells/QuickVisit.vue"; import { createNamespacedHelpers } from "vuex";
import TaskStatisticsVue from "./cells/TaskStatistics.vue"; const { mapState } = createNamespacedHelpers("UserContext");
import NoticeAnnouncementVue from "./cells/NoticeAnnouncement.vue";
import HallVue from "./cells/Hall.vue"; import QuickVisit from "./cells/QuickVisit.vue";
import CustomerAnalyseVue from "./cells/CustomerAnalyse.vue"; import TaskStatistics from "./cells/TaskStatistics.vue";
import QuickSearchVue from "./cells/QuickSearch.vue"; import NoticeAnnouncement from "./cells/NoticeAnnouncement.vue";
import Hall from "./cells/Hall.vue";
import CustomerAnalyse from "./cells/CustomerAnalyse.vue";
import QuickSearch from "./cells/QuickSearch.vue";
import { cellDataDefinition } from "./config";
export default { export default {
name: "Home", name: "Home",
components: { components: {
QuickVisitVue, QuickVisit,
TaskStatisticsVue, TaskStatistics,
NoticeAnnouncementVue, NoticeAnnouncement,
HallVue, Hall,
CustomerAnalyseVue, CustomerAnalyse,
QuickSearchVue, QuickSearch,
},
mounted() {
this.calcCellScrollHeight();
this.calcCellScrollHeightBind = this.calcCellScrollHeight.bind(this);
window.addEventListener("resize", this.calcCellScrollHeightBind);
}, },
data() { data() {
return { return {
cellScrollHeight: 0, cellContentHeight: 0,
}; };
}, },
created() {
this.loadCellData();
},
mounted() {
this.calcCellContentHeight();
this.calcCellContentHeightBind = this.calcCellContentHeight.bind(this);
window.addEventListener("resize", this.calcCellContentHeightBind);
},
computed: {
...mapState({
cellRows: (state) => state.homeCellsSetting.cellRows,
cellCols: (state) => state.homeCellsSetting.cellCols,
cellNames: (state) => state.homeCellsSetting.cellNames,
}),
},
watch: {
cellRows(newVal, oldVal) {
this.calcCellContentHeight()
},
},
methods: { methods: {
calcCellScrollHeight() { loadCellData() {
this.cellScrollHeight = this.$el.clientHeight * 0.49 - 52; this.$store.commit(
"UserContext/setHomeDefaultCells",
cellDataDefinition
);
let cellsSettingDefault = localStorage.getItem("cells-setting-default");
if (!cellsSettingDefault) {
const rows = 2;
const cols = 3;
localStorage.setItem(
"cells-setting-default",
JSON.stringify({
cellRows: rows,
cellCols: cols,
cellNames: this.generateRowColNames(
rows,
cols,
cellDataDefinition.map((definition) => definition.name)
),
})
);
}
let userCellsSetting = localStorage.getItem(
`cells-setting-${this.$store.state.UserContext.userId}`
);
if (!userCellsSetting) {
userCellsSetting = localStorage.getItem("cells-setting-default");
}
this.$store.commit(
"UserContext/setHomeCellsSetting",
JSON.parse(userCellsSetting)
);
},
generateRowColNames(rows, cols, cells) {
const rArr = [];
for (let i = 0; i < rows; i++) {
const cArr = [];
for (let j = 0; j < cols; j++) {
cArr.push(cells[i * cols + j]);
}
rArr.push(cArr);
}
return rArr;
},
getComponentName(rowIdx, colIdx) {
return this.cellNames[rowIdx] ? this.cellNames[rowIdx][colIdx] : null;
},
calcCellContentHeight() {
this.cellContentHeight = this.$el.clientHeight * this.getRowHeightPercent() - 52 - 10
},
getRowHeightPercent() {
// 每行预留 0.4% 的间距
return 1 / this.cellRows - 0.004 * this.cellRows;
}, },
}, },
destroyed() { destroyed() {
window.removeEventListener("resize", this.calcCellScrollHeightBind); window.removeEventListener("resize", this.calcCellContentHeightBind);
}, },
}; };
</script> </script>
...@@ -52,26 +134,7 @@ export default { ...@@ -52,26 +134,7 @@ export default {
.eContainer-home { .eContainer-home {
height: 100%; height: 100%;
display: flex; display: flex;
flex-wrap: wrap; flex-direction: column;
/* justify-content: space-around; */ justify-content: space-around;
align-items: center;
}
.home-cell {
width: 33%;
height: 49%;
margin-left: 0.166%;
margin-right: 0.166%;
background-color: #ffffff;
box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
border-radius: 8px;
}
.home-cell >>> .cell-content {
/* max-height: calc(100% - 52px); */
height: calc(100% - 52px);
overflow: auto;
}
.home-cell >>> .el-scrollbar__wrap {
overflow-y: scroll;
overflow-x: auto;
} }
</style> </style>
...@@ -42,6 +42,12 @@ ...@@ -42,6 +42,12 @@
>修改密码</el-button >修改密码</el-button
> >
<el-button <el-button
@click="showHomeCellSettingDialog"
size="small"
style="width:100%;margin-left:0px;margin-top:5px"
>首页组件</el-button
>
<el-button
@click="showLogoutDialog(false)" @click="showLogoutDialog(false)"
size="small" size="small"
style="width:100%;margin-left:0px;margin-top:5px" style="width:100%;margin-left:0px;margin-top:5px"
...@@ -117,6 +123,65 @@ ...@@ -117,6 +123,65 @@
</el-popover> </el-popover>
<span class="header-tool-item-text">会计日期: {{ accDate }}</span> <span class="header-tool-item-text">会计日期: {{ accDate }}</span>
</div> </div>
<el-dialog custom-class="homeSetting"
:visible="homeSettingDialog"
title="首页小组件设置"
width="60%"
:before-close="handleCloseHomeSettingDialog"
>
<div style="padding: 0 20px;">
<div class="clear">
<c-col :span="24" style="margin-bottom: 10px;">
选择行数:
<c-select v-model="homeSetting.rows" :clearable="false" @change="updateDisplayArr">
<el-option label="1" :value="1"></el-option>
<el-option label="2" :value="2"></el-option>
<el-option label="3" :value="3"></el-option>
</c-select>
</c-col>
<c-col :span="24" style="margin-bottom: 10px;">
选择列数:
<c-select v-model="homeSetting.cols" :clearable="false" @change="updateDisplayArr">
<el-option label="1" :value="1"></el-option>
<el-option label="2" :value="2"></el-option>
<el-option label="3" :value="3"></el-option>
<el-option label="4" :value="4"></el-option>
</c-select>
</c-col>
</div>
<div>
<div class="setting-grid-row" v-for="row in getCellRows()" :key="row">
<div class="setting-grid-col" v-for="col in getCellCols()" :key="col" :style="{ width: 100 / getCellCols() + '%', height: '50px'}">
<div class="cell-item">
<div>{{ homeSetting.displayArray[row - 1][col - 1].title ? '标题:' + homeSetting.displayArray[row - 1][col - 1].title : '' }}</div>
<div>{{ homeSetting.displayArray[row - 1][col - 1].description ? '描述:' + homeSetting.displayArray[row - 1][col - 1].description : '' }}</div>
</div>
<div class="cell-operate">
<el-dropdown trigger="click">
<span class="el-dropdown-link">
设置&nbsp;&nbsp;<i class="el-icon-edit"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
v-for="(item,idx) in $store.state.UserContext.homeCellsSetting.defaultCells"
:key="idx"
@click.native="setCell(row, col, item)"
>
{{ item.title }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</div>
</div>
</div>
<span slot="footer" class="dialog-footer">
<c-button @click="cancelHomeSetting">取消</c-button>
<c-button type="primary" @click="saveHomeSetting">保存</c-button>
</span>
</el-dialog>
</div> </div>
</template> </template>
...@@ -152,6 +217,12 @@ export default { ...@@ -152,6 +217,12 @@ export default {
{ lang: "th", shortName: "ไทย", fullName: "ภาษาไทย" }, { lang: "th", shortName: "ไทย", fullName: "ภาษาไทย" },
{ lang: "vi", shortName: "Tiếng Việt", fullName: "Tiếng Việt" }, { lang: "vi", shortName: "Tiếng Việt", fullName: "Tiếng Việt" },
], ],
homeSettingDialog: false,
homeSetting: {
rows: null,
cols: null,
displayArray: []
}
}; };
}, },
computed: { computed: {
...@@ -198,6 +269,68 @@ export default { ...@@ -198,6 +269,68 @@ export default {
showChgPwdDialog() { showChgPwdDialog() {
this.$refs["chgPwdForm"].dialogOpen = true; this.$refs["chgPwdForm"].dialogOpen = true;
}, },
showHomeCellSettingDialog() {
this.homeSettingDialog = true;
this.homeSetting.rows = this.$store.state.UserContext.homeCellsSetting.cellRows
this.homeSetting.cols = this.$store.state.UserContext.homeCellsSetting.cellCols
this.homeSetting.displayArray = this.$store.state.UserContext.homeCellsSetting.cellNames.map(cellNameRows => {
return cellNameRows.map(cellName => {
return Object.assign({}, this.$store.state.UserContext.homeCellsSetting.defaultCells.find(cell => cell.name === cellName))
})
})
},
saveHomeSetting() {
if (!this.homeSetting.rows || !this.homeSetting.cols) {
this.$message.warning('请选择正确的行列数!')
return
}
const cellNames = this.homeSetting.displayArray.map(row => {
return row.map(col => col.name)
})
if (cellNames.some(row => row.some(cellName => !cellName))) {
this.$message.warning('请配置全部的格子组件!')
return
}
this.$store.commit('UserContext/setHomeCellsSetting', {
cellRows: this.homeSetting.rows,
cellCols: this.homeSetting.cols,
cellNames: cellNames
})
this.homeSettingDialog = false;
},
cancelHomeSetting() {
this.homeSettingDialog = false;
},
handleCloseHomeSettingDialog(done) {
this.homeSettingDialog = false;
done();
},
getCellRows() {
return this.homeSetting.rows ? this.homeSetting.rows : this.homeSetting.cols ? 1 : 0
},
getCellCols() {
return this.homeSetting.cols ? this.homeSetting.cols : this.homeSetting.rows ? 1 : 0
},
updateDisplayArr() {
const rArr = []
for (let i = 0; i < this.getCellRows(); i++) {
const cArr = []
for (let j = 0; j < this.getCellCols(); j++) {
cArr.push({
title: null,
name: null,
description: null
})
}
rArr.push(cArr)
}
this.homeSetting.displayArray = rArr
},
setCell(row, col, item) {
this.homeSetting.displayArray[row - 1][col - 1].title = item.title
this.homeSetting.displayArray[row - 1][col - 1].name = item.name
this.homeSetting.displayArray[row - 1][col - 1].description = item.description
}
}, },
}; };
</script> </script>
...@@ -334,4 +467,38 @@ export default { ...@@ -334,4 +467,38 @@ export default {
.long-text:hover { .long-text:hover {
background-color: #e8f0fe; background-color: #e8f0fe;
} }
/* 首页设置框 */
.homeSetting .setting-grid-row {
width: 100%;
display: flex;
border-bottom: 1px solid #ebebeb;
}
.homeSetting .setting-grid-row:nth-of-type(1) {
border-top: 1px solid #ebebeb;
}
.homeSetting .setting-grid-col {
display: flex;
border-right: 1px solid #ebebeb;
}
.homeSetting .setting-grid-row .setting-grid-col:nth-of-type(1) {
border-left: 1px solid #ebebeb;
}
.homeSetting .setting-grid-col .cell-item {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
margin-left: 15px;
}
.homeSetting .setting-grid-col .cell-operate {
font-size: 24px;
margin: 0 10px;
display: flex;
justify-content: center;
align-items: center;
}
.homeSetting .setting-grid-col .cell-operate .el-dropdown-link {
cursor: pointer;
color: #409EFF;
}
</style> </style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment