fix: 增加页签

This commit is contained in:
uiuJun 2025-07-25 16:42:54 +08:00
parent 067522c87a
commit ea64f4a95d
51 changed files with 5179 additions and 35822 deletions

View File

@ -15,7 +15,7 @@ export default defineConfig({
proxy: {
'/api/': {
// target: 'http://yt:8003',
target: 'http://10.39.13.80:8003',
target: 'http://10.39.13.80:8006',
// target: 'http://we6f9c65.natappfree.cc',
// target: 'https://loanos-test.nchl.net/',
changeOrigin: true,

1
.vercel/project.json Normal file
View File

@ -0,0 +1 @@
{"projectName":"trae_pay-admin_tj5u"}

View File

@ -1,4 +1,4 @@
{
"url": "http://10.39.13.80:8003/api/docs/openapi",
"url": "http://10.39.13.80:8006/api/docs/openapi",
"module": "Admin"
}

19173
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -11,7 +11,8 @@
},
"dependencies": {
"@ant-design/icons": "^5.0.1",
"@ant-design/pro-components": "^2.4.4",
"@ant-design/pro-components": "^2.8.10",
"@antv/g2": "^5.3.5",
"@antv/s2": "^2.0.0-next.25",
"@antv/s2-react": "^2.0.0-next.24",
"@umijs/max": "^4.3.10",

14149
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,49 @@
.tabs-header-only {
.ant-tabs-content-holder {
display: none !important;
}
.ant-tabs-tab {
position: relative;
&:hover {
.tab-close-btn {
opacity: 1;
}
}
}
.tab-close-btn {
opacity: 0;
transition: opacity 0.2s;
margin-left: 4px;
&:hover {
color: #ff4d4f;
}
}
.ant-tabs-tab-active {
.tab-close-btn {
opacity: 0.7;
}
}
}
// 右键菜单样式优化
.ant-dropdown-menu {
.ant-dropdown-menu-item {
&:hover {
background-color: #f5f5f5;
}
&.ant-dropdown-menu-item-disabled {
color: #bfbfbf;
cursor: not-allowed;
}
}
.ant-dropdown-menu-item-divider {
margin: 4px 0;
}
}

View File

@ -1,16 +1,342 @@
import { CloseOutlined, ReloadOutlined } from '@ant-design/icons';
import { PageContainer, PageContainerProps } from '@ant-design/pro-components';
import { Space } from 'antd';
import { history, useLocation } from '@umijs/max';
import type { MenuProps } from 'antd';
import { Dropdown, message, Space, Tabs } from 'antd';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import './MyPageContainer.scss';
export interface TabItem {
key: string;
label: string;
path: string;
closable?: boolean;
}
export interface MyPageContainerProps extends PageContainerProps {
enableTabs?: boolean;
tabKey?: string;
tabLabel?: string;
onTabChange?: (activeKey: string) => void;
}
// 全局标签页状态管理
class TabsManager {
private tabs: TabItem[] = [];
private activeKey: string = '';
private listeners: Set<() => void> = new Set();
subscribe(listener: () => void) {
this.listeners.add(listener);
return () => this.listeners.delete(listener);
}
private notify() {
this.listeners.forEach((listener) => listener());
}
getTabs() {
return this.tabs;
}
getActiveKey() {
return this.activeKey;
}
addTab(tab: TabItem) {
const existingIndex = this.tabs.findIndex((t) => t.key === tab.key);
if (existingIndex === -1) {
this.tabs.push(tab);
} else {
this.tabs[existingIndex] = { ...this.tabs[existingIndex], ...tab };
}
this.activeKey = tab.key;
this.notify();
}
removeTab(targetKey: string) {
const targetIndex = this.tabs.findIndex((tab) => tab.key === targetKey);
if (targetIndex === -1) return;
const newTabs = this.tabs.filter((tab) => tab.key !== targetKey);
if (newTabs.length === 0) {
this.tabs = [];
this.activeKey = '';
history.push('/');
} else {
this.tabs = newTabs;
if (this.activeKey === targetKey) {
// 如果关闭的是当前激活的标签,激活相邻的标签
const newActiveKey =
targetIndex > 0 ? newTabs[targetIndex - 1].key : newTabs[0].key;
this.activeKey = newActiveKey;
const targetTab = newTabs.find((tab) => tab.key === newActiveKey);
if (targetTab) {
history.push(targetTab.path);
}
}
}
this.notify();
}
setActiveKey(key: string) {
this.activeKey = key;
const targetTab = this.tabs.find((tab) => tab.key === key);
if (targetTab) {
history.push(targetTab.path);
}
this.notify();
}
closeOtherTabs(currentKey: string) {
const currentTab = this.tabs.find((tab) => tab.key === currentKey);
if (currentTab) {
this.tabs = [currentTab];
this.activeKey = currentKey;
this.notify();
}
}
closeLeftTabs(currentKey: string) {
const currentIndex = this.tabs.findIndex((tab) => tab.key === currentKey);
if (currentIndex > 0) {
this.tabs = this.tabs.slice(currentIndex);
this.notify();
}
}
closeRightTabs(currentKey: string) {
const currentIndex = this.tabs.findIndex((tab) => tab.key === currentKey);
if (currentIndex !== -1) {
this.tabs = this.tabs.slice(0, currentIndex + 1);
this.notify();
}
}
refreshTab(key: string) {
// 通过路由跳转的方式刷新当前标签页,避免整个页面刷新导致标签页状态丢失
const targetTab = this.tabs.find((tab) => tab.key === key);
if (targetTab) {
const originalPath = targetTab.path;
// 移除可能存在的刷新参数,确保获取干净的原始路径
const cleanPath = originalPath
.replace(/[?&]_refresh=\d+/g, '')
.replace(/\?$/, '');
// 添加时间戳参数强制刷新
const refreshPath = cleanPath.includes('?')
? `${cleanPath}&_refresh=${Date.now()}`
: `${cleanPath}?_refresh=${Date.now()}`;
// 先更新为带刷新参数的路径并跳转
targetTab.path = refreshPath;
this.setActiveKey(key);
// 延迟恢复原始路径,确保路由跳转完成
setTimeout(() => {
// 恢复为干净的原始路径
targetTab.path = cleanPath;
// 再次跳转到干净路径移除URL中的刷新参数
history.push(cleanPath);
this.notify();
}, 300);
}
}
}
// 全局标签页管理器实例
const tabsManager = new TabsManager();
export function MyPageContainer({
title,
children,
enableTabs = true,
tabKey,
tabLabel,
onTabChange,
...rest
}: PageContainerProps) {
}: MyPageContainerProps) {
const location = useLocation();
const [tabs, setTabs] = useState<TabItem[]>([]);
const [activeKey, setActiveKey] = useState<string>('');
const contextMenuRef = useRef<{
x: number;
y: number;
targetKey: string;
} | null>(null);
// 订阅标签页状态变化
useEffect(() => {
const unsubscribe = tabsManager.subscribe(() => {
setTabs([...tabsManager.getTabs()]);
setActiveKey(tabsManager.getActiveKey());
});
// 初始化状态
setTabs([...tabsManager.getTabs()]);
setActiveKey(tabsManager.getActiveKey());
return () => {
unsubscribe();
};
}, []);
// 当组件挂载时,添加当前页面到标签页
useEffect(() => {
if (enableTabs && tabKey && tabLabel) {
tabsManager.addTab({
key: tabKey,
label: tabLabel,
path: location.pathname + location.search,
closable: true,
});
}
}, [enableTabs, tabKey, tabLabel, location.pathname, location.search]);
const handleTabChange = useCallback(
(key: string) => {
tabsManager.setActiveKey(key);
onTabChange?.(key);
},
[onTabChange],
);
const handleTabEdit = useCallback(
(
targetKey: string | React.MouseEvent | React.KeyboardEvent,
action: 'add' | 'remove',
) => {
if (action === 'remove' && typeof targetKey === 'string') {
tabsManager.removeTab(targetKey);
}
},
[],
);
// 右键菜单配置
const getContextMenuItems = useCallback(
(targetKey: string): MenuProps['items'] => {
const currentIndex = tabs.findIndex((tab) => tab.key === targetKey);
const hasLeftTabs = currentIndex > 0;
const hasRightTabs = currentIndex < tabs.length - 1;
const hasOtherTabs = tabs.length > 1;
return [
{
key: 'refresh',
label: '刷新',
icon: <ReloadOutlined />,
onClick: () => tabsManager.refreshTab(targetKey),
},
{
key: 'close',
label: '关闭',
icon: <CloseOutlined />,
onClick: () => tabsManager.removeTab(targetKey),
},
{
type: 'divider',
},
{
key: 'closeOthers',
label: '关闭其他',
disabled: !hasOtherTabs,
onClick: () => {
tabsManager.closeOtherTabs(targetKey);
message.success('已关闭其他标签页');
},
},
{
key: 'closeLeft',
label: '关闭左侧',
disabled: !hasLeftTabs,
onClick: () => {
tabsManager.closeLeftTabs(targetKey);
message.success('已关闭左侧标签页');
},
},
{
key: 'closeRight',
label: '关闭右侧',
disabled: !hasRightTabs,
onClick: () => {
tabsManager.closeRightTabs(targetKey);
message.success('已关闭右侧标签页');
},
},
];
},
[tabs],
);
// 自定义标签页渲染
const renderTabBar: React.ComponentProps<typeof Tabs>['renderTabBar'] = (
props,
DefaultTabBar,
) => {
return (
<DefaultTabBar {...props}>
{(node) => {
const tabKey = node.key as string;
return (
<Dropdown
menu={{ items: getContextMenuItems(tabKey) }}
trigger={['contextMenu']}
>
<div>{node}</div>
</Dropdown>
);
}}
</DefaultTabBar>
);
};
if (!enableTabs || tabs.length === 0) {
return (
<PageContainer
fixedHeader
header={{
title: title,
style: { backgroundColor: '#FFF' },
}}
token={{
paddingBlockPageContainerContent: 0,
paddingInlinePageContainerContent: 0,
}}
{...rest}
>
<Space direction="vertical" size="middle" style={{ width: '100%' }}>
{children}
</Space>
</PageContainer>
);
}
return (
<PageContainer
fixedHeader
header={{
title: title,
title: (
<Tabs
type="editable-card"
activeKey={activeKey}
onChange={handleTabChange}
onEdit={handleTabEdit}
hideAdd
size="small"
renderTabBar={renderTabBar}
items={tabs.map((tab) => ({
key: tab.key,
label: tab.label,
closable: tab.closable,
}))}
style={{
marginBottom: 0,
}}
className="tabs-header-only"
/>
),
style: { backgroundColor: '#FFF' },
}}
token={{
@ -25,3 +351,6 @@ export function MyPageContainer({
</PageContainer>
);
}
// 导出标签页管理器,供其他组件使用
export { tabsManager };

View File

@ -5,10 +5,11 @@ import { MyLoading } from './MyLoading';
export function MyRootContainer({ children }: { children: ReactNode }) {
return (
<ConfigProvider
// 输入框圆角
theme={{
token: {
fontSize: 14,
borderRadius: 1,
borderRadius: 5,
// colorPrimary: '#00928a',
// colorInfo: '#00928a',
},

View File

@ -0,0 +1,294 @@
# MyPageContainer 多标签页功能
基于 Ant Design Pro Components 的企业级多标签页解决方案,提供完整的标签页管理功能。
## ✨ 特性
- 🎯 **多标签页支持** - 支持同时打开多个页面标签
- 🖱️ **右键菜单** - 丰富的标签页操作菜单
- 🔄 **智能导航** - 关闭标签时自动切换到相邻标签
- 💾 **状态管理** - 全局标签页状态管理
- 🎨 **主题适配** - 完美适配 Ant Design 主题
- 📱 **响应式设计** - 支持不同屏幕尺寸
## 🚀 快速开始
### 基础用法
```tsx
import { MyPageContainer, usePageTabs } from '@/common';
function UserListPage() {
// 使用 Hook 简化标签页管理
usePageTabs({
tabKey: 'user-list',
tabLabel: '用户列表'
});
return (
<MyPageContainer
enableTabs
tabKey="user-list"
tabLabel="用户列表"
title="用户管理"
>
{/* 页面内容 */}
<div>用户列表内容</div>
</MyPageContainer>
);
}
```
### 高级用法
```tsx
import { MyPageContainer, usePageTabs, tabsManager } from '@/common';
import { Button, Space } from 'antd';
import { history } from '@umijs/max';
function DashboardPage() {
const tabsApi = usePageTabs({
tabKey: 'dashboard',
tabLabel: '仪表盘',
closable: false // 首页不可关闭
});
const openUserPage = () => {
tabsApi.addTab({
key: 'user-list',
label: '用户列表',
path: '/users'
});
history.push('/users');
};
return (
<MyPageContainer
enableTabs
tabKey="dashboard"
tabLabel="仪表盘"
title="系统仪表盘"
>
<Space>
<Button type="primary" onClick={openUserPage}>
打开用户列表
</Button>
<Button onClick={() => tabsApi.closeOtherTabs()}>
关闭其他标签
</Button>
</Space>
</MyPageContainer>
);
}
```
## 📚 API 文档
### MyPageContainer Props
| 参数 | 说明 | 类型 | 默认值 |
|------|------|------|--------|
| enableTabs | 是否启用多标签页功能 | `boolean` | `true` |
| tabKey | 标签页唯一标识 | `string` | - |
| tabLabel | 标签页显示标题 | `string` | - |
| onTabChange | 标签页切换回调 | `(activeKey: string) => void` | - |
| ...rest | 继承 PageContainerProps 的所有属性 | `PageContainerProps` | - |
### usePageTabs Hook
#### 参数
```tsx
interface UsePageTabsOptions {
tabKey: string; // 标签页唯一标识
tabLabel: string; // 标签页显示标题
closable?: boolean; // 是否可关闭,默认 true
autoAdd?: boolean; // 是否自动添加,默认 true
}
```
#### 返回值
```tsx
interface UsePageTabsReturn {
addTab: (tab: TabItem) => void; // 添加标签页
removeTab: (key: string) => void; // 关闭标签页
switchTab: (key: string) => void; // 切换标签页
closeOtherTabs: (currentKey?: string) => void; // 关闭其他标签
closeLeftTabs: (currentKey?: string) => void; // 关闭左侧标签
closeRightTabs: (currentKey?: string) => void; // 关闭右侧标签
refreshTab: (key?: string) => void; // 刷新标签页
getTabs: () => TabItem[]; // 获取所有标签
getActiveKey: () => string; // 获取当前激活标签
}
```
### TabsManager 全局管理器
```tsx
import { tabsManager } from '@/common';
// 直接操作标签页管理器
tabsManager.addTab({
key: 'new-page',
label: '新页面',
path: '/new-page',
closable: true
});
// 监听标签页变化
const unsubscribe = tabsManager.subscribe(() => {
console.log('标签页状态已更新');
});
// 取消监听
unsubscribe();
```
## 🎨 样式定制
### CSS 变量
```scss
// 自定义标签页样式
.tabs-header-only {
.ant-tabs-tab {
// 标签页样式
&:hover {
background-color: #f5f5f5;
}
}
.ant-tabs-tab-active {
// 激活状态样式
background-color: #e6f7ff;
}
}
```
### 主题定制
```tsx
import { ConfigProvider } from 'antd';
<ConfigProvider
theme={{
components: {
Tabs: {
cardBg: '#ffffff',
itemActiveColor: '#1890ff',
itemHoverColor: '#40a9ff'
}
}
}}
>
<MyPageContainer enableTabs tabKey="page" tabLabel="页面" />
</ConfigProvider>
```
## 🔧 最佳实践
### 1. 标签页命名规范
```tsx
// ✅ 推荐:使用语义化的 key
usePageTabs({
tabKey: 'user-list',
tabLabel: '用户列表'
});
// ❌ 不推荐:使用随机或无意义的 key
usePageTabs({
tabKey: 'page1',
tabLabel: '页面1'
});
```
### 2. 路由集成
```tsx
// 在路由配置中使用
export default {
path: '/users',
component: () => import('./UserListPage'),
// 可以在路由元信息中定义标签页信息
meta: {
tabKey: 'user-list',
tabLabel: '用户列表'
}
};
```
### 3. 权限控制
```tsx
function ProtectedPage() {
const { hasPermission } = useAccess();
usePageTabs({
tabKey: 'admin-panel',
tabLabel: '管理面板',
// 根据权限决定是否可关闭
closable: hasPermission('admin')
});
return (
<MyPageContainer
enableTabs
tabKey="admin-panel"
tabLabel="管理面板"
>
{/* 内容 */}
</MyPageContainer>
);
}
```
### 4. 性能优化
```tsx
// 使用 React.memo 优化组件渲染
const OptimizedPage = React.memo(() => {
usePageTabs({
tabKey: 'heavy-page',
tabLabel: '重型页面'
});
return (
<MyPageContainer
enableTabs
tabKey="heavy-page"
tabLabel="重型页面"
>
{/* 复杂内容 */}
</MyPageContainer>
);
});
```
## 🐛 常见问题
### Q: 标签页不显示?
A: 确保设置了 `enableTabs={true}` 并提供了 `tabKey``tabLabel`
### Q: 右键菜单不工作?
A: 检查是否正确导入了 CSS 样式文件。
### Q: 标签页状态丢失?
A: 标签页状态是全局的,但在页面刷新后会重置。如需持久化,可以结合 localStorage 实现。
### Q: 如何禁用某些标签页的关闭功能?
A: 在添加标签页时设置 `closable: false`
## 🔄 更新日志
### v1.0.0
- ✨ 新增多标签页功能
- ✨ 新增右键菜单操作
- ✨ 新增 usePageTabs Hook
- ✨ 新增全局状态管理
- 🎨 优化样式和交互体验
## 📄 许可证
MIT License

View File

@ -0,0 +1,126 @@
import React from 'react';
import { Button, Card, Space, Divider } from 'antd';
import { PlusOutlined, UserOutlined, SettingOutlined } from '@ant-design/icons';
import { MyPageContainer } from './MyPageContainer';
import { usePageTabs } from './usePageTabs';
import { history } from '@umijs/max';
/**
* 使
* 使MyPageContainer的多标签页功能
*/
export function TabsExample() {
const tabsApi = usePageTabs({
tabKey: 'tabs-example',
tabLabel: '标签页示例'
});
const handleAddTab = (key: string, label: string, path: string) => {
tabsApi.addTab({
key,
label,
path,
closable: true
});
history.push(path);
};
return (
<MyPageContainer
enableTabs
tabKey="tabs-example"
tabLabel="标签页示例"
title="多标签页功能演示"
>
<Card title="标签页操作示例" style={{ marginBottom: 16 }}>
<Space wrap>
<Button
type="primary"
icon={<PlusOutlined />}
onClick={() => handleAddTab('user-list', '用户列表', '/users')}
>
</Button>
<Button
icon={<UserOutlined />}
onClick={() => handleAddTab('user-profile', '用户详情', '/users/profile')}
>
</Button>
<Button
icon={<SettingOutlined />}
onClick={() => handleAddTab('settings', '系统设置', '/settings')}
>
</Button>
</Space>
<Divider />
<Space wrap>
<Button onClick={() => tabsApi.closeOtherTabs()}>
</Button>
<Button onClick={() => tabsApi.closeLeftTabs()}>
</Button>
<Button onClick={() => tabsApi.closeRightTabs()}>
</Button>
<Button onClick={() => tabsApi.refreshTab()}>
</Button>
</Space>
</Card>
<Card title="功能说明">
<div style={{ lineHeight: '1.8' }}>
<h4>🎯 </h4>
<ul>
<li><strong></strong></li>
<li><strong></strong></li>
<li><strong></strong></li>
<li><strong></strong></li>
</ul>
<h4>🖱 </h4>
<ul>
<li><strong></strong></li>
<li><strong></strong></li>
<li><strong></strong></li>
<li><strong></strong></li>
<li><strong></strong></li>
</ul>
<h4>💻 使</h4>
<pre style={{ background: '#f5f5f5', padding: '12px', borderRadius: '4px' }}>
{`// 1. 在页面组件中使用
import { MyPageContainer, usePageTabs } from '@/common';
function YourPage() {
usePageTabs({
tabKey: 'your-page',
tabLabel: '页面标题'
});
return (
<MyPageContainer
enableTabs
tabKey="your-page"
tabLabel="页面标题"
>
{/* 页面内容 */}
</MyPageContainer>
);
}`}
</pre>
</div>
</Card>
</MyPageContainer>
);
}

View File

@ -0,0 +1,100 @@
import { useEffect } from 'react';
import { useLocation } from '@umijs/max';
import { tabsManager } from './MyPageContainer';
export interface UsePageTabsOptions {
/** 标签页的唯一标识 */
tabKey: string;
/** 标签页显示的标题 */
tabLabel: string;
/** 是否可关闭默认为true */
closable?: boolean;
/** 是否自动添加到标签页默认为true */
autoAdd?: boolean;
}
/**
* Hook
*
*/
export function usePageTabs(options: UsePageTabsOptions) {
const location = useLocation();
const { tabKey, tabLabel, closable = true, autoAdd = true } = options;
useEffect(() => {
if (autoAdd) {
tabsManager.addTab({
key: tabKey,
label: tabLabel,
path: location.pathname + location.search,
closable
});
}
}, [tabKey, tabLabel, closable, autoAdd, location.pathname, location.search]);
return {
/** 添加新标签页 */
addTab: (tab: { key: string; label: string; path?: string; closable?: boolean }) => {
tabsManager.addTab({
...tab,
path: tab.path || location.pathname + location.search,
closable: tab.closable ?? true
});
},
/** 关闭指定标签页 */
removeTab: (key: string) => {
tabsManager.removeTab(key);
},
/** 切换到指定标签页 */
switchTab: (key: string) => {
tabsManager.setActiveKey(key);
},
/** 关闭其他标签页 */
closeOtherTabs: (currentKey?: string) => {
tabsManager.closeOtherTabs(currentKey || tabKey);
},
/** 关闭左侧标签页 */
closeLeftTabs: (currentKey?: string) => {
tabsManager.closeLeftTabs(currentKey || tabKey);
},
/** 关闭右侧标签页 */
closeRightTabs: (currentKey?: string) => {
tabsManager.closeRightTabs(currentKey || tabKey);
},
/** 刷新标签页 */
refreshTab: (key?: string) => {
tabsManager.refreshTab(key || tabKey);
},
/** 获取当前所有标签页 */
getTabs: () => tabsManager.getTabs(),
/** 获取当前激活的标签页key */
getActiveKey: () => tabsManager.getActiveKey()
};
}
/**
* Hook
*
*/
export function useTabsManager() {
return {
tabsManager,
addTab: tabsManager.addTab.bind(tabsManager),
removeTab: tabsManager.removeTab.bind(tabsManager),
setActiveKey: tabsManager.setActiveKey.bind(tabsManager),
closeOtherTabs: tabsManager.closeOtherTabs.bind(tabsManager),
closeLeftTabs: tabsManager.closeLeftTabs.bind(tabsManager),
closeRightTabs: tabsManager.closeRightTabs.bind(tabsManager),
refreshTab: tabsManager.refreshTab.bind(tabsManager),
getTabs: tabsManager.getTabs.bind(tabsManager),
getActiveKey: tabsManager.getActiveKey.bind(tabsManager)
};
}

View File

@ -4,8 +4,9 @@ import { SortOrder } from 'antd/es/table/interface';
export const MyProTableProps = {
props: {
scroll: { x: 'max-content', scrollToFirstRowOnChange: true },
bordered: true,
size: 'small',
//修改列表的样式
// bordered: true,
size: 'middle',
rowKey: 'id',
pagination: {
showTotal: (total) => `总共${total}`,

View File

@ -153,13 +153,14 @@ export const MyColumns = {
},
EnumTag({ ...rest }: ReturnType): ReturnType {
return {
align: 'center',
align: 'left',
renderText(text: string | number) {
const _enum = rest.valueEnum ?? {};
if (!_enum) return <>-</>;
const item = _enum[text] ?? undefined;
if (!item) return <>-</>;
return <Tag color={item.color}>{item.text}</Tag>;
return <Tag style={{ color: item?.color }}>{item.text}</Tag>;
//修改列表的标签样式
},
...rest,
};

View File

@ -10,6 +10,8 @@ export * from './components/layout/MyCommonModal';
export * from './components/layout/MyImportModal';
export * from './components/layout/MyPageContainer';
export * from './components/layout/MyRootContainer';
export * from './components/layout/usePageTabs';
export * from './components/layout/TabsExample';
export * from './components/props/MyDrawerProps';
export * from './components/props/MyModalFormProps';

View File

@ -28,10 +28,11 @@ export const renderTextHelper = {
return data.value === '' + value;
});
return isColor ? (
<Tag color={item?.color}>{item?.text}</Tag>
<Tag style={{ color: item?.color }}>{item?.text}</Tag>
) : (
<>{item?.text}</>
);
// return <Tag style={{ color: item.color }}>{item.text}</Tag>;
},
Images(images: string[]) {
return (

View File

@ -35,6 +35,7 @@ declare namespace ApiTypes {
"house_name"?: string; // 模糊搜索:房屋名称
"type"?: string; // 类型,[enum:HouseRegistersTypeEnum]
"status"?: string; // 状态,[enum:HouseRegistersStatusEnum]
"asset_houses_id"?: number; // 房屋ID
};
type Store = {
"asset_houses_id": number; // 房屋ID
@ -57,6 +58,8 @@ declare namespace ApiTypes {
};
type MoveOut = {
"house_occupants_id": number; // 房客id
"move_out_date"?: Date; // 搬离时间
"apply_reason"?: string; // 搬离原因
};
type RemoveOwner = {
"house_occupants_id": number; // 房客id

View File

@ -1,290 +1,398 @@
// AssetHousesOrientationEnum
export const AssetHousesOrientationEnum= {
'East': {"text":"东","color":"#007bff","value":"East"},
'South': {"text":"南","color":"#28a745","value":"South"},
'West': {"text":"西","color":"#ffc107","value":"West"},
'North': {"text":"北","color":"#dc3545","value":"North"},
'Southeast': {"text":"东南","color":"#20c997","value":"Southeast"},
'Northeast': {"text":"东北","color":"#6f42c1","value":"Northeast"},
'Southwest': {"text":"西南","color":"#fd7e14","value":"Southwest"},
'Northwest': {"text":"西北","color":"#17a2b8","value":"Northwest"},
'EastWest': {"text":"东西","color":"#6610f2","value":"EastWest"},
'SouthNorth': {"text":"南北","color":"#e83e8c","value":"SouthNorth"},
export const AssetHousesOrientationEnum = {
East: { text: '东', color: '#007bff', value: 'East' },
South: { text: '南', color: '#28a745', value: 'South' },
West: { text: '西', color: '#ffc107', value: 'West' },
North: { text: '北', color: '#dc3545', value: 'North' },
Southeast: { text: '东南', color: '#20c997', value: 'Southeast' },
Northeast: { text: '东北', color: '#6f42c1', value: 'Northeast' },
Southwest: { text: '西南', color: '#fd7e14', value: 'Southwest' },
Northwest: { text: '西北', color: '#17a2b8', value: 'Northwest' },
EastWest: { text: '东西', color: '#6610f2', value: 'EastWest' },
SouthNorth: { text: '南北', color: '#e83e8c', value: 'SouthNorth' },
};
// AssetHousesOwnershipTypeEnum
export const AssetHousesOwnershipTypeEnum= {
'CommodityHousing': {"text":"商品房","color":"#007bff","value":"CommodityHousing"},
'FundedHousing': {"text":"集资房","color":"#28a745","value":"FundedHousing"},
'MilitaryHousing': {"text":"军产房","color":"#17a2b8","value":"MilitaryHousing"},
'AffordableHousing': {"text":"保障房","color":"#ffc107","value":"AffordableHousing"},
'RuralHousing': {"text":"农民房","color":"#6f42c1","value":"RuralHousing"},
'CommercialOffice': {"text":"商业写字楼","color":"#fd7e14","value":"CommercialOffice"},
'CommercialComplex': {"text":"商业综合体","color":"#dc3545","value":"CommercialComplex"},
'ResettlementHousing': {"text":"回迁房","color":"#20c997","value":"ResettlementHousing"},
export const AssetHousesOwnershipTypeEnum = {
CommodityHousing: {
text: '商品房',
color: '#007bff',
value: 'CommodityHousing',
},
FundedHousing: { text: '集资房', color: '#28a745', value: 'FundedHousing' },
MilitaryHousing: {
text: '军产房',
color: '#17a2b8',
value: 'MilitaryHousing',
},
AffordableHousing: {
text: '保障房',
color: '#ffc107',
value: 'AffordableHousing',
},
RuralHousing: { text: '农民房', color: '#6f42c1', value: 'RuralHousing' },
CommercialOffice: {
text: '商业写字楼',
color: '#fd7e14',
value: 'CommercialOffice',
},
CommercialComplex: {
text: '商业综合体',
color: '#dc3545',
value: 'CommercialComplex',
},
ResettlementHousing: {
text: '回迁房',
color: '#20c997',
value: 'ResettlementHousing',
},
};
// AssetHousesStatusEnum
export const AssetHousesStatusEnum= {
'Unsold': {"text":"未售","color":"#6c757d","value":"Unsold"},
'SoldNotDelivered': {"text":"已售未交房","color":"#ffc107","value":"SoldNotDelivered"},
'SelfOccupied': {"text":"自住","color":"#28a745","value":"SelfOccupied"},
'Rented': {"text":"出租","color":"#007bff","value":"Rented"},
'Vacant': {"text":"空置","color":"#dc3545","value":"Vacant"},
export const AssetHousesStatusEnum = {
Unsold: { text: '未售', color: '#6c757d', value: 'Unsold' },
SoldNotDelivered: {
text: '已售未交房',
color: '#ffc107',
value: 'SoldNotDelivered',
},
SelfOccupied: { text: '自住', color: '#28a745', value: 'SelfOccupied' },
Rented: { text: '出租', color: '#007bff', value: 'Rented' },
Vacant: { text: '空置', color: '#dc3545', value: 'Vacant' },
};
// AssetHousesUsageEnum
export const AssetHousesUsageEnum= {
'Residence': {"text":"住宅","color":"#007bff","value":"Residence"},
'Apartment': {"text":"公寓","color":"#28a745","value":"Apartment"},
'Villa': {"text":"别墅","color":"#17a2b8","value":"Villa"},
'Shop': {"text":"商铺","color":"#ffc107","value":"Shop"},
'ParkingSpace': {"text":"车位","color":"#6c757d","value":"ParkingSpace"},
'Office': {"text":"写字楼","color":"#6610f2","value":"Office"},
'Clubhouse': {"text":"会所","color":"#fd7e14","value":"Clubhouse"},
'PropertyRoom': {"text":"物业用房","color":"#dc3545","value":"PropertyRoom"},
export const AssetHousesUsageEnum = {
Residence: { text: '住宅', color: '#007bff', value: 'Residence' },
Apartment: { text: '公寓', color: '#28a745', value: 'Apartment' },
Villa: { text: '别墅', color: '#17a2b8', value: 'Villa' },
Shop: { text: '商铺', color: '#ffc107', value: 'Shop' },
ParkingSpace: { text: '车位', color: '#6c757d', value: 'ParkingSpace' },
Office: { text: '写字楼', color: '#6610f2', value: 'Office' },
Clubhouse: { text: '会所', color: '#fd7e14', value: 'Clubhouse' },
PropertyRoom: { text: '物业用房', color: '#dc3545', value: 'PropertyRoom' },
};
// AssetProjectsChargeEnum
export const AssetProjectsChargeEnum= {
'Contract': {"text":"包干制","color":"#007bff","value":"Contract"},
'Commission': {"text":"酬金制","color":"#28a745","value":"Commission"},
export const AssetProjectsChargeEnum = {
Contract: { text: '包干制', color: '#007bff', value: 'Contract' },
Commission: { text: '酬金制', color: '#28a745', value: 'Commission' },
};
// AssetProjectsEntrustTypeEnum
export const AssetProjectsEntrustTypeEnum= {
'DeveloperJointEntrust': {"text":"开发商全委","color":"#007bff","value":"DeveloperJointEntrust"},
'OwnersFullEntrust': {"text":"业委会全委","color":"#28a745","value":"OwnersFullEntrust"},
'GovernmentFullEntrust': {"text":"政府类全委","color":"#ffc107","value":"GovernmentFullEntrust"},
export const AssetProjectsEntrustTypeEnum = {
DeveloperJointEntrust: {
text: '开发商全委',
color: '#007bff',
value: 'DeveloperJointEntrust',
},
OwnersFullEntrust: {
text: '业委会全委',
color: '#28a745',
value: 'OwnersFullEntrust',
},
GovernmentFullEntrust: {
text: '政府类全委',
color: '#ffc107',
value: 'GovernmentFullEntrust',
},
};
// AssetProjectsPropertyTypeEnum
export const AssetProjectsPropertyTypeEnum= {
'Residence': {"text":"住宅","color":"#ff0000","value":"Residence"},
'Commercial': {"text":"商业","color":"#ff6600","value":"Commercial"},
'Office': {"text":"办公","color":"#ffcc00","value":"Office"},
'IndustrialPark': {"text":"产业园","color":"#00cc66","value":"IndustrialPark"},
'Complex': {"text":"综合体","color":"#0099ff","value":"Complex"},
'Municipal': {"text":"市政设施","color":"#6633cc","value":"Municipal"},
'Venue': {"text":"场馆","color":"#9966ff","value":"Venue"},
'Education': {"text":"教育","color":"#339999","value":"Education"},
'Medical': {"text":"医疗","color":"#cc3366","value":"Medical"},
export const AssetProjectsPropertyTypeEnum = {
Residence: { text: '住宅', color: '#ff0000', value: 'Residence' },
Commercial: { text: '商业', color: '#ff6600', value: 'Commercial' },
Office: { text: '办公', color: '#ffcc00', value: 'Office' },
IndustrialPark: { text: '产业园', color: '#00cc66', value: 'IndustrialPark' },
Complex: { text: '综合体', color: '#0099ff', value: 'Complex' },
Municipal: { text: '市政设施', color: '#6633cc', value: 'Municipal' },
Venue: { text: '场馆', color: '#9966ff', value: 'Venue' },
Education: { text: '教育', color: '#339999', value: 'Education' },
Medical: { text: '医疗', color: '#cc3366', value: 'Medical' },
};
// AssetProjectsStatusEnum
export const AssetProjectsStatusEnum= {
'SignedNotDelivered': {"text":"签约未交付","color":"#6c757d","value":"SignedNotDelivered"},
'RollingDevelopment': {"text":"滚动开发","color":"#007bff","value":"RollingDevelopment"},
'ManagedAndClosed': {"text":"在管封园","color":"#ffc107","value":"ManagedAndClosed"},
'Exited': {"text":"退出","color":"#dc3545","value":"Exited"},
export const AssetProjectsStatusEnum = {
SignedNotDelivered: {
text: '签约未交付',
color: '#6c757d',
value: 'SignedNotDelivered',
},
RollingDevelopment: {
text: '滚动开发',
color: '#007bff',
value: 'RollingDevelopment',
},
ManagedAndClosed: {
text: '在管封园',
color: '#ffc107',
value: 'ManagedAndClosed',
},
Exited: { text: '退出', color: '#dc3545', value: 'Exited' },
};
// AssetUnitsBuildingStructureEnum
export const AssetUnitsBuildingStructureEnum= {
'SteelConcrete': {"text":"钢混","color":"#007bff","value":"SteelConcrete"},
'SteelStructure': {"text":"钢结构","color":"#28a745","value":"SteelStructure"},
'BrickConcrete': {"text":"砖混","color":"#ffc107","value":"BrickConcrete"},
'BrickWood': {"text":"砖木","color":"#dc3545","value":"BrickWood"},
export const AssetUnitsBuildingStructureEnum = {
SteelConcrete: { text: '钢混', color: '#007bff', value: 'SteelConcrete' },
SteelStructure: { text: '钢结构', color: '#28a745', value: 'SteelStructure' },
BrickConcrete: { text: '砖混', color: '#ffc107', value: 'BrickConcrete' },
BrickWood: { text: '砖木', color: '#dc3545', value: 'BrickWood' },
};
// AssetUnitsBuildingTypeEnum
export const AssetUnitsBuildingTypeEnum= {
'SlabAndTower': {"text":"板塔结合","color":"#007bff","value":"SlabAndTower"},
'Slab': {"text":"板楼","color":"#28a745","value":"Slab"},
'Tower': {"text":"塔楼","color":"#ffc107","value":"Tower"},
export const AssetUnitsBuildingTypeEnum = {
SlabAndTower: { text: '板塔结合', color: '#007bff', value: 'SlabAndTower' },
Slab: { text: '板楼', color: '#28a745', value: 'Slab' },
Tower: { text: '塔楼', color: '#ffc107', value: 'Tower' },
};
// 缓存类型
export const CacheTypeEnum= {
'MobilePhoneVerificationCode': {"text":"手机验证码","color":"#6c905c","value":"MobilePhoneVerificationCode"},
export const CacheTypeEnum = {
MobilePhoneVerificationCode: {
text: '手机验证码',
color: '#012ab0',
value: 'MobilePhoneVerificationCode',
},
};
// CompaniesMerchantTypeEnum
export const CompaniesMerchantTypeEnum= {
'PropertyManagement': {"text":"物业公司","color":"#007bff","value":"PropertyManagement"},
'ServiceProvider': {"text":"服务商","color":"#28a745","value":"ServiceProvider"},
export const CompaniesMerchantTypeEnum = {
PropertyManagement: {
text: '物业公司',
color: '#007bff',
value: 'PropertyManagement',
},
ServiceProvider: {
text: '服务商',
color: '#28a745',
value: 'ServiceProvider',
},
};
// CompanyAppsAppTypeEnum
export const CompanyAppsAppTypeEnum= {
'MiniProgram': {"text":"微信小程序","color":"#3b82f6","value":"MiniProgram"},
'MpOfficial': {"text":"微信公众号","color":"#22c55e","value":"MpOfficial"},
'WorkWechat': {"text":"企业微信","color":"#6366f1","value":"WorkWechat"},
export const CompanyAppsAppTypeEnum = {
MiniProgram: { text: '微信小程序', color: '#3b82f6', value: 'MiniProgram' },
MpOfficial: { text: '微信公众号', color: '#22c55e', value: 'MpOfficial' },
WorkWechat: { text: '企业微信', color: '#6366f1', value: 'WorkWechat' },
};
// CompanyAppsModuleEnum
export const CompanyAppsModuleEnum= {
'Employee': {"text":"员工端","color":"#3b82f6","value":"Employee"},
'Customer': {"text":"客户端","color":"#10b981","value":"Customer"},
export const CompanyAppsModuleEnum = {
Employee: { text: '员工端', color: '#3b82f6', value: 'Employee' },
Customer: { text: '客户端', color: '#10b981', value: 'Customer' },
};
// CompanyReceiptAccountsPayChannelEnum
export const CompanyReceiptAccountsPayChannelEnum= {
'WeChat': {"text":"微信","color":"#07c160","value":"WeChat"},
'Alipay': {"text":"支付宝","color":"#1677ff","value":"Alipay"},
'BankTransfer': {"text":"银行转账","color":"#6c757d","value":"BankTransfer"},
'TongLian': {"text":"通联支付","color":"#ff9f0a","value":"TongLian"},
export const CompanyReceiptAccountsPayChannelEnum = {
WeChat: { text: '微信', color: '#07c160', value: 'WeChat' },
Alipay: { text: '支付宝', color: '#1677ff', value: 'Alipay' },
BankTransfer: { text: '银行转账', color: '#6c757d', value: 'BankTransfer' },
TongLian: { text: '通联支付', color: '#ff9f0a', value: 'TongLian' },
};
// CustomerBacklogsStatusEnum
export const CustomerBacklogsStatusEnum= {
'Pending': {"text":"待办","color":"#faad14","value":"Pending"},
'Done': {"text":"已办","color":"#52c41a","value":"Done"},
export const CustomerBacklogsStatusEnum = {
Pending: { text: '待办', color: '#faad14', value: 'Pending' },
Done: { text: '已办', color: '#52c41a', value: 'Done' },
};
// CustomerBacklogsTypeEnum
export const CustomerBacklogsTypeEnum= {
'RegisterApply': {"text":"登记申请","color":"#2db7f5","value":"RegisterApply"},
'PaymentPending': {"text":"费用待缴","color":"#faad14","value":"PaymentPending"},
'ContractTodo': {"text":"合同待办","color":"#722ed1","value":"ContractTodo"},
export const CustomerBacklogsTypeEnum = {
RegisterApply: { text: '登记申请', color: '#2db7f5', value: 'RegisterApply' },
PaymentPending: {
text: '费用待缴',
color: '#faad14',
value: 'PaymentPending',
},
ContractTodo: { text: '合同待办', color: '#722ed1', value: 'ContractTodo' },
};
// 账单状态枚举
export const HouseBillsBillStatusEnum= {
'PendingPayment': {"text":"待支付","color":"#facc15","value":"PendingPayment"},
'PartiallyPaid': {"text":"部分支付","color":"#60a5fa","value":"PartiallyPaid"},
'Paid': {"text":"已支付","color":"#10b981","value":"Paid"},
'Overdue': {"text":"已逾期","color":"#ef4444","value":"Overdue"},
'Cancelled': {"text":"已取消","color":"#9ca3af","value":"Cancelled"},
export const HouseBillsBillStatusEnum = {
PendingPayment: { text: '待支付', color: '#facc15', value: 'PendingPayment' },
PartiallyPaid: { text: '部分支付', color: '#60a5fa', value: 'PartiallyPaid' },
Paid: { text: '已支付', color: '#10b981', value: 'Paid' },
Overdue: { text: '已逾期', color: '#ef4444', value: 'Overdue' },
Cancelled: { text: '已取消', color: '#9ca3af', value: 'Cancelled' },
};
// 房屋账单类型枚举
export const HouseBillsTypeEnum= {
'PropertyFee': {"text":"物业费","color":"#3b82f6","value":"PropertyFee"},
'MaintenanceFund': {"text":"维修基金","color":"#10b981","value":"MaintenanceFund"},
'WaterFee': {"text":"水费","color":"#06b6d4","value":"WaterFee"},
'ElectricityFee': {"text":"电费","color":"#f59e0b","value":"ElectricityFee"},
'SharedWaterFee': {"text":"公摊水费","color":"#8b5cf6","value":"SharedWaterFee"},
'SharedElectricityFee': {"text":"公摊电费","color":"#ec4899","value":"SharedElectricityFee"},
export const HouseBillsTypeEnum = {
PropertyFee: { text: '物业费', color: '#3b82f6', value: 'PropertyFee' },
MaintenanceFund: {
text: '维修基金',
color: '#10b981',
value: 'MaintenanceFund',
},
WaterFee: { text: '水费', color: '#06b6d4', value: 'WaterFee' },
ElectricityFee: { text: '电费', color: '#f59e0b', value: 'ElectricityFee' },
SharedWaterFee: {
text: '公摊水费',
color: '#8b5cf6',
value: 'SharedWaterFee',
},
SharedElectricityFee: {
text: '公摊电费',
color: '#ec4899',
value: 'SharedElectricityFee',
},
};
// HouseOccupantsCardTypeEnum
export const HouseOccupantsCardTypeEnum= {
'MainlandID': {"text":"中国大陆居民身份证","color":"#2db7f5","value":"MainlandID"},
'HKPermit': {"text":"香港来往大陆通行证(回乡证)","color":"#fa8c16","value":"HKPermit"},
'MOPermit': {"text":"澳门来往大陆通行证(回乡证)","color":"#faad14","value":"MOPermit"},
'TWPermit': {"text":"台湾来往大陆通行证(台胞证)","color":"#87d068","value":"TWPermit"},
'Passport': {"text":"护照","color":"#108ee9","value":"Passport"},
'BusinessLicense': {"text":"营业执照","color":"#f5222d","value":"BusinessLicense"},
export const HouseOccupantsCardTypeEnum = {
MainlandID: {
text: '中国大陆居民身份证',
color: '#2db7f5',
value: 'MainlandID',
},
HKPermit: {
text: '香港来往大陆通行证(回乡证)',
color: '#fa8c16',
value: 'HKPermit',
},
MOPermit: {
text: '澳门来往大陆通行证(回乡证)',
color: '#faad14',
value: 'MOPermit',
},
TWPermit: {
text: '台湾来往大陆通行证(台胞证)',
color: '#87d068',
value: 'TWPermit',
},
Passport: { text: '护照', color: '#108ee9', value: 'Passport' },
BusinessLicense: {
text: '营业执照',
color: '#f5222d',
value: 'BusinessLicense',
},
};
// HouseOccupantsHouseRelationEnum
export const HouseOccupantsHouseRelationEnum= {
'Owner': {"text":"产权人","color":"#2db7f5","value":"Owner"},
'Resident': {"text":"住户","color":"#87d068","value":"Resident"},
'Tenant': {"text":"租客","color":"#fa8c16","value":"Tenant"},
export const HouseOccupantsHouseRelationEnum = {
Owner: { text: '产权人', color: '#2db7f5', value: 'Owner' },
Resident: { text: '住户', color: '#87d068', value: 'Resident' },
Tenant: { text: '租客', color: '#fa8c16', value: 'Tenant' },
};
// HouseOccupantsRelationWithOwnerEnum
export const HouseOccupantsRelationWithOwnerEnum= {
'Self': {"text":"本人","color":"#52c41a","value":"Self"},
'Spouse': {"text":"夫妻","color":"#2db7f5","value":"Spouse"},
'FatherSon': {"text":"父子","color":"#faad14","value":"FatherSon"},
'MotherSon': {"text":"母子","color":"#fa8c16","value":"MotherSon"},
'Children': {"text":"子女","color":"#87d068","value":"Children"},
'ContactPerson': {"text":"指定联系人","color":"#f5222d","value":"ContactPerson"},
export const HouseOccupantsRelationWithOwnerEnum = {
Self: { text: '本人', color: '#52c41a', value: 'Self' },
Spouse: { text: '夫妻', color: '#2db7f5', value: 'Spouse' },
FatherSon: { text: '父子', color: '#faad14', value: 'FatherSon' },
MotherSon: { text: '母子', color: '#fa8c16', value: 'MotherSon' },
Children: { text: '子女', color: '#87d068', value: 'Children' },
ContactPerson: {
text: '指定联系人',
color: '#f5222d',
value: 'ContactPerson',
},
};
// HouseOccupantsStatusEnum
export const HouseOccupantsStatusEnum= {
'Normal': {"text":"正常","color":"#52c41a","value":"Normal"},
'Unbound': {"text":"已解除","color":"#f5222d","value":"Unbound"},
export const HouseOccupantsStatusEnum = {
Normal: { text: '正常', color: '#52c41a', value: 'Normal' },
Unbound: { text: '已解除', color: '#f5222d', value: 'Unbound' },
};
// 订单状态枚举
export const HouseOrdersOrderStatusEnum= {
'Pending': {"text":"待支付","color":"#facc15","value":"Pending"},
'Paid': {"text":"已支付","color":"#10b981","value":"Paid"},
'Refunded': {"text":"已退款","color":"#60a5fa","value":"Refunded"},
'Cancelled': {"text":"已取消","color":"#9ca3af","value":"Cancelled"},
'Failed': {"text":"支付失败","color":"#ef4444","value":"Failed"},
export const HouseOrdersOrderStatusEnum = {
Pending: { text: '待支付', color: '#facc15', value: 'Pending' },
Paid: { text: '已支付', color: '#10b981', value: 'Paid' },
Refunded: { text: '已退款', color: '#60a5fa', value: 'Refunded' },
Cancelled: { text: '已取消', color: '#9ca3af', value: 'Cancelled' },
Failed: { text: '支付失败', color: '#ef4444', value: 'Failed' },
};
// HouseOrdersPaymentMethodEnum
export const HouseOrdersPaymentMethodEnum= {
'WeChat': {"text":"微信","color":"#07c160","value":"WeChat"},
'Alipay': {"text":"支付宝","color":"#1677ff","value":"Alipay"},
'BankTransfer': {"text":"银行转账","color":"#6c757d","value":"BankTransfer"},
'TongLian': {"text":"通联支付","color":"#ff9f0a","value":"TongLian"},
export const HouseOrdersPaymentMethodEnum = {
WeChat: { text: '微信', color: '#07c160', value: 'WeChat' },
Alipay: { text: '支付宝', color: '#1677ff', value: 'Alipay' },
BankTransfer: { text: '银行转账', color: '#6c757d', value: 'BankTransfer' },
TongLian: { text: '通联支付', color: '#ff9f0a', value: 'TongLian' },
};
// HouseRegistersCustomerTypeEnum
export const HouseRegistersCustomerTypeEnum= {
'Individual': {"text":"个人客户","color":"#2db7f5","value":"Individual"},
'Enterprise': {"text":"普通企业","color":"#87d068","value":"Enterprise"},
'Developer': {"text":"开发企业","color":"#fa8c16","value":"Developer"},
'Government': {"text":"政府组织","color":"#f5222d","value":"Government"},
export const HouseRegistersCustomerTypeEnum = {
Individual: { text: '个人客户', color: '#2db7f5', value: 'Individual' },
Enterprise: { text: '普通企业', color: '#87d068', value: 'Enterprise' },
Developer: { text: '开发企业', color: '#fa8c16', value: 'Developer' },
Government: { text: '政府组织', color: '#f5222d', value: 'Government' },
};
// HouseRegistersHouseStatusEnum
export const HouseRegistersHouseStatusEnum= {
'SelfOccupied': {"text":"自住","color":"#28a745","value":"SelfOccupied"},
'Rented': {"text":"出租","color":"#007bff","value":"Rented"},
'Vacant': {"text":"空置","color":"#dc3545","value":"Vacant"},
export const HouseRegistersHouseStatusEnum = {
SelfOccupied: { text: '自住', color: '#28a745', value: 'SelfOccupied' },
Rented: { text: '出租', color: '#007bff', value: 'Rented' },
Vacant: { text: '空置', color: '#dc3545', value: 'Vacant' },
};
// 房屋登记身份类型
export const HouseRegistersIdentityTypeEnum= {
'Owner': {"text":"产权人","color":"#2db7f5","value":"Owner"},
'Tenant': {"text":"租客","color":"#87d068","value":"Tenant"},
'CoResident': {"text":"同住人(亲属)","color":"#108ee9","value":"CoResident"},
export const HouseRegistersIdentityTypeEnum = {
Owner: { text: '产权人', color: '#2db7f5', value: 'Owner' },
Tenant: { text: '租客', color: '#87d068', value: 'Tenant' },
CoResident: { text: '同住人(亲属)', color: '#108ee9', value: 'CoResident' },
};
// HouseRegistersStatusEnum
export const HouseRegistersStatusEnum= {
'Pending': {"text":"待审","color":"#faad14","value":"Pending"},
'Approved': {"text":"已审","color":"#52c41a","value":"Approved"},
'Rejected': {"text":"驳回","color":"#f5222d","value":"Rejected"},
export const HouseRegistersStatusEnum = {
Pending: { text: '待审', color: '#faad14', value: 'Pending' },
Approved: { text: '已审', color: '#52c41a', value: 'Approved' },
Rejected: { text: '驳回', color: '#f5222d', value: 'Rejected' },
};
// HouseRegistersTypeEnum
export const HouseRegistersTypeEnum= {
'Delivery': {"text":"交付登记","color":"#2db7f5","value":"Delivery"},
'Transfer': {"text":"过户登记","color":"#87d068","value":"Transfer"},
'AddOccupant': {"text":"添加住户","color":"#108ee9","value":"AddOccupant"},
'MoveOut': {"text":"搬离登记","color":"#f50","value":"MoveOut"},
'RemoveOwner': {"text":"减少产权人","color":"#d9363e","value":"RemoveOwner"},
export const HouseRegistersTypeEnum = {
Delivery: { text: '入户登记', color: '#2db7f5', value: 'Delivery' },
Transfer: { text: '过户登记', color: '#87d068', value: 'Transfer' },
AddOccupant: { text: '添加住户', color: '#108ee9', value: 'AddOccupant' },
MoveOut: { text: '搬离登记', color: '#f50', value: 'MoveOut' },
MoveIn: { text: '搬入登记', color: '#ffc53d', value: 'MoveIn' },
RemoveOwner: { text: '减少产权人', color: '#d9363e', value: 'RemoveOwner' },
};
// HouseRegistersUsagePlanEnum
export const HouseRegistersUsagePlanEnum= {
'Permanent': {"text":"常住","color":"#52c41a","value":"Permanent"},
'Vacation': {"text":"度假","color":"#faad14","value":"Vacation"},
'Rental': {"text":"出租","color":"#2db7f5","value":"Rental"},
'Commercial': {"text":"商用","color":"#f5222d","value":"Commercial"},
export const HouseRegistersUsagePlanEnum = {
Permanent: { text: '常住', color: '#52c41a', value: 'Permanent' },
Vacation: { text: '度假', color: '#faad14', value: 'Vacation' },
Rental: { text: '出租', color: '#2db7f5', value: 'Rental' },
Commercial: { text: '商用', color: '#f5222d', value: 'Commercial' },
};
// OrganizationsTypeEnum
export const OrganizationsTypeEnum= {
'Group': {"text":"集团","color":"#007bff","value":"Group"},
'Company': {"text":"公司","color":"#28a745","value":"Company"},
'ManagementOffice': {"text":"管理处","color":"#ffc107","value":"ManagementOffice"},
'Department': {"text":"部门","color":"#dc3545","value":"Department"},
export const OrganizationsTypeEnum = {
Group: { text: '集团', color: '#007bff', value: 'Group' },
Company: { text: '公司', color: '#28a745', value: 'Company' },
ManagementOffice: {
text: '管理处',
color: '#ffc107',
value: 'ManagementOffice',
},
Department: { text: '部门', color: '#dc3545', value: 'Department' },
};
// 性别
export const SexEnum= {
'Male': {"text":"男","color":"#0000ff","value":"Male"},
'FeMale': {"text":"女","color":"#ff0000","value":"FeMale"},
export const SexEnum = {
Male: { text: '男', color: '#0000ff', value: 'Male' },
FeMale: { text: '女', color: '#ff0000', value: 'FeMale' },
};
// SysModuleEnum
export const SysModuleEnum= {
'Admin': {"text":"管理员","color":"#cf1322","value":"Admin"},
'Customer': {"text":"客户","color":"#d4b106","value":"Customer"},
export const SysModuleEnum = {
Admin: { text: '管理员', color: '#cf1322', value: 'Admin' },
Customer: { text: '客户', color: '#d4b106', value: 'Customer' },
};
// SysPermissionsTypeEnum
export const SysPermissionsTypeEnum= {
'Directory': {"text":"目录","color":"#6d7e14","value":"Directory"},
'Page': {"text":"页面","color":"#4d9a13","value":"Page"},
'Button': {"text":"按钮","color":"#97224f","value":"Button"},
export const SysPermissionsTypeEnum = {
Directory: { text: '目录', color: '#6d7e14', value: 'Directory' },
Page: { text: '页面', color: '#4d9a13', value: 'Page' },
Button: { text: '按钮', color: '#97224f', value: 'Button' },
};
// WechatAuthsPlatformEnum
export const WechatAuthsPlatformEnum= {
'MiniProgram': {"text":"微信小程序","color":"#3b82f6","value":"MiniProgram"},
'MpOfficial': {"text":"微信公众号","color":"#22c55e","value":"MpOfficial"},
'WorkWechat': {"text":"企业微信","color":"#6366f1","value":"WorkWechat"},
export const WechatAuthsPlatformEnum = {
MiniProgram: { text: '微信小程序', color: '#3b82f6', value: 'MiniProgram' },
MpOfficial: { text: '微信公众号', color: '#22c55e', value: 'MpOfficial' },
WorkWechat: { text: '企业微信', color: '#6366f1', value: 'WorkWechat' },
};

View File

@ -5,7 +5,9 @@ import { useParams } from '@umijs/max';
import { Tabs } from 'antd';
import { useEffect, useState } from 'react';
import HouseInfo from './components/HouseInfo';
import OccupantsHistory from './table/OccupantsHistory';
import OccupantsNow from './table/OccupantsNow';
import RegistersList from './table/RegistersList';
export default function Show({ title = '房屋详情' }) {
const { id } = useParams<{ id: string }>();
@ -22,21 +24,29 @@ export default function Show({ title = '房屋详情' }) {
let items = [
{
label: '当前档案',
label: '当前客户',
key: '1',
closable: false,
children: (
children: data?.id ? (
<OccupantsNow
item={{ asset_houses_id: id }}
item={{ ...data, asset_houses_id: id }}
reload={() => loadShow()}
/>
) : (
''
),
},
{
label: '历史档案',
label: '历史客户',
key: '2',
closable: false,
// children: <MyAssetBuildings item={data} />,
children: <OccupantsHistory item={{ ...data, asset_houses_id: id }} />,
},
{
label: '操作记录',
key: '3',
closable: false,
children: <RegistersList item={{ ...data, asset_houses_id: id }} />,
},
];

View File

@ -3,6 +3,7 @@ import {
MyColumns,
MyPageContainer,
MyProTableProps,
usePageTabs,
} from '@/common';
import { Apis } from '@/gen/Apis';
import {
@ -17,7 +18,11 @@ import Delivery from './modals/Delivery';
export default function Index({ title = '房屋档案' }) {
const navigate = useNavigate();
// 注册当前页面为标签页
usePageTabs({
tabKey: 'archive-asset-houses',
tabLabel: title,
});
return (
<MyPageContainer title={title}>
<ProTable
@ -39,21 +44,20 @@ export default function Index({ title = '房屋档案' }) {
dataIndex: 'usage',
valueEnum: AssetHousesUsageEnum,
search: false,
width: 80,
}),
{
title: '房屋名称',
dataIndex: 'full_name',
},
{
title: '楼层',
dataIndex: 'floor',
render(_, record) {
return `${record?.floor}`;
},
search: false,
width: 60,
},
// {
// title: '楼层',
// dataIndex: 'floor',
// render(_, record) {
// return `${record?.floor}层`;
// },
// search: false,
// width: 60,
// },
{
title: '建筑面积',
dataIndex: 'built_area',
@ -63,15 +67,15 @@ export default function Index({ title = '房屋档案' }) {
search: false,
width: 80,
},
{
title: '套内面积',
dataIndex: 'inside_area',
render(_, record) {
return `${record?.inside_area}`;
},
search: false,
width: 80,
},
// {
// title: '套内面积',
// dataIndex: 'inside_area',
// render(_, record) {
// return `${record?.inside_area} m²`;
// },
// search: false,
// width: 80,
// },
{
title: '计费面积',
dataIndex: 'chargeable_area',
@ -81,7 +85,19 @@ export default function Index({ title = '房屋档案' }) {
search: false,
width: 80,
},
{
title: '产权人',
render(_, record) {
return (
record?.house_occupants
?.filter((res: any) => res?.house_relation !== 'Resident') // 过滤掉 Resident
.map((res: any) => res?.name)
.join(';') || '-'
); // 无数据时显示 -
},
search: false,
width: 200,
},
MyColumns.EnumTag({
title: '房屋状态',
dataIndex: 'status',

View File

@ -80,7 +80,7 @@ export default function Create(props: MyBetaModalFormProps) {
MyFormItems.EnumRadio({
key: 'house_relation',
title: '房客关系',
colProps: { span: 4 },
colProps: { span: 6 },
valueEnum: () => {
let obj: any = JSON.parse(
JSON.stringify(HouseOccupantsHouseRelationEnum),
@ -98,8 +98,8 @@ export default function Create(props: MyBetaModalFormProps) {
? [
MyFormItems.EnumRadio({
key: 'relation_with_owner',
title: '住户类型',
colProps: { span: 12 },
title: '关系标记',
colProps: { span: 18 },
valueEnum: () => {
let obj: any = JSON.parse(
JSON.stringify(
@ -116,8 +116,8 @@ export default function Create(props: MyBetaModalFormProps) {
: [
MyFormItems.EnumRadio({
key: 'relation_with_owner',
title: '住户类型',
colProps: { span: 12 },
title: '关系标记',
colProps: { span: 18 },
// valueEnum: HouseOccupantsRelationWithOwnerEnum,
valueEnum: () => {
let obj: any = JSON.parse(
@ -133,32 +133,7 @@ export default function Create(props: MyBetaModalFormProps) {
];
},
},
{
title: '是否入住',
dataIndex: 'is_live_in',
colProps: { span: 4 },
valueType: 'switch',
},
{
name: ['is_live_in'],
valueType: 'dependency',
columns: ({ is_live_in }: any) => {
return is_live_in
? [
{
title: '入住日期',
dataIndex: 'move_in_date',
valueType: 'date',
colProps: { span: 4 },
fieldProps: {
style: { width: '100%' },
},
formItemProps: { ...rulesHelper.text },
},
]
: [,];
},
},
{
title: '姓名',
dataIndex: 'name',
@ -205,9 +180,35 @@ export default function Create(props: MyBetaModalFormProps) {
key: 'card_back_image',
title: '证件反面',
max: 1,
colProps: { span: 4 },
colProps: { span: 8 },
formItemProps: { ...rulesHelper.text },
}),
{
title: '是否入住',
dataIndex: 'is_live_in',
colProps: { span: 6 },
valueType: 'switch',
},
{
name: ['is_live_in'],
valueType: 'dependency',
columns: ({ is_live_in }: any) => {
return is_live_in
? [
{
title: '入住日期',
dataIndex: 'move_in_date',
valueType: 'date',
colProps: { span: 6 },
fieldProps: {
style: { width: '100%' },
},
formItemProps: { ...rulesHelper.text },
},
]
: [];
},
},
],
},
],

View File

@ -9,7 +9,6 @@ import { Apis } from '@/gen/Apis';
import {
HouseOccupantsCardTypeEnum,
HouseOccupantsHouseRelationEnum,
HouseRegistersCustomerTypeEnum,
} from '@/gen/Enums';
import { BetaSchemaForm, ProCard } from '@ant-design/pro-components';
import { Form, message } from 'antd';
@ -19,23 +18,31 @@ export default function Create(props: MyBetaModalFormProps) {
return (
<BetaSchemaForm<ApiTypes.Archive.HouseRegisters.Store>
{...MyModalFormProps.props}
title={`添加${props.title}`}
title={`${props.title}`}
wrapperCol={{ span: 24 }}
width="900px"
form={form}
trigger={
<MyButtons.Default title={props.title} size="middle" type="primary" />
<MyButtons.Default title={props.title} type="primary" size="middle" />
}
onOpenChange={(open: any) => {
if (open) {
form.resetFields(); // 清空表单数据
}
}}
onFinish={async (values) =>
onFinish={async (values: any) =>
Apis.Archive.HouseRegisters.Store({
...values,
asset_houses_id: props?.item?.asset_houses_id,
type: 'Delivery',
house_status: props?.item?.status,
customer_info: values.customer_info?.map((res: any) => {
return {
...res,
house_relation: 'Owner',
relation_with_owner: 'Self',
};
}),
})
.then(() => {
props.reload?.();
@ -45,26 +52,6 @@ export default function Create(props: MyBetaModalFormProps) {
.catch(() => false)
}
columns={[
MyFormItems.EnumRadio({
key: 'house_relation',
title: '住户类型',
colProps: { span: 6 },
valueEnum: () => {
let obj: any = JSON.parse(
JSON.stringify(HouseOccupantsHouseRelationEnum),
);
delete obj.Resident;
delete obj.Tenant;
return obj;
},
required: true,
}),
MyFormItems.EnumRadio({
key: 'customer_type',
title: '客户类型',
colProps: { span: 12 },
valueEnum: HouseRegistersCustomerTypeEnum,
}),
{
valueType: 'formList',
dataIndex: 'customer_info',
@ -100,49 +87,44 @@ export default function Create(props: MyBetaModalFormProps) {
{
title: '姓名',
dataIndex: 'name',
colProps: { span: 12 },
colProps: { span: 5 },
formItemProps: { ...rulesHelper.text },
},
{
title: '手机号',
dataIndex: 'phone',
colProps: { span: 6 },
fieldProps: {
maxLength: 11,
},
formItemProps: { ...rulesHelper.text },
},
{
title: '备用手机号',
dataIndex: 'reserve_phone',
colProps: { span: 6 },
colProps: { span: 5 },
fieldProps: {
maxLength: 11,
},
formItemProps: { ...rulesHelper.phone },
},
MyFormItems.EnumSelect({
key: 'card_type',
title: '证件类型',
colProps: { span: 12 },
colProps: { span: 6 },
valueEnum: HouseOccupantsCardTypeEnum,
required: true,
}),
{
title: '证件号码',
dataIndex: 'id_card',
colProps: { span: 12 },
colProps: { span: 8 },
fieldProps: {
maxLength: 18,
},
formItemProps: { ...rulesHelper.text },
},
// {
// title: '是否在居住中',
// dataIndex: 'is_live_in',
// colProps: { span: 8 },
// valueType: 'switch',
// },
MyFormItems.EnumRadio({
key: 'house_relation',
title: '住户类型',
colProps: { span: 6 },
valueEnum: HouseOccupantsHouseRelationEnum,
fieldProps: {
defaultValue: 'Owner',
},
hideInForm: true,
}),
{
valueType: 'group',
columns: [
@ -157,9 +139,35 @@ export default function Create(props: MyBetaModalFormProps) {
key: 'card_back_image',
title: '证件反面',
max: 1,
colProps: { span: 4 },
colProps: { span: 8 },
formItemProps: { ...rulesHelper.text },
}),
{
title: '是否入住',
dataIndex: 'is_live_in',
colProps: { span: 6 },
valueType: 'switch',
},
{
name: ['is_live_in'],
valueType: 'dependency',
columns: ({ is_live_in }: any) => {
return is_live_in
? [
{
title: '入住日期',
dataIndex: 'move_in_date',
valueType: 'date',
colProps: { span: 6 },
fieldProps: {
style: { width: '100%' },
},
formItemProps: { ...rulesHelper.text },
},
]
: [];
},
},
],
},
],

View File

@ -8,9 +8,9 @@ import {
import { Apis } from '@/gen/Apis';
import {
HouseOccupantsCardTypeEnum,
HouseOccupantsHouseRelationEnum,
HouseRegistersCustomerTypeEnum,
HouseRegistersHouseStatusEnum,
HouseRegistersUsagePlanEnum,
} from '@/gen/Enums';
import { BetaSchemaForm, ProCard } from '@ant-design/pro-components';
import { Form, message } from 'antd';
@ -32,11 +32,18 @@ export default function Create(props: MyBetaModalFormProps) {
form.resetFields(); // 清空表单数据
}
}}
onFinish={async (values) =>
onFinish={async (values: any) =>
Apis.Archive.HouseRegisters.Store({
...values,
asset_houses_id: props?.item?.id,
type: 'Delivery',
customer_info: values.customer_info?.map((res: any) => {
return {
...res,
house_relation: 'Owner',
relation_with_owner: 'Self',
};
}),
})
.then(() => {
props.reload?.();
@ -59,12 +66,6 @@ export default function Create(props: MyBetaModalFormProps) {
valueEnum: HouseRegistersHouseStatusEnum,
formItemProps: { ...rulesHelper.text },
}),
MyFormItems.EnumSelect({
key: 'usage_plan',
title: '使用计划',
colProps: { span: 6 },
valueEnum: HouseRegistersUsagePlanEnum,
}),
{
valueType: 'formList',
dataIndex: 'customer_info',
@ -100,49 +101,44 @@ export default function Create(props: MyBetaModalFormProps) {
{
title: '姓名',
dataIndex: 'name',
colProps: { span: 12 },
colProps: { span: 5 },
formItemProps: { ...rulesHelper.text },
},
{
title: '手机号',
dataIndex: 'phone',
colProps: { span: 6 },
fieldProps: {
maxLength: 11,
},
formItemProps: { ...rulesHelper.text },
},
{
title: '备用手机号',
dataIndex: 'reserve_phone',
colProps: { span: 6 },
colProps: { span: 5 },
fieldProps: {
maxLength: 11,
},
formItemProps: { ...rulesHelper.phone },
},
MyFormItems.EnumSelect({
key: 'card_type',
title: '证件类型',
colProps: { span: 12 },
colProps: { span: 6 },
valueEnum: HouseOccupantsCardTypeEnum,
required: true,
}),
{
title: '证件号码',
dataIndex: 'id_card',
colProps: { span: 12 },
colProps: { span: 8 },
fieldProps: {
maxLength: 18,
},
formItemProps: { ...rulesHelper.text },
},
// {
// title: '是否在居住中',
// dataIndex: 'is_live_in',
// colProps: { span: 8 },
// valueType: 'switch',
// },
MyFormItems.EnumRadio({
key: 'house_relation',
title: '住户类型',
colProps: { span: 6 },
valueEnum: HouseOccupantsHouseRelationEnum,
fieldProps: {
defaultValue: 'Owner',
},
hideInForm: true,
}),
{
valueType: 'group',
columns: [
@ -157,9 +153,35 @@ export default function Create(props: MyBetaModalFormProps) {
key: 'card_back_image',
title: '证件反面',
max: 1,
colProps: { span: 4 },
colProps: { span: 8 },
formItemProps: { ...rulesHelper.text },
}),
{
title: '是否入住',
dataIndex: 'is_live_in',
colProps: { span: 6 },
valueType: 'switch',
},
{
name: ['is_live_in'],
valueType: 'dependency',
columns: ({ is_live_in }: any) => {
return is_live_in
? [
{
title: '入住日期',
dataIndex: 'move_in_date',
valueType: 'date',
colProps: { span: 6 },
fieldProps: {
style: { width: '100%' },
},
formItemProps: { ...rulesHelper.text },
},
]
: [];
},
},
],
},
],

View File

@ -1,31 +1,48 @@
import { MyBetaModalFormProps, MyButtons, MyModalFormProps } from '@/common';
import {
MyBetaModalFormProps,
MyButtons,
MyFormItems,
MyModalFormProps,
rulesHelper,
} from '@/common';
import { Apis } from '@/gen/Apis';
import { BetaSchemaForm } from '@ant-design/pro-components';
import {
HouseOccupantsCardTypeEnum,
HouseOccupantsHouseRelationEnum,
} from '@/gen/Enums';
import { BetaSchemaForm, ProCard } from '@ant-design/pro-components';
import { Form, message } from 'antd';
export default function Create(props: MyBetaModalFormProps) {
const [form] = Form.useForm();
return (
<BetaSchemaForm<ApiTypes.Archive.HouseRegisters.Update>
<BetaSchemaForm<ApiTypes.Archive.HouseRegisters.Store>
{...MyModalFormProps.props}
title={`添加${props.title}`}
title={`${props.title}`}
wrapperCol={{ span: 24 }}
width="500px"
width="900px"
form={form}
trigger={
<MyButtons.Default title={props.title} type="primary" size="middle" />
}
onOpenChange={(open: any) => {
if (open && props.item) {
form.setFieldsValue(props.item);
if (open) {
form.resetFields(); // 清空表单数据
}
}}
trigger={
<MyButtons.Default title={props.title} size="small" type="link" />
}
onFinish={async (values) =>
Apis.Archive.HouseRegisters.Update({
onFinish={async (values: any) =>
Apis.Archive.HouseRegisters.Store({
...values,
id: props?.item?.id ?? 0,
is_live_in: 1,
customer_info: props?.item?.id,
asset_houses_id: props?.item?.asset_houses_id,
type: 'Delivery',
house_status: props?.item?.status,
customer_info: values.customer_info?.map((res: any) => {
return {
...res,
house_relation: 'Owner',
relation_with_owner: 'Self',
};
}),
})
.then(() => {
props.reload?.();
@ -36,16 +53,126 @@ export default function Create(props: MyBetaModalFormProps) {
}
columns={[
{
title: '入住日期',
valueType: 'date',
dataIndex: 'move_in_date',
valueType: 'formList',
dataIndex: 'customer_info',
colProps: { span: 24 },
fieldProps: {
maxLength: 11,
style: {
width: '100%',
copyIconProps: false,
creatorButtonProps: {
creatorButtonText: '增加产权人',
style: { color: 'red' },
danger: true,
},
itemRender: (
{ listDom, action }: any,
{ index }: { index: number },
) => {
return (
<ProCard
bordered
style={{ marginBlockEnd: 8 }}
title={`产权人${index + 1}`}
extra={action}
bodyStyle={{ paddingBlockEnd: 0 }}
>
{listDom}
</ProCard>
);
},
},
columns: [
{
valueType: 'group',
columns: [
{
title: '姓名',
dataIndex: 'name',
colProps: { span: 5 },
formItemProps: { ...rulesHelper.text },
},
{
title: '手机号',
dataIndex: 'phone',
colProps: { span: 5 },
fieldProps: {
maxLength: 11,
},
formItemProps: { ...rulesHelper.phone },
},
MyFormItems.EnumSelect({
key: 'card_type',
title: '证件类型',
colProps: { span: 6 },
valueEnum: HouseOccupantsCardTypeEnum,
required: true,
}),
{
title: '证件号码',
dataIndex: 'id_card',
colProps: { span: 8 },
fieldProps: {
maxLength: 18,
},
formItemProps: { ...rulesHelper.text },
},
MyFormItems.EnumRadio({
key: 'house_relation',
title: '住户类型',
colProps: { span: 6 },
valueEnum: HouseOccupantsHouseRelationEnum,
fieldProps: {
defaultValue: 'Owner',
},
hideInForm: true,
}),
{
valueType: 'group',
columns: [
MyFormItems.UploadImages({
key: 'card_front_image',
title: '证件正面',
max: 1,
colProps: { span: 4 },
formItemProps: { ...rulesHelper.text },
}),
MyFormItems.UploadImages({
key: 'card_back_image',
title: '证件反面',
max: 1,
colProps: { span: 8 },
formItemProps: { ...rulesHelper.text },
}),
{
title: '是否入住',
dataIndex: 'is_live_in',
colProps: { span: 6 },
valueType: 'switch',
},
{
name: ['is_live_in'],
valueType: 'dependency',
columns: ({ is_live_in }: any) => {
return is_live_in
? [
{
title: '入住日期',
dataIndex: 'move_in_date',
valueType: 'date',
colProps: { span: 6 },
fieldProps: {
style: { width: '100%' },
},
formItemProps: { ...rulesHelper.text },
},
]
: [];
},
},
],
},
],
},
],
},
]}
/>

View File

@ -0,0 +1,60 @@
import {
MyBetaModalFormProps,
MyButtons,
MyModalFormProps,
rulesHelper,
} from '@/common';
import { Apis } from '@/gen/Apis';
import { BetaSchemaForm } from '@ant-design/pro-components';
import { Form, message } from 'antd';
export default function MoveIn(props: MyBetaModalFormProps) {
const [form] = Form.useForm();
return (
<BetaSchemaForm<ApiTypes.Archive.HouseOccupants.Update>
{...MyModalFormProps.props}
title={`添加${props.title}`}
wrapperCol={{ span: 24 }}
width="500px"
form={form}
onOpenChange={(open: any) => {
if (open && props.item) {
form.setFieldsValue(props.item);
}
}}
trigger={
<MyButtons.Default title={props.title} size="small" type="link" />
}
onFinish={async (values) =>
Apis.Archive.HouseOccupants.Update({
...values,
id: props?.item?.id ?? 0,
is_live_in: 1,
name: props?.item?.name,
phone: props?.item?.phone,
})
.then(() => {
props.reload?.();
message.success(props.title + '成功');
return true;
})
.catch(() => false)
}
columns={[
{
title: '入住日期',
valueType: 'date',
dataIndex: 'move_in_date',
colProps: { span: 24 },
fieldProps: {
maxLength: 11,
style: {
width: '100%',
},
},
formItemProps: { ...rulesHelper.text },
},
]}
/>
);
}

View File

@ -1,14 +1,19 @@
import { MyBetaModalFormProps, MyButtons, MyModalFormProps } from '@/common';
import {
MyBetaModalFormProps,
MyButtons,
MyModalFormProps,
rulesHelper,
} from '@/common';
import { Apis } from '@/gen/Apis';
import { BetaSchemaForm } from '@ant-design/pro-components';
import { Form, message } from 'antd';
export default function Create(props: MyBetaModalFormProps) {
export default function MoveOut(props: MyBetaModalFormProps) {
const [form] = Form.useForm();
return (
<BetaSchemaForm<ApiTypes.Archive.HouseRegisters.Store>
<BetaSchemaForm<ApiTypes.Archive.HouseRegisters.MoveOut>
{...MyModalFormProps.props}
title={`添加${props.title}`}
title={`设置${props.title}`}
wrapperCol={{ span: 24 }}
width="500px"
form={form}
@ -16,11 +21,9 @@ export default function Create(props: MyBetaModalFormProps) {
<MyButtons.Default title={props.title} size="small" type="link" />
}
onFinish={async (values) =>
Apis.Archive.HouseRegisters.Store({
Apis.Archive.HouseRegisters.MoveOut({
...values,
asset_houses_id: props?.item?.id,
type: 'MoveOut',
customer_info: props?.item?.id,
house_occupants_id: props?.item?.id,
})
.then(() => {
props.reload?.();
@ -33,14 +36,21 @@ export default function Create(props: MyBetaModalFormProps) {
{
title: '搬离日期',
valueType: 'date',
dataIndex: '',
dataIndex: 'unbound_time',
colProps: { span: 24 },
fieldProps: {
maxLength: 11,
style: {
width: '100%',
},
},
formItemProps: { ...rulesHelper.text },
},
{
title: '搬离原因',
valueType: 'textarea',
dataIndex: 'unbound_reason',
colProps: { span: 24 },
// formItemProps: { ...rulesHelper.text },
},
]}
/>

View File

@ -0,0 +1,119 @@
import { MyBetaModalFormProps, renderTextHelper } from '@/common';
import { MyModal } from '@/components/MyModal';
import {
HouseOccupantsCardTypeEnum,
HouseOccupantsHouseRelationEnum,
HouseOccupantsRelationWithOwnerEnum,
HouseOccupantsStatusEnum,
} from '@/gen/Enums';
import { ProCard, ProDescriptions } from '@ant-design/pro-components';
import { Image, Space } from 'antd';
export default function OccupantShow(props: MyBetaModalFormProps) {
return (
<MyModal
title={props.title || '查看'}
width="900px"
node={
<>
<ProCard extra={props.extra}>
<ProDescriptions bordered>
<ProDescriptions.Item label="姓名">
{props?.item?.name}
</ProDescriptions.Item>
<ProDescriptions.Item label="电话">
{props?.item?.phone}
</ProDescriptions.Item>
<ProDescriptions.Item label="状态">
<renderTextHelper.Tag
Enums={HouseOccupantsStatusEnum}
value={props?.item?.status}
key="status "
/>
</ProDescriptions.Item>
<ProDescriptions.Item label="房客关系">
<renderTextHelper.Tag
Enums={HouseOccupantsHouseRelationEnum}
value={props?.item?.house_relation}
key="house_relation"
/>
</ProDescriptions.Item>
<ProDescriptions.Item label="关系">
<renderTextHelper.Tag
Enums={HouseOccupantsRelationWithOwnerEnum}
value={props?.item?.relation_with_owner}
key="relation_with_owner"
/>
</ProDescriptions.Item>
<ProDescriptions.Item label="入住日期">
{props?.item?.is_live_in ? props?.item?.move_in_date : '未入住'}
</ProDescriptions.Item>
<ProDescriptions.Item label="证件类型">
<renderTextHelper.Tag
Enums={HouseOccupantsCardTypeEnum}
value={props?.item?.card_type}
key="card_type"
/>
</ProDescriptions.Item>
<ProDescriptions.Item label="证件号码" span={2}>
{props?.item?.id_card}
</ProDescriptions.Item>
<ProDescriptions.Item label="证件材料" span={3}>
<Space>
<Image.PreviewGroup>
{props?.item?.card_front_image?.map(
(res: any, index: number) => {
return (
<Image
width={160}
height={120}
src={res?.url || ''}
key={`${res?.name}_${index}`}
/>
);
},
)}
</Image.PreviewGroup>
<Image.PreviewGroup>
{props?.item?.card_back_image?.map(
(res: any, index: number) => {
return (
<Image
width={160}
height={120}
src={res?.url || ''}
key={`${res?.name}_${index}`}
/>
);
},
)}
</Image.PreviewGroup>
</Space>
</ProDescriptions.Item>
{props?.item?.house_relation === 'Owner' && (
<ProDescriptions.Item label="产证材料" span={3}>
<Space>
<Image.PreviewGroup>
{props?.item?.ownership_info?.map(
(res: any, index: number) => {
return (
<Image
width={160}
height={120}
src={res?.url || ''}
key={`${res?.name}_${index}`}
/>
);
},
)}
</Image.PreviewGroup>
</Space>
</ProDescriptions.Item>
)}
</ProDescriptions>
</ProCard>
</>
}
/>
);
}

View File

@ -0,0 +1,137 @@
import {
MyBetaModalFormProps,
MyColumns,
MyProTableProps,
renderTextHelper,
} from '@/common';
import { MyModal } from '@/components/MyModal';
import {
HouseOccupantsCardTypeEnum,
HouseOccupantsHouseRelationEnum,
HouseOccupantsRelationWithOwnerEnum,
HouseRegistersStatusEnum,
HouseRegistersTypeEnum,
} from '@/gen/Enums';
import { ProCard, ProDescriptions, ProTable } from '@ant-design/pro-components';
import { Image, Space } from 'antd';
export default function RegistersShow(props: MyBetaModalFormProps) {
return (
<MyModal
title={props.title || '查看'}
width="900px"
node={
<Space direction="vertical" style={{ width: '100%' }}>
<ProCard title="基本信息" extra={props.extra}>
<ProDescriptions bordered>
<ProDescriptions.Item label="登记类型">
<renderTextHelper.Tag
Enums={HouseRegistersTypeEnum}
value={props?.item?.type}
key="type "
/>
</ProDescriptions.Item>
<ProDescriptions.Item label="申请时间" span={2}>
{props?.item?.created_at}
</ProDescriptions.Item>
<ProDescriptions.Item label="登记状态">
<renderTextHelper.Tag
Enums={HouseRegistersStatusEnum}
value={props?.item?.status}
key="status "
/>
</ProDescriptions.Item>
<ProDescriptions.Item label="审核时间" span={2}>
{props?.item?.updated_at}
</ProDescriptions.Item>
</ProDescriptions>
</ProCard>
<ProCard title="客户信息">
<ProTable
{...MyProTableProps.props}
search={false}
toolBarRender={false}
pagination={false}
dataSource={props?.item?.customer_info}
rowKey="id_card"
columns={[
MyColumns.EnumTag({
title: '房客关系',
dataIndex: 'house_relation',
valueEnum: HouseOccupantsHouseRelationEnum,
}),
MyColumns.EnumTag({
title: '关系说明',
dataIndex: 'relation_with_owner',
valueEnum: HouseOccupantsRelationWithOwnerEnum,
}),
{
title: '姓名',
dataIndex: 'name',
},
{
title: '手机号',
dataIndex: 'phone',
},
{
title: '证件号码',
dataIndex: 'id_card',
},
MyColumns.EnumTag({
title: '证件类型',
dataIndex: 'card_type',
valueEnum: HouseOccupantsCardTypeEnum,
}),
{
title: '证件资料',
render: (_, item) => {
return (
<Space>
<Image
height={40}
src={
item?.card_front_image
? item?.card_front_image[0]?.url
: ''
}
/>
<Image
height={40}
src={
item?.card_back_image
? item?.card_back_image[0]?.url
: ''
}
/>
</Space>
);
},
},
]}
/>
</ProCard>
{props?.item?.type === 'Delivery' && (
<ProCard title="产证信息" style={{ paddingRight: 10 }}>
<Image.PreviewGroup>
{props?.item?.ownership_info?.map((res: any, index: number) => {
return (
<Space style={{ paddingRight: 10 }}>
<Image
height={80}
src={res?.url || ''}
key={`${res?.name}_${index}`}
/>
</Space>
);
})}
</Image.PreviewGroup>
</ProCard>
)}
</Space>
}
/>
);
}

View File

@ -0,0 +1,101 @@
import { MyColumns, MyProTableProps } from '@/common';
import { Apis } from '@/gen/Apis';
import {
HouseOccupantsHouseRelationEnum,
HouseOccupantsRelationWithOwnerEnum,
HouseOccupantsStatusEnum,
} from '@/gen/Enums';
import { ProTable } from '@ant-design/pro-components';
import { Space } from 'antd';
import { useEffect, useRef } from 'react';
import OccupantsUpdate from '../modals/OccupantsUpdate';
export default function Index({ ...rest }) {
const actionLooks = useRef<any>();
useEffect(() => {
actionLooks?.current.reloadAndRest();
}, [rest.loadmore]);
return (
<>
<ProTable<Record<any, any>>
{...MyProTableProps.props}
actionRef={actionLooks}
request={async (params, sort) =>
MyProTableProps.request(
{
...params,
asset_houses_id: rest.item?.asset_houses_id,
status: 'Unbound',
},
sort,
Apis.Archive.HouseOccupants.List,
)
}
// toolBarRender={(action) => [
// <AddOwner
// key="add"
// item={rest.item}
// reload={action?.reload}
// title="添加产权人"
// />,
// ]}
search={false}
columns={[
MyColumns.EnumTag({
title: '房客关系',
dataIndex: 'house_relation',
valueEnum: HouseOccupantsHouseRelationEnum,
search: false,
}),
MyColumns.EnumTag({
title: '关系说明',
dataIndex: 'relation_with_owner',
valueEnum: HouseOccupantsRelationWithOwnerEnum,
search: false,
}),
{
title: '姓名',
dataIndex: 'name',
},
{
title: '电话',
dataIndex: 'phone',
},
{
title: '是否入住',
dataIndex: 'is_live_in',
render(_, record) {
return `${record?.is_live_in ? '是' : '-'} `;
},
},
{
title: '入住日期',
dataIndex: 'is_live_in',
render(_, record) {
return `${record?.move_in_date || '-'}`;
},
},
MyColumns.EnumTag({
title: '状态',
dataIndex: 'status',
valueEnum: HouseOccupantsStatusEnum,
search: false,
}),
// MyColumns.UpdatedAt(),
MyColumns.Option({
render: (_, item: any, index, action) => (
<Space key={index}>
{item?.house_relation !== 'Owner' && (
<OccupantsUpdate item={item} reload={action?.reload} />
)}
</Space>
),
}),
]}
/>
</>
);
}

View File

@ -10,8 +10,9 @@ import { Space } from 'antd';
import { useEffect, useRef } from 'react';
import AddOccupant from '../modals/AddOccupant';
import AddOwner from '../modals/AddOwner';
import MoveIn from '../modals/MoveIn';
import MoveIn from '../modals/MoveIn00';
import MoveOut from '../modals/MoveOut';
import OccupantShow from '../modals/OccupantShow';
import OccupantsUpdate from '../modals/OccupantsUpdate';
import Transfer from '../modals/Transfer';
@ -66,7 +67,8 @@ export default function Index({ ...rest }) {
search: false,
}),
MyColumns.EnumTag({
title: '关系说明',
title:
rest?.item?.status === 'Rented' ? '与租客关系' : '与业主关系',
dataIndex: 'relation_with_owner',
valueEnum: HouseOccupantsRelationWithOwnerEnum,
search: false,
@ -91,7 +93,7 @@ export default function Index({ ...rest }) {
title: '入住日期',
dataIndex: 'is_live_in',
render(_, record) {
return `待补充`;
return `${record?.move_in_date || '-'}`;
},
},
MyColumns.EnumTag({
@ -104,18 +106,23 @@ export default function Index({ ...rest }) {
MyColumns.Option({
render: (_, item: any, index, action) => (
<Space key={index}>
<OccupantShow item={item} reload={action?.reload} />
{item?.house_relation !== 'Owner' && (
<OccupantsUpdate item={item} reload={action?.reload} />
)}
{item?.is_live_in && (
{!item?.is_live_in && (
<MoveIn item={item} reload={action?.reload} title="入住" />
)}
{item?.move_in_date && (
<MoveOut item={item} reload={action?.reload} title="搬离" />
)}
{/* {item?.HouseOccupantsHouseRelationEnum === 'Owner' && (
<MoveOut item={item} reload={action?.reload} title="移除" />
)} */}
{/* <MyButtons.Delete
onConfirm={() =>
Apis.Archive.HouseOccupants.Delete({ id: item.id }).then(
() => action?.reload(),
)
}
/> */}
</Space>
),
}),

View File

@ -0,0 +1,80 @@
import { MyColumns, MyProTableProps } from '@/common';
import { Apis } from '@/gen/Apis';
import { HouseRegistersStatusEnum, HouseRegistersTypeEnum } from '@/gen/Enums';
import { ProTable } from '@ant-design/pro-components';
import { Space } from 'antd';
import { useEffect, useRef } from 'react';
import RegistersShow from '../modals/RegistersShow';
export default function Index({ ...rest }) {
const actionLooks = useRef<any>();
useEffect(() => {
actionLooks?.current.reloadAndRest();
}, [rest.loadmore]);
return (
<>
<ProTable<Record<any, any>>
{...MyProTableProps.props}
actionRef={actionLooks}
request={async (params, sort) =>
MyProTableProps.request(
{
...params,
asset_houses_id: rest.item?.asset_houses_id,
// status: 'Approved',
},
sort,
Apis.Archive.HouseRegisters.List,
)
}
// toolBarRender={(action) => [
// <AddOwner
// key="add"
// item={rest.item}
// reload={action?.reload}
// title="添加产权人"
// />,
// ]}
search={false}
columns={[
MyColumns.ID(),
// {
// title: '房屋',
// dataIndex: ['asset_house', 'full_name'],
// },
MyColumns.EnumTag({
title: '类型',
dataIndex: 'type',
valueEnum: HouseRegistersTypeEnum,
}),
{
title: '客户信息',
render(_, record) {
return (
record?.customer_info.map((res: any) => res?.name).join(';') ||
'-'
); // 无数据时显示 -
},
search: false,
width: 200,
},
MyColumns.EnumTag({
title: '登记状态',
dataIndex: 'status',
valueEnum: HouseRegistersStatusEnum,
}),
MyColumns.UpdatedAt(),
MyColumns.Option({
render: (_, item: any, index, action) => (
<Space key={index}>
<RegistersShow item={item} reload={action?.reload} />
</Space>
),
}),
]}
/>
</>
);
}

View File

@ -3,6 +3,7 @@ import {
MyColumns,
MyPageContainer,
MyProTableProps,
usePageTabs,
} from '@/common';
import { Apis } from '@/gen/Apis';
import {
@ -19,6 +20,13 @@ import OccupantsCreate from './modals/OccupantsCreate';
export default function Index({ title = '房屋登记' }) {
const navigate = useNavigate();
// 注册当前页面为标签页
usePageTabs({
tabKey: 'archive-house-registers',
tabLabel: title,
});
return (
<MyPageContainer title={title}>
<ProTable

View File

@ -87,9 +87,12 @@ export default function info(props: MyBetaModalFormProps) {
<Space>
<div>
{props?.item?.company?.id}{props?.item?.company?.name}
</div>
<BindCompany item={props?.item} title="项目" reload={props?.reload}/>
<BindCompany
item={props?.item}
title="项目"
reload={props?.reload}
/>
</Space>
</ProDescriptions.Item>
</ProDescriptions>

View File

@ -3,6 +3,7 @@ import {
MyColumns,
MyPageContainer,
MyProTableProps,
usePageTabs,
} from '@/common';
import { Apis } from '@/gen/Apis';
import { AssetProjectsPropertyTypeEnum } from '@/gen/Enums';
@ -13,6 +14,12 @@ import Create from './modals/AssetCreate';
export default function Index({ title = '项目管理' }) {
const navigate = useNavigate();
// 注册当前页面为标签页
usePageTabs({
tabKey: 'asset-projects',
tabLabel: title,
});
return (
<MyPageContainer title={title}>
<ProTable
@ -21,6 +28,7 @@ export default function Index({ title = '项目管理' }) {
request={async (params, sort) =>
MyProTableProps.request(params, sort, Apis.Asset.AssetProjects.List)
}
// headerTitle="项目列表"
toolBarRender={(action) => [
<Create key="Create" reload={action?.reload} title={'项目'} />,
]}

View File

@ -30,7 +30,7 @@ export default function Index(props: MyBetaModalFormProps) {
title="员工"
/>,
]}
options={false}
// options={false}
columns={[
MyColumns.ID(),
//to-do 按层级选择

View File

@ -83,7 +83,6 @@ export default function Organizations(props: MyBetaModalFormProps) {
reload={action?.reload}
title="组织"
/>
<MyButtons.Delete
onConfirm={() =>
Apis.Company.Organizations.Delete({ id: item.id }).then(

View File

@ -5,14 +5,13 @@ import {
MyProTableProps,
} from '@/common';
import { Apis } from '@/gen/Apis';
import { AssetProjectsChargeEnum, AssetProjectsEntrustTypeEnum, AssetProjectsPropertyTypeEnum, AssetProjectsStatusEnum, OrganizationsTypeEnum } from '@/gen/Enums';
import { AssetProjectsPropertyTypeEnum } from '@/gen/Enums';
import { ProTable } from '@ant-design/pro-components';
import { Space } from 'antd';
import { useNavigate } from 'react-router-dom';
export default function Index(props: MyBetaModalFormProps) {
const navigate = useNavigate();
const navigate = useNavigate();
return (
<>
@ -47,10 +46,7 @@ export default function Index(props: MyBetaModalFormProps) {
title: '项目名称',
dataIndex: 'name',
},
{
title: '项目别名',
dataIndex: 'alias_name',
},
// {
// title: '项目编码',
// dataIndex: 'code',
@ -65,25 +61,25 @@ export default function Index(props: MyBetaModalFormProps) {
},
search: false,
},
MyColumns.EnumTag({
title: '项目状态',
dataIndex: 'status',
valueEnum: AssetProjectsStatusEnum,
search: false,
}),
// MyColumns.EnumTag({
// title: '项目状态',
// dataIndex: 'status',
// valueEnum: AssetProjectsStatusEnum,
// search: false,
// }),
MyColumns.EnumTag({
title: '委托类型',
dataIndex: 'entrust_type',
valueEnum: AssetProjectsEntrustTypeEnum,
search: false,
}),
MyColumns.EnumTag({
title: '收费方式',
dataIndex: 'charge',
valueEnum: AssetProjectsChargeEnum,
search: false,
}),
// MyColumns.EnumTag({
// title: '委托类型',
// dataIndex: 'entrust_type',
// valueEnum: AssetProjectsEntrustTypeEnum,
// search: false,
// }),
// MyColumns.EnumTag({
// title: '收费方式',
// dataIndex: 'charge',
// valueEnum: AssetProjectsChargeEnum,
// search: false,
// }),
MyColumns.SoftDelete({
title: '启/禁用',
onRestore: Apis.Asset.AssetProjects.Restore,

View File

@ -3,6 +3,7 @@ import {
MyColumns,
MyPageContainer,
MyProTableProps,
usePageTabs,
} from '@/common';
import { Apis } from '@/gen/Apis';
import { CompaniesMerchantTypeEnum } from '@/gen/Enums';
@ -13,8 +14,20 @@ import Create from './modals/Create';
export default function Index({ title = '机构管理' }) {
const navigate = useNavigate();
// 注册当前页面为标签页
usePageTabs({
tabKey: 'company-companies',
tabLabel: title,
});
return (
<MyPageContainer title={title}>
<MyPageContainer
title={title}
enableTabs={true}
tabKey="company-companies"
tabLabel={title}
>
<ProTable
{...MyProTableProps.props}
request={async (params, sort) =>

View File

@ -26,8 +26,12 @@ export default function Create(props: MyBetaModalFormProps) {
form.resetFields(); // 清空表单数据
}
}}
onFinish={async (values) =>
Apis.Company.CompanyEmployees.Store(values)
onFinish={async (values: any) =>
Apis.Company.CompanyEmployees.Store({
...values,
organizations_id:
values?.organizations_id?.[values.organizations_id.length - 1],
})
.then(() => {
props.reload?.();
message.success(props.title + '成功');
@ -36,11 +40,17 @@ export default function Create(props: MyBetaModalFormProps) {
.catch(() => false)
}
columns={[
Selects?.Organizations({
title: '设置所属组织',
params: { companies_id: props?.item?.companies_id },
// Selects?.Organizations({
// title: '设置所属组织',
// params: { companies_id: props?.item?.companies_id },
// key: 'organizations_id',
// formItemProps: { ...rulesHelper.text },
// }),
Selects?.OrganizationsTree({
title: '选择新的上级组织',
key: 'organizations_id',
formItemProps: { ...rulesHelper.text },
params: { companies_id: props?.item?.companies_id },
colProps: { span: 24 },
}),
{
key: 'name',

View File

@ -29,10 +29,13 @@ export default function Update(props: MyBetaModalFormProps) {
});
}
}}
onFinish={async (values) =>
onFinish={async (values: any) =>
Apis.Company.CompanyEmployees.Update({
...values,
id: props.item?.id ?? 0,
organizations_id:
values?.organizations_id?.[values.organizations_id.length - 1] ||
props.item?.organizations_id,
})
.then(() => {
props.reload?.();
@ -42,11 +45,20 @@ export default function Update(props: MyBetaModalFormProps) {
.catch(() => false)
}
columns={[
Selects?.Organizations({
title: '所属组织',
params: { companies_id: props?.item?.companies_id },
// Selects?.Organizations({
// title: '所属组织',
// params: { companies_id: props?.item?.companies_id },
// key: 'organizations_id',
// formItemProps: { ...rulesHelper.text },
// }),
Selects?.OrganizationsTree({
title: '选择新的上级组织',
key: 'organizations_id',
formItemProps: { ...rulesHelper.text },
params: { companies_id: props?.item?.companies_id },
colProps: { span: 24 },
fieldProps: {
showSearch: true,
},
}),
{
key: 'name',

View File

@ -9,11 +9,9 @@ export default function Update(props: MyBetaModalFormProps) {
return (
<BetaSchemaForm<ApiTypes.Company.Organizations.Update>
{...MyModalFormProps.props}
title={`调整上级${props.title}`}
title={`选择新的上级${props.title}`}
form={form}
trigger={
<MyButtons.Default title="组织调整" type="primary" size="small" />
}
trigger={<MyButtons.Edit title="组织调整" type="link" size="middle" />}
wrapperCol={{ span: 24 }}
width="500px"
onOpenChange={(open: any) => {
@ -27,7 +25,9 @@ export default function Update(props: MyBetaModalFormProps) {
id: props.item?.id ?? 0,
name: props.item?.name,
type: props.item?.type,
parent_id: values?.parent_id?.[values.parent_id.length - 1],
parent_id:
values?.parent_id?.[values.parent_id.length - 1] ||
props.item?.parent_id,
})
.then(() => {
props.reload?.();

View File

@ -3,16 +3,29 @@ import {
MyColumns,
MyPageContainer,
MyProTableProps,
usePageTabs,
} from '@/common';
import { Apis } from '@/gen/Apis';
import { ProTable } from '@ant-design/pro-components';
import { Space } from 'antd';
import Create from './modals/Create';
import Update from './modals/Update';
import EmployeesCreate from '../company/companies/modals/EmployeesCreate';
import EmployeesUpdate from '../company/companies/modals/EmployeesUpdate';
export default function Index({ title = '员工管理' }) {
// 使用多标签页功能
usePageTabs({
tabKey: 'employees-list',
tabLabel: title,
closable: true
});
return (
<MyPageContainer title={title}>
<MyPageContainer
enableTabs
tabKey="employees-list"
tabLabel={title}
title={title}
>
<ProTable
{...MyProTableProps.props}
// search={false}
@ -24,7 +37,11 @@ export default function Index({ title = '员工管理' }) {
)
}
toolBarRender={(action) => [
<Create key="Create" reload={action?.reload} title={title} />,
<EmployeesCreate
key="Create"
reload={action?.reload}
title={title}
/>,
]}
columns={[
MyColumns.ID(),
@ -35,35 +52,34 @@ export default function Index({ title = '员工管理' }) {
title: '机构',
dataIndex: ['company', 'name'],
search: false,
width: 220,
},
{
title: '组织',
dataIndex: ['organization', 'name'],
search: false,
width: 150,
},
{
title: '姓名',
dataIndex: 'name',
width: 150,
},
{
title: '手机号',
dataIndex: 'phone',
width: 150,
},
{
title: '岗位',
dataIndex: ['position', 'name'],
width: 150,
},
MyColumns.UpdatedAt(),
// MyColumns.CreatedAt(),
MyColumns.Option({
render: (_, item: any, index, action) => (
<Space key={index}>
<Update item={item} reload={action?.reload} title={title} />
<EmployeesUpdate
item={item}
reload={action?.reload}
title={title}
/>
<MyButtons.Delete
onConfirm={() =>
Apis.Common.Admins.Delete({ id: item.id }).then(() =>

View File

@ -1,104 +0,0 @@
import {
MyBetaModalFormProps,
MyButtons,
MyFormItems,
MyModalFormProps,
rulesHelper,
} from '@/common';
import { Selects } from '@/components/Select';
import { Apis } from '@/gen/Apis';
import { SexEnum } from '@/gen/Enums';
import { BetaSchemaForm } from '@ant-design/pro-components';
import { Form, message } from 'antd';
export default function Create(props: MyBetaModalFormProps) {
const [form] = Form.useForm();
return (
<BetaSchemaForm<ApiTypes.Company.CompanyEmployees.Store>
{...MyModalFormProps.props}
title={`添加员工`}
wrapperCol={{ span: 24 }}
width="500px"
trigger={<MyButtons.Create title={`添加`} />}
form={form}
onOpenChange={(open: any) => {
if (open) {
form.resetFields(); // 清空表单数据
}
}}
onFinish={async (values) =>
Apis.Company.CompanyEmployees.Store(values)
.then(() => {
props.reload?.();
message.success(props.title + '成功');
return true;
})
.catch(() => false)
}
columns={[
Selects?.Companies({
title: '所属机构',
key: 'companies_id',
formItemProps: { ...rulesHelper.text },
}),
{
valueType: 'dependency',
name: ['companies_id'],
columns: ({ companies_id }) => [
Selects?.Organizations({
title: '所属组织',
params: { companies_id: companies_id },
key: 'organizations_id',
formItemProps: { ...rulesHelper.text },
}),
],
},
{
key: 'name',
title: '姓名',
colProps: { span: 6 },
formItemProps: { ...rulesHelper.text },
},
{
key: 'phone',
title: '手机号',
valueType: 'number',
fieldProps: {
maxLength: 11,
},
colProps: { span: 12 },
formItemProps: { ...rulesHelper.phone },
},
MyFormItems.EnumRadio({
key: 'sex',
title: '性别',
colProps: { span: 6 },
valueEnum: SexEnum,
required: true,
}),
{
valueType: 'dependency',
name: ['companies_id'],
columns: ({ companies_id }) => [
Selects?.Positions({
title: '岗位',
params: { companies_id: companies_id },
key: 'positions_id',
formItemProps: { ...rulesHelper.text },
fieldProps: {
showSearch: true,
},
}),
],
},
{
key: 'remark',
title: '备注',
colProps: { span: 24 },
valueType: 'textarea',
},
]}
/>
);
}

View File

@ -1,109 +0,0 @@
import {
MyBetaModalFormProps,
MyButtons,
MyFormItems,
MyModalFormProps,
rulesHelper,
} from '@/common';
import { Selects } from '@/components/Select';
import { Apis } from '@/gen/Apis';
import { SexEnum } from '@/gen/Enums';
import { BetaSchemaForm } from '@ant-design/pro-components';
import { Form, message } from 'antd';
export default function Update(props: MyBetaModalFormProps) {
const [form] = Form.useForm();
return (
<BetaSchemaForm<ApiTypes.Company.CompanyEmployees.Update>
{...MyModalFormProps.props}
title={`编辑员工`}
trigger={<MyButtons.Edit />}
wrapperCol={{ span: 24 }}
width="500px"
form={form}
onOpenChange={(open: any) => {
if (open && props.item) {
form.setFieldsValue({
...props.item,
roles_id: props.item?.roles?.map((item: any) => item.value),
});
}
}}
onFinish={async (values) =>
Apis.Company.CompanyEmployees.Update({
...values,
id: props.item?.id ?? 0,
})
.then(() => {
props.reload?.();
message.success(props.title + '成功');
return true;
})
.catch(() => false)
}
columns={[
Selects?.Companies({
title: '所属机构',
key: 'companies_id',
formItemProps: { ...rulesHelper.text },
}),
{
valueType: 'dependency',
name: ['companies_id'],
columns: ({ companies_id }) => [
Selects?.Organizations({
title: '所属组织',
params: { companies_id: companies_id },
key: 'organizations_id',
formItemProps: { ...rulesHelper.text },
}),
],
},
{
key: 'name',
title: '姓名',
colProps: { span: 6 },
formItemProps: { ...rulesHelper.text },
},
{
key: 'phone',
title: '手机号',
valueType: 'number',
fieldProps: {
maxLength: 11,
},
colProps: { span: 12 },
formItemProps: { ...rulesHelper.phone },
},
MyFormItems.EnumRadio({
key: 'sex',
title: '性别',
colProps: { span: 6 },
valueEnum: SexEnum,
required: true,
}),
{
valueType: 'dependency',
name: ['companies_id'],
columns: ({ companies_id }) => [
Selects?.Positions({
title: '岗位',
params: { companies_id: companies_id },
key: 'positions_id',
formItemProps: { ...rulesHelper.text },
fieldProps: {
showSearch: true,
},
}),
],
},
{
key: 'remark',
title: '备注',
colProps: { span: 24 },
valueType: 'textarea',
},
]}
/>
);
}

View File

@ -1,4 +1,9 @@
import { MyColumns, MyPageContainer, MyProTableProps } from '@/common';
import {
MyColumns,
MyPageContainer,
MyProTableProps,
usePageTabs,
} from '@/common';
import { Apis } from '@/gen/Apis';
import {
HouseRegistersCustomerTypeEnum,
@ -12,6 +17,11 @@ import { Space } from 'antd';
import Audit from './modals/Audit';
export default function Index({ title = '房屋登记审核' }) {
// 注册当前页面为标签页
usePageTabs({
tabKey: 'examine-house-registers-audit',
tabLabel: title,
});
return (
<MyPageContainer title={title}>
<ProTable

View File

@ -3,6 +3,7 @@ import {
MyColumns,
MyPageContainer,
MyProTableProps,
usePageTabs,
} from '@/common';
import { Apis } from '@/gen/Apis';
import { HouseBillsTypeEnum } from '@/gen/Enums';
@ -12,8 +13,19 @@ import Create from './modals/Create';
import Update from './modals/Update';
export default function Index({ title = '账单' }) {
// 注册当前页面为标签页
usePageTabs({
tabKey: 'house-bills',
tabLabel: title,
});
return (
<MyPageContainer title={title}>
<MyPageContainer
title={title}
enableTabs={true}
tabKey="house-bills"
tabLabel={title}
>
<ProTable
{...MyProTableProps.props}
request={async (params, sort) =>

View File

@ -4,6 +4,7 @@ import {
MyPageContainer,
MyProTableProps,
renderTextHelper,
usePageTabs,
} from '@/common';
import { Apis } from '@/gen/Apis';
import { ProTable } from '@ant-design/pro-components';
@ -12,8 +13,19 @@ import Create from './modals/Create';
import Update from './modals/Update';
export default function Index({ title = '管理员' }) {
// 注册当前页面为标签页
usePageTabs({
tabKey: 'system-admins',
tabLabel: title,
});
return (
<MyPageContainer title={title}>
<MyPageContainer
title={title}
enableTabs={true}
tabKey="system-admins"
tabLabel={title}
>
<ProTable
{...MyProTableProps.props}
search={false}

View File

@ -3,6 +3,7 @@ import {
MyColumns,
MyPageContainer,
MyProTableProps,
usePageTabs,
} from '@/common';
import MyEnumRadioGroup from '@/common/components/formFields/MyEnumRadioGroup';
import { Apis } from '@/gen/Apis';
@ -19,6 +20,12 @@ export default function Index({ title = '功能' }) {
const actionRef = useRef<ActionType>();
const [guardName, setGuardName] = useState<string>('Admin');
// 注册当前页面为标签页
usePageTabs({
tabKey: 'system-permissions',
tabLabel: title,
});
const getData = async () => {
let data = await Apis.Permission.SysPermissions.List({
guard_name: guardName,
@ -150,7 +157,12 @@ export default function Index({ title = '功能' }) {
};
return (
<MyPageContainer title={title}>
<MyPageContainer
title={title}
enableTabs={true}
tabKey="system-permissions"
tabLabel={title}
>
<ShowTable />
</MyPageContainer>
);

View File

@ -3,6 +3,7 @@ import {
MyColumns,
MyPageContainer,
MyProTableProps,
usePageTabs,
} from '@/common';
import { Apis } from '@/gen/Apis';
import { ProTable } from '@ant-design/pro-components';
@ -12,8 +13,19 @@ import EditPermissions from './modals/EditPermissions';
import Update from './modals/Update';
export default function Index({ title = '角色' }) {
// 注册当前页面为标签页
usePageTabs({
tabKey: 'system-roles',
tabLabel: title,
});
return (
<MyPageContainer title={title}>
<MyPageContainer
title={title}
enableTabs={true}
tabKey="system-roles"
tabLabel={title}
>
<ProTable
{...MyProTableProps.props}
search={false}

243
src/pages/tabs-demo.tsx Normal file
View File

@ -0,0 +1,243 @@
import React from 'react';
import { Button, Card, Space, Divider, Row, Col, Statistic, Alert } from 'antd';
import {
PlusOutlined,
UserOutlined,
SettingOutlined,
HomeOutlined,
FileTextOutlined,
TeamOutlined
} from '@ant-design/icons';
import { MyPageContainer, usePageTabs } from '@/common';
import { history } from '@umijs/max';
/**
*
*
*/
export default function TabsDemo() {
const tabsApi = usePageTabs({
tabKey: 'tabs-demo',
tabLabel: '标签页演示',
closable: false // 演示页面不可关闭
});
// 模拟打开不同的页面标签
const openTab = (key: string, label: string, path: string) => {
tabsApi.addTab({
key,
label,
path,
closable: true
});
// 注意:在实际项目中,这里应该使用 history.push(path)
// 由于这是演示,我们只是添加标签而不实际跳转
console.log(`模拟跳转到: ${path}`);
};
const demoTabs = [
{
key: 'employees',
label: '员工管理',
path: '/employees',
icon: <TeamOutlined />,
description: '管理公司员工信息'
},
{
key: 'companies',
label: '公司管理',
path: '/company/companies',
icon: <HomeOutlined />,
description: '管理公司基本信息'
},
{
key: 'house-bills',
label: '房屋账单',
path: '/house_bills',
icon: <FileTextOutlined />,
description: '查看和管理房屋账单'
},
{
key: 'system-admins',
label: '系统管理员',
path: '/system/admins',
icon: <UserOutlined />,
description: '管理系统管理员账户'
},
{
key: 'system-roles',
label: '角色管理',
path: '/system/sys_roles',
icon: <SettingOutlined />,
description: '管理系统角色权限'
}
];
return (
<MyPageContainer
enableTabs
tabKey="tabs-demo"
tabLabel="标签页演示"
title="多标签页功能演示"
>
<Alert
message="多标签页功能演示"
description="这个页面展示了 MyPageContainer 的多标签页功能。您可以点击下方按钮打开新的标签页,然后右键点击标签体验各种操作。"
type="info"
showIcon
style={{ marginBottom: 24 }}
/>
{/* 统计信息 */}
<Row gutter={16} style={{ marginBottom: 24 }}>
<Col span={6}>
<Card>
<Statistic
title="当前标签数量"
value={tabsApi.getTabs().length}
prefix={<FileTextOutlined />}
/>
</Card>
</Col>
<Col span={6}>
<Card>
<Statistic
title="激活标签"
value={tabsApi.getActiveKey()}
valueStyle={{ fontSize: '16px' }}
/>
</Card>
</Col>
<Col span={6}>
<Card>
<Statistic
title="可用操作"
value={6}
suffix="种"
prefix={<SettingOutlined />}
/>
</Card>
</Col>
<Col span={6}>
<Card>
<Statistic
title="演示页面"
value={demoTabs.length}
suffix="个"
prefix={<PlusOutlined />}
/>
</Card>
</Col>
</Row>
{/* 快速打开标签页 */}
<Card title="🚀 快速打开页面" style={{ marginBottom: 24 }}>
<Row gutter={[16, 16]}>
{demoTabs.map(tab => (
<Col span={8} key={tab.key}>
<Card
size="small"
hoverable
onClick={() => openTab(tab.key, tab.label, tab.path)}
style={{ cursor: 'pointer', textAlign: 'center' }}
>
<div style={{ fontSize: '24px', marginBottom: '8px' }}>
{tab.icon}
</div>
<div style={{ fontWeight: 'bold', marginBottom: '4px' }}>
{tab.label}
</div>
<div style={{ fontSize: '12px', color: '#666' }}>
{tab.description}
</div>
</Card>
</Col>
))}
</Row>
</Card>
{/* 标签页操作 */}
<Card title="🎛️ 标签页操作" style={{ marginBottom: 24 }}>
<Space wrap size="middle">
<Button
type="primary"
onClick={() => tabsApi.closeOtherTabs()}
disabled={tabsApi.getTabs().length <= 1}
>
</Button>
<Button
onClick={() => tabsApi.closeLeftTabs()}
disabled={tabsApi.getTabs().length <= 1}
>
</Button>
<Button
onClick={() => tabsApi.closeRightTabs()}
disabled={tabsApi.getTabs().length <= 1}
>
</Button>
<Button
onClick={() => tabsApi.refreshTab()}
>
</Button>
<Button
danger
onClick={() => {
const tabs = tabsApi.getTabs();
const closableTabs = tabs.filter(tab => tab.closable);
closableTabs.forEach(tab => tabsApi.removeTab(tab.key));
}}
disabled={tabsApi.getTabs().filter(tab => tab.closable).length === 0}
>
</Button>
</Space>
</Card>
{/* 功能说明 */}
<Card title="📖 功能说明">
<Row gutter={24}>
<Col span={12}>
<h4>🎯 </h4>
<ul style={{ lineHeight: '1.8' }}>
<li><strong></strong></li>
<li><strong></strong></li>
<li><strong></strong></li>
<li><strong></strong></li>
<li><strong></strong></li>
</ul>
</Col>
<Col span={12}>
<h4>🖱 </h4>
<ul style={{ lineHeight: '1.8' }}>
<li><strong></strong></li>
<li><strong></strong></li>
<li><strong></strong></li>
<li><strong></strong></li>
<li><strong></strong></li>
</ul>
</Col>
</Row>
<Divider />
<h4>💡 使</h4>
<ul style={{ lineHeight: '1.8' }}>
<li></li>
<li></li>
<li>使</li>
<li></li>
<li></li>
</ul>
</Card>
</MyPageContainer>
);
}

4533
yarn.lock

File diff suppressed because it is too large Load Diff