This commit is contained in:
jack ning
2025-03-28 17:15:08 +08:00
parent cafa25718e
commit cfde013ac1
37 changed files with 2158 additions and 2145 deletions

View File

@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-05-11 18:22:04
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-03-11 09:27:26
* @LastEditTime: 2025-03-28 17:06:13
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -70,9 +70,7 @@ public class CategoryRestService extends BaseRestService<CategoryEntity, Categor
@Override
public Page<CategoryResponse> queryByOrg(CategoryRequest request) {
Pageable pageable = PageRequest.of(request.getPageNumber(), request.getPageSize(), Sort.Direction.ASC,
"updatedAt");
Pageable pageable = request.getPageable();
Specification<CategoryEntity> specs = CategorySpecification.search(request);
Page<CategoryEntity> page = categoryRepository.findAll(specs, pageable);
return page.map(this::convertToResponse);
@@ -117,7 +115,6 @@ public class CategoryRestService extends BaseRestService<CategoryEntity, Categor
return categoryRepository.findByKbUidAndDeletedFalse(kbUid);
}
public Boolean existsByUid(String uid) {
return categoryRepository.existsByUid(uid);
}

View File

@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-06-08 14:43:05
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-03-11 08:41:22
* @LastEditTime: 2025-03-28 17:03:58
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -23,5 +23,6 @@ public enum CategoryTypeEnum {
BLOG,
EMAIL,
TABOO,
TICKET
TICKET,
FAQ
}

View File

@@ -54,7 +54,13 @@ public class BdDateUtils {
return null;
}
// 使用 DateTimeFormatter 直接格式化 LocalDateTime
return localDateTime.format(DateTimeFormatter.ofPattern(datetimeFormat));
// return localDateTime.format(DateTimeFormatter.ofPattern(datetimeFormat));
// 使用应用配置的时区
// ZonedDateTime zonedDateTime = localDateTime.atZone(LocaleContextHolder.getTimeZone().toZoneId());
// 或者固定使用中国时区
ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.of("Asia/Shanghai"));
return DateTimeFormatter.ofPattern(datetimeFormat).format(zonedDateTime);
// 或者如果一定要使用 SimpleDateFormat可以这样转换
// try {

View File

@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-01 17:20:46
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-03-24 18:26:28
* @LastEditTime: 2025-03-28 14:22:30
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -168,8 +168,6 @@ public class ConvertUtils {
messageResponse.setExtra(extra);
}
return messageResponse;
}

View File

@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-11-22 16:07:49
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2024-11-22 16:20:52
* @LastEditTime: 2025-03-28 16:22:47
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -16,9 +16,9 @@ package com.bytedesk.kbase.faq;
public class FaqConsts {
private FaqConsts() {}
public static final String FAQ_CATEGORY_DEMO_UID_1 = "faq_category_demo_uid_1";
public static final String FAQ_CATEGORY_DEMO_UID_2 = "faq_category_demo_uid_2";
//
public static final String FAQ_DEMO_UID_1 = "faq_demo_uid_1";
public static final String FAQ_DEMO_UID_2 = "faq_demo_uid_2";
// public static final String FAQ_CATEGORY_DEMO_UID_1 = "faq_category_demo_uid_1";
// public static final String FAQ_CATEGORY_DEMO_UID_2 = "faq_category_demo_uid_2";
// //
// public static final String FAQ_DEMO_UID_1 = "faq_demo_uid_1";
// public static final String FAQ_DEMO_UID_2 = "faq_demo_uid_2";
}

View File

@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-03-22 22:59:18
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-03-18 15:37:05
* @LastEditTime: 2025-03-28 17:03:24
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -348,10 +348,12 @@ public class FaqRestService extends BaseRestService<FaqEntity, FaqRequest, FaqRe
// create category
CategoryRequest categoryRequest = CategoryRequest.builder()
.name(excel.getCategory())
.type(CategoryTypeEnum.FAQ.name())
.kbUid(kbUid)
.orgUid(orgUid)
.build();
categoryRequest.setType(CategoryTypeEnum.LLM.name());
categoryRequest.setOrgUid(orgUid);
// categoryRequest.setType(CategoryTypeEnum.FAQ.name());
// categoryRequest.setOrgUid(orgUid);
//
CategoryResponse categoryResponse = categoryService.create(categoryRequest);
faq.setCategoryUid(categoryResponse.getUid());

View File

@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-06-12 07:20:15
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-02-26 12:56:15
* @LastEditTime: 2025-03-28 16:22:30
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -14,7 +14,6 @@
package com.bytedesk.service.workgroup;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
@@ -27,8 +26,6 @@ import com.bytedesk.core.rbac.organization.OrganizationEntity;
import com.bytedesk.core.rbac.organization.event.OrganizationCreateEvent;
import com.bytedesk.core.rbac.user.UserEntity;
import com.bytedesk.core.uid.UidUtils;
import com.bytedesk.core.utils.Utils;
import com.bytedesk.kbase.faq.FaqConsts;
import com.bytedesk.service.agent.AgentEntity;
import com.bytedesk.service.agent.AgentRestService;
import com.bytedesk.service.worktime.WorktimeService;
@@ -64,10 +61,10 @@ public class WorkgroupEventListener {
agentUids.add(agent.getUid());
});
//
List<String> faqUids = Arrays.asList(
Utils.formatUid(orgUid, FaqConsts.FAQ_DEMO_UID_1),
Utils.formatUid(orgUid, FaqConsts.FAQ_DEMO_UID_2)
);
// List<String> faqUids = Arrays.asList(
// Utils.formatUid(orgUid, FaqConsts.FAQ_DEMO_UID_1),
// Utils.formatUid(orgUid, FaqConsts.FAQ_DEMO_UID_2)
// );
//
List<String> worktimeUids = new ArrayList<>();
String worktimeUid = worktimeService.createDefault();
@@ -83,8 +80,8 @@ public class WorkgroupEventListener {
.build();
// workgroupRequest.setUid(uidUtils.getUid());
// workgroupRequest.setOrgUid(orgUid);
workgroupRequest.getServiceSettings().setFaqUids(faqUids);
workgroupRequest.getServiceSettings().setQuickFaqUids(faqUids);
// workgroupRequest.getServiceSettings().setFaqUids(faqUids);
// workgroupRequest.getServiceSettings().setQuickFaqUids(faqUids);
workgroupRequest.getMessageLeaveSettings().setWorktimeUids(worktimeUids);
workgroupService.create(workgroupRequest);

View File

@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2025-02-15 12:39:46
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-02-26 12:57:35
* @LastEditTime: 2025-03-28 16:28:43
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -13,26 +13,12 @@
*/
package com.bytedesk.ticket.process;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Optional;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.Deployment;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;
import com.bytedesk.core.rbac.organization.OrganizationEntity;
import com.bytedesk.core.rbac.organization.event.OrganizationCreateEvent;
import com.bytedesk.core.utils.Utils;
import com.bytedesk.ticket.consts.TicketConsts;
import com.bytedesk.ticket.process.event.TicketProcessCreateEvent;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -41,9 +27,9 @@ import lombok.extern.slf4j.Slf4j;
@RequiredArgsConstructor
public class TicketProcessEventListener {
private final RepositoryService repositoryService;
// private final RepositoryService repositoryService;
private final ResourceLoader resourceLoader;
// private final ResourceLoader resourceLoader;
private final TicketProcessRestService ticketProcessRestService;
@@ -53,66 +39,12 @@ public class TicketProcessEventListener {
OrganizationEntity organization = (OrganizationEntity) event.getSource();
String orgUid = organization.getUid();
log.info("ticket process - organization created: {}", orgUid);
// 检查是否已经部署
List<Deployment> existingDeployments = repositoryService.createDeploymentQuery()
.deploymentTenantId(orgUid)
.deploymentName(TicketConsts.TICKET_PROCESS_NAME_GROUP_SIMPLE)
.list();
if (!existingDeployments.isEmpty()) {
log.info("工单流程已存在,跳过部署: tenantId={}", orgUid);
return;
}
// 读取并部署流程
try {
Resource resource = resourceLoader.getResource("classpath:" + TicketConsts.TICKET_PROCESS_GROUP_PATH_SIMPLE);
// String groupTicketBpmn20Xml = FileUtils.readFileToString(resource.getFile(), "UTF-8");
String groupTicketBpmn20Xml = "";
try (InputStream inputStream = resource.getInputStream()) {
groupTicketBpmn20Xml = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
}
// 生成 processUid 并创建流程记录
String processUid = Utils.formatUid(orgUid, TicketConsts.TICKET_PROCESS_KEY_GROUP_SIMPLE);
TicketProcessRequest processRequest = TicketProcessRequest.builder()
.name(TicketConsts.TICKET_PROCESS_NAME_GROUP_SIMPLE)
.key(TicketConsts.TICKET_PROCESS_KEY_GROUP_SIMPLE)
.description(TicketConsts.TICKET_PROCESS_NAME_GROUP_SIMPLE)
.build();
processRequest.setUid(processUid);
processRequest.setContent(groupTicketBpmn20Xml);
processRequest.setOrgUid(orgUid);
ticketProcessRestService.create(processRequest);
// 部署流程
Deployment deployment = repositoryService.createDeployment()
.name(TicketConsts.TICKET_PROCESS_NAME_GROUP_SIMPLE)
.addClasspathResource(TicketConsts.TICKET_PROCESS_GROUP_PATH_SIMPLE)
.tenantId(orgUid)
.deploy();
// 更新 TicketProcessEntity
Optional<TicketProcessEntity> processEntity = ticketProcessRestService.findByUid(processUid);
if (processEntity.isPresent()) {
processEntity.get().setDeploymentId(deployment.getId());
processEntity.get().setDeployed(true);
ticketProcessRestService.save(processEntity.get());
}
log.info("部署租户流程成功: deploymentId={}, tenantId={}",
deployment.getId(), deployment.getTenantId());
} catch (IOException e) {
log.error("部署工单流程失败: tenantId={}", orgUid, e);
}
ticketProcessRestService.initProcess(orgUid);
}
@EventListener
public void onTicketProcessCreateEvent(TicketProcessCreateEvent event) {
log.info("TicketProcessEventListener onTicketProcessCreateEvent: {}", event);
}
// @EventListener
// public void onTicketProcessCreateEvent(TicketProcessCreateEvent event) {
// log.info("TicketProcessEventListener onTicketProcessCreateEvent: {}", event);
// }
}

View File

@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2025-02-15 13:03:35
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-03-20 11:41:17
* @LastEditTime: 2025-03-28 16:28:29
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -13,24 +13,10 @@
*/
package com.bytedesk.ticket.process;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Optional;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.Deployment;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;
import com.bytedesk.core.rbac.organization.OrganizationEntity;
import com.bytedesk.core.rbac.organization.OrganizationRestService;
import com.bytedesk.core.utils.Utils;
import com.bytedesk.ticket.consts.TicketConsts;
import com.bytedesk.core.constant.BytedeskConsts;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -42,18 +28,22 @@ public class TicketProcessInitializer implements SmartInitializingSingleton {
// private final AuthorityRestService authorityService;
private final OrganizationRestService organizationService;
// private final OrganizationRestService organizationService;
private final TicketProcessRestService ticketProcessRestService;
private final RepositoryService repositoryService;
// private final RepositoryService repositoryService;
private final ResourceLoader resourceLoader;
// private final ResourceLoader resourceLoader;
@Override
public void afterSingletonsInstantiated() {
initAuthority();
initProcess();
// initProcess();
//
String orgUid = BytedeskConsts.DEFAULT_ORGANIZATION_UID;
log.info("ticket process - organization created: {}", orgUid);
ticketProcessRestService.initProcess(orgUid);
}
private void initAuthority() {
@@ -71,66 +61,4 @@ public class TicketProcessInitializer implements SmartInitializingSingleton {
// authorityService.create(authRequest);
// }
}
private void initProcess() {
try {
// 使用 getInputStream() 而不是 getFile()
Resource resource = resourceLoader.getResource("classpath:" + TicketConsts.TICKET_PROCESS_GROUP_PATH_SIMPLE);
String groupTicketBpmn20Xml = "";
try (InputStream inputStream = resource.getInputStream()) {
groupTicketBpmn20Xml = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
}
// 判断所有组织是否存在 TicketProcessEntity
List<OrganizationEntity> organizations = organizationService.findAll();
for (OrganizationEntity organization : organizations) {
String orgUid = organization.getUid();
// 检查是否已经部署
List<Deployment> existingDeployments = repositoryService.createDeploymentQuery()
.deploymentTenantId(orgUid)
.deploymentName(TicketConsts.TICKET_PROCESS_NAME_GROUP)
.list();
if (!existingDeployments.isEmpty()) {
log.info("工单流程已存在,跳过部署: tenantId={}", orgUid);
continue;
}
String processUid = Utils.formatUid(orgUid, TicketConsts.TICKET_PROCESS_KEY_GROUP_SIMPLE);
// 初始化 TicketProcessEntity
TicketProcessRequest processRequest = TicketProcessRequest.builder()
.name(TicketConsts.TICKET_PROCESS_NAME_GROUP_SIMPLE)
.key(TicketConsts.TICKET_PROCESS_KEY_GROUP_SIMPLE)
.description(TicketConsts.TICKET_PROCESS_NAME_GROUP_SIMPLE)
.build();
processRequest.setUid(processUid);
processRequest.setOrgUid(orgUid);
processRequest.setContent(groupTicketBpmn20Xml);
ticketProcessRestService.create(processRequest);
// 部署流程
Deployment deployment = repositoryService.createDeployment()
.name(TicketConsts.TICKET_PROCESS_NAME_GROUP_SIMPLE)
.addClasspathResource(TicketConsts.TICKET_PROCESS_GROUP_PATH_SIMPLE)
.tenantId(orgUid)
.deploy();
// 更新 TicketProcessEntity
Optional<TicketProcessEntity> processEntity = ticketProcessRestService.findByUid(processUid);
if (processEntity.isPresent()) {
processEntity.get().setDeploymentId(deployment.getId());
processEntity.get().setDeployed(true);
ticketProcessRestService.save(processEntity.get());
}
log.info("部署租户流程成功: deploymentId={}, tenantId={}",
deployment.getId(), deployment.getTenantId());
}
} catch (IOException e) {
log.error("读取流程文件失败", e);
throw new RuntimeException("读取流程文件失败: " + e.getMessage());
}
}
}

View File

@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-05-11 18:25:45
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-02-15 14:48:40
* @LastEditTime: 2025-03-28 16:18:36
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -13,14 +13,20 @@
*/
package com.bytedesk.ticket.process;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Optional;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.Deployment;
import org.modelmapper.ModelMapper;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.orm.ObjectOptimisticLockingFailureException;
import org.springframework.stereotype.Service;
@@ -30,6 +36,8 @@ import com.bytedesk.core.base.BaseRestService;
import com.bytedesk.core.rbac.auth.AuthService;
import com.bytedesk.core.rbac.user.UserEntity;
import com.bytedesk.core.uid.UidUtils;
import com.bytedesk.core.utils.Utils;
import com.bytedesk.ticket.consts.TicketConsts;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -37,7 +45,8 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
@AllArgsConstructor
public class TicketProcessRestService extends BaseRestService<TicketProcessEntity, TicketProcessRequest, TicketProcessResponse> {
public class TicketProcessRestService
extends BaseRestService<TicketProcessEntity, TicketProcessRequest, TicketProcessResponse> {
private final TicketProcessRepository processRepository;
@@ -47,10 +56,13 @@ public class TicketProcessRestService extends BaseRestService<TicketProcessEntit
private final AuthService authService;
private final RepositoryService repositoryService;
private final ResourceLoader resourceLoader;
@Override
public Page<TicketProcessResponse> queryByOrg(TicketProcessRequest request) {
Pageable pageable = PageRequest.of(request.getPageNumber(), request.getPageSize(), Sort.Direction.ASC,
"updatedAt");
Pageable pageable = request.getPageable();
Specification<TicketProcessEntity> spec = TicketProcessSpecification.search(request);
Page<TicketProcessEntity> page = processRepository.findAll(spec, pageable);
return page.map(this::convertToResponse);
@@ -65,15 +77,11 @@ public class TicketProcessRestService extends BaseRestService<TicketProcessEntit
}
String userUid = user.getUid();
request.setUserUid(userUid);
//
Pageable pageable = PageRequest.of(request.getPageNumber(), request.getPageSize(), Sort.Direction.ASC,
"updatedAt");
Specification<TicketProcessEntity> spec = TicketProcessSpecification.search(request);
Page<TicketProcessEntity> page = processRepository.findAll(spec, pageable);
return page.map(this::convertToResponse);
//
return queryByOrg(request);
}
@Cacheable(value = "process", key = "#uid", unless="#result==null")
@Cacheable(value = "process", key = "#uid", unless = "#result==null")
@Override
public Optional<TicketProcessEntity> findByUid(String uid) {
return processRepository.findByUid(uid);
@@ -81,7 +89,7 @@ public class TicketProcessRestService extends BaseRestService<TicketProcessEntit
@Override
public TicketProcessResponse create(TicketProcessRequest request) {
// 判断uid是否存在
// 判断uid是否存在
if (StringUtils.hasText(request.getUid())) {
Optional<TicketProcessEntity> optional = processRepository.findByUid(request.getUid());
if (optional.isPresent()) {
@@ -92,9 +100,11 @@ public class TicketProcessRestService extends BaseRestService<TicketProcessEntit
request.setUid(uidUtils.getUid());
}
// 流程key不能重复
Optional<TicketProcessEntity> optionalKey = processRepository.findByKeyAndOrgUid(request.getKey(), request.getOrgUid());
Optional<TicketProcessEntity> optionalKey = processRepository.findByKeyAndOrgUid(request.getKey(),
request.getOrgUid());
if (optionalKey.isPresent()) {
throw new RuntimeException("Process key " + request.getKey() + " in org " + request.getOrgUid() + " already exists");
throw new RuntimeException(
"Process key " + request.getKey() + " in org " + request.getOrgUid() + " already exists");
}
UserEntity user = authService.getUser();
@@ -103,7 +113,7 @@ public class TicketProcessRestService extends BaseRestService<TicketProcessEntit
} else {
// 如果用户为空,则为系统自动创建
}
TicketProcessEntity entity = modelMapper.map(request, TicketProcessEntity.class);
// entity.setUid(uidUtils.getUid()); // 移动到开头
@@ -123,14 +133,13 @@ public class TicketProcessRestService extends BaseRestService<TicketProcessEntit
entity.setName(request.getName());
entity.setContent(request.getContent());
entity.setDescription(request.getDescription());
//
//
TicketProcessEntity savedEntity = save(entity);
if (savedEntity == null) {
throw new RuntimeException("Update process failed");
}
return convertToResponse(savedEntity);
}
else {
} else {
throw new RuntimeException("TicketProcess not found");
}
}
@@ -151,8 +160,7 @@ public class TicketProcessRestService extends BaseRestService<TicketProcessEntit
if (optional.isPresent()) {
optional.get().setDeleted(true);
save(optional.get());
}
else {
} else {
throw new RuntimeException("TicketProcess not found");
}
}
@@ -163,7 +171,8 @@ public class TicketProcessRestService extends BaseRestService<TicketProcessEntit
}
@Override
public void handleOptimisticLockingFailureException(ObjectOptimisticLockingFailureException e, TicketProcessEntity entity) {
public void handleOptimisticLockingFailureException(ObjectOptimisticLockingFailureException e,
TicketProcessEntity entity) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'handleOptimisticLockingFailureException'");
}
@@ -173,5 +182,66 @@ public class TicketProcessRestService extends BaseRestService<TicketProcessEntit
return modelMapper.map(entity, TicketProcessResponse.class);
}
public void initProcess(String orgUid) {
// 检查是否已经部署
List<Deployment> existingDeployments = repositoryService.createDeploymentQuery()
.deploymentTenantId(orgUid)
.deploymentName(TicketConsts.TICKET_PROCESS_NAME_GROUP_SIMPLE)
.list();
if (!existingDeployments.isEmpty()) {
log.info("工单流程已存在,跳过部署: tenantId={}", orgUid);
return;
}
// 读取并部署流程
try {
Resource resource = resourceLoader
.getResource("classpath:" + TicketConsts.TICKET_PROCESS_GROUP_PATH_SIMPLE);
// String groupTicketBpmn20Xml = FileUtils.readFileToString(resource.getFile(),
// "UTF-8");
String groupTicketBpmn20Xml = "";
try (InputStream inputStream = resource.getInputStream()) {
groupTicketBpmn20Xml = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
}
// 生成 processUid 并创建流程记录
String processUid = Utils.formatUid(orgUid, TicketConsts.TICKET_PROCESS_KEY_GROUP_SIMPLE);
TicketProcessRequest processRequest = TicketProcessRequest.builder()
.uid(processUid)
.name(TicketConsts.TICKET_PROCESS_NAME_GROUP_SIMPLE)
.content(groupTicketBpmn20Xml)
.key(TicketConsts.TICKET_PROCESS_KEY_GROUP_SIMPLE)
.description(TicketConsts.TICKET_PROCESS_NAME_GROUP_SIMPLE)
.orgUid(orgUid)
.build();
// processRequest.setUid(processUid);
// processRequest.setContent(groupTicketBpmn20Xml);
// processRequest.setOrgUid(orgUid);
create(processRequest);
// 部署流程
Deployment deployment = repositoryService.createDeployment()
.name(TicketConsts.TICKET_PROCESS_NAME_GROUP_SIMPLE)
.addClasspathResource(TicketConsts.TICKET_PROCESS_GROUP_PATH_SIMPLE)
.tenantId(orgUid)
.deploy();
// 更新 TicketProcessEntity
Optional<TicketProcessEntity> processEntity = findByUid(processUid);
if (processEntity.isPresent()) {
processEntity.get().setDeploymentId(deployment.getId());
processEntity.get().setDeployed(true);
save(processEntity.get());
}
log.info("部署租户流程成功: deploymentId={}, tenantId={}",
deployment.getId(), deployment.getTenantId());
} catch (IOException e) {
log.error("部署工单流程失败: tenantId={}", orgUid, e);
}
}
}

