Vue初始项目结构

V u e 初 始 项 目 结 构 Vue初始项目结构 Vue

在这里插入图片描述

一 assets

二 components

Login.vue

<template>
  <div class="login-container">
    <el-row>
      <el-col :span="4" :offset="10">
        <h1 class='page-title'>管理系统</h1>
        <el-form ref="loginForm" :model="loginForm" label-width="80px" class='login-form' :rules="rules">
          <el-form-item label="手机" prop="username">
            <el-input v-model="loginForm.username"></el-input>
          </el-form-item>
          <el-form-item label="密码" prop="password">
            <el-input v-model="loginForm.password" type="password"></el-input>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="onSubmit">登录</el-button>
          </el-form-item>
        </el-form>
      </el-col>
    </el-row>
  </div>
</template>

<script>
import {Button,Row,Col,Form,Input,FormItem} from "element-ui"
// import axios from "axios"
export default {
  name: 'Login',
  data(){
    let validateTel = (rule, value, callback) => {
      if(!value.match(/1[3456789]\d{9}/)){
        callback(new Error("请输入正确的手机号码!"))
      }else{
        callback()
      }
    }
    return {
      loginForm: {
        username: "",
        password: ""
      },
      rules: {
        username: [
          {required: true,message: "请输入手机号码!",trigger: "blur"},
          {validator: validateTel,trigger: "blur"}
        ],
        password: [
          {required: true,message: "请输入密码!",trigger: "blur"},
          {min: 6, max: 20,message: "密码字符应该在6-20之间!",trigger: "blur"},
        ]
      }
    }
  },
  components: {
    [Button.name]: Button,
    [Row.name]: Row,
    [Col.name]: Col,
    [Form.name]: Form,
    [Input.name]: Input,
    [FormItem.name]: FormItem
  },
  methods: {
    onSubmit(){
      this.$refs['loginForm'].validate(valid => {
        if(!valid){
          console.log("验证失败!")
          return
        }
        const params = {
          username: this.loginForm.username,
          password: this.loginForm.password
        }
        this.$loading.show()
        this.$http.login(params).then(res => {
          const data = res.data;
          const token = data.token;
          const user = data.user;
          this.$auth.setUserToken(user,token)
          this.$router.push("/")
          this.$loading.hide()
        }).catch(err => {
          console.log(err);
          this.$loading.hide()
        })
      })
    }
  }
}
</script>

<style lang="scss">
body{
  background-color: #eee;
}
.login-container{
  padding-top: 80px;
  .page-title{
    text-align: center;
  }
  .login-form{
    padding-top: 40px;
  }
}
</style>

Frame.vue

<template>
<div class="frame">
  <el-container class="frame-container">
    <el-header class="header">
      <a href="/" class='brand'><strong>知了</strong>商户平台</a>
      <div class="header-content">
        <div class="greet">欢迎,{{$auth.user.username}}</div>
        <div class="signout" @click="onLogout">退出登录</div>
      </div>
    </el-header>
    <el-container>
      <el-aside width="200px" class="aside">
        <el-row class="menu-row">
          <el-col :span="24">
            <el-menu
              default-active="/"
              background-color="#545c64"
              class="el-menu"
              active-text-color="#fff"
              text-color="#ddd"
              :router="true"
              >
              <el-menu-item index="/">
                <i class="el-icon-s-home"></i>
                <span slot="title">首页</span>
              </el-menu-item>
              <el-menu-item index="/merchant">
                <i class="el-icon-menu"></i>
                <span slot="title">商家</span>
              </el-menu-item>
              <el-menu-item index="/user">
                <i class="el-icon-user-solid"></i>
                <span slot="title">用户</span>
              </el-menu-item>
              <el-menu-item index="/order">
                <i class="el-icon-s-order"></i>
                <span slot="title">订单</span>
              </el-menu-item>
            </el-menu>
          </el-col>
        </el-row>
      </el-aside>
      <el-container>
        <el-main class="main">
          <router-view></router-view>
        </el-main>
        <el-footer class="footer">这是Footer</el-footer>
      </el-container>
    </el-container>
  </el-container>
