shaogen1995 hace 10 meses
padre
commit
2208e6dbcd

+ 76 - 0
src/pages/A4iosUser/A4ip/index.module.scss

@@ -0,0 +1,76 @@
+.A4ip {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background-color: rgba(0, 0, 0, 0.6);
+  border-radius: 10px;
+  padding: 50px 100px;
+  :global {
+    .A4iBox {
+      width: 100%;
+      height: 100%;
+      border-radius: 10px;
+      background-color: #fff;
+      padding: 20px;
+      .A4iTop {
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        & > div {
+          display: flex;
+          align-items: center;
+        }
+      }
+      .ant-table-wrapper {
+        margin-top: 20px;
+        .ant-table-cell {
+          padding: 6px;
+        }
+      }
+    }
+  }
+}
+
+// 新增 /编辑
+.A4ipAdd {
+  :global {
+    .ant-modal-close {
+      display: none;
+    }
+    .ant-modal {
+      width: 800px !important;
+      top: 30%;
+    }
+    .ant-modal-body {
+      border-top: 1px solid #ccc;
+      padding-top: 15px !important;
+    }
+
+    .formRow {
+      display: flex;
+      align-items: center;
+      margin-bottom: 24px;
+
+      .formLeft {
+        width: 80px;
+        text-align: right;
+
+        & > span {
+          color: #ff4d4f;
+        }
+      }
+
+      .formRight {
+        width: calc(100% - 80px);
+        position: relative;
+      }
+    }
+
+    .A4ibtn {
+      text-align: center;
+      margin-top: 50px;
+    }
+  }
+}

+ 158 - 0
src/pages/A4iosUser/A4ip/index.tsx

@@ -0,0 +1,158 @@
+import React, { useCallback, useEffect, useMemo, useState } from 'react'
+import styles from './index.module.scss'
+import { Button, Input, Modal } from 'antd'
+import { A4_APIipDel, A4_APIipList, A4_APIipSave } from '@/store/action/A4iosUser'
+import { useDispatch, useSelector } from 'react-redux'
+import { RootState } from '@/store'
+import MyTable from '@/components/MyTable'
+import { MessageFu } from '@/utils/message'
+import { A4IpType } from '@/types'
+import MyPopconfirm from '@/components/MyPopconfirm'
+
+type Props = {
+  closeFu: () => void
+}
+
+function A4ip({ closeFu }: Props) {
+  const dispatch = useDispatch()
+
+  const getListFu = useCallback(async () => {
+    dispatch(A4_APIipList())
+  }, [dispatch])
+
+  useEffect(() => {
+    getListFu()
+  }, [getListFu])
+
+  const ipList = useSelector((state: RootState) => state.A4iosUser.ipList)
+
+  const delTableFu = useCallback(
+    async (id: number) => {
+      const res = await A4_APIipDel(id)
+      if (res.code === 0) {
+        MessageFu.success('删除成功!')
+        getListFu()
+      }
+    },
+    [getListFu]
+  )
+
+  const [opId, setOpId] = useState(0)
+  const [ip, setIp] = useState('')
+
+  const tableLastBtn = useMemo(() => {
+    return [
+      {
+        title: '操作',
+        render: (item: A4IpType) => (
+          <>
+            <Button
+              size='small'
+              type='text'
+              onClick={() => {
+                setOpId(item.id)
+                setIp(item.ip)
+              }}
+            >
+              编辑
+            </Button>
+
+            <MyPopconfirm txtK='删除' onConfirm={() => delTableFu(item.id)} />
+          </>
+        )
+      }
+    ]
+  }, [delTableFu])
+
+  const btnOk = useCallback(async () => {
+    if (ip === '') return MessageFu.warning('请输入IP地址!')
+
+    const res = await A4_APIipSave({
+      id: opId > 0 ? opId : null,
+      ip
+    })
+
+    if (res.code === 0) {
+      MessageFu.success(opId > 0 ? '编辑成功!' : '新增成功!')
+      setOpId(0)
+      setIp('')
+      getListFu()
+    }
+  }, [getListFu, ip, opId])
+
+  return (
+    <div className={styles.A4ip}>
+      <div className='A4iBox'>
+        <div className='A4iTop'>
+          <h1>IP黑名单</h1>
+          <div>
+            <Button
+              type='primary'
+              onClick={() => {
+                setOpId(-1)
+                setIp('')
+              }}
+            >
+              新增
+            </Button>
+            &emsp; <Button onClick={closeFu}>返回</Button>
+          </div>
+        </div>
+
+        <MyTable
+          classKey='A4ipTable'
+          yHeight={595}
+          list={ipList}
+          columnsTemp={[['txt', 'IP地址', 'ip']]}
+          lastBtn={tableLastBtn}
+          pagingInfo={false}
+        />
+      </div>
+
+      {opId ? (
+        <Modal
+          wrapClassName={styles.A4ipAdd}
+          open={true}
+          title={opId > 0 ? '编辑' : '新增'}
+          footer={
+            [] // 设置footer为空,去掉 取消 确定默认按钮
+          }
+        >
+          <br />
+          <div className='formRow'>
+            <div className='formLeft'>
+              <span>*</span>IP地址:
+            </div>
+            <div className='formRight'>
+              <Input
+                placeholder='请输入内容'
+                maxLength={20}
+                showCount
+                value={ip}
+                onChange={e => setIp(e.target.value.replace(/[^\d.]/g, ''))}
+              />
+            </div>
+          </div>
+
+          <div className='A4ibtn'>
+            <Button type='primary' onClick={btnOk}>
+              提交
+            </Button>
+            &emsp;
+            <MyPopconfirm
+              txtK='取消'
+              onConfirm={() => {
+                setOpId(0)
+                setIp('')
+              }}
+            />
+          </div>
+        </Modal>
+      ) : null}
+    </div>
+  )
+}
+
+const MemoA4ip = React.memo(A4ip)
+
+export default MemoA4ip

