日报提醒功能

main
kangwenjing 2026-04-10 13:33:17 +08:00
parent 3bea7ab015
commit 1b4cf60052
113 changed files with 3981 additions and 303 deletions

View File

@ -7,10 +7,12 @@ import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication(scanBasePackages = "com.unis.crm") @SpringBootApplication(scanBasePackages = "com.unis.crm")
@MapperScan("com.unis.crm.mapper") @MapperScan("com.unis.crm.mapper")
@EnableConfigurationProperties({WecomProperties.class, OmsProperties.class, InternalAuthProperties.class}) @EnableConfigurationProperties({WecomProperties.class, OmsProperties.class, InternalAuthProperties.class})
@EnableScheduling
public class UnisCrmBackendApplication { public class UnisCrmBackendApplication {
public static void main(String[] args) { public static void main(String[] args) {

View File

@ -0,0 +1,109 @@
package com.unis.crm.common;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import javax.sql.DataSource;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
@Component
public class ReportReminderSchemaInitializer implements ApplicationRunner {
private final DataSource dataSource;
public ReportReminderSchemaInitializer(DataSource dataSource) {
this.dataSource = dataSource;
}
@Override
public void run(ApplicationArguments args) {
try (Connection connection = dataSource.getConnection();
Statement statement = connection.createStatement()) {
statement.execute("""
create table if not exists wecom_app_config (
id bigint generated by default as identity primary key,
tenant_id bigint not null,
enabled boolean not null default false,
corp_id varchar(128),
agent_id varchar(64),
secret varchar(255),
created_at timestamptz not null default now(),
updated_at timestamptz not null default now(),
constraint uk_wecom_app_config_tenant unique (tenant_id)
)
""");
statement.execute("""
create table if not exists report_reminder_config (
id bigint generated by default as identity primary key,
tenant_id bigint not null,
wecom_push_enabled boolean not null default false,
missing_report_enabled boolean not null default true,
missing_report_target_type varchar(20) not null default 'ALL',
missing_report_user_ids text,
missing_report_role_ids text,
missing_report_org_ids text,
missing_report_exclude_user_ids text,
remind_start_time varchar(5) not null default '18:00',
remind_end_time varchar(5) not null default '18:30',
missing_report_template text,
remind_interval_minutes integer not null default 10,
max_remind_count_per_day integer not null default 3,
workday_only boolean not null default true,
skip_holiday boolean not null default true,
submit_notify_enabled boolean not null default true,
submit_notify_target_type varchar(20) not null default 'USERS',
submit_notify_user_ids text,
submit_notify_role_ids text,
submit_notify_template text,
exclude_submitter boolean not null default true,
created_at timestamptz not null default now(),
updated_at timestamptz not null default now(),
constraint uk_report_reminder_config_tenant unique (tenant_id)
)
""");
statement.execute("alter table if exists report_reminder_config add column if not exists missing_report_template text");
statement.execute("alter table if exists report_reminder_config add column if not exists submit_notify_template text");
statement.execute("""
create table if not exists wecom_user_mapping (
id bigint generated by default as identity primary key,
tenant_id bigint not null,
user_id bigint not null,
mobile varchar(32),
wecom_user_id varchar(128),
wecom_name varchar(128),
sync_status varchar(20) not null default 'PENDING',
sync_message varchar(255),
created_at timestamptz not null default now(),
updated_at timestamptz not null default now(),
constraint uk_wecom_user_mapping_tenant_user unique (tenant_id, user_id)
)
""");
statement.execute("""
create table if not exists wecom_message_log (
id bigint generated by default as identity primary key,
tenant_id bigint not null,
biz_type varchar(50) not null,
biz_id bigint,
message_type varchar(50) not null,
receiver_user_id bigint,
receiver_mobile varchar(32),
receiver_wecom_user_id varchar(128),
send_status varchar(20) not null,
error_code varchar(50),
error_message varchar(500),
request_body text,
response_body text,
sent_at timestamptz not null default now(),
created_at timestamptz not null default now()
)
""");
statement.execute("create index if not exists idx_wecom_message_log_tenant_sent_at on wecom_message_log (tenant_id, sent_at desc)");
statement.execute("create index if not exists idx_wecom_message_log_receiver_day on wecom_message_log (tenant_id, receiver_user_id, sent_at desc)");
statement.execute("create index if not exists idx_wecom_user_mapping_tenant_status on wecom_user_mapping (tenant_id, sync_status)");
} catch (SQLException exception) {
throw new IllegalStateException("Failed to initialize report reminder schema", exception);
}
}
}

View File

@ -0,0 +1,57 @@
package com.unis.crm.controller;
import com.unis.crm.common.ApiResponse;
import com.unis.crm.dto.reminder.ReportReminderConfigDTO;
import com.unis.crm.dto.reminder.ReportReminderTestRequest;
import com.unis.crm.dto.reminder.WecomAppConfigDTO;
import com.unis.crm.dto.reminder.WecomConfigStatusDTO;
import com.unis.crm.service.ReportReminderService;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/sys/api/admin")
public class ReportReminderAdminController {
private final ReportReminderService reportReminderService;
public ReportReminderAdminController(ReportReminderService reportReminderService) {
this.reportReminderService = reportReminderService;
}
@GetMapping("/wecom-app-config")
public ApiResponse<WecomAppConfigDTO> getWecomAppConfig(@RequestParam(value = "tenantId", required = false) Long tenantId) {
return ApiResponse.success(reportReminderService.getWecomAppConfig(tenantId));
}
@PutMapping("/wecom-app-config")
public ApiResponse<Boolean> updateWecomAppConfig(@Valid @RequestBody WecomAppConfigDTO payload) {
return ApiResponse.success(reportReminderService.saveWecomAppConfig(payload));
}
@GetMapping("/wecom-config-status")
public ApiResponse<WecomConfigStatusDTO> getWecomConfigStatus(@RequestParam(value = "tenantId", required = false) Long tenantId) {
return ApiResponse.success(reportReminderService.getWecomConfigStatus(tenantId));
}
@GetMapping("/report-reminder-config")
public ApiResponse<ReportReminderConfigDTO> getReportReminderConfig(@RequestParam(value = "tenantId", required = false) Long tenantId) {
return ApiResponse.success(reportReminderService.getReportReminderConfig(tenantId));
}
@PutMapping("/report-reminder-config")
public ApiResponse<Boolean> updateReportReminderConfig(@Valid @RequestBody ReportReminderConfigDTO payload) {
return ApiResponse.success(reportReminderService.saveReportReminderConfig(payload));
}
@PostMapping("/report-reminder-config/test")
public ApiResponse<Boolean> testReportReminderConfig(@Valid @RequestBody ReportReminderTestRequest payload) {
return ApiResponse.success(reportReminderService.testSend(payload));
}
}

View File

@ -0,0 +1,197 @@
package com.unis.crm.dto.reminder;
import java.util.ArrayList;
import java.util.List;
public class ReportReminderConfigDTO {
private Long tenantId;
private boolean wecomPushEnabled;
private boolean missingReportEnabled = true;
private String missingReportTargetType = "ALL";
private List<Long> missingReportUserIds = new ArrayList<>();
private List<Long> missingReportRoleIds = new ArrayList<>();
private List<Long> missingReportOrgIds = new ArrayList<>();
private List<Long> missingReportExcludeUserIds = new ArrayList<>();
private String remindStartTime = "18:00";
private String remindEndTime = "18:30";
private String missingReportTemplate = "【日报提醒】{{userName}},你 {{reportDate}} 的日报还未提交,请在 {{deadlineTime}} 前完成。";
private Integer remindIntervalMinutes = 10;
private Integer maxRemindCountPerDay = 3;
private boolean workdayOnly = true;
private boolean skipHoliday = true;
private boolean submitNotifyEnabled = true;
private String submitNotifyTargetType = "USERS";
private List<Long> submitNotifyUserIds = new ArrayList<>();
private List<Long> submitNotifyRoleIds = new ArrayList<>();
private String submitNotifyTemplate = "【日报提交】{{submitterName}}已于{{submitTime}}提交{{reportDate}}日报,请及时查看。";
private boolean excludeSubmitter = true;
public Long getTenantId() {
return tenantId;
}
public void setTenantId(Long tenantId) {
this.tenantId = tenantId;
}
public boolean isWecomPushEnabled() {
return wecomPushEnabled;
}
public void setWecomPushEnabled(boolean wecomPushEnabled) {
this.wecomPushEnabled = wecomPushEnabled;
}
public boolean isMissingReportEnabled() {
return missingReportEnabled;
}
public void setMissingReportEnabled(boolean missingReportEnabled) {
this.missingReportEnabled = missingReportEnabled;
}
public String getMissingReportTargetType() {
return missingReportTargetType;
}
public void setMissingReportTargetType(String missingReportTargetType) {
this.missingReportTargetType = missingReportTargetType;
}
public List<Long> getMissingReportUserIds() {
return missingReportUserIds;
}
public void setMissingReportUserIds(List<Long> missingReportUserIds) {
this.missingReportUserIds = missingReportUserIds;
}
public List<Long> getMissingReportRoleIds() {
return missingReportRoleIds;
}
public void setMissingReportRoleIds(List<Long> missingReportRoleIds) {
this.missingReportRoleIds = missingReportRoleIds;
}
public List<Long> getMissingReportOrgIds() {
return missingReportOrgIds;
}
public void setMissingReportOrgIds(List<Long> missingReportOrgIds) {
this.missingReportOrgIds = missingReportOrgIds;
}
public List<Long> getMissingReportExcludeUserIds() {
return missingReportExcludeUserIds;
}
public void setMissingReportExcludeUserIds(List<Long> missingReportExcludeUserIds) {
this.missingReportExcludeUserIds = missingReportExcludeUserIds;
}
public String getRemindStartTime() {
return remindStartTime;
}
public void setRemindStartTime(String remindStartTime) {
this.remindStartTime = remindStartTime;
}
public String getRemindEndTime() {
return remindEndTime;
}
public void setRemindEndTime(String remindEndTime) {
this.remindEndTime = remindEndTime;
}
public Integer getRemindIntervalMinutes() {
return remindIntervalMinutes;
}
public void setRemindIntervalMinutes(Integer remindIntervalMinutes) {
this.remindIntervalMinutes = remindIntervalMinutes;
}
public String getMissingReportTemplate() {
return missingReportTemplate;
}
public void setMissingReportTemplate(String missingReportTemplate) {
this.missingReportTemplate = missingReportTemplate;
}
public Integer getMaxRemindCountPerDay() {
return maxRemindCountPerDay;
}
public void setMaxRemindCountPerDay(Integer maxRemindCountPerDay) {
this.maxRemindCountPerDay = maxRemindCountPerDay;
}
public boolean isWorkdayOnly() {
return workdayOnly;
}
public void setWorkdayOnly(boolean workdayOnly) {
this.workdayOnly = workdayOnly;
}
public boolean isSkipHoliday() {
return skipHoliday;
}
public void setSkipHoliday(boolean skipHoliday) {
this.skipHoliday = skipHoliday;
}
public boolean isSubmitNotifyEnabled() {
return submitNotifyEnabled;
}
public void setSubmitNotifyEnabled(boolean submitNotifyEnabled) {
this.submitNotifyEnabled = submitNotifyEnabled;
}
public String getSubmitNotifyTargetType() {
return submitNotifyTargetType;
}
public void setSubmitNotifyTargetType(String submitNotifyTargetType) {
this.submitNotifyTargetType = submitNotifyTargetType;
}
public List<Long> getSubmitNotifyUserIds() {
return submitNotifyUserIds;
}
public void setSubmitNotifyUserIds(List<Long> submitNotifyUserIds) {
this.submitNotifyUserIds = submitNotifyUserIds;
}
public List<Long> getSubmitNotifyRoleIds() {
return submitNotifyRoleIds;
}
public void setSubmitNotifyRoleIds(List<Long> submitNotifyRoleIds) {
this.submitNotifyRoleIds = submitNotifyRoleIds;
}
public String getSubmitNotifyTemplate() {
return submitNotifyTemplate;
}
public void setSubmitNotifyTemplate(String submitNotifyTemplate) {
this.submitNotifyTemplate = submitNotifyTemplate;
}
public boolean isExcludeSubmitter() {
return excludeSubmitter;
}
public void setExcludeSubmitter(boolean excludeSubmitter) {
this.excludeSubmitter = excludeSubmitter;
}
}

View File

@ -0,0 +1,58 @@
package com.unis.crm.dto.reminder;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
public class ReportReminderTestRequest {
private Long tenantId;
@NotNull(message = "测试接收人不能为空")
private Long receiverUserId;
@NotNull(message = "测试消息类型不能为空")
private String messageType;
@Valid
private WecomAppConfigDTO appConfig;
@Valid
@NotNull(message = "提醒配置不能为空")
private ReportReminderConfigDTO config;
public Long getTenantId() {
return tenantId;
}
public void setTenantId(Long tenantId) {
this.tenantId = tenantId;
}
public Long getReceiverUserId() {
return receiverUserId;
}
public void setReceiverUserId(Long receiverUserId) {
this.receiverUserId = receiverUserId;
}
public String getMessageType() {
return messageType;
}
public void setMessageType(String messageType) {
this.messageType = messageType;
}
public WecomAppConfigDTO getAppConfig() {
return appConfig;
}
public void setAppConfig(WecomAppConfigDTO appConfig) {
this.appConfig = appConfig;
}
public ReportReminderConfigDTO getConfig() {
return config;
}
public void setConfig(ReportReminderConfigDTO config) {
this.config = config;
}
}

View File

@ -0,0 +1,50 @@
package com.unis.crm.dto.reminder;
public class WecomAppConfigDTO {
private Long tenantId;
private boolean enabled;
private String corpId;
private String agentId;
private String secret;
public Long getTenantId() {
return tenantId;
}
public void setTenantId(Long tenantId) {
this.tenantId = tenantId;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public String getCorpId() {
return corpId;
}
public void setCorpId(String corpId) {
this.corpId = corpId;
}
public String getAgentId() {
return agentId;
}
public void setAgentId(String agentId) {
this.agentId = agentId;
}
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
}

View File

@ -0,0 +1,41 @@
package com.unis.crm.dto.reminder;
public class WecomConfigStatusDTO {
private boolean enabled;
private boolean configured;
private String mappingMode;
private String message;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean isConfigured() {
return configured;
}
public void setConfigured(boolean configured) {
this.configured = configured;
}
public String getMappingMode() {
return mappingMode;
}
public void setMappingMode(String mappingMode) {
this.mappingMode = mappingMode;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}

View File

@ -19,7 +19,7 @@ public interface WorkMapper {
WorkCheckInDTO selectTodayCheckIn(@Param("userId") Long userId); WorkCheckInDTO selectTodayCheckIn(@Param("userId") Long userId);
WorkDailyReportDTO selectTodayReport(@Param("userId") Long userId); WorkDailyReportDTO selectTodayReport(@Param("userId") Long userId, @Param("reportDate") LocalDate reportDate);
List<WorkSuggestedActionDTO> selectTodayWorkContentActions(@Param("userId") Long userId); List<WorkSuggestedActionDTO> selectTodayWorkContentActions(@Param("userId") Long userId);
@ -54,11 +54,18 @@ public interface WorkMapper {
int updateCheckIn(@Param("checkInId") Long checkInId, @Param("request") CreateWorkCheckInRequest request); int updateCheckIn(@Param("checkInId") Long checkInId, @Param("request") CreateWorkCheckInRequest request);
Long selectTodayReportId(@Param("userId") Long userId); Long selectTodayReportId(@Param("userId") Long userId, @Param("reportDate") LocalDate reportDate);
int insertDailyReport(@Param("userId") Long userId, @Param("request") CreateWorkDailyReportRequest request); int insertDailyReport(
@Param("userId") Long userId,
@Param("request") CreateWorkDailyReportRequest request,
@Param("reportDate") LocalDate reportDate,
@Param("submitAt") java.time.OffsetDateTime submitAt);
int updateDailyReport(@Param("reportId") Long reportId, @Param("request") CreateWorkDailyReportRequest request); int updateDailyReport(
@Param("reportId") Long reportId,
@Param("request") CreateWorkDailyReportRequest request,
@Param("submitAt") java.time.OffsetDateTime submitAt);
int deleteGeneratedExpansionFollowUps(@Param("reportId") Long reportId); int deleteGeneratedExpansionFollowUps(@Param("reportId") Long reportId);

View File

@ -0,0 +1,19 @@
package com.unis.crm.service;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class ReportReminderScheduler {
private final ReportReminderService reportReminderService;
public ReportReminderScheduler(ReportReminderService reportReminderService) {
this.reportReminderService = reportReminderService;
}
@Scheduled(cron = "0 * * * * *")
public void dispatchMissingReportReminders() {
reportReminderService.processScheduledMissingReportReminders();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -19,6 +19,7 @@ import com.unis.crm.dto.work.WorkOverviewDTO;
import com.unis.crm.dto.work.WorkSuggestedActionDTO; import com.unis.crm.dto.work.WorkSuggestedActionDTO;
import com.unis.crm.mapper.ProfileMapper; import com.unis.crm.mapper.ProfileMapper;
import com.unis.crm.mapper.WorkMapper; import com.unis.crm.mapper.WorkMapper;
import com.unis.crm.service.ReportReminderService;
import com.unis.crm.service.WorkService; import com.unis.crm.service.WorkService;
import java.io.IOException; import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
@ -54,6 +55,8 @@ import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource; import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
@ -80,11 +83,13 @@ public class WorkServiceImpl implements WorkService {
private static final double EARTH_ECCENTRICITY = 0.00669342162296594323; private static final double EARTH_ECCENTRICITY = 0.00669342162296594323;
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
private static final DateTimeFormatter REPORT_DATE_TIME_TEXT_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm"); private static final DateTimeFormatter REPORT_DATE_TIME_TEXT_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm");
private static final ZoneId BUSINESS_ZONE_ID = ZoneId.of("Asia/Shanghai");
private final WorkMapper workMapper; private final WorkMapper workMapper;
private final ProfileMapper profileMapper; private final ProfileMapper profileMapper;
private final HttpClient httpClient; private final HttpClient httpClient;
private final ObjectMapper objectMapper; private final ObjectMapper objectMapper;
private final ReportReminderService reportReminderService;
private final Path checkInPhotoDirectory; private final Path checkInPhotoDirectory;
private final String tencentMapKey; private final String tencentMapKey;
private final Map<String, String> locationNameCache = new ConcurrentHashMap<>(); private final Map<String, String> locationNameCache = new ConcurrentHashMap<>();
@ -92,11 +97,13 @@ public class WorkServiceImpl implements WorkService {
public WorkServiceImpl( public WorkServiceImpl(
WorkMapper workMapper, WorkMapper workMapper,
ProfileMapper profileMapper, ProfileMapper profileMapper,
ReportReminderService reportReminderService,
ObjectMapper objectMapper, ObjectMapper objectMapper,
@Value("${unisbase.app.upload-path}") String uploadPath, @Value("${unisbase.app.upload-path}") String uploadPath,
@Value("${unisbase.app.tencent-map.key:}") String tencentMapKey) { @Value("${unisbase.app.tencent-map.key:}") String tencentMapKey) {
this.workMapper = workMapper; this.workMapper = workMapper;
this.profileMapper = profileMapper; this.profileMapper = profileMapper;
this.reportReminderService = reportReminderService;
this.objectMapper = objectMapper; this.objectMapper = objectMapper;
this.httpClient = HttpClient.newBuilder() this.httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(8)) .connectTimeout(Duration.ofSeconds(8))
@ -110,7 +117,7 @@ public class WorkServiceImpl implements WorkService {
requireUser(userId); requireUser(userId);
WorkCheckInDTO todayCheckIn = workMapper.selectTodayCheckIn(userId); WorkCheckInDTO todayCheckIn = workMapper.selectTodayCheckIn(userId);
normalizeCheckInMetadata(todayCheckIn); normalizeCheckInMetadata(todayCheckIn);
WorkDailyReportDTO todayReport = workMapper.selectTodayReport(userId); WorkDailyReportDTO todayReport = workMapper.selectTodayReport(userId, currentBusinessDate());
normalizeDailyReport(todayReport); normalizeDailyReport(todayReport);
String suggestedWorkContent = buildSuggestedWorkContent(workMapper.selectTodayWorkContentActions(userId)); String suggestedWorkContent = buildSuggestedWorkContent(workMapper.selectTodayWorkContentActions(userId));
return new WorkOverviewDTO(todayCheckIn, todayReport, suggestedWorkContent, List.of()); return new WorkOverviewDTO(todayCheckIn, todayReport, suggestedWorkContent, List.of());
@ -233,24 +240,26 @@ public class WorkServiceImpl implements WorkService {
request.setSourceType("manual"); request.setSourceType("manual");
} }
Long reportId = workMapper.selectTodayReportId(userId); LocalDate reportDate = currentBusinessDate();
OffsetDateTime submitAt = OffsetDateTime.now(BUSINESS_ZONE_ID);
Long reportId = workMapper.selectTodayReportId(userId, reportDate);
WorkDailyReportDTO previousReport = null; WorkDailyReportDTO previousReport = null;
if (reportId != null) { if (reportId != null) {
previousReport = workMapper.selectTodayReport(userId); previousReport = workMapper.selectTodayReport(userId, reportDate);
normalizeDailyReport(previousReport); normalizeDailyReport(previousReport);
} }
int affectedRows; int affectedRows;
if (reportId == null) { if (reportId == null) {
affectedRows = workMapper.insertDailyReport(userId, request); affectedRows = workMapper.insertDailyReport(userId, request, reportDate, submitAt);
reportId = workMapper.selectTodayReportId(userId); reportId = workMapper.selectTodayReportId(userId, reportDate);
} else { } else {
affectedRows = workMapper.updateDailyReport(reportId, request); affectedRows = workMapper.updateDailyReport(reportId, request, submitAt);
} }
if (affectedRows <= 0 || reportId == null) { if (affectedRows <= 0 || reportId == null) {
throw new BusinessException("日报保存失败"); throw new BusinessException("日报保存失败");
} }
WorkDailyReportDTO currentReport = workMapper.selectTodayReport(userId); WorkDailyReportDTO currentReport = workMapper.selectTodayReport(userId, reportDate);
normalizeDailyReport(currentReport); normalizeDailyReport(currentReport);
syncReportFollowUps( syncReportFollowUps(
userId, userId,
@ -259,6 +268,18 @@ public class WorkServiceImpl implements WorkService {
request, request,
currentReport); currentReport);
syncTomorrowPlanTodo(userId, reportId, request.getPlanItems()); syncTomorrowPlanTodo(userId, reportId, request.getPlanItems());
Long finalReportId = reportId;
WorkDailyReportDTO finalCurrentReport = currentReport;
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@Override
public void afterCommit() {
reportReminderService.notifyReportSubmitted(userId, finalReportId, finalCurrentReport);
}
});
} else {
reportReminderService.notifyReportSubmitted(userId, finalReportId, finalCurrentReport);
}
return reportId; return reportId;
} }
@ -1716,6 +1737,10 @@ public class WorkServiceImpl implements WorkService {
}; };
} }
private LocalDate currentBusinessDate() {
return LocalDate.now(BUSINESS_ZONE_ID);
}
private record PhotoMetadata(String cleanText, List<String> photoUrls) {} private record PhotoMetadata(String cleanText, List<String> photoUrls) {}
private record ReportLineMetadata(String cleanText, List<WorkReportLineItemDTO> lineItems) {} private record ReportLineMetadata(String cleanText, List<WorkReportLineItemDTO> lineItems) {}

View File

@ -60,7 +60,7 @@ unisbase:
access-default-minutes: 30 access-default-minutes: 30
refresh-default-days: 7 refresh-default-days: 7
wecom: wecom:
enabled: ${WECOM_ENABLED:true} enabled: ${WECOM_ENABLED:false}
corp-id: ${WECOM_CORP_ID:ww249648b2f76c3ba5} corp-id: ${WECOM_CORP_ID:ww249648b2f76c3ba5}
agent-id: ${WECOM_AGENT_ID:1000108} agent-id: ${WECOM_AGENT_ID:1000108}
secret: ${WECOM_SECRET:ngv-x4X1Epy5KcL85B7nhzY-qQkA4FnId9ZZ7Z3s3lQ} secret: ${WECOM_SECRET:ngv-x4X1Epy5KcL85B7nhzY-qQkA4FnId9ZZ7Z3s3lQ}

View File

@ -65,11 +65,11 @@ unisbase:
access-default-minutes: 30 access-default-minutes: 30
refresh-default-days: 7 refresh-default-days: 7
wecom: wecom:
enabled: false enabled: ${WECOM_ENABLED:true}
corp-id: ${WECOM_CORP_ID:} corp-id: ${WECOM_CORP_ID:ww249648b2f76c3ba5}
agent-id: ${WECOM_AGENT_ID:} agent-id: ${WECOM_AGENT_ID:1000108}
secret: ${WECOM_SECRET:} secret: ${WECOM_SECRET:ngv-x4X1Epy5KcL85B7nhzY-qQkA4FnId9ZZ7Z3s3lQ}
redirect-uri: ${WECOM_REDIRECT_URI:https://crm.unissense.top/api/wecom/sso/callback} redirect-uri: ${WECOM_REDIRECT_URI:https://111.10.202.195:9002/api/wecom/sso/callback}
frontend-callback-path: ${WECOM_FRONTEND_CALLBACK_PATH:/login/wecom} frontend-callback-path: ${WECOM_FRONTEND_CALLBACK_PATH:/login/wecom}
scope: ${WECOM_SCOPE:snsapi_base} scope: ${WECOM_SCOPE:snsapi_base}
state-ttl-seconds: 300 state-ttl-seconds: 300

View File

@ -47,7 +47,7 @@
order by report_id, reviewed_at desc nulls last, id desc order by report_id, reviewed_at desc nulls last, id desc
) c on c.report_id = r.id ) c on c.report_id = r.id
where r.user_id = #{userId} where r.user_id = #{userId}
and r.report_date = current_date and r.report_date = #{reportDate}
order by r.submit_time desc nulls last, r.id desc order by r.submit_time desc nulls last, r.id desc
limit 1 limit 1
</select> </select>
@ -428,7 +428,7 @@
select id select id
from work_daily_report from work_daily_report
where user_id = #{userId} where user_id = #{userId}
and report_date = current_date and report_date = #{reportDate}
order by submit_time desc nulls last, id desc order by submit_time desc nulls last, id desc
limit 1 limit 1
</select> </select>
@ -446,11 +446,11 @@
updated_at updated_at
) values ( ) values (
#{userId}, #{userId},
current_date, #{reportDate},
#{request.workContent}, #{request.workContent},
#{request.tomorrowPlan}, #{request.tomorrowPlan},
#{request.sourceType}, #{request.sourceType},
now(), #{submitAt},
'submitted', 'submitted',
now(), now(),
now() now()
@ -462,7 +462,7 @@
set work_content = #{request.workContent}, set work_content = #{request.workContent},
tomorrow_plan = #{request.tomorrowPlan}, tomorrow_plan = #{request.tomorrowPlan},
source_type = #{request.sourceType}, source_type = #{request.sourceType},
submit_time = now(), submit_time = #{submitAt},
status = 'submitted', status = 'submitted',
updated_at = now() updated_at = now()
where id = #{reportId} where id = #{reportId}

View File

@ -16,6 +16,7 @@ import com.unis.crm.dto.work.WorkHistoryItemDTO;
import com.unis.crm.dto.work.WorkHistoryPageDTO; import com.unis.crm.dto.work.WorkHistoryPageDTO;
import com.unis.crm.mapper.ProfileMapper; import com.unis.crm.mapper.ProfileMapper;
import com.unis.crm.mapper.WorkMapper; import com.unis.crm.mapper.WorkMapper;
import com.unis.crm.service.ReportReminderService;
import java.util.List; import java.util.List;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -33,11 +34,14 @@ class WorkServiceImplTest {
@Mock @Mock
private ProfileMapper profileMapper; private ProfileMapper profileMapper;
@Mock
private ReportReminderService reportReminderService;
private WorkServiceImpl workService; private WorkServiceImpl workService;
@BeforeEach @BeforeEach
void setUp() { void setUp() {
workService = new WorkServiceImpl(workMapper, profileMapper, new ObjectMapper(), "build/test-uploads", ""); workService = new WorkServiceImpl(workMapper, profileMapper, reportReminderService, new ObjectMapper(), "build/test-uploads", "");
} }
@Test @Test
@ -121,7 +125,11 @@ class WorkServiceImplTest {
() -> workService.saveDailyReport(17L, new CreateWorkDailyReportRequest())); () -> workService.saveDailyReport(17L, new CreateWorkDailyReportRequest()));
assertEquals("当前角色仅可查看日报历史记录", exception.getMessage()); assertEquals("当前角色仅可查看日报历史记录", exception.getMessage());
verify(workMapper, never()).insertDailyReport(org.mockito.ArgumentMatchers.anyLong(), org.mockito.ArgumentMatchers.any()); verify(workMapper, never()).insertDailyReport(
org.mockito.ArgumentMatchers.anyLong(),
org.mockito.ArgumentMatchers.any(),
org.mockito.ArgumentMatchers.any(),
org.mockito.ArgumentMatchers.any());
} }
@Test @Test

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,4 +0,0 @@
import{d2 as c,bI as o}from"./index-2nzO_M0d.js";const r=new o("antFadeIn",{"0%":{opacity:0},"100%":{opacity:1}}),s=new o("antFadeOut",{"0%":{opacity:1},"100%":{opacity:0}}),p=(t,a=!1)=>{const{antCls:e}=t,n=`${e}-fade`,i=a?"&":"";return[c(n,r,s,t.motionDurationMid,a),{[`
${i}${n}-enter,
${i}${n}-appear
`]:{opacity:0,animationTimingFunction:"linear"},[`${i}${n}-leave`]:{animationTimingFunction:"linear"}}]};export{p as i};

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
import{u as M,r as t,j as e,B as $,x as F,H,z as c,R as v,T as K,J as P,a9 as W,_ as Y,Z as D,a0 as G,s as w,a4 as J}from"./index-BGI3tmtB.js";import{P as Z}from"./index-xsV5o4zp.js";import{R as N,C as d}from"./row-C3H8lbGw.js";import{C as b}from"./index-DxgbQv5l.js";import{I as q}from"./index-FqFqpoYX.js";import{F as A}from"./Table-BewG91sh.js";import{T as u}from"./index-bzjak6Z4.js";import{C as S}from"./index-DJxTfCUX.js";import"./iconUtil-IZQuqZwd.js";import"./index-DUXqiKOh.js";import"./useForm-BpWJqkw6.js";import"./Pagination-COOq01L8.js";const{Text:C}=K;function ne(){const{t:a}=M(),[o,I]=t.useState([]),[h,U]=t.useState([]),[T,m]=t.useState(!1),[p,x]=t.useState(!1),[f,g]=t.useState(!1),[l,y]=t.useState(null),[j,i]=t.useState([]),[n,_]=t.useState(""),R=t.useMemo(()=>o.find(s=>s.userId===l)||null,[o,l]),z=async()=>{m(!0);try{const s=await Y();I(s||[])}finally{m(!1)}},k=async()=>{x(!0);try{const s=await D();U(s||[])}finally{x(!1)}},E=async s=>{try{const r=await G(s);i(r||[])}catch{i([])}};t.useEffect(()=>{z(),k()},[]),t.useEffect(()=>{l?E(l):i([])},[l]);const L=t.useMemo(()=>{if(!n)return o;const s=n.toLowerCase();return o.filter(r=>r.username.toLowerCase().includes(s)||r.displayName.toLowerCase().includes(s))},[o,n]),B=async()=>{if(!l){w.warning(a("userRole.selectUser"));return}g(!0);try{await J(l,j),w.success(a("common.success"))}finally{g(!1)}};return e.jsxs("div",{className:"app-page",children:[e.jsx(Z,{title:a("userRole.title"),subtitle:a("userRole.subtitle")}),e.jsx("div",{className:"app-page__page-actions",children:e.jsx($,{type:"primary",icon:e.jsx(F,{"aria-hidden":"true"}),onClick:B,loading:f,disabled:!l,children:a(f?"common.loading":"common.save")})}),e.jsxs(N,{gutter:24,className:"app-page__split",style:{height:"calc(100vh - 180px)"},children:[e.jsx(d,{xs:24,lg:12,style:{height:"100%"},children:e.jsxs(b,{title:e.jsxs(c,{children:[e.jsx(v,{"aria-hidden":"true"}),e.jsx("span",{children:a("userRole.userList")})]}),className:"app-page__panel-card full-height-card",children:[e.jsx("div",{className:"mb-4",children:e.jsx(q,{placeholder:a("userRole.searchUser"),prefix:e.jsx(H,{"aria-hidden":"true",className:"text-gray-400"}),value:n,onChange:s=>_(s.target.value),allowClear:!0,"aria-label":a("userRole.searchUser")})}),e.jsx("div",{style:{height:"calc(100% - 60px)",overflowY:"auto"},children:e.jsx(A,{rowKey:"userId",size:"middle",loading:T,dataSource:L,rowSelection:{type:"radio",selectedRowKeys:l?[l]:[],onChange:s=>y(s[0])},onRow:s=>({onClick:()=>y(s.userId),className:"cursor-pointer"}),pagination:{pageSize:10,showTotal:s=>a("common.total",{total:s})},columns:[{title:a("users.userInfo"),key:"user",render:(s,r)=>e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{style:{fontWeight:500},className:"truncate",children:r.displayName}),e.jsxs("div",{style:{fontSize:12,color:"#8c8c8c"},className:"truncate",children:["@",r.username]})]})},{title:a("common.status"),dataIndex:"status",width:80,render:s=>s===1?e.jsx(u,{color:"green",className:"m-0",children:"Enabled"}):e.jsx(u,{className:"m-0",children:"Disabled"})}]})})]})}),e.jsx(d,{xs:24,lg:12,style:{height:"100%"},children:e.jsx(b,{title:e.jsxs(c,{children:[e.jsx(W,{"aria-hidden":"true"}),e.jsx("span",{children:a("userRole.grantRoles")})]}),className:"app-page__panel-card full-height-card",extra:R?e.jsxs(u,{color:"blue",children:[a("userRole.editing"),": ",R.displayName]}):null,children:l?e.jsxs("div",{style:{padding:"8px 0",height:"100%",overflowY:"auto"},children:[e.jsx(S.Group,{style:{width:"100%"},value:j,onChange:s=>i(s),disabled:p,children:e.jsx(N,{gutter:[16,16],children:h.map(s=>e.jsx(d,{span:12,children:e.jsx(S,{value:s.roleId,className:"w-full",children:e.jsxs(c,{direction:"vertical",size:0,children:[e.jsx("span",{style:{fontWeight:500},children:s.roleName}),e.jsx(C,{type:"secondary",style:{fontSize:12},className:"tabular-nums",children:s.roleCode})]})})},s.roleId))})}),!h.length&&!p&&e.jsx(P,{description:"No roles available"})]}):e.jsxs("div",{className:"flex flex-col items-center justify-center py-20 bg-gray-50 rounded-lg border border-dashed border-gray-200",children:[e.jsx(v,{style:{fontSize:40,color:"#bfbfbf",marginBottom:16},"aria-hidden":"true"}),e.jsx(C,{type:"secondary",children:a("userRole.selectUser")})]})})})]})]})}export{ne as default};

