Vue速成--專案實戰(後臺管理系統)
需要後端伺服器資料的童鞋,私信留言哦~
umall 後臺管理
1.建立專案
vue init webpack umall
2.清空工作
1.assets 清空
2.components 清空
3.router/index.js 刪除helloword相關的
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export default new Router({
routes: [
]
})
4.App.vue重置
3.專案搭建
1.目錄結構
-src
-assets 靜態資源
-css
-js
-components 公共元件
index.js 整合公共元件
-filters 過濾器
index.js 整合過濾器
-pages 路由元件
-home 某個路由元件
home.vue 路由元件
-components 路由元件的子元件
banner.vue
list.vue
-router 路由
index.js
-store 倉庫
index.js 建立倉庫並匯出
mutations.js 根級別下 的state mutations getters
acions.js 根級別下的actions
-modules 模組
-utils 工具類
alert.js 彈框
request.js 資料互動
App.vue 根元件
main.js 入口檔案
2.assets
css /reset.css,在main.js引入
//1.assets
import "./assets/css/reset.css"
3.公共元件 components
components/index.js
import Vue from "vue"
let obj={
}
for(let i in obj){
Vue.component(i,obj[i])
}
4.路由元件的格式
-pages
-home
home.vue
-components
banner.vue
list.vue
-detail
detail.vue
-components
picker.vue
5.資料互動
1.安裝依賴包
npm i axios qs --save
2.配置代理 config/index.js
proxyTable: {
"/api":{
target:"http://localhost:3000",
changeOrigin:true,
pathRewrite:{
"^/api":"http://localhost:3000"
}
}
},
3.utils/request.js
import axios from "axios"
import qs from "qs"
let baseUrl="/api";
//響應攔截
axios.interceptors.response.use(res=>{
console.group("=====本次請求路徑是:"+res.config.url)
console.log(res);
console.groupEnd()
return res;
})
6.過濾器filters
filters/index.js
import Vue from "vue"
let obj={
}
for(let i in obj){
Vue.filter(i,obj[i])
}
7.vuex
1.安裝依賴包
npm i vuex --save
2.目錄搭建
-store 倉庫
index.js 建立倉庫並匯出
mutations.js 根級別下 的state mutations getters
acions.js 根級別下的actions
-modules 模組
3.store/index.js
import Vue from "vue"
import Vuex from "vuex"
Vue.use(Vuex)
import {state,getters,mutations} from "./mutations"
import {actions} from "./actions"
export default new Vuex.Store({
state,
getters,
mutations,
actions,
modules:{
}
})
store/mutations.js
export const state={}
export const mutations={}
export const getters={}
store/actions.js
export const actions={}
4.main.js引入store,並掛到根例項上
//6.vuex
import store from "./store"
new Vue({
el: '#app',
store,
})
8.element-ui
1.安裝依賴包
npm i element-ui --save
2.main.js引入
//7.element-ui
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
3.二次封裝彈框 utils/alert.js
import Vue from "vue"
let vm = new Vue()
export const successAlert = (msg) => {
vm.$message({
message: msg,
type: 'success'
});
}
export const warningAlert = (msg) => {
vm.$message({
message: msg,
type: 'warning'
});
}
4.配置一級路由
1.pages下建立了index 和login元件
2.router/index.js 配置路由規則
export default new Router({
routes: [
{
path:"/login",
component:()=>import("../pages/login/login.vue")
},
{
path:"/",
component:()=>import("../pages/index/index.vue")
}
]
})
3.app.vue 定義路由出口
<div>
<router-view></router-view>
</div>
4.書寫了一個使用者程式碼片段
{
"Print to console": {
"scope": "javascript,typescript,vue",
"prefix": "vue",
"body": [
"<template>",
"<div>",
"<h1>登入</h1>",
"</div>",
"</template>",
"<script>",
"import {mapGetters,mapActions} from \"vuex\"",
"export default {",
"props:[],",
"components:{},",
"data(){",
"return {",
"}",
"},",
"computed:{",
"...mapGetters({",
"})",
"},",
"methods:{",
"...mapActions({",
"})",
"},",
"mounted(){},",
"}",
"</script>",
"<style scoped>",
"</style>"
],
"description": "我的vue"
}
}
5.login.vue
1.html+css
<div class="login">
<div class="box">
<h3 class="center">登入</h3>
<div class="line">
<el-input placeholder="情輸入賬號" clearable></el-input>
</div>
<div class="line">
<el-input placeholder="情輸入密碼" clearable show-password></el-input>
</div>
<div class="center line">
<el-button type="primary" @click="login">登入</el-button>
</div>
</div>
</div>
<style scoped>
.login{
width: 100vw;
height: 100vh;
background: linear-gradient(to right,#553443,#303D60);
position: relative;
}
.box{
width: 400px;
padding: 20px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
background: #ffffff;
border-radius: 20px;
}
.center{
text-align: center;
}
.line{
margin-top: 20px;
}
</style>
6.index.vue
1.貼上布局容器
<el-container class="index">
<el-aside class="left" width="200px">
</el-aside>
<el-container>
<el-header class="header">Header</el-header>
<el-main class="main">
<!-- 二級路由出口 -->
<router-view></router-view>
</el-main>
</el-container>
</el-container>
2.貼上導航
<el-aside class="left" width="200px">
<!-- 左側導航 -->
<!-- 1.background-color -->
<el-menu
default-active="2"
class="el-menu-vertical-demo"
@open="handleOpen"
@close="handleClose"
background-color="#20222a"
text-color="#fff"
active-text-color="#ffd04b"
>
<el-submenu index="1">
<template slot="title">
<i class="el-icon-location"></i>
<span>導航一</span>
</template>
<el-menu-item-group>
<template slot="title">分組一</template>
<el-menu-item index="1-1">選項1</el-menu-item>
<el-menu-item index="1-2">選項2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分組2">
<el-menu-item index="1-3">選項3</el-menu-item>
</el-menu-item-group>
<el-submenu index="1-4">
<template slot="title">選項4</template>
<el-menu-item index="1-4-1">選項1</el-menu-item>
</el-submenu>
</el-submenu>
<el-menu-item index="2">
<i class="el-icon-menu"></i>
<span slot="title">導航二</span>
</el-menu-item>
<el-menu-item index="3" disabled>
<i class="el-icon-document"></i>
<span slot="title">導航三</span>
</el-menu-item>
<el-menu-item index="4">
<i class="el-icon-setting"></i>
<span slot="title">導航四</span>
</el-menu-item>
</el-menu>
</el-aside>
3.el-main 定義二級路由出口
<el-main class="main">
<!-- 二級路由出口 -->
<router-view></router-view>
</el-main>
4.建立二級路由元件
menu 選單管理
role 角色管理
manage 管理員管理
cate 商品分類
specs 商品規格
goods 商品管理
member 會員管理
banner 輪播圖管理
seckill 秒殺活動
5.配置路由規則 router/index.js
//首頁下面的二級路由規則
let indexRoutes = [
{
path: "/menu",
component: () => import("../pages/menu/menu.vue")
},
{
path: "/role",
component: () => import("../pages/role/role.vue")
},
{
path: "/manage",
component: () => import("../pages/manage/manage.vue")
},
{
path: "/cate",
component: () => import("../pages/cate/cate.vue")
},
{
path: "/specs",
component: () => import("../pages/specs/specs.vue")
},
{
path: "/goods",
component: () => import("../pages/goods/goods.vue")
},
{
path: "/member",
component: () => import("../pages/member/member.vue")
},
{
path: "/banner",
component: () => import("../pages/banner/banner.vue")
},
{
path: "/seckill",
component: () => import("../pages/seckill/seckill.vue")
},
]
{
path: "/",
component: () => import("../pages/index/index.vue"),
children: [
{
path: "",
component: () => import("../pages/home/home.vue"),
},
...indexRoutes
]
}
6.實現側邊欄
<el-aside class="left" width="200px">
<!-- 左側導航 -->
<!-- 1.background-color 背景顏色
2.router 開啟路由模式,index 是你想要跳轉的路徑
3.unique-opened 保持只有一個子選單展開
-->
<el-menu
class="el-menu-vertical-demo"
background-color="#20222a"
text-color="#fff"
active-text-color="#ffd04b"
router
unique-opened
>
<el-menu-item index="/">
<i class="el-icon-menu"></i>
<span slot="title">首頁</span>
</el-menu-item>
<el-submenu index="2">
<template slot="title">
<i class="el-icon-location"></i>
<span>系統設定</span>
</template>
<el-menu-item-group>
<el-menu-item index="/menu">選單管理</el-menu-item>
<el-menu-item index="/role">角色管理</el-menu-item>
<el-menu-item index="/manage">管理員管理</el-menu-item>
</el-menu-item-group>
</el-submenu>
<el-submenu index="3">
<template slot="title">
<i class="el-icon-location"></i>
<span>商城管理</span>
</template>
<el-menu-item-group>
<el-menu-item index="/cate">商品分類</el-menu-item>
<el-menu-item index="/specs">商品規格</el-menu-item>
<el-menu-item index="/goods">商品管理</el-menu-item>
<el-menu-item index="/member">會員管理</el-menu-item>
<el-menu-item index="/banner">輪播圖管理</el-menu-item>
<el-menu-item index="/seckill">秒殺活動</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</el-aside>
7.新增了一個麵包屑
<el-main class="main">
<!-- 麵包屑 -->
<el-breadcrumb v-if="$route.name" separator-class="el-icon-arrow-right">
<el-breadcrumb-item :to="{ path: '/' }">首頁</el-breadcrumb-item>
<el-breadcrumb-item>{{$route.name}}</el-breadcrumb-item>
</el-breadcrumb>
<!-- 二級路由出口 -->
<router-view></router-view>
</el-main>
8.給每一個二級路由規格新增了name屬性 router/index.js
let indexRoutes = [
{
path: "/menu",
name:"選單管理",
component: () => import("../pages/menu/menu.vue")
},
{
path: "/role",
name:"角色管理",
component: () => import("../pages/role/role.vue")
},
]
7.menu.vue
1.拆分menu.vue
將menu元件分為 新增按鈕 list add
<template>
<div>
<el-button type="primary" @click="willAdd">新增</el-button>
<!-- 表格 -->
<v-list></v-list>
<!-- 新增元件 -->
<v-add :info="info"></v-add>
</div>
</template>
2.通過模擬資料實現list.vue
<template>
<el-table
:data="tableData"
style="width: 100%; margin-bottom: 20px"
row-key="id"
border
default-expand-all
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
>
<el-table-column prop="date" label="日期" sortable width="180">
</el-table-column>
<el-table-column prop="name" label="姓名" sortable width="180">
</el-table-column>
<el-table-column prop="address" label="地址"> </el-table-column>
</el-table>
</template>
data() {
return {
tableData: [
{
id: 1,
date: "2016-05-02",
name: "王小虎",
address: "上海市普陀區金沙江路 1518 弄",
},
{
id: 2,
date: "2016-05-04",
name: "王小虎",
address: "上海市普陀區金沙江路 1517 弄",
},
{
id: 3,
date: "2016-05-01",
name: "王小虎",
address: "上海市普陀區金沙江路 1519 弄",
children: [
{
id: 31,
date: "2016-05-01",
name: "王小虎",
address: "上海市普陀區金沙江路 1519 弄",
},
{
id: 32,
date: "2016-05-01",
name: "王小虎",
address: "上海市普陀區金沙江路 1519 弄",
},
],
},
{
id: 4,
date: "2016-05-03",
name: "王小虎",
address: "上海市普陀區金沙江路 1516 弄",
},
],
};
},
3.add.vue
1.form
<el-form ref="form" :model="form" label-width="80px">
<el-form-item label="選單名稱">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="上級選單">
<el-select v-model="form.name" placeholder="請選擇上級選單">
<el-option label="頂級選單" value="shanghai"></el-option>
</el-select>
</el-form-item>
<el-form-item label="選單型別">
<el-radio v-model="form.name" label="1">目錄</el-radio>
<el-radio v-model="form.name" label="2">選單</el-radio>
</el-form-item>
<el-form-item label="選單圖示">
<el-select v-model="form.name" placeholder="請選擇上級選單">
<el-option v-for="item in icons" :key="item" :value="item">
<i :class="item"></i>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="選單地址">
<el-select v-model="form.name" placeholder="請選擇上級選單">
<el-option
v-for="item in indexRoutes"
:key="item.path"
:label="item.name"
:value="'/' + item.path"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="狀態">
<el-switch v-model="form.name"></el-switch>
</el-form-item>
</el-form>
data() {
return {
//圖示
icons: [
"el-icon-s-tools",
"el-icon-user",
"el-icon-camera",
"el-icon-message-solid",
],
//路由
indexRoutes: indexRoutes,
form: {
name: "",
},
};
},
4.對話方塊
<el-dialog title="新增選單" :visible.sync="info.isshow">
<el-form ref="form" :model="form" label-width="80px">
...
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="cancel">取 消</el-button>
<el-button type="primary">添 加</el-button
>
</div>
</el-dialog>
對話方塊需要一個變數isshow來控制出現和消失,將資料isshow定義在menu.vue中,傳遞過來,但是dialog需要直接修改這個資料,所以不能傳遞簡單型別,需要傳遞一個json格式的資料,才可以實現父變子變,子變 父變得要求。
menu.vue
data() {
return {
//傳遞給add的資料
info: {
//新增彈框的狀態
isshow: false,
},
};
},
methods: {
//點選了新增按鈕
willAdd() {
this.info.isshow = true;
},
},
<v-add :info="info"></v-add>
add.vue通過props接收
{
props:["info"]
}
<el-dialog :visible.sync="info.isshow"></el-dialog>
5.互動的介面 utils/request.js
//新增
export const reqMenuAdd=(params)=>{
return axios({
url:baseUrl+"/api/menuadd",
method:"post",
data:qs.stringify(params)
})
}
//列表
export const reqMenuList=()=>{
return axios({
url:baseUrl+"/api/menulist",
method:"get",
params:{
istree:true
}
})
}
//刪除
export const reqMenuDel=(id)=>{
return axios({
url:baseUrl+"/api/menudelete",
method:"post",
data:qs.stringify({id:id})
})
}
6.add.vue 新增互動
1.form的欄位和後端保持一致,然後繫結到每個表單上
form: {
pid:0,
title:"",
icon:"",
type:1,
url:"",
status:1
},
2.點選了新增按鈕,開始新增互動
//取消
cancel(){
this.info.isshow=false;
},
//資料重置
empty(){
this.form={
pid:0,
title:"",
icon:"",
type:1,
url:"",
status:1
}
},
//點選了新增按鈕
add(){
reqMenuAdd(this.form).then(res=>{
if(res.data.code==200){
//成功
successAlert(res.data.msg)
//資料重置
this.empty()
//彈框消失
this.cancel()
//list資料要重新整理
this.reqListAction()
}else{
warningAlert(res.data.msg)
}
})
}
3.如果是 頂級選單下,就是目錄,目錄有圖示,沒有地址;
如果不是頂級選單下的,就是選單,選單沒有圖示。有地址
<el-form-item label="上級選單">
<el-select v-model="form.pid" placeholder="請選擇上級選單" @change="changePid">
...
</el-select>
</el-form-item>
<el-form-item label="選單型別">
<el-radio v-model="form.type" :label="1" disabled>目錄</el-radio>
<el-radio v-model="form.type" :label="2" disabled>選單</el-radio>
</el-form-item>
<el-form-item label="選單圖示" v-if="form.type==1">
...
</el-form-item>
<el-form-item label="選單地址" v-else>
...
</el-form-item>
//修改了pid
changePid(){
if(this.form.pid==0){
this.form.type=1
}else{
this.form.type=2
}
},
7.獲取選單的list
由於選單的list的資料,很多地方都要用到。所以將他存在狀態層。
1.store/modules/menu.js
import {reqMenuList} from "../../utils/request"
const state = {
// 選單的list
list:[]
}
const mutations = {
//修改list
changeList(state,arr){
state.list=arr;
}
}
const actions = {
//頁面請求
reqListAction(context){
//發請求
reqMenuList().then(res=>{
context.commit("changeList",res.data.list)
})
}
}
const getters = {
list(state){
return state.list
}
}
export default {
state,
mutations,
actions,
getters,
namespaced: true
}
2.store/index.js 引入menu模組
import menu from "./modules/menu"
export default new Vuex.Store({
state,
getters,
mutations,
actions,
modules:{
menu
}
})
3.list.vue 通過mapGetters mapActions從狀態層取資料和方法
computed: {
...mapGetters({
list: "menu/list",
}),
},
methods: {
...mapActions({
reqListAction: "menu/reqListAction",
}),
},
mounted(){
this.reqListAction()
}
4.add.vue 裡也要用list資料和reqListAction 方法
computed: {
...mapGetters({
list: "menu/list",
}),
},
methods: {
...mapActions({
reqListAction: "menu/reqListAction",
}),
},
<el-form-item label="上級選單">
<el-select v-model="form.pid" placeholder="請選擇上級選單" @change="changePid">
<el-option label="頂級選單" :value="0"></el-option>
<el-option v-for="item in list" :key="item.id" :label="item.title" :value="item.id"></el-option>
</el-select>
</el-form-item>
當新增完成的時候,重新整理list資料
//點選了新增按鈕
add(){
reqMenuAdd(this.form).then(res=>{
if(res.data.code==200){
//成功
successAlert(res.data.msg)
//資料重置
this.empty()
//彈框消失
this.cancel()
//list資料要重新整理
this.reqListAction()
}else{
warningAlert(res.data.msg)
}
})
}
8.刪除互動
list.vue
<el-button type="danger" @click="del(scope.row.id)">刪除</el-button>
//刪除
del(id) {
this.$confirm("你確定要刪除嗎?", "刪除提示", {
confirmButtonText: "刪除",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
//點了確定按鈕
reqMenuDel(id).then(res=>{
if(res.data.code==200){
successAlert(res.data.msg)
this.reqListAction();
}else{
warningAlert(res.data.msg)
}
})
})
.catch(() => {
this.$message({
type: "info",
message: "已取消刪除",
});
});
},
9.編輯功能
1.list.vue 點選了編輯按鈕
<el-button type="primary" @click="edit(scope.row.id)">編輯</el-button>
//編輯
edit(id){
this.$emit("edit",id)
},
2.menu.vue 觸發自定事件 edit,收到id, 彈出彈框,讓add.vue 的look函式執行
<!-- 表格 -->
<v-list @edit="edit"></v-list>
<!-- 新增元件 -->
<v-add :info="info" ref="add"></v-add>
//編輯
edit(id){
this.info.isshow=true;
this.info.isAdd=false;
//讓add元件發起獲取詳情的請求
this.$refs.add.look(id)
}
3.add.vue look函式開始請求一條資料,請求完成後,賦值給form,但是請求得到的資料中沒有id欄位,但是一會兒修改是要id的,所以要補一個id
//獲取選單詳情 (1條)
look(id) {
//發請求
reqMenuDetail(id).then((res) => {
if (res.data.code == 200) {
//這個時候form是沒有id的
this.form = res.data.list;
this.form.id = id;
} else {
warningAlert(res.data.msg);
}
});
},
4.add.vue 點選了修改按鈕
//修改
update() {
reqMenuUpdate(this.form).then((res) => {
if (res.data.code == 200) {
successAlert(res.data.msg);
this.empty();
this.cancel();
this.reqListAction();
} else {
warningAlert(res.data.msg);
}
});
},
10.彈框bug
點選了 編輯–》取消 --》新增 ,這個時候,直接有上一次的資料。要改成:
如果是新增開的彈框,就什麼都不做;如果是編輯開的彈框,就清除form
<el-dialog @closed="close"></el-dialog>
//彈框消失完成
close(){
//如果是新增開的彈框,就什麼都不做;如果是編輯開的彈框,就清除form
if(!this.info.isAdd){
this.empty()
}
},
8.role.vue
1.拆分元件 list add 類似選單
2.靜態頁實現
list.vue
和選單list一樣
add.vue
<!-- 樹形控制元件 -->
<!-- data要展示的陣列 -->
<!-- props 配置 :children 用來判斷是否有下一層的欄位;label用來展示在頁面中的欄位 -->
<el-form-item label="角色許可權">
<el-tree
ref="tree"
:data="menuList"
show-checkbox
node-key="id"
:props="{children: 'children',label: 'title',}"
>
</el-tree>
</el-form-item>
3.互動介面書寫
request.js
/*********角色管理***************/
//新增
export const reqRoleAdd=(params)=>{
return axios({
url:baseUrl+"/api/roleadd",
method:"post",
data:qs.stringify(params)
})
}
//列表
export const reqRoleList=()=>{
return axios({
url:baseUrl+"/api/rolelist",
method:"get",
})
}
//刪除
export const reqRoleDel=(id)=>{
return axios({
url:baseUrl+"/api/roledelete",
method:"post",
data:qs.stringify({id:id})
})
}
//1條
export const reqRoleDetail=(id)=>{
return axios({
url:baseUrl+"/api/roleinfo",
method:"get",
params:{
id:id
}
})
}
//修改
export const reqRoleUpdate=(params)=>{
return axios({
url:baseUrl+"/api/roleedit",
method:"post",
data:qs.stringify(params)
})
}
4.獲取列表資料
1.store/modules/role.js
import {reqRoleList} from "../../utils/request"
const state = {
// list
list:[]
}
const mutations = {
//修改list
changeList(state,arr){
state.list=arr;
}
}
const actions = {
//頁面請求
reqListAction(context){
//發請求
reqRoleList().then(res=>{
let list=res.data.list?res.data.list:[]
context.commit("changeList",list)
})
}
}
const getters = {
list(state){
return state.list
}
}
export default {
state,
mutations,
actions,
getters,
namespaced: true
}
2.store/index.js 引入
import role from "./modules/role"
export default new Vuex.Store({
modules:{
menu,
role
}
})
3.pages/role/list.vue 引入資料和方法
computed: {
...mapGetters({
list: "role/list",
}),
},
methods: {
...mapActions({
reqListAction: "role/reqListAction",
}),
},
mounted() {
this.reqListAction();
},
5.新增
0.由於新增的樹形控制元件需要選單的list ,所以從vuex中取出
computed: {
...mapGetters({
//選單list
menuList: "menu/list",
}),
},
methods: {
...mapActions({
//請求選單list
reqMenuListAction: "menu/reqListAction",
//角色的list
reqRoleList:"role/reqListAction"
}),
},
mounted() {
//如果選單list沒有請求過,就請求一下,如果請求過了,就不用請求了
if(this.menuList.length==0){
this.reqMenuListAction()
}
},
1.初始資料form,保持和後端欄位一致
data() {
return {
form: {
rolename:"",
menus:'[]',
status: 1,
},
};
},
2.當點選了新增按鈕,先獲取到樹形控制元件的資料,賦值給form,才做資料互動。
//點選了新增按鈕
add() {
樹形控制元件取值 this.$refs.tree.getCheckedKeys()
this.form.menus=JSON.stringify(this.$refs.tree.getCheckedKeys())
reqRoleAdd(this.form).then((res) => {
if (res.data.code == 200) {
//成功
successAlert(res.data.msg);
//資料重置
this.empty();
//彈框消失
this.cancel();
//list資料要重新整理
this.reqRoleList();
} else {
warningAlert(res.data.msg);
}
});
},
由於form和樹形控制元件沒有關聯,所以在清空的時候,清空了form,還要把屬性控制元件清空
//資料重置
empty() {
this.form = {
rolename:"",
menus:'[]',
status: 1,
};
//樹形控制元件設定值
this.$refs.tree.setCheckedKeys([])
},
6.刪除
//刪除2
dele(id) {
//點了確定按鈕
reqRoleDel(id).then((res) => {
if (res.data.code == 200) {
successAlert(res.data.msg);
this.reqListAction();
} else {
warningAlert(res.data.msg);
}
});
},
7.編輯
點了編輯,獲取到資料,賦值給form,需要補id,而且樹形控制元件也需要賦值
//獲取選單詳情 (1條)
look(id) {
//發請求
reqRoleDetail(id).then((res) => {
if (res.data.code == 200) {
//這個時候form是沒有id的
this.form = res.data.list;
this.form.id=id
//給樹形控制元件賦值
this.$refs.tree.setCheckedKeys(JSON.parse(this.form.menus))
} else {
warningAlert(res.data.msg);
}
});
},
8.修改
樹形控制元件資料賦值給form
//修改
update() {
this.form.menus=JSON.stringify(this.$refs.tree.getCheckedKeys())
reqRoleUpdate(this.form).then((res) => {
if (res.data.code == 200) {
successAlert(res.data.msg);
this.empty();
this.cancel();
this.reqRoleList();
} else {
warningAlert(res.data.msg);
}
});
},
9.manage.vue 管理員管理
1.拆分元件
list add 貼上了menu 的list 和 add
2.靜態頁
list.vue
add.vue
3.互動介面書寫
/*********管理員管理***************/
//新增
export const reqManageAdd=(params)=>{
return axios({
url:baseUrl+"/api/useradd",
method:"post",
data:qs.stringify(params)
})
}
//管理員總數
export const reqManageCount=()=>{
return axios({
url:baseUrl+"/api/usercount",
})
}
//列表 params={page:1,size:10}
export const reqManageList=(params)=>{
return axios({
url:baseUrl+"/api/userlist",
method:"get",
params:params
})
}
//刪除
export const reqManageDel=(uid)=>{
return axios({
url:baseUrl+"/api/userdelete",
method:"post",
data:qs.stringify({uid:uid})
})
}
//1條
export const reqManageDetail=(uid)=>{
return axios({
url:baseUrl+"/api/userinfo",
method:"get",
params:{
uid:uid
}
})
}
//修改
export const reqManageUpdate=(params)=>{
return axios({
url:baseUrl+"/api/useredit",
method:"post",
data:qs.stringify(params)
})
}
4.獲取列表資料
1.store/modules/manage.js
import {reqManageList} from "../../utils/request"
const state = {
// 選單的list
list:[]
}
const mutations = {
//修改list
changeList(state,arr){
state.list=arr;
}
}
const actions = {
//頁面請求
reqListAction(context){
//發請求
reqManageList({page:1,size:10}).then(res=>{
let list=res.data.list?res.data.list:[]
context.commit("changeList",list)
})
}
}
const getters = {
list(state){
return state.list
}
}
export default {
state,
mutations,
actions,
getters,
namespaced: true
}
2.store/index.js 引入manage模組
import manage from "./modules/manage"
export default new Vuex.Store({
state,
getters,
mutations,
actions,
modules:{
menu,
role,
manage
}
})
3.list.vue使用
computed: {
...mapGetters({
list: "manage/list",
}),
},
methods: {
...mapActions({
reqListAction: "manage/reqListAction",
}),
},
mounted() {
this.reqListAction();
},
5.新增功能-add.vue
0.獲取角色列表
computed: {
...mapGetters({
roleList: "role/list",
}),
},
methods: {
...mapActions({
reqRoleListAction: "role/reqListAction",
reqManageList:"manage/reqListAction"
}),
},
mounted() {
//如果沒有請求過角色管理的資料,就請求一次,如果請求過了,就不用請求了
if(this.roleList.length==0){
this.reqRoleListAction()
}
},
1.定義form初始值
data() {
return {
form: {
roleid:"",
username:"",
password:"",
status:1
},
};
},
2.點選了新增按鈕
//點選了新增按鈕
add() {
reqManageAdd(this.form).then((res) => {
if (res.data.code == 200) {
//成功
successAlert(res.data.msg);
//資料重置
this.empty();
//彈框消失
this.cancel();
//list資料要重新整理
this.reqManageList();
} else {
warningAlert(res.data.msg);
}
});
},
3.清空form
//資料重置
empty() {
this.form ={
roleid:"",
username:"",
password:"",
status:1
};
},
6.刪除
<del-btn @confirm="dele(scope.row.uid)"></del-btn>
//刪除2
dele(uid) {
//點了確定按鈕
reqManageDel(uid).then((res) => {
if (res.data.code == 200) {
successAlert(res.data.msg);
this.reqListAction();
} else {
warningAlert(res.data.msg);
}
});
},
7.編輯
<el-button type="primary" @click="edit(scope.row.uid)">編輯</el-button>
add.vue
//獲取選單詳情 (1條)
look(uid) {
//發請求
reqManageDetail(uid).then((res) => {
if (res.data.code == 200) {
//這個時候form是沒有id的
this.form = res.data.list;
//密碼是加密過的,所以需要重置密碼
this.form.password=""
} else {
warningAlert(res.data.msg);
}
});
},
8.修改
//修改
update() {
reqManageUpdate(this.form).then((res) => {
if (res.data.code == 200) {
successAlert(res.data.msg);
this.empty();
this.cancel();
this.reqManageList();
} else {
warningAlert(res.data.msg);
}
});
},
9.分頁
1.分頁元件
<!-- 分頁元件 -->
<!--
total:設定總數
page-size:每頁數量
有多少頁,不用自己計算
current-change:當前頁碼發生了改變,就會觸發,引數就是當前的頁碼
-->
<el-pagination background layout="prev, pager, next" :total="total" :page-size="size"
@current-change="changePage"
>
</el-pagination>
2.狀態層(store/modules/manage.js)定義了狀態size ,並匯出
const state = {
//一頁的數量
size: 2,
}
const getters = {
size(state) {
return state.size
},
}
元件使用
<el-pagination background layout="prev, pager, next"
:page-size="size"
>
</el-pagination>
3.總數
定義了一個total狀態,他的修改的mutations,和請求的action,匯出的getters
const state = {
//總數
total:0,
}
const mutations = {
//修改total
changeTotal(state,num){
state.total=num;
},
}
const actions = {
//獲取總數的請求
reqTotalAction(context){
reqManageCount().then(res=>{
context.commit("changeTotal",res.data.list[0].total)
})
},
}
const getters = {
total(state){
return state.total;
}
}
list.vue取出total使用
<el-pagination background layout="prev, pager, next"
:total="total"
>
</el-pagination>
4.頁碼
在狀態層定義了一個狀態頁碼 page,修改
const state = {
//頁碼
page:1,
}
const mutations = {
//修改頁碼
changePage(state,page){
state.page=page
}
}
const actions = {
//元件修改了頁碼
changePageAction(context,page){
//修改頁碼
context.commit("changePage",page)
//發起list請求
context.dispatch('reqListAction')
}
}
list.vue 繫結事件,觸發修改頁碼
<el-pagination background layout="prev, pager, next" :total="total" :page-size="size"
@current-change="changePage"
>
</el-pagination>
methods: {
...mapActions({
changePageAction:"manage/changePageAction"
}),
//修改了當前頁碼
changePage(e){
this.changePageAction(e)
}
},
5.在請求list資料的時候,不在使用固定值,而是使用變數作為引數
const actions = {
//頁面請求
reqListAction(context) {
//發請求
reqManageList(
{ page: context.state.page, size: context.state.size }
).then(res => {
let list = res.data.list ? res.data.list : []
context.commit("changeList", list)
})
},
}
6.注意
一進來掛載完成、新增完成、刪除完成 都要重新請求總數。
7.bug
假設目前page是3,在page3 減到沒有資料了,就會顯示“暫無資料”,但是應該展示第2頁的資料。
//頁面請求
reqListAction(context) {
//發請求
reqManageList({ page: context.state.page, size: context.state.size }).then(res => {
//如果去list的時候,取到null,那麼有可能是最後一頁沒資料了,需要減一頁,再次請求list
let list = res.data.list ? res.data.list : []
//如果取到的資料是null,並且不是第一頁,那麼就頁碼減1,重新請求list
if(context.state.page>1&&list.length==0){
context.commit("changePage",context.state.page-1)
context.dispatch("reqListAction")
return;
}
context.commit("changeList", list)
})
},
10、cate商品分類
1、拆分頁面(複製menu頁面)
2、add.vue
<!-- 原生 -->
<el-form-item label="圖片">
<div class="fileBox">
<h3>+</h3>
<img :src="imgUrl" v-if="imgUrl">
<input type="file" @change="changeFile" v-if="info.isShow">
</div>
</el-form-item>
<!-- element-ui -->
<el-form-item label="圖片">
<el-upload
class="avatar-uploader"
action="#"
:show-file-list="false" :on-change="changeFile2">
<img v-if="imgUrl" :src="imgUrl" class="avatar" />
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</el-form-item>
// 原生改變圖片
changeFile(e) {
let file = e.target.files[0];
// 限制大小file.size 限制大小為2M B-->1024KB 1024KB-->1M
if(file.size > 2*1024*1024){
warningAlert("圖片大小超出限制")
return
}
// URL.createObjectURL 可以將圖片資訊轉換成具體的圖片
this.imgUrl = URL.createObjectURL(file);
this.form.img = file;
},
// element-ui改變圖片
changeFile2(e){
let file = e.raw
this.imgUrl = URL.createObjectURL(file);
this.form.img = file
}
3、在新增的請求裡面
export const reqCateAdd = (form) => {
// 因為form中包含了檔案,所以必須要這樣傳參
let data = new FormData()
// data.append("pid",1)
// data.append("catename",'hahaha')
// data.append("img",file)
// data.append("status",1)
for(let i in form){
data.append(i,form[i])
}
return axios({
url: baseUrl + "/api/cateadd",
method: "post",
data: data
})
}
4、列表渲染圖片
<el-table-column label="圖片">
<template slot-scope="scope">
<div class="imgBox">
<img :src="$imgUrl+scope.row.img" alt="">
</div>
</template>
</el-table-column>
// 開發環境
let baseUrl = "/api"
Vue.prototype.$imgUrl = "http://localhost:3000/"
// 上線環境
// let bstUrl = ""
// Vue.prototype.$imgUrl = ""
5、編輯功能也要修改request.js
export const reqCateUpdate = (form)=>{
let data = new FormData()
for(let i in form){
data.append(i,form[i])
}
return axios({
url:baseUrl+"/api/cateedit",
method:"POST",
data:data
})
}
11、specs商品規格
1、拆分靜態頁(複製manage頁面)
2、add.vue靜態頁面
<el-form-item label="規格屬性" v-for="(item,index) in attrArr" :key="index">
<div class="inpTop">
<el-input v-model="item.value"></el-input>
<el-button type="primary" @click="addAttr" v-if="index==0">新增規格屬性</el-button>
<el-button type="danger" @click="delAttr(index)" v-else>刪除</el-button>
</div>
</el-form-item>
data() {
return {
attrArr:[
{value:''},
{value:''}
],
};
}
3、點選新增商品規格和刪除
// 點選新增按鈕
addAttr(){
this.attrArr.push({value:''})
},
// 點選刪除按鈕
delAttr(index){
this.attrArr.splice(index,1)
}
4、點選提交按鈕
add() {
this.form.attrs = JSON.stringify(this.attrArr.map(item=>item.value))
reqSpecsAdd(this.form).then((res) => {
if (res.data.code === 200) {
// 彈窗
successAlert(res.data.msg);
// 取消彈窗並重置form資料
this.cancel();
// 重新整理list列表
this.reqManageList();
// 重新獲取總條數
this.reqChangeTotal();
} else {
warningAlert(res.data.msg);
}
});
}
5、在狀態層處理一下list資料
list.forEach(item=>{
item.attrs = JSON.parse(item.attrs)
})
<el-table-column prop="rolename" label="規格屬性">
<template slot-scope="scope">
<div>
<el-tag v-for="item in scope.row.attrs" :key="item">{{item}}</el-tag>
</div>
</template>
</el-table-column>
6、刪除功能
del2(id) {
reqSpecsDel(id).then((res) => {
if (res.data.code == 200) {
successAlert(res.data.msg);
// 重新請求列表
this.reqChangeList();
// 重新請求總條數
this.reqChangeTotal()
} else {
warningAlert(res.data.msg);
}
});
}
7、獲取一條詳情資訊
getOne(id) {
reqSpecsOne(id).then((res) => {
this.form = res.data.list[0];
this.attrArr = JSON.parse(this.form.attrs).map(item=>({value:item}))
});
}
8、編輯功能
update() {
this.form.attrs = JSON.stringify(this.attrArr.map(item=>item.value))
reqSpecsUpdate(this.form).then((res) => {
if (res.data.code === 200) {
successAlert(res.data.msg);
// 關閉彈窗並重置資料
this.cancel();
// 重新整理list列表
this.reqManageList();
} else {
warningAlert(res.data.msg);
}
});
},
}
12、goods商品管理
1、拆分靜態頁
2、統一設定介面
3、add.vue
3.1、設定靜態頁
3.2、設定初始form
form: {
first_cateid: "",
second_cateid: "",
goodsname: "",
price: "",
market_price: "",
img: "",
description: "",
specsid: "",
specsattr: "",
isnew: 1,
ishot: 1,
status: 1,
}
3.3、繫結資料v-model
3.3.1、通過狀態層獲取一級分類
3.3.2、二級分類
// 用於渲染二級分類
secondArr: [],
// 當一級分類改變的時候
changeFirst() {
reqCateList({ pid: this.form.first_cateid }).then((res) => {
// 清空form裡面的second_cateid
this.form.second_cateid = "";
// 用於渲染二級分類
this.secondArr = res.data.list;
});
}
3.3.3、圖片
<el-form-item label="圖片">
<div class="fileBox">
<h3>+</h3>
<img :src="imgUrl" v-if="imgUrl" />
<input type="file" @change="changeFile" v-if="info.isShow" />
</div>
</el-form-item>
// 改變了圖片
changeFile(e) {
console.log(e);
let file = e.target.files[0];
// 限制大小file.size 限制大小為2M B-->1024KB 1024KB-->1M
if (file.size > 2 * 1024 * 1024) {
warningAlert("圖片大小超出限制");
return;
}
// URL.createObjectURL 可以將圖片資訊轉換成具體的圖片
this.imgUrl = URL.createObjectURL(file);
this.form.img = file;
}
3.3.4、商品規格
通過狀態層取到specs商品規格
3.3.5、規格屬性
// 用於渲染規格屬性
specsArr: []
// 改變了商品規格
changeSpecs() {
// 清空規格屬性
this.specsArr = [];
this.form.specsattr = [];
// 找到specsList裡面id是我需要的那一條資料
let obj = this.specsList.find((item) => item.id == this.form.specsid);
// 把那一條資料的attrs賦值給我的specsArr
this.specsArr = obj.attrs;
}
4、list.vue
4.1、設定靜態頁
4.2、設定狀態層(複製的mange狀態層)
4.3、頁面一進來就請求列表資料
4.4、繫結資料
5、刪除
6、獲取一條資訊
getOne(id) {
reqGoodsOne(id).then((res) => {
this.form = res.data.list;
// 補充id,因為修改的時候需要id
this.form.id = id
// 1、根據一級分類的id獲取二級分類的列表
reqCateList({ pid: this.form.first_cateid }).then((res) => {
// 用於渲染二級分類
this.secondArr = res.data.list;
});
// 2、處理圖片
this.imgUrl = this.$imgUrl + this.form.img
// 3、處理規格屬性
this.form.specsattr = JSON.parse(this.form.specsattr)
// 4、處理規格屬性的下拉框
let obj = this.specsList.find((item) => item.id == this.form.specsid);
this.specsArr = obj.attrs;
});
}
7、修改功能
update() {
let data = {
...this.form,
specsattr: JSON.stringify(this.form.specsattr),
};
reqGoodsUpdate(data).then((res) => {
if (res.data.code === 200) {
successAlert(res.data.msg);
// 關閉彈窗並重置資料
this.cancel();
// 重新整理list列表
this.reqChangeList()
} else {
warningAlert(res.data.msg);
}
});
}
富文字編輯器
1、官網:http://www.wangeditor.com/
2、安裝方式:
npm安裝 npm i wangeditor --save
CDN連結 https://unpkg.com/wangeditor/dist/wangEditor.min.js
3、使用
// 當開啟動畫完成時
opened(){
// 載入富文字
this.editor = new E('#div1')
this.editor.create()
// 設定富文字的內容
this.editor.txt.html(this.form.description)
}
// 在新增請求之前
// 將富文字的內容加入到form中
this.form.description = this.editor.txt.html()
許可權
1、登入互動
login(){
reqLogin(this.info).then(res=>{
console.log(res)
if(res.data.code === 200){
successAlert(res.data.msg)
// 1、存res.data.list。不僅存了狀態層還存了本地儲存
this.reqUserInfoAction(res.data.list)
// 2、進入頁面
this.$router.push("/")
}else{
warningAlert(res.data.msg)
}
})
}
2、設定狀態層
// mutations.js
export const state = {
userInfo:sessionStorage.getItem("userInfo")?JSON.parse(sessionStorage.getItem("userInfo")):{}
}
export const getters = {
userInfo(state){
return state.userInfo
}
}
export const mutations = {
changeUserInfo(state,info){
state.userInfo = info
if(info.id){
//在本地儲存也存一份
sessionStorage.setItem("userInfo",JSON.stringify(info))
}else{
//清空本地儲存的userInfo
sessionStorage.removeItem("userInfo")
}
}
}
// actions.js
import {reqLogin} from "../util/request"
export const actions = {
reqUserInfoAction(context,info){
context.commit("changeUserInfo",info)
}
}
3、登陸攔截
// 登入攔截
router.beforeEach((to, from, next) => {
//1、如果去的是登入頁,就直接進
if (to.path == '/login') {
next()
return
}
//2、如果去的是其他頁面,驗證倉庫裡面的token是否存在,如果存在說明登入過了。
if (store.state.userInfo.token) {
next();
return
}
next("/login")
})
4、路由獨享守衛
function changeEnter(path,next) {
// 取出你可以去的地址
let menus_url = store.state.userInfo.menus_url
if (menus_url.includes(path)) {
next()
} else {
next("/")
}
}
export const indexRouters = [{
path: "menu",
name: "選單管理",
component: () => import("../page/menu/menu.vue"),
beforeEnter: (to, from, next) => {
changeEnter("/menu",next)
}
}
}]
5、動態側邊欄index.vue
<div v-for="item in userInfo.menus" :key="item.id">
<!-- 目錄 -->
<el-submenu :index="item.id+''" v-if="item.children">
<template slot="title">
<i :class="item.icon"></i>
<span>{{item.title}}</span>
</template>
<el-menu-item-group>
<el-menu-item v-for="i in item.children" :key="i.id" :index="i.url">
<span>{{i.title}}</span>
</el-menu-item>
</el-menu-item-group>
</el-submenu>
<!-- 選單 -->
<el-menu-item :index="item.url" v-else>
<span>{{item.title}}</span>
</el-menu-item>
</div>
注意:動態側邊欄需要一些資料,資料是從狀態層拿過來的
6、退出
<el-header class="header">
<div>
<span>{{userInfo.username}}</span>
<el-button @click="logOut">退出</el-button>
</div>
</el-header>
logOut(){
// 清空狀態層的userinfo
this.reqUserInfoAction({})
// 跳到登入頁
this.$router.push("/login")
}
相關文章
- Vue + ElementUI 後臺管理系統專案心得(一)VueUI
- Vue + ElementUI 後臺管理系統專案心得(二)VueUI
- Vue 專案應用 —— 後臺管理系統模板Vue
- 轉:SAP專案管理系統速成專案管理
- Vue 2.x 實戰之後臺管理系統開發(一)Vue
- Vue 2.x 實戰之後臺管理系統開發(二)Vue
- vue後臺管理系統程式碼Vue
- Vue+Node 後臺管理系統Vue
- 【Vue專案總結】後臺管理專案總結Vue
- 使用Vue搭建電商後臺管理系統Vue
- 後臺管理系統vue.js路由Vue.js路由
- 電商發退貨後臺管理系統專案需求
- Vue 後臺管理類專案相容IE9+VueIE9
- 適合做外包專案的開源後臺管理系統
- MVC + EFCore 專案實戰 - 數倉管理系統1MVC
- vue後臺管理系統許可權控制思考與實踐Vue
- 深入Vue後臺管理開發(1)專案安裝Vue
- VUE3後臺管理系統【路由鑑權】Vue路由
- 後臺管理系統
- 實驗室後臺管理專案總結
- 後臺管理系統CMS模組-後端實現後端
- lucms - vue 與 Laravel 開發的後臺管理系統VueLaravel
- MVC + EFCore 專案實戰 - 數倉管理系統4 – 需求分解MVC
- Thinkphp後臺管理系統PHP
- AlphaCms後臺管理系統ACM
- ITKEE後臺管理系統
- LaraCMS 後臺管理系統ACM
- 「免費開源」基於Vue和Quasar的前端SPA專案crudapi零程式碼開發平臺後臺管理系統實戰之後設資料匯出匯入(十五)Vue前端API
- 我最近做了一個react的後臺管理系統,用於快速建立後臺專案模板React
- Vue+Vue-router+Vuex專案實戰Vue
- Go 實現世界盃後臺管理系統Go
- Vue專案實戰(一)——ToDoListVue
- Vue 專案 SSR 改造實戰Vue
- 12 款做Java後臺管理系統的專案,超級無敵好用!Java
- 快速開發後臺管理系統vue-bag-adminVue
- vue-manage-system 後臺管理系統開發總結Vue
- 保姆級別的vue + ElementUI 搭建後臺管理系統教程VueUI
- JavaEE專案實戰(OA系統)之十三_員工管理之一Java