微信支付、福利

This commit is contained in:
Paidax
2025-03-10 09:40:09 +08:00
parent d5a8dd7534
commit 0d3bafb328
46 changed files with 2489 additions and 1435 deletions
+7 -1
View File
@@ -36,7 +36,7 @@
<jsoup.veision>1.12.1</jsoup.veision> <jsoup.veision>1.12.1</jsoup.veision>
<poitl.version>1.9.1</poitl.version> <poitl.version>1.9.1</poitl.version>
<easypoi.version>4.2.0</easypoi.version> <easypoi.version>4.2.0</easypoi.version>
<jetty.version>9.4.47.v20220610</jetty.version> <jetty.version>9.4.56.v20240826</jetty.version>
</properties> </properties>
<url>https://budwk.com</url> <url>https://budwk.com</url>
@@ -53,6 +53,12 @@
<dependencies> <dependencies>
<dependency>
<groupId>com.github.javen205</groupId>
<artifactId>IJPay-All</artifactId>
<version>2.9.10</version>
</dependency>
<dependency> <dependency>
<groupId>com.xingyuv</groupId> <groupId>com.xingyuv</groupId>
<artifactId>captcha-plus</artifactId> <artifactId>captcha-plus</artifactId>
@@ -1,10 +1,9 @@
package io.v.nutz.zhgh.memberCost.controller.payment; package io.v.nutz.zhgh.memberCost.controller;
import io.v.nutz.base.annontation.ViReturn; import io.v.nutz.base.annontation.ViReturn;
import io.v.nutz.base.dao.CndPlus; import io.v.nutz.base.dao.CndPlus;
import io.v.nutz.base.query.PageForm; import io.v.nutz.base.query.PageForm;
import io.v.nutz.zhgh.memberCost.model.MemberPaymentConfig; import io.v.nutz.zhgh.memberCost.model.MemberPaymentConfig;
import io.v.nutz.zhgh.memberCost.model.MemberPaymentProject;
import io.v.nutz.zhgh.memberCost.service.MemberPaymentService; import io.v.nutz.zhgh.memberCost.service.MemberPaymentService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.authz.annotation.RequiresPermissions;
@@ -30,7 +29,7 @@ public class MemberPaymentConfigController {
private MemberPaymentService memberPaymentService; private MemberPaymentService memberPaymentService;
@At("") @At("")
@Ok("beetl:/platform/memberCost/payment/config.html") @Ok("beetl:/platform/membercost/config.html")
@RequiresPermissions("member.payment.config") @RequiresPermissions("member.payment.config")
public void index() {} public void index() {}
@@ -0,0 +1,40 @@
package io.v.nutz.zhgh.memberCost.controller;
import io.v.nutz.zhgh.memberCost.payment.wxpay.service.WxPayCommonService;
import io.v.nutz.zhgh.memberCost.service.MemberPaymentService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
/**
* @version 1.0
* @Author zzr
* @name:MemberPaymentMineController
* @Date 2025/3/10 8:44
* @注释 我的缴费列表
*/
@Slf4j
@IocBean
@Ok("json:full")
@At("/platform/member/payment/mine")
public class MemberPaymentMineController {
@Inject
private WxPayCommonService wxPayCommonService;
@Inject
private MemberPaymentService memberPaymentService;
@At("")
@Ok("beetl:/platform/membercost/mine/index.html")
@RequiresPermissions("member.payment.project")
public void index() {
}
public Object pageData(){
return null;
}
}
@@ -1,4 +1,4 @@
package io.v.nutz.zhgh.memberCost.controller.payment; package io.v.nutz.zhgh.memberCost.controller;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateTime;
@@ -30,7 +30,6 @@ import org.nutz.mvc.annotation.Param;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
@@ -50,7 +49,7 @@ public class MemberPaymentProjectController {
private MemberPaymentService memberPaymentService; private MemberPaymentService memberPaymentService;
@At("") @At("")
@Ok("beetl:/platform/memberCost/payment/project.html") @Ok("beetl:/platform/membercost/project.html")
@RequiresPermissions("member.payment.project") @RequiresPermissions("member.payment.project")
public void index() { public void index() {
} }
@@ -1,4 +1,4 @@
package io.v.nutz.zhgh.memberCost.controller.payment; package io.v.nutz.zhgh.memberCost.controller;
import cn.afterturn.easypoi.excel.ExcelExportUtil; import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil; import cn.afterturn.easypoi.excel.ExcelImportUtil;
@@ -66,7 +66,7 @@ public class MemberPaymentSummaryController {
private MsgApi msgApi; private MsgApi msgApi;
@At("") @At("")
@Ok("beetl:/platform/memberCost/payment/summary.html") @Ok("beetl:/platform/membercost/summary.html")
@RequiresPermissions("member.payment.summary") @RequiresPermissions("member.payment.summary")
public void index() { public void index() {
} }
@@ -1,4 +1,4 @@
package io.v.nutz.zhgh.memberCost.controller.payment; package io.v.nutz.zhgh.memberCost.controller;
import io.v.nutz.base.annontation.ViReturn; import io.v.nutz.base.annontation.ViReturn;
@@ -6,28 +6,19 @@ import io.v.nutz.base.dao.CndPlus;
import io.v.nutz.base.query.PageForm; import io.v.nutz.base.query.PageForm;
import io.v.nutz.web.commons.utils.ShiroUtil; import io.v.nutz.web.commons.utils.ShiroUtil;
import io.v.nutz.zhgh.memberCost.model.MemberPaymentInfo; import io.v.nutz.zhgh.memberCost.model.MemberPaymentInfo;
import io.v.nutz.zhgh.memberCost.model.MemberPaymentProject;
import io.v.nutz.zhgh.memberCost.service.MemberPaymentService; import io.v.nutz.zhgh.memberCost.service.MemberPaymentService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd; import org.nutz.dao.Cnd;
import org.nutz.dao.Sqls; import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql; import org.nutz.dao.sql.Sql;
import org.nutz.dao.util.cri.Static;
import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings; import org.nutz.lang.Strings;
import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok; import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param; import org.nutz.mvc.annotation.Param;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
/** /**
* 个人缴费管理 * 个人缴费管理
* @author hpf * @author hpf
@@ -42,7 +33,7 @@ public class MemberPaymentUserController {
private MemberPaymentService memberPaymentService; private MemberPaymentService memberPaymentService;
@At("") @At("")
@Ok("beetl:/platform/memberCost/payment/user.html") @Ok("beetl:/platform/membercost/user.html")
@RequiresPermissions("member.payment.user") @RequiresPermissions("member.payment.user")
public void index() { public void index() {
} }
@@ -51,23 +42,26 @@ public class MemberPaymentUserController {
@ViReturn @ViReturn
@RequiresPermissions("member.payment.user") @RequiresPermissions("member.payment.user")
public Object pageData(PageForm pageForm,@Param(value = "year", required = false) String year,@Param(value = "projectName", required = false) String projectName){ public Object pageData(PageForm pageForm,@Param(value = "year", required = false) String year,@Param(value = "projectName", required = false) String projectName){
Sql sql = Sqls.create("SELECT" + Sql sql = Sqls.create("""
" mpi.*," + SELECT
" mpp.`year`," + mpi.*,
" mpp.projectName," + mpp.`year`,
" mpp.startTime," + mpp.projectName,
" mpp.endTime," + mpp.startTime,
" mpp.configId," + mpp.endTime,
" mpc.payStandards," + mpp.configId,
" mpc.paymentStartMonth," + mpc.payStandards,
" mpc.paymentEndMonth" + mpc.paymentStartMonth,
" FROM" + mpc.paymentEndMonth
" member_payment_info mpi" + FROM
" LEFT JOIN member_payment_project mpp ON mpi.paymentProjectId = mpp.id " + member_payment_info mpi
" LEFT JOIN member_payment_config mpc ON mpc.id = mpp.configId $condition"); LEFT JOIN member_payment_project mpp ON mpi.paymentProjectId = mpp.id
LEFT JOIN member_payment_config mpc ON mpc.id = mpp.configId
$condition
""");
CndPlus cnd = CndPlus.create(); CndPlus cnd = CndPlus.create();
cnd.andEX("mpp.isDisabled", "=", '0'); cnd.andEX("mpp.isDisabled", "=", false);
cnd.andEX("mpp.year", "=", year); cnd.andEX("mpp.year", "=", year);
cnd.and("mpi.userId", "=", ShiroUtil.getUserId()); cnd.and("mpi.userId", "=", ShiroUtil.getUserId());
if (Strings.isNotBlank(projectName)) { if (Strings.isNotBlank(projectName)) {
@@ -1,4 +1,4 @@
package io.v.nutz.zhgh.memberCost.controller.mobile; package io.v.nutz.zhgh.memberCost.h5controller;
import io.v.nutz.base.annontation.ViReturn; import io.v.nutz.base.annontation.ViReturn;
import io.v.nutz.web.commons.utils.ShiroUtil; import io.v.nutz.web.commons.utils.ShiroUtil;
@@ -1,6 +1,6 @@
package io.v.nutz.zhgh.memberCost.controller; package io.v.nutz.zhgh.memberCost.payment.alipay.controller;
import io.v.nutz.zhgh.memberCost.service.AlipayService; import io.v.nutz.zhgh.memberCost.payment.alipay.service.AlipayService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.ioc.loader.annotation.IocBean;
@@ -1,4 +1,4 @@
package io.v.nutz.zhgh.memberCost.controller; package io.v.nutz.zhgh.memberCost.payment.alipay.service;
/** /**
* @ClassName AlipayClientConfig * @ClassName AlipayClientConfig
@@ -1,4 +1,4 @@
package io.v.nutz.zhgh.memberCost.service; package io.v.nutz.zhgh.memberCost.payment.alipay.service;
import io.v.nutz.base.service.ViService; import io.v.nutz.base.service.ViService;
@@ -1,4 +1,4 @@
package io.v.nutz.zhgh.memberCost.service.impl; package io.v.nutz.zhgh.memberCost.payment.alipay.service.impl;
import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayConstants; import com.alipay.api.AlipayConstants;
@@ -9,9 +9,9 @@ import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradeWapPayResponse; import com.alipay.api.response.AlipayTradeWapPayResponse;
import io.v.nutz.base.service.impl.ViServiceImpl; import io.v.nutz.base.service.impl.ViServiceImpl;
import io.v.nutz.web.commons.utils.ShiroUtil; import io.v.nutz.web.commons.utils.ShiroUtil;
import io.v.nutz.zhgh.memberCost.controller.AlipayClientConfig; import io.v.nutz.zhgh.memberCost.payment.alipay.service.AlipayClientConfig;
import io.v.nutz.zhgh.memberCost.model.MemberPaymentInfo; import io.v.nutz.zhgh.memberCost.model.MemberPaymentInfo;
import io.v.nutz.zhgh.memberCost.service.AlipayService; import io.v.nutz.zhgh.memberCost.payment.alipay.service.AlipayService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.nutz.dao.Chain; import org.nutz.dao.Chain;
import org.nutz.dao.Cnd; import org.nutz.dao.Cnd;
@@ -0,0 +1,22 @@
package io.v.nutz.zhgh.memberCost.payment.enums;
import io.v.nutz.base.annontation.SelectEnum;
/**
* 退款状态枚举
*/
@Getter
@SelectEnum
@AllArgsConstructor
public enum RefundStateEnum {
INITIATE_REFUND("发起退款"),
REFUNDING("退款中"),
REFUND_SUCCESS("退款成功"),
REFUND_FAILED("退款失败");
/**
* 避免和枚举类的name冲突
*/
public final String refundStateName;
}
@@ -0,0 +1,23 @@
package io.v.nutz.zhgh.memberCost.payment.enums;
import io.v.nutz.base.annontation.SelectEnum;
/**
* 交易渠道枚举
*/
@Getter
@SelectEnum
@AllArgsConstructor
public enum TradingChannelEnum {
QQ_PAY("QQ"),
WX_PAY("微信"),
JD_PAY("京东"),
ALI_PAY("支付宝"),
UNION_PAY("云闪付");
/**
* 避免和枚举类的name冲突
*/
public final String trdingChannelName;
}
@@ -0,0 +1,22 @@
package io.v.nutz.zhgh.memberCost.payment.enums;
import io.v.nutz.base.annontation.SelectEnum;
/**
* 支付状态枚举
*/
@Getter
@SelectEnum
@AllArgsConstructor
public enum TradingStateEnum {
WAITING_FOR_PAYMENT("等待支付"),
PAY_SUCCESS("支付成功"),
CANCEL_PAYMENT("取消支付");
/**
* 避免和枚举类的name冲突
*/
public final String trdingStateName;
}
@@ -0,0 +1,20 @@
package io.v.nutz.zhgh.memberCost.payment.enums;
import io.v.nutz.base.annontation.SelectEnum;
/**
* 交易类型枚举
*/
@Getter
@SelectEnum
@AllArgsConstructor
public enum TradingTypeEnum {
PAYMENT("付款"),
REFUND("退款");
/**
* 避免和枚举类的name冲突
*/
public final String trdingTypeName;
}
@@ -0,0 +1,107 @@
package io.v.nutz.zhgh.memberCost.payment.model;
import io.v.nutz.base.model.BaseModel;
import java.math.BigDecimal;
/**
* 交易单表
*/
@Data
@Table
@Comment("交易订单表")
@EqualsAndHashCode(callSuper = true)
public class PaymentTransaction extends BaseModel {
@Column
@Name
@Comment("ID")
@ColDefine(type = ColType.VARCHAR, width = 32)
@PrevInsert(uu32 = true)
private String id;
@Column
@Comment("商户号")
@ColDefine(type = ColType.VARCHAR,width = 128)
private String mchId;
@Column
@Comment("订单号,传递给交易系统,交易系统订单号")
@ColDefine(type = ColType.VARCHAR,width = 128)
private String outTradeNo;
@Column
@Comment("交易系统交易号")
@ColDefine(type = ColType.VARCHAR,width = 128)
private String tradingOrderNo;
@Column
@Comment("交易渠道")
@ColDefine(type = ColType.VARCHAR,width = 50)
private String tradingChannel;
@Column
@Comment("交易类型")
@ColDefine(type = ColType.VARCHAR,width = 30)
private String tradingType;
@Column
@Comment("用户ID")
@ColDefine(type = ColType.VARCHAR,width = 32)
private String userId;
@Column
@Comment("用户工号")
@ColDefine(type = ColType.VARCHAR,width = 50)
private String loginName;
@Column
@Comment("用户姓名")
@ColDefine(type = ColType.VARCHAR,width = 50)
private String userName;
@Column
@Comment("用户工会")
@ColDefine(type = ColType.VARCHAR,width = 50)
private String unionName;
@Column
@Comment("用户单位")
@ColDefine(type = ColType.VARCHAR,width = 50)
private String unitName;
@Column
@Comment("交易金额")
@ColDefine(customType = "decimal")
private BigDecimal tradingAmount;
@Column
@Comment("是否退款")
@ColDefine(type = ColType.BOOLEAN)
private Boolean isRefund;
@Column
@Comment("退款金额")
@ColDefine(customType = "decimal")
private String refundAmount;
@Column
@Comment("订单描述")
@ColDefine(type = ColType.VARCHAR,width = 128)
private String description;
@Column
@Comment("附加详细描述")
@ColDefine(type = ColType.TEXT)
private String attach;
@Column
@Comment("微信支付用户openId")
@ColDefine(type = ColType.VARCHAR,width = 50)
private String openId;
@Column
@Comment("交易返回数据")
@ColDefine(type = ColType.MYSQL_JSON)
private String resultJson;
}
@@ -0,0 +1,57 @@
package io.v.nutz.zhgh.memberCost.payment.model;
import io.v.nutz.base.model.BaseModel;
import java.math.BigDecimal;
/**
* 退款记录表
*/
@Data
@Table
@Comment("退款记录表")
@EqualsAndHashCode(callSuper = true)
public class RefundRecord extends BaseModel {
@Column
@Name
@Comment("ID")
@ColDefine(type = ColType.VARCHAR, width = 32)
@PrevInsert(uu32 = true)
private String id;
@Column
@Comment("关联系统交易订单表Id")
@ColDefine(type = ColType.VARCHAR,width = 32)
private String paymentTransactionId;
@Column
@Comment("本次退款订单号")
@ColDefine(type = ColType.VARCHAR,width = 128)
private String outRefundTradeNo;
@Column
@Comment("第三方支付的退款单号")
@ColDefine(type = ColType.VARCHAR,width = 128)
private String refundNo;
@Column
@Comment("退款状态")
@ColDefine(type = ColType.VARCHAR,width = 30)
private String refundState;
@Column
@Comment("本次退款金额")
@ColDefine(customType = "decimal")
private BigDecimal refundAmount;
@Column
@Comment("原订单金额")
@ColDefine(customType = "decimal")
private BigDecimal total;
@Column
@Comment("交易返回数据")
@ColDefine(type = ColType.MYSQL_JSON)
private String resultJson;
}
@@ -0,0 +1,47 @@
package io.v.nutz.zhgh.memberCost.payment.wxpay.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @version 1.0
* @Author zzr
* @name:WxPayV3Bean
* @Date 2025/3/6 9:54
* @注释
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class WxPayV3Bean {
private String appId;
private String keyPath;
private String publicKeyPath;
private String certPath;
private String certP12Path;
private String platformCertPath;
private String mchId;
private String apiKey;
private String apiKey3;
private String domain;
private String publicKeyId;
@Override
public String toString() {
return "WxPayV3Bean{" +
"appId='" + appId + '\'' +
", keyPath='" + keyPath + '\'' +
", publicKeyPath='" + publicKeyPath + '\'' +
", certPath='" + certPath + '\'' +
", certP12Path='" + certP12Path + '\'' +
", platformCertPath='" + platformCertPath + '\'' +
", mchId='" + mchId + '\'' +
", apiKey='" + apiKey + '\'' +
", apiKey3='" + apiKey3 + '\'' +
", domain='" + domain + '\'' +
", publicKeyId='" + publicKeyId + '\'' +
'}';
}
}
@@ -0,0 +1,25 @@
-----BEGIN CERTIFICATE-----
MIIEKDCCAxCgAwIBAgIUONYpzvxVfV/RrWnLGPlL6/nb/AcwDQYJKoZIhvcNAQEL
BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT
FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg
Q0EwHhcNMjUwMzA2MTQwNDAzWhcNMzAwMzA1MTQwNDAzWjCBgTETMBEGA1UEAwwK
MTY2NjkzMDk4MDEbMBkGA1UECgwS5b6u5L+h5ZWG5oi357O757ufMS0wKwYDVQQL
DCTmrabmsYnlnLDlpKfkuInmgJ3np5HmioDmnInpmZDlhazlj7gxCzAJBgNVBAYT
AkNOMREwDwYDVQQHDAhTaGVuWmhlbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBALlDML+FJEW+m2hXp/qUH1cU6xlwFllLU4LjFusJkxwyzzcZO4nY0mOi
3woz8xIJipvUWj2Y413WYwMkfcJcRgghupZkfYwdQtSyPfUu7xQBUm8TLWGH88Re
kyyVABEB5T+ne6r3LesXS4IuZknm5N/iaa4z9mbbscGqF0GLvMUqZCRNyTkyfK9r
Bkvs/vspi+Jcjx9I7aU++h/vwzsGB6Bf/uB3kLMb+lj/i3xY20sdrrW8JD2sqONQ
NcRIKmNXSp4zsNy+d6kIKWE3P5609ZTta1ogkeGBNdGXMRNNy6vLIudQc7zny/9H
S4LxGsIrsYmZNhGljRng56X+PG3w1CUCAwEAAaOBuTCBtjAJBgNVHRMEAjAAMAsG
A1UdDwQEAwID+DCBmwYDVR0fBIGTMIGQMIGNoIGKoIGHhoGEaHR0cDovL2V2Y2Eu
aXRydXMuY29tLmNuL3B1YmxpYy9pdHJ1c2NybD9DQT0xQkQ0MjIwRTUwREJDMDRC
MDZBRDM5NzU0OTg0NkMwMUMzRThFQkQyJnNnPUhBQ0M0NzFCNjU0MjJFMTJCMjdB
OUQzM0E4N0FEMUNERjU5MjZFMTQwMzcxMA0GCSqGSIb3DQEBCwUAA4IBAQBQ5e8U
1pQ40gfRoZyO0s+QF16L8pAcVLVwHffo0mmJpIRB4bu8W5IJ9kKhksJ0CzZ0YEwB
Yv7/LTC1qpi7PE73nZ4Ytm9oZeH1Kk5KIlQS+2H3IwOpoV4wucMc34y6MVQJjC7E
u5OnglBPSAopwNP4p+Us9A3ah7Ks48XCw+LCEWpA/setJwo9C13Qq2AQm8qLpogK
pNBwm/oylxb8/kZK1lLPgcXd7geLDhl/Str+aOzBXyd7YSEMxS8zWiZhWozu6rCq
dg10QFKicPGDkDzNQwBz7cDXvlJXSWRDBK5r1li1YgX+QD5WJYPchATo5SlvF4Lr
5/V/dZzI7BJTinr1
-----END CERTIFICATE-----
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC5QzC/hSRFvpto
V6f6lB9XFOsZcBZZS1OC4xbrCZMcMs83GTuJ2NJjot8KM/MSCYqb1Fo9mONd1mMD
JH3CXEYIIbqWZH2MHULUsj31Lu8UAVJvEy1hh/PEXpMslQARAeU/p3uq9y3rF0uC
LmZJ5uTf4mmuM/Zm27HBqhdBi7zFKmQkTck5MnyvawZL7P77KYviXI8fSO2lPvof
78M7BgegX/7gd5CzG/pY/4t8WNtLHa61vCQ9rKjjUDXESCpjV0qeM7DcvnepCClh
Nz+etPWU7WtaIJHhgTXRlzETTcuryyLnUHO858v/R0uC8RrCK7GJmTYRpY0Z4Oel
/jxt8NQlAgMBAAECggEBAKGQqTi9Ii741Ysftsze1J4bDhS3HaZt/LyO0vPS+8qB
vRiuFrBWuNRPu/en6nl2fLz9al2Bsfep+dtJvar80c5Rq+lwZdUFx7y6XTIv5iwq
IvvfW5pM+Bfu6qbcopwybP0gUMd+nTsCq8UyNd6JUFy3lbZodqCpQ9JDRdjRxqSi
oMonve36Q9kJyDs0mS2F0w+Y9oYFtpE9WvGMBthwT7VfzWuDa+YC/Gh0RhT2V9OG
uDC8kxmfaIbk0IITDVFWVMMhScXiqmJL1II9yQWsCHH73dZS+dDxwwH0ObRD3kOx
hHptxpRzhtuNxLjCOZDGhneyvUHIftpqf4wdOgQ8iUECgYEA6TDo36s3XDFIs8SH
lpVYrhie0nmaNET50CtOc5C2M1OotrkMUrQTMoa4F263UloJfqweW9AKZX11wPp2
8h7af2sZsGawjuwv7mMthZJoi0fc5J2+z6BnVGgFo7uZbcs1Y/+B0tNrDKIHVrqb
Lywmh18iKDXrMiMDMRp8mtiNyU0CgYEAy2Im0oGb1rmAh9gPvQIENmNEgRsyIU4x
WPAFb5KO7jnseO9KrC9uiRSO5JuwZu/QNGlga2w77Gu7n+Q4HfSU2KFlNhR6pKjb
mqXzPq1quryzbtWay520VsRKz3F/Tfp1FUpIuZvj8x7FrL8z8vjbLkbW4p+Z7HE4
heYdmk2KCjkCgYBC6xU48pJtc3swk2pxjSQoucoCDoFxFIY39eWKhnGy4wQcg5gE
t8Z2jnCP0ObszAfDgTMpF9eT7l/3ZCj0LGR5gkuZ8q4iJadPmsh6d1xm89VxCc+z
F43vi/ZqWTCbcGA+9RjVXnRu6KSAgAZ+kAXyfRt5PJflCGUnFznA2fo+VQKBgG6s
n7Gno/UKBv5lPdM9mKs8A5g6A2KKWWIrYtnfJ/ZNAPiiRsFCImVoEYYnjqvFTkhn
G3f5cvZpfbU5jKwIX0MvOJNgO4kE9lPGgIKX/d9WNlJW3KB21h7tPER8X6lAZJxM
SxztzvKKyUkC1zMd5q/dDqxN64X16qs6mNtR3I9JAoGBAJbqQtg59Szi2m4jZ9Xo
0cKvP7+PSKgysdWsemTkU0ji1rcMpGRTtcUGRWlawLjRSInQS+xNdL6GVU5mHZWe
gNwXIXEpape4IJta0B1PYAhNcIvOSh5CzcUnVTeo6q0CTSVQPdsivlrObLKZ4uGQ
eewDw82Ej6YoSgczjf99ug0x
-----END PRIVATE KEY-----
@@ -0,0 +1,24 @@
-----BEGIN CERTIFICATE-----
MIIEFDCCAvygAwIBAgIUKN05Gm0Q9n9mLPPltUh8qjKKegQwDQYJKoZIhvcNAQEL
BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT
FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg
Q0EwHhcNMjUwMzA2MTQwNDAzWhcNMzAwMzA1MTQwNDAzWjBuMRgwFgYDVQQDDA9U
ZW5wYXkuY29tIHNpZ24xEzARBgNVBAoMClRlbnBheS5jb20xHTAbBgNVBAsMFFRl
bnBheS5jb20gQ0EgQ2VudGVyMQswCQYDVQQGEwJDTjERMA8GA1UEBwwIU2hlblpo
ZW4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDbMenF0GNlcUYErPpj
Aj+WOuzRFz+PJcrtgkI81S0WDh8flMtq1A2nwKARNyPXx+UPd9it657nH5G8E9kL
Ea5u5rENpn+JZc4cAIvZqazteSAUg2pfQH9ewW+/CxNOWarjXPNRYa0OjZWf+5F8
ZBOT/x8sJ2+jou9lxKNe1skha+jzmiQ8m3B2vPXqR87qgL/fyQjjpLvBGpvearh/
hxTMBEfGeB4F6Fu52Fz3/VCWe38ubxwj8EMcRSPp4xsl2BTaRVMMT525Hul2N49C
vXCSVsCNt3ND8UDffXnb19Zgpir4KqpECTbfqcT7YX+U34P1Av8gcDl6rRm+7Wpj
PY4RAgMBAAGjgbkwgbYwCQYDVR0TBAIwADALBgNVHQ8EBAMCA/gwgZsGA1UdHwSB
kzCBkDCBjaCBiqCBh4aBhGh0dHA6Ly9ldmNhLml0cnVzLmNvbS5jbi9wdWJsaWMv
aXRydXNjcmw/Q0E9MUJENDIyMEU1MERCQzA0QjA2QUQzOTc1NDk4NDZDMDFDM0U4
RUJEMiZzZz1IQUNDNDcxQjY1NDIyRTEyQjI3QTlEMzNBODdBRDFDREY1OTI2RTE0
MDM3MTANBgkqhkiG9w0BAQsFAAOCAQEAUAvXCx55ZGmd3ATi28W4mirnUHQb2RAw
X5/0OC2SkuBdzxI5RbY4YAuugP6nQIAU8TXCANzno2oqZ6vmFZ4dBnJmLewVFMoM
qp18A4RWmnsGnmEIgMm6N1kB+RbM11oLCLdy2KK0SvmqDmTBFJyjyUGqEmRshnV/
QfKn4UUzJ4suDFAolGX4DyDIOtM0D+SCHwwxGI4yf2+nj4IB8XgmmOeschxoSvu9
T3E6BgQ271YVDwg+3r9CiFVI5JdyftvQagOEQmZJMPINEKgFn5LzrZJW7mH42+N+
i4RFz04wpGUsrSFDESh3JxYSNhq/HulpMLinntWxEBHFhpkjyyGDGg==
-----END CERTIFICATE-----
@@ -0,0 +1,68 @@
package io.v.nutz.zhgh.memberCost.payment.wxpay.service;
import io.v.nutz.zhgh.memberCost.payment.wxpay.vo.WxPayNeedParamVo;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @version 1.0
* @Author zzr
* @name:WxPayCommonService
* @Date 2025/3/6 11:40
* @注释
*/
public interface WxPayCommonService {
/**
* 二维码统一下单,返回支付二维码链接
* @param paramVo 需要传递的信息,请自定义付款金额Amount 和 付款描述Description,其他关键信息请勿修改
* 注意Amount的总价total是int类型,会自动乘以0.01,例如传递100元,会自动转换为1元
* @return
*/
String nativePay(WxPayNeedParamVo paramVo);
/**
* JSAPI支付,返回支付参数
* @param paramVo 需要传递的信息,请自定义付款金额Amount 和 付款描述Description,其他关键信息请勿修改
* 注意Amount的总价total是int类型,会自动乘以0.01,例如传递100元,会自动转换为1元
* JsAPI支付,需要传递openId,请自行获取
* @return
*/
String jsApiPay(WxPayNeedParamVo paramVo);
/**
* WAP支付,返回支付参数
* @param paramVo 需要传递的信息,请自定义付款金额Amount 和 付款描述Description,其他关键信息请勿修改
* 注意Amount的总价total是int类型,会自动乘以0.01,例如传递100元,会自动转换为1元
* @return
*/
String wapPay(WxPayNeedParamVo paramVo);
/**
* 支付回调,验证是否支付成功
* @param request 请求
* @param response 响应
*/
void payNotify(HttpServletRequest request, HttpServletResponse response);
/**
* 退款
* @param transactionId 微信订单号
* @param outTradeNo 商户订单号
* @return
*/
String refund(String transactionId, String outTradeNo);
/**
* 退款回调
* @param request 请求
* @param response 响应
*/
void refundNotify(HttpServletRequest request, HttpServletResponse response);
}
@@ -0,0 +1,479 @@
package io.v.nutz.zhgh.memberCost.payment.wxpay.service.impl;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.ContentType;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ijpay.core.IJPayHttpResponse;
import com.ijpay.core.enums.AuthTypeEnum;
import com.ijpay.core.enums.RequestMethodEnum;
import com.ijpay.core.kit.AesUtil;
import com.ijpay.core.kit.HttpKit;
import com.ijpay.core.kit.PayKit;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.enums.WxDomainEnum;
import com.ijpay.wxpay.enums.v3.BasePayApiEnum;
import com.ijpay.wxpay.model.v3.*;
import io.v.nutz.zhgh.memberCost.payment.wxpay.bean.WxPayV3Bean;
import io.v.nutz.zhgh.memberCost.payment.wxpay.service.WxPayCommonService;
import io.v.nutz.zhgh.memberCost.payment.wxpay.vo.WxPayNeedParamVo;
import lombok.extern.slf4j.Slf4j;
import org.nutz.ioc.loader.annotation.IocBean;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.FileWriter;
import java.nio.charset.StandardCharsets;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @version 1.0
* @Author zzr
* @name:WxPayCommonServiceImpl
* @Date 2025/3/6 11:41
* @注释
*/
@Slf4j
@IocBean
public class WxPayCommonServiceImpl implements WxPayCommonService {
// 判断下单接口成功返回码
private final static int OK = 200;
// 微信V3必要的支付参数,后期优化
private final static WxPayV3Bean WX_PAY_V3_BEAN = new WxPayV3Bean(
"ww3eda050a1b5ad96e",
"src/main/java/io/v/nutz/zhgh/memberCost/wxpay/pem/apiclient_key.pem",
"src/main/java/io/v/nutz/zhgh/memberCost/wxpay/pem/apiclient_key.pem",
"src/main/java/io/v/nutz/zhgh/memberCost/wxpay/pem/apiclient_cert.pem",
"src/main/java/io/v/nutz/zhgh/memberCost/wxpay/pem/apiclient_cert.pem",
"src/main/java/io/v/nutz/zhgh/memberCost/wxpay/pem/wechatpay.pem",
"1666930980",
"",
"4ebd020883285d698c44ec50939c0967",
"https://schoolhd.top/platform",
"");
// 自定义参数,内容是统一的,但会被多次调用,直接声明
String serialNo;
String platSerialNo;
String payNotifyUrl = WX_PAY_V3_BEAN.getDomain().concat("/wxPay/notifyMessage");
/**
* 微信扫描二维码支付
* @param paramVo 需要传递的信息,请自定义付款金额Amount 和 付款描述Description,其他关键信息请勿修改
* 注意Amount的总价total是int类型,会自动乘以0.01,例如传递100元,会自动转换为1元
* @return
*/
@Override
public String nativePay(WxPayNeedParamVo paramVo) {
try {
// 商户订单号,存储当前用户的订单
String outTradeNo = PayKit.generateStr();
String timeExpire = getNowTimeExpire();
UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel()
.setAppid(WX_PAY_V3_BEAN.getAppId())
.setMchid(WX_PAY_V3_BEAN.getMchId())
// 描述信息
.setDescription(paramVo.getDescription())
.setOut_trade_no(outTradeNo)
.setTime_expire(timeExpire)
.setAttach(paramVo.getAttach())
.setNotify_url(payNotifyUrl)
// 订单金额
.setAmount(paramVo.getAmount());
log.info("二维码支付统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel));
IJPayHttpResponse response = WxPayApi.v3(
RequestMethodEnum.POST,
WxDomainEnum.CHINA.toString(),
BasePayApiEnum.NATIVE_PAY.toString(),
WX_PAY_V3_BEAN.getMchId(),
getSerialNumber(),
null,
WX_PAY_V3_BEAN.getKeyPath(),
JSONUtil.toJsonStr(unifiedOrderModel),
AuthTypeEnum.RSA.getCode()
);
log.info("统一下单响应 {}", response);
// 根据证书序列号查询对应的证书来验证签名结果
boolean verifySignature = WxPayKit.verifySignature(response, WX_PAY_V3_BEAN.getPlatformCertPath());
log.info("verifySignature: {}", verifySignature);
// 下单返回数据
String result = response.getBody();
if (result != null) {
// 向数据库插入订单记录
}
return result;
} catch (Exception e) {
log.error("系统异常", e);
return e.getMessage();
}
}
@Override
public String jsApiPay(WxPayNeedParamVo paramVo) {
try {
// 商户订单号,存储当前用户的订单
String outTradeNo = PayKit.generateStr();
// 订单关闭时间
String timeExpire = getNowTimeExpire();
UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel()
.setAppid(WX_PAY_V3_BEAN.getAppId())
.setMchid(WX_PAY_V3_BEAN.getMchId())
.setDescription(paramVo.getDescription())
.setOut_trade_no(outTradeNo)
.setTime_expire(timeExpire)
.setAttach(paramVo.getAttach())
.setNotify_url(payNotifyUrl)
.setAmount(paramVo.getAmount())
.setPayer(paramVo.getPayer());
log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel));
IJPayHttpResponse response = WxPayApi.v3(
RequestMethodEnum.POST,
WxDomainEnum.CHINA.toString(),
BasePayApiEnum.JS_API_PAY.toString(),
WX_PAY_V3_BEAN.getMchId(),
getSerialNumber(),
null,
WX_PAY_V3_BEAN.getKeyPath(),
JSONUtil.toJsonStr(unifiedOrderModel)
);
log.info("统一下单响应 {}", response);
// 根据证书序列号查询对应的证书来验证签名结果
boolean verifySignature = WxPayKit.verifySignature(response, WX_PAY_V3_BEAN.getPlatformCertPath());
log.info("verifySignature: {}", verifySignature);
if (response.getStatus() == OK && verifySignature) {
String body = response.getBody();
JSONObject jsonObject = JSONUtil.parseObj(body);
String prepayId = jsonObject.getStr("prepay_id");
Map<String, String> map = WxPayKit.jsApiCreateSign(WX_PAY_V3_BEAN.getAppId(), prepayId, WX_PAY_V3_BEAN.getKeyPath());
log.info("唤起支付参数:{}", map);
// 唤起支付成功,向数据库插入订单参数
return JSONUtil.toJsonStr(map);
}
return JSONUtil.toJsonStr(response);
} catch (Exception e) {
log.error("系统异常", e);
return e.getMessage();
}
}
@Override
public String wapPay(WxPayNeedParamVo paramVo) {
try {
// 商户订单号,存储当前用户的订单
String outTradeNo = PayKit.generateStr();
// 订单关闭时间
String timeExpire = getNowTimeExpire();
UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel()
.setAppid(WX_PAY_V3_BEAN.getAppId())
.setMchid(WX_PAY_V3_BEAN.getMchId())
.setDescription(paramVo.getDescription())
.setOut_trade_no(outTradeNo)
.setTime_expire(timeExpire)
.setAttach(paramVo.getAttach())
.setNotify_url(payNotifyUrl)
.setAmount(paramVo.getAmount())
.setScene_info(
new SceneInfo()
.setPayer_client_ip("").
setH5_info(new H5Info()
.setType("Wap")));
log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel));
IJPayHttpResponse response = WxPayApi.v3(
RequestMethodEnum.POST,
WxDomainEnum.CHINA.toString(),
BasePayApiEnum.H5_PAY.toString(),
WX_PAY_V3_BEAN.getMchId(),
getSerialNumber(),
null,
WX_PAY_V3_BEAN.getKeyPath(),
JSONUtil.toJsonStr(unifiedOrderModel)
);
log.info("统一下单响应 {}", response);
// 根据证书序列号查询对应的证书来验证签名结果
boolean verifySignature = WxPayKit.verifySignature(response, WX_PAY_V3_BEAN.getPlatformCertPath());
log.info("verifySignature: {}", verifySignature);
if (response.getStatus() == OK && verifySignature) {
String body = response.getBody();
return JSONUtil.toJsonStr(body);
}
return JSONUtil.toJsonStr(response);
} catch (Exception e) {
log.error("系统异常", e);
return e.getMessage();
}
}
/**
* 支付回调
* @param request
* @param response
*/
@Override
public void payNotify(HttpServletRequest request, HttpServletResponse response) {
Map<String, String> map = new HashMap<>(12);
try {
String timestamp = request.getHeader("Wechatpay-Timestamp");
String nonce = request.getHeader("Wechatpay-Nonce");
String serialNo = request.getHeader("Wechatpay-Serial");
String signature = request.getHeader("Wechatpay-Signature");
log.info("timestamp:{} nonce:{} serialNo:{} signature:{}", timestamp, nonce, serialNo, signature);
String result = HttpKit.readData(request);
log.info("支付通知密文 {}", result);
// String plainText = null;
// 需要通过证书序列号查找对应的证书,verifyNotify 中有验证证书的序列号
String plainText = WxPayKit.verifyNotify(serialNo, result, signature, nonce, timestamp,
WX_PAY_V3_BEAN.getApiKey3(), WX_PAY_V3_BEAN.getPlatformCertPath());
// 微信公钥验证签名并解密
// if (ObjectUtil.equals(serialNo, WX_PAY_V3_BEAN.getPublicKeyId())) {
// plainText = WxPayKit.verifyPublicKeyNotify(result, signature, nonce, timestamp,
// WX_PAY_V3_BEAN.getApiKey3(), WX_PAY_V3_BEAN.getPlatformCertPath());
// }
log.info("支付通知明文 {}", plainText);
if (StrUtil.isNotEmpty(plainText)) {
response.setStatus(200);
map.put("code", "SUCCESS");
map.put("message", "SUCCESS");
} else {
response.setStatus(500);
map.put("code", "ERROR");
map.put("message", "签名错误");
}
response.setHeader("Content-type", ContentType.JSON.toString());
response.getOutputStream().write(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8));
response.flushBuffer();
} catch (Exception e) {
log.error("系统异常", e);
}
}
/**
* 退款
* @param transactionId 微信订单号
* @param outTradeNo 商户订单号
* @return
*/
@Override
public String refund(String transactionId, String outTradeNo) {
try {
String outRefundNo = PayKit.generateStr();
log.info("商户退款单号: {}", outRefundNo);
List<RefundGoodsDetail> list = new ArrayList<>();
RefundGoodsDetail refundGoodsDetail = new RefundGoodsDetail()
.setMerchant_goods_id("123")
.setGoods_name("IJPay 测试")
.setUnit_price(1)
.setRefund_amount(1)
.setRefund_quantity(1);
list.add(refundGoodsDetail);
RefundModel refundModel = new RefundModel()
.setOut_refund_no(outRefundNo)
.setReason("IJPay 测试退款")
.setNotify_url(WX_PAY_V3_BEAN.getDomain().concat("/v3/refundNotify"))
.setAmount(new RefundAmount().setRefund(1).setTotal(1).setCurrency("CNY"))
.setGoods_detail(list);
if (StrUtil.isNotEmpty(transactionId)) {
refundModel.setTransaction_id(transactionId);
}
if (StrUtil.isNotEmpty(outTradeNo)) {
refundModel.setOut_trade_no(outTradeNo);
}
log.info("退款参数 {}", JSONUtil.toJsonStr(refundModel));
IJPayHttpResponse response = WxPayApi.v3(
RequestMethodEnum.POST,
WxDomainEnum.CHINA.toString(),
BasePayApiEnum.REFUND.toString(),
WX_PAY_V3_BEAN.getMchId(),
getSerialNumber(),
null,
WX_PAY_V3_BEAN.getKeyPath(),
JSONUtil.toJsonStr(refundModel)
);
// 根据证书序列号查询对应的证书来验证签名结果
boolean verifySignature = WxPayKit.verifySignature(response, WX_PAY_V3_BEAN.getPlatformCertPath());
// 微信支付公钥验证签名
// boolean verifySignature = WxPayKit.verifyPublicKeySignature(response, WX_PAY_V3_BEAN.getPlatformCertPath());
log.info("verifySignature: {}", verifySignature);
log.info("退款响应 {}", response);
if (verifySignature) {
return response.getBody();
}
} catch (Exception e) {
log.error("系统异常", e);
return e.getMessage();
}
return null;
}
/**
* 退款回调
* @param request
* @param response
*/
@Override
public void refundNotify(HttpServletRequest request, HttpServletResponse response) {
Map<String, String> map = new HashMap<>(12);
try {
String timestamp = request.getHeader("Wechatpay-Timestamp");
String nonce = request.getHeader("Wechatpay-Nonce");
String serialNo = request.getHeader("Wechatpay-Serial");
String signature = request.getHeader("Wechatpay-Signature");
log.info("退款通知 timestamp:{} nonce:{} serialNo:{} signature:{}", timestamp, nonce, serialNo, signature);
String result = HttpKit.readData(request);
log.info("退款通知密文 {}", result);
// String plainText = null;
// 需要通过证书序列号查找对应的证书,verifyNotify 中有验证证书的序列号
String plainText = WxPayKit.verifyNotify(serialNo, result, signature, nonce, timestamp,
WX_PAY_V3_BEAN.getApiKey3(), WX_PAY_V3_BEAN.getPlatformCertPath());
// 微信公钥验证签名并解密
// if (ObjectUtil.equals(serialNo, WX_PAY_V3_BEAN.getPublicKeyId())) {
// plainText = WxPayKit.verifyPublicKeyNotify(result, signature, nonce, timestamp,
// WX_PAY_V3_BEAN.getApiKey3(), WX_PAY_V3_BEAN.getPlatformCertPath());
// }
log.info("退款通知明文 {}", plainText);
if (StrUtil.isNotEmpty(plainText)) {
response.setStatus(200);
map.put("code", "SUCCESS");
map.put("message", "SUCCESS");
} else {
response.setStatus(500);
map.put("code", "ERROR");
map.put("message", "签名错误");
}
response.setHeader("Content-type", ContentType.JSON.toString());
response.getOutputStream().write(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8));
response.flushBuffer();
} catch (Exception e) {
log.error("系统异常", e);
}
}
/**
* 公共方法,获取证书序列号
* @return
*/
private String getSerialNumber() {
if (StrUtil.isEmpty(serialNo)) {
// 获取证书序列号
X509Certificate certificate = PayKit.getCertificate(WX_PAY_V3_BEAN.getCertPath());
if (null != certificate) {
serialNo = certificate.getSerialNumber().toString(16).toUpperCase();
// 提前两天检查证书是否有效
boolean isValid = PayKit.checkCertificateIsValid(certificate, WX_PAY_V3_BEAN.getMchId(), -2);
log.info("证书是否可用 {} 证书有效期为 {}", isValid, DateUtil.format(certificate.getNotAfter(), DatePattern.NORM_DATETIME_PATTERN));
}
// System.out.println("输出证书信息:\n" + certificate.toString());
// // 输出关键信息,截取部分并进行标记
// System.out.println("证书序列号:" + certificate.getSerialNumber().toString(16));
// System.out.println("版本号:" + certificate.getVersion());
// System.out.println("签发者:" + certificate.getIssuerDN());
// System.out.println("有效起始日期:" + certificate.getNotBefore());
// System.out.println("有效终止日期:" + certificate.getNotAfter());
// System.out.println("主体名:" + certificate.getSubjectDN());
// System.out.println("签名算法:" + certificate.getSigAlgName());
// System.out.println("签名:" + certificate.getSignature().toString());
}
System.out.println("serialNo:" + serialNo);
return serialNo;
}
/**
* 公共方法,获取平台证书序列号
* @return
*/
private String getPlatSerialNumber() {
if (StrUtil.isEmpty(platSerialNo)) {
// 获取平台证书序列号
X509Certificate certificate = PayKit.getCertificate(FileUtil.getInputStream(WX_PAY_V3_BEAN.getPlatformCertPath()));
platSerialNo = certificate.getSerialNumber().toString(16).toUpperCase();
}
System.out.println("platSerialNo:" + platSerialNo);
return platSerialNo;
}
/**
* 公共方法,保存平台证书
* @param associatedData
* @param nonce
* @param cipherText
* @param algorithm
* @param certPath
* @return
*/
private String savePlatformCert(String associatedData, String nonce, String cipherText, String algorithm, String certPath) {
try {
String key3 = WX_PAY_V3_BEAN.getApiKey3();
String publicKey;
if (StrUtil.equals(algorithm, AuthTypeEnum.SM2.getPlatformCertAlgorithm())) {
publicKey = PayKit.sm4DecryptToString(key3, cipherText, nonce, associatedData);
} else {
AesUtil aesUtil = new AesUtil(WX_PAY_V3_BEAN.getApiKey3().getBytes(StandardCharsets.UTF_8));
// 平台证书密文解密
// encrypt_certificate 中的 associated_data nonce ciphertext
publicKey = aesUtil.decryptToString(
associatedData.getBytes(StandardCharsets.UTF_8),
nonce.getBytes(StandardCharsets.UTF_8),
cipherText
);
}
if (StrUtil.isNotEmpty(publicKey)) {
// 保存证书
FileWriter writer = new FileWriter(certPath);
writer.write(publicKey);
// 获取平台证书序列号
X509Certificate certificate = PayKit.getCertificate(new ByteArrayInputStream(publicKey.getBytes()));
return certificate.getSerialNumber().toString(16).toUpperCase();
}
return "";
} catch (Exception e) {
log.error("保存平台证书异常", e);
return e.getMessage();
}
}
/**
* 公共方法,构建订单关闭时间,默认3分钟
* @return
*/
private String getNowTimeExpire() {
long currentTimeMillis = System.currentTimeMillis() + 1000 * 60 * 3;
// 将时间戳转换为 DateTime 对象
DateTime dateTime = DateUtil.date(currentTimeMillis);
return DateUtil.format(dateTime, "yyyy-MM-dd'T'HH:mm:ssXXX");
}
}
@@ -0,0 +1,39 @@
package io.v.nutz.zhgh.memberCost.payment.wxpay.vo;
import com.ijpay.wxpay.model.v3.Amount;
import com.ijpay.wxpay.model.v3.Payer;
import lombok.Data;
/**
* @version 1.0
* @Author zzr
* @name:WxPayNeedParamVo
* @Date 2025/3/7 18:43
* @注释
*/
@Data
public class WxPayNeedParamVo {
/**
* 订单描述,会显示在支付界面的标题,最大长度127,必填
*/
private String description;
/**
* 附加数据,订单的详细描述信息,不必填
*/
private String attach;
/**
* 金额对象,对象中的 total 是金额,必填;
* 其余参数可不传递也可不填
*/
private Amount amount;
/**
* 支付者对象,JsApi支付是必填,其他支付方式忽略;
* openid 微信绑定的用户openid和小程序的openid相同,必填;
* 其余参数可忽略
*/
private Payer payer;
}
@@ -1,5 +1,7 @@
package io.v.nutz.zhgh.welfare.controller; package io.v.nutz.zhgh.welfare.controller;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import io.v.nutz.base.annontation.ViReturn; import io.v.nutz.base.annontation.ViReturn;
import io.v.nutz.base.dao.CndPlus; import io.v.nutz.base.dao.CndPlus;
@@ -32,7 +34,6 @@ import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang; import org.nutz.lang.Lang;
import org.nutz.lang.Strings; import org.nutz.lang.Strings;
import org.nutz.lang.random.R; import org.nutz.lang.random.R;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok; import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param; import org.nutz.mvc.annotation.Param;
@@ -94,7 +95,7 @@ public class WelfareProjectMangeController {
Sql sql = Sqls.create("SELECT project.*,IF((SELECT count(1) FROM welfare_list WHERE projectId = project.id)>0,TRUE,FALSE) created FROM `welfare_project` project $condition"); Sql sql = Sqls.create("SELECT project.*,IF((SELECT count(1) FROM welfare_list WHERE projectId = project.id)>0,TRUE,FALSE) created FROM `welfare_project` project $condition");
CndPlus cnd = CndPlus.create(); CndPlus cnd = CndPlus.create();
pageForm.defaultSortDesc("createdAt"); pageForm.defaultSortDesc("opAt");
cnd.andEx("year", "=", year); cnd.andEx("year", "=", year);
if (Strings.isNotBlank(name)) { if (Strings.isNotBlank(name)) {
@@ -117,13 +118,14 @@ public class WelfareProjectMangeController {
Trans.exec(() -> { Trans.exec(() -> {
project.setYear(DateUtil.thisYear());
project.setIsDisabled(false);
if (project.getConditionStructure() != null) { if (project.getConditionStructure() != null) {
project.setConditionStructureId(matchConditionStructureService.save(project.getConditionStructure()).getId()); project.setConditionStructureId(matchConditionStructureService.save(project.getConditionStructure()).getId());
} }
if (StrUtil.isBlank(project.getId())) { if (StrUtil.isBlank(project.getId())) {
WelfareProject insertProject = dao.insertWith(project, "welfareProjectSubjects"); WelfareProject insertProject = dao.insertWith(project, "welfareProjectSubjects");
if (Lang.isNotEmpty(insertProject.getWelfareProjectSubjects())) { if (Lang.isNotEmpty(insertProject.getWelfareProjectSubjects())) {
insertProject.getWelfareProjectSubjects().forEach(v -> { insertProject.getWelfareProjectSubjects().forEach(v -> {
dao.insertLinks(v, "options"); dao.insertLinks(v, "options");
@@ -235,10 +237,8 @@ public class WelfareProjectMangeController {
dao.update(project); dao.update(project);
} }
// if (project.getIsPushHome() != 0) {
// mobileHomeService.handle(project, "welfare", "/mobile/welfare/list/receive?projectId=" + project.getId(), project.getIsPushHome());
// }
Sys_home_activity sysHomeActivity = project.covertToSysHomeActivity(); Sys_home_activity sysHomeActivity = project.covertToSysHomeActivity();
sysHomeActivity.setEnable(true);
dao.insertOrUpdate(sysHomeActivity); dao.insertOrUpdate(sysHomeActivity);
}); });
return null; return null;
@@ -256,7 +256,9 @@ public class WelfareProjectMangeController {
projectService.dao().delete(MatchConditionStructure.class, project.getConditionStructureId()); projectService.dao().delete(MatchConditionStructure.class, project.getConditionStructureId());
} }
projectService.dao().clear(WelfareProjectSubject.class, Cnd.where("projectId", "=", id)); projectService.dao().clear(WelfareProjectSubject.class, Cnd.where("projectId", "=", id));
projectService.dao().clear(WelfareProjectSubjectOption.class, Cnd.where("subjectId", "=", welfareProjectSubject.getId())); if (ObjectUtil.isNotEmpty(welfareProjectSubject)) {
projectService.dao().clear(WelfareProjectSubjectOption.class, Cnd.where("subjectId", "=", welfareProjectSubject.getId()));
}
projectService.dao().clear(WelfareUserSelection.class, Cnd.where("welfareId", "=", id)); projectService.dao().clear(WelfareUserSelection.class, Cnd.where("welfareId", "=", id));
projectService.delete(id); projectService.delete(id);
mobileHomeService.delete(id); mobileHomeService.delete(id);
@@ -292,7 +294,7 @@ public class WelfareProjectMangeController {
public Object sendMsgToNotWelfareUsers(String projectId, String sendMsgValue) { public Object sendMsgToNotWelfareUsers(String projectId, String sendMsgValue) {
Sql sql = Sqls.create(""" Sql sql = Sqls.create("""
SELECT SELECT
u.loginname as userId u.loginname
FROM FROM
welfare_list wl welfare_list wl
left join sys_user u on u.id = wl.userId left join sys_user u on u.id = wl.userId
@@ -308,8 +310,13 @@ public class WelfareProjectMangeController {
) )
"""); """);
sql.setParam("projectId", projectId); sql.setParam("projectId", projectId);
List<NutMap> userList = listService.listMap(sql); // List<NutMap> userList = listService.listMap(sql);
// msgApi.sendMsg(sendMsgValue, "福利选择链接", "", "https://zhgh.jiangnan.edu.cn/mobile/welfare/list/receive?projectId=4fa233704ddb41bc8e34e966efeda0a4", "4", userList); // Set<String> loginNameList = userList.stream().map(user -> user.getString("loginname")).collect(Collectors.toSet());
// String loginNames = loginNameList.stream().collect(Collectors.joining(","));
// WelfareProject project = dao.fetch(WelfareProject.class, projectId);
// String link = Globals.AppDomain + "/mobile/welfare/list/receive?projectId=%s".formatted(projectId);
// String imageUrl = Globals.AppDomain + "/file_server/fileStreamPreview?id=" + project.getCover();
// msgApi.sendMsg(List.of("DingTalk"), loginNames, 2, "职工福利", sendMsgValue, "", link);
return null; return null;
} }
@@ -321,9 +328,11 @@ public class WelfareProjectMangeController {
*/ */
@At @At
@ViReturn @ViReturn
@Aop(TransAop.READ_COMMITTED)
@RequiresPermissions("welfare.list.mange") @RequiresPermissions("welfare.list.mange")
public Object projectStatusChange(String id, boolean val) { public Object projectStatusChange(String id, boolean val) {
dao.update(WelfareProject.class, Chain.make("isDisabled", !val), Cnd.where("id", "=", id)); dao.update(WelfareProject.class, Chain.make("isDisabled", !val), Cnd.where("id", "=", id));
dao.update(Sys_home_activity.class, Chain.make("enable", val), Cnd.where("id", "=", id));
return null; return null;
} }
@@ -55,27 +55,29 @@ public class WelfareUserChooseController {
@ViReturn @ViReturn
@RequiresPermissions("welfare.user.choose") @RequiresPermissions("welfare.user.choose")
public Object pageData(PageForm pageForm, Integer year) { public Object pageData(PageForm pageForm, Integer year) {
Sql sql = Sqls.create(""" Sql sql = Sqls.create("""
SELECT SELECT
wp.*, wp.*,
CASE CASE
WHEN wus.selectUserId IS NOT NULL THEN 1 WHEN wus.selectUserId IS NOT NULL THEN 1
ELSE 0 ELSE 0
END AS isChoose, END AS isChoose,
wus.selectTime, wus.selectTime,
GROUP_CONCAT(DISTINCT wuso.optionName ,'(',wus.selectNum,'份)') AS gist_list, GROUP_CONCAT(DISTINCT wuso.optionName ,'(',wus.selectNum,'份)') AS gist_list,
wus.receiveAddress wus.receiveAddress
FROM FROM
welfare_project wp welfare_project wp
LEFT JOIN welfare_project_user_selection wus ON wp.id = wus.welfareId AND wus.selectUserId = @selectUserId LEFT JOIN welfare_project_user_selection wus ON wp.id = wus.welfareId AND wus.selectUserId = @selectUserId
INNER JOIN welfare_list wl ON wp.id = wl.projectId AND wl.userId = @selectUserId LEFT JOIN welfare_list wl ON wp.id = wl.projectId AND wl.userId = @selectUserId
LEFT JOIN welfare_project_subject_option wuso ON wus.selectOptionId = wuso.id LEFT JOIN welfare_project_subject_option wuso ON wus.selectOptionId = wuso.id
$condition $condition
"""); """);
sql.setParam("selectUserId", ShiroUtil.getUserId()); sql.setParam("selectUserId", ShiroUtil.getUserId());
Cnd cnd = Cnd.NEW(); Cnd cnd = Cnd.NEW();
cnd.and("wp.provideMode", "in", "2,3"); cnd.and("wp.provideMode", "in", "2,3");
cnd.and("wl.userId", "=", ShiroUtil.getUserId());
cnd.andEX("YEAR(wp.choiceTimeStart)", "in", year); cnd.andEX("YEAR(wp.choiceTimeStart)", "in", year);
cnd.and("wp.isDisabled", "=", 0); cnd.and("wp.isDisabled", "=", 0);
cnd.groupBy("wp.id"); cnd.groupBy("wp.id");
@@ -1,6 +1,6 @@
package io.v.nutz.zhgh.welfare.model; package io.v.nutz.zhgh.welfare.model;
import io.v.nutz.base.model.ViBaseModel; import cn.wizzer.framework.base.model.BaseModel;
import io.v.nutz.sys.models.Sys_home_activity; import io.v.nutz.sys.models.Sys_home_activity;
import io.v.nutz.sys.services.SysHomeConvert; import io.v.nutz.sys.services.SysHomeConvert;
import io.v.nutz.zhgh.data.model.MatchConditionStructure; import io.v.nutz.zhgh.data.model.MatchConditionStructure;
@@ -29,7 +29,7 @@ import java.util.List;
@Accessors(chain = true) @Accessors(chain = true)
@Table("welfare_project") @Table("welfare_project")
@Comment("福利项目") @Comment("福利项目")
public class WelfareProject extends ViBaseModel implements Serializable, SysHomeConvert { public class WelfareProject extends BaseModel implements Serializable, SysHomeConvert {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@@ -43,9 +43,6 @@ public class WelfareProject extends ViBaseModel implements Serializable, SysHome
@Column @Column
@Comment("年度") @Comment("年度")
@ColDefine(type = ColType.INT, width = 4) @ColDefine(type = ColType.INT, width = 4)
@PrevInsert(
els = {@EL("$me.nowYear()")}
)
private Integer year; private Integer year;
@Column @Column
@@ -1,10 +1,10 @@
package io.v.nutz.zhgh.welfare.service.impl; package io.v.nutz.zhgh.welfare.service.impl;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.annotation.Excel; import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.entity.ExportParams; import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import cn.afterturn.easypoi.excel.export.ExcelExportService;
import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
@@ -21,6 +21,7 @@ import io.v.nutz.zhgh.welfare.model.WelfareProject;
import io.v.nutz.zhgh.welfare.model.template.WelfareExportEntityTc; import io.v.nutz.zhgh.welfare.model.template.WelfareExportEntityTc;
import io.v.nutz.zhgh.welfare.service.WelfareSingleService; import io.v.nutz.zhgh.welfare.service.WelfareSingleService;
import lombok.Data; import lombok.Data;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddress;
@@ -46,9 +47,7 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@@ -671,23 +670,25 @@ public class WelfareSingleServiceImpl extends ViServiceImpl<WelfareProject> impl
SELECT SELECT
u.loginname, u.loginname,
u.username, u.username,
vwl.welfareUnitId as unionid, IF(staffUnion.id IS NOT NULL, staffUnion.id, vwl.welfareUnitId) AS unionid,
gh.unionname as unionname, IF(staffUnion.id IS NOT NULL, staffUnion.unionname, gh.unionname) AS unionname,
vwl.welfareSecondLevelUnitId as unitid, vwl.welfareSecondLevelUnitId as unitid,
dw.`name` as unitname, dw.`name` as unitname,
wpus.userSign, wpus.userSign,
wpus.selectOptionId, wpus.selectOptionId,
wpus.selectNum\s wpus.selectNum
FROM FROM
welfare_list vwl welfare_list vwl
LEFT join sys_user u on u.id = vwl.userId LEFT JOIN special_staff staff ON staff.userId = vwl.userId
left join sys_union gh on gh.id = vwl.welfareUnitId LEFT JOIN sys_union staffUnion ON staff.unionRelationUnionId = staffUnion.id
left join sys_unit dw on dw.id = vwl.welfareSecondLevelUnitId LEFT JOIN sys_user u ON u.id = vwl.userId
LEFT JOIN welfare_project_user_selection wpus ON wpus.selectUserId = vwl.userId\s LEFT JOIN sys_union gh ON gh.id = vwl.welfareUnitId
AND wpus.welfareId = @projectId\s LEFT JOIN sys_unit dw ON dw.id = vwl.welfareSecondLevelUnitId
LEFT JOIN welfare_project_user_selection wpus ON wpus.selectUserId = vwl.userId
AND wpus.welfareId = @projectId
WHERE WHERE
projectId = @projectId projectId = @projectId
AND vwl.welfareUnitId = @unionId AND (vwl.welfareUnitId = @unionId OR staffUnion.id = @unionId)
order by vwl.welfareUnitId,vwl.welfareSecondLevelUnitId order by vwl.welfareUnitId,vwl.welfareSecondLevelUnitId
"""); """);
@@ -712,18 +713,21 @@ public class WelfareSingleServiceImpl extends ViServiceImpl<WelfareProject> impl
}); });
List<ExcelExportEntity> exportEntities = new ArrayList<>(); List<ExcelExportEntity> exportEntities = new ArrayList<>();
exportEntities.add(new ExcelExportEntity("序号", "no", 20)); exportEntities.add(new ExcelExportEntity("序号", "no", 10));
exportEntities.add(new ExcelExportEntity("姓名", "username", 20)); exportEntities.add(new ExcelExportEntity("姓名", "username", 10));
exportEntities.add(new ExcelExportEntity("工号", "loginname", 20)); exportEntities.add(new ExcelExportEntity("工号", "loginname", 15));
exportEntities.add(new ExcelExportEntity("所在基层工会", "unionname", 20)); // exportEntities.add(new ExcelExportEntity("所在分工会", "unionname", 20));
exportEntities.add(new ExcelExportEntity("所在单位", "unitname", 20)); ExcelExportEntity excelExportEntity1 = new ExcelExportEntity("所在单位", "unitname", 20);
excelExportEntity1.setWrap(true);
exportEntities.add(excelExportEntity1);
for (NutMap option : options) { for (NutMap option : options) {
exportEntities.add(new ExcelExportEntity(option.getString("optionName"), option.getString("id"), 20)); exportEntities.add(new ExcelExportEntity(option.getString("optionName"), option.getString("id"), 10));
} }
ExcelExportEntity excelExportEntity = new ExcelExportEntity(); ExcelExportEntity excelExportEntity = new ExcelExportEntity();
excelExportEntity.setName("签字"); excelExportEntity.setName("签字");
excelExportEntity.setKey("qzBytes"); excelExportEntity.setKey("qzBytes");
excelExportEntity.setHeight(12);
excelExportEntity.setWidth(20); excelExportEntity.setWidth(20);
excelExportEntity.setType(2); excelExportEntity.setType(2);
excelExportEntity.setExportImageType(2); excelExportEntity.setExportImageType(2);
@@ -764,9 +768,16 @@ public class WelfareSingleServiceImpl extends ViServiceImpl<WelfareProject> impl
totalMap.put(option.getString("id"), selectNum); totalMap.put(option.getString("id"), selectNum);
} }
dataList.add(totalMap); dataList.add(totalMap);
ExportParams exportParams = new ExportParams(); /*ExportParams exportParams = new ExportParams();
exportParams.setType(ExcelType.XSSF); exportParams.setType(ExcelType.XSSF);
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, exportEntities, dataList); Workbook workbook = ExcelExportUtil.exportExcel(exportParams, exportEntities, dataList);
workbook.write(outputStream);*/
Workbook workbook = new HSSFWorkbook();
ExportParams exportParams = new ExportParams();
exportParams.setType(ExcelType.HSSF);
ExcelExportService service = new ExcelExportService();
service.createSheetForMap(workbook, exportParams, exportEntities, dataList);
workbook.write(outputStream); workbook.write(outputStream);
// List<NutMap> result = new ArrayList<>(); // List<NutMap> result = new ArrayList<>();
@@ -1023,7 +1034,6 @@ public class WelfareSingleServiceImpl extends ViServiceImpl<WelfareProject> impl
sheet.setColumnWidth(0, 1000 * 2); sheet.setColumnWidth(0, 1000 * 2);
sheet.setColumnWidth(1, 1500 * 2); sheet.setColumnWidth(1, 1500 * 2);
sheet.setColumnWidth(2, 3000 * 2); sheet.setColumnWidth(2, 3000 * 2);
sheet.setColumnWidth(2, 3000 * 2);
sheet.setColumnWidth(3, 2000 * 2); sheet.setColumnWidth(3, 2000 * 2);
sheet.setColumnWidth(4, 2000 * 2); sheet.setColumnWidth(4, 2000 * 2);
sheet.setColumnWidth(5, 1500 * 2); sheet.setColumnWidth(5, 1500 * 2);
@@ -1180,18 +1190,43 @@ public class WelfareSingleServiceImpl extends ViServiceImpl<WelfareProject> impl
} else { } else {
v.setQzBytes(null); v.setQzBytes(null);
} }
} }
Map<String, String> addressMap = new HashMap<>();
String receiveAddress = v.getReceiveAddress();
if (StrUtil.isNotBlank(receiveAddress)) {
List<String> addressList = Arrays.stream(receiveAddress.split("[,,]")).collect(Collectors.toList());
for (String pair : addressList) {
// 2. 根据冒号分割键和值
String[] keyValue = pair.split("[::]", 2);
if (keyValue.length == 2) {
String key = keyValue[0].trim();
String value = keyValue[1].trim();
addressMap.put(key, value);
}
}
// v.setRecipient(addressMap.get("收件人"));
// v.setPhone(addressMap.get("联系方式"));
// v.setAddress(addressMap.get("收货地址"));
}
}); });
ExportParams exportParams = new ExportParams(); ExportParams exportParams = new ExportParams();
exportParams.setType(ExcelType.XSSF); exportParams.setType(ExcelType.HSSF);
exportParams.setSheetName(project.getName()); exportParams.setSheetName(project.getName());
try { try {
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, WelfareExportEntityTc.class, welfareExportEntityTcList); ViTool.excelResponse(response, (project.getName() + (flag ? "已选名单" : "未选名单")) + ".xls");
ViTool.excelResponse(response, (project.getName() + (flag ? "已选名单" : "未选名单")) + ".xlsx"); Workbook workbook = new HSSFWorkbook();
ExcelExportService service = new ExcelExportService();
service.createSheet(workbook, exportParams, WelfareExportEntityTc.class, welfareExportEntityTcList);
ServletOutputStream outputStream = response.getOutputStream(); ServletOutputStream outputStream = response.getOutputStream();
workbook.write(outputStream); workbook.write(outputStream);
outputStream.close();
// Workbook workbook = ExcelExportUtil.exportExcel(exportParams, WelfareExportEntityTc.class, welfareExportEntityTcList);
// ServletOutputStream outputStream = response.getOutputStream();
// workbook.write(outputStream);
// outputStream.close();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
+12 -2
View File
@@ -47,7 +47,7 @@ jdbc.defaultAutoCommit=true
xsssql.ignore.urls=/platform/cms/content/article/addDo,/platform/sys/app/conf/addDo,/platform/sys/app/conf/editDo,\ xsssql.ignore.urls=/platform/cms/content/article/addDo,/platform/sys/app/conf/addDo,/platform/sys/app/conf/editDo,\
/platform/member/change/mange/userPageData,/platform/welfare/member/mange/userPageData,/platform/sys/task/cronExp,\ /platform/member/change/mange/userPageData,/platform/welfare/member/mange/userPageData,/platform/sys/task/cronExp,\
/platform/sys/task/editDo,/platform/sys/task/addDo,/platform/fellowship/manage/activity/doHandle,/platform/sys/menu/editMenuDo,\ /platform/sys/task/editDo,/platform/sys/task/addDo,/platform/fellowship/manage/activity/doHandle,/platform/sys/menu/editMenuDo,\
/platform/trainSingUp/manage/activity/doHandle /platform/trainSingUp/manage/activity/doHandle,/platform/activity/school/info/mange/doAdd,/platform/activity/school/info/mange/doEdit
#环境 dev/prod #环境 dev/prod
v.environment=dev v.environment=dev
v.loginUrl=/sso/login v.loginUrl=/sso/login
@@ -78,7 +78,7 @@ shiro.url.login=/platform
shiro.url.logout_redirect=/platform shiro.url.logout_redirect=/platform
shiro.url.unauth=/platform shiro.url.unauth=/platform
#开发时设置本地路径,便于调试 #开发时设置本地路径,便于调试
beetl.RESOURCE.rootLocal=G:/zhgh/zhgh_hrbnu/src/main/resources/views/ beetl.RESOURCE.rootLocal=G:/zhgh/ /src/main/resources/views/
beetl.RESOURCE.root=views/ beetl.RESOURCE.root=views/
beetl.DELIMITER_STATEMENT_START=<!--# beetl.DELIMITER_STATEMENT_START=<!--#
beetl.DELIMITER_STATEMENT_END=#--> beetl.DELIMITER_STATEMENT_END=#-->
@@ -143,5 +143,15 @@ logback.exts.loglevel.enabled=true
#心跳间隔(单位:秒) #心跳间隔(单位:秒)
logback.exts.loglevel.heartbeat=15 logback.exts.loglevel.heartbeat=15
wxpay.appId=\u5E94\u7528\u7F16\u53F7
wxpay.keyPath=key.pem
wxpay.certPath=cert.pem
wxpay.certP12Path=cert.p12
wxpay.platformCertPath=wx_cert.pem
wxpay.mchId=\u5FAE\u4FE1\u5546\u6237\u53F7
wxpay.apiKey3=Api-v3 \u5BC6\u94A5
wxpay.apiKey=Api \u5BC6\u94A5
wxpay.domain=https://ijpay.javen.com
+2 -2
View File
@@ -32,9 +32,9 @@
<logger name="org.quartz" level="INFO"/> <logger name="org.quartz" level="INFO"/>
<logger name="org.nutz" level="DEBUG"/> <logger name="org.nutz" level="DEBUG"/>
<root level="DEBUG"> <root level="INFO">
<appender-ref ref="STDOUT" /> <appender-ref ref="STDOUT" />
<appender-ref ref="ASYNC" /> <appender-ref ref="ASYNC" />
</root> </root>
</configuration> </configuration>
@@ -84,8 +84,17 @@ module.exports = {
clearInterval(signatureInterval) clearInterval(signatureInterval)
const ts = new Date().getTime() + (Math.floor(Math.random() * (1000 - 1 + 1)) + 1).toString() const ts = new Date().getTime() + (Math.floor(Math.random() * (1000 - 1 + 1)) + 1).toString()
console.log(ts) console.log(ts)
// this.postAddress = location.protocol + '//' + location.host + '/signature?prefix=' + this.prefix + '&id=' + ts + "&is_value_base64=" + this.is_value_base64 this.postAddress =
this.postAddress = "https://zhgh.hrbnu.edu.cn/signature?prefix=" + this.prefix + "&id=" + ts + "&is_value_base64=" + this.is_value_base64 location.protocol +
"//" +
location.host +
"/signature?prefix=" +
this.prefix +
"&id=" +
ts +
"&is_value_base64=" +
this.is_value_base64
// this.postAddress = "https://zhgh.hrbnu.edu.cn/signature?prefix=" + this.prefix + "&id=" + ts + "&is_value_base64=" + this.is_value_base64
this.showQrCode = true this.showQrCode = true
@@ -101,7 +101,6 @@
<script src="${base!}/assets/platform/js/offscreen.js"></script> <script src="${base!}/assets/platform/js/offscreen.js"></script>
<!-- <script src="https://cdn.jsdelivr.net/npm/vue-echarts@4.0.2"></script>--> <!-- <script src="https://cdn.jsdelivr.net/npm/vue-echarts@4.0.2"></script>-->
<script src="${base!}/assets/platform/plugins/vue-charts/echartTheme.js"></script> <script src="${base!}/assets/platform/plugins/vue-charts/echartTheme.js"></script>
<script src="${base!}/assets/platform/js/chengSh.js"></script>
<!--拖拽js--> <!--拖拽js-->
<script src="${base!}/assets/platform/js/directive/v-sticky.js"></script> <script src="${base!}/assets/platform/js/directive/v-sticky.js"></script>
@@ -109,6 +108,7 @@
<script src="${base!}/assets/platform/js/jr-qrcode.js"></script> <script src="${base!}/assets/platform/js/jr-qrcode.js"></script>
<!--字典混入--> <!--字典混入-->
<script src="${base!}/assets/platform/js/chengSh.js"></script>
<script src="${base!}/components/plugins/sysDict/DictData.js"></script> <script src="${base!}/components/plugins/sysDict/DictData.js"></script>
<script src="${base!}/assets/platform/js/util/commonUtil.js"></script> <script src="${base!}/assets/platform/js/util/commonUtil.js"></script>
@@ -0,0 +1,16 @@
<!--#
layout("/mobile/platform.html"){
#-->
<div id="app" v-cloak></div>
<script>
new Vue({
el: "#app",
mixins: [mobileMixins],
data() {
return {}
}
})
</script>
<!--#
}
#-->
@@ -16,11 +16,13 @@ layout("/mobile/platform.html"){
border-bottom: 1px dashed lightgrey; border-bottom: 1px dashed lightgrey;
} }
.selection .van-checkbox-group .van-cell, .selection .van-radio-group .van-cell { .selection .van-checkbox-group .van-cell,
.selection .van-radio-group .van-cell {
flex-direction: row-reverse; flex-direction: row-reverse;
} }
.selection .van-checkbox-group .van-cell .van-cell__title, .selection .van-radio-group .van-cell .van-cell__title { .selection .van-checkbox-group .van-cell .van-cell__title,
.selection .van-radio-group .van-cell .van-cell__title {
padding-left: 20px; padding-left: 20px;
} }
@@ -41,7 +43,6 @@ layout("/mobile/platform.html"){
} }
.van-collapse-item .van-collapse-item__title { .van-collapse-item .van-collapse-item__title {
} }
.selection .van-radio { .selection .van-radio {
@@ -59,7 +60,9 @@ layout("/mobile/platform.html"){
height: 80px; height: 80px;
} }
.welfare_img .van-image__error, .welfare_img .van-image__img, .welfare_img .van-image__loading { .welfare_img .van-image__error,
.welfare_img .van-image__img,
.welfare_img .van-image__loading {
border-radius: 10px; border-radius: 10px;
margin-left: -35px; margin-left: -35px;
} }
@@ -115,7 +118,7 @@ layout("/mobile/platform.html"){
padding-left: 20px; padding-left: 20px;
padding-right: 10px; padding-right: 10px;
position: relative; position: relative;
height: 100px height: 100px;
} }
.optionDesc { .optionDesc {
@@ -132,142 +135,143 @@ layout("/mobile/platform.html"){
border: 1pt solid #000000 !important; border: 1pt solid #000000 !important;
} }
.van-submit-bar__button {
width: 150px;
}
.custom-cell {
font-size: 18px;
font-weight: bold;
}
</style> </style>
<div id="app" v-cloak> <div id="app" v-cloak>
<van-sticky> <van-sticky>
<van-nav-bar @click-left="history.go(-1)" left-arrow <van-nav-bar @click-left="history.go(-1)" left-arrow title="福利详情"></van-nav-bar>
title="福利详情"></van-nav-bar>
</van-sticky> </van-sticky>
<template v-show="vLoading && !vLoading.value"> <template v-show="vLoading && !vLoading.value">
<div> <div>
<van-image :src="CREATE_PREVIEW_URL(projectInfo.cover)" <van-image :src="CREATE_PREVIEW_URL(projectInfo.cover)" fit="cover" style="width: 100%; height: 150px"></van-image>
fit="cover"
style="width: 100%;height: 150px"></van-image>
</div> </div>
<!--基本信息--> <!--基本信息-->
<van-cell-group class="van-cell-group--inset"> <van-cell-group class="van-cell-group--inset">
<van-cell> <van-cell>
<div style="font-weight: bold;font-size: 15px;display: flex;align-items: center"> <div style="font-weight: bold; font-size: 15px; display: flex; align-items: center; justify-content: space-between">
福利信息 <div>
<span>福利信息</span>
</div>
<div @click="clickUpOrDown=!clickUpOrDown">
<span>{{clickUpOrDown ? '点击收起' : '点击展开'}}</span>
<van-icon :name="clickUpOrDown?'arrow-up':'arrow-down'"></van-icon>
</div>
</div> </div>
</van-cell> </van-cell>
<van-cell :border="false" :value="projectInfo.name" title="福利名称"></van-cell> <template v-if="clickUpOrDown">
<van-cell :border="false" :value="projectInfo.festival" title="发放节日"></van-cell> <van-cell :border="false" :value="projectInfo.name" title="福利名称"></van-cell>
<van-cell :border="false" :value="projectInfo.gift" title="福利礼品" <van-cell :border="false" :value="projectInfo.festival" title="发放节日"></van-cell>
v-if="!projectInfo.flexible"></van-cell> <van-cell :border="false" :value="projectInfo.gift" title="福利礼品" v-if="!projectInfo.flexible"></van-cell>
<!--<van-cell :border="false" :value="projectInfo.provideAddress" <!--<van-cell :border="false" :value="projectInfo.provideAddress"
title="发放地点"></van-cell>--> title="发放地点"></van-cell>-->
<van-cell :border="false" title="选择形式"> <van-cell :border="false" title="选择形式">{{projectInfo.isCheckBox==='checkBox'?'多选':'单选'}}</van-cell>
{{projectInfo.isCheckBox==='checkBox'?'多选':'单选'}} <van-cell
</van-cell> :border="false"
<van-cell :border="false" :value="projectInfo.multiSelectNum" title="最多选几个" :value="projectInfo.multiSelectNum"
v-if="projectInfo.isCheckBox==='checkBox'"></van-cell> title="最多选几个"
<van-cell :border="false" title="发放形式"> v-if="projectInfo.isCheckBox==='checkBox'"
<template> ></van-cell>
{{welfareProvideMode.find(v=>v.code==projectInfo.provideMode) && <van-cell :border="false" title="发放形式">
welfareProvideMode.find(v=>v.code==projectInfo.provideMode).description}} <template>
</template> {{welfareProvideMode.find(v=>v.code==projectInfo.provideMode) &&
</van-cell> welfareProvideMode.find(v=>v.code==projectInfo.provideMode).description}}
<van-cell :border="false" title="签收形式"> </template>
<template> </van-cell>
{{welfareSignMode.find(v=>v.code==projectInfo.signMode) && <van-cell :border="false" title="签收形式">
welfareSignMode.find(v=>v.code==projectInfo.signMode).description}} <template>
</template> {{welfareSignMode.find(v=>v.code==projectInfo.signMode) && welfareSignMode.find(v=>v.code==projectInfo.signMode).description}}
</van-cell> </template>
<van-cell :border="false" title="选择时间"> </van-cell>
<template #label> <van-cell :border="false" title="选择时间">
{{projectInfo.choiceTimeStart + ' 至 ' + projectInfo.choiceTimeEnd}} <template #label>{{projectInfo.choiceTimeStart + ' 至 ' + projectInfo.choiceTimeEnd}}</template>
</template> </van-cell>
</van-cell> </template>
</van-cell-group> </van-cell-group>
<!--礼品套餐--> <!--礼品套餐-->
<div class="van-cell-group--inset" <div
style="margin:10px auto" class="van-cell-group--inset"
v-if="projectInfo.flexible && [2,3].includes(projectInfo.provideMode) style="margin: 10px auto"
v-if="projectInfo.flexible && [2,3].includes(projectInfo.provideMode)
&& projectInfo.welfareProjectSubjects && projectInfo.welfareProjectSubjects
&& projectInfo.welfareProjectSubjects.length>0"> && projectInfo.welfareProjectSubjects.length>0"
>
<van-cell> <van-cell>
<div style="font-weight: bold;font-size: 15px;display: flex;align-items: center"> <div style="font-weight: bold; font-size: 15px; display: flex; align-items: center">选择套餐</div>
选择套餐
</div>
</van-cell> </van-cell>
<div class="selection" style="background: #FFF" <div class="selection" style="background: #fff" v-for="(subject,sidx) in projectInfo.welfareProjectSubjects">
v-for="(subject,sidx) in projectInfo.welfareProjectSubjects"> <div style="display: flex; width: 100%; padding: 10px 0" v-for="(option, oidx) in subject.options">
<div style="display: flex;width: 100%;padding: 10px 0" <div style="width: 120px; height: 100px; display: flex; justify-content: center; align-items: center">
v-for="(option, oidx) in subject.options"> <van-image
<div style="width: 120px;height: 100px;display: flex;justify-content: center;align-items: center"> :src="FILE_STREAM_PREVIEW_ADDRESS+'?id='+option.imgUrl"
<van-image :src="FILE_STREAM_PREVIEW_ADDRESS+'?id='+option.imgUrl" fit="contain"
fit="contain" style="width: 100px; height: 100px; border-radius: 10px"
style="width: 100px;height: 100px;border-radius: 10px"></van-image> ></van-image>
<!-- @click="vant.ImagePreview([CREATE_PREVIEW_URL(option.imgUrl)])"--> <!-- @click="vant.ImagePreview([CREATE_PREVIEW_URL(option.imgUrl)])"-->
</div> </div>
<div class="right_content"> <div class="right_content">
<div style="display: flex;justify-content: space-between;align-items: center;font-size: 14px"> <div style="display: flex; justify-content: space-between; align-items: center; font-size: 14px">
<div style="width: 100%">{{option.optionName}}</div> <div style="width: 100%">{{option.optionName}}</div>
</div> </div>
<div class="optionDesc"> <div class="optionDesc">
<template v-if="option.supplier"> <template v-if="option.supplier">服务专线:{{option.supplier}}</template>
服务专线:{{option.supplier}}
</template>
</div> </div>
<div class="optionDesc" v-if="option.simpleDesc"> <div class="optionDesc" v-if="option.simpleDesc">备注:{{option.simpleDesc}}</div>
备注:{{option.simpleDesc}} <div style="position: absolute; right: 10px; bottom: 0; left: 0; display: flex; justify-content: space-between">
</div> <div @click="openViewDesc(option.description)" style="width: 70px; font-size: 13px; color: #918a8a; text-align: right">
<div style="position: absolute;right: 10px;bottom: 0;left: 0;display: flex;justify-content: space-between">
<div @click="openViewDesc(option.description)"
style="width: 70px;font-size: 13px;color: #918a8a;text-align: right">
套餐详情 套餐详情
</div> </div>
<van-stepper :default-value="0" <van-stepper
:disabled="confirmButtonInfo.disabled" :default-value="0"
:min="0" :disabled="confirmButtonInfo.disabled"
@change="(value)=>{numChange(value,option,oidx)}" :min="0"
async-change @change="(value)=>{numChange(value,option,oidx)}"
button-size="20" async-change
disable-input button-size="20"
integer disable-input
theme="round" integer
v-model="option.selectNum"></van-stepper> theme="round"
v-model="option.selectNum"
></van-stepper>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<van-submit-bar :button-text="confirmButtonInfo.text" <van-submit-bar
@submit="confirmSelect" :button-text="confirmButtonInfo.text"
tip="您可以在福利选择截至时间之前修改福利套餐" @submit="confirmSelect"
tip-icon="info-o"> tip="您可以在福利选择截至时间之前修改福利套餐"
<div style="width: calc(100% - 110px);"> tip-icon="info-o"
<div style="width: 25px;height: 25px;position: relative"> >
<div style="width: calc(100% - 110px)">
<div style="width: 25px; height: 25px; position: relative">
<van-icon name="shopping-cart-o" size="25"></van-icon> <van-icon name="shopping-cart-o" size="25"></van-icon>
<div class="van-info"> <div class="van-info">{{sumSelectNum}}</div>
{{sumSelectNum}}
</div>
</div> </div>
</div> </div>
</van-submit-bar> </van-submit-bar>
</template> </template>
<van-popup :style="{ height: '70%' }" closeable position="bottom" safe-area-inset-bottom <van-popup :style="{ height: '70%' }" closeable position="bottom" safe-area-inset-bottom v-model="selectAddressPopup">
v-model="selectAddressPopup">
<div style="height: 100%"> <div style="height: 100%">
<div style="font-size: 15px;font-weight: bold;text-align: center;padding-top: 16px;"> <div style="font-size: 15px; font-weight: bold; text-align: center; padding-top: 16px">配送至</div>
配送至
</div>
<template v-if="addressList && addressList.length>0"> <template v-if="addressList && addressList.length>0">
<van-cell @click="addressClick(item);selectAddressPopup=false" clickable <van-cell @click="addressClick(item);selectAddressPopup=false" clickable icon="location-o" v-for="item in addressList">
icon="location-o" <template #title>{{item.address}}</template>
v-for="item in addressList">
<template #title>
{{item.address}}
</template>
<template #label> <template #label>
<div>{{"地区:" + item.province + item.city + item.county}}</div> <div>{{"地区:" + item.province + item.city + item.county}}</div>
<div>{{"收件人:" + item.name}}</div> <div>{{"收件人:" + item.name}}</div>
@@ -278,59 +282,48 @@ layout("/mobile/platform.html"){
<van-empty description="暂无地址" v-else></van-empty> <van-empty description="暂无地址" v-else></van-empty>
<div style="position: absolute;bottom: 0;left: 0;box-sizing: border-box;width: 100%;padding: 0 16px;background: #fff"> <div style="position: absolute; bottom: 0; left: 0; box-sizing: border-box; width: 100%; padding: 0 16px; background: #fff">
<van-button @click="openAddressManage" block round <van-button @click="openAddressManage" block round style="height: 40px; margin: 5px 0" type="danger">地址管理</van-button>
style="height: 40px;margin: 5px 0"
type="danger">
地址管理
</van-button>
</div> </div>
</div> </div>
</van-popup> </van-popup>
<van-popup :style="{ height: '100%',width: '100%'}" position="right" safe-area-inset-bottom <van-popup :style="{ height: '100%',width: '100%'}" position="right" safe-area-inset-bottom v-model="descPopup">
v-model="descPopup">
<van-sticky> <van-sticky>
<van-nav-bar @click-left="descPopup=false" left-arrow <van-nav-bar @click-left="descPopup=false" left-arrow title="详情"></van-nav-bar>
title="详情"></van-nav-bar>
</van-sticky> </van-sticky>
<div @click="descImgClick" class="desc" style="padding: 20px;" v-html="desc"></div> <div @click="descImgClick" class="desc" style="padding: 20px" v-html="desc"></div>
</van-popup> </van-popup>
<van-popup :close-on-click-overlay="false" <van-popup
:style="{ height: '90vh', 'overflow-y':'auto', background:'#f9f9f9'}" :close-on-click-overlay="false"
closeable :style="{ height: '90vh', 'overflow-y':'auto', background:'#f9f9f9'}"
position="bottom" closeable
round position="bottom"
safe-area-inset-bottom round
v-model="confirmPopup"> safe-area-inset-bottom
v-model="confirmPopup"
>
<div> <div>
<!--选择的信息--> <!--选择的信息-->
<div class="van-cell-group--inset"> <div class="van-cell-group--inset">
<van-cell> <van-cell>
<van-icon class="van-cell__left-icon" color="red" name="location" <van-icon class="van-cell__left-icon" color="red" name="location" slot="icon"></van-icon>
slot="icon"></van-icon> <div slot="title" style="font-weight: bold; font-size: 15px">已选福利</div>
<div slot="title" style="font-weight: bold;font-size: 15px">已选福利</div>
</van-cell> </van-cell>
<van-cell style="padding: 0" v-for="(item,index) in selectedOptions"> <van-cell style="padding: 0" v-for="(item,index) in selectedOptions">
<van-card <van-card
:key="item.id" :key="item.id"
:num="item.selectNum" :num="item.selectNum"
:thumb="FILE_STREAM_PREVIEW_ADDRESS+'?id='+item.imgUrl" :thumb="FILE_STREAM_PREVIEW_ADDRESS+'?id='+item.imgUrl"
:title="item.optionName" :title="item.optionName"
desc="" desc=""
style="border-radius: 8px;background: #FFFFFF" style="border-radius: 8px; background: #ffffff"
></van-card> ></van-card>
<div class="van-hairline--top"></div> <div class="van-hairline--top"></div>
<van-cell @click="openShoppingPopup(item,index)" is-link title="收货门店" <van-cell @click="openShoppingPopup(item,index)" is-link title="收货门店" v-if="item.shoppingId">
v-if="item.shoppingId"> <template #label>{{item.receiveAddress?item.receiveAddress:'暂未选择'}}</template>
<template #label>
{{item.receiveAddress?item.receiveAddress:'暂未选择'}}
</template>
</van-cell> </van-cell>
</van-cell> </van-cell>
</div> </div>
@@ -338,17 +331,13 @@ layout("/mobile/platform.html"){
<!--邮寄到家 填写收货地址--> <!--邮寄到家 填写收货地址-->
<div class="van-cell-group--inset" v-if="projectInfo.provideMode===3"> <div class="van-cell-group--inset" v-if="projectInfo.provideMode===3">
<van-cell> <van-cell>
<van-icon class="van-cell__left-icon" color="red" name="location" <van-icon class="van-cell__left-icon" color="red" name="location" slot="icon"></van-icon>
slot="icon"></van-icon> <div slot="title" style="font-weight: bold; font-size: 15px">收货地址</div>
<div slot="title" style="font-weight: bold;font-size: 15px">收货地址</div>
</van-cell> </van-cell>
<van-cell @click="clickSelectAddressPopup" class="address-cell" is-link <van-cell @click="clickSelectAddressPopup" class="address-cell" is-link title="">
title="">
<template> <template>
<span v-if="$.isEmptyObject(selectAddress)">请选择地址</span> <span v-if="$.isEmptyObject(selectAddress)">请选择地址</span>
<span v-else> <span v-else>{{selectAddress}}</span>
{{selectAddress}}
</span>
</template> </template>
</van-cell> </van-cell>
</div> </div>
@@ -357,69 +346,58 @@ layout("/mobile/platform.html"){
<div class="van-cell-group--inset" v-if="projectInfo.signMode===2"> <div class="van-cell-group--inset" v-if="projectInfo.signMode===2">
<van-cell> <van-cell>
<template #title> <template #title>
<div style="font-weight: bold;font-size: 15px">电子签名</div> <div style="font-weight: bold; font-size: 15px">电子签名</div>
</template> </template>
</van-cell> </van-cell>
<van-cell title=""> <van-cell title="">
<template #label> <template #label>
<mobile-sign :is_value_base64="false" prefix="welfare" ref="signature" <mobile-sign :is_value_base64="false" prefix="welfare" ref="signature" v-model="signData"></mobile-sign>
v-model="signData"></mobile-sign>
</template> </template>
</van-cell> </van-cell>
</div> </div>
<div style="padding: 10px 16px;left: 0;right: 0;bottom: 0;background: #FFFFFF"> <div style="padding: 10px 16px; left: 0; right: 0; bottom: 0; background: #ffffff">
<van-button @click="submitSelect" round style="width: 100%" type="danger">提交 <van-button @click="submitSelect" round style="width: 100%" type="danger">提交</van-button>
</van-button>
</div> </div>
</div> </div>
</van-popup> </van-popup>
<van-popup :style="{ height: '90vh', 'overflow-y':'auto', background:'#f9f9f9'}" <van-popup
closeable :style="{ height: '90vh', 'overflow-y':'auto', background:'#f9f9f9'}"
position="bottom" closeable
round position="bottom"
safe-area-inset-bottom round
v-model="shoppingPopup"> safe-area-inset-bottom
v-model="shoppingPopup"
>
<div> <div>
<div style="margin-top: 45px"> <div style="margin-top: 45px">
<van-search <van-search @search="onSearchShoppingAddress" placeholder="请输入门店关键词" show-action v-model="shoppingAddress">
@search="onSearchShoppingAddress"
placeholder="请输入门店关键词"
show-action
v-model="shoppingAddress">
<template #action> <template #action>
<div @click="onSearchShoppingAddress">搜索</div> <div @click="onSearchShoppingAddress">搜索</div>
</template> </template>
</van-search> </van-search>
<div class="van-cell-group--inset" <div class="van-cell-group--inset" v-if="offlineStoresOption && offlineStoresOption.length>0">
v-if="offlineStoresOption&&offlineStoresOption.length>0"> <van-cell icon="location-o" class="custom-cell" @click="addShopping(item.address)" v-for="item in offlineStoresOption">
<van-cell @click="addShopping(item.address)" is-link
v-for="item in offlineStoresOption"
>
{{item.address}} {{item.address}}
</van-cell> </van-cell>
</div> </div>
<div v-else> <div v-else>
<van-empty description="描述文字" style="height: calc(100% - 180px);"></van-empty> <van-empty description="描述文字" style="height: calc(100% - 180px)"></van-empty>
</div> </div>
</div> </div>
</div> </div>
</van-popup> </van-popup>
</div> </div>
<script> <script>
<!--#include("/mobile/welfare/include/mixins.js"){}#--> <!--#include("/mobile/welfare/include/mixins.js"){}#-->
const vue = new Vue({ const vue = new Vue({
el: '#app', el: "#app",
mixins: [mobileMixins, welfareMixins], mixins: [mobileMixins, welfareMixins],
components: { components: {
'mobile-sign': httpVueLoader('/components/sign/mobileSign.vue'), "mobile-sign": httpVueLoader("/components/sign/mobileSign.vue")
}, },
data() { data() {
return { return {
@@ -441,13 +419,16 @@ layout("/mobile/platform.html"){
shoppingAddress: "", shoppingAddress: "",
optionIndex: null, optionIndex: null,
optionData: {}, optionData: {},
clickUpOrDown: false
} }
}, },
computed: { computed: {
sumSelectNum() { sumSelectNum() {
if (this.projectInfo && this.projectInfo.welfareProjectSubjects) { if (this.projectInfo && this.projectInfo.welfareProjectSubjects) {
return this.projectInfo.welfareProjectSubjects[0].options.map(v => v.selectNum).reduce((accumulator, currentValue) => accumulator + currentValue, 0) return this.projectInfo.welfareProjectSubjects[0].options
.map((v) => v.selectNum)
.reduce((accumulator, currentValue) => accumulator + currentValue, 0)
} }
return 0 return 0
}, },
@@ -465,92 +446,129 @@ layout("/mobile/platform.html"){
}, },
confirmButtonInfo() { confirmButtonInfo() {
if (this.projectInfo) { if (this.projectInfo) {
const {choiceTimeEnd, choiceTimeStart, overdueChoiceTimeEnd} = this.projectInfo const { choiceTimeEnd, choiceTimeStart, overdueChoiceTimeEnd } = this.projectInfo
const now = moment().valueOf() const now = moment().valueOf()
if (overdueChoiceTimeEnd == null || overdueChoiceTimeEnd === '') { if (overdueChoiceTimeEnd == null || overdueChoiceTimeEnd === "") {
if (now > moment(choiceTimeStart).valueOf() && now < moment(choiceTimeEnd).valueOf()) { if (now > moment(choiceTimeStart).valueOf() && now < moment(choiceTimeEnd).valueOf()) {
return {text: this.isSelect ? '确定修改' : '确定选择', disabled: false} return { text: this.isSelect ? "选好了,下一步" : "选好了,下一步", disabled: false }
} else if (now > moment(choiceTimeEnd).valueOf()) { } else if (now > moment(choiceTimeEnd).valueOf()) {
return {text: '选择已结束', disabled: true} return { text: "选择已结束", disabled: true }
} else if (now < moment(choiceTimeStart).valueOf()) { } else if (now < moment(choiceTimeStart).valueOf()) {
return {text: '选择未开始', disabled: true} return { text: "选择未开始", disabled: true }
} }
} else { } else {
//已选择了不能再动了 //已选择了不能再动了
if (this.isSelect) { if (this.isSelect) {
if (moment(this.selectTime).valueOf() > moment(choiceTimeEnd).valueOf() && now < moment(overdueChoiceTimeEnd).valueOf()) { if (moment(this.selectTime).valueOf() > moment(choiceTimeEnd).valueOf() && now < moment(overdueChoiceTimeEnd).valueOf()) {
return {text: '确定修改', disabled: false} return { text: "下一步", disabled: false }
} }
return {text: '选择已结束', disabled: true} return { text: "选择已结束", disabled: true }
} else { } else {
if (now > moment(choiceTimeStart).valueOf() && now < moment(overdueChoiceTimeEnd).valueOf()) { if (now > moment(choiceTimeStart).valueOf() && now < moment(overdueChoiceTimeEnd).valueOf()) {
return {text: this.isSelect ? '确定修改' : '确定选择', disabled: false} return { text: this.isSelect ? "选好了,下一步" : "选好了,下一步", disabled: false }
} else if (now > moment(overdueChoiceTimeEnd).valueOf()) { } else if (now > moment(overdueChoiceTimeEnd).valueOf()) {
return {text: '选择已结束', disabled: true} return { text: "选择已结束", disabled: true }
} else if (now < moment(choiceTimeStart).valueOf()) { } else if (now < moment(choiceTimeStart).valueOf()) {
return {text: '选择未开始', disabled: true} return { text: "选择未开始", disabled: true }
} }
} }
} }
} }
return {text: '', disabled: true} return { text: "", disabled: true }
}, },
selectedOptions() { selectedOptions() {
if (this.projectInfo && this.projectInfo.welfareProjectSubjects) { if (this.projectInfo && this.projectInfo.welfareProjectSubjects) {
return this.projectInfo.welfareProjectSubjects[0].options.filter(v => v.selectNum >= 1) return this.projectInfo.welfareProjectSubjects[0].options.filter((v) => v.selectNum >= 1)
} }
return [] return []
} }
}, },
methods: { methods: {
addShopping(address) { addShopping(address) {
this.$set(this.projectInfo.welfareProjectSubjects[0].options[this.optionIndex], 'receiveAddress', address) this.$set(this.projectInfo.welfareProjectSubjects[0].options[this.optionIndex], "receiveAddress", address)
this.projectInfo.welfareProjectSubjects[0].options[this.optionIndex].receiveAddress = address
this.shoppingPopup = false this.shoppingPopup = false
}, },
async onSearchShoppingAddress() { async onSearchShoppingAddress() {
const data = await this.getShoppingType() const data = await this.getShoppingType()
const shopping = data.find(d => d.id === this.optionData.shoppingId) const shopping = data.find((d) => d.id === this.optionData.shoppingId)
if (this.shoppingAddress) { if (this.shoppingAddress) {
this.offlineStoresOption = shopping.offlineStores.filter(s => s.address.includes(this.shoppingAddress)) this.offlineStoresOption = shopping.offlineStores.filter((s) => s.address.includes(this.shoppingAddress))
} else { } else {
this.offlineStoresOption = shopping.offlineStores this.offlineStoresOption = shopping.offlineStores
} }
}, },
openShoppingPopup(item, optionIndex) { openShoppingPopup(item, optionIndex) {
this.optionData = item this.optionData = item
const shopping = this.shoppingTypeOptions.find(v => v.id === item.shoppingId) const shopping = this.shoppingTypeOptions.find((v) => v.id === item.shoppingId)
this.offlineStoresOption = shopping.offlineStores this.offlineStoresOption = shopping.offlineStores
this.optionIndex = optionIndex this.optionIndex = optionIndex
this.shoppingAddress = "" this.shoppingAddress = ""
this.shoppingPopup = true this.shoppingPopup = true
}, },
editAddress(item) {
location.replace("/mobile/welfare/mine/addressEdit?projectId=" + this.projectId + "&id=" + item.id)
window.sessionStorage.setItem("welfareProjectId", this.projectId)
const formData = {
projectInfo: this.projectInfo,
signData: this.signData || null
}
window.sessionStorage.setItem("welfareProjectSelectInfo" + "${@shiro.getPrincipalProperty('loginname')}", JSON.stringify(formData))
},
deleteAddress(item) {
this.selectAddressPopup = true
// 确认要删除该地址吗
this.$dialog
.confirm({
title: "提示",
message: "确认要删除该地址吗"
})
.then(async () => {
const loading = this.$toast.loading({
message: "删除中...",
forbidClick: true,
overlay: true,
duration: 0
})
const resp = await $.post("/mobile/welfare/mine/deleteAddress", { id: item.id })
loading.close()
if (resp.code === 0) {
this.$toast.success(resp.msg)
}
await this.selectAddressList()
if (this.addressList && this.addressList.length > 0) {
const resp = this.addressList.find((v) => v.isDefault)
this.addressClick(resp)
} else {
this.selectAddress = ""
}
this.selectAddressPopup = true
})
.catch(() => {
this.selectAddressPopup = true
})
},
//数量更改 //数量更改
numChange(value, option, optionIndex) { numChange(value, option, optionIndex) {
const { const { isCheckBox, multiSelectNum, singleOptionSupportMultipleSelection } = this.projectInfo
isCheckBox, if (isCheckBox === "checkBox") {
multiSelectNum,
singleOptionSupportMultipleSelection
} = this.projectInfo
if (isCheckBox === 'checkBox') {
//判断是否支持单个多选 //判断是否支持单个多选
if (!singleOptionSupportMultipleSelection && value > 1) { if (!singleOptionSupportMultipleSelection && value > 1) {
this.$set(this.projectInfo.welfareProjectSubjects[0].options[optionIndex], 'selectNum', 1) this.$set(this.projectInfo.welfareProjectSubjects[0].options[optionIndex], "selectNum", 1)
this.$toast('此套餐最多只能选择1份') this.$toast("此套餐最多只能选择1份")
return; return
} }
} }
//获取用户当前选择的数量 //获取用户当前选择的数量
const selectNums = this.projectInfo.welfareProjectSubjects[0].options.map(v => v.selectNum) const selectNums = this.projectInfo.welfareProjectSubjects[0].options.map((v) => v.selectNum)
const sum = selectNums.reduce((accumulator, currentValue) => accumulator + currentValue, 0) const sum = selectNums.reduce((accumulator, currentValue) => accumulator + currentValue, 0)
if (sum > multiSelectNum) { if (sum > multiSelectNum) {
this.$set(this.projectInfo.welfareProjectSubjects[0].options[optionIndex], 'selectNum', value - 1) this.$set(this.projectInfo.welfareProjectSubjects[0].options[optionIndex], "selectNum", value - 1)
this.$toast('此次福利最多只能选择' + multiSelectNum + '份') this.$toast("此次福利最多只能选择" + multiSelectNum + "份")
} }
}, },
//确定选择 //确定选择
@@ -560,15 +578,11 @@ layout("/mobile/platform.html"){
return return
} }
const { const { isCheckBox, multiSelectNum, singleOptionSupportMultipleSelection } = this.projectInfo
isCheckBox,
multiSelectNum,
singleOptionSupportMultipleSelection
} = this.projectInfo
if (isCheckBox === "checkBox") { if (isCheckBox === "checkBox") {
if (this.sumSelectNum < multiSelectNum) { if (this.sumSelectNum < multiSelectNum) {
//用户没有选择完 //用户没有选择完
this.$toast('一共可以选择' + multiSelectNum + '份,您目前只选择了' + this.sumSelectNum + '份,快去选择吧!') this.$toast("一共可以选择" + multiSelectNum + "份,您目前只选择了" + this.sumSelectNum + "份,快去选择吧!")
return return
} }
} }
@@ -583,46 +597,43 @@ layout("/mobile/platform.html"){
if (this.projectInfo.signMode === 2 && this.isSelect && this.userSelection) { if (this.projectInfo.signMode === 2 && this.isSelect && this.userSelection) {
this.signData = this.userSelection[0].userSign this.signData = this.userSelection[0].userSign
} }
}, },
//提交选择 //提交选择
async submitSelect() { async submitSelect() {
if (this.projectInfo.provideMode === 3) { if (this.projectInfo.provideMode === 3) {
if (this.selectAddress == null || this.selectAddress === '') { if (this.selectAddress == null || this.selectAddress === "") {
this.$modal.msg("请填写您的收货地址") this.$modal.msg("请填写您的收货地址")
return return
} }
} }
if (this.projectInfo.signMode === 2) { if (this.projectInfo.signMode === 2) {
if (this.signData == null || this.signData === '') { if (this.signData == null || this.signData === "") {
this.$modal.msg("请签名") this.$modal.msg("请签名")
return return
} }
} }
const notReceiveAddress = [] const notReceiveAddress = []
const formData = this.projectInfo.welfareProjectSubjects[0].options.filter(v => v.selectNum >= 1).map(v => { const formData = this.projectInfo.welfareProjectSubjects[0].options
if (v.shoppingId && !v.receiveAddress) { .filter((v) => v.selectNum >= 1)
notReceiveAddress.push(v.optionName) .map((v) => {
} if (v.shoppingId && !v.receiveAddress) {
return { notReceiveAddress.push(v.optionName)
welfareId: this.projectId, }
subjectId: v.subjectId, return {
selectOptionId: v.id, welfareId: this.projectId,
receiveAddress: this.projectInfo.provideMode === 3 ? this.selectAddress : v.receiveAddress, subjectId: v.subjectId,
userSign: this.signData, selectOptionId: v.id,
selectNum: v.selectNum receiveAddress: this.projectInfo.provideMode === 3 ? this.selectAddress : v.receiveAddress,
} userSign: this.signData,
}) selectNum: v.selectNum
}
})
if (notReceiveAddress.length > 0) { if (notReceiveAddress.length > 0) {
this.$modal.msg("请填写收货门店:" + notReceiveAddress.join(",")) this.$modal.msg("请填写收货门店:" + notReceiveAddress.join(","))
return return
} }
const { const { code, msg, data } = await $.post("/platform/welfare/userChoose/confirmSelect", {
code,
msg,
data
} = await $.post('/platform/welfare/userChoose/confirmSelect', {
welfareUserSelections: JSON.stringify(formData), welfareUserSelections: JSON.stringify(formData),
projectId: this.projectId projectId: this.projectId
}) })
@@ -638,24 +649,29 @@ layout("/mobile/platform.html"){
//查看详情 //查看详情
openViewDesc(desc) { openViewDesc(desc) {
if (desc == null || desc.length === 0) { if (desc == null || desc.length === 0) {
this.$toast('没有更多了') this.$toast("没有更多了")
return return
} }
this.desc = desc this.desc = desc
this.descPopup = true this.descPopup = true
}, },
descImgClick(e) { descImgClick(e) {
if (e.target.tagName === 'IMG') { if (e.target.tagName === "IMG") {
vant.ImagePreview([e.target.src]) vant.ImagePreview([e.target.src])
} }
}, },
//地址管理 //地址管理
openAddressManage() { openAddressManage() {
location.replace('/mobile/welfare/mine/address') location.replace("/mobile/welfare/mine/addressEdit?projectId=" + this.projectId)
window.sessionStorage.setItem('welfareProjectId', this.projectId) window.sessionStorage.setItem("welfareProjectId", this.projectId)
const formData = {
projectInfo: this.projectInfo,
signData: this.signData || null
}
window.sessionStorage.setItem("welfareProjectSelectInfo" + "${@shiro.getPrincipalProperty('loginname')}", JSON.stringify(formData))
}, },
clickSelectAddressPopup() { clickSelectAddressPopup() {
@@ -665,12 +681,12 @@ layout("/mobile/platform.html"){
//地址列表点击 //地址列表点击
addressClick(item) { addressClick(item) {
const {province, city, county, address, name, tel} = item const { province, city, county, address, name, tel } = item
this.selectAddress = "收货地址:" + province + city + county + address + "," + "收件人:" + name + "," + "联系方式:" + tel this.selectAddress = "收货地址:" + province + city + county + address + "," + "收件人:" + name + "," + "联系方式:" + tel
}, },
async getProjectInfo() { async getProjectInfo() {
const resp = await $.get('/platform/welfare/common/findOne', {projectId: this.projectId}) const resp = await $.get("/platform/welfare/common/findOne", { projectId: this.projectId })
if (resp.code === 0) { if (resp.code === 0) {
resp.data.multiSelectNum = resp.data.multiSelectNum ? resp.data.multiSelectNum : 1 resp.data.multiSelectNum = resp.data.multiSelectNum ? resp.data.multiSelectNum : 1
this.projectInfo = resp.data this.projectInfo = resp.data
@@ -680,15 +696,15 @@ layout("/mobile/platform.html"){
//获取用户选择的数据 //获取用户选择的数据
async getUserSelection(projectId) { async getUserSelection(projectId) {
const resp = await $.get('/platform/welfare/mine/getUserSelection', {projectId: projectId}) const resp = await $.get("/platform/welfare/mine/getUserSelection", { projectId: projectId })
this.userSelection = resp.data this.userSelection = resp.data
this.echoUserSelection() this.echoUserSelection()
}, },
//回显用户选择的数据 //回显用户选择的数据
echoUserSelection() { echoUserSelection() {
this.projectInfo.welfareProjectSubjects[0].options.forEach(v => { this.projectInfo.welfareProjectSubjects[0].options.forEach((v) => {
const option = this.userSelection.find(x => x.selectOptionId === v.id) const option = this.userSelection.find((x) => x.selectOptionId === v.id)
if (option) { if (option) {
v.selectNum = option.selectNum v.selectNum = option.selectNum
v.receiveAddress = option.receiveAddress v.receiveAddress = option.receiveAddress
@@ -698,25 +714,36 @@ layout("/mobile/platform.html"){
async getShoppingType() { async getShoppingType() {
const resp = await $.get("/platform/shoppingType/apply/getShoppingType") const resp = await $.get("/platform/shoppingType/apply/getShoppingType")
return resp.data return resp.data
}
},
}, },
async created() { async created() {
const id = GetQueryString("projectId") const id = GetQueryString("projectId")
if (!id) return if (!id) return
this.projectId = id this.projectId = id
this.getProjectInfo()
this.shoppingTypeOptions = await this.getShoppingType() this.shoppingTypeOptions = await this.getShoppingType()
// this.getChoice() // this.getChoice()
getEnumOptions("WelfareProvideMode").then(res => { getEnumOptions("WelfareProvideMode").then((res) => {
this.welfareProvideMode = res this.welfareProvideMode = res
}) })
getEnumOptions("WelfareSignMode").then(res => { getEnumOptions("WelfareSignMode").then((res) => {
this.welfareSignMode = res this.welfareSignMode = res
}) })
},
const loginname = "${@shiro.getPrincipalProperty('loginname')}"
const formData = window.sessionStorage.getItem("welfareProjectSelectInfo" + loginname)
if (formData) {
const resp = JSON.parse(formData)
this.projectInfo = resp.projectInfo
this.signData = resp.signData
this.confirmSelect()
window.sessionStorage.removeItem("welfareProjectSelectInfo" + loginname)
// this.selectAddressPopup = true
} else {
this.getProjectInfo()
}
}
}) })
window.addEventListener('pageshow', e => { window.addEventListener("pageshow", (e) => {
if (e.persisted || (window.performance && window.performance.navigation.type === 2)) { if (e.persisted || (window.performance && window.performance.navigation.type === 2)) {
vue.init() vue.init()
} }
@@ -12,98 +12,97 @@ layout("/mobile/platform.html"){
<div id="app" v-cloak> <div id="app" v-cloak>
<van-sticky> <van-sticky>
<van-nav-bar title="地址管理" left-arrow placeholder fixed <van-nav-bar title="地址管理" left-arrow placeholder fixed @click-left="back()"></van-nav-bar>
@click-left="location.replace('/mobile/welfare/mine/address')"></van-nav-bar>
</van-sticky> </van-sticky>
<div v-if="vLoading && !vLoading.value"> <div v-if="vLoading && !vLoading.value">
<van-address-edit <van-address-edit
ref="address" ref="address"
:area-list="areaList" :area-list="areaList"
:show-delete="addressId" :show-delete="addressId"
:address-info="addressInfo" :address-info="addressInfo"
show-set-default show-set-default
show-search-result show-search-result
tel-maxlength="11" tel-maxlength="11"
:area-columns-placeholder="['请选择', '请选择', '请选择']" :area-columns-placeholder="['请选择', '请选择', '请选择']"
@save="onSave" @save="onSave"
@delete="onDelete" @delete="onDelete"
></van-address-edit> ></van-address-edit>
</div> </div>
</div> </div>
<script> <script>
<!--#include("/mobile/welfare/include/areaList.js"){};include("/mobile/welfare/include/mixins.js"){}#--> <!--#include("/mobile/welfare/include/areaList.js"){};include("/mobile/welfare/include/mixins.js"){}#-->
const vue = new Vue({ const vue = new Vue({
el: '#app', el: "#app",
mixins: [mobileMixins, welfareMixins], mixins: [mobileMixins, welfareMixins],
data() { data() {
return { return {
projectId: GetQueryString("projectId"),
areaList: areaList, areaList: areaList,
addressInfo: {}, addressInfo: {},
addressId: null addressId: null
}; }
}, },
methods: { methods: {
back() {
if (this.projectId) {
// pjaxReplace("/mobile/welfare/mine/address?projectId=" + this.projectId)
pjaxReplace("/mobile/welfare/list/receive?projectId=" + this.projectId)
} else {
pjaxReplace("/mobile/welfare/mine/address")
}
},
async onSave(content) { async onSave(content) {
const loading = this.$toast.loading({ const loading = this.$toast.loading({
message: '保存中...', message: "保存中...",
forbidClick: true, forbidClick: true,
overlay: true, overlay: true,
duration: 0 duration: 0
}) })
content.userName = content.name content.userName = content.name
const resp = await $.post('/mobile/welfare/mine/doSaveUserAddress', content) const resp = await $.post("/mobile/welfare/mine/doSaveUserAddress", content)
loading.close() loading.close()
if (resp.code === 0) { if (resp.code === 0) {
this.$toast.success(resp.msg) this.$toast.success(resp.msg)
setTimeout(() => { this.$nextTick(() => {
let welfareProjectId = window.sessionStorage.getItem("welfareProjectId"); this.back()
if (welfareProjectId) { })
location.replace('/mobile/welfare/list/receive?projectId=' + welfareProjectId)
window.sessionStorage.removeItem("welfareProjectId");
} else {
location.replace('/mobile/welfare/mine/address')
}
}, 1000)
} }
}, },
async onDelete(content) { async onDelete(content) {
const loading = this.$toast.loading({ const loading = this.$toast.loading({
message: '删除中...', message: "删除中...",
forbidClick: true, forbidClick: true,
overlay: true, overlay: true,
duration: 0 duration: 0
}) })
const resp = await $.post('/mobile/welfare/mine/deleteAddress', {id: content.id}) const resp = await $.post("/mobile/welfare/mine/deleteAddress", { id: content.id })
loading.close() loading.close()
if (resp.code === 0) { if (resp.code === 0) {
this.$toast.success(resp.msg) this.$toast.success(resp.msg)
setTimeout(() => { this.$nextTick(() => {
location.replace('/mobile/welfare/mine/address') this.back()
}, 1000) })
} }
} }
}, },
async created() { async created() {
this.startLoading() this.startLoading()
this.addressId = GetQueryString("id") === '' ? null : GetQueryString("id") this.addressId = GetQueryString("id") === "" ? null : GetQueryString("id")
if (this.addressId) { if (this.addressId) {
const resp = await $.get('/mobile/welfare/mine/findOneUserAddress', {id: this.addressId}) const resp = await $.get("/mobile/welfare/mine/findOneUserAddress", { id: this.addressId })
if (resp.code === 0) { if (resp.code === 0) {
this.addressInfo = resp.data this.addressInfo = resp.data
} }
this.closeLoading() this.closeLoading()
} else { } else {
this.addressInfo.name = "${@shiro.getPrincipalProperty('username')}"; this.addressInfo.name = "${@shiro.getPrincipalProperty('username')}"
this.closeLoading() this.closeLoading()
} }
/*this.areaList.province_list = {320000: "江苏省"} /*this.areaList.province_list = {320000: "江苏省"}
this.areaList.city_list = {320200: "无锡市"}*/ this.areaList.city_list = {320200: "无锡市"}*/
} }
}) })
</script> </script>
@@ -84,10 +84,10 @@ layout("/layouts/platform.html"){
<el-col :span="12"> <el-col :span="12">
<el-form-item label="申报基层工会" prop="fundsUnitName" v-if="formData.activity_type!=40003"> <el-form-item label="申报基层工会" prop="fundsUnitName" v-if="formData.activity_type!=40003">
<el-input placeholder="请输入基层工会名称" type="text" v-model="formData.fundsUnitName"></el-input> <el-input placeholder="请输入基层工会名称" readonly type="text" v-model="formData.fundsUnitName"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="申请协会" prop="clubId" v-else-if="formData.activity_type==40003"> <el-form-item label="申报文体协会" prop="clubId" v-else-if="formData.activity_type==40003">
<el-select @change="fundsUnitChange" placeholder="请选择申请协会" style="width: 100%" v-model="formData.clubId"> <el-select @change="fundsUnitChange" placeholder="请选择申报文体协会" style="width: 100%" v-model="formData.clubId">
<el-option <el-option
:key="item.id" :key="item.id"
:label="item.name+' ('+item.code+')'" :label="item.name+' ('+item.code+')'"
@@ -106,29 +106,6 @@ layout("/layouts/platform.html"){
v-model="formData.joinActivityNum" v-model="formData.joinActivityNum"
></el-input-number> ></el-input-number>
</el-form-item> </el-form-item>
<!-- <el-form-item prop="projectTypeCode" label="活动项目类型">
<el-select v-model="formData.projectTypeCode" placeholder="请选择活动类型"
style="width: 100%;">
<el-option
v-for="item in projectType"
:key="item.id"
:label="item.name+' ('+item.code+')'"
:value="item.code">
</el-option>
</el-select>
</el-form-item>-->
<!--<el-form-item label="活动经费类型" prop="projectJfCode">
<el-select placeholder="选择活动主体类型自动选择" style="width: 100%" v-model="formData.projectJfCode">
<el-option
:key="item.id"
:label="item.name+' ('+item.code+')'"
:value="item.code"
disabled
v-for="item in projectJfType"
></el-option>
</el-select>
</el-form-item>-->
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
@@ -155,7 +132,7 @@ layout("/layouts/platform.html"){
<el-form-item label="预算总费用" prop="funds_money"> <el-form-item label="预算总费用" prop="funds_money">
<el-input-number <el-input-number
disabled disabled
placeholder="输入物品单价自动计算" placeholder="输入预算费用自动计算"
:precision="2" :precision="2"
style="width: 100%" style="width: 100%"
v-model="formData.funds_money" v-model="formData.funds_money"
@@ -366,19 +343,10 @@ layout("/layouts/platform.html"){
} }
}, },
async getProjectCodeChange(val) { async getProjectCodeChange(val) {
this.$set(this.formData, "fundsUnitName", null)
await this.generateProjectCode(this.formData.activity_type) await this.generateProjectCode(this.formData.activity_type)
if (this.formData.activity_type == "40001") { if (this.formData.activity_type == "40002") {
const jfType = this.projectJfType.find((p) => p.code == "70001")
this.$set(this.formData, "projectJfCode", jfType ? jfType.code : null)
this.$set(this.formData, "fundsUnitName", "校工会")
} else if (this.formData.activity_type == "40002") {
const jfType = this.projectJfType.find((p) => p.code == "70002")
this.$set(this.formData, "projectJfCode", jfType ? jfType.code : null)
this.$set(this.formData, "fundsUnitName", '${@shiro.getPrincipalProperty("union").getUnionname()}') this.$set(this.formData, "fundsUnitName", '${@shiro.getPrincipalProperty("union").getUnionname()}')
} else if (this.formData.activity_type == "40003") { } else if (this.formData.activity_type == "40003") {
const jfType = this.projectJfType.find((p) => p.code == "70003")
this.$set(this.formData, "projectJfCode", jfType ? jfType.code : null)
const { data } = await $.get("/platform/jf/Funds/apply/getUserClub") const { data } = await $.get("/platform/jf/Funds/apply/getUserClub")
const clubList = await getClubs() const clubList = await getClubs()
const aa = clubList.filter((v) => { const aa = clubList.filter((v) => {
@@ -0,0 +1,17 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak></div>
<script>
new Vue({
el: "#app",
data() {
return {}
},
methods: {},
created() {}
})
</script>
<!--#
}
#-->
@@ -11,180 +11,181 @@ layout("/layouts/platform.html"){
</template> </template>
</table-tool> </table-tool>
<el-table :data="tableData" :size="tableSize" @sort-change="pageOrder" <el-table
ref="table" :data="tableData"
row-key="id" style="width: 100%" v-loading="tableLoading"> :size="tableSize"
@sort-change="pageOrder"
ref="table"
row-key="id"
style="width: 100%"
v-loading="tableLoading"
>
<el-table-column label="序号" type="index" width="80px"></el-table-column>
<el-table-column <el-table-column
label="序号" type="index" :key="column.prop"
width="80px"></el-table-column> :label="column.label"
<el-table-column :prop="column.prop"
:key="column.prop" :sortable="column.sortable"
:label="column.label" :width="column.width"
:prop="column.prop" show-overflow-tooltip
:sortable="column.sortable" v-for="column in tableColumns"
:width="column.width" show-overflow-tooltip >
v-for="column in tableColumns"> <template scope="{row}" v-if="column.prop=='address'">{{row.province}} {{row.city}} {{row.county}}</template>
<template scope="{row}" v-if="column.prop=='address'">
{{row.province}} {{row.city}} {{row.county}}
</template>
</el-table-column> </el-table-column>
<el-table-column align="center" fixed="right" header-align="center" <el-table-column align="center" fixed="right" header-align="center" label="操作" prop="userOnline" width="170px">
label="操作" prop="userOnline"
width="170px">
<template scope="{row}"> <template scope="{row}">
<el-button @click="openEdit(row)" size="mini" type="primary"> <el-button @click="openEdit(row)" size="mini" type="primary">修改</el-button>
修改 <el-button @click="doDelete(row.id)" size="mini" type="danger">删除</el-button>
</el-button>
<el-button @click="doDelete(row.id)" size="mini" type="danger">
删除
</el-button>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" fixed="right" header-align="center" label="" <el-table-column align="center" fixed="right" header-align="center" label="" prop="userOnline" width="170px">
prop="userOnline"
width="170px">
<template scope="{row}"> <template scope="{row}">
<span v-if="row.isDefault"> <span v-if="row.isDefault">
<el-tag type="danger">默认地址</el-tag></span> <el-tag type="danger">默认地址</el-tag>
</span>
<span v-else> <span v-else>
<el-button @click="doDefault(row)" size="mini" <el-button @click="doDefault(row)" size="mini" type="primary">设为默认</el-button>
type="primary">设为默认</el-button> </span>
</span>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
</el-card> </el-card>
</template> </template>
</guava> </guava>
<el-dialog <el-dialog title="收货地址" :close-on-click-modal="false" :visible.sync="dialogVisible" width="40%">
title="收货地址" <el-form :model="formData" label-position="right" :rules="formRules" label-suffix=":" label-width="120px" ref="addForm">
:close-on-click-modal="false"
:visible.sync="dialogVisible"
width="30%">
<el-form :model="formData" label-position="right"
label-suffix=":" label-width="120px" ref="addForm">
<el-row :gutter="60"> <el-row :gutter="60">
<el-col :span="24"> <el-col :span="24">
<el-form-item :rules="{required:true,message: '请选择地址信息', trigger: 'blur'}" <el-form-item label="地址信息" prop="addressList">
label="地址信息"
prop="addressList">
<el-cascader <el-cascader
:options="dzOptions" :options="dzOptions"
:props="{ expandTrigger: 'hover' }" :props="{ expandTrigger: 'hover' }"
@change="handleChange" @change="handleChange"
clearable clearable
placeholder="请选择地址信息" placeholder="请选择地址信息"
style="width: 100%" style="width: 100%"
v-model="formData.addressList"></el-cascader> v-model="formData.addressList"
></el-cascader>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="24"> <el-col :span="24">
<el-form-item <el-form-item label="详细地址" prop="addressDetail">
:rules="{required:true,message: '请填写您的详细地址', trigger: 'blur'}" <el-input
label="详细地址" maxlength="100"
prop="addressDetail"> placeholder="请输入详细地址信息,如道路、门牌号、小区、楼栋号、单元等信息"
<el-input maxlength="100" rows="3"
placeholder="请输入详细地址信息,如道路、门牌号、小区、楼栋号、单元等信息" show-word-limit
rows="3" type="textarea"
show-word-limit v-model="formData.addressDetail"
type="textarea" ></el-input>
v-model="formData.addressDetail"></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="24"> <el-col :span="24">
<el-form-item <el-form-item label="收货人姓名" prop="userName">
:rules="{required:true,message: '请填写收货人姓名', trigger: 'blur'}" <el-input maxlength="11" placeholder="请填写收货人姓名" v-model="formData.userName"></el-input>
label="收货人姓名"
prop="userName">
<el-input maxlength="11"
placeholder="请填写收货人姓名"
v-model="formData.userName"></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="24"> <el-col :span="24">
<el-form-item <el-form-item label="手机号码" prop="tel">
:rules="{required:true,message: '请填写手机号码', trigger: 'blur'}" <el-input maxlength="11" placeholder="请填写手机号码" clearable v-model="formData.tel"></el-input>
label="手机号码" </el-form-item>
prop="tel"> </el-col>
<el-input maxlength="11" placeholder="请填写手机号码"
type="tel" <el-col :span="24">
v-model="formData.tel"></el-input> <el-form-item label="是否默认" prop="isDefault">
<el-switch
v-model="formData.isDefault"
active-color="#13ce66"
inactive-color="#ff4949"
active-value="1"
inactive-value="0"
active-text="是"
inactive-text="否"
></el-switch>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
</el-form> </el-form>
<span class="dialog-footer" slot="footer"> <span class="dialog-footer" slot="footer">
<el-button @click="dialogVisible = false">取 消</el-button> <el-button @click="dialogVisible = false">取 消</el-button>
<el-button @click="doSaveUserAddress" type="primary">保存</el-button> <el-button @click="doSaveUserAddress" type="primary">保存</el-button>
</span> </span>
</el-dialog> </el-dialog>
</div> </div>
<script src="${base!}/assets/platform/js/chengSh.js"></script>
<script> <script>
const vue = new Vue({ const vue = new Vue({
el: '#app', el: "#app",
mixins: [initTableMixins], mixins: [initTableMixins],
data() { data() {
return { return {
dzOptions: chengShiList, dzOptions: chengShiList,
dialogVisible: false, dialogVisible: false,
tableColumns: [ tableColumns: [
{prop: 'userName', label: '收货人'}, { prop: "userName", label: "收货人" },
{prop: 'address', label: '所在地区'}, { prop: "address", label: "所在地区" },
{prop: 'addressDetail', label: '详细地址'}, { prop: "addressDetail", label: "详细地址" },
{prop: 'tel', label: '电话'}, { prop: "tel", label: "电话" }
] ],
formRules: {
addressList: [{ required: true, message: "请选择地址信息", trigger: ["blur", "change"] }],
addressDetail: [{ required: true, message: "请填写您的详细地址", trigger: ["blur", "change"] }],
userName: [{ required: true, message: "请填写收货人姓名", trigger: ["blur", "change"] }],
tel: [
{ required: true, message: "必填", trigger: ["blur", "change"] },
{ pattern: /^1[3-9]\d{9}$/, message: "请输入正确的手机号" }
]
}
} }
}, },
methods: { methods: {
pageData() { pageData() {
sublime.showLoadingbar(); sublime.showLoadingbar()
this.tableLoading = true this.tableLoading = true
$.post(loc() + "/selectUserAddress", this.pageForm, (data) => { $.post(
sublime.closeLoadingbar(); loc() + "/selectUserAddress",
this.tableLoading = false this.pageForm,
if (data.code === 0) { (data) => {
this.tableData = data.data; sublime.closeLoadingbar()
} else { this.tableLoading = false
this.$message.error(data.msg); if (data.code === 0) {
} this.tableData = data.data
}, "json"); } else {
this.$message.error(data.msg)
}
},
"json"
)
}, },
handleChange(val) { handleChange(val) {
if (val) { if (val) {
let provinceName = "" let provinceName = ""
let cityName = "" let cityName = ""
let countyName = "" let countyName = ""
const province = this.dzOptions.find(c => c.value === val[0]) const province = this.dzOptions.find((c) => c.value === val[0])
provinceName = province.label provinceName = province.label
const city = province.children.find(p => p.value === val[1]) const city = province.children.find((p) => p.value === val[1])
cityName = city.label cityName = city.label
if (val.length === 3) { if (val.length === 3) {
const county = city.children.find(p => p.value === val[2]) const county = city.children.find((p) => p.value === val[2])
countyName = county.label countyName = county.label
this.$set(this.formData, "areaCode", county.value) this.$set(this.formData, "areaCode", county.value)
}else{ } else {
this.$set(this.formData, "areaCode", city.value) this.$set(this.formData, "areaCode", city.value)
} }
this.$set(this.formData, "province", provinceName) this.$set(this.formData, "province", provinceName)
this.$set(this.formData, "city", cityName) this.$set(this.formData, "city", cityName)
this.$set(this.formData, "county", countyName) this.$set(this.formData, "county", countyName)
} }
}, },
openAddress() { openAddress() {
this.formData = {} this.formData = {
userName: "${@shiro.getPrincipalProperty('username')}",
tel: "${@shiro.getPrincipalProperty('mobile')}"
}
this.dialogVisible = true this.dialogVisible = true
if (this.$refs["addForm"]) if (this.$refs["addForm"]) this.$refs["addForm"].resetFields()
this.$refs["addForm"].resetFields();
}, },
doSaveUserAddress() { doSaveUserAddress() {
this.$refs["addForm"].validate(async (valid) => { this.$refs["addForm"].validate(async (valid) => {
@@ -194,72 +195,69 @@ layout("/layouts/platform.html"){
this.doSearch() this.doSearch()
this.$message({ this.$message({
message: resp.msg, message: resp.msg,
type: 'success' type: "success"
}); })
this.dialogVisible = false this.dialogVisible = false
} else { } else {
this.$message.error(resp.msg); this.$message.error(resp.msg)
} }
} }
}) })
}, },
doDelete(id) { doDelete(id) {
this.$confirm('此操作将永久删除该地址, 是否继续?', '提示', { this.$confirm("此操作将永久删除该地址, 是否继续?", "提示", {
confirmButtonText: '确定', confirmButtonText: "确定",
cancelButtonText: '取消', cancelButtonText: "取消",
type: 'warning' type: "warning"
}).then(async () => { }).then(async () => {
const resp = await $.post("/mobile/welfare/mine/deleteAddress", {id: id}) const resp = await $.post("/mobile/welfare/mine/deleteAddress", { id: id })
if (resp.code === 0) { if (resp.code === 0) {
this.doSearch() this.doSearch()
this.$message({ this.$message({
type: 'success', type: "success",
message: resp.msg message: resp.msg
}); })
} else { } else {
this.$message.error(resp.msg); this.$message.error(resp.msg)
} }
}) })
}, },
openEdit(row) { openEdit(row) {
row.addressList = [] row.addressList = []
const province = chengShiList.find(c => c.label === row.province) const province = chengShiList.find((c) => c.label === row.province)
row.addressList.push(province.value) row.addressList.push(province.value)
const city = province.children.find(p => p.label === row.city) const city = province.children.find((p) => p.label === row.city)
row.addressList.push(city.value) row.addressList.push(city.value)
const county = city.children.find(p => p.label === row.county) if (row.county) {
if (county) { const county = city.children.find((p) => p.label === row.county)
row.addressList.push(county.value) if (county) {
row.addressList.push(county.value)
}
} }
this.formData = row
this.formData = { ...row }
this.formData.isDefault = this.formData.isDefault ? "1" : "0"
this.dialogVisible = true this.dialogVisible = true
}, },
async doDefault(row) { async doDefault(row) {
const resp = await $.post(loc()+"/doDefault", {id: row.id}) const resp = await $.post(loc() + "/doDefault", { id: row.id })
if (resp.code === 0) { if (resp.code === 0) {
this.doSearch() this.doSearch()
this.$message({ this.$message({
type: 'success', type: "success",
message: resp.msg message: resp.msg
}); })
} else { } else {
this.$message.error(resp.msg); this.$message.error(resp.msg)
} }
}
},
}, },
async created() { async created() {
this.pageData() this.pageData()
/* if ("${@shiro.hasRole('sysadmin')}" === 'false') {
this.dzOptions = this.dzOptions.filter(d => d.label === "江苏省")
this.dzOptions[0].children = this.dzOptions[0].children.filter(d => d.label === "无锡市")
}*/
} }
}) })
</script> </script>
<!--# <!--#
} }
#--> #-->
@@ -25,26 +25,24 @@ layout("/layouts/platform.html"){
font-size: 13px; font-size: 13px;
color: #868282; color: #868282;
} }
</style> </style>
<div id="app" v-cloak> <div id="app" v-cloak>
<guava :edit_scroll="false" ref="guava"> <guava :edit_scroll="false" ref="guava">
<template> <template>
<el-card shadow="never"> <el-card shadow="never">
<div class="search"> <div class="search">
<div class="search-item"> <div class="search-item">
<div class="search-item-label">年度:</div> <div class="search-item-label">年度:</div>
<div class="search-item-option"> <div class="search-item-option">
<el-date-picker <el-date-picker
:clearable="true" :clearable="true"
placeholder="选择年" placeholder="选择年"
type="year" type="year"
v-model="pageForm.year" style="width: 100%"
value-format="yyyy"> v-model="pageForm.year"
</el-date-picker> value-format="yyyy"
></el-date-picker>
</div> </div>
</div> </div>
@@ -59,38 +57,48 @@ layout("/layouts/platform.html"){
</div>--> </div>-->
<div class="search-query"> <div class="search-query">
<el-button @click="doSearch" icon="el-icon-search" type="primary">搜索 <el-button @click="doSearch" icon="el-icon-search" type="primary">搜索</el-button>
</el-button>
</div> </div>
</div> </div>
</el-card> </el-card>
<el-card class="mt10" shadow="never"> <el-card class="mt10" shadow="never">
<table-tool :app="this" label="我的福利"> <table-tool :app="this" label="我的福利">
<template #func> <template #func></template>
</template>
</table-tool> </table-tool>
<el-table :data="tableData" :size="tableSize" @sort-change="pageOrder" <el-table
class="vi-table" ref="table" :data="tableData"
row-key="id" style="width: 100%" v-loading="tableLoading"> :size="tableSize"
@sort-change="pageOrder"
class="vi-table"
<el-table-column :index="indexMethod" align="center" header-align="center" ref="table"
label="序号" type="index" row-key="id"
width="80px"></el-table-column> style="width: 100%"
v-loading="tableLoading"
>
<el-table-column
:index="indexMethod"
align="center"
header-align="center"
label="序号"
type="index"
width="80px"
></el-table-column>
<el-table-column <el-table-column
:label="column.label" :label="column.label"
:prop="column.prop" :prop="column.prop"
:sortable="column.sortable" :sortable="column.sortable"
:width="column.width" :width="column.width"
align="center" align="center"
header-align="center" header-align="center"
min-width="100px" show-overflow-tooltip v-for="column in tableColumns"> min-width="100px"
show-overflow-tooltip
v-for="column in tableColumns"
>
<template scope="{row}" v-if="column.prop=='choiceTime'"> <template scope="{row}" v-if="column.prop=='choiceTime'">
<i class="el-icon-time"></i>&ensp; <i class="el-icon-time"></i>
{{moment(row.choiceTimeStart).format('YYYY/MM/DD HH:mm')}} &ensp; {{moment(row.choiceTimeStart).format('YYYY/MM/DD HH:mm')}}
<span>- {{moment(row.choiceTimeEnd).format('YYYY/MM/DD HH:mm')}}</span> <span>- {{moment(row.choiceTimeEnd).format('YYYY/MM/DD HH:mm')}}</span>
</template> </template>
@@ -101,9 +109,7 @@ layout("/layouts/platform.html"){
<template scope="{row}" v-else-if="column.prop=='gist_list'"> <template scope="{row}" v-else-if="column.prop=='gist_list'">
<template v-if="!projectInfo.flexible">{{projectInfo.gift}}</template> <template v-if="!projectInfo.flexible">{{projectInfo.gift}}</template>
<template v-if="row.gist_list"> <template v-if="row.gist_list">{{row.gifts.map(v=>v.name + '('+v.num+'份)').join(',')}}</template>
{{row.gifts.map(v=>v.name + '('+v.num+'份)').join(',')}}
</template>
</template> </template>
<template scope="{row}" v-else-if="column.prop=='receiveAddress'"> <template scope="{row}" v-else-if="column.prop=='receiveAddress'">
@@ -112,33 +118,21 @@ layout("/layouts/platform.html"){
</template> </template>
<template scope="{row}" v-else-if="column.prop=='courierNumber'"> <template scope="{row}" v-else-if="column.prop=='courierNumber'">
<span @click="viewCourierNumber(row)" class="text-primary" <span @click="viewCourierNumber(row)" class="text-primary" style="cursor: pointer">点击查看</span>
style="cursor: pointer">点击查看</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" fixed="right" header-align="center" <el-table-column align="center" fixed="right" header-align="center" label="操作" prop="userOnline" width="200px">
label="操作" prop="userOnline"
width="200px">
<template scope="{row}"> <template scope="{row}">
<el-button @click="openView(row)" size="mini" type="primary"> <el-button @click="openView(row)" size="mini" type="primary">查看</el-button>
查看
</el-button>
<!-- <el-button :disabled="!row.courierNumber" @click="openExpress(row)"--> <!-- <el-button :disabled="!row.courierNumber" @click="openExpress(row)"-->
<!-- size="mini"--> <!-- size="mini"-->
<!-- type="primary">--> <!-- type="primary">-->
<!-- 查看物流--> <!-- 查看物流-->
<!-- </el-button>--> <!-- </el-button>-->
<el-button :disabled="!row.courierNumber" @click="openEvaluate(row)" <el-button :disabled="!row.courierNumber" @click="openEvaluate(row)" size="mini" type="primary">评价</el-button>
size="mini"
type="primary">
评价
</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<!--#include("/layouts/pagination.html"){}#--> <!--#include("/layouts/pagination.html"){}#-->
</el-card> </el-card>
@@ -148,29 +142,20 @@ layout("/layouts/platform.html"){
<el-card shadow="never"> <el-card shadow="never">
<el-form :model="formData" label-width="120px" ref="addForm"> <el-form :model="formData" label-width="120px" ref="addForm">
<el-form-item label="福利名称"> <el-form-item label="福利名称">
<span style="font-weight: bold;font-size: 20px">{{projectInfo.name}}</span> <span style="font-weight: bold; font-size: 20px">{{projectInfo.name}}</span>
</el-form-item> </el-form-item>
<el-row :gutter="10"> <el-row :gutter="10">
<el-col span="8"> <el-col span="8">
<el-form-item label="福利节日"> <el-form-item label="福利节日">{{projectInfo.festival}}</el-form-item>
{{projectInfo.festival}}
</el-form-item>
</el-col> </el-col>
<el-col span="8" v-if="!projectInfo.flexible"> <el-col span="8" v-if="!projectInfo.flexible">
<el-form-item label="福利礼品"> <el-form-item label="福利礼品">{{projectInfo.gift}}</el-form-item>
{{projectInfo.gift}}
</el-form-item>
</el-col> </el-col>
<el-col span="8"> <el-col span="8">
<el-form-item label="选择形式">{{projectInfo.isCheckBox==='checkBox'?'多选':'单选'}}</el-form-item>
<el-form-item label="选择形式">
{{projectInfo.isCheckBox==='checkBox'?'多选':'单选'}}
</el-form-item>
</el-col> </el-col>
<el-col span="8" v-if="projectInfo.isCheckBox==='checkBox'"> <el-col span="8" v-if="projectInfo.isCheckBox==='checkBox'">
<el-form-item label="最多选几个"> <el-form-item label="最多选几个">{{projectInfo.multiSelectNum}}个</el-form-item>
{{projectInfo.multiSelectNum}}个
</el-form-item>
</el-col> </el-col>
<el-col span="8"> <el-col span="8">
<el-form-item label="发放形式"> <el-form-item label="发放形式">
@@ -189,75 +174,52 @@ layout("/layouts/platform.html"){
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col span="8"> <el-col span="8">
<el-form-item label="选择时间"> <el-form-item label="选择时间">{{projectInfo.choiceTimeStart}}至{{projectInfo.choiceTimeEnd}}</el-form-item>
{{projectInfo.choiceTimeStart}}至{{projectInfo.choiceTimeEnd}}
</el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-form-item label="福利套餐"> <el-form-item label="福利套餐">
<el-row :gutter="0"> <el-row :gutter="0">
<div :key="subject.id" <div :key="subject.id" v-for="subject in projectInfo.welfareProjectSubjects">
v-for="subject in projectInfo.welfareProjectSubjects"> <el-col :key="oidx" :span="6" v-for="(option, oidx) in subject.options">
<el-col :key="oidx" :span="6" <el-card shadow="never" style="margin: 5px">
v-for="(option, oidx) in subject.options"> <div slot="header" style="display: flex; justify-content: space-between">
<el-card shadow="never" <div>{{option.optionName}}</div>
style="margin: 5px;">
<div slot="header"
style="display: flex;justify-content: space-between">
<div> <div>
{{option.optionName}} <el-button @click.stop="viewDesc(option)" type="text">套餐详情</el-button>
</div>
<div>
<el-button @click.stop="viewDesc(option)"
type="text">套餐详情
</el-button>
</div> </div>
</div> </div>
<el-row :gutter="10"> <el-row :gutter="10">
<el-col :span="24"> <el-col :span="24">
<div class="optionImg"> <div class="optionImg">
<el-image <el-image :src="CREATE_PREVIEW_URL(option.imgUrl)" fit="contain"></el-image>
:src="CREATE_PREVIEW_URL(option.imgUrl)"
fit="contain"
></el-image>
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
<el-row :gutter="10" v-if="option.supplier"> <el-row :gutter="10" v-if="option.supplier">
<el-col :span="24"> <el-col :span="24">
<div class="descriptionClass"> <div class="descriptionClass">{{removeHTMLTag(option.supplier)}}</div>
{{removeHTMLTag(option.supplier)}}
</div>
</el-col> </el-col>
</el-row> </el-row>
<el-row style=""> <el-row style="">
<el-input-number disabled <el-input-number disabled style="width: 100%" v-model="option.selectNum"></el-input-number>
style="width: 100%"
v-model="option.selectNum"></el-input-number>
</el-row> </el-row>
</el-card> </el-card>
</el-col> </el-col>
</div> </div>
</el-row> </el-row>
</el-form-item> </el-form-item>
<el-form-item <el-form-item label="收货地址" prop="receiveAddress" v-if="projectInfo.provideMode===3">{{formData.receiveAddress}}</el-form-item>
label="收货地址"
prop="receiveAddress" v-if="projectInfo.provideMode===3">
{{formData.receiveAddress}}
</el-form-item>
<el-form-item label="签字" prop="sign" v-if="projectInfo.signMode===2"> <el-form-item label="签字" prop="sign" v-if="projectInfo.signMode===2">
<el-image :src="'/signature/getSignData?path=' +formData.imageUrl" <el-image
fit="contain" :src="'/signature/getSignData?path=' +formData.imageUrl"
style="height: 100px;width: 100%" v-if="formData.imageUrl"> fit="contain"
</el-image> style="height: 100px; width: 100%"
v-if="formData.imageUrl"
></el-image>
<span v-else>暂无</span> <span v-else>暂无</span>
</el-form-item> </el-form-item>
</el-form> </el-form>
@@ -265,86 +227,67 @@ layout("/layouts/platform.html"){
</template> </template>
</guava> </guava>
<el-dialog :close-on-click-modal="false" :visible.sync="evaluateDialogVisible" title="福利评价" width="40%">
<el-dialog
:close-on-click-modal="false"
:visible.sync="evaluateDialogVisible"
title="福利评价"
width="40%">
<el-form :model="formData" label-width="80px" ref="form"> <el-form :model="formData" label-width="80px" ref="form">
<el-form-item :rules="[{ required: true, message: ''}]" label="评价套餐"> <el-form-item :rules="[{ required: true, message: ''}]" label="评价套餐">
<el-radio-group <el-radio-group @change="finOneWelfareEvaluate(formData.projectId,formData.optionId)" v-model="formData.optionId">
@change="finOneWelfareEvaluate(formData.projectId,formData.optionId)"
v-model="formData.optionId">
<el-row gutter="10"> <el-row gutter="10">
<el-col :key="item.selectOptionId" class="mt10" span="24" <el-col :key="item.selectOptionId" class="mt10" span="24" v-for="item in userSelection">
v-for="item in userSelection"> <el-radio :label="item.selectOptionId" border style="width: 100%; position: relative">
<el-radio :label="item.selectOptionId" border style="width: 100%;position: relative">
{{item.optionName}} {{item.optionName}}
<span style="color: red;position: absolute;right: 10px;" v-if="!item.isPj">未评价</span> <span style="color: red; position: absolute; right: 10px" v-if="!item.isPj">未评价</span>
</el-radio> </el-radio>
</el-col> </el-col>
</el-row> </el-row>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item :rules="[{ required: true, message: ''}]" label="评分"> <el-form-item :rules="[{ required: true, message: ''}]" label="评分">
<div style="position: absolute; top: 20%;"> <div style="position: absolute; top: 20%">
<el-rate :disabled="formData.id" <el-rate :disabled="formData.id" show-score text-color="#ff9900" v-model="formData.evaluateScore"></el-rate>
show-score text-color="#ff9900"
v-model="formData.evaluateScore"></el-rate>
</div> </div>
</el-form-item> </el-form-item>
<el-form-item label="评价"> <el-form-item label="评价">
<el-input :disabled="formData.id" <el-input
maxlength="500" :disabled="formData.id"
placeholder="请输入评价" maxlength="500"
rows="5" placeholder="请输入评价"
show-word-limit rows="5"
type="textarea" show-word-limit
v-model="formData.evaluateText" type="textarea"
> v-model="formData.evaluateText"
</el-input> ></el-input>
</el-form-item> </el-form-item>
</el-form> </el-form>
<span class="dialog-footer" slot="footer"> <span class="dialog-footer" slot="footer">
<el-button @click="evaluateDialogVisible = false" type="primary">关 闭</el-button> <el-button @click="evaluateDialogVisible = false" type="primary">关 闭</el-button>
<el-button :loading="evaluateLoading" @click="doEvaluate" type="primary" <el-button :loading="evaluateLoading" @click="doEvaluate" type="primary" v-if="!formData.id">提 交</el-button>
v-if="!formData.id">提 交</el-button> </span>
</span>
</el-dialog> </el-dialog>
<el-drawer <el-drawer :visible.sync="descDialogVisible" direction="rtl" size="50%" title="福利详情">
:visible.sync="descDialogVisible"
direction="rtl"
size="50%"
title="福利详情">
<el-card style="margin: 20px"> <el-card style="margin: 20px">
<div v-html="descData"></div> <div v-html="descData"></div>
</el-card> </el-card>
</el-drawer> </el-drawer>
<el-drawer <el-drawer :visible.sync="expressDrawer" direction="rtl" size="50%">
:visible.sync="expressDrawer"
direction="rtl"
size="50%">
<template #title> <template #title>
<div style="font-size: 20px">物流详情 <div style="font-size: 20px">
物流详情
<span style="color: red">&nbsp;&nbsp;温馨提示:物流信息一小时更新一次</span> <span style="color: red">&nbsp;&nbsp;温馨提示:物流信息一小时更新一次</span>
</div> </div>
</template> </template>
<el-card style="margin: 30px"> <el-card style="margin: 30px">
<el-timeline reverse="true"> <el-timeline reverse="true">
<el-timeline-item <el-timeline-item
:color="item.color" :color="item.color"
:key="index" :key="index"
:timestamp="moment().format('YYYY-MM-DD HH:mm:ss')" :timestamp="moment().format('YYYY-MM-DD HH:mm:ss')"
v-for="(item, index) in logisticsTrace.logisticsTraceDetailList"> v-for="(item, index) in logisticsTrace.logisticsTraceDetailList"
>
{{item.desc}} {{item.desc}}
</el-timeline-item> </el-timeline-item>
</el-timeline> </el-timeline>
</el-card> </el-card>
</el-drawer> </el-drawer>
@@ -353,7 +296,7 @@ layout("/layouts/platform.html"){
</div> </div>
<script> <script>
const vue = new Vue({ const vue = new Vue({
el: '#app', el: "#app",
mixins: [initTableMixins], mixins: [initTableMixins],
data() { data() {
return { return {
@@ -361,7 +304,7 @@ layout("/layouts/platform.html"){
descDialogVisible: false, descDialogVisible: false,
projectInfo: {}, projectInfo: {},
userSelection: [], userSelection: [],
userId: '', userId: "",
projectOptions: [], projectOptions: [],
units: [], units: [],
welfareUnits: [], welfareUnits: [],
@@ -370,18 +313,17 @@ layout("/layouts/platform.html"){
welfareSignMode: [], welfareSignMode: [],
welfareNoticePushMode: [], welfareNoticePushMode: [],
pageForm: { pageForm: {
year: moment().format('YYYY'), year: moment().format("YYYY"),
searchName: 'username' searchName: "username"
}, },
tableColumns: [ tableColumns: [
{prop: 'year', label: '年度'}, { prop: "year", label: "年度" },
{prop: 'name', label: '项目名称'}, { prop: "name", label: "项目名称" },
{prop: 'choiceTime', label: '选择时间'}, { prop: "choiceTime", label: "选择时间" },
{prop: 'isChoose', label: '是否选择'}, { prop: "isChoose", label: "是否选择" },
{prop: 'gist_list', label: '所选福利'}, { prop: "gist_list", label: "所选福利" },
{prop: 'receiveAddress', label: '收货地址'}, { prop: "receiveAddress", label: "收货地址" },
{prop: 'courierNumber', label: '快递单号', sortable: true}, { prop: "courierNumber", label: "快递单号", sortable: true }
], ],
formRules: {}, formRules: {},
selPersonType: [], selPersonType: [],
@@ -392,12 +334,11 @@ layout("/layouts/platform.html"){
evaluateLoading: false, evaluateLoading: false,
expressDrawer: false, expressDrawer: false,
logisticsTrace: {}, logisticsTrace: {}
} }
}, },
components: { components: {
'courier-number-info': httpVueLoader('/components/welfare/CourierNumberInfo.vue?v=' + new Date().getTime()) "courier-number-info": httpVueLoader("/components/welfare/CourierNumberInfo.vue?v=" + new Date().getTime())
}, },
methods: { methods: {
//查看快递单号 //查看快递单号
@@ -411,15 +352,15 @@ layout("/layouts/platform.html"){
async doEvaluate() { async doEvaluate() {
if (!this.formData.evaluateScore || !this.formData.optionId) { if (!this.formData.evaluateScore || !this.formData.optionId) {
this.$message({ this.$message({
message: '请打分后再提交', message: "请打分后再提交",
type: 'warning' type: "warning"
}); })
return return
} }
const confirm = await this.$confirm('提交后将不能修改,确定要提交评价吗?', '提示', { const confirm = await this.$confirm("提交后将不能修改,确定要提交评价吗?", "提示", {
confirmButtonText: '确定', confirmButtonText: "确定",
cancelButtonText: '取消', cancelButtonText: "取消",
type: 'warning' type: "warning"
}) })
if (confirm === "confirm") { if (confirm === "confirm") {
this.evaluateLoading = true this.evaluateLoading = true
@@ -427,24 +368,18 @@ layout("/layouts/platform.html"){
if (resp.code === 0) { if (resp.code === 0) {
this.$message({ this.$message({
message: resp.msg, message: resp.msg,
type: 'success' type: "success"
}); })
this.doSearch() this.doSearch()
this.evaluateDialogVisible = false this.evaluateDialogVisible = false
} else { } else {
this.$message.error(resp.msg); this.$message.error(resp.msg)
} }
this.evaluateLoading = false this.evaluateLoading = false
} }
}, },
async finOneWelfareEvaluate(projectId, optionId) { async finOneWelfareEvaluate(projectId, optionId) {
const { data, code, msg } = await $.post(loc() + "/finOneWelfareEvaluate", {
const {
data,
code,
msg
} = await $.post(loc() + "/finOneWelfareEvaluate", {
projectId: projectId, projectId: projectId,
optionId: optionId optionId: optionId
}) })
@@ -470,7 +405,7 @@ layout("/layouts/platform.html"){
this.evaluateDialogVisible = true this.evaluateDialogVisible = true
}, },
async getProjectInfo(id) { async getProjectInfo(id) {
const resp = await $.get('/platform/welfare/common/findOne', {projectId: id}) const resp = await $.get("/platform/welfare/common/findOne", { projectId: id })
if (resp.code === 0) { if (resp.code === 0) {
this.projectInfo = resp.data this.projectInfo = resp.data
await this.getUserSelection(id) await this.getUserSelection(id)
@@ -479,14 +414,14 @@ layout("/layouts/platform.html"){
}, },
//获取用户选择的数据 //获取用户选择的数据
async getUserSelection(projectId) { async getUserSelection(projectId) {
const resp = await $.get('/platform/welfare/mine/getUserSelection', {projectId: projectId}) const resp = await $.get("/platform/welfare/mine/getUserSelection", { projectId: projectId })
this.userSelection = resp.data this.userSelection = resp.data
}, },
//回显用户选择的数据 //回显用户选择的数据
echoUserSelection() { echoUserSelection() {
//获取用户当前选择的数量 //获取用户当前选择的数量
this.projectInfo.welfareProjectSubjects[0].options.forEach(v => { this.projectInfo.welfareProjectSubjects[0].options.forEach((v) => {
const option = this.userSelection.find(x => x.selectOptionId === v.id) const option = this.userSelection.find((x) => x.selectOptionId === v.id)
if (option) { if (option) {
v.selectNum = option.selectNum v.selectNum = option.selectNum
} else { } else {
@@ -508,7 +443,7 @@ layout("/layouts/platform.html"){
this.$refs.guava.edit() this.$refs.guava.edit()
}, },
async getExpressInfo(row) { async getExpressInfo(row) {
const resp = await $.get(loc() + '/getExpressInfo', {courierNumber: row.courierNumber}) const resp = await $.get(loc() + "/getExpressInfo", { courierNumber: row.courierNumber })
if (resp.code === 0) { if (resp.code === 0) {
for (let i = 0; i < resp.data.logisticsTraceDetailList.length; i++) { for (let i = 0; i < resp.data.logisticsTraceDetailList.length; i++) {
if (i === resp.data.logisticsTraceDetailList.length - 1) { if (i === resp.data.logisticsTraceDetailList.length - 1) {
@@ -518,17 +453,16 @@ layout("/layouts/platform.html"){
} }
this.logisticsTrace = resp.data this.logisticsTrace = resp.data
} else { } else {
this.$message.error(resp.msg); this.$message.error(resp.msg)
} }
}, }
}, },
async created() { async created() {
this.pageData() this.pageData()
getEnumOptions("WelfareProvideMode").then(res => { getEnumOptions("WelfareProvideMode").then((res) => {
this.welfareProvideMode = res this.welfareProvideMode = res
}) })
getEnumOptions("WelfareSignMode").then(res => { getEnumOptions("WelfareSignMode").then((res) => {
this.welfareSignMode = res this.welfareSignMode = res
}) })
} }
File diff suppressed because it is too large Load Diff
@@ -65,6 +65,20 @@ layout("/layouts/platform.html"){
</div> </div>
</div> </div>
<div class="search-item">
<div class="search-item-label">人员类型:</div>
<div class="search-item-option">
<dict-select
@change="doSearch"
clearable
code="PERSON_TYPE"
placeholder="人员类型"
style="width: 100%"
v-model="pageForm.personType"
></dict-select>
</div>
</div>
<div class="search-query"> <div class="search-query">
<el-button @click="doSearch();unionGroupChange()" icon="el-icon-search" type="primary">搜索</el-button> <el-button @click="doSearch();unionGroupChange()" icon="el-icon-search" type="primary">搜索</el-button>
</div> </div>
@@ -86,7 +100,7 @@ layout("/layouts/platform.html"){
type="primary" type="primary"
v-if="judgmentAuthority" v-if="judgmentAuthority"
> >
导出各基层工会福利签领表 导出各分工会福利签领表
</el-button> </el-button>
<el-button <el-button
@@ -105,7 +119,7 @@ layout("/layouts/platform.html"){
type="primary">按品牌导出全部(蛋糕券) type="primary">按品牌导出全部(蛋糕券)
</el-button>--> </el-button>-->
<template v-if="judgmentAuthority || ${@shiro.hasRole('H04') || @shiro.hasRole('gh12')}"> <template v-if="judgmentAuthority || ${@shiro.hasRole('H04') || @shiro.hasRole('gh01') || @shiro.hasRole('gh12')}">
<el-button <el-button
:disabled="!pageForm.projectId" :disabled="!pageForm.projectId"
@click="exportReceiveDetail(true)" @click="exportReceiveDetail(true)"
@@ -138,12 +152,19 @@ layout("/layouts/platform.html"){
<!-- @click="exportByUnionGroup">按工会小组导出汇总表--> <!-- @click="exportByUnionGroup">按工会小组导出汇总表-->
<!-- </el-button>--> <!-- </el-button>-->
</template> </template>
<template v-if="judgmentAuthority"> <!--<template
<el-button :disabled="!pageForm.projectId" @click="exportByUnion" icon="el-icon-printer" size="small" type="primary"> v-if="judgmentAuthority">
导出基层工会/福利套餐汇总表 <el-button :disabled="!pageForm.projectId" @click="reimbursementDialog = true"
icon="el-icon-printer"
size="small"
type="primary">导出发放清单
</el-button> </el-button>
<el-button @click="selectOptionByAdmin" icon="el-icon-printer" size="small" type="primary">管理员代选择</el-button> <el-button @click="selectOptionByAdmin"
</template> icon="el-icon-printer"
size="small"
type="primary">管理员代选择
</el-button>
</template>-->
</template> </template>
</table-tool> </table-tool>
<el-table <el-table
@@ -309,6 +330,19 @@ layout("/layouts/platform.html"){
<el-button @click="doSelectByAdmin" type="primary">提交</el-button> <el-button @click="doSelectByAdmin" type="primary">提交</el-button>
</el-row> </el-row>
</el-dialog> </el-dialog>
<el-dialog :visible.sync="reimbursementDialog" title="导出发放清单" width="40%">
<el-radio-group v-model="reimbursementPersonType" size="small">
<el-radio label="在职人员" border>在职人员</el-radio>
<el-radio label="劳务派遣人员" border>劳务派遣人员</el-radio>
<el-radio label="空状态" border>空状态</el-radio>
<el-radio label="全部" border>全部</el-radio>
</el-radio-group>
<span class="dialog-footer" slot="footer">
<el-button @click="reimbursementDialog = false">取消</el-button>
<el-button @click="exportByUnion" type="primary">导出</el-button>
</span>
</el-dialog>
</div> </div>
<script> <script>
@@ -328,7 +362,8 @@ layout("/layouts/platform.html"){
month: "", month: "",
unionGroupId: "", unionGroupId: "",
year: "", year: "",
welfareUnitCode: "" welfareUnitCode: "",
personType: ""
}, },
unions: [], unions: [],
tableColumns: [], tableColumns: [],
@@ -383,7 +418,10 @@ layout("/layouts/platform.html"){
projectInfo: {}, projectInfo: {},
viewTableWrapHeight: 500, viewTableWrapHeight: 500,
judgmentAuthority judgmentAuthority,
reimbursementDialog: false,
reimbursementPersonType: null
} }
}, },
computed: { computed: {
@@ -614,6 +652,10 @@ layout("/layouts/platform.html"){
this.unclaimedPageData() this.unclaimedPageData()
}, },
exportByUnion() { exportByUnion() {
if (!this.reimbursementPersonType) {
this.$message.warning("请先选择需要导出的人员类型")
return
}
const { projectId, welfareUnitCode } = this.pageForm const { projectId, welfareUnitCode } = this.pageForm
window.open( window.open(
loc() + loc() +
@@ -622,8 +664,11 @@ layout("/layouts/platform.html"){
"&welfareUnitCode=" + "&welfareUnitCode=" +
(welfareUnitCode ? welfareUnitCode : "") + (welfareUnitCode ? welfareUnitCode : "") +
"&month=" + "&month=" +
this.pageForm.month this.pageForm.month +
"&personType=" +
this.reimbursementPersonType
) )
this.reimbursementDialog = false
}, },
exportByUnit() { exportByUnit() {
const { projectId, welfareUnitCode } = this.pageForm const { projectId, welfareUnitCode } = this.pageForm
@@ -3,8 +3,6 @@ layout("/layouts/platform.html"){
#--> #-->
<style> <style>
.optionImg { .optionImg {
display: grid; display: grid;
place-items: center; place-items: center;
@@ -49,7 +47,6 @@ layout("/layouts/platform.html"){
} }
</style> </style>
<div id="app" v-cloak> <div id="app" v-cloak>
<guava :edit_scroll="false" ref="guava"> <guava :edit_scroll="false" ref="guava">
<template> <template>
@@ -59,50 +56,59 @@ layout("/layouts/platform.html"){
<div class="search-item-label">年&emsp;&emsp;度:</div> <div class="search-item-label">年&emsp;&emsp;度:</div>
<div class="search-item-option"> <div class="search-item-option">
<el-date-picker <el-date-picker
@change="doSearch" @change="doSearch"
placeholder="请选择" placeholder="请选择"
style="width: 100%" style="width: 100%"
type="year" type="year"
v-model="pageForm.year" v-model="pageForm.year"
value-format="yyyy"> value-format="yyyy"
</el-date-picker> ></el-date-picker>
</div> </div>
</div> </div>
<div class="search-query"> <div class="search-query">
<el-button @click="doSearch" icon="el-icon-search" type="primary">搜索 <el-button @click="doSearch" icon="el-icon-search" type="primary">搜索</el-button>
</el-button>
</div> </div>
</div> </div>
</el-card> </el-card>
<el-card class="mt10" shadow="never"> <el-card class="mt10" shadow="never">
<table-tool :app="this" label="福利项目"> <table-tool :app="this" label="福利项目">
<template #func> <template #func></template>
</template>
</table-tool> </table-tool>
<el-table :data="tableData" :size="tableSize" @sort-change="pageOrder" <el-table
ref="table" :data="tableData"
row-key="id" style="width: 100%" v-loading="tableLoading"> :size="tableSize"
@sort-change="pageOrder"
<el-table-column :index="indexMethod" align="center" header-align="center" ref="table"
label="序号" type="index" row-key="id"
width="80px"></el-table-column> style="width: 100%"
v-loading="tableLoading"
>
<el-table-column
:index="indexMethod"
align="center"
header-align="center"
label="序号"
type="index"
width="80px"
></el-table-column>
<el-table-column <el-table-column
:key="column.prop" :key="column.prop"
:label="column.label" :label="column.label"
:prop="column.prop" :prop="column.prop"
:sortable="column.sortable" :sortable="column.sortable"
:width="column.width" :width="column.width"
align="center" align="center"
header-align="center" header-align="center"
min-width="100px" show-overflow-tooltip min-width="100px"
v-for="column in tableColumns"> show-overflow-tooltip
v-for="column in tableColumns"
>
<template scope="{row}" v-if="column.prop=='choiceTime'"> <template scope="{row}" v-if="column.prop=='choiceTime'">
<i class="el-icon-time"></i>&ensp; <i class="el-icon-time"></i>
{{moment(row.choiceTimeStart).format('YYYY/MM/DD HH:mm')}} &ensp; {{moment(row.choiceTimeStart).format('YYYY/MM/DD HH:mm')}}
<span>- {{moment(row.choiceTimeEnd).format('YYYY/MM/DD HH:mm')}}</span> <span>- {{moment(row.choiceTimeEnd).format('YYYY/MM/DD HH:mm')}}</span>
</template> </template>
@@ -122,12 +128,9 @@ layout("/layouts/platform.html"){
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" header-align="center" label="操作" <el-table-column align="center" header-align="center" label="操作" prop="userOnline" width="150px">
prop="userOnline" width="150px">
<template scope="{row}"> <template scope="{row}">
<el-button type="primary" size="mini" @click="openChoose(row)"> <el-button type="primary" size="mini" @click="openChoose(row)">{{confirmButtonInfo(row).text}}</el-button>
{{confirmButtonInfo(row).text}}
</el-button>
<!-- <el-button @click="openChoose(row)" size="mini" type="primary"--> <!-- <el-button @click="openChoose(row)" size="mini" type="primary"-->
<!-- v-if="new Date().getTime()>moment(row.choiceTimeStart).valueOf()--> <!-- v-if="new Date().getTime()>moment(row.choiceTimeStart).valueOf()-->
@@ -143,7 +146,6 @@ layout("/layouts/platform.html"){
<!-- </template>--> <!-- </template>-->
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<!--#include("/layouts/pagination.html"){}#--> <!--#include("/layouts/pagination.html"){}#-->
</el-card> </el-card>
@@ -153,29 +155,20 @@ layout("/layouts/platform.html"){
<el-card shadow="never"> <el-card shadow="never">
<el-form :model="formData" label-width="120px" ref="addForm"> <el-form :model="formData" label-width="120px" ref="addForm">
<el-form-item label="福利名称"> <el-form-item label="福利名称">
<span style="font-weight: bold;font-size: 20px">{{projectInfo.name}}</span> <span style="font-weight: bold; font-size: 20px">{{projectInfo.name}}</span>
</el-form-item> </el-form-item>
<el-row :gutter="10"> <el-row :gutter="10">
<el-col span="8"> <el-col span="8">
<el-form-item label="福利节日"> <el-form-item label="福利节日">{{projectInfo.festival}}</el-form-item>
{{projectInfo.festival}}
</el-form-item>
</el-col> </el-col>
<el-col span="8" v-if="!projectInfo.flexible"> <el-col span="8" v-if="!projectInfo.flexible">
<el-form-item label="福利礼品"> <el-form-item label="福利礼品">{{projectInfo.gift}}</el-form-item>
{{projectInfo.gift}}
</el-form-item>
</el-col> </el-col>
<el-col span="8"> <el-col span="8">
<el-form-item label="选择形式">{{projectInfo.isCheckBox==='checkBox'?'多选':'单选'}}</el-form-item>
<el-form-item label="选择形式">
{{projectInfo.isCheckBox==='checkBox'?'多选':'单选'}}
</el-form-item>
</el-col> </el-col>
<el-col span="8" v-if="projectInfo.isCheckBox==='checkBox'"> <el-col span="8" v-if="projectInfo.isCheckBox==='checkBox'">
<el-form-item label="最多选几个"> <el-form-item label="最多选几个">{{projectInfo.multiSelectNum}}个</el-form-item>
{{projectInfo.multiSelectNum}}个
</el-form-item>
</el-col> </el-col>
<el-col span="8"> <el-col span="8">
<el-form-item label="发放形式"> <el-form-item label="发放形式">
@@ -194,91 +187,76 @@ layout("/layouts/platform.html"){
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col span="8"> <el-col span="8">
<el-form-item label="选择时间"> <el-form-item label="选择时间">{{projectInfo.choiceTimeStart}}至{{projectInfo.choiceTimeEnd}}</el-form-item>
{{projectInfo.choiceTimeStart}}至{{projectInfo.choiceTimeEnd}}
</el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-form-item label="福利套餐"> <el-form-item label="福利套餐">
<el-row :gutter="0"> <el-row :gutter="0">
<div :key="subject.id" <div :key="subject.id" v-for="subject in projectInfo.welfareProjectSubjects">
v-for="subject in projectInfo.welfareProjectSubjects"> <el-col :key="oidx" :span="8" v-for="(option, oidx) in subject.options">
<el-col :key="oidx" :span="8" <el-card shadow="never" style="margin: 5px">
v-for="(option, oidx) in subject.options"> <div slot="header" style="display: flex; justify-content: space-between">
<el-card shadow="never" <div style="color: #000; font-size: 18px">{{option.optionName}}</div>
style="margin: 5px;">
<div slot="header" style="display: flex;justify-content: space-between">
<div style="color:#000;font-size: 18px">
{{option.optionName}}
</div>
<div> <div>
<el-button @click.stop="viewDesc(option)" <el-button @click.stop="viewDesc(option)" type="text">套餐详情</el-button>
type="text">套餐详情
</el-button>
</div> </div>
</div> </div>
<div style="display: flex"> <div style="display: grid; grid-template-rows: auto 1fr auto; height: 200px">
<el-image <div style="display: flex">
style="width: 150px;height: 150px;" <el-image
style="width: 150px; height: 150px"
:src="CREATE_PREVIEW_URL(option.imgUrl)" :src="CREATE_PREVIEW_URL(option.imgUrl)"
fit="contain" fit="contain"
></el-image> ></el-image>
<div style="width:calc(100% - 150px);padding-left: 20px;position: relative">
<div style="white-space: nowrap;display: flex"> <div style="width: calc(100% - 150px); padding-left: 20px; position: relative">
<span class="desc_label">服务专线</span> <div style="white-space: nowrap; display: flex">
<el-tooltip placement="top" :content="option.supplier"> <span class="desc_label"></span>
<span class="desc_value" <el-tooltip placement="top" :content="option.supplier">
style="width: calc(100% - 80px);text-overflow: ellipsis;overflow: hidden"> <span
{{option.supplier}} class="desc_value"
</span> style="width: calc(100% - 80px); text-overflow: ellipsis; overflow: hidden"
</el-tooltip> >
</div> {{ option.supplier }}
<div v-if="option.simpleDesc"> </span>
<span class="desc_label">备&emsp;&emsp;注</span> </el-tooltip>
<span class="desc_value"> </div>
{{option.simpleDesc}} <div v-if="option.simpleDesc">
</span> <span class="desc_label"></span>
</div> <span class="desc_value">{{ option.simpleDesc }}</span>
<div> </div>
<el-input-number :disabled="isView" <div>
:max="option.maxNum" <el-input-number
:min="0" :disabled="isView"
@change="numChange(option.selectNum,option,oidx)" :max="option.maxNum"
style="width: 150px;position: absolute;right: 0;bottom: 0;" :min="0"
v-model="option.selectNum"></el-input-number> @keydown.native="onKeydown"
@change="numChange(option.selectNum, option, oidx)"
style="width: 150px; position: absolute; right: 0; bottom: 0"
v-model="option.selectNum"
></el-input-number>
</div>
</div> </div>
</div> </div>
<div style="margin-top: 17px">
<el-select
style="width: 100%"
clearable
:disabled="option.selectNum == 0"
placeholder="请选择取货门店"
v-model="option.receiveAddress"
>
<el-option
v-for="item in option.receiveAddressList"
:key="item.address"
:label="item.address"
:value="item.address"
></el-option>
</el-select>
</div>
</div> </div>
<!-- <el-row :gutter="10">-->
<!-- <el-col :span="24">-->
<!-- <div class="optionImg">-->
<!-- <el-image-->
<!-- :src="CREATE_PREVIEW_URL(option.imgUrl)"-->
<!-- fit="contain"-->
<!-- ></el-image>-->
<!-- </div>-->
<!-- </el-col>-->
<!-- </el-row>-->
<!-- <div class="descriptionClass" style="white-space: pre-line">-->
<!-- {{option.supplier}}-->
<!-- </div>-->
<!-- <el-row style="text-align: right">-->
<!-- <el-input-number :disabled="isView"-->
<!-- :max="option.maxNum"-->
<!-- :min="0"-->
<!-- @change="numChange(option.selectNum,option,oidx)"-->
<!-- style="width: 50%"-->
<!-- v-model="option.selectNum"></el-input-number>-->
<!-- </el-row>-->
</el-card> </el-card>
</el-col> </el-col>
</div> </div>
@@ -291,58 +269,68 @@ layout("/layouts/platform.html"){
<el-form-item label="收货地址" prop="receiveAddress"> <el-form-item label="收货地址" prop="receiveAddress">
<div style="display: flex; column-gap: 10px"> <div style="display: flex; column-gap: 10px">
<div style="flex: 1"> <div style="flex: 1">
<el-select @change="addressChange" <el-select
filterable placeholder="请选择收货地址" @change="addressChange"
style="width: 100%" filterable
v-model="formData.addressId"> placeholder="请选择收货地址"
style="width: 100%"
v-model="formData.addressId"
>
<el-option <el-option
:key="item.id" :key="item.id"
:label="item.name+' '+item.defaultName" :label="item.name+' '+item.defaultName"
:value="item.id" :value="item.id"
v-for="item in addressOptions"> v-for="item in addressOptions"
</el-option> ></el-option>
</el-select> </el-select>
</div> </div>
<div> <div>
<el-button <el-button @click="openAddress" type="primary">添加收货地址</el-button>
@click="openAddress"
type="primary">添加收货地址
</el-button>
</div> </div>
</div> </div>
<span style="color: #ac3111">
温馨提示:填写默认收货地址后,系统会自动选择默认地址;如未设置默认,请您在添加收货地址后在此下拉框进行选择
</span>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col span="24"> <el-col span="24">
<el-form-item <el-form-item
:rules="{required:true,message: '请确认收货地址', trigger: 'blur'}" :rules="{required:true,message: '请确认收货地址', trigger: 'blur'}"
label="请确认收货地址" label="请确认收货地址"
prop="receiveAddress"> prop="receiveAddress"
<el-input :rows="4" disabled maxlength="100" >
placeholder="选择收货地址联动" type="textarea" <el-input
v-model="formData.receiveAddress"></el-input> :rows="4"
disabled
maxlength="100"
placeholder="选择收货地址联动"
type="textarea"
v-model="formData.receiveAddress"
></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
</template> </template>
<el-form-item :rules="{required:true,message: '请签字', trigger: 'blur'}" <el-form-item
label="签字" prop="sign" v-if="projectInfo.signMode===2"> :rules="{required:true,message: '请签字', trigger: 'blur'}"
label="签字"
prop="sign"
v-if="projectInfo.signMode===2"
>
<template v-if="isChoice===0||!isView"> <template v-if="isChoice===0||!isView">
<sign :is_value_base64="false" :qz.sync="formData.sign" <sign :is_value_base64="false" :qz.sync="formData.sign" prefix="welfare" ref="sign"></sign>
prefix="welfare"
ref="sign"></sign>
</template> </template>
<template v-else> <template v-else>
<el-image :src="'/signature/getSignData?path=' +formData.imageUrl" <el-image
fit="contain" :src="'/signature/getSignData?path=' +formData.imageUrl"
style="height: 100px;width: 100%" v-if="formData.imageUrl"> fit="contain"
</el-image> style="height: 100px; width: 100%"
v-if="formData.imageUrl"
></el-image>
<span v-else>暂无</span> <span v-else>暂无</span>
</template> </template>
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-card> </el-card>
@@ -354,85 +342,76 @@ layout("/layouts/platform.html"){
</template> </template>
</guava> </guava>
<el-drawer <el-drawer :visible.sync="descDialogVisible" direction="rtl" size="50%" title="福利详情">
:visible.sync="descDialogVisible"
direction="rtl"
size="50%"
title="福利详情">
<el-card style="margin: 20px" shadow="never"> <el-card style="margin: 20px" shadow="never">
<div v-html="descData"></div> <div v-html="descData"></div>
</el-card> </el-card>
</el-drawer> </el-drawer>
<el-dialog <el-dialog :close-on-click-modal="false" :visible.sync="addressDialogVisible" title="收货地址" width="40%">
:close-on-click-modal="false" <el-form :model="formData" label-position="right" :rules="formRules" label-suffix=":" label-width="120px" ref="addForm">
:visible.sync="addressDialogVisible"
title="收货地址"
width="30%">
<el-form :model="formData" label-position="right"
label-suffix=":" label-width="120px" ref="addForm">
<el-row :gutter="60"> <el-row :gutter="60">
<el-col :span="24"> <el-col :span="24">
<el-form-item :rules="{required:true,message: '请选择地址信息', trigger: 'blur'}" <el-form-item label="地址信息" prop="addressList">
label="地址信息"
prop="addressList">
<el-cascader <el-cascader
:options="dzOptions" :options="dzOptions"
:props="{ expandTrigger: 'hover' }" :props="{ expandTrigger: 'hover' }"
@change="handleChange" @change="handleChange"
clearable clearable
placeholder="请选择地址信息" placeholder="请选择地址信息"
style="width: 100%" style="width: 100%"
v-model="formData.addressList"></el-cascader> v-model="formData.addressList"
></el-cascader>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="24"> <el-col :span="24">
<el-form-item <el-form-item label="详细地址" prop="addressDetail">
:rules="{required:true,message: '请填写您的详细地址', trigger: 'blur'}" <el-input
label="详细地址" maxlength="100"
prop="addressDetail"> placeholder="请输入详细地址信息,如道路、门牌号、小区、楼栋号、单元等信息"
<el-input maxlength="100" rows="3"
placeholder="请输入详细地址信息,如道路、门牌号、小区、楼栋号、单元等信息" show-word-limit
rows="3" type="textarea"
show-word-limit v-model="formData.addressDetail"
type="textarea" ></el-input>
v-model="formData.addressDetail"></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="24"> <el-col :span="24">
<el-form-item <el-form-item label="收货人姓名" prop="userName">
:rules="{required:true,message: '请填写收货人姓名', trigger: 'blur'}" <el-input maxlength="11" placeholder="请填写收货人姓名" v-model="formData.userName"></el-input>
label="收货人姓名"
prop="userName">
<el-input maxlength="11"
placeholder="请填写收货人姓名"
v-model="formData.userName"></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="24"> <el-col :span="24">
<el-form-item <el-form-item label="手机号码" prop="tel">
:rules="{required:true,message: '请填写手机号码', trigger: 'blur'}" <el-input maxlength="11" placeholder="请填写手机号码" clearable v-model="formData.tel"></el-input>
label="手机号码" </el-form-item>
prop="tel"> </el-col>
<el-input maxlength="11" placeholder="请填写手机号码"
type="tel" <el-col :span="24">
v-model="formData.tel"></el-input> <el-form-item label="是否默认" prop="isDefault">
<el-switch
v-model="formData.isDefault"
active-color="#13ce66"
inactive-color="#ff4949"
active-value="1"
inactive-value="0"
active-text="是"
inactive-text="否"
></el-switch>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
</el-form> </el-form>
<span class="dialog-footer" slot="footer"> <span class="dialog-footer" slot="footer">
<el-button @click="addressDialogVisible = false">取 消</el-button> <el-button @click="addressDialogVisible = false">取 消</el-button>
<el-button @click="doSaveUserAddress" type="primary">保存</el-button> <el-button @click="doSaveUserAddress" type="primary">保存</el-button>
</span> </span>
</el-dialog> </el-dialog>
</div> </div>
<script> <script>
const vue = new Vue({ const vue = new Vue({
el: '#app', el: "#app",
mixins: [initTableMixins], mixins: [initTableMixins],
data() { data() {
return { return {
@@ -450,56 +429,78 @@ layout("/layouts/platform.html"){
welfareSubject: {}, welfareSubject: {},
pageForm: { pageForm: {
isChoose: false, isChoose: false,
year: moment().format('YYYY') year: moment().format("YYYY")
}, },
tableColumns: [ tableColumns: [
{prop: 'year', label: '年度'}, { prop: "year", label: "年度" },
{prop: 'name', label: '项目名称'}, { prop: "name", label: "项目名称" },
{prop: 'choiceTime', label: '选择时间'}, { prop: "choiceTime", label: "选择时间" },
{prop: 'isChoose', label: '是否选择'}, { prop: "isChoose", label: "是否选择" },
{prop: 'gist_list', label: '所选福利'}, { prop: "gist_list", label: "所选福利" },
{prop: 'receiveAddress', label: '收货地址'}, { prop: "receiveAddress", label: "收货地址" }
], ],
isView: false, isView: false,
isChoice: false, isChoice: false,
addressDialogVisible: false, addressDialogVisible: false,
formRules: {
addressList: [{ required: true, message: "请选择地址信息", trigger: ["blur", "change"] }],
addressDetail: [{ required: true, message: "请填写您的详细地址", trigger: ["blur", "change"] }],
userName: [{ required: true, message: "请填写收货人姓名", trigger: ["blur", "change"] }],
tel: [
{ required: true, message: "必填", trigger: ["blur", "change"] },
{ pattern: /^1[3-9]\d{9}$/, message: "请输入正确的手机号" }
]
},
// 供应商
shoppingType: [],
// 门店地址
offlineStoresOption: []
} }
}, },
computed: { computed: {
sumSelectNum() { sumSelectNum() {
if (this.projectInfo && this.projectInfo.welfareProjectSubjects) { if (this.projectInfo && this.projectInfo.welfareProjectSubjects) {
return this.projectInfo.welfareProjectSubjects[0].options.map(v => v.selectNum).reduce((accumulator, currentValue) => accumulator + currentValue, 0) return this.projectInfo.welfareProjectSubjects[0].options
.map((v) => v.selectNum)
.reduce((accumulator, currentValue) => accumulator + currentValue, 0)
} }
return 0 return 0
}, }
}, },
methods: { methods: {
onKeydown(event) {
if (event.key !== "ArrowUp" && event.key !== "ArrowDown") {
event.preventDefault()
}
},
confirmButtonInfo(row) { confirmButtonInfo(row) {
const {choiceTimeEnd, choiceTimeStart, overdueChoiceTimeEnd, isChoose, selectTime} = row const { choiceTimeEnd, choiceTimeStart, overdueChoiceTimeEnd, isChoose, selectTime } = row
const now = moment().valueOf() const now = moment().valueOf()
if (overdueChoiceTimeEnd == null || overdueChoiceTimeEnd === '') { if (overdueChoiceTimeEnd == null || overdueChoiceTimeEnd === "") {
if (now > moment(choiceTimeStart).valueOf() && now < moment(choiceTimeEnd).valueOf()) { if (now > moment(choiceTimeStart).valueOf() && now < moment(choiceTimeEnd).valueOf()) {
return {text: isChoose ? '确定修改' : '确定选择', disabled: false} return { text: isChoose ? "修改" : "选择", disabled: false }
} else if (now > moment(choiceTimeEnd).valueOf()) { } else if (now > moment(choiceTimeEnd).valueOf()) {
return {text: '选择已结束', disabled: true} return { text: "选择已结束", disabled: true }
} else if (now < moment(choiceTimeStart).valueOf()) { } else if (now < moment(choiceTimeStart).valueOf()) {
return {text: '选择未开始', disabled: true} return { text: "选择未开始", disabled: true }
} }
} else { } else {
//已选择了不能再动了 //已选择了不能再动了
if (isChoose) { if (isChoose) {
if(moment(selectTime).valueOf() > moment(choiceTimeEnd).valueOf() && now < moment(overdueChoiceTimeEnd).valueOf()){ if (moment(selectTime).valueOf() > moment(choiceTimeEnd).valueOf() && now < moment(overdueChoiceTimeEnd).valueOf()) {
return {text: '确定修改', disabled: false} return { text: "修改", disabled: false }
} }
return {text: '选择已结束', disabled: true} return { text: "选择已结束", disabled: true }
} else { } else {
if (now > moment(choiceTimeStart).valueOf() && now < moment(overdueChoiceTimeEnd).valueOf()) { if (now > moment(choiceTimeStart).valueOf() && now < moment(overdueChoiceTimeEnd).valueOf()) {
return {text: isChoose ? '确定修改' : '确定选择', disabled: false} return { text: isChoose ? "修改" : "选择", disabled: false }
} else if (now > moment(overdueChoiceTimeEnd).valueOf()) { } else if (now > moment(overdueChoiceTimeEnd).valueOf()) {
return {text: '选择已结束', disabled: true} return { text: "选择已结束", disabled: true }
} else if (now < moment(choiceTimeStart).valueOf()) { } else if (now < moment(choiceTimeStart).valueOf()) {
return {text: '选择未开始', disabled: true} return { text: "选择未开始", disabled: true }
} }
} }
} }
@@ -509,12 +510,12 @@ layout("/layouts/platform.html"){
let provinceName = "" let provinceName = ""
let cityName = "" let cityName = ""
let countyName = "" let countyName = ""
const province = this.dzOptions.find(c => c.value === val[0]) const province = this.dzOptions.find((c) => c.value === val[0])
provinceName = province.label provinceName = province.label
const city = province.children.find(p => p.value === val[1]) const city = province.children.find((p) => p.value === val[1])
cityName = city.label cityName = city.label
if (val.length === 3) { if (val.length === 3) {
const county = city.children.find(p => p.value === val[2]) const county = city.children.find((p) => p.value === val[2])
countyName = county.label countyName = county.label
this.$set(this.formData, "areaCode", county.value) this.$set(this.formData, "areaCode", county.value)
} else { } else {
@@ -523,7 +524,6 @@ layout("/layouts/platform.html"){
this.$set(this.formData, "province", provinceName) this.$set(this.formData, "province", provinceName)
this.$set(this.formData, "city", cityName) this.$set(this.formData, "city", cityName)
this.$set(this.formData, "county", countyName) this.$set(this.formData, "county", countyName)
} }
}, },
openAddress() { openAddress() {
@@ -540,64 +540,56 @@ layout("/layouts/platform.html"){
this.doSearch() this.doSearch()
this.$message({ this.$message({
message: resp.msg, message: resp.msg,
type: 'success' type: "success"
}); })
await this.selectUserAddress() await this.selectUserAddress()
this.addressDialogVisible = false this.addressDialogVisible = false
} else { } else {
this.$message.error(resp.msg); this.$message.error(resp.msg)
} }
} }
}) })
}, },
//数量更改 //数量更改
numChange(value, option, optionIndex) { numChange(value, option, optionIndex) {
this.$nextTick(() => { this.$nextTick(() => {
// 查找+1按钮 // 查找+1按钮
const plusButton = document.querySelector('.el-input-number__increase'); const plusButton = document.querySelector(".el-input-number__increase")
// 添加点击事件监听器 // 添加点击事件监听器
plusButton.addEventListener('click', this.handlePlusButtonClick(value, option, optionIndex)); plusButton.addEventListener("click", this.handlePlusButtonClick(value, option, optionIndex))
}) })
}, },
handlePlusButtonClick(value, option, optionIndex) { handlePlusButtonClick(value, option, optionIndex) {
const { const { isCheckBox, multiSelectNum, singleOptionSupportMultipleSelection } = this.projectInfo
isCheckBox, if (isCheckBox === "checkBox") {
multiSelectNum,
singleOptionSupportMultipleSelection
} = this.projectInfo
if (isCheckBox === 'checkBox') {
//判断是否支持单个多选 //判断是否支持单个多选
if (!singleOptionSupportMultipleSelection && value > 1) { if (!singleOptionSupportMultipleSelection && value > 1) {
this.$set(this.projectInfo.welfareProjectSubjects[0].options[optionIndex], 'selectNum', 1) this.$set(this.projectInfo.welfareProjectSubjects[0].options[optionIndex], "selectNum", 1)
this.$message.warning('此套餐最多只能选择1份'); this.$message.warning("此套餐最多只能选择1份")
return; return
} }
} }
//获取用户当前选择的数量 //获取用户当前选择的数量
const selectNums = this.projectInfo.welfareProjectSubjects[0].options.map(v => v.selectNum) const selectNums = this.projectInfo.welfareProjectSubjects[0].options.map((v) => v.selectNum)
const sum = selectNums.reduce((accumulator, currentValue) => accumulator + currentValue, 0) const sum = selectNums.reduce((accumulator, currentValue) => accumulator + currentValue, 0)
if (sum > multiSelectNum) { if (sum > multiSelectNum) {
this.$set(this.projectInfo.welfareProjectSubjects[0].options[optionIndex], 'selectNum', value - 1) this.$set(this.projectInfo.welfareProjectSubjects[0].options[optionIndex], "selectNum", value - 1)
this.$message.warning('此次福利最多只能选择' + multiSelectNum + '份'); this.$message.warning("此次福利最多只能选择" + multiSelectNum + "份")
} }
}, },
async getProjectInfo(id) { async getProjectInfo(id) {
const resp = await $.get('/platform/welfare/common/findOne', {projectId: id}) const resp = await $.get("/platform/welfare/common/findOne", { projectId: id })
if (resp.code === 0) { if (resp.code === 0) {
resp.data.multiSelectNum = resp.data.multiSelectNum ? resp.data.multiSelectNum : 1 resp.data.multiSelectNum = resp.data.multiSelectNum ? resp.data.multiSelectNum : 1
this.projectInfo = resp.data this.projectInfo = resp.data
await this.getUserSelection(id) await this.getUserSelection(id)
await this.getChoice() await this.getChoice()
await this.getShoppingType()
} }
}, },
async openView(row) { async openView(row) {
this.isView = true this.isView = true
await this.getProjectInfo(row.id) await this.getProjectInfo(row.id)
@@ -611,7 +603,7 @@ layout("/layouts/platform.html"){
this.$refs.guava.edit() this.$refs.guava.edit()
}, },
addressChange(val) { addressChange(val) {
const address = this.addressOptions.find(a => a.id === val) const address = this.addressOptions.find((a) => a.id === val)
if (address) { if (address) {
this.$set(this.formData, "receiveAddress", address.name) this.$set(this.formData, "receiveAddress", address.name)
} }
@@ -619,54 +611,76 @@ layout("/layouts/platform.html"){
doChoose() { doChoose() {
this.$refs["addForm"].validate(async (valid) => { this.$refs["addForm"].validate(async (valid) => {
if (valid) { if (valid) {
const { const { isCheckBox, multiSelectNum, singleOptionSupportMultipleSelection } = this.projectInfo
isCheckBox,
multiSelectNum,
singleOptionSupportMultipleSelection
} = this.projectInfo
if (isCheckBox === "checkBox") { if (isCheckBox === "checkBox") {
if (this.sumSelectNum < multiSelectNum) { if (this.sumSelectNum < multiSelectNum) {
//用户没有选择完 //用户没有选择完
this.$message('一共可以选择' + multiSelectNum + '份,您目前只选择了' + this.sumSelectNum + '份,快去选择吧!') this.$message.warning("一共可以选择" + multiSelectNum + "份,您目前只选择了" + this.sumSelectNum + "份,快去选择吧!")
return
}
} else {
if (this.sumSelectNum === 0) {
//用户选择了多份
this.$message.warning("您还没有选择福利套餐,快去选择吧!")
return return
} }
} }
if (this.formData.receiveAddress == null || this.formData.receiveAddress === '') {
this.$message.warning('请填写收货地址') // 判断门店是否选择
return const chooseOptions = this.projectInfo.welfareProjectSubjects[0].options
} .filter((v) => v.selectNum > 0)
if (this.formData.sign == null || this.formData.sign === '') { .map((item) => {
this.$message.warning('请签字') return { optionName: item.optionName, selectNum: item.selectNum, receiveAddress: item.receiveAddress }
return })
} let isReceiveAddress = true
const formData = this.projectInfo.welfareProjectSubjects[0].options.filter(v => v.selectNum >= 1).map(v => { for (const item of chooseOptions) {
return { if (!item.receiveAddress) {
welfareId: this.projectInfo.id, this.$message.warning(item.optionName + "还没有选择收货门店哦")
subjectId: v.subjectId, isReceiveAddress = false
selectOptionId: v.id, break
receiveAddress: this.formData.receiveAddress,
userSign: this.formData.sign,
selectNum: v.selectNum
} }
}) }
const { if (!isReceiveAddress) {
code, return
msg, }
data
} = await $.post('/platform/welfare/userChoose/confirmSelect', { if (this.projectInfo.provideMode == 3) {
if (this.formData.receiveAddress == null || this.formData.receiveAddress === "") {
this.$message.warning("请填写收货地址")
return
}
}
if (![1, 4].includes(this.projectInfo.signMode)) {
if (this.formData.sign == null || this.formData.sign === "") {
this.$message.warning("请签字")
return
}
}
const formData = this.projectInfo.welfareProjectSubjects[0].options
.filter((v) => v.selectNum >= 1)
.map((v) => {
return {
welfareId: this.projectInfo.id,
subjectId: v.subjectId,
selectOptionId: v.id,
receiveAddress: this.projectInfo.provideMode === 3 ? this.formData.receiveAddress : v.receiveAddress,
userSign: this.formData.sign,
selectNum: v.selectNum
}
})
console.log(formData)
const { code, msg, data } = await $.post("/platform/welfare/userChoose/confirmSelect", {
welfareUserSelections: JSON.stringify(formData), welfareUserSelections: JSON.stringify(formData),
projectId: this.projectInfo.id projectId: this.projectInfo.id
}) })
if (code === 0) { if (code === 0) {
this.$message({ this.$message.success("您已完成本次福利选择。")
message: msg,
type: 'success'
});
} else { } else {
this.$message({ this.$message({
message: msg, message: msg,
type: 'warning' type: "warning"
}); })
} }
this.doSearch() this.doSearch()
this.$refs.guava.index() this.$refs.guava.index()
@@ -695,7 +709,7 @@ layout("/layouts/platform.html"){
this.$set(this.formData, "addressId", null) this.$set(this.formData, "addressId", null)
this.$set(this.formData, "sign", this.userSelection[0].userSign) this.$set(this.formData, "sign", this.userSelection[0].userSign)
} else { } else {
const address = this.addressOptions.find(a => a.isDefault) const address = this.addressOptions.find((a) => a.isDefault)
if (address) { if (address) {
this.$set(this.formData, "receiveAddress", address.name) this.$set(this.formData, "receiveAddress", address.name)
this.$set(this.formData, "addressId", address.id) this.$set(this.formData, "addressId", address.id)
@@ -705,58 +719,67 @@ layout("/layouts/platform.html"){
}, },
//获取用户选择的数据 //获取用户选择的数据
async getUserSelection(projectId) { async getUserSelection(projectId) {
const resp = await $.get('/platform/welfare/mine/getUserSelection', {projectId: projectId}) const resp = await $.get("/platform/welfare/mine/getUserSelection", { projectId: projectId })
this.userSelection = resp.data this.userSelection = resp.data
this.echoUserSelection() this.echoUserSelection()
}, },
//回显用户选择的数据 //回显用户选择的数据
echoUserSelection() { echoUserSelection() {
//获取用户当前选择的数量 //获取用户当前选择的数量
this.projectInfo.welfareProjectSubjects[0].options.forEach(v => { this.projectInfo.welfareProjectSubjects[0].options.forEach((v) => {
const option = this.userSelection.find(x => x.selectOptionId === v.id) const option = this.userSelection.find((x) => x.selectOptionId === v.id)
if (option) { if (option) {
v.selectNum = option.selectNum v.selectNum = option.selectNum
this.$set(v, "receiveAddress", option.receiveAddress)
} else { } else {
v.selectNum = 0 v.selectNum = 0
this.$set(v, "receiveAddress", "")
} }
}) })
}, },
async getChoice() { async getChoice() {
const resp = await $.get('/mobile/welfare/mine/isChoice', {projectId: this.projectInfo.id}) const resp = await $.get("/mobile/welfare/mine/isChoice", { projectId: this.projectInfo.id })
this.isChoice = resp.data this.isChoice = resp.data
}, },
async selectUserAddress() { async selectUserAddress() {
const resp = await $.get('/platform/welfare/addressManage/selectUserAddress') const resp = await $.get("/platform/welfare/addressManage/selectUserAddress")
resp.data.map(r => { resp.data.map((r) => {
let defaultName = r.isDefault ? "默认地址" : "" let defaultName = r.isDefault ? "默认地址" : ""
r.defaultName = defaultName r.defaultName = defaultName
r.name = "收货地址:" + r.province + r.city + r.county + r.addressDetail + ",收件人:" + r.userName + ",联系方式:" + r.tel r.name = "收货地址:" + r.province + r.city + r.county + r.addressDetail + ",收件人:" + r.userName + ",联系方式:" + r.tel
}) })
this.addressOptions = resp.data this.addressOptions = resp.data
this.$nextTick(() => {
const address = this.addressOptions.find((v) => v.isDefault)
if (address) {
this.$set(this.formData, "addressId", address.id)
this.$set(this.formData, "receiveAddress", address.name)
}
})
}, },
// 获取供应商
async getShoppingType() {
const { data } = await $.get("/platform/shoppingType/apply/getShoppingType")
this.projectInfo.welfareProjectSubjects[0].options.forEach((item) => {
item.receiveAddressList = data.find((v) => v.id === item.shoppingId).offlineStores
})
console.log(this.projectInfo.welfareProjectSubjects[0])
}
}, },
async created() { async created() {
this.pageData() this.pageData()
this.selectUserAddress() this.selectUserAddress()
getEnumOptions("WelfareProvideMode").then(res => { getEnumOptions("WelfareProvideMode").then((res) => {
this.welfareProvideMode = res this.welfareProvideMode = res
}) })
getEnumOptions("WelfareSignMode").then(res => { getEnumOptions("WelfareSignMode").then((res) => {
this.welfareSignMode = res this.welfareSignMode = res
}) })
/* if ("${@shiro.hasRole('sysadmin')}" === 'false') {
this.dzOptions = this.dzOptions.filter(d => d.label === "江苏省")
this.dzOptions[0].children = this.dzOptions[0].children.filter(d => d.label === "无锡市")
}*/
} }
}) })
</script> </script>
<!--# <!--#
} }
#--> #-->