添加订单表

This commit is contained in:
闵宪瑞 2025-02-24 15:40:03 +08:00
parent 8e7e63bcd7
commit c8eda585cb
46 changed files with 10624 additions and 4883 deletions

View File

@ -30,7 +30,6 @@ import java.util.Date;
/** /**
* 登录 * 登录
*
*/ */
@RestController @RestController
@Tag(name = "登录管理") @Tag(name = "登录管理")
@ -51,9 +50,9 @@ public class LoginController {
} }
@PostMapping("login") @PostMapping("login")
@Operation(summary = "登录") @Operation(summary = "登录")
public Result login(HttpServletRequest request, @RequestBody LoginDTO login) { public Result login(@RequestBody LoginDTO login) {
//效验数据 //效验数据
ValidatorUtils.validateEntity(login); // ValidatorUtils.validateEntity(login);
//验证码是否正确 //验证码是否正确
// boolean flag = captchaService.validate(login.getUuid(), login.getCaptcha()); // boolean flag = captchaService.validate(login.getUuid(), login.getCaptcha());
// if (!flag) { // if (!flag) {

View File

@ -73,8 +73,7 @@ public class CommentController {
Long itemId = comment.getItemId(); Long itemId = comment.getItemId();
ItemDTO itemDTO = itemService.get(itemId); ItemDTO itemDTO = itemService.get(itemId);
if (itemDTO != null){ if (itemDTO != null){
// itemDTO.setLargePic(uploadUrl + "item/" + itemDTO.getLargePic()); itemDTO.setImage(uploadUrl + itemDTO.getImage());;
// itemDTO.setNormalPic(uploadUrl + "item/n_" + itemDTO.getNormalPic());
} }
comment.setItemDTO(itemDTO); comment.setItemDTO(itemDTO);
return comment; return comment;

View File

@ -95,7 +95,7 @@ public class ItemController {
public Result save(@RequestBody ItemDTO dto) { public Result save(@RequestBody ItemDTO dto) {
//效验数据 //效验数据
ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class); ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class);
dto.setImage(uploadUrl + dto.getImage()); dto.setImage(dto.getImage().replace(uploadUrl,""));
itemService.save(dto); itemService.save(dto);
return new Result(); return new Result();
} }
@ -104,7 +104,7 @@ public class ItemController {
@Operation(summary = "修改") @Operation(summary = "修改")
public Result update(@RequestBody ItemDTO dto) { //效验数据 public Result update(@RequestBody ItemDTO dto) { //效验数据
ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class); ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class);
dto.setImage(uploadUrl + dto.getImage()); dto.setImage(dto.getImage().replace(uploadUrl,""));
itemService.update(dto); itemService.update(dto);
return new Result(); return new Result();
} }
@ -113,7 +113,6 @@ public class ItemController {
@Operation(summary = "删除") @Operation(summary = "删除")
@LogOperation("删除") @LogOperation("删除")
public Result delete(@PathVariable Long id) { public Result delete(@PathVariable Long id) {
Long[] ids = new Long[]{id}; Long[] ids = new Long[]{id};
//效验数据 //效验数据
AssertUtils.isArrayEmpty(ids, "id"); AssertUtils.isArrayEmpty(ids, "id");

View File

@ -9,7 +9,13 @@ import io.common.validator.ValidatorUtils;
import io.common.validator.group.AddGroup; import io.common.validator.group.AddGroup;
import io.common.validator.group.DefaultGroup; import io.common.validator.group.DefaultGroup;
import io.common.validator.group.UpdateGroup; import io.common.validator.group.UpdateGroup;
import io.modules.item.dao.FrontUserDao;
import io.modules.item.dto.AddressDTO;
import io.modules.item.dto.ItemDTO;
import io.modules.item.dto.OrderDTO; import io.modules.item.dto.OrderDTO;
import io.modules.item.entity.FrontUserEntity;
import io.modules.item.service.AddressService;
import io.modules.item.service.ItemService;
import io.modules.item.service.OrderService; import io.modules.item.service.OrderService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
@ -17,9 +23,12 @@ import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
/** /**
@ -31,10 +40,23 @@ import java.util.Map;
@RestController @RestController
@RequestMapping("sys/order") @RequestMapping("sys/order")
@Tag(name="订单表") @Tag(name="订单表")
@CrossOrigin
public class OrderController { public class OrderController {
@Autowired @Autowired
private OrderService orderService; private OrderService orderService;
@Autowired
private ItemService itemService;
@Autowired
private AddressService addressService;
@Autowired
private FrontUserDao frontUserDao;
@Value("${upload.url}")
private String uploadUrl;
@GetMapping("page") @GetMapping("page")
@Operation(summary = "分页") @Operation(summary = "分页")
@Parameters({ @Parameters({
@ -45,7 +67,23 @@ public class OrderController {
}) })
public Result<PageData<OrderDTO>> page(@Parameter(hidden = true) @RequestParam Map<String, Object> params){ public Result<PageData<OrderDTO>> page(@Parameter(hidden = true) @RequestParam Map<String, Object> params){
PageData<OrderDTO> page = orderService.page(params); PageData<OrderDTO> page = orderService.page(params);
List<OrderDTO> collect = page.getList().stream().map(e -> {
ItemDTO item = itemService.get(e.getItemId());
if(item != null){
item.setImage(uploadUrl + item.getImage());
}
e.setItem(item);
FrontUserEntity frontUserEntity = frontUserDao.selectById(e.getUserId());
e.setUserEntity(frontUserEntity);
AddressDTO addressDTO = addressService.get(e.getAddressId());
if(addressDTO != null){
e.setAddressDTO(addressDTO);
}
return e;
}).collect(Collectors.toList());
page.setList(collect);
return new Result<PageData<OrderDTO>>().ok(page); return new Result<PageData<OrderDTO>>().ok(page);
} }

View File

@ -3,9 +3,9 @@ spring:
druid: druid:
#MySQL #MySQL
driver-class-name: com.mysql.cj.jdbc.Driver driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://47.94.76.54:23306/bookstore?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true url: jdbc:mysql://localhost:3306/bookstore?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
username: root username: root
password: x6dbfGN4s6YjcX8P password: 123456
initial-size: 10 initial-size: 10
max-active: 100 max-active: 100
min-idle: 10 min-idle: 10

View File

@ -4,6 +4,6 @@ import lombok.Data;
@Data @Data
public class AreaTree { public class AreaTree {
private Long id; private Long value;
private String area; private String label;
} }

View File

@ -7,7 +7,7 @@ import java.util.List;
@Data @Data
public class CityTree { public class CityTree {
private Long id; private Long value;
private String city; private String label;
private List<AreaTree> areaTrees; private List<AreaTree> children;
} }

View File

@ -83,4 +83,5 @@ public class ItemDTO implements Serializable {
* 是否收藏 * 是否收藏
*/ */
private Boolean IsFavorite; private Boolean IsFavorite;
} }

View File

@ -1,5 +1,7 @@
package io.modules.item.dto; package io.modules.item.dto;
import io.modules.item.entity.FrontUserEntity;
import io.modules.item.entity.ItemEntity;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.SchemaProperty; import io.swagger.v3.oas.annotations.media.SchemaProperty;
import lombok.Data; import lombok.Data;
@ -40,7 +42,8 @@ public class OrderDTO implements Serializable {
@SchemaProperty(name = "订单总金额") @SchemaProperty(name = "订单总金额")
private BigDecimal totalAmount; private BigDecimal totalAmount;
private BigDecimal price;
private AddressDTO addressDTO;
@SchemaProperty(name = "支付状态") @SchemaProperty(name = "支付状态")
private Integer paymentStatus; private Integer paymentStatus;
@ -51,4 +54,16 @@ public class OrderDTO implements Serializable {
private Date createdTime; private Date createdTime;
private UserDTO user; private UserDTO user;
private FrontUserEntity userEntity;
private ItemDTO item;
/**
* 订单评价分数
*/
private Integer score;
/**
* 评价内容
*/
private String content;
} }

View File

@ -8,7 +8,7 @@ import java.util.List;
@Data @Data
public class ProvinceTree { public class ProvinceTree {
private Long id; private Long value;
private String province; private String label;
private List<CityTree> cityTrees; private List<CityTree> children;
} }

View File

@ -16,6 +16,7 @@ public class ItemEntity {
* 编号 * 编号
*/ */
private Long id; private Long id;
/** /**
* 名称 * 名称
*/ */

View File

@ -17,6 +17,8 @@ public class OrderEntity {
* 订单编号 * 订单编号
*/ */
private Long id; private Long id;
private BigDecimal price;
/** /**
* 用户编号 * 用户编号
*/ */

View File

@ -63,6 +63,7 @@ public class ItemServiceImpl extends CrudServiceImpl<ItemDao, ItemEntity, ItemDT
} }
wrapper.like(StrUtil.isNotBlank(title), "title", title); wrapper.like(StrUtil.isNotBlank(title), "title", title);
wrapper.orderByDesc(StrUtil.isNotBlank(view), "view"); wrapper.orderByDesc(StrUtil.isNotBlank(view), "view");
wrapper.orderByDesc("create_time");
return wrapper; return wrapper;
@ -92,7 +93,7 @@ public class ItemServiceImpl extends CrudServiceImpl<ItemDao, ItemEntity, ItemDT
Long item_total = baseDao.selectCount(null); Long item_total = baseDao.selectCount(null);
//查询数据总和 //查询数据总和
HashMap<String, Object> a1 = new HashMap<>(); HashMap<String, Object> a1 = new HashMap<>();
a1.put("name", "电影总量"); a1.put("name", "商品总量");
a1.put("value", item_total); a1.put("value", item_total);
a1.put("tag", ""); a1.put("tag", "");
res.add(a1); res.add(a1);
@ -102,7 +103,6 @@ public class ItemServiceImpl extends CrudServiceImpl<ItemDao, ItemEntity, ItemDT
a2.put("value", frontUserDao.selectCount(null)); a2.put("value", frontUserDao.selectCount(null));
a2.put("tag", ""); a2.put("tag", "");
res.add(a2); res.add(a2);
return res; return res;
} }

