东莞房地产网站建设,h5浏览器,wordpress值得买,哈尔滨网站开发渠道项目简介#xff1a;
该项目为电商后台的管理系统。设计了登录页面。 管理人员需要通过输入正确的用户名和密码才能登录。登陆成功之后进入管理页面#xff1a; 管理页面由五个子模块组成#xff1a;用户管理#xff0c;权限管理#xff0c;商品管理#xff0c;订单管理…项目简介
该项目为电商后台的管理系统。设计了登录页面。 管理人员需要通过输入正确的用户名和密码才能登录。登陆成功之后进入管理页面 管理页面由五个子模块组成用户管理权限管理商品管理订单管理数据统计
每个子模块有若干子模块组成用户管理下-用户列表权限管理-角色列表权限管理商品管理-商品列表分类参数商品分配订单管理-订单列表数据统计-数据报表
登录页面
登录页面中对用户输入的内容进行预校验如果不符合要求则则不向后端发送请求同事挂载路由守卫防止强制跳转。同时设置令牌校验避免重复登录。如果用户输入格式正确的用户名以及密码时向后端发送请求请求通过则跳转到管理页面否则返回登录页面。
路由导航守卫
// 挂载路由导航守卫
router.beforeEach((to, from, next) {// to 将要访问的路径// from 代表从哪个路径跳转而来// next 是一个函数表示放行// next() 放行 next(/login) 强制跳转if (to.path /login) return next()// 获取tokenconst tokenStr window.sessionStorage.getItem(token)if (!tokenStr) return next(/login)next()
})
登录页面核心代码
templatediv classlogin_containerdiv classlogin_box!-- 头像区域 --div classavatar_boximg src../assets/logo.png alt/div!-- 登录表单区域 --el-form refloginFormRef :modelloginForm :rulesloginFormRules label-width0px classlogin_form!-- 用户名 --el-form-item propusernameel-input v-modelloginForm.username prefix-iconiconfont icon-user/el-input/el-form-item!-- 密码 --el-form-item proppasswordel-input v-modelloginForm.password prefix-iconiconfont icon-3702mima typepassword/el-input/el-form-item!-- 按钮区域 --el-form-item classbtnsel-button typeprimary clicklogin登录/el-buttonel-button typeinfo clickresetLoginForm重置/el-button/el-form-item/el-form/div/div
/templatescript
export default {data() {return {// 这是登录表单的数据绑定对象loginForm: {username: admin,password: 123456},// 这是表单的验证规则对象loginFormRules: {// 验证用户名是否合法username: [{ required: true, message: 请输入登录名称, trigger: blur },{ min: 3, max: 10, message: 长度在 3 到 10 个字符, trigger: blur }],// 验证密码是否合法password: [{ required: true, message: 请输入登录密码, trigger: blur },{ min: 6, max: 15, message: 长度在 6 到 15 个字符, trigger: blur }]}}},methods: {// 点击重置按钮重置登录表单resetLoginForm() {// console.log(this);this.$refs.loginFormRef.resetFields()},login() {this.$refs.loginFormRef.validate(async valid {if (!valid) returnconst { data: res } await this.$http.post(login, this.loginForm)if (res.meta.status ! 200) return this.$message.error(登录失败)this.$message.success(登录成功)// 1. 将登录成功之后的 token保存到客户端的 sessionStorage 中// 1.1 项目中出了登录之外的其他API接口必须在登录之后才能访问// 1.2 token 只应在当前网站打开期间生效所以将 token 保存在 sessionStorage 中window.sessionStorage.setItem(token, res.data.token)// 2. 通过编程式导航跳转到后台主页路由地址是 /homethis.$router.push(/home)})}}
}
/scriptstyle langless scoped
.login_container {background-color: #2b4b6b;height: 100%;
}.login_box {width: 450px;height: 300px;background-color: #fff;border-radius: 3px;position: absolute;left: 50%;top: 50%;transform: translate(-50%, -50%);.avatar_box {height: 130px;width: 130px;border: 1px solid #eee;border-radius: 50%;padding: 10px;box-shadow: 0 0 10px #ddd;position: absolute;left: 50%;transform: translate(-50%, -50%);background-color: #fff;img {width: 100%;height: 100%;border-radius: 50%;background-color: #eee;}}
}.login_form {position: absolute;bottom: 0;width: 100%;padding: 0 20px;box-sizing: border-box;
}.btns {display: flex;justify-content: flex-end;
}
/style
菜单实现
管理页面有一个侧面的两级菜单菜单的数据来自于后端点击二级菜单会跳转到相应的子页面中。在el-menu中设置router属性即可通过index添加到路由上进行跳转。
templateel-container classhome-container!-- 头部区域 --el-headerdivimg src../assets/heima.png altspan电商后台管理系统/span/divel-button typeinfo clicklogout退出/el-button/el-header!-- 页面主体区域 --el-container!-- 侧边栏 --el-aside :widthisCollapse ? 64px : 200pxdiv classtoggle-button clicktoggleCollapse|||/div!-- 侧边栏菜单区域 --el-menu background-color#333744 text-color#fff active-text-color#409EFF unique-opened :collapseisCollapse :collapse-transitionfalse router :default-activeactivePath!-- 一级菜单 --el-submenu :indexitem.id v-foritem in menulist :keyitem.id!-- 一级菜单的模板区域 --template slottitle!-- 图标 --i :classiconsObj[item.id]/i!-- 文本 --span{{item.authName}}/span/template!-- 二级菜单 --el-menu-item :index/ subItem.path v-forsubItem in item.children :keysubItem.id clicksaveNavState(/ subItem.path)template slottitle!-- 图标 --i classel-icon-menu/i!-- 文本 --span{{subItem.authName}}/span/template/el-menu-item/el-submenu/el-menu/el-aside!-- 右侧内容主体 --el-main!-- 路由占位符 --router-view/router-view/el-main/el-container/el-container
/templatescript
export default {data() {return {// 左侧菜单数据menulist: [],iconsObj: {125: iconfont icon-user,103: iconfont icon-tijikongjian,101: iconfont icon-shangpin,102: iconfont icon-danju,145: iconfont icon-baobiao},// 是否折叠isCollapse: false,// 被激活的链接地址activePath: }},created() {this.getMenuList()this.activePath window.sessionStorage.getItem(activePath)},methods: {logout() {window.sessionStorage.clear()this.$router.push(/login)},// 获取所有的菜单async getMenuList() {const { data: res } await this.$http.get(menus)if (res.meta.status ! 200) return this.$message.error(res.meta.msg)this.menulist res.dataconsole.log(res)},// 点击按钮切换菜单的折叠与展开toggleCollapse() {this.isCollapse !this.isCollapse},// 保存链接的激活状态saveNavState(activePath) {window.sessionStorage.setItem(activePath, activePath)this.activePath activePath}}
}
/scriptstyle langless scoped
.home-container {height: 100%;
}
.el-header {background-color: #373d41;display: flex;justify-content: space-between;padding-left: 0;align-items: center;color: #fff;font-size: 20px; div {display: flex;align-items: center;span {margin-left: 15px;}}
}.el-aside {background-color: #333744;.el-menu {border-right: none;}
}.el-main {background-color: #eaedf1;
}.iconfont {margin-right: 10px;
}.toggle-button {background-color: #4a5064;font-size: 10px;line-height: 24px;color: #fff;text-align: center;letter-spacing: 0.2em;cursor: pointer;
}
/style用户管理
用户列表
用户管理下有用户列表这里渲染了后端的用户列表可以编辑用户信息删除用户为用户分配角色还可以对用户是否禁用进行管理除此之外还添加了查询用户添加用户和分页功能。 核心代码
templatediv!-- 面包屑导航区域 --el-breadcrumb separator-classel-icon-arrow-rightel-breadcrumb-item :to{ path: /home }首页/el-breadcrumb-itemel-breadcrumb-item用户管理/el-breadcrumb-itemel-breadcrumb-item用户列表/el-breadcrumb-item/el-breadcrumb!-- 卡片视图区域 --el-card!-- 搜索与添加区域 --el-row :gutter20el-col :span8el-input placeholder请输入内容 v-modelqueryInfo.query clearable cleargetUserListel-button slotappend iconel-icon-search clickgetUserList/el-button/el-input/el-colel-col :span4el-button typeprimary clickaddDialogVisible true添加用户/el-button/el-col/el-row!-- 用户列表区域 --el-table :datauserlist border stripeel-table-column typeindex/el-table-columnel-table-column label姓名 propusername/el-table-columnel-table-column label邮箱 propemail/el-table-columnel-table-column label电话 propmobile/el-table-columnel-table-column label角色 proprole_name/el-table-columnel-table-column label状态template slot-scopescopeel-switch v-modelscope.row.mg_state changeuserStateChanged(scope.row)/el-switch/template/el-table-columnel-table-column label操作 width180pxtemplate slot-scopescope!-- 修改按钮 --el-button typeprimary iconel-icon-edit sizemini clickshowEditDialog(scope.row.id)/el-button!-- 删除按钮 --el-button typedanger iconel-icon-delete sizemini clickremoveUserById(scope.row.id)/el-button!-- 分配角色按钮 --el-tooltip effectdark content分配角色 placementtop :enterablefalseel-button typewarning iconel-icon-setting sizemini clicksetRole(scope.row)/el-button/el-tooltip/template/el-table-column/el-table!-- 分页区域 --el-pagination size-changehandleSizeChange current-changehandleCurrentChange :current-pagequeryInfo.pagenum :page-sizes[1, 2, 5, 10] :page-sizequeryInfo.pagesize layouttotal, sizes, prev, pager, next, jumper :totaltotal/el-pagination/el-card!-- 添加用户的对话框 --el-dialog title添加用户 :visible.syncaddDialogVisible width50% closeaddDialogClosed!-- 内容主体区域 --el-form :modeladdForm :rulesaddFormRules refaddFormRef label-width70pxel-form-item label用户名 propusernameel-input v-modeladdForm.username/el-input/el-form-itemel-form-item label密码 proppasswordel-input v-modeladdForm.password/el-input/el-form-itemel-form-item label邮箱 propemailel-input v-modeladdForm.email/el-input/el-form-itemel-form-item label手机 propmobileel-input v-modeladdForm.mobile/el-input/el-form-item/el-form!-- 底部区域 --span slotfooter classdialog-footerel-button clickaddDialogVisible false取 消/el-buttonel-button typeprimary clickaddUser确 定/el-button/span/el-dialog!-- 修改用户的对话框 --el-dialog title修改用户 :visible.synceditDialogVisible width50% closeeditDialogClosedel-form :modeleditForm :ruleseditFormRules refeditFormRef label-width70pxel-form-item label用户名el-input v-modeleditForm.username disabled/el-input/el-form-itemel-form-item label邮箱 propemailel-input v-modeleditForm.email/el-input/el-form-itemel-form-item label手机 propmobileel-input v-modeleditForm.mobile/el-input/el-form-item/el-formspan slotfooter classdialog-footerel-button clickeditDialogVisible false取 消/el-buttonel-button typeprimary clickeditUserInfo确 定/el-button/span/el-dialog!-- 分配角色的对话框 --el-dialog title分配角色 :visible.syncsetRoleDialogVisible width50% closesetRoleDialogCloseddivp当前的用户{{userInfo.username}}/pp当前的角色{{userInfo.role_name}}/pp分配新角色el-select v-modelselectedRoleId placeholder请选择el-option v-foritem in rolesList :keyitem.id :labelitem.roleName :valueitem.id/el-option/el-select/p/divspan slotfooter classdialog-footerel-button clicksetRoleDialogVisible false取 消/el-buttonel-button typeprimary clicksaveRoleInfo确 定/el-button/span/el-dialog/div
/templatescript
export default {data() {// 验证邮箱的规则var checkEmail (rule, value, cb) {// 验证邮箱的正则表达式const regEmail /^([a-zA-Z0-9_-])([a-zA-Z0-9_-])(\.[a-zA-Z0-9_-])/if (regEmail.test(value)) {// 合法的邮箱return cb()}cb(new Error(请输入合法的邮箱))}// 验证手机号的规则var checkMobile (rule, value, cb) {// 验证手机号的正则表达式const regMobile /^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$/if (regMobile.test(value)) {return cb()}cb(new Error(请输入合法的手机号))}return {// 获取用户列表的参数对象queryInfo: {query: ,// 当前的页数pagenum: 1,// 当前每页显示多少条数据pagesize: 2},userlist: [],total: 0,// 控制添加用户对话框的显示与隐藏addDialogVisible: false,// 添加用户的表单数据addForm: {username: ,password: ,email: ,mobile: },// 添加表单的验证规则对象addFormRules: {username: [{ required: true, message: 请输入用户名, trigger: blur },{min: 3,max: 10,message: 用户名的长度在3~10个字符之间,trigger: blur}],password: [{ required: true, message: 请输入密码, trigger: blur },{min: 6,max: 15,message: 用户名的长度在6~15个字符之间,trigger: blur}],email: [{ required: true, message: 请输入邮箱, trigger: blur },{ validator: checkEmail, trigger: blur }],mobile: [{ required: true, message: 请输入手机号, trigger: blur },{ validator: checkMobile, trigger: blur }]},// 控制修改用户对话框的显示与隐藏editDialogVisible: false,// 查询到的用户信息对象editForm: {},// 修改表单的验证规则对象editFormRules: {email: [{ required: true, message: 请输入用户邮箱, trigger: blur },{ validator: checkEmail, trigger: blur }],mobile: [{ required: true, message: 请输入用户手机, trigger: blur },{ validator: checkMobile, trigger: blur }]},// 控制分配角色对话框的显示与隐藏setRoleDialogVisible: false,// 需要被分配角色的用户信息userInfo: {},// 所有角色的数据列表rolesList: [],// 已选中的角色Id值selectedRoleId: }},created() {this.getUserList()},methods: {async getUserList() {const { data: res } await this.$http.get(users, {params: this.queryInfo})if (res.meta.status ! 200) {return this.$message.error(获取用户列表失败)}this.userlist res.data.usersthis.total res.data.totalconsole.log(res)},// 监听 pagesize 改变的事件handleSizeChange(newSize) {// console.log(newSize)this.queryInfo.pagesize newSizethis.getUserList()},// 监听 页码值 改变的事件handleCurrentChange(newPage) {console.log(newPage)this.queryInfo.pagenum newPagethis.getUserList()},// 监听 switch 开关状态的改变async userStateChanged(userinfo) {console.log(userinfo)const { data: res } await this.$http.put(users/${userinfo.id}/state/${userinfo.mg_state})if (res.meta.status ! 200) {userinfo.mg_state !userinfo.mg_statereturn this.$message.error(更新用户状态失败)}this.$message.success(更新用户状态成功)},// 监听添加用户对话框的关闭事件addDialogClosed() {this.$refs.addFormRef.resetFields()},// 点击按钮添加新用户addUser() {this.$refs.addFormRef.validate(async valid {if (!valid) return// 可以发起添加用户的网络请求const { data: res } await this.$http.post(users, this.addForm)if (res.meta.status ! 201) {this.$message.error(添加用户失败)}this.$message.success(添加用户成功)// 隐藏添加用户的对话框this.addDialogVisible false// 重新获取用户列表数据this.getUserList()})},// 展示编辑用户的对话框async showEditDialog(id) {// console.log(id)const { data: res } await this.$http.get(users/ id)if (res.meta.status ! 200) {return this.$message.error(查询用户信息失败)}this.editForm res.datathis.editDialogVisible true},// 监听修改用户对话框的关闭事件editDialogClosed() {this.$refs.editFormRef.resetFields()},// 修改用户信息并提交editUserInfo() {this.$refs.editFormRef.validate(async valid {if (!valid) return// 发起修改用户信息的数据请求const { data: res } await this.$http.put(users/ this.editForm.id,{email: this.editForm.email,mobile: this.editForm.mobile})if (res.meta.status ! 200) {return this.$message.error(更新用户信息失败)}// 关闭对话框this.editDialogVisible false// 刷新数据列表this.getUserList()// 提示修改成功this.$message.success(更新用户信息成功)})},// 根据Id删除对应的用户信息async removeUserById(id) {// 弹框询问用户是否删除数据const confirmResult await this.$confirm(此操作将永久删除该用户, 是否继续?,提示,{confirmButtonText: 确定,cancelButtonText: 取消,type: warning}).catch(err err)// 如果用户确认删除则返回值为字符串 confirm// 如果用户取消了删除则返回值为字符串 cancel// console.log(confirmResult)if (confirmResult ! confirm) {return this.$message.info(已取消删除)}const { data: res } await this.$http.delete(users/ id)if (res.meta.status ! 200) {return this.$message.error(删除用户失败)}this.$message.success(删除用户成功)this.getUserList()},// 展示分配角色的对话框async setRole(userInfo) {this.userInfo userInfo// 在展示对话框之前获取所有角色的列表const { data: res } await this.$http.get(roles)if (res.meta.status ! 200) {return this.$message.error(获取角色列表失败)}this.rolesList res.datathis.setRoleDialogVisible true},// 点击按钮分配角色async saveRoleInfo() {if (!this.selectedRoleId) {return this.$message.error(请选择要分配的角色)}const { data: res } await this.$http.put(users/${this.userInfo.id}/role,{rid: this.selectedRoleId})if (res.meta.status ! 200) {return this.$message.error(更新角色失败)}this.$message.success(更新角色成功)this.getUserList()this.setRoleDialogVisible false},// 监听分配角色对话框的关闭事件setRoleDialogClosed() {this.selectedRoleId this.userInfo {}}}
}
/scriptstyle langless scoped
/style
权限管理
角色列表
角色列表中可以创建新的角色创建的新的角色可以在用户管理中赋予用户同时可以为已有的角色赋予权限
templatediv!-- 面包屑导航区域 --el-breadcrumb separator-classel-icon-arrow-rightel-breadcrumb-item :to{ path: /home }首页/el-breadcrumb-itemel-breadcrumb-item权限管理/el-breadcrumb-itemel-breadcrumb-item角色列表/el-breadcrumb-item/el-breadcrumb!-- 卡片视图 --el-card!-- 添加角色按钮区域 --el-rowel-colel-button typeprimary添加角色/el-button/el-col/el-row!-- 角色列表区域 --el-table :datarolelist border stripe!-- 展开列 --el-table-column typeexpandtemplate slot-scopescopeel-row :class[bdbottom, i1 0 ? bdtop : , vcenter] v-for(item1, i1) in scope.row.children :keyitem1.id!-- 渲染一级权限 --el-col :span5el-tag closable closeremoveRightById(scope.row, item1.id){{item1.authName}}/el-tagi classel-icon-caret-right/i/el-col!-- 渲染二级和三级权限 --el-col :span19!-- 通过 for 循环 嵌套渲染二级权限 --el-row :class[i2 0 ? : bdtop, vcenter] v-for(item2, i2) in item1.children :keyitem2.idel-col :span6el-tag typesuccess closable closeremoveRightById(scope.row, item2.id){{item2.authName}}/el-tagi classel-icon-caret-right/i/el-colel-col :span18el-tag typewarning v-foritem3 in item2.children :keyitem3.id closable closeremoveRightById(scope.row, item3.id){{item3.authName}}/el-tag/el-col/el-row/el-col/el-row!-- pre{{scope.row}}/pre --/template/el-table-column!-- 索引列 --el-table-column typeindex/el-table-columnel-table-column label角色名称 proproleName/el-table-columnel-table-column label角色描述 proproleDesc/el-table-columnel-table-column label操作 width300pxtemplate slot-scopescopeel-button sizemini typeprimary iconel-icon-edit编辑/el-buttonel-button sizemini typedanger iconel-icon-delete删除/el-buttonel-button sizemini typewarning iconel-icon-setting clickshowSetRightDialog(scope.row)分配权限/el-button/template/el-table-column/el-table/el-card!-- 分配权限的对话框 --el-dialog title分配权限 :visible.syncsetRightDialogVisible width50% closesetRightDialogClosed!-- 树形控件 --el-tree :datarightslist :propstreeProps show-checkbox node-keyid default-expand-all :default-checked-keysdefKeys reftreeRef/el-treespan slotfooter classdialog-footerel-button clicksetRightDialogVisible false取 消/el-buttonel-button typeprimary clickallotRights确 定/el-button/span/el-dialog/div
/templatescript
export default {data() {return {// 所有角色列表数据rolelist: [],// 控制分配权限对话框的显示与隐藏setRightDialogVisible: false,// 所有权限的数据rightslist: [],// 树形控件的属性绑定对象treeProps: {label: authName,children: children},// 默认选中的节点Id值数组defKeys: [],// 当前即将分配权限的角色idroleId: }},created() {this.getRolesList()},methods: {// 获取所有角色的列表async getRolesList() {const { data: res } await this.$http.get(roles)if (res.meta.status ! 200) {return this.$message.error(获取角色列表失败)}this.rolelist res.dataconsole.log(this.rolelist)},// 根据Id删除对应的权限async removeRightById(role, rightId) {// 弹框提示用户是否要删除const confirmResult await this.$confirm(此操作将永久删除该文件, 是否继续?,提示,{confirmButtonText: 确定,cancelButtonText: 取消,type: warning}).catch(err err)if (confirmResult ! confirm) {return this.$message.info(取消了删除)}const { data: res } await this.$http.delete(roles/${role.id}/rights/${rightId})if (res.meta.status ! 200) {return this.$message.error(删除权限失败)}// this.getRolesList()role.children res.data},// 展示分配权限的对话框async showSetRightDialog(role) {this.roleId role.id// 获取所有权限的数据const { data: res } await this.$http.get(rights/tree)if (res.meta.status ! 200) {return this.$message.error(获取权限数据失败)}// 把获取到的权限数据保存到 data 中this.rightslist res.dataconsole.log(this.rightslist)// 递归获取三级节点的Idthis.getLeafKeys(role, this.defKeys)this.setRightDialogVisible true},// 通过递归的形式获取角色下所有三级权限的id并保存到 defKeys 数组中getLeafKeys(node, arr) {// 如果当前 node 节点不包含 children 属性则是三级节点if (!node.children) {return arr.push(node.id)}node.children.forEach(item this.getLeafKeys(item, arr))},// 监听分配权限对话框的关闭事件setRightDialogClosed() {this.defKeys []},// 点击为角色分配权限async allotRights() {const keys [...this.$refs.treeRef.getCheckedKeys(),...this.$refs.treeRef.getHalfCheckedKeys()]const idStr keys.join(,)const { data: res } await this.$http.post(roles/${this.roleId}/rights,{ rids: idStr })if (res.meta.status ! 200) {return this.$message.error(分配权限失败)}this.$message.success(分配权限成功)this.getRolesList()this.setRightDialogVisible false}}
}
/scriptstyle langless scoped
.el-tag {margin: 7px;
}.bdtop {border-top: 1px solid #eee;
}.bdbottom {border-bottom: 1px solid #eee;
}.vcenter {display: flex;align-items: center;
}
/style权限列表
权限列表对不同的权限做出展示只发送一个请求即可获取所有需要的数据
templatediv!-- 面包屑导航区域 --el-breadcrumb separator-classel-icon-arrow-rightel-breadcrumb-item :to{ path: /home }首页/el-breadcrumb-itemel-breadcrumb-item权限管理/el-breadcrumb-itemel-breadcrumb-item权限列表/el-breadcrumb-item/el-breadcrumb!-- 卡片视图 --el-cardel-table :datarightsList border stripeel-table-column typeindex/el-table-columnel-table-column label权限名称 propauthName/el-table-columnel-table-column label路径 proppath/el-table-columnel-table-column label权限等级 propleveltemplate slot-scopescopeel-tag v-ifscope.row.level 0一级/el-tagel-tag typesuccess v-else-ifscope.row.level 1二级/el-tagel-tag typewarning v-else三级/el-tag/template/el-table-column/el-table/el-card/div
/templatescript
export default {data() {return {// 权限列表rightsList: []}},created() {// 获取所有的权限this.getRightsList()},methods: {// 获取权限列表async getRightsList() {const { data: res } await this.$http.get(rights/list)if (res.meta.status ! 200) {return this.$message.error(获取权限列表失败)}this.rightsList res.dataconsole.log(this.rightsList)}}
}
/scriptstyle langless scoped
/style
商品管理
商品分类
templatediv!-- 面包屑导航区域 --el-breadcrumb separator-classel-icon-arrow-rightel-breadcrumb-item :to{ path: /home }首页/el-breadcrumb-itemel-breadcrumb-item商品管理/el-breadcrumb-itemel-breadcrumb-item商品分类/el-breadcrumb-item/el-breadcrumb!-- 卡片视图区域 --el-cardel-rowel-colel-button typeprimary clickshowAddCateDialog添加分类/el-button/el-col/el-row!-- 表格 --tree-table classtreeTable :datacatelist :columnscolumns :selection-typefalse :expand-typefalse show-index index-text# border :show-row-hoverfalse!-- 是否有效 --template slotisok slot-scopescopei classel-icon-success v-ifscope.row.cat_deleted false stylecolor: lightgreen;/ii classel-icon-error v-else stylecolor: red;/i/template!-- 排序 --template slotorder slot-scopescopeel-tag sizemini v-ifscope.row.cat_level0一级/el-tagel-tag typesuccess sizemini v-else-ifscope.row.cat_level1二级/el-tagel-tag typewarning sizemini v-else三级/el-tag/template!-- 操作 --template slotoptel-button typeprimary iconel-icon-edit sizemini编辑/el-buttonel-button typedanger iconel-icon-delete sizemini删除/el-button/template/tree-table!-- 分页区域 --el-pagination size-changehandleSizeChange current-changehandleCurrentChange :current-pagequerInfo.pagenum :page-sizes[3, 5, 10, 15] :page-sizequerInfo.pagesize layouttotal, sizes, prev, pager, next, jumper :totaltotal/el-pagination/el-card!-- 添加分类的对话框 --el-dialog title添加分类 :visible.syncaddCateDialogVisible width50% closeaddCateDialogClosed!-- 添加分类的表单 --el-form :modeladdCateForm :rulesaddCateFormRules refaddCateFormRef label-width100pxel-form-item label分类名称 propcat_nameel-input v-modeladdCateForm.cat_name/el-input/el-form-itemel-form-item label父级分类!-- options 用来指定数据源 --!-- props 用来指定配置对象 --el-cascader expand-triggerhover :optionsparentCateList :propscascaderProps v-modelselectedKeys changeparentCateChanged clearable change-on-select/el-cascader/el-form-item/el-formspan slotfooter classdialog-footerel-button clickaddCateDialogVisible false取 消/el-buttonel-button typeprimary clickaddCate确 定/el-button/span/el-dialog/div
/templatescript
export default {data() {return {// 查询条件querInfo: {type: 3,pagenum: 1,pagesize: 5},// 商品分类的数据列表默认为空catelist: [],// 总数据条数total: 0,// 为table指定列的定义columns: [{label: 分类名称,prop: cat_name},{label: 是否有效,// 表示将当前列定义为模板列type: template,// 表示当前这一列使用模板名称template: isok},{label: 排序,// 表示将当前列定义为模板列type: template,// 表示当前这一列使用模板名称template: order},{label: 操作,// 表示将当前列定义为模板列type: template,// 表示当前这一列使用模板名称template: opt}],// 控制添加分类对话框的显示与隐藏addCateDialogVisible: false,// 添加分类的表单数据对象addCateForm: {// 将要添加的分类的名称cat_name: ,// 父级分类的Idcat_pid: 0,// 分类的等级默认要添加的是1级分类cat_level: 0},// 添加分类表单的验证规则对象addCateFormRules: {cat_name: [{ required: true, message: 请输入分类名称, trigger: blur }]},// 父级分类的列表parentCateList: [],// 指定级联选择器的配置对象cascaderProps: {value: cat_id,label: cat_name,children: children},// 选中的父级分类的Id数组selectedKeys: []}},created() {this.getCateList()},methods: {// 获取商品分类数据async getCateList() {const { data: res } await this.$http.get(categories, {params: this.querInfo})if (res.meta.status ! 200) {return this.$message.error(获取商品分类失败)}console.log(res.data)// 把数据列表赋值给 catelistthis.catelist res.data.result// 为总数据条数赋值this.total res.data.total},// 监听 pagesize 改变handleSizeChange(newSize) {this.querInfo.pagesize newSizethis.getCateList()},// 监听 pagenum 改变handleCurrentChange(newPage) {this.querInfo.pagenum newPagethis.getCateList()},// 点击按钮展示添加分类的对话框showAddCateDialog() {// 先获取父级分类的数据列表this.getParentCateList()// 再展示出对话框this.addCateDialogVisible true},// 获取父级分类的数据列表async getParentCateList() {const { data: res } await this.$http.get(categories, {params: { type: 2 }})if (res.meta.status ! 200) {return this.$message.error(获取父级分类数据失败)}console.log(res.data)this.parentCateList res.data},// 选择项发生变化触发这个函数parentCateChanged() {console.log(this.selectedKeys)// 如果 selectedKeys 数组中的 length 大于0证明选中的父级分类// 反之就说明没有选中任何父级分类if (this.selectedKeys.length 0) {// 父级分类的Idthis.addCateForm.cat_pid this.selectedKeys[this.selectedKeys.length - 1]// 为当前分类的等级赋值this.addCateForm.cat_level this.selectedKeys.length} else {// 父级分类的Idthis.addCateForm.cat_pid 0// 为当前分类的等级赋值this.addCateForm.cat_level 0}},// 点击按钮添加新的分类addCate() {this.$refs.addCateFormRef.validate(async valid {if (!valid) returnconst { data: res } await this.$http.post(categories, this.addCateForm)if (res.meta.status ! 201) {return this.$message.error(添加分类失败)}this.$message.success(添加分类成功)this.getCateList()this.addCateDialogVisible false})},// 监听对话框的关闭事件重置表单数据addCateDialogClosed() {this.$refs.addCateFormRef.resetFields()this.selectedKeys []this.addCateForm.cat_level 0this.addCateForm.cat_pid 0}}
}
/scriptstyle langless scoped
.treeTable {margin-top: 15px;
}.el-cascader {width: 100%;
}
/style商品列表
templatediv!-- 面包屑导航区域 --el-breadcrumb separator-classel-icon-arrow-rightel-breadcrumb-item :to{ path: /home }首页/el-breadcrumb-itemel-breadcrumb-item商品管理/el-breadcrumb-itemel-breadcrumb-item商品列表/el-breadcrumb-item/el-breadcrumb!-- 卡片视图区域 --el-cardel-row :gutter20el-col :span8el-input placeholder请输入内容 v-modelqueryInfo.query clearable cleargetGoodsListel-button slotappend iconel-icon-search clickgetGoodsList/el-button/el-input/el-colel-col :span4el-button typeprimary clickgoAddpage添加商品/el-button/el-col/el-row!-- table表格区域 --el-table :datagoodslist border stripeel-table-column typeindex/el-table-columnel-table-column label商品名称 propgoods_name/el-table-columnel-table-column label商品价格(元) propgoods_price width95px/el-table-columnel-table-column label商品重量 propgoods_weight width70px/el-table-columnel-table-column label创建时间 propadd_time width140pxtemplate slot-scopescope{{scope.row.add_time | dateFormat}}/template/el-table-columnel-table-column label操作 width130pxtemplate slot-scopescopeel-button typeprimary iconel-icon-edit sizemini/el-buttonel-button typedanger iconel-icon-delete sizemini clickremoveById(scope.row.goods_id)/el-button/template/el-table-column/el-table!-- 分页区域 --el-pagination size-changehandleSizeChange current-changehandleCurrentChange :current-pagequeryInfo.pagenum :page-sizes[5, 10, 15, 20] :page-sizequeryInfo.pagesize layouttotal, sizes, prev, pager, next, jumper :totaltotal background/el-pagination/el-card/div
/templatescript
export default {data() {return {// 查询参数对象queryInfo: {query: ,pagenum: 1,pagesize: 10},// 商品列表goodslist: [],// 总数据条数total: 0}},created() {this.getGoodsList()},methods: {// 根据分页获取对应的商品列表async getGoodsList() {const { data: res } await this.$http.get(goods, {params: this.queryInfo})if (res.meta.status ! 200) {return this.$message.error(获取商品列表失败)}this.$message.success(获取商品列表成功)console.log(res.data)this.goodslist res.data.goodsthis.total res.data.total},handleSizeChange(newSize) {this.queryInfo.pagesize newSizethis.getGoodsList()},handleCurrentChange(newPage) {this.queryInfo.pagenum newPagethis.getGoodsList()},async removeById(id) {const confirmResult await this.$confirm(此操作将永久删除该商品, 是否继续?,提示,{confirmButtonText: 确定,cancelButtonText: 取消,type: warning}).catch(err err)if (confirmResult ! confirm) {return this.$message.info(已经取消删除)}const { data: res } await this.$http.delete(goods/${id})if (res.meta.status ! 200) {return this.$message.error(删除失败)}this.$message.success(删除成功)this.getGoodsList()},goAddpage() {this.$router.push(/goods/add)}}
}
/scriptstyle langless scoped
/style
增加商品
在商品分类中点击新增商品则跳转到新增商品窗口 templatediv!-- 面包屑导航区域 --el-breadcrumb separator-classel-icon-arrow-rightel-breadcrumb-item :to{ path: /home }首页/el-breadcrumb-itemel-breadcrumb-item商品管理/el-breadcrumb-itemel-breadcrumb-item添加商品/el-breadcrumb-item/el-breadcrumb!-- 卡片视图 --el-card!-- 提示区域 --el-alert title添加商品信息 typeinfo center show-icon :closablefalse/el-alert!-- 步骤条区域 --el-steps :space200 :activeactiveIndex - 0 finish-statussuccess align-centerel-step title基本信息/el-stepel-step title商品参数/el-stepel-step title商品属性/el-stepel-step title商品图片/el-stepel-step title商品内容/el-stepel-step title完成/el-step/el-steps!-- tab栏区域 --el-form :modeladdForm :rulesaddFormRules refaddFormRef label-width100px label-positiontopel-tabs v-modelactiveIndex :tab-positionleft :before-leavebeforeTabLeave tab-clicktabClickedel-tab-pane label基本信息 name0el-form-item label商品名称 propgoods_nameel-input v-modeladdForm.goods_name/el-input/el-form-itemel-form-item label商品价格 propgoods_priceel-input v-modeladdForm.goods_price typenumber/el-input/el-form-itemel-form-item label商品重量 propgoods_weightel-input v-modeladdForm.goods_weight typenumber/el-input/el-form-itemel-form-item label商品数量 propgoods_numberel-input v-modeladdForm.goods_number typenumber/el-input/el-form-itemel-form-item label商品分类 propgoods_catel-cascader expand-triggerhover :optionscatelist :propscateProps v-modeladdForm.goods_cat changehandleChange/el-cascader/el-form-item/el-tab-paneel-tab-pane label商品参数 name1!-- 渲染表单的Item项 --el-form-item :labelitem.attr_name v-foritem in manyTableData :keyitem.attr_id!-- 复选框组 --el-checkbox-group v-modelitem.attr_valsel-checkbox :labelcb v-for(cb, i) in item.attr_vals :keyi border/el-checkbox/el-checkbox-group/el-form-item/el-tab-paneel-tab-pane label商品属性 name2el-form-item :labelitem.attr_name v-foritem in onlyTableData :keyitem.attr_idel-input v-modelitem.attr_vals/el-input/el-form-item/el-tab-paneel-tab-pane label商品图片 name3!-- action 表示图片要上传到的后台API地址 --el-upload :actionuploadURL :on-previewhandlePreview :on-removehandleRemove list-typepicture :headersheaderObj :on-successhandleSuccessel-button sizesmall typeprimary点击上传/el-button/el-upload/el-tab-paneel-tab-pane label商品内容 name4!-- 富文本编辑器组件 --quill-editor v-modeladdForm.goods_introduce/quill-editor!-- 添加商品的按钮 --el-button typeprimary classbtnAdd clickadd添加商品/el-button/el-tab-pane/el-tabs/el-form/el-card!-- 图片预览 --el-dialog title图片预览 :visible.syncpreviewVisible width50%img :srcpreviewPath alt classpreviewImg/el-dialog/div
/templatescript
import _ from lodashexport default {data() {return {activeIndex: 0,// 添加商品的表单数据对象addForm: {goods_name: ,goods_price: 0,goods_weight: 0,goods_number: 0,// 商品所属的分类数组goods_cat: [],// 图片的数组pics: [],// 商品的详情描述goods_introduce: ,attrs: []},addFormRules: {goods_name: [{ required: true, message: 请输入商品名称, trigger: blur }],goods_price: [{ required: true, message: 请输入商品价格, trigger: blur }],goods_weight: [{ required: true, message: 请输入商品重量, trigger: blur }],goods_number: [{ required: true, message: 请输入商品数量, trigger: blur }],goods_cat: [{ required: true, message: 请选择商品分类, trigger: blur }]},// 商品分类列表catelist: [],cateProps: {label: cat_name,value: cat_id,children: children},// 动态参数列表数据manyTableData: [],// 静态属性列表数据onlyTableData: [],// 上传图片的URL地址uploadURL: http://127.0.0.1:8888/api/private/v1/upload,// 图片上传组件的headers请求头对象headerObj: {Authorization: window.sessionStorage.getItem(token)},previewPath: ,previewVisible: false}},created() {this.getCateList()},methods: {// 获取所有商品分类数据async getCateList() {const { data: res } await this.$http.get(categories)if (res.meta.status ! 200) {return this.$message.error(获取商品分类数据失败)}this.catelist res.dataconsole.log(this.catelist)},// 级联选择器选中项变化会触发这个函数handleChange() {console.log(this.addForm.goods_cat)if (this.addForm.goods_cat.length ! 3) {this.addForm.goods_cat []}},beforeTabLeave(activeName, oldActiveName) {// console.log(即将离开的标签页名字是 oldActiveName)// console.log(即将进入的标签页名字是 activeName)// return falseif (oldActiveName 0 this.addForm.goods_cat.length ! 3) {this.$message.error(请先选择商品分类)return false}},async tabClicked() {// console.log(this.activeIndex)// 证明访问的是动态参数面板if (this.activeIndex 1) {const { data: res } await this.$http.get(categories/${this.cateId}/attributes,{params: { sel: many }})if (res.meta.status ! 200) {return this.$message.error(获取动态参数列表失败)}console.log(res.data)res.data.forEach(item {item.attr_vals item.attr_vals.length 0 ? [] : item.attr_vals.split( )})this.manyTableData res.data} else if (this.activeIndex 2) {const { data: res } await this.$http.get(categories/${this.cateId}/attributes,{params: { sel: only }})if (res.meta.status ! 200) {return this.$message.error(获取静态属性失败)}console.log(res.data)this.onlyTableData res.data}},// 处理图片预览效果handlePreview(file) {console.log(file)this.previewPath file.response.data.urlthis.previewVisible true},// 处理移除图片的操作handleRemove(file) {// console.log(file)// 1. 获取将要删除的图片的临时路径const filePath file.response.data.tmp_path// 2. 从 pics 数组中找到这个图片对应的索引值const i this.addForm.pics.findIndex(x x.pic filePath)// 3. 调用数组的 splice 方法把图片信息对象从 pics 数组中移除this.addForm.pics.splice(i, 1)console.log(this.addForm)},// 监听图片上传成功的事件handleSuccess(response) {console.log(response)// 1. 拼接得到一个图片信息对象const picInfo { pic: response.data.tmp_path }// 2. 将图片信息对象push 到pics数组中this.addForm.pics.push(picInfo)console.log(this.addForm)},// 添加商品add() {this.$refs.addFormRef.validate(async valid {if (!valid) {return this.$message.error(请填写必要的表单项)}// 执行添加的业务逻辑// lodash cloneDeep(obj)const form _.cloneDeep(this.addForm)form.goods_cat form.goods_cat.join(,)// 处理动态参数this.manyTableData.forEach(item {const newInfo {attr_id: item.attr_id,attr_value: item.attr_vals.join( )}this.addForm.attrs.push(newInfo)})// 处理静态属性this.onlyTableData.forEach(item {const newInfo { attr_id: item.attr_id, attr_value: item.attr_vals }this.addForm.attrs.push(newInfo)})form.attrs this.addForm.attrsconsole.log(form)// 发起请求添加商品// 商品的名称必须是唯一的const { data: res } await this.$http.post(goods, form)if (res.meta.status ! 201) {return this.$message.error(添加商品失败)}this.$message.success(添加商品成功)this.$router.push(/goods)})}},computed: {cateId() {if (this.addForm.goods_cat.length 3) {return this.addForm.goods_cat[2]}return null}}
}
/scriptstyle langless scoped
.el-checkbox {margin: 0 10px 0 0 !important;
}.previewImg {width: 100%;
}.btnAdd {margin-top: 15px;
}
/style
分类参数
在分类参数中选择一件商品可以为其添加静态或者动态参数这个参数可以展示在移动端商品的属性中。 templatediv!-- 面包屑导航区域 --el-breadcrumb separator-classel-icon-arrow-rightel-breadcrumb-item :to{ path: /home }首页/el-breadcrumb-itemel-breadcrumb-item商品管理/el-breadcrumb-itemel-breadcrumb-item参数列表/el-breadcrumb-item/el-breadcrumb!-- 卡片视图区域 --el-card!-- 警告区域 --el-alert show-icon title注意只允许为第三级分类设置相关参数 typewarning :closablefalse/el-alert!-- 选择商品分类区域 --el-row classcat_optel-colspan选择商品分类/span!-- 选择商品分类的级联选择框 --el-cascader expand-triggerhover :optionscatelist :propscateProps v-modelselectedCateKeys changehandleChange/el-cascader/el-col/el-row!-- tab 页签区域 --el-tabs v-modelactiveName tab-clickhandleTabClick!-- 添加动态参数的面板 --el-tab-pane label动态参数 namemany!-- 添加参数的按钮 --el-button typeprimary sizemini :disabledisBtnDisabled clickaddDialogVisibletrue添加参数/el-button!-- 动态参数表格 --el-table :datamanyTableData border stripe!-- 展开行 --el-table-column typeexpandtemplate slot-scopescope!-- 循环渲染Tag标签 --el-tag v-for(item, i) in scope.row.attr_vals :keyi closable closehandleClose(i, scope.row){{item}}/el-tag!-- 输入的文本框 --el-input classinput-new-tag v-ifscope.row.inputVisible v-modelscope.row.inputValue refsaveTagInput sizesmall keyup.enter.nativehandleInputConfirm(scope.row) blurhandleInputConfirm(scope.row)/el-input!-- 添加按钮 --el-button v-else classbutton-new-tag sizesmall clickshowInput(scope.row) New Tag/el-button/template/el-table-column!-- 索引列 --el-table-column typeindex/el-table-columnel-table-column label参数名称 propattr_name/el-table-columnel-table-column label操作template slot-scopescopeel-button sizemini typeprimary iconel-icon-edit clickshowEditDialog(scope.row.attr_id)编辑/el-buttonel-button sizemini typedanger iconel-icon-delete clickremoveParams(scope.row.attr_id)删除/el-button/template/el-table-column/el-table/el-tab-pane!-- 添加静态属性的面板 --el-tab-pane label静态属性 nameonly!-- 添加属性的按钮 --el-button typeprimary sizemini :disabledisBtnDisabled clickaddDialogVisibletrue添加属性/el-button!-- 静态属性表格 --el-table :dataonlyTableData border stripe!-- 展开行 --el-table-column typeexpandtemplate slot-scopescope!-- 循环渲染Tag标签 --el-tag v-for(item, i) in scope.row.attr_vals :keyi closable closehandleClose(i, scope.row){{item}}/el-tag!-- 输入的文本框 --el-input classinput-new-tag v-ifscope.row.inputVisible v-modelscope.row.inputValue refsaveTagInput sizesmall keyup.enter.nativehandleInputConfirm(scope.row) blurhandleInputConfirm(scope.row)/el-input!-- 添加按钮 --el-button v-else classbutton-new-tag sizesmall clickshowInput(scope.row) New Tag/el-button/template/el-table-column!-- 索引列 --el-table-column typeindex/el-table-columnel-table-column label属性名称 propattr_name/el-table-columnel-table-column label操作template slot-scopescopeel-button sizemini typeprimary iconel-icon-edit clickshowEditDialog(scope.row.attr_id)编辑/el-buttonel-button sizemini typedanger iconel-icon-delete clickremoveParams(scope.row.attr_id)删除/el-button/template/el-table-column/el-table/el-tab-pane/el-tabs/el-card!-- 添加参数的对话框 --el-dialog :title添加 titleText :visible.syncaddDialogVisible width50% closeaddDialogClosed!-- 添加参数的对话框 --el-form :modeladdForm :rulesaddFormRules refaddFormRef label-width100pxel-form-item :labeltitleText propattr_nameel-input v-modeladdForm.attr_name/el-input/el-form-item/el-formspan slotfooter classdialog-footerel-button clickaddDialogVisible false取 消/el-buttonel-button typeprimary clickaddParams确 定/el-button/span/el-dialog!-- 修改参数的对话框 --el-dialog :title修改 titleText :visible.synceditDialogVisible width50% closeeditDialogClosed!-- 添加参数的对话框 --el-form :modeleditForm :ruleseditFormRules refeditFormRef label-width100pxel-form-item :labeltitleText propattr_nameel-input v-modeleditForm.attr_name/el-input/el-form-item/el-formspan slotfooter classdialog-footerel-button clickeditDialogVisible false取 消/el-buttonel-button typeprimary clickeditParams确 定/el-button/span/el-dialog/div
/templatescript
export default {data() {return {// 商品分类列表catelist: [],// 级联选择框的配置对象cateProps: {value: cat_id,label: cat_name,children: children},// 级联选择框双向绑定到的数组selectedCateKeys: [],// 被激活的页签的名称activeName: many,// 动态参数的数据manyTableData: [],// 静态属性的数据onlyTableData: [],// 控制添加对话框的显示与隐藏addDialogVisible: false,// 添加参数的表单数据对象addForm: {attr_name: },// 添加表单的验证规则对象addFormRules: {attr_name: [{ required: true, message: 请输入参数名称, trigger: blur }]},// 控制修改对话框的显示与隐藏editDialogVisible: false,// 修改的表单数据对象editForm: {},// 修改表单的验证规则对象editFormRules: {attr_name: [{ required: true, message: 请输入参数名称, trigger: blur }]}}},created() {this.getCateList()},methods: {// 获取所有的商品分类列表async getCateList() {const { data: res } await this.$http.get(categories)if (res.meta.status ! 200) {return this.$message.error(获取商品分类失败)}this.catelist res.dataconsole.log(this.catelist)},// 级联选择框选中项变化会触发这个函数handleChange() {this.getParamsData()},// tab 页签点击事件的处理函数handleTabClick() {console.log(this.activeName)this.getParamsData()},// 获取参数的列表数据async getParamsData() {// 证明选中的不是三级分类if (this.selectedCateKeys.length ! 3) {this.selectedCateKeys []this.manyTableData []this.onlyTableData []return}// 证明选中的是三级分类console.log(this.selectedCateKeys)// 根据所选分类的Id和当前所处的面板获取对应的参数const { data: res } await this.$http.get(categories/${this.cateId}/attributes,{params: { sel: this.activeName }})if (res.meta.status ! 200) {return this.$message.error(获取参数列表失败)}res.data.forEach(item {item.attr_vals item.attr_vals ? item.attr_vals.split( ) : []// 控制文本框的显示与隐藏item.inputVisible false// 文本框中输入的值item.inputValue })console.log(res.data)if (this.activeName many) {this.manyTableData res.data} else {this.onlyTableData res.data}},// 监听添加对话框的关闭事件addDialogClosed() {this.$refs.addFormRef.resetFields()},// 点击按钮添加参数addParams() {this.$refs.addFormRef.validate(async valid {if (!valid) returnconst { data: res } await this.$http.post(categories/${this.cateId}/attributes,{attr_name: this.addForm.attr_name,attr_sel: this.activeName})if (res.meta.status ! 201) {return this.$message.error(添加参数失败)}this.$message.success(添加参数成功)this.addDialogVisible falsethis.getParamsData()})},// 点击按钮展示修改的对话框async showEditDialog(attrId) {// 查询当前参数的信息const { data: res } await this.$http.get(categories/${this.cateId}/attributes/${attrId},{params: { attr_sel: this.activeName }})if (res.meta.status ! 200) {return this.$message.error(获取参数信息失败)}this.editForm res.datathis.editDialogVisible true},// 重置修改的表单editDialogClosed() {this.$refs.editFormRef.resetFields()},// 点击按钮修改参数信息editParams() {this.$refs.editFormRef.validate(async valid {if (!valid) returnconst { data: res } await this.$http.put(categories/${this.cateId}/attributes/${this.editForm.attr_id},{ attr_name: this.editForm.attr_name, attr_sel: this.activeName })if (res.meta.status ! 200) {return this.$message.error(修改参数失败)}this.$message.success(修改参数成功)this.getParamsData()this.editDialogVisible false})},// 根据Id删除对应的参数项async removeParams(attrId) {const confirmResult await this.$confirm(此操作将永久删除该参数, 是否继续?,提示,{confirmButtonText: 确定,cancelButtonText: 取消,type: warning}).catch(err err)// 用户取消了删除的操作if (confirmResult ! confirm) {return this.$message.info(已取消删除)}// 删除的业务逻辑const { data: res } await this.$http.delete(categories/${this.cateId}/attributes/${attrId})if (res.meta.status ! 200) {return this.$message.error(删除参数失败)}this.$message.success(删除参数成功)this.getParamsData()},// 文本框失去焦点或摁下了 Enter 都会触发async handleInputConfirm(row) {if (row.inputValue.trim().length 0) {row.inputValue row.inputVisible falsereturn}// 如果没有return则证明输入的内容需要做后续处理row.attr_vals.push(row.inputValue.trim())row.inputValue row.inputVisible false// 需要发起请求保存这次操作this.saveAttrVals(row)},// 将对 attr_vals 的操作保存到数据库async saveAttrVals(row) {// 需要发起请求保存这次操作const { data: res } await this.$http.put(categories/${this.cateId}/attributes/${row.attr_id},{attr_name: row.attr_name,attr_sel: row.attr_sel,attr_vals: row.attr_vals.join( )})if (res.meta.status ! 200) {return this.$message.error(修改参数项失败)}this.$message.success(修改参数项成功)},// 点击按钮展示文本输入框showInput(row) {row.inputVisible true// 让文本框自动获得焦点// $nextTick 方法的作用就是当页面上元素被重新渲染之后才会指定回调函数中的代码this.$nextTick(_ {this.$refs.saveTagInput.$refs.input.focus()})},// 删除对应的参数可选项handleClose(i, row) {row.attr_vals.splice(i, 1)this.saveAttrVals(row)}},computed: {// 如果按钮需要被禁用则返回true否则返回falseisBtnDisabled() {if (this.selectedCateKeys.length ! 3) {return true}return false},// 当前选中的三级分类的IdcateId() {if (this.selectedCateKeys.length 3) {return this.selectedCateKeys[2]}return null},// 动态计算标题的文本titleText() {if (this.activeName many) {return 动态参数}return 静态属性}}
}
/scriptstyle langless scoped
.cat_opt {margin: 15px 0;
}.el-tag {margin: 10px;
}.input-new-tag {width: 120px;
}
/style订单管理
订单列表
订单管理的实现和用户管理有很多类似的地方都是向后端发送请求然后渲染到页面上
templatediv!-- 面包屑导航区域 --el-breadcrumb separator-classel-icon-arrow-rightel-breadcrumb-item :to{ path: /home }首页/el-breadcrumb-itemel-breadcrumb-item订单管理/el-breadcrumb-itemel-breadcrumb-item订单列表/el-breadcrumb-item/el-breadcrumb!-- 卡片视图区域 --el-cardel-rowel-col :span8el-input placeholder请输入内容el-button slotappend iconel-icon-search/el-button/el-input/el-col/el-row!-- 订单列表数据 --el-table :dataorderlist border stripeel-table-column typeindex/el-table-columnel-table-column label订单编号 proporder_number/el-table-columnel-table-column label订单价格 proporder_price/el-table-columnel-table-column label是否付款 proppay_statustemplate slot-scopescopeel-tag typesuccess v-ifscope.row.pay_status 1已付款/el-tagel-tag typedanger v-else未付款/el-tag/template/el-table-columnel-table-column label是否发货 propis_sendtemplate slot-scopescopetemplate{{scope.row.is_send}}/template/template/el-table-columnel-table-column label下单时间 propcreate_timetemplate slot-scopescope{{scope.row.create_time | dateFormat}}/template/el-table-columnel-table-column label操作templateel-button sizemini typeprimary iconel-icon-edit clickshowBox/el-buttonel-button sizemini typesuccess iconel-icon-location clickshowProgressBox/el-button/template/el-table-column/el-table!-- 分页区域 --el-pagination size-changehandleSizeChange current-changehandleCurrentChange :current-pagequeryInfo.pagenum :page-sizes[5, 10, 15] :page-sizequeryInfo.pagesize layouttotal, sizes, prev, pager, next, jumper :totaltotal/el-pagination/el-card!-- 修改地址的对话框 --el-dialog title修改地址 :visible.syncaddressVisible width50% closeaddressDialogClosedel-form :modeladdressForm :rulesaddressFormRules refaddressFormRef label-width100pxel-form-item label省市区/县 propaddress1el-cascader :optionscityData v-modeladdressForm.address1/el-cascader/el-form-itemel-form-item label详细地址 propaddress2el-input v-modeladdressForm.address2/el-input/el-form-item/el-formspan slotfooter classdialog-footerel-button clickaddressVisible false取 消/el-buttonel-button typeprimary clickaddressVisible false确 定/el-button/span/el-dialog!-- 展示物流进度的对话框 --el-dialog title物流进度 :visible.syncprogressVisible width50%!-- 时间线 --el-timelineel-timeline-item v-for(activity, index) in progressInfo :keyindex :timestampactivity.time{{activity.context}}/el-timeline-item/el-timeline/el-dialog/div
/templatescript
import cityData from ./citydata.jsexport default {data() {return {queryInfo: {query: ,pagenum: 1,pagesize: 10},total: 0,orderlist: [],addressVisible: false,addressForm: {address1: [],address2: },addressFormRules: {address1: [{ required: true, message: 请选择省市区县, trigger: blur }],address2: [{ required: true, message: 请填写详细地址, trigger: blur }]},cityData,progressVisible: false,progressInfo: []}},created() {this.getOrderList()},methods: {async getOrderList() {const { data: res } await this.$http.get(orders, {params: this.queryInfo})if (res.meta.status ! 200) {return this.$message.error(获取订单列表失败)}console.log(res)this.total res.data.totalthis.orderlist res.data.goods},handleSizeChange(newSize) {this.queryInfo.pagesize newSizethis.getOrderList()},handleCurrentChange(newPage) {this.queryInfo.pagenum newPagethis.getOrderList()},// 展示修改地址的对话框showBox() {this.addressVisible true},addressDialogClosed() {this.$refs.addressFormRef.resetFields()},async showProgressBox() {const { data: res } await this.$http.get(/kuaidi/804909574412544580)if (res.meta.status ! 200) {return this.$message.error(获取物流进度失败)}this.progressInfo res.datathis.progressVisible trueconsole.log(this.progressInfo)}}
}
/scriptstyle langless scoped
import ../../plugins/timeline/timeline.css;
import ../../plugins/timeline-item/timeline-item.css;.el-cascader {width: 100%;
}
/style数据统计
数据报表
数据统计部分用到了echarts,从后端获得数据后通过 _.merge将数据组合在一起最后渲染在页面上
templatediv!-- 面包屑导航区域 --el-breadcrumb separator-classel-icon-arrow-rightel-breadcrumb-item :to{ path: /home }首页/el-breadcrumb-itemel-breadcrumb-item数据统计/el-breadcrumb-itemel-breadcrumb-item数据报表/el-breadcrumb-item/el-breadcrumb!-- 卡片视图区域 --el-card!-- 2. 为ECharts准备一个具备大小宽高的Dom --div idmain stylewidth: 750px;height:400px;/div/el-card/div
/templatescript
// 1. 导入 echarts
import echarts from echarts
import _ from lodashexport default {data() {return {// 需要合并的数据options: {title: {text: 用户来源},tooltip: {trigger: axis,axisPointer: {type: cross,label: {backgroundColor: #E9EEF3}}},grid: {left: 3%,right: 4%,bottom: 3%,containLabel: true},xAxis: [{boundaryGap: false}],yAxis: [{type: value}]}}},created() {},// 此时页面上的元素已经被渲染完毕了async mounted() {// 3. 基于准备好的dom初始化echarts实例var myChart echarts.init(document.getElementById(main))const { data: res } await this.$http.get(reports/type/1)if (res.meta.status ! 200) {return this.$message.error(获取折线图数据失败)}// 4. 准备数据和配置项const result _.merge(res.data, this.options)// 5. 展示数据myChart.setOption(result)},methods: {}
}
/scriptstyle langless scoped
/style
项目git地址
目录中有后端以及sql文件按照说明运行即可
电商系统前端: 电商管理系统前端
学习资源
黑马程序员前端