</div>
</template>

<script type="text/ecmascript-6">
import {Container,Header,Aside,Main,Footer,Row,Col,Menu,MenuItem} from "element-ui"
export default {
  name: "Frame",
  data() {
    return {}
  },
  components: {
    [Container.name]: Container,
    [Header.name]: Header,
    [Aside.name]: Aside,
    [Main.name]: Main,
    [Footer.name]: Footer,
    [Row.name]: Row,
    [Col.name]: Col,
    [Menu.name]: Menu,
    [MenuItem.name]: MenuItem
  },
  methods: {
    onLogout(){
      // JWToken
      this.$auth.clearUserToken()
      this.$router.replace("/login")
    }
  }
}
</script>

<style scoped lang='scss'>
.frame-container{
  height: 100vh;
  .header{
    height: 200px;
    background: #00a65a;
    display: flex;
    .brand{
      width: 200px;
      margin-left: -20px;
      background-color:#008d4c;
      font-size: 20px;
      color: #fff;
      display:flex;
      justify-content: center;
      align-items: center;
    }
    .header-content{
      flex: 1;
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-left: 20px;
      color: #fff;
      .signout{
        cursor: pointer;
      }
    }
  }
  .aside{
    background-color: #545c64;
    .el-menu{
      .is-active{
        background-color: #434a50!important;
      }
    }
  }
  .main{
    // background: salmon;
  }
  .footer{
    background: gray;
  }
}
</style>

<style scoped>
.aside >>> .el-menu{
  border-right: none;
}
</style>

三 styles

init.css

a,
abbr,
acronym,
address,
applet,
article,
aside,
audio,
b,
big,
blockquote,
body,
canvas,
caption,
center,
cite,
code,
dd,
del,
details,
dfn,
div,
dl,
dt,
em,
embed,
fieldset,
figcaption,
figure,
footer,
form,
h1,
h2,
h3,
h4,
h5,
h6,
header,
hgroup,
html,
i,
iframe,
img,
ins,
kbd,
label,
legend,
li,
mark,
menu,
nav,
object,
ol,
output,
p,
pre,
q,
ruby,
s,
samp,
section,
small,
span,
strike,
strong,
sub,
summary,
sup,
table,
tbody,
td,
tfoot,
th,
thead,
time,
tr,
tt,
u,
ul,
var,
video {
  margin: 0;
  padding: 0;
  border: 0;
  font-family: "PingFangSC-Regular", Hiragino Sans GB, Arial, Helvetica, "\5B8B\4F53", sans-serif;
}

四 utils

4.1 auth.js

const USER_KEY = "USER_KEY"
const TOKEN_KEY = "JWT_TOKEN_KEY"

class Auth{
  constructor(){
    this.token = null
    this.user = null
    this.token = localStorage.getItem(TOKEN_KEY)
    const userJson = localStorage.getItem(USER_KEY)
    if(userJson){
      this.user = JSON.parse(userJson)
    }
  }

  static getInstance(){
    if(!this._instance){
      this._instance = new Auth()
    }
    return this._instance
  }
  
  setUserToken(user,token){
    this.user = user
    this.token = token
    localStorage.setItem(USER_KEY,JSON.stringify(user))
    localStorage.setItem(TOKEN_KEY,token)
  }

  clearUserToken(){
    this.user = null;
    this.token = null;
    localStorage.removeItem(USER_KEY)
    localStorage.removeItem(TOKEN_KEY)
  }

  get is_authed(){
    if(this.user && this.token){
      return true
    }else{
      return false
    }
  }
}


export default Auth.getInstance()


在这里插入图片描述
保证始终面对的是一个对象

4.2http网络封装

import axios from "axios"
import auth from "./auth"
import router from "../routes"

const BASE_URL = 'http://127.0.0.1:8000'

class Http {
  constructor() {
    this.http = axios.create({
      baseURL: BASE_URL,
      timeout: 1000
    });

    // 请求之前的拦截器,用来设置JWT
    this.http.interceptors.request.use(config => {
      const token = auth.token
      if(token){
        config.headers.common.Authorization = "JWT " + token
      }
      return config
    })

    // 响应之后的拦截器
    this.http.interceptors.response.use(response => {
      return response
    },err => {
      // auth.clearUserToken()
      // router.replace("/login")
      console.log(err.response)
      console.log("==========")
      return Promise.reject(err)
    })
  }

  login(params){
    const url = "/cms/login"
    return this.http.post(url,params)
  }

  getMerchants(page=1){
    const url = "/cms/merchant?page="+page
    return this.http.get(url)
  }

  addMerchant(data){
    const url = "/cms/merchant"
    return this.http.post(url,data)
  }

  getMerchant(merchant_id){
    const url = "/cms/merchant/" + merchant_id
    return this.http.get(url)
  }

  updateMerchant(merchant_id,data){
    const url = "/cms/merchant/" + merchant_id
    return this.http.put(url,data)
  }

  getCategories(merchant_id){
    const url = "/cms/category/merchant/"+merchant_id
    return this.http.get(url)
  }

  updateCategory(category_id,data){
    const url = "/cms/category/" + category_id
    return this.http.put(url,data)
  }

  addCategory(data){
    const url = "/cms/category"
    return this.http.post(url,data)
  }

  deleteCategory(category_id){
    const url = "/cms/category/" + category_id
    return this.http.delete(url)
  }

  addGoods(data){
    const url = "/cms/goods"
    return this.http.post(url,data)
  }
}

export default new Http()

4.3 loading.js


import {Loading} from "element-ui"

class MTLoading{
  show(text=null){
    this.loading = Loading.service({
      fullscreen: true,
      background: "rgba(0, 0, 0, 0.7)",
      spinner: "el-icon-loading",
      text: text?text:"正在加载中..."
    })
  }

  hide(){
    if(this.loading){
      this.loading.close()
    }
  }
}

export default new MTLoading()

4.4 message.js

import {
  Message
} from "element-ui"

class MTMessage {
  constructor() {
    this.config = {
      showClose: true,
      duration: 2000
    }
  }

  show() {
    Message(JSON.parse(JSON.stringify(this.config)))
  }

  success(message = "恭喜!操作成功!") {
    this.config.type = "success"
    this.config.message = message
    this.show()
  }

  info(message = "") {
    this.config.type = 'info'
    this.config.message = message
    this.show()
  }

  warning(message = "") {
    this.config.type = 'warning'
    this.config.message = message
    this.show()
  }

  error(message = "") {
    this.config.type = 'error'
    this.config.message = message
    this.show()
  }
}

const message = new MTMessage()
export default message

五 main.js

import Vue from 'vue'
import App from './App.vue'
import router from "./routes"
import axios from "axios"
import auth from "./utils/auth"
import http from "./utils/http"
import loading from "./utils/loading"
import message from "./utils/message"

Vue.config.productionTip = false
Vue.prototype.$auth = auth
Vue.prototype.$http = http
Vue.prototype.$loading = loading
Vue.prototype.$message = message

new Vue({
  render: h => h(App),
  router
}).$mount('#app')

六 routes.js

import VueRouter from "vue-router"
import Vue from "vue"
import Frame from "./components/Frame"
import Login from "./components/Login"
import Index from "./components/Index"
import Merchant from "./components/Merchant"
import Order from "./components/Order"
import User from "./components/User"
import MerchantDetail from "./components/MerchantDetail"

Vue.use(VueRouter)

const router = new VueRouter({
  routes: [
    {
      path: "/",
      component: Frame,
      children: [
        {path: "",component: Index,name:"index"},
        {path: "merchant",component: Merchant,name: "merchant"},
        {path: "order",component: Order,name:"order"},
        {path: "user",component: User,name: "user"},
        {path: "merchant/detail",component: MerchantDetail,name: "merchant_detail"},
      ]
    },
    {
      path: "/login",
      component: Login,
      name: "login"
    }
  ]
})

export default router
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值