|
|
@@ -0,0 +1,693 @@
|
|
|
+import React, { useState, useEffect, useRef } from 'react';
|
|
|
+import { Search, Plus, RefreshCw, Edit2, Trash2, Settings } from 'lucide-react';
|
|
|
+import { padLockApi, PadLockVO, PageParam } from '../api/PadLock';
|
|
|
+import { padLockTypeApi, PadLockTypeVO, PageParam as PadLockTypePageParam } from '../api/PadLockType';
|
|
|
+import { toast } from 'sonner';
|
|
|
+import { Modal, Button, Input, Space, Table, Select } from 'antd';
|
|
|
+import { ExclamationCircleOutlined } from '@ant-design/icons';
|
|
|
+import type { ColumnsType } from 'antd/es/table';
|
|
|
+
|
|
|
+interface PadLockManagementProps {
|
|
|
+ subMenu?: string;
|
|
|
+}
|
|
|
+
|
|
|
+export default function PadLockManagement({ subMenu }: PadLockManagementProps) {
|
|
|
+ const [viewMode, setViewMode] = useState<'list' | 'type'>('list'); // 'list' 挂锁列表, 'type' 挂锁类型
|
|
|
+ const [loading, setLoading] = useState(true);
|
|
|
+ const [list, setList] = useState<PadLockVO[]>([]);
|
|
|
+ const [total, setTotal] = useState(0);
|
|
|
+ const [queryParams, setQueryParams] = useState<PageParam>({
|
|
|
+ pageNo: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ lockCode: undefined,
|
|
|
+ lockName: undefined,
|
|
|
+ enableFlag: undefined,
|
|
|
+ });
|
|
|
+
|
|
|
+ // 挂锁类型相关状态
|
|
|
+ const [typeLoading, setTypeLoading] = useState(true);
|
|
|
+ const [typeList, setTypeList] = useState<PadLockTypeVO[]>([]);
|
|
|
+ const [typeTotal, setTypeTotal] = useState(0);
|
|
|
+ const [typeQueryParams, setTypeQueryParams] = useState<PadLockTypePageParam>({
|
|
|
+ pageNo: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ lockTypeCode: undefined,
|
|
|
+ lockTypeName: undefined,
|
|
|
+ enableFlag: undefined,
|
|
|
+ });
|
|
|
+ const [showTypeForm, setShowTypeForm] = useState(false);
|
|
|
+ const [editingType, setEditingType] = useState<PadLockTypeVO | null>(null);
|
|
|
+
|
|
|
+ // 获取挂锁列表
|
|
|
+ const getList = async (params?: PageParam) => {
|
|
|
+ const currentParams = params || queryParams;
|
|
|
+ setLoading(true);
|
|
|
+ try {
|
|
|
+ const response = await padLockApi.listPadLock(currentParams);
|
|
|
+ setList(response.list || []);
|
|
|
+ setTotal(response.total || 0);
|
|
|
+ } catch (error: any) {
|
|
|
+ toast.error(error.message || '获取挂锁列表失败');
|
|
|
+ } finally {
|
|
|
+ setLoading(false);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 获取挂锁类型列表
|
|
|
+ const getTypeList = async (params?: PadLockTypePageParam) => {
|
|
|
+ const currentParams = params || typeQueryParams;
|
|
|
+ setTypeLoading(true);
|
|
|
+ try {
|
|
|
+ const response = await padLockTypeApi.listPadLockType(currentParams);
|
|
|
+ setTypeList(response.list || []);
|
|
|
+ setTypeTotal(response.total || 0);
|
|
|
+ } catch (error: any) {
|
|
|
+ toast.error(error.message || '获取挂锁类型列表失败');
|
|
|
+ } finally {
|
|
|
+ setTypeLoading(false);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ if (viewMode === 'list') {
|
|
|
+ getList();
|
|
|
+ } else {
|
|
|
+ getTypeList();
|
|
|
+ }
|
|
|
+ }, [viewMode, queryParams.pageNo, queryParams.pageSize, typeQueryParams.pageNo, typeQueryParams.pageSize]);
|
|
|
+
|
|
|
+ // 搜索挂锁
|
|
|
+ const handleQuery = () => {
|
|
|
+ const newParams = { ...queryParams, pageNo: 1 };
|
|
|
+ setQueryParams(newParams);
|
|
|
+ getList(newParams);
|
|
|
+ };
|
|
|
+
|
|
|
+ // 重置挂锁搜索
|
|
|
+ const resetQuery = () => {
|
|
|
+ const resetParams: PageParam = {
|
|
|
+ pageNo: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ lockCode: undefined,
|
|
|
+ lockName: undefined,
|
|
|
+ enableFlag: undefined,
|
|
|
+ };
|
|
|
+ setQueryParams(resetParams);
|
|
|
+ getList(resetParams);
|
|
|
+ };
|
|
|
+
|
|
|
+ // 搜索挂锁类型
|
|
|
+ const handleTypeQuery = () => {
|
|
|
+ const newParams = { ...typeQueryParams, pageNo: 1 };
|
|
|
+ setTypeQueryParams(newParams);
|
|
|
+ getTypeList(newParams);
|
|
|
+ };
|
|
|
+
|
|
|
+ // 重置挂锁类型搜索
|
|
|
+ const resetTypeQuery = () => {
|
|
|
+ const resetParams: PadLockTypePageParam = {
|
|
|
+ pageNo: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ lockTypeCode: undefined,
|
|
|
+ lockTypeName: undefined,
|
|
|
+ enableFlag: undefined,
|
|
|
+ };
|
|
|
+ setTypeQueryParams(resetParams);
|
|
|
+ getTypeList(resetParams);
|
|
|
+ };
|
|
|
+
|
|
|
+ // 删除挂锁
|
|
|
+ const handleDelete = async (id: number, name?: string) => {
|
|
|
+ Modal.confirm({
|
|
|
+ title: '确认删除',
|
|
|
+ icon: <ExclamationCircleOutlined />,
|
|
|
+ content: (
|
|
|
+ <div>
|
|
|
+ <p>确定要删除挂锁 <strong>"{name || '该挂锁'}"</strong> 吗?</p>
|
|
|
+ <p style={{ color: '#ff4d4f', marginTop: '8px' }}>删除后无法恢复,请谨慎操作!</p>
|
|
|
+ </div>
|
|
|
+ ),
|
|
|
+ okText: '确定删除',
|
|
|
+ okType: 'danger',
|
|
|
+ cancelText: '取消',
|
|
|
+ onOk: async () => {
|
|
|
+ try {
|
|
|
+ await padLockApi.delPadLock(id);
|
|
|
+ toast.success('删除成功');
|
|
|
+ await getList();
|
|
|
+ } catch (error: any) {
|
|
|
+ toast.error(error.message || '删除失败');
|
|
|
+ }
|
|
|
+ },
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ // 删除挂锁类型
|
|
|
+ const handleDeleteType = async (id: number, name?: string) => {
|
|
|
+ Modal.confirm({
|
|
|
+ title: '确认删除',
|
|
|
+ icon: <ExclamationCircleOutlined />,
|
|
|
+ content: (
|
|
|
+ <div>
|
|
|
+ <p>确定要删除挂锁类型 <strong>"{name || '该类型'}"</strong> 吗?</p>
|
|
|
+ <p style={{ color: '#ff4d4f', marginTop: '8px' }}>删除后无法恢复,请谨慎操作!</p>
|
|
|
+ </div>
|
|
|
+ ),
|
|
|
+ okText: '确定删除',
|
|
|
+ okType: 'danger',
|
|
|
+ cancelText: '取消',
|
|
|
+ onOk: async () => {
|
|
|
+ try {
|
|
|
+ await padLockTypeApi.delPadLockType(id);
|
|
|
+ toast.success('删除成功');
|
|
|
+ await getTypeList();
|
|
|
+ } catch (error: any) {
|
|
|
+ toast.error(error.message || '删除失败');
|
|
|
+ }
|
|
|
+ },
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ // 打开挂锁类型表单
|
|
|
+ const openTypeForm = (type?: 'create' | 'update', id?: number) => {
|
|
|
+ if (type === 'create') {
|
|
|
+ setEditingType(null);
|
|
|
+ setShowTypeForm(true);
|
|
|
+ } else if (type === 'update' && id) {
|
|
|
+ padLockTypeApi.getPadLockTypeInfo(id).then((data) => {
|
|
|
+ setEditingType(data);
|
|
|
+ setShowTypeForm(true);
|
|
|
+ }).catch((error: any) => {
|
|
|
+ toast.error(error.message || '获取挂锁类型信息失败');
|
|
|
+ });
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 保存挂锁类型
|
|
|
+ const saveType = async (formData: PadLockTypeVO) => {
|
|
|
+ try {
|
|
|
+ if (editingType?.lockTypeId) {
|
|
|
+ await padLockTypeApi.updatePadLockType({
|
|
|
+ ...formData,
|
|
|
+ lockTypeId: editingType.lockTypeId,
|
|
|
+ });
|
|
|
+ toast.success('修改成功');
|
|
|
+ } else {
|
|
|
+ await padLockTypeApi.addPadLockType(formData);
|
|
|
+ toast.success('新增成功');
|
|
|
+ }
|
|
|
+ setShowTypeForm(false);
|
|
|
+ setEditingType(null);
|
|
|
+ await getTypeList();
|
|
|
+ } catch (error: any) {
|
|
|
+ toast.error(error.message || '保存失败');
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 挂锁列表表格列
|
|
|
+ const padLockColumns: ColumnsType<PadLockVO> = [
|
|
|
+ {
|
|
|
+ title: '序号',
|
|
|
+ width: 80,
|
|
|
+ align: 'center',
|
|
|
+ render: (_: any, __: PadLockVO, index: number) => {
|
|
|
+ return (queryParams.pageNo - 1) * queryParams.pageSize + index + 1;
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '挂锁编号',
|
|
|
+ dataIndex: 'lockId',
|
|
|
+ width: 100,
|
|
|
+ align: 'center',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '挂锁编码',
|
|
|
+ dataIndex: 'lockCode',
|
|
|
+ width: 150,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '挂锁名称',
|
|
|
+ dataIndex: 'lockName',
|
|
|
+ width: 200,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '状态',
|
|
|
+ dataIndex: 'enableFlag',
|
|
|
+ width: 100,
|
|
|
+ align: 'center',
|
|
|
+ render: (flag: string) => {
|
|
|
+ return flag === '1' || flag === 'Y' ? '启用' : '禁用';
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '备注',
|
|
|
+ dataIndex: 'remark',
|
|
|
+ ellipsis: true,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '操作',
|
|
|
+ width: 120,
|
|
|
+ align: 'center',
|
|
|
+ fixed: 'right',
|
|
|
+ render: (_: any, record: PadLockVO) => (
|
|
|
+ <Space>
|
|
|
+ <Button
|
|
|
+ type="link"
|
|
|
+ icon={<Edit2 className="w-4 h-4" />}
|
|
|
+ onClick={() => {
|
|
|
+ // TODO: 实现编辑功能
|
|
|
+ toast.info('编辑功能待实现');
|
|
|
+ }}
|
|
|
+ title="编辑"
|
|
|
+ />
|
|
|
+ <Button
|
|
|
+ type="link"
|
|
|
+ danger
|
|
|
+ icon={<Trash2 className="w-4 h-4" />}
|
|
|
+ onClick={() => handleDelete(record.lockId!, record.lockName)}
|
|
|
+ title="删除"
|
|
|
+ />
|
|
|
+ </Space>
|
|
|
+ ),
|
|
|
+ },
|
|
|
+ ];
|
|
|
+
|
|
|
+ // 挂锁类型表格列
|
|
|
+ const padLockTypeColumns: ColumnsType<PadLockTypeVO> = [
|
|
|
+ {
|
|
|
+ title: '序号',
|
|
|
+ width: 80,
|
|
|
+ align: 'center',
|
|
|
+ render: (_: any, __: PadLockTypeVO, index: number) => {
|
|
|
+ return (typeQueryParams.pageNo - 1) * typeQueryParams.pageSize + index + 1;
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '类型编号',
|
|
|
+ dataIndex: 'lockTypeId',
|
|
|
+ width: 100,
|
|
|
+ align: 'center',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '类型编码',
|
|
|
+ dataIndex: 'lockTypeCode',
|
|
|
+ width: 150,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '类型名称',
|
|
|
+ dataIndex: 'lockTypeName',
|
|
|
+ width: 200,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '父类型',
|
|
|
+ dataIndex: 'parentTypeId',
|
|
|
+ width: 100,
|
|
|
+ align: 'center',
|
|
|
+ render: (id: number) => id || '-',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '状态',
|
|
|
+ dataIndex: 'enableFlag',
|
|
|
+ width: 100,
|
|
|
+ align: 'center',
|
|
|
+ render: (flag: string) => {
|
|
|
+ return flag === '1' || flag === 'Y' ? '启用' : '禁用';
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '备注',
|
|
|
+ dataIndex: 'remark',
|
|
|
+ ellipsis: true,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '操作',
|
|
|
+ width: 120,
|
|
|
+ align: 'center',
|
|
|
+ fixed: 'right',
|
|
|
+ render: (_: any, record: PadLockTypeVO) => (
|
|
|
+ <Space>
|
|
|
+ <Button
|
|
|
+ type="link"
|
|
|
+ icon={<Edit2 className="w-4 h-4" />}
|
|
|
+ onClick={() => openTypeForm('update', record.lockTypeId)}
|
|
|
+ title="编辑"
|
|
|
+ />
|
|
|
+ <Button
|
|
|
+ type="link"
|
|
|
+ danger
|
|
|
+ icon={<Trash2 className="w-4 h-4" />}
|
|
|
+ onClick={() => handleDeleteType(record.lockTypeId!, record.lockTypeName)}
|
|
|
+ title="删除"
|
|
|
+ />
|
|
|
+ </Space>
|
|
|
+ ),
|
|
|
+ },
|
|
|
+ ];
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div className="space-y-4">
|
|
|
+ {viewMode === 'list' ? (
|
|
|
+ <>
|
|
|
+ {/* 挂锁列表搜索栏 */}
|
|
|
+ <div className="bg-white rounded-xl border border-gray-200/50 shadow-sm p-5">
|
|
|
+ <div className="flex items-center justify-between gap-4 flex-wrap">
|
|
|
+ {/* 搜索输入框 */}
|
|
|
+ <div className="flex items-center gap-3 flex-wrap flex-1">
|
|
|
+ <div className="flex items-center gap-3">
|
|
|
+ <label className="text-sm font-medium text-gray-700 whitespace-nowrap">挂锁编码:</label>
|
|
|
+ <Input
|
|
|
+ value={queryParams.lockCode || ''}
|
|
|
+ onChange={(e) => setQueryParams({ ...queryParams, lockCode: e.target.value })}
|
|
|
+ onPressEnter={handleQuery}
|
|
|
+ placeholder="请输入挂锁编码"
|
|
|
+ style={{ width: 192 }}
|
|
|
+ allowClear
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div className="flex items-center gap-3">
|
|
|
+ <label className="text-sm font-medium text-gray-700 whitespace-nowrap">挂锁名称:</label>
|
|
|
+ <Input
|
|
|
+ value={queryParams.lockName || ''}
|
|
|
+ onChange={(e) => setQueryParams({ ...queryParams, lockName: e.target.value })}
|
|
|
+ onPressEnter={handleQuery}
|
|
|
+ placeholder="请输入挂锁名称"
|
|
|
+ style={{ width: 192 }}
|
|
|
+ allowClear
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* 操作按钮组 */}
|
|
|
+ <Space>
|
|
|
+ <Button
|
|
|
+ type="primary"
|
|
|
+ icon={<Search className="w-4 h-4" />}
|
|
|
+ onClick={handleQuery}
|
|
|
+ >
|
|
|
+ 搜索
|
|
|
+ </Button>
|
|
|
+
|
|
|
+ <Button
|
|
|
+ icon={<RefreshCw className="w-4 h-4" />}
|
|
|
+ onClick={resetQuery}
|
|
|
+ >
|
|
|
+ 重置
|
|
|
+ </Button>
|
|
|
+
|
|
|
+ <Button
|
|
|
+ type="primary"
|
|
|
+ icon={<Plus className="w-4 h-4" />}
|
|
|
+ onClick={() => {
|
|
|
+ // TODO: 实现新增挂锁功能
|
|
|
+ toast.info('新增挂锁功能待实现');
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ 新增
|
|
|
+ </Button>
|
|
|
+
|
|
|
+ <Button
|
|
|
+ icon={<Settings className="w-4 h-4" />}
|
|
|
+ onClick={() => setViewMode('type')}
|
|
|
+ >
|
|
|
+ 设置挂锁类型
|
|
|
+ </Button>
|
|
|
+ </Space>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* 挂锁列表表格 */}
|
|
|
+ <div className="bg-white rounded-2xl border border-gray-200/50 shadow-sm overflow-hidden">
|
|
|
+ <Table
|
|
|
+ columns={padLockColumns}
|
|
|
+ dataSource={list}
|
|
|
+ rowKey="lockId"
|
|
|
+ loading={loading}
|
|
|
+ pagination={false}
|
|
|
+ scroll={{ x: 'max-content' }}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* 分页 */}
|
|
|
+ {!loading && list.length > 0 && (
|
|
|
+ <div className="bg-white rounded-lg border border-gray-200 px-6 py-4">
|
|
|
+ <div className="flex items-center justify-between">
|
|
|
+ <div className="text-sm text-gray-600">
|
|
|
+ 共 <span className="text-blue-600 font-medium">{total}</span> 条记录
|
|
|
+ </div>
|
|
|
+ <div className="flex gap-2">
|
|
|
+ <Button
|
|
|
+ onClick={() => setQueryParams({ ...queryParams, pageNo: queryParams.pageNo! - 1 })}
|
|
|
+ disabled={queryParams.pageNo! <= 1}
|
|
|
+ >
|
|
|
+ 上一页
|
|
|
+ </Button>
|
|
|
+ <span className="px-4 py-2 text-sm text-gray-600 flex items-center">
|
|
|
+ {queryParams.pageNo} / {Math.ceil(total / queryParams.pageSize!) || 1}
|
|
|
+ </span>
|
|
|
+ <Button
|
|
|
+ onClick={() => setQueryParams({ ...queryParams, pageNo: queryParams.pageNo! + 1 })}
|
|
|
+ disabled={queryParams.pageNo! >= Math.ceil(total / queryParams.pageSize!)}
|
|
|
+ >
|
|
|
+ 下一页
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+ </>
|
|
|
+ ) : (
|
|
|
+ <>
|
|
|
+ {/* 挂锁类型搜索栏 */}
|
|
|
+ <div className="bg-white rounded-xl border border-gray-200/50 shadow-sm p-5">
|
|
|
+ <div className="flex items-center justify-between gap-4 flex-wrap">
|
|
|
+ {/* 搜索输入框 */}
|
|
|
+ <div className="flex items-center gap-3 flex-wrap flex-1">
|
|
|
+ <div className="flex items-center gap-3">
|
|
|
+ <label className="text-sm font-medium text-gray-700 whitespace-nowrap">类型编码:</label>
|
|
|
+ <Input
|
|
|
+ value={typeQueryParams.lockTypeCode || ''}
|
|
|
+ onChange={(e) => setTypeQueryParams({ ...typeQueryParams, lockTypeCode: e.target.value })}
|
|
|
+ onPressEnter={handleTypeQuery}
|
|
|
+ placeholder="请输入类型编码"
|
|
|
+ style={{ width: 192 }}
|
|
|
+ allowClear
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div className="flex items-center gap-3">
|
|
|
+ <label className="text-sm font-medium text-gray-700 whitespace-nowrap">类型名称:</label>
|
|
|
+ <Input
|
|
|
+ value={typeQueryParams.lockTypeName || ''}
|
|
|
+ onChange={(e) => setTypeQueryParams({ ...typeQueryParams, lockTypeName: e.target.value })}
|
|
|
+ onPressEnter={handleTypeQuery}
|
|
|
+ placeholder="请输入类型名称"
|
|
|
+ style={{ width: 192 }}
|
|
|
+ allowClear
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* 操作按钮组 */}
|
|
|
+ <Space>
|
|
|
+ <Button
|
|
|
+ type="primary"
|
|
|
+ icon={<Search className="w-4 h-4" />}
|
|
|
+ onClick={handleTypeQuery}
|
|
|
+ >
|
|
|
+ 搜索
|
|
|
+ </Button>
|
|
|
+
|
|
|
+ <Button
|
|
|
+ icon={<RefreshCw className="w-4 h-4" />}
|
|
|
+ onClick={resetTypeQuery}
|
|
|
+ >
|
|
|
+ 重置
|
|
|
+ </Button>
|
|
|
+
|
|
|
+ <Button
|
|
|
+ type="primary"
|
|
|
+ icon={<Plus className="w-4 h-4" />}
|
|
|
+ onClick={() => openTypeForm('create')}
|
|
|
+ >
|
|
|
+ 新增
|
|
|
+ </Button>
|
|
|
+
|
|
|
+ <Button
|
|
|
+ onClick={() => setViewMode('list')}
|
|
|
+ >
|
|
|
+ 返回挂锁列表
|
|
|
+ </Button>
|
|
|
+ </Space>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* 挂锁类型表格 */}
|
|
|
+ <div className="bg-white rounded-2xl border border-gray-200/50 shadow-sm overflow-hidden">
|
|
|
+ <Table
|
|
|
+ columns={padLockTypeColumns}
|
|
|
+ dataSource={typeList}
|
|
|
+ rowKey="lockTypeId"
|
|
|
+ loading={typeLoading}
|
|
|
+ pagination={false}
|
|
|
+ scroll={{ x: 'max-content' }}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* 分页 */}
|
|
|
+ {!typeLoading && typeList.length > 0 && (
|
|
|
+ <div className="bg-white rounded-lg border border-gray-200 px-6 py-4">
|
|
|
+ <div className="flex items-center justify-between">
|
|
|
+ <div className="text-sm text-gray-600">
|
|
|
+ 共 <span className="text-blue-600 font-medium">{typeTotal}</span> 条记录
|
|
|
+ </div>
|
|
|
+ <div className="flex gap-2">
|
|
|
+ <Button
|
|
|
+ onClick={() => setTypeQueryParams({ ...typeQueryParams, pageNo: typeQueryParams.pageNo! - 1 })}
|
|
|
+ disabled={typeQueryParams.pageNo! <= 1}
|
|
|
+ >
|
|
|
+ 上一页
|
|
|
+ </Button>
|
|
|
+ <span className="px-4 py-2 text-sm text-gray-600 flex items-center">
|
|
|
+ {typeQueryParams.pageNo} / {Math.ceil(typeTotal / typeQueryParams.pageSize!) || 1}
|
|
|
+ </span>
|
|
|
+ <Button
|
|
|
+ onClick={() => setTypeQueryParams({ ...typeQueryParams, pageNo: typeQueryParams.pageNo! + 1 })}
|
|
|
+ disabled={typeQueryParams.pageNo! >= Math.ceil(typeTotal / typeQueryParams.pageSize!)}
|
|
|
+ >
|
|
|
+ 下一页
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+
|
|
|
+ {/* 挂锁类型表单弹窗 */}
|
|
|
+ {showTypeForm && (
|
|
|
+ <TypeFormModal
|
|
|
+ visible={showTypeForm}
|
|
|
+ editingType={editingType}
|
|
|
+ onCancel={() => {
|
|
|
+ setShowTypeForm(false);
|
|
|
+ setEditingType(null);
|
|
|
+ }}
|
|
|
+ onSave={saveType}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ </>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+// 挂锁类型表单弹窗组件
|
|
|
+interface TypeFormModalProps {
|
|
|
+ visible: boolean;
|
|
|
+ editingType: PadLockTypeVO | null;
|
|
|
+ onCancel: () => void;
|
|
|
+ onSave: (data: PadLockTypeVO) => void;
|
|
|
+}
|
|
|
+
|
|
|
+function TypeFormModal({ visible, editingType, onCancel, onSave }: TypeFormModalProps) {
|
|
|
+ const [formData, setFormData] = useState<PadLockTypeVO>({
|
|
|
+ lockTypeCode: '',
|
|
|
+ lockTypeName: '',
|
|
|
+ parentTypeId: undefined,
|
|
|
+ enableFlag: '1',
|
|
|
+ remark: '',
|
|
|
+ });
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ if (editingType) {
|
|
|
+ setFormData({
|
|
|
+ lockTypeCode: editingType.lockTypeCode || '',
|
|
|
+ lockTypeName: editingType.lockTypeName || '',
|
|
|
+ parentTypeId: editingType.parentTypeId,
|
|
|
+ enableFlag: editingType.enableFlag || '1',
|
|
|
+ remark: editingType.remark || '',
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ setFormData({
|
|
|
+ lockTypeCode: '',
|
|
|
+ lockTypeName: '',
|
|
|
+ parentTypeId: undefined,
|
|
|
+ enableFlag: '1',
|
|
|
+ remark: '',
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }, [editingType, visible]);
|
|
|
+
|
|
|
+ const handleSubmit = () => {
|
|
|
+ if (!formData.lockTypeCode.trim()) {
|
|
|
+ toast.error('请输入类型编码');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (!formData.lockTypeName.trim()) {
|
|
|
+ toast.error('请输入类型名称');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ onSave(formData);
|
|
|
+ };
|
|
|
+
|
|
|
+ return (
|
|
|
+ <Modal
|
|
|
+ title={editingType ? '编辑挂锁类型' : '新增挂锁类型'}
|
|
|
+ open={visible}
|
|
|
+ onOk={handleSubmit}
|
|
|
+ onCancel={onCancel}
|
|
|
+ okText="确定"
|
|
|
+ cancelText="取消"
|
|
|
+ width={600}
|
|
|
+ >
|
|
|
+ <div className="space-y-4 mt-4">
|
|
|
+ <div>
|
|
|
+ <label className="block text-sm text-gray-700 mb-2">类型编码 *</label>
|
|
|
+ <Input
|
|
|
+ value={formData.lockTypeCode}
|
|
|
+ onChange={(e) => setFormData({ ...formData, lockTypeCode: e.target.value })}
|
|
|
+ placeholder="请输入类型编码"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <label className="block text-sm text-gray-700 mb-2">类型名称 *</label>
|
|
|
+ <Input
|
|
|
+ value={formData.lockTypeName}
|
|
|
+ onChange={(e) => setFormData({ ...formData, lockTypeName: e.target.value })}
|
|
|
+ placeholder="请输入类型名称"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <label className="block text-sm text-gray-700 mb-2">父类型ID</label>
|
|
|
+ <Input
|
|
|
+ type="number"
|
|
|
+ value={formData.parentTypeId || ''}
|
|
|
+ onChange={(e) => setFormData({
|
|
|
+ ...formData,
|
|
|
+ parentTypeId: e.target.value ? Number(e.target.value) : undefined
|
|
|
+ })}
|
|
|
+ placeholder="请输入父类型ID(可选)"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <label className="block text-sm text-gray-700 mb-2">状态</label>
|
|
|
+ <Select
|
|
|
+ value={formData.enableFlag}
|
|
|
+ onChange={(value) => setFormData({ ...formData, enableFlag: value })}
|
|
|
+ style={{ width: '100%' }}
|
|
|
+ >
|
|
|
+ <Select.Option value="1">启用</Select.Option>
|
|
|
+ <Select.Option value="0">禁用</Select.Option>
|
|
|
+ </Select>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <label className="block text-sm text-gray-700 mb-2">备注</label>
|
|
|
+ <Input.TextArea
|
|
|
+ value={formData.remark}
|
|
|
+ onChange={(e) => setFormData({ ...formData, remark: e.target.value })}
|
|
|
+ placeholder="请输入备注"
|
|
|
+ rows={3}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </Modal>
|
|
|
+ );
|
|
|
+}
|
|
|
+
|