Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/yudao-cloud
commit
ab188daa00
|
@ -1,5 +1,6 @@
|
|||
package cn.iocoder.yudao.framework.tenant.config;
|
||||
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
|
||||
import cn.iocoder.yudao.framework.redis.config.YudaoCacheProperties;
|
||||
|
@ -60,6 +61,13 @@ public class YudaoTenantAutoConfiguration {
|
|||
|
||||
@Bean
|
||||
public TenantFrameworkService tenantFrameworkService(TenantApi tenantApi) {
|
||||
// 参见 https://gitee.com/zhijiantianya/yudao-cloud/issues/IC6YZF
|
||||
try {
|
||||
TenantApi tenantApiImpl = SpringUtil.getBean("tenantApiImpl", TenantApi.class);
|
||||
if (tenantApiImpl != null) {
|
||||
tenantApi = tenantApiImpl;
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
return new TenantFrameworkServiceImpl(tenantApi);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ import cn.hutool.core.util.ArrayUtil;
|
|||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.github.yulichang.toolkit.MPJWrappers;
|
||||
import com.github.yulichang.wrapper.MPJLambdaWrapper;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
@ -15,94 +14,94 @@ import java.util.function.Consumer;
|
|||
* 拓展 MyBatis Plus Join QueryWrapper 类,主要增加如下功能:
|
||||
* <p>
|
||||
* 1. 拼接条件的方法,增加 xxxIfPresent 方法,用于判断值不存在的时候,不要拼接到条件中。
|
||||
*
|
||||
* 2. SFunction<S, ?> column + <S> 泛型:支持任意类字段(主表、子表、三表),推荐写法, 让编译器自动推断 S 类型
|
||||
* @param <T> 数据类型
|
||||
*/
|
||||
public class MPJLambdaWrapperX<T> extends MPJLambdaWrapper<T> {
|
||||
|
||||
public <R> MPJLambdaWrapperX<T> likeIfPresent(SFunction<R, ?> column, String val) {
|
||||
MPJWrappers.lambdaJoin().like(column, val);
|
||||
public <S> MPJLambdaWrapperX<T> likeIfPresent(SFunction<S, ?> column, String val) {
|
||||
if (StringUtils.hasText(val)) {
|
||||
return (MPJLambdaWrapperX<T>) super.like(column, val);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public <R> MPJLambdaWrapperX<T> inIfPresent(SFunction<R, ?> column, Collection<?> values) {
|
||||
public <S> MPJLambdaWrapperX<T> inIfPresent(SFunction<S, ?> column, Collection<?> values) {
|
||||
if (ObjectUtil.isAllNotEmpty(values) && !ArrayUtil.isEmpty(values)) {
|
||||
return (MPJLambdaWrapperX<T>) super.in(column, values);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public <R> MPJLambdaWrapperX<T> inIfPresent(SFunction<R, ?> column, Object... values) {
|
||||
public <S> MPJLambdaWrapperX<T> inIfPresent(SFunction<S, ?> column, Object... values) {
|
||||
if (ObjectUtil.isAllNotEmpty(values) && !ArrayUtil.isEmpty(values)) {
|
||||
return (MPJLambdaWrapperX<T>) super.in(column, values);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public <R> MPJLambdaWrapperX<T> eqIfPresent(SFunction<R, ?> column, Object val) {
|
||||
public <S> MPJLambdaWrapperX<T> eqIfPresent(SFunction<S, ?> column, Object val) {
|
||||
if (ObjectUtil.isNotEmpty(val)) {
|
||||
return (MPJLambdaWrapperX<T>) super.eq(column, val);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public <R> MPJLambdaWrapperX<T> neIfPresent(SFunction<R, ?> column, Object val) {
|
||||
public <S> MPJLambdaWrapperX<T> neIfPresent(SFunction<S, ?> column, Object val) {
|
||||
if (ObjectUtil.isNotEmpty(val)) {
|
||||
return (MPJLambdaWrapperX<T>) super.ne(column, val);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public <R> MPJLambdaWrapperX<T> gtIfPresent(SFunction<R, ?> column, Object val) {
|
||||
public <S> MPJLambdaWrapperX<T> gtIfPresent(SFunction<S, ?> column, Object val) {
|
||||
if (val != null) {
|
||||
return (MPJLambdaWrapperX<T>) super.gt(column, val);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public <R> MPJLambdaWrapperX<T> geIfPresent(SFunction<R, ?> column, Object val) {
|
||||
public <S> MPJLambdaWrapperX<T> geIfPresent(SFunction<S, ?> column, Object val) {
|
||||
if (val != null) {
|
||||
return (MPJLambdaWrapperX<T>) super.ge(column, val);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public <R> MPJLambdaWrapperX<T> ltIfPresent(SFunction<R, ?> column, Object val) {
|
||||
public <S> MPJLambdaWrapperX<T> ltIfPresent(SFunction<S, ?> column, Object val) {
|
||||
if (val != null) {
|
||||
return (MPJLambdaWrapperX<T>) super.lt(column, val);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public <R> MPJLambdaWrapperX<T> leIfPresent(SFunction<R, ?> column, Object val) {
|
||||
public <S> MPJLambdaWrapperX<T> leIfPresent(SFunction<S, ?> column, Object val) {
|
||||
if (val != null) {
|
||||
return (MPJLambdaWrapperX<T>) super.le(column, val);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public <R> MPJLambdaWrapperX<T> betweenIfPresent(SFunction<R, ?> column, Object val1, Object val2) {
|
||||
if (val1 != null && val2 != null) {
|
||||
return (MPJLambdaWrapperX<T>) super.between(column, val1, val2);
|
||||
}
|
||||
if (val1 != null) {
|
||||
return (MPJLambdaWrapperX<T>) ge(column, val1);
|
||||
}
|
||||
if (val2 != null) {
|
||||
return (MPJLambdaWrapperX<T>) le(column, val2);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public <R> MPJLambdaWrapperX<T> betweenIfPresent(SFunction<R, ?> column, Object[] values) {
|
||||
public <S> MPJLambdaWrapperX<T> betweenIfPresent(SFunction<S, ?> column, Object[] values) {
|
||||
Object val1 = ArrayUtils.get(values, 0);
|
||||
Object val2 = ArrayUtils.get(values, 1);
|
||||
return betweenIfPresent(column, val1, val2);
|
||||
}
|
||||
|
||||
public <S> MPJLambdaWrapperX<T> betweenIfPresent(SFunction<S, ?> column, Object val1, Object val2) {
|
||||
if (val1 != null && val2 != null) {
|
||||
return (MPJLambdaWrapperX<T>) super.between(column, val1, val2);
|
||||
}
|
||||
if (val1 != null) {
|
||||
return (MPJLambdaWrapperX<T>) super.ge(column, val1);
|
||||
}
|
||||
if (val2 != null) {
|
||||
return (MPJLambdaWrapperX<T>) super.le(column, val2);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
// ========== 重写父类方法,方便链式调用 ==========
|
||||
|
||||
@Override
|
||||
|
@ -310,4 +309,41 @@ public class MPJLambdaWrapperX<T> extends MPJLambdaWrapper<T> {
|
|||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
// ========== 关键重写:使 leftJoin 返回当前类型 this ==========
|
||||
@Override
|
||||
public <A, B> MPJLambdaWrapperX<T> leftJoin(Class<A> clazz, SFunction<A, ?> left, SFunction<B, ?> right) {
|
||||
super.leftJoin(clazz, left, right);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <A, B> MPJLambdaWrapperX<T> rightJoin(Class<A> clazz, SFunction<A, ?> left, SFunction<B, ?> right) {
|
||||
super.rightJoin(clazz, left, right);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <A, B> MPJLambdaWrapperX<T> innerJoin(Class<A> clazz, SFunction<A, ?> left, SFunction<B, ?> right) {
|
||||
super.innerJoin(clazz, left, right);
|
||||
return this;
|
||||
}
|
||||
|
||||
// ========== 添加扩展 Join 支持 ext 函数式参数 ==========
|
||||
public <A, B> MPJLambdaWrapperX<T> leftJoin(Class<A> clazz, SFunction<A, ?> left, SFunction<B, ?> right, Consumer<MPJLambdaWrapperX<T>> ext) {
|
||||
super.leftJoin(clazz, left, right);
|
||||
if (ext != null) ext.accept(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
public <A, B> MPJLambdaWrapperX<T> rightJoin(Class<A> clazz, SFunction<A, ?> left, SFunction<B, ?> right, Consumer<MPJLambdaWrapperX<T>> ext) {
|
||||
super.rightJoin(clazz, left, right);
|
||||
if (ext != null) ext.accept(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
public <A, B> MPJLambdaWrapperX<T> innerJoin(Class<A> clazz, SFunction<A, ?> left, SFunction<B, ?> right, Consumer<MPJLambdaWrapperX<T>> ext) {
|
||||
super.innerJoin(clazz, left, right);
|
||||
if (ext != null) ext.accept(this);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,7 +64,6 @@ public class AiUtils {
|
|||
return OpenAiChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens)
|
||||
.toolNames(toolNames).toolContext(toolContext).build();
|
||||
case AZURE_OPENAI:
|
||||
// TODO 芋艿:貌似没 model 字段???!
|
||||
return AzureOpenAiChatOptions.builder().deploymentName(model).temperature(temperature).maxTokens(maxTokens)
|
||||
.toolNames(toolNames).toolContext(toolContext).build();
|
||||
case OLLAMA:
|
||||
|
|
|
@ -5,6 +5,7 @@ import cn.hutool.core.map.MapUtil;
|
|||
import cn.iocoder.yudao.framework.common.core.KeyValue;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.base.user.UserSimpleBaseVO;
|
||||
|
@ -53,6 +54,7 @@ public interface BpmTaskConvert {
|
|||
taskVO.setProcessInstance(BeanUtils.toBean(processInstance, BpmTaskRespVO.ProcessInstance.class));
|
||||
AdminUserRespDTO startUser = userMap.get(NumberUtils.parseLong(processInstance.getStartUserId()));
|
||||
taskVO.getProcessInstance().setStartUser(BeanUtils.toBean(startUser, UserSimpleBaseVO.class));
|
||||
taskVO.getProcessInstance().setCreateTime(DateUtils.of(processInstance.getStartTime()));
|
||||
// 摘要
|
||||
taskVO.getProcessInstance().setSummary(FlowableUtils.getSummary(processDefinitionInfoMap.get(processInstance.getProcessDefinitionId()),
|
||||
processInstance.getProcessVariables()));
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.flowable.bpmn.model.UserTask;
|
|||
import org.flowable.engine.delegate.DelegateExecution;
|
||||
import org.flowable.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior;
|
||||
import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
@ -82,4 +83,13 @@ public class BpmSequentialMultiInstanceBehavior extends SequentialMultiInstanceB
|
|||
return super.resolveNrOfInstances(execution);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void executeOriginalBehavior(DelegateExecution execution, ExecutionEntity multiInstanceRootExecution, int loopCounter) {
|
||||
// 参见 https://gitee.com/zhijiantianya/yudao-cloud/issues/IC239F
|
||||
super.collectionExpression = null;
|
||||
super.collectionVariable = FlowableUtils.formatExecutionCollectionVariable(execution.getCurrentActivityId());
|
||||
super.collectionElementVariable = FlowableUtils.formatExecutionCollectionElementVariable(execution.getCurrentActivityId());
|
||||
super.executeOriginalBehavior(execution, multiInstanceRootExecution, loopCounter);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -597,6 +597,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
* @param nextAssignees 下一个节点审批人集合(参数)
|
||||
* @param processInstance 流程实例
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String, Object> validateAndSetNextAssignees(String taskDefinitionKey, Map<String, Object> variables, BpmnModel bpmnModel,
|
||||
Map<String, List<Long>> nextAssignees, ProcessInstance processInstance) {
|
||||
// simple 设计器第一个节点默认为发起人节点,不校验是否存在审批人
|
||||
|
@ -646,6 +647,11 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
approveUserSelectAssignees = new HashMap<>();
|
||||
}
|
||||
approveUserSelectAssignees.put(nextFlowNode.getId(), assignees);
|
||||
Map<String,List<Long>> existingApproveUserSelectAssignees = (Map<String,List<Long>>) variables.get(
|
||||
BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_APPROVE_USER_SELECT_ASSIGNEES);
|
||||
if (CollUtil.isNotEmpty(existingApproveUserSelectAssignees)) {
|
||||
approveUserSelectAssignees.putAll(existingApproveUserSelectAssignees);
|
||||
}
|
||||
variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_APPROVE_USER_SELECT_ASSIGNEES, approveUserSelectAssignees);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -214,7 +214,7 @@ public class CrmContactServiceImpl implements CrmContactService {
|
|||
}
|
||||
}
|
||||
|
||||
@LogRecord(type = CRM_CONTACT_TYPE, subType = CRM_CONTACT_UPDATE_OWNER_USER_SUB_TYPE, bizNo = "{{#contact.id}",
|
||||
@LogRecord(type = CRM_CONTACT_TYPE, subType = CRM_CONTACT_UPDATE_OWNER_USER_SUB_TYPE, bizNo = "{{#contact.id}}",
|
||||
success = CRM_CONTACT_UPDATE_OWNER_USER_SUCCESS)
|
||||
public void receiveContactLog(CrmContactDO contact, Long ownerUserId) {
|
||||
// 记录操作日志上下文
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts" setup>
|
||||
import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
|
||||
import type { VxeTableInstance } from 'vxe-table';
|
||||
import type { VxeTableInstance } from '#/adapter/vxe-table';
|
||||
|
||||
import { Page, useVbenModal } from '@vben/common-ui';
|
||||
import { cloneDeep, formatDateTime } from '@vben/utils';
|
||||
|
@ -9,9 +9,10 @@ import { DictTag } from '#/components/dict-tag';
|
|||
import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
|
||||
import ${simpleClassName}Form from './modules/form.vue';
|
||||
import { Download, Plus, RefreshCw, Search } from '@vben/icons';
|
||||
import { ContentWrap } from "#/components/content-wrap";
|
||||
import { VxeColumn, VxeTable } from 'vxe-table';
|
||||
import { ContentWrap } from '#/components/content-wrap';
|
||||
import { VxeColumn, VxeTable } from '#/adapter/vxe-table';
|
||||
import { TableToolbar } from '#/components/table-toolbar';
|
||||
import { useTableToolbar } from '#/hooks';
|
||||
|
||||
## 特殊:主子表专属逻辑
|
||||
#if ( $table.templateType == 11 || $table.templateType == 12 )
|
||||
|
@ -167,11 +168,6 @@ try {
|
|||
}
|
||||
}
|
||||
|
||||
/** 隐藏搜索栏 */
|
||||
const hiddenSearchBar = ref(false);
|
||||
const tableToolbarRef = ref<InstanceType<typeof TableToolbar>>();
|
||||
const tableRef = ref<VxeTableInstance>();
|
||||
|
||||
#if (${table.templateType} == 2)
|
||||
/** 切换树形展开/收缩状态 */
|
||||
const isExpanded = ref(true);
|
||||
|
@ -182,15 +178,9 @@ function toggleExpand() {
|
|||
#end
|
||||
|
||||
/** 初始化 */
|
||||
onMounted(async () => {
|
||||
await getList();
|
||||
await nextTick();
|
||||
// 挂载 toolbar 工具栏
|
||||
const table = tableRef.value;
|
||||
const tableToolbar = tableToolbarRef.value;
|
||||
if (table && tableToolbar) {
|
||||
await table.connect(tableToolbar.getToolbarRef()!);
|
||||
}
|
||||
const { hiddenSearchBar, tableToolbarRef, tableRef } = useTableToolbar();
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
import { DICT_TYPE, getDictOptions } from '#/utils';
|
||||
|
||||
#if ($subTable.subJoinMany) ## 一对多
|
||||
import type { VxeTableInstance } from 'vxe-table';
|
||||
import type { VxeTableInstance } from '#/adapter/vxe-table';
|
||||
import { Plus } from "@vben/icons";
|
||||
import { VxeColumn, VxeTable } from 'vxe-table';
|
||||
import { VxeColumn, VxeTable } from '#/adapter/vxe-table';
|
||||
import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
|
||||
#else
|
||||
import type { Rule } from 'ant-design-vue/es/form';
|
||||
|
|
|
@ -7,14 +7,14 @@
|
|||
#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
|
||||
<script lang="ts" setup>
|
||||
import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
|
||||
import type { VxeTableInstance } from 'vxe-table';
|
||||
import type { VxeTableInstance } from '#/adapter/vxe-table';
|
||||
|
||||
import { DictTag } from '#/components/dict-tag';
|
||||
import { DICT_TYPE, getDictOptions } from '#/utils';
|
||||
import { VxeColumn, VxeTable } from 'vxe-table';
|
||||
import { VxeColumn, VxeTable } from '#/adapter/vxe-table';
|
||||
import { reactive,ref, h, nextTick,watch,onMounted } from 'vue';
|
||||
import { cloneDeep, formatDateTime } from '@vben/utils';
|
||||
import { ContentWrap } from "#/components/content-wrap";
|
||||
import { ContentWrap } from '#/components/content-wrap';
|
||||
|
||||
#if ($table.templateType == 11) ## erp
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
|
@ -26,6 +26,7 @@
|
|||
import { Plus } from '@vben/icons';
|
||||
import { $t } from '#/locales';
|
||||
import { TableToolbar } from '#/components/table-toolbar';
|
||||
import { useTableToolbar } from '#/hooks';
|
||||
#end
|
||||
|
||||
#if ($table.templateType == 11) ## erp
|
||||
|
@ -165,21 +166,10 @@ const resetQuery = () => {
|
|||
);
|
||||
|
||||
#if ($table.templateType == 11) ## erp
|
||||
/** 隐藏搜索栏 */
|
||||
const hiddenSearchBar = ref(false);
|
||||
const tableToolbarRef = ref<InstanceType<typeof TableToolbar>>();
|
||||
const tableRef = ref<VxeTableInstance>();
|
||||
|
||||
/** 初始化 */
|
||||
onMounted(async () => {
|
||||
await getList();
|
||||
await nextTick();
|
||||
// 挂载 toolbar 工具栏
|
||||
const table = tableRef.value;
|
||||
const tableToolbar = tableToolbarRef.value;
|
||||
if (table && tableToolbar) {
|
||||
await table.connect(tableToolbar.getToolbarRef()!);
|
||||
}
|
||||
const { hiddenSearchBar, tableToolbarRef, tableRef } = useTableToolbar();
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
#end
|
||||
</script>
|
||||
|
|
|
@ -92,6 +92,7 @@ public class KeFuMessageServiceImpl implements KeFuMessageService {
|
|||
MemberUserRespDTO user = memberUserApi.getUser(kefuMessage.getSenderId()).getCheckedData();
|
||||
KeFuMessageRespVO message = BeanUtils.toBean(kefuMessage, KeFuMessageRespVO.class).setSenderAvatar(user.getAvatar());
|
||||
getSelf().sendAsyncMessageToAdmin(KEFU_MESSAGE_TYPE, message);
|
||||
getSelf().sendAsyncMessageToMember(conversation.getUserId(), KEFU_MESSAGE_TYPE, message);
|
||||
return kefuMessage.getId();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue