9 Commits

Author SHA1 Message Date
xuelijun
3497962627 Merge branch 'feature/order' into xlj 2025-10-24 17:30:30 +08:00
xuelijun
15e801e426 Merge remote-tracking branch 'origin/feature/order' into feature/order 2025-10-24 17:29:48 +08:00
xuelijun
b2e0cca804 图片 2025-10-24 17:29:14 +08:00
22b96b6feb 订单详情接口调整 2025-10-24 16:50:36 +08:00
fc62fa3167 订单详情接口调整 2025-10-23 13:34:32 +08:00
190e0e1605 订单详情接口调整 2025-10-17 18:32:04 +08:00
3fbb1383fd 订单详情接口调整 2025-10-16 16:49:36 +08:00
191eadbf77 调整分支 2025-10-16 15:34:55 +08:00
b6630f3f61 Merge branch 'refs/heads/xlj' into feature/order 2025-10-16 15:29:17 +08:00
64 changed files with 4777 additions and 690 deletions

View File

@@ -21,6 +21,8 @@ CREATE TABLE `tz_trade_order`
`merchant_name` varchar(64) DEFAULT NULL COMMENT '商家名称', `merchant_name` varchar(64) DEFAULT NULL COMMENT '商家名称',
`merchant_remark` varchar(512) DEFAULT NULL COMMENT '商家备注', `merchant_remark` varchar(512) DEFAULT NULL COMMENT '商家备注',
`comment_status` tinyint(1) DEFAULT NULL COMMENT '是否评价 (true-已评价, false-未评价)', `comment_status` tinyint(1) DEFAULT NULL COMMENT '是否评价 (true-已评价, false-未评价)',
`sub_type` tinyint(1) NOT NULL DEFAULT 1 COMMENT '预约类型1预约 2 加急)',
`sub_time` datetime NOT NULL COMMENT '预约时间',
`expense_price` int(11) DEFAULT NULL COMMENT '商品成本(单),单位:分', `expense_price` int(11) DEFAULT NULL COMMENT '商品成本(单),单位:分',
`price` int(11) DEFAULT NULL COMMENT '商品原价(单),单位:分', `price` int(11) DEFAULT NULL COMMENT '商品原价(单),单位:分',
`discount_price` int(11) DEFAULT NULL COMMENT '优惠金额(总),单位:分', `discount_price` int(11) DEFAULT NULL COMMENT '优惠金额(总),单位:分',
@@ -90,8 +92,7 @@ CREATE TABLE `tz_trade_order_item`
`adjust_price` int(11) NOT NULL COMMENT '订单调价(总),单位:分', `adjust_price` int(11) NOT NULL COMMENT '订单调价(总),单位:分',
`pay_price` int(11) NOT NULL COMMENT '应付金额(总),单位:分', `pay_price` int(11) NOT NULL COMMENT '应付金额(总),单位:分',
`live_price` int(11) NOT NULL COMMENT '实收金额(总),单位:分', `live_price` int(11) NOT NULL COMMENT '实收金额(总),单位:分',
`sub_type` tinyint(1) NOT NULL DEFAULT 1 COMMENT '预约类型1预约 2 加急)',
`sub_time` datetime NOT NULL COMMENT '预约时间',
`serve_address` datetime NOT NULL COMMENT '服务地址', `serve_address` datetime NOT NULL COMMENT '服务地址',
`properties` json DEFAULT NULL COMMENT '属性数组', `properties` json DEFAULT NULL COMMENT '属性数组',
`serve_info` json DEFAULT NULL COMMENT '服务信息', `serve_info` json DEFAULT NULL COMMENT '服务信息',

View File

@@ -70,6 +70,10 @@ public class ProdListVO {
* 还剩多少天 * 还剩多少天
*/ */
private Long remainingDays; private Long remainingDays;
/**
* 图片
*/
private String pic;
/** /**
* 审核备注 * 审核备注

View File

@@ -17,17 +17,15 @@ import java.util.Arrays;
@Getter @Getter
public enum TradeOrderStatusEnum implements ArrayValuable<Integer> { public enum TradeOrderStatusEnum implements ArrayValuable<Integer> {
UNPAID(0, "待支付"), WAITPAID(10, "等待付款"),
UNDELIVERED(10, "待发货"), WAITCONFIRM(20, "等待确定"),
DELIVERED(20, "已发货"), WAITSERVE(30, "等待服务"),
COMPLETED(30, "已完成"), WAITACCEPT(40, "等待验收"),
CANCELED(40, "取消"), COMPLETED(50, "完成"),
CANCELED(60, "已取消"),
WAITPAID(100, "等待付"), DELIVERED(70, "已退"),
WAITCONFIRM(110, "等待确定"), WAITDELIVERED(80, "待发货"),
WAITSERVE(120, "等待服务"), ;
WAITACCEPT(130, "等待验收"),
SERVECANCELED(140, "取消服务");
public static final Integer[] ARRAYS = Arrays.stream(values()).map(TradeOrderStatusEnum::getStatus).toArray(Integer[]::new); public static final Integer[] ARRAYS = Arrays.stream(values()).map(TradeOrderStatusEnum::getStatus).toArray(Integer[]::new);
@@ -55,7 +53,7 @@ public enum TradeOrderStatusEnum implements ArrayValuable<Integer> {
* @return 是否 * @return 是否
*/ */
public static boolean isUnpaid(Integer status) { public static boolean isUnpaid(Integer status) {
return ObjectUtil.equal(UNPAID.getStatus(), status); return ObjectUtil.equal(WAITPAID.getStatus(), status);
} }
/** /**
@@ -65,7 +63,7 @@ public enum TradeOrderStatusEnum implements ArrayValuable<Integer> {
* @return 是否 * @return 是否
*/ */
public static boolean isUndelivered(Integer status) { public static boolean isUndelivered(Integer status) {
return ObjectUtil.equal(UNDELIVERED.getStatus(), status); return ObjectUtil.equal(WAITDELIVERED.getStatus(), status);
} }
/** /**
@@ -105,7 +103,7 @@ public enum TradeOrderStatusEnum implements ArrayValuable<Integer> {
* @return 是否 * @return 是否
*/ */
public static boolean havePaid(Integer status) { public static boolean havePaid(Integer status) {
return ObjectUtils.equalsAny(status, UNDELIVERED.getStatus(), return ObjectUtils.equalsAny(status, WAITCONFIRM.getStatus(),
DELIVERED.getStatus(), COMPLETED.getStatus()); DELIVERED.getStatus(), COMPLETED.getStatus());
} }

View File

@@ -196,6 +196,15 @@ public class LocalDateTimeUtils {
return LocalDateTimeUtil.beginOfDay(LocalDateTime.now().minusDays(1)); return LocalDateTimeUtil.beginOfDay(LocalDateTime.now().minusDays(1));
} }
/**
* 获取day 天后的日期
*
* @return 昨天
*/
public static LocalDateTime getPlusDay(Integer day) {
return LocalDateTimeUtil.beginOfDay(LocalDateTime.now().plusDays(day));
}
/** /**
* 获取本月的开始时间 * 获取本月的开始时间
* *

View File

@@ -0,0 +1,27 @@
package com.tashow.cloud.common.util.json.databind;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.time.LocalDateTime;
/**
* 基于字符串的 LocalDateTime 序列化器
*
* @author 老五
*/
public class StringLocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
public static final StringLocalDateTimeSerializer INSTANCE = new StringLocalDateTimeSerializer();
@Override
public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
// 将 LocalDateTime 对象,转换为 Long 时间戳
gen.writeString(LocalDateTimeUtil.format(value, DatePattern.NORM_DATETIME_FORMATTER) );
}
}

View File

@@ -5,6 +5,8 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static com.tashow.cloud.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; import static com.tashow.cloud.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/** /**
@@ -70,7 +72,6 @@ public class AiDialogMessageRespVo {
* 创建时间 * 创建时间
*/ */
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime createTime;
private String createTime;
} }

View File

@@ -1,11 +1,11 @@
package com.tashow.cloud.ai.controller.app.dialog.vo; package com.tashow.cloud.ai.controller.app.dialog.vo;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.tashow.cloud.common.util.json.databind.StringLocalDateTimeSerializer;
import lombok.Data; import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import static com.tashow.cloud.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; import java.time.LocalDateTime;
/** /**
* 翻译接口结果vo * 翻译接口结果vo
@@ -40,8 +40,7 @@ public class TranslateRespVo {
//文件时长 //文件时长
private Long contentDuration; private Long contentDuration;
//发送时间 //发送时间
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @JsonSerialize(using = StringLocalDateTimeSerializer.class)
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime createTime;
private String createTime;
} }

View File

@@ -1,10 +1,14 @@
package com.tashow.cloud.ai.dal.dataobject.dialog; package com.tashow.cloud.ai.dal.dataobject.dialog;
import com.baomidou.mybatisplus.annotation.*; import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.*; import lombok.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import static com.tashow.cloud.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/** /**
* ai-对话消息 DO * ai-对话消息 DO
* *
@@ -89,6 +93,8 @@ public class AiDialogMessageDO {
* 创建时间 * 创建时间
*/ */
@TableField(fill = FieldFill.INSERT) @TableField(fill = FieldFill.INSERT)
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime createTime; private LocalDateTime createTime;
} }

View File

@@ -1,5 +1,6 @@
package com.tashow.cloud.ai.service.dialog; package com.tashow.cloud.ai.service.dialog;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil; import cn.hutool.http.HttpUtil;
@@ -30,8 +31,8 @@ import javax.sound.sampled.AudioSystem;
import java.io.InputStream; import java.io.InputStream;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.time.LocalDateTime;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -55,6 +56,17 @@ public class AiDialogServiceImpl extends ServiceImpl<AiDialogMapper, AiDialogDO>
private FileApi fileApi; private FileApi fileApi;
private Map<String, String> petAvatars = new HashMap<>() {{
put("cat", "https://petshy.tashowz.com/admin-api/infra/file/29/get/89f4982de19aadae3248ffde37132857df255b3276de484fdf12e603e5e29a7e.png");
put("dog", "https://petshy.tashowz.com/admin-api/infra/file/29/get/175ba9f58dc812786bfe0598ca9c4a7f422fe138c1889e08d8228aebc953c1b3.png");
}};
private Map<String, String> petName = new HashMap<>() {{
put("cat", "猫猫・三胖");
put("dog", "狗狗・旺财");
}};
@Override @Override
public DialogResp getDialog(Long userId) { public DialogResp getDialog(Long userId) {
AiDialogDO aiDialogDO = this.getOne(new LambdaQueryWrapper<AiDialogDO>().eq(AiDialogDO::getUserId, userId)); AiDialogDO aiDialogDO = this.getOne(new LambdaQueryWrapper<AiDialogDO>().eq(AiDialogDO::getUserId, userId));
@@ -108,7 +120,7 @@ public class AiDialogServiceImpl extends ServiceImpl<AiDialogMapper, AiDialogDO>
.last("limit 1") .last("limit 1")
); );
messageDO.setMessageOrder(aiDialogMessageDO == null ? 1 : aiDialogMessageDO.getMessageOrder() + 1); messageDO.setMessageOrder(aiDialogMessageDO == null ? 1 : aiDialogMessageDO.getMessageOrder() + 1);
messageDO.setCreateTime(LocalDateTime.now()); messageDO.setCreateTime(LocalDateTimeUtil.now());
} }
int i = messageDO.getId() == null ? aiDialogMessageMapper.insert(messageDO) : aiDialogMessageMapper.updateById(messageDO); int i = messageDO.getId() == null ? aiDialogMessageMapper.insert(messageDO) : aiDialogMessageMapper.updateById(messageDO);
TranslateRespVo bean = BeanUtils.toBean(messageDO, TranslateRespVo.class); TranslateRespVo bean = BeanUtils.toBean(messageDO, TranslateRespVo.class);
@@ -136,7 +148,11 @@ public class AiDialogServiceImpl extends ServiceImpl<AiDialogMapper, AiDialogDO>
//数据解析 //数据解析
JSONObject translateResult = JSON.parseObject(result); JSONObject translateResult = JSON.parseObject(result);
if (translateResult.isEmpty() || !translateResult.containsKey("intent_result") || !translateResult.getBoolean("is_species_sound")) { if (translateResult.isEmpty()
|| !translateResult.containsKey("intent_result")
|| !translateResult.getBoolean("is_species_sound")
|| translateResult.getInteger("confidence") < 0.7
) {
messageDO.setTransStatus(0); messageDO.setTransStatus(0);
messageDO.setTransResult(""); messageDO.setTransResult("");
return messageDO; return messageDO;
@@ -148,16 +164,24 @@ public class AiDialogServiceImpl extends ServiceImpl<AiDialogMapper, AiDialogDO>
.getJSONObject("probabilities"); .getJSONObject("probabilities");
String resultKey = probabilities.entrySet().stream() String resultKey = probabilities.entrySet().stream()
.filter(entry -> entry.getValue() instanceof Number) .filter(entry -> entry.getValue() instanceof Number && ((Number) entry.getValue()).doubleValue() > 0.7)
.max(Comparator.comparingDouble(entry -> ((Number) entry.getValue()).doubleValue())) .max(Comparator.comparingDouble(entry -> ((Number) entry.getValue()).doubleValue()))
.map(Map.Entry::getKey) .map(Map.Entry::getKey)
.orElse(null); .orElse(null);
//返回结果 //返回结果
if (StrUtil.isBlank(resultKey)) {
messageDO.setTransStatus(0);
messageDO.setTransResult("");
return messageDO;
}
//宠物档案 todo //宠物档案 todo
messageDO.setPetId(1l); messageDO.setPetId(1l);
messageDO.setPetName(speciesLabels); messageDO.setPetName(petName.get(speciesLabels));
messageDO.setPetAvatar("https://img1.baidu.com/it/u=1224902049,3440357835&fm=253&app=138&f=JPEG?w=801&h=800"); https:
//qcloud.dpfile.com/pc/qw4HqeQN5Af9tLaw0mx8pXQhxKUCvwHbCXmSRI-nKiW1NpX6wMdvSN80YpcTbMKw.jpg
messageDO.setPetAvatar(petAvatars.get(speciesLabels));
messageDO.setPetType(speciesLabels); messageDO.setPetType(speciesLabels);
messageDO.setTransStatus(1); messageDO.setTransStatus(1);
messageDO.setTransResult(StrUtil.isBlank(resultKey) ? "" : resultKey.split(StrUtil.UNDERLINE)[1]); messageDO.setTransResult(StrUtil.isBlank(resultKey) ? "" : resultKey.split(StrUtil.UNDERLINE)[1]);

View File

@@ -29,14 +29,13 @@ import static com.tashow.cloud.infra.framework.file.core.utils.FileTypeUtils.wri
@RequestMapping("/infra/file") @RequestMapping("/infra/file")
@Validated @Validated
@Slf4j @Slf4j
@PermitAll
public class FileController { public class FileController {
@Resource private FileService fileService; @Resource private FileService fileService;
/** 上传文件", description = "模式一:后端上传文件 */ /** 上传文件", description = "模式一:后端上传文件 */
@PostMapping("/upload") @PostMapping("/upload")
public CommonResult<String> uploadFile(FileUploadReqVO uploadReqVO) throws Exception { public CommonResult<String> uploadFile(@Valid FileUploadReqVO uploadReqVO) throws Exception {
MultipartFile file = uploadReqVO.getFile(); MultipartFile file = uploadReqVO.getFile();
String path = uploadReqVO.getPath(); String path = uploadReqVO.getPath();
return success( return success(

View File

@@ -5,6 +5,10 @@ import ${jakartaPackage}.annotation.Resource;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
#if ($sceneEnum.scene == 1)import org.springframework.security.access.prepost.PreAuthorize;#end #if ($sceneEnum.scene == 1)import org.springframework.security.access.prepost.PreAuthorize;#end
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import ${jakartaPackage}.validation.constraints.*; import ${jakartaPackage}.validation.constraints.*;
import ${jakartaPackage}.validation.*; import ${jakartaPackage}.validation.*;
import ${jakartaPackage}.servlet.http.*; import ${jakartaPackage}.servlet.http.*;
@@ -30,9 +34,7 @@ import ${basePackage}.module.${subTable.moduleName}.dal.dataobject.${subTable.bu
#end #end
import ${basePackage}.module.${table.moduleName}.service.${table.businessName}.${table.className}Service; import ${basePackage}.module.${table.moduleName}.service.${table.businessName}.${table.className}Service;
/** @Tag(name = "${sceneEnum.name} - ${table.classComment}")
* ${sceneEnum.name} - ${table.classComment}
*/
@RestController @RestController
##二级的 businessName 暂时不算在 HTTP 路径上,可以根据需要写 ##二级的 businessName 暂时不算在 HTTP 路径上,可以根据需要写
@RequestMapping("/${table.moduleName}/${simpleClassName_strikeCase}") @RequestMapping("/${table.moduleName}/${simpleClassName_strikeCase}")
@@ -42,10 +44,8 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
@Resource @Resource
private ${table.className}Service ${classNameVar}Service; private ${table.className}Service ${classNameVar}Service;
/**
* 创建${table.classComment}
*/
@PostMapping("/create") @PostMapping("/create")
@Operation(summary = "创建${table.classComment}")
#if ($sceneEnum.scene == 1) #if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:create')") @PreAuthorize("@ss.hasPermission('${permissionPrefix}:create')")
#end #end
@@ -53,10 +53,8 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
return success(${classNameVar}Service.create${simpleClassName}(createReqVO)); return success(${classNameVar}Service.create${simpleClassName}(createReqVO));
} }
/**
* 更新${table.classComment}
*/
@PutMapping("/update") @PutMapping("/update")
@Operation(summary = "更新${table.classComment}")
#if ($sceneEnum.scene == 1) #if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:update')") @PreAuthorize("@ss.hasPermission('${permissionPrefix}:update')")
#end #end
@@ -65,10 +63,9 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
return success(true); return success(true);
} }
/**
* 删除${table.classComment}
*/
@DeleteMapping("/delete") @DeleteMapping("/delete")
@Operation(summary = "删除${table.classComment}")
@Parameter(name = "id", description = "编号", required = true)
#if ($sceneEnum.scene == 1) #if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:delete')") @PreAuthorize("@ss.hasPermission('${permissionPrefix}:delete')")
#end #end
@@ -77,10 +74,9 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
return success(true); return success(true);
} }
/**
* 获得${table.classComment}
*/
@GetMapping("/get") @GetMapping("/get")
@Operation(summary = "获得${table.classComment}")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
#if ($sceneEnum.scene == 1) #if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')") @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")
#end #end
@@ -90,11 +86,8 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
} }
#if ( $table.templateType != 2 ) #if ( $table.templateType != 2 )
/**
* 获得${table.classComment}分页
*/
@GetMapping("/page") @GetMapping("/page")
@Operation(summary = "获得${table.classComment}分页")
#if ($sceneEnum.scene == 1) #if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')") @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")
#end #end
@@ -105,10 +98,8 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
## 特殊:树表专属逻辑(树不需要分页接口) ## 特殊:树表专属逻辑(树不需要分页接口)
#else #else
/**
* 获得${table.classComment}列表
*/
@GetMapping("/list") @GetMapping("/list")
@Operation(summary = "获得${table.classComment}列表")
#if ($sceneEnum.scene == 1) #if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')") @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")
#end #end
@@ -118,10 +109,8 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
} }
#end #end
/**
* 导出${table.classComment} Excel
*/
@GetMapping("/export-excel") @GetMapping("/export-excel")
@Operation(summary = "导出${table.classComment} Excel")
#if ($sceneEnum.scene == 1) #if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:export')") @PreAuthorize("@ss.hasPermission('${permissionPrefix}:export')")
#end #end
@@ -160,10 +149,9 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
## 情况一MASTER_ERP 时,需要分查询页子表 ## 情况一MASTER_ERP 时,需要分查询页子表
#if ( $table.templateType == 11 ) #if ( $table.templateType == 11 )
/**
* 获得${subTable.classComment}分页
*/
@GetMapping("/${subSimpleClassName_strikeCase}/page") @GetMapping("/${subSimpleClassName_strikeCase}/page")
@Operation(summary = "获得${subTable.classComment}分页")
@Parameter(name = "${subJoinColumn.javaField}", description = "${subJoinColumn.columnComment}")
#if ($sceneEnum.scene == 1) #if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')") @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")
#end #end
@@ -175,10 +163,9 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
## 情况二:非 MASTER_ERP 时,需要列表查询子表 ## 情况二:非 MASTER_ERP 时,需要列表查询子表
#else #else
#if ( $subTable.subJoinMany ) #if ( $subTable.subJoinMany )
/**
* 获得${subTable.classComment}列表
*/
@GetMapping("/${subSimpleClassName_strikeCase}/list-by-${subJoinColumn_strikeCase}") @GetMapping("/${subSimpleClassName_strikeCase}/list-by-${subJoinColumn_strikeCase}")
@Operation(summary = "获得${subTable.classComment}列表")
@Parameter(name = "${subJoinColumn.javaField}", description = "${subJoinColumn.columnComment}")
#if ($sceneEnum.scene == 1) #if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')") @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")
#end #end
@@ -187,10 +174,9 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
} }
#else #else
/**
* 获得${subTable.classComment}
*/
@GetMapping("/${subSimpleClassName_strikeCase}/get-by-${subJoinColumn_strikeCase}") @GetMapping("/${subSimpleClassName_strikeCase}/get-by-${subJoinColumn_strikeCase}")
@Operation(summary = "获得${subTable.classComment}")
@Parameter(name = "${subJoinColumn.javaField}", description = "${subJoinColumn.columnComment}")
#if ($sceneEnum.scene == 1) #if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')") @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")
#end #end
@@ -202,10 +188,8 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
#end #end
## 特殊MASTER_ERP 时,支持单个的新增、修改、删除操作 ## 特殊MASTER_ERP 时,支持单个的新增、修改、删除操作
#if ( $table.templateType == 11 ) #if ( $table.templateType == 11 )
/**
* 创建${subTable.classComment}
*/
@PostMapping("/${subSimpleClassName_strikeCase}/create") @PostMapping("/${subSimpleClassName_strikeCase}/create")
@Operation(summary = "创建${subTable.classComment}")
#if ($sceneEnum.scene == 1) #if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:create')") @PreAuthorize("@ss.hasPermission('${permissionPrefix}:create')")
#end #end
@@ -213,10 +197,8 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
return success(${classNameVar}Service.create${subSimpleClassName}(${subClassNameVar})); return success(${classNameVar}Service.create${subSimpleClassName}(${subClassNameVar}));
} }
/**
* 更新${subTable.classComment}
*/
@PutMapping("/${subSimpleClassName_strikeCase}/update") @PutMapping("/${subSimpleClassName_strikeCase}/update")
@Operation(summary = "更新${subTable.classComment}")
#if ($sceneEnum.scene == 1) #if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:update')") @PreAuthorize("@ss.hasPermission('${permissionPrefix}:update')")
#end #end
@@ -225,10 +207,9 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
return success(true); return success(true);
} }
/**
* 删除${subTable.classComment}
*/
@DeleteMapping("/${subSimpleClassName_strikeCase}/delete") @DeleteMapping("/${subSimpleClassName_strikeCase}/delete")
@Parameter(name = "id", description = "编号", required = true)
@Operation(summary = "删除${subTable.classComment}")
#if ($sceneEnum.scene == 1) #if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:delete')") @PreAuthorize("@ss.hasPermission('${permissionPrefix}:delete')")
#end #end
@@ -237,10 +218,9 @@ public class ${sceneEnum.prefixClass}${table.className}Controller {
return success(true); return success(true);
} }
/**
* 获得${subTable.classComment}
*/
@GetMapping("/${subSimpleClassName_strikeCase}/get") @GetMapping("/${subSimpleClassName_strikeCase}/get")
@Operation(summary = "获得${subTable.classComment}")
@Parameter(name = "id", description = "编号", required = true)
#if ($sceneEnum.scene == 1) #if ($sceneEnum.scene == 1)
@PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')") @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")
#end #end

View File

