mirror of
https://github.com/Sagit-chu/flvx.git
synced 2026-10-12 20:26:37 +08:00
refactor: Standardize empty state UI for tunnel and user pages, update announcement banner styling, and add new entries to .gitignore.
This commit is contained in:
@@ -268,3 +268,6 @@ sql/
|
|||||||
!go-backend/internal/store/postgres/sql/
|
!go-backend/internal/store/postgres/sql/
|
||||||
!go-backend/internal/store/postgres/sql/schema.sql
|
!go-backend/internal/store/postgres/sql/schema.sql
|
||||||
!go-backend/internal/store/postgres/sql/data.sql
|
!go-backend/internal/store/postgres/sql/data.sql
|
||||||
|
go-backend/gost.db-shm
|
||||||
|
.gitignore
|
||||||
|
go-backend/gost.db-wal
|
||||||
|
|||||||
@@ -17,13 +17,13 @@ export const AnnouncementBanner = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="mb-4 lg:mb-6 border border-blue-200 dark:border-blue-500/30 bg-gradient-to-r from-blue-50 to-purple-50 dark:from-blue-500/10 dark:to-purple-500/10">
|
<Card className="mb-4 lg:mb-6 border border-blue-100 dark:border-blue-500/20 bg-gradient-to-br from-blue-50/80 to-indigo-50/80 dark:from-blue-500/5 dark:to-indigo-500/5 shadow-sm">
|
||||||
<CardBody className="p-4">
|
<CardBody className="p-4 sm:p-5">
|
||||||
<div className="flex items-start justify-start gap-3.5">
|
<div className="flex items-center gap-3.5 sm:gap-4">
|
||||||
<div className="w-10 h-10 bg-blue-100 dark:bg-blue-500/20 rounded-lg flex-shrink-0 flex items-center justify-center mt-0.5">
|
<div className="w-10 h-10 sm:w-11 sm:h-11 bg-white dark:bg-blue-500/10 rounded-full flex-shrink-0 flex items-center justify-center shadow-sm border border-blue-100 dark:border-blue-500/20">
|
||||||
<svg
|
<svg
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
className="w-5 h-5 text-blue-600 dark:text-blue-400"
|
className="w-5 h-5 sm:w-5 sm:h-5 text-blue-500 dark:text-blue-400"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
viewBox="0 0 20 20"
|
viewBox="0 0 20 20"
|
||||||
>
|
>
|
||||||
@@ -34,11 +34,11 @@ export const AnnouncementBanner = ({
|
|||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 min-w-0 pt-0.5">
|
<div className="flex-1 min-w-0">
|
||||||
<h3 className="text-base font-semibold leading-none text-blue-900 dark:text-blue-100 mb-1.5">
|
<h3 className="text-[15px] font-semibold text-blue-900 dark:text-blue-100 tracking-wide mb-1 sm:mb-1.5 mt-1.5">
|
||||||
公告
|
公告
|
||||||
</h3>
|
</h3>
|
||||||
<div className="text-sm text-blue-800 dark:text-blue-200 break-words leading-relaxed">
|
<div className="text-sm text-blue-800/90 dark:text-blue-100/90 break-words leading-relaxed">
|
||||||
<ReactMarkdown
|
<ReactMarkdown
|
||||||
rehypePlugins={[rehypeSanitize]}
|
rehypePlugins={[rehypeSanitize]}
|
||||||
remarkPlugins={[remarkGfm]}
|
remarkPlugins={[remarkGfm]}
|
||||||
|
|||||||
@@ -1934,34 +1934,14 @@ export default function ForwardPage() {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
/* 空状态 */
|
/* 空状态 */
|
||||||
<Card className="shadow-sm border border-gray-200 dark:border-gray-700">
|
<Card className="shadow-sm border border-gray-200 dark:border-gray-700 bg-default-50/50">
|
||||||
<CardBody className="text-center py-16">
|
<CardBody className="text-center py-20 flex flex-col items-center justify-center min-h-[240px]">
|
||||||
<div className="flex flex-col items-center gap-4">
|
<h3 className="text-xl font-medium text-foreground tracking-tight mb-2">
|
||||||
<div className="w-16 h-16 bg-default-100 rounded-full flex items-center justify-center">
|
|
||||||
<svg
|
|
||||||
aria-hidden="true"
|
|
||||||
className="w-8 h-8 text-default-400"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M8 9l4-4 4 4m0 6l-4 4-4-4"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
strokeWidth={1.5}
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h3 className="text-lg font-semibold text-foreground">
|
|
||||||
暂无转发配置
|
暂无转发配置
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-default-500 text-sm mt-1">
|
<p className="text-default-500 text-sm max-w-xs mx-auto leading-relaxed">
|
||||||
还没有创建任何转发配置,点击上方按钮开始创建
|
还没有创建任何转发配置,点击上方按钮开始创建
|
||||||
</p>
|
</p>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
@@ -1988,34 +1968,14 @@ export default function ForwardPage() {
|
|||||||
</DndContext>
|
</DndContext>
|
||||||
) : (
|
) : (
|
||||||
/* 空状态 */
|
/* 空状态 */
|
||||||
<Card className="shadow-sm border border-gray-200 dark:border-gray-700">
|
<Card className="shadow-sm border border-gray-200 dark:border-gray-700 bg-default-50/50">
|
||||||
<CardBody className="text-center py-16">
|
<CardBody className="text-center py-20 flex flex-col items-center justify-center min-h-[240px]">
|
||||||
<div className="flex flex-col items-center gap-4">
|
<h3 className="text-xl font-medium text-foreground tracking-tight mb-2">
|
||||||
<div className="w-16 h-16 bg-default-100 rounded-full flex items-center justify-center">
|
|
||||||
<svg
|
|
||||||
aria-hidden="true"
|
|
||||||
className="w-8 h-8 text-default-400"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M8 9l4-4 4 4m0 6l-4 4-4-4"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
strokeWidth={1.5}
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h3 className="text-lg font-semibold text-foreground">
|
|
||||||
暂无转发配置
|
暂无转发配置
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-default-500 text-sm mt-1">
|
<p className="text-default-500 text-sm max-w-xs mx-auto leading-relaxed">
|
||||||
还没有创建任何转发配置,点击上方按钮开始创建
|
还没有创建任何转发配置,点击上方按钮开始创建
|
||||||
</p>
|
</p>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -334,34 +334,14 @@ export default function LimitPage() {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
/* 空状态 */
|
/* 空状态 */
|
||||||
<Card className="shadow-sm border border-gray-200 dark:border-gray-700">
|
<Card className="shadow-sm border border-gray-200 dark:border-gray-700 bg-default-50/50">
|
||||||
<CardBody className="text-center py-16">
|
<CardBody className="text-center py-20 flex flex-col items-center justify-center min-h-[240px]">
|
||||||
<div className="flex flex-col items-center gap-4">
|
<h3 className="text-xl font-medium text-foreground tracking-tight mb-2">
|
||||||
<div className="w-16 h-16 bg-default-100 rounded-full flex items-center justify-center">
|
|
||||||
<svg
|
|
||||||
aria-hidden="true"
|
|
||||||
className="w-8 h-8 text-default-400"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M12 6v6l4 2m6-6a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
strokeWidth={1.5}
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h3 className="text-lg font-semibold text-foreground">
|
|
||||||
暂无限速规则
|
暂无限速规则
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-default-500 text-sm mt-1">
|
<p className="text-default-500 text-sm max-w-xs mx-auto leading-relaxed">
|
||||||
还没有创建任何限速规则,点击上方按钮开始创建
|
还没有创建任何限速规则,点击上方按钮开始创建
|
||||||
</p>
|
</p>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1014,34 +1014,14 @@ export default function TunnelPage() {
|
|||||||
</DndContext>
|
</DndContext>
|
||||||
) : (
|
) : (
|
||||||
/* 空状态 */
|
/* 空状态 */
|
||||||
<Card className="shadow-sm border border-gray-200 dark:border-gray-700">
|
<Card className="shadow-sm border border-gray-200 dark:border-gray-700 bg-default-50/50">
|
||||||
<CardBody className="text-center py-16">
|
<CardBody className="text-center py-20 flex flex-col items-center justify-center min-h-[240px]">
|
||||||
<div className="flex flex-col items-center gap-4">
|
<h3 className="text-xl font-medium text-foreground tracking-tight mb-2">
|
||||||
<div className="w-16 h-16 bg-default-100 rounded-full flex items-center justify-center">
|
|
||||||
<svg
|
|
||||||
aria-hidden="true"
|
|
||||||
className="w-8 h-8 text-default-400"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M8.111 16.404a5.5 5.5 0 017.778 0M12 20h.01m-7.08-7.071c3.904-3.905 10.236-3.905 14.141 0M1.394 9.393c5.857-5.857 15.355-5.857 21.213 0"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
strokeWidth={1.5}
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h3 className="text-lg font-semibold text-foreground">
|
|
||||||
暂无隧道配置
|
暂无隧道配置
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-default-500 text-sm mt-1">
|
<p className="text-default-500 text-sm max-w-xs mx-auto leading-relaxed">
|
||||||
还没有创建任何隧道配置,点击上方按钮开始创建
|
还没有创建任何隧道配置,点击上方按钮开始创建
|
||||||
</p>
|
</p>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ import {
|
|||||||
SearchIcon,
|
SearchIcon,
|
||||||
EditIcon,
|
EditIcon,
|
||||||
DeleteIcon,
|
DeleteIcon,
|
||||||
UserIcon,
|
|
||||||
SettingsIcon,
|
SettingsIcon,
|
||||||
} from "@/components/icons";
|
} from "@/components/icons";
|
||||||
import { PageLoadingState } from "@/components/page-state";
|
import { PageLoadingState } from "@/components/page-state";
|
||||||
@@ -247,7 +246,7 @@ export default function UserPage() {
|
|||||||
if (response.code === 0) {
|
if (response.code === 0) {
|
||||||
setTunnels(Array.isArray(response.data) ? response.data : []);
|
setTunnels(Array.isArray(response.data) ? response.data : []);
|
||||||
}
|
}
|
||||||
} catch {}
|
} catch { }
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadSpeedLimits = async () => {
|
const loadSpeedLimits = async () => {
|
||||||
@@ -265,7 +264,7 @@ export default function UserPage() {
|
|||||||
|
|
||||||
setSpeedLimits(speedLimitList);
|
setSpeedLimits(speedLimitList);
|
||||||
}
|
}
|
||||||
} catch {}
|
} catch { }
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadUserGroups = async () => {
|
const loadUserGroups = async () => {
|
||||||
@@ -275,7 +274,7 @@ export default function UserPage() {
|
|||||||
if (response.code === 0) {
|
if (response.code === 0) {
|
||||||
setUserGroups(Array.isArray(response.data) ? response.data : []);
|
setUserGroups(Array.isArray(response.data) ? response.data : []);
|
||||||
}
|
}
|
||||||
} catch {}
|
} catch { }
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadUserTunnels = async (userId: number) => {
|
const loadUserTunnels = async (userId: number) => {
|
||||||
@@ -326,7 +325,7 @@ export default function UserPage() {
|
|||||||
if (groupRes.code === 0) {
|
if (groupRes.code === 0) {
|
||||||
currentGroupIds = groupRes.data || [];
|
currentGroupIds = groupRes.data || [];
|
||||||
}
|
}
|
||||||
} catch {}
|
} catch { }
|
||||||
|
|
||||||
setUserForm({
|
setUserForm({
|
||||||
id: user.id,
|
id: user.id,
|
||||||
@@ -652,21 +651,14 @@ export default function UserPage() {
|
|||||||
{loading ? (
|
{loading ? (
|
||||||
<PageLoadingState message="正在加载..." />
|
<PageLoadingState message="正在加载..." />
|
||||||
) : users.length === 0 ? (
|
) : users.length === 0 ? (
|
||||||
<Card className="shadow-sm border border-gray-200 dark:border-gray-700">
|
<Card className="shadow-sm border border-gray-200 dark:border-gray-700 bg-default-50/50">
|
||||||
<CardBody className="text-center py-16">
|
<CardBody className="text-center py-20 flex flex-col items-center justify-center min-h-[240px]">
|
||||||
<div className="flex flex-col items-center gap-4">
|
<h3 className="text-xl font-medium text-foreground tracking-tight mb-2">
|
||||||
<div className="w-16 h-16 bg-default-100 rounded-full flex items-center justify-center">
|
|
||||||
<UserIcon className="w-8 h-8 text-default-400" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h3 className="text-lg font-semibold text-foreground">
|
|
||||||
暂无用户数据
|
暂无用户数据
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-default-500 text-sm mt-1">
|
<p className="text-default-500 text-sm max-w-xs mx-auto leading-relaxed">
|
||||||
还没有创建任何用户,点击上方按钮开始创建
|
还没有创建任何用户,点击上方按钮开始创建
|
||||||
</p>
|
</p>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
) : (
|
) : (
|
||||||
@@ -1054,8 +1046,7 @@ export default function UserPage() {
|
|||||||
aria-disabled={isAssigned}
|
aria-disabled={isAssigned}
|
||||||
className={`
|
className={`
|
||||||
px-4 py-3 rounded-lg border transition-all duration-200 cursor-pointer
|
px-4 py-3 rounded-lg border transition-all duration-200 cursor-pointer
|
||||||
${
|
${isAssigned
|
||||||
isAssigned
|
|
||||||
? "bg-default-100/50 dark:bg-default-50/50 border-default-200/50 dark:border-default-100/20 opacity-60 cursor-not-allowed"
|
? "bg-default-100/50 dark:bg-default-50/50 border-default-200/50 dark:border-default-100/20 opacity-60 cursor-not-allowed"
|
||||||
: isSelected
|
: isSelected
|
||||||
? "bg-primary-50 dark:bg-primary-900/20 border-primary-300 dark:border-primary-500/50 shadow-sm"
|
? "bg-primary-50 dark:bg-primary-900/20 border-primary-300 dark:border-primary-500/50 shadow-sm"
|
||||||
|
|||||||
Reference in New Issue
Block a user