feat(ui): 宋对ui和输入框placeholder更改
This commit is contained in:
parent
ac01d08eb5
commit
c4fe34ed23
|
|
@ -472,8 +472,22 @@ export default function ChatPage() {
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="relative flex size-full justify-center px-[20px]">
|
<div className="relative flex size-full justify-center px-[20px]">
|
||||||
<div className="absolute top-2 right-2 z-30">
|
<div className="z-30">
|
||||||
<Button
|
|
||||||
|
</div>
|
||||||
|
{thread.values.artifacts?.length === 0 ? (
|
||||||
|
<ConversationEmptyState
|
||||||
|
icon={<FilesIcon />}
|
||||||
|
title="No artifact selected"
|
||||||
|
description="Select an artifact to view its details"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div className="flex size-full max-w-(--container-width-sm) flex-col justify-center">
|
||||||
|
<header className="shrink-0 flex justify-between items-center border-b ">
|
||||||
|
<h2 className="text-[14px] h-[58px] leading-[58px] font-bold text-[#333333]">
|
||||||
|
<span>{t.common.artifacts}</span>
|
||||||
|
</h2>
|
||||||
|
<Button
|
||||||
data-testid="artifacts-panel-close"
|
data-testid="artifacts-panel-close"
|
||||||
size="icon-sm"
|
size="icon-sm"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
|
|
@ -483,23 +497,10 @@ export default function ChatPage() {
|
||||||
>
|
>
|
||||||
<XIcon />
|
<XIcon />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
|
||||||
{thread.values.artifacts?.length === 0 ? (
|
|
||||||
<ConversationEmptyState
|
|
||||||
icon={<FilesIcon />}
|
|
||||||
title="No artifact selected"
|
|
||||||
description="Select an artifact to view its details"
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<div className="flex size-full max-w-(--container-width-sm) flex-col justify-center p-4">
|
|
||||||
<header className="shrink-0">
|
|
||||||
<h2 className="text-[14px] font-bold text-[#333333]">
|
|
||||||
{t.common.artifacts}
|
|
||||||
</h2>
|
|
||||||
</header>
|
</header>
|
||||||
<main className="min-h-0 grow overflow-auto">
|
<main className="min-h-0 grow overflow-auto">
|
||||||
<ArtifactFileList
|
<ArtifactFileList
|
||||||
className="mb-[207px] max-w-(--container-width-sm) p-4 pt-12"
|
className="mb-[207px] max-w-(--container-width-sm) pt-[20px]"
|
||||||
files={thread.values.artifacts ?? []}
|
files={thread.values.artifacts ?? []}
|
||||||
threadId={threadId}
|
threadId={threadId}
|
||||||
/>
|
/>
|
||||||
|
|
@ -656,7 +657,7 @@ export default function ChatPage() {
|
||||||
</DevDialog>
|
</DevDialog>
|
||||||
|
|
||||||
{/* MARK: 开发测试:iframe 通信功能测试面板 */}
|
{/* MARK: 开发测试:iframe 通信功能测试面板 */}
|
||||||
{process.env.NODE_ENV !== "production" && <IframeTestPanel />}
|
{/* {process.env.NODE_ENV !== "production" && <IframeTestPanel />} */}
|
||||||
</div>
|
</div>
|
||||||
</ThreadContext.Provider>
|
</ThreadContext.Provider>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -207,7 +207,7 @@ export const ChainOfThoughtContent = memo(
|
||||||
<Collapsible open={isOpen}>
|
<Collapsible open={isOpen}>
|
||||||
<CollapsibleContent
|
<CollapsibleContent
|
||||||
className={cn(
|
className={cn(
|
||||||
"mt-2 space-y-3",
|
"mt-4 space-y-3",
|
||||||
"data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-popover-foreground data-[state=closed]:animate-out data-[state=open]:animate-in outline-none",
|
"data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-popover-foreground data-[state=closed]:animate-out data-[state=open]:animate-in outline-none",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -22,15 +22,21 @@ import { Streamdown } from "streamdown";
|
||||||
|
|
||||||
export type MessageProps = HTMLAttributes<HTMLDivElement> & {
|
export type MessageProps = HTMLAttributes<HTMLDivElement> & {
|
||||||
from: UIMessage["role"];
|
from: UIMessage["role"];
|
||||||
|
isFirstInSession?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Message = ({ className, from, ...props }: MessageProps) => (
|
export const Message = ({
|
||||||
|
className,
|
||||||
|
from,
|
||||||
|
isFirstInSession = false,
|
||||||
|
...props
|
||||||
|
}: MessageProps) => (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"group flex w-full flex-col gap-2",
|
"group flex w-full flex-col gap-2",
|
||||||
from === "user"
|
from === "user"
|
||||||
? "is-user ml-auto justify-end"
|
? cn("is-user ml-auto justify-end", !isFirstInSession && "mt-6")
|
||||||
: "is-assistant bg-white p-[20px]",
|
: "is-assistant bg-white rounded-[10px] p-4",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ export const Suggestion = ({
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
className={cn(
|
className={cn(
|
||||||
"cursor-pointer rounded-full px-[20px] py-[15px] text-xs font-normal",
|
"cursor-pointer rounded-full px-[20px] py-[15px] text-[14px] font-normal",
|
||||||
"border-none bg-[#F9F8FA] text-[#666666]",
|
"border-none bg-[#F9F8FA] text-[#666666]",
|
||||||
"hover:bg-[#EAE9EB] hover:text-[#150033]",
|
"hover:bg-[#EAE9EB] hover:text-[#150033]",
|
||||||
className,
|
className,
|
||||||
|
|
|
||||||
|
|
@ -80,12 +80,12 @@ export function ArtifactFileList({
|
||||||
{files.map((file) => (
|
{files.map((file) => (
|
||||||
<Card
|
<Card
|
||||||
key={file}
|
key={file}
|
||||||
className="relative cursor-pointer p-3"
|
className="relative cursor-pointer p-4"
|
||||||
data-testid="artifact-file-card"
|
data-testid="artifact-file-card"
|
||||||
onClick={() => handleClick(file)}
|
onClick={() => handleClick(file)}
|
||||||
>
|
>
|
||||||
<CardHeader className="pr-2 pl-1">
|
<CardHeader className="pr-2 pl-1">
|
||||||
<CardTitle className="relative overflow-hidden pl-8">
|
<CardTitle className="relative overflow-hidden pl-10">
|
||||||
<div
|
<div
|
||||||
className="text-sm font-normal text-ellipsis whitespace-nowrap"
|
className="text-sm font-normal text-ellipsis whitespace-nowrap"
|
||||||
title={getFileName(file)}
|
title={getFileName(file)}
|
||||||
|
|
@ -93,10 +93,10 @@ export function ArtifactFileList({
|
||||||
{truncateMiddle(getFileName(file), 50)}
|
{truncateMiddle(getFileName(file), 50)}
|
||||||
</div>
|
</div>
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<div className="absolute top-5 left-3">
|
<div className="absolute top-5 left-4">
|
||||||
{getFileIcon(file, "size-6 stroke-[1.5px] stroke-[#333333]")}
|
{getFileIcon(file, "size-9 stroke-[1px] stroke-[#333333]")}
|
||||||
</div>
|
</div>
|
||||||
<CardDescription className="pl-8 text-xs">
|
<CardDescription className="pl-10 text-xs">
|
||||||
{getFileExtensionDisplayName(file)} file
|
{getFileExtensionDisplayName(file)} file
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
<CardAction>
|
<CardAction>
|
||||||
|
|
@ -124,7 +124,10 @@ export function ArtifactFileList({
|
||||||
target="_blank"
|
target="_blank"
|
||||||
onClick={(e) => e.stopPropagation()}
|
onClick={(e) => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
<Button variant="ghost">
|
<Button variant="ghost"
|
||||||
|
className="h-full! text-[var(--muted-foreground)]! hover:bg-transparent! hover:text-[#333333]!"
|
||||||
|
|
||||||
|
>
|
||||||
<DownloadIcon className="size-4" />
|
<DownloadIcon className="size-4" />
|
||||||
{t.common.download}
|
{t.common.download}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
||||||
|
|
@ -741,7 +741,7 @@ export function InputBox({
|
||||||
"pointer-events-none invisible h-[0px] translate-y-2 p-[0px] opacity-0",
|
"pointer-events-none invisible h-[0px] translate-y-2 p-[0px] opacity-0",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<PromptInputTools className="min-w-0 flex-1">
|
<PromptInputTools className="min-w-0 flex-1 gap-[20px]">
|
||||||
{/* TODO: Add more connectors here
|
{/* TODO: Add more connectors here
|
||||||
<PromptInputActionMenu>
|
<PromptInputActionMenu>
|
||||||
<PromptInputActionMenuTrigger className="px-2!" />
|
<PromptInputActionMenuTrigger className="px-2!" />
|
||||||
|
|
|
||||||
|
|
@ -125,7 +125,8 @@ export function MessageGroup({
|
||||||
{aboveLastToolCallSteps.length > 0 && (
|
{aboveLastToolCallSteps.length > 0 && (
|
||||||
<Button
|
<Button
|
||||||
key="above"
|
key="above"
|
||||||
className="w-full items-start justify-start text-left"
|
// 等宋
|
||||||
|
className="w-full items-start justify-start text-left h-auto! py-4"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
@ -152,7 +153,7 @@ export function MessageGroup({
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{shouldShowToolSteps && (
|
{shouldShowToolSteps && (
|
||||||
<ChainOfThoughtContent className="px-4 pb-2">
|
<ChainOfThoughtContent className="px-4 pb-4">
|
||||||
{showAbove &&
|
{showAbove &&
|
||||||
aboveLastToolCallSteps.map((step) =>
|
aboveLastToolCallSteps.map((step) =>
|
||||||
step.type === "reasoning" ? (
|
step.type === "reasoning" ? (
|
||||||
|
|
|
||||||
|
|
@ -41,11 +41,13 @@ export function MessageListItem({
|
||||||
message,
|
message,
|
||||||
isLoading,
|
isLoading,
|
||||||
threadId,
|
threadId,
|
||||||
|
isFirstInSession = false,
|
||||||
}: {
|
}: {
|
||||||
className?: string;
|
className?: string;
|
||||||
message: Message;
|
message: Message;
|
||||||
isLoading?: boolean;
|
isLoading?: boolean;
|
||||||
threadId: string;
|
threadId: string;
|
||||||
|
isFirstInSession?: boolean;
|
||||||
}) {
|
}) {
|
||||||
const isHuman = message.type === "human";
|
const isHuman = message.type === "human";
|
||||||
return (
|
return (
|
||||||
|
|
@ -55,6 +57,7 @@ export function MessageListItem({
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
from={isHuman ? "user" : "assistant"}
|
from={isHuman ? "user" : "assistant"}
|
||||||
|
isFirstInSession={isFirstInSession}
|
||||||
>
|
>
|
||||||
<MessageContent
|
<MessageContent
|
||||||
className={isHuman ? "w-fit" : "w-full"}
|
className={isHuman ? "w-fit" : "w-full"}
|
||||||
|
|
@ -223,7 +226,7 @@ function MessageContent_({
|
||||||
content={contentToDisplay}
|
content={contentToDisplay}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
rehypePlugins={[...rehypePlugins, [rehypeKatex, { output: "html" }]]}
|
rehypePlugins={[...rehypePlugins, [rehypeKatex, { output: "html" }]]}
|
||||||
className="my-3"
|
// className="my-3"
|
||||||
components={components}
|
components={components}
|
||||||
/>
|
/>
|
||||||
</AIElementMessageContent>
|
</AIElementMessageContent>
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,9 @@ export function MessageList({
|
||||||
const rehypePlugins = useRehypeSplitWordsIntoSpans(thread.isLoading);
|
const rehypePlugins = useRehypeSplitWordsIntoSpans(thread.isLoading);
|
||||||
const updateSubtask = useUpdateSubtask();
|
const updateSubtask = useUpdateSubtask();
|
||||||
const messages = messagesOverride ?? thread.messages;
|
const messages = messagesOverride ?? thread.messages;
|
||||||
|
const firstConversationMessageId = messages.find(
|
||||||
|
(message) => message.name !== "todo_reminder",
|
||||||
|
)?.id;
|
||||||
if (thread.isThreadLoading && !suppressThreadLoading) {
|
if (thread.isThreadLoading && !suppressThreadLoading) {
|
||||||
return <MessageListSkeleton />;
|
return <MessageListSkeleton />;
|
||||||
}
|
}
|
||||||
|
|
@ -71,6 +74,9 @@ export function MessageList({
|
||||||
message={group.messages[0]!}
|
message={group.messages[0]!}
|
||||||
isLoading={thread.isLoading}
|
isLoading={thread.isLoading}
|
||||||
threadId={threadId}
|
threadId={threadId}
|
||||||
|
isFirstInSession={
|
||||||
|
group.messages[0]?.id === firstConversationMessageId
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
} else if (group.type === "assistant:clarification") {
|
} else if (group.type === "assistant:clarification") {
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ export const zhCN: Translations = {
|
||||||
|
|
||||||
// Input Box
|
// Input Box
|
||||||
inputBox: {
|
inputBox: {
|
||||||
placeholder: "先输入说明需求,选择Skill,开始使用吧",
|
placeholder: "可直接聊天,或者输入需求并选择skill,完成更专业的任务",
|
||||||
createSkillPrompt:
|
createSkillPrompt:
|
||||||
"我们一起用 skill-creator 技能来创建一个技能吧。先问问我希望这个技能能做什么。",
|
"我们一起用 skill-creator 技能来创建一个技能吧。先问问我希望这个技能能做什么。",
|
||||||
sendMessagePrice:
|
sendMessagePrice:
|
||||||
|
|
|
||||||
|
|
@ -247,7 +247,9 @@
|
||||||
--accent: #1500331a;
|
--accent: #1500331a;
|
||||||
--accent-foreground: oklch(0.205 0 0);
|
--accent-foreground: oklch(0.205 0 0);
|
||||||
--destructive: oklch(0.577 0.245 27.325);
|
--destructive: oklch(0.577 0.245 27.325);
|
||||||
--border: oklch(0.922 0.0098 87.47);
|
--border: #00000015;
|
||||||
|
/* --border: oklch(92.23% 0.00983 87.442 / 0.09); */
|
||||||
|
|
||||||
--input: oklch(0.88 0.0098 87.47);
|
--input: oklch(0.88 0.0098 87.47);
|
||||||
--ring: transparent;
|
--ring: transparent;
|
||||||
--chart-1: oklch(0.646 0.222 41.116);
|
--chart-1: oklch(0.646 0.222 41.116);
|
||||||
|
|
@ -282,7 +284,7 @@
|
||||||
--accent: oklch(0.32 0.0036 106.64);
|
--accent: oklch(0.32 0.0036 106.64);
|
||||||
--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.191 22.216 / 10%);
|
--border: oklch(87.64% 0.06554 21.887 / 0.038);
|
||||||
--input: oklch(1 0 0 / 15%);
|
--input: oklch(1 0 0 / 15%);
|
||||||
--ring: transparent;
|
--ring: transparent;
|
||||||
--chart-1: oklch(0.488 0.243 264.376);
|
--chart-1: oklch(0.488 0.243 264.376);
|
||||||
|
|
@ -441,6 +443,10 @@ pre {
|
||||||
font-family:
|
font-family:
|
||||||
"Microsoft YaHei", "微软雅黑", "PingFang SC", sans-serif !important;
|
"Microsoft YaHei", "微软雅黑", "PingFang SC", sans-serif !important;
|
||||||
}
|
}
|
||||||
|
pre{
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 12px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
/* 列表项 - 14px */
|
/* 列表项 - 14px */
|
||||||
[data-streamdown="list-item"] {
|
[data-streamdown="list-item"] {
|
||||||
|
|
@ -465,6 +471,62 @@ pre {
|
||||||
font-size: calc(14px * var(--zoom-scale));
|
font-size: calc(14px * var(--zoom-scale));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 代码块 - 14px */
|
||||||
|
|
||||||
|
[data-streamdown="table"] {
|
||||||
|
border: none;
|
||||||
|
border-collapse: separate;
|
||||||
|
border-spacing: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-streamdown="table-cell"] {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
[data-streamdown="table-header"] {
|
||||||
|
background: #9c9b9b26;
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
[data-streamdown="table-header"] th {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 表格四角圆角:由四个角单元格承担视觉圆角 */
|
||||||
|
[data-streamdown="table-header"] tr:first-child > [data-streamdown="table-header-cell"]:first-child {
|
||||||
|
border-top-left-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-streamdown="table-header"] tr:first-child > [data-streamdown="table-header-cell"]:last-child {
|
||||||
|
border-top-right-radius: 5px;
|
||||||
|
}
|
||||||
|
[data-streamdown="table-body"] tr:first-child td{
|
||||||
|
padding-top: 20px;
|
||||||
|
}
|
||||||
|
/* 行分隔线 */
|
||||||
|
[data-streamdown="table-body"] tr{
|
||||||
|
border-bottom: 1px solid var(--border);
|
||||||
|
}
|
||||||
|
[data-streamdown="table-body"] tr:last-child > [data-streamdown="table-cell"]:first-child {
|
||||||
|
border-bottom-left-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-streamdown="table-body"] tr:last-child > [data-streamdown="table-cell"]:last-child {
|
||||||
|
border-bottom-right-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-streamdown="table-body"] tr:last-child {
|
||||||
|
height: 50px;
|
||||||
|
|
||||||
|
}
|
||||||
|
[data-streamdown="table-row"] >[data-streamdown="table-cell"]{
|
||||||
|
line-height: 14px;
|
||||||
|
vertical-align: top;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.cm-line {
|
.cm-line {
|
||||||
font-size: calc(14px * var(--zoom-scale));
|
font-size: calc(14px * var(--zoom-scale));
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue