This commit is contained in:
Paidax
2025-03-14 18:35:37 +08:00
parent 089959113a
commit a3d02c0f99
11 changed files with 226 additions and 34 deletions
@@ -1,6 +1,8 @@
package io.v.nutz.zhgh.staffmanage.sourcechange.service;
import io.v.nutz.base.service.BaseService;
import io.v.nutz.sys.models.User;
import io.v.nutz.zhgh.data.model.UserHistory;
import io.v.nutz.zhgh.staffmanage.sourcechange.model.SourceChangeMiddleTable;
import java.util.Date;
@@ -25,4 +27,11 @@ public interface SourceChangeManageService extends BaseService<SourceChangeMiddl
* 发送消息给新入职的老师,提醒可以入会
*/
void sendMsgToNewTeacher(SourceChangeMiddleTable middleTable);
/**
* 如果有单位异动的,找出异动前和异动后的分工会,发送消息提醒两个分工会的会员管理员
* 如果在同一个分工会下异动,则只发送一条消息
*/
void sendUnitChangeTeacher(SourceChangeMiddleTable middleTable, UserHistory history);
}
@@ -30,6 +30,8 @@ import org.nutz.aop.interceptor.ioc.TransAop;
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.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
@@ -233,12 +235,22 @@ public class SourceChangeManageServiceImpl extends BaseServiceImpl<SourceChangeM
dao().update(SourceChangeMiddleTable.class, Chain.make("isOperate", 2), Cnd.where("id", "=", middleTable.getId()));
sysUserService.deleteCacheAndUpdate(userId);
sysUserService.clearCache();
sysRoleService.clearCache();
// 如果有单位异动,发送消息提醒分工会
// if (middleTable.getChangeTypes().contains(MemberChangeType.UNIT_CHANGE.name())){
// sendUnitChangeTeacher(middleTable, history);
// }
}
}
/**
* 发送入会邀请
* @param middleTable
*/
@Override
public void sendMsgToNewTeacher(SourceChangeMiddleTable middleTable) {
String context = "尊敬的%s老师,欢迎您加入杭州医学院大家庭,请您点击此条信息或登录“智慧工会”平台申请成为杭医工会会员!"
@@ -246,4 +258,77 @@ public class SourceChangeManageServiceImpl extends BaseServiceImpl<SourceChangeM
String link = Globals.AppDomain + "/platform/member/apply/submit/h5";
msgApi.sendMsg(List.of("DingTalk"), middleTable.getLoginname(), 2, "入会邀请", context, "", link);
}
/**
* 如果有单位异动的,找出异动前和异动后的分工会,发送消息提醒两个分工会的会员管理员
* 如果在同一个分工会下异动,则只发送一条消息
*/
@Override
public void sendUnitChangeTeacher(SourceChangeMiddleTable middleTable, UserHistory history) {
// 查询出异动前的工会
Sql beforeUnionSql = Sqls.create("select un.id,un.unionname from sys_union un left join sys_unit unit on unit.unionid where unit.id = @unitId")
.setParam("unitId", history.getUnitid());
beforeUnionSql.setCallback(Sqls.callback.map());
dao().execute(beforeUnionSql);
NutMap beforeUnionMap = (NutMap) beforeUnionSql.getResult();
// 查询出异动后的工会
Sql afterUnionSql = Sqls.create("select un.id,un.unionname from sys_union un left join sys_unit unit on unit.unionid where unit.id = @unitId")
.setParam("unitId", middleTable.getUnitid());
afterUnionSql.setCallback(Sqls.callback.map());
dao().execute(afterUnionSql);
NutMap afterUnionMap = (NutMap) afterUnionSql.getResult();
// 如果这两个单位归属的是不同的分工会,发送消息提醒两个分工会
if (!beforeUnionMap.getString("id").equals(afterUnionMap.getString("id"))) {
// 找到变更前的分工会会员管理员,发送消息提醒
Sql beforeUnionAdminSql = Sqls.create("""
SELECT
u.loginname,
u.username
FROM
`user` u
LEFT JOIN `sys_user_role` userRole ON userRole.userId = u.id
LEFT JOIN sys_role role ON role.id = userRole.roleId
WHERE
role.`code` = 'BranchUnionMemberAdmin'
AND u.unionid = @unionId
""").setParam("unionId", beforeUnionMap.getString("id"));
List<NutMap> beforeMapList = commonService.listMap(beforeUnionAdminSql);
if (Lang.isNotEmpty(beforeMapList)) {
for (NutMap map : beforeMapList) {
String beforeContent = "尊敬的%s老师,根据学校最新人员信息调整,%s老师的工会关系已从您处调整至%s。特此告知,烦请知悉。祝您生活愉快!"
.formatted(map.getString("username"), middleTable.getUsername(), afterUnionMap.getString("unionname"));
// msgApi.sendMsg(List.of("DingTalk"), map.getString("loginname"), 1, "工会关系转出通知", beforeContent, "", "");
}
}
// 找到变更后的分工会会员管理员,发送消息提醒
Sql afterUnionAdminSql = Sqls.create("""
SELECT
u.loginname,
u.username
FROM
`user` u
LEFT JOIN `sys_user_role` userRole ON userRole.userId = u.id
LEFT JOIN sys_role role ON role.id = userRole.roleId
WHERE
role.`code` = 'BranchUnionMemberAdmin'
AND u.unionid = @unionId
""").setParam("unionId", afterUnionMap.getString("id"));
List<NutMap> afterMapList = commonService.listMap(afterUnionAdminSql);
if (Lang.isNotEmpty(afterMapList)) {
for (NutMap map : afterMapList) {
String afterContent = "尊敬的%s老师,根据学校最新人员信息调整,%s老师的工会关系已从%s调整至您处。特此告知,烦请知悉。祝您生活愉快!"
.formatted(map.getString("username"), middleTable.getUsername(), beforeUnionMap.getString("unionname"));
// msgApi.sendMsg(List.of("DingTalk"), map.getString("loginname"), 1, "工会关系转入通知", afterContent, "", "");
}
}
}
}
}
@@ -101,6 +101,7 @@ public class TrainSignUpActivityApplyController {
tsuc.isReceiveGift,
tsuc.giftType,
tsuc.reserveMode,
tsuc.remarks,
type.lxname
FROM
`train_sign_up_course` tsuc
@@ -1,6 +1,8 @@
package io.v.nutz.zhgh.trainSignUp.controller.manage;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import io.v.nutz.base.annontation.ViReturn;
import io.v.nutz.base.query.PageForm;
import io.v.nutz.base.utils.DateUtil;
@@ -81,14 +81,14 @@ public class TrainSignUpActivity extends BaseModel implements Serializable, SysH
private Integer limitNum;
@Column
@ColDefine(type = ColType.MYSQL_JSON)
@ColDefine(type = ColType.VARCHAR, width = 50)
@Comment("活动封面")
private Sys_file cover;
private String cover;
@Column
@ColDefine(type = ColType.MYSQL_JSON)
@ColDefine(type = ColType.VARCHAR, width = 50)
@Comment("微信群二维码")
private Sys_file wechat;
private String wechat;
@Column
@ColDefine(type = ColType.BOOLEAN)
@@ -139,7 +139,7 @@ public class TrainSignUpActivity extends BaseModel implements Serializable, SysH
Sys_home_activity sysHomeActivity = new Sys_home_activity();
sysHomeActivity.setId(this.getId());
sysHomeActivity.setName(this.getActivityName());
sysHomeActivity.setCover(this.getCover().getFilepath());
sysHomeActivity.setCover(this.getCover());
sysHomeActivity.setUrl("/platform/trainSingUp/manage/apply");
sysHomeActivity.setH5Url("/platform/mobile/trainSignUpActivity/trainInfo?activityId=" + this.getId() + "&endTime=" + DateUtil.format(this.getActivityEndTime(), "yyyy-MM-dd HH:mm:ss"));
if (Lang.isNotEmpty(this.getActivitySignUpStartTime())) {
@@ -143,6 +143,10 @@ public class TrainSignUpCourse extends BaseModel implements Serializable {
@ColDefine(type = ColType.VARCHAR, width = 30)
private String assort;
@Column
@Comment("详细内容备注")
@ColDefine(type = ColType.TEXT)
private String remarks;
private String courseTimeName;
}
@@ -153,6 +153,15 @@ layout("/mobile/platform.html"){
padding: 0;
}
.remark-content{
width: 100%;
max-width: 100%;
}
.remark-content *{
max-width: 100%!important;
}
</style>
<div id="app" v-cloak>
<van-sticky>
@@ -213,7 +222,7 @@ layout("/mobile/platform.html"){
<template v-else>
<span v-if="o.courseTimeList && o.courseTimeList.length > 1" @click="trainClick(o)"
style="color: #1867b0">点我查看</span>
<span @click="trainClick(o)" v-if="o.courseTimeList && o.courseTimeList.length === 1"
<span @click.stop="trainClick(o)" v-if="o.courseTimeList && o.courseTimeList.length === 1"
style="color: #1867b0">
{{o.courseTimeList[0].courseStartTime.substring(11, 19) + ' ~ ' + o.courseTimeList[0].courseEndTime.substring(11, 19)}}
</span>
@@ -225,6 +234,12 @@ layout("/mobile/platform.html"){
<span style="color: #1867b0">{{o.courseTimeName}}</span>
</div>
</template>
<template v-if="o.remarks">
<div>
<span class="train-title">详细信息:</span>
<span @click.stop="showRemark(o)" style="color: #1867b0">点我查看</span>
</div>
</template>
<div>
<span @click.stop="showPic(FILE_DOMAIN + '/fileStreamPreview?id=' + tableData.wechat.id)"
v-if="o.isSign === true && tableData.wechat"
@@ -354,6 +369,11 @@ layout("/mobile/platform.html"){
</van-popup>
<van-action-sheet v-model="remarkShow" title="详情" >
<div class="remark-content" v-html="courseRemark" @click="remarkClick"></div>
</van-action-sheet>
<div>
<van-tabbar v-model="tarBarActive">
<van-tabbar-item icon="home-o" replace @click="pjaxReplace('/platform/mobile/trainSignUpActivity/trainList')">活动报名</van-tabbar-item>
@@ -399,6 +419,9 @@ layout("/mobile/platform.html"){
showCoursePicker: false,
courseTimeSelectList: [],
remarkShow: false,
courseRemark: '',
}
},
components: {
@@ -427,8 +450,12 @@ layout("/mobile/platform.html"){
+ "<span style='color: red'>候补余" + lave2 + "</span>/" + o.courseReservedNumber + "人)"
return str
} else {
let lave = o.coursePeopleNumber - (o.hasRegisterNum + o.courseReservedNumber)
return "<span style='color: red'>余" + lave +"</span>/" + o.coursePeopleNumber + "人)"
if (Number(o.coursePeopleNumber) >= 1000) {
return "<span style='color: #ff8400'>无名额限制</span>/已报<span style='color: red'>" + o.hasRegisterNum + "</span>人)"
} else {
let lave = o.coursePeopleNumber - (o.hasRegisterNum + o.courseReservedNumber)
return "<span style='color: red'>余" + lave +"</span>/" + o.coursePeopleNumber + "人)"
}
}
},
getCourseTypeName(o) {
@@ -728,6 +755,16 @@ layout("/mobile/platform.html"){
}
this.popupShow = true
},
showRemark(o){
this.remarkShow = true
this.courseRemark = o.remarks
},
remarkClick(event){
//如果点击的是图片
if(event.target.tagName === 'IMG'){
vant.ImagePreview([event.target.src])
}
},
initMap(o) {
if (o.courseLocationCoordinates && o.courseLocationCoordinates.length < 2) {
return
@@ -110,9 +110,9 @@ layout("/mobile/platform.html"){
</div>
<div @click="welfareClick(o)">
<div>
<van-image :src="CREATE_PREVIEW_URL(o.cover.id)"
<van-image :src="CREATE_PREVIEW_URL(o.cover)"
style="display: contents"
v-if="o.cover && o.cover.filepath"></van-image>
v-if="o.cover"></van-image>
<van-image src=""
style="display: contents"
v-else></van-image>
@@ -81,6 +81,8 @@ layout("/layouts/platform.html"){
},
courseIndex: 0,
setUpCourseDialog: false,
remarkIndex: 0,
setUpRemarkDialog: false,
unionLimitIndex: 0,
setUpUnionLimitDialog: false,
viewMapDialog: false,
@@ -227,6 +229,10 @@ layout("/layouts/platform.html"){
this.courseIndex = index
this.setUpCourseDialog = true
},
openSetUpCourseRemarks(index) {
this.remarkIndex = index
this.setUpRemarkDialog = true
},
//打开设置分工会人数限制
async openSetUpUnionLimit(index) {
this.unionLimitIndex = index
@@ -308,6 +308,12 @@ layout("/layouts/platform.html"){
</el-table-column>
<el-table-column label="详细信息" prop="remarks">
<template scope="{row}">
<el-button type="text" @click="openViewRemark(row)">点我查看详情</el-button>
</template>
</el-table-column>
<el-table-column align="center" label="操作" width="150px">
<template slot-scope="scope">
<!-- <el-button type="primary" size="small">查看信息</el-button>-->
@@ -447,6 +453,13 @@ layout("/layouts/platform.html"){
<el-button type="primary" @click="doSubmit">提 交</el-button>
</el-row>
</el-dialog>
<el-dialog :visible.sync="remarkShow" title="详细信息" width="50%" append-to-body>
<div class="text-center" v-html="courseRemark"></div>
<el-row type="flex" justify="end" style="margin-top: 20px">
<el-button type="primary" @click="remarkShow = false">关 闭</el-button>
</el-row>
</el-dialog>
</div>
<script>
@@ -465,9 +478,9 @@ layout("/layouts/platform.html"){
activityList: [],
courseTypeList: [],
tableColumns: [
{prop: 'courseName', label: '名称', width: '350px'},
{prop: 'lxname', label: '类型', width: '80px'},
{prop: 'assort', label: '标识', width: '200px'},
{prop: 'courseName', label: '名称', width: '250px'},
{prop: 'lxname', label: '类型', width: '70px'},
{prop: 'assort', label: '标识', width: '150px'},
// {prop: 'coursePeopleNumber', label: '总人数', width: '80px'},
{prop: 'courseLocationCoordinates', label: '地点'},
{prop: 'courseInstructor', label: '联系人'},
@@ -485,9 +498,20 @@ layout("/layouts/platform.html"){
trainType: '培训班',
applyDialog: false,
remarkShow: false,
courseRemark: '',
}
},
methods: {
openViewRemark(row){
if (!row.remarks) {
this.$message.warning('暂无详细信息')
return
}
this.courseRemark = row.remarks
this.remarkShow = true
},
async doCancel(row){
const msg = '您确认要取消' + row.courseName + '的报名吗?'
this.$confirm(msg, '提示', {
@@ -522,8 +546,12 @@ layout("/layouts/platform.html"){
+ "<span style='color: red'>候补余" + lave2 + "</span>/" + o.courseReservedNumber + "人)"
return str
} else {
let lave = o.coursePeopleNumber - (o.hasRegisterNum + o.courseReservedNumber)
return "<span style='color: red'>余" + lave +"</span>/" + o.coursePeopleNumber + "人)"
if (Number(o.coursePeopleNumber) >= 1000) {
return "<span style='color: #ff8400'>无名额限制</span>/已报<span style='color: red'>" + o.hasRegisterNum + "</span>人)"
} else {
let lave = o.coursePeopleNumber - (o.hasRegisterNum + o.courseReservedNumber)
return "<span style='color: red'>余" + lave +"</span>/" + o.coursePeopleNumber + "人)"
}
}
},
async doSubmit() {
@@ -144,19 +144,29 @@
<el-form-item label="封面图片" prop="cover" :rules="{required:true,message: '请上传活动移动端封面图片', trigger: 'blur'}">
<el-col :span="12">
<file-upload ref="coverFileUpload" :files.sync="formData.cover" :max="1" :type="['jpg','jpeg','png','JPG','JPEG','PNG']">
<template #el-upload__tip>
<div class="el-upload__tip" slot="tip">请上传一张jpg/png/jpeg等格式,且不大于2M的照片</div>
</template>
</file-upload>
<image-Upload :file-size="10" :file-type="['jpg','jpeg','png','JPG','JPEG','PNG']"
:height="70" :limit="1"
:width="140"
ref="coverFileUpload"
v-model="formData.cover"></image-Upload>
<!-- <file-upload ref="coverFileUpload" :files.sync="formData.cover" :max="1" :type="['jpg','jpeg','png','JPG','JPEG','PNG']">-->
<!-- <template #el-upload__tip>-->
<!-- <div class="el-upload__tip" slot="tip">请上传一张jpg/png/jpeg等格式,且不大于2M的照片</div>-->
<!-- </template>-->
<!-- </file-upload>-->
</el-col>
<el-col :span="12">
<el-form-item label="微信群二维码" prop="wechat">
<file-upload :files.sync="formData.wechat" :max="1" :type="['jpg','jpeg','png','JPG','JPEG','PNG']">
<template #el-upload__tip>
<div slot="tip" class="el-upload__tip">请上传一张jpg/png/jpeg等格式,且不大于2M的照片</div>
</template>
</file-upload>
<image-Upload :file-size="10"
:file-type="['jpg','jpeg','png','JPG','JPEG','PNG']" :height="70"
:limit="1"
:width="140"
v-model="formData.wechat"></image-Upload>
<!-- <file-upload :files.sync="formData.wechat" :max="1" :type="['jpg','jpeg','png','JPG','JPEG','PNG']">-->
<!-- <template #el-upload__tip>-->
<!-- <div slot="tip" class="el-upload__tip">请上传一张jpg/png/jpeg等格式,且不大于2M的照片</div>-->
<!-- </template>-->
<!-- </file-upload>-->
</el-form-item>
</el-col>
</el-form-item>
@@ -170,7 +180,7 @@
</vi-title2>
<el-table :data="formData.courseList">
<el-table-column label="序号" prop="orderNum" width="120px">
<el-table-column fixed="left" label="序号" prop="orderNum" width="120px">
<template scope="{row}">
<el-input-number v-model="row.orderNum"
@change="courseOrderNumChange"
@@ -186,13 +196,13 @@
</template>
</el-table-column>
<el-table-column :label="trainType + '名称'" prop="courseName">
<el-table-column fixed="left" :label="trainType + '名称'" prop="courseName" width="200">
<template scope="{row}">
<el-input v-model="row.courseName"></el-input>
</template>
</el-table-column>
<el-table-column label="类型" prop="courseType" sortable>
<el-table-column label="类型" prop="courseType" sortable width="200">
<template scope="{row}">
<el-select v-model="row.courseType" @change="(val) => {courseTypeChange(val, row)}">
<el-option :label="c.lxname" :value="c.id" v-for="c in courseTypeList"></el-option>
@@ -225,7 +235,7 @@
</template>
</el-table-column>
<el-table-column label="校区" prop="campus">
<el-table-column label="校区" prop="campus" width="200">
<template scope="{row}">
<el-select v-model="row.campus" style="width: 100%">
<el-option :label="item.campus_name" :value="item.campus_name"
@@ -234,31 +244,37 @@
</template>
</el-table-column>
<el-table-column :label="trainType + '地点'" prop="courseLocation">
<el-table-column :label="trainType + '地点'" prop="courseLocation" width="250">
<template scope="{row}">
<el-input v-model="row.courseLocation"></el-input>
</template>
</el-table-column>
<el-table-column :label="trainType + '负责人'" prop="courseInstructor">
<el-table-column :label="trainType + '负责人'" prop="courseInstructor" width="200">
<template scope="{row}">
<el-input v-model="row.courseInstructor"></el-input>
</template>
</el-table-column>
<el-table-column label="分类标识" prop="assort">
<el-table-column label="分类标识" prop="assort" width="200">
<template scope="{row}">
<el-input v-model="row.assort"></el-input>
</template>
</el-table-column>
<el-table-column :label="trainType + '时间'">
<el-table-column :label="trainType + '时间'" width="200">
<template scope="scope">
<el-button @click="openSetUpCourseTime(scope.$index)" type="text">设置{{ trainType }}时间</el-button>
</template>
</el-table-column>
<el-table-column label="操作" width="200">
<el-table-column label="详细信息" prop="remarks" width="120">
<template scope="scope">
<el-button @click="openSetUpCourseRemarks(scope.$index)" type="text">详细信息</el-button>
</template>
</el-table-column>
<el-table-column fixed="right" label="操作" width="200">
<template scope="scope">
<el-button @click="openMoreInfo(scope, scope.$index)"
size="mini" type="primary">
@@ -415,6 +431,10 @@
</el-row>
</el-dialog>
<el-dialog :close-on-click-modal="false" :visible.sync="setUpRemarkDialog" title="详细信息">
<text-editor v-model="formData.courseList[remarkIndex].remarks"></text-editor>
</el-dialog>
<el-dialog :close-on-click-modal="false" :visible.sync="mapDialog" title="位置信息">
<!--#include("/platform/trainSingUp/manage/include_activity_map.html"){}#-->
</el-dialog>