shaogen1995 1 year ago
parent
commit
a2fe1a32e6

+ 2 - 0
.vscode/settings.json

@@ -0,0 +1,2 @@
+{
+}

+ 31 - 5
src/pages/A1outline/index.tsx

@@ -2,13 +2,15 @@ import React, { useCallback, useEffect, useRef, useState } from "react";
 import styles from "./index.module.scss";
 import { Button } from "antd";
 import { useDispatch, useSelector } from "react-redux";
-import { A1_APIgetInfo } from "@/store/action/A1outline";
+import { A1_APIgetInfo, editIntroAPI } from "@/store/action/A1outline";
 import ZRichText from "@/components/ZRichText";
 import { RootState } from "@/store";
+import { MessageFu } from "@/utils/message";
 
 function A1outline() {
   // 富文本的ref
   const ZRichTextRef = useRef<any>(null);
+  const [loading, setLoading] = useState(false)
 
   const dispatch = useDispatch();
 
@@ -21,6 +23,7 @@ function A1outline() {
   }, [getInfoFu]);
 
   const text = useSelector((state: RootState) => state.A1outline.data);
+  const detailId = useSelector((state: RootState) => state.A1outline.id);
 
   useEffect(() => {
     ZRichTextRef.current?.ritxtShowFu(text);
@@ -30,15 +33,38 @@ function A1outline() {
   const [isEdit, setIsEdit] = useState(true);
 
   // 点击确定
-  const btnOkFu = useCallback(() => {
-    const rtf = ZRichTextRef.current?.fatherBtnOkFu();
-  }, []);
+  const btnOkFu = useCallback(async() => {
+    try {
+      setLoading(true)
+      const rtf = ZRichTextRef.current?.fatherBtnOkFu();
+      await editIntroAPI({
+        id: detailId,
+        rtf: rtf.val
+      })
+      setIsEdit(true)
+      MessageFu.success('保存成功')
+    } finally {
+      setLoading(false)
+    }
+  }, [detailId]);
+
+  const handleCancel = () => {
+    setIsEdit(true)
+    ZRichTextRef.current?.ritxtShowFu(text);
+  }
 
   return (
     <div className={styles.A1outline}>
       <div className="pageTitle">概述管理</div>
       <div className="A1top">
-        <Button type="primary">编辑</Button>
+        {
+          isEdit ? (
+            <Button type="primary" onClick={() => setIsEdit(false)}>编辑</Button>
+          ) : <>
+            <Button style={{marginRight: '10px'}} onClick={handleCancel}>取消</Button>
+            <Button loading={loading} type="primary" onClick={btnOkFu}>保存</Button>
+          </>
+        }
       </div>
       <div className="A1main">
         <ZRichText

+ 9 - 1
src/pages/A2intro/index.module.scss

@@ -3,5 +3,13 @@
   border-radius: 10px;
   padding: 24px;
 
-  // :global {}
+  :global {
+    .A2main {
+      height: calc(100% - 62px - 32px);
+    }
+    .A2toolbar {
+      margin-bottom: 10px;
+      text-align: right;
+    }
+  }
 }

+ 86 - 1
src/pages/A2intro/index.tsx

@@ -1,9 +1,94 @@
-import React from "react";
+import React, { useCallback, useEffect, useRef, useState } from "react";
 import styles from "./index.module.scss";
+import { Button, Tabs } from "antd";
+import { editAboutAPI, getAboutListAPI } from "@/store/action/A2intro";
+import { useDispatch, useSelector } from "react-redux";
+import { RootState } from "@/store";
+import ZRichText from "@/components/ZRichText";
+import { MessageFu } from "@/utils/message";
+
 function A2intro() {
+  const dispatch = useDispatch();
+  const tableInfo = useSelector((state: RootState) => state.A2intro.tableInfo.map((i, idx) => ({
+    ...i,
+    key: `${idx}`,
+    label: i.name,
+  })));
+  const [activeKey, setActiveKey] = useState('0');
+  const [isLook, setIsLook] = useState(true);
+  const [loading, setLoading] = useState(false);
+  const ZRichTextRef = useRef<any>(null);
+
+  const getList = useCallback(async () => {
+    const data = await getAboutListAPI()
+    ZRichTextRef.current?.ritxtShowFu(data[0].rtf);
+    dispatch({ type: "A2/getList", payload: data });
+  }, [dispatch]);
+
+  useEffect(() => {
+    getList();
+  }, [getList]);
+
+  const handleSave = async() => {
+    try {
+      setLoading(true)
+      const val = ZRichTextRef.current?.fatherBtnOkFu().val
+      await editAboutAPI({
+        id: tableInfo[Number(activeKey)].id,
+        rtf: val
+      })
+      setIsLook(true)
+      MessageFu.success('保存成功')
+      const clone = [...tableInfo]
+      clone[Number(activeKey)].rtf = val
+      dispatch({ type: "A2/getList", payload: clone });
+    } finally {
+      setLoading(false)
+    }
+  };
+
+  const cancelSave = () => {
+    setIsLook(true)
+    ZRichTextRef.current?.ritxtShowFu(tableInfo[Number(activeKey)].rtf);
+  }
+
   return (
     <div className={styles.A2intro}>
       <div className="pageTitle">简介管理</div>
+
+      {/* @ts-ignore */}
+      <Tabs items={tableInfo} onChange={v => {
+        setActiveKey(v)
+        setIsLook(true)
+        ZRichTextRef.current?.ritxtShowFu(tableInfo[Number(v)].rtf);
+      }} />
+
+      <div className="A2toolbar">
+        {isLook ? (
+          <Button onClick={() => setIsLook(false)}>编辑</Button>
+        ) : <>
+          <Button
+            style={{marginRight: '10px'}}
+            onClick={cancelSave}
+          >取消</Button>
+          <Button
+            type="primary"
+            loading={loading}
+            onClick={handleSave}
+          >保存</Button>
+        </>}
+      </div>
+
+      <div className="A2main">
+        <ZRichText
+          check={false}
+          dirCode="A1outline"
+          isLook={isLook}
+          ref={ZRichTextRef}
+          myUrl="cms/about/upload"
+          full={true}
+        />
+      </div>
     </div>
   );
 }

+ 16 - 4
src/pages/A3message/index.module.scss

@@ -1,7 +1,19 @@
 .A3message {
-  background-color: #fff;
-  border-radius: 10px;
-  padding: 24px;
+  :global {
+    .selectBox {
+      border-radius: 10px;
+      padding: 15px 24px;
+      background-color: #fff;
+      display: flex;
+      justify-content: space-between;
+    }
 
-  // :global {}
+    .tableBox {
+      border-radius: 10px;
+      overflow: hidden;
+      margin-top: 15px;
+      height: calc(100% - 77px);
+      background-color: #fff;
+    }
+  }
 }

+ 126 - 1
src/pages/A3message/index.tsx

@@ -1,9 +1,134 @@
-import React from "react";
+import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
 import styles from "./index.module.scss";
+import { Button, Input } from "antd";
+import { UserTableAPIType, UserTableListType } from "@/types";
+import { useDispatch, useSelector } from "react-redux";
+import { getMessageListAPI, removeMessageAPI } from "@/store/action/A3message";
+import MyTable from "@/components/MyTable";
+import { RootState } from "@/store";
+import { MessageFu } from "@/utils/message";
+import { A3tableC } from "@/utils/tableData";
+import MyPopconfirm from "@/components/MyPopconfirm";
 function A3message() {
+  const dispatch = useDispatch();
+
+  // 顶部筛选
+  const [fromData, setFromData] = useState<UserTableAPIType>({
+    pageNum: 1,
+    pageSize: 10,
+    searchKey: "",
+  });
+
+  // 封装发送请求的函数
+
+  const getList = useCallback(async () => {
+    dispatch(getMessageListAPI(fromData));
+  }, [dispatch, fromData]);
+
+  useEffect(() => {
+    getList();
+  }, [getList]);
+
+  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,
+          pageNum: 1,
+        });
+      }, 500);
+    },
+    [fromData]
+  );
+
+  // 点击重置
+  const [inputKey, setInputKey] = useState(1);
+  const resetSelectFu = useCallback(() => {
+    // 把2个输入框和时间选择器清空
+    setInputKey(Date.now());
+    setFromData({
+      pageNum: 1,
+      pageSize: 10,
+      searchKey: "",
+    });
+  }, []);
+
+  // 从仓库中获取表格数据
+  const tableInfo = useSelector((state: RootState) => state.A3message.tableInfo);
+
+  // 点击删除
+  const delTableFu = useCallback(
+    async (id: number) => {
+      const res: any = await removeMessageAPI(id);
+      if (res.code === 0) {
+        MessageFu.success("删除成功!");
+        getList();
+      }
+    },
+    [getList]
+  );
+
+  const tableLastBtn = useMemo(() => {
+    return [
+      {
+        title: "操作",
+        render: (item: UserTableListType) => {
+          return item.isAdmin === 1 ? (
+            "-"
+          ) : (
+            <>
+              <MyPopconfirm txtK="删除" onConfirm={() => delTableFu(item.id)} />
+            </>
+          );
+        },
+      },
+    ];
+  }, [delTableFu]);
+
   return (
     <div className={styles.A3message}>
       <div className="pageTitle">留言反馈</div>
+
+      <div className="userTop">
+        <div className="selectBox">
+          <div className="selectBoxRow">
+            <span>搜索项:</span>
+            <Input
+              key={inputKey}
+              maxLength={10}
+              showCount
+              style={{ width: 300 }}
+              placeholder="请输入用户名"
+              allowClear
+              onChange={(e) => txtChangeFu(e, "searchKey")}
+            />
+          </div>
+
+          <div className="selectBoxRow">
+            &emsp;&emsp;<Button onClick={resetSelectFu}>重置</Button>
+          </div>
+        </div>
+      </div>
+
+      {/* 表格主体 */}
+      <div className="tableBox">
+        <MyTable
+          yHeight={617}
+          list={tableInfo.list}
+          columnsTemp={A3tableC}
+          lastBtn={tableLastBtn}
+          pageNum={fromData.pageNum}
+          pageSize={fromData.pageSize}
+          total={tableInfo.total}
+          onChange={(pageNum, pageSize) =>
+            setFromData({ ...fromData, pageNum, pageSize })
+          }
+        />
+      </div>
     </div>
   );
 }