View File

@ -35,6 +35,7 @@ public class OrderServiceImpl extends CrudServiceImpl<OrderDao, OrderEntity, Ord
String orderStatus = (String)params.get("orderStatus"); String orderStatus = (String)params.get("orderStatus");
String paymentStatus = (String)params.get("paymentStatus"); String paymentStatus = (String)params.get("paymentStatus");
String userId = (String)params.get("userId"); String userId = (String)params.get("userId");
QueryWrapper<OrderEntity> wrapper = new QueryWrapper<>(); QueryWrapper<OrderEntity> wrapper = new QueryWrapper<>();
wrapper.eq(StrUtil.isNotBlank(id), "id", id); wrapper.eq(StrUtil.isNotBlank(id), "id", id);
wrapper.eq(StrUtil.isNotBlank(orderStatus), "order_status", orderStatus); wrapper.eq(StrUtil.isNotBlank(orderStatus), "order_status", orderStatus);

View File

@ -54,11 +54,10 @@ public class ProvinceServiceImpl extends CrudServiceImpl<ProvinceDao, ProvinceEn
List<ProvinceEntity> provinces = baseDao.selectList(null); List<ProvinceEntity> provinces = baseDao.selectList(null);
List<ProvinceTree> provinceTrees = new ArrayList<>(); List<ProvinceTree> provinceTrees = new ArrayList<>();
for (ProvinceEntity province : provinces) { for (ProvinceEntity province : provinces) {
ProvinceTree provinceTree = new ProvinceTree(); ProvinceTree provinceTree = new ProvinceTree();
provinceTree.setId(province.getId()); provinceTree.setValue(province.getId());
provinceTree.setProvince(province.getProvince()); provinceTree.setLabel(province.getProvince());
provinceTree.setCityTrees(getCityTree(province.getProvinceId())); // 获取该省的城市树 provinceTree.setChildren(getCityTree(province.getProvinceId())); // 获取该省的城市树
provinceTrees.add(provinceTree); provinceTrees.add(provinceTree);
} }
return provinceTrees; return provinceTrees;
@ -71,9 +70,9 @@ public class ProvinceServiceImpl extends CrudServiceImpl<ProvinceDao, ProvinceEn
List<CityTree> cityTrees = new ArrayList<>(); List<CityTree> cityTrees = new ArrayList<>();
for (CityEntity city : cities) { for (CityEntity city : cities) {
CityTree cityTree = new CityTree(); CityTree cityTree = new CityTree();
cityTree.setId(city.getId()); cityTree.setValue(city.getId());
cityTree.setCity(city.getCity()); cityTree.setLabel(city.getCity());
cityTree.setAreaTrees(getAreaTree(city.getCityId())); // 获取该城市的地区树 cityTree.setChildren(getAreaTree(city.getCityId())); // 获取该城市的地区树
cityTrees.add(cityTree); cityTrees.add(cityTree);
} }
return cityTrees; return cityTrees;
@ -87,8 +86,8 @@ public class ProvinceServiceImpl extends CrudServiceImpl<ProvinceDao, ProvinceEn
List<AreaTree> areaTrees = new ArrayList<>(); List<AreaTree> areaTrees = new ArrayList<>();
for (AreaEntity area : areas) { for (AreaEntity area : areas) {
AreaTree areaTree = new AreaTree(); AreaTree areaTree = new AreaTree();
areaTree.setId(area.getId()); areaTree.setValue(area.getId());
areaTree.setArea(area.getArea()); areaTree.setLabel(area.getArea());
areaTrees.add(areaTree); areaTrees.add(areaTree);
} }
return areaTrees; return areaTrees;

4398
admin-ui/db/bookstore.sql Normal file

File diff suppressed because one or more lines are too long

View File

