| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142 |
- import * as React from 'react';
- import { observer } from 'mobx-react';
- import {
- List,
- Button,
- Divider,
- Flex,
- Layout,
- Empty,
- Image,
- Modal,
- Tag,
- message,
- Tooltip,
- Select,
- Form,
- Space,
- Row,
- Col,
- Input, Cascader, Card
- } from 'antd';
- import {
- PlusOutlined,
- FileOutlined,
- SettingOutlined,
- DeleteOutlined,
- StepForwardOutlined,
- SearchOutlined,
- ReloadOutlined,
- BookOutlined,
- TeamOutlined,
- AppstoreOutlined,
- EditOutlined, CloseOutlined, BulbOutlined, UpOutlined, DownOutlined
- } from '@ant-design/icons';
- import { apis } from '@/apis';
- import './style.less';
- import { PaginationConfig } from 'antd/es/pagination';
- import router from '@/router';
- import LocalStorage from '@/LocalStorage';
- import { create } from 'domain';
- import audit from '../../audit';
- import { set } from 'mobx';
- import IconSvg from "@/assets/public/icon.svg";
- import dayjs from 'dayjs';
- import UpdateNotification from '@/help/components/UpdateNotification';
- import { CURRENT_VERSION } from '@/help/components/UpdateNotification/version';
- const { Header, Footer, Sider, Content } = Layout;
- const { Option } = Select;
- const FormItem = Form.Item;
- const headerStyle: React.CSSProperties = {
- textAlign: 'center',
- height: 24,
- paddingInline: 48,
- lineHeight: '30px',
- backgroundColor: '#fff',
- };
- const contentStyle: React.CSSProperties = {
- textAlign: 'center',
- lineHeight: '40px',
- backgroundColor: '#fff',
- };
- const siderStyle: React.CSSProperties = {
- paddingLeft: 30,
- paddingTop: 30,
- height: 80,
- backgroundColor: '#fff',
- };
- const footerStyle: React.CSSProperties = {
- textAlign: 'center',
- color: '#fff',
- height: 24,
- backgroundColor: '#4096ff',
- };
- const layoutStyle = {
- borderRadius: 8,
- overflow: 'hidden',
- width: 'calc(10% - 8px)',
- maxWidth: 'calc(20% - 8px)',
- };
- const QuestionAnswerList: React.FC = () => {
- const [form] = Form.useForm();
- interface Item {
- name: string,
- desc: string,
- appId: number,
- createBy: string,
- typeId: string;
- status: string;
- comment: string;
- auditStatus: string;
- projectName: string;
- updateTime: string;
- };
- interface PageInfo {
- pageNumber: number,
- pageSize: number,
- total: number,
- };
- type AppTypeList = {
- label: string,
- value: string,
- }[];
- type ProjectTypeList = {
- label: string,
- value: string,
- }[];
- const [listLoading, setListLoading] = React.useState(false);
- const [list, setList] = React.useState<Item[]>([]);
- const [originalList, setOriginalList] = React.useState<Item[]>([]); // 保存原始列表数据,用于前端过滤
- const [page, setPage] = React.useState<PageInfo>({
- pageNumber: 1,
- pageSize: 10,
- total: 0,
- });
- const [appCount, setAppCount] = React.useState<string>();
- const [knowCount, setKnowCount] = React.useState<string>();
- const { Header, Footer, Sider, Content } = Layout;
- const [appTypeList, setAppTypeList] = React.useState<AppTypeList>([]);
- const [createFlag, setCreateFlag] = React.useState(false);
- const [deleteFlag, setDeleteFlag] = React.useState(false);
- const [updateFlag, setUpdateFlag] = React.useState(false);
- const [userInfoAll, setUserInfoAll] = React.useState<any>({});
- const [projectList, setProjectList] = React.useState<ProjectTypeList>([]);
- const [appProjectList, setAppProjectList] = React.useState<AppTypeList>([]);
- const [showSubPanel, setShowSubPanel] = React.useState(false);
- const [selectedType, setSelectedType] = React.useState<string | null>('全部');
- const wrapperRef = React.useRef<HTMLDivElement>(null);
- const selectRef = React.useRef<any>(null);
- const [levelTypeList, setLevelTypeList] = React.useState<AppTypeList>([]);
- // 新手引导整体可见性(持久化到 localStorage)
- const [showGuide, setShowGuide] = React.useState<boolean>(() => localStorage.getItem('appGuideHidden') !== 'true');
- // 新手引导展开/折叠状态(持久化到 localStorage),默认展开
- const [isGuideExpanded, setIsGuideExpanded] = React.useState<boolean>(() => {
- const saved = localStorage.getItem('appGuideExpanded');
- // 如果 localStorage 中没有值,默认展开(返回 true)
- return saved === null ? true : saved === 'true';
- });
- const toggleGuide = () => {
- setIsGuideExpanded(prev => {
- const newValue = !prev;
- // 保存到 localStorage
- localStorage.setItem('appGuideExpanded', String(newValue));
- return newValue;
- });
- };
- // 搜索输入框展开状态
- const [isSearchExpanded, setIsSearchExpanded] = React.useState(false);
- const searchWrapperRef = React.useRef<HTMLDivElement>(null);
- const searchInputRef = React.useRef<any>(null);
- // 标记是否正在重置,避免触发 useEffect 循环
- const isResettingRef = React.useRef(false);
- const appApi = {
- fetchList: async (typeId: any, projectId: any, forceRefresh: boolean = false, pageNumber?: number) => {
- const keyword = form.getFieldValue('keyword');
- const currentPageNumber = pageNumber !== undefined ? pageNumber : page.pageNumber;
-
- // 如果有关键字且不是强制刷新,直接从现有数据筛选,不请求接口
- if (keyword && keyword.trim() !== '' && !forceRefresh) {
- applyFrontendFilter(originalList, keyword, currentPageNumber);
- return;
- }
- setListLoading(true);
- try {
- const userInfo = LocalStorage.getUserInfo();
- const userId = (userInfo?.id ?? '').toString();
- const res = await apis.fetchTakaiAppList({
- pageSize: page.pageSize,
- pageNumber: currentPageNumber,
- userId: userId,
- typeId: typeId,
- projectId: projectId?.toString(),
- keyword: '', // 不传关键字给后端
- name: '', // 不传name给后端
- })
- const list = res.rows.map((item: any) => {
- return {
- name: item.name,
- desc: item.desc,
- appId: item.appId,
- createBy: item.createBy,
- typeId: item.typeId,
- status: item.status,
- comment: item.comment,
- auditStatus: item.auditStatus,
- projectName: item.projectName,
- updateTime: item.updateTime
- }
- });
- const c = LocalStorage.getStatusFlag('deepseek:application:create');
- const u = LocalStorage.getStatusFlag('deepseek:application:delete');
- const filteredList = list.filter((item: any) => {
- // 如果有 createFlag 或 updateFlag 权限,显示所有数据
- if (c || u) {
- return true;
- }
- // 没有权限时排除 status='5' 的数据
- return item.status !== '5';
- });
- // 保存原始数据
- setOriginalList(filteredList);
- // 没有关键字时,显示当前页的数据
- setList(filteredList);
- setPage({
- pageNumber: currentPageNumber,
- pageSize: page.pageSize,
- total: res.total,
- });
- } catch (error) {
- console.error(error);
- } finally {
- setListLoading(false);
- }
- },
- auditApplication: async (appId: string, userId: string) => {
- const res = await apis.auditTakaiApplicationLibApi(appId, userId);
- if (res.data === 9) {
- message.error('您没有添加审核人');
- }
- await appApi.fetchList(null, null);
- }
- };
- // 立即使用应用
- const useNowAppLication = (appId: number) => {
- const userInfo = LocalStorage.getUserInfo();
- const getToken = LocalStorage.getToken();
- // const baseUrl = import.meta.env.VITE_JUMP_URL;
- const baseUrl = 'https://llm.jkec.info:11432/#/knowledgeChat?showMenu=false&chatMode=LOCAL'
- window.open(`${baseUrl}&appId=${appId}&userId=${userInfo?.id}&nickName=${userInfo?.name}&token=${getToken}`, '_blank');
- }
- // 删除应用
- const delApplication = async (appId: string) => {
- try {
- await apis.deleteTakaiApplicationApi(appId);
- await appApi.fetchList(null, null);
- } catch (error) {
- console.error(error);
- }
- }
- const indexApi = {
- fetchIndex: async (typeId: any, projectId: any, pageNumber?: number) => {
- try {
- const userInfo = LocalStorage.getUserInfo();
- const userId = (userInfo?.id ?? '').toString();
- const keyword = form.getFieldValue('keyword');
- const currentPageNumber = pageNumber !== undefined ? pageNumber : page.pageNumber;
- const res = await apis.fetchTakaiIndexCount({
- pageSize: page.pageSize,
- pageNumber: currentPageNumber,
- userId: userId,
- typeId: typeId,
- projectId: projectId?.toString(),
- keyword: keyword,
- })
- setAppCount(res.data.applicationCount);
- setKnowCount(res.data.knowledgeCount);
- } catch (error) {
- console.error(error);
- } finally {
- setListLoading(false);
- }
- }
- };
- // 获取应用类型
- const appTypeApi = {
- fetchAppType: async () => {
- try {
- const res = await apis.fetchTakaiAppTypeList('app_type');
- const list = res.data.map((item: any) => {
- return {
- label: item.dictLabel,
- value: item.dictCode,
- }
- });
- setAppTypeList(list);
- } catch (error: any) {
- console.error(error);
- }
- },
- };
- // 项目级应用下的类型
- const appProTypeApi = {
- fetchAppProType: async () => {
- try {
- const res = await apis.fetchTakaiAppTypeList('projectTree');
- // const list: AppTypeList = res.data;
- const list: AppTypeList = res.data?.reduce((acc: any, item: any) => {
- if (item.children.length > 0) {
- item.children.forEach((val: any) => {
- acc.push({
- label: val.label,
- value: `${val.value}`,
- })
- })
- }
- return acc;
- }, []);
- setAppProjectList(list);
- // const res = await apis.fetchTakaiAppTypeList('projectTree');
- // const list = res.data.map((item: any) => {
- // return {
- // label: item.dictLabel,
- // value: item.dictCode,
- // }
- // });
- // setAppProjectList(list);
- } catch (error: any) {
- console.error(error);
- }
- },
- };
- const projectApi = {
- fetchProject: async () => {
- try {
- const res = await apis.fetchTakaiProjectLibApi();
- const list = res.data.map((item: any) => {
- return {
- label: item.projectName,
- value: item.projectId,
- }
- });
- setProjectList(list);
- } catch (error: any) {
- console.error(error);
- }
- },
- };
- // 获取应用类型
- const levelTypeApi = {
- fetchLevelAppType: async () => {
- try {
- const res = await apis.fetchTakaiAppTypeList('project_type');
- const list = res.data.map((item: any) => {
- return {
- label: item.dictLabel,
- value: item.dictCode,
- }
- });
- setLevelTypeList(list);
- } catch (error: any) {
- console.error(error);
- }
- },
- };
- const init = async () => {
- await appApi.fetchList(null, null, true); // 强制刷新
- await indexApi.fetchIndex(null, null);
- await appTypeApi.fetchAppType();
- await projectApi.fetchProject();
- await appProTypeApi.fetchAppProType();
- await levelTypeApi.fetchLevelAppType();
- // 设置默认选择"全部"
- form.setFieldsValue({ typeId: '全部' });
- }
- React.useEffect(() => {
- // 如果正在重置,跳过执行,避免循环
- if (isResettingRef.current) {
- isResettingRef.current = false;
- return;
- }
- setCreateFlag(LocalStorage.getStatusFlag('deepseek:application:create'));
- setDeleteFlag(LocalStorage.getStatusFlag('deepseek:application:delete'));
- setUpdateFlag(LocalStorage.getStatusFlag('deepseek:application:update'));
- setUserInfoAll(LocalStorage.getUserInfo());
- init();
- }, [page.pageSize, page.pageNumber])
- const paginationConfig: PaginationConfig = {
- // 显示数据总量
- showTotal: (total: number) => {
- return `共 ${total} 条`;
- },
- // 展示分页条数切换
- showSizeChanger: true,
- // 指定每页显示条数
- // pageSizeOptions: ['2', '20', '50', '100'],
- // 快速跳转至某页
- showQuickJumper: true,
- current: page.pageNumber,
- pageSize: page.pageSize,
- total: page.total,
- onChange: (pageNumber, pageSize) => {
- const keyword = form.getFieldValue('keyword');
- // 根据是否有搜索关键字,决定使用哪个数据源
- const dataSource = keyword && keyword.trim() !== ''
- ? originalList.filter((item: Item) =>
- item.name && item.name.toLowerCase().includes(keyword.toLowerCase().trim())
- )
- : originalList;
-
- // 获取新页的数据
- const startIndex = (pageNumber - 1) * pageSize;
- const endIndex = startIndex + pageSize;
- const paginatedData = dataSource.slice(startIndex, endIndex);
-
- setList(paginatedData);
- setPage({
- pageNumber: pageNumber,
- pageSize: pageSize,
- total: dataSource.length,
- });
- },
- };
- // 前端模糊查询过滤函数
- const applyFrontendFilter = (dataList: Item[], keyword: string | undefined, currentPageNumber: number = 1) => {
- if (!keyword || keyword.trim() === '') {
- // 如果没有关键字,显示所有数据
- const paginatedData = getPaginatedData(dataList, currentPageNumber, page.pageSize);
- setList(paginatedData);
- setPage(prev => ({
- ...prev,
- total: dataList.length,
- pageNumber: currentPageNumber,
- }));
- return;
- }
- // 对标题进行模糊匹配(不区分大小写)
- const filtered = dataList.filter((item: Item) => {
- return item.name && item.name.toLowerCase().includes(keyword.toLowerCase().trim());
- });
- // 计算过滤后的总页数
- const totalPages = Math.ceil(filtered.length / page.pageSize);
- // 如果当前页码超出了总页数,调整到最后一页(至少为1)
- const adjustedPageNumber = Math.min(currentPageNumber, Math.max(1, totalPages));
- // 获取调整后页码的数据
- const paginatedData = getPaginatedData(filtered, adjustedPageNumber, page.pageSize);
- setList(paginatedData);
- setPage(prev => ({
- ...prev,
- total: filtered.length,
- pageNumber: adjustedPageNumber,
- }));
- };
- // 获取分页数据
- const getPaginatedData = (dataList: Item[], pageNumber: number, pageSize: number) => {
- const startIndex = (pageNumber - 1) * pageSize;
- const endIndex = startIndex + pageSize;
- return dataList.slice(startIndex, endIndex);
- };
- // 点击查询
- const handleClickSearch = async () => {
- form.validateFields().then(async (values) => {
- const keyword = values.keyword;
-
- // 如果有关键字,直接从现有数据中筛选,不请求接口
- if (keyword && keyword.trim() !== '') {
- // 模糊查询:从现有数据中筛选,保持当前页码
- applyFrontendFilter(originalList, keyword, page.pageNumber);
- return;
- }
- // 如果没有关键字,正常查询接口
- if (values.proTypeId) {
- values.typeId = values.proTypeId;
- }
- if (values.typeId === '全部') {
- values.typeId = null;
- }
- if (values.projectId instanceof Array && values.projectId.length == 2) {
- values.projectId = values.projectId[1];
- }
- // 重置到第一页
- setPage(prev => ({ ...prev, pageNumber: 1 }));
- await indexApi.fetchIndex(values.typeId, values.projectId);
- await appApi.fetchList(values.typeId, values.projectId, true); // 强制刷新
- }).catch((error) => {
- console.error(error);
- });
- };
- // 点击重置
- const handleClickReset = async () => {
- form.resetFields();
- setShowSubPanel(false);
- setSelectedType('全部'); // 重置为"全部"
- // 标记正在重置,避免触发 useEffect 循环
- isResettingRef.current = true;
- // 先更新 page 到第一页
- setPage({
- pageNumber: 1,
- pageSize: 10,
- total: 0,
- });
- // 调用接口获取数据,传递 pageNumber: 1 确保返回第一页
- await appApi.fetchList(null, null, true, 1); // 强制刷新,第一页
- await indexApi.fetchIndex(null, null, 1); // 第一页
- };
- /** 点击外部关闭面板 */
- React.useEffect(() => {
- const handleClickOutside = (event: MouseEvent) => {
- if (wrapperRef.current && !wrapperRef.current.contains(event.target as Node)) {
- setShowSubPanel(false);
- }
- };
- document.addEventListener('mousedown', handleClickOutside, true);
- return () => {
- document.removeEventListener('mousedown', handleClickOutside, true);
- };
- }, []);
- /** 点击外部关闭搜索框 */
- React.useEffect(() => {
- const handleClickOutside = (event: MouseEvent) => {
- if (searchWrapperRef.current && !searchWrapperRef.current.contains(event.target as Node)) {
- setIsSearchExpanded(false);
- }
- };
- if (isSearchExpanded) {
- document.addEventListener('mousedown', handleClickOutside, true);
- return () => {
- document.removeEventListener('mousedown', handleClickOutside, true);
- };
- }
- }, [isSearchExpanded]);
- // 展开搜索框并聚焦输入框
- const handleExpandSearch = () => {
- setIsSearchExpanded(true);
- // 延迟聚焦,确保输入框已渲染
- setTimeout(() => {
- const input = searchInputRef.current?.input || searchInputRef.current;
- if (input) {
- input.focus();
- input.select(); // 选中输入框中的文本
- }
- }, 150);
- };
- const handleAppTypeChange = (value: string) => {
- if (value === '41') {
- // 如果是项目级应用,切换面板状态
- // setShowSubPanel(prev => !prev);
- setShowSubPanel(true);
- } else {
- // 其他选项,隐藏面板
- setShowSubPanel(false);
- }
- setSelectedType(value);
- form.setFieldsValue({ typeId: value });
- // 自动提交逻辑
- if (value === '全部') {
- // 全部选项,传递null给后端
- appApi.fetchList(null, null, true); // 强制刷新
- indexApi.fetchIndex(null, null);
- } else {
- // 其他选项,传递对应的typeId
- appApi.fetchList(value, null, true); // 强制刷新
- indexApi.fetchIndex(value, null);
- }
- };
- const handleAppProTypeChange = (value: string) => {
- console.log(value, 'valuevalue');
- setSelectedType(value);
- form.setFieldsValue({ typeId: value });
- };
- return (
- <div>
- {/* 更新通知弹窗 - 只在此页面显示 */}
- <UpdateNotification version={CURRENT_VERSION} />
-
- <div style={{ padding: '16px 20px', display: 'flex' }}>
- <Form
- form={form}
- layout='inline'
- colon={false}
- style={{ flex: 1 }}
- >
- <div>
- {/* 主选择器 - 修改为按钮组形式 */}
- <FormItem
- name="typeId"
- style={{ marginBottom: 0 }}
- >
- <div className="filter-button-group">
- {/* 全部按钮 */}
- <Button
- key="全部"
- type={selectedType === '全部' ? 'primary' : 'default'}
- size="small"
- onClick={() => handleAppTypeChange('全部')}
- >
- 全部
- </Button>
- {/* 动态应用类型按钮 */}
- {appTypeList.map(item => {
- // 根据label匹配对应的图标
- let icon = null;
- const isSelected = selectedType === item.value;
- if (item.label === '专业知识') {
- icon = <BookOutlined style={{ fontSize: '14px', marginRight: '0' }} />;
- } else if (item.label === '职能管理') {
- icon = <TeamOutlined style={{ fontSize: '14px', marginRight: '0' }} />;
- } else if (item.label === '项目级应用') {
- icon = <AppstoreOutlined style={{ fontSize: '14px', marginRight: '0' }} />;
- }
- return (
- <Button
- key={item.value}
- type={isSelected ? 'primary' : 'default'}
- size="small"
- onClick={() => handleAppTypeChange(item.value)}
- >
- {icon}
- {item.label}
- </Button>
- );
- })}
- </div>
- </FormItem>
- {/* 子选项面板 */}
- {showSubPanel && selectedType === '41' && (
- <FormItem
- label='类型'
- name='proTypeId'
- rules={[{ required: true, message: '类型不能为空' }]}
- >
- <Select
- placeholder='请选择'
- allowClear
- // style={ { width: 200 } }
- onChange={(value) => {
- // 项目类型选择器自动提交逻辑
- const currentProjectId = form.getFieldValue('projectId');
- appApi.fetchList(value, currentProjectId, true); // 强制刷新
- indexApi.fetchIndex(value, currentProjectId);
- }}
- >
- {
- appProjectList.map((item, index) => {
- return <Option value={item.value} key={index}>
- {item.label}
- </Option>
- })
- }
- </Select>
- </FormItem>
- )}
- </div>
- {/* {
- appProjectList.map((subItem, index) => (
- <div key={index}>
- {subItem.label}
- </div>
- ))
- } */ }
- {appTypeList.find(item => item.value === selectedType)?.label === '项目级应用' && (
- <FormItem name='projectId'>
- <Cascader
- options={appProjectList}
- placeholder="请选择项目"
- showSearch
- onChange={(value) => {
- // 项目选择器自动提交逻辑
- const currentProTypeId = form.getFieldValue('proTypeId');
- let projectId: any = value;
- // 如果是数组且长度为2,取第二个元素(项目ID)
- if (projectId instanceof Array && projectId.length === 2) {
- projectId = projectId[1];
- }
- appApi.fetchList(currentProTypeId, projectId, true); // 强制刷新
- indexApi.fetchIndex(currentProTypeId, projectId);
- }}
- />
- </FormItem>
- )}
- {/*<Select*/}
- {/* placeholder='请选择项目'*/}
- {/* allowClear*/}
- {/* onChange={(value) => {*/}
- {/* // 项目选择器自动提交逻辑*/}
- {/* const currentTypeId = form.getFieldValue('typeId');*/}
- {/* const typeId = currentTypeId === '全部' ? null : currentTypeId;*/}
- {/* appApi.fetchList(typeId, value);*/}
- {/* indexApi.fetchIndex(typeId, value);*/}
- {/* }}*/}
- {/*>*/}
- {/* {*/}
- {/* projectList.map((item, index) => {*/}
- {/* return <Option value={item.value} key={index}>*/}
- {/* {item.label}*/}
- {/* </Option>*/}
- {/* })*/}
- {/* }*/}
- {/*</Select>*/}
- {/* </FormItem> */}
- <FormItem>
- <Space size={12}>
- {/* <div
- className={`search-expand-wrapper ${isSearchExpanded ? 'expanded' : ''}`}
- ref={searchWrapperRef}
- >
- <div className={`search-input-container ${isSearchExpanded ? 'expanded' : ''}`}>
- <FormItem name='keyword' style={{ marginBottom: 0 }}>
- <Input
- ref={searchInputRef}
- className="search-input"
- placeholder="请输入关键字"
- allowClear
- onPressEnter={handleClickSearch}
- onFocus={() => setIsSearchExpanded(true)}
- />
- </FormItem>
- </div>
- <Button
- type='primary'
- className="search-button-blue"
- onClick={() => {
- if (isSearchExpanded) {
- handleClickSearch();
- } else {
- handleExpandSearch();
- }
- }}
- icon={<SearchOutlined />}
- />
- </div> */}
- <Tooltip title="重置">
- <Button
- shape="circle"
- icon={<ReloadOutlined />}
- onClick={handleClickReset}
- />
- </Tooltip>
- </Space>
- </FormItem>
- {/* {
- createFlag && (
- <div style={ { marginLeft: 'auto' } }>
- <Button type='primary'
- icon={ <PlusOutlined /> }
- onClick={ () => {
- router.navigate( { pathname: '/deepseek/questionAnswer/create' } );
- } }>创建问答应用</Button>
- </div>
- )
- }
- */}
- {/* 创建按钮已移至面包屑组件 */}
- </Form>
- </div>
-
- {/* 新手使用提示区块 */}
- {showGuide && (
- <div style={{ padding: '12px 20px 12px 20px' }}>
- <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: isGuideExpanded ? 8 : 0 }}>
- <div style={{ fontSize: 13, color: '#333', display: 'flex', alignItems: 'center', gap: 6 }}>
- <BulbOutlined style={{ color: '#faad14' }} />
- 提示:如何创建并发布自己的RAG(增强检索生成)应用?
- </div>
- <div onClick={toggleGuide} style={{ color: '#999', cursor: 'pointer', display: 'flex', alignItems: 'center' }}>
- {isGuideExpanded ? <UpOutlined /> : <DownOutlined />}
- </div>
- </div>
- {isGuideExpanded && (
- <Row gutter={12}>
- <Col xs={24} sm={24} md={12} lg={8}>
- <Card
- size="small"
- bordered={false}
- style={{
- background: 'linear-gradient(90deg, #e6f4ff 0%, #f0f7ff 100%)',
- boxShadow: '0 1px 2px rgba(0,0,0,0.04)',
- borderRadius: 8,
- height: '100%'
- }}
- bodyStyle={{ display: 'flex', flexDirection: 'column', justifyContent: 'space-between', minHeight: 80 }}
- title={<span style={{ fontWeight: 600 }}>创建或选用公共知识库</span>}
- >
- <div style={{ color: '#666', fontSize: 12 }}>选择公共知识库,或点击知识库菜单栏,创建自己的知识库。</div>
- <div style={{ textAlign: 'right', color: '#1677ff', fontWeight: 600 }}>step 1</div>
- </Card>
- </Col>
- <Col xs={24} sm={24} md={12} lg={8}>
- <Card
- size="small"
- bordered={false}
- style={{
- background: 'linear-gradient(90deg, #e6fffb 0%, #f0fffe 100%)',
- boxShadow: '0 1px 2px rgba(0,0,0,0.04)',
- borderRadius: 8,
- height: '100%'
- }}
- bodyStyle={{ display: 'flex', flexDirection: 'column', justifyContent: 'space-between', minHeight: 80 }}
- title={<span style={{ fontWeight: 600 }}>参数配置</span>}
- >
- <div style={{ color: '#666', fontSize: 12 }}>点击右上角,创建应用,选择模型与知识范围,配置Prompt、检索策略并调试。</div>
- <div style={{ textAlign: 'right', color: '#1677ff', fontWeight: 600 }}>step 2</div>
- </Card>
- </Col>
- <Col xs={24} sm={24} md={12} lg={8}>
- <Card
- size="small"
- bordered={false}
- style={{
- background: 'linear-gradient(90deg, #fff7e6 0%, #fffaf0 100%)',
- boxShadow: '0 1px 2px rgba(0,0,0,0.04)',
- borderRadius: 8,
- height: '100%'
- }}
- bodyStyle={{ display: 'flex', flexDirection: 'column', justifyContent: 'space-between', minHeight: 80 }}
- title={<span style={{ fontWeight: 600 }}>发布应用</span>}
- >
- <div style={{ color: '#666', fontSize: 12 }}>发布后可在相应的项目内使用。</div>
- <div style={{ textAlign: 'right', color: '#1677ff', fontWeight: 600 }}>step 3</div>
- </Card>
- </Col>
- </Row>
- )}
- </div>
- )}
- {
- list.length
- ?
- <div className='questionAnswerList'>
- {/*<div style={ { overflow: 'auto' } }>*/}
- {/* <Flex gap="middle" wrap>*/}
- {/* <Layout style={ layoutStyle }>*/}
- {/* <Sider width="25%" style={ siderStyle }>*/}
- {/* <FileOutlined />*/}
- {/* </Sider>*/}
- {/* <Layout>*/}
- {/* <Header style={ headerStyle }>问答应用总数</Header>*/}
- {/* <Content style={ contentStyle }>{ appCount }个</Content>*/}
- {/* </Layout>*/}
- {/* </Layout>*/}
- {/* <Layout style={ layoutStyle }>*/}
- {/* <Sider width="25%" style={ siderStyle }>*/}
- {/* <FileOutlined />*/}
- {/* </Sider>*/}
- {/* <Layout>*/}
- {/* <Header style={ headerStyle }>知识库总数</Header>*/}
- {/* <Content style={ contentStyle }>{ knowCount } 个</Content>*/}
- {/* </Layout>*/}
- {/* </Layout>*/}
- {/* </Flex>*/}
- {/*</div>*/}
- {/*<div style={ { display: 'flex', justifyContent: 'space-between', padding: '16px 20px' } }>*/}
- {/* <div>所有问答应用</div>*/}
- {/* /!*{*!/*/}
- {/* /!* createFlag &&*!/*/}
- {/* /!* <Button type='primary'*!/*/}
- {/* /!* icon={ <PlusOutlined /> }*!/*/}
- {/* /!* onClick={ () => {*!/*/}
- {/* /!* router.navigate( { pathname: '/deepseek/questionAnswer/create' } );*!/*/}
- {/* /!* } }>创建问答应用</Button>*!/*/}
- {/* /!*}*!/*/}
- {/*</div>*/}
- <div className='applicationList'>
- <List grid={{
- gutter: 16,
- xs: 1,
- sm: 1,
- md: 2,
- lg: 2,
- xl: 3,
- xxl: 4, // 展示的列数
- }}
- dataSource={list}
- renderItem={(item) => (
- <List.Item>
- <div className='card'>
- <div style={{
- display: 'flex',
- justifyContent: 'space-between',
- alignItems: 'center',
- overflow: 'hidden',
- }}>
- <div style={{ display: 'flex', alignItems: 'center', overflow: 'auto' }}>
- <div style={{ marginRight: 10, overflow: 'auto' }}>
- <Image
- width={32}
- height={32}
- src={IconSvg}
- preview={false}
- />
- </div>
- {/*<div style={ { overflow: 'auto' } }>*/}
- {/* { item.name }*/}
- {/*</div>*/}
- <div style={{
- display: 'flex',
- flexDirection: 'column',
- justifyContent: 'center',
- overflow: 'hidden',
- maxWidth: '85%',
- height: '100%'
- }}>
- <Tooltip title={item.name} placement="top">
- <div style={{
- lineHeight: '18px',
- fontSize: 14,
- fontWeight: 500,
- overflow: 'hidden',
- textOverflow: 'ellipsis',
- whiteSpace: 'nowrap',
- // maxWidth: '200px', // 可以根据需要调整宽度
- cursor: 'pointer'
- }}>
- {item.name.length > 20 ? `${item.name.substring(0, 30)}...` : item.name}
- </div>
- </Tooltip>
- <Space size={4} style={{ lineHeight: '18px' }}>
- <span style={{
- color: '#999',
- fontSize: 12,
- margin: 0
- }}>ID:{item.appId}</span>
- <Divider type="vertical" style={{ color: '999', margin: 0, height: 12 }} />
- <span
- style={ {
- color: '#999',
- fontSize: 12,
- display: 'inline-block',
- maxWidth: '100%', // 限制最大宽度
- flex: 1, // 使span占据剩余空间
- whiteSpace: 'nowrap', // 禁止换行
- overflow: 'hidden', // 隐藏溢出内容
- textOverflow: 'ellipsis', // 显示省略号
- verticalAlign: 'middle' // 垂直居中
- } }
- title={ item.projectName } // 鼠标悬停时显示完整名称
- >
- {item.projectName}
- </span>
- {/*<span style={{ color: '#999', fontSize: 12 }}>*/}
- {/* {*/}
- {/* item.projectName && item.projectName.length > 8 ?*/}
- {/* `${item.projectName.substring(0, 8)}...` :*/}
- {/* item.projectName*/}
- {/* }*/}
- {/*</span>*/}
- </Space>
- </div>
- </div>
- <div>
- <>
- {/*{ item.projectName } 移动599 line*/}
- {
- (item.status !== null && item.status !== '3') &&
- < Tag style={{
- // marginLeft: 16,
- width: 65,
- color: '#fff',
- height: 24,
- backgroundColor: item.status === '1' ? '#D26900' : item.status === '2' ? '#408080' : item.auditStatus === '4' ? '#CE0000' : item.status === '5' ? '#5151A2' : ''
- }}>
- {item.status === '1' ? '待审核' : item.status === '2' ? '审核中' : item.auditStatus === '4' ? '审核拒绝' : item.status === '5' ? '待提交' : '未知'}
- </Tag>
- }
- {
- (item.auditStatus === '4') &&
- <Tooltip title={item.comment}>
- {
- item.comment !== '' && item.comment !== null && item.comment.length > 10 ?
- item.comment.substring(0, 10) + '......' :
- item.comment
- }
- </Tooltip>
- }
- </>
- </div>
- </div>
- <Divider plain style={{ margin: '16px 0' }}></Divider>
- <div className='desc'>
- {
- item.desc !== '' && item.desc !== null && item.desc.length > 40 ? item.desc.substring(0, 40) + '......' : item.desc
- }
- </div>
- <div style={{
- display: 'flex',
- justifyContent: 'space-between',
- alignItems: 'center'
- }}>
- <span style={{
- color: '#999',
- fontSize: 12,
- margin: 0
- }}>更新时间: {dayjs(item.updateTime).format("YYYY-MM-DD HH:mm:ss")}</span>
- </div>
- <div style={{
- display: 'flex',
- justifyContent: 'space-between',
- alignItems: 'flex-end',
- paddingTop: 3,
- // overflow: 'auto',
- // paddingTop: 16,
- // height: '100%'
- }}>
- <div style={{
- overflow: 'auto'
- }}>
- {
- (item.status === '5' || item.status === '4' || item.status === '3' || item.status === '' || item.status === null) &&
- <>
- {
- (updateFlag || userInfoAll.id === item.createBy) &&
- <a
- className="action-button"
- style={{ marginRight: 16 }}
- onClick={() => {
- router.navigate({ pathname: '/deepseek/questionAnswer/modify' }, { state: { id: item.appId } });
- }}>
- <EditOutlined /> 编辑
- </a>
- }
- {
- (deleteFlag || userInfoAll.id === item.createBy) &&
- <a className='delete-button' onClick={() => {
- Modal.confirm({
- title: '删除',
- content: `确定删除应用: ` + item.name + ` 吗?`,
- okType: 'danger',
- onOk: async () => {
- await delApplication(item.appId.toString());
- }
- });
- }}>
- <DeleteOutlined /> 删除
- </a>
- }
- </>
- }
- {
- createFlag && item.status === '5' &&
- <a className="action-button" style={{ marginLeft: 16 }} onClick={() => {
- Modal.confirm({
- title: '提交审核',
- content: `确认提交审核应用: ` + item.name + `吗?`,
- okType: 'danger',
- onOk: async () => {
- const userInfo = LocalStorage.getUserInfo();
- const userId = (userInfo?.id ?? '').toString();
- appApi.auditApplication(item.appId.toString(), userId);
- }
- });
- }}>
- <StepForwardOutlined /> 提交审核
- </a>
- }
- <Button size='small' style={{
- background: 'transparent',
- border: '1px solid #1677ff',
- color: '#1677ff',
- marginTop: '2px',
- marginLeft: createFlag && item.status === '5' || (item.status === '5' || item.status === '4' || item.status === '3' || item.status === '' || item.status === null) && updateFlag||userInfoAll.id === item.createBy ? '10px' : 0,
- fontSize: 12,
- }} type="primary" variant="outlined" onClick={() => { useNowAppLication(item.appId) }}>立即使用</Button>
- </div>
- <div>
- <Tag
- style={{
- // padding: '4px 8px',
- marginRight: 0,
- fontSize: 12,
- fontWeight: 600,
- background: '#f8f8f8',
- // border: '1px solid #d9d9d9'
- }}
- >
- {
- appTypeList
- .find(item1 => item1.value.toString() === item.typeId)?.label || levelTypeList.find(item2 => item2.value.toString() === item.typeId)?.label || '未分类'
- }
- </Tag>
- </div>
- </div>
- </div>
- </List.Item>
- )}
- pagination={paginationConfig} // 分页
- />
- </div>
- </div>
- :
- <div>
- {/* {
- createFlag &&
- <Button type='primary'
- icon={ <PlusOutlined /> }
- onClick={ () => {
- router.navigate( { pathname: '/deepseek/questionAnswer/create' } );
- } }>创建问答应用</Button>
- } */}
- <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
- </div>
- }
- </div>
- )
- };
- export default observer(QuestionAnswerList);
|