mirror of
https://github.com/dataelement/bisheng.git
synced 2026-08-30 17:58:00 +08:00
fix(platform): make page heights license-banner-aware; fix form file-type image var backfill
F037 license banner shifts all admin content down by its height, but page scroll containers hardcode viewport-relative heights (calc(100vh - Npx)) that ignore it, so their bottoms fell off-screen and could not be scrolled to when the banner was shown. - LicenseBanner publishes its rendered height as the CSS var --license-banner-h on :root (0px when hidden, so all subtractions are no-ops without the banner) - sweep every calc(100vh - Npx) page/scroll height to subtract the var - MainLayout sidebar nav max-height subtracts the var too - SystemPage 组织同步/角色管理: root lacked a fill+scroll container (or used a viewport calc miscalibrated for the nested TabsList) -> switch to h-full + internal overflow-y-auto so they fill their flex parent, banner-agnostic - InputFormItem: in edit mode, switching the upload file type to an image-capable type no longer backfilled the image variable name (the new-item auto-fill effect is skipped when editing); backfill image_file / file_path on file-type change
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { getLicenseStatus, LicenseStatus } from "@/controllers/API/license";
|
||||
import { AlertTriangle } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useEffect, useLayoutEffect, useRef, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
// Severity → styling. Only warning/critical/expired render a banner; normal/unknown render nothing.
|
||||
@@ -13,6 +13,10 @@ const SEVERITY_STYLE: Record<string, string> = {
|
||||
|
||||
const VISIBLE_SEVERITIES = ["warning", "critical", "expired"];
|
||||
|
||||
// TODO(debug): TEMPORARY — force the banner visible so the license is not required
|
||||
// to be expired while debugging the page-height offset. Revert to `false` before shipping.
|
||||
const FORCE_DEBUG_VISIBLE = false;
|
||||
|
||||
/**
|
||||
* Persistent top banner that surfaces the gateway license expiry state.
|
||||
*
|
||||
@@ -20,10 +24,15 @@ const VISIBLE_SEVERITIES = ["warning", "critical", "expired"];
|
||||
* unless the severity is warning/critical/expired (so normal/unknown/unavailable stay silent).
|
||||
* Status comes from the gateway via getLicenseStatus(); open-source deployments have no gateway,
|
||||
* so it resolves to null and the banner stays hidden.
|
||||
*
|
||||
* When visible it publishes its rendered height as the CSS custom property `--license-banner-h`
|
||||
* on :root, so viewport-based page heights (`calc(100vh - Npx)`) can subtract it. The property
|
||||
* defaults to `0px` whenever the banner is hidden, making that subtraction a no-op.
|
||||
*/
|
||||
export function LicenseBanner() {
|
||||
const { t } = useTranslation();
|
||||
const [status, setStatus] = useState<LicenseStatus | null>(null);
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
let active = true;
|
||||
@@ -35,16 +44,32 @@ export function LicenseBanner() {
|
||||
};
|
||||
}, []);
|
||||
|
||||
if (!status || !VISIBLE_SEVERITIES.includes(status.severity)) return null;
|
||||
const realVisible = Boolean(status && VISIBLE_SEVERITIES.includes(status.severity));
|
||||
const visible = FORCE_DEBUG_VISIBLE || realVisible;
|
||||
|
||||
const { severity, days_remaining } = status;
|
||||
const message =
|
||||
severity === "expired"
|
||||
// Publish / clear the banner height as a global CSS var for page-height calcs.
|
||||
useLayoutEffect(() => {
|
||||
const root = document.documentElement;
|
||||
if (visible && ref.current) {
|
||||
root.style.setProperty("--license-banner-h", `${ref.current.offsetHeight}px`);
|
||||
} else {
|
||||
root.style.setProperty("--license-banner-h", "0px");
|
||||
}
|
||||
return () => root.style.setProperty("--license-banner-h", "0px");
|
||||
}, [visible, status]);
|
||||
|
||||
if (!visible) return null;
|
||||
|
||||
const severity = realVisible ? status!.severity : "expired";
|
||||
const message = realVisible
|
||||
? severity === "expired"
|
||||
? t("license.expired")
|
||||
: t(`license.${severity}`, { days: days_remaining ?? 0 });
|
||||
: t(`license.${severity}`, { days: status!.days_remaining ?? 0 })
|
||||
: t("license.expired"); // debug placeholder when the real license is not expired
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
role="alert"
|
||||
className={`flex shrink-0 items-center justify-center gap-2 border-b px-4 py-2 text-sm font-medium ${SEVERITY_STYLE[severity]}`}
|
||||
>
|
||||
|
||||
@@ -178,7 +178,7 @@ export default function MainLayout() {
|
||||
</div>
|
||||
<div className="flex flex-1 min-h-0">
|
||||
<div className="relative z-10 bg-background-main h-full w-[184px] min-w-[184px] px-3 shadow-x1 flex justify-between text-center ">
|
||||
<nav className="overflow-y-auto overflow-x-hidden" style={{ maxHeight: "calc(100vh - 64px - 90px)" }}>
|
||||
<nav className="overflow-y-auto overflow-x-hidden" style={{ maxHeight: "calc(100vh - 64px - 90px - var(--license-banner-h, 0px))" }}>
|
||||
{/* <NavLink to='/' className={`navlink inline-flex rounded-lg w-full px-6 hover:bg-nav-hover h-12 mb-[3.5px]`}>
|
||||
<ApplicationIcon className="h-6 w-6 my-[12px]" /><span className="mx-[14px] max-w-[48px] text-[14px] leading-[48px]">{t('menu.app')}</span>
|
||||
</NavLink> */}
|
||||
|
||||
@@ -161,11 +161,11 @@ export default function editAssistant() {
|
||||
|
||||
return <div className="bg-background-main">
|
||||
<Header loca={loca} canEdit={canEdit} onSave={() => handleSave(true)} onLine={handleOnline} onTabChange={(t) => setShowApiPage(t === 'api')}></Header>
|
||||
<div className="h-[calc(100vh-70px)]">
|
||||
<div className="h-[calc(100vh-70px-var(--license-banner-h,0px))]">
|
||||
<div className={`flex h-full ${showApiPage ? 'hidden' : ''}`}>
|
||||
<div className="w-[60%]">
|
||||
<div className="text-md font-medium leading-none p-4 shadow-sm">{t('build.assistantConfiguration')}</div>
|
||||
<div className="flex h-[calc(100vh-120px)]">
|
||||
<div className="flex h-[calc(100vh-120px-var(--license-banner-h,0px))]">
|
||||
<Prompt canEdit={canEdit}></Prompt>
|
||||
<Setting></Setting>
|
||||
</div>
|
||||
|
||||
@@ -65,7 +65,7 @@ export function AppCenter({ scopeVersion = 0 }: { scopeVersion?: number }) {
|
||||
<div className="h-full overflow-y-scroll scrollbar-hide relative border-t">
|
||||
<div className="pt-4 relative">
|
||||
<CardContent className="pt-4 relative">
|
||||
<div className="w-full max-h-[calc(100vh-180px)] overflow-y-scroll scrollbar-hide pb-10">
|
||||
<div className="w-full max-h-[calc(100vh-180px-var(--license-banner-h,0px))] overflow-y-scroll scrollbar-hide pb-10">
|
||||
<ConfigInheritanceBanner meta={configMeta} />
|
||||
<FormInput
|
||||
label={t('chatConfig.appCenterWelcome')}
|
||||
|
||||
@@ -91,7 +91,7 @@ export default function KnowledgeSpace({ scopeVersion = 0 }: { scopeVersion?: nu
|
||||
<div className="h-full overflow-y-scroll scrollbar-hide relative border-t">
|
||||
<div className="pt-4 relative">
|
||||
<CardContent className="p-0 pt-4 relative">
|
||||
<div className="w-full max-h-[calc(100vh-180px)] overflow-y-scroll scrollbar-hide">
|
||||
<div className="w-full max-h-[calc(100vh-180px-var(--license-banner-h,0px))] overflow-y-scroll scrollbar-hide">
|
||||
<ConfigInheritanceBanner meta={configMeta} />
|
||||
<div className="mb-6">
|
||||
<div className="p-5 bg-gray-50 rounded-lg">
|
||||
|
||||
@@ -103,7 +103,7 @@ export default function Subscribe({ scopeVersion = 0 }: { scopeVersion?: number
|
||||
<div className=" h-full overflow-y-scroll scrollbar-hide relative border-t">
|
||||
<div className="pt-4 relative">
|
||||
<CardContent className="pt-4 relative">
|
||||
<div className="w-full max-h-[calc(100vh-180px)] overflow-y-scroll scrollbar-hide">
|
||||
<div className="w-full max-h-[calc(100vh-180px-var(--license-banner-h,0px))] overflow-y-scroll scrollbar-hide">
|
||||
<ConfigInheritanceBanner meta={configMeta} />
|
||||
<div className="mb-6">
|
||||
<div className="flex items-center mb-2">
|
||||
|
||||
@@ -172,7 +172,7 @@ export default function index({ scopeVersion = 0 }: { scopeVersion?: number }) {
|
||||
<div className="daily-page h-full overflow-y-scroll scrollbar-hide relative border-t">
|
||||
<div className="pt-4 relative">
|
||||
<CardContent className="pt-4 relative ">
|
||||
<div className="w-full max-h-[calc(100vh-180px)] overflow-y-scroll scrollbar-hide pb-10">
|
||||
<div className="w-full max-h-[calc(100vh-180px-var(--license-banner-h,0px))] overflow-y-scroll scrollbar-hide pb-10">
|
||||
<ConfigInheritanceBanner meta={configMeta} />
|
||||
{/* <ToggleSection
|
||||
title={t('chatConfig.workstationEntry')}
|
||||
|
||||
@@ -98,7 +98,7 @@ export const ChatTest = forwardRef((props, ref) => {
|
||||
><X /></Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className={`h-[calc(100vh-28px)] relative overflow-y-auto ${small ? 'hidden' : ''}`} onKeyDown={(e) => e.stopPropagation()}>
|
||||
<div className={`h-[calc(100vh-28px-var(--license-banner-h,0px))] relative overflow-y-auto ${small ? 'hidden' : ''}`} onKeyDown={(e) => e.stopPropagation()}>
|
||||
<ChatPane autoRun chatId={chatId} flow={flow} wsUrl={`${host}${__APP_ENV__.BASE_URL}/api/v1/workflow/chat/${flow?.id}`} />
|
||||
</div>
|
||||
{!small && <div
|
||||
|
||||
@@ -241,7 +241,7 @@ export const RunTest = forwardRef((props, ref) => {
|
||||
{t('singleNodeRun')}
|
||||
</SheetTitle>
|
||||
</SheetHeader>
|
||||
<div className="px-2 pt-2 pb-10 h-[calc(100vh-40px)] overflow-y-auto bg-[#fff] dark:bg-[#303134]">
|
||||
<div className="px-2 pt-2 pb-10 h-[calc(100vh-40px-var(--license-banner-h,0px))] overflow-y-auto bg-[#fff] dark:bg-[#303134]">
|
||||
{inputs.map((input) => (
|
||||
input.autoFill ? null : <div className="mb-2" key={input.key}>
|
||||
<Label className="flex items-center bisheng-label mb-2">
|
||||
|
||||
+33
-1
@@ -376,9 +376,41 @@ function Form({ nodeId, nodeData, initialData, onSubmit, onCancel, existingOptio
|
||||
|
||||
// 处理文件类型变化
|
||||
const handleFileTypeChange = (fileType) => {
|
||||
setFormData({ ...formData, fileType });
|
||||
// 清空相关错误
|
||||
setErrors({});
|
||||
|
||||
setFormData(prev => {
|
||||
const updates: any = { fileType };
|
||||
const fileOptions = existingOptions?.filter(opt => opt.type === FormType.File) || [];
|
||||
const isImageCapable = fileType === 'all' || fileType === 'image';
|
||||
|
||||
// Image variable only exists for image-capable types. Backfill a unique name
|
||||
// when switching into such a type with no value yet — e.g. editing an item
|
||||
// that was saved as document-only, where image_file was cleared on submit and
|
||||
// the new-item auto-fill effect is skipped in edit mode (initialData present).
|
||||
if (isImageCapable && (!prev.imageFile || prev.imageFile.trim() === '')) {
|
||||
let name = 'image_file';
|
||||
let counter = 1;
|
||||
while (fileOptions.some(opt => opt.image_file === name)) {
|
||||
counter += 1;
|
||||
name = `image_file${counter}`;
|
||||
}
|
||||
updates.imageFile = name;
|
||||
}
|
||||
|
||||
// File path is always exposed now; backfill if somehow empty (legacy items).
|
||||
if (!prev.filepath || prev.filepath.trim() === '') {
|
||||
let name = 'file_path';
|
||||
let counter = 1;
|
||||
while (fileOptions.some(opt => opt.file_path === name)) {
|
||||
counter += 1;
|
||||
name = `file_path${counter}`;
|
||||
}
|
||||
updates.filepath = name;
|
||||
}
|
||||
|
||||
return { ...prev, ...updates };
|
||||
});
|
||||
}
|
||||
|
||||
// 处理文件处理策略变化(单选 3 项)
|
||||
|
||||
@@ -346,7 +346,7 @@ const McpServerEditorDialog = forwardRef(({ existingNames = [], onReload }, ref)
|
||||
<SheetTitle>{isEditMode ? t('edit') : t('add')} {t('mcpServer')}</SheetTitle>
|
||||
</SheetHeader>
|
||||
|
||||
<div className="mt-4 space-y-6 px-6 overflow-y-auto h-[calc(100vh-200px)]">
|
||||
<div className="mt-4 space-y-6 px-6 overflow-y-auto h-[calc(100vh-200px-var(--license-banner-h,0px))]">
|
||||
{/* Name input */}
|
||||
<div>
|
||||
<label className="">{t('tools.name')}</label>
|
||||
|
||||
@@ -193,7 +193,7 @@ export default function HomePage({ onSelect }) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="relative overflow-y-auto h-[calc(100vh-308px)]">
|
||||
<div className="relative overflow-y-auto h-[calc(100vh-308px-var(--license-banner-h,0px))]">
|
||||
<div className="flex flex-wrap gap-2 px-12 scrollbar-hide pt-4 pb-20">
|
||||
{renderChatOptions()}
|
||||
{hasMoreData && <LoadMore onScrollLoad={handleLoadMore} />}
|
||||
|
||||
@@ -217,7 +217,7 @@ export function DashboardSidebar({
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="overflow-y-auto space-y-2 h-[calc(100vh-174px)]">
|
||||
<div className="overflow-y-auto space-y-2 h-[calc(100vh-174px-var(--license-banner-h,0px))]">
|
||||
{filteredDashboards.length === 0 ? (
|
||||
<div className="text-center text-muted-foreground text-sm py-8">
|
||||
{searchQuery ? t('noMatchingDashboards') : t('noDashboards')}
|
||||
|
||||
@@ -46,7 +46,7 @@ export default function EditorPage() {
|
||||
dashboard={currentDashboard}
|
||||
dashboardId={dashboardId}
|
||||
/>
|
||||
<div className="h-[calc(100vh-64px)]">
|
||||
<div className="h-[calc(100vh-64px-var(--license-banner-h,0px))]">
|
||||
<EditorCanvas isLoading={isLoading} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -51,7 +51,7 @@ export default function index() {
|
||||
<LoadingIcon />
|
||||
</div>
|
||||
)}
|
||||
<div className="h-[calc(100vh-128px)] overflow-y-auto pb-10">
|
||||
<div className="h-[calc(100vh-128px-var(--license-banner-h,0px))] overflow-y-auto pb-10">
|
||||
<div className="flex justify-end gap-4 items-center">
|
||||
<SearchInput placeholder={t('dataset.name')} onChange={(e) => search(e.target.value)} />
|
||||
<Button className="px-8 text-[#FFFFFF]" onClick={() => modelRef.current.open()}>{t('dataset.create')}</Button>
|
||||
|
||||
@@ -513,7 +513,7 @@ export default function KnowledgeFile() {
|
||||
{loading && <div className="absolute w-full h-full top-0 left-0 flex justify-center items-center z-10 bg-[rgba(255,255,255,0.6)] dark:bg-blur-shared">
|
||||
<LoadingIcon />
|
||||
</div>}
|
||||
<div className="h-[calc(100vh-128px)] overflow-y-auto pb-20">
|
||||
<div className="h-[calc(100vh-128px-var(--license-banner-h,0px))] overflow-y-auto pb-20">
|
||||
<div className="flex justify-end gap-4 items-center absolute right-0 top-[-44px]">
|
||||
<SearchInput placeholder={t('lib.searchPlaceholder', { ns: 'bs' })} onChange={(e) => search(e.target.value)} />
|
||||
{canCreateLibrary && <Button className="px-8 text-[#FFFFFF]" onClick={() => setOpen(true)}>{t('create', { ns: 'bs' })}</Button>}
|
||||
|
||||
@@ -399,7 +399,7 @@ export default function KnowledgeQa(params) {
|
||||
<LoadingIcon />
|
||||
</div>
|
||||
)}
|
||||
<div className="h-[calc(100vh-128px)] overflow-y-auto pb-20">
|
||||
<div className="h-[calc(100vh-128px-var(--license-banner-h,0px))] overflow-y-auto pb-20">
|
||||
<div className="flex justify-end gap-4 items-center absolute right-0 top-[-44px]">
|
||||
<SearchInput placeholder={t('lib.searchPlaceholder', { ns: 'bs' })} onChange={(e) => search(e.target.value)} />
|
||||
{canCreateLibrary && <Button className="px-8 text-[#FFFFFF]" onClick={() => setOpen(true)}>{t('create', { ns: 'bs' })}</Button>}
|
||||
|
||||
@@ -203,7 +203,7 @@ export default function FileUploadStep4({ data, kId, hasRepeat }) {
|
||||
<div className="flex-1">
|
||||
<h1 className="text-3xl text-primary mt-2">{finish ? t('documentDataParsingCompleted') : t('documentDataBeingPrepared')}</h1>
|
||||
<p className="text-base text-gray-500 mt-2">{t('youCanReturn')}</p>
|
||||
<div className="overflow-y-auto mt-4 space-y-2 pb-10 max-h-[calc(100vh-400px)]">
|
||||
<div className="overflow-y-auto mt-4 space-y-2 pb-10 max-h-[calc(100vh-400px-var(--license-banner-h,0px))]">
|
||||
{files.map(item => <ProgressItem analysis key={item.id} item={item} />)}
|
||||
</div>
|
||||
<div className="flex justify-end gap-4">
|
||||
|
||||
@@ -536,7 +536,7 @@ export default function Files({ onPreview, canEditKb = false, canDeleteKb = fals
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="h-[calc(100vh-180px)] overflow-y-auto pb-20">
|
||||
<div className="h-[calc(100vh-180px-var(--license-banner-h,0px))] overflow-y-auto pb-20">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
|
||||
@@ -138,7 +138,7 @@ export default forwardRef(function Markdown({ edit, isUns, title, q, value }, re
|
||||
<Switch checked={!isAce} onCheckedChange={hangleCheckChagne} />
|
||||
</div>}
|
||||
</div>
|
||||
<div className="border mb-2 h-[calc(100vh-104px)]">
|
||||
<div className="border mb-2 h-[calc(100vh-104px-var(--license-banner-h,0px))]">
|
||||
{/* 编辑器 */}
|
||||
<AceEditorCom hidden={!isAce} markdown={val} onChange={setValue} />
|
||||
<VditorEditor ref={vditorRef} edit={edit} hidden={isAce} markdown={val} />
|
||||
|
||||
@@ -298,7 +298,7 @@ const ParagraphEdit = ({
|
||||
{/* file view */}
|
||||
<div className="bg-gray-100 relative">
|
||||
{showPos && value && Object.keys(labels).length !== 0 && <Button className="absolute top-2 right-2 z-10 bg-background" variant="outline" onClick={() => setRandom(Math.random() / 10000)}><Crosshair className="mr-1" size={16} />{t('backToPosition')}</Button>}
|
||||
<div className="h-[calc(100vh-104px)] overflow-auto"
|
||||
<div className="h-[calc(100vh-104px-var(--license-banner-h,0px))] overflow-auto"
|
||||
style={{
|
||||
width: 'calc(100vh - 104px)',
|
||||
minWidth: '100%',
|
||||
|
||||
@@ -811,7 +811,7 @@ export default function Paragraphs({ fileId, onBack, canEditKb = false, canDelet
|
||||
}, [canEditKb, mainMetadataList, selectedFileId, t]);
|
||||
|
||||
return (
|
||||
<div className="relative flex flex-col h-[calc(100vh-64px)]">
|
||||
<div className="relative flex flex-col h-[calc(100vh-64px-var(--license-banner-h,0px))]">
|
||||
{load && <div className="absolute w-full h-full top-0 left-0 flex justify-center items-center z-10 bg-[rgba(255,255,255,1)] dark:bg-blur-shared">
|
||||
<LoadingIcon />
|
||||
</div>}
|
||||
@@ -900,7 +900,7 @@ export default function Paragraphs({ fileId, onBack, canEditKb = false, canDelet
|
||||
edit={canEditKb}
|
||||
canDelete={canDeleteKb}
|
||||
page={page}
|
||||
className="h-[calc(100vh-206px)] pb-6"
|
||||
className="h-[calc(100vh-206px-var(--license-banner-h,0px))] pb-6"
|
||||
fileSuffix={currentFile?.suffix || ''}
|
||||
loading={loading}
|
||||
chunks={chunks}
|
||||
|
||||
@@ -361,7 +361,7 @@ export default function PreviewFile({
|
||||
<span className="text-primary cursor-pointer" onClick={handleOvergap}>{t('overwriteSegment')}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className={`relative ${previewScrollClass} ${edit ? 'h-[calc(100vh-206px)]' : 'h-[calc(100vh-284px)]'}`}>
|
||||
<div className={`relative ${previewScrollClass} ${edit ? 'h-[calc(100vh-206px-var(--license-banner-h,0px))]' : 'h-[calc(100vh-284px-var(--license-banner-h,0px))]'}`}>
|
||||
{render(file.suffix)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -260,7 +260,7 @@ export default function PreviewResult({
|
||||
fileId={syncChunksSelectId}
|
||||
fileSuffix={currentFile?.suffix}
|
||||
previewCount={previewCount}
|
||||
className="h-[calc(100vh-284px)]"
|
||||
className="h-[calc(100vh-284px-var(--license-banner-h,0px))]"
|
||||
edit={step === 3 || (step === 2 && !showPreview)}
|
||||
loading={loading}
|
||||
chunks={chunks}
|
||||
|
||||
@@ -529,7 +529,7 @@ export default function QasPage() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="overflow-y-auto h-[calc(100vh-132px)] pb-20">
|
||||
<div className="overflow-y-auto h-[calc(100vh-132px-var(--license-banner-h,0px))] pb-20">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
|
||||
@@ -159,7 +159,7 @@ export default function index() {
|
||||
</RadioGroup>
|
||||
<PageChange />
|
||||
</div>
|
||||
<div className="h-[calc(100vh-132px)]">
|
||||
<div className="h-[calc(100vh-132px-var(--license-banner-h,0px))]">
|
||||
{type === AppNumType.FLOW
|
||||
? <ChatMessages mark={mark} logo='' useName='' guideWord='' loadMore={() => loadMoreFlowHistoryMsg(fid, true)} onMarkClick={handleMarkClick}></ChatMessages>
|
||||
: <MessagePanne mark={mark} logo='' useName='' guideWord=''
|
||||
|
||||
@@ -115,7 +115,7 @@ export default function SystemLog() {
|
||||
<LoadingIcon />
|
||||
</div>
|
||||
)}
|
||||
<div className="h-[calc(100vh-128px)] overflow-y-auto px-2 py-4 pb-10">
|
||||
<div className="h-[calc(100vh-128px-var(--license-banner-h,0px))] overflow-y-auto px-2 py-4 pb-10">
|
||||
<div className="flex flex-wrap gap-4">
|
||||
<div className="w-[200px] relative">
|
||||
<MultiSelect contentClassName="overflow-y-auto max-w-[200px]" multiple
|
||||
|
||||
@@ -68,7 +68,7 @@ export default function AppChatDetail() {
|
||||
<span className=" text-gray-700 text-sm font-black pl-4">{title}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="h-[calc(100vh-132px)]">
|
||||
<div className="h-[calc(100vh-132px-var(--license-banner-h,0px))]">
|
||||
{type === AppNumType.FLOW
|
||||
? <ChatMessages logo={logo} debug useName={''} guideWord={''} loadMore={() => loadMoreFlowHistoryMsg(fid, true)} onMarkClick={null}></ChatMessages>
|
||||
: <MessagePanne logo={logo} debug useName='' guideWord=''
|
||||
|
||||
@@ -122,7 +122,7 @@ export default function DailyChatDetail() {
|
||||
</div>
|
||||
|
||||
{/* messages */}
|
||||
<div className="h-[calc(100vh-132px)] overflow-y-auto">
|
||||
<div className="h-[calc(100vh-132px-var(--license-banner-h,0px))] overflow-y-auto">
|
||||
<div className="max-w-4xl mx-auto px-4 py-8">
|
||||
{messages.map((msg) => (
|
||||
<div key={msg.messageId} className="mb-8 flex items-start gap-4">
|
||||
|
||||
@@ -267,7 +267,7 @@ export default function AppUseLog() {
|
||||
{loading && <div className="absolute w-full h-full top-0 left-0 flex justify-center items-center z-10 bg-[rgba(255,255,255,0.6)] dark:bg-blur-shared">
|
||||
<LoadingIcon />
|
||||
</div>}
|
||||
<div className="h-[calc(100vh-128px)] overflow-y-auto px-2 py-4 pb-20">
|
||||
<div className="h-[calc(100vh-128px-var(--license-banner-h,0px))] overflow-y-auto px-2 py-4 pb-20">
|
||||
<div className="flex flex-wrap gap-4">
|
||||
<FilterByApp value={filters.appName} placeholder={t('log.appName')} onChange={(value) => dispatch({ type: 'SET_FILTER', payload: { ['appName']: value } })} />
|
||||
<FilterByUser value={filters.userName} placeholder={t('log.userName')} onChange={(value) => dispatch({ type: 'SET_FILTER', payload: { ['userName']: value } })} />
|
||||
|
||||
@@ -77,7 +77,7 @@ export default function CreateTask({ rtClick, gpuClick, onCancel, onCreate }) {
|
||||
onCreate(res.id)
|
||||
}
|
||||
|
||||
return <div className="pt-2 h-[calc(100vh-162px)] px-2 overflow-y-auto">
|
||||
return <div className="pt-2 h-[calc(100vh-162px-var(--license-banner-h,0px))] px-2 overflow-y-auto">
|
||||
<div className="border-b pb-2 flex justify-between items-center">
|
||||
<h1 className="">{t('finetune.createTrainingTask')}</h1>
|
||||
{/* <Button variant="black" onClick={rtClick}>FT服务管理</Button> */}
|
||||
|
||||
@@ -67,7 +67,7 @@ export const Finetune = () => {
|
||||
<div className="mt-6 text-center text-gray-400">{t('finetune.noData')}</div>
|
||||
: <div className="flex gap-4 mt-4">
|
||||
<div className="w-[40%] relative">
|
||||
<div className="border-r overflow-y-auto max-h-[calc(100vh-150px)] pb-20">
|
||||
<div className="border-r overflow-y-auto max-h-[calc(100vh-150px-var(--license-banner-h,0px))] pb-20">
|
||||
<Table className="px-2">
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
@@ -99,7 +99,7 @@ export const Finetune = () => {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1 overflow-hidden overflow-y-auto max-h-[calc(100vh-150px)]">
|
||||
<div className="flex-1 overflow-hidden overflow-y-auto max-h-[calc(100vh-150px-var(--license-banner-h,0px))]">
|
||||
{taskId ?
|
||||
<FinetuneDetail id={taskId} onDelete={handleDeleteTask} onStatusChange={reload}></FinetuneDetail> :
|
||||
<div className="flex justify-center items-center h-full">
|
||||
|
||||
@@ -629,7 +629,7 @@ export default function ModelConfig({ id, onGetName, onBack, onReload, onBerforS
|
||||
</ShadTooltip>
|
||||
<span>{id === -1 ? t('model.addModel') : t('model.modelConfiguration')}</span>
|
||||
</div>
|
||||
<div className="w-[50%] min-w-64 px-4 pb-10 mx-auto mt-6 h-[calc(100vh-220px)] overflow-y-auto">
|
||||
<div className="w-[50%] min-w-64 px-4 pb-10 mx-auto mt-6 h-[calc(100vh-220px-var(--license-banner-h,0px))] overflow-y-auto">
|
||||
<div className="mb-2">
|
||||
<Label className="bisheng-label"> {t('model.interModelFormat')}</Label>
|
||||
<Select value={formData.type} disabled={id !== -1} onValueChange={handleTypeChange}>
|
||||
|
||||
@@ -160,7 +160,7 @@ export default function Departments() {
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div ref={containerRef} className="flex h-[calc(100vh-140px)]">
|
||||
<div ref={containerRef} className="flex h-[calc(100vh-140px-var(--license-banner-h,0px))]">
|
||||
{/* Left tree panel */}
|
||||
<div className="flex min-w-[240px] flex-col border-r pr-4 pt-2" style={{ width: leftPaneWidth }}>
|
||||
<LazyDepartmentTree
|
||||
|
||||
@@ -586,7 +586,7 @@ export default function EditRole({ id, name, groupId, knowledgeSpaceFileLimit, o
|
||||
onChange(true);
|
||||
};
|
||||
return (
|
||||
<div className="max-w-[600px] mx-auto pt-4 h-[calc(100vh-128px)] overflow-y-auto pb-40 scrollbar-hide">
|
||||
<div className="max-w-[600px] mx-auto pt-4 h-[calc(100vh-128px-var(--license-banner-h,0px))] overflow-y-auto pb-40 scrollbar-hide">
|
||||
{/* 角色名称输入 */}
|
||||
<div className="font-bold mt-4">
|
||||
<p className="text-xl mb-4">{t('system.roleName')}</p>
|
||||
|
||||
@@ -191,7 +191,7 @@ export default function EditUserGroup({ data, onBeforeChange, onChange }: EditPr
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mx-auto flex h-[calc(100vh-128px)] max-w-[800px] flex-col">
|
||||
<div className="mx-auto flex h-[calc(100vh-128px-var(--license-banner-h,0px))] max-w-[800px] flex-col">
|
||||
<div className="min-h-0 flex-1 overflow-y-auto px-1 pt-4 pb-4">
|
||||
<div className="font-bold mt-4">
|
||||
<p className="text-xl mb-4">{t('system.groupName')}</p>
|
||||
|
||||
@@ -67,7 +67,7 @@ export default function OrgSync() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-4 p-4">
|
||||
<div className="flex h-full flex-col gap-4 overflow-y-auto p-4">
|
||||
<h2 className="text-lg font-semibold">{t("title")}</h2>
|
||||
|
||||
<div className="rounded-lg border">
|
||||
|
||||
@@ -578,8 +578,8 @@ export default function Roles() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
<div className="h-[calc(100vh-128px)] overflow-y-auto pb-10 pt-2">
|
||||
<div className="relative h-full">
|
||||
<div className="h-full overflow-y-auto pb-10 pt-2">
|
||||
<div className="mb-3 flex items-center justify-between">
|
||||
<div className="w-[220px]">
|
||||
<SearchInput
|
||||
|
||||
@@ -157,7 +157,7 @@ export default function UserGroups() {
|
||||
}
|
||||
|
||||
return <div className="relative">
|
||||
<div className="h-[calc(100vh-128px)] overflow-y-auto pb-10">
|
||||
<div className="h-[calc(100vh-128px-var(--license-banner-h,0px))] overflow-y-auto pb-10">
|
||||
<div className="flex gap-6 items-center justify-end">
|
||||
<div className="w-[180px] relative">
|
||||
<SearchInput placeholder={t('system.groupName')} onChange={handleSearch}></SearchInput>
|
||||
|
||||
@@ -190,7 +190,7 @@ export default function Users(params) {
|
||||
}
|
||||
|
||||
return <div className="relative">
|
||||
<div className="h-[calc(100vh-128px)] overflow-y-auto pb-10">
|
||||
<div className="h-[calc(100vh-128px-var(--license-banner-h,0px))] overflow-y-auto pb-10">
|
||||
<div className="flex justify-end gap-6">
|
||||
<div className="w-[180px] relative">
|
||||
<SearchInput placeholder={t('system.username')} onChange={(e) => search(e.target.value)}></SearchInput>
|
||||
|
||||
@@ -38,7 +38,7 @@ const invoices = [
|
||||
export default function Example(params) {
|
||||
const { t } = useTranslation(); // Initialize translation hook
|
||||
|
||||
return <div className="h-[calc(100vh-220px)] overflow-y-auto py-10 pl-2 pr-10">
|
||||
return <div className="h-[calc(100vh-220px-var(--license-banner-h,0px))] overflow-y-auto py-10 pl-2 pr-10">
|
||||
<Label className="mt-10">{t('example.buttons')}</Label>
|
||||
<div className="flex gap-2 mb-6">
|
||||
<Button variant="default">{t('example.button')}</Button>
|
||||
|
||||
@@ -148,7 +148,7 @@ function TenantPageInner() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="h-[calc(100vh-200px)] overflow-y-auto">
|
||||
<div className="h-[calc(100vh-200px-var(--license-banner-h,0px))] overflow-y-auto">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
|
||||
Reference in New Issue
Block a user