Compare commits

..

2 Commits

Author SHA1 Message Date
wuyize 8db1162613 实现登录 2022-06-29 15:12:44 +08:00
wuyize 0ff9554a38 实现登录页 2022-06-29 14:04:44 +08:00
15 changed files with 1307 additions and 218 deletions

876
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -9,6 +9,7 @@
"dependencies": {
"@element-plus/icons": "^0.0.11",
"axios": "^0.24.0",
"blueimp-md5": "^2.19.0",
"core-js": "^3.6.5",
"element-plus": "^1.2.0-beta.5",
"moment": "^2.29.1",
@ -25,6 +26,7 @@
"@vue/compiler-sfc": "^3.0.0",
"sass": "^1.27.0",
"sass-loader": "^10.0.4",
"svg-sprite-loader": "^6.0.11",
"typescript": "~4.1.5",
"vue-cli-plugin-element-plus": "~0.0.13"
},

View File

@ -1,10 +1,11 @@
<!DOCTYPE html>
<html lang="">
<html lang="zh-CN">
<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 %>logo.ico">
<link rel="stylesheet" href="<%= BASE_URL %>reset.css">
<title>项目管理系统</title>
</head>
<body>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 963 B

22
public/reset.css Normal file
View File

@ -0,0 +1,22 @@
@charset "utf-8";
body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td{padding:0;margin:0; list-style-type:none;}
body,button,input,select,textarea{
}
table{border-collapse:collapse;border-spacing:0;}
caption,th{text-align:left;}
fieldset,img{border:none;}
ul,ol{list-style:none;}
h1,h2,h3,h4,h5,h6{}
input,button,textarea,select{vertical-align:middle;}
address,caption,cite,code,dfn,em,i,b,strong,th,var,optgroup{}
small{}
hr{color:#D1D7DC;background-color:#D1D7DC;border:none;height:1px;}
.left{float:left;}
.right{float:right;}
.clearfix:after {content:'\0020';display:block;height:0;clear:both;visibility:hidden;}
.clearfix{zoom:1;}
a {outline: none; text-decoration: none;}
a:active {star:expression(this.onFocus=this.blur());}
:focus { outline:0; }
a:hover{text-decoration:none}

View File

@ -12,15 +12,20 @@ export default {
#app {
height:100%;
max-height: 100%;
width: 100%;
max-width: 100%;
}
html{
height:100%;
max-height: 100%;
width: 100%;
max-width: 100%;
}
body{
height: 100%;
max-height: 100%;
width: 100%;
max-width: 100%;
margin:0;
padding:0;
}

View File

@ -0,0 +1,8 @@
// 获取当前目录所有为.svg的文件
const req = require.context('./', false, /\.svg$/)
// 解析获取的.svg文件的文件名称并返回
const requireAll = (requireContext) =>{
return requireContext.keys().map(requireContext)
}
requireAll(req)

20
src/assets/icons/logo.svg Normal file
View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<style type="text/css">
.st0{fill:#409EFF;}
</style>
<path class="st0" d="M69.8,0h372.4C480.7,0,512,31.3,512,69.8v372.4c0,38.6-31.3,69.8-69.8,69.8H69.8C31.3,512,0,480.7,0,442.2V69.8
C0,31.3,31.3,0,69.8,0C69.8,0,69.8,0,69.8,0z M318.2,394.7c3.3,0.2,6.2-2.4,6.4-5.7c0-0.2,0-0.5,0-0.7v-97.1
c0.7-26.2-19.5-48.3-45.6-49.9h-48.1c-26.2,1.6-46.3,23.7-45.5,49.9v97.1c-0.2,3.3,2.4,6.2,5.7,6.4c0.2,0,0.5,0,0.7,0L318.2,394.7
L318.2,394.7z M157.8,394.7c3.3,0.2,6.1-2.3,6.3-5.6c0-0.3,0-0.5,0-0.8V287.2c0.6-1.8,0.1-3.8-1.2-5.2c-1.1-1.3-2.8-2.1-4.5-1.9
h-19.5c-20.9,0.2-37.7,17-38,37.9v70.1c-0.2,3.3,2.4,6.2,5.7,6.4c0.2,0,0.4,0,0.6,0h50.7L157.8,394.7L157.8,394.7z M402.7,394.7
c3.3,0.2,6.2-2.4,6.4-5.7c0-0.2,0-0.5,0-0.7V318c0.1-21.1-16.9-38.3-38-38.4c0,0,0,0,0,0h-19.5c-1.3,0-3.8,0.6-4.5,1.9
c-0.8,1.6-1.2,3.4-1.2,5.2v101.1c-0.3,3.3,2.2,6.1,5.5,6.4c0.3,0,0.5,0,0.8,0L402.7,394.7L402.7,394.7z M365.4,270.1
c24.8,0.4,45.2-19.4,45.6-44.3c0.4-24.8-19.4-45.2-44.3-45.6c-24.8-0.4-45.2,19.4-45.6,44.3c0,0.2,0,0.4,0,0.7
c-0.3,24.5,19.3,44.6,43.8,44.9C365.1,270.1,365.2,270.1,365.4,270.1L365.4,270.1z M145.8,270.1c24.5,0,44.3-19.8,44.3-44.3
c0-0.2,0-0.5,0-0.7c0.3-24.5-19.2-44.5-43.7-44.9c-24.5-0.3-44.5,19.2-44.9,43.7c0,0.4,0,0.8,0,1.2c-0.4,24.5,19.2,44.6,43.6,44.9
C145.4,270.1,145.6,270.1,145.8,270.1L145.8,270.1z M254.9,231c31.5-0.1,57-25.7,57-57.2c0-0.1,0-0.3,0-0.4c0-31.5-25.5-57-56.9-57
s-57,25.5-57,56.9c0,0,0,0,0,0c-0.2,31.6,25.2,57.4,56.7,57.6C254.8,231,254.8,231,254.9,231L254.9,231z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

19
src/assets/icons/quit.svg Normal file
View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 17 19" style="enable-background:new 0 0 17 19;" xml:space="preserve">
<style type="text/css">
.st0{fill:currentColor;}
</style>
<g transform="matrix(1 0 0 1 -326 -52 )">
<path class="st0" d="M342.1,58.3c0.6,1.2,0.9,2.5,0.9,3.9c0,1.2-0.2,2.3-0.7,3.4c-0.5,1.1-1.1,2-1.8,2.8c-0.8,0.8-1.7,1.4-2.7,1.9
c-1,0.5-2.1,0.7-3.3,0.7s-2.3-0.2-3.3-0.7c-1-0.5-2-1.1-2.7-1.9c-0.8-0.8-1.4-1.7-1.8-2.8c-0.5-1.1-0.7-2.2-0.7-3.4
c0-1.4,0.3-2.7,0.9-3.9c0.6-1.2,1.4-2.3,2.5-3.1c0.3-0.2,0.7-0.3,1.1-0.3c0.4,0.1,0.7,0.2,0.9,0.6c0.2,0.3,0.3,0.7,0.3,1.1
c-0.1,0.4-0.2,0.7-0.5,1c-0.7,0.6-1.3,1.3-1.7,2.1s-0.6,1.7-0.6,2.6c0,0.8,0.1,1.5,0.4,2.3c0.3,0.7,0.7,1.3,1.2,1.9
c0.5,0.5,1.1,0.9,1.8,1.3c0.7,0.3,1.4,0.5,2.2,0.5s1.5-0.2,2.2-0.5c0.7-0.3,1.3-0.7,1.8-1.3c0.5-0.5,0.9-1.1,1.2-1.9
c0.3-0.7,0.4-1.5,0.4-2.3c0-0.9-0.2-1.8-0.6-2.6s-1-1.5-1.7-2.1c-0.3-0.2-0.5-0.6-0.5-1c-0.1-0.4,0-0.8,0.3-1.1
c0.2-0.3,0.5-0.5,0.9-0.6c0.4-0.1,0.7,0,1.1,0.3C340.7,56.1,341.5,57.1,342.1,58.3z M335.5,52.4c0.3,0.3,0.4,0.6,0.4,1v7.3
c0,0.4-0.1,0.7-0.4,1c-0.3,0.3-0.6,0.4-1,0.4s-0.7-0.1-1-0.4c-0.3-0.3-0.4-0.6-0.4-1v-7.3c0-0.4,0.1-0.7,0.4-1s0.6-0.4,1-0.4
S335.2,52.1,335.5,52.4z"/>
</g>
</svg>

View File

@ -0,0 +1,35 @@
<template>
<svg :class="svgClass" aria-hidden="true">
<use :xlink:href="iconName"></use>
</svg>
</template>
<script>
import { computed } from "@vue/reactivity";
export default {
name: "baseSvgIcon",
props: {
iconClass: { type: String },
className: { type: String },
},
setup(props) {
const iconName = computed(() => {
return props.iconClass ? `#icon-${props.iconClass}` : "#icon";
});
const svgClass = computed(() => {
return props.className ? "svg-icon " + props.className : "svg-icon";
});
return { iconName, svgClass };
},
};
</script>
<style scoped lang="scss">
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
</style>

View File

@ -4,6 +4,9 @@ import router from './router'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import zhCn from 'element-plus/es/locale/lang/zh-cn'
import '@/assets/icons'
const app = createApp(App)
import SvgIcon from '@/components/svgIcon.vue'
app.component('svg-icon', SvgIcon)
app.use(ElementPlus, {locale: zhCn,}).use(router).mount('#app')

View File

@ -1,3 +1,3 @@
const baseUrl = "http://localhost:8090/"
//const baseUrl = "http://192.168.31.113:8090/"
//const baseUrl = "http://localhost:8090/"
const baseUrl = "http://36.5.61.1:8081/"
export default baseUrl;

View File

@ -1,7 +1,43 @@
<template>
<div class="home">
<div>项目管理</div>
<router-view></router-view>
<div class="home" style="display: flex; flex-direction: row; background-color: #F2F3F5 ">
<el-menu style="width: 260px;"
default-active="1">
<div
style="width: 100%;height: 60px;margin: 30px 0 20px 20px; display: flex; flex-direction: row; align-items: center">
<svg-icon style="width: 52px;height: 52px;margin: 10px" icon-class="logo"></svg-icon>
<p style="font-family: 'Segoe UI',sans-serif;font-size: 20px;font-weight: bold;color: #606266">项目<br/>管理系统</p>
</div>
<el-menu-item index="1">
<span>在途项目</span>
</el-menu-item>
<el-menu-item index="2">
<span>已结项项目</span>
</el-menu-item>
</el-menu>
<div style="flex: 1; display: flex; flex-direction: column;">
<div style="height: 60px; margin: 30px 30px 30px 30px; background-color: white; border-radius: 10px;
display: flex; flex-direction: row; align-items: center;justify-content: space-between">
<div @click="logout" class="div-quitButton">
<svg-icon style="width: 17px;height: 19px;" icon-class="quit" class-name="icon-quit"></svg-icon>
</div>
<div style="margin: 0 30px 0 30px; ;
display: flex; flex-direction: row-reverse; align-items: center">
<div style="width: 42px;height: 42px; background-color: #409EFF; border-radius: 21px;
display: flex; justify-content: center;align-items: center;">
<span style="color: white">{{ staffName[0] }}</span>
</div>
<div style="height: 100%; margin-right: 10px;
display: flex; flex-direction: column;justify-content: center;align-items: flex-end;">
<span
style="color: #606266; font-family: 'Segoe UI',sans-serif;font-size: 14px;font-weight: bold; ">
{{staffName }}</span>
<span style="color: #606266; font-family: 'Segoe UI',sans-serif;font-size: 12px;">{{ staffUsername }}</span>
</div>
</div>
</div>
<div style="width: 100%;flex: 1;">
<div id="" class="tableBar">
<table cellspacing="" cellpadding="">
<tr>
@ -14,16 +50,18 @@
<th>操作</th>
</tr>
<tr v-for="item in tableData.list">
<td style="color: #409EFF;">{{item.name}}</td>
<td>{{item.price + '万'}}</td>
<td>{{item.important}}</td>
<td>{{item.classification}}</td>
<td>{{item.type}}</td>
<td style="color: #409EFF;">{{ item.name }}</td>
<td>{{ item.price + '万' }}</td>
<td>{{ item.important }}</td>
<td>{{ item.classification }}</td>
<td>{{ item.type }}</td>
<td>
<el-progress :text-inside="true" :stroke-width="18" :status="item.schedule === 100 ? 'success' : ''"
:percentage="item.schedule"></el-progress>
</td>
<td><button type="button">结项</button></td>
<td>
<button type="button">结项</button>
</td>
</tr>
</table>
<!-- 分页 -->
@ -39,6 +77,9 @@
</el-pagination>
</div>
</div>
</div>
</div>
</template>
<script setup>
@ -47,16 +88,17 @@
// @ is an alias to /src
import request from "@/utils/request";
import router from "../router";
export default {
name: 'Home',
props: ['tableData'],
components: {
},
components: {},
data() {
return {
staffName: '刘金龙',
staffUsername: 'liujinlong',
tableData: {
count: 100,
currentPage: 1,
@ -149,45 +191,62 @@ export default {
},
methods: {
logout() {
request({
url: 'staff/logout',
method: 'post',
}).then(response => {
router.push({path: '/login'})
}).catch(function (error) {
console.log(error)
})
},
//
handleSizeChange(val){
handleSizeChange(val) {
},
//
handleCurrentChange(val){
handleCurrentChange(val) {
},
}
}
</script>
<style>
.home {
.home {
height: 100%;
max-height: 100%;
}
width: 100%;
max-width: 100%;
}
.tableBar {
.tableBar {
width: 1000px;
}
}
.tableBar table {
.tableBar table {
width: 100%;
border-bottom: 1px solid red;
border-collapse: collapse;
}
}
.tableBar table tr th {
.tableBar table tr th {
font-weight: bolder;
}
}
.tableBar table tr {
.tableBar table tr {
height: 40px;
line-height: 40px;
border-bottom: 1px solid #ddd;
text-align: center;
}
}
.tableBar table button {
.tableBar table button {
color: #FFF;
background-color: #409EFF;
border-color: #409EFF;
@ -195,6 +254,27 @@ export default {
border: none;
border-radius: 5px;
font-size: 14px;
}
}
.icon-quit {
color: #606266;
}
div.div-quitButton {
margin-left: 10px;
width: 40px;
height: 40px;
display: flex;
justify-content: center;
align-items: center;
}
div.div-quitButton:hover {
cursor: pointer;
}
div.div-quitButton:hover > .icon-quit {
color: #409EFF;
}
</style>

View File

@ -1,7 +1,16 @@
<template>
<el-form class="login-box" ref="formRef" :model="loginForm" label-width="auto">
<h3 class="login-title">登录</h3>
<div class="background">
<div style="width: 848px;height: 456px;display: flex;flex-direction: row;background-color: white;border-radius: 6px;">
<div style="width: 50%;height: 100%;background-color: #ebf0f4;border-radius: 6px 0 0 6px;
display: flex; flex-direction: column;justify-content: center;align-items: center">
<img style="width: 94%" src="../assets/login.png">
</div>
<div style="width: 50%;height: 100%;display: flex;flex-direction: column; justify-content: center;align-items: stretch">
<div style="margin: 40px;
display: flex; flex-direction: column;justify-content: center">
<p style="margin-bottom: 10px;font-family: 'Segoe UI',sans-serif;font-size: 40px;font-weight: bold;">登录</p>
<p style="margin-bottom: 20px;font-family: 'Segoe UI',sans-serif;font-size: 14px;">欢迎回来请登录以使用项目管理系统</p>
<el-form style="" ref="formRef" :model="loginForm" label-width="auto">
<el-form-item>
<el-input v-model="loginForm.username" placeholder="用户名" :prefix-icon="User"></el-input>
</el-form-item>
@ -9,11 +18,14 @@
<el-input v-model="loginForm.password" placeholder="密码" :prefix-icon="Key"
type="password" show-password></el-input>
</el-form-item>
<el-alert v-if="showAlert" title="用户名或密码错误" type="error" show-icon @close="showAlert=false" style="margin-bottom: 16px"> </el-alert>
<el-form-item>
<el-button type="primary" @click="onSubmit"></el-button>
</el-form-item>
<el-alert v-if="showAlert" title="用户名或密码错误" type="error" show-icon @close="showAlert=false"
style="margin-bottom: 16px"></el-alert>
</el-form>
<el-button type="primary" @click="onSubmit"></el-button>
</div>
</div>
</div>
</div>
</template>
<script setup>
@ -22,6 +34,7 @@ import {reactive, ref} from 'vue'
import request from '@/utils/request'
import router from '@/router'
import baseUrl from "@/utils/baseUrl";
import md5 from 'blueimp-md5'
const axios = require("axios");
@ -34,20 +47,19 @@ const loginForm = reactive({
console.log(localStorage.getItem('token'))
const onSubmit = () => {
let param = new FormData()
param.append('id', loginForm.username.trim())
param.append('password', loginForm.password.trim())
axios.post(baseUrl+'api/login', param).then(function (response) {
let param = {
staffUsername: loginForm.username.trim(),
staffPassword: md5(loginForm.password.trim())
}
axios.post(baseUrl + 'staff/login', param).then(function (response) {
if (response.data === 'error') {
console.log(response.data)
showAlert.value=true
showAlert.value = true
} else {
localStorage.setItem('seller_id', param.get('id'))
localStorage.setItem('token', response.data)
console.log(response.data)
localStorage.setItem('token', response.data.data.Token)
localStorage.setItem('expire', new Date().getTime().toString())
if(param.get('id')==='admin')
router.push({path: '/TrainManage'})
else
router.push({path: '/'})
}
@ -63,30 +75,14 @@ export default {
}
</script>
<style>
body {
div.background {
width: 100%;
height: 100%;
}
.login-box {
border: 1px solid #DCDFE6;
width: 350px;
margin: 180px auto;
padding: 35px 35px 15px 35px;
border-radius: 5px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
box-shadow: 0 0 25px #909399;
}
.el-form-item__content{
background: url(../assets/login-bg.png) center no-repeat;
background-size: cover;
display: flex;
justify-content: center;
align-items: center;
}
.login-title {
text-align: center;
margin: 0 auto 40px auto;
color: #303133;
}
</style>

22
vue.config.js Normal file
View File

@ -0,0 +1,22 @@
const path = require('path')
function resolve(dir) {
return path.join(__dirname, '.', dir)
}
module.exports = {
chainWebpack: config => {
config.module.rules.delete("svg"); // 重点删除默认配置中处理svg,
config.module
.rule('svg-sprite-loader')
.test(/\.svg$/)
.include
.add(resolve('src/assets/icons')) // 处理svg目录
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
})
},
};