This commit is contained in:
Paidax
2024-07-22 17:36:03 +08:00
parent 03faa20548
commit 7e190d4ccc
24 changed files with 4001 additions and 2 deletions
+12
View File
@@ -52,6 +52,18 @@
</developers>
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dashscope-sdk-java</artifactId>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.35.37.ALL</version>
</dependency>
<dependency>
<groupId>cn.smallbun.screw</groupId>
<artifactId>screw-core</artifactId>
+4 -2
View File
@@ -977,11 +977,13 @@ public class MainLauncher {
try {
MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
ObjectName objectName = new ObjectName("com.alibaba.druid:type=MockDriver");
if (mbeanServer.isRegistered(objectName))
if (mbeanServer.isRegistered(objectName)) {
mbeanServer.unregisterMBean(objectName);
}
objectName = new ObjectName("com.alibaba.druid:type=DruidDriver");
if (mbeanServer.isRegistered(objectName))
if (mbeanServer.isRegistered(objectName)) {
mbeanServer.unregisterMBean(objectName);
}
} catch (Exception ex) {
}
}
@@ -0,0 +1,22 @@
package io.v.nutz.zhgh.memberCost.controller;
/**
* @ClassName AlipayClientConfig
* @Description TODO
* @Author zhf
* @Date 2024/1/25 15:33
*/
public interface AlipayClientConfig {
String serverUrl = "https://openapi.alipay.com/gateway.do";
String appId = "2021004133670087";
String sellerId = "2088002638762620";
String privateKey = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCEJBWNlUIY/2Tave1OtjTgvA21GZ5tdvZZD3jFmixIFTkEdZaRUpXCvlKuZ9heoL1IQwpbuOErJ4dM2f2Ju/Oc7QtUOjEOX6CnElR73KK5OSY8d8f5822LUOgp2zg5FHI6C7olYmjN4Nw26G6BGyqQBmWs4/sKzghKelEaH9AqkR8DZ+yOvuYtIg5KEvVixsM27TMhd6/3BuNXDIiQDVH9ZeQVb9IKuynZ6hnUJS0T4MkS41qehS1u8LgplGU5yvrNuUNeQtybADsiGHDNmNkl5lVt0QNh+N/lo56//duf5PJwh8ApDB22eXptiS6p321PSrYowy5VeFpHC07Tref9AgMBAAECggEAPQddXPKegGUT82LcgwnsCg9QVV/rp6rVw/Q9VyYJZZFHsCOO0rdNq4+zKBGWAL5ELWepFQuiEwhCmN/lFQPVU5i3LsNhfL31uLPiiQIxtVILssmvdmVTJpDLaOlyYgprZxubcUCuHsfHbSSURNSDJ9mMg/kXLLpTYfJ0Gpiuz7lkrMuAxncdz88Sp2r0O9k2T+TcnHFpRXHs+C/QAaa15EF18ieDSBLPkY0ti1R8J91LGAzDrjwcP7pNlq4u7TasZ7djv47ZFwQ3yjWoo13d9ab0MBYeQx9Grf5N+JGNf33YLyulQ0IshcuwNyB+RYhyWGjNmjnJdytzKRMOYSpPgQKBgQC6iqMPX+LGunyI+3T9l/AwAVWRJXzEHPflNxDYfQbicB5awlRixxH5T1qyZ46KZb/pBt01qDULXy0bEObVFSjAn1wXPzC9Fwb+BtVZUroYBTKV3tOAMpVCz2AAC34OZwG/3X//sRtW9Sr0Dr+yCcx8ULMiFS1BuCZfhSNXA516NQKBgQC1V+rge1pYKGnjtWqML4qJy4FEIDI4fSpGIizxumYDMxdXoUdNKoG2NHQkznHU4fIHJPVvIN/Tm82mfj2rhH9eFuu1FB8TL2soe5nPgzSJ9AmP7rZ7KBo3/SczvZqUEpii8+PjHu+Gx95BmgTzOFMnYz8xzitb4IBGTEGxVzavqQKBgCL28XFkS6FsOwOB/n+6Bu84kM1P9X7c3yo7lBC//pZa5ZWlbyPEpH3SffGKr5EJWVtYSgZQrQCgqle0Z0/xU14ngJ9q3LvUoR7kMQE5HGB8OOsWhRY2ZPvM2vWnMc2JSS6pWeCXVcSK164/RXcdlxKGHc15oq360lZ9Ig6hQtcxAoGAIYijd2V4HGtEwYXvsQKtlLOcMNPfVZDXu2Zgd0bnzFmrTFoXjE569A2ZGKFQbXRmxClydV1X5pKeIdagYtI6l1SXu8F/yZVwNGk+1R/HHGeTSRl0hyuwRYA7upaqOg2CSkfdcUdsNblKAUmQ9sUIo3T336bnX7MRJW6+iyO8ihkCgYBG8vG1fVUwPmqlRK+QanHxicR1+UyjRAN+aW6dgJUNMlC+tmPeHj21+WGkDdKPdhinHziLihLmzbmpwWSDwuGMMQPNQm8gSjiaqy1tWcP6XKDxjpG5biTzwEyHNuCIY6odS4HTeDOrrU4LvN6PxirN8xKBIpq+A2cgpGo+Mn4x+g==";
String alipayPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjO/QUy+ujNBlToL6Kt8YjvTRGpEwmXjqc9pFe7GIORVkzBXP3F/UC/w5mPiwXhhyymXAe7bUwLANL/QMUZhvpjjCdLENtFWC9bd6hq3m2oHiTu0oicbzqCuaoQkzik2NybrNjuH+aYVi4RU0eNYpdewQoHHW+hbfxkSYUWmx7NF4SuG93edYlpc/G/ImdrweATLE0b6W9il4H/BxVUweCraPrispiOM8r6TN3fiIKUQRP15HKQo8Xsr4pMJzfi37I9aN8AThN/xBf6sual8IZZsH5hC3PS37LrYkXbUjt0dK5tqKl3SsZPjvvHGyz9b9JC225+0q09Y6B8/axOlihwIDAQAB";
/* String serverUrl = "https://openapi-sandbox.dl.alipaydev.com/gateway.do";
String appId = "9021000134641646";
String privateKey = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCBFTF8qFbK+NiqUbKf1/jWHL/s0hfUXK6cyKwZCEXkEMZH1Lu6kZQl3kQye9Fsasawxn1vLmKz+OKjMiE+TdTytHDu5ULdLlSHN3bY1qf91i8L+RJfmZpb1p+NQOk9zImhhSauuk+itMkTC3bTiwwAkg/utOxkNB7YaynpAb3evhXnlX3LUVTHaMnCQFeV7ithh7CDKx0LPlxOpOvxnkWDBR3nsdcfjDqYNDVHXnUxEk0KQV4Ik6fA40+Gq/HXTByJolCSAaTk0OaH2ULp1RZAklWLqhiNEhytTZAlJUx8cSm36mm0c4jhgSXNdRz0Yi1BlPY9yxQGStpH5ue3+EfvAgMBAAECggEAda/D4Zp9HysIJyi7SZ6XwWaO2TSnAzfI/yq6NUxkpE1i6cSbr7rgrjHaTYiz5DvpkOw3GnHZDarhvtaKlopRl0JKIJSnhI6kBG/eDE6Q9Q4c8LaSONULdaXU6+z9ehmMddW28eDtkDNxi8qM+MuyEqcYnZMYXzdh1ADIQicTXArxo+9fpvlKUMNxOTO5LoOf0DtJg/xE1CD9PtWVc+l2G8S3+C52+RhfZ214YQdxwayMlvJQlWzLTbfzJCp8w4F2up1nJdwp7EY8k8xDUngEnG6BWm8ztWUVTTg7qp/+SC9yMTD2dl86wDkJt1lTtwcKaWxHYh2ZIn8a8+icHFykaQKBgQDgBEWAmuj0pgpny5Q0GRsUYPq42SwpN70u4rmD5UYFCeDHaKb4U3kyvA1V+1Tp0XWzFi7GU855h1n8dnQX64J3Vm4GfhftWwTJgB5ibbY53cZVEoV5nZe0bOO4hxxMdNy3BKjPovkT0REPpCkVas/RRLAFCdnvi6vmDkFxvv9JewKBgQCTgx9NZZCqSzzCJYpLTDOCitooOQmR8kAlgBiDCcHeH2wNVMh5O2Dl/OyTGauKUJFWIOSD8FXVTrNUbOEmx58msnS/+Mc5SnbEka5ptVEDp73gf6ctB+eZAMdO1kLsBT3iKnuyNa7pRyR/D2A692RHOTQZIvRHE1N+kM1r+iBPHQKBgCZRVLocxUAjrp/2eJE4wiMIO5qmuyEJwbhlW6ot634tJF+3jOfpD1AYToeoh+u+wk0xvCp8Z1LuTfwbHtyAkj5rcEJ4Cwu0h+sXmRro/USEpMokcuRMioh4H7OOmM6TJrW/fEiX7dbv6eUtBUH+lTGMeDdEahzJXUvqoFMegnhFAoGAa2eflRUMflIFzT7UMPsszjIXog3VoASJHETmlBK4q+ipHhPLXCoV5Z+BCaI5Op5rFBEjEcYeWQ/Slvgn/7p9cQmi5FxZgqdrTrjcC2/Pqx+pqxqHOMx2nvroI8jyNTOj2VchdaKM1qHMOw+Q+55Bz3IhMuQ2hMHXm2IHkEUw3SkCgYBjcqcWbJcq26L8yYVpU2JFzOvu7iHuV99TpEvF9Ym3cAcSNuoR5kGXzGS0MadYY87cd4HK9HvmXQmthLY14buKYxq27ZFfNbK/Auz8vk0Wbrm1Ym4Z1yMqClQqxKdr4hV29ijn1nPProRqgnVsGH3EtFmNxDfilZoVzh9ERaZe7w==";
String alipayPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArhElUiFMpxqFCs+8zDHa4OVuhdWgKUUGVKgWnfLktPgy9mDZkuGPKk295k8ktWQSUZsnFvT8ikJIKdGYfbSWzlXvCAn6lDDDlsjfOJWMQ6zLmb9xygCih2OjwN5xt9QFIIthnWq8sOXpWvqmoRpIFQHolxxmvvCmUZ/VwK6mwgwU/yVvVypruQ/FGrJA70LAcJ764spWAMy/pWIoIs5UewOlJa3TAcZQIqRnjupL2/sI/TpIWFWF90a/rahwLfBgZ83VH7MA4Tl9uFLc3aeNFLllDF4X7lRdzaHIMYgUUKte9yvlDy5Ihrt+ssjsgdRhqLHvFn00u/g7BCvO5ZmIUwIDAQAB";
*/
}
@@ -0,0 +1,68 @@
package io.v.nutz.zhgh.memberCost.controller;
import io.v.nutz.zhgh.memberCost.service.AlipayService;
import lombok.extern.slf4j.Slf4j;
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;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* @ClassName AlipayClientController
* @Description TODO
* @Author zhf
* @Date 2024/1/25 15:36
*/
@IocBean
@Slf4j
@Ok("json:full")
@At("/mobile/memberCost/AlipayClient")
public class AlipayClientController {
@Inject
private AlipayService alipayService;
@At("/tradePagePay")
public String tradePagePay(String money, String paymentProjectId) throws Exception {
log.info("统一收单下单并支付接口调用");
String formStr = alipayService.tradeCreate(money, paymentProjectId);
return formStr;
}
@At("/tradeNotify")
@Ok("re")
public String tradeNotify(HttpServletRequest request) {
try {
Map<String, String> params = new HashMap<String, String>();
Map<String, String[]> requestParams = request.getParameterMap();
for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
String name = (String) iter.next();
String[] values = (String[]) requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i]
: valueStr + values[i] + ",";
}
//乱码解决,这段代码在出现乱码时使用
valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
params.put(name, valueStr);
}
log.info("支付通知,正在执行,通知参数:{}");
return alipayService.tradeNotify(params);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
@@ -0,0 +1,69 @@
package io.v.nutz.zhgh.memberCost.controller.mobile;
import io.v.nutz.base.annontation.ViReturn;
import io.v.nutz.web.commons.utils.ShiroUtil;
import io.v.nutz.zhgh.memberCost.service.MemberPaymentService;
import lombok.extern.slf4j.Slf4j;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
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;
/**
* @ClassName MobileMemberCostListController
* @Description TODO
* @Author zhf
* @Date 2024/1/26 15:37
*/
@IocBean
@Slf4j
@Ok("json:full")
@At("/mobile/memberCost/list")
public class MobileMemberCostListController {
@Inject
private MemberPaymentService memberPaymentService;
@At("")
@Ok("beetl:/mobile/memberCost/memberCostList.html")
public void index() {
}
@At("/paySuccess")
@Ok("beetl:/mobile/memberCost/paySuccess.html")
public void paySuccess() {
}
@At
@ViReturn
public Object pageData(Integer memberActive) {
Sql sql = Sqls.create("""
SELECT
mpi.*,
mpp.modeValue,
mpp.modeValueList,
mpp.selectMode,
mpp.projectName
FROM
member_payment_info mpi
LEFT JOIN member_payment_project mpp ON mpi.paymentProjectId = mpp.id
WHERE
mpi.userId = @userId
AND mpp.isDisabled =0
and mpi.isPayment =@isPayment
""").setParam("userId", ShiroUtil.getUserId()).setParam("isPayment", memberActive);
return memberPaymentService.listMap(sql);
}
@At
@ViReturn
public Object getPayInfo(String id) {
return memberPaymentService.fetch(id);
}
}
@@ -0,0 +1,44 @@
package io.v.nutz.zhgh.memberCost.controller.payment;
import io.v.nutz.base.annontation.ViReturn;
import io.v.nutz.zhgh.memberCost.model.MemberPaymentConfig;
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;
@IocBean
@Slf4j
@Ok("json:full")
@At("/platform/member/payment/config")
public class MemberPaymentConfigController {
@Inject
private MemberPaymentService memberPaymentService;
@At("")
@Ok("beetl:/platform/memberCost/payment/config.html")
@RequiresPermissions("member.payment.config")
public void index() {}
@At
@ViReturn
public Object getPaymentConfig(){
return memberPaymentService.getConfig();
}
@At
@ViReturn
@RequiresPermissions("member.payment.config")
public Object doAddOrModify(MemberPaymentConfig memberPaymentConfig){
System.out.println(memberPaymentConfig);
memberPaymentService.dao().insertOrUpdate(memberPaymentConfig);
return null;
}
}
@@ -0,0 +1,261 @@
package io.v.nutz.zhgh.memberCost.controller.payment;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import io.v.nutz.base.annontation.ViReturn;
import io.v.nutz.base.dao.CndPlus;
import io.v.nutz.base.query.PageForm;
import io.v.nutz.base.result.Result;
import io.v.nutz.sys.models.Sys_user;
import io.v.nutz.zhgh.memberCost.model.MemberPaymentConfig;
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 lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Sqls;
import org.nutz.dao.impl.NutTxDao;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.json.Json;
import org.nutz.lang.Strings;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
@IocBean
@Slf4j
@Ok("json:full")
@At("/platform/member/payment/manage")
public class MemberPaymentManageController {
@Inject
private MemberPaymentService memberPaymentService;
@At("")
@Ok("beetl:/platform/memberCost/payment/manage.html")
@RequiresPermissions("member.payment.manage")
public void index() {
}
@At
@ViReturn
@RequiresPermissions("member.payment.manage")
public Object pageData(PageForm pageForm,
@Param(value = "year", required = false) String year,
@Param(value = "projectName", required = false) String projectName) {
Sql sql = Sqls.create("select project.*,IF((SELECT count(1) FROM member_payment_info WHERE paymentProjectId = project.id)>0,TRUE,FALSE) created from member_payment_project project $condition");
CndPlus cnd = CndPlus.create();
cnd.andEX("project.`year`", "=", year);
if (Strings.isNotBlank(projectName)) {
cnd.and(Cnd.likeEX("project.projectName", projectName));
}
// cnd.desc("project.`year`");
cnd.desc("project.createTime");
sql.setCondition(cnd);
return memberPaymentService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
}
/**
* 是否开启
*
* @param id 项目Id
* @return
*/
@At
@ViReturn
@RequiresPermissions("member.payment.manage")
public Object openClosedProject(String id) {
//位运算 取反
memberPaymentService.dao().update(MemberPaymentProject.class,
Chain.makeSpecial("isDisabled", "isDisabled ^ 1"),
Cnd.where("id", "=", id));
return null;
}
/**
* 添加或修改缴费项目
*
* @param paymentProject
* @return
*/
@At
@ViReturn
@RequiresPermissions("member.payment.manage")
public Object doSave(MemberPaymentProject paymentProject) {
memberPaymentService.insertOrUpdate(paymentProject);
return null;
}
/**
* 设置缴费人员
*
* @param id 缴费项目Id
* @param isRenew 是否更行缴费人员
* @return
*/
@At
@ViReturn
@RequiresPermissions("member.payment.manage")
public Object doSetPayment(String id, Boolean isRenew) {
//如果不是更新缴费人员,就删除该项目下的所有待缴费信息,再重新设置
if (!isRenew) {
memberPaymentService.clear(Cnd.where("paymentProjectId", "=", id));
}
//获取缴费配置
MemberPaymentConfig config = memberPaymentService.getConfig();
List<MemberPaymentConfig.PayStandards> payStandards = config.getPayStandards();
//缴费人员类型
List<String> personTypeList = new ArrayList<>();
payStandards.forEach(v->{
personTypeList.addAll(v.getPersonTypes());
});
//获取所有有入会时间的会员
List<Sys_user> memberList = memberPaymentService.dao().query(Sys_user.class, Cnd.where("member", "=", 1).and("memberJoinTime","is not",null).and("personType","in",personTypeList));
//获取该项目下的代缴人员
List<String> paymentUserIdList = memberPaymentService.query(Cnd.where("paymentProjectId", "=", id)).stream().map(MemberPaymentInfo::getUserId).collect(Collectors.toList());
//过滤出需要新增到记录表中的人员
List<Sys_user> needInsertUserIds = memberList.stream().filter(v -> !paymentUserIdList.contains(v.getId())).collect(Collectors.toList());
//获取缴费项目
MemberPaymentProject project = memberPaymentService.dao().fetch(MemberPaymentProject.class, id);
//该项目的缴费月份是几月到几月,转为数组,判断新入职教工应缴费几个月
String[] strings = project.getPaymentMonth().substring(0, project.getPaymentMonth().length() - 1).split("-");
DateTime beginDate = DateUtil.parse(project.getYear() + "-" + strings[0] + "-01");
//获取月份的最后一天
DateTime endDate = DateUtil.endOfMonth(DateUtil.parse(project.getYear() + "-" + strings[1] + "-01"));
List<MemberPaymentInfo> memberPaymentInfos = new ArrayList<>();
needInsertUserIds.forEach(v -> {
MemberPaymentInfo paymentInfo = new MemberPaymentInfo();
//如果是新入职教工,计算需要缴纳的月数
if (v.getMemberJoinTime().after(beginDate) && v.getMemberJoinTime().before(endDate)){
long differMonth = DateUtil.betweenMonth(v.getMemberJoinTime(), endDate, false);
paymentInfo.setPaymentMonth(String.valueOf(differMonth));
} else {
paymentInfo.setPaymentMonth(config.getPaidDuration());
}
paymentInfo.setUserId(v.getId());
paymentInfo.setLoginname(v.getLoginname());
paymentInfo.setPaymentProjectId(id);
paymentInfo.setPayment(false);
memberPaymentInfos.add(paymentInfo);
});
if (memberPaymentInfos.size() < 500) {
memberPaymentService.insert(memberPaymentInfos);
} else {
List<List<MemberPaymentInfo>> splitList = CollectionUtil.split(memberPaymentInfos, 500);
NutTxDao nutTxDao = new NutTxDao(memberPaymentService.dao()).setDebug(true);
nutTxDao.beginRC();
ExecutorService executorService = Executors.newWorkStealingPool();
List<Callable<Object>> taskList = new ArrayList<>();
for (List<MemberPaymentInfo> everyList : splitList) {
taskList.add(() -> nutTxDao.insert(everyList).size());
}
List<Future<Object>> futureList = null;
AtomicInteger atomicInteger = new AtomicInteger();
try {
futureList = executorService.invokeAll(taskList);
for (Future<Object> future : futureList) {
atomicInteger.getAndAdd((Integer) future.get());
}
if (atomicInteger.get() != memberPaymentInfos.size()) {
throw new RuntimeException("插入数据与期望数据条数不符");
}
nutTxDao.commit();
} catch (Exception e) {
nutTxDao.rollback();
throw new RuntimeException(e);
} finally {
executorService.shutdown();
}
}
return null;
}
/**
* 删除
*
* @param id 项目Id
* @return
*/
@At
@RequiresPermissions("member.payment.manage")
@Aop(TransAop.READ_COMMITTED)
public Object doRemove(String id) {
int paymentCount = memberPaymentService.count(Cnd.where("paymentProjectId", "=", id).and("isPayment", "=", 1));
if (paymentCount > 0) {
return Result.error().addMsg("该项目已有人完成缴费,请将缴费人员设置为未缴后再进行删除!");
}
memberPaymentService.dao().clear(MemberPaymentProject.class, Cnd.where("id", "=", id));
memberPaymentService.clear(Cnd.where("paymentProjectId", "=", id));
return Result.success();
}
/**
* 获取全部缴费项目
*
* @param year
* @return
*/
@At
@ViReturn
@RequiresPermissions("member.payment.manage")
public Object getAllProject(String year) {
CndPlus cnd = CndPlus.create();
cnd.and("isDisabled", "=", 0);
if (Strings.isNotBlank(year)) {
cnd.and("`year`", "=", year);
}
cnd.desc("createTime");
cnd.desc("year");
return memberPaymentService.dao().query(MemberPaymentProject.class, cnd);
}
@At("/findOne")
@ViReturn
public Object findOne(String id) {
return memberPaymentService.findOneProject(id);
}
@At
@ViReturn
@RequiresPermissions("member.payment.manage")
public Object isMonthCreatedByYear(@Param("year") String year, @Param("monthSelect") String monthSelect, @Param("id") String projectId) {
List<NutMap> nutMapList = Json.fromJsonAsList(NutMap.class, monthSelect);
for (NutMap nutMap : nutMapList) {
int count = memberPaymentService.dao().count(MemberPaymentProject.class, Cnd.where("`year`", "=", year).and("paymentMonth", "=", nutMap.getString("label")));
nutMap.setv("code", count > 0 ? 1 : 0);
}
return nutMapList;
}
}
@@ -0,0 +1,338 @@
package io.v.nutz.zhgh.memberCost.controller.payment;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import cn.hutool.core.util.StrUtil;
import io.v.nutz.base.annontation.ViReturn;
import io.v.nutz.base.dao.CndPlus;
import io.v.nutz.base.query.PageForm;
import io.v.nutz.base.result.Result;
import io.v.nutz.base.utils.MsgApi;
import io.v.nutz.base.utils.Vi;
import io.v.nutz.base.utils.ViTool;
import io.v.nutz.sys.models.Sys_union;
import io.v.nutz.sys.services.SysUserService;
import io.v.nutz.web.commons.utils.ShiroUtil;
import io.v.nutz.zhgh.memberCost.model.MemberPaymentInfo;
import io.v.nutz.zhgh.memberCost.service.MemberPaymentService;
import io.v.nutz.zhgh.memberCost.template.MemberPaymentTemp;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.annotation.AdaptBy;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;
import org.nutz.mvc.upload.TempFile;
import org.nutz.mvc.upload.UploadAdaptor;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@IocBean
@Slf4j
@Ok("json:full")
@At("/platform/member/payment/summary")
public class MemberPaymentSummaryController {
@Inject
private MemberPaymentService memberPaymentService;
@Inject
private SysUserService sysUserService;
@Inject
private MsgApi msgApi;
@At("")
@Ok("beetl:/platform/memberCost/payment/summary.html")
@RequiresPermissions("member.payment.summary")
public void index() {
}
public Sql dataSql(String pageOrderName, String pageOrderBy, String searchName, String searchKeyword,
String unionId, String unitId, String threeUnitId, String unionGroupId,
String personType, String userState, String paymentProjectId, String year,
String isPay) {
Sql sql = Sqls.create("""
SELECT
mpi.*,
IF(mpi.isPayment = 1,'已缴费','未缴费') AS isPay,
mpp.projectName,
u.username,
u.sex,
u.member,
u.welfareMember,
u.personType,
u.userState,
u.unionname,
u.unionid,
u.unitname,
u.unitid,
u.threeUnitName,
u.threeUnitCode,
u.unionGroupName,
u.mobile,
u.birthday
FROM
`member_payment_info` mpi
LEFT JOIN `user` u ON u.id = mpi.userId
left join `member_payment_project` mpp on mpp.id = mpi.paymentProjectId
$condition
""");
CndPlus cnd = CndPlus.create();
if (StrUtil.isNotBlank(searchName) && StrUtil.isNotBlank(searchKeyword)) {
cnd.and(Cnd.likeEX(searchName, searchKeyword));
}
if (!ShiroUtil.hasAnyRoles("sysadmin,A06,H03")) {
if (ShiroUtil.hasRole("H04")) {
cnd.and("u.unionid", "=", Vi.getUnionId());
} else {
cnd.and("u.unionGroupId", "in", io.v.nutz.web.commons.utils.ShiroUtil.getUnionGroupIds());
}
}
cnd.andEX("mpp.`year`", "=", year);
cnd.andEX("mpi.paymentProjectId", "=", paymentProjectId);
if (Strings.isNotBlank(isPay) && !"null".equals(isPay)) {
cnd.andEX("mpi.isPayment", "=", "true".equals(isPay) ? 1 : 0);
}
cnd.andEX("u.unionid", "=", unionId);
cnd.andEX("u.unitid", "=", unitId);
cnd.andEX("u.threeUnitId", "=", threeUnitId);
cnd.andEX("u.unionGroupId", "=", unionGroupId);
cnd.andEX("u.personType", "=", personType);
cnd.andEX("u.userState", "=", userState);
cnd.groupBy("u.id");
if (StrUtil.isNotBlank(pageOrderName) && StrUtil.isNotBlank(pageOrderBy)) {
cnd.orderBy(pageOrderName, pageOrderBy.equalsIgnoreCase("ascending") ? "ASC" : "DESC");
} else {
cnd.desc("mpi.isPayment");
cnd.desc("mpi.paymentTime");
cnd.asc("u.loginname");
}
sql.setCondition(cnd);
return sql;
}
@At
@ViReturn
@RequiresPermissions("member.payment.summary")
public Object pageData(PageForm pageForm,
@Param(value = "unionId", required = false) String unionId,
@Param(value = "unitId", required = false) String unitId,
@Param(value = "unionGroupId", required = false) String unionGroupId,
@Param(value = "threeUnitId", required = false) String threeUnitId,
@Param(value = "personType", required = false) String personType,
@Param(value = "userState", required = false) String userState,
@Param(value = "paymentProjectId", required = false) String paymentProjectId,
@Param(value = "year", required = false) String year,
@Param(value = "isPay", required = false) String isPay) {
Sql sql = this.dataSql(pageForm.getPageOrderName(), pageForm.getPageOrderBy(), pageForm.getSearchName(),
pageForm.getSearchKeyword(), unionId, unitId, threeUnitId, unionGroupId,
personType, userState, paymentProjectId, year, isPay);
return memberPaymentService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
}
@At
@ViReturn
@RequiresPermissions("member.payment.summary")
public Object modify(@Param("ids") String[] ids, String paymentMoney, boolean isPay, String remark) {
List<String> idList = Arrays.asList(ids);
if (Lang.isNotEmpty(idList)) {
if (isPay) {
//未缴费设为已缴费
memberPaymentService.update(Chain.make("paymentMoney", paymentMoney)
.add("remark", remark).add("isPayment", 1)
.add("paymentTime", new Date()),
Cnd.where("id", "in", idList));
} else {
//已缴费设为未缴费
memberPaymentService.update(Chain.make("paymentMoney", null)
.add("isPayment", 0).add("paymentTime", null),
Cnd.where("id", "in", idList));
}
}
return null;
}
@At
@ViReturn
@RequiresPermissions("member.payment.summary")
public Object doRemoveById(String id) {
memberPaymentService.delete(id);
return null;
}
@At
@Ok("void")
@RequiresPermissions("member.payment.summary")
public void downloadImportTemp(HttpServletResponse response) {
try {
ViTool.excelResponse(response, "会员缴费导入模版.xlsx");
ExportParams exportParams = new ExportParams();
exportParams.setType(ExcelType.XSSF);
Workbook sheets = ExcelExportUtil.exportExcel(exportParams, MemberPaymentTemp.class, new ArrayList<>());
ServletOutputStream outputStream = response.getOutputStream();
sheets.write(outputStream);
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
@At
@RequiresPermissions("member.payment.summary")
@AdaptBy(type = UploadAdaptor.class, args = {"ioc:fileUpload"})
public Object doImport(TempFile file, String projectId) {
try {
List<MemberPaymentTemp> memberPaymentTempList = ExcelImportUtil.importExcel(file.getFile(), MemberPaymentTemp.class, new ImportParams());
List<MemberPaymentInfo> paymentUserList = memberPaymentService.query(Cnd.where("paymentProjectId", "=", projectId));
Map<String, MemberPaymentInfo> infoMap = paymentUserList.stream().collect(Collectors.toMap(MemberPaymentInfo::getLoginname, v -> v));
List<MemberPaymentTemp> errorInfos = new ArrayList<>();
List<MemberPaymentInfo> needInsertList = new ArrayList<>();
//缴费比例
BigDecimal paymentProportion = new BigDecimal("0.005");
memberPaymentTempList.forEach(v -> {
if (infoMap.containsKey(v.getLoginname().trim())) {
if (Strings.isNotBlank(v.getPaymentBaseOne()) && Strings.isNotBlank(v.getPaymentBaseTwo())) {
MemberPaymentInfo memberPaymentInfo = infoMap.get(v.getLoginname().trim());
memberPaymentInfo.setPayment(true);
memberPaymentInfo.setPaymentBaseOne(v.getPaymentBaseOne());
memberPaymentInfo.setPaymentBaseTwo(v.getPaymentBaseTwo());
//缴费金额,精度计算
DecimalFormat df = new DecimalFormat("#0.000");
BigDecimal baseOne = new BigDecimal(v.getPaymentBaseOne());
BigDecimal baseTwo = new BigDecimal(v.getPaymentBaseTwo());
String paymentMoney = df.format((baseOne.add(baseTwo)).multiply(paymentProportion));
memberPaymentInfo.setPaymentMoney(paymentMoney);
// memberPaymentInfo.setPaymentTime(v.getPaymentTime() != null ? v.getPaymentTime() : new Date());
memberPaymentInfo.setRemark(v.getRemark());
memberPaymentInfo.setPaymentMethod("导入");
needInsertList.add(memberPaymentInfo);
} else {
v.setResult("请填写该教职工的缴费数据!");
errorInfos.add(v);
}
} else {
v.setResult("该教工可能不在此次缴费项目之中,请重新设置缴费人员或检查人员是否正确!");
errorInfos.add(v);
}
});
int i = 0;
if (Lang.isNotEmpty(needInsertList)) {
i = memberPaymentService.updateIgnoreNull(needInsertList);
}
if (Lang.isNotEmpty(errorInfos)) {
NutMap nutMap = NutMap.NEW();
nutMap.setv("totalCount", memberPaymentTempList.size());
nutMap.setv("successCount", i);
nutMap.setv("errorCount", errorInfos.size());
nutMap.setv("errorList", errorInfos.stream().map(v -> {
return NutMap.NEW().addv("工号", v.getLoginname()).addv("姓名", v.getUsername()).addv("错误原因", v.getResult());
}).collect(Collectors.toList()));
return Result.success(nutMap);
}
return Result.success();
} catch (Exception e) {
e.printStackTrace();
return Result.error();
}
}
@At
@Ok("void")
@RequiresPermissions("member.payment.summary")
public void doExport(@Param(value = "searchName", required = false) String searchName,
@Param(value = "searchKeyword", required = false) String searchKeyword,
@Param(value = "unionId", required = false) String unionId,
@Param(value = "unitId", required = false) String unitId,
@Param(value = "unionGroupId", required = false) String unionGroupId,
@Param(value = "threeUnitId", required = false) String threeUnitId,
@Param(value = "personType", required = false) String personType,
@Param(value = "userState", required = false) String userState,
@Param(value = "paymentProjectId", required = false) String paymentProjectId,
@Param(value = "year", required = false) String year,
@Param(value = "isPay", required = false) String isPay,
boolean isZip, HttpServletResponse response) {
Sql sql = this.dataSql(null, null, searchName, searchKeyword, unionId, unitId, threeUnitId,
unionGroupId, personType, userState, paymentProjectId, year, isPay);
List<NutMap> list = memberPaymentService.listMap(sql);
NutMap nutMap = list.stream().findFirst().orElse(null);
List<Sys_union> unionIdList = memberPaymentService.dao().query(Sys_union.class, Cnd.NEW());
try {
assert nutMap != null;
if (isZip) {
response.setContentType("application/octet-stream");
response.setHeader("content-disposition", "attachment;filename="
+ URLEncoder.encode(nutMap.getString("projectName") + "缴费详情.zip", "UTF-8"));
ZipOutputStream zipOutputStream = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()));
for (Sys_union union : unionIdList) {
String fileName = union.getUnioncode() + union.getUnionname().replaceAll("/", "、") + "缴费记录表.xlsx";
zipOutputStream.putNextEntry(new ZipEntry(fileName));
List<NutMap> unionUserList = list.stream().filter(v -> Strings.isNotBlank(v.getString("unionid")) && v.getString("unionid").equals(union.getId())).collect(Collectors.toList());
Workbook workbook = memberPaymentService.exportOrZip(unionUserList, response.getOutputStream());
workbook.write(zipOutputStream);
zipOutputStream.closeEntry();
response.flushBuffer();
}
zipOutputStream.flush();
zipOutputStream.close();
} else {
ViTool.excelResponse(response, nutMap.getString("projectName") + "缴费详情表.xlsx");
Workbook workbook = memberPaymentService.exportOrZip(list, response.getOutputStream());
workbook.write(response.getOutputStream());
}
} catch (Exception e) {
e.printStackTrace();
}
}
@At
@ViReturn
@RequiresPermissions("member.payment.summary")
public Object sendPaymentMsg(@Param(value = "id", required = false) String id) {
if (Strings.isNotBlank(id)) {
List<MemberPaymentInfo> paymentInfos = memberPaymentService.query(Cnd.where("isPayment", "=", 0));
// msgApi.sendMsg();
} else {
MemberPaymentInfo paymentInfo = memberPaymentService.fetch(id);
// msgApi.sendMsg();
}
return null;
}
}
@@ -0,0 +1,51 @@
package io.v.nutz.zhgh.memberCost.model;
import lombok.Data;
import org.nutz.dao.entity.annotation.*;
import org.nutz.dao.interceptor.annotation.PrevInsert;
import org.nutz.lang.util.NutMap;
import java.io.Serializable;
import java.util.List;
@Data
@Table
public class MemberPaymentConfig {
@Column
@Name
@Comment("ID")
@ColDefine(type = ColType.VARCHAR, width = 32)
@PrevInsert(uu32 = true)
private String id;
@Column
@Comment("缴费标准")
@ColDefine(type = ColType.MYSQL_JSON)
private List<PayStandards> payStandards;
@Column
@Comment("未缴费退会时长")
@ColDefine(type = ColType.VARCHAR,width = 10)
private String unPaidExitDuration;
@Column
@Comment("退会模式(1,。自动退会;2.人工退会)")
@ColDefine(type = ColType.VARCHAR,width = 10)
private String exitMode;
@Column
@Comment("缴费时长(多久缴费一次)")
@ColDefine(type = ColType.VARCHAR,width = 10)
private String paidDuration;
@Data
public static class PayStandards implements Serializable {
private String payPersonnel;
private String payMode;
private List<String> personTypes;
private String payModeValue;
private List<NutMap> payModeValueList;
}
}
@@ -0,0 +1,90 @@
package io.v.nutz.zhgh.memberCost.model;
import lombok.Data;
import org.nutz.dao.entity.annotation.*;
import org.nutz.dao.interceptor.annotation.PrevInsert;
import java.util.Date;
@Data
@Table
public class MemberPaymentInfo {
@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 userId;
@Column
@Comment("工号")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String loginname;
@Column
@Comment("缴费项目id")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String paymentProjectId;
@Column
@Comment("工资")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String wages;
@Column
@Comment("是否缴费")
@ColDefine(type = ColType.BOOLEAN)
private boolean isPayment;
@Column
@Comment("缴费基数1")
@ColDefine(type = ColType.VARCHAR,width = 32)
private String paymentBaseOne;
@Column
@Comment("缴费基数2")
@ColDefine(type = ColType.VARCHAR,width = 32)
private String paymentBaseTwo;
@Column
@Comment("缴费金额")
@ColDefine(type = ColType.VARCHAR,width = 32)
private String paymentMoney;
@Column
@Comment("缴费日期")
@ColDefine(type = ColType.DATETIME)
private Date paymentTime;
@Column
@Comment("备注")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String remark;
@Column
@Comment("支付记录Id")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String payId;
@Column
@Comment("支付宝记录Id")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String tradeNo;
@Column
@Comment("缴费方式")
@ColDefine(type = ColType.VARCHAR, width = 20)
private String paymentMethod;
@Column
@Comment("缴费月份")
@ColDefine(type = ColType.VARCHAR, width = 10)
private String paymentMonth;
}
@@ -0,0 +1,45 @@
package io.v.nutz.zhgh.memberCost.model;
import lombok.Data;
import org.nutz.dao.entity.annotation.*;
import org.nutz.dao.interceptor.annotation.PrevInsert;
import java.util.Date;
@Data
@Table
public class MemberPaymentProject {
@Column
@Name
@Comment("ID")
@ColDefine(type = ColType.VARCHAR, width = 32)
@PrevInsert(uu32 = true)
private String id;
@Column
@Comment("年度")
@ColDefine(type = ColType.VARCHAR, width = 4)
private String year;
@Column
@Comment("项目名称")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String projectName;
@Column
@Comment("是否开启")
@ColDefine(type = ColType.BOOLEAN)
private boolean isDisabled;
@Column
@Comment("创建时间")
@ColDefine(type = ColType.DATETIME)
private Date createTime;
@Column
@Comment("缴费月份")
@ColDefine(type = ColType.VARCHAR, width = 10)
private String paymentMonth;
}
@@ -0,0 +1,15 @@
package io.v.nutz.zhgh.memberCost.service;
import io.v.nutz.base.service.ViService;
import java.util.Map;
public interface AlipayService extends ViService {
/**
* 支付宝开放平台接收 request请求对象后
* @return
*/
String tradeCreate( String money, String paymentProjectId) throws Exception;
String tradeNotify(Map<String, String> params) ;
}
@@ -0,0 +1,20 @@
package io.v.nutz.zhgh.memberCost.service;
import io.v.nutz.base.service.ViService;
import io.v.nutz.zhgh.memberCost.model.MemberPaymentConfig;
import io.v.nutz.zhgh.memberCost.model.MemberPaymentInfo;
import io.v.nutz.zhgh.memberCost.model.MemberPaymentProject;
import org.apache.poi.ss.usermodel.Workbook;
import org.nutz.lang.util.NutMap;
import java.io.OutputStream;
import java.util.List;
public interface MemberPaymentService extends ViService<MemberPaymentInfo> {
MemberPaymentProject findOneProject(String id);
Workbook exportOrZip(List<NutMap> list, OutputStream outputStream)throws Exception;
MemberPaymentConfig getConfig();
}
@@ -0,0 +1,140 @@
package io.v.nutz.zhgh.memberCost.service.impl;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayConstants;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradeWapPayResponse;
import io.v.nutz.base.service.impl.ViServiceImpl;
import io.v.nutz.web.commons.utils.ShiroUtil;
import io.v.nutz.zhgh.memberCost.controller.AlipayClientConfig;
import io.v.nutz.zhgh.memberCost.model.MemberPaymentInfo;
import io.v.nutz.zhgh.memberCost.service.AlipayService;
import lombok.extern.slf4j.Slf4j;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.IocBean;
import java.util.Date;
import java.util.Map;
/**
* @ClassName AlipayNewServiceImpl
* @Description TODO
* @Author zhf
* @Date 2024/1/25 15:38
*/
@Slf4j
@IocBean(args = {"refer:dao"})
public class AlipayNewServiceImpl extends ViServiceImpl implements AlipayService {
public AlipayNewServiceImpl(Dao dao) {
super(dao);
}
DefaultAlipayClient alipayClient = new DefaultAlipayClient(AlipayClientConfig.serverUrl,
AlipayClientConfig.appId,
AlipayClientConfig.privateKey,
AlipayConstants.FORMAT_JSON,
AlipayConstants.CHARSET_UTF8,
AlipayClientConfig.alipayPublicKey,
AlipayConstants.SIGN_TYPE_RSA2);
@Override
public String tradeCreate(String money, String paymentProjectId) throws Exception {
String outTradeNo = String.valueOf(new Date().getTime());
AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
//支付宝公共参数
request.setReturnUrl("http://sansi.ltd/mobile/memberCost/AlipayClient/tradeNotify");
//面向对象封装业务参数
AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
model.setOutTradeNo(outTradeNo);
model.setTotalAmount(money);
model.setSubject("会员入会会费");
model.setProductCode("QUICK_WAP_WAY");
model.setSellerId(AlipayClientConfig.sellerId);
model.setTimeoutExpress("30m");
model.setQuitUrl("http://sansi.ltd/mobile/memberCost/list");
request.setBizModel(model);
//执行请求,调用支付宝
AlipayTradeWapPayResponse response = alipayClient.pageExecute(request, "POST");
if (response.isSuccess()) {
dao().update(MemberPaymentInfo.class, Chain.make("payId", outTradeNo), Cnd.where("paymentProjectId", "=", paymentProjectId)
.and("userId", "=", ShiroUtil.getUserId()));
log.info("调用成功,返回结果:[{}]", response.getBody());
return response.getBody();
} else {
log.info("调用失败!!");
}
return null;
}
@Override
public String tradeNotify(Map<String, String> params) {
String total_amount = params.get("total_amount");
String out_trade_no = params.get("out_trade_no");
String trade_no = params.get("trade_no");
//
String result = "failure";
try {
//异步通知验签
boolean signVerified = AlipaySignature.rsaCheckV1(params,
AlipayClientConfig.alipayPublicKey,
AlipayConstants.CHARSET_UTF8,
AlipayConstants.SIGN_TYPE_RSA2);
if (!signVerified) {
// TODO 验签失败则记录异常日志,并在response中返回failure.
log.error("支付成功,异步通知验签失败!");
return result;
}
log.info("支付成功,异步通知验签成功!");
//TODO 验签成功后,按照支付结果异步通知中的描述,对支付结果中的业务内容进行二次校验
//1.验证out_trade_no 是否为商家系统中创建的订单号
String outTradeNo = params.get("out_trade_no");
if (!outTradeNo.equals(out_trade_no)) {
log.error("订单号不一致");
return result;
}
//2.判断 total_amount 是否确实为该订单的实际金额
String totalAmount = params.get("total_amount");
if (!totalAmount.equals(total_amount)) {
log.error("订单的实际金额不一致");
return result;
}
//3.校验通知中的 seller_id是否为 out_trade_no 这笔单据的对应的操作方
String sellerId = params.get("seller_id");
if (!sellerId.equals(AlipayClientConfig.sellerId)) {
log.error("商家PID校验失败");
return result;
}
//4.验证 app_id 是否为该商家本身
String appId = params.get("app_id");
if (!appId.equals(AlipayClientConfig.appId)) {
log.error("app_id校验失败");
return result;
}
dao().update(MemberPaymentInfo.class,
Chain.make("isPayment", true)
.add("paymentMoney", total_amount)
.add("paymentTime", new Date())
.add("tradeNo", trade_no),
Cnd.where("userId", "=", ShiroUtil.getUserId()).and("payId", "=", out_trade_no));
//TODO 处理自身业务
result = "->:/mobile/memberCost/list/paySuccess";
} catch (AlipayApiException e) {
e.printStackTrace();
}
return result;
}
}
@@ -0,0 +1,64 @@
package io.v.nutz.zhgh.memberCost.service.impl;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import io.v.nutz.base.service.impl.ViServiceImpl;
import io.v.nutz.zhgh.memberCost.model.MemberPaymentConfig;
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 lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@IocBean(args = {"refer:dao"})
public class MemberPaymentServiceImpl extends ViServiceImpl<MemberPaymentInfo> implements MemberPaymentService {
public MemberPaymentServiceImpl(Dao dao) {
super(dao);
}
@Override
public MemberPaymentProject findOneProject(String id) {
return dao().fetch(MemberPaymentProject.class, id);
}
@Override
public Workbook exportOrZip(List<NutMap> list, OutputStream outputStream) throws Exception {
List<ExcelExportEntity> exportEntities = new ArrayList<>();
exportEntities.add(new ExcelExportEntity("工号", "loginname", 20));
exportEntities.add(new ExcelExportEntity("姓名", "username", 20));
// exportEntities.add(new ExcelExportEntity("年度", "year", 20));
exportEntities.add(new ExcelExportEntity("缴费项目", "projectName", 20));
exportEntities.add(new ExcelExportEntity("性别", "sex", 20));
exportEntities.add(new ExcelExportEntity("联系电话", "mobile", 20));
// exportEntities.add(new ExcelExportEntity("身份证号", "idcard", 30));
exportEntities.add(new ExcelExportEntity("在职状态", "userState", 20));
exportEntities.add(new ExcelExportEntity("人员类型", "personType", 20));
exportEntities.add(new ExcelExportEntity("所属工会", "unionname", 20));
exportEntities.add(new ExcelExportEntity("所属单位", "unitname", 30));
exportEntities.add(new ExcelExportEntity("是否缴费", "isPay", 10));
exportEntities.add(new ExcelExportEntity("缴费金额", "paymentMoney", 10));
exportEntities.add(new ExcelExportEntity("缴费时间", "paymentTime", 20));
exportEntities.add(new ExcelExportEntity("备注", "remark", 30));
ExportParams exportParams = new ExportParams();
exportParams.setType(ExcelType.XSSF);
exportParams.setHeight((short) 10);
return ExcelExportUtil.exportExcel(exportParams, exportEntities, list);
}
@Override
public MemberPaymentConfig getConfig() {
return dao().fetch(MemberPaymentConfig.class);
}
}
@@ -0,0 +1,31 @@
package io.v.nutz.zhgh.memberCost.template;
import cn.afterturn.easypoi.excel.annotation.Excel;
import lombok.Data;
@Data
public class MemberPaymentTemp {
@Excel(name = "工号")
String loginname;
@Excel(name = "姓名")
String username;
@Excel(name = "缴纳基数1")
String paymentBaseOne;
@Excel(name = "缴纳基数2")
String paymentBaseTwo;
// @Excel(name = "缴费金额")
// String paymentMoney;
//
// @Excel(name = "缴费日期")
// Date paymentTime;
@Excel(name = "备注")
String remark;
String result;
}
@@ -0,0 +1,357 @@
<!--#
layout("/mobile/platform.html"){
#-->
<style>
.module {
margin: 10px 10px 14px 10px;
box-shadow: 0 8px 12px #ebedf0;
border-radius: 10px;
}
.menu {
display: flex;
flex-wrap: wrap;
row-gap: 10px;
background-color: white;
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
padding: 6px 0px;
}
.menu_img {
position: absolute;
right: 10px;
bottom: 0px;
}
.menu_img_yjf {
position: absolute;
right: 10px;
bottom: 10px;
width: 100px;
height: 60px;
}
.pay_img {
margin-right: 5px;
display: flex;
}
.member_cost .van-cell__title {
display: flex;
align-items: center;
}
</style>
<div id="app" v-cloak>
<van-sticky>
<van-nav-bar @click-left="history.go(-1)" left-arrow
title="会费支付"></van-nav-bar>
</van-sticky>
<div>
<van-tabs @change="pageData" v-model="memberActive">
<van-tab title="未缴费"></van-tab>
<van-tab title="已缴费"></van-tab>
</van-tabs>
<van-row class="module" v-for="p in payList">
<div class="menu">
<van-col :span="8" style="padding: 10px;">
<van-image
height="6rem"
round
src="/assets/mobile/svg/memberPay/hf.svg"
width="6rem"
></van-image>
</van-col>
<van-col :span="16" style="position: relative">
<div style="text-align: left; ">
会费项目:
<div style="font-weight: bold;font-size: 14px">{{p.projectName}}</div>
</div>
<div style="text-align: left; ">
会费标准:
<div v-if="p.selectMode==='1'" style="font-weight: bold;font-size: 14px">{{p.modeValue}}</div>
<div v-if="p.selectMode==='2'" style="font-weight: bold;font-size: 14px">{{p.modeValueName}}
</div>
</div>
<div style="text-align: left; " v-if="p.paymentMoney&&p.isPayment">
已缴费金额:{{p.paymentMoney}}
</div>
<div class="menu_img" v-if="!p.isPayment">
<van-button @click.stop="openAlipay(p)" color="#1867b0" round
size="mini"
style=" width: 75px; height: 30px;"
type="primary">
我要缴费
</van-button>
</div>
<div class="menu_img_yjf" v-if="p.isPayment">
<van-image src="/assets/mobile/svg/memberPay/yjf.svg"
></van-image>
</div>
</van-col>
<el-col span="2">
</el-col>
</div>
</van-row>
<van-action-sheet :close-on-click-overlay="false" :title="viewData.projectName"
style="height: 60%"
v-model="payShow">
<div class="member_cost">
<div v-if="viewData.selectMode==='2'">
<van-cell :value="costFormula" title="会费计算公式"></van-cell>
<van-cell-group>
<van-field :label="o.name" :placeholder="'请输入'+o.name"
@input="moneyInput"
input-align="right"
type="number" v-for="(o,index) in viewData.modeValueList"
v-model="o.value">
<template #left-icon>
<div class="pay_img">
<van-image src="/assets/mobile/svg/memberPay/money.svg"
></van-image>
</div>
</template>
</van-field>
</van-cell-group>
</div>
<div>
<van-radio-group checked-color="#1867b0" v-model="moneyModel">
<van-cell-group>
<van-cell @click="moneyModel = 1" clickable title="支付宝">
<template #icon>
<div class="pay_img">
<van-image src="/assets/mobile/svg/memberPay/zfb.svg"
></van-image>
</div>
</template>
<template #right-icon>
<van-radio :name="1"></van-radio>
</template>
</van-cell>
<van-cell @click="moneyModel = 2" clickable title="微信">
<template #icon>
<div class="pay_img">
<van-image src="/assets/mobile/svg/memberPay/wx.svg"
></van-image>
</div>
</template>
<template #right-icon>
<van-radio :name="2"></van-radio>
</template>
</van-cell>
</van-cell-group>
</van-radio-group>
</div>
</div>
<van-submit-bar
:loading="loading"
:price="money"
@submit="doAlipay"
button-color="#1867b0"
button-text="支付"
></van-submit-bar>
</van-action-sheet>
<van-popup :style="{ height: '100%', width: '100%'}" @close="imgClose" closeable
position="right"
v-model="zfImg">
<van-image src="/assets/mobile/svg/memberPay/zf_img.png"
style="margin-top: 40px; height: 95%;width: 100%"></van-image>
</van-popup>
<van-empty
class="custom-image"
description="暂无缴费记录"
image="https://img01.yzcdn.cn/vant/custom-empty-image.png"
v-if="payList&&payList.length===0"
></van-empty>
</div>
</div>
<script>
const vue = new Vue({
el: '#app',
mixins: [mobileMixins],
data() {
return {
zfImg: false,
costFormula: "",
formData: {},
payShow: false,
loading: false,
moneyModel: "",
money: 0,
viewData: {},
configData: {},
payList: [],
memberActive: 0,
intervalTimer: null,
}
},
methods: {
imgClose() {
clearInterval(this.intervalTimer)
this.loading = false
this.zfImg = false
},
moneyInput() {
const moneys = this.viewData.modeValueList.map(m => Number(m.value))
let money = 0
moneys.forEach(m => {
money += m;
})
if (money <= 10) {
this.money = 1
} else {
money = money.toFixed(2)
this.money = Number(money.replace(".", "")) * 0.5 / 100
}
},
async doAlipay() {
this.doIsPaySuccess()
if (!this.money) {
vant.Toast('请计算会费金额')
return
}
if (!this.moneyModel) {
vant.Toast('请选择支付方式')
return
}
this.loading = true
var u = navigator.userAgent;
var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1; //android终端
var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
let money = 0
if (this.viewData.selectMode === "1") {
money = this.viewData.modeValue
} else if (this.viewData.selectMode === "2") {
const moneys = this.viewData.modeValueList.map(m => Number(m.value))
moneys.forEach(m => {
money += m;
})
money = money * 0.5 / 100
money = money.toFixed(2)
}
if (this.moneyModel === 1) {
let use = window.navigator.userAgent.toLowerCase();
//是否微信浏览器
if (use.match(/MicroMessenger/i) && use.match(/MicroMessenger/i)[0] === "micromessenger") {
this.zfImg = true
return
} else {
if (this.moneyModel === 1) {
const resp = await $.get("/mobile/memberCost/AlipayClient/tradePagePay", {
money: money,
paymentProjectId: this.viewData.paymentProjectId,
})
const div = document.createElement('div');
div.innerHTML = resp; // data就是接口返回的form 表单字符串
document.body.appendChild(div);
//如果是ios,不新开页面直接跳转
if (isiOS) {
document.forms[0].submit();
} else {
document.forms[0].setAttribute('target', '_blank') // 新开窗口跳转
document.forms[0].submit();
}
}
}
} else {
}
},
async getConfig() {
const {data} = await $.get("/platform/member/payment/config/getPaymentConfig")
this.configData = data
},
async openAlipay(p) {
const data = clone(p)
this.money = 0
this.moneyModel = ""
this.viewData = data
if (this.viewData.selectMode === "1") {
this.money = Number(data.modeValue + "00")
}
if (this.viewData.selectMode === "2") {
const names = this.viewData.modeValueList.map(m => m.name)
this.costFormula = "(" + names.join("+") + ")" + "×0.5%"
}
this.payShow = true
},
async pageData() {
const resp = await $.post("/mobile/memberCost/list/pageData", {memberActive: this.memberActive})
if (resp.code === 0) {
const personType = "${@shiro.getPrincipalProperty('personType')}"
const payStandards = this.configData.payStandards
resp.data.forEach(r => {
payStandards.map(p => {
if (p.personTypes.includes(personType)) {
r.selectMode = p.payMode
if (p.payMode === "1") {
r.modeValue = p.payModeValue
} else {
r.modeValueList = p.payModeValueList
const names = r.modeValueList.map(m => m.name)
r.modeValueName = "(" + names.join("+") + ")" + "×0.5%"
}
}
})
})
this.payList = resp.data
}
},
doIsPaySuccess() {
this.intervalTimer = setInterval(async () => {
const resp = await $.get("/mobile/memberCost/list/getPayInfo", {id: this.viewData.id})
if (resp.data.isPayment === true) {
clearInterval(this.intervalTimer)
this.doSearch()
this.payShow = false
this.loading = false
this.zfImg = false
}
}, 4000)
}
},
async created() {
await this.getConfig()
await this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,134 @@
<!--#
layout("/mobile/platform.html"){
#-->
<style>
.head {
position: relative;
height: 300px;
background-color: #02be6e;
}
.head_img {
position: absolute;
top: 35%;
left: 54%;
transform: translate(-50%, -50%);
}
.head_zfcg {
position: absolute;
top: 63%;
left: 52%;
transform: translate(-50%, -50%);
font-size: 20px;
font-weight: 700;
color: #ffffff;
}
.head_xq {
position: absolute;
top: 70%;
left: 15%;
color: #ffffff;
}
.middle_zfxx {
background: radial-gradient(circle, transparent, transparent 8px, #FFFFFF 8px, #FFFFFF) 170px;
height: 20vh;
position: relative;
top: -25px;
margin-left: 25px;
margin-right: 25px;
}
.middle_x {
margin-right: 20px;
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.middle_jine {
position: absolute;
top: 25%;
left: 50%;
transform: translate(-50%, -50%);
font-weight: 700;
font-size: 20px;
color: #02be6e;
}
.middle_zxxx {
position: absolute;
top: 55%;
line-height: 25px;
font-size: 13px;
width: 100%;
}
.app {
background-color: #f7f7f7;
}
</style>
<div id="app" v-cloak>
<div class="head">
<div>
<van-image class="head_img"
src="/assets/mobile/svg/memberPay/paySuccess.svg"></van-image>
<span class="head_zfcg">支付成功</span>
<span class="head_xq">您已付款成功,请返回查看会费情况</span>
</div>
</div>
<div class="middle_zfxx">
<div class="middle_jine">¥{{total_amount}}</div>
<div class="middle_x">
<van-divider dashed></van-divider>
</div>
<div class="middle_zxxx">
<van-row>
<van-col span="8" style="text-align: left;padding-left: 10px;">订单编号</van-col>
<van-col span="16" style="text-align: right;padding-right: 10px;">
{{out_trade_no}}
</van-col>
</van-row>
<van-row>
<van-col span="8" style="text-align: left;padding-left: 10px;">支付时间</van-col>
<van-col span="16" style="text-align: right;padding-right: 10px;">
{{timestamp}}
</van-col>
</van-row>
</div>
</div>
</div>
<script>
const vue = new Vue({
el: '#app',
mixins: [mobileMixins],
data() {
return {
out_trade_no: 0,
total_amount: 0,
timestamp: 0,
}
},
methods: {},
async created() {
this.out_trade_no = GetQueryString("out_trade_no")
this.total_amount = GetQueryString("total_amount")
this.timestamp = GetQueryString("timestamp").replace("+", " ")
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,221 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.el-input-group__append {
border-left: 0;
padding: 0 13px;
height: 40px;
}
</style>
<div id="app" v-cloak>
<guava ref="guava">
<el-card shadow="never">
<div slot="header" class="clearfix">
<h3 style="color: rgb(24, 103, 176);font-family: Microsoft YaHei;">缴费配置</h3>
</div>
<el-form :model="formData" ref="addForm" :rules="rules"
label-width="120px"
style="margin: 10px 0 0 0">
<vi-title title="缴纳标准"></vi-title>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item class="is-required" label="会费缴纳情况" prop="payStandard">
<el-button @click="formData.payStandards.push({payPersonnel: null, payMode: '1', personTypes: null, payModeValue: null,payModeValueList:[{name:'',value:''}]})" icon="el-icon-plus" size="mini"
style="float: right;margin-bottom: 10px">
添加
</el-button>
<span style="color: red">说明:。</span>
<el-table
:data="formData.payStandards"
border
v-fit-columns
size="mini"
style="width: 100%">
<el-table-column label="缴费人员" prop="payPersonnel" width="200">
<template scope="{row,$index}">
<el-form-item :prop="'payStandards.'+$index+'.payPersonnel'"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]"
label-width="0">
<el-input clearable maxlength="100" placeholder="请输入缴费人员"
v-model="row.payPersonnel"></el-input>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="缴费模式" prop="payMode" width="200">
<template scope="{row,$index}">
<el-form-item :prop="'payStandards.'+$index+'.payMode'"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]"
label-width="0">
<el-select placeholder="请选择缴费模式" v-model="row.payMode"
style="width: 100%">
<el-option v-for="item in payModeList" :label="item.value" :value="item.code"></el-option>
</el-select>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="人员类型" prop="personTypes" width="300">
<template slot-scope="{row,$index}">
<el-select multiple placeholder="请选择人员类型" v-model="row.personTypes"
style="width: 100%" clearable>
<el-option v-for="item in personTypeList" :label="item.name" :value="item.code"></el-option>
</el-select>
</template>
</el-table-column>
<el-table-column label="缴费标准" prop="payModeValue">
<template scope="{row,$index}">
<div v-if="row.payMode=='2'">
<el-form-item :prop="'payStandards.'+$index+'.payModeValueList'"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]"
label-width="0">
<div style="display:flex;justify-content: space-between;margin-left: 30px">
(
<template v-for="(o,i) in row.payModeValueList">
<el-input placeholder="请输入" style="width: 120px;"
v-model="o.name">
<el-button @click="row.payModeValueList.splice(i, 1)" slot="append" style="padding: 0 7px;"
icon="el-icon-circle-close"></el-button>
</el-input>
<span v-if="i !== row.payModeValueList.length - 1">+</span>
</template>
) * 0.5%
<div>
<el-button @click="row.payModeValueList.push({name: '',value:''})" size="mini">新增</el-button>
</div>
</div>
</el-form-item>
</div>
<div v-else-if="row.payMode == '1' || row.payMode == '3'">
<el-form-item :prop="'payStandards.'+$index+'.payModeValue'"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]"
label-width="0">
<div v-if="row.payMode == '1'">
<el-input clearable maxlength="100" type="number" placeholder="请输入缴费金额"
v-model="row.payModeValue"></el-input>
</div>
<div v-if="row.payMode == '3'" style="text-align: center">
<span>导入名单</span>
</div>
<!-- <el-input clearable maxlength="100" placeholder="请填写缴费标准"-->
<!-- v-model="row.payModeValue"></el-input>-->
</el-form-item>
</div>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="操作" width="80">
<template slot-scope="scope">
<el-button :disabled="formData.payStandards.length<=1"
@click="formData.payStandards.splice(scope.$index,1)" circle
icon="el-icon-delete"
size="mini"
type="danger"></el-button>
</template>
</el-table-column>
</el-table>
</el-form-item>
</el-col>
</el-row>
<vi-title title="退会标准"></vi-title>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="未缴费退会时间" prop="unPaidExitDuration">
<el-input v-model="formData.unPaidExitDuration">
<template slot="append">月</template>
</el-input>
</el-form-item>
</el-col>
<div style="margin-top: 10px">
<span style="color: red">说明:多长时间未缴纳会费则视为退会处理。</span>
</div>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="退会模式" prop="exitMode">
<el-radio-group v-model="formData.exitMode">
<el-radio label="1" border>自动退会</el-radio>
<el-radio label="2" border>人工退会</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<vi-title title="缴费时长"></vi-title>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="缴费时长" prop="paidDuration">
<el-input v-model="formData.paidDuration">
<template slot="append">月</template>
</el-input>
</el-form-item>
</el-col>
<div style="margin-top: 10px">
<span style="color: red">说明:多长时间缴费一次。</span>
</div>
</el-row>
</el-form>
<el-row class="mt10" justify="center" type="flex">
<el-button @click="doSubmit" style="width: 300px" type="primary">保存
</el-button>
<el-button @click="doSubmit" style="width: 300px" type="primary">提交
</el-button>
</el-row>
</el-card>
</guava>
</div>
<script>
const vue = new Vue({
el: '#app',
mixins: [initTableMixins],
data() {
return {
payModeList:[{code:'1',value:'固定金额缴纳'},{code:'2',value:'按比例缴纳'},{code:'3',value:'导入'}],
formData: {
payStandards: [{payPersonnel: null, payMode: '1', personTypes: null, payModeValue: null,payModeValueList:[{name:'',value:''}]}]
},
rules: {
exit: [{required: true, message: '必填', trigger: ['blur', 'change']}],
},
personTypeList:[],
}
},
methods: {
async doSubmit(){
const formData = clone(this.formData)
formData.payStandards = JSON.stringify(this.formData.payStandards)
const resp = await $.post(loc() + '/doAddOrModify',formData)
if (resp.code === 0){
await this.getPaymentConfig()
this.notifySuccess(resp.msg)
} else {
this.notifyWarning(resp.msg)
}
},
async getPaymentConfig(){
const resp = await $.get(loc() + '/getPaymentConfig')
if (resp.code === 0){
this.formData = {...resp.data}
}
}
},
async created() {
this.personTypeList = await getDictOptions('UserType')
await this.getPaymentConfig()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,408 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.el-input-group__append {
border-left: 0;
padding: 0 7px;
}
</style>
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<div class="search">
<div class="search-item">
<div class="search-item-label">年度:</div>
<div class="search-item-option">
<el-date-picker
:clearable="false"
clearable
@change="doSearch"
placeholder="选择年度"
type="year" style="width: 100%"
v-model="pageForm.year"
value-format="yyyy">
</el-date-picker>
</div>
</div>
<div class="search-item">
<div class="search-item-label">缴费项目:</div>
<div class="search-item-option">
<el-input @keyup.enter.native="doSearch" clearable placeholder="请输入内容"
style="width: 100%"
v-model="pageForm.projectName">
</el-input>
</div>
</div>
<div class="search-query">
<el-button type="primary" icon="el-icon-search" @click="doSearch">搜索
</el-button>
</div>
</div>
</el-card>
<el-card class="mt10" shadow="never">
<table-tool :app="this" label="缴费项目列表">
<template #func>
<el-button @click="openAdd" size="small" type="primary">
新增缴费项目
</el-button>
</template>
</table-tool>
<el-table :data="tableData" :size="tableSize"
@sort-change="pageOrder"
class="vi-table"
ref="table" row-key="id" 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
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
align="center"
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns"
>
<template scope="{row}" v-if="column.prop==='isDisabled'">
<el-switch
:active-value="false"
:inactive-value="true"
@change="(val)=>{projectStatusChange(row.id)}"
active-color="#13ce66"
inactive-color="#ff4949"
v-model="row.isDisabled">
</el-switch>
</template>
</el-table-column>
<el-table-column prop="userOnline" align="center" header-align="center"
label="操作"
width="100px">
<template scope="scope">
<el-dropdown @command="dropdownCommand">
<el-button :loading="submitLoading" plain size="mini">
<i class="ti-settings"></i>
<span class="ti-angle-down"></span>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="{type:'openCode',data:scope.row}">
二维码
</el-dropdown-item>
<el-dropdown-item :command="{type:'view',data:scope.row}">
查看
</el-dropdown-item>
<el-dropdown-item :command="{type:'edit',data:scope.row}">
编辑
</el-dropdown-item>
<el-dropdown-item :command="{type:'doRenew',data:scope.row}"
v-if="scope.row.created">
更新缴费人员
</el-dropdown-item>
<el-dropdown-item :command="{type:'doSet',data:scope.row}">
{{scope.row.created?'重置缴费人员':'生成缴费人员'}}
</el-dropdown-item>
<el-dropdown-item :command="{type:'remove',data:scope.row}">
删除
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #view>
<el-form :model="formData" :rules="formRules" label-width="100px" ref="form">
<vi-title title="缴费项目信息"></vi-title>
<el-form-item label="项目名称" prop="projectName">
<el-input maxlength="100" placeholder="项目名称" v-model="formData.projectName"></el-input>
</el-form-item>
<el-row :gutter="20">
<el-col span="12">
<el-form-item label="缴费年度" prop="year">
<el-date-picker
:clearable="false"
placeholder="选择年度"
type="year" style="width: 100%"
v-model="formData.year"
@change="isMonthCreatedByYear"
value-format="yyyy">
</el-date-picker>
</el-form-item>
</el-col>
<el-col span="12">
<el-form-item label="创建日期" prop="createTime">
<el-date-picker
placeholder="创建日期"
readonly
style="width: 100%"
type="date"
v-model="formData.createTime"
value-format="yyyy-MM-dd">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="缴费月份" prop="paymentMonth" size="medium">
<el-radio-group v-model="formData.paymentMonth">
<el-radio-button v-for="item in monthSelect" :label="item.label"
:disabled="item.code===1"></el-radio-button>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div>
<el-button @click="doSave" v-if="isSubmit" v-loading="submitLoading" style="float: right"
type="primary">
提交
</el-button>
</div>
</template>
<open-qr-code ref="openQRCode"></open-qr-code>
</guava>
</div>
<script>
const vue = new Vue({
el: '#app',
mixins: [initTableMixins],
data() {
return {
isSubmit: true,
pageForm: {
year: moment().format('YYYY'),
},
tableColumns: [
{prop: 'year', label: '年度', sortable: true},
{prop: 'projectName', label: '项目名称', sortable: true},
{prop: 'createTime', label: '创建时间', sortable: true},
{prop: 'isDisabled', label: '开启状态'},
],
formData: {
year: moment().format('YYYY'),
},
formRules: {
projectName: [{required: true, message: '必填', trigger: ['blur', 'change']}],
year: [{required: true, message: '必填', trigger: ['blur', 'change']}],
paymentMonth: [{required: true, message: '必填', trigger: ['blur', 'change']}],
},
paymentConfig: {},
monthSelect: []
}
},
components: {
'guava': httpVueLoader('/components/plugins/Guava.vue'),
'open-qr-code': httpVueLoader('/components/plugins/OpenQRCode.vue'),
},
methods: {
dropdownCommand(command) {
const {type, data} = command
if (type === 'openCode') {
this.openCode(data)
} else if (type === 'view') {
this.openView(data)
} else if (type === 'edit') {
this.openEdit(data)
} else if (type === 'doRenew') {
this.doRenewPayment(data.id)
} else if (type === 'doSet') {
this.doSetPayment(data)
} else if (type === 'remove') {
this.doRemove(data.id)
}
},
openCode(row) {
this.$refs.openQRCode.openCode('/mobile/memberCost/list')
},
openView(data) {
this.formData = {}
this.formData = {...data}
this.isSubmit = false
this.$refs.guava.view()
},
openEdit(data) {
this.formData = {}
this.formData = {...data}
this.isSubmit = true
this.$refs.guava.view()
},
async doRenewPayment(id) {
this.$confirm('系统根据现有的会员,更新当前缴费名单,对已经缴费人员没有影响,请确认是否更新?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
callback: async (a, b) => {
if ("confirm" === a) {
const loading = this.$loading({
lock: true,
text: '数据保存中请稍后',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
this.submitLoading = true
const resp = await $.get(loc() + '/doSetPayment', {id: id, isRenew: true})
this.submitLoading = false
loading.close()
if (resp.code === 0) {
this.pageData()
this.notifySuccess(resp.msg)
} else {
this.notifyWarning(resp.msg)
}
}
}
})
},
async doSetPayment(row) {
let msg = row.created ? "请确认是否重新生成缴费名单,如果确认,系统将清空已缴费的人员信息!" : "确定要生成缴费名单吗?"
this.$confirm(msg, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
callback: async (a, b) => {
if ("confirm" === a) {
const loading = this.$loading({
lock: true,
text: '数据保存中请稍后',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
this.submitLoading = true
const resp = await $.get(loc() + '/doSetPayment', {id: row.id, isRenew: false})
this.submitLoading = false
loading.close()
if (resp.code === 0) {
this.pageData()
this.notifySuccess(resp.msg)
} else {
this.notifyWarning(resp.msg)
}
}
}
})
},
async doRemove(id) {
const confirm = await this.$confirm('您确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
if (confirm === 'confirm') {
const resp = await $.get(loc() + '/doRemove', {id: id})
if (resp.code === 0) {
this.notifySuccess(resp.msg)
this.pageData()
} else {
this.notifyWarning(resp.msg)
}
}
},
openAdd() {
this.formData = {
createTime: moment().format('YYYY-MM-DD HH:mm:ss'),
year: moment().format('YYYY'),
}
this.$refs.guava.view()
this.isMonthCreatedByYear()
},
async doSave() {
const formValid = await this.$refs["form"].validate()
if (formValid) {
this.submitLoading = true
const loading = this.$loading({
lock: true,
text: '数据保存中请稍后',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
const formData = clone(this.formData)
const o = this.monthSelect.find(v => v.label === formData.paymentMonth)
if (o.code === 1) {
this.notifyWarning("该年份下的此月份已创建了项目,请选择其他月份!")
loading.close()
this.submitLoading = false
return
}
const resp = await $.post(loc() + '/doSave', formData)
loading.close()
this.submitLoading = false
if (resp.code === 0) {
this.notifySuccess(resp.msg)
this.$refs.guava.index()
this.pageData()
} else {
this.notifyWarning(resp.msg)
}
}
},
async projectStatusChange(id) {
const resp = await $.post(loc() + '/openClosedProject', {id: id})
if (resp.code === 0) {
this.notifySuccess(resp.msg)
this.pageData()
} else {
this.notifyWarning(resp.msg)
}
},
async getPaymentConfig() {
const resp = await $.get('/platform/member/payment/config/getPaymentConfig')
if (resp.code === 0) {
this.paymentConfig = resp.data
const arr = []
let monthHalve = this.paymentConfig.paidDuration
let halve = 12 / monthHalve
for (let i = 1; i <= halve; i++) {
let value = (Number(i) - 1) * monthHalve + 1;
let followValue = i * monthHalve
if (i === 1) {
arr.push({label: i + '-' + monthHalve + '月', code: 0})
} else {
arr.push({label: value + '-' + followValue + '月', code: 0})
}
}
this.monthSelect = arr
}
},
async isMonthCreatedByYear() {
console.log(this.formData.year)
const resp = await $.post(loc() + '/isMonthCreatedByYear', {
year: this.formData.year,
monthSelect: JSON.stringify(this.monthSelect)
})
if (resp.code === 0) {
this.monthSelect = resp.data
}
}
},
async created() {
this.pageData()
await this.getPaymentConfig();
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,489 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<div class="search">
<div class="search-item">
<div class="search-item-label">年度:</div>
<div class="search-item-option">
<el-date-picker
:clearable="false"
@change="doSearch();getProjectList()"
placeholder="选择年度"
type="year" style="width: 100%"
v-model="pageForm.year"
value-format="yyyy">
</el-date-picker>
</div>
</div>
<div class="search-item">
<div class="search-item-label">缴费项目:</div>
<div class="search-item-option">
<el-select placeholder="请选择项目" v-model="pageForm.paymentProjectId"
style="width: 100%;"
clearable="true"
@change="doSearch" @clear="doSearch"
filterable="true">
<el-option v-for="item in paymentProjectList" :label="item.projectName"
:value="item.id"></el-option>
</el-select>
</div>
</div>
<div class="search-item">
<div class="search-item-label">职工信息:</div>
<div class="search-item-option">
<el-input placeholder="请输入内容" clearable v-model="pageForm.searchKeyword"
style="width: 100%"
@keyup.enter.native="doSearch">
<el-select v-model="pageForm.searchName" slot="prepend"
placeholder="查询类型"
style="width: 80px;">
<el-option label="姓名" value="u.username"></el-option>
<el-option label="工号" value="u.loginname"></el-option>
</el-select>
</el-input>
</div>
</div>
<div class="search-item">
<div class="search-item-label">所属工会:</div>
<div class="search-item-option">
<el-select placeholder="所属工会" v-model="pageForm.unionId"
style="width: 100%;"
clearable="true"
@change="flushUnits" @clear="flushUnits"
filterable="true">
<el-option v-for="item in unions" :label="item.unionname"
:value="item.id"></el-option>
</el-select>
</div>
</div>
<div class="search-item">
<div class="search-item-label">所属单位:</div>
<div class="search-item-option">
<el-select placeholder="所属单位" v-model="pageForm.unitId"
style="width: 100%;"
@change="getThreeUnits"
clearable="true"
filterable="true">
<el-option v-for="item in units" :label="item.name"
:value="item.id"></el-option>
</el-select>
</div>
</div>
<template v-if="searchMore">
<template v-if="isThreeUnit">
<div class="search-item">
<div class="search-item-label">工会小组:</div>
<div class="search-item-option">
<el-select v-model="pageForm.unionGroupId" style="width: 100%"
filterable
clearable
@change="getThreeUnits"
placeholder="请选择">
<el-option
v-for="item in unionGroups"
:key="item.id"
:label="item.groupName"
:value="item.id">
</el-option>
</el-select>
</div>
</div>
<div class="search-item">
<div class="search-item-label">组成科室:</div>
<div class="search-item-option">
<el-select v-model="pageForm.threeUnitId" style="width: 100%"
filterable
clearable
placeholder="请选择">
<el-option
v-for="item in threeUnits"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
</div>
</div>
</template>
<div class="search-item">
<div class="search-item-label">人员类型:</div>
<div class="search-item-option">
<dict-select v-model="pageForm.personType" style="width: 100%"
clearable
placeholder="人员类型"
code="UserType"></dict-select>
</div>
</div>
<div class="search-item">
<div class="search-item-label">在职状态:</div>
<div class="search-item-option">
<dict-select v-model="pageForm.userState" style="width: 100%"
clearable
placeholder="在职状态"
code="UserState"></dict-select>
</div>
</div>
</template>
<div class="search-query">
<el-button type="primary" icon="el-icon-search" @click="doSearch">搜索
</el-button>
<more v-model="searchMore"></more>
</div>
</div>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="缴费列表" :app="this">
<template #func>
<el-radio-group @change="doSearch" class="mr10" size="small" v-model="pageForm.isPay">
<el-radio-button :label="null">全部</el-radio-button>
<el-radio-button :label="true">已缴</el-radio-button>
<el-radio-button :label="false">未缴</el-radio-button>
</el-radio-group>
<el-button @click="sendPaymentMsg" size="small" type="primary">
一键催缴
</el-button>
<el-button @click="openModify(false)" size="small" type="primary">
批量设为已缴
</el-button>
<el-button @click="doPaidToUnPaid(false)" size="small" type="primary">
批量设为未缴
</el-button>
<el-button icon="el-icon-s-promotion" type="primary" size="small"
:loading="submitLoading"
@click="openImport">导入
</el-button>
<el-button icon="el-icon-document-add" type="primary" size="small"
:loading="submitLoading"
@click="doExport(false)">导出
</el-button>
<el-button icon="el-icon-document-add" type="primary" size="small"
:loading="submitLoading"
@click="doExport(true)">按分工会导出
</el-button>
</template>
</table-tool>
<el-table :data="tableData" :size="tableSize"
@sort-change="pageOrder"
class="vi-table"
@selection-change="tableHandleSelectionChange"
ref="table" row-key="id" style="width: 100%"
v-loading="tableLoading">
<el-table-column :reserve-selection="true" type="selection"></el-table-column>
<el-table-column :index="indexMethod" align="center" header-align="center"
label="序号" type="index"
width="80px"></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
align="center"
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns"
>
<template scope="{row}" v-if="column.prop==='isPayment'">
<span style="color: #00aa3a" v-if="row.isPayment">已缴</span>
<span style="color: red" v-else>未缴</span>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="操作"
prop="userOnline"
width="250px">
<template scope="{row}">
<el-button v-if="row.isPayment" @click="doPaidToUnPaid(row.id,true)" size="mini" type="primary">
设为未缴
</el-button>
<el-button v-if="!row.isPayment" @click="sendPaymentMsg(row.id)" size="mini" type="primary">
催缴
</el-button>
<el-button v-if="!row.isPayment" @click="openModify(row.id,true)" size="mini" type="primary">
设为已缴
</el-button>
<el-button @click="doDelete(row.id)" size="mini" type="danger">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #edit>
<file-import ref="viewImport" temp_url="/platform/member/payment/summary/downloadImportTemp"
post_url="/platform/member/payment/summary/doImport" :project_id="pageForm.paymentProjectId"
@flush="successImport"
></file-import>
</template>
</guava>
<el-diaLog :close-on-click-modal="false" :visible.sync="modifyVisible" title="已缴设置" width="35%">
<el-form ref="form" :model="formData" :rules="formRules" label-width="80px">
<el-form-item label="缴费金额" prop="paymentMoney">
<el-input placeholder="请输入要缴费的金额" type="number"
v-model="formData.paymentMoney"></el-input>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input placeholder="请输入备注" type="text"
v-model="formData.remark"></el-input>
</el-form-item>
</el-form>
<div style="text-align: right">
<span>
<el-button @click="modifyVisible = false">取 消</el-button>
<el-button @click="doSubmit" type="primary">确 定</el-button>
</span>
</div>
</el-diaLog>
</div>
<script>
const vue = new Vue({
el: '#app',
mixins: [initTableMixins],
data() {
return {
paymentProjectList:[],
units:[],
unions:[],
tableColumns: [
{prop: 'loginname', label: '工号', sortable: true},
{prop: 'username', label: '姓名'},
{prop: 'sex', label: '性别'},
{prop: 'mobile', label: '联系电话'},
{prop: 'personType', label: '人员类型', sortable: true},
{prop: 'userState', label: '在职状态', sortable: true},
{prop: 'unionname', label: '所属工会', sortable: true},
{prop: 'unitname', label: '所属单位', sortable: true},
{prop: 'isPayment', label: '是否缴费', sortable: true},
{prop: 'paymentMoney', label: '缴费金额', sortable: true},
],
pageForm:{
year: moment().format('YYYY'),
searchName: 'u.username',
isPay:false,
searchKeyword: '',
unionId: '',
unitId: '',
threeUnitId: '',
unionGroupId: '',
personType: '',
userState: '',
paymentProjectId:'',
},
checkUsers: [],
modifyVisible:false,
formData:{
ids:[]
},
formRules:{
paymentMoney: [{required: true, message: '必填', trigger: ['blur', 'change']}]
},
}
},
components: {
'guava': httpVueLoader('/components/plugins/Guava.vue'),
'file-import': httpVueLoader('/components/plugins/FileImport.vue'),
'dict-select': httpVueLoader('/components/plugins/DictSelect.vue?v=1.0.0'),
},
methods: {
async sendPaymentMsg(id){
const resp = await $.get(loc() + '/sendPaymentMsg',{id:id})
if (resp.code === 0){
this.notifySuccess(resp.msg)
this.pageData()
} else {
this.notifyWarning(resp.msg)
}
},
/**
* 单个将未缴费设为已缴费
* @param id
* @param flag
*/
openModify(id,flag){
this.formData = {
paymentMoney:'',
remark:''
}
if(flag){
this.checkUsers = []
this.checkUsers.push(id)
this.formData.ids = JSON.stringify(this.checkUsers)
}else {
const ids = this.checkUsers.map(obj => obj.id);
this.formData.ids = JSON.stringify(ids)
}
if (!this.checkUsers.length){
this.notifyWarning("请在左侧勾选需要进行操作的数据!")
return
}
this.modifyVisible = true
this.formData.isPay = true
},
async doPaidToUnPaid(id,flag){
this.formData = {
paymentMoney:'',
remark:''
}
if (flag){
this.checkUsers = []
this.checkUsers.push(id)
this.formData.ids = JSON.stringify(this.checkUsers)
} else {
const ids = this.checkUsers.map(obj => obj.id);
this.formData.ids = JSON.stringify(ids)
}
if (!this.checkUsers.length){
this.notifyWarning("请在左侧勾选需要进行操作的数据!")
return
}
const confirm = await this.$confirm('您确定要设为【未缴】吗,此操作不可撤销!', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
if (confirm === 'confirm') {
const resp = await $.post(loc() + '/modify',this.formData)
if (resp.code === 0){
this.$refs.table.clearSelection();
this.checkUsers = []
this.notifySuccess(resp.msg)
this.modifyVisible = false
this.pageData()
} else {
this.notifyWarning(resp.msg)
}
}
},
async doSubmit(){
if (!this.checkUsers.length){
this.notifyWarning("请在左侧勾选需要进行操作的数据!")
return
}
const formValid = await this.$refs["form"].validate()
if (formValid) {
const confirm = await this.$confirm('您确定要更改缴费信息吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
if (confirm === 'confirm') {
const resp = await $.post(loc() + '/modify',this.formData)
if (resp.code === 0){
this.$refs.table.clearSelection();
this.checkUsers = []
this.notifySuccess(resp.msg)
this.modifyVisible = false
this.pageData()
} else {
this.notifyWarning(resp.msg)
}
}
}
},
async doDelete(id){
const confirm = await this.$confirm('您确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
if (confirm === 'confirm') {
const resp = await $.get(loc() + '/doRemoveById', {id: id})
if (resp.code === 0) {
this.notifySuccess(resp.msg)
this.pageData();
} else {
this.notifyWarning(resp.msg)
}
}
},
openImport(){
this.$refs.guava.edit()
this.$refs.viewImport.resetImportData()
},
successImport(){
this.$refs.guava.index()
this.pageData()
},
doExport(isZip){
const {year,paymentProjectId,searchName,searchKeyword,unionId,unitId,threeUnitId, unionGroupId, personType, userState,isPay} = this.pageForm
window.open(loc() + '/doExport?' + searchName + '=' + searchKeyword + '&unionId=' + unionId + '&unitId=' + unitId + '&isPay=' + isPay +
'&year=' + year + '&threeUnitId=' + threeUnitId + '&isZip=' + isZip + '&paymentProjectId=' + paymentProjectId +
'&unionGroupId=' + unionGroupId + '&personType=' + personType + '&userState=' + userState)
},
async flushUnits() {
this.$set(this.pageForm, "unitId", null)
this.$set(this.pageForm, "unionGroupId", null)
this.$set(this.pageForm, "threeUnitId", null)
this.units = []
this.unionGroups = []
this.threeUnits = []
if (this.pageForm.unionId) {
this.units = await getUnits(this.pageForm.unionId)
this.unionGroups = await unionGroupsByUnionId(this.pageForm.unionId)
}
},
tableHandleSelectionChange(val) {
this.checkUsers = val;
},
async getProjectList(){
const resp = await $.get('/platform/member/payment/manage/getAllProject',{year:this.pageForm.year})
if (resp.code === 0){
this.paymentProjectList = resp.data
this.$set(this.pageForm, 'paymentProjectId',this.paymentProjectList ? this.paymentProjectList[0].id : null)
}
},
async doSearch(){
this.pageData()
},
},
async created() {
this.isThreeUnit = await getConfigKey('isThreeUnit') === 'true'
if (this.isThreeUnit) {
this.tableColumns.forEach(v => {
if (["threeUnitName", "unionGroupName"].includes(v.prop)) {
v.checked = 1
}
})
}
if ("${@shiro.hasRole('sysadmin')||@shiro.hasRole('A06')||@shiro.hasRole('H03')}" === 'true') {
this.unions = await getUnions(null, false)
} else {
this.unions = await getUnions(null, true)
this.$set(this.pageForm, 'unionId', this.unions ? this.unions[0].id : null)
this.flushUnits()
}
await this.getProjectList()
this.pageData();
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,221 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.el-input-group__append {
border-left: 0;
padding: 0 13px;
height: 40px;
}
</style>
<div id="app" v-cloak>
<guava ref="guava">
<el-card shadow="never">
<div slot="header" class="clearfix">
<h3 style="color: rgb(24, 103, 176);font-family: Microsoft YaHei;">缴费配置</h3>
</div>
<el-form :model="formData" ref="addForm" :rules="rules"
label-width="120px"
style="margin: 10px 0 0 0">
<vi-title title="缴纳标准"></vi-title>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item class="is-required" label="会费缴纳情况" prop="payStandard">
<el-button @click="formData.payStandards.push({payPersonnel: null, payMode: '1', personTypes: null, payModeValue: null,payModeValueList:[{name:'',value:''}]})" icon="el-icon-plus" size="mini"
style="float: right;margin-bottom: 10px">
添加
</el-button>
<span style="color: red">说明:。</span>
<el-table
:data="formData.payStandards"
border
v-fit-columns
size="mini"
style="width: 100%">
<el-table-column label="缴费人员" prop="payPersonnel" width="200">
<template scope="{row,$index}">
<el-form-item :prop="'payStandards.'+$index+'.payPersonnel'"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]"
label-width="0">
<el-input clearable maxlength="100" placeholder="请输入缴费人员"
v-model="row.payPersonnel"></el-input>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="缴费模式" prop="payMode" width="200">
<template scope="{row,$index}">
<el-form-item :prop="'payStandards.'+$index+'.payMode'"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]"
label-width="0">
<el-select placeholder="请选择缴费模式" v-model="row.payMode"
style="width: 100%">
<el-option v-for="item in payModeList" :label="item.value" :value="item.code"></el-option>
</el-select>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="人员类型" prop="personTypes" width="300">
<template slot-scope="{row,$index}">
<el-select multiple placeholder="请选择人员类型" v-model="row.personTypes"
style="width: 100%" clearable>
<el-option v-for="item in personTypeList" :label="item.name" :value="item.code"></el-option>
</el-select>
</template>
</el-table-column>
<el-table-column label="缴费标准" prop="payModeValue">
<template scope="{row,$index}">
<div v-if="row.payMode=='2'">
<el-form-item :prop="'payStandards.'+$index+'.payModeValueList'"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]"
label-width="0">
<div style="display:flex;justify-content: space-between;margin-left: 30px">
(
<template v-for="(o,i) in row.payModeValueList">
<el-input placeholder="请输入" style="width: 120px;"
v-model="o.name">
<el-button @click="row.payModeValueList.splice(i, 1)" slot="append" style="padding: 0 7px;"
icon="el-icon-circle-close"></el-button>
</el-input>
<span v-if="i !== row.payModeValueList.length - 1">+</span>
</template>
) * 0.5%
<div>
<el-button @click="row.payModeValueList.push({name: '',value:''})" size="mini">新增</el-button>
</div>
</div>
</el-form-item>
</div>
<div v-else-if="row.payMode == '1' || row.payMode == '3'">
<el-form-item :prop="'payStandards.'+$index+'.payModeValue'"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]"
label-width="0">
<div v-if="row.payMode == '1'">
<el-input clearable maxlength="100" type="number" placeholder="请输入缴费金额"
v-model="row.payModeValue"></el-input>
</div>
<div v-if="row.payMode == '3'" style="text-align: center">
<span>导入名单</span>
</div>
<!-- <el-input clearable maxlength="100" placeholder="请填写缴费标准"-->
<!-- v-model="row.payModeValue"></el-input>-->
</el-form-item>
</div>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="操作" width="80">
<template slot-scope="scope">
<el-button :disabled="formData.payStandards.length<=1"
@click="formData.payStandards.splice(scope.$index,1)" circle
icon="el-icon-delete"
size="mini"
type="danger"></el-button>
</template>
</el-table-column>
</el-table>
</el-form-item>
</el-col>
</el-row>
<vi-title title="退会标准"></vi-title>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="未缴费退会时间" prop="unPaidExitDuration">
<el-input v-model="formData.unPaidExitDuration">
<template slot="append">月</template>
</el-input>
</el-form-item>
</el-col>
<div style="margin-top: 10px">
<span style="color: red">说明:多长时间未缴纳会费则视为退会处理。</span>
</div>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="退会模式" prop="exitMode">
<el-radio-group v-model="formData.exitMode">
<el-radio label="1" border>自动退会</el-radio>
<el-radio label="2" border>人工退会</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<vi-title title="缴费时长"></vi-title>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="缴费时长" prop="paidDuration">
<el-input v-model="formData.paidDuration">
<template slot="append">月</template>
</el-input>
</el-form-item>
</el-col>
<div style="margin-top: 10px">
<span style="color: red">说明:多长时间缴费一次。</span>
</div>
</el-row>
</el-form>
<el-row class="mt10" justify="center" type="flex">
<el-button @click="doSubmit" style="width: 300px" type="primary">保存
</el-button>
<el-button @click="doSubmit" style="width: 300px" type="primary">提交
</el-button>
</el-row>
</el-card>
</guava>
</div>
<script>
const vue = new Vue({
el: '#app',
mixins: [initTableMixins],
data() {
return {
payModeList:[{code:'1',value:'固定金额缴纳'},{code:'2',value:'按比例缴纳'},{code:'3',value:'导入'}],
formData: {
payStandards: [{payPersonnel: null, payMode: '1', personTypes: null, payModeValue: null,payModeValueList:[{name:'',value:''}]}]
},
rules: {
exit: [{required: true, message: '必填', trigger: ['blur', 'change']}],
},
personTypeList:[],
}
},
methods: {
async doSubmit(){
const formData = clone(this.formData)
formData.payStandards = JSON.stringify(this.formData.payStandards)
const resp = await $.post(loc() + '/doAddOrModify',formData)
if (resp.code === 0){
await this.getPaymentConfig()
this.notifySuccess(resp.msg)
} else {
this.notifyWarning(resp.msg)
}
},
async getPaymentConfig(){
const resp = await $.get(loc() + '/getPaymentConfig')
if (resp.code === 0){
this.formData = {...resp.data}
}
}
},
async created() {
this.personTypeList = await getDictOptions('UserType')
await this.getPaymentConfig()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,408 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.el-input-group__append {
border-left: 0;
padding: 0 7px;
}
</style>
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<div class="search">
<div class="search-item">
<div class="search-item-label">年度:</div>
<div class="search-item-option">
<el-date-picker
:clearable="false"
clearable
@change="doSearch"
placeholder="选择年度"
type="year" style="width: 100%"
v-model="pageForm.year"
value-format="yyyy">
</el-date-picker>
</div>
</div>
<div class="search-item">
<div class="search-item-label">缴费项目:</div>
<div class="search-item-option">
<el-input @keyup.enter.native="doSearch" clearable placeholder="请输入内容"
style="width: 100%"
v-model="pageForm.projectName">
</el-input>
</div>
</div>
<div class="search-query">
<el-button type="primary" icon="el-icon-search" @click="doSearch">搜索
</el-button>
</div>
</div>
</el-card>
<el-card class="mt10" shadow="never">
<table-tool :app="this" label="缴费项目列表">
<template #func>
<el-button @click="openAdd" size="small" type="primary">
新增缴费项目
</el-button>
</template>
</table-tool>
<el-table :data="tableData" :size="tableSize"
@sort-change="pageOrder"
class="vi-table"
ref="table" row-key="id" 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
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
align="center"
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns"
>
<template scope="{row}" v-if="column.prop==='isDisabled'">
<el-switch
:active-value="false"
:inactive-value="true"
@change="(val)=>{projectStatusChange(row.id)}"
active-color="#13ce66"
inactive-color="#ff4949"
v-model="row.isDisabled">
</el-switch>
</template>
</el-table-column>
<el-table-column prop="userOnline" align="center" header-align="center"
label="操作"
width="100px">
<template scope="scope">
<el-dropdown @command="dropdownCommand">
<el-button :loading="submitLoading" plain size="mini">
<i class="ti-settings"></i>
<span class="ti-angle-down"></span>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="{type:'openCode',data:scope.row}">
二维码
</el-dropdown-item>
<el-dropdown-item :command="{type:'view',data:scope.row}">
查看
</el-dropdown-item>
<el-dropdown-item :command="{type:'edit',data:scope.row}">
编辑
</el-dropdown-item>
<el-dropdown-item :command="{type:'doRenew',data:scope.row}"
v-if="scope.row.created">
更新缴费人员
</el-dropdown-item>
<el-dropdown-item :command="{type:'doSet',data:scope.row}">
{{scope.row.created?'重置缴费人员':'生成缴费人员'}}
</el-dropdown-item>
<el-dropdown-item :command="{type:'remove',data:scope.row}">
删除
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #view>
<el-form :model="formData" :rules="formRules" label-width="100px" ref="form">
<vi-title title="缴费项目信息"></vi-title>
<el-form-item label="项目名称" prop="projectName">
<el-input maxlength="100" placeholder="项目名称" v-model="formData.projectName"></el-input>
</el-form-item>
<el-row :gutter="20">
<el-col span="12">
<el-form-item label="缴费年度" prop="year">
<el-date-picker
:clearable="false"
placeholder="选择年度"
type="year" style="width: 100%"
v-model="formData.year"
@change="isMonthCreatedByYear"
value-format="yyyy">
</el-date-picker>
</el-form-item>
</el-col>
<el-col span="12">
<el-form-item label="创建日期" prop="createTime">
<el-date-picker
placeholder="创建日期"
readonly
style="width: 100%"
type="date"
v-model="formData.createTime"
value-format="yyyy-MM-dd">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="缴费月份" prop="paymentMonth" size="medium">
<el-radio-group v-model="formData.paymentMonth">
<el-radio-button v-for="item in monthSelect" :label="item.label"
:disabled="item.code===1"></el-radio-button>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div>
<el-button @click="doSave" v-if="isSubmit" v-loading="submitLoading" style="float: right"
type="primary">
提交
</el-button>
</div>
</template>
<open-qr-code ref="openQRCode"></open-qr-code>
</guava>
</div>
<script>
const vue = new Vue({
el: '#app',
mixins: [initTableMixins],
data() {
return {
isSubmit: true,
pageForm: {
year: moment().format('YYYY'),
},
tableColumns: [
{prop: 'year', label: '年度', sortable: true},
{prop: 'projectName', label: '项目名称', sortable: true},
{prop: 'createTime', label: '创建时间', sortable: true},
{prop: 'isDisabled', label: '开启状态'},
],
formData: {
year: moment().format('YYYY'),
},
formRules: {
projectName: [{required: true, message: '必填', trigger: ['blur', 'change']}],
year: [{required: true, message: '必填', trigger: ['blur', 'change']}],
paymentMonth: [{required: true, message: '必填', trigger: ['blur', 'change']}],
},
paymentConfig: {},
monthSelect: []
}
},
components: {
'guava': httpVueLoader('/components/plugins/Guava.vue'),
'open-qr-code': httpVueLoader('/components/plugins/OpenQRCode.vue'),
},
methods: {
dropdownCommand(command) {
const {type, data} = command
if (type === 'openCode') {
this.openCode(data)
} else if (type === 'view') {
this.openView(data)
} else if (type === 'edit') {
this.openEdit(data)
} else if (type === 'doRenew') {
this.doRenewPayment(data.id)
} else if (type === 'doSet') {
this.doSetPayment(data)
} else if (type === 'remove') {
this.doRemove(data.id)
}
},
openCode(row) {
this.$refs.openQRCode.openCode('/mobile/memberCost/list')
},
openView(data) {
this.formData = {}
this.formData = {...data}
this.isSubmit = false
this.$refs.guava.view()
},
openEdit(data) {
this.formData = {}
this.formData = {...data}
this.isSubmit = true
this.$refs.guava.view()
},
async doRenewPayment(id) {
this.$confirm('系统根据现有的会员,更新当前缴费名单,对已经缴费人员没有影响,请确认是否更新?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
callback: async (a, b) => {
if ("confirm" === a) {
const loading = this.$loading({
lock: true,
text: '数据保存中请稍后',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
this.submitLoading = true
const resp = await $.get(loc() + '/doSetPayment', {id: id, isRenew: true})
this.submitLoading = false
loading.close()
if (resp.code === 0) {
this.pageData()
this.notifySuccess(resp.msg)
} else {
this.notifyWarning(resp.msg)
}
}
}
})
},
async doSetPayment(row) {
let msg = row.created ? "请确认是否重新生成缴费名单,如果确认,系统将清空已缴费的人员信息!" : "确定要生成缴费名单吗?"
this.$confirm(msg, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
callback: async (a, b) => {
if ("confirm" === a) {
const loading = this.$loading({
lock: true,
text: '数据保存中请稍后',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
this.submitLoading = true
const resp = await $.get(loc() + '/doSetPayment', {id: row.id, isRenew: false})
this.submitLoading = false
loading.close()
if (resp.code === 0) {
this.pageData()
this.notifySuccess(resp.msg)
} else {
this.notifyWarning(resp.msg)
}
}
}
})
},
async doRemove(id) {
const confirm = await this.$confirm('您确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
if (confirm === 'confirm') {
const resp = await $.get(loc() + '/doRemove', {id: id})
if (resp.code === 0) {
this.notifySuccess(resp.msg)
this.pageData()
} else {
this.notifyWarning(resp.msg)
}
}
},
openAdd() {
this.formData = {
createTime: moment().format('YYYY-MM-DD HH:mm:ss'),
year: moment().format('YYYY'),
}
this.$refs.guava.view()
this.isMonthCreatedByYear()
},
async doSave() {
const formValid = await this.$refs["form"].validate()
if (formValid) {
this.submitLoading = true
const loading = this.$loading({
lock: true,
text: '数据保存中请稍后',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
const formData = clone(this.formData)
const o = this.monthSelect.find(v => v.label === formData.paymentMonth)
if (o.code === 1) {
this.notifyWarning("该年份下的此月份已创建了项目,请选择其他月份!")
loading.close()
this.submitLoading = false
return
}
const resp = await $.post(loc() + '/doSave', formData)
loading.close()
this.submitLoading = false
if (resp.code === 0) {
this.notifySuccess(resp.msg)
this.$refs.guava.index()
this.pageData()
} else {
this.notifyWarning(resp.msg)
}
}
},
async projectStatusChange(id) {
const resp = await $.post(loc() + '/openClosedProject', {id: id})
if (resp.code === 0) {
this.notifySuccess(resp.msg)
this.pageData()
} else {
this.notifyWarning(resp.msg)
}
},
async getPaymentConfig() {
const resp = await $.get('/platform/member/payment/config/getPaymentConfig')
if (resp.code === 0) {
this.paymentConfig = resp.data
const arr = []
let monthHalve = this.paymentConfig.paidDuration
let halve = 12 / monthHalve
for (let i = 1; i <= halve; i++) {
let value = (Number(i) - 1) * monthHalve + 1;
let followValue = i * monthHalve
if (i === 1) {
arr.push({label: i + '-' + monthHalve + '月', code: 0})
} else {
arr.push({label: value + '-' + followValue + '月', code: 0})
}
}
this.monthSelect = arr
}
},
async isMonthCreatedByYear() {
console.log(this.formData.year)
const resp = await $.post(loc() + '/isMonthCreatedByYear', {
year: this.formData.year,
monthSelect: JSON.stringify(this.monthSelect)
})
if (resp.code === 0) {
this.monthSelect = resp.data
}
}
},
async created() {
this.pageData()
await this.getPaymentConfig();
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,489 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<div class="search">
<div class="search-item">
<div class="search-item-label">年度:</div>
<div class="search-item-option">
<el-date-picker
:clearable="false"
@change="doSearch();getProjectList()"
placeholder="选择年度"
type="year" style="width: 100%"
v-model="pageForm.year"
value-format="yyyy">
</el-date-picker>
</div>
</div>
<div class="search-item">
<div class="search-item-label">缴费项目:</div>
<div class="search-item-option">
<el-select placeholder="请选择项目" v-model="pageForm.paymentProjectId"
style="width: 100%;"
clearable="true"
@change="doSearch" @clear="doSearch"
filterable="true">
<el-option v-for="item in paymentProjectList" :label="item.projectName"
:value="item.id"></el-option>
</el-select>
</div>
</div>
<div class="search-item">
<div class="search-item-label">职工信息:</div>
<div class="search-item-option">
<el-input placeholder="请输入内容" clearable v-model="pageForm.searchKeyword"
style="width: 100%"
@keyup.enter.native="doSearch">
<el-select v-model="pageForm.searchName" slot="prepend"
placeholder="查询类型"
style="width: 80px;">
<el-option label="姓名" value="u.username"></el-option>
<el-option label="工号" value="u.loginname"></el-option>
</el-select>
</el-input>
</div>
</div>
<div class="search-item">
<div class="search-item-label">所属工会:</div>
<div class="search-item-option">
<el-select placeholder="所属工会" v-model="pageForm.unionId"
style="width: 100%;"
clearable="true"
@change="flushUnits" @clear="flushUnits"
filterable="true">
<el-option v-for="item in unions" :label="item.unionname"
:value="item.id"></el-option>
</el-select>
</div>
</div>
<div class="search-item">
<div class="search-item-label">所属单位:</div>
<div class="search-item-option">
<el-select placeholder="所属单位" v-model="pageForm.unitId"
style="width: 100%;"
@change="getThreeUnits"
clearable="true"
filterable="true">
<el-option v-for="item in units" :label="item.name"
:value="item.id"></el-option>
</el-select>
</div>
</div>
<template v-if="searchMore">
<template v-if="isThreeUnit">
<div class="search-item">
<div class="search-item-label">工会小组:</div>
<div class="search-item-option">
<el-select v-model="pageForm.unionGroupId" style="width: 100%"
filterable
clearable
@change="getThreeUnits"
placeholder="请选择">
<el-option
v-for="item in unionGroups"
:key="item.id"
:label="item.groupName"
:value="item.id">
</el-option>
</el-select>
</div>
</div>
<div class="search-item">
<div class="search-item-label">组成科室:</div>
<div class="search-item-option">
<el-select v-model="pageForm.threeUnitId" style="width: 100%"
filterable
clearable
placeholder="请选择">
<el-option
v-for="item in threeUnits"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
</div>
</div>
</template>
<div class="search-item">
<div class="search-item-label">人员类型:</div>
<div class="search-item-option">
<dict-select v-model="pageForm.personType" style="width: 100%"
clearable
placeholder="人员类型"
code="UserType"></dict-select>
</div>
</div>
<div class="search-item">
<div class="search-item-label">在职状态:</div>
<div class="search-item-option">
<dict-select v-model="pageForm.userState" style="width: 100%"
clearable
placeholder="在职状态"
code="UserState"></dict-select>
</div>
</div>
</template>
<div class="search-query">
<el-button type="primary" icon="el-icon-search" @click="doSearch">搜索
</el-button>
<more v-model="searchMore"></more>
</div>
</div>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="缴费列表" :app="this">
<template #func>
<el-radio-group @change="doSearch" class="mr10" size="small" v-model="pageForm.isPay">
<el-radio-button :label="null">全部</el-radio-button>
<el-radio-button :label="true">已缴</el-radio-button>
<el-radio-button :label="false">未缴</el-radio-button>
</el-radio-group>
<el-button @click="sendPaymentMsg" size="small" type="primary">
一键催缴
</el-button>
<el-button @click="openModify(false)" size="small" type="primary">
批量设为已缴
</el-button>
<el-button @click="doPaidToUnPaid(false)" size="small" type="primary">
批量设为未缴
</el-button>
<el-button icon="el-icon-s-promotion" type="primary" size="small"
:loading="submitLoading"
@click="openImport">导入
</el-button>
<el-button icon="el-icon-document-add" type="primary" size="small"
:loading="submitLoading"
@click="doExport(false)">导出
</el-button>
<el-button icon="el-icon-document-add" type="primary" size="small"
:loading="submitLoading"
@click="doExport(true)">按分工会导出
</el-button>
</template>
</table-tool>
<el-table :data="tableData" :size="tableSize"
@sort-change="pageOrder"
class="vi-table"
@selection-change="tableHandleSelectionChange"
ref="table" row-key="id" style="width: 100%"
v-loading="tableLoading">
<el-table-column :reserve-selection="true" type="selection"></el-table-column>
<el-table-column :index="indexMethod" align="center" header-align="center"
label="序号" type="index"
width="80px"></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
align="center"
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns"
>
<template scope="{row}" v-if="column.prop==='isPayment'">
<span style="color: #00aa3a" v-if="row.isPayment">已缴</span>
<span style="color: red" v-else>未缴</span>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="操作"
prop="userOnline"
width="250px">
<template scope="{row}">
<el-button v-if="row.isPayment" @click="doPaidToUnPaid(row.id,true)" size="mini" type="primary">
设为未缴
</el-button>
<el-button v-if="!row.isPayment" @click="sendPaymentMsg(row.id)" size="mini" type="primary">
催缴
</el-button>
<el-button v-if="!row.isPayment" @click="openModify(row.id,true)" size="mini" type="primary">
设为已缴
</el-button>
<el-button @click="doDelete(row.id)" size="mini" type="danger">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #edit>
<file-import ref="viewImport" temp_url="/platform/member/payment/summary/downloadImportTemp"
post_url="/platform/member/payment/summary/doImport" :project_id="pageForm.paymentProjectId"
@flush="successImport"
></file-import>
</template>
</guava>
<el-diaLog :close-on-click-modal="false" :visible.sync="modifyVisible" title="已缴设置" width="35%">
<el-form ref="form" :model="formData" :rules="formRules" label-width="80px">
<el-form-item label="缴费金额" prop="paymentMoney">
<el-input placeholder="请输入要缴费的金额" type="number"
v-model="formData.paymentMoney"></el-input>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input placeholder="请输入备注" type="text"
v-model="formData.remark"></el-input>
</el-form-item>
</el-form>
<div style="text-align: right">
<span>
<el-button @click="modifyVisible = false">取 消</el-button>
<el-button @click="doSubmit" type="primary">确 定</el-button>
</span>
</div>
</el-diaLog>
</div>
<script>
const vue = new Vue({
el: '#app',
mixins: [initTableMixins],
data() {
return {
paymentProjectList:[],
units:[],
unions:[],
tableColumns: [
{prop: 'loginname', label: '工号', sortable: true},
{prop: 'username', label: '姓名'},
{prop: 'sex', label: '性别'},
{prop: 'mobile', label: '联系电话'},
{prop: 'personType', label: '人员类型', sortable: true},
{prop: 'userState', label: '在职状态', sortable: true},
{prop: 'unionname', label: '所属工会', sortable: true},
{prop: 'unitname', label: '所属单位', sortable: true},
{prop: 'isPayment', label: '是否缴费', sortable: true},
{prop: 'paymentMoney', label: '缴费金额', sortable: true},
],
pageForm:{
year: moment().format('YYYY'),
searchName: 'u.username',
isPay:false,
searchKeyword: '',
unionId: '',
unitId: '',
threeUnitId: '',
unionGroupId: '',
personType: '',
userState: '',
paymentProjectId:'',
},
checkUsers: [],
modifyVisible:false,
formData:{
ids:[]
},
formRules:{
paymentMoney: [{required: true, message: '必填', trigger: ['blur', 'change']}]
},
}
},
components: {
'guava': httpVueLoader('/components/plugins/Guava.vue'),
'file-import': httpVueLoader('/components/plugins/FileImport.vue'),
'dict-select': httpVueLoader('/components/plugins/DictSelect.vue?v=1.0.0'),
},
methods: {
async sendPaymentMsg(id){
const resp = await $.get(loc() + '/sendPaymentMsg',{id:id})
if (resp.code === 0){
this.notifySuccess(resp.msg)
this.pageData()
} else {
this.notifyWarning(resp.msg)
}
},
/**
* 单个将未缴费设为已缴费
* @param id
* @param flag
*/
openModify(id,flag){
this.formData = {
paymentMoney:'',
remark:''
}
if(flag){
this.checkUsers = []
this.checkUsers.push(id)
this.formData.ids = JSON.stringify(this.checkUsers)
}else {
const ids = this.checkUsers.map(obj => obj.id);
this.formData.ids = JSON.stringify(ids)
}
if (!this.checkUsers.length){
this.notifyWarning("请在左侧勾选需要进行操作的数据!")
return
}
this.modifyVisible = true
this.formData.isPay = true
},
async doPaidToUnPaid(id,flag){
this.formData = {
paymentMoney:'',
remark:''
}
if (flag){
this.checkUsers = []
this.checkUsers.push(id)
this.formData.ids = JSON.stringify(this.checkUsers)
} else {
const ids = this.checkUsers.map(obj => obj.id);
this.formData.ids = JSON.stringify(ids)
}
if (!this.checkUsers.length){
this.notifyWarning("请在左侧勾选需要进行操作的数据!")
return
}
const confirm = await this.$confirm('您确定要设为【未缴】吗,此操作不可撤销!', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
if (confirm === 'confirm') {
const resp = await $.post(loc() + '/modify',this.formData)
if (resp.code === 0){
this.$refs.table.clearSelection();
this.checkUsers = []
this.notifySuccess(resp.msg)
this.modifyVisible = false
this.pageData()
} else {
this.notifyWarning(resp.msg)
}
}
},
async doSubmit(){
if (!this.checkUsers.length){
this.notifyWarning("请在左侧勾选需要进行操作的数据!")
return
}
const formValid = await this.$refs["form"].validate()
if (formValid) {
const confirm = await this.$confirm('您确定要更改缴费信息吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
if (confirm === 'confirm') {
const resp = await $.post(loc() + '/modify',this.formData)
if (resp.code === 0){
this.$refs.table.clearSelection();
this.checkUsers = []
this.notifySuccess(resp.msg)
this.modifyVisible = false
this.pageData()
} else {
this.notifyWarning(resp.msg)
}
}
}
},
async doDelete(id){
const confirm = await this.$confirm('您确定要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
if (confirm === 'confirm') {
const resp = await $.get(loc() + '/doRemoveById', {id: id})
if (resp.code === 0) {
this.notifySuccess(resp.msg)
this.pageData();
} else {
this.notifyWarning(resp.msg)
}
}
},
openImport(){
this.$refs.guava.edit()
this.$refs.viewImport.resetImportData()
},
successImport(){
this.$refs.guava.index()
this.pageData()
},
doExport(isZip){
const {year,paymentProjectId,searchName,searchKeyword,unionId,unitId,threeUnitId, unionGroupId, personType, userState,isPay} = this.pageForm
window.open(loc() + '/doExport?' + searchName + '=' + searchKeyword + '&unionId=' + unionId + '&unitId=' + unitId + '&isPay=' + isPay +
'&year=' + year + '&threeUnitId=' + threeUnitId + '&isZip=' + isZip + '&paymentProjectId=' + paymentProjectId +
'&unionGroupId=' + unionGroupId + '&personType=' + personType + '&userState=' + userState)
},
async flushUnits() {
this.$set(this.pageForm, "unitId", null)
this.$set(this.pageForm, "unionGroupId", null)
this.$set(this.pageForm, "threeUnitId", null)
this.units = []
this.unionGroups = []
this.threeUnits = []
if (this.pageForm.unionId) {
this.units = await getUnits(this.pageForm.unionId)
this.unionGroups = await unionGroupsByUnionId(this.pageForm.unionId)
}
},
tableHandleSelectionChange(val) {
this.checkUsers = val;
},
async getProjectList(){
const resp = await $.get('/platform/member/payment/manage/getAllProject',{year:this.pageForm.year})
if (resp.code === 0){
this.paymentProjectList = resp.data
this.$set(this.pageForm, 'paymentProjectId',this.paymentProjectList ? this.paymentProjectList[0].id : null)
}
},
async doSearch(){
this.pageData()
},
},
async created() {
this.isThreeUnit = await getConfigKey('isThreeUnit') === 'true'
if (this.isThreeUnit) {
this.tableColumns.forEach(v => {
if (["threeUnitName", "unionGroupName"].includes(v.prop)) {
v.checked = 1
}
})
}
if ("${@shiro.hasRole('sysadmin')||@shiro.hasRole('A06')||@shiro.hasRole('H03')}" === 'true') {
this.unions = await getUnions(null, false)
} else {
this.unions = await getUnions(null, true)
this.$set(this.pageForm, 'unionId', this.unions ? this.unions[0].id : null)
this.flushUnits()
}
await this.getProjectList()
this.pageData();
}
})
</script>
<!--#
}
#-->