Browse Source

词云列表-部门-上传-图片-生成

master
談蓝色 10 months ago
parent
commit
81058b27ef
  1. 26
      frontend/src/App.jsx
  2. 3
      frontend/src/components/Modals/ManageWorkspace/Documents/Directory/index.jsx
  3. 63
      frontend/src/components/Modals/ManageWorkspace/Documents/UploadFile/index.jsx
  4. 3
      frontend/src/components/Modals/ManageWorkspace/Documents/WorkspaceDirectory/WorkspaceFileRow/index.jsx
  5. 5
      frontend/src/components/Modals/ManageWorkspace/Documents/WorkspaceDirectory/index.jsx
  6. 10
      frontend/src/components/Modals/ManageWorkspace/Documents/index.jsx
  7. 4
      frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/HistoricalMessage/index.jsx
  8. 3
      frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/PromptReply/index.jsx
  9. 2
      frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/index.jsx
  10. 29
      frontend/src/components/WorkspaceChat/ChatContainer/PromptInput/SlashCommands/SlashPresets/AddPresetModal.jsx
  11. 32
      frontend/src/components/WorkspaceChat/ChatContainer/PromptInput/SlashCommands/SlashPresets/EditPresetModal.jsx
  12. 45
      frontend/src/components/WorkspaceChat/ChatContainer/PromptInput/index.jsx
  13. 34
      frontend/src/pages/Admin/Users/NewUserModal/index.jsx
  14. 18
      frontend/src/pages/Admin/Users/UserRow/EditUserModal/index.jsx
  15. 9
      frontend/src/pages/Admin/Users/UserRow/index.jsx
  16. 8
      frontend/src/pages/Admin/Users/index.jsx
  17. 2
      frontend/src/pages/Admin/Workspaces/WorkspaceRow/index.jsx
  18. 5
      frontend/src/pages/DataAnalysis/DataAnalysis.css
  19. BIN
      frontend/src/pages/DataAnalysis/img/1.png
  20. BIN
      frontend/src/pages/DataAnalysis/img/10.png
  21. BIN
      frontend/src/pages/DataAnalysis/img/11.png
  22. BIN
      frontend/src/pages/DataAnalysis/img/12.png
  23. BIN
      frontend/src/pages/DataAnalysis/img/13.png
  24. BIN
      frontend/src/pages/DataAnalysis/img/14.png
  25. BIN
      frontend/src/pages/DataAnalysis/img/2.png
  26. BIN
      frontend/src/pages/DataAnalysis/img/3.png
  27. BIN
      frontend/src/pages/DataAnalysis/img/4.png
  28. BIN
      frontend/src/pages/DataAnalysis/img/5.png
  29. BIN
      frontend/src/pages/DataAnalysis/img/6.png
  30. BIN
      frontend/src/pages/DataAnalysis/img/7.png
  31. BIN
      frontend/src/pages/DataAnalysis/img/8.png
  32. BIN
      frontend/src/pages/DataAnalysis/img/9.png
  33. 45
      frontend/src/pages/DataAnalysis/index.jsx
  34. 18
      frontend/src/pages/Home/index.jsx
  35. 5
      frontend/src/pages/ReportGeneration/ReportGeneration.css
  36. 44
      frontend/src/pages/ReportGeneration/index.jsx
  37. 5
      frontend/src/pages/Tendency/Tendency.css
  38. 33
      frontend/src/pages/Tendency/index.jsx
  39. 4
      frontend/src/utils/constants.js
  40. 15
      frontend/src/utils/paths.js
  41. 5
      server/models/slashCommandsPresets.js
  42. 2
      server/utils/chats/commands/reset.js

26
frontend/src/App.jsx

