-
BINsrc/assets/images/dialog_right_top.png
-
BINsrc/assets/images/largeScreen/bg.png
-
BINsrc/assets/images/largeScreen/device-1.png
-
BINsrc/assets/images/largeScreen/device-2.png
-
BINsrc/assets/images/largeScreen/device-3.png
-
BINsrc/assets/images/largeScreen/device-4.png
-
BINsrc/assets/images/largeScreen/device-5.png
-
BINsrc/assets/images/largeScreen/device-6.png
-
BINsrc/assets/images/largeScreen/item-left.png
-
BINsrc/assets/images/largeScreen/item-right.png
-
BINsrc/assets/images/largeScreen/top-title.png
-
BINsrc/assets/images/largeScreen/top.png
-
BINsrc/assets/images/left_bottom.png
-
BINsrc/assets/images/left_top.png
-
BINsrc/assets/images/login/dl-bg.png
-
BINsrc/assets/images/login/dl-bgt.png
-
BINsrc/assets/images/login/dl-logo.png
-
BINsrc/assets/images/logo.png
-
BINsrc/assets/images/panel-n.png
-
BINsrc/assets/images/panel-y.png
-
BINsrc/assets/images/pop-message.png
-
BINsrc/assets/images/pop_arrow.png
-
BINsrc/assets/images/pop_sanjiao.png
-
BINsrc/assets/images/right_bottom.png
-
BINsrc/assets/images/right_top.png
-
BINsrc/assets/images/sidebar_bg.png
-
BINsrc/assets/images/system/logo.png
-
BINsrc/assets/images/system/xt-gdx.png
-
BINsrc/assets/images/system/xt-gdz.png
-
BINsrc/assets/images/tab_archives_logo.png
-
BINsrc/assets/images/tab_collate_logo.png
-
BINsrc/assets/images/tab_fullview_logo.png
-
BINsrc/assets/images/tab_img.png
-
BINsrc/assets/images/tab_left.png
-
BINsrc/assets/images/tab_left_active.png
-
BINsrc/assets/images/tab_read_logo.png
-
BINsrc/assets/images/tab_right.png
-
BINsrc/assets/images/tab_right_active.png
-
BINsrc/assets/images/table_head_bg.png
-
BINsrc/assets/images/warehouse_arrow_left.png
-
BINsrc/assets/images/warehouse_arrow_right.png
-
BINsrc/assets/images/warehouse_tab_active.png
-
BINsrc/assets/images/warehouse_tab_bg.png
-
769src/assets/styles/archives-manage.scss
-
80src/assets/styles/element-ui.scss
-
31src/assets/styles/element-variables.scss
-
46src/assets/styles/font-some.css
-
290src/assets/styles/index.scss
-
86src/assets/styles/mixin.scss
-
292src/assets/styles/sidebar.scss
-
48src/assets/styles/transition.scss
-
45src/assets/styles/variables.scss
-
1211src/assets/styles/yxk-admin.scss
-
104src/components/Breadcrumb/index.vue
-
228src/components/Crud/CRUD.operation.vue
-
18src/components/Crud/Pagination.vue
-
28src/components/Crud/RR.operation.vue
-
103src/components/Crud/UD.operation.vue
-
869src/components/Crud/crud.js
-
45src/components/DateRangePicker/index.vue
-
29src/components/Dict/Dict.js
-
29src/components/Dict/index.js
-
16src/components/Doc/index.vue
-
106src/components/Echarts/BarChart.vue
-
438src/components/Echarts/Category.vue
-
120src/components/Echarts/Funnel.vue
-
74src/components/Echarts/Gauge.vue
-
101src/components/Echarts/Graph.vue
-
105src/components/Echarts/HeatMap.vue
-
96src/components/Echarts/Line3D.vue
-
84src/components/Echarts/PieChart.vue
-
149src/components/Echarts/Point.vue
-
120src/components/Echarts/RadarChart.vue
-
149src/components/Echarts/Rich.vue
-
100src/components/Echarts/Sankey.vue
-
143src/components/Echarts/Scatter.vue
-
107src/components/Echarts/Sunburst.vue
-
148src/components/Echarts/ThemeRiver.vue
-
192src/components/Echarts/WordCloud.vue
-
54src/components/GithubCorner/index.vue
-
44src/components/Hamburger/index.vue
-
188src/components/HeaderSearch/index.vue
-
68src/components/IconSelect/index.vue
-
11src/components/IconSelect/requireIcons.js
-
30src/components/Iframe/index.vue
-
78src/components/JavaEdit/index.vue
-
101src/components/Pagination/index.vue
-
140src/components/PanThumb/index.vue
-
3src/components/ParentView/index.vue
-
13src/components/Permission/index.js
-
21src/components/Permission/permission.js
-
149src/components/RightPanel/index.vue
-
60src/components/Screenfull/index.vue
-
57src/components/SizeSelect/index.vue
-
62src/components/SvgIcon/index.vue
-
165src/components/ThemePicker/index.vue
-
138src/components/UploadExcel/index.vue
-
81src/components/YamlEdit/index.vue
-
679src/components/jsmpeg-player/jsmpeg-player.vue
-
3src/components/jsmpeg-player/jsmpeg/index.js
|
After Width: 235 | Height: 124 | Size: 2.1 KiB |
|
After Width: 1920 | Height: 1080 | Size: 332 KiB |
|
After Width: 92 | Height: 102 | Size: 5.0 KiB |
|
After Width: 77 | Height: 122 | Size: 4.8 KiB |
|
After Width: 87 | Height: 122 | Size: 4.5 KiB |
|
After Width: 57 | Height: 116 | Size: 3.6 KiB |
|
After Width: 72 | Height: 118 | Size: 7.2 KiB |
|
After Width: 73 | Height: 99 | Size: 4.2 KiB |
|
After Width: 72 | Height: 24 | Size: 1.5 KiB |
|
After Width: 72 | Height: 24 | Size: 1.4 KiB |
|
After Width: 1921 | Height: 130 | Size: 31 KiB |
|
After Width: 1921 | Height: 130 | Size: 23 KiB |
|
After Width: 124 | Height: 63 | Size: 1.1 KiB |
|
After Width: 124 | Height: 63 | Size: 933 B |
|
After Width: 1920 | Height: 1080 | Size: 1.2 MiB |
|
After Width: 925 | Height: 732 | Size: 258 KiB |
|
After Width: 272 | Height: 49 | Size: 6.9 KiB |
|
After Width: 1024 | Height: 1024 | Size: 8.0 KiB |
|
After Width: 165 | Height: 710 | Size: 23 KiB |
|
After Width: 165 | Height: 710 | Size: 24 KiB |
|
After Width: 89 | Height: 20 | Size: 1.1 KiB |
|
After Width: 15 | Height: 7 | Size: 1.1 KiB |
|
After Width: 180 | Height: 14 | Size: 1.7 KiB |
|
After Width: 124 | Height: 63 | Size: 997 B |
|
After Width: 124 | Height: 63 | Size: 968 B |
|
After Width: 300 | Height: 609 | Size: 74 KiB |
|
After Width: 172 | Height: 31 | Size: 4.5 KiB |
|
After Width: 130 | Height: 43 | Size: 2.2 KiB |
|
After Width: 386 | Height: 544 | Size: 3.1 KiB |
|
After Width: 72 | Height: 52 | Size: 3.9 KiB |
|
After Width: 72 | Height: 52 | Size: 3.9 KiB |
|
After Width: 72 | Height: 52 | Size: 4.2 KiB |
|
After Width: 185 | Height: 56 | Size: 1.5 KiB |
|
After Width: 33 | Height: 86 | Size: 1.4 KiB |
|
After Width: 33 | Height: 86 | Size: 1.3 KiB |
|
After Width: 72 | Height: 52 | Size: 4.0 KiB |
|
After Width: 33 | Height: 86 | Size: 1.3 KiB |
|
After Width: 33 | Height: 86 | Size: 1.3 KiB |
|
After Width: 457 | Height: 30 | Size: 1.1 KiB |
|
After Width: 36 | Height: 12 | Size: 854 B |
|
After Width: 36 | Height: 12 | Size: 904 B |
|
After Width: 258 | Height: 88 | Size: 13 KiB |
|
After Width: 258 | Height: 88 | Size: 2.9 KiB |
@ -0,0 +1,769 @@ |
|||
@import 'variables'; |
|||
@import 'mixin'; |
|||
|
|||
.head-archives{ |
|||
padding: 0 0 20px 0; |
|||
.archives-crud{ |
|||
float: left; |
|||
} |
|||
.archives-recycle{ |
|||
float: left; |
|||
} |
|||
.head-search{ |
|||
float: left; |
|||
margin-left: 10px; |
|||
margin-bottom: 0 !important; |
|||
.filter-item{ |
|||
margin-right: 5px !important; |
|||
} |
|||
} |
|||
.archives-handler-btn{ |
|||
float: right; |
|||
} |
|||
} |
|||
|
|||
.input-prepend{ |
|||
position: relative; |
|||
z-index: 99; |
|||
.el-input__inner { |
|||
padding-left: 80px; |
|||
background-color: transparent; |
|||
} |
|||
.el-input-group__prepend { |
|||
position: absolute; |
|||
left: 0; |
|||
top: 0; |
|||
color: #fff; |
|||
background-color: transparent; |
|||
border: none; |
|||
height: 30px; |
|||
line-height: 30px; |
|||
.el-input__inner { |
|||
padding-left: 15px !important; |
|||
color: $mainColor !important; |
|||
} |
|||
.el-input__inner:hover, |
|||
.el-input__inner:focus{ |
|||
color: $mainColor; |
|||
} |
|||
.el-select__caret{ |
|||
color: $mainColor; |
|||
} |
|||
} |
|||
} |
|||
.packing-head{ |
|||
display: flex; |
|||
justify-content: space-between; |
|||
.el-input__inner { |
|||
padding-left: 90px; |
|||
} |
|||
} |
|||
.container-main{ |
|||
.left-tree-item{ |
|||
margin-bottom: 20px; |
|||
min-height: calc(100vh/2 - 105px); |
|||
&:last-child{ |
|||
margin-bottom: 0; |
|||
} |
|||
} |
|||
|
|||
.tree-title{ |
|||
height: 40px; |
|||
line-height: 40px; |
|||
text-align: center; |
|||
color: $mainColor; |
|||
background-color: #02255F; |
|||
} |
|||
} |
|||
.archives-warp{ |
|||
margin-bottom: 20px; |
|||
} |
|||
.archives-top{ |
|||
display: flex; |
|||
justify-content: right; |
|||
margin-bottom: 10px; |
|||
.el-checkbox .el-checkbox__label{ |
|||
color: #fff; |
|||
} |
|||
} |
|||
.archives-right-list{ |
|||
position: relative; |
|||
} |
|||
.archives-fixed-top{ |
|||
position: absolute; |
|||
right: 0; |
|||
top: 6px; |
|||
margin-bottom: 0; |
|||
} |
|||
.crud-opts{ |
|||
justify-content: space-between; |
|||
} |
|||
|
|||
.archives-handler-btn{ |
|||
.el-button{ |
|||
padding: 0 13px 0 3px; |
|||
span{ |
|||
margin-left: 5px; |
|||
} |
|||
&.packing-btn{ |
|||
border-color: $arcPurple; |
|||
background-color: $arcPurple; |
|||
&.is-disabled{ |
|||
border-color:#2B1D70; |
|||
background-color: #2B1D70; |
|||
} |
|||
} |
|||
&.part-btn{ |
|||
border-color: $arcCyan; |
|||
background-color: $arcCyan; |
|||
&.is-disabled{ |
|||
border-color:#075E6C; |
|||
background-color: #075E6C; |
|||
} |
|||
} |
|||
&.warehousing-btn{ |
|||
border-color: $arcYellow; |
|||
background-color: $arcYellow; |
|||
&.is-disabled{ |
|||
border-color:#7E4021; |
|||
background-color: #7E4021; |
|||
} |
|||
} |
|||
&.lending-btn{ |
|||
border-color: $arcRed; |
|||
background-color: $arcRed; |
|||
&.is-disabled{ |
|||
border-color:#7A2831; |
|||
background-color: #7A2831; |
|||
} |
|||
} |
|||
&.binding-btn{ |
|||
border-color: $arcGreen; |
|||
background-color: $arcGreen; |
|||
&.is-disabled{ |
|||
border-color:#0D5649; |
|||
background-color: #0D5649; |
|||
} |
|||
} |
|||
&.is-disabled{ |
|||
color: #666; |
|||
} |
|||
} |
|||
.iconfont{ |
|||
line-height: 30px; |
|||
} |
|||
} |
|||
|
|||
.archives-table, |
|||
.base-info{ |
|||
td.el-table__cell .row-state{ |
|||
display: block; |
|||
height: 26px; |
|||
line-height: 24px; |
|||
padding: 0 14px; |
|||
margin: 0 6px; |
|||
border-width: 1px; |
|||
border-style: solid; |
|||
border-radius: 26px; |
|||
} |
|||
.row-packing{ |
|||
color: $arcPurple; |
|||
border-color: $arcPurple; |
|||
&.state-active{ |
|||
color: #fff; |
|||
background-color: $arcPurple; |
|||
} |
|||
} |
|||
.row-warehousing{ |
|||
color: $arcYellow; |
|||
border-color: $arcYellow; |
|||
&.state-active{ |
|||
color: #fff; |
|||
background-color: $arcYellow; |
|||
} |
|||
} |
|||
.row-lending{ |
|||
color: $arcRed; |
|||
border-color: $arcRed; |
|||
&.state-active{ |
|||
color: #fff; |
|||
background-color: $arcRed; |
|||
} |
|||
} |
|||
.row-binding{ |
|||
color: $arcGreen; |
|||
border-color: $arcGreen; |
|||
&.state-active{ |
|||
color: #fff; |
|||
background-color: $arcGreen; |
|||
} |
|||
} |
|||
.is-scrolling-left, |
|||
.is-scrolling-middle, |
|||
.is-scrolling-right{ |
|||
max-height: calc(100vh - 434px) !important; |
|||
} |
|||
} |
|||
.base-info .row-state{ |
|||
width: 68px; |
|||
height: 26px; |
|||
line-height: 24px; |
|||
text-align: center; |
|||
margin-top: -6px; |
|||
border-width: 1px; |
|||
border-style: solid; |
|||
border-radius: 26px; |
|||
} |
|||
|
|||
.archives-table.el-table .el-table__fixed-right{ |
|||
background-color: $boxBg !important; |
|||
box-shadow: -5px 5px 10px 1px rgba(15,164,222,0.16); |
|||
} |
|||
|
|||
// archives - tab |
|||
.archives-tab{ |
|||
position: relative; |
|||
display: flex; |
|||
flex-direction: row; |
|||
padding: 0 35px; |
|||
font-size: 16px; |
|||
border-bottom: 1px solid $mainColor; |
|||
z-index: 1001; |
|||
li{ |
|||
padding: 22px 14px 14px 14px; |
|||
color: $mainColor; |
|||
cursor: pointer; |
|||
&.active{ |
|||
position: relative; |
|||
color: #fff; |
|||
&::after{ |
|||
content: ""; |
|||
position: absolute; |
|||
left: 0; |
|||
bottom: -1px; |
|||
width: 100%; |
|||
height: 3px; |
|||
border-radius: 3px; |
|||
background-color: #fff; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
// 上传附件 |
|||
.upload-dialog{ |
|||
.el-dialog{ |
|||
width: 940px; |
|||
.el-dialog__body{ |
|||
padding: 20px 0 30px 0; |
|||
} |
|||
} |
|||
} |
|||
.upload-file{ |
|||
position: relative; |
|||
z-index: 1001; |
|||
.upload-curd{ |
|||
display: flex; |
|||
flex-direction: row; |
|||
margin: 0 32px 20px 32px; |
|||
} |
|||
.upload-demo{ |
|||
position: relative; |
|||
margin-right: 10px; |
|||
.el-upload-list{ |
|||
display: none; |
|||
position: absolute; |
|||
left: 0; |
|||
bottom: 0; |
|||
} |
|||
} |
|||
} |
|||
.screenshot{ |
|||
display: block; |
|||
margin: 0 auto; |
|||
object-fit: cover; |
|||
} |
|||
.file-down, |
|||
.packing-handle-btn, |
|||
.packing-recall-btn{ |
|||
display: block; |
|||
width: 66px; |
|||
height: 28px; |
|||
line-height: 28px; |
|||
padding: 0; |
|||
color: #fff; |
|||
border-radius: 2px; |
|||
margin: 0 auto; |
|||
&::before{ |
|||
margin-right: 5px; |
|||
} |
|||
} |
|||
.file-down{ |
|||
padding: 0 !important; |
|||
background-color: $mainColor; |
|||
border-color: $mainColor; |
|||
} |
|||
.packing-handle-btn{ |
|||
background-color: $arcPurple; |
|||
border-color: $arcPurple; |
|||
} |
|||
.packing-recall-btn{ |
|||
background-color: $arcRed; |
|||
border-color: $arcRed; |
|||
} |
|||
|
|||
.drag-tip { |
|||
display: block; |
|||
padding-left: 20px; |
|||
padding-bottom: 10px; |
|||
font-style: normal; |
|||
font-weight: bold; |
|||
color: #fff; |
|||
} |
|||
|
|||
// 档案详情 |
|||
.base-info{ |
|||
padding: 20px 20px 0 60px; |
|||
color: #fff; |
|||
.base-info-item{ |
|||
display: flex; |
|||
flex-direction: row; |
|||
margin-bottom: 20px; |
|||
span{ |
|||
display: block; |
|||
width: 160px; |
|||
margin-right: 5px; |
|||
text-align: right; |
|||
color: #3A99FD; |
|||
} |
|||
} |
|||
} |
|||
// 元数据 |
|||
.hljs{ |
|||
padding: 0 30px; |
|||
color: #fff !important; |
|||
background-color: transparent !important; |
|||
font-family: "Sans Mono", "Consolas", "Courier", monospace; |
|||
font-size: 12px; |
|||
.hljs-attribute{ |
|||
display: inline-block; |
|||
margin: 2px 0 !important; |
|||
} |
|||
} |
|||
|
|||
.selct-data-head{ |
|||
color: #fff; |
|||
line-height: 30px; |
|||
} |
|||
|
|||
// 绑定标签 |
|||
.bindingDialog{ |
|||
.el-dialog{ |
|||
width: 720px; |
|||
} |
|||
.el-dialog__body{ |
|||
padding: 35px 35px 58px 35px; |
|||
} |
|||
} |
|||
.rebinding { |
|||
display: flex; |
|||
justify-content: space-between; |
|||
padding: 50px 65px 35px 65px; |
|||
span{ |
|||
display: block; |
|||
width: 60px; |
|||
line-height: 36px; |
|||
color: #3A99FD; |
|||
} |
|||
.el-input { |
|||
.el-input__inner{ |
|||
font-size: 14px; |
|||
height: 36px; |
|||
line-height: 36px; |
|||
color: #fff; |
|||
border: 1px solid #3A99FD; |
|||
background-color: transparent; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.binding-flow{ |
|||
.step-item{ |
|||
position: relative; |
|||
display: flex; |
|||
justify-content: space-between; |
|||
margin-bottom: 10px; |
|||
z-index: 1; |
|||
&::before{ |
|||
content: ""; |
|||
position: absolute; |
|||
left: 15px; |
|||
top: 10px; |
|||
width: 1px; |
|||
height: 100%; |
|||
background-color: #3A99FD; |
|||
z-index: 1; |
|||
} |
|||
&:last-child::before{ |
|||
display: none; |
|||
} |
|||
} |
|||
.step-left-num{ |
|||
position: relative; |
|||
display: block; |
|||
width: 30px; |
|||
height: 30px; |
|||
line-height: 30px; |
|||
border-radius: 50%; |
|||
font-size: 16px; |
|||
text-align: center; |
|||
color: #fff; |
|||
border: 1px solid $mainColor; |
|||
background-color: $boxBg; |
|||
z-index: 4; |
|||
&.step-active{ |
|||
background-color: $mainColor; |
|||
} |
|||
&.step-loading{ |
|||
&::before, |
|||
&::after{ |
|||
content: ""; |
|||
position: absolute; |
|||
left: 50%; |
|||
top: 50%; |
|||
width: 40px; |
|||
height: 40px; |
|||
border-radius: 50%; |
|||
border: 1px solid #13439E; |
|||
box-shadow: inset 0px 0px 8px 1px #13439E; |
|||
margin: -20px 0 0 -20px; |
|||
z-index: 1; |
|||
} |
|||
&::before{ |
|||
animation: halo 2s linear 0.5s infinite; |
|||
} |
|||
&::after{ |
|||
animation: halo 2s linear 1.5s infinite; |
|||
} |
|||
} |
|||
} |
|||
// 晕开效果 |
|||
@keyframes halo { |
|||
0% { |
|||
transform: scale(1); |
|||
-webkit-transform: scale(1); |
|||
opacity: 0.0; |
|||
} |
|||
25% { |
|||
transform: scale(1); |
|||
-webkit-transform: scale(1); |
|||
opacity: 0.1; |
|||
} |
|||
50% { |
|||
transform: scale(1); |
|||
-webkit-transform: scale(1); |
|||
opacity: 0.3; |
|||
} |
|||
75% { |
|||
transform: scale(1.2); |
|||
-webkit-transform: scale(1.2); |
|||
opacity: 0.5; |
|||
} |
|||
100% { |
|||
transform: scale(1.5); |
|||
-webkit-transform: scale(1.5); |
|||
opacity: 0.0; |
|||
} |
|||
} |
|||
.step-right-cont{ |
|||
flex: 1; |
|||
margin-left: 12px; |
|||
.step-title{ |
|||
line-height: 30px; |
|||
color: $mainColor; |
|||
span{ |
|||
padding-left: 10px; |
|||
font-weight: bold; |
|||
color: #fff; |
|||
} |
|||
} |
|||
.step-tip{ |
|||
padding: 0 10px; |
|||
height: 40px; |
|||
line-height: 40px; |
|||
color: #13439E; |
|||
background-color: #02255F; |
|||
border-radius: 4px; |
|||
&.tip-active{ |
|||
color: $mainColor; |
|||
} |
|||
&.tip-error{ |
|||
color: #EF3147; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
// 分卷装盒 |
|||
.partPackingDialog{ |
|||
.el-dialog{ |
|||
width: 950px !important; |
|||
position: absolute; |
|||
left: 50%; |
|||
top: 50%; |
|||
transform: translate(-50%, -50%); |
|||
margin-top: 2vh !important; |
|||
} |
|||
.el-dialog__body{ |
|||
padding: 0; |
|||
} |
|||
.dialog-footer{ |
|||
margin: 20px auto 0 auto; |
|||
padding-bottom: 20px; |
|||
} |
|||
.packing-head{ |
|||
border-bottom: 1px solid $mainColor; |
|||
.head-search{ |
|||
margin-bottom: 0; |
|||
} |
|||
} |
|||
} |
|||
.part-packing-cont{ |
|||
display: flex; |
|||
flex-direction: row; |
|||
flex-wrap: wrap; |
|||
justify-content: space-between; |
|||
} |
|||
.part-packing-item{ |
|||
width: calc(100%/2 - 10px); |
|||
.part-packing-title{ |
|||
padding: 0 30px; |
|||
height: 40px; |
|||
line-height: 40px; |
|||
font-size: 16px; |
|||
font-weight: normal; |
|||
color: #fff; |
|||
} |
|||
.el-table{ |
|||
overflow-x: hidden; |
|||
overflow-y: auto; |
|||
border: 2px solid #02255f; |
|||
border-top: none; |
|||
.el-table__body-wrapper{ |
|||
background-color: $boxBg; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.item-content{ |
|||
max-height: calc(100vh - 410px); |
|||
overflow: hidden; |
|||
overflow-y: scroll; |
|||
} |
|||
|
|||
.upload-btn{ |
|||
position: relative; |
|||
margin-right: 10px; |
|||
overflow: hidden; |
|||
#upFile{ |
|||
position: absolute; |
|||
left: 0; |
|||
top: 0; |
|||
opacity: 0; |
|||
height: 34px; |
|||
} |
|||
} |
|||
|
|||
// 借阅管理 |
|||
.el-dialog .el-dialog__body{ |
|||
.el-button{ |
|||
background-color: #3A99FD; |
|||
border-color: #3A99FD; |
|||
} |
|||
.el-button.is-disabled, |
|||
.el-button.is-disabled:hover, |
|||
.el-button.is-disabled:focus{ |
|||
background-color: #02255F; |
|||
color: #13439E; |
|||
border-color: #02255F; |
|||
} |
|||
} |
|||
|
|||
.crud-opts { |
|||
display: inline-block; |
|||
} |
|||
|
|||
.iconfont::before { |
|||
margin-right: 5px; |
|||
} |
|||
|
|||
.cell-lend { |
|||
display: inline-block; |
|||
height: 26px; |
|||
line-height: 26px; |
|||
border-radius: 13px; |
|||
text-align: center; |
|||
} |
|||
|
|||
.no-lend { |
|||
color: $arcRed; |
|||
border: 1px solid $arcRed; |
|||
} |
|||
.wait-lend{ |
|||
color: $arcYellow; |
|||
border: 1px solid $arcYellow; |
|||
} |
|||
.have-lend { |
|||
color: #fff; |
|||
background-color: $arcRed; |
|||
} |
|||
|
|||
.other-lend { |
|||
color: $arcRed; |
|||
border: 1px solid $arcRed; |
|||
position: relative; |
|||
|
|||
&::after { |
|||
content: ''; |
|||
display: block; |
|||
height: 2px; |
|||
width: 20px; |
|||
background-color: $arcRed; |
|||
position: absolute; |
|||
left: 50%; |
|||
top: 50%; |
|||
transform: translate(-50%, -50%); |
|||
} |
|||
} |
|||
|
|||
.has-return{ |
|||
color: #fff; |
|||
border: 1px solid $arcGreen; |
|||
background-color: $arcGreen; |
|||
} |
|||
|
|||
.clear { |
|||
border-radius: 13px; |
|||
width: 80px; |
|||
height: 26px; |
|||
line-height: 26px; |
|||
display: inline-block; |
|||
text-align: center; |
|||
} |
|||
|
|||
.no-clear .clear { |
|||
color: $arcYellow; |
|||
border: 1px solid $arcYellow; |
|||
} |
|||
|
|||
.have-clear .clear { |
|||
color: $arcGreen; |
|||
border: 1px solid $arcGreen; |
|||
} |
|||
|
|||
.fail-clear .clear { |
|||
color: $arcRed; |
|||
border: 1px solid $arcRed; |
|||
} |
|||
.other-clear .clear { |
|||
color: $arcCyan; |
|||
border: 1px solid $arcCyan; |
|||
} |
|||
.error-clear-bg .clear{ |
|||
color: #fff; |
|||
background-color: $arcRed; |
|||
} |
|||
.have-clear-bg .clear{ |
|||
color: #fff; |
|||
background-color: $arcGreen; |
|||
} |
|||
.no-clear-bg .clear{ |
|||
color: #fff; |
|||
background-color: $arcYellow; |
|||
} |
|||
|
|||
//3D库房 |
|||
.iframe_box { |
|||
width: 100%; |
|||
height: calc(100vh - 285px); |
|||
} |
|||
|
|||
.warehouse { |
|||
display: flex; |
|||
max-height: calc(100vh - 184px); |
|||
overflow: hidden; |
|||
|
|||
.warehouse-left { |
|||
flex: 1; |
|||
} |
|||
|
|||
.warehouse-right { |
|||
width: 458px; |
|||
max-height: calc(100vh - 192px); |
|||
} |
|||
} |
|||
|
|||
.warehose-el-table .el-table__header-wrapper { |
|||
box-shadow: inset 0px 0px 6px 1px $mainColor; |
|||
background: none !important; |
|||
} |
|||
|
|||
.warehose-el-table .el-table__header .el-table__cell { |
|||
padding: 0; |
|||
height: 30px; |
|||
background: transparent; |
|||
.cell { |
|||
font-size: 14px; |
|||
} |
|||
} |
|||
|
|||
.light-blue { |
|||
background-color: #011E4F !important; |
|||
} |
|||
|
|||
.el-tag.el-tag--info { |
|||
height: 26px; |
|||
line-height: 26px; |
|||
background-color: #13439E; |
|||
border: none; |
|||
color: #fff; |
|||
} |
|||
|
|||
.el-tag.el-tag--info .el-tag__close { |
|||
background-color: #fff; |
|||
} |
|||
|
|||
//出入库 |
|||
.dpflex { |
|||
display: flex; |
|||
justify-content: space-between; |
|||
} |
|||
|
|||
.orange-btn { |
|||
width: 76px; |
|||
height: 30px; |
|||
background-color: $arcYellow; |
|||
border: none; |
|||
&.el-button.is-disabled, |
|||
&.el-button.is-disabled:hover { |
|||
background-color: #7E4021; |
|||
color: #666; |
|||
} |
|||
} |
|||
|
|||
.green-btn { |
|||
width: 106px; |
|||
height: 30px; |
|||
background-color: $arcGreen; |
|||
border: none; |
|||
&.el-button.is-disabled, |
|||
&.el-button.is-disabled:hover { |
|||
background-color: #0D5649; |
|||
color: #666; |
|||
} |
|||
} |
|||
//其他 |
|||
.delMsg{ |
|||
color: #fff; |
|||
font-size: 16px; |
|||
} |
|||
@ -0,0 +1,80 @@ |
|||
// cover some element-ui styles |
|||
|
|||
.el-breadcrumb__inner, |
|||
.el-breadcrumb__inner a { |
|||
color: #339CFF; |
|||
font-weight: 400 !important; |
|||
} |
|||
|
|||
.el-upload { |
|||
input[type="file"] { |
|||
display: none !important; |
|||
} |
|||
} |
|||
|
|||
.el-upload__input { |
|||
display: none; |
|||
} |
|||
|
|||
.cell { |
|||
.el-tag { |
|||
margin-right: 0; |
|||
} |
|||
} |
|||
|
|||
.small-padding { |
|||
.cell { |
|||
padding-left: 5px; |
|||
padding-right: 5px; |
|||
} |
|||
} |
|||
|
|||
.fixed-width { |
|||
.el-button--mini { |
|||
padding: 7px 10px; |
|||
width: 60px; |
|||
} |
|||
} |
|||
|
|||
.status-col { |
|||
.cell { |
|||
padding: 0 10px; |
|||
text-align: center; |
|||
|
|||
.el-tag { |
|||
margin-right: 0; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// to fixed https://github.com/ElemeFE/element/issues/2461 |
|||
.el-dialog { |
|||
transform: none; |
|||
left: 0; |
|||
position: relative; |
|||
margin: 0 auto; |
|||
} |
|||
|
|||
// refine element ui upload |
|||
.upload-container { |
|||
.el-upload { |
|||
width: 100%; |
|||
|
|||
.el-upload-dragger { |
|||
width: 100%; |
|||
height: 200px; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// dropdown |
|||
.el-dropdown-menu { |
|||
a { |
|||
display: block |
|||
} |
|||
} |
|||
|
|||
// fix date-picker ui bug in filter-item |
|||
.el-range-editor.el-input__inner { |
|||
display: inline-flex !important; |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
/** |
|||
* I think element-ui's default theme color is too light for long-term use. |
|||
* So I modified the default color and you can modify it to your liking. |
|||
**/ |
|||
|
|||
/* theme color */ |
|||
$--color-primary: #1890ff; |
|||
$--color-success: #13ce66; |
|||
$--color-warning: #FFBA00; |
|||
$--color-danger: #ff4949; |
|||
// $--color-info: #1E1E1E; |
|||
|
|||
$--button-font-weight: 400; |
|||
|
|||
// $--color-text-regular: #1f2d3d; |
|||
|
|||
$--border-color-light: #dfe4ed; |
|||
$--border-color-lighter: #e6ebf5; |
|||
|
|||
$--table-border:1px solid#dfe6ec; |
|||
|
|||
/* icon font path, required */ |
|||
$--font-path: '~element-ui/lib/theme-chalk/fonts'; |
|||
|
|||
@import "../../../node_modules/element-ui/packages/theme-chalk/src/index"; |
|||
|
|||
// the :export directive is the magic sauce for webpack |
|||
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass |
|||
:export { |
|||
theme: $--color-primary; |
|||
} |
|||
@ -0,0 +1,46 @@ |
|||
.chartNum{ |
|||
display: flex; |
|||
justify-content: center; |
|||
margin-top: -1rem; |
|||
} |
|||
.box-items { |
|||
position: relative; |
|||
display: flex; |
|||
height: 0.6rem; |
|||
text-align: center; |
|||
} |
|||
/*滚动数字设置*/ |
|||
.number-item { |
|||
display: flex; |
|||
justify-content: center; |
|||
text-align: center; |
|||
width: 1.95rem; |
|||
height: 1.85rem; |
|||
line-height: 1.8rem; |
|||
margin-right: 0.2rem; |
|||
border: 1px solid #0E3465; |
|||
} |
|||
.number-item span{ |
|||
position: relative; |
|||
display: inline-block; |
|||
width: 100%; |
|||
height: 100%; |
|||
writing-mode: vertical-rl; |
|||
text-orientation: upright; |
|||
overflow: hidden; |
|||
} |
|||
.number-item span i{ |
|||
font-style: normal; |
|||
position: absolute; |
|||
top: 25%; |
|||
left: 50%; |
|||
font-size: 0.8rem; |
|||
font-weight: bold; |
|||
color: #fff; |
|||
transform: translate(-50%,0); |
|||
transition: transform 1s ease-in-out; |
|||
letter-spacing: 10px; |
|||
} |
|||
.number-item:last-child { |
|||
margin-right: 0; |
|||
} |
|||
@ -0,0 +1,290 @@ |
|||
@import 'variables'; |
|||
@import 'mixin'; |
|||
@import 'transition'; |
|||
@import 'element-ui'; |
|||
@import 'sidebar'; |
|||
@import '~@/assets/iconfonts/light/iconfont.css'; |
|||
@import 'yxk-admin'; |
|||
@import 'archives-manage'; |
|||
|
|||
body { |
|||
height: 100%; |
|||
-moz-osx-font-smoothing: grayscale; |
|||
-webkit-font-smoothing: antialiased; |
|||
text-rendering: optimizeLegibility; |
|||
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif; |
|||
} |
|||
|
|||
label { |
|||
font-weight: 700; |
|||
} |
|||
|
|||
html { |
|||
height: 100%; |
|||
box-sizing: border-box; |
|||
} |
|||
|
|||
#app { |
|||
height: 100%; |
|||
} |
|||
|
|||
*, |
|||
*:before, |
|||
*:after { |
|||
margin: 0; |
|||
padding: 0; |
|||
box-sizing: inherit; |
|||
} |
|||
|
|||
.no-padding { |
|||
padding: 0 !important; |
|||
} |
|||
|
|||
.padding-content { |
|||
padding: 4px 0; |
|||
} |
|||
|
|||
a:focus, |
|||
a:active { |
|||
outline: none; |
|||
} |
|||
|
|||
a, |
|||
a:focus, |
|||
a:hover { |
|||
cursor: pointer; |
|||
color: inherit; |
|||
text-decoration: none; |
|||
} |
|||
|
|||
div:focus { |
|||
outline: none; |
|||
} |
|||
|
|||
.fr { |
|||
float: right; |
|||
} |
|||
|
|||
.fl { |
|||
float: left; |
|||
} |
|||
|
|||
.pr-5 { |
|||
padding-right: 5px; |
|||
} |
|||
|
|||
.pl-5 { |
|||
padding-left: 5px; |
|||
} |
|||
|
|||
.block { |
|||
display: block; |
|||
} |
|||
|
|||
.pointer { |
|||
cursor: pointer; |
|||
} |
|||
|
|||
.inlineBlock { |
|||
display: block; |
|||
} |
|||
|
|||
.clearfix { |
|||
&:after { |
|||
visibility: hidden; |
|||
display: block; |
|||
font-size: 0; |
|||
content: " "; |
|||
clear: both; |
|||
height: 0; |
|||
} |
|||
} |
|||
|
|||
aside { |
|||
background: #eef1f6; |
|||
padding: 8px 24px; |
|||
margin-bottom: 20px; |
|||
border-radius: 2px; |
|||
display: block; |
|||
line-height: 30px; |
|||
font-size: 16px; |
|||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; |
|||
color: #2c3e50; |
|||
-webkit-font-smoothing: antialiased; |
|||
-moz-osx-font-smoothing: grayscale; |
|||
|
|||
a { |
|||
color: #337ab7; |
|||
cursor: pointer; |
|||
&:hover { |
|||
color: rgb(32, 160, 255); |
|||
} |
|||
} |
|||
} |
|||
|
|||
ul{ |
|||
margin: 0; |
|||
padding: 0; |
|||
li{ |
|||
list-style: none; |
|||
} |
|||
} |
|||
|
|||
|
|||
//main-container全局样式 |
|||
// .app-wrapper{ |
|||
// @include bg_color($background-color-theme); |
|||
// } |
|||
|
|||
.app-container { |
|||
margin: 20px; |
|||
} |
|||
|
|||
|
|||
.components-container { |
|||
margin: 30px 50px; |
|||
position: relative; |
|||
} |
|||
|
|||
.pagination-container { |
|||
margin-top: 30px; |
|||
} |
|||
|
|||
.text-center { |
|||
text-align: center |
|||
} |
|||
|
|||
.sub-navbar { |
|||
height: 50px; |
|||
line-height: 50px; |
|||
position: relative; |
|||
width: 100%; |
|||
text-align: right; |
|||
padding-right: 20px; |
|||
transition: 600ms ease position; |
|||
background: linear-gradient(90deg, rgba(32, 182, 249, 1) 0%, rgba(32, 182, 249, 1) 0%, rgba(33, 120, 241, 1) 100%, rgba(33, 120, 241, 1) 100%); |
|||
|
|||
.subtitle { |
|||
font-size: 20px; |
|||
color: #fff; |
|||
} |
|||
|
|||
&.draft { |
|||
background: #d0d0d0; |
|||
} |
|||
|
|||
&.deleted { |
|||
background: #d0d0d0; |
|||
} |
|||
} |
|||
|
|||
.link-type, |
|||
.link-type:focus { |
|||
color: #337ab7; |
|||
cursor: pointer; |
|||
|
|||
&:hover { |
|||
color: rgb(32, 160, 255); |
|||
} |
|||
} |
|||
|
|||
//refine vue-multiselect plugin |
|||
.multiselect { |
|||
line-height: 16px; |
|||
} |
|||
|
|||
.multiselect--active { |
|||
z-index: 1000 !important; |
|||
} |
|||
|
|||
/**滚动条的宽度*/ |
|||
::-webkit-scrollbar { |
|||
width: 4px; |
|||
height: 4px; |
|||
} |
|||
|
|||
//滚动条的滑块 |
|||
::-webkit-scrollbar-thumb { |
|||
background-color: #13439E; |
|||
border-radius: 3px; |
|||
} |
|||
|
|||
//只需要加上这一行 |
|||
::-webkit-scrollbar-corner { |
|||
background-color: #021941; |
|||
} |
|||
|
|||
// 设置loading-mask |
|||
.el-loading-mask{ |
|||
background-color: rgba(0,0,0,0.2); |
|||
} |
|||
|
|||
@media screen and (min-width:1200px) and (max-width:1536px){ |
|||
.tab-content .tab-nav { |
|||
li{ |
|||
font-size: 14px; |
|||
padding: 0 4px !important; |
|||
letter-spacing: normal; |
|||
&:first-child{ |
|||
padding: 0 12px !important; |
|||
} |
|||
} |
|||
.tab-right-img{ |
|||
width: 73px !important; |
|||
} |
|||
} |
|||
.des-preview-left{ |
|||
width: 510px; |
|||
flex: auto !important; |
|||
.des-form{ |
|||
width: 100% !important; |
|||
.el-input__inner{ |
|||
width: 100% !important; |
|||
} |
|||
.input-num .el-input__inner{ |
|||
width: 30px !important; |
|||
} |
|||
.input-num { |
|||
.el-form-item__content .el-input, |
|||
.el-input-number{ |
|||
width: 100% !important; |
|||
// margin-right: 6px; |
|||
} |
|||
.el-input__inner{ |
|||
padding: 0; |
|||
text-align: center; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
// 档案管理 |
|||
.tree-scroll{ |
|||
height: calc(100vh - 480px) !important; |
|||
} |
|||
// 库房 |
|||
.warehouse-left{ |
|||
.msg-list{ |
|||
li{ |
|||
.msg-list-svg{ |
|||
font-size: 26px !important; |
|||
margin-left: 8px !important; |
|||
} |
|||
.msg-list-unit{ |
|||
font-size: 10px !important; |
|||
} |
|||
.msg-list-num{ |
|||
font-size: 20px !important; |
|||
top: 20px !important; |
|||
} |
|||
&.msg-pm{ |
|||
.msg-list-svg{ |
|||
font-size: 32px !important; |
|||
} |
|||
.msg-list-unit{ |
|||
left: -8px !important; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,86 @@ |
|||
@import "variables"; |
|||
@mixin clearfix { |
|||
&:after { |
|||
content: ""; |
|||
display: table; |
|||
clear: both; |
|||
} |
|||
} |
|||
|
|||
@mixin scrollBar { |
|||
&::-webkit-scrollbar-track-piece { |
|||
background: #d3dce6; |
|||
} |
|||
|
|||
&::-webkit-scrollbar { |
|||
width: 6px; |
|||
} |
|||
|
|||
&::-webkit-scrollbar-thumb { |
|||
background: #99a9bf; |
|||
border-radius: 20px; |
|||
} |
|||
} |
|||
|
|||
// @mixin relative { |
|||
// position: relative; |
|||
// width: 100%; |
|||
// height: 100%; |
|||
// } |
|||
|
|||
// @mixin pct($pct) { |
|||
// width: #{$pct}; |
|||
// position: relative; |
|||
// margin: 0 auto; |
|||
// } |
|||
|
|||
// @mixin triangle($width, $height, $color, $direction) { |
|||
// $width: $width/2; |
|||
// $color-border-style: $height solid $color; |
|||
// $transparent-border-style: $width solid transparent; |
|||
// height: 0; |
|||
// width: 0; |
|||
|
|||
// @if $direction==up { |
|||
// border-bottom: $color-border-style; |
|||
// border-left: $transparent-border-style; |
|||
// border-right: $transparent-border-style; |
|||
// } @else if $direction==right { |
|||
// border-left: $color-border-style; |
|||
// border-top: $transparent-border-style; |
|||
// border-bottom: $transparent-border-style; |
|||
// } @else if $direction==down { |
|||
// border-top: $color-border-style; |
|||
// border-left: $transparent-border-style; |
|||
// border-right: $transparent-border-style; |
|||
// } @else if $direction==left { |
|||
// border-right: $color-border-style; |
|||
// border-top: $transparent-border-style; |
|||
// border-bottom: $transparent-border-style; |
|||
// } |
|||
// } |
|||
|
|||
|
|||
|
|||
@mixin font_color($color) { |
|||
color: $color; |
|||
[data-theme="dark"] & { |
|||
color: $font-color-theme1; |
|||
} |
|||
[data-theme="light"] & { |
|||
color: $font-color-theme2; |
|||
} |
|||
} |
|||
|
|||
@mixin bg_color($color) { |
|||
/*通过该函数设置主题颜色,后期方便统一管理;*/ |
|||
background-color: $color; |
|||
[data-theme="dark"] & { |
|||
background-color: $background-color-theme1; |
|||
@include font-color($font-color-theme1) |
|||
} |
|||
[data-theme="light"] & { |
|||
background-color: $background-color-theme2; |
|||
@include font-color($font-color-theme2) |
|||
} |
|||
} |
|||
@ -0,0 +1,292 @@ |
|||
#app { |
|||
.main-container { |
|||
min-height: 100%; |
|||
transition: margin-left .28s; |
|||
margin-left: $sideBarWidth; |
|||
position: relative; |
|||
padding-top: $headerHeight; |
|||
} |
|||
|
|||
.sidebar-container { |
|||
transition: width 0.28s; |
|||
width: $sideBarWidth !important; |
|||
background-color: $boxBg; |
|||
height: 100%; |
|||
position: fixed; |
|||
font-size: 0; |
|||
top: $headerHeight; |
|||
bottom: 0; |
|||
left: 0; |
|||
z-index: 99; |
|||
background: url(~@/assets/images/sidebar_bg.png) #031435 no-repeat right bottom; |
|||
@include bg_color($background-color-theme); |
|||
background-size: contain; |
|||
box-shadow: 5px 2px 10px 1px rgba(15,164,222,0.16); |
|||
overflow: hidden; |
|||
|
|||
// reset element-ui css |
|||
.horizontal-collapse-transition { |
|||
transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out; |
|||
} |
|||
|
|||
.scrollbar-wrapper { |
|||
overflow-x: hidden !important; |
|||
} |
|||
|
|||
.el-scrollbar__bar.is-vertical { |
|||
right: 0; |
|||
} |
|||
|
|||
.el-scrollbar { |
|||
height: 100%; |
|||
} |
|||
|
|||
&.has-logo { |
|||
.el-scrollbar { |
|||
height: calc(100% - 50px); |
|||
} |
|||
} |
|||
|
|||
.is-horizontal { |
|||
display: none; |
|||
} |
|||
|
|||
a { |
|||
display: inline-block; |
|||
width: 100%; |
|||
overflow: hidden; |
|||
} |
|||
|
|||
.svg-icon { |
|||
margin-right: 10px; |
|||
} |
|||
|
|||
.el-submenu__icon-arrow{ |
|||
font-size: 18px; |
|||
color: $mainColor; |
|||
right: 60px; |
|||
} |
|||
|
|||
.el-menu { |
|||
border: none; |
|||
height: 100%; |
|||
width: 100% !important; |
|||
background-color: transparent !important; |
|||
} |
|||
|
|||
// menu hover |
|||
.submenu-title-noDropdown, |
|||
.el-submenu__title { |
|||
font-size: 16px; |
|||
height: 60px !important; |
|||
line-height: 60px !important; |
|||
padding: 0 60px 0 58px !important; |
|||
background-color: transparent !important; |
|||
&:hover { |
|||
background-image: $menuActiveBg !important; |
|||
&::before{ |
|||
content: ""; |
|||
position: absolute; |
|||
left: 0; |
|||
top: 0; |
|||
width: 5px; |
|||
height: 60px; |
|||
background-color: $mainColor; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.is-active>.el-submenu__title, |
|||
.is-active.submenu-title-noDropdown { |
|||
position: relative; |
|||
color: $mainColor !important; |
|||
background-image: $menuActiveBg !important; |
|||
&::before{ |
|||
content: ""; |
|||
position: absolute; |
|||
left: 0; |
|||
top: 0; |
|||
width: 5px; |
|||
height: 60px; |
|||
background-color: $mainColor; |
|||
} |
|||
} |
|||
|
|||
& .nest-menu .el-submenu>.el-submenu__title, |
|||
& .el-submenu .el-menu-item { |
|||
min-width: $sideBarWidth !important; |
|||
background-color: transparent !important; |
|||
|
|||
&:hover { |
|||
background-image: $subMenuHover !important; |
|||
} |
|||
} |
|||
|
|||
& .el-submenu .el-menu-item{ |
|||
position: relative; |
|||
padding: 0 60px 0 82px !important; |
|||
height: 40px !important; |
|||
line-height: 40px; |
|||
&::before{ |
|||
content: ""; |
|||
position: absolute; |
|||
left: 56px; |
|||
top: 50%; |
|||
width: 6px; |
|||
height: 6px; |
|||
background-color: #fff; |
|||
border-radius: 50%; |
|||
transform: translateY(-50%); |
|||
} |
|||
.svg-icon { |
|||
display: none; |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
.hideSidebar { |
|||
.sidebar-container { |
|||
width: 54px !important; |
|||
} |
|||
|
|||
.main-container { |
|||
margin-left: 54px; |
|||
} |
|||
|
|||
.submenu-title-noDropdown { |
|||
padding: 0 !important; |
|||
position: relative; |
|||
|
|||
.el-tooltip { |
|||
padding: 0 !important; |
|||
|
|||
.svg-icon { |
|||
margin-left: 20px; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.el-submenu { |
|||
overflow: hidden; |
|||
|
|||
&>.el-submenu__title { |
|||
padding: 0 !important; |
|||
|
|||
.svg-icon { |
|||
margin-left: 20px; |
|||
} |
|||
|
|||
.el-submenu__icon-arrow { |
|||
display: none; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.el-menu--collapse { |
|||
.el-submenu { |
|||
&>.el-submenu__title { |
|||
&>span { |
|||
height: 0; |
|||
width: 0; |
|||
overflow: hidden; |
|||
visibility: hidden; |
|||
display: inline-block; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
.main-breadcrumb{ |
|||
left: 54px; |
|||
} |
|||
} |
|||
|
|||
.el-menu--collapse .el-menu .el-submenu { |
|||
min-width: $sideBarWidth !important; |
|||
} |
|||
|
|||
// mobile responsive |
|||
.mobile { |
|||
.main-container { |
|||
margin-left: 0; |
|||
} |
|||
|
|||
.sidebar-container { |
|||
transition: transform .28s; |
|||
width: $sideBarWidth !important; |
|||
} |
|||
|
|||
&.hideSidebar { |
|||
.sidebar-container { |
|||
pointer-events: none; |
|||
transition-duration: 0.3s; |
|||
transform: translate3d(-$sideBarWidth, 0, 0); |
|||
} |
|||
} |
|||
} |
|||
|
|||
.withoutAnimation { |
|||
|
|||
.main-container, |
|||
.sidebar-container { |
|||
transition: none; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.is-active.el-menu-item { |
|||
background-image: $subMenuActiveBg !important; |
|||
} |
|||
|
|||
|
|||
// when menu collapsed |
|||
.el-menu--vertical { |
|||
&>.el-menu { |
|||
.svg-icon { |
|||
display: none; |
|||
margin-right: 16px; |
|||
} |
|||
} |
|||
|
|||
.nest-menu .el-submenu>.el-submenu__title, |
|||
.el-menu-item { |
|||
position: relative; |
|||
padding-left: 50px !important; |
|||
height: 40px !important; |
|||
line-height: 40px; |
|||
&::before{ |
|||
content: ""; |
|||
position: absolute; |
|||
left: 30px; |
|||
top: 50%; |
|||
width: 6px; |
|||
height: 6px; |
|||
background-color: #fff; |
|||
border-radius: 50%; |
|||
transform: translateY(-50%); |
|||
} |
|||
&:hover { |
|||
background-image: $subMenuHover !important; |
|||
} |
|||
} |
|||
|
|||
// the scroll bar appears when the subMenu is too long |
|||
>.el-menu--popup { |
|||
max-height: 100vh; |
|||
overflow-y: auto; |
|||
|
|||
&::-webkit-scrollbar-track-piece { |
|||
background: #d3dce6; |
|||
} |
|||
|
|||
&::-webkit-scrollbar { |
|||
width: 6px; |
|||
} |
|||
|
|||
&::-webkit-scrollbar-thumb { |
|||
background: #99a9bf; |
|||
border-radius: 20px; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,48 @@ |
|||
// global transition css |
|||
|
|||
/* fade */ |
|||
.fade-enter-active, |
|||
.fade-leave-active { |
|||
transition: opacity 0.28s; |
|||
} |
|||
|
|||
.fade-enter, |
|||
.fade-leave-active { |
|||
opacity: 0; |
|||
} |
|||
|
|||
/* fade-transform */ |
|||
.fade-transform-leave-active, |
|||
.fade-transform-enter-active { |
|||
transition: all .5s; |
|||
} |
|||
|
|||
.fade-transform-enter { |
|||
opacity: 0; |
|||
transform: translateX(-30px); |
|||
} |
|||
|
|||
.fade-transform-leave-to { |
|||
opacity: 0; |
|||
transform: translateX(30px); |
|||
} |
|||
|
|||
/* breadcrumb transition */ |
|||
.breadcrumb-enter-active, |
|||
.breadcrumb-leave-active { |
|||
transition: all .5s; |
|||
} |
|||
|
|||
.breadcrumb-enter, |
|||
.breadcrumb-leave-active { |
|||
opacity: 0; |
|||
transform: translateX(20px); |
|||
} |
|||
|
|||
.breadcrumb-move { |
|||
transition: all .5s; |
|||
} |
|||
|
|||
.breadcrumb-leave-active { |
|||
position: absolute; |
|||
} |
|||
@ -0,0 +1,45 @@ |
|||
$background-color-theme: #031435; //背景主题颜色默认 |
|||
$background-color-theme1: #031435; //背景主题颜色1 |
|||
$background-color-theme2: #F6F8FC; //背景主题颜色1 |
|||
|
|||
$font-color-theme : #fff; //字体主题颜色默认 |
|||
$font-color-theme1 : #fff; //字体主题颜色1 |
|||
$font-color-theme2 : #031435; //字体主题颜色2 |
|||
|
|||
$boxBg: #031435; // 板块背景色 |
|||
$mainColor: #339CFF; // 主色 |
|||
$otherColor: #02255F; // 辅助色1 |
|||
$otherColor2: #13439E; // 辅助色2 |
|||
$btnBorder:#3581CC; // 按钮描边 |
|||
|
|||
$arcPurple:#563BE1; |
|||
$arcYellow:#FD8042; |
|||
$arcRed:#F65163; |
|||
$arcGreen: #1AAE93; |
|||
$arcCyan: #0FBED9; |
|||
|
|||
$menuText:#359AFC; |
|||
$menuActiveBg: linear-gradient(90deg, rgba(59, 160, 255, 0.3) 0% 0%, rgba(42,112,177,0.3) 43%, rgba(51, 156, 255, 0) 100%); |
|||
$subMenuActiveBg: linear-gradient(90deg, rgba(59, 160, 255, 0) 0%, rgba(42,112,177,0.3) 43%, rgba(51, 156, 255, 0) 100%); |
|||
$subMenuHover: linear-gradient(90deg, rgba(59, 160, 255, 0) 0%, rgba(42,112,177,0.3) 43%, rgba(51, 156, 255, 0) 100%); |
|||
|
|||
|
|||
$headerHeight: 64px; |
|||
$sideBarWidth: 300px; |
|||
|
|||
$breadcrumbBg: #021941; |
|||
$mainContainerBorder: 1px solid #113D72; |
|||
|
|||
$desPreviewColor: #3A99FD; |
|||
|
|||
:export { |
|||
menuText: $menuText; |
|||
menuActiveBg: $menuActiveBg; |
|||
subMenuHover: $subMenuHover; |
|||
sideBarWidth: $sideBarWidth; |
|||
headerHeight: $headerHeight; |
|||
subMenuActiveBg: $subMenuActiveBg; |
|||
mainContainerBorder: $mainContainerBorder; |
|||
breadcrumbBg: $breadcrumbBg; |
|||
desPreviewColor: $desPreviewColor; |
|||
} |
|||
1211
src/assets/styles/yxk-admin.scss
File diff suppressed because it is too large
View File
@ -0,0 +1,104 @@ |
|||
<template> |
|||
<el-breadcrumb class="app-breadcrumb" separator="/"> |
|||
<transition-group name="breadcrumb"> |
|||
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path"> |
|||
<span v-if="item.redirect==='noredirect'||index==levelList.length-1" class="no-redirect">{{ item.meta.title }}</span> |
|||
<a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a> |
|||
</el-breadcrumb-item> |
|||
</transition-group> |
|||
</el-breadcrumb> |
|||
</template> |
|||
|
|||
<script> |
|||
import pathToRegexp from 'path-to-regexp' |
|||
|
|||
export default { |
|||
data() { |
|||
return { |
|||
levelList: null |
|||
} |
|||
}, |
|||
watch: { |
|||
$route(route) { |
|||
// if you go to the redirect page, do not update the breadcrumbs |
|||
if (route.path.startsWith('/redirect/')) { |
|||
return |
|||
} |
|||
this.getBreadcrumb() |
|||
} |
|||
}, |
|||
created() { |
|||
this.getBreadcrumb() |
|||
}, |
|||
methods: { |
|||
getBreadcrumb() { |
|||
// only show routes with meta.title |
|||
let matched = this.$route.matched.filter(item => item.meta && item.meta.title) |
|||
const first = matched[0] |
|||
|
|||
if (!this.isDashboard(first)) { |
|||
matched = [{ path: '/dashboard', meta: { title: '首页' }}].concat(matched) |
|||
} |
|||
|
|||
this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false) |
|||
}, |
|||
isDashboard(route) { |
|||
const name = route && route.name |
|||
if (!name) { |
|||
return false |
|||
} |
|||
return name.trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase() |
|||
}, |
|||
pathCompile(path) { |
|||
// To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561 |
|||
const { params } = this.$route |
|||
var toPath = pathToRegexp.compile(path) |
|||
return toPath(params) |
|||
}, |
|||
handleLink(item) { |
|||
const { redirect, path } = item |
|||
if (redirect) { |
|||
this.$router.push(redirect) |
|||
return |
|||
} |
|||
this.$router.push(this.pathCompile(path)) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.app-breadcrumb.el-breadcrumb { |
|||
position: relative; |
|||
flex: 1; |
|||
font-size: 14px; |
|||
line-height: 50px; |
|||
padding-left: 30px; |
|||
&::before { |
|||
position: absolute; |
|||
left: 6px; |
|||
top: 50%; |
|||
font-family: "iconfont" !important; |
|||
font-style: normal; |
|||
-webkit-font-smoothing: antialiased; |
|||
-moz-osx-font-smoothing: grayscale; |
|||
content: "\e60d"; |
|||
color: #339CFF; |
|||
transform: translateY(-50%); |
|||
} |
|||
.el-breadcrumb__item:last-child{ |
|||
.el-breadcrumb__inner .no-redirect{ |
|||
color: #fff; |
|||
} |
|||
} |
|||
::v-deep .el-breadcrumb__separator{ |
|||
color: #339CFF; |
|||
} |
|||
.no-redirect { |
|||
color: #339CFF; |
|||
cursor: text; |
|||
|
|||
} |
|||
|
|||
} |
|||
</style> |
|||
@ -0,0 +1,228 @@ |
|||
<template> |
|||
<div class="crud-opts"> |
|||
<div class="crud-opts-left"> |
|||
<!--左侧插槽--> |
|||
<slot name="left" /> |
|||
<!-- type="primary" --> |
|||
<el-button v-if="crud.optShow.add" v-permission="permission.add" size="mini" icon="el-icon-plus" @click="crud.toAdd"> |
|||
新增 |
|||
</el-button> |
|||
<!-- type="success" --> |
|||
<el-button v-if="crud.optShow.edit" v-permission="permission.edit" size="mini" icon="el-icon-edit" :disabled="crud.selections.length !== 1" @click="crud.toEdit(crud.selections[0])"> |
|||
修改 |
|||
</el-button> |
|||
<!-- type="danger" --> |
|||
<el-button v-if="crud.optShow.del" slot="reference" v-permission="permission.del" icon="el-icon-delete" size="mini" :loading="crud.delAllLoading" :disabled="crud.selections.length === 0" @click="delVisible=true"> |
|||
删除 |
|||
</el-button> |
|||
<!-- type="warning" --> |
|||
<el-button v-if="crud.optShow.download" :loading="crud.downloadLoading" :disabled="!crud.data.length" size="mini" icon="el-icon-download" @click="crud.doExport">导出</el-button> |
|||
<!--右侧--> |
|||
<slot name="right" /> |
|||
</div> |
|||
<!-- 删除弹窗 --> |
|||
<el-dialog :visible.sync="delVisible" title="确认删除"> |
|||
<span class="dialog-right-top" /> |
|||
<span class="dialog-left-bottom" /> |
|||
<div class="setting-dialog"> |
|||
<p class="delMsg">确定删除所选{{ crud.selections.length }}条数据吗?</p> |
|||
<div slot="footer" class="dialog-footer"> |
|||
<el-button type="primary" :loading="crud.delAllLoading" @click="toDelete(crud.selections)">确定</el-button> |
|||
</div> |
|||
</div> |
|||
</el-dialog> |
|||
<el-button-group v-if="crud.optShow.group" class="crud-opts-right"> |
|||
<el-button size="mini" plain type="info" icon="el-icon-search" @click="toggleSearch()" /> |
|||
<el-button size="mini" icon="el-icon-refresh" @click="crud.refresh()" /> |
|||
<el-popover placement="bottom-end" width="150" trigger="click"> |
|||
<el-button slot="reference" size="mini" icon="el-icon-s-grid"> |
|||
<i class="fa fa-caret-down" aria-hidden="true" /> |
|||
</el-button> |
|||
<el-checkbox v-model="allColumnsSelected" :indeterminate="allColumnsSelectedIndeterminate" @change="handleCheckAllChange"> |
|||
全选 |
|||
</el-checkbox> |
|||
<el-checkbox v-for="item in tableColumns" :key="item.property" v-model="item.visible" @change="handleCheckedTableColumnsChange(item)"> |
|||
{{ item.label }} |
|||
</el-checkbox> |
|||
</el-popover> |
|||
</el-button-group> |
|||
<slot name="rightButtonGroup" /> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
import CRUD, { crud } from '@crud/crud' |
|||
|
|||
function sortWithRef(src, ref) { |
|||
const result = Object.assign([], ref) |
|||
let cursor = -1 |
|||
src.forEach(e => { |
|||
const idx = result.indexOf(e) |
|||
if (idx === -1) { |
|||
cursor += 1 |
|||
result.splice(cursor, 0, e) |
|||
} else { |
|||
cursor = idx |
|||
} |
|||
}) |
|||
return result |
|||
} |
|||
|
|||
export default { |
|||
mixins: [crud()], |
|||
props: { |
|||
permission: { |
|||
type: Object, |
|||
default: () => { return {} } |
|||
}, |
|||
hiddenColumns: { |
|||
type: Array, |
|||
default: () => { return [] } |
|||
}, |
|||
ignoreColumns: { |
|||
type: Array, |
|||
default: () => { return [] } |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
tableColumns: [], |
|||
allColumnsSelected: true, |
|||
allColumnsSelectedIndeterminate: false, |
|||
tableUnwatcher: null, |
|||
// 忽略下次表格列变动 |
|||
ignoreNextTableColumnsChange: false, |
|||
delVisible: false |
|||
|
|||
} |
|||
}, |
|||
watch: { |
|||
'crud.props.table'() { |
|||
this.updateTableColumns() |
|||
this.tableColumns.forEach(column => { |
|||
if (this.hiddenColumns.indexOf(column.property) !== -1) { |
|||
column.visible = false |
|||
this.updateColumnVisible(column) |
|||
} |
|||
}) |
|||
}, |
|||
'crud.props.table.store.states.columns'() { |
|||
this.updateTableColumns() |
|||
} |
|||
}, |
|||
created() { |
|||
this.crud.updateProp('searchToggle', true) |
|||
}, |
|||
methods: { |
|||
updateTableColumns() { |
|||
const table = this.crud.getTable() |
|||
if (!table) { |
|||
this.tableColumns = [] |
|||
return |
|||
} |
|||
let cols = null |
|||
const columnFilter = e => e && e.type === 'default' && e.property && this.ignoreColumns.indexOf(e.property) === -1 |
|||
const refCols = table.columns.filter(columnFilter) |
|||
if (this.ignoreNextTableColumnsChange) { |
|||
this.ignoreNextTableColumnsChange = false |
|||
return |
|||
} |
|||
this.ignoreNextTableColumnsChange = false |
|||
const columns = [] |
|||
const fullTableColumns = table.$children.map(e => e.columnConfig).filter(columnFilter) |
|||
cols = sortWithRef(fullTableColumns, refCols) |
|||
cols.forEach(config => { |
|||
const column = { |
|||
property: config.property, |
|||
label: config.label, |
|||
visible: refCols.indexOf(config) !== -1 |
|||
} |
|||
columns.push(column) |
|||
}) |
|||
this.tableColumns = columns |
|||
}, |
|||
toDelete(datas) { |
|||
// this.$confirm(this.crud.confirmDeleteMsg ? this.crud.confirmDeleteMsg : `确认删除选中的${datas.length}条数据?`, '提示', { |
|||
// confirmButtonText: '确定', |
|||
// cancelButtonText: '取消' |
|||
// }).then(() => { |
|||
this.crud.delAllLoading = true |
|||
this.delVisible = false |
|||
this.crud.doDelete(datas) |
|||
// }).catch(() => { |
|||
// }) |
|||
}, |
|||
handleCheckAllChange(val) { |
|||
if (val === false) { |
|||
this.allColumnsSelected = true |
|||
return |
|||
} |
|||
this.tableColumns.forEach(column => { |
|||
if (!column.visible) { |
|||
column.visible = true |
|||
this.updateColumnVisible(column) |
|||
} |
|||
}) |
|||
this.allColumnsSelected = val |
|||
this.allColumnsSelectedIndeterminate = false |
|||
}, |
|||
handleCheckedTableColumnsChange(item) { |
|||
let totalCount = 0 |
|||
let selectedCount = 0 |
|||
this.tableColumns.forEach(column => { |
|||
++totalCount |
|||
selectedCount += column.visible ? 1 : 0 |
|||
}) |
|||
if (selectedCount === 0) { |
|||
this.crud.notify('请至少选择一列', CRUD.NOTIFICATION_TYPE.WARNING) |
|||
this.$nextTick(function() { |
|||
item.visible = true |
|||
}) |
|||
return |
|||
} |
|||
this.allColumnsSelected = selectedCount === totalCount |
|||
this.allColumnsSelectedIndeterminate = selectedCount !== totalCount && selectedCount !== 0 |
|||
this.updateColumnVisible(item) |
|||
}, |
|||
updateColumnVisible(item) { |
|||
const table = this.crud.props.table |
|||
const vm = table.$children.find(e => e.prop === item.property) |
|||
const columnConfig = vm.columnConfig |
|||
if (item.visible) { |
|||
// 找出合适的插入点 |
|||
const columnIndex = this.tableColumns.indexOf(item) |
|||
vm.owner.store.commit('insertColumn', columnConfig, columnIndex + 1, null) |
|||
} else { |
|||
vm.owner.store.commit('removeColumn', columnConfig, null) |
|||
} |
|||
this.ignoreNextTableColumnsChange = true |
|||
}, |
|||
toggleSearch() { |
|||
this.crud.props.searchToggle = !this.crud.props.searchToggle |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style> |
|||
.crud-opts { |
|||
display: -webkit-flex; |
|||
display: flex; |
|||
align-items: center; |
|||
} |
|||
.crud-opts-left{ |
|||
display: flex; |
|||
} |
|||
.crud-opts-right { |
|||
margin-left: auto; |
|||
} |
|||
.crud-opts-right .el-button{ |
|||
padding: 7px 15px; |
|||
} |
|||
.crud-opts .crud-opts-right span { |
|||
float: left; |
|||
} |
|||
.delMsg{ |
|||
color: #fff; |
|||
font-size: 16px; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,18 @@ |
|||
<!--分页--> |
|||
<template> |
|||
<el-pagination |
|||
:page-size.sync="page.size" |
|||
:total="page.total" |
|||
:current-page.sync="page.page" |
|||
style="margin-top: 8px;" |
|||
layout="total, prev, pager, next, sizes" |
|||
@size-change="crud.sizeChangeHandler($event)" |
|||
@current-change="crud.pageChangeHandler" |
|||
/> |
|||
</template> |
|||
<script> |
|||
import { pagination } from '@crud/crud' |
|||
export default { |
|||
mixins: [pagination()] |
|||
} |
|||
</script> |
|||
@ -0,0 +1,28 @@ |
|||
<!--搜索与重置--> |
|||
<template> |
|||
<span> |
|||
<el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="crud.toQuery">搜索</el-button> |
|||
<el-button v-if="crud.optShow.reset" class="filter-item" size="mini" type="warning" icon="el-icon-refresh-left" @click="crud.resetQuery()">重置</el-button> |
|||
</span> |
|||
</template> |
|||
<script> |
|||
import { crud } from '@crud/crud' |
|||
export default { |
|||
mixins: [crud()], |
|||
props: { |
|||
itemClass: { |
|||
type: String, |
|||
required: false, |
|||
default: '' |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss" scoped> |
|||
.el-button{ |
|||
background-color: #3A99FD; |
|||
&:hover{ |
|||
background-color: #02255F; |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,103 @@ |
|||
<template> |
|||
<div> |
|||
<el-button v-permission="permission.edit" :loading="crud.status.cu === 2" :disabled="disabledEdit" size="mini" type="primary" icon="el-icon-edit" @click="crud.toEdit(data)" /> |
|||
<el-popover v-model="pop" v-permission="permission.del" placement="top" width="180" trigger="manual" popper-class="myPopover" @show="onPopoverShow" @hide="onPopoverHide"> |
|||
<p>{{ msg }}</p> |
|||
<div style="text-align: right; margin: 10px 0 0 0;"> |
|||
<el-button size="mini" type="text" @click="doCancel">取消</el-button> |
|||
<el-button :loading="crud.dataStatus[crud.getDataId(data)].delete === 2" type="primary" size="mini" @click="crud.doDelete(data)">确定</el-button> |
|||
</div> |
|||
<el-button slot="reference" :disabled="disabledDle" type="danger" icon="el-icon-delete" size="mini" @click="toDelete" /> |
|||
</el-popover> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
import CRUD, { crud } from '@crud/crud' |
|||
export default { |
|||
mixins: [crud()], |
|||
props: { |
|||
data: { |
|||
type: Object, |
|||
required: true |
|||
}, |
|||
permission: { |
|||
type: Object, |
|||
required: true |
|||
}, |
|||
disabledEdit: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
disabledDle: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
msg: { |
|||
type: String, |
|||
default: '确定删除本条数据吗?' |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
pop: false |
|||
} |
|||
}, |
|||
methods: { |
|||
doCancel() { |
|||
this.pop = false |
|||
this.crud.cancelDelete(this.data) |
|||
}, |
|||
toDelete() { |
|||
this.pop = true |
|||
}, |
|||
[CRUD.HOOK.afterDelete](crud, data) { |
|||
if (data === this.data) { |
|||
this.pop = false |
|||
} |
|||
}, |
|||
onPopoverShow() { |
|||
setTimeout(() => { |
|||
document.addEventListener('click', this.handleDocumentClick) |
|||
}, 0) |
|||
}, |
|||
onPopoverHide() { |
|||
document.removeEventListener('click', this.handleDocumentClick) |
|||
}, |
|||
handleDocumentClick(event) { |
|||
this.pop = false |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.el-popover.myPopover{ |
|||
background-color: #02255F; |
|||
color: #fff; |
|||
box-shadow: 0px 0px 10px #3A99FD inset; |
|||
border: none; |
|||
.el-button{ |
|||
background: #3A99FD; |
|||
&:hover{ |
|||
color: #fff; |
|||
border: 1px solid #3A99FD; |
|||
background-color: #02255F; |
|||
} |
|||
} |
|||
.popper__arrow{ |
|||
border: none; |
|||
&::after{ |
|||
content: ''; |
|||
width: 20px; |
|||
height: 14px; |
|||
position: absolute; |
|||
left: -3px; |
|||
bottom: 0; |
|||
border: none; |
|||
background: url('~@/assets/images/pop_sanjiao.png') no-repeat -35px 0; |
|||
z-index: 11; |
|||
} |
|||
} |
|||
} |
|||
|
|||
</style> |
|||
@ -0,0 +1,869 @@ |
|||
import { initData, download } from '@/api/data' |
|||
import { parseTime, downloadFile } from '@/utils/index' |
|||
import Vue from 'vue' |
|||
|
|||
/** |
|||
* CRUD配置 |
|||
* @author moxun |
|||
* @param {*} options <br> |
|||
* @return crud instance. |
|||
* @example |
|||
* 要使用多crud时,请在关联crud的组件处使用crud-tag进行标记,如:<jobForm :job-status="dict.job_status" crud-tag="job" /> |
|||
*/ |
|||
function CRUD(options) { |
|||
const defaultOptions = { |
|||
tag: 'default', |
|||
// id字段名
|
|||
idField: 'id', |
|||
// 标题
|
|||
title: '', |
|||
// 请求数据的url
|
|||
url: '', |
|||
// 表格数据
|
|||
data: [], |
|||
// 选择项
|
|||
selections: [], |
|||
// 待查询的对象
|
|||
query: {}, |
|||
// 查询数据的参数
|
|||
params: {}, |
|||
// Form 表单
|
|||
form: {}, |
|||
// 重置表单
|
|||
defaultForm: () => {}, |
|||
// 排序规则,默认 id 降序, 支持多字段排序 ['id,desc', 'createTime,asc']
|
|||
sort: ['id,desc'], |
|||
// 等待时间
|
|||
time: 50, |
|||
// CRUD Method
|
|||
crudMethod: { |
|||
add: (form) => {}, |
|||
del: (id) => {}, |
|||
edit: (form) => {}, |
|||
get: (id) => {} |
|||
}, |
|||
// 主页操作栏显示哪些按钮
|
|||
optShow: { |
|||
add: true, |
|||
edit: true, |
|||
del: true, |
|||
download: true, |
|||
reset: true, |
|||
group: true |
|||
}, |
|||
// 自定义一些扩展属性
|
|||
props: {}, |
|||
// 在主页准备
|
|||
queryOnPresenterCreated: true, |
|||
// 调试开关
|
|||
debug: false, |
|||
confirmDeleteMsg: null |
|||
} |
|||
options = mergeOptions(defaultOptions, options) |
|||
const data = { |
|||
...options, |
|||
// 记录数据状态
|
|||
dataStatus: {}, |
|||
status: { |
|||
add: CRUD.STATUS.NORMAL, |
|||
edit: CRUD.STATUS.NORMAL, |
|||
// 添加或编辑状态
|
|||
get cu() { |
|||
if (this.add === CRUD.STATUS.NORMAL && this.edit === CRUD.STATUS.NORMAL) { |
|||
return CRUD.STATUS.NORMAL |
|||
} else if (this.add === CRUD.STATUS.PREPARED || this.edit === CRUD.STATUS.PREPARED) { |
|||
return CRUD.STATUS.PREPARED |
|||
} else if (this.add === CRUD.STATUS.PROCESSING || this.edit === CRUD.STATUS.PROCESSING) { |
|||
return CRUD.STATUS.PROCESSING |
|||
} |
|||
throw new Error('wrong crud\'s cu status') |
|||
}, |
|||
// 标题
|
|||
get title() { |
|||
return this.add > CRUD.STATUS.NORMAL ? `新增${crud.title}` : this.edit > CRUD.STATUS.NORMAL ? `编辑${crud.title}` : crud.title |
|||
} |
|||
}, |
|||
msg: { |
|||
submit: '提交成功', |
|||
add: '新增成功', |
|||
edit: '编辑成功', |
|||
del: '删除成功' |
|||
}, |
|||
page: { |
|||
// 页码
|
|||
page: 0, |
|||
// 每页数据条数
|
|||
size: 10, |
|||
// 总数据条数
|
|||
total: 0 |
|||
}, |
|||
// 整体loading
|
|||
loading: false, |
|||
// 导出的 Loading
|
|||
downloadLoading: false, |
|||
// 删除的 Loading
|
|||
delAllLoading: false |
|||
} |
|||
const methods = { |
|||
/** |
|||
* 通用的提示 |
|||
*/ |
|||
submitSuccessNotify() { |
|||
crud.notify(crud.msg.submit, CRUD.NOTIFICATION_TYPE.SUCCESS) |
|||
}, |
|||
addSuccessNotify() { |
|||
crud.notify(crud.msg.add, CRUD.NOTIFICATION_TYPE.SUCCESS) |
|||
}, |
|||
editSuccessNotify() { |
|||
crud.notify(crud.msg.edit, CRUD.NOTIFICATION_TYPE.SUCCESS) |
|||
}, |
|||
delSuccessNotify() { |
|||
crud.notify(crud.msg.del, CRUD.NOTIFICATION_TYPE.SUCCESS) |
|||
}, |
|||
// 搜索
|
|||
toQuery() { |
|||
crud.page.page = 1 |
|||
crud.refresh() |
|||
}, |
|||
// 刷新
|
|||
refresh() { |
|||
if (!callVmHook(crud, CRUD.HOOK.beforeRefresh)) { |
|||
return |
|||
} |
|||
return new Promise((resolve, reject) => { |
|||
crud.loading = true |
|||
// 请求数据
|
|||
initData(crud.url, crud.getQueryParams()).then(data => { |
|||
const table = crud.getTable() |
|||
if (table && table.lazy) { // 懒加载子节点数据,清掉已加载的数据
|
|||
table.store.states.treeData = {} |
|||
table.store.states.lazyTreeNodeMap = {} |
|||
} |
|||
crud.page.total = data.totalElements !== null ? data.totalElements : data.length |
|||
crud.data = data.content ? data.content : data |
|||
crud.resetDataStatus() |
|||
// time 毫秒后显示表格
|
|||
setTimeout(() => { |
|||
crud.loading = false |
|||
callVmHook(crud, CRUD.HOOK.afterRefresh) |
|||
}, crud.time) |
|||
resolve(data) |
|||
}).catch(err => { |
|||
crud.loading = false |
|||
reject(err) |
|||
}) |
|||
}) |
|||
}, |
|||
/** |
|||
* 启动添加 |
|||
*/ |
|||
toAdd() { |
|||
crud.resetForm() |
|||
if (!(callVmHook(crud, CRUD.HOOK.beforeToAdd, crud.form) && callVmHook(crud, CRUD.HOOK.beforeToCU, crud.form, 'add'))) { |
|||
return |
|||
} |
|||
crud.status.add = CRUD.STATUS.PREPARED |
|||
callVmHook(crud, CRUD.HOOK.afterToAdd, crud.form) |
|||
callVmHook(crud, CRUD.HOOK.afterToCU, crud.form) |
|||
}, |
|||
/** |
|||
* 启动编辑 |
|||
* @param {*} data 数据项 |
|||
*/ |
|||
toEdit(data) { |
|||
crud.resetForm(JSON.parse(JSON.stringify(data))) |
|||
if (!(callVmHook(crud, CRUD.HOOK.beforeToEdit, crud.form) && callVmHook(crud, CRUD.HOOK.beforeToCU, crud.form, 'edit'))) { |
|||
return |
|||
} |
|||
crud.status.edit = CRUD.STATUS.PREPARED |
|||
crud.getDataStatus(crud.getDataId(data)).edit = CRUD.STATUS.PREPARED |
|||
callVmHook(crud, CRUD.HOOK.afterToEdit, crud.form) |
|||
callVmHook(crud, CRUD.HOOK.afterToCU, crud.form) |
|||
}, |
|||
/** |
|||
* 启动删除 |
|||
* @param {*} data 数据项 |
|||
*/ |
|||
toDelete(data) { |
|||
crud.getDataStatus(crud.getDataId(data)).delete = CRUD.STATUS.PREPARED |
|||
}, |
|||
/** |
|||
* 取消删除 |
|||
* @param {*} data 数据项 |
|||
*/ |
|||
cancelDelete(data) { |
|||
if (!callVmHook(crud, CRUD.HOOK.beforeDeleteCancel, data)) { |
|||
return |
|||
} |
|||
crud.getDataStatus(crud.getDataId(data)).delete = CRUD.STATUS.NORMAL |
|||
callVmHook(crud, CRUD.HOOK.afterDeleteCancel, data) |
|||
}, |
|||
/** |
|||
* 取消新增/编辑 |
|||
*/ |
|||
cancelCU() { |
|||
const addStatus = crud.status.add |
|||
const editStatus = crud.status.edit |
|||
if (addStatus === CRUD.STATUS.PREPARED) { |
|||
if (!callVmHook(crud, CRUD.HOOK.beforeAddCancel, crud.form)) { |
|||
return |
|||
} |
|||
crud.status.add = CRUD.STATUS.NORMAL |
|||
} |
|||
if (editStatus === CRUD.STATUS.PREPARED) { |
|||
if (!callVmHook(crud, CRUD.HOOK.beforeEditCancel, crud.form)) { |
|||
return |
|||
} |
|||
crud.status.edit = CRUD.STATUS.NORMAL |
|||
crud.getDataStatus(crud.getDataId(crud.form)).edit = CRUD.STATUS.NORMAL |
|||
} |
|||
crud.resetForm() |
|||
if (addStatus === CRUD.STATUS.PREPARED) { |
|||
callVmHook(crud, CRUD.HOOK.afterAddCancel, crud.form) |
|||
} |
|||
if (editStatus === CRUD.STATUS.PREPARED) { |
|||
callVmHook(crud, CRUD.HOOK.afterEditCancel, crud.form) |
|||
} |
|||
// 清除表单验证
|
|||
if (crud.findVM('form').$refs['form']) { |
|||
crud.findVM('form').$refs['form'].clearValidate() |
|||
} |
|||
}, |
|||
/** |
|||
* 提交新增/编辑 |
|||
*/ |
|||
submitCU() { |
|||
if (!callVmHook(crud, CRUD.HOOK.beforeValidateCU)) { |
|||
return |
|||
} |
|||
crud.findVM('form').$refs['form'].validate(valid => { |
|||
if (!valid) { |
|||
return |
|||
} |
|||
if (!callVmHook(crud, CRUD.HOOK.afterValidateCU)) { |
|||
return |
|||
} |
|||
if (crud.status.add === CRUD.STATUS.PREPARED) { |
|||
crud.doAdd() |
|||
} else if (crud.status.edit === CRUD.STATUS.PREPARED) { |
|||
crud.doEdit() |
|||
} |
|||
}) |
|||
}, |
|||
/** |
|||
* 执行添加 |
|||
*/ |
|||
doAdd() { |
|||
if (!callVmHook(crud, CRUD.HOOK.beforeSubmit)) { |
|||
return |
|||
} |
|||
crud.status.add = CRUD.STATUS.PROCESSING |
|||
crud.crudMethod.add(crud.form).then((res) => { |
|||
crud.status.add = CRUD.STATUS.NORMAL |
|||
crud.resetForm() |
|||
crud.addSuccessNotify() |
|||
if (res && res !== 'SUCCESS' && res !== '保存成功') { |
|||
callVmHook(crud, CRUD.HOOK.afterSubmit, res) |
|||
} else { |
|||
callVmHook(crud, CRUD.HOOK.afterSubmit) |
|||
} |
|||
crud.toQuery() |
|||
}).catch(() => { |
|||
crud.status.add = CRUD.STATUS.PREPARED |
|||
callVmHook(crud, CRUD.HOOK.afterAddError) |
|||
}) |
|||
}, |
|||
/** |
|||
* 执行编辑 |
|||
*/ |
|||
doEdit() { |
|||
if (!callVmHook(crud, CRUD.HOOK.beforeSubmit)) { |
|||
return |
|||
} |
|||
crud.status.edit = CRUD.STATUS.PROCESSING |
|||
crud.crudMethod.edit(crud.form).then(() => { |
|||
crud.status.edit = CRUD.STATUS.NORMAL |
|||
crud.getDataStatus(crud.getDataId(crud.form)).edit = CRUD.STATUS.NORMAL |
|||
crud.editSuccessNotify() |
|||
crud.resetForm() |
|||
callVmHook(crud, CRUD.HOOK.afterSubmit) |
|||
crud.refresh() |
|||
}).catch(() => { |
|||
crud.status.edit = CRUD.STATUS.PREPARED |
|||
callVmHook(crud, CRUD.HOOK.afterEditError) |
|||
}) |
|||
}, |
|||
/** |
|||
* 执行删除 |
|||
* @param {*} data 数据项 |
|||
*/ |
|||
doDelete(data) { |
|||
let delAll = false |
|||
let dataStatus |
|||
const ids = [] |
|||
if (data instanceof Array) { |
|||
delAll = true |
|||
data.forEach(val => { |
|||
ids.push(this.getDataId(val)) |
|||
}) |
|||
} else { |
|||
ids.push(this.getDataId(data)) |
|||
dataStatus = crud.getDataStatus(this.getDataId(data)) |
|||
} |
|||
if (!callVmHook(crud, CRUD.HOOK.beforeDelete, data)) { |
|||
return |
|||
} |
|||
if (!delAll) { |
|||
dataStatus.delete = CRUD.STATUS.PROCESSING |
|||
} |
|||
return crud.crudMethod.del(ids).then(() => { |
|||
if (delAll) { |
|||
crud.delAllLoading = false |
|||
} else dataStatus.delete = CRUD.STATUS.PREPARED |
|||
crud.dleChangePage(1) |
|||
// crud.delSuccessNotify()
|
|||
callVmHook(crud, CRUD.HOOK.afterDelete, data) |
|||
crud.refresh() |
|||
}).catch(() => { |
|||
if (delAll) { |
|||
crud.delAllLoading = false |
|||
} else dataStatus.delete = CRUD.STATUS.PREPARED |
|||
}) |
|||
}, |
|||
/** |
|||
* 通用导出 |
|||
*/ |
|||
doExport() { |
|||
crud.downloadLoading = true |
|||
download(crud.url + '/download', crud.getQueryParams()).then(result => { |
|||
downloadFile(result, crud.title + '数据', 'xlsx') |
|||
crud.downloadLoading = false |
|||
}).catch(() => { |
|||
crud.downloadLoading = false |
|||
}) |
|||
}, |
|||
/** |
|||
* 获取查询参数 |
|||
*/ |
|||
getQueryParams: function() { |
|||
// 清除参数无值的情况
|
|||
Object.keys(crud.query).length !== 0 && Object.keys(crud.query).forEach(item => { |
|||
if (crud.query[item] === null || crud.query[item] === '') crud.query[item] = undefined |
|||
}) |
|||
Object.keys(crud.params).length !== 0 && Object.keys(crud.params).forEach(item => { |
|||
if (crud.params[item] === null || crud.params[item] === '') crud.params[item] = undefined |
|||
}) |
|||
return { |
|||
page: crud.page.page - 1, |
|||
size: crud.page.size, |
|||
sort: crud.sort, |
|||
...crud.query, |
|||
...crud.params |
|||
} |
|||
}, |
|||
// 当前页改变
|
|||
pageChangeHandler(e) { |
|||
crud.page.page = e |
|||
crud.refresh() |
|||
}, |
|||
// 每页条数改变
|
|||
sizeChangeHandler(e) { |
|||
crud.page.size = e |
|||
crud.page.page = 1 |
|||
crud.refresh() |
|||
}, |
|||
// 预防删除第二页最后一条数据时,或者多选删除第二页的数据时,页码错误导致请求无数据
|
|||
dleChangePage(size) { |
|||
if (crud.data.length === size && crud.page.page !== 1) { |
|||
crud.page.page -= 1 |
|||
} |
|||
}, |
|||
// 选择改变
|
|||
selectionChangeHandler(val) { |
|||
crud.selections = val |
|||
}, |
|||
/** |
|||
* 重置查询参数 |
|||
* @param {Boolean} toQuery 重置后进行查询操作 |
|||
*/ |
|||
resetQuery(toQuery = true) { |
|||
const defaultQuery = JSON.parse(JSON.stringify(crud.defaultQuery)) |
|||
const query = crud.query |
|||
Object.keys(query).forEach(key => { |
|||
query[key] = defaultQuery[key] |
|||
}) |
|||
// 重置参数
|
|||
this.params = {} |
|||
if (toQuery) { |
|||
crud.toQuery() |
|||
} |
|||
}, |
|||
/** |
|||
* 重置表单 |
|||
* @param {Array} data 数据 |
|||
*/ |
|||
resetForm(data) { |
|||
const form = data || (typeof crud.defaultForm === 'object' ? JSON.parse(JSON.stringify(crud.defaultForm)) : crud.defaultForm.apply(crud.findVM('form'))) |
|||
const crudFrom = crud.form |
|||
for (const key in form) { |
|||
if (crudFrom.hasOwnProperty(key)) { |
|||
crudFrom[key] = form[key] |
|||
} else { |
|||
Vue.set(crudFrom, key, form[key]) |
|||
} |
|||
} |
|||
// add by ghl 2020-10-04 页面重复添加信息时,下拉框的校验会存在,需要找工取消
|
|||
if (crud.findVM('form').$refs['form']) { |
|||
crud.findVM('form').$refs['form'].clearValidate() |
|||
} |
|||
}, |
|||
/** |
|||
* 重置数据状态 |
|||
*/ |
|||
resetDataStatus() { |
|||
const dataStatus = {} |
|||
function resetStatus(datas) { |
|||
datas.forEach(e => { |
|||
dataStatus[crud.getDataId(e)] = { |
|||
delete: 0, |
|||
edit: 0 |
|||
} |
|||
if (e.children) { |
|||
resetStatus(e.children) |
|||
} |
|||
}) |
|||
} |
|||
resetStatus(crud.data) |
|||
crud.dataStatus = dataStatus |
|||
}, |
|||
/** |
|||
* 获取数据状态 |
|||
* @param {Number | String} id 数据项id |
|||
*/ |
|||
getDataStatus(id) { |
|||
return crud.dataStatus[id] |
|||
}, |
|||
/** |
|||
* 用于树形表格多选, 选中所有 |
|||
* @param selection |
|||
*/ |
|||
selectAllChange(selection) { |
|||
// 如果选中的数目与请求到的数目相同就选中子节点,否则就清空选中
|
|||
if (selection && selection.length === crud.data.length) { |
|||
selection.forEach(val => { |
|||
crud.selectChange(selection, val) |
|||
}) |
|||
} else { |
|||
crud.getTable().clearSelection() |
|||
} |
|||
}, |
|||
/** |
|||
* 用于树形表格多选,单选的封装 |
|||
* @param selection |
|||
* @param row |
|||
*/ |
|||
selectChange(selection, row) { |
|||
// 如果selection中存在row代表是选中,否则是取消选中
|
|||
if (selection.find(val => { return crud.getDataId(val) === crud.getDataId(row) })) { |
|||
if (row.children) { |
|||
row.children.forEach(val => { |
|||
crud.getTable().toggleRowSelection(val, true) |
|||
selection.push(val) |
|||
if (val.children) { |
|||
crud.selectChange(selection, val) |
|||
} |
|||
}) |
|||
} |
|||
} else { |
|||
crud.toggleRowSelection(selection, row) |
|||
} |
|||
}, |
|||
/** |
|||
* 切换选中状态 |
|||
* @param selection |
|||
* @param data |
|||
*/ |
|||
toggleRowSelection(selection, data) { |
|||
if (data.children) { |
|||
data.children.forEach(val => { |
|||
crud.getTable().toggleRowSelection(val, false) |
|||
if (val.children) { |
|||
crud.toggleRowSelection(selection, val) |
|||
} |
|||
}) |
|||
} |
|||
}, |
|||
findVM(type) { |
|||
return crud.vms.find(vm => vm && vm.type === type).vm |
|||
}, |
|||
notify(message, type = CRUD.NOTIFICATION_TYPE.INFO) { |
|||
crud.vms[0].vm.$message({ |
|||
message, |
|||
type, |
|||
duration: 2500 |
|||
}) |
|||
}, |
|||
updateProp(name, value) { |
|||
Vue.set(crud.props, name, value) |
|||
}, |
|||
getDataId(data) { |
|||
return data[this.idField] |
|||
}, |
|||
getTable() { |
|||
return this.findVM('presenter').$refs.table |
|||
}, |
|||
attchTable() { |
|||
const table = this.getTable() |
|||
this.updateProp('table', table) |
|||
const that = this |
|||
table.$on('expand-change', (row, expanded) => { |
|||
if (!expanded) { |
|||
return |
|||
} |
|||
const lazyTreeNodeMap = table.store.states.lazyTreeNodeMap |
|||
row.children = lazyTreeNodeMap[crud.getDataId(row)] |
|||
if (row.children) { |
|||
row.children.forEach(ele => { |
|||
const id = crud.getDataId(ele) |
|||
if (that.dataStatus[id] === undefined) { |
|||
that.dataStatus[id] = { |
|||
delete: 0, |
|||
edit: 0 |
|||
} |
|||
} |
|||
}) |
|||
} |
|||
}) |
|||
} |
|||
} |
|||
const crud = Object.assign({}, data) |
|||
// 可观测化
|
|||
Vue.observable(crud) |
|||
// 附加方法
|
|||
Object.assign(crud, methods) |
|||
// 记录初始默认的查询参数,后续重置查询时使用
|
|||
Object.assign(crud, { |
|||
defaultQuery: JSON.parse(JSON.stringify(data.query)), |
|||
// 预留4位存储:组件 主页、头部、分页、表单,调试查看也方便找
|
|||
vms: Array(4), |
|||
/** |
|||
* 注册组件实例 |
|||
* @param {String} type 类型 |
|||
* @param {*} vm 组件实例 |
|||
* @param {Number} index 该参数内部使用 |
|||
*/ |
|||
registerVM(type, vm, index = -1) { |
|||
const vmObj = { |
|||
type, |
|||
vm: vm |
|||
} |
|||
if (index < 0) { |
|||
this.vms.push(vmObj) |
|||
return |
|||
} |
|||
if (index < 4) { // 内置预留vm数
|
|||
this.vms[index] = vmObj |
|||
return |
|||
} |
|||
this.vms.length = Math.max(this.vms.length, index) |
|||
this.vms.splice(index, 1, vmObj) |
|||
}, |
|||
/** |
|||
* 取消注册组件实例 |
|||
* @param {*} vm 组件实例 |
|||
*/ |
|||
unregisterVM(type, vm) { |
|||
for (let i = this.vms.length - 1; i >= 0; i--) { |
|||
if (this.vms[i] === undefined) { |
|||
continue |
|||
} |
|||
if (this.vms[i].type === type && this.vms[i].vm === vm) { |
|||
if (i < 4) { // 内置预留vm数
|
|||
this.vms[i] = undefined |
|||
} else { |
|||
this.vms.splice(i, 1) |
|||
} |
|||
break |
|||
} |
|||
} |
|||
} |
|||
}) |
|||
// 冻结处理,需要扩展数据的话,使用crud.updateProp(name, value),以crud.props.name形式访问,这个是响应式的,可以做数据绑定
|
|||
Object.freeze(crud) |
|||
return crud |
|||
} |
|||
|
|||
// hook VM
|
|||
function callVmHook(crud, hook) { |
|||
if (crud.debug) { |
|||
console.log('callVmHook: ' + hook) |
|||
} |
|||
const tagHook = crud.tag ? hook + '$' + crud.tag : null |
|||
let ret = true |
|||
const nargs = [crud] |
|||
for (let i = 2; i < arguments.length; ++i) { |
|||
nargs.push(arguments[i]) |
|||
} |
|||
// 有些组件扮演了多个角色,调用钩子时,需要去重
|
|||
const vmSet = new Set() |
|||
crud.vms.forEach(vm => vm && vmSet.add(vm.vm)) |
|||
vmSet.forEach(vm => { |
|||
if (vm[hook]) { |
|||
ret = vm[hook].apply(vm, nargs) !== false && ret |
|||
} |
|||
if (tagHook && vm[tagHook]) { |
|||
ret = vm[tagHook].apply(vm, nargs) !== false && ret |
|||
} |
|||
}) |
|||
return ret |
|||
} |
|||
|
|||
function mergeOptions(src, opts) { |
|||
const optsRet = { |
|||
...src |
|||
} |
|||
for (const key in src) { |
|||
if (opts.hasOwnProperty(key)) { |
|||
optsRet[key] = opts[key] |
|||
} |
|||
} |
|||
return optsRet |
|||
} |
|||
|
|||
/** |
|||
* 查找crud |
|||
* @param {*} vm |
|||
* @param {string} tag |
|||
*/ |
|||
function lookupCrud(vm, tag) { |
|||
tag = tag || vm.$attrs['crud-tag'] || 'default' |
|||
// function lookupCrud(vm, tag) {
|
|||
if (vm.$crud) { |
|||
const ret = vm.$crud[tag] |
|||
if (ret) { |
|||
return ret |
|||
} |
|||
} |
|||
return vm.$parent ? lookupCrud(vm.$parent, tag) : undefined |
|||
} |
|||
|
|||
/** |
|||
* crud主页 |
|||
*/ |
|||
function presenter(crud) { |
|||
if (crud) { |
|||
console.warn('[CRUD warn]: ' + 'please use $options.cruds() { return CRUD(...) or [CRUD(...), ...] }') |
|||
} |
|||
return { |
|||
data() { |
|||
// 在data中返回crud,是为了将crud与当前实例关联,组件观测crud相关属性变化
|
|||
return { |
|||
crud: this.crud |
|||
} |
|||
}, |
|||
beforeCreate() { |
|||
this.$crud = this.$crud || {} |
|||
let cruds = this.$options.cruds instanceof Function ? this.$options.cruds() : crud |
|||
if (!(cruds instanceof Array)) { |
|||
cruds = [cruds] |
|||
} |
|||
cruds.forEach(ele => { |
|||
if (this.$crud[ele.tag]) { |
|||
console.error('[CRUD error]: ' + 'crud with tag [' + ele.tag + ' is already exist') |
|||
} |
|||
this.$crud[ele.tag] = ele |
|||
ele.registerVM('presenter', this, 0) |
|||
}) |
|||
this.crud = this.$crud['defalut'] || cruds[0] |
|||
}, |
|||
methods: { |
|||
parseTime |
|||
}, |
|||
created() { |
|||
for (const k in this.$crud) { |
|||
if (this.$crud[k].queryOnPresenterCreated) { |
|||
this.$crud[k].toQuery() |
|||
} |
|||
} |
|||
}, |
|||
destroyed() { |
|||
for (const k in this.$crud) { |
|||
this.$crud[k].unregisterVM('presenter', this) |
|||
} |
|||
}, |
|||
mounted() { |
|||
// 如果table未实例化(例如使用了v-if),请稍后在适当时机crud.attchTable刷新table信息
|
|||
if (this.$refs.table !== undefined) { |
|||
this.crud.attchTable() |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 头部 |
|||
*/ |
|||
function header() { |
|||
return { |
|||
data() { |
|||
return { |
|||
crud: this.crud, |
|||
query: this.crud.query |
|||
} |
|||
}, |
|||
beforeCreate() { |
|||
this.crud = lookupCrud(this) |
|||
this.crud.registerVM('header', this, 1) |
|||
}, |
|||
destroyed() { |
|||
this.crud.unregisterVM('header', this) |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 分页 |
|||
*/ |
|||
function pagination() { |
|||
return { |
|||
data() { |
|||
return { |
|||
crud: this.crud, |
|||
page: this.crud.page |
|||
} |
|||
}, |
|||
beforeCreate() { |
|||
this.crud = lookupCrud(this) |
|||
this.crud.registerVM('pagination', this, 2) |
|||
}, |
|||
destroyed() { |
|||
this.crud.unregisterVM('pagination', this) |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 表单 |
|||
*/ |
|||
function form(defaultForm) { |
|||
return { |
|||
data() { |
|||
return { |
|||
crud: this.crud, |
|||
form: this.crud.form |
|||
} |
|||
}, |
|||
beforeCreate() { |
|||
this.crud = lookupCrud(this) |
|||
this.crud.registerVM('form', this, 3) |
|||
}, |
|||
created() { |
|||
this.crud.defaultForm = defaultForm |
|||
this.crud.resetForm() |
|||
}, |
|||
destroyed() { |
|||
this.crud.unregisterVM('form', this) |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* crud |
|||
*/ |
|||
function crud(options = {}) { |
|||
const defaultOptions = { |
|||
type: undefined |
|||
} |
|||
options = mergeOptions(defaultOptions, options) |
|||
return { |
|||
data() { |
|||
return { |
|||
crud: this.crud |
|||
} |
|||
}, |
|||
beforeCreate() { |
|||
this.crud = lookupCrud(this) |
|||
this.crud.registerVM(options.type, this) |
|||
}, |
|||
destroyed() { |
|||
this.crud.unregisterVM(options.type, this) |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* CRUD钩子 |
|||
*/ |
|||
CRUD.HOOK = { |
|||
/** 刷新 - 之前 */ |
|||
beforeRefresh: 'beforeCrudRefresh', |
|||
/** 刷新 - 之后 */ |
|||
afterRefresh: 'afterCrudRefresh', |
|||
/** 删除 - 之前 */ |
|||
beforeDelete: 'beforeCrudDelete', |
|||
/** 删除 - 之后 */ |
|||
afterDelete: 'afterCrudDelete', |
|||
/** 删除取消 - 之前 */ |
|||
beforeDeleteCancel: 'beforeCrudDeleteCancel', |
|||
/** 删除取消 - 之后 */ |
|||
afterDeleteCancel: 'afterCrudDeleteCancel', |
|||
/** 新建 - 之前 */ |
|||
beforeToAdd: 'beforeCrudToAdd', |
|||
/** 新建 - 之后 */ |
|||
afterToAdd: 'afterCrudToAdd', |
|||
/** 编辑 - 之前 */ |
|||
beforeToEdit: 'beforeCrudToEdit', |
|||
/** 编辑 - 之后 */ |
|||
afterToEdit: 'afterCrudToEdit', |
|||
/** 开始 "新建/编辑" - 之前 */ |
|||
beforeToCU: 'beforeCrudToCU', |
|||
/** 开始 "新建/编辑" - 之后 */ |
|||
afterToCU: 'afterCrudToCU', |
|||
/** "新建/编辑" 验证 - 之前 */ |
|||
beforeValidateCU: 'beforeCrudValidateCU', |
|||
/** "新建/编辑" 验证 - 之后 */ |
|||
afterValidateCU: 'afterCrudValidateCU', |
|||
/** 添加取消 - 之前 */ |
|||
beforeAddCancel: 'beforeCrudAddCancel', |
|||
/** 添加取消 - 之后 */ |
|||
afterAddCancel: 'afterCrudAddCancel', |
|||
/** 编辑取消 - 之前 */ |
|||
beforeEditCancel: 'beforeCrudEditCancel', |
|||
/** 编辑取消 - 之后 */ |
|||
afterEditCancel: 'afterCrudEditCancel', |
|||
/** 提交 - 之前 */ |
|||
beforeSubmit: 'beforeCrudSubmitCU', |
|||
/** 提交 - 之后 */ |
|||
afterSubmit: 'afterCrudSubmitCU', |
|||
afterAddError: 'afterCrudAddError', |
|||
afterEditError: 'afterCrudEditError' |
|||
} |
|||
|
|||
/** |
|||
* CRUD状态 |
|||
*/ |
|||
CRUD.STATUS = { |
|||
NORMAL: 0, |
|||
PREPARED: 1, |
|||
PROCESSING: 2 |
|||
} |
|||
|
|||
/** |
|||
* CRUD通知类型 |
|||
*/ |
|||
CRUD.NOTIFICATION_TYPE = { |
|||
SUCCESS: 'success', |
|||
WARNING: 'warning', |
|||
INFO: 'info', |
|||
ERROR: 'error' |
|||
} |
|||
|
|||
export default CRUD |
|||
|
|||
export { |
|||
presenter, |
|||
header, |
|||
form, |
|||
pagination, |
|||
crud |
|||
} |
|||
@ -0,0 +1,45 @@ |
|||
<script> |
|||
import { DatePicker, DatePickerOptions } from 'element-ui' |
|||
import { calendarShortcuts } from '@/utils/shortcuts' |
|||
|
|||
export default { |
|||
name: 'DateRangePicker', |
|||
mixins: [DatePicker], |
|||
props: { |
|||
type: { |
|||
type: String, |
|||
default: 'daterange' |
|||
}, |
|||
valueFormat: { |
|||
type: String, |
|||
default: 'yyyy-MM-dd HH:mm:ss' |
|||
}, |
|||
defaultTime: { |
|||
type: Array, |
|||
default: _ => ['00:00:00', '23:59:59'] |
|||
}, |
|||
pickerOptions: { |
|||
type: DatePickerOptions, |
|||
default: _ => { |
|||
return { shortcuts: calendarShortcuts } |
|||
} |
|||
}, |
|||
size: { |
|||
type: String, |
|||
default: 'small' |
|||
}, |
|||
rangeSeparator: { |
|||
type: String, |
|||
default: ':' |
|||
}, |
|||
startPlaceholder: { |
|||
type: String, |
|||
default: '开始日期' |
|||
}, |
|||
endPlaceholder: { |
|||
type: String, |
|||
default: '结束日期' |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,29 @@ |
|||
import Vue from 'vue' |
|||
import { get as getDictDetail } from '@/api/archivesConfig/dictDetail' |
|||
|
|||
export default class Dict { |
|||
constructor(dict) { |
|||
this.dict = dict |
|||
} |
|||
|
|||
async init(names, completeCallback) { |
|||
if (names === undefined || name === null) { |
|||
throw new Error('need Dict names') |
|||
} |
|||
const ps = [] |
|||
names.forEach(n => { |
|||
Vue.set(this.dict.dict, n, {}) |
|||
Vue.set(this.dict.label, n, {}) |
|||
Vue.set(this.dict, n, []) |
|||
ps.push(getDictDetail(n).then(data => { |
|||
this.dict[n].splice(0, 0, ...data.content) |
|||
data.content.forEach(d => { |
|||
Vue.set(this.dict.dict[n], d.value, d) |
|||
Vue.set(this.dict.label[n], d.value, d.label) |
|||
}) |
|||
})) |
|||
}) |
|||
await Promise.all(ps) |
|||
completeCallback() |
|||
} |
|||
} |
|||
@ -0,0 +1,29 @@ |
|||
import Dict from './Dict' |
|||
|
|||
const install = function(Vue) { |
|||
Vue.mixin({ |
|||
data() { |
|||
if (this.$options.dicts instanceof Array) { |
|||
const dict = { |
|||
dict: {}, |
|||
label: {} |
|||
} |
|||
return { |
|||
dict |
|||
} |
|||
} |
|||
return {} |
|||
}, |
|||
created() { |
|||
if (this.$options.dicts instanceof Array) { |
|||
new Dict(this.dict).init(this.$options.dicts, () => { |
|||
this.$nextTick(() => { |
|||
this.$emit('dictReady') |
|||
}) |
|||
}) |
|||
} |
|||
} |
|||
}) |
|||
} |
|||
|
|||
export default { install } |
|||
@ -0,0 +1,16 @@ |
|||
<template> |
|||
<div> |
|||
<svg-icon icon-class="doc" @click="click" /> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'Doc', |
|||
methods: { |
|||
click() { |
|||
window.open('https://XXXXX/pages/010101/', '_blank') |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,106 @@ |
|||
<template> |
|||
<div :class="className" :style="{height:height,width:width}" /> |
|||
</template> |
|||
|
|||
<script> |
|||
import echarts from 'echarts' |
|||
require('echarts/theme/macarons') // echarts theme |
|||
import { debounce } from '@/utils' |
|||
|
|||
const animationDuration = 6000 |
|||
|
|||
export default { |
|||
props: { |
|||
className: { |
|||
type: String, |
|||
default: 'chart' |
|||
}, |
|||
width: { |
|||
type: String, |
|||
default: '100%' |
|||
}, |
|||
height: { |
|||
type: String, |
|||
default: '300px' |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
chart: null |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.initChart() |
|||
this.__resizeHandler = debounce(() => { |
|||
if (this.chart) { |
|||
this.chart.resize() |
|||
} |
|||
}, 100) |
|||
window.addEventListener('resize', this.__resizeHandler) |
|||
}, |
|||
beforeDestroy() { |
|||
if (!this.chart) { |
|||
return |
|||
} |
|||
window.removeEventListener('resize', this.__resizeHandler) |
|||
this.chart.dispose() |
|||
this.chart = null |
|||
}, |
|||
methods: { |
|||
initChart() { |
|||
this.chart = echarts.init(this.$el, 'macarons') |
|||
|
|||
this.chart.setOption({ |
|||
tooltip: { |
|||
trigger: 'axis', |
|||
axisPointer: { // 坐标轴指示器,坐标轴触发有效 |
|||
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow' |
|||
} |
|||
}, |
|||
grid: { |
|||
top: 10, |
|||
left: '2%', |
|||
right: '2%', |
|||
bottom: '3%', |
|||
containLabel: true |
|||
}, |
|||
xAxis: [{ |
|||
type: 'category', |
|||
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], |
|||
axisTick: { |
|||
alignWithLabel: true |
|||
} |
|||
}], |
|||
yAxis: [{ |
|||
type: 'value', |
|||
axisTick: { |
|||
show: false |
|||
} |
|||
}], |
|||
series: [{ |
|||
name: 'pageA', |
|||
type: 'bar', |
|||
stack: 'vistors', |
|||
barWidth: '60%', |
|||
data: [79, 52, 200, 334, 390, 330, 220], |
|||
animationDuration |
|||
}, { |
|||
name: 'pageB', |
|||
type: 'bar', |
|||
stack: 'vistors', |
|||
barWidth: '60%', |
|||
data: [80, 52, 200, 334, 390, 330, 220], |
|||
animationDuration |
|||
}, { |
|||
name: 'pageC', |
|||
type: 'bar', |
|||
stack: 'vistors', |
|||
barWidth: '60%', |
|||
data: [30, 52, 200, 334, 390, 330, 220], |
|||
animationDuration |
|||
}] |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,438 @@ |
|||
<template> |
|||
<div :class="className" :style="{height:height,width:width}" /> |
|||
</template> |
|||
|
|||
<script> |
|||
import echarts from 'echarts' |
|||
|
|||
require('echarts/theme/macarons') // echarts theme |
|||
import { debounce } from '@/utils' |
|||
|
|||
export default { |
|||
props: { |
|||
className: { |
|||
type: String, |
|||
default: 'chart' |
|||
}, |
|||
width: { |
|||
type: String, |
|||
default: '100%' |
|||
}, |
|||
height: { |
|||
type: String, |
|||
default: '500px' |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
chart: null |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.initChart() |
|||
this.__resizeHandler = debounce(() => { |
|||
if (this.chart) { |
|||
this.chart.resize() |
|||
} |
|||
}, 100) |
|||
window.addEventListener('resize', this.__resizeHandler) |
|||
}, |
|||
beforeDestroy() { |
|||
if (!this.chart) { |
|||
return |
|||
} |
|||
window.removeEventListener('resize', this.__resizeHandler) |
|||
this.chart.dispose() |
|||
this.chart = null |
|||
}, |
|||
methods: { |
|||
initChart() { |
|||
this.chart = echarts.init(this.$el, 'macarons') |
|||
const dataMap = {} |
|||
|
|||
function dataFormatter(obj) { |
|||
const pList = ['北京', '天津', '河北', '山西', '内蒙古', '辽宁', '吉林', '黑龙江', '上海', '江苏', '浙江', '安徽', '福建', '江西', '山东', '河南', '湖北', '湖南', '广东', '广西', '海南', '重庆', '四川', '贵州', '云南', '西藏', '陕西', '甘肃', '青海', '宁夏', '新疆'] |
|||
let temp |
|||
for (let year = 2002; year <= 2011; year++) { |
|||
let max = 0 |
|||
let sum = 0 |
|||
temp = obj[year] |
|||
for (let i = 0, l = temp.length; i < l; i++) { |
|||
max = Math.max(max, temp[i]) |
|||
sum += temp[i] |
|||
obj[year][i] = { |
|||
name: pList[i], |
|||
value: temp[i] |
|||
} |
|||
} |
|||
obj[year + 'max'] = Math.floor(max / 100) * 100 |
|||
obj[year + 'sum'] = sum |
|||
} |
|||
return obj |
|||
} |
|||
|
|||
dataMap.dataGDP = dataFormatter({ |
|||
2011: [16251.93, 11307.28, 24515.76, 11237.55, 14359.88, 22226.7, 10568.83, 12582, 19195.69, 49110.27, 32318.85, 15300.65, 17560.18, 11702.82, 45361.85, 26931.03, 19632.26, 19669.56, 53210.28, 11720.87, 2522.66, 10011.37, 21026.68, 5701.84, 8893.12, 605.83, 12512.3, 5020.37, 1670.44, 2102.21, 6610.05], |
|||
2010: [14113.58, 9224.46, 20394.26, 9200.86, 11672, 18457.27, 8667.58, 10368.6, 17165.98, 41425.48, 27722.31, 12359.33, 14737.12, 9451.26, 39169.92, 23092.36, 15967.61, 16037.96, 46013.06, 9569.85, 2064.5, 7925.58, 17185.48, 4602.16, 7224.18, 507.46, 10123.48, 4120.75, 1350.43, 1689.65, 5437.47], |
|||
2009: [12153.03, 7521.85, 17235.48, 7358.31, 9740.25, 15212.49, 7278.75, 8587, 15046.45, 34457.3, 22990.35, 10062.82, 12236.53, 7655.18, 33896.65, 19480.46, 12961.1, 13059.69, 39482.56, 7759.16, 1654.21, 6530.01, 14151.28, 3912.68, 6169.75, 441.36, 8169.8, 3387.56, 1081.27, 1353.31, 4277.05], |
|||
2008: [11115, 6719.01, 16011.97, 7315.4, 8496.2, 13668.58, 6426.1, 8314.37, 14069.87, 30981.98, 21462.69, 8851.66, 10823.01, 6971.05, 30933.28, 18018.53, 11328.92, 11555, 36796.71, 7021, 1503.06, 5793.66, 12601.23, 3561.56, 5692.12, 394.85, 7314.58, 3166.82, 1018.62, 1203.92, 4183.21], |
|||
2007: [9846.81, 5252.76, 13607.32, 6024.45, 6423.18, 11164.3, 5284.69, 7104, 12494.01, 26018.48, 18753.73, 7360.92, 9248.53, 5800.25, 25776.91, 15012.46, 9333.4, 9439.6, 31777.01, 5823.41, 1254.17, 4676.13, 10562.39, 2884.11, 4772.52, 341.43, 5757.29, 2703.98, 797.35, 919.11, 3523.16], |
|||
2006: [8117.78, 4462.74, 11467.6, 4878.61, 4944.25, 9304.52, 4275.12, 6211.8, 10572.24, 21742.05, 15718.47, 6112.5, 7583.85, 4820.53, 21900.19, 12362.79, 7617.47, 7688.67, 26587.76, 4746.16, 1065.67, 3907.23, 8690.24, 2338.98, 3988.14, 290.76, 4743.61, 2277.35, 648.5, 725.9, 3045.26], |
|||
2005: [6969.52, 3905.64, 10012.11, 4230.53, 3905.03, 8047.26, 3620.27, 5513.7, 9247.66, 18598.69, 13417.68, 5350.17, 6554.69, 4056.76, 18366.87, 10587.42, 6590.19, 6596.1, 22557.37, 3984.1, 918.75, 3467.72, 7385.1, 2005.42, 3462.73, 248.8, 3933.72, 1933.98, 543.32, 612.61, 2604.19], |
|||
2004: [6033.21, 3110.97, 8477.63, 3571.37, 3041.07, 6672, 3122.01, 4750.6, 8072.83, 15003.6, 11648.7, 4759.3, 5763.35, 3456.7, 15021.84, 8553.79, 5633.24, 5641.94, 18864.62, 3433.5, 819.66, 3034.58, 6379.63, 1677.8, 3081.91, 220.34, 3175.58, 1688.49, 466.1, 537.11, 2209.09], |
|||
2003: [5007.21, 2578.03, 6921.29, 2855.23, 2388.38, 6002.54, 2662.08, 4057.4, 6694.23, 12442.87, 9705.02, 3923.11, 4983.67, 2807.41, 12078.15, 6867.7, 4757.45, 4659.99, 15844.64, 2821.11, 713.96, 2555.72, 5333.09, 1426.34, 2556.02, 185.09, 2587.72, 1399.83, 390.2, 445.36, 1886.35], |
|||
2002: [4315, 2150.76, 6018.28, 2324.8, 1940.94, 5458.22, 2348.54, 3637.2, 5741.03, 10606.85, 8003.67, 3519.72, 4467.55, 2450.48, 10275.5, 6035.48, 4212.82, 4151.54, 13502.42, 2523.73, 642.73, 2232.86, 4725.01, 1243.43, 2312.82, 162.04, 2253.39, 1232.03, 340.65, 377.16, 1612.6] |
|||
}) |
|||
|
|||
dataMap.dataPI = dataFormatter({ |
|||
2011: [136.27, 159.72, 2905.73, 641.42, 1306.3, 1915.57, 1277.44, 1701.5, 124.94, 3064.78, 1583.04, 2015.31, 1612.24, 1391.07, 3973.85, 3512.24, 2569.3, 2768.03, 2665.2, 2047.23, 659.23, 844.52, 2983.51, 726.22, 1411.01, 74.47, 1220.9, 678.75, 155.08, 184.14, 1139.03], |
|||
2010: [124.36, 145.58, 2562.81, 554.48, 1095.28, 1631.08, 1050.15, 1302.9, 114.15, 2540.1, 1360.56, 1729.02, 1363.67, 1206.98, 3588.28, 3258.09, 2147, 2325.5, 2286.98, 1675.06, 539.83, 685.38, 2482.89, 625.03, 1108.38, 68.72, 988.45, 599.28, 134.92, 159.29, 1078.63], |
|||
2009: [118.29, 128.85, 2207.34, 477.59, 929.6, 1414.9, 980.57, 1154.33, 113.82, 2261.86, 1163.08, 1495.45, 1182.74, 1098.66, 3226.64, 2769.05, 1795.9, 1969.69, 2010.27, 1458.49, 462.19, 606.8, 2240.61, 550.27, 1067.6, 63.88, 789.64, 497.05, 107.4, 127.25, 759.74], |
|||
2008: [112.83, 122.58, 2034.59, 313.58, 907.95, 1302.02, 916.72, 1088.94, 111.8, 2100.11, 1095.96, 1418.09, 1158.17, 1060.38, 3002.65, 2658.78, 1780, 1892.4, 1973.05, 1453.75, 436.04, 575.4, 2216.15, 539.19, 1020.56, 60.62, 753.72, 462.27, 105.57, 118.94, 691.07], |
|||
2007: [101.26, 110.19, 1804.72, 311.97, 762.1, 1133.42, 783.8, 915.38, 101.84, 1816.31, 986.02, 1200.18, 1002.11, 905.77, 2509.14, 2217.66, 1378, 1626.48, 1695.57, 1241.35, 361.07, 482.39, 2032, 446.38, 837.35, 54.89, 592.63, 387.55, 83.41, 97.89, 628.72], |
|||
2006: [88.8, 103.35, 1461.81, 276.77, 634.94, 939.43, 672.76, 750.14, 93.81, 1545.05, 925.1, 1011.03, 865.98, 786.14, 2138.9, 1916.74, 1140.41, 1272.2, 1532.17, 1032.47, 323.48, 386.38, 1595.48, 382.06, 724.4, 50.9, 484.81, 334, 67.55, 79.54, 527.8], |
|||
2005: [88.68, 112.38, 1400, 262.42, 589.56, 882.41, 625.61, 684.6, 90.26, 1461.51, 892.83, 966.5, 827.36, 727.37, 1963.51, 1892.01, 1082.13, 1100.65, 1428.27, 912.5, 300.75, 463.4, 1481.14, 368.94, 661.69, 48.04, 435.77, 308.06, 65.34, 72.07, 509.99], |
|||
2004: [87.36, 105.28, 1370.43, 276.3, 522.8, 798.43, 568.69, 605.79, 83.45, 1367.58, 814.1, 950.5, 786.84, 664.5, 1778.45, 1649.29, 1020.09, 1022.45, 1248.59, 817.88, 278.76, 428.05, 1379.93, 334.5, 607.75, 44.3, 387.88, 286.78, 60.7, 65.33, 461.26], |
|||
2003: [84.11, 89.91, 1064.05, 215.19, 420.1, 615.8, 488.23, 504.8, 81.02, 1162.45, 717.85, 749.4, 692.94, 560, 1480.67, 1198.7, 798.35, 886.47, 1072.91, 658.78, 244.29, 339.06, 1128.61, 298.69, 494.6, 40.7, 302.66, 237.91, 48.47, 55.63, 412.9], |
|||
2002: [82.44, 84.21, 956.84, 197.8, 374.69, 590.2, 446.17, 474.2, 79.68, 1110.44, 685.2, 783.66, 664.78, 535.98, 1390, 1288.36, 707, 847.25, 1015.08, 601.99, 222.89, 317.87, 1047.95, 281.1, 463.44, 39.75, 282.21, 215.51, 47.31, 52.95, 305] |
|||
}) |
|||
|
|||
dataMap.dataSI = dataFormatter({ |
|||
2011: [3752.48, 5928.32, 13126.86, 6635.26, 8037.69, 12152.15, 5611.48, 5962.41, 7927.89, 25203.28, 16555.58, 8309.38, 9069.2, 6390.55, 24017.11, 15427.08, 9815.94, 9361.99, 26447.38, 5675.32, 714.5, 5543.04, 11029.13, 2194.33, 3780.32, 208.79, 6935.59, 2377.83, 975.18, 1056.15, 3225.9], |
|||
2010: [3388.38, 4840.23, 10707.68, 5234, 6367.69, 9976.82, 4506.31, 5025.15, 7218.32, 21753.93, 14297.93, 6436.62, 7522.83, 5122.88, 21238.49, 13226.38, 7767.24, 7343.19, 23014.53, 4511.68, 571, 4359.12, 8672.18, 1800.06, 3223.49, 163.92, 5446.1, 1984.97, 744.63, 827.91, 2592.15], |
|||
2009: [2855.55, 3987.84, 8959.83, 3993.8, 5114, 7906.34, 3541.92, 4060.72, 6001.78, 18566.37, 11908.49, 4905.22, 6005.3, 3919.45, 18901.83, 11010.5, 6038.08, 5687.19, 19419.7, 3381.54, 443.43, 3448.77, 6711.87, 1476.62, 2582.53, 136.63, 4236.42, 1527.24, 575.33, 662.32, 1929.59], |
|||
2008: [2626.41, 3709.78, 8701.34, 4242.36, 4376.19, 7158.84, 3097.12, 4319.75, 6085.84, 16993.34, 11567.42, 4198.93, 5318.44, 3554.81, 17571.98, 10259.99, 5082.07, 5028.93, 18502.2, 3037.74, 423.55, 3057.78, 5823.39, 1370.03, 2452.75, 115.56, 3861.12, 1470.34, 557.12, 609.98, 2070.76], |
|||
2007: [2509.4, 2892.53, 7201.88, 3454.49, 3193.67, 5544.14, 2475.45, 3695.58, 5571.06, 14471.26, 10154.25, 3370.96, 4476.42, 2975.53, 14647.53, 8282.83, 4143.06, 3977.72, 16004.61, 2425.29, 364.26, 2368.53, 4648.79, 1124.79, 2038.39, 98.48, 2986.46, 1279.32, 419.03, 455.04, 1647.55], |
|||
2006: [2191.43, 2457.08, 6110.43, 2755.66, 2374.96, 4566.83, 1915.29, 3365.31, 4969.95, 12282.89, 8511.51, 2711.18, 3695.04, 2419.74, 12574.03, 6724.61, 3365.08, 3187.05, 13469.77, 1878.56, 308.62, 1871.65, 3775.14, 967.54, 1705.83, 80.1, 2452.44, 1043.19, 331.91, 351.58, 1459.3], |
|||
2005: [2026.51, 2135.07, 5271.57, 2357.04, 1773.21, 3869.4, 1580.83, 2971.68, 4381.2, 10524.96, 7164.75, 2245.9, 3175.92, 1917.47, 10478.62, 5514.14, 2852.12, 2612.57, 11356.6, 1510.68, 240.83, 1564, 3067.23, 821.16, 1426.42, 63.52, 1951.36, 838.56, 264.61, 281.05, 1164.79], |
|||
2004: [1853.58, 1685.93, 4301.73, 1919.4, 1248.27, 3061.62, 1329.68, 2487.04, 3892.12, 8437.99, 6250.38, 1844.9, 2770.49, 1566.4, 8478.69, 4182.1, 2320.6, 2190.54, 9280.73, 1253.7, 205.6, 1376.91, 2489.4, 681.5, 1281.63, 52.74, 1553.1, 713.3, 211.7, 244.05, 914.47], |
|||
2003: [1487.15, 1337.31, 3417.56, 1463.38, 967.49, 2898.89, 1098.37, 2084.7, 3209.02, 6787.11, 5096.38, 1535.29, 2340.82, 1204.33, 6485.05, 3310.14, 1956.02, 1777.74, 7592.78, 984.08, 175.82, 1135.31, 2014.8, 569.37, 1047.66, 47.64, 1221.17, 572.02, 171.92, 194.27, 719.54], |
|||
2002: [1249.99, 1069.08, 2911.69, 1134.31, 754.78, 2609.85, 943.49, 1843.6, 2622.45, 5604.49, 4090.48, 1337.04, 2036.97, 941.77, 5184.98, 2768.75, 1709.89, 1523.5, 6143.4, 846.89, 148.88, 958.87, 1733.38, 481.96, 934.88, 32.72, 1007.56, 501.69, 144.51, 153.06, 603.15] |
|||
}) |
|||
|
|||
dataMap.dataTI = dataFormatter({ |
|||
2011: [12363.18, 5219.24, 8483.17, 3960.87, 5015.89, 8158.98, 3679.91, 4918.09, 11142.86, 20842.21, 14180.23, 4975.96, 6878.74, 3921.2, 17370.89, 7991.72, 7247.02, 7539.54, 24097.7, 3998.33, 1148.93, 3623.81, 7014.04, 2781.29, 3701.79, 322.57, 4355.81, 1963.79, 540.18, 861.92, 2245.12], |
|||
2010: [10600.84, 4238.65, 7123.77, 3412.38, 4209.03, 6849.37, 3111.12, 4040.55, 9833.51, 17131.45, 12063.82, 4193.69, 5850.62, 3121.4, 14343.14, 6607.89, 6053.37, 6369.27, 20711.55, 3383.11, 953.67, 2881.08, 6030.41, 2177.07, 2892.31, 274.82, 3688.93, 1536.5, 470.88, 702.45, 1766.69], |
|||
2009: [9179.19, 3405.16, 6068.31, 2886.92, 3696.65, 5891.25, 2756.26, 3371.95, 8930.85, 13629.07, 9918.78, 3662.15, 5048.49, 2637.07, 11768.18, 5700.91, 5127.12, 5402.81, 18052.59, 2919.13, 748.59, 2474.44, 5198.8, 1885.79, 2519.62, 240.85, 3143.74, 1363.27, 398.54, 563.74, 1587.72], |
|||
2008: [8375.76, 2886.65, 5276.04, 2759.46, 3212.06, 5207.72, 2412.26, 2905.68, 7872.23, 11888.53, 8799.31, 3234.64, 4346.4, 2355.86, 10358.64, 5099.76, 4466.85, 4633.67, 16321.46, 2529.51, 643.47, 2160.48, 4561.69, 1652.34, 2218.81, 218.67, 2699.74, 1234.21, 355.93, 475, 1421.38], |
|||
2007: [7236.15, 2250.04, 4600.72, 2257.99, 2467.41, 4486.74, 2025.44, 2493.04, 6821.11, 9730.91, 7613.46, 2789.78, 3770, 1918.95, 8620.24, 4511.97, 3812.34, 3835.4, 14076.83, 2156.76, 528.84, 1825.21, 3881.6, 1312.94, 1896.78, 188.06, 2178.2, 1037.11, 294.91, 366.18, 1246.89], |
|||
2006: [5837.55, 1902.31, 3895.36, 1846.18, 1934.35, 3798.26, 1687.07, 2096.35, 5508.48, 7914.11, 6281.86, 2390.29, 3022.83, 1614.65, 7187.26, 3721.44, 3111.98, 3229.42, 11585.82, 1835.12, 433.57, 1649.2, 3319.62, 989.38, 1557.91, 159.76, 1806.36, 900.16, 249.04, 294.78, 1058.16], |
|||
2005: [4854.33, 1658.19, 3340.54, 1611.07, 1542.26, 3295.45, 1413.83, 1857.42, 4776.2, 6612.22, 5360.1, 2137.77, 2551.41, 1411.92, 5924.74, 3181.27, 2655.94, 2882.88, 9772.5, 1560.92, 377.17, 1440.32, 2836.73, 815.32, 1374.62, 137.24, 1546.59, 787.36, 213.37, 259.49, 929.41], |
|||
2004: [4092.27, 1319.76, 2805.47, 1375.67, 1270, 2811.95, 1223.64, 1657.77, 4097.26, 5198.03, 4584.22, 1963.9, 2206.02, 1225.8, 4764.7, 2722.4, 2292.55, 2428.95, 8335.3, 1361.92, 335.3, 1229.62, 2510.3, 661.8, 1192.53, 123.3, 1234.6, 688.41, 193.7, 227.73, 833.36], |
|||
2003: [3435.95, 1150.81, 2439.68, 1176.65, 1000.79, 2487.85, 1075.48, 1467.9, 3404.19, 4493.31, 3890.79, 1638.42, 1949.91, 1043.08, 4112.43, 2358.86, 2003.08, 1995.78, 7178.94, 1178.25, 293.85, 1081.35, 2189.68, 558.28, 1013.76, 96.76, 1063.89, 589.91, 169.81, 195.46, 753.91], |
|||
2002: [2982.57, 997.47, 2149.75, 992.69, 811.47, 2258.17, 958.88, 1319.4, 3038.9, 3891.92, 3227.99, 1399.02, 1765.8, 972.73, 3700.52, 1978.37, 1795.93, 1780.79, 6343.94, 1074.85, 270.96, 956.12, 1943.68, 480.37, 914.5, 89.56, 963.62, 514.83, 148.83, 171.14, 704.5] |
|||
}) |
|||
|
|||
dataMap.dataEstate = dataFormatter({ |
|||
2011: [1074.93, 411.46, 918.02, 224.91, 384.76, 876.12, 238.61, 492.1, 1019.68, 2747.89, 1677.13, 634.92, 911.16, 402.51, 1838.14, 987, 634.67, 518.04, 3321.31, 465.68, 208.71, 396.28, 620.62, 160.3, 222.31, 17.44, 398.03, 134.25, 29.05, 79.01, 176.22], |
|||
2010: [1006.52, 377.59, 697.79, 192, 309.25, 733.37, 212.32, 391.89, 1002.5, 2600.95, 1618.17, 532.17, 679.03, 340.56, 1622.15, 773.23, 564.41, 464.21, 2813.95, 405.79, 188.33, 266.38, 558.56, 139.64, 223.45, 14.54, 315.95, 110.02, 25.41, 60.53, 143.44], |
|||
2009: [1062.47, 308.73, 612.4, 173.31, 286.65, 605.27, 200.14, 301.18, 1237.56, 2025.39, 1316.84, 497.94, 656.61, 305.9, 1329.59, 622.98, 546.11, 400.11, 2470.63, 348.98, 121.76, 229.09, 548.14, 136.15, 205.14, 13.28, 239.92, 101.37, 23.05, 47.56, 115.23], |
|||
2008: [844.59, 227.88, 513.81, 166.04, 273.3, 500.81, 182.7, 244.47, 939.34, 1626.13, 1052.03, 431.27, 506.98, 281.96, 1104.95, 512.42, 526.88, 340.07, 2057.45, 282.96, 95.6, 191.21, 453.63, 104.81, 195.48, 15.08, 193.27, 93.8, 19.96, 38.85, 89.79], |
|||
2007: [821.5, 183.44, 467.97, 134.12, 191.01, 410.43, 153.03, 225.81, 958.06, 1365.71, 981.42, 366.57, 511.5, 225.96, 953.69, 447.44, 409.65, 301.8, 2029.77, 239.45, 67.19, 196.06, 376.84, 93.19, 193.59, 13.24, 153.98, 83.52, 16.98, 29.49, 91.28], |
|||
2006: [658.3, 156.64, 397.14, 117.01, 136.5, 318.54, 131.01, 194.7, 773.61, 1017.91, 794.41, 281.98, 435.22, 184.67, 786.51, 348.7, 294.73, 254.81, 1722.07, 192.2, 44.45, 158.2, 336.2, 80.24, 165.92, 11.92, 125.2, 73.21, 15.17, 25.53, 68.9], |
|||
2005: [493.73, 122.67, 330.87, 106, 98.75, 256.77, 112.29, 163.34, 715.97, 799.73, 688.86, 231.66, 331.8, 171.88, 664.9, 298.19, 217.17, 215.63, 1430.37, 165.05, 38.2, 143.88, 286.23, 76.38, 148.69, 10.02, 108.62, 63.78, 14.1, 22.97, 55.79], |
|||
2004: [436.11, 106.14, 231.08, 95.1, 73.81, 203.1, 97.93, 137.74, 666.3, 534.17, 587.83, 188.28, 248.44, 167.2, 473.27, 236.44, 204.8, 191.5, 1103.75, 122.52, 30.64, 129.12, 264.3, 68.3, 116.54, 5.8, 95.9, 56.84, 13, 20.78, 53.55], |
|||
2003: [341.88, 92.31, 185.19, 78.73, 61.05, 188.49, 91.99, 127.2, 487.82, 447.47, 473.16, 162.63, 215.84, 138.02, 418.21, 217.58, 176.8, 186.49, 955.66, 100.93, 25.14, 113.69, 231.72, 59.86, 103.79, 4.35, 83.9, 48.09, 11.41, 16.85, 47.84], |
|||
2002: [298.02, 73.04, 140.89, 65.83, 51.48, 130.94, 76.11, 118.7, 384.86, 371.09, 360.63, 139.18, 188.09, 125.27, 371.13, 199.31, 145.17, 165.29, 808.16, 82.83, 21.45, 90.48, 210.82, 53.49, 95.68, 3.42, 77.68, 41.52, 9.74, 13.46, 43.04] |
|||
}) |
|||
|
|||
dataMap.dataFinancial = dataFormatter({ |
|||
2011: [2215.41, 756.5, 746.01, 519.32, 447.46, 755.57, 207.65, 370.78, 2277.4, 2600.11, 2730.29, 503.85, 862.41, 357.44, 1640.41, 868.2, 674.57, 501.09, 2916.13, 445.37, 105.24, 704.66, 868.15, 297.27, 456.23, 31.7, 432.11, 145.05, 62.56, 134.18, 288.77], |
|||
2010: [1863.61, 572.99, 615.42, 448.3, 346.44, 639.27, 190.12, 304.59, 1950.96, 2105.92, 2326.58, 396.17, 767.58, 241.49, 1361.45, 697.68, 561.27, 463.16, 2658.76, 384.53, 78.12, 496.56, 654.7, 231.51, 375.08, 27.08, 384.75, 100.54, 54.53, 97.87, 225.2], |
|||
2009: [1603.63, 461.2, 525.67, 361.64, 291.1, 560.2, 180.83, 227.54, 1804.28, 1596.98, 1899.33, 359.6, 612.2, 165.1, 1044.9, 499.92, 479.11, 402.57, 2283.29, 336.82, 65.73, 389.97, 524.63, 194.44, 351.74, 23.17, 336.21, 88.27, 45.63, 75.54, 198.87], |
|||
2008: [1519.19, 368.1, 420.74, 290.91, 219.09, 455.07, 147.24, 177.43, 1414.21, 1298.48, 1653.45, 313.81, 497.65, 130.57, 880.28, 413.83, 393.05, 334.32, 1972.4, 249.01, 47.33, 303.01, 411.14, 151.55, 277.66, 22.42, 287.16, 72.49, 36.54, 64.8, 171.97], |
|||
2007: [1302.77, 288.17, 347.65, 218.73, 148.3, 386.34, 126.03, 155.48, 1209.08, 1054.25, 1251.43, 223.85, 385.84, 101.34, 734.9, 302.31, 337.27, 260.14, 1705.08, 190.73, 34.43, 247.46, 359.11, 122.25, 168.55, 11.51, 231.03, 61.6, 27.67, 51.05, 149.22], |
|||
2006: [982.37, 186.87, 284.04, 169.63, 108.21, 303.41, 100.75, 74.17, 825.2, 653.25, 906.37, 166.01, 243.9, 79.75, 524.94, 219.72, 174.99, 204.72, 899.91, 129.14, 16.37, 213.7, 299.5, 89.43, 143.62, 6.44, 152.25, 50.51, 23.69, 36.99, 99.25], |
|||
2005: [840.2, 147.4, 213.47, 135.07, 72.52, 232.85, 83.63, 35.03, 675.12, 492.4, 686.32, 127.05, 186.12, 69.55, 448.36, 181.74, 127.32, 162.37, 661.81, 91.93, 13.16, 185.18, 262.26, 73.67, 130.5, 7.57, 127.58, 44.73, 20.36, 32.25, 80.34], |
|||
2004: [713.79, 136.97, 209.1, 110.29, 55.89, 188.04, 77.17, 32.2, 612.45, 440.5, 523.49, 94.1, 171, 65.1, 343.37, 170.82, 118.85, 118.64, 602.68, 74, 11.56, 162.38, 236.5, 60.3, 118.4, 5.4, 90.1, 42.99, 19, 27.92, 70.3], |
|||
2003: [635.56, 112.79, 199.87, 118.48, 55.89, 145.38, 73.15, 32.2, 517.97, 392.11, 451.54, 87.45, 150.09, 64.31, 329.71, 165.11, 107.31, 99.35, 534.28, 61.59, 10.68, 147.04, 206.24, 48.01, 105.48, 4.74, 77.87, 42.31, 17.98, 24.8, 64.92], |
|||
2002: [561.91, 76.86, 179.6, 124.1, 48.39, 137.18, 75.45, 31.6, 485.25, 368.86, 347.53, 81.85, 138.28, 76.51, 310.07, 158.77, 96.95, 92.43, 454.65, 35.86, 10.08, 134.52, 183.13, 41.45, 102.39, 2.81, 67.3, 42.08, 16.75, 21.45, 52.18] |
|||
}) |
|||
|
|||
this.chart.setOption({ |
|||
baseOption: { |
|||
timeline: { |
|||
axisType: 'category', |
|||
autoPlay: true, |
|||
playInterval: 1000, |
|||
data: [ |
|||
'2002-01-01', '2003-01-01', '2004-01-01', |
|||
{ |
|||
value: '2005-01-01', |
|||
tooltip: { |
|||
formatter: '{b} GDP达到一个高度' |
|||
}, |
|||
symbol: 'diamond', |
|||
symbolSize: 16 |
|||
}, |
|||
'2006-01-01', '2007-01-01', '2008-01-01', '2009-01-01', '2010-01-01', |
|||
{ |
|||
value: '2011-01-01', |
|||
tooltip: { |
|||
formatter: function(params) { |
|||
return params.name + 'GDP达到又一个高度' |
|||
} |
|||
}, |
|||
symbol: 'diamond', |
|||
symbolSize: 18 |
|||
} |
|||
], |
|||
label: { |
|||
formatter: function(s) { |
|||
return (new Date(s)).getFullYear() |
|||
} |
|||
} |
|||
}, |
|||
title: { |
|||
subtext: '数据来自国家统计局' |
|||
}, |
|||
tooltip: {}, |
|||
legend: { |
|||
x: 'right', |
|||
data: ['第一产业', '第二产业', '第三产业', 'GDP', '金融', '房地产'], |
|||
selected: { |
|||
'GDP': false, '金融': false, '房地产': false |
|||
} |
|||
}, |
|||
calculable: true, |
|||
grid: { |
|||
top: 80, |
|||
bottom: 100, |
|||
tooltip: { |
|||
trigger: 'axis', |
|||
axisPointer: { |
|||
type: 'shadow', |
|||
label: { |
|||
show: true, |
|||
formatter: function(params) { |
|||
return params.value.replace('\n', '') |
|||
} |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
xAxis: [ |
|||
{ |
|||
'type': 'category', |
|||
'axisLabel': { |
|||
'interval': 0, |
|||
rotate: 45 |
|||
}, |
|||
'data': [ |
|||
'北京', '\n天津', '河北', '\n山西', '内蒙古', '\n辽宁', '吉林', '\n黑龙江', |
|||
'上海', '\n江苏', '浙江', '\n安徽', '福建', '\n江西', '山东', '\n河南', |
|||
'湖北', '\n湖南', '广东', '\n广西', '海南', '\n重庆', '四川', '\n贵州', |
|||
'云南', '\n西藏', '陕西', '\n甘肃', '青海', '\n宁夏', '新疆' |
|||
], |
|||
splitLine: { show: false } |
|||
} |
|||
], |
|||
yAxis: [ |
|||
{ |
|||
type: 'value', |
|||
name: 'GDP(亿元)' |
|||
} |
|||
], |
|||
series: [ |
|||
{ name: 'GDP', type: 'bar' }, |
|||
{ name: '金融', type: 'bar' }, |
|||
{ name: '房地产', type: 'bar' }, |
|||
{ name: '第一产业', type: 'bar' }, |
|||
{ name: '第二产业', type: 'bar' }, |
|||
{ name: '第三产业', type: 'bar' }, |
|||
{ |
|||
name: 'GDP占比', |
|||
type: 'pie', |
|||
center: ['75%', '35%'], |
|||
radius: '28%', |
|||
z: 100 |
|||
} |
|||
] |
|||
}, |
|||
options: [ |
|||
{ |
|||
title: { text: '2002全国宏观经济指标' }, |
|||
series: [ |
|||
{ data: dataMap.dataGDP['2002'] }, |
|||
{ data: dataMap.dataFinancial['2002'] }, |
|||
{ data: dataMap.dataEstate['2002'] }, |
|||
{ data: dataMap.dataPI['2002'] }, |
|||
{ data: dataMap.dataSI['2002'] }, |
|||
{ data: dataMap.dataTI['2002'] }, |
|||
{ |
|||
data: [ |
|||
{ name: '第一产业', value: dataMap.dataPI['2002sum'] }, |
|||
{ name: '第二产业', value: dataMap.dataSI['2002sum'] }, |
|||
{ name: '第三产业', value: dataMap.dataTI['2002sum'] } |
|||
] |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
title: { text: '2003全国宏观经济指标' }, |
|||
series: [ |
|||
{ data: dataMap.dataGDP['2003'] }, |
|||
{ data: dataMap.dataFinancial['2003'] }, |
|||
{ data: dataMap.dataEstate['2003'] }, |
|||
{ data: dataMap.dataPI['2003'] }, |
|||
{ data: dataMap.dataSI['2003'] }, |
|||
{ data: dataMap.dataTI['2003'] }, |
|||
{ |
|||
data: [ |
|||
{ name: '第一产业', value: dataMap.dataPI['2003sum'] }, |
|||
{ name: '第二产业', value: dataMap.dataSI['2003sum'] }, |
|||
{ name: '第三产业', value: dataMap.dataTI['2003sum'] } |
|||
] |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
title: { text: '2004全国宏观经济指标' }, |
|||
series: [ |
|||
{ data: dataMap.dataGDP['2004'] }, |
|||
{ data: dataMap.dataFinancial['2004'] }, |
|||
{ data: dataMap.dataEstate['2004'] }, |
|||
{ data: dataMap.dataPI['2004'] }, |
|||
{ data: dataMap.dataSI['2004'] }, |
|||
{ data: dataMap.dataTI['2004'] }, |
|||
{ |
|||
data: [ |
|||
{ name: '第一产业', value: dataMap.dataPI['2004sum'] }, |
|||
{ name: '第二产业', value: dataMap.dataSI['2004sum'] }, |
|||
{ name: '第三产业', value: dataMap.dataTI['2004sum'] } |
|||
] |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
title: { text: '2005全国宏观经济指标' }, |
|||
series: [ |
|||
{ data: dataMap.dataGDP['2005'] }, |
|||
{ data: dataMap.dataFinancial['2005'] }, |
|||
{ data: dataMap.dataEstate['2005'] }, |
|||
{ data: dataMap.dataPI['2005'] }, |
|||
{ data: dataMap.dataSI['2005'] }, |
|||
{ data: dataMap.dataTI['2005'] }, |
|||
{ |
|||
data: [ |
|||
{ name: '第一产业', value: dataMap.dataPI['2005sum'] }, |
|||
{ name: '第二产业', value: dataMap.dataSI['2005sum'] }, |
|||
{ name: '第三产业', value: dataMap.dataTI['2005sum'] } |
|||
] |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
title: { text: '2006全国宏观经济指标' }, |
|||
series: [ |
|||
{ data: dataMap.dataGDP['2006'] }, |
|||
{ data: dataMap.dataFinancial['2006'] }, |
|||
{ data: dataMap.dataEstate['2006'] }, |
|||
{ data: dataMap.dataPI['2006'] }, |
|||
{ data: dataMap.dataSI['2006'] }, |
|||
{ data: dataMap.dataTI['2006'] }, |
|||
{ |
|||
data: [ |
|||
{ name: '第一产业', value: dataMap.dataPI['2006sum'] }, |
|||
{ name: '第二产业', value: dataMap.dataSI['2006sum'] }, |
|||
{ name: '第三产业', value: dataMap.dataTI['2006sum'] } |
|||
] |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
title: { text: '2007全国宏观经济指标' }, |
|||
series: [ |
|||
{ data: dataMap.dataGDP['2007'] }, |
|||
{ data: dataMap.dataFinancial['2007'] }, |
|||
{ data: dataMap.dataEstate['2007'] }, |
|||
{ data: dataMap.dataPI['2007'] }, |
|||
{ data: dataMap.dataSI['2007'] }, |
|||
{ data: dataMap.dataTI['2007'] }, |
|||
{ |
|||
data: [ |
|||
{ name: '第一产业', value: dataMap.dataPI['2007sum'] }, |
|||
{ name: '第二产业', value: dataMap.dataSI['2007sum'] }, |
|||
{ name: '第三产业', value: dataMap.dataTI['2007sum'] } |
|||
] |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
title: { text: '2008全国宏观经济指标' }, |
|||
series: [ |
|||
{ data: dataMap.dataGDP['2008'] }, |
|||
{ data: dataMap.dataFinancial['2008'] }, |
|||
{ data: dataMap.dataEstate['2008'] }, |
|||
{ data: dataMap.dataPI['2008'] }, |
|||
{ data: dataMap.dataSI['2008'] }, |
|||
{ data: dataMap.dataTI['2008'] }, |
|||
{ |
|||
data: [ |
|||
{ name: '第一产业', value: dataMap.dataPI['2008sum'] }, |
|||
{ name: '第二产业', value: dataMap.dataSI['2008sum'] }, |
|||
{ name: '第三产业', value: dataMap.dataTI['2008sum'] } |
|||
] |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
title: { text: '2009全国宏观经济指标' }, |
|||
series: [ |
|||
{ data: dataMap.dataGDP['2009'] }, |
|||
{ data: dataMap.dataFinancial['2009'] }, |
|||
{ data: dataMap.dataEstate['2009'] }, |
|||
{ data: dataMap.dataPI['2009'] }, |
|||
{ data: dataMap.dataSI['2009'] }, |
|||
{ data: dataMap.dataTI['2009'] }, |
|||
{ |
|||
data: [ |
|||
{ name: '第一产业', value: dataMap.dataPI['2009sum'] }, |
|||
{ name: '第二产业', value: dataMap.dataSI['2009sum'] }, |
|||
{ name: '第三产业', value: dataMap.dataTI['2009sum'] } |
|||
] |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
title: { text: '2010全国宏观经济指标' }, |
|||
series: [ |
|||
{ data: dataMap.dataGDP['2010'] }, |
|||
{ data: dataMap.dataFinancial['2010'] }, |
|||
{ data: dataMap.dataEstate['2010'] }, |
|||
{ data: dataMap.dataPI['2010'] }, |
|||
{ data: dataMap.dataSI['2010'] }, |
|||
{ data: dataMap.dataTI['2010'] }, |
|||
{ |
|||
data: [ |
|||
{ name: '第一产业', value: dataMap.dataPI['2010sum'] }, |
|||
{ name: '第二产业', value: dataMap.dataSI['2010sum'] }, |
|||
{ name: '第三产业', value: dataMap.dataTI['2010sum'] } |
|||
] |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
title: { text: '2011全国宏观经济指标' }, |
|||
series: [ |
|||
{ data: dataMap.dataGDP['2011'] }, |
|||
{ data: dataMap.dataFinancial['2011'] }, |
|||
{ data: dataMap.dataEstate['2011'] }, |
|||
{ data: dataMap.dataPI['2011'] }, |
|||
{ data: dataMap.dataSI['2011'] }, |
|||
{ data: dataMap.dataTI['2011'] }, |
|||
{ |
|||
data: [ |
|||
{ name: '第一产业', value: dataMap.dataPI['2011sum'] }, |
|||
{ name: '第二产业', value: dataMap.dataSI['2011sum'] }, |
|||
{ name: '第三产业', value: dataMap.dataTI['2011sum'] } |
|||
] |
|||
} |
|||
] |
|||
} |
|||
] |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,120 @@ |
|||
<template> |
|||
<div :class="className" :style="{height:height,width:width}" /> |
|||
</template> |
|||
|
|||
<script> |
|||
import echarts from 'echarts' |
|||
|
|||
require('echarts/theme/macarons') // echarts theme |
|||
import { debounce } from '@/utils' |
|||
|
|||
export default { |
|||
props: { |
|||
className: { |
|||
type: String, |
|||
default: 'chart' |
|||
}, |
|||
width: { |
|||
type: String, |
|||
default: '100%' |
|||
}, |
|||
height: { |
|||
type: String, |
|||
default: '300px' |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
chart: null |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.initChart() |
|||
this.__resizeHandler = debounce(() => { |
|||
if (this.chart) { |
|||
this.chart.resize() |
|||
} |
|||
}, 100) |
|||
window.addEventListener('resize', this.__resizeHandler) |
|||
}, |
|||
beforeDestroy() { |
|||
if (!this.chart) { |
|||
return |
|||
} |
|||
window.removeEventListener('resize', this.__resizeHandler) |
|||
this.chart.dispose() |
|||
this.chart = null |
|||
}, |
|||
methods: { |
|||
initChart() { |
|||
this.chart = echarts.init(this.$el, 'macarons') |
|||
|
|||
this.chart.setOption({ |
|||
title: { |
|||
text: '漏斗图', |
|||
subtext: '纯属虚构' |
|||
}, |
|||
tooltip: { |
|||
trigger: 'item', |
|||
formatter: '{a} <br/>{b} : {c}%' |
|||
}, |
|||
toolbox: { |
|||
feature: { |
|||
dataView: { readOnly: false }, |
|||
restore: {}, |
|||
saveAsImage: {} |
|||
} |
|||
}, |
|||
legend: { |
|||
data: ['展现', '点击', '访问', '咨询', '订单'] |
|||
}, |
|||
calculable: true, |
|||
series: [ |
|||
{ |
|||
name: '漏斗图', |
|||
type: 'funnel', |
|||
left: '10%', |
|||
top: 60, |
|||
bottom: 60, |
|||
width: '80%', |
|||
// height: {totalHeight} - y - y2, |
|||
min: 0, |
|||
max: 100, |
|||
minSize: '0%', |
|||
maxSize: '100%', |
|||
sort: 'descending', |
|||
gap: 2, |
|||
label: { |
|||
show: true, |
|||
position: 'inside' |
|||
}, |
|||
labelLine: { |
|||
length: 10, |
|||
lineStyle: { |
|||
width: 1, |
|||
type: 'solid' |
|||
} |
|||
}, |
|||
itemStyle: { |
|||
borderColor: '#fff', |
|||
borderWidth: 1 |
|||
}, |
|||
emphasis: { |
|||
label: { |
|||
fontSize: 20 |
|||
} |
|||
}, |
|||
data: [ |
|||
{ value: 60, name: '访问' }, |
|||
{ value: 40, name: '咨询' }, |
|||
{ value: 20, name: '订单' }, |
|||
{ value: 80, name: '点击' }, |
|||
{ value: 100, name: '展现' } |
|||
] |
|||
} |
|||
] |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,74 @@ |
|||
<template> |
|||
<div :class="className" :style="{height:height,width:width}" /> |
|||
</template> |
|||
|
|||
<script> |
|||
import echarts from 'echarts' |
|||
|
|||
require('echarts/theme/macarons') // echarts theme |
|||
import { debounce } from '@/utils' |
|||
|
|||
export default { |
|||
props: { |
|||
className: { |
|||
type: String, |
|||
default: 'chart' |
|||
}, |
|||
width: { |
|||
type: String, |
|||
default: '100%' |
|||
}, |
|||
height: { |
|||
type: String, |
|||
default: '300px' |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
chart: null |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.initChart() |
|||
this.__resizeHandler = debounce(() => { |
|||
if (this.chart) { |
|||
this.chart.resize() |
|||
} |
|||
}, 100) |
|||
window.addEventListener('resize', this.__resizeHandler) |
|||
}, |
|||
beforeDestroy() { |
|||
if (!this.chart) { |
|||
return |
|||
} |
|||
window.removeEventListener('resize', this.__resizeHandler) |
|||
this.chart.dispose() |
|||
this.chart = null |
|||
}, |
|||
methods: { |
|||
initChart() { |
|||
this.chart = echarts.init(this.$el, 'macarons') |
|||
|
|||
this.chart.setOption({ |
|||
tooltip: { |
|||
formatter: '{a} <br/>{b} : {c}%' |
|||
}, |
|||
toolbox: { |
|||
feature: { |
|||
restore: {}, |
|||
saveAsImage: {} |
|||
} |
|||
}, |
|||
series: [ |
|||
{ |
|||
name: '业务指标', |
|||
type: 'gauge', |
|||
detail: { formatter: '{value}%' }, |
|||
data: [{ value: 50, name: '完成率' }] |
|||
} |
|||
] |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,101 @@ |
|||
<template> |
|||
<div :class="className" :style="{height:height,width:width}" /> |
|||
</template> |
|||
|
|||
<script> |
|||
import echarts from 'echarts' |
|||
|
|||
require('echarts/theme/macarons') // echarts theme |
|||
import { debounce } from '@/utils' |
|||
|
|||
export default { |
|||
props: { |
|||
className: { |
|||
type: String, |
|||
default: 'chart' |
|||
}, |
|||
width: { |
|||
type: String, |
|||
default: '100%' |
|||
}, |
|||
height: { |
|||
type: String, |
|||
default: '300px' |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
chart: null |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.initChart() |
|||
this.__resizeHandler = debounce(() => { |
|||
if (this.chart) { |
|||
this.chart.resize() |
|||
} |
|||
}, 100) |
|||
window.addEventListener('resize', this.__resizeHandler) |
|||
}, |
|||
beforeDestroy() { |
|||
if (!this.chart) { |
|||
return |
|||
} |
|||
window.removeEventListener('resize', this.__resizeHandler) |
|||
this.chart.dispose() |
|||
this.chart = null |
|||
}, |
|||
methods: { |
|||
initChart() { |
|||
this.chart = echarts.init(this.$el, 'macarons') |
|||
const axisData = ['周一', '周二', '周三', '很长很长的周四', '周五', '周六', '周日'] |
|||
const data = axisData.map(function(item, i) { |
|||
return Math.round(Math.random() * 1000 * (i + 1)) |
|||
}) |
|||
const links = data.map(function(item, i) { |
|||
return { |
|||
source: i, |
|||
target: i + 1 |
|||
} |
|||
}) |
|||
links.pop() |
|||
this.chart.setOption({ |
|||
title: { |
|||
text: '笛卡尔坐标系上的 Graph' |
|||
}, |
|||
tooltip: {}, |
|||
xAxis: { |
|||
type: 'category', |
|||
boundaryGap: false, |
|||
data: axisData |
|||
}, |
|||
yAxis: { |
|||
type: 'value' |
|||
}, |
|||
series: [ |
|||
{ |
|||
type: 'graph', |
|||
layout: 'none', |
|||
coordinateSystem: 'cartesian2d', |
|||
symbolSize: 40, |
|||
label: { |
|||
normal: { |
|||
show: true |
|||
} |
|||
}, |
|||
edgeSymbol: ['circle', 'arrow'], |
|||
edgeSymbolSize: [4, 10], |
|||
data: data, |
|||
links: links, |
|||
lineStyle: { |
|||
normal: { |
|||
color: '#2f4554' |
|||
} |
|||
} |
|||
} |
|||
] |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,105 @@ |
|||
<template> |
|||
<div :class="className" :style="{height:height,width:width}" /> |
|||
</template> |
|||
|
|||
<script> |
|||
import echarts from 'echarts' |
|||
|
|||
require('echarts/theme/macarons') // echarts theme |
|||
import { debounce } from '@/utils' |
|||
|
|||
export default { |
|||
props: { |
|||
className: { |
|||
type: String, |
|||
default: 'chart' |
|||
}, |
|||
width: { |
|||
type: String, |
|||
default: '100%' |
|||
}, |
|||
height: { |
|||
type: String, |
|||
default: '300px' |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
chart: null |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.initChart() |
|||
this.__resizeHandler = debounce(() => { |
|||
if (this.chart) { |
|||
this.chart.resize() |
|||
} |
|||
}, 100) |
|||
window.addEventListener('resize', this.__resizeHandler) |
|||
}, |
|||
beforeDestroy() { |
|||
if (!this.chart) { |
|||
return |
|||
} |
|||
window.removeEventListener('resize', this.__resizeHandler) |
|||
this.chart.dispose() |
|||
this.chart = null |
|||
}, |
|||
methods: { |
|||
initChart() { |
|||
this.chart = echarts.init(this.$el, 'macarons') |
|||
|
|||
this.chart.setOption({ |
|||
tooltip: { |
|||
position: 'top' |
|||
}, |
|||
animation: false, |
|||
grid: { |
|||
height: '50%', |
|||
y: '10%' |
|||
}, |
|||
xAxis: { |
|||
type: 'category', |
|||
data: ['12a', '1a', '2a', '3a', '4a', '5a', '6a', '7a', '8a', '9a', '10a', '11a', '12p', '1p', '2p', '3p', '4p', '5p', '6p', '7p', '8p', '9p', '10p', '11p'], |
|||
splitArea: { |
|||
show: true |
|||
} |
|||
}, |
|||
yAxis: { |
|||
type: 'category', |
|||
data: ['Saturday', 'Friday', 'Thursday', 'Wednesday', 'Tuesday', 'Monday', 'Sunday'], |
|||
splitArea: { |
|||
show: true |
|||
} |
|||
}, |
|||
visualMap: { |
|||
min: 0, |
|||
max: 10, |
|||
calculable: true, |
|||
orient: 'horizontal', |
|||
left: 'center', |
|||
bottom: '15%' |
|||
}, |
|||
series: [{ |
|||
name: 'Punch Card', |
|||
type: 'heatmap', |
|||
data: [[0, 0, 5], [0, 1, 1], [0, 2, 0], [0, 3, 0], [0, 4, 0], [0, 5, 0], [0, 6, 0], [0, 7, 0], [0, 8, 0], [0, 9, 0], [0, 10, 0], [0, 11, 2], [0, 12, 4], [0, 13, 1], [0, 14, 1], [0, 15, 3], [0, 16, 4], [0, 17, 6], [0, 18, 4], [0, 19, 4], [0, 20, 3], [0, 21, 3], [0, 22, 2], [0, 23, 5], [1, 0, 7], [1, 1, 0], [1, 2, 0], [1, 3, 0], [1, 4, 0], [1, 5, 0], [1, 6, 0], [1, 7, 0], [1, 8, 0], [1, 9, 0], [1, 10, 5], [1, 11, 2], [1, 12, 2], [1, 13, 6], [1, 14, 9], [1, 15, 11], [1, 16, 6], [1, 17, 7], [1, 18, 8], [1, 19, 12], [1, 20, 5], [1, 21, 5], [1, 22, 7], [1, 23, 2], [2, 0, 1], [2, 1, 1], [2, 2, 0], [2, 3, 0], [2, 4, 0], [2, 5, 0], [2, 6, 0], [2, 7, 0], [2, 8, 0], [2, 9, 0], [2, 10, 3], [2, 11, 2], [2, 12, 1], [2, 13, 9], [2, 14, 8], [2, 15, 10], [2, 16, 6], [2, 17, 5], [2, 18, 5], [2, 19, 5], [2, 20, 7], [2, 21, 4], [2, 22, 2], [2, 23, 4], [3, 0, 7], [3, 1, 3], [3, 2, 0], [3, 3, 0], [3, 4, 0], [3, 5, 0], [3, 6, 0], [3, 7, 0], [3, 8, 1], [3, 9, 0], [3, 10, 5], [3, 11, 4], [3, 12, 7], [3, 13, 14], [3, 14, 13], [3, 15, 12], [3, 16, 9], [3, 17, 5], [3, 18, 5], [3, 19, 10], [3, 20, 6], [3, 21, 4], [3, 22, 4], [3, 23, 1], [4, 0, 1], [4, 1, 3], [4, 2, 0], [4, 3, 0], [4, 4, 0], [4, 5, 1], [4, 6, 0], [4, 7, 0], [4, 8, 0], [4, 9, 2], [4, 10, 4], [4, 11, 4], [4, 12, 2], [4, 13, 4], [4, 14, 4], [4, 15, 14], [4, 16, 12], [4, 17, 1], [4, 18, 8], [4, 19, 5], [4, 20, 3], [4, 21, 7], [4, 22, 3], [4, 23, 0], [5, 0, 2], [5, 1, 1], [5, 2, 0], [5, 3, 3], [5, 4, 0], [5, 5, 0], [5, 6, 0], [5, 7, 0], [5, 8, 2], [5, 9, 0], [5, 10, 4], [5, 11, 1], [5, 12, 5], [5, 13, 10], [5, 14, 5], [5, 15, 7], [5, 16, 11], [5, 17, 6], [5, 18, 0], [5, 19, 5], [5, 20, 3], [5, 21, 4], [5, 22, 2], [5, 23, 0], [6, 0, 1], [6, 1, 0], [6, 2, 0], [6, 3, 0], [6, 4, 0], [6, 5, 0], [6, 6, 0], [6, 7, 0], [6, 8, 0], [6, 9, 0], [6, 10, 1], [6, 11, 0], [6, 12, 2], [6, 13, 1], [6, 14, 3], [6, 15, 4], [6, 16, 0], [6, 17, 0], [6, 18, 0], [6, 19, 0], [6, 20, 1], [6, 21, 2], [6, 22, 2], [6, 23, 6]].map(function(item) { |
|||
return [item[1], item[0], item[2] || '-'] |
|||
}), |
|||
label: { |
|||
normal: { |
|||
show: true |
|||
} |
|||
}, |
|||
itemStyle: { |
|||
emphasis: { |
|||
shadowBlur: 10, |
|||
shadowColor: 'rgba(0, 0, 0, 0.5)' |
|||
} |
|||
} |
|||
}] |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,96 @@ |
|||
<template> |
|||
<div :class="className" :style="{height:height,width:width}" /> |
|||
</template> |
|||
|
|||
<script> |
|||
import echarts from 'echarts' |
|||
import 'echarts-gl' |
|||
|
|||
require('echarts/theme/macarons') // echarts theme |
|||
import { debounce } from '@/utils' |
|||
|
|||
export default { |
|||
props: { |
|||
className: { |
|||
type: String, |
|||
default: 'chart' |
|||
}, |
|||
width: { |
|||
type: String, |
|||
default: '100%' |
|||
}, |
|||
height: { |
|||
type: String, |
|||
default: '300px' |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
chart: null |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.initChart() |
|||
this.__resizeHandler = debounce(() => { |
|||
if (this.chart) { |
|||
this.chart.resize() |
|||
} |
|||
}, 100) |
|||
window.addEventListener('resize', this.__resizeHandler) |
|||
}, |
|||
beforeDestroy() { |
|||
if (!this.chart) { |
|||
return |
|||
} |
|||
window.removeEventListener('resize', this.__resizeHandler) |
|||
this.chart.dispose() |
|||
this.chart = null |
|||
}, |
|||
methods: { |
|||
initChart() { |
|||
this.chart = echarts.init(this.$el, 'macarons') |
|||
const data = [] |
|||
for (let t = 0; t < 25; t += 0.001) { |
|||
const x = (1 + 0.25 * Math.cos(75 * t)) * Math.cos(t) |
|||
const y = (1 + 0.25 * Math.cos(75 * t)) * Math.sin(t) |
|||
const z = t + 2.0 * Math.sin(75 * t) |
|||
data.push([x, y, z]) |
|||
} |
|||
this.chart.setOption({ |
|||
tooltip: {}, |
|||
backgroundColor: '#fff', |
|||
visualMap: { |
|||
show: false, |
|||
dimension: 2, |
|||
min: 0, |
|||
max: 30, |
|||
inRange: { |
|||
color: ['#313695', '#4575b4', '#74add1', '#abd9e9', '#e0f3f8', '#ffffbf', '#fee090', '#fdae61', '#f46d43', '#d73027', '#a50026'] |
|||
} |
|||
}, |
|||
xAxis3D: { |
|||
type: 'value' |
|||
}, |
|||
yAxis3D: { |
|||
type: 'value' |
|||
}, |
|||
zAxis3D: { |
|||
type: 'value' |
|||
}, |
|||
grid3D: { |
|||
viewControl: { |
|||
projection: 'orthographic' |
|||
} |
|||
}, |
|||
series: [{ |
|||
type: 'line3D', |
|||
data: data, |
|||
lineStyle: { |
|||
width: 4 |
|||
} |
|||
}] |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,84 @@ |
|||
<template> |
|||
<div :class="className" :style="{height:height,width:width}" /> |
|||
</template> |
|||
|
|||
<script> |
|||
import echarts from 'echarts' |
|||
require('echarts/theme/macarons') // echarts theme |
|||
import { debounce } from '@/utils' |
|||
|
|||
export default { |
|||
props: { |
|||
className: { |
|||
type: String, |
|||
default: 'chart' |
|||
}, |
|||
width: { |
|||
type: String, |
|||
default: '100%' |
|||
}, |
|||
height: { |
|||
type: String, |
|||
default: '300px' |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
chart: null |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.initChart() |
|||
this.__resizeHandler = debounce(() => { |
|||
if (this.chart) { |
|||
this.chart.resize() |
|||
} |
|||
}, 100) |
|||
window.addEventListener('resize', this.__resizeHandler) |
|||
}, |
|||
beforeDestroy() { |
|||
if (!this.chart) { |
|||
return |
|||
} |
|||
window.removeEventListener('resize', this.__resizeHandler) |
|||
this.chart.dispose() |
|||
this.chart = null |
|||
}, |
|||
methods: { |
|||
initChart() { |
|||
this.chart = echarts.init(this.$el, 'macarons') |
|||
|
|||
this.chart.setOption({ |
|||
tooltip: { |
|||
trigger: 'item', |
|||
formatter: '{a} <br/>{b} : {c} ({d}%)' |
|||
}, |
|||
legend: { |
|||
left: 'center', |
|||
bottom: '10', |
|||
data: ['Industries', 'Technology', 'Forex', 'Gold', 'Forecasts'] |
|||
}, |
|||
calculable: true, |
|||
series: [ |
|||
{ |
|||
name: 'WEEKLY WRITE ARTICLES', |
|||
type: 'pie', |
|||
roseType: 'radius', |
|||
radius: [15, 95], |
|||
center: ['50%', '38%'], |
|||
data: [ |
|||
{ value: 730, name: '案卷' }, |
|||
// { value: 240, name: 'Technology' }, |
|||
// { value: 149, name: 'Forex' }, |
|||
// { value: 100, name: 'Gold' }, |
|||
{ value: 900, name: '文件' } |
|||
], |
|||
animationEasing: 'cubicInOut', |
|||
animationDuration: 2600 |
|||
} |
|||
] |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,149 @@ |
|||
<template> |
|||
<div :class="className" :style="{height:height,width:width}" /> |
|||
</template> |
|||
|
|||
<script> |
|||
import echarts from 'echarts' |
|||
|
|||
require('echarts/theme/macarons') // echarts theme |
|||
import { debounce } from '@/utils' |
|||
|
|||
export default { |
|||
props: { |
|||
className: { |
|||
type: String, |
|||
default: 'chart' |
|||
}, |
|||
width: { |
|||
type: String, |
|||
default: '100%' |
|||
}, |
|||
height: { |
|||
type: String, |
|||
default: '300px' |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
chart: null |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.initChart() |
|||
this.__resizeHandler = debounce(() => { |
|||
if (this.chart) { |
|||
this.chart.resize() |
|||
} |
|||
}, 100) |
|||
window.addEventListener('resize', this.__resizeHandler) |
|||
}, |
|||
beforeDestroy() { |
|||
if (!this.chart) { |
|||
return |
|||
} |
|||
window.removeEventListener('resize', this.__resizeHandler) |
|||
this.chart.dispose() |
|||
this.chart = null |
|||
}, |
|||
methods: { |
|||
initChart() { |
|||
this.chart = echarts.init(this.$el, 'macarons') |
|||
|
|||
this.chart.setOption({ |
|||
title: { |
|||
text: 'Graph 简单示例' |
|||
}, |
|||
tooltip: {}, |
|||
animationDurationUpdate: 1500, |
|||
animationEasingUpdate: 'quinticInOut', |
|||
series: [ |
|||
{ |
|||
type: 'graph', |
|||
layout: 'none', |
|||
symbolSize: 50, |
|||
roam: true, |
|||
label: { |
|||
normal: { |
|||
show: true |
|||
} |
|||
}, |
|||
edgeSymbol: ['circle', 'arrow'], |
|||
edgeSymbolSize: [4, 10], |
|||
edgeLabel: { |
|||
normal: { |
|||
textStyle: { |
|||
fontSize: 20 |
|||
} |
|||
} |
|||
}, |
|||
data: [{ |
|||
name: '节点1', |
|||
x: 100, |
|||
y: 300 |
|||
}, { |
|||
name: '节点2', |
|||
x: 1000, |
|||
y: 300 |
|||
}, { |
|||
name: '节点3', |
|||
x: 550, |
|||
y: 100 |
|||
}, { |
|||
name: '节点4', |
|||
x: 550, |
|||
y: 500 |
|||
}], |
|||
// links: [], |
|||
links: [{ |
|||
source: 0, |
|||
target: 1, |
|||
symbolSize: [5, 20], |
|||
label: { |
|||
normal: { |
|||
show: true |
|||
} |
|||
}, |
|||
lineStyle: { |
|||
normal: { |
|||
width: 5, |
|||
curveness: 0.2 |
|||
} |
|||
} |
|||
}, { |
|||
source: '节点2', |
|||
target: '节点1', |
|||
label: { |
|||
normal: { |
|||
show: true |
|||
} |
|||
}, |
|||
lineStyle: { |
|||
normal: { curveness: 0.2 } |
|||
} |
|||
}, { |
|||
source: '节点1', |
|||
target: '节点3' |
|||
}, { |
|||
source: '节点2', |
|||
target: '节点3' |
|||
}, { |
|||
source: '节点2', |
|||
target: '节点4' |
|||
}, { |
|||
source: '节点1', |
|||
target: '节点4' |
|||
}], |
|||
lineStyle: { |
|||
normal: { |
|||
opacity: 0.9, |
|||
width: 2, |
|||
curveness: 0 |
|||
} |
|||
} |
|||
} |
|||
] |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,120 @@ |
|||
<template> |
|||
<div :class="className" :style="{height:height,width:width}" /> |
|||
</template> |
|||
|
|||
<script> |
|||
import echarts from 'echarts' |
|||
require('echarts/theme/macarons') // echarts theme |
|||
import { debounce } from '@/utils' |
|||
|
|||
const animationDuration = 3000 |
|||
|
|||
export default { |
|||
props: { |
|||
className: { |
|||
type: String, |
|||
default: 'chart' |
|||
}, |
|||
width: { |
|||
type: String, |
|||
default: '100%' |
|||
}, |
|||
height: { |
|||
type: String, |
|||
default: '300px' |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
chart: null |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.initChart() |
|||
this.__resizeHandler = debounce(() => { |
|||
if (this.chart) { |
|||
this.chart.resize() |
|||
} |
|||
}, 100) |
|||
window.addEventListener('resize', this.__resizeHandler) |
|||
}, |
|||
beforeDestroy() { |
|||
if (!this.chart) { |
|||
return |
|||
} |
|||
window.removeEventListener('resize', this.__resizeHandler) |
|||
this.chart.dispose() |
|||
this.chart = null |
|||
}, |
|||
methods: { |
|||
initChart() { |
|||
this.chart = echarts.init(this.$el, 'macarons') |
|||
|
|||
this.chart.setOption({ |
|||
tooltip: { |
|||
trigger: 'axis', |
|||
axisPointer: { // 坐标轴指示器,坐标轴触发有效 |
|||
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow' |
|||
} |
|||
}, |
|||
radar: { |
|||
radius: '66%', |
|||
center: ['50%', '42%'], |
|||
splitNumber: 8, |
|||
splitArea: { |
|||
areaStyle: { |
|||
color: 'rgba(127,95,132,.3)', |
|||
opacity: 1, |
|||
shadowBlur: 45, |
|||
shadowColor: 'rgba(0,0,0,.5)', |
|||
shadowOffsetX: 0, |
|||
shadowOffsetY: 15 |
|||
} |
|||
}, |
|||
indicator: [ |
|||
{ name: 'Sales', max: 10000 }, |
|||
{ name: 'Administration', max: 20000 }, |
|||
{ name: 'Information Techology', max: 20000 }, |
|||
{ name: 'Customer Support', max: 20000 }, |
|||
{ name: 'Development', max: 20000 }, |
|||
{ name: 'Marketing', max: 20000 } |
|||
] |
|||
}, |
|||
legend: { |
|||
left: 'center', |
|||
bottom: '10', |
|||
data: ['Allocated Budget', 'Expected Spending', 'Actual Spending'] |
|||
}, |
|||
series: [{ |
|||
type: 'radar', |
|||
symbolSize: 0, |
|||
areaStyle: { |
|||
normal: { |
|||
shadowBlur: 13, |
|||
shadowColor: 'rgba(0,0,0,.2)', |
|||
shadowOffsetX: 0, |
|||
shadowOffsetY: 10, |
|||
opacity: 1 |
|||
} |
|||
}, |
|||
data: [ |
|||
{ |
|||
value: [5000, 7000, 12000, 11000, 15000, 14000], |
|||
name: 'Allocated Budget' |
|||
}, |
|||
{ |
|||
value: [4000, 9000, 15000, 15000, 13000, 11000], |
|||
name: 'Expected Spending' |
|||
}, |
|||
{ |
|||
value: [5500, 11000, 12000, 15000, 12000, 12000], |
|||
name: 'Actual Spending' |
|||
} |
|||
], |
|||
animationDuration: animationDuration |
|||
}] |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,149 @@ |
|||
<template> |
|||
<div :class="className" :style="{height:height,width:width}" /> |
|||
</template> |
|||
|
|||
<script> |
|||
import echarts from 'echarts' |
|||
|
|||
require('echarts/theme/macarons') // echarts theme |
|||
import { debounce } from '@/utils' |
|||
|
|||
export default { |
|||
props: { |
|||
className: { |
|||
type: String, |
|||
default: 'chart' |
|||
}, |
|||
width: { |
|||
type: String, |
|||
default: '100%' |
|||
}, |
|||
height: { |
|||
type: String, |
|||
default: '500px' |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
chart: null |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.initChart() |
|||
this.__resizeHandler = debounce(() => { |
|||
if (this.chart) { |
|||
this.chart.resize() |
|||
} |
|||
}, 100) |
|||
window.addEventListener('resize', this.__resizeHandler) |
|||
}, |
|||
beforeDestroy() { |
|||
if (!this.chart) { |
|||
return |
|||
} |
|||
window.removeEventListener('resize', this.__resizeHandler) |
|||
this.chart.dispose() |
|||
this.chart = null |
|||
}, |
|||
methods: { |
|||
initChart() { |
|||
this.chart = echarts.init(this.$el, 'macarons') |
|||
|
|||
this.chart.setOption({ |
|||
tooltip: { |
|||
trigger: 'item', |
|||
formatter: '{a} <br/>{b}: {c} ({d}%)' |
|||
}, |
|||
legend: { |
|||
orient: 'vertical', |
|||
x: 'left', |
|||
data: ['直达', '营销广告', '搜索引擎', '邮件营销', '联盟广告', '视频广告', '百度', '谷歌', '必应', '其他'] |
|||
}, |
|||
series: [ |
|||
{ |
|||
name: '访问来源', |
|||
type: 'pie', |
|||
selectedMode: 'single', |
|||
radius: [0, '30%'], |
|||
|
|||
label: { |
|||
normal: { |
|||
position: 'inner' |
|||
} |
|||
}, |
|||
labelLine: { |
|||
normal: { |
|||
show: false |
|||
} |
|||
}, |
|||
data: [ |
|||
{ value: 335, name: '直达', selected: true }, |
|||
{ value: 679, name: '营销广告' }, |
|||
{ value: 1548, name: '搜索引擎' } |
|||
] |
|||
}, |
|||
{ |
|||
name: '访问来源', |
|||
type: 'pie', |
|||
radius: ['40%', '55%'], |
|||
label: { |
|||
normal: { |
|||
formatter: '{a|{a}}{abg|}\n{hr|}\n {b|{b}:}{c} {per|{d}%} ', |
|||
backgroundColor: '#eee', |
|||
borderColor: '#aaa', |
|||
borderWidth: 1, |
|||
borderRadius: 4, |
|||
shadowBlur: 3, |
|||
shadowOffsetX: 2, |
|||
shadowOffsetY: 2, |
|||
shadowColor: '#999', |
|||
padding: [0, 7], |
|||
rich: { |
|||
a: { |
|||
color: '#999', |
|||
lineHeight: 22, |
|||
align: 'center' |
|||
}, |
|||
abg: { |
|||
backgroundColor: '#333', |
|||
width: '100%', |
|||
align: 'right', |
|||
height: 22, |
|||
borderRadius: [4, 4, 0, 0] |
|||
}, |
|||
hr: { |
|||
borderColor: '#aaa', |
|||
width: '100%', |
|||
borderWidth: 0.5, |
|||
height: 0 |
|||
}, |
|||
b: { |
|||
fontSize: 16, |
|||
lineHeight: 33 |
|||
}, |
|||
per: { |
|||
color: '#eee', |
|||
backgroundColor: '#334455', |
|||
padding: [2, 4], |
|||
borderRadius: 2 |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
data: [ |
|||
{ value: 335, name: '直达' }, |
|||
{ value: 310, name: '邮件营销' }, |
|||
{ value: 234, name: '联盟广告' }, |
|||
{ value: 135, name: '视频广告' }, |
|||
{ value: 1048, name: '百度' }, |
|||
{ value: 251, name: '谷歌' }, |
|||
{ value: 147, name: '必应' }, |
|||
{ value: 102, name: '其他' } |
|||
] |
|||
} |
|||
] |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,100 @@ |
|||
<template> |
|||
<div :class="className" :style="{height:height,width:width}" /> |
|||
</template> |
|||
|
|||
<script> |
|||
import echarts from 'echarts' |
|||
|
|||
require('echarts/theme/macarons') // echarts theme |
|||
import { debounce } from '@/utils' |
|||
|
|||
export default { |
|||
props: { |
|||
className: { |
|||
type: String, |
|||
default: 'chart' |
|||
}, |
|||
width: { |
|||
type: String, |
|||
default: '100%' |
|||
}, |
|||
height: { |
|||
type: String, |
|||
default: '300px' |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
chart: null |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.initChart() |
|||
this.__resizeHandler = debounce(() => { |
|||
if (this.chart) { |
|||
this.chart.resize() |
|||
} |
|||
}, 100) |
|||
window.addEventListener('resize', this.__resizeHandler) |
|||
}, |
|||
beforeDestroy() { |
|||
if (!this.chart) { |
|||
return |
|||
} |
|||
window.removeEventListener('resize', this.__resizeHandler) |
|||
this.chart.dispose() |
|||
this.chart = null |
|||
}, |
|||
methods: { |
|||
initChart() { |
|||
this.chart = echarts.init(this.$el, 'macarons') |
|||
|
|||
this.chart.setOption({ |
|||
series: { |
|||
type: 'sankey', |
|||
layout: 'none', |
|||
focusNodeAdjacency: 'allEdges', |
|||
data: [{ |
|||
name: 'a' |
|||
}, { |
|||
name: 'b' |
|||
}, { |
|||
name: 'a1' |
|||
}, { |
|||
name: 'a2' |
|||
}, { |
|||
name: 'b1' |
|||
}, { |
|||
name: 'c' |
|||
}], |
|||
links: [{ |
|||
source: 'a', |
|||
target: 'a1', |
|||
value: 5 |
|||
}, { |
|||
source: 'a', |
|||
target: 'a2', |
|||
value: 3 |
|||
}, { |
|||
source: 'b', |
|||
target: 'b1', |
|||
value: 8 |
|||
}, { |
|||
source: 'a', |
|||
target: 'b1', |
|||
value: 3 |
|||
}, { |
|||
source: 'b1', |
|||
target: 'a1', |
|||
value: 1 |
|||
}, { |
|||
source: 'b1', |
|||
target: 'c', |
|||
value: 2 |
|||
}] |
|||
} |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,143 @@ |
|||
<template> |
|||
<div :class="className" :style="{height:height,width:width}" /> |
|||
</template> |
|||
|
|||
<script> |
|||
import echarts from 'echarts' |
|||
|
|||
require('echarts/theme/macarons') // echarts theme |
|||
import { debounce } from '@/utils' |
|||
|
|||
export default { |
|||
props: { |
|||
className: { |
|||
type: String, |
|||
default: 'chart' |
|||
}, |
|||
width: { |
|||
type: String, |
|||
default: '100%' |
|||
}, |
|||
height: { |
|||
type: String, |
|||
default: '300px' |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
chart: null |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.initChart() |
|||
this.__resizeHandler = debounce(() => { |
|||
if (this.chart) { |
|||
this.chart.resize() |
|||
} |
|||
}, 100) |
|||
window.addEventListener('resize', this.__resizeHandler) |
|||
}, |
|||
beforeDestroy() { |
|||
if (!this.chart) { |
|||
return |
|||
} |
|||
window.removeEventListener('resize', this.__resizeHandler) |
|||
this.chart.dispose() |
|||
this.chart = null |
|||
}, |
|||
methods: { |
|||
initChart() { |
|||
this.chart = echarts.init(this.$el, 'macarons') |
|||
const data = [ |
|||
[[28604, 77, 17096869, 'Australia', 1990], [31163, 77.4, 27662440, 'Canada', 1990], [1516, 68, 1154605773, 'China', 1990], [13670, 74.7, 10582082, 'Cuba', 1990], [28599, 75, 4986705, 'Finland', 1990], [29476, 77.1, 56943299, 'France', 1990], [31476, 75.4, 78958237, 'Germany', 1990], [28666, 78.1, 254830, 'Iceland', 1990], [1777, 57.7, 870601776, 'India', 1990], [29550, 79.1, 122249285, 'Japan', 1990], [2076, 67.9, 20194354, 'North Korea', 1990], [12087, 72, 42972254, 'South Korea', 1990], [24021, 75.4, 3397534, 'New Zealand', 1990], [43296, 76.8, 4240375, 'Norway', 1990], [10088, 70.8, 38195258, 'Poland', 1990], [19349, 69.6, 147568552, 'Russia', 1990], [10670, 67.3, 53994605, 'Turkey', 1990], [26424, 75.7, 57110117, 'United Kingdom', 1990], [37062, 75.4, 252847810, 'United States', 1990]], |
|||
[[44056, 81.8, 23968973, 'Australia', 2015], [43294, 81.7, 35939927, 'Canada', 2015], [13334, 76.9, 1376048943, 'China', 2015], [21291, 78.5, 11389562, 'Cuba', 2015], [38923, 80.8, 5503457, 'Finland', 2015], [37599, 81.9, 64395345, 'France', 2015], [44053, 81.1, 80688545, 'Germany', 2015], [42182, 82.8, 329425, 'Iceland', 2015], [5903, 66.8, 1311050527, 'India', 2015], [36162, 83.5, 126573481, 'Japan', 2015], [1390, 71.4, 25155317, 'North Korea', 2015], [34644, 80.7, 50293439, 'South Korea', 2015], [34186, 80.6, 4528526, 'New Zealand', 2015], [64304, 81.6, 5210967, 'Norway', 2015], [24787, 77.3, 38611794, 'Poland', 2015], [23038, 73.13, 143456918, 'Russia', 2015], [19360, 76.5, 78665830, 'Turkey', 2015], [38225, 81.4, 64715810, 'United Kingdom', 2015], [53354, 79.1, 321773631, 'United States', 2015]] |
|||
] |
|||
this.chart.setOption({ |
|||
title: { |
|||
text: '1990 与 2015 年各国家人均寿命与 GDP' |
|||
}, |
|||
legend: { |
|||
right: 10, |
|||
data: ['1990', '2015'] |
|||
}, |
|||
xAxis: { |
|||
splitLine: { |
|||
lineStyle: { |
|||
type: 'dashed' |
|||
} |
|||
} |
|||
}, |
|||
yAxis: { |
|||
splitLine: { |
|||
lineStyle: { |
|||
type: 'dashed' |
|||
} |
|||
}, |
|||
scale: true |
|||
}, |
|||
series: [{ |
|||
name: '1990', |
|||
data: data[0], |
|||
type: 'scatter', |
|||
symbolSize: function(data) { |
|||
return Math.sqrt(data[2]) / 5e2 |
|||
}, |
|||
label: { |
|||
emphasis: { |
|||
show: true, |
|||
formatter: function(param) { |
|||
return param.data[3] |
|||
}, |
|||
position: 'top' |
|||
} |
|||
}, |
|||
itemStyle: { |
|||
normal: { |
|||
shadowBlur: 10, |
|||
shadowColor: 'rgba(120, 36, 50, 0.5)', |
|||
shadowOffsetY: 5, |
|||
color: new echarts.graphic.RadialGradient(0.4, 0.3, 1, [{ |
|||
offset: 0, |
|||
color: 'rgb(251, 118, 123)' |
|||
}, { |
|||
offset: 1, |
|||
color: 'rgb(204, 46, 72)' |
|||
}]) |
|||
} |
|||
} |
|||
}, { |
|||
name: '2015', |
|||
data: data[1], |
|||
type: 'scatter', |
|||
symbolSize: function(data) { |
|||
return Math.sqrt(data[2]) / 5e2 |
|||
}, |
|||
label: { |
|||
emphasis: { |
|||
show: true, |
|||
formatter: function(param) { |
|||
return param.data[3] |
|||
}, |
|||
position: 'top' |
|||
} |
|||
}, |
|||
itemStyle: { |
|||
normal: { |
|||
shadowBlur: 10, |
|||
shadowColor: 'rgba(25, 100, 150, 0.5)', |
|||
shadowOffsetY: 5, |
|||
color: new echarts.graphic.RadialGradient(0.4, 0.3, 1, [{ |
|||
offset: 0, |
|||
color: 'rgb(129, 227, 238)' |
|||
}, { |
|||
offset: 1, |
|||
color: 'rgb(25, 183, 207)' |
|||
}]) |
|||
} |
|||
} |
|||
}] |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,107 @@ |
|||
<template> |
|||
<div :class="className" :style="{height:height,width:width}" /> |
|||
</template> |
|||
|
|||
<script> |
|||
import echarts from 'echarts' |
|||
|
|||
require('echarts/theme/macarons') // echarts theme |
|||
import { debounce } from '@/utils' |
|||
|
|||
export default { |
|||
props: { |
|||
className: { |
|||
type: String, |
|||
default: 'chart' |
|||
}, |
|||
width: { |
|||
type: String, |
|||
default: '100%' |
|||
}, |
|||
height: { |
|||
type: String, |
|||
default: '300px' |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
chart: null |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.initChart() |
|||
this.__resizeHandler = debounce(() => { |
|||
if (this.chart) { |
|||
this.chart.resize() |
|||
} |
|||
}, 100) |
|||
window.addEventListener('resize', this.__resizeHandler) |
|||
}, |
|||
beforeDestroy() { |
|||
if (!this.chart) { |
|||
return |
|||
} |
|||
window.removeEventListener('resize', this.__resizeHandler) |
|||
this.chart.dispose() |
|||
this.chart = null |
|||
}, |
|||
methods: { |
|||
initChart() { |
|||
this.chart = echarts.init(this.$el, 'macarons') |
|||
const data = [{ |
|||
name: 'Grandpa', |
|||
children: [{ |
|||
name: 'Uncle Leo', |
|||
value: 15, |
|||
children: [{ |
|||
name: 'Cousin Jack', |
|||
value: 2 |
|||
}, { |
|||
name: 'Cousin Mary', |
|||
value: 5, |
|||
children: [{ |
|||
name: 'Jackson', |
|||
value: 2 |
|||
}] |
|||
}, { |
|||
name: 'Cousin Ben', |
|||
value: 4 |
|||
}] |
|||
}, { |
|||
name: 'Father', |
|||
value: 10, |
|||
children: [{ |
|||
name: 'Me', |
|||
value: 5 |
|||
}, { |
|||
name: 'Brother Peter', |
|||
value: 1 |
|||
}] |
|||
}] |
|||
}, { |
|||
name: 'Nancy', |
|||
children: [{ |
|||
name: 'Uncle Nike', |
|||
children: [{ |
|||
name: 'Cousin Betty', |
|||
value: 1 |
|||
}, { |
|||
name: 'Cousin Jenny', |
|||
value: 2 |
|||
}] |
|||
}] |
|||
}] |
|||
this.chart.setOption({ |
|||
series: { |
|||
type: 'sunburst', |
|||
data: data, |
|||
radius: [0, '90%'], |
|||
label: { |
|||
rotate: 'radial' |
|||
} |
|||
} |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,148 @@ |
|||
<template> |
|||
<div :class="className" :style="{height:height,width:width}" /> |
|||
</template> |
|||
|
|||
<script> |
|||
import echarts from 'echarts' |
|||
|
|||
require('echarts/theme/macarons') // echarts theme |
|||
import { debounce } from '@/utils' |
|||
|
|||
export default { |
|||
props: { |
|||
className: { |
|||
type: String, |
|||
default: 'chart' |
|||
}, |
|||
width: { |
|||
type: String, |
|||
default: '100%' |
|||
}, |
|||
height: { |
|||
type: String, |
|||
default: '500px' |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
chart: null |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.initChart() |
|||
this.__resizeHandler = debounce(() => { |
|||
if (this.chart) { |
|||
this.chart.resize() |
|||
} |
|||
}, 100) |
|||
window.addEventListener('resize', this.__resizeHandler) |
|||
}, |
|||
beforeDestroy() { |
|||
if (!this.chart) { |
|||
return |
|||
} |
|||
window.removeEventListener('resize', this.__resizeHandler) |
|||
this.chart.dispose() |
|||
this.chart = null |
|||
}, |
|||
methods: { |
|||
initChart() { |
|||
this.chart = echarts.init(this.$el, 'macarons') |
|||
|
|||
this.chart.setOption({ |
|||
|
|||
tooltip: { |
|||
trigger: 'axis', |
|||
axisPointer: { |
|||
type: 'line', |
|||
lineStyle: { |
|||
color: 'rgba(0,0,0,0.2)', |
|||
width: 1, |
|||
type: 'solid' |
|||
} |
|||
} |
|||
}, |
|||
|
|||
legend: { |
|||
data: ['DQ', 'TY', 'SS', 'QG', 'SY', 'DD'] |
|||
}, |
|||
|
|||
singleAxis: { |
|||
top: 50, |
|||
bottom: 50, |
|||
axisTick: {}, |
|||
axisLabel: {}, |
|||
type: 'time', |
|||
axisPointer: { |
|||
animation: true, |
|||
label: { |
|||
show: true |
|||
} |
|||
}, |
|||
splitLine: { |
|||
show: true, |
|||
lineStyle: { |
|||
type: 'dashed', |
|||
opacity: 0.2 |
|||
} |
|||
} |
|||
}, |
|||
|
|||
series: [ |
|||
{ |
|||
type: 'themeRiver', |
|||
itemStyle: { |
|||
emphasis: { |
|||
shadowBlur: 20, |
|||
shadowColor: 'rgba(0, 0, 0, 0.8)' |
|||
} |
|||
}, |
|||
data: [['2015/11/08', 10, 'DQ'], ['2015/11/09', 15, 'DQ'], ['2015/11/10', 35, 'DQ'], |
|||
['2015/11/11', 38, 'DQ'], ['2015/11/12', 22, 'DQ'], ['2015/11/13', 16, 'DQ'], |
|||
['2015/11/14', 7, 'DQ'], ['2015/11/15', 2, 'DQ'], ['2015/11/16', 17, 'DQ'], |
|||
['2015/11/17', 33, 'DQ'], ['2015/11/18', 40, 'DQ'], ['2015/11/19', 32, 'DQ'], |
|||
['2015/11/20', 26, 'DQ'], ['2015/11/21', 35, 'DQ'], ['2015/11/22', 40, 'DQ'], |
|||
['2015/11/23', 32, 'DQ'], ['2015/11/24', 26, 'DQ'], ['2015/11/25', 22, 'DQ'], |
|||
['2015/11/26', 16, 'DQ'], ['2015/11/27', 22, 'DQ'], ['2015/11/28', 10, 'DQ'], |
|||
['2015/11/08', 35, 'TY'], ['2015/11/09', 36, 'TY'], ['2015/11/10', 37, 'TY'], |
|||
['2015/11/11', 22, 'TY'], ['2015/11/12', 24, 'TY'], ['2015/11/13', 26, 'TY'], |
|||
['2015/11/14', 34, 'TY'], ['2015/11/15', 21, 'TY'], ['2015/11/16', 18, 'TY'], |
|||
['2015/11/17', 45, 'TY'], ['2015/11/18', 32, 'TY'], ['2015/11/19', 35, 'TY'], |
|||
['2015/11/20', 30, 'TY'], ['2015/11/21', 28, 'TY'], ['2015/11/22', 27, 'TY'], |
|||
['2015/11/23', 26, 'TY'], ['2015/11/24', 15, 'TY'], ['2015/11/25', 30, 'TY'], |
|||
['2015/11/26', 35, 'TY'], ['2015/11/27', 42, 'TY'], ['2015/11/28', 42, 'TY'], |
|||
['2015/11/08', 21, 'SS'], ['2015/11/09', 25, 'SS'], ['2015/11/10', 27, 'SS'], |
|||
['2015/11/11', 23, 'SS'], ['2015/11/12', 24, 'SS'], ['2015/11/13', 21, 'SS'], |
|||
['2015/11/14', 35, 'SS'], ['2015/11/15', 39, 'SS'], ['2015/11/16', 40, 'SS'], |
|||
['2015/11/17', 36, 'SS'], ['2015/11/18', 33, 'SS'], ['2015/11/19', 43, 'SS'], |
|||
['2015/11/20', 40, 'SS'], ['2015/11/21', 34, 'SS'], ['2015/11/22', 28, 'SS'], |
|||
['2015/11/23', 26, 'SS'], ['2015/11/24', 37, 'SS'], ['2015/11/25', 41, 'SS'], |
|||
['2015/11/26', 46, 'SS'], ['2015/11/27', 47, 'SS'], ['2015/11/28', 41, 'SS'], |
|||
['2015/11/08', 10, 'QG'], ['2015/11/09', 15, 'QG'], ['2015/11/10', 35, 'QG'], |
|||
['2015/11/11', 38, 'QG'], ['2015/11/12', 22, 'QG'], ['2015/11/13', 16, 'QG'], |
|||
['2015/11/14', 7, 'QG'], ['2015/11/15', 2, 'QG'], ['2015/11/16', 17, 'QG'], |
|||
['2015/11/17', 33, 'QG'], ['2015/11/18', 40, 'QG'], ['2015/11/19', 32, 'QG'], |
|||
['2015/11/20', 26, 'QG'], ['2015/11/21', 35, 'QG'], ['2015/11/22', 40, 'QG'], |
|||
['2015/11/23', 32, 'QG'], ['2015/11/24', 26, 'QG'], ['2015/11/25', 22, 'QG'], |
|||
['2015/11/26', 16, 'QG'], ['2015/11/27', 22, 'QG'], ['2015/11/28', 10, 'QG'], |
|||
['2015/11/08', 10, 'SY'], ['2015/11/09', 15, 'SY'], ['2015/11/10', 35, 'SY'], |
|||
['2015/11/11', 38, 'SY'], ['2015/11/12', 22, 'SY'], ['2015/11/13', 16, 'SY'], |
|||
['2015/11/14', 7, 'SY'], ['2015/11/15', 2, 'SY'], ['2015/11/16', 17, 'SY'], |
|||
['2015/11/17', 33, 'SY'], ['2015/11/18', 40, 'SY'], ['2015/11/19', 32, 'SY'], |
|||
['2015/11/20', 26, 'SY'], ['2015/11/21', 35, 'SY'], ['2015/11/22', 4, 'SY'], |
|||
['2015/11/23', 32, 'SY'], ['2015/11/24', 26, 'SY'], ['2015/11/25', 22, 'SY'], |
|||
['2015/11/26', 16, 'SY'], ['2015/11/27', 22, 'SY'], ['2015/11/28', 10, 'SY'], |
|||
['2015/11/08', 10, 'DD'], ['2015/11/09', 15, 'DD'], ['2015/11/10', 35, 'DD'], |
|||
['2015/11/11', 38, 'DD'], ['2015/11/12', 22, 'DD'], ['2015/11/13', 16, 'DD'], |
|||
['2015/11/14', 7, 'DD'], ['2015/11/15', 2, 'DD'], ['2015/11/16', 17, 'DD'], |
|||
['2015/11/17', 33, 'DD'], ['2015/11/18', 4, 'DD'], ['2015/11/19', 32, 'DD'], |
|||
['2015/11/20', 26, 'DD'], ['2015/11/21', 35, 'DD'], ['2015/11/22', 40, 'DD'], |
|||
['2015/11/23', 32, 'DD'], ['2015/11/24', 26, 'DD'], ['2015/11/25', 22, 'DD'], |
|||
['2015/11/26', 16, 'DD'], ['2015/11/27', 22, 'DD'], ['2015/11/28', 10, 'DD']] |
|||
} |
|||
] |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,192 @@ |
|||
<template> |
|||
<div :class="className" :style="{height:height,width:width}" /> |
|||
</template> |
|||
|
|||
<script> |
|||
import echarts from 'echarts' |
|||
require('echarts-wordcloud') |
|||
require('echarts/theme/macarons') // echarts theme |
|||
import { debounce } from '@/utils' |
|||
export default { |
|||
props: { |
|||
className: { |
|||
type: String, |
|||
default: 'chart' |
|||
}, |
|||
width: { |
|||
type: String, |
|||
default: '100%' |
|||
}, |
|||
height: { |
|||
type: String, |
|||
default: '300px' |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
chart: null |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.initChart() |
|||
this.__resizeHandler = debounce(() => { |
|||
if (this.chart) { |
|||
this.chart.resize() |
|||
} |
|||
}, 100) |
|||
window.addEventListener('resize', this.__resizeHandler) |
|||
}, |
|||
beforeDestroy() { |
|||
if (!this.chart) { |
|||
return |
|||
} |
|||
window.removeEventListener('resize', this.__resizeHandler) |
|||
this.chart.dispose() |
|||
this.chart = null |
|||
}, |
|||
methods: { |
|||
initChart() { |
|||
this.chart = echarts.init(this.$el, 'macarons') |
|||
const data = [{ |
|||
'name': '花鸟市场', |
|||
'value': 1446 |
|||
}, |
|||
{ |
|||
'name': '汽车', |
|||
'value': 928 |
|||
}, |
|||
{ |
|||
'name': '视频', |
|||
'value': 906 |
|||
}, |
|||
{ |
|||
'name': '电视', |
|||
'value': 825 |
|||
}, |
|||
{ |
|||
'name': 'Lover Boy', |
|||
'value': 514 |
|||
}, |
|||
{ |
|||
'name': '动漫', |
|||
'value': 486 |
|||
}, |
|||
{ |
|||
'name': '音乐', |
|||
'value': 53 |
|||
}, |
|||
{ |
|||
'name': '直播', |
|||
'value': 163 |
|||
}, |
|||
{ |
|||
'name': '广播电台', |
|||
'value': 86 |
|||
}, |
|||
{ |
|||
'name': '戏曲曲艺', |
|||
'value': 17 |
|||
}, |
|||
{ |
|||
'name': '演出票务', |
|||
'value': 6 |
|||
}, |
|||
{ |
|||
'name': '给陌生的你听', |
|||
'value': 1 |
|||
}, |
|||
{ |
|||
'name': '资讯', |
|||
'value': 1437 |
|||
}, |
|||
{ |
|||
'name': '商业财经', |
|||
'value': 422 |
|||
}, |
|||
{ |
|||
'name': '娱乐八卦', |
|||
'value': 353 |
|||
}, |
|||
{ |
|||
'name': '军事', |
|||
'value': 331 |
|||
}, |
|||
{ |
|||
'name': '科技资讯', |
|||
'value': 313 |
|||
}, |
|||
{ |
|||
'name': '社会时政', |
|||
'value': 307 |
|||
}, |
|||
{ |
|||
'name': '时尚', |
|||
'value': 43 |
|||
}, |
|||
{ |
|||
'name': '网络奇闻', |
|||
'value': 15 |
|||
}, |
|||
{ |
|||
'name': '旅游出行', |
|||
'value': 438 |
|||
}, |
|||
{ |
|||
'name': '景点类型', |
|||
'value': 957 |
|||
}, |
|||
{ |
|||
'name': '国内游', |
|||
'value': 927 |
|||
}, |
|||
{ |
|||
'name': '远途出行方式', |
|||
'value': 908 |
|||
}, |
|||
{ |
|||
'name': '酒店', |
|||
'value': 693 |
|||
}, |
|||
{ |
|||
'name': '关注景点', |
|||
'value': 611 |
|||
}, |
|||
{ |
|||
'name': '旅游网站偏好', |
|||
'value': 512 |
|||
}, |
|||
{ |
|||
'name': '出国游', |
|||
'value': 382 |
|||
}] |
|||
this.chart.setOption({ |
|||
backgroundColor: '#fff', |
|||
tooltip: { |
|||
show: false |
|||
}, |
|||
series: [{ |
|||
type: 'wordCloud', |
|||
gridSize: 1, |
|||
sizeRange: [12, 55], |
|||
rotationRange: [-45, 0, 45, 90], |
|||
textStyle: { |
|||
normal: { |
|||
color: function() { |
|||
return 'rgb(' + |
|||
Math.round(Math.random() * 255) + |
|||
', ' + Math.round(Math.random() * 255) + |
|||
', ' + Math.round(Math.random() * 255) + ')' |
|||
} |
|||
} |
|||
}, |
|||
left: 'center', |
|||
top: 'center', |
|||
right: null, |
|||
bottom: null, |
|||
data: data |
|||
}] |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,54 @@ |
|||
<template> |
|||
<a href="https://XXXXXXX" target="_blank" class="github-corner" aria-label="View source on Github"> |
|||
<svg |
|||
width="80" |
|||
height="80" |
|||
viewBox="0 0 250 250" |
|||
style="fill:#40c9c6; color:#fff;" |
|||
aria-hidden="true" |
|||
> |
|||
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z" /> |
|||
<path |
|||
d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" |
|||
fill="currentColor" |
|||
style="transform-origin: 130px 106px;" |
|||
class="octo-arm" |
|||
/> |
|||
<path |
|||
d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" |
|||
fill="currentColor" |
|||
class="octo-body" |
|||
/> |
|||
</svg> |
|||
</a> |
|||
</template> |
|||
|
|||
<style scoped> |
|||
.github-corner:hover .octo-arm { |
|||
animation: octocat-wave 560ms ease-in-out |
|||
} |
|||
|
|||
@keyframes octocat-wave { |
|||
0%, |
|||
100% { |
|||
transform: rotate(0) |
|||
} |
|||
20%, |
|||
60% { |
|||
transform: rotate(-25deg) |
|||
} |
|||
40%, |
|||
80% { |
|||
transform: rotate(10deg) |
|||
} |
|||
} |
|||
|
|||
@media (max-width:500px) { |
|||
.github-corner:hover .octo-arm { |
|||
animation: none |
|||
} |
|||
.github-corner .octo-arm { |
|||
animation: octocat-wave 560ms ease-in-out |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,44 @@ |
|||
<template> |
|||
<div style="padding: 0 15px;" @click="toggleClick"> |
|||
<svg |
|||
:class="{'is-active':isActive}" |
|||
class="hamburger" |
|||
viewBox="0 0 1024 1024" |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
width="64" |
|||
height="64" |
|||
> |
|||
<path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" fill="rgb(255, 255, 255)" /> |
|||
</svg> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'Hamburger', |
|||
props: { |
|||
isActive: { |
|||
type: Boolean, |
|||
default: false |
|||
} |
|||
}, |
|||
methods: { |
|||
toggleClick() { |
|||
this.$emit('toggleClick') |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.hamburger { |
|||
display: inline-block; |
|||
vertical-align: middle; |
|||
width: 20px; |
|||
height: 20px; |
|||
} |
|||
|
|||
.hamburger.is-active { |
|||
transform: rotate(180deg); |
|||
} |
|||
</style> |
|||
@ -0,0 +1,188 @@ |
|||
<template> |
|||
<div :class="{'show':show}" class="header-search"> |
|||
<svg-icon class-name="search-icon" icon-class="search" @click.stop="click" /> |
|||
<el-select |
|||
ref="headerSearchSelect" |
|||
v-model="search" |
|||
:remote-method="querySearch" |
|||
filterable |
|||
default-first-option |
|||
remote |
|||
placeholder="Search" |
|||
class="header-search-select" |
|||
@change="change" |
|||
> |
|||
<el-option v-for="item in options" :key="item.path" :value="item" :label="item.title.join(' > ')" /> |
|||
</el-select> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
// fuse is a lightweight fuzzy-search module |
|||
// make search results more in line with expectations |
|||
import Fuse from 'fuse.js' |
|||
import path from 'path' |
|||
|
|||
export default { |
|||
name: 'HeaderSearch', |
|||
data() { |
|||
return { |
|||
search: '', |
|||
options: [], |
|||
searchPool: [], |
|||
show: false, |
|||
fuse: undefined |
|||
} |
|||
}, |
|||
computed: { |
|||
routes() { |
|||
return this.$store.state.permission.routers |
|||
} |
|||
}, |
|||
watch: { |
|||
routes() { |
|||
this.searchPool = this.generateRoutes(this.routes) |
|||
}, |
|||
searchPool(list) { |
|||
this.initFuse(list) |
|||
}, |
|||
show(value) { |
|||
if (value) { |
|||
document.body.addEventListener('click', this.close) |
|||
} else { |
|||
document.body.removeEventListener('click', this.close) |
|||
} |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.searchPool = this.generateRoutes(this.routes) |
|||
}, |
|||
methods: { |
|||
click() { |
|||
this.show = !this.show |
|||
if (this.show) { |
|||
this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.focus() |
|||
} |
|||
}, |
|||
close() { |
|||
this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.blur() |
|||
this.options = [] |
|||
this.show = false |
|||
}, |
|||
change(val) { |
|||
if (this.ishttp(val.path)) { |
|||
// http(s):// 路径新窗口打开 |
|||
window.open(val.path, '_blank') |
|||
} else { |
|||
this.$router.push(val.path) |
|||
} |
|||
this.search = '' |
|||
this.options = [] |
|||
this.$nextTick(() => { |
|||
this.show = false |
|||
}) |
|||
}, |
|||
initFuse(list) { |
|||
this.fuse = new Fuse(list, { |
|||
shouldSort: true, |
|||
threshold: 0.4, |
|||
location: 0, |
|||
distance: 100, |
|||
maxPatternLength: 32, |
|||
minMatchCharLength: 1, |
|||
keys: [{ |
|||
name: 'title', |
|||
weight: 0.7 |
|||
}, { |
|||
name: 'path', |
|||
weight: 0.3 |
|||
}] |
|||
}) |
|||
}, |
|||
// Filter out the routes that can be displayed in the sidebar |
|||
// And generate the internationalized title |
|||
generateRoutes(routes, basePath = '/', prefixTitle = []) { |
|||
let res = [] |
|||
|
|||
for (const router of routes) { |
|||
// skip hidden router |
|||
if (router.hidden) { continue } |
|||
|
|||
const data = { |
|||
path: !this.ishttp(router.path) ? path.resolve(basePath, router.path) : router.path, |
|||
title: [...prefixTitle] |
|||
} |
|||
|
|||
if (router.meta && router.meta.title) { |
|||
data.title = [...data.title, router.meta.title] |
|||
|
|||
if (router.redirect !== 'noRedirect') { |
|||
// only push the routes with title |
|||
// special case: need to exclude parent router without redirect |
|||
res.push(data) |
|||
} |
|||
} |
|||
|
|||
// recursive child routes |
|||
if (router.children) { |
|||
const tempRoutes = this.generateRoutes(router.children, data.path, data.title) |
|||
if (tempRoutes.length >= 1) { |
|||
res = [...res, ...tempRoutes] |
|||
} |
|||
} |
|||
} |
|||
return res |
|||
}, |
|||
querySearch(query) { |
|||
if (query !== '') { |
|||
this.options = this.fuse.search(query) |
|||
} else { |
|||
this.options = [] |
|||
} |
|||
}, |
|||
ishttp(url) { |
|||
return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1 |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.header-search { |
|||
font-size: 0 !important; |
|||
|
|||
.search-icon { |
|||
cursor: pointer; |
|||
font-size: 18px; |
|||
vertical-align: middle; |
|||
} |
|||
|
|||
.header-search-select { |
|||
font-size: 18px; |
|||
transition: width 0.2s; |
|||
width: 0; |
|||
overflow: hidden; |
|||
background: transparent; |
|||
border-radius: 0; |
|||
display: inline-block; |
|||
vertical-align: middle; |
|||
|
|||
::v-deep .el-input__inner { |
|||
border-radius: 0; |
|||
border: 0; |
|||
padding-left: 0; |
|||
padding-right: 0; |
|||
box-shadow: none !important; |
|||
border-bottom: 1px solid #d9d9d9; |
|||
vertical-align: middle; |
|||
} |
|||
} |
|||
|
|||
&.show { |
|||
.header-search-select { |
|||
width: 210px; |
|||
margin-left: 10px; |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,68 @@ |
|||
<!-- @author zhengjie --> |
|||
<template> |
|||
<div class="icon-body"> |
|||
<el-input v-model="name" style="position: relative;" clearable placeholder="请输入图标名称" @clear="filterIcons" @input.native="filterIcons"> |
|||
<i slot="suffix" class="el-icon-search el-input__icon" /> |
|||
</el-input> |
|||
<div class="icon-list"> |
|||
<div v-for="(item, index) in iconList" :key="index" @click="selectedIcon(item)"> |
|||
<svg-icon :icon-class="item" style="height: 30px;width: 16px;" /> |
|||
<span>{{ item }}</span> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import icons from './requireIcons' |
|||
export default { |
|||
name: 'IconSelect', |
|||
data() { |
|||
return { |
|||
name: '', |
|||
iconList: icons |
|||
} |
|||
}, |
|||
methods: { |
|||
filterIcons() { |
|||
this.iconList = icons |
|||
if (this.name) { |
|||
this.iconList = this.iconList.filter(item => item.includes(this.name)) |
|||
} |
|||
}, |
|||
selectedIcon(name) { |
|||
this.$emit('selected', name) |
|||
document.body.click() |
|||
}, |
|||
reset() { |
|||
this.name = '' |
|||
this.iconList = icons |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style rel="stylesheet/scss" lang="scss" scoped> |
|||
.icon-body { |
|||
width: 100%; |
|||
padding: 10px; |
|||
.icon-list { |
|||
height: 200px; |
|||
overflow-y: scroll; |
|||
div { |
|||
height: 30px; |
|||
line-height: 30px; |
|||
margin-bottom: -5px; |
|||
cursor: pointer; |
|||
width: 33%; |
|||
float: left; |
|||
} |
|||
span { |
|||
display: inline-block; |
|||
vertical-align: -0.15em; |
|||
fill: currentColor; |
|||
overflow: hidden; |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,11 @@ |
|||
|
|||
const req = require.context('../../assets/icons/svg', false, /\.svg$/) |
|||
const requireAll = requireContext => requireContext.keys() |
|||
|
|||
const re = /\.\/(.*)\.svg/ |
|||
|
|||
const icons = requireAll(req).map(i => { |
|||
return i.match(re)[1] |
|||
}) |
|||
|
|||
export default icons |
|||
@ -0,0 +1,30 @@ |
|||
<template> |
|||
<div v-loading="loading" :style="'height:'+ height"> |
|||
<iframe :src="src" frameborder="no" style="width: 100%;height: 100%" scrolling="auto" /> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
export default { |
|||
props: { |
|||
src: { |
|||
type: String, |
|||
required: true |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
height: document.documentElement.clientHeight - 94.5 + 'px;', |
|||
loading: true |
|||
} |
|||
}, |
|||
mounted: function() { |
|||
setTimeout(() => { |
|||
this.loading = false |
|||
}, 230) |
|||
const that = this |
|||
window.onresize = function temp() { |
|||
that.height = document.documentElement.clientHeight - 94.5 + 'px;' |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,78 @@ |
|||
<template> |
|||
<div class="json-editor"> |
|||
<textarea ref="textarea" /> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import CodeMirror from 'codemirror' |
|||
import 'codemirror/lib/codemirror.css' |
|||
// 替换主题这里需修改名称 |
|||
import 'codemirror/theme/idea.css' |
|||
import 'codemirror/mode/clike/clike' |
|||
export default { |
|||
props: { |
|||
value: { |
|||
type: String, |
|||
required: true |
|||
}, |
|||
height: { |
|||
type: String, |
|||
required: true |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
editor: false |
|||
} |
|||
}, |
|||
watch: { |
|||
value(value) { |
|||
const editorValue = this.editor.getValue() |
|||
if (value !== editorValue) { |
|||
this.editor.setValue(this.value) |
|||
} |
|||
}, |
|||
height(value) { |
|||
this.editor.setSize('auto', this.height) |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.editor = CodeMirror.fromTextArea(this.$refs.textarea, { |
|||
mode: 'text/x-java', |
|||
lineNumbers: true, |
|||
lint: true, |
|||
lineWrapping: true, |
|||
tabSize: 2, |
|||
cursorHeight: 0.9, |
|||
// 替换主题这里需修改名称 |
|||
theme: 'idea', |
|||
readOnly: true |
|||
}) |
|||
this.editor.setSize('auto', this.height) |
|||
this.editor.setValue(this.value) |
|||
}, |
|||
methods: { |
|||
getValue() { |
|||
return this.editor.getValue() |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.json-editor{ |
|||
height: 100%; |
|||
margin-bottom: 10px; |
|||
} |
|||
.json-editor >>> .CodeMirror { |
|||
font-size: 14px; |
|||
overflow-y:auto; |
|||
font-weight:normal |
|||
} |
|||
.json-editor >>> .CodeMirror-scroll{ |
|||
} |
|||
.json-editor >>> .cm-s-rubyblue span.cm-string { |
|||
color: #F08047; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,101 @@ |
|||
<template> |
|||
<div :class="{'hidden':hidden}" class="pagination-container"> |
|||
<el-pagination |
|||
:background="background" |
|||
:current-page.sync="currentPage" |
|||
:page-size.sync="pageSize" |
|||
:layout="layout" |
|||
:page-sizes="pageSizes" |
|||
:total="total" |
|||
v-bind="$attrs" |
|||
@size-change="handleSizeChange" |
|||
@current-change="handleCurrentChange" |
|||
/> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { scrollTo } from '@/utils/scroll-to' |
|||
|
|||
export default { |
|||
name: 'Pagination', |
|||
props: { |
|||
total: { |
|||
required: true, |
|||
type: Number |
|||
}, |
|||
page: { |
|||
type: Number, |
|||
default: 1 |
|||
}, |
|||
limit: { |
|||
type: Number, |
|||
default: 20 |
|||
}, |
|||
pageSizes: { |
|||
type: Array, |
|||
default() { |
|||
return [10, 20, 30, 50] |
|||
} |
|||
}, |
|||
layout: { |
|||
type: String, |
|||
default: 'total, sizes, prev, pager, next, jumper' |
|||
}, |
|||
background: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
autoScroll: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
hidden: { |
|||
type: Boolean, |
|||
default: false |
|||
} |
|||
}, |
|||
computed: { |
|||
currentPage: { |
|||
get() { |
|||
return this.page |
|||
}, |
|||
set(val) { |
|||
this.$emit('update:page', val) |
|||
} |
|||
}, |
|||
pageSize: { |
|||
get() { |
|||
return this.limit |
|||
}, |
|||
set(val) { |
|||
this.$emit('update:limit', val) |
|||
} |
|||
} |
|||
}, |
|||
methods: { |
|||
handleSizeChange(val) { |
|||
this.$emit('pagination', { page: this.currentPage, limit: val }) |
|||
if (this.autoScroll) { |
|||
scrollTo(0, 800) |
|||
} |
|||
}, |
|||
handleCurrentChange(val) { |
|||
this.$emit('pagination', { page: val, limit: this.pageSize }) |
|||
if (this.autoScroll) { |
|||
scrollTo(0, 800) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.pagination-container { |
|||
background: #fff; |
|||
padding: 32px 16px; |
|||
} |
|||
.pagination-container.hidden { |
|||
display: none; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,140 @@ |
|||
<template> |
|||
<div :style="{zIndex:zIndex,height:height,width:width}" class="pan-item"> |
|||
<div class="pan-info"> |
|||
<div class="pan-info-roles-container"> |
|||
<slot /> |
|||
</div> |
|||
</div> |
|||
<img :src="image" class="pan-thumb"> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'PanThumb', |
|||
props: { |
|||
image: { |
|||
type: String, |
|||
required: true |
|||
}, |
|||
zIndex: { |
|||
type: Number, |
|||
default: 1 |
|||
}, |
|||
width: { |
|||
type: String, |
|||
default: '150px' |
|||
}, |
|||
height: { |
|||
type: String, |
|||
default: '150px' |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.pan-item { |
|||
width: 200px; |
|||
height: 200px; |
|||
border-radius: 50%; |
|||
display: inline-block; |
|||
position: relative; |
|||
cursor: default; |
|||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); |
|||
} |
|||
|
|||
.pan-info-roles-container { |
|||
padding: 20px; |
|||
text-align: center; |
|||
} |
|||
|
|||
.pan-thumb { |
|||
width: 100%; |
|||
height: 100%; |
|||
background-size: 100%; |
|||
border-radius: 50%; |
|||
overflow: hidden; |
|||
position: absolute; |
|||
transform-origin: 95% 40%; |
|||
transition: all 0.3s ease-in-out; |
|||
} |
|||
|
|||
.pan-thumb:after { |
|||
content: ''; |
|||
width: 8px; |
|||
height: 8px; |
|||
position: absolute; |
|||
border-radius: 50%; |
|||
top: 40%; |
|||
left: 95%; |
|||
margin: -4px 0 0 -4px; |
|||
background: radial-gradient(ellipse at center, rgba(14, 14, 14, 1) 0%, rgba(125, 126, 125, 1) 100%); |
|||
box-shadow: 0 0 1px rgba(255, 255, 255, 0.9); |
|||
} |
|||
|
|||
.pan-info { |
|||
position: absolute; |
|||
width: inherit; |
|||
height: inherit; |
|||
border-radius: 50%; |
|||
overflow: hidden; |
|||
box-shadow: inset 0 0 0 5px rgba(0, 0, 0, 0.05); |
|||
} |
|||
|
|||
.pan-info h3 { |
|||
color: #fff; |
|||
text-transform: uppercase; |
|||
position: relative; |
|||
letter-spacing: 2px; |
|||
font-size: 18px; |
|||
margin: 0 60px; |
|||
padding: 22px 0 0 0; |
|||
height: 85px; |
|||
font-family: 'Open Sans', Arial, sans-serif; |
|||
text-shadow: 0 0 1px #fff, 0 1px 2px rgba(0, 0, 0, 0.3); |
|||
} |
|||
|
|||
.pan-info p { |
|||
color: #fff; |
|||
padding: 10px 5px; |
|||
font-style: italic; |
|||
margin: 0 30px; |
|||
font-size: 12px; |
|||
border-top: 1px solid rgba(255, 255, 255, 0.5); |
|||
} |
|||
|
|||
.pan-info p a { |
|||
display: block; |
|||
color: #333; |
|||
width: 80px; |
|||
height: 80px; |
|||
background: rgba(255, 255, 255, 0.3); |
|||
border-radius: 50%; |
|||
color: #fff; |
|||
font-style: normal; |
|||
font-weight: 700; |
|||
text-transform: uppercase; |
|||
font-size: 9px; |
|||
letter-spacing: 1px; |
|||
padding-top: 24px; |
|||
margin: 7px auto 0; |
|||
font-family: 'Open Sans', Arial, sans-serif; |
|||
opacity: 0; |
|||
transition: transform 0.3s ease-in-out 0.2s, opacity 0.3s ease-in-out 0.2s, background 0.2s linear 0s; |
|||
transform: translateX(60px) rotate(90deg); |
|||
} |
|||
|
|||
.pan-info p a:hover { |
|||
background: rgba(255, 255, 255, 0.5); |
|||
} |
|||
|
|||
.pan-item:hover .pan-thumb { |
|||
transform: rotate(-110deg); |
|||
} |
|||
|
|||
.pan-item:hover .pan-info p a { |
|||
opacity: 1; |
|||
transform: translateX(0px) rotate(0deg); |
|||
} |
|||
</style> |
|||
@ -0,0 +1,3 @@ |
|||
<template> |
|||
<router-view /> |
|||
</template> |
|||
@ -0,0 +1,13 @@ |
|||
import permission from './permission' |
|||
|
|||
const install = function(Vue) { |
|||
Vue.directive('permission', permission) |
|||
} |
|||
|
|||
if (window.Vue) { |
|||
window['permission'] = permission |
|||
Vue.use(install); // eslint-disable-line
|
|||
} |
|||
|
|||
permission.install = install |
|||
export default permission |
|||
@ -0,0 +1,21 @@ |
|||
import store from '@/store' |
|||
|
|||
export default { |
|||
inserted(el, binding) { |
|||
const { value } = binding |
|||
const roles = store.getters && store.getters.roles |
|||
if (value && value instanceof Array) { |
|||
if (value.length > 0) { |
|||
const permissionRoles = value |
|||
const hasPermission = roles.some(role => { |
|||
return permissionRoles.includes(role) |
|||
}) |
|||
if (!hasPermission) { |
|||
el.parentNode && el.parentNode.removeChild(el) |
|||
} |
|||
} |
|||
} else { |
|||
throw new Error(`使用方式: v-permission="['admin','editor']"`) |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,149 @@ |
|||
<template> |
|||
<div ref="rightPanel" :class="{show:show}" class="rightPanel-container"> |
|||
<div class="rightPanel-background" /> |
|||
<div class="rightPanel"> |
|||
<div class="rightPanel-items"> |
|||
<slot /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { addClass, removeClass } from '@/utils' |
|||
|
|||
export default { |
|||
name: 'RightPanel', |
|||
props: { |
|||
clickNotClose: { |
|||
default: false, |
|||
type: Boolean |
|||
}, |
|||
buttonTop: { |
|||
default: 250, |
|||
type: Number |
|||
} |
|||
}, |
|||
computed: { |
|||
show: { |
|||
get() { |
|||
return this.$store.state.settings.showSettings |
|||
}, |
|||
set(val) { |
|||
this.$store.dispatch('settings/changeSetting', { |
|||
key: 'showSettings', |
|||
value: val |
|||
}) |
|||
} |
|||
}, |
|||
theme() { |
|||
return this.$store.state.settings.theme |
|||
} |
|||
}, |
|||
watch: { |
|||
show(value) { |
|||
if (value && !this.clickNotClose) { |
|||
this.addEventClick() |
|||
} |
|||
if (value) { |
|||
addClass(document.body, 'showRightPanel') |
|||
} else { |
|||
removeClass(document.body, 'showRightPanel') |
|||
} |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.insertToBody() |
|||
this.addEventClick() |
|||
}, |
|||
beforeDestroy() { |
|||
const elx = this.$refs.rightPanel |
|||
elx.remove() |
|||
}, |
|||
methods: { |
|||
addEventClick() { |
|||
window.addEventListener('click', this.closeSidebar) |
|||
}, |
|||
closeSidebar(evt) { |
|||
const parent = evt.target.closest('.rightPanel') |
|||
if (!parent) { |
|||
this.show = false |
|||
window.removeEventListener('click', this.closeSidebar) |
|||
} |
|||
}, |
|||
insertToBody() { |
|||
const elx = this.$refs.rightPanel |
|||
const body = document.querySelector('body') |
|||
body.insertBefore(elx, body.firstChild) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style> |
|||
.showRightPanel { |
|||
overflow: hidden; |
|||
position: relative; |
|||
width: calc(100% - 15px); |
|||
} |
|||
</style> |
|||
|
|||
<style lang="scss" scoped> |
|||
.rightPanel-background { |
|||
position: fixed; |
|||
top: 0; |
|||
left: 0; |
|||
opacity: 0; |
|||
transition: opacity .3s cubic-bezier(.7, .3, .1, 1); |
|||
background: rgba(0, 0, 0, .2); |
|||
z-index: -1; |
|||
} |
|||
|
|||
.rightPanel { |
|||
width: 100%; |
|||
max-width: 260px; |
|||
height: 100vh; |
|||
position: fixed; |
|||
top: 0; |
|||
right: 0; |
|||
box-shadow: 0px 0px 15px 0px rgba(0, 0, 0, .05); |
|||
transition: all .25s cubic-bezier(.7, .3, .1, 1); |
|||
transform: translate(100%); |
|||
background: #fff; |
|||
z-index: 40000; |
|||
} |
|||
|
|||
.show { |
|||
transition: all .3s cubic-bezier(.7, .3, .1, 1); |
|||
|
|||
.rightPanel-background { |
|||
z-index: 20000; |
|||
opacity: 1; |
|||
width: 100%; |
|||
height: 100%; |
|||
} |
|||
|
|||
.rightPanel { |
|||
transform: translate(0); |
|||
} |
|||
} |
|||
|
|||
.handle-button { |
|||
width: 48px; |
|||
height: 48px; |
|||
position: absolute; |
|||
left: -48px; |
|||
text-align: center; |
|||
font-size: 24px; |
|||
border-radius: 6px 0 0 6px !important; |
|||
z-index: 0; |
|||
pointer-events: auto; |
|||
cursor: pointer; |
|||
color: #fff; |
|||
line-height: 48px; |
|||
i { |
|||
font-size: 24px; |
|||
line-height: 48px; |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,60 @@ |
|||
<template> |
|||
<div> |
|||
<svg-icon :icon-class="isFullscreen?'exit-fullscreen':'fullscreen'" @click="click" /> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import screenfull from 'screenfull' |
|||
|
|||
export default { |
|||
name: 'Screenfull', |
|||
data() { |
|||
return { |
|||
isFullscreen: false |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.init() |
|||
}, |
|||
beforeDestroy() { |
|||
this.destroy() |
|||
}, |
|||
methods: { |
|||
click() { |
|||
if (!screenfull.enabled) { |
|||
this.$message({ |
|||
message: 'you browser can not work', |
|||
type: 'warning' |
|||
}) |
|||
return false |
|||
} |
|||
screenfull.toggle() |
|||
}, |
|||
change() { |
|||
this.isFullscreen = screenfull.isFullscreen |
|||
}, |
|||
init() { |
|||
if (screenfull.enabled) { |
|||
screenfull.on('change', this.change) |
|||
} |
|||
}, |
|||
destroy() { |
|||
if (screenfull.enabled) { |
|||
screenfull.off('change', this.change) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.screenfull-svg { |
|||
display: inline-block; |
|||
cursor: pointer; |
|||
fill: #5a5e66;; |
|||
width: 20px; |
|||
height: 20px; |
|||
vertical-align: 10px; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,57 @@ |
|||
<template> |
|||
<el-dropdown trigger="click" @command="handleSetSize"> |
|||
<div> |
|||
<svg-icon class-name="size-icon" icon-class="size" /> |
|||
</div> |
|||
<el-dropdown-menu slot="dropdown"> |
|||
<el-dropdown-item v-for="item of sizeOptions" :key="item.value" :disabled="size===item.value" :command="item.value"> |
|||
{{ |
|||
item.label }} |
|||
</el-dropdown-item> |
|||
</el-dropdown-menu> |
|||
</el-dropdown> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
data() { |
|||
return { |
|||
sizeOptions: [ |
|||
{ label: 'Default', value: 'default' }, |
|||
{ label: 'Medium', value: 'medium' }, |
|||
{ label: 'Small', value: 'small' }, |
|||
{ label: 'Mini', value: 'mini' } |
|||
] |
|||
} |
|||
}, |
|||
computed: { |
|||
size() { |
|||
return this.$store.getters.size |
|||
} |
|||
}, |
|||
methods: { |
|||
handleSetSize(size) { |
|||
this.$ELEMENT.size = size |
|||
this.$store.dispatch('app/setSize', size) |
|||
this.refreshView() |
|||
this.$message({ |
|||
message: '布局设置成功', |
|||
type: 'success' |
|||
}) |
|||
}, |
|||
refreshView() { |
|||
// In order to make the cached page re-rendered |
|||
this.$store.dispatch('tagsView/delAllCachedViews', this.$route) |
|||
|
|||
const { fullPath } = this.$route |
|||
|
|||
this.$nextTick(() => { |
|||
this.$router.replace({ |
|||
path: '/redirect' + fullPath |
|||
}) |
|||
}) |
|||
} |
|||
} |
|||
|
|||
} |
|||
</script> |
|||
@ -0,0 +1,62 @@ |
|||
<template> |
|||
<div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" /> |
|||
<svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners"> |
|||
<use :href="iconName" /> |
|||
</svg> |
|||
</template> |
|||
|
|||
<script> |
|||
// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage |
|||
import { isExternal } from '@/utils/validate' |
|||
|
|||
export default { |
|||
name: 'SvgIcon', |
|||
props: { |
|||
iconClass: { |
|||
type: String, |
|||
required: true |
|||
}, |
|||
className: { |
|||
type: String, |
|||
default: '' |
|||
} |
|||
}, |
|||
computed: { |
|||
isExternal() { |
|||
return isExternal(this.iconClass) |
|||
}, |
|||
iconName() { |
|||
return `#icon-${this.iconClass}` |
|||
}, |
|||
svgClass() { |
|||
if (this.className) { |
|||
return 'svg-icon ' + this.className |
|||
} else { |
|||
return 'svg-icon' |
|||
} |
|||
}, |
|||
styleExternalIcon() { |
|||
return { |
|||
mask: `url(${this.iconClass}) no-repeat 50% 50%`, |
|||
'-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%` |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.svg-icon { |
|||
width: 1em; |
|||
height: 1em; |
|||
vertical-align: -0.15em; |
|||
fill: currentColor; |
|||
overflow: hidden; |
|||
} |
|||
|
|||
.svg-external-icon { |
|||
background-color: currentColor; |
|||
mask-size: cover!important; |
|||
display: inline-block; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,165 @@ |
|||
<template> |
|||
<el-color-picker |
|||
v-model="theme" |
|||
:predefine="['#031435', '#1890ff', '#304156','#212121','#11a983', '#13c2c2', '#6959CD', '#f5222d']" |
|||
class="theme-picker" |
|||
popper-class="theme-picker-dropdown" |
|||
/> |
|||
</template> |
|||
|
|||
<script> |
|||
const version = require('element-ui/package.json').version // element-ui version from node_modules |
|||
const ORIGINAL_THEME = '#031435' // default color |
|||
import Cookies from 'js-cookie' |
|||
export default { |
|||
data() { |
|||
return { |
|||
chalk: '', // content of theme-chalk css |
|||
theme: '' |
|||
} |
|||
}, |
|||
computed: { |
|||
defaultTheme() { |
|||
return this.$store.state.settings.theme |
|||
} |
|||
}, |
|||
watch: { |
|||
defaultTheme: { |
|||
handler: function(val, oldVal) { |
|||
this.theme = val |
|||
}, |
|||
immediate: true |
|||
}, |
|||
async theme(val) { |
|||
Cookies.set('theme', val, { expires: 365 }) |
|||
const oldVal = this.chalk ? this.theme : Cookies.get('theme') ? Cookies.get('theme') : ORIGINAL_THEME |
|||
if (typeof val !== 'string') return |
|||
const themeCluster = this.getThemeCluster(val.replace('#', '')) |
|||
const originalCluster = this.getThemeCluster(oldVal.replace('#', '')) |
|||
|
|||
const getHandler = (variable, id) => { |
|||
return () => { |
|||
const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', '')) |
|||
const newStyle = this.updateStyle(this[variable], originalCluster, themeCluster) |
|||
|
|||
let styleTag = document.getElementById(id) |
|||
if (!styleTag) { |
|||
styleTag = document.createElement('style') |
|||
styleTag.setAttribute('id', id) |
|||
document.head.appendChild(styleTag) |
|||
} |
|||
styleTag.innerText = newStyle |
|||
} |
|||
} |
|||
|
|||
if (!this.chalk) { |
|||
const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css` |
|||
await this.getCSSString(url, 'chalk') |
|||
} |
|||
|
|||
const chalkHandler = getHandler('chalk', 'chalk-style') |
|||
|
|||
chalkHandler() |
|||
|
|||
const styles = [].slice.call(document.querySelectorAll('style')) |
|||
.filter(style => { |
|||
const text = style.innerText |
|||
return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text) |
|||
}) |
|||
styles.forEach(style => { |
|||
const { innerText } = style |
|||
if (typeof innerText !== 'string') return |
|||
style.innerText = this.updateStyle(innerText, originalCluster, themeCluster) |
|||
}) |
|||
|
|||
this.$emit('change', val) |
|||
} |
|||
}, |
|||
|
|||
methods: { |
|||
updateStyle(style, oldCluster, newCluster) { |
|||
let newStyle = style |
|||
oldCluster.forEach((color, index) => { |
|||
newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index]) |
|||
}) |
|||
return newStyle |
|||
}, |
|||
|
|||
getCSSString(url, variable) { |
|||
return new Promise(resolve => { |
|||
const xhr = new XMLHttpRequest() |
|||
xhr.onreadystatechange = () => { |
|||
if (xhr.readyState === 4 && xhr.status === 200) { |
|||
this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '') |
|||
resolve() |
|||
} |
|||
} |
|||
xhr.open('GET', url) |
|||
xhr.send() |
|||
}) |
|||
}, |
|||
|
|||
getThemeCluster(theme) { |
|||
const tintColor = (color, tint) => { |
|||
let red = parseInt(color.slice(0, 2), 16) |
|||
let green = parseInt(color.slice(2, 4), 16) |
|||
let blue = parseInt(color.slice(4, 6), 16) |
|||
|
|||
if (tint === 0) { // when primary color is in its rgb space |
|||
return [red, green, blue].join(',') |
|||
} else { |
|||
red += Math.round(tint * (255 - red)) |
|||
green += Math.round(tint * (255 - green)) |
|||
blue += Math.round(tint * (255 - blue)) |
|||
|
|||
red = red.toString(16) |
|||
green = green.toString(16) |
|||
blue = blue.toString(16) |
|||
|
|||
return `#${red}${green}${blue}` |
|||
} |
|||
} |
|||
|
|||
const shadeColor = (color, shade) => { |
|||
let red = parseInt(color.slice(0, 2), 16) |
|||
let green = parseInt(color.slice(2, 4), 16) |
|||
let blue = parseInt(color.slice(4, 6), 16) |
|||
|
|||
red = Math.round((1 - shade) * red) |
|||
green = Math.round((1 - shade) * green) |
|||
blue = Math.round((1 - shade) * blue) |
|||
|
|||
red = red.toString(16) |
|||
green = green.toString(16) |
|||
blue = blue.toString(16) |
|||
|
|||
return `#${red}${green}${blue}` |
|||
} |
|||
|
|||
const clusters = [theme] |
|||
for (let i = 0; i <= 9; i++) { |
|||
clusters.push(tintColor(theme, Number((i / 10).toFixed(2)))) |
|||
} |
|||
clusters.push(shadeColor(theme, 0.1)) |
|||
return clusters |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style> |
|||
.theme-message, |
|||
.theme-picker-dropdown { |
|||
z-index: 99999 !important; |
|||
} |
|||
|
|||
.theme-picker .el-color-picker__trigger { |
|||
height: 26px !important; |
|||
width: 26px !important; |
|||
padding: 2px; |
|||
} |
|||
|
|||
.theme-picker-dropdown .el-color-dropdown__link-btn { |
|||
display: none; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,138 @@ |
|||
<template> |
|||
<div> |
|||
<input ref="excel-upload-input" class="excel-upload-input" type="file" accept=".xlsx, .xls" @change="handleClick"> |
|||
<div class="drop" @drop="handleDrop" @dragover="handleDragover" @dragenter="handleDragover"> |
|||
拖拽excel文件到此处 或者 |
|||
<el-button :loading="loading" style="margin-left:16px;" size="mini" type="primary" @click="handleUpload"> |
|||
浏览 |
|||
</el-button> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import XLSX from 'xlsx' |
|||
|
|||
export default { |
|||
props: { |
|||
beforeUpload: Function, // eslint-disable-line |
|||
onSuccess: Function// eslint-disable-line |
|||
}, |
|||
data() { |
|||
return { |
|||
loading: false, |
|||
excelData: { |
|||
header: null, |
|||
results: null |
|||
} |
|||
} |
|||
}, |
|||
methods: { |
|||
generateData({ header, results }) { |
|||
this.excelData.header = header |
|||
this.excelData.results = results |
|||
this.onSuccess && this.onSuccess(this.excelData) |
|||
}, |
|||
handleDrop(e) { |
|||
e.stopPropagation() |
|||
e.preventDefault() |
|||
if (this.loading) return |
|||
const files = e.dataTransfer.files |
|||
if (files.length !== 1) { |
|||
this.$message.error('只支持单个文件上传!') |
|||
return |
|||
} |
|||
const rawFile = files[0] |
|||
|
|||
if (!this.isExcel(rawFile)) { |
|||
this.$message.error('只支持.xlsx, .xls, .csv 格式文件') |
|||
return false |
|||
} |
|||
this.upload(rawFile) |
|||
e.stopPropagation() |
|||
e.preventDefault() |
|||
}, |
|||
handleDragover(e) { |
|||
e.stopPropagation() |
|||
e.preventDefault() |
|||
e.dataTransfer.dropEffect = 'copy' |
|||
}, |
|||
handleUpload() { |
|||
this.$refs['excel-upload-input'].click() |
|||
}, |
|||
handleClick(e) { |
|||
const files = e.target.files |
|||
const rawFile = files[0] // only use files[0] |
|||
if (!rawFile) return |
|||
this.upload(rawFile) |
|||
}, |
|||
upload(rawFile) { |
|||
this.$refs['excel-upload-input'].value = null // fix can't select the same excel |
|||
|
|||
if (!this.beforeUpload) { |
|||
this.readerData(rawFile) |
|||
return |
|||
} |
|||
const before = this.beforeUpload(rawFile) |
|||
if (before) { |
|||
this.readerData(rawFile) |
|||
} |
|||
}, |
|||
readerData(rawFile) { |
|||
this.loading = true |
|||
return new Promise((resolve, reject) => { |
|||
const reader = new FileReader() |
|||
reader.onload = e => { |
|||
const data = e.target.result |
|||
const workbook = XLSX.read(data, { type: 'array' }) |
|||
const firstSheetName = workbook.SheetNames[0] |
|||
const worksheet = workbook.Sheets[firstSheetName] |
|||
const header = this.getHeaderRow(worksheet) |
|||
const results = XLSX.utils.sheet_to_json(worksheet) |
|||
this.generateData({ header, results }) |
|||
this.loading = false |
|||
resolve() |
|||
} |
|||
reader.readAsArrayBuffer(rawFile) |
|||
}) |
|||
}, |
|||
getHeaderRow(sheet) { |
|||
const headers = [] |
|||
const range = XLSX.utils.decode_range(sheet['!ref']) |
|||
let C |
|||
const R = range.s.r |
|||
/* start in the first row */ |
|||
for (C = range.s.c; C <= range.e.c; ++C) { /* walk every column in the range */ |
|||
const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })] |
|||
/* find the cell in the first row */ |
|||
let hdr = 'UNKNOWN ' + C // <-- replace with your desired default |
|||
if (cell && cell.t) hdr = XLSX.utils.format_cell(cell) |
|||
headers.push(hdr) |
|||
} |
|||
return headers |
|||
}, |
|||
isExcel(file) { |
|||
return /\.(xlsx|xls|csv)$/.test(file.name) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.excel-upload-input{ |
|||
display: none; |
|||
z-index: -9999; |
|||
} |
|||
.drop{ |
|||
border: 2px dashed #bbb; |
|||
width: 600px; |
|||
height: 160px; |
|||
line-height: 160px; |
|||
margin: 0 auto; |
|||
font-size: 24px; |
|||
border-radius: 5px; |
|||
text-align: center; |
|||
color: #bbb; |
|||
position: relative; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,81 @@ |
|||
<template> |
|||
<div class="json-editor"> |
|||
<textarea ref="textarea" /> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import CodeMirror from 'codemirror' |
|||
import 'codemirror/lib/codemirror.css' |
|||
// 替换主题这里需修改名称 |
|||
import 'codemirror/theme/idea.css' |
|||
import 'codemirror/mode/yaml/yaml' |
|||
export default { |
|||
props: { |
|||
value: { |
|||
type: String, |
|||
required: true |
|||
}, |
|||
height: { |
|||
type: String, |
|||
required: true |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
editor: false |
|||
} |
|||
}, |
|||
watch: { |
|||
value(value) { |
|||
const editorValue = this.editor.getValue() |
|||
if (value !== editorValue) { |
|||
this.editor.setValue(this.value) |
|||
} |
|||
}, |
|||
height(value) { |
|||
this.editor.setSize('auto', this.height) |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.editor = CodeMirror.fromTextArea(this.$refs.textarea, { |
|||
mode: 'text/x-yaml', |
|||
lineNumbers: true, |
|||
lint: true, |
|||
lineWrapping: true, |
|||
tabSize: 2, |
|||
cursorHeight: 0.9, |
|||
// 替换主题这里需修改名称 |
|||
theme: 'idea' |
|||
}) |
|||
this.editor.setSize('auto', this.height) |
|||
this.editor.setValue(this.value) |
|||
this.editor.on('change', cm => { |
|||
this.$emit('changed', cm.getValue()) |
|||
this.$emit('input', cm.getValue()) |
|||
}) |
|||
}, |
|||
methods: { |
|||
getValue() { |
|||
return this.editor.getValue() |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.json-editor{ |
|||
height: 100%; |
|||
margin-bottom: 10px; |
|||
} |
|||
.json-editor >>> .CodeMirror { |
|||
font-size: 13px; |
|||
overflow-y:auto; |
|||
font-weight:normal |
|||
} |
|||
.json-editor >>> .CodeMirror-scroll{ |
|||
} |
|||
.json-editor >>> .cm-s-rubyblue span.cm-string { |
|||
color: #F08047; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,679 @@ |
|||
<template> |
|||
<div class="jsmpeg-player" @mouseenter="handlePlayerMouseEnter" @mouseleave="handlePlayerMouseLeave"> |
|||
<div class="player-header" :class="{ 'is-show': showTitle }"> |
|||
<slot v-if="$slots.title" name="title" /> |
|||
<span v-else-if="displayTitle" class="player-title"> |
|||
{{ displayTitle }} |
|||
</span> |
|||
<div v-if="isRecording" class="recording-tips"> |
|||
<div class="recording-icon" :class="recordingDuration % 2 == 0 ? 'is-hide' : ''" /> |
|||
REC <template v-if="showTitle"> {{ recordingDurationLabel }} </template> |
|||
</div> |
|||
<button v-if="showCloseBtn" class="close-btn jm-icon-close" type="button" title="关闭" @click="$emit('close')" /> |
|||
</div> |
|||
<div ref="canvas-wrap" v-loading="loading" class="player-canvas__wrap" :element-loading-text="loadingText" @mousemove.passive="handleCanvasMouseMove" @click="handleCanvasClick"> |
|||
<!-- @dblclick="toggleFullscreen" --> |
|||
<!-- <canvas class="jsmpeg-canvas" |
|||
ref="canvas" /> --> |
|||
<template v-if="!loading && flags.noSignal"> |
|||
<template v-if="$slots['no-signal']"> |
|||
<slot name="no-signal" /> |
|||
</template> |
|||
<template v-else> |
|||
<div class="no-signal-text"> {{ noSignalText }} </div> |
|||
</template> |
|||
</template> |
|||
</div> |
|||
<div v-if="withToolbar" class="player-toolbar" :class="{ 'is-show': player && flags.playerHover }" @mouseenter="handleToolbarMouseEnter" @mouseleave="handleToolbarMouseLeave"> |
|||
<button class="toolbar-btn play-btn" type="button" :class="paused ? 'jm-icon-video-play is-paused' : 'jm-icon-video-pause'" :title="paused ? '播放' : '暂停'" @click="handleToolbar('play')" /> |
|||
<button class="toolbar-btn stop-btn jm-icon-stop" title="停止" type="button" @click="handleToolbar('stop')" /> |
|||
<button v-popover:popover-volume class="toolbar-btn volume-btn" type="button" title="音量" :class="isMuted ? 'jm-icon-muted' : 'jm-icon-volume'" @click="handleToolbar('mute')" /> |
|||
<div class="progress-bar"> |
|||
<span v-if="showDuration" class="current-time"> |
|||
{{ currentTimeLabel }} |
|||
</span> |
|||
</div> |
|||
<!-- <button class="snapshot-btn" |
|||
title="画中画" |
|||
@click="requesPip"> |
|||
<i class="jm-icon-copy-document"></i> |
|||
</button> --> |
|||
<button class="toolbar-btn snapshot-btn jm-icon-screenshots" title="截图" type="button" @click="handleToolbar('snapshot')" /> |
|||
<button class="toolbar-btn recording-btn jm-icon-recording" type="button" :class="isRecording ? 'is-recording' : ''" :title="isRecording ? '停止录制' : '录制'" @click="handleToolbar('recording')" /> |
|||
<button v-popover:popover-setting class="toolbar-btn setting-btn jm-icon-settings" title="设置" type="button" /> |
|||
<!-- <button |
|||
class="toolbar-btn fullscreen-btn" |
|||
type="button" |
|||
:class=" |
|||
flags.fullscreen ? 'jm-icon-exitfullscreen' : 'jm-icon-fullscreen' |
|||
" |
|||
:title="flags.fullscreen ? '取消全屏' : '全屏'" |
|||
@click="handleToolbar('fullscreen')" |
|||
></button> --> |
|||
</div> |
|||
<div class="overlayers"> |
|||
<template v-if="withToolbar"> |
|||
<el-popover ref="popover-setting" popper-class="jsmpeg-player-popover popover-setting" trigger="hover" placement="top-end" :visible-arrow="popoverVisibleArrow" :append-to-body="false"> |
|||
<!-- <div class="setting-item"> |
|||
<span class="label">禁用WebGL</span> |
|||
<div class="input__wrap"> |
|||
<el-switch class="input" |
|||
v-model="playerSettings.disableGl"> |
|||
</el-switch> |
|||
</div> |
|||
</div> --> |
|||
<!-- <div class="setting-item" |
|||
highlight> |
|||
<span class="label">后台播放</span> |
|||
<div class="input__wrap"> |
|||
<el-switch class="input" |
|||
v-model="playerSettings.backgroudPlay" |
|||
@change="settingPlayer('pauseWhenHidden',!$event)"> |
|||
</el-switch> |
|||
</div> |
|||
</div> --> |
|||
<div class="setting-item" highlight> |
|||
<span class="label">自动拉伸</span> |
|||
<div class="input__wrap"> |
|||
<el-switch v-model="playerSettings.autoStretch" class="input" @change="settingPlayer('autoStretch', $event)" /> |
|||
</div> |
|||
</div> |
|||
<div class="setting-item" highlight> |
|||
<span class="label">旋转画面</span> |
|||
<div class="input__wrap"> |
|||
<button class="toolbar-btn jm-icon-rotate-left" title="向左旋转90度" type="button" @click="rotate(-90, true)" /> |
|||
<button class="toolbar-btn jm-icon-rotate-right" title="向右旋转90度" type="button" @click="rotate(90, true)" /> |
|||
</div> |
|||
</div> |
|||
<!-- <div class="setting-item"> |
|||
<span class="label">test</span> |
|||
<div class="input__wrap"> |
|||
<el-button class="input" |
|||
@click="player.stop(true)"> |
|||
</el-button> |
|||
</div> |
|||
</div> --> |
|||
</el-popover> |
|||
<el-popover ref="popover-volume" popper-class="jsmpeg-player-popover popover-volume" trigger="hover" placement="top" :visible-arrow="popoverVisibleArrow" :append-to-body="false"> |
|||
<div class="volume-value">{{ volumePercent }}</div> |
|||
<el-slider |
|||
v-model="volume" |
|||
vertical |
|||
height="120px" |
|||
:max="1" |
|||
:min="0" |
|||
:step="0.01" |
|||
:show-tooltip="false" |
|||
:marks="{ |
|||
0: '', |
|||
0.5: '', |
|||
1: '' |
|||
}" |
|||
@change="$emit('volume-change', volume)" |
|||
/> |
|||
</el-popover> |
|||
</template> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import JSMpeg from './jsmpeg' |
|||
// import fullscreen from '@/utils/fullscreen' |
|||
|
|||
/** 补零 */ |
|||
function prefixPadZero(num) { |
|||
return (num >= 10 ? '' : '0') + num |
|||
} |
|||
|
|||
/** |
|||
* 将秒转换为时:分:秒 |
|||
*/ |
|||
function formatTime(time) { |
|||
const seconds = parseInt(time % 60) |
|||
const minutes = parseInt(time / 60) |
|||
const hours = parseInt(minutes / 60) |
|||
return time < 3600 |
|||
? `${prefixPadZero(minutes)}:${prefixPadZero(seconds)}` |
|||
: `${prefixPadZero(hours)}:${prefixPadZero(minutes)}:${prefixPadZero( |
|||
seconds |
|||
)}` |
|||
} |
|||
|
|||
const defaultOptions = () => ({ |
|||
/** 是否循环播放视频(仅静态文件)。默认true */ |
|||
autoplay: true, |
|||
/** 是否解码音频。默认true */ |
|||
audio: true, |
|||
/** 是否解码视频。默认true */ |
|||
video: true, |
|||
/** 预览图像的URL,用来在视频播放之前作为海报显示。 */ |
|||
poster: null, |
|||
/** 是否禁用后台播放,当web页面处于非活动状态时是否暂停播放,默认true(注意,浏览器通常会在非活动标签中限制JS) */ |
|||
pauseWhenHidden: true, |
|||
/** 是否禁用WebGL,始终使用Canvas2D渲染器。默认.false */ |
|||
disableGl: false, |
|||
/** 是否禁用WebAssembly并始终使用JavaScript解码器。默认false */ |
|||
disableWebAssembly: false, |
|||
/** WebGL上下文是否创建必要的“截图”。默认false */ |
|||
preserveDrawingBuffer: true, |
|||
/** 是否以块的形式加载数据(仅静态文件)。当启用时,回放可以在完整加载源之前开始,默认=true */ |
|||
progressive: true, |
|||
/** 当不需要回放时是否推迟加载块。默认=progressive */ |
|||
throttled: true, |
|||
/** 使用时,以字节为单位加载的块大小。默认(1 mb)1024*1024 */ |
|||
chunkSize: 1024 * 1024, |
|||
/** 是否解码并显示视频的第一帧,一般用于设置画布大小以及使用初始帧作为"poster"图像。当使用自动播放或流媒体资源时,此参数不受影响。默认true */ |
|||
decodeFirstFrame: false, |
|||
/** 流媒体时,以秒为单位的最大排队音频长度。(可以理解为能接受的最大音画不同步时间) */ |
|||
maxAudioLag: 0.25, |
|||
/** 流媒体时,视频解码缓冲区的字节大小。默认的512 * 1024 (512 kb)。对于非常高的比特率,您可能需要增加此值。 */ |
|||
videoBufferSize: 1024 * 1024, |
|||
/** 流媒体时,音频解码缓冲区的字节大小。默认的128 * 1024 (128 kb)。对于非常高的比特率,您可能需要增加此值。 */ |
|||
audioBufferSize: 256 * 1024 |
|||
}) |
|||
|
|||
export default { |
|||
components: {}, |
|||
inheritAttrs: false, |
|||
|
|||
// #region 组件基础 |
|||
props: { |
|||
url: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
title: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
options: { |
|||
type: Object, |
|||
default: defaultOptions |
|||
}, |
|||
/** 是否可关闭(单击关闭按钮,仅抛出事件) */ |
|||
closeable: Boolean, |
|||
/** 是否处于后台,如el-tabs的切换,路由的切换等 */ |
|||
inBackground: Boolean, |
|||
/** 是否现实持续播放时间 */ |
|||
showDuration: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
/** 默认静音 */ |
|||
defaultMute: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
/** 是否需要工具栏 */ |
|||
withToolbar: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
popoverVisibleArrow: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
noSignalText: { |
|||
type: String, |
|||
default: '无信号' |
|||
}, |
|||
loadingText: { |
|||
type: String, |
|||
default: '拼命加载中...' |
|||
} |
|||
}, |
|||
inject: { |
|||
/** @returns {any} */ |
|||
rootTabs: { |
|||
default: '' |
|||
} |
|||
}, |
|||
// #endregion |
|||
|
|||
// #region 数据相关 |
|||
data() { |
|||
return { |
|||
loading: false, |
|||
/** @type {import('./jsmpeg/types').JSMpegPlayer} */ |
|||
player: null, |
|||
lastVolume: 0, |
|||
flags: { |
|||
/** |
|||
* 是否处于无信号状态 |
|||
* 1.当流中断事件触发后,15秒后还没有收到ws消息 |
|||
* 2.ws关闭事件触发 |
|||
*/ |
|||
noSignal: false, |
|||
/** 是否已获取到视频分辨率 */ |
|||
gotResolution: false, |
|||
/** 是否鼠标悬停在播放器内部 */ |
|||
playerHover: false, |
|||
/** 是否处于全屏播放 */ |
|||
fullscreen: false |
|||
}, |
|||
playerSettings: { |
|||
disableGl: false, |
|||
/** canvas旋转角度 */ |
|||
rotationAngle: 0, |
|||
/** 后台播放 */ |
|||
backgroudPlay: false, |
|||
/** 自动拉伸 */ |
|||
autoStretch: false |
|||
}, |
|||
timers: { |
|||
noSignal: null, |
|||
canvasMouseMove: null |
|||
} |
|||
} |
|||
}, |
|||
computed: { |
|||
/** @returns {string} */ |
|||
displayTitle() { |
|||
return this.title || this.url |
|||
}, |
|||
/** @returns {boolean} */ |
|||
paused() { |
|||
return this.player?.paused ?? true |
|||
}, |
|||
/** @returns {number} */ |
|||
volume: { |
|||
/** @returns {number} */ |
|||
set(val) { |
|||
if (!this.player) return |
|||
|
|||
if (val >= 1) { |
|||
this.player.volume = 1 |
|||
} else if (val <= 0) { |
|||
this.player.volume = 0 |
|||
} else { |
|||
this.player.volume = val |
|||
} |
|||
|
|||
if (this.player.volume === 0) { |
|||
this.$emit('muted', this.player.volume) |
|||
} |
|||
}, |
|||
/** @returns {number} */ |
|||
get() { |
|||
return this.player?.volume ?? 100 |
|||
} |
|||
}, |
|||
/** @returns {number} */ |
|||
volumePercent() { |
|||
return parseInt(this.volume * 100) |
|||
}, |
|||
/** @returns {number} */ |
|||
currentTime: { |
|||
set(val) { |
|||
this.player.currentTime = val |
|||
}, |
|||
get() { |
|||
return this.player?.currentTime ?? 0 |
|||
} |
|||
}, |
|||
/** @returns {string} */ |
|||
currentTimeLabel() { |
|||
return formatTime(this.currentTime) |
|||
}, |
|||
/** @returns {boolean} */ |
|||
isMuted() { |
|||
return this.volume === 0 |
|||
}, |
|||
/** @returns {boolean} */ |
|||
isRecording() { |
|||
return this.player && this.player.isRecording |
|||
}, |
|||
/** @returns {number} */ |
|||
recordingDuration() { |
|||
return this.player ? this.player.recordingDuration : 0 |
|||
}, |
|||
/** @returns {string} */ |
|||
recordingDurationLabel() { |
|||
return formatTime(this.recordingDuration) |
|||
}, |
|||
/** @returns {boolean} */ |
|||
showCloseBtn() { |
|||
return this.closeable && !this.flags.fullscreen |
|||
}, |
|||
/** @returns {boolean} */ |
|||
showTitle() { |
|||
return this.flags.playerHover |
|||
// && |
|||
// (this.$slots.title || this.title || this.showCloseBtn) |
|||
} |
|||
}, |
|||
watch: { |
|||
url(nval) { |
|||
// this.rotate(0) |
|||
// if (this.player) { |
|||
// this.player.setUrl(nval) |
|||
// } else { |
|||
// this.initPlayer() |
|||
// } |
|||
this.player?.destroy() |
|||
|
|||
if (this.url == null || this.url === '') { |
|||
this.player = null |
|||
} else { |
|||
this.initPlayer() |
|||
} |
|||
}, |
|||
options: { |
|||
deep: true, |
|||
handler() { |
|||
this.destroyPlayer() |
|||
this.initPlayer() |
|||
} |
|||
}, |
|||
inBackground(nval) { |
|||
if (nval) { |
|||
this.intoBackground() |
|||
} else { |
|||
this.intoFront() |
|||
} |
|||
} |
|||
}, |
|||
// #endregion |
|||
|
|||
// #region 生命周期 |
|||
mounted() { |
|||
if (this.rootTabs) { |
|||
this.rootTabs.$on('tab-click', (tab) => { |
|||
try { |
|||
// 处理el-tabs切换标签时,el-table右侧可能出现空白的Bug |
|||
if (!tab.$el?.contains(this.$el)) { |
|||
this.intoBackground() |
|||
this.$emit('update:inBackground', true) |
|||
} |
|||
} catch (error) { |
|||
console.log(error) |
|||
} |
|||
}) |
|||
} |
|||
window.addEventListener('unload', () => { |
|||
this.destroyPlayer() |
|||
}) |
|||
this.init() |
|||
}, |
|||
beforeDestroy() { |
|||
this.destroyPlayer() |
|||
}, |
|||
// #endregion |
|||
|
|||
methods: { |
|||
init() { |
|||
this.initPlayer() |
|||
}, |
|||
|
|||
initPlayer() { |
|||
if (!this.url) return |
|||
|
|||
this.loading = true |
|||
this.player = new JSMpeg.Player(this.url, { |
|||
contianer: this.$refs['canvas-wrap'], |
|||
...this.options, |
|||
onVideoDecode: (decoder, time) => { |
|||
this.$emit('video-decode', decoder, time) |
|||
}, |
|||
onAudioDecode: (decoder, time) => { |
|||
this.$emit('audio-decode', decoder, time) |
|||
}, |
|||
onPlay: (player) => { |
|||
this.loading = false |
|||
console.log('onPlay') |
|||
this.$emit('play', player) |
|||
}, |
|||
onPause: (player) => { |
|||
this.loading = false |
|||
console.log('onPause') |
|||
this.$emit('pause', player) |
|||
}, |
|||
onEnded: (player) => { |
|||
console.log('onEnded') |
|||
this.$emit('ended', player) |
|||
}, |
|||
onStalled: (player) => { |
|||
console.log('onStalled') |
|||
this.$emit('stalled', player) |
|||
}, |
|||
onSourceEstablished: (source) => { |
|||
console.log('onSourceEstablished') |
|||
|
|||
this.flags.noSignal = false |
|||
this.loading = false |
|||
clearTimeout(this.timers.noSignal) |
|||
this.timers.noSignal = null |
|||
|
|||
this.$emit('source-established', source) |
|||
}, |
|||
onSourceCompleted: (source) => { |
|||
console.log('onSourceCompleted') |
|||
this.$emit('source-completed', source) |
|||
}, |
|||
onSourceConnected: () => { |
|||
console.log('onSourceConnected') |
|||
clearTimeout(this.timers.noSignal) |
|||
this.loading = true |
|||
this.flags.noSignal = false |
|||
this.$emit('source-connected') |
|||
}, |
|||
onSourceStreamInterrupt: () => { |
|||
console.log('onSourceStreamInterrupt') |
|||
this.loading = true |
|||
clearTimeout(this.timers.noSignal) |
|||
|
|||
this.timers.noSignal = setTimeout(this.handleNoSignal, 15000) |
|||
this.$emit('source-interrupt') |
|||
}, |
|||
onSourceStreamContinue: () => { |
|||
console.log('onSourceStreamContinue') |
|||
clearTimeout(this.timers.noSignal) |
|||
this.timers.noSignal = null |
|||
this.loading = false |
|||
this.flags.noSignal = false |
|||
this.$emit('source-continue') |
|||
}, |
|||
onSourceClosed: () => { |
|||
console.log('onSourceClosed') |
|||
clearTimeout(this.timers.noSignal) |
|||
this.$emit('source-closed') |
|||
this.handleNoSignal() |
|||
}, |
|||
onResolutionDecode: (width, height) => { |
|||
// 从流中获取到视频的分辨率 |
|||
this.flags.gotResolution = true |
|||
this.settingPlayer('autoStretch', this.playerSettings.autoStretch) |
|||
this.$emit('resolution-decode', width, height) |
|||
} |
|||
}) |
|||
this.playerSettings.backgroudPlay = !this.options.pauseWhenHidden |
|||
|
|||
if (this.defaultMute) { |
|||
this.volume = 0 |
|||
} |
|||
|
|||
this.timers.noSignal = setTimeout(this.handleNoSignal, 15000) |
|||
|
|||
for (const key in this.playerSettings) { |
|||
this.settingPlayer(key, this.playerSettings[key]) |
|||
} |
|||
|
|||
console.log('player', this.player) |
|||
}, |
|||
rotate(angle, append = false) { |
|||
this.player.rotate(angle, append) |
|||
}, |
|||
|
|||
// #region 方法 |
|||
/** |
|||
* 进入画中画模式 |
|||
* @deprecated 未实现 |
|||
*/ |
|||
requesPip() { |
|||
// if (!document.pictureInPictureElement) { |
|||
// this.$refs.canvas.requestPictureInPicture() |
|||
// } |
|||
}, |
|||
/** |
|||
* 退出画中画模式 |
|||
* @deprecated 未实现 |
|||
*/ |
|||
exitPip() { |
|||
// document.exitPictureInPicture() |
|||
}, |
|||
/** |
|||
* 切换全屏模式 |
|||
*/ |
|||
// toggleFullscreen() { |
|||
// if (this.flags.fullscreen) { |
|||
// fullscreen.exit(this.$el) |
|||
// } else { |
|||
// fullscreen.request(this.$el, () => { |
|||
// this.flags.fullscreen = false |
|||
// }) |
|||
// } |
|||
// this.flags.fullscreen = !this.flags.fullscreen |
|||
// }, |
|||
play() { |
|||
if (!this.url) return |
|||
this.loading = true |
|||
if (!this.player) { |
|||
this.initPlayer() |
|||
} |
|||
this.player?.play() |
|||
}, |
|||
/** |
|||
* 切换播放模式 |
|||
*/ |
|||
togglePlay() { |
|||
if (this.paused) { |
|||
this.play() |
|||
} else { |
|||
this.pause() |
|||
} |
|||
}, |
|||
pause() { |
|||
this.player?.pause() |
|||
}, |
|||
intoFront() { |
|||
this.player?.intoFront() |
|||
}, |
|||
intoBackground() { |
|||
this.player?.intoBackground() |
|||
}, |
|||
stop(clear) { |
|||
this.player?.stop(clear) |
|||
}, |
|||
nextFrame() { |
|||
this.player?.nextFrame() |
|||
}, |
|||
destroyPlayer() { |
|||
this.stop() |
|||
this.player?.destroy() |
|||
this.player = null |
|||
}, |
|||
mute() { |
|||
this.lastVolume = this.volume |
|||
this.volume = 0 |
|||
}, |
|||
toggleMute() { |
|||
if (this.isMuted) { |
|||
this.volume = this.lastVolume ? this.lastVolume : 1 |
|||
} else { |
|||
this.mute() |
|||
} |
|||
this.$emit('volume-change', this.volume) |
|||
}, |
|||
/** 截图 */ |
|||
snapshot() { |
|||
this.player?.snapshot(this.displayTitle) |
|||
}, |
|||
recording() { |
|||
this.player?.recording(this.title) |
|||
}, |
|||
|
|||
/** |
|||
* @param |
|||
*/ |
|||
settingPlayer(optionName, value) { |
|||
if (!this.player) return |
|||
switch (optionName) { |
|||
case 'autoStretch': { |
|||
if (!this.flags.gotResolution) return |
|||
|
|||
const canvas = this.player.canvas |
|||
if (value) { |
|||
if (canvas.width > canvas.height) { |
|||
canvas.style.width = '100%' |
|||
} else { |
|||
canvas.style.height = '100%' |
|||
} |
|||
} else { |
|||
canvas.style.width = '' |
|||
canvas.style.height = '' |
|||
} |
|||
break |
|||
} |
|||
default: |
|||
this.player?.setOption(optionName, value) |
|||
break |
|||
} |
|||
}, |
|||
// #endregion |
|||
|
|||
handleToolbar(cmd) { |
|||
if (!this.player) return |
|||
|
|||
switch (cmd) { |
|||
case 'play': |
|||
this.togglePlay() |
|||
break |
|||
case 'stop': |
|||
this.stop() |
|||
break |
|||
case 'mute': |
|||
this.toggleMute() |
|||
break |
|||
case 'snapshot': |
|||
this.snapshot() |
|||
break |
|||
case 'recording': |
|||
this.recording() |
|||
break |
|||
// case 'fullscreen': |
|||
// this.toggleFullscreen() |
|||
// break |
|||
} |
|||
}, |
|||
handleNoSignal() { |
|||
this.flags.noSignal = true |
|||
this.loading = false |
|||
this.stop() |
|||
this.$emit('no-signal') |
|||
}, |
|||
handlePlayerMouseEnter() { |
|||
this.flags.playerHover = true |
|||
}, |
|||
handleCanvasMouseMove() { |
|||
this.flags.playerHover = true |
|||
clearTimeout(this.timers.canvasMouseMove) |
|||
this.timers.canvasMouseMove = setTimeout(() => { |
|||
this.flags.playerHover = false |
|||
}, 3000) |
|||
}, |
|||
handlePlayerMouseLeave() { |
|||
clearTimeout(this.timers.canvasMouseMove) |
|||
this.flags.playerHover = false |
|||
}, |
|||
handleCanvasClick() { }, |
|||
handleToolbarMouseEnter() { |
|||
this.flags.playerHover = true |
|||
clearTimeout(this.timers.canvasMouseMove) |
|||
}, |
|||
handleToolbarMouseLeave() { } |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" src="./styles/index.scss"></style> |
|||
@ -0,0 +1,3 @@ |
|||
import JSMpeg from './modules/jsmpeg' |
|||
|
|||
export default JSMpeg |
|||