尚硅谷尚品汇_后台管理项目

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\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': '' }
          }
        }
        },
        
    • 修改axios中的config.header
      • vueAdmin\vue-admin-template-master\src\utils\request.js
        config.headers['token'] = getToken()
        

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;
        }
        
    • 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;
          
      • 通过发请求获取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();
            },
          },
          
      • 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>
          
      • 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>
          
      • 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;
          },
          
      • 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',
          })
        }
        

  • 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'
        });
      }
      

后面大部分也都,差不多,时间原因,阉割了一些功能。主要是熟悉elementUI,和一些逻辑上的实现。笔记的话也没写完,感觉没啥可写的,主要就是api以及elementUI组件的一些属性以及事件,可以在官方文档上进行查看

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值