Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Q
qjclaw-dmg
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
AI-甘富林
qjclaw-dmg
Commits
fc12bfc3
Commit
fc12bfc3
authored
Apr 30, 2026
by
AI-甘富林
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
样式修改
parent
7ca78b1b
Changes
2
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
592 additions
and
28 deletions
+592
-28
App.tsx
apps/ui/src/App.tsx
+30
-20
styles.css
apps/ui/src/styles.css
+562
-8
No files found.
apps/ui/src/App.tsx
View file @
fc12bfc3
...
@@ -138,12 +138,12 @@ const IMAGE_ATTACHMENT_EXTENSIONS = new Set([".png", ".jpg", ".jpeg", ".webp", "
...
@@ -138,12 +138,12 @@ const IMAGE_ATTACHMENT_EXTENSIONS = new Set([".png", ".jpg", ".jpeg", ".webp", "
const
DOCUMENT_ATTACHMENT_EXTENSIONS
=
new
Set
([
".pdf"
,
".ppt"
,
".pptx"
,
".xls"
,
".xlsx"
,
".csv"
,
".tsv"
,
".doc"
,
".docx"
,
".txt"
,
".md"
,
".json"
,
".mp3"
]);
const
DOCUMENT_ATTACHMENT_EXTENSIONS
=
new
Set
([
".pdf"
,
".ppt"
,
".pptx"
,
".xls"
,
".xlsx"
,
".csv"
,
".tsv"
,
".doc"
,
".docx"
,
".txt"
,
".md"
,
".json"
,
".mp3"
]);
const
SUPPORTED_ATTACHMENT_EXTENSIONS
=
new
Set
([...
IMAGE_ATTACHMENT_EXTENSIONS
,
...
DOCUMENT_ATTACHMENT_EXTENSIONS
]);
const
SUPPORTED_ATTACHMENT_EXTENSIONS
=
new
Set
([...
IMAGE_ATTACHMENT_EXTENSIONS
,
...
DOCUMENT_ATTACHMENT_EXTENSIONS
]);
const
COMPOSER_ATTACHMENT_ACCEPT
=
[...
SUPPORTED_ATTACHMENT_EXTENSIONS
].
join
(
","
);
const
COMPOSER_ATTACHMENT_ACCEPT
=
[...
SUPPORTED_ATTACHMENT_EXTENSIONS
].
join
(
","
);
const
COMPOSER_TEXTAREA_DEFAULT_MIN_HEIGHT
=
4
8
;
const
COMPOSER_TEXTAREA_DEFAULT_MIN_HEIGHT
=
3
8
;
const
COMPOSER_TEXTAREA_SAFE_MIN_HEIGHT
=
3
8
;
const
COMPOSER_TEXTAREA_SAFE_MIN_HEIGHT
=
3
0
;
const
COMPOSER_TEXTAREA_MAX_HEIGHT
=
1
88
;
const
COMPOSER_TEXTAREA_MAX_HEIGHT
=
1
50
;
const
COMPOSER_TEXTAREA_DEFAULT_RATIO
=
0.1
45
;
const
COMPOSER_TEXTAREA_DEFAULT_RATIO
=
0.1
16
;
const
COMPOSER_TEXTAREA_MIN_RATIO
=
0.
12
;
const
COMPOSER_TEXTAREA_MIN_RATIO
=
0.
096
;
const
COMPOSER_TEXTAREA_MAX_RATIO
=
0.
32
;
const
COMPOSER_TEXTAREA_MAX_RATIO
=
0.
256
;
function
getComposerTextareaBounds
(
workspaceHeight
:
number
):
{
min
:
number
;
max
:
number
}
{
function
getComposerTextareaBounds
(
workspaceHeight
:
number
):
{
min
:
number
;
max
:
number
}
{
const
safeWorkspaceHeight
=
Number
.
isFinite
(
workspaceHeight
)
&&
workspaceHeight
>
0
?
workspaceHeight
:
0
;
const
safeWorkspaceHeight
=
Number
.
isFinite
(
workspaceHeight
)
&&
workspaceHeight
>
0
?
workspaceHeight
:
0
;
...
@@ -313,6 +313,24 @@ function buildUserMessage(content: string): UiChatMessage {
...
@@ -313,6 +313,24 @@ function buildUserMessage(content: string): UiChatMessage {
};
};
}
}
function
formatMessageTimestamp
(
value
:
string
):
string
{
const
date
=
new
Date
(
value
);
if
(
Number
.
isNaN
(
date
.
getTime
()))
{
return
value
;
}
const
pad
=
(
part
:
number
)
=>
String
(
part
).
padStart
(
2
,
"0"
);
return
[
date
.
getFullYear
(),
pad
(
date
.
getMonth
()
+
1
),
pad
(
date
.
getDate
())
].
join
(
"-"
)
+
" "
+
[
pad
(
date
.
getHours
()),
pad
(
date
.
getMinutes
()),
pad
(
date
.
getSeconds
())
].
join
(
":"
);
}
function
buildAssistantPlaceholder
(
statusLabel
:
string
):
UiChatMessage
{
function
buildAssistantPlaceholder
(
statusLabel
:
string
):
UiChatMessage
{
return
{
return
{
id
:
createClientMessageId
(
"assistant"
),
id
:
createClientMessageId
(
"assistant"
),
...
@@ -549,7 +567,7 @@ function renderExpertIcon(expertKey: ExpertVisualKey): ReactNode {
...
@@ -549,7 +567,7 @@ function renderExpertIcon(expertKey: ExpertVisualKey): ReactNode {
function
getIntentSuggestionIcon
(
platform
?:
string
):
ReactNode
{
function
getIntentSuggestionIcon
(
platform
?:
string
):
ReactNode
{
const
normalized
=
platform
?.
trim
().
toLowerCase
();
const
normalized
=
platform
?.
trim
().
toLowerCase
();
if
(
normalized
===
"xiaohongshu"
)
{
if
(
normalized
===
"xiaohongshu"
||
normalized
===
"xhs"
||
normalized
===
"rednote"
)
{
return
<
RedBookIcon
/>;
return
<
RedBookIcon
/>;
}
}
if
(
normalized
===
"douyin"
)
{
if
(
normalized
===
"douyin"
)
{
...
@@ -2199,7 +2217,7 @@ export default function App() {
...
@@ -2199,7 +2217,7 @@ export default function App() {
const [isComposerDragOver, setIsComposerDragOver] = useState(false);
const [isComposerDragOver, setIsComposerDragOver] = useState(false);
const [isComposerResizeActive, setIsComposerResizeActive] = useState(false);
const [isComposerResizeActive, setIsComposerResizeActive] = useState(false);
const [composerTextareaRatio, setComposerTextareaRatio] = useState(COMPOSER_TEXTAREA_DEFAULT_RATIO);
const [composerTextareaRatio, setComposerTextareaRatio] = useState(COMPOSER_TEXTAREA_DEFAULT_RATIO);
const [composerTextareaHeight, setComposerTextareaHeight] = useState(
96
);
const [composerTextareaHeight, setComposerTextareaHeight] = useState(
77
);
const [composerWorkspaceHeight, setComposerWorkspaceHeight] = useState(0);
const [composerWorkspaceHeight, setComposerWorkspaceHeight] = useState(0);
const [copiedToken, setCopiedToken] = useState("");
const [copiedToken, setCopiedToken] = useState("");
const activeStreamRef = useRef<ActiveStreamState | null>(null);
const activeStreamRef = useRef<ActiveStreamState | null>(null);
...
@@ -4773,6 +4791,7 @@ export default function App() {
...
@@ -4773,6 +4791,7 @@ export default function App() {
</div>
</div>
) : null}
) : null}
</div>
</div>
<span className="message-timestamp" aria-hidden="true">{formatMessageTimestamp(message.createdAt)}</span>
{message.role === "assistant" && canCopyMessage ? (
{message.role === "assistant" && canCopyMessage ? (
<div className="message-card-actions">
<div className="message-card-actions">
<button
<button
...
@@ -4825,7 +4844,7 @@ export default function App() {
...
@@ -4825,7 +4844,7 @@ export default function App() {
</div>
</div>
);
);
const conversationStatusNotice = showInlineStartupNotice ? (
const conversationStatusNotice = showInlineStartupNotice ? (
<div className={"notice" + (chatLaunchState === "error" ? " error" : " toast-notice")}>
<div className={"notice" + (chatLaunchState === "error" ? " error" : " toast-notice")}
role={chatLaunchState === "error" ? "alert" : "status"} aria-live="polite"
>
{startupCurtainStatus}
{startupCurtainStatus}
</div>
</div>
) : null;
) : null;
...
@@ -4843,20 +4862,11 @@ export default function App() {
...
@@ -4843,20 +4862,11 @@ export default function App() {
{pendingHomeIntentSuggestion.suggestion.projectDisplayName}
{pendingHomeIntentSuggestion.suggestion.projectDisplayName}
{ui.suggestionSwitchSuffix}
{ui.suggestionSwitchSuffix}
</p>
</p>
<span>
{pendingHomeIntentSuggestion.suggestion.reason}
{pendingHomeIntentSuggestion.suggestion.matchedAliases.length
? `
·
$
{
pendingHomeIntentSuggestion
.
suggestion
.
matchedAliases
.
join
(
" / "
)}
`
: ""}
</span>
</div>
</div>
<div className="home-intent-suggestion-actions">
<div className="home-intent-suggestion-actions">
<button type="button" className="secondary" disabled={homeIntentDecisionPending} onClick={() => void continuePendingHomePromptInHome()}>
<button type="button" className="secondary" disabled={homeIntentDecisionPending} onClick={() => void continuePendingHomePromptInHome()}>
{ui.suggestionContinue}
{ui.suggestionContinue}
</button>
</button>
<button type="button" className="secondary home-intent-suggestion-dismiss" disabled={homeIntentDecisionPending} onClick={dismissPendingHomeIntentSuggestion}>
{ui.suggestionDismiss}
</button>
<button type="button" disabled={homeIntentDecisionPending} onClick={() => void switchExpertAndContinuePendingHomePrompt()}>
<button type="button" disabled={homeIntentDecisionPending} onClick={() => void switchExpertAndContinuePendingHomePrompt()}>
{ui.suggestionSwitchAction}
{ui.suggestionSwitchAction}
</button>
</button>
...
@@ -5155,8 +5165,8 @@ export default function App() {
...
@@ -5155,8 +5165,8 @@ export default function App() {
</div>
</div>
</aside>
</aside>
<div className={"main-shell" + (isConversationView ? " conversation-main-layout" : "") + (viewMode === "settings" ? " settings-main-shell" : "")}>
<div className={"main-shell" + (isConversationView ? " conversation-main-layout" : "") + (viewMode === "settings" ? " settings-main-shell" : "")}>
{infoText ? <div className="notice toast-notice">{infoText}</div> : null}
{infoText ? <div className="notice toast-notice"
role="status" aria-live="polite"
>{infoText}</div> : null}
{errorText ? <div className="notice error">{errorText}</div> : null}
{errorText ? <div className="notice error"
role="alert"
>{errorText}</div> : null}
<main className={"content-area" + (isConversationView ? " conversation-content-area" : "")}>
<main className={"content-area" + (isConversationView ? " conversation-content-area" : "")}>
{isConversationView ? (
{isConversationView ? (
<section className="chat-panel conversation-panel">
<section className="chat-panel conversation-panel">
...
...
apps/ui/src/styles.css
View file @
fc12bfc3
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment