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>
<el-table-column 中的prop属性为:data="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>
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框
<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样式
<!-- 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代码,
//点击删除按钮
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: "已取消删除",
});
});
},