提交 21a3d404 authored 作者: 王鹏飞's avatar 王鹏飞

refactor(admin): migrate settings help module

上级 9b39dd3e
# Settings help migration
## Delivered
- Moved the Help route shell, list, and add/edit editor into `modules/settings/help` while retaining `/setting/help/list` and `/setting/help/addedit`.
- Preserved route state for edit navigation, permissions, list filters, delete confirmation, rich-editor preview, OSS image/video upload, add/edit publishing, and back navigation.
- Extracted the Help API, query construction, and list state; replaced only `TableCom` and `PaginationCom` with controlled `AppList`.
- Removed the old Help page implementation and styles.
## Compatibility exception
`pages/setting/help/addedit/requet.js` remains because multiple un-migrated pages import its OSS-token helper. The migrated Help editor calls it only as a compatibility dependency.
## Verification
- `pnpm build`: passed for both learning and admin.
- `pnpm test`: Admin 11/11 passed. The workspace remains red because of existing Learning failures in `src/modules/my/routes.test.tsx`, `src/api/http-auth.test.ts`, and router tests without a `QueryClientProvider`.
- `git diff --check`: passed.
import { Outlet } from "react-router";
import { Outlet } from 'react-router'
const Help = () => {
return (
......
import axios from "@/utils/request.js";
import axios from '@/utils/request.js';
import qs from "qs";
import { message } from "antd";
import { get } from "lodash-es";
......
export function buildHelpQuery({ page, pageSize, filters = {} }) {
const query = { page, page_size: pageSize }
Object.entries(filters).forEach(([key, value]) => {
if (value) query[key] = value
})
return query
}
import { lazy } from 'react'
import { Navigate, useRoutes } from 'react-router'
import HelpLayout from './HelpLayout'
const HelpListView = lazy(() => import('./views/HelpListView'))
const HelpAddEditView = lazy(() => import('./views/HelpAddEditView'))
export default function HelpRoutes() {
return useRoutes([
{
Component: HelpLayout,
children: [
{ index: true, element: <Navigate to="/setting/help/list" /> },
{ path: 'list', Component: HelpListView },
{ path: 'addedit', Component: HelpAddEditView },
],
},
{ path: '*', element: <Navigate to="/setting/help/list" /> },
])
}
import { useCallback, useEffect, useRef, useState } from 'react'
import { getList } from './api'
import { buildHelpQuery } from './query'
export function useHelpList() {
const [rows, setRows] = useState([])
const [total, setTotal] = useState(0)
const [page, setPage] = useState(1)
const [pageSize, setPageSize] = useState(10)
const [loading, setLoading] = useState(true)
const [error, setError] = useState(null)
const requestId = useRef(0)
const init = useCallback(async (filters = {}, nextPage = page, nextPageSize = pageSize) => {
const id = ++requestId.current
setLoading(true)
setError(null)
try {
const result = await getList(buildHelpQuery({ page: nextPage, pageSize: nextPageSize, filters }))
if (id === requestId.current && result) {
setRows(result.list || [])
setTotal(result.total || 0)
}
} catch (reason) {
if (id === requestId.current) setError(reason instanceof Error ? reason : new Error('数据获取失败!'))
} finally {
if (id === requestId.current) setLoading(false)
}
}, [page, pageSize])
useEffect(() => {
void init({}, 1, 10)
}, [])
const changePage = useCallback((nextPage, filters) => {
setPage(nextPage)
void init(filters, nextPage, pageSize)
}, [init, pageSize])
const changePageSize = useCallback((nextPageSize, filters) => {
setPage(1)
setPageSize(nextPageSize)
void init(filters, 1, nextPageSize)
}, [init])
return { rows, total, page, pageSize, loading, error, init, changePage, changePageSize }
}
......@@ -6,14 +6,14 @@ import { Editor, Toolbar } from "@wangeditor/editor-for-react";
import { DomEditor } from "@wangeditor/editor";
import { useLocation, useNavigate } from "react-router";
import { CloseOutlined } from "@ant-design/icons";
import { addHelp, HelpInfo, editHelp, editPreview } from "../requet";
import { addHelp, HelpInfo, editHelp, editPreview } from "../api";
import { uploadFiles } from "@/utils/upload";
import AliOSS from "ali-oss";
import dayjs from "dayjs";
import { getAliOSSSTSToken } from "./requet";
import { getAliOSSSTSToken } from "@/pages/setting/help/addedit/requet";
import "./index.less";
import "./HelpAddEditView.less";
const HelpAddEdit = () => {
const location = useLocation();
......
import React, { useEffect, useState } from "react";
import React, { useState } from "react";
import {
Table,
Input,
Button,
Row,
......@@ -13,26 +12,21 @@ import {
Image,
} from "antd";
const { RangePicker } = DatePicker;
import PaginationCom from "@/common/Pagination";
import { getList, delHelp } from "./requet";
import { delHelp } from "../api";
import { useNavigate } from "react-router";
import Add from "@/assets/images/icon/add.png";
import reload from "@/assets/images/icon/reload.png";
import reset from "@/assets/images/icon/reset.png";
import filter from "@/assets/images/icon/filter.png";
import dayjs from "dayjs";
import TableCom from "@/common/TableCom/index";
import { useSelector } from "react-redux";
import { AppList } from "@/shared/components/AppList";
import { useHelpList } from "../useHelpList";
const HelpTable = () => {
const navigate = useNavigate();
const [data, setData] = useState([]);
const [page_size, setpage_size] = useState(10);
const [page, setPage] = useState(1);
const [total, setTotal] = useState(0);
const [loading, setLoading] = useState(true);
const { rows, total, page, pageSize, loading, error, init, changePage, changePageSize } = useHelpList();
const [delModal, setDelModal] = useState(false);
const [delid, setdelid] = useState(0);
const [form] = Form.useForm();
// 获取操作权限
const { operationPermissionsList } = useSelector((state) => state.user);
const [filterObj, setFilterObj] = useState({
......@@ -51,7 +45,7 @@ const HelpTable = () => {
setDateVal("");
init();
init({});
};
// useEffect(() => {
......@@ -90,25 +84,9 @@ const HelpTable = () => {
// 删除
const handleDel = async (id) => {
const bool = await delHelp({ id: delid });
bool && init();
bool && init(filterObj);
setDelModal(false);
};
// 获取数据
const init = async (obj = {}) => {
setLoading(true);
let requestParams = { page, page_size, ...obj };
if (obj.start_time && obj.end_time) {
const start_time = parseInt(obj.start_time);
const end_time = parseInt(obj.end_time);
requestParams = { ...requestParams, start_time, end_time };
}
const { total, list } = await getList(requestParams);
console.log("init list", list);
setTotal(total);
setData(list);
setLoading(false);
};
const columns = [
{
title: "ID",
......@@ -237,8 +215,7 @@ const HelpTable = () => {
}
ghost
onClick={() => {
setPage(1);
Object.values(filterObj).some((item) => item) ? init(filterObj) : init();
Object.values(filterObj).some((item) => item) ? init(filterObj, 1) : init({}, 1);
}}
>
筛选
......@@ -259,7 +236,7 @@ const HelpTable = () => {
</span>
}
onClick={() =>
Object.values(filterObj).some((item) => item) ? init(filterObj) : init()
Object.values(filterObj).some((item) => item) ? init(filterObj) : init({})
}
>
刷新
......@@ -318,16 +295,18 @@ const HelpTable = () => {
问题将永久删除,是否继续?
</p>
</Modal>
{TableCom({ loading, data, columns })}
<br />
<PaginationCom
total={total}
init={init}
page={page}
page_size={page_size}
setPage={setPage}
setpage_size={setpage_size}
filterObj={filterObj}
<AppList
rowKey="id"
columns={columns}
data={{ rows, total, loading, error }}
pagination={{
page,
pageSize,
pageSizeOptions: [10, 20, 30, 40],
onChange: (nextPage) => changePage(nextPage, filterObj),
onPageSizeChange: (nextPageSize) => changePageSize(nextPageSize, filterObj),
}}
onRetry={() => init(filterObj)}
/>
</div>
);
......
......@@ -3,9 +3,7 @@ import { Navigate, useRoutes } from "react-router";
import ModuleBoundary from "@/app/ModuleBoundary";
const SettingsLayout = lazy(() => import("@/pages/setting/index"));
const HelpLayout = lazy(() => import("@/pages/setting/help/index"));
const HelpList = lazy(() => import("@/pages/setting/help/table"));
const HelpAddEdit = lazy(() => import("@/pages/setting/help/addedit/index"));
const HelpRoutes = lazy(() => import("./help/routes"));
const Applied = lazy(() => import("@/pages/setting/applied/index"));
const PersonalizedSetting = lazy(() => import("@/pages/setting/personalized-setting/index"));
const PointManagement = lazy(() => import("@/pages/setting/point-management/index"));
......@@ -20,15 +18,7 @@ export default function SettingsRoutes() {
Component: SettingsLayout,
children: [
{ index: true, element: <Navigate to="/setting/applied" /> },
{
path: "help",
Component: HelpLayout,
children: [
{ index: true, element: <Navigate to="/setting/help/list" /> },
{ path: "list", Component: HelpList },
{ path: "addedit", Component: HelpAddEdit },
],
},
{ path: "help/*", Component: HelpRoutes },
{ path: "applied", Component: Applied },
{ path: "personalized-setting", Component: PersonalizedSetting },
{ path: "point-management", Component: PointManagement },
......
.phone {
width: 300px;
height: 600px;
background: url("@/assets/images/phone.png");
background-size: 100% 100%;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
margin: auto;
z-index: 1111;
background-color: #fff;
}
.phone .close {
position: absolute;
right: 0;
top: 0;
font-size: 18px;
}
#help_content video {
max-width: 100%;
}
.scrollable-div {
margin: 35px 30px 0 30px;
padding-top: 10px;
padding-left: 0;
width: 240px;
height: 536px;
overflow: auto;
line-height: 28px;
}
.scrollable-div ol li,
.scrollable-div ul li {
padding-left: 40px;
}
.scrollable-div img,
.scrollable-div video {
max-width: 230px;
max-height: 240px;
height: auto;
width: auto;
display: block;
/* 保持图片在其容器内居中 */
margin: 0 auto;
}
.scrollable-div p {
line-height: 1.5;
font-size: 16px;
font-family: "宋体";
margin: 15px 0;
}
.scrollable-div p img {
width: 100% !important;
height: auto !important;
}
.scrollable-div .chapter-practice .chapter-practice-close {
display: none;
}
.scrollable-div pre {
white-space: pre-wrap;
word-break: break-all;
word-wrap: break-word;
line-height: 20px;
font-size: 14px;
padding: 10px;
color: #333;
background-color: #f5f2f0;
}
.scrollable-div blockquote {
padding: 10px;
line-height: 20px;
font-size: 14px;
background-color: #f5f2f0;
border-left: 5px solid #b4d5ff;
margin: 10px 0;
}
.scrollable-div a:link,
.scrollable-div a:visited,
.scrollable-div a:hover {
color: #2a9feb;
}
.scrollable-div h1 {
line-height: 40px;
font-size: 24px;
}
.scrollable-div h2 {
line-height: 34px;
font-size: 20px;
}
.scrollable-div h3 {
line-height: 28px;
font-size: 18px;
}
.scrollable-div h4 {
line-height: 22px;
font-size: 16px;
}
.scrollable-div h5 {
line-height: 18px;
font-size: 14px;
}
.scrollable-div h6 {
line-height: 16px;
font-size: 12px;
}
.scrollable-div video,
.scrollable-div audio {
width: 100%;
}
.scrollable-div .chapter-image-pic img {
width: 100%;
height: auto;
}
.scrollable-div .w-e-image-container img {
width: 100%;
}
.scrollable-div table {
border-collapse: collapse;
display: table;
min-width: 240px;
width: auto !important;
}
.scrollable-div table tr:first-child th {
background-color: #f5f2f0;
border-right: 2px solid #cccccc;
}
.scrollable-div tr {
height: 30px;
}
.scrollable-div li {
margin-left: -30px;
list-style-position: inside;
/* 列表项符号在内容内部 */
}
.scrollable-div table,
.scrollable-div th,
.scrollable-div td {
border: 1px solid #cccccc;
}
.scrollable-div::-webkit-scrollbar {
width: 0px;
}
.scrollable-div::-webkit-scrollbar-thumb {
background-color: #2d2d2d;
border-radius: 40px;
}
Markdown 格式
0% 或
您添加了 0 人 到此讨论。请谨慎行事。
请先完成此评论的编辑!
请 注册 或者 后发表评论