Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 98 KiB |
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 94 KiB |
After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
@ -0,0 +1,12 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
export const generateToken = (user) => request({
|
||||
url: '/api/auth/token',
|
||||
method: 'post',
|
||||
data: user
|
||||
});
|
||||
|
||||
export const checkTokenValid = (token) => request({
|
||||
url: '/auth/token/' + token,
|
||||
method: 'post'
|
||||
});
|
@ -0,0 +1,185 @@
|
||||
.login-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0 auto;
|
||||
background: radial-gradient(circle, #fff, #1296DB);
|
||||
}
|
||||
|
||||
.login-weaper {
|
||||
margin: 0 auto;
|
||||
width: 1000px;
|
||||
border-radius: 5px;
|
||||
box-shadow: -4px 5px 10px rgba(0, 0, 0, 0.4);
|
||||
|
||||
.el-input-group__append {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.login-left,
|
||||
.login-border {
|
||||
position: relative;
|
||||
min-height: 500px;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.login-left {
|
||||
border-top-left-radius: 5px;
|
||||
border-bottom-left-radius: 5px;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
background-color: #1296DB;
|
||||
color: #fff;
|
||||
float: left;
|
||||
width: 50%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.login-left .img {
|
||||
width: 350px;
|
||||
}
|
||||
|
||||
.login-time {
|
||||
position: absolute;
|
||||
left: 25px;
|
||||
top: 25px;
|
||||
width: 100%;
|
||||
color: #fff;
|
||||
font-weight: 200;
|
||||
opacity: 0.9;
|
||||
font-size: 18px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.login-left .title {
|
||||
margin-top: 60px;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
font-weight: 300;
|
||||
letter-spacing: 2px;
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
.login-border {
|
||||
z-index: 1;
|
||||
border-left: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
border-bottom-right-radius: 5px;
|
||||
color: #fff;
|
||||
background-color: #fff;
|
||||
width: 50%;
|
||||
float: left;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.login-main {
|
||||
margin: 0 auto;
|
||||
width: 65%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.login-main > h3 {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.login-main > p {
|
||||
color: #76838f;
|
||||
}
|
||||
|
||||
.login-title {
|
||||
color: #333;
|
||||
margin-bottom: 40px;
|
||||
font-weight: 500;
|
||||
font-size: 22px;
|
||||
text-align: center;
|
||||
letter-spacing: 4px;
|
||||
}
|
||||
|
||||
.login-menu {
|
||||
margin-top: 40px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
|
||||
a {
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
margin: 0px 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.login-submit {
|
||||
width: 100%;
|
||||
height: 45px;
|
||||
background: none;
|
||||
font-size: 18px;
|
||||
letter-spacing: 2px;
|
||||
font-weight: 300;
|
||||
color: #1296DB;
|
||||
cursor: pointer;
|
||||
margin-top: 30px;
|
||||
transition: 0.25s;
|
||||
}
|
||||
|
||||
.login-form {
|
||||
margin: 10px 0;
|
||||
|
||||
i {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.el-form-item__content {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.el-form-item {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.el-input {
|
||||
input {
|
||||
padding-bottom: 10px;
|
||||
text-indent: 5px;
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
color: #333;
|
||||
border-bottom: 1px solid rgb(235, 237, 242);
|
||||
}
|
||||
|
||||
.el-input__prefix {
|
||||
i {
|
||||
padding: 0 5px;
|
||||
font-size: 16px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.login-code {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
margin: 0 0 0 10px;
|
||||
}
|
||||
|
||||
.login-code-img {
|
||||
margin-top: 2px;
|
||||
width: 100px;
|
||||
height: 38px;
|
||||
background-color: #fdfdfd;
|
||||
border: 1px solid #f0f0f0;
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
letter-spacing: 5px;
|
||||
line-height: 38px;
|
||||
text-indent: 5px;
|
||||
text-align: center;
|
||||
}
|
@ -0,0 +1,465 @@
|
||||
<template>
|
||||
<div class="waves">
|
||||
<slot/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
class ShaderProgram {
|
||||
constructor(holder, options = {}) {
|
||||
options = Object.assign(
|
||||
{
|
||||
antialias: false,
|
||||
depthTest: false,
|
||||
mousemove: false,
|
||||
autosize: true,
|
||||
side: "front",
|
||||
vertex: `
|
||||
precision highp float;
|
||||
attribute vec4 a_position;
|
||||
attribute vec4 a_color;
|
||||
uniform float u_time;
|
||||
uniform vec2 u_resolution;
|
||||
uniform vec2 u_mousemove;
|
||||
uniform mat4 u_projection;
|
||||
varying vec4 v_color;
|
||||
void main() {
|
||||
gl_Position = u_projection * a_position;
|
||||
gl_PointSize = (10.0 / gl_Position.w) * 100.0;
|
||||
v_color = a_color;
|
||||
}`,
|
||||
fragment: `
|
||||
precision highp float;
|
||||
uniform sampler2D u_texture;
|
||||
uniform int u_hasTexture;
|
||||
varying vec4 v_color;
|
||||
void main() {
|
||||
if ( u_hasTexture == 1 ) {
|
||||
gl_FragColor = v_color * texture2D(u_texture, gl_PointCoord);
|
||||
} else {
|
||||
gl_FragColor = v_color;
|
||||
}
|
||||
}`,
|
||||
onUpdate: () => {
|
||||
},
|
||||
onResize: () => {
|
||||
}
|
||||
},
|
||||
options
|
||||
);
|
||||
const uniforms = Object.assign(
|
||||
{
|
||||
time: {
|
||||
type: "float",
|
||||
value: 0
|
||||
},
|
||||
hasTexture: {
|
||||
type: "int",
|
||||
value: 0
|
||||
},
|
||||
resolution: {
|
||||
type: "vec2",
|
||||
value: [0, 0]
|
||||
},
|
||||
projection: {
|
||||
type: "mat4",
|
||||
value: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
|
||||
}
|
||||
},
|
||||
options.uniforms
|
||||
);
|
||||
const buffers = Object.assign(
|
||||
{
|
||||
position: {
|
||||
size: 3,
|
||||
data: []
|
||||
},
|
||||
color: {
|
||||
size: 4,
|
||||
data: []
|
||||
}
|
||||
},
|
||||
options.buffers
|
||||
);
|
||||
const camera = Object.assign(
|
||||
{
|
||||
fov: 60,
|
||||
near: 1,
|
||||
far: 10000,
|
||||
aspect: 1,
|
||||
z: 100,
|
||||
perspective: true
|
||||
},
|
||||
options.camera
|
||||
);
|
||||
const canvas = document.createElement("canvas");
|
||||
const gl = canvas.getContext("webgl", {
|
||||
antialias: options.antialias
|
||||
});
|
||||
if (!gl) return false;
|
||||
this.count = 0;
|
||||
this.gl = gl;
|
||||
this.canvas = canvas;
|
||||
this.camera = camera;
|
||||
this.holder = holder;
|
||||
this.onUpdate = options.onUpdate;
|
||||
this.onResize = options.onResize;
|
||||
this.data = {};
|
||||
holder.appendChild(canvas);
|
||||
this.createProgram(options.vertex, options.fragment);
|
||||
this.createBuffers(buffers);
|
||||
this.createUniforms(uniforms);
|
||||
this.updateUniforms();
|
||||
this.createTexture(options.texture);
|
||||
gl.enable(gl.BLEND);
|
||||
gl.enable(gl.CULL_FACE);
|
||||
gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
|
||||
gl[options.depthTest ? "enable" : "disable"](gl.DEPTH_TEST);
|
||||
if (options.autosize)
|
||||
window.addEventListener("resize", () => this.resize(), false);
|
||||
this.resize();
|
||||
this.update = this.update.bind(this);
|
||||
this.time = {
|
||||
start: performance.now(),
|
||||
old: performance.now()
|
||||
};
|
||||
this.update();
|
||||
}
|
||||
|
||||
resize() {
|
||||
const holder = this.holder;
|
||||
const canvas = this.canvas;
|
||||
const gl = this.gl;
|
||||
const width = (this.width = holder.offsetWidth);
|
||||
const height = (this.height = holder.offsetHeight);
|
||||
const aspect = (this.aspect = width / height);
|
||||
const dpi = (this.dpi = devicePixelRatio);
|
||||
canvas.width = width * dpi;
|
||||
canvas.height = height * dpi;
|
||||
canvas.style.width = 100 + "%";
|
||||
canvas.style.height = 100 + "%";
|
||||
gl.viewport(0, 0, width * dpi, height * dpi);
|
||||
this.uniforms.resolution = [width, height];
|
||||
this.uniforms.projection = this.setProjection(aspect);
|
||||
this.onResize(width, height, dpi);
|
||||
}
|
||||
|
||||
setProjection(aspect) {
|
||||
const camera = this.camera;
|
||||
if (camera.perspective) {
|
||||
camera.aspect = aspect;
|
||||
const fovRad = camera.fov * (Math.PI / 180);
|
||||
const f = Math.tan(Math.PI * 0.5 - 0.5 * fovRad);
|
||||
const rangeInv = 1.0 / (camera.near - camera.far);
|
||||
const matrix = [
|
||||
f / camera.aspect,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
f,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
(camera.near + camera.far) * rangeInv,
|
||||
-1,
|
||||
0,
|
||||
0,
|
||||
camera.near * camera.far * rangeInv * 2,
|
||||
0
|
||||
];
|
||||
matrix[14] += camera.z;
|
||||
matrix[15] += camera.z;
|
||||
return matrix;
|
||||
} else {
|
||||
return [
|
||||
2 / this.width,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
-2 / this.height,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
-1,
|
||||
1,
|
||||
0,
|
||||
1
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
createShader(type, source) {
|
||||
const gl = this.gl;
|
||||
const shader = gl.createShader(type);
|
||||
gl.shaderSource(shader, source);
|
||||
gl.compileShader(shader);
|
||||
if (gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
||||
return shader;
|
||||
} else {
|
||||
gl.deleteShader(shader);
|
||||
}
|
||||
}
|
||||
|
||||
createProgram(vertex, fragment) {
|
||||
const gl = this.gl;
|
||||
const vertexShader = this.createShader(gl.VERTEX_SHADER, vertex);
|
||||
const fragmentShader = this.createShader(gl.FRAGMENT_SHADER, fragment);
|
||||
const program = gl.createProgram();
|
||||
gl.attachShader(program, vertexShader);
|
||||
gl.attachShader(program, fragmentShader);
|
||||
gl.linkProgram(program);
|
||||
if (gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
||||
gl.useProgram(program);
|
||||
this.program = program;
|
||||
} else {
|
||||
gl.deleteProgram(program);
|
||||
}
|
||||
}
|
||||
|
||||
createUniforms(data) {
|
||||
const gl = this.gl;
|
||||
const uniforms = (this.data.uniforms = data);
|
||||
const values = (this.uniforms = {});
|
||||
Object.keys(uniforms).forEach(name => {
|
||||
const uniform = uniforms[name];
|
||||
uniform.location = gl.getUniformLocation(this.program, "u_" + name);
|
||||
Object.defineProperty(values, name, {
|
||||
set: value => {
|
||||
uniforms[name].value = value;
|
||||
this.setUniform(name, value);
|
||||
},
|
||||
get: () => uniforms[name].value
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
setUniform(name, value) {
|
||||
const gl = this.gl;
|
||||
const uniform = this.data.uniforms[name];
|
||||
uniform.value = value;
|
||||
switch (uniform.type) {
|
||||
case "int": {
|
||||
gl.uniform1i(uniform.location, value);
|
||||
break;
|
||||
}
|
||||
case "float": {
|
||||
gl.uniform1f(uniform.location, value);
|
||||
break;
|
||||
}
|
||||
case "vec2": {
|
||||
gl.uniform2f(uniform.location, ...value);
|
||||
break;
|
||||
}
|
||||
case "vec3": {
|
||||
gl.uniform3f(uniform.location, ...value);
|
||||
break;
|
||||
}
|
||||
case "vec4": {
|
||||
gl.uniform4f(uniform.location, ...value);
|
||||
break;
|
||||
}
|
||||
case "mat2": {
|
||||
gl.uniformMatrix2fv(uniform.location, false, value);
|
||||
break;
|
||||
}
|
||||
case "mat3": {
|
||||
gl.uniformMatrix3fv(uniform.location, false, value);
|
||||
break;
|
||||
}
|
||||
case "mat4": {
|
||||
gl.uniformMatrix4fv(uniform.location, false, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateUniforms() {
|
||||
const uniforms = this.data.uniforms;
|
||||
Object.keys(uniforms).forEach(name => {
|
||||
const uniform = uniforms[name];
|
||||
this.uniforms[name] = uniform.value;
|
||||
});
|
||||
}
|
||||
|
||||
createBuffers(data) {
|
||||
const buffers = (this.data.buffers = data);
|
||||
const values = (this.buffers = {});
|
||||
Object.keys(buffers).forEach(name => {
|
||||
const buffer = buffers[name];
|
||||
buffer.buffer = this.createBuffer("a_" + name, buffer.size);
|
||||
Object.defineProperty(values, name, {
|
||||
set: data => {
|
||||
buffers[name].data = data;
|
||||
this.setBuffer(name, data);
|
||||
if (name === "position") this.count = buffers.position.data.length / 3;
|
||||
},
|
||||
get: () => buffers[name].data
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
createBuffer(name, size) {
|
||||
const gl = this.gl;
|
||||
const program = this.program;
|
||||
const index = gl.getAttribLocation(program, name);
|
||||
const buffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
||||
gl.enableVertexAttribArray(index);
|
||||
gl.vertexAttribPointer(index, size, gl.FLOAT, false, 0, 0);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
setBuffer(name, data) {
|
||||
const gl = this.gl;
|
||||
const buffers = this.data.buffers;
|
||||
if (name == null && !gl.bindBuffer(gl.ARRAY_BUFFER, null)) return;
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, buffers[name].buffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STATIC_DRAW);
|
||||
}
|
||||
|
||||
createTexture(src) {
|
||||
const gl = this.gl;
|
||||
const texture = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||
gl.texImage2D(
|
||||
gl.TEXTURE_2D,
|
||||
0,
|
||||
gl.RGBA,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
gl.RGBA,
|
||||
gl.UNSIGNED_BYTE,
|
||||
new Uint8Array([0, 0, 0, 0])
|
||||
);
|
||||
this.texture = texture;
|
||||
if (src) {
|
||||
this.uniforms.hasTexture = 1;
|
||||
this.loadTexture(src);
|
||||
}
|
||||
}
|
||||
|
||||
loadTexture(src) {
|
||||
const gl = this.gl;
|
||||
const texture = this.texture;
|
||||
const textureImage = new Image();
|
||||
textureImage.onload = () => {
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||
gl.texImage2D(
|
||||
gl.TEXTURE_2D,
|
||||
0,
|
||||
gl.RGBA,
|
||||
gl.RGBA,
|
||||
gl.UNSIGNED_BYTE,
|
||||
textureImage
|
||||
);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
};
|
||||
textureImage.src = src;
|
||||
}
|
||||
|
||||
update() {
|
||||
const gl = this.gl;
|
||||
const now = performance.now();
|
||||
const elapsed = (now - this.time.start) / 5000;
|
||||
this.time.old = now;
|
||||
this.uniforms.time = elapsed;
|
||||
if (this.count > 0) {
|
||||
gl.drawArrays(gl.POINTS, 0, this.count);
|
||||
}
|
||||
this.onUpdate();
|
||||
requestAnimationFrame(this.update);
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
name: "BgAnimation",
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
mounted() {
|
||||
const pointSize = 1.5;
|
||||
new ShaderProgram(
|
||||
document.querySelector(".waves"), {
|
||||
texture: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAb1BMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8v0wLRAAAAJHRSTlMAC/goGvDhmwcExrVjWzrm29TRqqSKenRXVklANSIUE8mRkGpv+HOfAAABCElEQVQ4y4VT13LDMAwLrUHteO+R9f/fWMfO6dLaPeKVEECRxOULWsEGpS9nULDwia2Y+ALqUNbAWeg775zv+sA4/FFRMxt8U2FZFCVWjR/YrH4/H9sarclSKdPMWKzb8VsEeHB3m0shkhVCyNzeXeAQ9Xl4opEieX2QCGnwGbj6GMyjw9t1K0fK9YZunPXeAGsfJtYjwzxaBnozGGorYz0ypK2HzQSYx1y8DgSRo2ewOiyh2QWOEk1Y9OrQV0a8TiBM1a8eMHWYnRMy7CZ4t1CmyRkhSUvP3gRXyHOCLBxNoC3IJv//ZrJ/kxxUHPUB+6jJZZHrpg6GOjnqaOmzp4NDR48OLxn/H27SRQ08S0ZJAAAAAElFTkSuQmCC",
|
||||
uniforms: {
|
||||
size: {type: "float", value: pointSize},
|
||||
field: {type: "vec3", value: [0, 0, 0]},
|
||||
speed: {type: "float", value: 5}
|
||||
},
|
||||
vertex: `
|
||||
#define M_PI 3.1415926535897932384626433832795
|
||||
precision highp float;
|
||||
attribute vec4 a_position;
|
||||
attribute vec4 a_color;
|
||||
uniform float u_time;
|
||||
uniform float u_size;
|
||||
uniform float u_speed;
|
||||
uniform vec3 u_field;
|
||||
uniform mat4 u_projection;
|
||||
varying vec4 v_color;
|
||||
void main() {
|
||||
vec3 pos = a_position.xyz;
|
||||
pos.y += (
|
||||
cos(pos.x / u_field.x * M_PI * 8.0 + u_time * u_speed) +
|
||||
sin(pos.z / u_field.z * M_PI * 8.0 + u_time * u_speed)
|
||||
) * u_field.y;
|
||||
gl_Position = u_projection * vec4( pos.xyz, a_position.w );
|
||||
gl_PointSize = ( u_size / gl_Position.w ) * 100.0;
|
||||
v_color = a_color;
|
||||
}`,
|
||||
fragment: `
|
||||
precision highp float;
|
||||
uniform sampler2D u_texture;
|
||||
varying vec4 v_color;
|
||||
void main() {
|
||||
gl_FragColor = v_color * texture2D(u_texture, gl_PointCoord);
|
||||
}`,
|
||||
onResize(w, h, dpi) {
|
||||
const position = [], color = [];
|
||||
const width = 400 * (w / h), depth = 500, height = 3, distance = 3;
|
||||
for (let x = 0; x < width; x += distance) {
|
||||
for (let z = 0; z < depth; z += distance) {
|
||||
position.push(-width / 2 + x, -30, -depth / 2 + z);
|
||||
color.push(
|
||||
1,
|
||||
//1 - (x / width),
|
||||
1,
|
||||
1,
|
||||
//0.5 + (x / width) * 0.5,
|
||||
z / depth
|
||||
);
|
||||
}
|
||||
}
|
||||
this.uniforms.field = [width, height, depth];
|
||||
this.buffers.position = position;
|
||||
this.buffers.color = color;
|
||||
this.uniforms.size = (h / 400) * pointSize * dpi;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
canvas {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.waves {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,36 @@
|
||||
import router from '@/router/router'
|
||||
import store from '@/store/store'
|
||||
import NProgress from 'nprogress'
|
||||
import 'nprogress/nprogress.css'
|
||||
import {getToken} from '@/util/auth'
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
NProgress.start();
|
||||
const meta = to.meta || {};
|
||||
if (getToken()) {
|
||||
if (to.path === '/login') { //如果登录成功访问登录页跳转到主页
|
||||
next({path: '/'})
|
||||
} else {
|
||||
//如果用户信息为空则获取用户信息,获取用户信息失败,跳转到登录页
|
||||
console.log(store.getters.token);
|
||||
if (store.getters.token.length === 0) {
|
||||
store.dispatch('FedLogOut').then(() => {
|
||||
next({path: '/login'})
|
||||
})
|
||||
} else {
|
||||
next()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//判断是否需要认证,没有登录访问去登录页
|
||||
if (meta.isAuth === false) {
|
||||
next()
|
||||
} else {
|
||||
next('/login')
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
router.afterEach(() => {
|
||||
NProgress.done();
|
||||
});
|
@ -0,0 +1,42 @@
|
||||
export default [
|
||||
{
|
||||
name: 'login',
|
||||
path: '/login',
|
||||
meta: {
|
||||
isAuth: false
|
||||
},
|
||||
component: () => import('@/views/login/index')
|
||||
}, {
|
||||
name: 'index',
|
||||
path: '/',
|
||||
redirect: '/home',
|
||||
meta: {
|
||||
isAuth: true
|
||||
}
|
||||
}, {
|
||||
name: '404',
|
||||
path: '/404',
|
||||
meta: {
|
||||
isAuth: false
|
||||
},
|
||||
component: () => import('@/components/error/404')
|
||||
|
||||
}, {
|
||||
name: '403',
|
||||
path: '/403',
|
||||
meta: {
|
||||
isAuth: false
|
||||
},
|
||||
component: () => import('@/components/error/403')
|
||||
}, {
|
||||
name: '500',
|
||||
path: '/500',
|
||||
meta: {
|
||||
isAuth: false
|
||||
},
|
||||
component: () => import('@/components/error/500')
|
||||
}, {
|
||||
path: '*',
|
||||
redirect: '/404'
|
||||
}
|
||||
]
|
@ -1,43 +1,86 @@
|
||||
export default [
|
||||
/*{
|
||||
path: '/login',
|
||||
name: '登录页',
|
||||
component: () => import('@/page/login/index'),
|
||||
meta: {
|
||||
keepAlive: true,
|
||||
isTab: false,
|
||||
isAuth: false
|
||||
}
|
||||
},*/ {
|
||||
path: '/404',
|
||||
component: () => import('@/components/error/404'),
|
||||
name: '404',
|
||||
meta: {
|
||||
keepAlive: true,
|
||||
isTab: false,
|
||||
isAuth: false
|
||||
}
|
||||
import Index from '@/views/index/index'
|
||||
|
||||
export default [
|
||||
{
|
||||
path: '/',
|
||||
redirect: '/home',
|
||||
meta: {
|
||||
isAuth: true
|
||||
},
|
||||
component: Index,
|
||||
children: [
|
||||
{
|
||||
name: 'home',
|
||||
path: '/home',
|
||||
meta: {
|
||||
isAuth: true
|
||||
},
|
||||
component: () => import('@/views/Home')
|
||||
},
|
||||
{
|
||||
name: 'things',
|
||||
path: '/things',
|
||||
meta: {
|
||||
isAuth: true
|
||||
},
|
||||
component: () => import('@/views/Things')
|
||||
}, {
|
||||
path: '/403',
|
||||
component: () => import('@/components/error/403'),
|
||||
name: '403',
|
||||
name: 'template',
|
||||
path: '/template',
|
||||
meta: {
|
||||
keepAlive: true,
|
||||
isTab: false,
|
||||
isAuth: false
|
||||
}
|
||||
isAuth: true
|
||||
},
|
||||
component: () => import('@/views/Template')
|
||||
}, {
|
||||
path: '/500',
|
||||
component: () => import('@/components/error/500'),
|
||||
name: '500',
|
||||
name: 'now',
|
||||
path: '/now',
|
||||
meta: {
|
||||
keepAlive: true,
|
||||
isTab: false,
|
||||
isAuth: false
|
||||
}
|
||||
isAuth: true
|
||||
},
|
||||
component: () => import('@/views/Now')
|
||||
}, {
|
||||
name: 'history',
|
||||
path: '/history',
|
||||
meta: {
|
||||
isAuth: true
|
||||
},
|
||||
component: () => import('@/views/History')
|
||||
}, {
|
||||
path: '*',
|
||||
redirect: '/404'
|
||||
name: 'alarm',
|
||||
path: '/alarm',
|
||||
meta: {
|
||||
isAuth: true
|
||||
},
|
||||
component: () => import('@/views/Alarm')
|
||||
}, {
|
||||
name: 'label',
|
||||
path: '/label',
|
||||
meta: {
|
||||
isAuth: true
|
||||
},
|
||||
component: () => import('@/views/Label')
|
||||
}, {
|
||||
name: 'picture',
|
||||
path: '/picture',
|
||||
meta: {
|
||||
isAuth: true
|
||||
},
|
||||
component: () => import('@/views/Picture')
|
||||
}, {
|
||||
name: 'video',
|
||||
path: '/video',
|
||||
meta: {
|
||||
isAuth: true
|
||||
},
|
||||
component: () => import('@/views/Video')
|
||||
}, {
|
||||
name: 'about',
|
||||
path: '/about',
|
||||
meta: {
|
||||
isAuth: true
|
||||
},
|
||||
component: () => import('@/views/About')
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
@ -1,5 +1,5 @@
|
||||
const getters = {
|
||||
currentNav: state => state.common.currentNav
|
||||
token: state => state.user.token,
|
||||
};
|
||||
|
||||
export default getters
|
@ -1,20 +1,10 @@
|
||||
import website from '../../config/website'
|
||||
import {getStore, setStore} from '../../util/store'
|
||||
import website from '@/config/website'
|
||||
|
||||
const common = {
|
||||
|
||||
state: {
|
||||
website: website,
|
||||
currentNav: getStore({name: 'currentNav'}) || '/',
|
||||
},
|
||||
mutations: {
|
||||
SET_CURRENT_PATH: (state, currentNav) => {
|
||||
state.currentNav = currentNav;
|
||||
setStore({
|
||||
name: 'currentNav',
|
||||
content: state.currentNav,
|
||||
})
|
||||
}
|
||||
}
|
||||
mutations: {}
|
||||
};
|
||||
export default common
|
@ -0,0 +1,51 @@
|
||||
import {getStore, setStore} from '@/util/store'
|
||||
import {setToken} from '@/util/auth'
|
||||
import {checkTokenValid, generateToken} from '@/api/user'
|
||||
|
||||
const user = {
|
||||
state: {
|
||||
userInfo: getStore({name: 'userInfo'}) || [],
|
||||
token: getStore({name: 'token'}) || '',
|
||||
},
|
||||
actions: {
|
||||
GenerateToken({commit}, user) {
|
||||
return new Promise((resolve, reject) => {
|
||||
generateToken(user).then(res => {
|
||||
const data = res.data;
|
||||
if (data.ok) {
|
||||
commit('SET_USER', user);
|
||||
commit('SET_TOKEN', data.message);
|
||||
resolve();
|
||||
}
|
||||
}).catch(error => {
|
||||
reject(error);
|
||||
})
|
||||
})
|
||||
},
|
||||
CheckTokenValid(body) {
|
||||
return new Promise((resolve, reject) => {
|
||||
checkTokenValid(body).then(res => {
|
||||
const data = res.data;
|
||||
if (data.ok) {
|
||||
resolve();
|
||||
}
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
mutations: {
|
||||
SET_TOKEN: (state, token) => {
|
||||
setToken(token);
|
||||
state.token = token;
|
||||
setStore({name: 'token', content: state.token, type: 'session'})
|
||||
},
|
||||
SET_USER: (state, userInfo) => {
|
||||
state.userInfo = userInfo;
|
||||
setStore({name: 'userInfo', content: state.userInfo})
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default user
|
@ -0,0 +1,16 @@
|
||||
import Cookies from 'js-cookie'
|
||||
|
||||
const TokenKey = 'x-access-token';
|
||||
const inFifteenMinutes = new Date(new Date().getTime() + 120 * 60 * 1000);
|
||||
|
||||
export function getToken() {
|
||||
return Cookies.get(TokenKey);
|
||||
}
|
||||
|
||||
export function setToken(token) {
|
||||
return Cookies.set(TokenKey, token, {expires: inFifteenMinutes});
|
||||
}
|
||||
|
||||
export function removeToken() {
|
||||
return Cookies.remove(TokenKey);
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/**
|
||||
*
|
||||
* @param date1
|
||||
* @param date2
|
||||
* @returns {{leave1: number, hours: number, seconds: number, leave2: number, leave3: number, minutes: number, days: number}}
|
||||
*/
|
||||
export const calcDate = (date1, date2) => {
|
||||
let date3 = date2 - date1;
|
||||
|
||||
let days = Math.floor(date3 / (24 * 3600 * 1000));
|
||||
|
||||
let leave1 = date3 % (24 * 3600 * 1000);//计算天数后剩余的毫秒数
|
||||
let hours = Math.floor(leave1 / (3600 * 1000));
|
||||
|
||||
let leave2 = leave1 % (3600 * 1000);//计算小时数后剩余的毫秒数
|
||||
let minutes = Math.floor(leave2 / (60 * 1000));
|
||||
|
||||
let leave3 = leave2 % (60 * 1000);//计算分钟数后剩余的毫秒数
|
||||
let seconds = Math.round(date3 / 1000);
|
||||
return {
|
||||
leave1,
|
||||
leave2,
|
||||
leave3,
|
||||
days: days,
|
||||
hours: hours,
|
||||
minutes: minutes,
|
||||
seconds: seconds,
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 日期格式化
|
||||
*
|
||||
* @param date
|
||||
* @returns {string}
|
||||
*/
|
||||
export function dateFormat(date) {
|
||||
let format = 'yyyy-MM-dd hh:mm:ss';
|
||||
if (date !== 'Invalid Date') {
|
||||
let o = {
|
||||
"M+": date.getMonth() + 1, //month
|
||||
"d+": date.getDate(), //day
|
||||
"h+": date.getHours(), //hour
|
||||
"m+": date.getMinutes(), //minute
|
||||
"s+": date.getSeconds(), //second
|
||||
"q+": Math.floor((date.getMonth() + 3) / 3), //quarter
|
||||
"S": date.getMilliseconds() //millisecond
|
||||
};
|
||||
if (/(y+)/.test(format)) format = format.replace(RegExp.$1,
|
||||
(date.getFullYear() + "").substr(4 - RegExp.$1.length));
|
||||
for (let k in o)
|
||||
if (new RegExp("(" + k + ")").test(format))
|
||||
format = format.replace(RegExp.$1,
|
||||
RegExp.$1.length === 1 ? o[k] :
|
||||
("00" + o[k]).substr(("" + o[k]).length));
|
||||
return format;
|
||||
}
|
||||
return '';
|
||||
}
|
@ -0,0 +1,345 @@
|
||||
import {isNull} from './validate'
|
||||
|
||||
/**
|
||||
* 表单序列化
|
||||
*
|
||||
* @param data
|
||||
* @returns {string}
|
||||
*/
|
||||
export const serialize = data => {
|
||||
let list = [];
|
||||
Object.keys(data).forEach(ele => {
|
||||
list.push(`${ele}=${data[ele]}`)
|
||||
});
|
||||
return list.join('&');
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取对象类型
|
||||
*
|
||||
* @param obj
|
||||
* @returns {string|*}
|
||||
*/
|
||||
export const getObjType = obj => {
|
||||
let toString = Object.prototype.toString;
|
||||
let map = {
|
||||
'[object Boolean]': 'boolean',
|
||||
'[object Number]': 'number',
|
||||
'[object String]': 'string',
|
||||
'[object Function]': 'function',
|
||||
'[object Array]': 'array',
|
||||
'[object Date]': 'date',
|
||||
'[object RegExp]': 'regExp',
|
||||
'[object Undefined]': 'undefined',
|
||||
'[object Null]': 'null',
|
||||
'[object Object]': 'object'
|
||||
};
|
||||
if (obj instanceof Element) {
|
||||
return 'element';
|
||||
}
|
||||
return map[toString.call(obj)];
|
||||
};
|
||||
|
||||
/**
|
||||
* 对象深拷贝
|
||||
*
|
||||
* @param data
|
||||
* @returns {{}|*}
|
||||
*/
|
||||
export const deepClone = data => {
|
||||
let type = getObjType(data);
|
||||
let obj;
|
||||
if (type === 'array') {
|
||||
obj = [];
|
||||
} else if (type === 'object') {
|
||||
obj = {};
|
||||
} else {
|
||||
//不再具有下一层次
|
||||
return data;
|
||||
}
|
||||
if (type === 'array') {
|
||||
for (let i = 0, len = data.length; i < len; i++) {
|
||||
obj.push(deepClone(data[i]));
|
||||
}
|
||||
} else if (type === 'object') {
|
||||
for (let key in data) {
|
||||
obj[key] = deepClone(data[key]);
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
/**
|
||||
* 设置灰度模式
|
||||
*
|
||||
* @param status
|
||||
*/
|
||||
export const toggleGrayMode = (status) => {
|
||||
if (status) {
|
||||
document.body.className = document.body.className + ' grayMode';
|
||||
} else {
|
||||
document.body.className = document.body.className.replace(' grayMode', '');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 设置主题
|
||||
*
|
||||
* @param name
|
||||
*/
|
||||
export const setTheme = (name) => {
|
||||
document.body.className = name;
|
||||
};
|
||||
|
||||
/**
|
||||
* 加密处理
|
||||
*
|
||||
* @param params
|
||||
* @returns {any}
|
||||
*/
|
||||
export const encryption = (params) => {
|
||||
let {
|
||||
data,
|
||||
type,
|
||||
param,
|
||||
key
|
||||
} = params;
|
||||
let result = JSON.parse(JSON.stringify(data));
|
||||
if (type === 'Base64') {
|
||||
param.forEach(ele => {
|
||||
result[ele] = btoa(result[ele]);
|
||||
})
|
||||
} else if (type === 'Aes') {
|
||||
param.forEach(ele => {
|
||||
result[ele] = window.CryptoJS.AES.encrypt(result[ele], key).toString();
|
||||
})
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 递归寻找子类的父类
|
||||
*
|
||||
* @param menu
|
||||
* @param id
|
||||
* @returns {undefined|*}
|
||||
*/
|
||||
export const findParent = (menu, id) => {
|
||||
for (let i = 0; i < menu.length; i++) {
|
||||
if (menu[i].children.length !== 0) {
|
||||
for (let j = 0; j < menu[i].children.length; j++) {
|
||||
if (menu[i].children[j].id === id) {
|
||||
return menu[i];
|
||||
} else {
|
||||
if (menu[i].children[j].children.length !== 0) {
|
||||
return findParent(menu[i].children[j].children, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 动态插入css
|
||||
*
|
||||
* @param url
|
||||
*/
|
||||
export const loadStyle = url => {
|
||||
const link = document.createElement('link');
|
||||
link.type = 'text/css';
|
||||
link.rel = 'stylesheet';
|
||||
link.href = url;
|
||||
const head = document.getElementsByTagName('head')[0];
|
||||
head.appendChild(link);
|
||||
};
|
||||
|
||||
/**
|
||||
* 判断2个对象属性和值是否相等
|
||||
*
|
||||
* @param obj1
|
||||
* @param obj2
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const diff = (obj1, obj2) => {
|
||||
delete obj1.close;
|
||||
let o1 = obj1 instanceof Object;
|
||||
let o2 = obj2 instanceof Object;
|
||||
if (!o1 || !o2) {
|
||||
return obj1 === obj2;
|
||||
}
|
||||
|
||||
if (Object.keys(obj1).length !== Object.keys(obj2).length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let attr in obj1) {
|
||||
let t1 = obj1[attr] instanceof Object;
|
||||
let t2 = obj2[attr] instanceof Object;
|
||||
if (t1 && t2) {
|
||||
return diff(obj1[attr], obj2[attr]);
|
||||
} else if (obj1[attr] !== obj2[attr]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据字典的value显示label
|
||||
*
|
||||
* @param dic
|
||||
* @param value
|
||||
* @returns {string|*}
|
||||
*/
|
||||
export const findDicLabel = (dic, value) => {
|
||||
let result = '';
|
||||
if (isNull(dic)) return value;
|
||||
if (typeof (value) == 'string' || typeof (value) == 'number' || typeof (value) == 'boolean') {
|
||||
let index = 0;
|
||||
index = findDicIndex(dic, value);
|
||||
if (index !== -1) {
|
||||
result = dic[index].label;
|
||||
} else {
|
||||
result = value;
|
||||
}
|
||||
} else if (value instanceof Array) {
|
||||
result = [];
|
||||
let index = 0;
|
||||
value.forEach(ele => {
|
||||
index = findDicIndex(dic, ele);
|
||||
if (index !== -1) {
|
||||
result.push(dic[index].label);
|
||||
} else {
|
||||
result.push(value);
|
||||
}
|
||||
});
|
||||
result = result.toString();
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据字典的value查找对应的index
|
||||
*
|
||||
* @param dic
|
||||
* @param value
|
||||
* @returns {number}
|
||||
*/
|
||||
export const findDicIndex = (dic, value) => {
|
||||
for (let i = 0; i < dic.length; i++) {
|
||||
if (dic[i].value === value) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
/**
|
||||
* 生成随机len位数字
|
||||
*
|
||||
* @param len
|
||||
* @param date
|
||||
* @returns {string}
|
||||
*/
|
||||
export const randomLenNum = (len, date) => {
|
||||
let random = '';
|
||||
random = Math.ceil(Math.random() * 100000000000000).toString().substr(0, len ? len : 4);
|
||||
if (date) random = random + Date.now();
|
||||
return random;
|
||||
};
|
||||
|
||||
/**
|
||||
* 打开全屏/关闭全屏
|
||||
*/
|
||||
export const triggerFullscreen = () => {
|
||||
if (fullscreenEnable()) {
|
||||
exitFullScreen();
|
||||
} else {
|
||||
reqFullScreen();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* esc监听全屏
|
||||
*
|
||||
* @param callback
|
||||
*/
|
||||
export const listenFullscreen = (callback) => {
|
||||
function listen() {
|
||||
callback()
|
||||
}
|
||||
|
||||
document.addEventListener("fullscreenchange", function () {
|
||||
listen();
|
||||
});
|
||||
document.addEventListener("mozfullscreenchange", function () {
|
||||
listen();
|
||||
});
|
||||
document.addEventListener("webkitfullscreenchange", function () {
|
||||
listen();
|
||||
});
|
||||
document.addEventListener("msfullscreenchange", function () {
|
||||
listen();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 浏览器判断是否全屏
|
||||
*/
|
||||
export const fullscreenEnable = () => {
|
||||
return document.isFullScreen || document.mozIsFullScreen || document.webkitIsFullScreen;
|
||||
};
|
||||
|
||||
/**
|
||||
* 浏览器全屏
|
||||
*/
|
||||
export const reqFullScreen = () => {
|
||||
if (document.documentElement.requestFullScreen) {
|
||||
document.documentElement.requestFullScreen();
|
||||
} else if (document.documentElement.webkitRequestFullScreen) {
|
||||
document.documentElement.webkitRequestFullScreen();
|
||||
} else if (document.documentElement.mozRequestFullScreen) {
|
||||
document.documentElement.mozRequestFullScreen();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 浏览器退出全屏
|
||||
*/
|
||||
export const exitFullScreen = () => {
|
||||
if (document.documentElement.requestFullScreen) {
|
||||
document.exitFullScreen();
|
||||
} else if (document.documentElement.webkitRequestFullScreen) {
|
||||
document.webkitCancelFullScreen();
|
||||
} else if (document.documentElement.mozRequestFullScreen) {
|
||||
document.mozCancelFullScreen();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 打开小窗口
|
||||
*
|
||||
* @param url
|
||||
* @param title
|
||||
* @param w
|
||||
* @param h
|
||||
*/
|
||||
export const openWindow = (url, title, w, h) => {
|
||||
// Fixes dual-screen position Most browsers Firefox
|
||||
const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left;
|
||||
const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top;
|
||||
|
||||
const width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
|
||||
const height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;
|
||||
|
||||
const left = ((width / 2) - (w / 2)) + dualScreenLeft;
|
||||
const top = ((height / 2) - (h / 2)) + dualScreenTop;
|
||||
const newWindow = window.open(url, title, 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=yes, copyhistory=no, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left);
|
||||
|
||||
// Puts focus on the newWindow
|
||||
if (window.focus) {
|
||||
newWindow.focus()
|
||||
}
|
||||
};
|
@ -0,0 +1,164 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<el-col :span="4" class="header_item">
|
||||
<img class="logo" src="/images/logo/logo.png">
|
||||
</el-col>
|
||||
<el-col :span="16" class="header_item">
|
||||
<el-menu class="menu"
|
||||
:default-active="this.$route.path"
|
||||
mode="horizontal"
|
||||
:router=true>
|
||||
<el-menu-item index="/home"><span class="el-icon-menu"/>首页</el-menu-item>
|
||||
<el-menu-item index="/things">物联</el-menu-item>
|
||||
<el-menu-item index="/template">模板</el-menu-item>
|
||||
<el-menu-item index="/now">实时</el-menu-item>
|
||||
<el-menu-item index="/history">历史</el-menu-item>
|
||||
<el-menu-item index="/alarm">报警</el-menu-item>
|
||||
<el-menu-item index="/label">标签</el-menu-item>
|
||||
<el-menu-item index="/picture">图片</el-menu-item>
|
||||
<el-menu-item index="/video">视频</el-menu-item>
|
||||
<el-menu-item index="/setting">设置</el-menu-item>
|
||||
<el-menu-item index="/help">帮助</el-menu-item>
|
||||
<el-menu-item index="/about">关于</el-menu-item>
|
||||
</el-menu>
|
||||
</el-col>
|
||||
<el-col :span="2" class="header_item">
|
||||
<el-badge :value="12" :max="99" class="badge_item" type="primary">
|
||||
<span class="span_small" @click="handleMessage">消息</span>
|
||||
</el-badge>
|
||||
</el-col>
|
||||
<el-col :span="2" class="header_item">
|
||||
<el-dropdown class="avatar_item" @command="handleCommand">
|
||||
<span class="el-dropdown-link">
|
||||
<el-avatar>
|
||||
<img src="/images/common/avatar.png">
|
||||
</el-avatar>
|
||||
</span>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item command="profile">个人信息</el-dropdown-item>
|
||||
<el-dropdown-item command="setting" divided>设置</el-dropdown-item>
|
||||
<el-dropdown-item command="about">关于</el-dropdown-item>
|
||||
<el-dropdown-item command="logout" divided>退出登录</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
<span class="span_small avatar">管理员</span>
|
||||
</el-col>
|
||||
</div>
|
||||
<div class="body">
|
||||
<el-scrollbar style="height: 100%;">
|
||||
<router-view/>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
created() {
|
||||
},
|
||||
methods: {
|
||||
handleMessage() {
|
||||
this.$message('click on message');
|
||||
},
|
||||
handleCommand(command) {
|
||||
this.$message('click on item ' + command);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
body {
|
||||
margin: 0;
|
||||
min-width: 1366px;
|
||||
min-height: 768px;
|
||||
}
|
||||
|
||||
.container {
|
||||
color: #2c3e50;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-family: 'Avenir', Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
.header {
|
||||
top: 0px;
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
border-bottom: 1px solid #dcdfe6;
|
||||
}
|
||||
|
||||
.header_item {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 60px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.menu {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
border-bottom: none !important;
|
||||
}
|
||||
|
||||
.menu .el-menu-item {
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.badge_item {
|
||||
top: 25px;
|
||||
cursor: pointer;
|
||||
margin-right: 40px;
|
||||
}
|
||||
|
||||
.span_small {
|
||||
color: #909399;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.span_small.avatar {
|
||||
margin: 20px 10px;
|
||||
}
|
||||
|
||||
.avatar_item {
|
||||
top: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.body {
|
||||
top: 65px;
|
||||
bottom: 5px;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
|
||||
.el-scrollbar__wrap {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.view {
|
||||
top: 1px;
|
||||
bottom: 0px;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.operator {
|
||||
text-align: center;
|
||||
margin: 5px 0px;
|
||||
}
|
||||
|
||||
.page {
|
||||
right: 1px;
|
||||
bottom: 1px;
|
||||
position: absolute !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
@ -0,0 +1,105 @@
|
||||
<template>
|
||||
<div class="login-container">
|
||||
<div class="login-weaper animated bounceInDown">
|
||||
<div class="login-left">
|
||||
<img class="img" src="/images/logo/logo-white.png">
|
||||
</div>
|
||||
<div class="login-border">
|
||||
<div class="login-main">
|
||||
<h4 class="login-title">
|
||||
登录 DC3 Web UI
|
||||
</h4>
|
||||
<el-form class="login-form"
|
||||
status-icon
|
||||
:rules="loginRules"
|
||||
ref="loginForm"
|
||||
:model="loginForm"
|
||||
label-width="0">
|
||||
<el-form-item prop="name">
|
||||
<el-input size="small"
|
||||
@keyup.enter.native="handleLogin"
|
||||
v-model="loginForm.name"
|
||||
auto-complete="off"
|
||||
placeholder="请输入用户名">
|
||||
<i slot="prefix" class="el-icon-user"/>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<el-input size="small"
|
||||
@keyup.enter.native="handleLogin"
|
||||
:type="passwordType"
|
||||
v-model="loginForm.password"
|
||||
auto-complete="off"
|
||||
placeholder="请输入密码">
|
||||
<i class="el-icon-view el-input__icon" slot="suffix" @click="showPassword"/>
|
||||
<i slot="prefix" class="el-icon-lock"/>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary"
|
||||
size="small"
|
||||
@click.native.prevent="handleLogin"
|
||||
class="login-submit">登录
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<particles></particles>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import particles from "@/components/particles/particles";
|
||||
|
||||
export default {
|
||||
name: "login",
|
||||
components: {particles},
|
||||
data() {
|
||||
return {
|
||||
loginForm: {
|
||||
name: "pnoker",
|
||||
password: "dc3dc3dc3"
|
||||
},
|
||||
loginRules: {
|
||||
name: [
|
||||
{required: true, message: "请输入用户名", trigger: "blur"}
|
||||
],
|
||||
password: [
|
||||
{required: true, message: "请输入密码", trigger: "blur"},
|
||||
{min: 1, message: "密码长度最少为6位", trigger: "blur"}
|
||||
]
|
||||
},
|
||||
passwordType: "password"
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
showPassword() {
|
||||
this.passwordType === ""
|
||||
? (this.passwordType = "password")
|
||||
: (this.passwordType = "");
|
||||
},
|
||||
handleLogin() {
|
||||
this.$refs.loginForm.validate(valid => {
|
||||
if (valid) {
|
||||
const loading = this.$loading({
|
||||
lock: true,
|
||||
text: '登录中,请稍后。。。',
|
||||
spinner: "el-icon-loading"
|
||||
});
|
||||
this.$store.dispatch("GenerateToken", this.loginForm).then(() => {
|
||||
this.$router.push({path: '/'});
|
||||
loading.close();
|
||||
}).catch(() => {
|
||||
loading.close()
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "~@/assets/styles/login.scss";
|
||||
</style>
|
@ -1,5 +1,17 @@
|
||||
module.exports = {
|
||||
publicPath: './',
|
||||
lintOnSave: true,
|
||||
productionSourceMap: false
|
||||
}
|
||||
productionSourceMap: false,
|
||||
devServer: {
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: 'http://localhost:8400',
|
||||
changeOrigin: true,
|
||||
ws: true,
|
||||
pathRewrite: {
|
||||
'^/api': ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|