Compare commits
No commits in common. "d8520e72ec3f0d5a5ebfd508bff8a257aa93ecf4" and "a7370d4e8ccd1e816006d156054c7fff353a862a" have entirely different histories.
d8520e72ec
...
a7370d4e8c
@ -1,8 +0,0 @@
|
|||||||
# APP ID
|
|
||||||
NEXT_PUBLIC_APP_ID=c36db3aa-20a6-4421-8e62-c9af03020088
|
|
||||||
# APP API key
|
|
||||||
NEXT_PUBLIC_APP_KEY=app-WN8APQeButq9jIRj2g5D7r22
|
|
||||||
# API url prefix
|
|
||||||
NEXT_PUBLIC_API_URL=http://192.168.6.35:180/v1
|
|
||||||
|
|
||||||
NEXT_PUBLIC_BASE_API_URL=http://127.0.0.1:8085
|
|
||||||
8
.env.local
Normal file
8
.env.local
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# APP ID
|
||||||
|
NEXT_PUBLIC_APP_ID=8f005d85-a520-4b64-82d7-09f76104cc80
|
||||||
|
# APP API key
|
||||||
|
NEXT_PUBLIC_APP_KEY=app-9o5BfmyoyKiNui9Pe855xasf
|
||||||
|
# API url prefix
|
||||||
|
NEXT_PUBLIC_API_URL=http://192.168.6.37:180/v1
|
||||||
|
|
||||||
|
NEXT_PUBLIC_BASE_API_URL=http://192.168.6.9:8085
|
||||||
@ -1,8 +0,0 @@
|
|||||||
# APP ID
|
|
||||||
NEXT_PUBLIC_APP_ID=c36db3aa-20a6-4421-8e62-c9af03020088
|
|
||||||
# APP API key
|
|
||||||
NEXT_PUBLIC_APP_KEY=app-WN8APQeButq9jIRj2g5D7r22
|
|
||||||
# API url prefix
|
|
||||||
NEXT_PUBLIC_API_URL=http://192.168.6.35:180/v1
|
|
||||||
|
|
||||||
NEXT_PUBLIC_BASE_API_URL=http://192.168.6.35:8088/ruoyi-admin
|
|
||||||
28
.eslintrc.json
Normal file
28
.eslintrc.json
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"extends": [
|
||||||
|
"@antfu",
|
||||||
|
"plugin:react-hooks/recommended"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"@typescript-eslint/consistent-type-definitions": [
|
||||||
|
"error",
|
||||||
|
"type"
|
||||||
|
],
|
||||||
|
"no-console": "off",
|
||||||
|
"indent": "off",
|
||||||
|
"@typescript-eslint/indent": [
|
||||||
|
"error",
|
||||||
|
2,
|
||||||
|
{
|
||||||
|
"SwitchCase": 1,
|
||||||
|
"flatTernaryExpressions": false,
|
||||||
|
"ignoredNodes": [
|
||||||
|
"PropertyDefinition[decorators]",
|
||||||
|
"TSUnionType",
|
||||||
|
"FunctionExpression[params]:has(Identifier[decorators])"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"react-hooks/exhaustive-deps": "warn"
|
||||||
|
}
|
||||||
|
}
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -48,7 +48,7 @@ yarn.lock
|
|||||||
.yarnrc.yml
|
.yarnrc.yml
|
||||||
|
|
||||||
# pmpm
|
# pmpm
|
||||||
# pnpm-lock.yaml
|
pnpm-lock.yaml
|
||||||
|
|
||||||
# info
|
# info
|
||||||
keys.ts
|
keys.ts
|
||||||
|
|||||||
@ -4,11 +4,9 @@ WORKDIR /app
|
|||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
RUN npm install -g pnpm
|
RUN yarn install
|
||||||
RUN npm config set registry https://registry.npmmirror.com
|
RUN yarn build
|
||||||
RUN pnpm install
|
|
||||||
RUN pnpm build
|
|
||||||
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|
||||||
CMD ["pnpm","start"]
|
CMD ["yarn","start"]
|
||||||
|
|||||||
@ -1,17 +1,12 @@
|
|||||||
import { type NextRequest } from "next/server";
|
import { type NextRequest } from 'next/server'
|
||||||
import { NextResponse } from "next/server";
|
import { NextResponse } from 'next/server'
|
||||||
import { client, getInfo } from "@/app/api/utils/common";
|
import { client, getInfo } from '@/app/api/utils/common'
|
||||||
|
|
||||||
export async function POST(
|
export async function POST(request: NextRequest, { params }: {
|
||||||
request: NextRequest,
|
params: { taskId: string }
|
||||||
{
|
}) {
|
||||||
params,
|
const { taskId } = await params
|
||||||
}: {
|
const { user } = getInfo(request)
|
||||||
params: Promise<{ taskId: string }>;
|
const { data } = await client.stopChat(taskId, user)
|
||||||
}
|
return NextResponse.json(data)
|
||||||
) {
|
|
||||||
const { taskId } = await params;
|
|
||||||
const { user } = getInfo(request);
|
|
||||||
const { data } = await client.stopChat(taskId, user);
|
|
||||||
return NextResponse.json(data);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,26 +1,19 @@
|
|||||||
import { type NextRequest } from "next/server";
|
import { type NextRequest } from 'next/server'
|
||||||
import { NextResponse } from "next/server";
|
import { NextResponse } from 'next/server'
|
||||||
import { client, getInfo } from "@/app/api/utils/common";
|
import { client, getInfo } from '@/app/api/utils/common'
|
||||||
|
|
||||||
export async function POST(
|
export async function POST(request: NextRequest, { params }: {
|
||||||
request: NextRequest,
|
params: { conversationId: string }
|
||||||
{
|
}) {
|
||||||
params,
|
const body = await request.json()
|
||||||
}: {
|
const {
|
||||||
params: Promise<{ conversationId: string }>;
|
auto_generate,
|
||||||
}
|
name,
|
||||||
) {
|
} = body
|
||||||
const body = await request.json();
|
const { conversationId } = await params
|
||||||
const { auto_generate, name } = body;
|
const { user } = getInfo(request)
|
||||||
const { conversationId } = await params;
|
|
||||||
const { user } = getInfo(request);
|
|
||||||
|
|
||||||
// auto generate name
|
// auto generate name
|
||||||
const { data } = await client.renameConversation(
|
const { data } = await client.renameConversation(conversationId, name, user, auto_generate)
|
||||||
conversationId,
|
return NextResponse.json(data)
|
||||||
name,
|
|
||||||
user,
|
|
||||||
auto_generate
|
|
||||||
);
|
|
||||||
return NextResponse.json(data);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,18 +1,13 @@
|
|||||||
import { type NextRequest } from "next/server";
|
import { type NextRequest } from 'next/server'
|
||||||
import { NextResponse } from "next/server";
|
import { NextResponse } from 'next/server'
|
||||||
import { client, getInfo } from "@/app/api/utils/common";
|
import { client, getInfo } from '@/app/api/utils/common'
|
||||||
|
|
||||||
export async function DELETE(
|
export async function DELETE(request: NextRequest, { params }: {
|
||||||
request: NextRequest,
|
params: { conversationId: string }
|
||||||
{
|
}) {
|
||||||
params,
|
const { conversationId } = await params
|
||||||
}: {
|
const { user } = await getInfo(request)
|
||||||
params: Promise<{ conversationId: string }>;
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
const { conversationId } = await params;
|
|
||||||
const { user } = await getInfo(request);
|
|
||||||
|
|
||||||
const { data } = await client.deleteConversation(conversationId, user);
|
const { data } = await client.deleteConversation(conversationId, user)
|
||||||
return NextResponse.json(data);
|
return NextResponse.json(data)
|
||||||
}
|
}
|
||||||
@ -1,34 +1,35 @@
|
|||||||
import { type NextRequest } from "next/server";
|
import { type NextRequest } from 'next/server'
|
||||||
import { NextResponse } from "next/server";
|
import { NextResponse } from 'next/server'
|
||||||
import { client, getInfo, setSession } from "@/app/api/utils/common";
|
import { client, getInfo, setSession } from '@/app/api/utils/common'
|
||||||
|
|
||||||
export async function GET(request: NextRequest) {
|
export async function GET(request: NextRequest) {
|
||||||
const { sessionId, user } = getInfo(request);
|
const { sessionId, user } = getInfo(request)
|
||||||
try {
|
try {
|
||||||
const { data } = await client.getInfo(user);
|
const { data } = await client.getInfo(user)
|
||||||
// 接口未返回 建议从配置文件或者环境变量获取
|
// 接口未返回 建议从配置文件或者环境变量获取
|
||||||
data.app_id = "app_id";
|
data.app_id = 'app_id'
|
||||||
data.site = {
|
data.site = {
|
||||||
title: "ERP问答助手",
|
"title": "卓远智能问答",
|
||||||
chat_color_theme: null,
|
"chat_color_theme": null,
|
||||||
chat_color_theme_inverted: false,
|
"chat_color_theme_inverted": false,
|
||||||
icon_type: "image",
|
"icon_type": "image",
|
||||||
icon: "48159ee8",
|
"icon": "48159ee8",
|
||||||
icon_background: "#E4FBCC",
|
"icon_background": "#E4FBCC",
|
||||||
icon_url: "/files/aaa.png",
|
"icon_url": "/files/aaa.png",
|
||||||
description: "Zhuoyuan AI Helper",
|
"description": "Zhuoyuan AI Helper",
|
||||||
copyright: null,
|
"copyright": null,
|
||||||
privacy_policy: null,
|
"privacy_policy": null,
|
||||||
custom_disclaimer: "",
|
"custom_disclaimer": "",
|
||||||
default_language: "zh-Hans",
|
"default_language": "zh-Hans",
|
||||||
prompt_public: false,
|
"prompt_public": false,
|
||||||
show_workflow_steps: true,
|
"show_workflow_steps": true,
|
||||||
use_icon_as_answer_icon: false,
|
"use_icon_as_answer_icon": false
|
||||||
};
|
}
|
||||||
return NextResponse.json(data as object, {
|
return NextResponse.json(data as object, {
|
||||||
headers: setSession(sessionId),
|
headers: setSession(sessionId),
|
||||||
});
|
})
|
||||||
} catch (error) {
|
}
|
||||||
return NextResponse.json([]);
|
catch (error) {
|
||||||
|
return NextResponse.json([])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,19 +1,16 @@
|
|||||||
import { type NextRequest } from "next/server";
|
import { type NextRequest } from 'next/server'
|
||||||
import { NextResponse } from "next/server";
|
import { NextResponse } from 'next/server'
|
||||||
import { client, getInfo } from "@/app/api/utils/common";
|
import { client, getInfo } from '@/app/api/utils/common'
|
||||||
|
|
||||||
export async function POST(
|
export async function POST(request: NextRequest, { params }: {
|
||||||
request: NextRequest,
|
params: { messageId: string }
|
||||||
{
|
}) {
|
||||||
params,
|
const body = await request.json()
|
||||||
}: {
|
const {
|
||||||
params: Promise<{ messageId: string }>;
|
rating,
|
||||||
}
|
} = body
|
||||||
) {
|
const { messageId } = await params
|
||||||
const body = await request.json();
|
const { user } = getInfo(request)
|
||||||
const { rating } = body;
|
const { data } = await client.messageFeedback(messageId, rating, user)
|
||||||
const { messageId } = await params;
|
return NextResponse.json(data)
|
||||||
const { user } = getInfo(request);
|
|
||||||
const { data } = await client.messageFeedback(messageId, rating, user);
|
|
||||||
return NextResponse.json(data);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +1,10 @@
|
|||||||
import { type NextRequest } from "next/server";
|
import { type NextRequest } from 'next/server'
|
||||||
import { NextResponse } from "next/server";
|
import { NextResponse } from 'next/server'
|
||||||
import { client, getInfo } from "@/app/api/utils/common";
|
import { client, getInfo } from '@/app/api/utils/common'
|
||||||
|
|
||||||
export async function GET(
|
export async function GET(request: NextRequest, params: { messageId: string }) {
|
||||||
request: NextRequest,
|
const { messageId } = await params
|
||||||
{
|
const { user } = getInfo(request)
|
||||||
params,
|
const { data }: any = await client.getSuggested(messageId, user,)
|
||||||
}: {
|
return NextResponse.json(data)
|
||||||
params: Promise<{ messageId: string }>;
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
const { messageId } = await params;
|
|
||||||
const { user } = getInfo(request);
|
|
||||||
const { data }: any = await client.getSuggested(messageId, user);
|
|
||||||
return NextResponse.json(data);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,30 +1,20 @@
|
|||||||
import { type NextRequest } from "next/server";
|
import { type NextRequest } from 'next/server'
|
||||||
import { ChatClient } from "dify-client-plus";
|
import { ChatClient } from 'dify-client-plus'
|
||||||
import { v4 } from "uuid";
|
import { v4 } from 'uuid'
|
||||||
import { API_KEY, API_URL } from "@/config";
|
import { API_KEY, API_URL } from '@/config'
|
||||||
|
|
||||||
export const getInfo = (request: NextRequest) => {
|
export const getInfo = (request: NextRequest) => {
|
||||||
const username = request.cookies.get("username")?.value || "no-user";
|
const username = request.cookies.get('username')?.value || 'no-user'
|
||||||
const sessionId = request.cookies.get("session_id")?.value || v4();
|
const sessionId = request.cookies.get('session_id')?.value || v4()
|
||||||
const user = `${username}`;
|
const user = `${username}`
|
||||||
return {
|
return {
|
||||||
sessionId,
|
sessionId,
|
||||||
user,
|
user,
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
export const setSession = (sessionId: string) => {
|
export const setSession = (sessionId: string) => {
|
||||||
return { "Set-Cookie": `session_id=${sessionId}` };
|
return { 'Set-Cookie': `session_id=${sessionId}` }
|
||||||
};
|
|
||||||
|
|
||||||
export const client = new ChatClient(API_KEY, API_URL || undefined);
|
|
||||||
|
|
||||||
export function getCookieValue(cookieName: string): string | null {
|
|
||||||
const cookies = document.cookie.split("; ").reduce((acc, cookie) => {
|
|
||||||
const [name, value] = cookie.split("=");
|
|
||||||
acc[name] = value;
|
|
||||||
return acc;
|
|
||||||
}, {} as Record<string, string>);
|
|
||||||
|
|
||||||
return cookies[cookieName] || null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const client = new ChatClient(API_KEY, API_URL || undefined)
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import { ToastContext } from '@/app/components/base/toast'
|
|||||||
import Loading from '@/app/components/base/loading'
|
import Loading from '@/app/components/base/loading'
|
||||||
// import { fetchAgentLogDetail } from '@/service/log'
|
// import { fetchAgentLogDetail } from '@/service/log'
|
||||||
// TODO
|
// TODO
|
||||||
const fetchAgentLogDetail: any = (data: any) => {
|
const fetchAgentLogDetail = () => {
|
||||||
console.log('TODO MARS')
|
console.log('TODO MARS')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -39,7 +39,8 @@ const AnswerIcon: FC<AnswerIconProps> = ({
|
|||||||
>
|
>
|
||||||
{isValidImageIcon
|
{isValidImageIcon
|
||||||
? <img src={imageUrl} className="w-full h-full rounded-full" alt="answer icon" />
|
? <img src={imageUrl} className="w-full h-full rounded-full" alt="answer icon" />
|
||||||
: (icon && icon !== '') ? (<em-emoji id={icon} />) : (<em-emoji id='🤖' />) }
|
: (icon && icon !== '') ? <em-emoji id={icon} /> : <em-emoji id='🤖' />
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,8 +4,7 @@ import { t } from 'i18next'
|
|||||||
import { debounce } from 'lodash-es'
|
import { debounce } from 'lodash-es'
|
||||||
import copy from 'copy-to-clipboard'
|
import copy from 'copy-to-clipboard'
|
||||||
import s from './style.module.css'
|
import s from './style.module.css'
|
||||||
// import Tooltip from '@/app/components/base/tooltip'
|
import Tooltip from '@/app/components/base/tooltip'
|
||||||
import { Tooltip } from 'antd';
|
|
||||||
|
|
||||||
type ICopyBtnProps = {
|
type ICopyBtnProps = {
|
||||||
value: string
|
value: string
|
||||||
@ -32,7 +31,8 @@ const CopyBtn = ({
|
|||||||
return (
|
return (
|
||||||
<div className={`${className}`}>
|
<div className={`${className}`}>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={(isCopied ? t('appApi.copied') : t('appApi.copy'))}
|
popupContent={(isCopied ? t('appApi.copied') : t('appApi.copy'))}
|
||||||
|
asChild={false}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
onMouseLeave={onMouseLeave}
|
onMouseLeave={onMouseLeave}
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import { t } from 'i18next'
|
import { t } from 'i18next'
|
||||||
import { Refresh } from '@/app/components/base/icons/src/vender/line/general'
|
import { Refresh } from '@/app/components/base/icons/src/vender/line/general'
|
||||||
// import Tooltip from '@/app/components/base/tooltip'
|
import Tooltip from '@/app/components/base/tooltip'
|
||||||
import { Tooltip } from 'antd';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
className?: string
|
className?: string
|
||||||
@ -13,7 +12,7 @@ const RegenerateBtn = ({ className, onClick }: Props) => {
|
|||||||
return (
|
return (
|
||||||
<div className={`${className}`}>
|
<div className={`${className}`}>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={t('appApi.regenerate') as string}
|
popupContent={t('appApi.regenerate') as string}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={'box-border p-0.5 flex items-center justify-center rounded-md bg-white cursor-pointer'}
|
className={'box-border p-0.5 flex items-center justify-center rounded-md bg-white cursor-pointer'}
|
||||||
|
|||||||
@ -1,52 +1,34 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { Modal, Checkbox, Input, message } from 'antd';
|
import { Modal, Checkbox, Input, message } from 'antd';
|
||||||
import { useTranslation } from 'react-i18next'
|
|
||||||
|
|
||||||
const { TextArea } = Input;
|
const { TextArea } = Input;
|
||||||
|
|
||||||
interface FeedbackModalProps {
|
interface FeedbackModalProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onOk: (selectedOption: number | null, feedbackText: string) => Promise<void>;
|
onOk: (selectedOption: number | null, feedbackText: string) => void;
|
||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FeedbackModal: React.FC<FeedbackModalProps> = ({ open, onOk, onCancel }) => {
|
const FeedbackModal: React.FC<FeedbackModalProps> = ({ open, onOk, onCancel }) => {
|
||||||
const [selectedOption, setSelectedOption] = useState<number | null>(null);
|
const [selectedOption, setSelectedOption] = useState<number | null>(null);
|
||||||
const [feedbackText, setFeedbackText] = useState<string>('');
|
const [feedbackText, setFeedbackText] = useState<string>('');
|
||||||
const { t } = useTranslation()
|
|
||||||
const [confirmLoading, setConfirmLoading] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
const handleOk = () => {
|
||||||
if (open) {
|
if (selectedOption === null || !feedbackText) {
|
||||||
setFeedbackText('');
|
message.warning('请选择操作类型并填写反馈建议');
|
||||||
}
|
|
||||||
}, [open]);
|
|
||||||
|
|
||||||
const handleOk = async () => {
|
|
||||||
if (!feedbackText) {
|
|
||||||
message.warning('请填写反馈建议');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setConfirmLoading(true)
|
onOk(selectedOption, feedbackText);
|
||||||
try {
|
|
||||||
await onOk(selectedOption, feedbackText);
|
|
||||||
} finally {
|
|
||||||
setConfirmLoading(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
title="反馈"
|
title="反馈"
|
||||||
open={open}
|
open={open}
|
||||||
onOk={handleOk}
|
onOk={handleOk}
|
||||||
onCancel={onCancel}
|
onCancel={onCancel}
|
||||||
okText={`${t('common.operation.confirm')}`}
|
|
||||||
cancelText={`${t('common.operation.cancel')}`}
|
|
||||||
confirmLoading={confirmLoading}
|
|
||||||
>
|
>
|
||||||
{/* <div>
|
<div>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
checked={selectedOption === 0}
|
checked={selectedOption === 0}
|
||||||
onChange={() => setSelectedOption(0)}
|
onChange={() => setSelectedOption(0)}
|
||||||
@ -59,7 +41,7 @@ const FeedbackModal: React.FC<FeedbackModalProps> = ({ open, onOk, onCancel }) =
|
|||||||
>
|
>
|
||||||
修改
|
修改
|
||||||
</Checkbox>
|
</Checkbox>
|
||||||
</div> */}
|
</div>
|
||||||
<TextArea
|
<TextArea
|
||||||
rows={4}
|
rows={4}
|
||||||
placeholder="请输入您的反馈建议"
|
placeholder="请输入您的反馈建议"
|
||||||
@ -70,4 +52,4 @@ const FeedbackModal: React.FC<FeedbackModalProps> = ({ open, onOk, onCancel }) =
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default FeedbackModal;
|
export default FeedbackModal;
|
||||||
@ -46,7 +46,7 @@ export type ChatWithHistoryContextValue = {
|
|||||||
isMobile: boolean
|
isMobile: boolean
|
||||||
isInstalledApp: boolean
|
isInstalledApp: boolean
|
||||||
appId?: string
|
appId?: string
|
||||||
handleFeedback: (messageId: string, feedback: Feedback) => Promise<boolean>
|
handleFeedback: (messageId: string, feedback: Feedback) => void
|
||||||
currentChatInstanceRef: RefObject<{ handleStop: () => void }>
|
currentChatInstanceRef: RefObject<{ handleStop: () => void }>
|
||||||
themeBuilder?: ThemeBuilder
|
themeBuilder?: ThemeBuilder
|
||||||
}
|
}
|
||||||
@ -73,7 +73,7 @@ export const ChatWithHistoryContext = createContext<ChatWithHistoryContextValue>
|
|||||||
chatShouldReloadKey: '',
|
chatShouldReloadKey: '',
|
||||||
isMobile: false,
|
isMobile: false,
|
||||||
isInstalledApp: false,
|
isInstalledApp: false,
|
||||||
handleFeedback: () => new Promise(() => { }),
|
handleFeedback: () => { },
|
||||||
currentChatInstanceRef: { current: { handleStop: () => { } } },
|
currentChatInstanceRef: { current: { handleStop: () => { } } },
|
||||||
})
|
})
|
||||||
export const useChatWithHistoryContext = () => useContext(ChatWithHistoryContext)
|
export const useChatWithHistoryContext = () => useContext(ChatWithHistoryContext)
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import useSWR from "swr";
|
|||||||
import { useLocalStorageState } from "ahooks";
|
import { useLocalStorageState } from "ahooks";
|
||||||
import { produce } from "immer";
|
import { produce } from "immer";
|
||||||
import { message } from "antd";
|
import { message } from "antd";
|
||||||
import { client, getCookieValue } from "@/app/api/utils/common";
|
import { client, getInfo } from "@/app/api/utils/common";
|
||||||
import type { Callback, ChatConfig, ChatItem, Feedback } from "../types";
|
import type { Callback, ChatConfig, ChatItem, Feedback } from "../types";
|
||||||
import { CONVERSATION_ID_INFO } from "../constants";
|
import { CONVERSATION_ID_INFO } from "../constants";
|
||||||
import { buildChatItemTree } from "../utils";
|
import { buildChatItemTree } from "../utils";
|
||||||
@ -537,43 +537,16 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
|
|||||||
setCurrentConversationIdForFeedback,
|
setCurrentConversationIdForFeedback,
|
||||||
] = useState<string | null>(null);
|
] = useState<string | null>(null);
|
||||||
|
|
||||||
const [resolveFeedback, setResolveFeedback] = useState<(value: boolean | PromiseLike<boolean>) => void | null>(null);
|
|
||||||
const [isSubmittingNow, setIsSubmittingNow] = useState(false); // 防止重复提交
|
|
||||||
const handleFeedback = useCallback(
|
const handleFeedback = useCallback(
|
||||||
async (messageId: string, feedback: Feedback, conversationId: string) => {
|
(messageId: string, feedback: Feedback, conversationId: string) => {
|
||||||
console.log('feedback.rating ', feedback.rating);
|
|
||||||
|
|
||||||
setCurrentMessageId(messageId);
|
setCurrentMessageId(messageId);
|
||||||
setCurrentFeedback(feedback);
|
setCurrentFeedback(feedback);
|
||||||
setCurrentConversationIdForFeedback(conversationId);
|
setCurrentConversationIdForFeedback(conversationId);
|
||||||
|
setIsFeedbackModalVisible(true);
|
||||||
if (feedback.rating === 'like') {
|
|
||||||
setIsSubmittingNow(true)
|
|
||||||
|
|
||||||
return true
|
|
||||||
} else if (!feedback.rating) {
|
|
||||||
setIsSubmittingNow(true)
|
|
||||||
|
|
||||||
return true
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
return new Promise<boolean>(async (resolve) => {
|
|
||||||
console.log('handleFeedback', messageId, feedback, conversationId);
|
|
||||||
setIsFeedbackModalVisible(true);
|
|
||||||
setResolveFeedback(() => resolve);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
},
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (isSubmittingNow) {
|
|
||||||
handleFeedbackSubmit(null, '')
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const handleFeedbackSubmit = useCallback(
|
const handleFeedbackSubmit = useCallback(
|
||||||
async (selectedOption: number | null, feedbackText: string) => {
|
async (selectedOption: number | null, feedbackText: string) => {
|
||||||
console.log(currentMessageId);
|
console.log(currentMessageId);
|
||||||
@ -582,16 +555,16 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
|
|||||||
try {
|
try {
|
||||||
// 构造请求参数
|
// 构造请求参数
|
||||||
const requestBody = {
|
const requestBody = {
|
||||||
operationType: currentFeedback!.rating, // 0 或 1
|
operationType: selectedOption, // 0 或 1
|
||||||
feedbackText, // 用户反馈建议
|
feedbackText, // 用户反馈建议
|
||||||
conversationId: currentConversationId, // 会话 ID
|
conversationId: '89fba8a7-e4e2-4167-8b7c-b3c103797053', // 会话 ID
|
||||||
messageId: currentMessageId, // 消息 ID
|
messageId: currentMessageId, // 消息 ID
|
||||||
username: getCookieValue('username'), // 用户名
|
username: "user_admin", // 用户名
|
||||||
};
|
};
|
||||||
|
|
||||||
// 调用 Java 接口
|
// 调用 Java 接口
|
||||||
const javaResponse = await fetch(
|
const javaResponse = await fetch(
|
||||||
`/dev-api/api/conversation/feedback`,
|
`${process.env.NEXT_PUBLIC_BASE_API_URL}/api/conversation/feedback`,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
@ -605,33 +578,26 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
|
|||||||
await updateFeedback(
|
await updateFeedback(
|
||||||
{
|
{
|
||||||
url: `/messages/${currentMessageId}/feedbacks`,
|
url: `/messages/${currentMessageId}/feedbacks`,
|
||||||
body: { rating: currentFeedback!.rating },
|
body: { rating: currentFeedback.rating },
|
||||||
},
|
},
|
||||||
// isInstalledApp,
|
isInstalledApp,
|
||||||
// appId
|
appId
|
||||||
);
|
);
|
||||||
|
|
||||||
// 显示成功通知
|
// 显示成功通知
|
||||||
notify({ type: "success", message: t("common.api.success") });
|
notify({ type: "success", message: t("common.api.success") });
|
||||||
|
|
||||||
if (resolveFeedback) {
|
|
||||||
resolveFeedback(true); // 用户取消了反馈
|
|
||||||
setResolveFeedback(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 关闭对话框
|
// 关闭对话框
|
||||||
setIsFeedbackModalVisible(false);
|
setIsFeedbackModalVisible(false);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error:", error);
|
console.error("Error:", error);
|
||||||
notify({ type: "error", message: t("common.api.failed") });
|
notify({ type: "error", message: t("common.api.failed") });
|
||||||
} finally {
|
|
||||||
setIsSubmittingNow(false);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
currentMessageId,
|
currentMessageId,
|
||||||
currentFeedback,
|
currentFeedback,
|
||||||
currentConversationId,
|
currentConversationIdForFeedback,
|
||||||
isInstalledApp,
|
isInstalledApp,
|
||||||
appId,
|
appId,
|
||||||
notify,
|
notify,
|
||||||
@ -683,13 +649,7 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
|
|||||||
<FeedbackModal
|
<FeedbackModal
|
||||||
open={isFeedbackModalVisible}
|
open={isFeedbackModalVisible}
|
||||||
onOk={handleFeedbackSubmit}
|
onOk={handleFeedbackSubmit}
|
||||||
onCancel={() => {
|
onCancel={() => setIsFeedbackModalVisible(false)}
|
||||||
if (resolveFeedback) {
|
|
||||||
resolveFeedback(false); // 用户取消了反馈
|
|
||||||
setResolveFeedback(null);
|
|
||||||
}
|
|
||||||
setIsFeedbackModalVisible(false)
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|||||||
@ -199,7 +199,7 @@ const ChatWithHistoryWrapWithCheckToken: FC<ChatWithHistoryWrapProps> = ({
|
|||||||
if (!accessToken) {
|
if (!accessToken) {
|
||||||
router.replace("/login");
|
router.replace("/login");
|
||||||
} else {
|
} else {
|
||||||
fetch(`/dev-api/getInfo`, {
|
fetch(`${process.env.NEXT_PUBLIC_BASE_API_URL}/getInfo`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${accessToken}`,
|
Authorization: `Bearer ${accessToken}`,
|
||||||
|
|||||||
@ -3,7 +3,6 @@ import {
|
|||||||
memo,
|
memo,
|
||||||
useMemo,
|
useMemo,
|
||||||
useState,
|
useState,
|
||||||
useCallback
|
|
||||||
} from 'react'
|
} from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import type { ChatItem } from '../../types'
|
import type { ChatItem } from '../../types'
|
||||||
@ -20,9 +19,8 @@ import {
|
|||||||
ThumbsDown,
|
ThumbsDown,
|
||||||
ThumbsUp,
|
ThumbsUp,
|
||||||
} from '@/app/components/base/icons/src/vender/line/alertsAndFeedback'
|
} from '@/app/components/base/icons/src/vender/line/alertsAndFeedback'
|
||||||
// import Tooltip from '@/app/components/base/tooltip'
|
import Tooltip from '@/app/components/base/tooltip'
|
||||||
import Log from '@/app/components/chat/log'
|
import Log from '@/app/components/chat/log'
|
||||||
import { message, Popconfirm, Tooltip } from 'antd';
|
|
||||||
|
|
||||||
interface OperationProps {
|
interface OperationProps {
|
||||||
item: ChatItem
|
item: ChatItem
|
||||||
@ -77,19 +75,10 @@ const Operation: FC<OperationProps> = ({
|
|||||||
if (!config?.supportFeedback || !onFeedback)
|
if (!config?.supportFeedback || !onFeedback)
|
||||||
return
|
return
|
||||||
|
|
||||||
if (await onFeedback?.(id, { rating })) {
|
await onFeedback?.(id, { rating })
|
||||||
setLocalFeedback({ rating })
|
setLocalFeedback({ rating })
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const confirmCancelCallback = useCallback(async () => {
|
|
||||||
try {
|
|
||||||
await handleFeedback(null)
|
|
||||||
} finally {
|
|
||||||
message.success(localFeedback!.rating === 'like' ? `${t('appDebug.operation.cancelAgree')}成功` : `${t('appDebug.operation.cancelDisagree')}成功`)
|
|
||||||
}
|
|
||||||
}, [handleFeedback])
|
|
||||||
|
|
||||||
const operationWidth = useMemo(() => {
|
const operationWidth = useMemo(() => {
|
||||||
let width = 0
|
let width = 0
|
||||||
if (!isOpeningStatement)
|
if (!isOpeningStatement)
|
||||||
@ -149,7 +138,7 @@ const Operation: FC<OperationProps> = ({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{/*
|
{/*
|
||||||
{(!isOpeningStatement && config?.supportAnnotation && config.annotation_reply?.enabled) && (
|
{(!isOpeningStatement && config?.supportAnnotation && config.annotation_reply?.enabled) && (
|
||||||
<AnnotationCtrlBtn
|
<AnnotationCtrlBtn
|
||||||
appId={config?.appId || ''}
|
appId={config?.appId || ''}
|
||||||
@ -181,7 +170,7 @@ const Operation: FC<OperationProps> = ({
|
|||||||
{
|
{
|
||||||
config?.supportFeedback && !localFeedback?.rating && onFeedback && !isOpeningStatement && (
|
config?.supportFeedback && !localFeedback?.rating && onFeedback && !isOpeningStatement && (
|
||||||
<div className='hidden group-hover:flex shrink-0 items-center px-0.5 bg-white border-[0.5px] border-gray-100 shadow-md text-gray-500 rounded-lg'>
|
<div className='hidden group-hover:flex shrink-0 items-center px-0.5 bg-white border-[0.5px] border-gray-100 shadow-md text-gray-500 rounded-lg'>
|
||||||
<Tooltip title={t('appDebug.operation.agree')}>
|
<Tooltip popupContent={t('appDebug.operation.agree')}>
|
||||||
<div
|
<div
|
||||||
className='flex items-center justify-center mr-0.5 w-6 h-6 rounded-md hover:bg-black/5 hover:text-gray-800 cursor-pointer'
|
className='flex items-center justify-center mr-0.5 w-6 h-6 rounded-md hover:bg-black/5 hover:text-gray-800 cursor-pointer'
|
||||||
onClick={() => handleFeedback('like')}
|
onClick={() => handleFeedback('like')}
|
||||||
@ -190,7 +179,7 @@ const Operation: FC<OperationProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={t('appDebug.operation.disagree')}
|
popupContent={t('appDebug.operation.disagree')}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className='flex items-center justify-center w-6 h-6 rounded-md hover:bg-black/5 hover:text-gray-800 cursor-pointer'
|
className='flex items-center justify-center w-6 h-6 rounded-md hover:bg-black/5 hover:text-gray-800 cursor-pointer'
|
||||||
@ -205,37 +194,27 @@ const Operation: FC<OperationProps> = ({
|
|||||||
{
|
{
|
||||||
config?.supportFeedback && localFeedback?.rating && onFeedback && !isOpeningStatement && (
|
config?.supportFeedback && localFeedback?.rating && onFeedback && !isOpeningStatement && (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={localFeedback.rating === 'like' ? t('appDebug.operation.cancelAgree') : t('appDebug.operation.cancelDisagree')}
|
popupContent={localFeedback.rating === 'like' ? t('appDebug.operation.cancelAgree') : t('appDebug.operation.cancelDisagree')}
|
||||||
>
|
>
|
||||||
<Popconfirm
|
<div
|
||||||
title={localFeedback.rating === 'like' ? t('appDebug.operation.cancelAgree') : t('appDebug.operation.cancelDisagree')}
|
className={`
|
||||||
description={localFeedback.rating === 'like' ? `是否${t('appDebug.operation.cancelAgree')}?` : `是否${t('appDebug.operation.cancelDisagree')}?`}
|
flex items-center justify-center w-7 h-7 rounded-[10px] border-[2px] border-white cursor-pointer
|
||||||
onConfirm={confirmCancelCallback}
|
${localFeedback.rating === 'like' && 'bg-blue-50 text-blue-600'}
|
||||||
okText={`${t('common.operation.confirm')}`}
|
${localFeedback.rating === 'dislike' && 'bg-red-100 text-red-600'}
|
||||||
cancelText={`${t('common.operation.cancel')}`}
|
`}
|
||||||
|
onClick={() => handleFeedback(null)}
|
||||||
>
|
>
|
||||||
<button
|
{
|
||||||
type="button"
|
localFeedback.rating === 'like' && (
|
||||||
className={`
|
<ThumbsUp className='w-4 h-4' />
|
||||||
flex items-center justify-center w-7 h-7 rounded-[10px] border-[2px] border-white cursor-pointer
|
)
|
||||||
${localFeedback.rating === 'like' && 'bg-blue-50 text-blue-600'}
|
}
|
||||||
${localFeedback.rating === 'dislike' && 'bg-red-100 text-red-600'}
|
{
|
||||||
`}
|
localFeedback.rating === 'dislike' && (
|
||||||
onClick={(e) => e.stopPropagation()}
|
<ThumbsDown className='w-4 h-4' />
|
||||||
>
|
)
|
||||||
{
|
}
|
||||||
localFeedback.rating === 'like' && (
|
</div>
|
||||||
<ThumbsUp className='w-4 h-4' />
|
|
||||||
)
|
|
||||||
}
|
|
||||||
{
|
|
||||||
localFeedback.rating === 'dislike' && (
|
|
||||||
<ThumbsDown className='w-4 h-4' />
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</button>
|
|
||||||
|
|
||||||
</Popconfirm>
|
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -60,7 +60,7 @@ export type ChatProps = {
|
|||||||
onAnnotationAdded?: (annotationId: string, authorName: string, question: string, answer: string, index: number) => void
|
onAnnotationAdded?: (annotationId: string, authorName: string, question: string, answer: string, index: number) => void
|
||||||
onAnnotationRemoved?: (index: number) => void
|
onAnnotationRemoved?: (index: number) => void
|
||||||
chatNode?: ReactNode
|
chatNode?: ReactNode
|
||||||
onFeedback?: (messageId: string, feedback: Feedback) => Promise<boolean>
|
onFeedback?: (messageId: string, feedback: Feedback) => void
|
||||||
chatAnswerContainerInner?: string
|
chatAnswerContainerInner?: string
|
||||||
hideProcessDetail?: boolean
|
hideProcessDetail?: boolean
|
||||||
hideLogModal?: boolean
|
hideLogModal?: boolean
|
||||||
|
|||||||
@ -1,70 +1,70 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
|
|
||||||
export default function LoginPage() {
|
export default function LoginPage() {
|
||||||
const [username, setUsername] = useState('')
|
const [username, setUsername] = useState('')
|
||||||
const [password, setPassword] = useState('')
|
const [password, setPassword] = useState('')
|
||||||
const [error, setError] = useState('')
|
const [error, setError] = useState('')
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const [loading, setLoading] = useState(false) // 新增加载状态
|
const [loading, setLoading] = useState(false) // 新增加载状态
|
||||||
|
|
||||||
const handleLogin = async (e: React.FormEvent) => {
|
const handleLogin = async (e: React.FormEvent) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
setLoading(true) // 开始加载
|
setLoading(true) // 开始加载
|
||||||
fetch(`/dev-api/login`, {
|
fetch(`${process.env.NEXT_PUBLIC_BASE_API_URL}/login`, {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
body: JSON.stringify({ username, password }),
|
body: JSON.stringify({ username, password }),
|
||||||
}).then(res => res.json()).then(data => {
|
}).then(res => res.json()).then(data => {
|
||||||
if (data.code === 200) {
|
if (data.code === 200) {
|
||||||
localStorage.setItem('token', data.token)
|
localStorage.setItem('token', data.token)
|
||||||
document.cookie = `username=${username}; path=/` // 新增cookie设置
|
document.cookie = `username=${username}; path=/` // 新增cookie设置
|
||||||
router.push('/')
|
router.push('/')
|
||||||
} else {
|
} else {
|
||||||
setError('登录失败,请检查凭证')
|
setError('登录失败,请检查凭证')
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-gray-100 flex items-center justify-center">
|
<div className="min-h-screen bg-gray-100 flex items-center justify-center">
|
||||||
<div className="bg-white p-8 rounded-lg shadow-md w-96">
|
<div className="bg-white p-8 rounded-lg shadow-md w-96">
|
||||||
<h1 className="text-2xl font-bold mb-6 text-center">Login</h1>
|
<h1 className="text-2xl font-bold mb-6 text-center">Login</h1>
|
||||||
<form onSubmit={handleLogin}>
|
<form onSubmit={handleLogin}>
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
<label className="block text-sm font-medium mb-1">Username</label>
|
<label className="block text-sm font-medium mb-1">Username</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
className="w-full px-3 py-2 border rounded-md"
|
className="w-full px-3 py-2 border rounded-md"
|
||||||
value={username}
|
value={username}
|
||||||
onChange={e => setUsername(e.target.value)}
|
onChange={e => setUsername(e.target.value)}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-6">
|
<div className="mb-6">
|
||||||
<label className="block text-sm font-medium mb-1">Password</label>
|
<label className="block text-sm font-medium mb-1">Password</label>
|
||||||
<input
|
<input
|
||||||
type="password"
|
type="password"
|
||||||
className="w-full px-3 py-2 border rounded-md"
|
className="w-full px-3 py-2 border rounded-md"
|
||||||
value={password}
|
value={password}
|
||||||
onChange={e => setPassword(e.target.value)}
|
onChange={e => setPassword(e.target.value)}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{error && <p className="text-red-500 text-sm mb-4">{error}</p>}
|
{error && <p className="text-red-500 text-sm mb-4">{error}</p>}
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={loading} // 禁用按钮
|
disabled={loading} // 禁用按钮
|
||||||
className={`w-full bg-blue-500 text-white py-2 px-4 rounded-md transition-colors ${!loading && 'hover:bg-blue-600'}`}
|
className={`w-full bg-blue-500 text-white py-2 px-4 rounded-md transition-colors ${!loading && 'hover:bg-blue-600'}`}
|
||||||
>
|
>
|
||||||
{loading ? 'Loading...' : 'Sign In'}
|
{loading ? 'Loading...' : 'Sign In'}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import React from 'react'
|
|||||||
|
|
||||||
import type { IMainProps } from '@/app/components'
|
import type { IMainProps } from '@/app/components'
|
||||||
import ChatWithHistoryWrapWithCheckToken from '@/app/components/chat-with-history'
|
import ChatWithHistoryWrapWithCheckToken from '@/app/components/chat-with-history'
|
||||||
import '@ant-design/v5-patch-for-react-19';
|
|
||||||
|
|
||||||
const App: FC<IMainProps> = ({
|
const App: FC<IMainProps> = ({
|
||||||
params,
|
params,
|
||||||
|
|||||||
@ -1,13 +1,11 @@
|
|||||||
@import "preflight.css";
|
@import "preflight.css";
|
||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
|
||||||
@import '../../themes/light.css';
|
@import '../../themes/light.css';
|
||||||
@import '../../themes/dark.css';
|
@import '../../themes/dark.css';
|
||||||
@import "../../themes/manual-light.css";
|
@import "../../themes/manual-light.css";
|
||||||
@import "../../themes/manual-dark.css";
|
@import "../../themes/manual-dark.css";
|
||||||
@import "../components/base/button/index.css";
|
|
||||||
@import "../components/base/action-button/index.css";
|
|
||||||
@import "../components/base/modal/index.css";
|
|
||||||
@tailwind base;
|
|
||||||
@tailwind components;
|
|
||||||
|
|
||||||
html {
|
html {
|
||||||
color-scheme: light;
|
color-scheme: light;
|
||||||
@ -682,4 +680,8 @@ button:focus-within {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@tailwind utilities;
|
@import "../components/base/button/index.css";
|
||||||
|
@import "../components/base/action-button/index.css";
|
||||||
|
@import "../components/base/modal/index.css";
|
||||||
|
|
||||||
|
@tailwind utilities;
|
||||||
@ -1,32 +0,0 @@
|
|||||||
const antfu = require('@antfu/eslint-config').default
|
|
||||||
|
|
||||||
// module.exports = antfu()
|
|
||||||
|
|
||||||
export default {
|
|
||||||
extends: [
|
|
||||||
'@antfu',
|
|
||||||
'plugin:react-hooks/recommended',
|
|
||||||
],
|
|
||||||
rules: {
|
|
||||||
'@typescript-eslint/consistent-type-definitions': [
|
|
||||||
'error',
|
|
||||||
'type',
|
|
||||||
],
|
|
||||||
'no-console': 'off',
|
|
||||||
'indent': 'off',
|
|
||||||
'@typescript-eslint/indent': [
|
|
||||||
'error',
|
|
||||||
2,
|
|
||||||
{
|
|
||||||
SwitchCase: 1,
|
|
||||||
flatTernaryExpressions: false,
|
|
||||||
ignoredNodes: [
|
|
||||||
'PropertyDefinition[decorators]',
|
|
||||||
'TSUnionType',
|
|
||||||
'FunctionExpression[params]:has(Identifier[decorators])',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'react-hooks/exhaustive-deps': 'warn',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
@ -1,44 +1,32 @@
|
|||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
eslint: {
|
|
||||||
// Warning: This allows production builds to successfully complete even if
|
|
||||||
// your project has ESLint errors.
|
|
||||||
ignoreDuringBuilds: true,
|
|
||||||
},
|
|
||||||
typescript: {
|
|
||||||
// !! WARN !!
|
|
||||||
// Dangerously allow production builds to successfully complete even if
|
|
||||||
// your project has type errors.
|
|
||||||
// !! WARN !!
|
|
||||||
ignoreBuildErrors: true,
|
|
||||||
},
|
|
||||||
reactStrictMode: true,
|
reactStrictMode: true,
|
||||||
// 压缩优化(Next.js 13+默认启用SWC,无需手动配置)
|
// 压缩优化(Next.js 13+默认启用SWC,无需手动配置)
|
||||||
compress: true,
|
compress: true,
|
||||||
|
|
||||||
// 图片优化
|
// 图片优化
|
||||||
images: {
|
images: {
|
||||||
formats: ['image/avif', 'image/webp'],
|
formats: ["image/avif", "image/webp"],
|
||||||
domains: ['cdn.yourdomain.com'],
|
domains: ["cdn.yourdomain.com"],
|
||||||
},
|
},
|
||||||
|
|
||||||
// 修正后的开发指示器配置
|
// 修正后的开发指示器配置
|
||||||
devIndicators: {
|
devIndicators: {
|
||||||
position: 'bottom-right', // 新版统一用position
|
position: "bottom-right", // 新版统一用position
|
||||||
},
|
},
|
||||||
|
|
||||||
// 页面扩展名
|
// 页面扩展名
|
||||||
pageExtensions: ['ts', 'tsx', 'js', 'jsx', 'md', 'mdx'],
|
pageExtensions: ["ts", "tsx", "js", "jsx", "md", "mdx"],
|
||||||
|
|
||||||
// 路由重写
|
// 路由重写
|
||||||
async rewrites() {
|
async rewrites() {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
source: '/dev-api/:path*',
|
source: "/dev-api/:path*",
|
||||||
destination: `${process.env.NEXT_PUBLIC_BASE_API_URL}/:path*`,
|
destination: "http://192.168.6.9:8085/:path*",
|
||||||
},
|
},
|
||||||
]
|
];
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
module.exports = nextConfig
|
module.exports = nextConfig;
|
||||||
|
|||||||
@ -37,7 +37,6 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ant-design/v5-patch-for-react-19": "^1.0.3",
|
|
||||||
"@emoji-mart/data": "^1.2.1",
|
"@emoji-mart/data": "^1.2.1",
|
||||||
"@floating-ui/react": "^0.27.3",
|
"@floating-ui/react": "^0.27.3",
|
||||||
"@formatjs/intl-localematcher": "^0.5.10",
|
"@formatjs/intl-localematcher": "^0.5.10",
|
||||||
@ -52,7 +51,6 @@
|
|||||||
"@types/react-dom": "^19.0.3",
|
"@types/react-dom": "^19.0.3",
|
||||||
"@types/react-syntax-highlighter": "^15.5.13",
|
"@types/react-syntax-highlighter": "^15.5.13",
|
||||||
"ahooks": "^3.8.4",
|
"ahooks": "^3.8.4",
|
||||||
"antd": "^5.26.4",
|
|
||||||
"axios": "^1.7.9",
|
"axios": "^1.7.9",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"classnames": "^2.5.1",
|
"classnames": "^2.5.1",
|
||||||
|
|||||||
10497
pnpm-lock.yaml
generated
10497
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user