🐛 fix(模块): 修复了一些 bug
This commit is contained in:
parent
6a7a8985ce
commit
271a4ad751
116
config/config.ts
116
config/config.ts
@ -1,127 +1,17 @@
|
|||||||
// import { defineConfig } from "umi";
|
// import { defineConfig } from "umi";
|
||||||
import proxy from './proxy';
|
import proxy from './proxy';
|
||||||
|
import router from './router'
|
||||||
|
|
||||||
//不使用defineConfig则能在其他地方获取这些配置
|
//不使用defineConfig则能在其他地方获取这些配置
|
||||||
export default {
|
export default {
|
||||||
plugins: [
|
plugins: [
|
||||||
'@umijs/plugins/dist/dva'
|
'@umijs/plugins/dist/dva'
|
||||||
],
|
],
|
||||||
// proxy,
|
proxy,
|
||||||
dva: {},
|
dva: {},
|
||||||
title: 'UMI4 Admin',
|
title: 'UMI4 Admin',
|
||||||
favicons: [
|
favicons: [
|
||||||
'/favicon.svg'
|
'/favicon.svg'
|
||||||
],
|
],
|
||||||
routes: [
|
routes: router
|
||||||
{
|
|
||||||
path: '/',
|
|
||||||
component: '@/layouts/index',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
key: '2',
|
|
||||||
name: '关于',
|
|
||||||
path: '/about',
|
|
||||||
redirect: '',
|
|
||||||
routes: [
|
|
||||||
{
|
|
||||||
id: 21,
|
|
||||||
key: '2-1',
|
|
||||||
name: '关于你',
|
|
||||||
path: '/about/u',
|
|
||||||
redirect: '',
|
|
||||||
pid: 2,
|
|
||||||
routes: [
|
|
||||||
{
|
|
||||||
id: 211,
|
|
||||||
key: '2-1-1',
|
|
||||||
name: '关于你1',
|
|
||||||
path: '/about/u/index',
|
|
||||||
component: "@/pages/about/u/index",
|
|
||||||
redirect: '',
|
|
||||||
pid: 21
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 212,
|
|
||||||
key: '2-1-2',
|
|
||||||
name: '关于你2',
|
|
||||||
path: '/about/u/2',
|
|
||||||
component: "@/pages/about/u/$id",
|
|
||||||
redirect: '',
|
|
||||||
pid: 21
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 22,
|
|
||||||
key: '2-2',
|
|
||||||
path: '/about/m',
|
|
||||||
redirect: '',
|
|
||||||
name: '(页面元素权限)关于我',
|
|
||||||
component: "@/pages/about/m",
|
|
||||||
pid: 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 23,
|
|
||||||
key: '2-3',
|
|
||||||
path: '/about/um',
|
|
||||||
redirect: '',
|
|
||||||
name: '关于你和我',
|
|
||||||
component: "@/pages/about/um",
|
|
||||||
pid: 2
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
key: '3',
|
|
||||||
name: '教师',
|
|
||||||
path: '/teacher',
|
|
||||||
redirect: '',
|
|
||||||
routes: [
|
|
||||||
{
|
|
||||||
id: 31,
|
|
||||||
key: '3-1',
|
|
||||||
path: '/teacher/u',
|
|
||||||
redirect: '',
|
|
||||||
name: '(403)关于你教师',
|
|
||||||
component: "@/pages/teacher/u",
|
|
||||||
pid: 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 32,
|
|
||||||
key: '3-2',
|
|
||||||
path: '/teacher/m',
|
|
||||||
redirect: '',
|
|
||||||
name: '关于我教师',
|
|
||||||
component: "@/pages/teacher/m",
|
|
||||||
pid: 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 33,
|
|
||||||
key: '3-3',
|
|
||||||
path: '/teacher/um',
|
|
||||||
redirect: '',
|
|
||||||
name: '关于你和我教师',
|
|
||||||
component: "@/pages/teacher/um",
|
|
||||||
pid: 3
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
key: '4',
|
|
||||||
name: '(404)学生',
|
|
||||||
path: '/student',
|
|
||||||
redirect: '',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
key: '5',
|
|
||||||
path: '/user/login',
|
|
||||||
redirect: '',
|
|
||||||
name: '登录',
|
|
||||||
component: "@/pages/user/login",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,8 +1,15 @@
|
|||||||
const proxy = {
|
const proxy = {
|
||||||
'/api': {
|
'/auth': {
|
||||||
target: 'http://10.104.1.38:3000',
|
target: 'http://home.robot-z.cn:7001',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
pathRewrite: { '^/api': '' },
|
secure: false,
|
||||||
|
pathRewrite: { '^/auth': '' },
|
||||||
|
onProxyRes: function(proxyRes) {
|
||||||
|
proxyRes.headers['Access-Control-Allow-Origin'] = '*';
|
||||||
|
proxyRes.headers['Access-Control-Allow-Methods'] = 'GET,PUT,POST,DELETE,OPTIONS';
|
||||||
|
proxyRes.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization';
|
||||||
|
proxyRes.headers['Access-Control-Allow-Credentials'] = 'true';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
50
config/router.ts
Normal file
50
config/router.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
// 路由配置文件
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
path: '/user',
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
path: '/user/login',
|
||||||
|
redirect: '',
|
||||||
|
name: '登录',
|
||||||
|
component: "@/pages/user/login",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
path: '/standard/index',
|
||||||
|
redirect: '',
|
||||||
|
name: '生成标准页面',
|
||||||
|
component: "@/pages/standard/index",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/examine',
|
||||||
|
redirect: '',
|
||||||
|
name: '走动式管理',
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
path: '/examine/index',
|
||||||
|
name: '考评分类管理',
|
||||||
|
component: "@/pages/examine/index",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/examine/question',
|
||||||
|
name: '考核问题管理',
|
||||||
|
component: "@/pages/examine/question",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/examine/modal',
|
||||||
|
name: '考核模版管理',
|
||||||
|
component: "@/pages/examine/modal",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
@ -1,3 +1,11 @@
|
|||||||
|
/*
|
||||||
|
* @Author: cclu 1106109051@qq.com
|
||||||
|
* @Date: 2025-02-25 11:39:58
|
||||||
|
* @LastEditors: cclu 1106109051@qq.com
|
||||||
|
* @LastEditTime: 2025-03-10 15:30:28
|
||||||
|
* @FilePath: \umi4-admin-main\src\components\PageAccess.tsx
|
||||||
|
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
||||||
|
*/
|
||||||
import type { FC, ReactElement } from 'react';
|
import type { FC, ReactElement } from 'react';
|
||||||
import { connect, history, useLocation } from 'umi';
|
import { connect, history, useLocation } from 'umi';
|
||||||
import { Button, Result } from 'antd';
|
import { Button, Result } from 'antd';
|
||||||
@ -17,6 +25,9 @@ const PageAccess: FC<Props> = (props): ReactElement | null => {
|
|||||||
//当遇到输入的是菜单组件中可展开的节点的path的时候就没有权限了, 此时可能会报错,
|
//当遇到输入的是菜单组件中可展开的节点的path的时候就没有权限了, 此时可能会报错,
|
||||||
//加可选操作符可避免这个报错导致的页面渲染问题
|
//加可选操作符可避免这个报错导致的页面渲染问题
|
||||||
const accessible = authority[pathname]?.some((item: string) => userAuthority.includes(item));
|
const accessible = authority[pathname]?.some((item: string) => userAuthority.includes(item));
|
||||||
|
console.log('authority', authority);
|
||||||
|
console.log('userAuthority', userAuthority);
|
||||||
|
console.log('children', children);
|
||||||
|
|
||||||
let res = children;
|
let res = children;
|
||||||
|
|
||||||
|
|||||||
@ -41,6 +41,47 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.pageLayout {
|
||||||
|
:global {
|
||||||
|
.ant-pro-menu-item {
|
||||||
|
&.ant-menu-item-selected {
|
||||||
|
background-color: #1890ff !important;
|
||||||
|
|
||||||
|
.ant-pro-menu-item-title {
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #1890ff !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-menu-item-selected {
|
||||||
|
background-color: #1890ff !important;
|
||||||
|
color: #fff !important;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #1890ff !important;
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-menu-submenu-selected > .ant-menu-submenu-title {
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-menu-item {
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(24, 144, 255, 0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.ant-pro-layout-container{
|
.ant-pro-layout-container{
|
||||||
background-color: #f0f2f5;
|
background-color: #f0f2f5;
|
||||||
|
|||||||
@ -1,3 +1,11 @@
|
|||||||
|
/*
|
||||||
|
* @Author: cclu 1106109051@qq.com
|
||||||
|
* @Date: 2025-02-27 15:55:46
|
||||||
|
* @LastEditors: cclu 1106109051@qq.com
|
||||||
|
* @LastEditTime: 2025-03-10 17:46:55
|
||||||
|
* @FilePath: \umi4-admin-main\src\layouts\index.tsx
|
||||||
|
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
||||||
|
*/
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { Dropdown, Layout, Menu, Tabs, Tooltip } from 'antd';
|
import { Dropdown, Layout, Menu, Tabs, Tooltip } from 'antd';
|
||||||
@ -9,7 +17,6 @@ import LayoutWrapper from '@/components/LayoutWrapper';
|
|||||||
import Nav from '@/components/Nav';
|
import Nav from '@/components/Nav';
|
||||||
import Page404 from '@/pages/404';
|
import Page404 from '@/pages/404';
|
||||||
import handleRecursiveNestedData from '@/utils/handleRecursiveNestedData';
|
import handleRecursiveNestedData from '@/utils/handleRecursiveNestedData';
|
||||||
import handleGetCurrentLocation from '@/utils/handleGetCurrentLocation';
|
|
||||||
import { MenuDataItem, ProLayout } from '@ant-design/pro-components';
|
import { MenuDataItem, ProLayout } from '@ant-design/pro-components';
|
||||||
import './index.less'
|
import './index.less'
|
||||||
import logo from '../assets/logo.svg';
|
import logo from '../assets/logo.svg';
|
||||||
@ -41,10 +48,6 @@ const handleGetOpenKeys = (currentLocation: API.MenuItem[] | []): string[] => {
|
|||||||
for (let i = 0; i < currentLocation.length - 1; i++) {
|
for (let i = 0; i < currentLocation.length - 1; i++) {
|
||||||
res.push(`${currentLocation[i].key}`);
|
res.push(`${currentLocation[i].key}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('res', res);
|
|
||||||
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -66,8 +69,8 @@ const BasicLayout: FC<{ user: UserModelState, global: ProfileModelState, dispatc
|
|||||||
|
|
||||||
console.log('props', props);
|
console.log('props', props);
|
||||||
console.log('pathname', pathname);
|
console.log('pathname', pathname);
|
||||||
|
console.log('indexValidMenuItemByPath', indexValidMenuItemByPath);
|
||||||
const validMenuItem = indexValidMenuItemByPath[pathname];
|
const validMenuItem = indexValidMenuItemByPath[pathname];
|
||||||
console.log('validMenuItem', validMenuItem);
|
|
||||||
// const selectedKeys = validMenuItem?.key;
|
// const selectedKeys = validMenuItem?.key;
|
||||||
const [activeKey, setActiveKey] = useState<string>(validMenuItem?.path || '/')
|
const [activeKey, setActiveKey] = useState<string>(validMenuItem?.path || '/')
|
||||||
|
|
||||||
@ -81,7 +84,6 @@ const BasicLayout: FC<{ user: UserModelState, global: ProfileModelState, dispatc
|
|||||||
//点击有子菜单的父菜单的回调
|
//点击有子菜单的父菜单的回调
|
||||||
// const onOpenChange: MenuProps['onOpenChange'] = (keys) => {
|
// const onOpenChange: MenuProps['onOpenChange'] = (keys) => {
|
||||||
// setOpenKeys(keys)
|
// setOpenKeys(keys)
|
||||||
// console.log('keys', keys);
|
|
||||||
// dispatch({
|
// dispatch({
|
||||||
// namespace: "global/setProfileData",
|
// namespace: "global/setProfileData",
|
||||||
// payload: {
|
// payload: {
|
||||||
@ -101,7 +103,8 @@ const BasicLayout: FC<{ user: UserModelState, global: ProfileModelState, dispatc
|
|||||||
? (
|
? (
|
||||||
<Link
|
<Link
|
||||||
to={item.path}
|
to={item.path}
|
||||||
style={{ color: 'inherit' }}
|
style={{ color: pathname === item.path ? '#1890ff' : 'inherit' }}
|
||||||
|
className={pathname === item.path ? 'ant-menu-item-selected' : ''}
|
||||||
>{item.name}</Link>
|
>{item.name}</Link>
|
||||||
)
|
)
|
||||||
: item.name,
|
: item.name,
|
||||||
@ -167,68 +170,35 @@ const BasicLayout: FC<{ user: UserModelState, global: ProfileModelState, dispatc
|
|||||||
SYSTEMMODULE_DESC: "",
|
SYSTEMMODULE_DESC: "",
|
||||||
guid: "1",
|
guid: "1",
|
||||||
hideInMenu: false,
|
hideInMenu: false,
|
||||||
name: "首页",
|
name: "生成标准页面",
|
||||||
path: "/",
|
path: "/standard/index",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SYSTEMMODULE_DESC: "",
|
SYSTEMMODULE_DESC: "",
|
||||||
guid: "2",
|
guid: "2",
|
||||||
hideInMenu: false,
|
hideInMenu: false,
|
||||||
name: "关于你1",
|
name: "考评分类管理",
|
||||||
path: "/about/u/index",
|
path: "/examine/index",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SYSTEMMODULE_DESC: "",
|
SYSTEMMODULE_DESC: "",
|
||||||
guid: "3",
|
guid: "3",
|
||||||
hideInMenu: false,
|
hideInMenu: false,
|
||||||
name: "关于你2",
|
name: "考核问题管理",
|
||||||
path: "/about/u/2",
|
path: "/examine/question",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SYSTEMMODULE_DESC: "",
|
SYSTEMMODULE_DESC: "",
|
||||||
guid: "4",
|
guid: "4",
|
||||||
hideInMenu: false,
|
hideInMenu: false,
|
||||||
name: "(页面元素权限)关于我",
|
name: "考核模版管理",
|
||||||
path: "/about/m",
|
path: "/examine/modal",
|
||||||
},
|
|
||||||
{
|
|
||||||
SYSTEMMODULE_DESC: "",
|
|
||||||
guid: "5",
|
|
||||||
hideInMenu: false,
|
|
||||||
name: "关于你和我",
|
|
||||||
path: "/about/um",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
SYSTEMMODULE_DESC: "",
|
|
||||||
guid: "5",
|
|
||||||
hideInMenu: false,
|
|
||||||
name: "(403)关于你教师",
|
|
||||||
path: "/teacher/u",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
SYSTEMMODULE_DESC: "",
|
|
||||||
guid: "6",
|
|
||||||
hideInMenu: false,
|
|
||||||
name: "关于我教师",
|
|
||||||
path: "/teacher/m",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
SYSTEMMODULE_DESC: "",
|
|
||||||
guid: "7",
|
|
||||||
hideInMenu: false,
|
|
||||||
name: "关于你和我教师",
|
|
||||||
path: "/teacher/um",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
SYSTEMMODULE_DESC: "",
|
|
||||||
guid: "8",
|
|
||||||
hideInMenu: false,
|
|
||||||
name: "(404)学生",
|
|
||||||
path: "/student",
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
console.log('tabsRoutes', tabsRoutes);
|
console.log('tabsRoutes', tabsRoutes);
|
||||||
|
console.log('location', location);
|
||||||
|
console.log('consumableMenu', consumableMenu);
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -247,10 +217,17 @@ const BasicLayout: FC<{ user: UserModelState, global: ProfileModelState, dispatc
|
|||||||
location={location}
|
location={location}
|
||||||
style={{ minHeight: '100vh' }}
|
style={{ minHeight: '100vh' }}
|
||||||
siderWidth={208}
|
siderWidth={208}
|
||||||
menuDataRender={() =>
|
selectedKeys={[pathname]}
|
||||||
consumableMenu
|
defaultSelectedKeys={[pathname]}
|
||||||
// menu
|
menuDataRender={() => consumableMenu}
|
||||||
}
|
menuItemRender={(menuItemProps, defaultDom) => {
|
||||||
|
if (menuItemProps.isUrl || !menuItemProps.path) {
|
||||||
|
return defaultDom;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Link to={menuItemProps.path}>{defaultDom}</Link>
|
||||||
|
);
|
||||||
|
}}
|
||||||
subMenuItemRender={(menuItemProps) => {
|
subMenuItemRender={(menuItemProps) => {
|
||||||
if (menuItemProps.icon && typeof menuItemProps.icon === 'string') {
|
if (menuItemProps.icon && typeof menuItemProps.icon === 'string') {
|
||||||
const ele = React.createElement(Icon[menuItemProps.icon])
|
const ele = React.createElement(Icon[menuItemProps.icon])
|
||||||
@ -288,12 +265,11 @@ const BasicLayout: FC<{ user: UserModelState, global: ProfileModelState, dispatc
|
|||||||
}}
|
}}
|
||||||
actionsRender={() => <nav />}
|
actionsRender={() => <nav />}
|
||||||
onPageChange={(location) => {
|
onPageChange={(location) => {
|
||||||
console.log('location------', location);
|
console.log('location', location);
|
||||||
|
|
||||||
if (location?.pathname && location?.pathname !== '/') {
|
if (location?.pathname && location?.pathname !== '/') {
|
||||||
console.log('oneFloorList', oneFloorList);
|
|
||||||
|
|
||||||
const nextModule: any = oneFloorList.filter(n => location?.pathname === n?.path)
|
const nextModule: any = oneFloorList.filter(n => location?.pathname === n?.path)
|
||||||
console.log('nextModule', nextModule);
|
|
||||||
let title = ''
|
let title = ''
|
||||||
if (nextModule && nextModule.length > 0) {
|
if (nextModule && nextModule.length > 0) {
|
||||||
title = nextModule[0].name
|
title = nextModule[0].name
|
||||||
@ -312,8 +288,8 @@ const BasicLayout: FC<{ user: UserModelState, global: ProfileModelState, dispatc
|
|||||||
hideAdd
|
hideAdd
|
||||||
type="editable-card"
|
type="editable-card"
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
// history.push(value)
|
history.push(value)
|
||||||
// setActiveKey(value)
|
setActiveKey(value)
|
||||||
}}
|
}}
|
||||||
activeKey={activeKey}
|
activeKey={activeKey}
|
||||||
onEdit={handleEdit}
|
onEdit={handleEdit}
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import handleRedirect from '@/utils/handleRedirect';
|
|||||||
import handleGetRootSubmenuKeys from '@/utils/handleGetRootSubmenuKeys';
|
import handleGetRootSubmenuKeys from '@/utils/handleGetRootSubmenuKeys';
|
||||||
import handleGetEachDatumFromNestedDataByKey from '@/utils/handleGetEachDatumFromNestedDataByKey';
|
import handleGetEachDatumFromNestedDataByKey from '@/utils/handleGetEachDatumFromNestedDataByKey';
|
||||||
import handleGetIndexValidMenuItemByPath from '@/utils/handleGetIndexValidMenuItemByPath';
|
import handleGetIndexValidMenuItemByPath from '@/utils/handleGetIndexValidMenuItemByPath';
|
||||||
|
import { notification } from 'antd';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 全局用户数据
|
* 全局用户数据
|
||||||
@ -69,40 +70,16 @@ const UserModel: UserModelType = {
|
|||||||
loginBtnLoading: false,
|
loginBtnLoading: false,
|
||||||
layoutWrapperLoading: true,
|
layoutWrapperLoading: true,
|
||||||
menu: [
|
menu: [
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
key: '1',
|
|
||||||
path: '/',
|
|
||||||
label: '首页',
|
|
||||||
redirect: '',
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
indexAllMenuItemById: {
|
indexAllMenuItemById: {
|
||||||
1: {
|
|
||||||
id: 1,
|
|
||||||
key: '1',
|
|
||||||
path: '/',
|
|
||||||
label: '首页',
|
|
||||||
redirect: '',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
indexAllMenuItemByPath: {
|
indexAllMenuItemByPath: {
|
||||||
'/': {
|
|
||||||
id: 1,
|
|
||||||
key: '1',
|
|
||||||
path: '/',
|
|
||||||
label: '首页',
|
|
||||||
redirect: '',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
indexValidMenuItemByPath: {
|
indexValidMenuItemByPath: {
|
||||||
'/': {
|
|
||||||
id: 1,
|
|
||||||
key: '1',
|
|
||||||
path: '/',
|
|
||||||
label: '首页',
|
|
||||||
redirect: '',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
effects: {
|
effects: {
|
||||||
@ -128,9 +105,10 @@ const UserModel: UserModelType = {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const res: API.LoginResponse = yield call(userLogin, payload);
|
const res: API.LoginResponse = yield call(userLogin, payload);
|
||||||
|
console.log('res', res);
|
||||||
|
|
||||||
if (!res.code) {
|
if (res.code === 200) {
|
||||||
localStorage.setItem('Authorization', res.data.token);
|
localStorage.setItem('Authorization', res.data.accessToken);
|
||||||
|
|
||||||
yield put({
|
yield put({
|
||||||
type: 'getUserInfoAuthorityMenu',
|
type: 'getUserInfoAuthorityMenu',
|
||||||
@ -146,7 +124,7 @@ const UserModel: UserModelType = {
|
|||||||
loginBtnLoading: false,
|
loginBtnLoading: false,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return res;
|
return { code: res.code, message: res.message };
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
yield put({
|
yield put({
|
||||||
@ -155,7 +133,7 @@ const UserModel: UserModelType = {
|
|||||||
loginBtnLoading: false,
|
loginBtnLoading: false,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return { code: 1, message: '登录失败,请稍后重试' };
|
return { code: 1, message: error?.message || '登录失败,请稍后重试' };
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
//获取用户信息和权限以及菜单
|
//获取用户信息和权限以及菜单
|
||||||
@ -193,13 +171,15 @@ const UserModel: UserModelType = {
|
|||||||
code: 0,
|
code: 0,
|
||||||
message: '',
|
message: '',
|
||||||
};
|
};
|
||||||
|
console.log('type', type);
|
||||||
|
|
||||||
//用户在登录页登录完成之后执行
|
//用户在登录页登录完成之后执行
|
||||||
if (type === 'concurrent') {
|
if (type === 'concurrent') {
|
||||||
const res: API.UserInfoAuthMenuResponse = yield call(retrieveUserInfoAuthorityMenu);
|
const res: API.UserInfoAuthMenuResponse = yield call(retrieveUserInfoAuthorityMenu);
|
||||||
|
console.log('res', res);
|
||||||
userInfoRes = res[0] as API.UserInfoResponse;
|
userInfoRes = res[0] as API.UserInfoResponse;
|
||||||
userAuthorityRes = res[1] as API.UserAuthorityResponse;
|
// userAuthorityRes = res[1] as API.UserAuthorityResponse;
|
||||||
menuRes = res[2] as API.MenuDataResponse;
|
menuRes = res[1] as API.MenuDataResponse;
|
||||||
} else {
|
} else {
|
||||||
//其他情形首先查询用户的登录状态, 未登录则不继续操作
|
//其他情形首先查询用户的登录状态, 未登录则不继续操作
|
||||||
try {
|
try {
|
||||||
@ -224,15 +204,47 @@ const UserModel: UserModelType = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const res: API.UserAuthMenuResponse = yield call(retrieveUserAuthorityMenu);
|
const res: API.UserAuthMenuResponse = yield call(retrieveUserAuthorityMenu);
|
||||||
userAuthorityRes = res[0] as API.UserAuthorityResponse;
|
// userAuthorityRes = res[0] as API.UserAuthorityResponse;
|
||||||
menuRes = res[1] as API.MenuDataResponse;
|
menuRes = res[0] as API.MenuDataResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
const indexAllMenuItemByPath = handleGetEachDatumFromNestedDataByKey(menuRes.data, 'path');
|
console.log('userInfoRes', userInfoRes);
|
||||||
const indexValidMenuItemByPath = handleGetIndexValidMenuItemByPath(menuRes.data);
|
|
||||||
|
|
||||||
console.log('indexValidMenuItemByPath', indexValidMenuItemByPath);
|
|
||||||
|
|
||||||
|
menuRes.data = [{
|
||||||
|
path: '/standard/index',
|
||||||
|
redirect: '',
|
||||||
|
name: '生成标准页面',
|
||||||
|
component: "@/pages/standard/index",
|
||||||
|
}, {
|
||||||
|
path: '/examine',
|
||||||
|
redirect: '',
|
||||||
|
name: '走动式管理',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '/examine/index',
|
||||||
|
name: '考评分类管理',
|
||||||
|
component: "@/pages/examine/index",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/examine/question',
|
||||||
|
name: '考核问题管理',
|
||||||
|
component: "@/pages/examine/question",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/examine/modal',
|
||||||
|
name: '考核模版管理',
|
||||||
|
component: "@/pages/examine/modal",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
},]
|
||||||
|
let indexAllMenuItemByPath: any = []
|
||||||
|
let indexValidMenuItemByPath: any = []
|
||||||
|
if (menuRes.data && menuRes.data.length > 0) {
|
||||||
|
indexAllMenuItemByPath = handleGetEachDatumFromNestedDataByKey(menuRes.data, 'path');
|
||||||
|
indexValidMenuItemByPath = handleGetIndexValidMenuItemByPath(menuRes.data);
|
||||||
|
}
|
||||||
|
|
||||||
//在登录完获取菜单数据之后做是否需要重定向的操作
|
//在登录完获取菜单数据之后做是否需要重定向的操作
|
||||||
yield call(
|
yield call(
|
||||||
@ -241,7 +253,6 @@ const UserModel: UserModelType = {
|
|||||||
indexAllMenuItemByPath,
|
indexAllMenuItemByPath,
|
||||||
indexValidMenuItemByPath,
|
indexValidMenuItemByPath,
|
||||||
);
|
);
|
||||||
|
|
||||||
yield put({
|
yield put({
|
||||||
type: 'save',
|
type: 'save',
|
||||||
payload: {
|
payload: {
|
||||||
@ -252,27 +263,32 @@ const UserModel: UserModelType = {
|
|||||||
indexAllMenuItemByPath,
|
indexAllMenuItemByPath,
|
||||||
indexValidMenuItemByPath,
|
indexValidMenuItemByPath,
|
||||||
layoutWrapperLoading: false,
|
layoutWrapperLoading: false,
|
||||||
authority: userAuthorityRes.data.authority,
|
// authority: userAuthorityRes.data.authority,
|
||||||
|
authority: [
|
||||||
|
'/standard/index',
|
||||||
|
'/examine/index',
|
||||||
|
'/examine/modal',
|
||||||
|
'/examine/question',
|
||||||
|
],
|
||||||
rootSubmenuKeys: handleGetRootSubmenuKeys(menuRes.data),
|
rootSubmenuKeys: handleGetRootSubmenuKeys(menuRes.data),
|
||||||
indexAllMenuItemById: handleGetEachDatumFromNestedDataByKey(menuRes.data, 'id'),
|
indexAllMenuItemById: handleGetEachDatumFromNestedDataByKey(menuRes.data, 'id'),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
//为保证所有语句都return, 因此这里加一句这个
|
//为保证所有语句都return, 因此这里加一句这个
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
//登出
|
//登出
|
||||||
*logout({ payload }, { call, put }) {
|
* logout({ payload }, { call, put }) {
|
||||||
const res: API.LogoutResponse = yield call(userLogout, payload);
|
const res: API.LogoutResponse = yield call(userLogout, payload);
|
||||||
|
console.log('res', res)
|
||||||
if (!res.code) {
|
if (res.code === 200) {
|
||||||
yield put({
|
yield put({
|
||||||
type: 'resetLoginStatus',
|
type: 'resetLoginStatus',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
//重置登录状态
|
//重置登录状态
|
||||||
*resetLoginStatus(_, { put }) {
|
* resetLoginStatus(_, { put }) {
|
||||||
localStorage.removeItem('Authorization');
|
localStorage.removeItem('Authorization');
|
||||||
|
|
||||||
yield put({
|
yield put({
|
||||||
|
|||||||
@ -1,12 +0,0 @@
|
|||||||
import type { FC } from 'react';
|
|
||||||
|
|
||||||
const Index: FC = () => {
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<div>/about</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Index;
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
const authority: Authority = {
|
|
||||||
aboutMUpdate: '/about/m/update',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default authority;
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
import type { FC } from 'react';
|
|
||||||
import Access from '@/components/Access';
|
|
||||||
import authority from './authority';
|
|
||||||
|
|
||||||
const { aboutMUpdate } = authority;
|
|
||||||
|
|
||||||
const Index: FC = () => {
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<div>/about/m</div>
|
|
||||||
<Access
|
|
||||||
authority={aboutMUpdate}
|
|
||||||
fallback={
|
|
||||||
<div>冇权限显示/操作页面内的元素</div>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div>有权限显示/操作页面内的元素</div>
|
|
||||||
</Access>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Index;
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
import { useParams } from 'umi';
|
|
||||||
|
|
||||||
const Index = () => {
|
|
||||||
|
|
||||||
const params = useParams();
|
|
||||||
|
|
||||||
console.log(params);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>{`动态路由: /about/u/${params.id}`}</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Index;
|
|
||||||
@ -1,582 +0,0 @@
|
|||||||
import { connect } from "umi";
|
|
||||||
import { MouseEvent, useRef, useState } from "react";
|
|
||||||
import type { FormInstance } from "antd";
|
|
||||||
import { Button, message, Spin } from "antd";
|
|
||||||
import type { ActionType } from "@ant-design/pro-table";
|
|
||||||
import ProTable from "@ant-design/pro-table";
|
|
||||||
import * as XLSX from 'xlsx'; // 读写数据的核心工具(无需写样式时可用)
|
|
||||||
import XLSXStyle from 'xlsx-style-fixed';
|
|
||||||
import moment from "moment";
|
|
||||||
import { handleFormatNumber } from "@/utils/publicMethods";
|
|
||||||
import LeftSelectTree from "@/components/leftSelectTree";
|
|
||||||
import { UserConnectedProps } from "@/models/user";
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const saleRankReport = (props: any) => {
|
|
||||||
const { currentUser } = props
|
|
||||||
const downloadBtnRef = useRef<any>()
|
|
||||||
const actionRef = useRef<ActionType>();
|
|
||||||
const formRef = useRef<FormInstance>();
|
|
||||||
const [reqDetailList, setReqDetailList] = useState<any>([{
|
|
||||||
SPREGIONTYPE_NAME: "1",
|
|
||||||
SERVERPART_NAME: "1",
|
|
||||||
MERCHANTS_NAME: "1",
|
|
||||||
SERVERPARTSHOP_NAME: "1",
|
|
||||||
IndexStr: "1",
|
|
||||||
COMPACT_STARTDATECOMPACT_ENDDATE: "1",
|
|
||||||
RENTFEE: "1",
|
|
||||||
GUARANTEERATIO: "1",
|
|
||||||
CASHPAY_AMOUNT: "1",
|
|
||||||
MOBILEPAY_AMOUNT: "1",
|
|
||||||
REVENUEDAILY_AMOUNTTotal: "1",
|
|
||||||
GUARANTEERATIOAMOUNT: "1",
|
|
||||||
BANKACCOUNT_AMOUNT: "1",
|
|
||||||
RECEIVABLEAMOUNT: "1",
|
|
||||||
SHOPEXPENSE_AMOUNT: "1",
|
|
||||||
PAID_AMOUNT: "1",
|
|
||||||
REFUND_SUPPLEMENT: "1",
|
|
||||||
STATISTICS_MONTH: "1",
|
|
||||||
settlementStateObjApprovalstate: "1",
|
|
||||||
REFUND_SUPPLEMENTdesc: "1",
|
|
||||||
}]); // 合计项数据源
|
|
||||||
const [printOut, setPrintOut] = useState<any>(); // 打印数据的内容
|
|
||||||
const [collapsible, setCollapsible] = useState<boolean>(false)
|
|
||||||
const [treeView, setTreeView] = useState<any>()
|
|
||||||
const [printIndex, setPrintIndex] = useState<number>(new Date().getTime())
|
|
||||||
|
|
||||||
|
|
||||||
// 树相关的属性和方法
|
|
||||||
const [selectedId, setSelectedId] = useState<string>()
|
|
||||||
// 导出的加载效果
|
|
||||||
const [showLoading, setShowLoading] = useState<boolean>(false)
|
|
||||||
// 是否显示打印的表格
|
|
||||||
const [showExportTable, setShowExportTable] = useState<boolean>(false)
|
|
||||||
// 查询的条件
|
|
||||||
const [searchParams, setSearchParams] = useState<any>()
|
|
||||||
|
|
||||||
const columns: any = [
|
|
||||||
{
|
|
||||||
title: '统计日期',
|
|
||||||
dataIndex: 'StatisticsYear',
|
|
||||||
valueType: "date",
|
|
||||||
hideInTable: true,
|
|
||||||
hideInDescriptions: true,
|
|
||||||
initialValue: moment().subtract('1', 'month'),
|
|
||||||
|
|
||||||
fieldProps: {
|
|
||||||
picker: "year",
|
|
||||||
format: 'YYYY'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "结算状态",
|
|
||||||
dataIndex: 'SettlementState',
|
|
||||||
valueType: 'select',
|
|
||||||
hideInTable: true,
|
|
||||||
valueEnum: {
|
|
||||||
"9": "已结算",
|
|
||||||
"0": "待结算",
|
|
||||||
"-1": "提前退场",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: <div style={{ textAlign: 'center' }}>管理中心</div>,
|
|
||||||
titleStr: '管理中心',
|
|
||||||
dataIndex: 'SPREGIONTYPE_NAME',
|
|
||||||
width: 200,
|
|
||||||
hideInSearch: true,
|
|
||||||
ellipsis: true,
|
|
||||||
align: 'center'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: <div style={{ textAlign: 'center' }}>服务区</div>,
|
|
||||||
titleStr: '服务区',
|
|
||||||
dataIndex: 'SERVERPART_NAME',
|
|
||||||
width: 200,
|
|
||||||
hideInSearch: true,
|
|
||||||
ellipsis: true,
|
|
||||||
align: 'center'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: <div style={{ textAlign: 'center' }}>经营商户</div>,
|
|
||||||
titleStr: '经营商户',
|
|
||||||
dataIndex: 'MERCHANTS_NAME',
|
|
||||||
width: 200,
|
|
||||||
hideInSearch: true,
|
|
||||||
ellipsis: true,
|
|
||||||
align: 'center'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: <div style={{ textAlign: 'center' }}>门店</div>,
|
|
||||||
titleStr: '门店',
|
|
||||||
dataIndex: 'SERVERPARTSHOP_NAME',
|
|
||||||
width: 150,
|
|
||||||
hideInSearch: true,
|
|
||||||
ellipsis: true,
|
|
||||||
align: 'center',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: <div style={{ textAlign: 'center' }}>基础信息</div>,
|
|
||||||
dataIndex: 'termInfo',
|
|
||||||
titleStr: '基础信息',
|
|
||||||
// fixed: 'left',
|
|
||||||
hideInSearch: true,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
title: <div style={{ textAlign: 'center' }}>期数</div>,
|
|
||||||
titleStr: '期数',
|
|
||||||
dataIndex: 'IndexStr',
|
|
||||||
width: 100,
|
|
||||||
align: 'center',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: <div style={{ textAlign: 'center' }}>时限</div>,
|
|
||||||
titleStr: '时限',
|
|
||||||
dataIndex: 'COMPACT_STARTDATECOMPACT_ENDDATE',
|
|
||||||
width: 180,
|
|
||||||
align: 'center',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: <div style={{ textAlign: 'center' }}>保底/固定租金</div>,
|
|
||||||
titleStr: '保底/固定租金',
|
|
||||||
exportType: "momeny",
|
|
||||||
align: 'right',
|
|
||||||
width: 140,
|
|
||||||
valueType: 'digit',
|
|
||||||
dataIndex: 'RENTFEE',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: <div style={{ textAlign: 'center' }}>提成比率</div>,
|
|
||||||
titleStr: '提成比率',
|
|
||||||
exportType: "rate",
|
|
||||||
dataIndex: 'GUARANTEERATIO',
|
|
||||||
align: 'center',
|
|
||||||
width: 120,
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: <div style={{ textAlign: 'center' }}>营业额</div>,
|
|
||||||
titleStr: '营业额',
|
|
||||||
dataIndex: '',
|
|
||||||
hideInSearch: true,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
title: <div style={{ textAlign: 'center' }}>现金</div>,
|
|
||||||
titleStr: '现金',
|
|
||||||
exportType: "momeny",
|
|
||||||
align: 'right',
|
|
||||||
width: 120,
|
|
||||||
valueType: 'digit',
|
|
||||||
dataIndex: 'CASHPAY_AMOUNT',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: <div style={{ textAlign: 'center' }}>移动支付</div>,
|
|
||||||
titleStr: '移动支付',
|
|
||||||
exportType: "momeny",
|
|
||||||
align: 'right',
|
|
||||||
width: 120,
|
|
||||||
valueType: 'digit',
|
|
||||||
dataIndex: 'MOBILEPAY_AMOUNT',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: <div style={{ textAlign: 'center' }}>小计</div>,
|
|
||||||
titleStr: '小计',
|
|
||||||
exportType: "momeny",
|
|
||||||
align: 'right',
|
|
||||||
valueType: 'digit',
|
|
||||||
width: 120,
|
|
||||||
dataIndex: 'REVENUEDAILY_AMOUNTTotal',
|
|
||||||
},
|
|
||||||
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: <div style={{ textAlign: 'center' }}>提成金额</div>,
|
|
||||||
titleStr: '提成金额',
|
|
||||||
exportType: "momeny",
|
|
||||||
align: 'right',
|
|
||||||
valueType: 'digit',
|
|
||||||
hideInSearch: true,
|
|
||||||
width: 120,
|
|
||||||
dataIndex: 'GUARANTEERATIOAMOUNT',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: <div style={{ textAlign: 'center' }}>业主收款</div>,
|
|
||||||
titleStr: '业主收款',
|
|
||||||
exportType: "momeny",
|
|
||||||
align: 'right',
|
|
||||||
valueType: 'digit',
|
|
||||||
hideInSearch: true,
|
|
||||||
width: 120,
|
|
||||||
dataIndex: 'BANKACCOUNT_AMOUNT',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: <div style={{ textAlign: 'center' }}>应收租金</div>,
|
|
||||||
titleStr: '应收租金',
|
|
||||||
exportType: "momeny",
|
|
||||||
align: 'right',
|
|
||||||
width: 120,
|
|
||||||
hideInSearch: true,
|
|
||||||
valueType: 'digit',
|
|
||||||
dataIndex: 'RECEIVABLEAMOUNT',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: <div style={{ textAlign: 'center' }}>应收费用</div>,
|
|
||||||
titleStr: '应收费用',
|
|
||||||
exportType: "momeny",
|
|
||||||
align: 'right',
|
|
||||||
valueType: 'digit',
|
|
||||||
hideInSearch: true,
|
|
||||||
width: 120,
|
|
||||||
dataIndex: 'SHOPEXPENSE_AMOUNT',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: <div style={{ textAlign: 'center' }}>已缴费用</div>,
|
|
||||||
titleStr: '已缴费用',
|
|
||||||
exportType: "momeny",
|
|
||||||
align: 'right',
|
|
||||||
valueType: 'digit',
|
|
||||||
hideInSearch: true,
|
|
||||||
width: 120,
|
|
||||||
dataIndex: 'PAID_AMOUNT',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: <div style={{ textAlign: 'center' }}>退补款</div>,
|
|
||||||
titleStr: '退补款',
|
|
||||||
exportType: "momeny",
|
|
||||||
align: 'right',
|
|
||||||
valueType: 'digit',
|
|
||||||
hideInSearch: true,
|
|
||||||
width: 120,
|
|
||||||
dataIndex: 'REFUND_SUPPLEMENT',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: <div style={{ textAlign: 'center' }}>结算月份</div>,
|
|
||||||
titleStr: '结算月份',
|
|
||||||
align: 'center',
|
|
||||||
valueType: 'digit',
|
|
||||||
hideInSearch: true,
|
|
||||||
width: 120,
|
|
||||||
dataIndex: 'STATISTICS_MONTH',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: <div style={{ textAlign: 'center' }}>是否结算</div>,
|
|
||||||
titleStr: '是否结算',
|
|
||||||
align: 'center',
|
|
||||||
valueType: 'digit',
|
|
||||||
hideInSearch: true,
|
|
||||||
width: 120,
|
|
||||||
dataIndex: 'settlementStateObjApprovalstate',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: <div style={{ textAlign: 'center' }}>备注(收退款)</div>,
|
|
||||||
titleStr: '备注(收退款)',
|
|
||||||
align: 'center',
|
|
||||||
hideInSearch: true,
|
|
||||||
width: 120,
|
|
||||||
dataIndex: 'REFUND_SUPPLEMENTdesc',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
const exportTable = (isHaveChildren: boolean, isHaveTitle?: boolean) => {
|
|
||||||
// isHaveChildren 判断表头是否有子集
|
|
||||||
// isHaveTitle 判断是否有title
|
|
||||||
let columnsNoChildren: any = []
|
|
||||||
// 先创建需要显示的列表头
|
|
||||||
let headerArray: any = isHaveChildren ? [[], []] : []
|
|
||||||
// 需要合并单元格的内容
|
|
||||||
let mergesList: any = []
|
|
||||||
// 因为子集也拆出来了 这样实际的行数会比columns多 所以得知道多了多少
|
|
||||||
let moreColumns: number = 0
|
|
||||||
// 显示的列表有多少个
|
|
||||||
let showItemNumber: number = 0
|
|
||||||
|
|
||||||
let showIndex: number = 0
|
|
||||||
if (columns && columns.length > 0) {
|
|
||||||
columns.forEach((item: any, index: number) => {
|
|
||||||
if (!item.hideInTable) {
|
|
||||||
showItemNumber += 1
|
|
||||||
if (item.children && item.children.length > 0) {
|
|
||||||
mergesList.push({
|
|
||||||
s: { r: 0 + (isHaveTitle ? 1 : 0), c: showIndex },
|
|
||||||
e: { r: 0 + (isHaveTitle ? 1 : 0), c: showIndex + item.children.length - 1 },
|
|
||||||
})
|
|
||||||
moreColumns += item.children.length - 1
|
|
||||||
showIndex += item.children.length
|
|
||||||
item.children.forEach((subItem: any) => {
|
|
||||||
if (!subItem.hideInTable) {
|
|
||||||
columnsNoChildren.push(subItem)
|
|
||||||
headerArray[0].push(item.titleStr)
|
|
||||||
headerArray[1].push(subItem.titleStr)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
columnsNoChildren.push(item)
|
|
||||||
headerArray[0].push(item.titleStr)
|
|
||||||
if (isHaveChildren) {
|
|
||||||
headerArray[1].push(item.titleStr)
|
|
||||||
mergesList.push({
|
|
||||||
s: { r: 0 + (isHaveTitle ? 1 : 0), c: showIndex },
|
|
||||||
e: { r: 1 + (isHaveTitle ? 1 : 0), c: showIndex },
|
|
||||||
})
|
|
||||||
}
|
|
||||||
showIndex += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// **创建工作表**
|
|
||||||
let ws = XLSX.utils.aoa_to_sheet([]);
|
|
||||||
|
|
||||||
// 设置列宽:动态计算每列的最大内容长度
|
|
||||||
let colWidths: any = [];
|
|
||||||
// 设置样式:对齐方式
|
|
||||||
const cellStyle: any = {
|
|
||||||
alignment: {
|
|
||||||
horizontal: 'center',
|
|
||||||
vertical: 'center'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (headerArray && headerArray.length > 0) {
|
|
||||||
headerArray.forEach((row: any, rowIndex: any) => {
|
|
||||||
row.forEach((cell: any, colIndex: any) => {
|
|
||||||
const cellRef = XLSX.utils.encode_cell({ r: (isHaveChildren ? rowIndex : rowIndex) + (isHaveTitle ? 1 : 0), c: colIndex });
|
|
||||||
ws[cellRef] = {
|
|
||||||
v: cell, t: 's', s: cellStyle
|
|
||||||
};
|
|
||||||
const cellLength = getCharWidth((cell && cell.toString()) || '');
|
|
||||||
|
|
||||||
if (!colWidths[colIndex]) {
|
|
||||||
colWidths[colIndex] = cellLength;
|
|
||||||
} else {
|
|
||||||
colWidths[colIndex] = Math.max(colWidths[colIndex], cellLength);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 设置工作表的范围(必需)
|
|
||||||
const range = {
|
|
||||||
s: { r: 0, c: 0 }, // 开始行列
|
|
||||||
e: { r: reqDetailList.length + (isHaveChildren ? 2 : 1) + (isHaveTitle ? 1 : 0), c: columnsNoChildren.length } // 结束行列
|
|
||||||
};
|
|
||||||
|
|
||||||
ws["A1"] = {
|
|
||||||
v: `(${searchParams?.StatisticsYear})年度结算汇总表`, t: 's', s: {
|
|
||||||
font: {
|
|
||||||
bold: true, // 字体加粗
|
|
||||||
color: { rgb: "#000" }, // 字体颜色红色
|
|
||||||
sz: 20 // 字号为14
|
|
||||||
},
|
|
||||||
alignment: {
|
|
||||||
horizontal: 'center', // 水平居中
|
|
||||||
vertical: 'center' // 垂直居中
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (isHaveTitle) {
|
|
||||||
mergesList.push(
|
|
||||||
{
|
|
||||||
s: { r: 0, c: 0 },
|
|
||||||
e: { r: 0, c: columnsNoChildren.length },
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
ws['!merges'] = mergesList
|
|
||||||
|
|
||||||
ws['!ref'] = XLSX.utils.encode_range(range); // 设置单元格范围
|
|
||||||
|
|
||||||
if (reqDetailList && reqDetailList.length > 0) {
|
|
||||||
reqDetailList.forEach((item: any, index: number) => {
|
|
||||||
columnsNoChildren.forEach((subItem: any, subIndex: number) => {
|
|
||||||
for (let key in item) {
|
|
||||||
if (subItem.dataIndex === key) {
|
|
||||||
let res = item[key]
|
|
||||||
const cellRef = XLSX.utils.encode_cell({ r: (isHaveChildren ? index + 2 : index + 1) + (isHaveTitle ? 1 : 0), c: subIndex });
|
|
||||||
let newRes = res ? subItem.exportType === 'momeny' ? handleFormatNumber(res) : subItem.exportType === 'rate' ? `${res}%` : res : subItem.exportType === 'momeny' ? '0' : ""
|
|
||||||
|
|
||||||
ws[cellRef] = {
|
|
||||||
v: newRes, t: 's', s: {
|
|
||||||
alignment: {
|
|
||||||
horizontal: subItem.align, // 水平居中
|
|
||||||
vertical: 'center' // 垂直居中
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const cellLength = getCharWidth((newRes && newRes.toString()) || '');
|
|
||||||
if (!colWidths[subIndex]) {
|
|
||||||
colWidths[subIndex] = cellLength;
|
|
||||||
} else {
|
|
||||||
colWidths[subIndex] = Math.max(colWidths[subIndex], cellLength);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
ws['!cols'] = colWidths.map((width: any) => ({ wch: width + 2 })); // wch 表示字符宽度
|
|
||||||
|
|
||||||
// 创建工作簿
|
|
||||||
const wb = XLSX.utils.book_new();
|
|
||||||
XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');
|
|
||||||
const wbout = XLSXStyle.write(wb, { bookType: 'xlsx', type: 'binary' });
|
|
||||||
|
|
||||||
const blob = new Blob([s2ab(wbout)], { type: 'application/octet-stream' });
|
|
||||||
const url = URL.createObjectURL(blob);
|
|
||||||
const a = document.createElement('a');
|
|
||||||
a.href = url;
|
|
||||||
a.download = `(${searchParams?.StatisticsYear})年度结算汇总表.xlsx`;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
URL.revokeObjectURL(url);
|
|
||||||
document.body.removeChild(a);
|
|
||||||
setShowLoading(false)
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
const s2ab = (s: string) => {
|
|
||||||
const buf = new ArrayBuffer(s.length);
|
|
||||||
const view = new Uint8Array(buf);
|
|
||||||
for (let i = 0; i < s.length; i++) {
|
|
||||||
view[i] = s.charCodeAt(i) & 0xff;
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 判断字符类型的辅助函数
|
|
||||||
const getCharWidth = (cell: any) => {
|
|
||||||
if (!cell) {
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
if (typeof cell === 'number') {
|
|
||||||
return cell.toString().length > 150 ? 150 : cell.toString().length; // 数字通常和英文字符宽度相同
|
|
||||||
} else if (/[^\x00-\xff]/.test(cell)) {
|
|
||||||
return cell.length * 1.8 > 300 ? 300 : cell.length * 1.8; // 中文字符宽度大约是英文字符的2倍
|
|
||||||
} else {
|
|
||||||
return cell.length > 150 ? 150 : cell.length; // 英文字符的宽度为1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div ref={(el) => {
|
|
||||||
// 打印报表
|
|
||||||
if (!reqDetailList || reqDetailList.length === 0) return;
|
|
||||||
setPrintOut(el);
|
|
||||||
}} >
|
|
||||||
|
|
||||||
{
|
|
||||||
showLoading ?
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
width: '100%',
|
|
||||||
height: '100%',
|
|
||||||
background: 'rgba(0,0,0,0.1)',
|
|
||||||
position: 'fixed',
|
|
||||||
zIndex: 5,
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div style={{
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
padding: '15px 20px 10px',
|
|
||||||
background: '#fff',
|
|
||||||
borderRadius: '8px',
|
|
||||||
width: '200px'
|
|
||||||
}}>
|
|
||||||
<Spin />
|
|
||||||
<span style={{ marginLeft: '5px' }}>数据导出中...</span>
|
|
||||||
</div>
|
|
||||||
</div> : ''
|
|
||||||
}
|
|
||||||
|
|
||||||
<div className={`saleReportHideBox${printIndex}`} style={{ position: 'fixed', zIndex: -1, top: 0, left: 0 }}>
|
|
||||||
{
|
|
||||||
showExportTable && reqDetailList && reqDetailList.length > 0 ?
|
|
||||||
<ProTable
|
|
||||||
columns={columns}
|
|
||||||
dataSource={reqDetailList}
|
|
||||||
pagination={false}
|
|
||||||
expandable={{
|
|
||||||
defaultExpandAllRows: true
|
|
||||||
}}
|
|
||||||
/> : ''
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id='hiddenBox' style={{ position: 'fixed', zIndex: -1, top: 0, left: 0 }} />
|
|
||||||
|
|
||||||
<div style={{ backgroundColor: '#fff', display: 'flex' }}>
|
|
||||||
<LeftSelectTree setSelectedId={setSelectedId} setCollapsible={setCollapsible} collapsible={collapsible} />
|
|
||||||
<div style={{
|
|
||||||
width: !collapsible ? 'calc(100% - 300px)' : 'calc(100% - 60px)',
|
|
||||||
paddingTop: 0,
|
|
||||||
paddingBottom: 0,
|
|
||||||
paddingRight: 0
|
|
||||||
}}>
|
|
||||||
<ProTable
|
|
||||||
actionRef={actionRef}
|
|
||||||
formRef={formRef}
|
|
||||||
columns={columns}
|
|
||||||
bordered
|
|
||||||
expandable={{
|
|
||||||
expandRowByClick: true
|
|
||||||
}}
|
|
||||||
scroll={{ x: '100%' }}
|
|
||||||
headerTitle={<span style={{ color: "#1890ff", fontSize: 14, fontWeight: 600 }}>单品销售排行统计</span>}
|
|
||||||
search={{ span: 6 }}
|
|
||||||
request={async (params) => {
|
|
||||||
if (!selectedId) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
setSearchParams(params)
|
|
||||||
}}
|
|
||||||
toolbar={{
|
|
||||||
actions: [
|
|
||||||
<span style={{ visibility: 'hidden' }}>
|
|
||||||
|
|
||||||
</span>,
|
|
||||||
<Button
|
|
||||||
key="new"
|
|
||||||
type="primary"
|
|
||||||
onClick={(e) => {
|
|
||||||
if (reqDetailList && reqDetailList.length > 0) {
|
|
||||||
setShowLoading(true)
|
|
||||||
setTimeout(() => {
|
|
||||||
setShowExportTable(true)
|
|
||||||
setTimeout(() => {
|
|
||||||
exportTable(true, true)
|
|
||||||
}, 100)
|
|
||||||
}, 100)
|
|
||||||
} else {
|
|
||||||
message.error('暂无数据可导出!')
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
导出excel
|
|
||||||
</Button>
|
|
||||||
]
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(
|
|
||||||
({ user }: { user: UserConnectedProps['user'] }) => ({
|
|
||||||
user
|
|
||||||
}),
|
|
||||||
)(saleRankReport);
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
import { PureComponent } from 'react';
|
|
||||||
|
|
||||||
class Index extends PureComponent {
|
|
||||||
|
|
||||||
render() {
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>/about/um</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Index;
|
|
||||||
@ -1,33 +1,17 @@
|
|||||||
|
|
||||||
const authority: PageAuthority = {
|
const authority: PageAuthority = {
|
||||||
'/user/login': [], // 登录页面不需要权限验证
|
'/standard/index': [
|
||||||
'/': [
|
'/standard/index',
|
||||||
'/',
|
|
||||||
],
|
],
|
||||||
'/about/u/index': [
|
'/examine/index': [
|
||||||
'/about/u/index',
|
'/examine/index'
|
||||||
],
|
],
|
||||||
'/about/u/2': [
|
'/examine/modal': [
|
||||||
'/about/u/2',
|
'/examine/modal'
|
||||||
],
|
],
|
||||||
'/about/m': [
|
'/examine/question': [
|
||||||
'/about/m',
|
'/examine/question',
|
||||||
],
|
|
||||||
'/about/um': [
|
|
||||||
'/about/um',
|
|
||||||
],
|
|
||||||
'/teacher/u': [
|
|
||||||
'/ttt',
|
|
||||||
],
|
|
||||||
'/teacher/m': [
|
|
||||||
'/teacher/m',
|
|
||||||
],
|
|
||||||
'/teacher/um': [
|
|
||||||
'/teacher/um',
|
|
||||||
],
|
|
||||||
'/student': [
|
|
||||||
'/student',
|
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export default authority;
|
export default authority;
|
||||||
|
|||||||
190
src/pages/examine/index.tsx
Normal file
190
src/pages/examine/index.tsx
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
import { connect } from "umi";
|
||||||
|
import { useRef, useState } from "react";
|
||||||
|
import { Button, message, Modal, Space, type FormInstance } from "antd";
|
||||||
|
import type { ActionType } from "@ant-design/pro-table";
|
||||||
|
import ProTable from "@ant-design/pro-table";
|
||||||
|
import moment from "moment";
|
||||||
|
import LeftSelectTree from "@/components/leftSelectTree";
|
||||||
|
import { handleGetAddExamineType, handleGetExamineTypeList } from "./service";
|
||||||
|
import { ProForm, ProFormSwitch, ProFormText, ProFormTextArea } from "@ant-design/pro-components";
|
||||||
|
|
||||||
|
|
||||||
|
const examineIndex: React.FC<{ currentUser: any }> = (props) => {
|
||||||
|
console.log('props', props);
|
||||||
|
const { currentUser } = props
|
||||||
|
|
||||||
|
console.log('currentUser', currentUser);
|
||||||
|
|
||||||
|
const actionRef = useRef<ActionType>();
|
||||||
|
const formRef = useRef<FormInstance>();
|
||||||
|
// 弹出框的表单实例
|
||||||
|
const modalRef = useRef<FormInstance>()
|
||||||
|
// 查询的条件
|
||||||
|
const [searchParams, setSearchParams] = useState<any>()
|
||||||
|
// 打开新增的悬浮框
|
||||||
|
const [openAddModal, setOpenAddModal] = useState<boolean>(false)
|
||||||
|
|
||||||
|
const columns: any = [
|
||||||
|
{
|
||||||
|
title: <div style={{ textAlign: 'center' }}>分类名称</div>,
|
||||||
|
dataIndex: "name",
|
||||||
|
align: 'left',
|
||||||
|
width: 200,
|
||||||
|
hideInSearch: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: <div style={{ textAlign: 'center' }}>分类注释</div>,
|
||||||
|
dataIndex: "description",
|
||||||
|
align: 'left',
|
||||||
|
width: 250,
|
||||||
|
hideInSearch: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "有效状态",
|
||||||
|
dataIndex: "status",
|
||||||
|
align: 'center',
|
||||||
|
width: 150,
|
||||||
|
hideInSearch: true,
|
||||||
|
render: (_: any, record: { status: any; }) => {
|
||||||
|
return record?.status ? '有效' : '无效'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "创建时间",
|
||||||
|
dataIndex: "createdAt",
|
||||||
|
align: 'center',
|
||||||
|
width: 200,
|
||||||
|
hideInSearch: true,
|
||||||
|
render: (_: any, record: { status: any; }) => {
|
||||||
|
return record?.createdAt ? moment(record?.createdAt).format('YYYY-MM-DD HH:mm:ss') : '-'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "更新时间",
|
||||||
|
dataIndex: "updatedAt",
|
||||||
|
align: 'center',
|
||||||
|
width: 200,
|
||||||
|
hideInSearch: true,
|
||||||
|
render: (_: any, record: { status: any; }) => {
|
||||||
|
return record?.updatedAt ? moment(record?.updatedAt).format('YYYY-MM-DD HH:mm:ss') : '-'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
dataIndex: 'option',
|
||||||
|
align: 'center',
|
||||||
|
hideInSearch: true,
|
||||||
|
width: 150,
|
||||||
|
render: (_: any, record: any) => {
|
||||||
|
return <Space>
|
||||||
|
<a>编辑</a>
|
||||||
|
<a>删除</a>
|
||||||
|
</Space>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div style={{ backgroundColor: '#fff', display: 'flex' }}>
|
||||||
|
<div style={{
|
||||||
|
width: '100%',
|
||||||
|
paddingTop: 0,
|
||||||
|
paddingBottom: 0,
|
||||||
|
paddingRight: 0
|
||||||
|
}}>
|
||||||
|
<ProTable
|
||||||
|
actionRef={actionRef}
|
||||||
|
formRef={formRef}
|
||||||
|
columns={columns}
|
||||||
|
bordered
|
||||||
|
expandable={{
|
||||||
|
expandRowByClick: true
|
||||||
|
}}
|
||||||
|
headerTitle={<span style={{ color: "#1890ff", fontSize: 14, fontWeight: 600 }}>考评分类管理</span>}
|
||||||
|
search={{ span: 6 }}
|
||||||
|
request={async (params) => {
|
||||||
|
const data = await handleGetExamineTypeList()
|
||||||
|
console.log('table', data);
|
||||||
|
if (data && data.length > 0) {
|
||||||
|
return { data, success: true }
|
||||||
|
}
|
||||||
|
return { data: [], success: true }
|
||||||
|
}}
|
||||||
|
toolbar={{
|
||||||
|
actions: [
|
||||||
|
<Button type="primary" onClick={(e) => {
|
||||||
|
setOpenAddModal(true)
|
||||||
|
}}>
|
||||||
|
新增分类
|
||||||
|
</Button>
|
||||||
|
]
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Modal
|
||||||
|
title="分类"
|
||||||
|
open={openAddModal}
|
||||||
|
onOk={() => {
|
||||||
|
modalRef.current?.validateFields().then(async (res) => {
|
||||||
|
console.log('res', res);
|
||||||
|
const req = {
|
||||||
|
name: res.name,
|
||||||
|
description: res.description,
|
||||||
|
sortOrder: "1",
|
||||||
|
status: res.status,
|
||||||
|
operator: currentUser?.operator
|
||||||
|
}
|
||||||
|
const data = await handleGetAddExamineType(req)
|
||||||
|
console.log('data', data);
|
||||||
|
if (data.code === 200) {
|
||||||
|
message.success(data.message)
|
||||||
|
setOpenAddModal(false)
|
||||||
|
actionRef.current?.reload()
|
||||||
|
} else {
|
||||||
|
message.error(data.message)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
onCancel={() => {
|
||||||
|
setOpenAddModal(false)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ProForm
|
||||||
|
formRef={modalRef}
|
||||||
|
submitter={false}
|
||||||
|
onFinish={async (values) => {
|
||||||
|
console.log('values', values);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ProFormText
|
||||||
|
label={"类别名称"}
|
||||||
|
name={"name"}
|
||||||
|
rules={[
|
||||||
|
{ required: true, message: '请输入类别名称!' }
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<ProFormTextArea
|
||||||
|
label={"类别注释"}
|
||||||
|
name={"description"}
|
||||||
|
/>
|
||||||
|
<ProFormSwitch
|
||||||
|
label={"有效状态"}
|
||||||
|
name={"status"}
|
||||||
|
initialValue={true}
|
||||||
|
/>
|
||||||
|
</ProForm>
|
||||||
|
|
||||||
|
|
||||||
|
</Modal>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(({ user }: ConnectState) => ({
|
||||||
|
currentUser: user.data
|
||||||
|
}))(examineIndex);
|
||||||
21
src/pages/examine/modal.tsx
Normal file
21
src/pages/examine/modal.tsx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { UserConnectedProps } from "@/models/user";
|
||||||
|
import { connect } from "umi";
|
||||||
|
|
||||||
|
|
||||||
|
type DetailProps = {
|
||||||
|
|
||||||
|
}
|
||||||
|
const modal = ({ }: DetailProps) => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
modal
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(
|
||||||
|
({ user }: { user: UserConnectedProps['user'] }) => ({
|
||||||
|
user
|
||||||
|
}),
|
||||||
|
)(modal);
|
||||||
21
src/pages/examine/question.tsx
Normal file
21
src/pages/examine/question.tsx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { UserConnectedProps } from "@/models/user";
|
||||||
|
import { connect } from "umi";
|
||||||
|
|
||||||
|
|
||||||
|
type DetailProps = {
|
||||||
|
|
||||||
|
}
|
||||||
|
const question = ({ }: DetailProps) => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
question
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(
|
||||||
|
({ user }: { user: UserConnectedProps['user'] }) => ({
|
||||||
|
user
|
||||||
|
}),
|
||||||
|
)(question);
|
||||||
16
src/pages/examine/service.ts
Normal file
16
src/pages/examine/service.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import request from "@/utils/request"
|
||||||
|
|
||||||
|
// 拿到类别列表接口
|
||||||
|
export async function handleGetExamineTypeList(params?: any) {
|
||||||
|
const data = await request.get('/question-categories', params)
|
||||||
|
if (data.code === 200) {
|
||||||
|
return data.data
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增类别列表接口
|
||||||
|
export async function handleGetAddExamineType(params: any) {
|
||||||
|
const data = await request.post('/question-categories', params)
|
||||||
|
return data
|
||||||
|
}
|
||||||
582
src/pages/standard/index.tsx
Normal file
582
src/pages/standard/index.tsx
Normal file
@ -0,0 +1,582 @@
|
|||||||
|
import { connect } from "umi";
|
||||||
|
import { MouseEvent, useRef, useState } from "react";
|
||||||
|
import type { FormInstance } from "antd";
|
||||||
|
import { Button, message, Spin } from "antd";
|
||||||
|
import type { ActionType } from "@ant-design/pro-table";
|
||||||
|
import ProTable from "@ant-design/pro-table";
|
||||||
|
import * as XLSX from 'xlsx'; // 读写数据的核心工具(无需写样式时可用)
|
||||||
|
import XLSXStyle from 'xlsx-style-fixed';
|
||||||
|
import moment from "moment";
|
||||||
|
import { handleFormatNumber } from "@/utils/publicMethods";
|
||||||
|
import LeftSelectTree from "@/components/leftSelectTree";
|
||||||
|
import { UserConnectedProps } from "@/models/user";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const saleRankReport = (props: any) => {
|
||||||
|
const { currentUser } = props
|
||||||
|
const downloadBtnRef = useRef<any>()
|
||||||
|
const actionRef = useRef<ActionType>();
|
||||||
|
const formRef = useRef<FormInstance>();
|
||||||
|
const [reqDetailList, setReqDetailList] = useState<any>([{
|
||||||
|
SPREGIONTYPE_NAME: "1",
|
||||||
|
SERVERPART_NAME: "1",
|
||||||
|
MERCHANTS_NAME: "1",
|
||||||
|
SERVERPARTSHOP_NAME: "1",
|
||||||
|
IndexStr: "1",
|
||||||
|
COMPACT_STARTDATECOMPACT_ENDDATE: "1",
|
||||||
|
RENTFEE: "1",
|
||||||
|
GUARANTEERATIO: "1",
|
||||||
|
CASHPAY_AMOUNT: "1",
|
||||||
|
MOBILEPAY_AMOUNT: "1",
|
||||||
|
REVENUEDAILY_AMOUNTTotal: "1",
|
||||||
|
GUARANTEERATIOAMOUNT: "1",
|
||||||
|
BANKACCOUNT_AMOUNT: "1",
|
||||||
|
RECEIVABLEAMOUNT: "1",
|
||||||
|
SHOPEXPENSE_AMOUNT: "1",
|
||||||
|
PAID_AMOUNT: "1",
|
||||||
|
REFUND_SUPPLEMENT: "1",
|
||||||
|
STATISTICS_MONTH: "1",
|
||||||
|
settlementStateObjApprovalstate: "1",
|
||||||
|
REFUND_SUPPLEMENTdesc: "1",
|
||||||
|
}]); // 合计项数据源
|
||||||
|
const [printOut, setPrintOut] = useState<any>(); // 打印数据的内容
|
||||||
|
const [collapsible, setCollapsible] = useState<boolean>(false)
|
||||||
|
const [treeView, setTreeView] = useState<any>()
|
||||||
|
const [printIndex, setPrintIndex] = useState<number>(new Date().getTime())
|
||||||
|
|
||||||
|
|
||||||
|
// 树相关的属性和方法
|
||||||
|
const [selectedId, setSelectedId] = useState<string>()
|
||||||
|
// 导出的加载效果
|
||||||
|
const [showLoading, setShowLoading] = useState<boolean>(false)
|
||||||
|
// 是否显示打印的表格
|
||||||
|
const [showExportTable, setShowExportTable] = useState<boolean>(false)
|
||||||
|
// 查询的条件
|
||||||
|
const [searchParams, setSearchParams] = useState<any>()
|
||||||
|
|
||||||
|
const columns: any = [
|
||||||
|
{
|
||||||
|
title: '统计日期',
|
||||||
|
dataIndex: 'StatisticsYear',
|
||||||
|
valueType: "date",
|
||||||
|
hideInTable: true,
|
||||||
|
hideInDescriptions: true,
|
||||||
|
initialValue: moment().subtract('1', 'month'),
|
||||||
|
|
||||||
|
fieldProps: {
|
||||||
|
picker: "year",
|
||||||
|
format: 'YYYY'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "结算状态",
|
||||||
|
dataIndex: 'SettlementState',
|
||||||
|
valueType: 'select',
|
||||||
|
hideInTable: true,
|
||||||
|
valueEnum: {
|
||||||
|
"9": "已结算",
|
||||||
|
"0": "待结算",
|
||||||
|
"-1": "提前退场",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: <div style={{ textAlign: 'center' }}>管理中心</div>,
|
||||||
|
titleStr: '管理中心',
|
||||||
|
dataIndex: 'SPREGIONTYPE_NAME',
|
||||||
|
width: 200,
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: <div style={{ textAlign: 'center' }}>服务区</div>,
|
||||||
|
titleStr: '服务区',
|
||||||
|
dataIndex: 'SERVERPART_NAME',
|
||||||
|
width: 200,
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: <div style={{ textAlign: 'center' }}>经营商户</div>,
|
||||||
|
titleStr: '经营商户',
|
||||||
|
dataIndex: 'MERCHANTS_NAME',
|
||||||
|
width: 200,
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: <div style={{ textAlign: 'center' }}>门店</div>,
|
||||||
|
titleStr: '门店',
|
||||||
|
dataIndex: 'SERVERPARTSHOP_NAME',
|
||||||
|
width: 150,
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: <div style={{ textAlign: 'center' }}>基础信息</div>,
|
||||||
|
dataIndex: 'termInfo',
|
||||||
|
titleStr: '基础信息',
|
||||||
|
// fixed: 'left',
|
||||||
|
hideInSearch: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: <div style={{ textAlign: 'center' }}>期数</div>,
|
||||||
|
titleStr: '期数',
|
||||||
|
dataIndex: 'IndexStr',
|
||||||
|
width: 100,
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: <div style={{ textAlign: 'center' }}>时限</div>,
|
||||||
|
titleStr: '时限',
|
||||||
|
dataIndex: 'COMPACT_STARTDATECOMPACT_ENDDATE',
|
||||||
|
width: 180,
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: <div style={{ textAlign: 'center' }}>保底/固定租金</div>,
|
||||||
|
titleStr: '保底/固定租金',
|
||||||
|
exportType: "momeny",
|
||||||
|
align: 'right',
|
||||||
|
width: 140,
|
||||||
|
valueType: 'digit',
|
||||||
|
dataIndex: 'RENTFEE',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: <div style={{ textAlign: 'center' }}>提成比率</div>,
|
||||||
|
titleStr: '提成比率',
|
||||||
|
exportType: "rate",
|
||||||
|
dataIndex: 'GUARANTEERATIO',
|
||||||
|
align: 'center',
|
||||||
|
width: 120,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: <div style={{ textAlign: 'center' }}>营业额</div>,
|
||||||
|
titleStr: '营业额',
|
||||||
|
dataIndex: '',
|
||||||
|
hideInSearch: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: <div style={{ textAlign: 'center' }}>现金</div>,
|
||||||
|
titleStr: '现金',
|
||||||
|
exportType: "momeny",
|
||||||
|
align: 'right',
|
||||||
|
width: 120,
|
||||||
|
valueType: 'digit',
|
||||||
|
dataIndex: 'CASHPAY_AMOUNT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: <div style={{ textAlign: 'center' }}>移动支付</div>,
|
||||||
|
titleStr: '移动支付',
|
||||||
|
exportType: "momeny",
|
||||||
|
align: 'right',
|
||||||
|
width: 120,
|
||||||
|
valueType: 'digit',
|
||||||
|
dataIndex: 'MOBILEPAY_AMOUNT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: <div style={{ textAlign: 'center' }}>小计</div>,
|
||||||
|
titleStr: '小计',
|
||||||
|
exportType: "momeny",
|
||||||
|
align: 'right',
|
||||||
|
valueType: 'digit',
|
||||||
|
width: 120,
|
||||||
|
dataIndex: 'REVENUEDAILY_AMOUNTTotal',
|
||||||
|
},
|
||||||
|
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: <div style={{ textAlign: 'center' }}>提成金额</div>,
|
||||||
|
titleStr: '提成金额',
|
||||||
|
exportType: "momeny",
|
||||||
|
align: 'right',
|
||||||
|
valueType: 'digit',
|
||||||
|
hideInSearch: true,
|
||||||
|
width: 120,
|
||||||
|
dataIndex: 'GUARANTEERATIOAMOUNT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: <div style={{ textAlign: 'center' }}>业主收款</div>,
|
||||||
|
titleStr: '业主收款',
|
||||||
|
exportType: "momeny",
|
||||||
|
align: 'right',
|
||||||
|
valueType: 'digit',
|
||||||
|
hideInSearch: true,
|
||||||
|
width: 120,
|
||||||
|
dataIndex: 'BANKACCOUNT_AMOUNT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: <div style={{ textAlign: 'center' }}>应收租金</div>,
|
||||||
|
titleStr: '应收租金',
|
||||||
|
exportType: "momeny",
|
||||||
|
align: 'right',
|
||||||
|
width: 120,
|
||||||
|
hideInSearch: true,
|
||||||
|
valueType: 'digit',
|
||||||
|
dataIndex: 'RECEIVABLEAMOUNT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: <div style={{ textAlign: 'center' }}>应收费用</div>,
|
||||||
|
titleStr: '应收费用',
|
||||||
|
exportType: "momeny",
|
||||||
|
align: 'right',
|
||||||
|
valueType: 'digit',
|
||||||
|
hideInSearch: true,
|
||||||
|
width: 120,
|
||||||
|
dataIndex: 'SHOPEXPENSE_AMOUNT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: <div style={{ textAlign: 'center' }}>已缴费用</div>,
|
||||||
|
titleStr: '已缴费用',
|
||||||
|
exportType: "momeny",
|
||||||
|
align: 'right',
|
||||||
|
valueType: 'digit',
|
||||||
|
hideInSearch: true,
|
||||||
|
width: 120,
|
||||||
|
dataIndex: 'PAID_AMOUNT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: <div style={{ textAlign: 'center' }}>退补款</div>,
|
||||||
|
titleStr: '退补款',
|
||||||
|
exportType: "momeny",
|
||||||
|
align: 'right',
|
||||||
|
valueType: 'digit',
|
||||||
|
hideInSearch: true,
|
||||||
|
width: 120,
|
||||||
|
dataIndex: 'REFUND_SUPPLEMENT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: <div style={{ textAlign: 'center' }}>结算月份</div>,
|
||||||
|
titleStr: '结算月份',
|
||||||
|
align: 'center',
|
||||||
|
valueType: 'digit',
|
||||||
|
hideInSearch: true,
|
||||||
|
width: 120,
|
||||||
|
dataIndex: 'STATISTICS_MONTH',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: <div style={{ textAlign: 'center' }}>是否结算</div>,
|
||||||
|
titleStr: '是否结算',
|
||||||
|
align: 'center',
|
||||||
|
valueType: 'digit',
|
||||||
|
hideInSearch: true,
|
||||||
|
width: 120,
|
||||||
|
dataIndex: 'settlementStateObjApprovalstate',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: <div style={{ textAlign: 'center' }}>备注(收退款)</div>,
|
||||||
|
titleStr: '备注(收退款)',
|
||||||
|
align: 'center',
|
||||||
|
hideInSearch: true,
|
||||||
|
width: 120,
|
||||||
|
dataIndex: 'REFUND_SUPPLEMENTdesc',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const exportTable = (isHaveChildren: boolean, isHaveTitle?: boolean) => {
|
||||||
|
// isHaveChildren 判断表头是否有子集
|
||||||
|
// isHaveTitle 判断是否有title
|
||||||
|
let columnsNoChildren: any = []
|
||||||
|
// 先创建需要显示的列表头
|
||||||
|
let headerArray: any = isHaveChildren ? [[], []] : []
|
||||||
|
// 需要合并单元格的内容
|
||||||
|
let mergesList: any = []
|
||||||
|
// 因为子集也拆出来了 这样实际的行数会比columns多 所以得知道多了多少
|
||||||
|
let moreColumns: number = 0
|
||||||
|
// 显示的列表有多少个
|
||||||
|
let showItemNumber: number = 0
|
||||||
|
|
||||||
|
let showIndex: number = 0
|
||||||
|
if (columns && columns.length > 0) {
|
||||||
|
columns.forEach((item: any, index: number) => {
|
||||||
|
if (!item.hideInTable) {
|
||||||
|
showItemNumber += 1
|
||||||
|
if (item.children && item.children.length > 0) {
|
||||||
|
mergesList.push({
|
||||||
|
s: { r: 0 + (isHaveTitle ? 1 : 0), c: showIndex },
|
||||||
|
e: { r: 0 + (isHaveTitle ? 1 : 0), c: showIndex + item.children.length - 1 },
|
||||||
|
})
|
||||||
|
moreColumns += item.children.length - 1
|
||||||
|
showIndex += item.children.length
|
||||||
|
item.children.forEach((subItem: any) => {
|
||||||
|
if (!subItem.hideInTable) {
|
||||||
|
columnsNoChildren.push(subItem)
|
||||||
|
headerArray[0].push(item.titleStr)
|
||||||
|
headerArray[1].push(subItem.titleStr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
columnsNoChildren.push(item)
|
||||||
|
headerArray[0].push(item.titleStr)
|
||||||
|
if (isHaveChildren) {
|
||||||
|
headerArray[1].push(item.titleStr)
|
||||||
|
mergesList.push({
|
||||||
|
s: { r: 0 + (isHaveTitle ? 1 : 0), c: showIndex },
|
||||||
|
e: { r: 1 + (isHaveTitle ? 1 : 0), c: showIndex },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
showIndex += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// **创建工作表**
|
||||||
|
let ws = XLSX.utils.aoa_to_sheet([]);
|
||||||
|
|
||||||
|
// 设置列宽:动态计算每列的最大内容长度
|
||||||
|
let colWidths: any = [];
|
||||||
|
// 设置样式:对齐方式
|
||||||
|
const cellStyle: any = {
|
||||||
|
alignment: {
|
||||||
|
horizontal: 'center',
|
||||||
|
vertical: 'center'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (headerArray && headerArray.length > 0) {
|
||||||
|
headerArray.forEach((row: any, rowIndex: any) => {
|
||||||
|
row.forEach((cell: any, colIndex: any) => {
|
||||||
|
const cellRef = XLSX.utils.encode_cell({ r: (isHaveChildren ? rowIndex : rowIndex) + (isHaveTitle ? 1 : 0), c: colIndex });
|
||||||
|
ws[cellRef] = {
|
||||||
|
v: cell, t: 's', s: cellStyle
|
||||||
|
};
|
||||||
|
const cellLength = getCharWidth((cell && cell.toString()) || '');
|
||||||
|
|
||||||
|
if (!colWidths[colIndex]) {
|
||||||
|
colWidths[colIndex] = cellLength;
|
||||||
|
} else {
|
||||||
|
colWidths[colIndex] = Math.max(colWidths[colIndex], cellLength);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 设置工作表的范围(必需)
|
||||||
|
const range = {
|
||||||
|
s: { r: 0, c: 0 }, // 开始行列
|
||||||
|
e: { r: reqDetailList.length + (isHaveChildren ? 2 : 1) + (isHaveTitle ? 1 : 0), c: columnsNoChildren.length } // 结束行列
|
||||||
|
};
|
||||||
|
|
||||||
|
ws["A1"] = {
|
||||||
|
v: `(${searchParams?.StatisticsYear})年度结算汇总表`, t: 's', s: {
|
||||||
|
font: {
|
||||||
|
bold: true, // 字体加粗
|
||||||
|
color: { rgb: "#000" }, // 字体颜色红色
|
||||||
|
sz: 20 // 字号为14
|
||||||
|
},
|
||||||
|
alignment: {
|
||||||
|
horizontal: 'center', // 水平居中
|
||||||
|
vertical: 'center' // 垂直居中
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isHaveTitle) {
|
||||||
|
mergesList.push(
|
||||||
|
{
|
||||||
|
s: { r: 0, c: 0 },
|
||||||
|
e: { r: 0, c: columnsNoChildren.length },
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
ws['!merges'] = mergesList
|
||||||
|
|
||||||
|
ws['!ref'] = XLSX.utils.encode_range(range); // 设置单元格范围
|
||||||
|
|
||||||
|
if (reqDetailList && reqDetailList.length > 0) {
|
||||||
|
reqDetailList.forEach((item: any, index: number) => {
|
||||||
|
columnsNoChildren.forEach((subItem: any, subIndex: number) => {
|
||||||
|
for (let key in item) {
|
||||||
|
if (subItem.dataIndex === key) {
|
||||||
|
let res = item[key]
|
||||||
|
const cellRef = XLSX.utils.encode_cell({ r: (isHaveChildren ? index + 2 : index + 1) + (isHaveTitle ? 1 : 0), c: subIndex });
|
||||||
|
let newRes = res ? subItem.exportType === 'momeny' ? handleFormatNumber(res) : subItem.exportType === 'rate' ? `${res}%` : res : subItem.exportType === 'momeny' ? '0' : ""
|
||||||
|
|
||||||
|
ws[cellRef] = {
|
||||||
|
v: newRes, t: 's', s: {
|
||||||
|
alignment: {
|
||||||
|
horizontal: subItem.align, // 水平居中
|
||||||
|
vertical: 'center' // 垂直居中
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const cellLength = getCharWidth((newRes && newRes.toString()) || '');
|
||||||
|
if (!colWidths[subIndex]) {
|
||||||
|
colWidths[subIndex] = cellLength;
|
||||||
|
} else {
|
||||||
|
colWidths[subIndex] = Math.max(colWidths[subIndex], cellLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
ws['!cols'] = colWidths.map((width: any) => ({ wch: width + 2 })); // wch 表示字符宽度
|
||||||
|
|
||||||
|
// 创建工作簿
|
||||||
|
const wb = XLSX.utils.book_new();
|
||||||
|
XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');
|
||||||
|
const wbout = XLSXStyle.write(wb, { bookType: 'xlsx', type: 'binary' });
|
||||||
|
|
||||||
|
const blob = new Blob([s2ab(wbout)], { type: 'application/octet-stream' });
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = url;
|
||||||
|
a.download = `(${searchParams?.StatisticsYear})年度结算汇总表.xlsx`;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
document.body.removeChild(a);
|
||||||
|
setShowLoading(false)
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
const s2ab = (s: string) => {
|
||||||
|
const buf = new ArrayBuffer(s.length);
|
||||||
|
const view = new Uint8Array(buf);
|
||||||
|
for (let i = 0; i < s.length; i++) {
|
||||||
|
view[i] = s.charCodeAt(i) & 0xff;
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 判断字符类型的辅助函数
|
||||||
|
const getCharWidth = (cell: any) => {
|
||||||
|
if (!cell) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
if (typeof cell === 'number') {
|
||||||
|
return cell.toString().length > 150 ? 150 : cell.toString().length; // 数字通常和英文字符宽度相同
|
||||||
|
} else if (/[^\x00-\xff]/.test(cell)) {
|
||||||
|
return cell.length * 1.8 > 300 ? 300 : cell.length * 1.8; // 中文字符宽度大约是英文字符的2倍
|
||||||
|
} else {
|
||||||
|
return cell.length > 150 ? 150 : cell.length; // 英文字符的宽度为1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div ref={(el) => {
|
||||||
|
// 打印报表
|
||||||
|
if (!reqDetailList || reqDetailList.length === 0) return;
|
||||||
|
setPrintOut(el);
|
||||||
|
}} >
|
||||||
|
|
||||||
|
{
|
||||||
|
showLoading ?
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
background: 'rgba(0,0,0,0.1)',
|
||||||
|
position: 'fixed',
|
||||||
|
zIndex: 5,
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
padding: '15px 20px 10px',
|
||||||
|
background: '#fff',
|
||||||
|
borderRadius: '8px',
|
||||||
|
width: '200px'
|
||||||
|
}}>
|
||||||
|
<Spin />
|
||||||
|
<span style={{ marginLeft: '5px' }}>数据导出中...</span>
|
||||||
|
</div>
|
||||||
|
</div> : ''
|
||||||
|
}
|
||||||
|
|
||||||
|
<div className={`saleReportHideBox${printIndex}`} style={{ position: 'fixed', zIndex: -1, top: 0, left: 0 }}>
|
||||||
|
{
|
||||||
|
showExportTable && reqDetailList && reqDetailList.length > 0 ?
|
||||||
|
<ProTable
|
||||||
|
columns={columns}
|
||||||
|
dataSource={reqDetailList}
|
||||||
|
pagination={false}
|
||||||
|
expandable={{
|
||||||
|
defaultExpandAllRows: true
|
||||||
|
}}
|
||||||
|
/> : ''
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id='hiddenBox' style={{ position: 'fixed', zIndex: -1, top: 0, left: 0 }} />
|
||||||
|
|
||||||
|
<div style={{ backgroundColor: '#fff', display: 'flex' }}>
|
||||||
|
<LeftSelectTree setSelectedId={setSelectedId} setCollapsible={setCollapsible} collapsible={collapsible} />
|
||||||
|
<div style={{
|
||||||
|
width: !collapsible ? 'calc(100% - 300px)' : 'calc(100% - 60px)',
|
||||||
|
paddingTop: 0,
|
||||||
|
paddingBottom: 0,
|
||||||
|
paddingRight: 0
|
||||||
|
}}>
|
||||||
|
<ProTable
|
||||||
|
actionRef={actionRef}
|
||||||
|
formRef={formRef}
|
||||||
|
columns={columns}
|
||||||
|
bordered
|
||||||
|
expandable={{
|
||||||
|
expandRowByClick: true
|
||||||
|
}}
|
||||||
|
scroll={{ x: '100%' }}
|
||||||
|
headerTitle={<span style={{ color: "#1890ff", fontSize: 14, fontWeight: 600 }}>单品销售排行统计</span>}
|
||||||
|
search={{ span: 6 }}
|
||||||
|
request={async (params) => {
|
||||||
|
if (!selectedId) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
setSearchParams(params)
|
||||||
|
}}
|
||||||
|
toolbar={{
|
||||||
|
actions: [
|
||||||
|
<span style={{ visibility: 'hidden' }}>
|
||||||
|
|
||||||
|
</span>,
|
||||||
|
<Button
|
||||||
|
key="new"
|
||||||
|
type="primary"
|
||||||
|
onClick={(e) => {
|
||||||
|
if (reqDetailList && reqDetailList.length > 0) {
|
||||||
|
setShowLoading(true)
|
||||||
|
setTimeout(() => {
|
||||||
|
setShowExportTable(true)
|
||||||
|
setTimeout(() => {
|
||||||
|
exportTable(true, true)
|
||||||
|
}, 100)
|
||||||
|
}, 100)
|
||||||
|
} else {
|
||||||
|
message.error('暂无数据可导出!')
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
导出excel
|
||||||
|
</Button>
|
||||||
|
]
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(
|
||||||
|
({ user }: { user: UserConnectedProps['user'] }) => ({
|
||||||
|
user
|
||||||
|
}),
|
||||||
|
)(saleRankReport);
|
||||||
@ -1,10 +0,0 @@
|
|||||||
import type { FC } from 'react';
|
|
||||||
|
|
||||||
const Index: FC = () => {
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>/teacher/m</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Index;
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
import type { FC } from 'react';
|
|
||||||
|
|
||||||
const Index: FC = () => {
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>/teacher/u</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Index;
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
import type { FC } from 'react';
|
|
||||||
|
|
||||||
const Index: FC = () => {
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>/teacher/um</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Index;
|
|
||||||
@ -22,8 +22,11 @@ const Index: FC<UserConnectedProps> = (props) => {
|
|||||||
payload: values,
|
payload: values,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response?.code) {
|
if (response?.code === 200) {
|
||||||
message.error(response.message || '登录失败,请检查账号密码');
|
message.success('登录成功');
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
message.error(response?.message || '登录失败,请检查账号密码');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -79,16 +82,16 @@ const Index: FC<UserConnectedProps> = (props) => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
onFinish={(values) => {
|
onFinish={async (values) => {
|
||||||
handleSubmit({
|
const success = await handleSubmit({
|
||||||
...values,
|
...values,
|
||||||
})
|
});
|
||||||
// LoginIP: baseInfo?.ip ? baseInfo?.ip : '',
|
return success;
|
||||||
// LoginPlace: `${baseInfo?.prov ? baseInfo?.prov : ''}${baseInfo?.prov && baseInfo?.city ? '-' : ''}${baseInfo?.city ? baseInfo?.city : ''}`,
|
|
||||||
// BrowserVersion: browser || '',
|
|
||||||
// OperatingSystem: systemInfo || '',
|
|
||||||
return Promise.resolve();
|
|
||||||
}}
|
}}
|
||||||
|
// LoginIP: baseInfo?.ip ? baseInfo?.ip : '',
|
||||||
|
// LoginPlace: `${baseInfo?.prov ? baseInfo?.prov : ''}${baseInfo?.prov && baseInfo?.city ? '-' : ''}${baseInfo?.city ? baseInfo?.city : ''}`,
|
||||||
|
// BrowserVersion: browser || '',
|
||||||
|
// OperatingSystem: systemInfo || '',
|
||||||
>
|
>
|
||||||
<ProFormText
|
<ProFormText
|
||||||
name="username"
|
name="username"
|
||||||
|
|||||||
@ -7,36 +7,45 @@ import request from '@/utils/request';
|
|||||||
|
|
||||||
// 登录
|
// 登录
|
||||||
export async function userLogin(params: any) {
|
export async function userLogin(params: any) {
|
||||||
console.log('paramsuserLogin', params);
|
const data = await request.post('/auth/admin/login', params)
|
||||||
|
|
||||||
const data = await request.post('/api/user/login', params)
|
|
||||||
// const data = await request.post('/auth/login', params)
|
|
||||||
console.log('data', data);
|
|
||||||
|
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//获取用户信息
|
//获取用户信息
|
||||||
export const retrieveUserInfo = (): Promise<API.UserInfoResponse> => (
|
export async function retrieveUserInfo(params: any) {
|
||||||
request.get('/api/user/info')
|
const data = await request.get('/auth/admin/profile', params)
|
||||||
);
|
return data
|
||||||
|
}
|
||||||
|
// export const retrieveUserInfo = (): Promise<API.UserInfoResponse> => (
|
||||||
|
// request.get('/api/user/info')
|
||||||
|
// );
|
||||||
|
|
||||||
//获取用户权限
|
//获取用户权限
|
||||||
export const retrieveUserAuthority = (): Promise<API.UserAuthorityResponse> => (
|
export async function retrieveUserAuthority(params: any) {
|
||||||
request.get('/api/user/authority')
|
const data = await request.get('/api/user/authority', params)
|
||||||
);
|
return data
|
||||||
|
}
|
||||||
|
// export const retrieveUserAuthority = (): Promise<API.UserAuthorityResponse> => (
|
||||||
|
// request.get('/api/user/authority')
|
||||||
|
// );
|
||||||
|
|
||||||
//获取菜单数据
|
//获取菜单数据
|
||||||
export const retrieveMenuData = (): Promise<API.MenuDataResponse> => (
|
export async function retrieveMenuData(params: any) {
|
||||||
request.get('/api/user/menu')
|
const data = await request.get('/menus', params)
|
||||||
);
|
return data
|
||||||
|
}
|
||||||
|
// export const retrieveMenuData = (): Promise<API.MenuDataResponse> => (
|
||||||
|
// request.get('/api/user/menu')
|
||||||
|
// );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//获取用户信息和权限以及菜单
|
//获取用户信息和权限以及菜单
|
||||||
export const retrieveUserInfoAuthorityMenu = (): Promise<API.UserInfoAuthMenuResponse> => (
|
export const retrieveUserInfoAuthorityMenu = (): Promise<API.UserInfoAuthMenuResponse> => (
|
||||||
Promise.all([
|
Promise.all([
|
||||||
retrieveUserInfo(),
|
retrieveUserInfo(),
|
||||||
retrieveUserAuthority(),
|
// retrieveUserAuthority(),
|
||||||
retrieveMenuData(),
|
retrieveMenuData(),
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
@ -44,14 +53,14 @@ export const retrieveUserInfoAuthorityMenu = (): Promise<API.UserInfoAuthMenuRes
|
|||||||
//获取用户权限以及菜单
|
//获取用户权限以及菜单
|
||||||
export const retrieveUserAuthorityMenu = (): Promise<API.UserAuthMenuResponse> => (
|
export const retrieveUserAuthorityMenu = (): Promise<API.UserAuthMenuResponse> => (
|
||||||
Promise.all([
|
Promise.all([
|
||||||
retrieveUserAuthority(),
|
// retrieveUserAuthority(),
|
||||||
retrieveMenuData(),
|
retrieveMenuData(),
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
|
||||||
//登出
|
//登出
|
||||||
export const userLogout = (): Promise<API.LogoutResponse> => (
|
export const userLogout = (): Promise<API.LogoutResponse> => (
|
||||||
request.post('/api/user/logout')
|
request.post('/auth/logout')
|
||||||
);
|
);
|
||||||
|
|
||||||
//获取验证码
|
//获取验证码
|
||||||
|
|||||||
@ -6,9 +6,9 @@ import CryptoJS from "crypto-js";
|
|||||||
|
|
||||||
const { UMI_APP_BASEURL } = process.env;
|
const { UMI_APP_BASEURL } = process.env;
|
||||||
|
|
||||||
const instance = axios.create({ baseURL: UMI_APP_BASEURL });
|
// const instance = axios.create({ baseURL: UMI_APP_BASEURL });
|
||||||
// const instance = axios.create({ baseURL: 'https://api.eshangtech.com/EShangApiMain' });
|
// const instance = axios.create({ baseURL: 'https://api.eshangtech.com/EShangApiMain' });
|
||||||
// const instance = axios.create({ baseURL: '/api' });
|
const instance = axios.create({ baseURL: '/auth' });
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -21,7 +21,8 @@ instance.interceptors.request.use(
|
|||||||
|
|
||||||
config.headers = {
|
config.headers = {
|
||||||
...config.headers,
|
...config.headers,
|
||||||
Authorization: localStorage.getItem('Authorization') || '',
|
Authorization: `Bearer ${localStorage.getItem('Authorization') || ''}`,
|
||||||
|
"Content-Type": "application/json;charset=utf-8"
|
||||||
} as AxiosRequestHeaders;
|
} as AxiosRequestHeaders;
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
@ -33,9 +34,8 @@ instance.interceptors.response.use(
|
|||||||
//状态码为2xx的时候执行
|
//状态码为2xx的时候执行
|
||||||
(response) => {
|
(response) => {
|
||||||
const { data } = response;
|
const { data } = response;
|
||||||
const { code } = data;
|
|
||||||
|
|
||||||
if (code !== 200) {
|
if (data.code !== 200) {
|
||||||
notification.error({
|
notification.error({
|
||||||
message: data.message,
|
message: data.message,
|
||||||
});
|
});
|
||||||
@ -43,46 +43,32 @@ instance.interceptors.response.use(
|
|||||||
|
|
||||||
const timestamp = getFormattedDate()
|
const timestamp = getFormattedDate()
|
||||||
|
|
||||||
// let res = JSON.parse(decryptAESECB(data.data, timestamp))
|
|
||||||
// return res;
|
|
||||||
// console.log('resdsa', data);
|
|
||||||
|
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
//状态码不为2xx的时候执行
|
//状态码不是2xx的时候执行
|
||||||
(error) => {
|
(error) => {
|
||||||
const { response } = error;
|
const { response } = error;
|
||||||
const { status } = response;
|
|
||||||
|
|
||||||
enum CodeMessage {
|
if (response && response.status === 401) {
|
||||||
'发出的请求有错误,服务器没有进行新建或修改数据的操作。' = 400,
|
// // 清除本地存储的token
|
||||||
'用户未登录。' = 401,
|
// localStorage.removeItem('Authorization');
|
||||||
'用户得到授权,但是访问是被禁止的。' = 403,
|
// // 重定向到登录页
|
||||||
'发出的请求针对的是不存在的记录,服务器没有进行操作。' = 404,
|
// window.location.href = '/user/login';
|
||||||
'请求的格式不可得。' = 406,
|
// notification.error({
|
||||||
'请求的资源被永久删除,且不会再得到的。' = 410,
|
// message: response?.data?.message || '请求失败',
|
||||||
'当创建一个对象时,发生一个验证错误。' = 422,
|
// description: error.message
|
||||||
'服务器发生错误,请检查服务器。' = 500,
|
// });
|
||||||
'网关错误。' = 502,
|
} else {
|
||||||
'服务不可用,服务器暂时过载或维护。' = 503,
|
notification.error({
|
||||||
'网关超时。' = 504
|
message: response?.data?.message || '请求失败',
|
||||||
}
|
description: error.message
|
||||||
|
|
||||||
notification.error({
|
|
||||||
message: response.data.message || CodeMessage[status],
|
|
||||||
});
|
|
||||||
|
|
||||||
if (status === 401) {
|
|
||||||
const {
|
|
||||||
_store: { dispatch },
|
|
||||||
} = getDvaApp();
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
type: 'user/resetLoginStatus',
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.reject(error);
|
return Promise.reject({
|
||||||
|
code: response?.status || 500,
|
||||||
|
message: response?.data?.message || '请求失败'
|
||||||
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user