MES审批复用钉钉审批设置

This commit is contained in:
geht
2026-06-10 16:57:07 +08:00
parent 617d47a3db
commit 5cb24c582d
4 changed files with 115 additions and 24 deletions

View File

@@ -944,6 +944,11 @@ jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules
jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslMixingSpecServiceImpl.java jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslMixingSpecServiceImpl.java
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingSpecModal.vue jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingSpecModal.vue
-- author:GHT---date:20260610--for: 【IM审批通用化】MES发起审批按钮按ding_tpl_bind路由匹配(与钉钉按钮一致) -----
jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/approval/controller/MesXslApprovalLaunchController.java
jeecgboot-vue3/src/components/ApprovalLaunch/index.vue
jeecgboot-vue3/src/views/approval/flow/launch.api.ts
-- author:GHT---date:20260610--for: 【IM审批通用化】IM工作通知公众号(同事列表置顶+审批消息统一推送) ----- -- author:GHT---date:20260610--for: 【IM审批通用化】IM工作通知公众号(同事列表置顶+审批消息统一推送) -----
jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_147__sys_im_work_notify_user.sql jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_147__sys_im_work_notify_user.sql
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/im/service/impl/SysImChatServiceImpl.java jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/im/service/impl/SysImChatServiceImpl.java

View File

