vue后台(一)

一,项目准备工作

1.拿到已经是二次开发的代码, npm i , 安装依赖包

 

ES6模块暴露和导入复习
    1. 导出方式一: 默认一次性导出 (只能有一个)
            export default xxx
            本质: 整个模块是一个对象, 对象中有default属性, 即: {default: xxx}
    2. 导出方式二: 非默认分别导出 (可以有多个)
            export yyy
            export zzz
            本质: 整个模块是一个对象, 对象中有yyy和zzz属性, 即: {yyy, zzz}
    3. 导出方式三: 非默认统一导出 (可以有多个)
            export {yyy, zzz}
            本质:  整个模块是一个对象, 对象中有yyy和zzz属性, 即: {yyy, zzz}  
        
    4. 导入方式一: 导入默认导出的模块
            简洁写法: import xxx from './test' // 可以是任意名称
            完整写法: import {default as xxx} from './test'
    5. 导入方式二: 导入分别导出的模块
            import {yyy, zzz} from './test'  // 必须是指定的名称
    6. 导入方式三: 导入整个/所有模块(包括默认与非默认导出的)
            import * as obj from './test' // 可以是任意名称
        obj的结构: {default, yyy, zzz}

    7. 导入并导出: 对导入的模块同时做导出的操作
           export {default as xxx} from './test'
        export {yyy, zzz} from './test'

 

2.在api中新建trademark文件夹(index.js),封装品牌分页管理的接口函数,post请求是新增数据,请求体不需要带id的,put请求是改数据,请求体需要加id

封装商品增,删,改,查四个接口

import request from '@/utils/request'

//截取公共路径
const api_name = '/admin/product'

export default {
  /*
  获取品牌分页列表(带搜索)
  GET /admin/product/baseTrademark/{page}/{limit}

  */
  getPageList(page, limit) {
    //对象写法
    return request({
      url: `${api_name}/baseTrademark/${page}/${limit}`,
      method: 'get',
    })
  },

  /*
  增加或者修改品牌
  POST /admin/product/baseTrademark/save
  PUT /admin/product/baseTrademark/update

trademark是个对象,请求体
  {
  "id": 0,
  "logoUrl": "string",
  "tmName": "string"
}
  */ 
  addOrUpdate(trademark){
    if(trademark.id){
      //修改put请求需要有id
      return request({
        url:`${api_name}/baseTrademark/update`,
        method:'put',
        //请求体
        data:trademark
      })
    }else{
      //增加数据不需要id,post请求
      return request({
        url:`${api_name}/baseTrademark/save`,
        method:'post',
        data:trademark
      })
    }
  },
  /*
  删除 DELETE /admin/product/baseTrademark/remove/{id}
  */
  delete(id){
    return request({
      url:`${api_name}/baseTrademark/remove/${id}`,
      method:'delete'
    })
  }
  
}

 

3.然后在api(index.js)中,引入该封装接口函数的对象,然后在暴露出去

export {default as login} from './acl/login'
export {default as user} from './acl/user'
export {default as role} from './acl/role'
export {default as permission} from './acl/permission'
export {default as category} from './category'
export {default as clientUser} from './clientUser'
export {default as order} from './order'
export {default as trademark} from './trademark' //先把trademark的默认暴露引入进来

4.在入口文件main.js引入这些接口模块

// 引入包含所有接口请求函数模块的API对象
import * as API from '@/api'
Vue.prototype.$API = API
// this.$API.trademark.getPageList

 

5.在tradmark组件中发送请求,获取页面数据

响应数据

{
  "code": 200,
  "message": "成功",
  "data": {
    "records": [
      {
        "id": 245,
        "tmName": "摩托罗拉",
        "logoUrl": "http://182.92.128.115:8080/group1/M00/00/49/rBFUDF9I276APAugAAAV9aU5b64934.png"
      },
      {
        "id": 246,
        "tmName": "诺基亚",
        "logoUrl": "http://182.92.128.115:8080/group1/M00/00/2D/rBFUDF8hkeCAVX2oAAEGp0OpqNA105.png"
      },
      {
        "id": 247,
        "tmName": "苹果(Apple)",
        "logoUrl": "http://182.92.128.115:8080/group1/M00/00/34/rBFUDF8sAE2AACP7AAAPN5YrVxw528.jpg"
      }
    ],
    "total": 32,
    "size": 3,
    "current": 1,
    "pages": 11
  },
  "ok": true
}

 

 data(){
    return {
      page:1,
      limit:5,
      total:100,
      trademarkList:[]
    }
  },

  mounted(){
    this.getreqPageList()
  },

  methods:{
    async  getreqPageList(){
      let result = await  this.$API.trademark.getPageList(this.page, this.limit)
      if(result.code ===200){
        this.trademarkList= result.data.records
        this.total= result.data.total
      }
    }
  }
};

 

6.利用element-ui框架搭建静态页面

注;

<!-- border 表格边框,     stripe隔行变色,-->
<el-table :data="trademarkList" border stripe style="width: 100%;margin:20px 0">


<!-- label是每列顶部的文字说明 align="center" 每行文字居中-->
<el-table-column align="center" label="序号" type="index" width="80"></el-table-column>

 table的每一列都是暗含了遍历我们的trademarkList 
        默认情况下,你只需要给这个列指定要显示的,对象的对应属性,然后就会展示对应这个属性的属性值,比如每列用prop="tmName",就是trademarkList 数组遍历每个对象的tmName属性
 
<el-table-column 中的prop属性为:data="trademarkList"数组的每一个对象的属性
        但是如果你要修改这个数据的结构,那么必须使用作用域插槽的用法
 

       row为trademarkList的每一个对象,暗含遍历

slot-scope="{row,$index}是固定写法,row为trademarkList的每一个对象,暗含遍历,$index为索引

<template slot-scope="{row,$index}">
<img :src="row.logoUrl" style="height:80px;" />
</template>

 
<template>
  <div>
    <el-button type="primary"  icon="el-icon-plus">添加</el-button>
    
    <el-table  :data="trademarkList" border stripe  style="width:100%; margin:20px 0">
      <el-table-column 

        label="序号"
        align="center"
        type="index"
        width="80">
      </el-table-column>
       <el-table-column 
        align="center"
        label="品牌名称"
        prop="tmName"
        width="width">
      </el-table-column>
       <el-table-column 
      
        label="品牌Logo"
        
        width="width">
        <template slot-scope="{row, $index}">
          <img :src="row.logoUrl"  style="height:80px;">
        </template>

      </el-table-column>
       <el-table-column 
      
       label="操作"
        
        width="width">
        <template  slot-scope="{row, $index}">
            <el-button type="warning" size="mini"   icon="el-icon-edit"></el-button>
            <el-button type="danger" size="mini"  icon="el-icon-delete" ></el-button>
            
        </template>

      </el-table-column>
    </el-table>
    <el-pagination
     style="text-align:center"
      :current-page="page"
      :page-sizes="[3, 5, 7, 9]"
      :page-size="limit"
      layout=" prev, pager, next, jumper ,->, sizes,total "
       @current-change="getreqPageList"
       @size-change="handleSizeChange"
      :total="total">
    </el-pagination>
    
  </div>
</template>

 

@current-change="getreqPageList" ,点击当前页的事件,重新发送请求,获取数据
 @size-change="handleSizeChange" , 点击每页的多少条事件,重新发送请求,获取数据
 
js代码
 methods:{
    //发送请求,获取数据,点击当前页,发送请求
    async  getreqPageList(page=1){
      this.page = page
      let result = await  this.$API.trademark.getPageList(this.page, this.limit)
      if(result.code ===200){
        this.trademarkList= result.data.records
        this.total= result.data.total
      }
    },

    //每页多少条
    handleSizeChange(limit){
      this.limit =limit
      this.getreqPageList()
    }
  }

 

7, 点击添加按钮,弹出dialog框

title="添加"  为弹框顶部的文字
:visible.sync="isShowDialog"  为控制dialog的框开关,在data中默认设置关闭,isShowDialog:false,
 style="width:80%"  为控制form表单的宽度
:label-width="formLabelWidth"  为input的宽度, 在data中设置 formLabelWidth:'100px',
 
:model="form"   为form表单的一个对象,为每一个el-form-item配置属性, 在data中配置
 
 form:{
        tmName:'',
      }
 
 
 
模板页面
:model="form"是个对象,在data中定义了, 而<el-form-item 中的v-model可以获取form的一个属性
  <el-dialog title="添加" :visible.sync="isShowDialog">
      <el-form :model="form"  style="width:80%">
        <el-form-item label="品牌名称" :label-width="formLabelWidth">
          <el-input v-model="form.tmName" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="品牌LOGO" :label-width="formLabelWidth">
          <!-- el-upload -->
          
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="isShowDialog = false">取 消</el-button>
        <el-button type="primary" @click="isShowDialog = false"
          >确 定</el-button
        >
      </div>
    </el-dialog>
 <el-button type="primary" icon="el-icon-plus"  @click="showAddDialog">添加</el-button>
 //点击添加按钮,开启dialog弹框
    showAddDialog(){
      this.isShowDialog=true
    }

图片

 

 8,

Upload 上传

在官网中,获取他的模板,js代码, css样式

 v-if="form.logoUrl" :src="form.logoUr"   在data中定义该数据
  <!-- el-upload -->
          <el-upload
            class="avatar-uploader"
            action="https://jsonplaceholder.typicode.com/posts/"
            :show-file-list="false"
            :on-success="handleLogoSuccess"
            :before-upload="beforeLogoUpload"
          >
            <img v-if="form.logoUrl" :src="form.logoUr" class="avatar" />
            <i v-else class="el-icon-plus avatar-uploader-icon"></i>
          </el-upload>

js代码

  //上传成功调用
     handleLogoSuccess(res, file) {
        this.imageUrl = URL.createObjectURL(file.raw);
      },

      //上传之前调用,一般都是在上传之前去对要上传的文件做限制用的
      beforeLogoUpload(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;
      }

 

 

 

 

 

 上传图片

