添加订单表

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
@Tag(name = "登录管理")
@ -51,9 +50,9 @@ public class LoginController {
}
@PostMapping("login")
@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());
// if (!flag) {

View File

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

View File

@ -95,7 +95,7 @@ public class ItemController {
public Result save(@RequestBody ItemDTO dto) {
//效验数据
ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class);
dto.setImage(uploadUrl + dto.getImage());
dto.setImage(dto.getImage().replace(uploadUrl,""));
itemService.save(dto);
return new Result();
}
@ -104,7 +104,7 @@ public class ItemController {
@Operation(summary = "修改")
public Result update(@RequestBody ItemDTO dto) { //效验数据
ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class);
dto.setImage(uploadUrl + dto.getImage());
dto.setImage(dto.getImage().replace(uploadUrl,""));
itemService.update(dto);
return new Result();
}
@ -113,7 +113,6 @@ public class ItemController {
@Operation(summary = "删除")
@LogOperation("删除")
public Result delete(@PathVariable Long id) {
Long[] ids = new Long[]{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.DefaultGroup;
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.entity.FrontUserEntity;
import io.modules.item.service.AddressService;
import io.modules.item.service.ItemService;
import io.modules.item.service.OrderService;
import io.swagger.v3.oas.annotations.Operation;
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.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
@ -31,10 +40,23 @@ import java.util.Map;
@RestController
@RequestMapping("sys/order")
@Tag(name="订单表")
@CrossOrigin
public class OrderController {
@Autowired
private OrderService orderService;
@Autowired
private ItemService itemService;
@Autowired
private AddressService addressService;
@Autowired
private FrontUserDao frontUserDao;
@Value("${upload.url}")
private String uploadUrl;
@GetMapping("page")
@Operation(summary = "分页")
@Parameters({
@ -45,7 +67,23 @@ public class OrderController {
})
public Result<PageData<OrderDTO>> page(@Parameter(hidden = true) @RequestParam Map<String, Object> 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);
}

View File

@ -3,9 +3,9 @@ spring:
druid:
#MySQL
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
password: x6dbfGN4s6YjcX8P
password: 123456
initial-size: 10
max-active: 100
min-idle: 10

View File

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

View File

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

View File

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

View File

@ -1,5 +1,7 @@
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.SchemaProperty;
import lombok.Data;
@ -40,7 +42,8 @@ public class OrderDTO implements Serializable {
@SchemaProperty(name = "订单总金额")
private BigDecimal totalAmount;
private BigDecimal price;
private AddressDTO addressDTO;
@SchemaProperty(name = "支付状态")
private Integer paymentStatus;
@ -51,4 +54,16 @@ public class OrderDTO implements Serializable {
private Date createdTime;
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
public class ProvinceTree {
private Long id;
private String province;
private List<CityTree> cityTrees;
private Long value;
private String label;
private List<CityTree> children;
}

View File

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

View File

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

View File

@ -35,6 +35,7 @@ public class OrderServiceImpl extends CrudServiceImpl<OrderDao, OrderEntity, Ord
String orderStatus = (String)params.get("orderStatus");
String paymentStatus = (String)params.get("paymentStatus");
String userId = (String)params.get("userId");
QueryWrapper<OrderEntity> wrapper = new QueryWrapper<>();
wrapper.eq(StrUtil.isNotBlank(id), "id", id);
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<ProvinceTree> provinceTrees = new ArrayList<>();
for (ProvinceEntity province : provinces) {
ProvinceTree provinceTree = new ProvinceTree();
provinceTree.setId(province.getId());
provinceTree.setProvince(province.getProvince());
provinceTree.setCityTrees(getCityTree(province.getProvinceId())); // 获取该省的城市树
provinceTree.setValue(province.getId());
provinceTree.setLabel(province.getProvince());
provinceTree.setChildren(getCityTree(province.getProvinceId())); // 获取该省的城市树
provinceTrees.add(provinceTree);
}
return provinceTrees;
@ -71,9 +70,9 @@ public class ProvinceServiceImpl extends CrudServiceImpl<ProvinceDao, ProvinceEn
List<CityTree> cityTrees = new ArrayList<>();
for (CityEntity city : cities) {
CityTree cityTree = new CityTree();
cityTree.setId(city.getId());
cityTree.setCity(city.getCity());
cityTree.setAreaTrees(getAreaTree(city.getCityId())); // 获取该城市的地区树
cityTree.setValue(city.getId());
cityTree.setLabel(city.getCity());
cityTree.setChildren(getAreaTree(city.getCityId())); // 获取该城市的地区树
cityTrees.add(cityTree);
}
return cityTrees;
@ -87,8 +86,8 @@ public class ProvinceServiceImpl extends CrudServiceImpl<ProvinceDao, ProvinceEn
List<AreaTree> areaTrees = new ArrayList<>();
for (AreaEntity area : areas) {
AreaTree areaTree = new AreaTree();
areaTree.setId(area.getId());
areaTree.setArea(area.getArea());
areaTree.setValue(area.getId());
areaTree.setLabel(area.getArea());
areaTrees.add(areaTree);
}
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 io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
@ -30,6 +28,7 @@ import java.util.Map;
@RestController
@RequestMapping("api/address")
@Tag(name="收货地址表")
@CrossOrigin
public class AddressController {
@Autowired
private AddressService addressService;

View File

@ -24,6 +24,7 @@ import java.util.Map;
@RestController
@RequestMapping("api/area")
@Tag(name="地区信息")
@CrossOrigin
public class AreaController {
@Autowired
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);
List<ItemDTO> list = page.getList().stream().map(e -> {
e.setImage(uploadUrl + e.getImage());
// 获取评价信息
List<OrderDTO> orderEntityList = orderService.getCommintList(e.getId() );
e.setOrderEntityList(orderEntityList);
@ -79,14 +78,11 @@ public class ItemController {
@Operation(summary = "查询收藏")
public Result<List<ItemEntity>> list(@Parameter(hidden = true) @RequestAttribute("userId") Long userId){
List<ItemEntity> page = itemService.listUser(userId);
// List<ItemDTO> list = page.getList().stream().map(e -> {
// e.setLargePic(uploadUrl + "item/" + e.getLargePic());
// e.setNormalPic(uploadUrl + "item/n_" + e.getNormalPic());
// return e;
// }).collect(Collectors.toList());
// page.setList(list);
return new Result<List<ItemEntity>>().ok(page);
List<ItemEntity> list = page.stream().map(e -> {
e.setImage(uploadUrl + e.getImage());
return e;
}).collect(Collectors.toList());
return new Result<List<ItemEntity>>().ok(list);
}
@ -119,11 +115,16 @@ public class ItemController {
@GetMapping("{id}")
@Operation(summary = "信息")
public Result<ItemDTO> get(@PathVariable("id") Long id){
//获取详情
ItemDTO data = itemService.get(id);
data.setImage(uploadUrl + data.getImage());
data.setImage(data.getImage().replace(uploadUrl,""));
// 添加预览
data.setView(data.getView() + 1);
// 更新
itemService.update(data);
data.setImage(uploadUrl + data.getImage());
//是否收藏
data.setIsFavorite(userBehaviorService.getIsFavorite(data.getId(),1));
return new Result<ItemDTO>().ok(data);
@ -141,7 +142,8 @@ public class ItemController {
@Operation(summary = "修改")
public Result update(@RequestBody ItemDTO dto){ //效验数据
ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class);
dto.setImage(uploadUrl + dto.getImage());
dto.setImage(dto.getImage().replace(uploadUrl,""));
itemService.update(dto);
return new Result();
}
@ -153,7 +155,4 @@ public class ItemController {
itemService.delete(ids);
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.DefaultGroup;
import io.common.validator.group.UpdateGroup;
import io.modules.item.dto.ItemDTO;
import io.modules.item.dto.OrderDTO;
import io.modules.item.service.ItemService;
import io.modules.item.service.OrderService;
import io.swagger.v3.oas.annotations.Operation;
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.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 订单表
*
* @author Mark #
* @since 1.0.0 2025-02-14
*/
@RestController
@RequestMapping("api/order")
@RequestMapping("/api/order")
@Tag(name="订单表")
@CrossOrigin
public class OrderController {
@Autowired
private OrderService orderService;
@Autowired
private ItemService itemService;
@Value("${upload.url}")
private String uploadUrl;
@GetMapping("page")
@Operation(summary = "分页")
@Parameters({
@ -45,8 +55,18 @@ public class OrderController {
})
@Login
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);
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);
}
@ -59,9 +79,9 @@ public class OrderController {
@PostMapping
@Operation(summary = "保存")
public Result save(@RequestBody OrderDTO dto){
//效验数据
ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class);
@Login
public Result save(@RequestBody OrderDTO dto,@Parameter(hidden = true) @RequestAttribute("userId") Long userId){
dto.setUserId(userId);
orderService.save(dto);
return new Result();
}
@ -69,22 +89,17 @@ public class OrderController {
@PutMapping
@Operation(summary = "修改")
public Result update(@RequestBody OrderDTO dto){
//效验数据
ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class);
orderService.update(dto);
return new Result();
}
@DeleteMapping
@DeleteMapping("{id}")
@Operation(summary = "删除")
public Result delete(@RequestBody Long[] ids){
public Result delete(@PathVariable Long id) {
Long[] ids = new Long[]{id};
//效验数据
AssertUtils.isArrayEmpty(ids, "id");
orderService.delete(ids);
return new Result();
}
}

View File

@ -6,9 +6,9 @@ spring:
datasource:
druid:
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
password: x6dbfGN4s6YjcX8P
password: 123456
initial-size: 10
max-active: 100
min-idle: 10
@ -33,7 +33,7 @@ spring:
multi-statement-allow: true
web:
resources:
static-locations: "file:F:/2025/bookstore-springboot-vue/admin-ui/upload/"
static-locations: "file:D:/2025/bookstore-springboot-vue/admin-ui/upload/"
upload:
path: F:\2025\bookstore-springboot-vue\admin-ui\upload
path: D:\2025\bookstore-springboot-vue\admin-ui\upload
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_APP_TITLE = 电影系统
VITE_APP_TITLE = 图书系统
# markdown 渲染支持
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"
>
<img v-if="state.imageUrl" :src="state.imageUrl" class="avatar" />
<el-icon v-else class="avatar-uploader-icon">
<Plus />
</el-icon>
</el-upload>
{{state.imageUrl}}
</div>
</template>
<script setup lang="ts">
@ -39,7 +42,6 @@ watch(
}
)
onMounted(()=>{
console.log(props.imageUrl)
if (props.imageUrl){
state.imageUrl = props.imageUrl
}
@ -62,8 +64,9 @@ const handleSuccess: UploadProps['onSuccess'] = (
state.imageUrl = response.data.path
ElMessage.success('上传成功')
console.log("fanhui1",response)
console.log("fanhui2",response.data.path)
// emit
emit('update:imageUrl', response.data.absolute);
emit('update:imageUrl', response.data.path);
}
</script>

View File

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

View File

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

View File

@ -3,21 +3,16 @@
<el-row :gutter="20" class="info">
<el-col :span="10">
<!-- 详情图片-->
<el-image :src="state.info.largePic" fit="contain" />
<el-image :src="state.info.image" fit="contain" />
</el-col>
<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.country"> <span style="font-weight: 700">导演: </span> {{state.info.director}} </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.country"> <span style="font-weight: 700">电影评分: </span> {{state.info.ratingValue}} </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="introduction" v-if="state.info.tag"> <span style="font-weight: 700">作者:</span> {{state.info.tag}} </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.price">
<span style="font-weight: 700">价格:</span> <span style="color:red">{{state.info.price}} </span> </div>
<!--操作-->
<div class="operate">
<!-- 加入购物车-->
@ -37,7 +32,7 @@
title="购买"
>
<el-form
ref="buyFormRef"
ref="formRef"
style="max-width: 600px"
:model="state.buyForm"
label-width="auto"
@ -47,7 +42,7 @@
<el-input disabled v-model="state.buyForm.title" />
</el-form-item>
<el-form-item prop="title" label="商品单价" >
<el-form-item prop="title" label="商品单价(元)" >
<el-input disabled v-model="state.buyForm.price" />
</el-form-item>
@ -57,7 +52,18 @@
</el-form-item>
<el-form-item prop="title" label="总价" >
<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-button type="primary" @click="buySubmitForm(formRef)">确定</el-button>
@ -70,26 +76,18 @@ import { reactive } from 'vue'
import type { FormInstance } from 'element-plus'
const buyDrawer = ref(false)
const formRef = ref<FormInstance>()
import { useRoute } from 'vue-router';
const route = useRoute();
const itemId = route.params.id;
const state =reactive(<any>{
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,
},
info:{},
buyForm:{
id:null,
itemId:itemId,
title:"",
quantity:1,
total:0
}
totalAmount:0
},
cateList:[]
})
// route.params.id
@ -104,6 +102,11 @@ function init() {
frontRequest.get(`/api/item/${itemId}`).then(response =>{
state.info = response.data
})
frontRequest.get(`api/address/page`).then(response =>{
state.cateList = response.data.list
})
}
onMounted(()=>{
init()
@ -133,9 +136,11 @@ const buySubmitForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.validate((valid) => {
if (valid) {
console.log('submit!')
} else {
console.log('error submit!')
console.log(state.buyForm)
frontRequest.post("/api/order",state.buyForm).then(res =>{
ElMessage.success("购买成功")
buyDrawer.value = false
})
}
})
}
@ -148,10 +153,17 @@ const handleBuy = () => {
state.buyForm.title = state.info.title
state.buyForm.id = state.info.id
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 = () => {
state.buyForm.total = state.info.price * state.buyForm.quantity
state.buyForm.totalAmount = (state.info.price * state.buyForm.quantity).toFixed(2);
}
</script>
<style scoped>

View File

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

View File

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

View File

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

View File

@ -34,8 +34,10 @@ const state = reactive({
activeIndex:'/user',
userMenu:[
{name: '个人中心', path: '/user'},
{name: '用户收藏', path: '/order'},
{name: '用户文创', path: '/fronttopic'},
{name: '收货地址', path: '/address'},
{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-table :data="state.getList">
<!-- 列表结开始-->
<el-table-column prop="id" label="编号" align="center" width="120px"/>
<el-table-column prop="itemDTO.title" label="电影名称" align="center" width="120px"/>
<el-table-column prop="nickName" label="用户昵称" align="center" width="120px" />
<el-table-column prop="itemDTO.largePic" label="电影图片" align="center" width="100" >
<el-table-column prop="item.id" label="编号" align="center" width="120px"/>
<el-table-column prop="item.title" 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" >
<template #default="{ row }">
<!-- 点击图片后显示弹框预览 -->
<el-image
:src="row.itemDTO.largePic"
:src="row.item.image"
fit="cover"
/>
</template>
</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">
<template #default="scope">
<div style="width: 100%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;">
@ -36,7 +36,6 @@
</div>
</template>
</el-table-column>
<!--列表结束-->
<el-table-column label="操作" align="center" width="120px">
@ -60,89 +59,13 @@
</el-col>
</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>
</template>
<script setup lang="ts">
//
import { UploadProps } from 'element-plus'
import type { FormInstance } from 'element-plus'
const formRef = ref<FormInstance>()
const state = reactive({
route:"sys/comment",
route:"sys/order",
dialogVisible:false,
getList: [],//
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 = () => {
adminRequest.get(`${state.route}/page`, {
@ -175,40 +84,9 @@ const init = () => {
}).then((res:any) => {
state.getList = res.data.list
state.query.total = res.data.total
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-col :span="24">
<bar-chart />
</el-col>
<!-- <el-col :span="24">-->
<!-- <bar-chart />-->
<!-- </el-col>-->
</el-row>
</template>

View File

@ -39,6 +39,7 @@
<el-table-column prop="view" label="预览" align="center" />
<el-table-column prop="tag" label="作者" align="center" />
<el-table-column prop="sort" label="排序" align="center" />
<!--列表结束-->
<el-table-column label="操作" align="center" >
<template #default="scope">
@ -63,30 +64,51 @@
/>
</el-col>
</el-row>
<!-- 新增/编辑对话框 -->
<el-dialog v-model="state.dialogVisible" title="新增" width="50%">
<el-form
:model="formData"
:model="state.formData"
ref="formRef"
label-width="100px"
>
<!-- 表单开始===============================================================================================================================-->
<el-form-item label="图片" prop="image" :rules="[{ required: true, message: '请插入图片', trigger: 'blur' }]">
<image-upload @update:imageUrl="handleImageUrl" :image-url="state.formData.image"></image-upload>
</el-form-item>
<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 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-input-number v-model="state.formData.sort" :min="1" :max="500000" />
<el-form-item label="描述" prop="description" :rules="[{ required: true, message: '请输入描述', trigger: 'blur' }]">
<e-editor :content="state.formData.description" @update:content="handleUrl" />
</el-form-item>
<!--表单结束===============================================================================================================================-->
</el-form>
@ -98,14 +120,13 @@
</div>
</template>
<script setup lang="ts">
//
//
import type {FormInstance, TabsPaneContext} from 'element-plus'
const formRef = ref<FormInstance>()
const loading = ref(true)
const state = reactive({
const state = reactive(<any>{
route:"sys/item",
getStatus:['上架','下架','库存警告','售空'],
getStatus:[
{name:"上架",status:0},
{name:"下架",status:1},
@ -121,18 +142,19 @@ const state = reactive({
title:"",
status:0,
},
formData:{}
formData:{},
cateList:[]
})
//
let formData = reactive(<any>{})
//
function handleImageUrl(path: string) {
state.formData.path = path
state.formData.image = path
}
//
function handleUrl(content: string) {
state.formData.description = content
}
//
const init = () => {
adminRequest.get(`${state.route}/page`, {
@ -143,17 +165,25 @@ const init = () => {
}).finally(() => {
loading.value = false
})
adminRequest.get(`sys/categories/page`, {
params: state.query
}).then((res:any) => {
state.cateList = res.data.list
})
}
//
const openAddDialog = () => {
formData = {
state.formData = {
sort:1
}
state.dialogVisible = true
}
//
const edit = (row: any) => {
formData = row
state.formData = row
state.dialogVisible = true
}
//
@ -161,22 +191,21 @@ const saveTransaction = async (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.validate((valid) => {
if (valid) {
if (formData.id) {
if (state.formData.id) {
//
adminRequest.put(`${state.route}`, formData).then(() =>{
adminRequest.put(`${state.route}`, state.formData).then(() =>{
init()
state.dialogVisible = false
ElMessage.success("提交成功~")
})
} else {
//
adminRequest.post(`${state.route}`, formData).then(() =>{
adminRequest.post(`${state.route}`, state.formData).then(() =>{
init()
state.dialogVisible = false
ElMessage.success("提交成功~")
})
}
}
})
}
@ -226,19 +255,6 @@ onMounted(() => {
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>
<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="username" label="账号"/>
<el-table-column prop="password" label="密码"/>
<el-table-column prop="createDate" label="创建时间"/>
<el-table-column prop="nickName" label="昵称"/>
<el-table-column prop="introduce" label="介绍"/>
@ -48,30 +47,26 @@
<!-- 新增/编辑对话框 -->
<el-dialog v-model="state.dialogVisible" title="新增" width="50%">
<el-form
:model="formData"
:model="state.formData"
ref="formRef"
label-width="100px"
>
<!-- 表单开始===============================================================================================================================-->
<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 label="密码" prop="password" :rules="[{ required: true, message: '请输入密码', trigger: 'blur' }]">
<el-input v-model="formData.password"/>
<el-form-item label="密码" >
<el-input v-model="state.formData.password"/>
</el-form-item>
<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 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>
@ -94,7 +89,8 @@ const state = reactive({
page: 1, //
limit: 10, //
username: "",
}
},
formData:{}
})
// 1990-2015
@ -103,8 +99,6 @@ for (let year = 1990; year <= 2015; year++) {
years.push(year.toString());
}
//
let formData = reactive(<any>{})
//
const init = () => {
adminRequest.get(`${state.route}/page`, {
@ -116,12 +110,14 @@ const init = () => {
}
//
const openAddDialog = () => {
formData = {}
state.formData = {}
state.dialogVisible = true
}
//
const edit = (row: any) => {
formData = row
state.formData = row
delete state.formData.password
state.dialogVisible = true
}
@ -130,12 +126,12 @@ const saveTransaction = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.validate((valid) => {
if (valid) {
if (formData.id) {
if (state.formData.id) {
//
adminRequest.put(`${state.route}`, formData)
adminRequest.put(`${state.route}`, state.formData)
} else {
//
adminRequest.post(`${state.route}`, formData)
adminRequest.post(`${state.route}`, state.formData)
}
init()
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")
}
})
</script>
<style scoped>

View File

@ -15,13 +15,6 @@
<div class="module_text">密码</div>
<input class="module_input" type="password" placeholder="输入密码" v-model="login.password" />
</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_code">
<el-radio-group v-model="state.role" class="ml-4">
@ -30,9 +23,8 @@
</el-radio-group>
</div>
</div>
<!-- <div class="module_radio"><input type="radio"/>记住密码 </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>
@ -52,8 +44,7 @@ const state = reactive({
const login = reactive({
username: '',
password: '',
captcha: '',
uuid: '' })
})
const onLogin = () => {
state.loading = true
if (state.role) {
@ -68,40 +59,18 @@ const onLogin = () => {
ElMessage.success("登录成功~")
})
}).catch(() => {
state.loading = false
onRefreshCode()
})
} else {
frontRequest.post("/api/user/login", login).then(response =>{
const user = userStore()
user.frontToken = response.data.token
frontRequest.get("/api/user/userInfo").then(response =>{
user.frontIsLogin = true
user.frontUserInfo = response.data
ElMessage.success("登录成功~")
router.push('/')
})
user.frontIsLogin = true
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>
<style scoped>

View File

@ -1,74 +1,164 @@
<!--用户详情-->
<template>
<el-tabs v-model="state.activeName" @tab-click="handleClick">
<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">
<!-- 列表结开始-->
<el-table-column prop="id" label="编号" align="center" />
<el-table-column prop="title" label="电影名称" align="center" />
<el-table-column prop="year" label="上映时间" align="center" />
<el-table-column prop="largePic" label="图片" align="center" >
<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 }">
<!-- 点击图片后显示弹框预览 -->
<el-image
:src="row.largePic"
fit="cover"
:preview-src-list="row.largePic.split(',')"
:preview-teleported="true"
/>
<img :src="row.item.image" style="width: 100px; height: 100px;">
</template>
</el-table-column>
<el-table-column prop="country" label="国家" align="center" />
<el-table-column prop="movieType" label="电影类型" align="center" />
<el-table-column prop="director" label="导演" align="center" />
<el-table-column prop="actor" label="主演" align="center" />
<el-table-column prop="ratingValue" label="评分" align="center" />
<el-table-column prop="ratingCount" label="评分人数" align="center" />
<!--列表结束-->
<el-table-column label="操作" align="center" >
<template #default="scope">
<el-button @click="del(scope.row.id)" type="danger" size="small">取消</el-button>
<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 label="操作" min-width="120">
<template #default="scope" >
<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>
<template v-slot:empty>
<el-empty description="数据去外太空了~" />
</template>
</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({
activeName:1,
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() {
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()
}
function getList() {
frontRequest.get("/api/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()
}
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>

View File

@ -21,14 +21,6 @@
<input class="module_input" type="password" placeholder="再次输入密码" v-model="register.confirmPassword" />
</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>
<button class="module_button" @click="onRegister">注册</button>
</div>
@ -42,7 +34,7 @@ const register = reactive({
username: '',
password: '',
confirmPassword: '',
captcha: '',
nickName: '',
uuid: ''
})

View File

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

View File

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