@@ -16,11 +16,13 @@ import org.jeecg.modules.xslmes.approval.service.IMesXslApprovalHandleService;
import org.jeecg.modules.xslmes.approval.service.IMesXslApprovalInstanceService; import org.jeecg.modules.xslmes.approval.service.IMesXslApprovalInstanceService;
import org.jeecg.modules.xslmes.approval.vo.ApprovalGateVo; import org.jeecg.modules.xslmes.approval.vo.ApprovalGateVo;
import org.jeecg.modules.xslmes.common.MesXslTenantUtils; import org.jeecg.modules.xslmes.common.MesXslTenantUtils;
import org.jeecg.modules.xslmes.dingtalk.service.IMesXslDingTplBindService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -61,19 +63,37 @@ public class MesXslApprovalLaunchController {
@Autowired @Autowired
private JdbcTemplate jdbcTemplate; private JdbcTemplate jdbcTemplate;
//update-begin---author:GHT ---date:20260610 for【IM审批通用化】MES发起按钮与钉钉绑定同路由匹配-----------
@Autowired
private IMesXslDingTplBindService dingTplBindService;
//update-end---author:GHT ---date:20260610 for【IM审批通用化】MES发起按钮与钉钉绑定同路由匹配-----------
/** /**
* 已发布审批流列表(按租户隔离),即"可发起的单据类型"。 * 已发布审批流列表(按租户隔离),即"可发起的单据类型"。
* 同时按"功能模块(单据表)"自动反查其菜单路由填入 routePath供前端控制悬浮按钮仅在该功能页显示无需手工配置 * routePath 有值时:与钉钉审批按钮一致,先按 mes_xsl_ding_tpl_bind 解析当前页绑定,再返回该页业务表下已发布审批流
*/ */
@Operation(summary = "发起审批-已发布审批流列表") @Operation(summary = "发起审批-已发布审批流列表")
@GetMapping("/publishedList") @GetMapping("/publishedList")
public Result<List<MesXslApprovalFlow>> publishedList() { public Result<List<MesXslApprovalFlow>> publishedList(
@RequestParam(name = "routePath", required = false) String routePath) {
QueryWrapper<MesXslApprovalFlow> qw = new QueryWrapper<>(); QueryWrapper<MesXslApprovalFlow> qw = new QueryWrapper<>();
qw.eq("status", "1"); qw.eq("status", "1");
Integer tenantId = MesXslTenantUtils.resolveTenantId(null); Integer tenantId = MesXslTenantUtils.resolveTenantId(null);
if (tenantId != null) { if (tenantId != null) {
qw.eq("tenant_id", tenantId); qw.eq("tenant_id", tenantId);
} }
//update-begin---author:GHT ---date:20260610 for【IM审批通用化】MES发起按钮与钉钉绑定同路由匹配-----------
if (oConvertUtils.isNotEmpty(routePath)) {
if (dingTplBindService.resolveActiveByRoutePath(routePath.trim()) == null) {
return Result.OK(Collections.emptyList());
}
String bizTable = resolveTableByRoutePath(routePath);
if (oConvertUtils.isEmpty(bizTable) || !IDENTIFIER.matcher(bizTable).matches()) {
return Result.OK(Collections.emptyList());
}
qw.eq("biz_table", bizTable);
}
//update-end---author:GHT ---date:20260610 for【IM审批通用化】MES发起按钮与钉钉绑定同路由匹配-----------
qw.orderByDesc("create_time"); qw.orderByDesc("create_time");
List<MesXslApprovalFlow> list = approvalFlowService.list(qw); List<MesXslApprovalFlow> list = approvalFlowService.list(qw);
// 未手工指定 route_path 时,按单据表名自动反查菜单路由 // 未手工指定 route_path 时,按单据表名自动反查菜单路由
@@ -90,6 +110,59 @@ public class MesXslApprovalLaunchController {
* 约定jeecg 代码生成的列表组件名为 表名驼峰 + List如 mes_xsl_formula_spec -> MesXslFormulaSpecList * 约定jeecg 代码生成的列表组件名为 表名驼峰 + List如 mes_xsl_formula_spec -> MesXslFormulaSpecList
* 对应 sys_permission.component 形如 xslmes/mesXslFormulaSpec/MesXslFormulaSpecList取其 url 即路由。 * 对应 sys_permission.component 形如 xslmes/mesXslFormulaSpec/MesXslFormulaSpecList取其 url 即路由。
*/ */
//update-begin---author:GHT ---date:20260610 for【IM审批通用化】按前端路由反查业务表(与钉钉绑定路由解析一致)-----------
private String resolveTableByRoutePath(String routePath) {
if (oConvertUtils.isEmpty(routePath)) {
return null;
}
String component = resolveComponentByRoutePath(routePath);
if (oConvertUtils.isEmpty(component)) {
return null;
}
String comp = component.contains("/") ? component.substring(component.lastIndexOf('/') + 1) : component;
if (comp.endsWith("List")) {
comp = comp.substring(0, comp.length() - "List".length());
}
return camelToUnderline(comp);
}
private String resolveComponentByRoutePath(String routePath) {
if (oConvertUtils.isEmpty(routePath)) {
return null;
}
String path = routePath.trim().replaceAll("/+$", "");
String sql = "SELECT component FROM sys_permission WHERE menu_type IN (0,1) "
+ "AND (del_flag = 0 OR del_flag IS NULL) AND url = ? "
+ "ORDER BY menu_type DESC LIMIT 1";
try {
List<String> list = jdbcTemplate.queryForList(sql, String.class, path);
return list.isEmpty() ? null : list.get(0);
} catch (Exception e) {
log.warn("反查菜单组件失败 routePath={}", routePath, e);
return null;
}
}
private String camelToUnderline(String camel) {
if (oConvertUtils.isEmpty(camel)) {
return null;
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < camel.length(); i++) {
char c = camel.charAt(i);
if (Character.isUpperCase(c)) {
if (i > 0) {
sb.append('_');
}
sb.append(Character.toLowerCase(c));
} else {
sb.append(c);
}
}
return sb.toString();
}
//update-end---author:GHT ---date:20260610 for【IM审批通用化】按前端路由反查业务表(与钉钉绑定路由解析一致)-----------
private String resolveRoutePathByTable(String table) { private String resolveRoutePathByTable(String table) {
if (oConvertUtils.isEmpty(table) || !IDENTIFIER.matcher(table).matches()) { if (oConvertUtils.isEmpty(table) || !IDENTIFIER.matcher(table).matches()) {
return null; return null;

View File

@@ -1,6 +1,7 @@
<!-- <!--
全局发起审批悬浮按钮 全局发起审批悬浮按钮
仅在设计并发布了审批且能匹配到对应功能页路由的页面显示 钉钉审批按钮一致当前页存在 mes_xsl_ding_tpl_bind 绑定且钉钉模板启用时显示
弹窗内可选该页业务表下已发布的 MES 审批流
支持两种发起方式 支持两种发起方式
1列表多选联动在列表勾选数据后点击弹窗自动带入选中单据并可批量发起 1列表多选联动在列表勾选数据后点击弹窗自动带入选中单据并可批量发起
2手动选择未勾选时在弹窗内搜索选择单条单据发起 2手动选择未勾选时在弹窗内搜索选择单条单据发起
@@ -57,11 +58,12 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { computed, onMounted, reactive, ref } from 'vue'; import { computed, reactive, ref, watch } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { debounce } from 'lodash-es'; import { debounce } from 'lodash-es';
import { useMessage } from '/@/hooks/web/useMessage'; import { useMessage } from '/@/hooks/web/useMessage';
import { getPublishedFlows, getBizRecords, launchApproval, launchApprovalBatch } from '/@/views/approval/flow/launch.api'; import { getPublishedFlows, getBizRecords, launchApproval, launchApprovalBatch } from '/@/views/approval/flow/launch.api';
import { getBindingByRoute } from '/@/views/xslmes/dingtalk/dingTplBind/dingTplBind.api';
import { useApprovalSelection } from './useApprovalSelection'; import { useApprovalSelection } from './useApprovalSelection';
defineOptions({ name: 'ApprovalLaunchFloat' }); defineOptions({ name: 'ApprovalLaunchFloat' });
@@ -78,6 +80,7 @@
const bizDataId = ref<string>(); const bizDataId = ref<string>();
const bizTitle = ref<string>(''); const bizTitle = ref<string>('');
const binding = ref<any>(null);
const flowList = ref<any[]>([]); const flowList = ref<any[]>([]);
const recordList = ref<any[]>([]); const recordList = ref<any[]>([]);
// 打开弹窗时快照的列表勾选行(批量模式数据源) // 打开弹窗时快照的列表勾选行(批量模式数据源)
@@ -86,18 +89,10 @@
// 悬浮位置(右下角) // 悬浮位置(右下角)
const floatStyle = reactive({ right: '24px', bottom: '120px' }); const floatStyle = reactive({ right: '24px', bottom: '120px' });
function normalizePath(p?: string) { // 与钉钉审批按钮一致:按 mes_xsl_ding_tpl_bind + 路由解析是否显示
return (p || '').trim().replace(/\/+$/, ''); const show = computed(() => !!binding.value);
}
// 当前路由匹配到的已发布审批流 const matchedFlows = computed(() => flowList.value);
const matchedFlows = computed(() => {
const cur = normalizePath(currentRoute.value?.path);
if (!cur) return [];
return flowList.value.filter((f) => f.routePath && normalizePath(f.routePath) === cur);
});
const show = computed(() => matchedFlows.value.length > 0);
const flowOptions = computed(() => const flowOptions = computed(() =>
matchedFlows.value.map((f) => ({ matchedFlows.value.map((f) => ({
@@ -130,15 +125,27 @@
})) }))
); );
onMounted(loadFlows); watch(
() => currentRoute.value?.path,
async function loadFlows() { async (path) => {
binding.value = null;
flowList.value = [];
if (!path || path === '/' || path.startsWith('/login')) {
return;
}
try { try {
flowList.value = (await getPublishedFlows()) || []; const bind = await getBindingByRoute(path);
binding.value = bind || null;
if (binding.value) {
flowList.value = (await getPublishedFlows(path)) || [];
}
} catch { } catch {
binding.value = null;
flowList.value = []; flowList.value = [];
} }
} },
{ immediate: true },
);
function resetSelection() { function resetSelection() {
flowId.value = undefined; flowId.value = undefined;
@@ -149,6 +156,10 @@
} }
async function openModal() { async function openModal() {
if (!matchedFlows.value.length) {
createMessage.warning('当前页面暂无已发布的 MES 审批流,请先在审批流设计中发布');
return;
}
visible.value = true; visible.value = true;
resetSelection(); resetSelection();
// 读取当前列表页的勾选行 // 读取当前列表页的勾选行

View File

@@ -14,8 +14,10 @@ enum Api {
/** /**
* 已发布审批流列表(可发起的单据类型) * 已发布审批流列表(可发起的单据类型)
* @param routePath 当前功能页路由;传入时与钉钉审批按钮一致,按 mes_xsl_ding_tpl_bind 绑定页过滤
*/ */
export const getPublishedFlows = () => defHttp.get({ url: Api.publishedList }); export const getPublishedFlows = (routePath?: string) =>
defHttp.get({ url: Api.publishedList, params: routePath ? { routePath } : undefined });
/** /**
* 根据审批流查询其绑定单据的记录列表 * 根据审批流查询其绑定单据的记录列表