refactor(core): 重构会议接口并统一代码换行符
- 调整前端会议接口类型,新增 MeetingParticipant 定义 - 统一全项目文件换行符为 LF,清理 CRLF 格式 - 完善 .gitignore 规则与 H5 端基础类型定义dev_na
parent
e3a37757ba
commit
2660f65bd2
|
|
@ -42,6 +42,9 @@ public class MeetingVO {
|
||||||
@Schema(description = "参会人ID列表")
|
@Schema(description = "参会人ID列表")
|
||||||
private List<Long> participantIds;
|
private List<Long> participantIds;
|
||||||
|
|
||||||
|
@Schema(description = "参会人列表,ID 与名称一一对应")
|
||||||
|
private List<MeetingParticipantVO> participantUsers;
|
||||||
|
|
||||||
@Schema(description = "标签串")
|
@Schema(description = "标签串")
|
||||||
private String tags;
|
private String tags;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@ import com.imeeting.mapper.biz.HotWordGroupMapper;
|
||||||
import com.imeeting.mapper.biz.HotWordMapper;
|
import com.imeeting.mapper.biz.HotWordMapper;
|
||||||
import com.imeeting.service.biz.HotWordService;
|
import com.imeeting.service.biz.HotWordService;
|
||||||
import com.unisbase.common.exception.BusinessException;
|
import com.unisbase.common.exception.BusinessException;
|
||||||
|
import com.unisbase.dto.SysDictItemDTO;
|
||||||
|
import com.unisbase.service.SysDictItemService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.sourceforge.pinyin4j.PinyinHelper;
|
import net.sourceforge.pinyin4j.PinyinHelper;
|
||||||
|
|
@ -35,12 +37,14 @@ import java.util.stream.Collectors;
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class HotWordServiceImpl extends ServiceImpl<HotWordMapper, HotWord> implements HotWordService {
|
public class HotWordServiceImpl extends ServiceImpl<HotWordMapper, HotWord> implements HotWordService {
|
||||||
|
|
||||||
private static final int MAX_HOT_WORDS_PER_GROUP = 200;
|
private static final String HOT_WORD_GROUP_LIMIT_DICT_TYPE = "biz_hotword_group_limit";
|
||||||
|
private static final int DEFAULT_MAX_HOT_WORDS_PER_GROUP = 200;
|
||||||
private static final int DEFAULT_MATCH_STRATEGY = 1;
|
private static final int DEFAULT_MATCH_STRATEGY = 1;
|
||||||
private static final int DEFAULT_WEIGHT = 2;
|
private static final int DEFAULT_WEIGHT = 2;
|
||||||
private static final int ENABLED_STATUS = 1;
|
private static final int ENABLED_STATUS = 1;
|
||||||
|
|
||||||
private final HotWordGroupMapper hotWordGroupMapper;
|
private final HotWordGroupMapper hotWordGroupMapper;
|
||||||
|
private final SysDictItemService sysDictItemService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
|
@ -201,8 +205,9 @@ public class HotWordServiceImpl extends ServiceImpl<HotWordMapper, HotWord> impl
|
||||||
long currentCount = this.count(new LambdaQueryWrapper<HotWord>()
|
long currentCount = this.count(new LambdaQueryWrapper<HotWord>()
|
||||||
.eq(HotWord::getHotWordGroupId, groupId)
|
.eq(HotWord::getHotWordGroupId, groupId)
|
||||||
.ne(currentHotWordId != null, HotWord::getId, currentHotWordId));
|
.ne(currentHotWordId != null, HotWord::getId, currentHotWordId));
|
||||||
if (currentCount >= MAX_HOT_WORDS_PER_GROUP) {
|
int maxHotWordsPerGroup = getMaxHotWordsPerGroup();
|
||||||
throw new BusinessException("热词组最多只能包含 200 个热词");
|
if (currentCount >= maxHotWordsPerGroup) {
|
||||||
|
throwGroupCapacityExceeded(maxHotWordsPerGroup);
|
||||||
}
|
}
|
||||||
return group.getId();
|
return group.getId();
|
||||||
}
|
}
|
||||||
|
|
@ -222,8 +227,9 @@ public class HotWordServiceImpl extends ServiceImpl<HotWordMapper, HotWord> impl
|
||||||
long incomingCount = movingHotWords.stream()
|
long incomingCount = movingHotWords.stream()
|
||||||
.filter(item -> !groupId.equals(item.getHotWordGroupId()))
|
.filter(item -> !groupId.equals(item.getHotWordGroupId()))
|
||||||
.count();
|
.count();
|
||||||
if (currentCount + incomingCount > MAX_HOT_WORDS_PER_GROUP) {
|
int maxHotWordsPerGroup = getMaxHotWordsPerGroup();
|
||||||
throw new BusinessException("热词组最多只能包含 200 个热词");
|
if (currentCount + incomingCount > maxHotWordsPerGroup) {
|
||||||
|
throwGroupCapacityExceeded(maxHotWordsPerGroup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -268,8 +274,9 @@ public class HotWordServiceImpl extends ServiceImpl<HotWordMapper, HotWord> impl
|
||||||
}
|
}
|
||||||
long currentCount = this.count(new LambdaQueryWrapper<HotWord>()
|
long currentCount = this.count(new LambdaQueryWrapper<HotWord>()
|
||||||
.eq(HotWord::getHotWordGroupId, groupId));
|
.eq(HotWord::getHotWordGroupId, groupId));
|
||||||
if (currentCount + incomingCount > MAX_HOT_WORDS_PER_GROUP) {
|
int maxHotWordsPerGroup = getMaxHotWordsPerGroup();
|
||||||
throw new BusinessException("热词组最多只能包含 200 个热词");
|
if (currentCount + incomingCount > maxHotWordsPerGroup) {
|
||||||
|
throwGroupCapacityExceeded(maxHotWordsPerGroup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -288,6 +295,31 @@ public class HotWordServiceImpl extends ServiceImpl<HotWordMapper, HotWord> impl
|
||||||
return hotWord;
|
return hotWord;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getMaxHotWordsPerGroup() {
|
||||||
|
List<SysDictItemDTO> items = sysDictItemService.getItemsByTypeCode(HOT_WORD_GROUP_LIMIT_DICT_TYPE);
|
||||||
|
if (items == null || items.isEmpty()) {
|
||||||
|
return DEFAULT_MAX_HOT_WORDS_PER_GROUP;
|
||||||
|
}
|
||||||
|
for (SysDictItemDTO item : items) {
|
||||||
|
if (item == null || item.getItemValue() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
int configuredLimit = Integer.parseInt(item.getItemValue().trim());
|
||||||
|
if (configuredLimit > 0) {
|
||||||
|
return configuredLimit;
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException exception) {
|
||||||
|
log.warn("热词组上限字典配置值非法: {}", item.getItemValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return DEFAULT_MAX_HOT_WORDS_PER_GROUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void throwGroupCapacityExceeded(int maxHotWordsPerGroup) {
|
||||||
|
throw new BusinessException("热词组最多只能包含 " + maxHotWordsPerGroup + " 个热词");
|
||||||
|
}
|
||||||
|
|
||||||
private void generateCombinations(List<List<String>> matrix, int index, String current, List<String> result) {
|
private void generateCombinations(List<List<String>> matrix, int index, String current, List<String> result) {
|
||||||
if (index == matrix.size()) {
|
if (index == matrix.size()) {
|
||||||
result.add(current.trim());
|
result.add(current.trim());
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import com.imeeting.entity.biz.HotWordGroup;
|
||||||
import com.imeeting.entity.biz.Meeting;
|
import com.imeeting.entity.biz.Meeting;
|
||||||
import com.imeeting.entity.biz.MeetingTranscript;
|
import com.imeeting.entity.biz.MeetingTranscript;
|
||||||
import com.imeeting.entity.biz.PromptTemplate;
|
import com.imeeting.entity.biz.PromptTemplate;
|
||||||
|
import com.imeeting.dto.biz.MeetingParticipantVO;
|
||||||
import com.imeeting.event.MeetingCreatedEvent;
|
import com.imeeting.event.MeetingCreatedEvent;
|
||||||
import com.imeeting.mapper.biz.MeetingTranscriptMapper;
|
import com.imeeting.mapper.biz.MeetingTranscriptMapper;
|
||||||
import com.imeeting.dto.biz.AiModelVO;
|
import com.imeeting.dto.biz.AiModelVO;
|
||||||
|
|
@ -23,6 +24,7 @@ import com.imeeting.service.realtime.RealtimeMeetingAudioStorageService;
|
||||||
import com.unisbase.entity.SysUser;
|
import com.unisbase.entity.SysUser;
|
||||||
import com.unisbase.mapper.SysUserMapper;
|
import com.unisbase.mapper.SysUserMapper;
|
||||||
import com.unisbase.service.SysParamService;
|
import com.unisbase.service.SysParamService;
|
||||||
|
import com.unisbase.service.SysTenantUserService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
|
@ -47,6 +49,7 @@ import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
@ -61,6 +64,7 @@ public class MeetingDomainSupport {
|
||||||
private final MeetingTranscriptMapper transcriptMapper;
|
private final MeetingTranscriptMapper transcriptMapper;
|
||||||
private final MeetingPointsService meetingPointsService;
|
private final MeetingPointsService meetingPointsService;
|
||||||
private final SysUserMapper sysUserMapper;
|
private final SysUserMapper sysUserMapper;
|
||||||
|
private final SysTenantUserService sysTenantUserService;
|
||||||
private final ApplicationEventPublisher eventPublisher;
|
private final ApplicationEventPublisher eventPublisher;
|
||||||
private final MeetingSummaryFileService meetingSummaryFileService;
|
private final MeetingSummaryFileService meetingSummaryFileService;
|
||||||
private final MeetingPlaybackAudioResolver meetingPlaybackAudioResolver;
|
private final MeetingPlaybackAudioResolver meetingPlaybackAudioResolver;
|
||||||
|
|
@ -460,19 +464,31 @@ public class MeetingDomainSupport {
|
||||||
.map(Long::valueOf)
|
.map(Long::valueOf)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
vo.setParticipantIds(userIds);
|
vo.setParticipantIds(userIds);
|
||||||
|
vo.setParticipantUsers(Collections.emptyList());
|
||||||
if (!userIds.isEmpty()) {
|
if (!userIds.isEmpty()) {
|
||||||
List<SysUser> users = sysUserMapper.selectBatchIds(userIds);
|
List<SysUser> users = sysUserMapper.selectBatchIds(userIds);
|
||||||
String names = users.stream()
|
Map<Long, String> userNameMap = users.stream().collect(Collectors.toMap(
|
||||||
.map(u -> u.getDisplayName() != null ? u.getDisplayName() : u.getUsername())
|
SysUser::getUserId,
|
||||||
|
user -> resolveParticipantName(user, meeting.getTenantId())
|
||||||
|
));
|
||||||
|
List<MeetingParticipantVO> participantUsers = userIds.stream()
|
||||||
|
.map(userId -> new MeetingParticipantVO(userId, userNameMap.get(userId)))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
vo.setParticipantUsers(participantUsers);
|
||||||
|
String names = participantUsers.stream()
|
||||||
|
.map(MeetingParticipantVO::getName)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
.collect(Collectors.joining(", "));
|
.collect(Collectors.joining(", "));
|
||||||
vo.setParticipants(names);
|
vo.setParticipants(names);
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
vo.setParticipantIds(Collections.emptyList());
|
vo.setParticipantIds(Collections.emptyList());
|
||||||
|
vo.setParticipantUsers(Collections.emptyList());
|
||||||
vo.setParticipants(meeting.getParticipants());
|
vo.setParticipants(meeting.getParticipants());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vo.setParticipantIds(Collections.emptyList());
|
vo.setParticipantIds(Collections.emptyList());
|
||||||
|
vo.setParticipantUsers(Collections.emptyList());
|
||||||
}
|
}
|
||||||
fillLatestTaskAttemptInfo(meeting, vo);
|
fillLatestTaskAttemptInfo(meeting, vo);
|
||||||
if (includeSummary) {
|
if (includeSummary) {
|
||||||
|
|
@ -482,6 +498,13 @@ public class MeetingDomainSupport {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String resolveParticipantName(SysUser user, Long tenantId) {
|
||||||
|
if (user == null || user.getUserId() == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return user.getDisplayName() != null ? user.getDisplayName() : user.getUsername();
|
||||||
|
}
|
||||||
|
|
||||||
private void fillSummaryConfigurationNames(Meeting meeting, com.imeeting.dto.biz.MeetingVO vo) {
|
private void fillSummaryConfigurationNames(Meeting meeting, com.imeeting.dto.biz.MeetingVO vo) {
|
||||||
if (meeting.getSummaryModelId() != null) {
|
if (meeting.getSummaryModelId() != null) {
|
||||||
AiModelVO summaryModel = aiModelService.getModelById(meeting.getSummaryModelId(), "LLM");
|
AiModelVO summaryModel = aiModelService.getModelById(meeting.getSummaryModelId(), "LLM");
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,11 @@ const MEETING_DETAIL_TIMEOUT = 120000;
|
||||||
export type SummaryDetailLevel = "DETAILED" | "STANDARD" | "BRIEF";
|
export type SummaryDetailLevel = "DETAILED" | "STANDARD" | "BRIEF";
|
||||||
export type MeetingSource = "WINDOWS" | "MACOS" | "KYLIN" | "UOS" | "HARMONYOS" | "WEB" | "CUSTOM_TERMINAL" | "ANDROID";
|
export type MeetingSource = "WINDOWS" | "MACOS" | "KYLIN" | "UOS" | "HARMONYOS" | "WEB" | "CUSTOM_TERMINAL" | "ANDROID";
|
||||||
|
|
||||||
|
export interface MeetingParticipant {
|
||||||
|
id: number;
|
||||||
|
name: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
export interface MeetingCreateConfig {
|
export interface MeetingCreateConfig {
|
||||||
offlineEnabled: boolean;
|
offlineEnabled: boolean;
|
||||||
realtimeEnabled: boolean;
|
realtimeEnabled: boolean;
|
||||||
|
|
@ -27,6 +32,7 @@ export interface MeetingVO {
|
||||||
meetingTime: string;
|
meetingTime: string;
|
||||||
participants: string;
|
participants: string;
|
||||||
participantIds?: number[];
|
participantIds?: number[];
|
||||||
|
participantUsers?: MeetingParticipant[];
|
||||||
tags: string;
|
tags: string;
|
||||||
audioUrl: string;
|
audioUrl: string;
|
||||||
playbackAudioUrl?: string;
|
playbackAudioUrl?: string;
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ import {
|
||||||
uploadAudio,
|
uploadAudio,
|
||||||
} from "../../api/business/meeting";
|
} from "../../api/business/meeting";
|
||||||
import { getPromptPage, type PromptTemplateVO } from "../../api/business/prompt";
|
import { getPromptPage, type PromptTemplateVO } from "../../api/business/prompt";
|
||||||
|
import {useHotWordGroupLimit} from "../../hooks/useHotWordGroupLimit";
|
||||||
import type { SysUser } from "../../types";
|
import type { SysUser } from "../../types";
|
||||||
import "./MeetingCreateDrawer.css";
|
import "./MeetingCreateDrawer.css";
|
||||||
|
|
||||||
|
|
@ -121,6 +122,7 @@ export const MeetingCreateDrawer: React.FC<MeetingCreateDrawerProps> = ({
|
||||||
onSuccess,
|
onSuccess,
|
||||||
}) => {
|
}) => {
|
||||||
const { message } = App.useApp();
|
const { message } = App.useApp();
|
||||||
|
const {limit: hotWordGroupLimit} = useHotWordGroupLimit();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
|
|
||||||
|
|
@ -559,7 +561,15 @@ export const MeetingCreateDrawer: React.FC<MeetingCreateDrawerProps> = ({
|
||||||
<Row gutter={24}>
|
<Row gutter={24}>
|
||||||
<Col xs={24} md={12}>
|
<Col xs={24} md={12}>
|
||||||
<Form.Item name="hotWordGroupId" label="热词组" tooltip={selectedPrompt?.hotWordGroupName ? `默认跟随模板:${selectedPrompt.hotWordGroupName}` : "模板未绑定热词组时可手动选择"} extra={watchedHotWordGroupId != null ? "创建会议时会优先使用这里选中的热词组" : undefined}>
|
<Form.Item name="hotWordGroupId" label="热词组" tooltip={selectedPrompt?.hotWordGroupName ? `默认跟随模板:${selectedPrompt.hotWordGroupName}` : "模板未绑定热词组时可手动选择"} extra={watchedHotWordGroupId != null ? "创建会议时会优先使用这里选中的热词组" : undefined}>
|
||||||
<Select placeholder={selectedPrompt?.hotWordGroupId ? "默认已带出模板热词组,可按需修改" : "请选择热词组"} options={[{ label: "不使用热词组", value: 0 }, ...hotWordGroups.map((item) => ({ label: `${item.groupName} (${item.hotWordCount}/200)`, value: item.id }))]} />
|
<Select
|
||||||
|
placeholder={selectedPrompt?.hotWordGroupId ? "默认已带出模板热词组,可按需修改" : "请选择热词组"}
|
||||||
|
options={[{
|
||||||
|
label: "不使用热词组",
|
||||||
|
value: 0
|
||||||
|
}, ...hotWordGroups.map((item) => ({
|
||||||
|
label: `${item.groupName} (${item.hotWordCount}/${hotWordGroupLimit})`,
|
||||||
|
value: item.id
|
||||||
|
}))]}/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs={24} md={12}>
|
<Col xs={24} md={12}>
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ import {
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useDict } from "../../hooks/useDict";
|
import { useDict } from "../../hooks/useDict";
|
||||||
|
import {useHotWordGroupLimit} from "../../hooks/useHotWordGroupLimit";
|
||||||
import {
|
import {
|
||||||
deleteHotWord,
|
deleteHotWord,
|
||||||
getHotWordPage,
|
getHotWordPage,
|
||||||
|
|
@ -97,6 +98,7 @@ const HotWords: React.FC = () => {
|
||||||
const [groupForm] = Form.useForm<HotWordGroupFormValues>();
|
const [groupForm] = Form.useForm<HotWordGroupFormValues>();
|
||||||
const [bulkGroupForm] = Form.useForm<BulkGroupFormValues>();
|
const [bulkGroupForm] = Form.useForm<BulkGroupFormValues>();
|
||||||
const { items: categories } = useDict("biz_hotword_category");
|
const { items: categories } = useDict("biz_hotword_category");
|
||||||
|
const {limit: hotWordGroupLimit} = useHotWordGroupLimit();
|
||||||
const userProfile = useMemo(() => {
|
const userProfile = useMemo(() => {
|
||||||
const profileStr = sessionStorage.getItem("userProfile");
|
const profileStr = sessionStorage.getItem("userProfile");
|
||||||
return profileStr ? JSON.parse(profileStr) : {};
|
return profileStr ? JSON.parse(profileStr) : {};
|
||||||
|
|
@ -606,8 +608,9 @@ const HotWords: React.FC = () => {
|
||||||
item.id
|
item.id
|
||||||
? (
|
? (
|
||||||
<span className="hotwords-group-item__desc">
|
<span className="hotwords-group-item__desc">
|
||||||
<Tag color={item.hotWordCount >= 200 ? "red" : item.status === 1 ? "processing" : "default"}>
|
<Tag
|
||||||
{item.hotWordCount}/200
|
color={item.hotWordCount >= hotWordGroupLimit ? "red" : item.status === 1 ? "processing" : "default"}>
|
||||||
|
{item.hotWordCount}/{hotWordGroupLimit}
|
||||||
</Tag>
|
</Tag>
|
||||||
<span>{item.remark || "暂无备注"}</span>
|
<span>{item.remark || "暂无备注"}</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -766,7 +769,10 @@ const HotWords: React.FC = () => {
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs={24} sm={12}>
|
<Col xs={24} sm={12}>
|
||||||
<Form.Item name="hotWordGroupId" label="所属热词组">
|
<Form.Item name="hotWordGroupId" label="所属热词组">
|
||||||
<Select placeholder="请选择热词组" allowClear options={groupOptions.map((item) => ({ label: `${item.groupName} (${item.hotWordCount}/200)`, value: item.id }))} />
|
<Select placeholder="请选择热词组" allowClear options={groupOptions.map((item) => ({
|
||||||
|
label: `${item.groupName} (${item.hotWordCount}/${hotWordGroupLimit})`,
|
||||||
|
value: item.id
|
||||||
|
}))}/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
@ -843,7 +849,10 @@ const HotWords: React.FC = () => {
|
||||||
placeholder="请选择热词组"
|
placeholder="请选择热词组"
|
||||||
options={[
|
options={[
|
||||||
{ label: "未分组", value: 0 },
|
{ label: "未分组", value: 0 },
|
||||||
...groupOptions.map((item) => ({ label: `${item.groupName} (${item.hotWordCount}/200)`, value: item.id })),
|
...groupOptions.map((item) => ({
|
||||||
|
label: `${item.groupName} (${item.hotWordCount}/${hotWordGroupLimit})`,
|
||||||
|
value: item.id
|
||||||
|
})),
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ import {getHotWordGroupOptions, type HotWordGroupVO} from '../../api/business/ho
|
||||||
import { getPromptPage, PromptTemplateVO } from '../../api/business/prompt';
|
import { getPromptPage, PromptTemplateVO } from '../../api/business/prompt';
|
||||||
import { listUsers } from '../../api';
|
import { listUsers } from '../../api';
|
||||||
import { useDict } from '../../hooks/useDict';
|
import { useDict } from '../../hooks/useDict';
|
||||||
|
import {useHotWordGroupLimit} from '../../hooks/useHotWordGroupLimit';
|
||||||
import { SysUser } from '../../types';
|
import { SysUser } from '../../types';
|
||||||
import PageContainer from "../../components/shared/PageContainer";
|
import PageContainer from "../../components/shared/PageContainer";
|
||||||
import SectionCard from "../../components/shared/SectionCard";
|
import SectionCard from "../../components/shared/SectionCard";
|
||||||
|
|
@ -1214,6 +1215,7 @@ const ActiveTranscriptRow = React.memo<ActiveTranscriptRowProps>(({
|
||||||
|
|
||||||
const MeetingDetail: React.FC = () => {
|
const MeetingDetail: React.FC = () => {
|
||||||
const { message } = App.useApp();
|
const { message } = App.useApp();
|
||||||
|
const {limit: hotWordGroupLimit, loading: hotWordGroupLimitLoading} = useHotWordGroupLimit();
|
||||||
const { id } = useParams<{ id: string }>();
|
const { id } = useParams<{ id: string }>();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
|
|
@ -1886,11 +1888,15 @@ const MeetingDetail: React.FC = () => {
|
||||||
message.warning('请先选择关键词');
|
message.warning('请先选择关键词');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (hotWordGroupLimitLoading) {
|
||||||
|
message.info('热词组上限配置加载中,请稍后重试');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setHotWordGroupLoading(true);
|
setHotWordGroupLoading(true);
|
||||||
try {
|
try {
|
||||||
const response = await getHotWordGroupOptions();
|
const response = await getHotWordGroupOptions();
|
||||||
const options = (response.data?.data || []).filter((item) => item.status === 1 && item.hotWordCount < 200);
|
const options = (response.data?.data || []).filter((item) => item.status === 1 && item.hotWordCount < hotWordGroupLimit);
|
||||||
setHotWordGroupOptions(options);
|
setHotWordGroupOptions(options);
|
||||||
setSelectedHotWordGroupId(options.some((item) => item.id === meeting?.hotWordGroupId) ? meeting?.hotWordGroupId : options[0]?.id);
|
setSelectedHotWordGroupId(options.some((item) => item.id === meeting?.hotWordGroupId) ? meeting?.hotWordGroupId : options[0]?.id);
|
||||||
setHotWordGroupModalOpen(true);
|
setHotWordGroupModalOpen(true);
|
||||||
|
|
@ -4262,7 +4268,7 @@ const MeetingDetail: React.FC = () => {
|
||||||
onChange={setSelectedHotWordGroupId}
|
onChange={setSelectedHotWordGroupId}
|
||||||
options={[
|
options={[
|
||||||
...hotWordGroupOptions.map((item) => ({
|
...hotWordGroupOptions.map((item) => ({
|
||||||
label: `${item.groupName} (${item.hotWordCount}/200)`,
|
label: `${item.groupName} (${item.hotWordCount}/${hotWordGroupLimit})`,
|
||||||
value: item.id,
|
value: item.id,
|
||||||
})),
|
})),
|
||||||
]}
|
]}
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ import ReactMarkdown from 'react-markdown';
|
||||||
import remarkGfm from 'remark-gfm';
|
import remarkGfm from 'remark-gfm';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useDict } from '../../hooks/useDict';
|
import { useDict } from '../../hooks/useDict';
|
||||||
|
import {useHotWordGroupLimit} from '../../hooks/useHotWordGroupLimit';
|
||||||
import {
|
import {
|
||||||
deletePromptTemplate,
|
deletePromptTemplate,
|
||||||
clearPromptDefault,
|
clearPromptDefault,
|
||||||
|
|
@ -69,6 +70,7 @@ const PromptTemplates: React.FC = () => {
|
||||||
const { items: categories, loading: dictLoading } = useDict('biz_prompt_category');
|
const { items: categories, loading: dictLoading } = useDict('biz_prompt_category');
|
||||||
const { items: dictTags } = useDict('biz_prompt_tag');
|
const { items: dictTags } = useDict('biz_prompt_tag');
|
||||||
const { items: promptLevels } = useDict('biz_prompt_level');
|
const { items: promptLevels } = useDict('biz_prompt_level');
|
||||||
|
const {limit: hotWordGroupLimit} = useHotWordGroupLimit();
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [data, setData] = useState<PromptTemplateVO[]>([]);
|
const [data, setData] = useState<PromptTemplateVO[]>([]);
|
||||||
|
|
@ -585,7 +587,10 @@ const PromptTemplates: React.FC = () => {
|
||||||
<Select
|
<Select
|
||||||
placeholder="请选择热词组"
|
placeholder="请选择热词组"
|
||||||
allowClear
|
allowClear
|
||||||
options={groupOptions.map((item) => ({ label: `${item.groupName} (${item.hotWordCount}/200)`, value: item.id }))}
|
options={groupOptions.map((item) => ({
|
||||||
|
label: `${item.groupName} (${item.hotWordCount}/${hotWordGroupLimit})`,
|
||||||
|
value: item.id
|
||||||
|
}))}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,11 @@ export interface TokenResponse {
|
||||||
refreshExpiresInDays: number;
|
refreshExpiresInDays: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface MeetingParticipant {
|
||||||
|
id: number;
|
||||||
|
name: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
export interface MeetingVO {
|
export interface MeetingVO {
|
||||||
id: number;
|
id: number;
|
||||||
tenantId: number;
|
tenantId: number;
|
||||||
|
|
@ -36,6 +41,7 @@ export interface MeetingVO {
|
||||||
meetingTime: string;
|
meetingTime: string;
|
||||||
participants: string;
|
participants: string;
|
||||||
participantIds?: number[];
|
participantIds?: number[];
|
||||||
|
participantUsers?: MeetingParticipant[];
|
||||||
tags: string;
|
tags: string;
|
||||||
audioUrl: string;
|
audioUrl: string;
|
||||||
playbackAudioUrl?: string;
|
playbackAudioUrl?: string;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue