文件夹介绍
build----index.js: 是webpack配置文件 mock:mock数据的文件夹【模拟一些假的数据】,实际开发利用的是真实的接口 node_modules:项目依赖的模块 public:ico图标,静态页面,该文件夹里面经常放置一些静态资源,而且在项目打包的时候webpack不会编译这个文件夹,原封不动的打包到dist文件夹里面 src: ---- 程序员源代码的地方 ---- api文件夹:涉及相关请求 ---- assets文件夹:里面放置一些静态资源(一般是共享的),放在该文件夹里的静态资源,在webpack打包的时候,会进行编译 ---- componets文件夹:一般放置非路由组件或是全局组件 ---- icons文件夹放置一些svg矢量图 ---- layout文件夹放置了组件和混入 ---- router文件夹与路由相关 ---- store文件夹与vux相关 ---- style文件夹与样式相关的 ---- utils文件夹:request.js是axios二次封装文件 ---- views 文件夹:里面放置的路由组件 App.vue:根组件 main.js:入口文件 permission.js:与导航守卫相关 settings.js:项目的配置项文件
登录页面
1、静态组件完成,使用element-UI 2、将假的接口换成真实的接口并且解决代理跨域问题,在vue.config.js文件里的devServer中配置如下
proxy: {
'/dev-api': {
target: 'http://gmall-h5-api.atguigu.cn',
pathRewrite: { '^/dev-api': '' }
}
}
然后重启服务器 3、action
async login({ commit }, userInfo) {
const { username, password } = userInfo
let result = await login({ username: username.trim(), password: password });
if (result.code == 20000) {
commit('SET_TOKEN', result.data.token)
setToken(result.data.token)
return 'ok'
} else {
return Promise.reject(new Error('faile'))
}
},
4、绑定事件
handleLogin() {
this.$refs.loginForm.validate(valid => {
if (valid) {
this.loading = true;
this.$store.dispatch('user/login', this.loginForm).then(() => {
this.$router.push({ path: this.redirect || '/' });
this.loading = false
}).catch(() => {
this.loading = false
})
} else {
console.log('error submit!!')
return false
}
})
}
路由的搭建
删掉不需要的路由组件,删除之后无法运行,因为这些路由已经被配置,所以需要删掉。 新建自己需要的路由,然后搭建路由,使用路由懒加载引入组件。
品牌管理
动态展示
1、静态组件,按钮和表格组件以及分页器
<el-table style="width: 100%" border :data="list">
<el-table-column label="序号" width="80px" align="center">
</el-table-column>
<el-table-column label="品牌名称" width="width">
</el-table-column>
<!--
分页器
当前第几页、数据总条数、每一页展示条数、连续页码数
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
current-page:代表的是当前第几页
total:代表分页器一共需要展示数据条数
page-size:代表的是每一页需要展示多少条数据
page-sizes:代表可以设置每一页展示多少条数据
layout:可以实现分页器布局
pager-count:按钮的数量 如果 9 连续页码是7
-->
<el-pagination
style="margin-top: 20px; text-align: center"
:current-page="page"
:total="total"
:page-size="limit"
:pager-count="7"
:page-sizes="[3, 5, 10]"
@current-change="getPageList"
@size-change="handleSizeChange"
layout="prev, pager, next, jumper,->,sizes,total"
>
</el-pagination>
2、接口 3、写一个获取品牌列表数据的方法 4、品牌管理列表的获取
async getPageList(pager = 1) {
this.page = pager;
const { page, limit } = this;
let result = await this.$API.trademark.reqTradeMarkList(page, limit);
if (result.code == 200) {
this.total = result.data.total;
this.list = result.data.records;
}
},
5、数据展示
<el-table style="width: 100%" border :data="list">
<el-table-column type="index" label="序号" width="80px" align="center">
</el-table-column>
<el-table-column prop="tmName" label="品牌名称" width="width">
</el-table-column>
<el-table-column prop="logoUrl" label="品牌LOGO" width="width">
<template slot-scope="{ row, $index }">
<img :src="row.logoUrl" alt="" style="width: 100px; height: 100px" />
</template>
</el-table-column>
<el-table-column prop="prop" label="操作" width="width">
<template slot-scope="{ row, $index }">
<el-button
type="warning"
icon="el-icon-edit"
size="mini"
@click="updateTradeMark(row)"
>修改</el-button
>
<el-button
type="danger"
icon="el-icon-delete"
size="mini"
@click="deleteTradeMark(row)"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
6、分页器点击事件
async getPageList(pager = 1) {
this.page = pager;
const { page, limit } = this;
let result = await this.$API.trademark.reqTradeMarkList(page, limit);
if (result.code == 200) {
this.total = result.data.total;
this.list = result.data.records;
}
},
handleSizeChange(limit) {
this.limit = limit;
this.getPageList();
},
添加品牌
1、静态组件
<el-dialog
:title="tmForm.id ? '修改品牌' : '添加品牌'"
:visible.sync="dialogFormVisible"
>
<el-form style="width: 80%" :model="tmForm" :rules="rules" ref="ruleForm">
<el-form-item label="品牌名称" label-width="100px" prop="tmName">
<el-input autocomplete="off" v-model="tmForm.tmName"></el-input>
</el-form-item>
<el-form-item label="品牌LOGO" label-width="100px" prop="logoUrl">
<el-upload
class="avatar-uploader"
action="/dev-api/admin/product/fileUpload"
:show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload"
>
<img v-if="tmForm.logoUrl" :src="tmForm.logoUrl" class="avatar" />
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
<div slot="tip" class="el-upload__tip">
只能上传jpg/png文件,且不超过500kb
</div>
</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="addOrUpdateTradeMark"
>确 定</el-button
>
</div>
</el-dialog>
2、点击事件显示对话框
showDialog() {
this.dialogFormVisible = true;
this.tmForm = { tmName: "", logoUrl: "" };
},
updateTradeMark(row) {
this.dialogFormVisible = true;
this.tmForm = { ...row };
},
3、上传图片相关的回调
handleAvatarSuccess(res, file) {
this.tmForm.logoUrl = res.data;
},
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;
},
4、完成功能 (1)接口 (2)
export const reqAddOrUpdateTradeMark = (tradeMark) => {
if (tradeMark.id) {
return request({ url: '/admin/product/baseTrademark/update', method: 'put', data: tradeMark });
} else {
return request({ url: '/admin/product/baseTrademark/save', method: 'post', data: tradeMark });
}
}
图片收集,action:设置图片上传的地址 (3)功能实现
addOrUpdateTradeMark() {
this.$refs.ruleForm.validate(async (success) => {
if (success) {
this.dialogFormVisible = false;
let result = await this.$API.trademark.reqAddOrUpdateTradeMark(
this.tmForm
);
if (result.code == 200) {
this.$message({
type: "success",
message: this.tmForm.id ? "修改品牌成功" : "添加品牌成功",
});
this.getPageList(this.tmForm.id ? this.page : 1);
}
} else {
console.log("error submit!!");
return false;
}
});
},
updateTradeMark(row) {
this.dialogFormVisible = true;
this.tmForm = { ...row };
},
注意: 由于tmFrom是直接影响列表展示的,而服务器收集数据也是用到的tmFrom,当修改品牌时,如果直接将row赋值给tmFrom,tmFrom会影响到服务器返回的值,即使点击取消,表单列表展示的数据也发生了改变,所以此时需要用到浅拷贝,即将服务器的数据拷贝一份赋值给tmFrom而不会影响到row。
(4)表单验证功能
var validateTmName = (rule, value, callback) => {
if (value.length < 2 || value.length > 10) {
callback(new Error("品牌名称2-10位"));
} else {
callback();
}
};
rules: {
tmName: [
{ required: true, message: "请输入品牌名称", trigger: "blur" },
{ validator: validateTmName, trigger: "change" },
],
logoUrl: [{ required: true, message: "请选择品牌的图片" }],
},
需要所有表单验证通过才可以发送请求
删除品牌
1、弹框设置
deleteTradeMark(row) {
this.$confirm(`你确定删除${row.tmName}?`, "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(async () => {
let result = await this.$API.trademark.reqDeleteTradeMark(row.id);
if (result.code == 200) {
this.$message({
type: "success",
message: "删除成功!",
});
this.getPageList(this.list.length > 1 ? this.page : this.page - 1);
}
})
.catch(() => {
this.$message({
type: "info",
message: "已取消删除",
});
});
},
},
2、接口
export const reqDeleteTradeMark = (id)=>request({url:`/admin/product/baseTrademark/remove/${id}`,method:'delete'});
3、当点击确认按钮,要向服务器发请求
let result = await this.$API.trademark.reqDeleteTradeMark(row.id);
this.getPageList(this.list.length > 1 ? this.page : this.page - 1);
|