@ -18,8 +18,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.Parameters;
import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map; import java.util.Map;
@ -30,6 +28,7 @@ import java.util.Map;
@RestController @RestController
@RequestMapping("api/address") @RequestMapping("api/address")
@Tag(name="收货地址表") @Tag(name="收货地址表")
@CrossOrigin
public class AddressController { public class AddressController {
@Autowired @Autowired
private AddressService addressService; private AddressService addressService;

View File

@ -24,6 +24,7 @@ import java.util.Map;
@RestController @RestController
@RequestMapping("api/area") @RequestMapping("api/area")
@Tag(name="地区信息") @Tag(name="地区信息")
@CrossOrigin
public class AreaController { public class AreaController {
@Autowired @Autowired
private ProvinceService provinceService; private ProvinceService provinceService;

View File

@ -1,127 +0,0 @@
package io.controller;
import io.annotation.Login;
import io.common.constant.Constant;
import io.common.page.PageData;
import io.common.utils.Result;
import io.common.validator.AssertUtils;
import io.common.validator.ValidatorUtils;
import io.common.validator.group.AddGroup;
import io.common.validator.group.DefaultGroup;
import io.common.validator.group.UpdateGroup;
import io.modules.item.dto.ArticleDTO;
import io.modules.item.service.ArticleService;
import io.modules.item.service.DictService;
import io.modules.item.service.UserBehaviorService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 文章表
*/
@RestController
@RequestMapping("/api/article")
@Tag(name = "文章表")
@CrossOrigin
public class ArticleFrontController {
@Autowired
private ArticleService articleService;
@Autowired
private UserBehaviorService userBehaviorService;
@Autowired
private DictService dictService;
@GetMapping("page")
@Operation(summary = "分页")
@Parameters({
@Parameter(name = Constant.PAGE, description = "当前页码从1开始", in = ParameterIn.QUERY, required = true, ref = "int"),
@Parameter(name = Constant.LIMIT, description = "每页显示记录数", in = ParameterIn.QUERY, required = true, ref = "int"),
@Parameter(name = Constant.ORDER_FIELD, description = "排序字段", in = ParameterIn.QUERY, ref = "String"),
@Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)", in = ParameterIn.QUERY, ref = "String"),
@Parameter(name = "type", description = "类型", in = ParameterIn.QUERY, ref = "String")
})
public Result<PageData<ArticleDTO>> page(@Parameter(hidden = true) @RequestParam Map<String, Object> params) {
PageData<ArticleDTO> page = articleService.page(params);
return new Result<PageData<ArticleDTO>>().ok(page);
}
@GetMapping("top")
@Operation(summary = "推荐")
public Result<List<ArticleDTO>> top() {
List<ArticleDTO> res = new ArrayList<>();
List<Long> topItems = userBehaviorService.getTopItems();
// 根据ID获取文章数据
for (Long id : topItems) {
ArticleDTO articleDTO = articleService.get(id); // 假设 get 方法返回 ArticleDTO
if (articleDTO != null) {
res.add(articleDTO);
}
}
return new Result< List<ArticleDTO>>().ok(res);
}
@Login
@GetMapping("list")
@Operation(summary = "信息")
public Result<List<ArticleDTO>> list(@Parameter(hidden = true) @RequestParam Map<String, Object> params,
@Parameter(hidden = true) @RequestAttribute("userId") Long userId) {
params.put("userId",userId);
List<ArticleDTO> list = articleService.list(params);
return new Result< List<ArticleDTO>>().ok(list);
}
@GetMapping("{id}")
@Operation(summary = "信息")
public Result<ArticleDTO> get(@PathVariable("id") Long id) {
ArticleDTO data = articleService.get(id);
return new Result<ArticleDTO>().ok(data);
}
@Login
@PostMapping
@Operation(summary = "保存")
public Result save(@Parameter(hidden = true) @RequestAttribute("userId") Long userId, @RequestBody ArticleDTO dto) {
//效验数据
System.out.println("用户" + userId);
ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class);
dto.setUserId(userId);
List<String> contentExistsList = dictService.isExistsList(dto.getContent());
if (!contentExistsList.isEmpty()){
return new Result().error("内容出现敏感词:"+ contentExistsList);
}
articleService.save(dto);
return new Result();
}
@Login
@PutMapping
@Operation(summary = "修改")
public Result update(@Parameter(hidden = true) @RequestAttribute("userId") Long userId, @RequestBody ArticleDTO dto) {
//效验数据
ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class);
dto.setUserId(userId);
articleService.update(dto);
return new Result();
}
@DeleteMapping("{id}")
@Operation(summary = "删除")
public Result delete(@PathVariable Long id) {
//效验数据
articleService.deleteById(id);
return new Result();
}
}

View File

@ -64,7 +64,6 @@ public class ItemController {
PageData<ItemDTO> page = itemService.page(params); PageData<ItemDTO> page = itemService.page(params);
List<ItemDTO> list = page.getList().stream().map(e -> { List<ItemDTO> list = page.getList().stream().map(e -> {
e.setImage(uploadUrl + e.getImage()); e.setImage(uploadUrl + e.getImage());
// 获取评价信息 // 获取评价信息
List<OrderDTO> orderEntityList = orderService.getCommintList(e.getId() ); List<OrderDTO> orderEntityList = orderService.getCommintList(e.getId() );
e.setOrderEntityList(orderEntityList); e.setOrderEntityList(orderEntityList);
@ -79,14 +78,11 @@ public class ItemController {
@Operation(summary = "查询收藏") @Operation(summary = "查询收藏")
public Result<List<ItemEntity>> list(@Parameter(hidden = true) @RequestAttribute("userId") Long userId){ public Result<List<ItemEntity>> list(@Parameter(hidden = true) @RequestAttribute("userId") Long userId){
List<ItemEntity> page = itemService.listUser(userId); List<ItemEntity> page = itemService.listUser(userId);
List<ItemEntity> list = page.stream().map(e -> {
// List<ItemDTO> list = page.getList().stream().map(e -> { e.setImage(uploadUrl + e.getImage());
// e.setLargePic(uploadUrl + "item/" + e.getLargePic()); return e;
// e.setNormalPic(uploadUrl + "item/n_" + e.getNormalPic()); }).collect(Collectors.toList());
// return e; return new Result<List<ItemEntity>>().ok(list);
// }).collect(Collectors.toList());
// page.setList(list);
return new Result<List<ItemEntity>>().ok(page);
} }
@ -119,11 +115,16 @@ public class ItemController {
@GetMapping("{id}") @GetMapping("{id}")
@Operation(summary = "信息") @Operation(summary = "信息")
public Result<ItemDTO> get(@PathVariable("id") Long id){ public Result<ItemDTO> get(@PathVariable("id") Long id){
//获取详情
ItemDTO data = itemService.get(id); ItemDTO data = itemService.get(id);
data.setImage(uploadUrl + data.getImage()); data.setImage(data.getImage().replace(uploadUrl,""));
// 添加预览 // 添加预览
data.setView(data.getView() + 1); data.setView(data.getView() + 1);
// 更新
itemService.update(data); itemService.update(data);
data.setImage(uploadUrl + data.getImage());
//是否收藏 //是否收藏
data.setIsFavorite(userBehaviorService.getIsFavorite(data.getId(),1)); data.setIsFavorite(userBehaviorService.getIsFavorite(data.getId(),1));
return new Result<ItemDTO>().ok(data); return new Result<ItemDTO>().ok(data);
@ -141,7 +142,8 @@ public class ItemController {
@Operation(summary = "修改") @Operation(summary = "修改")
public Result update(@RequestBody ItemDTO dto){ //效验数据 public Result update(@RequestBody ItemDTO dto){ //效验数据
ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class); ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class);
dto.setImage(uploadUrl + dto.getImage());
dto.setImage(dto.getImage().replace(uploadUrl,""));
itemService.update(dto); itemService.update(dto);
return new Result(); return new Result();
} }
@ -153,7 +155,4 @@ public class ItemController {
itemService.delete(ids); itemService.delete(ids);
return new Result(); return new Result();
} }
} }

View File

@ -10,31 +10,41 @@ import io.common.validator.ValidatorUtils;
import io.common.validator.group.AddGroup; import io.common.validator.group.AddGroup;
import io.common.validator.group.DefaultGroup; import io.common.validator.group.DefaultGroup;
import io.common.validator.group.UpdateGroup; import io.common.validator.group.UpdateGroup;
import io.modules.item.dto.ItemDTO;
import io.modules.item.dto.OrderDTO; import io.modules.item.dto.OrderDTO;
import io.modules.item.service.ItemService;
import io.modules.item.service.OrderService; import io.modules.item.service.OrderService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.Parameters;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
/** /**
* 订单表 * 订单表
*
* @author Mark #
* @since 1.0.0 2025-02-14
*/ */
@RestController @RestController
@RequestMapping("api/order") @RequestMapping("/api/order")
@Tag(name="订单表") @Tag(name="订单表")
@CrossOrigin
public class OrderController { public class OrderController {
@Autowired @Autowired
private OrderService orderService; private OrderService orderService;
@Autowired
private ItemService itemService;
@Value("${upload.url}")
private String uploadUrl;
@GetMapping("page") @GetMapping("page")
@Operation(summary = "分页") @Operation(summary = "分页")
@Parameters({ @Parameters({
@ -45,8 +55,18 @@ public class OrderController {
}) })
@Login @Login
public Result<PageData<OrderDTO>> page(@Parameter(hidden = true) @RequestParam Map<String, Object> params,@Parameter(hidden = true) @RequestAttribute("userId") Long userId){ public Result<PageData<OrderDTO>> page(@Parameter(hidden = true) @RequestParam Map<String, Object> params,@Parameter(hidden = true) @RequestAttribute("userId") Long userId){
params.put("userId",userId); params.put("userId",userId.toString());
PageData<OrderDTO> page = orderService.page(params); PageData<OrderDTO> page = orderService.page(params);
List<OrderDTO> collect = page.getList().stream().map(e -> {
ItemDTO item = itemService.get(e.getItemId());
if(item != null){
item.setImage(uploadUrl + item.getImage());
}
e.setItem(item);
return e;
}).collect(Collectors.toList());
page.setList(collect);
return new Result<PageData<OrderDTO>>().ok(page); return new Result<PageData<OrderDTO>>().ok(page);
} }
@ -59,9 +79,9 @@ public class OrderController {
@PostMapping @PostMapping
@Operation(summary = "保存") @Operation(summary = "保存")
public Result save(@RequestBody OrderDTO dto){ @Login
//效验数据 public Result save(@RequestBody OrderDTO dto,@Parameter(hidden = true) @RequestAttribute("userId") Long userId){
ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class); dto.setUserId(userId);
orderService.save(dto); orderService.save(dto);
return new Result(); return new Result();
} }
@ -69,22 +89,17 @@ public class OrderController {
@PutMapping @PutMapping
@Operation(summary = "修改") @Operation(summary = "修改")
public Result update(@RequestBody OrderDTO dto){ public Result update(@RequestBody OrderDTO dto){
//效验数据
ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class);
orderService.update(dto); orderService.update(dto);
return new Result(); return new Result();
} }
@DeleteMapping @DeleteMapping("{id}")
@Operation(summary = "删除") @Operation(summary = "删除")
public Result delete(@PathVariable Long id) {
public Result delete(@RequestBody Long[] ids){ Long[] ids = new Long[]{id};
//效验数据 //效验数据
AssertUtils.isArrayEmpty(ids, "id"); AssertUtils.isArrayEmpty(ids, "id");
orderService.delete(ids); orderService.delete(ids);
return new Result(); return new Result();
} }
} }

View File

@ -6,9 +6,9 @@ spring:
datasource: datasource:
druid: druid:
driver-class-name: com.mysql.cj.jdbc.Driver driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://47.94.76.54:23306/bookstore?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true url: jdbc:mysql://localhost:3306/bookstore?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
username: root username: root
password: x6dbfGN4s6YjcX8P password: 123456
initial-size: 10 initial-size: 10
max-active: 100 max-active: 100
min-idle: 10 min-idle: 10
@ -33,7 +33,7 @@ spring:
multi-statement-allow: true multi-statement-allow: true
web: web:
resources: resources:
static-locations: "file:F:/2025/bookstore-springboot-vue/admin-ui/upload/" static-locations: "file:D:/2025/bookstore-springboot-vue/admin-ui/upload/"
upload: upload:
path: F:\2025\bookstore-springboot-vue\admin-ui\upload path: D:\2025\bookstore-springboot-vue\admin-ui\upload
url: http://localhost:18081/ url: http://localhost:18081/

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

View File

@ -7,7 +7,7 @@ VITE_ADMIN_API_BASE_URL = http://localhost:18080
VITE_LOGIN_BG = "/login/e36341619bf8f04dcbdc6b01105a85a.png" VITE_LOGIN_BG = "/login/e36341619bf8f04dcbdc6b01105a85a.png"
# 标题 # 标题
VITE_APP_TITLE = 电影系统 VITE_APP_TITLE = 图书系统
# markdown 渲染支持 # markdown 渲染支持
VITE_APP_MARKDOWN = true VITE_APP_MARKDOWN = true

9595
ui/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -8,10 +8,13 @@
:before-upload="beforeUpload" :before-upload="beforeUpload"
> >
<img v-if="state.imageUrl" :src="state.imageUrl" class="avatar" /> <img v-if="state.imageUrl" :src="state.imageUrl" class="avatar" />
<el-icon v-else class="avatar-uploader-icon"> <el-icon v-else class="avatar-uploader-icon">
<Plus /> <Plus />
</el-icon> </el-icon>
</el-upload> </el-upload>
{{state.imageUrl}}
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -39,7 +42,6 @@ watch(
} }
) )
onMounted(()=>{ onMounted(()=>{
console.log(props.imageUrl)
if (props.imageUrl){ if (props.imageUrl){
state.imageUrl = props.imageUrl state.imageUrl = props.imageUrl
} }
@ -62,8 +64,9 @@ const handleSuccess: UploadProps['onSuccess'] = (
state.imageUrl = response.data.path state.imageUrl = response.data.path
ElMessage.success('上传成功') ElMessage.success('上传成功')
console.log("fanhui1",response) console.log("fanhui1",response)
console.log("fanhui2",response.data.path)
// emit // emit
emit('update:imageUrl', response.data.absolute); emit('update:imageUrl', response.data.path);
} }
</script> </script>

View File

@ -6,7 +6,7 @@
:defaultConfig="toolbarConfig" :defaultConfig="toolbarConfig"
:mode="mode" :mode="mode"
/> />
<!-- 内容--> <!-- 内容-->
<Editor <Editor
style="height: 500px; overflow-y: hidden" style="height: 500px; overflow-y: hidden"
v-model="valueHtml" v-model="valueHtml"
@ -14,7 +14,6 @@
:mode="mode" :mode="mode"
@onCreated="handleCreated" @onCreated="handleCreated"
/> />
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -25,7 +24,6 @@ import { ElMessage } from 'element-plus'
// shallowRef // shallowRef
const editorRef = shallowRef<InstanceType<typeof Editor> | null>(null) const editorRef = shallowRef<InstanceType<typeof Editor> | null>(null)
const emit = defineEmits(); const emit = defineEmits();
const state = reactive({ const state = reactive({
path: import.meta.env.VITE_API_FRONT_BASE_URL + '/api/upload', path: import.meta.env.VITE_API_FRONT_BASE_URL + '/api/upload',
}) })
@ -38,7 +36,6 @@ const valueHtml = ref<string>('')
watch( watch(
() => props.content, () => props.content,
(newContent) => { (newContent) => {
console.log('新值变化', newContent);
valueHtml.value = newContent; valueHtml.value = newContent;
emit( "update:content",valueHtml.value) emit( "update:content",valueHtml.value)
}, },

View File

@ -1,8 +1,7 @@
<!--详情底部--> <!--详情底部-->
<template> <template>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="14"> <el-col :span="12">
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<el-input v-model="state.content" class="commit " placeholder="发表神秘评论" /> <el-input v-model="state.content" class="commit " placeholder="发表神秘评论" />
@ -29,22 +28,25 @@
</el-col> </el-col>
<!--热门--> <!--热门-->
<el-col :span="10"> <el-col :span="12">
<item2></item2> <div v-html="state.info.description"></div>
</el-col> </el-col>
</el-row> </el-row>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Item2 from '~/components/front/item2.vue'
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
const route = useRoute(); const route = useRoute();
const state =reactive(<any>{ const state =reactive(<any>{
commentList:[], commentList:[],
content:"" content:"",
info:""
}) })
const itemId = route.params.id; const itemId = route.params.id;
function init() { function init() {
frontRequest.get(`/api/item/${itemId}`).then(response =>{
state.info = response.data
})
frontRequest.get("/api/comment/list",{ frontRequest.get("/api/comment/list",{
params:{itemId:itemId} params:{itemId:itemId}
}).then(response =>{ }).then(response =>{

View File

@ -3,21 +3,16 @@
<el-row :gutter="20" class="info"> <el-row :gutter="20" class="info">
<el-col :span="10"> <el-col :span="10">
<!-- 详情图片--> <!-- 详情图片-->
<el-image :src="state.info.largePic" fit="contain" /> <el-image :src="state.info.image" fit="contain" />
</el-col> </el-col>
<el-col :span="14"> <el-col :span="14">
<!-- 标题--> <!-- 标题-->
<h1>{{state.info.title}} ( {{state.info.year}} ) </h1> <h1>{{state.info.title}} </h1>
<!-- 简介--> <!-- 简介-->
<div class="introduction" v-if="state.info.country"> <span style="font-weight: 700">编剧:</span> {{state.info.actor}} </div> <div class="introduction" v-if="state.info.tag"> <span style="font-weight: 700">作者:</span> {{state.info.tag}} </div>
<div class="introduction" v-if="state.info.country"> <span style="font-weight: 700">导演: </span> {{state.info.director}} </div> <div class="introduction" v-if="state.info.stockQuantity"> <span style="font-weight: 700">库存:</span> {{state.info.stockQuantity}} </div>
<div class="introduction" v-if="state.info.country"> <span style="font-weight: 700">制片国家/地区: </span> {{state.info.country}} </div> <div class="introduction" v-if="state.info.price">
<div class="introduction" v-if="state.info.country"> <span style="font-weight: 700">电影评分: </span> {{state.info.ratingValue}} </div> <span style="font-weight: 700">价格:</span> <span style="color:red">{{state.info.price}} </span> </div>
<!--标签-->
<div class="tag">
<span style="font-weight: 700">导演: </span> <el-tag v-for="tag in (state.info.movieType || '').split(' ')" :key="tag" style="margin-right: 10px">{{ tag }}</el-tag>
</div>
<!--操作--> <!--操作-->
<div class="operate"> <div class="operate">
<!-- 加入购物车--> <!-- 加入购物车-->
@ -37,7 +32,7 @@
title="购买" title="购买"
> >
<el-form <el-form
ref="buyFormRef" ref="formRef"
style="max-width: 600px" style="max-width: 600px"
:model="state.buyForm" :model="state.buyForm"
label-width="auto" label-width="auto"
@ -47,7 +42,7 @@
<el-input disabled v-model="state.buyForm.title" /> <el-input disabled v-model="state.buyForm.title" />
</el-form-item> </el-form-item>
<el-form-item prop="title" label="商品单价" > <el-form-item prop="title" label="商品单价(元)" >
<el-input disabled v-model="state.buyForm.price" /> <el-input disabled v-model="state.buyForm.price" />
</el-form-item> </el-form-item>
@ -57,7 +52,18 @@
</el-form-item> </el-form-item>
<el-form-item prop="title" label="总价" > <el-form-item prop="title" label="总价" >
<el-input-number disabled <el-input-number disabled
v-model="state.buyForm.total" :min="1" /> v-model="state.buyForm.totalAmount" />
</el-form-item>
<el-form-item prop="addressId" label="选择收货地址" >
<el-select v-model="state.buyForm.addressId" placeholder="Select" style="width: 240px">
<el-option
v-for="item in state.cateList"
:key="item.id"
:label="item.city"
:value="item.id"
/>
</el-select>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="buySubmitForm(formRef)">确定</el-button> <el-button type="primary" @click="buySubmitForm(formRef)">确定</el-button>
@ -70,26 +76,18 @@ import { reactive } from 'vue'
import type { FormInstance } from 'element-plus' import type { FormInstance } from 'element-plus'
const buyDrawer = ref(false) const buyDrawer = ref(false)
const formRef = ref<FormInstance>() const formRef = ref<FormInstance>()
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
const route = useRoute(); const route = useRoute();
const itemId = route.params.id; const itemId = route.params.id;
const state =reactive(<any>{ const state =reactive(<any>{
info:{ info:{},
id:1122334545,
title:"粉色羽绒服女冬季长款过膝2024新款韩版宽松加厚白鸭绒面包服外套",
url: 'https://img2.epetbar.com/common/upload/commonfile/2020/011/13/150904_705255.jpg@!300w-c',
introduction:"毒液最后一舞是一部评分7.0的电影影视作品,影片的导演是凯莉·马塞尔 ,是由汤姆·哈迪 切瓦特·埃加福 朱诺·坦普尔 斯蒂芬·格拉汉姆 主演的动作 科幻 惊悚 冒险 科幻片 类型作品,毒液和埃迪(汤姆·哈迪 Tom Hardy 饰)迎来至暗时刻。一边是人类神秘组织的穷追猛打,一边是外星共生体大军入侵地球,他们一心同体,花式解锁海陆空作战新形态。面对两边的疯狂追捕,这对亡命搭档将被迫做出毁灭性决定,为他们的最后一舞拉下帷幕。",
tags:["面包服","外套"],
price: 129.00,
stock: 99,
},
buyForm:{ buyForm:{
id:null, itemId:itemId,
title:"", title:"",
quantity:1, quantity:1,
total:0 totalAmount:0
} },
cateList:[]
}) })
// route.params.id // route.params.id
@ -104,6 +102,11 @@ function init() {
frontRequest.get(`/api/item/${itemId}`).then(response =>{ frontRequest.get(`/api/item/${itemId}`).then(response =>{
state.info = response.data state.info = response.data
}) })
frontRequest.get(`api/address/page`).then(response =>{
state.cateList = response.data.list
})
} }
onMounted(()=>{ onMounted(()=>{
init() init()
@ -133,9 +136,11 @@ const buySubmitForm = (formEl: FormInstance | undefined) => {
if (!formEl) return if (!formEl) return
formEl.validate((valid) => { formEl.validate((valid) => {
if (valid) { if (valid) {
console.log('submit!') console.log(state.buyForm)
} else { frontRequest.post("/api/order",state.buyForm).then(res =>{
console.log('error submit!') ElMessage.success("购买成功")
buyDrawer.value = false
})
} }
}) })
} }
@ -148,10 +153,17 @@ const handleBuy = () => {
state.buyForm.title = state.info.title state.buyForm.title = state.info.title
state.buyForm.id = state.info.id state.buyForm.id = state.info.id
state.buyForm.price = state.info.price state.buyForm.price = state.info.price
state.buyForm.total = state.info.price * state.buyForm.quantity state.buyForm.totalAmount = (state.info.price * state.buyForm.quantity).toFixed(2);
} }
/**
* 添加数量
*/
const handleChange = () => { const handleChange = () => {
state.buyForm.total = state.info.price * state.buyForm.quantity state.buyForm.totalAmount = (state.info.price * state.buyForm.quantity).toFixed(2);
} }
</script> </script>
<style scoped> <style scoped>

View File

@ -60,9 +60,9 @@
</el-row> </el-row>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useRouter } from 'vue-router'
import { itemPage } from '~/api/itemApi' import { itemPage } from '~/api/itemApi'
import { Search } from '@element-plus/icons-vue' import { Search } from '@element-plus/icons-vue'
import { useRouter } from 'vue-router'
const router = useRouter() const router = useRouter()
const props = defineProps({ const props = defineProps({
isPage: { isPage: {

View File

@ -26,7 +26,7 @@
<el-dropdown v-else> <el-dropdown v-else>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="24"> <el-col :span="24">
<h6>{{ userStore().frontUserInfo.nickName }}</h6> <h6>{{ state.userInfo.nickName }}</h6>
</el-col> </el-col>
</el-row> </el-row>
<template #dropdown> <template #dropdown>
@ -51,11 +51,24 @@ const nav = navStore()
const handleSelect = (key: string, keyPath: string[]) => { const handleSelect = (key: string, keyPath: string[]) => {
nav.frontPath = key.fullPath nav.frontPath = key.fullPath
} }
const state = reactive({
userInfo:{}
})
onMounted(()=>{
frontRequest.get("/api/user/userInfo").then(response =>{
state.userInfo = response.data
})
})
/** /**
* 退出登录 * 退出登录
*/ */
const logout = () => { const logout = () => {
logoutFront().then(() => { logoutFront().then(() => {
const user = userStore()
user.frontIsLogin = false
user.frontToken = ''
user.frontUserInfo = {}
toast.success('退出成功~') toast.success('退出成功~')
router.push('/login') router.push('/login')
}) })

View File

@ -1,4 +1,3 @@
<template> <template>
<el-container> <el-container>
<el-header> <el-header>

View File

@ -34,8 +34,10 @@ const state = reactive({
activeIndex:'/user', activeIndex:'/user',
userMenu:[ userMenu:[
{name: '个人中心', path: '/user'}, {name: '个人中心', path: '/user'},
{name: '用户收藏', path: '/order'}, {name: '收货地址', path: '/address'},
{name: '用户文创', path: '/fronttopic'}, {name: '我的收藏', path: '/collect'},
{name: '我的订单', path: '/order'},
] ]
}) })

View File

@ -0,0 +1,175 @@
<!--用户详情-->
<template>
<el-tabs v-model="state.page.orderStatus" @tab-click="handleClick">
<el-tab-pane v-for="status in state.getOrderStatus" :label="status.name" :name="status.status">
<el-table
:data="state.getList"
style="width: 100%"
>
<el-table-column prop="id" label="编号" />
<el-table-column prop="item.title" label="商品名称" />
<el-table-column prop="price" label="图片" >
<template #default="{ row }">
<img :src="row.item.image" style="width: 100px; height: 100px;">
</template>
</el-table-column>
<el-table-column prop="price" label="购买单价" />
<el-table-column prop="quantity" label="购买数量" />
<el-table-column prop="totalAmount" label="成交总价" />
<el-table-column prop="createdTime" label="购买时间" width="220" />
<el-table-column prop="addressDTO.city" label="收货地址" width="220" />
<el-table-column label="操作" min-width="120">
<template #default="scope" >
<el-button link type="primary" size="small" v-if="state.page.orderStatus == 0" @click="update(scope.row,1)">开始发货</el-button>
<el-button link type="primary" size="small" v-if="state.page.orderStatus == 1" @click="update(scope.row,2)">确认收货</el-button>
<el-button link type="primary" size="small" v-if="state.page.orderStatus == 2" @click="update(scope.row,3)">我要评价</el-button>
<el-button link type="primary" size="small" v-if="state.page.orderStatus == 3" @click="del(scope.row.id)">删除订单</el-button>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
<el-dialog
v-model="dialogVisible"
title="我要评价"
width="500"
>
<el-form
ref="formRef"
style="max-width: 600px"
:model="state.orderForm"
label-width="auto"
label-position="top"
>
<el-form-item
prop="evaluate"
label="评论内容"
:rules="[
{
required: true,
message: '评论内容不能为空',
trigger: 'blur',
},
]"
>
<el-input v-model="state.orderForm.evaluate" :rows="4"
type="textarea"/>
</el-form-item>
<el-form-item
prop="score"
label="评分"
>
<el-rate v-model="state.orderForm.score" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="review(formRef)" >
</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
import { FormInstance, TabsPaneContext } from 'element-plus'
const formRef = ref<FormInstance>()
const state = reactive({
getOrderStatus:[
{name:"未发货",status:0},
{name:"已发货",status:1},
{name:"未评价",status:2},
{name:"已完成",status:3},
],
getList:[],
orderForm:{
score: 0
},
page:{
page:1,
limit:10,
order:'desc',
orderStatus:0,
}
})
const dialogVisible = ref(false)
/**
* 删除订单
* @param id
*/
const del = (id:any) => {
frontRequest.delete(`/sys/order/${id}`).then(res =>{
toast.success("删除成功~")
getList()
})
}
/**
* 获取列表数据
*/
function getList() {
adminRequest.get("/sys/order/page",{ params: state.page}).then(res =>{
state.getList = res.data.list;
})
}
const handleClick = (tab: TabsPaneContext, event: Event) => {
const selectedStatus = state.getOrderStatus[tab.index].status;
state.page.orderStatus = selectedStatus;
getList()
}
const update = (data:any,status:number) => {
// if(status === 4){
// dialogVisible.value = true
// state.orderForm = {...data,evaluate:''}
// state.orderForm.status = 4
// return
// }
data.orderStatus = status
adminRequest.put("/sys/order",data).then(() =>{
toast.success("修改成功~")
getList()
})
}
onMounted(()=>{
getList()
})
const review = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.validate((valid) => {
if (valid) {
updateOrderItemApi(state.orderForm).then(res =>{
toast.success("修改成功~")
dialogVisible.value = false
getList()
})
}
})
}
</script>
<style scoped>
</style>
<route lang="json">
{
"meta": {
"layout": "frontUserInfo"
}
}
</route>

View File

@ -16,19 +16,19 @@
<el-col :span="24"> <el-col :span="24">
<el-table :data="state.getList"> <el-table :data="state.getList">
<!-- 列表结开始--> <!-- 列表结开始-->
<el-table-column prop="id" label="编号" align="center" width="120px"/> <el-table-column prop="item.id" label="编号" align="center" width="120px"/>
<el-table-column prop="itemDTO.title" label="电影名称" align="center" width="120px"/> <el-table-column prop="item.title" label="名称" align="center" width="120px"/>
<el-table-column prop="nickName" label="用户昵称" align="center" width="120px" /> <el-table-column prop="userEntity.nickName" label="用户昵称" align="center" width="120px" />
<el-table-column prop="itemDTO.largePic" label="电影图片" align="center" width="100" > <el-table-column prop="itemDTO.largePic" label="图片" align="center" width="100" >
<template #default="{ row }"> <template #default="{ row }">
<!-- 点击图片后显示弹框预览 --> <!-- 点击图片后显示弹框预览 -->
<el-image <el-image
:src="row.itemDTO.largePic" :src="row.item.image"
fit="cover" fit="cover"
/> />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="score" label="评分" align="center" width="120px"/> <el-table-column prop="score" label="评分" align="center" />
<el-table-column prop="content" label="评论内容" align="center"> <el-table-column prop="content" label="评论内容" align="center">
<template #default="scope"> <template #default="scope">
<div style="width: 100%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;"> <div style="width: 100%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;">
@ -36,7 +36,6 @@
</div> </div>
</template> </template>
</el-table-column> </el-table-column>
<!--列表结束--> <!--列表结束-->
<el-table-column label="操作" align="center" width="120px"> <el-table-column label="操作" align="center" width="120px">
@ -60,89 +59,13 @@
</el-col> </el-col>
</el-row> </el-row>
<!-- 新增/编辑对话框 -->
<el-dialog v-model="state.dialogVisible" title="新增" width="50%">
<el-form
:model="formData"
ref="formRef"
label-width="100px"
>
<!-- 表单开始===============================================================================================================================-->
<el-form-item label="电影名称" prop="title" :rules="[{ required: true, message: '请输入电影名称', trigger: 'blur' }]">
<el-input v-model="formData.title"/>
</el-form-item>
<el-form-item label="电影副标题" prop="cardSubtitle" :rules="[{ required: true, message: '请输入电影副标题', trigger: 'blur' }]">
<el-input v-model="formData.cardSubtitle"/>
</el-form-item>
<el-form-item label="国家" prop="country" :rules="[{ required: true, message: '请输入国家', trigger: 'blur' }]">
<el-input v-model="formData.country"/>
</el-form-item>
<el-form-item label="电影类型" prop="movieType" :rules="[{ required: true, message: '请输入电影类型', trigger: 'blur' }]">
<el-input v-model="formData.movieType" placeholder="多个请空格分隔"/>
</el-form-item>
<el-form-item label="导演" prop="director" :rules="[{ required: true, message: '请输入导演', trigger: 'blur' }]">
<el-input v-model="formData.director" placeholder="多个请空格分隔"/>
</el-form-item>
<el-form-item label="主演" prop="actor" :rules="[{ required: true, message: '请输入主演', trigger: 'blur' }]">
<el-input v-model="formData.actor" placeholder="多个请空格分隔"/>
</el-form-item>
<el-form-item label="上映时间" prop="year" :rules="[{ required: true, message: '请输入上映时间', trigger: 'blur' }]">
<el-select v-model="formData.year" placeholder="请选择上映年份">
<!-- 使用 v-for 动态生成年份列表 -->
<el-option
v-for="year in years"
:key="year"
:label="year"
:value="year"
/>
</el-select>
</el-form-item>
<el-form-item label="图片" prop="largePic" :rules="[{ required: true, message: '请插入图片', trigger: 'blur' }]">
<el-upload
class="avatar-uploader"
action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
:show-file-list="false"
:on-success="handleAvatarSuccess"
>
<img v-if="formData.largePic" :src="formData.largePic" class="avatar" />
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
</el-upload>
</el-form-item>
<el-form-item label="评分" prop="ratingValue" :rules="[{ required: true, message: '请输入评分', trigger: 'blur' }]">
<el-input-number v-model="formData.ratingValue" :min="1" :max="10" :precision="1" />
</el-form-item>
<!--表单结束===============================================================================================================================-->
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="state.dialogVisible = false">取消</el-button>
<el-button type="primary" @click="saveTransaction(formRef)">保存</el-button>
</div>
</el-dialog>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
//
import { UploadProps } from 'element-plus'
import type { FormInstance } from 'element-plus'
const formRef = ref<FormInstance>()
const state = reactive({ const state = reactive({
route:"sys/comment", route:"sys/order",
dialogVisible:false, dialogVisible:false,
getList: [],// getList: [],//
query:{ query:{
@ -154,20 +77,6 @@ const state = reactive({
} }
}) })
// 1990-2015
const years = [];
for (let year = 1990; year <= 2015; year++) {
years.push(year.toString());
}
const handleAvatarSuccess: UploadProps['onSuccess'] = (
response,
uploadFile
) => {
formData.largePic = URL.createObjectURL(uploadFile.raw!)
}
//
let formData = reactive(<any>{})
// //
const init = () => { const init = () => {
adminRequest.get(`${state.route}/page`, { adminRequest.get(`${state.route}/page`, {
@ -175,40 +84,9 @@ const init = () => {
}).then((res:any) => { }).then((res:any) => {
state.getList = res.data.list state.getList = res.data.list
state.query.total = res.data.total state.query.total = res.data.total
console.log(state.getList) console.log(state.getList)
}) })
} }
//
const openAddDialog = () => {
formData = {}
state.dialogVisible = true
}
//
const edit = (row: any) => {
formData = row
state.dialogVisible = true
}
//
const saveTransaction = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.validate((valid) => {
if (valid) {
if (formData.id) {
//
adminRequest.put(`${state.route}`, formData)
} else {
//
adminRequest.post(`${state.route}`, formData)
}
init()
state.dialogVisible = false
ElMessage.success("提交成功~")
}
})
}
// //

View File

@ -22,9 +22,9 @@
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="24"> <!-- <el-col :span="24">-->
<bar-chart /> <!-- <bar-chart />-->
</el-col> <!-- </el-col>-->
</el-row> </el-row>
</template> </template>

View File

@ -39,6 +39,7 @@
<el-table-column prop="view" label="预览" align="center" /> <el-table-column prop="view" label="预览" align="center" />
<el-table-column prop="tag" label="作者" align="center" /> <el-table-column prop="tag" label="作者" align="center" />
<el-table-column prop="sort" label="排序" align="center" /> <el-table-column prop="sort" label="排序" align="center" />
<!--列表结束--> <!--列表结束-->
<el-table-column label="操作" align="center" > <el-table-column label="操作" align="center" >
<template #default="scope"> <template #default="scope">
@ -63,30 +64,51 @@
/> />
</el-col> </el-col>
</el-row> </el-row>
<!-- 新增/编辑对话框 --> <!-- 新增/编辑对话框 -->
<el-dialog v-model="state.dialogVisible" title="新增" width="50%"> <el-dialog v-model="state.dialogVisible" title="新增" width="50%">
<el-form <el-form
:model="formData" :model="state.formData"
ref="formRef" ref="formRef"
label-width="100px" label-width="100px"
> >
<!-- 表单开始===============================================================================================================================--> <!-- 表单开始===============================================================================================================================-->
<el-form-item label="图片" prop="image" :rules="[{ required: true, message: '请插入图片', trigger: 'blur' }]"> <el-form-item label="图片" prop="image" :rules="[{ required: true, message: '请插入图片', trigger: 'blur' }]">
<image-upload @update:imageUrl="handleImageUrl" :image-url="state.formData.image"></image-upload> <image-upload @update:imageUrl="handleImageUrl" :image-url="state.formData.image"></image-upload>
</el-form-item> </el-form-item>
<el-form-item label="图书名称" prop="title" :rules="[{ required: true, message: '请输入图书名称', trigger: 'blur' }]"> <el-form-item label="图书名称" prop="title" :rules="[{ required: true, message: '请输入图书名称', trigger: 'blur' }]">
<el-input v-model="formData.title"/> <el-input v-model="state.formData.title"/>
</el-form-item>
<el-form-item label="作者" prop="tag" :rules="[{ required: true, message: '请输入作者', trigger: 'blur' }]">
<el-input v-model="state.formData.tag"/>
</el-form-item>
<el-form-item label="类别" prop="categoryId" :rules="[{ required: true, message: '请输入类别编号', trigger: 'blur' }]">
<el-select v-model="state.formData.categoryId" placeholder="请选择" style="width: 240px">
<el-option
v-for="item in state.cateList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="价格" prop="price" :rules="[{ required: true, message: '请输入价格', trigger: 'blur' }]">
<el-input v-model.number="state.formData.price"/>
</el-form-item>
<el-form-item label="库存数量" prop="stockQuantity" :rules="[{ required: true, message: '请输入商品库存数量', trigger: 'blur' }]">
<el-input v-model="state.formData.stockQuantity"/>
</el-form-item> </el-form-item>
<el-form-item label="排序" prop="sort" :rules="[{ required: true, message: '请输入排序', trigger: 'blur' }]">
<el-input v-model="state.formData.sort"/>
</el-form-item>
<el-form-item label="排行榜" prop="sort" :rules="[{ required: true, message: '请输入排行榜', trigger: 'blur' }]"> <el-form-item label="描述" prop="description" :rules="[{ required: true, message: '请输入描述', trigger: 'blur' }]">
<el-input-number v-model="state.formData.sort" :min="1" :max="500000" /> <e-editor :content="state.formData.description" @update:content="handleUrl" />
</el-form-item> </el-form-item>
<!--表单结束===============================================================================================================================--> <!--表单结束===============================================================================================================================-->
</el-form> </el-form>
@ -98,14 +120,13 @@
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
// //
import type {FormInstance, TabsPaneContext} from 'element-plus' import type {FormInstance, TabsPaneContext} from 'element-plus'
const formRef = ref<FormInstance>() const formRef = ref<FormInstance>()
const loading = ref(true) const loading = ref(true)
const state = reactive({ const state = reactive(<any>{
route:"sys/item", route:"sys/item",
getStatus:['上架','下架','库存警告','售空'],
getStatus:[ getStatus:[
{name:"上架",status:0}, {name:"上架",status:0},
{name:"下架",status:1}, {name:"下架",status:1},
@ -121,18 +142,19 @@ const state = reactive({
title:"", title:"",
status:0, status:0,
}, },
formData:{} formData:{},
cateList:[]
}) })
//
let formData = reactive(<any>{})
// //
function handleImageUrl(path: string) { function handleImageUrl(path: string) {
state.formData.path = path state.formData.image = path
} }
//
function handleUrl(content: string) {
state.formData.description = content
}
// //
const init = () => { const init = () => {
adminRequest.get(`${state.route}/page`, { adminRequest.get(`${state.route}/page`, {
@ -143,17 +165,25 @@ const init = () => {
}).finally(() => { }).finally(() => {
loading.value = false loading.value = false
}) })
adminRequest.get(`sys/categories/page`, {
params: state.query
}).then((res:any) => {
state.cateList = res.data.list
})
} }
// //
const openAddDialog = () => { const openAddDialog = () => {
formData = { state.formData = {
sort:1 sort:1
} }
state.dialogVisible = true state.dialogVisible = true
} }
// //
const edit = (row: any) => { const edit = (row: any) => {
formData = row state.formData = row
state.dialogVisible = true state.dialogVisible = true
} }
// //
@ -161,22 +191,21 @@ const saveTransaction = async (formEl: FormInstance | undefined) => {
if (!formEl) return if (!formEl) return
formEl.validate((valid) => { formEl.validate((valid) => {
if (valid) { if (valid) {
if (formData.id) { if (state.formData.id) {
// //
adminRequest.put(`${state.route}`, formData).then(() =>{ adminRequest.put(`${state.route}`, state.formData).then(() =>{
init() init()
state.dialogVisible = false state.dialogVisible = false
ElMessage.success("提交成功~") ElMessage.success("提交成功~")
}) })
} else { } else {
// //
adminRequest.post(`${state.route}`, formData).then(() =>{ adminRequest.post(`${state.route}`, state.formData).then(() =>{
init() init()
state.dialogVisible = false state.dialogVisible = false
ElMessage.success("提交成功~") ElMessage.success("提交成功~")
}) })
} }
} }
}) })
} }
@ -226,19 +255,6 @@ onMounted(() => {
border-color: var(--el-color-primary); border-color: var(--el-color-primary);
} }
.el-icon.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
text-align: center;
}
.avatar{
width: 178px;
height: 178px;
object-fit: cover;
}
</style> </style>
<route lang="json"> <route lang="json">
{ {

View File

@ -0,0 +1,175 @@
<!--用户详情-->
<template>
<el-tabs v-model="state.page.orderStatus" @tab-click="handleClick">
<el-tab-pane v-for="status in state.getOrderStatus" :label="status.name" :name="status.status">
<el-table
:data="state.getList"
style="width: 100%"
>
<el-table-column prop="id" label="编号" />
<el-table-column prop="item.title" label="商品名称" />
<el-table-column prop="price" label="图片" >
<template #default="{ row }">
<img :src="row.item.image" style="width: 100px; height: 100px;">
</template>
</el-table-column>
<el-table-column prop="price" label="购买单价" />
<el-table-column prop="quantity" label="购买数量" />
<el-table-column prop="totalAmount" label="成交总价" />
<el-table-column prop="createdTime" label="购买时间" width="220" />
<el-table-column prop="addressDTO.city" label="收货地址" width="220" />
<el-table-column label="操作" min-width="120">
<template #default="scope" >
<el-button link type="primary" size="small" v-if="state.page.orderStatus == 0" @click="update(scope.row,1)">开始发货</el-button>
<el-button link type="primary" size="small" v-if="state.page.orderStatus == 1" @click="update(scope.row,2)">确认收货</el-button>
<el-button link type="primary" size="small" v-if="state.page.orderStatus == 2" @click="update(scope.row,3)">我要评价</el-button>
<el-button link type="primary" size="small" v-if="state.page.orderStatus == 3" @click="del(scope.row.id)">删除订单</el-button>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
<el-dialog
v-model="dialogVisible"
title="我要评价"
width="500"
>
<el-form
ref="formRef"
style="max-width: 600px"
:model="state.orderForm"
label-width="auto"
label-position="top"
>
<el-form-item
prop="evaluate"
label="评论内容"
:rules="[
{
required: true,
message: '评论内容不能为空',
trigger: 'blur',
},
]"
>
<el-input v-model="state.orderForm.evaluate" :rows="4"
type="textarea"/>
</el-form-item>
<el-form-item
prop="score"
label="评分"
>
<el-rate v-model="state.orderForm.score" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="review(formRef)" >
</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
import { FormInstance, TabsPaneContext } from 'element-plus'
const formRef = ref<FormInstance>()
const state = reactive({
getOrderStatus:[
{name:"未发货",status:0},
{name:"已发货",status:1},
{name:"未评价",status:2},
{name:"已完成",status:3},
],
getList:[],
orderForm:{
score: 0
},
page:{
page:1,
limit:10,
order:'desc',
orderStatus:0,
}
})
const dialogVisible = ref(false)
/**
* 删除订单
* @param id
*/
const del = (id:any) => {
frontRequest.delete(`/sys/order/${id}`).then(res =>{
toast.success("删除成功~")
getList()
})
}
/**
* 获取列表数据
*/
function getList() {
adminRequest.get("/sys/order/page",{ params: state.page}).then(res =>{
state.getList = res.data.list;
})
}
const handleClick = (tab: TabsPaneContext, event: Event) => {
const selectedStatus = state.getOrderStatus[tab.index].status;
state.page.orderStatus = selectedStatus;
getList()
}
const update = (data:any,status:number) => {
// if(status === 4){
// dialogVisible.value = true
// state.orderForm = {...data,evaluate:''}
// state.orderForm.status = 4
// return
// }
data.orderStatus = status
adminRequest.put("/sys/order",data).then(() =>{
toast.success("修改成功~")
getList()
})
}
onMounted(()=>{
getList()
})
const review = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.validate((valid) => {
if (valid) {
updateOrderItemApi(state.orderForm).then(res =>{
toast.success("修改成功~")
dialogVisible.value = false
getList()
})
}
})
}
</script>
<style scoped>
</style>
<route lang="json">
{
"meta": {
"layout": "admin"
}
}
</route>

View File

@ -18,7 +18,6 @@
<!-- 列表结开始--> <!-- 列表结开始-->
<el-table-column prop="id" label="id"/> <el-table-column prop="id" label="id"/>
<el-table-column prop="username" label="账号"/> <el-table-column prop="username" label="账号"/>
<el-table-column prop="password" label="密码"/>
<el-table-column prop="createDate" label="创建时间"/> <el-table-column prop="createDate" label="创建时间"/>
<el-table-column prop="nickName" label="昵称"/> <el-table-column prop="nickName" label="昵称"/>
<el-table-column prop="introduce" label="介绍"/> <el-table-column prop="introduce" label="介绍"/>
@ -48,30 +47,26 @@
<!-- 新增/编辑对话框 --> <!-- 新增/编辑对话框 -->
<el-dialog v-model="state.dialogVisible" title="新增" width="50%"> <el-dialog v-model="state.dialogVisible" title="新增" width="50%">
<el-form <el-form
:model="formData" :model="state.formData"
ref="formRef" ref="formRef"
label-width="100px" label-width="100px"
> >
<!-- 表单开始===============================================================================================================================--> <!-- 表单开始===============================================================================================================================-->
<el-form-item label="账号" prop="username" :rules="[{ required: true, message: '请输入账号', trigger: 'blur' }]"> <el-form-item label="账号" prop="username" :rules="[{ required: true, message: '请输入账号', trigger: 'blur' }]">
<el-input v-model="formData.username"/> <el-input v-model="state.formData.username"/>
</el-form-item> </el-form-item>
<el-form-item label="密码" prop="password" :rules="[{ required: true, message: '请输入密码', trigger: 'blur' }]"> <el-form-item label="密码" >
<el-input v-model="formData.password"/> <el-input v-model="state.formData.password"/>
</el-form-item> </el-form-item>
<el-form-item label="昵称" prop="nickName" :rules="[{ required: true, message: '请输入昵称', trigger: 'blur' }]"> <el-form-item label="昵称" prop="nickName" :rules="[{ required: true, message: '请输入昵称', trigger: 'blur' }]">
<el-input v-model="formData.nickName"/> <el-input v-model="state.formData.nickName"/>
</el-form-item> </el-form-item>
<el-form-item label="介绍" prop="introduce" :rules="[{ required: true, message: '请输入介绍', trigger: 'blur' }]"> <el-form-item label="介绍" prop="introduce" :rules="[{ required: true, message: '请输入介绍', trigger: 'blur' }]">
<el-input v-model="formData.introduce"/> <el-input v-model="state.formData.introduce"/>
</el-form-item> </el-form-item>
<!--表单结束===============================================================================================================================--> <!--表单结束===============================================================================================================================-->
</el-form> </el-form>
@ -94,7 +89,8 @@ const state = reactive({
page: 1, // page: 1, //
limit: 10, // limit: 10, //
username: "", username: "",
} },
formData:{}
}) })
// 1990-2015 // 1990-2015
@ -103,8 +99,6 @@ for (let year = 1990; year <= 2015; year++) {
years.push(year.toString()); years.push(year.toString());
} }
//
let formData = reactive(<any>{})
// //
const init = () => { const init = () => {
adminRequest.get(`${state.route}/page`, { adminRequest.get(`${state.route}/page`, {
@ -116,12 +110,14 @@ const init = () => {
} }
// //
const openAddDialog = () => { const openAddDialog = () => {
formData = {} state.formData = {}
state.dialogVisible = true state.dialogVisible = true
} }
// //
const edit = (row: any) => { const edit = (row: any) => {
formData = row state.formData = row
delete state.formData.password
state.dialogVisible = true state.dialogVisible = true
} }
@ -130,12 +126,12 @@ const saveTransaction = (formEl: FormInstance | undefined) => {
if (!formEl) return if (!formEl) return
formEl.validate((valid) => { formEl.validate((valid) => {
if (valid) { if (valid) {
if (formData.id) { if (state.formData.id) {
// //
adminRequest.put(`${state.route}`, formData) adminRequest.put(`${state.route}`, state.formData)
} else { } else {
// //
adminRequest.post(`${state.route}`, formData) adminRequest.post(`${state.route}`, state.formData)
} }
init() init()
state.dialogVisible = false state.dialogVisible = false

View File

@ -0,0 +1,89 @@
<!--用户详情-->
<template>
<el-tabs v-model="state.activeName" >
<el-tab-pane v-for="status in state.getOrderStatus" :label="status.name" :name="status.status">
<el-table :data="state.getList">
<!-- 列表结开始-->
<el-table-column prop="id" label="编号" align="center" width="160" />
<el-table-column prop="title" label="名称" align="center" />
<el-table-column prop="largePic" label="图片" align="center" >
<template #default="{ row }">
<!-- 点击图片后显示弹框预览 -->
<el-image
:src="row.image"
fit="cover"
:preview-src-list="[row.image]"
:preview-teleported="true"
/>
</template>
</el-table-column>
<el-table-column prop="price" label="价格" align="center" />
<el-table-column prop="stockQuantity" label="库存" align="center" />
<el-table-column prop="tag" label="作者" align="center" width="160"/>
<!--列表结束-->
<el-table-column label="操作" align="center" width="160" >
<template #default="scope">
<el-button @click="del(scope.row.id)" type="danger" size="small">取消</el-button>
<el-button @click="to(scope.row.id)" size="small">去购买</el-button>
</template>
</el-table-column>
<template v-slot:empty>
<el-empty description="数据去外太空了~" />
</template>
</el-table>
</el-tab-pane>
</el-tabs>
</template>
<script setup lang="ts">
import { useRouter } from 'vue-router'
const router = useRouter()
import { reactive } from 'vue'
const state = reactive({
activeName:1,
getOrderStatus:[
{name:"全部",status:1},
],
getList:[]
})
/**
* 跳转
*/
const to = (id:number) => {
router.push(`/info/${id}`)
}
/**
* 获取列表数据
*/
function init() {
frontRequest.get("/api/item/list").then(res =>{
state.getList = res.data
})
}
const del = (id:number) => {
frontRequest.post("/api/behavior/delete",{itemId:id,type:1}).then(res =>{
ElMessage.success("收藏成功")
init()
})
init()
}
onMounted(()=>{
init()
})
</script>
<style scoped>
</style>
<route lang="json">
{
"meta": {
"layout": "frontUserInfo"
}
}
</route>

View File

@ -25,7 +25,6 @@ onMounted(()=>{
router.push("/login") router.push("/login")
} }
}) })
</script> </script>
<style scoped> <style scoped>

View File

@ -15,13 +15,6 @@
<div class="module_text">密码</div> <div class="module_text">密码</div>
<input class="module_input" type="password" placeholder="输入密码" v-model="login.password" /> <input class="module_input" type="password" placeholder="输入密码" v-model="login.password" />
</div> </div>
<!-- <div class="module_m">-->
<!-- <div class="module_text">验证码</div>-->
<!-- <div class="module_code">-->
<!-- <input class="module_code_input" type="text" placeholder="输入验证码" v-model="login.captcha" />-->
<!-- <img class="module_code_img" :src="state.captchaUrl" @click="getCaptcha">-->
<!-- </div>-->
<!-- </div>-->
<div class="module_m"> <div class="module_m">
<div class="module_code"> <div class="module_code">
<el-radio-group v-model="state.role" class="ml-4"> <el-radio-group v-model="state.role" class="ml-4">
@ -30,9 +23,8 @@
</el-radio-group> </el-radio-group>
</div> </div>
</div> </div>
<!-- <div class="module_radio"><input type="radio"/>记住密码 </div>-->
<div class="forgetpwd" @click="router.push('/register')">没有密码吗</div> <div class="forgetpwd" @click="router.push('/register')">没有密码吗</div>
<button class="module_button" :disabled="state.loading" @click="onLogin">登录</button> <el-button class="module_button" @click="onLogin">登录</el-button>
</div> </div>
</div> </div>
</div> </div>
@ -52,8 +44,7 @@ const state = reactive({
const login = reactive({ const login = reactive({
username: '', username: '',
password: '', password: '',
captcha: '', })
uuid: '' })
const onLogin = () => { const onLogin = () => {
state.loading = true state.loading = true
if (state.role) { if (state.role) {
@ -68,40 +59,18 @@ const onLogin = () => {
ElMessage.success("登录成功~") ElMessage.success("登录成功~")
}) })
}).catch(() => {
state.loading = false
onRefreshCode()
}) })
} else { } else {
frontRequest.post("/api/user/login", login).then(response =>{ frontRequest.post("/api/user/login", login).then(response =>{
const user = userStore() const user = userStore()
user.frontToken = response.data.token user.frontToken = response.data.token
frontRequest.get("/api/user/userInfo").then(response =>{ user.frontIsLogin = true
user.frontIsLogin = true ElMessage.success("登录成功~")
user.frontUserInfo = response.data router.push('/')
ElMessage.success("登录成功~")
router.push('/')
})
}) })
} }
} }
/**
* 获取验证码
*/
const getCaptchaUrl = () => {
login.uuid = getUuid()
login.captcha = ''
state.captchaUrl = import.meta.env.VITE_ADMIN_API_BASE_URL + `/captcha?uuid=${login.uuid}`
}
const onRefreshCode = () => {
getCaptchaUrl()
}
onMounted(() => {
getCaptchaUrl()
})
</script> </script>
<style scoped> <style scoped>

View File

@ -1,74 +1,164 @@
<!--用户详情--> <!--用户详情-->
<template> <template>
<el-tabs v-model="state.page.orderStatus" @tab-click="handleClick">
<el-tabs v-model="state.activeName" @tab-click="handleClick">
<el-tab-pane v-for="status in state.getOrderStatus" :label="status.name" :name="status.status"> <el-tab-pane v-for="status in state.getOrderStatus" :label="status.name" :name="status.status">
<el-table :data="state.getList"> <el-table
<!-- 列表结开始--> :data="state.getList"
<el-table-column prop="id" label="编号" align="center" /> style="width: 100%"
<el-table-column prop="title" label="电影名称" align="center" /> >
<el-table-column prop="year" label="上映时间" align="center" /> <el-table-column prop="id" label="编号" />
<el-table-column prop="largePic" label="图片" align="center" > <el-table-column prop="item.title" label="商品名称" />
<el-table-column prop="price" label="图片" >
<template #default="{ row }"> <template #default="{ row }">
<!-- 点击图片后显示弹框预览 --> <img :src="row.item.image" style="width: 100px; height: 100px;">
<el-image
:src="row.largePic"
fit="cover"
:preview-src-list="row.largePic.split(',')"
:preview-teleported="true"
/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="country" label="国家" align="center" /> <el-table-column prop="price" label="购买单价" />
<el-table-column prop="movieType" label="电影类型" align="center" /> <el-table-column prop="quantity" label="购买数量" />
<el-table-column prop="director" label="导演" align="center" /> <el-table-column prop="totalAmount" label="成交总价" />
<el-table-column prop="actor" label="主演" align="center" /> <el-table-column prop="createdTime" label="购买时间" width="220" />
<el-table-column prop="ratingValue" label="评分" align="center" /> <el-table-column label="操作" min-width="120">
<el-table-column prop="ratingCount" label="评分人数" align="center" /> <template #default="scope" >
<!--列表结束--> <el-button link type="primary" size="small" v-if="state.page.orderStatus == 1" @click="update(scope.row,2)">确认收货</el-button>
<el-table-column label="操作" align="center" > <el-button link type="primary" size="small" v-if="state.page.orderStatus == 2" @click="update(scope.row,3)">我要评价</el-button>
<template #default="scope"> <el-button link type="primary" size="small" v-if="state.page.orderStatus == 3" @click="del(scope.row.id)">删除订单</el-button>
<el-button @click="del(scope.row.id)" type="danger" size="small">取消</el-button>
</template> </template>
</el-table-column> </el-table-column>
<template v-slot:empty>
<el-empty description="数据去外太空了~" />
</template>
</el-table> </el-table>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
<el-dialog
v-model="dialogVisible"
title="我要评价"
width="500"
>
<el-form
ref="formRef"
style="max-width: 600px"
:model="state.orderForm"
label-width="auto"
label-position="top"
>
<el-form-item
prop="evaluate"
label="评论内容"
:rules="[
{
required: true,
message: '评论内容不能为空',
trigger: 'blur',
},
]"
>
<el-input v-model="state.orderForm.evaluate" :rows="4"
type="textarea"/>
</el-form-item>
<el-form-item
prop="score"
label="评分"
>
<el-rate v-model="state.orderForm.score" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="review(formRef)" >
</el-button>
</div>
</template>
</el-dialog>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive } from 'vue' import { reactive } from 'vue'
import { FormInstance, TabsPaneContext } from 'element-plus'
const formRef = ref<FormInstance>()
const state = reactive({ const state = reactive({
activeName:1,
getOrderStatus:[ getOrderStatus:[
{name:"全部",status:1}, {name:"未发货",status:0},
{name:"已发货",status:1},
{name:"未评价",status:2},
{name:"已完成",status:3},
], ],
getList:[] getList:[],
orderForm:{
score: 0
},
page:{
page:1,
limit:9999,
order:'desc',
orderStatus:0,
}
}) })
const dialogVisible = ref(false)
/**
* 删除订单
* @param id
*/
const del = (id:any) => {
frontRequest.delete(`/api/order/${id}`).then(res =>{
toast.success("删除成功~")
getList()
})
}
/** /**
* 获取列表数据 * 获取列表数据
*/ */
function init() { function getList() {
frontRequest.get("/api/item/list").then(res =>{ frontRequest.get("/api/order/page",{ params: state.page}).then(res =>{
state.getList = res.data state.getList = res.data.list;
})
}
const del = (id:number) => {
frontRequest.post("/api/behavior/delete",{itemId:id,type:1}).then(res =>{
ElMessage.success("收藏成功")
init()
})
init()
}
})
}
const handleClick = (tab: TabsPaneContext, event: Event) => {
const selectedStatus = state.getOrderStatus[tab.index].status;
state.page.orderStatus = selectedStatus;
getList()
}
onMounted(()=>{ onMounted(()=>{
init() getList()
}) })
const update = (data:any,status:number) => {
// if(status === 4){
// dialogVisible.value = true
// state.orderForm = {...data,evaluate:''}
// state.orderForm.status = 4
// return
// }
data.orderStatus = status
frontRequest.put("/api/order",data).then(res =>{
toast.success("修改成功~")
getList()
})
}
const review = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.validate((valid) => {
if (valid) {
updateOrderItemApi(state.orderForm).then(res =>{
toast.success("修改成功~")
dialogVisible.value = false
getList()
})
}
})
}
</script> </script>

View File

@ -21,14 +21,6 @@
<input class="module_input" type="password" placeholder="再次输入密码" v-model="register.confirmPassword" /> <input class="module_input" type="password" placeholder="再次输入密码" v-model="register.confirmPassword" />
</div> </div>
</div> </div>
<!-- <div class="module_m">-->
<!-- <div class="module_text">验证码</div>-->
<!-- <div class="module_code">-->
<!-- <input class="module_code_input" type="text" placeholder="输入验证码" v-model="vftcode" />-->
<!-- <img class="module_code_img" src="/codeimg.png" @click="onCode">-->
<!-- </div>-->
<!-- </div>-->
<!-- <div class="module_radio"><input type="radio"/>记住密码 </div>-->
<div class="forgetpwd" @click="router.push('/login')">有账号</div> <div class="forgetpwd" @click="router.push('/login')">有账号</div>
<button class="module_button" @click="onRegister">注册</button> <button class="module_button" @click="onRegister">注册</button>
</div> </div>
@ -42,7 +34,7 @@ const register = reactive({
username: '', username: '',
password: '', password: '',
confirmPassword: '', confirmPassword: '',
captcha: '', nickName: '',
uuid: '' uuid: ''
}) })

View File

@ -1,67 +1,77 @@
<!--用户详情--> <!--用户详情-->
<template> <template>
<el-form
ref="formRef" <el-card >
style="max-width: 600px" <template #header>
:model="state.userInfo" <div class="card-header">
label-width="auto" <span>个人信息</span>
> </div>
<el-form-item </template>
prop="username" <el-form
label="用户名" ref="formRef"
:rules="[ style="max-width: 600px"
:model="state.userInfo"
label-width="auto"
>
<el-form-item
prop="username"
label="用户名"
:rules="[
{ {
required: true, required: true,
message: '用户名不能为空', message: '用户名不能为空',
trigger: 'blur', trigger: 'blur',
}, },
]" ]"
> >
<el-input v-model="state.userInfo.username" /> <el-input v-model="state.userInfo.username" />
</el-form-item> </el-form-item>
<el-form-item <el-form-item
prop="nickName" prop="nickName"
label="用户昵称" label="用户昵称"
:rules="[ :rules="[
{ {
required: true, required: true,
message: '用户昵称不能为空', message: '用户昵称不能为空',
trigger: 'blur', trigger: 'blur',
} }
]" ]"
> >
<el-input v-model="state.userInfo.nickName" /> <el-input v-model="state.userInfo.nickName" />
</el-form-item> </el-form-item>
<el-form-item <el-form-item
prop="password" prop="password"
label="密码" label="密码"
:rules="[ :rules="[
{ {
required: true, required: true,
message: '密码不能为空', message: '密码不能为空',
trigger: 'blur', trigger: 'blur',
}, },
]" ]"
> >
<el-input v-model="state.userInfo.password" /> <el-input v-model="state.userInfo.password" />
</el-form-item> </el-form-item>
<el-form-item <el-form-item
prop="confirmPassword" prop="confirmPassword"
label="确认密码" label="确认密码"
:rules="[ :rules="[
{ {
required: true, required: true,
message: '确认密码不能为空', message: '确认密码不能为空',
trigger: 'blur', trigger: 'blur',
}, },
]" ]"
> >
<el-input v-model="state.userInfo.confirmPassword" /> <el-input v-model="state.userInfo.confirmPassword" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="submitForm(formRef)">提交</el-button> <el-button type="primary" @click="submitForm(formRef)" style="width: 260px">提交</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-card>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import type { FormInstance } from 'element-plus' import type { FormInstance } from 'element-plus'

View File

@ -38,15 +38,15 @@ export const getAdminList = () => {
"icon": "ChatLineRound" // 评论管理 "icon": "ChatLineRound" // 评论管理
}, },
{ {
"path": "/admin/topic", "path": "/admin/order",
"name": "话题管理", "name": "订单管理",
"icon": "Edit" // 更换为 Edit 图标 "icon": "Edit" // 更换为 Edit 图标
}, },
{ // {
"path": "/admin/leaderboard", // "path": "/admin/leaderboard",
"name": "文创管理", // "name": "文创管理",
"icon": "Trophy" // 更换为 Trophy 图标 // "icon": "Trophy" // 更换为 Trophy 图标
}, // },
{ {
"path": "/admin/user", "path": "/admin/user",
"name": "用户管理", "name": "用户管理",
@ -73,16 +73,16 @@ export const getFrontList = () => {
"name": "排行榜", "name": "排行榜",
"icon": "House", "icon": "House",
}, },
{ // {
"path": "/topic", // "path": "/topic",
"name": "话题专区", // "name": "话题专区",
"icon": "House", // "icon": "House",
}, // },
{ // {
"path": "/cultural", // "path": "/cultural",
"name": "文创专区", // "name": "文创专区",
"icon": "House", // "icon": "House",
}, // },
] ]
return routes; return routes;
} }