refactor: 设置页面调整-退休提醒独立tab+显示设置并入企业信息

- 退休提醒从企业信息中拆分为独立tab(RetirementSettings 独立 Card 组件)
- 显示设置从独立tab移入企业信息卡片底部(移除 DisplaySettings 组件)
- tab顺序:企业信息、用户管理、套餐、通知设置、退休提醒、数据导入、数据导出
This commit is contained in:
freedakgmail
2026-08-05 07:53:53 +08:00
parent 9512b555ee
commit 41b3030442
+27 -61
View File
@@ -14,7 +14,7 @@ import { useConfirm } from '../hooks/useConfirm'
export default function Settings() {
const queryClient = useQueryClient()
const [activeSection, setActiveSection] = useState<'org' | 'users' | 'plan' | 'notifications' | 'import' | 'export' | 'display'>('org')
const [activeSection, setActiveSection] = useState<'org' | 'users' | 'plan' | 'notifications' | 'retirement' | 'import' | 'export'>('org')
const { data: orgData } = useQuery<any>({
queryKey: ['org-settings'],
@@ -40,9 +40,9 @@ export default function Settings() {
{ key: 'users' as const, label: '用户管理', icon: Users },
{ key: 'plan' as const, label: '套餐', icon: CreditCard },
{ key: 'notifications' as const, label: '通知设置', icon: Bell },
{ key: 'retirement' as const, label: '退休提醒', icon: Clock },
{ key: 'import' as const, label: '数据导入', icon: FileSpreadsheet },
{ key: 'export' as const, label: '数据导出', icon: Download },
{ key: 'display' as const, label: '显示设置', icon: LayoutGrid },
]
return (
@@ -79,14 +79,17 @@ export default function Settings() {
{activeSection === 'users' && <UserSettings usersData={usersData} />}
{activeSection === 'plan' && <PlanSettings orgData={orgData} />}
{activeSection === 'notifications' && <NotificationSettings />}
{activeSection === 'retirement' && (
<RetirementSettings orgData={orgData} onSave={(data) => updateOrgMutation.mutate(data)} />
)}
{activeSection === 'import' && <ImportSettings />}
{activeSection === 'export' && <ExportSettings />}
{activeSection === 'display' && <DisplaySettings />}
</div>
)
}
function OrgSettings({ orgData, onSave, saving }: { orgData: any; onSave: (data: any) => void; saving: boolean }) {
const [pageSize, setPageSize] = useState(getPageSize())
const [form, setForm] = useState({
name: '',
contactName: '',
@@ -144,44 +147,36 @@ function OrgSettings({ orgData, onSave, saving }: { orgData: any; onSave: (data:
</Button>
</div>
<RetirementSection enabled={form.retirementReminderEnabled} onToggle={(v) => { setForm({ ...form, retirementReminderEnabled: v }); onSave({ ...form, retirementReminderEnabled: v }) }} />
{/* 电子签设置 */}
{/* 显示设置 */}
<div className="mt-6 pt-6 border-t">
<div className="flex items-center gap-2 mb-4">
<PenTool className="w-5 h-5 text-primary" />
<h3 className="font-medium"></h3>
<LayoutGrid className="w-5 h-5 text-primary" />
<h3 className="font-medium"></h3>
</div>
<p className="text-xs text-gray-500 mb-3">使/</p>
<div className="space-y-3">
{[
{ key: 'esignPolicyEnabled', label: '规章制度电子签', desc: '开启后制度签收升级为电子签署,缺省为阅读确认' },
{ key: 'esignPayslipEnabled', label: '工资条电子签', desc: '开启后工资条确认升级为电子签署,缺省为点击确认' },
{ key: 'esignOnboardingEnabled', label: '入职文件电子签', desc: '开启后入职填报时签署入职相关文件,缺省不签' },
].map(item => (
<div key={item.key} className="flex items-center justify-between p-3 rounded-lg bg-gray-50">
<div>
<div className="text-sm font-medium">{item.label}</div>
<div className="text-xs text-gray-500 mt-0.5">{item.desc}</div>
</div>
<button
type="button"
onClick={() => { const v = !form[item.key as keyof typeof form]; setForm({ ...form, [item.key]: v }); onSave({ ...form, [item.key]: v }) }}
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors shrink-0 ml-4 ${form[item.key as keyof typeof form] ? 'bg-primary' : 'bg-gray-300'}`}
>
<span className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${form[item.key as keyof typeof form] ? 'translate-x-6' : 'translate-x-1'}`} />
</button>
<div className="space-y-4">
<div>
<Label></Label>
<p className="text-xs text-gray-500 mt-1 mb-2"></p>
<div className="flex items-center gap-3">
<Select value={String(pageSize)} onChange={(e) => setPageSize(parseInt(e.target.value, 10))} className="!w-32">
<option value="10">10 /</option>
<option value="20">20 /</option>
<option value="50">50 /</option>
<option value="100">100 /</option>
</Select>
<Button size="sm" onClick={() => { setGlobalPageSize(pageSize); toast.success(`分页大小已设置为 ${pageSize} 条/页`) }}></Button>
</div>
))}
</div>
</div>
</div>
</Card>
)
}
function RetirementSection({ enabled, onToggle }: { enabled: boolean; onToggle: (v: boolean) => void }) {
function RetirementSettings({ orgData, onSave }: { orgData: any; onSave: (data: any) => void }) {
const queryClient = useQueryClient()
const [confirming, setConfirming] = useState(false)
const enabled = orgData?.retirementReminderEnabled || false
const { data: policyData, isLoading } = useQuery<any>({
queryKey: ['retirement-policy'],
@@ -229,7 +224,7 @@ function RetirementSection({ enabled, onToggle }: { enabled: boolean; onToggle:
)
return (
<div className="mt-6 pt-6 border-t">
<Card>
<div className="flex items-center justify-between mb-4">
<div className="flex items-center gap-2">
<Clock className="w-5 h-5 text-primary" />
@@ -248,7 +243,7 @@ function RetirementSection({ enabled, onToggle }: { enabled: boolean; onToggle:
<span className="text-sm text-gray-500">{enabled ? '已开启' : '未开启'}</span>
<button
type="button"
onClick={() => onToggle(!enabled)}
onClick={() => onSave({ retirementReminderEnabled: !enabled })}
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${enabled ? 'bg-primary' : 'bg-gray-300'}`}
>
<span className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${enabled ? 'translate-x-6' : 'translate-x-1'}`} />
@@ -293,7 +288,7 @@ function RetirementSection({ enabled, onToggle }: { enabled: boolean; onToggle:
{isLoading && <p className="text-sm text-gray-400 text-center">...</p>}
</div>
)}
</div>
</Card>
)
}
@@ -1327,32 +1322,3 @@ function MonthlyImport() {
)
}
function DisplaySettings() {
const [size, setSize] = useState(getPageSize())
const handleSave = () => {
setGlobalPageSize(size)
toast.success(`分页大小已设置为 ${size} 条/页`)
}
return (
<Card>
<h2 className="text-sm font-medium mb-4"></h2>
<div className="space-y-4">
<div>
<Label></Label>
<p className="text-xs text-gray-500 mt-1 mb-2"></p>
<div className="flex items-center gap-3">
<Select value={String(size)} onChange={(e) => setSize(parseInt(e.target.value, 10))} className="!w-32">
<option value="10">10 /</option>
<option value="20">20 /</option>
<option value="50">50 /</option>
<option value="100">100 /</option>
</Select>
<Button size="sm" onClick={handleSave}></Button>
</div>
</div>
</div>
</Card>
)
}