├── project ├── Exception │ ├── style.less │ ├── 403.js │ ├── 404.js │ ├── 500.js │ └── triggerException.js ├── Profile │ ├── BasicProfile.less │ ├── AdvancedProfile.less │ ├── BasicProfile.js │ └── AdvancedProfile.js ├── Result │ ├── Success.test.js │ ├── Error.js │ └── Success.js ├── User │ ├── RegisterResult.less │ ├── Login.less │ ├── Register.less │ ├── RegisterResult.js │ ├── Login.js │ └── Register.js ├── Dashboard │ ├── Monitor.less │ ├── Analysis.less │ ├── Workplace.less │ ├── Monitor.js │ ├── Workplace.js │ └── Analysis.js ├── List │ ├── TableList.less │ ├── Applications.less │ ├── Projects.less │ ├── Articles.less │ ├── List.js │ ├── CardList.less │ ├── CardList.js │ ├── BasicList.less │ ├── BasicList.js │ ├── Projects.js │ ├── Applications.js │ ├── Articles.js │ └── TableList.js ├── Pharmacopoeia │ ├── List.less │ └── List.js └── Forms │ ├── StepForm │ ├── style.less │ ├── index.js │ ├── Step3.js │ ├── Step2.js │ └── Step1.js │ ├── style.less │ ├── BasicForm.js │ ├── TableForm.js │ └── AdvancedForm.js ├── README.md ├── index.js ├── package.json └── lib ├── simp2trad.js └── data.js /project/Exception/style.less: -------------------------------------------------------------------------------- 1 | .trigger { 2 | background: 'red'; 3 | :global(.ant-btn) { 4 | margin-right: 8px; 5 | margin-bottom: 12px; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /project/Profile/BasicProfile.less: -------------------------------------------------------------------------------- 1 | @import '~antd/lib/style/themes/default.less'; 2 | 3 | .title { 4 | color: @heading-color; 5 | font-size: 16px; 6 | font-weight: 500; 7 | margin-bottom: 16px; 8 | } 9 | -------------------------------------------------------------------------------- /project/Exception/403.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link } from 'dva/router'; 3 | import Exception from 'components/Exception'; 4 | 5 | export default () => ( 6 | 7 | ); 8 | -------------------------------------------------------------------------------- /project/Exception/404.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link } from 'dva/router'; 3 | import Exception from 'components/Exception'; 4 | 5 | export default () => ( 6 | 7 | ); 8 | -------------------------------------------------------------------------------- /project/Exception/500.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link } from 'dva/router'; 3 | import Exception from 'components/Exception'; 4 | 5 | export default () => ( 6 | 7 | ); 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Simp2trad 2 | 3 | 一个简单工具将简体中文项目转换成繁体中文项目。 4 | 5 | ## Installation 6 | 7 | ```bash 8 | npm install -g simp2trad 9 | ``` 10 | 11 | ## Usage 12 | 13 | ```bash 14 | simp2trad /path/to/project 15 | ``` 16 | 17 | ## Versioning 18 | 19 | 1.0.0 Implemention. 20 | 21 | -------------------------------------------------------------------------------- /project/Result/Success.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | import Success from './Success'; 4 | 5 | it('renders with Result', () => { 6 | const wrapper = shallow(); 7 | expect(wrapper.find('Result').length).toBe(1); 8 | expect(wrapper.find('Result').prop('type')).toBe('success'); 9 | }); 10 | -------------------------------------------------------------------------------- /project/User/RegisterResult.less: -------------------------------------------------------------------------------- 1 | .registerResult { 2 | :global { 3 | .anticon { 4 | font-size: 64px; 5 | } 6 | } 7 | .title { 8 | margin-top: 32px; 9 | font-size: 20px; 10 | line-height: 28px; 11 | } 12 | .actions { 13 | margin-top: 40px; 14 | a + a { 15 | margin-left: 8px; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env node 2 | 3 | const simp2trad = require('./lib/simp2trad') 4 | const fs = require('fs') 5 | 6 | if (process.argv.length !== 3){ 7 | console.log('Usage: simp2trad '); 8 | process.exit(); 9 | } 10 | 11 | var path = process.argv[2]; 12 | if (!fs.existsSync(path)){ 13 | console.log('Path Not Exists.'); 14 | process.exit(); 15 | } 16 | 17 | var tool = new simp2trad(path); 18 | tool.start(); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "simp2trad", 3 | "version": "1.0.2", 4 | "description": "A tool for convert whole project's simplified chinese to traditional chinese.", 5 | "preferGlobal": true, 6 | "bin": { 7 | "simp2trad": "index.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/superhos/simp2trad.git" 12 | }, 13 | "scripts": { 14 | "test": "node index.js" 15 | }, 16 | "author": "SevensChan", 17 | "license": "MIT" 18 | } 19 | -------------------------------------------------------------------------------- /project/Dashboard/Monitor.less: -------------------------------------------------------------------------------- 1 | @import '~antd/lib/style/themes/default.less'; 2 | @import '../../utils/utils.less'; 3 | 4 | .mapChart { 5 | padding-top: 24px; 6 | height: 457px; 7 | text-align: center; 8 | img { 9 | display: inline-block; 10 | max-width: 100%; 11 | max-height: 437px; 12 | } 13 | } 14 | 15 | .pieCard :global(.pie-stat) { 16 | font-size: 24px !important; 17 | } 18 | 19 | @media screen and (max-width: @screen-lg) { 20 | .mapChart { 21 | height: auto; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /project/User/Login.less: -------------------------------------------------------------------------------- 1 | @import '~antd/lib/style/themes/default.less'; 2 | 3 | .main { 4 | width: 368px; 5 | margin: 0 auto; 6 | @media screen and (max-width: @screen-sm) { 7 | width: 95%; 8 | } 9 | 10 | .icon { 11 | font-size: 24px; 12 | color: rgba(0, 0, 0, 0.2); 13 | margin-left: 16px; 14 | vertical-align: middle; 15 | cursor: pointer; 16 | transition: color 0.3s; 17 | 18 | &:hover { 19 | color: @primary-color; 20 | } 21 | } 22 | 23 | .other { 24 | text-align: left; 25 | margin-top: 24px; 26 | line-height: 22px; 27 | 28 | .register { 29 | float: right; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /project/User/Register.less: -------------------------------------------------------------------------------- 1 | @import '~antd/lib/style/themes/default.less'; 2 | 3 | .main { 4 | width: 368px; 5 | margin: 0 auto; 6 | 7 | :global { 8 | .ant-form-item { 9 | margin-bottom: 24px; 10 | } 11 | } 12 | 13 | h3 { 14 | font-size: 16px; 15 | margin-bottom: 20px; 16 | } 17 | 18 | .getCaptcha { 19 | display: block; 20 | width: 100%; 21 | } 22 | 23 | .submit { 24 | width: 50%; 25 | } 26 | 27 | .login { 28 | float: right; 29 | line-height: @btn-height-lg; 30 | } 31 | } 32 | 33 | .success, 34 | .warning, 35 | .error { 36 | transition: color 0.3s; 37 | } 38 | 39 | .success { 40 | color: @success-color; 41 | } 42 | 43 | .warning { 44 | color: @warning-color; 45 | } 46 | 47 | .error { 48 | color: @error-color; 49 | } 50 | 51 | .progress-pass > .progress { 52 | :global { 53 | .ant-progress-bg { 54 | background-color: @warning-color; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /project/Profile/AdvancedProfile.less: -------------------------------------------------------------------------------- 1 | @import '~antd/lib/style/themes/default.less'; 2 | 3 | .headerList { 4 | margin-bottom: 4px; 5 | } 6 | 7 | .tabsCard { 8 | :global { 9 | .ant-card-head { 10 | padding: 0 16px; 11 | } 12 | } 13 | } 14 | 15 | .noData { 16 | color: @disabled-color; 17 | text-align: center; 18 | line-height: 64px; 19 | font-size: 16px; 20 | i { 21 | font-size: 24px; 22 | margin-right: 16px; 23 | position: relative; 24 | top: 3px; 25 | } 26 | } 27 | 28 | .heading { 29 | color: @heading-color; 30 | font-size: 20px; 31 | } 32 | 33 | .stepDescription { 34 | font-size: 14px; 35 | position: relative; 36 | left: 38px; 37 | & > div { 38 | margin-top: 8px; 39 | margin-bottom: 4px; 40 | } 41 | } 42 | 43 | .textSecondary { 44 | color: @text-color-secondary; 45 | } 46 | 47 | @media screen and (max-width: @screen-sm) { 48 | .stepDescription { 49 | left: 8px; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /project/User/RegisterResult.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Button } from 'antd'; 3 | import { Link } from 'dva/router'; 4 | import Result from 'components/Result'; 5 | import styles from './RegisterResult.less'; 6 | 7 | const actions = ( 8 |
9 | 10 | 13 | 14 | 15 | 16 | 17 |
18 | ); 19 | 20 | export default ({ location }) => ( 21 | 26 | 妳的賬戶:{location.state ? location.state.account : 'AntDesign@example.com'} 註冊成功 27 | 28 | } 29 | description="激活郵件已發送到妳的郵箱中,郵件有效期為24小時。請及時登錄郵箱,點擊郵件中的鏈接激活帳戶。" 30 | actions={actions} 31 | style={{ marginTop: 56 }} 32 | /> 33 | ); 34 | -------------------------------------------------------------------------------- /project/List/TableList.less: -------------------------------------------------------------------------------- 1 | @import '~antd/lib/style/themes/default.less'; 2 | @import '../../utils/utils.less'; 3 | 4 | .tableList { 5 | .tableListOperator { 6 | margin-bottom: 16px; 7 | button { 8 | margin-right: 8px; 9 | } 10 | } 11 | } 12 | 13 | .tableListForm { 14 | :global { 15 | .ant-form-item { 16 | margin-bottom: 24px; 17 | margin-right: 0; 18 | display: flex; 19 | > .ant-form-item-label { 20 | width: auto; 21 | line-height: 32px; 22 | padding-right: 8px; 23 | } 24 | .ant-form-item-control { 25 | line-height: 32px; 26 | } 27 | } 28 | .ant-form-item-control-wrapper { 29 | flex: 1; 30 | } 31 | } 32 | .submitButtons { 33 | white-space: nowrap; 34 | margin-bottom: 24px; 35 | } 36 | } 37 | 38 | @media screen and (max-width: @screen-lg) { 39 | .tableListForm :global(.ant-form-item) { 40 | margin-right: 24px; 41 | } 42 | } 43 | 44 | @media screen and (max-width: @screen-md) { 45 | .tableListForm :global(.ant-form-item) { 46 | margin-right: 8px; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /project/Pharmacopoeia/List.less: -------------------------------------------------------------------------------- 1 | @import '~antd/lib/style/themes/default.less'; 2 | @import '../../utils/utils.less'; 3 | 4 | .tableList { 5 | .tableListOperator { 6 | margin-bottom: 16px; 7 | button { 8 | margin-right: 8px; 9 | } 10 | } 11 | } 12 | 13 | .tableListForm { 14 | :global { 15 | .ant-form-item { 16 | margin-bottom: 24px; 17 | margin-right: 0; 18 | display: flex; 19 | > .ant-form-item-label { 20 | width: auto; 21 | line-height: 32px; 22 | padding-right: 8px; 23 | } 24 | .ant-form-item-control { 25 | line-height: 32px; 26 | } 27 | } 28 | .ant-form-item-control-wrapper { 29 | flex: 1; 30 | } 31 | } 32 | .submitButtons { 33 | white-space: nowrap; 34 | margin-bottom: 24px; 35 | } 36 | } 37 | 38 | @media screen and (max-width: @screen-lg) { 39 | .tableListForm :global(.ant-form-item) { 40 | margin-right: 24px; 41 | } 42 | } 43 | 44 | @media screen and (max-width: @screen-md) { 45 | .tableListForm :global(.ant-form-item) { 46 | margin-right: 8px; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /project/List/Applications.less: -------------------------------------------------------------------------------- 1 | @import '~antd/lib/style/themes/default.less'; 2 | @import '../../utils/utils.less'; 3 | 4 | .filterCardList { 5 | margin-bottom: -24px; 6 | :global { 7 | .ant-card-meta-content { 8 | margin-top: 0; 9 | } 10 | // disabled white space 11 | .ant-card-meta-avatar { 12 | font-size: 0; 13 | } 14 | .ant-card-actions { 15 | background: #f7f9fa; 16 | } 17 | .ant-list .ant-list-item-content-single { 18 | max-width: 100%; 19 | } 20 | } 21 | .cardInfo { 22 | .clearfix(); 23 | margin-top: 16px; 24 | margin-left: 40px; 25 | & > div { 26 | position: relative; 27 | text-align: left; 28 | float: left; 29 | width: 50%; 30 | p { 31 | line-height: 32px; 32 | font-size: 24px; 33 | margin: 0; 34 | } 35 | p:first-child { 36 | color: @text-color-secondary; 37 | font-size: 12px; 38 | line-height: 20px; 39 | margin-bottom: 4px; 40 | } 41 | } 42 | } 43 | } 44 | 45 | .wan { 46 | position: relative; 47 | top: -2px; 48 | font-size: @font-size-base; 49 | font-style: normal; 50 | line-height: 20px; 51 | margin-left: 2px; 52 | } 53 | -------------------------------------------------------------------------------- /project/List/Projects.less: -------------------------------------------------------------------------------- 1 | @import '~antd/lib/style/themes/default.less'; 2 | @import '../../utils/utils.less'; 3 | 4 | .coverCardList { 5 | margin-bottom: -24px; 6 | 7 | .card { 8 | :global { 9 | .ant-card-meta-title { 10 | margin-bottom: 4px; 11 | & > a { 12 | color: @heading-color; 13 | display: inline-block; 14 | max-width: 100%; 15 | } 16 | } 17 | .ant-card-meta-description { 18 | height: 44px; 19 | line-height: 22px; 20 | overflow: hidden; 21 | } 22 | } 23 | 24 | &:hover { 25 | :global { 26 | .ant-card-meta-title > a { 27 | color: @primary-color; 28 | } 29 | } 30 | } 31 | } 32 | 33 | .cardItemContent { 34 | display: flex; 35 | margin-top: 16px; 36 | margin-bottom: -4px; 37 | line-height: 20px; 38 | height: 20px; 39 | & > span { 40 | color: @text-color-secondary; 41 | flex: 1; 42 | font-size: 12px; 43 | } 44 | .avatarList { 45 | flex: 0 1 auto; 46 | } 47 | } 48 | .cardList { 49 | margin-top: 24px; 50 | } 51 | 52 | :global { 53 | .ant-list .ant-list-item-content-single { 54 | max-width: 100%; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /project/Exception/triggerException.js: -------------------------------------------------------------------------------- 1 | import React, { PureComponent } from 'react'; 2 | import { Button, Spin, Card } from 'antd'; 3 | import { connect } from 'dva'; 4 | import styles from './style.less'; 5 | 6 | @connect(state => ({ 7 | isloading: state.error.isloading, 8 | })) 9 | export default class TriggerException extends PureComponent { 10 | state = { 11 | isloading: false, 12 | }; 13 | triggerError = code => { 14 | this.setState({ 15 | isloading: true, 16 | }); 17 | this.props.dispatch({ 18 | type: 'error/query', 19 | payload: { 20 | code, 21 | }, 22 | }); 23 | }; 24 | render() { 25 | return ( 26 | 27 | 28 | 31 | 34 | 37 | 40 | 41 | 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /project/List/Articles.less: -------------------------------------------------------------------------------- 1 | @import '~antd/lib/style/themes/default.less'; 2 | @import '../../utils/utils.less'; 3 | 4 | .listContent { 5 | .description { 6 | line-height: 22px; 7 | max-width: 720px; 8 | } 9 | .extra { 10 | color: @text-color-secondary; 11 | margin-top: 16px; 12 | line-height: 22px; 13 | & > :global(.ant-avatar) { 14 | vertical-align: top; 15 | margin-right: 8px; 16 | width: 20px; 17 | height: 20px; 18 | position: relative; 19 | top: 1px; 20 | } 21 | & > em { 22 | color: @disabled-color; 23 | font-style: normal; 24 | margin-left: 16px; 25 | } 26 | } 27 | } 28 | a.listItemMetaTitle { 29 | color: @heading-color; 30 | } 31 | .listItemExtra { 32 | width: 272px; 33 | height: 1px; 34 | } 35 | .selfTrigger { 36 | margin-left: 12px; 37 | } 38 | 39 | @media screen and (max-width: @screen-xs) { 40 | .selfTrigger { 41 | display: block; 42 | margin-left: 0; 43 | } 44 | .listContent { 45 | .extra { 46 | & > em { 47 | display: block; 48 | margin-left: 0; 49 | margin-top: 8px; 50 | } 51 | } 52 | } 53 | } 54 | @media screen and (max-width: @screen-md) { 55 | .selfTrigger { 56 | display: block; 57 | margin-left: 0; 58 | } 59 | } 60 | @media screen and (max-width: @screen-lg) { 61 | .listItemExtra { 62 | width: 0; 63 | height: 1px; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /project/Result/Error.js: -------------------------------------------------------------------------------- 1 | import React, { Fragment } from 'react'; 2 | import { Button, Icon, Card } from 'antd'; 3 | import Result from 'components/Result'; 4 | import PageHeaderLayout from '../../layouts/PageHeaderLayout'; 5 | 6 | const extra = ( 7 | 8 |
16 | 您提交的內容有如下錯誤: 17 |
18 |
19 | 您的賬戶已被凍結 20 | 21 | 立即解凍 22 | 23 |
24 |
25 | 您的賬戶還不具備申請資格 26 | 27 | 立即升級 28 | 29 |
30 |
31 | ); 32 | 33 | const actions = ; 34 | 35 | export default () => ( 36 | 37 | 38 | 46 | 47 | 48 | ); 49 | -------------------------------------------------------------------------------- /project/Forms/StepForm/style.less: -------------------------------------------------------------------------------- 1 | @import '~antd/lib/style/themes/default.less'; 2 | 3 | .stepForm { 4 | margin: 40px auto 0; 5 | max-width: 500px; 6 | } 7 | 8 | .stepFormText { 9 | margin-bottom: 24px; 10 | :global { 11 | .ant-form-item-label, 12 | .ant-form-item-control { 13 | line-height: 22px; 14 | } 15 | } 16 | } 17 | 18 | .result { 19 | margin: 0 auto; 20 | max-width: 560px; 21 | padding: 24px 0 8px; 22 | } 23 | 24 | .desc { 25 | padding: 0 56px; 26 | color: @text-color-secondary; 27 | h3 { 28 | font-size: 16px; 29 | margin: 0 0 12px 0; 30 | color: @text-color-secondary; 31 | line-height: 32px; 32 | } 33 | h4 { 34 | margin: 0 0 4px 0; 35 | color: @text-color-secondary; 36 | font-size: 14px; 37 | line-height: 22px; 38 | } 39 | p { 40 | margin-top: 0; 41 | margin-bottom: 12px; 42 | line-height: 22px; 43 | } 44 | } 45 | 46 | @media screen and (max-width: @screen-md) { 47 | .desc { 48 | padding: 0; 49 | } 50 | } 51 | 52 | .information { 53 | line-height: 22px; 54 | :global { 55 | .ant-row:not(:last-child) { 56 | margin-bottom: 24px; 57 | } 58 | } 59 | .label { 60 | color: @heading-color; 61 | text-align: right; 62 | padding-right: 8px; 63 | @media screen and (max-width: @screen-sm) { 64 | text-align: left; 65 | } 66 | } 67 | } 68 | 69 | .money { 70 | font-family: 'Helvetica Neue', sans-serif; 71 | font-weight: 500; 72 | font-size: 20px; 73 | line-height: 14px; 74 | } 75 | 76 | .uppercase { 77 | font-size: 12px; 78 | } 79 | -------------------------------------------------------------------------------- /project/Forms/style.less: -------------------------------------------------------------------------------- 1 | @import '~antd/lib/style/themes/default.less'; 2 | 3 | .card { 4 | margin-bottom: 24px; 5 | } 6 | 7 | .heading { 8 | font-size: 14px; 9 | line-height: 22px; 10 | margin: 0 0 16px 0; 11 | } 12 | 13 | .steps:global(.ant-steps) { 14 | max-width: 750px; 15 | margin: 16px auto; 16 | } 17 | 18 | .errorIcon { 19 | cursor: pointer; 20 | color: @error-color; 21 | margin-right: 24px; 22 | i { 23 | margin-right: 4px; 24 | } 25 | } 26 | 27 | .errorPopover { 28 | :global { 29 | .ant-popover-inner-content { 30 | padding: 0; 31 | max-height: 290px; 32 | overflow: auto; 33 | min-width: 256px; 34 | } 35 | } 36 | } 37 | 38 | .errorListItem { 39 | list-style: none; 40 | border-bottom: 1px solid @border-color-split; 41 | padding: 8px 16px; 42 | cursor: pointer; 43 | transition: all 0.3s; 44 | &:hover { 45 | background: @primary-1; 46 | } 47 | &:last-child { 48 | border: 0; 49 | } 50 | .errorIcon { 51 | color: @error-color; 52 | float: left; 53 | margin-top: 4px; 54 | margin-right: 12px; 55 | padding-bottom: 22px; 56 | } 57 | .errorField { 58 | font-size: 12px; 59 | color: @text-color-secondary; 60 | margin-top: 2px; 61 | } 62 | } 63 | 64 | .editable { 65 | td { 66 | padding-top: 13px !important; 67 | padding-bottom: 12.5px !important; 68 | } 69 | } 70 | 71 | // custom footer for fixed footer toolbar 72 | .advancedForm + div { 73 | padding-bottom: 64px; 74 | } 75 | 76 | .advancedForm { 77 | :global { 78 | .ant-form .ant-row:last-child .ant-form-item { 79 | margin-bottom: 24px; 80 | } 81 | .ant-table td { 82 | transition: none !important; 83 | } 84 | } 85 | } 86 | 87 | .optional { 88 | color: @text-color-secondary; 89 | font-style: normal; 90 | } 91 | -------------------------------------------------------------------------------- /project/Forms/StepForm/index.js: -------------------------------------------------------------------------------- 1 | import React, { PureComponent, Fragment } from 'react'; 2 | import { Route, Redirect, Switch } from 'dva/router'; 3 | import { Card, Steps } from 'antd'; 4 | import PageHeaderLayout from '../../../layouts/PageHeaderLayout'; 5 | import NotFound from '../../Exception/404'; 6 | import { getRoutes } from '../../../utils/utils'; 7 | import styles from '../style.less'; 8 | 9 | const { Step } = Steps; 10 | 11 | export default class StepForm extends PureComponent { 12 | getCurrentStep() { 13 | const { location } = this.props; 14 | const { pathname } = location; 15 | const pathList = pathname.split('/'); 16 | switch (pathList[pathList.length - 1]) { 17 | case 'info': 18 | return 0; 19 | case 'confirm': 20 | return 1; 21 | case 'result': 22 | return 2; 23 | default: 24 | return 0; 25 | } 26 | } 27 | render() { 28 | const { match, routerData, location } = this.props; 29 | return ( 30 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | {getRoutes(match.path, routerData).map(item => ( 44 | 50 | ))} 51 | 52 | 53 | 54 | 55 | 56 | 57 | ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /project/Forms/StepForm/Step3.js: -------------------------------------------------------------------------------- 1 | import React, { Fragment } from 'react'; 2 | import { connect } from 'dva'; 3 | import { Button, Row, Col } from 'antd'; 4 | import { routerRedux } from 'dva/router'; 5 | import Result from 'components/Result'; 6 | import styles from './style.less'; 7 | 8 | class Step3 extends React.PureComponent { 9 | render() { 10 | const { dispatch, data } = this.props; 11 | const onFinish = () => { 12 | dispatch(routerRedux.push('/form/step-form')); 13 | }; 14 | const information = ( 15 |
16 | 17 | 18 | 付款賬戶: 19 | 20 | 21 | {data.payAccount} 22 | 23 | 24 | 25 | 26 | 收款賬戶: 27 | 28 | 29 | {data.receiverAccount} 30 | 31 | 32 | 33 | 34 | 收款人姓名: 35 | 36 | 37 | {data.receiverName} 38 | 39 | 40 | 41 | 42 | 轉賬金額: 43 | 44 | 45 | {data.amount} 元 46 | 47 | 48 |
49 | ); 50 | const actions = ( 51 | 52 | 55 | 56 | 57 | ); 58 | return ( 59 | 67 | ); 68 | } 69 | } 70 | 71 | export default connect(({ form }) => ({ 72 | data: form.step, 73 | }))(Step3); 74 | -------------------------------------------------------------------------------- /project/List/List.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { routerRedux, Route, Switch } from 'dva/router'; 3 | import { connect } from 'dva'; 4 | import { Input } from 'antd'; 5 | import PageHeaderLayout from '../../layouts/PageHeaderLayout'; 6 | import { getRoutes } from '../../utils/utils'; 7 | 8 | @connect() 9 | export default class SearchList extends Component { 10 | handleTabChange = key => { 11 | const { dispatch, match } = this.props; 12 | switch (key) { 13 | case 'articles': 14 | dispatch(routerRedux.push(`${match.url}/articles`)); 15 | break; 16 | case 'applications': 17 | dispatch(routerRedux.push(`${match.url}/applications`)); 18 | break; 19 | case 'projects': 20 | dispatch(routerRedux.push(`${match.url}/projects`)); 21 | break; 22 | default: 23 | break; 24 | } 25 | }; 26 | 27 | render() { 28 | const tabList = [ 29 | { 30 | key: 'articles', 31 | tab: '文章', 32 | }, 33 | { 34 | key: 'applications', 35 | tab: '應用', 36 | }, 37 | { 38 | key: 'projects', 39 | tab: '項目', 40 | }, 41 | ]; 42 | 43 | const mainSearch = ( 44 |
45 | 52 |
53 | ); 54 | 55 | const { match, routerData, location } = this.props; 56 | const routes = getRoutes(match.path, routerData); 57 | 58 | return ( 59 | 66 | 67 | {routes.map(item => ( 68 | 69 | ))} 70 | 71 | 72 | ); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /lib/simp2trad.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 將項目中的所有簡體轉成繁體 3 | */ 4 | const fs = require('fs'); 5 | const simpChar = require('./data.js').simpChar; 6 | const tradChar = require('./data.js').tradChar; 7 | 8 | var simp2trad = function(path){ 9 | this.path = path; 10 | } 11 | 12 | simp2trad.prototype = { 13 | start: async function(){ 14 | //Get all files 15 | var files = await this.getFiles(); 16 | var _this = this; 17 | files.forEach(function(path){ 18 | console.log('Translating: ' + path); 19 | _this.scanFile(path); 20 | }) 21 | 22 | console.log('Translate successfully ('+files.length+' files have been traslated). ') 23 | }, 24 | scanFile: function(path){ 25 | var content = fs.readFileSync(path).toString(); 26 | //获取中文 27 | var chinese = content.match(/[\u4e00-\u9fa5]/g); 28 | if (chinese){ 29 | for (var item in chinese) { 30 | var str = ''; 31 | if (simpChar().indexOf(chinese[item]) != -1) { 32 | str = tradChar().charAt(simpChar().indexOf(chinese[item])); 33 | content = content.replace(chinese[item],str); 34 | } 35 | } 36 | 37 | this.writeFile(path,content); 38 | } 39 | }, 40 | writeFile: function(path,content){ 41 | fs.writeFileSync(path,content); 42 | }, 43 | getFiles: function (){ 44 | var _this = this; 45 | var fileList = []; 46 | return new Promise(function(resolve,reject){ 47 | var fileQueue = []; 48 | fileQueue.push(_this.path); 49 | while(fileQueue.length > 0){ 50 | var cur = fileQueue.shift(); 51 | var pa = fs.readdirSync(cur); 52 | pa.forEach(function(ele,index){ 53 | var info = fs.statSync(cur+"/"+ele) 54 | if(info.isDirectory()){ 55 | fileQueue.push(cur+"/"+ele); 56 | }else{ 57 | fileList.push(cur + "/" + ele); 58 | } 59 | }) 60 | } 61 | resolve(fileList); 62 | }) 63 | } 64 | } 65 | 66 | // var tool = new simp2trad(path); 67 | // tool.start(); 68 | 69 | module.exports = simp2trad; -------------------------------------------------------------------------------- /project/List/CardList.less: -------------------------------------------------------------------------------- 1 | @import '~antd/lib/style/themes/default.less'; 2 | @import '../../utils/utils.less'; 3 | 4 | .cardList { 5 | margin-bottom: -24px; 6 | 7 | .card { 8 | :global { 9 | .ant-card-meta-title { 10 | margin-bottom: 12px; 11 | & > a { 12 | color: @heading-color; 13 | display: inline-block; 14 | max-width: 100%; 15 | } 16 | } 17 | .ant-card-actions { 18 | background: #f7f9fa; 19 | } 20 | .ant-card-body:hover { 21 | .ant-card-meta-title > a { 22 | color: @primary-color; 23 | } 24 | } 25 | } 26 | } 27 | .item { 28 | height: 64px; 29 | } 30 | 31 | :global { 32 | .ant-list .ant-list-item-content-single { 33 | max-width: 100%; 34 | } 35 | } 36 | } 37 | 38 | .extraImg { 39 | margin-top: -60px; 40 | text-align: center; 41 | width: 195px; 42 | img { 43 | width: 100%; 44 | } 45 | } 46 | 47 | .newButton { 48 | background-color: #fff; 49 | border-color: @border-color-base; 50 | border-radius: @border-radius-sm; 51 | color: @text-color-secondary; 52 | width: 100%; 53 | height: 188px; 54 | } 55 | 56 | .cardAvatar { 57 | width: 48px; 58 | height: 48px; 59 | border-radius: 48px; 60 | } 61 | 62 | .cardDescription { 63 | .textOverflowMulti(); 64 | } 65 | 66 | .pageHeaderContent { 67 | position: relative; 68 | } 69 | 70 | .contentLink { 71 | margin-top: 16px; 72 | a { 73 | margin-right: 32px; 74 | img { 75 | width: 24px; 76 | } 77 | } 78 | img { 79 | vertical-align: middle; 80 | margin-right: 8px; 81 | } 82 | } 83 | 84 | @media screen and (max-width: @screen-lg) { 85 | .contentLink { 86 | a { 87 | margin-right: 16px; 88 | } 89 | } 90 | } 91 | @media screen and (max-width: @screen-md) { 92 | .extraImg { 93 | display: none; 94 | } 95 | } 96 | 97 | @media screen and (max-width: @screen-sm) { 98 | .pageHeaderContent { 99 | padding-bottom: 30px; 100 | } 101 | .contentLink { 102 | position: absolute; 103 | left: 0; 104 | bottom: -4px; 105 | width: 1000px; 106 | a { 107 | margin-right: 16px; 108 | } 109 | img { 110 | margin-right: 4px; 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /project/Result/Success.js: -------------------------------------------------------------------------------- 1 | import React, { Fragment } from 'react'; 2 | import { Button, Row, Col, Icon, Steps, Card } from 'antd'; 3 | import Result from 'components/Result'; 4 | import PageHeaderLayout from '../../layouts/PageHeaderLayout'; 5 | 6 | const { Step } = Steps; 7 | 8 | const desc1 = ( 9 |
17 |
18 | 曲麗麗 19 |
20 |
2016-12-12 12:32
21 |
22 | ); 23 | 24 | const desc2 = ( 25 |
26 |
27 | 週毛毛 28 |
29 |
30 | 催壹下 31 |
32 |
33 | ); 34 | 35 | const extra = ( 36 | 37 |
45 | 項目名稱 46 |
47 | 48 | 49 | 項目 ID: 50 | 23421 51 | 52 | 53 | 負責人: 54 | 曲麗麗 55 | 56 | 57 | 生效時間: 58 | 2016-12-12 ~ 2017-12-12 59 | 60 | 61 | 62 | 創建項目} description={desc1} /> 63 | 部門初審} description={desc2} /> 64 | 財務復核} /> 65 | 完成} /> 66 | 67 |
68 | ); 69 | 70 | const actions = ( 71 | 72 | 73 | 74 | 75 | 76 | ); 77 | 78 | export default () => ( 79 | 80 | 81 | 92 | 93 | 94 | ); 95 | -------------------------------------------------------------------------------- /project/User/Login.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { connect } from 'dva'; 3 | import { Link } from 'dva/router'; 4 | import { Checkbox, Alert, Icon } from 'antd'; 5 | import Login from 'components/Login'; 6 | import styles from './Login.less'; 7 | 8 | const { Tab, UserName, Password, Mobile, Captcha, Submit } = Login; 9 | 10 | @connect(({ login, loading }) => ({ 11 | login, 12 | submitting: loading.effects['login/login'], 13 | })) 14 | export default class LoginPage extends Component { 15 | state = { 16 | type: 'account', 17 | autoLogin: true, 18 | }; 19 | 20 | onTabChange = type => { 21 | this.setState({ type }); 22 | }; 23 | 24 | handleSubmit = (err, values) => { 25 | const { type } = this.state; 26 | if (!err) { 27 | this.props.dispatch({ 28 | type: 'login/login', 29 | payload: { 30 | ...values, 31 | type, 32 | }, 33 | }); 34 | } 35 | }; 36 | 37 | changeAutoLogin = e => { 38 | this.setState({ 39 | autoLogin: e.target.checked, 40 | }); 41 | }; 42 | 43 | renderMessage = content => { 44 | return ; 45 | }; 46 | 47 | render() { 48 | const { login, submitting } = this.props; 49 | const { type } = this.state; 50 | return ( 51 |
52 | 53 | 54 | {login.status === 'error' && 55 | login.type === 'account' && 56 | !submitting && 57 | this.renderMessage('賬戶或密碼錯誤(admin/888888)')} 58 | 59 | 60 | 61 | 62 | {login.status === 'error' && 63 | login.type === 'mobile' && 64 | !submitting && 65 | this.renderMessage('驗證碼錯誤')} 66 | 67 | 68 | 69 |
70 | 71 | 自動登錄 72 | 73 | 74 | 忘記密碼 75 | 76 |
77 | 登錄 78 |
79 | 其他登錄方式 80 | 81 | 82 | 83 | 84 | 註冊賬戶 85 | 86 |
87 |
88 |
89 | ); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /project/List/CardList.js: -------------------------------------------------------------------------------- 1 | import React, { PureComponent } from 'react'; 2 | import { connect } from 'dva'; 3 | import { Card, Button, Icon, List } from 'antd'; 4 | 5 | import Ellipsis from 'components/Ellipsis'; 6 | import PageHeaderLayout from '../../layouts/PageHeaderLayout'; 7 | 8 | import styles from './CardList.less'; 9 | 10 | @connect(({ list, loading }) => ({ 11 | list, 12 | loading: loading.models.list, 13 | })) 14 | export default class CardList extends PureComponent { 15 | componentDidMount() { 16 | this.props.dispatch({ 17 | type: 'list/fetch', 18 | payload: { 19 | count: 8, 20 | }, 21 | }); 22 | } 23 | 24 | render() { 25 | const { list: { list }, loading } = this.props; 26 | 27 | const content = ( 28 |
29 |

30 | 段落示意:螞蟻金服務設計平臺 ant.design,用最小的工作量,無縫接入螞蟻金服生態, 31 | 提供跨越設計與開發的體驗解決方案。 32 |

33 | 47 |
48 | ); 49 | 50 | const extraContent = ( 51 |
52 | 這是壹個標題 56 |
57 | ); 58 | 59 | return ( 60 | 61 |
62 | 68 | item ? ( 69 | 70 | 操作壹, 操作二]}> 71 | } 73 | title={{item.title}} 74 | description={ 75 | 76 | {item.description} 77 | 78 | } 79 | /> 80 | 81 | 82 | ) : ( 83 | 84 | 87 | 88 | ) 89 | } 90 | /> 91 |
92 |
93 | ); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /project/Forms/StepForm/Step2.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'dva'; 3 | import { Form, Input, Button, Alert, Divider } from 'antd'; 4 | import { routerRedux } from 'dva/router'; 5 | import { digitUppercase } from '../../../utils/utils'; 6 | import styles from './style.less'; 7 | 8 | const formItemLayout = { 9 | labelCol: { 10 | span: 5, 11 | }, 12 | wrapperCol: { 13 | span: 19, 14 | }, 15 | }; 16 | 17 | @Form.create() 18 | class Step2 extends React.PureComponent { 19 | render() { 20 | const { form, data, dispatch, submitting } = this.props; 21 | const { getFieldDecorator, validateFields } = form; 22 | const onPrev = () => { 23 | dispatch(routerRedux.push('/form/step-form')); 24 | }; 25 | const onValidateForm = e => { 26 | e.preventDefault(); 27 | validateFields((err, values) => { 28 | if (!err) { 29 | dispatch({ 30 | type: 'form/submitStepForm', 31 | payload: { 32 | ...data, 33 | ...values, 34 | }, 35 | }); 36 | } 37 | }); 38 | }; 39 | return ( 40 |
41 | 47 | 48 | {data.payAccount} 49 | 50 | 51 | {data.receiverAccount} 52 | 53 | 54 | {data.receiverName} 55 | 56 | 57 | {data.amount} 58 | ({digitUppercase(data.amount)}) 59 | 60 | 61 | 62 | {getFieldDecorator('password', { 63 | initialValue: '123456', 64 | rules: [ 65 | { 66 | required: true, 67 | message: '需要支付密碼才能進行支付', 68 | }, 69 | ], 70 | })()} 71 | 72 | 83 | 86 | 89 | 90 | 91 | ); 92 | } 93 | } 94 | 95 | export default connect(({ form, loading }) => ({ 96 | submitting: loading.effects['form/submitStepForm'], 97 | data: form.step, 98 | }))(Step2); 99 | -------------------------------------------------------------------------------- /project/Dashboard/Analysis.less: -------------------------------------------------------------------------------- 1 | @import '~antd/lib/style/themes/default.less'; 2 | @import '../../utils/utils.less'; 3 | 4 | .iconGroup { 5 | i { 6 | transition: color 0.32s; 7 | color: @text-color-secondary; 8 | cursor: pointer; 9 | margin-left: 16px; 10 | &:hover { 11 | color: @text-color; 12 | } 13 | } 14 | } 15 | 16 | .rankingList { 17 | margin: 25px 0 0; 18 | padding: 0; 19 | list-style: none; 20 | li { 21 | .clearfix(); 22 | margin-top: 16px; 23 | span { 24 | color: @text-color; 25 | font-size: 14px; 26 | line-height: 22px; 27 | } 28 | span:first-child { 29 | background-color: @background-color-base; 30 | border-radius: 20px; 31 | display: inline-block; 32 | font-size: 12px; 33 | font-weight: 600; 34 | margin-right: 24px; 35 | height: 20px; 36 | line-height: 20px; 37 | width: 20px; 38 | text-align: center; 39 | } 40 | span.active { 41 | //background-color: @primary-color; 42 | background-color: #314659; 43 | color: #fff; 44 | } 45 | span:last-child { 46 | float: right; 47 | } 48 | } 49 | } 50 | 51 | .salesExtra { 52 | display: inline-block; 53 | margin-right: 24px; 54 | a { 55 | color: @text-color; 56 | margin-left: 24px; 57 | &:hover { 58 | color: @primary-color; 59 | } 60 | &.currentDate { 61 | color: @primary-color; 62 | } 63 | } 64 | } 65 | 66 | .salesCard { 67 | .salesBar { 68 | padding: 0 0 32px 32px; 69 | } 70 | .salesRank { 71 | padding: 0 32px 32px 72px; 72 | } 73 | :global { 74 | .ant-tabs-bar { 75 | padding-left: 16px; 76 | .ant-tabs-nav .ant-tabs-tab { 77 | padding-top: 16px; 78 | padding-bottom: 14px; 79 | line-height: 24px; 80 | } 81 | } 82 | .ant-tabs-extra-content { 83 | padding-right: 24px; 84 | line-height: 55px; 85 | } 86 | .ant-card-head { 87 | position: relative; 88 | } 89 | } 90 | } 91 | 92 | .salesCardExtra { 93 | height: 68px; 94 | } 95 | 96 | .salesTypeRadio { 97 | position: absolute; 98 | left: 24px; 99 | bottom: 15px; 100 | } 101 | 102 | .offlineCard { 103 | :global { 104 | .ant-tabs-ink-bar { 105 | bottom: auto; 106 | } 107 | .ant-tabs-bar { 108 | border-bottom: none; 109 | } 110 | .ant-tabs-nav-container-scrolling { 111 | padding-left: 40px; 112 | padding-right: 40px; 113 | } 114 | .ant-tabs-tab-prev-icon:before { 115 | position: relative; 116 | left: 6px; 117 | } 118 | .ant-tabs-tab-next-icon:before { 119 | position: relative; 120 | right: 6px; 121 | } 122 | } 123 | 124 | :global(.ant-tabs-tab-active) h4 { 125 | color: @primary-color; 126 | } 127 | } 128 | 129 | .trendText { 130 | margin-left: 8px; 131 | color: @heading-color; 132 | } 133 | 134 | @media screen and (max-width: @screen-lg) { 135 | .salesExtra { 136 | display: none; 137 | } 138 | 139 | .rankingList { 140 | li { 141 | span:first-child { 142 | margin-right: 8px; 143 | } 144 | } 145 | } 146 | } 147 | 148 | @media screen and (max-width: @screen-md) { 149 | .rankingTitle { 150 | margin-top: 16px; 151 | } 152 | 153 | .salesCard .salesBar { 154 | padding: 16px; 155 | } 156 | } 157 | 158 | @media screen and (max-width: @screen-sm) { 159 | .salesExtraWrap { 160 | display: none; 161 | } 162 | 163 | .salesCard { 164 | :global { 165 | .ant-tabs-content { 166 | padding-top: 30px; 167 | } 168 | } 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /project/List/BasicList.less: -------------------------------------------------------------------------------- 1 | @import '~antd/lib/style/themes/default.less'; 2 | @import '../../utils/utils.less'; 3 | 4 | .standardList { 5 | :global { 6 | .ant-card-head { 7 | border-bottom: none; 8 | } 9 | .ant-card-head-title { 10 | line-height: 32px; 11 | padding: 24px 0; 12 | } 13 | .ant-card-extra { 14 | padding: 24px 0; 15 | } 16 | .ant-list-pagination { 17 | text-align: right; 18 | margin-top: 24px; 19 | } 20 | .ant-avatar-lg { 21 | width: 48px; 22 | height: 48px; 23 | line-height: 48px; 24 | } 25 | } 26 | .headerInfo { 27 | position: relative; 28 | text-align: center; 29 | & > span { 30 | color: @text-color-secondary; 31 | display: inline-block; 32 | font-size: @font-size-base; 33 | line-height: 22px; 34 | margin-bottom: 4px; 35 | } 36 | & > p { 37 | color: @heading-color; 38 | font-size: 24px; 39 | line-height: 32px; 40 | margin: 0; 41 | } 42 | & > em { 43 | background-color: @border-color-split; 44 | position: absolute; 45 | height: 56px; 46 | width: 1px; 47 | top: 0; 48 | right: 0; 49 | } 50 | } 51 | .listContent { 52 | font-size: 0; 53 | .listContentItem { 54 | color: @text-color-secondary; 55 | display: inline-block; 56 | vertical-align: middle; 57 | font-size: @font-size-base; 58 | margin-left: 40px; 59 | > span { 60 | line-height: 20px; 61 | } 62 | > p { 63 | margin-top: 4px; 64 | margin-bottom: 0; 65 | line-height: 22px; 66 | } 67 | } 68 | } 69 | .extraContentSearch { 70 | margin-left: 16px; 71 | width: 272px; 72 | } 73 | } 74 | 75 | @media screen and (max-width: @screen-xs) { 76 | .standardList { 77 | :global { 78 | .ant-list-item-content { 79 | display: block; 80 | flex: none; 81 | width: 100%; 82 | } 83 | .ant-list-item-action { 84 | margin-left: 0; 85 | } 86 | } 87 | .listContent { 88 | margin-left: 0; 89 | & > div { 90 | margin-left: 0; 91 | } 92 | } 93 | .listCard { 94 | :global { 95 | .ant-card-head-title { 96 | overflow: visible; 97 | } 98 | } 99 | } 100 | } 101 | } 102 | 103 | @media screen and (max-width: @screen-sm) { 104 | .standardList { 105 | .extraContentSearch { 106 | margin-left: 0; 107 | width: 100%; 108 | } 109 | .headerInfo { 110 | margin-bottom: 16px; 111 | & > em { 112 | display: none; 113 | } 114 | } 115 | } 116 | } 117 | 118 | @media screen and (max-width: @screen-md) { 119 | .standardList { 120 | .listContent { 121 | & > div { 122 | display: block; 123 | } 124 | & > div:last-child { 125 | top: 0; 126 | width: 100%; 127 | } 128 | } 129 | } 130 | .listCard { 131 | :global { 132 | .ant-radio-group { 133 | display: block; 134 | margin-bottom: 8px; 135 | } 136 | } 137 | } 138 | } 139 | 140 | @media screen and (max-width: @screen-lg) and (min-width: @screen-md) { 141 | .standardList { 142 | .listContent { 143 | & > div { 144 | display: block; 145 | } 146 | & > div:last-child { 147 | top: 0; 148 | width: 100%; 149 | } 150 | } 151 | } 152 | } 153 | 154 | @media screen and (max-width: @screen-xl) { 155 | .standardList { 156 | .listContent { 157 | & > div { 158 | margin-left: 24px; 159 | } 160 | & > div:last-child { 161 | top: 0; 162 | } 163 | } 164 | } 165 | } 166 | 167 | @media screen and (max-width: 1400px) { 168 | .standardList { 169 | .listContent { 170 | text-align: right; 171 | & > div:last-child { 172 | top: 0; 173 | } 174 | } 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /project/Forms/StepForm/Step1.js: -------------------------------------------------------------------------------- 1 | import React, { Fragment } from 'react'; 2 | import { connect } from 'dva'; 3 | import { Form, Input, Button, Select, Divider } from 'antd'; 4 | import { routerRedux } from 'dva/router'; 5 | import styles from './style.less'; 6 | 7 | const { Option } = Select; 8 | 9 | const formItemLayout = { 10 | labelCol: { 11 | span: 5, 12 | }, 13 | wrapperCol: { 14 | span: 19, 15 | }, 16 | }; 17 | 18 | @Form.create() 19 | class Step1 extends React.PureComponent { 20 | render() { 21 | const { form, dispatch, data } = this.props; 22 | const { getFieldDecorator, validateFields } = form; 23 | const onValidateForm = () => { 24 | validateFields((err, values) => { 25 | if (!err) { 26 | dispatch({ 27 | type: 'form/saveStepFormData', 28 | payload: values, 29 | }); 30 | dispatch(routerRedux.push('/form/step-form/confirm')); 31 | } 32 | }); 33 | }; 34 | return ( 35 | 36 |
37 | 38 | {getFieldDecorator('payAccount', { 39 | initialValue: data.payAccount, 40 | rules: [{ required: true, message: '請選擇付款賬戶' }], 41 | })( 42 | 45 | )} 46 | 47 | 48 | 49 | 53 | {getFieldDecorator('receiverAccount', { 54 | initialValue: data.receiverAccount, 55 | rules: [ 56 | { required: true, message: '請輸入收款人賬戶' }, 57 | { type: 'email', message: '賬戶名應為郵箱格式' }, 58 | ], 59 | })()} 60 | 61 | 62 | 63 | {getFieldDecorator('receiverName', { 64 | initialValue: data.receiverName, 65 | rules: [{ required: true, message: '請輸入收款人姓名' }], 66 | })()} 67 | 68 | 69 | {getFieldDecorator('amount', { 70 | initialValue: data.amount, 71 | rules: [ 72 | { required: true, message: '請輸入轉賬金額' }, 73 | { 74 | pattern: /^(\d+)((?:\.\d+)?)$/, 75 | message: '請輸入合法金額數字', 76 | }, 77 | ], 78 | })()} 79 | 80 | 90 | 93 | 94 |
95 | 96 |
97 |

說明

98 |

轉賬到支付寶賬戶

99 |

100 | 如果需要,這裏可以放壹些關於產品的常見問題說明。如果需要,這裏可以放壹些關於產品的常見問題說明。如果需要,這裏可以放壹些關於產品的常見問題說明。 101 |

102 |

轉賬到銀行卡

103 |

104 | 如果需要,這裏可以放壹些關於產品的常見問題說明。如果需要,這裏可以放壹些關於產品的常見問題說明。如果需要,這裏可以放壹些關於產品的常見問題說明。 105 |

106 |
107 |
108 | ); 109 | } 110 | } 111 | 112 | export default connect(({ form }) => ({ 113 | data: form.step, 114 | }))(Step1); 115 | -------------------------------------------------------------------------------- /project/List/BasicList.js: -------------------------------------------------------------------------------- 1 | import React, { PureComponent } from 'react'; 2 | import moment from 'moment'; 3 | import { connect } from 'dva'; 4 | import { 5 | List, 6 | Card, 7 | Row, 8 | Col, 9 | Radio, 10 | Input, 11 | Progress, 12 | Button, 13 | Icon, 14 | Dropdown, 15 | Menu, 16 | Avatar, 17 | } from 'antd'; 18 | 19 | import PageHeaderLayout from '../../layouts/PageHeaderLayout'; 20 | 21 | import styles from './BasicList.less'; 22 | 23 | const RadioButton = Radio.Button; 24 | const RadioGroup = Radio.Group; 25 | const { Search } = Input; 26 | 27 | @connect(({ list, loading }) => ({ 28 | list, 29 | loading: loading.models.list, 30 | })) 31 | export default class BasicList extends PureComponent { 32 | componentDidMount() { 33 | this.props.dispatch({ 34 | type: 'list/fetch', 35 | payload: { 36 | count: 5, 37 | }, 38 | }); 39 | } 40 | 41 | render() { 42 | const { list: { list }, loading } = this.props; 43 | 44 | const Info = ({ title, value, bordered }) => ( 45 |
46 | {title} 47 |

{value}

48 | {bordered && } 49 |
50 | ); 51 | 52 | const extraContent = ( 53 |
54 | 55 | 全部 56 | 進行中 57 | 等待中 58 | 59 | ({})} /> 60 |
61 | ); 62 | 63 | const paginationProps = { 64 | showSizeChanger: true, 65 | showQuickJumper: true, 66 | pageSize: 5, 67 | total: 50, 68 | }; 69 | 70 | const ListContent = ({ data: { owner, createdAt, percent, status } }) => ( 71 |
72 |
73 | Owner 74 |

{owner}

75 |
76 |
77 | 開始時間 78 |

{moment(createdAt).format('YYYY-MM-DD HH:mm')}

79 |
80 |
81 | 82 |
83 |
84 | ); 85 | 86 | const menu = ( 87 | 88 | 89 | 編輯 90 | 91 | 92 | 刪除 93 | 94 | 95 | ); 96 | 97 | const MoreBtn = () => ( 98 | 99 | 100 | 更多 101 | 102 | 103 | ); 104 | 105 | return ( 106 | 107 |
108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 130 | 133 | ( 140 | 編輯, ]}> 141 | } 143 | title={{item.title}} 144 | description={item.subDescription} 145 | /> 146 | 147 | 148 | )} 149 | /> 150 | 151 |
152 |
153 | ); 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /project/Dashboard/Workplace.less: -------------------------------------------------------------------------------- 1 | @import '~antd/lib/style/themes/default.less'; 2 | @import '../../utils/utils.less'; 3 | 4 | .activitiesList { 5 | padding: 0 24px 8px 24px; 6 | .username { 7 | color: @text-color; 8 | } 9 | .event { 10 | font-weight: normal; 11 | } 12 | } 13 | 14 | .pageHeaderContent { 15 | display: flex; 16 | .avatar { 17 | flex: 0 1 72px; 18 | margin-bottom: 8px; 19 | & > span { 20 | border-radius: 72px; 21 | display: block; 22 | width: 72px; 23 | height: 72px; 24 | } 25 | } 26 | .content { 27 | position: relative; 28 | top: 4px; 29 | margin-left: 24px; 30 | flex: 1 1 auto; 31 | color: @text-color-secondary; 32 | line-height: 22px; 33 | .contentTitle { 34 | font-size: 20px; 35 | line-height: 28px; 36 | font-weight: 500; 37 | color: @heading-color; 38 | margin-bottom: 12px; 39 | } 40 | } 41 | } 42 | 43 | .extraContent { 44 | .clearfix(); 45 | float: right; 46 | white-space: nowrap; 47 | .statItem { 48 | padding: 0 32px; 49 | position: relative; 50 | display: inline-block; 51 | > p:first-child { 52 | color: @text-color-secondary; 53 | font-size: @font-size-base; 54 | line-height: 22px; 55 | margin-bottom: 4px; 56 | } 57 | > p { 58 | color: @heading-color; 59 | font-size: 30px; 60 | line-height: 38px; 61 | margin: 0; 62 | > span { 63 | color: @text-color-secondary; 64 | font-size: 20px; 65 | } 66 | } 67 | &:after { 68 | background-color: @border-color-split; 69 | position: absolute; 70 | top: 8px; 71 | right: 0; 72 | width: 1px; 73 | height: 40px; 74 | content: ''; 75 | } 76 | &:last-child { 77 | padding-right: 0; 78 | &:after { 79 | display: none; 80 | } 81 | } 82 | } 83 | } 84 | 85 | .members { 86 | a { 87 | display: block; 88 | margin: 12px 0; 89 | line-height: 24px; 90 | height: 24px; 91 | .textOverflow(); 92 | .member { 93 | font-size: @font-size-base; 94 | color: @text-color; 95 | line-height: 24px; 96 | max-width: 100px; 97 | vertical-align: top; 98 | margin-left: 12px; 99 | transition: all 0.3s; 100 | display: inline-block; 101 | .textOverflow(); 102 | } 103 | &:hover { 104 | span { 105 | color: @primary-color; 106 | } 107 | } 108 | } 109 | } 110 | 111 | .projectList { 112 | :global { 113 | .ant-card-meta-description { 114 | color: @text-color-secondary; 115 | height: 44px; 116 | line-height: 22px; 117 | overflow: hidden; 118 | } 119 | } 120 | .cardTitle { 121 | font-size: 0; 122 | a { 123 | color: @heading-color; 124 | margin-left: 12px; 125 | line-height: 24px; 126 | height: 24px; 127 | display: inline-block; 128 | vertical-align: top; 129 | font-size: @font-size-base; 130 | &:hover { 131 | color: @primary-color; 132 | } 133 | } 134 | } 135 | .projectGrid { 136 | width: 33.33%; 137 | } 138 | .projectItemContent { 139 | display: flex; 140 | margin-top: 8px; 141 | overflow: hidden; 142 | font-size: 12px; 143 | height: 20px; 144 | line-height: 20px; 145 | .textOverflow(); 146 | a { 147 | color: @text-color-secondary; 148 | display: inline-block; 149 | flex: 1 1 0; 150 | .textOverflow(); 151 | &:hover { 152 | color: @primary-color; 153 | } 154 | } 155 | .datetime { 156 | color: @disabled-color; 157 | flex: 0 0 auto; 158 | float: right; 159 | } 160 | } 161 | } 162 | 163 | .datetime { 164 | color: @disabled-color; 165 | } 166 | 167 | @media screen and (max-width: @screen-xl) and (min-width: @screen-lg) { 168 | .activeCard { 169 | margin-bottom: 24px; 170 | } 171 | .members { 172 | margin-bottom: 0; 173 | } 174 | .extraContent { 175 | margin-left: -44px; 176 | .statItem { 177 | padding: 0 16px; 178 | } 179 | } 180 | } 181 | 182 | @media screen and (max-width: @screen-lg) { 183 | .activeCard { 184 | margin-bottom: 24px; 185 | } 186 | .members { 187 | margin-bottom: 0; 188 | } 189 | .extraContent { 190 | float: none; 191 | margin-right: 0; 192 | .statItem { 193 | padding: 0 16px; 194 | text-align: left; 195 | &:after { 196 | display: none; 197 | } 198 | } 199 | } 200 | } 201 | 202 | @media screen and (max-width: @screen-md) { 203 | .extraContent { 204 | margin-left: -16px; 205 | } 206 | .projectList { 207 | .projectGrid { 208 | width: 50%; 209 | } 210 | } 211 | } 212 | 213 | @media screen and (max-width: @screen-sm) { 214 | .pageHeaderContent { 215 | display: block; 216 | .content { 217 | margin-left: 0; 218 | } 219 | } 220 | .extraContent { 221 | .statItem { 222 | float: none; 223 | } 224 | } 225 | } 226 | 227 | @media screen and (max-width: @screen-xs) { 228 | .projectList { 229 | .projectGrid { 230 | width: 100%; 231 | } 232 | } 233 | } 234 | -------------------------------------------------------------------------------- /project/Dashboard/Monitor.js: -------------------------------------------------------------------------------- 1 | import React, { PureComponent, Fragment } from 'react'; 2 | import { connect } from 'dva'; 3 | import { Row, Col, Card, Tooltip } from 'antd'; 4 | import numeral from 'numeral'; 5 | import { Pie, WaterWave, Gauge, TagCloud } from 'components/Charts'; 6 | import NumberInfo from 'components/NumberInfo'; 7 | import CountDown from 'components/CountDown'; 8 | import ActiveChart from 'components/ActiveChart'; 9 | import Authorized from '../../utils/Authorized'; 10 | import styles from './Monitor.less'; 11 | 12 | const { Secured } = Authorized; 13 | 14 | const targetTime = new Date().getTime() + 3900000; 15 | 16 | // use permission as a parameter 17 | const havePermissionAsync = new Promise(resolve => { 18 | // Call resolve on behalf of passed 19 | setTimeout(() => resolve(), 1000); 20 | }); 21 | @Secured(havePermissionAsync) 22 | @connect(({ monitor, loading }) => ({ 23 | monitor, 24 | loading: loading.models.monitor, 25 | })) 26 | export default class Monitor extends PureComponent { 27 | componentDidMount() { 28 | this.props.dispatch({ 29 | type: 'monitor/fetchTags', 30 | }); 31 | } 32 | 33 | render() { 34 | const { monitor, loading } = this.props; 35 | const { tags } = monitor; 36 | 37 | return ( 38 | 39 | 40 | 41 | 42 | 43 | 44 | 49 | 50 | 51 | 52 | 53 | 54 | } /> 55 | 56 | 57 | 62 | 63 | 64 |
65 | 66 | map 70 | 71 |
72 |
73 | 74 | 75 | 76 | 77 | 78 | 84 | 85 | 86 | 87 |
88 | 89 | 90 | 91 | 92 | 93 | 101 | 102 | 103 | 112 | 113 | 114 | 123 | 124 | 125 | 126 | 127 | 128 | 134 | 135 | 136 | 137 | 138 | 143 | 144 | 145 | 146 | 147 |
148 | ); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /project/Profile/BasicProfile.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { connect } from 'dva'; 3 | import { Card, Badge, Table, Divider } from 'antd'; 4 | import DescriptionList from 'components/DescriptionList'; 5 | import PageHeaderLayout from '../../layouts/PageHeaderLayout'; 6 | import styles from './BasicProfile.less'; 7 | 8 | const { Description } = DescriptionList; 9 | 10 | const progressColumns = [ 11 | { 12 | title: '時間', 13 | dataIndex: 'time', 14 | key: 'time', 15 | }, 16 | { 17 | title: '當前進度', 18 | dataIndex: 'rate', 19 | key: 'rate', 20 | }, 21 | { 22 | title: '狀態', 23 | dataIndex: 'status', 24 | key: 'status', 25 | render: text => 26 | text === 'success' ? ( 27 | 28 | ) : ( 29 | 30 | ), 31 | }, 32 | { 33 | title: '操作員ID', 34 | dataIndex: 'operator', 35 | key: 'operator', 36 | }, 37 | { 38 | title: '耗時', 39 | dataIndex: 'cost', 40 | key: 'cost', 41 | }, 42 | ]; 43 | 44 | @connect(({ profile, loading }) => ({ 45 | profile, 46 | loading: loading.effects['profile/fetchBasic'], 47 | })) 48 | export default class BasicProfile extends Component { 49 | componentDidMount() { 50 | const { dispatch } = this.props; 51 | dispatch({ 52 | type: 'profile/fetchBasic', 53 | }); 54 | } 55 | 56 | render() { 57 | const { profile, loading } = this.props; 58 | const { basicGoods, basicProgress } = profile; 59 | let goodsData = []; 60 | if (basicGoods.length) { 61 | let num = 0; 62 | let amount = 0; 63 | basicGoods.forEach(item => { 64 | num += Number(item.num); 65 | amount += Number(item.amount); 66 | }); 67 | goodsData = basicGoods.concat({ 68 | id: '總計', 69 | num, 70 | amount, 71 | }); 72 | } 73 | const renderContent = (value, row, index) => { 74 | const obj = { 75 | children: value, 76 | props: {}, 77 | }; 78 | if (index === basicGoods.length) { 79 | obj.props.colSpan = 0; 80 | } 81 | return obj; 82 | }; 83 | const goodsColumns = [ 84 | { 85 | title: '商品編號', 86 | dataIndex: 'id', 87 | key: 'id', 88 | render: (text, row, index) => { 89 | if (index < basicGoods.length) { 90 | return {text}; 91 | } 92 | return { 93 | children: 總計, 94 | props: { 95 | colSpan: 4, 96 | }, 97 | }; 98 | }, 99 | }, 100 | { 101 | title: '商品名稱', 102 | dataIndex: 'name', 103 | key: 'name', 104 | render: renderContent, 105 | }, 106 | { 107 | title: '商品條碼', 108 | dataIndex: 'barcode', 109 | key: 'barcode', 110 | render: renderContent, 111 | }, 112 | { 113 | title: '單價', 114 | dataIndex: 'price', 115 | key: 'price', 116 | align: 'right', 117 | render: renderContent, 118 | }, 119 | { 120 | title: '數量(件)', 121 | dataIndex: 'num', 122 | key: 'num', 123 | align: 'right', 124 | render: (text, row, index) => { 125 | if (index < basicGoods.length) { 126 | return text; 127 | } 128 | return {text}; 129 | }, 130 | }, 131 | { 132 | title: '金額', 133 | dataIndex: 'amount', 134 | key: 'amount', 135 | align: 'right', 136 | render: (text, row, index) => { 137 | if (index < basicGoods.length) { 138 | return text; 139 | } 140 | return {text}; 141 | }, 142 | }, 143 | ]; 144 | return ( 145 | 146 | 147 | 148 | 1000000000 149 | 已取貨 150 | 1234123421 151 | 3214321432 152 | 153 | 154 | 155 | 付小小 156 | 18100000000 157 | 菜鳥倉儲 158 | 浙江省杭州市西湖區萬塘路18號 159 | 160 | 161 | 162 |
退貨商品
163 | 171 |
退貨進度
172 |
179 | 180 | 181 | ); 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /project/List/Projects.js: -------------------------------------------------------------------------------- 1 | import React, { PureComponent } from 'react'; 2 | import moment from 'moment'; 3 | import { connect } from 'dva'; 4 | import { Row, Col, Form, Card, Select, List } from 'antd'; 5 | 6 | import TagSelect from 'components/TagSelect'; 7 | import AvatarList from 'components/AvatarList'; 8 | import Ellipsis from 'components/Ellipsis'; 9 | import StandardFormRow from 'components/StandardFormRow'; 10 | 11 | import styles from './Projects.less'; 12 | 13 | const { Option } = Select; 14 | const FormItem = Form.Item; 15 | 16 | /* eslint react/no-array-index-key: 0 */ 17 | @Form.create() 18 | @connect(({ list, loading }) => ({ 19 | list, 20 | loading: loading.models.list, 21 | })) 22 | export default class CoverCardList extends PureComponent { 23 | componentDidMount() { 24 | this.props.dispatch({ 25 | type: 'list/fetch', 26 | payload: { 27 | count: 8, 28 | }, 29 | }); 30 | } 31 | 32 | handleFormSubmit = () => { 33 | const { form, dispatch } = this.props; 34 | // setTimeout 用於保證獲取表單值是在所有表單字段更新完畢的時候 35 | setTimeout(() => { 36 | form.validateFields(err => { 37 | if (!err) { 38 | // eslint-disable-next-line 39 | dispatch({ 40 | type: 'list/fetch', 41 | payload: { 42 | count: 8, 43 | }, 44 | }); 45 | } 46 | }); 47 | }, 0); 48 | }; 49 | 50 | render() { 51 | const { list: { list = [] }, loading, form } = this.props; 52 | const { getFieldDecorator } = form; 53 | 54 | const cardList = list ? ( 55 | ( 61 | 62 | } 66 | > 67 | {item.title}} 69 | description={{item.subDescription}} 70 | /> 71 |
72 | {moment(item.updatedAt).fromNow()} 73 |
74 | 75 | {item.members.map((member, i) => ( 76 | 81 | ))} 82 | 83 |
84 |
85 |
86 |
87 | )} 88 | /> 89 | ) : null; 90 | 91 | const formItemLayout = { 92 | wrapperCol: { 93 | xs: { span: 24 }, 94 | sm: { span: 16 }, 95 | }, 96 | }; 97 | 98 | return ( 99 |
100 | 101 |
102 | 103 | 104 | {getFieldDecorator('category')( 105 | 106 | 類目壹 107 | 類目二 108 | 類目三 109 | 類目四 110 | 類目五 111 | 類目六 112 | 類目七 113 | 類目八 114 | 類目九 115 | 類目十 116 | 類目十壹 117 | 類目十二 118 | 119 | )} 120 | 121 | 122 | 123 | 124 |
125 | 126 | {getFieldDecorator('author', {})( 127 | 134 | )} 135 | 136 | 137 | 138 | 139 | {getFieldDecorator('rate', {})( 140 | 148 | )} 149 | 150 | 151 | 152 | 153 | 154 | 155 |
{cardList}
156 | 157 | ); 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /project/Forms/BasicForm.js: -------------------------------------------------------------------------------- 1 | import React, { PureComponent } from 'react'; 2 | import { connect } from 'dva'; 3 | import { 4 | Form, 5 | Input, 6 | DatePicker, 7 | Select, 8 | Button, 9 | Card, 10 | InputNumber, 11 | Radio, 12 | Icon, 13 | Tooltip, 14 | } from 'antd'; 15 | import PageHeaderLayout from '../../layouts/PageHeaderLayout'; 16 | import styles from './style.less'; 17 | 18 | const FormItem = Form.Item; 19 | const { Option } = Select; 20 | const { RangePicker } = DatePicker; 21 | const { TextArea } = Input; 22 | 23 | @connect(({ loading }) => ({ 24 | submitting: loading.effects['form/submitRegularForm'], 25 | })) 26 | @Form.create() 27 | export default class BasicForms extends PureComponent { 28 | handleSubmit = e => { 29 | e.preventDefault(); 30 | this.props.form.validateFieldsAndScroll((err, values) => { 31 | if (!err) { 32 | this.props.dispatch({ 33 | type: 'form/submitRegularForm', 34 | payload: values, 35 | }); 36 | } 37 | }); 38 | }; 39 | render() { 40 | const { submitting } = this.props; 41 | const { getFieldDecorator, getFieldValue } = this.props.form; 42 | 43 | const formItemLayout = { 44 | labelCol: { 45 | xs: { span: 24 }, 46 | sm: { span: 7 }, 47 | }, 48 | wrapperCol: { 49 | xs: { span: 24 }, 50 | sm: { span: 12 }, 51 | md: { span: 10 }, 52 | }, 53 | }; 54 | 55 | const submitFormLayout = { 56 | wrapperCol: { 57 | xs: { span: 24, offset: 0 }, 58 | sm: { span: 10, offset: 7 }, 59 | }, 60 | }; 61 | 62 | return ( 63 | 67 | 68 |
69 | 70 | {getFieldDecorator('title', { 71 | rules: [ 72 | { 73 | required: true, 74 | message: '請輸入標題', 75 | }, 76 | ], 77 | })()} 78 | 79 | 80 | {getFieldDecorator('date', { 81 | rules: [ 82 | { 83 | required: true, 84 | message: '請選擇起止日期', 85 | }, 86 | ], 87 | })()} 88 | 89 | 90 | {getFieldDecorator('goal', { 91 | rules: [ 92 | { 93 | required: true, 94 | message: '請輸入目標描述', 95 | }, 96 | ], 97 | })( 98 |