diff --git a/.env.template b/.env.template
index d353f535f40..00b5f16e438 100644
--- a/.env.template
+++ b/.env.template
@@ -77,8 +77,5 @@ HITOKOTO_URL=
###(optional) 侧边栏logo地址,默认是原图标
HEADER_LOGO_URL=
-###(optional) 公告,支持markdown语法
-ANNOUNCEMENT="## 新模型
-* grok-beta: 来源XAI,马斯克的大模型。
-* gemini-exp-1114: 来源Google,听说当今第一模型?
-"
+###(optional) 公告路径,支持markdown语法
+ANNOUNCEMENT_PATH=
diff --git a/README.md b/README.md
index 3b7b5bd34a2..c807bf7e9bb 100644
--- a/README.md
+++ b/README.md
@@ -27,5 +27,4 @@
- [one-api](https://github.com/songquanpeng/one-api): 一站式大模型额度管理平台,支持市面上所有主流大语言模型
- [new-api](https://github.com/Calcium-Ion/new-api):在One API的基础上进行二次开发.
## 开源协议
-
[MIT](https://opensource.org/license/mit/)
diff --git a/app/api/config/route.ts b/app/api/config/route.ts
index 1cf2f36b1ec..c7eb6114511 100644
--- a/app/api/config/route.ts
+++ b/app/api/config/route.ts
@@ -17,7 +17,6 @@ const DANGER_CONFIG = {
title: sidebarConfig.title,
hitokotoUrl: sidebarConfig.hitokotoUrl,
headerLogoUrl: sidebarConfig.headerLogoUrl,
- announcement: sidebarConfig.announcement,
};
declare global {
diff --git a/app/api/readFile/route.ts b/app/api/readFile/route.ts
index f17d115ce0e..0a2339e6328 100644
--- a/app/api/readFile/route.ts
+++ b/app/api/readFile/route.ts
@@ -1,13 +1,17 @@
import fs from "fs/promises";
+import crypto from "crypto";
import { NextResponse } from "next/server";
+function generateHash(input: string) {
+ return crypto.createHash("sha256").update(input).digest("hex");
+}
async function handler(req: any, res: any) {
// 定义文件路径
if (process.env.ANNOUNCEMENT_PATH) {
const filePath = process.env.ANNOUNCEMENT_PATH;
const data = await fs.readFile(filePath, "utf8");
- return NextResponse.json({ content: data });
+ return NextResponse.json({ content: data, hash: generateHash(data) });
}
- return NextResponse.json({ content: "" });
+ return NextResponse.json({ content: "", hash: "" });
}
export const GET = handler;
export const POST = handler;
diff --git a/app/components/chat.tsx b/app/components/chat.tsx
index e6f681a8b49..fb3b0e55702 100644
--- a/app/components/chat.tsx
+++ b/app/components/chat.tsx
@@ -939,22 +939,10 @@ export function ShortcutKeyModal(props: { onClose: () => void }) {
);
}
-export function AnnouncementModal(props: { onClose: () => void }) {
- const announcement = useRef("");
- const fetchData = async () => {
- const response = await fetch("/api/readFile", { method: "GET" });
- const data = await response.json();
- if (data.content) {
- console.log(data.content);
- announcement.current = data.content;
- } else {
- console.error("Failed to fetch file content");
- }
- };
- // const { announcement } = useAccessStore();
- useEffect(() => {
- fetchData();
- }, []);
+export function AnnouncementModal(props: {
+ announcement: string;
+ onClose: () => void;
+}) {
return (
@@ -1655,13 +1643,28 @@ function _Chat() {
const [showAnnouncementModal, setShowAnnouncementModal] = useState(false);
let hasNewAnnouncement = useRef(false);
+ const announcement = useRef("");
+ const announcementHash = useRef("");
+ const localAnnounceHash = useAppConfig().announcementHash;
+ const refreshAnnouncementHash = useAppConfig().refreshAnnouncementHash;
// 通过识别远程和本地公告来在按钮右上角加圆点
- let remoteAnnounce = useAccessStore().announcement;
- let localAnnounce = useAppConfig().announcement;
- const refreshAnnouncement = useAppConfig().refreshAnnouncement;
- if (remoteAnnounce !== localAnnounce) {
- hasNewAnnouncement.current = true;
- }
+ const fetchData = async () => {
+ const response = await fetch("/api/readFile", { method: "GET" });
+ const data = await response.json();
+ if (data.content) {
+ announcement.current = data.content;
+ announcementHash.current = data.hash;
+ if (data.hash !== localAnnounceHash) {
+ hasNewAnnouncement.current = true;
+ refreshAnnouncementHash(announcementHash.current);
+ }
+ } else {
+ console.error("Failed to fetch file content");
+ }
+ };
+ useEffect(() => {
+ fetchData();
+ });
return (
<>
@@ -1754,7 +1757,6 @@ function _Chat() {
onClick={() => {
setShowAnnouncementModal(true);
hasNewAnnouncement.current = false;
- refreshAnnouncement(remoteAnnounce);
}}
/>
@@ -2143,7 +2145,10 @@ function _Chat() {
/>
)}
{showAnnouncementModal && (
- setShowAnnouncementModal(false)} />
+ setShowAnnouncementModal(false)}
+ />
)}
{showShortcutKeyModal && (
setShowShortcutKeyModal(false)} />
diff --git a/app/config/server.ts b/app/config/server.ts
index c0b69917dc3..73e6cd6dd50 100644
--- a/app/config/server.ts
+++ b/app/config/server.ts
@@ -84,7 +84,6 @@ declare global {
HITOKOTO_URL?: string;
SIDEBAR_TITLE?: string;
HEADER_LOGO_URL?: string;
- ANNOUNCEMENT?: string;
ANNOUNCEMENT_PATH?: string;
}
}
@@ -123,7 +122,6 @@ export const getSidebarConfig = () => {
title: process.env.SIDEBAR_TITLE ?? "Next Web",
hitokotoUrl: process.env.HITOKOTO_URL ?? "https://v1.hitokoto.cn",
headerLogoUrl: process.env.HEADER_LOGO_URL ?? "",
- announcement: process.env.ANNOUNCEMENT ?? "",
};
};
export const getServerSideConfig = () => {
diff --git a/app/store/access.ts b/app/store/access.ts
index 575c2a2249b..b733ce097d2 100644
--- a/app/store/access.ts
+++ b/app/store/access.ts
@@ -127,7 +127,6 @@ const DEFAULT_ACCESS_STATE = {
title: "",
hitokotoUrl: "",
headerLogoUrl: "",
- announcement: "",
// tts config
edgeTTSVoiceName: "zh-CN-YunxiNeural",
};
diff --git a/app/store/config.ts b/app/store/config.ts
index e607fdf86cf..79ff9c21112 100644
--- a/app/store/config.ts
+++ b/app/store/config.ts
@@ -40,7 +40,7 @@ const config = getClientConfig();
export const DEFAULT_CONFIG = {
lastUpdate: Date.now(), // timestamp, to merge state
- announcement: "",
+ announcementHash: "",
submitKey: SubmitKey.Enter,
avatar: "1f603",
fontSize: 14,
@@ -62,7 +62,6 @@ export const DEFAULT_CONFIG = {
customModels: "",
models: DEFAULT_MODELS as any as LLMModel[],
-
modelConfig: {
model: "gpt-4o-mini" as ModelType,
providerName: "OpenAI" as ServiceProvider,
@@ -167,9 +166,9 @@ export const useAppConfig = createPersistStore(
reset() {
set(() => ({ ...DEFAULT_CONFIG }));
},
- refreshAnnouncement(ann: string) {
+ refreshAnnouncementHash(hash: string) {
set(() => ({
- announcement: ann,
+ announcementHash: hash,
}));
},
mergeModels(newModels: LLMModel[]) {