This commit is contained in:
=
2026-08-25 17:02:40 +08:00
parent c4a19e15c9
commit 303725da50
13 changed files with 372 additions and 54 deletions
@@ -131,7 +131,9 @@ public class SysSignatureController {
@Aop(TransAop.READ_COMMITTED)
public Result update(@Param("file") TempFile tempFile) {
String url = sysFileService.uploadReturnUrl(SysFileEngineTypeEnum.MINIO.getValue(), tempFile);
Sys_user_signature sysUserSignature = dao.fetch(Sys_user_signature.class);
// 按当前用户查询签字记录,避免更新时误取到其他用户的签字数据。
Sys_user_signature sysUserSignature = dao.fetch(Sys_user_signature.class,
Cnd.where(Sys_user_signature::getUserId, "=", SecurityUtil.getUserId()));
if (ObjectUtil.isNull(sysUserSignature)) {
sysUserSignature = new Sys_user_signature();
}
@@ -82,9 +82,9 @@ public class TeacherCongressDelegationController {
SELECT
tcd.*,
tcs.fullName as sessionName,
GROUP_CONCAT(u.username,u.loginname) as delegationHead,
GROUP_CONCAT(u2.username,u2.loginname) as viceDelegationHead,
GROUP_CONCAT(u3.username,u3.loginname) as delegationContact
GROUP_CONCAT(DISTINCT CONCAT_WS('', u.username, u.loginname)) as delegationHead,
GROUP_CONCAT(DISTINCT CONCAT_WS('', u2.username, u2.loginname)) as viceDelegationHead,
GROUP_CONCAT(DISTINCT CONCAT_WS('', u3.username, u3.loginname)) as delegationContact
FROM
teacher_congress_delegation tcd
LEFT JOIN teacher_congress_session tcs ON tcs.id = tcd.sessionId
@@ -308,6 +308,37 @@ public class TeacherCongressDelegationController {
throw new BaseException("参数错误");
}
// 副团长允许多人,需要返回完整候选人列表;团长和联络人仍保持单人返回结构。
if (type.equals(RoleConstant.TEACHER_CONGRESS_VICE_DELEGATION_HEAD.name())) {
List<Sys_user_role> userRoles = dao.query(Sys_user_role.class,
Cnd.where(Sys_user_role::getTcSessionId, "=", sessionId)
.and(Sys_user_role::getTcDelegationId, "=", delegationId)
.and(Sys_user_role::getRoleId, "=", role.getId()));
List<String> userIds = userRoles.stream().map(Sys_user_role::getUserId).filter(StrUtil::isNotBlank).toList();
if (userIds.isEmpty()) {
return Result.success().addData(List.of());
}
Sql sql = Sqls.create("""
SELECT
u.id as userId,
u.loginname as loginName,
u.username as userName,
u.mobile,
n.name as unitName
FROM
sys_user u
LEFT JOIN sys_unit n on n.id = u.unitId
WHERE
u.id IN (@userIds)
""");
sql.setParam("userIds", userIds);
sql.setCallback(Sqls.callback.maps());
dao.execute(sql);
@SuppressWarnings("unchecked")
List<NutMap> users = (List<NutMap>) sql.getResult();
return Result.success().addData(users);
}
Record record = dao.fetch("sys_user_role", Cnd.where("tcSessionId", "=", sessionId).and("tcDelegationId", "=", delegationId).and("roleId", "=", role.getId()));
String userId = Optional.ofNullable(record).map(r -> r.getString("userId")).orElse(null);
@@ -337,14 +368,16 @@ public class TeacherCongressDelegationController {
* @param delegationId 代表团ID
* @param sessionId 届次ID
* @param userId 团长id
* @param viceUserId 副团长id
* @param viceUserIds 逗号分隔的副团长id列表
* @param viceUserIdArray 表单数组编码的副团长id列表
* @param viceUserId 兼容旧版页面提交的单个副团长id
* @param contactUserId 联络人
* @return
*/
@At
@SaCheckPermission("tc.delegation")
@Aop(TransAop.READ_COMMITTED)
public Result insertHead(@Valid String delegationId, @Valid String sessionId, @Valid String userId, @Valid String viceUserId, String contactUserId) {
public Result insertHead(@Valid String delegationId, @Valid String sessionId, @Valid String userId, @Param("viceUserIds") String viceUserIds, @Param("viceUserIds[]") String[] viceUserIdArray, @Param("viceUserId") String viceUserId, String contactUserId) {
// 团长
Sys_role role = sysRoleService.getByCode(RoleConstant.TEACHER_CONGRESS_DELEGATION_HEAD);
dao.clear(Sys_user_role.class, Cnd.where(Sys_user_role::getTcDelegationId, "=", delegationId).and(Sys_user_role::getTcSessionId, "=", sessionId).and(Sys_user_role::getRoleId, "=", role.getId()));
@@ -353,7 +386,22 @@ public class TeacherCongressDelegationController {
// 副团长
Sys_role role2 = sysRoleService.getByCode(RoleConstant.TEACHER_CONGRESS_VICE_DELEGATION_HEAD);
dao.clear(Sys_user_role.class, Cnd.where(Sys_user_role::getTcDelegationId, "=", delegationId).and(Sys_user_role::getTcSessionId, "=", sessionId).and(Sys_user_role::getRoleId, "=", role2.getId()));
dao.insert("sys_user_role", Chain.make("userId", viceUserId).add("roleId", role2.getId()).add("tcDelegationId", delegationId).add("tcSessionId", sessionId));
List<String> selectedViceUserIds = CollUtil.newArrayList();
if (StrUtil.isNotBlank(viceUserIds)) {
selectedViceUserIds.addAll(Arrays.stream(viceUserIds.split(",")).filter(StrUtil::isNotBlank).distinct().toList());
}
if (viceUserIdArray != null) {
selectedViceUserIds.addAll(Arrays.stream(viceUserIdArray).filter(StrUtil::isNotBlank).distinct().toList());
}
// 旧版页面只提交 viceUserId,兼容该参数可避免升级后保存时清空已有选择。
if (selectedViceUserIds.isEmpty() && StrUtil.isNotBlank(viceUserId)) {
selectedViceUserIds.add(viceUserId);
}
for (String selectedViceUserId : selectedViceUserIds.stream().distinct().toList()) {
if (StrUtil.isNotBlank(selectedViceUserId)) {
dao.insert("sys_user_role", Chain.make("userId", selectedViceUserId).add("roleId", role2.getId()).add("tcDelegationId", delegationId).add("tcSessionId", sessionId));
}
}
// 联络人
Sys_role role3 = sysRoleService.getByCode(RoleConstant.TEACHER_CONGRESS_DELEGATION_CONTACT);
@@ -95,6 +95,12 @@ public class CondolenceApplyController {
Dict args = Dict.create();
args.set(FlowConst.SUBMIT_TYPE, ProcessSubmitTypeEnum.APPLY.getCode());
args.set(FlowConst.FORM_DATA, condolence);
// 根据提交人的校工会角色设置流程分支变量,供 ZGWW 流程表达式判断是否直达校工会审核。
boolean directToSchoolUnionAudit = AuthUtil.hasRoleOr(
RoleConstant.SCHOOL_UNION_CHAIRMAN.name(),
RoleConstant.SCHOOL_UNION_VICE_CHAIRMAN.name(),
RoleConstant.SCHOOL_UNION_ADMIN.name());
args.set("tf_source", directToSchoolUnionAudit ? "SCHOOL_UNION" : "PERSONAL");
ProcessInstance instance = flowEngine.startProcessInstanceByKey("ZGWW", condolence.getId(), SecurityUtil.getUserId(), args);
// 自动完成第一个申请任务
@@ -116,6 +122,12 @@ public class CondolenceApplyController {
Dict dict = Dict.create();
dict.set(FlowConst.PROCESS_TASK_ID_KEY, taskId);
dict.set(FlowConst.SUBMIT_TYPE, ProcessSubmitTypeEnum.RE_APPLY.getCode());
// 重新提交时同步设置分支变量,避免角色符合条件时仍按普通申请路径流转。
boolean directToSchoolUnionAudit = AuthUtil.hasRoleOr(
RoleConstant.SCHOOL_UNION_CHAIRMAN.name(),
RoleConstant.SCHOOL_UNION_VICE_CHAIRMAN.name(),
RoleConstant.SCHOOL_UNION_ADMIN.name());
dict.set("tf_source", directToSchoolUnionAudit ? "SCHOOL_UNION" : "PERSONAL");
flowCommonService.executeTask(dict);
return Result.success();
}
@@ -25,6 +25,9 @@ public class MemberStatisticsPageForm extends PageForm {
private String searchType;
@ApiModelProperty("是否缴费会员")
private Boolean memberFeePaid;
private String startDate;
private String endDate;
@@ -156,6 +156,7 @@ public class MemberStatisticsServiceImpl extends BaseServiceImpl<Sys_user> imple
FROM
$table
$hisUser
LEFT JOIN sys_user su ON su.id = u.id
LEFT JOIN sys_user_role sur ON sur.userid = u.id
$condition
""");
@@ -173,6 +174,10 @@ public class MemberStatisticsServiceImpl extends BaseServiceImpl<Sys_user> imple
if (StrUtil.isNotBlank(pageForm.getIsUnion())) {
cnd.and("u.unionId", "true".equals(pageForm.getIsUnion()) ? "is not" : "is", null);
}
// 缴费会员由会员分组管理维护,空值按未缴费处理。
if (pageForm.getMemberFeePaid() != null) {
cnd.and("IFNULL(su.memberFeePaid, 0)", "=", pageForm.getMemberFeePaid() ? 1 : 0);
}
if (StrUtil.isNotBlank(pageForm.getSearchType()) && !"all".equals(pageForm.getSearchType())) {
if ("member".equals(pageForm.getSearchType())) {
@@ -209,17 +214,18 @@ public class MemberStatisticsServiceImpl extends BaseServiceImpl<Sys_user> imple
@Override
public List<NutMap> getUnionAnalysisData(String queryId, Integer currentYear) {
// 会员统计口径统一为会员分组管理中标记为已缴费的人员。
Sql sql = Sqls.create("""
SELECT
gh.id,
gh.unionCode,
gh.`name` as unionName,
( SELECT count( 1 ) FROM member_history his LEFT JOIN vw_user u on u.id = his.userId WHERE his.`year` = @lastYear AND u.unionId = gh.id ) AS lastYearMemberNum,
( SELECT count( 1 ) FROM member_apply_record WHERE changeUnionId is not null AND unionId = gh.id AND unionId != changeUnionId AND YEAR ( applyDateTime ) = @currentYear ) AS memberUnitChangeNumIn,
( SELECT count( 1 ) FROM member_apply_record WHERE changeUnionId is not null AND changeUnionId = gh.id AND unionId != changeUnionId AND YEAR ( applyDateTime ) = @currentYear ) AS memberUnitChangeNumOut,
( SELECT count( 1 ) FROM sys_user_history his LEFT JOIN `vw_user` u ON u.loginname = his.loginname WHERE JSON_CONTAINS(his.changeTypes, '["NEW", "RESTORE"]', '$') AND u.unionId = gh.id AND YEAR ( his.changeTime ) = @currentYear ) AS newResetMemberNum,
( SELECT count( 1 ) FROM sys_user_history his LEFT JOIN `vw_user` u ON u.loginname = his.loginname WHERE JSON_CONTAINS(his.changeTypes, '["WITHDRAWAL"]', '$') AND u.unionId = gh.id AND YEAR ( his.changeTime ) = @currentYear ) AS reduceOtherNum,
( SELECT count( 1 ) FROM $table where member = 1 and unionId = gh.id) as currentYearMemberNum
( SELECT count( 1 ) FROM member_history his LEFT JOIN vw_user u on u.id = his.userId INNER JOIN sys_user su ON su.id = his.userId AND su.memberFeePaid = 1 WHERE his.`year` = @lastYear AND u.unionId = gh.id ) AS lastYearMemberNum,
( SELECT count( 1 ) FROM member_apply_record mar INNER JOIN sys_user su ON su.id = mar.userId AND su.memberFeePaid = 1 WHERE mar.changeUnionId is not null AND mar.unionId = gh.id AND mar.unionId != mar.changeUnionId AND YEAR ( mar.applyDateTime ) = @currentYear ) AS memberUnitChangeNumIn,
( SELECT count( 1 ) FROM member_apply_record mar INNER JOIN sys_user su ON su.id = mar.userId AND su.memberFeePaid = 1 WHERE mar.changeUnionId is not null AND mar.changeUnionId = gh.id AND mar.unionId != mar.changeUnionId AND YEAR ( mar.applyDateTime ) = @currentYear ) AS memberUnitChangeNumOut,
( SELECT count( 1 ) FROM sys_user_history his LEFT JOIN `vw_user` u ON u.loginname = his.loginname INNER JOIN sys_user su ON su.id = u.id AND su.memberFeePaid = 1 WHERE JSON_CONTAINS(his.changeTypes, '["NEW", "RESTORE"]', '$') AND u.unionId = gh.id AND YEAR ( his.changeTime ) = @currentYear ) AS newResetMemberNum,
( SELECT count( 1 ) FROM sys_user_history his LEFT JOIN `vw_user` u ON u.loginname = his.loginname INNER JOIN sys_user su ON su.id = u.id AND su.memberFeePaid = 1 WHERE JSON_CONTAINS(his.changeTypes, '["WITHDRAWAL"]', '$') AND u.unionId = gh.id AND YEAR ( his.changeTime ) = @currentYear ) AS reduceOtherNum,
( SELECT count( 1 ) FROM $table u INNER JOIN sys_user su ON su.id = $memberUserId AND su.memberFeePaid = 1 WHERE u.member = 1 AND u.unionId = gh.id) as currentYearMemberNum
FROM
sys_union gh
$condition
@@ -227,6 +233,7 @@ public class MemberStatisticsServiceImpl extends BaseServiceImpl<Sys_user> imple
sql.setParam("lastYear", currentYear - 1);
sql.setParam("currentYear", currentYear);
sql.setVar("table", ((Integer) DateUtil.thisYear()).equals(currentYear) ? "`vw_user`" : "member_history");
sql.setVar("memberUserId", new Static(((Integer) DateUtil.thisYear()).equals(currentYear) ? "u.id" : "u.userId"));
Cnd cnd = Cnd.NEW();
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
cnd.and("gh.id", "=", SecurityUtil.getUnionId());
@@ -247,17 +254,18 @@ public class MemberStatisticsServiceImpl extends BaseServiceImpl<Sys_user> imple
@Override
public List<NutMap> getUnitAnalysisData(String queryId, Integer currentYear) {
// 会员统计口径统一为会员分组管理中标记为已缴费的人员。
Sql sql = Sqls.create("""
SELECT
dw.id,
dw.unitcode as unitCode,
dw.`name` as unitName,
( SELECT count( 1 ) FROM member_history WHERE `year` = @lastYear AND unitId = dw.id ) AS lastYearMemberNum,
( SELECT count( 1 ) FROM member_apply_record WHERE changeUnitId is not null AND unitId = dw.id AND unitId != changeUnitId AND YEAR ( applyDateTime ) = @currentYear ) AS memberUnitChangeNumIn,
( SELECT count( 1 ) FROM member_apply_record WHERE changeUnitId is not null AND changeUnitId = dw.id AND unitId != changeUnitId AND YEAR ( applyDateTime ) = @currentYear ) AS memberUnitChangeNumOut,
( SELECT count( 1 ) FROM sys_user_history his LEFT JOIN vw_user u ON u.loginname = his.loginname WHERE JSON_CONTAINS(his.changeTypes, '["NEW", "RESTORE"]', '$') AND u.unitId = dw.id AND YEAR ( his.changeTime ) = @currentYear ) AS newResetMemberNum,
( SELECT count( 1 ) FROM sys_user_history his LEFT JOIN vw_user u ON u.loginname = his.loginname WHERE JSON_CONTAINS(his.changeTypes, '["WITHDRAWAL"]', '$') AND u.unitId = dw.id AND YEAR ( his.changeTime ) = @currentYear ) AS reduceOtherNum,
( SELECT count( 1 ) from vw_user where member = 1 and unitId = dw.id) as currentYearMemberNum
( SELECT count( 1 ) FROM member_history his INNER JOIN sys_user su ON su.id = his.userId AND su.memberFeePaid = 1 WHERE his.`year` = @lastYear AND his.unitId = dw.id ) AS lastYearMemberNum,
( SELECT count( 1 ) FROM member_apply_record mar INNER JOIN sys_user su ON su.id = mar.userId AND su.memberFeePaid = 1 WHERE mar.changeUnitId is not null AND mar.unitId = dw.id AND mar.unitId != mar.changeUnitId AND YEAR ( mar.applyDateTime ) = @currentYear ) AS memberUnitChangeNumIn,
( SELECT count( 1 ) FROM member_apply_record mar INNER JOIN sys_user su ON su.id = mar.userId AND su.memberFeePaid = 1 WHERE mar.changeUnitId is not null AND mar.changeUnitId = dw.id AND mar.unitId != mar.changeUnitId AND YEAR ( mar.applyDateTime ) = @currentYear ) AS memberUnitChangeNumOut,
( SELECT count( 1 ) FROM sys_user_history his LEFT JOIN vw_user u ON u.loginname = his.loginname INNER JOIN sys_user su ON su.id = u.id AND su.memberFeePaid = 1 WHERE JSON_CONTAINS(his.changeTypes, '["NEW", "RESTORE"]', '$') AND u.unitId = dw.id AND YEAR ( his.changeTime ) = @currentYear ) AS newResetMemberNum,
( SELECT count( 1 ) FROM sys_user_history his LEFT JOIN vw_user u ON u.loginname = his.loginname INNER JOIN sys_user su ON su.id = u.id AND su.memberFeePaid = 1 WHERE JSON_CONTAINS(his.changeTypes, '["WITHDRAWAL"]', '$') AND u.unitId = dw.id AND YEAR ( his.changeTime ) = @currentYear ) AS reduceOtherNum,
( SELECT count( 1 ) FROM vw_user u INNER JOIN sys_user su ON su.id = u.id AND su.memberFeePaid = 1 WHERE u.member = 1 AND u.unitId = dw.id) as currentYearMemberNum
FROM
sys_unit dw
$condition
@@ -310,6 +318,7 @@ public class MemberStatisticsServiceImpl extends BaseServiceImpl<Sys_user> imple
@Override
public List<NutMap> getUnionStatisticsData(String unionId, Integer currentYear) {
// 会员统计口径统一为会员分组管理中标记为已缴费的人员。
Sql sql = Sqls.create("""
SELECT
un.id,
@@ -320,11 +329,12 @@ public class MemberStatisticsServiceImpl extends BaseServiceImpl<Sys_user> imple
SUM(CASE WHEN TIMESTAMPDIFF(YEAR, u.birthday, CURDATE()) >= 51 AND TIMESTAMPDIFF(YEAR, u.birthday, CURDATE()) <= 55 $personCnd $yearCnd THEN 1 ELSE 0 END) AS smallFiftyFive,
SUM(CASE WHEN TIMESTAMPDIFF(YEAR, u.birthday, CURDATE()) > 55 $personCnd $yearCnd THEN 1 ELSE 0 END) AS smallFiftyFive2,
COUNT(*) AS totalNumber,
SUM(CASE WHEN sex = '男' $personCnd $yearCnd THEN 1 ELSE 0 END) AS maleMember,
SUM(CASE WHEN sex = '女' $personCnd $yearCnd THEN 1 ELSE 0 END) AS femaleMember
SUM(CASE WHEN u.sex = '男' $personCnd $yearCnd THEN 1 ELSE 0 END) AS maleMember,
SUM(CASE WHEN u.sex = '女' $personCnd $yearCnd THEN 1 ELSE 0 END) AS femaleMember
FROM
sys_union un
JOIN $table u ON u.unionId = un.id AND u.member = 1
JOIN sys_user su ON su.id = $memberUserId AND su.memberFeePaid = 1
$condition
""");
Cnd cnd = Cnd.NEW();
@@ -335,9 +345,11 @@ public class MemberStatisticsServiceImpl extends BaseServiceImpl<Sys_user> imple
}
if (DateUtil.thisYear() == currentYear) {
sql.setVar("table", new Static("vw_user"));
sql.setVar("memberUserId", new Static("u.id"));
// sql.setVar("abbr", new Static("u"));
} else {
sql.setVar("table", new Static("member_history"));
sql.setVar("memberUserId", new Static("u.userId"));
sql.setVar("yearCnd", new Static(" AND u.`year` = %d".formatted(currentYear)));
// sql.setVar("abbr", new Static("his"));
}
@@ -349,6 +361,7 @@ public class MemberStatisticsServiceImpl extends BaseServiceImpl<Sys_user> imple
@Override
public List<NutMap> getUnitStatisticsData(String unitId, Integer currentYear) {
// 会员统计口径统一为会员分组管理中标记为已缴费的人员。
Sql sql = Sqls.create("""
SELECT
un.id,
@@ -359,11 +372,12 @@ public class MemberStatisticsServiceImpl extends BaseServiceImpl<Sys_user> imple
SUM(CASE WHEN TIMESTAMPDIFF(YEAR, u.birthday, CURDATE()) >= 51 AND TIMESTAMPDIFF(YEAR, u.birthday, CURDATE()) <= 55 $personCnd $yearCnd THEN 1 ELSE 0 END) AS smallFiftyFive,
SUM(CASE WHEN TIMESTAMPDIFF(YEAR, u.birthday, CURDATE()) > 55 $personCnd $yearCnd THEN 1 ELSE 0 END) AS smallFiftyFive2,
COUNT(*) AS totalNumber,
SUM(CASE WHEN sex = '男' $personCnd $yearCnd THEN 1 ELSE 0 END) AS maleMember,
SUM(CASE WHEN sex = '女' $personCnd $yearCnd THEN 1 ELSE 0 END) AS femaleMember
SUM(CASE WHEN u.sex = '男' $personCnd $yearCnd THEN 1 ELSE 0 END) AS maleMember,
SUM(CASE WHEN u.sex = '女' $personCnd $yearCnd THEN 1 ELSE 0 END) AS femaleMember
FROM
sys_unit un
JOIN $table u ON u.unitId = un.id AND u.member = 1
JOIN sys_user su ON su.id = $memberUserId AND su.memberFeePaid = 1
$condition
""");
Cnd cnd = Cnd.NEW();
@@ -374,8 +388,10 @@ public class MemberStatisticsServiceImpl extends BaseServiceImpl<Sys_user> imple
}
if (DateUtil.thisYear() == currentYear) {
sql.setVar("table", new Static("vw_user"));
sql.setVar("memberUserId", new Static("u.id"));
} else {
sql.setVar("table", new Static("member_history"));
sql.setVar("memberUserId", new Static("u.userId"));
sql.setVar("yearCnd", new Static(" AND u.`year` = %d".formatted(currentYear)));
}
cnd.and("un.unitLevel", "=", 2);
@@ -40,6 +40,14 @@ module.exports = {
}
},
methods: {
// 打开手机端签字组件前,先读取当前用户已经保存的签字。
async init() {
const { code, data } = await this.$axios.post("/platform/signature/get")
if (code === 0) {
this.$set(this, "signatureContent", data && data.signature)
this.$emit("input", this.signatureContent)
}
},
openSignature() {
this.showSignaturePanel = true
},
@@ -86,7 +94,9 @@ module.exports = {
return new File([blob], filename, { type: contentType })
}
},
created() {}
created() {
this.init()
}
}
</script>
@@ -1,5 +1,5 @@
<template>
<el-select v-model="selectValue" :clearable="clearable" filterable remote :remote-method="selectUser"
<el-select v-model="selectValue" :multiple="multiple" :clearable="clearable" filterable remote :remote-method="selectUser"
placeholder="请输入姓名或工号查询" @change="onChange" v-bind="$attrs" style="width: 100%">
<el-option
v-for="item in options"
@@ -39,6 +39,11 @@ module.exports = {
default: true
},
multiple: {
type: Boolean,
default: false
},
api_input_key_name: {
type: String,
required: false,
@@ -78,8 +83,9 @@ module.exports = {
watch: {
value: {
handler: function (val) {
if (this.$attrs.multiple) {
this.selectValue = [...val]
if (this.multiple) {
// 多选回显统一使用数组,兼容接口返回单个用户或空值的情况。
this.selectValue = Array.isArray(val) ? val : (val ? [val] : [])
} else {
this.selectValue = val ? val.toString() : ""
}
@@ -478,7 +478,7 @@
align-items: center;
gap: 24px;
height: 100%;
max-width: 310px;
max-width: 400px;
flex-shrink: 0;
}
@@ -529,7 +529,7 @@
display: flex;
align-items: center;
gap: 12px;
padding: 0 12px;
/*padding: 0 12px;*/
height: 100%;
border-radius: 0;
cursor: pointer;
@@ -559,6 +559,18 @@
white-space: nowrap;
}
.v4-sign-name {
font-weight: 500;
color: #ffffff;
white-space: nowrap;
margin-right: 20px;
padding: 0;
border: 0;
background: transparent;
font: inherit;
cursor: pointer;
}
.v4-logout {
color: #ffffff;
cursor: pointer;
@@ -680,6 +692,22 @@
<span class="v4-user-name">${@auth.getPrincipalProperty('username')} (${@auth.getPrincipalProperty('loginname')})</span>
<!-- <i class="fa fa-angle-down"></i> -->
</div>
<div id="aboutNameApp">
<button type="button" class="v4-sign-name" @click="showSignDialog">我的签字</button>
<el-dialog
title="我的签字"
:visible.sync="signDialogVisible"
width="520px"
append-to-body
:close-on-click-modal="false"
>
<pc-signature v-if="signDialogVisible" v-model="signForm.signature"></pc-signature>
<span slot="footer" class="dialog-footer">
<el-button @click="signDialogVisible = false">取消</el-button>
<el-button type="primary" :loading="signDialogLoading" @click="submitSignature">确定</el-button>
</span>
</el-dialog>
</div>
<a class="v4-logout" href="/platform/login/logout">
<i class="fa fa-sign-out"></i>
退出
@@ -707,6 +735,68 @@
</div>
</footer>
<script nonce="${cspNonce!}">
new Vue({
el: "#aboutNameApp",
data() {
return {
signDialogVisible: false,
signDialogLoading: false,
signForm: {
signature: ""
}
}
},
methods: {
showSignDialog() {
this.$set(this.signForm, "signature", "")
this.$set(this, "signDialogVisible", true)
},
// 将签字组件返回的图片地址转换为接口要求的文件参数。
buildSignatureFormData(signatureUrl) {
return axios.get(signatureUrl, {
responseType: "blob"
}).then((response) => {
const formData = new FormData()
formData.append("file", response.data, "signature.png")
return formData
})
},
// 弹窗确认后统一保存当前登录用户的签字信息。
submitSignature() {
if (!this.signForm.signature) {
this.$message.warning("请先完成签字")
return
}
this.$set(this, "signDialogLoading", true)
this.buildSignatureFormData(this.signForm.signature)
.then((formData) => {
return axios.post("/platform/signature/update", formData, {
headers: {
"Content-Type": "multipart/form-data"
}
})
})
.then((response) => {
const res = response.data
if (res.code === 0) {
this.$message.success(res.msg || "签字更新成功")
this.$set(this, "signDialogVisible", false)
return
}
this.$message.error(res.msg || "签字更新失败")
})
.catch(() => {
this.$message.error("签字更新失败,请稍后重试")
})
.finally(() => {
this.$set(this, "signDialogLoading", false)
})
}
}
})
</script>
<script nonce="${cspNonce!}">
// 处理导航项的active状态
@@ -25,9 +25,11 @@ const HEAD_FORM_TEMPLATE = {
placeholder="请输入工号或者姓名"
style="width: 100%"></user-select>
</el-form-item>
<el-form-item prop="viceUserId" label="副团长">
<user-select v-model="formData.viceUserId"
<el-form-item prop="viceUserIds" label="副团长">
<user-select v-model="formData.viceUserIds"
v-if="headDialogFormVisible"
:multiple="true"
@change="viceUserChange"
api="/platform/teacherCongress/delegation/notHeadUser"
:api_params="{sessionId:formData.sessionId,delegationId:formData.delegationId}"
api_input_key_name="keyWord"
@@ -70,7 +72,7 @@ const HEAD_FORM_TEMPLATE = {
name: [{required: true, message: "必填", trigger: ["change", "blur"]}],
code: [{required: true, message: "必填", trigger: ["change", "blur"]}],
userId: [{required: true, message: "必填", trigger: ["change", "blur"]}],
//viceUserId: [{required: true, message: "必填", trigger: ["change", "blur"]}],
//viceUserIds: [{required: true, message: "必填", trigger: ["change", "blur"]}],
//contactUserId: [{required: true, message: "必填", trigger: ["change", "blur"]}]
}
}
@@ -84,8 +86,12 @@ const HEAD_FORM_TEMPLATE = {
this.listSession()
this.formData = {
sessionId,
delegationId
delegationId,
viceUserIds: []
}
this.$set(this, "headOptions", [])
this.$set(this, "viceHeadOptions", [])
this.$set(this, "contactOptions", [])
this.findHeadUser()
},
@@ -107,10 +113,9 @@ const HEAD_FORM_TEMPLATE = {
type: 'TEACHER_CONGRESS_VICE_DELEGATION_HEAD'
}).then((res) => {
if (res.code === 0) {
if (res.data) {
this.viceHeadOptions = [res.data]
this.$set(this.formData, "viceUserId", res.data.userId)
}
const viceUsers = Array.isArray(res.data) ? res.data : (res.data ? [res.data] : [])
this.$set(this, "viceHeadOptions", viceUsers)
this.$set(this.formData, "viceUserIds", viceUsers.map((item) => item.userId))
}
})
this.$axios.post("/platform/teacherCongress/delegation/headUser", {
@@ -129,7 +134,13 @@ const HEAD_FORM_TEMPLATE = {
doSubmitHead() {
this.$refs.headFormRef.validate((valid) => {
if (valid) {
this.$axios.post("/platform/teacherCongress/delegation/insertHead", this.formData).then((res) => {
const viceUserIds = Array.isArray(this.formData.viceUserIds) ? this.formData.viceUserIds : []
const submitData = {
...this.formData,
// 请求采用表单编码,多个副团长用逗号分隔,避免数组参数被编码为 viceUserIds[] 后无法绑定。
viceUserIds: viceUserIds.join(",")
}
this.$axios.post("/platform/teacherCongress/delegation/insertHead", submitData).then((res) => {
if (res.code === 0) {
this.headDialogFormVisible = false
this.$message.success(res.msg)
@@ -139,6 +150,10 @@ const HEAD_FORM_TEMPLATE = {
}
})
},
viceUserChange(viceUserIds) {
const selectedViceUserIds = Array.isArray(viceUserIds) ? viceUserIds : (viceUserIds ? [viceUserIds] : [])
this.$set(this.formData, "viceUserIds", selectedViceUserIds)
},
listSession() {
this.$axios.post("/platform/teacherCongress/common/listSession").then((res) => {
if (res.code === 0) {
@@ -338,10 +338,19 @@ layout("/layouts/platform.html"){
})
})
},
// 前端提示与后端使用相同的角色范围,后端仍会再次校验并决定实际流程分支。
isDirectToSchoolUnionAudit() {
return this.$auth.hasRoleOr(["SCHOOL_UNION_CHAIRMAN", "SCHOOL_UNION_VICE_CHAIRMAN", "SCHOOL_UNION_ADMIN"])
},
getSubmitConfirmMessage() {
return this.isDirectToSchoolUnionAudit()
? "您确定要提交吗?当前提交会直接到校工会审核。"
: "您确定要提交吗?"
},
onSubmit() {
this.$refs.formRef.validate((valid) => {
if (valid) {
this.$confirm("您确定要提交吗?", "提示", {
this.$confirm(this.getSubmitConfirmMessage(), "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
@@ -361,7 +370,7 @@ layout("/layouts/platform.html"){
onFinishTask() {
this.$refs.formRef.validate((valid) => {
if (valid) {
this.$confirm("您确定要提交吗?", "提示", {
this.$confirm(this.getSubmitConfirmMessage(), "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
@@ -120,6 +120,25 @@ layout("/layouts/platform.html"){
height: auto !important;
}
.member-summary-row {
display: grid;
grid-template-columns: 100px minmax(0, 1fr) 120px;
flex-shrink: 0;
height: 48px;
line-height: 48px;
border-top: 1px solid #ebeef5;
color: #606266;
text-align: center;
}
.member-summary-row > div {
border-right: 1px solid #ebeef5;
}
.member-summary-row > div:last-child {
border-right: none;
}
.content-right .card-title {
flex-shrink: 0;
}
@@ -362,6 +381,11 @@ layout("/layouts/platform.html"){
width="120px"
></el-table-column>
</el-table>
<div class="member-summary-row">
<div>合计</div>
<div></div>
<div>{{ unionMemberTotal }}</div>
</div>
</div>
</div>
</guava>
@@ -399,11 +423,60 @@ layout("/layouts/platform.html"){
diff: 0
},
memberPercentage: "--",
unionMember: []
unionMember: [],
unionMemberTotal: 0
}
},
methods: {
/**
* 等待图表容器完成布局后再渲染,避免网格布局尚未计算尺寸导致图表初始化失败。
*/
renderChartWhenReady(chartInstance, containerId, attempt = 0) {
this.$nextTick(() => {
const container = document.getElementById(containerId)
if (!container || container.clientWidth === 0 || container.clientHeight === 0) {
if (attempt < 10) {
setTimeout(() => this.renderChartWhenReady(chartInstance, containerId, attempt + 1), 100)
}
return
}
try {
const renderResult = chartInstance.render()
if (renderResult && typeof renderResult.catch === "function") {
renderResult.catch(() => {
if (attempt < 10) {
setTimeout(() => this.renderChartWhenReady(chartInstance, containerId, attempt + 1), 100)
}
})
}
} catch (error) {
if (attempt < 10) {
setTimeout(() => this.renderChartWhenReady(chartInstance, containerId, attempt + 1), 100)
}
}
})
},
/**
* G2Plot 构造函数本身会操作目标 DOM,必须在容器存在后再创建实例。
*/
createChartWhenReady(containerId, createChart, attempt = 0) {
this.$nextTick(() => {
if (!document.getElementById(containerId)) {
if (attempt < 10) {
setTimeout(() => this.createChartWhenReady(containerId, createChart, attempt + 1), 100)
}
return
}
try {
createChart()
} catch (error) {
if (attempt < 10) {
setTimeout(() => this.createChartWhenReady(containerId, createChart, attempt + 1), 100)
}
}
})
},
/**
* 会员数
* @returns {Promise<void>}
@@ -444,7 +517,8 @@ layout("/layouts/platform.html"){
return
}
chart.growthTrendChart = new G2Plot.TinyArea("growthTrendChart", {
this.createChartWhenReady("growthTrendChart", () => {
chart.growthTrendChart = new G2Plot.TinyArea("growthTrendChart", {
autoFit: true,
data: values,
smooth: true,
@@ -480,8 +554,9 @@ layout("/layouts/platform.html"){
return ""
}
}
})
this.renderChartWhenReady(chart.growthTrendChart, "growthTrendChart")
})
chart.growthTrendChart.render()
} else {
this.$message.warning(resp.msg)
}
@@ -502,7 +577,8 @@ layout("/layouts/platform.html"){
chart.memberPercentageChart.changeData(data)
return
}
chart.memberPercentageChart = new G2Plot.Liquid("memberPercentageChart", {
this.createChartWhenReady("memberPercentageChart", () => {
chart.memberPercentageChart = new G2Plot.Liquid("memberPercentageChart", {
outline: {
border: 4,
distance: 8
@@ -521,8 +597,9 @@ layout("/layouts/platform.html"){
}
}
}
})
this.renderChartWhenReady(chart.memberPercentageChart, "memberPercentageChart")
})
chart.memberPercentageChart.render()
} else {
this.$message.warning(resp.msg)
}
@@ -543,7 +620,8 @@ layout("/layouts/platform.html"){
return
}
chart.memberSexPercentageChart = new G2Plot.Pie("memberSexPercentageChart", {
this.createChartWhenReady("memberSexPercentageChart", () => {
chart.memberSexPercentageChart = new G2Plot.Pie("memberSexPercentageChart", {
data,
angleField: "value",
colorField: "type",
@@ -564,8 +642,9 @@ layout("/layouts/platform.html"){
{ type: 'element-active' },
],
color: ['#217050', '#f0a35c']
})
this.renderChartWhenReady(chart.memberSexPercentageChart, "memberSexPercentageChart")
})
chart.memberSexPercentageChart.render()
} else {
this.$message.warning(resp.msg)
}
@@ -612,6 +691,7 @@ layout("/layouts/platform.html"){
chartData.forEach((item) => this.$set(item, "paidValue", this.getUnionPaidValue(item)))
tableData.forEach((item) => this.$set(item, "paidValue", this.getUnionPaidValue(item)))
this.$set(this, "unionMemberTotal", tableData.reduce((total, item) => total + this.getUnionPaidValue(item), 0))
this.$set(this, "unionMember", tableData)
if (chart.unionMemberChart) {
@@ -619,7 +699,8 @@ layout("/layouts/platform.html"){
return
}
chart.unionMemberChart = new G2Plot.Column("unionMemberChart", {
this.createChartWhenReady("unionMemberChart", () => {
chart.unionMemberChart = new G2Plot.Column("unionMemberChart", {
data: chartData,
autoFit: true,
xField: "unionname",
@@ -697,8 +778,9 @@ layout("/layouts/platform.html"){
alias: "职工数"
}
}
})
this.renderChartWhenReady(chart.unionMemberChart, "unionMemberChart")
})
chart.unionMemberChart.render()
} else {
this.$message.warning(resp.msg)
}
@@ -721,7 +803,8 @@ layout("/layouts/platform.html"){
return
}
chart.personTypeMemberChart = new G2Plot.Column("personTypeMemberChart", {
this.createChartWhenReady("personTypeMemberChart", () => {
chart.personTypeMemberChart = new G2Plot.Column("personTypeMemberChart", {
data,
autoFit: true,
xField: "label",
@@ -802,8 +885,9 @@ layout("/layouts/platform.html"){
alias: "会员数"
}
}
})
this.renderChartWhenReady(chart.personTypeMemberChart, "personTypeMemberChart")
})
chart.personTypeMemberChart.render()
} else {
this.$message.warning(resp.msg)
}
@@ -21,6 +21,19 @@ layout("/layouts/platform.html"){
<el-option label="非会员" value="unMember"></el-option>
</el-select>
<el-select
v-model="pageForm.memberFeePaid"
placeholder="是否缴费"
clearable
style="width: 120px"
@change="pageData"
class="mr10"
size="small"
>
<el-option label="已缴费" :value="true"></el-option>
<el-option label="未缴费" :value="false"></el-option>
</el-select>
<el-select
v-model="pageForm.isUnit"
placeholder="是否有单位"
@@ -143,7 +156,8 @@ layout("/layouts/platform.html"){
data() {
return {
pageForm: {
searchType: "member"
searchType: "member",
memberFeePaid: true
},
unions: [],
units: [],
@@ -493,6 +493,15 @@ layout("/layouts/platform_h5.html"){
})
})
},
// 前端提示与后端使用相同的角色范围,后端仍会再次校验并决定实际流程分支。
isDirectToSchoolUnionAudit() {
return this.$auth.hasRoleOr(["SCHOOL_UNION_CHAIRMAN", "SCHOOL_UNION_VICE_CHAIRMAN", "SCHOOL_UNION_ADMIN"])
},
getSubmitConfirmMessage() {
return this.isDirectToSchoolUnionAudit()
? "您确定要提交吗?当前提交会直接到校工会审核。"
: "您确定要提交申请吗?"
},
async onSubmit() {
this.$refs.formRef.validate().then(() => {
if (!this.formData.signature){
@@ -501,7 +510,7 @@ layout("/layouts/platform_h5.html"){
}
this.$dialog.confirm({
title: "提示",
message: "您确定要提交申请吗?"
message: this.getSubmitConfirmMessage()
}).then(() => {
this.$axios.post("/platform/condolence/apply/submit", { data: JSON.stringify(this.formData) }).then(res => {
if (res.code === 0) {
@@ -520,7 +529,7 @@ layout("/layouts/platform_h5.html"){
}
this.$dialog.confirm({
title: "提示",
message: "您确定要提交申请吗?"
message: this.getSubmitConfirmMessage()
}).then(() => {
this.$axios.post("/platform/condolence/apply/submitAgain", {
data: JSON.stringify(this.formData),