feat(management-navigation-single-company-ux): 收敛管理导航与单公司配置体验
这个提交包含在:
@@ -30,6 +30,7 @@ import { Input } from "../components/ui/input";
|
||||
import { Label } from "../components/ui/label";
|
||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "../components/ui/table";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "../components/ui/tabs";
|
||||
import { resolveSingleCompanyState } from "../features/company/singleCompany";
|
||||
|
||||
const DOCUMENT_ENTITY_TYPE_OPTIONS: Array<{ value: DocumentCategoryEntityType; label: string }> = [
|
||||
{ value: "reimbursement", label: "报销" },
|
||||
@@ -132,6 +133,12 @@ export function MasterDataPage() {
|
||||
}),
|
||||
});
|
||||
|
||||
const activeCompaniesQuery = useQuery({
|
||||
queryKey: ["master-data", "legal-entities", "active-company-state"],
|
||||
enabled: canView,
|
||||
queryFn: () => fetchLegalEntities({ enabled: true }),
|
||||
});
|
||||
|
||||
const costCentersQuery = useQuery({
|
||||
queryKey: [
|
||||
"master-data",
|
||||
@@ -167,6 +174,8 @@ export function MasterDataPage() {
|
||||
});
|
||||
|
||||
const legalEntities = legalEntitiesQuery.data?.items ?? [];
|
||||
const activeCompanies = activeCompaniesQuery.data?.items ?? [];
|
||||
const companyState = resolveSingleCompanyState(activeCompanies);
|
||||
const costCenters = costCentersQuery.data?.items ?? [];
|
||||
const documentCategories = documentCategoriesQuery.data?.items ?? [];
|
||||
const masterDataStats = {
|
||||
@@ -211,7 +220,7 @@ export function MasterDataPage() {
|
||||
setLegalEntityCurrency("CNY");
|
||||
setLegalEntityTaxNo("");
|
||||
setError("");
|
||||
toast.success("法体已创建");
|
||||
toast.success("公司信息已创建");
|
||||
},
|
||||
onError: (mutationError) => {
|
||||
const message = resolveError(mutationError);
|
||||
@@ -312,7 +321,7 @@ export function MasterDataPage() {
|
||||
<ListWorkspace>
|
||||
<WorkspaceHeader
|
||||
title="主数据"
|
||||
subtitle="集中维护法体、成本中心、单据分类、日历与供应商,为预算、采购、请假与资产扩展提供统一骨架。"
|
||||
subtitle="集中维护公司信息、成本中心、单据分类、日历与供应商,为预算、采购、请假与资产扩展提供统一基础资料。"
|
||||
actions={
|
||||
<Button variant="secondary" type="button" onClick={() => setIncludeArchived((value) => !value)}>
|
||||
{includeArchived ? "隐藏归档" : "显示归档"}
|
||||
@@ -325,7 +334,7 @@ export function MasterDataPage() {
|
||||
) : null}
|
||||
|
||||
<div className="finance-status-strip" data-testid="master-data-summary">
|
||||
<div className="finance-metric-card"><div className="finance-metric-card__label">法体</div><div className="finance-metric-card__value">{masterDataStats.legalEntities}</div></div>
|
||||
<div className="finance-metric-card"><div className="finance-metric-card__label">公司信息</div><div className="finance-metric-card__value">{masterDataStats.legalEntities}</div></div>
|
||||
<div className="finance-metric-card"><div className="finance-metric-card__label">成本中心</div><div className="finance-metric-card__value">{masterDataStats.costCenters}</div></div>
|
||||
<div className="finance-metric-card"><div className="finance-metric-card__label">单据分类</div><div className="finance-metric-card__value">{masterDataStats.documentCategories}</div></div>
|
||||
<div className="finance-metric-card"><div className="finance-metric-card__label">归档项</div><div className="finance-metric-card__value">{masterDataStats.archived}</div></div>
|
||||
@@ -334,7 +343,7 @@ export function MasterDataPage() {
|
||||
|
||||
<Tabs value={tab} onValueChange={(value) => setTab(value as typeof tab)}>
|
||||
<TabsList className="ops-command-bar__tabs !w-full !justify-start">
|
||||
<TabsTrigger value="legal-entities">法体</TabsTrigger>
|
||||
<TabsTrigger value="legal-entities">公司信息</TabsTrigger>
|
||||
<TabsTrigger value="cost-centers">成本中心</TabsTrigger>
|
||||
<TabsTrigger value="document-categories">单据分类</TabsTrigger>
|
||||
<TabsTrigger value="holiday-calendars">日历</TabsTrigger>
|
||||
@@ -344,7 +353,7 @@ export function MasterDataPage() {
|
||||
<TabsContent value="legal-entities" className="space-y-4">
|
||||
<FilterBar className="ops-command-bar !p-3 md:!p-3.5">
|
||||
<div className="flex flex-wrap items-center justify-between gap-3">
|
||||
<h3 className="text-base font-semibold text-zinc-900">法体筛选</h3>
|
||||
<h3 className="text-base font-semibold text-zinc-900">公司信息筛选</h3>
|
||||
<select
|
||||
className="select-std max-w-xs"
|
||||
value={legalEntityEnabledFilter}
|
||||
@@ -357,9 +366,18 @@ export function MasterDataPage() {
|
||||
</div>
|
||||
</FilterBar>
|
||||
|
||||
{canManage ? (
|
||||
{activeCompaniesQuery.isError ? (
|
||||
<div className="admin-command-panel border-red-200 bg-red-50/70 text-sm text-red-600">
|
||||
公司信息读取失败,请刷新后重试。
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{canManage && !activeCompaniesQuery.isLoading && !activeCompaniesQuery.isError && companyState.kind === "empty" ? (
|
||||
<div className="admin-command-panel space-y-4">
|
||||
<h3 className="text-base font-semibold text-zinc-900">新建法体</h3>
|
||||
<div>
|
||||
<h3 className="text-base font-semibold text-zinc-900">完善公司信息</h3>
|
||||
<p className="mt-1 text-sm text-zinc-600">系统仅服务当前公司。完成后,企业银行账户等配置会自动关联这家公司。</p>
|
||||
</div>
|
||||
<div className="grid gap-3 md:grid-cols-3">
|
||||
<div className="space-y-1">
|
||||
<Label htmlFor="legalEntityCode">编码</Label>
|
||||
@@ -387,15 +405,29 @@ export function MasterDataPage() {
|
||||
disabled={legalEntityCreateMutation.isPending || !legalEntityCode.trim() || !legalEntityName.trim() || !legalEntityCurrency.trim()}
|
||||
onClick={() => legalEntityCreateMutation.mutate()}
|
||||
>
|
||||
{legalEntityCreateMutation.isPending ? "创建中..." : "创建法体"}
|
||||
{legalEntityCreateMutation.isPending ? "创建中..." : "保存公司信息"}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{!activeCompaniesQuery.isLoading && !activeCompaniesQuery.isError && companyState.kind === "single" ? (
|
||||
<div className="admin-command-panel">
|
||||
<div className="text-sm font-medium text-zinc-900">当前公司:{companyState.company.name}</div>
|
||||
<div className="mt-1 text-sm text-zinc-600">系统按单公司运行,不需要选择或切换公司。</div>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{!activeCompaniesQuery.isLoading && !activeCompaniesQuery.isError && companyState.kind === "multiple" ? (
|
||||
<div className="admin-command-panel border-red-200 bg-red-50/70">
|
||||
<div className="text-sm font-medium text-red-700">检测到多条启用的公司信息</div>
|
||||
<div className="mt-1 text-sm text-red-600">系统不会自动选择或合并,请先停用多余记录后再继续关联配置。</div>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
<div className="admin-command-panel space-y-4">
|
||||
<h3 className="text-base font-semibold text-zinc-900">法体列表</h3>
|
||||
<h3 className="text-base font-semibold text-zinc-900">公司信息</h3>
|
||||
{legalEntitiesQuery.isLoading ? <TableSkeleton columns={6} rows={4} /> : null}
|
||||
{!legalEntitiesQuery.isLoading ? (
|
||||
<PrimaryTable className="ops-table-focus">
|
||||
@@ -443,7 +475,7 @@ export function MasterDataPage() {
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell colSpan={6} className="text-center text-sm text-zinc-500">
|
||||
暂无法体数据
|
||||
暂无公司信息
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
@@ -471,7 +503,7 @@ export function MasterDataPage() {
|
||||
value={costCenterLegalEntityFilter}
|
||||
onChange={(event) => setCostCenterLegalEntityFilter(event.target.value)}
|
||||
>
|
||||
<option value="">全部法体</option>
|
||||
<option value="">全部公司</option>
|
||||
{legalEntities
|
||||
.filter((item) => !item.archivedAt)
|
||||
.map((item) => (
|
||||
@@ -488,7 +520,7 @@ export function MasterDataPage() {
|
||||
<h3 className="text-base font-semibold text-zinc-900">新建成本中心</h3>
|
||||
<div className="grid gap-3 md:grid-cols-4">
|
||||
<div className="space-y-1 md:col-span-2">
|
||||
<Label htmlFor="costCenterLegalEntity">所属法体</Label>
|
||||
<Label htmlFor="costCenterLegalEntity">所属公司</Label>
|
||||
<select
|
||||
id="costCenterLegalEntity"
|
||||
className="select-std"
|
||||
@@ -498,7 +530,7 @@ export function MasterDataPage() {
|
||||
setCostCenterParentId("");
|
||||
}}
|
||||
>
|
||||
<option value="">请选择法体</option>
|
||||
<option value="">请选择公司</option>
|
||||
{legalEntities
|
||||
.filter((item) => !item.archivedAt)
|
||||
.map((item) => (
|
||||
@@ -561,7 +593,7 @@ export function MasterDataPage() {
|
||||
<TableRow>
|
||||
<TableHead>编码</TableHead>
|
||||
<TableHead>名称</TableHead>
|
||||
<TableHead>所属法体</TableHead>
|
||||
<TableHead>所属公司</TableHead>
|
||||
<TableHead>上级</TableHead>
|
||||
<TableHead>负责人</TableHead>
|
||||
<TableHead>状态</TableHead>
|
||||
|
||||
在新工单中引用
屏蔽一个用户