# 安装依赖 npm install
# 建议不要直接使用 cnpm 安装以来,会有各种诡异的 bug。可以通过如下操作解决 npm 下载速度慢的问题,或者使用yarn安装也行 npm install --registry=https://registry.npm.taobao.org
# 启动服务 npm run dev ```
# 构建生产环境 npm run build ```
## 其它
# 代码格式检查 npm run lint
# 代码格式检查并自动修复 npm run lint -- --fix |
utils/request.js对axios进行了二次封装,导出了变量request,request封装了几种常用的请求方式(get,post,postForm,put,delete,getFile)
请求方式 |
请求说明 |
get |
get请求 |
post |
post请求(json格式) |
postForm |
post请求(formData格式) |
put |
put请求(json格式) |
delete |
delete请求 |
getFile |
对get请求二次封装导出文件功能,所有的导出文件功能用这个方式即可 |
另外暴露了整个axios的实例,用于自定义请求(该请求方式可自定义操作,用于后端的各种操作)
用法:
//暴露的request变量,自定义封装的请求方式 import { request } from '@/utils/request' request.get(url, data) request.post(url, data) request.postForm(url, data) request.put(url, data) request.delete(url, data) request.getFile(url, data)
//使用axios的实例请求,自定义使用 import request from '@/utils/request' request({ url, method: 'get', params, data:, headers }) |
为了统一管理好接口,根据模块定义一个api.js文件。一个系统有多个模块,每个模块对应多个页面。故一个模块有一个js文件,一个页面中定义一个对象变量存储页面的接口地址。
例如:
// ModuleDistr.js //分销模块,故定义一个js //例如:分销设置页面里面的所有api(建议每个页面的变量名后缀都是Api和每个接口都需要写注释) const distrSetApi = { // 保存菜单 addSettings: (data) => request.post('/activity/admin/distribution/rules/basic/settings', data), //获取分销规则设置 distributionRules: (data) => request.get('/activity/admin/distribution/rules', data),
//保存分销结算设置 addbillingSettings: (data) => request.post('/activity/admin/distribution/rules/billing/settings', data),
//切换分销规则开关 updateRulesSwitch: (data) => request.post('/activity/admin/distribution/rules/update/rules/switch', data), } //暴露页面变量 export { distrSetApi, //分销设置 } |
路由分为本地路由和动态路由(在@/config/config.js中asyncRoutes属性控制)
const config = { server: 'http://192.168.0.66:9999', // 少龙 (后端接口地址) photoServer: 'http://192.168.0.13:9000/dev6.0/', // 图片服务器地址 shareUrl: 'http://mdiamonds.legendshop.cn/',//h5域名 staticServer: 'https://legendshop-front-resource.oss-cn-shenzhen.aliyuncs.com/miniprogram/',//静态服务器地址 imServer: 'ws://192.168.0.19:2397',//im地址,客服地址(暂时没有用) AmapKey: 'b67650d214590281b2ab8e413473553d',//高德地图秘钥 asyncRoutes: false //true:本地路由,false:后端动态路由 } |
const ModuleGoods = [ //所有的name、path都和文件夹的名称一样(注意一级路由的path前面需要加一个/) { path: '/ModuleGoods', component: Layout, //所有需要侧边栏页面的一级路由的component都是layout name: 'ModuleGoods', meta: { title: '商品管理', //页面标题 icon: 'shangpin' //侧边栏icon }, children: [ // 商品管理start { path: 'GoodsManage', component: () => import('@/views/ModuleGoods/GoodsManage/index'), // 在vue文件中都需要定义name属性(和文件名称一致) name: 'GoodsManage', meta: { title: '商品管理' }, children: [ { path: 'addGood', component: () => import('@/views/ModuleGoods/GoodsManage/addGood'), name: 'addGood', meta: { title: '商品添加' , noCache: true}, hidden: true //(默认 false),当设置 true 的时候该路由不会在侧边栏出现 如401,login等页面,或者如一些编辑页面/edit/1 } ] } ] } ] |
动态路由在平台管理系统(系统设置→菜单权限→平台菜单)平台菜单这个页面设置。
菜单字段 |
菜单说明 |
类型 |
分为菜单类型和按钮类型。菜单类型定义的是菜单路径;按钮类型主要定义按钮权限 |
菜单名称 |
页面标题:设置该路由在侧边栏和面包屑中展示的名字 |
链接地址 |
对应的是path和name字段(因为name和path是一样的) |
组件地址 |
页面对应的文件路径。注意(一级路由固定是layout,拥有三级路由以上的父级路由的固定是ParentView。意思是最后一级是文件路径,除了一级和最后一级以外,都是ParentView) 例如下图:
|
权限编码 |
页面的权限编码 |
显示侧边栏 |
菜单类型的选项,菜单是否显示在侧边栏。 |
页面类型 |
编写说明 |
表格页面 |
已经写好了公共样式直接拷贝现有就行了 |
表单提交页面 |
表单提交页外层需要定义一个class=‘sumbit__warp’属性,用户该页面撑满当前页面。有提交按钮需要引入<sumbitBottom>组件,作用把提交按钮一直置于底部,当表单过长时,就不需要滑动到底部了。 |
在mixins/pages/commom.js(处理表格搜索)和cud.js(处理弹窗表单操作)中混入了表格请求的方法
第一 导入混入结构
import common from '@/mixins/pages/commom' //表格混入 import cud from '@/mixins/pages/cud.js' //表单混入 data() { return { date: '', url: { getData: '/shop/admin/grass/lable/page', //获取分页列表请求路径 delete: '/shop/admin/grass/lable',//删除数据接口 update: '/shop/admin/grass/lable',//编辑数据接口 create: '/shop/admin/grass/lable',//新增数据接口 getExcel: "/product/admin/count/search/page/excel" //导出数据接口 }, //弹窗表单校验 dialogForm: { formData: { //弹窗表单需要默认值需要定义,不需要默认值的可以不写 recommendFlag: 1, status: 1 }, formRule: {//弹窗表单校验定义, name: [{ required: true, message: '请输入标题', trigger: 'blur' }], } } } } |
第二,搜索字段定义
<div class="search"> <el-form :inline="true" :model="searchFilters" size="small"> <el-form-item label="举报类型"> <!-- 例如后台需要的搜索参数是name,只需要 v-model="searchFilters.name"就行了 --> <el-input v-model="searchFilters.name" placeholder="请输入" /> </el-form-item> <el-form-item label="状态"> <el-select v-model="searchFilters.status" placeholder="请选择" clearable> <el-option label="上线" :value="1" /> <el-option label="下线" :value="0" /> </el-select> </el-form-item> <el-form-item class="mb-20"> <el-button size="small" @click.stop="dbnSearch">搜索</el-button> <el-button size="small" @click.stop="dbnResetSearch">重置</el-button> </el-form-item> </el-form> </div> |
第三,表格渲染
<!--表格--> <div class="table mt-20"> <!-- 多选要添加 @selection-change="handleSelectionChange" 方法--> <!-- selectable 属性封装了禁止选择 --> <!-- 禁止表格多选选择框,配合data里的fillerOption属性使用 --> <!--例如 fillerOption: { //禁止状态 fillerOption:{status:'1,-1,-2'}} -->
<el-table ref="multipleTable" v-loading="tableListLoading" :data="tableList" :selectable="selectable" tooltip-effect="dark" class="w-100" @selection-change="handleSelectionChange" >
<!-- 如果有多选功能需要加上属性reserve-selection,能记录分页后选中的数据 --> <el-table-column type="selection" width="55" reserve-selection /> <el-table-column prop="name" label="举报类型" align="center" /> </el-table> <el-row type="flex" justify="space-between" class="mt-20"> <el-col> <el-button size="mini" class="allCheck"> <!-- 全选功能封装--> <el-checkbox v-model="checkAll" label="全选" size="small" @change="selAll()" /> </el-button> </el-col> <!-- //分页组件封装(直接使用) --> <pagination :current-page="page.curPage" :total="tableTotal" @size-change="pageSizeChange" @current-change="currentPageChange" /> </el-row> </div> |
第四、表单新增编辑
<!-- 表单新增-编辑 --> <el-dialog :title="dialogForm.title" custom-class="dialog-form" width="420px" :visible.sync="dialogForm.isVisible"> <el-form ref="myForm" :model="dialogForm.formData" :rules="dialogForm.formRule" label-width="95px" label-position="right" size="small"> <!-- 只需要把后端需要的参数放进dialogForm.formData属性里就能动态修改了 注意:prop属性不能丢,为了能保存默认值和关闭弹窗的时候清空数据,因为用的是element的form组件清除的表单 --> <el-form-item label="举报类型" prop="name"> <el-input v-model="dialogForm.formData.name" maxlength="20" show-word-limit placeholder="举报类型" /> </el-form-item> <el-form-item label="状态" prop="status"> <el-radio-group v-model="dialogForm.formData.status"> <el-radio :label="1">上线</el-radio> <el-radio :label="0">下线</el-radio> </el-radio-group> </el-form-item> </el-form> <!-- //以下两个按钮都是固定的值,直接拷贝即可 --> <div slot="footer" class="dialog-footer"> <el-button size="small" @click.stop="dialogForm.isVisible = false">取 消</el-button> <el-button size="small" type="primary" @click.stop="debounceSubmit('myForm')">确 定</el-button> </div> </el-dialog>
<!-- 新增编辑删除导出都是固定方法,直接拷贝就行 新增 handleCreate() 编辑 handleEdit(scope.row, scope.column, scope.$index) 删除 handleDel(scope.row, scope.column, scope.$index) 导出 getExcel() --> <el-button style="height: 32px" type="primary" size="small" @click="handleCreate">新增</el-button> <el-button style="height: 32px" type="primary" size="small" @click="getExcel">导出</el-button> <el-link :underline="false" type="primary" @click.stop="handleEdit(scope.row, scope.column, scope.$index)"> 编辑 </el-link> <el-link :underline="false" type="primary" @click.stop="handleDel(scope.row, scope.column, scope.$index)"> 删除 </el-link> |
组件名称 |
组件作用 |
dialogAudit |
平台所有的审核都使用这个组件,可以搜索组件名称参考使用 |
dialogViewLinks |
平台商家端的查看链接,暂时统一用这个组件。后面需要写死一个页面中转跳转路径。所有的跳转都需要经过此页面。再由这个页面跳转到相应的页面 |
selectCascader |
多级联动地址选择器 |
selectLoad |
下拉选择框支持上拉加载和远程搜索 |
sumbitBottom |
底部按钮组件,作用是始终显示在底部 |
***原型和需求文档一定要看,但是画页面不一定要和原型一模一样,高保真才是页面的最终实现。建议着手前先和前端或产品沟通,避免重复劳动***
1、正常情况下对于输入信息的地方(输入框、选择框等)都需要做边界处理(比如限制字数),原型一般标有,没有则原型--->需求文档-→产品同事
2、页面编写记得加上头部注释(至少说明页面名称和作者)
3、列表页面搜索头部(输入框、选择框、日期等)一般加清除按钮clearable,特殊需求除外
4、组件尺寸一般使用small,建议直接改el-form 中 size="small"属性,特殊需求除外
5、详情中的返回、取消按钮建议用go(-1)或back()返回,因为有时跳转进的入口有可能多个
6、普通金额使用全局过滤(priceFilter,保留两位,向下取整)即可,如果有特殊需求,则需要考虑是否需要四舍五入
7、表格和表单数据展示一般不要留空
8、表格验证可以参考这个页面seckillGoodsTable.vue
9、对于嵌套表单,A表单嵌套B表单,点击A表单要验证B表单的内容,可以这么写