Ver código fonte

fix:若干bug

lvkun 4 anos atrás
pai
commit
543bb5b9c5

+ 7 - 1
src/pages/agent/list/detail.tsx

@@ -56,7 +56,13 @@ const DetailModal: React.FC<DetailModalType> = ({ visible, id, closeModal }) =>
           userInfo.followBars.map((item) => (
             <Col key={item.id} span={4}>
               <Space direction="vertical" align="center">
-                <Image width={50} height={50} src={item.avatarUrl} alt="我炸裂了"></Image>
+                <Image
+                  style={{ objectFit: 'cover' }}
+                  width={50}
+                  height={50}
+                  src={item.avatarUrl}
+                  alt="我炸裂了"
+                />
                 <span>{item.label}</span>
               </Space>
             </Col>

+ 254 - 235
src/pages/agent/list/index.tsx

@@ -1,235 +1,254 @@
-import React, { useEffect, useState, useReducer} from 'react'
-
-import { getAgent, stopOrOpenAgent } from '@/services/agent'
-import { getRoleList } from '@/services/role'
-import { Button, Card, Col, Input, Row, Select, Space, Table, message, Tag} from 'antd';
-import { PageContainer } from '@ant-design/pro-layout'
-import DetailModal from './detail'
-;
-
-const { Option } = Select
-
-type User = {
-  id: string,
-  nickName: string;
-  phoneNumber: number,
-  region: string,
-  authRoles: string,
-  followBarNum: number,
-  postsNum: number,
-  state: number,
-  caeateTime: string,
-  action?: React.ReactNode
-}
-
-export type roleListType = {
-    id: string,
-    label: string,
-    [key: string]: any
-}
-  
-type initStateType =  {
-    curPage: number,
-    roleId: string,
-    state: number ,
-    label: string | number
-}
-
-type Action = {
-    type: string,
-    [key: string]: any
-}
-
-const initState: initStateType = {
-  curPage: 1,
-  roleId: '',
-  state: 2,
-  label: ''
-}
-
-const reducer: React.Reducer<initStateType, Action> = (  State, action): initStateType => {
-    const { type , value} = action
-
-    switch (type) {
-        case 'page':
-            return { ...State, curPage: value }
-        case 'state':
-            return { ...State, state: value }
-        case 'label':
-            return { ...State, label: value }
-        case 'roleId':
-            return { ...State, roleId: value }
-        case 'reload':
-            return { ...State, roleId: '', state: 2, label: '' }
-        default:
-            throw new Error('没有对应的initStateType类型')
-    }
-}
-
-const Agent: React.FC = () => {
-
-    const [state, dispatch] = useReducer(reducer, initState)
-
-    const [agentList, setAgentList] = useState<User[]>([])
-
-    const [roleList, setRoleList] = useState<roleListType[]>([])
-    const [total, setTotal] = useState<number>(0)
-    const [loading, setLoading] = useState<boolean>(false)
-
-    // 弹窗
-    const [visible, setVisible] = useState<boolean>(false)
-
-    // 当前点击的代理商
-    const [id, setId] = useState<string>('')
-
-
-    
-    // 获取代理商列表
-    const GetAgent = async () => {
-        setLoading(true)
-        const {code, data } = await getAgent(state)
-        setLoading(false)
-        if (code === 0) {
-            const {records, total: Total} = data
-            setAgentList(records)
-            setTotal(Total)
-        }
-    }
-
-    // 获取权限列表
-    const GetRoleList = async () => {
-        const { code, data } = await getRoleList({curPage: 1})
-        if ( code === 0) {
-          const { records } = data
-          setRoleList([{id: '', label: '全部'}, ...records])
-        }
-    }
-
-    // 停用或者启用代理商
-    const StopOrOpenAgent = async (text: Record<string, any>, index: number): Promise<void> => {
-      const {code} =  await stopOrOpenAgent (text.id, {state: text.state})
-      if (code === 0) {
-         const a = {...text, state: text.state === 1 ? 0 : 1}
-         const b = JSON.parse( JSON.stringify(agentList))
-         b.splice(index, 1, a )
-         setAgentList(b)
-         message.success('操作成功')
-      }
-    }
-   
-    useEffect( () => {
-        GetAgent()
-        GetRoleList()
-    }, [])
-
-    // 重置搜索条件
-    const reloadSate = ( ): void => dispatch({type: 'reload', value: ''})
-    // 打开弹窗
-    const openModal = (value: Record<string, any>): void => {setVisible(true); setId(value.id) }
-    
-    // 关闭弹窗
-    const closeModal = (): void => setVisible(false)
-
-    // 账户状态
-    const changeAccState = ( value: number ): void =>  dispatch({type: 'state', value})
-
-    // 手机号
-    const changePhone = ( e: React.ChangeEvent<HTMLInputElement> ): void => dispatch({type: 'label', value: e.target.value})
-
-    // 选择角色
-    const changeRole = ( value: string): void => dispatch({type: 'roleId', value})
-
-    // 分页
-    const pagination = (changePage: number): void =>  dispatch({type: 'page', value: changePage })
-
-    return (
-        <PageContainer title="代理商列表">
-            <Card>
-                <Row gutter={[16, 16]} justify="space-between">
-                    <Col span={10}>
-                        <Space>
-                            <Select
-                                placeholder="请选择认证角色" 
-                                style={{ width: 200 }} 
-                                onChange={changeRole}
-                                value={state.roleId}
-                            >
-                                {
-                                    roleList.map( item => (
-                                        <Option key={item.id} value={item.id}>{item.label}</Option>
-                                    ))
-                                }
-                               
-                            </Select>
-                            <Select 
-                                placeholder="请选择账号状态" 
-                                style={{ width: 200 }} 
-                                onChange={changeAccState}
-                                value={state.state}
-                            >
-                                <Option value={2}>全部</Option>  
-                                <Option value={1}>启用</Option>
-                                <Option value={0}>禁用</Option>
-                            </Select>
-                            <Input onChange={changePhone} value={state.label} style={{ width: 200 }}  placeholder="输入手机号/姓名"></Input>
-                        </Space>
-                    </Col>
-                    <Col>
-                        <Space>
-                            <Button type="primary" onClick={GetAgent}>搜索</Button>
-                            <Button onClick={reloadSate}>重置</Button>
-                        </Space>
-                    </Col>
-                </Row>
-                <Table
-                    rowKey={(record) => record.id}
-                    loading={loading}
-                    pagination={{total, showSizeChanger: false, onChange: pagination}} 
-                    dataSource={agentList}
-                >
-                    <Table.Column<User> title="姓名" dataIndex="nickName" key="nickName" />
-                    <Table.Column<User> title="手机号" dataIndex="phoneNumber" key="phoneNumber" />
-                    <Table.Column<User> title="地区" dataIndex="region" key="region"
-                        render={region =>  <span>{region || '未知地区'}</span> }
-                    />
-                    <Table.Column<User> title="认证角色" dataIndex="authRoles" key="authRoles"
-                        render={ authRoles => (
-                            <>
-                              {
-                                  authRoles.map( (item: Record<string, any>) => {
-                                      return <span key={item.id}>{item.roleLabel}</span>
-                                  })
-                              }
-                            </>
-                        ) }
-                    />
-                    <Table.Column<User> title="关注贴吧板块" dataIndex="followBarNum" key="followBarNum" />
-                    <Table.Column<User> title="发帖数" dataIndex="postsNum" key="postsNum" />
-                    <Table.Column<User> title="发帖数" dataIndex="postsNum" key="postsNum" />
-                    <Table.Column<User> title="账号状态" dataIndex="state" key="state" 
-                        render={ (text) => (<Tag color="blue" > {text === 1 ? '正常' : '禁用中'}  </Tag>)}
-                    />
-                    <Table.Column<User> title="日期" dataIndex="createTime" key="stcreateTimeate" />
-                    <Table.Column<User> key="action"  title="操作"
-                        render={(text, record, index) => (
-                            <Space>
-                            <a onClick={() => openModal(text)}>查看</a>
-                            <a onClick={() => StopOrOpenAgent(text, index)}>{text.state === 1 ? '禁用' : '启用'}</a>
-                            {/* <Dropdown overlay={menu}>
-                                  <a className="ant-dropdown-link" onClick={e => e.preventDefault()}>
-                                      更多 <DownOutlined />
-                                  </a>
-                            </Dropdown> */}
-                        </Space>
-                        )}
-                    />
-                </Table>
-            </Card>
-            {/* 详情弹窗 */}
-            {visible ? <DetailModal visible={visible} closeModal={closeModal} id={id} /> : null}
-           
-        </PageContainer>
-    )
-}
-
-export default Agent
+import React, { useEffect, useState, useReducer } from 'react';
+
+import { getAgent, stopOrOpenAgent } from '@/services/agent';
+import { getRoleList } from '@/services/role';
+import { Button, Card, Col, Input, Row, Select, Space, Table, message, Tag } from 'antd';
+import { PageContainer } from '@ant-design/pro-layout';
+import DetailModal from './detail';
+
+const { Option } = Select;
+
+type User = {
+  id: string;
+  nickName: string;
+  phoneNumber: number;
+  region: string;
+  authRoles: string;
+  followBarNum: number;
+  postsNum: number;
+  state: number;
+  caeateTime: string;
+  action?: React.ReactNode;
+};
+
+export type roleListType = {
+  id: string;
+  label: string;
+  [key: string]: any;
+};
+
+type initStateType = {
+  curPage: number;
+  roleId: string;
+  state: number;
+  label: string | number;
+};
+
+type Action = {
+  type: string;
+  [key: string]: any;
+};
+
+const initState: initStateType = {
+  curPage: 1,
+  roleId: '',
+  state: 2,
+  label: '',
+};
+
+const reducer: React.Reducer<initStateType, Action> = (State, action): initStateType => {
+  const { type, value } = action;
+
+  switch (type) {
+    case 'page':
+      return { ...State, curPage: value };
+    case 'state':
+      return { ...State, state: value };
+    case 'label':
+      return { ...State, label: value };
+    case 'roleId':
+      return { ...State, roleId: value };
+    case 'reload':
+      return { ...State, roleId: '', state: 2, label: '' };
+    default:
+      throw new Error('没有对应的initStateType类型');
+  }
+};
+
+const Agent: React.FC = () => {
+  const [state, dispatch] = useReducer(reducer, initState);
+
+  const [agentList, setAgentList] = useState<User[]>([]);
+
+  const [roleList, setRoleList] = useState<roleListType[]>([]);
+  const [total, setTotal] = useState<number>(0);
+  const [loading, setLoading] = useState<boolean>(false);
+
+  // 弹窗
+  const [visible, setVisible] = useState<boolean>(false);
+
+  // 当前点击的代理商
+  const [id, setId] = useState<string>('');
+
+  // 获取代理商列表
+  const GetAgent = async () => {
+    setLoading(true);
+    const { code, data } = await getAgent(state);
+    setLoading(false);
+    if (code === 0) {
+      const { records, total: Total } = data;
+      setAgentList(records);
+      setTotal(Total);
+    }
+  };
+
+  // 获取权限列表
+  const GetRoleList = async () => {
+    const { code, data } = await getRoleList({ curPage: 1 });
+    if (code === 0) {
+      const { records } = data;
+      setRoleList([{ id: '', label: '全部' }, ...records]);
+    }
+  };
+
+  // 停用或者启用代理商
+  const StopOrOpenAgent = async (text: Record<string, any>, index: number): Promise<void> => {
+    setLoading(true);
+    const { code } = await stopOrOpenAgent(text.id, { state: text.state === 1 ? 0 : 1 });
+    setLoading(false);
+    if (code === 0) {
+      const a = { ...text, state: text.state === 1 ? 0 : 1 };
+      const b = JSON.parse(JSON.stringify(agentList));
+      b.splice(index, 1, a);
+      setAgentList(b);
+      message.success('操作成功');
+    }
+  };
+
+  useEffect(() => {
+    GetAgent();
+    GetRoleList();
+  }, []);
+
+  // 重置搜索条件
+  const reloadSate = (): void => dispatch({ type: 'reload', value: '' });
+  // 打开弹窗
+  const openModal = (value: Record<string, any>): void => {
+    setVisible(true);
+    setId(value.id);
+  };
+
+  // 关闭弹窗
+  const closeModal = (): void => setVisible(false);
+
+  // 账户状态
+  const changeAccState = (value: number): void => dispatch({ type: 'state', value });
+
+  // 手机号
+  const changePhone = (e: React.ChangeEvent<HTMLInputElement>): void =>
+    dispatch({ type: 'label', value: e.target.value });
+
+  // 选择角色
+  const changeRole = (value: string): void => dispatch({ type: 'roleId', value });
+
+  // 分页
+  const pagination = (changePage: number): void => dispatch({ type: 'page', value: changePage });
+
+  return (
+    <PageContainer title="代理商列表">
+      <Card>
+        <Row gutter={[16, 16]} justify="space-between">
+          <Col span={10}>
+            <Space>
+              <Select
+                placeholder="请选择认证角色"
+                style={{ width: 200 }}
+                onChange={changeRole}
+                value={state.roleId}
+              >
+                {roleList.map((item) => (
+                  <Option key={item.id} value={item.id}>
+                    {item.label}
+                  </Option>
+                ))}
+              </Select>
+              <Select
+                placeholder="请选择账号状态"
+                style={{ width: 200 }}
+                onChange={changeAccState}
+                value={state.state}
+              >
+                <Option value={2}>全部</Option>
+                <Option value={1}>启用</Option>
+                <Option value={0}>禁用</Option>
+              </Select>
+              <Input
+                onChange={changePhone}
+                value={state.label}
+                style={{ width: 200 }}
+                placeholder="输入手机号/姓名"
+              ></Input>
+            </Space>
+          </Col>
+          <Col>
+            <Space>
+              <Button type="primary" onClick={GetAgent}>
+                搜索
+              </Button>
+              <Button onClick={reloadSate}>重置</Button>
+            </Space>
+          </Col>
+        </Row>
+        <Table
+          rowKey={(record) => record.id}
+          loading={loading}
+          pagination={{ total, showSizeChanger: false, onChange: pagination }}
+          dataSource={agentList}
+          style={{ marginTop: '20px' }}
+        >
+          <Table.Column<User> title="姓名" dataIndex="nickName" key="nickName" />
+          <Table.Column<User> title="手机号" dataIndex="phoneNumber" key="phoneNumber" />
+          <Table.Column<User>
+            title="地区"
+            dataIndex="region"
+            key="region"
+            render={(region) => <span>{region || '未知地区'}</span>}
+          />
+          <Table.Column<User>
+            title="认证角色"
+            dataIndex="authRoles"
+            key="authRoles"
+            render={(authRoles) => (
+              <>
+                {authRoles.map((item: Record<string, any>) => {
+                  return <span key={item.id}>{item.roleLabel}</span>;
+                })}
+              </>
+            )}
+          />
+          <Table.Column<User> title="关注贴吧板块" dataIndex="followBarNum" key="followBarNum" />
+          <Table.Column<User> title="发帖数" dataIndex="postsNum" key="postsNum" />
+          <Table.Column<User> title="发帖数" dataIndex="postsNum" key="postsNum" />
+          <Table.Column<User>
+            title="账号状态"
+            dataIndex="state"
+            key="state"
+            render={(text) => <Tag color="blue"> {text === 1 ? '正常' : '禁用中'} </Tag>}
+          />
+          <Table.Column<User> title="日期" dataIndex="createTime" key="stcreateTimeate" />
+          <Table.Column<User>
+            key="action"
+            title="操作"
+            render={(text, record, index) => (
+              <Space>
+                <a onClick={() => openModal(text)}>查看</a>
+                <a onClick={() => StopOrOpenAgent(text, index)}>
+                  {text.state === 1 ? '禁用' : '启用'}
+                </a>
+                {/* <Dropdown overlay={menu}>
+                                  <a className="ant-dropdown-link" onClick={e => e.preventDefault()}>
+                                      更多 <DownOutlined />
+                                  </a>
+                            </Dropdown> */}
+              </Space>
+            )}
+          />
+        </Table>
+      </Card>
+      {/* 详情弹窗 */}
+      {visible ? <DetailModal visible={visible} closeModal={closeModal} id={id} /> : null}
+    </PageContainer>
+  );
+};
+
+export default Agent;

+ 2 - 0
src/pages/club/model.tsx → src/pages/club/ClubModal.tsx

@@ -1,6 +1,8 @@
 import React from 'react';
 import { Modal, Input, Row, Col } from 'antd';
+
 import { role } from '@/types/role';
+
 const layout = {
   labelCol: { span: 5 },
   wrapperCol: { span: 16 },

+ 32 - 12
src/pages/club/index.tsx

@@ -1,5 +1,5 @@
 import React, { useEffect, useState } from 'react';
-import { Card, Row, Col, Table, Space, Divider, message } from 'antd';
+import { Card, Row, Col, Table, Space, Divider, message, Image } from 'antd';
 import { PageContainer } from '@ant-design/pro-layout';
 import { produce } from 'immer';
 
@@ -15,7 +15,7 @@ import { role } from '@/types/role';
 
 import { putRoleList } from '@/services/role';
 
-import ClubModal from './model';
+import ClubModal from './ClubModal';
 
 interface IProps {
   dispatch: Dispatch;
@@ -33,6 +33,7 @@ const Club: React.FC<IProps> = ({ dispatch, roleList }) => {
       isForbidden: null,
       label: '',
       previousLabel: '',
+      userCount: 0,
     },
   });
 
@@ -97,10 +98,29 @@ const Club: React.FC<IProps> = ({ dispatch, roleList }) => {
     getRoleList();
   };
 
+  // 禁用或者启用
+  const forbiddenState = async (records: role) => {
+    setState(
+      produce(state, (draft) => {
+        draft.loading = true;
+      }),
+    );
+    const $par = Object.assign({}, records, { isForbidden: !records.isForbidden });
+    const { code, data } = await putRoleList($par);
+    console.log(code, data);
+    if (code === 0 && data === 1) {
+      message.success($par.isForbidden ? '禁用成功' : '启用成功');
+    }
+    getRoleList();
+    setState(
+      produce(state, (draft) => {
+        draft.loading = false;
+      }),
+    );
+  };
+
   // 修改label
   const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
-    console.log(e);
-
     setState(
       produce(state, (draft) => {
         draft.curClub = {
@@ -116,25 +136,25 @@ const Club: React.FC<IProps> = ({ dispatch, roleList }) => {
       <Card>
         <Table loading={loading} dataSource={roleList} style={{ marginTop: 20 }}>
           <Table.Column
-            title="公告标题"
+            title="俱乐部分类"
             ellipsis
-            width={300}
-            key="previousLabel"
+            key="previousLabel "
             dataIndex="previousLabel"
           />
-          <Table.Column title="俱乐部名称" ellipsis width={300} key="label" dataIndex="label" />
-          <Table.Column title="人数" ellipsis width={300} key="label" dataIndex="label" />
+          <Table.Column title="俱乐部名称" ellipsis key="label" dataIndex="label" />
+          <Table.Column title="人数" ellipsis key="userCount" dataIndex="userCount" />
           <Table.Column
             title="操作"
             ellipsis
-            width={300}
             key="action"
             dataIndex="action"
-            render={(text, records) => (
+            render={(text, records: role) => (
               <Space>
                 <a onClick={() => openModal(records as role)}>修改</a>
                 <Divider type="vertical" />
-                <a>禁用</a>
+                <a onClick={() => forbiddenState(records as role)}>
+                  {records.isForbidden ? '禁用' : '启用'}
+                </a>
               </Space>
             )}
           />

+ 158 - 136
src/pages/complaint/admin/index.tsx

@@ -1,136 +1,158 @@
-import React, { useState, useEffect } from 'react'
-import { Card , Row, Col, Table, Input, Button, message, Space} from 'antd'
-import { PageContainer } from '@ant-design/pro-layout'
-
-import { getComplaint } from '@/services/complaint'
-
-import { enablePosts } from '@/services/tieba'
-import type { getComplaintType, articleTypeEnum } from './data'
-
-import AdminModal from './modal'
-
-
-
-const Complaint: React.FC = () => {
-
-    const [articleType, setArticleType] = useState('POSTS')
-    const [label, setLabel] = useState('')
-
-    const [complaintList, setComplaintList] = useState([])
-    const [total, setTotal] = useState(0)
-
-    const [complaintData, setComplaintData] = useState({})
-
-    const [visible, setVisible] = useState(false)
-
-    const [ loading, setLoading ] = useState(false)
-
-    const [curPage, setCurPage] = useState(1)
-
-     // 获取帖子
-    const GetComplaint = async (): Promise<void> => {
-        const $par = {
-            articleType,
-            label,
-            curPage: 1
-        }
-        setLoading(true)
-        const { code, data } = await getComplaint($par as getComplaintType)
-        setLoading(false)
-        if (code === 0) {
-            console.log(data);
-            const { records, total: Total} = data
-            setComplaintList(records)
-            setTotal(Total)
-        }
-    }
-
-    // 封禁 或者 解封帖子
-    const EnablePosts = async (record: Record<string, any>): Promise<void> => {
-       const $par = {
-         id: record.id,
-         enable: record.itemEnable ? 0 : 1,
-         type: articleType === 'POSTS'? 0 : 1
-       }
-       const { code } =  await enablePosts($par)
-       if (code === 0) {
-           message.success('操作成功')
-       }
-       GetComplaint()
-    }
-
-
-    useEffect( () => {
-        GetComplaint()
-    }, [articleType, curPage])
-
-    // 切换tab
-    const onTabChange = (key: string): void => setArticleType(key)
-    // 标题
-    const changeLabel = (e: React.ChangeEvent<HTMLInputElement>): void =>  setLabel(e.target.value)
-
-    // 打开弹窗
-    const openModal = (record: Record<string, any>): void => {
-        setVisible(true)
-        setComplaintData(record)
-    }
-    // 关闭弹窗
-    const closeModal = (): void => setVisible(false)
-
-    // 分页
-    const changePagination = (page: number): void => setCurPage(page) 
-    return (
-        <PageContainer
-            title="投诉管理"
-            onTabChange={onTabChange}
-            tabList={[
-                {
-                    key: 'POSTS',
-                    tab: '帖子'
-                },
-                {
-                    key: 'ISSUES',
-                    tab: '问答'
-                }
-            ]}
-        >
-            <Card>
-                <Row justify="space-between">
-                    <Col >
-                       <Input onChange={changeLabel} placeholder={ articleType === 'POSTS' ? '帖子标题' : '问答标题'} />
-                    </Col>
-                    <Col>
-                        <Button type="primary" onClick={GetComplaint}>搜索</Button>
-                    </Col>
-                </Row>
-                <Table dataSource={complaintList} style={{marginTop: 20}} loading={loading} pagination={{total, onChange: changePagination}}>
-                    <Table.Column key="itemLabel" dataIndex="itemLabel" title="标题"></Table.Column>
-                    <Table.Column key="reason" dataIndex="reason" title="投诉原因"></Table.Column>
-                    <Table.Column key="itemAuthor" dataIndex="itemAuthor" title="投诉人"></Table.Column>
-                    <Table.Column key="reportNum" dataIndex="reportNum" title="投诉次数"></Table.Column>
-                    <Table.Column key="action" dataIndex="action" title="操作"
-                        render={ (text, record: Record<string, any>) => (
-                            <Space>
-                                <a onClick={() => openModal(record)}>查看</a>
-                                <a onClick={() => EnablePosts(record)}>{record.itemEnable ? '封禁' : '恢复'}</a>
-                            </Space>
-                        )}
-                    ></Table.Column>
-                </Table>
-            </Card>
-            {/* 弹窗 */}
-            {
-                visible && <AdminModal
-                                visible={visible} 
-                                articleType={articleType as articleTypeEnum}  
-                                complaintData={complaintData}
-                                closeModal={closeModal}
-                            />
-            }
-            
-        </PageContainer>
-    )
-}
-
-
-export default Complaint
+import React, { useState, useEffect } from 'react';
+import { Card, Row, Col, Table, Input, Button, message, Space, Tag } from 'antd';
+import { PageContainer } from '@ant-design/pro-layout';
+
+import { getComplaint } from '@/services/complaint';
+
+import { enablePosts } from '@/services/tieba';
+import type { getComplaintType, articleTypeEnum } from './data';
+
+import AdminModal from './modal';
+
+const Complaint: React.FC = () => {
+  const [articleType, setArticleType] = useState('POSTS');
+  const [label, setLabel] = useState('');
+
+  const [complaintList, setComplaintList] = useState([]);
+  const [total, setTotal] = useState(0);
+
+  const [complaintData, setComplaintData] = useState({});
+
+  const [visible, setVisible] = useState(false);
+
+  const [loading, setLoading] = useState(false);
+
+  const [curPage, setCurPage] = useState(1);
+
+  useEffect(() => {
+    GetComplaint();
+  }, [articleType, curPage]);
+
+  // 获取帖子
+  const GetComplaint = async (): Promise<void> => {
+    const $par = {
+      articleType,
+      label,
+      curPage,
+    };
+    setLoading(true);
+    const { code, data } = await getComplaint($par as getComplaintType);
+    setLoading(false);
+    if (code === 0) {
+      console.log(data);
+      const { records, total: Total } = data;
+      setComplaintList(records);
+      setTotal(Total);
+    }
+  };
+
+  // 封禁 或者 解封帖子
+  const EnablePosts = async (record: Record<string, any>): Promise<void> => {
+    console.log(record, 'record.itemEnable');
+
+    const $par = {
+      id: record.id,
+      enable: record.itemEnable ? 0 : 1,
+      type: articleType === 'POSTS' ? 0 : 1,
+    };
+    const { code } = await enablePosts($par);
+    if (code === 0) {
+      message.success('操作成功');
+    }
+    GetComplaint();
+  };
+
+  // 切换tab
+  const onTabChange = (key: string): void => setArticleType(key);
+  // 标题
+  const changeLabel = (e: React.ChangeEvent<HTMLInputElement>): void => setLabel(e.target.value);
+
+  // 打开弹窗
+  const openModal = (record: Record<string, any>): void => {
+    setVisible(true);
+    setComplaintData(record);
+  };
+  // 关闭弹窗
+  const closeModal = (): void => setVisible(false);
+
+  // 分页
+  const changePagination = (page: number): void => {
+    setCurPage(page);
+  };
+  return (
+    <PageContainer
+      title="投诉管理"
+      onTabChange={onTabChange}
+      tabList={[
+        {
+          key: 'POSTS',
+          tab: '帖子',
+        },
+        {
+          key: 'ISSUES',
+          tab: '问答',
+        },
+      ]}
+    >
+      <Card>
+        <Row justify="space-between">
+          <Col>
+            <Input
+              onChange={changeLabel}
+              placeholder={articleType === 'POSTS' ? '帖子标题' : '问答标题'}
+            />
+          </Col>
+          <Col>
+            <Button type="primary" onClick={GetComplaint}>
+              搜索
+            </Button>
+          </Col>
+        </Row>
+        <Table
+          dataSource={complaintList}
+          style={{ marginTop: 20 }}
+          loading={loading}
+          pagination={{ total, onChange: changePagination }}
+        >
+          <Table.Column key="itemLabel" dataIndex="itemLabel" title="标题"></Table.Column>
+          <Table.Column key="reason" dataIndex="reason" title="投诉原因"></Table.Column>
+          <Table.Column
+            key="itemAuthor"
+            dataIndex="itemAuthor"
+            title="被投诉人"
+            render={(text) => <Tag color="blue">{text}</Tag>}
+          />
+          <Table.Column
+            key="userName"
+            dataIndex="userName"
+            title="投诉人"
+            render={(text) => <Tag color="#f50">{text}</Tag>}
+          />
+          <Table.Column key="reportNum" dataIndex="reportNum" title="投诉次数"></Table.Column>
+          <Table.Column
+            key="action"
+            dataIndex="action"
+            title="操作"
+            render={(text, record: Record<string, any>) => (
+              <Space>
+                <a onClick={() => openModal(record)}>查看</a>
+                <a onClick={() => EnablePosts(record)}>{record.itemEnable ? '封禁' : '恢复'}</a>
+              </Space>
+            )}
+          ></Table.Column>
+        </Table>
+      </Card>
+      {/* 弹窗 */}
+      {visible && (
+        <AdminModal
+          visible={visible}
+          articleType={articleType as articleTypeEnum}
+          complaintData={complaintData}
+          closeModal={closeModal}
+        />
+      )}
+    </PageContainer>
+  );
+};
+
+export default Complaint;

+ 19 - 2
src/pages/notice/index.tsx

@@ -1,6 +1,18 @@
 import React, { useState, useEffect } from 'react';
 import { PageContainer } from '@ant-design/pro-layout';
-import { Button, Card, Row, Col, Input, Table, Tooltip, Space, Popconfirm, message } from 'antd';
+import {
+  Button,
+  Card,
+  Row,
+  Col,
+  Input,
+  Table,
+  Tooltip,
+  Space,
+  Popconfirm,
+  message,
+  Divider,
+} from 'antd';
 
 import { getNotice, deleteNotice } from '@/services/notice';
 
@@ -38,6 +50,7 @@ const Notice: React.FC<IProps> = ({ dispatch, roleList }) => {
     const $par = {
       curPage,
       label,
+      type: 'ANN',
     };
     setLoading(true);
     const { code, data } = await getNotice($par);
@@ -68,6 +81,7 @@ const Notice: React.FC<IProps> = ({ dispatch, roleList }) => {
       console.log(data);
       message.success('删除成功');
     }
+
     GetNotice();
   };
   // 关闭弹窗
@@ -155,8 +169,11 @@ const Notice: React.FC<IProps> = ({ dispatch, roleList }) => {
                 >
                   查看
                 </a>
-                {/* <a onClick={ () => openModal(1, record as Record<string, any>) }>编辑</a> */}
+                <Divider type="vertical" />
+
+                <a onClick={() => openModal(1, record as Record<string, any>)}>编辑</a>
 
+                <Divider type="vertical" />
                 <Popconfirm
                   title="你确定要删除这条公告吗?"
                   onConfirm={() => DeleteNotice(record.id)}

+ 76 - 29
src/pages/notice/modal.tsx

@@ -1,5 +1,5 @@
 import React, { useState, useEffect, useLayoutEffect } from 'react';
-import { Modal, Row, Col, Space, Form, Input, Select, message, Upload, Button, Icon } from 'antd';
+import { Modal, Row, Col, Space, Form, Input, Select, message, Upload, Button } from 'antd';
 
 import { ScissorOutlined } from '@ant-design/icons';
 
@@ -87,11 +87,13 @@ class EditorDemo extends React.Component<EditorDemoProps> {
     const len = fileList.length - 1;
     if (fileList[len]?.status === 'done') {
       if (fileList[len].response.code === 0) {
+        console.log(fileList[len].response.data, ' fileList[len].response.data');
+
         this.setState({
           editorState: ContentUtils.insertMedias(this.state.editorState, [
             {
               type: 'IMAGE',
-              url: fileList[len].response.data,
+              url: fileList[len].response.data + `?imageView2/1/w/343/h/192`,
               width: '343px',
               height: '192px',
             },
@@ -102,6 +104,8 @@ class EditorDemo extends React.Component<EditorDemoProps> {
   };
 
   circleImg = (mediaData) => {
+    console.log(mediaData, 'mediaDatamediaData');
+
     const { url }: { url: string } = mediaData;
     if (url.includes('?imageView2')) {
       mediaData.url = mediaData.url.split('?imageView2')[0];
@@ -157,24 +161,34 @@ class EditorDemo extends React.Component<EditorDemoProps> {
 
     const hooks = {
       'set-image-size': ({ width, height }) => {
-        if (parseInt(width) !== 343) {
+        console.log(width, 'widthwidth');
+        let _width = width;
+        if (_width === undefined) {
+          _width = '343rpx';
+        }
+        if (parseInt(_width) !== 343) {
           message.warning('图片宽度默认为343');
           return false;
         }
+
+        return {
+          width: _width,
+          height: height,
+        };
       },
     };
 
     const imageControls: ImageControlType[] = [
-      'float-left',
-      'float-right',
-      {
-        text: '裁剪图片',
-        render: (mediaData) => (
-          <a>
-            <ScissorOutlined color="#fff" onClick={() => this.circleImg(mediaData)} />
-          </a>
-        ),
-      },
+      // 'float-left',
+      // 'float-right',
+      // {
+      //   text: '裁剪图片',
+      //   render: (mediaData) => (
+      //     <a>
+      //       <ScissorOutlined color="#fff" onClick={() => this.circleImg(mediaData)} />
+      //     </a>
+      //   ),
+      // },
       'size',
       'remove',
     ];
@@ -221,6 +235,9 @@ const NoticeModal: React.FC<noticeModalProps & IProps> = ({
   // editContent 反填
   const [editContent, setEditContent] = useState<string>('');
 
+  // 反填表单时的值
+  const [editForm, setEditForm] = useState({});
+
   useEffect(() => {
     onFill();
     dispatch({
@@ -234,10 +251,11 @@ const NoticeModal: React.FC<noticeModalProps & IProps> = ({
 
   // 新增或者编辑公告
   const PostOrPutNotice = async (record: any): Promise<void> => {
-    const { code, data } = await postOrPutNotice(record);
-    if (code === 0) {
-      console.log(data);
-      message.success('新增成功');
+    const { code, data } = await postOrPutNotice({ ...record });
+    if (code === 0 && data) {
+      message.success(type === 1 ? '编辑成功' : '新增成功');
+    } else {
+      message.success(type === 1 ? '编辑失败' : '新增失败');
     }
     closeModal();
     GetNotice();
@@ -246,28 +264,49 @@ const NoticeModal: React.FC<noticeModalProps & IProps> = ({
   // 反填表单
   const onFill = (): void => {
     console.log(curNoticeData, '反填表单');
-    // , userIds: !!curNoticeData && curNoticeData.userIds.join('')
     const $par = { ...curNoticeData };
     form.setFieldsValue($par);
+    setEditForm($par);
     setEditContent(curNoticeData.content);
   };
 
   const onFinish = (values: any) => {
     console.log(values, 'values');
+    console.log(content, 'contentcontent');
+
+    if (content === '<p></p>') {
+      message.error('请填写公告内容');
+      return;
+    }
+    let $par;
+    if (type === 1) {
+      $par = {
+        ...editForm,
+        ...values,
+        userIds: ['ALL'],
+        roles: values.roles,
+        type: 'ANN',
+        methodType: type,
+        content,
+      };
+    } else {
+      $par = {
+        ...values,
+        userIds: ['ALL'],
+        roles: values.roles,
+        type: 'ANN',
+        methodType: type,
+        content,
+      };
+    }
+
+    console.log($par);
 
-    const $par = {
-      ...values,
-      userIds: ['ALL'],
-      roles: values.userIds,
-      type: 'ANN',
-      methodType: type,
-      content,
-    };
     PostOrPutNotice($par);
   };
 
   // 提交表单
-  const onsubmit = (): void => form.submit();
+  const onsubmit = () => form.submit();
 
   // 设置标题
   const changeLabel = (e: React.ChangeEvent<HTMLInputElement>): void => setLabel(e.target.value);
@@ -284,7 +323,11 @@ const NoticeModal: React.FC<noticeModalProps & IProps> = ({
       onCancel={closeModal}
     >
       <Form {...layout} form={form} onFinish={onFinish}>
-        <Form.Item name="userIds" label="可看人员:">
+        <Form.Item
+          name="roles"
+          label="可看人员:"
+          rules={[{ required: true, message: '请选择可看人员' }]}
+        >
           <Select style={{ width: '375px' }} mode="multiple">
             {roleList.length &&
               roleList.map((item: Record<string, any>) => (
@@ -294,7 +337,11 @@ const NoticeModal: React.FC<noticeModalProps & IProps> = ({
               ))}
           </Select>
         </Form.Item>
-        <Form.Item name="label" label="公告标题:">
+        <Form.Item
+          name="label"
+          label="公告标题:"
+          rules={[{ required: true, message: '请填写公告标题' }]}
+        >
           <Input style={{ width: '375px' }} onChange={changeLabel} maxLength={80}></Input>
         </Form.Item>
         <Form.Item name="content" label="公告内容:">

+ 56 - 8
src/pages/tieba/plate/index.tsx

@@ -1,5 +1,5 @@
 import React, { Component } from 'react';
-import { Row, Col, Card, Space, Select, Button, Input, Table, Image, message } from 'antd';
+import { Row, Col, Card, Space, Select, Button, Input, Table, Image, message, Tag } from 'antd';
 import { PageContainer } from '@ant-design/pro-layout';
 import { getPlate, postOrPutPlate, changeTiebaState } from '@/services/tieba';
 import ModalForm from './ModalForm';
@@ -22,6 +22,7 @@ class Plate extends Component<React.Component> {
     total: 0,
     plateList: [],
     roleList: [],
+    loading: false,
   };
 
   componentDidMount() {
@@ -46,7 +47,6 @@ class Plate extends Component<React.Component> {
   // 选择认证角色
   changeRole = (value: string): void => {
     console.log(value);
-
     this.setState({
       queryParams: { ...this.state.queryParams, typeId: value },
     });
@@ -104,21 +104,52 @@ class Plate extends Component<React.Component> {
   // 获取板块列表
   getPlate = async (): Promise<void> => {
     const { queryParams } = this.state;
+    this.setState({
+      ...this.state,
+      loading: true,
+    });
     const { code, data } = await getPlate(queryParams);
     if (code === 0) {
       const { records, total } = data;
-      console.log(records, 'recordsrecordsrecords');
 
       this.setState({
         plateList: records,
         total,
+        loading: false,
+      });
+    } else {
+      this.setState({
+        loading: false,
       });
     }
   };
 
+  // 分页
+  pagination = async (page: number) => {
+    console.log(page);
+    const queryParams = Object.assign({}, this.state.queryParams, { curPage: page });
+    this.setState(
+      {
+        ...this.state,
+        queryParams,
+      },
+      () => {
+        this.getPlate();
+      },
+    );
+  };
+
   render() {
-    const { plateList, visible, type, form, roleList, queryParams } = this.state;
-    const { openModal, changeForm, closeModal, onSearch, changeRole, changeTiebaState } = this;
+    const { plateList, visible, type, form, roleList, queryParams, total, loading } = this.state;
+    const {
+      openModal,
+      changeForm,
+      closeModal,
+      onSearch,
+      changeRole,
+      changeTiebaState,
+      pagination,
+    } = this;
     return (
       <PageContainer title="贴吧板块管理">
         <Card>
@@ -165,15 +196,32 @@ class Plate extends Component<React.Component> {
               </Space>
             </Col>
           </Row>
-          <Table dataSource={plateList} style={{ marginTop: 20 }}>
+          <Table
+            dataSource={plateList}
+            loading={loading}
+            style={{ marginTop: 20 }}
+            pagination={{ total, showSizeChanger: false, onChange: pagination }}
+          >
             <Table.Column<ColumnType>
               key="avatarUrl"
               title="贴吧图标"
               render={(text, record): React.ReactNode => (
-                <Image width={50} height={50} preview src={text.avatarUrl} alt="我炸裂了" />
+                <Image
+                  width={50}
+                  height={50}
+                  style={{ objectFit: 'cover' }}
+                  preview
+                  src={text.avatarUrl}
+                  alt="我炸裂了"
+                />
               )}
             ></Table.Column>
-            <Table.Column<ColumnType> key="label" dataIndex="label" title="贴吧名"></Table.Column>
+            <Table.Column<ColumnType>
+              key="label"
+              dataIndex="label"
+              title="贴吧名"
+              render={(text) => <Tag color="blue">{text}</Tag>}
+            />
             <Table.Column<ColumnType>
               key="categoryLabel"
               dataIndex="categoryLabel"

+ 31 - 12
src/pages/tieba/posts/index.tsx

@@ -1,6 +1,19 @@
 import React, { useEffect, useState, useReducer } from 'react';
 import { PageContainer } from '@ant-design/pro-layout';
-import { Row, Col, Space, Button, Input, Table, Card, Select, message, Tooltip, Image } from 'antd';
+import {
+  Row,
+  Col,
+  Space,
+  Button,
+  Input,
+  Table,
+  Card,
+  Select,
+  message,
+  Tooltip,
+  Image,
+  Tag,
+} from 'antd';
 
 import { getPlate, getPosts, enablePosts } from '@/services/tieba';
 
@@ -72,11 +85,19 @@ const Posts: React.FC = () => {
   const [detailData, setDetailData] = useState({});
 
   const [loading, setLoading] = useState(false);
-  // 当前点击的id
-  // const [id, setId] = useState('')
+
+  useEffect(() => {
+    GetPlate();
+    GetPosts();
+  }, []);
+
+  useEffect(() => {
+    GetPosts();
+  }, [queryParams.curPage]);
+
   // 获取贴吧板块
   const GetPlate = async (): Promise<void> => {
-    const { code, data } = await getPlate({ curPage: 1, pageSize: 10000 });
+    const { code, data } = await getPlate({ curPage: queryParams.curPage, pageSize: 10 });
 
     if (code === 0) {
       const { records } = data;
@@ -118,10 +139,6 @@ const Posts: React.FC = () => {
     GetPosts();
   };
 
-  useEffect(() => {
-    GetPlate();
-    GetPosts();
-  }, []);
   // 打开弹窗
   const openModal = (record: Record<string, any>): void => {
     setVissible(true);
@@ -133,7 +150,7 @@ const Posts: React.FC = () => {
   // 选择barId
   const changeBarId = (value: string): void => dispatch({ type: 'barId', value });
   // 填写标题
-  const changeLabel = (e: React.ChangeEvent<HTMLInputElement>): void =>
+  const changeLabel = (e: React.ChangeEvent<HTMLInputElement>) =>
     dispatch({ type: 'label', value: e.target.value });
 
   return (
@@ -218,12 +235,14 @@ const Posts: React.FC = () => {
             title="发布人"
             render={(text, record: Record<string, any>) => (
               <Space>
-                <Col>{record.authorName}</Col>
-                <Col>{record.createTime}</Col>
+                <Col>
+                  <Tag color="blue"> {record.authorName} </Tag>
+                </Col>
+                {/* <Col>{record.createTime}</Col> */}
               </Space>
             )}
           />
-          <Table.Column key="answerNum" dataIndex="answerNum" title="回帖数"></Table.Column>
+          <Table.Column key="replyNum" dataIndex="replyNum" title="回帖数"></Table.Column>
           <Table.Column key="praiseNum" dataIndex="praiseNum" title="点赞数"></Table.Column>
           <Table.Column
             key="action"

+ 1 - 0
src/services/notice.ts

@@ -13,6 +13,7 @@ export async function getNotice(params: getNoticeType): Promise<any> {
 
 export async function postOrPutNotice(data: PostOrPutNoticeType): Promise<any> {
   const { methodType } = data;
+
   return request('/forum/admin/notice', { method: methodType === 0 ? 'POST' : 'PUT', data });
 }
 

+ 1 - 0
src/types/role.ts

@@ -3,5 +3,6 @@ export interface role {
   isForbidden: boolean | null;
   label: string;
   previousLabel?: string;
+  userCount: number;
   [key: string]: any;
 }

+ 1 - 0
tsconfig.json

@@ -7,6 +7,7 @@
     "sourceMap": true,
     "baseUrl": ".",
     "jsx": "preserve",
+    // "jsx": "react-jsx",
     "allowSyntheticDefaultImports": true,
     "moduleResolution": "node",
     "forceConsistentCasingInFileNames": true,