公告用户前端以及管理员
Change-Id: I3ea4a7f62ae91ef97734d6d673cce28855d10eeb
diff --git a/src/components/ActivityAdminPanel.jsx b/src/components/ActivityAdminPanel.jsx
new file mode 100644
index 0000000..5c0ce26
--- /dev/null
+++ b/src/components/ActivityAdminPanel.jsx
@@ -0,0 +1,269 @@
+import React, { useEffect, useState } from 'react';
+import {
+ Table, Button, Modal, Image, message, Tag,
+ Space, Input, Tooltip, Form, Upload
+} from 'antd';
+import {
+ ExclamationCircleOutlined, SearchOutlined, UploadOutlined
+} from '@ant-design/icons';
+import {
+ getAllActivities,
+ searchActivitiesByTitle,
+ deleteActivity,
+ createActivity,
+ updateActivity
+} from '../api/activity';
+
+const { confirm } = Modal;
+
+const ActivityAdminPanel = () => {
+ const [activities, setActivities] = useState([]);
+ const [loading, setLoading] = useState(false);
+ const [keyword, setKeyword] = useState('');
+ const [modalVisible, setModalVisible] = useState(false);
+ const [editMode, setEditMode] = useState(false);
+ const [currentActivity, setCurrentActivity] = useState(null);
+ const [form] = Form.useForm();
+
+ const fetchActivities = async () => {
+ setLoading(true);
+ try {
+ const data = keyword.trim()
+ ? await searchActivitiesByTitle(keyword.trim())
+ : await getAllActivities();
+ setActivities(data.data || []);
+ } catch (error) {
+ message.error('获取公告失败');
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ useEffect(() => {
+ fetchActivities();
+ }, []);
+
+ const handleSearch = () => {
+ fetchActivities();
+ };
+
+ const handleDelete = (activityid) => {
+ confirm({
+ title: '确认删除该公告吗?',
+ icon: <ExclamationCircleOutlined />,
+ okText: '删除',
+ okType: 'danger',
+ cancelText: '取消',
+ onOk: async () => {
+ try {
+ const res = await deleteActivity(activityid);
+ if (res.data === true) {
+ message.success('删除成功');
+ fetchActivities();
+ } else {
+ message.error('删除失败');
+ }
+ } catch {
+ message.error('删除请求失败');
+ }
+ },
+ });
+ };
+
+ const openEditModal = (record) => {
+ setEditMode(true);
+ setCurrentActivity(record);
+ form.setFieldsValue({
+ activityid: record.activityid,
+ title: record.title,
+ content: record.content,
+ isShow: record.is_show,
+ });
+ setModalVisible(true);
+ };
+
+ const openCreateModal = () => {
+ setEditMode(false);
+ form.resetFields();
+ setModalVisible(true);
+ };
+
+ const handleModalOk = async () => {
+ try {
+ const values = await form.validateFields();
+ const formData = new FormData();
+ Object.keys(values).forEach(key => {
+ if (key !== 'photo' && values[key] !== undefined) {
+ formData.append(key, values[key]);
+ }
+ });
+ if (values.photo && values.photo.file) {
+ formData.append('photo', values.photo.file);
+ }
+
+ const res = editMode
+ ? await updateActivity(formData)
+ : await createActivity(formData);
+
+ if (res.data === true) {
+ message.success(editMode ? '修改成功' : '创建成功');
+ setModalVisible(false);
+ fetchActivities();
+ } else {
+ message.error('提交失败');
+ }
+ } catch (error) {
+ message.error('提交失败,请检查表单');
+ }
+ };
+
+ const columns = [
+ {
+ title: 'ID',
+ dataIndex: 'activityid',
+ key: 'activityid',
+ width: 80,
+ },
+ {
+ title: '标题',
+ dataIndex: 'title',
+ key: 'title',
+ width: 200,
+ ellipsis: true,
+ },
+ {
+ title: '内容',
+ dataIndex: 'content',
+ key: 'content',
+ ellipsis: { showTitle: false },
+ render: (text) => (
+ <Tooltip placement="topLeft" title={text}>
+ {text}
+ </Tooltip>
+ ),
+ },
+ {
+ title: '图片',
+ dataIndex: 'photo',
+ key: 'photo',
+ width: 100,
+ render: (url) =>
+ url ? (
+ <Image
+ src={`http://localhost:8080${url}`}
+ width={80}
+ height={80}
+ style={{ objectFit: 'cover' }}
+ />
+ ) : (
+ <Tag color="default">无</Tag>
+ ),
+ },
+ {
+ title: '展示状态',
+ dataIndex: 'is_show',
+ key: 'is_show',
+ width: 100,
+ render: (val) =>
+ val === 0 ? <Tag color="green">展示</Tag> : <Tag color="red">隐藏</Tag>,
+ },
+ {
+ title: '发布时间',
+ dataIndex: 'time',
+ key: 'time',
+ width: 180,
+ render: (time) =>
+ time ? new Date(time).toLocaleString() : <Tag color="default">暂无</Tag>,
+ },
+ {
+ title: '操作',
+ key: 'action',
+ width: 180,
+ render: (_, record) => (
+ <Space size="middle">
+ <Button type="primary" onClick={() => openEditModal(record)}>
+ 修改
+ </Button>
+ <Button danger onClick={() => handleDelete(record.activityid)}>
+ 删除
+ </Button>
+ </Space>
+ ),
+ },
+ ];
+
+ return (
+ <div style={{ padding: 20 }}>
+ <h2 style={{ marginBottom: 20 }}>公告管理面板</h2>
+ <Space style={{ marginBottom: 16 }}>
+ <Input
+ placeholder="请输入标题关键词"
+ value={keyword}
+ onChange={(e) => setKeyword(e.target.value)}
+ style={{ width: 300 }}
+ />
+ <Button type="primary" icon={<SearchOutlined />} onClick={handleSearch}>
+ 搜索
+ </Button>
+ <Button onClick={() => { setKeyword(''); fetchActivities(); }}>
+ 重置
+ </Button>
+ <Button type="primary" onClick={openCreateModal}>
+ 新建公告
+ </Button>
+ </Space>
+ <Table
+ rowKey="activityid"
+ columns={columns}
+ dataSource={activities}
+ loading={loading}
+ scroll={{ x: 1200 }}
+ pagination={{ pageSize: 8 }}
+ bordered
+ size="middle"
+ />
+
+ <Modal
+ title={editMode ? '修改公告' : '新建公告'}
+ open={modalVisible}
+ onOk={handleModalOk}
+ onCancel={() => setModalVisible(false)}
+ okText="提交"
+ cancelText="取消"
+ destroyOnClose
+ >
+ <Form form={form} layout="vertical" preserve={false}>
+ {editMode && (
+ <Form.Item name="activityid" hidden>
+ <Input />
+ </Form.Item>
+ )}
+ <Form.Item
+ name="title"
+ label="标题"
+ rules={[{ required: true, message: '请输入标题' }]}
+ >
+ <Input />
+ </Form.Item>
+ <Form.Item
+ name="content"
+ label="内容"
+ rules={[{ required: true, message: '请输入内容' }]}
+ >
+ <Input.TextArea rows={4} />
+ </Form.Item>
+ <Form.Item name="isShow" label="是否展示">
+ <Input placeholder="0 表示展示,1 表示隐藏" />
+ </Form.Item>
+ <Form.Item name="photo" label="上传图片">
+ <Upload beforeUpload={() => false} maxCount={1}>
+ <Button icon={<UploadOutlined />}>选择文件</Button>
+ </Upload>
+ </Form.Item>
+ </Form>
+ </Modal>
+ </div>
+ );
+};
+
+export default ActivityAdminPanel;