+ 21 - 0
src/pages/A4iosUser/data.ts

@@ -0,0 +1,21 @@
+export type A4FromDataType = {
+  searchKey: string
+  pageNum: number
+  pageSize: number
+  isEnabled: 0 | 1 | ''
+}
+
+export const A4selArr1 = [
+  {
+    value: '',
+    label: '全部'
+  },
+  {
+    value: 0,
+    label: '禁用'
+  },
+  {
+    value: 1,
+    label: '启用'
+  }
+]

+ 28 - 3
src/pages/A4iosUser/index.module.scss

@@ -1,5 +1,30 @@
-.A4iosUser{
-  :global{
-
+.A4iosUser {
+  position: relative;
+  :global {
+    .A4top {
+      border-radius: 10px;
+      background-color: #fff;
+      padding: 15px 24px;
+      display: flex;
+      justify-content: space-between;
+      & > div {
+        display: flex;
+        .A4TopRow {
+          display: flex;
+          align-items: center;
+          margin-right: 20px;
+          .ant-select-selection-placeholder {
+            color: black;
+          }
+        }
+      }
+    }
+    .A4tableBox {
+      border-radius: 10px;
+      overflow: hidden;
+      margin-top: 15px;
+      height: calc(100% - 77px);
+      background-color: #fff;
+    }
   }
 }

+ 136 - 6
src/pages/A4iosUser/index.tsx

@@ -1,14 +1,144 @@
-import React from "react";
-import styles from "./index.module.scss";
- function A4iosUser() {
+import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
+import styles from './index.module.scss'
+import { Button, Input, Select, Switch } from 'antd'
+import { A4FromDataType, A4selArr1 } from './data'
+import { useDispatch, useSelector } from 'react-redux'
+import { A4_APIgetList, A4_APIisEnabled } from '@/store/action/A4iosUser'
+import { RootState } from '@/store'
+import { A4tableType } from '@/types'
+import MyTable from '@/components/MyTable'
+import { A4tableC } from '@/utils/tableData'
+import { MessageFu } from '@/utils/message'
+import A4ip from './A4ip'
+
+const fromDataBase: A4FromDataType = {
+  searchKey: '',
+  pageNum: 1,
+  pageSize: 10,
+  isEnabled: ''
+}
+
+function A4iosUser() {
+  const dispatch = useDispatch()
+
+  const [fromData, setFromData] = useState(fromDataBase)
+
+  const getListFu = useCallback(() => {
+    dispatch(A4_APIgetList(fromData))
+  }, [dispatch, fromData])
+
+  useEffect(() => {
+    getListFu()
+  }, [getListFu])
+
+  const [inputKey, setInputKey] = useState(1)
+
+  // 输入框的输入
+  const timeRef = useRef(-1)
+  const txtChangeFu = useCallback(
+    (e: React.ChangeEvent<HTMLInputElement>, key: 'searchKey') => {
+      clearTimeout(timeRef.current)
+      timeRef.current = window.setTimeout(() => {
+        setFromData({ ...fromData, [key]: e.target.value.replaceAll("'", ''), pageNum: 1 })
+      }, 500)
+    },
+    [fromData]
+  )
+
+  // 点击重置
+  const resetSelectFu = useCallback(() => {
+    setInputKey(Date.now())
+    setFromData({ ...fromDataBase })
+  }, [])
+
+  const tableInfo = useSelector((state: RootState) => state.A4iosUser.tableInfo)
+
+  // 用户状态切换
+  const cutIsEnabled = useCallback(
+    async (id: number, val: 0 | 1) => {
+      const res = await A4_APIisEnabled(id, val ? 0 : 1)
+      if (res.code === 0) {
+        MessageFu.success('操作成功!')
+        getListFu()
+      }
+    },
+    [getListFu]
+  )
+
+  const tableLastBtn = useMemo(() => {
+    return [
+      {
+        title: '用户状态',
+        render: (item: A4tableType) => (
+          <Switch
+            checked={!!item.isEnabled}
+            onChange={() => cutIsEnabled(item.id, item.isEnabled)}
+            checkedChildren='启用'
+            unCheckedChildren='禁用'
+          />
+        )
+      }
+    ]
+  }, [cutIsEnabled])
+
+  const [ipShow, setIpShow] = useState(false)
 
   return (
     <div className={styles.A4iosUser}>
-      <h1>A4iosUser</h1>
+      <div className='pageTitle'>平台用户</div>
+
+      {/* 顶部筛选 */}
+      <div className='A4top'>
+        <div>
+          <div className='A4TopRow'>
+            <span>搜索:</span>
+            <Input
+              key={inputKey}
+              maxLength={20}
+              style={{ width: 192 }}
+              placeholder='请输入用户昵称'
+              allowClear
+              onChange={e => txtChangeFu(e, 'searchKey')}
+            />
+          </div>
+
+          <div className='A4TopRow'>
+            <span>用户状态:</span>
+            <Select
+              style={{ width: 180 }}
+              value={fromData.isEnabled}
+              onChange={e => setFromData({ ...fromData, pageNum: 1, isEnabled: e })}
+              options={A4selArr1}
+            />
+          </div>
+        </div>
+        <div>
+          <Button onClick={resetSelectFu}>重置</Button>&emsp;
+          <Button type='primary' onClick={() => setIpShow(true)}>
+            IP黑名单
+          </Button>
+        </div>
+      </div>
+
+      {/* 表格主体 */}
+      <div className='A4tableBox'>
+        <MyTable
+          yHeight={625}
+          list={tableInfo.list}
+          columnsTemp={A4tableC}
+          lastBtn={tableLastBtn}
+          pageNum={fromData.pageNum}
+          pageSize={fromData.pageSize}
+          total={tableInfo.total}
+          onChange={(pageNum, pageSize) => setFromData({ ...fromData, pageNum, pageSize })}
+        />
+      </div>
+
+      {ipShow ? <A4ip closeFu={() => setIpShow(false)} /> : null}
     </div>
   )
 }
 
-const MemoA4iosUser = React.memo(A4iosUser);
+const MemoA4iosUser = React.memo(A4iosUser)
 
-export default MemoA4iosUser;
+export default MemoA4iosUser

+ 53 - 0
src/store/action/A4iosUser.ts

@@ -0,0 +1,53 @@
+import http from '@/utils/http'
+import { AppDispatch } from '..'
+
+/**
+ *平台用户-列表
+ */
+
+export const A4_APIgetList = (data: any): any => {
+  return async (dispatch: AppDispatch) => {
+    const res = await http.post('cms/wxUser/pageList', data)
+    if (res.code === 0) {
+      const obj = {
+        list: res.data.records,
+        total: res.data.total
+      }
+      dispatch({ type: 'A4/getList', payload: obj })
+    }
+  }
+}
+
+/**
+ * 平台用户-停用启用
+ */
+export const A4_APIisEnabled = (id: number, val: 0 | 1) => {
+  return http.get(`cms/wxUser/editStatus/${id}/${val}`)
+}
+
+// ip白名单列表
+export const A4_APIipList = (): any => {
+  return async (dispatch: AppDispatch) => {
+    const res = await http.post('sys/ip/pageList', {
+      pageNum: 1,
+      pageSize: 99999
+    })
+    if (res.code === 0) {
+      dispatch({ type: 'A3/getIpList', payload: res.data.records })
+    }
+  }
+}
+
+/**
+ * ip白名单-删除
+ */
+export const A4_APIipDel = (id: number) => {
+  return http.get(`sys/ip/remove/${id}`)
+}
+
+/**
+ * ip白名单-新增、编辑
+ */
+export const A4_APIipSave = (data: any) => {
+  return http.post('sys/ip/save', data)
+}

+ 38 - 0
src/store/reducer/A4iosUser.ts

@@ -0,0 +1,38 @@
+import { A4IpType, A4tableType } from '@/types'
+
+// 初始化状态
+const initState = {
+  // 列表数据
+  tableInfo: {
+    list: [] as A4tableType[],
+    total: 0
+  },
+  // ip列表数据
+  ipList: [] as A4IpType[]
+}
+
+// 定义 action 类型
+type Props =
+  | {
+      type: 'A4/getList'
+      payload: { list: A4tableType[]; total: number }
+    }
+  | {
+      type: 'A3/getIpList'
+      payload: A4IpType[]
+    }
+
+// reducer
+export default function Reducer(state = initState, action: Props) {
+  switch (action.type) {
+    // 获取列表数据
+    case 'A4/getList':
+      return { ...state, tableInfo: action.payload }
+
+    case 'A3/getIpList':
+      return { ...state, ipList: action.payload }
+
+    default:
+      return state
+  }
+}

+ 2 - 0
src/store/reducer/index.ts

@@ -6,6 +6,7 @@ import A0Layout from './layout'
 import A1manage from './A1manage'
 import A2classify from './A2classify'
 import A3recommend from './A3recommend'
+import A4iosUser from './A4iosUser'
 import Z1user from './Z1user'
 import Z2log from './Z2log'
 
@@ -15,6 +16,7 @@ const rootReducer = combineReducers({
   A1manage,
   A2classify,
   A3recommend,
+  A4iosUser,
   Z1user,
   Z2log
 })

+ 20 - 0
src/types/api/A4iosUser.ts

@@ -0,0 +1,20 @@
+export type A4tableType = {
+  avatarUrl: string
+  city: string
+  country: string
+  createTime: string
+  creatorName: string
+  gender: string
+  id: number
+  isEnabled: 0 | 1
+  lastIp: string
+  nickName: string
+  openId: string
+  phone: string
+  province: string
+  type: string
+  unionId: string
+  updateTime: string
+}
+
+export type A4IpType = any

+ 1 - 0
src/types/index.d.ts

@@ -2,5 +2,6 @@ export * from './api/layot'
 export * from './api/A1manage'
 export * from './api/A2classify'
 export * from './api/A3recommend'
+export * from './api/A4iosUser'
 export * from './api/Z1user'
 export * from './api/Z2log'

+ 9 - 0
src/utils/tableData.ts

@@ -63,6 +63,15 @@ export const A3tableC = [
   ['txt', '编辑时间', 'updateTime']
 ]
 
+export const A4tableC = [
+  ['txt', '用户ID', 'openId'],
+  ['txt', '用户昵称', 'nickName'],
+  ['img', '用户头像', 'avatarUrl'],
+  ['txt', '注册时间', 'createTime'],
+  ['txt', '最近登录时间', 'lastLoginTime'],
+  ['txt', '最近登录IP', 'lastIp']
+]
+
 export const Z1tableC = [
   ['txt', '用户名', 'userName'],
   ['txtChange', '角色', 'isAdmin', { 1: '管理员', 0: '普通成员' }],