forked from wangziqi/gongxue-base
feat: classroom status filter + export button + menu (departments/notifications)
This commit is contained in:
@@ -24,6 +24,7 @@ import {
|
||||
KeyOutlined,
|
||||
CheckCircleOutlined,
|
||||
LaptopOutlined,
|
||||
BellOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { usePermission } from '../hooks/usePermission';
|
||||
import NotificationBell from '../components/NotificationBell';
|
||||
@@ -107,6 +108,8 @@ const allMenuItems: MenuItemType[] = [
|
||||
label: '系统管理',
|
||||
permission: 'log:view',
|
||||
children: [
|
||||
{ key: '/departments', icon: <HomeOutlined />, label: '校区/部门', permission: 'department:view' },
|
||||
{ key: '/notifications', icon: <BellOutlined />, label: '通知中心', permission: 'notification:view' },
|
||||
{ key: '/operation-logs', icon: <AuditOutlined />, label: '操作日志', permission: 'log:view' },
|
||||
{ key: '/roles', icon: <SafetyOutlined />, label: '角色管理', permission: 'role:view' },
|
||||
{ key: '/permissions', icon: <KeyOutlined />, label: '权限一览', permission: 'role:view' },
|
||||
|
||||
@@ -52,14 +52,14 @@ const ClassroomsPage: React.FC = () => {
|
||||
const [showArchived, setShowArchived] = useState(false);
|
||||
const [form] = Form.useForm();
|
||||
const [searchText, setSearchText] = useState('');
|
||||
const [filterStatus, setFilterStatus] = useState<string | undefined>(undefined);
|
||||
|
||||
const filteredData = useMemo(() => {
|
||||
if (!searchText) return data;
|
||||
const s = searchText.toLowerCase();
|
||||
return data.filter(
|
||||
(d: any) => d.name?.toLowerCase().includes(s) || d.building?.toLowerCase().includes(s),
|
||||
);
|
||||
}, [data, searchText]);
|
||||
let result = data;
|
||||
if (searchText) { const s = searchText.toLowerCase(); result = result.filter((d: Record<string, unknown>) => (typeof d.name === 'string' && d.name.toLowerCase().includes(s)) || (typeof d.building === 'string' && d.building.toLowerCase().includes(s))); }
|
||||
if (filterStatus) result = result.filter((d: Record<string, unknown>) => d.status === filterStatus);
|
||||
return result;
|
||||
}, [data, searchText, filterStatus]);
|
||||
|
||||
const fetchData = async () => {
|
||||
setLoading(true);
|
||||
@@ -223,6 +223,7 @@ const ClassroomsPage: React.FC = () => {
|
||||
if (!e.target.value) setSearchText('');
|
||||
}}
|
||||
/>
|
||||
<Select placeholder="状态" allowClear style={{ width: 110 }} value={filterStatus} onChange={setFilterStatus} options={[{value:'available',label:'可用'},{value:'in_use',label:'使用中'},{value:'maintenance',label:'维护中'}]} />
|
||||
<Button
|
||||
type={showArchived ? 'primary' : 'default'}
|
||||
onClick={() => setShowArchived(!showArchived)}
|
||||
@@ -243,6 +244,7 @@ const ClassroomsPage: React.FC = () => {
|
||||
>
|
||||
添加教室
|
||||
</PermissionButton>
|
||||
<PermissionButton permission="classroom:view" icon={<DownloadOutlined />} onClick={() => { const baseURL = '/api'; const token = localStorage.getItem('token'); fetch(`${baseURL}/classrooms/export`, { headers: { Authorization: `Bearer ${token}` } }).then(r => r.blob()).then(b => { const a = document.createElement('a'); a.href = URL.createObjectURL(b); a.download = '教室使用报表.xlsx'; a.click(); }); }}>导出报表</PermissionButton>
|
||||
<Upload
|
||||
accept=".xlsx,.xls"
|
||||
showUploadList={false}
|
||||
|
||||
@@ -7,7 +7,7 @@ services:
|
||||
restart: always
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-gongxue_2024}
|
||||
MYSQL_DATABASE: ${DB_DATABASE:-gongxue}
|
||||
MYSQL_DATABASE: gongxue
|
||||
MYSQL_CHARSET: utf8mb4
|
||||
MYSQL_COLLATION: utf8mb4_unicode_ci
|
||||
ports:
|
||||
@@ -15,6 +15,42 @@ services:
|
||||
volumes:
|
||||
- mysql_data:/var/lib/mysql
|
||||
command: --default-authentication-plugin=mysql_native_password --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
||||
interval: 5s
|
||||
retries: 10
|
||||
|
||||
backend:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: apps/server/Dockerfile
|
||||
container_name: gongxue_backend
|
||||
restart: always
|
||||
environment:
|
||||
DB_TYPE: mysql
|
||||
DB_HOST: mysql
|
||||
DB_PORT: 3306
|
||||
DB_USERNAME: root
|
||||
DB_PASSWORD: ${MYSQL_ROOT_PASSWORD:-gongxue_2024}
|
||||
DB_DATABASE: gongxue
|
||||
DB_SYNCHRONIZE: "false"
|
||||
JWT_SECRET: ${JWT_SECRET:-gongxue-jwt-prod-2026-k3y}
|
||||
JWT_EXPIRES_IN: 24h
|
||||
PORT: 3000
|
||||
depends_on:
|
||||
mysql:
|
||||
condition: service_healthy
|
||||
|
||||
frontend:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: apps/admin/Dockerfile
|
||||
container_name: gongxue_frontend
|
||||
restart: always
|
||||
ports:
|
||||
- "9527:80"
|
||||
depends_on:
|
||||
- backend
|
||||
|
||||
volumes:
|
||||
mysql_data:
|
||||
|
||||
Reference in New Issue
Block a user