+ 48 - 3
src/pages/A4hot/index.tsx

@@ -1,4 +1,4 @@
-import React, { useCallback, useEffect, useRef, useState } from "react";
+import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
 import styles from "./index.module.scss";
 import { useDispatch, useSelector } from "react-redux";
 import { A4_APIgetInfo } from "@/store/action/A4hot";
@@ -51,6 +51,27 @@ function A4hot() {
 
   // 从仓库获取数据
   const dataAll = useSelector((state: RootState) => state.A4hot.list);
+  const filterData = useMemo(() => {
+    const temp = [...dataAll];
+    const find18D1fIndex = temp.findIndex(i => i.name === '十八洞村陈列馆一楼');
+    const find18D2fIndex = temp.findIndex(i => i.name === '十八洞村陈列馆二楼');
+    if (find18D1fIndex > -1 && find18D2fIndex > -1) {
+      const temp18D1 = temp[find18D1fIndex];
+      const temp18D2 = temp[find18D2fIndex];
+      temp18D1.name = '十八洞村陈列馆';
+      temp18D1.pcsCheck += temp18D2.pcsCheck;
+      temp18D1.pcsShare += temp18D2.pcsShare;
+      temp18D1.pcsVisit += temp18D2.pcsVisit;
+      temp.splice(find18D2fIndex, 1)
+    }
+
+    const find18DV1Index = temp.findIndex(i => i.name === '十八洞村村部一楼');
+    if (find18DV1Index > -1) {
+      temp[find18DV1Index].name = '十八洞村村部';
+    }
+
+    return temp;
+  }, [dataAll])
 
   // 生成饼图的函数
   const echBingFu = useCallback(
@@ -157,7 +178,7 @@ function A4hot() {
 
     // 单个饼图
 
-    dataAll.forEach((v) => {
+    filterData.forEach((v) => {
       maxFileArr[0].value += v.pcsVisit;
       maxFileArr[1].value += v.pcsStar;
       maxFileArr[2].value += v.pcsCheck;
@@ -169,8 +190,32 @@ function A4hot() {
       maxFileArr[3].bing.push({ name: v.name, value: v.pcsShare });
     });
     maxFileArr = maxFileArr.sort((a, b) => b.value - a.value);
+
+    maxFileArr[0].bing = getTop4Arr(maxFileArr[0].bing)
+    maxFileArr[1].bing = getTop4Arr(maxFileArr[1].bing)
+    maxFileArr[2].bing = getTop4Arr(maxFileArr[2].bing)
+    maxFileArr[3].bing = getTop4Arr(maxFileArr[3].bing)
+
     setMaxData(maxFileArr);
-  }, [dataAll]);
+  }, [filterData]);
+
+  const getTop4Arr = (arr: any[]) => {
+    const clone = arr.sort((a, b) => b.value - a.value)
+    const temp: any[] = []
+    clone.forEach((item, idx) => {
+      if (idx < 4) {
+        temp.push(item)
+      } else if (idx === 4) {
+        temp.push({
+          name: '其他',
+          value: item.value
+        })
+      } else if (temp[4]) {
+        temp[4].value += item.value
+      }
+    })
+    return temp
+  }
 
   const maxDataObjRef = useRef({
     pcsVisit: echRef2,

+ 5 - 1
src/store/action/A1outline.ts

@@ -7,7 +7,11 @@ export const A1_APIgetInfo = () => {
   return async (dispatch: AppDispatch) => {
     const res = await http.get("cms/intro/detail");
     if (res.code === 0) {
-      dispatch({ type: "A1/data", payload: res.data.rtf });
+      dispatch({ type: "A1/data", payload: res.data });
     }
   };
 };
+
+export const editIntroAPI = (params: any) => {
+  return http.post('cms/intro/edit', params);
+};

+ 13 - 0
src/store/action/A2intro.ts

@@ -0,0 +1,13 @@
+import http from "@/utils/http";
+
+export const getAboutListAPI = async () => {
+  const res = await http.get("cms/about/getList");
+  if (res.code === 0) {
+    return res.data
+  }
+  return []
+};
+
+export const editAboutAPI = (params: any) => {
+  return http.post('cms/about/edit', params);
+};

+ 23 - 0
src/store/action/A3message.ts

@@ -0,0 +1,23 @@
+import { UserTableAPIType } from "@/types";
+import http from "@/utils/http";
+import { AppDispatch } from "..";
+/**
+ * 获取留言表格列表
+ */
+export const getMessageListAPI = (data: UserTableAPIType) => {
+  return async (dispatch: AppDispatch) => {
+    const res = await http.post("cms/message/pageList", data);
+    if (res.code === 0) {
+      const obj = {
+        list: res.data.records,
+        total: res.data.total,
+      };
+
+      dispatch({ type: "A3/getList", payload: obj });
+    }
+  };
+};
+
+export const removeMessageAPI = (id: number) => {
+  return http.get(`cms/message/removes/${id}`);
+};

+ 3 - 2
src/store/reducer/A1outline.ts

@@ -1,12 +1,13 @@
 // 初始化状态
 const initState = {
   data: "",
+  id: 0
 };
 
 // 定义 action 类型
 type Props = {
   type: "A1/data";
-  payload: string;
+  payload: any;
 };
 
 // reducer
@@ -14,7 +15,7 @@ export default function userReducer(state = initState, action: Props) {
   switch (action.type) {
     // 获取列表数据
     case "A1/data":
-      return { ...state, data: action.payload };
+      return { ...state, data: action.payload.rtf, id: action.payload.id };
 
     default:
       return state;

+ 29 - 0
src/store/reducer/A2intro.ts

@@ -0,0 +1,29 @@
+export interface IntroItem {
+  id: number;
+  name: string;
+  rtf: string;
+}
+
+// 初始化状态
+const initState = {
+  // 列表数据
+  tableInfo: [] as IntroItem[],
+};
+
+// 定义 action 类型
+type Props = {
+  type: "A2/getList";
+  payload: IntroItem[];
+};
+
+// reducer
+export default function userReducer(state = initState, action: Props) {
+  switch (action.type) {
+    // 获取列表数据
+    case "A2/getList":
+      return { ...state, tableInfo: action.payload };
+
+    default:
+      return state;
+  }
+}

+ 28 - 0
src/store/reducer/A3message.ts

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

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

@@ -7,11 +7,15 @@ import A1outline from "./A1outline";
 import A4hot from "./A4hot";
 import Z1user from "./Z1user";
 import Z2log from "./Z2log";
+import A2intro from './A2intro'
+import A3message from './A3message'
 
 // 合并 reducer
 const rootReducer = combineReducers({
   A0Layout,
   A1outline,
+  A2intro,
+  A3message,
   A4hot,
   Z1user,
   Z2log,

+ 2 - 2
src/utils/http.ts

@@ -7,8 +7,8 @@ import { domShowFu } from "./domShow";
 
 const envFlag = process.env.NODE_ENV === "development";
 
-// const baseUrlTemp = "https://sit-wuxicishan.4dage.com"; // 测试环境
-const baseUrlTemp = "http://192.168.20.61:8068"; // 线下环境
+const baseUrlTemp = "https://sit-shibadong.4dage.com"; // 测试环境
+// const baseUrlTemp = "http://192.168.20.61:8068"; // 线下环境
 
 const baseFlag = baseUrlTemp.includes("https://");
 

+ 1 - 1
src/utils/storage.ts

@@ -1,7 +1,7 @@
 // ------------------------------------token的本地存储------------------------------------
 
 // 用户 Token 的本地缓存键名,自己定义
-const TOKEN_KEY = "WXCS_HT_USER_INFO";
+const TOKEN_KEY = "SBDC_HT_USER_INFO";
 
 /**
  * 从本地缓存中获取 用户 信息

+ 4 - 4
src/utils/tableData.ts

@@ -52,10 +52,10 @@ export const A2tableC3 = [
 ];
 
 export const A3tableC = [
-  ["txt", "时间", "createTime"],
-  ["txt", "用户名", "creatorName"],
-  ["txt", "类型", "type"],
-  ["text", "说明", "description", 50],
+  ["txt", "发布时间", "createTime"],
+  ["txt", "称呼", "name"],
+  ["txt", "联系方式", "phone"],
+  ["text", "内容", "content", 50],
 ];
 
 export const A4tableC = [