@@ -2,7 +2,7 @@ package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePac
import lombok.*; import lombok.*;
import java.util.*; import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import ${PageParamClassName}; import ${PageParamClassName};
#foreach ($column in $columns) #foreach ($column in $columns)
#if (${column.javaType} == "BigDecimal") #if (${column.javaType} == "BigDecimal")
@@ -22,24 +22,18 @@ import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
#end #end
## 字段模板 ## 字段模板
#macro(columnTpl $prefix $prefixStr) #macro(columnTpl $prefix $prefixStr)
/** @Schema(description = "${prefixStr}${column.columnComment}"#if ("$!column.example" != ""), example = "${column.example}"#end)
* ${prefixStr}${column.columnComment}"#if ("$!column.example" != "
*/, example = "${column.example}"#end)
private ${column.javaType}#if ("$!prefix" != "") ${prefix}${JavaField}#else ${column.javaField}#end; private ${column.javaType}#if ("$!prefix" != "") ${prefix}${JavaField}#else ${column.javaField}#end;
#end #end
/** @Schema(description = "${sceneEnum.name} - ${table.classComment}列表 Request VO")
* ${sceneEnum.name} - ${table.classComment}列表 Request VO
*/
@Data @Data
public class ${sceneEnum.prefixClass}${table.className}ListReqVO { public class ${sceneEnum.prefixClass}${table.className}ListReqVO {
#foreach ($column in $columns) #foreach ($column in $columns)
#if (${column.listOperation})##查询操作 #if (${column.listOperation})##查询操作
#if (${column.listOperationCondition} == "BETWEEN")## 情况一Between 的时候 #if (${column.listOperationCondition} == "BETWEEN")## 情况一Between 的时候
/** @Schema(description = "${column.columnComment}"#if ("$!column.example" != ""), example = "${column.example}"#end)
* ${column.columnComment}"#if ("$!column.example" != "
*/, example = "${column.example}"#end)
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private ${column.javaType}[] ${column.javaField}; private ${column.javaType}[] ${column.javaField};
#else##情况二,非 Between 的时间 #else##情况二,非 Between 的时间

View File

@@ -2,7 +2,7 @@ package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePac
import lombok.*; import lombok.*;
import java.util.*; import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import ${PageParamClassName}; import ${PageParamClassName};
#foreach ($column in $columns) #foreach ($column in $columns)
#if (${column.javaType} == "BigDecimal") #if (${column.javaType} == "BigDecimal")
@@ -22,15 +22,11 @@ import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
#end #end
## 字段模板 ## 字段模板
#macro(columnTpl $prefix $prefixStr) #macro(columnTpl $prefix $prefixStr)
/** @Schema(description = "${prefixStr}${column.columnComment}"#if ("$!column.example" != ""), example = "${column.example}"#end)
* ${prefixStr}${column.columnComment}"#if ("$!column.example" != "
*/, example = "${column.example}"#end)
private ${column.javaType}#if ("$!prefix" != "") ${prefix}${JavaField}#else ${column.javaField}#end; private ${column.javaType}#if ("$!prefix" != "") ${prefix}${JavaField}#else ${column.javaField}#end;
#end #end
/** @Schema(description = "${sceneEnum.name} - ${table.classComment}分页 Request VO")
* ${sceneEnum.name} - ${table.classComment}分页 Request VO
*/
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true) @ToString(callSuper = true)
@@ -39,9 +35,7 @@ public class ${sceneEnum.prefixClass}${table.className}PageReqVO extends PagePar
#foreach ($column in $columns) #foreach ($column in $columns)
#if (${column.listOperation})##查询操作 #if (${column.listOperation})##查询操作
#if (${column.listOperationCondition} == "BETWEEN")## 情况一Between 的时候 #if (${column.listOperationCondition} == "BETWEEN")## 情况一Between 的时候
/** @Schema(description = "${column.columnComment}"#if ("$!column.example" != ""), example = "${column.example}"#end)
* ${column.columnComment}"#if ("$!column.example" != "
*/, example = "${column.example}"#end)
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private ${column.javaType}[] ${column.javaField}; private ${column.javaType}[] ${column.javaField};
#else##情况二,非 Between 的时间 #else##情况二,非 Between 的时间

View File

@@ -1,6 +1,6 @@
package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo; package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*; import lombok.*;
import java.util.*; import java.util.*;
## 处理 BigDecimal 字段的引入 ## 处理 BigDecimal 字段的引入
@@ -28,9 +28,7 @@ import ${DictConvertClassName};
#end #end
#end #end
/** @Schema(description = "${sceneEnum.name} - ${table.classComment} Response VO")
* ${sceneEnum.name} - ${table.classComment} Response VO
*/
@Data @Data
@ExcelIgnoreUnannotated @ExcelIgnoreUnannotated
public class ${sceneEnum.prefixClass}${table.className}RespVO { public class ${sceneEnum.prefixClass}${table.className}RespVO {
@@ -39,9 +37,7 @@ public class ${sceneEnum.prefixClass}${table.className}RespVO {
#foreach ($column in $columns) #foreach ($column in $columns)
#if (${column.listOperationResult}) #if (${column.listOperationResult})
## 1. 处理 Swagger 注解 ## 1. 处理 Swagger 注解
/** @Schema(description = "${column.columnComment}"#if (!${column.nullable}), requiredMode = Schema.RequiredMode.REQUIRED#end#if ("$!column.example" != ""), example = "${column.example}"#end)
* ${column.columnComment}"#if (!${column.nullable}), requiredMode = Schema.RequiredMode.REQUIRED#end#if ("$!column.example" != "
*/, example = "${column.example}"#end)
## 2. 处理 Excel 导出 ## 2. 处理 Excel 导出
#if ("$!column.dictType" != "")##处理枚举值 #if ("$!column.dictType" != "")##处理枚举值
@ExcelProperty(value = "${column.columnComment}", converter = DictConvert.class) @ExcelProperty(value = "${column.columnComment}", converter = DictConvert.class)

View File

@@ -1,6 +1,6 @@
package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo; package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*; import lombok.*;
import java.util.*; import java.util.*;
import ${jakartaPackage}.validation.constraints.*; import ${jakartaPackage}.validation.constraints.*;
@@ -24,9 +24,7 @@ import java.time.LocalDateTime;
import ${basePackage}.module.${subTable.moduleName}.dal.dataobject.${subTable.businessName}.${subTable.className}DO; import ${basePackage}.module.${subTable.moduleName}.dal.dataobject.${subTable.businessName}.${subTable.className}DO;
#end #end
/** @Schema(description = "${sceneEnum.name} - ${table.classComment}新增/修改 Request VO")
* ${sceneEnum.name} - ${table.classComment}新增/修改 Request VO
*/
@Data @Data
public class ${sceneEnum.prefixClass}${table.className}SaveReqVO { public class ${sceneEnum.prefixClass}${table.className}SaveReqVO {
@@ -34,9 +32,7 @@ public class ${sceneEnum.prefixClass}${table.className}SaveReqVO {
#foreach ($column in $columns) #foreach ($column in $columns)
#if (${column.createOperation} || ${column.updateOperation}) #if (${column.createOperation} || ${column.updateOperation})
## 1. 处理 Swagger 注解 ## 1. 处理 Swagger 注解
/** @Schema(description = "${column.columnComment}"#if (!${column.nullable}), requiredMode = Schema.RequiredMode.REQUIRED#end#if ("$!column.example" != ""), example = "${column.example}"#end)
* ${column.columnComment}"#if (!${column.nullable}), requiredMode = Schema.RequiredMode.REQUIRED#end#if ("$!column.example" != "
*/, example = "${column.example}"#end)
## 2. 处理 Validator 参数校验 ## 2. 处理 Validator 参数校验
#if (!${column.nullable} && !${column.primaryKey}) #if (!${column.nullable} && !${column.primaryKey})
#if (${column.javaType} == 'String') #if (${column.javaType} == 'String')
@@ -55,15 +51,11 @@ public class ${sceneEnum.prefixClass}${table.className}SaveReqVO {
#foreach ($subTable in $subTables) #foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1) #set ($index = $foreach.count - 1)
#if ( $subTable.subJoinMany) #if ( $subTable.subJoinMany)
/** @Schema(description = "${subTable.classComment}列表")
* ${subTable.classComment}列表
*/
private List<${subTable.className}DO> ${subClassNameVars.get($index)}s; private List<${subTable.className}DO> ${subClassNameVars.get($index)}s;
#else #else
/** @Schema(description = "${subTable.classComment}")
* ${subTable.classComment}
*/
private ${subTable.className}DO ${subClassNameVars.get($index)}; private ${subTable.className}DO ${subClassNameVars.get($index)};
#end #end

View File

@@ -0,0 +1,168 @@
package ${basePackage}.module.${table.moduleName}.service.${table.businessName};
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import ${jakartaPackage}.annotation.Resource;
import ${baseFrameworkPackage}.test.core.ut.BaseDbUnitTest;
import ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo.*;
import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO;
import ${basePackage}.module.${table.moduleName}.dal.mysql.${table.businessName}.${table.className}Mapper;
import ${PageResultClassName};
import ${jakartaPackage}.annotation.Resource;
import org.springframework.context.annotation.Import;
import java.util.*;
import java.time.LocalDateTime;
import static cn.hutool.core.util.RandomUtil.*;
import static ${basePackage}.module.${table.moduleName}.enums.ErrorCodeConstants.*;
import static ${baseFrameworkPackage}.test.core.util.AssertUtils.*;
import static ${baseFrameworkPackage}.test.core.util.RandomUtils.*;
import static ${LocalDateTimeUtilsClassName}.*;
import static ${ObjectUtilsClassName}.*;
import static ${DateUtilsClassName}.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
## 字段模板
#macro(getPageCondition $VO)
// mock 数据
${table.className}DO db${simpleClassName} = randomPojo(${table.className}DO.class, o -> { // 等会查询到
#foreach ($column in $columns)
#if (${column.listOperation})
#set ($JavaField = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})##首字母大写
o.set$JavaField(null);
#end
#end
});
${classNameVar}Mapper.insert(db${simpleClassName});
#foreach ($column in $columns)
#if (${column.listOperation})
#set ($JavaField = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})##首字母大写
// 测试 ${column.javaField} 不匹配
${classNameVar}Mapper.insert(cloneIgnoreId(db${simpleClassName}, o -> o.set$JavaField(null)));
#end
#end
// 准备参数
${sceneEnum.prefixClass}${table.className}${VO} reqVO = new ${sceneEnum.prefixClass}${table.className}${VO}();
#foreach ($column in $columns)
#if (${column.listOperation})
#set ($JavaField = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})##首字母大写
#if (${column.listOperationCondition} == "BETWEEN")## BETWEEN 的情况
reqVO.set${JavaField}(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
#else
reqVO.set$JavaField(null);
#end
#end
#end
#end
/**
* {@link ${table.className}ServiceImpl} 的单元测试类
*
* @author ${table.author}
*/
@Import(${table.className}ServiceImpl.class)
public class ${table.className}ServiceImplTest extends BaseDbUnitTest {
@Resource
private ${table.className}ServiceImpl ${classNameVar}Service;
@Resource
private ${table.className}Mapper ${classNameVar}Mapper;
@Test
public void testCreate${simpleClassName}_success() {
// 准备参数
${sceneEnum.prefixClass}${table.className}SaveReqVO createReqVO = randomPojo(${sceneEnum.prefixClass}${table.className}SaveReqVO.class).setId(null);
// 调用
${primaryColumn.javaType} ${classNameVar}Id = ${classNameVar}Service.create${simpleClassName}(createReqVO);
// 断言
assertNotNull(${classNameVar}Id);
// 校验记录的属性是否正确
${table.className}DO ${classNameVar} = ${classNameVar}Mapper.selectById(${classNameVar}Id);
assertPojoEquals(createReqVO, ${classNameVar}, "id");
}
@Test
public void testUpdate${simpleClassName}_success() {
// mock 数据
${table.className}DO db${simpleClassName} = randomPojo(${table.className}DO.class);
${classNameVar}Mapper.insert(db${simpleClassName});// @Sql: 先插入出一条存在的数据
// 准备参数
${sceneEnum.prefixClass}${table.className}SaveReqVO updateReqVO = randomPojo(${sceneEnum.prefixClass}${table.className}SaveReqVO.class, o -> {
o.setId(db${simpleClassName}.getId()); // 设置更新的 ID
});
// 调用
${classNameVar}Service.update${simpleClassName}(updateReqVO);
// 校验是否更新正确
${table.className}DO ${classNameVar} = ${classNameVar}Mapper.selectById(updateReqVO.getId()); // 获取最新的
assertPojoEquals(updateReqVO, ${classNameVar});
}
@Test
public void testUpdate${simpleClassName}_notExists() {
// 准备参数
${sceneEnum.prefixClass}${table.className}SaveReqVO updateReqVO = randomPojo(${sceneEnum.prefixClass}${table.className}SaveReqVO.class);
// 调用, 并断言异常
assertServiceException(() -> ${classNameVar}Service.update${simpleClassName}(updateReqVO), ${simpleClassName_underlineCase.toUpperCase()}_NOT_EXISTS);
}
@Test
public void testDelete${simpleClassName}_success() {
// mock 数据
${table.className}DO db${simpleClassName} = randomPojo(${table.className}DO.class);
${classNameVar}Mapper.insert(db${simpleClassName});// @Sql: 先插入出一条存在的数据
// 准备参数
${primaryColumn.javaType} id = db${simpleClassName}.getId();
// 调用
${classNameVar}Service.delete${simpleClassName}(id);
// 校验数据不存在了
assertNull(${classNameVar}Mapper.selectById(id));
}
@Test
public void testDelete${simpleClassName}_notExists() {
// 准备参数
${primaryColumn.javaType} id = random${primaryColumn.javaType}Id();
// 调用, 并断言异常
assertServiceException(() -> ${classNameVar}Service.delete${simpleClassName}(id), ${simpleClassName_underlineCase.toUpperCase()}_NOT_EXISTS);
}
## 特殊:树表专属逻辑(树不需要分页接口)
#if ( $table.templateType != 2 )
@Test
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
public void testGet${simpleClassName}Page() {
#getPageCondition("PageReqVO")
// 调用
PageResult<${table.className}DO> pageResult = ${classNameVar}Service.get${simpleClassName}Page(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(db${simpleClassName}, pageResult.getList().get(0));
}
#else
@Test
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
public void testGet${simpleClassName}List() {
#getPageCondition("ListReqVO")
// 调用
List<${table.className}DO> list = ${classNameVar}Service.get${simpleClassName}List(reqVO);
// 断言
assertEquals(1, list.size());
assertPojoEquals(db${simpleClassName}, list.get(0));
}
#end
}

View File

@@ -0,0 +1,37 @@
-- 将该建表 SQL 语句,添加到 yudao-module-${table.moduleName}-biz 模块的 test/resources/sql/create_tables.sql 文件里
CREATE TABLE IF NOT EXISTS "${table.tableName.toLowerCase()}" (
#foreach ($column in $columns)
#if (${column.javaType} == 'Long')
#set ($dataType='bigint')
#elseif (${column.javaType} == 'Integer')
#set ($dataType='int')
#elseif (${column.javaType} == 'Boolean')
#set ($dataType='bit')
#elseif (${column.javaType} == 'Date')
#set ($dataType='datetime')
#else
#set ($dataType='varchar')
#end
#if (${column.primaryKey})##处理主键
"${column.javaField}"#if (${column.javaType} == 'String') ${dataType} NOT NULL#else ${dataType} NOT NULL GENERATED BY DEFAULT AS IDENTITY#end,
#else
#if (${column.columnName} == 'create_time')
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
#elseif (${column.columnName} == 'update_time')
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
#elseif (${column.columnName} == 'creator' || ${column.columnName} == 'updater')
"${column.columnName}" ${dataType} DEFAULT '',
#elseif (${column.columnName} == 'deleted')
"deleted" bit NOT NULL DEFAULT FALSE,
#elseif (${column.columnName} == 'tenant_id')
"tenant_id" bigint NOT NULL DEFAULT 0,
#else
"${column.columnName.toLowerCase()}" ${dataType}#if (${column.nullable} == false) NOT NULL#end,
#end
#end
#end
PRIMARY KEY ("${primaryColumn.columnName.toLowerCase()}")
) COMMENT '${table.tableComment}';
-- 将该删表 SQL 语句,添加到 yudao-module-${table.moduleName}-biz 模块的 test/resources/sql/clean.sql 文件里
DELETE FROM "${table.tableName}";

View File

@@ -0,0 +1,28 @@
-- 菜单 SQL
INSERT INTO system_menu(
name, permission, type, sort, parent_id,
path, icon, component, status, component_name
)
VALUES (
'${table.classComment}管理', '', 2, 0, ${table.parentMenuId},
'${simpleClassName_strikeCase}', '', '${table.moduleName}/${table.businessName}/index', 0, '${table.className}'
);
-- 按钮父菜单ID
-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码
SELECT @parentId := LAST_INSERT_ID();
-- 按钮 SQL
#set ($functionNames = ['查询', '创建', '更新', '删除', '导出'])
#set ($functionOps = ['query', 'create', 'update', 'delete', 'export'])
#foreach ($functionName in $functionNames)
#set ($index = $foreach.count - 1)
INSERT INTO system_menu(
name, permission, type, sort, parent_id,
path, icon, component, status
)
VALUES (
'${table.classComment}${functionName}', '${permissionPrefix}:${functionOps.get($index)}', 3, $foreach.count, @parentId,
'', '', '', 0
);
#end

View File

@@ -0,0 +1,141 @@
import request from '@/utils/request'
#set ($baseURL = "/${table.moduleName}/${simpleClassName_strikeCase}")
// 创建${table.classComment}
export function create${simpleClassName}(data) {
return request({
url: '${baseURL}/create',
method: 'post',
data: data
})
}
// 更新${table.classComment}
export function update${simpleClassName}(data) {
return request({
url: '${baseURL}/update',
method: 'put',
data: data
})
}
// 删除${table.classComment}
export function delete${simpleClassName}(id) {
return request({
url: '${baseURL}/delete?id=' + id,
method: 'delete'
})
}
// 获得${table.classComment}
export function get${simpleClassName}(id) {
return request({
url: '${baseURL}/get?id=' + id,
method: 'get'
})
}
#if ( $table.templateType != 2 )
// 获得${table.classComment}分页
export function get${simpleClassName}Page(params) {
return request({
url: '${baseURL}/page',
method: 'get',
params
})
}
#else
// 获得${table.classComment}列表
export function get${simpleClassName}List(params) {
return request({
url: '${baseURL}/list',
method: 'get',
params
})
}
#end
// 导出${table.classComment} Excel
export function export${simpleClassName}Excel(params) {
return request({
url: '${baseURL}/export-excel',
method: 'get',
params,
responseType: 'blob'
})
}
## 特殊:主子表专属逻辑
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subSimpleClassName = $subSimpleClassNames.get($index))
#set ($subPrimaryColumn = $subPrimaryColumns.get($index))##当前 primary 字段
#set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段
#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
#set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
#set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
#set ($subClassNameVar = $subClassNameVars.get($index))
// ==================== 子表($subTable.classComment ====================
## 情况一MASTER_ERP 时,需要分查询页子表
#if ($table.templateType == 11)
// 获得${subTable.classComment}分页
export function get${subSimpleClassName}Page(params) {
return request({
url: '${baseURL}/${subSimpleClassName_strikeCase}/page',
method: 'get',
params
})
}
## 情况二:非 MASTER_ERP 时,需要列表查询子表
#else
#if ($subTable.subJoinMany)
// 获得${subTable.classComment}列表
export function get${subSimpleClassName}ListBy${SubJoinColumnName}(${subJoinColumn.javaField}) {
return request({
url: '${baseURL}/${subSimpleClassName_strikeCase}/list-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=' + ${subJoinColumn.javaField},
method: 'get'
})
}
#else
// 获得${subTable.classComment}
export function get${subSimpleClassName}By${SubJoinColumnName}(${subJoinColumn.javaField}) {
return request({
url: '${baseURL}/${subSimpleClassName_strikeCase}/get-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=' + ${subJoinColumn.javaField},
method: 'get'
})
}
#end
#end
## 特殊MASTER_ERP 时,支持单个的新增、修改、删除操作
#if ($table.templateType == 11)
// 新增${subTable.classComment}
export function create${subSimpleClassName}(data) {
return request({
url: '${baseURL}/${subSimpleClassName_strikeCase}/create',
method: 'post',
data
})
}
// 修改${subTable.classComment}
export function update${subSimpleClassName}(data) {
return request({
url: '${baseURL}/${subSimpleClassName_strikeCase}/update',
method: 'post',
data
})
}
// 删除${subTable.classComment}
export function delete${subSimpleClassName}(id) {
return request({
url: '${baseURL}/${subSimpleClassName_strikeCase}/delete?id=' + id,
method: 'delete'
})
}
// 获得${subTable.classComment}
export function get${subSimpleClassName}(id) {
return request({
url: '${baseURL}/${subSimpleClassName_strikeCase}/get?id=' + id,
method: 'get'
})
}
#end
#end

View File

@@ -0,0 +1,205 @@
#set ($subTable = $subTables.get($subIndex))##当前表
#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
<template>
<div class="app-container">
<!-- 对话框(添加 / 修改) -->
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="45%" v-dialogDrag append-to-body>
<el-form ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-width="100px">
#foreach($column in $subColumns)
#if ($column.createOperation || $column.updateOperation)
#set ($dictType = $column.dictType)
#set ($javaField = $column.javaField)
#set ($javaType = $column.javaType)
#set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
#set ($comment = $column.columnComment)
#if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
#elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
<el-form-item label="${comment}" prop="${javaField}">
<el-input v-model="formData.${javaField}" placeholder="请输入${comment}" />
</el-form-item>
#elseif($column.htmlType == "imageUpload")## 图片上传
#set ($hasImageUploadColumn = true)
<el-form-item label="${comment}" prop="${javaField}">
<ImageUpload v-model="formData.${javaField}"/>
</el-form-item>
#elseif($column.htmlType == "fileUpload")## 文件上传
#set ($hasFileUploadColumn = true)
<el-form-item label="${comment}" prop="${javaField}">
<FileUpload v-model="formData.${javaField}"/>
</el-form-item>
#elseif($column.htmlType == "editor")## 文本编辑器
#set ($hasEditorColumn = true)
<el-form-item label="${comment}" prop="${javaField}">
<editor v-model="formData.${javaField}" :min-height="192"/>
</el-form-item>
#elseif($column.htmlType == "select")## 下拉框
<el-form-item label="${comment}" prop="${javaField}">
<el-select v-model="formData.${javaField}" placeholder="请选择${comment}">
#if ("" != $dictType)## 有数据字典
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value" :label="dict.label" #if ($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.value)"#else:value="dict.value"#end />
#else##没数据字典
<el-option label="请选择字典生成" value="" />
#end
</el-select>
</el-form-item>
#elseif($column.htmlType == "checkbox")## 多选框
<el-form-item label="${comment}" prop="${javaField}">
<el-checkbox-group v-model="formData.${javaField}">
#if ("" != $dictType)## 有数据字典
<el-checkbox v-for="dict in this.getDictDatas(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value" #if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.value)"#else:label="dict.value"#end>{{dict.label}}</el-checkbox>
#else##没数据字典
<el-checkbox>请选择字典生成</el-checkbox>
#end
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "radio")## 单选框
<el-form-item label="${comment}" prop="${javaField}">
<el-radio-group v-model="formData.${javaField}">
#if ("" != $dictType)## 有数据字典
<el-radio v-for="dict in this.getDictDatas(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value" #if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.value)"
#else:label="dict.value"#end>{{dict.label}}</el-radio>
#else##没数据字典
<el-radio label="1">请选择字典生成</el-radio>
#end
</el-radio-group>
</el-form-item>
#elseif($column.htmlType == "datetime")## 时间框
<el-form-item label="${comment}" prop="${javaField}">
<el-date-picker clearable v-model="formData.${javaField}" type="date" value-format="timestamp" placeholder="选择${comment}" />
</el-form-item>
#elseif($column.htmlType == "textarea")## 文本框
<el-form-item label="${comment}" prop="${javaField}">
<el-input v-model="formData.${javaField}" type="textarea" placeholder="请输入内容" />
</el-form-item>
#end
#end
#end
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm" :disabled="formLoading">确 定</el-button>
<el-button @click="dialogVisible = false">取 消</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${table.businessName}';
#if ($hasImageUploadColumn)
import ImageUpload from '@/components/ImageUpload';
#end
#if ($hasFileUploadColumn)
import FileUpload from '@/components/FileUpload';
#end
#if ($hasEditorColumn)
import Editor from '@/components/Editor';
#end
export default {
name: "${subSimpleClassName}Form",
components: {
#if ($hasImageUploadColumn)
ImageUpload,
#end
#if ($hasFileUploadColumn)
FileUpload,
#end
#if ($hasEditorColumn)
Editor,
#end
},
data() {
return {
// 弹出层标题
dialogTitle: "",
// 是否显示弹出层
dialogVisible: false,
// 表单的加载中1修改时的数据加载2提交的按钮禁用
formLoading: false,
// 表单参数
formData: {
#foreach ($column in $subColumns)
#if ($column.createOperation || $column.updateOperation)
#if ($column.htmlType == "checkbox")
$column.javaField: [],
#else
$column.javaField: undefined,
#end
#end
#end
},
// 表单校验
formRules: {
#foreach ($column in $subColumns)
#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
#set($comment=$column.columnComment)
$column.javaField: [{ required: true, message: "${comment}不能为空", trigger: #if($column.htmlType == "select")"change"#else"blur"#end }],
#end
#end
},
};
},
methods: {
/** 打开弹窗 */
async open(id, ${subJoinColumn.javaField}) {
this.dialogVisible = true;
this.reset();
this.formData.${subJoinColumn.javaField} = ${subJoinColumn.javaField};
// 修改时,设置数据
if (id) {
this.formLoading = true;
try {
const res = await ${simpleClassName}Api.get${subSimpleClassName}(id);
this.formData = res.data;
this.dialogTitle = "修改${subTable.classComment}";
} finally {
this.formLoading = false;
}
}
this.dialogTitle = "新增${subTable.classComment}";
},
/** 提交按钮 */
async submitForm() {
await this.#[[$]]#refs["formRef"].validate();
this.formLoading = true;
try {
const data = this.formData;
// 修改的提交
if (data.${primaryColumn.javaField}) {
await ${simpleClassName}Api.update${subSimpleClassName}(data);
this.#[[$modal]]#.msgSuccess("修改成功");
this.dialogVisible = false;
this.#[[$]]#emit('success');
return;
}
// 添加的提交
await ${simpleClassName}Api.create${subSimpleClassName}(data);
this.#[[$modal]]#.msgSuccess("新增成功");
this.dialogVisible = false;
this.#[[$]]#emit('success');
}finally {
this.formLoading = false;
}
},
/** 表单重置 */
reset() {
this.formData = {
#foreach ($column in $subColumns)
#if ($column.createOperation || $column.updateOperation)
#if ($column.htmlType == "checkbox")
$column.javaField: [],
#else
$column.javaField: undefined,
#end
#end
#end
};
this.resetForm("formRef");
},
}
};
</script>

View File

@@ -0,0 +1,2 @@
## 主表的 normal 和 inner 使用相同的 form 表单
#parse("codegen/vue/views/components/form_sub_normal.vue.vm")

View File

@@ -0,0 +1,347 @@
#set ($subTable = $subTables.get($subIndex))##当前表
#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
<template>
<div class="app-container">
#if ( $subTable.subJoinMany )## 情况一一对多table + form
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-width="0px"
:inline-message="true"
>
<el-table :data="formData" class="-mt-10px">
<el-table-column label="序号" type="index" width="100" />
#foreach($column in $subColumns)
#if ($column.createOperation || $column.updateOperation)
#set ($dictType = $column.dictType)
#set ($javaField = $column.javaField)
#set ($javaType = $column.javaType)
#set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
#set ($comment = $column.columnComment)
#if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
#elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
<el-table-column label="${comment}" min-width="150">
<template v-slot="{ row, $index }">
<el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!">
<el-input v-model="row.${javaField}" placeholder="请输入${comment}" />
</el-form-item>
</template>
</el-table-column>
#elseif($column.htmlType == "imageUpload")## 图片上传
#set ($hasImageUploadColumn = true)
<el-table-column label="${comment}" min-width="200">
<template v-slot="{ row, $index }">
<el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!">
<ImageUpload v-model="row.${javaField}"/>
</el-form-item>
</template>
</el-table-column>
#elseif($column.htmlType == "fileUpload")## 文件上传
#set ($hasFileUploadColumn = true)
<el-table-column label="${comment}" min-width="200">
<template v-slot="{ row, $index }">
<el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!">
<FileUpload v-model="row.${javaField}"/>
</el-form-item>
</template>
</el-table-column>
#elseif($column.htmlType == "editor")## 文本编辑器
#set ($hasEditorColumn = true)
<el-table-column label="${comment}" min-width="400">
<template v-slot="{ row, $index }">
<el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!">
<Editor v-model="row.${javaField}" :min-height="192"/>
</el-form-item>
</template>
</el-table-column>
#elseif($column.htmlType == "select")## 下拉框
<el-table-column label="${comment}" min-width="150">
<template v-slot="{ row, $index }">
<el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!">
<el-select v-model="row.${javaField}" placeholder="请选择${comment}">
#if ("" != $dictType)## 有数据字典
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value" :label="dict.label" #if ($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.value)"#else:value="dict.value"#end />
#else##没数据字典
<el-option label="请选择字典生成" value="" />
#end
</el-select>
</el-form-item>
</template>
</el-table-column>
#elseif($column.htmlType == "checkbox")## 多选框
<el-table-column label="${comment}" min-width="150">
<template v-slot="{ row, $index }">
<el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!">
<el-checkbox-group v-model="row.${javaField}">
#if ("" != $dictType)## 有数据字典
<el-checkbox v-for="dict in this.getDictDatas(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value" #if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.value)"#else:label="dict.value"#end>{{dict.label}}</el-checkbox>
#else##没数据字典
<el-checkbox>请选择字典生成</el-checkbox>
#end
</el-checkbox-group>
</el-form-item>
</template>
</el-table-column>
#elseif($column.htmlType == "radio")## 单选框
<el-table-column label="${comment}" min-width="150">
<template v-slot="{ row, $index }">
<el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!">
<el-radio-group v-model="row.${javaField}">
#if ("" != $dictType)## 有数据字典
<el-radio v-for="dict in this.getDictDatas(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value" #if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.value)"
#else:label="dict.value"#end>{{dict.label}}</el-radio>
#else##没数据字典
<el-radio label="1">请选择字典生成</el-radio>
#end
</el-radio-group>
</el-form-item>
</template>
</el-table-column>
#elseif($column.htmlType == "datetime")## 时间框
<el-table-column label="${comment}" min-width="150">
<template v-slot="{ row, $index }">
<el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!">
<el-date-picker clearable v-model="row.${javaField}" type="date" value-format="timestamp" placeholder="选择${comment}" />
</el-form-item>
</template>
</el-table-column>
#elseif($column.htmlType == "textarea")## 文本框
<el-table-column label="${comment}" min-width="200">
<template v-slot="{ row, $index }">
<el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!">
<el-input v-model="row.${javaField}" type="textarea" placeholder="请输入${comment}" />
</el-form-item>
</template>
</el-table-column>
#end
#end
#end
<el-table-column align="center" fixed="right" label="操作" width="60">
<template v-slot="{ $index }">
<el-link @click="handleDelete($index)">—</el-link>
</template>
</el-table-column>
</el-table>
</el-form>
<el-row justify="center" class="mt-3">
<el-button @click="handleAdd" round>+ 添加${subTable.classComment}</el-button>
</el-row>
#else## 情况二一对一form
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
#foreach($column in $subColumns)
#if ($column.createOperation || $column.updateOperation)
#set ($dictType = $column.dictType)
#set ($javaField = $column.javaField)
#set ($javaType = $column.javaType)
#set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
#set ($comment = $column.columnComment)
#if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
#elseif ($column.htmlType == "input" && !$column.primaryKey)
<el-form-item label="${comment}" prop="${javaField}">
<el-input v-model="formData.${javaField}" placeholder="请输入${comment}" />
</el-form-item>
#elseif($column.htmlType == "imageUpload")## 图片上传
#set ($hasImageUploadColumn = true)
<el-form-item label="${comment}">
<ImageUpload v-model="formData.${javaField}"/>
</el-form-item>
#elseif($column.htmlType == "fileUpload")## 文件上传
#set ($hasFileUploadColumn = true)
<el-form-item label="${comment}">
<FileUpload v-model="formData.${javaField}"/>
</el-form-item>
#elseif($column.htmlType == "editor")## 文本编辑器
#set ($hasEditorColumn = true)
<el-form-item label="${comment}">
<Editor v-model="formData.${javaField}" :min-height="192"/>
</el-form-item>
#elseif($column.htmlType == "select")## 下拉框
<el-form-item label="${comment}" prop="${javaField}">
<el-select v-model="formData.${javaField}" placeholder="请选择${comment}">
#if ("" != $dictType)## 有数据字典
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value" :label="dict.label" #if ($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.value)"#else:value="dict.value"#end />
#else##没数据字典
<el-option label="请选择字典生成" value="" />
#end
</el-select>
</el-form-item>
#elseif($column.htmlType == "checkbox")## 多选框
<el-form-item label="${comment}" prop="${javaField}">
<el-checkbox-group v-model="formData.${javaField}">
#if ("" != $dictType)## 有数据字典
<el-checkbox v-for="dict in this.getDictDatas(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value" #if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.value)"#else:label="dict.value"#end>{{dict.label}}</el-checkbox>
#else##没数据字典
<el-checkbox>请选择字典生成</el-checkbox>
#end
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "radio")## 单选框
<el-form-item label="${comment}" prop="${javaField}">
<el-radio-group v-model="formData.${javaField}">
#if ("" != $dictType)## 有数据字典
<el-radio v-for="dict in this.getDictDatas(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value" #if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.value)"
#else:label="dict.value"#end>{{dict.label}}</el-radio>
#else##没数据字典
<el-radio label="1">请选择字典生成</el-radio>
#end
</el-radio-group>
</el-form-item>
#elseif($column.htmlType == "datetime")## 时间框
<el-form-item label="${comment}" prop="${javaField}">
<el-date-picker clearable v-model="formData.${javaField}" type="date" value-format="timestamp" placeholder="选择${comment}" />
</el-form-item>
#elseif($column.htmlType == "textarea")## 文本框
<el-form-item label="${comment}" prop="${javaField}">
<el-input v-model="formData.${javaField}" type="textarea" placeholder="请输入${comment}" />
</el-form-item>
#end
#end
#end
</el-form>
#end
</div>
</template>
<script>
import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${table.businessName}';
#if ($hasImageUploadColumn)
import ImageUpload from '@/components/ImageUpload';
#end
#if ($hasFileUploadColumn)
import FileUpload from '@/components/FileUpload';
#end
#if ($hasEditorColumn)
import Editor from '@/components/Editor';
#end
export default {
name: "${subSimpleClassName}Form",
components: {
#if ($hasImageUploadColumn)
ImageUpload,
#end
#if ($hasFileUploadColumn)
FileUpload,
#end
#if ($hasEditorColumn)
Editor,
#end
},
props:[
'${subJoinColumn.javaField}'
],// ${subJoinColumn.columnComment}(主表的关联字段)
data() {
return {
// 表单的加载中1修改时的数据加载2提交的按钮禁用
formLoading: false,
// 表单参数
formData: [],
// 表单校验
formRules: {
#foreach ($column in $subColumns)
#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
#set($comment=$column.columnComment)
$column.javaField: [{ required: true, message: "${comment}不能为空", trigger: #if($column.htmlType == "select")"change"#else"blur"#end }],
#end
#end
},
};
},
watch:{/** 监听主表的关联字段的变化,加载对应的子表数据 */
${subJoinColumn.javaField}:{
handler(val) {
// 1. 重置表单
#if ( $subTable.subJoinMany )
this.formData = []
#else
this.formData = {
#foreach ($column in $subColumns)
#if ($column.createOperation || $column.updateOperation)
#if ($column.htmlType == "checkbox")
$column.javaField: [],
#else
$column.javaField: undefined,
#end
#end
#end
}
#end
// 2. val 非空,则加载数据
if (!val) {
return;
}
try {
this.formLoading = true;
// 这里还是需要获取一下 this 的不然取不到 formData
const that = this;
#if ( $subTable.subJoinMany )
${simpleClassName}Api.get${subSimpleClassName}ListBy${SubJoinColumnName}(val).then(function (res){
that.formData = res.data;
})
#else
${simpleClassName}Api.get${subSimpleClassName}By${SubJoinColumnName}(val).then(function (res){
const data = res.data;
if (!data) {
return
}
that.formData = data;
})
#end
} finally {
this.formLoading = false;
}
},
immediate: true
}
},
methods: {
#if ( $subTable.subJoinMany )
/** 新增按钮操作 */
handleAdd() {
const row = {
#foreach ($column in $subColumns)
#if ($column.createOperation || $column.updateOperation)
#if ($column.htmlType == "checkbox")
$column.javaField: [],
#else
$column.javaField: undefined,
#end
#end
#end
}
row.${subJoinColumn.javaField} = this.${subJoinColumn.javaField};
this.formData.push(row);
},
/** 删除按钮操作 */
handleDelete(index) {
this.formData.splice(index, 1);
},
#end
/** 表单校验 */
validate(){
return this.#[[$]]#refs["formRef"].validate();
},
/** 表单值 */
getData(){
return this.formData;
}
}
};
</script>

View File

@@ -0,0 +1,165 @@
#set ($subTable = $subTables.get($subIndex))##当前表
#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
<template>
<div class="app-container">
#if ($table.templateType == 11)
<!-- 操作工具栏 -->
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="openForm(undefined)"
v-hasPermi="['${permissionPrefix}:create']">新增</el-button>
</el-col>
</el-row>
#end
## 列表
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
#foreach($column in $subColumns)
#if ($column.listOperationResult)
#set ($dictType=$column.dictType)
#set ($javaField = $column.javaField)
#set ($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
#set ($comment=$column.columnComment)
#if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
#elseif ($column.javaType == "LocalDateTime")## 时间类型
<el-table-column label="${comment}" align="center" prop="${javaField}" width="180">
<template v-slot="scope">
<span>{{ parseTime(scope.row.${javaField}) }}</span>
</template>
</el-table-column>
#elseif($column.dictType && "" != $column.dictType)## 数据字典
<el-table-column label="${comment}" align="center" prop="${javaField}">
<template v-slot="scope">
<dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.${column.javaField}" />
</template>
</el-table-column>
#else
<el-table-column label="${comment}" align="center" prop="${javaField}" />
#end
#end
#end
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template v-slot="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="openForm(scope.row.${primaryColumn.javaField})"
v-hasPermi="['${permissionPrefix}:update']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
v-hasPermi="['${permissionPrefix}:delete']">删除</el-button>
</template>
</el-table-column>
</el-table>
#if ($table.templateType == 11)
<!-- 分页组件 -->
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
@pagination="getList"/>
<!-- 对话框(添加 / 修改) -->
<${subSimpleClassName}Form ref="formRef" @success="getList" />
#end
</div>
</template>
<script>
import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${table.businessName}';
#if ($table.templateType == 11)
import ${subSimpleClassName}Form from './${subSimpleClassName}Form.vue';
#end
export default {
name: "${subSimpleClassName}List",
#if ($table.templateType == 11)
components: {
${subSimpleClassName}Form
},
#end
props:[
'${subJoinColumn.javaField}'
],// ${subJoinColumn.columnComment}(主表的关联字段)
data() {
return {
// 遮罩层
loading: true,
// 列表的数据
list: [],
#if ($table.templateType == 11)
// 列表的总页数
total: 0,
// 查询参数
queryParams: {
pageNo: 1,
pageSize: 10,
${subJoinColumn.javaField}: undefined
}
#end
};
},
#if ($table.templateType != 11)
created() {
this.getList();
},
#end
watch:{/** 监听主表的关联字段的变化,加载对应的子表数据 */
${subJoinColumn.javaField}:{
handler(val) {
this.queryParams.${subJoinColumn.javaField} = val;
if (val){
this.handleQuery();
}
},
immediate: true
}
},
methods: {
/** 查询列表 */
async getList() {
try {
this.loading = true;
#if ($table.templateType == 11)
const res = await ${simpleClassName}Api.get${subSimpleClassName}Page(this.queryParams);
this.list = res.data.list;
this.total = res.data.total;
#else
#if ( $subTable.subJoinMany )
const res = await ${simpleClassName}Api.get${subSimpleClassName}ListBy${SubJoinColumnName}(this.${subJoinColumn.javaField});
this.list = res.data;
#else
const res = await ${simpleClassName}Api.get${subSimpleClassName}By${SubJoinColumnName}(this.${subJoinColumn.javaField});
const data = res.data;
if (!data) {
return;
}
this.list.push(data);
#end
#end
} finally {
this.loading = false;
}
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNo = 1;
this.getList();
},
#if ($table.templateType == 11)
/** 添加/修改操作 */
openForm(id) {
if (!this.${subJoinColumn.javaField}) {
this.#[[$modal]]#.msgError('请选择一个${table.classComment}');
return;
}
this.#[[$]]#refs["formRef"].open(id, this.${subJoinColumn.javaField});
},
/** 删除按钮操作 */
async handleDelete(row) {
const ${primaryColumn.javaField} = row.${primaryColumn.javaField};
await this.#[[$modal]]#.confirm('是否确认删除${table.classComment}编号为"' + ${primaryColumn.javaField} + '"的数据项?');
try {
await ${simpleClassName}Api.delete${subSimpleClassName}(${primaryColumn.javaField});
await this.getList();
this.#[[$modal]]#.msgSuccess("删除成功");
} catch {}
},
#end
}
};
</script>

View File

@@ -0,0 +1,4 @@
## 子表的 erp 和 inner 使用相似的 list 列表,差异主要两点:
## 1inner 使用 list 不分页erp 使用 page 分页
## 2erp 支持单个子表的新增、修改、删除inner 不支持
#parse("codegen/vue/views/components/list_sub_erp.vue.vm")

View File

@@ -0,0 +1,320 @@
<template>
<div class="app-container">
<!-- 对话框(添加 / 修改) -->
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="45%" v-dialogDrag append-to-body>
<el-form ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-width="100px">
#foreach($column in $columns)
#if ($column.createOperation || $column.updateOperation)
#set ($dictType = $column.dictType)
#set ($javaField = $column.javaField)
#set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
#set ($comment = $column.columnComment)
#if ( $table.templateType == 2 && $column.id == $treeParentColumn.id )
<el-form-item label="${comment}" prop="${javaField}">
<TreeSelect
v-model="formData.${javaField}"
:options="${classNameVar}Tree"
:normalizer="normalizer"
placeholder="请选择${comment}"
/>
</el-form-item>
#elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
<el-form-item label="${comment}" prop="${javaField}">
<el-input v-model="formData.${javaField}" placeholder="请输入${comment}" />
</el-form-item>
#elseif($column.htmlType == "imageUpload")## 图片上传
#set ($hasImageUploadColumn = true)
<el-form-item label="${comment}">
<ImageUpload v-model="formData.${javaField}"/>
</el-form-item>
#elseif($column.htmlType == "fileUpload")## 文件上传
#set ($hasFileUploadColumn = true)
<el-form-item label="${comment}">
<FileUpload v-model="formData.${javaField}"/>
</el-form-item>
#elseif($column.htmlType == "editor")## 文本编辑器
#set ($hasEditorColumn = true)
<el-form-item label="${comment}">
<Editor v-model="formData.${javaField}" :min-height="192"/>
</el-form-item>
#elseif($column.htmlType == "select")## 下拉框
<el-form-item label="${comment}" prop="${javaField}">
<el-select v-model="formData.${javaField}" placeholder="请选择${comment}">
#if ("" != $dictType)## 有数据字典
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value" :label="dict.label" #if ($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.value)"#else:value="dict.value"#end />
#else##没数据字典
<el-option label="请选择字典生成" value="" />
#end
</el-select>
</el-form-item>
#elseif($column.htmlType == "checkbox")## 多选框
<el-form-item label="${comment}" prop="${javaField}">
<el-checkbox-group v-model="formData.${javaField}">
#if ("" != $dictType)## 有数据字典
<el-checkbox v-for="dict in this.getDictDatas(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value" #if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.value)"#else:label="dict.value"#end>{{dict.label}}</el-checkbox>
#else##没数据字典
<el-checkbox>请选择字典生成</el-checkbox>
#end
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "radio")## 单选框
<el-form-item label="${comment}" prop="${javaField}">
<el-radio-group v-model="formData.${javaField}">
#if ("" != $dictType)## 有数据字典
<el-radio v-for="dict in this.getDictDatas(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value" #if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.value)"
#else:label="dict.value"#end>{{dict.label}}</el-radio>
#else##没数据字典
<el-radio label="1">请选择字典生成</el-radio>
#end
</el-radio-group>
</el-form-item>
#elseif($column.htmlType == "datetime")## 时间框
<el-form-item label="${comment}" prop="${javaField}">
<el-date-picker clearable v-model="formData.${javaField}" type="date" value-format="timestamp" placeholder="选择${comment}" />
</el-form-item>
#elseif($column.htmlType == "textarea")## 文本框
<el-form-item label="${comment}" prop="${javaField}">
<el-input v-model="formData.${javaField}" type="textarea" placeholder="请输入内容" />
</el-form-item>
#end
#end
#end
</el-form>
## 特殊:主子表专属逻辑
#if ( $table.templateType == 10 || $table.templateType == 12 )
<!-- 子表的表单 -->
<el-tabs v-model="subTabsName">
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subClassNameVar = $subClassNameVars.get($index))
#set ($subSimpleClassName = $subSimpleClassNames.get($index))
#set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
<el-tab-pane label="${subTable.classComment}" name="$subClassNameVar">
<${subSimpleClassName}Form ref="${subClassNameVar}FormRef" :${subJoinColumn_strikeCase}="formData.id" />
</el-tab-pane>
#end
</el-tabs>
#end
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm" :disabled="formLoading">确 定</el-button>
<el-button @click="dialogVisible = false">取 消</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${table.businessName}';
#if ($hasImageUploadColumn)
import ImageUpload from '@/components/ImageUpload';
#end
#if ($hasFileUploadColumn)
import FileUpload from '@/components/FileUpload';
#end
#if ($hasEditorColumn)
import Editor from '@/components/Editor';
#end
## 特殊:树表专属逻辑
#if ( $table.templateType == 2 )
import TreeSelect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
#end
## 特殊:主子表专属逻辑
#if ( $table.templateType == 10 || $table.templateType == 12 )
#foreach ($subSimpleClassName in $subSimpleClassNames)
import ${subSimpleClassName}Form from './components/${subSimpleClassName}Form.vue'
#end
#end
export default {
name: "${simpleClassName}Form",
components: {
#if ($hasImageUploadColumn)
ImageUpload,
#end
#if ($hasFileUploadColumn)
FileUpload,
#end
#if ($hasEditorColumn)
Editor,
#end
## 特殊:树表专属逻辑
#if ( $table.templateType == 2 )
TreeSelect,
#end
## 特殊:主子表专属逻辑
#if ( $table.templateType == 10 || $table.templateType == 12 )
#foreach ($subSimpleClassName in $subSimpleClassNames)
${subSimpleClassName}Form,
#end
#end
},
data() {
return {
// 弹出层标题
dialogTitle: "",
// 是否显示弹出层
dialogVisible: false,
// 表单的加载中1修改时的数据加载2提交的按钮禁用
formLoading: false,
// 表单参数
formData: {
#foreach ($column in $columns)
#if ($column.createOperation || $column.updateOperation)
#if ($column.htmlType == "checkbox")
$column.javaField: [],
#else
$column.javaField: undefined,
#end
#end
#end
},
// 表单校验
formRules: {
#foreach ($column in $columns)
#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
#set($comment=$column.columnComment)
$column.javaField: [{ required: true, message: '${comment}不能为空', trigger: #if($column.htmlType == 'select')'change'#else'blur'#end }],
#end
#end
},
## 特殊:树表专属逻辑
#if ( $table.templateType == 2 )
${classNameVar}Tree: [], // 树形结构
#end
## 特殊:主子表专属逻辑
#if ( $table.templateType == 10 || $table.templateType == 12 )
#if ( $subTables && $subTables.size() > 0 )
/** 子表的表单 */
subTabsName: '$subClassNameVars.get(0)'
#end
#end
};
},
methods: {
/** 打开弹窗 */
async open(id) {
this.dialogVisible = true;
this.reset();
// 修改时,设置数据
if (id) {
this.formLoading = true;
try {
const res = await ${simpleClassName}Api.get${simpleClassName}(id);
this.formData = res.data;
this.title = "修改${table.classComment}";
} finally {
this.formLoading = false;
}
}
this.title = "新增${table.classComment}";
## 特殊:树表专属逻辑
#if ( $table.templateType == 2 )
await this.get${simpleClassName}Tree();
#end
},
/** 提交按钮 */
async submitForm() {
// 校验主表
await this.$refs["formRef"].validate();
## 特殊:主子表专属逻辑
#if ( $table.templateType == 10 || $table.templateType == 12 )
#if ( $subTables && $subTables.size() > 0 )
// 校验子表
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subClassNameVar = $subClassNameVars.get($index))
try {
## 代码生成后会替换为正确的 refs
await this.refs['${subClassNameVar}FormRef'].validate();
} catch (e) {
this.subTabsName = '${subClassNameVar}';
return;
}
#end
#end
#end
this.formLoading = true;
try {
const data = this.formData;
## 特殊:主子表专属逻辑
#if ( $table.templateType == 10 || $table.templateType == 12 )
#if ( $subTables && $subTables.size() > 0 )
// 拼接子表的数据
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subClassNameVar = $subClassNameVars.get($index))
data.${subClassNameVar}#if ( $subTable.subJoinMany)s#end = this.refs['${subClassNameVar}FormRef'].getData();
#end
#end
#end
// 修改的提交
if (data.${primaryColumn.javaField}) {
await ${simpleClassName}Api.update${simpleClassName}(data);
this.#[[$modal]]#.msgSuccess("修改成功");
this.dialogVisible = false;
this.#[[$]]#emit('success');
return;
}
// 添加的提交
await ${simpleClassName}Api.create${simpleClassName}(data);
this.#[[$modal]]#.msgSuccess("新增成功");
this.dialogVisible = false;
this.#[[$]]#emit('success');
} finally {
this.formLoading = false;
}
},
## 特殊:树表专属逻辑
#if ( $table.templateType == 2 )
/** 获得${table.classComment}树 */
async get${simpleClassName}Tree() {
this.${classNameVar}Tree = [];
const res = await ${simpleClassName}Api.get${simpleClassName}List();
const root = { id: 0, name: '顶级${table.classComment}', children: [] };
root.children = this.handleTree(res.data, 'id', '${treeParentColumn.javaField}')
this.${classNameVar}Tree.push(root)
},
#end
## 特殊:树表专属逻辑
#if ( $table.templateType == 2 )
/** 转换${table.classComment}数据结构 */
normalizer(node) {
if (node.children && !node.children.length) {
delete node.children;
}
#if ($treeNameColumn.javaField == "name")
return {
id: node.id,
label: node.name,
children: node.children
};
#else
return {
id: node.id,
label: node['$treeNameColumn.javaField'],
children: node.children
};
#end
},
#end
/** 表单重置 */
reset() {
this.formData = {
#foreach ($column in $columns)
#if ($column.createOperation || $column.updateOperation)
#if ($column.htmlType == "checkbox")
$column.javaField: [],
#else
$column.javaField: undefined,
#end
#end
#end
};
this.resetForm("formRef");
}
}
};
</script>

View File

@@ -0,0 +1,340 @@
<template>
<div class="app-container">
<!-- 搜索工作栏 -->
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
#foreach($column in $columns)
#if ($column.listOperation)
#set ($dictType=$column.dictType)
#set ($javaField = $column.javaField)
#set ($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
#set ($comment=$column.columnComment)
#if ($column.htmlType == "input")
<el-form-item label="${comment}" prop="${javaField}">
<el-input v-model="queryParams.${javaField}" placeholder="请输入${comment}" clearable @keyup.enter.native="handleQuery"/>
</el-form-item>
#elseif ($column.htmlType == "select" || $column.htmlType == "radio")
<el-form-item label="${comment}" prop="${javaField}">
<el-select v-model="queryParams.${javaField}" placeholder="请选择${comment}" clearable size="small">
#if ("" != $dictType)## 设置了 dictType 数据字典的情况
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value" :label="dict.label" :value="dict.value"/>
#else## 未设置 dictType 数据字典的情况
<el-option label="请选择字典生成" value="" />
#end
</el-select>
</el-form-item>
#elseif($column.htmlType == "datetime")
#if ($column.listOperationCondition != "BETWEEN")## 非范围
<el-form-item label="${comment}" prop="${javaField}">
<el-date-picker clearable v-model="queryParams.${javaField}" type="date" value-format="yyyy-MM-dd" placeholder="选择${comment}" />
</el-form-item>
#else## 范围
<el-form-item label="${comment}" prop="${javaField}">
<el-date-picker v-model="queryParams.${javaField}" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
</el-form-item>
#end
#end
#end
#end
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 操作工具栏 -->
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="openForm(undefined)"
v-hasPermi="['${permissionPrefix}:create']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" :loading="exportLoading"
v-hasPermi="['${permissionPrefix}:export']">导出</el-button>
</el-col>
## 特殊:树表专属逻辑
#if ( $table.templateType == 2 )
<el-col :span="1.5">
<el-button type="danger" plain icon="el-icon-sort" size="mini" @click="toggleExpandAll">
展开/折叠
</el-button>
</el-col>
#end
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
## 特殊:主子表专属逻辑
#if ( $table.templateType == 11 && $subTables && $subTables.size() > 0 )
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:highlight-current-row="true"
:show-overflow-tooltip="true"
@current-change="handleCurrentChange"
>
## 特殊:树表专属逻辑
#elseif ( $table.templateType == 2 )
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
v-if="refreshTable"
row-key="id"
:default-expand-all="isExpandAll"
:tree-props="{children: 'children', hasChildren: 'hasChildren'}"
>
#else
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
#end
## 特殊:主子表专属逻辑
#if ( $table.templateType == 12 && $subTables && $subTables.size() > 0 )
<!-- 子表的列表 -->
<el-table-column type="expand">
<template #default="scope">
<el-tabs value="$subClassNameVars.get(0)">
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subClassNameVar = $subClassNameVars.get($index))
#set ($subSimpleClassName = $subSimpleClassNames.get($index))
#set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
<el-tab-pane label="${subTable.classComment}" name="$subClassNameVar">
<${subSimpleClassName}List :${subJoinColumn_strikeCase}="scope.row.id" />
</el-tab-pane>
#end
</el-tabs>
</template>
</el-table-column>
#end
#foreach($column in $columns)
#if ($column.listOperationResult)
#set ($dictType=$column.dictType)
#set ($javaField = $column.javaField)
#set ($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
#set ($comment=$column.columnComment)
#if ($column.javaType == "LocalDateTime")## 时间类型
<el-table-column label="${comment}" align="center" prop="${javaField}" width="180">
<template v-slot="scope">
<span>{{ parseTime(scope.row.${javaField}) }}</span>
</template>
</el-table-column>
#elseif("" != $column.dictType)## 数据字典
<el-table-column label="${comment}" align="center" prop="${javaField}">
<template v-slot="scope">
<dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.${column.javaField}" />
</template>
</el-table-column>
#else
<el-table-column label="${comment}" align="center" prop="${javaField}" />
#end
#end
#end
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template v-slot="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="openForm(scope.row.${primaryColumn.javaField})"
v-hasPermi="['${permissionPrefix}:update']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
v-hasPermi="['${permissionPrefix}:delete']">删除</el-button>
</template>
</el-table-column>
</el-table>
## 特殊:树表专属逻辑(树不需要分页)
#if ( $table.templateType != 2 )
<!-- 分页组件 -->
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
@pagination="getList"/>
#end
<!-- 对话框(添加 / 修改) -->
<${simpleClassName}Form ref="formRef" @success="getList" />
## 特殊:主子表专属逻辑
#if ( $table.templateType == 11 && $subTables && $subTables.size() > 0 )
<!-- 子表的列表 -->
<el-tabs v-model="subTabsName">
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subClassNameVar = $subClassNameVars.get($index))
#set ($subSimpleClassName = $subSimpleClassNames.get($index))
#set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
<el-tab-pane label="${subTable.classComment}" name="$subClassNameVar">
<${subSimpleClassName}List v-if="currentRow.id" :${subJoinColumn_strikeCase}="currentRow.id" />
</el-tab-pane>
#end
</el-tabs>
#end
</div>
</template>
<script>
import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${table.businessName}';
import ${simpleClassName}Form from './${simpleClassName}Form.vue';
#if ($hasImageUploadColumn)
import ImageUpload from '@/components/ImageUpload';
#end
#if ($hasFileUploadColumn)
import FileUpload from '@/components/FileUpload';
#end
#if ($hasEditorColumn)
import Editor from '@/components/Editor';
#end
## 特殊:主子表专属逻辑
#if ( $table.templateType != 10 )
#if ( $subTables && $subTables.size() > 0 )
#foreach ($subSimpleClassName in $subSimpleClassNames)
import ${subSimpleClassName}List from './components/${subSimpleClassName}List.vue';
#end
#end
#end
export default {
name: "${simpleClassName}",
components: {
${simpleClassName}Form,
## 特殊:主子表专属逻辑
#if ( $table.templateType != 10 )
#if ( $subTables && $subTables.size() > 0 )
#foreach ($subSimpleClassName in $subSimpleClassNames)
${subSimpleClassName}List,
#end
#end
#end
#if ($hasImageUploadColumn)
ImageUpload,
#end
#if ($hasFileUploadColumn)
FileUpload,
#end
#if ($hasEditorColumn)
Editor,
#end
},
data() {
return {
// 遮罩层
loading: true,
// 导出遮罩层
exportLoading: false,
// 显示搜索条件
showSearch: true,
## 特殊:树表专属逻辑(树不需要分页接口)
#if ( $table.templateType != 2 )
// 总条数
total: 0,
#end
// ${table.classComment}列表
list: [],
// 是否展开,默认全部展开
isExpandAll: true,
// 重新渲染表格状态
refreshTable: true,
// 选中行
currentRow: {},
// 查询参数
queryParams: {
## 特殊:树表专属逻辑(树不需要分页接口)
#if ( $table.templateType != 2 )
pageNo: 1,
pageSize: 10,
#end
#foreach ($column in $columns)
#if ($column.listOperation)
#if ($column.listOperationCondition != 'BETWEEN')
$column.javaField: null,
#end
#if ($column.htmlType == "datetime" && $column.listOperationCondition == "BETWEEN")
$column.javaField: [],
#end
#end
#end
},
## 特殊:主子表专属逻辑-erp
#if ( $table.templateType == 11)
#if ( $subTables && $subTables.size() > 0 )
/** 子表的列表 */
subTabsName: '$subClassNameVars.get(0)'
#end
#end
};
},
created() {
this.getList();
},
methods: {
/** 查询列表 */
async getList() {
try {
this.loading = true;
## 特殊:树表专属逻辑(树不需要分页接口)
#if ( $table.templateType == 2 )
const res = await ${simpleClassName}Api.get${simpleClassName}List(this.queryParams);
this.list = this.handleTree(res.data, 'id', '${treeParentColumn.javaField}');
#else
const res = await ${simpleClassName}Api.get${simpleClassName}Page(this.queryParams);
this.list = res.data.list;
this.total = res.data.total;
#end
} finally {
this.loading = false;
}
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNo = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
/** 添加/修改操作 */
openForm(id) {
this.#[[$]]#refs["formRef"].open(id);
},
/** 删除按钮操作 */
async handleDelete(row) {
const ${primaryColumn.javaField} = row.${primaryColumn.javaField};
await this.#[[$modal]]#.confirm('是否确认删除${table.classComment}编号为"' + ${primaryColumn.javaField} + '"的数据项?')
try {
await ${simpleClassName}Api.delete${simpleClassName}(${primaryColumn.javaField});
await this.getList();
this.#[[$modal]]#.msgSuccess("删除成功");
} catch {}
},
/** 导出按钮操作 */
async handleExport() {
await this.#[[$modal]]#.confirm('是否确认导出所有${table.classComment}数据项?');
try {
this.exportLoading = true;
const data = await ${simpleClassName}Api.export${simpleClassName}Excel(this.queryParams);
this.#[[$]]#download.excel(data, '${table.classComment}.xls');
} catch {
} finally {
this.exportLoading = false;
}
},
## 特殊:主子表专属逻辑
#if ( $table.templateType == 11 )
/** 选中行操作 */
handleCurrentChange(row) {
this.currentRow = row;
#if ( $subTables && $subTables.size() > 0 )
/** 子表的列表 */
this.subTabsName = '$subClassNameVars.get(0)';
#end
},
#end
## 特殊:树表专属逻辑
#if ( $table.templateType == 2 )
/** 展开/折叠操作 */
toggleExpandAll() {
this.refreshTable = false
this.isExpandAll = !this.isExpandAll
this.$nextTick(function () {
this.refreshTable = true
})
}
#end
}
};
</script>

View File

@@ -0,0 +1,115 @@
import request from '@/config/axios'
#set ($baseURL = "/${table.moduleName}/${simpleClassName_strikeCase}")
// ${table.classComment} VO
export interface ${simpleClassName}VO {
#foreach ($column in $columns)
#if ($column.createOperation || $column.updateOperation)
#if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer" || ${column.javaType.toLowerCase()} == "short" || ${column.javaType.toLowerCase()} == "double" || ${column.javaType.toLowerCase()} == "bigdecimal")
${column.javaField}: number // ${column.columnComment}
#elseif(${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdate" || ${column.javaType.toLowerCase()} == "localdatetime")
${column.javaField}: Date // ${column.columnComment}
#else
${column.javaField}: ${column.javaType.toLowerCase()} // ${column.columnComment}
#end
#end
#end
}
// ${table.classComment} API
export const ${simpleClassName}Api = {
#if ( $table.templateType != 2 )
// 查询${table.classComment}分页
get${simpleClassName}Page: async (params: any) => {
return await request.get({ url: `${baseURL}/page`, params })
},
#else
// 查询${table.classComment}列表
get${simpleClassName}List: async (params) => {
return await request.get({ url: `${baseURL}/list`, params })
},
#end
// 查询${table.classComment}详情
get${simpleClassName}: async (id: number) => {
return await request.get({ url: `${baseURL}/get?id=` + id })
},
// 新增${table.classComment}
create${simpleClassName}: async (data: ${simpleClassName}VO) => {
return await request.post({ url: `${baseURL}/create`, data })
},
// 修改${table.classComment}
update${simpleClassName}: async (data: ${simpleClassName}VO) => {
return await request.put({ url: `${baseURL}/update`, data })
},
// 删除${table.classComment}
delete${simpleClassName}: async (id: number) => {
return await request.delete({ url: `${baseURL}/delete?id=` + id })
},
// 导出${table.classComment} Excel
export${simpleClassName}: async (params) => {
return await request.download({ url: `${baseURL}/export-excel`, params })
},
## 特殊:主子表专属逻辑
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subSimpleClassName = $subSimpleClassNames.get($index))
#set ($subPrimaryColumn = $subPrimaryColumns.get($index))##当前 primary 字段
#set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段
#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
#set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
#set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
#set ($subClassNameVar = $subClassNameVars.get($index))
// ==================== 子表($subTable.classComment ====================
## 情况一MASTER_ERP 时,需要分查询页子表
#if ( $table.templateType == 11 )
// 获得${subTable.classComment}分页
get${subSimpleClassName}Page: async (params) => {
return await request.get({ url: `${baseURL}/${subSimpleClassName_strikeCase}/page`, params })
},
## 情况二:非 MASTER_ERP 时,需要列表查询子表
#else
#if ( $subTable.subJoinMany )
// 获得${subTable.classComment}列表
get${subSimpleClassName}ListBy${SubJoinColumnName}: async (${subJoinColumn.javaField}) => {
return await request.get({ url: `${baseURL}/${subSimpleClassName_strikeCase}/list-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=` + ${subJoinColumn.javaField} })
},
#else
// 获得${subTable.classComment}
get${subSimpleClassName}By${SubJoinColumnName}: async (${subJoinColumn.javaField}) => {
return await request.get({ url: `${baseURL}/${subSimpleClassName_strikeCase}/get-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=` + ${subJoinColumn.javaField} })
},
#end
#end
## 特殊MASTER_ERP 时,支持单个的新增、修改、删除操作
#if ( $table.templateType == 11 )
// 新增${subTable.classComment}
create${subSimpleClassName}: async (data) => {
return await request.post({ url: `${baseURL}/${subSimpleClassName_strikeCase}/create`, data })
},
// 修改${subTable.classComment}
update${subSimpleClassName}: async (data) => {
return await request.put({ url: `${baseURL}/${subSimpleClassName_strikeCase}/update`, data })
},
// 删除${subTable.classComment}
delete${subSimpleClassName}: async (id: number) => {
return await request.delete({ url: `${baseURL}/${subSimpleClassName_strikeCase}/delete?id=` + id })
},
// 获得${subTable.classComment}
get${subSimpleClassName}: async (id: number) => {
return await request.get({ url: `${baseURL}/${subSimpleClassName_strikeCase}/get?id=` + id })
},
#end
#end
}

View File

@@ -0,0 +1,204 @@
#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
#foreach($column in $subColumns)
#if ($column.createOperation || $column.updateOperation)
#set ($dictType = $column.dictType)
#set ($javaField = $column.javaField)
#set ($javaType = $column.javaType)
#set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
#set ($comment = $column.columnComment)
#set ($dictMethod = "getDictOptions")## 计算使用哪个 dict 字典方法
#if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
#set ($dictMethod = "getIntDictOptions")
#elseif ($javaType == "String")
#set ($dictMethod = "getStrDictOptions")
#elseif ($javaType == "Boolean")
#set ($dictMethod = "getBoolDictOptions")
#end
#if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
#elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
<el-form-item label="${comment}" prop="${javaField}">
<el-input v-model="formData.${javaField}" placeholder="请输入${comment}" />
</el-form-item>
#elseif($column.htmlType == "imageUpload")## 图片上传
<el-form-item label="${comment}" prop="${javaField}">
<UploadImg v-model="formData.${javaField}" />
</el-form-item>
#elseif($column.htmlType == "fileUpload")## 文件上传
<el-form-item label="${comment}" prop="${javaField}">
<UploadFile v-model="formData.${javaField}" />
</el-form-item>
#elseif($column.htmlType == "editor")## 文本编辑器
<el-form-item label="${comment}" prop="${javaField}">
<Editor v-model="formData.${javaField}" height="150px" />
</el-form-item>
#elseif($column.htmlType == "select")## 下拉框
<el-form-item label="${comment}" prop="${javaField}">
<el-select v-model="formData.${javaField}" placeholder="请选择${comment}">
#if ("" != $dictType)## 有数据字典
<el-option
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
#else##没数据字典
<el-option label="请选择字典生成" value="" />
#end
</el-select>
</el-form-item>
#elseif($column.htmlType == "checkbox")## 多选框
<el-form-item label="${comment}" prop="${javaField}">
<el-checkbox-group v-model="formData.${javaField}">
#if ("" != $dictType)## 有数据字典
<el-checkbox
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
#else##没数据字典
<el-checkbox label="请选择字典生成" />
#end
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "radio")## 单选框
<el-form-item label="${comment}" prop="${javaField}">
<el-radio-group v-model="formData.${javaField}">
#if ("" != $dictType)## 有数据字典
<el-radio
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
#else##没数据字典
<el-radio value="1">请选择字典生成</el-radio>
#end
</el-radio-group>
</el-form-item>
#elseif($column.htmlType == "datetime")## 时间框
<el-form-item label="${comment}" prop="${javaField}">
<el-date-picker
v-model="formData.${javaField}"
type="date"
value-format="x"
placeholder="选择${comment}"
/>
</el-form-item>
#elseif($column.htmlType == "textarea")## 文本框
<el-form-item label="${comment}" prop="${javaField}">
<el-input v-model="formData.${javaField}" type="textarea" placeholder="请输入${comment}" />
</el-form-item>
#end
#end
#end
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
<el-button @click="dialogVisible = false">取 消</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { getIntDictOptions, getStrDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
import { ${simpleClassName}Api } from '@/api/${table.moduleName}/${table.businessName}'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中1修改时的数据加载2提交的按钮禁用
const formType = ref('') // 表单的类型create - 新增update - 修改
const formData = ref({
#foreach ($column in $subColumns)
#if ($column.createOperation || $column.updateOperation)
#if ($column.htmlType == "checkbox")
$column.javaField: [],
#else
$column.javaField: undefined,
#end
#end
#end
})
const formRules = reactive({
#foreach ($column in $subColumns)
#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
#set($comment=$column.columnComment)
$column.javaField: [{ required: true, message: '${comment}不能为空', trigger: #if($column.htmlType == 'select')'change'#else'blur'#end }],
#end
#end
})
const formRef = ref() // 表单 Ref
/** 打开弹窗 */
const open = async (type: string, id?: number, ${subJoinColumn.javaField}: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
formData.value.${subJoinColumn.javaField} = ${subJoinColumn.javaField}
// 修改时,设置数据
if (id) {
formLoading.value = true
try {
formData.value = await ${simpleClassName}Api.get${subSimpleClassName}(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
const submitForm = async () => {
// 校验表单
await formRef.value.validate()
// 提交请求
formLoading.value = true
try {
const data = formData.value
if (formType.value === 'create') {
await ${simpleClassName}Api.create${subSimpleClassName}(data)
message.success(t('common.createSuccess'))
} else {
await ${simpleClassName}Api.update${subSimpleClassName}(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
// 发送操作成功的事件
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
#foreach ($column in $subColumns)
#if ($column.createOperation || $column.updateOperation)
#if ($column.htmlType == "checkbox")
$column.javaField: [],
#else
$column.javaField: undefined,
#end
#end
#end
}
formRef.value?.resetFields()
}
</script>

View File

@@ -0,0 +1,2 @@
## 主表的 normal 和 inner 使用相同的 form 表单
#parse("codegen/vue3/views/components/form_sub_normal.vue.vm")

View File

@@ -0,0 +1,360 @@
#set ($subTable = $subTables.get($subIndex))##当前表
#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
<template>
#if ( $subTable.subJoinMany )## 情况一一对多table + form
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-width="0px"
:inline-message="true"
>
<el-table :data="formData" class="-mt-10px">
<el-table-column label="序号" type="index" width="100" />
#foreach($column in $subColumns)
#if ($column.createOperation || $column.updateOperation)
#set ($dictType = $column.dictType)
#set ($javaField = $column.javaField)
#set ($javaType = $column.javaType)
#set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
#set ($comment = $column.columnComment)
#set ($dictMethod = "getDictOptions")## 计算使用哪个 dict 字典方法
#if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
#set ($dictMethod = "getIntDictOptions")
#elseif ($javaType == "String")
#set ($dictMethod = "getStrDictOptions")
#elseif ($javaType == "Boolean")
#set ($dictMethod = "getBoolDictOptions")
#end
#if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
#elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
<el-table-column label="${comment}" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!">
<el-input v-model="row.${javaField}" placeholder="请输入${comment}" />
</el-form-item>
</template>
</el-table-column>
#elseif($column.htmlType == "imageUpload")## 图片上传
<el-table-column label="${comment}" min-width="200">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!">
<UploadImg v-model="row.${javaField}" />
</el-form-item>
</template>
</el-table-column>
#elseif($column.htmlType == "fileUpload")## 文件上传
<el-table-column label="${comment}" min-width="200">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!">
<UploadFile v-model="row.${javaField}" />
</el-form-item>
</template>
</el-table-column>
#elseif($column.htmlType == "editor")## 文本编辑器
<el-table-column label="${comment}" min-width="400">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!">
<Editor v-model="row.${javaField}" height="150px" />
</el-form-item>
</template>
</el-table-column>
#elseif($column.htmlType == "select")## 下拉框
<el-table-column label="${comment}" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!">
<el-select v-model="row.${javaField}" placeholder="请选择${comment}">
#if ("" != $dictType)## 有数据字典
<el-option
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
#else##没数据字典
<el-option label="请选择字典生成" value="" />
#end
</el-select>
</el-form-item>
</template>
</el-table-column>
#elseif($column.htmlType == "checkbox")## 多选框
<el-table-column label="${comment}" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!">
<el-checkbox-group v-model="row.${javaField}">
#if ("" != $dictType)## 有数据字典
<el-checkbox
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
#else##没数据字典
<el-checkbox label="请选择字典生成" />
#end
</el-checkbox-group>
</el-form-item>
</template>
</el-table-column>
#elseif($column.htmlType == "radio")## 单选框
<el-table-column label="${comment}" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!">
<el-radio-group v-model="row.${javaField}">
#if ("" != $dictType)## 有数据字典
<el-radio
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
#else##没数据字典
<el-radio value="1">请选择字典生成</el-radio>
#end
</el-radio-group>
</el-form-item>
</template>
</el-table-column>
#elseif($column.htmlType == "datetime")## 时间框
<el-table-column label="${comment}" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!">
<el-date-picker
v-model="row.${javaField}"
type="date"
value-format="x"
placeholder="选择${comment}"
/>
</el-form-item>
</template>
</el-table-column>
#elseif($column.htmlType == "textarea")## 文本框
<el-table-column label="${comment}" min-width="200">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.${javaField}`" :rules="formRules.${javaField}" class="mb-0px!">
<el-input v-model="row.${javaField}" type="textarea" placeholder="请输入${comment}" />
</el-form-item>
</template>
</el-table-column>
#end
#end
#end
<el-table-column align="center" fixed="right" label="操作" width="60">
<template #default="{ $index }">
<el-button @click="handleDelete($index)" link>—</el-button>
</template>
</el-table-column>
</el-table>
</el-form>
<el-row justify="center" class="mt-3">
<el-button @click="handleAdd" round>+ 添加${subTable.classComment}</el-button>
</el-row>
#else## 情况二一对一form
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
#foreach($column in $subColumns)
#if ($column.createOperation || $column.updateOperation)
#set ($dictType = $column.dictType)
#set ($javaField = $column.javaField)
#set ($javaType = $column.javaType)
#set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
#set ($comment = $column.columnComment)
#set ($dictMethod = "getDictOptions")## 计算使用哪个 dict 字典方法
#if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
#set ($dictMethod = "getIntDictOptions")
#elseif ($javaType == "String")
#set ($dictMethod = "getStrDictOptions")
#elseif ($javaType == "Boolean")
#set ($dictMethod = "getBoolDictOptions")
#end
#if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
#elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
<el-form-item label="${comment}" prop="${javaField}">
<el-input v-model="formData.${javaField}" placeholder="请输入${comment}" />
</el-form-item>
#elseif($column.htmlType == "imageUpload")## 图片上传
<el-form-item label="${comment}" prop="${javaField}">
<UploadImg v-model="formData.${javaField}" />
</el-form-item>
#elseif($column.htmlType == "fileUpload")## 文件上传
<el-form-item label="${comment}" prop="${javaField}">
<UploadFile v-model="formData.${javaField}" />
</el-form-item>
#elseif($column.htmlType == "editor")## 文本编辑器
<el-form-item label="${comment}" prop="${javaField}">
<Editor v-model="formData.${javaField}" height="150px" />
</el-form-item>
#elseif($column.htmlType == "select")## 下拉框
<el-form-item label="${comment}" prop="${javaField}">
<el-select v-model="formData.${javaField}" placeholder="请选择${comment}">
#if ("" != $dictType)## 有数据字典
<el-option
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
#else##没数据字典
<el-option label="请选择字典生成" value="" />
#end
</el-select>
</el-form-item>
#elseif($column.htmlType == "checkbox")## 多选框
<el-form-item label="${comment}" prop="${javaField}">
<el-checkbox-group v-model="formData.${javaField}">
#if ("" != $dictType)## 有数据字典
<el-checkbox
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
#else##没数据字典
<el-checkbox label="请选择字典生成" />
#end
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "radio")## 单选框
<el-form-item label="${comment}" prop="${javaField}">
<el-radio-group v-model="formData.${javaField}">
#if ("" != $dictType)## 有数据字典
<el-radio
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
#else##没数据字典
<el-radio value="1">请选择字典生成</el-radio>
#end
</el-radio-group>
</el-form-item>
#elseif($column.htmlType == "datetime")## 时间框
<el-form-item label="${comment}" prop="${javaField}">
<el-date-picker
v-model="formData.${javaField}"
type="date"
value-format="x"
placeholder="选择${comment}"
/>
</el-form-item>
#elseif($column.htmlType == "textarea")## 文本框
<el-form-item label="${comment}" prop="${javaField}">
<el-input v-model="formData.${javaField}" type="textarea" placeholder="请输入${comment}" />
</el-form-item>
#end
#end
#end
</el-form>
#end
</template>
<script setup lang="ts">
import { getIntDictOptions, getStrDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
import { ${simpleClassName}Api } from '@/api/${table.moduleName}/${table.businessName}'
const props = defineProps<{
${subJoinColumn.javaField}: undefined // ${subJoinColumn.columnComment}(主表的关联字段)
}>()
const formLoading = ref(false) // 表单的加载中
const formData = ref([])
const formRules = reactive({
#foreach ($column in $subColumns)
#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
#set($comment=$column.columnComment)
$column.javaField: [{ required: true, message: '${comment}不能为空', trigger: #if($column.htmlType == 'select')'change'#else'blur'#end }],
#end
#end
})
const formRef = ref() // 表单 Ref
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.${subJoinColumn.javaField},
async (val) => {
// 1. 重置表单
#if ( $subTable.subJoinMany )
formData.value = []
#else
formData.value = {
#foreach ($column in $subColumns)
#if ($column.createOperation || $column.updateOperation)
#if ($column.htmlType == "checkbox")
$column.javaField: [],
#else
$column.javaField: undefined,
#end
#end
#end
}
#end
// 2. val 非空,则加载数据
if (!val) {
return;
}
try {
formLoading.value = true
#if ( $subTable.subJoinMany )
formData.value = await ${simpleClassName}Api.get${subSimpleClassName}ListBy${SubJoinColumnName}(val)
#else
const data = await ${simpleClassName}Api.get${subSimpleClassName}By${SubJoinColumnName}(val)
if (!data) {
return
}
formData.value = data
#end
} finally {
formLoading.value = false
}
},
{ immediate: true }
)
#if ( $subTable.subJoinMany )
/** 新增按钮操作 */
const handleAdd = () => {
const row = {
#foreach ($column in $subColumns)
#if ($column.createOperation || $column.updateOperation)
#if ($column.htmlType == "checkbox")
$column.javaField: [],
#else
$column.javaField: undefined,
#end
#end
#end
}
row.${subJoinColumn.javaField} = props.${subJoinColumn.javaField}
formData.value.push(row)
}
/** 删除按钮操作 */
const handleDelete = (index) => {
formData.value.splice(index, 1)
}
#end
/** 表单校验 */
const validate = () => {
return formRef.value.validate()
}
/** 表单值 */
const getData = () => {
return formData.value
}
defineExpose({ validate, getData })
</script>

View File

@@ -0,0 +1,184 @@
#set ($subTable = $subTables.get($subIndex))##当前表
#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
<template>
<!-- 列表 -->
<ContentWrap>
#if ($table.templateType == 11)
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['${permissionPrefix}:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
#end
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
#foreach($column in $subColumns)
#if ($column.listOperationResult)
#set ($dictType=$column.dictType)
#set ($javaField = $column.javaField)
#set ($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
#set ($comment=$column.columnComment)
#if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
#elseif ($column.javaType == "LocalDateTime")## 时间类型
<el-table-column
label="${comment}"
align="center"
prop="${javaField}"
:formatter="dateFormatter"
width="180px"
/>
#elseif($column.dictType && "" != $column.dictType)## 数据字典
<el-table-column label="${comment}" align="center" prop="${javaField}">
<template #default="scope">
<dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.${column.javaField}" />
</template>
</el-table-column>
#else
<el-table-column label="${comment}" align="center" prop="${javaField}" />
#end
#end
#end
#if ($table.templateType == 11)
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['${permissionPrefix}:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['${permissionPrefix}:delete']"
>
删除
</el-button>
</template>
</el-table-column>
#end
</el-table>
#if ($table.templateType == 11)
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
#end
</ContentWrap>
#if ($table.templateType == 11)
<!-- 表单弹窗:添加/修改 -->
<${subSimpleClassName}Form ref="formRef" @success="getList" />
#end
</template>
<script setup lang="ts">
import { getIntDictOptions, getStrDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import { ${simpleClassName}Api } from '@/api/${table.moduleName}/${table.businessName}'
#if ($table.templateType == 11)
import ${subSimpleClassName}Form from './${subSimpleClassName}Form.vue'
#end
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const props = defineProps<{
${subJoinColumn.javaField}?: number // ${subJoinColumn.columnComment}(主表的关联字段)
}>()
const loading = ref(false) // 列表的加载中
const list = ref([]) // 列表的数据
#if ($table.templateType == 11)
const total = ref(0) // 列表的总页数
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
${subJoinColumn.javaField}: undefined as unknown
})
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.${subJoinColumn.javaField},
(val: number) => {
if (!val) {
return
}
queryParams.${subJoinColumn.javaField} = val
handleQuery()
},
{ immediate: true, deep: true }
)
#end
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
#if ($table.templateType == 11)
const data = await ${simpleClassName}Api.get${subSimpleClassName}Page(queryParams)
list.value = data.list
total.value = data.total
#else
#if ( $subTable.subJoinMany )
list.value = await ${simpleClassName}Api.get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField})
#else
const data = await ${simpleClassName}Api.get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField})
if (!data) {
return
}
list.value.push(data)
#end
#end
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
#if ($table.templateType == 11)
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
if (!props.${subJoinColumn.javaField}) {
message.error('请选择一个${table.classComment}')
return
}
formRef.value.open(type, id, props.${subJoinColumn.javaField})
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
// 删除的二次确认
await message.delConfirm()
// 发起删除
await ${simpleClassName}Api.delete${subSimpleClassName}(id)
message.success(t('common.delSuccess'))
// 刷新列表
await getList()
} catch {}
}
#end
#if ($table.templateType != 11)
/** 初始化 **/
onMounted(() => {
getList()
})
#end
</script>

View File

@@ -0,0 +1,4 @@
## 子表的 erp 和 inner 使用相似的 list 列表,差异主要两点:
## 1inner 使用 list 不分页erp 使用 page 分页
## 2erp 支持单个子表的新增、修改、删除inner 不支持
#parse("codegen/vue3/views/components/list_sub_erp.vue.vm")

View File

@@ -0,0 +1,300 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
#foreach($column in $columns)
#if ($column.createOperation || $column.updateOperation)
#set ($dictType = $column.dictType)
#set ($javaField = $column.javaField)
#set ($javaType = $column.javaType)
#set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
#set ($comment = $column.columnComment)
#set ($dictMethod = "getDictOptions")## 计算使用哪个 dict 字典方法
#if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
#set ($dictMethod = "getIntDictOptions")
#elseif ($javaType == "String")
#set ($dictMethod = "getStrDictOptions")
#elseif ($javaType == "Boolean")
#set ($dictMethod = "getBoolDictOptions")
#end
#if ( $table.templateType == 2 && $column.id == $treeParentColumn.id )
<el-form-item label="${comment}" prop="${javaField}">
<el-tree-select
v-model="formData.${javaField}"
:data="${classNameVar}Tree"
#if ($treeNameColumn.javaField == "name")
:props="defaultProps"
#else
:props="{...defaultProps, label: '$treeNameColumn.javaField'}"
#end
check-strictly
default-expand-all
placeholder="请选择${comment}"
/>
</el-form-item>
#elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
<el-form-item label="${comment}" prop="${javaField}">
<el-input v-model="formData.${javaField}" placeholder="请输入${comment}" />
</el-form-item>
#elseif($column.htmlType == "imageUpload")## 图片上传
<el-form-item label="${comment}" prop="${javaField}">
<UploadImg v-model="formData.${javaField}" />
</el-form-item>
#elseif($column.htmlType == "fileUpload")## 文件上传
<el-form-item label="${comment}" prop="${javaField}">
<UploadFile v-model="formData.${javaField}" />
</el-form-item>
#elseif($column.htmlType == "editor")## 文本编辑器
<el-form-item label="${comment}" prop="${javaField}">
<Editor v-model="formData.${javaField}" height="150px" />
</el-form-item>
#elseif($column.htmlType == "select")## 下拉框
<el-form-item label="${comment}" prop="${javaField}">
<el-select v-model="formData.${javaField}" placeholder="请选择${comment}">
#if ("" != $dictType)## 有数据字典
<el-option
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
#else##没数据字典
<el-option label="请选择字典生成" value="" />
#end
</el-select>
</el-form-item>
#elseif($column.htmlType == "checkbox")## 多选框
<el-form-item label="${comment}" prop="${javaField}">
<el-checkbox-group v-model="formData.${javaField}">
#if ("" != $dictType)## 有数据字典
<el-checkbox
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
#else##没数据字典
<el-checkbox label="请选择字典生成" />
#end
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "radio")## 单选框
<el-form-item label="${comment}" prop="${javaField}">
<el-radio-group v-model="formData.${javaField}">
#if ("" != $dictType)## 有数据字典
<el-radio
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
#else##没数据字典
<el-radio value="1">请选择字典生成</el-radio>
#end
</el-radio-group>
</el-form-item>
#elseif($column.htmlType == "datetime")## 时间框
<el-form-item label="${comment}" prop="${javaField}">
<el-date-picker
v-model="formData.${javaField}"
type="date"
value-format="x"
placeholder="选择${comment}"
/>
</el-form-item>
#elseif($column.htmlType == "textarea")## 文本框
<el-form-item label="${comment}" prop="${javaField}">
<el-input v-model="formData.${javaField}" type="textarea" placeholder="请输入${comment}" />
</el-form-item>
#end
#end
#end
</el-form>
## 特殊:主子表专属逻辑
#if ( $table.templateType == 10 || $table.templateType == 12 )
<!-- 子表的表单 -->
<el-tabs v-model="subTabsName">
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subClassNameVar = $subClassNameVars.get($index))
#set ($subSimpleClassName = $subSimpleClassNames.get($index))
#set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
<el-tab-pane label="${subTable.classComment}" name="$subClassNameVar">
<${subSimpleClassName}Form ref="${subClassNameVar}FormRef" :${subJoinColumn_strikeCase}="formData.id" />
</el-tab-pane>
#end
</el-tabs>
#end
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
<el-button @click="dialogVisible = false">取 消</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { getIntDictOptions, getStrDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
import { ${simpleClassName}Api, ${simpleClassName}VO } from '@/api/${table.moduleName}/${table.businessName}'
## 特殊:树表专属逻辑
#if ( $table.templateType == 2 )
import { defaultProps, handleTree } from '@/utils/tree'
#end
## 特殊:主子表专属逻辑
#if ( $table.templateType == 10 || $table.templateType == 12 )
#foreach ($subSimpleClassName in $subSimpleClassNames)
import ${subSimpleClassName}Form from './components/${subSimpleClassName}Form.vue'
#end
#end
/** ${table.classComment} 表单 */
defineOptions({ name: '${simpleClassName}Form' })
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中1修改时的数据加载2提交的按钮禁用
const formType = ref('') // 表单的类型create - 新增update - 修改
const formData = ref({
#foreach ($column in $columns)
#if ($column.createOperation || $column.updateOperation)
#if ($column.htmlType == "checkbox")
$column.javaField: [],
#else
$column.javaField: undefined,
#end
#end
#end
})
const formRules = reactive({
#foreach ($column in $columns)
#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
#set($comment=$column.columnComment)
$column.javaField: [{ required: true, message: '${comment}不能为空', trigger: #if($column.htmlType == 'select')'change'#else'blur'#end }],
#end
#end
})
const formRef = ref() // 表单 Ref
## 特殊:树表专属逻辑
#if ( $table.templateType == 2 )
const ${classNameVar}Tree = ref() // 树形结构
#end
## 特殊:主子表专属逻辑
#if ( $table.templateType == 10 || $table.templateType == 12 )
#if ( $subTables && $subTables.size() > 0 )
/** 子表的表单 */
const subTabsName = ref('$subClassNameVars.get(0)')
#foreach ($subClassNameVar in $subClassNameVars)
const ${subClassNameVar}FormRef = ref()
#end
#end
#end
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
// 修改时,设置数据
if (id) {
formLoading.value = true
try {
formData.value = await ${simpleClassName}Api.get${simpleClassName}(id)
} finally {
formLoading.value = false
}
}
## 特殊:树表专属逻辑
#if ( $table.templateType == 2 )
await get${simpleClassName}Tree()
#end
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
const submitForm = async () => {
// 校验表单
await formRef.value.validate()
## 特殊:主子表专属逻辑
#if ( $table.templateType == 10 || $table.templateType == 12 )
#if ( $subTables && $subTables.size() > 0 )
// 校验子表单
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subClassNameVar = $subClassNameVars.get($index))
try {
await ${subClassNameVar}FormRef.value.validate()
} catch (e) {
subTabsName.value = '${subClassNameVar}'
return
}
#end
#end
#end
// 提交请求
formLoading.value = true
try {
const data = formData.value as unknown as ${simpleClassName}VO
## 特殊:主子表专属逻辑
#if ( $table.templateType == 10 || $table.templateType == 12 )
#if ( $subTables && $subTables.size() > 0 )
// 拼接子表的数据
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subClassNameVar = $subClassNameVars.get($index))
data.${subClassNameVar}#if ( $subTable.subJoinMany)s#end = ${subClassNameVar}FormRef.value.getData()
#end
#end
#end
if (formType.value === 'create') {
await ${simpleClassName}Api.create${simpleClassName}(data)
message.success(t('common.createSuccess'))
} else {
await ${simpleClassName}Api.update${simpleClassName}(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
// 发送操作成功的事件
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
#foreach ($column in $columns)
#if ($column.createOperation || $column.updateOperation)
#if ($column.htmlType == "checkbox")
$column.javaField: [],
#else
$column.javaField: undefined,
#end
#end
#end
}
formRef.value?.resetFields()
}
## 特殊:树表专属逻辑
#if ( $table.templateType == 2 )
/** 获得${table.classComment}树 */
const get${simpleClassName}Tree = async () => {
${classNameVar}Tree.value = []
const data = await ${simpleClassName}Api.get${simpleClassName}List()
const root: Tree = { id: 0, name: '顶级${table.classComment}', children: [] }
root.children = handleTree(data, 'id', '${treeParentColumn.javaField}')
${classNameVar}Tree.value.push(root)
}
#end
</script>

View File

@@ -0,0 +1,374 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
#foreach($column in $columns)
#if ($column.listOperation)
#set ($dictType = $column.dictType)
#set ($javaField = $column.javaField)
#set ($javaType = $column.javaType)
#set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
#set ($comment = $column.columnComment)
#set ($dictMethod = "getDictOptions")## 计算使用哪个 dict 字典方法
#if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
#set ($dictMethod = "getIntDictOptions")
#elseif ($javaType == "String")
#set ($dictMethod = "getStrDictOptions")
#elseif ($javaType == "Boolean")
#set ($dictMethod = "getBoolDictOptions")
#end
#if ($column.htmlType == "input")
<el-form-item label="${comment}" prop="${javaField}">
<el-input
v-model="queryParams.${javaField}"
placeholder="请输入${comment}"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
#elseif ($column.htmlType == "select" || $column.htmlType == "radio")
<el-form-item label="${comment}" prop="${javaField}">
<el-select
v-model="queryParams.${javaField}"
placeholder="请选择${comment}"
clearable
class="!w-240px"
>
#if ("" != $dictType)## 设置了 dictType 数据字典的情况
<el-option
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
#else## 未设置 dictType 数据字典的情况
<el-option label="请选择字典生成" value="" />
#end
</el-select>
</el-form-item>
#elseif($column.htmlType == "datetime")
#if ($column.listOperationCondition != "BETWEEN")## 非范围
<el-form-item label="${comment}" prop="${javaField}">
<el-date-picker
v-model="queryParams.${javaField}"
value-format="YYYY-MM-DD"
type="date"
placeholder="选择${comment}"
clearable
class="!w-240px"
/>
</el-form-item>
#else## 范围
<el-form-item label="${comment}" prop="${javaField}">
<el-date-picker
v-model="queryParams.${javaField}"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
#end
#end
#end
#end
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['${permissionPrefix}:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['${permissionPrefix}:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
## 特殊:树表专属逻辑
#if ( $table.templateType == 2 )
<el-button type="danger" plain @click="toggleExpandAll">
<Icon icon="ep:sort" class="mr-5px" /> 展开/折叠
</el-button>
#end
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
## 特殊:主子表专属逻辑
#if ( $table.templateType == 11 && $subTables && $subTables.size() > 0 )
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
highlight-current-row
@current-change="handleCurrentChange"
>
## 特殊:树表专属逻辑
#elseif ( $table.templateType == 2 )
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
row-key="id"
:default-expand-all="isExpandAll"
v-if="refreshTable"
>
#else
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
#end
## 特殊:主子表专属逻辑
#if ( $table.templateType == 12 && $subTables && $subTables.size() > 0 )
<!-- 子表的列表 -->
<el-table-column type="expand">
<template #default="scope">
<el-tabs model-value="$subClassNameVars.get(0)">
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subClassNameVar = $subClassNameVars.get($index))
#set ($subSimpleClassName = $subSimpleClassNames.get($index))
#set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
<el-tab-pane label="${subTable.classComment}" name="$subClassNameVar">
<${subSimpleClassName}List :${subJoinColumn_strikeCase}="scope.row.id" />
</el-tab-pane>
#end
</el-tabs>
</template>
</el-table-column>
#end
#foreach($column in $columns)
#if ($column.listOperationResult)
#set ($dictType=$column.dictType)
#set ($javaField = $column.javaField)
#set ($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
#set ($comment=$column.columnComment)
#if ($column.javaType == "LocalDateTime")## 时间类型
<el-table-column
label="${comment}"
align="center"
prop="${javaField}"
:formatter="dateFormatter"
width="180px"
/>
#elseif($column.dictType && "" != $column.dictType)## 数据字典
<el-table-column label="${comment}" align="center" prop="${javaField}">
<template #default="scope">
<dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.${column.javaField}" />
</template>
</el-table-column>
#else
<el-table-column label="${comment}" align="center" prop="${javaField}" />
#end
#end
#end
<el-table-column label="操作" align="center" min-width="120px">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['${permissionPrefix}:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['${permissionPrefix}:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗:添加/修改 -->
<${simpleClassName}Form ref="formRef" @success="getList" />
## 特殊:主子表专属逻辑
#if ( $table.templateType == 11 && $subTables && $subTables.size() > 0 )
<!-- 子表的列表 -->
<ContentWrap>
<el-tabs model-value="$subClassNameVars.get(0)">
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subClassNameVar = $subClassNameVars.get($index))
#set ($subSimpleClassName = $subSimpleClassNames.get($index))
#set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
<el-tab-pane label="${subTable.classComment}" name="$subClassNameVar">
<${subSimpleClassName}List :${subJoinColumn_strikeCase}="currentRow.id" />
</el-tab-pane>
#end
</el-tabs>
</ContentWrap>
#end
</template>
<script setup lang="ts">
import { getIntDictOptions, getStrDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
## 特殊:树表专属逻辑
#if ( $table.templateType == 2 )
import { handleTree } from '@/utils/tree'
#end
import download from '@/utils/download'
import { ${simpleClassName}Api, ${simpleClassName}VO } from '@/api/${table.moduleName}/${table.businessName}'
import ${simpleClassName}Form from './${simpleClassName}Form.vue'
## 特殊:主子表专属逻辑
#if ( $table.templateType != 10 )
#foreach ($subSimpleClassName in $subSimpleClassNames)
import ${subSimpleClassName}List from './components/${subSimpleClassName}List.vue'
#end
#end
/** ${table.classComment} 列表 */
defineOptions({ name: '${table.className}' })
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
const loading = ref(true) // 列表的加载中
const list = ref<${simpleClassName}VO[]>([]) // 列表的数据
## 特殊:树表专属逻辑(树不需要分页接口)
#if ( $table.templateType != 2 )
const total = ref(0) // 列表的总页数
#end
const queryParams = reactive({
## 特殊:树表专属逻辑(树不需要分页接口)
#if ( $table.templateType != 2 )
pageNo: 1,
pageSize: 10,
#end
#foreach ($column in $columns)
#if ($column.listOperation)
#if ($column.listOperationCondition != 'BETWEEN')
$column.javaField: undefined,
#end
#if ($column.htmlType == "datetime" || $column.listOperationCondition == "BETWEEN")
$column.javaField: [],
#end
#end
#end
})
const queryFormRef = ref() // 搜索的表单
const exportLoading = ref(false) // 导出的加载中
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
## 特殊:树表专属逻辑(树不需要分页接口)
#if ( $table.templateType == 2 )
const data = await ${simpleClassName}Api.get${simpleClassName}List(queryParams)
list.value = handleTree(data, 'id', '${treeParentColumn.javaField}')
#else
const data = await ${simpleClassName}Api.get${simpleClassName}Page(queryParams)
list.value = data.list
total.value = data.total
#end
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
// 删除的二次确认
await message.delConfirm()
// 发起删除
await ${simpleClassName}Api.delete${simpleClassName}(id)
message.success(t('common.delSuccess'))
// 刷新列表
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
// 导出的二次确认
await message.exportConfirm()
// 发起导出
exportLoading.value = true
const data = await ${simpleClassName}Api.export${simpleClassName}(queryParams)
download.excel(data, '${table.classComment}.xls')
} catch {
} finally {
exportLoading.value = false
}
}
## 特殊:主子表专属逻辑
#if ( $table.templateType == 11 )
/** 选中行操作 */
const currentRow = ref({}) // 选中行
const handleCurrentChange = (row) => {
currentRow.value = row
}
#end
## 特殊:树表专属逻辑
#if ( $table.templateType == 2 )
/** 展开/折叠操作 */
const isExpandAll = ref(true) // 是否展开,默认全部展开
const refreshTable = ref(true) // 重新渲染表格状态
const toggleExpandAll = async () => {
refreshTable.value = false
isExpandAll.value = !isExpandAll.value
await nextTick()
refreshTable.value = true
}
#end
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

View File

@@ -0,0 +1,32 @@
import { defHttp } from '@/utils/http/axios'
#set ($baseURL = "/${table.moduleName}/${simpleClassName_strikeCase}")
// 查询${table.classComment}列表
export function get${simpleClassName}Page(params) {
return defHttp.get({ url: '${baseURL}/page', params })
}
// 查询${table.classComment}详情
export function get${simpleClassName}(id: number) {
return defHttp.get({ url: `${baseURL}/get?id=${id}` })
}
// 新增${table.classComment}
export function create${simpleClassName}(data) {
return defHttp.post({ url: '${baseURL}/create', data })
}
// 修改${table.classComment}
export function update${simpleClassName}(data) {
return defHttp.put({ url: '${baseURL}/update', data })
}
// 删除${table.classComment}
export function delete${simpleClassName}(id: number) {
return defHttp.delete({ url: `${baseURL}/delete?id=${id}` })
}
// 导出${table.classComment} Excel
export function export${simpleClassName}(params) {
return defHttp.download({ url: '${baseURL}/export-excel', params }, '${table.classComment}.xls')
}

View File

@@ -0,0 +1,260 @@
import type {BasicColumn, FormSchema} from '@/components/Table'
import {useRender} from '@/components/Table'
import {DICT_TYPE, getDictOptions} from '@/utils/dict'
export const columns: BasicColumn[] = [
#foreach($column in $columns)
#if ($column.listOperationResult)
#set ($dictType=$column.dictType)
#set ($javaField = $column.javaField)
#set ($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
#set ($comment=$column.columnComment)
#if ($column.javaType == "LocalDateTime")## 时间类型
{
title: '${comment}',
dataIndex: '${javaField}',
width: 180,
customRender: ({ text }) => {
return useRender.renderDate(text)
},
},
#elseif("" != $column.dictType)## 数据字典
{
title: '${comment}',
dataIndex: '${javaField}',
width: 180,
customRender: ({ text }) => {
return useRender.renderDict(text, DICT_TYPE.$dictType.toUpperCase())
},
},
#else
{
title: '${comment}',
dataIndex: '${javaField}',
width: 160,
},
#end
#end
#end
]
export const searchFormSchema: FormSchema[] = [
#foreach($column in $columns)
#if ($column.listOperation)
#set ($dictType=$column.dictType)
#set ($javaType = $column.javaType)
#set ($javaField = $column.javaField)
#set ($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
#set ($comment=$column.columnComment)
#if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
#set ($dictMethod = "number")
#elseif ($javaType == "String")
#set ($dictMethod = "string")
#elseif ($javaType == "Boolean")
#set ($dictMethod = "boolean")
#end
{
label: '${comment}',
field: '${javaField}',
#if ($column.htmlType == "input")
component: 'Input',
#elseif ($column.htmlType == "select")
component: 'Select',
componentProps: {
#if ("" != $dictType)## 设置了 dictType 数据字典的情况
options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
#else## 未设置 dictType 数据字典的情况
options: [],
#end
},
#elseif ($column.htmlType == "radio")
component: 'RadioButtonGroup',
componentProps: {
#if ("" != $dictType)## 设置了 dictType 数据字典的情况
options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
#else## 未设置 dictType 数据字典的情况
options: [],
#end
},
#elseif($column.htmlType == "datetime")
component: 'RangePicker',
#end
colProps: { span: 8 },
},
#end
#end
]
export const createFormSchema: FormSchema[] = [
{
label: '编号',
field: 'id',
show: false,
component: 'Input',
},
#foreach($column in $columns)
#if ($column.createOperation)
#set ($dictType = $column.dictType)
#set ($javaType = $column.javaType)
#set ($javaField = $column.javaField)
#set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
#set ($comment = $column.columnComment)
#if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
#set ($dictMethod = "number")
#elseif ($javaType == "String")
#set ($dictMethod = "string")
#elseif ($javaType == "Boolean")
#set ($dictMethod = "boolean")
#end
#if (!$column.primaryKey)## 忽略主键,不用在表单里
{
label: '${comment}',
field: '${javaField}',
#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
required: true,
#end
#if ($column.htmlType == "input")
component: 'Input',
#elseif($column.htmlType == "imageUpload")## 图片上传
component: 'FileUpload',
componentProps: {
fileType: 'image',
maxCount: 1,
},
#elseif($column.htmlType == "fileUpload")## 文件上传
component: 'FileUpload',
componentProps: {
fileType: 'file',
maxCount: 1,
},
#elseif($column.htmlType == "editor")## 文本编辑器
component: 'Editor',
#elseif($column.htmlType == "select")## 下拉框
component: 'Select',
componentProps: {
#if ("" != $dictType)## 有数据字典
options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
#else##没数据字典
options:[],
#end
},
#elseif($column.htmlType == "checkbox")## 多选框
component: 'Checkbox',
componentProps: {
#if ("" != $dictType)## 有数据字典
options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
#else##没数据字典
options:[],
#end
},
#elseif($column.htmlType == "radio")## 单选框
component: 'RadioButtonGroup',
componentProps: {
#if ("" != $dictType)## 有数据字典
options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
#else##没数据字典
options:[],
#end
},
#elseif($column.htmlType == "datetime")## 时间框
component: 'DatePicker',
componentProps: {
showTime: true,
format: 'YYYY-MM-DD HH:mm:ss',
valueFormat: 'x',
},
#elseif($column.htmlType == "textarea")## 文本域
component: 'InputTextArea',
#end
},
#end
#end
#end
]
export const updateFormSchema: FormSchema[] = [
{
label: '编号',
field: 'id',
show: false,
component: 'Input',
},
#foreach($column in $columns)
#if ($column.updateOperation)
#set ($dictType = $column.dictType)
#set ($javaType = $column.javaType)
#set ($javaField = $column.javaField)
#set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
#set ($comment = $column.columnComment)
#if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
#set ($dictMethod = "number")
#elseif ($javaType == "String")
#set ($dictMethod = "string")
#elseif ($javaType == "Boolean")
#set ($dictMethod = "boolean")
#end
#if (!$column.primaryKey)## 忽略主键,不用在表单里
{
label: '${comment}',
field: '${javaField}',
#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
required: true,
#end
#if ($column.htmlType == "input")
component: 'Input',
#elseif($column.htmlType == "imageUpload")## 图片上传
component: 'FileUpload',
componentProps: {
fileType: 'image',
maxCount: 1,
},
#elseif($column.htmlType == "fileUpload")## 文件上传
component: 'FileUpload',
componentProps: {
fileType: 'file',
maxCount: 1,
},
#elseif($column.htmlType == "editor")## 文本编辑器
component: 'Editor',
#elseif($column.htmlType == "select")## 下拉框
component: 'Select',
componentProps: {
#if ("" != $dictType)## 有数据字典
options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
#else##没数据字典
options:[],
#end
},
#elseif($column.htmlType == "checkbox")## 多选框
component: 'Checkbox',
componentProps: {
#if ("" != $dictType)## 有数据字典
options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
#else##没数据字典
options:[],
#end
},
#elseif($column.htmlType == "radio")## 单选框
component: 'RadioButtonGroup',
componentProps: {
#if ("" != $dictType)## 有数据字典
options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
#else##没数据字典
options:[],
#end
},
#elseif($column.htmlType == "datetime")## 时间框
component: 'DatePicker',
componentProps: {
showTime: true,
format: 'YYYY-MM-DD HH:mm:ss',
valueFormat: 'x',
},
#elseif($column.htmlType == "textarea")## 文本域
component: 'InputTextArea',
#end
},
#end
#end
#end
]

View File

@@ -0,0 +1,58 @@
<script lang="ts" setup>
import { ref, unref } from 'vue'
import { createFormSchema, updateFormSchema } from './${classNameVar}.data'
import { useI18n } from '@/hooks/web/useI18n'
import { useMessage } from '@/hooks/web/useMessage'
import { BasicForm, useForm } from '@/components/Form'
import { BasicModal, useModalInner } from '@/components/Modal'
import { create${simpleClassName}, get${simpleClassName}, update${simpleClassName} } from '@/api/${table.moduleName}/${table.businessName}'
defineOptions({ name: '${table.className}Modal' })
const emit = defineEmits(['success', 'register'])
const { t } = useI18n()
const { createMessage } = useMessage()
const isUpdate = ref(true)
const [registerForm, { setFieldsValue, resetFields, resetSchema, validate }] = useForm({
labelWidth: 120,
baseColProps: { span: 24 },
schemas: createFormSchema,
showActionButtonGroup: false,
actionColOptions: { span: 23 },
})
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
resetFields()
setModalProps({ confirmLoading: false })
isUpdate.value = !!data?.isUpdate
if (unref(isUpdate)) {
resetSchema(updateFormSchema)
const res = await get${simpleClassName}(data.record.id)
setFieldsValue({ ...res })
}
})
async function handleSubmit() {
try {
const values = await validate()
setModalProps({ confirmLoading: true })
if (unref(isUpdate))
await update${simpleClassName}(values)
else
await create${simpleClassName}(values)
closeModal()
emit('success')
createMessage.success(t('common.saveSuccessText'))
} finally {
setModalProps({ confirmLoading: false })
}
}
</script>
<template>
<BasicModal v-bind="$attrs" :title="isUpdate ? t('action.edit') : t('action.create')" @register="registerModal" @ok="handleSubmit">
<BasicForm @register="registerForm" />
</BasicModal>
</template>

View File

@@ -0,0 +1,92 @@
<script lang="ts" setup>
import ${simpleClassName}Modal from './${simpleClassName}Modal.vue'
import { columns, searchFormSchema } from './${classNameVar}.data'
import { useI18n } from '@/hooks/web/useI18n'
import { useMessage } from '@/hooks/web/useMessage'
import { useModal } from '@/components/Modal'
import { IconEnum } from '@/enums/appEnum'
import { BasicTable, TableAction, useTable } from '@/components/Table'
import { delete${simpleClassName}, export${simpleClassName}, get${simpleClassName}Page } from '@/api/${table.moduleName}/${table.businessName}'
defineOptions({ name: '${table.className}' })
const { t } = useI18n()
const { createConfirm, createMessage } = useMessage()
const [registerModal, { openModal }] = useModal()
const [registerTable, { getForm, reload }] = useTable({
title: '${table.classComment}列表',
api: get${simpleClassName}Page,
columns,
formConfig: { labelWidth: 120, schemas: searchFormSchema },
useSearchForm: true,
showTableSetting: true,
actionColumn: {
width: 140,
title: t('common.action'),
dataIndex: 'action',
fixed: 'right',
},
})
function handleCreate() {
openModal(true, { isUpdate: false })
}
function handleEdit(record: Recordable) {
openModal(true, { record, isUpdate: true })
}
async function handleExport() {
createConfirm({
title: t('common.exportTitle'),
iconType: 'warning',
content: t('common.exportMessage'),
async onOk() {
await export${simpleClassName}(getForm().getFieldsValue())
createMessage.success(t('common.exportSuccessText'))
},
})
}
async function handleDelete(record: Recordable) {
await delete${simpleClassName}(record.id)
createMessage.success(t('common.delSuccessText'))
reload()
}
</script>
<template>
<div>
<BasicTable @register="registerTable">
<template #toolbar>
<a-button type="primary" v-auth="['${permissionPrefix}:create']" :preIcon="IconEnum.ADD" @click="handleCreate">
{{ t('action.create') }}
</a-button>
<a-button v-auth="['${permissionPrefix}:export']" :preIcon="IconEnum.EXPORT" @click="handleExport">
{{ t('action.export') }}
</a-button>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction
:actions="[
{ icon: IconEnum.EDIT, label: t('action.edit'), auth: '${permissionPrefix}:update', onClick: handleEdit.bind(null, record) },
{
icon: IconEnum.DELETE,
danger: true,
label: t('action.delete'),
auth: '${permissionPrefix}:delete',
popConfirm: {
title: t('common.delMessage'),
placement: 'left',
confirm: handleDelete.bind(null, record),
},
},
]"
/>
</template>
</template>
</BasicTable>
<${simpleClassName}Modal @register="registerModal" @success="reload()" />
</div>
</template>

View File

@@ -121,15 +121,13 @@ public class ProdController {
/* @GetMapping("/getProdInfo")
@GetMapping("/get") @Operation(summary = "获得商品详情a")
@Operation(summary = "获得商品")
@Parameter(name = "id", description = "编号", required = true, example = "1024") @Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('tashow-module-product:prod:query')") public CommonResult<ProdDO> getProdInfo(@RequestParam("id") Long id) {
public CommonResult<ProdRespVO> getProd(@RequestParam("id") Long id) {
ProdDO prod = prodService.getProd(id); ProdDO prod = prodService.getProd(id);
return success(BeanUtils.toBean(prod, ProdRespVO.class)); return success(prod);
}*/ }
@PermitAll @PermitAll
@GetMapping("/page") @GetMapping("/page")

View File

@@ -7,10 +7,10 @@ spring:
username: nacos # Nacos 账号 username: nacos # Nacos 账号
password: nacos # Nacos 密码 password: nacos # Nacos 密码
discovery: # 【配置中心】配置项 discovery: # 【配置中心】配置项
namespace: 16bd40df-7cc7-4c2c-82c2-6186ade7bb08 # 命名空间。这里使用 dev 开发环境 namespace: dev # 命名空间。这里使用 dev 开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
metadata: metadata:
version: 1.0.0 # 服务实例的版本号,可用于灰度发布 version: 1.0.0 # 服务实例的版本号,可用于灰度发布
config: # 【注册中心】配置项 config: # 【注册中心】配置项
namespace: 16bd40df-7cc7-4c2c-82c2-6186ade7bb08 # 命名空间。这里使用 dev 开发环境 namespace: dev # 命名空间。这里使用 dev 开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP

View File

@@ -585,7 +585,7 @@
<select id="getProdPageList" resultMap="ProdListMap" > <select id="getProdPageList" resultMap="ProdListMap" >
select tp.prod_id,tp.prod_name,tp.category_name,tp.shop_id,tsd.shop_name,tpsa.area_name,min_eri.response_hours, select tp.prod_id,tp.prod_name,tp.category_name,tp.shop_id,tsd.shop_name,tpsa.area_name,min_eri.response_hours,
tprc.reservation_time_slots,tp.delete_time,tp.create_time,tp.update_time,tp.status,tp.is_prohibit, tprc.reservation_time_slots,tp.delete_time,tp.create_time,tp.update_time,tp.status,tp.is_prohibit,tp.pic,
tp.process_notes processNotes tp.process_notes processNotes
from tz_prod tp from tz_prod tp
left join tz_shop_detail tsd on tp.shop_id = tsd.shop_id left join tz_shop_detail tsd on tp.shop_id = tsd.shop_id

View File

@@ -70,6 +70,7 @@ public class OAuth2AccessTokenDO extends TenantBaseDO {
/** /**
* 过期时间 * 过期时间
*/ */
private LocalDateTime expiresTime; private LocalDateTime expiresTime;
} }

View File

@@ -4,7 +4,6 @@ package com.tashow.cloud.trade.controller.admin.aftersale.vo;
import com.tashow.cloud.trade.controller.admin.aftersale.vo.log.AfterSaleLogRespVO; import com.tashow.cloud.trade.controller.admin.aftersale.vo.log.AfterSaleLogRespVO;
import com.tashow.cloud.trade.controller.admin.base.member.user.MemberUserRespVO; import com.tashow.cloud.trade.controller.admin.base.member.user.MemberUserRespVO;
import com.tashow.cloud.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO;
import com.tashow.cloud.trade.controller.admin.order.vo.TradeOrderBaseVO; import com.tashow.cloud.trade.controller.admin.order.vo.TradeOrderBaseVO;
import com.tashow.cloud.trade.controller.admin.order.vo.TradeOrderItemBaseVO; import com.tashow.cloud.trade.controller.admin.order.vo.TradeOrderItemBaseVO;
import lombok.Data; import lombok.Data;
@@ -43,11 +42,6 @@ public class AfterSaleDetailRespVO extends AfterSaleBaseVO {
@Data @Data
public static class OrderItem extends TradeOrderItemBaseVO { public static class OrderItem extends TradeOrderItemBaseVO {
/**
* 属性数组
*/
private List<ProductPropertyValueDetailRespVO> properties;
} }
} }

View File

@@ -5,8 +5,9 @@ import com.tashow.cloud.common.pojo.CommonResult;
import com.tashow.cloud.common.pojo.PageResult; import com.tashow.cloud.common.pojo.PageResult;
import com.tashow.cloud.memberapi.api.user.MemberUserApi; import com.tashow.cloud.memberapi.api.user.MemberUserApi;
import com.tashow.cloud.trade.controller.admin.order.vo.TradeOrderDetailRespVO; import com.tashow.cloud.trade.controller.admin.order.vo.TradeOrderDetailRespVO;
import com.tashow.cloud.trade.controller.admin.order.vo.TradeOrderPageRespVO;
import com.tashow.cloud.trade.controller.admin.order.vo.TradeOrderPageReqVO; import com.tashow.cloud.trade.controller.admin.order.vo.TradeOrderPageReqVO;
import com.tashow.cloud.trade.controller.admin.order.vo.TradeOrderPageRespVO;
import com.tashow.cloud.trade.controller.admin.order.vo.TradeOrderSummaryRespVO;
import com.tashow.cloud.trade.convert.order.TradeOrderConvert; import com.tashow.cloud.trade.convert.order.TradeOrderConvert;
import com.tashow.cloud.trade.dal.dataobject.order.TradeOrderDO; import com.tashow.cloud.trade.dal.dataobject.order.TradeOrderDO;
import com.tashow.cloud.trade.dal.dataobject.order.TradeOrderItemDO; import com.tashow.cloud.trade.dal.dataobject.order.TradeOrderItemDO;
@@ -63,16 +64,11 @@ public class TradeOrderController {
if (CollUtil.isEmpty(pageResult.getList())) { if (CollUtil.isEmpty(pageResult.getList())) {
return success(PageResult.empty()); return success(PageResult.empty());
} }
// // 查询用户信息
// Set<Long> userIds = CollUtil.unionDistinct(convertList(pageResult.getList(), TradeOrderDO::getUserId),
// convertList(pageResult.getList(), TradeOrderDO::getBrokerageUserId, Objects::nonNull));
// Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(userIds);
// 查询订单项 // 查询订单项
List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId( List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(
convertSet(pageResult.getList(), TradeOrderDO::getId)); convertSet(pageResult.getList(), TradeOrderDO::getId));
// 最终组合 // 最终组合
return success(TradeOrderConvert.INSTANCE.convertPage(pageResult, orderItems, null)); return success(TradeOrderConvert.INSTANCE.convertPage(pageResult, orderItems));
} }
/** /**
@@ -92,20 +88,22 @@ public class TradeOrderController {
// 查询订单项 // 查询订单项
List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(id); List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(id);
// 拼接数据
// MemberUserRespDTO user = memberUserApi.getUser(order.getUserId()).getCheckedData();
// MemberUserRespDTO brokerageUser = order.getBrokerageUserId() != null ?
// memberUserApi.getUser(order.getBrokerageUserId()).getCheckedData() : null;
List<TradeOrderLogDO> orderLogs = tradeOrderLogService.getOrderLogListByOrderId(id); List<TradeOrderLogDO> orderLogs = tradeOrderLogService.getOrderLogListByOrderId(id);
return success(TradeOrderConvert.INSTANCE.convert(order, orderItems, orderLogs, null, null)); return success(TradeOrderConvert.INSTANCE.convert(order, orderItems, orderLogs));
} }
// // 获得交易订单统计 //
// @GetMapping("/summary")
/**
* 获得交易订单统计
* @return
*/
@GetMapping("/summary")
@PermitAll
// @PreAuthorize("@ss.hasPermission('trade:order:query')") // @PreAuthorize("@ss.hasPermission('trade:order:query')")
// public CommonResult<TradeOrderSummaryRespVO> getOrderSummary(TradeOrderPageReqVO reqVO) { public CommonResult<TradeOrderSummaryRespVO> getOrderSummary() {
// return success(tradeOrderQueryService.getOrderSummary(reqVO)); return success(tradeOrderQueryService.getOrderSummary());
// } }
// //
// // 获得交易订单的物流轨迹 // // 获得交易订单的物流轨迹
// // id: 交易订单编号 // // id: 交易订单编号

View File

@@ -2,6 +2,12 @@ package com.tashow.cloud.trade.controller.admin.order.vo;
// 移除Swagger相关导入 // 移除Swagger相关导入
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.tashow.cloud.common.enums.TerminalEnum;
import com.tashow.cloud.common.util.json.databind.StringLocalDateTimeSerializer;
import com.tashow.cloud.common.validation.InEnum;
import com.tashow.cloud.tradeapi.enums.order.TradeOrderStatusEnum;
import com.tashow.cloud.tradeapi.enums.order.TradeOrderTypeEnum;
import lombok.Data; import lombok.Data;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@@ -15,17 +21,27 @@ public class TradeOrderBaseVO {
// 订单编号 // 订单编号
private Long id; private Long id;
// 订单流水 // 订单
private String orderNum; private String orderNum;
// 下单时间 /**
private LocalDateTime createTime; * 订单类型
* {@link TradeOrderTypeEnum#getType()}
*/
private Integer orderType;
// 订单类目 /**
private String orderCategoryName; * 订单来源
* {@link TerminalEnum#getTerminal()}
// 订单来源 */
@InEnum(TerminalEnum.class)
private Integer orderTerminal; private Integer orderTerminal;
/**
* 订单状态
* {@link TradeOrderStatusEnum#getStatus()}
*/
@InEnum(TradeOrderStatusEnum.class)
private Integer orderStatus;
// 用户编号 // 用户编号
private Long userId; private Long userId;
@@ -37,35 +53,14 @@ public class TradeOrderBaseVO {
private String userAvatar; private String userAvatar;
//用户手机号 //用户手机号
private String userMobile; private String userMobile;
// 订单状态
private Integer orderStatus;
//商品图片
private String picUrl;
//商品名称
private String spuName;
//商品规格
private String skuName;
// 购买的商品数量
private Integer count;
// 单价
private Integer price;
//到手价
private Integer handedPrice;
//实付金额
private Integer payPrice;
// 单位
private String unit;
//预约时间
private String orderTime;
//服务地址
private String serveAddress;
// 用户备注 - 必填,示例:你猜 // 用户备注 - 必填,示例:你猜
private String userRemark; private String userRemark;
//支付方式
private String payType; // 下单时间
//财务状态 @JsonSerialize(using = StringLocalDateTimeSerializer.class)
private String financeStatus; private LocalDateTime createTime;
// 订单完成时间
@JsonSerialize(using = StringLocalDateTimeSerializer.class)
private LocalDateTime finishTime;
} }

View File

@@ -2,114 +2,125 @@ package com.tashow.cloud.trade.controller.admin.order.vo;
// 移除Swagger相关导入 // 移除Swagger相关导入
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.tashow.cloud.common.util.json.databind.StringLocalDateTimeSerializer;
import lombok.Data; import lombok.Data;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List;
// 管理后台 - 交易订单的详情 Response VO // 管理后台 - 交易订单的详情 Response VO
@Data @Data
@Accessors(chain = true) @Accessors(chain = true)
public class TradeOrderDetailRespVO extends TradeOrderBaseVO { public class TradeOrderDetailRespVO extends TradeOrderBaseVO{
//基本信息 //订单类目id
private TradeOrderBaseInfo tradeOrderInfoBase; private Long orderCategoryId;
//配送信息 //订单类目名称
private TradeDeliveryInfo tradeDeliveryInfo; private String orderCategoryName;
//商品信息
private String tradeProductInfo;
//扩展服务信息
private String tradeExtendServeInfo;
//附加费信息
private String tradeExtendCostInfo;
//取消原因
private String cancelReason;
//商家备注
private String merchantRemark;
//退款时间
private LocalDateTime refundTime;
//保障时间
private LocalDateTime propertyTime;
//保障状态
private Integer propertyStatus;
//订单金额
private Integer price;
//实付金额
private Integer payPrice;
//优惠金额
private Integer discountPrice;
//退款金额
private Integer refundPrice;
//实收金额
private Integer livePrice;
//支付方式
private Integer payType;
//支付渠道 (线上线下)
private Integer payChannelCode;
//倒计时()
private String payLastTime;
//财务状态
private Integer financeStatus;
//交易流水号
private String payOrderId;
//支付时间
@JsonSerialize(using = StringLocalDateTimeSerializer.class)
private LocalDateTime payTime;
//取消时间
@JsonSerialize(using = StringLocalDateTimeSerializer.class)
private LocalDateTime cancelTime;
//订单状态流转记录
List<TradeOrderStatusRespVo> statusList;
//商品列表
private List<Item> items;
//服务信息(order_serve_info配置)
private JSONObject tradeServeInfo;
//扩展服务信息(order_serve_info配置)
private JSONArray tradeExtendServeInfo;
//附加费信息(order_serve_info配置)
private JSONArray tradeExtendCostInfo;
@Data @Data
@Accessors(chain = true) public static class Item {
class TradeOrderBaseInfo{
//订单id //店铺名称
private String id; private Long id;
//订单编号 //店铺名称
private String orderNo; private String shopName;
//订单状态 //店铺logo
private String orderStatus; private String shopLogo;
//订单类型
private String orderType; //商品id
//订单来源 private Long spuId;
private String orderTerminal; //skuId
//创建时间 private Long skuId;
private LocalDateTime createTime; //商品图片
//完成时间 private String picUrl;
private LocalDateTime finishTime;
//取消时间 //商品名称
private LocalDateTime cancelTime; private String spuName;
//订单金额 //商品规格
private String payPrice; private String skuName;
//订单类目id
private Long orderCategoryId;
//订单类目名称
private String orderCategoryName;
// 购买的商品数量
private Integer count;
// 订单总价
private Integer price;
// 单位
private String unit;
//商品总价
private Integer totalPrice;
//优惠金额 //优惠金额
private String discountPrice; private Integer discountPrice;
//退款金额 //实付金额
private String refundPrice; private Integer payPrice;
//实收金额 //累计退款金额
private String actualPrice; private Integer refundPrice;
//支付方式 //累计退款数量
private String payChannel; private Integer refundCount;
//交易流水号 //到手价
private String payOrderId; private Integer handedPrice;
//支付时间 //成本价
private LocalDateTime payTime; private Integer expensePrice;
// 退款状态 - 必填,示例:待审核/待退款/已退款/已拒绝
private String refundStatus;
// 售后编号 - 必填示例450878
private String afterSaleCode;
// 售后类型 - 必填,示例:仅退款/退货退款/可扩展增加使用
private String afterSaleType;
// 退款类型 - 必填,示例:订单退款/差价退款/运费退款/可扩展增加
private String refundType;
// 退款原因 - 必填,示例:不想要了
private String refundReason;
// 退款说明 - 必填,示例:这里是用户填写的退款描述
private String refundRemark;
// 退款金额 - 必填
private Integer refundAmount;
// 申请人 - 必填,示例:用户/商家/平台+ID
private String applicant;
// 审核人 - 必填,示例:姓名+ID
private String auditor;
// 审核时间 - 必填示例2025-07-01 12:00:00
private LocalDateTime auditTime;
// 退款方式 - 必填,示例:系统自动退款
private String refundMethod;
// 退款至 - 必填,示例:原支付方式返还
private String refundTo;
// 关闭时间 - 必填示例2025-07-01 12:00:00
private LocalDateTime closeTime;
//用户昵称 示例:钱多多
private String userNickname;
//用户ID 示例666
private Long userId;
//服务保障列表
private String properties;
//服务内容
private String serveContent;
} }
@Data
@Accessors(chain = true)
class TradeDeliveryInfo{
//承运方
private String logisticsName;
//送货方式
private String logisticsType;
//送货上门
private String logisticsNum;
//收货人
private String receiverName;
//收货手机
private String receiverMobile;
//收货地址
private String receiverDetailAddress;
//快递详情
private String deliveryDetail;
}
} }

View File

@@ -1,6 +1,7 @@
package com.tashow.cloud.trade.controller.admin.order.vo; package com.tashow.cloud.trade.controller.admin.order.vo;
// 移除Swagger相关导入 // 移除Swagger相关导入
import lombok.Data; import lombok.Data;
/** /**
@@ -8,60 +9,7 @@ import lombok.Data;
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/ */
@Data @Data
public class TradeOrderItemBaseVO { public class TradeOrderItemBaseVO extends TradeOrderBaseVO{
// ========== 订单项基本信息 ==========
// 编号 - 必填示例1
private Long id;
// 用户编号 - 必填示例1
private Long userId;
// 订单编号 - 必填示例1
private Long orderId;
// ========== 商品基本信息 ==========
// 商品 SPU 编号 - 必填示例1
private Long spuId;
// 商品 SPU 名称 - 必填,示例:芋道源码
private String spuName;
// 商品 SKU 编号 - 必填示例1
private Long skuId;
// 商品图片 - 必填示例https://www.iocoder.cn/1.png
private String picUrl;
// 购买数量 - 必填示例1
private Integer count;
// ========== 价格 + 支付基本信息 ==========
// 商品原价(单) - 必填示例100
private Integer price;
// 商品优惠(总) - 必填示例100
private Integer discountPrice;
// 商品实付金额(总) - 必填示例100
private Integer payPrice;
// 子订单分摊金额(总) - 必填示例100
private Integer orderPartPrice;
// 分摊后子订单实付金额(总) - 必填示例100
private Integer orderDividePrice;
// ========== 营销基本信息 ==========
// TODO 芋艿:在捉摸一下
// ========== 售后基本信息 ==========
// 售后状态 - 必填示例1
private Integer afterSaleStatus;
} }

View File

@@ -1,11 +1,52 @@
package com.tashow.cloud.trade.controller.admin.order.vo; package com.tashow.cloud.trade.controller.admin.order.vo;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.tashow.cloud.common.util.json.databind.StringLocalDateTimeSerializer;
import lombok.Data; import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
// 管理后台 - 交易订单的分页项 Response VO // 管理后台 - 交易订单的分页项 Response VO
@Data @Data
public class TradeOrderPageRespVO extends TradeOrderBaseVO { public class TradeOrderPageRespVO extends TradeOrderBaseVO {
//订单项列表
private List<Item> items;
//店铺名称
private String shopName;
//店铺log
private String shopLogo;
//支付剩余时间
private String payLastTime;
@Data
public static class Item {
//商品图片
private String picUrl;
//商品名称
private String spuName;
//商品规格
private String skuName;
// 购买的商品数量
private Integer count;
// 订单总价
private Integer price;
// 订单总价
private Integer discountPrice;
//到手价
private Integer handedPrice;
//实付金额
private Integer payPrice;
// 单位
private String unit;
//预约时间
@JsonSerialize(using = StringLocalDateTimeSerializer.class)
private LocalDateTime subTime;
//服务地址
private String serveAddress;
}
} }

View File

@@ -0,0 +1,43 @@
package com.tashow.cloud.trade.controller.admin.order.vo;
import com.tashow.cloud.trade.dal.dataobject.order.TradeOrderDO;
import com.tashow.cloud.tradeapi.enums.order.TradeOrderOperateTypeEnum;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class TradeOrderStatusRespVo {
private Long id;
/**
* 订单号
*
* 关联 {@link TradeOrderDO#getId()}
*/
private Long orderId;
/**
* 操作前状态
*/
private Integer beforeStatus;
/**
* 操作后状态
*/
private Integer afterStatus;
/**
* 操作类型
*
* {@link TradeOrderOperateTypeEnum}
*/
private Integer operateType;
/**
* 订单日志信息
*/
private String content;
/**
* 订单日志信息
*/
private LocalDateTime createTime;
}

View File

@@ -10,13 +10,10 @@ public class TradeOrderSummaryRespVO {
// 订单数量 - 必填示例1024 // 订单数量 - 必填示例1024
private Long orderCount; private Long orderCount;
// 订单金额 - 必填示例1024 // 实付金额 - 必填示例1024
private Long orderPayPrice; private Long payPrice;
// 退款单数 - 必填示例1024 // 最终实收金额 - 必填示例1024
private Long afterSaleCount; private Long livePrice;
// 退款金额 - 必填示例1024
private Long afterSalePrice;
} }

View File

@@ -137,12 +137,12 @@ public class AppTradeOrderController {
Map<String, Long> orderCount = Maps.newLinkedHashMapWithExpectedSize(5); Map<String, Long> orderCount = Maps.newLinkedHashMapWithExpectedSize(5);
// 全部 // 全部
orderCount.put("allCount", tradeOrderQueryService.getOrderCount(getLoginUserId(), null, null)); orderCount.put("allCount", tradeOrderQueryService.getOrderCount(getLoginUserId(), null, null));
// 待付款(未支付) // // 待付款(未支付)
orderCount.put("unpaidCount", tradeOrderQueryService.getOrderCount(getLoginUserId(), // orderCount.put("unpaidCount", tradeOrderQueryService.getOrderCount(getLoginUserId(),
TradeOrderStatusEnum.UNPAID.getStatus(), null)); // TradeOrderStatusEnum.UNPAID.getStatus(), null));
// 待发货 // // 待发货
orderCount.put("undeliveredCount", tradeOrderQueryService.getOrderCount(getLoginUserId(), // orderCount.put("undeliveredCount", tradeOrderQueryService.getOrderCount(getLoginUserId(),
TradeOrderStatusEnum.UNDELIVERED.getStatus(), null)); // TradeOrderStatusEnum.UNDELIVERED.getStatus(), null));
// 待收货 // 待收货
orderCount.put("deliveredCount", tradeOrderQueryService.getOrderCount(getLoginUserId(), orderCount.put("deliveredCount", tradeOrderQueryService.getOrderCount(getLoginUserId(),
TradeOrderStatusEnum.DELIVERED.getStatus(), null)); TradeOrderStatusEnum.DELIVERED.getStatus(), null));

View File

@@ -2,11 +2,8 @@ package com.tashow.cloud.trade.controller.app.order.vo.item;
// 移除Swagger相关导入 // 移除Swagger相关导入
import com.tashow.cloud.trade.controller.app.base.property.AppProductPropertyValueDetailRespVO;
import lombok.Data; import lombok.Data;
import java.util.List;
// 用户 App - 订单交易项 Response VO // 用户 App - 订单交易项 Response VO
@Data @Data
public class AppTradeOrderItemRespVO { public class AppTradeOrderItemRespVO {
@@ -25,11 +22,6 @@ public class AppTradeOrderItemRespVO {
// 商品 SKU 编号 - 必填示例1 // 商品 SKU 编号 - 必填示例1
private Long skuId; private Long skuId;
/**
* 属性数组
*/
private List<AppProductPropertyValueDetailRespVO> properties;
// 商品图片 - 必填示例https://www.iocoder.cn/1.png // 商品图片 - 必填示例https://www.iocoder.cn/1.png
private String picUrl; private String picUrl;

View File

@@ -30,6 +30,7 @@ public interface AfterSaleConvert {
@Mappings({ @Mappings({
@Mapping(target = "id", ignore = true), @Mapping(target = "id", ignore = true),
@Mapping(target = "refundPrice", ignore = true),
@Mapping(target = "createTime", ignore = true), @Mapping(target = "createTime", ignore = true),
@Mapping(target = "updateTime", ignore = true), @Mapping(target = "updateTime", ignore = true),
@Mapping(target = "creator", ignore = true), @Mapping(target = "creator", ignore = true),

View File

@@ -2,8 +2,11 @@ package com.tashow.cloud.trade.convert.order;
import cn.hutool.core.util.BooleanUtil; import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tashow.cloud.common.pojo.PageResult; import com.tashow.cloud.common.pojo.PageResult;
import com.tashow.cloud.common.util.collection.CollectionUtils; import com.tashow.cloud.common.util.collection.CollectionUtils;
import com.tashow.cloud.common.util.date.LocalDateTimeUtils;
import com.tashow.cloud.common.util.ip.AreaUtils; import com.tashow.cloud.common.util.ip.AreaUtils;
import com.tashow.cloud.common.util.string.StrUtils; import com.tashow.cloud.common.util.string.StrUtils;
import com.tashow.cloud.excel.dict.core.DictFrameworkUtils; import com.tashow.cloud.excel.dict.core.DictFrameworkUtils;
@@ -15,7 +18,6 @@ import com.tashow.cloud.trade.controller.admin.base.member.user.MemberUserRespVO
import com.tashow.cloud.trade.controller.admin.order.vo.*; import com.tashow.cloud.trade.controller.admin.order.vo.*;
import com.tashow.cloud.trade.controller.app.order.vo.*; import com.tashow.cloud.trade.controller.app.order.vo.*;
import com.tashow.cloud.trade.controller.app.order.vo.item.AppTradeOrderItemRespVO; import com.tashow.cloud.trade.controller.app.order.vo.item.AppTradeOrderItemRespVO;
import com.tashow.cloud.trade.convert.order.dto.CombinationRecordCreateReqDTO;
import com.tashow.cloud.trade.convert.order.dto.ProductSkuRespDTO; import com.tashow.cloud.trade.convert.order.dto.ProductSkuRespDTO;
import com.tashow.cloud.trade.convert.order.dto.ProductSkuUpdateStockReqDTO; import com.tashow.cloud.trade.convert.order.dto.ProductSkuUpdateStockReqDTO;
import com.tashow.cloud.trade.convert.order.dto.ProductSpuRespDTO; import com.tashow.cloud.trade.convert.order.dto.ProductSpuRespDTO;
@@ -30,15 +32,18 @@ import com.tashow.cloud.trade.service.brokerage.bo.BrokerageAddReqBO;
import com.tashow.cloud.trade.service.price.bo.TradePriceCalculateReqBO; import com.tashow.cloud.trade.service.price.bo.TradePriceCalculateReqBO;
import com.tashow.cloud.trade.service.price.bo.TradePriceCalculateRespBO; import com.tashow.cloud.trade.service.price.bo.TradePriceCalculateRespBO;
import com.tashow.cloud.tradeapi.api.order.dto.TradeOrderRespDTO; import com.tashow.cloud.tradeapi.api.order.dto.TradeOrderRespDTO;
import com.tashow.cloud.tradeapi.enums.order.TradeOrderStatusEnum;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.Mapping; import org.mapstruct.Mapping;
import org.mapstruct.Mappings; import org.mapstruct.Mappings;
import org.mapstruct.Named; import org.mapstruct.Named;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import static com.tashow.cloud.common.util.collection.CollectionUtils.convertMap; import static com.tashow.cloud.common.util.collection.CollectionUtils.convertMap;
import static com.tashow.cloud.common.util.collection.CollectionUtils.convertMultiMap; import static com.tashow.cloud.common.util.collection.CollectionUtils.convertMultiMap;
@@ -50,6 +55,75 @@ public interface TradeOrderConvert {
TradeOrderConvert INSTANCE = Mappers.getMapper(TradeOrderConvert.class); TradeOrderConvert INSTANCE = Mappers.getMapper(TradeOrderConvert.class);
//region 分页结果
default PageResult<TradeOrderPageRespVO> convertPage(PageResult<TradeOrderDO> pageResult, List<TradeOrderItemDO> orderItems) {
Map<Long, List<TradeOrderItemDO>> orderItemMap = convertMultiMap(orderItems, TradeOrderItemDO::getOrderId);
// 转化 List
List<TradeOrderPageRespVO> orderVOs = CollectionUtils.convertList(pageResult.getList(), order -> {
List<TradeOrderItemDO> itemDO = orderItemMap.get(order.getId());
TradeOrderPageRespVO orderPageRespVO = convert(order, itemDO);
orderPageRespVO.getItems().stream().forEach(item -> {
item.setHandedPrice(item.getPrice() - item.getDiscountPrice());
});
return orderPageRespVO;
});
return new PageResult<>(orderVOs, pageResult.getTotal());
}
@Mappings({
@Mapping(source = "order.id", target = "id"),
@Mapping(source = "order.userId", target = "userId"),
})
TradeOrderPageRespVO convert(TradeOrderDO order, List<TradeOrderItemDO> items);
//endregion
//region 订单详情
default TradeOrderDetailRespVO convert(TradeOrderDO order, List<TradeOrderItemDO> orderItems, List<TradeOrderLogDO> orderLogs) {
//订单基本信息
TradeOrderDetailRespVO orderVO = convert2(order, orderItems, orderLogs);
//计算商品到手价
orderVO.getItems().stream().forEach(item -> {
item.setHandedPrice(item.getPrice() - item.getDiscountPrice());
item.setTotalPrice(item.getPrice() * item.getCount() - item.getDiscountPrice());
//产品类目在订单详情里
orderVO.setOrderCategoryId(item.getOrderCategoryId());
orderVO.setOrderCategoryName(item.getOrderCategoryName());
//todo 服务保障列表 properties 服务内容 serveContent
});
//服务信息
orderItems.stream().filter(a->StrUtil.isNotBlank(a.getServeInfo())).findAny().ifPresent(a -> {
orderVO.setTradeServeInfo(JSON.parseObject(a.getServeInfo()));
orderVO.setTradeExtendServeInfo(JSON.parseArray(a.getServeExtInfo()));
orderVO.setTradeExtendCostInfo(JSON.parseArray(a.getPriceExtInfo()));
});
//保障时间 保障状态 如果状态是已完成 则
if (Objects.equals(order.getOrderStatus(), TradeOrderStatusEnum.COMPLETED.getStatus())) {
LocalDateTime finishTime = order.getFinishTime();
Long between = LocalDateTimeUtils.between(finishTime);
orderVO.setPropertyStatus(between >= 7 ? 0 : 1);
orderVO.setPropertyTime(LocalDateTimeUtils.getPlusDay(7));
}
return orderVO;
}
// @Mappings(
// @Mapping(target ="items.tradeServeInfo", source = "tradeServeInfo",qualifiedByName = "jsonToMap")
// )
TradeOrderDetailRespVO convert2(TradeOrderDO order, List<TradeOrderItemDO> items, List<TradeOrderLogDO> statusList);
@Named("jsonToMap")
default Map<String, Object> jsonToMap(String json) {
try {
return new ObjectMapper().readValue(json, Map.class);
} catch (Exception e) {
throw new RuntimeException("json转换map出错", e);
}
}
//endregion
@Mappings({ @Mappings({
@Mapping(target = "id", ignore = true), @Mapping(target = "id", ignore = true),
@Mapping(source = "userId", target = "userId"), @Mapping(source = "userId", target = "userId"),
@@ -61,7 +135,7 @@ public interface TradeOrderConvert {
TradeOrderRespDTO convert(TradeOrderDO orderDO); TradeOrderRespDTO convert(TradeOrderDO orderDO);
default List<TradeOrderItemDO> convertList(TradeOrderDO tradeOrderDO) { default List<TradeOrderItemDO> convertList(TradeOrderDO tradeOrderDO) {
return null;//CollectionUtils.convertList(calculateRespBO.getItems(), item -> { return null;//CollectionUtils.convertList(calculateRespBO.getItems(), item -> {
// TradeOrderItemDO orderItem = convert(item); // TradeOrderItemDO orderItem = convert(item);
// orderItem.setOrderId(tradeOrderDO.getId()); // orderItem.setOrderId(tradeOrderDO.getId());
// orderItem.setUserId(tradeOrderDO.getUserId()); // orderItem.setUserId(tradeOrderDO.getUserId());
@@ -100,43 +174,6 @@ public interface TradeOrderConvert {
return createReqDTO; return createReqDTO;
} }
default PageResult<TradeOrderPageRespVO> convertPage(PageResult<TradeOrderDO> pageResult,
List<TradeOrderItemDO> orderItems,
Map<Long, MemberUserRespDTO> memberUserMap) {
Map<Long, List<TradeOrderItemDO>> orderItemMap = convertMultiMap(orderItems, TradeOrderItemDO::getOrderId);
// 转化 List
List<TradeOrderPageRespVO> orderVOs = CollectionUtils.convertList(pageResult.getList(), order -> {
List<TradeOrderItemDO> xOrderItems = orderItemMap.get(order.getId());
TradeOrderPageRespVO orderVO = convert(order, xOrderItems);
// 处理收货地址
return orderVO;
});
return new PageResult<>(orderVOs, pageResult.getTotal());
}
MemberUserRespVO convertUser(MemberUserRespDTO memberUserRespDTO);
TradeOrderPageRespVO convert(TradeOrderDO order, List<TradeOrderItemDO> items);
// ProductPropertyValueDetailRespVO convert(ProductPropertyValueDetailRespDTO bean);
default TradeOrderDetailRespVO convert(TradeOrderDO order, List<TradeOrderItemDO> orderItems,
List<TradeOrderLogDO> orderLogs,
MemberUserRespDTO user, MemberUserRespDTO brokerageUser) {
TradeOrderDetailRespVO orderVO = convert2(order, orderItems);
// // 处理收货地址
// orderVO.setReceiverAreaName(AreaUtils.format(order.getReceiverAreaId()));
// // 处理用户信息
// orderVO.setUser(convert(user));
// orderVO.setBrokerageUser(convert(brokerageUser));
// // 处理日志
// orderVO.setLogs(convertList03(orderLogs));
return orderVO;
}
List<TradeOrderDetailRespVO> convertList03(List<TradeOrderLogDO> orderLogs);
TradeOrderDetailRespVO convert2(TradeOrderDO order, List<TradeOrderItemDO> items);
MemberUserRespVO convert(MemberUserRespDTO bean); MemberUserRespVO convert(MemberUserRespDTO bean);
default PageResult<AppTradeOrderPageItemRespVO> convertPage02(PageResult<TradeOrderDO> pageResult, default PageResult<AppTradeOrderPageItemRespVO> convertPage02(PageResult<TradeOrderDO> pageResult,
@@ -152,14 +189,12 @@ public interface TradeOrderConvert {
AppTradeOrderPageItemRespVO convert02(TradeOrderDO order, List<TradeOrderItemDO> items); AppTradeOrderPageItemRespVO convert02(TradeOrderDO order, List<TradeOrderItemDO> items);
// AppProductPropertyValueDetailRespVO convert02(ProductPropertyValueDetailRespDTO bean);
default AppTradeOrderDetailRespVO convert02(TradeOrderDO order, List<TradeOrderItemDO> orderItems, default AppTradeOrderDetailRespVO convert02(TradeOrderDO order, List<TradeOrderItemDO> orderItems,
TradeOrderProperties tradeOrderProperties, TradeOrderProperties tradeOrderProperties,
DeliveryExpressDO express) { DeliveryExpressDO express) {
AppTradeOrderDetailRespVO orderVO = convert3(order, orderItems); AppTradeOrderDetailRespVO orderVO = convert3(order, orderItems);
orderVO.setPayExpireTime(order.getCreateTime().plus(tradeOrderProperties.getPayExpireTime())); orderVO.setPayExpireTime(order.getCreateTime().plus(tradeOrderProperties.getPayExpireTime()));
if (StrUtil.isNotEmpty(order.getPayChannelCode())) { if (order.getPayChannelCode() == null) {
orderVO.setPayChannelName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.CHANNEL_CODE, order.getPayChannelCode())); orderVO.setPayChannelName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.CHANNEL_CODE, order.getPayChannelCode()));
} }
// 处理收货地址 // 处理收货地址
@@ -185,10 +220,6 @@ public interface TradeOrderConvert {
@Mapping(target = "anonymous", source = "createReqVO.anonymous"), @Mapping(target = "anonymous", source = "createReqVO.anonymous"),
@Mapping(target = "userId", source = "tradeOrderItemDO.userId") @Mapping(target = "userId", source = "tradeOrderItemDO.userId")
}) })
// ProductCommentCreateReqDTO convert04(AppTradeOrderItemCommentCreateReqVO createReqVO, TradeOrderItemDO tradeOrderItemDO);
//
// TradePriceCalculateReqBO convert(AppTradeOrderSettlementReqVO settlementReqVO);
//
default TradePriceCalculateReqBO convert(Long userId, AppTradeOrderSettlementReqVO settlementReqVO, default TradePriceCalculateReqBO convert(Long userId, AppTradeOrderSettlementReqVO settlementReqVO,
List<CartDO> cartList) { List<CartDO> cartList) {
TradePriceCalculateReqBO reqBO = new TradePriceCalculateReqBO().setUserId(userId) TradePriceCalculateReqBO reqBO = new TradePriceCalculateReqBO().setUserId(userId)
@@ -222,7 +253,8 @@ public interface TradeOrderConvert {
} }
return reqBO; return reqBO;
} }
//
//
default AppTradeOrderSettlementRespVO convert(TradePriceCalculateRespBO calculate, MemberAddressRespDTO address) { default AppTradeOrderSettlementRespVO convert(TradePriceCalculateRespBO calculate, MemberAddressRespDTO address) {
AppTradeOrderSettlementRespVO respVO = convert0(calculate, address); AppTradeOrderSettlementRespVO respVO = convert0(calculate, address);
if (address != null) { if (address != null) {
@@ -230,7 +262,8 @@ public interface TradeOrderConvert {
} }
return respVO; return respVO;
} }
//
//
AppTradeOrderSettlementRespVO convert0(TradePriceCalculateRespBO calculate, MemberAddressRespDTO address); AppTradeOrderSettlementRespVO convert0(TradePriceCalculateRespBO calculate, MemberAddressRespDTO address);
List<AppOrderExpressTrackRespDTO> convertList02(List<ExpressTrackRespDTO> list); List<AppOrderExpressTrackRespDTO> convertList02(List<ExpressTrackRespDTO> list);
@@ -253,16 +286,4 @@ public interface TradeOrderConvert {
return bo; return bo;
} }
@Named("convertList04")
List<TradeOrderRespDTO> convertList04(List<TradeOrderDO> list);
@Mappings({
@Mapping(target = "spuId", source = "item.spuId"),
@Mapping(target = "skuId", source = "item.skuId"),
@Mapping(target = "count", source = "item.count"),
@Mapping(target = "orderId", source = "order.id"),
@Mapping(target = "userId", source = "order.userId"),
})
CombinationRecordCreateReqDTO convert(TradeOrderDO order, TradeOrderItemDO item);
} }

View File

@@ -121,13 +121,6 @@ public class AfterSaleDO extends BaseDO {
* 关联 ProductSkuDO 的编号 * 关联 ProductSkuDO 的编号
*/ */
private Long skuId; private Long skuId;
/**
* 属性数组JSON 格式
*
* 冗余 {@link TradeOrderItemDO#getProperties()}
*/
@TableField(typeHandler = JacksonTypeHandler.class)
private List<TradeOrderItemDO.Property> properties;
/** /**
* 商品图片 * 商品图片
* *

View File

@@ -1,15 +1,9 @@
package com.tashow.cloud.trade.dal.dataobject.order; package com.tashow.cloud.trade.dal.dataobject.order;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import com.tashow.cloud.common.enums.TerminalEnum;
import com.tashow.cloud.mybatis.mybatis.core.dataobject.BaseDO; import com.tashow.cloud.mybatis.mybatis.core.dataobject.BaseDO;
import com.tashow.cloud.trade.dal.dataobject.delivery.DeliveryExpressDO;
import com.tashow.cloud.trade.dal.dataobject.delivery.DeliveryPickUpStoreDO;
import com.tashow.cloud.tradeapi.enums.delivery.DeliveryTypeEnum;
import com.tashow.cloud.tradeapi.enums.order.TradeOrderCancelTypeEnum;
import com.tashow.cloud.tradeapi.enums.order.TradeOrderRefundStatusEnum;
import com.tashow.cloud.tradeapi.enums.order.TradeOrderStatusEnum;
import com.tashow.cloud.tradeapi.enums.order.TradeOrderTypeEnum;
import lombok.*; import lombok.*;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@@ -19,7 +13,8 @@ import java.time.LocalDateTime;
* *
* @author 芋道源码 * @author 芋道源码
*/ */
@TableName(value = "tz_trade_order", autoResultMap = true) @TableName("tz_trade_order")
@KeySequence("tz_trade_order_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true) @ToString(callSuper = true)
@@ -28,57 +23,48 @@ import java.time.LocalDateTime;
@AllArgsConstructor @AllArgsConstructor
public class TradeOrderDO extends BaseDO { public class TradeOrderDO extends BaseDO {
/**
* 发货物流公司编号 - 空(无需发货)
*/
public static final Long LOGISTICS_ID_NULL = 0L;
// ========== 订单基本信息 ==========
/** /**
* 订单编号,主键自增 * 订单编号,主键自增
*/ */
@TableId
private Long id; private Long id;
/** /**
* 订单流水号 * 订单流水号
*
* 例如说1146347329394184195
*/ */
private String orderNum; private String orderNum;
/** /**
* 订单类型 * 订单类型 (枚举 TradeOrderTypeEnum)
*
* 枚举 {@link TradeOrderTypeEnum}
*/ */
private Integer orderType; private Integer orderType;
/** /**
* 订单来源 * 订单来源 (枚举 TerminalEnum)
*
* 枚举 {@link TerminalEnum}
*/ */
private Integer orderTerminal; private Integer orderTerminal;
/**
* 订单状态 (枚举 TradeOrderStatusEnum)
*/
private Integer orderStatus;
/** /**
* 用户编号 * 用户编号
*
* 关联 MemberUserDO 的 id 编号
*/ */
private Long userId; private Long userId;
private String userMobile;
private String userName;
/** /**
* 用户 IP * 用户IP
*/ */
private String userIp; private String userIp;
/**
* 用户昵称
*/
private String userName;
/**
* 用户手机号
*/
private String userMobile;
/** /**
* 用户备注 * 用户备注
*/ */
private String userRemark; private String userRemark;
/**
* 订单状态
*
* 枚举 {@link TradeOrderStatusEnum}
*/
private Integer orderStatus;
private Integer financeStatus;
/** /**
* 订单完成时间 * 订单完成时间
*/ */
@@ -88,115 +74,74 @@ public class TradeOrderDO extends BaseDO {
*/ */
private LocalDateTime cancelTime; private LocalDateTime cancelTime;
/** /**
* 取消类型 * 取消类型 (枚举 TradeOrderCancelTypeEnum)
*
* 枚举 {@link TradeOrderCancelTypeEnum}
*/ */
private Integer cancelType; private Integer cancelType;
/**
* 取消原因
*/
private String cancelReason;
/**
* 商家编号
*/
private Long merchantId;
/**
* 商家名称
*/
private String merchantName;
/** /**
* 商家备注 * 商家备注
*/ */
private String merchantRemark; private String merchantRemark;
private String merchantName;
private Long orderCategoryId;
/** /**
* 是否评价 * 是否评价 (true-已评价, false-未评价)
*
* true - 已评价
* false - 未评价
*/ */
private Boolean commentStatus; private Boolean commentStatus;
/**
// ========== 价格 + 支付基本信息 ========== * 应付金额(总),单位:分
*/
// 价格文档 - 淘宝https://open.taobao.com/docV3.htm?docId=108471&docType=1 private Integer payPrice;
// 价格文档 - 京东到家https://openo2o.jddj.com/api/getApiDetail/182/4d1494c5e7ac4679bfdaaed950c5bc7f.htm /**
// 价格文档 - 有赞https://doc.youzanyun.com/detail/API/0/906 * 实收金额(总),单位:分
*/
private Integer livePrice;
/** /**
* 支付订单编号 * 支付订单编号
*
* 对接 pay-module-biz 支付服务的支付订单编号,即 PayOrderDO 的 id 编号
*/ */
private Long payOrderId; private Long payOrderId;
/** /**
* 是否已支付 * 是否已支付 (true-已支付, false-未支付)
*
* true - 已经支付过
* false - 没有支付过
*/ */
private Boolean payStatus; private Boolean payStatus;
/**
* 支付方式PayTypeEnum
*/
private Integer payType;
/** /**
* 付款时间 * 付款时间
*/ */
private LocalDateTime payTime; private LocalDateTime payTime;
/** /**
* 支付渠道 * 支付渠道(PayTypeEnum)
*
* 对应 PayChannelEnum 枚举
*/ */
private String payChannelCode; private Integer payChannelCode;
/** /**
* 商品原价,单位:分 * 配送方式 (枚举 DeliveryTypeEnum)
*
* totalPrice = {@link TradeOrderItemDO#getPrice()} * {@link TradeOrderItemDO#getCount()} 求和
*
* 对应 taobao 的 trade.total_fee 字段
*/
private Integer totalPrice;
/**
* 优惠金额,单位:分
*
* 对应 taobao 的 order.discount_fee 字段
*/
private Integer discountPrice;
/**
* 运费金额,单位:分
*/
private Integer deliveryPrice;
/**
* 订单调价,单位:分
*
* 正数,加价;负数,减价
*/
private Integer adjustPrice;
/**
* 应付金额(总),单位:分
*
* = {@link #totalPrice}
* - {@link #discountPrice}
* + {@link #deliveryPrice}
* + {@link #adjustPrice}
*/
private Integer payPrice;
// ========== 收件 + 物流基本信息 ==========
/**
* 配送方式
*
* 枚举 {@link DeliveryTypeEnum}
*/ */
private Integer deliveryType; private Integer deliveryType;
/** /**
* 发货物流公司编号 * 发货物流公司编号
*
* 如果无需发货,则 logisticsId 设置为 0。原因是不想再添加额外字段
*
* 关联 {@link DeliveryExpressDO#getId()}
*/ */
private Long logisticsId; private Long logisticsId;
/** /**
* 发货物流单号 * 发货物流单号
*
* 如果无需发货,则 logisticsNo 设置 ""。原因是,不想再添加额外字段
*/ */
private String logisticsNo; private String logisticsNo;
/** /**
* 发货时间 * 发货时间
*/ */
private LocalDateTime deliveryTime; private LocalDateTime deliveryTime;
/** /**
* 收货时间 * 收货时间
*/ */
@@ -217,35 +162,45 @@ public class TradeOrderDO extends BaseDO {
* 收件人详细地址 * 收件人详细地址
*/ */
private String receiverDetailAddress; private String receiverDetailAddress;
/** /**
* 自提门店编号 * 自提门店编号
*
* 关联 {@link DeliveryPickUpStoreDO#getId()}
*/ */
private Long pickUpStoreId; private Long pickUpStoreId;
/** /**
* 自提核销码 * 自提核销码
*/ */
private String pickUpVerifyCode; private String pickUpVerifyCode;
// ========== 售后基本信息 ==========
/** /**
* 售后状态 * 退款状态 (枚举 TradeOrderRefundStatusEnum)
*
* 枚举 {@link TradeOrderRefundStatusEnum}
*/ */
private Integer refundStatus; private Integer refundStatus;
/** /**
* 退款金额,单位:分 * 退款金额,单位:分
*
* 注意,退款并不会影响 {@link #payPrice} 实际支付金额
* 也就说,一个订单最终产生多少金额的收入 = payPrice - refundPrice
*/ */
private Integer refundPrice; private Integer refundPrice;
/**
* 退款时间
*/
private LocalDateTime refundTime;
/**
* 售后单编号
*/
private Long afterSaleId;
/**
* 售后状态 (枚举 TradeOrderItemAfterSaleStatusEnum)
*/
private Integer afterSaleStatus; private Integer afterSaleStatus;
private Integer subType; /**
private LocalDateTime subTime; * 财务单编号
*/
private Long financeId;
/**
* 财务状态 (枚举 TradeOrderItemFinanceEnum)
*/
private Integer financeStatus;
/**
* 版本号(乐观锁)
*/
private Integer version;
} }

View File

@@ -1,80 +1,81 @@
package com.tashow.cloud.trade.dal.dataobject.order; package com.tashow.cloud.trade.dal.dataobject.order;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.Version;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.tashow.cloud.mybatis.mybatis.core.dataobject.BaseDO; import com.tashow.cloud.mybatis.mybatis.core.dataobject.BaseDO;
import lombok.Data; import lombok.*;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List;
/** /**
* 交易订单项 DO * 交易订单项 DO
* *
* @author 芋道源码 * @author 芋道源码
*/ */
@TableName(value = "trade_order_item", autoResultMap = true) @TableName("tz_trade_order_item")
@KeySequence("tz_trade_order_item_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data @Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TradeOrderItemDO extends BaseDO { public class TradeOrderItemDO extends BaseDO {
// ========== 订单项基本信息 ==========
/** /**
* 编号 * 编号
*/ */
@TableId
private Long id; private Long id;
/** /**
* 用户编号 * 用户编号
*
* 关联 MemberUserDO 的 id 编号
*/ */
private Long userId; private Long userId;
/** /**
* 订单编号 * 订单编号
*
* 关联 {@link TradeOrderDO#getId()}
*/ */
private Long orderId; private Long orderId;
/** /**
* 购物车项编号 * 购物车项编号
*/ */
private Long cartId; private Long cartId;
// ========== 商品基本信息; 冗余较多字段,减少关联查询 ==========
/** /**
* 商品 SPU 编号 * 商品 SPU 编号
*
* 关联 ProductSkuDO 的 spuId 编号
*/ */
private Long spuId; private Long spuId;
/** /**
* 商品 SPU 名称 * 商品 SPU 名称
*
* 冗余 ProductSkuDO 的 spuName 编号
*/ */
private String spuName; private String spuName;
/**
private Integer spuType; * 商品类型1商品 2服务
*/
private Boolean spuType;
/** /**
* 商品 SKU 编号 * 商品 SKU 编号
*
* 关联 ProductSkuDO 的 id 编号
*/ */
private Long skuId; private Long skuId;
/**
* 商品 SKU 名称
*/
private String skuName; private String skuName;
/** /**
* 属性数组JSON 格式 * 店铺id
*
* 冗余 ProductSkuDO 的 properties 字段
*/ */
@TableField(typeHandler = JacksonTypeHandler.class) private Long shopId;
private List<Property> properties; /**
* 店铺名称
*/
private String shopName;
/**
* 订单类目id
*/
private Long orderCategoryId;
/**
* 订单类目名称
*/
private String orderCategoryName;
/** /**
* 商品图片 * 商品图片
*/ */
@@ -83,22 +84,20 @@ public class TradeOrderItemDO extends BaseDO {
* 购买数量 * 购买数量
*/ */
private Integer count; private Integer count;
/**
// ========== 价格 + 支付基本信息 ========== * 商品单位
//商品成本 */
private String unit;
/**
* 商品成本(单),单位:分
*/
private Integer expensePrice; private Integer expensePrice;
/** /**
* 商品原价(单),单位:分 * 商品原价(单),单位:分
*
* 对应 ProductSkuDO 的 price 字段
* 对应 taobao 的 order.price 字段
*/ */
private Integer price; private Integer price;
/** /**
* 优惠金额(总),单位:分 * 优惠金额(总),单位:分
*
* 对应 taobao 的 order.discount_fee 字段
*/ */
private Integer discountPrice; private Integer discountPrice;
/** /**
@@ -107,67 +106,65 @@ public class TradeOrderItemDO extends BaseDO {
private Integer deliveryPrice; private Integer deliveryPrice;
/** /**
* 订单调价(总),单位:分 * 订单调价(总),单位:分
*
* 正数,加价;负数,减价
*/ */
private Integer adjustPrice; private Integer adjustPrice;
/** /**
* 应付金额(总),单位:分 * 应付金额(总),单位:分
*
* = {@link #price} * {@link #count}
* - {@link #discountPrice}
* + {@link #deliveryPrice}
* + {@link #adjustPrice}
*/ */
private Integer payPrice; private Integer payPrice;
//实收金额 /**
* 实收金额(总),单位:分
*/
private Integer livePrice; private Integer livePrice;
/**
private Integer orderType; * 退款金额(总),单位:分
private LocalDateTime orderTime; */
private String serveAddress; private Integer refundPrice;
private String serveInfo; /**
private String serveExtInfo; * 退款状态
private String priceExtInfo; */
private Integer refundStatus;
@Version /**
private Integer version; * 退款时间
*/
private LocalDateTime refundTime;
/**
* 预约类型1预约 2 加急)
*/
private Boolean subType;
/**
* 预约时间
*/
private LocalDateTime subTime;
/** /**
* 商品属性 * 服务地址
*/ */
@Data private String serveAddress;
public static class Property implements Serializable {
/** /**
* 属性编号 * 服务内容
* */
* 关联 ProductPropertyDO 的 id 编号 private String serveContent;
*/ /**
private Long propertyId; * 属性数组
/** */
* 属性名字 private String properties;
* /**
* 关联 ProductPropertyDO 的 name 字段 * 服务信息
*/ */
private String propertyName; private String serveInfo;
/**
/** * 扩展服务信息,存储额外的服务相关数据
* 属性值编号 */
* private String serveExtInfo;
* 关联 ProductPropertyValueDO 的 id 编号 /**
*/ * 附加费信息
private Long valueId; */
/** private String priceExtInfo;
* 属性值名字 /**
* * 版本号(乐观锁)
* 关联 ProductPropertyValueDO 的 name 字段 */
*/ private Integer version;
private String valueName;
}
}
}

View File

@@ -1,6 +1,5 @@
package com.tashow.cloud.trade.dal.dataobject.order; package com.tashow.cloud.trade.dal.dataobject.order;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import com.tashow.cloud.common.enums.UserTypeEnum; import com.tashow.cloud.common.enums.UserTypeEnum;
@@ -13,7 +12,7 @@ import lombok.*;
* *
* @author 陈賝 * @author 陈賝
*/ */
@TableName("trade_order_log") @TableName("tz_trade_order_log")
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true) @ToString(callSuper = true)

View File

@@ -32,12 +32,9 @@ public interface TradeOrderMapper extends BaseMapperX<TradeOrderDO> {
default PageResult<TradeOrderDO> selectPage(TradeOrderPageReqVO reqVO, Set<Long> userIds) { default PageResult<TradeOrderDO> selectPage(TradeOrderPageReqVO reqVO, Set<Long> userIds) {
return selectPage(reqVO, new LambdaQueryWrapperX<TradeOrderDO>() return selectPage(reqVO, new LambdaQueryWrapperX<TradeOrderDO>()
.likeIfPresent(TradeOrderDO::getMerchantName, reqVO.getMerchantName()) .likeIfPresent(TradeOrderDO::getMerchantName, reqVO.getMerchantName())
.eqIfPresent(TradeOrderDO::getOrderCategoryId, reqVO.getOrderCategoryId())
.eqIfPresent(TradeOrderDO::getOrderTerminal, reqVO.getOrderTerminal()) .eqIfPresent(TradeOrderDO::getOrderTerminal, reqVO.getOrderTerminal())
.eqIfPresent(TradeOrderDO::getFinanceStatus, reqVO.getFinanceStatus()) .eqIfPresent(TradeOrderDO::getFinanceStatus, reqVO.getFinanceStatus())
.eqIfPresent(TradeOrderDO::getAfterSaleStatus, reqVO.getAfterSaleStatus()) .eqIfPresent(TradeOrderDO::getAfterSaleStatus, reqVO.getAfterSaleStatus())
.eqIfPresent(TradeOrderDO::getSubType, reqVO.getSubType())
.betweenIfPresent(TradeOrderDO::getSubTime, reqVO.getSubTime())
.betweenIfPresent(TradeOrderDO::getCreateTime, reqVO.getCreateTime()) .betweenIfPresent(TradeOrderDO::getCreateTime, reqVO.getCreateTime())
.and(StrUtil.isNotBlank(reqVO.getProdSearch()), .and(StrUtil.isNotBlank(reqVO.getProdSearch()),
qw->qw.like(TradeOrderDO::getOrderNum, reqVO.getProdSearch()) qw->qw.like(TradeOrderDO::getOrderNum, reqVO.getProdSearch())
@@ -49,15 +46,13 @@ public interface TradeOrderMapper extends BaseMapperX<TradeOrderDO> {
.orderByDesc(TradeOrderDO::getId)); .orderByDesc(TradeOrderDO::getId));
} }
// TODO @疯狂:如果用 map 返回,要不这里直接用 TradeOrderSummaryRespVO 返回?也算合理,就当 sql 查询出这么个玩意~~ default List<Map<String, Object>> selectOrderSummary() {
default List<Map<String, Object>> selectOrderSummaryGroupByRefundStatus(TradeOrderPageReqVO reqVO, Set<Long> userIds) {
return selectMaps(new MPJLambdaWrapperX<TradeOrderDO>() return selectMaps(new MPJLambdaWrapperX<TradeOrderDO>()
.selectAs(TradeOrderDO::getRefundStatus, TradeOrderDO::getRefundStatus) // 售后状态 .selectCount(TradeOrderDO::getId, "count")
.selectCount(TradeOrderDO::getId, "count") // 售后状态对应的数量 .selectSum(TradeOrderDO::getPayPrice, "payPrice")
.selectSum(TradeOrderDO::getPayPrice, "price") // 售后状态对应的支付金额 .selectSum(TradeOrderDO::getLivePrice, "livePrice")
.inIfPresent(TradeOrderDO::getUserId, userIds) .groupBy(TradeOrderDO::getId)
.betweenIfPresent(TradeOrderDO::getCreateTime, reqVO.getCreateTime()) );
.groupBy(TradeOrderDO::getRefundStatus)); // 按售后状态分组
} }
default PageResult<TradeOrderDO> selectPage(AppTradeOrderPageReqVO reqVO, Long userId) { default PageResult<TradeOrderDO> selectPage(AppTradeOrderPageReqVO reqVO, Long userId) {

View File

@@ -0,0 +1,176 @@
package com.tashow.cloud.trade.framework.order.core.utils;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.tashow.cloud.common.util.json.JsonUtils;
import com.tashow.cloud.trade.dal.dataobject.order.TradeOrderItemDO;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class TransOrderByTempUtils {
private final static String tempUrl = "temp/order_serve_info.json";
public static JSONObject trans(TradeOrderItemDO item) {
JSONObject result = new JSONObject();
String json = ResourceUtil.readUtf8Str(tempUrl);
//解析json
JSONObject orderInfo = JSON.parseObject(json);
JSONArray serveInfoTempObj = orderInfo.getJSONArray("serveInfo");
JSONArray serveExtInfoTempObj = orderInfo.getJSONArray("selectedServeInfo");
JSONArray priceExtInfoTempObj = orderInfo.getJSONArray("priceExtInfo");
//获取服务信息
result.put("serveInfo", getServeInfo(serveInfoTempObj, item.getServeInfo()));
//可选服务
result.put("selectedServeInfo", getServeInfo(serveExtInfoTempObj, item.getServeExtInfo()));
//服务附加费
result.put("priceExtInfo", getServeInfo(priceExtInfoTempObj, item.getPriceExtInfo()));
return result;
}
private static List<List<JSONObject>> getServeInfo(JSONArray tempObj, String valueInfo) {
List<List<JSONObject>> result = new ArrayList<>();
//数据json [{},{}]
JSONArray valueInfoObj = JSON.parseArray(valueInfo);
for (Object val : valueInfoObj) {
List<JSONObject> valResult = new ArrayList<>();
Map valMap = JsonUtils.parseObject(val.toString(), Map.class);
if (valMap == null) {
continue;
}
//模版json
for (Object tem : tempObj) {
JSONObject resultMap = new JSONObject();
Map<String, Object> tempMap = JsonUtils.parseObject(tem.toString(), Map.class);
resultMap.put("key", MapUtil.getStr(tempMap, "key"));
resultMap.put("name", MapUtil.getStr(tempMap, "name"));
resultMap.put("value", valMap.get(MapUtil.getStr(tempMap, "key")));
resultMap.put("sort", MapUtil.getStr(tempMap, "sort"));
valResult.add(resultMap);
}
result.add(valResult);
}
return result;
}
public static void main(String[] args) {
TradeOrderItemDO itemDO = new TradeOrderItemDO();
JSONArray tempObj = new JSONArray();
JSONObject orderInfo = new JSONObject();
orderInfo.put("petName", "aaa");
orderInfo.put("petType", "aaa");
orderInfo.put("weight", "aaa");
orderInfo.put("diedTime", "aaa");
orderInfo.put("diedReason", "aaa");
orderInfo.put("remainsPhoneUrl", "aaa");
orderInfo.put("subType", "aaa");
orderInfo.put("changeRule", "aaa");
orderInfo.put("subOrder", "aaa");
orderInfo.put("userRemark", "aaa");
orderInfo.put("merchantRemark", "aaa");
orderInfo.put("pickUpAddress", "aaa");
orderInfo.put("sendAddress", "aaa");
tempObj.add(orderInfo);
orderInfo = new JSONObject();
orderInfo.put("petName", "bbb");
orderInfo.put("petType", "bbb");
orderInfo.put("weight", "bbb");
orderInfo.put("diedTime", "bbb");
orderInfo.put("diedReason", "bbb");
orderInfo.put("remainsPhoneUrl", "bbb");
orderInfo.put("subType", "bbb");
orderInfo.put("changeRule", "bbb");
orderInfo.put("subOrder", "bbb");
orderInfo.put("userRemark", "bbb");
orderInfo.put("merchantRemark", "bbb");
orderInfo.put("pickUpAddress", "bbb");
orderInfo.put("sendAddress", "bbb");
tempObj.add(orderInfo);
String jsonString = JSON.toJSONString(tempObj);
System.out.println("serveInfo:" + jsonString);
itemDO.setServeInfo(jsonString);
JSONArray tempObj1 = new JSONArray();
JSONObject extraInfo = new JSONObject();
extraInfo.put("serveUrl", "aaa");
extraInfo.put("serveName", "aaa");
extraInfo.put("serveDesc", "aaa");
extraInfo.put("prodType", "aaa");
extraInfo.put("parentActive", "aaa");
extraInfo.put("count", "aaa");
extraInfo.put("price", "aaa");
extraInfo.put("handPrice", "aaa");
extraInfo.put("totalPrice", "aaa");
extraInfo.put("discountPrice", "aaa");
extraInfo.put("payPrice", "aaa");
extraInfo.put("refundMoney", "aaa");
extraInfo.put("refundCount", "aaa");
extraInfo.put("deliveryType", "aaa");
extraInfo.put("receiptUser", "aaa");
extraInfo.put("userMobile", "aaa");
extraInfo.put("receiveAddress", "aaa");
tempObj1.add(extraInfo);
extraInfo = new JSONObject();
extraInfo.put("serveUrl", "bbb");
extraInfo.put("serveName", "bbb");
extraInfo.put("serveDesc", "bbb");
extraInfo.put("prodType", "bbb");
extraInfo.put("parentActive", "bbb");
extraInfo.put("count", "bbb");
extraInfo.put("price", "bbb");
extraInfo.put("handPrice", "bbb");
extraInfo.put("totalPrice", "bbb");
extraInfo.put("discountPrice", "bbb");
extraInfo.put("payPrice", "bbb");
extraInfo.put("refundMoney", "bbb");
extraInfo.put("refundCount", "bbb");
extraInfo.put("deliveryType", "bbb");
extraInfo.put("receiptUser", "bbb");
extraInfo.put("userMobile", "bbb");
extraInfo.put("receiveAddress", "bbb");
tempObj1.add(extraInfo);
String jsonString1 = JSON.toJSONString(tempObj1);
System.out.println("selected:" + jsonString1);
itemDO.setServeExtInfo(jsonString1);
JSONArray priceExtObj = new JSONArray();
JSONObject priceExtInfo = new JSONObject();
priceExtInfo.put("costName", "aaa");
priceExtInfo.put("serveArea", "aaa");
priceExtInfo.put("targetArea", "aaa");
priceExtInfo.put("chargeType", "aaa");
priceExtInfo.put("respMode", "aaa");
priceExtInfo.put("respTime", "aaa");
priceExtInfo.put("weight", "aaa");
priceExtInfo.put("chargeTime", "aaa");
priceExtInfo.put("totalPrice", "aaa");
priceExtInfo.put("discountPrice", "aaa");
priceExtInfo.put("payPrice", "aaa");
priceExtInfo.put("refundPrice", "aaa");
priceExtObj.add(priceExtInfo);
priceExtInfo = new JSONObject();
priceExtInfo.put("costName", "bbb");
priceExtInfo.put("serveArea", "bbb");
priceExtInfo.put("targetArea", "bbb");
priceExtInfo.put("chargeType", "bbb");
priceExtInfo.put("respMode", "bbb");
priceExtInfo.put("respTime", "bbb");
priceExtInfo.put("weight", "bbb");
priceExtInfo.put("chargeTime", "bbb");
priceExtInfo.put("totalPrice", "bbb");
priceExtInfo.put("discountPrice", "bbb");
priceExtInfo.put("payPrice", "bbb");
priceExtInfo.put("refundPrice", "bbb");
priceExtObj.add(priceExtInfo);
String jsonString2 = JSON.toJSONString(priceExtObj);
System.out.println("price:" + jsonString2);
itemDO.setPriceExtInfo(jsonString2);
Map<String, Object> trans = trans(itemDO);
System.out.println(JSON.toJSONString(trans));
}
}

View File

@@ -70,10 +70,9 @@ public interface TradeOrderQueryService {
/** /**
* 获得订单统计 * 获得订单统计
* *
* @param reqVO 请求参数
* @return 订单统计 * @return 订单统计
*/ */
TradeOrderSummaryRespVO getOrderSummary(TradeOrderPageReqVO reqVO); TradeOrderSummaryRespVO getOrderSummary();
/** /**
* 【会员】获得交易订单分页 * 【会员】获得交易订单分页

View File

@@ -1,7 +1,6 @@
package com.tashow.cloud.trade.service.order; package com.tashow.cloud.trade.service.order;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil; import cn.hutool.extra.spring.SpringUtil;
import com.tashow.cloud.common.pojo.PageResult; import com.tashow.cloud.common.pojo.PageResult;
@@ -18,7 +17,6 @@ import com.tashow.cloud.trade.framework.delivery.core.client.ExpressClientFactor
import com.tashow.cloud.trade.framework.delivery.core.client.dto.ExpressTrackQueryReqDTO; import com.tashow.cloud.trade.framework.delivery.core.client.dto.ExpressTrackQueryReqDTO;
import com.tashow.cloud.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO; import com.tashow.cloud.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO;
import com.tashow.cloud.trade.service.delivery.DeliveryExpressService; import com.tashow.cloud.trade.service.delivery.DeliveryExpressService;
import com.tashow.cloud.tradeapi.enums.order.TradeOrderRefundStatusEnum;
import com.tashow.cloud.tradeapi.enums.order.TradeOrderStatusEnum; import com.tashow.cloud.tradeapi.enums.order.TradeOrderStatusEnum;
import com.tashow.cloud.tradeapi.enums.order.TradeOrderTypeEnum; import com.tashow.cloud.tradeapi.enums.order.TradeOrderTypeEnum;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@@ -118,27 +116,12 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService {
} }
@Override @Override
public TradeOrderSummaryRespVO getOrderSummary(TradeOrderPageReqVO reqVO) { public TradeOrderSummaryRespVO getOrderSummary() {
// 根据用户查询条件构建用户编号列表 List<Map<String, Object>> list = tradeOrderMapper.selectOrderSummary();
Set<Long> userIds = buildQueryConditionUserIds(reqVO); return new TradeOrderSummaryRespVO()
if (userIds == null) { // 没查询到用户,说明肯定也没他的订单 .setOrderCount(list.stream().mapToLong(x -> Long.parseLong(x.get("count").toString())).sum())
return new TradeOrderSummaryRespVO(); .setLivePrice(list.stream().mapToLong(x -> Long.parseLong(x.get("livePrice").toString())).sum())
} .setPayPrice(list.stream().mapToLong(x -> Long.parseLong(x.get("payPrice").toString())).sum());
// 查询每个售后状态对应的数量、金额
List<Map<String, Object>> list = tradeOrderMapper.selectOrderSummaryGroupByRefundStatus(reqVO, userIds);
TradeOrderSummaryRespVO vo = new TradeOrderSummaryRespVO().setAfterSaleCount(0L).setAfterSalePrice(0L);
for (Map<String, Object> map : list) {
Long count = MapUtil.getLong(map, "count", 0L);
Long price = MapUtil.getLong(map, "price", 0L);
// 未退款的计入订单,部分退款、全部退款计入售后
if (TradeOrderRefundStatusEnum.NONE.getStatus().equals(MapUtil.getInt(map, "refundStatus"))) {
vo.setOrderCount(count).setOrderPayPrice(price);
} else {
vo.setAfterSaleCount(vo.getAfterSaleCount() + count).setAfterSalePrice(vo.getAfterSalePrice() + price);
}
}
return vo;
} }
@Override @Override

View File

@@ -268,19 +268,19 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
PayOrderRespDTO payOrder = validatePayOrderPaid(order, payOrderId); PayOrderRespDTO payOrder = validatePayOrderPaid(order, payOrderId);
// 3. 更新 TradeOrderDO 状态为已支付,等待发货 // 3. 更新 TradeOrderDO 状态为已支付,等待发货
int updateCount = tradeOrderMapper.updateByIdAndStatus(id, order.getOrderStatus(), // int updateCount = tradeOrderMapper.updateByIdAndStatus(id, order.getOrderStatus(),
new TradeOrderDO().setOrderStatus(TradeOrderStatusEnum.UNDELIVERED.getStatus()).setPayStatus(true) // new TradeOrderDO().setOrderStatus(TradeOrderStatusEnum.UNDELIVERED.getStatus()).setPayStatus(true)
.setPayTime(LocalDateTime.now()).setPayChannelCode("")); // .setPayTime(LocalDateTime.now()).setPayChannelCode(1));
if (updateCount == 0) { // if (updateCount == 0) {
throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID); // throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID);
} // }
// 4. 执行 TradeOrderHandler 的后置处理 // 4. 执行 TradeOrderHandler 的后置处理
List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(id); List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(id);
tradeOrderHandlers.forEach(handler -> handler.afterPayOrder(order, orderItems)); tradeOrderHandlers.forEach(handler -> handler.afterPayOrder(order, orderItems));
// 5. 记录订单日志 // 5. 记录订单日志
TradeOrderLogUtils.setOrderInfo(order.getId(), order.getOrderStatus(), TradeOrderStatusEnum.UNDELIVERED.getStatus()); // TradeOrderLogUtils.setOrderInfo(order.getId(), order.getOrderStatus(), TradeOrderStatusEnum.UNDELIVERED.getStatus());
TradeOrderLogUtils.setUserInfo(order.getUserId(), UserTypeEnum.MEMBER.getValue()); TradeOrderLogUtils.setUserInfo(order.getUserId(), UserTypeEnum.MEMBER.getValue());
} }
@@ -351,7 +351,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
TradeOrderDO updateOrderObj = new TradeOrderDO(); TradeOrderDO updateOrderObj = new TradeOrderDO();
// 2.1 快递发货 // 2.1 快递发货
DeliveryExpressDO express = null; DeliveryExpressDO express = null;
if (ObjectUtil.notEqual(deliveryReqVO.getLogisticsId(), TradeOrderDO.LOGISTICS_ID_NULL)) { if (ObjectUtil.notEqual(deliveryReqVO.getLogisticsId(), null)) {
express = deliveryExpressService.validateDeliveryExpress(deliveryReqVO.getLogisticsId()); express = deliveryExpressService.validateDeliveryExpress(deliveryReqVO.getLogisticsId());
updateOrderObj.setLogisticsId(deliveryReqVO.getLogisticsId()).setLogisticsNo(deliveryReqVO.getLogisticsNo()); updateOrderObj.setLogisticsId(deliveryReqVO.getLogisticsId()).setLogisticsNo(deliveryReqVO.getLogisticsNo());
} else { } else {
@@ -516,9 +516,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
throw exception(ORDER_NOT_FOUND); throw exception(ORDER_NOT_FOUND);
} }
// 1.2 校验状态 // 1.2 校验状态
if (ObjectUtil.notEqual(order.getOrderStatus(), TradeOrderStatusEnum.UNPAID.getStatus())) { // if (ObjectUtil.notEqual(order.getOrderStatus(), TradeOrderStatusEnum.UNPAID.getStatus())) {
throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID); // throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID);
} // }
// 2. 取消订单 // 2. 取消订单
cancelOrder0(order, TradeOrderCancelTypeEnum.MEMBER_CANCEL); cancelOrder0(order, TradeOrderCancelTypeEnum.MEMBER_CANCEL);
@@ -529,7 +529,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
// 1. 查询过期的待支付订单 // 1. 查询过期的待支付订单
LocalDateTime expireTime = minusTime(tradeOrderProperties.getPayExpireTime()); LocalDateTime expireTime = minusTime(tradeOrderProperties.getPayExpireTime());
List<TradeOrderDO> orders = tradeOrderMapper.selectListByStatusAndCreateTimeLt( List<TradeOrderDO> orders = tradeOrderMapper.selectListByStatusAndCreateTimeLt(
TradeOrderStatusEnum.UNPAID.getStatus(), expireTime); TradeOrderStatusEnum.WAITPAID.getStatus(), expireTime);
if (CollUtil.isEmpty(orders)) { if (CollUtil.isEmpty(orders)) {
return 0; return 0;
} }
@@ -643,9 +643,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
throw exception(ORDER_UPDATE_PRICE_FAIL_PAID); throw exception(ORDER_UPDATE_PRICE_FAIL_PAID);
} }
// 1.2 校验调价金额是否变化 // 1.2 校验调价金额是否变化
if (order.getAdjustPrice() > 0) { // if (order.getAdjustPrice() > 0) {
throw exception(ORDER_UPDATE_PRICE_FAIL_ALREADY); // throw exception(ORDER_UPDATE_PRICE_FAIL_ALREADY);
} // }
// 1.3 支付价格不能为 0 // 1.3 支付价格不能为 0
int newPayPrice = order.getPayPrice() + reqVO.getAdjustPrice(); int newPayPrice = order.getPayPrice() + reqVO.getAdjustPrice();
if (newPayPrice <= 0) { if (newPayPrice <= 0) {
@@ -653,8 +653,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
} }
// 2. 更新订单 // 2. 更新订单
tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()) // tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId())
.setAdjustPrice(reqVO.getAdjustPrice() + order.getAdjustPrice()).setPayPrice(newPayPrice)); // .setAdjustPrice(reqVO.getAdjustPrice() + order.getAdjustPrice()).setPayPrice(newPayPrice));
// 3. 更新 TradeOrderItem需要做 adjustPrice 的分摊 // 3. 更新 TradeOrderItem需要做 adjustPrice 的分摊
List<TradeOrderItemDO> orderOrderItems = tradeOrderItemMapper.selectListByOrderId(order.getId()); List<TradeOrderItemDO> orderOrderItems = tradeOrderItemMapper.selectListByOrderId(order.getId());

View File

@@ -0,0 +1,184 @@
{
"serveInfo": {
"boneInfo": {
"petName": "aaa",
"petType": "aaa",
"weight": "aaa",
"diedTime": "aaa",
"diedReason": "aaa",
"boneUrl": [
"aaa",
"bbb"
]
},
"subInfo": {
"subType": "bbbb",
"changeRule": "bbbb",
"subOrder": "bbbb",
"userRemark": "bbbb",
"merchantRemark": "bbbb",
"pickUpAddress": "bbbb",
"sendAddress": "bbbb"
}
},
"selectedServeInfo": [
[
{
"tempType": 1,
"serve": [
{
"serveUrl": "ccc",
"serveName": "ccc",
"serveDesc": "ccc",
"count": "ccc",
"price": "ccc",
"handPrice": "ccc"
}
],
"totalPrice": "ccc",
"discountPrice": "ccc",
"payPrice": "ccc",
"refundMoney": "ccc",
"refundCount": "ccc"
},
{
"tempType": 2,
"serve": [
{
"serveUrl": "ccc",
"serveName": "ccc",
"serveDesc": "ccc",
"count": "ccc",
"price": "ccc",
"handPrice": "ccc",
"parentActive": "ccc",
"riteAddress": "ccc"
}
],
"totalPrice": "ccc",
"discountPrice": "ccc",
"payPrice": "ccc",
"refundMoney": "ccc",
"refundCount": "ccc"
}
],
[
{
"tempType": 3,
"serveTitle": "骨灰处理",
"serveType": "处理方式",
"serve": [
{
"serveUrl": "ccc",
"serveName": "ccc",
"serveDesc": "ccc",
"count": "ccc",
"price": "ccc",
"handPrice": "ccc"
},
{
"serveUrl": "ccc",
"serveName": "ccc",
"serveDesc": "ccc",
"count": "ccc",
"price": "ccc",
"handPrice": "ccc"
}
],
"totalPrice": "ccc",
"discountPrice": "ccc",
"payPrice": "ccc",
"refundMoney": "ccc",
"refundCount": "ccc"
},
{
"deliveryType": "配送方式",
"receiveUser": "收货人",
"sendUser": "提货人",
"userMobile": "手机号码",
"address": "收货地址"
}
],
[
{
"tempType": 4,
"serve": [
{
"prodUrl": "ccc",
"prodName": "ccc",
"prodDesc": "ccc",
"prodType": "ccc",
"parentActivity": "ccc",
"count": "ccc",
"price": "ccc",
"handPrice": "ccc"
}
],
"totalPrice": "ccc",
"discountPrice": "ccc",
"payPrice": "ccc",
"refundMoney": "ccc",
"refundCount": "ccc"
},
{
"deliveryType": "配送方式",
"receiveUser": "收货人",
"sendUser": "提货人",
"userMobile": "手机号码",
"address": "收货地址"
}
]
],
"priceExtInfo": [
{
"serveExtFee": "",
"costName": "超区域服务费",
"serveArea": "可服务区域",
"targetArea": "目标区域",
"chargeType": "收费方式",
"payInfo": {
"totalPrice": "11",
"discountPrice": "222",
"payPrice": "333"
},
"refundPrice": "11"
},
{
"serveExtFee": "",
"respMode": "响应模式",
"respTime": "响应时间",
"chargeType": "收费方式",
"payInfo": {
"totalPrice": "11",
"discountPrice": "222",
"payPrice": "333"
},
"refundPrice": "11"
},
{
"serveExtFee": "",
"costName": "超区域服务费",
"weight": "体型/体重",
"chargeType": "收费方式",
"payInfo": {
"totalPrice": "11",
"discountPrice": "222",
"payPrice": "333"
},
"refundPrice": "11"
},
{
"serveExtFee": "",
"costName": "超区域服务费",
"chargeTime": "收费时段",
"chargeType": "收费方式",
"payInfo": {
"totalPrice": "11",
"discountPrice": "222",
"payPrice": "333"
},
"refundPrice": "11"
}
]
}