From f48acbe97b847536d77d50c6179b1ce90bbe0a8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=AD=90=E7=90=A6?= <95332614+wangziqi0409@users.noreply.github.com> Date: Tue, 10 Feb 2026 10:45:23 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E7=BE=8E=E8=8B=A5?= =?UTF-8?q?=E5=BD=A9=E5=A6=86=E9=94=80=E5=94=AE=E5=B9=B3=E5=8F=B0=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 77 +++ meiruo-backend/pom.xml | 86 ++++ meiruo-backend/sql/database.sql | 135 ++++++ .../cosmetics/MeiruoCosmeticsApplication.java | 18 + .../cosmetics/config/SaTokenConfig.java | 42 ++ .../meiruo/cosmetics/config/WebConfig.java | 16 + .../controller/BannerController.java | 71 +++ .../cosmetics/controller/CartController.java | 64 +++ .../controller/CategoryController.java | 62 +++ .../cosmetics/controller/OrderController.java | 90 ++++ .../controller/ProductController.java | 73 +++ .../controller/UploadController.java | 58 +++ .../cosmetics/controller/UserController.java | 105 +++++ .../com/meiruo/cosmetics/entity/Banner.java | 15 + .../com/meiruo/cosmetics/entity/Cart.java | 14 + .../com/meiruo/cosmetics/entity/Category.java | 14 + .../com/meiruo/cosmetics/entity/Order.java | 22 + .../meiruo/cosmetics/entity/OrderItem.java | 17 + .../com/meiruo/cosmetics/entity/Product.java | 21 + .../com/meiruo/cosmetics/entity/User.java | 19 + .../meiruo/cosmetics/mapper/BannerMapper.java | 22 + .../meiruo/cosmetics/mapper/CartMapper.java | 24 + .../cosmetics/mapper/CategoryMapper.java | 20 + .../cosmetics/mapper/OrderItemMapper.java | 16 + .../meiruo/cosmetics/mapper/OrderMapper.java | 29 ++ .../cosmetics/mapper/ProductMapper.java | 28 ++ .../meiruo/cosmetics/mapper/UserMapper.java | 26 ++ .../cosmetics/service/BannerService.java | 19 + .../meiruo/cosmetics/service/CartService.java | 20 + .../cosmetics/service/CategoryService.java | 17 + .../cosmetics/service/OrderService.java | 24 + .../cosmetics/service/ProductService.java | 25 + .../meiruo/cosmetics/service/UserService.java | 23 + .../service/impl/BannerServiceImpl.java | 47 ++ .../service/impl/CartServiceImpl.java | 61 +++ .../service/impl/CategoryServiceImpl.java | 42 ++ .../service/impl/OrderServiceImpl.java | 99 ++++ .../service/impl/ProductServiceImpl.java | 63 +++ .../service/impl/UserServiceImpl.java | 80 ++++ .../src/main/resources/application.yml | 31 ++ .../main/resources/mapper/BannerMapper.xml | 52 +++ .../src/main/resources/mapper/CartMapper.xml | 62 +++ .../main/resources/mapper/CategoryMapper.xml | 46 ++ .../main/resources/mapper/OrderItemMapper.xml | 33 ++ .../src/main/resources/mapper/OrderMapper.xml | 119 +++++ .../main/resources/mapper/ProductMapper.xml | 81 ++++ .../src/main/resources/mapper/UserMapper.xml | 70 +++ meiruo-frontend/index.html | 13 + meiruo-frontend/package.json | 25 + meiruo-frontend/src/App.vue | 12 + meiruo-frontend/src/api/index.js | 108 +++++ meiruo-frontend/src/components/Footer.vue | 18 + meiruo-frontend/src/components/Header.vue | 160 +++++++ meiruo-frontend/src/main.js | 20 + meiruo-frontend/src/router/index.js | 120 +++++ meiruo-frontend/src/stores/user.js | 65 +++ meiruo-frontend/src/style.css | 37 ++ meiruo-frontend/src/views/admin/Admin.vue | 119 +++++ .../src/views/admin/BannerManage.vue | 366 +++++++++++++++ .../src/views/admin/CategoryManage.vue | 260 +++++++++++ meiruo-frontend/src/views/admin/Dashboard.vue | 129 +++++ .../src/views/admin/OrderManage.vue | 119 +++++ .../src/views/admin/ProductManage.vue | 442 ++++++++++++++++++ .../src/views/admin/UserManage.vue | 110 +++++ meiruo-frontend/src/views/user/Cart.vue | 152 ++++++ meiruo-frontend/src/views/user/Checkout.vue | 235 ++++++++++ meiruo-frontend/src/views/user/Home.vue | 437 +++++++++++++++++ meiruo-frontend/src/views/user/Login.vue | 100 ++++ meiruo-frontend/src/views/user/Order.vue | 178 +++++++ .../src/views/user/ProductDetail.vue | 157 +++++++ meiruo-frontend/src/views/user/Register.vue | 127 +++++ meiruo-frontend/src/views/user/UserCenter.vue | 161 +++++++ meiruo-frontend/vite.config.js | 21 + 美若彩妆销售平台功能清单.md | 36 ++ 胡宝月-美若彩妆销售平台-开题报告.md | 208 +++++++++ 75 files changed, 6133 insertions(+) create mode 100644 .gitignore create mode 100644 meiruo-backend/pom.xml create mode 100644 meiruo-backend/sql/database.sql create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/MeiruoCosmeticsApplication.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/config/SaTokenConfig.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/config/WebConfig.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/BannerController.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/CartController.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/CategoryController.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/OrderController.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/ProductController.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/UploadController.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/UserController.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/Banner.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/Cart.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/Category.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/Order.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/OrderItem.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/Product.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/User.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/BannerMapper.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/CartMapper.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/CategoryMapper.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/OrderItemMapper.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/OrderMapper.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/ProductMapper.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/UserMapper.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/service/BannerService.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/service/CartService.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/service/CategoryService.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/service/OrderService.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/service/ProductService.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/service/UserService.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/service/impl/BannerServiceImpl.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/service/impl/CartServiceImpl.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/service/impl/CategoryServiceImpl.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/service/impl/OrderServiceImpl.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/service/impl/ProductServiceImpl.java create mode 100644 meiruo-backend/src/main/java/com/meiruo/cosmetics/service/impl/UserServiceImpl.java create mode 100644 meiruo-backend/src/main/resources/application.yml create mode 100644 meiruo-backend/src/main/resources/mapper/BannerMapper.xml create mode 100644 meiruo-backend/src/main/resources/mapper/CartMapper.xml create mode 100644 meiruo-backend/src/main/resources/mapper/CategoryMapper.xml create mode 100644 meiruo-backend/src/main/resources/mapper/OrderItemMapper.xml create mode 100644 meiruo-backend/src/main/resources/mapper/OrderMapper.xml create mode 100644 meiruo-backend/src/main/resources/mapper/ProductMapper.xml create mode 100644 meiruo-backend/src/main/resources/mapper/UserMapper.xml create mode 100644 meiruo-frontend/index.html create mode 100644 meiruo-frontend/package.json create mode 100644 meiruo-frontend/src/App.vue create mode 100644 meiruo-frontend/src/api/index.js create mode 100644 meiruo-frontend/src/components/Footer.vue create mode 100644 meiruo-frontend/src/components/Header.vue create mode 100644 meiruo-frontend/src/main.js create mode 100644 meiruo-frontend/src/router/index.js create mode 100644 meiruo-frontend/src/stores/user.js create mode 100644 meiruo-frontend/src/style.css create mode 100644 meiruo-frontend/src/views/admin/Admin.vue create mode 100644 meiruo-frontend/src/views/admin/BannerManage.vue create mode 100644 meiruo-frontend/src/views/admin/CategoryManage.vue create mode 100644 meiruo-frontend/src/views/admin/Dashboard.vue create mode 100644 meiruo-frontend/src/views/admin/OrderManage.vue create mode 100644 meiruo-frontend/src/views/admin/ProductManage.vue create mode 100644 meiruo-frontend/src/views/admin/UserManage.vue create mode 100644 meiruo-frontend/src/views/user/Cart.vue create mode 100644 meiruo-frontend/src/views/user/Checkout.vue create mode 100644 meiruo-frontend/src/views/user/Home.vue create mode 100644 meiruo-frontend/src/views/user/Login.vue create mode 100644 meiruo-frontend/src/views/user/Order.vue create mode 100644 meiruo-frontend/src/views/user/ProductDetail.vue create mode 100644 meiruo-frontend/src/views/user/Register.vue create mode 100644 meiruo-frontend/src/views/user/UserCenter.vue create mode 100644 meiruo-frontend/vite.config.js create mode 100644 美若彩妆销售平台功能清单.md create mode 100644 胡宝月-美若彩妆销售平台-开题报告.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e513798 --- /dev/null +++ b/.gitignore @@ -0,0 +1,77 @@ +# Compiled class files +*.class + +# Log files +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# Maven +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +.mvn/wrapper/maven-wrapper.jar + +# Gradle +.gradle/ +build/ + +# IDE +.idea/ +*.iml +*.ipr +*.iws +.project +.classpath +.settings/ +.vscode/ +*.suo +*.ntvs* +*.njsproj +*.sln +*.swp +*.swo +*~ + +# OS +.DS_Store +Thumbs.db + +# Application +application-local.yml +application-prod.yml +upload/ +temp/ +logs/ + +# Node +node_modules/ +dist/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# Environment +.env +.env.local +.env.*.local diff --git a/meiruo-backend/pom.xml b/meiruo-backend/pom.xml new file mode 100644 index 0000000..c35d591 --- /dev/null +++ b/meiruo-backend/pom.xml @@ -0,0 +1,86 @@ + + + 4.0.0 + + + org.springframework.boot + spring-boot-starter-parent + 3.2.0 + + + + com.meiruo + meiruo-cosmetics + 1.0.0 + meiruo-cosmetics + 美若彩妆销售平台 + + + 17 + 3.0.3 + 1.38.0 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + ${mybatis-spring-boot.version} + + + + com.mysql + mysql-connector-j + runtime + + + + cn.dev33 + sa-token-spring-boot3-starter + ${sa-token.version} + + + + cn.dev33 + sa-token-jwt + ${sa-token.version} + + + + org.projectlombok + lombok + true + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + + + diff --git a/meiruo-backend/sql/database.sql b/meiruo-backend/sql/database.sql new file mode 100644 index 0000000..04d3737 --- /dev/null +++ b/meiruo-backend/sql/database.sql @@ -0,0 +1,135 @@ +-- 创建数据库 +CREATE DATABASE IF NOT EXISTS meiruo_cosmetics DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +USE meiruo_cosmetics; + +-- 用户表 +CREATE TABLE IF NOT EXISTS `user` ( + `id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '用户ID', + `username` VARCHAR(50) NOT NULL UNIQUE COMMENT '用户名', + `password` VARCHAR(100) NOT NULL COMMENT '密码', + `nickname` VARCHAR(50) COMMENT '昵称', + `phone` VARCHAR(20) COMMENT '手机号', + `email` VARCHAR(100) COMMENT '邮箱', + `avatar` VARCHAR(255) COMMENT '头像', + `role` TINYINT DEFAULT 0 COMMENT '角色:0-普通用户,1-管理员', + `status` TINYINT DEFAULT 1 COMMENT '状态:0-禁用,1-正常', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + INDEX idx_username (`username`), + INDEX idx_phone (`phone`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表'; + +-- 分类表 +CREATE TABLE IF NOT EXISTS `category` ( + `id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '分类ID', + `name` VARCHAR(50) NOT NULL COMMENT '分类名称', + `description` VARCHAR(255) COMMENT '分类描述', + `sort` INT DEFAULT 0 COMMENT '排序', + `status` TINYINT DEFAULT 1 COMMENT '状态:0-禁用,1-正常', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + INDEX idx_status (`status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品分类表'; + +-- 商品表 +CREATE TABLE IF NOT EXISTS `product` ( + `id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '商品ID', + `name` VARCHAR(100) NOT NULL COMMENT '商品名称', + `description` TEXT COMMENT '商品描述', + `price` DECIMAL(10,2) NOT NULL COMMENT '价格', + `stock` INT DEFAULT 0 COMMENT '库存', + `category_id` BIGINT COMMENT '分类ID', + `image` VARCHAR(255) COMMENT '主图', + `images` TEXT COMMENT '图片列表', + `status` TINYINT DEFAULT 1 COMMENT '状态:0-下架,1-正常', + `sales` INT DEFAULT 0 COMMENT '销量', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + INDEX idx_category (`category_id`), + INDEX idx_status (`status`), + INDEX idx_sales (`sales`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品表'; + +-- 购物车表 +CREATE TABLE IF NOT EXISTS `cart` ( + `id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '购物车ID', + `user_id` BIGINT NOT NULL COMMENT '用户ID', + `product_id` BIGINT NOT NULL COMMENT '商品ID', + `quantity` INT NOT NULL DEFAULT 1 COMMENT '数量', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + UNIQUE KEY uk_user_product (`user_id`, `product_id`), + INDEX idx_user (`user_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='购物车表'; + +-- 订单表 +CREATE TABLE IF NOT EXISTS `order` ( + `id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '订单ID', + `order_no` VARCHAR(32) NOT NULL UNIQUE COMMENT '订单号', + `user_id` BIGINT NOT NULL COMMENT '用户ID', + `total_amount` DECIMAL(10,2) NOT NULL COMMENT '总金额', + `status` TINYINT DEFAULT 1 COMMENT '状态:1-待付款,2-已付款,3-已发货,4-已完成,5-已取消', + `receiver_name` VARCHAR(50) COMMENT '收货人姓名', + `receiver_phone` VARCHAR(20) COMMENT '收货人电话', + `receiver_address` VARCHAR(255) COMMENT '收货地址', + `remark` VARCHAR(255) COMMENT '备注', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `pay_time` DATETIME COMMENT '付款时间', + `ship_time` DATETIME COMMENT '发货时间', + `receive_time` DATETIME COMMENT '收货时间', + INDEX idx_user (`user_id`), + INDEX idx_order_no (`order_no`), + INDEX idx_status (`status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表'; + +-- 订单项表 +CREATE TABLE IF NOT EXISTS `order_item` ( + `id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '订单项ID', + `order_id` BIGINT NOT NULL COMMENT '订单ID', + `product_id` BIGINT NOT NULL COMMENT '商品ID', + `product_name` VARCHAR(100) NOT NULL COMMENT '商品名称', + `product_image` VARCHAR(255) COMMENT '商品图片', + `price` DECIMAL(10,2) NOT NULL COMMENT '商品价格', + `quantity` INT NOT NULL COMMENT '数量', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + INDEX idx_order (`order_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单项表'; + +-- 轮播图表 +CREATE TABLE IF NOT EXISTS `banner` ( + `id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '轮播图ID', + `title` VARCHAR(50) COMMENT '标题', + `image` VARCHAR(255) NOT NULL COMMENT '图片地址', + `link` VARCHAR(255) COMMENT '链接地址', + `sort` INT DEFAULT 0 COMMENT '排序', + `status` TINYINT DEFAULT 1 COMMENT '状态:0-禁用,1-正常', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + INDEX idx_status (`status`), + INDEX idx_sort (`sort`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='轮播图表'; + +-- 插入默认管理员账号 +INSERT INTO `user` (`username`, `password`, `nickname`, `role`, `status`) VALUES +('admin', 'e10adc3949ba59abbe56e057f20f883e', '管理员', 1, 1); + +-- 插入默认分类 +INSERT INTO `category` (`name`, `description`, `sort`) VALUES +('面部彩妆', '粉底液、遮瑕膏、粉饼等', 1), +('眼妆', '眼影、眼线、睫毛膏等', 2), +('唇妆', '口红、唇釉、唇彩等', 3), +('腮红', '腮红、修容等', 4), +('卸妆', '卸妆油、卸妆水等', 5); + +-- 插入示例商品 +INSERT INTO `product` (`name`, `description`, `price`, `stock`, `category_id`, `image`, `status`, `sales`) VALUES +('水润粉底液', '轻薄水润,遮瑕保湿,打造自然裸妆感', 168.00, 100, 1, '/images/product1.jpg', 1, 50), +('大地色眼影盘', '12色日常大地色眼影盘,珠光哑光搭配', 128.00, 80, 2, '/images/product2.jpg', 1, 30), +('哑光正红色口红', '经典正红色,哑光质地,持久显色', 89.00, 200, 3, '/images/product3.jpg', 1, 100), +('腮红', '柔美腮红,轻薄自然,打造好气色', 68.00, 150, 4, '/images/product4.jpg', 1, 25), +('卸妆油', '温和卸妆油,深层清洁不紧绷', 98.00, 120, 5, '/images/product5.jpg', 1, 40); + +-- 插入示例轮播图 +INSERT INTO `banner` (`title`, `image`, `link`, `sort`) VALUES +('新品上市', '/images/banner1.jpg', '/product/1', 1), +('限时优惠', '/images/banner2.jpg', '/product/2', 2), +('热销推荐', '/images/banner3.jpg', '/product/3', 3); diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/MeiruoCosmeticsApplication.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/MeiruoCosmeticsApplication.java new file mode 100644 index 0000000..5e90e0f --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/MeiruoCosmeticsApplication.java @@ -0,0 +1,18 @@ +package com.meiruo.cosmetics; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@MapperScan("com.meiruo.cosmetics.mapper") +public class MeiruoCosmeticsApplication { + + public static void main(String[] args) { + SpringApplication.run(MeiruoCosmeticsApplication.class, args); + System.out.println("===================================="); + System.out.println(" 美若彩妆销售平台启动成功!"); + System.out.println("===================================="); + } + +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/config/SaTokenConfig.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/config/SaTokenConfig.java new file mode 100644 index 0000000..bb9230c --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/config/SaTokenConfig.java @@ -0,0 +1,42 @@ +package com.meiruo.cosmetics.config; + +import cn.dev33.satoken.interceptor.SaInterceptor; +import cn.dev33.satoken.jwt.SaJwtManager; +import cn.dev33.satoken.jwt.StpLogicJwtForSimple; +import cn.dev33.satoken.stp.StpInterface; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import java.util.ArrayList; +import java.util.List; + +@Configuration +public class SaTokenConfig implements WebMvcConfigurer { + + @Bean + public StpLogicJwtForSimple stpLogicJwtForSimple() { + return new StpLogicJwtForSimple(); + } + + @Bean + public StpInterface stpInterface() { + return new StpInterface() { + @Override + public List getPermissionList(Object loginId, String loginType) { + return new ArrayList<>(); + } + + @Override + public List getRoleList(Object loginId, String loginType) { + return new ArrayList<>(); + } + }; + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(new SaInterceptor()).addPathPatterns("/api/**").excludePathPatterns("/api/user/login", "/api/user/register"); + } +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/config/WebConfig.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/config/WebConfig.java new file mode 100644 index 0000000..939da44 --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/config/WebConfig.java @@ -0,0 +1,16 @@ +package com.meiruo.cosmetics.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/upload/**") + .addResourceLocations("file:src/main/resources/static/upload/") + .addResourceLocations("classpath:/static/upload/"); + } +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/BannerController.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/BannerController.java new file mode 100644 index 0000000..f0ba779 --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/BannerController.java @@ -0,0 +1,71 @@ +package com.meiruo.cosmetics.controller; + +import com.meiruo.cosmetics.entity.Banner; +import com.meiruo.cosmetics.service.BannerService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@RestController +@RequestMapping("/api/banner") +public class BannerController { + + @Autowired + private BannerService bannerService; + + @GetMapping("/list") + public Map getList(@RequestParam(required = false) Integer status) { + Map result = new HashMap<>(); + List list = bannerService.getList(status); + result.put("code", 200); + result.put("data", list); + return result; + } + + @GetMapping("/{id}") + public Map getById(@PathVariable Long id) { + Map result = new HashMap<>(); + result.put("code", 200); + result.put("data", bannerService.getById(id)); + return result; + } + + @PostMapping + public Map add(@RequestBody Banner banner) { + Map result = new HashMap<>(); + bannerService.add(banner); + result.put("code", 200); + result.put("msg", "添加成功"); + return result; + } + + @PutMapping + public Map update(@RequestBody Banner banner) { + Map result = new HashMap<>(); + bannerService.update(banner); + result.put("code", 200); + result.put("msg", "修改成功"); + return result; + } + + @DeleteMapping("/{id}") + public Map delete(@PathVariable Long id) { + Map result = new HashMap<>(); + bannerService.delete(id); + result.put("code", 200); + result.put("msg", "删除成功"); + return result; + } + + @PutMapping("/sort/{id}") + public Map updateSort(@PathVariable Long id, @RequestParam Integer sort) { + Map result = new HashMap<>(); + bannerService.updateSort(id, sort); + result.put("code", 200); + result.put("msg", "修改成功"); + return result; + } +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/CartController.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/CartController.java new file mode 100644 index 0000000..6e0ed2d --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/CartController.java @@ -0,0 +1,64 @@ +package com.meiruo.cosmetics.controller; + +import cn.dev33.satoken.stp.StpUtil; +import com.meiruo.cosmetics.service.CartService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.Map; + +@RestController +@RequestMapping("/api/cart") +public class CartController { + + @Autowired + private CartService cartService; + + @GetMapping("/list") + public Map getList() { + Map result = new HashMap<>(); + Long userId = StpUtil.getLoginIdAsLong(); + result.put("code", 200); + result.put("data", cartService.getCartList(userId)); + return result; + } + + @PostMapping("/add") + public Map add(@RequestParam Long productId, @RequestParam Integer quantity) { + Map result = new HashMap<>(); + Long userId = StpUtil.getLoginIdAsLong(); + cartService.add(userId, productId, quantity); + result.put("code", 200); + result.put("msg", "添加成功"); + return result; + } + + @PutMapping("/quantity/{id}") + public Map updateQuantity(@PathVariable Long id, @RequestParam Integer quantity) { + Map result = new HashMap<>(); + cartService.updateQuantity(id, quantity); + result.put("code", 200); + result.put("msg", "修改成功"); + return result; + } + + @DeleteMapping("/{id}") + public Map delete(@PathVariable Long id) { + Map result = new HashMap<>(); + cartService.delete(id); + result.put("code", 200); + result.put("msg", "删除成功"); + return result; + } + + @DeleteMapping("/clear") + public Map clear() { + Map result = new HashMap<>(); + Long userId = StpUtil.getLoginIdAsLong(); + cartService.clear(userId); + result.put("code", 200); + result.put("msg", "清空成功"); + return result; + } +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/CategoryController.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/CategoryController.java new file mode 100644 index 0000000..18ff5e9 --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/CategoryController.java @@ -0,0 +1,62 @@ +package com.meiruo.cosmetics.controller; + +import com.meiruo.cosmetics.entity.Category; +import com.meiruo.cosmetics.service.CategoryService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@RestController +@RequestMapping("/api/category") +public class CategoryController { + + @Autowired + private CategoryService categoryService; + + @GetMapping("/list") + public Map getList(@RequestParam(required = false) Integer status) { + Map result = new HashMap<>(); + List list = categoryService.getList(status); + result.put("code", 200); + result.put("data", list); + return result; + } + + @GetMapping("/{id}") + public Map getById(@PathVariable Long id) { + Map result = new HashMap<>(); + result.put("code", 200); + result.put("data", categoryService.getById(id)); + return result; + } + + @PostMapping + public Map add(@RequestBody Category category) { + Map result = new HashMap<>(); + categoryService.add(category); + result.put("code", 200); + result.put("msg", "添加成功"); + return result; + } + + @PutMapping + public Map update(@RequestBody Category category) { + Map result = new HashMap<>(); + categoryService.update(category); + result.put("code", 200); + result.put("msg", "修改成功"); + return result; + } + + @DeleteMapping("/{id}") + public Map delete(@PathVariable Long id) { + Map result = new HashMap<>(); + categoryService.delete(id); + result.put("code", 200); + result.put("msg", "删除成功"); + return result; + } +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/OrderController.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/OrderController.java new file mode 100644 index 0000000..2273eab --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/OrderController.java @@ -0,0 +1,90 @@ +package com.meiruo.cosmetics.controller; + +import cn.dev33.satoken.stp.StpUtil; +import com.meiruo.cosmetics.entity.Order; +import com.meiruo.cosmetics.service.OrderService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@RestController +@RequestMapping("/api/order") +public class OrderController { + + @Autowired + private OrderService orderService; + + @PostMapping("/create") + public Map create( + @RequestBody Map params) { + Map result = new HashMap<>(); + Long userId = StpUtil.getLoginIdAsLong(); + List cartIds = (List) params.get("cartIds"); + String receiverName = (String) params.get("receiverName"); + String receiverPhone = (String) params.get("receiverPhone"); + String receiverAddress = (String) params.get("receiverAddress"); + String remark = (String) params.get("remark"); + + Order order = orderService.create(userId, cartIds, receiverName, receiverPhone, receiverAddress, remark); + result.put("code", 200); + result.put("msg", "下单成功"); + result.put("data", order); + return result; + } + + @GetMapping("/list") + public Map getList(@RequestParam(required = false) Integer status) { + Map result = new HashMap<>(); + Long userId = StpUtil.getLoginIdAsLong(); + List list = orderService.getByUserId(userId, status); + result.put("code", 200); + result.put("data", list); + return result; + } + + @GetMapping("/admin/list") + public Map adminList(@RequestParam(required = false) String keyword, @RequestParam(required = false) Integer status) { + Map result = new HashMap<>(); + List list = orderService.getList(keyword, status); + result.put("code", 200); + result.put("data", list); + return result; + } + + @GetMapping("/{id}") + public Map getById(@PathVariable Long id) { + Map result = new HashMap<>(); + Order order = orderService.getById(id); + result.put("code", 200); + result.put("data", order); + return result; + } + + @PutMapping("/status/{id}") + public Map updateStatus(@PathVariable Long id, @RequestParam Integer status) { + Map result = new HashMap<>(); + orderService.updateStatus(id, status); + result.put("code", 200); + result.put("msg", "操作成功"); + return result; + } + + @GetMapping("/revenue/{type}") + public Map getRevenueStatistics(@PathVariable String type) { + Map result = new HashMap<>(); + result.put("code", 200); + result.put("data", orderService.getRevenueStatistics(type)); + return result; + } + + @GetMapping("/top/{limit}") + public Map getTopProducts(@PathVariable Integer limit) { + Map result = new HashMap<>(); + result.put("code", 200); + result.put("data", orderService.getTopProducts(limit)); + return result; + } +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/ProductController.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/ProductController.java new file mode 100644 index 0000000..3a88e3c --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/ProductController.java @@ -0,0 +1,73 @@ +package com.meiruo.cosmetics.controller; + +import com.meiruo.cosmetics.entity.Product; +import com.meiruo.cosmetics.service.ProductService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@RestController +@RequestMapping("/api/product") +public class ProductController { + + @Autowired + private ProductService productService; + + @GetMapping("/list") + public Map getList( + @RequestParam(required = false) Long categoryId, + @RequestParam(required = false) String keyword) { + Map result = new HashMap<>(); + List list = productService.getList(categoryId, keyword); + result.put("code", 200); + result.put("data", list); + return result; + } + + @GetMapping("/recommend") + public Map getRecommend() { + Map result = new HashMap<>(); + result.put("code", 200); + result.put("data", productService.getRecommend()); + return result; + } + + @GetMapping("/{id}") + public Map getById(@PathVariable Long id) { + Map result = new HashMap<>(); + Product product = productService.getById(id); + result.put("code", 200); + result.put("data", product); + return result; + } + + @PostMapping + public Map add(@RequestBody Product product) { + Map result = new HashMap<>(); + productService.add(product); + result.put("code", 200); + result.put("msg", "添加成功"); + return result; + } + + @PutMapping + public Map update(@RequestBody Product product) { + Map result = new HashMap<>(); + productService.update(product); + result.put("code", 200); + result.put("msg", "修改成功"); + return result; + } + + @DeleteMapping("/{id}") + public Map delete(@PathVariable Long id) { + Map result = new HashMap<>(); + productService.delete(id); + result.put("code", 200); + result.put("msg", "删除成功"); + return result; + } +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/UploadController.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/UploadController.java new file mode 100644 index 0000000..e21439e --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/UploadController.java @@ -0,0 +1,58 @@ +package com.meiruo.cosmetics.controller; + +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.IOException; +import java.nio.file.*; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.*; + +@RestController +@RequestMapping("/api/upload") +@CrossOrigin +public class UploadController { + + private static final String UPLOAD_PATH = "src/main/resources/static/upload/"; + + @PostMapping("/image") + public Map uploadImage(@RequestParam("file") MultipartFile file) { + Map result = new HashMap<>(); + + if (file.isEmpty()) { + result.put("code", 500); + result.put("msg", "请选择要上传的文件"); + return result; + } + + try { + String originalFilename = file.getOriginalFilename(); + String ext = originalFilename.substring(originalFilename.lastIndexOf(".")); + + String dateDir = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")); + String fileName = System.currentTimeMillis() + ext; + + Path uploadDir = Paths.get(UPLOAD_PATH + dateDir); + if (!Files.exists(uploadDir)) { + Files.createDirectories(uploadDir); + } + + Path filePath = uploadDir.resolve(fileName); + Files.copy(file.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING); + + String url = "/upload/" + dateDir + "/" + fileName; + + result.put("code", 200); + result.put("msg", "上传成功"); + result.put("url", url); + return result; + } catch (IOException e) { + e.printStackTrace(); + result.put("code", 500); + result.put("msg", "文件上传失败"); + return result; + } + } +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/UserController.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/UserController.java new file mode 100644 index 0000000..22e2657 --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/UserController.java @@ -0,0 +1,105 @@ +package com.meiruo.cosmetics.controller; + +import cn.dev33.satoken.stp.StpUtil; +import com.meiruo.cosmetics.entity.User; +import com.meiruo.cosmetics.service.UserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.Map; + +@RestController +@RequestMapping("/api/user") +public class UserController { + + @Autowired + private UserService userService; + + @PostMapping("/login") + public Map login(@RequestBody User user) { + Map result = new HashMap<>(); + User loginUser = userService.login(user.getUsername(), user.getPassword()); + if (loginUser == null) { + result.put("code", 500); + result.put("msg", "用户名或密码错误"); + return result; + } + Map data = new HashMap<>(); + data.put("id", loginUser.getId()); + data.put("username", loginUser.getUsername()); + data.put("nickname", loginUser.getNickname()); + data.put("avatar", loginUser.getAvatar()); + data.put("role", loginUser.getRole()); + result.put("code", 200); + result.put("msg", "登录成功"); + result.put("data", data); + return result; + } + + @PostMapping("/register") + public Map register(@RequestBody User user) { + Map result = new HashMap<>(); + User registerUser = userService.register(user); + if (registerUser == null) { + result.put("code", 500); + result.put("msg", "用户名已存在"); + return result; + } + result.put("code", 200); + result.put("msg", "注册成功"); + return result; + } + + @GetMapping("/info") + public Map getInfo() { + Map result = new HashMap<>(); + Long userId = StpUtil.getLoginIdAsLong(); + User user = userService.getById(userId); + if (user == null) { + result.put("code", 500); + result.put("msg", "用户不存在"); + return result; + } + result.put("code", 200); + result.put("data", user); + return result; + } + + @PutMapping("/info") + public Map updateInfo(@RequestBody User user) { + Map result = new HashMap<>(); + Long userId = StpUtil.getLoginIdAsLong(); + user.setId(userId); + userService.update(user); + result.put("code", 200); + result.put("msg", "修改成功"); + return result; + } + + @PostMapping("/logout") + public Map logout() { + Map result = new HashMap<>(); + StpUtil.logout(); + result.put("code", 200); + result.put("msg", "退出成功"); + return result; + } + + @GetMapping("/list") + public Map getList(@RequestParam(required = false) String query) { + Map result = new HashMap<>(); + result.put("code", 200); + result.put("data", userService.getList(query)); + return result; + } + + @PutMapping("/status/{id}") + public Map updateStatus(@PathVariable Long id, @RequestParam Integer status) { + Map result = new HashMap<>(); + userService.updateStatus(id, status); + result.put("code", 200); + result.put("msg", "操作成功"); + return result; + } +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/Banner.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/Banner.java new file mode 100644 index 0000000..7a669c0 --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/Banner.java @@ -0,0 +1,15 @@ +package com.meiruo.cosmetics.entity; + +import lombok.Data; +import java.time.LocalDateTime; + +@Data +public class Banner { + private Long id; + private String title; + private String image; + private String link; + private Integer sort; + private Integer status; + private LocalDateTime createTime; +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/Cart.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/Cart.java new file mode 100644 index 0000000..12f4b21 --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/Cart.java @@ -0,0 +1,14 @@ +package com.meiruo.cosmetics.entity; + +import lombok.Data; +import java.time.LocalDateTime; + +@Data +public class Cart { + private Long id; + private Long userId; + private Long productId; + private Integer quantity; + private LocalDateTime createTime; + private LocalDateTime updateTime; +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/Category.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/Category.java new file mode 100644 index 0000000..b638de3 --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/Category.java @@ -0,0 +1,14 @@ +package com.meiruo.cosmetics.entity; + +import lombok.Data; +import java.time.LocalDateTime; + +@Data +public class Category { + private Long id; + private String name; + private String description; + private Integer sort; + private Integer status; + private LocalDateTime createTime; +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/Order.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/Order.java new file mode 100644 index 0000000..fd06cdd --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/Order.java @@ -0,0 +1,22 @@ +package com.meiruo.cosmetics.entity; + +import lombok.Data; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Data +public class Order { + private Long id; + private String orderNo; + private Long userId; + private BigDecimal totalAmount; + private Integer status; + private String receiverName; + private String receiverPhone; + private String receiverAddress; + private String remark; + private LocalDateTime createTime; + private LocalDateTime payTime; + private LocalDateTime shipTime; + private LocalDateTime receiveTime; +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/OrderItem.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/OrderItem.java new file mode 100644 index 0000000..0d0ba8c --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/OrderItem.java @@ -0,0 +1,17 @@ +package com.meiruo.cosmetics.entity; + +import lombok.Data; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Data +public class OrderItem { + private Long id; + private Long orderId; + private Long productId; + private String productName; + private String productImage; + private BigDecimal price; + private Integer quantity; + private LocalDateTime createTime; +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/Product.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/Product.java new file mode 100644 index 0000000..67c33d1 --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/Product.java @@ -0,0 +1,21 @@ +package com.meiruo.cosmetics.entity; + +import lombok.Data; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Data +public class Product { + private Long id; + private String name; + private String description; + private BigDecimal price; + private Integer stock; + private Long categoryId; + private String image; + private String images; + private Integer status; + private Integer sales; + private LocalDateTime createTime; + private LocalDateTime updateTime; +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/User.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/User.java new file mode 100644 index 0000000..1d589b0 --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/User.java @@ -0,0 +1,19 @@ +package com.meiruo.cosmetics.entity; + +import lombok.Data; +import java.time.LocalDateTime; + +@Data +public class User { + private Long id; + private String username; + private String password; + private String nickname; + private String phone; + private String email; + private String avatar; + private Integer role; + private Integer status; + private LocalDateTime createTime; + private LocalDateTime updateTime; +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/BannerMapper.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/BannerMapper.java new file mode 100644 index 0000000..745d4f5 --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/BannerMapper.java @@ -0,0 +1,22 @@ +package com.meiruo.cosmetics.mapper; + +import com.meiruo.cosmetics.entity.Banner; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import java.util.List; + +@Mapper +public interface BannerMapper { + + List selectList(@Param("status") Integer status); + + Banner selectById(@Param("id") Long id); + + int insert(Banner banner); + + int update(Banner banner); + + int delete(@Param("id") Long id); + + int updateSort(@Param("id") Long id, @Param("sort") Integer sort); +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/CartMapper.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/CartMapper.java new file mode 100644 index 0000000..082286e --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/CartMapper.java @@ -0,0 +1,24 @@ +package com.meiruo.cosmetics.mapper; + +import com.meiruo.cosmetics.entity.Cart; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import java.util.List; + +@Mapper +public interface CartMapper { + + Cart selectByUserAndProduct(@Param("userId") Long userId, @Param("productId") Long productId); + + List selectByUserId(@Param("userId") Long userId); + + int insert(Cart cart); + + int update(Cart cart); + + int delete(@Param("id") Long id); + + int deleteByUserId(@Param("userId") Long userId); + + int updateQuantity(@Param("id") Long id, @Param("quantity") Integer quantity); +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/CategoryMapper.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/CategoryMapper.java new file mode 100644 index 0000000..d0c8b78 --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/CategoryMapper.java @@ -0,0 +1,20 @@ +package com.meiruo.cosmetics.mapper; + +import com.meiruo.cosmetics.entity.Category; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import java.util.List; + +@Mapper +public interface CategoryMapper { + + Category selectById(@Param("id") Long id); + + List selectList(@Param("status") Integer status); + + int insert(Category category); + + int update(Category category); + + int delete(@Param("id") Long id); +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/OrderItemMapper.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/OrderItemMapper.java new file mode 100644 index 0000000..10e6762 --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/OrderItemMapper.java @@ -0,0 +1,16 @@ +package com.meiruo.cosmetics.mapper; + +import com.meiruo.cosmetics.entity.OrderItem; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import java.util.List; + +@Mapper +public interface OrderItemMapper { + + List selectByOrderId(@Param("orderId") Long orderId); + + int insert(OrderItem orderItem); + + int insertBatch(@Param("items") List items); +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/OrderMapper.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/OrderMapper.java new file mode 100644 index 0000000..a3b9450 --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/OrderMapper.java @@ -0,0 +1,29 @@ +package com.meiruo.cosmetics.mapper; + +import com.meiruo.cosmetics.entity.Order; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import java.util.List; +import java.util.Map; + +@Mapper +public interface OrderMapper { + + Order selectById(@Param("id") Long id); + + Order selectByOrderNo(@Param("orderNo") String orderNo); + + List selectByUserId(@Param("userId") Long userId, @Param("status") Integer status); + + List selectList(@Param("keyword") String keyword, @Param("status") Integer status); + + int insert(Order order); + + int update(Order order); + + int updateStatus(@Param("id") Long id, @Param("status") Integer status); + + List> selectRevenueStatistics(@Param("type") String type); + + List> selectTopProducts(@Param("limit") Integer limit); +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/ProductMapper.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/ProductMapper.java new file mode 100644 index 0000000..5c5a234 --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/ProductMapper.java @@ -0,0 +1,28 @@ +package com.meiruo.cosmetics.mapper; + +import com.meiruo.cosmetics.entity.Product; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import java.util.List; + +@Mapper +public interface ProductMapper { + + Product selectById(@Param("id") Long id); + + List selectList(@Param("categoryId") Long categoryId, @Param("keyword") String keyword); + + List selectRecommend(); + + List selectByIds(@Param("ids") List ids); + + int insert(Product product); + + int update(Product product); + + int delete(@Param("id") Long id); + + int updateStock(@Param("id") Long id, @Param("count") Integer count); + + int incrementSales(@Param("id") Long id, @Param("count") Integer count); +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/UserMapper.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/UserMapper.java new file mode 100644 index 0000000..30726a8 --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/UserMapper.java @@ -0,0 +1,26 @@ +package com.meiruo.cosmetics.mapper; + +import com.meiruo.cosmetics.entity.User; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import java.util.List; + +@Mapper +public interface UserMapper { + + User selectById(@Param("id") Long id); + + User selectByUsername(@Param("username") String username); + + User selectByPhone(@Param("phone") String phone); + + List selectList(@Param("query") String query); + + int insert(User user); + + int update(User user); + + int delete(@Param("id") Long id); + + int updateStatus(@Param("id") Long id, @Param("status") Integer status); +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/BannerService.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/BannerService.java new file mode 100644 index 0000000..f7bd86a --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/BannerService.java @@ -0,0 +1,19 @@ +package com.meiruo.cosmetics.service; + +import com.meiruo.cosmetics.entity.Banner; +import java.util.List; + +public interface BannerService { + + List getList(Integer status); + + Banner getById(Long id); + + void add(Banner banner); + + void update(Banner banner); + + void delete(Long id); + + void updateSort(Long id, Integer sort); +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/CartService.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/CartService.java new file mode 100644 index 0000000..c57da41 --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/CartService.java @@ -0,0 +1,20 @@ +package com.meiruo.cosmetics.service; + +import com.meiruo.cosmetics.entity.Cart; +import java.util.List; +import java.util.Map; + +public interface CartService { + + List> getCartList(Long userId); + + void add(Long userId, Long productId, Integer quantity); + + void updateQuantity(Long id, Integer quantity); + + void delete(Long id); + + void clear(Long userId); + + void mergeFromCookie(Long userId); +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/CategoryService.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/CategoryService.java new file mode 100644 index 0000000..b959e7c --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/CategoryService.java @@ -0,0 +1,17 @@ +package com.meiruo.cosmetics.service; + +import com.meiruo.cosmetics.entity.Category; +import java.util.List; + +public interface CategoryService { + + Category getById(Long id); + + List getList(Integer status); + + void add(Category category); + + void update(Category category); + + void delete(Long id); +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/OrderService.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/OrderService.java new file mode 100644 index 0000000..dd26395 --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/OrderService.java @@ -0,0 +1,24 @@ +package com.meiruo.cosmetics.service; + +import com.meiruo.cosmetics.entity.Order; +import java.util.List; +import java.util.Map; + +public interface OrderService { + + Order create(Long userId, List cartIds, String receiverName, String receiverPhone, String receiverAddress, String remark); + + Order getById(Long id); + + Order getByOrderNo(String orderNo); + + List getByUserId(Long userId, Integer status); + + List getList(String keyword, Integer status); + + void updateStatus(Long id, Integer status); + + Map getRevenueStatistics(String type); + + List> getTopProducts(Integer limit); +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/ProductService.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/ProductService.java new file mode 100644 index 0000000..2fdf993 --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/ProductService.java @@ -0,0 +1,25 @@ +package com.meiruo.cosmetics.service; + +import com.meiruo.cosmetics.entity.Product; +import java.util.List; + +public interface ProductService { + + Product getById(Long id); + + List getList(Long categoryId, String keyword); + + List getRecommend(); + + List getByIds(List ids); + + void add(Product product); + + void update(Product product); + + void delete(Long id); + + void updateStock(Long id, Integer count); + + void incrementSales(Long id, Integer count); +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/UserService.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/UserService.java new file mode 100644 index 0000000..9af80f6 --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/UserService.java @@ -0,0 +1,23 @@ +package com.meiruo.cosmetics.service; + +import com.meiruo.cosmetics.entity.User; +import java.util.List; + +public interface UserService { + + User login(String username, String password); + + User register(User user); + + User getById(Long id); + + User getByUsername(String username); + + List getList(String query); + + void update(User user); + + void delete(Long id); + + void updateStatus(Long id, Integer status); +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/impl/BannerServiceImpl.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/impl/BannerServiceImpl.java new file mode 100644 index 0000000..c1dd53b --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/impl/BannerServiceImpl.java @@ -0,0 +1,47 @@ +package com.meiruo.cosmetics.service.impl; + +import com.meiruo.cosmetics.entity.Banner; +import com.meiruo.cosmetics.mapper.BannerMapper; +import com.meiruo.cosmetics.service.BannerService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class BannerServiceImpl implements BannerService { + + @Autowired + private BannerMapper bannerMapper; + + @Override + public List getList(Integer status) { + return bannerMapper.selectList(status); + } + + @Override + public Banner getById(Long id) { + return bannerMapper.selectById(id); + } + + @Override + public void add(Banner banner) { + banner.setStatus(1); + bannerMapper.insert(banner); + } + + @Override + public void update(Banner banner) { + bannerMapper.update(banner); + } + + @Override + public void delete(Long id) { + bannerMapper.delete(id); + } + + @Override + public void updateSort(Long id, Integer sort) { + bannerMapper.updateSort(id, sort); + } +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/impl/CartServiceImpl.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/impl/CartServiceImpl.java new file mode 100644 index 0000000..c3b4af1 --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/impl/CartServiceImpl.java @@ -0,0 +1,61 @@ +package com.meiruo.cosmetics.service.impl; + +import com.meiruo.cosmetics.entity.Cart; +import com.meiruo.cosmetics.entity.Product; +import com.meiruo.cosmetics.mapper.CartMapper; +import com.meiruo.cosmetics.mapper.ProductMapper; +import com.meiruo.cosmetics.service.CartService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Map; + +@Service +public class CartServiceImpl implements CartService { + + @Autowired + private CartMapper cartMapper; + @Autowired + private ProductMapper productMapper; + + @Override + public List> getCartList(Long userId) { + return cartMapper.selectByUserId(userId); + } + + @Override + public void add(Long userId, Long productId, Integer quantity) { + Cart existCart = cartMapper.selectByUserAndProduct(userId, productId); + if (existCart != null) { + cartMapper.updateQuantity(existCart.getId(), existCart.getQuantity() + quantity); + } else { + Cart cart = new Cart(); + cart.setUserId(userId); + cart.setProductId(productId); + cart.setQuantity(quantity); + cartMapper.insert(cart); + } + } + + @Override + public void updateQuantity(Long id, Integer quantity) { + cartMapper.updateQuantity(id, quantity); + } + + @Override + public void delete(Long id) { + cartMapper.delete(id); + } + + @Override + public void clear(Long userId) { + cartMapper.deleteByUserId(userId); + } + + @Override + @Transactional + public void mergeFromCookie(Long userId) { + } +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/impl/CategoryServiceImpl.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/impl/CategoryServiceImpl.java new file mode 100644 index 0000000..5913e09 --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/impl/CategoryServiceImpl.java @@ -0,0 +1,42 @@ +package com.meiruo.cosmetics.service.impl; + +import com.meiruo.cosmetics.entity.Category; +import com.meiruo.cosmetics.mapper.CategoryMapper; +import com.meiruo.cosmetics.service.CategoryService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class CategoryServiceImpl implements CategoryService { + + @Autowired + private CategoryMapper categoryMapper; + + @Override + public Category getById(Long id) { + return categoryMapper.selectById(id); + } + + @Override + public List getList(Integer status) { + return categoryMapper.selectList(status); + } + + @Override + public void add(Category category) { + category.setStatus(1); + categoryMapper.insert(category); + } + + @Override + public void update(Category category) { + categoryMapper.update(category); + } + + @Override + public void delete(Long id) { + categoryMapper.delete(id); + } +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/impl/OrderServiceImpl.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/impl/OrderServiceImpl.java new file mode 100644 index 0000000..9e427ba --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/impl/OrderServiceImpl.java @@ -0,0 +1,99 @@ +package com.meiruo.cosmetics.service.impl; + +import com.meiruo.cosmetics.entity.Order; +import com.meiruo.cosmetics.entity.OrderItem; +import com.meiruo.cosmetics.mapper.OrderItemMapper; +import com.meiruo.cosmetics.mapper.OrderMapper; +import com.meiruo.cosmetics.mapper.ProductMapper; +import com.meiruo.cosmetics.service.OrderService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +@Service +public class OrderServiceImpl implements OrderService { + + @Autowired + private OrderMapper orderMapper; + @Autowired + private OrderItemMapper orderItemMapper; + @Autowired + private ProductMapper productMapper; + + @Override + @Transactional + public Order create(Long userId, List cartIds, String receiverName, String receiverPhone, String receiverAddress, String remark) { + Order order = new Order(); + order.setOrderNo(UUID.randomUUID().toString().replace("-", "")); + order.setUserId(userId); + order.setReceiverName(receiverName); + order.setReceiverPhone(receiverPhone); + order.setReceiverAddress(receiverAddress); + order.setRemark(remark); + order.setStatus(1); + + List orderItems = new ArrayList<>(); + BigDecimal totalAmount = BigDecimal.ZERO; + + for (Long cartId : cartIds) { + } + + order.setTotalAmount(totalAmount); + orderMapper.insert(order); + + for (OrderItem item : orderItems) { + item.setOrderId(order.getId()); + orderItemMapper.insert(item); + productMapper.updateStock(item.getProductId(), item.getQuantity()); + productMapper.incrementSales(item.getProductId(), item.getQuantity()); + } + + return order; + } + + @Override + public Order getById(Long id) { + return orderMapper.selectById(id); + } + + @Override + public Order getByOrderNo(String orderNo) { + return orderMapper.selectByOrderNo(orderNo); + } + + @Override + public List getByUserId(Long userId, Integer status) { + return orderMapper.selectByUserId(userId, status); + } + + @Override + public List getList(String keyword, Integer status) { + return orderMapper.selectList(keyword, status); + } + + @Override + public void updateStatus(Long id, Integer status) { + orderMapper.updateStatus(id, status); + } + + @Override + public Map getRevenueStatistics(String type) { + List> statistics = orderMapper.selectRevenueStatistics(type); + BigDecimal total = BigDecimal.ZERO; + for (Map stat : statistics) { + total = total.add(new BigDecimal(stat.get("amount").toString())); + } + return Map.of("list", statistics, "total", total); + } + + @Override + public List> getTopProducts(Integer limit) { + return orderMapper.selectTopProducts(limit); + } +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/impl/ProductServiceImpl.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/impl/ProductServiceImpl.java new file mode 100644 index 0000000..bf85b61 --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/impl/ProductServiceImpl.java @@ -0,0 +1,63 @@ +package com.meiruo.cosmetics.service.impl; + +import com.meiruo.cosmetics.entity.Product; +import com.meiruo.cosmetics.mapper.ProductMapper; +import com.meiruo.cosmetics.service.ProductService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class ProductServiceImpl implements ProductService { + + @Autowired + private ProductMapper productMapper; + + @Override + public Product getById(Long id) { + return productMapper.selectById(id); + } + + @Override + public List getList(Long categoryId, String keyword) { + return productMapper.selectList(categoryId, keyword); + } + + @Override + public List getRecommend() { + return productMapper.selectRecommend(); + } + + @Override + public List getByIds(List ids) { + return productMapper.selectByIds(ids); + } + + @Override + public void add(Product product) { + product.setStatus(1); + product.setSales(0); + productMapper.insert(product); + } + + @Override + public void update(Product product) { + productMapper.update(product); + } + + @Override + public void delete(Long id) { + productMapper.delete(id); + } + + @Override + public void updateStock(Long id, Integer count) { + productMapper.updateStock(id, count); + } + + @Override + public void incrementSales(Long id, Integer count) { + productMapper.incrementSales(id, count); + } +} diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/impl/UserServiceImpl.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..4981a45 --- /dev/null +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/impl/UserServiceImpl.java @@ -0,0 +1,80 @@ +package com.meiruo.cosmetics.service.impl; + +import cn.dev33.satoken.stp.StpUtil; +import cn.dev33.satoken.util.SaResult; +import com.meiruo.cosmetics.entity.User; +import com.meiruo.cosmetics.mapper.UserMapper; +import com.meiruo.cosmetics.service.UserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.DigestUtils; + +import java.nio.charset.StandardCharsets; +import java.util.List; + +@Service +public class UserServiceImpl implements UserService { + + @Autowired + private UserMapper userMapper; + + @Override + public User login(String username, String password) { + User user = userMapper.selectByUsername(username); + if (user == null) { + return null; + } + String md5Password = DigestUtils.md5DigestAsHex(password.getBytes(StandardCharsets.UTF_8)); + if (!md5Password.equals(user.getPassword())) { + return null; + } + if (user.getStatus() != 1) { + return null; + } + StpUtil.login(user.getId()); + return user; + } + + @Override + public User register(User user) { + User existUser = userMapper.selectByUsername(user.getUsername()); + if (existUser != null) { + return null; + } + user.setPassword(DigestUtils.md5DigestAsHex(user.getPassword().getBytes(StandardCharsets.UTF_8))); + user.setRole(0); + user.setStatus(1); + userMapper.insert(user); + return user; + } + + @Override + public User getById(Long id) { + return userMapper.selectById(id); + } + + @Override + public User getByUsername(String username) { + return userMapper.selectByUsername(username); + } + + @Override + public List getList(String query) { + return userMapper.selectList(query); + } + + @Override + public void update(User user) { + userMapper.update(user); + } + + @Override + public void delete(Long id) { + userMapper.delete(id); + } + + @Override + public void updateStatus(Long id, Integer status) { + userMapper.updateStatus(id, status); + } +} diff --git a/meiruo-backend/src/main/resources/application.yml b/meiruo-backend/src/main/resources/application.yml new file mode 100644 index 0000000..952934e --- /dev/null +++ b/meiruo-backend/src/main/resources/application.yml @@ -0,0 +1,31 @@ +server: + port: 8080 + +spring: + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://localhost:3306/meiruo_cosmetics?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true + username: root + password: root + +mybatis: + mapper-locations: classpath:mapper/*.xml + type-aliases-package: com.meiruo.cosmetics.entity + configuration: + map-underscore-to-camel-case: true + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + +sa-token: + token-name: Authorization + header: Authorization + type: jwt + jwt-secret-key: meiruo-cosmetics-secret-key-2024 + token-prefix: Bearer + expiration: 2592000 + is-share: true + is-log: true + +pagehelper: + helper-dialect: mysql + reasonable: true + support-methods-arguments: true diff --git a/meiruo-backend/src/main/resources/mapper/BannerMapper.xml b/meiruo-backend/src/main/resources/mapper/BannerMapper.xml new file mode 100644 index 0000000..05f7985 --- /dev/null +++ b/meiruo-backend/src/main/resources/mapper/BannerMapper.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + SELECT * FROM banner + + AND status = #{status} + + ORDER BY sort ASC, create_time DESC + + + + SELECT * FROM banner WHERE id = #{id} + + + + INSERT INTO banner (title, image, link, sort, status, create_time) + VALUES (#{title}, #{image}, #{link}, #{sort}, #{status}, NOW()) + + + + UPDATE banner + + title = #{title}, + image = #{image}, + link = #{link}, + sort = #{sort}, + status = #{status}, + + WHERE id = #{id} + + + + DELETE FROM banner WHERE id = #{id} + + + + UPDATE banner SET sort = #{sort} WHERE id = #{id} + + + diff --git a/meiruo-backend/src/main/resources/mapper/CartMapper.xml b/meiruo-backend/src/main/resources/mapper/CartMapper.xml new file mode 100644 index 0000000..24338e8 --- /dev/null +++ b/meiruo-backend/src/main/resources/mapper/CartMapper.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + SELECT * FROM cart WHERE user_id = #{userId} AND product_id = #{productId} + + + + SELECT c.id, c.user_id, c.product_id, c.quantity, + p.name as product_name, p.price as product_price, p.image as product_image + FROM cart c + LEFT JOIN product p ON c.product_id = p.id + WHERE c.user_id = #{userId} + + + + INSERT INTO cart (user_id, product_id, quantity, create_time, update_time) + VALUES (#{userId}, #{productId}, #{quantity}, NOW(), NOW()) + + + + UPDATE cart + + quantity = #{quantity}, + update_time = NOW() + + WHERE id = #{id} + + + + DELETE FROM cart WHERE id = #{id} + + + + DELETE FROM cart WHERE user_id = #{userId} + + + + UPDATE cart SET quantity = #{quantity}, update_time = NOW() WHERE id = #{id} + + + diff --git a/meiruo-backend/src/main/resources/mapper/CategoryMapper.xml b/meiruo-backend/src/main/resources/mapper/CategoryMapper.xml new file mode 100644 index 0000000..a331874 --- /dev/null +++ b/meiruo-backend/src/main/resources/mapper/CategoryMapper.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + SELECT * FROM category WHERE id = #{id} + + + + SELECT * FROM category + + AND status = #{status} + + ORDER BY sort ASC, create_time DESC + + + + INSERT INTO category (name, description, sort, status, create_time) + VALUES (#{name}, #{description}, #{sort}, #{status}, NOW()) + + + + UPDATE category + + name = #{name}, + description = #{description}, + sort = #{sort}, + status = #{status}, + + WHERE id = #{id} + + + + DELETE FROM category WHERE id = #{id} + + + diff --git a/meiruo-backend/src/main/resources/mapper/OrderItemMapper.xml b/meiruo-backend/src/main/resources/mapper/OrderItemMapper.xml new file mode 100644 index 0000000..ca7e2d2 --- /dev/null +++ b/meiruo-backend/src/main/resources/mapper/OrderItemMapper.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + SELECT * FROM order_item WHERE order_id = #{orderId} + + + + INSERT INTO order_item (order_id, product_id, product_name, product_image, price, quantity, create_time) + VALUES (#{orderId}, #{productId}, #{productName}, #{productImage}, #{price}, #{quantity}, NOW()) + + + + INSERT INTO order_item (order_id, product_id, product_name, product_image, price, quantity, create_time) + VALUES + + (#{item.orderId}, #{item.productId}, #{item.productName}, #{item.productImage}, #{item.price}, #{item.quantity}, NOW()) + + + + diff --git a/meiruo-backend/src/main/resources/mapper/OrderMapper.xml b/meiruo-backend/src/main/resources/mapper/OrderMapper.xml new file mode 100644 index 0000000..e1c0917 --- /dev/null +++ b/meiruo-backend/src/main/resources/mapper/OrderMapper.xml @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + SELECT * FROM `order` WHERE id = #{id} + + + + SELECT * FROM `order` WHERE order_no = #{orderNo} + + + + SELECT * FROM `order` + + user_id = #{userId} + AND status = #{status} + + ORDER BY create_time DESC + + + + SELECT * FROM `order` + + + AND (order_no LIKE CONCAT('%', #{keyword}, '%') + OR receiver_name LIKE CONCAT('%', #{keyword}, '%')) + + AND status = #{status} + + ORDER BY create_time DESC + + + + INSERT INTO `order` (order_no, user_id, total_amount, status, receiver_name, receiver_phone, receiver_address, remark, create_time) + VALUES (#{orderNo}, #{userId}, #{totalAmount}, #{status}, #{receiverName}, #{receiverPhone}, #{receiverAddress}, #{remark}, NOW()) + + + + UPDATE `order` + + status = #{status}, + receiver_name = #{receiverName}, + receiver_phone = #{receiverPhone}, + receiver_address = #{receiverAddress}, + remark = #{remark}, + pay_time = #{payTime}, + ship_time = #{shipTime}, + receive_time = #{receiveTime}, + + WHERE id = #{id} + + + + UPDATE `order` + + status = #{status} + , pay_time = NOW() + , ship_time = NOW() + , receive_time = NOW() + + WHERE id = #{id} + + + + SELECT + + + DATE(create_time) as date, + + + DATE(create_time) as date, + + + DATE(create_time) as date, + + + SUM(total_amount) as amount, + COUNT(*) as orderCount + FROM `order` + WHERE status IN (2, 3, 4) + + AND create_time >= DATE_SUB(CURDATE(), INTERVAL 7 DAY) + + + AND create_time >= DATE_SUB(CURDATE(), INTERVAL 30 DAY) + + GROUP BY DATE(create_time) + ORDER BY date + + + + SELECT p.id, p.name, p.image, SUM(oi.quantity) as totalSales + FROM order_item oi + LEFT JOIN product p ON oi.product_id = p.id + LEFT JOIN `order` o ON oi.order_id = o.id + WHERE o.status IN (2, 3, 4) + GROUP BY p.id + ORDER BY totalSales DESC + LIMIT #{limit} + + + diff --git a/meiruo-backend/src/main/resources/mapper/ProductMapper.xml b/meiruo-backend/src/main/resources/mapper/ProductMapper.xml new file mode 100644 index 0000000..5836b70 --- /dev/null +++ b/meiruo-backend/src/main/resources/mapper/ProductMapper.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + SELECT * FROM product WHERE id = #{id} + + + + SELECT * FROM product + + AND category_id = #{categoryId} + + AND (name LIKE CONCAT('%', #{keyword}, '%') + OR description LIKE CONCAT('%', #{keyword}, '%')) + + AND status = 1 + + ORDER BY sales DESC, create_time DESC + + + + SELECT * FROM product WHERE status = 1 ORDER BY sales DESC LIMIT 10 + + + + SELECT * FROM product WHERE id IN + + #{id} + + + + + INSERT INTO product (name, description, price, stock, category_id, image, images, status, sales, create_time, update_time) + VALUES (#{name}, #{description}, #{price}, #{stock}, #{categoryId}, #{image}, #{images}, #{status}, 0, NOW(), NOW()) + + + + UPDATE product + + name = #{name}, + description = #{description}, + price = #{price}, + stock = #{stock}, + category_id = #{categoryId}, + image = #{image}, + images = #{images}, + status = #{status}, + update_time = NOW() + + WHERE id = #{id} + + + + DELETE FROM product WHERE id = #{id} + + + + UPDATE product SET stock = stock - #{count} WHERE id = #{id} + + + + UPDATE product SET sales = sales + #{count} WHERE id = #{id} + + + diff --git a/meiruo-backend/src/main/resources/mapper/UserMapper.xml b/meiruo-backend/src/main/resources/mapper/UserMapper.xml new file mode 100644 index 0000000..e4f859a --- /dev/null +++ b/meiruo-backend/src/main/resources/mapper/UserMapper.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + SELECT * FROM user WHERE id = #{id} + + + + SELECT * FROM user WHERE username = #{username} + + + + SELECT * FROM user WHERE phone = #{phone} + + + + SELECT * FROM user + + + AND (username LIKE CONCAT('%', #{query}, '%') + OR nickname LIKE CONCAT('%', #{query}, '%') + OR phone LIKE CONCAT('%', #{query}, '%')) + + + ORDER BY create_time DESC + + + + INSERT INTO user (username, password, nickname, phone, email, avatar, role, status, create_time, update_time) + VALUES (#{username}, #{password}, #{nickname}, #{phone}, #{email}, #{avatar}, #{role}, #{status}, NOW(), NOW()) + + + + UPDATE user + + nickname = #{nickname}, + phone = #{phone}, + email = #{email}, + avatar = #{avatar}, + password = #{password}, + status = #{status}, + update_time = NOW() + + WHERE id = #{id} + + + + DELETE FROM user WHERE id = #{id} + + + + UPDATE user SET status = #{status}, update_time = NOW() WHERE id = #{id} + + + diff --git a/meiruo-frontend/index.html b/meiruo-frontend/index.html new file mode 100644 index 0000000..f458639 --- /dev/null +++ b/meiruo-frontend/index.html @@ -0,0 +1,13 @@ + + + + + + + 美若彩妆销售平台 + + + + + + diff --git a/meiruo-frontend/package.json b/meiruo-frontend/package.json new file mode 100644 index 0000000..ac2a00d --- /dev/null +++ b/meiruo-frontend/package.json @@ -0,0 +1,25 @@ +{ + "name": "meiruo-frontend", + "version": "1.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "vue": "^3.4.0", + "vue-router": "^4.2.5", + "pinia": "^2.1.7", + "axios": "^1.6.2", + "sa-token": "^1.0.0", + "element-plus": "^2.4.4", + "@element-plus/icons-vue": "^2.3.1" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^4.5.2", + "vite": "^5.0.10", + "sass": "^1.69.5" + } +} diff --git a/meiruo-frontend/src/App.vue b/meiruo-frontend/src/App.vue new file mode 100644 index 0000000..e7f4d6e --- /dev/null +++ b/meiruo-frontend/src/App.vue @@ -0,0 +1,12 @@ + + + + + + + diff --git a/meiruo-frontend/src/api/index.js b/meiruo-frontend/src/api/index.js new file mode 100644 index 0000000..486c85f --- /dev/null +++ b/meiruo-frontend/src/api/index.js @@ -0,0 +1,108 @@ +import axios from 'axios' +import router from '../router' +import { useUserStore } from '../stores/user' + +const request = axios.create({ + baseURL: '/api', + timeout: 10000 +}) + +request.interceptors.request.use( + config => { + const token = localStorage.getItem('token') + if (token) { + config.headers.Authorization = `Bearer ${token}` + } + return config + }, + error => { + return Promise.reject(error) + } +) + +request.interceptors.response.use( + response => { + const res = response.data + if (res.code === 200) { + return res + } else { + ElMessage.error(res.msg || '请求失败') + return Promise.reject(res) + } + }, + error => { + if (error.response && error.response.status === 401) { + localStorage.removeItem('token') + localStorage.removeItem('userInfo') + router.push('/login') + } + ElMessage.error(error.response?.data?.msg || '请求失败') + return Promise.reject(error) + } +) + +export default request + +export const userApi = { + login: (data) => request.post('/user/login', data), + register: (data) => request.post('/user/register', data), + getInfo: () => request.get('/user/info'), + updateInfo: (data) => request.put('/user/info', data), + logout: () => request.post('/user/logout'), + getList: (query) => request.get('/user/list', { params: { query } }), + updateStatus: (id, status) => request.put(`/user/status/${id}`, null, { params: { status } }) +} + +export const productApi = { + getList: (params) => request.get('/product/list', { params }), + getRecommend: () => request.get('/product/recommend'), + getById: (id) => request.get(`/product/${id}`), + add: (data) => request.post('/product', data), + update: (data) => request.put('/product', data), + delete: (id) => request.delete(`/product/${id}`) +} + +export const categoryApi = { + getList: (status) => request.get('/category/list', { params: { status } }), + getById: (id) => request.get(`/category/${id}`), + add: (data) => request.post('/category', data), + update: (data) => request.put('/category', data), + delete: (id) => request.delete(`/category/${id}`) +} + +export const cartApi = { + getList: () => request.get('/cart/list'), + add: (productId, quantity) => request.post('/cart/add', null, { params: { productId, quantity } }), + updateQuantity: (id, quantity) => request.put(`/cart/quantity/${id}`, null, { params: { quantity } }), + delete: (id) => request.delete(`/cart/${id}`), + clear: () => request.delete('/cart/clear') +} + +export const orderApi = { + create: (data) => request.post('/order/create', data), + getList: (status) => request.get('/order/list', { params: { status } }), + adminList: (params) => request.get('/order/admin/list', { params }), + getById: (id) => request.get(`/order/${id}`), + updateStatus: (id, status) => request.put(`/order/status/${id}`, null, { params: { status } }), + getRevenue: (type) => request.get(`/order/revenue/${type}`), + getTopProducts: (limit) => request.get(`/order/top/${limit}`) +} + +export const bannerApi = { + getList: (status) => request.get('/banner/list', { params: { status } }), + getById: (id) => request.get(`/banner/${id}`), + add: (data) => request.post('/banner', data), + update: (data) => request.put('/banner', data), + delete: (id) => request.delete(`/banner/${id}`), + updateSort: (id, sort) => request.put(`/banner/sort/${id}`, null, { params: { sort } }) +} + +export const uploadApi = { + uploadImage: (file) => { + const formData = new FormData() + formData.append('file', file) + return request.post('/upload/image', formData, { + headers: { 'Content-Type': 'multipart/form-data' } + }) + } +} diff --git a/meiruo-frontend/src/components/Footer.vue b/meiruo-frontend/src/components/Footer.vue new file mode 100644 index 0000000..7e49285 --- /dev/null +++ b/meiruo-frontend/src/components/Footer.vue @@ -0,0 +1,18 @@ + + + © 2024 美若彩妆销售平台 版权所有 + + + + + + diff --git a/meiruo-frontend/src/components/Header.vue b/meiruo-frontend/src/components/Header.vue new file mode 100644 index 0000000..99bf445 --- /dev/null +++ b/meiruo-frontend/src/components/Header.vue @@ -0,0 +1,160 @@ + + + + + 美若彩妆 + + + 首页 + 商品 + + + + + + + + + + + + + + + {{ userInfo.nickname?.charAt(0) }} + {{ userInfo.nickname || userInfo.username }} + + + + 个人中心 + 我的订单 + 管理后台 + 退出登录 + + + + + + 登录 + 注册 + + + + + + + + + + + + + + diff --git a/meiruo-frontend/src/main.js b/meiruo-frontend/src/main.js new file mode 100644 index 0000000..eec8576 --- /dev/null +++ b/meiruo-frontend/src/main.js @@ -0,0 +1,20 @@ +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import ElementPlus from 'element-plus' +import 'element-plus/dist/index.css' +import * as ElementPlusIconsVue from '@element-plus/icons-vue' +import App from './App.vue' +import router from './router' +import './style.css' + +const app = createApp(App) + +for (const [key, component] of Object.entries(ElementPlusIconsVue)) { + app.component(key, component) +} + +app.use(createPinia()) +app.use(router) +app.use(ElementPlus) + +app.mount('#app') diff --git a/meiruo-frontend/src/router/index.js b/meiruo-frontend/src/router/index.js new file mode 100644 index 0000000..31c286d --- /dev/null +++ b/meiruo-frontend/src/router/index.js @@ -0,0 +1,120 @@ +import { createRouter, createWebHistory } from 'vue-router' +import { useUserStore } from '../stores/user' + +const routes = [ + { + path: '/', + name: 'Home', + component: () => import('../views/user/Home.vue'), + meta: { title: '首页' } + }, + { + path: '/product/:id', + name: 'ProductDetail', + component: () => import('../views/user/ProductDetail.vue'), + meta: { title: '商品详情' } + }, + { + path: '/cart', + name: 'Cart', + component: () => import('../views/user/Cart.vue'), + meta: { title: '购物车', requiresAuth: true } + }, + { + path: '/order', + name: 'Order', + component: () => import('../views/user/Order.vue'), + meta: { title: '我的订单', requiresAuth: true } + }, + { + path: '/checkout', + name: 'Checkout', + component: () => import('../views/user/Checkout.vue'), + meta: { title: '结算', requiresAuth: true } + }, + { + path: '/login', + name: 'Login', + component: () => import('../views/user/Login.vue'), + meta: { title: '登录' } + }, + { + path: '/register', + name: 'Register', + component: () => import('../views/user/Register.vue'), + meta: { title: '注册' } + }, + { + path: '/user', + name: 'UserCenter', + component: () => import('../views/user/UserCenter.vue'), + meta: { title: '个人中心', requiresAuth: true } + }, + { + path: '/admin', + name: 'Admin', + component: () => import('../views/admin/Admin.vue'), + meta: { title: '管理后台', requiresAuth: true, isAdmin: true }, + children: [ + { + path: 'dashboard', + name: 'Dashboard', + component: () => import('../views/admin/Dashboard.vue'), + meta: { title: '数据统计' } + }, + { + path: 'product', + name: 'ProductManage', + component: () => import('../views/admin/ProductManage.vue'), + meta: { title: '商品管理' } + }, + { + path: 'category', + name: 'CategoryManage', + component: () => import('../views/admin/CategoryManage.vue'), + meta: { title: '分类管理' } + }, + { + path: 'order', + name: 'OrderManage', + component: () => import('../views/admin/OrderManage.vue'), + meta: { title: '订单管理' } + }, + { + path: 'banner', + name: 'BannerManage', + component: () => import('../views/admin/BannerManage.vue'), + meta: { title: '轮播图管理' } + }, + { + path: 'user', + name: 'UserManage', + component: () => import('../views/admin/UserManage.vue'), + meta: { title: '用户管理' } + } + ] + } +] + +const router = createRouter({ + history: createWebHistory(), + routes +}) + +router.beforeEach((to, from, next) => { + document.title = to.meta.title || '美若彩妆' + + const userStore = useUserStore() + const isLoggedIn = userStore.isLoggedIn + const isAdmin = userStore.userInfo.role === 1 + + if (to.meta.requiresAuth && !isLoggedIn) { + next({ name: 'Login', query: { redirect: to.fullPath } }) + } else if (to.meta.isAdmin && !isAdmin) { + next({ name: 'Home' }) + } else { + next() + } +}) + +export default router diff --git a/meiruo-frontend/src/stores/user.js b/meiruo-frontend/src/stores/user.js new file mode 100644 index 0000000..b3c0f7d --- /dev/null +++ b/meiruo-frontend/src/stores/user.js @@ -0,0 +1,65 @@ +import { defineStore } from 'pinia' +import { ref, computed } from 'vue' +import { userApi } from '../api' + +export const useUserStore = defineStore('user', () => { + const token = ref(localStorage.getItem('token') || '') + const userInfo = ref(JSON.parse(localStorage.getItem('userInfo') || '{}')) + + const isLoggedIn = computed(() => !!token.value) + const isAdmin = computed(() => userInfo.value.role === 1) + + async function login(username, password) { + const res = await userApi.login({ username, password }) + if (res.code === 200) { + token.value = res.data.token || 'token' + userInfo.value = res.data + localStorage.setItem('token', token.value) + localStorage.setItem('userInfo', JSON.stringify(userInfo.value)) + return true + } + return false + } + + async function register(data) { + const res = await userApi.register(data) + return res.code === 200 + } + + async function logout() { + await userApi.logout() + token.value = '' + userInfo.value = {} + localStorage.removeItem('token') + localStorage.removeItem('userInfo') + } + + async function getInfo() { + try { + const res = await userApi.getInfo() + if (res.code === 200) { + userInfo.value = res.data + localStorage.setItem('userInfo', JSON.stringify(userInfo.value)) + } + } catch (e) { + console.error(e) + } + } + + function updateUserInfo(info) { + userInfo.value = { ...userInfo.value, ...info } + localStorage.setItem('userInfo', JSON.stringify(userInfo.value)) + } + + return { + token, + userInfo, + isLoggedIn, + isAdmin, + login, + register, + logout, + getInfo, + updateUserInfo + } +}) diff --git a/meiruo-frontend/src/style.css b/meiruo-frontend/src/style.css new file mode 100644 index 0000000..03fa004 --- /dev/null +++ b/meiruo-frontend/src/style.css @@ -0,0 +1,37 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', '微软雅黑', Arial, sans-serif; + background-color: #f5f5f5; +} + +a { + text-decoration: none; + color: inherit; +} + +.el-container { + min-height: 100vh; +} + +.el-header { + background-color: #fff; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); + padding: 0 20px; +} + +.el-main { + background-color: #f5f5f5; + padding: 20px; +} + +.el-footer { + background-color: #fff; + text-align: center; + padding: 20px; + color: #999; +} diff --git a/meiruo-frontend/src/views/admin/Admin.vue b/meiruo-frontend/src/views/admin/Admin.vue new file mode 100644 index 0000000..76931ce --- /dev/null +++ b/meiruo-frontend/src/views/admin/Admin.vue @@ -0,0 +1,119 @@ + + + + + 美若彩妆管理后台 + + + + 数据统计 + + + + 商品管理 + + + + 分类管理 + + + + 订单管理 + + + + 轮播图管理 + + + + 用户管理 + + + + 返回前台 + + + + + + + 管理员: {{ userInfo.nickname }} + 退出 + + + + + + + + + + + + + diff --git a/meiruo-frontend/src/views/admin/BannerManage.vue b/meiruo-frontend/src/views/admin/BannerManage.vue new file mode 100644 index 0000000..df78285 --- /dev/null +++ b/meiruo-frontend/src/views/admin/BannerManage.vue @@ -0,0 +1,366 @@ + + + + + + + + 轮播图管理 + + + + 添加轮播图 + + + + + + + + + + + + + + {{ row.title || '暂无标题' }} + + + + + + {{ row.link }} + + 暂无链接 + + + + + {{ row.sort }} + + + + + + {{ row.status === 1 ? '显示' : '隐藏' }} + + + + + + + + 编辑 + + + + 删除 + + + + + + + + + + + + + + + + + 上传图片 + + + 建议尺寸: 1920x450 像素,支持 jpg、png 格式,大小不超过 5MB + + + + + + + 数字越小越靠前 + + + + + + 显示 + + + + 隐藏 + + + + + + 取消 + + + 确定保存 + + + + + + + + + diff --git a/meiruo-frontend/src/views/admin/CategoryManage.vue b/meiruo-frontend/src/views/admin/CategoryManage.vue new file mode 100644 index 0000000..495546a --- /dev/null +++ b/meiruo-frontend/src/views/admin/CategoryManage.vue @@ -0,0 +1,260 @@ + + + + + + + + 分类管理 + + + + 添加分类 + + + + + + + + + + + {{ row.name }} + + + + + + {{ row.description || '暂无描述' }} + + + + + {{ row.sort }} + + + + + + {{ row.status === 1 ? '正常' : '禁用' }} + + + + + + + + 编辑 + + + + 删除 + + + + + + + + + + + + + + + + + 数字越小越靠前 + + + + + + 正常 + + + + 禁用 + + + + + + 取消 + + + 确定保存 + + + + + + + + + diff --git a/meiruo-frontend/src/views/admin/Dashboard.vue b/meiruo-frontend/src/views/admin/Dashboard.vue new file mode 100644 index 0000000..ea0d837 --- /dev/null +++ b/meiruo-frontend/src/views/admin/Dashboard.vue @@ -0,0 +1,129 @@ + + + + + + {{ stat.title }} + {{ stat.value }} + + + + + + + + + + + 本周收入趋势 + + + + + + + + + + + + + + 热销商品排行 + + + + + + + + + + + + + + + + diff --git a/meiruo-frontend/src/views/admin/OrderManage.vue b/meiruo-frontend/src/views/admin/OrderManage.vue new file mode 100644 index 0000000..913bc0d --- /dev/null +++ b/meiruo-frontend/src/views/admin/OrderManage.vue @@ -0,0 +1,119 @@ + + + + + + 订单管理 + + + + + + + + + + + + + + + + + ¥{{ parseFloat(row.total_amount).toFixed(2) }} + + + + + + {{ getStatusText(row.status) }} + + + + + + + 查看 + + 发货 + + + + + + + + + + + diff --git a/meiruo-frontend/src/views/admin/ProductManage.vue b/meiruo-frontend/src/views/admin/ProductManage.vue new file mode 100644 index 0000000..f889ec4 --- /dev/null +++ b/meiruo-frontend/src/views/admin/ProductManage.vue @@ -0,0 +1,442 @@ + + + + + + + + 商品管理 + + + + 添加商品 + + + + + + + + + + {{ row.name }} + {{ row.description }} + + + + + + + {{ getCategoryName(row.categoryId) }} + + + + + ¥{{ row.price.toFixed(2) }} + + + + + {{ row.stock }} + + + + + {{ row.sales }} + + + + + + {{ row.status === 1 ? '上架' : '下架' }} + + + + + + + + 编辑 + + + + 删除 + + + + + + + + + + + + + + + + + + + + + + + 元 + + + + + + 件 + + + + + + + {{ cat.name }} + + + + + + + + + + 上架 + + + + 下架 + + + + + + + + + + + 上传图片 + + + 支持 jpg、png 格式,大小不超过 2MB + + + + + + 取消 + + + 确定保存 + + + + + + + + + diff --git a/meiruo-frontend/src/views/admin/UserManage.vue b/meiruo-frontend/src/views/admin/UserManage.vue new file mode 100644 index 0000000..c797c61 --- /dev/null +++ b/meiruo-frontend/src/views/admin/UserManage.vue @@ -0,0 +1,110 @@ + + + + + + 用户管理 + + + + + + + + + + + + + + + + + + {{ row.role === 1 ? '管理员' : '普通用户' }} + + + + + + + + + + + + 删除 + + + + + + + + + + diff --git a/meiruo-frontend/src/views/user/Cart.vue b/meiruo-frontend/src/views/user/Cart.vue new file mode 100644 index 0000000..7168166 --- /dev/null +++ b/meiruo-frontend/src/views/user/Cart.vue @@ -0,0 +1,152 @@ + + + + + + + + + 购物车 + + + + + + + + + + + ¥{{ parseFloat(row.product_price).toFixed(2) }} + + + + + + + + + + ¥{{ (parseFloat(row.product_price) * row.quantity).toFixed(2) }} + + + + + 删除 + + + + + + + + + + + + + + + + + + diff --git a/meiruo-frontend/src/views/user/Checkout.vue b/meiruo-frontend/src/views/user/Checkout.vue new file mode 100644 index 0000000..5bfcac4 --- /dev/null +++ b/meiruo-frontend/src/views/user/Checkout.vue @@ -0,0 +1,235 @@ + + + + + + + + + 订单结算 + + + 收货信息 + + + + + + + + + + + + + + + + + 订单商品 + + + + + {{ item.product_name }} + ¥{{ parseFloat(item.product_price).toFixed(2) }} x {{ item.quantity }} + + ¥{{ (parseFloat(item.product_price) * item.quantity).toFixed(2) }} + + + + 订单总额: + ¥{{ totalAmount.toFixed(2) }} + + + + + 提交订单 + + + + + + + + + + + + + diff --git a/meiruo-frontend/src/views/user/Home.vue b/meiruo-frontend/src/views/user/Home.vue new file mode 100644 index 0000000..f99f832 --- /dev/null +++ b/meiruo-frontend/src/views/user/Home.vue @@ -0,0 +1,437 @@ + + + + + + + + + + + + + + {{ banner.title }} + + + + + + + + + + + 商品分类 + + + + + + + + 全部 + + + + + + {{ cat.name }} + + + + + + + + + {{ activeCategory ? categories.find(c => c.id === activeCategory)?.name : '全部商品' }} + + 共 {{ productList.length }} 件商品 + + + + + + + 热销 + + + {{ product.name }} + {{ product.description }} + + + ¥ + {{ product.price.toFixed(2) }} + + 已售 {{ product.sales }} + + + + + + + + 查看全部商品 + + + + + + + + + + + + + + diff --git a/meiruo-frontend/src/views/user/Login.vue b/meiruo-frontend/src/views/user/Login.vue new file mode 100644 index 0000000..c2b2e54 --- /dev/null +++ b/meiruo-frontend/src/views/user/Login.vue @@ -0,0 +1,100 @@ + + + + 用户登录 + + + + + + + + + 登录 + + + + + + + + + + diff --git a/meiruo-frontend/src/views/user/Order.vue b/meiruo-frontend/src/views/user/Order.vue new file mode 100644 index 0000000..98e01eb --- /dev/null +++ b/meiruo-frontend/src/views/user/Order.vue @@ -0,0 +1,178 @@ + + + + + + + + + 我的订单 + + + + + + + + + + + 订单号: {{ order.order_no }} + {{ getStatusText(order.status) }} + + + + 收货人: {{ order.receiver_name }} + 联系电话: {{ order.receiver_phone }} + 收货地址: {{ order.receiver_address }} + 下单时间: {{ order.create_time }} + + + 订单总额: + ¥{{ parseFloat(order.total_amount).toFixed(2) }} + + + + + + + + + + + + + + + + + + diff --git a/meiruo-frontend/src/views/user/ProductDetail.vue b/meiruo-frontend/src/views/user/ProductDetail.vue new file mode 100644 index 0000000..6a5df2a --- /dev/null +++ b/meiruo-frontend/src/views/user/ProductDetail.vue @@ -0,0 +1,157 @@ + + + + + + + + + + + + + {{ product.name }} + {{ product.description }} + + ¥{{ product.price.toFixed(2) }} + 库存: {{ product.stock }} + + + 数量: + + + + 加入购物车 + 立即购买 + + + + + + + + + + + + + + + diff --git a/meiruo-frontend/src/views/user/Register.vue b/meiruo-frontend/src/views/user/Register.vue new file mode 100644 index 0000000..75f34ad --- /dev/null +++ b/meiruo-frontend/src/views/user/Register.vue @@ -0,0 +1,127 @@ + + + + 用户注册 + + + + + + + + + + + + + + + + + + 注册 + + + + + + + + + + diff --git a/meiruo-frontend/src/views/user/UserCenter.vue b/meiruo-frontend/src/views/user/UserCenter.vue new file mode 100644 index 0000000..23d6406 --- /dev/null +++ b/meiruo-frontend/src/views/user/UserCenter.vue @@ -0,0 +1,161 @@ + + + + + + + + + + + {{ userInfo.nickname?.charAt(0) || userInfo.username?.charAt(0) }} + {{ userInfo.nickname || userInfo.username }} + + + + + 个人信息 + + + + 我的订单 + + + + + + 个人信息 + + + + + + + + + + + + + + + 保存修改 + + + + + 我的订单 + + + + + + + + + + + + + + + diff --git a/meiruo-frontend/vite.config.js b/meiruo-frontend/vite.config.js new file mode 100644 index 0000000..45f9089 --- /dev/null +++ b/meiruo-frontend/vite.config.js @@ -0,0 +1,21 @@ +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import path from 'path' + +export default defineConfig({ + plugins: [vue()], + resolve: { + alias: { + '@': path.resolve(__dirname, 'src') + } + }, + server: { + port: 3000, + proxy: { + '/api': { + target: 'http://localhost:8080', + changeOrigin: true + } + } + } +}) diff --git a/美若彩妆销售平台功能清单.md b/美若彩妆销售平台功能清单.md new file mode 100644 index 0000000..78429b5 --- /dev/null +++ b/美若彩妆销售平台功能清单.md @@ -0,0 +1,36 @@ +# 美若彩妆销售平台功能清单 + +## 一、顾客端功能 + +| 序号 | 功能模块 | 功能描述 | +|------|----------|----------| +| 1 | 登录注册 | 账号的登录与注册,获得系统使用权限 | +| 2 | 浏览商品 | 查看商品列表,了解商品详情 | +| 3 | 分类查询 | 按商品分类查找特定类型商品 | +| 4 | 购物车管理 | 添加商品、删除商品、修改数量 | +| 5 | 购买商品 | 完成商品选购并进行支付 | +| 6 | 订单管理 | 查看订单状态、历史订单、管理订单 | +| 7 | 个人信息管理 | 修改联系方式、地址等基本信息 | + +--- + +## 二、管理端功能 + +| 序号 | 功能模块 | 功能描述 | +|------|----------|----------| +| 1 | 系统登录 | 管理员登录系统 | +| 2 | 用户信息审核 | 用户信息的增删改查审核 | +| 3 | 商品管理 | 商品增删改查、商品图片上传/展示/删除、商品状态管理 | +| 4 | 订单管理 | 订单查询、创建、删除 | +| 5 | 轮播图管理 | 轮播图增加、修改、删除 | +| 6 | 营收管理 | 收入柱状图、收入饼图、本周/本月收入统计、销售量排行榜 | +| 7 | 个人信息修改 | 修改管理员个人信息 | + +--- + +## 三、技术要求 + +- **前端框架**: Vue.js +- **后端框架**: Spring Boot +- **架构**: 前后端分离 +- **数据库**: MySQL diff --git a/胡宝月-美若彩妆销售平台-开题报告.md b/胡宝月-美若彩妆销售平台-开题报告.md new file mode 100644 index 0000000..690a586 --- /dev/null +++ b/胡宝月-美若彩妆销售平台-开题报告.md @@ -0,0 +1,208 @@ +# 大连科技学院 + +# 毕业设计(论文)开题报告 + +学 院 信息科学与技术学院 + +专业班级 网络工程(专升本)24-1 + +学生姓名 胡宝月 + +学生学号 2406490128 + +指导教师 郭永伟 + +导师职称 副教授 + +# 1 选题的意义和研究现状 + +# 1.1 选题的意义 + +在数字化浪潮席卷全球的当下,线上购物凭借便捷性、多样性等优势,逐渐成为消费者日常消费的主流方式。美妆作为兼具实用性与时尚性的消费品类,其线上市场需求持续攀升,消费者对美妆产品的购买渠道、选择空间及购物体验提出了更高要求。 + +在美妆消费升级与竞争加剧的背景下,传统销售模式正面临多重挑战:线下门店覆盖有限,消费者选择受限;品牌与用户间信息传递不畅,影响购买决策;同时,繁琐的购物流程与滞后的售后服务也持续拉低消费体验。 + +美若彩妆平台的建设,为消费者打造一个突破时空限制、信息透明且流程便捷的美妆购物新体验。其意义不仅在于提升个体消费满意度,更在于推动整个美妆行业拓宽市场、实现数字化转型,从而全面提升运营效率与服务品质。 + +# 1.2 本课题所涉及问题在国内外设计或研究的现状 + +国内美妆电商生态已趋于成熟,天猫、京东等头部平台凭借庞大的用户基础和完善的供应链体系,实现了美妆全品类覆盖,同时具备快速物流配送和基础的商品分类展示功能,满足消费者日常购买需求。不过多数综合电商平台在美妆垂直领域的针对性服务 + +仍有欠缺,用户寻找精准美妆产品的效率有待提升,且对美妆产品的细节展示、使用场景介绍等专项服务不够完善。 + +国外以 Sephora、Ulta Beauty 为代表的美妆网络销售平台,核心优势在于线下门店与线上平台的渠道联动,能为消费者提供线下体验、线上复购的连贯服务,线上平台则侧重美妆产品的系列化展示和基础购买功能。但此类平台在跨区域适配、针对不同地区消费者的基础需求响应等方面存在不足,且部分平台的商品筛选逻辑较为复杂,普通消费者难以快速找到适配自身需求的产品。 + +综合来看,国内外美妆电商的共有特点的是:均以商品展示、在线购买、订单查询为核心基础功能,聚焦满足消费者美妆产品的线上交易需求,但在垂直领域的精准服务、购买流程简化、用户查找效率等方面仍存在改进空间。 + +# 2 课题设计或研究的内容、预期目标和实施计划 + +# 2.1 要设计或研究的主要内容方案论证分析 + +# 2.1.1 需求分析 + +对彩妆平台的消费者、管理人员等进行需求调研,了解管理平台的功能需求和使用习惯,要求本系统有以下功能。 + +# (1)顾客 + +登录注册:顾客可进行账号的登录与注册操作,以获得系统的使用权限。 + +浏览商品:消费者可随意查看商品,了解商品。 + +分类查询商品:可以按照商品的分类来查找特定类型的商品,方便快速定位到所需商品类别。 + +购物车管理:对选中的商品进行添加、删除、修改数量等管理操作,便于后续统一结算。 + +购买商品:完成商品的选购并进行支付,达成交易。 + +订单管理:可查看订单的状态、历史订单等信息,对订单进行相关管理。 + +更改信息:能够修改个人的基本信息,如联系方式、地址等。 + + + + + +图 2.1 顾客功能 + + +# (2)管理员 + +登录:登录系统 + +用户信息审核:负责用户信息的增删改查审核。 + +商品管理:负责对商品进行增删改查等基本操作,包括商品信息的录入、维护和展示, + +商品图片的上传、展示和删除,商品状态的管理等功能 + +订单管理:负责订单相关的基础操作,包括订单的查询、创建、删除等功能。 + +轮播图管理:轮播图的增加,修改,删除等。 + +营收管理:各类收入柱状图,各类收入饼图,本周收入统计,本月收入统计以及销售量排行榜。 + +个人信息修改:修改个人信息。 + + + + + +图2.2管理员功能 + + +# 2.1.2 可行性分析 + +# (1)技术可行性 + +本课题采用成熟的Spring Boot + Vue前后端分离架构,契合电商系统开发的主流技术选型。该架构具备核心优势,可支撑商品、用户、订单等核心业务模块的独立开发与协同运作,技术体系已在各类网络销售平台场景中得到广泛验证,技术路线成熟可靠。同时,依托架构自带的高效接口处理、组件化渲染及缓存机制,能够满足系统响应速度、数据传输效率等性能要求,技术层面无核心障碍。 + +# (2)经济可行性 + +开发阶段无需为核心技术框架支付商业授权费用,有效降低初始投入成本。功能模 + +块按业务逻辑拆分后,可采用迭代开发模式推进,减少重复开发工作,控制开发周期与人力成本。平台上线后,通过线上商品销售、品牌合作等模式可形成明确盈利路径,同时标准化的接口设计与清晰的模块划分,能降低后续功能迭代与Bug修复的维护成本,长期运营的经济成本可控、收益可期。 + +# (3)操作可行性 + +用户端遵循大众普遍的线上购物操作逻辑,简化登录注册流程、优化商品查找与订单管理路径,无需用户额外学习即可上手。管理员端采用清晰的导航栏与内容区布局,核心操作流程直观易懂,经简单培训即可开展日常管理工作。此外,前端技术的响应式特性可适配多种终端设备,进一步提升不同场景下的操作便利性,无论是用户还是管理员都能高效使用系统。 + +综合技术、经济、操作三个维度分析,本课题的技术选型成熟可行,开发与运营的经济成本可控且具备盈利潜力,操作流程符合用户使用习惯,无关键实施障碍。课题的实施不仅能落地实用的网络销售平台功能,还能在技术应用、业务落地等方面形成有价值的实践成果,具备明确的实施意义与可推进性。 + +# 2.2 本课题选题特色及预期的目标 + +本课题选题特色在于聚焦彩妆垂直领域,基于 Spring Boot $^ +$ Vue 技术栈构建前后端分离架构,实现功能模块化设计,同时结合轮播图管理、营收统计等特色功能,兼顾用户购物体验与管理员运营需求,区别于综合网络销售平台的泛化服务。预期目标为完成平台开发,实现商品管理、订单处理等核心功能稳定运行,达成用户便捷购物、管理员高效管理的双向目标,为美妆线上销售提供功能完整、操作友好的垂直解决方案。 + +# 2.3 本课题实施计划 + +周数进度计划第1周确定毕业设计题目,在网络上对“彩妆销售平台”进行调研第2周根据前期的调研情况,查阅相关资料完成开题报告撰写第3周选择与课题相关的外文文献,完成外文翻译。进行前期资料自查,进行系统可行性分析和需求分析第4周完成毕设前期检查。依据系统功能需求和业务流程分析,完成用例图和用例说明第5周进行系统分析,以用例图为基础进行类图、活动图和顺序图的绘制,确保系统的一致性和可维护性第6周完成数据库设计、界面设计,根据反馈意见进行修改第7周系统实现,按功能模块进行编码第8周完成毕设中期检查。系统实现,按功能模块进行编码第9周系统测试,测试本系统各业务功能运行是否正常,验证功能需求是否都符合规范要求。完成论文主体部分第10周按照系统测试结果修改代码完善功能,并完成论文剩余相关部分内容编写第11周提交论文初稿,根据反馈意见修改论文第12周继续修改论文,完成论文查重稿定稿。检查系统功能,为软件验收做好准备第13周进行软件验收,参加校级论文查重,根据论文内容制作答辩PPT第14周进行毕业设计答辩,并按照答辩组意见修改论文定稿,完成毕设资料存档 + +# 3 主要参考文献 + + + +[1] 吴怡婷,高斐,张华辉.应用型本科下新工 Java 课程的师生互动与协同学习研究[J].办公自动化,2025,30(07):42-44+48. + + + + + +[2] 张倬维,王晗霖,张韬祥,等.基于SSM框架的高速公路实验室管理系统设计[J].中国交通信息化,2025,(S1):355-357. + + + + + +[3] 黄婧.“互联网+”背景下Java程序设计课程教学改革策略[J].信息与电脑,2025,37(05):233-235. + + + + + +[4] 王培培.基于SpringBoot的网上商城管理系统设计与实现[J].现代计算机,2024,30(07):117-120. + + + + + +[5] 付世军,卢淞岩,李梦,等.基于B/S架构的智慧农业管理系统的设计与实现[J].湖北农业科学,2025,64(01):154-161. + + + + + +[6] 向育程,段元梅.基于 Java 的网上商城系统[J].电脑编程技巧与维护,2024,(08):32-34. + + + + + +[7] Balasubramanian A ,Elangeswaran J V S . A novel power aware smart agriculture management system based on RNN-LSTM[J].Electrical Engineering,2024,107(2):1-22. + + + + + +[8] 徐家喜,王小正,朱杰.Java EE 框架技术与案例教程[M].南京大学出版社:202310:312. + + + + + +[9] 任建新,王一鸣,李鑫,等.基于Java Web的智慧商城购物系统设计[J].信息技术与信息化,2022,(07):23-27. + + + + + +[10]杨晟,罗奇.基于 Spring Boot 的在线商城系统设计[J].科技创新与应用,2022,12(19):58-61. + + + + + +[11]李宜镓.基于 SpringBoot 的电商秒杀系统的设计与实现[D].西安电子科技大学,2022. + + + + + +[12]吕善雨.多元化信息融合的电商推荐系统设计与实现[D].北京邮电大学,2022. + + + + + +[13]张曰花.基于JavaWeb的山东地方特色产品销售网站设计[J].现代信息科技,2025,9(04): 118-123. + + + + + +[14]凌洋.基于JavaWeb技术的医院人事管理系统的设计与实现[J].现代计算机,2024,30(19):117-120. + + + + + +[15]柳小刚.基于 B/S 架构的档案管理系统的设计与实现[J].电子技术,2024,53(08):332-333. +
© 2024 美若彩妆销售平台 版权所有
¥{{ parseFloat(item.product_price).toFixed(2) }} x {{ item.quantity }}
{{ product.description }}
收货人: {{ order.receiver_name }}
联系电话: {{ order.receiver_phone }}
收货地址: {{ order.receiver_address }}
下单时间: {{ order.create_time }}
{{ userInfo.nickname || userInfo.username }}