Browse Source

first commit

main
郑州 3 years ago
commit
42ebe56857
44 changed files with 925 additions and 0 deletions
  1. +16
    -0
      .editorconfig
  2. +20
    -0
      .gitignore
  3. +8
    -0
      .prettierignore
  4. +11
    -0
      .prettierrc
  5. +25
    -0
      .umirc.ts
  6. +15
    -0
      README.md
  7. +8
    -0
      docs/appHeader.md
  8. +6
    -0
      docs/button.md
  9. +8
    -0
      docs/message.md
  10. +0
    -0
      mock/.gitkeep
  11. +44
    -0
      package.json
  12. +114
    -0
      src/app.ts
  13. +24
    -0
      src/components/AppHeader/AppHeader.tsx
  14. BIN
      src/components/AppHeader/assets/logo.png
  15. +9
    -0
      src/components/AppHeader/components/close.tsx
  16. +68
    -0
      src/components/AppHeader/components/icon.less
  17. +9
    -0
      src/components/AppHeader/components/minimize.tsx
  18. +9
    -0
      src/components/AppHeader/components/zoom.tsx
  19. +25
    -0
      src/components/AppHeader/index.less
  20. +1
    -0
      src/components/AppHeader/index.tsx
  21. +11
    -0
      src/components/Button/Button.tsx
  22. +1
    -0
      src/components/Button/index.ts
  23. +7
    -0
      src/global.less
  24. +29
    -0
      src/layouts/index.tsx
  25. +13
    -0
      src/layouts/indexLayout.less
  26. +24
    -0
      src/models/useAuthModel.ts
  27. +3
    -0
      src/pages/index.less
  28. +9
    -0
      src/pages/index.tsx
  29. +1
    -0
      src/pages/log/README.md
  30. +9
    -0
      src/pages/log/index.tsx
  31. +75
    -0
      src/pages/login/index.tsx
  32. +36
    -0
      src/pages/login/login.less
  33. +1
    -0
      src/pages/messages/README.md
  34. +9
    -0
      src/pages/messages/index.tsx
  35. +1
    -0
      src/pages/sync/README.md
  36. +9
    -0
      src/pages/sync/index.tsx
  37. +15
    -0
      src/services/API.d.ts
  38. +66
    -0
      src/services/user.ts
  39. +53
    -0
      src/utils/request.config.ts
  40. +18
    -0
      src/utils/request.ts
  41. +15
    -0
      src/utils/storage.ts
  42. +54
    -0
      src/utils/tool.ts
  43. +36
    -0
      tsconfig.json
  44. +10
    -0
      typings.d.ts

+ 16
- 0
.editorconfig View File

@@ -0,0 +1,16 @@
# http://editorconfig.org
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false

[Makefile]
indent_style = tab

+ 20
- 0
.gitignore View File

@@ -0,0 +1,20 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/npm-debug.log*
/yarn-error.log
/yarn.lock
/package-lock.json

# production
/dist

# misc
.DS_Store

# umi
/src/.umi
/src/.umi-production
/src/.umi-test
/.env.local

+ 8
- 0
.prettierignore View File

@@ -0,0 +1,8 @@
**/*.md
**/*.svg
**/*.ejs
**/*.html
package.json
.umi
.umi-production
.umi-test

+ 11
- 0
.prettierrc View File

@@ -0,0 +1,11 @@
{
"singleQuote": true,
"trailingComma": "all",
"printWidth": 80,
"overrides": [
{
"files": ".prettierrc",
"options": { "parser": "json" }
}
]
}

+ 25
- 0
.umirc.ts View File

@@ -0,0 +1,25 @@
import { defineConfig } from 'umi';

export default defineConfig({
nodeModulesTransform: {
type: 'none',
},
// routes: [
// { path: '/', component: '@/pages/index' },
// ],
fastRefresh: {},
theme: {
"primary-color": "#7850FF",
"app-header-height": "48px"
},
proxy: {
'/api': {
target: 'http://139.198.180.242:9003',
// target: 'http://www.lockingos.org:9003',
//target: 'http://192.168.8.114:8082',
changeOrigin: true,
secure: false,
}
}

});

+ 15
- 0
README.md View File

@@ -0,0 +1,15 @@
# umi project

## Getting Started

Install dependencies,

```bash
$ yarn
```

Start the dev server,

```bash
$ yarn start
```

+ 8
- 0
docs/appHeader.md View File

@@ -0,0 +1,8 @@
### 页面顶部导航栏

```jsx
import React from 'react';
import AppHeader from '@/components/AppHeader/AppHeader';

export default () => <AppHeader style={{ position: 'relative' }} />
```

+ 6
- 0
docs/button.md View File

@@ -0,0 +1,6 @@
```jsx
import React from 'react';
import AButton from '@/components/Button/Button';

export default () => <AButton type="primary">Hello dumi!</AButton>;
```

+ 8
- 0
docs/message.md View File

@@ -0,0 +1,8 @@
```jsx
import React from 'react';
import { message, Button } from 'antd';

export default () => (
<Button onClick={() => message.success('成功提示')} >成功按钮</Button>
)
```

+ 0
- 0
mock/.gitkeep View File


+ 44
- 0
package.json View File

@@ -0,0 +1,44 @@
{
"private": true,
"scripts": {
"start": "umi dev",
"build": "umi build",
"postinstall": "umi generate tmp",
"prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'",
"test": "umi-test",
"test:coverage": "umi-test --coverage"
},
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"*.{js,jsx,less,md,json}": [
"prettier --write"
],
"*.ts?(x)": [
"prettier --parser=typescript --write"
]
},
"dependencies": {
"@ant-design/icons": "^4.6.2",
"@ant-design/pro-layout": "^6.5.0",
"@types/lodash": "^4.14.170",
"@umijs/preset-react": "1.x",
"antd": "^4.16.5",
"classnames": "^2.3.1",
"lodash": "^4.17.21",
"umi": "^3.4.25"
},
"devDependencies": {
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"@umijs/preset-dumi": "^1.1.20",
"@umijs/test": "^3.4.25",
"lint-staged": "^10.0.7",
"prettier": "^2.2.0",
"react": "17.x",
"react-dom": "17.x",
"typescript": "^4.1.2",
"yorkie": "^2.0.0"
}
}

+ 114
- 0
src/app.ts View File

@@ -0,0 +1,114 @@
import { history, RequestConfig } from 'umi';
import { ResponseError } from 'umi-request';
import { notification } from 'antd';
import { firstCharToLowerCase, handleRequest } from './utils/tool';
import { isObject } from 'lodash';
import { logout, queryCurrent } from './services/user';

const codeMessage = {
200: '服务器成功返回请求的数据。',
201: '新建或修改数据成功。',
202: '一个请求已经进入后台排队(异步任务)。',
204: '删除数据成功。',
400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
401: '用户没有权限(令牌、用户名、密码错误)。',
403: '用户得到授权,但是访问是被禁止的。',
404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
405: '请求方法不被允许。',
406: '请求的格式不可得。',
410: '请求的资源被永久删除,且不会再得到的。',
422: '当创建一个对象时,发生一个验证错误。',
500: '服务器发生错误,请检查服务器。',
502: '网关错误。',
503: '服务不可用,服务器暂时过载或维护。',
504: '网关超时。',
};

/**
* 异常处理程序
*/
const errorHandler = (error: ResponseError) => {
const { response, data } = error;
if (response && response.status) {
const errorText = codeMessage[response.status] || response.statusText;
const { status, url } = response;

notification.error({
message: `请求错误 ${status}: ${url}`,
description: errorText,
});
return {
code: response.status,
message: errorText,
}
}
if (data && typeof data === 'object' && ('error' in data)) return data;
// todo 报错都不走error, 改为构建成data;
if (!response) {
notification.error({
description: '您的网络发生异常,无法连接服务器',
message: '网络异常',
});
}
// throw error;
return {
code: 'err',
message: '网络异常',
}
};


export const request: RequestConfig = {
errorConfig: {
adaptor: (resData, ctx) => {
const { Code, Data, Msg } = resData;
if ('Code' in resData) { resData.code = Code; delete resData.Code; }
if ('Data' in resData) {
resData.data = Data;
if (isObject(Data)) {
resData.data = firstCharToLowerCase(Data);
}
delete resData.Data;
}
if ('Msg' in resData) { resData.message = Msg; delete resData.Msg; };
if (!('success' in resData)) { // http请求是否成功
// console.log('adpator log:', resData);
resData.success = true;
}
if ('code' in resData) { // 业务请求是否成功
resData.requestIsSuccess = resData.code === null || resData.code === 0 || resData.code === '0';
}
return resData;
},
},
credentials: "same-origin",
// errorHandler,
errorHandler,
};


export async function getInitialState() {
async function fetchUserInfo() {
const res = await queryCurrent();
handleRequest(res)
.error(() => logout())
.httpError(() => logout());

return res.data;
}

// 如果是登录页面,不执行
if (history.location.pathname !== '/login') {
const currentUser = await fetchUserInfo();
if(!currentUser) {
logout();
}
return {
fetchUserInfo,
currentUser,
};
}
return {
fetchUserInfo,
};
}

+ 24
- 0
src/components/AppHeader/AppHeader.tsx View File

@@ -0,0 +1,24 @@
import React from 'react';
import styles from './index.less';
import css from 'classnames';
import CloseIcon from './components/close';
import MinimizeIcon from './components/minimize';
import ZoomIcon from './components/zoom';
import logoImg from './assets/logo.png';

export default function AppHeader(props) {
const { className, style } = props;
return (
<div className={css(styles.appHeader, className)} style={style}>
<div className={styles.left}>
<img src={logoImg} alt="" />
</div>
<div className={styles.right}>
<div className={styles.split} />
<MinimizeIcon className={styles.mr12} />
<ZoomIcon className={styles.mr12} />
<CloseIcon className={styles.mr12} />
</div>
</div>
)
}

BIN
src/components/AppHeader/assets/logo.png View File

Before After
Width: 160  |  Height: 48  |  Size: 3.3 KiB

+ 9
- 0
src/components/AppHeader/components/close.tsx View File

@@ -0,0 +1,9 @@
import classNames from 'classnames';
import React from 'react';
import styles from './icon.less';

export default function CloseIcon(props) {
return (
<div {...props} className={classNames(styles.close, props.className)} />
)
}

+ 68
- 0
src/components/AppHeader/components/icon.less View File

@@ -0,0 +1,68 @@

.icon {
position: relative;
display: inline-block;
width: 20px;
height: 20px;
cursor: pointer;
}

.beCenter {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}

.close {
.icon();
&:before, &:after {
content: '';
.beCenter();
width: 14px;
height: 2px;
background-color: #A7A8B7;
}
&:before { transform: rotate(45deg); }
&:after { transform: rotate(-45deg); }
&:hover {
&:before, &:after {
background-color: @primary-color;
}
}
}

.minimize {
.icon();
&:before {
content: '';
.beCenter();
width: 14px;
height: 2px;
background-color: #A7A8B7;
}
&:hover {
&:before {
background-color: @primary-color;
}
}
}

.zoom {
.icon();
&:before {
content: '';
.beCenter();
width: 14px;
height:14px;
border: 1px solid #A7A8B7;
border-top-width: 2px;
}
&:hover {
&:before {
border-color: @primary-color;
}
}
}

+ 9
- 0
src/components/AppHeader/components/minimize.tsx View File

@@ -0,0 +1,9 @@
import React from 'react';
import classNames from 'classnames';
import styles from './icon.less';

export default function MinimizeIcon(props) {
return (
<div {...props} className={classNames(styles.minimize, props.className)} />
)
}

+ 9
- 0
src/components/AppHeader/components/zoom.tsx View File

@@ -0,0 +1,9 @@
import React from 'react';
import classNames from 'classnames';
import styles from './icon.less';

export default function ZoomIcon(props) {
return (
<div {...props} className={classNames(styles.zoom, props.className)} />
)
}

+ 25
- 0
src/components/AppHeader/index.less View File

@@ -0,0 +1,25 @@
.appHeader {
position: fixed;
height: @app-header-height;
display: flex;
top: 0;
width: 100%;
justify-content: space-between;
align-items: center;
flex-direction: row;
box-shadow: 0px 0px 0px 0px #EEF2F5;
background-color: #fff;
}
.left, .right {
flex: none;
line-height: 0;
.mr16 { margin-right: 16px; }
.mr12 { margin-right: 12px;}
.split {
display: inline-block;
width: 1px;
height: 16px;
.mr16();
background-color: rgba(#000, 0.1);
}
}

+ 1
- 0
src/components/AppHeader/index.tsx View File

@@ -0,0 +1 @@
export { default } from './AppHeader';

+ 11
- 0
src/components/Button/Button.tsx View File

@@ -0,0 +1,11 @@
import React from 'react';
import { Button, ButtonProps } from 'antd';

interface AButtonProps extends ButtonProps {}

export default function AButton(props: AButtonProps) {

return (
<Button {...props} />
)
}

+ 1
- 0
src/components/Button/index.ts View File

@@ -0,0 +1 @@
export { default } from './Button';

+ 7
- 0
src/global.less View File

@@ -0,0 +1,7 @@
// @app-header-height: 48px;
body {
color: red;
}
#root {
height: 100%;
}

+ 29
- 0
src/layouts/index.tsx View File

@@ -0,0 +1,29 @@
import { useModel } from 'umi';
import AppHeader from '@/components/AppHeader';
import { RouteProps } from 'react-router';
import React from 'react';
import styles from './indexLayout.less';

export default function IndexLayout(props: RouteProps) {
const { isLogin } = useModel('useAuthModel');
const isLoginView = props.location
return (
<div className={styles.app}>
<AppHeader className={styles.header} />
<main className={styles.main}>
{
isLogin
? (
<div className={styles.nav}>

</div>
)
: null
}
<div className={styles.content}>
{isLogin || isLoginView ? props.children : null}
</div>
</main>
</div>
)
}

+ 13
- 0
src/layouts/indexLayout.less View File

@@ -0,0 +1,13 @@
.app {
height: 100%;
padding-top: @app-header-height;
}
.main {
display: flex;
flex-direction: row;
height: 100%;

.content {
flex: 1;
}
}

+ 24
- 0
src/models/useAuthModel.ts View File

@@ -0,0 +1,24 @@
import { useCallback, useState } from "react";

export default function useAuthModel() {
const [isLogin, setLoginState] = useState(false);
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(false);

const signin = useCallback((account, password) => {
setLoading(true);

setLoading(false);
}, []);

const signout = useCallback(() => {
}, [])

return {
isLogin,
user,
signin,
signout,
}
}

+ 3
- 0
src/pages/index.less View File

@@ -0,0 +1,3 @@
.title {
background: rgb(121, 242, 157);
}

+ 9
- 0
src/pages/index.tsx View File

@@ -0,0 +1,9 @@
import styles from './index.less';

export default function IndexPage() {
return (
<div>
<h1 className={styles.title}>Page index</h1>
</div>
);
}

+ 1
- 0
src/pages/log/README.md View File

@@ -0,0 +1 @@
# 操作日志

+ 9
- 0
src/pages/log/index.tsx View File

@@ -0,0 +1,9 @@
import React from 'react'

export default function LogView() {
return (
<div>
操作日志界面
</div>
)
}

+ 75
- 0
src/pages/login/index.tsx View File

@@ -0,0 +1,75 @@
import React, { useState } from 'react';
import { Input, Button } from 'antd';
import styles from './login.less';
import { history, useModel } from 'umi';
import { MobileFilled, LockFilled } from '@ant-design/icons';
import css from 'classnames';
import { useCallback } from 'react';
import { useEffect } from 'react';
import { login } from '@/services/user';
import { handleRequest } from '@/utils/tool';

export default function Login() {
const [errText, setErrText] = useState('');
const [account, setAccount] = useState('');
const [password, setPassword] = useState('');
const [loading, setLoading] = useState(false);

// const { loading, signin } = useModel('useAuthModel');

const onLogin = useCallback(async () => {
if(!account) { setErrText('账号/手机号不能为空'); return;}
if (!password) { setErrText('密码不能为空'); return; }
setLoading(true);
const res = await login(account, password);
setLoading(false);
handleRequest(res)
.error(() => {
setErrText(res.message!);
})
.success(() => {
// history.push('/');
window.location.href = '/';
})
// if(!isReqSuccess(res)) {
// setErrText(res.msg);
// return;
// }
// Taro.switchTab({ url: '/pages/project/index' });
// Taro.navigateTo({ url: '/pages/project/index' });
}, [account, password]);

useEffect(() => {
setErrText('');
}, [account, password])

return (
<div className={styles.login}>
<div className={styles.title}>
<div>欢迎使用</div>
<div>locking</div>
</div>
<div className={styles.form}>
<Input
size="large"
prefix={<MobileFilled className={styles.icon} />}
disabled={loading}
className={styles.mb24}
value={account}
onChange={e => setAccount(e.target.value)}
/>
<Input
size="large"
prefix={<LockFilled className={styles.icon} />}
type="password"
disabled={loading}
className={styles.mb4}
value={password}
onChange={e => setPassword(e.target.value)}
/>
<div className={styles.errText}>{errText}</div>
<Button loading={loading} type="primary" block onClick={onLogin} >登录</Button>
</div>
</div>
)
}

+ 36
- 0
src/pages/login/login.less View File

@@ -0,0 +1,36 @@
.login {
height: 100%;
background: linear-gradient(270deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.24) 47%, rgba(0, 0, 0, 0.3) 100%);
.title {
position: absolute;
left: 60px;
top: 88px;
font-size: 36px;
color: #fff;
line-height: 48px;
}
.form {
position: absolute;
left: 60px;
bottom: 53px;
width: 290px;

.errText {
height: 20px;
line-height: 20px;
padding: 0 16px;
border-radius: 2px;
color: #fff;
margin-bottom: 12px;
&:not(:empty) {
background-color: #D6243A;
}
}
.mb24 { margin-bottom: 24px; }
.mb4 { margin-bottom: 4px; }
}
.icon {
color: @primary-color;
font-size: 24px;
}
}

+ 1
- 0
src/pages/messages/README.md View File

@@ -0,0 +1 @@
# 消息通知

+ 9
- 0
src/pages/messages/index.tsx View File

@@ -0,0 +1,9 @@
import React from 'react'

export default function MessagesView() {
return (
<div>
消息通知界面
</div>
)
}

+ 1
- 0
src/pages/sync/README.md View File

@@ -0,0 +1 @@
# 同步任务

+ 9
- 0
src/pages/sync/index.tsx View File

@@ -0,0 +1,9 @@
import React from 'react'

export default function SyncView() {
return (
<div>
同步任务界面
</div>
)
}

+ 15
- 0
src/services/API.d.ts View File

@@ -0,0 +1,15 @@
declare namespace API {
export interface ResponseData<T> {
code: number | string;
data: T;
message?: string;
/**
* 用于表明http请求是否成功
*/
success: boolean;
/**
* 用于标明业务请求内容是否成功, 等价于code === 0
*/
requestIsSuccess: boolean;
}
}

+ 66
- 0
src/services/user.ts View File

@@ -0,0 +1,66 @@
import { history } from '@/.umi/core/history';
import { fetchApi } from '@/utils/request';
import storage from '@/utils/storage';
import { errorReponse, firstCharToLowerCase, isReqSuccess } from '@/utils/tool';
import { propertyOf } from 'lodash';

export async function queryCurrent() {
const accountId = storage.get('accountId');
if(!accountId) {
return errorReponse('');
}
const res = await fetchApi<API.ResponseData<any>>('user/queryUserByUserId', { id: accountId });

// const data = firstCharToLowerCase(Object.assign({}, propertyOf(res)('Data.UserExt', {}), res.data || {}));
// data.roleName = roleMap[data.permission] || '';
// data.backgroundRoleName = consoleRoleMap[data.backgroundPermission] || '';
// data.userState = stateMap[data.staffStatus] || '';
// data.isDeparture = data.staffStatus;
return res;
}

export async function login(account: string, password: string) {
const res = await fetchApi('authentication/login', { UserName: account, Password: password }, { silent: true });
if (!isReqSuccess(res)) {
// dispatch(logout());
return res;
}
const userData = res.data;

const isSuperAdmin = userData.backgroundPermission === 3;
if (isSuperAdmin) {
return errorReponse('该账号没有访问权限');
}

// const companyInfoRes = await fetchApi('company/queryFrontDeskCompanyById', { id: userData.companyId }, { silent: true });
// if (!isReqSuccess(companyInfoRes)) {
// return companyInfoRes;
// }


// const { data: { company: { SoftwareVersion } = {} } = {} } = companyInfoRes;

// 角色判断
// const { app: appStore } = getState();
// if (appStore.appType && userData.userType !== appStore.appType) { // 登录角色权限不符合,退出登录
// hint('账号权限不足');
// dispatch(logout());
// return false;
// }
// const payload = {
// accountId: userData.id,
// accountName: userData.cnName,
// customerId: userData.companyId,
// avatorUrl: userData.headImgUrl,
// isMini: SoftwareVersion === 'Mini',
// };
storage.set('accountId', userData.id);
storage.set('companyId', userData.companyId);
// storage.set('isMini', payload.isMini);
return res;
}

export function logout() {
storage.clear();
history.replace('/login');
}

+ 53
- 0
src/utils/request.config.ts View File

@@ -0,0 +1,53 @@
const pmsServiceMap = ['template', 'project', 'folder', 'file', 'templateCompany', 'projectLinkInvite', 'lockingmsg']
.reduce((h: { [key: string]: 'pms' | undefined }, str) => (h[str] = 'pms', h), {});

const postRequestMap = [
'authentication/login',
'authentication/passwordCheck',
'company/addCompany',
'company/queryGeneralOverview',
'company/queryProviceTree',
'company/updateCompanyById',
'company/link/addCompanyLink',
'company/link/updateCompanyLink',
'dept/addDept',
'dept/updateDept',
'user/addUser',
'user/resetPassWord',
'user/updateUser',
'template/createTemplate',
'template/fileExchange',
'template/updateTemplate',
'template/uploadingXmind',
'template/addTemplateNodeModelFile',
'template/createNestedRelevance',
'template/connectNestTemplateFolder',
"folder/createSubfolder",
"project/createProject",
"project/editProject",
"project/assignedWork",
"file/addArchMilesStone",
"file/addFile",
"file/updateFile",
"file/fileCoordinationChange",
"file/setShareFile",
"operation/record",
"file/updateProjArchiveHistory",
"templateCompany/addTemplateCompany",
"project/addProjectGobalConfig",
"project/linkProject",
'file/submitDeliverables',
'lockingmsg/markRead',
'file/removeFromRecycleBin',
'file/batchAddFile',
].reduce((h: { [key: string]: 'POST' | 'GET' }, str) => (h[str] = 'POST', h), {});


export function parseRequest(path: string): ['POST' | 'GET', string] {
const [service] = path.split('/');
const prefix = pmsServiceMap[service] || 'cms';
const fullpath = `api/${prefix}/${service === 'authentication' ? '' : 'v1/'}${path}`;
const method = postRequestMap[path] || 'GET';

return [method, fullpath];
}

+ 18
- 0
src/utils/request.ts View File

@@ -0,0 +1,18 @@
import { message } from 'antd';
import { request } from 'umi';
import { parseRequest } from './request.config';
import { firstCharToLowerCase, handleRequest } from './tool';


export async function fetchApi<T = any>(path: string, params = {}, options = { silent: false }) {
const [method, fullpath] = parseRequest(path);
const { silent, ...restOptions } = options;
const res = await request<API.ResponseData<T>>(fullpath, { method, [method === 'GET' ? 'params' : 'data']: params, ...restOptions });
if(!silent) {
handleRequest(res)
.error(() => {
message.error(res.message);
})
}
return res;
}

+ 15
- 0
src/utils/storage.ts View File

@@ -0,0 +1,15 @@


const storage = {
get(key: string) {
return sessionStorage.getItem(key);
},
set(key: string, value: string) {
sessionStorage.setItem(key, value);
},
clear() {
sessionStorage.clear();
}
}

export default storage;

+ 54
- 0
src/utils/tool.ts View File

@@ -0,0 +1,54 @@
export function firstCharToLowerCase(obj: any) {
return Object.entries(obj).reduce((o: { [key: string]: any }, [key, value]) => {
o[`${key[0].toLocaleLowerCase()}${key.slice(1)}`] = value;
return o;
},{});
}

export function firstCharToUpperCase(obj) {
return Object.entries(obj).reduce((o: { [key: string]: any }, [key, value]) => {
o[`${key[0].toLocaleUpperCase()}${key.slice(1)}`] = value;
return o;
},{});
}

export const isReqSuccess = (res: any) => res.code === 0 || res.Code === 0;


class RequestHandler {
constructor(public response: API.ResponseData<any>) {
this.response = response;
}
success(f: () => void) {
const res = this.response;
if (!res.success) { return this; }
if (!isReqSuccess(res)) { return this; }
f();
return this;
}
error(f: () => void) {
const res = this.response;
if (!res.success) { return this; }
if (isReqSuccess(res)) { return this; }
f();
return this;
}
httpError(f: () => void) {
const res = this.response;
if (res.success) { return this; }
f();
return this;
}
}

export const handleRequest = (res: API.ResponseData<any>) => new RequestHandler(res);

export function errorReponse(message: string, code = 'err'): API.ResponseData<null> {
return {
code,
data: null,
success: true,
requestIsSuccess: false,
message,
}
}

+ 36
- 0
tsconfig.json View File

@@ -0,0 +1,36 @@
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"moduleResolution": "node",
"importHelpers": true,
"jsx": "react-jsx",
"esModuleInterop": true,
"sourceMap": true,
"baseUrl": "./",
"strict": true,
"paths": {
"@/*": ["src/*"],
"@@/*": ["src/.umi/*"]
},
"allowSyntheticDefaultImports": true
},
"include": [
"mock/**/*",
"src/**/*",
"config/**/*",
".umirc.ts",
"typings.d.ts"
],
"exclude": [
"node_modules",
"lib",
"es",
"dist",
"typings",
"**/__test__",
"test",
"docs",
"tests"
]
}

+ 10
- 0
typings.d.ts View File

@@ -0,0 +1,10 @@
declare module '*.css';
declare module '*.less';
declare module '*.png';
declare module '*.svg' {
export function ReactComponent(
props: React.SVGProps<SVGSVGElement>,
): React.ReactElement;
const url: string;
export default url;
}

Loading…
Cancel
Save