diff --git a/api-interface/itmk-base-parent/itmk-base-common/pom.xml b/api-interface/itmk-base-parent/itmk-base-common/pom.xml index 24b404f..49031ba 100644 --- a/api-interface/itmk-base-parent/itmk-base-common/pom.xml +++ b/api-interface/itmk-base-parent/itmk-base-common/pom.xml @@ -53,6 +53,10 @@ org.apache.httpcomponents httpclient + + org.springframework + spring-core + diff --git a/api-interface/itmk-base-parent/itmk-base-common/src/main/java/com/itmk/utils/JwtUtils.java b/api-interface/itmk-base-parent/itmk-base-common/src/main/java/com/itmk/utils/JwtUtils.java new file mode 100644 index 0000000..82c4ea7 --- /dev/null +++ b/api-interface/itmk-base-parent/itmk-base-common/src/main/java/com/itmk/utils/JwtUtils.java @@ -0,0 +1,48 @@ +package com.itmk.utils; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.security.Keys; +import org.springframework.util.StringUtils; + +import javax.crypto.SecretKey; +import java.util.Date; + +public class JwtUtils { + + // 使用 Keys.secretKeyFor 生成足够强的密钥(512位) + private static final SecretKey SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS512); + private static final long EXPIRATION_TIME = 86400000; // 24小时 + + public static String generateToken(String username) { + return Jwts.builder() + .setSubject(username) + .setIssuedAt(new Date()) + .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) + .signWith(SECRET_KEY, SignatureAlgorithm.HS512) + .compact(); + } + + public static Claims getClaimsByToken(String token) { + if (StringUtils.isEmpty(token)) { + return null; + } + + try { + return Jwts.parserBuilder() + .setSigningKey(SECRET_KEY) + .build() + .parseClaimsJws(token) + .getBody(); + } catch (Exception e) { + System.out.println("validate is token error, token: " + token + ", error: " + e); + return null; + } + } + + public static String getSubject(String token) { + Claims claims = getClaimsByToken(token); + return claims != null ? claims.getSubject() : null; + } +} \ No newline at end of file diff --git a/api-interface/itmk-base-parent/itmk-base-web/src/main/java/com/itmk/web/order/controller/UserOrderController.java b/api-interface/itmk-base-parent/itmk-base-web/src/main/java/com/itmk/web/order/controller/UserOrderController.java index 36aabdc..f851a88 100644 --- a/api-interface/itmk-base-parent/itmk-base-web/src/main/java/com/itmk/web/order/controller/UserOrderController.java +++ b/api-interface/itmk-base-parent/itmk-base-web/src/main/java/com/itmk/web/order/controller/UserOrderController.java @@ -7,6 +7,8 @@ import com.itmk.utils.ResultUtils; import com.itmk.utils.ResultVo; import com.itmk.web.order.entity.*; import com.itmk.web.order.service.UserOrderService; +import com.itmk.web.order_detail.entity.UserOrderDetail; +import com.itmk.web.order_detail.service.UserOrderDetailService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @@ -18,98 +20,127 @@ public class UserOrderController { @Autowired private UserOrderService userOrderService; - //下的 + @Autowired + private UserOrderDetailService userOrderDetailService; + + //下单 @PostMapping("/splaceOrder") - public ResultVo splaceOrder(@RequestBody OrderParm parm){ + public ResultVo splaceOrder(@RequestBody OrderParm parm) { userOrderService.splaceOrder(parm); return ResultUtils.success("提交成功!"); } //查询订单 @GetMapping("/getOrderList") - public ResultVo getOrderList(WxOrderParm parm){ + public ResultVo getOrderList(WxOrderParm parm) { IPage orderList = userOrderService.getOrderList(parm); - return ResultUtils.success("查询成功!",orderList); + return ResultUtils.success("查询成功!", orderList); } //查询pc订单 @GetMapping("/getPcOrderList") - public ResultVo getPcOrderList(WxOrderParm parm){ + public ResultVo getPcOrderList(WxOrderParm parm) { IPage orderList = userOrderService.getPcOrderList(parm); - return ResultUtils.success("查询成功!",orderList); + return ResultUtils.success("查询成功!", orderList); } //发货 @PutMapping("/sendOrder") - public ResultVo sendOrder(@RequestBody SendParm parm){ + public ResultVo sendOrder(@RequestBody SendParm parm) { //判断订单是否被取消 QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.lambda().eq(UserOrder::getOrderId,parm.getOrderId()).eq(UserOrder::getStatus,"3"); + queryWrapper.lambda().eq(UserOrder::getOrderId, parm.getOrderId()).eq(UserOrder::getStatus, "3"); UserOrder one = userOrderService.getOne(queryWrapper); - if(one != null){ + if (one != null) { return ResultUtils.error("订单已被取消,不能发货!"); } //更新条件 LambdaUpdateWrapper query = new LambdaUpdateWrapper<>(); - query.eq(UserOrder::getOrderId,parm.getOrderId()) - .set(UserOrder::getStatus,"1"); - if(userOrderService.update(query)){ + query.eq(UserOrder::getOrderId, parm.getOrderId()) + .set(UserOrder::getStatus, "1"); + if (userOrderService.update(query)) { return ResultUtils.success("更新成功!"); } return ResultUtils.error("更新失败!"); } + //取消订单 @PostMapping("/cancelOrder") - public ResultVo cancelOrder(@RequestBody SendParm parm){ + public ResultVo cancelOrder(@RequestBody SendParm parm) { //如果已发货,不能取消 QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.lambda().eq(UserOrder::getOrderId,parm.getOrderId()).eq(UserOrder::getStatus,"1"); + queryWrapper.lambda().eq(UserOrder::getOrderId, parm.getOrderId()).eq(UserOrder::getStatus, "1"); UserOrder one = userOrderService.getOne(queryWrapper); - if(one != null){ + if (one != null) { return ResultUtils.error("订单已发货,不能取消!"); } //更新条件 LambdaUpdateWrapper query = new LambdaUpdateWrapper<>(); - query.eq(UserOrder::getOrderId,parm.getOrderId()) - .set(UserOrder::getStatus,"3"); - if(userOrderService.update(query)){ + query.eq(UserOrder::getOrderId, parm.getOrderId()) + .set(UserOrder::getStatus, "3"); + if (userOrderService.update(query)) { return ResultUtils.success("取消成功!"); } return ResultUtils.error("取消失败!"); } + //确定收货 @PostMapping("/confirmOrder") - public ResultVo confirmOrder(@RequestBody SendParm parm){ + public ResultVo confirmOrder(@RequestBody SendParm parm) { //更新条件 LambdaUpdateWrapper query = new LambdaUpdateWrapper<>(); - query.eq(UserOrder::getOrderId,parm.getOrderId()) - .set(UserOrder::getStatus,"2"); - if(userOrderService.update(query)){ + query.eq(UserOrder::getOrderId, parm.getOrderId()) + .set(UserOrder::getStatus, "2"); + if (userOrderService.update(query)) { return ResultUtils.success("收货成功!"); } return ResultUtils.error("收货失败!"); } + + // 在 UserOrderController 中添加删除订单接口 + @DeleteMapping("/{orderId}") + public ResultVo deleteOrder(@PathVariable Long orderId) { + // 先删除订单详情 + QueryWrapper detailQuery = new QueryWrapper<>(); + detailQuery.lambda().eq(UserOrderDetail::getOrderId, orderId); + userOrderDetailService.remove(detailQuery); + + // 再删除订单 + if (userOrderService.removeById(orderId)) { + return ResultUtils.success("删除成功!"); + } + return ResultUtils.error("删除失败!"); + } + //首页统计 0:日 1:月 2:年 @GetMapping("/getTotal") - public ResultVo getTotal(String type){ - List list = null; - switch (type){ - case "1": - list = userOrderService.getMonths(); - break; - case "2": - list = userOrderService.getYears(); - break; - default: - list = userOrderService.getDays(); - } - Echarts echarts = new Echarts(); - if(list!= null && list.size() >0){ - for (int i=0;i list = null; + switch (type) { + case "1": + list = userOrderService.getMonths(); + break; + case "2": + list = userOrderService.getYears(); + break; + default: + list = userOrderService.getDays(); + } + Echarts echarts = new Echarts(); + if (list != null && list.size() > 0) { + for (SunList sun : list) { + // 添加空值检查 + if (sun.getDays() != null && sun.getPrice() != null) { + echarts.getNames().add(sun.getDays()); + echarts.getValues().add(sun.getPrice()); + } + } } + return ResultUtils.success("查询成功", echarts); + } catch (Exception e) { + e.printStackTrace(); + return ResultUtils.error("统计查询失败: " + e.getMessage()); } - return ResultUtils.success("查询成功",echarts); } } diff --git a/api-interface/itmk-base-parent/itmk-base-web/src/main/java/com/itmk/web/user/controller/SysUserController.java b/api-interface/itmk-base-parent/itmk-base-web/src/main/java/com/itmk/web/user/controller/SysUserController.java index 919c396..9204e99 100644 --- a/api-interface/itmk-base-parent/itmk-base-web/src/main/java/com/itmk/web/user/controller/SysUserController.java +++ b/api-interface/itmk-base-parent/itmk-base-web/src/main/java/com/itmk/web/user/controller/SysUserController.java @@ -5,22 +5,27 @@ import com.alibaba.druid.util.StringUtils; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.itmk.utils.JwtUtils; import com.itmk.utils.ResultUtils; import com.itmk.utils.ResultVo; import com.itmk.web.user.entity.SysUser; import com.itmk.web.user.entity.UserPageParm; import com.itmk.web.user.service.SysUserService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.DigestUtils; import org.springframework.web.bind.annotation.*; +import java.util.HashMap; +import java.util.Map; + @RestController @RequestMapping("/api/user")//所有含有/api/user的请求都交给这个控制器处理 public class SysUserController { -// 注入服务类 + // 注入服务类 @Autowired private SysUserService sysUserService; -// 新增用户 + // 新增用户 @PostMapping//使用post请求 public ResultVo addUser(@RequestBody SysUser sysUser) { // 1. 单独检查用户名 @@ -43,41 +48,110 @@ public class SysUserController { : ResultUtils.error("新增用户失败!"); } -// 编辑用户 + // 编辑用户 @PutMapping - public ResultVo editUser(@RequestBody SysUser sysUser){ - if(sysUserService.updateById(sysUser)){ + public ResultVo editUser(@RequestBody SysUser sysUser) { + if (sysUserService.updateById(sysUser)) { return ResultUtils.success("编辑用户成功!", sysUser); } return ResultUtils.error("编辑用户失败!"); } -// 删除用户 + // 删除用户 @DeleteMapping("/{userId}")//delete请求时需要指定参数,传递参数用户id // 接收参数 - public ResultVo deleteUser(@PathVariable Long userId){ - if(sysUserService.removeById(userId)){ + public ResultVo deleteUser(@PathVariable Long userId) { + if (sysUserService.removeById(userId)) { return ResultUtils.success("删除用户成功!"); } return ResultUtils.error("删除用户失败!"); } -// 列表查询 + // 列表查询 // 列表查询需要分页 @GetMapping("/list") - public ResultVo getList(UserPageParm parm){ + public ResultVo getList(UserPageParm parm) { // 构造分页对象 - IPage page = new Page<>(parm.getCurrentPage(),parm.getPageSize()); + IPage page = new Page<>(parm.getCurrentPage(), parm.getPageSize()); // 构造查询条件 QueryWrapper queryWrapper = new QueryWrapper<>(); // 当parm.getName()或parm.getPhone()不为空时,设置查询条件,根据姓名和手机号模糊查询 - queryWrapper.lambda().like(!StringUtils.isEmpty(parm.getName()),SysUser::getName,parm.getName()) - .like(!StringUtils.isEmpty(parm.getPhone()),SysUser::getPhone,parm.getPhone()) + queryWrapper.lambda().like(!StringUtils.isEmpty(parm.getName()), SysUser::getName, parm.getName()) + .like(!StringUtils.isEmpty(parm.getPhone()), SysUser::getPhone, parm.getPhone()) // 根据姓名升序排序 .orderByAsc(SysUser::getName); - IPage list = sysUserService.page(page,queryWrapper); + IPage list = sysUserService.page(page, queryWrapper); + + return ResultUtils.success("查询成功!", list); + + } - return ResultUtils.success("查询成功!",list); + // 用户注册接口 + @PostMapping("/register") + public ResultVo register(@RequestBody SysUser sysUser) { + // 检查用户名是否已存在 + if (sysUserService.lambdaQuery() + .eq(SysUser::getUsername, sysUser.getUsername()) + .exists()) { + return ResultUtils.error("用户名已存在!"); + } + // 检查手机号是否已存在 + if (sysUserService.lambdaQuery() + .eq(SysUser::getPhone, sysUser.getPhone()) + .exists()) { + return ResultUtils.error("手机号已被使用!"); + } + + // 对密码进行MD5加密 + String md5Password = DigestUtils.md5DigestAsHex(sysUser.getPassword().getBytes()); + sysUser.setPassword(md5Password); + + // 保存用户 + if (sysUserService.save(sysUser)) { + return ResultUtils.success("注册成功!"); + } + return ResultUtils.error("注册失败!"); + } + + // 用户登录接口 + @PostMapping("/login") + public ResultVo login(@RequestBody SysUser sysUser) { + // 对密码进行MD5加密 + String md5Password = DigestUtils.md5DigestAsHex(sysUser.getPassword().getBytes()); + + // 查询用户 + QueryWrapper query = new QueryWrapper<>(); + query.lambda().eq(SysUser::getUsername, sysUser.getUsername()) + .eq(SysUser::getPassword, md5Password); + + SysUser user = sysUserService.getOne(query); + if (user != null) { + // 生成token + String token = JwtUtils.generateToken(user.getUsername()); + + // 返回用户信息和token + Map result = new HashMap<>(); + result.put("user", user); + result.put("token", token); + + return ResultUtils.success("登录成功!", result); + } + return ResultUtils.error("用户名或密码错误!"); + } + + // 根据token获取用户信息 + @GetMapping("/getUserInfo") + public ResultVo getUserInfo(@RequestHeader("token") String token) { + String username = JwtUtils.getClaimsByToken(token).getSubject(); + SysUser user = sysUserService.lambdaQuery() + .eq(SysUser::getUsername, username) + .one(); + if (user != null) { + // 不返回密码 + user.setPassword(null); + return ResultUtils.success("查询成功", user); + } + return ResultUtils.error("用户不存在"); } } diff --git a/api-interface/itmk-base-parent/itmk-base-web/src/main/java/com/itmk/web/wx_user/controller/WxUserController.java b/api-interface/itmk-base-parent/itmk-base-web/src/main/java/com/itmk/web/wx_user/controller/WxUserController.java index 9f0b1c6..54e6098 100644 --- a/api-interface/itmk-base-parent/itmk-base-web/src/main/java/com/itmk/web/wx_user/controller/WxUserController.java +++ b/api-interface/itmk-base-parent/itmk-base-web/src/main/java/com/itmk/web/wx_user/controller/WxUserController.java @@ -15,14 +15,19 @@ public class WxUserController { @PostMapping("/saveOrUpdate") public ResultVo saveOrUpdate(@RequestBody WxUser wxUser){ - wxUserService.saveOrUpdate(wxUser); - return ResultUtils.success("更新成功!"); + // 使用 MyBatis Plus 自带的 saveOrUpdate 方法 + boolean result = wxUserService.saveOrUpdate(wxUser); + if(result) { + return ResultUtils.success("更新成功!"); + } else { + return ResultUtils.error("更新失败!"); + } } //查询头像昵称 @GetMapping("/getUserInfo") public ResultVo getUserInfo(String openid) { WxUser user = wxUserService.getById(openid); - return ResultUtils.error("查询成功!",user); + return ResultUtils.success("查询成功!",user); } } diff --git a/api-interface/itmk-base-parent/itmk-base-web/src/main/resources/mapper/UserOrderMapper.xml b/api-interface/itmk-base-parent/itmk-base-web/src/main/resources/mapper/UserOrderMapper.xml index 368f843..415c596 100644 --- a/api-interface/itmk-base-parent/itmk-base-web/src/main/resources/mapper/UserOrderMapper.xml +++ b/api-interface/itmk-base-parent/itmk-base-web/src/main/resources/mapper/UserOrderMapper.xml @@ -4,12 +4,25 @@ + select DATE_FORMAT(create_time, '%Y-%m') days, sum(price) price + from `user_order` + where `status` = '2' + group by days + order by days asc + + \ No newline at end of file diff --git a/api-interface/itmk-base-parent/itmk-base-web/src/main/resources/mapper/WxUserMapper.xml b/api-interface/itmk-base-parent/itmk-base-web/src/main/resources/mapper/WxUserMapper.xml new file mode 100644 index 0000000..0839015 --- /dev/null +++ b/api-interface/itmk-base-parent/itmk-base-web/src/main/resources/mapper/WxUserMapper.xml @@ -0,0 +1,41 @@ + + + + + insert into wx_user + + + openid, + + + nick_name, + + + avatar_url, + + + + + #{user.openid}, + + + #{user.nickName}, + + + #{user.avatarUrl}, + + + on duplicate key update + + + nick_name = #{user.nickName}, + + + avatar_url = #{user.avatarUrl}, + + + + + \ No newline at end of file diff --git a/order-app/src/pages/car/car.vue b/order-app/src/pages/car/car.vue index c5b828e..ca49e6e 100644 --- a/order-app/src/pages/car/car.vue +++ b/order-app/src/pages/car/car.vue @@ -50,6 +50,9 @@ import { carStore } from '../../store/car.js' + import { + orderStore + } from '../../store/order.js' //获取store const store = carStore(); const show = ref(true); @@ -140,6 +143,22 @@ }) //跳转确认订单 const confirm = (item) => { + // 获取选中的商品 + const selectedGoods = store.carList.filter(item => item.flag); + + // 如果没有选中商品,提示用户 + if (selectedGoods.length === 0) { + uni.showToast({ + title: '请选择商品', + icon: 'none' + }); + return; + } + + // 将选中的商品设置到 orderStore 中 + const ostore = orderStore(); + ostore.addOrderList(selectedGoods); + uni.navigateTo({ url: '../confirm/confirm' }); diff --git a/order-app/src/pages/collect/collect.vue b/order-app/src/pages/collect/collect.vue index f500084..93163f4 100644 --- a/order-app/src/pages/collect/collect.vue +++ b/order-app/src/pages/collect/collect.vue @@ -91,6 +91,19 @@ margin: 5px 10px 5px 0px; } + .collect-container { + height: 100vh; + background-color: #f8f8f8; + + .scroll-view { + height: 100%; + + .empty-tip { + padding-top: 200rpx; + } + } + } + .item { padding: 40rpx 20rpx; display: flex; diff --git a/order-app/src/pages/detail/detail.vue b/order-app/src/pages/detail/detail.vue index 325a9b0..d9cd387 100644 --- a/order-app/src/pages/detail/detail.vue +++ b/order-app/src/pages/detail/detail.vue @@ -273,7 +273,25 @@ onLoad((options) => { userLogin() - const goods = JSON.parse(options.goods) + // 解码参数 + let goodsParam = options.goods; + try { + // 先尝试直接解析(处理来自index.vue的参数) + goodsParam = JSON.parse(goodsParam); + } catch (e) { + // 如果直接解析失败,尝试先解码再解析(处理来自category.vue的参数) + try { + goodsParam = JSON.parse(decodeURIComponent(goodsParam)); + } catch (e2) { + uni.showToast({ + title: '参数错误', + icon: 'none' + }); + return; + } + } + + const goods = goodsParam; swipperList.value = goods.goodsImage.split(',') console.log(goods) goodsUnit.value = goods.goodsUnit diff --git a/order-app/src/pages/mine/mine.vue b/order-app/src/pages/mine/mine.vue index 99bb05c..12cee23 100644 --- a/order-app/src/pages/mine/mine.vue +++ b/order-app/src/pages/mine/mine.vue @@ -18,7 +18,7 @@ - + @@ -102,7 +102,7 @@ } const onNickName = (e) => { console.log(e) - uni.createSelectorQuery().in(instance) // 注意这里要加上 in(this) + uni.createSelectorQuery().in(instance) .select("#nickname-input") .fields({ properties: ["value"], @@ -233,6 +233,14 @@ url: '../order/order' }); } + + //跳转收藏 + const toCollect = () => { + uni.navigateTo({ + url: '../collect/collect' + }); + } + onShow(() => { userLogin() // getUserInfo() diff --git a/order-system/src/api/order/index.ts b/order-system/src/api/order/index.ts index 0765208..57b3159 100644 --- a/order-system/src/api/order/index.ts +++ b/order-system/src/api/order/index.ts @@ -10,6 +10,11 @@ export const sendOrderApi = (orderId: string) => { return http.put("/wxapi/order/sendOrder", { orderId: orderId }) } +// 删除订单 +export const deleteOrderApi = (orderId: string) => { + return http.delete(`/wxapi/order/${orderId}`); +}; + //统计 export const getTotalApi = (type:string)=>{ return http.get("/wxapi/order/getTotal",{type:type}) diff --git a/order-system/src/api/user/index.ts b/order-system/src/api/user/index.ts index 22328b7..9fef1a6 100644 --- a/order-system/src/api/user/index.ts +++ b/order-system/src/api/user/index.ts @@ -1,5 +1,5 @@ import http from "../../http"; -import type { ListUserParm, UserModel } from "./userModel"; +import type { ListUserParm, UserModel, RegisterModel } from "./userModel"; // 新增接口 export const addUserApi = (parm:UserModel)=>{ @@ -19,4 +19,19 @@ export const editUserApi = (parm:UserModel)=>{ // 删除接口 export const deleteUserApi = (userId:string)=>{ return http.delete(`/api/user/${userId}`) +} + +// 用户登录 +export const loginApi = (parm: { username: string; password: string }) => { + return http.post('/api/user/login', parm) +} + +// 用户注册 +export const registerApi = (parm: RegisterModel) => { + return http.post('/api/user/register', parm) +} + +// 获取用户信息 +export const getUserInfoApi = () => { + return http.get('/api/user/getUserInfo') } \ No newline at end of file diff --git a/order-system/src/api/user/userModel.ts b/order-system/src/api/user/userModel.ts index 25a025f..95a5f35 100644 --- a/order-system/src/api/user/userModel.ts +++ b/order-system/src/api/user/userModel.ts @@ -17,4 +17,15 @@ export type UserModel = { email: string; sex: string; name: string; +} + +// 注册表单类型 +export type RegisterModel = { + username: string; + password: string; + phone: string; + email: string; + sex: string; + name: string; + confirmPassword?: string; } \ No newline at end of file diff --git a/order-system/src/compositions/order/useOrderTable.ts b/order-system/src/compositions/order/useOrderTable.ts index f2558bd..eae2e98 100644 --- a/order-system/src/compositions/order/useOrderTable.ts +++ b/order-system/src/compositions/order/useOrderTable.ts @@ -1,6 +1,6 @@ import type { OrderListParm } from '../../api/order/OrderModel' import { nextTick, onMounted, reactive, ref } from 'vue' -import { gePcOrdertListApi, sendOrderApi } from '../../api/order' +import { gePcOrdertListApi, sendOrderApi, deleteOrderApi } from '../../api/order' // 导入 deleteOrderApi import useInstance from '@/hooks/useInstance' export default function useOrderTable() { const { global } = useInstance() @@ -34,6 +34,7 @@ export default function useOrderTable() { const resetBtn = () => { listParm.currentPage = 1; listParm.type = '' + listParm.userName = '' // 重置搜索条件 getList() } //页容量改变触发 @@ -52,7 +53,29 @@ export default function useOrderTable() { if (confirm) { let res = await sendOrderApi(orderId) if (res && res.code == 200) { + global.$message({ type: 'success', message: '发货成功!' }) getList() + } else { + global.$message({ type: 'error', message: res?.msg || '发货失败!' }) + } + } + } + + // 删除订单 + const deleteOrder = async (orderId: string) => { + let confirm = await global.$myconfirm('确定删除该订单吗?此操作不可恢复。') + if (confirm) { + try { + let res = await deleteOrderApi(orderId) + if (res && res.code == 200) { + global.$message({ type: 'success', message: '删除成功!' }) + getList() + } else { + global.$message({ type: 'error', message: res?.msg || '删除失败!' }) + } + } catch (error) { + console.error('删除订单失败:', error) + global.$message({ type: 'error', message: '删除失败!' }) } } } @@ -66,6 +89,7 @@ export default function useOrderTable() { return { tableList, sendOrder, + deleteOrder, // 返回删除订单方法 listParm, getList, searchBtn, diff --git a/order-system/src/http/index.ts b/order-system/src/http/index.ts index d3a98da..c4bfa93 100644 --- a/order-system/src/http/index.ts +++ b/order-system/src/http/index.ts @@ -33,10 +33,10 @@ class Http { private interceptors() { // 请求发送之前的拦截器,通常用来配置、携带token this.instance.interceptors.request.use((config: InternalAxiosRequestConfig) => { - // 设置token到请求头部 - let token = ""; + // 从localStorage获取token + const token = localStorage.getItem('token'); if (token) { - config.headers!['token'] = token; + config.headers!['Authorization'] = `Bearer ${token}`; } return config; }, (error: any) => { @@ -59,58 +59,64 @@ class Http { console.log('进入错误') error.data = {} if (error && error.response) { - switch (error.response.status) { - case 400: - error.data.msg = '错误请求' - ElMessage.error(error.data.msg) - break - case 401: - error.data.msg = '未授权,请重新登录' - ElMessage.error(error.data.msg) - break - case 403: - error.data.msg = '拒绝访问' - ElMessage.error(error.data.msg) - break - case 404: - error.data.msg = '请求错误,未找到该资源' - ElMessage.error(error.data.msg) - break - case 405: - error.data.msg = '请求方法未允许' - ElMessage.error(error.data.msg) - break - case 408: - error.data.msg = '请求超时' - ElMessage.error(error.data.msg) - break - case 500: - error.data.msg = '服务器端出错' - ElMessage.error(error.data.msg) - break - case 501: - error.data.msg = '网络未实现' - ElMessage.error(error.data.msg) - break - case 502: - error.data.msg = '网络错误' - ElMessage.error(error.data.msg) - break - case 503: - error.data.msg = '服务不可用' - ElMessage.error(error.data.msg) - break - case 504: - error.data.msg = '网络超时' - ElMessage.error(error.data.msg) - break - case 505: - error.data.msg = 'http版本不支持该请求' - ElMessage.error(error.data.msg) - break - default: - error.data.msg = `连接错误${error.response.status}` - ElMessage.error(error.data.msg) + if (error.response.status === 401) { + error.data.msg = '未授权,请重新登录' + ElMessage.error(error.data.msg) + // 清除本地存储的token和用户信息 + localStorage.removeItem('token') + localStorage.removeItem('user') + // 跳转到登录页 + window.location.href = '/login' + } else { + switch (error.response.status) { + case 400: + error.data.msg = '错误请求' + ElMessage.error(error.data.msg) + break + case 403: + error.data.msg = '拒绝访问' + ElMessage.error(error.data.msg) + break + case 404: + error.data.msg = '请求错误,未找到该资源' + ElMessage.error(error.data.msg) + break + case 405: + error.data.msg = '请求方法未允许' + ElMessage.error(error.data.msg) + break + case 408: + error.data.msg = '请求超时' + ElMessage.error(error.data.msg) + break + case 500: + error.data.msg = '服务器端出错' + ElMessage.error(error.data.msg) + break + case 501: + error.data.msg = '网络未实现' + ElMessage.error(error.data.msg) + break + case 502: + error.data.msg = '网络错误' + ElMessage.error(error.data.msg) + break + case 503: + error.data.msg = '服务不可用' + ElMessage.error(error.data.msg) + break + case 504: + error.data.msg = '网络超时' + ElMessage.error(error.data.msg) + break + case 505: + error.data.msg = 'http版本不支持该请求' + ElMessage.error(error.data.msg) + break + default: + error.data.msg = `连接错误${error.response.status}` + ElMessage.error(error.data.msg) + } } } else { error.data.msg = "连接到服务器失败" diff --git a/order-system/src/layout/header/LoginOut.vue b/order-system/src/layout/header/LoginOut.vue index 33469ec..aabce2c 100644 --- a/order-system/src/layout/header/LoginOut.vue +++ b/order-system/src/layout/header/LoginOut.vue @@ -1,36 +1,80 @@ \ No newline at end of file diff --git a/order-system/src/router/index.ts b/order-system/src/router/index.ts index 9e1e91f..21ffd28 100644 --- a/order-system/src/router/index.ts +++ b/order-system/src/router/index.ts @@ -26,7 +26,8 @@ const routes: Array = [ name: 'dashboard', component: () => import('@/views/dashboard/Index.vue'), meta: { - title: '首页' + title: '首页', + requiresAuth: true // 添加认证要求 }, }, { @@ -34,7 +35,8 @@ const routes: Array = [ name: 'banner', component: () => import('@/views/banner/Index.vue'), meta: { - title: '广告管理' + title: '广告管理', + requiresAuth: true // 添加认证要求 }, }, { @@ -42,7 +44,8 @@ const routes: Array = [ name: 'category', component: () => import('@/views/category/Index.vue'), meta: { - title: '菜品分类' + title: '菜品分类', + requiresAuth: true // 添加认证要求 }, }, { @@ -50,7 +53,8 @@ const routes: Array = [ name: 'comment', component: () => import('@/views/comment/Index.vue'), meta: { - title: '评论管理' + title: '评论管理', + requiresAuth: true // 添加认证要求 }, }, { @@ -58,7 +62,8 @@ const routes: Array = [ name: 'goods', component: () => import('@/views/goods/Index.vue'), meta: { - title: '菜品管理' + title: '菜品管理', + requiresAuth: true // 添加认证要求 }, }, { @@ -66,7 +71,8 @@ const routes: Array = [ name: 'order', component: () => import('@/views/order/Index.vue'), meta: { - title: '订单管理' + title: '订单管理', + requiresAuth: true // 添加认证要求 }, }, { @@ -74,10 +80,25 @@ const routes: Array = [ name: 'user', component: () => import('@/views/user/Index.vue'), meta: { - title: '用户管理' + title: '用户管理', + requiresAuth: true // 添加认证要求 }, - }, + } ] + }, + + // 登录和注册作为独立路由,不在Layout中 + { + path: '/login', + name: 'Login', + component: () => import('@/views/login/Index.vue'), + meta: { title: '登录' } + }, + { + path: '/register', + name: 'Register', + component: () => import('@/views/register/Index.vue'), + meta: { title: '注册' } } ] @@ -86,4 +107,23 @@ const router = createRouter({ routes }) +// 路由守卫 +router.beforeEach((to, from, next) => { + const token = localStorage.getItem('token') + + // 检查路由是否需要认证 + const requiresAuth = to.matched.some(record => record.meta.requiresAuth) + + if (requiresAuth && !token) { + // 如果需要认证但没有token,跳转到登录页 + next('/login') + } else if ((to.path === '/login' || to.path === '/register') && token) { + // 如果已登录但尝试访问登录/注册页,跳转到首页 + next('/dashboard') + } else { + // 否则继续导航 + next() + } +}) + export default router \ No newline at end of file diff --git a/order-system/src/views/dashboard/Index.vue b/order-system/src/views/dashboard/Index.vue index 64bb1b7..3036f1a 100644 --- a/order-system/src/views/dashboard/Index.vue +++ b/order-system/src/views/dashboard/Index.vue @@ -1,165 +1,332 @@ - + \ No newline at end of file diff --git a/order-system/src/views/login/Index.vue b/order-system/src/views/login/Index.vue new file mode 100644 index 0000000..c0d7f72 --- /dev/null +++ b/order-system/src/views/login/Index.vue @@ -0,0 +1,108 @@ + + + + + \ No newline at end of file diff --git a/order-system/src/views/order/Index.vue b/order-system/src/views/order/Index.vue index bc74091..1599cab 100644 --- a/order-system/src/views/order/Index.vue +++ b/order-system/src/views/order/Index.vue @@ -60,11 +60,15 @@ 已收货 + 已取消 - + @@ -90,6 +94,7 @@ const { tableList, sendOrder, + deleteOrder, // 添加删除订单方法 listParm, resetBtn, searchBtn, @@ -99,5 +104,4 @@ } = useOrderTable(); - - \ No newline at end of file + \ No newline at end of file diff --git a/order-system/src/views/register/Index.vue b/order-system/src/views/register/Index.vue new file mode 100644 index 0000000..3bb1284 --- /dev/null +++ b/order-system/src/views/register/Index.vue @@ -0,0 +1,171 @@ + + + + + \ No newline at end of file diff --git a/order-system/tsconfig.app.json b/order-system/tsconfig.app.json index 7cdf423..a040218 100644 --- a/order-system/tsconfig.app.json +++ b/order-system/tsconfig.app.json @@ -2,42 +2,29 @@ "extends": "@vue/tsconfig/tsconfig.dom.json", "compilerOptions": { "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", - // 添加以下路径配置 "baseUrl": ".", "paths": { - "@/*": [ - "src/*" - ], - "@/api/*": [ - "src/api/*" - ] + "@/*": ["src/*"], + "@/api/*": ["src/api/*"] }, - // 添加必要的库支持 - "lib": [ - "ESNext", - "DOM", - "DOM.Iterable" - ], - "types": [ - "vite/client" - ], - // 添加模块解析配置 + "lib": ["ESNext", "DOM", "DOM.Iterable"], + "types": ["vite/client"], "module": "ESNext", "moduleResolution": "bundler", - // 确保包含以下选项 "target": "ESNext", "esModuleInterop": true, "resolveJsonModule": true, "strict": true, "jsx": "preserve", "downlevelIteration": true, + "skipLibCheck": true, + "allowSyntheticDefaultImports": true }, "include": [ "src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "vite-env.d.ts", - "vite.config.ts", "src/api/**/*.ts" ] } \ No newline at end of file diff --git a/order-system/vite.config.ts b/order-system/vite.config.ts index 9017f29..8c3e300 100644 --- a/order-system/vite.config.ts +++ b/order-system/vite.config.ts @@ -10,7 +10,7 @@ export default defineConfig(({ mode }) => { return { define: { // 替换为全局变量 - __APP_BASE_URL__: JSON.stringify("http://localhost:8089") + __APP_BASE_URL__: JSON.stringify("http://localhost:8089"), }, plugins: [vue()], server: { @@ -50,6 +50,4 @@ export default defineConfig(({ mode }) => { chunkSizeWarningLimit: 1500 } } - - -}) +}) \ No newline at end of file