演示项目

This commit is contained in:
2023-12-12 17:31:48 +08:00
parent 9e3f0c440a
commit 9ae4a83573
121 changed files with 20562 additions and 288 deletions

3
web_home/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
node_modules
.idea
dist

24
web_home/README.md Normal file
View File

@@ -0,0 +1,24 @@
# map-web
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).

5
web_home/babel.config.js Normal file
View File

@@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}

15589
web_home/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

73
web_home/package.json Normal file
View File

@@ -0,0 +1,73 @@
{
"name": "web-home",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"@antv/g6": "^4.2.7",
"@antv/x6": "^1.30.1",
"@antv/x6-vue-shape": "^1.3.1",
"@vue/composition-api": "^1.4.9",
"axios": "^0.21.1",
"core-js": "^3.6.5",
"cssnano": "^5.0.8",
"echarts": "^5.3.2",
"element-ui": "^2.15.10",
"js-base64": "^3.7.2",
"js-cookie": "^2.2.0",
"less-loader": "^5.0.0",
"lodash": "^4.17.21",
"node-sass": "^6.0",
"normalize.css": "^8.0.1",
"postcss-aspect-ratio-mini": "^1.1.0",
"postcss-cssnext": "^3.1.1",
"postcss-px-to-viewport": "^1.1.1",
"postcss-viewport-units": "^0.1.6",
"postcss-write-svg": "^3.0.1",
"sortablejs": "^1.14.0",
"vue": "^2.6.11",
"vue-axios": "^3.2.4",
"vue-json-editor": "^1.4.3",
"vue-papa-parse": "^3.1.0",
"vue-quill-editor": "^3.0.6",
"vuex": "^3.1.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"babel-eslint": "^10.1.0",
"d3": "^7.4.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"sass-loader": "^10.0",
"stylus-loader": "^3.0.2",
"vue-router": "^3.5.1",
"vue-template-compiler": "^2.6.11"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {
"no-unused-vars": "off"
}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}

View File

@@ -0,0 +1,14 @@
module.exports = {
plugins: {
autoprefixer: {},
"postcss-px-to-viewport": {
viewportWidth: 1920,//视窗的宽度,对应的是我们设计稿的宽度
viewportHeight: 1080,//视窗的高度,对应的是我们设计稿的高度
unitPrecision: 5,//制定px转换为视窗单位的小数位数很多时候无法整除
viewportUnit: 'vw',//指定需要转换成的视窗单位建议使用vw
selectorBlackList: ['ignore', 'tab-bar', 'tab-bar-item'],//指定不需要转换的类,
minPixelValue: 1,//小于或等于1px不转换为视窗单位
mediaQuery: false//允许在媒体查询中转换为px
}
}
}

View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

154
web_home/src/App.vue Normal file
View File

@@ -0,0 +1,154 @@
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
}
</script>
<style>
body {
overflow: auto;
min-width: 1280px;
font-size: 14px;
}
html, body, #app {
height: 100%;
}
.el-table th.is-leaf {
background: rgba(235,241,255);
border-top: 1px solid #EBEEF5;
}
.el-table th.el-table__cell{
background: rgba(235,241,255)!important;
color: #333333!important;
font-weight: normal!important;
}
.menu-content {
margin: 25px;
background: #FFFFFF;
overflow: auto;
position: absolute;
left: 260px;
top: 40px;
bottom: 0;
right: 0;
padding: 25px;
border-radius: 3px;
}
.page-box {
text-align: center;
margin-top: 20px;
}
.menu-content .el-table td, .menu-content .el-table th {
padding: 10px 0;
}
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409EFF;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 178px;
text-align: center;
}
.avatar {
width: 178px;
height: 178px;
display: block;
}
.login-input .el-input__inner{
height: 60px!important;
line-height: 60px!important;
border-radius: 10px!important;
font-size: 16px!important;
padding: 0px 30px 0 60px!important;
}
.el-tag {
margin-left: 5px!important;
margin-bottom: 5px!important;
}
.login-input i{
font-size: 30px!important;
line-height: 60px!important;
margin-left: 15px!important;
}
.login-button{
height: 50px!important;
border-radius: 10px!important;
//background: rgba(16,108,255, 1);
border: none;
font-size: 16px!important;
letter-spacing:5px!important;
margin-bottom: 20px;
}
/*滚动条样式*/
::-webkit-scrollbar {/*滚动条整体样式*/
width: 8px; /*高宽分别对应横竖滚动条的尺寸*/
height: 1px;
}
::-webkit-scrollbar-thumb {/*滚动条里面小方块*/
border-radius: 5px;
-webkit-box-shadow: inset 0 0 5px #d9d9d9;
background: #d9d9d9;
}
::-webkit-scrollbar-track { /*滚动条里面轨道*/
-webkit-box-shadow: inset 0 0 5px #ffffff;
border-radius: 0;
background: #ffffff;
}
.el-dialog__header{
background: cornflowerblue;
padding-bottom:15px!important;
padding-top: 15px!important;
}
.el-dialog__title{
color: #ffffff!important;
}
.el-dialog__headerbtn .el-dialog__close{
color: #ffffff!important;
}
.el-dialog__body{
padding-bottom:20px!important;
}
.content-box .el-input__inner{
height: 33px!important;
line-height: 33px!important;
}
.content-box .el-button--primary,.content-box .el-button--default{
padding: 9px 15px!important;
font-size: 12px!important;
}
</style>

27
web_home/src/api/user.js Normal file
View File

