add message
All checks were successful
Build and Deploy Web / build-and-deploy (push) Successful in 1m34s

This commit is contained in:
zyc 2026-02-14 13:23:06 +08:00
parent b4108961fa
commit 94ac3687e5
4 changed files with 171 additions and 0 deletions

26
src/api/feedback.ts Normal file
View File

@ -0,0 +1,26 @@
import request from './request';
import type { ApiResponse, PaginatedResponse } from './request';
// 意见反馈类型
export interface Feedback {
id: number;
user_phone: string;
user_nickname: string;
content: string;
contact: string;
created_at: string;
}
// 获取反馈列表
export const getFeedbacks = (params?: {
page?: number;
page_size?: number;
phone?: string;
}) => {
return request.get<unknown, ApiResponse<PaginatedResponse<Feedback>>>('/api/admin/feedbacks/', { params });
};
// 获取反馈详情
export const getFeedback = (id: number) => {
return request.get<unknown, ApiResponse<Feedback>>(`/api/admin/feedbacks/${id}/`);
};

View File

@ -17,6 +17,7 @@ import {
MobileOutlined,
UserOutlined,
TeamOutlined,
MessageOutlined,
LogoutOutlined,
MenuFoldOutlined,
MenuUnfoldOutlined,
@ -56,6 +57,11 @@ const menuItems = [
icon: <TeamOutlined />,
label: '管理员',
},
{
key: '/feedbacks',
icon: <MessageOutlined />,
label: '意见反馈',
},
];
const MainLayout: React.FC = () => {

View File

@ -0,0 +1,134 @@
import React, { useRef, useState } from 'react';
import { Button, message, Modal, Descriptions } from 'antd';
import { ProTable } from '@ant-design/pro-components';
import type { ProColumns, ActionType } from '@ant-design/pro-components';
import { getFeedbacks } from '../../api/feedback';
import type { Feedback } from '../../api/feedback';
const FeedbackPage: React.FC = () => {
const actionRef = useRef<ActionType>(null);
const [detailVisible, setDetailVisible] = useState(false);
const [currentRecord, setCurrentRecord] = useState<Feedback | null>(null);
const handleView = (record: Feedback) => {
setCurrentRecord(record);
setDetailVisible(true);
};
const columns: ProColumns<Feedback>[] = [
{
title: 'ID',
dataIndex: 'id',
width: 80,
search: false,
},
{
title: '用户手机号',
dataIndex: 'user_phone',
width: 140,
render: (_, record) => {
const phone = record.user_phone;
return phone ? phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2') : '-';
},
},
{
title: '用户昵称',
dataIndex: 'user_nickname',
width: 120,
search: false,
ellipsis: true,
},
{
title: '反馈内容',
dataIndex: 'content',
ellipsis: true,
search: false,
},
{
title: '联系方式',
dataIndex: 'contact',
width: 140,
search: false,
render: (_, record) => record.contact || '-',
},
{
title: '提交时间',
dataIndex: 'created_at',
valueType: 'dateTime',
width: 180,
search: false,
},
{
title: '操作',
width: 80,
search: false,
render: (_, record) => (
<Button type="link" size="small" onClick={() => handleView(record)}>
</Button>
),
},
];
return (
<>
<ProTable<Feedback>
headerTitle="意见反馈"
rowKey="id"
actionRef={actionRef}
columns={columns}
cardBordered
request={async (params) => {
try {
const res = await getFeedbacks({
page: params.current,
page_size: params.pageSize,
phone: params.user_phone,
});
return {
data: res.data.items,
total: res.data.total,
success: true,
};
} catch {
message.error('获取数据失败');
return { data: [], total: 0, success: false };
}
}}
pagination={{
defaultPageSize: 10,
showSizeChanger: true,
}}
/>
<Modal
title="反馈详情"
open={detailVisible}
onCancel={() => setDetailVisible(false)}
footer={null}
width={600}
>
{currentRecord && (
<Descriptions column={1} style={{ marginTop: 24 }}>
<Descriptions.Item label="用户手机号">
{currentRecord.user_phone}
</Descriptions.Item>
<Descriptions.Item label="用户昵称">
{currentRecord.user_nickname || '-'}
</Descriptions.Item>
<Descriptions.Item label="反馈内容">
<div style={{ whiteSpace: 'pre-wrap' }}>{currentRecord.content}</div>
</Descriptions.Item>
<Descriptions.Item label="联系方式">
{currentRecord.contact || '-'}
</Descriptions.Item>
<Descriptions.Item label="提交时间">
{currentRecord.created_at}
</Descriptions.Item>
</Descriptions>
)}
</Modal>
</>
);
};
export default FeedbackPage;

View File

@ -9,6 +9,7 @@ import BatchDetail from '../pages/Batch/Detail';
import DevicePage from '../pages/Device';
import UserPage from '../pages/User';
import AdminPage from '../pages/Admin';
import FeedbackPage from '../pages/Feedback';
import { useAuthStore } from '../store/useAuthStore';
// 路由守卫组件
@ -68,6 +69,10 @@ const router = createBrowserRouter([
path: 'admins',
element: <AdminPage />,
},
{
path: 'feedbacks',
element: <FeedbackPage />,
},
],
},
{