lvkun996 8 сар өмнө
parent
commit
950eef5eb0

+ 5 - 0
config/config.ts

@@ -166,6 +166,11 @@ export default defineConfig({
                   path: '/setting/banner',
                   component: './setting/banner/index',
                 },
+                {
+                  name: '登录页背景图',
+                  path: '/setting/bgi',
+                  component: './setting/bgi/index',
+                },
               ],
             },
           ],

+ 1 - 1
config/defaultSettings.ts

@@ -16,7 +16,7 @@ const proSettings: DefaultSettings = {
   },
   pwa: false,
   headerHeight: 48,
-  title: '中德论坛',
+  title: '中德精英俱乐部后台',
   menuHeaderRender: false,
 };
 

+ 1 - 6
config/proxy.ts

@@ -7,13 +7,8 @@
  */
 export default {
   dev: {
-    // '/api': {
-    //   target: 'http://192.168.1.21:38089',
-    //   changeOrigin: true,
-    //   pathRewrite: { '^/api': '' },
-    // },
     '/api': {
-      target: 'https://open.luojigou.vip',
+      target: 'https://open.test.luojigou.vip',
       changeOrigin: true,
       pathRewrite: { '^/api': '' },
     },

+ 9 - 3
src/components/upload/index.tsx

@@ -6,6 +6,7 @@ import { PlusOutlined } from '@ant-design/icons';
 import type { PicturesWallType } from './data';
 
 import { baseUrl } from '@/utils/request';
+import { message } from 'antd';
 
 function getBase64(file) {
   return new Promise((resolve, reject) => {
@@ -64,8 +65,12 @@ class PicturesWall extends Component<PicturesWallType> {
     }
 
     if (fileList[0]?.status === 'done') {
-      // fileList.response.data
-      this.props.setCoverFn(fileList[0].response.data);
+      if (fileList[0].response.code === 0) {
+        // fileList.response.data
+        this.props.setCoverFn(fileList[0].response.data);
+      } else {
+        message.error(fileList[0].response.message);
+      }
     }
   };
   render() {
@@ -81,6 +86,7 @@ class PicturesWall extends Component<PicturesWallType> {
     return (
       <>
         <Upload
+          key={previewImage}
           action={`${baseUrl}/forum/file/uploadImage`}
           listType="picture-card"
           fileList={fileList}
@@ -96,7 +102,7 @@ class PicturesWall extends Component<PicturesWallType> {
           footer={null}
           onCancel={this.handleCancel}
         >
-          <img alt="example" style={{ width: '100%' }} src={previewImage} />
+          <img alt="example" style={{ width: '100%' }} key={previewImage} src={previewImage} />
         </Modal>
       </>
     );

+ 2 - 1
src/e2e/baseLayout.e2e.js

@@ -1,7 +1,8 @@
 const { uniq } = require('lodash');
 const RouterConfig = require('../../config/config').default.routes;
 
-const BASE_URL = `http://localhost:${process.env.PORT || 8000}`;
+// const BASE_URL = `http://localhost:${process.env.PORT || 8000}`;
+import { BASE_URL } from '@/utils/eventkey';
 
 function formatter(routes, parentPath = '') {
   const fixedParentPath = parentPath.replace(/\/{1,}/g, '/');

+ 4 - 5
src/layouts/BasicLayout.tsx

@@ -8,17 +8,15 @@ import type {
   BasicLayoutProps as ProLayoutProps,
   Settings,
 } from '@ant-design/pro-layout';
-import ProLayout, { DefaultFooter, SettingDrawer } from '@ant-design/pro-layout';
+import ProLayout, { SettingDrawer } from '@ant-design/pro-layout';
 import React, { useEffect, useMemo, useRef } from 'react';
 import type { Dispatch } from 'umi';
 import { Link, useIntl, connect, history } from 'umi';
-import { GithubOutlined } from '@ant-design/icons';
 import { Result, Button } from 'antd';
 import Authorized from '@/utils/Authorized';
 import RightContent from '@/components/GlobalHeader/RightContent';
 import type { ConnectState } from '@/models/connect';
 import { getMatchMenu } from '@umijs/route-utils';
-import logo from '../assets/logo.svg';
 
 const noMatch = (
   <Result
@@ -96,11 +94,12 @@ const BasicLayout: React.FC<BasicLayoutProps> = (props) => {
   useEffect(() => {
     console.log('hello');
 
+    const { origin } = window.location;
     if (!window.localStorage.getItem('token')) {
       if (process.env.NODE_ENV === 'development') {
-        window.location.href = 'http://localhost:8000/#/user/login';
+        window.location.href = `${origin}/#/user/login`;
       } else {
-        window.location.href = 'https://luojigou.vip/tieba-admin/#/user/login';
+        window.location.href = `${origin}/tieba-admin/#/user/login`;
       }
     }
     // if (dispatch) {

+ 21 - 1
src/models/user.ts

@@ -2,7 +2,7 @@ import type { Effect, Reducer } from 'umi';
 
 import { queryCurrent, query as queryUsers } from '@/services/user';
 
-import { getRoleList } from '@/services/role';
+import { getRoleList, getRoleListNew } from '@/services/role';
 
 export type CurrentUser = {
   avatar?: string;
@@ -78,13 +78,33 @@ const UserModel: UserModelType = {
 
       callback();
     },
+    *getRoleListNew(_, { call, put }) {
+      const { payload, callback } = _;
+
+      const r = yield call(getRoleListNew, payload);
+
+      yield put({
+        type: 'saveRoleListNew',
+        payload: r.data,
+      });
+
+      if (callback) callback();
+    },
   },
 
   reducers: {
+    saveRoleListNew(state, action) {
+      console.log(action, 'action');
+
+      let newState = { ...state, roleList: action.payload || [] };
+      return newState;
+    },
     /**
      * @description 保存权限列表
      */
     saveRoleList(state, action) {
+      console.log(action, 'action');
+
       let newState = { ...state, roleList: action.payload.slice(1) || [] };
       return newState;
     },

+ 32 - 16
src/pages/User/login/index.tsx

@@ -53,6 +53,20 @@ const Login: React.FC<LoginProps> = (props) => {
       payload: { ...values, type },
     });
   };
+
+  const items = [
+    {
+      label: intl.formatMessage({
+        id: 'pages.login.accountLogin.tab',
+        defaultMessage: '账户密码登录',
+      }),
+      key: 'account',
+    }, // 务必填写 key
+    // { label: intl.formatMessage({
+    //     id: 'pages.login.phoneLogin.tab',
+    //     defaultMessage: '手机号登录',
+    //   }), key: 'mobile',},
+  ];
   return (
     <div className={styles.main}>
       <ProForm
@@ -74,22 +88,24 @@ const Login: React.FC<LoginProps> = (props) => {
           return Promise.resolve();
         }}
       >
-        <Tabs activeKey={type} onChange={setType}>
-          <Tabs.TabPane
-            key="account"
-            tab={intl.formatMessage({
-              id: 'pages.login.accountLogin.tab',
-              defaultMessage: '账户密码登录',
-            })}
-          />
-          {/* <Tabs.TabPane
-            key="mobile"
-            tab={intl.formatMessage({
-              id: 'pages.login.phoneLogin.tab',
-              defaultMessage: '手机号登录',
-            })}
-          /> */}
-        </Tabs>
+        {/*<Tabs activeKey={type} onChange={setType}>*/}
+        {/*  <Tabs.TabPane*/}
+        {/*    key="account"*/}
+        {/*    tab={intl.formatMessage({*/}
+        {/*      id: 'pages.login.accountLogin.tab',*/}
+        {/*      defaultMessage: '账户密码登录',*/}
+        {/*    })}*/}
+        {/*  />*/}
+        {/*  /!* <Tabs.TabPane*/}
+        {/*    key="mobile"*/}
+        {/*    tab={intl.formatMessage({*/}
+        {/*      id: 'pages.login.phoneLogin.tab',*/}
+        {/*      defaultMessage: '手机号登录',*/}
+        {/*    })}*/}
+        {/*  /> *!/*/}
+        {/*</Tabs>*/}
+
+        <Tabs items={items} activeKey={type} onChange={setType} />
 
         {status === 'error' && loginType === 'account' && !submitting && (
           <LoginMessage

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

@@ -13,13 +13,16 @@ import {
   Input,
   Popconfirm,
   message,
+  Radio,
 } from 'antd';
-import { getAgentDetail } from '@/services/agent';
+import { changeAdminManagement, getAgentDetail } from '@/services/agent';
 
 import { editAgentInfo } from '@/services/agent';
 
 import type { roleListType } from './index';
 
+import type { RadioChangeEvent } from 'antd';
+
 type DetailModalType = {
   visible: boolean;
   id: string;
@@ -226,6 +229,17 @@ const DetailModal: React.FC<DetailModalType> = ({ visible, id, closeModal }) =>
     );
   };
 
+  // 修改代理商权限
+  const changeAdmin = async (e: RadioChangeEvent) => {
+    const { code } = await changeAdminManagement(userInfo.id, e.target.value);
+
+    if (code === 0) {
+      message.success('修改成功');
+
+      setUserInfo({ ...userInfo, admin: e.target.value });
+    }
+  };
+
   return (
     <Modal title="详细信息" visible={visible} width={1200} onOk={closeModal} onCancel={closeModal}>
       <Spin spinning={spinning}>
@@ -250,6 +264,12 @@ const DetailModal: React.FC<DetailModalType> = ({ visible, id, closeModal }) =>
                 <Descriptions.Item span={1} label="角色">
                   {userInfo.authRoles && renderAuthRoles()}
                 </Descriptions.Item>
+                <Descriptions.Item span={1} label="是否开启发布思维芯·芯声">
+                  <Radio.Group onChange={changeAdmin} value={userInfo.admin}>
+                    <Radio value={1}>是</Radio>
+                    <Radio value={0}>否</Radio>
+                  </Radio.Group>
+                </Descriptions.Item>
               </Descriptions>
             </Space>
           </Col>

+ 1 - 0
src/pages/notice/data.d.ts

@@ -9,6 +9,7 @@ export type PostOrPutNoticeType = {
   content: string;
   label: string;
   type: Type;
+  imgUrl: string;
 };
 
 export interface noticeModalProps {

+ 9 - 6
src/pages/notice/index.tsx

@@ -143,18 +143,21 @@ const Notice: React.FC<IProps> = ({ dispatch, roleList }) => {
               </a>
             )}
           />
-          <Table.Column
-            title="发布人"
-            key="1"
-            dataIndex="1"
-            render={() => <span>管理员</span>}
-          ></Table.Column>
+          <Table.Column title="发布人" key="authorName" dataIndex="authorName"></Table.Column>
           <Table.Column
             title="发布时间"
             key="createTime"
             dataIndex="createTime"
             render={(text) => <span>{filterTimestamp(text)}</span>}
           ></Table.Column>
+          <Table.Column
+            title="跳转链接"
+            key="jumpPath"
+            dataIndex="jumpPath"
+            render={(text, record: Record<string, any>) => (
+              <span>/pages/home/notice?id={record.id}</span>
+            )}
+          ></Table.Column>
           <Table.Column
             title="操作"
             key="action"

+ 82 - 18
src/pages/notice/modal.tsx

@@ -1,18 +1,18 @@
-import React, { useState, useEffect, useLayoutEffect } from 'react';
-import { Modal, Row, Col, Space, Form, Input, Select, message, Upload, Button } from 'antd';
+import React, { useState, useEffect } from 'react';
+import { Modal, Form, Input, Select, message, Upload, Radio } from 'antd';
 
-import { ScissorOutlined } from '@ant-design/icons';
+// import { ScissorOutlined } from '@ant-design/icons';
 
-import { getAgent } from '@/services/agent';
+// import { getAgent } from '@/services/agent';
 
 import { postOrPutNotice } from '@/services/notice';
 
-import { uploadFile } from '@/services/user';
+// import { uploadFile } from '@/services/user';
 
 // import ReactWEditor from 'wangeditor-for-react';
 
 // 引入编辑器组件
-import BraftEditor, { ControlType, ExtendControlType, ImageControlType } from 'braft-editor';
+import BraftEditor, { ExtendControlType, ImageControlType } from 'braft-editor';
 // 引入编辑器样式
 import 'braft-editor/dist/index.css';
 
@@ -24,17 +24,17 @@ import type { noticeModalProps } from './data';
 
 import type { Dispatch } from 'umi';
 
-import { useIntl } from 'react-intl';
-
 import { Role } from '@/models/user';
 
+import PicturesWall from '@/components/upload';
+
 const layout = {
   labelCol: { span: 5 },
   wrapperCol: { span: 16 },
 };
 
 // 定义rem基准值
-const sizeBase = 23.4375;
+// const sizeBase = 23.4375;
 
 interface IProps {
   dispatch: Dispatch;
@@ -93,8 +93,8 @@ class EditorDemo extends React.Component<EditorDemoProps> {
           editorState: ContentUtils.insertMedias(this.state.editorState, [
             {
               type: 'IMAGE',
-              url: fileList[len].response.data + `?imageView2/1/`,
-              // width: '343px',
+              url: fileList[len].response.data + `?imageView2/1`,
+              width: '343px',
               // height: '192px',
             },
           ]),
@@ -133,6 +133,7 @@ class EditorDemo extends React.Component<EditorDemoProps> {
       'blockquote',
       'font-size',
       'line-height',
+      'font-family',
     ];
 
     const extendControls: ExtendControlType[] = [
@@ -195,6 +196,29 @@ class EditorDemo extends React.Component<EditorDemoProps> {
 
     const { editorState } = this.state;
 
+    const fontFamilies = [
+      {
+        name: 'Araial',
+        family: 'Arial, Helvetica, sans-serif',
+      },
+      {
+        name: 'Georgia',
+        family: 'Georgia, serif',
+      },
+      {
+        name: 'Impact',
+        family: 'Impact, serif',
+      },
+      {
+        name: 'Monospace',
+        family: '"Courier New", Courier, monospace',
+      },
+      {
+        name: 'Tahoma',
+        family: 'tahoma, arial, "Hiragino Sans GB", 宋体, sans-serif',
+      },
+    ];
+
     return (
       <div className="my-component">
         <BraftEditor
@@ -202,6 +226,7 @@ class EditorDemo extends React.Component<EditorDemoProps> {
           imageResizable={false}
           style={{ border: '1px solid #d9d9d9', width: '375px' }}
           controls={controls}
+          fontFamilies={fontFamilies}
           imageControls={imageControls}
           ref={(instance) => (this.state.editorInstance = instance)}
           extendControls={extendControls}
@@ -230,6 +255,8 @@ const NoticeModal: React.FC<noticeModalProps & IProps> = ({
 
   const [label, setLabel] = useState('');
 
+  const [imgUrl, setImgUrl] = useState('');
+
   const [content, setContent] = useState('');
 
   // editContent 反填
@@ -251,11 +278,11 @@ const NoticeModal: React.FC<noticeModalProps & IProps> = ({
 
   // 新增或者编辑公告
   const PostOrPutNotice = async (record: any): Promise<void> => {
-    const { code, data } = await postOrPutNotice({ ...record });
-    if (code === 0 && data) {
+    const { code } = await postOrPutNotice({ ...record });
+    if (code === 0) {
       message.success(type === 1 ? '编辑成功' : '新增成功');
     } else {
-      message.success(type === 1 ? '编辑失败' : '新增失败');
+      message.error(type === 1 ? '编辑失败' : '新增失败');
     }
     closeModal();
     GetNotice();
@@ -268,6 +295,7 @@ const NoticeModal: React.FC<noticeModalProps & IProps> = ({
     form.setFieldsValue($par);
     setEditForm($par);
     setEditContent(curNoticeData.content);
+    setImgUrl(curNoticeData.imgUrl);
   };
 
   const onFinish = (values: any) => {
@@ -283,8 +311,9 @@ const NoticeModal: React.FC<noticeModalProps & IProps> = ({
       $par = {
         ...editForm,
         ...values,
+        imgUrl,
         userIds: ['ALL'],
-        roles: values.roles,
+        roles: Array.isArray(values.roles) ? values.roles : [values.roles],
         type: 'ANN',
         methodType: type,
         content,
@@ -292,19 +321,27 @@ const NoticeModal: React.FC<noticeModalProps & IProps> = ({
     } else {
       $par = {
         ...values,
+        imgUrl,
         userIds: ['ALL'],
-        roles: values.roles,
+        roles: Array.isArray(values.roles) ? values.roles : [values.roles],
         type: 'ANN',
         methodType: type,
         content,
       };
     }
 
-    console.log($par);
+    console.log($par, '参数');
 
     PostOrPutNotice($par);
   };
 
+  const changeImgUrl = (url: string) => {
+    setImgUrl(url);
+    form.setFieldsValue({
+      imgUrl: url,
+    });
+  };
+
   // 提交表单
   const onsubmit = () => form.submit();
 
@@ -323,12 +360,26 @@ const NoticeModal: React.FC<noticeModalProps & IProps> = ({
       onCancel={closeModal}
     >
       <Form {...layout} form={form} onFinish={onFinish}>
+        <Form.Item
+          name="imgUrl"
+          label="封面图"
+          rules={[{ required: true, message: '请上传封面图' }]}
+        >
+          <PicturesWall
+            key={imgUrl}
+            imgUrl={imgUrl}
+            setCoverFn={changeImgUrl}
+            maxCount={1}
+            desc="上传封面图"
+          />
+          <div>建议上传尺寸:398 * 530</div>
+        </Form.Item>
         <Form.Item
           name="roles"
           label="可看人员:"
           rules={[{ required: true, message: '请选择可看人员' }]}
         >
-          <Select style={{ width: '375px' }} mode="multiple">
+          <Select style={{ width: '375px' }}>
             {roleList.length &&
               roleList.map((item: Record<string, any>) => (
                 <Select.Option key={item.id} value={item.id}>
@@ -344,6 +395,19 @@ const NoticeModal: React.FC<noticeModalProps & IProps> = ({
         >
           <Input style={{ width: '375px' }} onChange={changeLabel} maxLength={80}></Input>
         </Form.Item>
+        <Form.Item name="tag" label="公告标签:">
+          <Input style={{ width: '375px' }} onChange={changeLabel} maxLength={10}></Input>
+        </Form.Item>
+        <Form.Item
+          name="top"
+          label="是否置顶:"
+          rules={[{ required: true, message: '请选择是否置顶' }]}
+        >
+          <Radio.Group>
+            <Radio value={0}>否</Radio>
+            <Radio value={1}>是</Radio>
+          </Radio.Group>
+        </Form.Item>
         <Form.Item name="content" label="公告内容:">
           <EditorDemo key={editContent} changeContent={changeContent} editorContent={editContent} />
         </Form.Item>

+ 6 - 3
src/pages/setting/banner/index.tsx

@@ -91,14 +91,14 @@ const Banner: React.FC<IProps> = ({ roleList, dispatch }) => {
     bannerList: [],
   });
 
-  const [roleId, setRoleId] = useState<string>('');
+  const [roleId, setRoleId] = useState<string>();
 
   const { visible, bannerList, loading, modalVisible } = state;
 
   // 请求身份分类
   useEffect(() => {
     dispatch({
-      type: 'user/getRoleList',
+      type: 'user/getRoleListNew',
       payload: {
         curPage: 1,
         passSize: 100,
@@ -108,9 +108,11 @@ const Banner: React.FC<IProps> = ({ roleList, dispatch }) => {
 
   // 设置默认的roleId
   useEffect(() => {
+    console.log(roleList, 'roleList');
+
     if (roleList.length === 0) return;
 
-    setRoleId(roleList[0].id);
+    setRoleId(roleList[0].id.toString());
   }, [roleList]);
 
   useEffect(() => {
@@ -308,6 +310,7 @@ const Banner: React.FC<IProps> = ({ roleList, dispatch }) => {
             loading={loading}
             dataSource={bannerList}
             columns={columns}
+            rowKey={'id'}
             components={components}
             onRow={(record, index) => ({
               index,

+ 14 - 0
src/pages/setting/banner/item.less

@@ -0,0 +1,14 @@
+.ant-input-textarea-show-count::after {
+  position: absolute;
+  right: 0;
+  bottom: 0;
+}
+
+.ant-input-textarea-show-count {
+  position: relative;
+}
+
+.ant-input-textarea-show-count.ant-input-textarea-in-form-item::after {
+  margin-right: 9px;
+  margin-bottom: 3px;
+}

+ 20 - 17
src/pages/setting/banner/item.tsx

@@ -1,24 +1,16 @@
-import React, { useEffect, useState, memo } from 'react';
-
-import {
-  Button,
-  Card,
-  Col,
-  Form,
-  Input,
-  Row,
-  Select,
-  Switch,
-  Popconfirm,
-  Tooltip,
-  Space,
-} from 'antd';
+import React, { memo, useEffect, useState } from 'react';
+
+import { Button, Card, Form, Input, Popconfirm, Select, Space, Switch, Tooltip } from 'antd';
 
 import { QuestionCircleOutlined } from '@ant-design/icons';
 
 import CustomUpload from '@/components/upload/index';
 
-import { IBanner, EJumpType as Etype } from './types';
+import { EJumpType as Etype, IBanner } from './types';
+
+import './item.less';
+
+const { TextArea } = Input;
 
 const { Option } = Select;
 
@@ -50,6 +42,7 @@ const BannerItem: React.FC<IProps> = ({ itemData, collecrtItem, delItem }) => {
 
   // change form
   const changeForm = (key: string, value: any) => {
+    console.log(key, value);
     form.setFieldsValue({ key: value });
 
     itemData[key] = value;
@@ -77,6 +70,16 @@ const BannerItem: React.FC<IProps> = ({ itemData, collecrtItem, delItem }) => {
             imgUrl={itemData.imgUrl}
           />
         </Form.Item>
+        <Form.Item label="封面标题" name="coverTitle">
+          <TextArea
+            rows={4}
+            placeholder="请填写"
+            maxLength={18}
+            showCount
+            allowClear
+            onChange={(e) => changeForm('coverTitle', e.target.value)}
+          />
+        </Form.Item>
         <Form.Item label="跳转类型" name="jumpType">
           <Select
             placeholder="请选择跳转类型"
@@ -90,7 +93,7 @@ const BannerItem: React.FC<IProps> = ({ itemData, collecrtItem, delItem }) => {
         {/* 跳转到h5 */}
         {form.getFieldValue('jumpType') === Etype.h5 && (
           <Form.Item label="跳转地址" name="jumpPath">
-            <Input onChange={(e) => changeForm('jumpPath', e.target.value)} />
+            <Input allowClear onChange={(e) => changeForm('jumpPath', e.target.value)} />
           </Form.Item>
         )}
 

+ 10 - 10
src/pages/setting/banner/swiper.tsx

@@ -18,7 +18,7 @@ interface IProps {
 const SwiperCom: React.FC<IProps> = ({ bannerList, visible, opraPreviewModal }) => {
   return (
     <Modal
-      visible={visible}
+      open={visible}
       width={512}
       onCancel={() => opraPreviewModal(false)}
       onOk={() => opraPreviewModal(false)}
@@ -48,18 +48,18 @@ const SwiperCom: React.FC<IProps> = ({ bannerList, visible, opraPreviewModal })
           ))}
       </Swiper>
 
-      {/* <Carousel 
+      {/* <Carousel
         autoplay
       >
         {
-          bannerList.filter( _banner =>  _banner.isShow ).map( banner => 
-            <Image 
-              style={{objectFit: 'cover'}} 
-              key={banner.imgUrl} 
-              preview={false} 
-              src={banner.imgUrl} 
-              width={466} 
-              height={200} 
+          bannerList.filter( _banner =>  _banner.isShow ).map( banner =>
+            <Image
+              style={{objectFit: 'cover'}}
+              key={banner.imgUrl}
+              preview={false}
+              src={banner.imgUrl}
+              width={466}
+              height={200}
             />
          )
         }

+ 1 - 0
src/pages/setting/banner/types.ts

@@ -12,5 +12,6 @@ export interface IBanner {
   roleId: string;
   sort: number;
   id?: string;
+  coverTitle: string;
   [key: string]: any;
 }

+ 17 - 0
src/pages/setting/bgi/common.less

@@ -0,0 +1,17 @@
+.loginBGI {
+  .ant-upload-list-item {
+    width: 384px;
+    height: 576px;
+  }
+
+  .ant-upload {
+    width: 384px;
+    height: 576px;
+  }
+}
+
+.remark {
+  width: 384px;
+  margin-top: 500px;
+  text-align: center;
+}

+ 51 - 0
src/pages/setting/bgi/index.tsx

@@ -0,0 +1,51 @@
+import React, { memo, useEffect, useState } from 'react';
+import { PageContainer } from '@ant-design/pro-layout';
+import Upload from '../../../components/upload';
+import { message } from 'antd';
+import { getLoginBGI, setLoginBGI } from '@/services/notice';
+import './common.less';
+
+const MemoUpload = memo(Upload);
+
+const Banner = () => {
+  const [imgUrl, setImgUrl] = useState('');
+
+  // 设置登录背景图
+  const saveImgUrl = async (url: string) => {
+    const { status, msg } = await setLoginBGI(url);
+    if (status === 200) {
+      setImgUrl(url);
+    } else {
+      message.error(msg);
+    }
+  };
+
+  // 获取登录背景图
+  const getImgUrl = async () => {
+    const { status, data, msg } = await getLoginBGI();
+    if (status === 200) {
+      setImgUrl(data.backgroundImage);
+    } else {
+      message.error(msg);
+    }
+  };
+
+  useEffect(() => {
+    getImgUrl();
+  }, [imgUrl]);
+
+  return (
+    <PageContainer title="登录页背景图" className="loginBGI">
+      <MemoUpload
+        key={imgUrl}
+        maxCount={1}
+        desc="上传图片"
+        setCoverFn={saveImgUrl}
+        imgUrl={imgUrl}
+      />
+      <div className="remark">登录页封面GIF图上传</div>
+    </PageContainer>
+  );
+};
+
+export default Banner;

+ 9 - 0
src/services/agent.ts

@@ -33,3 +33,12 @@ export async function stopOrOpenAgent(id: string, params: stopOrOpenAgentType):
 export async function editAgentInfo(data: any) {
   return request(`/forum/admin/agent`, { method: 'PUT', data });
 }
+
+/**
+ * @description 开通或关闭管理员
+ * @author 朱波
+ * @date 2022/10/27
+ */
+export async function changeAdminManagement(userId: string, state: number | string) {
+  return request(`/forum/admin/agent/management/${userId}/${state}`, { method: 'PUT' });
+}

+ 19 - 0
src/services/notice.ts

@@ -45,3 +45,22 @@ export async function getBanner(roleId: string) {
 export async function deleteBanner(id: string) {
   return request(`/forum/admin/banner/${id}`, { method: 'DELETE' });
 }
+
+/**
+ * @description 获取登录页背景图
+ * @author 朱波
+ * @date 2022/10/24
+ */
+export async function getLoginBGI() {
+  return request(`/forum/system/config/content/LOGIN_BACKGROUND_IMAGE`, { method: 'GET' });
+}
+
+/**
+ * @description 设置登录页背景图
+ * @author 朱波
+ * @date 2022/10/24
+ */
+export async function setLoginBGI(imgUrl: string) {
+  const data = { backgroundImage: imgUrl };
+  return request(`/forum/system/config/ct/LOGIN_BACKGROUND_IMAGE`, { method: 'PUT', data });
+}

+ 8 - 0
src/services/role.ts

@@ -4,10 +4,18 @@ import { role } from '@/types/role';
 type getRoleListType = {
   curPage: number;
 };
+// 获取权限列表
 export async function getRoleList(params: getRoleListType): Promise<any> {
   return request('/forum/admin/role', { params });
 }
 
+/**
+ * @description 获取权限列表(新)
+ */
+export async function getRoleListNew(): Promise<any> {
+  return request('/forum/system/config/list/BANNER_NAME_LIST', { method: 'GET' });
+}
+
 //   修改角色名称
 // /forum/admin/role
 export async function putRoleList(data: role): Promise<any> {

+ 7 - 0
src/utils/eventkey.ts

@@ -3,3 +3,10 @@
  */
 
 export const Token = 'token';
+
+/**
+ * @description BASE_URL
+ * @author zhubo
+ * @date 2022/8/24
+ */
+export const BASE_URL = window.location.host;

+ 6 - 5
src/utils/request.ts

@@ -4,7 +4,7 @@
  */
 import { extend } from 'umi-request';
 import { notification, message } from 'antd';
-import { Token } from '@/utils/eventkey';
+import { BASE_URL, Token } from '@/utils/eventkey';
 
 const codeMessage = {
   200: '服务器成功返回请求的数据。',
@@ -64,8 +64,7 @@ const headers = {
 
 // https://open.luojigou.vip
 
-export const baseUrl: string =
-  process.env.NODE_ENV === 'development' ? '/api' : 'https://open.luojigou.vip';
+export const baseUrl: string = process.env.NODE_ENV === 'development' ? '/api' : '/zd-api';
 
 request.interceptors.request.use(
   (url: string, options: any, mutUrl?: string) => {
@@ -83,10 +82,12 @@ request.interceptors.request.use(
 request.interceptors.response.use(async (response, options) => {
   const r = await response.clone().json();
   if (r.code === 5001) {
+    const { origin } = window.location;
     if (process.env.NODE_ENV === 'development') {
-      window.location.href = 'http://localhost:8000/#/user/login';
+      // console.log(origin,'origin')
+      window.location.href = `${origin}/#/user/login`;
     } else {
-      window.location.href = 'https://luojigou.vip/tieba-admin/#/user/login';
+      window.location.href = `${origin}/tieba-admin/#/user/login`;
     }
   }