View File

@ -0,0 +1 @@
.report-reminder-page{max-width:1280px;height:100%;min-height:0;overflow:hidden}.report-reminder-scroll{flex:1;min-height:0;overflow-y:auto;overflow-x:hidden;padding:0 4px 32px 0}.report-reminder-page .app-page__content-card{overflow:visible}.report-reminder-page .ant-row{row-gap:24px}.report-reminder-page__preview{background:#fafafa;border:1px dashed #d9d9d9;border-radius:12px;padding:12px 16px}.report-reminder-page__preview .ant-typography:last-child{margin-bottom:0}.report-reminder-page__template-tools{background:#fafafa;border:1px dashed #d9d9d9;border-radius:12px;padding:12px 16px;margin-bottom:12px}.report-reminder-page__template-tools-header{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:10px}.report-reminder-page__template-tools-tags{display:flex;flex-wrap:wrap;gap:8px}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
import{u as v,r as l,f as S,s as x,j as e,T as k,R as C,a as T,b as P,B as f,c as R,g as B,d as E,l as z,e as L}from"./index-2nzO_M0d.js";import{F as r}from"./index-BNTgrN92.js";import{I as m}from"./index-fAufRegR.js";import{C as U}from"./index-z7YG9RTL.js";import"./useForm-CzLkm9RK.js";import"./row-CR991LIl.js";const{Text:q}=k;function A(){const{t:a}=v(),[i,j]=l.useState(null),[o,g]=l.useState(!0),[u,h]=l.useState(!1),[t,b]=l.useState(null),[y]=r.useForm(),N="汇智CRM管理后台",c=l.useCallback(async()=>{if(!o)return;const s=await S();j(s)},[o]);l.useEffect(()=>{(async()=>{try{const[n,d]=await Promise.all([B("security.captcha.enabled","true"),E()]);b(d);const p=n!=="false";g(p),p&&await c()}catch{g(!0),await c()}})()},[c]),l.useEffect(()=>{new URLSearchParams(window.location.search).get("timeout")==="1"&&(x.warning(a("login.loginTimeout")),window.history.replaceState({},document.title,window.location.pathname))},[a]);const w=async s=>{h(!0);try{const n=await z({username:s.username,password:s.password,tenantCode:s.tenantCode,captchaId:o?i==null?void 0:i.captchaId:void 0,captchaCode:o?s.captchaCode:void 0});if(localStorage.setItem("accessToken",n.accessToken),localStorage.setItem("refreshToken",n.refreshToken),localStorage.setItem("username",s.username),n.availableTenants){localStorage.setItem("availableTenants",JSON.stringify(n.availableTenants));const d=JSON.parse(atob(n.accessToken.split(".")[1]));localStorage.setItem("activeTenantId",String(d.tenantId))}try{const d=await L();sessionStorage.setItem("userProfile",JSON.stringify(d))}catch{sessionStorage.removeItem("userProfile")}x.success(a("common.success")),window.location.href="/"}catch{o&&await c()}finally{h(!1)}},I=t!=null&&t.loginBgUrl?{backgroundImage:`url(${t.loginBgUrl})`,backgroundSize:"cover",backgroundPosition:"center",position:"relative"}:{};return e.jsxs("div",{className:"login-page",style:I,children:[e.jsx("div",{className:"login-page-backdrop"}),e.jsx("div",{className:"login-page-grid",children:e.jsx("section",{className:"login-panel",children:e.jsx("div",{className:"login-panel-card",children:e.jsxs("div",{className:"login-panel-layout",children:[e.jsx("div",{className:"login-left",children:e.jsxs("div",{className:"login-brand",children:[e.jsx("div",{className:"brand-logo-wrap",children:e.jsx("img",{src:(t==null?void 0:t.logoUrl)||"/logo.svg",alt:"Logo",className:"brand-logo-img"})}),e.jsxs("div",{className:"brand-copy",children:[e.jsx("p",{className:"brand-kicker",children:"智慧销售协同平台"}),e.jsx("span",{className:"brand-name",children:N})]})]})}),e.jsx("div",{className:"login-right",children:e.jsxs("div",{className:"login-container",children:[e.jsxs("div",{className:"login-header",children:[e.jsx("p",{className:"login-panel-eyebrow",children:a("login.welcome")}),e.jsx(q,{type:"secondary",children:a("login.subtitle")})]}),e.jsxs(r,{form:y,layout:"vertical",onFinish:w,className:"login-form",requiredMark:!1,autoComplete:"off",children:[e.jsx(r.Item,{name:"username",rules:[{required:!0,message:a("login.username")}],children:e.jsx(m,{size:"large",prefix:e.jsx(C,{className:"text-gray-400","aria-hidden":"true"}),placeholder:a("login.username"),autoComplete:"username",spellCheck:!1,"aria-label":a("login.username")})}),e.jsx(r.Item,{name:"password",rules:[{required:!0,message:a("login.password")}],children:e.jsx(m.Password,{size:"large",prefix:e.jsx(T,{className:"text-gray-400","aria-hidden":"true"}),placeholder:a("login.password"),autoComplete:"current-password","aria-label":a("login.password")})}),o?e.jsx(r.Item,{name:"captchaCode",rules:[{required:!0,message:a("login.captcha")}],children:e.jsxs("div",{className:"captcha-wrapper",children:[e.jsx(m,{size:"large",prefix:e.jsx(P,{className:"text-gray-400","aria-hidden":"true"}),placeholder:a("login.captcha"),maxLength:6,"aria-label":a("login.captcha")}),e.jsx(f,{className:"captcha-image-btn",onClick:()=>void c(),icon:i?null:e.jsx(R,{spin:!0}),"aria-label":"刷新验证码",children:i?e.jsx("img",{src:i.imageBase64,alt:"验证码"}):null})]})}):null,e.jsx("div",{className:"login-extra",children:e.jsx(r.Item,{name:"remember",valuePropName:"checked",noStyle:!0,children:e.jsx(U,{children:a("login.rememberMe")})})}),e.jsx(r.Item,{children:e.jsx(f,{type:"primary",htmlType:"submit",loading:u,block:!0,size:"large",className:"login-submit-btn",children:a(u?"login.loggingIn":"login.submit")})})]})]})})]})})})})]})}export{A as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
import{j as e,m as N,n as I,u as R,T as $,o as c,p as k,B as o,q as w,t as T,v as C,w as M,R as S,S as _}from"./index-BGI3tmtB.js";import{P as D}from"./index-xsV5o4zp.js";import{T as l}from"./index-bzjak6Z4.js";import{R as h,C as r}from"./row-C3H8lbGw.js";import{C as p}from"./index-DxgbQv5l.js";import{F as E}from"./Table-BewG91sh.js";import"./iconUtil-IZQuqZwd.js";import"./index-DUXqiKOh.js";import"./useForm-BpWJqkw6.js";import"./index-DJxTfCUX.js";import"./Pagination-COOq01L8.js";function n({title:a,value:d,icon:i,color:s="blue",trend:t,suffix:u="",layout:b="column",gridColumn:m,className:f="",onClick:g,style:v={}}){const x={blue:"#1677ff",green:"#52c41a",orange:"#faad14",red:"#ff4d4f",purple:"#722ed1",gray:"#8c8c8c"}[s]||s,y={...m?{gridColumn:m}:{},...v};return e.jsxs("div",{className:`stat-card stat-card-${b} ${f}`,style:y,onClick:g,children:[e.jsxs("div",{className:"stat-card-header",children:[e.jsx("span",{className:"stat-card-title",children:a}),i&&e.jsx("span",{className:"stat-card-icon",style:{color:x},"aria-hidden":"true",children:i})]}),e.jsxs("div",{className:"stat-card-body",children:[e.jsxs("div",{className:"stat-card-value tabular-nums",style:{color:x},children:[d,u&&e.jsx("span",{className:"stat-card-suffix",children:u})]}),t&&e.jsxs("div",{className:`stat-card-trend ${t.direction==="up"?"trend-up":"trend-down"} tabular-nums`,"aria-label":`${t.direction==="up"?"Increase":"Decrease"} of ${t.value}%`,children:[t.direction==="up"?e.jsx(N,{"aria-hidden":"true"}):e.jsx(I,{"aria-hidden":"true"}),e.jsxs("span",{children:[Math.abs(t.value),"%"]})]})]})]})}const{Text:j}=$;function O(){const{t:a}=R(),d=[{key:"1",name:"Product Sync",time:"2024-02-10 14:00",duration:"45min",status:"processing"},{key:"2",name:"Tech Review",time:"2024-02-10 10:00",duration:"60min",status:"success"},{key:"3",name:"Daily Standup",time:"2024-02-10 09:00",duration:"15min",status:"success"},{key:"4",name:"Client Call",time:"2024-02-10 16:30",duration:"30min",status:"default"}],i=[{title:a("dashboard.meetingName"),dataIndex:"name",key:"name",render:s=>e.jsx(j,{strong:!0,children:s})},{title:a("dashboard.startTime"),dataIndex:"time",key:"time",className:"tabular-nums",render:s=>e.jsx(j,{type:"secondary",children:s})},{title:a("dashboard.duration"),dataIndex:"duration",key:"duration",width:100,className:"tabular-nums"},{title:a("common.status"),dataIndex:"status",key:"status",width:120,render:s=>s==="processing"?e.jsx(l,{icon:e.jsx(c,{spin:!0,"aria-hidden":"true"}),color:"processing",children:a("dashboardExt.processing")}):s==="success"?e.jsx(l,{icon:e.jsx(k,{"aria-hidden":"true"}),color:"success",children:a("dashboardExt.completed")}):e.jsx(l,{color:"default",children:a("dashboardExt.pending")})},{title:a("common.action"),key:"action",width:80,render:()=>e.jsx(o,{type:"link",size:"small",icon:e.jsx(w,{"aria-hidden":"true"}),"aria-label":a("dashboard.viewAll")})}];return e.jsxs("div",{className:"app-page dashboard-page",children:[e.jsx(D,{title:a("dashboard.title"),subtitle:a("dashboard.subtitle")}),e.jsx("div",{className:"app-page__page-actions",children:e.jsx(o,{icon:e.jsx(c,{"aria-hidden":"true"}),size:"small",children:a("common.refresh")})}),e.jsxs(h,{gutter:[24,24],children:[e.jsx(r,{xs:24,sm:12,lg:6,children:e.jsx(n,{title:a("dashboard.todayMeetings"),value:12,icon:e.jsx(T,{"aria-hidden":"true"}),color:"blue",trend:{value:8,direction:"up"}})}),e.jsx(r,{xs:24,sm:12,lg:6,children:e.jsx(n,{title:a("dashboard.activeDevices"),value:45,icon:e.jsx(C,{"aria-hidden":"true"}),color:"green",trend:{value:2,direction:"up"}})}),e.jsx(r,{xs:24,sm:12,lg:6,children:e.jsx(n,{title:a("dashboard.transcriptionDuration"),value:1280,suffix:"min",icon:e.jsx(M,{"aria-hidden":"true"}),color:"orange",trend:{value:5,direction:"down"}})}),e.jsx(r,{xs:24,sm:12,lg:6,children:e.jsx(n,{title:a("dashboard.totalUsers"),value:320,icon:e.jsx(S,{"aria-hidden":"true"}),color:"purple",trend:{value:12,direction:"up"}})})]}),e.jsxs(h,{gutter:[24,24],className:"mt-6",children:[e.jsx(r,{xs:24,xl:16,children:e.jsx(p,{title:a("dashboard.recentMeetings"),variant:"borderless",className:"app-page__content-card",extra:e.jsx(o,{type:"link",size:"small",children:a("dashboard.viewAll")}),styles:{body:{padding:0}},children:e.jsx(E,{dataSource:d,columns:i,pagination:!1,size:"middle",className:"roles-table"})})}),e.jsx(r,{xs:24,xl:8,children:e.jsx(p,{title:a("dashboard.deviceLoad"),variant:"borderless",className:"app-page__content-card",children:e.jsxs("div",{className:"flex flex-col items-center justify-center py-12",children:[e.jsx(_,{active:!0,paragraph:{rows:4}}),e.jsxs("div",{className:"mt-4 text-gray-400 flex items-center gap-2",children:[e.jsx(c,{spin:!0,"aria-hidden":"true"}),e.jsx("span",{children:a("dashboardExt.chartLoading")})]})]})})})]})]})}export{O as default};

View File

@ -1 +0,0 @@
import{j as e,m as N,n as I,u as R,T as $,o as c,p as k,B as l,q as w,t as T,v as C,w as M,R as S,S as _}from"./index-2nzO_M0d.js";import{P as D}from"./index-Ds3G3GDW.js";import{T as o}from"./index-CASbXnpp.js";import{R as h,C as r}from"./row-CR991LIl.js";import{C as p}from"./index-ESbS3nHt.js";import{F as E}from"./Table-UD3nj3r6.js";import"./useForm-CzLkm9RK.js";import"./index-z7YG9RTL.js";import"./Pagination-CRtRHhmu.js";function d({title:a,value:n,icon:i,color:s="blue",trend:t,suffix:u="",layout:f="column",gridColumn:m,className:b="",onClick:g,style:y={}}){const x={blue:"#1677ff",green:"#52c41a",orange:"#faad14",red:"#ff4d4f",purple:"#722ed1",gray:"#8c8c8c"}[s]||s,v={...m?{gridColumn:m}:{},...y};return e.jsxs("div",{className:`stat-card stat-card-${f} ${b}`,style:v,onClick:g,children:[e.jsxs("div",{className:"stat-card-header",children:[e.jsx("span",{className:"stat-card-title",children:a}),i&&e.jsx("span",{className:"stat-card-icon",style:{color:x},"aria-hidden":"true",children:i})]}),e.jsxs("div",{className:"stat-card-body",children:[e.jsxs("div",{className:"stat-card-value tabular-nums",style:{color:x},children:[n,u&&e.jsx("span",{className:"stat-card-suffix",children:u})]}),t&&e.jsxs("div",{className:`stat-card-trend ${t.direction==="up"?"trend-up":"trend-down"} tabular-nums`,"aria-label":`${t.direction==="up"?"Increase":"Decrease"} of ${t.value}%`,children:[t.direction==="up"?e.jsx(N,{"aria-hidden":"true"}):e.jsx(I,{"aria-hidden":"true"}),e.jsxs("span",{children:[Math.abs(t.value),"%"]})]})]})]})}const{Text:j}=$;function J(){const{t:a}=R(),n=[{key:"1",name:"Product Sync",time:"2024-02-10 14:00",duration:"45min",status:"processing"},{key:"2",name:"Tech Review",time:"2024-02-10 10:00",duration:"60min",status:"success"},{key:"3",name:"Daily Standup",time:"2024-02-10 09:00",duration:"15min",status:"success"},{key:"4",name:"Client Call",time:"2024-02-10 16:30",duration:"30min",status:"default"}],i=[{title:a("dashboard.meetingName"),dataIndex:"name",key:"name",render:s=>e.jsx(j,{strong:!0,children:s})},{title:a("dashboard.startTime"),dataIndex:"time",key:"time",className:"tabular-nums",render:s=>e.jsx(j,{type:"secondary",children:s})},{title:a("dashboard.duration"),dataIndex:"duration",key:"duration",width:100,className:"tabular-nums"},{title:a("common.status"),dataIndex:"status",key:"status",width:120,render:s=>s==="processing"?e.jsx(o,{icon:e.jsx(c,{spin:!0,"aria-hidden":"true"}),color:"processing",children:a("dashboardExt.processing")}):s==="success"?e.jsx(o,{icon:e.jsx(k,{"aria-hidden":"true"}),color:"success",children:a("dashboardExt.completed")}):e.jsx(o,{color:"default",children:a("dashboardExt.pending")})},{title:a("common.action"),key:"action",width:80,render:()=>e.jsx(l,{type:"link",size:"small",icon:e.jsx(w,{"aria-hidden":"true"}),"aria-label":a("dashboard.viewAll")})}];return e.jsxs("div",{className:"app-page dashboard-page",children:[e.jsx(D,{title:a("dashboard.title"),subtitle:a("dashboard.subtitle")}),e.jsx("div",{className:"app-page__page-actions",children:e.jsx(l,{icon:e.jsx(c,{"aria-hidden":"true"}),size:"small",children:a("common.refresh")})}),e.jsxs(h,{gutter:[24,24],children:[e.jsx(r,{xs:24,sm:12,lg:6,children:e.jsx(d,{title:a("dashboard.todayMeetings"),value:12,icon:e.jsx(T,{"aria-hidden":"true"}),color:"blue",trend:{value:8,direction:"up"}})}),e.jsx(r,{xs:24,sm:12,lg:6,children:e.jsx(d,{title:a("dashboard.activeDevices"),value:45,icon:e.jsx(C,{"aria-hidden":"true"}),color:"green",trend:{value:2,direction:"up"}})}),e.jsx(r,{xs:24,sm:12,lg:6,children:e.jsx(d,{title:a("dashboard.transcriptionDuration"),value:1280,suffix:"min",icon:e.jsx(M,{"aria-hidden":"true"}),color:"orange",trend:{value:5,direction:"down"}})}),e.jsx(r,{xs:24,sm:12,lg:6,children:e.jsx(d,{title:a("dashboard.totalUsers"),value:320,icon:e.jsx(S,{"aria-hidden":"true"}),color:"purple",trend:{value:12,direction:"up"}})})]}),e.jsxs(h,{gutter:[24,24],className:"mt-6",children:[e.jsx(r,{xs:24,xl:16,children:e.jsx(p,{title:a("dashboard.recentMeetings"),bordered:!1,className:"app-page__content-card",extra:e.jsx(l,{type:"link",size:"small",children:a("dashboard.viewAll")}),styles:{body:{padding:0}},children:e.jsx(E,{dataSource:n,columns:i,pagination:!1,size:"middle",className:"roles-table"})})}),e.jsx(r,{xs:24,xl:8,children:e.jsx(p,{title:a("dashboard.deviceLoad"),bordered:!1,className:"app-page__content-card",children:e.jsxs("div",{className:"flex flex-col items-center justify-center py-12",children:[e.jsx(_,{active:!0,paragraph:{rows:4}}),e.jsxs("div",{className:"mt-4 text-gray-400 flex items-center gap-2",children:[e.jsx(c,{spin:!0,"aria-hidden":"true"}),e.jsx("span",{children:a("dashboardExt.chartLoading")})]})]})})})]})]})}export{J as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
import{r as u,h as p,j as e,L as f,a as o,T as j,B as l,i as w,k as y,s as g}from"./index-2nzO_M0d.js";import{F as s}from"./index-BNTgrN92.js";import{C as h}from"./index-ESbS3nHt.js";import{I as a}from"./index-fAufRegR.js";import"./useForm-CzLkm9RK.js";import"./row-CR991LIl.js";const{Title:P,Text:b}=j;function F(){const[d,t]=u.useState(!1),c=p(),[m]=s.useForm(),n=()=>{localStorage.clear(),sessionStorage.clear(),c("/login")},x=async r=>{t(!0);try{await y({oldPassword:r.oldPassword,newPassword:r.newPassword}),g.success("密码已更新,请重新登录"),n()}finally{t(!1)}};return e.jsx(f,{style:{minHeight:"100vh",background:"#f0f2f5",display:"flex",alignItems:"center",justifyContent:"center"},children:e.jsxs(h,{style:{width:420,borderRadius:8,boxShadow:"0 4px 12px rgba(0,0,0,0.1)"},children:[e.jsxs("div",{className:"text-center mb-6",children:[e.jsx(o,{style:{fontSize:40,color:"#1890ff"}}),e.jsx(P,{level:3,style:{marginTop:16},children:"首次登录请修改密码"}),e.jsx(b,{type:"secondary",children:"当前账号被要求更新初始密码,提交成功后会跳转到登录页。"})]}),e.jsxs(s,{form:m,layout:"vertical",onFinish:x,children:[e.jsx(s.Item,{label:"当前密码",name:"oldPassword",rules:[{required:!0,message:"请输入当前密码"}],children:e.jsx(a.Password,{prefix:e.jsx(o,{})})}),e.jsx(s.Item,{label:"新密码",name:"newPassword",rules:[{required:!0,min:6,message:"新密码至少 6 位"}],children:e.jsx(a.Password,{prefix:e.jsx(o,{})})}),e.jsx(s.Item,{label:"确认新密码",name:"confirmPassword",dependencies:["newPassword"],rules:[{required:!0,message:"请再次输入新密码"},({getFieldValue:r})=>({validator(T,i){return!i||r("newPassword")===i?Promise.resolve():Promise.reject(new Error("两次输入的新密码不一致"))}})],children:e.jsx(a.Password,{prefix:e.jsx(o,{})})}),e.jsx(l,{type:"primary",htmlType:"submit",block:!0,size:"large",loading:d,style:{marginTop:8},children:"提交并重新登录"}),e.jsx(l,{type:"link",block:!0,icon:e.jsx(w,{}),onClick:n,style:{marginTop:8},children:"退出登录"})]})]})})}export{F as default}; import{r as u,h as p,j as e,L as f,a as o,T as j,B as l,i as w,k as y,s as g}from"./index-BGI3tmtB.js";import{F as s}from"./index-BuOmEnKg.js";import{C as h}from"./index-DxgbQv5l.js";import{I as a}from"./index-FqFqpoYX.js";import"./useForm-BpWJqkw6.js";import"./row-C3H8lbGw.js";const{Title:P,Text:b}=j;function F(){const[d,t]=u.useState(!1),c=p(),[m]=s.useForm(),n=()=>{localStorage.clear(),sessionStorage.clear(),c("/login")},x=async r=>{t(!0);try{await y({oldPassword:r.oldPassword,newPassword:r.newPassword}),g.success("密码已更新,请重新登录"),n()}finally{t(!1)}};return e.jsx(f,{style:{minHeight:"100vh",background:"#f0f2f5",display:"flex",alignItems:"center",justifyContent:"center"},children:e.jsxs(h,{style:{width:420,borderRadius:8,boxShadow:"0 4px 12px rgba(0,0,0,0.1)"},children:[e.jsxs("div",{className:"text-center mb-6",children:[e.jsx(o,{style:{fontSize:40,color:"#1890ff"}}),e.jsx(P,{level:3,style:{marginTop:16},children:"首次登录请修改密码"}),e.jsx(b,{type:"secondary",children:"当前账号被要求更新初始密码,提交成功后会跳转到登录页。"})]}),e.jsxs(s,{form:m,layout:"vertical",onFinish:x,children:[e.jsx(s.Item,{label:"当前密码",name:"oldPassword",rules:[{required:!0,message:"请输入当前密码"}],children:e.jsx(a.Password,{prefix:e.jsx(o,{})})}),e.jsx(s.Item,{label:"新密码",name:"newPassword",rules:[{required:!0,min:6,message:"新密码至少 6 位"}],children:e.jsx(a.Password,{prefix:e.jsx(o,{})})}),e.jsx(s.Item,{label:"确认新密码",name:"confirmPassword",dependencies:["newPassword"],rules:[{required:!0,message:"请再次输入新密码"},({getFieldValue:r})=>({validator(T,i){return!i||r("newPassword")===i?Promise.resolve():Promise.reject(new Error("两次输入的新密码不一致"))}})],children:e.jsx(a.Password,{prefix:e.jsx(o,{})})}),e.jsx(l,{type:"primary",htmlType:"submit",block:!0,size:"large",loading:d,style:{marginTop:8},children:"提交并重新登录"}),e.jsx(l,{type:"link",block:!0,icon:e.jsx(w,{}),onClick:n,style:{marginTop:8},children:"退出登录"})]})]})})}export{F as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
import{aq as A,r as s,cO as $,an as w,bw as F,bx as D,d9 as E,B as M,da as U,db as Y,dc as G,ao as S,au as J,bv as K,dd as Q,a$ as Z}from"./index-BGI3tmtB.js";const ee=e=>{const{componentCls:n,iconCls:a,antCls:t,zIndexPopup:o,colorText:u,colorWarning:f,marginXXS:c,marginXS:i,fontSize:g,fontWeightStrong:v,colorTextHeading:y}=e;return{[n]:{zIndex:o,[`&${t}-popover`]:{fontSize:g},[`${n}-message`]:{marginBottom:i,display:"flex",flexWrap:"nowrap",alignItems:"start",[`> ${n}-message-icon ${a}`]:{color:f,fontSize:g,lineHeight:1,marginInlineEnd:i},[`${n}-title`]:{fontWeight:v,color:y,"&:only-child":{fontWeight:"normal"}},[`${n}-description`]:{marginTop:c,color:u}},[`${n}-buttons`]:{textAlign:"end",whiteSpace:"nowrap",button:{marginInlineStart:i}}}}},te=e=>{const{zIndexPopupBase:n}=e;return{zIndexPopup:n+60}},I=A("Popconfirm",e=>ee(e),te,{resetStyle:!1});var ne=function(e,n){var a={};for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&n.indexOf(t)<0&&(a[t]=e[t]);if(e!=null&&typeof Object.getOwnPropertySymbols=="function")for(var o=0,t=Object.getOwnPropertySymbols(e);o<t.length;o++)n.indexOf(t[o])<0&&Object.prototype.propertyIsEnumerable.call(e,t[o])&&(a[t[o]]=e[t[o]]);return a};const k=e=>{const{prefixCls:n,okButtonProps:a,cancelButtonProps:t,title:o,description:u,cancelText:f,okText:c,okType:i="primary",icon:g=s.createElement($,null),showCancel:v=!0,close:y,onConfirm:C,onCancel:O,onPopupClick:m}=e,{getPrefixCls:p}=s.useContext(w),[d]=F("Popconfirm",D.Popconfirm),b=E(o),x=E(u);return s.createElement("div",{className:`${n}-inner-content`,onClick:m},s.createElement("div",{className:`${n}-message`},g&&s.createElement("span",{className:`${n}-message-icon`},g),s.createElement("div",{className:`${n}-message-text`},b&&s.createElement("div",{className:`${n}-title`},b),x&&s.createElement("div",{className:`${n}-description`},x))),s.createElement("div",{className:`${n}-buttons`},v&&s.createElement(M,Object.assign({onClick:O,size:"small"},t),f||(d==null?void 0:d.cancelText)),s.createElement(U,{buttonProps:Object.assign(Object.assign({size:"small"},Y(i)),a),actionFn:C,close:y,prefixCls:p("btn"),quitOnNullishReturnValue:!0,emitEvent:!0},c||(d==null?void 0:d.okText))))},oe=e=>{const{prefixCls:n,placement:a,className:t,style:o}=e,u=ne(e,["prefixCls","placement","className","style"]),{getPrefixCls:f}=s.useContext(w),c=f("popconfirm",n),[i]=I(c);return i(s.createElement(G,{placement:a,className:S(c,t),style:o,content:s.createElement(k,Object.assign({prefixCls:c},u))}))};var se=function(e,n){var a={};for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&n.indexOf(t)<0&&(a[t]=e[t]);if(e!=null&&typeof Object.getOwnPropertySymbols=="function")for(var o=0,t=Object.getOwnPropertySymbols(e);o<t.length;o++)n.indexOf(t[o])<0&&Object.prototype.propertyIsEnumerable.call(e,t[o])&&(a[t[o]]=e[t[o]]);return a};const ae=s.forwardRef((e,n)=>{var a,t;const{prefixCls:o,placement:u="top",trigger:f="click",okType:c="primary",icon:i=s.createElement($,null),children:g,overlayClassName:v,onOpenChange:y,onVisibleChange:C,overlayStyle:O,styles:m,classNames:p}=e,d=se(e,["prefixCls","placement","trigger","okType","icon","children","overlayClassName","onOpenChange","onVisibleChange","overlayStyle","styles","classNames"]),{getPrefixCls:b,className:x,style:T,classNames:j,styles:h}=J("popconfirm"),[_,z]=K(!1,{value:(a=e.open)!==null&&a!==void 0?a:e.visible,defaultValue:(t=e.defaultOpen)!==null&&t!==void 0?t:e.defaultVisible}),P=(l,r)=>{z(l,!0),C==null||C(l),y==null||y(l,r)},B=l=>{P(!1,l)},V=l=>{var r;return(r=e.onConfirm)===null||r===void 0?void 0:r.call(void 0,l)},W=l=>{var r;P(!1,l),(r=e.onCancel)===null||r===void 0||r.call(void 0,l)},R=(l,r)=>{const{disabled:q=!1}=e;q||P(l,r)},N=b("popconfirm",o),H=S(N,x,v,j.root,p==null?void 0:p.root),L=S(j.body,p==null?void 0:p.body),[X]=I(N);return X(s.createElement(Q,Object.assign({},Z(d,["title"]),{trigger:f,placement:u,onOpenChange:R,open:_,ref:n,classNames:{root:H,body:L},styles:{root:Object.assign(Object.assign(Object.assign(Object.assign({},h.root),T),O),m==null?void 0:m.root),body:Object.assign(Object.assign({},h.body),m==null?void 0:m.body)},content:s.createElement(k,Object.assign({okType:c,icon:i},e,{prefixCls:N,close:B,onConfirm:V,onCancel:W})),"data-popover-inject":!0}),g))}),le=ae;le._InternalPanelDoNotUseOrYouWillBeFired=oe;export{le as P};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
import{am as X,r as a,an as A,cf as Z,bu as J,cM as Q,ce as B,ao as w,dZ as U,d4 as Y,a$ as ee,ax as z}from"./index-BGI3tmtB.js";import{u as D,a as te,C as se}from"./index-DUXqiKOh.js";const T=X.createContext(null);var ae=function(l,u){var o={};for(var t in l)Object.prototype.hasOwnProperty.call(l,t)&&u.indexOf(t)<0&&(o[t]=l[t]);if(l!=null&&typeof Object.getOwnPropertySymbols=="function")for(var n=0,t=Object.getOwnPropertySymbols(l);n<t.length;n++)u.indexOf(t[n])<0&&Object.prototype.propertyIsEnumerable.call(l,t[n])&&(o[t[n]]=l[t[n]]);return o};const le=(l,u)=>{var o;const{prefixCls:t,className:n,rootClassName:$,children:x,indeterminate:h=!1,style:j,onMouseEnter:y,onMouseLeave:c,skipGroup:O=!1,disabled:I}=l,r=ae(l,["prefixCls","className","rootClassName","children","indeterminate","style","onMouseEnter","onMouseLeave","skipGroup","disabled"]),{getPrefixCls:k,direction:_,checkbox:d}=a.useContext(A),s=a.useContext(T),{isFormItemInput:E}=a.useContext(Z),N=a.useContext(J),g=(o=(s==null?void 0:s.disabled)||I)!==null&&o!==void 0?o:N,m=a.useRef(r.value),p=a.useRef(null),V=Q(u,p);a.useEffect(()=>{s==null||s.registerValue(r.value)},[]),a.useEffect(()=>{if(!O)return r.value!==m.current&&(s==null||s.cancelValue(m.current),s==null||s.registerValue(r.value),m.current=r.value),()=>s==null?void 0:s.cancelValue(r.value)},[r.value]),a.useEffect(()=>{var f;!((f=p.current)===null||f===void 0)&&f.input&&(p.current.input.indeterminate=h)},[h]);const i=k("checkbox",t),S=B(i),[R,P,G]=D(i,S),v=Object.assign({},r);s&&!O&&(v.onChange=(...f)=>{r.onChange&&r.onChange.apply(r,f),s.toggleOption&&s.toggleOption({label:x,value:r.value})},v.name=s.name,v.checked=s.value.includes(r.value));const M=w(`${i}-wrapper`,{[`${i}-rtl`]:_==="rtl",[`${i}-wrapper-checked`]:v.checked,[`${i}-wrapper-disabled`]:g,[`${i}-wrapper-in-form-item`]:E},d==null?void 0:d.className,n,$,G,S,P),e=w({[`${i}-indeterminate`]:h},U,P),[C,b]=te(v.onClick);return R(a.createElement(Y,{component:"Checkbox",disabled:g},a.createElement("label",{className:M,style:Object.assign(Object.assign({},d==null?void 0:d.style),j),onMouseEnter:y,onMouseLeave:c,onClick:C},a.createElement(se,Object.assign({},v,{onClick:b,prefixCls:i,className:e,disabled:g,ref:V})),x!=null&&a.createElement("span",{className:`${i}-label`},x))))},q=a.forwardRef(le);var ne=function(l,u){var o={};for(var t in l)Object.prototype.hasOwnProperty.call(l,t)&&u.indexOf(t)<0&&(o[t]=l[t]);if(l!=null&&typeof Object.getOwnPropertySymbols=="function")for(var n=0,t=Object.getOwnPropertySymbols(l);n<t.length;n++)u.indexOf(t[n])<0&&Object.prototype.propertyIsEnumerable.call(l,t[n])&&(o[t[n]]=l[t[n]]);return o};const re=a.forwardRef((l,u)=>{const{defaultValue:o,children:t,options:n=[],prefixCls:$,className:x,rootClassName:h,style:j,onChange:y}=l,c=ne(l,["defaultValue","children","options","prefixCls","className","rootClassName","style","onChange"]),{getPrefixCls:O,direction:I}=a.useContext(A),[r,k]=a.useState(c.value||o||[]),[_,d]=a.useState([]);a.useEffect(()=>{"value"in c&&k(c.value||[])},[c.value]);const s=a.useMemo(()=>n.map(e=>typeof e=="string"||typeof e=="number"?{label:e,value:e}:e),[n]),E=e=>{d(C=>C.filter(b=>b!==e))},N=e=>{d(C=>[].concat(z(C),[e]))},g=e=>{const C=r.indexOf(e.value),b=z(r);C===-1?b.push(e.value):b.splice(C,1),"value"in c||k(b),y==null||y(b.filter(f=>_.includes(f)).sort((f,H)=>{const K=s.findIndex(L=>L.value===f),W=s.findIndex(L=>L.value===H);return K-W}))},m=O("checkbox",$),p=`${m}-group`,V=B(m),[i,S,R]=D(m,V),P=ee(c,["value","disabled"]),G=n.length?s.map(e=>a.createElement(q,{prefixCls:m,key:e.value.toString(),disabled:"disabled"in e?e.disabled:c.disabled,value:e.value,checked:r.includes(e.value),onChange:e.onChange,className:w(`${p}-item`,e.className),style:e.style,title:e.title,id:e.id,required:e.required},e.label)):t,v=a.useMemo(()=>({toggleOption:g,value:r,disabled:c.disabled,name:c.name,registerValue:N,cancelValue:E}),[g,r,c.disabled,c.name,N,E]),M=w(p,{[`${p}-rtl`]:I==="rtl"},x,h,R,V,S);return i(a.createElement("div",Object.assign({className:M,style:j},P,{ref:u}),a.createElement(T.Provider,{value:v},G)))}),F=q;F.Group=re;F.__ANT_CHECKBOX=!0;export{F as C};

View File

@ -0,0 +1,7 @@
import{r as t,aW as I,bv as j,aS as L,ao as M,bc as v,aX as N,aV as y,am as T,bM as x,ar as H,aq as O,at as u,as as S,e0 as W}from"./index-BGI3tmtB.js";var q=["prefixCls","className","style","checked","disabled","defaultChecked","type","title","onChange"],G=t.forwardRef(function(e,r){var a=e.prefixCls,i=a===void 0?"rc-checkbox":a,b=e.className,l=e.style,w=e.checked,s=e.disabled,p=e.defaultChecked,R=p===void 0?!1:p,h=e.type,f=h===void 0?"checkbox":h,P=e.title,d=e.onChange,_=I(e,q),c=t.useRef(null),g=t.useRef(null),D=j(R,{value:w}),$=L(D,2),C=$[0],z=$[1];t.useImperativeHandle(r,function(){return{focus:function(o){var n;(n=c.current)===null||n===void 0||n.focus(o)},blur:function(){var o;(o=c.current)===null||o===void 0||o.blur()},input:c.current,nativeElement:g.current}});var B=M(i,b,v(v({},"".concat(i,"-checked"),C),"".concat(i,"-disabled"),s)),E=function(o){s||("checked"in e||z(o.target.checked),d==null||d({target:y(y({},e),{},{type:f,checked:o.target.checked}),stopPropagation:function(){o.stopPropagation()},preventDefault:function(){o.preventDefault()},nativeEvent:o.nativeEvent}))};return t.createElement("span",{className:B,title:P,style:l,ref:g},t.createElement("input",N({},_,{className:"".concat(i,"-input"),ref:c,onChange:E,disabled:s,checked:!!C,type:f})),t.createElement("span",{className:"".concat(i,"-inner")}))});function V(e){const r=T.useRef(null),a=()=>{x.cancel(r.current),r.current=null};return[()=>{a(),r.current=x(()=>{r.current=null})},l=>{r.current&&(l.stopPropagation(),a()),e==null||e(l)}]}const F=e=>{const{checkboxCls:r}=e,a=`${r}-wrapper`;return[{[`${r}-group`]:Object.assign(Object.assign({},u(e)),{display:"inline-flex",flexWrap:"wrap",columnGap:e.marginXS,[`> ${e.antCls}-row`]:{flex:1}}),[a]:Object.assign(Object.assign({},u(e)),{display:"inline-flex",alignItems:"baseline",cursor:"pointer","&:after":{display:"inline-block",width:0,overflow:"hidden",content:"'\\a0'"},[`& + ${a}`]:{marginInlineStart:0},[`&${a}-in-form-item`]:{'input[type="checkbox"]':{width:14,height:14}}}),[r]:Object.assign(Object.assign({},u(e)),{position:"relative",whiteSpace:"nowrap",lineHeight:1,cursor:"pointer",borderRadius:e.borderRadiusSM,alignSelf:"center",[`${r}-input`]:{position:"absolute",inset:0,zIndex:1,cursor:"pointer",opacity:0,margin:0,[`&:focus-visible + ${r}-inner`]:W(e)},[`${r}-inner`]:{boxSizing:"border-box",display:"block",width:e.checkboxSize,height:e.checkboxSize,direction:"ltr",backgroundColor:e.colorBgContainer,border:`${S(e.lineWidth)} ${e.lineType} ${e.colorBorder}`,borderRadius:e.borderRadiusSM,borderCollapse:"separate",transition:`all ${e.motionDurationSlow}`,"&:after":{boxSizing:"border-box",position:"absolute",top:"50%",insetInlineStart:"25%",display:"table",width:e.calc(e.checkboxSize).div(14).mul(5).equal(),height:e.calc(e.checkboxSize).div(14).mul(8).equal(),border:`${S(e.lineWidthBold)} solid ${e.colorWhite}`,borderTop:0,borderInlineStart:0,transform:"rotate(45deg) scale(0) translate(-50%,-50%)",opacity:0,content:'""',transition:`all ${e.motionDurationFast} ${e.motionEaseInBack}, opacity ${e.motionDurationFast}`}},"& + span":{paddingInlineStart:e.paddingXS,paddingInlineEnd:e.paddingXS}})},{[`
${a}:not(${a}-disabled),
${r}:not(${r}-disabled)
`]:{[`&:hover ${r}-inner`]:{borderColor:e.colorPrimary}},[`${a}:not(${a}-disabled)`]:{[`&:hover ${r}-checked:not(${r}-disabled) ${r}-inner`]:{backgroundColor:e.colorPrimaryHover,borderColor:"transparent"},[`&:hover ${r}-checked:not(${r}-disabled):after`]:{borderColor:e.colorPrimaryHover}}},{[`${r}-checked`]:{[`${r}-inner`]:{backgroundColor:e.colorPrimary,borderColor:e.colorPrimary,"&:after":{opacity:1,transform:"rotate(45deg) scale(1) translate(-50%,-50%)",transition:`all ${e.motionDurationMid} ${e.motionEaseOutBack} ${e.motionDurationFast}`}}},[`
${a}-checked:not(${a}-disabled),
${r}-checked:not(${r}-disabled)
`]:{[`&:hover ${r}-inner`]:{backgroundColor:e.colorPrimaryHover,borderColor:"transparent"}}},{[r]:{"&-indeterminate":{"&":{[`${r}-inner`]:{backgroundColor:`${e.colorBgContainer}`,borderColor:`${e.colorBorder}`,"&:after":{top:"50%",insetInlineStart:"50%",width:e.calc(e.fontSizeLG).div(2).equal(),height:e.calc(e.fontSizeLG).div(2).equal(),backgroundColor:e.colorPrimary,border:0,transform:"translate(-50%, -50%) scale(1)",opacity:1,content:'""'}},[`&:hover ${r}-inner`]:{backgroundColor:`${e.colorBgContainer}`,borderColor:`${e.colorPrimary}`}}}}},{[`${a}-disabled`]:{cursor:"not-allowed"},[`${r}-disabled`]:{[`&, ${r}-input`]:{cursor:"not-allowed",pointerEvents:"none"},[`${r}-inner`]:{background:e.colorBgContainerDisabled,borderColor:e.colorBorder,"&:after":{borderColor:e.colorTextDisabled}},"&:after":{display:"none"},"& + span":{color:e.colorTextDisabled},[`&${r}-indeterminate ${r}-inner::after`]:{background:e.colorTextDisabled}}}]};function X(e,r){const a=H(r,{checkboxCls:`.${e}`,checkboxSize:r.controlInteractiveSize});return F(a)}const A=O("Checkbox",(e,{prefixCls:r})=>[X(r,e)]);export{G as C,V as a,X as g,A as u};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
import{u as v,r,f as S,s as x,j as e,T as k,R as C,a as T,b as P,B as f,c as R,g as B,d as E,l as z,e as L}from"./index-BGI3tmtB.js";import{F as l}from"./index-BuOmEnKg.js";import{I as m}from"./index-FqFqpoYX.js";import{C as U}from"./index-DJxTfCUX.js";import"./useForm-BpWJqkw6.js";import"./row-C3H8lbGw.js";import"./index-DUXqiKOh.js";const{Text:q}=k;function D(){const{t:a}=v(),[i,j]=r.useState(null),[o,g]=r.useState(!0),[u,h]=r.useState(!1),[t,b]=r.useState(null),[y]=l.useForm(),N="汇智CRM管理后台",c=r.useCallback(async()=>{if(!o)return;const s=await S();j(s)},[o]);r.useEffect(()=>{(async()=>{try{const[n,d]=await Promise.all([B("security.captcha.enabled","true"),E()]);b(d);const p=n!=="false";g(p),p&&await c()}catch{g(!0),await c()}})()},[c]),r.useEffect(()=>{new URLSearchParams(window.location.search).get("timeout")==="1"&&(x.warning(a("login.loginTimeout")),window.history.replaceState({},document.title,window.location.pathname))},[a]);const w=async s=>{h(!0);try{const n=await z({username:s.username,password:s.password,tenantCode:s.tenantCode,captchaId:o?i==null?void 0:i.captchaId:void 0,captchaCode:o?s.captchaCode:void 0});if(localStorage.setItem("accessToken",n.accessToken),localStorage.setItem("refreshToken",n.refreshToken),localStorage.setItem("username",s.username),n.availableTenants){localStorage.setItem("availableTenants",JSON.stringify(n.availableTenants));const d=JSON.parse(atob(n.accessToken.split(".")[1]));localStorage.setItem("activeTenantId",String(d.tenantId))}try{const d=await L();sessionStorage.setItem("userProfile",JSON.stringify(d))}catch{sessionStorage.removeItem("userProfile")}x.success(a("common.success")),window.location.href="/"}catch{o&&await c()}finally{h(!1)}},I=t!=null&&t.loginBgUrl?{backgroundImage:`url(${t.loginBgUrl})`,backgroundSize:"cover",backgroundPosition:"center",position:"relative"}:{};return e.jsxs("div",{className:"login-page",style:I,children:[e.jsx("div",{className:"login-page-backdrop"}),e.jsx("div",{className:"login-page-grid",children:e.jsx("section",{className:"login-panel",children:e.jsx("div",{className:"login-panel-card",children:e.jsxs("div",{className:"login-panel-layout",children:[e.jsx("div",{className:"login-left",children:e.jsxs("div",{className:"login-brand",children:[e.jsx("div",{className:"brand-logo-wrap",children:e.jsx("img",{src:(t==null?void 0:t.logoUrl)||"/logo.svg",alt:"Logo",className:"brand-logo-img"})}),e.jsxs("div",{className:"brand-copy",children:[e.jsx("p",{className:"brand-kicker",children:"智慧销售协同平台"}),e.jsx("span",{className:"brand-name",children:N})]})]})}),e.jsx("div",{className:"login-right",children:e.jsxs("div",{className:"login-container",children:[e.jsxs("div",{className:"login-header",children:[e.jsx("p",{className:"login-panel-eyebrow",children:a("login.welcome")}),e.jsx(q,{type:"secondary",children:a("login.subtitle")})]}),e.jsxs(l,{form:y,layout:"vertical",onFinish:w,className:"login-form",requiredMark:!1,autoComplete:"off",children:[e.jsx(l.Item,{name:"username",rules:[{required:!0,message:a("login.username")}],children:e.jsx(m,{size:"large",prefix:e.jsx(C,{className:"text-gray-400","aria-hidden":"true"}),placeholder:a("login.username"),autoComplete:"username",spellCheck:!1,"aria-label":a("login.username")})}),e.jsx(l.Item,{name:"password",rules:[{required:!0,message:a("login.password")}],children:e.jsx(m.Password,{size:"large",prefix:e.jsx(T,{className:"text-gray-400","aria-hidden":"true"}),placeholder:a("login.password"),autoComplete:"current-password","aria-label":a("login.password")})}),o?e.jsx(l.Item,{name:"captchaCode",rules:[{required:!0,message:a("login.captcha")}],children:e.jsxs("div",{className:"captcha-wrapper",children:[e.jsx(m,{size:"large",prefix:e.jsx(P,{className:"text-gray-400","aria-hidden":"true"}),placeholder:a("login.captcha"),maxLength:6,"aria-label":a("login.captcha")}),e.jsx(f,{className:"captcha-image-btn",onClick:()=>void c(),icon:i?null:e.jsx(R,{spin:!0}),"aria-label":"刷新验证码",children:i?e.jsx("img",{src:i.imageBase64,alt:"验证码"}):null})]})}):null,e.jsx("div",{className:"login-extra",children:e.jsx(l.Item,{name:"remember",valuePropName:"checked",noStyle:!0,children:e.jsx(U,{children:a("login.rememberMe")})})}),e.jsx(l.Item,{children:e.jsx(f,{type:"primary",htmlType:"submit",loading:u,block:!0,size:"large",className:"login-submit-btn",children:a(u?"login.loggingIn":"login.submit")})})]})]})})]})})})})]})}export{D as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
import{u as W,r as t,j as e,B as M,W as Y,a3 as $,Y as c,R as v,T as F,a5 as K,b3 as P,aU as D,aT as G,aW as H,s as w,a_ as q}from"./index-2nzO_M0d.js";import{P as A}from"./index-Ds3G3GDW.js";import{R as b,C as d}from"./row-CR991LIl.js";import{C as N}from"./index-ESbS3nHt.js";import{I as J}from"./index-fAufRegR.js";import{F as O}from"./Table-UD3nj3r6.js";import{T as u}from"./index-CASbXnpp.js";import{C as S}from"./index-z7YG9RTL.js";import"./useForm-CzLkm9RK.js";import"./Pagination-CRtRHhmu.js";const{Text:U}=F;function oe(){const{t:a}=W(),[o,C]=t.useState([]),[h,I]=t.useState([]),[T,m]=t.useState(!1),[p,x]=t.useState(!1),[f,g]=t.useState(!1),[l,y]=t.useState(null),[j,i]=t.useState([]),[n,_]=t.useState(""),R=t.useMemo(()=>o.find(s=>s.userId===l)||null,[o,l]),k=async()=>{m(!0);try{const s=await D();C(s||[])}finally{m(!1)}},z=async()=>{x(!0);try{const s=await G();I(s||[])}finally{x(!1)}},E=async s=>{try{const r=await H(s);i(r||[])}catch{i([])}};t.useEffect(()=>{k(),z()},[]),t.useEffect(()=>{l?E(l):i([])},[l]);const L=t.useMemo(()=>{if(!n)return o;const s=n.toLowerCase();return o.filter(r=>r.username.toLowerCase().includes(s)||r.displayName.toLowerCase().includes(s))},[o,n]),B=async()=>{if(!l){w.warning(a("userRole.selectUser"));return}g(!0);try{await q(l,j),w.success(a("common.success"))}finally{g(!1)}};return e.jsxs("div",{className:"app-page",children:[e.jsx(A,{title:a("userRole.title"),subtitle:a("userRole.subtitle")}),e.jsx("div",{className:"app-page__page-actions",children:e.jsx(M,{type:"primary",icon:e.jsx(Y,{"aria-hidden":"true"}),onClick:B,loading:f,disabled:!l,children:a(f?"common.loading":"common.save")})}),e.jsxs(b,{gutter:24,className:"app-page__split",style:{height:"calc(100vh - 180px)"},children:[e.jsx(d,{xs:24,lg:12,style:{height:"100%"},children:e.jsxs(N,{title:e.jsxs(c,{children:[e.jsx(v,{"aria-hidden":"true"}),e.jsx("span",{children:a("userRole.userList")})]}),className:"app-page__panel-card full-height-card",children:[e.jsx("div",{className:"mb-4",children:e.jsx(J,{placeholder:a("userRole.searchUser"),prefix:e.jsx($,{"aria-hidden":"true",className:"text-gray-400"}),value:n,onChange:s=>_(s.target.value),allowClear:!0,"aria-label":a("userRole.searchUser")})}),e.jsx("div",{style:{height:"calc(100% - 60px)",overflowY:"auto"},children:e.jsx(O,{rowKey:"userId",size:"middle",loading:T,dataSource:L,rowSelection:{type:"radio",selectedRowKeys:l?[l]:[],onChange:s=>y(s[0])},onRow:s=>({onClick:()=>y(s.userId),className:"cursor-pointer"}),pagination:{pageSize:10,showTotal:s=>a("common.total",{total:s})},columns:[{title:a("users.userInfo"),key:"user",render:(s,r)=>e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{style:{fontWeight:500},className:"truncate",children:r.displayName}),e.jsxs("div",{style:{fontSize:12,color:"#8c8c8c"},className:"truncate",children:["@",r.username]})]})},{title:a("common.status"),dataIndex:"status",width:80,render:s=>s===1?e.jsx(u,{color:"green",className:"m-0",children:"Enabled"}):e.jsx(u,{className:"m-0",children:"Disabled"})}]})})]})}),e.jsx(d,{xs:24,lg:12,style:{height:"100%"},children:e.jsx(N,{title:e.jsxs(c,{children:[e.jsx(P,{"aria-hidden":"true"}),e.jsx("span",{children:a("userRole.grantRoles")})]}),className:"app-page__panel-card full-height-card",extra:R?e.jsxs(u,{color:"blue",children:[a("userRole.editing"),": ",R.displayName]}):null,children:l?e.jsxs("div",{style:{padding:"8px 0",height:"100%",overflowY:"auto"},children:[e.jsx(S.Group,{style:{width:"100%"},value:j,onChange:s=>i(s),disabled:p,children:e.jsx(b,{gutter:[16,16],children:h.map(s=>e.jsx(d,{span:12,children:e.jsx(S,{value:s.roleId,className:"w-full",children:e.jsxs(c,{direction:"vertical",size:0,children:[e.jsx("span",{style:{fontWeight:500},children:s.roleName}),e.jsx(U,{type:"secondary",style:{fontSize:12},className:"tabular-nums",children:s.roleCode})]})})},s.roleId))})}),!h.length&&!p&&e.jsx(K,{description:"No roles available"})]}):e.jsxs("div",{className:"flex flex-col items-center justify-center py-20 bg-gray-50 rounded-lg border border-dashed border-gray-200",children:[e.jsx(v,{style:{fontSize:40,color:"#bfbfbf",marginBottom:16},"aria-hidden":"true"}),e.jsx(U,{type:"secondary",children:a("userRole.selectUser")})]})})})]})]})}export{oe as default};

View File

@ -1 +0,0 @@
import{x as F,r as s,H as $,ay as w,b$ as q,c0 as D,d7 as E,B as J,cQ as M,d8 as Q,C as S,A as U,av as Y,d9 as G,aJ as K}from"./index-2nzO_M0d.js";import{A as Z}from"./useDict-Cjy4qKoT.js";const ee=e=>{const{componentCls:n,iconCls:l,antCls:t,zIndexPopup:o,colorText:f,colorWarning:u,marginXXS:c,marginXS:i,fontSize:g,fontWeightStrong:v,colorTextHeading:y}=e;return{[n]:{zIndex:o,[`&${t}-popover`]:{fontSize:g},[`${n}-message`]:{marginBottom:i,display:"flex",flexWrap:"nowrap",alignItems:"start",[`> ${n}-message-icon ${l}`]:{color:u,fontSize:g,lineHeight:1,marginInlineEnd:i},[`${n}-title`]:{fontWeight:v,color:y,"&:only-child":{fontWeight:"normal"}},[`${n}-description`]:{marginTop:c,color:f}},[`${n}-buttons`]:{textAlign:"end",whiteSpace:"nowrap",button:{marginInlineStart:i}}}}},te=e=>{const{zIndexPopupBase:n}=e;return{zIndexPopup:n+60}},I=F("Popconfirm",e=>ee(e),te,{resetStyle:!1});var ne=function(e,n){var l={};for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&n.indexOf(t)<0&&(l[t]=e[t]);if(e!=null&&typeof Object.getOwnPropertySymbols=="function")for(var o=0,t=Object.getOwnPropertySymbols(e);o<t.length;o++)n.indexOf(t[o])<0&&Object.prototype.propertyIsEnumerable.call(e,t[o])&&(l[t[o]]=e[t[o]]);return l};const k=e=>{const{prefixCls:n,okButtonProps:l,cancelButtonProps:t,title:o,description:f,cancelText:u,okText:c,okType:i="primary",icon:g=s.createElement($,null),showCancel:v=!0,close:y,onConfirm:C,onCancel:O,onPopupClick:m}=e,{getPrefixCls:p}=s.useContext(w),[d]=q("Popconfirm",D.Popconfirm),b=E(o),x=E(f);return s.createElement("div",{className:`${n}-inner-content`,onClick:m},s.createElement("div",{className:`${n}-message`},g&&s.createElement("span",{className:`${n}-message-icon`},g),s.createElement("div",{className:`${n}-message-text`},b&&s.createElement("div",{className:`${n}-title`},b),x&&s.createElement("div",{className:`${n}-description`},x))),s.createElement("div",{className:`${n}-buttons`},v&&s.createElement(J,Object.assign({onClick:O,size:"small"},t),u||(d==null?void 0:d.cancelText)),s.createElement(Z,{buttonProps:Object.assign(Object.assign({size:"small"},M(i)),l),actionFn:C,close:y,prefixCls:p("btn"),quitOnNullishReturnValue:!0,emitEvent:!0},c||(d==null?void 0:d.okText))))},oe=e=>{const{prefixCls:n,placement:l,className:t,style:o}=e,f=ne(e,["prefixCls","placement","className","style"]),{getPrefixCls:u}=s.useContext(w),c=u("popconfirm",n),[i]=I(c);return i(s.createElement(Q,{placement:l,className:S(c,t),style:o,content:s.createElement(k,Object.assign({prefixCls:c},f))}))};var se=function(e,n){var l={};for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&n.indexOf(t)<0&&(l[t]=e[t]);if(e!=null&&typeof Object.getOwnPropertySymbols=="function")for(var o=0,t=Object.getOwnPropertySymbols(e);o<t.length;o++)n.indexOf(t[o])<0&&Object.prototype.propertyIsEnumerable.call(e,t[o])&&(l[t[o]]=e[t[o]]);return l};const le=s.forwardRef((e,n)=>{var l,t;const{prefixCls:o,placement:f="top",trigger:u="click",okType:c="primary",icon:i=s.createElement($,null),children:g,overlayClassName:v,onOpenChange:y,onVisibleChange:C,overlayStyle:O,styles:m,classNames:p}=e,d=se(e,["prefixCls","placement","trigger","okType","icon","children","overlayClassName","onOpenChange","onVisibleChange","overlayStyle","styles","classNames"]),{getPrefixCls:b,className:x,style:T,classNames:j,styles:h}=U("popconfirm"),[_,z]=Y(!1,{value:(l=e.open)!==null&&l!==void 0?l:e.visible,defaultValue:(t=e.defaultOpen)!==null&&t!==void 0?t:e.defaultVisible}),P=(a,r)=>{z(a,!0),C==null||C(a),y==null||y(a,r)},B=a=>{P(!1,a)},V=a=>{var r;return(r=e.onConfirm)===null||r===void 0?void 0:r.call(void 0,a)},W=a=>{var r;P(!1,a),(r=e.onCancel)===null||r===void 0||r.call(void 0,a)},A=(a,r)=>{const{disabled:X=!1}=e;X||P(a,r)},N=b("popconfirm",o),H=S(N,x,v,j.root,p==null?void 0:p.root),R=S(j.body,p==null?void 0:p.body),[L]=I(N);return L(s.createElement(G,Object.assign({},K(d,["title"]),{trigger:u,placement:f,onOpenChange:A,open:_,ref:n,classNames:{root:H,body:R},styles:{root:Object.assign(Object.assign(Object.assign(Object.assign({},h.root),T),O),m==null?void 0:m.root),body:Object.assign(Object.assign({},h.body),m==null?void 0:m.body)},content:s.createElement(k,Object.assign({okType:c,icon:i},e,{prefixCls:N,close:B,onConfirm:V,onCancel:W})),"data-popover-inject":!0}),g))}),ae=le;ae._InternalPanelDoNotUseOrYouWillBeFired=oe;export{ae as P};

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
import{cs as F,r as i,an as I,ce as S,ct as j,cu as v,cv as E,cw as $,ao as M,cx as N,cy as _,cz as A,cA as c,cB as V,cC as W,cD as z,cE as B,cF as x,cG as D,cH as G}from"./index-BGI3tmtB.js";var H=function(e,n){var l={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&n.indexOf(r)<0&&(l[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols=="function")for(var o=0,r=Object.getOwnPropertySymbols(e);o<r.length;o++)n.indexOf(r[o])<0&&Object.prototype.propertyIsEnumerable.call(e,r[o])&&(l[r[o]]=e[r[o]]);return l};const R=e=>{const{prefixCls:n,className:l,closeIcon:r,closable:o,type:a,title:b,children:d,footer:h}=e,y=H(e,["prefixCls","className","closeIcon","closable","type","title","children","footer"]),{getPrefixCls:m}=i.useContext(I),C=m(),s=n||m("modal"),p=S(C),[w,O,g]=j(s,p),f=`${s}-confirm`;let u={};return a?u={closable:o??!1,title:"",footer:"",children:i.createElement(v,Object.assign({},e,{prefixCls:s,confirmPrefixCls:f,rootPrefixCls:C,content:d}))}:u={closable:o??!0,title:b,footer:h!==null&&i.createElement(E,Object.assign({},e)),children:d},w(i.createElement($,Object.assign({prefixCls:s,className:M(O,`${s}-pure-panel`,a&&f,a&&`${f}-${a}`,l,g,p)},y,{closeIcon:N(s,r),closable:o},u)))},T=F(R);function P(e){return c(G(e))}const t=_;t.useModal=A;t.info=function(n){return c(V(n))};t.success=function(n){return c(W(n))};t.error=function(n){return c(z(n))};t.warning=P;t.warn=P;t.confirm=function(n){return c(B(n))};t.destroyAll=function(){for(;x.length;){const n=x.pop();n&&n()}};t.config=D;t._InternalPanelDoNotUseOrYouWillBeFired=T;export{t as M};

View File

@ -1 +1 @@
import{j as e,T as d}from"./index-2nzO_M0d.js";const{Title:i,Text:n}=d,c=({title:r,subtitle:s,extra:a,className:l=""})=>e.jsxs("div",{className:`page-header flex justify-between items-end mb-6 ${l}`,children:[e.jsxs("div",{children:[e.jsx(i,{level:4,className:"mb-1",style:{margin:0},children:r}),s&&e.jsx(n,{type:"secondary",style:{display:"block"},children:s})]}),a&&e.jsx("div",{className:"page-header-extra",children:a})]});export{c as P}; import{j as e,T as d}from"./index-BGI3tmtB.js";const{Title:i,Text:n}=d,c=({title:r,subtitle:s,extra:a,className:l=""})=>e.jsxs("div",{className:`page-header flex justify-between items-end mb-6 ${l}`,children:[e.jsxs("div",{children:[e.jsx(i,{level:4,className:"mb-1",style:{margin:0},children:r}),s&&e.jsx(n,{type:"secondary",style:{display:"block"},children:s})]}),a&&e.jsx("div",{className:"page-header-extra",children:a})]});export{c as P};

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
import{bm as t}from"./index-2nzO_M0d.js";async function n(a){return(await t.get("/sys/api/orgs",{params:{tenantId:a}})).data.data}async function p(a){return(await t.post("/sys/api/orgs",a)).data.data}async function o(a,s){return(await t.put(`/sys/api/orgs/${a}`,s)).data.data}async function c(a){return(await t.delete(`/sys/api/orgs/${a}`)).data.data}export{p as c,c as d,n as l,o as u}; import{aC as t}from"./index-BGI3tmtB.js";async function n(a){return(await t.get("/sys/api/orgs",{params:{tenantId:a}})).data.data}async function p(a){return(await t.post("/sys/api/orgs",a)).data.data}async function o(a,s){return(await t.put(`/sys/api/orgs/${a}`,s)).data.data}async function c(a){return(await t.delete(`/sys/api/orgs/${a}`)).data.data}export{p as c,c as d,n as l,o as u};

View File

@ -1 +1 @@
import{cH as r}from"./index-2nzO_M0d.js";const s=(t,o,a,e)=>({total:t,current:o,pageSize:a,onChange:e,showSizeChanger:!0,showQuickJumper:!0,showTotal:n=>r.t("common.total",{total:n}),pageSizeOptions:["10","20","50","100"]});export{s as g}; import{cm as r}from"./index-BGI3tmtB.js";const s=(t,o,a,e)=>({total:t,current:o,pageSize:a,onChange:e,showSizeChanger:!0,showQuickJumper:!0,showTotal:n=>r.t("common.total",{total:n}),pageSizeOptions:["10","20","50","100"]});export{s as g};

View File

@ -0,0 +1 @@
import{r as f,an as A,e8 as I,ao as G,az as S,ay as _,e9 as z}from"./index-BGI3tmtB.js";const k=f.createContext({});var J=function(e,l){var n={};for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&l.indexOf(t)<0&&(n[t]=e[t]);if(e!=null&&typeof Object.getOwnPropertySymbols=="function")for(var r=0,t=Object.getOwnPropertySymbols(e);r<t.length;r++)l.indexOf(t[r])<0&&Object.prototype.propertyIsEnumerable.call(e,t[r])&&(n[t[r]]=e[t[r]]);return n};function R(e){return e==="auto"?"1 1 auto":typeof e=="number"?`${e} ${e} auto`:/^\d+(\.\d+)?(px|em|rem|%)$/.test(e)?`0 0 ${e}`:e}const M=["xs","sm","md","lg","xl","xxl"],F=f.forwardRef((e,l)=>{const{getPrefixCls:n,direction:t}=f.useContext(A),{gutter:r,wrap:c}=f.useContext(k),{prefixCls:p,span:i,order:g,offset:m,push:h,pull:O,className:E,children:x,flex:b,style:C}=e,d=J(e,["prefixCls","span","order","offset","push","pull","className","children","flex","style"]),o=n("col",p),[N,P,y]=I(o),j={};let $={};M.forEach(a=>{let s={};const v=e[a];typeof v=="number"?s.span=v:typeof v=="object"&&(s=v||{}),delete d[a],$=Object.assign(Object.assign({},$),{[`${o}-${a}-${s.span}`]:s.span!==void 0,[`${o}-${a}-order-${s.order}`]:s.order||s.order===0,[`${o}-${a}-offset-${s.offset}`]:s.offset||s.offset===0,[`${o}-${a}-push-${s.push}`]:s.push||s.push===0,[`${o}-${a}-pull-${s.pull}`]:s.pull||s.pull===0,[`${o}-rtl`]:t==="rtl"}),s.flex&&($[`${o}-${a}-flex`]=!0,j[`--${o}-${a}-flex`]=R(s.flex))});const w=G(o,{[`${o}-${i}`]:i!==void 0,[`${o}-order-${g}`]:g,[`${o}-offset-${m}`]:m,[`${o}-push-${h}`]:h,[`${o}-pull-${O}`]:O},E,$,P,y),u={};if(r!=null&&r[0]){const a=typeof r[0]=="number"?`${r[0]/2}px`:`calc(${r[0]} / 2)`;u.paddingLeft=a,u.paddingRight=a}return b&&(u.flex=R(b),c===!1&&!u.minWidth&&(u.minWidth=0)),N(f.createElement("div",Object.assign({},d,{style:Object.assign(Object.assign(Object.assign({},u),C),j),className:w,ref:l}),x))});function B(e,l){const n=[void 0,void 0],t=Array.isArray(e)?e:[e,void 0],r=l||{xs:!0,sm:!0,md:!0,lg:!0,xl:!0,xxl:!0};return t.forEach((c,p)=>{if(typeof c=="object"&&c!==null)for(let i=0;i<S.length;i++){const g=S[i];if(r[g]&&c[g]!==void 0){n[p]=c[g];break}}else n[p]=c}),n}var L=function(e,l){var n={};for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&l.indexOf(t)<0&&(n[t]=e[t]);if(e!=null&&typeof Object.getOwnPropertySymbols=="function")for(var r=0,t=Object.getOwnPropertySymbols(e);r<t.length;r++)l.indexOf(t[r])<0&&Object.prototype.propertyIsEnumerable.call(e,t[r])&&(n[t[r]]=e[t[r]]);return n};function V(e,l){const[n,t]=f.useState(typeof e=="string"?e:""),r=()=>{if(typeof e=="string"&&t(e),typeof e=="object")for(let c=0;c<S.length;c++){const p=S[c];if(!l||!l[p])continue;const i=e[p];if(i!==void 0){t(i);return}}};return f.useEffect(()=>{r()},[JSON.stringify(e),l]),n}const H=f.forwardRef((e,l)=>{const{prefixCls:n,justify:t,align:r,className:c,style:p,children:i,gutter:g=0,wrap:m}=e,h=L(e,["prefixCls","justify","align","className","style","children","gutter","wrap"]),{getPrefixCls:O,direction:E}=f.useContext(A),x=_(!0,null),b=V(r,x),C=V(t,x),d=O("row",n),[o,N,P]=z(d),y=B(g,x),j=G(d,{[`${d}-no-wrap`]:m===!1,[`${d}-${C}`]:C,[`${d}-${b}`]:b,[`${d}-rtl`]:E==="rtl"},c,N,P),$={};if(y!=null&&y[0]){const s=typeof y[0]=="number"?`${y[0]/-2}px`:`calc(${y[0]} / -2)`;$.marginLeft=s,$.marginRight=s}const[w,u]=y;$.rowGap=u;const a=f.useMemo(()=>({gutter:[w,u],wrap:m}),[w,u,m]);return o(f.createElement(k.Provider,{value:a},f.createElement("div",Object.assign({},h,{className:j,style:Object.assign(Object.assign({},$),p),ref:l}),i)))});export{F as C,H as R};

View File

@ -1 +0,0 @@
import{r as f,ay as k,C as A,bk as S,bj as I}from"./index-2nzO_M0d.js";import{c as _,d as J}from"./useForm-CzLkm9RK.js";const G=f.createContext({});var M=function(e,l){var n={};for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&l.indexOf(t)<0&&(n[t]=e[t]);if(e!=null&&typeof Object.getOwnPropertySymbols=="function")for(var r=0,t=Object.getOwnPropertySymbols(e);r<t.length;r++)l.indexOf(t[r])<0&&Object.prototype.propertyIsEnumerable.call(e,t[r])&&(n[t[r]]=e[t[r]]);return n};function R(e){return e==="auto"?"1 1 auto":typeof e=="number"?`${e} ${e} auto`:/^\d+(\.\d+)?(px|em|rem|%)$/.test(e)?`0 0 ${e}`:e}const z=["xs","sm","md","lg","xl","xxl"],H=f.forwardRef((e,l)=>{const{getPrefixCls:n,direction:t}=f.useContext(k),{gutter:r,wrap:c}=f.useContext(G),{prefixCls:p,span:i,order:g,offset:m,push:h,pull:O,className:E,children:b,flex:x,style:C}=e,d=M(e,["prefixCls","span","order","offset","push","pull","className","children","flex","style"]),o=n("col",p),[N,P,y]=_(o),j={};let $={};z.forEach(a=>{let s={};const v=e[a];typeof v=="number"?s.span=v:typeof v=="object"&&(s=v||{}),delete d[a],$=Object.assign(Object.assign({},$),{[`${o}-${a}-${s.span}`]:s.span!==void 0,[`${o}-${a}-order-${s.order}`]:s.order||s.order===0,[`${o}-${a}-offset-${s.offset}`]:s.offset||s.offset===0,[`${o}-${a}-push-${s.push}`]:s.push||s.push===0,[`${o}-${a}-pull-${s.pull}`]:s.pull||s.pull===0,[`${o}-rtl`]:t==="rtl"}),s.flex&&($[`${o}-${a}-flex`]=!0,j[`--${o}-${a}-flex`]=R(s.flex))});const w=A(o,{[`${o}-${i}`]:i!==void 0,[`${o}-order-${g}`]:g,[`${o}-offset-${m}`]:m,[`${o}-push-${h}`]:h,[`${o}-pull-${O}`]:O},E,$,P,y),u={};if(r!=null&&r[0]){const a=typeof r[0]=="number"?`${r[0]/2}px`:`calc(${r[0]} / 2)`;u.paddingLeft=a,u.paddingRight=a}return x&&(u.flex=R(x),c===!1&&!u.minWidth&&(u.minWidth=0)),N(f.createElement("div",Object.assign({},d,{style:Object.assign(Object.assign(Object.assign({},u),C),j),className:w,ref:l}),b))});function B(e,l){const n=[void 0,void 0],t=Array.isArray(e)?e:[e,void 0],r=l||{xs:!0,sm:!0,md:!0,lg:!0,xl:!0,xxl:!0};return t.forEach((c,p)=>{if(typeof c=="object"&&c!==null)for(let i=0;i<S.length;i++){const g=S[i];if(r[g]&&c[g]!==void 0){n[p]=c[g];break}}else n[p]=c}),n}var L=function(e,l){var n={};for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&l.indexOf(t)<0&&(n[t]=e[t]);if(e!=null&&typeof Object.getOwnPropertySymbols=="function")for(var r=0,t=Object.getOwnPropertySymbols(e);r<t.length;r++)l.indexOf(t[r])<0&&Object.prototype.propertyIsEnumerable.call(e,t[r])&&(n[t[r]]=e[t[r]]);return n};function V(e,l){const[n,t]=f.useState(typeof e=="string"?e:""),r=()=>{if(typeof e=="string"&&t(e),typeof e=="object")for(let c=0;c<S.length;c++){const p=S[c];if(!l||!l[p])continue;const i=e[p];if(i!==void 0){t(i);return}}};return f.useEffect(()=>{r()},[JSON.stringify(e),l]),n}const q=f.forwardRef((e,l)=>{const{prefixCls:n,justify:t,align:r,className:c,style:p,children:i,gutter:g=0,wrap:m}=e,h=L(e,["prefixCls","justify","align","className","style","children","gutter","wrap"]),{getPrefixCls:O,direction:E}=f.useContext(k),b=I(!0,null),x=V(r,b),C=V(t,b),d=O("row",n),[o,N,P]=J(d),y=B(g,b),j=A(d,{[`${d}-no-wrap`]:m===!1,[`${d}-${C}`]:C,[`${d}-${x}`]:x,[`${d}-rtl`]:E==="rtl"},c,N,P),$={};if(y!=null&&y[0]){const s=typeof y[0]=="number"?`${y[0]/-2}px`:`calc(${y[0]} / -2)`;$.marginLeft=s,$.marginRight=s}const[w,u]=y;$.rowGap=u;const a=f.useMemo(()=>({gutter:[w,u],wrap:m}),[w,u,m]);return o(f.createElement(G.Provider,{value:a},f.createElement("div",Object.assign({},h,{className:j,style:Object.assign(Object.assign({},$),p),ref:l}),i)))});export{H as C,q as R};

View File

@ -0,0 +1 @@
import{aC as n}from"./index-BGI3tmtB.js";async function r(a){return(await n.get("/sys/api/tenants",{params:a})).data.data}async function p(a){return(await n.post("/sys/api/tenants",a)).data.data}async function c(a,t){return(await n.put(`/sys/api/tenants/${a}`,t)).data.data}async function i(a){return(await n.delete(`/sys/api/tenants/${a}`)).data.data}export{p as c,i as d,r as l,c as u};

View File

@ -1 +0,0 @@
import{bm as n}from"./index-2nzO_M0d.js";async function r(t){return(await n.get("/sys/api/tenants",{params:t})).data.data}async function p(t){return(await n.post("/sys/api/tenants",t)).data.data}async function c(t,a){return(await n.put(`/sys/api/tenants/${t}`,a)).data.data}async function i(t){return(await n.delete(`/sys/api/tenants/${t}`)).data.data}export{p as c,i as d,r as l,c as u};

View File

@ -0,0 +1 @@
import{aC as s,r}from"./index-BGI3tmtB.js";async function f(t){return(await s.get("/sys/api/dict-types",{params:t})).data.data}async function l(t){return(await s.post("/sys/api/dict-types",t)).data.data}async function m(t,a){return(await s.put(`/sys/api/dict-types/${t}`,a)).data.data}async function w(t){return(await s.delete(`/sys/api/dict-types/${t}`)).data.data}async function D(t){return(await s.get("/sys/api/dict-items",{params:{typeCode:t}})).data.data}async function h(t){return(await s.post("/sys/api/dict-items",t)).data.data}async function g(t,a){return(await s.put(`/sys/api/dict-items/${t}`,a)).data.data}async function I(t){return(await s.delete(`/sys/api/dict-items/${t}`)).data.data}async function o(t){return(await s.get(`/sys/api/dict-items/type/${t}`)).data.data}const e={};function $(t){const[a,c]=r.useState(e[t]||[]),[d,p]=r.useState(!e[t]);return r.useEffect(()=>{if(e[t]){c(e[t]),p(!1);return}let n=!0;return(async()=>{try{const i=await o(t);n&&(e[t]=i,c(i))}catch(i){console.error(`Failed to fetch dictionary ${t}:`,i)}finally{n&&p(!1)}})(),()=>{n=!1}},[t]),{items:a,loading:d}}export{D as a,m as b,l as c,w as d,I as e,f,g,h,$ as u};

View File

@ -1 +0,0 @@
import{r as i,ds as S,B as $,cQ as E,bm as n}from"./index-2nzO_M0d.js";const g=t=>typeof(t==null?void 0:t.then)=="function",x=t=>{const{type:e,children:c,prefixCls:y,buttonProps:d,close:r,autoFocus:m,emitEvent:o,isSilent:v,quitOnNullishReturnValue:D,actionFn:l}=t,u=i.useRef(!1),w=i.useRef(null),[I,h]=S(!1),p=(...a)=>{r==null||r.apply(void 0,a)};i.useEffect(()=>{let a=null;return m&&(a=setTimeout(()=>{var s;(s=w.current)===null||s===void 0||s.focus({preventScroll:!0})})),()=>{a&&clearTimeout(a)}},[m]);const T=a=>{g(a)&&(h(!0),a.then((...s)=>{h(!1,!0),p.apply(void 0,s),u.current=!1},s=>{if(h(!1,!0),u.current=!1,!(v!=null&&v()))return Promise.reject(s)}))},b=a=>{if(u.current)return;if(u.current=!0,!l){p();return}let s;if(o){if(s=l(a),D&&!g(s)){u.current=!1,p(a);return}}else if(l.length)s=l(r),u.current=!1;else if(s=l(),!g(s)){p();return}T(s)};return i.createElement($,Object.assign({},E(e),{onClick:b,loading:I,prefixCls:y},d,{ref:w}),c)};async function B(t){return(await n.get("/sys/api/dict-types",{params:t})).data.data}async function O(t){return(await n.post("/sys/api/dict-types",t)).data.data}async function P(t,e){return(await n.put(`/sys/api/dict-types/${t}`,e)).data.data}async function F(t){return(await n.delete(`/sys/api/dict-types/${t}`)).data.data}async function L(t){return(await n.get("/sys/api/dict-items",{params:{typeCode:t}})).data.data}async function j(t){return(await n.post("/sys/api/dict-items",t)).data.data}async function A(t,e){return(await n.put(`/sys/api/dict-items/${t}`,e)).data.data}async function q(t){return(await n.delete(`/sys/api/dict-items/${t}`)).data.data}async function R(t){return(await n.get(`/sys/api/dict-items/type/${t}`)).data.data}const f={};function M(t){const[e,c]=i.useState(f[t]||[]),[y,d]=i.useState(!f[t]);return i.useEffect(()=>{if(f[t]){c(f[t]),d(!1);return}let r=!0;return(async()=>{try{const o=await R(t);r&&(f[t]=o,c(o))}catch(o){console.error(`Failed to fetch dictionary ${t}:`,o)}finally{r&&d(!1)}})(),()=>{r=!1}},[t]),{items:e,loading:y}}export{x as A,L as a,P as b,O as c,F as d,q as e,B as f,A as g,j as h,M as u};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -5,7 +5,7 @@
<link rel="icon" type="image/svg+xml" href="/logo.svg" /> <link rel="icon" type="image/svg+xml" href="/logo.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>UnisBase - 智能会议系统</title> <title>UnisBase - 智能会议系统</title>
<script type="module" crossorigin src="/assets/index-2nzO_M0d.js"></script> <script type="module" crossorigin src="/assets/index-BGI3tmtB.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-CaWPk49l.css"> <link rel="stylesheet" crossorigin href="/assets/index-CaWPk49l.css">
</head> </head>
<body> <body>

View File

@ -1,9 +1,20 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { ConfigProvider, theme } from "antd"; import { App as AntdApp, ConfigProvider, theme } from "antd";
import AppRoutes from "./routes"; import AppRoutes from "./routes";
import { getOpenPlatformConfig } from "./api"; import { getOpenPlatformConfig } from "./api";
import type { SysPlatformConfig } from "./types"; import type { SysPlatformConfig } from "./types";
import { useThemeStore } from "./store/themeStore"; import { useThemeStore } from "./store/themeStore";
import { setGlobalMessageApi } from "./utils/antdApp";
function AntdAppBridge() {
const { message } = AntdApp.useApp();
useEffect(() => {
setGlobalMessageApi(message);
}, [message]);
return null;
}
export default function App() { export default function App() {
const [config, setConfig] = useState<SysPlatformConfig | null>(null); const [config, setConfig] = useState<SysPlatformConfig | null>(null);
@ -39,11 +50,11 @@ export default function App() {
return ( return (
<ConfigProvider <ConfigProvider
theme={{ theme={{
algorithm: themeMode === 'tech' ? theme.darkAlgorithm : theme.defaultAlgorithm, algorithm: themeMode === "tech" ? theme.darkAlgorithm : theme.defaultAlgorithm,
token: { token: {
colorPrimary: colorPrimary, colorPrimary,
borderRadius: 10, borderRadius: 10,
colorBgLayout: 'transparent', colorBgLayout: "transparent"
}, },
components: { components: {
Card: { Card: {
@ -52,7 +63,10 @@ export default function App() {
} }
}} }}
> >
<AntdApp>
<AntdAppBridge />
<AppRoutes /> <AppRoutes />
</AntdApp>
</ConfigProvider> </ConfigProvider>
); );
} }

View File

@ -1,5 +1,5 @@
import axios from "axios"; import axios from "axios";
import { message } from "antd"; import { notifyError } from "@/utils/antdApp";
const http = axios.create({ const http = axios.create({
baseURL: "/", baseURL: "/",
@ -117,7 +117,7 @@ http.interceptors.response.use(
const body = resp.data; const body = resp.data;
if (body && body.code !== "0") { if (body && body.code !== "0") {
const errorMsg = body.msg || "请求失败"; const errorMsg = body.msg || "请求失败";
message.error(errorMsg); notifyError(errorMsg);
const err = new Error(errorMsg); const err = new Error(errorMsg);
(err as any).code = body.code; (err as any).code = body.code;
(err as any).msg = body.msg; (err as any).msg = body.msg;
@ -149,7 +149,7 @@ http.interceptors.response.use(
const body = error.response?.data; const body = error.response?.data;
const errorMsg = body?.msg || error.message || "网络异常"; const errorMsg = body?.msg || error.message || "网络异常";
message.error(errorMsg); notifyError(errorMsg);
if (body && body.msg) { if (body && body.msg) {
const err = new Error(body.msg); const err = new Error(body.msg);

View File

@ -213,3 +213,4 @@ export * from "./dict";
export * from "./tenant"; export * from "./tenant";
export * from "./org"; export * from "./org";
export * from "./platform"; export * from "./platform";
export * from "./reportPush";

View File

@ -0,0 +1 @@
export * from "@/features/report-reminder/api";

View File

@ -67,7 +67,7 @@ function ButtonWithHoverCard({
> >
<Card <Card
size="small" size="small"
bordered={false} variant="borderless"
className="hover-info-card-content" className="hover-info-card-content"
> >
{/* 标题区 */} {/* 标题区 */}

View File

@ -0,0 +1,32 @@
import http from "@/api/http";
import type { ReportReminderConfig, ReportReminderTestPayload, WecomAppConfig, WecomConfigStatus } from "./types";
export async function getWecomAppConfig(tenantId?: number) {
const resp = await http.get("/sys/api/admin/wecom-app-config", { params: { tenantId } });
return resp.data.data as WecomAppConfig;
}
export async function updateWecomAppConfig(payload: WecomAppConfig) {
const resp = await http.put("/sys/api/admin/wecom-app-config", payload);
return resp.data.data as boolean;
}
export async function getReportReminderConfig(tenantId?: number) {
const resp = await http.get("/sys/api/admin/report-reminder-config", { params: { tenantId } });
return resp.data.data as ReportReminderConfig;
}
export async function updateReportReminderConfig(payload: ReportReminderConfig) {
const resp = await http.put("/sys/api/admin/report-reminder-config", payload);
return resp.data.data as boolean;
}
export async function testReportReminderConfig(payload: ReportReminderTestPayload) {
const resp = await http.post("/sys/api/admin/report-reminder-config/test", payload);
return resp.data.data as boolean;
}
export async function getWecomConfigStatus(tenantId?: number) {
const resp = await http.get("/sys/api/admin/wecom-config-status", { params: { tenantId } });
return resp.data.data as WecomConfigStatus;
}

View File

@ -0,0 +1,66 @@
import type { ReportReminderConfig, ReportReminderTestMessageType, WecomAppConfig } from "./types";
export interface TemplatePlaceholderOption {
token: string;
labelKey: string;
}
export const REPORT_REMINDER_TEST_TYPES: ReportReminderTestMessageType[] = ["MISSING_REPORT", "SUBMIT_NOTIFY"];
export const DEFAULT_WECOM_APP_CONFIG: WecomAppConfig = {
enabled: false,
corpId: "",
agentId: "",
secret: ""
};
export const DEFAULT_REPORT_REMINDER_CONFIG: ReportReminderConfig = {
wecomPushEnabled: false,
missingReportEnabled: true,
missingReportTargetType: "ALL",
missingReportUserIds: [],
missingReportRoleIds: [],
missingReportOrgIds: [],
missingReportExcludeUserIds: [],
remindStartTime: "18:00",
remindEndTime: "18:30",
missingReportTemplate: "【日报提醒】{{userName}},你 {{reportDate}} 的日报还未提交,请在 {{deadlineTime}} 前完成。",
remindIntervalMinutes: 10,
maxRemindCountPerDay: 3,
workdayOnly: true,
skipHoliday: true,
submitNotifyEnabled: true,
submitNotifyTargetType: "USERS",
submitNotifyUserIds: [],
submitNotifyRoleIds: [],
submitNotifyTemplate: "【日报提交】{{submitterName}}已于{{submitTime}}提交{{reportDate}}日报,请及时查看。",
excludeSubmitter: true
};
export const MISSING_TEMPLATE_PLACEHOLDERS: TemplatePlaceholderOption[] = [
{ token: "{{remindIndex}}", labelKey: "reportReminder.placeholderRemindIndex" },
{ token: "{{userName}}", labelKey: "reportReminder.placeholderUserName" },
{ token: "{{userAccount}}", labelKey: "reportReminder.placeholderUserAccount" },
{ token: "{{userPhone}}", labelKey: "reportReminder.placeholderUserPhone" },
{ token: "{{userOrgName}}", labelKey: "reportReminder.placeholderUserOrgName" },
{ token: "{{reportDate}}", labelKey: "reportReminder.placeholderReportDate" },
{ token: "{{startTime}}", labelKey: "reportReminder.placeholderStartTime" },
{ token: "{{endTime}}", labelKey: "reportReminder.placeholderEndTime" },
{ token: "{{deadlineTime}}", labelKey: "reportReminder.placeholderDeadlineTime" },
{ token: "{{remindWindow}}", labelKey: "reportReminder.placeholderRemindWindow" },
{ token: "{{tenantName}}", labelKey: "reportReminder.placeholderTenantName" }
];
export const SUBMIT_TEMPLATE_PLACEHOLDERS: TemplatePlaceholderOption[] = [
{ token: "{{submitterName}}", labelKey: "reportReminder.placeholderSubmitterName" },
{ token: "{{submitterAccount}}", labelKey: "reportReminder.placeholderSubmitterAccount" },
{ token: "{{submitterPhone}}", labelKey: "reportReminder.placeholderSubmitterPhone" },
{ token: "{{submitterOrgName}}", labelKey: "reportReminder.placeholderSubmitterOrgName" },
{ token: "{{submitterRoleNames}}", labelKey: "reportReminder.placeholderSubmitterRoleNames" },
{ token: "{{reportDate}}", labelKey: "reportReminder.placeholderReportDate" },
{ token: "{{submitTime}}", labelKey: "reportReminder.placeholderSubmitTime" },
{ token: "{{receiverName}}", labelKey: "reportReminder.placeholderReceiverName" },
{ token: "{{tenantName}}", labelKey: "reportReminder.placeholderTenantName" },
{ token: "{{reportSummary}}", labelKey: "reportReminder.placeholderReportSummary" },
{ token: "{{planSummary}}", labelKey: "reportReminder.placeholderPlanSummary" }
];

View File

@ -0,0 +1,3 @@
export { default } from "./pages/report-reminder-settings";
export * from "./api";
export * from "./types";

View File

@ -0,0 +1,99 @@
const reportReminderEnUS = {
reportReminder: {
title: "Daily Report Reminder Settings",
subtitle: "Configure WeCom app parameters, missing report reminders, and post-submission notifications in one place while staying aligned with frontend1 permission and tenant behavior.",
wecomSection: "WeCom App Configuration",
missingSection: "Missing Report Reminder",
submitSection: "Submission Notification",
testSection: "Test Send",
wecomAppEnabled: "Enable WeCom App",
wecomPushEnabled: "Enable WeCom reminder push",
corpId: "CorpId",
agentId: "AgentId",
secret: "Secret",
corpIdPlaceholder: "Enter the WeCom CorpId",
agentIdPlaceholder: "Enter the app AgentId",
secretPlaceholder: "Enter the app Secret",
wecomStatus: "WeCom Status",
wecomConfigured: "Configured",
wecomNotConfigured: "Not Configured",
defaultMappingMode: "Member mapping: treat the CRM account as a mobile number first, then fall back to the CRM mobile number",
mappingModeTitle: "Member Mapping",
mappingModeDesc: "This version first treats the CRM account as a mobile number and tries to match a WeCom member by mobile. If that fails, it falls back to the CRM mobile number. If both strategies fail, the message will be logged as failed.",
missingEnabled: "Enable missing report reminder",
missingTargetType: "Reminder audience",
missingUsers: "Reminder users",
missingRoles: "Reminder roles",
missingOrgs: "Reminder departments",
excludeUsers: "Excluded users",
missingTemplate: "Missing reminder template",
missingTemplatePlaceholder: "Enter the missing report reminder template",
templateToolsTitle: "Placeholder quick insert",
templateToolsHint: "Click a placeholder below to insert it into the template",
templateRestoreDefault: "Restore default template",
templateHintPrefix: "Supported placeholders:",
startTime: "Start time",
endTime: "End time",
interval: "Interval (minutes)",
maxCount: "Max reminders per user per day",
workdayOnly: "Workdays only",
skipHoliday: "Skip holidays",
submitEnabled: "Enable submission notification",
submitTargetType: "Notification audience",
notifyUsers: "Notify users",
notifyRoles: "Notify roles",
submitTemplate: "Submission notification template",
submitTemplatePlaceholder: "Enter the submission notification template",
excludeSubmitter: "Exclude submitter",
previewTitle: "Message Preview",
previewMissing: "【Daily report reminder】{{userName}}, your {{reportDate}} daily report is still missing. Please complete it before {{deadlineTime}}.",
previewSubmit: "【Daily report submitted】{{submitterName}} submitted the {{reportDate}} daily report at {{submitTime}}. Please review it in time.",
sampleUser: "Alex",
targetAll: "All employees",
targetUsers: "Specific users",
targetRoles: "Specific roles",
targetOrgs: "Specific departments",
selectUsers: "Select users",
selectRoles: "Select roles",
selectOrgs: "Select departments",
testSend: "Test Send",
testMessageType: "Test message type",
testReceiver: "Test receiver",
testMissing: "Missing report reminder",
testSubmit: "Submission notification",
testSent: "The test message has been triggered. Please check the WeCom result.",
noViewPermission: "You do not have permission to view this page.",
selectTenantFirst: "Switch to a specific tenant before editing report reminders.",
selectTenantHint: "This page stores one WeCom config and one reminder config per tenant. If a platform admin stays on the platform tenant, the config owner cannot be determined.",
validationWecomConfig: "After enabling the WeCom app, fill in CorpId, AgentId, and Secret.",
validationTimeRange: "The reminder end time must be later than the start time.",
validationMissingUsers: "Select at least one user to remind.",
validationMissingRoles: "Select at least one role to remind.",
validationMissingOrgs: "Select at least one department to remind.",
validationNotifyUsers: "Select at least one user to notify.",
validationNotifyRoles: "Select at least one role to notify.",
validationTestReceiver: "Select a test receiver.",
placeholderRemindIndex: "Reminder index",
placeholderUserName: "Receiver name",
placeholderUserAccount: "Receiver account",
placeholderUserPhone: "Receiver phone",
placeholderUserOrgName: "Receiver department",
placeholderReportDate: "Report date",
placeholderStartTime: "Start time",
placeholderEndTime: "End time",
placeholderDeadlineTime: "Deadline",
placeholderRemindWindow: "Reminder window",
placeholderTenantName: "Tenant name",
placeholderSubmitterName: "Submitter name",
placeholderSubmitterAccount: "Submitter account",
placeholderSubmitterPhone: "Submitter phone",
placeholderSubmitterOrgName: "Submitter department",
placeholderSubmitterRoleNames: "Submitter roles",
placeholderSubmitTime: "Submit time",
placeholderReceiverName: "Receiver name",
placeholderReportSummary: "Report summary",
placeholderPlanSummary: "Plan summary"
}
} as const;
export default reportReminderEnUS;

View File

@ -0,0 +1,99 @@
const reportReminderZhCN = {
reportReminder: {
title: "日报提醒设置",
subtitle: "统一配置企业微信应用参数、日报催填提醒和提交后通知规则,保持与 frontend1 的菜单权限和租户模式一致。",
wecomSection: "企业微信应用配置",
missingSection: "未填写日报提醒",
submitSection: "提交后通知",
testSection: "测试发送",
wecomAppEnabled: "启用企业微信应用",
wecomPushEnabled: "启用企业微信提醒推送",
corpId: "CorpId",
agentId: "AgentId",
secret: "Secret",
corpIdPlaceholder: "请输入企业微信 CorpId",
agentIdPlaceholder: "请输入应用 AgentId",
secretPlaceholder: "请输入应用 Secret",
wecomStatus: "企业微信配置状态",
wecomConfigured: "已配置",
wecomNotConfigured: "未配置",
defaultMappingMode: "成员匹配方式:优先按 CRM 账户匹配企业微信成员手机号,未匹配到时再按 CRM 用户手机号匹配",
mappingModeTitle: "成员匹配方式",
mappingModeDesc: "这版方案默认优先将 CRM 账户作为手机号去匹配企业微信通讯录成员;若账户未匹配到,再按 CRM 用户手机号匹配企业微信通讯录成员。若两种方式都未匹配到,消息会记录为发送失败。",
missingEnabled: "开启未填写日报提醒",
missingTargetType: "提醒对象范围",
missingUsers: "提醒对象用户",
missingRoles: "提醒对象角色",
missingOrgs: "提醒对象部门",
excludeUsers: "排除人员",
missingTemplate: "未填写提醒模板",
missingTemplatePlaceholder: "请输入未填写日报提醒模板",
templateToolsTitle: "占位符快捷插入",
templateToolsHint: "点击下方占位符可自动插入到模板中",
templateRestoreDefault: "恢复默认模板",
templateHintPrefix: "支持占位符:",
startTime: "提醒开始时间",
endTime: "提醒结束时间",
interval: "提醒频率(分钟)",
maxCount: "单人每日最多提醒次数",
workdayOnly: "仅工作日提醒",
skipHoliday: "节假日跳过",
submitEnabled: "开启提交后通知",
submitTargetType: "通知对象范围",
notifyUsers: "通知用户",
notifyRoles: "通知角色",
submitTemplate: "提交后通知模板",
submitTemplatePlaceholder: "请输入提交后通知模板",
excludeSubmitter: "排除提交人本人",
previewTitle: "消息预览",
previewMissing: "【日报提醒】{{userName}},你 {{reportDate}} 的日报还未提交,请在 {{deadlineTime}} 前完成。",
previewSubmit: "【日报提交】{{submitterName}}已于{{submitTime}}提交{{reportDate}}日报,请及时查看。",
sampleUser: "张三",
targetAll: "全部员工",
targetUsers: "指定用户",
targetRoles: "指定角色",
targetOrgs: "指定部门",
selectUsers: "请选择用户",
selectRoles: "请选择角色",
selectOrgs: "请选择部门",
testSend: "测试发送",
testMessageType: "测试消息类型",
testReceiver: "测试接收人",
testMissing: "未填写日报提醒",
testSubmit: "提交后通知",
testSent: "测试消息已发起,请关注企业微信接收结果。",
noViewPermission: "你当前没有查看日报提醒设置的权限。",
selectTenantFirst: "请先切换到具体租户后再配置日报提醒。",
selectTenantHint: "当前页面按租户保存企业微信和提醒规则。平台管理员如果停留在平台租户,将无法确定配置归属。",
validationWecomConfig: "启用企业微信应用后,请补全 CorpId、AgentId 和 Secret。",
validationTimeRange: "提醒结束时间必须晚于开始时间。",
validationMissingUsers: "请选择需要提醒的用户。",
validationMissingRoles: "请选择需要提醒的角色。",
validationMissingOrgs: "请选择需要提醒的部门。",
validationNotifyUsers: "请选择提交后需要通知的用户。",
validationNotifyRoles: "请选择提交后需要通知的角色。",
validationTestReceiver: "请选择测试接收人。",
placeholderRemindIndex: "提醒序号",
placeholderUserName: "接收人姓名",
placeholderUserAccount: "接收人账号",
placeholderUserPhone: "接收人手机号",
placeholderUserOrgName: "接收人部门",
placeholderReportDate: "日报日期",
placeholderStartTime: "开始时间",
placeholderEndTime: "结束时间",
placeholderDeadlineTime: "截止时间",
placeholderRemindWindow: "提醒时间窗",
placeholderTenantName: "租户名称",
placeholderSubmitterName: "提交人姓名",
placeholderSubmitterAccount: "提交人账号",
placeholderSubmitterPhone: "提交人手机号",
placeholderSubmitterOrgName: "提交人部门",
placeholderSubmitterRoleNames: "提交人角色",
placeholderSubmitTime: "提交时间",
placeholderReceiverName: "通知接收人",
placeholderReportSummary: "日报摘要",
placeholderPlanSummary: "计划摘要"
}
} as const;
export default reportReminderZhCN;

Some files were not shown because too many files have changed in this diff Show More