尚硅谷尚品汇_后台管理项目
vueProject_尚品汇项目源码文章目录vueProject_尚品汇登录登出product模块登录登出.env.development .evn.production .evn.staging用于wabpack的process变量属性来监测当前所处的开发环境根据当前所处的版本(开发环境)来确定baseUrlapi地址http://39.98.123.211:8170/swagger-ui.ht
·
vueProject_尚品汇后台管理
login/out模块
- .env.development .evn.production .evn.staging
- 用于wabpack的process变量属性来监测当前所处的开发环境
- 根据当前所处的版本(开发环境)来确定baseUrl
- api地址
- http://39.98.123.211:8170/swagger-ui.html#/
- http://39.98.123.211:8216/swagger-ui.html
- elementUI中文文档
- https://element.eleme.cn/#/zh-CN
- login & loginOut
- 将所有mock模拟的数据改成api接口
- vueAdmin\vue-admin-template-master\src\api\user.js
import request from '@/utils/request' export function login(data) { return request({ url: '/admin/acl/index/login', method: 'post', data }) } export function getInfo(token) { return request({ url: '/admin/acl/index/info', method: 'get', params: { token } }) } export function logout() { return request({ url: '/admin/acl/index/logout', method: 'post' }) }
- vueAdmin\vue-admin-template-master\src\api\user.js
- 解决跨域问题
- vueAdmin\vue-admin-template-master\vue.config.js
devServer: { port: port, open: true, overlay: { warnings: false, errors: true }, proxy: { '/dev-api': { target: "http://39.98.123.211", pathRewrite: { '^/dev-api': '' } } } },
- vueAdmin\vue-admin-template-master\vue.config.js
- 修改axios中的config.header
- vueAdmin\vue-admin-template-master\src\utils\request.js
config.headers['token'] = getToken()
- vueAdmin\vue-admin-template-master\src\utils\request.js
- 将所有mock模拟的数据改成api接口
product模块
- product 组件
- 修改相关路由
- 删除原有模板中不需要的路由
- 添加上需要的product的二级路由
- 每一个一级路由都需要使用Layout组件,及在Layout的基础上,再进行二级路由的拓展
- vueAdmin\vue-admin-template-master\src\router\index.js
{ path: '/product', component: Layout, name: 'Product', meta: { title: 'Product', icon: 'el-icon-goods' }, children: [ { path: 'tradeMark', name: 'TradeMark', component: () => import('@/views/product/TradeMark'), meta: { title: 'TradeMark' } }, { path: 'sku', name: 'Sku', component: () => import('@/views/product/Sku'), meta: { title: 'Sku' } }, { path: 'spu', name: 'Spu', component: () => import('@/views/product/Spu'), meta: { title: 'Spu' } }, { path: 'attr', name: 'Attr', component: () => import('@/views/product/Attr'), meta: { title: 'Attr' } } ] },
- 修改scss中的错误,使得内容区域有内边距
- vueAdmin\vue-admin-template-master\src\styles\index.scss
.app-main { padding: 20px; }
- vueAdmin\vue-admin-template-master\src\styles\index.scss
- product_TradeMark
- button & table & pagination (静态)
- el-button
- type 类型 string primary / success / warning / danger / info / text
- icon 图标类名 string -
- el-table
- 外边框可以通过border属性进行添加
- data 显示的数据 array -
- width 宽度 int -
- el-pagination
- page-size 每页显示条目个数,支持.sync修饰符 number 10
- total 总条目数 number —
- current-page 当前页数,支持.sync修饰符 number — 1
- pager-count 页码按钮的数量,当总页数超过该值时会折叠 number 大于等于5且小于等于21的奇数 7
- layout 组件布局,子组件名用逗号分隔 String sizes, prev, pager, next, jumper, ->, total, slot ‘prev, pager, next, jumper, ->, total’
- page-sizes 每页显示个数选择器的选项设置 number[] — [10, 20, 30, 40, 50, 100]
- @current-change currentPage 改变时会触发 当前页
- @size-change pageSize 改变时会触发 每页条数
- vueAdmin\vue-admin-template-master\src\views\product\TradeMark\index.vue
<template> <div> <el-button type="primary" icon="el-icon-plus">add</el-button> <el-table :data="tableData" border style="width: 100%"> <el-table-column prop="date" label="日期" width="180"> </el-table-column> <el-table-column prop="name" label="姓名" width="180"> </el-table-column> <el-table-column prop="address" label="地址"> </el-table-column> </el-table> <el-pagination style="margin-top:20px;textAlign: center" @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="1" :page-sizes="[10, 20, 30, 40]" :page-size="10" layout="prev, pager, next, jumper, ->, sizes, total" :total="400" > </el-pagination> </div> </template> //JavaScript data() { return { tableData: [ { date: "2016-05-02", name: "王小虎", address: "上海市普陀区金沙江路 1518 弄", }, { date: "2016-05-04", name: "王小虎", address: "上海市普陀区金沙江路 1517 弄", }, { date: "2016-05-01", name: "王小虎", address: "上海市普陀区金沙江路 1519 弄", }, { date: "2016-05-03", name: "王小虎", address: "上海市普陀区金沙江路 1516 弄", }, ], }; },
- api
- api_product模块
- 通过index(vueAdmin\vue-admin-template-master\src\api\index.js)统一暴露
- 并挂在到vue.prototype上,方便使用
- vueAdmin\vue-admin-template-master\src\api\product\tradeMark.js
/* ** admin/product/baseTrademark/{page}/{limit} get */ import request from '@/utils/request' export function reqTradeMark(page,limit){ return request({ url: `/admin/product/baseTrademark/${page}/${limit}`, method: 'get', }) }
- vueAdmin\vue-admin-template-master\src\api\index.js
import * as tradeMark from './product/tradeMark'; import * as attr from './product/attr'; import * as sku from './product/sku'; import * as spu from './product/spu'; export default { tradeMark, attr, sku, spu }
- vueAdmin\vue-admin-template-master\src\main.js
import api from './api'; Vue.prototype.$api = api;
- vueAdmin\vue-admin-template-master\src\api\product\tradeMark.js
- 通过发请求获取tradeMark数据传递给table以及pagination
- JavaScript
- vueAdmin\vue-admin-template-master\src\views\product\TradeMark\index.vue
data() { return { page: 1, limit: 4, total: 0, records: [], }; }, //挂载完毕时发请求获取tradeMark数据 mounted() { this.getTradeMark(); }, methods: { //封装请求 async getTradeMark(current = 1) { this.page = current; const { page, limit } = this; let res = await this.$api.tradeMark.reqTradeMark(page, limit); if (res.code == 200) { this.records = res.data.records; this.total = res.data.total; } }, //分页器当前页展示size改变时回调 sizeChange(limit) { this.limit = limit; this.getTradeMark(); }, },
- vueAdmin\vue-admin-template-master\src\views\product\TradeMark\index.vue
- table
- 主要table中的数据是一列一列进行展示的,每一列具有一个row和$index参数,包含了所要展示的内容
- 在slot插槽中可以利用其进行插入其他需要传递参数的元素如img等
- vueAdmin\vue-admin-template-master\src\views\product\TradeMark\index.vue
<el-table :data="records" border style="width: 100%; margin-top: 20px"> <el-table-column type="index" prop="id" label="id" width="80" align="center" ></el-table-column> <el-table-column prop="tmName" label="tradeMarkName" width="width" align="center" ></el-table-column> <el-table-column prop="logoUrl" label="tradeMarkLogo" width="width" align="center" > <template slot-scope="{ row}"> <img :src="row.logoUrl" alt="" style="width: 100px; height: 100%" /> </template> </el-table-column> <el-table-column prop="prop" label="option" width="width" align="center"> <template slot-scope=""> <el-button type="warning" icon="el-icon-edit">edit</el-button> <el-button type="danger" icon="el-icon-delete">delete</el-button> </template> </el-table-column> </el-table>
- vueAdmin\vue-admin-template-master\src\views\product\TradeMark\index.vue
- pagination
- 主要关注两个event
- @size-change pageSize 改变时会触发 每页条数(回调参数)
- @current-change currentPage 改变时会触发 当前页(回调参数)
- vueAdmin\vue-admin-template-master\src\views\product\TradeMark\index.vue
<el-pagination style="margin-top: 20px; text-align: center" :current-page="page" :page-size="limit" :page-sizes="[4, 6, 8, 10]" layout="prev, pager, next, jumper, ->, sizes, total" :total="total" @current-change="getTradeMark" @size-change="sizeChange" > </el-pagination>
- vueAdmin\vue-admin-template-master\src\views\product\TradeMark\index.vue
- addTradeMark
- el-dialog 实现弹出对话框
- el-from 中采用 :model 收集数据 对应的输入框中的数据可以通过v-model绑定
- 对于 el-upload 上传图片组件中的数据是不可以通过v-model绑定的
- 需要采用:on-success :before-upload 事件实现
- 点击确定时再发请求,根据auForm中的id参数判断是add还是update
- vueProject\vueAdmin\vue-admin-template-master\src\views\product\TradeMark\index.vue
<el-dialog title="update tradeMark" :visible.sync="dialogFormVisible"> <el-form :model="addForm"> <el-form-item label="Name" :label-width="formLabelWidth"> <el-input v-model="addForm.tmName" autocomplete="off"></el-input> </el-form-item> <el-form-item label="Logo" :label-width="formLabelWidth"> <el-upload class="avatar-uploader" action="dev-api/admin/product/fileUpload" :show-file-list="false" :on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload" > <img v-if="addForm.logoUrl" :src="addForm.logoUrl" class="avatar" /> <i v-else class="el-icon-plus avatar-uploader-icon"></i> </el-upload> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button @click="dialogFormVisible = false">取 消</el-button> <el-button type="primary" @click="addTradeMark" >确 定</el-button > </div> </el-dialog> //JavaScript methods async addTradeMark(){ this.dialogFormVisible = false; let res = await this.$api.tradeMark.reqAddOrUpdateTradeMark(this.addForm); if(res.code == 200){ console.log("success"); this.getTradeMark(); }else{ console.log("error"); } }, handleAvatarSuccess(res, file) { this.addForm.logoUrl = URL.createObjectURL(file.raw); }, beforeAvatarUpload(file) { const isJPG = file.type === "image/jpeg"; const isLt2M = file.size / 1024 / 1024 < 2; if (!isJPG) { this.$message.error("上传头像图片只能是 JPG 格式!"); } if (!isLt2M) { this.$message.error("上传头像图片大小不能超过 2MB!"); } return isJPG && isLt2M; },
- vueProject\vueAdmin\vue-admin-template-master\src\views\product\TradeMark\index.vue
- updateTradeMark
- 和add采用同一对话框
- 点击时传递row参数,传递当前点击的数据信息,并更新this.auForm添加id参数即可
- 注意更新时,采用浅拷贝,避免页面数据被直接修改 this.auform = { …row };
- delete基本大差不差,点击发请求即可
- 对于提示信息
- elementUI中的this.$message可通过对象形式配置类型和内容
this.$message({ message: "delete failed", type: "error", });
- 自定义校验
- 在el-form添加:rules="rules"属性以及ref,需要校验的数据在el-form-item中通过prop绑定
- 校验规则写在data中的rules对象中,提交前进行校验
rules: { tmName: [ { required: true, message: "Please enter the tradeMark name", trigger: "blur", }, { min: 2, max: 8, message: "长度在 2 到 8 个字符", trigger: "change", }, ], logoUrl: [ { required: true, message: "Please select tradeMark image", trigger: "blur", }, ], }, this.$refs[auform].validate((valid) => { if (valid) { .... } else { return false; }
- product_Attr
- 静态结构
<el-card> <categorySelect> 自定义组件 </el-card> <el-card> <el-table v-show> <el-form v-show> </el-card>
- api
- vueProject\vueAdmin\vue-admin-template-master\src\api\product\attr.js
import request from '@/utils/request' // getCategory // /admin/product/getCategory1 get // /admin/product/getCategory2/{category1Id} // /admin/product/getCategory3/{category2Id} export function reqGetCategory1() { return request({ url: `/admin/product/getCategory1`, method: 'get', }) } export function reqGetCategory2(id) { return request({ url: `/admin/product/getCategory2/${id}`, method: 'get', }) } export function reqGetCategory3(id) { return request({ url: `/admin/product/getCategory3/${id}`, method: 'get', }) } // reqGetAttrInfoList // /admin/product/attrInfoList/{category1Id}/{category2Id}/{category3Id} export function reqGetAttrInfoList(category1Id,category2Id,category3Id) { return request({ url: `/admin/product/attrInfoList/${category1Id}/${category2Id}/${category3Id}`, method: 'get', }) } // saveCategory3 // /admin/product/saveCategory3 export function reqSaveCategory3(data) { return request({ url: `/admin/product/saveAttrInfo`, method: 'post', data }) } // delete // /admin/product/deleteAttr/{attrId} export function reqDeleteAttr(attrId) { return request({ url: `/admin/product/deleteAttr/${attrId}`, method: 'delete', }) }
- 具体功能实现
- 数据通过请求进行获取,在el组件上进行使用,具体看element官方文档
- table与addOrUpdate通过v-show进行切换
- table中的数据根据category自定义事件传递回来的categoryId1, categoryId2, categoryId3作为参数通过getAttrInfoList()获取
- addOrUpdate模块中进行数据的修改或添加
- 数据修改完毕后save按钮进行保存发请求reqSaveCategory3(),并再次getCategory()
- addOrUpdate模块中input框以及el-tag的切换
- 点击add/edit时将数据进行修改,添加flag属性(edit中需要通过$set添加,否则vue无法检测到新添加的数据)
- 再通过v-if实现切换
addAttr() { this.attrInfo.attrValueList.push({ attrId: 0, valueName: "", flag: true, }); }, edit(row) { this.show = !this.show; this.attrInfo = cloneDeep(row); //lodash_深度拷贝 this.attrInfo.attrValueList.forEach((item) => { this.$set(item, "flag", false); }); this.editModel = true; // this.deleteAttr(row); },
- 静态结构
- 后面感觉都没什么难度,结合视频中演示部分搞定静态elmentUI,然后组件中的数据通过请求获取并绑定即可,请求建议在swagerUI中测试,查看一下数据,再判断是属于那一部分的功能
- product_spu_阉割版
- request
import request from '@/utils/request'; // 获取表格数据,分页器功能 // /admin/product/{page}/{limit} get export function reqGetSpuInfo(page,limit,category3Id) { return request({ url: `/admin/product/${page}/${limit}`, method: 'get', params: {category3Id} }) } // spuForm_getTradeMarkList spuFrom部分商品列表 // /admin/product/baseTrademark/getTrademarkList export function reqGetTradeMarkList(){ return request({ url: `/admin/product/baseTrademark/getTrademarkList`, method: 'get' }) } // spuForm_getSpu spu名称描述 // /admin/product/getSpuById/{spuId} export function reqGetSpu(spuId){ return request({ url: `/admin/product/getSpuById/${spuId}`, method: 'get' }) } // spuForm_getImgList spu图片 // /admin/product/spuImageList/{spuId} export function reqGetImgList(spuId){ return request({ url: /admin/product/spuImageList/${spuId}, method: 'get' }) } // spuForm_selectAttrList 销售属性 // /admin/product/baseSaleAttrList export function reqGetbaseSaleAttrList(){ return request({ url: /admin/product/baseSaleAttrList, method: 'get' }) } // spuForm_saveInfo 提交 // /admin/product/saveSpuInfo post export function reqSaveSpuInfo(data){ return request({ url: /admin/product/saveSpuInfo, method: 'post', data }) } // spuForm_updateInfo 修改 // /admin/product/updateSpuInfo post export function reqUpdateSpuInfo(data){ return request({ url: /admin/product/updateSpuInfo, method: 'post', data }) } // spu_deleteSpu 删除 // /admin/product/deleteSpu/{spuId} delete export function reqDeleteSpu(spuId){ return request({ url: /admin/product/deleteSpu/${spuId}, method: 'delete', }) } // spu_findBySpuId 商品详细信息 // /admin/product/findBySpuId/{spuId} get export function reqFindBySpuId(spuId){ return request({ url: /admin/product/findBySpuId/${spuId}, method: 'get', }) }
- request
- product_sku_阉割版
- request
import request from '@/utils/request'; // sku_getSkuList 表格数据 // /admin/product/list/{page}/{limit} get export function reqGetSkuList(page,limit){ return request({ url: `/admin/product/list/${page}/${limit}`, method: 'get' }); } // sku_cancelSale 下架sku // /admin/product/cancelSale/{skuId} get export function reqCancelSale(skuId){ return request({ url: `/admin/product/cancelSale/${skuId}`, method: 'get' }); } // sku_OnSale 上架sku // /admin/product/onSale/{skuId} get export function reqOnSale(skuId){ return request({ url: `/admin/product/onSale/${skuId}`, method: 'get' }); } // sku_DeleteSku 删除sku // /admin/product/deleteSku/{skuId} delete export function reqDeleteSku(skuId){ return request({ url: `/admin/product/deleteSku/${skuId}`, method: 'delete' }); }
- request
后面大部分也都,差不多,时间原因,阉割了一些功能。主要是熟悉elementUI,和一些逻辑上的实现。笔记的话也没写完,感觉没啥可写的,主要就是api以及elementUI组件的一些属性以及事件,可以在官方文档上进行查看
更多推荐
已为社区贡献1条内容
所有评论(0)