shaogen1995 1 ヶ月 前
コミット
33719b38f2

+ 62 - 61
后台管理/src/components/MyTable/index.tsx

@@ -1,38 +1,38 @@
-import React, { useCallback, useEffect, useMemo } from "react";
-import styles from "./index.module.scss";
-import { Table } from "antd";
-import ImageLazy from "../ImageLazy";
+import React, { useCallback, useEffect, useMemo } from 'react'
+import styles from './index.module.scss'
+import { Table } from 'antd'
+import ImageLazy from '../ImageLazy'
 
 type Props = {
-  yHeight?: number; //设置表格的高度
-  list: any; //表格数据
-  columnsTemp: any[][]; //表格展示
-  total?: number; //总数
-  pageNum?: number;
-  pageSize?: number;
-  pagingInfo?: any | boolean;
-  onChange?: (pageNum: number, pageSize: number) => void;
-  lastBtn?: any;
-  classKey?: string; //一个组件多次使用的时候要传递,分别设置style
+  yHeight?: number //设置表格的高度
+  list: any //表格数据
+  columnsTemp: any[][] //表格展示
+  total?: number //总数
+  pageNum?: number
+  pageSize?: number
+  pagingInfo?: any | boolean
+  onChange?: (pageNum: number, pageSize: number) => void
+  lastBtn?: any
+  classKey?: string //一个组件多次使用的时候要传递,分别设置style
   // 表格简单的合并
-  merge?: { type: string; num: number; loc: "rowSpan" | "colSpan" };
+  merge?: { type: string; num: number; loc: 'rowSpan' | 'colSpan' }
   // 定制化表头
-  myTitle?: { name: string; Com: React.ReactNode };
+  myTitle?: { name: string; Com: React.ReactNode }
   // 为空的定制字段
-  isNull?: string;
-};
+  isNull?: string
+}
 
 // 表格内容定制化
 const tableComObj = (key: string, val: string[]) => {
   const obj = {
     A: (
-      <a href={val[1]} target="_blank" title={val[1]} rel="noreferrer">
+      <a href={val[1]} target='_blank' title={val[1]} rel='noreferrer'>
         {val[0]}
       </a>
-    ),
-  };
-  return Reflect.get(obj, key);
-};
+    )
+  }
+  return Reflect.get(obj, key)
+}
 
 function MyTable({
   yHeight,
@@ -43,33 +43,31 @@ function MyTable({
   pageSize = 10,
   pagingInfo = {
     showQuickJumper: true,
-    position: ["bottomCenter"],
-    showSizeChanger: true,
+    position: ['bottomCenter'],
+    showSizeChanger: true
   },
   onChange,
   lastBtn = [],
-  classKey = "",
+  classKey = '',
   merge,
   myTitle,
-  isNull = "(空)",
+  isNull = '(空)'
 }: Props) {
   useEffect(() => {
-    const dom = document.querySelector(
-      `.MyTable${classKey} .ant-table-body`
-    ) as HTMLDivElement;
+    const dom = document.querySelector(`.MyTable${classKey} .ant-table-body`) as HTMLDivElement
 
-    if (dom && yHeight) dom.style.height = yHeight + "px";
-  }, [classKey, yHeight]);
+    if (dom && yHeight) dom.style.height = yHeight + 'px'
+  }, [classKey, yHeight])
 
   // 页码变化
   const paginationChange = useCallback(
     () => (pageNum: number, pageSize: number) => {
       if (onChange) {
-        onChange(pageNum, pageSize);
+        onChange(pageNum, pageSize)
       }
     },
     [onChange]
-  );
+  )
 
   const dataChangeFu = useCallback(
     (v: any) => {
@@ -82,41 +80,44 @@ function MyTable({
        */
 
       const obj = {
-        index: (_: any, __: any, index: number) =>
-          index + 1 + (pageNum - 1) * pageSize,
+        index: (_: any, __: any, index: number) => index + 1 + (pageNum - 1) * pageSize,
         txt: (item: any) => item[v[2]] || isNull,
         img: (item: any) => (
-          <div className="tableImgAuto">
-            <ImageLazy width={60} height={60} src={item[v[2]] || item.thumb} />
+          <div className='tableImgAuto'>
+            <ImageLazy
+              width={60}
+              height={60}
+              src={item[v[2]] || item.thumb}
+              srcBig={item.thumbPc}
+            />
           </div>
         ),
-        txtChange: (item: any) =>
-          Reflect.get(v[3], item[v[2]]) || v[4] || isNull,
+        txtChange: (item: any) => Reflect.get(v[3], item[v[2]]) || v[4] || isNull,
         text: (item: any) => {
-          let tempCom: any = item[v[2]] || isNull;
+          let tempCom: any = item[v[2]] || isNull
 
           if (tempCom.length >= v[3]) {
-            tempCom = tempCom.substring(0, v[3]) + "...";
+            tempCom = tempCom.substring(0, v[3]) + '...'
           }
 
           if (v[4]) {
-            tempCom = tableComObj(v[4], [tempCom, item[v[2]]]);
+            tempCom = tableComObj(v[4], [tempCom, item[v[2]]])
           } else if (item[v[2]].length >= v[3]) {
             tempCom = (
-              <span style={{ cursor: "pointer" }} title={item[v[2]]}>
+              <span style={{ cursor: 'pointer' }} title={item[v[2]]}>
                 {tempCom}
               </span>
-            );
+            )
           }
 
-          return tempCom;
-        },
-      };
+          return tempCom
+        }
+      }
 
-      return Reflect.get(obj, v[0]);
+      return Reflect.get(obj, v[0])
     },
     [isNull, pageNum, pageSize]