1.actions为上传图片的管理接口,本地浏览器服务器,需要到http://182.92.128.115服务器,此时需要跨域,配置代理

 
<el-upload
            class="avatar-uploader"
            
            action="/dev-api/admin/product/fileUpload"
            :show-file-list="false"
            :on-success="handleLogoSuccess"
            :before-upload="beforeLogoUpload"
          >
  proxy: {  //localhost:9528
      // localhost:9528/admin/product/fileUpload    404
      // localhost:9528/dev-api/admin/product/fileUpload
      // http://182.92.128.115/admin/product/fileUpload
      '/dev-api': { // 匹配所有以 '/dev-api'开头的请求路径
        target: 'http://182.92.128.115', // 代理目标的基础路径
        // target: 'http://47.93.148.192',
        changeOrigin: true, // 支持跨域
        pathRewrite: { // 重写路径: 去掉路径中开头的'/dev-api'
          '^/dev-api': ''
        }
      },
    }

 

 上传的两个回调函数,做下处理

//上传图片需要用的回调
    //上传成功调用
    handleLogoSuccess(res, file) {
      // this.form.logoUrl = URL.createObjectURL(file.raw);//其实本质还是拿的是本地的文件路径,我们不要这个
      this.form.logoUrl = res.data; //这个存储的就是上传成功服务器返回的真实线上路径
      console.log(this.form.logoUrl);
    },

    //上传之前调用,一般都是在上传之前去对要上传的文件做限制用的
    beforeLogoUpload(file) {
      const TypeArr = ["image/jpeg", "image/png"];
      const isJPGOrPNG = TypeArr.indexOf(file.type) !== -1;
      const isLt500K = file.size / 1024 < 500;

      if (!isJPGOrPNG) {
        this.$message.error("上传头像图片只能是 JPG或PNG 格式!");
      }
      if (!isLt500K) {
        this.$message.error("上传头像图片大小不能超过 500K");
      }
      return isJPGOrPNG && isLt500K; //返回布尔值,如果为真则上传,如果为假则报错
    },

 

9,添加品牌的逻辑

点击弹框的确定按钮,添加品牌

    <div slot="footer" class="dialog-footer">
        <el-button @click="isShowDialog = false">取 消</el-button>
        <el-button type="primary" @click="addOrupdateTrademark">确 定</el-button>
      </div>
    </el-dialog>

js代码

 async addOrupdateTrademark() {
      //添加和修改二合一
      //找参数
      let trademark = this.form;
      //发请求,添加品牌
      const result = await this.$API.trademark.addOrUpdate(trademark);
      //成功干啥
      if (result.code === 200) {
        this.$message.success(`${trademark.id ? "修改" : "添加"}品牌成功`);
        this.getTrademarkList(trademark.id ? this.page : 1); //重新加载数据 默认添加的新的品牌在最后
        // 关闭Upload弹框
        this.isShowDialog = false;
      } else {
        //失败干啥
        this.$message.error(`${trademark.id ? "修改" : "添加"}品牌失败`);
      }
    },

 

10, 每次点击添加按钮,弹出框,会出现之前的信息,必须每次在每次点击添加时,清空form数据

 //点击添加按钮,开启dialog弹框
    showAddDialog() {
      //每次点开dialog就去把form清空,保证每次弹出来都是新的form,否则就会显示上次上传的图片信息
      // 此时form没有id
      this.form = {
        tmName: "",
        logoUrl: "",
      };
      this.isShowDialog = true;
    },

 

11,点击修改按钮,设置form对象,打开弹框,需要传递row,是哪个品牌

 

 

<el-table-column label="操作" width="width">
        <template slot-scope="{row,$index}">
          <el-button
            type="warning"
            icon="el-icon-edit"
            size="mini"
            @click="showUpdateDialog(row)"
          >修改</el-button>

js代码

  //点击修改按钮
    showUpdateDialog(trademark) {
      // this.form = trademark //添加的时候弹出dialog需要form全局清空,保证是新的,但是修改的时候修改的是哪一条,form就是谁
      // 此时form有id
      this.form = { ...trademark }; //浅拷贝
      this.isShowDialog = true;
    },

 

12,删除品牌逻辑

 <el-button
            type="danger"
            size="mini"
            icon="el-icon-delete"
            @click="deleteTrademark(row)"
          >删除</el-button>

js代码,

confirm组件在element官网,可以去查看具体配置

 

 

  //点击删除按钮
     deleteTrademark(trademark) {
      this.$confirm(`你想删除${trademark.tmName}吗?`, "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(async () => {
          //点击了确定按钮
          //发送删除请求
          const result = await this.$API.trademark.delete(trademark.id);
          if (result.code === 200) {
            this.$message.success(`删除${trademark.tmName}品牌成功`);
            //重新发送请求,更新数据
            this.getreqPageList(
              this.trademarkList.length > 1 ? this.page : this.page - 1
            );
          } else {
            this.$message.error("删除品牌失败");
          }
        })
        .catch(() => {
          //点击了取消按钮
          this.$message({
            type: "info",
            message: "已取消删除",
          });
        });
    },

 

 

 

 

 

 

 

posted @ 2020-08-28 10:25  全情海洋  阅读(441)  评论(0编辑  收藏  举报