View File

@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2025-01-29 12:24:32
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-03-26 17:45:49
* @LastEditTime: 2025-03-28 16:43:26
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -705,17 +705,20 @@ public class TicketService {
}
try {
// 4. 添加评论
// 注意添加评论一定要放在complete之前否则会报错找不到task
// 4. 添加评论
Comment comment = taskService.addComment(task.getId(), ticket.getProcessInstanceId(),
TicketStatusEnum.RESOLVED.name(), "工单已解决");
comment.setUserId(assigneeUid); // 设置评论的userId为当前认领人
taskService.saveComment(comment);
// 5. 完成任务
taskService.complete(task.getId());
// 5. 设置流程变量,添加这段代码
Map<String, Object> variables = new HashMap<>();
variables.put("verified", false); // 默认设置为false等待客户验证
// 6. 完成任务,传入变量
taskService.complete(task.getId(), variables);
// 6. 更新工单状态
// 7. 更新工单状态
ticket.setStatus(TicketStatusEnum.RESOLVED.name());
ticket.setResolvedTime(LocalDateTime.now());
ticketRepository.save(ticket);
@@ -787,7 +790,7 @@ public class TicketService {
// 8. 更新工单状态
if (request.getVerified()) {
ticket.setStatus(TicketStatusEnum.CLOSED.name());
ticket.setStatus(request.getVerified() ? TicketStatusEnum.VERIFIED_OK.name() : TicketStatusEnum.VERIFIED_FAIL.name());
ticket.setVerified(true);
ticket.setClosedTime(LocalDateTime.now());
} else {

View File

@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-29 16:17:36
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-03-01 08:46:58
* @LastEditTime: 2025-03-28 14:32:22
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -14,6 +14,7 @@
package com.bytedesk.starter.runner;
import java.util.List;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
@@ -38,6 +39,9 @@ public class InitDataRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
// 在应用的主类或配置类中
// TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));
// TimeZone.setDefault(TimeZone.getTimeZone("GMT+8"));
String localIP = NetworkUtils.getFirstNonLoopbackIP();
List<String> allIPs = NetworkUtils.getLocalIPs();
@@ -49,7 +53,7 @@ public class InitDataRunner implements ApplicationRunner {
log.info("Other Network IPs:");
allIPs.stream()
.filter(ip -> !ip.equals(localIP))
.forEach(ip -> log.info(" http://{}:{}", ip, port));
.forEach(ip -> log.info("http://{}:{}", ip, port));
}
}

View File

@@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="UTF-8"/><link rel="icon" type="image/x-icon" href="/agent/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>微语</title><script type="module" crossorigin src="/agent/agent/assets/js/index-GOHxOdpv.js"></script><link rel="stylesheet" crossorigin href="/agent/agent/assets/css/index-gWOepWFe.css"></head><body><div id="root"></div><script src="https://www.weiyuai.cn/agent/assets/js/0.3.5/sdk.js"></script><script src="https://www.weiyuai.cn/agent/assets/js/2.0.2/index.js" async></script></body></html>
<!doctype html><html lang="en"><head><meta charset="UTF-8"/><link rel="icon" type="image/x-icon" href="/agent/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>微语</title><script type="module" crossorigin src="/agent/agent/assets/js/index-C1jiQc_M.js"></script><link rel="stylesheet" crossorigin href="/agent/agent/assets/css/index-gWOepWFe.css"></head><body><div id="root"></div><script src="https://www.weiyuai.cn/agent/assets/js/0.3.5/sdk.js"></script><script src="https://www.weiyuai.cn/agent/assets/js/2.0.2/index.js" async></script></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

View File

@@ -0,0 +1,15 @@
<!--
* @Author: jackning 270580156@qq.com
* @Date: 2025-02-09 18:26:27
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-02-09 18:26:31
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
* 仅支持企业内部员工自用严禁私自用于销售、二次销售或者部署SaaS方式销售
* Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
* contact: 270580156@qq.com
* 技术/商务联系270580156@qq.com
* Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
-->
# 自定义图标

View File

@@ -0,0 +1,27 @@
###
# @Author: jackning 270580156@qq.com
# @Date: 2024-03-27 10:52:01
# @LastEditors: jackning 270580156@qq.com
# @LastEditTime: 2024-03-27 10:56:19
# @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
# Please be aware of the BSL license restrictions before installing Bytedesk IM
# selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
# 仅支持企业内部员工自用严禁私自用于销售、二次销售或者部署SaaS方式销售
# Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
# contact: 270580156@qq.com
# 联系270580156@qq.com
# Copyright (c) 2024 by bytedesk.com, All Rights Reserved.
###
mkdir logo.iconset
sips -z 16 16 logo1024.png --out logo.iconset/icon_16x16.png
sips -z 32 32 logo1024.png --out logo.iconset/icon_16x16@2x.png
sips -z 32 32 logo1024.png --out logo.iconset/icon_32x32.png
sips -z 64 64 logo1024.png --out logo.iconset/icon_32x32@2x.png
sips -z 128 128 logo1024.png --out logo.iconset/icon_128x128.png
sips -z 256 256 logo1024.png --out logo.iconset/icon_128x128@2x.png
sips -z 256 256 logo1024.png --out logo.iconset/icon_256x256.png
sips -z 512 512 logo1024.png --out logo.iconset/icon_256x256@2x.png
sips -z 512 512 logo1024.png --out logo.iconset/icon_512x512.png
sips -z 1024 1024 logo1024.png --out logo.iconset/icon_512x512@2x.png
iconutil -c icns logo.iconset -o icon.icns

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 714 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 778 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

View File

@@ -25,7 +25,7 @@
<meta name="format-detection" content="email=no">
<!-- title将由JavaScript动态设置使用国际化 -->
<title>ByteDesk</title>
<script type="module" crossorigin src="/chat/assets/index-C5y6TUnm.js"></script>
<script type="module" crossorigin src="/chat/assets/index-COpaTw7c.js"></script>
<link rel="stylesheet" crossorigin href="/chat/assets/index-DTmg-Kms.css">
</head>