Compare commits

..

No commits in common. 'main' and 'branch4' have entirely different histories.

File diff suppressed because it is too large Load Diff

@ -1,166 +1,167 @@
@charset "utf-8"; @charset "utf-8";
* { * {
box-sizing: border-box; /* 设置所有元素的盒子模型为border-box */ box-sizing: border-box;
} }
#app-menu ul { #app-menu ul {
padding: 0; /* 移除列表的默认内边距 */ padding: 0;
} }
#app-menu li { #app-menu li {
list-style: none; /* 移除列表项的默认样式 */ list-style: none;
} }
#app-menu { #app-menu {
overflow: hidden; /* 隐藏溢出的内容 */ overflow: hidden;
width: 100%; /* 设置宽度为100% */ width: 100%;
} }
.weixin-preview { .weixin-preview {
position: relative; /* 相对定位 */ position: relative;
width: 320px; /* 设置宽度 */ width: 320px;
height: 540px; /* 设置高度 */ height: 540px;
float: left; /* 左浮动 */ float: left;
margin-right: 10px; /* 右边距 */ margin-right: 10px;
border: 1px solid #e7e7eb; /* 边框颜色和宽度 */ border: 1px solid #e7e7eb;
} }
.weixin-preview a { .weixin-preview a {
text-decoration: none; /* 移除链接下划线 */ text-decoration: none;
color: #616161; /* 文字颜色 */ color: #616161;
} }
.weixin-preview .weixin-hd .weixin-title { .weixin-preview .weixin-hd .weixin-title {
color: #fff; /* 文字颜色 */ color: #fff;
font-size: 15px; /* 字体大小 */ font-size: 15px;
width: 100%; /* 宽度 */ width: 100%;
text-align: center; /* 文字居中对齐 */ text-align: center;
position: absolute; /* 绝对定位 */ position: absolute;
top: 33px; /* 顶部位置 */ top: 33px;
left: 0px; /* 左侧位置 */ left: 0px;
} }
.weixin-preview .weixin-header{ .weixin-preview .weixin-header{
text-align: center; /* 文字居中对齐 */ text-align: center;
padding: 10px 0; /* 上下内边距 */ padding: 10px 0;
background-color: #616161; /* 背景颜色 */ background-color: #616161;
color: #ffffff; /* 文字颜色 */ color: #ffffff;
} }
.weixin-preview .weixin-menu { .weixin-preview .weixin-menu {
position: absolute; /* 绝对定位 */ position: absolute;
bottom: 0; /* 底部位置 */ bottom: 0;
left: 0; /* 左侧位置 */ left: 0;
right: 0; /* 右侧位置 */ right: 0;
border-top: 1px solid #e7e7e7; /* 上边框颜色和宽度 */ border-top: 1px solid #e7e7e7;
background-position: 0 0; /* 背景图像位置 */ background-position: 0 0;
background-repeat: no-repeat; /* 背景图像不重复 */ background-repeat: no-repeat;
margin-bottom: 0px; /* 底部外边距 */ margin-bottom: 0px;
} }
/*一级*/ /*一级*/
.weixin-preview .weixin-menu .menu-item { .weixin-preview .weixin-menu .menu-item {
position: relative; /* 相对定位 */ position: relative;
float: left; /* 左浮动 */ float: left;
line-height: 50px; /* 行高 */ line-height: 50px;
height: 50px; /* 高度 */ height: 50px;
text-align: center; /* 文字居中对齐 */ text-align: center;
width: 33.33%; /* 宽度 */ width: 33.33%;
border-left: 1px solid #e7e7e7; /* 左边框颜色和宽度 */ border-left: 1px solid #e7e7e7;
cursor: pointer; /* 鼠标指针变为手型 */ cursor: pointer;
color: #616161; /* 文字颜色 */ color: #616161;
} }
/*二级*/ /*二级*/
.weixin-preview .weixin-sub-menu { .weixin-preview .weixin-sub-menu {
position: absolute; /* 绝对定位 */ position: absolute;
bottom: 60px; /* 底部位置 */ bottom: 60px;
left: 0; /* 左侧位置 */ left: 0;
right: 0; /* 右侧位置 */ right: 0;
border-top: 1px solid #d0d0d0; /* 上边框颜色和宽度 */ border-top: 1px solid #d0d0d0;
margin-bottom: 0px; /* 底部外边距 */ margin-bottom: 0px;
background: #fafafa; /* 背景颜色 */ background: #fafafa;
display: block; /* 块级显示 */ display: block;
padding: 0; /* 内边距 */ padding: 0;
} }
.weixin-preview .weixin-sub-menu .menu-sub-item { .weixin-preview .weixin-sub-menu .menu-sub-item {
line-height: 50px; /* 行高 */ line-height: 50px;
height: 50px; /* 高度 */ height: 50px;
text-align: center; /* 文字居中对齐 */ text-align: center;
width: 100%; /* 宽度 */ width: 100%;
border: 1px solid #d0d0d0; /* 边框颜色和宽度 */ border: 1px solid #d0d0d0;
border-top-width: 0px; /* 顶部边框宽度 */ border-top-width: 0px;
cursor: pointer; /* 鼠标指针变为手型 */ cursor: pointer;
position: relative; /* 相对定位 */ position: relative;
color: #616161; /* 文字颜色 */ color: #616161;
} }
.weixin-preview .weixin-sub-menu .menu-sub-item.on-drag-over{ .weixin-preview .weixin-sub-menu .menu-sub-item.on-drag-over{
border-top: 2px solid #44b549; /* 顶部边框颜色和宽度 */ border-top: 2px solid #44b549;
} }
.weixin-preview .menu-arrow { .weixin-preview .menu-arrow {
position: absolute; /* 绝对定位 */ position: absolute;
left: 50%; /* 左侧位置 */ left: 50%;
margin-left: -6px; /* 左边距调整 */ margin-left: -6px;
} }
.weixin-preview .arrow_in { .weixin-preview .arrow_in {
bottom: -4px; /* 底部位置 */ bottom: -4px;
display: inline-block; /* 行内块级显示 */ display: inline-block;
width: 0px; /* 宽度 */ width: 0px;
height: 0px; /* 高度 */ height: 0px;
border-width: 6px 6px 0px; /* 边框宽度 */ border-width: 6px 6px 0px;
border-style: solid dashed dashed; /* 边框样式 */ border-style: solid dashed dashed;
border-color: #fafafa transparent transparent; /* 边框颜色 */ border-color: #fafafa transparent transparent;
} }
.weixin-preview .arrow_out { .weixin-preview .arrow_out {
bottom: -5px; /* 底部位置 */ bottom: -5px;
display: inline-block; /* 行内块级显示 */ display: inline-block;
width: 0px; /* 宽度 */ width: 0px;
height: 0px; /* 高度 */ height: 0px;
border-width: 6px 6px 0px; /* 边框宽度 */ border-width: 6px 6px 0px;
border-style: solid dashed dashed; /* 边框样式 */ border-style: solid dashed dashed;
border-color: #d0d0d0 transparent transparent; /* 边框颜色 */ border-color: #d0d0d0 transparent transparent;
} }
.weixin-preview .menu-item .menu-item-title, .weixin-preview .menu-sub-item .menu-item-title { .weixin-preview .menu-item .menu-item-title, .weixin-preview .menu-sub-item .menu-item-title {
width: 100%; /* 宽度 */ width: 100%;
overflow: hidden; /* 内容溢出时隐藏 */ overflow: hidden;
white-space: nowrap; /* 不换行 */ white-space: nowrap;
text-overflow: ellipsis; /* 文本溢出时显示省略号 */ text-overflow: ellipsis;
box-sizing: border-box; /* 盒子模型为border-box */ box-sizing: border-box;
} }
.weixin-preview .menu-item.current, .weixin-preview .menu-sub-item.current { .weixin-preview .menu-item.current, .weixin-preview .menu-sub-item.current {
border: 1px solid #44b549; /* 边框颜色和宽度 */ border: 1px solid #44b549;
background: #fff; /* 背景颜色 */ background: #fff;
color: #44b549; /* 文字颜色 */ color: #44b549;
} }
.weixin-preview .weixin-sub-menu.show { .weixin-preview .weixin-sub-menu.show {
display: block; /* 块级显示 */ display: block;
} }
.weixin-preview .icon_menu_dot { .weixin-preview .icon_menu_dot {
/* background: url(../images/index_z354723.png) 0px -36px no-repeat; */ /* background: url(../images/index_z354723.png) 0px -36px no-repeat; */
width: 7px; /* 宽度 */ width: 7px;
height: 7px; /* 高度 */ height: 7px;
vertical-align: middle; /* 垂直居中对齐 */ vertical-align: middle;
display: inline-block; /* 行内块级显示 */ display: inline-block;
margin-right: 2px; /* 右边距 */ margin-right: 2px;
margin-top: -2px; /* 顶部外边距调整 */ margin-top: -2px;
} }
.weixin-preview .icon14_menu_add { .weixin-preview .icon14_menu_add {
/* background: url(../images/index_z354723.png) 0px 0px no-repeat; */ /* background: url(../images/index_z354723.png) 0px 0px no-repeat; */
width: 14px; /* 宽度 */ width: 14px;
height: 14px; /* 高度 */ height: 14px;
vertical-align: middle; /* 垂直居中对齐 */ vertical-align: middle;
display: inline-block; /* 行内块级显示 */ display: inline-block;
margin-top: -2px; /* 顶部外边距调整 */ margin-top: -2px;
} }
.weixin-preview li:hover .icon14_menu_add { .weixin-preview li:hover .icon14_menu_add {
@ -168,197 +169,197 @@
} }
.weixin-preview .menu-item:hover { .weixin-preview .menu-item:hover {
color: #000; /* 文字颜色 */ color: #000;
} }
.weixin-preview .menu-sub-item:hover { .weixin-preview .menu-sub-item:hover {
background: #eee; /* 背景颜色 */ background: #eee;
} }
.weixin-preview li.current:hover { .weixin-preview li.current:hover {
background: #fff; /* 背景颜色 */ background: #fff;
color: #44b549; /* 文字颜色 */ color: #44b549;
} }
/*菜单内容*/ /*菜单内容*/
.weixin-menu-detail { .weixin-menu-detail {
width: 600px; /* 宽度 */ width: 600px;
padding: 0px 20px 5px; /* 内边距 */ padding: 0px 20px 5px;
background-color: #f4f5f9; /* 背景颜色 */ background-color: #f4f5f9;
border: 1px solid #e7e7eb; /* 边框颜色和宽度 */ border: 1px solid #e7e7eb;
float: left; /* 左浮动 */ float: left;
min-height: 540px; /* 最小高度 */ min-height: 540px;
} }
.weixin-menu-detail .menu-name { .weixin-menu-detail .menu-name {
float: left; /* 左浮动 */ float: left;
height: 40px; /* 高度 */ height: 40px;
line-height: 40px; /* 行高 */ line-height: 40px;
font-size: 18px; /* 字体大小 */ font-size: 18px;
} }
.weixin-menu-detail .menu-del { .weixin-menu-detail .menu-del {
float: right; /* 右浮动 */ float: right;
height: 40px; /* 高度 */ height: 40px;
line-height: 40px; /* 行高 */ line-height: 40px;
color: #459ae9; /* 文字颜色 */ color: #459ae9;
cursor: pointer; /* 鼠标指针变为手型 */ cursor: pointer;
} }
.weixin-menu-detail .menu-input-group { .weixin-menu-detail .menu-input-group {
width: 540px; /* 宽度 */ width: 540px;
margin: 10px 0 30px 0; /* 外边距 */ margin: 10px 0 30px 0;
overflow: hidden; /* 隐藏溢出的内容 */ overflow: hidden;
} }
.weixin-menu-detail .menu-label { .weixin-menu-detail .menu-label {
float: left; /* 左浮动 */ float: left;
height: 30px; /* 高度 */ height: 30px;
line-height: 30px; /* 行高 */ line-height: 30px;
width: 80px; /* 宽度 */ width: 80px;
text-align: right; /* 文字右对齐 */ text-align: right;
} }
.weixin-menu-detail .menu-input { .weixin-menu-detail .menu-input {
float: left; /* 左浮动 */ float: left;
width: 380px; /* 宽度 */ width: 380px
} }
.weixin-menu-detail .menu-input-text { .weixin-menu-detail .menu-input-text {
border: 0px; /* 边框宽度 */ border: 0px;
outline: 0px; /* focus时的轮廓宽度 */ outline: 0px;
background: #fff; /* 背景颜色 */ background: #fff;
width: 300px; /* 宽度 */ width: 300px;
padding: 5px 0px 5px 0px; /* 内边距 */ padding: 5px 0px 5px 0px;
margin-left: 10px; /* 左边距 */ margin-left: 10px;
text-indent: 10px; /* text缩进 */ text-indent: 10px;
height: 35px; /* 高度 */ height: 35px;
} }
.weixin-menu-detail .menu-tips { .weixin-menu-detail .menu-tips {
color: #8d8d8d; /* 文字颜色 */ color: #8d8d8d;
padding-top: 4px; /* top方向的内边距 */ padding-top: 4px;
margin: 0; /* margin属性值设置为0 */ margin: 0;
} }
.weixin-menu-detail .menu-tips.cursor { .weixin-menu-detail .menu-tips.cursor {
color: #459ae9; /* 文字颜色 */ color: #459ae9;
cursor: pointer; /* mouse指针变为手型图标 */ cursor: pointer;
} }
.weixin-menu-detail .menu-input .menu-tips { .weixin-menu-detail .menu-input .menu-tips {
margin: 0 0 0 10px; /* margin属性值设置为0最后一个参数为10px */ margin: 0 0 0 10px;
} }
.weixin-menu-detail .menu-content { .weixin-menu-detail .menu-content {
padding: 16px 20px; /* Padding属性值设置为16px和20px */ padding: 16px 20px;
border: 1px solid #e7e7eb; /* Border属性值设置为1px和#e7e7eb颜色值 */ border: 1px solid #e7e7eb;
background-color: #fff; /* background-color属性值设置为白色 */ background-color: #fff;
} }
.weixin-menu-detail .menu-content .menu-input-group { .weixin-menu-detail .menu-content .menu-input-group {
margin: 0px 0 10px 0; /* margin属性值设置为0px,10px和0px */ margin: 0px 0 10px 0;
} }
.weixin-menu-detail .menu-content .menu-label { .weixin-menu-detail .menu-content .menu-label {
text-align: left; /* text对齐方式设置为左对齐 */ text-align: left;
width: 100px; /* width属性值设置为100px */ width: 100px;
} }
.weixin-menu-detail .menu-content .menu-input-text { .weixin-menu-detail .menu-content .menu-input-text {
border: 1px solid #e7e7eb; /* border属性值设置为1px和#e7e7eb颜色值 */ border: 1px solid #e7e7eb;
} }
.weixin-menu-detail .menu-content .menu-tips { .weixin-menu-detail .menu-content .menu-tips {
padding-bottom: 10px; /* bottom方向的内边距设置为10px */ padding-bottom: 10px;
} }
.weixin-menu-detail .menu-msg-content { .weixin-menu-detail .menu-msg-content {
padding: 0; /* Padding属性值设置为0 */ padding: 0;
border: 1px solid #e7e7eb; /* Border属性值设置为1px和#e7e7eb颜色值 */ border: 1px solid #e7e7eb;
background-color: #fff; /* background-color属性值设置为白色 */ background-color: #fff;
} }
.weixin-menu-detail .menu-msg-content .menu-msg-head { .weixin-menu-detail .menu-msg-content .menu-msg-head {
overflow: hidden; /* Overflow属性值设置为hidden */ overflow: hidden;
border-bottom: 1px solid #e7e7eb; /* Border属性值设置为1px和#e7e7eb颜色值 */ border-bottom: 1px solid #e7e7eb;
line-height: 38px; /* Line height属性值设置为38px */ line-height: 38px;
height: 38px; /* height属性值设置为38px */ height: 38px;
padding: 0 20px; /* Padding属性值设置为0和20px */ padding: 0 20px;
} }
.weixin-menu-detail .menu-msg-content .menu-msg-panel { .weixin-menu-detail .menu-msg-content .menu-msg-panel {
padding: 30px 50px; /* Padding属性值设置为30px和50px */ padding: 30px 50px;
} }
.weixin-menu-detail .menu-msg-content .menu-msg-select { .weixin-menu-detail .menu-msg-content .menu-msg-select {
padding: 40px 20px; /* Padding属性值设置为40px和20px */ padding: 40px 20px;
border: 2px dotted #d9dadc; /* Border属性值设置为2px虚线和#d9dadc颜色值 */ border: 2px dotted #d9dadc;
text-align: center; /* text对齐方式设置为居中对齐 */ text-align: center;
} }
.weixin-menu-detail .menu-msg-content .menu-msg-select:hover { .weixin-menu-detail .menu-msg-content .menu-msg-select:hover {
border-color: #b3b3b3; /* border颜色值设置为#b3b3b3 */ border-color: #b3b3b3;
} }
.weixin-menu-detail .menu-msg-content strong { .weixin-menu-detail .menu-msg-content strong {
display: block; /* Display属性值设置为block */ display: block;
padding-top: 3px; /* Top方向的内边距设置为3px */ padding-top: 3px;
font-weight: 400; /* font weight属性值设置为400 */ font-weight: 400;
font-style: normal; /* font style属性值设置为normal */ font-style: normal;
} }
.weixin-menu-detail .menu-msg-content .menu-msg-title { .weixin-menu-detail .menu-msg-content .menu-msg-title {
float: left; /* float属性值设置为left */ float: left;
width: 310px; /* width属性值设置为310px */ width: 310px;
height: 30px; /* height属性值设置为30px */ height: 30px;
line-height: 30px; /* line height属性值设置为30px */ line-height: 30px;
overflow: hidden; /* Overflow属性值设置为hidden */ overflow: hidden;
text-overflow: ellipsis; /* TextOverflow属性值设置为ellipsis */ text-overflow: ellipsis;
white-space: nowrap; /* WhiteSpace属性值设置为nowrap */ white-space: nowrap;
} }
.icon36_common { .icon36_common {
width: 36px; /* width属性值设置为36px */ width: 36px;
height: 36px; /* height属性值设置为36px */ height: 36px;
vertical-align: middle; /* vertical align属性值设置为middle */ vertical-align: middle;
display: inline-block; /* Display属性值设置为inline block */ display: inline-block;
} }
.icon_msg_sender { .icon_msg_sender {
margin-right: 3px; /* Right方向的外边距设置为3px */ margin-right: 3px;
margin-top: -2px; /* Top方向的外边距设置为负2px */ margin-top: -2px;
width: 20px; /* width属性值设置为20px */ width: 20px;
height: 20px; /* height属性值设置为20px */ height: 20px;
vertical-align: middle; /* vertical align属性值设置为middle */ vertical-align: middle;
display: inline-block; /* Display属性值设置为inline block */ display: inline-block;
/* background: url(../images/msg_tab_z25df2d.png) 0 -270px no-repeat; */ /* background: url(../images/msg_tab_z25df2d.png) 0 -270px no-repeat; */
} }
.weixin-btn-group { .weixin-btn-group {
text-align: center; /* text对齐方式设置为居中对齐 */ text-align: center;
width: 100%; /* width属性值设置为100% */ width: 100%;
margin: 30px 0px; /* margin属性值设置为30px和0px */ margin: 30px 0px;
overflow: hidden; /* Overflow属性值设置为hidden */ overflow: hidden;
} }
.weixin-btn-group .btn { .weixin-btn-group .btn {
width: 100px; /* width属性值设置为100px */ width: 100px;
border-radius: 0px; /* border radius属性值设置为0px */ border-radius: 0px;
} }
#material-list { #material-list {
padding: 20px; /* Padding属性值设置为20px */ padding: 20px;
overflow-y: scroll; /* Overflow y属性值设置为scroll使内容可滚动 */ overflow-y: scroll;
height: 558px; /* height属性值设置为558px */ height: 558px;
} }
#news-list { #news-list {
padding: 20px; /* Padding属性值设置为20px */ padding: 20px;
overflow-y: scroll; /* Overflow y属性值设置为scroll使内容可滚动 */ overflow-y: scroll;
height: 558px; /* height属性值设置为558px */ height: 558px;
} }
#material-list table { #material-list table {
width: 100%; /* width属性值设置为100% */ width: 100%;
} }

@ -1,11 +1,9 @@
/* 设置所有元素和伪元素的 box-sizing 为 border-box */
*, *,
*:before, *:before,
*:after { *:after {
box-sizing: border-box; box-sizing: border-box;
} }
/* 设置 body 的字体、大小、行高和颜色 */
body { body {
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif; font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
font-size: 14px; font-size: 14px;
@ -14,12 +12,10 @@ body {
background-color: #fff; background-color: #fff;
} }
/* 设置链接的颜色和文本装饰 */
a { a {
color: mix(#fff, $--color-primary, 20%); /* 使用混合色函数设置颜色 */ color: mix(#fff, $--color-primary, 20%);
text-decoration: none; /* 去掉下划线 */ text-decoration: none;
/* 当链接获得焦点或悬停时,改变颜色并添加下划线 */
&:focus, &:focus,
&:hover { &:hover {
color: $--color-primary; color: $--color-primary;
@ -27,104 +23,97 @@ a {
} }
} }
/* 设置图片垂直对齐方式为中间 */
img { img {
vertical-align: middle; vertical-align: middle;
} }
/* Utils /* Utils
------------------------------ */ ------------------------------ */
/* 清除浮动工具类 */
.clearfix:before, .clearfix:before,
.clearfix:after { .clearfix:after {
content: " "; /* 生成内容以触发 clearfix */ content: " ";
display: table; /* 设置为表格布局 */ display: table;
} }
.clearfix:after { .clearfix:after {
clear: both; /* 清除浮动 */ clear: both;
} }
/* Animation /* Animation
------------------------------ */ ------------------------------ */
/* 淡入淡出动画过渡效果 */
.fade-enter-active, .fade-enter-active,
.fade-leave-active { .fade-leave-active {
transition: opacity .5s; /* 设置透明度变化的过渡时间 */ transition: opacity .5s;
} }
.fade-enter, .fade-enter,
.fade-leave-to { .fade-leave-to {
opacity: 0; /* 初始透明度为 0 */ opacity: 0;
} }
/* Reset element-ui /* Reset element-ui
------------------------------ */ ------------------------------ */
/* 重置 element-ui 样式 */
.site-wrapper { .site-wrapper {
.el-pagination { .el-pagination {
margin-top: 15px; /* 设置分页组件的上边距 */ margin-top: 15px;
text-align: right; /* 设置分页组件的文本对齐方式 */ text-align: right;
} }
} }
/* Layout /* Layout
------------------------------ */ ------------------------------ */
/* 设置布局相关样式 */
.site-wrapper { .site-wrapper {
position: relative; /* 相对定位 */ position: relative;
min-width: 1180px; /* 最小宽度 */ min-width: 1180px;
} }
/* Sidebar fold /* Sidebar fold
------------------------------ */ ------------------------------ */
/* 侧边栏折叠样式 */
.site-sidebar--fold { .site-sidebar--fold {
/* 设置导航栏头部、品牌、侧边栏及其内部元素的宽度 */
.site-navbar__header, .site-navbar__header,
.site-navbar__brand, .site-navbar__brand,
.site-sidebar, .site-sidebar,
.site-sidebar__inner, .site-sidebar__inner,
.el-menu.site-sidebar__menu { .el-menu.site-sidebar__menu {
width: 64px; /* 宽度为 64px */ width: 64px;
} }
/* 设置导航栏主体和内容包装器的左边距 */
.site-navbar__body, .site-navbar__body,
.site-content__wrapper { .site-content__wrapper {
margin-left: 64px; /* 左边距为 64px */ margin-left: 64px;
} }
/* 设置品牌图标在不同状态下的显示方式 */
.site-navbar__brand { .site-navbar__brand {
&-lg { &-lg {
display: none; /* 大尺寸时隐藏 */ display: none;
} }
&-mini { &-mini {
display: inline-block; /* 小尺寸时内联显示 */ display: inline-block;
} }
} }
/* 设置侧边栏和其内部元素的溢出处理 */
.site-sidebar, .site-sidebar,
.site-sidebar__inner { .site-sidebar__inner {
overflow: initial; /* 初始溢出处理 */ overflow: initial;
} }
/* 设置侧边栏菜单图标的右边距和字体大小 */
.site-sidebar__menu-icon { .site-sidebar__menu-icon {
margin-right: 0; /* 右边距为 0 */ margin-right: 0;
font-size: 20px; /* 字体大小为 20px */ font-size: 20px;
} }
/* 设置标签页内容的左边距 */
.site-content--tabs > .el-tabs > .el-tabs__header { .site-content--tabs > .el-tabs > .el-tabs__header {
left: 64px; /* 左边距为 64px */ left: 64px;
} }
} }
//* animation */ // animation
.site-navbar__header, .site-navbar__header,
.site-navbar__brand, .site-navbar__brand,
.site-navbar__body, .site-navbar__body,
@ -134,154 +123,154 @@ img {
.site-sidebar__menu-icon, .site-sidebar__menu-icon,
.site-content__wrapper, .site-content__wrapper,
.site-content--tabs > .el-tabs .el-tabs__header { .site-content--tabs > .el-tabs .el-tabs__header {
//
transition: inline-block .3s, left .3s, width .3s, margin-left .3s, font-size .3s; transition: inline-block .3s, left .3s, width .3s, margin-left .3s, font-size .3s;
} }
/* Navbar */
/* Navbar
------------------------------ */
.site-navbar { .site-navbar {
//
position: fixed; position: fixed;
top: 0; top: 0;
right: 0; right: 0;
left: 0; left: 0;
z-index: 1030; // z-index: 1030;
height: 50px; // 50px height: 50px;
box-shadow: 0 2px 4px rgba(0, 0, 0, .08); // box-shadow: 0 2px 4px rgba(0, 0, 0, .08);
background-color: $navbar--background-color; // background-color: $navbar--background-color;
&--inverse { &--inverse {
.site-navbar__body { .site-navbar__body {
background-color: transparent; // background-color: transparent;
} }
.el-menu { .el-menu {
> .el-menu-item, > .el-menu-item,
> .el-submenu > .el-submenu__title { > .el-submenu > .el-submenu__title {
color: #fff; // color: #fff;
&:focus, &:focus,
&:hover { &:hover {
color: #fff; // color: #fff;
background-color: mix(#000, $navbar--background-color, 15%); // background-color: mix(#000, $navbar--background-color, 15%);
} }
} }
> .el-menu-item.is-active, > .el-menu-item.is-active,
> .el-submenu.is-active > .el-submenu__title { > .el-submenu.is-active > .el-submenu__title {
border-bottom-color: mix(#fff, $navbar--background-color, 85%); // border-bottom-color: mix(#fff, $navbar--background-color, 85%);
} }
.el-menu-item i, .el-menu-item i,
.el-submenu__title i, .el-submenu__title i,
.el-dropdown { .el-dropdown {
color: #fff; // color: #fff;
} }
} }
.el-menu--popup-bottom-start { .el-menu--popup-bottom-start {
background-color: $navbar--background-color; // background-color: $navbar--background-color;
} }
} }
&__header { &__header {
position: relative; // position: relative;
float: left; // float: left;
width: 230px; // 230px width: 230px;
height: 50px; // 50px height: 50px;
overflow: hidden; // overflow: hidden;
} }
&__brand { &__brand {
display: table-cell; // display: table-cell;
vertical-align: middle; // vertical-align: middle;
width: 230px; // 230px width: 230px;
height: 50px; // 50px height: 50px;
margin: 0; // margin: 0;
line-height: 50px; // 50px line-height: 50px;
font-size: 20px; // 20px font-size: 20px;
text-align: center; // text-align: center;
text-transform: uppercase; // text-transform: uppercase;
white-space: nowrap; // white-space: nowrap;
color: #fff; // color: #fff;
&-lg, &-lg,
&-mini { &-mini {
margin: 0 5px; // 5px margin: 0 5px;
color: #fff; // color: #fff;
&:focus, &:focus,
&:hover { &:hover {
color: #fff; // color: #fff;
text-decoration: none; // 线 text-decoration: none;
} }
} }
&-mini { &-mini {
display: none; // display: none;
} }
} }
&__switch { &__switch {
font-size: 18px; // 18px font-size: 18px;
border-bottom: none !important; // border-bottom: none !important;
} }
&__avatar { &__avatar {
border-bottom: none !important; // border-bottom: none !important;
* { * {
vertical-align: inherit; // vertical-align: inherit;
} }
.el-dropdown-link { .el-dropdown-link {
> img { > img {
width: 36px; // 36px width: 36px;
height: auto; // height: auto;
margin-right: 5px; // 5px margin-right: 5px;
border-radius: 100%; // border-radius: 100%;
vertical-align: middle; // vertical-align: middle;
} }
} }
} }
&__body { &__body {
position: relative; // position: relative;
margin-left: 230px; // 230px margin-left: 230px;
padding-right: 15px; // 15px padding-right: 15px;
background-color: #fff; // background-color: #fff;
} }
&__menu { &__menu {
float: left; // float: left;
background-color: transparent; // background-color: transparent;
border-bottom: 0; // border-bottom: 0;
&--right { &--right {
float: right; // float: right;
} }
a:focus, a:focus,
a:hover { a:hover {
text-decoration: none; // 线 text-decoration: none;
} }
.el-menu-item, .el-menu-item,
.el-submenu > .el-submenu__title { .el-submenu > .el-submenu__title {
height: 50px; // 50px height: 50px;
line-height: 50px; // 50px line-height: 50px;
} }
.el-submenu > .el-menu { .el-submenu > .el-menu {
top: 55px; // 55px top: 55px;
} }
.el-badge { .el-badge {
display: inline; // display: inline;
z-index: 2; // z2 z-index: 2;
&__content { &__content {
line-height: 16px; // 16px line-height: 16px;
} }
} }
} }
@ -291,123 +280,124 @@ img {
/* Sidebar /* Sidebar
------------------------------ */ ------------------------------ */
.site-sidebar { .site-sidebar {
position: fixed; // position: fixed;
top: 50px; // 50px top: 50px;
left: 0; // 0 left: 0;
bottom: 0; // bottom: 0;
z-index: 1020; // z z-index: 1020;
width: 230px; // 230px width: 230px;
overflow: hidden; // overflow: hidden;
&--dark, &--dark,
&--dark-popper { &--dark-popper {
background-color: $sidebar--background-color-dark; // background-color: $sidebar--background-color-dark;
.site-sidebar__menu.el-menu, .site-sidebar__menu.el-menu,
> .el-menu--popup { > .el-menu--popup {
background-color: $sidebar--background-color-dark; // background-color: $sidebar--background-color-dark;
.el-menu-item, .el-menu-item,
.el-submenu > .el-submenu__title { .el-submenu > .el-submenu__title {
color: $sidebar--color-text-dark; // color: $sidebar--color-text-dark;
&:focus, &:focus,
&:hover { &:hover {
color: mix(#fff, $sidebar--color-text-dark, 50%); // color: mix(#fff, $sidebar--color-text-dark, 50%);
background-color: mix(#fff, $sidebar--background-color-dark, 2.5%); // background-color: mix(#fff, $sidebar--background-color-dark, 2.5%);
} }
} }
.el-menu, .el-menu,
.el-submenu.is-opened { .el-submenu.is-opened {
background-color: mix(#000, $sidebar--background-color-dark, 15%); // background-color: mix(#000, $sidebar--background-color-dark, 15%);
} }
.el-menu-item.is-active, .el-menu-item.is-active,
.el-submenu.is-active > .el-submenu__title { .el-submenu.is-active > .el-submenu__title {
color: mix(#fff, $sidebar--color-text-dark, 80%); // color: mix(#fff, $sidebar--color-text-dark, 80%);
} }
} }
} }
&__inner { &__inner {
position: relative; // position: relative;
z-index: 1; // z z-index: 1;
width: 250px; // 250px width: 250px;
height: 100%; // 100% height: 100%;
padding-bottom: 15px; // 15px padding-bottom: 15px;
overflow-y: scroll; // y overflow-y: scroll;
} }
&__menu.el-menu { &__menu.el-menu {
width: 230px; // 230px width: 230px;
border-right: 0; // border-right: 0;
} }
&__menu-icon { &__menu-icon {
width: 24px; // 24px width: 24px;
margin-right: 5px; // 5px margin-right: 5px;
text-align: center; // text-align: center;
font-size: 16px; // 16px font-size: 16px;
color: inherit !important; // color: inherit !important;
} }
} }
/* Content /* Content
------------------------------ */ ------------------------------ */
.site-content { .site-content {
position: relative; // position: relative;
padding: 15px; // 15px padding: 15px;
&__wrapper { &__wrapper {
position: relative; // position: relative;
padding-top: 50px; // 50px padding-top: 50px;
margin-left: 230px; // 230px margin-left: 230px;
min-height: 100%; // 100% min-height: 100%;
background: $content--background-color; // background: $content--background-color;
} }
&--tabs { &--tabs {
padding: 55px 0 0; // 55px00 padding: 55px 0 0;
} }
> .el-tabs { > .el-tabs {
> .el-tabs__header { > .el-tabs__header {
position: fixed; // position: fixed;
top: 50px; // 50px top: 50px;
left: 230px; // 230px left: 230px;
right: 0; // 0 right: 0;
z-index: 930; // z z-index: 930;
padding: 0 55px 0 15px; // padding: 0 55px 0 15px;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, .12), 0 0 6px 0 rgba(0, 0, 0, .04); // box-shadow: 0 2px 4px 0 rgba(0, 0, 0, .12), 0 0 6px 0 rgba(0, 0, 0, .04);
background-color: #fff; // background-color: #fff;
> .el-tabs__nav-wrap { > .el-tabs__nav-wrap {
margin-bottom: 0; // 0 margin-bottom: 0;
&:after { &:after {
display: none; // display: none;
} }
} }
} }
> .el-tabs__content { > .el-tabs__content {
padding: 0 15px 15px; // padding: 0 15px 15px;
> .site-tabs__tools { > .site-tabs__tools {
position: fixed; // position: fixed;
top: 50px; // 50px top: 50px;
right: 0; // 0 right: 0;
z-index: 931; // z z-index: 931;
height: 40px; // 40px height: 40px;
padding: 0 12px; // padding: 0 12px;
font-size: 16px; // 16px font-size: 16px;
line-height: 40px; // 40px line-height: 40px;
background-color: $content--background-color; // background-color: $content--background-color;
cursor: pointer; // cursor: pointer;
.el-icon--right { .el-icon--right {
margin-left: 0; // 0 margin-left: 0;
} }
} }
} }
@ -415,8 +405,8 @@ img {
} }
.el-table__expand-icon { .el-table__expand-icon {
display: inline-block; // display: inline-block;
width: 14px; // 14px width: 14px;
vertical-align: middle; // vertical-align: middle;
margin-right: 5px; // 5px margin-right: 5px;
} }

@ -1,11 +1,12 @@
/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */ /*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */
//* Document /* Document
========================================================================== */ ========================================================================== */
/** /**
* 1. * 1. Correct the line height in all browsers.
* 2. Windows Phone iOS IE * 2. Prevent adjustments of font size after orientation changes in
* IE on Windows Phone and in iOS.
*/ */
html { html {
@ -18,7 +19,7 @@ html {
========================================================================== */ ========================================================================== */
/** /**
* * Remove the margin in all browsers (opinionated).
*/ */
body { body {
@ -26,7 +27,7 @@ body {
} }
/** /**
* IE 9- * Add the correct display in IE 9-.
*/ */
article, article,
@ -39,7 +40,8 @@ section {
} }
/** /**
* ChromeFirefox Safari `h1` `section` `article` * Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/ */
h1 { h1 {
@ -51,8 +53,8 @@ h1 {
========================================================================== */ ========================================================================== */
/** /**
* IE 9- * Add the correct display in IE 9-.
* 1. IE * 1. Add the correct display in IE.
*/ */
figcaption, figcaption,
@ -62,7 +64,7 @@ main { /* 1 */
} }
/** /**
* IE 8 * Add the correct margin in IE 8.
*/ */
figure { figure {
@ -70,8 +72,8 @@ figure {
} }
/** /**
* 1. Firefox * 1. Add the correct box sizing in Firefox.
* 2. Edge IE * 2. Show the overflow in Edge and IE.
*/ */
hr { hr {
@ -81,8 +83,8 @@ hr {
} }
/** /**
* 1. * 1. Correct the inheritance and scaling of font size in all browsers.
* 2. `em` * 2. Correct the odd `em` font sizing in all browsers.
*/ */
pre { pre {
@ -94,8 +96,8 @@ pre {
========================================================================== */ ========================================================================== */
/** /**
* 1. IE 10 * 1. Remove the gray background on active links in IE 10.
* 2. iOS 8+ Safari 8+ 线 * 2. Remove gaps in links underline in iOS 8+ and Safari 8+.
*/ */
a { a {
@ -104,8 +106,8 @@ a {
} }
/** /**
* 1. Chrome 57- Firefox 39- * 1. Remove the bottom border in Chrome 57- and Firefox 39-.
* 2. ChromeEdgeIEOpera Safari * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/ */
abbr[title] { abbr[title] {
@ -115,7 +117,7 @@ abbr[title] {
} }
/** /**
* Safari 6 `bolder` * Prevent the duplicate application of `bolder` by the next rule in Safari 6.
*/ */
b, b,
@ -124,7 +126,7 @@ strong {
} }
/** /**
* ChromeEdge Safari * Add the correct font weight in Chrome, Edge, and Safari.
*/ */
b, b,
@ -133,8 +135,8 @@ strong {
} }
/** /**
* 1. * 1. Correct the inheritance and scaling of font size in all browsers.
* 2. `em` * 2. Correct the odd `em` font sizing in all browsers.
*/ */
code, code,
@ -145,7 +147,7 @@ samp {
} }
/** /**
* Android 4.3- * Add the correct font style in Android 4.3-.
*/ */
dfn { dfn {
@ -153,7 +155,7 @@ dfn {
} }
/** /**
* IE 9- * Add the correct background and color in IE 9-.
*/ */
mark { mark {
@ -162,7 +164,7 @@ mark {
} }
/** /**
* * Add the correct font size in all browsers.
*/ */
small { small {
@ -170,7 +172,8 @@ small {
} }
/** /**
* `sub` `sup` * Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/ */
sub, sub,
@ -193,7 +196,7 @@ sup {
========================================================================== */ ========================================================================== */
/** /**
* IE 9- * Add the correct display in IE 9-.
*/ */
audio, audio,
@ -202,7 +205,7 @@ video {
} }
/** /**
* iOS 4-7 * Add the correct display in iOS 4-7.
*/ */
audio:not([controls]) { audio:not([controls]) {
@ -211,7 +214,7 @@ audio:not([controls]) {
} }
/** /**
* IE 10- * Remove the border on images inside links in IE 10-.
*/ */
img { img {
@ -219,20 +222,19 @@ img {
} }
/** /**
* IE * Hide the overflow in IE.
*/ */
svg:not(:root) { svg:not(:root) {
overflow: hidden; overflow: hidden;
} }
/* Forms /* Forms
========================================================================== */ ========================================================================== */
/** /**
* 1. * 1. Change the font styles in all browsers (opinionated).
* 2. Firefox Safari * 2. Remove the margin in Firefox and Safari.
*/ */
button, button,
@ -247,8 +249,8 @@ textarea {
} }
/** /**
* IE * Show the overflow in IE.
* 1. Edge * 1. Show the overflow in Edge.
*/ */
button, button,
@ -257,8 +259,8 @@ input { /* 1 */
} }
/** /**
* EdgeFirefox IE * Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Firefox * 1. Remove the inheritance of text transform in Firefox.
*/ */
button, button,
@ -267,8 +269,9 @@ select { /* 1 */
} }
/** /**
* 1. WebKit bug bug Android 4 `audio` `video` * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
* 2. iOS Safari * controls in Android 4.
* 2. Correct the inability to style clickable types in iOS and Safari.
*/ */
button, button,
@ -279,7 +282,7 @@ html [type="button"], /* 1 */
} }
/** /**
* Firefox * Remove the inner border and padding in Firefox.
*/ */
button::-moz-focus-inner, button::-moz-focus-inner,
@ -291,7 +294,7 @@ button::-moz-focus-inner,
} }
/** /**
* * Restore the focus styles unset by the previous rule.
*/ */
button:-moz-focusring, button:-moz-focusring,
@ -302,7 +305,7 @@ button:-moz-focusring,
} }
/** /**
* Firefox * Correct the padding in Firefox.
*/ */
fieldset { fieldset {
@ -310,9 +313,10 @@ fieldset {
} }
/** /**
* 1. Edge IE * 1. Correct the text wrapping in Edge and IE.
* 2. IE `fieldset` * 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. `fieldset` * 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/ */
legend { legend {
@ -325,8 +329,8 @@ legend {
} }
/** /**
* 1. IE 9+ * 1. Add the correct display in IE 9-.
* 2. ChromeFirefox Opera * 2. Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/ */
progress { progress {
@ -335,7 +339,7 @@ progress {
} }
/** /**
* IE * Remove the default vertical scrollbar in IE.
*/ */
textarea { textarea {
@ -343,8 +347,8 @@ textarea {
} }
/** /**
* 1. IE 10+ * 1. Add the correct box sizing in IE 10-.
* 2. IE 10+ * 2. Remove the padding in IE 10-.
*/ */
[type="checkbox"], [type="checkbox"],
@ -354,7 +358,7 @@ textarea {
} }
/** /**
* Chrome * Correct the cursor style of increment and decrement buttons in Chrome.
*/ */
[type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-inner-spin-button,
@ -363,8 +367,8 @@ textarea {
} }
/** /**
* 1. Chrome Safari * 1. Correct the odd appearance in Chrome and Safari.
* 2. Safari * 2. Correct the outline style in Safari.
*/ */
[type="search"] { [type="search"] {
@ -373,7 +377,7 @@ textarea {
} }
/** /**
* Chrome Safari on macOS * Remove the inner padding and cancel buttons in Chrome and Safari on macOS.
*/ */
[type="search"]::-webkit-search-cancel-button, [type="search"]::-webkit-search-cancel-button,
@ -382,8 +386,8 @@ textarea {
} }
/** /**
* 1. iOS Safari * 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Safari `inherit` * 2. Change font properties to `inherit` in Safari.
*/ */
::-webkit-file-upload-button { ::-webkit-file-upload-button {
@ -395,8 +399,8 @@ textarea {
========================================================================== */ ========================================================================== */
/* /*
* IE 9+ * Add the correct display in IE 9-.
* 1. EdgeIE Firefox * 1. Add the correct display in Edge, IE, and Firefox.
*/ */
details, /* 1 */ details, /* 1 */
@ -405,7 +409,7 @@ menu {
} }
/* /*
* * Add the correct display in all browsers.
*/ */
summary { summary {
@ -416,7 +420,7 @@ summary {
========================================================================== */ ========================================================================== */
/** /**
* IE 9+ * Add the correct display in IE 9-.
*/ */
canvas { canvas {
@ -424,7 +428,7 @@ canvas {
} }
/** /**
* IE * Add the correct display in IE.
*/ */
template { template {
@ -435,7 +439,7 @@ template {
========================================================================== */ ========================================================================== */
/** /**
* IE 10+ * Add the correct display in IE 10-.
*/ */
[hidden] { [hidden] {

@ -3,15 +3,11 @@
$--color-primary: #409EFF; $--color-primary: #409EFF;
// Navbar // Navbar
//
$navbar--background-color: $--color-primary; $navbar--background-color: $--color-primary;
// Sidebar // Sidebar
//
$sidebar--background-color-dark: #263238; $sidebar--background-color-dark: #263238;
//
$sidebar--color-text-dark: #8a979e; $sidebar--color-text-dark: #8a979e;
// Content // Content
//
$content--background-color: #f1f4f5; $content--background-color: #f1f4f5;

@ -1,7 +1,5 @@
@import "normalize"; @import "normalize";
// normalize.css
// api: https://github.com/necolas/normalize.css/ // api: https://github.com/necolas/normalize.css/
@import "variables"; @import "variables";
// 使 //
@import "base"; @import "base";
//

@ -1,40 +1,36 @@
<template> <template>
<!-- SVG元素使用动态绑定的类名宽度和高度属性 -->
<svg :class="getClassName" :width="width" :height="height" aria-hidden="true"> <svg :class="getClassName" :width="width" :height="height" aria-hidden="true">
<!-- 使用xlink:href属性引用外部定义的SVG符号 -->
<use :xlink:href="getName"></use> <use :xlink:href="getName"></use>
</svg> </svg>
</template> </template>
<script> <script>
export default { export default {
name: 'icon-svg', // 'icon-svg' name: 'icon-svg',
props: { props: {
name: { name: {
type: String, // 'name' type: String,
required: true // 'name' required: true
}, },
className: { className: {
type: String // 'className' type: String
}, },
width: { width: {
type: String // 'width' type: String
}, },
height: { height: {
type: String // 'height' type: String
} }
}, },
computed: { computed: {
// 'getName'ID
getName() { getName() {
return `#icon-${this.name}` return `#icon-${this.name}`
}, },
// 'getClassName'
getClassName() { getClassName() {
return [ return [
'icon-svg', // 'icon-svg',
`icon-svg__${this.name}`, // 'name' `icon-svg__${this.name}`,
this.className && /\S/.test(this.className) ? `${this.className}` : '' // 'className' this.className && /\S/.test(this.className) ? `${this.className}` : ''
] ]
} }
} }
@ -42,11 +38,10 @@ export default {
</script> </script>
<style> <style>
/* 样式定义 */
.icon-svg { .icon-svg {
width: 1em; // 1em width: 1em;
height: 1em; // 1em height: 1em;
fill: currentColor; // fill: currentColor;
overflow: hidden; // overflow: hidden;
} }
</style> </style>

@ -1,11 +1,7 @@
<template> <template>
<!-- 定义一个表格列绑定属性和插槽 -->
<el-table-column :prop="prop" v-bind="$attrs"> <el-table-column :prop="prop" v-bind="$attrs">
<!-- 自定义单元格内容 -->
<template slot-scope="scope"> <template slot-scope="scope">
<!-- 点击时触发toggleHandle方法并应用样式 -->
<span @click.prevent="toggleHandle(scope.$index, scope.row)" :style="childStyles(scope.row)"> <span @click.prevent="toggleHandle(scope.$index, scope.row)" :style="childStyles(scope.row)">
<!-- 根据行数据动态设置图标类和样式 -->
<i :class="iconClasses(scope.row)" :style="iconStyles(scope.row)"></i> <i :class="iconClasses(scope.row)" :style="iconStyles(scope.row)"></i>
{{ scope.row[prop] }} {{ scope.row[prop] }}
</span> </span>
@ -14,81 +10,74 @@
</template> </template>
<script> <script>
// lodashisArray
import isArray from 'lodash/isArray' import isArray from 'lodash/isArray'
export default { export default {
name: 'table-tree-column', // name: 'table-tree-column',
props: { props: {
prop: { prop: {
type: String // type: String
}, },
treeKey: { treeKey: {
type: String, type: String,
default: 'id' // 'id' default: 'id'
}, },
parentKey: { parentKey: {
type: String, type: String,
default: 'parentId' // 'parentId' default: 'parentId'
}, },
levelKey: { levelKey: {
type: String, type: String,
default: '_level' // '_level' default: '_level'
}, },
childKey: { childKey: {
type: String, type: String,
default: 'children' // 'children' default: 'children'
} }
}, },
methods: { methods: {
//
childStyles(row) { childStyles(row) {
return { 'padding-left': (row[this.levelKey] > 1 ? row[this.levelKey] * 7 : 0) + 'px' } return { 'padding-left': (row[this.levelKey] > 1 ? row[this.levelKey] * 7 : 0) + 'px' }
}, },
//
iconClasses(row) { iconClasses(row) {
return [!row._expanded ? 'el-icon-caret-right' : 'el-icon-caret-bottom'] return [!row._expanded ? 'el-icon-caret-right' : 'el-icon-caret-bottom']
}, },
//
iconStyles(row) { iconStyles(row) {
return { 'visibility': this.hasChild(row) ? 'visible' : 'hidden' } return { 'visibility': this.hasChild(row) ? 'visible' : 'hidden' }
}, },
//
hasChild(row) { hasChild(row) {
return (isArray(row[this.childKey]) && row[this.childKey].length >= 1) || false return (isArray(row[this.childKey]) && row[this.childKey].length >= 1) || false
}, },
// //
toggleHandle(index, row) { toggleHandle(index, row) {
if (this.hasChild(row)) { if (this.hasChild(row)) {
var data = this.$parent.store.states.data.slice(0) // var data = this.$parent.store.states.data.slice(0)
data[index]._expanded = !data[index]._expanded // data[index]._expanded = !data[index]._expanded
if (data[index]._expanded) { if (data[index]._expanded) {
//
data = data.splice(0, index + 1).concat(row[this.childKey]).concat(data) data = data.splice(0, index + 1).concat(row[this.childKey]).concat(data)
} else { } else {
//
data = this.removeChildNode(data, row[this.treeKey]) data = this.removeChildNode(data, row[this.treeKey])
} }
this.$parent.store.commit('setData', data) // this.$parent.store.commit('setData', data)
this.$nextTick(() => { this.$nextTick(() => {
this.$parent.doLayout() // this.$parent.doLayout()
}) })
} }
}, },
// //
removeChildNode(data, parentId) { removeChildNode(data, parentId) {
var parentIds = isArray(parentId) ? parentId : [parentId] // parentId var parentIds = isArray(parentId) ? parentId : [parentId]
if (parentId.length <= 0) { if (parentId.length <= 0) {
return data // parentId return data
} }
var ids = [] // ID var ids = []
for (var i = 0; i < data.length; i++) { for (var i = 0; i < data.length; i++) {
if (parentIds.indexOf(data[i][this.parentKey]) !== -1 && parentIds.indexOf(data[i][this.treeKey]) === -1) { if (parentIds.indexOf(data[i][this.parentKey]) !== -1 && parentIds.indexOf(data[i][this.treeKey]) === -1) {
data[i]._expanded = false // data[i]._expanded = false
ids.push(data.splice(i, 1)[0][this.treeKey]) // ID ids.push(data.splice(i, 1)[0][this.treeKey])
i-- // i--
} }
} }
return this.removeChildNode(data, ids) // return this.removeChildNode(data, ids)
} }
} }
} }

@ -1,83 +1,77 @@
<template> <template>
<!-- 面板容器使用flex布局 --> <div class="panel flex flex-wrap">
<div class="panel flex flex-wrap">
<!-- 动态生成的标签列表 -->
<el-tag v-for="tag in dynamicTags" closable @close="handleClose(tag)" :disable-transitions="false" :key="tag"> <el-tag v-for="tag in dynamicTags" closable @close="handleClose(tag)" :disable-transitions="false" :key="tag">
{{tag}} {{tag}}
</el-tag> </el-tag>
<!-- 输入框用于添加新标签 -->
<el-input class="input-new-tag" v-if="inputVisible" v-model="inputValue" ref="saveTagInput" size="small" @keyup.enter.native="handleInputConfirm" @blur="handleInputConfirm"> <el-input class="input-new-tag" v-if="inputVisible" v-model="inputValue" ref="saveTagInput" size="small" @keyup.enter.native="handleInputConfirm" @blur="handleInputConfirm">
</el-input> </el-input>
<!-- 按钮点击后显示输入框 -->
<el-button v-else class="button-new-tag" size="small" @click="showInput">+ </el-button> <el-button v-else class="button-new-tag" size="small" @click="showInput">+ </el-button>
</div> </div>
</template> </template>
<script>
/** /**
* 标签编辑器组件 * 标签编辑器
*/ */
let touchMoved = false; // let touchMoved = false;
export default { export default {
name: 'tags-editor', // name: 'tags-editor',
props: { props: {
value: { // value: {
type: String, type: String,
required: true, required: true,
default: "" default: ""
}, },
size: { // [small:,large:] size: {//[small:,large:]
type: String, type: String,
default: 'small' default: 'small'
} }
}, },
data() { data() {
return { return {
inputVisible: false, // inputVisible: false,
inputValue: '' // inputValue: ''
} }
}, },
computed: { computed: {
dynamicTags() { // value dynamicTags() {
if (this.value != "") return this.value.split(',') if (this.value != "") return this.value.split(',')
return [] return []
} }
}, },
methods: { methods: {
handleClose(tag) { // handleClose(tag) {
let newTags = this.dynamicTags; // let newTags = this.dynamicTags;
newTags.splice(newTags.indexOf(tag), 1); // newTags.splice(newTags.indexOf(tag), 1);
this.$emit('input', newTags.join(",")); // this.$emit('input', newTags.join(","));
}, },
showInput() { // showInput() {
this.inputVisible = true; // this.inputVisible = true;
this.$nextTick(_ => { // DOM this.$nextTick(_ => {
this.$refs.saveTagInput.$refs.input.focus(); // this.$refs.saveTagInput.$refs.input.focus();
}); });
}, },
handleInputConfirm() { // handleInputConfirm() {
let inputValue = this.inputValue; // let inputValue = this.inputValue;
let newTags = this.dynamicTags; // let newTags = this.dynamicTags;
if (inputValue && newTags.indexOf(inputValue) < 0) { // if (inputValue && newTags.indexOf(inputValue) < 0) {
newTags.push(inputValue); // newTags.push(inputValue);
} }
this.inputVisible = false; // this.inputVisible = false;
this.inputValue = ''; // this.inputValue = '';
this.$emit('input', newTags.join(",")); // this.$emit('input', newTags.join(","));
} }
} }
} }
</script>
<style scoped> <style scoped>
/* 面板样式 */
.panel { .panel {
flex: 1; /* 弹性布局,占满剩余空间 */ flex: 1;
} }
/* 标签和按钮样式 */
.el-tag,.button-new-tag{ .el-tag,.button-new-tag{
margin: 5px; /* 外边距 */ margin: 5px;
} }
/* 输入框样式 */
.input-new-tag { .input-new-tag {
width: inherit; /* 继承父元素的宽度 */ width: inherit;
} }
</style> </style>

@ -1,207 +1,185 @@
<template> <template>
<!-- 模态对话框用于筛选模板消息目标用户 -->
<el-dialog title="筛选模板消息目标用户" :close-on-click-modal="false" :visible.sync="visible"> <el-dialog title="筛选模板消息目标用户" :close-on-click-modal="false" :visible.sync="visible">
<!-- 表单布局为行内绑定数据模型dataForm清除按钮可清空输入框 -->
<el-form :inline="true" :model="dataForm" ref="dataForm" clearable @keyup.enter.native="getWxUsers()"> <el-form :inline="true" :model="dataForm" ref="dataForm" clearable @keyup.enter.native="getWxUsers()">
<!-- 用户标签选择框 -->
<el-form-item> <el-form-item>
<el-select v-model="dataForm.tagid" filterable placeholder="用户标签" @change="getWxUsers()"> <el-select v-model="dataForm.tagid" filterable placeholder="用户标签" @change="getWxUsers()">
<!-- 遍历用户标签列表生成选项 -->
<el-option v-for="item in wxUserTags" :key="item.id" :label="item.name" :value="item.id+''"></el-option> <el-option v-for="item in wxUserTags" :key="item.id" :label="item.name" :value="item.id+''"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- 昵称输入框 -->
<el-form-item> <el-form-item>
<el-input v-model="dataForm.nickname" placeholder="昵称" @change="getWxUsers()" clearable></el-input> <el-input v-model="dataForm.nickname" placeholder="昵称" @change="getWxUsers()" clearable></el-input>
</el-form-item> </el-form-item>
<!-- 省份输入框 -->
<el-form-item> <el-form-item>
<el-input v-model="dataForm.province" placeholder="省份" @change="getWxUsers()" clearable></el-input> <el-input v-model="dataForm.province" placeholder="省份" @change="getWxUsers()" clearable></el-input>
</el-form-item> </el-form-item>
<!-- 城市输入框 -->
<el-form-item> <el-form-item>
<el-input v-model="dataForm.city" placeholder="城市" @change="getWxUsers()" clearable></el-input> <el-input v-model="dataForm.city" placeholder="城市" @change="getWxUsers()" clearable></el-input>
</el-form-item> </el-form-item>
<!-- 备注输入框 -->
<el-form-item> <el-form-item>
<el-input v-model="dataForm.remark" placeholder="备注" @change="getWxUsers()" clearable></el-input> <el-input v-model="dataForm.remark" placeholder="备注" @change="getWxUsers()" clearable></el-input>
</el-form-item> </el-form-item>
<!-- 扫码场景值输入框 -->
<el-form-item> <el-form-item>
<el-input v-model="dataForm.qrScene" placeholder="扫码场景值" @change="getWxUsers()" clearable></el-input> <el-input v-model="dataForm.qrScene" placeholder="扫码场景值" @change="getWxUsers()" clearable></el-input>
</el-form-item> </el-form-item>
</el-form> </el-form>
<!-- 显示将发送的消息预览 -->
<div class="text-bold">本消息将发送给</div> <div class="text-bold">本消息将发送给</div>
<!-- 用户列表区域加载状态时显示加载动画 -->
<div class="user-list" v-loading="wxUsersLoading"> <div class="user-list" v-loading="wxUsersLoading">
<!-- 遍历用户列表生成用户卡片 -->
<div class="user-card" v-for="item in wxUserList" :key="item.openid"> <div class="user-card" v-for="item in wxUserList" :key="item.openid">
<!-- 用户头像 -->
<el-avatar :src="item.headimgurl"></el-avatar> <el-avatar :src="item.headimgurl"></el-avatar>
<!-- 用户昵称 -->
<div class="nickname">{{item.nickname}}</div> <div class="nickname">{{item.nickname}}</div>
</div> </div>
<!-- 当用户数量超过10个时显示省略号和总用户数 -->
<div class="text-bold"> <div class="text-bold">
<span v-show="totalCount>10">...</span> <span v-show="totalCount>10">...</span>
等共<span class="text-success">{{totalCount}}</span>个用户 等共<span class="text-success">{{totalCount}}</span>个用户
</div> </div>
</div> </div>
<!-- 消息预览标题 -->
<div class="margin-top text-bold">消息预览</div> <div class="margin-top text-bold">消息预览</div>
<!-- 消息预览内容禁用编辑且自动调整大小 -->
<div class="margin-top-xs"> <div class="margin-top-xs">
<el-input type="textarea" disabled autosize v-model="msgReview" placeholder="模版"></el-input> <el-input type="textarea" disabled autosize v-model="msgReview" placeholder="模版"></el-input>
</div> </div>
<!-- 底部操作栏 -->
<span slot="footer" class="dialog-footer"> <span slot="footer" class="dialog-footer">
<!-- 发送按钮根据发送状态显示不同文本 -->
<el-button @click="send" type="success" :disabled="totalCount<=0 || sending">{{sending?'发送中...':'发送'}}</el-button> <el-button @click="send" type="success" :disabled="totalCount<=0 || sending">{{sending?'发送中...':'发送'}}</el-button>
<!-- 关闭按钮 -->
<el-button @click="visible=false"></el-button> <el-button @click="visible=false"></el-button>
</span> </span>
</div> </el-dialog>
</template> </template>
<script> <script>
import { mapState } from 'vuex' import { mapState } from 'vuex'
export default { export default {
name: 'template-msg', // name:'template-msg-task',
props: { props:{
// wxUserTagName:{
wxUserTagName: String, type:String,
required:false
}
}, },
data() { data(){
return { return{
visible: false, // visible:false,
wxUsersLoading: false, // wxUsersLoading:false,
dataForm: { // sending:false,
page: 1, // msgTemplate:{},
sidx: 'subscribe_time', // dataForm: {
order: 'desc', // page:1,
tagid: '', // ID sidx: 'subscribe_time',
nickname: '', // order: 'desc',
province: '', // tagid:'',
city: '', // nickname: '',
remark: '', // city:'',
qrScene: '', // province:'',
remark:'',
qrScene:''
}, },
msgTemplate: {}, // wxUserList:[],
wxUserList: [], // totalCount:0
totalCount: 0, //
} }
}, },
computed: mapState({ computed: mapState({
wxUserTags: state => state.wxUserTags.tags, // Vuex wxUserTags:state=>state.wxUserTags.tags,
msgReview(): string { // msgReview(){
if (!this.msgTemplate.data) return "" // if(!this.msgTemplate.data) return ""
let content = this.msgTemplate.content // let content = this.msgTemplate.content
this.msgTemplate.data.forEach(item => { // this.msgTemplate.data.forEach(item=>{
content = content.replace("{{" + item.name + ".DATA}}", item.value) // content = content.replace("{{"+item.name+".DATA}}",item.value)
}) })
return content // return content
} }
}), }),
mounted() { mounted() {
this.getWxUserTags().then((taglist) => { // this.getWxUserTags().then((taglist)=>{
if (this.wxUserTagName) { // if(this.wxUserTagName){
let tagItem = taglist.find(tag => tag.name === this.wxUserTagName) // let tagItem = taglist.find(tag=>tag.name==this.wxUserTagName)
if (tagItem) { // console.log(tagItem)
this.dataForm.tagid = tagItem.id + '' // IDID if(tagItem) {
this.dataForm.tagid=tagItem.id+''
} }
} }
this.getWxUsers(); // this.getWxUsers()
}); });
}, },
methods: { methods:{
init(msgTemplate) { // init(msgTemplate){
if (!msgTemplate || !msgTemplate.templateId) { // ID if(!msgTemplate || !msgTemplate.templateId){
this.$message.error('消息模板无效') // this.$message.error('消息模板无效')
return // return
} }
if (!msgTemplate.data || !(msgTemplate.data instanceof Array)) { // if(!msgTemplate.data || !(msgTemplate.data instanceof Array)){
this.$message.error('请现配置此模板填充数据') // this.$message.error('请现配置此模板填充数据')
return // return
} }
this.msgTemplate = msgTemplate // this.msgTemplate=msgTemplate
this.visible = true; // this.visible=true;
}, },
getWxUserTags() { // getWxUserTags() {
return new Promise((resolve, reject) => { // Promise return new Promise((resolve,reject)=>{
this.$http({ // HTTP this.$http({
url: this.$adorn.url('/manage/wxUserTags/list'), // URL url: this.$http.adornUrl('/manage/wxUserTags/list'),
method: 'get', // HTTPGET method: 'get',
params: this.$adorn.params({}) // }).then(({ data }) => {
}).then((response) => { // if (data && data.code === 200) {
if (response.data.code == 200) { // 200 this.$store.commit('wxUserTags/updateTags', data.list)
this.$store.dispatch('wxUserTags/updateTags', response.data.list) // Vuex resolve(data.list)
resolve(response.data.list) // Promise
} else { } else {
this.$message.error(response.data.msg) // this.$message.error(data.msg)
reject(response.data.msg) // Promise reject(data.msg)
} }
}).catch(err=>reject(err)) // Promise }).catch(err=>reject(err))
}); })
}, },
getWxUsers() { // getWxUsers() {
this.wxUsersLoading = true // true this.wxUsersLoading = true
this.$http({ // HTTP this.$http({
url: this.$adorn.url('/manage/wxUser/list'), // URL url: this.$http.adornUrl('/manage/wxUser/list'),
method: 'get', // HTTPGET method: 'get',
params: this.$adorn.params(this.dataForm) // params: this.$http.adornParams(this.dataForm)
}).then((response) => { // }).then(({ data }) => {
if (response.data.code == 200) { // 200 if (data && data.code === 200) {
this.wxUserList = response.data.page.list // this.wxUserList = data.page.list
this.totalCount = response.data.page.totalCount // this.totalCount = data.page.totalCount
} else { } else {
this.$message.error(response.data.msg) // this.$message.error(data.msg)
} }
this.wxUsersLoading = false // false this.wxUsersLoading = false
}).catch(err=>reject(err)) // Promise })
}, },
send() { // send(){
if (this.sending) return // if(this.sending)return
this.sending = true // true this.sending=true
this.$http({ // HTTP this.$http({
url: this.$adorn.url('/manage/msgTemplate/sendMsgBatch'), // URL url: this.$http.adornUrl('/manage/msgTemplate/sendMsgBatch'),
method: 'post', // HTTPPOST method: 'post',
data: this.$adorn.data({ // data:this.$http.adornData({
wxUserFilterParams: this.dataForm, // wxUserFilterParams : this.dataForm,
templateId: this.msgTemplate.templateId, // IDID templateId : this.msgTemplate.templateId,
url: this.msgTemplate.url, // URLURL url : this.msgTemplate.url,
miniprogram: this.msgTemplate.miniprogram, // miniprogram miniprogram : this.msgTemplate.miniprogram,
data: this.msgTemplate.data, // data data : this.msgTemplate.data,
}) })
}).then((response) => { // }).then(({ data }) => {
this.sending = false // false this.sending = false
if (response.data.code == 200) { // 200 if (data && data.code === 200) {
this.$message.success("消息将在后台发送") // this.$message.success("消息将在后台发送")
this.visible = false; // this.visible=false
} else { } else {
this.$message.error(response.data.msg) // this.$message.error(data.msg)
} }
}).catch(err=>reject(err)) // Promise })
} }
} }
} }
</script> </script>
<style scoped> <style scoped>
/* 用户列表样式 */
.user-list{ .user-list{
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
align-items: center; align-items: center;
} }
/* 用户卡片样式 */
.user-card{ .user-card{
overflow: hidden; overflow: hidden;
max-width: 60px; max-width: 60px;
margin: 5px; margin: 5px;
text-align: center; text-align: center;
} }
/* 昵称样式 */
.nickname{ .nickname{
color: #999999; color: #999999;
overflow: hidden; overflow: hidden;

@ -1,102 +1,99 @@
<template> <template>
<!-- 定义一个包含TinyMCE编辑器的div容器 -->
<div class="tinymce-editor"> <div class="tinymce-editor">
<!-- 使用TinyMCE组件绑定v-model为myValue初始化配置为init监听onExecCommand事件 -->
<editor v-model="myValue" :init="init" @onExecCommand="onExecCommand"></editor> <editor v-model="myValue" :init="init" @onExecCommand="onExecCommand"></editor>
</div> </div>
</template> </template>
<script>
import Editor from "@tinymce/tinymce-vue";
import Editor from "@tinymce/tinymce-vue"; // TinyMCE Vue var cos;
var cos; // cos
export default { export default {
name: "tinymce-editor", // name: "tinymce-editor",
components: { components: {
Editor // TinyMCE Editor
}, },
props: { props: {
value: { value: {
type: String, // value type: String,
default: "" // default: ""
} }
}, },
data() { data() {
return { return {
// TinyMCE
init: { init: {
language_url: "./tinymce/zh_CN.js", // language_url: "./tinymce/zh_CN.js", //public
language: "zh_CN", // language: "zh_CN",
height: 500, // height: 500,
plugins: "lists image media table paste link searchreplace anchor code preview pagebreak importcss", // plugins: "lists image media table paste link searchreplace anchor code preview pagebreak importcss",
toolbar: "undo redo searchreplace | formatselect pagebreak | bold italic forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | lists link anchor image media table | removeformat code preview", // toolbar: "undo redo searchreplace | formatselect pagebreak | bold italic forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | lists link anchor image media table | removeformat code preview", //
toolbar_drawer: false, // toolbar_drawer: false,
image_advtab: true, // image_advtab: true,
object_resizing: false, // object_resizing: false,
paste_data_images: true, // paste_data_images: true,
content_css: "./tinymce/article.css", // content_css: "./tinymce/article.css",
images_upload_handler: (blobInfo, success, failure) => { images_upload_handler: (blobInfo, success, failure) => {
//
this.uploadFile(blobInfo.blob()).then(fileUrl => success(fileUrl)).catch(err => failure(err)) this.uploadFile(blobInfo.blob()).then(fileUrl => success(fileUrl)).catch(err => failure(err))
} }
}, },
myValue: this.value, // valuemyValue myValue: this.value,
uploading: false, // uploading: false,
cosConfig: [] // cosConfig: []
}; };
}, },
mounted() { mounted() {
// console.log('tinymce-editor mounted:',this.value) // value // console.log('tinymce-editor mounted:',this.value)
tinymce.init({}); // TinyMCE tinymce.init({});
this.cosInit(); // cosInit this.cosInit();
}, },
methods: { methods: {
cosInit() { cosInit() {
// HTTP
this.$http({ this.$http({
url: this.$http.adornUrl("/sys/oss/config"), // URL url: this.$http.adornUrl("/sys/oss/config"),
method: "get", // HTTPGET method: "get",
params: this.$http.adornParams() // params: this.$http.adornParams()
}).then(({ data }) => { }).then(({ data }) => {
if (data && data.code === 200) { if (data && data.code === 200) {
this.cosConfig = data.config; // cosConfig this.cosConfig = data.config;
} else { } else {
this.$message.error("请先配置云存储相关信息!"); // this.$message.error("请先配置云存储相关信息!");
} }
}); });
}, },
onExecCommand(e) { onExecCommand(e) {
//console.log(e) // //console.log(e)
}, },
uploadFile(file) { uploadFile(file) {
this.uploading = true; // true this.uploading = true;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let formData = new FormData(); // FormData let formData = new FormData();
formData.append("file", file); // FormData formData.append("file", file);
// HTTP
this.$http({ this.$http({
url: this.$http.adornUrl('/sys/oss/upload'), // URL url: this.$http.adornUrl('/sys/oss/upload'),
method: 'post', // HTTPPOST method: 'post',
data: formData // FormData data: formData
}).then(({ data }) => { }).then(({ data }) => {
console.log(data) // console.log(data)
if (data && data.code === 200) { if (data && data.code === 200) {
this.$emit('uploaded', data.url) // uploadedURL this.$emit('uploaded', data.url)
resolve(data.url) // PromiseURL resolve(data.url)
} else { } else {
this.$message.error("文件上传失败:" + data.msg) // this.$message.error("文件上传失败:" + data.msg)
reject(data.msg) // Promise reject(data.msg)
} }
this.uploading = false; // false this.uploading = false;
}).catch(err=>reject(err)) // Promise }).catch(err=>reject(err))
}); });
} }
}, },
watch: { watch: {
value(newValue) { value(newValue) {
this.myValue = newValue; // valuemyValue this.myValue = newValue;
}, },
myValue(newValue) { myValue(newValue) {
this.$emit("input", newValue); // myValueinput this.$emit("input", newValue);
} }
} }
}; };
</script>

@ -1,46 +1,45 @@
<template> <template>
<!-- 使用Element UI的el-select组件绑定v-model为selectedAppid设置size为small并添加v-loading指令来控制加载状态 --> <el-select v-model="selectedAppid" size="small" v-loading="dataListLoading" @change="selectAccount" filterable>
<el-select v-model="selectedAppid" size="small" v-loading="dataListLoading" @change="selectAccount" filterable>
<!-- 遍历accountList数组生成el-option选项 -->
<el-option v-for="item in accountList" :key="item.appid" :label="item.name+''+ACCOUNT_TYPES[item.type]+''" :value="item.appid"></el-option> <el-option v-for="item in accountList" :key="item.appid" :label="item.name+''+ACCOUNT_TYPES[item.type]+''" :value="item.appid"></el-option>
</el-select> </el-select>
</template> </template>
<script>
import { mapState } from 'vuex' import { mapState } from 'vuex'
export default { export default {
data() { data() {
return { return {
dataListLoading: false // dataListLoading dataListLoading: false
} }
}, },
computed: mapState({ computed: mapState({
accountList: state=>state.wxAccount.accountList, // VuexaccountList accountList: state=>state.wxAccount.accountList,
ACCOUNT_TYPES: state=>state.wxAccount.ACCOUNT_TYPES, // VuexACCOUNT_TYPES ACCOUNT_TYPES: state=>state.wxAccount.ACCOUNT_TYPES,
selectedAppid:state=>state.wxAccount.selectedAppid // VuexselectedAppid selectedAppid:state=>state.wxAccount.selectedAppid
}), }),
mounted(){ mounted(){
this.getDataList() // getDataList this.getDataList()
}, },
methods:{ methods:{
getDataList() { getDataList() {
this.dataListLoading = true // dataListLoadingtrue this.dataListLoading = true
this.$http({ this.$http({
url: this.$http.adornUrl('/manage/wxAccount/list'), // URL url: this.$http.adornUrl('/manage/wxAccount/list'),
method: 'get' // HTTPGET method: 'get'
}).then(({ data }) => { }).then(({ data }) => {
if (data && data.code === 200) { // 200 if (data && data.code === 200) {
this.$store.commit('wxAccount/updateAccountList', data.list) // mutationaccountList this.$store.commit('wxAccount/updateAccountList', data.list)
if(!data.list.length){ // if(!data.list.length){
this.$message.info("公众号列表为空,请先添加") // this.$message.info("公众号列表为空,请先添加")
} }
} }
this.dataListLoading = false // dataListLoadingfalse this.dataListLoading = false
}) })
}, },
selectAccount(appid){ selectAccount(appid){
if(this.selectedAppid!=appid){ // appidappid if(this.selectedAppid!=appid){
this.$store.commit('wxAccount/selectAccount', appid) // mutationselectedAppid this.$store.commit('wxAccount/selectAccount', appid)
} }
} }
} }
} }
</script>

@ -1,28 +1,20 @@
<template> <template>
<!-- 消息预览面板 -->
<div class="panel"> <div class="panel">
<!-- 工具提示显示消息方向 -->
<el-tooltip class="item" effect="dark" :content="msg.inOut?'公众号发出的消息':'来自用户的消息'" placement="right"> <el-tooltip class="item" effect="dark" :content="msg.inOut?'公众号发出的消息':'来自用户的消息'" placement="right">
<!-- 根据消息方向显示不同的图标和标签 --> <el-tag size="mini" v-if="msg.inOut" class="margin-right el-icon-upload2" type="info"></el-tag>
<el-tag size="mini" v-if="msg.inOut" class="margin-right el-icon-upload2" type="info"></el-tag>
<el-tag size="mini" v-else class="margin-right el-icon-download"></el-tag> <el-tag size="mini" v-else class="margin-right el-icon-download"></el-tag>
</el-tooltip> </el-tooltip>
<!-- 消息内容展示区域 -->
<span class="panel-content"> <span class="panel-content">
<!-- 文本消息类型 -->
<span v-if="msg.msgType=='text'" v-html="msg.detail.content"></span> <span v-if="msg.msgType=='text'" v-html="msg.detail.content"></span>
<!-- 事件消息类型 --> <span v-else-if="msg.msgType=='event'" >
<span v-else-if="msg.msgType=='event'">
<el-tag size="mini" type="warning" effect="plain">事件</el-tag> <el-tag size="mini" type="warning" effect="plain">事件</el-tag>
<el-tag size="mini" type="info" effect="plain">{{msg.detail.event}}</el-tag> <el-tag size="mini" type="info" effect="plain">{{msg.detail.event}}</el-tag>
{{msg.detail.eventKey}} {{msg.detail.eventKey}}
</span> </span>
<!-- 转客服事件 -->
<span v-else-if="msg.msgType=='transfer_customer_service'"> <span v-else-if="msg.msgType=='transfer_customer_service'">
<el-tag size="mini" type="warning" effect="plain">事件</el-tag> <el-tag size="mini" type="warning" effect="plain">事件</el-tag>
<el-tag size="mini" type="info" effect="plain">消息转客服</el-tag> <el-tag size="mini" type="info" effect="plain">消息转客服</el-tag>
</span> </span>
<!-- 其他消息类型 -->
<span v-else> <span v-else>
<el-tag size="mini" effect="plain">{{XmlMsgType[msg.msgType]}}</el-tag> <el-tag size="mini" effect="plain">{{XmlMsgType[msg.msgType]}}</el-tag>
后台不支持预览 后台不支持预览
@ -30,25 +22,21 @@
</span> </span>
</div> </div>
</template> </template>
<script> <script>
import { mapState } from 'vuex' import { mapState } from 'vuex'
export default { export default {
name:'wx-msg-preview', // name:'wx-msg-preview',
props:{ props:{
msg:Object // msg:Object
}, },
computed:mapState({ computed:mapState({
// VuexXmlMsgType
XmlMsgType:state=>state.message.XmlMsgType, XmlMsgType:state=>state.message.XmlMsgType,
}) })
} }
</script> </script>
<style scoped> <style scoped>
/* 面板样式 */
.panel,.panel a{ .panel,.panel a{
color: #999; // color: #999;
word-break: break-all; // word-break: break-all;
} }
</style> </style>

@ -1,157 +1,139 @@
<template> <template>
<!-- 模态框用于显示公众号用户标签管理界面 -->
<el-dialog title="公众号用户标签管理" :close-on-click-modal="false" :visible.sync="dialogVisible"> <el-dialog title="公众号用户标签管理" :close-on-click-modal="false" :visible.sync="dialogVisible">
<!-- 面板容器包含标签和输入框 --> <div class="panel flex flex-wrap" v-loading="submitting">
<div class="panel flex flex-wrap" v-loading="submitting">
<!-- 遍历并显示所有标签 -->
<el-tag v-for="tag in wxUserTags" closable @click="editTag(tag.id,tag.name)" @close="deleteTag(tag.id)" :disable-transitions="false" :key="tag.id"> <el-tag v-for="tag in wxUserTags" closable @click="editTag(tag.id,tag.name)" @close="deleteTag(tag.id)" :disable-transitions="false" :key="tag.id">
{{tag.id}} {{tag.name}} {{tag.id}} {{tag.name}}
</el-tag> </el-tag>
<!-- 当inputVisible为true时显示输入框否则显示添加按钮 -->
<el-input class="input-new-tag" v-if="inputVisible" placeholder="回车确认" v-model="inputValue" ref="saveTagInput" size="small" @keyup.enter.native="addTag"> <el-input class="input-new-tag" v-if="inputVisible" placeholder="回车确认" v-model="inputValue" ref="saveTagInput" size="small" @keyup.enter.native="addTag">
</el-input> </el-input>
<el-button v-else class="button-new-tag" size="small" @click="showInput">+ </el-button> <el-button v-else class="button-new-tag" size="small" @click="showInput">+ </el-button>
</div> </div>
<!-- 对话框底部的关闭按钮 -->
<span slot="footer" class="dialog-footer"> <span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible=false"></el-button> <el-button @click="dialogVisible=false"></el-button>
</span> </span>
</el-dialog> </el-dialog>
</template> </template>
<script>
import { mapState } from 'vuex' import { mapState } from 'vuex'
export default { export default {
name: 'wx-user-tags-manager', // name: 'wx-user-tags-manager',
props: { props: {
visible: { visible: {
type: Boolean, // type: Boolean,
default: true // true default: true
} }
}, },
data() { data() {
return { return {
dialogVisible: false, // dialogVisible:false,
inputVisible: false, // inputVisible: false,
inputValue: '', // inputValue: '',
submitting: false, // submitting:false,
} }
}, },
computed: mapState({ computed: mapState({
// VuexwxUserTags wxUserTags:state=>state.wxUserTags.tags
wxUserTags: state => state.wxUserTags.tags
}), }),
mounted() { mounted() {
//
this.getWxUserTags(); this.getWxUserTags();
}, },
methods: { methods: {
//
show(){ show(){
this.dialogVisible = true; this.dialogVisible=true;
}, },
//
getWxUserTags() { getWxUserTags() {
this.$http({ this.$http({
url: this.$http.adornUrl('/manage/wxUserTags/list'), // URL url: this.$http.adornUrl('/manage/wxUserTags/list'),
method: 'get', // HTTPGET method: 'get',
}).then(({ data }) => { }).then(({ data }) => {
if (data && data.code === 200) { if (data && data.code === 200) {
// Vuex
this.$store.commit('wxUserTags/updateTags', data.list) this.$store.commit('wxUserTags/updateTags', data.list)
} else { } else {
//
this.$message.error(data.msg) this.$message.error(data.msg)
} }
}) })
}, },
//
deleteTag(tagid) { deleteTag(tagid) {
if(this.submitting){ if(this.submitting){
return // return
} }
this.$confirm(`确定删除标签?`, '提示', { this.$confirm(`确定删除标签?`, '提示', {
confirmButtonText: '确定', // confirmButtonText: '确定',
cancelButtonText: '取消', // cancelButtonText: '取消',
type: 'warning' // type: 'warning'
}).then(() => { }).then(() => {
this.submitting = true // true this.submitting=true
this.$http({ this.$http({
url: this.$http.adornUrl('/manage/wxUserTags/delete/' + tagid), // URL url: this.$http.adornUrl('/manage/wxUserTags/delete/'+tagid),
method: 'post', // HTTPPOST method: 'post',
}).then(({ data }) => { }).then(({ data }) => {
if (data && data.code === 200) { if (data && data.code === 200) {
this.getWxUserTags(); // this.getWxUserTags();
this.$emit('change'); // change this.$emit('change');
} else { } else {
this.$message.error(data.msg) // this.$message.error(data.msg)
} }
this.submitting = false; // this.submitting=false;
}) })
}) })
}, },
//
showInput() { showInput() {
this.inputVisible = true; // this.inputVisible = true;
this.$nextTick(_ => { this.$nextTick(_ => {
this.$refs.saveTagInput.$refs.input.focus(); // this.$refs.saveTagInput.$refs.input.focus();
}); });
}, },
//
addTag() { addTag() {
let newTagName = this.inputValue; // let newTagName = this.inputValue;
this.saveTag(newTagName) // this.saveTag(newTagName)
this.inputVisible = false; // this.inputVisible = false;
this.inputValue = ''; // this.inputValue = '';
}, },
// editTag(tagid,orignName=''){
editTag(tagid, orignName=''){
this.$prompt('请输入新标签名称', '提示', { this.$prompt('请输入新标签名称', '提示', {
confirmButtonText: '确定', // confirmButtonText: '确定',
cancelButtonText: '取消', // cancelButtonText: '取消',
inputValue: orignName, // inputValue:orignName,
inputPattern: /^.{1,30}$/, // 1-30 inputPattern: /^.{1,30}$/,
inputErrorMessage: '名称1-30字符' // inputErrorMessage: '名称1-30字符'
}).then(({ value }) => { }).then(({ value }) => {
this.saveTag(value, tagid) // console.log(value)
this.saveTag(value,tagid)
}) })
}, },
// saveTag(name,tagid){
saveTag(name, tagid){
if(this.submitting){ if(this.submitting){
return // return
} }
this.submitting = true // true this.submitting=true
this.$http({ this.$http({
url: this.$http.adornUrl('/manage/wxUserTags/save'), // URL url: this.$http.adornUrl('/manage/wxUserTags/save'),
method: 'post', // HTTPPOST method: 'post',
data: this.$http.adornData({ data:this.$http.adornData({
id: tagid ? tagid : undefined, // tagid id : tagid?tagid:undefined,
name: name // name : name
}) })
}).then(({ data }) => { }).then(({ data }) => {
if (data && data.code === 200) { if (data && data.code === 200) {
this.getWxUserTags(); // this.getWxUserTags();
this.$emit('change'); // change this.$emit('change');
} else { } else {
this.$message.error(data.msg) // this.$message.error(data.msg)
} }
this.submitting = false; // this.submitting=false;
}) })
} }
} }
} }
</script>
<style scoped> <style scoped>
/* 面板样式 */
.panel { .panel {
flex: 1; /* 弹性布局,占满剩余空间 */ flex: 1;
} }
/* 标签和按钮样式 */ .el-tag,.button-new-tag {
.el-tag, .button-new-tag { margin: 5px;
margin: 5px; /* 外边距 */
} }
/* 输入框样式 */
.input-new-tag { .input-new-tag {
width: inherit; /* 宽度继承父元素 */ width: inherit;
} }
</style> </style>

@ -1,3 +1 @@
// 导出一个函数,该函数接收一个文件名作为参数
// 返回一个动态导入模块的函数
module.exports = file => () => import('@/views/' + file + '.vue') module.exports = file => () => import('@/views/' + file + '.vue')

@ -10,76 +10,75 @@ import http from '@/utils/httpRequest'
import { isURL } from '@/utils/validate' import { isURL } from '@/utils/validate'
import { clearLoginInfo } from '@/utils' import { clearLoginInfo } from '@/utils'
// 使用VueRouter插件
Vue.use(VueRouter) Vue.use(VueRouter)
// 动态导入视图组件的函数
const _import = require('./import-views') const _import = require('./import-views')
// 全局路由(无需嵌套上左右整体布局) // 全局路由(无需嵌套上左右整体布局)
const globalRoutes = [ const globalRoutes = [
{ path: '/404', component: () => import('@/views/common/404'), name: '404', meta: { title: '404未找到' } }, // 404页面路由 { path: '/404', component: () => import('@/views/common/404'), name: '404', meta: { title: '404未找到' } },
{ path: '/login', component: () => import('@/views/common/login'), name: 'login', meta: { title: '登录' } } // 登录页面路由 { path: '/login', component: () => import('@/views/common/login'), name: 'login', meta: { title: '登录' } }
] ]
// 主入口路由(需嵌套上左右整体布局) // 主入口路由(需嵌套上左右整体布局)
const mainRoutes = { const mainRoutes = {
path: '/', path: '/',
component: () => import('@/views/main'), component: () => import('@/views/main'),
name: 'main', name: 'main',
redirect: { name: 'home' }, redirect: { name: 'home' },
meta: { title: '主入口整体布局' }, meta: { title: '主入口整体布局' },
children: [ children: [
// 通过meta对象设置路由展示方式 // 通过meta对象设置路由展示方式
// 1. isTab: 是否通过tab展示内容, true: 是, false: 否 // 1. isTab: 是否通过tab展示内容, true: 是, false: 否
// 2. iframeUrl: 是否通过iframe嵌套展示内容, '以http[s]://开头': 是, '': 否 // 2. iframeUrl: 是否通过iframe嵌套展示内容, '以http[s]://开头': 是, '': 否
{ path: '/home', component: () => import('@/views/common/home'), name: 'home', meta: { title: '首页' } }, // 首页路由 // 提示: 如需要通过iframe嵌套展示内容, 但不通过tab打开, 请自行创建组件使用iframe处理!
{ path: '/theme', component: () => import('@/views/common/theme'), name: 'theme', meta: { title: '主题' } } // 主题页面路由 { path: '/home', component: () => import('@/views/common/home'), name: 'home', meta: { title: '首页' } },
], { path: '/theme', component: () => import('@/views/common/theme'), name: 'theme', meta: { title: '主题' } },
beforeEnter(to, from, next) { ],
// 检查用户是否已登录,如果未登录则重定向到登录页 beforeEnter(to, from, next) {
let token = Vue.cookie.get('token') let token = Vue.cookie.get('token')
if (!token || !/\S/.test(token)) { if (!token || !/\S/.test(token)) {
clearLoginInfo() clearLoginInfo()
next({ name: 'login' }) next({ name: 'login' })
}
next()
} }
next()
}
} }
// 创建VueRouter实例
const router = new VueRouter({ const router = new VueRouter({
mode: 'hash', // 使用hash模式 mode: 'hash',
scrollBehavior: () => ({ y: 0 }), // 滚动行为:切换路由时滚动到顶部 scrollBehavior: () => ({ y: 0 }),
isAddDynamicMenuRoutes: false, // 是否已经添加动态(菜单)路由 isAddDynamicMenuRoutes: false, // 是否已经添加动态(菜单)路由
routes: globalRoutes.concat(mainRoutes) // 合并全局路由和主入口路由 routes: globalRoutes.concat(mainRoutes)
}) })
// 全局前置守卫,用于处理动态菜单路由的添加
router.beforeEach((to, from, next) => { router.beforeEach((to, from, next) => {
// 如果已经添加了动态(菜单)路由或当前路由是全局路由,直接放行 // 添加动态(菜单)路由
if (router.options.isAddDynamicMenuRoutes || fnCurrentRouteType(to, globalRoutes) === 'global') { // 1. 已经添加 or 全局路由, 直接访问
// 2. 获取菜单列表, 添加并保存本地存储
if (router.options.isAddDynamicMenuRoutes || fnCurrentRouteType(to, globalRoutes) === 'global') {
next()
} else {
http({
url: http.adornUrl('/sys/menu/nav'),
method: 'get',
params: http.adornParams()
}).then(({ data }) => {
if (data && data.code === 200) {
fnAddDynamicMenuRoutes(data.menuList)
router.options.isAddDynamicMenuRoutes = true
sessionStorage.setItem('menuList', JSON.stringify(data.menuList || '[]'))
sessionStorage.setItem('permissions', JSON.stringify(data.permissions || '[]'))
next({ ...to, replace: true })
} else {
sessionStorage.setItem('menuList', '[]')
sessionStorage.setItem('permissions', '[]')
next() next()
} else { }
// 否则,请求菜单列表并添加动态(菜单)路由 }).catch((e) => {
http({ console.log(`%c${e} 请求菜单列表和权限失败,跳转至登录页!!`, 'color:blue')
url: http.adornUrl('/sys/menu/nav'), router.push({ name: 'login' })
method: 'get', })
params: http.adornParams() }
}).then(({ data }) => {
if (data && data.code === 200) {
fnAddDynamicMenuRoutes(data.menuList) // 添加动态(菜单)路由
router.options.isAddDynamicMenuRoutes = true // 标记为已添加动态(菜单)路由
next({ ...to, replace: true }) // 重新导航到当前路由,确保添加完动态路由后能正确显示页面
} else {
console.log(`%c${e} 请求菜单列表和权限失败,跳转至登录页!!`, 'color:blue') // 打印错误信息
router.push({ name: 'login' }) // 跳转到登录页
}
}).catch((e) => {
console.log(`%c${e} 请求菜单列表和权限失败,跳转至登录页!!`, 'color:blue') // 打印错误信息
router.push({ name: 'login' }) // 跳转到登录页
})
}
}) })
/** /**
@ -87,15 +86,15 @@ router.beforeEach((to, from, next) => {
* @param {*} route 当前路由 * @param {*} route 当前路由
*/ */
function fnCurrentRouteType(route, globalRoutes = []) { function fnCurrentRouteType(route, globalRoutes = []) {
var temp = [] var temp = []
for (var i = 0; i < globalRoutes.length; i++) { for (var i = 0; i < globalRoutes.length; i++) {
if (route.path === globalRoutes[i].path) { if (route.path === globalRoutes[i].path) {
return 'global' // 如果是全局路由,返回'global' return 'global'
} else if (globalRoutes[i].children && globalRoutes[i].children.length >= 1) { } else if (globalRoutes[i].children && globalRoutes[i].children.length >= 1) {
temp = temp.concat(globalRoutes[i].children) // 如果有子路由,添加到临时数组中 temp = temp.concat(globalRoutes[i].children)
}
} }
return temp.length >= 1 ? fnCurrentRouteType(route, temp) : 'main' // 递归判断,直到找到匹配的路由类型 }
return temp.length >= 1 ? fnCurrentRouteType(route, temp) : 'main'
} }
/** /**
@ -104,49 +103,52 @@ function fnCurrentRouteType(route, globalRoutes = []) {
* @param {*} routes 递归创建的动态(菜单)路由 * @param {*} routes 递归创建的动态(菜单)路由
*/ */
function fnAddDynamicMenuRoutes(menuList = [], routes = []) { function fnAddDynamicMenuRoutes(menuList = [], routes = []) {
var temp = [] var temp = []
for (var i = 0; i < menuList.length; i++) { for (var i = 0; i < menuList.length; i++) {
if (menuList[i].list && menuList[i].list.length >= 1) { if (menuList[i].list && menuList[i].list.length >= 1) {
temp = temp.concat(menuList[i].list) // 如果菜单项有子菜单,添加到临时数组中 temp = temp.concat(menuList[i].list)
} else if (menuList[i].url && /\S/.test(menuList[i].url)) { } else if (menuList[i].url && /\S/.test(menuList[i].url)) {
menuList[i].url = menuList[i].url.replace(/^\//, '') // 去掉URL前的斜杠 menuList[i].url = menuList[i].url.replace(/^\//, '')
var route = { var route = {
path: menuList[i].url.replace('/', '-'), // 将URL中的斜杠替换为短横线作为路径的一部分 path: menuList[i].url.replace('/', '-'),
component: null, // 初始化组件为空 component: null,
name: menuList[i].url.replace('/', '-'), // 将URL中的斜杠替换为短横线作为路由名称的一部分 name: menuList[i].url.replace('/', '-'),
meta: { meta: {
menuId: menuList[i].menuId, // 菜单ID menuId: menuList[i].menuId,
title: menuList[i].name, // 菜单名称 title: menuList[i].name,
isDynamic: true, // 标记为动态路由 isDynamic: true,
isTab: true, // 标记为标签页 isTab: true,
iframeUrl: '' // 初始化iframeUrl为空 iframeUrl: ''
}
}
// 如果URL以http[s]://开头通过iframe展示
if (isURL(menuList[i].url)) {
route['path'] = `i-${menuList[i].menuId}` // 修改路径为i-加上菜单ID
route['name'] = `i-${menuList[i].menuId}` // 修改名称为i-加上菜单ID
route['meta']['iframeUrl'] = menuList[i].url // 设置iframeUrl为菜单URL
} else {
try {
route['component'] = _import(`modules/${menuList[i].url}`) || null // 动态导入组件
} catch (e) { } // 如果导入失败,捕获异常但不做处理
}
routes.push(route) // 将路由添加到routes数组中
} }
}
// url以http[s]://开头, 通过iframe展示
if (isURL(menuList[i].url)) {
route['path'] = `i-${menuList[i].menuId}`
route['name'] = `i-${menuList[i].menuId}`
route['meta']['iframeUrl'] = menuList[i].url
} else {
try {
route['component'] = _import(`modules/${menuList[i].url}`) || null
// route['component'] = ()=>import(`@/views/modules/${menuList[i].url}.vue`) || null
} catch (e) { }
}
routes.push(route)
} }
if (temp.length >= 1) { }
fnAddDynamicMenuRoutes(temp, routes) // 如果临时数组中有数据,递归调用自身继续处理 if (temp.length >= 1) {
} else { fnAddDynamicMenuRoutes(temp, routes)
mainRoutes.name = 'main-dynamic' // 修改主入口路由的名称为main-dynamic } else {
mainRoutes.children = routes // 将动态生成的路由设置为主入口路由的子路由 mainRoutes.name = 'main-dynamic'
router.addRoutes([mainRoutes, { path: '*', redirect: { name: '404' } }]) // 添加动态路由和404重定向规则到路由器中 mainRoutes.children = routes
sessionStorage.setItem('dynamicMenuRoutes', JSON.stringify(mainRoutes.children || '')) // 将动态路由存储到sessionStorage中以便后续使用 router.addRoutes([
console.log('\n') mainRoutes,
console.log('%c!<-------------------- 动态(菜单)路由 s -------------------->', 'color:blue') // 打印动态路由开始标志 { path: '*', redirect: { name: '404' } }
console.log(mainRoutes.children) // 打印动态生成的路由信息 ])
console.log('%c!<-------------------- 动态(菜单)路由 e -------------------->', 'color:blue') // 打印动态路由结束标志 sessionStorage.setItem('dynamicMenuRoutes', JSON.stringify(mainRoutes.children || '[]'))
console.log('\n') console.log('\n')
} console.log('%c!<-------------------- 动态(菜单)路由 s -------------------->', 'color:blue')
console.log(mainRoutes.children)
console.log('%c!<-------------------- 动态(菜单)路由 e -------------------->', 'color:blue')
}
} }
export default router // 导出路由器实例 export default router

@ -1,14 +1,12 @@
export default { export default {
// 启用命名空间使得该模块的状态和getters、actions、mutations是注册在全局命名空间下的子模块 namespaced: true,
namespaced: true, state: {
state: { ARTICLE_TYPES: {
// 定义文章类型常量对象 1: '普通文章',
ARTICLE_TYPES: { 5: '帮助中心',
1: '普通文章', // 普通文章类型
5: '帮助中心', // 帮助中心类型
}
},
mutations: {
// 目前没有定义任何mutation
} }
},
mutations: {
}
} }

@ -1,7 +1,6 @@
import router from '@/router' import router from '@/router'
export default { export default {
// 启用命名空间使得该模块的状态和getters、actions、mutations是注册在全局命名空间下的子模块
namespaced: true, namespaced: true,
state: { state: {
// 页面文档可视高度(随窗口改变大小) // 页面文档可视高度(随窗口改变大小)
@ -12,60 +11,47 @@ export default {
sidebarLayoutSkin: 'dark', sidebarLayoutSkin: 'dark',
// 侧边栏, 折叠状态 // 侧边栏, 折叠状态
sidebarFold: false, sidebarFold: false,
// 侧边栏, 菜单列表 // 侧边栏, 菜单
menuList: [], menuList: [],
// 当前激活的菜单项名称
menuActiveName: '', menuActiveName: '',
// 内容区域是否需要刷新 // 内容, 是否需要刷新
contentIsNeedRefresh: false, contentIsNeedRefresh: false,
// 主入口标签页数组 // 主入口标签页
mainTabs: [], mainTabs: [],
// 当前激活的标签页名称
mainTabsActiveName: '' mainTabsActiveName: ''
}, },
mutations: { mutations: {
// 更新文档可视高度
updateDocumentClientHeight(state, height) { updateDocumentClientHeight(state, height) {
state.documentClientHeight = height state.documentClientHeight = height
}, },
// 更新导航条布局类型
updateNavbarLayoutType(state, type) { updateNavbarLayoutType(state, type) {
state.navbarLayoutType = type state.navbarLayoutType = type
}, },
// 更新侧边栏布局皮肤
updateSidebarLayoutSkin(state, skin) { updateSidebarLayoutSkin(state, skin) {
state.sidebarLayoutSkin = skin state.sidebarLayoutSkin = skin
}, },
// 更新侧边栏折叠状态
updateSidebarFold(state, fold) { updateSidebarFold(state, fold) {
state.sidebarFold = fold state.sidebarFold = fold
}, },
// 更新菜单列表
updateMenuList(state, list) { updateMenuList(state, list) {
state.menuList = list state.menuList = list
}, },
// 更新当前激活的菜单项名称
updateMenuActiveName(state, name) { updateMenuActiveName(state, name) {
state.menuActiveName = name state.menuActiveName = name
}, },
// 更新内容区域是否需要刷新
updateContentIsNeedRefresh(state, status) { updateContentIsNeedRefresh(state, status) {
state.contentIsNeedRefresh = status state.contentIsNeedRefresh = status
}, },
// 更新主入口标签页数组
updateMainTabs(state, tabs) { updateMainTabs(state, tabs) {
state.mainTabs = tabs state.mainTabs = tabs
}, },
// 更新当前激活的标签页名称
updateMainTabsActiveName(state, name) { updateMainTabsActiveName(state, name) {
state.mainTabsActiveName = name state.mainTabsActiveName = name
}, },
// 移除指定的标签页
removeTab(state, tabName) { removeTab(state, tabName) {
// 过滤掉要删除的标签页
state.mainTabs = state.mainTabs.filter(item => item.name !== tabName) state.mainTabs = state.mainTabs.filter(item => item.name !== tabName)
if (state.mainTabs.length >= 1) { if (state.mainTabs.length >= 1) {
// 如果当前选中的标签页被删除,则跳转到最后一个标签页 // 当前选中tab被删除
if (tabName === state.mainTabsActiveName) { if (tabName === state.mainTabsActiveName) {
var tab = state.mainTabs[state.mainTabs.length - 1] var tab = state.mainTabs[state.mainTabs.length - 1]
router.push({ name: tab.name, query: tab.query, params: tab.params }, () => { router.push({ name: tab.name, query: tab.query, params: tab.params }, () => {
@ -73,12 +59,10 @@ export default {
}) })
} }
} else { } else {
// 如果没有剩余的标签页,重置菜单并跳转到首页
state.menuActiveName = '' state.menuActiveName = ''
router.push({ name: 'home' }) router.push({ name: 'home' })
} }
}, },
// 关闭当前激活的标签页
closeCurrentTab(state) { closeCurrentTab(state) {
this.commit('common/removeTab', state.mainTabsActiveName) this.commit('common/removeTab', state.mainTabsActiveName)
} }

@ -1,39 +1,32 @@
// 导出一个默认的模块对象
export default { export default {
// 启用命名空间使得该模块的状态和getters、actions、mutations是注册在全局命名空间下的子模块
namespaced: true, namespaced: true,
// 定义模块的初始状态
state: { state: {
// 定义微信消息类型的映射关系 XmlMsgType:{
XmlMsgType: { "text":"文字",
"text": "文字", // 文本消息类型 "image":"图片",
"image": "图片", // 图片消息类型 "voice":"语音",
"voice": "语音", // 语音消息类型 "shortvideo":"短视频",
"shortvideo": "短视频", // 短视频消息类型 "video":"视频",
"video": "视频", // 视频消息类型 "news":"图文",
"news": "图文", // 图文消息类型 "music":"音乐",
"music": "音乐", // 音乐消息类型 "location":"位置",
"location": "位置", // 位置消息类型 "link":"链接",
"link": "链接", // 链接消息类型 "event":"事件",
"event": "事件", // 事件消息类型 "transfer_customer_service":"转客服"
"transfer_customer_service": "转客服" // 转接客服消息类型
}, },
// 定义客服消息类型的映射关系
KefuMsgType: { KefuMsgType: {
"text": "文本消息", // 文本消息类型 "text": "文本消息",
"image": "图片消息", // 图片消息类型 "image": "图片消息",
"voice": "语音消息", // 语音消息类型 "voice": "语音消息",
"video": "视频消息", // 视频消息类型 "video": "视频消息",
"music": "音乐消息", // 音乐消息类型 "music": "音乐消息",
"news": "文章链接", // 文章链接消息类型 "news": "文章链接",
"mpnews": "公众号图文消息", // 公众号图文消息类型 "mpnews": "公众号图文消息",
"wxcard": "卡券消息", // 卡券消息类型 "wxcard": "卡券消息",
"miniprogrampage": "小程序消息", // 小程序消息类型 "miniprogrampage": "小程序消息",
"msgmenu": "菜单消息" // 菜单消息类型 "msgmenu": "菜单消息"
} }
}, },
// 定义用于修改状态的 mutations目前为空
mutations: { mutations: {
} }

@ -1,23 +1,15 @@
// 导出一个默认的模块对象
export default { export default {
// 启用命名空间使得该模块的状态和getters、actions、mutations是注册在全局命名空间下的子模块 namespaced: true,
namespaced: true, state: {
id: 0,
// 定义模块的初始状态 name: ''
state: { },
id: 0, // 初始化 id 为 0 mutations: {
name: '' // 初始化 name 为空字符串 updateId(state, id) {
state.id = id
}, },
updateName(state, name) {
// 定义用于修改状态的 mutations state.name = name
mutations: {
// 更新 id 的 mutation
updateId(state, id) {
state.id = id; // 将传入的 id 赋值给 state 中的 id
},
// 更新 name 的 mutation
updateName(state, name) {
state.name = name; // 将传入的 name 赋值给 state 中的 name
}
} }
}
} }

Loading…
Cancel
Save