9 files added
14 files modified
| New file |
| | |
| | | -- ============================================================ |
| | | -- 国家运费配置表 |
| | | -- ============================================================ |
| | | DROP TABLE IF EXISTS mall_country_delivery; |
| | | CREATE TABLE mall_country_delivery ( |
| | | ID BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键', |
| | | REVISION INT DEFAULT 1 COMMENT '乐观锁', |
| | | CREATED_BY VARCHAR(32) DEFAULT 'system' COMMENT '创建人', |
| | | CREATED_TIME DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', |
| | | UPDATED_BY VARCHAR(32) DEFAULT 'system' COMMENT '更新人', |
| | | UPDATED_TIME DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', |
| | | COUNTRY_CODE VARCHAR(10) NOT NULL COMMENT '国家编码(ISO 3166-1,如 CN/US/JP)', |
| | | COUNTRY_NAME VARCHAR(64) NOT NULL COMMENT '国家名称(中文)', |
| | | SHIPPING_FEE DECIMAL(10,2) NOT NULL DEFAULT 0.00 COMMENT '运费(元)', |
| | | STATUS INT DEFAULT 1 COMMENT '状态:1-启用,0-禁用', |
| | | REMARK VARCHAR(255) COMMENT '备注', |
| | | PRIMARY KEY (ID), |
| | | UNIQUE KEY uk_country_code (COUNTRY_CODE) |
| | | ) COMMENT = '国家运费配置表'; |
| | | |
| | | -- ---------------------------- |
| | | -- 默认数据 |
| | | -- ---------------------------- |
| | | INSERT INTO mall_country_delivery (COUNTRY_CODE, COUNTRY_NAME, SHIPPING_FEE, STATUS, REMARK) VALUES |
| | | ('CN', '中国', 0.00, 1, '国内免运费'), |
| | | ('US', '美国', 59.00, 1, NULL), |
| | | ('JP', '日本', 35.00, 1, NULL), |
| | | ('KR', '韩国', 30.00, 1, NULL), |
| | | ('GB', '英国', 50.00, 1, NULL), |
| | | ('DE', '德国', 50.00, 1, NULL), |
| | | ('FR', '法国', 50.00, 1, NULL), |
| | | ('AU', '澳大利亚', 55.00, 1, NULL), |
| | | ('CA', '加拿大', 55.00, 1, NULL), |
| | | ('SG', '新加坡', 28.00, 1, NULL); |
| | | |
| | | -- ============================================================ |
| | | -- 菜单注册 SQL(通过后台菜单管理页面操作,或直接执行) |
| | | -- ============================================================ |
| | | -- INSERT INTO t_menu (MENU_NAME, URL, PERMS, ICON, TYPE, PARENT_ID, ORDER_NUM, CREATED_TIME) |
| | | -- VALUES ('国家运费设置', 'modules/system/countryDeliveryList', 'countryDelivery:view', 'layui-icon-template-1', 0, {系统设置菜单ID}, 13, NOW()); |
| | |
| | | @ExceptionHandler(value = Exception.class) |
| | | public FebsResponse handleException(Exception e) { |
| | | log.error("系统内部异常,异常信息", e); |
| | | return new FebsResponse().code(HttpStatus.INTERNAL_SERVER_ERROR).message("系统繁忙,请稍后重试"); |
| | | return new FebsResponse().code(HttpStatus.INTERNAL_SERVER_ERROR).message("The system is busy, please try again later"); |
| | | } |
| | | |
| | | @ExceptionHandler(value = FebsException.class) |
| | |
| | | package cc.mrbird.febs.mall.controller; |
| | | |
| | | import cc.mrbird.febs.common.annotation.ControllerEndpoint; |
| | | import cc.mrbird.febs.common.controller.BaseController; |
| | | import cc.mrbird.febs.common.entity.FebsResponse; |
| | | import cc.mrbird.febs.common.entity.QueryRequest; |
| | | import cc.mrbird.febs.common.enumerates.DataDictionaryEnum; |
| | | import cc.mrbird.febs.common.utils.AppContants; |
| | | import cc.mrbird.febs.mall.dto.*; |
| | | import cc.mrbird.febs.mall.entity.DataDictionaryCustom; |
| | | import cc.mrbird.febs.mall.entity.MallCountryDelivery; |
| | | import cc.mrbird.febs.mall.entity.MallNewsInfo; |
| | | import cc.mrbird.febs.mall.mapper.DataDictionaryCustomMapper; |
| | | import cc.mrbird.febs.mall.service.ICommonService; |
| | | import cc.mrbird.febs.mall.service.IMallCountryDeliveryService; |
| | | import cc.mrbird.febs.mall.service.ISystemService; |
| | | import cc.mrbird.febs.pay.model.HeaderDto; |
| | | import cc.mrbird.febs.pay.service.WxFaPiaoService; |
| | |
| | | import org.apache.commons.httpclient.methods.StringRequestEntity; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.PathVariable; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RequestParam; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import java.io.IOException; |
| | |
| | | import java.security.NoSuchAlgorithmException; |
| | | import java.security.PrivateKey; |
| | | import java.util.Arrays; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | |
| | | @RestController |
| | | @RequiredArgsConstructor |
| | | @RequestMapping(value = "/admin/system") |
| | | public class AdminSystemController { |
| | | public class AdminSystemController extends BaseController { |
| | | |
| | | @Autowired |
| | | private ISystemService systemService; |
| | |
| | | private final ICommonService commonService; |
| | | private final DataDictionaryCustomMapper dataDictionaryCustomMapper; |
| | | private final WxFaPiaoService wxFaPiaoService; |
| | | private final IMallCountryDeliveryService countryDeliveryService; |
| | | |
| | | @PostMapping(value = "/bonusSystemSetting") |
| | | public FebsResponse bonusSystemSetting(@RequestBody Map<String, Object> map) { |
| | |
| | | } |
| | | commonService.addDataDic("TOKENVIEW_CONFIG", "WEBHOOK_SECRET", dto.getWebhookSecret(), "Tokenview Webhook签名密钥", false); |
| | | commonService.addDataDic("TOKENVIEW_CONFIG", "TRC20_USDT_ADDRESS", dto.getTrc20UsdtAddress(), "TRC20 USDT收款地址", false); |
| | | commonService.addDataDic("SALES_SERVICE", "TRC_ADDRESS", dto.getTrc20UsdtAddress(), "TRC20 USDT收款地址", false); |
| | | return new FebsResponse().success().message("保存成功"); |
| | | } |
| | | |
| | |
| | | return new FebsResponse().success().message("保存成功"); |
| | | } |
| | | |
| | | @GetMapping(value = "/moneyChangeList") |
| | | public FebsResponse moneyChangeList() { |
| | | List<DataDictionaryCustom> list = dataDictionaryCustomMapper.selectDicByType("MONEY_CHANGE"); |
| | | Map<String, Object> data = new HashMap<>(); |
| | | data.put("rows", list); |
| | | data.put("total", list.size()); |
| | | return new FebsResponse().success().data(data); |
| | | } |
| | | |
| | | @PostMapping(value = "/moneyChangeSave") |
| | | @ControllerEndpoint(operation = "保存汇率配置") |
| | | public FebsResponse moneyChangeSave(@RequestParam Map<String, String> params) { |
| | | String id = params.get("id"); |
| | | String code = params.get("code"); |
| | | String value = params.get("value"); |
| | | String description = params.get("description"); |
| | | |
| | | if (StrUtil.isBlank(code)) return new FebsResponse().fail().message("货币编码不能为空"); |
| | | if (StrUtil.isBlank(value)) return new FebsResponse().fail().message("汇率不能为空"); |
| | | if (StrUtil.isBlank(description)) return new FebsResponse().fail().message("符号不能为空"); |
| | | |
| | | code = code.toUpperCase(); |
| | | |
| | | // 编辑模式:先删旧记录 |
| | | if (StrUtil.isNotBlank(id)) { |
| | | dataDictionaryCustomMapper.deleteById(Long.valueOf(id)); |
| | | } |
| | | |
| | | // 检查编码是否已存在(避免重复) |
| | | DataDictionaryCustom exist = dataDictionaryCustomMapper.selectDicDataByTypeAndCode("MONEY_CHANGE", code); |
| | | if (exist != null) { |
| | | return new FebsResponse().fail().message("货币编码 " + code + " 已存在"); |
| | | } |
| | | |
| | | commonService.addDataDic("MONEY_CHANGE", code, value, description, false); |
| | | return new FebsResponse().success().message("保存成功"); |
| | | } |
| | | |
| | | @GetMapping(value = "/moneyChangeDelete/{id}") |
| | | @ControllerEndpoint(operation = "删除汇率配置") |
| | | public FebsResponse moneyChangeDelete(@PathVariable Long id) { |
| | | dataDictionaryCustomMapper.deleteById(id); |
| | | return new FebsResponse().success().message("删除成功"); |
| | | } |
| | | |
| | | @GetMapping("countryDeliveryList") |
| | | public FebsResponse countryDeliveryList(MallCountryDelivery dto, QueryRequest request) { |
| | | Map<String, Object> data = getDataTable(countryDeliveryService.countryDeliveryList(dto, request)); |
| | | return new FebsResponse().success().data(data); |
| | | } |
| | | |
| | | @PostMapping(value = "/countryDeliverySave") |
| | | @ControllerEndpoint(operation = "保存国家运费配置") |
| | | public FebsResponse countryDeliverySave(@Validated CountryDeliveryDto dto) { |
| | | return countryDeliveryService.saveOrUpdate(dto); |
| | | } |
| | | |
| | | @GetMapping(value = "/countryDeliveryDelete/{id}") |
| | | @ControllerEndpoint(operation = "删除国家运费配置") |
| | | public FebsResponse countryDeliveryDelete(@PathVariable Long id) { |
| | | return countryDeliveryService.delete(id); |
| | | } |
| | | |
| | | @PostMapping(value = "/agentAmountSetSetting") |
| | | public FebsResponse agentAmountSetSetting(AdminAgentAmountDto adminAgentAmountDto) { |
| | | DataDictionaryCustom dic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( |
| | |
| | | model.addAttribute("salesService", dto); |
| | | return FebsUtil.view("modules/system/salesService"); |
| | | } |
| | | |
| | | @GetMapping("countryDeliveryList") |
| | | @RequiresPermissions("countryDelivery:view") |
| | | public String countryDeliveryList() { |
| | | return FebsUtil.view("modules/system/countryDeliveryList"); |
| | | } |
| | | |
| | | @GetMapping("moneyChange") |
| | | @RequiresPermissions("moneyChange:update") |
| | | public String moneyChange() { |
| | | return FebsUtil.view("modules/system/moneyChange"); |
| | | } |
| | | } |
| | |
| | | import cc.mrbird.febs.common.annotation.Limit; |
| | | import cc.mrbird.febs.common.entity.FebsResponse; |
| | | import cc.mrbird.febs.common.entity.LimitType; |
| | | import cc.mrbird.febs.common.enumerates.OrderStatusEnum; |
| | | import cc.mrbird.febs.common.utils.MallUtils; |
| | | import cc.mrbird.febs.common.utils.ValidateEntityUtils; |
| | | import cc.mrbird.febs.mall.controller.dependentStation.constant.OrderConstants; |
| | | import cc.mrbird.febs.mall.dto.*; |
| | | import cc.mrbird.febs.mall.entity.MallOrderInfo; |
| | | import cc.mrbird.febs.mall.service.IApiMallOrderInfoService; |
| | | import cc.mrbird.febs.mall.service.IMallCountryDeliveryService; |
| | | import cc.mrbird.febs.mall.vo.ApiOrderPayVo; |
| | | import cc.mrbird.febs.mall.vo.OrderDetailVo; |
| | | import cc.mrbird.febs.mall.vo.OrderListVo; |
| | | import cc.mrbird.febs.pay.service.IXcxPayService; |
| | | import cc.mrbird.febs.pay.service.LwPayService; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import io.swagger.annotations.ApiResponse; |
| | |
| | | private final IApiMallOrderInfoService mallOrderInfoService; |
| | | private final IXcxPayService iXcxPayService; |
| | | private final LwPayService lwPayService; |
| | | private final IMallCountryDeliveryService countryDeliveryService; |
| | | |
| | | @ApiOperation(value = "创建订单--验证是否允许创建", notes = "创建订单--验证是否允许创建") |
| | | @PostMapping(value = "/createOrderVerify") |
| | |
| | | |
| | | // 2. 获取订单详情 |
| | | MallOrderInfo order = mallOrderInfoService.getById(orderId); |
| | | if (order == null) { |
| | | return new FebsResponse().fail().message("订单创建失败"); |
| | | } |
| | | if (order != null |
| | | && OrderStatusEnum.WAIT_PAY.getValue() == order.getStatus() |
| | | ){ |
| | | |
| | | // 3. 调用 LWPAY 代收接口 |
| | | try { |
| | | String payUrl = lwPayService.createPayment( |
| | | order, |
| | | lwPayDto.getBankCode(), |
| | | lwPayDto.getNetwork() |
| | | // 3. 调用 LWPAY 代收接口 |
| | | try { |
| | | String payUrl = lwPayService.createPayment( |
| | | order, |
| | | lwPayDto.getBankCode(), |
| | | lwPayDto.getNetwork() |
| | | ); |
| | | |
| | | Map<String, Object> result = new HashMap<>(); |
| | | result.put("orderNo", order.getOrderNo()); |
| | | result.put("amount", order.getAmount()); |
| | | result.put("payUrl", payUrl); |
| | | return new FebsResponse().success().data(result); |
| | | } catch (Exception e) { |
| | | log.error("LWPAY 代收下单失败: orderId={}", orderId, e); |
| | | return new FebsResponse().fail().message("Payment channel exception: " + e.getMessage()); |
| | | } |
| | | } |
| | | return new FebsResponse().fail().message("Payment channel exception"); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | @ApiOperation(value = "LWPAY支付", notes = "LWPAY支付") |
| | | @ApiResponses({ |
| | | @ApiResponse(code = 200, message = "success", response = ApiOrderPayVo.class) |
| | | }) |
| | | @PostMapping(value = "/payOrderByLwPay", produces = "application/json") |
| | | public FebsResponse payOrderByLwPay(@RequestBody @Validated ApiOrderPayDto payDto) { |
| | | |
| | | Long orderId = payDto.getOrderId(); |
| | | Integer payType = payDto.getPayType(); |
| | | // 2. 获取订单详情 |
| | | MallOrderInfo order = mallOrderInfoService.getById(orderId); |
| | | if (order != null |
| | | && OrderConstants.PAY_TYPE_SYSTEM == payType |
| | | && OrderStatusEnum.WAIT_PAY.getValue() == order.getStatus() |
| | | ){ |
| | | String orderNo = MallUtils.getOrderNum(); |
| | | order.setOrderNo(orderNo); |
| | | mallOrderInfoService.getBaseMapper().update( |
| | | null, |
| | | Wrappers.lambdaUpdate(MallOrderInfo.class) |
| | | .set(MallOrderInfo::getOrderNo, orderNo) |
| | | .eq(MallOrderInfo::getId, orderId) |
| | | ); |
| | | // 3. 调用 LWPAY 代收接口 |
| | | try { |
| | | String payUrl = lwPayService.createPayment( |
| | | order, |
| | | "967", |
| | | null |
| | | ); |
| | | |
| | | Map<String, Object> result = new HashMap<>(); |
| | | result.put("orderNo", order.getOrderNo()); |
| | | result.put("amount", order.getAmount()); |
| | | result.put("payUrl", payUrl); |
| | | return new FebsResponse().success().data(result).message("下单成功"); |
| | | } catch (Exception e) { |
| | | log.error("LWPAY 代收下单失败: orderId={}", orderId, e); |
| | | return new FebsResponse().fail().message("支付通道异常: " + e.getMessage()); |
| | | Map<String, Object> result = new HashMap<>(); |
| | | result.put("orderNo", order.getOrderNo()); |
| | | result.put("amount", order.getAmount()); |
| | | result.put("payUrl", payUrl); |
| | | return new FebsResponse().success().data(result).message("下单成功"); |
| | | } catch (Exception e) { |
| | | log.error("LWPAY 代收下单失败: orderId={}", orderId, e); |
| | | return new FebsResponse().fail().message("Payment channel exception: " + e.getMessage()); |
| | | } |
| | | } |
| | | return new FebsResponse().fail().message("Payment channel exception"); |
| | | } |
| | | |
| | | /** |
| | |
| | | return "redirect:/pages/payResult?orderNo=" + orderId + "&code=" + returncode; |
| | | } |
| | | |
| | | @ApiOperation(value = "根据国家编码查询运费", notes = "根据国家编码查询对应运费") |
| | | @ApiResponses({ |
| | | @ApiResponse(code = 200, message = "success") |
| | | }) |
| | | @GetMapping(value = "/getShippingFee") |
| | | public FebsResponse getShippingFee(@RequestParam String countryCode) { |
| | | return countryDeliveryService.getShippingFeeByCountryCode(countryCode); |
| | | } |
| | | |
| | | } |
| | |
| | | } |
| | | |
| | | // 从 payload 提取关键字段(兼容多种 key 命名) |
| | | String toAddress = getField(payload, "address", "toAddress","to"); |
| | | String txid = getField(payload, "txid", "hash", "transactionHash"); |
| | | String toAddress = getField(payload, "to", "toAddress"); |
| | | String time = getField(payload, "time"); |
| | | String value = getField(payload, "value", "amount"); |
| | | String tokenAddr = getField(payload, "token", "tokenAddr", "contractAddress"); |
| | | String symbol = getField(payload, "symbol", "tokenSymbol"); |
| | | String coin = getField(payload, "coin"); |
| | | String tokenAddr = getField(payload, "token", "tokenAddr", "contractAddress","tokenAddress"); |
| | | String tokenSymbol = getField(payload, "tokenSymbol"); |
| | | String tokenValue = getField(payload, "tokenValue"); |
| | | |
| | | if (StrUtil.isBlank(txid)) { |
| | | log.warn("webhook 推送数据缺少交易哈希 txid: {}", payload); |
| | | return "缺少 txid,跳过处理"; |
| | | } |
| | | |
| | | if (StrUtil.isNotBlank(tokenSymbol) && !"USDT".equalsIgnoreCase(tokenSymbol)) { |
| | | log.info("交易币种不匹配,期望: {}, 实际: {}, txid: {}", "USDT", tokenSymbol, txid); |
| | | return "收款地址不匹配,跳过处理"; |
| | | } |
| | | |
| | | // 验证收款地址是否匹配 |
| | |
| | | |
| | | // 验证 token 合约地址(USDT: TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t) |
| | | if (StrUtil.isNotBlank(tokenAddr) && !"TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t".equalsIgnoreCase(tokenAddr)) { |
| | | log.info("非 USDT 代币交易,跳过处理: token={}, symbol={}, txid={}", tokenAddr, symbol, txid); |
| | | log.info("非 USDT 代币交易,跳过处理: token={}, symbol={}, txid={}", tokenAddr, tokenSymbol, txid); |
| | | return "非 USDT 交易,跳过处理"; |
| | | } |
| | | |
| | | // 执行充值匹配 |
| | | return matchAndUpdateOrder(txid, value, receiveAddress); |
| | | return matchAndUpdateOrder(txid, tokenValue, receiveAddress); |
| | | } |
| | | |
| | | /** |
| | |
| | | } |
| | | BigDecimal amount; |
| | | try { |
| | | amount = new BigDecimal(rawValue) |
| | | .divide(new BigDecimal("1000000"), 2, RoundingMode.DOWN); |
| | | // amount = new BigDecimal(rawValue) |
| | | // .divide(new BigDecimal("1000000"), 2, RoundingMode.DOWN); |
| | | amount = new BigDecimal(rawValue); |
| | | } catch (NumberFormatException e) { |
| | | log.error("金额解析失败: txid={}, value={}", txid, rawValue, e); |
| | | return "金额解析失败: " + txid; |
| | |
| | | @ApiModelProperty(value = "配送费") |
| | | private BigDecimal deliveryAmount; |
| | | |
| | | @ApiModelProperty(value = "国家编码") |
| | | private String countryCode; |
| | | |
| | | @ApiModelProperty(value = "1-普通订单/2-积分订单") |
| | | private Integer orderType; |
| | | |
| | |
| | | @NotBlank(message = "Country/Region required") |
| | | @ApiModelProperty(value = "Country/Region") |
| | | private String country; |
| | | @ApiModelProperty(value = "Country/Region") |
| | | private String countryName; |
| | | |
| | | /** |
| | | * 经度 |
| | |
| | | private Long orderId; |
| | | |
| | | @NotNull(message = "支付方式不能为空") |
| | | @ApiModelProperty(value = "支付方式 1-微信 2-支付宝 3-USDT", example = "you_ke_*****") |
| | | @ApiModelProperty(value = "支付方式 1-微信 2-支付宝 3-USDT 4-LwPAY", example = "you_ke_*****") |
| | | private Integer payType; |
| | | } |
| New file |
| | |
| | | package cc.mrbird.febs.mall.dto; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import javax.validation.constraints.NotBlank; |
| | | import javax.validation.constraints.NotNull; |
| | | import java.math.BigDecimal; |
| | | |
| | | /** |
| | | * 国家运费配置 DTO |
| | | * |
| | | * @author auto-generated |
| | | */ |
| | | @Data |
| | | public class CountryDeliveryDto { |
| | | |
| | | private Long id; |
| | | |
| | | /** 国家编码 */ |
| | | @NotBlank(message = "国家编码不能为空") |
| | | private String countryCode; |
| | | |
| | | /** 国家名称 */ |
| | | @NotBlank(message = "国家名称不能为空") |
| | | private String countryName; |
| | | |
| | | /** 运费 */ |
| | | @NotNull(message = "运费不能为空") |
| | | private BigDecimal shippingFee; |
| | | |
| | | /** 状态 */ |
| | | private Integer status; |
| | | |
| | | /** 备注 */ |
| | | private String remark; |
| | | } |
| | |
| | | //市 |
| | | private String city; |
| | | private String country; |
| | | private String countryName; |
| | | |
| | | } |
| New file |
| | |
| | | package cc.mrbird.febs.mall.entity; |
| | | |
| | | import cc.mrbird.febs.common.entity.BaseEntity; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| | | /** |
| | | * 国家运费配置表 |
| | | * |
| | | * @author auto-generated |
| | | * @date 2026-06-22 |
| | | */ |
| | | @Data |
| | | @TableName("mall_country_delivery") |
| | | public class MallCountryDelivery extends BaseEntity { |
| | | |
| | | /** 国家编码(如 CN, US, JP) */ |
| | | private String countryCode; |
| | | |
| | | /** 国家名称(中文) */ |
| | | private String countryName; |
| | | |
| | | /** 运费(元) */ |
| | | private BigDecimal shippingFee; |
| | | |
| | | /** 状态:1-启用,0-禁用 */ |
| | | private Integer status; |
| | | |
| | | /** 备注 */ |
| | | private String remark; |
| | | } |
| New file |
| | |
| | | package cc.mrbird.febs.mall.mapper; |
| | | |
| | | import cc.mrbird.febs.mall.entity.MallCountryDelivery; |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | |
| | | /** |
| | | * 国家运费配置 Mapper |
| | | * |
| | | * @author auto-generated |
| | | */ |
| | | public interface MallCountryDeliveryMapper extends BaseMapper<MallCountryDelivery> { |
| | | |
| | | IPage<MallCountryDelivery> getCountryDeliveryListInPage(Page<MallCountryDelivery> page, MallCountryDelivery dto); |
| | | } |
| New file |
| | |
| | | package cc.mrbird.febs.mall.service; |
| | | |
| | | import cc.mrbird.febs.common.entity.FebsResponse; |
| | | import cc.mrbird.febs.common.entity.QueryRequest; |
| | | import cc.mrbird.febs.mall.dto.CountryDeliveryDto; |
| | | import cc.mrbird.febs.mall.entity.MallCountryDelivery; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | |
| | | /** |
| | | * 国家运费配置 Service 接口 |
| | | * |
| | | * @author auto-generated |
| | | */ |
| | | public interface IMallCountryDeliveryService { |
| | | |
| | | /** 列表查询 */ |
| | | FebsResponse list(); |
| | | |
| | | IPage<MallCountryDelivery> countryDeliveryList(MallCountryDelivery dto, QueryRequest request); |
| | | |
| | | /** 新增/更新 */ |
| | | FebsResponse saveOrUpdate(CountryDeliveryDto dto); |
| | | |
| | | /** 删除 */ |
| | | FebsResponse delete(Long id); |
| | | |
| | | /** 根据国家编码查询运费 */ |
| | | FebsResponse getShippingFeeByCountryCode(String countryCode); |
| | | } |
| | |
| | | addressInfoVo.setCity(mallAddressInfo.getCity()); |
| | | addressInfoVo.setProvince(mallAddressInfo.getProvince()); |
| | | addressInfoVo.setCountry(mallAddressInfo.getCountry()); |
| | | addressInfoVo.setCountryName(mallAddressInfo.getCountryName()); |
| | | } |
| | | return new FebsResponse().success().data(addressInfoVo); |
| | | } |
| | |
| | | .set(MallAddressInfo::getCity, addressInfoDto.getCity()) |
| | | .set(MallAddressInfo::getProvince, addressInfoDto.getProvince()) |
| | | .set(MallAddressInfo::getCountry, addressInfoDto.getCountry()) |
| | | .set(MallAddressInfo::getCountryName, addressInfoDto.getCountryName()) |
| | | .eq(MallAddressInfo::getMemberId, memberId) |
| | | ); |
| | | |
| | |
| | | private final IApiMallMemberService memberService; |
| | | private final IMallMoneyFlowService mallMoneyFlowService; |
| | | private final RedisUtils redisUtils; |
| | | private final MallCountryDeliveryMapper mallCountryDeliveryMapper; |
| | | |
| | | private final AgentProducer agentProducer; |
| | | private final ApiChatPayService apiChatPayService; |
| | |
| | | this.baseMapper.insert(orderInfo); |
| | | |
| | | BigDecimal total = BigDecimal.ZERO; |
| | | //运费 |
| | | BigDecimal delivaryAmount = addOrderDto.getDeliveryAmount() == null ? BigDecimal.ZERO : addOrderDto.getDeliveryAmount(); |
| | | for (AddOrderItemDto item : addOrderDto.getItems()) { |
| | | MallOrderItem orderItem = new MallOrderItem(); |
| | | |
| | |
| | | if(1 != goodsResult){ |
| | | throw new FebsException("Discontinued"); |
| | | } |
| | | |
| | | delivaryAmount = delivaryAmount.add(mallGoods.getCarriageAmount()); |
| | | |
| | | BigDecimal amount = sku.getPresentPrice().multiply(BigDecimal.valueOf(item.getCnt())); |
| | | orderItem.setAmount(amount); |
| | |
| | | } |
| | | mallOrderItemMapper.insert(orderItem); |
| | | } |
| | | |
| | | |
| | | |
| | | //运费 |
| | | MallCountryDelivery delivery = mallCountryDeliveryMapper.selectOne( |
| | | Wrappers.lambdaQuery(MallCountryDelivery.class) |
| | | .eq(MallCountryDelivery::getCountryCode, addOrderDto.getCountryCode().toUpperCase()) |
| | | .eq(MallCountryDelivery::getStatus, 1) |
| | | ); |
| | | MallCountryDelivery defaultDelivery = mallCountryDeliveryMapper.selectOne( |
| | | Wrappers.lambdaQuery(MallCountryDelivery.class) |
| | | .eq(MallCountryDelivery::getCountryCode, "DEFAULT") |
| | | .eq(MallCountryDelivery::getStatus, 1) |
| | | ); |
| | | BigDecimal delivaryAmount = defaultDelivery.getShippingFee(); |
| | | if (delivery != null) { |
| | | delivaryAmount = delivery.getShippingFee(); |
| | | } |
| | | orderInfo.setCarriage(delivaryAmount); |
| | | |
| | | total = total.add(delivaryAmount); |
| | |
| | | orderInfo.setName(address.getFristName() + address.getName()); |
| | | orderInfo.setPhone(address.getPhone()); |
| | | |
| | | orderInfo.setAddress(address.getArea()+ address.getAddress()+address.getCity()+address.getProvince() + address.getCountry() ); |
| | | orderInfo.setAddress( |
| | | address.getAddress() +" - " |
| | | +address.getArea() +" - " |
| | | +address.getCity() +" - " |
| | | +address.getProvince() +" - " |
| | | +address.getCountryName() +" - " |
| | | + address.getCountry() ); |
| | | orderInfo.setLatitude(address.getLatitude()); |
| | | orderInfo.setLongitude(address.getLongitude()); |
| | | this.baseMapper.updateById(orderInfo); |
| New file |
| | |
| | | package cc.mrbird.febs.mall.service.impl; |
| | | |
| | | import cc.mrbird.febs.common.entity.FebsResponse; |
| | | import cc.mrbird.febs.common.entity.QueryRequest; |
| | | import cc.mrbird.febs.mall.dto.CountryDeliveryDto; |
| | | import cc.mrbird.febs.mall.entity.MallCountryDelivery; |
| | | import cc.mrbird.febs.mall.mapper.MallCountryDeliveryMapper; |
| | | import cc.mrbird.febs.mall.service.IMallCountryDeliveryService; |
| | | import cc.mrbird.febs.mall.vo.AdminMallNewsInfoVo; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 国家运费配置 Service 实现 |
| | | * |
| | | * @author auto-generated |
| | | */ |
| | | @Slf4j |
| | | @Service |
| | | @RequiredArgsConstructor |
| | | public class MallCountryDeliveryServiceImpl implements IMallCountryDeliveryService { |
| | | |
| | | private final MallCountryDeliveryMapper mallCountryDeliveryMapper; |
| | | |
| | | @Override |
| | | public FebsResponse list() { |
| | | List<MallCountryDelivery> list = mallCountryDeliveryMapper.selectList( |
| | | Wrappers.lambdaQuery(MallCountryDelivery.class) |
| | | .orderByAsc(MallCountryDelivery::getCountryCode) |
| | | ); |
| | | return new FebsResponse().success().data(list); |
| | | } |
| | | |
| | | @Override |
| | | public IPage<MallCountryDelivery> countryDeliveryList(MallCountryDelivery dto, QueryRequest request) { |
| | | Page<MallCountryDelivery> page = new Page<>(request.getPageNum(), request.getPageSize()); |
| | | IPage<MallCountryDelivery> pages = mallCountryDeliveryMapper.getCountryDeliveryListInPage(page, dto); |
| | | return pages; |
| | | } |
| | | |
| | | @Override |
| | | public FebsResponse saveOrUpdate(CountryDeliveryDto dto) { |
| | | MallCountryDelivery entity = new MallCountryDelivery(); |
| | | entity.setCountryCode(dto.getCountryCode().toUpperCase()); |
| | | entity.setCountryName(dto.getCountryName()); |
| | | entity.setShippingFee(dto.getShippingFee()); |
| | | entity.setStatus(dto.getStatus() != null ? dto.getStatus() : 1); |
| | | entity.setRemark(dto.getRemark()); |
| | | |
| | | if (dto.getId() != null) { |
| | | // 更新 |
| | | entity.setId(dto.getId()); |
| | | mallCountryDeliveryMapper.updateById(entity); |
| | | log.info("更新国家运费配置: countryCode={}, fee={}", entity.getCountryCode(), entity.getShippingFee()); |
| | | } else { |
| | | // 新增前检查编码是否重复 |
| | | MallCountryDelivery exist = mallCountryDeliveryMapper.selectOne( |
| | | Wrappers.lambdaQuery(MallCountryDelivery.class) |
| | | .eq(MallCountryDelivery::getCountryCode, entity.getCountryCode()) |
| | | ); |
| | | if (exist != null) { |
| | | return new FebsResponse().fail().message("国家编码 " + entity.getCountryCode() + " 已存在"); |
| | | } |
| | | mallCountryDeliveryMapper.insert(entity); |
| | | log.info("新增国家运费配置: countryCode={}, fee={}", entity.getCountryCode(), entity.getShippingFee()); |
| | | } |
| | | return new FebsResponse().success().message("保存成功"); |
| | | } |
| | | |
| | | @Override |
| | | public FebsResponse delete(Long id) { |
| | | mallCountryDeliveryMapper.deleteById(id); |
| | | return new FebsResponse().success().message("删除成功"); |
| | | } |
| | | |
| | | @Override |
| | | public FebsResponse getShippingFeeByCountryCode(String countryCode) { |
| | | if (StrUtil.isBlank(countryCode)) { |
| | | return new FebsResponse().fail().message("国家编码不能为空"); |
| | | } |
| | | |
| | | MallCountryDelivery delivery = mallCountryDeliveryMapper.selectOne( |
| | | Wrappers.lambdaQuery(MallCountryDelivery.class) |
| | | .eq(MallCountryDelivery::getCountryCode, countryCode.toUpperCase()) |
| | | .eq(MallCountryDelivery::getStatus, 1) |
| | | ); |
| | | |
| | | if (delivery == null) { |
| | | |
| | | MallCountryDelivery defaultDelivery = mallCountryDeliveryMapper.selectOne( |
| | | Wrappers.lambdaQuery(MallCountryDelivery.class) |
| | | .eq(MallCountryDelivery::getCountryCode, "DEFAULT") |
| | | .eq(MallCountryDelivery::getStatus, 1) |
| | | ); |
| | | // 没有配置则返回默认运费 0(可根据业务调整) |
| | | return new FebsResponse().success().data(defaultDelivery.getShippingFee()); |
| | | } |
| | | |
| | | return new FebsResponse().success().data(delivery.getShippingFee()); |
| | | } |
| | | } |
| | |
| | | @ApiModelProperty(value = "Country/Region") |
| | | private String country; |
| | | |
| | | |
| | | private String countryName; |
| | | |
| | | /** |
| | | * 经度 |
| | | */ |
| | |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.util.Date; |
| | | import java.util.Map; |
| | | import java.util.TreeMap; |
| | |
| | | /** LWPAY 配置字典 type */ |
| | | private static final String DICT_TYPE = "LWPAY_CONFIG"; |
| | | /** LWPAY API 基础地址 */ |
| | | private static final String LWPAY_BASE_URL = "https://www.lwpay.com"; |
| | | private static final String LWPAY_BASE_URL = "https://lwpay.live"; |
| | | |
| | | /** |
| | | * 参与签名的字段白名单 |
| | | * 签名只包含这 7 个业务必传字段,pay_productname / pay_attach / pay_md5sign 不参与签名 |
| | | */ |
| | | private static final String[] SIGN_FIELD_KEYS = { |
| | | "pay_memberid", "pay_orderid", "pay_applydate", |
| | | "pay_bankcode", "pay_notifyurl", "pay_callbackurl", "pay_amount" |
| | | }; |
| | | |
| | | // ==================== 代收接口 ==================== |
| | | |
| | |
| | | params.put("pay_bankcode", bankCode); |
| | | params.put("pay_notifyurl", getNotifyUrl()); |
| | | params.put("pay_callbackurl", getReturnUrl()); |
| | | params.put("pay_amount", order.getAmount().toPlainString()); |
| | | params.put("pay_amount", getBRLAmount(order.getAmount())); |
| | | params.put("pay_productname", "商品订单-" + order.getOrderNo()); |
| | | |
| | | // 通道 968 需要 network 参数 |
| | |
| | | params.put("pay_attach", "network:" + network); |
| | | } |
| | | |
| | | // 生成签名 |
| | | String sign = generateSign(params, secretKey); |
| | | // 签名:仅使用白名单中的 7 个业务必传字段 |
| | | TreeMap<String, String> signParams = new TreeMap<>(); |
| | | for (String key : SIGN_FIELD_KEYS) { |
| | | String val = params.get(key); |
| | | if (StrUtil.isNotBlank(val)) { |
| | | signParams.put(key, val); |
| | | } |
| | | } |
| | | String sign = generateSign(signParams, secretKey); |
| | | params.put("pay_md5sign", sign); |
| | | |
| | | log.info("LWPAY 代收请求: memberId={}, orderNo={}, amount={}, bankCode={}", |
| | |
| | | } |
| | | |
| | | return json.getString("payurl"); |
| | | } |
| | | |
| | | private String getBRLAmount(BigDecimal amount){ |
| | | DataDictionaryCustom dataDictionaryCustom = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( |
| | | "MONEY_CHANGE", |
| | | "BRL" |
| | | ); |
| | | BigDecimal rate = new BigDecimal("5.18"); |
| | | if (dataDictionaryCustom != null){ |
| | | rate = new BigDecimal(dataDictionaryCustom.getValue()); |
| | | } |
| | | |
| | | return amount.multiply( rate).setScale(2, RoundingMode.DOWN).toString(); |
| | | } |
| | | |
| | | // ==================== 回调处理 ==================== |
| | |
| | | */ |
| | | public String generateSign(TreeMap<String, String> params, String secretKey) { |
| | | String signStr = buildSignString(params) + "&key=" + secretKey; |
| | | log.debug("LWPAY 待签名字符串: {}", signStr); |
| | | log.info("LWPAY 待签名字符串: {}", signStr); |
| | | return SecureUtil.md5(signStr).toUpperCase(); |
| | | } |
| | | |
| | |
| | | datasource: |
| | | # 数据源-1,名称为 base |
| | | base: |
| | | username: db_e2 |
| | | password: db_e20806123!@# |
| | | # username: db_e2 |
| | | # password: db_e20806123!@# |
| | | # driver-class-name: com.mysql.cj.jdbc.Driver |
| | | # url: jdbc:mysql://120.27.238.55:3406/db_e2?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8 |
| | | username: root |
| | | password: 1!qaz2@WSX |
| | | driver-class-name: com.mysql.cj.jdbc.Driver |
| | | url: jdbc:mysql://120.27.238.55:3406/db_e2?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8 |
| | | url: jdbc:mysql://159.198.39.140:3306/db_e2?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8 |
| | | |
| | | redis: |
| | | # Redis数据库索引(默认为 0) |
| New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="cc.mrbird.febs.mall.mapper.MallCountryDeliveryMapper"> |
| | | |
| | | <resultMap id="BaseResultMap" type="cc.mrbird.febs.mall.entity.MallCountryDelivery"> |
| | | <id column="ID" jdbcType="BIGINT" property="id"/> |
| | | <result column="REVISION" jdbcType="INTEGER" property="revision"/> |
| | | <result column="CREATED_BY" jdbcType="VARCHAR" property="createdBy"/> |
| | | <result column="CREATED_TIME" jdbcType="TIMESTAMP" property="createdTime"/> |
| | | <result column="UPDATED_BY" jdbcType="VARCHAR" property="updatedBy"/> |
| | | <result column="UPDATED_TIME" jdbcType="TIMESTAMP" property="updatedTime"/> |
| | | <result column="COUNTRY_CODE" jdbcType="VARCHAR" property="countryCode"/> |
| | | <result column="COUNTRY_NAME" jdbcType="VARCHAR" property="countryName"/> |
| | | <result column="SHIPPING_FEE" jdbcType="DECIMAL" property="shippingFee"/> |
| | | <result column="STATUS" jdbcType="INTEGER" property="status"/> |
| | | <result column="REMARK" jdbcType="VARCHAR" property="remark"/> |
| | | </resultMap> |
| | | |
| | | |
| | | |
| | | <select id="getCountryDeliveryListInPage" resultType="cc.mrbird.febs.mall.entity.MallCountryDelivery"> |
| | | SELECT |
| | | a.* |
| | | FROM mall_country_delivery a |
| | | order by a.CREATED_TIME desc |
| | | </select> |
| | | |
| | | </mapper> |
| New file |
| | |
| | | <div class="layui-fluid layui-anim febs-anim" id="country-delivery-list" lay-title="国家运费设置"> |
| | | <div class="layui-row febs-container"> |
| | | <div class="layui-col-md12"> |
| | | <div class="layui-card"> |
| | | <div class="layui-card-body febs-table-full"> |
| | | <form class="layui-form layui-table-form" lay-filter="country-delivery-table-form"> |
| | | <div class="layui-row"> |
| | | <div class="layui-col-md10"> |
| | | <div class="layui-form-item"> |
| | | <button class="layui-btn layui-btn-normal" type="button" id="add-btn"> |
| | | <i class="layui-icon"></i> 新增 |
| | | </button> |
| | | </div> |
| | | </div> |
| | | <div class="layui-col-md2 layui-col-sm12 layui-col-xs12 table-action-area"> |
| | | <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-green-plain table-action" id="reset"> |
| | | <i class="layui-icon"></i> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </form> |
| | | <table lay-filter="countryDeliveryTable" lay-data="{id: 'countryDeliveryTable'}"></table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <!-- 表格操作栏 --> |
| | | <script type="text/html" id="country-delivery-option"> |
| | | <a lay-event="edit"><i class="layui-icon febs-edit-area febs-blue"></i></a> |
| | | <a lay-event="del"><i class="layui-icon febs-edit-area febs-red"></i></a> |
| | | </script> |
| | | <style> |
| | | .layui-form-label { width: 120px; } |
| | | .layui-form-item .layui-input-block { margin-left: 150px; } |
| | | </style> |
| | | <script data-th-inline="none" type="text/javascript"> |
| | | layui.use(['jquery', 'form', 'table', 'febs'], function () { |
| | | var $ = layui.jquery, |
| | | febs = layui.febs, |
| | | form = layui.form, |
| | | table = layui.table, |
| | | layer = layui.layer, |
| | | $view = $('#country-delivery-list'), |
| | | $reset = $view.find('#reset'), |
| | | $addBtn = $view.find('#add-btn'), |
| | | tableIns; |
| | | |
| | | form.render(); |
| | | initTable(); |
| | | |
| | | // 表格操作 |
| | | table.on('tool(countryDeliveryTable)', function (obj) { |
| | | var data = obj.data, |
| | | layEvent = obj.event; |
| | | if (layEvent === 'edit') { |
| | | openEditModal(data); |
| | | } else if (layEvent === 'del') { |
| | | layer.confirm('确定删除该国家的运费配置吗?', function (index) { |
| | | febs.get(ctx + 'admin/system/countryDeliveryDelete/' + data.id, {}, function () { |
| | | layer.close(index); |
| | | febs.alert.success('删除成功'); |
| | | tableIns.reload(); |
| | | }); |
| | | }); |
| | | } |
| | | }); |
| | | |
| | | // 新增按钮 |
| | | $addBtn.on('click', function () { |
| | | openEditModal(null); |
| | | }); |
| | | |
| | | // 刷新按钮 |
| | | $reset.on('click', function () { |
| | | tableIns.reload(); |
| | | }); |
| | | |
| | | // 初始化表格 |
| | | function initTable() { |
| | | tableIns = febs.table.init({ |
| | | elem: $view.find('table'), |
| | | id: 'countryDeliveryTable', |
| | | url: ctx + 'admin/system/countryDeliveryList', |
| | | cols: [[ |
| | | {field: 'countryCode', title: '国家编码', width: 120, align: 'center'}, |
| | | {field: 'countryName', title: '国家名称', width: 150, align: 'center'}, |
| | | {field: 'shippingFee', title: '运费($)', width: 120, align: 'center'}, |
| | | {field: 'status', title: '状态', width: 100, align: 'center', |
| | | templet: function (d) { |
| | | return d.status === 1 |
| | | ? '<span style="color:#5FB878;">● 启用</span>' |
| | | : '<span style="color:#999;">● 禁用</span>'; |
| | | } |
| | | }, |
| | | {title: '操作', templet: '#country-delivery-option', width: 120, align: 'center'}, |
| | | {field: 'remark', title: '备注', minWidth: 100, align: 'center'}, |
| | | ]] |
| | | }); |
| | | } |
| | | |
| | | // 打开编辑弹窗 |
| | | function openEditModal(data) { |
| | | var title = data ? '编辑国家运费' : '新增国家运费'; |
| | | var html = '<div style="padding:20px 25px 0 0;">' + |
| | | '<form class="layui-form" lay-filter="country-delivery-form">' + |
| | | (data ? '<div class="layui-form-item febs-hide"><label class="layui-form-label">ID</label><div class="layui-input-block"><input type="text" name="id" value="' + data.id + '"></div></div>' : '') + |
| | | ' <div class="layui-form-item">' + |
| | | ' <label class="layui-form-label febs-form-item-require">国家编码</label>' + |
| | | ' <div class="layui-input-block">' + |
| | | ' <input type="text" name="countryCode" class="layui-input" ' + (data ? 'value="' + data.countryCode + '"' : 'placeholder="如 CN, US, JP"') + ' lay-verify="required">' + |
| | | ' <div class="layui-form-mid layui-word-aux">ISO国家编码,如CN/US/JP</div>' + |
| | | ' </div>' + |
| | | ' </div>' + |
| | | ' <div class="layui-form-item">' + |
| | | ' <label class="layui-form-label febs-form-item-require">国家名称</label>' + |
| | | ' <div class="layui-input-block">' + |
| | | ' <input type="text" name="countryName" class="layui-input" ' + (data ? 'value="' + (data.countryName || '') + '"' : 'placeholder="中文名称"') + ' lay-verify="required">' + |
| | | ' </div>' + |
| | | ' </div>' + |
| | | ' <div class="layui-form-item">' + |
| | | ' <label class="layui-form-label febs-form-item-require">运费($)</label>' + |
| | | ' <div class="layui-input-block">' + |
| | | ' <input type="number" name="shippingFee" class="layui-input" ' + (data ? 'value="' + data.shippingFee + '"' : 'placeholder="运费金额"') + ' lay-verify="required|number">' + |
| | | ' </div>' + |
| | | ' </div>' + |
| | | ' <div class="layui-form-item">' + |
| | | ' <label class="layui-form-label">状态</label>' + |
| | | ' <div class="layui-input-block">' + |
| | | ' <input type="radio" name="status" value="1" title="启用" ' + (!data || data.status === 1 ? 'checked' : '') + '>' + |
| | | ' <input type="radio" name="status" value="0" title="禁用" ' + (data && data.status === 0 ? 'checked' : '') + '>' + |
| | | ' </div>' + |
| | | ' </div>' + |
| | | ' <div class="layui-form-item">' + |
| | | ' <label class="layui-form-label">备注</label>' + |
| | | ' <div class="layui-input-block">' + |
| | | ' <input type="text" name="remark" class="layui-input" ' + (data && data.remark ? 'value="' + data.remark + '"' : '') + '>' + |
| | | ' </div>' + |
| | | ' </div>' + |
| | | '</form></div>'; |
| | | |
| | | var layerIndex = layer.open({ |
| | | type: 1, |
| | | title: title, |
| | | area: ['500px', '420px'], |
| | | content: html, |
| | | success: function (layero) { |
| | | form.render('radio', 'country-delivery-form'); |
| | | }, |
| | | btn: ['保存', '取消'], |
| | | yes: function (index, layero) { |
| | | var formObj = $(layero).find('form'); |
| | | var data = form.val("country-delivery-form"); |
| | | febs.post(ctx + 'admin/system/countryDeliverySave', data, function (res) { |
| | | layer.close(index); |
| | | febs.alert.success('保存成功'); |
| | | tableIns.reload(); |
| | | }); |
| | | }, |
| | | btn2: function () { |
| | | layer.closeAll(); |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | </script> |
| New file |
| | |
| | | <div class="layui-fluid layui-anim febs-anim" id="money-change-list" lay-title="汇率设置"> |
| | | <div class="layui-row febs-container"> |
| | | <div class="layui-col-md12"> |
| | | <div class="layui-card"> |
| | | <div class="layui-card-body febs-table-full"> |
| | | <form class="layui-form layui-table-form" lay-filter="money-change-table-form"> |
| | | <div class="layui-row"> |
| | | <div class="layui-col-md10"> |
| | | <div class="layui-form-item"> |
| | | <button class="layui-btn layui-btn-normal" type="button" id="add-btn"> |
| | | <i class="layui-icon"></i> 新增 |
| | | </button> |
| | | </div> |
| | | </div> |
| | | <div class="layui-col-md2 layui-col-sm12 layui-col-xs12 table-action-area"> |
| | | <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-green-plain table-action" id="reset"> |
| | | <i class="layui-icon"></i> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </form> |
| | | <table lay-filter="moneyChangeTable" lay-data="{id: 'moneyChangeTable'}"></table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <!-- 表格操作栏 --> |
| | | <script type="text/html" id="money-change-option"> |
| | | <a lay-event="edit"><i class="layui-icon febs-edit-area febs-blue"></i></a> |
| | | <a lay-event="del"><i class="layui-icon febs-edit-area febs-red"></i></a> |
| | | </script> |
| | | <style> |
| | | .layui-form-label { width: 120px; } |
| | | .layui-form-item .layui-input-block { margin-left: 150px; } |
| | | </style> |
| | | <script data-th-inline="none" type="text/javascript"> |
| | | layui.use(['jquery', 'form', 'table', 'febs'], function () { |
| | | var $ = layui.jquery, |
| | | febs = layui.febs, |
| | | form = layui.form, |
| | | table = layui.table, |
| | | layer = layui.layer, |
| | | $view = $('#money-change-list'), |
| | | $reset = $view.find('#reset'), |
| | | $addBtn = $view.find('#add-btn'), |
| | | tableIns; |
| | | |
| | | form.render(); |
| | | initTable(); |
| | | |
| | | // 表格操作 |
| | | table.on('tool(moneyChangeTable)', function (obj) { |
| | | var data = obj.data, |
| | | layEvent = obj.event; |
| | | if (layEvent === 'edit') { |
| | | openEditModal(data); |
| | | } else if (layEvent === 'del') { |
| | | layer.confirm('确定删除 ' + data.code + ' 的汇率配置吗?', function (index) { |
| | | febs.get(ctx + 'admin/system/moneyChangeDelete/' + data.id, {}, function () { |
| | | layer.close(index); |
| | | febs.alert.success('删除成功'); |
| | | tableIns.reload(); |
| | | }); |
| | | }); |
| | | } |
| | | }); |
| | | |
| | | // 新增按钮 |
| | | $addBtn.on('click', function () { |
| | | openEditModal(null); |
| | | }); |
| | | |
| | | // 刷新按钮 |
| | | $reset.on('click', function () { |
| | | tableIns.reload(); |
| | | }); |
| | | |
| | | // 初始化表格 |
| | | function initTable() { |
| | | tableIns = febs.table.init({ |
| | | elem: $view.find('table'), |
| | | id: 'moneyChangeTable', |
| | | url: ctx + 'admin/system/moneyChangeList', |
| | | cols: [[ |
| | | {field: 'code', title: '货币编码', width: 120, align: 'center'}, |
| | | {field: 'value', title: '汇率', width: 120, align: 'center'}, |
| | | {field: 'description', title: '符号', width: 80, align: 'center'}, |
| | | {title: '操作', templet: '#money-change-option', width: 120, align: 'center'} |
| | | ]] |
| | | }); |
| | | } |
| | | |
| | | // 打开编辑弹窗 |
| | | function openEditModal(data) { |
| | | var title = data ? '编辑汇率' : '新增汇率'; |
| | | var html = '<div style="padding:20px 25px 0 0;">' + |
| | | '<form class="layui-form" lay-filter="money-change-form">' + |
| | | (data ? '<div class="layui-form-item febs-hide"><label class="layui-form-label">ID</label><div class="layui-input-block"><input type="text" name="id" value="' + data.id + '"></div></div>' : '') + |
| | | ' <div class="layui-form-item">' + |
| | | ' <label class="layui-form-label febs-form-item-require">货币编码</label>' + |
| | | ' <div class="layui-input-block">' + |
| | | ' <input type="text" name="code" class="layui-input" ' + (data ? 'value="' + data.code + '"' : 'placeholder="如 USD, CNY, EUR"') + ' lay-verify="required">' + |
| | | ' <div class="layui-form-mid layui-word-aux">ISO货币编码,如USD/CNY/EUR</div>' + |
| | | ' </div>' + |
| | | ' </div>' + |
| | | ' <div class="layui-form-item">' + |
| | | ' <label class="layui-form-label febs-form-item-require">汇率</label>' + |
| | | ' <div class="layui-input-block">' + |
| | | ' <input type="text" name="value" class="layui-input" ' + (data ? 'value="' + data.value + '"' : 'placeholder="汇率数值"') + ' lay-verify="required|number">' + |
| | | ' </div>' + |
| | | ' </div>' + |
| | | ' <div class="layui-form-item">' + |
| | | ' <label class="layui-form-label febs-form-item-require">符号</label>' + |
| | | ' <div class="layui-input-block">' + |
| | | ' <input type="text" name="description" class="layui-input" ' + (data && data.description ? 'value="' + data.description + '"' : 'placeholder="$"') + ' lay-verify="required">' + |
| | | ' <div class="layui-form-mid layui-word-aux">货币符号,如 $ ¥ € £</div>' + |
| | | ' </div>' + |
| | | ' </div>' + |
| | | '</form></div>'; |
| | | |
| | | layer.open({ |
| | | type: 1, |
| | | title: title, |
| | | area: ['500px', '350px'], |
| | | content: html, |
| | | success: function (layero) { |
| | | form.render(null, 'money-change-form'); |
| | | }, |
| | | btn: ['保存', '取消'], |
| | | yes: function (index, layero) { |
| | | var formObj = $(layero).find('form'); |
| | | var formData = form.val("money-change-form"); |
| | | febs.post(ctx + 'admin/system/moneyChangeSave', formData, function (res) { |
| | | layer.close(index); |
| | | febs.alert.success('保存成功'); |
| | | tableIns.reload(); |
| | | }); |
| | | }, |
| | | btn2: function () { |
| | | layer.closeAll(); |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | </script> |