From 42ebe568573e24ceb31f4c8fc8148fe739f24edf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=91=E5=B7=9E?= Date: Mon, 28 Jun 2021 17:53:59 +0800 Subject: [PATCH] first commit --- .editorconfig | 16 +++ .gitignore | 20 +++ .prettierignore | 8 ++ .prettierrc | 11 ++ .umirc.ts | 25 ++++ README.md | 15 +++ docs/appHeader.md | 8 ++ docs/button.md | 6 + docs/message.md | 8 ++ mock/.gitkeep | 0 package.json | 44 +++++++ src/app.ts | 114 ++++++++++++++++++ src/components/AppHeader/AppHeader.tsx | 24 ++++ src/components/AppHeader/assets/logo.png | Bin 0 -> 3350 bytes src/components/AppHeader/components/close.tsx | 9 ++ src/components/AppHeader/components/icon.less | 68 +++++++++++ .../AppHeader/components/minimize.tsx | 9 ++ src/components/AppHeader/components/zoom.tsx | 9 ++ src/components/AppHeader/index.less | 25 ++++ src/components/AppHeader/index.tsx | 1 + src/components/Button/Button.tsx | 11 ++ src/components/Button/index.ts | 1 + src/global.less | 7 ++ src/layouts/index.tsx | 29 +++++ src/layouts/indexLayout.less | 13 ++ src/models/useAuthModel.ts | 24 ++++ src/pages/index.less | 3 + src/pages/index.tsx | 9 ++ src/pages/log/README.md | 1 + src/pages/log/index.tsx | 9 ++ src/pages/login/index.tsx | 75 ++++++++++++ src/pages/login/login.less | 36 ++++++ src/pages/messages/README.md | 1 + src/pages/messages/index.tsx | 9 ++ src/pages/sync/README.md | 1 + src/pages/sync/index.tsx | 9 ++ src/services/API.d.ts | 15 +++ src/services/user.ts | 66 ++++++++++ src/utils/request.config.ts | 53 ++++++++ src/utils/request.ts | 18 +++ src/utils/storage.ts | 15 +++ src/utils/tool.ts | 54 +++++++++ tsconfig.json | 36 ++++++ typings.d.ts | 10 ++ 44 files changed, 925 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 .prettierignore create mode 100644 .prettierrc create mode 100644 .umirc.ts create mode 100644 README.md create mode 100644 docs/appHeader.md create mode 100644 docs/button.md create mode 100644 docs/message.md create mode 100644 mock/.gitkeep create mode 100644 package.json create mode 100644 src/app.ts create mode 100644 src/components/AppHeader/AppHeader.tsx create mode 100644 src/components/AppHeader/assets/logo.png create mode 100644 src/components/AppHeader/components/close.tsx create mode 100644 src/components/AppHeader/components/icon.less create mode 100644 src/components/AppHeader/components/minimize.tsx create mode 100644 src/components/AppHeader/components/zoom.tsx create mode 100644 src/components/AppHeader/index.less create mode 100644 src/components/AppHeader/index.tsx create mode 100644 src/components/Button/Button.tsx create mode 100644 src/components/Button/index.ts create mode 100644 src/global.less create mode 100644 src/layouts/index.tsx create mode 100644 src/layouts/indexLayout.less create mode 100644 src/models/useAuthModel.ts create mode 100644 src/pages/index.less create mode 100644 src/pages/index.tsx create mode 100644 src/pages/log/README.md create mode 100644 src/pages/log/index.tsx create mode 100644 src/pages/login/index.tsx create mode 100644 src/pages/login/login.less create mode 100644 src/pages/messages/README.md create mode 100644 src/pages/messages/index.tsx create mode 100644 src/pages/sync/README.md create mode 100644 src/pages/sync/index.tsx create mode 100644 src/services/API.d.ts create mode 100644 src/services/user.ts create mode 100644 src/utils/request.config.ts create mode 100644 src/utils/request.ts create mode 100644 src/utils/storage.ts create mode 100644 src/utils/tool.ts create mode 100644 tsconfig.json create mode 100644 typings.d.ts diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..7e3649a --- /dev/null +++ b/.editorconfig @@ -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 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bee1cf6 --- /dev/null +++ b/.gitignore @@ -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 diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..0d4222f --- /dev/null +++ b/.prettierignore @@ -0,0 +1,8 @@ +**/*.md +**/*.svg +**/*.ejs +**/*.html +package.json +.umi +.umi-production +.umi-test diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..94beb14 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,11 @@ +{ + "singleQuote": true, + "trailingComma": "all", + "printWidth": 80, + "overrides": [ + { + "files": ".prettierrc", + "options": { "parser": "json" } + } + ] +} diff --git a/.umirc.ts b/.umirc.ts new file mode 100644 index 0000000..3e52fdc --- /dev/null +++ b/.umirc.ts @@ -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, + } + } + +}); diff --git a/README.md b/README.md new file mode 100644 index 0000000..07afeb7 --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +# umi project + +## Getting Started + +Install dependencies, + +```bash +$ yarn +``` + +Start the dev server, + +```bash +$ yarn start +``` diff --git a/docs/appHeader.md b/docs/appHeader.md new file mode 100644 index 0000000..6443422 --- /dev/null +++ b/docs/appHeader.md @@ -0,0 +1,8 @@ +### 页面顶部导航栏 + +```jsx +import React from 'react'; +import AppHeader from '@/components/AppHeader/AppHeader'; + +export default () => +``` \ No newline at end of file diff --git a/docs/button.md b/docs/button.md new file mode 100644 index 0000000..fd2ea22 --- /dev/null +++ b/docs/button.md @@ -0,0 +1,6 @@ +```jsx +import React from 'react'; +import AButton from '@/components/Button/Button'; + +export default () => Hello dumi!; +``` \ No newline at end of file diff --git a/docs/message.md b/docs/message.md new file mode 100644 index 0000000..6e1ccfa --- /dev/null +++ b/docs/message.md @@ -0,0 +1,8 @@ +```jsx +import React from 'react'; +import { message, Button } from 'antd'; + +export default () => ( + +) +``` \ No newline at end of file diff --git a/mock/.gitkeep b/mock/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/package.json b/package.json new file mode 100644 index 0000000..d7b88ed --- /dev/null +++ b/package.json @@ -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" + } +} diff --git a/src/app.ts b/src/app.ts new file mode 100644 index 0000000..bfea198 --- /dev/null +++ b/src/app.ts @@ -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, + }; +} \ No newline at end of file diff --git a/src/components/AppHeader/AppHeader.tsx b/src/components/AppHeader/AppHeader.tsx new file mode 100644 index 0000000..4c7ec52 --- /dev/null +++ b/src/components/AppHeader/AppHeader.tsx @@ -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 ( +
+
+ +
+
+
+ + + +
+
+ ) +} \ No newline at end of file diff --git a/src/components/AppHeader/assets/logo.png b/src/components/AppHeader/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b2f84c5d1ca9970829e8d049d32e6d3c5739bbf0 GIT binary patch literal 3350 zcmV+x4e9cUP)001xu1^@s6mZ@=W000c#Nkl?XS)AP6WBz|FlYgQ0+hiuGBM(m_#7l&PIkTCJ5bf>02s>d4XoAa93P#yb46_LJ&9-ADEmLdsSa@H+!|!^oB8Lk3JbKdz5; zFKrrC1fU_+i8|#@PX$gHK-=NCk#2#&qNr7Bndt}n9t&?So#Tn0dg>N%aqWgZ_w|U? z%{%APs&N-RbF_EYA&Wh$@chFN*6As!GphC|kQM;B!`VeNR}dbK?>u5QhPIT>J+eKp zqz6Eq+p`6mR=8=~-p8sxEc;7$f^}B3-6sG{YtICovZuEK83iyl^<#|{wQE0{8q%xQ z^to8QCzQ$=Fjlv|@yny{?VQ$F_SGBb0a)=J0dy&fqH>#3%C7=}z_F7pOF=cmr*vW#f>l(Kc_Z#WDzCY1;R8{p8k+dx9P#a^;@%#OQB9TZJ z(=;n8Dk>^dnO7#uqz%CP3uzVs3r{xKio=@^)imrE!_U8+oro4EWaz+KYsQawfx|0p zrplU+syCE8u%hDdhPmw(#OL$%ky3ui^@I?&YMS;^qBayoxd6bQ0Zaf8J32%-j6_5a z7>2R4je3)a=s_XGg|U1hs*zGY(b(8Hzp}FOxS}Xm0NBF$rfC+GmzUe&Cq+@Fa&&J+OoR?@LvFPbzNW6UQN?gK5YQb1IeaB+(zFlAX}@XDdq(Ou+;O$ zSB)F~WT&p32gC$wsZYRBm%t;34`A8Tp9&7=v@4|opsK3Z5YZa|y0y`G2*9s&UH?~H zzEBi}LAbq*I=kxX>MpOYuC7l6prR;a0K5wzM+ot(rfGL@JIMefqT?=?>*7El&=OaT z!h8aNY?T4512CwKF_I9XSktt}+a+q63a1Ug*m&k$OWi_V%n^hc05}NUW?Hvv`oT~2 zmk6D0?#6ZIrHBY)!%i_$pBPUbpR3Vidu(qUJ%nX z*Lpl2(=^S|rfDvSS~rGpl&I)%WjYJ|`uGH;z=UJ9D*|Mw`gTY`h z3dgrBpp?=QLVO5-9j*1cu8)hxN|OQ@)nT_~S)+o%AdksT2`nHVJw667f}xdC&I^ab zuejarBLId=DIWzeR7yFfHO${t>-N@5JAknP{OM-8AY$T00GFL?P_^~@kF42oM{~uI zP4=0GQ?C2$n(-r^D;tz|^VEfJh=ki-dnTF;!2JCDr-Tqwh^W%CtRIz^m)qNQ+`^s> z;3EKoiRdlEFm8-)YX^AC1F&4z_30-YQ@jNfLR>*atc@SQzDOi;>45_WYGd`2SU}!7 z4+G#2_X%CsTb#1i0OsfC|5^ya$BhUPjWG;^LuTj)uk)-;We z4kuVZMN#+;{(1nf=(_&PSRbmY{y+$E!tNA_L`vc zp7y!RvdqXQfu)Bwl|IfgWrIk~yHymfIJ27rNl zh=?{ChA}$XO2k{h__9KXC7PzqY!86Cu1i%_|G~~i)Y-X6)3l1#7En=?eSG#KqA7-9 zv^XuQs%k`}v>vk%;&M&XK1eo~bmnIiz~Tusi6mYUfGg3U*$I)tZC-idBlVZ~XPzsi z+s)+~n`(}&+j;kWC10$3IvtZenFY+t%j@a!c-R867dqT93_c5w3#gP+Q|o03bUCWBJ@CrMxH}{A3o80rdHNUMVG??}oB>t?T+|MNxPg zZ}EZ^MPW~SFn~LCUAH~$sHN1|*J(XgBD%^j4BJ!hsFYCvc@ndWXt*H!6~NW4Cl%)f zql>q1^|&8COX_*o9RT6(g{wr`zQkl_Kt)kF9@dvHb#z@%7)nxA^*4NOP4hY;;&UQ3H#hh1=-6P!0gO$0 zb|Hnt|6^@I_)ERhP*Y#h-2cEgEs;V=I=-NmmGSTgJGicw614ctX@AFYkN_k5l z5U}4lrV3!R>@*?7G9t2r-a-ghEDoruYEkqfAtL&@VHoz?%D8!Pz?&VD;Y76EFpM9k zQ}M#I{i>MLw%~PvbN(`VKD9spv0Ok|X+SnMv;c$r%f;=7%d)o{c-+CJ`jq-Y+;*w`UR6o|I16o7*b z4Gn{n4M!WabK@qSX$zPTK>m>z((CoIRp5|?9hW4cBSMJR-EQ}zWo2bw zBw8S!&-W84C0j}MhI78DMtr_oZWzY%{O`7|;-VI84iWJgu8D})!ya{#t2n+3=9lN+ zN{XWV6u^JjM{0c)S5Q!p8w!Q)B%r){y*uzb6ujh+r_tZL~auh%dyC z8k(D%&nho3XOBMXPue;Tz(TU`DdWX3skzxDa%`c)kz>ap%WWO}A)8E$gt{6LfSx!OTExg@rB!NGq3olHB0SCZj3OV^1Rlor-qw+e9CsV)y gFquM5enu7eANwPji-`zKNdN!<07*qoM6N<$f*y=dwEzGB literal 0 HcmV?d00001 diff --git a/src/components/AppHeader/components/close.tsx b/src/components/AppHeader/components/close.tsx new file mode 100644 index 0000000..c7165d2 --- /dev/null +++ b/src/components/AppHeader/components/close.tsx @@ -0,0 +1,9 @@ +import classNames from 'classnames'; +import React from 'react'; +import styles from './icon.less'; + +export default function CloseIcon(props) { + return ( +
+ ) +} \ No newline at end of file diff --git a/src/components/AppHeader/components/icon.less b/src/components/AppHeader/components/icon.less new file mode 100644 index 0000000..3e24bd5 --- /dev/null +++ b/src/components/AppHeader/components/icon.less @@ -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; + } + } +} \ No newline at end of file diff --git a/src/components/AppHeader/components/minimize.tsx b/src/components/AppHeader/components/minimize.tsx new file mode 100644 index 0000000..42e2ac1 --- /dev/null +++ b/src/components/AppHeader/components/minimize.tsx @@ -0,0 +1,9 @@ +import React from 'react'; +import classNames from 'classnames'; +import styles from './icon.less'; + +export default function MinimizeIcon(props) { + return ( +
+ ) +} \ No newline at end of file diff --git a/src/components/AppHeader/components/zoom.tsx b/src/components/AppHeader/components/zoom.tsx new file mode 100644 index 0000000..f530b85 --- /dev/null +++ b/src/components/AppHeader/components/zoom.tsx @@ -0,0 +1,9 @@ +import React from 'react'; +import classNames from 'classnames'; +import styles from './icon.less'; + +export default function ZoomIcon(props) { + return ( +
+ ) +} \ No newline at end of file diff --git a/src/components/AppHeader/index.less b/src/components/AppHeader/index.less new file mode 100644 index 0000000..be397c2 --- /dev/null +++ b/src/components/AppHeader/index.less @@ -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); + } +} \ No newline at end of file diff --git a/src/components/AppHeader/index.tsx b/src/components/AppHeader/index.tsx new file mode 100644 index 0000000..5aba1b1 --- /dev/null +++ b/src/components/AppHeader/index.tsx @@ -0,0 +1 @@ +export { default } from './AppHeader'; \ No newline at end of file diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx new file mode 100644 index 0000000..70a6a8e --- /dev/null +++ b/src/components/Button/Button.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { Button, ButtonProps } from 'antd'; + +interface AButtonProps extends ButtonProps {} + +export default function AButton(props: AButtonProps) { + + return ( + +
+
+ ) +} \ No newline at end of file diff --git a/src/pages/login/login.less b/src/pages/login/login.less new file mode 100644 index 0000000..f622724 --- /dev/null +++ b/src/pages/login/login.less @@ -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; + } +} \ No newline at end of file diff --git a/src/pages/messages/README.md b/src/pages/messages/README.md new file mode 100644 index 0000000..1525143 --- /dev/null +++ b/src/pages/messages/README.md @@ -0,0 +1 @@ +# 消息通知 \ No newline at end of file diff --git a/src/pages/messages/index.tsx b/src/pages/messages/index.tsx new file mode 100644 index 0000000..3a0af27 --- /dev/null +++ b/src/pages/messages/index.tsx @@ -0,0 +1,9 @@ +import React from 'react' + +export default function MessagesView() { + return ( +
+ 消息通知界面 +
+ ) +} \ No newline at end of file diff --git a/src/pages/sync/README.md b/src/pages/sync/README.md new file mode 100644 index 0000000..ada90cf --- /dev/null +++ b/src/pages/sync/README.md @@ -0,0 +1 @@ +# 同步任务 \ No newline at end of file diff --git a/src/pages/sync/index.tsx b/src/pages/sync/index.tsx new file mode 100644 index 0000000..2afb7d5 --- /dev/null +++ b/src/pages/sync/index.tsx @@ -0,0 +1,9 @@ +import React from 'react' + +export default function SyncView() { + return ( +
+ 同步任务界面 +
+ ) +} \ No newline at end of file diff --git a/src/services/API.d.ts b/src/services/API.d.ts new file mode 100644 index 0000000..791e732 --- /dev/null +++ b/src/services/API.d.ts @@ -0,0 +1,15 @@ +declare namespace API { + export interface ResponseData { + code: number | string; + data: T; + message?: string; + /** + * 用于表明http请求是否成功 + */ + success: boolean; + /** + * 用于标明业务请求内容是否成功, 等价于code === 0 + */ + requestIsSuccess: boolean; + } +} \ No newline at end of file diff --git a/src/services/user.ts b/src/services/user.ts new file mode 100644 index 0000000..0c150bd --- /dev/null +++ b/src/services/user.ts @@ -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>('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'); +} \ No newline at end of file diff --git a/src/utils/request.config.ts b/src/utils/request.config.ts new file mode 100644 index 0000000..6c2a632 --- /dev/null +++ b/src/utils/request.config.ts @@ -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]; +} \ No newline at end of file diff --git a/src/utils/request.ts b/src/utils/request.ts new file mode 100644 index 0000000..15bafbe --- /dev/null +++ b/src/utils/request.ts @@ -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(path: string, params = {}, options = { silent: false }) { + const [method, fullpath] = parseRequest(path); + const { silent, ...restOptions } = options; + const res = await request>(fullpath, { method, [method === 'GET' ? 'params' : 'data']: params, ...restOptions }); + if(!silent) { + handleRequest(res) + .error(() => { + message.error(res.message); + }) + } + return res; +} \ No newline at end of file diff --git a/src/utils/storage.ts b/src/utils/storage.ts new file mode 100644 index 0000000..0da3ce9 --- /dev/null +++ b/src/utils/storage.ts @@ -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; diff --git a/src/utils/tool.ts b/src/utils/tool.ts new file mode 100644 index 0000000..72f8581 --- /dev/null +++ b/src/utils/tool.ts @@ -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) { + 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) => new RequestHandler(res); + +export function errorReponse(message: string, code = 'err'): API.ResponseData { + return { + code, + data: null, + success: true, + requestIsSuccess: false, + message, + } +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..bc5250b --- /dev/null +++ b/tsconfig.json @@ -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" + ] +} diff --git a/typings.d.ts b/typings.d.ts new file mode 100644 index 0000000..06c8a5b --- /dev/null +++ b/typings.d.ts @@ -0,0 +1,10 @@ +declare module '*.css'; +declare module '*.less'; +declare module '*.png'; +declare module '*.svg' { + export function ReactComponent( + props: React.SVGProps, + ): React.ReactElement; + const url: string; + export default url; +}