基于 Vue3 ,打造前台+中台通用提效解决方案
核心代码,注释必读
// download:
3w ukoou com
实战项目具体要求:
- 基于 Vue3 开发一款前台 + 中台的应用品牌网站,提供基础的用户登陆、注册、收藏等功能。
- 使用 Vue3 + Vue Router + Vuex 作为主要技术栈,同时使用 axios 作为HTTP客户端,并使用 Ant Design Vue 作为UI组件库。
- 前台部分包括首页、商品列表页、商品详情页、购物车、用户登录注册页面等核心业务页面,实现商品的分类、搜索、排序、加入购物车、收藏等功能,用户登录注册需要实现表单校验和提交。
- 中台部分包括用户管理、数据统计、商品管理、订单管理等后台管理页面,对数据进行增删改查等操作,并对用户角色和权限进行管理。
首先,我们需要安装和配置 Vue3 开发环境以及相关工具和插件。这些都是相当基础和常规的工作,我在这里简单说明一下,具体可以参考 Vue3 官网。
安装 Node.js:
Node.js 是一种 JavaScript 运行环境,可以在开发中运行 JavaScript 代码,很多前后端开发都需要用到。你需要到 Node.js 官网上下载安装包并安装,然后打开命令行窗口,输入下面的命令来验证安装是否成功:
node -v
安装 Git:
Git 是版本控制系统,可以帮助我们对代码进行管理。你需要到 Git 官网上下载安装包并安装,然后打开命令行窗口,输入下面的命令来验证安装是否成功:
git --version
安装 Vue CLI:
Vue CLI 是 Vue.js 官方提供的脚手架工具,可以帮助我们快速搭建基于 Vue.js 的项目。你需要打开命令行窗口,输入下面的命令进行安装:
sudo npm install -g @vue/cli
搭建应用工程:
接下来我们需要使用 Vue CLI 来搭建一个 Vue3 应用工程。你可以打开命令行窗口,输入下面的命令来创建一个名为 vue3-demo 的项目:
vue create vue3-demo
这个命令会让你选择一种预设,我们选择“Manually select features”自定义安装,然后会让你选择需要的特性,选择如下的特性:
- Choose Vue version: 3.x
- Router: Vue Router
- Vuex: Vuex
- CSS Pre-processors: Sass/SCSS (with node-sass)
- Linter: ESLint with error prevention only
- Formatter: Prettier
- Config for Babel, ESLint, etc.: (Pick the left one)
最后按照提示安装即可。
接下来,为了让 Ant Design Vue 插件好用,我们需要配置一下 babel.config.js 文件:
module.exports = {
plugins: [
[
"import",
{
libraryName: "ant-design-vue",
libraryDirectory: "es",
style: true,
},
"ant-design-vue",
],
],
};
然后,我们可以开始编写具体的实现代码了。正常开发时,我们可能会使用mock数据,本文我将用[Easy-Mock](www.easy-mock.com/)模拟数据。当然,使用…
前台页面实现
首先,我们需要实现基本的前台页面,包括首页、商品列表、商品详情、购物车、用户登录注册页面等。
首页
首页是应用的入口,也是用户浏览网站的起点。我们使用 Ant Design Vue 中的 Carousel 组件来实现首页轮播图和“经典案例”列表。代码如下:
<template>
<div>
<a-carousel autoplay :dot-position="dotPosition" style="margin-top: 32px;">
<a-carousel-slide v-for="(item, index) in carouselList" :key="index">
<a-card :cover="item.imgUrl">
<a-card-meta
:title="item.title"
:description="item.description"
/>
</a-card>
</a-carousel-slide>
</a-carousel>
<a-divider orientation="left" style="margin-top: 48px;">
经典案例
</a-divider>
<a-row>
<a-col :span="6" v-for="(item, index) in classicList" :key="index">
<a-card
hoverable
style="margin: 16px;"
:cover="item.imgUrl"
>
<a-card-meta :title="item.title" :description="item.description" />
</a-card>
</a-col>
</a-row>
</div>
</template>
<script>
import { defineComponent } from "vue";
import { Carousel, Card, Divider, Row, Col } from "ant-design-vue";
export default defineComponent({
name: "Home",
components: {
"a-carousel": Carousel,
"a-carousel-slide": Carousel.Slide,
"a-card": Card,
"a-card-meta": Card.Meta,
"a-divider": Divider,
"a-row": Row,
"a-col": Col,
},
data() {
return {
dotPosition: "bottom",
carouselList: [
{
title: "标题1",
description: "描述1",
imgUrl:
"https://www.easy-mock.com/mock/5f7a95d488fe695575895a29/demo/image/01.jpg",
},
{
title: "标题2",
description: "描述2",
imgUrl:
"https://www.easy-mock.com/mock/5f7a95d488fe695575895a29/demo/image/02.jpg",
},
{
title: "标题3",
description: "描述3",
imgUrl:
"https://www.easy-mock.com/mock/5f7a95d488fe695575895a29/demo/image/03.jpg",
},
],
classicList: [
{
title: "经典案例1",
description: "描述1",
imgUrl:
"https://www.easy-mock.com/mock/5f7a95d488fe695575895a29/demo/image/04.jpg",
},
{
title: "经典案例2",
description: "描述2",
imgUrl:
"https://www.easy-mock.com/mock/5f7a95d488fe695575895a29/demo/image/05.jpg",
},
{
title: "经典案例3",
description: "描述3",
imgUrl:
"https://www.easy-mock.com/mock/5f7a95d488fe695575895a29/demo/image/06.jpg",
},
{
title: "经典案例4",
description: "描述4",
imgUrl:
"https://www.easy-mock.com/mock/5f7a95d488fe695575895a29/demo/image/07.jpg",
},
],
};
},
});
</script>
商品列表
商品列表是网站主要的展示内容,需要满足商品的分类、搜索、排序、加入购物车、收藏等功能。我们使用 Ant Design Vue 中的 Table 组件来实现商品列表展示,PageHeader 组件实现顶部的分类筛选和搜索框,Pagination 组件实现分页功能。代码如下:
<template>
<div>
<a-page-header @back="goBack" :title="'商品列表'" :tags="tags">
<template #tags>
<a-tag v-for="(item, index) in filterData" :key="index" @click="handleFilter(item)">
{{ item.name }}
</a-tag>
</template>
<template #extra>
<a-input-search
:placeholder="'请输入商品名称'"
:allow-clear="true"
:on-search="handleSearch"
/>
<a-dropdown placement="bottomLeft">
<a-menu slot="overlay">
<a-menu-item-group title="按价格排序">
<a-menu-item @click="handleSort(PriceSortType.ASC)">
价格由低到高
</a-menu-item>
<a-menu-item @click="handleSort(PriceSortType.DESC)">
价格由高到低
</a-menu-item>
</a-menu-item-group>
<a-menu-item-group title="按销量排序">
<a-menu-item @click="handleSort(SaleSortType.ASC)">
销量由低到高
</a-menu-item>
<a-menu-item @click="handleSort(SaleSortType.DESC)">
销量由高到低
</a-menu-item>
</a-menu-item-group>
</a-menu>
<a-button style="margin-right: 16px;">
<a-icon type="ordered-list" />
</a-button>
</a-dropdown>
<a-dropdown placement="bottomLeft">
<a-avatar slot="overlay" size="small" :src="avatarUrl" />
</a-dropdown>
</template>
</a-page-header>
<a-table :columns="columns" :dataSource="dataSource" :loading="loading">
<template #imgUrl="record">
<a-avatar :size="64" :src="record.imgUrl" />
</template>
<template #action="record">
<a-button-group>
<a-button type="primary" :shape="circle" @click="handleAddCart(record)">
<a-icon type="shopping-cart" />
</a-button>
<a-button :shape="circle" @click="handleAddFavor(record)">
<a-icon type="heart" />
</a-button>
</a-button-group>
</template>
</a-table>
<a-pagination
:current="pagination.current"
:total="pagination.total"
:pageSize="pagination.pageSize"
@current-change="handlePage"
style="margin-top: 16px; text-align: right"
/>
</div>
</template>
<script>
import { defineComponent } from "vue";
import {
PageHeader,
Tag,
Input,
Dropdown,
Button,
Avatar,
Menu,
MenuItem,
MenuItemGroup,
Table,
AvatarGroup,
Pagination,
ButtonGroup,
Icon,
} from "ant-design-vue";
export default defineComponent({
name: "GoodsList",
components: {
"a-page-header": PageHeader,
"a-tag": Tag,
"a-input-search": Input.Search,
"a-dropdown": Dropdown,
"a-button": Button,
"a-avatar": Avatar,
"a-menu": Menu,
"a-menu-item": MenuItem,
"a-menu-item-group": MenuItemGroup,
"a-table": Table,
"a-pagination": Pagination,
"a-button-group": ButtonGroup,
"a-icon": Icon,
},
data() {
return {
avatarUrl:
"https://www.easy-mock.com/mock/5f7a95d488fe695575895a29/demo/avatar.png",
tags: [],
filterData: [
{ key: 1, name: "分类1" },
{ key: 2, name: "分类2" },
{ key: 3, name: "分类3" },
],
loading: false,
columns: [
{
title: "商品名称",
dataIndex: "name",
sorter: (a, b) => a.name.localeCompare(b.name),
defaultSortOrder: "ascend",
},
{
title: "商品图片",
dataIndex: "imgUrl",
slots: { customRender: "imgUrl" },
},
{
title: "价格",
dataIndex: "price",
sorter: (a, b) => a.price - b.price,
},
{
title: "销量",
dataIndex: "sale",
sorter: (a, b) => a.sale - b.sale,
},
{
title: "操作",
dataIndex: "",
slots: { customRender: "action" },
},
],
dataSource: [],
pagination: {
current: 1,
total: 0,
pageSize: 10,
},
PriceSortType: {
ASC: "ascend",
DESC: "descend",
},
SaleSortType: {
ASC: "sale-ascend",
DESC: "sale-descend",
},
};
},
mounted() {
this.fetchList();
},
methods: {
goBack() {
this.$router.go(-1);
},
async fetchList() {
this.loading = true;
const res = await this.$axios.get("/list", {
params: {
page: this.pagination.current,
pageSize: this.pagination.pageSize,
},
});
this.dataSource = res.data.list;
this.pagination.total = res.data.total;
this.loading = false;
},
async handleFilter(item) {
const tags = this.tags.slice();
const idx = tags.findIndex((tag) => tag.key === item.key);
if (idx === -1) {
tags.push(item);
} else {
tags.splice(idx, 1);
}
this.tags = tags;
this.fetchList();
},
async handleSearch(value) {
this.fetchList();
},
async handleSort(sortType) {
this.columns[2].sortOrder = sortType;
this.columns[3].sortOrder = null;
this.fetchList();
},
async handlePage(current) {
this.pagination.current = current;
this.fetchList();
},
async handleAddCart(record) {
this.$message.success(`已添加商品 ${record.name} 到购物车`);
},
async handleAddFavor(record) {
this.$message.success(`已添加商品 ${record.name} 到收藏`);
},
},
});
</script>
<style>
.ant-page-header-heading-sub-description {
font-size: 14px;
}
</style>
商品详情
商品详情页面展示了商品的详细信息,包括大图、名称、价格、描述、库存等,以及购买按钮和收藏按钮。我们使用 Ant Design Vue 中的 Card 组件来实现商品详情展示和收藏功能,使用 Button 组件实现购买按钮。代码如下:
<template>
<div>
<a-page-header @back="goBack" :title="'商品详情'">
<template #extra>
<a-button @click="handleFavor" :shape="circle">
<a-icon :type="favorStatus ? 'heart' : 'heart-outlined'" />
</a-button>
</template>
</a-page-header>
<a-card
:title="goodsInfo.name"
:cover="goodsInfo.imgUrl"
style="margin-top: 16px;"
>
<p style="font-size: 24px; color: red">{{ goodsInfo.price }}</p>
<p style="font-size: 16px;">库存: {{ goodsInfo.stock }}</p>
<hr />
<p style="font-size: 16px;">
{{ goodsInfo.description }}
</p>
<a-button type="primary" style="margin-top: 16px;" @click="handleBuy">
购买
</a-button>
</a-card>
</div>
</template>
<script>
import { defineComponent } from "vue";
import { PageHeader, Card, Button, Icon } from "ant-design-vue";
export default defineComponent({
name: "GoodsDetail",
components: {
"a-page-header": PageHeader,
"a-card": Card,
"a-button": Button,
"a-icon": Icon,
},
data() {
return {
goodsInfo: {},
favorStatus: false,
};
},
mounted() {
this.fetchGoodsInfo();
},
methods: {
goBack() {
this.$router.go(-1);
},
async fetchGoodsInfo() {
const res = await this.$axios.get(`/detail?id=${this.$route.query.id}`);
this.goodsInfo = res.data;
},
async handleFavor() {
this.favorStatus = !this.favorStatus;
this.$message.success(
`商品 ${this.goodsInfo.name} ${
this.favorStatus ? "已添加到收藏" : "已取消收藏"
}`
);
},
async handleBuy() {
this.$message.success(`购买成功,祝您愉快!`);
},
},
});
</script>
购物车
购物车主要展示用户添加的商品,包括商品个数、单价、小计、总计等信息,以及删除和结算按钮。我们使用 Ant Design Vue 中的 List 组件来实现购物车展示,使用 Divider 组件实现列表