diff --git a/README.md b/README.md
index be5e91d65..bf7c30594 100644
--- a/README.md
+++ b/README.md
@@ -18,11 +18,11 @@ One-Click to get a well-designed cross-platform ChatGPT web UI, with GPT3, GPT4
[![MacOS][MacOS-image]][download-url]
[![Linux][Linux-image]][download-url]
-[NextChatAI](https://nextchat.dev/chat) / [Web App](https://app.nextchat.dev) / [Desktop App](https://github.com/Yidadaa/ChatGPT-Next-Web/releases) / [Discord](https://discord.gg/YCkeafCafC) / [Enterprise Edition](#enterprise-edition) / [Twitter](https://twitter.com/NextChatDev)
+[NextChatAI](https://nextchat.dev/chat?utm_source=readme) / [Web App](https://app.nextchat.dev) / [Desktop App](https://github.com/Yidadaa/ChatGPT-Next-Web/releases) / [Discord](https://discord.gg/YCkeafCafC) / [Enterprise Edition](#enterprise-edition) / [Twitter](https://twitter.com/NextChatDev)
[NextChatAI](https://nextchat.dev/chat) / [网页版](https://app.nextchat.dev) / [客户端](https://github.com/Yidadaa/ChatGPT-Next-Web/releases) / [企业版](#%E4%BC%81%E4%B8%9A%E7%89%88) / [反馈](https://github.com/Yidadaa/ChatGPT-Next-Web/issues)
-[saas-url]: https://nextchat.dev/chat
+[saas-url]: https://nextchat.dev/chat?utm_source=readme
[saas-image]: https://img.shields.io/badge/NextChat-Saas-green?logo=microsoftedge
[web-url]: https://app.nextchat.dev/
[download-url]: https://github.com/Yidadaa/ChatGPT-Next-Web/releases
diff --git a/README_CN.md b/README_CN.md
index 640fe3933..73fbc3f51 100644
--- a/README_CN.md
+++ b/README_CN.md
@@ -8,7 +8,7 @@
一键免费部署你的私人 ChatGPT 网页应用,支持 GPT3, GPT4 & Gemini Pro 模型。
-[NextChatAI](https://nextchat.dev/chat) / [企业版](#%E4%BC%81%E4%B8%9A%E7%89%88) / [演示 Demo](https://chat-gpt-next-web.vercel.app/) / [反馈 Issues](https://github.com/Yidadaa/ChatGPT-Next-Web/issues) / [加入 Discord](https://discord.gg/zrhvHCr79N)
+[NextChatAI](https://nextchat.dev/chat?utm_source=readme) / [企业版](#%E4%BC%81%E4%B8%9A%E7%89%88) / [演示 Demo](https://chat-gpt-next-web.vercel.app/) / [反馈 Issues](https://github.com/Yidadaa/ChatGPT-Next-Web/issues) / [加入 Discord](https://discord.gg/zrhvHCr79N)
[
](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FChatGPTNextWeb%2FChatGPT-Next-Web&env=OPENAI_API_KEY&env=CODE&project-name=nextchat&repository-name=NextChat) [
](https://zeabur.com/templates/ZBUEFA) [
](https://gitpod.io/#https://github.com/Yidadaa/ChatGPT-Next-Web)
diff --git a/README_JA.md b/README_JA.md
index ba3c514dc..416928c26 100644
--- a/README_JA.md
+++ b/README_JA.md
@@ -5,7 +5,7 @@
ワンクリックで無料であなた専用の ChatGPT ウェブアプリをデプロイ。GPT3、GPT4 & Gemini Pro モデルをサポート。
-[NextChatAI](https://nextchat.dev/chat) / [企業版](#企業版) / [デモ](https://chat-gpt-next-web.vercel.app/) / [フィードバック](https://github.com/Yidadaa/ChatGPT-Next-Web/issues) / [Discordに参加](https://discord.gg/zrhvHCr79N)
+[NextChatAI](https://nextchat.dev/chat?utm_source=readme) / [企業版](#企業版) / [デモ](https://chat-gpt-next-web.vercel.app/) / [フィードバック](https://github.com/Yidadaa/ChatGPT-Next-Web/issues) / [Discordに参加](https://discord.gg/zrhvHCr79N)
[
](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FChatGPTNextWeb%2FChatGPT-Next-Web&env=OPENAI_API_KEY&env=CODE&project-name=nextchat&repository-name=NextChat) [
](https://zeabur.com/templates/ZBUEFA) [
](https://gitpod.io/#https://github.com/Yidadaa/ChatGPT-Next-Web)
diff --git a/app/app/(auth)/login/set-password/page.tsx b/app/app/(auth)/login/set-password/page.tsx
index 2ee04158c..1e0f60ff9 100644
--- a/app/app/(auth)/login/set-password/page.tsx
+++ b/app/app/(auth)/login/set-password/page.tsx
@@ -35,7 +35,6 @@ export default function SetPasswordPage() {
const onFinish: FormProps["onFinish"] = (values) => {
// setLoading(true);
// console.log('-------------', values)
- // @ts-expect-error
fetch(`/api/user/${session?.user?.id}`, {
method: "PUT",
credentials: "include",
@@ -61,31 +60,28 @@ export default function SetPasswordPage() {
layout="vertical"
onFinish={onFinish}
>
- {
- // @ts-expect-error
- status === "authenticated" && session?.user?.hasPassword && (
- {
- if (!value) {
- return Promise.reject(new Error("请填写该字段"));
- }
- },
+ {status === "authenticated" && session?.user?.hasPassword && (
+ {
+ if (!value) {
+ return Promise.reject(new Error("请填写该字段"));
+ }
},
- ]}
- >
- }
- type="password"
- autoComplete="current-password"
- id="user_old_password"
- />
-
- )
- }
+ },
+ ]}
+ >
+ }
+ type="password"
+ autoComplete="current-password"
+ id="user_old_password"
+ />
+
+ )}
{
- // @ts-expect-error
if (!value?.user?.hasPassword) {
if (result_url === "/") {
result_url = "/login/set-password";
diff --git a/app/components/chat.tsx b/app/components/chat.tsx
index 29091aced..c50905d2e 100644
--- a/app/components/chat.tsx
+++ b/app/components/chat.tsx
@@ -438,14 +438,23 @@ function useScrollToBottom(
if (dom) {
requestAnimationFrame(() => {
setAutoScroll(true);
- dom.scrollTo(0, dom.scrollHeight);
+ // dom.scrollTo(0, dom.scrollHeight);
+ // 丝滑一点
+ dom.scrollTo({
+ top: dom.scrollHeight,
+ behavior: "smooth",
+ });
});
}
}
// auto scroll
useEffect(() => {
- if (autoScroll && !detach) {
+ // if (autoScroll && !detach) {
+ // scrollDomToBottom();
+ // }
+ // 自动滚动一直有bug,直接强制修改了
+ if (autoScroll) {
scrollDomToBottom();
}
});
diff --git a/app/components/markdown.tsx b/app/components/markdown.tsx
index db4d757b4..3df9d00fb 100644
--- a/app/components/markdown.tsx
+++ b/app/components/markdown.tsx
@@ -253,7 +253,7 @@ function tryWrapHtmlCode(text: string) {
},
)
.replace(
- /(<\/body>)([\r\n\s]*?)(<\/html>)([\n\r]*?)([`]*?)([\n\r]*?)/g,
+ /(<\/body>)([\r\n\s]*?)(<\/html>)([\n\r]*)([`]*)([\n\r]*?)/g,
(match, bodyEnd, space, htmlEnd, newLine, quoteEnd) => {
return !quoteEnd ? bodyEnd + space + htmlEnd + "\n```\n" : match;
},
diff --git a/chat.conf b/chat.conf
deleted file mode 100644
index 1a5c8d26e..000000000
--- a/chat.conf
+++ /dev/null
@@ -1,88 +0,0 @@
-map $http_upgrade $connection_upgrade {
- default upgrade;
- '' close;
-}
-
- # 匹配以 www. 开头的请求并重定向到 HTTPS 的不带 www.
- server {
- listen 80;
- listen 443 ssl;
- server_name ~^www\.(?.+)$;
-
- ssl_protocols TLSv1.2 TLSv1.3;
- ssl_certificate "/root/cert.pem";
- ssl_certificate_key "/root/cert.key";
- ssl_session_cache shared:SSL:1m;
- ssl_session_timeout 10m;
- ssl_ciphers PROFILE=SYSTEM;
- ssl_prefer_server_ciphers on;
- add_header Strict-Transport-Security "max-age=31536000";
-
- return 301 https://$domain$request_uri;
- }
-
- # 匹配任意 HTTP 重定向到 HTTPS
- server {
- listen 80 default_server;
- server_name _;
-
- # 将 HTTP 请求重定向到 HTTPS
- return 301 https://$host$request_uri;
- }
-
-
-
-server {
- listen 443 ssl http2 default_server;
- server_name _;
-
- ssl_protocols TLSv1.2 TLSv1.3;
- ssl_certificate "/root/cert.pem";
- ssl_certificate_key "/root/cert.key";
- ssl_session_cache shared:SSL:1m;
- ssl_session_timeout 10m;
- ssl_ciphers PROFILE=SYSTEM;
- ssl_prefer_server_ciphers on;
- add_header Strict-Transport-Security "max-age=31536000";
-
- access_log /var/log/nginx/access.log;
- error_log /var/log/nginx/error.log;
-
-
-#REWRITE-START
-if ($host ~* ^www\.(.+)$) {
- set $new_host \$1;
- return 301 https://$new_host$request_uri;
-}
-#REWRITE-END
-
-#PROXY-START/
-
-location ^~ /
-{
- proxy_pass http://127.0.0.1:23000;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header REMOTE-HOST $remote_addr;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection $connection_upgrade;
- proxy_http_version 1.1;
-
- # 禁止缓存的相关设置
- proxy_buffering off;
- proxy_no_cache 1;
- proxy_cache_bypass 1;
- add_header X-Accel-Buffering "no";
- # 设置代理超时
- proxy_read_timeout 24h;
- proxy_connect_timeout 3m;
- proxy_send_timeout 24h;
- proxy_max_temp_file_size 0;
-}
-
-#PROXY-END/
-
-
-}
-
diff --git a/lib/auth.ts b/lib/auth.ts
index b698f82f4..7562a60a8 100644
--- a/lib/auth.ts
+++ b/lib/auth.ts
@@ -9,6 +9,9 @@ import { isEmail, isName } from "@/lib/auth_list";
import {createTransport} from "nodemailer";
import { comparePassword } from "@/lib/utils";
import { randomBytes } from "crypto";
+import { type Session } from "next-auth";
+import { type JWT } from "next-auth/jwt";
+
const SECURE_COOKIES:boolean = !!process.env.SECURE_COOKIES;
let verificationTokens = new Map();
@@ -153,25 +156,23 @@ export const authOptions: NextAuthOptions = {
if (user) {
token.user = user;
} else {
- const updateUser = await prisma.user.findUnique({ where: { id: token.sub }});
- // console.log('========', updateUser)
+ const updateUser: User | null = await prisma.user.findUnique({ where: { id: token.sub }});
if (!updateUser || !updateUser.allowToLogin) {
throw new Error('无法刷新令牌,用户状态不正确');
}
- token.user = updateUser;
+ token.user = updateUser as User;
}
return token;
},
- session: async ({ session, token }) => {
+ session: async ({ session, token }: {
+ session: Session,
+ token: JWT
+ }) => {
session.user = {
...session.user,
- // @ts-expect-error
- id: token?.sub,
- // @ts-expect-error
+ id: token?.sub ?? "",
username: token?.user?.username || token?.user?.gh_username,
- // @ts-expect-error
hasPassword: !!token?.user?.password,
- // @ts-expect-error
isAdmin: token?.user?.isAdmin,
};
// console.log('555555555,', session, token)
diff --git a/lib/auth_client.ts b/lib/auth_client.ts
index 143480963..5b65b200f 100644
--- a/lib/auth_client.ts
+++ b/lib/auth_client.ts
@@ -1,21 +1,21 @@
import { isName } from "@/lib/auth_list";
-import { CUS_JWT } from "@/lib/auth_type";
+import { type JWT } from "next-auth/jwt";
-export async function VerifiedUser(session: CUS_JWT | null) {
+export async function VerifiedUser(session: JWT | null) {
const userId = session?.sub
const name = session?.email || session?.name
return !!(name && isName(name) && userId);
}
-export async function VerifiedAdminUser(session: CUS_JWT | null) {
+export async function VerifiedAdminUser(session: JWT | null) {
// console.log('-------', session, session?.user?.isAdmin)
return !!session?.user?.isAdmin;
// const name = session?.email || session?.name
// return !!(name && ADMIN_LIST.includes(name));
}
-export function VerifiedNeedSetPassword(path: string, session: CUS_JWT | null,) {
+export function VerifiedNeedSetPassword(path: string, session: JWT | null,) {
const need_set_pwd = !session?.user?.password
return path === "/login/set-password" && need_set_pwd;
}
diff --git a/lib/auth_type.ts b/lib/auth_type.ts
deleted file mode 100644
index 28623eb73..000000000
--- a/lib/auth_type.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { JWT } from "next-auth/jwt";
-import { User } from "@prisma/client";
-
-export type CUS_JWT = JWT & {
- user: User,
-}
diff --git a/lib/types/next-auth.d.ts b/lib/types/next-auth.d.ts
new file mode 100644
index 000000000..f062194b2
--- /dev/null
+++ b/lib/types/next-auth.d.ts
@@ -0,0 +1,45 @@
+// types/next-auth.d.ts
+import { DefaultSession, DefaultUser } from "next-auth";
+
+
+declare module "next-auth" {
+ /**
+ * 扩展 Session 接口,添加自定义的用户属性
+ */
+ interface Session {
+ user: {
+ id: string;
+ username?: string | null;
+ hasPassword?: boolean | null;
+ isAdmin?: boolean | null;
+ } & DefaultSession["user"];
+ }
+
+ /**
+ * 扩展 User 接口,添加自定义属性
+ * 注意:保持属性可选,以与 AdapterUser 兼容
+ */
+ interface User extends DefaultUser {
+ id: string;
+ username?: string;
+ gh_username?: string;
+ password?: string;
+ isAdmin?: boolean;
+ }
+
+}
+
+declare module "next-auth/jwt" {
+ /**
+ * 扩展 JWT 接口,添加自定义的用户属性
+ */
+ interface JWT {
+ user?: {
+ id: string;
+ username?: string | null;
+ gh_username?: string | null;
+ password?: string | null;
+ isAdmin?: boolean | null;
+ };
+ }
+}
diff --git a/middleware.ts b/middleware.ts
index 1a8c7ff79..745b4314f 100644
--- a/middleware.ts
+++ b/middleware.ts
@@ -1,9 +1,7 @@
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { getToken } from "next-auth/jwt";
-import { VerifiedUser, VerifiedAdminUser, VerifiedNeedSetPassword } from "@/lib/auth_client";
-import { CUS_JWT } from "@/lib/auth_type";
-
+import { VerifiedUser, VerifiedAdminUser } from "@/lib/auth_client";
export default async function middleware(req: NextRequest) {
const url = req.nextUrl;
@@ -17,8 +15,8 @@ export default async function middleware(req: NextRequest) {
}
const session = await getToken({ req });
- const isUser = await VerifiedUser(session as CUS_JWT);
- const isAdminUser = await VerifiedAdminUser(session as CUS_JWT);
+ const isUser = await VerifiedUser(session);
+ const isAdminUser = await VerifiedAdminUser(session);
// console.log('----session', session, '---isUser', isUser, '---isAdmin', isAdminUser)
// 管理员页面的api接口还是要认证的
if (path.startsWith('/api/admin/')) {
@@ -45,7 +43,7 @@ export default async function middleware(req: NextRequest) {
);
}
- // if (VerifiedNeedSetPassword(path, session as CUS_JWT)) {
+ // if (VerifiedNeedSetPassword(path, session)) {
// console.log('-0-0-- 需要修改密码', )
// // return NextResponse.redirect(new URL("/login/set-password", req.url))
// }
diff --git a/tsconfig.json b/tsconfig.json
index c73eef3e8..ce1a04b38 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -21,7 +21,8 @@
],
"paths": {
"@/*": ["./*"]
- }
+ },
+ "typeRoots": ["lib/types"]
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "app/calcTextareaHeight.ts"],
"exclude": ["node_modules"]