@ -24,7 +24,12 @@ const PolicyLibrary = lazy(() => import("@/pages/PolicyLibrary")); // 政策库
const DataAnalysis = lazy(() => import("@/pages/DataAnalysis")); //
const Tendency = lazy(() => import("@/pages/Tendency")); //
const Yuqingfenxi = lazy(() => import("@/pages/Yuqingfenxi")); //
const Economics = lazy(() => import("@/pages/Economics")); //
const Talents = lazy(() => import("@/pages/Talents")); //
const Industry = lazy(() => import("@/pages/Industry")); //
const TrendPrediction = lazy(() => import("@/pages/TrendPrediction")); //
const ReportGeneration = lazy(() => import("@/pages/ReportGeneration")); //
const Report = lazy(() => import("@/pages/Report")); // 1
const InvitePage = lazy(() => import("@/pages/Invite"));
const WorkspaceChat = lazy(() => import("@/pages/WorkspaceChat"));
@ -110,6 +115,22 @@ export default function App() {
path="/home/Yuqingfenxi"
element={<ManagerRoute Component={Yuqingfenxi} />}
/>
<Route
path="/home/TrendPrediction"
element={<ManagerRoute Component={TrendPrediction} />}
/>
<Route
path="/home/Economics"
element={<ManagerRoute Component={Economics} />}
/>
<Route
path="/home/Talents"
element={<ManagerRoute Component={Talents} />}
/>
<Route
path="/home/Industry"
element={<ManagerRoute Component={Industry} />}
/>
<Route
path="/home/DataAnalysis"
element={<ManagerRoute Component={DataAnalysis} />}
@ -118,7 +139,10 @@ export default function App() {
path="/home/ReportGeneration"
element={<ManagerRoute Component={ReportGeneration} />}
/>
<Route
path="/home/Report"
element={<ManagerRoute Component={Report} />}
/>
<Route path="/login" element={<Login />} />
<Route
path="/sso/simple"

3
frontend/src/components/Modals/ManageWorkspace/Documents/Directory/index.jsx

@ -178,8 +178,7 @@ function Directory({
setSearchTerm(searchValue);
}, 500);
const filteredFiles = filterFileSearchResults(files, searchTerm);
console.log(333,filteredFiles);
const filteredFiles = filterFileSearchResults(files, searchTerm)
const handleContextMenu = (event) => {
event.preventDefault();

63
frontend/src/components/Modals/ManageWorkspace/Documents/UploadFile/index.jsx

@ -80,7 +80,7 @@ export default function UploadFile({
return (
<div>
<div
// 560px
// 560px
className={`w-[100%] border-dashed border-[1px] border-theme-modal-border light:border-[#686C6F] rounded-2xl bg-theme-bg-primary transition-colors duration-300 p-3 ${ready
? " light:bg-transparent cursor-pointer hover:bg-theme-bg-secondary light:hover:bg-[#E0F2FE]"
: "cursor-not-allowed"
@ -92,42 +92,43 @@ export default function UploadFile({
<div className="flex flex-col items-center justify-center h-full">
<CloudArrowUp className="w-8 h-8 text-white/80 light:invert" />
<div className="text-white text-opacity-80 text-sm font-semibold py-1">
Document Processor Unavailable
文档处理器不可用
</div>
<div className="text-white text-opacity-60 text-xs font-medium py-1 px-20 text-center">
We can't upload your files right now because the document
processor is offline. Please try again later.
我们现在不能上传你的文件因为文件
处理器脱机请稍后再试
</div>
</div>
) : files.length === 0 ? (
<div className="flex flex-col items-center justify-center">
<CloudArrowUp className="w-8 h-8 text-white/80 light:invert" />
<div className="text-white text-opacity-80 text-sm font-semibold py-1">
单击上传或拖放
)
: files.length === 0 ? (
<div className="flex flex-col items-center justify-center">
<CloudArrowUp className="w-8 h-8 text-white/80 light:invert" />
<div className="text-white text-opacity-80 text-sm font-semibold py-1">
单击上传或拖放
</div>
<div className="text-white text-opacity-60 text-xs font-medium py-1">
支持文本文件csv电子表格音频文件和更多
</div>
</div>
<div className="text-white text-opacity-60 text-xs font-medium py-1">
支持文本文件csv电子表格音频文件和更多
) : (
<div className="grid grid-cols-2 gap-2 overflow-auto max-h-[180px] p-1 overflow-y-scroll no-scroll">
{files.map((file) => (
<FileUploadProgress
key={file.uid}
file={file.file}
uuid={file.uid}
setFiles={setFiles}
slug={workspace.slug}
rejected={file?.rejected}
reason={file?.reason}
onUploadSuccess={handleUploadSuccess}
onUploadError={handleUploadError}
setLoading={setLoading}
setLoadingMessage={setLoadingMessage}
/>
))}
</div>
</div>
) : (
<div className="grid grid-cols-2 gap-2 overflow-auto max-h-[180px] p-1 overflow-y-scroll no-scroll">
{files.map((file) => (
<FileUploadProgress
key={file.uid}
file={file.file}
uuid={file.uid}
setFiles={setFiles}
slug={workspace.slug}
rejected={file?.rejected}
reason={file?.reason}
onUploadSuccess={handleUploadSuccess}
onUploadError={handleUploadError}
setLoading={setLoading}
setLoadingMessage={setLoadingMessage}
/>
))}
</div>
)}
)}
</div>
<div className="text-center text-white text-opacity-50 text-xs font-medium w-[560px] py-2">
或者提交一个链接

3
frontend/src/components/Modals/ManageWorkspace/Documents/WorkspaceDirectory/WorkspaceFileRow/index.jsx

@ -31,7 +31,8 @@ export default function WorkspaceFileRow({
setLoadingMessage(`从文件分析区中删除文件中`);
await Workspace.modifyEmbeddings(workspace.slug, {
adds: [],
deletes: [`${folderName}/${item.name}`],
// deletes: [`${folderName}/${item.name}`],
deletes: [`${item.relativePath}`],
});
await fetchKeys(true);
} catch (error) {

5
frontend/src/components/Modals/ManageWorkspace/Documents/WorkspaceDirectory/index.jsx

@ -26,7 +26,6 @@ function WorkspaceDirectory({
movedItems,
}) {
const [selectedItems, setSelectedItems] = useState({});
const toggleSelection = (item) => {
setSelectedItems((prevSelectedItems) => {
const newSelectedItems = { ...prevSelectedItems };
@ -41,6 +40,7 @@ function WorkspaceDirectory({
const toggleSelectAll = () => {
const allItems = files.items.flatMap((folder) => folder.items);
const allSelected = allItems.every((item) => selectedItems[item.id]);
if (allSelected) {
setSelectedItems({});
@ -53,6 +53,7 @@ function WorkspaceDirectory({
}
};
const removeSelectedItems = async () => {
setLoading(true);
setLoadingMessage("Removing selected files from workspace");
@ -60,7 +61,9 @@ function WorkspaceDirectory({
const itemsToRemove = Object.keys(selectedItems).map((itemId) => {
const folder = files.items.find((f) =>
f.items.some((i) => i.id === itemId)
);
const item = folder.items.find((i) => i.id === itemId);
return `${folder.name}/${item.name}`;
});

10
frontend/src/components/Modals/ManageWorkspace/Documents/index.jsx

@ -34,7 +34,7 @@ export default function DocumentSettings({ workspace, systemSettings }) {
: workspace;
const documentsInWorkspace =
currentWorkspace.documents.map((doc) => doc.docpath) || [];
currentWorkspace.documents.map((doc) => doc.filename) || [];
// Documents that are not in the workspace
const availableDocs = {
@ -46,7 +46,7 @@ export default function DocumentSettings({ workspace, systemSettings }) {
items: folder.items.filter(
(file) =>
file.type === "file" &&
!documentsInWorkspace.includes(`${folder.name}/${file.name}`)
!documentsInWorkspace.includes(`${file.name}`)
),
};
} else {
@ -65,7 +65,7 @@ export default function DocumentSettings({ workspace, systemSettings }) {
items: folder.items.filter(
(file) =>
file.type === "file" &&
documentsInWorkspace.includes(`${folder.name}/${file.name}`)
documentsInWorkspace.includes(`${file.name}`)
),
};
} else {
@ -90,9 +90,11 @@ export default function DocumentSettings({ workspace, systemSettings }) {
setLoadingMessage("对于大型文档,这可能需要一段时间");
const changesToSend = {
adds: movedItems.map((item) => `${item.folderName}/${item.name}`),
// adds: movedItems.map((item) => `${item.folderName}/${item.name}`),
adds: movedItems.map((item) => `${item.relativePath}`),
};
setSelectedItems({});
setHasChanges(false);
setHighlightWorkspace(false);

4
frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/HistoricalMessage/index.jsx

@ -53,7 +53,7 @@ const HistoricalMessage = ({
return (
<div
key={uuid}
className={`flex justify-center items-end w-full bg-theme-bg-chat`}
className={`flex justify-center items-end w-full`}
>
<div className="py-8 px-4 w-full flex gap-x-5 md:max-w-[80%] flex-col">
<div className="flex gap-x-5">
@ -81,7 +81,7 @@ const HistoricalMessage = ({
onAnimationEnd={onEndAnimation}
className={`${
isDeleted ? "animate-remove" : ""
} flex justify-center items-end w-full group `}
} flex justify-center items-end w-full group`}
>
<div className="py-8 px-4 w-full flex gap-x-5 md:max-w-[80%] flex-col">
<div className="flex gap-x-5">

3
frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/PromptReply/index.jsx

@ -19,7 +19,8 @@ const PromptReply = ({
sources = [],
closed = true,
}) => {
const assistantBackgroundColor = "bg-theme-bg-chat";
// const assistantBackgroundColor = bg-theme-bg-chat
const assistantBackgroundColor = "bg-[#F9FBFD]";
if (!reply && sources.length === 0 && !pending && !error) return null;

2
frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/index.jsx

@ -176,7 +176,7 @@ export default function ChatHistory({
if (history.length === 0 && !hasAttachments) {
return (
<div className="flex flex-col h-full md:mt-0 pb-44 md:pb-40 w-full justify-end items-center">
<div className="flex flex-col h-full md:mt-0 pb-44 md:pb-40 w-full justify-end items-center mb-[50px]">
<div className="flex flex-col items-center md:items-start md:max-w-[600px] w-full px-4">
<p className="text-white/60 text-lg font-base py-4">
欢迎来到你的新工作空间

29
frontend/src/components/WorkspaceChat/ChatContainer/PromptInput/SlashCommands/SlashPresets/AddPresetModal.jsx

@ -9,17 +9,22 @@ export default function AddPresetModal({ isOpen, onClose, onSave }) {
const handleSubmit = async (e) => {
e.preventDefault();
const form = new FormData(e.target);
const sanitizedCommand = command.replace(CMD_REGEX, "");
//
// const sanitizedCommand = command.replace(CMD_REGEX, "");
const sanitizedCommand = command
const saved = await onSave({
command: `/${sanitizedCommand}`,
// command: `/${sanitizedCommand}`,
command:sanitizedCommand,
prompt: form.get("prompt"),
description: form.get("description"),
});
if (saved) setCommand("");
window.location.reload()
};
const handleCommandChange = (e) => {
const value = e.target.value.replace(CMD_REGEX, "");
// const value = e.target.value.replace(CMD_REGEX, "");
const value = e.target.value
setCommand(value);
};
@ -29,7 +34,7 @@ export default function AddPresetModal({ isOpen, onClose, onSave }) {
<div className="relative p-6 border-b rounded-t border-theme-modal-border">
<div className="w-full flex gap-x-2 items-center">
<h3 className="text-xl font-semibold text-white overflow-hidden overflow-ellipsis whitespace-nowrap">
Add New Preset
添加新的提示词
</h3>
</div>
<button
@ -52,7 +57,7 @@ export default function AddPresetModal({ isOpen, onClose, onSave }) {
htmlFor="command"
className="block mb-2 text-sm font-medium text-white"
>
Command
命令
</label>
<div className="flex items-center">
<span className="text-white text-sm mr-2 font-bold">/</span>
@ -60,7 +65,7 @@ export default function AddPresetModal({ isOpen, onClose, onSave }) {
name="command"
type="text"
id="command"
placeholder="your-command"
placeholder="您的命令"
value={command}
onChange={handleCommandChange}
maxLength={25}
@ -75,13 +80,13 @@ export default function AddPresetModal({ isOpen, onClose, onSave }) {
htmlFor="prompt"
className="block mb-2 text-sm font-medium text-white"
>
Prompt
提示
</label>
<textarea
name="prompt"
id="prompt"
autoComplete="off"
placeholder="This is the content that will be injected in front of your prompt."
placeholder="这是将被注入到提示符前面的内容."
required={true}
className="border-none bg-theme-settings-input-bg w-full text-white placeholder:text-theme-settings-input-placeholder text-sm rounded-lg focus:outline-primary-button active:outline-primary-button outline-none block w-full p-2.5"
></textarea>
@ -91,13 +96,13 @@ export default function AddPresetModal({ isOpen, onClose, onSave }) {
htmlFor="description"
className="block mb-2 text-sm font-medium text-white"
>
Description
描述
</label>
<input
type="text"
name="description"
id="description"
placeholder="Responds with a poem about LLMs."
placeholder="描述提示次的内容."
maxLength={80}
autoComplete="off"
required={true}
@ -112,13 +117,13 @@ export default function AddPresetModal({ isOpen, onClose, onSave }) {
type="button"
className="transition-all duration-300 bg-transparent text-white hover:opacity-60 px-4 py-2 rounded-lg text-sm"
>
Cancel
取消
</button>
<button
type="submit"
className="transition-all duration-300 bg-white text-black hover:opacity-60 px-4 py-2 rounded-lg text-sm"
>
Save
保存
</button>
</div>
</form>

32
frontend/src/components/WorkspaceChat/ChatContainer/PromptInput/SlashCommands/SlashPresets/EditPresetModal.jsx

@ -22,27 +22,33 @@ export default function EditPresetModal({
const handleSubmit = (e) => {
e.preventDefault();
const form = new FormData(e.target);
const sanitizedCommand = command.replace(CMD_REGEX, "");
//
// const sanitizedCommand = command.replace(CMD_REGEX, "");
const sanitizedCommand = command
onSave({
id: preset.id,
command: `/${sanitizedCommand}`,
// command: `/${sanitizedCommand}`,
command: sanitizedCommand,
prompt: form.get("prompt"),
description: form.get("description"),
});
window.location.reload()
};
const handleCommandChange = (e) => {
const value = e.target.value.replace(CMD_REGEX, "");
// const value = e.target.value.replace(CMD_REGEX, "");
const value = e.target.value
setCommand(value);
};
const handleDelete = async () => {
if (!window.confirm("Are you sure you want to delete this preset?")) return;
if (!window.confirm("您确定要删除此预设吗?")) return;
setDeleting(true);
await onDelete(preset.id);
setDeleting(false);
onClose();
window.location.reload()
};
return (
@ -51,7 +57,7 @@ export default function EditPresetModal({
<div className="relative p-6 border-b rounded-t border-theme-modal-border">
<div className="w-full flex gap-x-2 items-center">
<h3 className="text-xl font-semibold text-white overflow-hidden overflow-ellipsis whitespace-nowrap">
Edit Preset
编辑预设
</h3>
</div>
<button
@ -74,14 +80,14 @@ export default function EditPresetModal({
htmlFor="command"
className="block mb-2 text-sm font-medium text-white"
>
Command
命令
</label>
<div className="flex items-center">
<span className="text-white text-sm mr-2 font-bold">/</span>
<input
type="text"
name="command"
placeholder="your-command"
placeholder="您的命令"
value={command}
onChange={handleCommandChange}
required={true}
@ -94,11 +100,11 @@ export default function EditPresetModal({
htmlFor="prompt"
className="block mb-2 text-sm font-medium text-white"
>
Prompt
提示
</label>
<textarea
name="prompt"
placeholder="This is a test prompt. Please respond with a poem about LLMs."
placeholder="请输入提示内容."
defaultValue={preset.prompt}
required={true}
className="border-none bg-theme-settings-input-bg w-full text-white placeholder:text-theme-settings-input-placeholder text-sm rounded-lg focus:outline-primary-button active:outline-primary-button outline-none block w-full p-2.5"
@ -109,7 +115,7 @@ export default function EditPresetModal({
htmlFor="description"
className="block mb-2 text-sm font-medium text-white"
>
Description
描述
</label>
<input
type="text"
@ -129,7 +135,7 @@ export default function EditPresetModal({
type="button"
className="transition-all duration-300 bg-transparent text-red-500 hover:bg-red-500/25 px-4 py-2 rounded-lg text-sm disabled:opacity-50"
>
{deleting ? "Deleting..." : "Delete Preset"}
{deleting ? "Deleting..." : "删除"}
</button>
<div className="flex space-x-2">
<button
@ -137,13 +143,13 @@ export default function EditPresetModal({
type="button"
className="transition-all duration-300 bg-transparent text-white hover:opacity-60 px-4 py-2 rounded-lg text-sm"
>
Cancel
取消
</button>
<button
type="submit"
className="transition-all duration-300 bg-white text-black hover:opacity-60 px-4 py-2 rounded-lg text-sm"
>
Save
保存
</button>
</div>
</div>

45
frontend/src/components/WorkspaceChat/ChatContainer/PromptInput/index.jsx

@ -18,6 +18,7 @@ import AttachItem from "./AttachItem";
import { PASTE_ATTACHMENT_EVENT } from "../DnDWrapper";
import useTextSize from "@/hooks/useTextSize";
import "../../srk.css"
import System from "@/models/system";
export const PROMPT_INPUT_EVENT = "set_prompt_input";
const MAX_EDIT_STACK_SIZE = 100;
@ -39,7 +40,7 @@ export default function PromptInput({
const undoStack = useRef([]);
const redoStack = useRef([]);
const { textSizeClass } = useTextSize();
const [presets, setPresets] = useState([]);
/**
* To prevent too many re-renders we remotely listen for updates from the parent
* via an event cycle. Otherwise, using message as a prop leads to a re-render every
@ -235,6 +236,16 @@ export default function PromptInput({
setPromptInput(e.target.value);
}
useEffect(() => {
fetchPresets();
}, []);
//
const fetchPresets = async () => {
const presets = await System.getSlashCommandPresets();
setPresets(presets);
};
return (
<div className="w-full fixed md:absolute bottom-0 left-0 z-10 md:z-0 flex justify-center items-center">
<SlashCommands
@ -250,10 +261,34 @@ export default function PromptInput({
/>
<form
onSubmit={handleSubmit}
className="flex flex-col gap-y-1 rounded-t-lg md:w-3/4 w-full mx-auto max-w-xl items-center"
// className="flex flex-col gap-y-1 rounded-t-lg md:w-3/4 w-full mx-auto max-w-xl items-center"
>
<div className="flex items-center rounded-lg md:mb-4 input_border">
<div className="w-[95vw] md:w-[800px] shadow-[0_0_11px_0px_#EBEDF6] bg-theme-bg-chat-input light:bg-white light:border-theme-chat-input-border rounded-2xl flex flex-col px-4 overflow-hidden">
<div style={{ display: 'flex', flexWrap:'wrap'}} className='w-[95vw] md:w-[800px]'>
<button
onClick={() => {
sendCommand("/reset", true);
}}
className="bg-[#F9FBFD] hover:bg-[#cacad1] border border-solid border-[#E5E7EB]"
style={{ textAlign: 'left', padding: '3px 15px', margin: '5px 0 5px 10px', display: 'flex', alignItems: 'center', borderRadius: '5px' }}
>
<div className="text-[14px]" >重置</div>
</button>
{presets.map((preset) => (
<button
key={preset.id}
onClick={() => {
sendCommand(`${preset.command}`, true);
}}
className="bg-[#F9FBFD] hover:bg-[#cacad1] border border-solid border-[#E5E7EB]"
style={{ textAlign: 'left', padding: '3px 15px', margin: '5px 0 5px 10px', display: 'flex', alignItems: 'center', borderRadius: '5px' }}
>
<div className="text-[14px]" >{preset.command}</div>
</button>
))}
</div>
<div className="flex items-center rounded-lg md:mb-4 input_border">
<div className="w-[95vw] md:w-[800px] shadow-[0_0_11px_0px_#EBEDF6] bg-theme-bg-chat-input light:bg-white light:border-theme-chat-input-border rounded-2xl flex flex-col px-4 overflow-hidden">
<AttachmentManager attachments={attachments} />
<div className="flex items-center w-full border-b border-gray-200">
<textarea
@ -272,7 +307,7 @@ export default function PromptInput({
adjustTextArea(e);
}}
value={promptInput}
className={`border-none cursor-text max-h-[50vh] md:max-h-[350px] md:min-h-[40px] mx-2 md:mx-0 pt-[12px] pb-[5px] w-full leading-5 md:text-md text-white bg-transparent resize-none active:outline-none focus:outline-none flex-grow ${textSizeClass}`}
className={`border-none cursor-text max-h-[50vh] md:max-h-[350px] md:min-h-[40px] mx-2 md:mx-0 pt-[10px] w-full leading-5 md:text-md text-white bg-transparent resize-none active:outline-none focus:outline-none flex-grow ${textSizeClass}`}
placeholder={"和deepSeek说几句话"}
/>
{buttonDisabled ? (

34
frontend/src/pages/Admin/Users/NewUserModal/index.jsx

@ -3,7 +3,7 @@ import { X } from "@phosphor-icons/react";
import Admin from "@/models/admin";
import { userFromStorage } from "@/utils/request";
import { MessageLimitInput, RoleHintDisplay } from "..";
import { Select } from "antd";
import { Select,message } from "antd";
export default function NewUserModal({ closeModal }) {
const [error, setError] = useState(null);
@ -13,26 +13,30 @@ export default function NewUserModal({ closeModal }) {
limit: 10,
});
const [depId, setDepId] = useState([]);
const [flag, setFlag] = useState(null);
const handleCreate = async (e) => {
setError(null);
e.preventDefault();
const data = {};
const form = new FormData(e.target);
for (var [key, value] of form.entries()) data[key] = value;
data.dailyMessageLimit = messageLimit.enabled ? messageLimit.limit : null;
console.log('用户', data);
const { user, error } = await Admin.newUserTo(data,depId);
// console.log('',user);
console.log('获取',depId);
// if (!!user) window.location.reload();
setError(error);
if(depId.length==0){
message.info(`部门不能为空`)
e.preventDefault();
setFlag('error')
}else{
setError(null);
e.preventDefault();
const data = {};
const form = new FormData(e.target);
for (var [key, value] of form.entries()) data[key] = value;
data.dailyMessageLimit = messageLimit.enabled ? messageLimit.limit : null;
const { user, error } = await Admin.newUserTo(data,depId);
if (!!user) window.location.reload();
setError(error);
}
};
const user = userFromStorage();
const [departments, setDepartments] = useState([]);
const [treeData, setTreeData] = useState([]);
useEffect(() => {
async function fetchDepartments() {
@ -41,7 +45,6 @@ export default function NewUserModal({ closeModal }) {
value:item.deptId,
label:item.deptName
}))
console.log(222222, list);
setDepartments(list);
}
fetchDepartments();
@ -129,6 +132,7 @@ export default function NewUserModal({ closeModal }) {
部门
</label>
<Select
status={flag}
className="w-[100%] h-[42px]"
showSearch
placeholder="请选择部门"

18
frontend/src/pages/Admin/Users/UserRow/EditUserModal/index.jsx

@ -37,7 +37,7 @@ export default function EditUserModal({ currentUser, user, closeModal }) {
<div className="relative p-6 border-b rounded-t border-theme-modal-border">
<div className="w-full flex gap-x-2 items-center">
<h3 className="text-xl font-semibold text-white overflow-hidden overflow-ellipsis whitespace-nowrap">
Edit {user.username}
编辑 {user.username}
</h3>
</div>
<button
@ -56,7 +56,7 @@ export default function EditUserModal({ currentUser, user, closeModal }) {
htmlFor="username"
className="block mb-2 text-sm font-medium text-white"
>
Username
用户名
</label>
<input
name="username"
@ -69,8 +69,8 @@ export default function EditUserModal({ currentUser, user, closeModal }) {
autoComplete="off"
/>
<p className="mt-2 text-xs text-white/60">
Username must only contain lowercase letters, numbers,
underscores, and hyphens with no spaces
用户名只能包含小写字母数字
下划线和连字符不带空格
</p>
</div>
<div>
@ -78,7 +78,7 @@ export default function EditUserModal({ currentUser, user, closeModal }) {
htmlFor="password"
className="block mb-2 text-sm font-medium text-white"
>
New Password
新密码
</label>
<input
name="password"
@ -89,7 +89,7 @@ export default function EditUserModal({ currentUser, user, closeModal }) {
minLength={8}
/>
<p className="mt-2 text-xs text-white/60">
Password must be at least 8 characters long
密码长度至少为8个字符
</p>
</div>
<div>
@ -97,7 +97,7 @@ export default function EditUserModal({ currentUser, user, closeModal }) {
htmlFor="role"
className="block mb-2 text-sm font-medium text-white"
>
Role
角色
</label>
<select
name="role"
@ -128,13 +128,13 @@ export default function EditUserModal({ currentUser, user, closeModal }) {
type="button"
className="transition-all duration-300 text-white hover:bg-zinc-700 px-4 py-2 rounded-lg text-sm"
>
Cancel
取消
</button>
<button
type="submit"
className="transition-all duration-300 bg-white text-black hover:opacity-60 px-4 py-2 rounded-lg text-sm"
>
Update user
更新用户
</button>
</div>
</form>

9
frontend/src/pages/Admin/Users/UserRow/index.jsx

@ -5,6 +5,7 @@ import EditUserModal from "./EditUserModal";
import showToast from "@/utils/toast";
import { useModal } from "@/hooks/useModal";
import ModalWrapper from "@/components/ModalWrapper";
import moment from 'moment';
const ModMap = {
admin: ["admin", "manager", "default"],
@ -20,7 +21,7 @@ export default function UserRow({ currUser, user }) {
const handleSuspend = async () => {
if (
!window.confirm(
`Are you sure you want to suspend ${user.username}?\nAfter you do this they will be logged out and unable to log back into this instance of AnythingLLM until unsuspended by an admin.`
`您确定要删除吗 ${user.username}?\n在您这样做之后,它们将被注销,并且无法重新登录`
)
)
return false;
@ -41,7 +42,7 @@ export default function UserRow({ currUser, user }) {
const handleDelete = async () => {
if (
!window.confirm(
`Are you sure you want to delete ${user.username}?\nAfter you do this they will be logged out and unable to use this instance of AnythingLLM.\n\nThis action is irreversible.`
`您确定要删除吗 ${user.username}?\n在您这样做之后,它们将被注销,并且无法重新登录`
)
)
return false;
@ -70,7 +71,7 @@ export default function UserRow({ currUser, user }) {
onClick={openModal}
className="text-sm font-medium text-white/80 light:text-black/80 rounded-lg hover:text-white hover:light:text-gray-500 px-2 py-1 hover:bg-white hover:bg-opacity-10"
>
Edit
编辑
</button>
)}
{currUser?.id !== user.id && canModify && (
@ -85,7 +86,7 @@ export default function UserRow({ currUser, user }) {
onClick={handleDelete}
className="text-sm font-medium text-white/80 light:text-black/80 hover:light:text-red-500 hover:text-red-300 rounded-lg px-2 py-1 hover:bg-white hover:light:bg-red-50 hover:bg-opacity-10"
>
Delete
删除
</button>
</>
)}

8
frontend/src/pages/Admin/Users/index.jsx

@ -62,7 +62,6 @@ function UsersContainer() {
useEffect(() => {
async function fetchUsers() {
const _users = await Admin.users();
console.log(1111, _users);
setUsers(_users);
setLoading(false);
}
@ -96,6 +95,9 @@ function UsersContainer() {
<th scope="col" className="px-6 py-3">
添加日期
</th>
<th scope="col" className="px-6 py-3">
操作
</th>
<th scope="col" className="px-6 py-3 rounded-tr-lg">
{" "}
</th>
@ -121,8 +123,8 @@ const ROLE_HINT = {
"Cannot modify LLM, vectorDB, embedding, or other connections.",
],
admin: [
"Highest user level privilege.",
"Can see and do everything across the system.",
"最高用户权限",
"可以看到并执行整个系统的所有操作。",
],
};

2
frontend/src/pages/Admin/Workspaces/WorkspaceRow/index.jsx

@ -8,7 +8,7 @@ export default function WorkspaceRow({ workspace, users }) {
const handleDelete = async () => {
if (
!window.confirm(
`Are you sure you want to delete ${workspace.name}?\nAfter you do this it will be unavailable in this instance of AnythingLLM.\n\nThis action is irreversible.`
`您确定要删除吗 ${workspace.name}?\nAfter you do this it will be unavailable in this instance of AnythingLLM.\n\nThis action is irreversible.`
)
)
return false;

5
frontend/src/pages/DataAnalysis/DataAnalysis.css

@ -97,7 +97,8 @@
}
.nr1 img {
width: 100%;
/* width: 100%; */
width: 70px;
}
.nr2 {
@ -136,4 +137,4 @@
margin-right: 20px;
border-radius: 5px;
font-size: 14px;
}
}

BIN
frontend/src/pages/DataAnalysis/img/1.png

Before

Width: 61  |  Height: 62  |  Size: 4.5 KiB

After

Width: 1667  |  Height: 1667  |  Size: 24 KiB

BIN
frontend/src/pages/DataAnalysis/img/10.png

Before

Width: 61  |  Height: 62  |  Size: 3.2 KiB

After

Width: 1668  |  Height: 1667  |  Size: 33 KiB

BIN
frontend/src/pages/DataAnalysis/img/11.png

Before

Width: 62  |  Height: 60  |  Size: 4.2 KiB

After

Width: 1668  |  Height: 1667  |  Size: 15 KiB

BIN
frontend/src/pages/DataAnalysis/img/12.png

Before

Width: 64  |  Height: 62  |  Size: 5.1 KiB

After

Width: 1667  |  Height: 1667  |  Size: 35 KiB

BIN
frontend/src/pages/DataAnalysis/img/13.png

Before

Width: 64  |  Height: 64  |  Size: 4.9 KiB

After

Width: 1668  |  Height: 1667  |  Size: 26 KiB

BIN
frontend/src/pages/DataAnalysis/img/14.png

Before

Width: 62  |  Height: 62  |  Size: 3.9 KiB

After

Width: 1668  |  Height: 1667  |  Size: 39 KiB

BIN
frontend/src/pages/DataAnalysis/img/2.png

Before

Width: 62  |  Height: 64  |  Size: 3.6 KiB

After

Width: 1668  |  Height: 1667  |  Size: 28 KiB

BIN
frontend/src/pages/DataAnalysis/img/3.png

Before

Width: 62  |  Height: 61  |  Size: 4.5 KiB

After

Width: 1668  |  Height: 1667  |  Size: 27 KiB

BIN
frontend/src/pages/DataAnalysis/img/4.png

Before

Width: 63  |  Height: 64  |  Size: 4.4 KiB

After

Width: 1667  |  Height: 1667  |  Size: 30 KiB

BIN
frontend/src/pages/DataAnalysis/img/5.png

Before

Width: 64  |  Height: 63  |  Size: 5.0 KiB

After

Width: 1667  |  Height: 1667  |  Size: 39 KiB

BIN
frontend/src/pages/DataAnalysis/img/6.png

Before

Width: 62  |  Height: 63  |  Size: 4.1 KiB

After

Width: 1668  |  Height: 1667  |  Size: 28 KiB

BIN
frontend/src/pages/DataAnalysis/img/7.png

Before

Width: 63  |  Height: 62  |  Size: 3.9 KiB

After

Width: 1668  |  Height: 1667  |  Size: 39 KiB

BIN
frontend/src/pages/DataAnalysis/img/8.png

Before

Width: 64  |  Height: 62  |  Size: 2.9 KiB

After

Width: 1667  |  Height: 1667  |  Size: 37 KiB

BIN
frontend/src/pages/DataAnalysis/img/9.png

Before

Width: 63  |  Height: 61  |  Size: 3.5 KiB

After

Width: 1667  |  Height: 1667  |  Size: 30 KiB

45
frontend/src/pages/DataAnalysis/index.jsx

@ -3,16 +3,16 @@ import { useNavigate } from 'react-router-dom';
import './DataAnalysis.css'
import sou from './img/sou.png'
import home from './img/home.png'
import tu1 from './img/1.png'
import tu2 from './img/2.png'
import tu12 from './img/12.png'
import tu3 from './img/3.png'
import tu4 from './img/4.png'
import tu5 from './img/5.png'
import tu6 from './img/6.png'
import tu7 from './img/7.png'
import tu8 from './img/8.png'
import tu9 from './img/9.png'
import tu10 from './img/10.png'
import tu11 from './img/11.png'
import tu14 from './img/14.png'
import { message } from "antd";
function DataAnalysis() {
@ -22,54 +22,58 @@ function DataAnalysis() {
{
name: '舆情分析',
text: '收集群众反馈意见,对意见进行分类,并分析对应舆情状态',
img: tu1,
img: tu3,
url: '/home/Yuqingfenxi'
},
{
name: '经济发展分析',
text: '整合并分析经济数据,输出经济趋势分析报告,自动生成包含图表和文字解读的分析报告',
img: tu2
img: tu4,
url: '/home/Economics'
},
{
name: '人才分析',
text: '分析人才流动情况、就业情况、人才数量、性别占比、岗位数量、录用率等',
img: tu8,
url: '/home/Talents'
},
{
name: '产业分析',
text: '对新能源、盐碱化工等产业进行资源、市场、技术分析用户输入产业信息,系统自动进行分析并输出报告资源分析:评估产业所需的自然、人力资源市场分析:分析当前市场需求、竞争态势',
img: tu12,
url: '/home/Industry'
},
{
name: '沙漠化分析',
text: '分析植被覆盖率和沙化面积',
img: tu3
img: tu5
},
{
name: '工业污染分析',
text: '分析工业区域污染物排放情况',
img: tu4
img: tu6
},
{
name: '生态修复分析',
text: '分析不同区域内环境治理前后生态指标',
img: tu5
},
{
name: '人才分析',
text: '分析人才流动情况、就业情况、人才数量、性别占比、岗位数量、录用率等',
img: tu6
img: tu7
},
{
name: '教育资源分析',
text: '分析教育资源的分布情况,评估教育公平性',
img: tu7
img: tu9
},
{
name: '医疗服务分析',
text: '监测医疗服务数据,分析就诊率和疾病谱变化',
img: tu8
img: tu10
},
{
name: '项目进度跟踪',
text: '实时显示项目的进度状态,对比计划与实际进度',
img: tu11
},
{
name: '产业分析',
text: '对新能源、盐碱化工等产业进行资源、市场、技术分析用户输入产业信息,系统自动进行分析并输出报告资源分析:评估产业所需的自然、人力资源市场分析:分析当前市场需求、竞争态势',
img: tu14
},
]
useEffect(() => {
@ -77,7 +81,6 @@ function DataAnalysis() {
}, []);
const bindUrl = (e) => {
console.log(1234, e);
if (e.url) {
navigate(e.url)
} else {

18
frontend/src/pages/Home/index.jsx

@ -13,20 +13,33 @@ import icon5 from "./img/5.png"
import icon6 from "./img/6.png"
import icon7 from "./img/7.png"
import icon8 from "./img/8.png"
import paths from "@/utils/paths";
import Workspace from "@/models/workspace";
export default function Home() {
const [workspaces, setWorkspaces] = useState([]);
const WeekDays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
const [currentTime, setCurrentTime] = useState(moment());
const navigate = useNavigate();
useEffect(() => {
async function getWorkspaces() {
const workspaces = await Workspace.all();
const workSlug = workspaces[0].slug
setWorkspaces(workSlug);
}
getWorkspaces();
}, []);
// 1- 2- 3- 4-
const list = [
{
type: 1,
url: '/Main',
url: paths.workspace.chat(workspaces),
name: 'AI问政',
icon: icon3,
// paths.workspace.chat(workspaces)
},
{
type: 1,
@ -75,7 +88,6 @@ export default function Home() {
//
const bindUrl = (e) => {
console.log(1234, e);
if (e.type == 1) {
// window.location = e.url
navigate(e.url)

5
frontend/src/pages/ReportGeneration/ReportGeneration.css

@ -97,7 +97,8 @@
}
.nr1 img {
width: 100%;
/* width: 100%; */
width: 70px;
}
.nr2 {
@ -136,4 +137,4 @@
margin-right: 20px;
border-radius: 5px;
font-size: 14px;
}
}

44
frontend/src/pages/ReportGeneration/index.jsx

@ -1,37 +1,41 @@
// import React, { useEffect, useRef } from 'react';
import React, { useEffect, useState, useRef } from 'react';
import { useNavigate } from 'react-router-dom';
import { message } from "antd";
import './ReportGeneration.css'
import sou from '../DataAnalysis/img/sou.png'
import home from '../DataAnalysis/img/home.png'
import tu1 from '../DataAnalysis/img/8.png'
import tu17 from '../DataAnalysis/img/17.png'
import tu2 from '../DataAnalysis/img/2.png'
import tu3 from '../DataAnalysis/img/3.png'
import tu4 from '../DataAnalysis/img/14.png'
import tu4 from '../DataAnalysis/img/4.png'
import tu1 from '../DataAnalysis/img/1.png'
function IframeComponent() {
const [renderKey, setRenderKey] = useState();
const navigate = useNavigate();
const list = [
{
name: '报告生成',
text: '根据分析结果和用户需求,自动生成各类报告,并支持多种输出格式。',
img: tu17,
url: '/home/Report'
},
{
name: '报告模板',
text: '根据需要选择合适的模板进行编辑和生成报告。',
img: tu1
img: tu2
},
{
name: '数据支撑',
text: '可从文件库内选取指定参考文件',
img: tu2
},
{
name: '报告生成',
text: '根据分析结果和用户需求,自动生成各类报告,并支持多种输出格式。',
img: tu3
img: tu4
},
{
name: '智能推送',
text: '支持根据预设条件自动推送报告,确保相关人员及时获取报告信息',
img: tu4
img: tu1
},
]
@ -39,7 +43,17 @@ function IframeComponent() {
}, []);
const bindUrl = () =>{
const bindUrl = (e) => {
if (e.url) {
navigate(e.url)
} else {
message.info({
content: e.name + '开发中...'
})
}
}
const bindUrl1 = () =>{
window.location = '/'
}
@ -47,7 +61,7 @@ function IframeComponent() {
<div className='box'>
<div className='box1'>
<div className='head'>
<div><img src={home} onClick={bindUrl} alt="" /></div>
<div><img src={home} onClick={bindUrl1} alt="" /></div>
<div className='search'>
<div className='search1'>
<img src={sou} alt="" />
@ -68,7 +82,7 @@ function IframeComponent() {
<div>{item.text}</div>
</div>
</div>
<div className='content2_2'>
<div className='content2_2' onClick={() => bindUrl(item)}>
<button>立即使用</button>
</div>
</div>

5
frontend/src/pages/Tendency/Tendency.css

@ -96,7 +96,8 @@
}
.nr1 img {
width: 100%;
/* width: 100%; */
width: 70px;
}
.nr2 {
@ -135,4 +136,4 @@
margin-right: 20px;
border-radius: 5px;
font-size: 14px;
}
}

33
frontend/src/pages/Tendency/index.jsx

@ -1,29 +1,32 @@
import React, { useEffect, useState, useRef } from 'react';
import { useNavigate } from 'react-router-dom';
import { message } from "antd";
import './Tendency.css'
import sou from '../DataAnalysis/img/sou.png'
import home from '../DataAnalysis/img/home.png'
import tu1 from '../DataAnalysis/img/5.png'
import tu2 from '../DataAnalysis/img/8.png'
import tu3 from '../DataAnalysis/img/11.png'
import tu13 from '../DataAnalysis/img/13.png'
import tu14 from '../DataAnalysis/img/14.png'
import tu15 from '../DataAnalysis/img/15.png'
function Tendency() {
const [renderKey, setRenderKey] = useState();
const navigate = useNavigate();
const list = [
{
name: '趋势预测',
text: '利用机器学习算法对历史数据进行分析,预测未来一段时间内的数据变化趋势,如经济发展、人口流动、环境状况等。',
img: tu1
img: tu13,
url: '/home/TrendPrediction'
},
{
name: '异常监测',
text: '自动检测数据中的异常值或突变点,提醒用户注意可能存在的问题或风险。',
img: tu2
img: tu14
},
{
name: '指标监测',
text: '对关键指标进行实时监控,当指标达到预设阈值时,自动触发警报,确保管理层能迅速响应。',
img: tu3
img: tu15
},
]
@ -31,7 +34,17 @@ function Tendency() {
}, []);
const bindUrl = () => {
const bindUrl = (e) => {
if (e.url) {
navigate(e.url)
} else {
message.info({
content: e.name + '开发中...'
})
}
}
const bindUrl1 = () => {
window.location = '/'
}
@ -39,7 +52,7 @@ function Tendency() {
<div className='box'>
<div className='box1'>
<div className='head'>
<div><img src={home} onClick={bindUrl} alt="" /></div>
<div><img src={home} onClick={bindUrl1} alt="" /></div>
<div className='search'>
<div className='search1'>
<img src={sou} alt="" />
@ -60,7 +73,7 @@ function Tendency() {
<div>{item.text}</div>
</div>
</div>
<div className='content2_2'>
<div className='content2_2' onClick={() => bindUrl(item)}>
<button>立即使用</button>
</div>
</div>

4
frontend/src/utils/constants.js

@ -1,5 +1,5 @@
export const API_BASE = import.meta.env.VITE_API_BASE || "/api";
// export const API_BASE = 'http://172.16.2.31:3001/api'
// export const API_BASE = import.meta.env.VITE_API_BASE || "/api";
export const API_BASE = 'http://172.16.2.9:3001/api'
export const ONBOARDING_SURVEY_URL = "https://onboarding.anythingllm.com";
export const AUTH_USER = "anythingllm_user";

15
frontend/src/utils/paths.js

@ -20,11 +20,26 @@ export default {
Yuqingfenxi: () => {
return "/home/Yuqingfenxi";
},
Economics: () => {
return "/home/Economics";
},
TrendPrediction: () => {
return "/home/TrendPrediction";
},
Industry: () => {
return "/home/Industry";
},
Talents: () => {
return "/home/Talents";
},
DataAnalysis: () => {
return "/home/DataAnalysis";
},
ReportGeneration:() =>{
return "/home/ReportGeneration";
},
Report:() =>{
return "/home/Report";
}
},
onboarding: {

5
server/models/slashCommandsPresets.js

@ -6,9 +6,10 @@ const SlashCommandPresets = {
formatCommand: function (command = "") {
if (!command || command.length < 2) return `/${v4().split("-")[0]}`;
let adjustedCmd = command.toLowerCase(); // force lowercase
let adjustedCmd = command.toLowerCase(); // force lowercase
if (!adjustedCmd.startsWith("/")) adjustedCmd = `/${adjustedCmd}`; // Fix if no preceding / is found.
return `/${adjustedCmd.slice(1).toLowerCase().replace(CMD_REGEX, "-")}`; // replace any invalid chars with '-'
return `${adjustedCmd.slice(1).toLowerCase()}`; // replace any invalid chars with '-'
// return `/${adjustedCmd.slice(1).toLowerCase().replace(CMD_REGEX, "-")}`
},
get: async function (clause = {}) {

2
server/utils/chats/commands/reset.js

@ -19,7 +19,7 @@ async function resetMemory(
return {
uuid: msgUUID,
type: "textResponse",
textResponse: "Workspace chat memory was reset!",
textResponse: "清空聊天记录!",
sources: [],
close: true,
error: false,

Loading…
Cancel
Save