diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000000000000000000000000000000000..8e90ca6d5026b261dd5e7af54bbe65eddda0a94b --- /dev/null +++ b/.dockerignore @@ -0,0 +1,35 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +**/node_modules +/src/utils/request-temp.js + +# production +/.vscode + +# misc +.DS_Store +npm-debug.log* +yarn-error.log + +/coverage +.idea +yarn.lock +package-lock.json +*bak +.vscode + +# visual studio code +.history +*.log + +functions/mock +.temp/** + +# umi +.umi +.umi-production + +# screenshot +screenshot +.firebase \ No newline at end of file diff --git a/.firebaserc b/.firebaserc new file mode 100644 index 0000000000000000000000000000000000000000..e3a9a50c8a53831595f67ab41862f94d8f050bd0 --- /dev/null +++ b/.firebaserc @@ -0,0 +1,5 @@ +{ + "projects": { + "default": "antd-pro" + } +} diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000000000000000000000000000000000..9e41f2e9f60185335b67843d8d9b57466b9c3ee8 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at afc163@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..7cbc5c31cd95e3cad949c50aa02103e126ae0c83 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM circleci/node:latest-browsers + +WORKDIR /usr/src/app/ +USER root +COPY package.json ./ +RUN yarn + +COPY ./ ./ + +RUN npm run test:all + +CMD ["npm", "run", "build"] diff --git a/Dockerfile.dev b/Dockerfile.dev new file mode 100644 index 0000000000000000000000000000000000000000..f5a50e58a0cde0d980516f3fba9cccde02afcf9a --- /dev/null +++ b/Dockerfile.dev @@ -0,0 +1,11 @@ +FROM node:latest + +WORKDIR /usr/src/app/ + +COPY package.json ./ +RUN npm install --silent --no-cache + +COPY ./ ./ + + +CMD ["npm", "run", "start"] diff --git a/Dockerfile.hub b/Dockerfile.hub new file mode 100644 index 0000000000000000000000000000000000000000..2e9c1ec9133f1762656e6bdc2672a1802bd24186 --- /dev/null +++ b/Dockerfile.hub @@ -0,0 +1,11 @@ +FROM nginx + +WORKDIR /usr/src/app/ + +COPY ./docker/nginx.conf /etc/nginx/conf.d/default.conf + +COPY ./dist /usr/share/nginx/html/ + +EXPOSE 80 + +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/config/config.js b/config/config.js index 264dcab33af4164c73bcaf26e019ec60d485acf7..fafb1484874e3e306cc23e6988fab48c75f03401 100644 --- a/config/config.js +++ b/config/config.js @@ -1,89 +1,143 @@ -// ref: https://umijs.org/config/ -import { primaryColor } from '../src/defaultSettings'; +// https://umijs.org/config/ +import os from 'os'; +import webpackPlugin from './plugin.config'; +import defaultSettings from '../src/defaultSettings'; +import slash from 'slash2'; -export default { - plugins: [ - [ - 'umi-plugin-react', - { - antd: true, - dva: { - hmr: true, - }, - targets: { - ie: 11, - }, - locale: { - enable: true, // default false - default: 'zh-CN', // default zh-CN - baseNavigator: true, // default true, when it is true, will use `navigator.language` overwrite default - }, - dynamicImport: { - loadingComponent: './components/PageLoading/index', - }, +const plugins = [ + [ + 'umi-plugin-react', + { + antd: true, + dva: { + hmr: true, + }, + locale: { + enable: true, // default false + default: 'zh-CN', // default zh-CN + baseNavigator: true, // default true, when it is true, will use `navigator.language` overwrite default }, - ], - [ - 'umi-plugin-pro-block', - { - moveMock: false, - moveService: false, - modifyRequest: true, - autoAddMenu: true, + dynamicImport: { + loadingComponent: './components/PageLoading/index', + webpackChunkName: true, + }, + pwa: { + workboxPluginMode: 'InjectManifest', + workboxOptions: { + importWorkboxFrom: 'local', + }, }, - ], + }, + ], + [ + 'umi-plugin-pro-block', + { + moveMock: false, + moveService: false, + modifyRequest: true, + autoAddMenu: true, + }, ], + // ...(!process.env.TEST && os.platform() === 'darwin' + // ? { + // dll: { + // include: ['dva', 'dva/router', 'dva/saga', 'dva/fetch'], + // exclude: ['@babel/runtime'], + // }, + // hardSource: true, + // } + // : {}), +]; + +// 针对 preview.pro.ant.design 的 GA 统计代码 +// 业务上不需要这个 +if (process.env.APP_TYPE === 'site') { + plugins.push([ + 'umi-plugin-ga', + { + code: 'UA-72788897-6', + }, + ]); +} + +export default { + // add for transfer to umi + plugins, + define: { + APP_TYPE: process.env.APP_TYPE || '', + }, + treeShaking: true, targets: { ie: 11, }, - - /** - * 路由相关配置 - */ + // 路由配置 routes: [ { path: '/user', - component: '../layouts/UserLayout', - routes: [{ path: '/user', component: './Welcome' }], + components: ['../layouts/UserLayout'], + routes: [], }, { path: '/', component: '../layouts/BasicLayout', + Routes: ['src/pages/Authorized'], + authority: ['admin', 'user'], routes: [ - { path: '/', redirect: '/welcome' }, // dashboard { - path: '/welcome', + path: '/', name: 'welcome', icon: 'smile', component: './Welcome', }, - { - path: 'https://github.com/umijs/umi-blocks/tree/master/ant-design-pro', - name: 'more-blocks', - icon: 'block', - }, ], }, ], - disableRedirectHoist: true, - - /** - * webpack 相关配置 - */ - define: { - APP_TYPE: process.env.APP_TYPE || '', - }, // Theme for antd // https://ant.design/docs/react/customize-theme-cn theme: { - 'primary-color': primaryColor, + 'primary-color': defaultSettings.primaryColor, }, externals: { '@antv/data-set': 'DataSet', }, + // proxy: { + // '/server/api/': { + // target: 'https://preview.pro.ant.design/', + // changeOrigin: true, + // pathRewrite: { '^/server': '' }, + // }, + // }, ignoreMomentLocale: true, lessLoaderOptions: { javascriptEnabled: true, }, + disableRedirectHoist: true, + cssLoaderOptions: { + modules: true, + getLocalIdent: (context, localIdentName, localName) => { + if ( + context.resourcePath.includes('node_modules') || + context.resourcePath.includes('ant.design.pro.less') || + context.resourcePath.includes('global.less') + ) { + return localName; + } + const match = context.resourcePath.match(/src(.*)/); + if (match && match[1]) { + const antdProPath = match[1].replace('.less', ''); + const arr = slash(antdProPath) + .split('/') + .map(a => a.replace(/([A-Z])/g, '-$1')) + .map(a => a.toLowerCase()); + return `antd-pro${arr.join('-')}-${localName}`.replace(/--/g, '-'); + } + return localName; + }, + }, + manifest: { + basePath: '/', + }, + + chainWebpack: webpackPlugin, }; diff --git a/config/plugin.config.js b/config/plugin.config.js new file mode 100644 index 0000000000000000000000000000000000000000..b9e842d26a900cceb0880b75c3e5c7489cb0c81f --- /dev/null +++ b/config/plugin.config.js @@ -0,0 +1,33 @@ +// Change theme plugin + +import MergeLessPlugin from 'antd-pro-merge-less'; +import AntDesignThemePlugin from 'antd-theme-webpack-plugin'; +import path from 'path'; + +export default config => { + // pro 和 开发环境再添加这个插件 + if (process.env.APP_TYPE === 'site' || process.env.NODE_ENV !== 'production') { + // 将所有 less 合并为一个供 themePlugin使用 + const outFile = path.join(__dirname, '../.temp/ant-design-pro.less'); + const stylesDir = path.join(__dirname, '../src/'); + + config.plugin('merge-less').use(MergeLessPlugin, [ + { + stylesDir, + outFile, + }, + ]); + + config.plugin('ant-design-theme').use(AntDesignThemePlugin, [ + { + antDir: path.join(__dirname, '../node_modules/antd'), + stylesDir, + varFile: path.join(__dirname, '../node_modules/antd/lib/style/themes/default.less'), + mainLessFile: outFile, // themeVariables: ['@primary-color'], + indexFileName: 'index.html', + generateOne: true, + lessUrl: 'https://gw.alipayobjects.com/os/lib/less.js/3.8.1/less.min.js', + }, + ]); + } +}; diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.dev.yml new file mode 100644 index 0000000000000000000000000000000000000000..d7ab2138339a456e9c46e830b8692545c712fbc2 --- /dev/null +++ b/docker/docker-compose.dev.yml @@ -0,0 +1,14 @@ +version: "3.5" + +services: + ant-design-pro_dev: + ports: + - 8000:8000 + build: + context: ../ + dockerfile: Dockerfile.dev + container_name: "ant-design-pro_dev" + volumes: + - ../src:/usr/src/app/src + - ../config:/usr/src/app/config + - ../mock:/usr/src/app/mock diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..d055600644912e1af5010c0461808caa7b756b96 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,21 @@ +version: "3.5" + +services: + ant-design-pro_build: + build: ../ + container_name: "ant-design-pro_build" + volumes: + - dist:/usr/src/app/dist + + ant-design-pro_web: + image: nginx + ports: + - 80:80 + container_name: "ant-design-pro_web" + restart: unless-stopped + volumes: + - dist:/usr/share/nginx/html:ro + - ./nginx.conf:/etc/nginx/conf.d/default.conf + +volumes: + dist: diff --git a/docker/nginx.conf b/docker/nginx.conf new file mode 100644 index 0000000000000000000000000000000000000000..5f86992c8fbb8accbb878e6c9c93366d1ab8eb26 --- /dev/null +++ b/docker/nginx.conf @@ -0,0 +1,22 @@ +server { + listen 80; + # gzip config + gzip on; + gzip_min_length 1k; + gzip_comp_level 9; + gzip_types text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml; + gzip_vary on; + gzip_disable "MSIE [1-6]\."; + + root /usr/share/nginx/html; + + location / { + try_files $uri $uri/ /index.html; + } + location /api { + proxy_pass https://preview.pro.ant.design; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + } +} diff --git a/firebase.json b/firebase.json new file mode 100644 index 0000000000000000000000000000000000000000..a00223d4ddce6ed47ef14af8e3b78f86294c0706 --- /dev/null +++ b/firebase.json @@ -0,0 +1,13 @@ +{ + "hosting": { + "public": "dist", + "rewrites": [ + { "source": "/api/**", "function": "api" }, + { + "source": "**", + "destination": "/index.html" + } + ], + "ignore": ["firebase.json", "**/.*", "**/node_modules/**"] + } +} diff --git a/netlify.toml b/netlify.toml new file mode 100644 index 0000000000000000000000000000000000000000..18b22e9d58b17ae991caaa6f96317b1aeac87f93 --- /dev/null +++ b/netlify.toml @@ -0,0 +1,13 @@ +[[redirects]] + from = "/api/*" + to = "https://us-central1-antd-pro.cloudfunctions.net/api/api/:splat" + status = 200 + force = true + [redirects.headers] + X-From = "Netlify" + X-Api-Key = "some-api-key-string" + +[[redirects]] + from = "/*" + to = "/index.html" + status = 200 \ No newline at end of file diff --git a/package.json b/package.json index 411c81d1c6588c9c06555aff6887980652c24525..850c474544ddafe1157ef7968be5c5956926f8df 100644 --- a/package.json +++ b/package.json @@ -38,11 +38,13 @@ "lodash-decorators": "^6.0.0", "memoize-one": "^5.0.0", "moment": "^2.22.2", + "omit.js": "^1.0.0", "path-to-regexp": "^2.4.0", "prop-types": "^15.5.10", "rc-animate": "^2.4.4", "react": "^16.6.3", "react-container-query": "^0.11.0", + "react-copy-to-clipboard": "^5.0.1", "react-document-title": "^2.0.3", "react-media": "^1.8.0", "umi-request": "^1.0.0" diff --git a/scripts/generateMock.js b/scripts/generateMock.js new file mode 100644 index 0000000000000000000000000000000000000000..54c7d6d624fcefd98cec3600538284a5056910a7 --- /dev/null +++ b/scripts/generateMock.js @@ -0,0 +1,3 @@ +const generateMock = require('merge-umi-mock-data'); +const path = require('path'); +generateMock(path.join(__dirname, '../mock'), path.join(__dirname, '../functions/mock/index.js')); diff --git a/src/components/SettingDrawer/ThemeColor.js b/src/components/SettingDrawer/ThemeColor.js new file mode 100644 index 0000000000000000000000000000000000000000..e5d66d4be5cb29a2684eff46734e06fba17d6923 --- /dev/null +++ b/src/components/SettingDrawer/ThemeColor.js @@ -0,0 +1,74 @@ +import React from 'react'; +import { Tooltip, Icon } from 'antd'; +import { formatMessage } from 'umi/locale'; +import styles from './ThemeColor.less'; + +const Tag = ({ color, check, ...rest }) => ( +
+ {check ? : ''} +
+); + +const ThemeColor = ({ colors, title, value, onChange }) => { + let colorList = colors; + if (!colors) { + colorList = [ + { + key: 'dust', + color: '#F5222D', + }, + { + key: 'volcano', + color: '#FA541C', + }, + { + key: 'sunset', + color: '#FAAD14', + }, + { + key: 'cyan', + color: '#13C2C2', + }, + { + key: 'green', + color: '#52C41A', + }, + { + key: 'daybreak', + color: '#1890FF', + }, + { + key: 'geekblue', + color: '#2F54EB', + }, + { + key: 'purple', + color: '#722ED1', + }, + ]; + } + return ( +
+

{title}

+
+ {colorList.map(({ key, color }) => ( + + onChange && onChange(color)} + /> + + ))} +
+
+ ); +}; + +export default ThemeColor; diff --git a/src/components/SettingDrawer/ThemeColor.less b/src/components/SettingDrawer/ThemeColor.less new file mode 100644 index 0000000000000000000000000000000000000000..4983eb9c67d207cfa4f9470a5a82068eb9c20c71 --- /dev/null +++ b/src/components/SettingDrawer/ThemeColor.less @@ -0,0 +1,21 @@ +.themeColor { + overflow: hidden; + margin-top: 24px; + .title { + font-size: 14px; + color: rgba(0, 0, 0, 0.65); + line-height: 22px; + margin-bottom: 12px; + } + .colorBlock { + width: 20px; + height: 20px; + border-radius: 2px; + float: left; + cursor: pointer; + margin-right: 8px; + text-align: center; + color: #fff; + font-weight: bold; + } +} diff --git a/src/components/SettingDrawer/index.less b/src/components/SettingDrawer/index.less new file mode 100644 index 0000000000000000000000000000000000000000..af4109be3a3293a4cbdee09eda6a7355d20d62a2 --- /dev/null +++ b/src/components/SettingDrawer/index.less @@ -0,0 +1,74 @@ +@import '~antd/lib/style/themes/default.less'; + +.content { + min-height: 100%; + background: #fff; + position: relative; +} + +.blockChecbox { + display: flex; + .item { + margin-right: 16px; + position: relative; + // box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1); + border-radius: @border-radius-base; + cursor: pointer; + img { + width: 48px; + } + } + .selectIcon { + position: absolute; + top: 0; + right: 0; + width: 100%; + padding-top: 15px; + padding-left: 24px; + height: 100%; + color: @primary-color; + font-size: 14px; + font-weight: bold; + } +} + +.color_block { + width: 38px; + height: 22px; + margin: 4px; + border-radius: 4px; + cursor: pointer; + margin-right: 12px; + display: inline-block; + vertical-align: middle; +} + +.title { + font-size: 14px; + color: @heading-color; + line-height: 22px; + margin-bottom: 12px; +} + +.handle { + position: absolute; + top: 240px; + background: @primary-color; + width: 48px; + height: 48px; + right: 300px; + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; + pointer-events: auto; + z-index: 0; + text-align: center; + font-size: 16px; + border-radius: 4px 0 0 4px; +} + +.productionHint { + font-size: 12px; + margin-top: 16px; +} diff --git a/src/global.js b/src/global.js new file mode 100644 index 0000000000000000000000000000000000000000..62f8ccebefe899371f39e0419cc3f82d514fafc9 --- /dev/null +++ b/src/global.js @@ -0,0 +1,54 @@ +import React from 'react'; +import { notification, Button, message } from 'antd'; +import { formatMessage } from 'umi/locale'; + +// Notify user if offline now +window.addEventListener('sw.offline', () => { + message.warning(formatMessage({ id: 'app.pwa.offline' })); +}); + +// Pop up a prompt on the page asking the user if they want to use the latest version +window.addEventListener('sw.updated', e => { + const reloadSW = async () => { + // Check if there is sw whose state is waiting in ServiceWorkerRegistration + // https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration + const worker = e.detail && e.detail.waiting; + if (!worker) { + return Promise.resolve(); + } + // Send skip-waiting event to waiting SW with MessageChannel + await new Promise((resolve, reject) => { + const channel = new MessageChannel(); + channel.port1.onmessage = event => { + if (event.data.error) { + reject(event.data.error); + } else { + resolve(event.data); + } + }; + worker.postMessage({ type: 'skip-waiting' }, [channel.port2]); + }); + // Refresh current page to use the updated HTML and other assets after SW has skiped waiting + window.location.reload(true); + return true; + }; + const key = `open${Date.now()}`; + const btn = ( + + ); + notification.open({ + message: formatMessage({ id: 'app.pwa.serviceworker.updated' }), + description: formatMessage({ id: 'app.pwa.serviceworker.updated.hint' }), + btn, + key, + onClose: async () => {}, + }); +}); diff --git a/src/layouts/BasicLayout.js b/src/layouts/BasicLayout.js index 512272b3e27cc22a0f389e85769e178adaaa8c12..cb97621204d2b3af43dbbed007ae41457f487b45 100644 --- a/src/layouts/BasicLayout.js +++ b/src/layouts/BasicLayout.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { Suspense } from 'react'; import { Layout } from 'antd'; import DocumentTitle from 'react-document-title'; import isEqual from 'lodash/isEqual'; @@ -14,10 +14,14 @@ import logo from '../assets/logo.svg'; import Footer from './Footer'; import Header from './Header'; import Context from './MenuContext'; +import PageLoading from '@/components/PageLoading'; import SiderMenu from '@/components/SiderMenu'; import { title } from '../defaultSettings'; import styles from './BasicLayout.less'; +// lazy load SettingDrawer +const SettingDrawer = React.lazy(() => import('@/components/SettingDrawer')); + const { Content } = Layout; const query = { @@ -139,6 +143,15 @@ class BasicLayout extends React.PureComponent { }); }; + renderSettingDrawer = () => { + // Do not render SettingDrawer in production + // unless it is deployed in preview.pro.ant.design as demo + if (process.env.NODE_ENV === 'production' && APP_TYPE !== 'site') { + return null; + } + return ; + }; + render() { const { navTheme, @@ -200,6 +213,7 @@ class BasicLayout extends React.PureComponent { )} + }>{this.renderSettingDrawer()} ); } diff --git a/src/locales/en-US.js b/src/locales/en-US.js index 7b8aea318cd87c503e71cbdaa911152cd22e2f65..7cc113872924fccae97d5df3840de6287634c242 100644 --- a/src/locales/en-US.js +++ b/src/locales/en-US.js @@ -1,6 +1,8 @@ import globalHeader from './en-US/globalHeader'; import menu from './en-US/menu'; +import settingDrawer from './en-US/settingDrawer'; import settings from './en-US/settings'; +import pwa from './en-US/pwa'; export default { 'navBar.lang': 'Languages', @@ -10,5 +12,7 @@ export default { 'app.home.introduce': 'introduce', ...globalHeader, ...menu, + ...settingDrawer, ...settings, + ...pwa, }; diff --git a/src/locales/en-US/pwa.js b/src/locales/en-US/pwa.js new file mode 100644 index 0000000000000000000000000000000000000000..ed8d199ead182b5e0834de03410de2eb19167a88 --- /dev/null +++ b/src/locales/en-US/pwa.js @@ -0,0 +1,6 @@ +export default { + 'app.pwa.offline': 'You are offline now', + 'app.pwa.serviceworker.updated': 'New content is available', + 'app.pwa.serviceworker.updated.hint': 'Please press the "Refresh" button to reload current page', + 'app.pwa.serviceworker.updated.ok': 'Refresh', +}; diff --git a/src/locales/en-US/settingDrawer.js b/src/locales/en-US/settingDrawer.js new file mode 100644 index 0000000000000000000000000000000000000000..a644905e756eb70d4a2677d6979a5895d78ebbbb --- /dev/null +++ b/src/locales/en-US/settingDrawer.js @@ -0,0 +1,31 @@ +export default { + 'app.setting.pagestyle': 'Page style setting', + 'app.setting.pagestyle.dark': 'Dark style', + 'app.setting.pagestyle.light': 'Light style', + 'app.setting.content-width': 'Content Width', + 'app.setting.content-width.fixed': 'Fixed', + 'app.setting.content-width.fluid': 'Fluid', + 'app.setting.themecolor': 'Theme Color', + 'app.setting.themecolor.dust': 'Dust Red', + 'app.setting.themecolor.volcano': 'Volcano', + 'app.setting.themecolor.sunset': 'Sunset Orange', + 'app.setting.themecolor.cyan': 'Cyan', + 'app.setting.themecolor.green': 'Polar Green', + 'app.setting.themecolor.daybreak': 'Daybreak Blue (default)', + 'app.setting.themecolor.geekblue': 'Geek Glue', + 'app.setting.themecolor.purple': 'Golden Purple', + 'app.setting.navigationmode': 'Navigation Mode', + 'app.setting.sidemenu': 'Side Menu Layout', + 'app.setting.topmenu': 'Top Menu Layout', + 'app.setting.fixedheader': 'Fixed Header', + 'app.setting.fixedsidebar': 'Fixed Sidebar', + 'app.setting.fixedsidebar.hint': 'Works on Side Menu Layout', + 'app.setting.hideheader': 'Hidden Header when scrolling', + 'app.setting.hideheader.hint': 'Works when Hidden Header is enabled', + 'app.setting.othersettings': 'Other Settings', + 'app.setting.weakmode': 'Weak Mode', + 'app.setting.copy': 'Copy Setting', + 'app.setting.copyinfo': 'copy success,please replace defaultSettings in src/models/setting.js', + 'app.setting.production.hint': + 'Setting panel shows in development environment only, please manually modify', +}; diff --git a/src/locales/pt-BR.js b/src/locales/pt-BR.js index bc8e6149e0f9fac37ba58c884a0472c2ba48b7fa..b4c456f060a10036c484ae6282c9b1e3c7d27cdc 100644 --- a/src/locales/pt-BR.js +++ b/src/locales/pt-BR.js @@ -1,6 +1,8 @@ import globalHeader from './pt-BR/globalHeader'; import menu from './pt-BR/menu'; +import settingDrawer from './pt-BR/settingDrawer'; import settings from './pt-BR/settings'; +import pwa from './pt-BR/pwa'; export default { 'navBar.lang': 'Idiomas', @@ -10,5 +12,7 @@ export default { 'app.home.introduce': 'introduzir', ...globalHeader, ...menu, + ...settingDrawer, ...settings, + ...pwa, }; diff --git a/src/locales/pt-BR/pwa.js b/src/locales/pt-BR/pwa.js new file mode 100644 index 0000000000000000000000000000000000000000..05cc79784227229ec18ed0b7598e6a03db6bb7d7 --- /dev/null +++ b/src/locales/pt-BR/pwa.js @@ -0,0 +1,7 @@ +export default { + 'app.pwa.offline': 'Você está offline agora', + 'app.pwa.serviceworker.updated': 'Novo conteúdo está disponível', + 'app.pwa.serviceworker.updated.hint': + 'Por favor, pressione o botão "Atualizar" para recarregar a página atual', + 'app.pwa.serviceworker.updated.ok': 'Atualizar', +}; diff --git a/src/locales/pt-BR/settingDrawer.js b/src/locales/pt-BR/settingDrawer.js new file mode 100644 index 0000000000000000000000000000000000000000..8a10b57e2d9ddf2a4de00eba5b4da1bef0ebedb0 --- /dev/null +++ b/src/locales/pt-BR/settingDrawer.js @@ -0,0 +1,32 @@ +export default { + 'app.setting.pagestyle': 'Configuração de estilo da página', + 'app.setting.pagestyle.dark': 'Dark style', + 'app.setting.pagestyle.light': 'Light style', + 'app.setting.content-width': 'Largura do conteúdo', + 'app.setting.content-width.fixed': 'Fixo', + 'app.setting.content-width.fluid': 'Fluido', + 'app.setting.themecolor': 'Cor do Tema', + 'app.setting.themecolor.dust': 'Dust Red', + 'app.setting.themecolor.volcano': 'Volcano', + 'app.setting.themecolor.sunset': 'Sunset Orange', + 'app.setting.themecolor.cyan': 'Cyan', + 'app.setting.themecolor.green': 'Polar Green', + 'app.setting.themecolor.daybreak': 'Daybreak Blue (default)', + 'app.setting.themecolor.geekblue': 'Geek Glue', + 'app.setting.themecolor.purple': 'Golden Purple', + 'app.setting.navigationmode': 'Modo de Navegação', + 'app.setting.sidemenu': 'Layout do Menu Lateral', + 'app.setting.topmenu': 'Layout do Menu Superior', + 'app.setting.fixedheader': 'Cabeçalho fixo', + 'app.setting.fixedsidebar': 'Barra lateral fixa', + 'app.setting.fixedsidebar.hint': 'Funciona no layout do menu lateral', + 'app.setting.hideheader': 'Esconder o cabeçalho quando rolar', + 'app.setting.hideheader.hint': 'Funciona quando o esconder cabeçalho está abilitado', + 'app.setting.othersettings': 'Outras configurações', + 'app.setting.weakmode': 'Weak Mode', + 'app.setting.copy': 'Copiar Configuração', + 'app.setting.copyinfo': + 'copiado com sucesso,por favor trocar o defaultSettings em src/models/setting.js', + 'app.setting.production.hint': + 'O painel de configuração apenas é exibido no ambiente de desenvolvimento, por favor modifique manualmente o', +}; diff --git a/src/locales/zh-CN.js b/src/locales/zh-CN.js index eedffaf79708bbec76d57b7f47f0aa3633d20f2c..273a7f6a4e11596efc558ff8aad0495d94687ad7 100644 --- a/src/locales/zh-CN.js +++ b/src/locales/zh-CN.js @@ -1,6 +1,8 @@ import globalHeader from './zh-CN/globalHeader'; import menu from './zh-CN/menu'; +import settingDrawer from './zh-CN/settingDrawer'; import settings from './zh-CN/settings'; +import pwa from './zh-CN/pwa'; export default { 'navBar.lang': '语言', @@ -10,5 +12,7 @@ export default { 'app.home.introduce': '介绍', ...globalHeader, ...menu, + ...settingDrawer, ...settings, + ...pwa, }; diff --git a/src/locales/zh-CN/pwa.js b/src/locales/zh-CN/pwa.js new file mode 100644 index 0000000000000000000000000000000000000000..e9504849e7840c963295ac2f732a68136a1e48f0 --- /dev/null +++ b/src/locales/zh-CN/pwa.js @@ -0,0 +1,6 @@ +export default { + 'app.pwa.offline': '当前处于离线状态', + 'app.pwa.serviceworker.updated': '有新内容', + 'app.pwa.serviceworker.updated.hint': '请点击“刷新”按钮或者手动刷新页面', + 'app.pwa.serviceworker.updated.ok': '刷新', +}; diff --git a/src/locales/zh-CN/settingDrawer.js b/src/locales/zh-CN/settingDrawer.js new file mode 100644 index 0000000000000000000000000000000000000000..15685a4055eb61174e39ad8eb6308cca7517af91 --- /dev/null +++ b/src/locales/zh-CN/settingDrawer.js @@ -0,0 +1,31 @@ +export default { + 'app.setting.pagestyle': '整体风格设置', + 'app.setting.pagestyle.dark': '暗色菜单风格', + 'app.setting.pagestyle.light': '亮色菜单风格', + 'app.setting.content-width': '内容区域宽度', + 'app.setting.content-width.fixed': '定宽', + 'app.setting.content-width.fluid': '流式', + 'app.setting.themecolor': '主题色', + 'app.setting.themecolor.dust': '薄暮', + 'app.setting.themecolor.volcano': '火山', + 'app.setting.themecolor.sunset': '日暮', + 'app.setting.themecolor.cyan': '明青', + 'app.setting.themecolor.green': '极光绿', + 'app.setting.themecolor.daybreak': '拂晓蓝(默认)', + 'app.setting.themecolor.geekblue': '极客蓝', + 'app.setting.themecolor.purple': '酱紫', + 'app.setting.navigationmode': '导航模式', + 'app.setting.sidemenu': '侧边菜单布局', + 'app.setting.topmenu': '顶部菜单布局', + 'app.setting.fixedheader': '固定 Header', + 'app.setting.fixedsidebar': '固定侧边菜单', + 'app.setting.fixedsidebar.hint': '侧边菜单布局时可配置', + 'app.setting.hideheader': '下滑时隐藏 Header', + 'app.setting.hideheader.hint': '固定 Header 时可配置', + 'app.setting.othersettings': '其他设置', + 'app.setting.weakmode': '色弱模式', + 'app.setting.copy': '拷贝设置', + 'app.setting.copyinfo': '拷贝成功,请到 src/defaultSettings.js 中替换默认配置', + 'app.setting.production.hint': + '配置栏只在开发环境用于预览,生产环境不会展现,请拷贝后手动修改配置文件', +}; diff --git a/src/locales/zh-TW.js b/src/locales/zh-TW.js index 5c5b4d299bad455148e824938d8278c6084d54c5..35d483401ec776afef19d702b9ea863e527363d5 100644 --- a/src/locales/zh-TW.js +++ b/src/locales/zh-TW.js @@ -1,6 +1,8 @@ import globalHeader from './zh-TW/globalHeader'; import menu from './zh-TW/menu'; +import settingDrawer from './zh-TW/settingDrawer'; import settings from './zh-TW/settings'; +import pwa from './zh-TW/pwa'; export default { 'navBar.lang': '語言', @@ -13,5 +15,7 @@ export default { '表單頁用於向用戶收集或驗證信息,基礎表單常見於數據項較少的表單場景。', ...globalHeader, ...menu, + ...settingDrawer, ...settings, + ...pwa, }; diff --git a/src/locales/zh-TW/pwa.js b/src/locales/zh-TW/pwa.js new file mode 100644 index 0000000000000000000000000000000000000000..108a6e489be8e7567ac6d41cd7d81d7715020b3b --- /dev/null +++ b/src/locales/zh-TW/pwa.js @@ -0,0 +1,6 @@ +export default { + 'app.pwa.offline': '當前處於離線狀態', + 'app.pwa.serviceworker.updated': '有新內容', + 'app.pwa.serviceworker.updated.hint': '請點擊“刷新”按鈕或者手動刷新頁面', + 'app.pwa.serviceworker.updated.ok': '刷新', +}; diff --git a/src/locales/zh-TW/settingDrawer.js b/src/locales/zh-TW/settingDrawer.js new file mode 100644 index 0000000000000000000000000000000000000000..24dc281fa87e613c41824a78bf6561eaa0152a6d --- /dev/null +++ b/src/locales/zh-TW/settingDrawer.js @@ -0,0 +1,31 @@ +export default { + 'app.setting.pagestyle': '整體風格設置', + 'app.setting.pagestyle.dark': '暗色菜單風格', + 'app.setting.pagestyle.light': '亮色菜單風格', + 'app.setting.content-width': '內容區域寬度', + 'app.setting.content-width.fixed': '定寬', + 'app.setting.content-width.fluid': '流式', + 'app.setting.themecolor': '主題色', + 'app.setting.themecolor.dust': '薄暮', + 'app.setting.themecolor.volcano': '火山', + 'app.setting.themecolor.sunset': '日暮', + 'app.setting.themecolor.cyan': '明青', + 'app.setting.themecolor.green': '極光綠', + 'app.setting.themecolor.daybreak': '拂曉藍(默認)', + 'app.setting.themecolor.geekblue': '極客藍', + 'app.setting.themecolor.purple': '醬紫', + 'app.setting.navigationmode': '導航模式', + 'app.setting.sidemenu': '側邊菜單布局', + 'app.setting.topmenu': '頂部菜單布局', + 'app.setting.fixedheader': '固定 Header', + 'app.setting.fixedsidebar': '固定側邊菜單', + 'app.setting.fixedsidebar.hint': '側邊菜單布局時可配置', + 'app.setting.hideheader': '下滑時隱藏 Header', + 'app.setting.hideheader.hint': '固定 Header 時可配置', + 'app.setting.othersettings': '其他設置', + 'app.setting.weakmode': '色弱模式', + 'app.setting.copy': '拷貝設置', + 'app.setting.copyinfo': '拷貝成功,請到 src/defaultSettings.js 中替換默認配置', + 'app.setting.production.hint': + '配置欄只在開發環境用於預覽,生產環境不會展現,請拷貝後手動修改配置文件', +}; diff --git a/src/manifest.json b/src/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..839bc5b5e4a561676fca44a61674d3990b5acd48 --- /dev/null +++ b/src/manifest.json @@ -0,0 +1,22 @@ +{ + "name": "Ant Design Pro", + "short_name": "Ant Design Pro", + "display": "standalone", + "start_url": "./?utm_source=homescreen", + "theme_color": "#002140", + "background_color": "#001529", + "icons": [ + { + "src": "icons/icon-192x192.png", + "sizes": "192x192" + }, + { + "src": "icons/icon-128x128.png", + "sizes": "128x128" + }, + { + "src": "icons/icon-512x512.png", + "sizes": "512x512" + } + ] +} diff --git a/src/pages/Authorized.js b/src/pages/Authorized.js new file mode 100644 index 0000000000000000000000000000000000000000..5c1b819925522c4cd43bb745a2bf160d3337f475 --- /dev/null +++ b/src/pages/Authorized.js @@ -0,0 +1,13 @@ +import React from 'react'; +import RenderAuthorized from 'ant-design-pro/lib/Authorized'; +import { getAuthority } from '@/utils/authority'; +import Redirect from 'umi/redirect'; + +const Authority = getAuthority(); +const Authorized = RenderAuthorized(Authority); + +export default ({ children }) => ( + }> + {children} + +); diff --git a/src/service-worker.js b/src/service-worker.js new file mode 100644 index 0000000000000000000000000000000000000000..48d43c2545b6bd9e92ba6fce550dfbccbc3615f3 --- /dev/null +++ b/src/service-worker.js @@ -0,0 +1,65 @@ +/* globals workbox */ +/* eslint-disable no-restricted-globals */ +workbox.core.setCacheNameDetails({ + prefix: 'antd-pro', + suffix: 'v1', +}); +// Control all opened tabs ASAP +workbox.clientsClaim(); + +/** + * Use precaching list generated by workbox in build process. + * https://developers.google.com/web/tools/workbox/reference-docs/latest/workbox.precaching + */ +/* eslint-disable no-underscore-dangle */ +workbox.precaching.precacheAndRoute(self.__precacheManifest || []); + +/** + * Register a navigation route. + * https://developers.google.com/web/tools/workbox/modules/workbox-routing#how_to_register_a_navigation_route + */ +workbox.routing.registerNavigationRoute('/index.html'); + +/** + * Use runtime cache: + * https://developers.google.com/web/tools/workbox/reference-docs/latest/workbox.routing#.registerRoute + * + * Workbox provides all common caching strategies including CacheFirst, NetworkFirst etc. + * https://developers.google.com/web/tools/workbox/reference-docs/latest/workbox.strategies + */ + +/** + * Handle API requests + */ +workbox.routing.registerRoute(/\/api\//, workbox.strategies.networkFirst()); + +/** + * Handle third party requests + */ +workbox.routing.registerRoute( + /^https:\/\/gw.alipayobjects.com\//, + workbox.strategies.networkFirst() +); +workbox.routing.registerRoute( + /^https:\/\/cdnjs.cloudflare.com\//, + workbox.strategies.networkFirst() +); +workbox.routing.registerRoute(/\/color.less/, workbox.strategies.networkFirst()); + +/** + * Response to client after skipping waiting with MessageChannel + */ +addEventListener('message', event => { + const replyPort = event.ports[0]; + const message = event.data; + if (replyPort && message && message.type === 'skip-waiting') { + event.waitUntil( + self + .skipWaiting() + .then( + () => replyPort.postMessage({ error: null }), + error => replyPort.postMessage({ error }) + ) + ); + } +}); diff --git a/webpack.config.js b/webpack.config.js deleted file mode 100644 index 4acb27a907aefe273907d906f169a33612d3a0bd..0000000000000000000000000000000000000000 --- a/webpack.config.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * 不是真实的 webpack 配置,仅为兼容 webstorm 和 intellij idea 代码跳转 - * ref: https://github.com/umijs/umi/issues/1109#issuecomment-423380125 - */ - -module.exports = { - resolve: { - alias: { - '@': require('path').resolve(__dirname, 'src'), // eslint-disable-line - }, - }, -};