Merge remote-tracking branch 'origin/main'

This commit is contained in:
@jyuhsin
2026-03-20 11:26:14 +08:00
4 changed files with 498 additions and 1 deletions
@@ -0,0 +1,179 @@
package com.budwk.app.zhgh.democratic.executiveCommittee.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.constant.RoleConstant;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.result.Result;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.democratic.executiveCommittee.models.ExecutiveCommitteeTwoPush;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.util.cri.SqlExpressionGroup;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
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 javax.validation.Valid;
import java.util.List;
import java.util.Map;
/**
* @author zhf
* @date 2026/3/20 10:51
* @description 正式委员录入
*/
@IocBean
@At("/platform/executiveCommittee/formalPush")
@Ok("json:full")
@Slf4j
@Api(tags = "执委会推选-正式委员录入")
public class ExecutiveCommitteeFormalPushController {
@Inject
private Dao dao;
@Inject
private BaseService baseService;
@At("/index")
@SaCheckPermission("executiveCommittee.formalPush")
@Ok("beetl:/platform/zhgh/democratic/executiveCommittee/formalPush/index.html")
public void index() {
}
@At
@ApiOperation("分页查询")
@SaCheckPermission("executiveCommittee.formalPush")
public Result pageData(PageForm pageForm,
String teacherMeetId,
String delegationId,
String unionId,
String roleCode) {
Sql sql = Sqls.create("""
SELECT
t1.*,
t2.loginName,
t2.userName,
t3.name AS unitName,
t4.name unionName,
t5.sex,
TIMESTAMPDIFF(
YEAR,
t5.birthday,
CURDATE()) AS age,
t6.name AS delegationName
FROM
`executive_committee_two_push` t1
LEFT JOIN executive_committee_one_push t2 on t2.userId=t1.userId and t2.teacherMeetId=t1.teacherMeetId
LEFT JOIN sys_unit t3 ON t2.unitId = t3.id
LEFT JOIN `sys_union` t4 ON t4.id = t3.unionid
LEFT JOIN `vw_user` t5 ON t5.id = t1.userId
LEFT JOIN teacher_congress_delegation t6 ON t6.id = t2.delegationId
$condition
""");
Cnd cnd = Cnd.NEW();
cnd.andEX("t1.teacherMeetId", "=", teacherMeetId);
cnd.andEX("t2.delegationId", "=", delegationId);
cnd.andEX("t1.roleCode", "=", roleCode);
cnd.andEX("t1.isFormal", "=", true);
if (StpUtil.hasRole(RoleConstant.SYSADMIN.name()) ||
StpUtil.hasRole(RoleConstant.SCHOOL_UNION_ADMIN.name()) ||
StpUtil.hasRole(RoleConstant.BRANCH_UNION_CHAIRMAN.name())) {
cnd.andEX("t4.id", "=", unionId);
} else {
cnd.andEX("t4.id", "=", SecurityUtil.getUnionId());
}
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
SqlExpressionGroup group = new SqlExpressionGroup();
group.orLike("t2.userName", pageForm.getSearchKeyword());
group.orLike("t2.loginName", pageForm.getSearchKeyword());
cnd.and(group);
}
cnd.asc("t6.code").asc("t2.firstLetter");
sql.setCondition(cnd);
return Result.success(baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql));
}
@At
@SaCheckPermission("executiveCommittee.formalPush")
@ApiOperation("查询可以推选委员和已经推选的人员")
public Result getDelegationUser(String teacherMeetId) {
List<ExecutiveCommitteeTwoPush> twoPushList = dao.query(ExecutiveCommitteeTwoPush.class,
Cnd.where("teacherMeetId", "=", teacherMeetId).and(ExecutiveCommitteeTwoPush::getRoleCode, "is not", null));
List<ExecutiveCommitteeTwoPush> userValue = twoPushList.stream().filter(ExecutiveCommitteeTwoPush::getIsFormal).toList();
List<String> userIds = userValue.stream().map(ExecutiveCommitteeTwoPush::getUserId).toList();
Sql sql = Sqls.create("""
SELECT
t2.id userId,
t2.username userName,
t2.loginname loginName,
t2.unitName,
t2.sex,
t2.professionalTitle,
t2.professionalLevel,
t1.roleCode,
TIMESTAMPDIFF(
YEAR,
t2.birthday,
CURDATE()) age
FROM
executive_committee_two_push t1
LEFT JOIN `vw_user` t2 ON t1.userId = t2.id
$condition
""");
Cnd cnd = Cnd.NEW();
cnd.andEX("t1.teacherMeetId", "=", teacherMeetId);
cnd.andEX("t1.userId", "not in", userIds);
sql.setCondition(cnd);
List<NutMap> userData = baseService.listMap(sql);
return Result.success(Map.of("userData", userData, "userValue", userValue));
}
@At
@SaCheckPermission("executiveCommittee.formalPush")
@SLog(tag = "执委会推选-正式委员录入", msg = "推选委员")
public Result addOnePush(@Param("userValue") String[] userValue,
String teacherMeetId) {
try {
if (ObjectUtil.isEmpty(userValue)) {
return Result.error("请选择要录入的委员!");
}
if (ObjectUtil.isEmpty(teacherMeetId)) {
return Result.error("请选择教代会!");
}
List<ExecutiveCommitteeTwoPush> twoPushList = dao.query(ExecutiveCommitteeTwoPush.class, Cnd.where(ExecutiveCommitteeTwoPush::getTeacherMeetId, "=", teacherMeetId).and(ExecutiveCommitteeTwoPush::getUserId, "in", userValue));
List<String> ids = twoPushList.stream().map(ExecutiveCommitteeTwoPush::getId).toList();
dao.update(ExecutiveCommitteeTwoPush.class, Chain.make("isFormal", true), Cnd.where("id", "in", ids));
return Result.success("添加成功!");
} catch (Exception e) {
e.printStackTrace();
return Result.error("添加失败!");
}
}
@At
@SaCheckPermission("executiveCommittee.formalPush")
@SLog(tag = "执委会推选-正式委员录入", msg = "删除推选的人")
public Result doDelete(@Valid String id, @Valid String teacherMeetId) {
dao.update(ExecutiveCommitteeTwoPush.class, Chain.make("isFormal", false), Cnd.where("id", "=", id));
return Result.success("删除成功!");
}
}
@@ -0,0 +1,223 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="姓名/工号">
<el-input v-model="pageForm.searchKeyword" placeholder="请输入姓名或工号" clearable>
</el-input>
</search-item>
<search-item label="教代会">
<el-select
v-model="pageForm.teacherMeetId"
filterable
placeholder="请选择教代会"
style="width:100%;"
@change="teacherMeetChange(pageForm.teacherMeetId)"
>
<el-option
v-for="item in teacherMeets"
:key="item.id"
:label="item.fullName"
:value="item.id"
></el-option>
</el-select>
</search-item>
<search-item label="所属工会">
<el-select clearable filterable placeholder="请选择所属工会" style="width: 100%"
v-model="pageForm.unionId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in unionOptions"></el-option>
</el-select>
</search-item>
<search-item label="代表团">
<el-select clearable filterable placeholder="请选择代表团" style="width: 100%"
v-model="pageForm.delegationId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in delegations"></el-option>
</el-select>
</search-item>
<search-item label="委员类别">
<el-select
v-model="pageForm.roleCode"
filterable
placeholder="请选择委员类别"
clearable
style="width:100%;"
>
<el-option label="执委会委员" value="1"></el-option>
<el-option label="工会委员会委员" value="2"></el-option>
<el-option label="经审委员会委员" value="3"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="上报列表">
<el-button
icon="el-icon-check"
size="small"
type="primary"
@click="$refs.onePushFormalRef.onOpen(pageForm.teacherMeetId)"
>正式委员录入
</el-button>
</table-tool>
<el-table
ref="tableRef"
:data="tableData"
row-key="id"
@sort-change="pageOrder"
v-loading="tableLoading"
>
<el-table-column :index="indexMethod" align="center" header-align="center"
label="序号"
fixed
type="index"
width="50"></el-table-column>
<el-table-column align="center" label="工号" prop="loginName"></el-table-column>
<el-table-column align="center" label="姓名" prop="userName"></el-table-column>
<el-table-column align="center" label="年龄" prop="age"></el-table-column>
<el-table-column align="center" label="性别" prop="sex"></el-table-column>
<el-table-column align="center" label="代表团" prop="delegationName"></el-table-column>
<el-table-column align="center" label="所属工会" prop="unionName"></el-table-column>
<el-table-column align="center" label="所属单位" prop="unitName"></el-table-column>
<el-table-column label="委员类别" prop="roleCode">
<template scope="{row}">
<el-tag v-if="row.roleCode === '1'">执委会委员</el-tag>
<el-tag v-if="row.roleCode === '2'">工会委员会委员</el-tag>
<el-tag v-if="row.roleCode === '3'">经审委员会委员</el-tag>
</template>
</el-table-column>
<el-table-column align="center" label="操作" width="100" fixed="right">
<template scope="{row}">
<el-button
size="mini"
type="danger"
@click="onDelete(row)"
>删除
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
</guava>
<push-formal-dialog ref="onePushFormalRef" @refresh="doSearch"></push-formal-dialog>
</div>
<script>
<!--#include("pushFormalDialog.js"){}#-->
const vue = new Vue({
el: '#app',
mixins: [initTableMixins],
data() {
return {
pageDataUrl: "/platform/executiveCommittee/formalPush/pageData",
pageForm: {
teacherMeetId: null,
unionId: null
},
teacherMeets: [],
unionOptions: [],
delegations: []
}
},
components: {
"push-formal-dialog": PUSH_FORMAL_DIALOG
},
async created() {
this.unionOptions = await this.$businessTool.listUnion()
await this.getAllJdh()
},
methods: {
async teacherMeetChange(val) {
this.$set(this.pageForm, 'delegationId', null)
this.getAllDelegation(val)
this.doSearch()
},
getAllDelegation(id) {
this.$axios.post("/platform/teacherCongress/common/listDelegation", {sessionId: id}).then(resp => {
if (resp.code === 0) {
this.delegations = resp.data
}
})
},
getAllJdh() {
this.$axios.post("/platform/teacherCongress/common/listSession", {}).then(resp => {
if (resp.code === 0) {
this.teacherMeets = resp.data
if (this.teacherMeets && this.teacherMeets.length > 0) {
this.$set(this.pageForm, 'teacherMeetId', this.teacherMeets[0].id)
this.getAllDelegation(this.teacherMeets[0].id)
this.pageData()
}
}
})
},
onDelete(row) {
this.$confirm('确定要删除该条数据吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
const resp = await this.$axios.post('/platform/executiveCommittee/formalPush/doDelete', {
id: row.id,
teacherMeetId: this.pageForm.teacherMeetId
})
if (resp.code === 0) {
this.doSearch()
this.$message.success(resp.msg)
}
})
},
}
})
</script>
<style>
.pushFormDialog .el-transfer-panel__item.el-checkbox {
height: auto;
display: block;
margin-right: 0;
padding: 0 15px;
}
.pushFormDialog .el-checkbox__input {
vertical-align: top;
margin-top: 5px;
}
.pushFormDialog .transfer-item {
padding: 5px;
font-size: 12px;
border-bottom: 1px solid #f0f0f0;
}
.pushFormDialog .el-transfer-panel {
height: 60vh;
width: unset !important;
flex: 2 !important;
}
.pushFormDialog .el-transfer-panel__body {
height: calc(100% - 40px) !important;
display: flex;
flex-direction: column;
}
.pushFormDialog .el-transfer-panel__list.is-filterable {
flex: 1;
}
</style>
<!--#
}
#-->
@@ -0,0 +1,95 @@
const PUSH_FORMAL_DIALOG = {
template: /*language=HTML*/ `
<div class="pushFormDialog">
<el-dialog
:close-on-click-modal="false"
:visible.sync="dialogVisible"
title="正式委员录入"
width="70%"
>
<el-transfer
ref="transfer"
v-model="userValue"
:data="userData"
filter-placeholder="请按姓名模糊搜索"
:filter-method="filterMethod"
:props="{key: 'userId',label: 'name'}"
:right-default-checked="rightChecked"
:titles="['可推选人员名单', '当前选择']"
filterable
class="transfer-high"
>
<div slot-scope="{ option }">
<div class="transfer-item">
<div class="transfer-item-name">{{ option.userName }} - {{ option.loginName }} -
{{option.unitName}}
</div>
<div class="transfer-item-details">
<span class="detail-item">
{{option.sex}}
</span>
<span class="detail-item">{{ option.age }}岁</span>
<span class="detail-item">{{ option.professionalTitle }}</span>
<span class="detail-item" style="color:#ee0a24;">{{ option.roleCode==='1'?'执委会委员':option.roleCode==='2'?'工会委员会委员':'经审委员会委员' }}</span>
</div>
</div>
</div>
</el-transfer>
<span slot="footer">
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="onConfirm">确 定</el-button>
</span>
</span>
</el-dialog>
</div>
`,
data() {
return {
dialogVisible: false,
userValue: [],
userData: [],
rightChecked: [],
attendanceRightChecked: [],
teacherMeetId: null,
prepareGroupQuotaCount: 0
}
},
methods: {
async onOpen(teacherMeetId) {
this.dialogVisible = true
this.teacherMeetId = teacherMeetId
this.userValue = []
this.userData = []
const {
code,
data
} = await this.$axios.post('/platform/executiveCommittee/formalPush/getDelegationUser', {teacherMeetId: teacherMeetId})
if (code === 0) {
data.userData.forEach(v => {
this.userData.push({userId: v.userId, ...v})
})
this.prepareGroupQuotaCount = data.prepareGroupQuotaCount
}
},
filterMethod(query, item) {
return item.userName.indexOf(query) > -1
},
async onConfirm() {
const {
code,
msg
} = await this.$axios.post('/platform/executiveCommittee/formalPush/addOnePush', {
userValue: JSON.stringify(this.userValue),
teacherMeetId: this.teacherMeetId
})
if (code === 0) {
this.dialogVisible = false
this.$message.success(msg)
this.$emit('refresh')
}
}
},
}
@@ -31,12 +31,12 @@ const PUSH_FORMAL_DIALOG = {
</span>
<span class="detail-item">{{ option.age }}岁</span>
<span class="detail-item">{{ option.professionalTitle }}</span>
<span class="detail-item" style="color:#ee0a24;">{{ option.roleCode==='1'?'执委会委员':option.roleCode==='2'?'工会委员会委员':'经审委员会委员' }}</span>
</div>
</div>
</div>
</el-transfer>
<span slot="footer">
<span style="color:red;font-size: 15px; display:flex;text-align: right;">推选名额:{{prepareGroupQuotaCount}}个</span>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="onConfirm">确 定</el-button>