@@ -0,0 +1,27 @@
import request from '@/utils/request'
export function login(data) {
return request({
url: '/login/user',
method: 'post',
data
})
}
export function getInfoAdmin(data) {
return request({
url: '/user/info_admin',
method: 'post',
})
}
export function getFriends(userId) {
let space = 'user_relation';
return request({
url: `/nebula_operate/findonepathbyidwithrelation/${space}/${userId}`,
method: 'post',
data: {
relations: ['edge_768395026']
}
})
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@@ -0,0 +1,854 @@
/** reset **/
body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, dl, dt, dd, ul, ol, li, pre, form, fieldset, legend, button, input, textarea, th, td, img{border:medium none;margin: 0;padding: 0;font-size: 100%;}
body,button, input, select, textarea{font-size: 14px;line-height: 1.5;font-family: Arial, 'Microsoft Yahei';}
h1, h2, h3, h4, h5, h6{font-weight: normal;}
em{font-style:normal;}
ul, ol{list-style: none;}
button{background: none;border: none;outline: none;-webkit-appearance: none;}
textarea{resize: none;}
a{text-decoration: none;color:#333;}
a:hover{text-decoration: none;
color:#0D6DFF;
-moz-transition: all 0.3s ease-in;
-webkit-transition: all 0.3s ease-in;
-o-transition: all 0.3s ease-in;
transition: all 0.3s ease-in;
}
img{border:0px; outline-width:0px; vertical-align:top;}
.clearfix { *zoom: 1; }
.clearfix:before, .clearfix:after { display: table; line-height: 0; content: ""; }
.clearfix:after { clear: both; }
.fl { float:left;}
.fr { float:right;}
.hide { display:none !important;}
.show { display:block !important;}
/*******************************************
-****公共样式****-
********************************************/
html,body{overflow-x: hidden;}
.wp{width: 1200px;max-width: 94%;margin: 0 auto;}
#hd{height: 68px;background: #0571FF;position: relative;z-index: 11;}
.hd-logo{height: 100%;line-height: 68px;margin-left: 40px;}
.hd-logo img{vertical-align: middle;max-height: 80%;}
.hd-nav{margin-left: 9.3%;}
.hd-nav ul li{float: left;margin: 0 20px;}
.hd-nav ul li h3 a{display: block;line-height: 68px;padding: 0 10px;font-size: 16px;color: #fff;position: relative;overflow: hidden;}
.hd-nav ul li h3 a::after{display: block;content: "";width: 100%;height: 2px;position: absolute;bottom: 0;left: 0;}
.hd-nav ul li.on h3 a::after{background: #00FF66;-webkit-transition: 0.4s ease;-ms-transition: 0.4s ease;transition: 0.4s ease;}
@media screen and (min-width: 1366px) {
.hd-nav ul li h3 a:hover::after{background: #00FF66;-webkit-transition: 0.4s ease;-ms-transition: 0.4s ease;transition: 0.4s ease;}
}
.hd-nav ul li .subnav{position: absolute;width: 100%;left: 0;top: 100%;background: rgba(255, 255, 255, 0.95);padding: 30px;text-align: center;display: none;}
.hd-nav ul li .sub-inner{width: 1000px;max-width: 60%;margin: 0 auto;}
.hd-nav ul li .sub-inner a{float: left;line-height: 24px;display: inline-block;margin: 5px 40px;}
.hd-bar h3{float: left;font-size: 14px;line-height: 20px;border-right: 1px solid #fff;margin: 24px 0 0 0;padding-right: 49px;color: #fff;}
.hd-bar .hd-user{padding: 19px 40px 0;height: 68px;position: relative;}
.hd-bar .hd-user .photo{display: block;width: 30px;height: 30px;border-radius: 100%;overflow: hidden;}
.hd-bar .hd-user .photo img{width: 100%;height: 100%;}
.hd-bar .hd-user .dropdown{position: absolute;width: 100%;right: 0;top: 100%;background: rgba(255, 255, 255, 0.3);padding: 0 10px;display: none;}
.hd-bar .hd-user .dropdown ul li a{display: block;line-height: 48px;color: rgba(255, 255, 255, 0.5);border-bottom: 1px solid rgba(255, 255, 255, 0.3);}
.hd-bar .hd-user .dropdown ul li a:hover{color: #fff;transition: 0.4s ease;}
.hd-bar .hd-user .dropdown .signout{display: block;line-height: 38px;color: #fff;}
#ft{background: #222C3A;}
#ft .ft-infos{padding: 32px 0;}
#ft .ft-infos .hot-line{color: #fff;line-height: 30px;}
#ft .ft-infos .hot-line h4{font-size: 18px;margin-bottom: 15px;}
#ft .ft-infos .hot-line h4 img{vertical-align: top;margin: 0 10px 0 0;}
#ft .ft-infos .hot-line h3{font-size: 22px;letter-spacing: 1px;}
#ft .ft-infos dl{float: right;margin-left: 80px;}
#ft .ft-infos dl dt{font-size: 16px;line-height: 22px;color: #fff;margin-bottom: 24px;}
#ft .ft-infos dl dd{font-size: 12px;line-height: 28px;color: #ccc;}
#ft .ft-infos dl dd a{color: #ccc;}
#ft .ft-infos dl dd a:hover{color: #fff;}
#ft .ft-infos .erweima li{float: left;margin-left: 46px;text-align: center;}
#ft .ft-infos .erweima li img{}
#ft .ft-infos .erweima li p{line-height: 24px;color: #fff;margin-top: 14px;font-size: 13px;}
#ft .copyright{border-top: 1px solid rgba(216, 216, 216, 0.1);padding: 10px 20px;}
#ft .copyright p{text-align: center;line-height: 20px;font-size: 12px;color: #888;}
.sidebar{position: fixed;top: 50%;right: 30px;z-index: 97;width: 48px;-webkit-transform: translateY(-50%);-ms-transform: translateY(-50%);transform: translateY(-50%);}
.sidebar a{display: block;width: 48px;height: 48px;box-sizing: border-box;border: 1px solid #e6e6e6;background-color: #fff;}
.sidebar .backtop{background-image: url('index/icon3.png');background-size: 100% 100%;margin-top: 36px;transform: translateX(200%);transition: 0.4s;}
.sidebar .backtop:hover{background: #0066FF url('index/icon3-on.png');background-size: 100% 100%;border-color: #0066FF;}
.sidebar .backtop.backtop-show{transform: translateX(0);transition: 0.4s;}
.sidebar .side-inner{border: 1px solid #D7D7D7;background: #fff;border-radius: 4px;box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);position: relative;}
.sidebar .side-inner::before{display: block;content: "";width: 4px;height: 4px;border: 1px solid #fff;border-color: #d7d7d7 #d7d7d7 #fff #fff;background: #fff;position: absolute;top: 50%;right: -4px;margin-top: -4px;transform: rotate(45deg);}
.sidebar .side-phone{position: relative;}
.sidebar .side-phone .phone-num{position: absolute;top: 50%;right: 100%;-webkit-transform: translateY(-50%);-ms-transform: translateY(-50%);transform: translateY(-50%);padding-right: 10px;display: none;}
.sidebar .side-phone .phone-num span{display: block;line-height: 56px;padding: 0 15px;white-space: nowrap;font-size: 16px;color: #666;}
.sidebar .side-phone:hover .phone-num{display: block;}
.sidebar .side-erweima{position: relative;margin-top: 20px;}
.sidebar .side-erweima .erweima{position: absolute;top: 50%;right: 100%;-webkit-transform: translateY(-50%);-ms-transform: translateY(-50%);transform: translateY(-50%);padding-right: 10px;display: none;}
.sidebar .side-erweima:hover .erweima{display: block;}
@media screen and (max-width: 1280px) {
.hd-nav{margin-left: 5%;}
.hd-nav ul li .sub-inner{max-width: 80%;}
.hd-nav ul li{margin: 0 12px;}
.hd-bar h3{padding-right: 20px;}
.hd-bar .hd-user{padding: 19px 20px 0;}
#ft .ft-infos dl{margin-left: 3%;max-width: 200px;}
#ft .ft-infos .erweima li{margin-left: 24px;}
#ft .ft-infos .erweima li img{width: 100px;}
}
@media screen and (max-width: 1000px) {
.hd-nav{margin-left: 3%;}
.hd-nav ul li{margin: 0 10px;}
.hd-nav ul li .sub-inner{max-width: 94%;}
.hd-bar h3{padding-right: 10px;}
.hd-bar .hd-user{padding: 19px 8px 0;}
}
/*******************************************
-****首页样式****-
********************************************/
#banner{height: 500px;width: 100%;}
#banner .wp{height: 100%;position: relative;}
#banner .text{float: left;width: 50%;color: #fff;position: relative;top: 50%;-webkit-transform: translateY(-50%);-ms-transform: translateY(-50%);transform: translateY(-50%);}
#banner .text h2{font-size: 36px;line-height: 50px;}
#banner .text p{font-size: 16px;line-height: 32px;margin-top: 23px;}
#banner .text a{display: block;vertical-align: top;margin-top: 46px;width: 201px;line-height: 34px;background: #74FF00;border-radius: 4px;text-align: center;}
#banner .img{float: right;width: 50%;height: 100%;position: relative;}
#banner .img img{max-width: 90%;max-height: 90%;position: absolute;right: 0;top: 50%;-webkit-transform: translateY(-50%);-ms-transform: translateY(-50%);transform: translateY(-50%);}
#banner .swiper-pagination-bullet{width: 18px;height: 18px;background: url('index/hexagon.png');background-size: 100% 100%;}
.title{text-align: center;margin-bottom: 90px;}
.title h3 span{display: inline-block;vertical-align: top;line-height: 40px;font-size: 28px;color: #0D1A26;position: relative;}
.title h3 span::before,
.title h3 span::after{display: inline-block;content: "";width: 188px;height: 1px;background: #ADBAC6;position: absolute;top: 50%;}
.title h3 span::before{left: -236px;}
.title h3 span::after{right: -236px;}
.title p{margin-top: 28px;font-size: 16px;line-height: 22px;color: #314659;}
.title.white h3 span{color: #fff;}
.title.white h3 ::before,
.title.white h3 ::after{background: #fff;}
.title.white p{color: #fff;}
.index-sec1{padding: 86px 0 130px;}
.index-sec1 ul{margin: 0 -14px;}
.index-sec1 ul li{float: left;width: 25%;box-sizing: border-box;padding: 0 14px;}
.index-sec1 .item-box{padding: 70px 20px 31px;background: #F6F8FA;border-radius: 4px;text-align: center;overflow: hidden;}
.index-sec1 .item-box .inner-wp{transition: 0.4s;}
.index-sec1 .item-box span{display: block;width: 60px;height: 60px;margin: 0 auto 26px;position: relative;}
.index-sec1 .item-box span img{width: 100%;height: 100%;transition: 0.4s;}
.index-sec1 .item-box span .img-hover{position: absolute;top: 0;left: 0;opacity: 0;}
.index-sec1 .item-box p{font-size: 18px;line-height: 28px;color: #666;}
.index-sec1 .item-box a{display: block;display: block;width: 90px;line-height: 32px;margin: 22px auto 0;text-align: center;color: #fff;font-size: 18px;color: #666;cursor: auto}
.index-sec1 .item-box:hover{background: #375EEE;transition: 0.4s;}
/*.index-sec1 .item-box:hover .inner-wp{transition: 0.4s;transform: translateY(-30px);}*/
.index-sec1 .item-box:hover span .img{opacity: 0;transition: 0.4s;}
.index-sec1 .item-box:hover span .img-hover{opacity: 1;transition: 0.4s;}
.index-sec1 .item-box:hover p{color: #fff;transition: 0.4s;}
.index-sec1 .item-box:hover a{transform: translateY(0);transition: 0.4s ease in;color: #fff}
.index-sec2{padding: 72px 0 32px;background: #F6F8FA;}
.index-sec2 ul li{float: left;width: 25%;margin-bottom: 88px;text-align: center;}
.index-sec2 ul li a{display: block;}
.index-sec2 ul li span{display: block;width: 102px;height: 102px;background: #fff;border-radius: 100%;overflow: hidden;margin: 0 auto 40px;transition: 0.4s ease-in-out;}
.index-sec2 ul li span img{width: 100%;height: 100%;}
.index-sec2 ul li h4{font-size: 18px;line-height: 25px;}
.index-sec2 ul li p{color: #385064;height: 40px;overflow: hidden;line-height: 20px;max-width: 188px;margin: 8px auto 0;}
.index-sec2 ul li:hover h4{color: #0066FF;transition: 0.4s;}
.index-sec2 ul li:hover p{color: #0066FF;transition: 0.4s;}
.index-sec2 ul li:hover span{transition: 0.4s ease-in-out;transform: translateY(-10px);}
.index-sec3{background: #396CEF url('index/pattern.png');background-size: 100% 100%;padding: 86px 0 124px;}
.index-sec3 .item-swiper{margin: 0 -15px;position: relative;}
.index-sec3 .item-swiper .swiper-slide{padding: 0 15px;}
.index-sec3 .item-swiper .item-box{display: block;border-radius: 4px;overflow: hidden;}
.index-sec3 .item-swiper .item-box .img{overflow: hidden;height: 300px;border-bottom:1px solid #ADBAC6;background: #ffffff;padding: 20px}
.index-sec3 .item-swiper .item-box .img span{display: block;height: 100%;border-radius: 4px 4px 0 0;overflow: hidden;}
.index-sec3 .item-swiper .item-box .img img{width: 100%;height: 100%;transition: 0.4s;}
.index-sec3 .item-swiper .item-box .text{padding: 20px 40px;background: #fff;text-align: center;}
.index-sec3 .item-swiper .item-box .text h4{font-size: 16px;line-height: 22px;color: #2A2A2A;}
.index-sec3 .item-swiper .item-box .text p{margin-top: 18px;font-size: 12px;line-height: 18px;color: #385064;height: 36px;overflow: hidden;}
.index-sec3 .item-swiper .item-box .text .links{margin-top: 16px;}
.index-sec3 .item-swiper .item-box .text .links span{display: inline-block;vertical-align: top;width: 36px;height: 36px;border-radius: 100%;overflow: hidden;margin: 0 14px;}
.index-sec3 .item-swiper .item-box:hover{filter: grayscale(0%);transition: 0.4s;}
.index-sec3 .item-swiper .item-box:hover .img img{transition: 0.4s;transform: scale(1.1);}
.index-sec3 .item-swiper .swiper-button-prev,
.index-sec3 .item-swiper .swiper-button-next{width: 24px;height: 36px;margin-top: -18px;outline: none;}
.index-sec3 .item-swiper .swiper-button-prev{background: url('index/prev.png');background-size: 100% 100%;left: -40px;}
.index-sec3 .item-swiper .swiper-button-next{background: url('index/next.png');background-size: 100% 100%;right: -40px;}
.index-sec4{padding: 97px 0 100px;}
.index-sec4 .title{margin-bottom: 60px;}
.index-sec4 ul li{float: left;width: 25%;}
.index-sec4 ul li a{display: table-cell;width: 300px;height: 90px;text-align: center;vertical-align: middle;margin-bottom: 30px;}
.index-sec4 ul li a img{max-height: 90%;max-width: 90%;}
@media screen and (max-width: 1320px) {
.index-sec3 .item-swiper .swiper-button-prev{left: 0px;}
.index-sec3 .item-swiper .swiper-button-next{right: 0px;}
}
/*******************************************
-****内页样式****-
********************************************/
.page-banner{height: 260px;background: url('index/download-banner.jpg') center 0;position: relative;}
.page-banner .text{position: absolute;left: 0;width: 100%;top: 50%;-webkit-transform: translateY(-50%);-ms-transform: translateY(-50%);transform: translateY(-50%);color: #fff;text-align: center;}
.page-banner .text h1{font-size: 68px;line-height: 95px;}
.page-banner .text h5{font-size: 20px;line-height: 28px;margin-top: 11px;}
/* 解决方案 */
.solution .sol-wp{width: 1400px;max-width: 94%;margin: 0 auto;}
.solution .sol-wp .img{text-align: center;}
.solution .sol-wp .img img{max-width: 100%;}
.solution .sol-sec1{background: #F6F8FA;/* padding: 85px 0 123px; */}
.solution .sol-sec2{/* padding: 88px 0 153px; */}
.solution .sol-sec3{/* padding: 81px 0 123px; */background: url('index/sol-bg3.png');background-size: 100% 100%;}
.solution .sol-sec4{/* padding: 87px 0 99px; */}
/* 资源下载 */
.download{padding: 30px 0 129px;}
.download>ul>li{padding: 16px 0px 14px 16px;background: #fff;position: relative;}
.download ul li .text h4{font-size: 18px;line-height: 25px;color: #0D1A26;margin-bottom: 14px;}
.download ul li .text p{font-size: 13px;line-height: 18px;margin-bottom: 7px;color: #555;display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 2;overflow: hidden;}
.download ul li .text h5{font-size: 12px;line-height: 17px;color: #314659;}
.download ul li .btns{position: absolute;right: 16px;top: 50%;margin-top: -25px;height: 50px;}
.download ul li .btns a{float: left;}
.download ul li .btns a.see-btn{color: #0066FF;line-height: 22px;margin: 14px 20px 0 0;}
.download ul li .btns a.download-btn{line-height: 50px;padding: 0 25px;background: #0066FF;border-radius: 4px;color: #fff;}
.download ul li:hover{box-shadow: 0px 5px 12px 1px rgba(105, 105, 105, 0.12);z-index: 11;}
/**
* Swiper 4.4.2
* Most modern mobile touch slider and framework with hardware accelerated transitions
* http://www.idangero.us/swiper/
*
* Copyright 2014-2018 Vladimir Kharlampidi
*
* Released under the MIT License
*
* Released on: November 1, 2018
*/
.swiper-container {
margin: 0 auto;
position: relative;
overflow: hidden;
list-style: none;
padding: 0;
/* Fix of Webkit flickering */
z-index: 1;
}
.swiper-container-no-flexbox .swiper-slide {
float: left;
}
.swiper-container-vertical > .swiper-wrapper {
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
}
.swiper-wrapper {
position: relative;
width: 100%;
height: 100%;
z-index: 1;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-transition-property: -webkit-transform;
transition-property: -webkit-transform;
-o-transition-property: transform;
transition-property: transform;
transition-property: transform, -webkit-transform;
-webkit-box-sizing: content-box;
box-sizing: content-box;
}
.swiper-container-android .swiper-slide,
.swiper-wrapper {
-webkit-transform: translate3d(0px, 0, 0);
transform: translate3d(0px, 0, 0);
}
.swiper-container-multirow > .swiper-wrapper {
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
}
.swiper-container-free-mode > .swiper-wrapper {
-webkit-transition-timing-function: ease-out;
-o-transition-timing-function: ease-out;
transition-timing-function: ease-out;
margin: 0 auto;
}
.swiper-slide {
-webkit-flex-shrink: 0;
-ms-flex-negative: 0;
flex-shrink: 0;
width: 100%;
height: 100%;
position: relative;
-webkit-transition-property: -webkit-transform;
transition-property: -webkit-transform;
-o-transition-property: transform;
transition-property: transform;
transition-property: transform, -webkit-transform;
}
.swiper-slide-invisible-blank {
visibility: hidden;
}
/* Auto Height */
.swiper-container-autoheight,
.swiper-container-autoheight .swiper-slide {
height: auto;
}
.swiper-container-autoheight .swiper-wrapper {
-webkit-box-align: start;
-webkit-align-items: flex-start;
-ms-flex-align: start;
align-items: flex-start;
-webkit-transition-property: height, -webkit-transform;
transition-property: height, -webkit-transform;
-o-transition-property: transform, height;
transition-property: transform, height;
transition-property: transform, height, -webkit-transform;
}
/* 3D Effects */
.swiper-container-3d {
-webkit-perspective: 1200px;
perspective: 1200px;
}
.swiper-container-3d .swiper-wrapper,
.swiper-container-3d .swiper-slide,
.swiper-container-3d .swiper-slide-shadow-left,
.swiper-container-3d .swiper-slide-shadow-right,
.swiper-container-3d .swiper-slide-shadow-top,
.swiper-container-3d .swiper-slide-shadow-bottom,
.swiper-container-3d .swiper-cube-shadow {
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
}
.swiper-container-3d .swiper-slide-shadow-left,
.swiper-container-3d .swiper-slide-shadow-right,
.swiper-container-3d .swiper-slide-shadow-top,
.swiper-container-3d .swiper-slide-shadow-bottom {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 10;
}
.swiper-container-3d .swiper-slide-shadow-left {
background-image: -webkit-gradient(linear, right top, left top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0)));
background-image: -webkit-linear-gradient(right, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
background-image: -o-linear-gradient(right, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
background-image: linear-gradient(to left, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
}
.swiper-container-3d .swiper-slide-shadow-right {
background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0)));
background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
}
.swiper-container-3d .swiper-slide-shadow-top {
background-image: -webkit-gradient(linear, left bottom, left top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0)));
background-image: -webkit-linear-gradient(bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
background-image: -o-linear-gradient(bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
background-image: linear-gradient(to top, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
}
.swiper-container-3d .swiper-slide-shadow-bottom {
background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0)));
background-image: -webkit-linear-gradient(top, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
background-image: -o-linear-gradient(top, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
}
/* IE10 Windows Phone 8 Fixes */
.swiper-container-wp8-horizontal,
.swiper-container-wp8-horizontal > .swiper-wrapper {
-ms-touch-action: pan-y;
touch-action: pan-y;
}
.swiper-container-wp8-vertical,
.swiper-container-wp8-vertical > .swiper-wrapper {
-ms-touch-action: pan-x;
touch-action: pan-x;
}
.swiper-button-prev,
.swiper-button-next {
position: absolute;
top: 50%;
width: 27px;
height: 44px;
margin-top: -22px;
z-index: 10;
cursor: pointer;
background-size: 27px 44px;
background-position: center;
background-repeat: no-repeat;
}
.swiper-button-prev.swiper-button-disabled,
.swiper-button-next.swiper-button-disabled {
opacity: 0.35;
cursor: auto;
pointer-events: none;
}
.swiper-button-prev,
.swiper-container-rtl .swiper-button-next {
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23007aff'%2F%3E%3C%2Fsvg%3E");
left: 10px;
right: auto;
}
.swiper-button-next,
.swiper-container-rtl .swiper-button-prev {
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23007aff'%2F%3E%3C%2Fsvg%3E");
right: 10px;
left: auto;
}
.swiper-button-prev.swiper-button-white,
.swiper-container-rtl .swiper-button-next.swiper-button-white {
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E");
}
.swiper-button-next.swiper-button-white,
.swiper-container-rtl .swiper-button-prev.swiper-button-white {
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E");
}
.swiper-button-prev.swiper-button-black,
.swiper-container-rtl .swiper-button-next.swiper-button-black {
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23000000'%2F%3E%3C%2Fsvg%3E");
}
.swiper-button-next.swiper-button-black,
.swiper-container-rtl .swiper-button-prev.swiper-button-black {
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23000000'%2F%3E%3C%2Fsvg%3E");
}
.swiper-button-lock {
display: none;
}
.swiper-pagination {
position: absolute;
text-align: center;
-webkit-transition: 300ms opacity;
-o-transition: 300ms opacity;
transition: 300ms opacity;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
z-index: 10;
}
.swiper-pagination.swiper-pagination-hidden {
opacity: 0;
}
/* Common Styles */
.swiper-pagination-fraction,
.swiper-pagination-custom,
.swiper-container-horizontal > .swiper-pagination-bullets {
bottom: 10px;
left: 0;
width: 100%;
}
/* Bullets */
.swiper-pagination-bullets-dynamic {
overflow: hidden;
font-size: 0;
}
.swiper-pagination-bullets-dynamic .swiper-pagination-bullet {
-webkit-transform: scale(0.33);
-ms-transform: scale(0.33);
transform: scale(0.33);
position: relative;
}
.swiper-pagination-bullets-dynamic .swiper-pagination-bullet-active {
-webkit-transform: scale(1);
-ms-transform: scale(1);
transform: scale(1);
}
.swiper-pagination-bullets-dynamic .swiper-pagination-bullet-active-main {
-webkit-transform: scale(1);
-ms-transform: scale(1);
transform: scale(1);
}
.swiper-pagination-bullets-dynamic .swiper-pagination-bullet-active-prev {
-webkit-transform: scale(0.66);
-ms-transform: scale(0.66);
transform: scale(0.66);
}
.swiper-pagination-bullets-dynamic .swiper-pagination-bullet-active-prev-prev {
-webkit-transform: scale(0.33);
-ms-transform: scale(0.33);
transform: scale(0.33);
}
.swiper-pagination-bullets-dynamic .swiper-pagination-bullet-active-next {
-webkit-transform: scale(0.66);
-ms-transform: scale(0.66);
transform: scale(0.66);
}
.swiper-pagination-bullets-dynamic .swiper-pagination-bullet-active-next-next {
-webkit-transform: scale(0.33);
-ms-transform: scale(0.33);
transform: scale(0.33);
}
.swiper-pagination-bullet {
width: 8px;
height: 8px;
display: inline-block;
border-radius: 100%;
background: #000;
opacity: 0.2;
}
button.swiper-pagination-bullet {
border: none;
margin: 0;
padding: 0;
-webkit-box-shadow: none;
box-shadow: none;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
.swiper-pagination-clickable .swiper-pagination-bullet {
cursor: pointer;
}
.swiper-pagination-bullet-active {
opacity: 1;
background: #007aff;
}
.swiper-container-vertical > .swiper-pagination-bullets {
right: 10px;
top: 50%;
-webkit-transform: translate3d(0px, -50%, 0);
transform: translate3d(0px, -50%, 0);
}
.swiper-container-vertical > .swiper-pagination-bullets .swiper-pagination-bullet {
margin: 6px 0;
display: block;
}
.swiper-container-vertical > .swiper-pagination-bullets.swiper-pagination-bullets-dynamic {
top: 50%;
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
width: 8px;
}
.swiper-container-vertical > .swiper-pagination-bullets.swiper-pagination-bullets-dynamic .swiper-pagination-bullet {
display: inline-block;
-webkit-transition: 200ms top, 200ms -webkit-transform;
transition: 200ms top, 200ms -webkit-transform;
-o-transition: 200ms transform, 200ms top;
transition: 200ms transform, 200ms top;
transition: 200ms transform, 200ms top, 200ms -webkit-transform;
}
.swiper-container-horizontal > .swiper-pagination-bullets .swiper-pagination-bullet {
margin: 0 4px;
}
.swiper-container-horizontal > .swiper-pagination-bullets.swiper-pagination-bullets-dynamic {
left: 50%;
-webkit-transform: translateX(-50%);
-ms-transform: translateX(-50%);
transform: translateX(-50%);
white-space: nowrap;
}
.swiper-container-horizontal > .swiper-pagination-bullets.swiper-pagination-bullets-dynamic .swiper-pagination-bullet {
-webkit-transition: 200ms left, 200ms -webkit-transform;
transition: 200ms left, 200ms -webkit-transform;
-o-transition: 200ms transform, 200ms left;
transition: 200ms transform, 200ms left;
transition: 200ms transform, 200ms left, 200ms -webkit-transform;
}
.swiper-container-horizontal.swiper-container-rtl > .swiper-pagination-bullets-dynamic .swiper-pagination-bullet {
-webkit-transition: 200ms right, 200ms -webkit-transform;
transition: 200ms right, 200ms -webkit-transform;
-o-transition: 200ms transform, 200ms right;
transition: 200ms transform, 200ms right;
transition: 200ms transform, 200ms right, 200ms -webkit-transform;
}
/* Progress */
.swiper-pagination-progressbar {
background: rgba(0, 0, 0, 0.25);
position: absolute;
}
.swiper-pagination-progressbar .swiper-pagination-progressbar-fill {
background: #007aff;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
-webkit-transform: scale(0);
-ms-transform: scale(0);
transform: scale(0);
-webkit-transform-origin: left top;
-ms-transform-origin: left top;
transform-origin: left top;
}
.swiper-container-rtl .swiper-pagination-progressbar .swiper-pagination-progressbar-fill {
-webkit-transform-origin: right top;
-ms-transform-origin: right top;
transform-origin: right top;
}
.swiper-container-horizontal > .swiper-pagination-progressbar,
.swiper-container-vertical > .swiper-pagination-progressbar.swiper-pagination-progressbar-opposite {
width: 100%;
height: 4px;
left: 0;
top: 0;
}
.swiper-container-vertical > .swiper-pagination-progressbar,
.swiper-container-horizontal > .swiper-pagination-progressbar.swiper-pagination-progressbar-opposite {
width: 4px;
height: 100%;
left: 0;
top: 0;
}
.swiper-pagination-white .swiper-pagination-bullet-active {
background: #ffffff;
}
.swiper-pagination-progressbar.swiper-pagination-white {
background: rgba(255, 255, 255, 0.25);
}
.swiper-pagination-progressbar.swiper-pagination-white .swiper-pagination-progressbar-fill {
background: #ffffff;
}
.swiper-pagination-black .swiper-pagination-bullet-active {
background: #000000;
}
.swiper-pagination-progressbar.swiper-pagination-black {
background: rgba(0, 0, 0, 0.25);
}
.swiper-pagination-progressbar.swiper-pagination-black .swiper-pagination-progressbar-fill {
background: #000000;
}
.swiper-pagination-lock {
display: none;
}
/* Scrollbar */
.swiper-scrollbar {
border-radius: 10px;
position: relative;
-ms-touch-action: none;
background: rgba(0, 0, 0, 0.1);
}
.swiper-container-horizontal > .swiper-scrollbar {
position: absolute;
left: 1%;
bottom: 3px;
z-index: 50;
height: 5px;
width: 98%;
}
.swiper-container-vertical > .swiper-scrollbar {
position: absolute;
right: 3px;
top: 1%;
z-index: 50;
width: 5px;
height: 98%;
}
.swiper-scrollbar-drag {
height: 100%;
width: 100%;
position: relative;
background: rgba(0, 0, 0, 0.5);
border-radius: 10px;
left: 0;
top: 0;
}
.swiper-scrollbar-cursor-drag {
cursor: move;
}
.swiper-scrollbar-lock {
display: none;
}
.swiper-zoom-container {
width: 100%;
height: 100%;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
text-align: center;
}
.swiper-zoom-container > img,
.swiper-zoom-container > svg,
.swiper-zoom-container > canvas {
max-width: 100%;
max-height: 100%;
-o-object-fit: contain;
object-fit: contain;
}
.swiper-slide-zoomed {
cursor: move;
}
/* Preloader */
.swiper-lazy-preloader {
width: 42px;
height: 42px;
position: absolute;
left: 50%;
top: 50%;
margin-left: -21px;
margin-top: -21px;
z-index: 10;
-webkit-transform-origin: 50%;
-ms-transform-origin: 50%;
transform-origin: 50%;
-webkit-animation: swiper-preloader-spin 1s steps(12, end) infinite;
animation: swiper-preloader-spin 1s steps(12, end) infinite;
}
.swiper-lazy-preloader:after {
display: block;
content: '';
width: 100%;
height: 100%;
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D'0%200%20120%20120'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20xmlns%3Axlink%3D'http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink'%3E%3Cdefs%3E%3Cline%20id%3D'l'%20x1%3D'60'%20x2%3D'60'%20y1%3D'7'%20y2%3D'27'%20stroke%3D'%236c6c6c'%20stroke-width%3D'11'%20stroke-linecap%3D'round'%2F%3E%3C%2Fdefs%3E%3Cg%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(30%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(60%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(90%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(120%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(150%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.37'%20transform%3D'rotate(180%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.46'%20transform%3D'rotate(210%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.56'%20transform%3D'rotate(240%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.66'%20transform%3D'rotate(270%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.75'%20transform%3D'rotate(300%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.85'%20transform%3D'rotate(330%2060%2C60)'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");
background-position: 50%;
background-size: 100%;
background-repeat: no-repeat;
}
.swiper-lazy-preloader-white:after {
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D'0%200%20120%20120'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20xmlns%3Axlink%3D'http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink'%3E%3Cdefs%3E%3Cline%20id%3D'l'%20x1%3D'60'%20x2%3D'60'%20y1%3D'7'%20y2%3D'27'%20stroke%3D'%23fff'%20stroke-width%3D'11'%20stroke-linecap%3D'round'%2F%3E%3C%2Fdefs%3E%3Cg%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(30%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(60%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(90%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(120%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(150%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.37'%20transform%3D'rotate(180%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.46'%20transform%3D'rotate(210%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.56'%20transform%3D'rotate(240%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.66'%20transform%3D'rotate(270%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.75'%20transform%3D'rotate(300%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.85'%20transform%3D'rotate(330%2060%2C60)'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");
}
@-webkit-keyframes swiper-preloader-spin {
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes swiper-preloader-spin {
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
/* a11y */
.swiper-container .swiper-notification {
position: absolute;
left: 0;
top: 0;
pointer-events: none;
opacity: 0;
z-index: -1000;
}
.swiper-container-fade.swiper-container-free-mode .swiper-slide {
-webkit-transition-timing-function: ease-out;
-o-transition-timing-function: ease-out;
transition-timing-function: ease-out;
}
.swiper-container-fade .swiper-slide {
pointer-events: none;
-webkit-transition-property: opacity;
-o-transition-property: opacity;
transition-property: opacity;
}
.swiper-container-fade .swiper-slide .swiper-slide {
pointer-events: none;
}
.swiper-container-fade .swiper-slide-active,
.swiper-container-fade .swiper-slide-active .swiper-slide-active {
pointer-events: auto;
}
.swiper-container-cube {
overflow: visible;
}
.swiper-container-cube .swiper-slide {
pointer-events: none;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
z-index: 1;
visibility: hidden;
-webkit-transform-origin: 0 0;
-ms-transform-origin: 0 0;
transform-origin: 0 0;
width: 100%;
height: 100%;
}
.swiper-container-cube .swiper-slide .swiper-slide {
pointer-events: none;
}
.swiper-container-cube.swiper-container-rtl .swiper-slide {
-webkit-transform-origin: 100% 0;
-ms-transform-origin: 100% 0;
transform-origin: 100% 0;
}
.swiper-container-cube .swiper-slide-active,
.swiper-container-cube .swiper-slide-active .swiper-slide-active {
pointer-events: auto;
}
.swiper-container-cube .swiper-slide-active,
.swiper-container-cube .swiper-slide-next,
.swiper-container-cube .swiper-slide-prev,
.swiper-container-cube .swiper-slide-next + .swiper-slide {
pointer-events: auto;
visibility: visible;
}
.swiper-container-cube .swiper-slide-shadow-top,
.swiper-container-cube .swiper-slide-shadow-bottom,
.swiper-container-cube .swiper-slide-shadow-left,
.swiper-container-cube .swiper-slide-shadow-right {
z-index: 0;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.swiper-container-cube .swiper-cube-shadow {
position: absolute;
left: 0;
bottom: 0px;
width: 100%;
height: 100%;
background: #000;
opacity: 0.6;
-webkit-filter: blur(50px);
filter: blur(50px);
z-index: 0;
}
.swiper-container-flip {
overflow: visible;
}
.swiper-container-flip .swiper-slide {
pointer-events: none;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
z-index: 1;
}
.swiper-container-flip .swiper-slide .swiper-slide {
pointer-events: none;
}
.swiper-container-flip .swiper-slide-active,
.swiper-container-flip .swiper-slide-active .swiper-slide-active {
pointer-events: auto;
}
.swiper-container-flip .swiper-slide-shadow-top,
.swiper-container-flip .swiper-slide-shadow-bottom,
.swiper-container-flip .swiper-slide-shadow-left,
.swiper-container-flip .swiper-slide-shadow-right {
z-index: 0;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.swiper-container-coverflow .swiper-wrapper {
/* Windows 8 IE 10 fix */
-ms-perspective: 1200px;
}

View File

@@ -0,0 +1,208 @@
<template>
<div>
<div class="menu-title">
全部用户
</div>
<div class="menu-content">
<div>
<el-form :inline="true" :model="qo" class="demo-form-inline">
<el-form-item label="用户ID">
<el-input v-model="qo.LIKES_fid" placeholder="请输入用户ID" clearable style="width: 300px"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="queryDataById()"> </el-button>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="queryData(-1)">上一页</el-button>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="queryData(1)">下一页</el-button>
</el-form-item>
</el-form>
</div>
<div>
<el-table :data="result.records" style="width: 100%" v-loading="loading">
<el-table-column type="index" label="行号" width="60"></el-table-column>
<el-table-column prop="UserId" label="用户ID"></el-table-column>
<el-table-column prop="Labels" label="标签">
<div slot-scope="scope">
<template v-if="scope.row.Labels">
<template v-for="(tag,index) in scope.row.Labels">
<el-tag :key="index" v-if="index < 5">{{ tag }}</el-tag>
</template>
<el-tag v-if="scope.row.Labels.length > 5">...</el-tag>
</template>
</div>
</el-table-column>
<el-table-column label="业务" width="80">
<template slot-scope="scope">
<el-button @click.native.prevent="followUser(scope.row)" type="text" size="small">
关注
</el-button>
</template>
</el-table-column>
<el-table-column label="操作" width="280">
<template slot-scope="scope">
<el-button @click.native.prevent="feedbackHistory(scope.row)" type="text" size="small">
Ta的喜欢
</el-button>
<el-button @click.native.prevent="linkUser(scope.row)" type="text" size="small">
Ta的好友
</el-button>
<el-button @click.native.prevent="similarUser(scope.row)" type="text" size="small">
相似用户
</el-button>
<el-button @click.native.prevent="recommendItem(scope.row)" type="text" size="small">
Ta的推荐
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
</div>
</template>
<script>
import request, {getBaseUrl} from '@/utils/request';
var _this;
var _index = 0;
export default {
name: "allUsers",
data() {
return {
qo: {
pageNo: 1,
pageSize: 10,
LIKES_fid: '',
},
result: {
records: [],
total: 0
},
loading: false,
cursorArr: [''], // 分页游标
}
},
mounted() {
_this = this;
let _qo = _this.$route.query.qo;
if (_qo) {
_this.qo = JSON.parse(_qo);
}
_this.queryData(0);
},
methods: {
queryDataById() {
if (this.qo.LIKES_fid.length > 0) {
this.loading = true;
request({
url: '/gorse/query_user/' + this.qo.LIKES_fid,
method: 'get',
}).then(res => {
let user = res.data;
if (!user) {
_this.result.records = [];
} else {
_this.result.records = [user];
}
this.loading = false;
});
} else {
this.cursorArr = [''];
this.queryData(1);
}
},
queryData(index) { // index -1 上一页0刷新 1下一页
this.loading = true;
this.cursorArr = this.cursorArr.slice(0, this.cursorArr.length - 1 + index);
this.cursorArr = this.cursorArr.length === 0 ? [''] : this.cursorArr;
request({
url: '/gorse/query_users?cursor=' + this.cursorArr[this.cursorArr.length - 1],
method: 'get',
}).then(res => {
this.cursorArr.push(res.data.Cursor);
_this.result.records = res.data.Users;
this.loading = false;
});
},
feedbackHistory(item) {
_this.$router.push({
path: "feedbackHistory", query: {
userId: item.UserId,
cursorArr: JSON.stringify(_this.cursorArr)
}
});
},
linkUser(item) {
_this.$router.push({
path: "linkUser", query: {
userId: item.UserId,
qo: JSON.stringify(_this.qo)
}
});
},
similarUser(item) {
_this.$router.push({
path: "similarUser", query: {
userId: item.UserId,
qo: JSON.stringify(_this.qo)
}
});
},
recommendItem(item) {
_this.$router.push({
path: "recommendItem", query: {
userId: item.UserId,
qo: JSON.stringify(_this.qo)
}
});
},
followUser(item) {
_this.$confirm('是否关注此用户?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
_this.loading = true;
// 添加节点
request({
url: '/nebula_operate/insertvertex/user_relation/tag_252150072',
method: 'post',
data: {
ob: {name: item.UserId},
vid: item.UserId
}
}).then(res => {
request({
url: '/nebula_operate/insertvertex/user_relation/tag_252150072',
method: 'post',
data: {
ob: {name: _this.$store.getters.name},
vid: _this.$store.getters.name
}
}).then(res => {
request({
url: '/nebula_operate/insertedgeline/user_relation/edge_768395026',
method: 'post',
data: {
dstId: item.UserId,
srcId: _this.$store.getters.name
}
}).then(res => {
_this.loading = false;
_this.$message.success("关注成功");
});
});
});
}).catch(() => {
});
},
}
}
</script>
<style lang="scss">
</style>

View File

@@ -0,0 +1,203 @@
<template>
<div style="height: 100%">
<div class="menu-title">
我的推荐
</div>
<div class="block_box">
<el-form :inline="true" class="demo-form-inline">
<el-form-item>
<el-select v-model="gorseQo.recommendation" @change="getRecommendItem">
<el-option :key="item.value" :value="item.value" :label="item.label"
v-for="item in recommendList"></el-option>
</el-select>
</el-form-item>
<el-form-item label="种类">
<el-select v-model="gorseQo.category" @change="getRecommendItem">
<el-option value="" label="无"></el-option>
<el-option :key="item.id" :value="item.name" :label="item.name"
v-for="item in categoryList"></el-option>
</el-select>
</el-form-item>
</el-form>
<div class="line-item-box" v-loading="loading">
<div class="line-item" v-for="item in list" :key="item.id">
<div class="title-time">
<div>{{ item.ItemId }}</div>
<div>{{ item.Timestamp }}</div>
</div>
<div class="description">{{ item.Comment }}</div>
<div class="labels">
<el-tag v-for="(la,index) in item.Labels" :key="index">{{ la }}</el-tag>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import request from '@/utils/request';
import {getFriends} from "@/api/user";
var _this;
export default {
name: "HotNews",
data() {
return {
qo: "",
gorseQo: {
userId: '',
n: 20,
recommendation: '_',
category: ''
},
user: {},
categoryList: [],
recommendList: [{
label: '默认推荐',
value: '_'
}, {
label: '基于物品推荐',
value: 'item_based'
}, {
label: '基于用户推荐',
value: 'user_based'
}],
list: [],
loading: false
}
},
mounted() {
_this = this;
_this.gorseQo.userId = _this.$store.getters.name;
_this.queryCategoryList();
_this.getRecommendItem();
},
methods: {
queryCategoryList() {
request({
url: '/category/query_list',
method: 'post',
data: {}
}).then(res => {
_this.categoryList = res.data;
});
},
getRecommendItem() {
_this.loading = true;
if (_this.gorseQo.recommendation === 'user_based') {
// 获取关注用户
let myId = this.$store.getters.name;
getFriends(myId).then(res => {
let recommendList = [];
let index = 0;
res.data.nodes.forEach(user => {
index++;
if (user.vid !== myId) {
request({
url: '/gorse/get_recommend_by_user',
method: 'post',
data: {
userId: user.vid,
n: 20,
recommendation: '_',
category: _this.gorseQo.category
}
}).then(rec => {
rec.data.forEach(row => {
row.labelsArr = row.labels ? row.labels.split(',') : [];
});
recommendList = recommendList.concat(rec.data);
if (index >= res.data.nodes.length) {
shuffle(recommendList);
_this.list = recommendList.slice(0, 20);
_this.loading = false;
}
});
}
});
});
} else {
request({
url: '/gorse/get_recommend_by_user',
method: 'post',
data: _this.gorseQo
}).then(res => {
res.data.forEach(row => {
row.labelsArr = row.labels ? row.labels.split(',') : [];
});
_this.list = res.data;
_this.loading = false;
});
}
},
}
}
// 数组乱序
function shuffle(array) {
array.sort(() => Math.random() - 0.5);
}
</script>
<style src="../../css/back.css" scoped></style>
<style scoped lang="scss">
.block_box {
margin: 25px 25px 0 25px;
background: #FFFFFF;
border-radius: 3px;
height: calc(100% - 120px);
.title {
border-bottom: 1px solid #ccc;
padding: 15px 25px;
}
}
.demo-form-inline {
padding: 25px 25px 0 25px;
}
.line-item-box {
height: calc(100% - 88px);
overflow-y: auto;
.line-item {
font-size: 14px;
line-height: 32px;
padding: 0 25px 10px 25px;
margin: 20px 0;
border-bottom: 1px solid #dee0e2;
.title-time {
display: flex;
div:first-child {
font-weight: bold;
font-size: 18px;
color: #9da2a8;
}
div:last-child {
margin-left: auto;
color: #bbbcbd;
}
}
.description {
color: #bbbcbd;
}
.labels {
color: #9da2a8;
.el-tag {
margin: 0 10px 10px 0;
}
}
}
}
</style>

View File

@@ -0,0 +1,99 @@
<template>
<div>
<div class="menu-title">
我的好友
</div>
<div class="menu-content">
<div>
<el-table :data="list" style="width: 100%" v-loading="loading">
<el-table-column type="index" label="行号" width="60"></el-table-column>
<el-table-column prop="vid" label="用户ID"></el-table-column>
<el-table-column prop="Labels" label="标签">
<div slot-scope="scope">
<template v-if="scope.row.Labels">
<template v-for="(tag,index) in scope.row.Labels">
<el-tag :key="index" v-if="index < 5">{{ tag }}</el-tag>
</template>
<el-tag v-if="scope.row.Labels.length > 5">...</el-tag>
</template>
</div>
</el-table-column>
<el-table-column label="操作" width="240">
<template slot-scope="scope">
<el-button @click.native.prevent="feedbackHistory(scope.row)" type="text" size="small">
Ta的喜欢
</el-button>
<el-button @click.native.prevent="similarUser(scope.row)" type="text" size="small">
相似用户
</el-button>
<el-button @click.native.prevent="recommendItem(scope.row)" type="text" size="small">
Ta的推荐
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
</div>
</template>
<script>
import request, {getBaseUrl} from '@/utils/request';
import {getFriends} from "@/api/user";
var _this;
export default {
name: "userManage",
data() {
return {
list: [],
loading: false,
}
},
mounted() {
_this = this;
_this.queryData();
},
methods: {
queryData() {
_this.list = [];
let myId = this.$store.getters.name;
getFriends(myId).then(res => {
let _list = res.data.nodes;
_list.forEach(item => {
if (item.vid !== myId) {
_this.list.push(item);
}
});
});
},
feedbackHistory(item) {
_this.$router.push({
path: "feedbackHistory", query: {
userId: item.UserId,
cursorArr: JSON.stringify(_this.cursorArr)
}
});
},
similarUser(item) {
_this.$router.push({
path: "similarUser", query: {
userId: item.UserId,
qo: JSON.stringify(_this.qo)
}
});
},
recommendItem(item) {
_this.$router.push({
path: "recommendItem", query: {
userId: item.UserId,
qo: JSON.stringify(_this.qo)
}
});
}
}
}
</script>
<style lang="scss">
</style>

View File

@@ -0,0 +1,141 @@
<template>
<div style="height: 100%">
<div class="menu-title">
我的喜欢
</div>
<div class="block_box">
<div class="line-item-box">
<div class="line-item" v-for="item in list" :key="item.id">
<div class="title-time">
<div>{{ item.ItemId }}</div>
<div>{{ item.Timestamp }}</div>
</div>
<div class="description">{{ item.Comment }}</div>
<div class="labels">
<el-tag v-for="(la,index) in item.Labels" :key="index">{{ la }}</el-tag>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import request from '@/utils/request';
import {getFriends} from "@/api/user";
var _this;
export default {
name: "MyStar",
data() {
return {
qo: "",
gorseQo: {
userId: '',
n: 20,
recommendation: '_',
category: ''
},
user: {},
list: []
}
},
mounted() {
_this = this;
_this.gorseQo.userId = _this.$store.getters.name;
_this.getRecommendItem();
},
methods: {
getRecommendItem() {
request({
url: '/gorse/get_feedback_list/' + _this.gorseQo.userId + "/like",
method: 'get'
}).then(res => {
res.data.forEach(row => {
row.Labels = row.Item.Labels;
row.ItemId = row.Item.ItemId;
row.Comment = row.Item.Comment;
if(_this.list.length < 20) {
_this.list.push(row);
}
});
});
request({
url: '/gorse/get_feedback_list/' + _this.gorseQo.userId + "/star",
method: 'get'
}).then(res => {
res.data.forEach(row => {
row.Labels = row.Item.Labels;
row.ItemId = row.Item.ItemId;
row.Comment = row.Item.Comment;
if(_this.list.length < 20) {
_this.list.push(row);
}
});
});
},
}
}
</script>
<style src="../../css/back.css" scoped></style>
<style scoped lang="scss">
.block_box {
margin: 25px 25px 0 25px;
background: #FFFFFF;
border-radius: 3px;
height: calc(100% - 120px);
.title {
border-bottom: 1px solid #ccc;
padding: 15px 25px;
}
}
.demo-form-inline {
padding: 25px 25px 0 25px;
}
.line-item-box {
height: calc(100% - 88px);
overflow-y: auto;
.line-item {
font-size: 14px;
line-height: 32px;
padding: 0 25px 10px 25px;
margin: 20px 0;
border-bottom: 1px solid #dee0e2;
.title-time {
display: flex;
div:first-child {
font-weight: bold;
font-size: 18px;
color: #9da2a8;
}
div:last-child {
margin-left: auto;
color: #bbbcbd;
}
}
.description {
color: #bbbcbd;
}
.labels {
color: #9da2a8;
.el-tag {
margin: 0 10px 10px 0;
}
}
}
}
</style>

View File

@@ -0,0 +1,157 @@
<template>
<div style="height: 100%">
<div class="menu-title">
Ta的喜欢{{ gorseQo.userId }}
<div class="icon icon-back" @click="backBtn">
<i title="返回"></i>
</div>
</div>
<div class="block_box">
<div class="line-item-box">
<div class="line-item" v-for="(item,index) in list" :key="index">
<div class="title-time">
<div>{{ item.ItemId }} <el-button @click.native.prevent="similarItem(item)" type="text" size="small">
相似条目
</el-button></div>
<div>{{ item.Timestamp }}</div>
</div>
<div class="description">{{ item.Comment }}</div>
<div class="labels">
<el-tag v-for="la in item.Labels">{{ la }}</el-tag>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import request from '@/utils/request';
var _this;
export default {
name: "RecommendItem",
data() {
return {
qo: "",
gorseQo: {
userId: '',
n: 10,
recommendation: '_',
category: ''
},
user: {},
list: []
}
},
mounted() {
_this = this;
_this.qo = _this.$route.query.qo;
_this.gorseQo.userId = _this.$route.query.userId;
_this.getFeedbackList();
},
methods: {
getFeedbackList() {
request({
url: '/gorse/get_feedback_list/' + _this.gorseQo.userId + "/like",
method: 'get'
}).then(res => {
res.data.forEach(row => {
row.Labels = row.Item.Labels;
row.ItemId = row.Item.ItemId;
row.Comment = row.Item.Comment;
if(_this.list.length < 20) {
_this.list.push(row);
}
});
});
request({
url: '/gorse/get_feedback_list/' + _this.gorseQo.userId + "/star",
method: 'get'
}).then(res => {
res.data.forEach(row => {
row.Labels = row.Item.Labels;
row.ItemId = row.Item.ItemId;
row.Comment = row.Item.Comment;
if(_this.list.length < 20) {
_this.list.push(row);
}
});
});
},
similarItem(item) {
_this.$router.push({
path: "similarItem", query: {
itemId: item.ItemId
}
});
},
backBtn() {
this.$router.go(-1);
},
}
}
</script>
<style src="../../../css/back.css" scoped></style>
<style scoped lang="scss">
.block_box {
margin: 25px 25px 0 25px;
background: #FFFFFF;
border-radius: 3px;
height: calc(100% - 120px);
.title {
border-bottom: 1px solid #ccc;
padding: 15px 25px;
}
}
.demo-form-inline {
padding: 25px 25px 0 25px;
}
.line-item-box {
height: calc(100% - 40px);
overflow-y: auto;
width: 100%;
.line-item {
font-size: 14px;
line-height: 32px;
padding: 0 25px 10px 25px;
margin: 20px 0;
border-bottom: 1px solid #dee0e2;
.title-time {
display: flex;
div:first-child {
font-weight: bold;
font-size: 18px;
color: #9da2a8;
}
div:last-child {
margin-left: auto;
color: #bbbcbd;
}
}
.description {
color: #bbbcbd;
}
.labels {
color: #9da2a8;
.el-tag {
margin: 0 10px 10px 0;
}
}
}
}
</style>

View File

@@ -0,0 +1,189 @@
<template>
<div style="height: 100%">
<div class="menu-title">
Ta的推荐{{ gorseQo.userId }}
<div class="icon icon-back" @click="backBtn">
<i title="返回"></i>
</div>
</div>
<div class="block_box">
<el-form :inline="true" class="demo-form-inline">
<el-form-item>
<el-select v-model="gorseQo.recommendation" @change="getRecommendItem">
<el-option :key="item.value" :value="item.value" :label="item.label"
v-for="item in recommendList"></el-option>
</el-select>
</el-form-item>
<el-form-item label="种类">
<el-select v-model="gorseQo.category" @change="getRecommendItem">
<el-option value="" label="无"></el-option>
<el-option :key="item.id" :value="item.name" :label="item.name"
v-for="item in categoryList"></el-option>
</el-select>
</el-form-item>
</el-form>
<div class="line-item-box">
<div class="line-item" v-for="item in list" :key="item.id">
<el-row>
<el-col :span="23">
<div class="title-time">
<div>{{ item.ItemId }} <el-button @click.native.prevent="similarItem(item)" type="text" size="small">
相似条目
</el-button></div>
<div>{{ item.Timestamp }}</div>
</div>
<div class="description">{{ item.Comment }}</div>
<div class="labels">
<el-tag v-for="(la,index) in item.Labels" :key="index">{{ la }}</el-tag>
</div>
</el-col>
<el-col :span="1" style="text-align: center;padding-top: 50px">
<i class="el-icon-star-off" @click="starItem(item)" style="font-size: 35px;cursor: pointer" title="喜欢"></i>
</el-col>
</el-row>
</div>
</div>
</div>
</div>
</template>
<script>
import request from '@/utils/request';
var _this;
export default {
name: "RecommendItem",
data() {
return {
qo: "",
gorseQo: {
userId: '',
n: 10,
recommendation: '_',
category: ''
},
user: {},
categoryList: [],
recommendList: [{
label: '默认推荐',
value: '_'
}, {
label: '基于物品推荐',
value: 'item_based'
}],
list: []
}
},
mounted() {
_this = this;
_this.qo = _this.$route.query.qo;
_this.gorseQo.userId = _this.$route.query.userId;
_this.queryCategoryList();
_this.getRecommendItem();
},
methods: {
queryCategoryList() {
request({
url: '/category/query_list',
method: 'post',
data: {}
}).then(res => {
_this.categoryList = res.data;
});
},
similarItem(item) {
_this.$router.push({
path: "similarItem", query: {
itemId: item.ItemId
}
});
},
getRecommendItem() {
request({
url: '/gorse/get_recommend_by_user',
method: 'post',
data: _this.gorseQo
}).then(res => {
res.data.forEach(row => {
row.labelsArr = row.labels ? row.labels.split(',') : [];
});
_this.list = res.data;
});
},
starItem(item) {
request({
url: `/gorse/insert_feedback/star/${this.$store.getters.name}/${item.ItemId}`,
method: 'post',
data: {}
}).then(res => {
this.$message.success("收藏成功")
});
},
backBtn() {
this.$router.go(-1);
},
}
}
</script>
<style src="../../../css/back.css" scoped></style>
<style scoped lang="scss">
.block_box {
margin: 25px 25px 0 25px;
background: #FFFFFF;
border-radius: 3px;
height: calc(100% - 120px);
.title {
border-bottom: 1px solid #ccc;
padding: 15px 25px;
}
}
.demo-form-inline {
padding: 25px 25px 0 25px;
}
.line-item-box {
height: calc(100% - 88px);
overflow-y: auto;
.line-item {
font-size: 14px;
line-height: 32px;
padding: 0 25px 10px 25px;
margin: 20px 0;
border-bottom: 1px solid #dee0e2;
.title-time {
display: flex;
div:first-child {
font-weight: bold;
font-size: 18px;
color: #9da2a8;
}
div:last-child {
margin-left: auto;
color: #bbbcbd;
}
}
.description {
color: #bbbcbd;
}
.labels {
color: #9da2a8;
.el-tag {
margin: 0 10px 10px 0;
}
}
}
}
</style>

View File

@@ -0,0 +1,170 @@
<template>
<div class="similar-item-box">
<div class="menu-title">
相似推荐{{ gorseQo.itemId }}
<div class="icon icon-back" @click="backBtn">
<i title="返回"></i>
</div>
</div>
<div class="block_box" style="margin-top: 20px">
<div class="title">信息</div>
<div>
<el-form label-width="50px">
<el-form-item label="时间">{{ item.Timestamp }}</el-form-item>
<el-form-item label="类别">
<template v-for="(tag,index) in item.Categories">
<el-tag :key="index">{{ tag }}</el-tag>
</template>
</el-form-item>
<el-form-item label="标签">
<template v-for="(tag,index) in item.Labels">
<el-tag :key="index">{{ tag }}</el-tag>
</template>
</el-form-item>
<el-form-item label="描述">
{{ item.Comment }}
</el-form-item>
</el-form>
</div>
</div>
<div class="block_box">
<div class="title">Related Items</div>
<el-form :inline="true" class="demo-form-inline">
<el-form-item label="categories">
<el-select v-model="gorseQo.category" @change="getSimilarItem">
<el-option value="" label="无"></el-option>
<el-option :key="item.id" :value="item.name" :label="item.name"
v-for="item in categoryList"></el-option>
</el-select>
</el-form-item>
</el-form>
<div style="padding-top: 0">
<el-table :data="list" style="width: 100%">
<el-table-column type="index" label="行号" width="60"></el-table-column>
<el-table-column prop="ItemId" label="fid"></el-table-column>
<el-table-column prop="labels" label="类别">
<div slot-scope="scope">
<template v-if="scope.row.Categories">
<template v-for="(tag,index) in scope.row.Categories">
<el-tag :key="index" v-if="index < 5">{{ tag }}</el-tag>
</template>
<el-tag v-if="scope.row.Categories.length > 5">...</el-tag>
</template>
</div>
</el-table-column>
<el-table-column prop="labels" label="标签">
<div slot-scope="scope">
<template v-if="scope.row.Labels">
<template v-for="(tag,index) in scope.row.Labels">
<el-tag :key="index" v-if="index < 10">{{ tag }}</el-tag>
</template>
<el-tag v-if="scope.row.Labels.length > 10">...</el-tag>
</template>
</div>
</el-table-column>
<el-table-column prop="Comment" label="描述">
<template slot-scope="scope" v-if="scope.row.Comment">
{{ scope.row.Comment.substring(0, 100) }}
</template>
</el-table-column>
<el-table-column prop="Score" label="相似度 [0, 1]" width="100">
<template slot-scope="scope">
{{ scope.row.Score.toFixed(5) }}
</template>
</el-table-column>
<el-table-column prop="Timestamp" label="创建时间" width="200"></el-table-column>
</el-table>
</div>
</div>
</div>
</template>
<script>
import request from '@/utils/request';
var _this;
export default {
name: "similarItem",
data() {
return {
qo: "",
gorseQo: {
itemId: '',
category: '',
n: 10
},
item: {},
list: [],
categoryList: []
}
},
mounted() {
_this = this;
_this.qo = _this.$route.query.qo;
_this.gorseQo.itemId = _this.$route.query.itemId;
_this.queryCategoryList();
_this.queryItem();
_this.getSimilarItem();
},
methods: {
queryCategoryList() {
request({
url: '/category/query_list',
method: 'post',
data: {}
}).then(res => {
_this.categoryList = res.data;
});
},
queryItem() {
request({
url: '/gorse/get_item/' + _this.gorseQo.itemId,
method: 'get',
}).then(res => {
_this.item = res.data;
});
},
getSimilarItem() {
request({
url: '/gorse/get_similar_item',
method: 'post',
data: _this.gorseQo
}).then(res => {
_this.list = res.data;
});
},
backBtn() {
this.$router.go(-1);
},
}
}
</script>
<style src="../../../css/back.css" scoped></style>
<style scoped lang="scss">
.similar-item-box {
height: 100%;
overflow-y: auto;
}
.block_box {
margin: 25px;
background: #FFFFFF;
border-radius: 3px;
.title {
border-bottom: 1px solid #ccc;
padding: 15px 25px;
}
> div {
padding: 25px;
}
}
.demo-form-inline {
padding: 25px 25px 0 25px;
}
</style>

View File

@@ -0,0 +1,228 @@
<template>
<div>
<div class="menu-title">
导入用户
<div class="icon icon-back" @click="backBtn">
<i title="返回"></i>
</div>
</div>
<div class="block_box" style="margin-top: 20px;padding: 20px">
<el-form ref="cmd" label-width="100px" :rules="rules" :model="cmd" :inline="true">
<el-form-item label="文件" prop="file">
<el-upload
class="upload-demo"
action="#"
:auto-upload="false"
accept=".csv"
:on-change="handleFileChange"
:limit="1"
:show-file-list="false">
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">只能上传csv文件</div>
</el-upload>
</el-form-item>
<br/>
<el-form-item label="字段分隔符" prop="field">
<el-input v-model="cmd.field" placeholder="请输入字段分隔符" style="width: 300px"
@change="handleFieldChange"></el-input>
</el-form-item>
<el-form-item label="类别分隔符" prop="categories">
<el-input v-model="cmd.categories" placeholder="请输入类别分隔符" style="width: 300px"></el-input>
</el-form-item>
<br/>
<el-form-item label="唯一ID" prop="id">
<el-select v-model="cmd.id" style="width: 300px" @change="refreshList">
<template v-if="cmd.ifFirstHead">
<el-option :value="index" :label="item" v-for="(item,index) in columnList" :key="index"></el-option>
</template>
<template v-if="!cmd.ifFirstHead">
<el-option :value="index" :label="index" v-for="(item,index) in columnList" :key="index"></el-option>
</template>
</el-select>
</el-form-item>
<el-form-item label="标签" prop="labels">
<el-select v-model="cmd.labels" style="width: 300px" @change="refreshList">
<template v-if="cmd.ifFirstHead">
<el-option :value="index" :label="item" v-for="(item,index) in columnList" :key="index"></el-option>
</template>
<template v-if="!cmd.ifFirstHead">
<el-option :value="index" :label="index" v-for="(item,index) in columnList" :key="index"></el-option>
</template>
</el-select>
</el-form-item>
<br/>
<el-form-item label=" ">
<el-checkbox label="第一行为表头" v-model="cmd.ifFirstHead" @change="refreshList"></el-checkbox>
</el-form-item>
</el-form>
<el-table :data="list" style="width: 100%" height="400" v-show="list.length > 0">
<el-table-column type="index" label="行号" width="60"></el-table-column>
<el-table-column prop="id" :label="'ID('+(cmd.ifFirstHead ? columnList[cmd.id] : cmd.id)+')'"></el-table-column>
<el-table-column prop="labels" :label="'标签('+(cmd.ifFirstHead ? columnList[cmd.labels] : cmd.labels)+')'">
<template v-slot="scope">
<label style="color: red" v-if="scope.row.errorFlag">JSON格式化异常</label>
<label v-if="!scope.row.errorFlag">{{ scope.row.labels }}</label>
</template>
</el-table-column>
</el-table>
<el-button type="primary" class="submit-btn" @click="confirmSubmit" :disabled="list.length === 0">确认提交</el-button>
</div>
</div>
</template>
<script>
import request from '@/utils/request';
var _this;
export default {
name: "ImportUser",
data() {
return {
cmd: {
field: ',',
categories: '|',
id: '',
labels: '',
ifFirstHead: true
},
file: [],
originList: [], // 原始的可能包含表头的数据默认存储最多21行如果数据不止21行的话
list: [], // 页面table显示的数据
columnList: [],// 上传csv的表头
rules: {
fid: [
{required: true, message: '请选择文件'}
],
field: [
{required: true, message: '字段分隔符不能为空'}
],
categories: [
{required: true, message: '类别分隔符不能为空'}
],
},
}
},
mounted() {
_this = this;
},
methods: {
handleFileChange(file, fileList) {
_this.file = file.raw;
if(_this.cmd.field.length > 0) {
_this.handleFieldChange();
}
},
handleFieldChange() {
this.$papa.parse(_this.file, {
delimiter: _this.cmd.field,
complete: (results) => {
_this.originList = results.data.slice(0, 21);
// 提前填充一个默认的值给对应的ID列和标签列
_this.prepareFieldAndLabels();
_this.refreshList();
}
})
},
prepareFieldAndLabels() {
_this.columnList = _this.originList[0];
_this.cmd.id = 0;
_this.cmd.labels = 1;
},
refreshList() {
// 处理原始数据将行文本截取成数组放入list
_this.list = [];
if (_this.cmd.field.length === 0) {
return;
}
for (let i in _this.originList) {
if (_this.cmd.ifFirstHead && i == 0) {
// 第一行是表头跳过list塞入
continue;
}
let row = _this.originList[i];
let errorFlag = false;
try {
JSON.parse(row[_this.cmd.labels]);
} catch (e) {
errorFlag = true;
}
_this.list.push({
id: row[_this.cmd.id],
labels: row[_this.cmd.labels],
errorFlag: errorFlag
});
}
},
confirmSubmit() { // 提交确认
this.$refs.cmd.validate((valid) => {
let formData = new FormData();
formData.append("sep", _this.cmd.field);
formData.append("has-header", _this.cmd.ifFirstHead);
formData.append("label-sep", _this.cmd.categories);
formData.append("file", _this.file);
let idIndex = _this.cmd.id;
let labelIndex = _this.cmd.labels;
let _format = '';
for (let i = 0; i <= Math.max(idIndex, labelIndex); i++) {
if (i == idIndex) {
_format += "u";
} else if (i == labelIndex) {
_format += "l";
} else {
_format += "_";
}
}
formData.append("format", _format);
request({
url: '/gorse/bulk/users',
method: 'put',
data: formData
}).then(res => {
if(res.data && res.data.RowAffected) {
_this.$message.success(`成功导入${res.data.RowAffected}条记录`);
} else {
_this.$message.warning("导入异常");
}
});
});
},
backBtn() {
this.$router.push({
path: "userManage", query: {
qo: JSON.stringify({
pageNo: 1,
pageSize: 10,
LIKES_fid: '',
})
}
});
},
}
}
</script>
<style src="../../../css/back.css" scoped></style>
<style scoped lang="scss">
.block_box {
margin: 25px;
background: #FFFFFF;
border-radius: 3px;
.title {
border-bottom: 1px solid #ccc;
padding: 15px 25px;
}
> div {
padding: 25px;
}
.submit-btn {
margin-left: auto;
margin-top: 20px;
display: flex;
}
}
</style>

View File

@@ -0,0 +1,118 @@
<template>
<div>
<div class="menu-title">
Ta的好友{{ userId }}
<div class="icon icon-back" @click="backBtn">
<i title="返回"></i>
</div>
</div>
<div class="block_box" style="margin-top: 10px">
<div class="title">信息</div>
<div>
<el-form label-width="100px">
<el-form-item label="标签">
<template v-for="(tag,index) in user.labelsArr">
<el-tag :key="index">{{ tag }}</el-tag>
</template>
</el-form-item>
</el-form>
</div>
</div>
<div class="block_box">
<div class="title">Association Items</div>
<div>
<el-table :data="list" style="width: 100%">
<el-table-column type="index" label="行号" width="60"></el-table-column>
<el-table-column prop="vid" label="UserId"></el-table-column>
<el-table-column label="操作" width="210">
<template slot-scope="scope">
<el-button @click.native.prevent="recommendItem(scope.row)" type="text" size="small">
查看推荐
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
</div>
</template>
<script>
import request from '@/utils/request';
var _this;
export default {
name: "linkUser",
data() {
return {
qo: "",
userId: '',
user: {},
list: []
}
},
mounted() {
_this = this;
_this.qo = _this.$route.query.qo;
_this.userId = _this.$route.query.userId;
_this.queryUser();
_this.getLinkUser();
},
methods: {
queryUser() {
request({
url: '/risk-user/query_unique',
method: 'post',
data: {
EQS_fid: _this.userId
}
}).then(res => {
res.data.labelsArr = res.data.labels ? res.data.labels.split(',') : [];
_this.user = res.data;
});
},
getLinkUser() {
let space = 'user_relation';
request({
url: `/nebula_operate/findonepathbyidwithrelation/${space}/${_this.userId}`,
method: 'post',
data: {
relations: ['edge_768395026']
}
}).then(res => {
_this.list = res.data.nodes;
});
},
recommendItem(item) {
_this.$router.push({
path: "recommendItem", query: {
userId: item.vid,
qo: JSON.stringify(_this.qo)
}
});
},
backBtn() {
this.$router.go(-1);
},
}
}
</script>
<style src="../../../css/back.css" scoped></style>
<style scoped lang="scss">
.block_box {
margin: 25px;
background: #FFFFFF;
border-radius: 3px;
.title {
border-bottom: 1px solid #ccc;
padding: 15px 25px;
}
>div {
padding: 25px;
}
}
</style>

View File

@@ -0,0 +1,133 @@
<template>
<div>
<div class="menu-title">
相似用户{{ userId }}
<div class="icon icon-back" @click="backBtn">
<i title="返回"></i>
</div>
</div>
<div class="block_box" style="margin-top: 20px">
<div class="title">信息</div>
<div>
<el-form label-width="100px">
<el-form-item label="标签">
<template v-for="(tag,index) in user.labelsArr">
<el-tag :key="index">{{ tag }}</el-tag>
</template>
</el-form-item>
</el-form>
</div>
</div>
<div class="block_box">
<div class="title">Related Items</div>
<div>
<el-table :data="list" style="width: 100%">
<el-table-column type="index" label="行号" width="60"></el-table-column>
<el-table-column prop="UserId" label="UserId"></el-table-column>
<el-table-column prop="labels" label="标签">
<div slot-scope="scope">
<template v-for="(tag,index) in scope.row.labelsArr">
<el-tag :key="index" v-if="index < 5">{{ tag }}</el-tag>
</template>
<el-tag v-if="scope.row.labelsArr.length > 5">...</el-tag>
</div>
</el-table-column>
<el-table-column prop="Score" label="相似度 [0, 1]">
<template slot-scope="scope">
{{scope.row.Score.toFixed(5)}}
</template>
</el-table-column>
<el-table-column label="操作" width="210">
<template slot-scope="scope">
<el-button @click.native.prevent="recommendItem(scope.row)" type="text" size="small">
查看推荐
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
</div>
</template>
<script>
import request from '@/utils/request';
var _this;
export default {
name: "similarUser",
data() {
return {
qo: "",
userId: '',
user: {},
list: []
}
},
mounted() {
_this = this;
_this.qo = _this.$route.query.qo;
_this.userId = _this.$route.query.userId;
_this.queryUser();
_this.getSimilarUser();
},
methods: {
queryUser() {
request({
url: '/risk-user/query_unique',
method: 'post',
data: {
EQS_fid: _this.userId
}
}).then(res => {
res.data.labelsArr = res.data.labels ? res.data.labels.split(',') : [];
_this.user = res.data;
});
},
getSimilarUser() {
request({
url: '/gorse/get_similar_user',
method: 'post',
data: {
userId: _this.userId
}
}).then(res => {
res.data.forEach(row => {
row.labelsArr = row.labels ? row.labels.split(',') : [];
});
_this.list = res.data;
});
},
recommendItem(item) {
_this.$router.push({
path: "recommendItem", query: {
userId: item.UserId,
qo: JSON.stringify(_this.qo)
}
});
},
backBtn() {
this.$router.go(-1);
},
}
}
</script>
<style src="../../../css/back.css" scoped></style>
<style scoped lang="scss">
.block_box {
margin: 25px;
background: #FFFFFF;
border-radius: 3px;
.title {
border-bottom: 1px solid #ccc;
padding: 15px 25px;
}
>div {
padding: 25px;
}
}
</style>

30
web_home/src/css/back.css Normal file
View File

@@ -0,0 +1,30 @@
div.icon {
display: inline-block;
cursor: pointer;
height: 50px;
background-color: #fff;
border-radius: 2.08333vw;
float: right;
width: 50px;
text-align: center;
line-height: 50px;
margin-right: 80px;
margin-top: 9px;
padding: 0;
}
div.icon i {
width: 25px;
height: 25px;
margin: auto;
display: inline-block;
vertical-align: sub;
}
.icon-back {
box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
}
.icon-back i {
background: url("../assets/image/icon/fanhui.png") no-repeat center/contain;
}

43
web_home/src/main.js Normal file
View File

@@ -0,0 +1,43 @@
import Vue from 'vue'
import App from './App.vue'
import 'normalize.css/normalize.css'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import 'element-ui/lib/theme-chalk/icon.css'
import VueQuillEditor from 'vue-quill-editor'
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
import store from './store'
import router from './router'
// 引入echarts
import * as echarts from 'echarts'
import {getToken, setToken, removeToken} from '@/utils/auth'
import '@/permission'
import '@antv/x6-vue-shape'
import VuePapaParse from 'vue-papa-parse'
Vue.prototype.$echarts = echarts;
Vue.use(ElementUI);
Vue.use(VueQuillEditor);
Vue.use(VuePapaParse);
Vue.config.productionTip = false;
new Vue({
el: '#app',
router,
store,
render: h => h(App)
})

View File

@@ -0,0 +1,36 @@
import router from './router'
import { getToken } from '@/utils/auth' // get token from cookie
import getPageTitle from '@/utils/get-page-title'
const whiteList = ['/', '/login','/register'] // no redirect whitelist
router.beforeEach(async(to, from, next) => {
// set page title
document.title = getPageTitle(to.meta.title)
// determine whether the user has logged in
const hasToken = getToken()
if (hasToken) {
// if (to.path === '/login') {
// // if is logged in, redirect to the home page
// next({ path: '/' })
// } else {
next()
// }
} else {
/* has no token*/
if (whiteList.indexOf(to.path) !== -1) {
// in the free login whitelist, go directly
next()
} else {
// other pages that do not have permission to access are redirected to the login page.
next(`/login`)
}
}
})
// router.afterEach(() => {
// // finish progress bar
// })

View File

@@ -0,0 +1,77 @@
import Vue from 'vue'
import Router from 'vue-router'
const originalPush = Router.prototype.push;
Router.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => err);
}
Vue.use(Router)
export default new Router({
routes: [
{
path: '/404',
component: () => import('@/views/404')
},
{
path: '/',
component: () => import('@/views/Index'),
children: [
{
path: 'myFriends',
component: () => import('@/components/menus/MyFriends')
},
{
path: 'myStar',
component: () => import('@/components/menus/MyStar')
},
{
path: 'allUsers',
component: () => import('@/components/menus/AllUsers')
},
{
path: 'hotNews',
component: () => import('@/components/menus/HotNews')
},
{
path: 'similarUser',
component: () => import('@/components/menus/user/SimilarUser')
},
{
path: 'linkUser',
component: () => import('@/components/menus/user/LinkUser')
},
{
path: 'recommendItem',
component: () => import('@/components/menus/item/RecommendItem')
},
{
path: 'feedbackHistory',
component: () => import('@/components/menus/item/FeedbackHistory')
},
{
path: 'similarItem',
component: () => import('@/components/menus/item/SimilarItem')
},
{
path: '/',
redirect: "myFriends"
},
]
},
{
path: '/login',
name: 'Login',
component: () => import('@/views/Login'),
},
{
path: '/register',
name: 'Register',
component: () => import('@/views/Register'),
},
{path: '*', redirect: '/404'}
],
mode: "hash"
})

4
web_home/src/settings.js Normal file
View File

@@ -0,0 +1,4 @@
module.exports = {
title: '推荐系统-演示'
}

View File

@@ -0,0 +1,8 @@
const getters = {
sidebar: state => state.app.sidebar,
device: state => state.app.device,
token: state => state.user.token,
avatar: state => state.user.avatar,
name: state => state.user.name
}
export default getters

View File

@@ -0,0 +1,19 @@
import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
import app from './modules/app'
import settings from './modules/settings'
import user from './modules/user'
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
app,
settings,
user
},
getters
})
export default store

View File

@@ -0,0 +1,48 @@
import Cookies from 'js-cookie'
const state = {
sidebar: {
opened: Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true,
withoutAnimation: false
},
device: 'desktop'
}
const mutations = {
TOGGLE_SIDEBAR: state => {
state.sidebar.opened = !state.sidebar.opened
state.sidebar.withoutAnimation = false
if (state.sidebar.opened) {
Cookies.set('sidebarStatus', 1)
} else {
Cookies.set('sidebarStatus', 0)
}
},
CLOSE_SIDEBAR: (state, withoutAnimation) => {
Cookies.set('sidebarStatus', 0)
state.sidebar.opened = false
state.sidebar.withoutAnimation = withoutAnimation
},
TOGGLE_DEVICE: (state, device) => {
state.device = device
}
}
const actions = {
toggleSideBar({ commit }) {
commit('TOGGLE_SIDEBAR')
},
closeSideBar({ commit }, { withoutAnimation }) {
commit('CLOSE_SIDEBAR', withoutAnimation)
},
toggleDevice({ commit }, device) {
commit('TOGGLE_DEVICE', device)
}
}
export default {
namespaced: true,
state,
mutations,
actions
}

View File

@@ -0,0 +1,32 @@
import defaultSettings from '@/settings'
const { showSettings, fixedHeader, sidebarLogo } = defaultSettings
const state = {
showSettings: showSettings,
fixedHeader: fixedHeader,
sidebarLogo: sidebarLogo
}
const mutations = {
CHANGE_SETTING: (state, { key, value }) => {
// eslint-disable-next-line no-prototype-builtins
if (state.hasOwnProperty(key)) {
state[key] = value
}
}
}
const actions = {
changeSetting({ commit }, data) {
commit('CHANGE_SETTING', data)
}
}
export default {
namespaced: true,
state,
mutations,
actions
}

View File

@@ -0,0 +1,94 @@
import {login, loginUser, getInfoAdmin, logout, getInfo} from '@/api/user'
import {getToken, setToken, removeToken, getName, setName} from '@/utils/auth'
import {resetRouter} from '@/router'
const getDefaultState = () => {
return {
token: getToken(),
name: getName(),
avatar: ''
}
}
const state = getDefaultState()
const mutations = {
RESET_STATE: (state) => {
Object.assign(state, getDefaultState())
},
SET_TOKEN: (state, token) => {
state.token = token
},
SET_NAME: (state, name) => {
state.name = name;
},
SET_AVATAR: (state, avatar) => {
state.avatar = avatar
}
}
const actions = {
// user login
login({commit}, userInfo) {
const {username, password, type} = userInfo;
return new Promise((resolve, reject) => {
login({username: username.trim(), password: password, type: type}).then(response => {
const res = response;
commit('SET_TOKEN', res.data.Authorization);
setToken(res.data.Authorization);
setName(res.data.user.realname);
resolve(res)
}).catch(error => {
reject(error)
})
})
},
getInfoAdmin({commit, state}) {
// return false;
return new Promise((resolve, reject) => {
getInfoAdmin().then(response => {
const {data} = response
if (!data) {
return reject('权限异常,请重新登录!')
}
commit('SET_NAME', data.realname)
resolve(data)
}).catch(error => {
reject(error)
})
})
},
// user logout
logout({commit, state}) {
return new Promise((resolve, reject) => {
// logout(state.token).then(() => {
removeToken() // must remove token first
commit('RESET_STATE')
resolve()
// }).catch(error => {
// reject(error)
// })
})
},
// remove token
resetToken({commit}) {
return new Promise(resolve => {
removeToken() // must remove token first
commit('RESET_STATE')
resolve()
})
}
}
export default {
namespaced: true,
state,
mutations,
actions
}

View File

@@ -0,0 +1,21 @@
const TokenKey = 'recom_gorse_admin_web_token'
export function getToken() {
return localStorage.getItem(TokenKey)
}
export function setToken(token) {
return localStorage.setItem(TokenKey, token)
}
export function removeToken() {
return localStorage.removeItem(TokenKey)
}
export function getName() {
return localStorage.getItem(TokenKey + "_name")
}
export function setName(name) {
return localStorage.setItem(TokenKey + "_name", name)
}

View File

@@ -0,0 +1,115 @@
/**
* 包含parentId的数组转成树形结构数组
* @param data 原始数据数组
* @param idName ID属性名称
* @param parentIdName 父ID属性名称
* @returns {[]}
*/
const listToTree = function (data, idName, parentIdName) {
if (!idName) {
idName = 'id';
}
if (!parentIdName) {
parentIdName = 'parentId';
}
// * 先生成parent建立父子关系
const obj = {};
data.forEach((item) => {
obj[item[idName]] = item;
});
const parentList = [];
data.forEach((item) => {
// item.hasChildren = false;
const parent = obj[item[parentIdName]];
if (parent) {
// * 当前项有父节点
parent.children = parent.children || [];
parent.children.push(item);
// parent.hasChildren = true;
} else {
// * 当前项没有父节点 -> 顶层
parentList.push(item);
}
});
return parentList;
}
/**
* 三元组转换成树形结构
* @param nodes 节点数组
* @param relations 关系数据
* @param idName 节点ID属性名称
* @param sourceName 关系起始节点ID属性名称
* @param targetName 关系终止节点ID属性名称
* @returns {[]}
*/
const tripletToTree = function ({nodes, relations, idName, sourceName, targetName}) {
idName = idName ? idName : 'id';
sourceName = sourceName ? sourceName : 'sourceId';
targetName = targetName ? targetName : 'targetId';
// * 先生成parent建立父子关系
const nodeObj = {};
nodes.forEach((item) => {
nodeObj[item[idName]] = item;
});
const parentList = [];
relations.forEach((item) => {
// item.hasChildren = false;
const parent = nodeObj[item[sourceName]];
const child = nodeObj[item[targetName]];
if (parent && child) {
child.isChild = true;
parent.children = parent.children || [];
parent.children.push(nodeObj[item[targetName]]);
}
// parent.hasChildren = true;
});
Reflect.ownKeys(nodeObj).forEach(key => {
if (!nodeObj[key].isChild) {
parentList.push(nodeObj[key]);
}
});
return parentList;
}
/**
* 优先获取name无则获取对象的第一个可用值
* @param param
* @returns {string}
*/
const getFirstStringProperty = function (param) {
if (param.constructor == Array) {
if (param.length > 0) {
return getFirstStringProperty(param[0]);
}
} else if (param.constructor == Object) {
if (param["name"]) {
return getFirstStringProperty(param["name"]);
} else if (Object.keys(param).length > 0) {
return getFirstStringProperty(param[Object.keys(param)[0]]);
}
} else {
return param.toString();
}
return '';
}
//格式化时间
function formatTime(dat) {
//获取年月日,时间
var year = dat.getFullYear();
var mon = (dat.getMonth() + 1) < 10 ? "0" + (dat.getMonth() + 1) : dat.getMonth() + 1;
var data = dat.getDate() < 10 ? "0" + (dat.getDate()) : dat.getDate();
var hour = dat.getHours() < 10 ? "0" + (dat.getHours()) : dat.getHours();
var min = dat.getMinutes() < 10 ? "0" + (dat.getMinutes()) : dat.getMinutes();
var seon = dat.getSeconds() < 10 ? "0" + (dat.getSeconds()) : dat.getSeconds();
var newDate = year + "-" + mon + "-" + data + " " + hour + ":" + min + ":" + seon;
return newDate;
}
export {listToTree, tripletToTree, getFirstStringProperty, formatTime};

View File

@@ -0,0 +1,10 @@
import defaultSettings from '@/settings'
const title = defaultSettings.title || 'Vue Admin Template'
export default function getPageTitle(pageTitle) {
if (pageTitle) {
return `${pageTitle} - ${title}`
}
return `${title}`
}

View File

@@ -0,0 +1,32 @@
const menuList = [
{
index: "0",
icon: "el-icon-user-solid",
name: "我的好友",
url: "/myFriends"
},
{
index: "1",
icon: "el-icon-user",
name: "全部用户",
url: "/allUsers"
},
{
index: "2",
icon: "el-icon-star-off",
name: "我的喜欢",
url: "/myStar"
},
{
index: "3",
icon: "el-icon-sugar",
name: "我的推荐",
url: "/hotNews"
},
];
/*返回当前菜单列表*/
export function getMenuList() {
return menuList;
}

View File

@@ -0,0 +1,88 @@
import axios from 'axios'
import {MessageBox, Message} from 'element-ui'
import store from '@/store'
import {getToken} from '@/utils/auth'
// var _baseURL = "http://localhost:4026";
var _baseURL = "http://139.9.106.207:4026";
var _fileURL = "http://139.9.106.207:4026/web/";
// create an axios instance
const service = axios.create({
baseURL: _baseURL, // url = base url + request url
// withCredentials: true, // send cookies when cross-domain requests
timeout: 1000000 // request timeout
});
// request interceptor
service.interceptors.request.use(
config => {
// do something before request is sent
if (store.getters.token) {
// let each request carry token
// ['X-Token'] is a custom headers key
// please modify it according to the actual situation
config.headers['Authorization'] = getToken()
}
return config
},
error => {
// do something with request error
return Promise.reject(error)
}
)
// response interceptor
service.interceptors.response.use(
/**
* If you want to get http information such as headers or status
* Please return response => response
*/
/**
* Determine the request status by custom code
* Here is just an example
* You can also judge the status by HTTP Status Code
*/
response => {
const res = response.data
// if the custom code is not 20000, it is judged as an error.
if (res.code !== "SUCCESS") {
Message({
message: res.msg || res.data.msg || '系统错误',
type: 'error',
duration: 5 * 1000
})
if (res.code == "UNAUTHORIZED") {
store.dispatch('user/resetToken').then(() => {
location.reload()
})
}
return Promise.reject(new Error(res.message || 'Error'))
} else {
return res
}
},
error => {
Message({
message: error.message,
type: 'error',
duration: 5 * 1000
})
return Promise.reject(error)
}
)
export default service;
// return url prefix
export function getBaseUrl() {
return _baseURL;
}
export function getFileUrl() {
return _fileURL;
}

224
web_home/src/views/404.vue Normal file
View File

@@ -0,0 +1,224 @@
<template>
<div class="wscn-http404-container">
<div class="wscn-http404">
<div class="pic-404">
<img class="pic-404__parent" src="@/assets/404_images/404.png" alt="404">
<img class="pic-404__child left" src="@/assets/404_images/404_cloud.png" alt="404">
<img class="pic-404__child mid" src="@/assets/404_images/404_cloud.png" alt="404">
<img class="pic-404__child right" src="@/assets/404_images/404_cloud.png" alt="404">
</div>
<div class="bullshit">
<div class="bullshit__oops">您访问的页面不存在!</div>
<div class="bullshit__info">请检查网页路径是否正确或点击下方按钮返回主页</div>
<a href="/" class="bullshit__return-home">返回主页</a>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Page404',
computed: {
message() {
return 'The webmaster said that you can not enter this page...'
}
}
}
</script>
<style lang="scss" scoped>
.wscn-http404-container{
transform: translate(-50%,-50%);
position: absolute;
top: 40%;
left: 50%;
}
.wscn-http404 {
position: relative;
width: 1200px;
padding: 0 50px;
overflow: hidden;
.pic-404 {
position: relative;
float: left;
width: 600px;
overflow: hidden;
&__parent {
width: 100%;
}
&__child {
position: absolute;
&.left {
width: 80px;
top: 17px;
left: 220px;
opacity: 0;
animation-name: cloudLeft;
animation-duration: 2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
animation-delay: 1s;
}
&.mid {
width: 46px;
top: 10px;
left: 420px;
opacity: 0;
animation-name: cloudMid;
animation-duration: 2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
animation-delay: 1.2s;
}
&.right {
width: 62px;
top: 100px;
left: 500px;
opacity: 0;
animation-name: cloudRight;
animation-duration: 2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
animation-delay: 1s;
}
@keyframes cloudLeft {
0% {
top: 17px;
left: 220px;
opacity: 0;
}
20% {
top: 33px;
left: 188px;
opacity: 1;
}
80% {
top: 81px;
left: 92px;
opacity: 1;
}
100% {
top: 97px;
left: 60px;
opacity: 0;
}
}
@keyframes cloudMid {
0% {
top: 10px;
left: 420px;
opacity: 0;
}
20% {
top: 40px;
left: 360px;
opacity: 1;
}
70% {
top: 130px;
left: 180px;
opacity: 1;
}
100% {
top: 160px;
left: 120px;
opacity: 0;
}
}
@keyframes cloudRight {
0% {
top: 100px;
left: 500px;
opacity: 0;
}
20% {
top: 120px;
left: 460px;
opacity: 1;
}
80% {
top: 180px;
left: 340px;
opacity: 1;
}
100% {
top: 200px;
left: 300px;
opacity: 0;
}
}
}
}
.bullshit {
position: relative;
float: left;
width: 300px;
padding: 30px 0;
overflow: hidden;
&__oops {
font-size: 32px;
font-weight: bold;
line-height: 40px;
color: #1482f0;
opacity: 0;
margin-bottom: 20px;
animation-name: slideUp;
animation-duration: 0.5s;
animation-fill-mode: forwards;
}
&__headline {
font-size: 20px;
line-height: 24px;
color: #222;
font-weight: bold;
opacity: 0;
margin-bottom: 10px;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.1s;
animation-fill-mode: forwards;
}
&__info {
font-size: 13px;
line-height: 21px;
color: grey;
opacity: 0;
margin-bottom: 30px;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.2s;
animation-fill-mode: forwards;
}
&__return-home {
display: block;
float: left;
width: 110px;
height: 36px;
background: #1482f0;
border-radius: 100px;
text-align: center;
color: #ffffff;
opacity: 0;
font-size: 14px;
line-height: 36px;
cursor: pointer;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.3s;
animation-fill-mode: forwards;
}
@keyframes slideUp {
0% {
transform: translateY(60px);
opacity: 0;
}
100% {
transform: translateY(0);
opacity: 1;
}
}
}
}
</style>

View File

@@ -0,0 +1,406 @@
<template>
<div id="menuBox">
<div class="menu-box">
<div class="content-title">
<img src="../assets/image/content-logo.png" class="content-logo">
<div class="first-title">{{ title }}</div>
<div class="user-name">欢迎您{{ $store.getters.name }}</div>
</div>
<el-menu :default-active="activeIndex" class="el-menu-vertical-demo">
<template v-for="item in menuList">
<el-submenu :index="item.index" :key="item.index" v-if="item.list"
v-show="permission.indexOf(item.index) >= 0">
<template slot="title">
<i :class="item.icon"></i>
<span>{{ item.name }}</span>
</template>
<el-menu-item-group>
<el-menu-item :index="menu.index" v-for="menu in item.list" v-show="permission.indexOf(menu.index) >= 0"
:key="menu.index" @click="gotoMenu(menu)">{{ menu.name }}
</el-menu-item>
</el-menu-item-group>
</el-submenu>
<el-menu-item :index="item.index" v-if="!item.list" :key="item.index" @click="gotoMenu(item)"
v-show="permission.indexOf(item.index) >= 0">
<i :class="item.icon"></i>
<span slot="title">{{ item.name }}</span>
</el-menu-item>
</template>
</el-menu>
<div class="out-login">
<el-button type="success" @click="logout" icon="el-icon-switch-button" size="small" style="margin-top: 20px">退出登录</el-button>
</div>
</div>
<div class="content-box">
<router-view ref="routeNode"></router-view>
</div>
</div>
</template>
<script>
import {getMenuList} from "../utils/menu";
import {title} from "@/settings";
import request from '@/utils/request';
var _this;
export default {
name: "Menu",
data() {
return {
title: title,
activeMenu: '',
menuList: [],
info: {},
activeIndex: '',
permission: ['0','1','2', '3'],
}
},
mounted() {
_this = this;
_this.activeMenu = this.$route.path == "/" ? "/graphModel" : this.$route.path;
_this.queryInfo();
},
methods: {
gotoMenu(item) {
if (this.activeMenu != item.url) {
this.activeMenu = item.url;
this.$router.push({path: item.url, query: {}})
}
},
queryInfo() {
_this.menuList = getMenuList();
_this.initActiveIndex();
},
initActiveIndex() {
this.activeIndex = null;
this.menuList.forEach(item => {
if (item.url && item.url == this.activeMenu) {
this.activeIndex = item.index;
}
if (item.list) {
item.list.forEach(menu => {
if (menu.url == this.activeMenu) {
this.activeIndex = menu.index;
}
})
}
});
if (this.activeIndex == null) {
if (this.menuList[0].url != undefined) {
this.$router.push({path: this.menuList[0].url, query: {}})
} else {
this.$router.push({path: this.menuList[0].list[0].url, query: {}})
}
}
},
logout() {
this.$store.dispatch('user/logout');
this.$router.push('/login');
}
}
}
</script>
<style lang="scss">
#menuBox {
height: 100%;
overflow: hidden;
width: 100%;
.header-box {
height: 60px;
width: 100%;
box-shadow: 0px 1px 4px 0px rgba(0, 21, 41, 0.12);
overflow: hidden;
color: #ffffff;
background: #2780ff;
.logo {
float: left;
width: 50%;
overflow: hidden;
height: 100%;
line-height: 60px;
font-size: 20px;
padding-left: 30px;
letter-spacing:3px;
background: linear-gradient(to bottom, #a8b6c9, white);
-webkit-text-fill-color: transparent;
-webkit-background-clip: text;
font-weight: bolder;
/*font-weight: bold;*/
.logo-img{
width: 35px;
vertical-align: middle;
margin-right: 15px;
}
}
.info-box {
height: 60px;
float: right;
color: #ffffff;
.head-img {
height: 30px;
width: 30px;
border-radius: 100%;
overflow: hidden;
float: right;
margin-top: 20px;
border: 1px solid rgb(233, 233, 233);
}
.user-name-label {
height: 100%;
color: #d9d9d9;
margin-left: 20px;
float: right;
line-height: 70px;
i{
margin-right: 5px;
}
}
.btn-logout {
border-radius: 5px;
/*border: 1px solid rgb(167, 210, 249);*/
color: #ffffff;
margin-left: 15px;
margin-top: 20px;
margin-right: 20px;
float: right;
padding: 6px 10px;
cursor: pointer;
i{
margin-right: 5px;
}
}
}
}
.system-menu-box {
display: flex;
background: #1652D5;
}
.system-menu-box > div {
display: inline;
padding: 10px 10px;
height: 30px;
line-height: 30px;
font-size: 18px;
text-align: center;
cursor: pointer;
color: #fff;
margin: 10px 0px 0px 50px;
border-bottom: 5px solid rgba(255, 208, 75, 0);
}
.system-menu-box > div:first-child {
margin-left: 20px;
}
.system-menu-box > div:hover, .system-menu-box > div.active {
border-bottom: 5px solid rgb(255, 208, 75);
}
.el-menu-item-group__title {
background: #1652D5 !important;
padding: 0px !important;
}
.el-menu {
border: 0px;
}
.el-menu-item-group {
.el-menu-item {
color: #999999;
}
.el-menu-item.is-active {
color: #2780ff !important;
border-left: 5px solid #2780ff;
i{
color: #2780ff !important;
}
}
}
.el-menu-item-group:hover {
background: rgba(240, 245, 250, 1);
color: #2780ff !important;
}
.menu-box {
width: 260px;
height: 100%;
//background: #2780ff;
color: #333333;
float: left;
//overflow-y: auto;
position: relative;
.out-login{
position: absolute;
bottom:0px;
left: 0px;
right: 0px;
height: 80px;
text-align: center;
background: #ffffff;
}
.el-menu-vertical-demo{
height: calc(100% - 300px);
overflow-y: auto;
}
.content-title{
height: 220px;
text-align: center;
.content-logo{
text-align: center;
width: 60px;
margin-top: 40px;
margin-bottom: 30px;
}
.first-title{
font-size: 20px;
letter-spacing:3px;
font-weight: bold;
background: linear-gradient(to bottom, #1652D5, cornflowerblue);
-webkit-text-fill-color: transparent;
-webkit-background-clip: text;
padding-bottom: 30px;
}
.user-name{
font-weight: normal;
font-size: 14px;
text-align: left;
margin: 0 30px;
color: brown;
}
}
.system-title {
height: 70px;
line-height: 70px;
font-size: 22px;
font-weight: bold;
color: #FFFFFF;
text-align: center;
background: #2780ff;
}
ul {
//background: rgba(42, 70, 170, 0.3);
.el-menu-item{
border-left: 5px solid transparent;
}
.el-menu-item:hover {
background: rgba(240, 245, 250, 1);
}
.el-menu-item.is-active {
background: rgba(240, 245, 250, 1);
color: #2780ff;
border-left: 5px solid #2780ff;
i{
color: #2780ff;
}
span {
color: #2780ff;
}
}
.el-submenu.is-active .el-submenu__title i, .el-submenu.is-active .el-submenu__title span {
color: #2780ff !important;
}
li {
.el-menu {
background: #ffffff;
li {
background: #ffffff;
}
}
span {
color: #666666;
}
i {
color: #666666;
}
.el-submenu__title {
i {
color: #666666;
}
span {
color: #666666;
}
}
}
li:hover {
.el-submenu__title {
background: rgba(0, 0, 0, 0);
}
}
}
}
.content-box {
float: left;
width: calc(100% - 13.54167vw);
height: 100%;
display: block;
background: #F0F2F5;
//background: rgb(240, 242, 245);
.menu-title {
width: 100%;
/*background: #FFFFFF;*/
//height: 68px;
//line-height: 68px;
/*border-top: 1px solid rgb(233, 233, 233);*/
/*border-bottom: 1px solid rgb(233, 233, 233);*/
padding: 0 30px;
font-size: 18px;
font-weight: bold;
color: #4E5054;
padding-top: 20px;
}
.menu-title::after {
content: "";
display: block;
width: 20px;
height: 5px;
background: #2780ff;
}
}
.content-box > div {
width: 100%;
}
}
</style>

View File

@@ -0,0 +1,176 @@
<template>
<div id="login">
<div class="login-content">
<div class="logo-img">
<img src="../assets/image/ambari-logo.png">
<label class="left-title">推荐系统-演示</label>
</div>
<div class="login-center">
<div class="left-content">
<img src="../assets/image/login-img.png" class="login-img">
</div>
<div class="right-content">
<div class="login-title">登录</div>
<div class="second-title">账号密码登录</div>
<el-form ref="form" :model="form" label-width="0px">
<el-form-item label="" style="margin-bottom: 30px">
<el-input placeholder="账号" prefix-icon="el-icon-user" class="login-input" v-model="form.username"></el-input>
</el-form-item>
<el-form-item label="" style="margin-bottom: 30px">
<el-input type="password" placeholder="密码" prefix-icon="el-icon-lock" class="login-input" v-model="form.password"></el-input>
</el-form-item>
<div style="color: #333;letter-spacing:1px;font-size: 15px;margin-bottom: 30px">如果忘记密码请联系管理员</div>
<el-form-item>
<el-button type="primary" plain class="login-button" style="width: 45%;float: left" @click="register()">注册</el-button>
<el-button type="primary" class="login-button" style="width: 45%;float: right" @click="login()">登录</el-button>
</el-form-item>
</el-form>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "login",
data() {
return {
form: {
username: '',
password: '',
type: 'admin'
},
}
},
mounted() {
},
methods: {
login() {
this.$store.dispatch('user/login', this.form).then((res) => {
this.$router.push('/myFriends');
}).catch((res) => {
})
},
register() {
this.$router.push('/register');
}
}
}
</script>
<style scoped lang="scss">
#login{
position: fixed;
left: 0px;
right: 0px;
top: 0px;
bottom: 0px;
background: url('../assets/image/manage-bg.jpg') no-repeat;
background-size: 100% 100%;
.login-content{
left: 0px;
right: 0px;
top: 0px;
bottom: 0px;
//background: rgba(75, 100, 216, 0.74);
background: linear-gradient(192deg, rgba(85, 111, 231, 0.3) 0%, rgba(68, 93, 208, 0.3) 100%);
//background: linear-gradient(to right, rgba(75, 100, 216, 0.4), rgba(75, 100, 216, 0.74));
position: absolute;
z-index: 1;
.logo-img{
position: absolute;
top: 40px;
left: 50px;
img{
width: 50px;
}
.left-title{
color: #ffffff;
line-height: 50px;
font-weight: bolder;
letter-spacing:3px;
height: 50px;
font-size: 26px;
vertical-align: bottom;
padding-left: 30px;
}
}
.login-center{
width: 1400px;
margin: 180px auto 0 auto;
height:600px;
border-radius: 20px;
display: flex;
.left-content{
flex: 1;
//background: rgba(63,81,181,0.5);
//border-top-left-radius: 10px;
//border-bottom-left-radius: 10px;
position: relative;
.left-title{
position: absolute;
left: 0px;
top: -30px;
font-size: 35px;
color: #ffffff;
line-height: 60px;
font-weight: bolder;
letter-spacing:3px;
}
.login-title{
position: absolute;
left: 0px;
top: 0px;
}
.login-img{
position: absolute;
bottom: -40px;
left: 45%;
width: 120%;
margin-left: -60%;
}
}
.right-content{
width: 500px;
padding: 70px 60px 0 60px;
//background: rgba(100,121,222,0.25);
background: #fff;
border-radius: 10px;
box-sizing: border-box;
.login-title{
font-size: 30px;
font-weight: 600;
color: #333;
letter-spacing:5px;
height: 50px;
line-height: 50px;
}
.second-title{
letter-spacing:2px;
height: 30px;
line-height: 30px;
font-size: 20px;
color: #666;
margin-top: 30px;
margin-bottom: 30px;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,198 @@
<template>
<div id="login">
<div class="login-content">
<div class="logo-img">
<img src="../assets/image/ambari-logo.png">
<label class="left-title">推荐系统-演示</label>
</div>
<div class="login-center">
<div class="left-content">
<img src="../assets/image/login-img.png" class="login-img">
</div>
<div class="right-content">
<div class="login-title">注册</div>
<div class="second-title">账号密码登录</div>
<el-form ref="form" :model="form" label-width="0px">
<el-form-item label="" style="margin-bottom: 30px">
<el-input placeholder="账号" prefix-icon="el-icon-user" class="login-input" v-model="form.username"></el-input>
</el-form-item>
<el-form-item label="" style="margin-bottom: 30px">
<el-input type="password" placeholder="密码" prefix-icon="el-icon-lock" class="login-input" v-model="form.password"></el-input>
</el-form-item>
<div style="color: #333;letter-spacing:1px;font-size: 15px;margin-bottom: 30px">如果忘记密码请联系管理员</div>
<el-form-item>
<el-button type="primary" plain class="login-button" style="width: 45%;float:left;" @click="gotoLogin()">前往登陆</el-button>
<el-button type="primary" class="login-button" style="width: 45%;float: right" @click="confirmRegister()">注册</el-button>
</el-form-item>
</el-form>
</div>
</div>
</div>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
name: "login",
data() {
return {
form: {
username: '',
password: '',
type: 'admin'
},
}
},
mounted() {
},
methods: {
gotoLogin() {
this.$router.push('/login');
},
confirmRegister() {
if(this.form.username.length === 0) {
this.$message.warning("用户名不能为空");
return;
}
if(this.form.password.length === 0) {
this.$message.warning("密码不能为空");
return;
}
request({
url: '/login/register',
method: 'post',
data: this.form
}).then(res => {
this.$message.success("注册成功,请前往登陆")
});
request({
url: 'http://43.139.83.67:8088/api/user',
method: 'post',
data: {
UserId: this.form.username
}
}).then(res => {
});
}
}
}
</script>
<style scoped lang="scss">
#login{
position: fixed;
left: 0px;
right: 0px;
top: 0px;
bottom: 0px;
background: url('../assets/image/manage-bg.jpg') no-repeat;
background-size: 100% 100%;
.login-content{
left: 0px;
right: 0px;
top: 0px;
bottom: 0px;
//background: rgba(75, 100, 216, 0.74);
background: linear-gradient(192deg, rgba(85, 111, 231, 0.3) 0%, rgba(68, 93, 208, 0.3) 100%);
//background: linear-gradient(to right, rgba(75, 100, 216, 0.4), rgba(75, 100, 216, 0.74));
position: absolute;
z-index: 1;
.logo-img{
position: absolute;
top: 40px;
left: 50px;
img{
width: 50px;
}
.left-title{
color: #ffffff;
line-height: 50px;
font-weight: bolder;
letter-spacing:3px;
height: 50px;
font-size: 26px;
vertical-align: bottom;
padding-left: 30px;
}
}
.login-center{
width: 1400px;
margin: 180px auto 0 auto;
height:600px;
border-radius: 20px;
display: flex;
.left-content{
flex: 1;
//background: rgba(63,81,181,0.5);
//border-top-left-radius: 10px;
//border-bottom-left-radius: 10px;
position: relative;
.left-title{
position: absolute;
left: 0px;
top: -30px;
font-size: 35px;
color: #ffffff;
line-height: 60px;
font-weight: bolder;
letter-spacing:3px;
}
.login-title{
position: absolute;
left: 0px;
top: 0px;
}
.login-img{
position: absolute;
bottom: -40px;
left: 45%;
width: 120%;
margin-left: -60%;
}
}
.right-content{
width: 500px;
padding: 70px 60px 0 60px;
//background: rgba(100,121,222,0.25);
background: #fff;
border-radius: 10px;
box-sizing: border-box;
.login-title{
font-size: 30px;
font-weight: 600;
color: #333;
letter-spacing:5px;
height: 50px;
line-height: 50px;
}
.second-title{
letter-spacing:2px;
height: 30px;
line-height: 30px;
font-size: 20px;
color: #666;
margin-top: 30px;
margin-bottom: 30px;
}
}
}
}
}
</style>

8
web_home/vue.config.js Normal file
View File

@@ -0,0 +1,8 @@
const path = require('path')
module.exports = {
publicPath: './', // 基本路径
outputDir: 'dist',
assetsDir: 'static',
lintOnSave: false, // eslint-loader 是否在保存的时候检查
}