mirror of
https://github.com/langbot-app/LangBot.git
synced 2025-11-25 11:29:39 +08:00
Merge pull request #1605 from TwperBody/master
feat: dark mode supports for webui
This commit is contained in:
@@ -56,6 +56,15 @@
|
|||||||
background: rgba(0, 0, 0, 0.35); /* 悬停加深 */
|
background: rgba(0, 0, 0, 0.35); /* 悬停加深 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 暗黑模式下的滚动条 */
|
||||||
|
.dark ::-webkit-scrollbar-thumb {
|
||||||
|
background: rgba(255, 255, 255, 0.2); /* 半透明白色 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark ::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.35); /* 悬停加深 */
|
||||||
|
}
|
||||||
|
|
||||||
/* 兼容 Edge */
|
/* 兼容 Edge */
|
||||||
@supports (-ms-ime-align: auto) {
|
@supports (-ms-ime-align: auto) {
|
||||||
body {
|
body {
|
||||||
@@ -108,36 +117,36 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
--background: oklch(0.141 0.005 285.823);
|
--background: oklch(0.08 0.002 285.823);
|
||||||
--foreground: oklch(0.985 0 0);
|
--foreground: oklch(0.985 0 0);
|
||||||
--card: oklch(0.21 0.006 285.885);
|
--card: oklch(0.12 0.004 285.885);
|
||||||
--card-foreground: oklch(0.985 0 0);
|
--card-foreground: oklch(0.985 0 0);
|
||||||
--popover: oklch(0.21 0.006 285.885);
|
--popover: oklch(0.12 0.004 285.885);
|
||||||
--popover-foreground: oklch(0.985 0 0);
|
--popover-foreground: oklch(0.985 0 0);
|
||||||
--primary: oklch(0.92 0.004 286.32);
|
--primary: oklch(0.62 0.2 255);
|
||||||
--primary-foreground: oklch(0.21 0.006 285.885);
|
--primary-foreground: oklch(1 0 0);
|
||||||
--secondary: oklch(0.274 0.006 286.033);
|
--secondary: oklch(0.18 0.004 286.033);
|
||||||
--secondary-foreground: oklch(0.985 0 0);
|
--secondary-foreground: oklch(0.985 0 0);
|
||||||
--muted: oklch(0.274 0.006 286.033);
|
--muted: oklch(0.18 0.004 286.033);
|
||||||
--muted-foreground: oklch(0.705 0.015 286.067);
|
--muted-foreground: oklch(0.705 0.015 286.067);
|
||||||
--accent: oklch(0.274 0.006 286.033);
|
--accent: oklch(0.18 0.004 286.033);
|
||||||
--accent-foreground: oklch(0.985 0 0);
|
--accent-foreground: oklch(0.985 0 0);
|
||||||
--destructive: oklch(0.704 0.191 22.216);
|
--destructive: oklch(0.704 0.191 22.216);
|
||||||
--border: oklch(1 0 0 / 10%);
|
--border: oklch(1 0 0 / 8%);
|
||||||
--input: oklch(1 0 0 / 15%);
|
--input: oklch(1 0 0 / 10%);
|
||||||
--ring: oklch(0.552 0.016 285.938);
|
--ring: oklch(0.552 0.016 285.938);
|
||||||
--chart-1: oklch(0.488 0.243 264.376);
|
--chart-1: oklch(0.488 0.243 264.376);
|
||||||
--chart-2: oklch(0.696 0.17 162.48);
|
--chart-2: oklch(0.696 0.17 162.48);
|
||||||
--chart-3: oklch(0.769 0.188 70.08);
|
--chart-3: oklch(0.769 0.188 70.08);
|
||||||
--chart-4: oklch(0.627 0.265 303.9);
|
--chart-4: oklch(0.627 0.265 303.9);
|
||||||
--chart-5: oklch(0.645 0.246 16.439);
|
--chart-5: oklch(0.645 0.246 16.439);
|
||||||
--sidebar: oklch(0.21 0.006 285.885);
|
--sidebar: oklch(0.1 0.003 285.885);
|
||||||
--sidebar-foreground: oklch(0.985 0 0);
|
--sidebar-foreground: oklch(0.985 0 0);
|
||||||
--sidebar-primary: oklch(0.488 0.243 264.376);
|
--sidebar-primary: oklch(0.62 0.2 255);
|
||||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
--sidebar-primary-foreground: oklch(1 0 0);
|
||||||
--sidebar-accent: oklch(0.274 0.006 286.033);
|
--sidebar-accent: oklch(0.18 0.004 286.033);
|
||||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||||
--sidebar-border: oklch(1 0 0 / 10%);
|
--sidebar-border: oklch(1 0 0 / 8%);
|
||||||
--sidebar-ring: oklch(0.552 0.016 285.938);
|
--sidebar-ring: oklch(0.552 0.016 285.938);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ export default function BotDetailDialog({
|
|||||||
<SidebarProvider className="items-start w-full flex">
|
<SidebarProvider className="items-start w-full flex">
|
||||||
<Sidebar
|
<Sidebar
|
||||||
collapsible="none"
|
collapsible="none"
|
||||||
className="hidden md:flex h-[80vh] w-40 min-w-[120px] border-r bg-white"
|
className="hidden md:flex h-[80vh] w-40 min-w-[120px] border-r bg-white dark:bg-black"
|
||||||
>
|
>
|
||||||
<SidebarContent>
|
<SidebarContent>
|
||||||
<SidebarGroup>
|
<SidebarGroup>
|
||||||
|
|||||||
@@ -6,12 +6,22 @@
|
|||||||
box-shadow: 0px 2px 2px 0 rgba(0, 0, 0, 0.2);
|
box-shadow: 0px 2px 2px 0 rgba(0, 0, 0, 0.2);
|
||||||
padding: 1.2rem;
|
padding: 1.2rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .cardContainer {
|
||||||
|
background-color: #1f1f22;
|
||||||
|
box-shadow: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardContainer:hover {
|
.cardContainer:hover {
|
||||||
box-shadow: 0px 2px 8px 0 rgba(0, 0, 0, 0.1);
|
box-shadow: 0px 2px 8px 0 rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .cardContainer:hover {
|
||||||
|
box-shadow: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.iconBasicInfoContainer {
|
.iconBasicInfoContainer {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -47,6 +57,11 @@
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
color: #1a1a1a;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .basicInfoName {
|
||||||
|
color: #f0f0f0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.basicInfoDescription {
|
.basicInfoDescription {
|
||||||
@@ -58,6 +73,10 @@
|
|||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .basicInfoDescription {
|
||||||
|
color: #888888;
|
||||||
|
}
|
||||||
|
|
||||||
.basicInfoAdapterContainer {
|
.basicInfoAdapterContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@@ -71,12 +90,20 @@
|
|||||||
color: #626262;
|
color: #626262;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .basicInfoAdapterIcon {
|
||||||
|
color: #a0a0a0;
|
||||||
|
}
|
||||||
|
|
||||||
.basicInfoAdapterLabel {
|
.basicInfoAdapterLabel {
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: #626262;
|
color: #626262;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .basicInfoAdapterLabel {
|
||||||
|
color: #a0a0a0;
|
||||||
|
}
|
||||||
|
|
||||||
.basicInfoPipelineContainer {
|
.basicInfoPipelineContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@@ -90,12 +117,20 @@
|
|||||||
margin-top: 0.2rem;
|
margin-top: 0.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .basicInfoPipelineIcon {
|
||||||
|
color: #a0a0a0;
|
||||||
|
}
|
||||||
|
|
||||||
.basicInfoPipelineLabel {
|
.basicInfoPipelineLabel {
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: #626262;
|
color: #626262;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .basicInfoPipelineLabel {
|
||||||
|
color: #a0a0a0;
|
||||||
|
}
|
||||||
|
|
||||||
.bigText {
|
.bigText {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|||||||
@@ -394,7 +394,7 @@ export default function BotForm({
|
|||||||
<FormLabel>{t('bots.bindPipeline')}</FormLabel>
|
<FormLabel>{t('bots.bindPipeline')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Select onValueChange={field.onChange} {...field}>
|
<Select onValueChange={field.onChange} {...field}>
|
||||||
<SelectTrigger>
|
<SelectTrigger className="bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||||
<SelectValue
|
<SelectValue
|
||||||
placeholder={t('bots.selectPipeline')}
|
placeholder={t('bots.selectPipeline')}
|
||||||
/>
|
/>
|
||||||
@@ -467,7 +467,7 @@ export default function BotForm({
|
|||||||
}}
|
}}
|
||||||
value={field.value}
|
value={field.value}
|
||||||
>
|
>
|
||||||
<SelectTrigger className="w-[180px]">
|
<SelectTrigger className="w-[180px] bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||||
<SelectValue placeholder={t('bots.selectAdapter')} />
|
<SelectValue placeholder={t('bots.selectAdapter')} />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent className="fixed z-[1000]">
|
<SelectContent className="fixed z-[1000]">
|
||||||
|
|||||||
@@ -18,6 +18,11 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .botLogCardContainer {
|
||||||
|
background-color: #1f1f22;
|
||||||
|
border: 1px solid #2a2a2e;
|
||||||
|
}
|
||||||
|
|
||||||
.listHeader {
|
.listHeader {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 2.5rem;
|
height: 2.5rem;
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ export default function DynamicFormItemComponent({
|
|||||||
case DynamicFormItemType.SELECT:
|
case DynamicFormItemType.SELECT:
|
||||||
return (
|
return (
|
||||||
<Select value={field.value} onValueChange={field.onChange}>
|
<Select value={field.value} onValueChange={field.onChange}>
|
||||||
<SelectTrigger>
|
<SelectTrigger className="bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||||
<SelectValue placeholder={t('common.select')} />
|
<SelectValue placeholder={t('common.select')} />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
@@ -150,7 +150,7 @@ export default function DynamicFormItemComponent({
|
|||||||
case DynamicFormItemType.LLM_MODEL_SELECTOR:
|
case DynamicFormItemType.LLM_MODEL_SELECTOR:
|
||||||
return (
|
return (
|
||||||
<Select value={field.value} onValueChange={field.onChange}>
|
<Select value={field.value} onValueChange={field.onChange}>
|
||||||
<SelectTrigger>
|
<SelectTrigger className="bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||||
<SelectValue placeholder={t('models.selectModel')} />
|
<SelectValue placeholder={t('models.selectModel')} />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
@@ -267,7 +267,7 @@ export default function DynamicFormItemComponent({
|
|||||||
case DynamicFormItemType.KNOWLEDGE_BASE_SELECTOR:
|
case DynamicFormItemType.KNOWLEDGE_BASE_SELECTOR:
|
||||||
return (
|
return (
|
||||||
<Select value={field.value} onValueChange={field.onChange}>
|
<Select value={field.value} onValueChange={field.onChange}>
|
||||||
<SelectTrigger>
|
<SelectTrigger className="bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||||
<SelectValue placeholder={t('knowledge.selectKnowledgeBase')} />
|
<SelectValue placeholder={t('knowledge.selectKnowledgeBase')} />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
@@ -291,7 +291,7 @@ export default function DynamicFormItemComponent({
|
|||||||
<div key={index} className="flex gap-2 items-center">
|
<div key={index} className="flex gap-2 items-center">
|
||||||
{/* 角色选择 */}
|
{/* 角色选择 */}
|
||||||
{index === 0 ? (
|
{index === 0 ? (
|
||||||
<div className="w-[120px] px-3 py-2 border rounded bg-gray-50 text-gray-500">
|
<div className="w-[120px] px-3 py-2 border rounded bg-gray-50 dark:bg-[#2a292e] text-gray-500 dark:text-white dark:border-gray-600">
|
||||||
system
|
system
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
@@ -303,7 +303,7 @@ export default function DynamicFormItemComponent({
|
|||||||
field.onChange(newValue);
|
field.onChange(newValue);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<SelectTrigger className="w-[120px]">
|
<SelectTrigger className="w-[120px] bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||||
<SelectValue />
|
<SelectValue />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
import styles from './emptyAndCreate.module.css';
|
|
||||||
|
|
||||||
export default function EmptyAndCreateComponent({
|
|
||||||
title,
|
|
||||||
subTitle,
|
|
||||||
buttonText,
|
|
||||||
onButtonClick,
|
|
||||||
}: {
|
|
||||||
title: string;
|
|
||||||
subTitle: string;
|
|
||||||
buttonText: string;
|
|
||||||
onButtonClick: () => void;
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<div className={`${styles.emptyPageContainer}`}>
|
|
||||||
<div className={`${styles.emptyContainer}`}>
|
|
||||||
<div className={`${styles.emptyInfoContainer}`}>
|
|
||||||
<div className={`${styles.emptyInfoText}`}>{title}</div>
|
|
||||||
<div className={`${styles.emptyInfoSubText}`}>{subTitle}</div>
|
|
||||||
</div>
|
|
||||||
<div className={`${styles.emptyCreateButton}`} onClick={onButtonClick}>
|
|
||||||
{buttonText}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
.emptyPageContainer {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
background: #fff;
|
|
||||||
border: 1px solid #c5c5c5;
|
|
||||||
border-radius: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.emptyContainer {
|
|
||||||
width: 100%;
|
|
||||||
height: 50%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-evenly;
|
|
||||||
}
|
|
||||||
|
|
||||||
.emptyCreateButton {
|
|
||||||
width: 200px;
|
|
||||||
height: 50px;
|
|
||||||
border-radius: 20px;
|
|
||||||
background-color: #2288ee;
|
|
||||||
color: #fff;
|
|
||||||
font-size: 20px;
|
|
||||||
font-weight: bold;
|
|
||||||
text-align: center;
|
|
||||||
line-height: 50px;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.emptyCreateButton:hover {
|
|
||||||
background-color: #1b77d2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.emptyInfoContainer {
|
|
||||||
width: 100%;
|
|
||||||
height: 60px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
color: #353535;
|
|
||||||
}
|
|
||||||
|
|
||||||
.emptyInfoText {
|
|
||||||
font-size: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.emptyInfoSubText {
|
|
||||||
font-size: 28px;
|
|
||||||
}
|
|
||||||
@@ -13,6 +13,10 @@
|
|||||||
/* box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.1); */
|
/* box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.1); */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .sidebarContainer {
|
||||||
|
background-color: #0a0a0b !important;
|
||||||
|
}
|
||||||
|
|
||||||
.langbotIconContainer {
|
.langbotIconContainer {
|
||||||
width: 200px;
|
width: 200px;
|
||||||
height: 70px;
|
height: 70px;
|
||||||
@@ -21,32 +25,49 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 0.8rem;
|
gap: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
.langbotIcon {
|
.langbotIcon {
|
||||||
width: 2.8rem;
|
width: 2.8rem;
|
||||||
height: 2.8rem;
|
height: 2.8rem;
|
||||||
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
|
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.langbotTextContainer {
|
:global(.dark) .langbotIcon {
|
||||||
display: flex;
|
box-shadow: 0 0 10px 0 rgba(255, 255, 255, 0.1);
|
||||||
flex-direction: column;
|
}
|
||||||
align-items: flex-start;
|
|
||||||
justify-content: flex-start;
|
|
||||||
gap: 0.1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.langbotText {
|
.langbotTextContainer {
|
||||||
font-size: 1.4rem;
|
display: flex;
|
||||||
font-weight: 500;
|
flex-direction: column;
|
||||||
}
|
align-items: flex-start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: 0.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
.langbotVersion {
|
.langbotText {
|
||||||
font-size: 0.8rem;
|
font-size: 1.4rem;
|
||||||
font-weight: 700;
|
font-weight: 500;
|
||||||
color: #6c6c6c;
|
color: #1a1a1a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .langbotText {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #f0f0f0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.langbotVersion {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #6c6c6c;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .langbotVersion {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #a0a0a0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebarTopContainer {
|
.sidebarTopContainer {
|
||||||
@@ -76,6 +97,7 @@
|
|||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
|
transition: all 0.2s ease;
|
||||||
/* background-color: aqua; */
|
/* background-color: aqua; */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,16 +107,40 @@
|
|||||||
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
|
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .sidebarSelected {
|
||||||
|
background-color: #2288ee;
|
||||||
|
color: white;
|
||||||
|
box-shadow: 0 0 10px 0 rgba(34, 136, 238, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
.sidebarUnselected {
|
.sidebarUnselected {
|
||||||
color: #6c6c6c;
|
color: #6c6c6c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .sidebarUnselected {
|
||||||
|
color: #a0a0a0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebarUnselected:hover {
|
||||||
|
background-color: rgba(34, 136, 238, 0.1);
|
||||||
|
color: #2288ee;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .sidebarUnselected:hover {
|
||||||
|
background-color: rgba(34, 136, 238, 0.2);
|
||||||
|
color: #66baff;
|
||||||
|
}
|
||||||
|
|
||||||
.sidebarChildIcon {
|
.sidebarChildIcon {
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
background-color: rgba(96, 149, 209, 0);
|
background-color: rgba(96, 149, 209, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebarChildName {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
.sidebarBottomContainer {
|
.sidebarBottomContainer {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -17,6 +17,10 @@
|
|||||||
color: #585858;
|
color: #585858;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .titleText {
|
||||||
|
color: #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
.subtitleText {
|
.subtitleText {
|
||||||
margin-left: 3.2rem;
|
margin-left: 3.2rem;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
@@ -25,8 +29,16 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .subtitleText {
|
||||||
|
color: #b0b0b0;
|
||||||
|
}
|
||||||
|
|
||||||
.helpLink {
|
.helpLink {
|
||||||
margin-left: 0.2rem;
|
margin-left: 0.2rem;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
color: #8b8b8b;
|
color: #8b8b8b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .helpLink {
|
||||||
|
color: #a0a0a0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ export default function KBDetailDialog({
|
|||||||
<SidebarProvider className="items-start w-full flex">
|
<SidebarProvider className="items-start w-full flex">
|
||||||
<Sidebar
|
<Sidebar
|
||||||
collapsible="none"
|
collapsible="none"
|
||||||
className="hidden md:flex h-[80vh] w-40 min-w-[120px] border-r bg-white"
|
className="hidden md:flex h-[80vh] w-40 min-w-[120px] border-r bg-white dark:bg-black"
|
||||||
>
|
>
|
||||||
<SidebarContent>
|
<SidebarContent>
|
||||||
<SidebarGroup>
|
<SidebarGroup>
|
||||||
|
|||||||
@@ -10,12 +10,22 @@
|
|||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .cardContainer {
|
||||||
|
background-color: #1f1f22;
|
||||||
|
box-shadow: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardContainer:hover {
|
.cardContainer:hover {
|
||||||
box-shadow: 0px 2px 8px 0 rgba(0, 0, 0, 0.1);
|
box-shadow: 0px 2px 8px 0 rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .cardContainer:hover {
|
||||||
|
box-shadow: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.basicInfoContainer {
|
.basicInfoContainer {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -35,6 +45,11 @@
|
|||||||
.basicInfoNameText {
|
.basicInfoNameText {
|
||||||
font-size: 1.4rem;
|
font-size: 1.4rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
color: #1a1a1a;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .basicInfoNameText {
|
||||||
|
color: #f0f0f0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.basicInfoDescriptionText {
|
.basicInfoDescriptionText {
|
||||||
@@ -48,6 +63,10 @@
|
|||||||
color: #b1b1b1;
|
color: #b1b1b1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .basicInfoDescriptionText {
|
||||||
|
color: #888888;
|
||||||
|
}
|
||||||
|
|
||||||
.basicInfoLastUpdatedTimeContainer {
|
.basicInfoLastUpdatedTimeContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@@ -58,11 +77,21 @@
|
|||||||
.basicInfoUpdateTimeIcon {
|
.basicInfoUpdateTimeIcon {
|
||||||
width: 1.2rem;
|
width: 1.2rem;
|
||||||
height: 1.2rem;
|
height: 1.2rem;
|
||||||
|
color: #626262;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .basicInfoUpdateTimeIcon {
|
||||||
|
color: #a0a0a0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.basicInfoUpdateTimeText {
|
.basicInfoUpdateTimeText {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
color: #626262;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .basicInfoUpdateTimeText {
|
||||||
|
color: #a0a0a0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.operationContainer {
|
.operationContainer {
|
||||||
@@ -86,12 +115,20 @@
|
|||||||
color: #ffcd27;
|
color: #ffcd27;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .operationDefaultBadgeIcon {
|
||||||
|
color: #fbbf24;
|
||||||
|
}
|
||||||
|
|
||||||
.operationDefaultBadgeText {
|
.operationDefaultBadgeText {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
color: #ffcd27;
|
color: #ffcd27;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .operationDefaultBadgeText {
|
||||||
|
color: #fbbf24;
|
||||||
|
}
|
||||||
|
|
||||||
.bigText {
|
.bigText {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|||||||
@@ -127,12 +127,12 @@ export default function FileUploadZone({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<p className="text-base font-medium text-gray-900">
|
<p className="text-base font-medium text-gray-900 dark:text-gray-100">
|
||||||
{isUploading
|
{isUploading
|
||||||
? t('knowledge.documentsTab.uploading')
|
? t('knowledge.documentsTab.uploading')
|
||||||
: t('knowledge.documentsTab.dragAndDrop')}
|
: t('knowledge.documentsTab.dragAndDrop')}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-xs text-gray-500 mt-1">
|
<p className="text-xs text-gray-500 mt-1 dark:text-gray-400">
|
||||||
{t('knowledge.documentsTab.supportedFormats')}
|
{t('knowledge.documentsTab.supportedFormats')}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -77,7 +77,10 @@ export const columns = (
|
|||||||
<MoreHorizontal className="h-4 w-4" />
|
<MoreHorizontal className="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent align="end">
|
<DropdownMenuContent
|
||||||
|
align="end"
|
||||||
|
className="bg-white dark:bg-[#2a2a2e]"
|
||||||
|
>
|
||||||
<DropdownMenuLabel>
|
<DropdownMenuLabel>
|
||||||
{t('knowledge.documentsTab.actions')}
|
{t('knowledge.documentsTab.actions')}
|
||||||
</DropdownMenuLabel>
|
</DropdownMenuLabel>
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ export default function KBForm({
|
|||||||
}}
|
}}
|
||||||
value={field.value}
|
value={field.value}
|
||||||
>
|
>
|
||||||
<SelectTrigger className="w-[180px]">
|
<SelectTrigger className="w-[180px] bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||||
<SelectValue
|
<SelectValue
|
||||||
placeholder={t('knowledge.selectEmbeddingModel')}
|
placeholder={t('knowledge.selectEmbeddingModel')}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -7,6 +7,19 @@
|
|||||||
background-color: #eee;
|
background-color: #eee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .homeLayoutContainer {
|
||||||
|
background-color: #0a0a0b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 侧边栏区域 */
|
||||||
|
.sidebar {
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .sidebar {
|
||||||
|
background-color: #0a0a0b;
|
||||||
|
}
|
||||||
|
|
||||||
/* 主内容区域 */
|
/* 主内容区域 */
|
||||||
.main {
|
.main {
|
||||||
background-color: #fafafa;
|
background-color: #fafafa;
|
||||||
@@ -23,6 +36,11 @@
|
|||||||
box-shadow: 0 0 6px 0 rgba(0, 0, 0, 0.05);
|
box-shadow: 0 0 6px 0 rgba(0, 0, 0, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .main {
|
||||||
|
background-color: #151518;
|
||||||
|
box-shadow: 0 0 6px 0 rgba(255, 255, 255, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
.mainContent {
|
.mainContent {
|
||||||
padding: 1.5rem;
|
padding: 1.5rem;
|
||||||
padding-left: 2rem;
|
padding-left: 2rem;
|
||||||
@@ -30,3 +48,7 @@
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
background-color: #fafafa;
|
background-color: #fafafa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .mainContent {
|
||||||
|
background-color: #151518;
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,12 +6,22 @@
|
|||||||
box-shadow: 0px 2px 2px 0 rgba(0, 0, 0, 0.2);
|
box-shadow: 0px 2px 2px 0 rgba(0, 0, 0, 0.2);
|
||||||
padding: 1.2rem;
|
padding: 1.2rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .cardContainer {
|
||||||
|
background-color: #1f1f22;
|
||||||
|
box-shadow: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardContainer:hover {
|
.cardContainer:hover {
|
||||||
box-shadow: 0px 2px 8px 0 rgba(0, 0, 0, 0.1);
|
box-shadow: 0px 2px 8px 0 rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .cardContainer:hover {
|
||||||
|
box-shadow: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.iconBasicInfoContainer {
|
.iconBasicInfoContainer {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -39,6 +49,11 @@
|
|||||||
.basicInfoText {
|
.basicInfoText {
|
||||||
font-size: 1.4rem;
|
font-size: 1.4rem;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
color: #1a1a1a;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .basicInfoText {
|
||||||
|
color: #f0f0f0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.providerContainer {
|
.providerContainer {
|
||||||
@@ -56,12 +71,20 @@
|
|||||||
color: #626262;
|
color: #626262;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .providerIcon {
|
||||||
|
color: #a0a0a0;
|
||||||
|
}
|
||||||
|
|
||||||
.providerLabel {
|
.providerLabel {
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #626262;
|
color: #626262;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .providerLabel {
|
||||||
|
color: #a0a0a0;
|
||||||
|
}
|
||||||
|
|
||||||
.baseURLContainer {
|
.baseURLContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@@ -77,6 +100,10 @@
|
|||||||
color: #626262;
|
color: #626262;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .baseURLIcon {
|
||||||
|
color: #a0a0a0;
|
||||||
|
}
|
||||||
|
|
||||||
.baseURLText {
|
.baseURLText {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -87,6 +114,10 @@
|
|||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .baseURLText {
|
||||||
|
color: #a0a0a0;
|
||||||
|
}
|
||||||
|
|
||||||
.bigText {
|
.bigText {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|||||||
@@ -404,7 +404,7 @@ export default function EmbeddingForm({
|
|||||||
}}
|
}}
|
||||||
value={field.value}
|
value={field.value}
|
||||||
>
|
>
|
||||||
<SelectTrigger className="w-[180px]">
|
<SelectTrigger className="w-[180px] bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||||
<SelectValue
|
<SelectValue
|
||||||
placeholder={t('models.selectModelProvider')}
|
placeholder={t('models.selectModelProvider')}
|
||||||
/>
|
/>
|
||||||
@@ -479,7 +479,7 @@ export default function EmbeddingForm({
|
|||||||
updateExtraArg(index, 'type', value)
|
updateExtraArg(index, 'type', value)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<SelectTrigger className="w-[120px]">
|
<SelectTrigger className="w-[120px] bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||||
<SelectValue placeholder={t('models.type')} />
|
<SelectValue placeholder={t('models.type')} />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
|
|||||||
@@ -6,12 +6,22 @@
|
|||||||
box-shadow: 0px 2px 2px 0 rgba(0, 0, 0, 0.2);
|
box-shadow: 0px 2px 2px 0 rgba(0, 0, 0, 0.2);
|
||||||
padding: 1.2rem;
|
padding: 1.2rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .cardContainer {
|
||||||
|
background-color: #1f1f22;
|
||||||
|
box-shadow: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardContainer:hover {
|
.cardContainer:hover {
|
||||||
box-shadow: 0px 2px 8px 0 rgba(0, 0, 0, 0.1);
|
box-shadow: 0px 2px 8px 0 rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .cardContainer:hover {
|
||||||
|
box-shadow: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.iconBasicInfoContainer {
|
.iconBasicInfoContainer {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -40,6 +50,11 @@
|
|||||||
.basicInfoText {
|
.basicInfoText {
|
||||||
font-size: 1.4rem;
|
font-size: 1.4rem;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
color: #1a1a1a;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .basicInfoText {
|
||||||
|
color: #f0f0f0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.providerContainer {
|
.providerContainer {
|
||||||
@@ -57,12 +72,20 @@
|
|||||||
color: #626262;
|
color: #626262;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .providerIcon {
|
||||||
|
color: #a0a0a0;
|
||||||
|
}
|
||||||
|
|
||||||
.providerLabel {
|
.providerLabel {
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #626262;
|
color: #626262;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .providerLabel {
|
||||||
|
color: #a0a0a0;
|
||||||
|
}
|
||||||
|
|
||||||
.baseURLContainer {
|
.baseURLContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@@ -78,6 +101,10 @@
|
|||||||
color: #626262;
|
color: #626262;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .baseURLIcon {
|
||||||
|
color: #a0a0a0;
|
||||||
|
}
|
||||||
|
|
||||||
.baseURLText {
|
.baseURLText {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -88,6 +115,10 @@
|
|||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .baseURLText {
|
||||||
|
color: #a0a0a0;
|
||||||
|
}
|
||||||
|
|
||||||
.abilitiesContainer {
|
.abilitiesContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@@ -108,18 +139,30 @@
|
|||||||
background-color: #66baff80;
|
background-color: #66baff80;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .abilityBadge {
|
||||||
|
background-color: rgba(34, 136, 238, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
.abilityIcon {
|
.abilityIcon {
|
||||||
width: 1rem;
|
width: 1rem;
|
||||||
height: 1rem;
|
height: 1rem;
|
||||||
color: #2288ee;
|
color: #2288ee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .abilityIcon {
|
||||||
|
color: #66baff;
|
||||||
|
}
|
||||||
|
|
||||||
.abilityLabel {
|
.abilityLabel {
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
color: #2288ee;
|
color: #2288ee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .abilityLabel {
|
||||||
|
color: #66baff;
|
||||||
|
}
|
||||||
|
|
||||||
.bigText {
|
.bigText {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|||||||
@@ -420,7 +420,7 @@ export default function LLMForm({
|
|||||||
}}
|
}}
|
||||||
value={field.value}
|
value={field.value}
|
||||||
>
|
>
|
||||||
<SelectTrigger className="w-[180px]">
|
<SelectTrigger className="w-[180px] bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||||
<SelectValue
|
<SelectValue
|
||||||
placeholder={t('models.selectModelProvider')}
|
placeholder={t('models.selectModelProvider')}
|
||||||
/>
|
/>
|
||||||
@@ -553,7 +553,7 @@ export default function LLMForm({
|
|||||||
updateExtraArg(index, 'type', value)
|
updateExtraArg(index, 'type', value)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<SelectTrigger className="w-[120px]">
|
<SelectTrigger className="w-[120px] bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||||
<SelectValue placeholder={t('models.type')} />
|
<SelectValue placeholder={t('models.type')} />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ export default function LLMConfigPage() {
|
|||||||
<Tabs defaultValue="llm" className="w-full">
|
<Tabs defaultValue="llm" className="w-full">
|
||||||
<div className="flex flex-row gap-0 mb-4">
|
<div className="flex flex-row gap-0 mb-4">
|
||||||
<div className="flex flex-row justify-between items-center px-[0.8rem]">
|
<div className="flex flex-row justify-between items-center px-[0.8rem]">
|
||||||
<TabsList className="shadow-md py-5 bg-[#f0f0f0]">
|
<TabsList className="shadow-md py-5 bg-[#f0f0f0] dark:bg-[#2a2a2e]">
|
||||||
<TabsTrigger value="llm" className="px-6 py-4 cursor-pointer">
|
<TabsTrigger value="llm" className="px-6 py-4 cursor-pointer">
|
||||||
{t('llm.llmModels')}
|
{t('llm.llmModels')}
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
@@ -206,12 +206,14 @@ export default function LLMConfigPage() {
|
|||||||
</div>
|
</div>
|
||||||
<TabsContent value="llm">
|
<TabsContent value="llm">
|
||||||
<div className="flex flex-row justify-between items-center px-[0.4rem] h-full">
|
<div className="flex flex-row justify-between items-center px-[0.4rem] h-full">
|
||||||
<p className="text-sm text-gray-500">{t('llm.description')}</p>
|
<p className="text-sm text-gray-500 dark:text-gray-400">
|
||||||
|
{t('llm.description')}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
<TabsContent value="embedding">
|
<TabsContent value="embedding">
|
||||||
<div className="flex flex-row justify-between items-center px-[0.4rem] h-full">
|
<div className="flex flex-row justify-between items-center px-[0.4rem] h-full">
|
||||||
<p className="text-sm text-gray-500">
|
<p className="text-sm text-gray-500 dark:text-gray-400">
|
||||||
{t('embedding.description')}
|
{t('embedding.description')}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ export default function PipelineDialog({
|
|||||||
<SidebarProvider className="items-start w-full flex h-full min-h-0">
|
<SidebarProvider className="items-start w-full flex h-full min-h-0">
|
||||||
<Sidebar
|
<Sidebar
|
||||||
collapsible="none"
|
collapsible="none"
|
||||||
className="hidden md:flex h-full min-h-0 w-40 border-r bg-white"
|
className="hidden md:flex h-full min-h-0 w-40 border-r bg-white dark:bg-black"
|
||||||
>
|
>
|
||||||
<SidebarContent>
|
<SidebarContent>
|
||||||
<SidebarGroup>
|
<SidebarGroup>
|
||||||
|
|||||||
@@ -15,13 +15,13 @@ export default function AtBadge({
|
|||||||
return (
|
return (
|
||||||
<Badge
|
<Badge
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
className="flex items-center gap-1 px-2 py-1 text-sm bg-blue-100 text-blue-600 hover:bg-blue-200"
|
className="flex items-center gap-1 px-2 py-1 text-sm bg-blue-100 dark:bg-blue-900/40 text-blue-600 dark:text-blue-300 hover:bg-blue-200 dark:hover:bg-blue-900/60"
|
||||||
>
|
>
|
||||||
@{targetName}
|
@{targetName}
|
||||||
{!readonly && onRemove && (
|
{!readonly && onRemove && (
|
||||||
<button
|
<button
|
||||||
onClick={onRemove}
|
onClick={onRemove}
|
||||||
className="ml-1 hover:text-blue-800 focus:outline-none"
|
className="ml-1 hover:text-blue-800 dark:hover:text-blue-200 focus:outline-none"
|
||||||
>
|
>
|
||||||
<X className="h-3 w-3" />
|
<X className="h-3 w-3" />
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -218,14 +218,14 @@ export default function DebugDialog({
|
|||||||
|
|
||||||
const renderContent = () => (
|
const renderContent = () => (
|
||||||
<div className="flex flex-1 h-full min-h-0">
|
<div className="flex flex-1 h-full min-h-0">
|
||||||
<div className="w-14 bg-white p-2 pl-0 flex-shrink-0 flex flex-col justify-start gap-2">
|
<div className="w-14 bg-white dark:bg-black p-2 pl-0 flex-shrink-0 flex flex-col justify-start gap-2">
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="icon"
|
size="icon"
|
||||||
className={`w-10 h-10 justify-center rounded-md transition-none ${
|
className={`w-10 h-10 justify-center rounded-md transition-none ${
|
||||||
sessionType === 'person'
|
sessionType === 'person'
|
||||||
? 'bg-[#2288ee] text-white hover:bg-[#2288ee] hover:text-white'
|
? 'bg-[#2288ee] text-white hover:bg-[#2288ee] hover:text-white'
|
||||||
: 'bg-white text-gray-800 hover:bg-gray-100'
|
: 'bg-white dark:bg-gray-800 text-gray-800 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700'
|
||||||
} border-0 shadow-none`}
|
} border-0 shadow-none`}
|
||||||
onClick={() => setSessionType('person')}
|
onClick={() => setSessionType('person')}
|
||||||
>
|
>
|
||||||
@@ -244,7 +244,7 @@ export default function DebugDialog({
|
|||||||
className={`w-10 h-10 justify-center rounded-md transition-none ${
|
className={`w-10 h-10 justify-center rounded-md transition-none ${
|
||||||
sessionType === 'group'
|
sessionType === 'group'
|
||||||
? 'bg-[#2288ee] text-white hover:bg-[#2288ee] hover:text-white'
|
? 'bg-[#2288ee] text-white hover:bg-[#2288ee] hover:text-white'
|
||||||
: 'bg-white text-gray-800 hover:bg-gray-100'
|
: 'bg-white dark:bg-gray-800 text-gray-800 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700'
|
||||||
} border-0 shadow-none`}
|
} border-0 shadow-none`}
|
||||||
onClick={() => setSessionType('group')}
|
onClick={() => setSessionType('group')}
|
||||||
>
|
>
|
||||||
@@ -261,7 +261,7 @@ export default function DebugDialog({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex-1 flex flex-col w-[10rem] h-full min-h-0">
|
<div className="flex-1 flex flex-col w-[10rem] h-full min-h-0">
|
||||||
<ScrollArea className="flex-1 p-6 overflow-y-auto min-h-0 bg-white">
|
<ScrollArea className="flex-1 p-6 overflow-y-auto min-h-0 bg-white dark:bg-black">
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
{messages.length === 0 ? (
|
{messages.length === 0 ? (
|
||||||
<div className="text-center text-muted-foreground py-12 text-lg">
|
<div className="text-center text-muted-foreground py-12 text-lg">
|
||||||
@@ -281,7 +281,7 @@ export default function DebugDialog({
|
|||||||
'max-w-md px-5 py-3 rounded-2xl',
|
'max-w-md px-5 py-3 rounded-2xl',
|
||||||
message.role === 'user'
|
message.role === 'user'
|
||||||
? 'bg-[#2288ee] text-white rounded-br-none'
|
? 'bg-[#2288ee] text-white rounded-br-none'
|
||||||
: 'bg-gray-100 text-gray-900 rounded-bl-none',
|
: 'bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-gray-100 rounded-bl-none',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{renderMessageContent(message)}
|
{renderMessageContent(message)}
|
||||||
@@ -290,7 +290,7 @@ export default function DebugDialog({
|
|||||||
'text-xs mt-2',
|
'text-xs mt-2',
|
||||||
message.role === 'user'
|
message.role === 'user'
|
||||||
? 'text-white/70'
|
? 'text-white/70'
|
||||||
: 'text-gray-500',
|
: 'text-gray-500 dark:text-gray-400',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{message.role === 'user'
|
{message.role === 'user'
|
||||||
@@ -305,7 +305,7 @@ export default function DebugDialog({
|
|||||||
</div>
|
</div>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
|
|
||||||
<div className="p-4 pb-0 bg-white flex gap-2">
|
<div className="p-4 pb-0 bg-white dark:bg-black flex gap-2">
|
||||||
<div className="flex-1 flex items-center gap-2">
|
<div className="flex-1 flex items-center gap-2">
|
||||||
{hasAt && (
|
{hasAt && (
|
||||||
<AtBadge targetName="webchatbot" onRemove={handleAtRemove} />
|
<AtBadge targetName="webchatbot" onRemove={handleAtRemove} />
|
||||||
@@ -322,23 +322,25 @@ export default function DebugDialog({
|
|||||||
? t('pipelines.debugDialog.privateChat')
|
? t('pipelines.debugDialog.privateChat')
|
||||||
: t('pipelines.debugDialog.groupChat'),
|
: t('pipelines.debugDialog.groupChat'),
|
||||||
})}
|
})}
|
||||||
className="flex-1 rounded-md px-3 py-2 border border-gray-300 focus:border-[#2288ee] transition-none text-base"
|
className="flex-1 rounded-md px-3 py-2 border border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-100 focus:border-[#2288ee] transition-none text-base"
|
||||||
/>
|
/>
|
||||||
{showAtPopover && (
|
{showAtPopover && (
|
||||||
<div
|
<div
|
||||||
ref={popoverRef}
|
ref={popoverRef}
|
||||||
className="absolute bottom-full left-0 mb-2 w-auto rounded-md border bg-white shadow-lg"
|
className="absolute bottom-full left-0 mb-2 w-auto rounded-md border bg-white dark:bg-gray-800 dark:border-gray-600 shadow-lg"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'flex items-center gap-2 px-4 py-1.5 rounded cursor-pointer',
|
'flex items-center gap-2 px-4 py-1.5 rounded cursor-pointer',
|
||||||
isHovering ? 'bg-gray-100' : 'bg-white',
|
isHovering
|
||||||
|
? 'bg-gray-100 dark:bg-gray-700'
|
||||||
|
: 'bg-white dark:bg-gray-800',
|
||||||
)}
|
)}
|
||||||
onClick={handleAtSelect}
|
onClick={handleAtSelect}
|
||||||
onMouseEnter={() => setIsHovering(true)}
|
onMouseEnter={() => setIsHovering(true)}
|
||||||
onMouseLeave={() => setIsHovering(false)}
|
onMouseLeave={() => setIsHovering(false)}
|
||||||
>
|
>
|
||||||
<span>
|
<span className="text-gray-800 dark:text-gray-200">
|
||||||
@webchatbot - {t('pipelines.debugDialog.atTips')}
|
@webchatbot - {t('pipelines.debugDialog.atTips')}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -369,7 +371,7 @@ export default function DebugDialog({
|
|||||||
|
|
||||||
// 原有的Dialog包装
|
// 原有的Dialog包装
|
||||||
return (
|
return (
|
||||||
<DialogContent className="!max-w-[70vw] max-w-6xl h-[70vh] p-6 flex flex-col rounded-2xl shadow-2xl bg-white">
|
<DialogContent className="!max-w-[70vw] max-w-6xl h-[70vh] p-6 flex flex-col rounded-2xl shadow-2xl bg-white dark:bg-black">
|
||||||
{renderContent()}
|
{renderContent()}
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -10,12 +10,22 @@
|
|||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .cardContainer {
|
||||||
|
background-color: #1f1f22;
|
||||||
|
box-shadow: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardContainer:hover {
|
.cardContainer:hover {
|
||||||
box-shadow: 0px 2px 8px 0 rgba(0, 0, 0, 0.1);
|
box-shadow: 0px 2px 8px 0 rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .cardContainer:hover {
|
||||||
|
box-shadow: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.basicInfoContainer {
|
.basicInfoContainer {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -35,6 +45,11 @@
|
|||||||
.basicInfoNameText {
|
.basicInfoNameText {
|
||||||
font-size: 1.4rem;
|
font-size: 1.4rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
color: #1a1a1a;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .basicInfoNameText {
|
||||||
|
color: #f0f0f0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.basicInfoDescriptionText {
|
.basicInfoDescriptionText {
|
||||||
@@ -48,6 +63,10 @@
|
|||||||
color: #b1b1b1;
|
color: #b1b1b1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .basicInfoDescriptionText {
|
||||||
|
color: #888888;
|
||||||
|
}
|
||||||
|
|
||||||
.basicInfoLastUpdatedTimeContainer {
|
.basicInfoLastUpdatedTimeContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@@ -58,11 +77,21 @@
|
|||||||
.basicInfoUpdateTimeIcon {
|
.basicInfoUpdateTimeIcon {
|
||||||
width: 1.2rem;
|
width: 1.2rem;
|
||||||
height: 1.2rem;
|
height: 1.2rem;
|
||||||
|
color: #626262;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .basicInfoUpdateTimeIcon {
|
||||||
|
color: #a0a0a0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.basicInfoUpdateTimeText {
|
.basicInfoUpdateTimeText {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
color: #626262;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .basicInfoUpdateTimeText {
|
||||||
|
color: #a0a0a0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.operationContainer {
|
.operationContainer {
|
||||||
@@ -86,12 +115,20 @@
|
|||||||
color: #ffcd27;
|
color: #ffcd27;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .operationDefaultBadgeIcon {
|
||||||
|
color: #fbbf24;
|
||||||
|
}
|
||||||
|
|
||||||
.operationDefaultBadgeText {
|
.operationDefaultBadgeText {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
color: #ffcd27;
|
color: #ffcd27;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .operationDefaultBadgeText {
|
||||||
|
color: #fbbf24;
|
||||||
|
}
|
||||||
|
|
||||||
.bigText {
|
.bigText {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|||||||
@@ -342,7 +342,7 @@ export default function PipelineFormComponent({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="!max-w-[70vw] max-w-6xl h-full p-0 flex flex-col bg-white">
|
<div className="!max-w-[70vw] max-w-6xl h-full p-0 flex flex-col bg-white dark:bg-black">
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form
|
<form
|
||||||
id="pipeline-form"
|
id="pipeline-form"
|
||||||
@@ -456,7 +456,7 @@ export default function PipelineFormComponent({
|
|||||||
</form>
|
</form>
|
||||||
{/* 按钮栏移到 Tabs 外部,始终固定底部 */}
|
{/* 按钮栏移到 Tabs 外部,始终固定底部 */}
|
||||||
{showButtons && (
|
{showButtons && (
|
||||||
<div className="flex justify-end gap-2 pt-4 border-t mb-0 bg-white sticky bottom-0 z-10">
|
<div className="flex justify-end gap-2 pt-4 border-t mb-0 bg-white dark:bg-black sticky bottom-0 z-10">
|
||||||
{isEditMode && !isDefaultPipeline && (
|
{isEditMode && !isDefaultPipeline && (
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
|
|||||||
@@ -125,17 +125,26 @@ export default function PluginConfigPage() {
|
|||||||
value={`${sortByValue},${sortOrderValue}`}
|
value={`${sortByValue},${sortOrderValue}`}
|
||||||
onValueChange={handleSortChange}
|
onValueChange={handleSortChange}
|
||||||
>
|
>
|
||||||
<SelectTrigger className="w-[180px] cursor-pointer bg-white dark:bg-gray-800">
|
<SelectTrigger className="w-[180px] cursor-pointer bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||||
<SelectValue placeholder={t('pipelines.sortBy')} />
|
<SelectValue placeholder={t('pipelines.sortBy')} />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent className="bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||||
<SelectItem value="created_at,DESC">
|
<SelectItem
|
||||||
|
value="created_at,DESC"
|
||||||
|
className="text-gray-900 dark:text-gray-100"
|
||||||
|
>
|
||||||
{t('pipelines.newestCreated')}
|
{t('pipelines.newestCreated')}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
<SelectItem value="updated_at,DESC">
|
<SelectItem
|
||||||
|
value="updated_at,DESC"
|
||||||
|
className="text-gray-900 dark:text-gray-100"
|
||||||
|
>
|
||||||
{t('pipelines.recentlyEdited')}
|
{t('pipelines.recentlyEdited')}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
<SelectItem value="updated_at,ASC">
|
<SelectItem
|
||||||
|
value="updated_at,ASC"
|
||||||
|
className="text-gray-900 dark:text-gray-100"
|
||||||
|
>
|
||||||
{t('pipelines.earliestEdited')}
|
{t('pipelines.earliestEdited')}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ export default function PluginConfigPage() {
|
|||||||
<div className={styles.pageContainer}>
|
<div className={styles.pageContainer}>
|
||||||
<Tabs defaultValue="installed" className="w-full">
|
<Tabs defaultValue="installed" className="w-full">
|
||||||
<div className="flex flex-row justify-between items-center px-[0.8rem]">
|
<div className="flex flex-row justify-between items-center px-[0.8rem]">
|
||||||
<TabsList className="shadow-md py-5 bg-[#f0f0f0]">
|
<TabsList className="shadow-md py-5 bg-[#f0f0f0] dark:bg-[#2a2a2e]">
|
||||||
<TabsTrigger value="installed" className="px-6 py-4 cursor-pointer">
|
<TabsTrigger value="installed" className="px-6 py-4 cursor-pointer">
|
||||||
{t('plugins.installed')}
|
{t('plugins.installed')}
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
@@ -134,7 +134,7 @@ export default function PluginConfigPage() {
|
|||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
<Dialog open={modalOpen} onOpenChange={setModalOpen}>
|
<Dialog open={modalOpen} onOpenChange={setModalOpen}>
|
||||||
<DialogContent className="w-[500px] p-6">
|
<DialogContent className="w-[500px] p-6 bg-white dark:bg-[#1a1a1e]">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle className="flex items-center gap-4">
|
<DialogTitle className="flex items-center gap-4">
|
||||||
<GithubIcon className="size-6" />
|
<GithubIcon className="size-6" />
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export default function PluginCardComponent({
|
|||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="w-[100%] h-[10rem] bg-white rounded-[10px] shadow-[0px_2px_2px_0_rgba(0,0,0,0.2)] p-[1.2rem] cursor-pointer"
|
className="w-[100%] h-[10rem] bg-white dark:bg-[#1f1f22] rounded-[10px] shadow-[0px_2px_2px_0_rgba(0,0,0,0.2)] dark:shadow-[0] p-[1.2rem] cursor-pointer transition-all duration-200 hover:shadow-[0px_2px_8px_0_rgba(0,0,0,0.1)] dark:hover:shadow-[0]"
|
||||||
onClick={onCardClick}
|
onClick={onCardClick}
|
||||||
>
|
>
|
||||||
<div className="w-full h-full flex flex-row items-start justify-start gap-[1.2rem]">
|
<div className="w-full h-full flex flex-row items-start justify-start gap-[1.2rem]">
|
||||||
@@ -50,18 +50,20 @@ export default function PluginCardComponent({
|
|||||||
<div className="w-full h-full flex flex-col items-start justify-between gap-[0.6rem]">
|
<div className="w-full h-full flex flex-col items-start justify-between gap-[0.6rem]">
|
||||||
<div className="flex flex-col items-start justify-start">
|
<div className="flex flex-col items-start justify-start">
|
||||||
<div className="flex flex-col items-start justify-start">
|
<div className="flex flex-col items-start justify-start">
|
||||||
<div className="text-[0.7rem] text-[#666]">
|
<div className="text-[0.7rem] text-[#666] dark:text-[#a0a0a0]">
|
||||||
{cardVO.author} /{' '}
|
{cardVO.author} /{' '}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-row items-center justify-start gap-[0.4rem]">
|
<div className="flex flex-row items-center justify-start gap-[0.4rem]">
|
||||||
<div className="text-[1.2rem] text-black">{cardVO.name}</div>
|
<div className="text-[1.2rem] text-black dark:text-[#f0f0f0]">
|
||||||
|
{cardVO.name}
|
||||||
|
</div>
|
||||||
<Badge variant="outline" className="text-[0.7rem]">
|
<Badge variant="outline" className="text-[0.7rem]">
|
||||||
v{cardVO.version}
|
v{cardVO.version}
|
||||||
</Badge>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="text-[0.8rem] text-[#666] line-clamp-2">
|
<div className="text-[0.8rem] text-[#666] dark:text-[#888888] line-clamp-2">
|
||||||
{cardVO.description}
|
{cardVO.description}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -69,14 +71,14 @@ export default function PluginCardComponent({
|
|||||||
<div className="w-full flex flex-row items-start justify-start gap-[0.6rem]">
|
<div className="w-full flex flex-row items-start justify-start gap-[0.6rem]">
|
||||||
<div className="flex h-full flex-row items-center justify-center gap-[0.4rem]">
|
<div className="flex h-full flex-row items-center justify-center gap-[0.4rem]">
|
||||||
<svg
|
<svg
|
||||||
className="w-[1.2rem] h-[1.2rem] text-black"
|
className="w-[1.2rem] h-[1.2rem] text-black dark:text-[#f0f0f0]"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
>
|
>
|
||||||
<path d="M24 12L18.3431 17.6569L16.9289 16.2426L21.1716 12L16.9289 7.75736L18.3431 6.34315L24 12ZM2.82843 12L7.07107 16.2426L5.65685 17.6569L0 12L5.65685 6.34315L7.07107 7.75736L2.82843 12ZM9.78845 21H7.66009L14.2116 3H16.3399L9.78845 21Z"></path>
|
<path d="M24 12L18.3431 17.6569L16.9289 16.2426L21.1716 12L16.9289 7.75736L18.3431 6.34315L24 12ZM2.82843 12L7.07107 16.2426L5.65685 17.6569L0 12L5.65685 6.34315L7.07107 7.75736L2.82843 12ZM9.78845 21H7.66009L14.2116 3H16.3399L9.78845 21Z"></path>
|
||||||
</svg>
|
</svg>
|
||||||
<div className="text-base text-black font-medium">
|
<div className="text-base text-black dark:text-[#f0f0f0] font-medium">
|
||||||
{t('plugins.eventCount', {
|
{t('plugins.eventCount', {
|
||||||
count: Object.keys(cardVO.event_handlers).length,
|
count: Object.keys(cardVO.event_handlers).length,
|
||||||
})}
|
})}
|
||||||
@@ -85,14 +87,14 @@ export default function PluginCardComponent({
|
|||||||
|
|
||||||
<div className="flex h-full flex-row items-center justify-center gap-[0.4rem]">
|
<div className="flex h-full flex-row items-center justify-center gap-[0.4rem]">
|
||||||
<svg
|
<svg
|
||||||
className="w-[1.2rem] h-[1.2rem] text-black"
|
className="w-[1.2rem] h-[1.2rem] text-black dark:text-[#f0f0f0]"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
>
|
>
|
||||||
<path d="M5.32943 3.27158C6.56252 2.8332 7.9923 3.10749 8.97927 4.09446C10.1002 5.21537 10.3019 6.90741 9.5843 8.23385L20.293 18.9437L18.8788 20.3579L8.16982 9.64875C6.84325 10.3669 5.15069 10.1654 4.02952 9.04421C3.04227 8.05696 2.7681 6.62665 3.20701 5.39332L5.44373 7.63C6.02952 8.21578 6.97927 8.21578 7.56505 7.63C8.15084 7.04421 8.15084 6.09446 7.56505 5.50868L5.32943 3.27158ZM15.6968 5.15512L18.8788 3.38736L20.293 4.80157L18.5252 7.98355L16.7574 8.3371L14.6361 10.4584L13.2219 9.04421L15.3432 6.92289L15.6968 5.15512ZM8.97927 13.2868L10.3935 14.7011L5.09018 20.0044C4.69966 20.3949 4.06649 20.3949 3.67597 20.0044C3.31334 19.6417 3.28744 19.0699 3.59826 18.6774L3.67597 18.5902L8.97927 13.2868Z"></path>
|
<path d="M5.32943 3.27158C6.56252 2.8332 7.9923 3.10749 8.97927 4.09446C10.1002 5.21537 10.3019 6.90741 9.5843 8.23385L20.293 18.9437L18.8788 20.3579L8.16982 9.64875C6.84325 10.3669 5.15069 10.1654 4.02952 9.04421C3.04227 8.05696 2.7681 6.62665 3.20701 5.39332L5.44373 7.63C6.02952 8.21578 6.97927 8.21578 7.56505 7.63C8.15084 7.04421 8.15084 6.09446 7.56505 5.50868L5.32943 3.27158ZM15.6968 5.15512L18.8788 3.38736L20.293 4.80157L18.5252 7.98355L16.7574 8.3371L14.6361 10.4584L13.2219 9.04421L15.3432 6.92289L15.6968 5.15512ZM8.97927 13.2868L10.3935 14.7011L5.09018 20.0044C4.69966 20.3949 4.06649 20.3949 3.67597 20.0044C3.31334 19.6417 3.28744 19.0699 3.59826 18.6774L3.67597 18.5902L8.97927 13.2868Z"></path>
|
||||||
</svg>
|
</svg>
|
||||||
<div className="text-base text-black font-medium">
|
<div className="text-base text-black dark:text-[#f0f0f0] font-medium">
|
||||||
{t('plugins.toolCount', { count: cardVO.tools.length })}
|
{t('plugins.toolCount', { count: cardVO.tools.length })}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -115,7 +117,9 @@ export default function PluginCardComponent({
|
|||||||
<div className="flex items-center justify-center gap-[0.4rem]">
|
<div className="flex items-center justify-center gap-[0.4rem]">
|
||||||
<svg
|
<svg
|
||||||
className={`w-[1.4rem] h-[1.4rem] cursor-pointer ${
|
className={`w-[1.4rem] h-[1.4rem] cursor-pointer ${
|
||||||
cardVO.repository ? 'text-black' : 'text-gray-400'
|
cardVO.repository
|
||||||
|
? 'text-black dark:text-[#f0f0f0]'
|
||||||
|
: 'text-gray-400 dark:text-gray-600'
|
||||||
}`}
|
}`}
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
|
|||||||
@@ -141,15 +141,26 @@ export default function PluginMarketComponent({
|
|||||||
value={`${sortByValue},${sortOrderValue}`}
|
value={`${sortByValue},${sortOrderValue}`}
|
||||||
onValueChange={handleSortChange}
|
onValueChange={handleSortChange}
|
||||||
>
|
>
|
||||||
<SelectTrigger className="w-[180px] ml-2 cursor-pointer">
|
<SelectTrigger className="w-[180px] ml-2 cursor-pointer bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||||
<SelectValue placeholder={t('plugins.sortBy')} />
|
<SelectValue placeholder={t('plugins.sortBy')} />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent className="bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||||
<SelectItem value="stars,DESC">{t('plugins.mostStars')}</SelectItem>
|
<SelectItem
|
||||||
<SelectItem value="created_at,DESC">
|
value="stars,DESC"
|
||||||
|
className="text-gray-900 dark:text-gray-100"
|
||||||
|
>
|
||||||
|
{t('plugins.mostStars')}
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem
|
||||||
|
value="created_at,DESC"
|
||||||
|
className="text-gray-900 dark:text-gray-100"
|
||||||
|
>
|
||||||
{t('plugins.recentlyAdded')}
|
{t('plugins.recentlyAdded')}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
<SelectItem value="pushed_at,DESC">
|
<SelectItem
|
||||||
|
value="pushed_at,DESC"
|
||||||
|
className="text-gray-900 dark:text-gray-100"
|
||||||
|
>
|
||||||
{t('plugins.recentlyUpdated')}
|
{t('plugins.recentlyUpdated')}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
@@ -198,7 +209,7 @@ export default function PluginMarketComponent({
|
|||||||
isActive={pageNum === nowPage}
|
isActive={pageNum === nowPage}
|
||||||
onClick={() => handlePageChange(pageNum)}
|
onClick={() => handlePageChange(pageNum)}
|
||||||
>
|
>
|
||||||
<span className="text-black select-none">
|
<span className="text-black dark:text-white select-none">
|
||||||
{pageNum}
|
{pageNum}
|
||||||
</span>
|
</span>
|
||||||
</PaginationLink>
|
</PaginationLink>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export default function PluginMarketCardComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-[100%] h-[10rem] bg-white rounded-[10px] shadow-[0px_2px_2px_0_rgba(0,0,0,0.2)] p-[1.2rem]">
|
<div className="w-[100%] h-[10rem] bg-white dark:bg-[#1f1f22] rounded-[10px] shadow-[0px_2px_2px_0_rgba(0,0,0,0.2)] dark:shadow-[0] p-[1.2rem] transition-all duration-200 hover:shadow-[0px_2px_8px_0_rgba(0,0,0,0.1)] dark:hover:shadow-[0]">
|
||||||
<div className="w-full h-full flex flex-row items-start justify-start gap-[1.2rem]">
|
<div className="w-full h-full flex flex-row items-start justify-start gap-[1.2rem]">
|
||||||
<svg
|
<svg
|
||||||
className="w-16 h-16 text-[#2288ee]"
|
className="w-16 h-16 text-[#2288ee]"
|
||||||
@@ -30,15 +30,17 @@ export default function PluginMarketCardComponent({
|
|||||||
<div className="w-full h-full flex flex-col items-start justify-between gap-[0.6rem]">
|
<div className="w-full h-full flex flex-col items-start justify-between gap-[0.6rem]">
|
||||||
<div className="flex flex-col items-start justify-start">
|
<div className="flex flex-col items-start justify-start">
|
||||||
<div className="flex flex-col items-start justify-start">
|
<div className="flex flex-col items-start justify-start">
|
||||||
<div className="text-[0.7rem] text-[#666]">
|
<div className="text-[0.7rem] text-[#666] dark:text-[#a0a0a0]">
|
||||||
{cardVO.author} /{' '}
|
{cardVO.author} /{' '}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-row items-center justify-start gap-[0.4rem]">
|
<div className="flex flex-row items-center justify-start gap-[0.4rem]">
|
||||||
<div className="text-[1.2rem] text-black">{cardVO.name}</div>
|
<div className="text-[1.2rem] text-black dark:text-[#f0f0f0]">
|
||||||
|
{cardVO.name}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="text-[0.8rem] text-[#666] line-clamp-2">
|
<div className="text-[0.8rem] text-[#666] dark:text-[#888888] line-clamp-2">
|
||||||
{cardVO.description}
|
{cardVO.description}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -46,21 +48,21 @@ export default function PluginMarketCardComponent({
|
|||||||
<div className="w-full flex flex-row items-start justify-between gap-[0.6rem]">
|
<div className="w-full flex flex-row items-start justify-between gap-[0.6rem]">
|
||||||
<div className="flex h-full flex-row items-center justify-center gap-[0.4rem]">
|
<div className="flex h-full flex-row items-center justify-center gap-[0.4rem]">
|
||||||
<svg
|
<svg
|
||||||
className="w-[1.2rem] h-[1.2rem] text-[#ffcd27]"
|
className="w-[1.2rem] h-[1.2rem] text-[#ffcd27] dark:text-[#fbbf24]"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
>
|
>
|
||||||
<path d="M12.0006 18.26L4.94715 22.2082L6.52248 14.2799L0.587891 8.7918L8.61493 7.84006L12.0006 0.5L15.3862 7.84006L23.4132 8.7918L17.4787 14.2799L19.054 22.2082L12.0006 18.26Z"></path>
|
<path d="M12.0006 18.26L4.94715 22.2082L6.52248 14.2799L0.587891 8.7918L8.61493 7.84006L12.0006 0.5L15.3862 7.84006L23.4132 8.7918L17.4787 14.2799L19.054 22.2082L12.0006 18.26Z"></path>
|
||||||
</svg>
|
</svg>
|
||||||
<div className="text-base text-[#ffcd27] font-medium">
|
<div className="text-base text-[#ffcd27] dark:text-[#fbbf24] font-medium">
|
||||||
{t('plugins.starCount', { count: cardVO.starCount })}
|
{t('plugins.starCount', { count: cardVO.starCount })}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex h-full flex-row items-center justify-center gap-[0.4rem]">
|
<div className="flex h-full flex-row items-center justify-center gap-[0.4rem]">
|
||||||
<svg
|
<svg
|
||||||
className="w-[1.4rem] h-[1.4rem] text-black cursor-pointer"
|
className="w-[1.4rem] h-[1.4rem] text-black dark:text-[#f0f0f0] cursor-pointer"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
|
|||||||
@@ -7,13 +7,27 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-evenly;
|
justify-content: space-evenly;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.dark) .cardContainer {
|
||||||
|
background-color: #1f1f22;
|
||||||
|
box-shadow: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardContainer:hover {
|
.cardContainer:hover {
|
||||||
box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.05);
|
box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .cardContainer:hover {
|
||||||
|
box-shadow: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.createCardContainer {
|
.createCardContainer {
|
||||||
font-size: 90px;
|
font-size: 90px;
|
||||||
color: #acacac;
|
color: #acacac;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.dark) .createCardContainer {
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import 'react-photo-view/dist/react-photo-view.css';
|
|||||||
import type { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
import { Toaster } from '@/components/ui/sonner';
|
import { Toaster } from '@/components/ui/sonner';
|
||||||
import I18nProvider from '@/i18n/I18nProvider';
|
import I18nProvider from '@/i18n/I18nProvider';
|
||||||
|
import { ThemeProvider } from '@/components/providers/theme-provider';
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: 'LangBot',
|
title: 'LangBot',
|
||||||
@@ -15,12 +16,14 @@ export default function RootLayout({
|
|||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}>) {
|
||||||
return (
|
return (
|
||||||
<html>
|
<html lang="zh" suppressHydrationWarning>
|
||||||
<body className={``}>
|
<body className={``}>
|
||||||
<I18nProvider>
|
<ThemeProvider>
|
||||||
{children}
|
<I18nProvider>
|
||||||
<Toaster />
|
{children}
|
||||||
</I18nProvider>
|
<Toaster />
|
||||||
|
</I18nProvider>
|
||||||
|
</ThemeProvider>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import { toast } from 'sonner';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import i18n from '@/i18n';
|
import i18n from '@/i18n';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
import { ThemeToggle } from '@/components/ui/theme-toggle';
|
||||||
|
|
||||||
const formSchema = (t: (key: string) => string) =>
|
const formSchema = (t: (key: string) => string) =>
|
||||||
z.object({
|
z.object({
|
||||||
@@ -155,10 +156,11 @@ export default function Login() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen flex items-center justify-center bg-gray-50">
|
<div className="min-h-screen flex items-center justify-center bg-gray-50 dark:dark:bg-neutral-900">
|
||||||
<Card className="w-[375px]">
|
<Card className="w-[375px] shadow-lg dark:shadow-white/10">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<div className="flex justify-end mb-6">
|
<div className="flex justify-between items-center mb-6">
|
||||||
|
<ThemeToggle />
|
||||||
<Select
|
<Select
|
||||||
value={currentLanguage}
|
value={currentLanguage}
|
||||||
onValueChange={handleLanguageChange}
|
onValueChange={handleLanguageChange}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import langbotIcon from '@/app/assets/langbot-logo.webp';
|
|||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import i18n from '@/i18n';
|
import i18n from '@/i18n';
|
||||||
|
import { ThemeToggle } from '@/components/ui/theme-toggle';
|
||||||
|
|
||||||
const formSchema = (t: (key: string) => string) =>
|
const formSchema = (t: (key: string) => string) =>
|
||||||
z.object({
|
z.object({
|
||||||
@@ -139,10 +140,11 @@ export default function Register() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen flex items-center justify-center bg-gray-50">
|
<div className="min-h-screen flex items-center justify-center bg-gray-50 dark:bg-neutral-900">
|
||||||
<Card className="w-[375px]">
|
<Card className="w-[375px] shadow-lg dark:shadow-white/10">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<div className="flex justify-end mb-6">
|
<div className="flex justify-between items-center mb-6">
|
||||||
|
<ThemeToggle />
|
||||||
<Select
|
<Select
|
||||||
value={currentLanguage}
|
value={currentLanguage}
|
||||||
onValueChange={handleLanguageChange}
|
onValueChange={handleLanguageChange}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import { Mail, Lock, ArrowLeft } from 'lucide-react';
|
|||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
import { ThemeToggle } from '@/components/ui/theme-toggle';
|
||||||
|
|
||||||
const REGEXP_ONLY_DIGITS_AND_CHARS = /^[0-9a-zA-Z]+$/;
|
const REGEXP_ONLY_DIGITS_AND_CHARS = /^[0-9a-zA-Z]+$/;
|
||||||
|
|
||||||
@@ -84,17 +85,18 @@ export default function ResetPassword() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen flex items-center justify-center bg-gray-50">
|
<div className="min-h-screen flex items-center justify-center bg-gray-50 dark:bg-neutral-900">
|
||||||
<Card className="w-[375px]">
|
<Card className="w-[375px] shadow-lg dark:shadow-white/10">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<div className="flex justify-between items-center mb-6">
|
<div className="flex justify-between items-center mb-6">
|
||||||
<Link
|
<Link
|
||||||
href="/login"
|
href="/login"
|
||||||
className="flex items-center text-sm text-gray-600 hover:text-gray-900 transition-colors"
|
className="flex items-center text-sm text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-100 transition-colors"
|
||||||
>
|
>
|
||||||
<ArrowLeft className="h-4 w-4 mr-1" />
|
<ArrowLeft className="h-4 w-4 mr-1" />
|
||||||
{t('resetPassword.backToLogin')}
|
{t('resetPassword.backToLogin')}
|
||||||
</Link>
|
</Link>
|
||||||
|
<ThemeToggle />
|
||||||
</div>
|
</div>
|
||||||
<CardTitle className="text-2xl text-center">
|
<CardTitle className="text-2xl text-center">
|
||||||
{t('resetPassword.title')}
|
{t('resetPassword.title')}
|
||||||
|
|||||||
18
web/src/components/providers/theme-provider.tsx
Normal file
18
web/src/components/providers/theme-provider.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { ThemeProvider as NextThemesProvider } from 'next-themes';
|
||||||
|
import { type ThemeProviderProps } from 'next-themes';
|
||||||
|
|
||||||
|
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
|
||||||
|
return (
|
||||||
|
<NextThemesProvider
|
||||||
|
attribute="class"
|
||||||
|
defaultTheme="system"
|
||||||
|
enableSystem
|
||||||
|
disableTransitionOnChange
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</NextThemesProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -76,7 +76,7 @@ function PaginationPrevious({
|
|||||||
className={cn('gap-1 px-2.5 sm:pl-2.5', className)}
|
className={cn('gap-1 px-2.5 sm:pl-2.5', className)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<ChevronLeftIcon className="text-black" />
|
<ChevronLeftIcon className="text-black dark:text-white" />
|
||||||
<span className="hidden sm:block"></span>
|
<span className="hidden sm:block"></span>
|
||||||
</PaginationLink>
|
</PaginationLink>
|
||||||
);
|
);
|
||||||
@@ -94,7 +94,7 @@ function PaginationNext({
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<span className="hidden sm:block"></span>
|
<span className="hidden sm:block"></span>
|
||||||
<ChevronRightIcon className="text-black" />
|
<ChevronRightIcon className="text-black dark:text-white" />
|
||||||
</PaginationLink>
|
</PaginationLink>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
23
web/src/components/ui/theme-toggle.tsx
Normal file
23
web/src/components/ui/theme-toggle.tsx
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import * as React from 'react';
|
||||||
|
import { Moon, Sun } from 'lucide-react';
|
||||||
|
import { useTheme } from 'next-themes';
|
||||||
|
|
||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
|
||||||
|
export function ThemeToggle() {
|
||||||
|
const { theme, setTheme } = useTheme();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="icon"
|
||||||
|
onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}
|
||||||
|
className="h-9 w-9"
|
||||||
|
>
|
||||||
|
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
|
||||||
|
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user