main
			
			
		
		
							parent
							
								
									d86054b091
								
							
						
					
					
						commit
						ed8381de51
					
				
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										53
									
								
								src/App.vue
								
								
								
								
							
							
						
						
									
										53
									
								
								src/App.vue
								
								
								
								
							| 
						 | 
					@ -1,11 +1,62 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <div class="common-layout">
 | 
					  <div class="common-layout">
 | 
				
			||||||
    <el-container>
 | 
					    <el-container>
 | 
				
			||||||
      <el-header>INNcom 清单生成器</el-header>
 | 
					      <el-header v-if="state.showMenu">INNcom 清单生成器</el-header>
 | 
				
			||||||
      <el-main><router-view /></el-main>
 | 
					      <el-main><router-view /></el-main>
 | 
				
			||||||
    </el-container>
 | 
					    </el-container>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					<script>
 | 
				
			||||||
 | 
					import { onUnmounted, reactive } from 'vue'
 | 
				
			||||||
 | 
					import { useRouter } from 'vue-router'
 | 
				
			||||||
 | 
					import { pathMap, localGet } from '@/utils';
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					  name: 'App',
 | 
				
			||||||
 | 
					  setup() {
 | 
				
			||||||
 | 
					    const noMenu = ['/login']
 | 
				
			||||||
 | 
					    const router = useRouter();
 | 
				
			||||||
 | 
					    const state = reactive({
 | 
				
			||||||
 | 
					      showMenu: true,
 | 
				
			||||||
 | 
					      currentPath: '/dashboard'
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    // 监听浏览器原生回退事件
 | 
				
			||||||
 | 
					    if (window.history && window.history.pushState) {
 | 
				
			||||||
 | 
					      history.pushState(null, null, document.URL);
 | 
				
			||||||
 | 
					      window.addEventListener('popstate', () => {
 | 
				
			||||||
 | 
					        if (!localGet('token')) {
 | 
				
			||||||
 | 
					          state.showMenu = false
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }, false);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const unwatch = router.beforeEach((to, from, next) => {
 | 
				
			||||||
 | 
					      if (to.path == '/login') {
 | 
				
			||||||
 | 
					        // 如果路径是 /login 则正常执行
 | 
				
			||||||
 | 
					        next()
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        // 如果不是 /login,判断是否有 token
 | 
				
			||||||
 | 
					        if (!localGet('token')) {
 | 
				
			||||||
 | 
					          // 如果没有,则跳至登录页面
 | 
				
			||||||
 | 
					          next({ path: '/login' })
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          // 否则继续执行
 | 
				
			||||||
 | 
					          next()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      state.showMenu = !noMenu.includes(to.path)
 | 
				
			||||||
 | 
					      state.currentPath = to.path
 | 
				
			||||||
 | 
					      document.title = pathMap[to.name]
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onUnmounted(() => {
 | 
				
			||||||
 | 
					      unwatch();
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					      state
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style scoped>
 | 
					<style scoped>
 | 
				
			||||||
.logo {
 | 
					.logo {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,11 +1,13 @@
 | 
				
			||||||
import axios from "axios";
 | 
					import axios from "axios";
 | 
				
			||||||
 | 
					import { pathMap, localGet, localRemove } from '@/utils';
 | 
				
			||||||
axios.defaults.withCredentials = true;
 | 
					axios.defaults.withCredentials = true;
 | 
				
			||||||
 | 
					import { ElMessage } from "element-plus";
 | 
				
			||||||
 | 
					import router from "@/router/index";
 | 
				
			||||||
// 请求头,headers 信息
 | 
					// 请求头,headers 信息
 | 
				
			||||||
axios.defaults.headers["X-Requested-With"] = "XMLHttpRequest";
 | 
					axios.defaults.headers["X-Requested-With"] = "XMLHttpRequest";
 | 
				
			||||||
axios.defaults.headers = {
 | 
					axios.defaults.headers = {
 | 
				
			||||||
  name: "cc",
 | 
					  name: localGet('name'),
 | 
				
			||||||
  token: "",
 | 
					  token: localGet('token'),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,6 +15,14 @@ axios.defaults.headers = {
 | 
				
			||||||
// 请求拦截器,内部根据返回值,重新组装,统一管理。
 | 
					// 请求拦截器,内部根据返回值,重新组装,统一管理。
 | 
				
			||||||
axios.interceptors.response.use(
 | 
					axios.interceptors.response.use(
 | 
				
			||||||
  (res) => {
 | 
					  (res) => {
 | 
				
			||||||
 | 
					    console.log(111,res);
 | 
				
			||||||
 | 
					    if(res.data.code === 2001) {
 | 
				
			||||||
 | 
					      ElMessage.error(res.data.message || "401 Unauthorized");
 | 
				
			||||||
 | 
					      router.push({ path: "/login" });
 | 
				
			||||||
 | 
					      localRemove('token');
 | 
				
			||||||
 | 
					      localRemove('name');
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    return res.data;
 | 
					    return res.data;
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  (error) => {
 | 
					  (error) => {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@ import { createRouter, createWebHashHistory } from 'vue-router';
 | 
				
			||||||
import Home from '../views/Home.vue';
 | 
					import Home from '../views/Home.vue';
 | 
				
			||||||
import Project from '../views/Project.vue';
 | 
					import Project from '../views/Project.vue';
 | 
				
			||||||
import Room from '../views/Room.vue';
 | 
					import Room from '../views/Room.vue';
 | 
				
			||||||
 | 
					import Login from '../views/Login.vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const routes = [
 | 
					const routes = [
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					@ -13,6 +14,11 @@ const routes = [
 | 
				
			||||||
        name: 'home',
 | 
					        name: 'home',
 | 
				
			||||||
        component: Home
 | 
					        component: Home
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: '/login',
 | 
				
			||||||
 | 
					        name: 'login',
 | 
				
			||||||
 | 
					        component: Login
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        path: '/project',
 | 
					        path: '/project',
 | 
				
			||||||
        name: 'project',
 | 
					        name: 'project',
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,24 @@
 | 
				
			||||||
 | 
					export function localGet(key) {
 | 
				
			||||||
 | 
					  const value = window.localStorage.getItem(key)
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    return JSON.parse(window.localStorage.getItem(key))
 | 
				
			||||||
 | 
					  } catch (error) {
 | 
				
			||||||
 | 
					    return value
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function localSet(key, value) {
 | 
				
			||||||
 | 
					  window.localStorage.setItem(key, JSON.stringify(value))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function localRemove(key) {
 | 
				
			||||||
 | 
					  window.localStorage.removeItem(key)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const pathMap = {
 | 
				
			||||||
 | 
					  login: '登录',
 | 
				
			||||||
 | 
					  home: 'INNcom 清单生成器',
 | 
				
			||||||
 | 
					  project: 'INNcom 清单生成器',
 | 
				
			||||||
 | 
					  room: 'INNcom 清单生成器',
 | 
				
			||||||
 | 
					  weather: 'INNcom 清单生成器',
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -198,7 +198,7 @@ onMounted(() => {
 | 
				
			||||||
    height: 800px;
 | 
					    height: 800px;
 | 
				
			||||||
    overflow: auto;
 | 
					    overflow: auto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ::v-deep>.el-card__body {
 | 
					    :deep(>.el-card__body) {
 | 
				
			||||||
        display: flex;
 | 
					        display: flex;
 | 
				
			||||||
        flex-wrap: wrap;
 | 
					        flex-wrap: wrap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,126 @@
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					    <div class="login-body">
 | 
				
			||||||
 | 
					      <div class="login-container">
 | 
				
			||||||
 | 
					        <div class="head">
 | 
				
			||||||
 | 
					          <div class="name">
 | 
				
			||||||
 | 
					            <div class="title">登录</div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <el-form label-position="top" :rules="rules" :model="ruleForm" ref="loginForm" class="login-form">
 | 
				
			||||||
 | 
					          <el-form-item label="账号" prop="username">
 | 
				
			||||||
 | 
					            <el-input type="text" v-model.trim="ruleForm.username" autocomplete="off"></el-input>
 | 
				
			||||||
 | 
					          </el-form-item>
 | 
				
			||||||
 | 
					          <el-form-item label="密码" prop="password">
 | 
				
			||||||
 | 
					            <el-input type="password" v-model.trim="ruleForm.password" autocomplete="off"></el-input>
 | 
				
			||||||
 | 
					          </el-form-item>
 | 
				
			||||||
 | 
					          <el-form-item>
 | 
				
			||||||
 | 
					            <el-button style="width: 100%" type="primary" @click="submitForm">立即登录</el-button>
 | 
				
			||||||
 | 
					          </el-form-item>
 | 
				
			||||||
 | 
					        </el-form>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </template>
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  <script>
 | 
				
			||||||
 | 
					  import { reactive, ref, toRefs } from 'vue'
 | 
				
			||||||
 | 
					  import myApi from "@/api/myApi.js";
 | 
				
			||||||
 | 
					  import { localSet } from '@/utils';
 | 
				
			||||||
 | 
					  // const bcryptjs = require('bcryptjs')
 | 
				
			||||||
 | 
					  import bcrypt from 'bcryptjs'
 | 
				
			||||||
 | 
					  export default {
 | 
				
			||||||
 | 
					    name: 'Login',
 | 
				
			||||||
 | 
					    setup() {
 | 
				
			||||||
 | 
					      const loginForm = ref(null)
 | 
				
			||||||
 | 
					      const state = reactive({
 | 
				
			||||||
 | 
					        ruleForm: {
 | 
				
			||||||
 | 
					          username: '',
 | 
				
			||||||
 | 
					          password: ''
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        checked: true,
 | 
				
			||||||
 | 
					        rules: {
 | 
				
			||||||
 | 
					          username: [
 | 
				
			||||||
 | 
					            { required: 'true', message: '账户不能为空', trigger: 'blur' }
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					          password: [
 | 
				
			||||||
 | 
					            { required: 'true', message: '密码不能为空', trigger: 'blur' }
 | 
				
			||||||
 | 
					          ]
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      const submitForm = async () => {
 | 
				
			||||||
 | 
					        loginForm.value.validate(async (valid) => {
 | 
				
			||||||
 | 
					          if (valid) {
 | 
				
			||||||
 | 
					            // const res = await myApi.login(param);
 | 
				
			||||||
 | 
					            const encryptedPassword = await bcrypt.hash(state.ruleForm.password, 10);
 | 
				
			||||||
 | 
					            localSet('name', state.ruleForm.username);
 | 
				
			||||||
 | 
					            localSet('token', encryptedPassword);
 | 
				
			||||||
 | 
					            window.location.href = '/';
 | 
				
			||||||
 | 
					          } else {
 | 
				
			||||||
 | 
					            console.log('error submit!!')
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      const resetForm = () => {
 | 
				
			||||||
 | 
					        loginForm.value.resetFields();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        ...toRefs(state),
 | 
				
			||||||
 | 
					        loginForm,
 | 
				
			||||||
 | 
					        submitForm,
 | 
				
			||||||
 | 
					        resetForm
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  </script>
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  <style scoped>
 | 
				
			||||||
 | 
					    .login-body {
 | 
				
			||||||
 | 
					      display: flex;
 | 
				
			||||||
 | 
					      justify-content: center;
 | 
				
			||||||
 | 
					      align-items: center;
 | 
				
			||||||
 | 
					      width: 100%;
 | 
				
			||||||
 | 
					      /* background-color: #fff; */
 | 
				
			||||||
 | 
					      /* background-image: linear-gradient(25deg, #077f7c, #3aa693, #5ecfaa, #7ffac2); */
 | 
				
			||||||
 | 
					      /* background: url('../assets/bg.png') no-repeat; */
 | 
				
			||||||
 | 
					      background-size: 100% 100%;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    .login-container {
 | 
				
			||||||
 | 
					      width: 420px;
 | 
				
			||||||
 | 
					      height: 400px;
 | 
				
			||||||
 | 
					      background-color: #fff;
 | 
				
			||||||
 | 
					      border-radius: 4px;
 | 
				
			||||||
 | 
					      box-shadow: 0px 21px 41px 0px rgba(0, 0, 0, 0.2);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    .head {
 | 
				
			||||||
 | 
					      display: flex;
 | 
				
			||||||
 | 
					      justify-content: center;
 | 
				
			||||||
 | 
					      align-items: center;
 | 
				
			||||||
 | 
					      padding: 40px 0 20px 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    .head img {
 | 
				
			||||||
 | 
					      width: 100px;
 | 
				
			||||||
 | 
					      height: 100px;
 | 
				
			||||||
 | 
					      margin-right: 20px;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    .head .title {
 | 
				
			||||||
 | 
					      font-size: 28px;
 | 
				
			||||||
 | 
					      color: #1BAEAE;
 | 
				
			||||||
 | 
					      font-weight: bold;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    .head .tips {
 | 
				
			||||||
 | 
					      font-size: 12px;
 | 
				
			||||||
 | 
					      color: #999;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    .login-form {
 | 
				
			||||||
 | 
					      width: 70%;
 | 
				
			||||||
 | 
					      margin: 0 auto;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  </style>
 | 
				
			||||||
 | 
					  <style>
 | 
				
			||||||
 | 
					    .el-form--label-top .el-form-item__label {
 | 
				
			||||||
 | 
					      padding: 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    .login-form .el-form-item {
 | 
				
			||||||
 | 
					      margin-bottom: 20px;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  </style>
 | 
				
			||||||
| 
						 | 
					@ -366,7 +366,7 @@ const checkList = reactive([{
 | 
				
			||||||
    >div:first-child {
 | 
					    >div:first-child {
 | 
				
			||||||
        width: 20%;
 | 
					        width: 20%;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ::v-deep .el-card__body {
 | 
					        :deep(.el-card__body) {
 | 
				
			||||||
            display: flex;
 | 
					            display: flex;
 | 
				
			||||||
            flex-direction: column;
 | 
					            flex-direction: column;
 | 
				
			||||||
            height: 95%;
 | 
					            height: 95%;
 | 
				
			||||||
| 
						 | 
					@ -408,7 +408,7 @@ const checkList = reactive([{
 | 
				
			||||||
    >div:nth-child(2) {
 | 
					    >div:nth-child(2) {
 | 
				
			||||||
        width: 79%;
 | 
					        width: 79%;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ::v-deep .el-card__body {
 | 
					        :deep(.el-card__body) {
 | 
				
			||||||
            display: flex;
 | 
					            display: flex;
 | 
				
			||||||
            flex-direction: column;
 | 
					            flex-direction: column;
 | 
				
			||||||
            height: 95%;
 | 
					            height: 95%;
 | 
				
			||||||
| 
						 | 
					@ -507,7 +507,7 @@ const checkList = reactive([{
 | 
				
			||||||
            padding: 5px;
 | 
					            padding: 5px;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ::v-deep .el-textarea__inner {
 | 
					        :deep(.el-textarea__inner) {
 | 
				
			||||||
            height: 80px !important;
 | 
					            height: 80px !important;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue