This commit is contained in:
2026-04-16 11:09:56 +08:00
parent 22176f342f
commit cbc9c4ee5c
10 changed files with 239 additions and 165 deletions
@@ -31,149 +31,152 @@ import java.util.List;
@IocBean
public class SmsJshvcServiceImpl implements SmsService {
@Override
public void sendSingleMessage(String loginName, String content) {
this.sendSingleMessage(loginName, "智慧工会", content);
}
@Override
public void sendSingleMessage(String loginName, String content) {
this.sendSingleMessage(loginName, "智慧工会", content);
}
@Override
public void sendSingleMessage(String loginName, String title, String content) {
this.massSendMessage(List.of(loginName), title, content);
}
@Override
public void sendSingleMessage(String loginName, String title, String content) {
this.massSendMessage(List.of(loginName), title, content);
}
@Override
public void sendSingleTextCard(String loginName, String content, String pcUrl, String mobileUrl) {
this.sendSingleTextCard(loginName, "智慧工会", content, pcUrl, mobileUrl);
}
@Override
public void sendSingleTextCard(String loginName, String content, String pcUrl, String mobileUrl) {
this.sendSingleTextCard(loginName, "智慧工会", content, pcUrl, mobileUrl);
}
@Override
public void sendSingleTextCard(String loginName, String title, String content, String pcUrl, String mobileUrl) {
this.massSendTextCard(List.of(loginName), title, content, pcUrl, mobileUrl);
}
@Override
public void sendSingleTextCard(String loginName, String title, String content, String pcUrl, String mobileUrl) {
this.massSendTextCard(List.of(loginName), title, content, pcUrl, mobileUrl);
}
@Override
public void sendSinglePicTextCard(String loginName, String content, String pcUrl, String mobileUrl, String picUrl) {
this.sendSinglePicTextCard(loginName, "智慧工会", content, pcUrl, mobileUrl, picUrl);
}
@Override
public void sendSinglePicTextCard(String loginName, String content, String pcUrl, String mobileUrl, String picUrl) {
this.sendSinglePicTextCard(loginName, "智慧工会", content, pcUrl, mobileUrl, picUrl);
}
@Override
public void sendSinglePicTextCard(String loginName, String title, String content, String pcUrl, String mobileUrl, String picUrl) {
this.massSendPicTextCard(List.of(loginName), title, content, pcUrl, mobileUrl, picUrl);
}
@Override
public void sendSinglePicTextCard(String loginName, String title, String content, String pcUrl, String mobileUrl, String picUrl) {
this.massSendPicTextCard(List.of(loginName), title, content, pcUrl, mobileUrl, picUrl);
}
@Override
public void massSendMessage(List<String> loginNames, String content) {
this.massSendMessage(loginNames, "智慧工会", content);
}
@Override
public void massSendMessage(List<String> loginNames, String content) {
this.massSendMessage(loginNames, "智慧工会", content);
}
@Override
public void massSendMessage(List<String> loginNames, String title, String content) {
List<ReceiverDto> list = loginNames.stream().map(loginName -> {
ReceiverDto receiverDto = new ReceiverDto();
receiverDto.setUserId(loginName);
return receiverDto;
}).toList();
this.doSend(WxSendType_Constants.TEXT, list, title, content, null, null, null);
}
@Override
public void massSendMessage(List<String> loginNames, String title, String content) {
List<ReceiverDto> list = loginNames.stream().map(loginName -> {
ReceiverDto receiverDto = new ReceiverDto();
receiverDto.setUserId(loginName);
return receiverDto;
}).toList();
this.doSend(WxSendType_Constants.TEXT, list, title, content, null, null, null);
}
@Override
public void massSendTextCard(List<String> loginNames, String content, String pcUrl, String mobileUrl) {
this.massSendTextCard(loginNames, "智慧工会", content, pcUrl, mobileUrl);
}
@Override
public void massSendTextCard(List<String> loginNames, String content, String pcUrl, String mobileUrl) {
this.massSendTextCard(loginNames, "智慧工会", content, pcUrl, mobileUrl);
}
@Override
public void massSendTextCard(List<String> loginNames, String title, String content, String pcUrl, String mobileUrl) {
List<ReceiverDto> list = loginNames.stream().map(loginName -> {
ReceiverDto receiverDto = new ReceiverDto();
receiverDto.setUserId(loginName);
return receiverDto;
}).toList();
this.doSend(WxSendType_Constants.TEXT_CARD, list, title, content, pcUrl, mobileUrl, null);
}
@Override
public void massSendTextCard(List<String> loginNames, String title, String content, String pcUrl, String mobileUrl) {
List<ReceiverDto> list = loginNames.stream().map(loginName -> {
ReceiverDto receiverDto = new ReceiverDto();
receiverDto.setUserId(loginName);
return receiverDto;
}).toList();
this.doSend(WxSendType_Constants.TEXT_CARD, list, title, content, pcUrl, mobileUrl, null);
}
@Override
public void massSendPicTextCard(List<String> loginNames, String content, String pcUrl, String mobileUrl, String picUrl) {
this.massSendPicTextCard(loginNames, "智慧工会", content, pcUrl, mobileUrl, picUrl);
}
@Override
public void massSendPicTextCard(List<String> loginNames, String content, String pcUrl, String mobileUrl, String picUrl) {
this.massSendPicTextCard(loginNames, "智慧工会", content, pcUrl, mobileUrl, picUrl);
}
@Override
public void massSendPicTextCard(List<String> loginNames, String title, String content, String pcUrl, String mobileUrl, String picUrl) {
List<ReceiverDto> list = loginNames.stream().map(loginName -> {
ReceiverDto receiverDto = new ReceiverDto();
receiverDto.setUserId(loginName);
return receiverDto;
}).toList();
this.doSend(WxSendType_Constants.NEWS, list, title, content, pcUrl, mobileUrl, picUrl);
}
@Override
public void massSendPicTextCard(List<String> loginNames, String title, String content, String pcUrl, String mobileUrl, String picUrl) {
List<ReceiverDto> list = loginNames.stream().map(loginName -> {
ReceiverDto receiverDto = new ReceiverDto();
receiverDto.setUserId(loginName);
return receiverDto;
}).toList();
this.doSend(WxSendType_Constants.NEWS, list, title, content, pcUrl, mobileUrl, picUrl);
}
@Override
public void recallMsg(String msgId) {
try {
Client client = new DefaultClient(TodoPlatformConfig.TODO_PLATFORM_BASE_URL, TodoPlatformConfig.TODO_APP_ID, TodoPlatformConfig.TODO_APP_SECRET);
RecallMsgRequest request = new RecallMsgRequest();
request.setMsgId(msgId);
@Override
public void recallMsg(String msgId) {
try {
Client client = new DefaultClient(TodoPlatformConfig.TODO_PLATFORM_BASE_URL, TodoPlatformConfig.TODO_APP_ID, TodoPlatformConfig.TODO_APP_SECRET);
RecallMsgRequest request = new RecallMsgRequest();
request.setMsgId(msgId);
log.info("撤回企业微信消息,请求参数:{}", Json.toJson(request));
RecallMsgResponse response = client.execute(request);
log.info("撤回企业微信消息,接口响应数据:{}", Json.toJson(response));
} catch (Exception e) {
log.error("撤回企业微信消息失败", e);
}
}
log.info("撤回企业微信消息,请求参数:{}", Json.toJson(request));
RecallMsgResponse response = client.execute(request);
log.info("撤回企业微信消息,接口响应数据:{}", Json.toJson(response));
} catch (Exception e) {
log.error("撤回企业微信消息失败", e);
}
}
private void doSend(String sendType,
List<ReceiverDto> receivers,
String title,
String content,
String pcUrl,
String mobileUrl,
String picUrl) {
private void doSend(String sendType,
List<ReceiverDto> receivers,
String title,
String content,
String pcUrl,
String mobileUrl,
String picUrl) {
if (!Globals.MyConfig.getBoolean("AppSms", false)) {
log.error("【log】消息配置未开启");
return;
}
if (!Globals.sso) {
log.error("【log】开发模式不允许发送企业微信通知");
return;
}
if (!Globals.sso) {
log.error("【log】开发模式不允许发送企业微信通知");
return;
}
if (Lang.isEmpty(receivers)) {
log.error("send fail by receivers is null");
return;
}
try {
// 创建客户端
Client client = new DefaultClient(TodoPlatformConfig.TODO_PLATFORM_BASE_URL, TodoPlatformConfig.TODO_APP_ID, TodoPlatformConfig.TODO_APP_SECRET);
SendMsgRequest request = new SendMsgRequest();
request.setSubject(title);
request.setContent(content);
request.setMsgType(MsgType_Constants.COMMON);
request.setSendType(SendType_Constants.WECHAT_ENTERPRISE);
request.setWxSendType(sendType);
request.setReceivers(receivers);
if (Lang.isEmpty(receivers)) {
log.error("send fail by receivers is null");
return;
}
try {
// 创建客户端
Client client = new DefaultClient(TodoPlatformConfig.TODO_PLATFORM_BASE_URL, TodoPlatformConfig.TODO_APP_ID, TodoPlatformConfig.TODO_APP_SECRET);
SendMsgRequest request = new SendMsgRequest();
request.setSubject(title);
request.setContent(content);
request.setMsgType(MsgType_Constants.COMMON);
request.setSendType(SendType_Constants.WECHAT_ENTERPRISE);
request.setWxSendType(sendType);
request.setReceivers(receivers);
if (WxSendType_Constants.TEXT_CARD.equals(sendType)) {
request.setPcUrl(pcUrl);
request.setMobileUrl(mobileUrl);
request.setUrlDesc("查看详情");
}
if (WxSendType_Constants.NEWS.equals(sendType)) {
request.setPcUrl(pcUrl);
request.setMobileUrl(mobileUrl);
request.setUrlDesc("查看详情");
request.setQyWeChatImgUrl(picUrl);
}
if (WxSendType_Constants.TEXT_CARD.equals(sendType)) {
request.setPcUrl(pcUrl);
request.setMobileUrl(mobileUrl);
request.setUrlDesc("查看详情");
}
if (WxSendType_Constants.NEWS.equals(sendType)) {
request.setPcUrl(pcUrl);
request.setMobileUrl(mobileUrl);
request.setUrlDesc("查看详情");
request.setQyWeChatImgUrl(picUrl);
}
log.info("发送企业微信通知,请求参数:{}", Json.toJson(request));
SendMsgResponse response = client.execute(request);
log.info("发送企业微信通知,接口响应数据:{}", Json.toJson(response));
log.info("发送企业微信通知,请求参数:{}", Json.toJson(request));
SendMsgResponse response = client.execute(request);
log.info("发送企业微信通知,接口响应数据:{}", Json.toJson(response));
if (response.isSuccess() && response.getStatus() == 200) {
// TODO 消息Id,后面可以存着,撤回要用到
String msgId = response.getMsgId();
log.info("发送企业微信通知成功: {}, msg: {}", response.getStatus(), response.getMsg());
} else {
log.info("发送企业微信通知失败:{}", response.getMsg());
}
} catch (Exception e) {
log.error("发送企业微信通知失败", e);
}
}
if (response.isSuccess() && response.getStatus() == 200) {
// TODO 消息Id,后面可以存着,撤回要用到
String msgId = response.getMsgId();
log.info("发送企业微信通知成功: {}, msg: {}", response.getStatus(), response.getMsg());
} else {
log.info("发送企业微信通知失败:{}", response.getMsg());
}
} catch (Exception e) {
log.error("发送企业微信通知失败", e);
}
}
}
@@ -1,6 +1,7 @@
package com.budwk.app.zhgh.democratic.proposal.service.common;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
@@ -172,6 +173,7 @@ public class ProposalCommonServiceImpl extends BaseServiceImpl<ProposalInfo> imp
SELECT
info.name,
info.code,
info.excerpt,
info.brief,
info.measures,
info.createUserName,
@@ -215,6 +217,20 @@ public class ProposalCommonServiceImpl extends BaseServiceImpl<ProposalInfo> imp
// 按任务节点分组
Map<String, List<ProcessTaskVO>> taskGroups = doneTaskVos.stream().collect(Collectors.groupingBy(ProcessTaskVO::getDisplayName));
taskGroups.forEach((taskKey, taskVOS) -> {
if (taskKey.equals("提案附议")){
taskVOS.forEach(taskVO -> {
Dict ext = taskVO.getExt();
if (ObjectUtil.isNotEmpty(ext)) {
String tfSignature = ext.getStr("tf_signature");
// 导出 Word 时将签字附件地址转换为图片对象,避免 taskFormData 重建后丢失值。
if (StrUtil.isNotBlank(tfSignature)) {
ext.set("tf_signatureImg", sysOfficeTemplateUtil.createPictureRenderData(tfSignature));
}
}
});
}
});
docData.putAll(taskGroups);
LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
@@ -166,6 +166,7 @@ public class ProposalExportServiceImpl extends BaseServiceImpl<ProposalInfo> imp
info.name,
info.code,
info.researchFindings,
info.excerpt,
info.brief,
info.measures,
info.createUserName,
@@ -220,8 +221,8 @@ public class ProposalExportServiceImpl extends BaseServiceImpl<ProposalInfo> imp
exportEntities.add(new ExcelExportEntity("序号", "index", 10));
exportEntities.add(new ExcelExportEntity("提案编号", "code", 20));
exportEntities.add(new ExcelExportEntity("提案名称", "name", 20));
exportEntities.add(new ExcelExportEntity("提案概要", "excerpt", 40));
exportEntities.add(new ExcelExportEntity("提案案由", "brief", 40));
exportEntities.add(new ExcelExportEntity("代表调研情况", "researchFindings", 40));
exportEntities.add(new ExcelExportEntity("代表建议措施", "measures", 40));
exportEntities.add(new ExcelExportEntity("提案人", "createUserName", 20));
exportEntities.add(new ExcelExportEntity("提案人电话", "mobile", 20));
@@ -541,6 +542,7 @@ public class ProposalExportServiceImpl extends BaseServiceImpl<ProposalInfo> imp
info.name,
info.code,
info.researchFindings,
info.excerpt,
info.brief,
info.measures,
info.createUserName,
@@ -29,9 +29,9 @@ const PROPOSAL_INFO = {
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_RESULT"
:value="viewData.caseFilingResult"></dict-tag>
</el-descriptions-item>
<!--<el-descriptions-item label="调研情况" :span="3">
<div class="text-left">{{viewData.researchFindings}}</div>
</el-descriptions-item>-->
<el-descriptions-item label="提案摘要" :span="3">
<div class="text-left">{{viewData.excerpt}}</div>
</el-descriptions-item>
<el-descriptions-item label="提案案由" :span="3">
<div class="text-left" v-html="viewData.brief"></div>
</el-descriptions-item>
@@ -140,6 +140,31 @@ const PROPOSAL_INFO = {
<el-table-column label="代表团" prop="delegationName"></el-table-column>
</el-table>
</el-descriptions-item>
</el-descriptions>
<el-descriptions border class="flow-task-form" :column="3" :key="task.id"
v-else-if="task.taskName === 'second'">
<el-descriptions-item label="附议人">{{ task.taskFormData.userName
}}({{task.taskFormData.loginName}})
</el-descriptions-item>
<el-descriptions-item label="附议时间">{{ task.finishTime }}</el-descriptions-item>
<el-descriptions-item label="办理结果">
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
:value="task.ext.submitType"></dict-tag>
</el-descriptions-item>
<el-descriptions-item label="附议意见" :span="3">
<div v-html="task.ext.tf_opinion"></div>
</el-descriptions-item>
<el-descriptions-item label="签字" :span="3">
<el-image :src="task.ext.tf_signature" class="signature-image"
v-if="task.ext.tf_signature">
<div slot="error" class="image-slot">
<i class="el-icon-picture-outline"></i>
</div>
</el-image>
<span v-else>暂无</span>
</el-descriptions-item>
</el-descriptions>
<!--提案委员会立案-->
@@ -163,10 +188,12 @@ const PROPOSAL_INFO = {
</div>
</el-descriptions-item>
<el-descriptions-item label="主办单位" :span="3"
v-if="['CONFIRM_FILING','SUGGESTION'].includes(task.ext.tf_caseFilingResult)">{{task.ext.tf_masterUnitName}}
v-if="['CONFIRM_FILING','SUGGESTION'].includes(task.ext.tf_caseFilingResult)">
{{task.ext.tf_masterUnitName}}
</el-descriptions-item>
<el-descriptions-item label="协办单位" :span="3"
v-if="['CONFIRM_FILING','SUGGESTION'].includes(task.ext.tf_caseFilingResult)">{{task?.ext?.tf_slaveUnitNameStr}}
v-if="['CONFIRM_FILING','SUGGESTION'].includes(task.ext.tf_caseFilingResult)">
{{task?.ext?.tf_slaveUnitNameStr}}
</el-descriptions-item>
<el-descriptions-item label="办理意见" :span="3">
<div v-html="task.ext.approvalOpinion"></div>
@@ -201,6 +201,7 @@ layout("/layouts/platform.html"){
{label: "立案结果", prop: "caseFilingResult"},
{label: "立案类型", prop: "caseFilingType"},
{label: "是否并案", prop: "merge"},
{label: "提案概要", prop: "excerpt", visible: false},
{label: "案由", prop: "brief", visible: false},
{label: "建议措施", prop: "measures", visible: false},
{label: "主办单位", prop: "masterUnitName"},
@@ -76,6 +76,9 @@ layout("/layouts/platform.html"){
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<user-opinion-textarea v-model="formData.tf_opinion"></user-opinion-textarea>
</el-form-item>
<el-form-item label="电子签名" prop="tf_signature" :rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<pc-signature v-model="formData.tf_signature"></pc-signature>
</el-form-item>
</el-form>
<el-row type="flex" justify="end">
<el-button @click="$refs.guava.index()" size="small">取消</el-button>
@@ -99,21 +99,21 @@ layout("/layouts/platform.html"){
</el-col>
</el-row>
<!-- <el-form-item label="提案要" prop="excerpt">-->
<!-- <span slot="label">-->
<!-- 提案摘要-->
<!-- <el-tooltip content="请简述提案内容和依据、改进建议和措施摘要" placement="right">-->
<!-- <i class="el-icon-question"></i>-->
<!-- </el-tooltip>-->
<!-- </span>-->
<!-- <el-input-->
<!-- v-model="formData.excerpt"-->
<!-- type="textarea"-->
<!-- autosize-->
<!-- :autosize="{ minRows: 4, maxRows: 4}"-->
<!-- placeholder="提案摘要"-->
<!-- ></el-input>-->
<!-- </el-form-item>-->
<el-form-item label="提案要" prop="excerpt">
<span slot="label">
提案摘要
<el-tooltip content="请简述提案内容和依据、改进建议和措施摘要"
placement="right">
<i class="el-icon-question"></i>
</el-tooltip>
</span>
<el-input
show-word-limit
v-model="formData.excerpt"
maxlength="20"
placeholder="提案摘要"
></el-input>
</el-form-item>
<!-- <el-form-item label="调研情况" prop="researchFindings">-->
<!-- <el-input-->
@@ -27,9 +27,9 @@ const PROPOSAL_INFO = {
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_RESULT"
:value="viewData.caseFilingResult"></dict-tag>
</van-cell>
<!--<van-cell title="调研情况" class="direction-column-cell">
<div v-html="viewData.researchFindings"></div>
</van-cell>-->
<van-cell title="提案摘要" class="direction-column-cell">
<div class="text-left">{{viewData.excerpt}}</div>
</van-cell>
<van-cell title="提案案由" class="direction-column-cell">
<div v-html="viewData.brief"></div>
</van-cell>
@@ -121,6 +121,26 @@ const PROPOSAL_INFO = {
</van-cell>
</van-cell-group>
<van-cell-group :title="task.displayName"
v-else-if="task.taskName === 'second'">
<van-cell title="附议人">{{ task.taskFormData.userName }}({{task.taskFormData.loginName}})
</van-cell>
<van-cell title="附议时间">{{ task.finishTime }}</van-cell>
<van-cell title="办理结果">
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
:value="task.ext.submitType"></dict-tag>
</van-cell>
<van-cell title="办理意见" v-if="!task.ext.isFirstTaskNode" class="direction-column-cell">
<div v-html="task.taskFormData.tf_opinion"></div>
</van-cell>
<van-cell title="签字">
<div slot="label">
<van-image :src="task.taskFormData.tf_signature"
style="width: 100%;height: 150px;border: 1px dashed"></van-image>
</div>
</van-cell>
</van-cell-group>
<!--提案委员会立案-->
<van-cell-group :title="task.displayName"
v-else-if="task.taskName === 'committee'">
@@ -63,9 +63,10 @@ layout("/layouts/platform_h5.html"){
maxlength="100"
show-word-limit
></van-field>
<!-- <van-field label="签字" name="approvalSignature" v-model="formData.signature" required class="direction-column-field">-->
<!-- <h5-signature v-model="formData.approvalSignature" slot="input"></h5-signature>-->
<!-- </van-field>-->
<van-field label="签字" name="tf_signature" v-model="formData.tf_signature" required
class="direction-column-field">
<h5-signature v-model="formData.tf_signature" slot="input"></h5-signature>
</van-field>
</van-form>
<div style="display: flex; justify-content: space-between; column-gap: 10px; padding: 10px">
<van-button type="danger" block @click="handleTaskAction(20)">不同意</van-button>
@@ -97,7 +98,7 @@ layout("/layouts/platform_h5.html"){
formData: {},
showApprovalForm: false,
rules: {
approvalSignature: [{required: true, message: "请签字"}]
tf_signature: [{required: true, message: "请签字"}]
}
}
},
@@ -283,17 +283,18 @@ layout("/layouts/platform_h5.html"){
</van-cell-group>
<van-cell-group title="提案内容" class="form-group">
<!--<van-field
v-model="formData.researchFindings"
name="researchFindings"
label="调研情况"
type="textarea"
rows="4"
autosize
placeholder="请输入调研情况"
:rules="[{ required: true, message: '请填写调研情况' }]"
<van-field
v-model="formData.excerpt"
name="excerpt"
label="提案概要"
placeholder="请输入提案概要"
:rules="[{ required: true, message: '请填写提案概要' }]"
required
></van-field>-->
type="textarea"
rows="2"
maxlength="20"
show-word-limit
></van-field>
<van-field
v-model="formData.brief"