-  );
+  )
 
   const columns = useMemo(() => {
     const arr: any = columnsTemp.map((v: any) => ({
@@ -126,21 +127,21 @@ function MyTable({
         merge && v.includes(merge.type)
           ? // {rowSpan:3}
             (item: any, index: number) => ({
-              rowSpan: index === 0 ? merge.num : 0,
+              rowSpan: index === 0 ? merge.num : 0
             })
-          : "",
-    }));
+          : ''
+    }))
 
-    return arr;
-  }, [columnsTemp, dataChangeFu, merge, myTitle]);
+    return arr
+  }, [columnsTemp, dataChangeFu, merge, myTitle])
 
   return (
     <Table
       className={`${styles.MyTable} MyTable${classKey}`}
-      scroll={{ y: yHeight ? yHeight : "" }}
+      scroll={{ y: yHeight ? yHeight : '' }}
       dataSource={list}
       columns={[...columns, ...lastBtn]}
-      rowKey="id"
+      rowKey='id'
       pagination={
         pagingInfo
           ? {
@@ -148,14 +149,14 @@ function MyTable({
               current: pageNum,
               pageSize: pageSize,
               total: total,
-              onChange: paginationChange(),
+              onChange: paginationChange()
             }
           : false
       }
     />
-  );
+  )
 }
 
-const MemoMyTable = React.memo(MyTable);
+const MemoMyTable = React.memo(MyTable)
 
-export default MemoMyTable;
+export default MemoMyTable

+ 1 - 0
后台管理/src/pages/A2message/A2audit/index.tsx

@@ -55,6 +55,7 @@ function A2audit({ sId, state, closeFu, succFu }: Props) {
         {A2SelectData.map(v => (
           <Button
             key={v.label}
+            disabled={v.value === 0 && state !== 0}
             onClick={() => auditFu(v.value)}
             type={v.value === newSta ? 'primary' : 'default'}
           >

+ 48 - 0
后台管理/src/pages/A3relation/A3add/index.module.scss

@@ -0,0 +1,48 @@
+.A3add {
+  :global {
+    .ant-modal-close {
+      display: none;
+    }
+    .ant-modal {
+      width: 800px !important;
+    }
+    .A3aMain {
+      border-top: 1px solid #ccc;
+      padding-top: 20px;
+
+      .formRow {
+        display: flex;
+
+        .formLeft {
+          position: relative;
+          top: 3px;
+          width: 63px;
+          text-align: right;
+
+          & > span {
+            color: #ff4d4f;
+          }
+        }
+
+        .formRight {
+          width: calc(100% - 63px);
+        }
+      }
+      .A3fromRow {
+        position: relative;
+
+        .A3_6Frow {
+          position: absolute;
+          left: 165px;
+          top: 5px;
+          color: #999;
+          font-size: 12px;
+        }
+      }
+      .A3aBtn {
+        margin-top: 40px;
+        padding-left: 66px;
+      }
+    }
+  }
+}

+ 175 - 0
后台管理/src/pages/A3relation/A3add/index.tsx

@@ -0,0 +1,175 @@
+import React, { useCallback, useEffect, useRef, useState } from 'react'
+import styles from './index.module.scss'
+import { Button, Form, FormInstance, Input, InputNumber, Modal } from 'antd'
+import { A3tableType } from '../data'
+import { MessageFu } from '@/utils/message'
+import { A3_APIsave } from '@/store/action/A3relation'
+import ZupOne from '@/components/ZupOne'
+import MyPopconfirm from '@/components/MyPopconfirm'
+
+type Props = {
+  info: A3tableType
+  closeFu: () => void
+  addTableFu: () => void
+  upTableFu: () => void
+}
+
+function A3add({ info, closeFu, addTableFu, upTableFu }: Props) {
+  // 表单的ref
+  const FormBoxRef = useRef<FormInstance>(null)
+
+  // 封面图的ref
+  const ZupThumbRef = useRef<any>(null)
+
+  // 编辑进来获取详情
+  const getInfoFu = useCallback(
+    (id: number) => {
+      FormBoxRef.current?.setFieldsValue(info)
+      // 设置封面图
+      ZupThumbRef.current?.setFileComFileFu({
+        fileName: '',
+        filePath: info.thumbPc,
+        thumb: info.thumb
+      })
+    },
+    [info]
+  )
+
+  useEffect(() => {
+    if (info.id > 0) getInfoFu(info.id)
+    else FormBoxRef.current?.setFieldsValue({ sort: 999 })
+  }, [getInfoFu, info.id])
+
+  // 附件 是否 已经点击过确定
+  const [fileCheck, setFileCheck] = useState(false)
+
+  // 没有通过校验
+  const onFinishFailed = useCallback(() => {
+    setFileCheck(true)
+  }, [])
+
+  //  通过校验点击确定
+  const onFinish = useCallback(
+    async (values: any) => {
+      setFileCheck(true)
+
+      const coverUrl1 = ZupThumbRef.current?.fileComFileResFu()
+      // 没有传 封面图
+      if (!coverUrl1.filePath) return MessageFu.warning('请上传头像')
+
+      const obj = {
+        ...values,
+        id: info.id > 0 ? info.id : null,
+        thumb: coverUrl1.thumb || '',
+        thumbPc: coverUrl1.filePath || ''
+      }
+
+      // if (1 + 1 === 2) {
+      //   console.log('------222', obj)
+      //   return
+      // }
+
+      const res = await A3_APIsave(obj)
+
+      if (res.code === 0) {
+        MessageFu.success(`${info.id > 0 ? '编辑' : '新增'}成功`)
+        if (info.id > 0) upTableFu()
+        else addTableFu()
+        closeFu()
+      }
+    },
+    [addTableFu, closeFu, info.id, upTableFu]
+  )
+
+  return (
+    <Modal
+      wrapClassName={styles.A3add}
+      open={true}
+      title={info.id > 0 ? '编辑人物' : '新增人物'}
+      footer={
+        [] // 设置footer为空,去掉 取消 确定默认按钮
+      }
+    >
+      <div className='A3aMain'>
+        <Form
+          ref={FormBoxRef}
+          name='basic'
+          labelCol={{ span: 2 }}
+          onFinish={onFinish}
+          onFinishFailed={onFinishFailed}
+          autoComplete='off'
+          scrollToFirstError
+        >
+          <Form.Item
+            label='姓名'
+            name='name'
+            rules={[{ required: true, message: '请输入姓名' }]}
+            // getValueFromEvent={(e) => e.target.value.replace(/\s+/g, "")}
+            getValueFromEvent={e => e.target.value.trim()}
+          >
+            <Input maxLength={10} showCount placeholder='请输入内容' />
+          </Form.Item>
+
+          {/* 头像 */}
+          <div className='formRow'>
+            <div className='formLeft'>
+              <span>* </span>
+              头像:
+            </div>
+            <div className='formRight'>
+              <ZupOne
+                ref={ZupThumbRef}
+                isLook={false}
+                fileCheck={fileCheck}
+                size={5}
+                dirCode='A3relation'
+                myUrl='cms/person/upload'
+                format={['image/jpeg', 'image/png']}
+                formatTxt='png、jpg和jpeg'
+                checkTxt='请上传头像'
+                upTxt='最多1张'
+                myType='thumb'
+              />
+            </div>
+          </div>
+
+          <Form.Item
+            label='关系'
+            name='type'
+            rules={[{ required: true, message: '请输入关系' }]}
+            // getValueFromEvent={(e) => e.target.value.replace(/\s+/g, "")}
+            getValueFromEvent={e => e.target.value.trim()}
+          >
+            <Input maxLength={10} showCount placeholder='请输入内容' />
+          </Form.Item>
+
+          <div className='A3fromRow'>
+            <Form.Item
+              label='排序值'
+              name='sort'
+              rules={[{ required: true, message: '请输入排序值' }]}
+            >
+              <InputNumber min={1} max={999} precision={0} placeholder='请输入' />
+            </Form.Item>
+            <div className='A3_6Frow'>
+              请输入1~999的数字。数字越小,排序越靠前。数字相同时,更新发布的内容排在前面
+            </div>
+          </div>
+
+          {/* 确定和取消按钮 */}
+          <Form.Item className='A3aBtn'>
+            <Button type='primary' htmlType='submit'>
+              提交
+            </Button>
+            &emsp;
+            <MyPopconfirm txtK='取消' onConfirm={closeFu} />
+          </Form.Item>
+        </Form>
+      </div>
+    </Modal>
+  )
+}
+
+const MemoA3add = React.memo(A3add)
+
+export default MemoA3add

+ 19 - 0
后台管理/src/pages/A3relation/A3group/A3gAdd/index.module.scss

@@ -0,0 +1,19 @@
+.A3gAdd {
+  :global {
+    .ant-modal-close {
+      display: none;
+    }
+    .ant-modal {
+      width: 800px !important;
+    }
+    .A3GAmain {
+      border-top: 1px solid #ccc;
+      padding-top: 20px;
+
+      .A3GAbtn {
+        margin-top: 40px;
+        padding-left: 94px;
+      }
+    }
+  }
+}

+ 138 - 0
后台管理/src/pages/A3relation/A3group/A3gAdd/index.tsx

@@ -0,0 +1,138 @@
+import React, { useCallback, useEffect, useRef } from 'react'
+import styles from './index.module.scss'
+import { Button, Form, FormInstance, Input, Modal, Select } from 'antd'
+import { A3GlistType, A3tableType } from '../../data'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import { A3_APIG_save } from '@/store/action/A3relation'
+import { MessageFu } from '@/utils/message'
+
+type Props = {
+  info: A3GlistType
+  waiList: A3tableType[]
+  closeFu: () => void
+  upTableFu: () => void
+}
+
+function A3gAdd({ info, waiList, closeFu, upTableFu }: Props) {
+  // 表单的ref
+  const FormBoxRef = useRef<FormInstance>(null)
+
+  // 之前的关系组人员id存起来
+  const personIdsOld = useRef<number[]>([])
+
+  // 编辑进来获取详情
+  const getInfoFu = useCallback(
+    (id: number) => {
+      let personIdsArr: number[] = []
+
+      if (info.personIds) {
+        personIdsArr = info.personIds.split(',').map(v => Number(v))
+        personIdsOld.current = personIdsArr
+      }
+
+      FormBoxRef.current?.setFieldsValue({ ...info, personIdsArr })
+    },
+    [info]
+  )
+
+  useEffect(() => {
+    if (info.id > 0) getInfoFu(info.id)
+  }, [getInfoFu, info.id])
+
+  // 没有通过校验
+  const onFinishFailed = useCallback(() => {}, [])
+
+  //  通过校验点击确定
+  const onFinish = useCallback(
+    async (values: any) => {
+      const personIdsArr: number[] = values.personIdsArr
+      const obj: any = {
+        id: info.id > 0 ? info.id : null,
+        name: values.name,
+        personIds: personIdsArr.join(',')
+      }
+
+      // 需要删除人物ids
+      if (info.id > 0) {
+        const set2 = new Set(personIdsArr)
+        const delPersonIds = personIdsOld.current.filter(item => !set2.has(item))
+
+        if (delPersonIds && delPersonIds.length) {
+          obj.delPersonIds = delPersonIds.join(',')
+        }
+      }
+
+      const res = await A3_APIG_save(obj)
+      if (res.code === 0) {
+        MessageFu.success(info.id > 0 ? '编辑成功' : '新增成功')
+        upTableFu()
+        closeFu()
+      }
+    },
+    [closeFu, info.id, upTableFu]
+  )
+
+  return (
+    <Modal
+      wrapClassName={styles.A3gAdd}
+      open={true}
+      title={info.id > 0 ? '编辑关系组' : '新增关系组'}
+      footer={
+        [] // 设置footer为空,去掉 取消 确定默认按钮
+      }
+    >
+      <div className='A3GAmain'>
+        <Form
+          ref={FormBoxRef}
+          name='basic'
+          labelCol={{ span: 3 }}
+          onFinish={onFinish}
+          onFinishFailed={onFinishFailed}
+          autoComplete='off'
+          scrollToFirstError
+        >
+          <Form.Item
+            label='名称'
+            name='name'
+            rules={[{ required: true, message: '请输入名称' }]}
+            // getValueFromEvent={(e) => e.target.value.replace(/\s+/g, "")}
+            getValueFromEvent={e => e.target.value.trim()}
+          >
+            <Input maxLength={10} showCount placeholder='请输入内容' />
+          </Form.Item>
+
+          <Form.Item
+            label='关系组人员'
+            name='personIdsArr'
+            rules={[{ required: true, message: '请选择关系组人员' }]}
+          >
+            <Select
+              showSearch={false}
+              mode='multiple'
+              allowClear
+              style={{ width: '100%' }}
+              placeholder='请选择'
+              // value={personIds||[]}
+              // onChange={value => setPersonIds(value)}
+              options={waiList}
+              fieldNames={{ value: 'id', label: 'name' }}
+            />
+          </Form.Item>
+
+          {/* 确定和取消按钮 */}
+          <Form.Item className='A3GAbtn'>
+            <Button type='primary' htmlType='submit'>
+              提交
+            </Button>
+            &emsp;
+            <MyPopconfirm txtK='取消' onConfirm={closeFu} />
+          </Form.Item>
+        </Form>
+      </div>
+    </Modal>
+  )
+}
+
+const MemoA3gAdd = React.memo(A3gAdd)
+
+export default MemoA3gAdd

+ 22 - 0
后台管理/src/pages/A3relation/A3group/index.module.scss

@@ -0,0 +1,22 @@
+.A3group {
+  width: 100%;
+  height: 100%;
+  background-color: #fff;
+  border-radius: 10px;
+  padding: 20px;
+  :global {
+    .A3gTop {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      margin-bottom: 15px;
+      & > h3 {
+        color: var(--themeColor);
+        font-size: 18px;
+      }
+    }
+    .ant-table-cell {
+      padding: 8px !important;
+    }
+  }
+}

+ 123 - 0
后台管理/src/pages/A3relation/A3group/index.tsx

@@ -0,0 +1,123 @@
+import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
+import styles from './index.module.scss'
+import { Button } from 'antd'
+import { A3_APIG_del, A3_APIG_getList, A3_APIgetList } from '@/store/action/A3relation'
+import { A3GlistType, A3tableType } from '../data'
+import MyTable from '@/components/MyTable'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import { MessageFu } from '@/utils/message'
+import A3gAdd from './A3gAdd'
+
+type Props = {
+  closeFu: () => void
+  upTableFu: () => void
+}
+
+function A3group({ closeFu, upTableFu }: Props) {
+  // 拿到所有外层人物的列表
+  const [waiList, setWaiList] = useState<A3tableType[]>([])
+
+  const [list, setList] = useState<A3GlistType[]>([])
+
+  const getListFu = useCallback(async (flag?: boolean) => {
+    const res = await A3_APIG_getList()
+    if (res.code === 0) {
+      setList(res.data || [])
+    }
+    if (!flag) {
+      // 拿到所有外层人物的列表
+      const res2 = await A3_APIgetList({ pageNum: 1, pageSize: 99999 }, true)
+      if (res2.code === 0) {
+        setWaiList(res2.data.records || [])
+      }
+    }
+  }, [])
+
+  useEffect(() => {
+    getListFu()
+  }, [getListFu])
+
+  const delTableFu = useCallback(
+    async (id: number) => {
+      const res = await A3_APIG_del(id)
+      if (res.code === 0) {
+        MessageFu.success('删除成功!')
+        getListFu()
+      }
+    },
+    [getListFu]
+  )
+
+  const tableLastBtn = useMemo(() => {
+    return [
+      {
+        title: '关系组人员',
+        render: (item: A3GlistType) => (item.personsName ? item.personsName.join(',') : '(空)')
+      },
+      {
+        title: '操作',
+        render: (item: A3GlistType) => (
+          <>
+            <Button size='small' type='text' onClick={() => setAddInfo(item)}>
+              编辑
+            </Button>
+            <MyPopconfirm txtK='删除' onConfirm={() => delTableFu(item.id)} />
+          </>
+        )
+      }
+    ]
+  }, [delTableFu])
+
+  // 是否需要更新外部表格
+  const waiUpFlag = useRef(false)
+
+  // 新增和编辑关系组
+  const [addInfo, setAddInfo] = useState({} as A3GlistType)
+
+  return (
+    <div className={styles.A3group}>
+      <div className='A3gTop'>
+        <h3>关系组设置</h3>
+        <div>
+          <Button type='primary' onClick={() => setAddInfo({ id: -1 } as A3GlistType)}>
+            新增关系组
+          </Button>
+          &emsp;
+          <Button
+            onClick={() => {
+              if (waiUpFlag.current) upTableFu()
+              closeFu()
+            }}
+          >
+            关闭
+          </Button>
+        </div>
+      </div>
+
+      <MyTable
+        classKey='A3group'
+        yHeight={600}
+        list={list}
+        columnsTemp={[['txt', '关系组名称', 'name']]}
+        lastBtn={tableLastBtn}
+        pagingInfo={false}
+      />
+      {/* 新增和编辑关系组 */}
+      {addInfo.id ? (
+        <A3gAdd
+          info={addInfo}
+          waiList={waiList}
+          closeFu={() => setAddInfo({} as A3GlistType)}
+          upTableFu={() => {
+            waiUpFlag.current = true
+            getListFu(true)
+          }}
+        />
+      ) : null}
+    </div>
+  )
+}
+
+const MemoA3group = React.memo(A3group)
+
+export default MemoA3group

+ 25 - 0
后台管理/src/pages/A3relation/data.ts

@@ -0,0 +1,25 @@
+export type A3tableType = {
+  createTime: string
+  creatorId: number
+  creatorName: string
+  id: number
+  name: string
+  relationId: number
+  relationName: string
+  sort: number
+  thumb: string
+  thumbPc: string
+  type: string
+  updateTime: string
+}
+
+export type A3GlistType = {
+  createTime: string
+  creatorId: number
+  creatorName: string
+  id: number
+  name: string
+  personIds: string
+  personsName: string[]
+  updateTime: string
+}

+ 28 - 0
后台管理/src/pages/A3relation/index.module.scss

@@ -1,4 +1,32 @@
 .A3relation {
   :global {
+    .A3top {
+      padding: 15px 24px;
+      border-radius: 10px;
+      background-color: #fff;
+      display: flex;
+      justify-content: space-between;
+    }
+
+    .A3tableBox {
+      border-radius: 10px;
+      overflow: hidden;
+      margin-top: 15px;
+      height: calc(100% - 77px);
+      background-color: #fff;
+      .ant-table-tbody .ant-table-cell {
+        padding: 8px !important;
+      }
+    }
+    .A3groupBox {
+      position: absolute;
+      top: 0;
+      left: 0;
+      width: 100%;
+      height: 100%;
+      padding: 50px 80px;
+      background-color: rgba(0, 0, 0, 0.7);
+      border-radius: 10px;
+    }
   }
 }

+ 112 - 1
后台管理/src/pages/A3relation/index.tsx

@@ -1,9 +1,120 @@
-import React from 'react'
+import React, { useCallback, useEffect, useMemo, useState } from 'react'
 import styles from './index.module.scss'
+import { useDispatch, useSelector } from 'react-redux'
+import { A3_APIdel, A3_APIgetList } from '@/store/action/A3relation'
+import { RootState } from '@/store'
+import { MessageFu } from '@/utils/message'
+import { A3tableType } from './data'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import { Button } from 'antd'
+import MyTable from '@/components/MyTable'
+import { A3tableC } from '@/utils/tableData'
+import A3add from './A3add'
+import A3group from './A3group'
+
+const baseFromData = {
+  pageNum: 1,
+  pageSize: 10
+}
+
 function A3relation() {
+  const dispatch = useDispatch()
+
+  const [fromData, setFromData] = useState(baseFromData)
+
+  const getListFu = useCallback(() => {
+    dispatch(A3_APIgetList(fromData))
+  }, [dispatch, fromData])
+
+  useEffect(() => {
+    getListFu()
+  }, [getListFu])
+
+  const tableInfo = useSelector((state: RootState) => state.A3relation.tableInfo)
+
+  const delTableFu = useCallback(
+    async (id: number) => {
+      const res = await A3_APIdel(id)
+      if (res.code === 0) {
+        MessageFu.success('删除成功!')
+        getListFu()
+      }
+    },
+    [getListFu]
+  )
+
+  const tableLastBtn = useMemo(() => {
+    return [
+      {
+        title: '操作',
+        width: 120,
+        render: (item: A3tableType) => (
+          <>
+            <Button size='small' type='text' onClick={() => setAddInfo(item)}>
+              编辑
+            </Button>
+            <MyPopconfirm txtK='删除' onConfirm={() => delTableFu(item.id)} />
+          </>
+        )
+      }
+    ]
+  }, [delTableFu])
+
+  // 新增和编辑
+  const [addInfo, setAddInfo] = useState({} as A3tableType)
+
+  // 关系组页面
+  const [group, setGroup] = useState(false)
+
   return (
     <div className={styles.A3relation}>
       <div className='pageTitle'>人际关系</div>
+
+      {/* 顶部筛选 */}
+      <div className='A3top'>
+        <div></div>
+
+        <div>
+          <Button type='primary' onClick={() => setGroup(true)}>
+            关系组设置
+          </Button>
+          &emsp;
+          <Button type='primary' onClick={() => setAddInfo({ id: -1 } as A3tableType)}>
+            新增人物
+          </Button>
+        </div>
+      </div>
+
+      {/* 表格主体 */}
+      <div className='A3tableBox'>
+        <MyTable
+          yHeight={625}
+          list={tableInfo.list}
+          columnsTemp={A3tableC}
+          lastBtn={tableLastBtn}
+          pageNum={fromData.pageNum}
+          pageSize={fromData.pageSize}
+          total={tableInfo.total}
+          onChange={(pageNum, pageSize) => setFromData({ ...fromData, pageNum, pageSize })}
+        />
+      </div>
+
+      {/* 新增和编辑-人物 */}
+      {addInfo.id ? (
+        <A3add
+          info={addInfo}
+          closeFu={() => setAddInfo({} as A3tableType)}
+          addTableFu={() => setFromData({ ...baseFromData })}
+          upTableFu={getListFu}
+        />
+      ) : null}
+
+      {/* 关系组页面 */}
+      {group ? (
+        <div className='A3groupBox'>
+          <A3group closeFu={() => setGroup(false)} upTableFu={getListFu} />
+        </div>
+      ) : null}
     </div>
   )
 }

+ 57 - 0
后台管理/src/store/action/A3relation.ts

@@ -0,0 +1,57 @@
+import http from '@/utils/http'
+import { AppDispatch } from '..'
+
+/**
+ *人际关系-列表
+ */
+
+export const A3_APIgetList = (data: any, isAll?: boolean): any => {
+  if (isAll) return http.post('cms/person/pageList', data)
+
+  return async (dispatch: AppDispatch) => {
+    const res = await http.post('cms/person/pageList', data)
+    if (res.code === 0) {
+      const obj = {
+        list: res.data.records,
+        total: res.data.total
+      }
+      dispatch({ type: 'A3/getList', payload: obj })
+    }
+  }
+}
+
+/**
+ * 人际关系-删除
+ */
+export const A3_APIdel = (id: number) => {
+  return http.get(`cms/person/remove/${id}`)
+}
+
+/**
+ * 人际关系-新增、编辑
+ */
+export const A3_APIsave = (data: any) => {
+  return http.post('cms/person/save', data)
+}
+
+// -------------------关系组-----------------
+/**
+ * 人际关系-关系组-获取列表
+ */
+export const A3_APIG_getList = () => {
+  return http.post('cms/relation/getList')
+}
+
+/**
+ * 人际关系-关系组-删除
+ */
+export const A3_APIG_del = (id: number) => {
+  return http.get(`cms/relation/remove/${id}`)
+}
+
+/**
+ * 人际关系-关系组-新增、编辑
+ */
+export const A3_APIG_save = (data: any) => {
+  return http.post('cms/relation/save', data)
+}

+ 28 - 0
后台管理/src/store/reducer/A3relation.ts

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

+ 2 - 0
后台管理/src/store/reducer/index.ts

@@ -5,6 +5,7 @@ import { combineReducers } from 'redux'
 import A0Layout from './layout'
 import A1works from './A1works'
 import A2message from './A2message'
+import A3relation from './A3relation'
 
 import Z1user from './Z1user'
 import Z2log from './Z2log'
@@ -14,6 +15,7 @@ const rootReducer = combineReducers({
   A0Layout,
   A1works,
   A2message,
+  A3relation,
   Z1user,
   Z2log
 })

+ 8 - 0
后台管理/src/utils/tableData.ts

@@ -29,6 +29,14 @@ export const A2tableC = [
   // ['text', '简介', 'content', 100]
 ]
 
+export const A3tableC = [
+  ['txt', '姓名', 'name'],
+  ['img', '头像', 'thumb'],
+  ['txt', '关系', 'type'],
+  ['txt', '关系组', 'relationName'],
+  ['txt', '排序', 'sort']
+]
+
 export const Z1tableC = [
   ['txt', '用户名', 'userName'],
   ['txtChange', '角色', 'isAdmin', { 1: '管理员', 0: '普通成员' }],