├── .gitignore ├── 1.1 数据结构:栈 ├── demo01.html ├── demo02.html ├── demo03.html └── demo04.html ├── 1.1.1 数组与Map ├── index.html └── process.html ├── 1.2 数据结构:堆 ├── demo01.html └── demo02.html ├── 1.3 数据结构:队列 └── demo01.html ├── 1.4 数据结构:链表 └── demo01.html ├── 2.1 函数 └── 状态管理模块.html ├── 2.13 函数组合 ├── demo01.html └── demo02.html ├── 2.14 柯里化 ├── 1.js └── index.html ├── 2.2 作用域与作用域链 └── demo01.html ├── 2.3 函数调用栈 ├── demo01.html └── demo02.html ├── 2.4 执行上下文 └── demo01.html ├── 2.5 闭包 ├── demo01.html ├── demo02.html ├── demo03.html ├── demo04.html ├── demo05.html └── test.html ├── 2.7 this └── demo01.html ├── 2.8 函数式编程 └── demo01.html ├── 3.0 对象 ├── demo01.html ├── demo02.html ├── demo03.html ├── demo04.html └── demo05.html ├── 3.1 一切始于封装 └── demo.html ├── 3.16 运动框架 ├── demo.html └── index.js ├── 4.6 jQuery 封装思维 └── index.html ├── 4.7 拖拽 ├── index.html └── index.js ├── 4.8 选项卡对象 ├── index.html └── index.js ├── 4.9 无缝滚动对象 ├── index.html └── index.js ├── 5.2 单例模式 ├── 1.js ├── 2.js ├── 3.js ├── 4.js └── index.html ├── 5.3 工厂模式 ├── 1.js ├── 2.js ├── 3.js ├── 4.js ├── 5.js └── index.html ├── 5.4 观察者模式 ├── 1.js ├── 2.js ├── 3.js ├── 4.js └── index.html ├── 5.5 代理模式 ├── 1.js ├── 2.js └── index.html ├── 5.6 策略模式 ├── 1.js ├── 2.js ├── 3.js └── index.html ├── 5.7 装饰者模式 ├── 1.js ├── 2.js └── index.html ├── 6.1 ES6常用语法 ├── 1.js ├── 2.js ├── 3.js └── index.html ├── 6.6 Promise封装 ├── 1.js ├── 2.js ├── index.html └── promise.js ├── 6.7 事件循环 ├── 1.js ├── 2.js ├── 3.js ├── 4.js ├── 5.js ├── 6.js ├── 7.js ├── 8.js └── index.html ├── 6.8 模块化 ├── 1.js ├── 2.js ├── 3.js ├── 4.js ├── 5.js ├── 6.js └── index.html ├── 6.8.1 模块化语法 └── my-app │ ├── .eslintcache │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ ├── src │ ├── App.css │ ├── App.test.tsx │ ├── App.tsx │ ├── index.css │ ├── index.tsx │ ├── logo.svg │ ├── person.ts │ ├── person2.ts │ ├── react-app-env.d.ts │ ├── reportWebVitals.ts │ └── setupTests.ts │ ├── tsconfig.json │ └── yarn.lock ├── 6.9模块化开发实例 ├── controldiv │ ├── .eslintcache │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ ├── src │ │ ├── App.test.tsx │ │ ├── App.tsx │ │ ├── box.ts │ │ ├── controlButtons │ │ │ ├── bgColor.ts │ │ │ ├── borderColor.ts │ │ │ ├── height.ts │ │ │ ├── index.ts │ │ │ ├── show.ts │ │ │ └── width.ts │ │ ├── index.css │ │ ├── index.tsx │ │ ├── logo.svg │ │ ├── react-app-env.d.ts │ │ ├── register.ts │ │ ├── setupTests.ts │ │ ├── state.ts │ │ └── utils.ts │ ├── tsconfig.json │ └── yarn.lock └── zhihunew │ ├── .eslintcache │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ ├── src │ ├── App.css │ ├── App.test.tsx │ ├── App.tsx │ ├── api.ts │ ├── data.ts │ ├── index.css │ ├── index.tsx │ ├── logo.svg │ ├── react-app-env.d.ts │ ├── render.ts │ ├── reportWebVitals.ts │ ├── request.ts │ └── setupTests.ts │ ├── tsconfig.json │ └── yarn.lock ├── 7.1组件化 └── tab │ ├── .eslintcache │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ ├── src │ ├── App.css │ ├── App.test.tsx │ ├── App.tsx │ ├── Tabbar │ │ ├── index.css │ │ └── index.tsx │ ├── index.css │ ├── index.tsx │ ├── logo.svg │ ├── react-app-env.d.ts │ ├── reportWebVitals.ts │ ├── setupTests.ts │ ├── tab.css │ └── tab.ts │ ├── tsconfig.json │ └── yarn.lock ├── 7.2webpack ├── .gitignore ├── index.html ├── package-lock.json ├── package.json ├── src │ ├── inbox.jpg │ ├── index.css │ ├── index.js │ └── test.scss └── webpack.config.js ├── 7.3React └── controldiv │ ├── .eslintcache │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ ├── src │ ├── App.css │ ├── App.test.tsx │ ├── App.tsx │ ├── components │ │ └── Toast │ │ │ ├── Container.tsx │ │ │ ├── Item.tsx │ │ │ ├── container.css │ │ │ ├── index.tsx │ │ │ └── item.css │ ├── index.css │ ├── index.tsx │ ├── logo.svg │ ├── react-app-env.d.ts │ ├── reportWebVitals.ts │ └── setupTests.ts │ ├── tsconfig.json │ └── yarn.lock ├── 7.4admin ├── .gitignore ├── CODE_OF_CONDUCT.md ├── Dockerfile ├── Dockerfile.dev ├── Dockerfile.hub ├── LICENSE ├── README.ar-DZ.md ├── README.fr-FR.md ├── README.ja-JP.md ├── README.md ├── README.pt-BR.md ├── README.ru-RU.md ├── README.tr-TR.md ├── README.zh-CN.md ├── azure-pipelines.yml ├── config │ ├── config.dev.ts │ ├── config.ts │ ├── defaultSettings.ts │ └── proxy.ts ├── docker │ ├── docker-compose.dev.yml │ ├── docker-compose.yml │ └── nginx.conf ├── jest.config.js ├── jsconfig.json ├── mock │ ├── listTableList.ts │ ├── notices.ts │ ├── route.ts │ └── user.ts ├── package.json ├── public │ ├── CNAME │ ├── favicon.ico │ ├── home_bg.png │ ├── icons │ │ ├── icon-128x128.png │ │ ├── icon-192x192.png │ │ └── icon-512x512.png │ └── pro_icon.svg ├── src │ ├── assets │ │ └── logo.svg │ ├── components │ │ ├── Authorized │ │ │ ├── Authorized.tsx │ │ │ ├── AuthorizedRoute.tsx │ │ │ ├── CheckPermissions.tsx │ │ │ ├── PromiseRender.tsx │ │ │ ├── Secured.tsx │ │ │ ├── index.tsx │ │ │ └── renderAuthorize.ts │ │ ├── GlobalHeader │ │ │ ├── AvatarDropdown.tsx │ │ │ ├── NoticeIconView.tsx │ │ │ ├── RightContent.tsx │ │ │ └── index.less │ │ ├── HeaderDropdown │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── HeaderSearch │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── NoticeIcon │ │ │ ├── NoticeList.less │ │ │ ├── NoticeList.tsx │ │ │ ├── index.less │ │ │ └── index.tsx │ │ └── PageLoading │ │ │ └── index.tsx │ ├── e2e │ │ ├── __mocks__ │ │ │ └── antd-pro-merge-less.js │ │ └── baseLayout.e2e.js │ ├── global.less │ ├── global.tsx │ ├── layouts │ │ ├── BasicLayout.tsx │ │ ├── BlankLayout.tsx │ │ ├── SecurityLayout.tsx │ │ ├── UserLayout.less │ │ └── UserLayout.tsx │ ├── locales │ │ ├── en-US.ts │ │ ├── en-US │ │ │ ├── component.ts │ │ │ ├── globalHeader.ts │ │ │ ├── menu.ts │ │ │ ├── pages.ts │ │ │ ├── pwa.ts │ │ │ ├── settingDrawer.ts │ │ │ └── settings.ts │ │ ├── id-ID.ts │ │ ├── id-ID │ │ │ ├── component.ts │ │ │ ├── globalHeader.ts │ │ │ ├── menu.ts │ │ │ ├── pages.ts │ │ │ ├── pwa.ts │ │ │ ├── settingDrawer.ts │ │ │ └── settings.ts │ │ ├── ja-JP.ts │ │ ├── ja-JP │ │ │ ├── component.ts │ │ │ ├── globalHeader.ts │ │ │ ├── menu.ts │ │ │ ├── pages.ts │ │ │ ├── pwa.ts │ │ │ ├── settingDrawer.ts │ │ │ └── settings.ts │ │ ├── pt-BR.ts │ │ ├── pt-BR │ │ │ ├── component.ts │ │ │ ├── globalHeader.ts │ │ │ ├── menu.ts │ │ │ ├── pwa.ts │ │ │ ├── settingDrawer.ts │ │ │ └── settings.ts │ │ ├── zh-CN.ts │ │ ├── zh-CN │ │ │ ├── component.ts │ │ │ ├── globalHeader.ts │ │ │ ├── menu.ts │ │ │ ├── pages.ts │ │ │ ├── pwa.ts │ │ │ ├── settingDrawer.ts │ │ │ └── settings.ts │ │ ├── zh-TW.ts │ │ └── zh-TW │ │ │ ├── component.ts │ │ │ ├── globalHeader.ts │ │ │ ├── menu.ts │ │ │ ├── pwa.ts │ │ │ ├── settingDrawer.ts │ │ │ └── settings.ts │ ├── manifest.json │ ├── models │ │ ├── connect.d.ts │ │ ├── global.ts │ │ ├── login.ts │ │ ├── setting.ts │ │ └── user.ts │ ├── pages │ │ ├── 404.tsx │ │ ├── Admin.tsx │ │ ├── TableList │ │ │ ├── components │ │ │ │ └── UpdateForm.tsx │ │ │ ├── data.d.ts │ │ │ ├── index.tsx │ │ │ └── service.ts │ │ ├── User │ │ │ ├── login │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── register-result │ │ │ │ ├── index.tsx │ │ │ │ ├── locales │ │ │ │ │ ├── en-US.ts │ │ │ │ │ ├── zh-CN.ts │ │ │ │ │ └── zh-TW.ts │ │ │ │ └── style.less │ │ │ └── register │ │ │ │ ├── _mock.ts │ │ │ │ ├── index.tsx │ │ │ │ ├── locales │ │ │ │ ├── en-US.ts │ │ │ │ ├── zh-CN.ts │ │ │ │ └── zh-TW.ts │ │ │ │ ├── model.ts │ │ │ │ ├── service.ts │ │ │ │ └── style.less │ │ ├── Welcome.less │ │ ├── Welcome.tsx │ │ ├── account │ │ │ ├── center │ │ │ │ ├── Center.less │ │ │ │ ├── _mock.ts │ │ │ │ ├── components │ │ │ │ │ ├── Applications │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── ArticleListContent │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── Articles │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── AvatarList │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── Projects │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ └── index.tsx │ │ │ │ ├── data.d.ts │ │ │ │ ├── index.tsx │ │ │ │ ├── model.ts │ │ │ │ └── service.ts │ │ │ └── settings │ │ │ │ ├── _mock.ts │ │ │ │ ├── components │ │ │ │ ├── BaseView.less │ │ │ │ ├── GeographicView.less │ │ │ │ ├── GeographicView.tsx │ │ │ │ ├── PhoneView.less │ │ │ │ ├── PhoneView.tsx │ │ │ │ ├── base.tsx │ │ │ │ ├── binding.tsx │ │ │ │ ├── notification.tsx │ │ │ │ └── security.tsx │ │ │ │ ├── data.d.ts │ │ │ │ ├── geographic │ │ │ │ ├── city.json │ │ │ │ └── province.json │ │ │ │ ├── index.tsx │ │ │ │ ├── locales │ │ │ │ ├── en-US.ts │ │ │ │ ├── zh-CN.ts │ │ │ │ └── zh-TW.ts │ │ │ │ ├── model.ts │ │ │ │ ├── service.ts │ │ │ │ └── style.less │ │ ├── dashboard │ │ │ ├── analysis │ │ │ │ ├── _mock.ts │ │ │ │ ├── components │ │ │ │ │ ├── Charts │ │ │ │ │ │ ├── Bar │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── ChartCard │ │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── Field │ │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── Gauge │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── MiniArea │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── MiniBar │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── MiniProgress │ │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── Pie │ │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── TagCloud │ │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── TimelineChart │ │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── WaterWave │ │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── autoHeight.tsx │ │ │ │ │ │ ├── bizcharts.tsx │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── IntroduceRow.tsx │ │ │ │ │ ├── NumberInfo │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── OfflineData.tsx │ │ │ │ │ ├── PageLoading │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── ProportionSales.tsx │ │ │ │ │ ├── SalesCard.tsx │ │ │ │ │ ├── TopSearch.tsx │ │ │ │ │ └── Trend │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ └── index.tsx │ │ │ │ ├── data.d.ts │ │ │ │ ├── index.tsx │ │ │ │ ├── locales │ │ │ │ │ ├── en-US.ts │ │ │ │ │ ├── pt-BR.ts │ │ │ │ │ ├── zh-CN.ts │ │ │ │ │ └── zh-TW.ts │ │ │ │ ├── model.ts │ │ │ │ ├── service.ts │ │ │ │ ├── style.less │ │ │ │ └── utils │ │ │ │ │ ├── Yuan.tsx │ │ │ │ │ ├── utils.less │ │ │ │ │ └── utils.ts │ │ │ ├── monitor │ │ │ │ ├── _mock.ts │ │ │ │ ├── components │ │ │ │ │ ├── ActiveChart │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── Charts │ │ │ │ │ │ ├── Gauge │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── Map │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── MiniArea │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── Pie │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── TagCloud │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── WaterWave │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── autoHeight.tsx │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ └── index.tsx │ │ │ │ ├── data.d.ts │ │ │ │ ├── index.tsx │ │ │ │ ├── locales │ │ │ │ │ ├── en-US.ts │ │ │ │ │ ├── pt-BR.ts │ │ │ │ │ ├── zh-CN.ts │ │ │ │ │ └── zh-TW.ts │ │ │ │ ├── model.ts │ │ │ │ ├── service.ts │ │ │ │ └── style.less │ │ │ └── workplace │ │ │ │ ├── _mock.ts │ │ │ │ ├── components │ │ │ │ ├── EditableLinkGroup │ │ │ │ │ ├── index.less │ │ │ │ │ └── index.tsx │ │ │ │ └── Radar │ │ │ │ │ ├── autoHeight.tsx │ │ │ │ │ ├── index.less │ │ │ │ │ └── index.tsx │ │ │ │ ├── data.d.ts │ │ │ │ ├── index.tsx │ │ │ │ ├── model.ts │ │ │ │ ├── service.ts │ │ │ │ └── style.less │ │ ├── document.ejs │ │ ├── editor │ │ │ ├── flow │ │ │ │ ├── common │ │ │ │ │ └── IconFont │ │ │ │ │ │ └── index.ts │ │ │ │ ├── components │ │ │ │ │ ├── EditorContextMenu │ │ │ │ │ │ ├── FlowContextMenu.tsx │ │ │ │ │ │ ├── KoniContextMenu.tsx │ │ │ │ │ │ ├── MenuItem.tsx │ │ │ │ │ │ ├── MindContextMenu.tsx │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── EditorDetailPanel │ │ │ │ │ │ ├── DetailForm.tsx │ │ │ │ │ │ ├── FlowDetailPanel.tsx │ │ │ │ │ │ ├── KoniDetailPanel.tsx │ │ │ │ │ │ ├── MindDetailPanel.tsx │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── EditorItemPanel │ │ │ │ │ │ ├── FlowItemPanel.tsx │ │ │ │ │ │ ├── KoniItemPanel.tsx │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── EditorMinimap │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── EditorToolbar │ │ │ │ │ │ ├── FlowToolbar.tsx │ │ │ │ │ │ ├── KoniToolbar.tsx │ │ │ │ │ │ ├── MindToolbar.tsx │ │ │ │ │ │ ├── ToolbarButton.tsx │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ └── index.tsx │ │ │ │ ├── index.less │ │ │ │ ├── index.tsx │ │ │ │ └── locales │ │ │ │ │ ├── en-US.ts │ │ │ │ │ └── zh-CN.ts │ │ │ ├── koni │ │ │ │ ├── common │ │ │ │ │ └── IconFont │ │ │ │ │ │ └── index.ts │ │ │ │ ├── components │ │ │ │ │ ├── EditorContextMenu │ │ │ │ │ │ ├── FlowContextMenu.tsx │ │ │ │ │ │ ├── KoniContextMenu.tsx │ │ │ │ │ │ ├── MenuItem.tsx │ │ │ │ │ │ ├── MindContextMenu.tsx │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── EditorDetailPanel │ │ │ │ │ │ ├── DetailForm.tsx │ │ │ │ │ │ ├── FlowDetailPanel.tsx │ │ │ │ │ │ ├── KoniDetailPanel.tsx │ │ │ │ │ │ ├── MindDetailPanel.tsx │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── EditorItemPanel │ │ │ │ │ │ ├── FlowItemPanel.tsx │ │ │ │ │ │ ├── KoniItemPanel.tsx │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── EditorMinimap │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── EditorToolbar │ │ │ │ │ │ ├── FlowToolbar.tsx │ │ │ │ │ │ ├── KoniToolbar.tsx │ │ │ │ │ │ ├── MindToolbar.tsx │ │ │ │ │ │ ├── ToolbarButton.tsx │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ └── index.tsx │ │ │ │ ├── index.less │ │ │ │ ├── index.tsx │ │ │ │ └── locales │ │ │ │ │ ├── en-US.ts │ │ │ │ │ └── zh-CN.ts │ │ │ └── mind │ │ │ │ ├── common │ │ │ │ └── IconFont │ │ │ │ │ └── index.ts │ │ │ │ ├── components │ │ │ │ ├── EditorContextMenu │ │ │ │ │ ├── FlowContextMenu.tsx │ │ │ │ │ ├── KoniContextMenu.tsx │ │ │ │ │ ├── MenuItem.tsx │ │ │ │ │ ├── MindContextMenu.tsx │ │ │ │ │ ├── index.less │ │ │ │ │ └── index.tsx │ │ │ │ ├── EditorDetailPanel │ │ │ │ │ ├── DetailForm.tsx │ │ │ │ │ ├── FlowDetailPanel.tsx │ │ │ │ │ ├── KoniDetailPanel.tsx │ │ │ │ │ ├── MindDetailPanel.tsx │ │ │ │ │ ├── index.less │ │ │ │ │ └── index.tsx │ │ │ │ ├── EditorItemPanel │ │ │ │ │ ├── FlowItemPanel.tsx │ │ │ │ │ ├── KoniItemPanel.tsx │ │ │ │ │ ├── index.less │ │ │ │ │ └── index.tsx │ │ │ │ ├── EditorMinimap │ │ │ │ │ └── index.tsx │ │ │ │ └── EditorToolbar │ │ │ │ │ ├── FlowToolbar.tsx │ │ │ │ │ ├── KoniToolbar.tsx │ │ │ │ │ ├── MindToolbar.tsx │ │ │ │ │ ├── ToolbarButton.tsx │ │ │ │ │ ├── index.less │ │ │ │ │ └── index.tsx │ │ │ │ ├── index.less │ │ │ │ ├── index.tsx │ │ │ │ ├── locales │ │ │ │ ├── en-US.ts │ │ │ │ └── zh-CN.ts │ │ │ │ └── worldCup2018.json │ │ ├── exception │ │ │ ├── 403 │ │ │ │ └── index.tsx │ │ │ ├── 404 │ │ │ │ └── index.tsx │ │ │ └── 500 │ │ │ │ ├── index.tsx │ │ │ │ └── locales │ │ │ │ ├── en-US.ts │ │ │ │ ├── pt-BR.ts │ │ │ │ ├── zh-CN.ts │ │ │ │ └── zh-TW.ts │ │ ├── form │ │ │ ├── advanced-form │ │ │ │ ├── _mock.ts │ │ │ │ ├── components │ │ │ │ │ └── TableForm.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── model.ts │ │ │ │ ├── service.ts │ │ │ │ └── style.less │ │ │ ├── basic-form │ │ │ │ ├── _mock.ts │ │ │ │ ├── index.tsx │ │ │ │ ├── locales │ │ │ │ │ ├── en-US.ts │ │ │ │ │ ├── pt-BR.ts │ │ │ │ │ ├── zh-CN.ts │ │ │ │ │ └── zh-TW.ts │ │ │ │ ├── model.ts │ │ │ │ ├── service.ts │ │ │ │ └── style.less │ │ │ └── step-form │ │ │ │ ├── _mock.ts │ │ │ │ ├── components │ │ │ │ ├── Step1 │ │ │ │ │ ├── index.less │ │ │ │ │ └── index.tsx │ │ │ │ ├── Step2 │ │ │ │ │ ├── index.less │ │ │ │ │ └── index.tsx │ │ │ │ └── Step3 │ │ │ │ │ ├── index.less │ │ │ │ │ └── index.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── locales │ │ │ │ ├── en-US.ts │ │ │ │ ├── pt-BR.ts │ │ │ │ ├── zh-CN.ts │ │ │ │ └── zh-TW.ts │ │ │ │ ├── model.ts │ │ │ │ ├── service.ts │ │ │ │ └── style.less │ │ ├── list │ │ │ ├── basic-list │ │ │ │ ├── _mock.ts │ │ │ │ ├── components │ │ │ │ │ └── OperationModal.tsx │ │ │ │ ├── data.d.ts │ │ │ │ ├── index.tsx │ │ │ │ ├── model.ts │ │ │ │ ├── service.ts │ │ │ │ ├── style.less │ │ │ │ └── utils │ │ │ │ │ └── utils.less │ │ │ ├── card-list │ │ │ │ ├── _mock.ts │ │ │ │ ├── data.d.ts │ │ │ │ ├── index.tsx │ │ │ │ ├── model.ts │ │ │ │ ├── service.ts │ │ │ │ ├── style.less │ │ │ │ └── utils │ │ │ │ │ └── utils.less │ │ │ ├── search │ │ │ │ ├── applications │ │ │ │ │ ├── _mock.ts │ │ │ │ │ ├── components │ │ │ │ │ │ ├── StandardFormRow │ │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ └── TagSelect │ │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── data.d.ts │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── model.ts │ │ │ │ │ ├── service.ts │ │ │ │ │ ├── style.less │ │ │ │ │ └── utils │ │ │ │ │ │ └── utils.less │ │ │ │ ├── articles │ │ │ │ │ ├── _mock.ts │ │ │ │ │ ├── components │ │ │ │ │ │ ├── ArticleListContent │ │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── StandardFormRow │ │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ └── TagSelect │ │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── data.d.ts │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── model.ts │ │ │ │ │ ├── service.ts │ │ │ │ │ └── style.less │ │ │ │ ├── index.tsx │ │ │ │ └── projects │ │ │ │ │ ├── _mock.ts │ │ │ │ │ ├── components │ │ │ │ │ ├── AvatarList │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── StandardFormRow │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── TagSelect │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── data.d.ts │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── model.ts │ │ │ │ │ ├── service.ts │ │ │ │ │ ├── style.less │ │ │ │ │ └── utils │ │ │ │ │ └── utils.less │ │ │ └── table-list │ │ │ │ ├── _mock.ts │ │ │ │ ├── components │ │ │ │ ├── CreateForm.tsx │ │ │ │ └── UpdateForm.tsx │ │ │ │ ├── data.d.ts │ │ │ │ ├── index.tsx │ │ │ │ └── service.ts │ │ ├── profile │ │ │ ├── advanced │ │ │ │ ├── _mock.ts │ │ │ │ ├── data.d.ts │ │ │ │ ├── index.tsx │ │ │ │ ├── model.ts │ │ │ │ ├── service.ts │ │ │ │ └── style.less │ │ │ └── basic │ │ │ │ ├── _mock.ts │ │ │ │ ├── data.d.ts │ │ │ │ ├── index.tsx │ │ │ │ ├── model.ts │ │ │ │ ├── service.ts │ │ │ │ └── style.less │ │ └── result │ │ │ ├── fail │ │ │ ├── index.less │ │ │ ├── index.tsx │ │ │ └── locales │ │ │ │ ├── en-US.ts │ │ │ │ ├── zh-CN.ts │ │ │ │ └── zh-TW.ts │ │ │ └── success │ │ │ ├── index.less │ │ │ ├── index.tsx │ │ │ └── locales │ │ │ ├── en-US.ts │ │ │ ├── zh-CN.ts │ │ │ └── zh-TW.ts │ ├── service-worker.js │ ├── services │ │ ├── login.ts │ │ └── user.ts │ ├── typings.d.ts │ └── utils │ │ ├── Authorized.ts │ │ ├── authority.ts │ │ ├── request.ts │ │ ├── utils.less │ │ ├── utils.test.ts │ │ └── utils.ts ├── tests │ ├── PuppeteerEnvironment.js │ ├── beforeTest.js │ ├── getBrowser.js │ └── run-tests.js └── tsconfig.json ├── README.md └── other └── demo01.html /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | dist -------------------------------------------------------------------------------- /1.1 数据结构:栈/demo01.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 8 | 9 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /1.1.1 数组与Map/process.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 视频进度条 8 | 24 | 25 | 26 |
27 |
基础概念
28 |
火焰图及性能优化
29 |
栈的实现
30 |
栈的算法题
31 |
嵌套思维与实践场景
32 |
33 | 34 | 35 | -------------------------------------------------------------------------------- /2.14 柯里化/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 函数式编程 - 柯里化 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /2.3 函数调用栈/demo01.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 函数调用栈 7 | 8 | 9 | 26 | 27 | -------------------------------------------------------------------------------- /2.3 函数调用栈/demo02.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 函数调用栈:闭包 7 | 8 | 9 | 21 | 22 | -------------------------------------------------------------------------------- /2.4 执行上下文/demo01.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 执行上下文 7 | 8 | 9 | 24 | 25 | -------------------------------------------------------------------------------- /2.5 闭包/demo01.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 闭包 7 | 8 | 9 | 10 | 44 | 45 | -------------------------------------------------------------------------------- /2.5 闭包/demo02.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 闭包 7 | 8 | 9 | 10 | 56 | 57 | -------------------------------------------------------------------------------- /2.5 闭包/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 调试工具 7 | 8 | 9 | 10 | 29 | 30 | -------------------------------------------------------------------------------- /2.8 函数式编程/demo01.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 封装 7 | 8 | 9 | 10 | 11 | 34 | 35 | -------------------------------------------------------------------------------- /3.0 对象/demo01.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 对象 7 | 8 | 9 | 35 | 36 | -------------------------------------------------------------------------------- /3.0 对象/demo02.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 对象 7 | 8 | 9 | 40 | 41 | -------------------------------------------------------------------------------- /3.0 对象/demo03.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 对象 7 | 8 | 9 | 31 | 32 | -------------------------------------------------------------------------------- /3.0 对象/demo04.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 对象 7 | 8 | 9 | 20 | 21 | -------------------------------------------------------------------------------- /3.16 运动框架/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /4.7 拖拽/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 19 | 20 | 21 |
22 |
23 | 24 | 25 | -------------------------------------------------------------------------------- /5.2 单例模式/1.js: -------------------------------------------------------------------------------- 1 | class Login { 2 | // 使用静态属性在内存存储实例 3 | static instance = null 4 | constructor(parentNode) { 5 | // 判断,如果已经存在实例,直接返回该实例 6 | if (Login.instance) { 7 | return Login.instance 8 | } 9 | this.parentNode = parentNode 10 | this.render() 11 | Login.instance = this 12 | return this 13 | } 14 | 15 | show() { } 16 | hide() { } 17 | // 渲染 DOM 节点 18 | render() { } 19 | } 20 | 21 | const p2 = new Login() 22 | const p1 = new Login() 23 | 24 | console.log(p1 === p2) // true 25 | -------------------------------------------------------------------------------- /5.2 单例模式/2.js: -------------------------------------------------------------------------------- 1 | const Login = (function () { 2 | // 使用 闭包 在内存存储实例 3 | let instance = null 4 | class LoginComponent { 5 | constructor(parentNode) { 6 | // 判断,如果已经存在实例,直接返回该实例 7 | if (instance) { 8 | return instance 9 | } 10 | this.parentNode = parentNode 11 | this.render() 12 | instance = this 13 | return this 14 | } 15 | 16 | show() { } 17 | hide() { } 18 | // 渲染 DOM 节点 19 | render() { } 20 | } 21 | return LoginComponent 22 | })() 23 | 24 | const p2 = new Login() 25 | const p1 = new Login() 26 | 27 | console.log(p1 === p2) // true 28 | -------------------------------------------------------------------------------- /5.2 单例模式/3.js: -------------------------------------------------------------------------------- 1 | class Login { 2 | constructor() { } 3 | show() { } 4 | hide() { } 5 | // 渲染 DOM 节点 6 | render() { } 7 | } 8 | 9 | const LoginProxy = (function () { 10 | let instance = null 11 | return function() { 12 | if (!instance) { 13 | instance = new Login() 14 | } 15 | return instance 16 | } 17 | })() 18 | 19 | const p1 = new LoginProxy() 20 | const p2 = new LoginProxy() 21 | 22 | console.log(p1 === p2) -------------------------------------------------------------------------------- /5.2 单例模式/4.js: -------------------------------------------------------------------------------- 1 | class Login { 2 | constructor() { } 3 | show() { } 4 | hide() { } 5 | // 渲染 DOM 节点 6 | render() { } 7 | } 8 | 9 | function singleCreator(constructor) { 10 | let instance = null 11 | return function() { 12 | if (!instance) { 13 | instance = new constructor() 14 | } 15 | return instance 16 | } 17 | } 18 | 19 | const _Login = singleCreator(Login) 20 | 21 | const p1 = new _Login() 22 | const p2 = new _Login() 23 | console.log(p1) 24 | console.log(p1 === p2, 4) -------------------------------------------------------------------------------- /5.2 单例模式/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 单例模式 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /5.3 工厂模式/2.js: -------------------------------------------------------------------------------- 1 | class PhoneFactory { 2 | constructor(type) { 3 | if (type == 'xiaomi') { 4 | this.materials = { 5 | 1: 'xiaomi_material1', 6 | 2: 'xiaomi_material2', 7 | 3: 'xiaomi_material3', 8 | } 9 | } 10 | if (type == 'iphone') { 11 | this.materials = { 12 | 1: 'iphone_material1', 13 | 2: 'iphone_material2', 14 | 3: 'iphone_material3', 15 | } 16 | } 17 | if (type == 'huawei') { 18 | this.materials = { 19 | 1: 'huawei_material1', 20 | 2: 'huawei_material2', 21 | 3: 'huawei_material3', 22 | } 23 | } 24 | } 25 | step1() {} 26 | step2() {} 27 | step3() {} 28 | step4() {} 29 | } 30 | 31 | const xm = new PhoneFactory('xiaomi') 32 | const ip = new PhoneFactory('iphone') 33 | const hw = new PhoneFactory('huawei') 34 | 35 | function foo() {} 36 | 37 | function factory(type) { 38 | return new window[type]() 39 | } 40 | 41 | factory('foo') 42 | -------------------------------------------------------------------------------- /5.3 工厂模式/3.js: -------------------------------------------------------------------------------- 1 | function Factory() {} 2 | Factory.prototype.create = function(type) { 3 | var cur = this.config[type] 4 | if (cur) { 5 | return new this.config[type]() 6 | } 7 | } 8 | Factory.prototype.config = {} 9 | Factory.prototype.setConfig = function(type, sub) { 10 | this.config[type] = sub 11 | } 12 | 13 | 14 | class Xiaomi5 { 15 | constructor() { 16 | this.materials = { 17 | 1: 'xiaomi_material1', 18 | 2: 'xiaomi_material2', 19 | 3: 'xiaomi_material3', 20 | } 21 | } 22 | step1() {} 23 | step2() {} 24 | step3() {} 25 | step4() {} 26 | } 27 | 28 | new Factory().setConfig('xiaomi5', Xiaomi5) 29 | -------------------------------------------------------------------------------- /5.3 工厂模式/4.js: -------------------------------------------------------------------------------- 1 | const config = { 2 | xiaomi: { 3 | 1: 'xiaomi_material1', 4 | 2: 'xiaomi_material2', 5 | 3: 'xiaomi_material3', 6 | }, 7 | iphone: { 8 | 1: 'iphone_material1', 9 | 2: 'iphone_material2', 10 | 3: 'iphone_material3', 11 | }, 12 | huawei: { 13 | 1: 'huawei_material1', 14 | 2: 'huawei_material2', 15 | 3: 'huawei_material3', 16 | } 17 | } 18 | 19 | class PhoneFactory { 20 | constructor(type) { 21 | this.materials = config[type] 22 | } 23 | step1() {} 24 | step2() {} 25 | step3() {} 26 | step4() {} 27 | } 28 | 29 | const xm = new PhoneFactory('xiaomi') 30 | const ip = new PhoneFactory('iphone') 31 | const hw = new PhoneFactory('huawei') -------------------------------------------------------------------------------- /5.3 工厂模式/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 工厂模式 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /5.4 观察者模式/1.js: -------------------------------------------------------------------------------- 1 | var event = new Event('build') 2 | 3 | // 观察者 4 | document.addEventListener('build', function () { 5 | console.log('我是新增的一个观察者1,我现在观察到 document 触发了 build 事件') 6 | }) 7 | 8 | // 观察者 9 | document.addEventListener('build', function () { 10 | console.log('我是新增的一个观察者2,我现在观察到 document 触发了 build 事件') 11 | }) 12 | 13 | // 被观察者 触发事件 14 | document.dispatchEvent(event) -------------------------------------------------------------------------------- /5.4 观察者模式/2.js: -------------------------------------------------------------------------------- 1 | let subjectid = 0 2 | let observerid = 0 3 | 4 | class Subject { 5 | constructor(name) { 6 | // 观察者队列 7 | this.observers = [] 8 | this.id = subjectid++ 9 | this.name = name 10 | } 11 | 12 | // 添加观察者 13 | addListener(observer) { 14 | this.observers.push(observer) 15 | } 16 | 17 | // 删除观察者 18 | removeListener(observer) { 19 | this.observers = this.observers.filter(item => item.id !== observer.id) 20 | } 21 | 22 | // 通知 23 | dispatch() { 24 | this.observers.forEach(item => { 25 | item.watch(this.name) 26 | }) 27 | } 28 | } 29 | 30 | class Observer { 31 | constructor() { 32 | this.id = observerid++ 33 | } 34 | watch(subjectName) { 35 | console.log(`观察者${this.id}发现了被观察者 ${subjectName} 产生了变化。`) 36 | } 37 | } 38 | 39 | const sub = new Subject('div元素') 40 | const observer1 = new Observer() 41 | const observer2 = new Observer() 42 | 43 | sub.addListener(observer1) 44 | sub.addListener(observer2) 45 | 46 | sub.dispatch() 47 | -------------------------------------------------------------------------------- /5.4 观察者模式/3.js: -------------------------------------------------------------------------------- 1 | class Subject { 2 | constructor(name) { 3 | // 观察者队列 4 | // 格式为: { click: [fn1, fn2], scroll: [fn1, fn2] } 5 | this.events = {} 6 | this.name = name 7 | } 8 | 9 | // 添加观察者 10 | addListener(type, fn) { 11 | const cbs = this.events[type] 12 | if (cbs && cbs.length > 0) { 13 | const _cbs = cbs.filter(cb => cb != cbs) 14 | _cbs.push(fn) 15 | this.events[type] = _cbs 16 | } else { 17 | this.events[type] = [fn] 18 | } 19 | } 20 | 21 | // 删除观察者 22 | removeListener(type) { 23 | delete this.events[type] 24 | } 25 | 26 | // 通知 27 | dispatch(type) { 28 | this.events[type].forEach(cb => cb()) 29 | } 30 | } 31 | 32 | const sub = new Subject('div') 33 | 34 | sub.addListener('build', function() { 35 | console.log('build 事件触发1') 36 | }) 37 | sub.addListener('build', function () { 38 | console.log('build 事件触发2') 39 | }) 40 | sub.addListener('click', function() { 41 | console.log('click 事件触发') 42 | }) 43 | 44 | sub.dispatch('build') 45 | -------------------------------------------------------------------------------- /5.4 观察者模式/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 观察者模式 7 | 21 | 22 | 23 |
24 | 25 | 26 | -------------------------------------------------------------------------------- /5.5 代理模式/2.js: -------------------------------------------------------------------------------- 1 | var targetImage = (function () { 2 | var imgNode = document.createElement('img'); 3 | document.body.appendChild(imgNode); 4 | return { 5 | setSrc: function (src) { 6 | imgNode.src = src; 7 | } 8 | } 9 | })(); 10 | 11 | var proxyImage = (function() { 12 | var img = new Image(); 13 | // 先加载 loading 或者默认图片用于快速显示 14 | targetImage.setSrc('loading.gif') 15 | img.onload = img.onerror = function () { 16 | // 加载完成之后,替换目标图片 17 | targetImage.setSrc(img.src); 18 | }; 19 | 20 | return { 21 | setSrc: function (src) { 22 | // 此时开始加载图片 23 | img.src = src; 24 | } 25 | } 26 | })(); 27 | 28 | proxyImage.setSrc('https://cn.bing.com/sa/simg/hpb/LaDigue_EN-CA1115245085_1920x1080.jpg'); 29 | -------------------------------------------------------------------------------- /5.5 代理模式/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 代理模式 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /5.6 策略模式/1.js: -------------------------------------------------------------------------------- 1 | function getBouns(base, level) { 2 | if (level == 'A') { 3 | return base * 5 4 | } 5 | if (level == 'B') { 6 | return base * 4 7 | } 8 | if (level == 'C') { 9 | return base * 3 10 | } 11 | if (level == 'D') { 12 | return base * 2 13 | } 14 | if (level == 'E') { 15 | return base * 1 16 | } 17 | } 18 | 19 | 20 | const p1 = { 21 | name: '张三', 22 | base: 1000, 23 | level: 'A' 24 | } 25 | p1.bouns = getBouns(p1.base, p1.level) 26 | 27 | console.log(p1) -------------------------------------------------------------------------------- /5.6 策略模式/2.js: -------------------------------------------------------------------------------- 1 | const map = { 2 | A: function(base) { 3 | return base * 5 4 | }, 5 | B: function (base) { 6 | return base * 4 7 | }, 8 | C: function (base) { 9 | return base * 3 10 | }, 11 | D: function (base) { 12 | return base * 2 13 | }, 14 | E: function (base) { 15 | return base * 1 16 | }, 17 | } 18 | 19 | function getBouns(base, level) { 20 | return map[level](base) 21 | } 22 | 23 | 24 | const p2 = { 25 | name: '李四', 26 | base: 1200, 27 | level: 'B' 28 | } 29 | p2.bouns = getBouns(p2.base, p2.level) 30 | 31 | console.log(p2) -------------------------------------------------------------------------------- /5.6 策略模式/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 策略模式 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /5.7 装饰者模式/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 装饰者模式 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /6.1 ES6常用语法/1.js: -------------------------------------------------------------------------------- 1 | { 2 | let a = 20 3 | } 4 | 5 | // Uncaught ReferenceError: a is not defined 6 | console.log(a) -------------------------------------------------------------------------------- /6.1 ES6常用语法/3.js: -------------------------------------------------------------------------------- 1 | // var tom = { 2 | // name: 'TOM', 3 | // age: 20, 4 | // gender: 1, 5 | // job: 'studend' 6 | // } 7 | 8 | // const { 9 | // name: name, 10 | // age: age, 11 | // gender: gender, 12 | // job: job 13 | // } = tom; 14 | 15 | // const peoples = { 16 | // counts: 100, 17 | // detail: { 18 | // tom: { 19 | // name: 'tom', 20 | // age: 20, 21 | // gender: 1, 22 | // job: 'student' 23 | // } 24 | // } 25 | // } 26 | 27 | // // 获取tom 28 | // const { detail: { tom } } = peoples; 29 | 30 | // // 直接获取tom的age与gender 31 | // const { detail: { tom: { age, gender } } } = peoples; 32 | 33 | 34 | // var a = 10; 35 | // var b = 20; 36 | 37 | // [a, b] = [b, a]; 38 | // console.log(a); // 20 39 | // console.log(b); // 10 40 | 41 | 42 | const p = { 43 | name: 'tony' 44 | } 45 | p.__proto__.age = 20 46 | 47 | const {name, age} = p 48 | console.log(name, age) // tony 20 -------------------------------------------------------------------------------- /6.1 ES6常用语法/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ES6+ 常用语法 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /6.6 Promise封装/1.js: -------------------------------------------------------------------------------- 1 | const p = new MyPromise2((resolve, reject) => { 2 | setTimeout(() => { 3 | resolve('World') 4 | }, 1000) 5 | }) 6 | 7 | console.log(p) 8 | 9 | p.then(res => { 10 | console.log('1 then:', res) 11 | return 'hello ' + res 12 | }).then(res => { 13 | console.log('2 then:', res) 14 | }).catch(err => { 15 | console.log('catch', err) 16 | }).finally(() => { 17 | console.log('我都会执行') 18 | }) -------------------------------------------------------------------------------- /6.6 Promise封装/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 封装 Promise 对象 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /6.7 事件循环/1.js: -------------------------------------------------------------------------------- 1 | new Promise(resolve => { 2 | resolve() 3 | }) 4 | .then(() => { 5 | Promise(resolve => { 6 | resolve() 7 | }) 8 | .then(() => { 9 | console.log(1) 10 | }) 11 | .then(() => { 12 | console.log(2) 13 | }) 14 | .then(() => { 15 | console.log(3.1) 16 | }) 17 | }) 18 | .then(() => { 19 | console.log(1.1) 20 | new Promise((resolve => { 21 | resolve() 22 | })) 23 | .then(() => { 24 | new Promise(resolve => { 25 | resolve() 26 | }) 27 | .then(() => { 28 | console.log(4) 29 | }) 30 | .then(() => { 31 | console.log(6) 32 | }) 33 | }).then(() => { 34 | console.log(5) 35 | }) 36 | }) 37 | .then(() => { 38 | console.log(3) 39 | }) 40 | console.log(0) 41 | 42 | -------------------------------------------------------------------------------- /6.7 事件循环/2.js: -------------------------------------------------------------------------------- 1 | // 队列分析,数字表示右侧代码行数 2 | queue = [4] 3 | // 已经知道了 回调 4 的返回结果为 undefined,所以 18 也可以入列了 4 | queue = [8, 18] // 4 出列、8、18入列, 5 | 6 | // 执行 8,输出1,得知了 8 的返回结果为 undefined,11也可以入列 7 | queue = [18, 11] 8 | 9 | // 执行 18,输出 1.1,23 可直接入列,同时能得知 18 的返回结果,37入列 10 | queue = [11, 23, 37] 11 | 12 | // 执行 11,输出 2,得到11的返回结果,14可入列 13 | queue = [23, 37, 14] 14 | 15 | // 执行 23,27可直接入列,同时得到 23 的返回结果,33可直接入列 16 | queue = [37, 14, 27, 33] 17 | 18 | // 执行 37,输出 3 19 | queue = [14, 27, 33] 20 | 21 | // 执行 14,输出3.1 22 | queue = [27, 33] 23 | 24 | // 执行 27,输出 4,得到27的返回结果,30可直接入列 25 | queue = [33, 30] 26 | 27 | // 执行 33,输出 5 28 | queue = [30] 29 | 30 | // 执行 30,输出 6 31 | queue = [] 32 | 33 | // 输出结果 34 | // 0 35 | // 1 36 | // 1.1 37 | // 2 38 | // 3 39 | // 3.1 40 | // 4 41 | // 5 42 | // 6 -------------------------------------------------------------------------------- /6.7 事件循环/3.js: -------------------------------------------------------------------------------- 1 | const p1 = new Promise((resolve) => { 2 | resolve() 3 | }).then(function f1() { 4 | console.log(1) 5 | const p2 = new Promise(resolve => { 6 | resolve() 7 | }).then(function f3() { 8 | console.log(2) 9 | }).then(function f4() { 10 | console.log(4) 11 | }) 12 | }).then(function f2() { 13 | console.log(3) 14 | }) 15 | 16 | console.log(0) -------------------------------------------------------------------------------- /6.7 事件循环/4.js: -------------------------------------------------------------------------------- 1 | const p1 = new Promise((resolve) => { 2 | resolve() 3 | }).then(function f1() { 4 | console.log(1) 5 | const p2 = new Promise(resolve => { 6 | resolve() 7 | }).then(function f3() { 8 | console.log(2) 9 | }).then(function f4() { 10 | console.log(4) 11 | }) 12 | }).then(function f2() { 13 | console.log(3) 14 | let index = 0 15 | const queue = [m1] 16 | 17 | function m1() { 18 | console.log('m1') 19 | if (index < 10) { 20 | queue.push(m2) 21 | } 22 | } 23 | 24 | function m2() { 25 | console.log('m2') 26 | index++; 27 | queue.push(m1) 28 | } 29 | 30 | let cb 31 | while(cb = queue.shift()) { 32 | cb() 33 | } 34 | }) 35 | 36 | console.log(0) -------------------------------------------------------------------------------- /6.7 事件循环/5.js: -------------------------------------------------------------------------------- 1 | const btn = document.querySelector('#button') 2 | btn.addEventListener('click', function() { 3 | new Promise(res => res()).then(() => { 4 | console.log(3) 5 | }) 6 | console.log(1) 7 | }, false) 8 | 9 | btn.addEventListener('click', function () { 10 | new Promise(res => res()).then(() => { 11 | console.log(4) 12 | }) 13 | console.log(2) 14 | }, false) 15 | 16 | // btn.click() 17 | 18 | requestIdleCallback((deadline) => { 19 | console.log(deadline) 20 | }) 21 | 22 | requestAnimationFrame(() => { 23 | console.log('requestAnimationFrame') 24 | }) 25 | 26 | console.log('empty callstack') 27 | 28 | 29 | // UI render 30 | // requestAnimationFrame 31 | // I/O 32 | // setTimeout -------------------------------------------------------------------------------- /6.7 事件循环/6.js: -------------------------------------------------------------------------------- 1 | document.onclick = () => { 2 | console.log('s') 3 | setTimeout(() => { 4 | console.log(0) 5 | }, 0) 6 | 7 | setTimeout(() => { 8 | console.log(1) 9 | }, 1000) 10 | 11 | setTimeout(() => { 12 | console.log(2) 13 | }, 2000) 14 | 15 | for (var i = 0; i < 5000000000; i++); 16 | console.log('e') 17 | } 18 | -------------------------------------------------------------------------------- /6.7 事件循环/7.js: -------------------------------------------------------------------------------- 1 | // demo01 出自于上面我引用文章的一个例子,我们来根据上面的结论,一步一步分析具体的执行过程。 2 | // 为了方便理解,我以打印出来的字符作为当前的任务名称 3 | setTimeout(function s1() { 4 | console.log(5); 5 | }, 1) 6 | 7 | setTimeout(function s2() { 8 | console.log(6); 9 | }, 0) 10 | 11 | new Promise(function (resolve) { 12 | console.log(1); 13 | for (var i = 0; i < 1000; i++) { 14 | i == 99 && resolve(); 15 | } 16 | console.log(2); 17 | }).then(function p1() { 18 | console.log(4); 19 | }) 20 | 21 | console.log(3); 22 | -------------------------------------------------------------------------------- /6.7 事件循环/8.js: -------------------------------------------------------------------------------- 1 | // 用数组模拟一个队列 2 | var tasks = []; 3 | 4 | // 模拟一个事件分发器 5 | var addFn1 = function (task) { 6 | tasks.push(task); 7 | } 8 | 9 | // 执行所有的任务 10 | var flush = function () { 11 | tasks.map(function (task) { 12 | task(); 13 | }) 14 | } 15 | 16 | // 最后利用setTimeout/或者其他你认为合适的方式丢入事件循环中 17 | setTimeout(function () { 18 | flush(); 19 | }) 20 | 21 | // 当然,也可以不用丢进事件循环,而是我们自己手动在适当的时机去执行对应的某一个方法 22 | var dispatch = function (name) { 23 | tasks.map(function (item) { 24 | if (item.name == name) { 25 | item.handler(); 26 | } 27 | }) 28 | } 29 | 30 | // 当然,我们把任务丢进去的时候,多保存一个name即可。 31 | // 这时候,task的格式就如下 32 | demoTask = { 33 | name: 'demo', 34 | handler: function () { } 35 | } 36 | 37 | // 于是,一个订阅-通知的设计模式就这样轻松的被实现了 -------------------------------------------------------------------------------- /6.8 模块化/1.js: -------------------------------------------------------------------------------- 1 | // 自执行函数模拟模块化 2 | 3 | // Person 模块 4 | (() => { 5 | // 实例个数,模块内部变量,外部无法直接访问, 6 | let number = 0 7 | function Person(name, age) { 8 | number ++ 9 | this.name = name 10 | this.age = age 11 | } 12 | 13 | Person.prototype.getName = function() { 14 | return this.name 15 | } 16 | 17 | Person.getInstanceNumber = function() { 18 | return number 19 | } 20 | 21 | // 对外抛出接口 22 | window.Person = Person 23 | })(); 24 | 25 | 26 | // main 模块 27 | (() => { 28 | // 引入模块 29 | const Person = window.Person 30 | 31 | const p1 = new Person('Tom', 20) 32 | const p2 = new Person('Jake', 20) 33 | const p3 = new Person('Alex', 20) 34 | 35 | p1.getName() 36 | 37 | console.log('实例化个数', Person.getInstanceNumber()) 38 | })() -------------------------------------------------------------------------------- /6.8 模块化/2.js: -------------------------------------------------------------------------------- 1 | // CommonJS 2 | 3 | // person 模块 4 | // person.js 5 | let number = 0 6 | function Person(name, age) { 7 | number++ 8 | this.name = name 9 | this.age = age 10 | } 11 | 12 | // 对外暴露接口 13 | Person.prototype.getName = function () { 14 | return this.name 15 | } 16 | 17 | // 对外暴露接口 18 | module.exports.getInstanceNumber = function () { 19 | return number 20 | } 21 | module.exports.Person = Person 22 | 23 | // ---------------- 24 | // main.js 25 | // 引入模块 26 | const person = require('./person.js') 27 | 28 | const {Person, getInstanceNumber} = person 29 | 30 | const p1 = new Person('Tom', 20) 31 | const p2 = new Person('Jake', 20) 32 | const p3 = new Person('Alex', 20) 33 | 34 | p1.getName() 35 | p2.getName() 36 | p3.getName() 37 | 38 | console.log('实例化个数', getInstanceNumber()) 39 | -------------------------------------------------------------------------------- /6.8 模块化/3.js: -------------------------------------------------------------------------------- 1 | // AMD 2 | 3 | // person.js 4 | define(function() { 5 | let number = 0 6 | function Person(name, age) { 7 | number++ 8 | this.name = name 9 | this.age = age 10 | } 11 | 12 | // 对外暴露接口 13 | Person.prototype.getName = function () { 14 | return this.name 15 | } 16 | 17 | function getInstanceNumber() { 18 | return number 19 | } 20 | 21 | // 对外暴露接口 22 | return { 23 | getInstanceNumber, 24 | Person 25 | } 26 | }) 27 | 28 | 29 | // mian.js 30 | 31 | // main.js 32 | // 引入模块 33 | define(['./person.js'], function(person) { 34 | const { Person, getInstanceNumber } = person 35 | 36 | const p1 = new Person('Tom', 20) 37 | const p2 = new Person('Jake', 20) 38 | const p3 = new Person('Alex', 20) 39 | 40 | p1.getName() 41 | p2.getName() 42 | p3.getName() 43 | 44 | console.log('实例化个数', getInstanceNumber()) 45 | }) 46 | -------------------------------------------------------------------------------- /6.8 模块化/4.js: -------------------------------------------------------------------------------- 1 | // person.js 2 | define(function(require, exports, module) { 3 | let number = 0 4 | function Person(name, age) { 5 | number++ 6 | this.name = name 7 | this.age = age 8 | } 9 | 10 | // 对外暴露接口 11 | Person.prototype.getName = function () { 12 | return this.name 13 | } 14 | 15 | // 对外暴露接口 16 | module.exports.getInstanceNumber = function () { 17 | return number 18 | } 19 | module.exports.Person = Person 20 | }) 21 | 22 | 23 | // mian.js 24 | define(function(require) { 25 | const person = require('./person.js') 26 | const { Person, getInstanceNumber } = person 27 | 28 | const p1 = new Person('Tom', 20) 29 | const p2 = new Person('Jake', 20) 30 | const p3 = new Person('Alex', 20) 31 | 32 | p1.getName() 33 | p2.getName() 34 | p3.getName() 35 | 36 | console.log('实例化个数', getInstanceNumber()) 37 | 38 | }) -------------------------------------------------------------------------------- /6.8 模块化/5.js: -------------------------------------------------------------------------------- 1 | (function(root, factory) { 2 | if (typeof define === 'function' && define.amd) { // AMD 3 | define(['person'], factory) 4 | } else if (typeof define === 'function' && define.cmd) { // CMD 5 | define(function(require, exports, module) { 6 | module.exports = factory() 7 | }) 8 | } else if (typeof exports === 'object') { // CommonJS 9 | module.exports = factory() 10 | } else { // global 11 | root.person = factory() 12 | } 13 | })(this, function() { 14 | let number = 0 15 | function Person(name, age) { 16 | number++ 17 | this.name = name 18 | this.age = age 19 | } 20 | 21 | // 对外暴露接口 22 | Person.prototype.getName = function () { 23 | return this.name 24 | } 25 | 26 | function getInstanceNumber () { 27 | return number 28 | } 29 | 30 | return { 31 | Person, 32 | getInstanceNumber 33 | } 34 | }) 35 | -------------------------------------------------------------------------------- /6.8 模块化/6.js: -------------------------------------------------------------------------------- 1 | // CommonJS 2 | 3 | // person 模块 4 | // person.js 5 | let number = 0 6 | export function Person(name, age) { // 暴露接口 7 | number++ 8 | this.name = name 9 | this.age = age 10 | } 11 | 12 | // 对外暴露接口 13 | Person.prototype.getName = function () { 14 | return this.name 15 | } 16 | 17 | // 对外暴露接口 18 | export const getInstanceNumber = function () { 19 | return number 20 | } 21 | 22 | // ---------------- 23 | // main.js 24 | // 引入模块 25 | import {Person, getInstanceNumber} from './person.js' 26 | 27 | const p1 = new Person('Tom', 20) 28 | const p2 = new Person('Jake', 20) 29 | const p3 = new Person('Alex', 20) 30 | 31 | p1.getName() 32 | p2.getName() 33 | p3.getName() 34 | 35 | console.log('实例化个数', getInstanceNumber()) 36 | -------------------------------------------------------------------------------- /6.8 模块化/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /6.8.1 模块化语法/my-app/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /6.8.1 模块化语法/my-app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangbo5207/jsCore/4d6aae959f9ff22d3ba84a0845b662fc8c85572f/6.8.1 模块化语法/my-app/public/favicon.ico -------------------------------------------------------------------------------- /6.8.1 模块化语法/my-app/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangbo5207/jsCore/4d6aae959f9ff22d3ba84a0845b662fc8c85572f/6.8.1 模块化语法/my-app/public/logo192.png -------------------------------------------------------------------------------- /6.8.1 模块化语法/my-app/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangbo5207/jsCore/4d6aae959f9ff22d3ba84a0845b662fc8c85572f/6.8.1 模块化语法/my-app/public/logo512.png -------------------------------------------------------------------------------- /6.8.1 模块化语法/my-app/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /6.8.1 模块化语法/my-app/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /6.8.1 模块化语法/my-app/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /6.8.1 模块化语法/my-app/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render, screen } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | render(); 7 | const linkElement = screen.getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /6.8.1 模块化语法/my-app/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import logo from './logo.svg'; 3 | import './App.css'; 4 | 5 | function App() { 6 | return ( 7 |
8 |
9 | logo 10 |

11 | Edit src/App.tsx and save to reload. 12 |

13 | 19 | Learn React 20 | 21 |
22 |
23 | ); 24 | } 25 | 26 | export default App; 27 | -------------------------------------------------------------------------------- /6.8.1 模块化语法/my-app/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /6.8.1 模块化语法/my-app/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | import Person from './person' 8 | import Person2, {fn, bar} from './person2' 9 | 10 | ReactDOM.render( 11 | 12 | 13 | , 14 | document.getElementById('root') 15 | ); 16 | 17 | // If you want to start measuring performance in your app, pass a function 18 | // to log results (for example: reportWebVitals(console.log)) 19 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 20 | reportWebVitals(); 21 | 22 | 23 | const p1 = new Person('TOM', 20) 24 | console.log(p1.getName()) 25 | 26 | -------------------------------------------------------------------------------- /6.8.1 模块化语法/my-app/src/person.ts: -------------------------------------------------------------------------------- 1 | class Person { 2 | private name: string 3 | private age: number 4 | 5 | constructor(name: string, age: number) { 6 | this.name = name 7 | this.age = age 8 | } 9 | getName() { 10 | return this.name 11 | } 12 | } 13 | 14 | export default Person -------------------------------------------------------------------------------- /6.8.1 模块化语法/my-app/src/person2.ts: -------------------------------------------------------------------------------- 1 | export function fn() { 2 | console.log('this is a function named fn.'); 3 | } 4 | 5 | export function bar() { 6 | console.log('hello everybody.'); 7 | } 8 | 9 | class Person { 10 | private name: string 11 | private age: number 12 | 13 | constructor(name: string, age: number) { 14 | this.name = name; 15 | this.age = age; 16 | } 17 | getName() { 18 | return this.name 19 | } 20 | } 21 | 22 | export default Person; -------------------------------------------------------------------------------- /6.8.1 模块化语法/my-app/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /6.8.1 模块化语法/my-app/src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from 'web-vitals'; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /6.8.1 模块化语法/my-app/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /6.8.1 模块化语法/my-app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /6.9模块化开发实例/controldiv/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /6.9模块化开发实例/controldiv/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangbo5207/jsCore/4d6aae959f9ff22d3ba84a0845b662fc8c85572f/6.9模块化开发实例/controldiv/public/favicon.ico -------------------------------------------------------------------------------- /6.9模块化开发实例/controldiv/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangbo5207/jsCore/4d6aae959f9ff22d3ba84a0845b662fc8c85572f/6.9模块化开发实例/controldiv/public/logo192.png -------------------------------------------------------------------------------- /6.9模块化开发实例/controldiv/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangbo5207/jsCore/4d6aae959f9ff22d3ba84a0845b662fc8c85572f/6.9模块化开发实例/controldiv/public/logo512.png -------------------------------------------------------------------------------- /6.9模块化开发实例/controldiv/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /6.9模块化开发实例/controldiv/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /6.9模块化开发实例/controldiv/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render, screen } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | render(); 7 | const linkElement = screen.getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /6.9模块化开发实例/controldiv/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | function App() { 3 | return ( 4 |
5 | ); 6 | } 7 | 8 | export default App; 9 | -------------------------------------------------------------------------------- /6.9模块化开发实例/controldiv/src/controlButtons/bgColor.ts: -------------------------------------------------------------------------------- 1 | import { setState } from '../state'; 2 | 3 | const input = document.querySelector('.bgcolor_input'); 4 | const btn = document.querySelector('.bgcolor_btn'); 5 | 6 | if (!input || !btn) { 7 | throw new Error('元素对象不存在') 8 | } 9 | 10 | btn.addEventListener('click', () => { 11 | if (input.value) { 12 | setState('backgroundColor', input.value); 13 | } 14 | }, false); -------------------------------------------------------------------------------- /6.9模块化开发实例/controldiv/src/controlButtons/borderColor.ts: -------------------------------------------------------------------------------- 1 | import { setState } from '../state'; 2 | 3 | const input = document.querySelector('.bdcolor_input'); 4 | const btn = document.querySelector('.bdcolor_btn'); 5 | 6 | if (!input || !btn) { 7 | throw new Error('元素对象不存在') 8 | } 9 | 10 | 11 | btn.addEventListener('click', () => { 12 | if (input.value) { 13 | setState('borderColor', input.value); 14 | } 15 | }, false); -------------------------------------------------------------------------------- /6.9模块化开发实例/controldiv/src/controlButtons/height.ts: -------------------------------------------------------------------------------- 1 | import { getState, setState } from '../state'; 2 | 3 | const red_btn = document.querySelector('.height_reduce'); 4 | const add_btn = document.querySelector('.height_add'); 5 | const height_input = document.querySelector('.height_input'); 6 | 7 | if (!red_btn || !add_btn || !height_input) { 8 | throw new Error('元素对象不存在') 9 | } 10 | 11 | height_input.value = getState('height') || 200; 12 | 13 | red_btn.addEventListener('click', () => { 14 | const cur = getState('height'); 15 | if (cur > 50) { 16 | setState('height', cur - 5); 17 | height_input.value = cur - 5 + ''; 18 | } 19 | }, false) 20 | 21 | add_btn.addEventListener('click', () => { 22 | const cur = getState('height'); 23 | if (cur < 400) { 24 | setState('height', cur + 5); 25 | height_input.value = cur + 5; 26 | } 27 | }, false) -------------------------------------------------------------------------------- /6.9模块化开发实例/controldiv/src/controlButtons/index.ts: -------------------------------------------------------------------------------- 1 | import './show'; 2 | import './bgColor'; 3 | import './borderColor'; 4 | import './width'; 5 | import './height'; -------------------------------------------------------------------------------- /6.9模块化开发实例/controldiv/src/controlButtons/show.ts: -------------------------------------------------------------------------------- 1 | import { getState, setState } from '../state'; 2 | 3 | const btn = document.querySelector('.show'); 4 | 5 | if (!btn) { 6 | throw new Error('元素对象不存在') 7 | } 8 | 9 | btn.addEventListener('click', () => { 10 | setState('show', !getState('show')) 11 | }, false); -------------------------------------------------------------------------------- /6.9模块化开发实例/controldiv/src/controlButtons/width.ts: -------------------------------------------------------------------------------- 1 | import { getState, setState } from '../state'; 2 | 3 | const red_btn = document.querySelector('.width_reduce'); 4 | const add_btn = document.querySelector('.width_add'); 5 | 6 | if (!red_btn || !add_btn) { 7 | throw new Error('元素对象不存在') 8 | } 9 | 10 | red_btn.addEventListener('click', () => { 11 | const cur = getState('width'); 12 | if (cur > 50) { 13 | setState('width', cur - 5); 14 | } 15 | }, false) 16 | 17 | add_btn.addEventListener('click', () => { 18 | const cur = getState('width'); 19 | if (cur < 400) { 20 | setState('width', cur + 5); 21 | } 22 | }, false) -------------------------------------------------------------------------------- /6.9模块化开发实例/controldiv/src/index.css: -------------------------------------------------------------------------------- 1 | #control .target { 2 | width: 200px; 3 | height: 200px; 4 | background-color: #cccccc; 5 | transition: 0.3s; 6 | } 7 | #control .target.hide { 8 | display: none; 9 | } -------------------------------------------------------------------------------- /6.9模块化开发实例/controldiv/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | import './index.css'; 5 | import './box' 6 | import './controlButtons' 7 | 8 | ReactDOM.render( 9 | 10 | 11 | , 12 | document.getElementById('root') 13 | ); 14 | -------------------------------------------------------------------------------- /6.9模块化开发实例/controldiv/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /6.9模块化开发实例/controldiv/src/register.ts: -------------------------------------------------------------------------------- 1 | import {registerState} from './state' 2 | 3 | registerState('show', true) 4 | registerState('backgroundColor', '#cccccc') 5 | registerState('borderColor', '#000') 6 | registerState('width', 200) 7 | registerState('height', 200) -------------------------------------------------------------------------------- /6.9模块化开发实例/controldiv/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /6.9模块化开发实例/controldiv/src/utils.ts: -------------------------------------------------------------------------------- 1 | export const getStyle = (ele: Element, key: any) => { 2 | if (window.getComputedStyle) { 3 | return window.getComputedStyle(ele, null)[key] 4 | } 5 | // @ts-ignore for IE 6 | return ele.currentStyle[key] 7 | } -------------------------------------------------------------------------------- /6.9模块化开发实例/controldiv/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /6.9模块化开发实例/zhihunew/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /6.9模块化开发实例/zhihunew/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangbo5207/jsCore/4d6aae959f9ff22d3ba84a0845b662fc8c85572f/6.9模块化开发实例/zhihunew/public/favicon.ico -------------------------------------------------------------------------------- /6.9模块化开发实例/zhihunew/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangbo5207/jsCore/4d6aae959f9ff22d3ba84a0845b662fc8c85572f/6.9模块化开发实例/zhihunew/public/logo192.png -------------------------------------------------------------------------------- /6.9模块化开发实例/zhihunew/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangbo5207/jsCore/4d6aae959f9ff22d3ba84a0845b662fc8c85572f/6.9模块化开发实例/zhihunew/public/logo512.png -------------------------------------------------------------------------------- /6.9模块化开发实例/zhihunew/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /6.9模块化开发实例/zhihunew/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /6.9模块化开发实例/zhihunew/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /6.9模块化开发实例/zhihunew/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render, screen } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | render(); 7 | const linkElement = screen.getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /6.9模块化开发实例/zhihunew/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './App.css'; 3 | 4 | function App() { 5 | return ( 6 |
7 | ); 8 | } 9 | 10 | export default App; 11 | -------------------------------------------------------------------------------- /6.9模块化开发实例/zhihunew/src/api.ts: -------------------------------------------------------------------------------- 1 | import {get} from './request' 2 | import news, {Newspaper} from './data' 3 | 4 | 5 | 6 | export function newsApi() { 7 | // 本来应该如此请求接口,但是由于跨域限制,因此我们这里模拟该接口的行为返回数据 mock 8 | // return get('https://news-at.zhihu.com/api/4/news/latest') 9 | return new Promise((resolve) => { 10 | setTimeout(() => { 11 | resolve(news) 12 | }, 1000) 13 | }) 14 | } 15 | 16 | export function other1Api(url: string) {} 17 | 18 | export function other2Api(url: string) {} 19 | 20 | export function other3Api(url: string) {} 21 | 22 | // 实践中可能还会有更多 api 请求 -------------------------------------------------------------------------------- /6.9模块化开发实例/zhihunew/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /6.9模块化开发实例/zhihunew/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | import './render' 7 | 8 | ReactDOM.render( 9 | 10 | 11 | , 12 | document.getElementById('root') 13 | ); 14 | 15 | // If you want to start measuring performance in your app, pass a function 16 | // to log results (for example: reportWebVitals(console.log)) 17 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 18 | reportWebVitals(); 19 | -------------------------------------------------------------------------------- /6.9模块化开发实例/zhihunew/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /6.9模块化开发实例/zhihunew/src/render.ts: -------------------------------------------------------------------------------- 1 | import {newsApi} from './api' 2 | 3 | const news = document.querySelector('#news') 4 | 5 | if (!news) { 6 | throw new Error('容器元素不存在') 7 | } 8 | 9 | // 初始值 10 | news.innerHTML = '数据加载中...' 11 | 12 | newsApi().then(res => { 13 | const top = ` 14 |
15 | ${res.top_stories.map(item => ( 16 | ` 17 | 18 |
${item.title}
19 |
` 20 | )).join('')} 21 |
22 | ` 23 | 24 | const list = ` 25 |
26 | ${res.stories.map(item => ( 27 | ` 28 | 29 |
${item.title}
30 |
` 31 | )).join('')} 32 |
33 | ` 34 | news.innerHTML = `${top}${list}` 35 | }) 36 | -------------------------------------------------------------------------------- /6.9模块化开发实例/zhihunew/src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from 'web-vitals'; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /6.9模块化开发实例/zhihunew/src/request.ts: -------------------------------------------------------------------------------- 1 | // 简易版,未考虑参数情况,请勿运用于实践 2 | export function get(url: string): Promise { 3 | return new Promise((resolve, reject) => { 4 | const XHR = new XMLHttpRequest() 5 | XHR.open('GET', url, true) 6 | XHR.send() 7 | 8 | XHR.onreadystatechange = () => { 9 | if (XHR.readyState == 4) { 10 | if (XHR.status == 200) { 11 | try { 12 | resolve(JSON.parse(XHR.responseText)) 13 | } catch(e) { 14 | reject(e) 15 | } 16 | } else { 17 | reject(new Error(XHR.statusText)) 18 | } 19 | } 20 | } 21 | }) 22 | } -------------------------------------------------------------------------------- /6.9模块化开发实例/zhihunew/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /6.9模块化开发实例/zhihunew/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /7.1组件化/tab/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /7.1组件化/tab/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangbo5207/jsCore/4d6aae959f9ff22d3ba84a0845b662fc8c85572f/7.1组件化/tab/public/favicon.ico -------------------------------------------------------------------------------- /7.1组件化/tab/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangbo5207/jsCore/4d6aae959f9ff22d3ba84a0845b662fc8c85572f/7.1组件化/tab/public/logo192.png -------------------------------------------------------------------------------- /7.1组件化/tab/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangbo5207/jsCore/4d6aae959f9ff22d3ba84a0845b662fc8c85572f/7.1组件化/tab/public/logo512.png -------------------------------------------------------------------------------- /7.1组件化/tab/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /7.1组件化/tab/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /7.1组件化/tab/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /7.1组件化/tab/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render, screen } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | render(); 7 | const linkElement = screen.getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /7.1组件化/tab/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './App.css'; 3 | 4 | import Tabbar from './Tabbar' 5 | 6 | function App() { 7 | return ( 8 |
9 |
组件化 Tab
10 | 11 |
12 | ); 13 | } 14 | 15 | export default App; 16 | -------------------------------------------------------------------------------- /7.1组件化/tab/src/Tabbar/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | } 4 | 5 | html, body { 6 | height: 100%; 7 | } 8 | 9 | .tab_container { 10 | width: 300px; 11 | margin: 20px auto; 12 | border: 1px solid #CCC; 13 | height: 400px; 14 | } 15 | 16 | .titles { 17 | display: flex; 18 | height: 44px; 19 | border-bottom: 1px solid #CCC; 20 | } 21 | 22 | .titles .item { 23 | flex: 1; 24 | height: 100%; 25 | text-align: center; 26 | line-height: 44px; 27 | font-size: 12px; 28 | } 29 | 30 | .titles .item.active { 31 | background-color: orange; 32 | color: #FFF; 33 | } 34 | 35 | .contents { 36 | position: relative; 37 | height: 100%; 38 | } 39 | 40 | .contents .item { 41 | position: absolute; 42 | top: 0; 43 | left: 0; 44 | bottom: 0; 45 | right: 0; 46 | display: none; 47 | align-items: center; 48 | justify-content: center; 49 | } 50 | 51 | .contents .item.active { 52 | display: flex; 53 | } -------------------------------------------------------------------------------- /7.1组件化/tab/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /7.1组件化/tab/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | import './tab' 8 | import './tab.css' 9 | 10 | ReactDOM.render( 11 | 12 | 13 | , 14 | document.getElementById('root') 15 | ); 16 | 17 | // If you want to start measuring performance in your app, pass a function 18 | // to log results (for example: reportWebVitals(console.log)) 19 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 20 | reportWebVitals(); 21 | -------------------------------------------------------------------------------- /7.1组件化/tab/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /7.1组件化/tab/src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from 'web-vitals'; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /7.1组件化/tab/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /7.1组件化/tab/src/tab.css: -------------------------------------------------------------------------------- 1 | 2 | body { 3 | margin: 0; 4 | } 5 | 6 | html, body { 7 | height: 100%; 8 | } 9 | 10 | #tab-root { 11 | width: 300px; 12 | margin: 20px auto; 13 | border: 1px solid #CCC; 14 | height: 400px; 15 | } 16 | 17 | .titles { 18 | display: flex; 19 | height: 44px; 20 | border-bottom: 1px solid #CCC; 21 | } 22 | 23 | .titles .item { 24 | flex: 1; 25 | height: 100%; 26 | text-align: center; 27 | line-height: 44px; 28 | font-size: 12px; 29 | } 30 | 31 | .titles .item.active { 32 | background-color: orange; 33 | color: #FFF; 34 | } 35 | 36 | .contents { 37 | position: relative; 38 | height: 100%; 39 | } 40 | 41 | .contents .item { 42 | position: absolute; 43 | top: 0; 44 | left: 0; 45 | bottom: 0; 46 | right: 0; 47 | display: none; 48 | align-items: center; 49 | justify-content: center; 50 | } 51 | 52 | .contents .item.active { 53 | display: flex; 54 | } -------------------------------------------------------------------------------- /7.1组件化/tab/src/tab.ts: -------------------------------------------------------------------------------- 1 | const titles = document.querySelector('.titles'); 2 | const contents = document.querySelector('.contents'); 3 | 4 | if (!titles || !contents) { 5 | throw new Error('element not exist.') 6 | } 7 | 8 | let index = 0; 9 | 10 | titles.onclick = (event) => { 11 | const activeTitle = event.target as HTMLElement; 12 | 13 | if (!activeTitle) { 14 | return; 15 | } 16 | 17 | const aindex = Number(activeTitle.dataset.index); 18 | 19 | if (aindex !== index) { 20 | titles.children[index].classList.remove('active'); 21 | contents.children[index].classList.remove('active'); 22 | 23 | activeTitle.classList.add('active'); 24 | contents.children[aindex].classList.add('active'); 25 | index = aindex; 26 | } 27 | } 28 | 29 | export default {} -------------------------------------------------------------------------------- /7.1组件化/tab/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /7.2webpack/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /7.2webpack/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | webpack 起步 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /7.2webpack/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "7.2webpack", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "webpack serve --open", 9 | "build": "webpack --config webpack.config.js" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "devDependencies": { 15 | "clean-webpack-plugin": "^3.0.0", 16 | "css-loader": "^5.0.1", 17 | "html-webpack-plugin": "^4.5.1", 18 | "node-sass": "^5.0.0", 19 | "sass-loader": "^10.1.1", 20 | "style-loader": "^2.0.0", 21 | "webpack": "^5.15.0", 22 | "webpack-cli": "^4.3.1", 23 | "webpack-dev-server": "^3.11.2" 24 | }, 25 | "dependencies": { 26 | "lodash": "^4.17.20" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /7.2webpack/src/inbox.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangbo5207/jsCore/4d6aae959f9ff22d3ba84a0845b662fc8c85572f/7.2webpack/src/inbox.jpg -------------------------------------------------------------------------------- /7.2webpack/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: orange; 3 | color: #FFF; 4 | } -------------------------------------------------------------------------------- /7.2webpack/src/index.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash' 2 | import './index.css' 3 | import './test.scss' 4 | import Inbox from './inbox.jpg' 5 | 6 | function component() { 7 | const element = document.createElement('div'); 8 | element.innerHTML = _.join(['Hello', 'webpack'], ' '); 9 | 10 | const img = new Image() 11 | img.src = Inbox 12 | element.appendChild(img) 13 | 14 | return element; 15 | } 16 | 17 | document.body.appendChild(component()); -------------------------------------------------------------------------------- /7.2webpack/src/test.scss: -------------------------------------------------------------------------------- 1 | body { 2 | font-size: 50px; 3 | } -------------------------------------------------------------------------------- /7.3React/controldiv/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /7.3React/controldiv/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangbo5207/jsCore/4d6aae959f9ff22d3ba84a0845b662fc8c85572f/7.3React/controldiv/public/favicon.ico -------------------------------------------------------------------------------- /7.3React/controldiv/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangbo5207/jsCore/4d6aae959f9ff22d3ba84a0845b662fc8c85572f/7.3React/controldiv/public/logo192.png -------------------------------------------------------------------------------- /7.3React/controldiv/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangbo5207/jsCore/4d6aae959f9ff22d3ba84a0845b662fc8c85572f/7.3React/controldiv/public/logo512.png -------------------------------------------------------------------------------- /7.3React/controldiv/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /7.3React/controldiv/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /7.3React/controldiv/src/App.css: -------------------------------------------------------------------------------- 1 | #control { 2 | width: 500px; 3 | margin: 100px auto; 4 | } 5 | 6 | #control .target { 7 | width: 200px; 8 | height: 200px; 9 | border: 2px solid #FFF; 10 | background-color: #cccccc; 11 | transition: 0.3s; 12 | } 13 | #control .target.hide { 14 | display: none; 15 | } -------------------------------------------------------------------------------- /7.3React/controldiv/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render, screen } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | render(); 7 | const linkElement = screen.getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /7.3React/controldiv/src/components/Toast/Item.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useRef } from 'react'; 2 | import "./item.css"; 3 | 4 | export interface ToastProps { 5 | id: string, 6 | duration: number, 7 | onClose?: (id: string, isShowMask: boolean) => any, 8 | isShowMask: boolean, 9 | text: string, 10 | type: 'info' | 'warning' | 'danger' 11 | } 12 | 13 | export default function ToastItem(props: ToastProps) { 14 | const {id, duration, onClose, isShowMask, text} = props 15 | const tiemr = useRef() 16 | tiemr.current = setTimeout(() => { 17 | onClose && onClose(id, isShowMask) 18 | }, duration) 19 | 20 | useEffect(() => { 21 | return () => { 22 | // @ts-ignore 23 | clearTimeout(tiemr.current) 24 | } 25 | }, []) 26 | 27 | return ( 28 |
{text}
29 | ) 30 | } -------------------------------------------------------------------------------- /7.3React/controldiv/src/components/Toast/container.css: -------------------------------------------------------------------------------- 1 | 2 | .toast-container { 3 | margin: 0; 4 | padding: 0; 5 | } 6 | 7 | .mask { 8 | position: fixed; 9 | left: 0; 10 | right: 0; 11 | top: 0; 12 | bottom: 0; 13 | background: rgba(0, 0, 0, 0.1); 14 | z-index: 100; 15 | } 16 | 17 | .toast-wrap { 18 | position: fixed; 19 | left: 50%; 20 | top: 30%; 21 | transform: translateX(-50%); 22 | z-index: 200; 23 | } -------------------------------------------------------------------------------- /7.3React/controldiv/src/components/Toast/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import Container from './Container'; 4 | 5 | const toastContainerDiv = document.createElement('div'); 6 | document.body.appendChild(toastContainerDiv); 7 | 8 | // 这里返回的是 ToastContainer 组件引用 9 | const getToastContainerRef = () => { 10 | return ReactDOM.render(, toastContainerDiv); 11 | } 12 | 13 | // 获取 container 实例 14 | let containerRef = getToastContainerRef(); 15 | 16 | const destroy = () => { 17 | ReactDOM.unmountComponentAtNode(toastContainerDiv); 18 | containerRef = getToastContainerRef(); 19 | } 20 | 21 | export default { 22 | // @ts-ignore 23 | info: (text, duration, isShowMask) => (containerRef.push({ type: 'info', text, duration, isShowMask })), 24 | hide: destroy 25 | }; -------------------------------------------------------------------------------- /7.3React/controldiv/src/components/Toast/item.css: -------------------------------------------------------------------------------- 1 | .toast-item { 2 | padding: 5px 8px; 3 | background: rgba(0, 0, 0, 0.7); 4 | color: #fff; 5 | border-radius: 3px; 6 | margin-top: 10px; 7 | } -------------------------------------------------------------------------------- /7.3React/controldiv/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } -------------------------------------------------------------------------------- /7.3React/controldiv/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | document.getElementById('root') 12 | ); 13 | 14 | // If you want to start measuring performance in your app, pass a function 15 | // to log results (for example: reportWebVitals(console.log)) 16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 17 | reportWebVitals(); 18 | -------------------------------------------------------------------------------- /7.3React/controldiv/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /7.3React/controldiv/src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from 'web-vitals'; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /7.3React/controldiv/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /7.3React/controldiv/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "preserve", 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /7.4admin/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | **/node_modules 5 | # roadhog-api-doc ignore 6 | /src/utils/request-temp.js 7 | _roadhog-api-doc 8 | 9 | # production 10 | /dist 11 | /.vscode 12 | 13 | # misc 14 | .DS_Store 15 | npm-debug.log* 16 | yarn-error.log 17 | 18 | /coverage 19 | .idea 20 | yarn.lock 21 | package-lock.json 22 | *bak 23 | .vscode 24 | 25 | # visual studio code 26 | .history 27 | *.log 28 | functions/* 29 | .temp/** 30 | 31 | # umi 32 | .umi 33 | .umi-production 34 | 35 | # screenshot 36 | screenshot 37 | .firebase 38 | .eslintcache 39 | 40 | build -------------------------------------------------------------------------------- /7.4admin/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM circleci/node:latest-browsers 2 | 3 | WORKDIR /usr/src/app/ 4 | USER root 5 | COPY package.json ./ 6 | RUN yarn 7 | 8 | COPY ./ ./ 9 | 10 | RUN npm run test:all 11 | 12 | RUN npm run fetch:blocks 13 | 14 | CMD ["npm", "run", "build"] 15 | -------------------------------------------------------------------------------- /7.4admin/Dockerfile.dev: -------------------------------------------------------------------------------- 1 | FROM node:latest 2 | 3 | WORKDIR /usr/src/app/ 4 | 5 | COPY package.json ./ 6 | RUN npm install --silent --no-cache --registry=https://registry.npm.taobao.org 7 | 8 | COPY ./ ./ 9 | 10 | RUN npm run fetch:blocks 11 | 12 | CMD ["npm", "run", "start"] 13 | -------------------------------------------------------------------------------- /7.4admin/Dockerfile.hub: -------------------------------------------------------------------------------- 1 | FROM circleci/node:latest-browsers as builder 2 | 3 | WORKDIR /usr/src/app/ 4 | USER root 5 | COPY package.json ./ 6 | RUN yarn 7 | 8 | COPY ./ ./ 9 | 10 | RUN npm run test:all 11 | 12 | RUN npm run fetch:blocks 13 | 14 | RUN npm run build 15 | 16 | 17 | FROM nginx 18 | 19 | WORKDIR /usr/share/nginx/html/ 20 | 21 | COPY ./docker/nginx.conf /etc/nginx/conf.d/default.conf 22 | 23 | COPY --from=builder /usr/src/app/dist /usr/share/nginx/html/ 24 | 25 | EXPOSE 80 26 | 27 | CMD ["nginx", "-g", "daemon off;"] -------------------------------------------------------------------------------- /7.4admin/config/config.dev.ts: -------------------------------------------------------------------------------- 1 | // https://umijs.org/config/ 2 | import { defineConfig } from 'umi'; 3 | 4 | export default defineConfig({ 5 | plugins: [ 6 | // https://github.com/zthxxx/react-dev-inspector 7 | 'react-dev-inspector/plugins/umi/react-inspector', 8 | ], 9 | // https://github.com/zthxxx/react-dev-inspector#inspector-loader-props 10 | inspectorConfig: { 11 | exclude: [], 12 | babelPlugins: [], 13 | babelOptions: {}, 14 | }, 15 | }); 16 | -------------------------------------------------------------------------------- /7.4admin/config/defaultSettings.ts: -------------------------------------------------------------------------------- 1 | import { Settings as ProSettings } from '@ant-design/pro-layout'; 2 | 3 | type DefaultSettings = Partial & { 4 | pwa: boolean; 5 | }; 6 | 7 | const proSettings: DefaultSettings = { 8 | navTheme: 'dark', 9 | // 拂晓蓝 10 | primaryColor: '#1890ff', 11 | layout: 'side', 12 | contentWidth: 'Fluid', 13 | fixedHeader: false, 14 | fixSiderbar: true, 15 | colorWeak: false, 16 | title: 'Ant Design Pro', 17 | pwa: false, 18 | iconfontUrl: '', 19 | }; 20 | 21 | export type { DefaultSettings }; 22 | 23 | export default proSettings; 24 | -------------------------------------------------------------------------------- /7.4admin/config/proxy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 在生产环境 代理是无法生效的,所以这里没有生产环境的配置 3 | * The agent cannot take effect in the production environment 4 | * so there is no configuration of the production environment 5 | * For details, please see 6 | * https://pro.ant.design/docs/deploy 7 | */ 8 | export default { 9 | dev: { 10 | '/api/': { 11 | target: 'https://preview.pro.ant.design', 12 | changeOrigin: true, 13 | pathRewrite: { '^': '' }, 14 | }, 15 | }, 16 | test: { 17 | '/api/': { 18 | target: 'https://preview.pro.ant.design', 19 | changeOrigin: true, 20 | pathRewrite: { '^': '' }, 21 | }, 22 | }, 23 | pre: { 24 | '/api/': { 25 | target: 'your pre url', 26 | changeOrigin: true, 27 | pathRewrite: { '^': '' }, 28 | }, 29 | }, 30 | }; 31 | -------------------------------------------------------------------------------- /7.4admin/docker/docker-compose.dev.yml: -------------------------------------------------------------------------------- 1 | version: '3.5' 2 | 3 | services: 4 | ant-design-pro_dev: 5 | ports: 6 | - 8000:8000 7 | build: 8 | context: ../ 9 | dockerfile: Dockerfile.dev 10 | container_name: 'ant-design-pro_dev' 11 | volumes: 12 | - ../src:/usr/src/app/src 13 | - ../config:/usr/src/app/config 14 | - ../mock:/usr/src/app/mock 15 | -------------------------------------------------------------------------------- /7.4admin/docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.5' 2 | 3 | services: 4 | ant-design-pro_build: 5 | build: ../ 6 | container_name: 'ant-design-pro_build' 7 | volumes: 8 | - dist:/usr/src/app/dist 9 | 10 | ant-design-pro_web: 11 | image: nginx 12 | ports: 13 | - 80:80 14 | container_name: 'ant-design-pro_web' 15 | restart: unless-stopped 16 | volumes: 17 | - dist:/usr/share/nginx/html:ro 18 | - ./nginx.conf:/etc/nginx/conf.d/default.conf 19 | 20 | volumes: 21 | dist: 22 | -------------------------------------------------------------------------------- /7.4admin/docker/nginx.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | # gzip config 4 | gzip on; 5 | gzip_min_length 1k; 6 | gzip_comp_level 9; 7 | gzip_types text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml; 8 | gzip_vary on; 9 | gzip_disable "MSIE [1-6]\."; 10 | 11 | root /usr/share/nginx/html; 12 | include /etc/nginx/mime.types; 13 | location / { 14 | try_files $uri $uri/ /index.html; 15 | } 16 | location /api { 17 | proxy_pass https://proapi.azurewebsites.net; 18 | proxy_set_header X-Forwarded-Proto $scheme; 19 | proxy_set_header X-Real-IP $remote_addr; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /7.4admin/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | testURL: 'http://localhost:8000', 3 | testEnvironment: './tests/PuppeteerEnvironment', 4 | verbose: false, 5 | globals: { 6 | ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION: false, 7 | localStorage: null, 8 | }, 9 | }; 10 | -------------------------------------------------------------------------------- /7.4admin/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "emitDecoratorMetadata": true, 4 | "experimentalDecorators": true, 5 | "baseUrl": ".", 6 | "paths": { 7 | "@/*": ["./src/*"] 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /7.4admin/mock/route.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | '/api/auth_routes': { 3 | '/form/advanced-form': { authority: ['admin', 'user'] }, 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /7.4admin/public/CNAME: -------------------------------------------------------------------------------- 1 | preview.pro.ant.design -------------------------------------------------------------------------------- /7.4admin/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangbo5207/jsCore/4d6aae959f9ff22d3ba84a0845b662fc8c85572f/7.4admin/public/favicon.ico -------------------------------------------------------------------------------- /7.4admin/public/home_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangbo5207/jsCore/4d6aae959f9ff22d3ba84a0845b662fc8c85572f/7.4admin/public/home_bg.png -------------------------------------------------------------------------------- /7.4admin/public/icons/icon-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangbo5207/jsCore/4d6aae959f9ff22d3ba84a0845b662fc8c85572f/7.4admin/public/icons/icon-128x128.png -------------------------------------------------------------------------------- /7.4admin/public/icons/icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangbo5207/jsCore/4d6aae959f9ff22d3ba84a0845b662fc8c85572f/7.4admin/public/icons/icon-192x192.png -------------------------------------------------------------------------------- /7.4admin/public/icons/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangbo5207/jsCore/4d6aae959f9ff22d3ba84a0845b662fc8c85572f/7.4admin/public/icons/icon-512x512.png -------------------------------------------------------------------------------- /7.4admin/public/pro_icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /7.4admin/src/components/Authorized/AuthorizedRoute.tsx: -------------------------------------------------------------------------------- 1 | import { Redirect, Route } from 'umi'; 2 | 3 | import React from 'react'; 4 | import Authorized from './Authorized'; 5 | import type { IAuthorityType } from './CheckPermissions'; 6 | 7 | type AuthorizedRouteProps = { 8 | currentAuthority: string; 9 | component: React.ComponentClass; 10 | render: (props: any) => React.ReactNode; 11 | redirectPath: string; 12 | authority: IAuthorityType; 13 | }; 14 | 15 | const AuthorizedRoute: React.SFC = ({ 16 | component: Component, 17 | render, 18 | authority, 19 | redirectPath, 20 | ...rest 21 | }) => ( 22 | } />} 25 | > 26 | (Component ? : render(props))} 29 | /> 30 | 31 | ); 32 | 33 | export default AuthorizedRoute; 34 | -------------------------------------------------------------------------------- /7.4admin/src/components/Authorized/index.tsx: -------------------------------------------------------------------------------- 1 | import Authorized from './Authorized'; 2 | import Secured from './Secured'; 3 | import check from './CheckPermissions'; 4 | import renderAuthorize from './renderAuthorize'; 5 | 6 | Authorized.Secured = Secured; 7 | Authorized.check = check; 8 | 9 | const RenderAuthorize = renderAuthorize(Authorized); 10 | 11 | export default RenderAuthorize; 12 | -------------------------------------------------------------------------------- /7.4admin/src/components/HeaderDropdown/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .container > * { 4 | background-color: @popover-bg; 5 | border-radius: 4px; 6 | box-shadow: @shadow-1-down; 7 | } 8 | 9 | @media screen and (max-width: @screen-xs) { 10 | .container { 11 | width: 100% !important; 12 | } 13 | .container > * { 14 | border-radius: 0 !important; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /7.4admin/src/components/HeaderDropdown/index.tsx: -------------------------------------------------------------------------------- 1 | import type { DropDownProps } from 'antd/es/dropdown'; 2 | import { Dropdown } from 'antd'; 3 | import React from 'react'; 4 | import classNames from 'classnames'; 5 | import styles from './index.less'; 6 | 7 | export type HeaderDropdownProps = { 8 | overlayClassName?: string; 9 | overlay: React.ReactNode | (() => React.ReactNode) | any; 10 | placement?: 'bottomLeft' | 'bottomRight' | 'topLeft' | 'topCenter' | 'topRight' | 'bottomCenter'; 11 | } & Omit; 12 | 13 | const HeaderDropdown: React.FC = ({ overlayClassName: cls, ...restProps }) => ( 14 | 15 | ); 16 | 17 | export default HeaderDropdown; 18 | -------------------------------------------------------------------------------- /7.4admin/src/components/HeaderSearch/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .headerSearch { 4 | .input { 5 | width: 0; 6 | min-width: 0; 7 | overflow: hidden; 8 | background: transparent; 9 | border-radius: 0; 10 | transition: width 0.3s, margin-left 0.3s; 11 | :global(.ant-select-selection) { 12 | background: transparent; 13 | } 14 | input { 15 | padding-right: 0; 16 | padding-left: 0; 17 | border: 0; 18 | box-shadow: none !important; 19 | } 20 | &, 21 | &:hover, 22 | &:focus { 23 | border-bottom: 1px solid @border-color-base; 24 | } 25 | &.show { 26 | width: 210px; 27 | margin-left: 8px; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /7.4admin/src/components/NoticeIcon/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .popover { 4 | position: relative; 5 | width: 336px; 6 | } 7 | 8 | .noticeButton { 9 | display: inline-block; 10 | cursor: pointer; 11 | transition: all 0.3s; 12 | } 13 | .icon { 14 | padding: 4px; 15 | vertical-align: middle; 16 | } 17 | 18 | .badge { 19 | font-size: 16px; 20 | } 21 | 22 | .tabs { 23 | :global { 24 | .ant-tabs-nav-list { 25 | margin: auto; 26 | } 27 | 28 | .ant-tabs-nav-scroll { 29 | text-align: center; 30 | } 31 | .ant-tabs-bar { 32 | margin-bottom: 0; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /7.4admin/src/components/PageLoading/index.tsx: -------------------------------------------------------------------------------- 1 | import { PageLoading } from '@ant-design/pro-layout'; 2 | 3 | // loading components from code split 4 | // https://umijs.org/plugin/umi-plugin-react.html#dynamicimport 5 | export default PageLoading; 6 | -------------------------------------------------------------------------------- /7.4admin/src/e2e/__mocks__/antd-pro-merge-less.js: -------------------------------------------------------------------------------- 1 | export default undefined; 2 | -------------------------------------------------------------------------------- /7.4admin/src/global.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | html, 4 | body, 5 | #root { 6 | height: 100%; 7 | } 8 | 9 | .colorWeak { 10 | filter: invert(80%); 11 | } 12 | 13 | .ant-layout { 14 | min-height: 100vh; 15 | } 16 | 17 | canvas { 18 | display: block; 19 | } 20 | 21 | body { 22 | text-rendering: optimizeLegibility; 23 | -webkit-font-smoothing: antialiased; 24 | -moz-osx-font-smoothing: grayscale; 25 | } 26 | 27 | ul, 28 | ol { 29 | list-style: none; 30 | } 31 | 32 | @media (max-width: @screen-xs) { 33 | .ant-table { 34 | width: 100%; 35 | overflow-x: auto; 36 | &-thead > tr, 37 | &-tbody > tr { 38 | > th, 39 | > td { 40 | white-space: pre; 41 | > span { 42 | display: block; 43 | } 44 | } 45 | } 46 | } 47 | } 48 | 49 | // 兼容IE11 50 | @media screen and(-ms-high-contrast: active), (-ms-high-contrast: none) { 51 | body .ant-design-pro > .ant-layout { 52 | min-height: 100vh; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /7.4admin/src/layouts/BlankLayout.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Inspector } from 'react-dev-inspector'; 3 | 4 | const InspectorWrapper = process.env.NODE_ENV === 'development' ? Inspector : React.Fragment; 5 | 6 | const Layout: React.FC = ({ children }) => { 7 | return {children}; 8 | }; 9 | 10 | export default Layout; 11 | -------------------------------------------------------------------------------- /7.4admin/src/locales/en-US.ts: -------------------------------------------------------------------------------- 1 | import component from './en-US/component'; 2 | import globalHeader from './en-US/globalHeader'; 3 | import menu from './en-US/menu'; 4 | import pwa from './en-US/pwa'; 5 | import settingDrawer from './en-US/settingDrawer'; 6 | import settings from './en-US/settings'; 7 | import pages from './en-US/pages'; 8 | 9 | export default { 10 | 'navBar.lang': 'Languages', 11 | 'layout.user.link.help': 'Help', 12 | 'layout.user.link.privacy': 'Privacy', 13 | 'layout.user.link.terms': 'Terms', 14 | 'app.preview.down.block': 'Download this page to your local project', 15 | 'app.welcome.link.fetch-blocks': 'Get all block', 16 | 'app.welcome.link.block-list': 'Quickly build standard, pages based on `block` development', 17 | ...globalHeader, 18 | ...menu, 19 | ...settingDrawer, 20 | ...settings, 21 | ...pwa, 22 | ...component, 23 | ...pages, 24 | }; 25 | -------------------------------------------------------------------------------- /7.4admin/src/locales/en-US/component.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'component.tagSelect.expand': 'Expand', 3 | 'component.tagSelect.collapse': 'Collapse', 4 | 'component.tagSelect.all': 'All', 5 | }; 6 | -------------------------------------------------------------------------------- /7.4admin/src/locales/en-US/globalHeader.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'component.globalHeader.search': 'Search', 3 | 'component.globalHeader.search.example1': 'Search example 1', 4 | 'component.globalHeader.search.example2': 'Search example 2', 5 | 'component.globalHeader.search.example3': 'Search example 3', 6 | 'component.globalHeader.help': 'Help', 7 | 'component.globalHeader.notification': 'Notification', 8 | 'component.globalHeader.notification.empty': 'You have viewed all notifications.', 9 | 'component.globalHeader.message': 'Message', 10 | 'component.globalHeader.message.empty': 'You have viewed all messsages.', 11 | 'component.globalHeader.event': 'Event', 12 | 'component.globalHeader.event.empty': 'You have viewed all events.', 13 | 'component.noticeIcon.clear': 'Clear', 14 | 'component.noticeIcon.cleared': 'Cleared', 15 | 'component.noticeIcon.empty': 'No notifications', 16 | 'component.noticeIcon.view-more': 'View more', 17 | }; 18 | -------------------------------------------------------------------------------- /7.4admin/src/locales/en-US/pwa.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'app.pwa.offline': 'You are offline now', 3 | 'app.pwa.serviceworker.updated': 'New content is available', 4 | 'app.pwa.serviceworker.updated.hint': 'Please press the "Refresh" button to reload current page', 5 | 'app.pwa.serviceworker.updated.ok': 'Refresh', 6 | }; 7 | -------------------------------------------------------------------------------- /7.4admin/src/locales/id-ID.ts: -------------------------------------------------------------------------------- 1 | import component from './id-ID/component'; 2 | import globalHeader from './id-ID/globalHeader'; 3 | import menu from './id-ID/menu'; 4 | import pwa from './id-ID/pwa'; 5 | import settingDrawer from './id-ID/settingDrawer'; 6 | import settings from './id-ID/settings'; 7 | import pages from './id-ID/pages'; 8 | 9 | export default { 10 | 'navbar.lang': 'Bahasa', 11 | 'layout.user.link.help': 'Bantuan', 12 | 'layout.user.link.privacy': 'Privasi', 13 | 'layout.user.link.terms': 'Ketentuan', 14 | 'app.preview.down.block': 'Unduh halaman ini dalam projek lokal anda', 15 | 'app.welcome.link.fetch-blocks': 'Dapatkan semua blok', 16 | 'app.welcome.link.block-list': 17 | 'Buat standar dengan cepat, halaman-halaman berdasarkan pengembangan `block`', 18 | ...globalHeader, 19 | ...menu, 20 | ...settingDrawer, 21 | ...settings, 22 | ...pwa, 23 | ...component, 24 | ...pages, 25 | }; 26 | -------------------------------------------------------------------------------- /7.4admin/src/locales/id-ID/component.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'component.tagSelect.expand': 'Perluas', 3 | 'component.tagSelect.collapse': 'Lipat', 4 | 'component.tagSelect.all': 'Semua', 5 | }; 6 | -------------------------------------------------------------------------------- /7.4admin/src/locales/id-ID/globalHeader.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'component.globalHeader.search': 'Pencarian', 3 | 'component.globalHeader.search.example1': 'Contoh 1 Pencarian', 4 | 'component.globalHeader.search.example2': 'Contoh 2 Pencarian', 5 | 'component.globalHeader.search.example3': 'Contoh 3 Pencarian', 6 | 'component.globalHeader.help': 'Bantuan', 7 | 'component.globalHeader.notification': 'Notifikasi', 8 | 'component.globalHeader.notification.empty': 'Anda telah membaca semua notifikasi', 9 | 'component.globalHeader.message': 'Pesan', 10 | 'component.globalHeader.message.empty': 'Anda telah membaca semua pesan.', 11 | 'component.globalHeader.event': 'Acara', 12 | 'component.globalHeader.event.empty': 'Anda telah melihat semua acara.', 13 | 'component.noticeIcon.clear': 'Kosongkan', 14 | 'component.noticeIcon.cleared': 'Berhasil dikosongkan', 15 | 'component.noticeIcon.empty': 'Tidak ada pemberitahuan', 16 | 'component.noticeIcon.view-more': 'Melihat lebih', 17 | }; 18 | -------------------------------------------------------------------------------- /7.4admin/src/locales/id-ID/pwa.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'app.pwa.offline': 'Koneksi anda terputus', 3 | 'app.pwa.serviceworker.updated': 'Konten baru sudah tersedia', 4 | 'app.pwa.serviceworker.updated.hint': 5 | 'Silahkan klik tombol "Refresh" untuk memuat ulang halaman ini', 6 | 'app.pwa.serviceworker.updated.ok': 'Memuat ulang', 7 | }; 8 | -------------------------------------------------------------------------------- /7.4admin/src/locales/ja-JP.ts: -------------------------------------------------------------------------------- 1 | import globalHeader from './ja-JP/globalHeader'; 2 | import menu from './ja-JP/menu'; 3 | import settingDrawer from './ja-JP/settingDrawer'; 4 | import settings from './ja-JP/settings'; 5 | import pwa from './ja-JP/pwa'; 6 | import component from './ja-JP/component'; 7 | import pages from './ja-JP/pages'; 8 | 9 | export default { 10 | 'navBar.lang': '言語', 11 | 'layout.user.link.help': 'ヘルプ', 12 | 'layout.user.link.privacy': 'プライバシー', 13 | 'layout.user.link.terms': '利用規約', 14 | 'app.preview.down.block': 'このページをローカルプロジェクトにダウンロードしてください', 15 | 'app.welcome.link.fetch-blocks': '', 16 | 'app.welcome.link.block-list': '', 17 | ...globalHeader, 18 | ...menu, 19 | ...settingDrawer, 20 | ...settings, 21 | ...pwa, 22 | ...component, 23 | ...pages, 24 | }; 25 | -------------------------------------------------------------------------------- /7.4admin/src/locales/ja-JP/component.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'component.tagSelect.expand': '展開', 3 | 'component.tagSelect.collapse': '折りたたむ', 4 | 'component.tagSelect.all': 'すべて', 5 | }; 6 | -------------------------------------------------------------------------------- /7.4admin/src/locales/ja-JP/globalHeader.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'component.globalHeader.search': '検索', 3 | 'component.globalHeader.search.example1': '検索例1', 4 | 'component.globalHeader.search.example2': '検索例2', 5 | 'component.globalHeader.search.example3': '検索例3', 6 | 'component.globalHeader.help': 'ヘルプ', 7 | 'component.globalHeader.notification': '通知', 8 | 'component.globalHeader.notification.empty': 'すべての通知を表示しました。', 9 | 'component.globalHeader.message': 'メッセージ', 10 | 'component.globalHeader.message.empty': 'すべてのメッセージを表示しました。', 11 | 'component.globalHeader.event': 'イベント', 12 | 'component.globalHeader.event.empty': 'すべてのイベントを表示しました。', 13 | 'component.noticeIcon.clear': 'クリア', 14 | 'component.noticeIcon.cleared': 'クリア済み', 15 | 'component.noticeIcon.empty': '通知なし', 16 | 'component.noticeIcon.view-more': 'もっと見る', 17 | }; 18 | -------------------------------------------------------------------------------- /7.4admin/src/locales/ja-JP/pwa.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'app.pwa.offline': 'あなたは今オフラインです', 3 | 'app.pwa.serviceworker.updated': '新しいコンテンツが利用可能です', 4 | 'app.pwa.serviceworker.updated.hint': 5 | '現在のページをリロードするには、「更新」ボタンを押してください', 6 | 'app.pwa.serviceworker.updated.ok': 'リフレッシュ', 7 | }; 8 | -------------------------------------------------------------------------------- /7.4admin/src/locales/pt-BR.ts: -------------------------------------------------------------------------------- 1 | import component from './pt-BR/component'; 2 | import globalHeader from './pt-BR/globalHeader'; 3 | import menu from './pt-BR/menu'; 4 | import pwa from './pt-BR/pwa'; 5 | import settingDrawer from './pt-BR/settingDrawer'; 6 | import settings from './pt-BR/settings'; 7 | 8 | export default { 9 | 'navBar.lang': 'Idiomas', 10 | 'layout.user.link.help': 'ajuda', 11 | 'layout.user.link.privacy': 'política de privacidade', 12 | 'layout.user.link.terms': 'termos de serviços', 13 | 'app.preview.down.block': 'Download this page to your local project', 14 | ...globalHeader, 15 | ...menu, 16 | ...settingDrawer, 17 | ...settings, 18 | ...pwa, 19 | ...component, 20 | }; 21 | -------------------------------------------------------------------------------- /7.4admin/src/locales/pt-BR/component.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'component.tagSelect.expand': 'Expandir', 3 | 'component.tagSelect.collapse': 'Diminuir', 4 | 'component.tagSelect.all': 'Todas', 5 | }; 6 | -------------------------------------------------------------------------------- /7.4admin/src/locales/pt-BR/globalHeader.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'component.globalHeader.search': 'Busca', 3 | 'component.globalHeader.search.example1': 'Exemplo de busca 1', 4 | 'component.globalHeader.search.example2': 'Exemplo de busca 2', 5 | 'component.globalHeader.search.example3': 'Exemplo de busca 3', 6 | 'component.globalHeader.help': 'Ajuda', 7 | 'component.globalHeader.notification': 'Notificação', 8 | 'component.globalHeader.notification.empty': 'Você visualizou todas as notificações.', 9 | 'component.globalHeader.message': 'Mensagem', 10 | 'component.globalHeader.message.empty': 'Você visualizou todas as mensagens.', 11 | 'component.globalHeader.event': 'Evento', 12 | 'component.globalHeader.event.empty': 'Você visualizou todos os eventos.', 13 | 'component.noticeIcon.clear': 'Limpar', 14 | 'component.noticeIcon.cleared': 'Limpo', 15 | 'component.noticeIcon.empty': 'Sem notificações', 16 | 'component.noticeIcon.loaded': 'Carregado', 17 | 'component.noticeIcon.view-more': 'Veja mais', 18 | }; 19 | -------------------------------------------------------------------------------- /7.4admin/src/locales/pt-BR/pwa.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'app.pwa.offline': 'Você está offline agora', 3 | 'app.pwa.serviceworker.updated': 'Novo conteúdo está disponível', 4 | 'app.pwa.serviceworker.updated.hint': 5 | 'Por favor, pressione o botão "Atualizar" para recarregar a página atual', 6 | 'app.pwa.serviceworker.updated.ok': 'Atualizar', 7 | }; 8 | -------------------------------------------------------------------------------- /7.4admin/src/locales/zh-CN.ts: -------------------------------------------------------------------------------- 1 | import component from './zh-CN/component'; 2 | import globalHeader from './zh-CN/globalHeader'; 3 | import menu from './zh-CN/menu'; 4 | import pwa from './zh-CN/pwa'; 5 | import settingDrawer from './zh-CN/settingDrawer'; 6 | import settings from './zh-CN/settings'; 7 | import pages from './zh-CN/pages'; 8 | 9 | export default { 10 | 'navBar.lang': '语言', 11 | 'layout.user.link.help': '帮助', 12 | 'layout.user.link.privacy': '隐私', 13 | 'layout.user.link.terms': '条款', 14 | 'app.preview.down.block': '下载此页面到本地项目', 15 | 'app.welcome.link.fetch-blocks': '获取全部区块', 16 | 'app.welcome.link.block-list': '基于 block 开发,快速构建标准页面', 17 | ...pages, 18 | ...globalHeader, 19 | ...menu, 20 | ...settingDrawer, 21 | ...settings, 22 | ...pwa, 23 | ...component, 24 | }; 25 | -------------------------------------------------------------------------------- /7.4admin/src/locales/zh-CN/component.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'component.tagSelect.expand': '展开', 3 | 'component.tagSelect.collapse': '收起', 4 | 'component.tagSelect.all': '全部', 5 | }; 6 | -------------------------------------------------------------------------------- /7.4admin/src/locales/zh-CN/globalHeader.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'component.globalHeader.search': '站内搜索', 3 | 'component.globalHeader.search.example1': '搜索提示一', 4 | 'component.globalHeader.search.example2': '搜索提示二', 5 | 'component.globalHeader.search.example3': '搜索提示三', 6 | 'component.globalHeader.help': '使用文档', 7 | 'component.globalHeader.notification': '通知', 8 | 'component.globalHeader.notification.empty': '你已查看所有通知', 9 | 'component.globalHeader.message': '消息', 10 | 'component.globalHeader.message.empty': '您已读完所有消息', 11 | 'component.globalHeader.event': '待办', 12 | 'component.globalHeader.event.empty': '你已完成所有待办', 13 | 'component.noticeIcon.clear': '清空', 14 | 'component.noticeIcon.cleared': '清空了', 15 | 'component.noticeIcon.empty': '暂无数据', 16 | 'component.noticeIcon.view-more': '查看更多', 17 | }; 18 | -------------------------------------------------------------------------------- /7.4admin/src/locales/zh-CN/pwa.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'app.pwa.offline': '当前处于离线状态', 3 | 'app.pwa.serviceworker.updated': '有新内容', 4 | 'app.pwa.serviceworker.updated.hint': '请点击“刷新”按钮或者手动刷新页面', 5 | 'app.pwa.serviceworker.updated.ok': '刷新', 6 | }; 7 | -------------------------------------------------------------------------------- /7.4admin/src/locales/zh-TW.ts: -------------------------------------------------------------------------------- 1 | import component from './zh-TW/component'; 2 | import globalHeader from './zh-TW/globalHeader'; 3 | import menu from './zh-TW/menu'; 4 | import pwa from './zh-TW/pwa'; 5 | import settingDrawer from './zh-TW/settingDrawer'; 6 | import settings from './zh-TW/settings'; 7 | 8 | export default { 9 | 'navBar.lang': '語言', 10 | 'layout.user.link.help': '幫助', 11 | 'layout.user.link.privacy': '隱私', 12 | 'layout.user.link.terms': '條款', 13 | 'app.preview.down.block': '下載此頁面到本地項目', 14 | ...globalHeader, 15 | ...menu, 16 | ...settingDrawer, 17 | ...settings, 18 | ...pwa, 19 | ...component, 20 | }; 21 | -------------------------------------------------------------------------------- /7.4admin/src/locales/zh-TW/component.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'component.tagSelect.expand': '展開', 3 | 'component.tagSelect.collapse': '收起', 4 | 'component.tagSelect.all': '全部', 5 | }; 6 | -------------------------------------------------------------------------------- /7.4admin/src/locales/zh-TW/globalHeader.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'component.globalHeader.search': '站內搜索', 3 | 'component.globalHeader.search.example1': '搜索提示壹', 4 | 'component.globalHeader.search.example2': '搜索提示二', 5 | 'component.globalHeader.search.example3': '搜索提示三', 6 | 'component.globalHeader.help': '使用手冊', 7 | 'component.globalHeader.notification': '通知', 8 | 'component.globalHeader.notification.empty': '妳已查看所有通知', 9 | 'component.globalHeader.message': '消息', 10 | 'component.globalHeader.message.empty': '您已讀完所有消息', 11 | 'component.globalHeader.event': '待辦', 12 | 'component.globalHeader.event.empty': '妳已完成所有待辦', 13 | 'component.noticeIcon.clear': '清空', 14 | 'component.noticeIcon.cleared': '清空了', 15 | 'component.noticeIcon.empty': '暫無資料', 16 | 'component.noticeIcon.view-more': '查看更多', 17 | }; 18 | -------------------------------------------------------------------------------- /7.4admin/src/locales/zh-TW/pwa.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'app.pwa.offline': '當前處於離線狀態', 3 | 'app.pwa.serviceworker.updated': '有新內容', 4 | 'app.pwa.serviceworker.updated.hint': '請點擊“刷新”按鈕或者手動刷新頁面', 5 | 'app.pwa.serviceworker.updated.ok': '刷新', 6 | }; 7 | -------------------------------------------------------------------------------- /7.4admin/src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Ant Design Pro", 3 | "short_name": "Ant Design Pro", 4 | "display": "standalone", 5 | "start_url": "./?utm_source=homescreen", 6 | "theme_color": "#002140", 7 | "background_color": "#001529", 8 | "icons": [ 9 | { 10 | "src": "icons/icon-192x192.png", 11 | "sizes": "192x192" 12 | }, 13 | { 14 | "src": "icons/icon-128x128.png", 15 | "sizes": "128x128" 16 | }, 17 | { 18 | "src": "icons/icon-512x512.png", 19 | "sizes": "512x512" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /7.4admin/src/models/connect.d.ts: -------------------------------------------------------------------------------- 1 | import type { MenuDataItem, Settings as ProSettings } from '@ant-design/pro-layout'; 2 | import { GlobalModelState } from './global'; 3 | import { UserModelState } from './user'; 4 | import type { StateType } from './login'; 5 | 6 | export { GlobalModelState, UserModelState }; 7 | 8 | export type Loading = { 9 | global: boolean; 10 | effects: Record; 11 | models: { 12 | global?: boolean; 13 | menu?: boolean; 14 | setting?: boolean; 15 | user?: boolean; 16 | login?: boolean; 17 | }; 18 | }; 19 | 20 | export type ConnectState = { 21 | global: GlobalModelState; 22 | loading: Loading; 23 | settings: ProSettings; 24 | user: UserModelState; 25 | login: StateType; 26 | }; 27 | 28 | export type Route = { 29 | routes?: Route[]; 30 | } & MenuDataItem; 31 | -------------------------------------------------------------------------------- /7.4admin/src/pages/404.tsx: -------------------------------------------------------------------------------- 1 | import { Button, Result } from 'antd'; 2 | import React from 'react'; 3 | import { history } from 'umi'; 4 | 5 | const NoFoundPage: React.FC = () => ( 6 | history.push('/')}> 12 | Back Home 13 | 14 | } 15 | /> 16 | ); 17 | 18 | export default NoFoundPage; 19 | -------------------------------------------------------------------------------- /7.4admin/src/pages/TableList/data.d.ts: -------------------------------------------------------------------------------- 1 | export type TableListItem = { 2 | key: number; 3 | disabled?: boolean; 4 | href: string; 5 | avatar: string; 6 | name: string; 7 | owner: string; 8 | desc: string; 9 | callNo: number; 10 | status: number; 11 | updatedAt: Date; 12 | createdAt: Date; 13 | progress: number; 14 | }; 15 | 16 | export type TableListPagination = { 17 | total: number; 18 | pageSize: number; 19 | current: number; 20 | }; 21 | 22 | export type TableListData = { 23 | list: TableListItem[]; 24 | pagination: Partial; 25 | }; 26 | 27 | export type TableListParams = { 28 | status?: string; 29 | name?: string; 30 | desc?: string; 31 | key?: number; 32 | pageSize?: number; 33 | currentPage?: number; 34 | filter?: Record; 35 | sorter?: Record; 36 | }; 37 | -------------------------------------------------------------------------------- /7.4admin/src/pages/TableList/service.ts: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import type { TableListParams, TableListItem } from './data.d'; 3 | 4 | export async function queryRule(params?: TableListParams) { 5 | return request('/api/rule', { 6 | params, 7 | }); 8 | } 9 | 10 | export async function removeRule(params: { key: number[] }) { 11 | return request('/api/rule', { 12 | method: 'POST', 13 | data: { 14 | ...params, 15 | method: 'delete', 16 | }, 17 | }); 18 | } 19 | 20 | export async function addRule(params: TableListItem) { 21 | return request('/api/rule', { 22 | method: 'POST', 23 | data: { 24 | ...params, 25 | method: 'post', 26 | }, 27 | }); 28 | } 29 | 30 | export async function updateRule(params: TableListParams) { 31 | return request('/api/rule', { 32 | method: 'POST', 33 | data: { 34 | ...params, 35 | method: 'update', 36 | }, 37 | }); 38 | } 39 | -------------------------------------------------------------------------------- /7.4admin/src/pages/User/login/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .main { 4 | width: 328px; 5 | margin: 0 auto; 6 | @media screen and (max-width: @screen-sm) { 7 | width: 95%; 8 | max-width: 328px; 9 | } 10 | 11 | :global { 12 | .@{ant-prefix}-tabs-nav-list { 13 | margin: auto; 14 | font-size: 16px; 15 | } 16 | } 17 | 18 | .icon { 19 | margin-left: 16px; 20 | color: rgba(0, 0, 0, 0.2); 21 | font-size: 24px; 22 | vertical-align: middle; 23 | cursor: pointer; 24 | transition: color 0.3s; 25 | 26 | &:hover { 27 | color: @primary-color; 28 | } 29 | } 30 | 31 | .other { 32 | margin-top: 24px; 33 | line-height: 22px; 34 | text-align: left; 35 | .register { 36 | float: right; 37 | } 38 | } 39 | 40 | .prefixIcon { 41 | color: @primary-color; 42 | font-size: @font-size-base; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /7.4admin/src/pages/User/register-result/style.less: -------------------------------------------------------------------------------- 1 | .registerResult { 2 | width: 800px; 3 | min-height: 400px; 4 | margin: auto; 5 | padding: 80px; 6 | background: none; 7 | :global { 8 | .anticon { 9 | font-size: 64px; 10 | } 11 | } 12 | .title { 13 | margin-top: 32px; 14 | font-size: 20px; 15 | line-height: 28px; 16 | } 17 | .actions { 18 | margin-top: 40px; 19 | a + a { 20 | margin-left: 8px; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /7.4admin/src/pages/User/register/_mock.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line import/no-extraneous-dependencies 2 | import { Request, Response } from 'express'; 3 | 4 | export default { 5 | 'POST /api/register': (_: Request, res: Response) => { 6 | res.send({ status: 'ok', currentAuthority: 'user' }); 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /7.4admin/src/pages/User/register/service.ts: -------------------------------------------------------------------------------- 1 | import request from 'umi-request'; 2 | import { UserRegisterParams } from './index'; 3 | 4 | export async function fakeRegister(params: UserRegisterParams) { 5 | return request('/api/register', { 6 | method: 'POST', 7 | data: params, 8 | }); 9 | } 10 | -------------------------------------------------------------------------------- /7.4admin/src/pages/User/register/style.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .main { 4 | width: 368px; 5 | margin: 0 auto; 6 | 7 | h3 { 8 | margin-bottom: 20px; 9 | font-size: 16px; 10 | } 11 | 12 | .password { 13 | margin-bottom: 24px; 14 | :global { 15 | .ant-form-item-explain { 16 | display: none; 17 | } 18 | } 19 | } 20 | 21 | .getCaptcha { 22 | display: block; 23 | width: 100%; 24 | } 25 | 26 | .submit { 27 | width: 50%; 28 | } 29 | 30 | .login { 31 | float: right; 32 | line-height: @btn-height-lg; 33 | } 34 | } 35 | 36 | .success, 37 | .warning, 38 | .error { 39 | transition: color 0.3s; 40 | } 41 | 42 | .success { 43 | color: @success-color; 44 | } 45 | 46 | .warning { 47 | color: @warning-color; 48 | } 49 | 50 | .error { 51 | color: @error-color; 52 | } 53 | 54 | .progress-pass > .progress { 55 | :global { 56 | .ant-progress-bg { 57 | background-color: @warning-color; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /7.4admin/src/pages/Welcome.less: -------------------------------------------------------------------------------- 1 | @import '~antd/lib/style/themes/default.less'; 2 | 3 | .pre { 4 | margin: 12px 0; 5 | padding: 12px 20px; 6 | background: @input-bg; 7 | box-shadow: @card-shadow; 8 | } 9 | -------------------------------------------------------------------------------- /7.4admin/src/pages/account/center/components/ArticleListContent/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .listContent { 4 | .description { 5 | max-width: 720px; 6 | line-height: 22px; 7 | } 8 | .extra { 9 | margin-top: 16px; 10 | color: @text-color-secondary; 11 | line-height: 22px; 12 | & > :global(.ant-avatar) { 13 | position: relative; 14 | top: 1px; 15 | width: 20px; 16 | height: 20px; 17 | margin-right: 8px; 18 | vertical-align: top; 19 | } 20 | & > em { 21 | margin-left: 16px; 22 | color: @disabled-color; 23 | font-style: normal; 24 | } 25 | } 26 | } 27 | 28 | @media screen and (max-width: @screen-xs) { 29 | .listContent { 30 | .extra { 31 | & > em { 32 | display: block; 33 | margin-top: 8px; 34 | margin-left: 0; 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /7.4admin/src/pages/account/center/components/ArticleListContent/index.tsx: -------------------------------------------------------------------------------- 1 | import { Avatar } from 'antd'; 2 | import React from 'react'; 3 | import moment from 'moment'; 4 | import styles from './index.less'; 5 | 6 | export interface ApplicationsProps { 7 | data: { 8 | content?: string; 9 | updatedAt?: any; 10 | avatar?: string; 11 | owner?: string; 12 | href?: string; 13 | }; 14 | } 15 | const ArticleListContent: React.FC = ({ 16 | data: { content, updatedAt, avatar, owner, href }, 17 | }) => ( 18 |
19 |
{content}
20 |
21 | 22 | {owner} 发布在 {href} 23 | {moment(updatedAt).format('YYYY-MM-DD HH:mm')} 24 |
25 |
26 | ); 27 | 28 | export default ArticleListContent; 29 | -------------------------------------------------------------------------------- /7.4admin/src/pages/account/center/components/Articles/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .articleList { 4 | :global { 5 | .ant-list-item:first-child { 6 | padding-top: 0; 7 | } 8 | } 9 | } 10 | a.listItemMetaTitle { 11 | color: @heading-color; 12 | } 13 | -------------------------------------------------------------------------------- /7.4admin/src/pages/account/center/service.ts: -------------------------------------------------------------------------------- 1 | import request from 'umi-request'; 2 | 3 | export async function queryCurrent() { 4 | return request('/api/currentUser'); 5 | } 6 | 7 | export async function queryFakeList(params: { count: number }) { 8 | return request('/api/fake_list', { 9 | params, 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /7.4admin/src/pages/account/settings/components/GeographicView.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .row { 4 | .item { 5 | width: 50%; 6 | max-width: 220px; 7 | } 8 | .item:first-child { 9 | width: ~'calc(50% - 8px)'; 10 | margin-right: 8px; 11 | } 12 | } 13 | 14 | @media screen and (max-width: @screen-sm) { 15 | .item:first-child { 16 | margin: 0; 17 | margin-bottom: 8px; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /7.4admin/src/pages/account/settings/components/PhoneView.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .area_code { 4 | width: 30%; 5 | max-width: 128px; 6 | margin-right: 8px; 7 | } 8 | .phone_number { 9 | width: ~'calc(70% - 8px)'; 10 | max-width: 312px; 11 | } 12 | -------------------------------------------------------------------------------- /7.4admin/src/pages/account/settings/data.d.ts: -------------------------------------------------------------------------------- 1 | export interface TagType { 2 | key: string; 3 | label: string; 4 | } 5 | 6 | export interface GeographicItemType { 7 | name: string; 8 | id: string; 9 | } 10 | 11 | export interface GeographicType { 12 | province: GeographicItemType; 13 | city: GeographicItemType; 14 | } 15 | 16 | export interface NoticeType { 17 | id: string; 18 | title: string; 19 | logo: string; 20 | description: string; 21 | updatedAt: string; 22 | member: string; 23 | href: string; 24 | memberLink: string; 25 | } 26 | 27 | export interface CurrentUser { 28 | name: string; 29 | avatar: string; 30 | userid: string; 31 | notice: NoticeType[]; 32 | email: string; 33 | signature: string; 34 | title: string; 35 | group: string; 36 | tags: TagType[]; 37 | notifyCount: number; 38 | unreadCount: number; 39 | country: string; 40 | geographic: GeographicType; 41 | address: string; 42 | phone: string; 43 | } 44 | -------------------------------------------------------------------------------- /7.4admin/src/pages/account/settings/service.ts: -------------------------------------------------------------------------------- 1 | import request from 'umi-request'; 2 | 3 | export async function queryCurrent() { 4 | return request('/api/currentUser'); 5 | } 6 | 7 | export async function queryProvince() { 8 | return request('/api/geographic/province'); 9 | } 10 | 11 | export async function queryCity(province: string) { 12 | return request(`/api/geographic/city/${province}`); 13 | } 14 | 15 | export async function query() { 16 | return request('/api/users'); 17 | } 18 | -------------------------------------------------------------------------------- /7.4admin/src/pages/dashboard/analysis/components/Charts/Field/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .field { 4 | margin: 0; 5 | overflow: hidden; 6 | white-space: nowrap; 7 | text-overflow: ellipsis; 8 | .label, 9 | .number { 10 | font-size: @font-size-base; 11 | line-height: 22px; 12 | } 13 | .number { 14 | margin-left: 8px; 15 | color: @heading-color; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /7.4admin/src/pages/dashboard/analysis/components/Charts/Field/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styles from './index.less'; 3 | 4 | export interface FieldProps { 5 | label: React.ReactNode; 6 | value: React.ReactNode; 7 | style?: React.CSSProperties; 8 | } 9 | 10 | const Field: React.FC = ({ label, value, ...rest }) => ( 11 |
12 | {label} 13 | {value} 14 |
15 | ); 16 | 17 | export default Field; 18 | -------------------------------------------------------------------------------- /7.4admin/src/pages/dashboard/analysis/components/Charts/MiniProgress/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .miniProgress { 4 | position: relative; 5 | width: 100%; 6 | padding: 5px 0; 7 | .progressWrap { 8 | position: relative; 9 | background-color: @background-color-base; 10 | } 11 | .progress { 12 | width: 0; 13 | height: 100%; 14 | background-color: @primary-color; 15 | border-radius: 1px 0 0 1px; 16 | transition: all 0.4s cubic-bezier(0.08, 0.82, 0.17, 1) 0s; 17 | } 18 | .target { 19 | position: absolute; 20 | top: 0; 21 | bottom: 0; 22 | z-index: 9; 23 | width: 20px; 24 | span { 25 | position: absolute; 26 | top: 0; 27 | left: 0; 28 | width: 2px; 29 | height: 4px; 30 | border-radius: 100px; 31 | } 32 | span:last-child { 33 | top: auto; 34 | bottom: 0; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /7.4admin/src/pages/dashboard/analysis/components/Charts/TagCloud/index.less: -------------------------------------------------------------------------------- 1 | .tagCloud { 2 | overflow: hidden; 3 | canvas { 4 | transform-origin: 0 0; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /7.4admin/src/pages/dashboard/analysis/components/Charts/TimelineChart/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .timelineChart { 4 | background: @component-background; 5 | } 6 | -------------------------------------------------------------------------------- /7.4admin/src/pages/dashboard/analysis/components/Charts/WaterWave/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .waterWave { 4 | position: relative; 5 | display: inline-block; 6 | transform-origin: left; 7 | .text { 8 | position: absolute; 9 | top: 32px; 10 | left: 0; 11 | width: 100%; 12 | text-align: center; 13 | span { 14 | color: @text-color-secondary; 15 | font-size: 14px; 16 | line-height: 22px; 17 | } 18 | h4 { 19 | color: @heading-color; 20 | font-size: 24px; 21 | line-height: 32px; 22 | } 23 | } 24 | .waterWaveCanvasWrapper { 25 | transform: scale(0.5); 26 | transform-origin: 0 0; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /7.4admin/src/pages/dashboard/analysis/components/Charts/bizcharts.tsx: -------------------------------------------------------------------------------- 1 | import * as BizChart from 'bizcharts'; 2 | 3 | export default BizChart; 4 | -------------------------------------------------------------------------------- /7.4admin/src/pages/dashboard/analysis/components/Charts/index.less: -------------------------------------------------------------------------------- 1 | .miniChart { 2 | position: relative; 3 | width: 100%; 4 | .chartContent { 5 | position: absolute; 6 | bottom: -28px; 7 | width: 100%; 8 | > div { 9 | margin: 0 -5px; 10 | overflow: hidden; 11 | } 12 | } 13 | .chartLoading { 14 | position: absolute; 15 | top: 16px; 16 | left: 50%; 17 | margin-left: -7px; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /7.4admin/src/pages/dashboard/analysis/components/PageLoading/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Spin } from 'antd'; 3 | 4 | // loading components from code split 5 | // https://umijs.org/plugin/umi-plugin-react.html#dynamicimport 6 | export default () => ( 7 |
8 | 9 |
10 | ); 11 | -------------------------------------------------------------------------------- /7.4admin/src/pages/dashboard/analysis/components/Trend/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .trendItem { 4 | display: inline-block; 5 | font-size: @font-size-base; 6 | line-height: 22px; 7 | 8 | .up, 9 | .down { 10 | position: relative; 11 | top: 1px; 12 | margin-left: 4px; 13 | span { 14 | font-size: 12px; 15 | transform: scale(0.83); 16 | } 17 | } 18 | .up { 19 | color: @red-6; 20 | } 21 | .down { 22 | top: -1px; 23 | color: @green-6; 24 | } 25 | 26 | &.trendItemGrey .up, 27 | &.trendItemGrey .down { 28 | color: @text-color; 29 | } 30 | 31 | &.reverseColor .up { 32 | color: @green-6; 33 | } 34 | &.reverseColor .down { 35 | color: @red-6; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /7.4admin/src/pages/dashboard/analysis/data.d.ts: -------------------------------------------------------------------------------- 1 | export interface VisitDataType { 2 | x: string; 3 | y: number; 4 | } 5 | 6 | export interface SearchDataType { 7 | index: number; 8 | keyword: string; 9 | count: number; 10 | range: number; 11 | status: number; 12 | } 13 | 14 | export interface OfflineDataType { 15 | name: string; 16 | cvr: number; 17 | } 18 | 19 | export interface OfflineChartData { 20 | x: any; 21 | y1: number; 22 | y2: number; 23 | } 24 | 25 | export interface RadarData { 26 | name: string; 27 | label: string; 28 | value: number; 29 | } 30 | 31 | export interface AnalysisData { 32 | visitData: VisitDataType[]; 33 | visitData2: VisitDataType[]; 34 | salesData: VisitDataType[]; 35 | searchData: SearchDataType[]; 36 | offlineData: OfflineDataType[]; 37 | offlineChartData: OfflineChartData[]; 38 | salesTypeData: VisitDataType[]; 39 | salesTypeDataOnline: VisitDataType[]; 40 | salesTypeDataOffline: VisitDataType[]; 41 | radarData: RadarData[]; 42 | } 43 | -------------------------------------------------------------------------------- /7.4admin/src/pages/dashboard/analysis/service.ts: -------------------------------------------------------------------------------- 1 | import request from 'umi-request'; 2 | 3 | export async function fakeChartData() { 4 | return request('/api/fake_chart_data'); 5 | } 6 | -------------------------------------------------------------------------------- /7.4admin/src/pages/dashboard/analysis/utils/Yuan.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { yuan } from '../components/Charts'; 3 | /** 4 | * 减少使用 dangerouslySetInnerHTML 5 | */ 6 | export default class Yuan extends React.Component<{ 7 | children: React.ReactText; 8 | }> { 9 | main: HTMLSpanElement | undefined | null = null; 10 | 11 | componentDidMount() { 12 | this.renderToHtml(); 13 | } 14 | 15 | componentDidUpdate() { 16 | this.renderToHtml(); 17 | } 18 | 19 | renderToHtml = () => { 20 | const { children } = this.props; 21 | if (this.main) { 22 | this.main.innerHTML = yuan(children); 23 | } 24 | }; 25 | 26 | render() { 27 | return ( 28 | { 30 | this.main = ref; 31 | }} 32 | /> 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /7.4admin/src/pages/dashboard/monitor/_mock.ts: -------------------------------------------------------------------------------- 1 | import mockjs from 'mockjs'; 2 | 3 | export default { 4 | 'GET /api/tags': mockjs.mock({ 5 | 'list|100': [{ name: '@city', 'value|1-100': 150, 'type|0-2': 1 }], 6 | }), 7 | }; 8 | -------------------------------------------------------------------------------- /7.4admin/src/pages/dashboard/monitor/components/Charts/TagCloud/index.less: -------------------------------------------------------------------------------- 1 | .tagCloud { 2 | overflow: hidden; 3 | canvas { 4 | transform-origin: 0 0; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /7.4admin/src/pages/dashboard/monitor/components/Charts/WaterWave/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .waterWave { 4 | position: relative; 5 | display: inline-block; 6 | transform-origin: left; 7 | .text { 8 | position: absolute; 9 | top: 32px; 10 | left: 0; 11 | width: 100%; 12 | text-align: center; 13 | span { 14 | color: @text-color-secondary; 15 | font-size: 14px; 16 | line-height: 22px; 17 | } 18 | h4 { 19 | color: @heading-color; 20 | font-size: 24px; 21 | line-height: 32px; 22 | } 23 | } 24 | .waterWaveCanvasWrapper { 25 | transform: scale(0.5); 26 | transform-origin: 0 0; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /7.4admin/src/pages/dashboard/monitor/components/Charts/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .miniChart { 4 | position: relative; 5 | width: 100%; 6 | .chartContent { 7 | position: absolute; 8 | bottom: -28px; 9 | width: 100%; 10 | > div { 11 | margin: 0 -5px; 12 | overflow: hidden; 13 | } 14 | } 15 | .chartLoading { 16 | position: absolute; 17 | top: 16px; 18 | left: 50%; 19 | margin-left: -7px; 20 | } 21 | } 22 | 23 | :global { 24 | body .l7-popup-content { 25 | background: @component-background; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /7.4admin/src/pages/dashboard/monitor/components/Charts/index.tsx: -------------------------------------------------------------------------------- 1 | import Gauge from './Gauge'; 2 | import MiniArea from './MiniArea'; 3 | import Pie from './Pie'; 4 | import TagCloud from './TagCloud'; 5 | import WaterWave from './WaterWave'; 6 | import Map from './Map'; 7 | 8 | const Charts = { 9 | Pie, 10 | WaterWave, 11 | Gauge, 12 | MiniArea, 13 | TagCloud, 14 | Map, 15 | }; 16 | 17 | export { Charts as default, Pie, WaterWave, Gauge, TagCloud, MiniArea, Map }; 18 | -------------------------------------------------------------------------------- /7.4admin/src/pages/dashboard/monitor/data.d.ts: -------------------------------------------------------------------------------- 1 | export interface TagType { 2 | name: string; 3 | value: string; 4 | type: string; 5 | } 6 | -------------------------------------------------------------------------------- /7.4admin/src/pages/dashboard/monitor/model.ts: -------------------------------------------------------------------------------- 1 | import { Effect, Reducer } from 'umi'; 2 | 3 | import { TagType } from './data.d'; 4 | import { queryTags } from './service'; 5 | 6 | export interface StateType { 7 | tags: TagType[]; 8 | } 9 | 10 | export interface ModelType { 11 | namespace: string; 12 | state: StateType; 13 | effects: { 14 | fetchTags: Effect; 15 | }; 16 | reducers: { 17 | saveTags: Reducer; 18 | }; 19 | } 20 | 21 | const Model: ModelType = { 22 | namespace: 'dashboardAndmonitor', 23 | 24 | state: { 25 | tags: [], 26 | }, 27 | 28 | effects: { 29 | *fetchTags(_, { call, put }) { 30 | const response = yield call(queryTags); 31 | yield put({ 32 | type: 'saveTags', 33 | payload: response.list, 34 | }); 35 | }, 36 | }, 37 | 38 | reducers: { 39 | saveTags(state, action) { 40 | return { 41 | ...state, 42 | tags: action.payload, 43 | }; 44 | }, 45 | }, 46 | }; 47 | 48 | export default Model; 49 | -------------------------------------------------------------------------------- /7.4admin/src/pages/dashboard/monitor/service.ts: -------------------------------------------------------------------------------- 1 | import request from 'umi-request'; 2 | 3 | export async function queryTags() { 4 | return request('/api/tags'); 5 | } 6 | -------------------------------------------------------------------------------- /7.4admin/src/pages/dashboard/monitor/style.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .mapChart { 4 | height: 452px; 5 | padding-top: 24px; 6 | img { 7 | display: inline-block; 8 | max-width: 100%; 9 | max-height: 437px; 10 | } 11 | } 12 | 13 | .pieCard :global(.pie-stat) { 14 | font-size: 24px !important; 15 | } 16 | 17 | @media screen and (max-width: @screen-lg) { 18 | .mapChart { 19 | height: auto; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /7.4admin/src/pages/dashboard/workplace/components/EditableLinkGroup/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .linkGroup { 4 | padding: 20px 0 8px 24px; 5 | font-size: 0; 6 | & > a { 7 | display: inline-block; 8 | width: 25%; 9 | margin-bottom: 13px; 10 | color: @text-color; 11 | font-size: @font-size-base; 12 | &:hover { 13 | color: @primary-color; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /7.4admin/src/pages/dashboard/workplace/service.ts: -------------------------------------------------------------------------------- 1 | import request from 'umi-request'; 2 | 3 | export async function queryProjectNotice() { 4 | return request('/api/project/notice'); 5 | } 6 | 7 | export async function queryActivities() { 8 | return request('/api/activities'); 9 | } 10 | 11 | export async function fakeChartData() { 12 | return request('/api/fake_chart_data'); 13 | } 14 | 15 | export async function queryCurrent() { 16 | return request('/api/currentUser'); 17 | } 18 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/flow/common/IconFont/index.ts: -------------------------------------------------------------------------------- 1 | import { createFromIconfontCN } from '@ant-design/icons'; 2 | 3 | const IconFont = createFromIconfontCN({ 4 | scriptUrl: 'https://at.alicdn.com/t/font_1101588_01zniftxm9yp.js', 5 | }); 6 | 7 | export default IconFont; 8 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/flow/components/EditorContextMenu/KoniContextMenu.tsx: -------------------------------------------------------------------------------- 1 | import FlowContextMenu from './FlowContextMenu'; 2 | 3 | export default FlowContextMenu; 4 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/flow/components/EditorContextMenu/MenuItem.tsx: -------------------------------------------------------------------------------- 1 | import { Command } from 'gg-editor'; 2 | import React from 'react'; 3 | import IconFont from '../../common/IconFont'; 4 | import styles from './index.less'; 5 | 6 | const upperFirst = (str: string) => 7 | str.toLowerCase().replace(/( |^)[a-z]/g, (l: string) => l.toUpperCase()); 8 | 9 | interface MenuItemProps { 10 | command: string; 11 | icon?: string; 12 | text?: string; 13 | } 14 | const MenuItem: React.FC = (props) => { 15 | const { command, icon, text } = props; 16 | 17 | return ( 18 | 19 |
20 | 21 | {text || upperFirst(command)} 22 |
23 |
24 | ); 25 | }; 26 | 27 | export default MenuItem; 28 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/flow/components/EditorContextMenu/MindContextMenu.tsx: -------------------------------------------------------------------------------- 1 | import { CanvasMenu, ContextMenu, NodeMenu } from 'gg-editor'; 2 | 3 | import React from 'react'; 4 | import MenuItem from './MenuItem'; 5 | import styles from './index.less'; 6 | 7 | const MindContextMenu = () => ( 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | ); 22 | 23 | export default MindContextMenu; 24 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/flow/components/EditorContextMenu/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .contextMenu { 4 | display: none; 5 | overflow: hidden; 6 | background: @component-background; 7 | border-radius: 4px; 8 | box-shadow: @box-shadow-base; 9 | 10 | .item { 11 | display: flex; 12 | align-items: center; 13 | padding: 5px 12px; 14 | cursor: pointer; 15 | transition: all 0.3s; 16 | user-select: none; 17 | 18 | &:hover { 19 | background: @select-item-selected-bg; 20 | } 21 | 22 | span.anticon { 23 | margin-right: 8px; 24 | } 25 | } 26 | 27 | :global { 28 | .disable { 29 | :local { 30 | .item { 31 | color: @disabled-color; 32 | cursor: auto; 33 | 34 | &:hover { 35 | background: @item-hover-bg; 36 | } 37 | } 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/flow/components/EditorContextMenu/index.tsx: -------------------------------------------------------------------------------- 1 | import FlowContextMenu from './FlowContextMenu'; 2 | import KoniContextMenu from './KoniContextMenu'; 3 | import MindContextMenu from './MindContextMenu'; 4 | 5 | export { FlowContextMenu, MindContextMenu, KoniContextMenu }; 6 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/flow/components/EditorDetailPanel/FlowDetailPanel.tsx: -------------------------------------------------------------------------------- 1 | import { CanvasPanel, DetailPanel, EdgePanel, GroupPanel, MultiPanel, NodePanel } from 'gg-editor'; 2 | 3 | import { Card } from 'antd'; 4 | import React from 'react'; 5 | import DetailForm from './DetailForm'; 6 | import styles from './index.less'; 7 | 8 | const FlowDetailPanel = () => ( 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | ); 27 | 28 | export default FlowDetailPanel; 29 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/flow/components/EditorDetailPanel/KoniDetailPanel.tsx: -------------------------------------------------------------------------------- 1 | import FlowDetailPanel from './FlowDetailPanel'; 2 | 3 | export default FlowDetailPanel; 4 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/flow/components/EditorDetailPanel/MindDetailPanel.tsx: -------------------------------------------------------------------------------- 1 | import { CanvasPanel, DetailPanel, NodePanel } from 'gg-editor'; 2 | 3 | import { Card } from 'antd'; 4 | import React from 'react'; 5 | import DetailForm from './DetailForm'; 6 | import styles from './index.less'; 7 | 8 | const MindDetailPanel = () => ( 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | ); 18 | 19 | export default MindDetailPanel; 20 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/flow/components/EditorDetailPanel/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .detailPanel { 4 | flex: 1; 5 | background-color: @component-background; 6 | } 7 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/flow/components/EditorDetailPanel/index.tsx: -------------------------------------------------------------------------------- 1 | import FlowDetailPanel from './FlowDetailPanel'; 2 | import KoniDetailPanel from './KoniDetailPanel'; 3 | import MindDetailPanel from './MindDetailPanel'; 4 | 5 | export { FlowDetailPanel, MindDetailPanel, KoniDetailPanel }; 6 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/flow/components/EditorItemPanel/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .itemPanel { 4 | flex: 1; 5 | 6 | :global { 7 | .ant-card { 8 | height: 100%; 9 | } 10 | .ant-card-body { 11 | display: flex; 12 | flex-direction: column; 13 | align-items: center; 14 | > div { 15 | margin-bottom: 16px; 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/flow/components/EditorItemPanel/index.tsx: -------------------------------------------------------------------------------- 1 | import FlowItemPanel from './FlowItemPanel'; 2 | import KoniItemPanel from './KoniItemPanel'; 3 | 4 | export { FlowItemPanel, KoniItemPanel }; 5 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/flow/components/EditorMinimap/index.tsx: -------------------------------------------------------------------------------- 1 | import { Card } from 'antd'; 2 | import { Minimap } from 'gg-editor'; 3 | import React from 'react'; 4 | 5 | const EditorMinimap = () => ( 6 | 7 | 8 | 9 | ); 10 | 11 | export default EditorMinimap; 12 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/flow/components/EditorToolbar/KoniToolbar.tsx: -------------------------------------------------------------------------------- 1 | import FlowToolbar from './FlowToolbar'; 2 | 3 | export default FlowToolbar; 4 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/flow/components/EditorToolbar/ToolbarButton.tsx: -------------------------------------------------------------------------------- 1 | import { Command } from 'gg-editor'; 2 | import React from 'react'; 3 | import { Tooltip } from 'antd'; 4 | import IconFont from '../../common/IconFont'; 5 | import styles from './index.less'; 6 | 7 | const upperFirst = (str: string) => 8 | str.toLowerCase().replace(/( |^)[a-z]/g, (l: string) => l.toUpperCase()); 9 | 10 | interface ToolbarButtonProps { 11 | command: string; 12 | icon?: string; 13 | text?: string; 14 | } 15 | const ToolbarButton: React.FC = (props) => { 16 | const { command, icon, text } = props; 17 | 18 | return ( 19 | 20 | 25 | 26 | 27 | 28 | ); 29 | }; 30 | 31 | export default ToolbarButton; 32 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/flow/components/EditorToolbar/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .toolbar { 4 | display: flex; 5 | align-items: center; 6 | 7 | :global { 8 | .command .anticon { 9 | display: inline-block; 10 | width: 27px; 11 | height: 27px; 12 | margin: 0 6px; 13 | padding-top: 6px; 14 | text-align: center; 15 | cursor: pointer; 16 | 17 | &:hover { 18 | border: 1px solid @item-active-bg; 19 | } 20 | } 21 | 22 | .disable .anticon { 23 | color: @text-color-secondary; 24 | cursor: auto; 25 | 26 | &:hover { 27 | border: 1px solid @border-color-base; 28 | } 29 | } 30 | } 31 | } 32 | 33 | .tooltip { 34 | :global { 35 | .ant-tooltip-inner { 36 | font-size: 12px; 37 | border-radius: 0; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/flow/components/EditorToolbar/index.tsx: -------------------------------------------------------------------------------- 1 | import FlowToolbar from './FlowToolbar'; 2 | import KoniToolbar from './KoniToolbar'; 3 | import MindToolbar from './MindToolbar'; 4 | 5 | export { FlowToolbar, MindToolbar, KoniToolbar }; 6 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/flow/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .editor { 4 | display: flex; 5 | flex: 1; 6 | flex-direction: column; 7 | width: 100%; 8 | height: calc(100vh - 250px); 9 | background: @component-background; 10 | } 11 | 12 | .editorHd { 13 | padding: 8px; 14 | background: @descriptions-bg; 15 | border: 1px solid @item-active-bg; 16 | } 17 | 18 | .editorBd { 19 | flex: 1; 20 | } 21 | 22 | .editorSidebar, 23 | .editorContent { 24 | display: flex; 25 | flex-direction: column; 26 | } 27 | 28 | .editorSidebar { 29 | background: @descriptions-bg; 30 | :global { 31 | .g6-editor-minimap-container { 32 | background: none !important ; 33 | } 34 | } 35 | &:first-child { 36 | border-right: 1px solid @item-active-bg; 37 | } 38 | 39 | &:last-child { 40 | border-left: 1px solid @item-active-bg; 41 | } 42 | } 43 | 44 | .flow, 45 | .mind, 46 | .koni { 47 | flex: 1; 48 | } 49 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/flow/locales/en-US.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'editorandflow.description': 3 | 'The flow chart is an excellent way to represent the idea of the algorithm', 4 | }; 5 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/flow/locales/zh-CN.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'editorandflow.description': '千言万语不如一张图,流程图是表示算法思路的好方法', 3 | }; 4 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/koni/common/IconFont/index.ts: -------------------------------------------------------------------------------- 1 | import { createFromIconfontCN } from '@ant-design/icons'; 2 | 3 | const IconFont = createFromIconfontCN({ 4 | scriptUrl: 'https://at.alicdn.com/t/font_1101588_01zniftxm9yp.js', 5 | }); 6 | 7 | export default IconFont; 8 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/koni/components/EditorContextMenu/KoniContextMenu.tsx: -------------------------------------------------------------------------------- 1 | import FlowContextMenu from './FlowContextMenu'; 2 | 3 | export default FlowContextMenu; 4 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/koni/components/EditorContextMenu/MenuItem.tsx: -------------------------------------------------------------------------------- 1 | import { Command } from 'gg-editor'; 2 | import React from 'react'; 3 | import IconFont from '../../common/IconFont'; 4 | import styles from './index.less'; 5 | 6 | const upperFirst = (str: string) => 7 | str.toLowerCase().replace(/( |^)[a-z]/g, (l: string) => l.toUpperCase()); 8 | 9 | interface MenuItemProps { 10 | command: string; 11 | icon?: string; 12 | text?: string; 13 | } 14 | const MenuItem: React.FC = (props) => { 15 | const { command, icon, text } = props; 16 | 17 | return ( 18 | 19 |
20 | 21 | {text || upperFirst(command)} 22 |
23 |
24 | ); 25 | }; 26 | 27 | export default MenuItem; 28 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/koni/components/EditorContextMenu/MindContextMenu.tsx: -------------------------------------------------------------------------------- 1 | import { CanvasMenu, ContextMenu, NodeMenu } from 'gg-editor'; 2 | 3 | import React from 'react'; 4 | import MenuItem from './MenuItem'; 5 | import styles from './index.less'; 6 | 7 | const MindContextMenu = () => ( 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | ); 22 | 23 | export default MindContextMenu; 24 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/koni/components/EditorContextMenu/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .contextMenu { 4 | display: none; 5 | overflow: hidden; 6 | background: @component-background; 7 | border-radius: 4px; 8 | box-shadow: @box-shadow-base; 9 | .item { 10 | display: flex; 11 | align-items: center; 12 | padding: 5px 12px; 13 | cursor: pointer; 14 | transition: all 0.3s; 15 | user-select: none; 16 | 17 | &:hover { 18 | background: @select-item-selected-bg; 19 | } 20 | 21 | .anticon { 22 | margin-right: 8px; 23 | } 24 | } 25 | 26 | :global { 27 | .disable { 28 | :local { 29 | .item { 30 | color: @disabled-color; 31 | cursor: auto; 32 | 33 | &:hover { 34 | background: @item-hover-bg; 35 | } 36 | } 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/koni/components/EditorContextMenu/index.tsx: -------------------------------------------------------------------------------- 1 | import FlowContextMenu from './FlowContextMenu'; 2 | import KoniContextMenu from './KoniContextMenu'; 3 | import MindContextMenu from './MindContextMenu'; 4 | 5 | export { FlowContextMenu, MindContextMenu, KoniContextMenu }; 6 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/koni/components/EditorDetailPanel/FlowDetailPanel.tsx: -------------------------------------------------------------------------------- 1 | import { CanvasPanel, DetailPanel, EdgePanel, GroupPanel, MultiPanel, NodePanel } from 'gg-editor'; 2 | 3 | import { Card } from 'antd'; 4 | import React from 'react'; 5 | import DetailForm from './DetailForm'; 6 | import styles from './index.less'; 7 | 8 | const FlowDetailPanel = () => ( 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | ); 27 | 28 | export default FlowDetailPanel; 29 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/koni/components/EditorDetailPanel/KoniDetailPanel.tsx: -------------------------------------------------------------------------------- 1 | import FlowDetailPanel from './FlowDetailPanel'; 2 | 3 | export default FlowDetailPanel; 4 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/koni/components/EditorDetailPanel/MindDetailPanel.tsx: -------------------------------------------------------------------------------- 1 | import { CanvasPanel, DetailPanel, NodePanel } from 'gg-editor'; 2 | 3 | import { Card } from 'antd'; 4 | import React from 'react'; 5 | import DetailForm from './DetailForm'; 6 | import styles from './index.less'; 7 | 8 | const MindDetailPanel = () => ( 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | ); 18 | 19 | export default MindDetailPanel; 20 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/koni/components/EditorDetailPanel/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .detailPanel { 4 | flex: 1; 5 | background-color: @component-background; 6 | } 7 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/koni/components/EditorDetailPanel/index.tsx: -------------------------------------------------------------------------------- 1 | import FlowDetailPanel from './FlowDetailPanel'; 2 | import KoniDetailPanel from './KoniDetailPanel'; 3 | import MindDetailPanel from './MindDetailPanel'; 4 | 5 | export { FlowDetailPanel, MindDetailPanel, KoniDetailPanel }; 6 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/koni/components/EditorItemPanel/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .itemPanel { 4 | flex: 1; 5 | 6 | :global { 7 | .ant-card { 8 | height: 100%; 9 | } 10 | .ant-card-body { 11 | display: flex; 12 | flex-direction: column; 13 | align-items: center; 14 | > div { 15 | margin-bottom: 16px; 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/koni/components/EditorItemPanel/index.tsx: -------------------------------------------------------------------------------- 1 | import FlowItemPanel from './FlowItemPanel'; 2 | import KoniItemPanel from './KoniItemPanel'; 3 | 4 | export { FlowItemPanel, KoniItemPanel }; 5 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/koni/components/EditorMinimap/index.tsx: -------------------------------------------------------------------------------- 1 | import { Card } from 'antd'; 2 | import { Minimap } from 'gg-editor'; 3 | import React from 'react'; 4 | 5 | const EditorMinimap = () => ( 6 | 7 | 8 | 9 | ); 10 | 11 | export default EditorMinimap; 12 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/koni/components/EditorToolbar/KoniToolbar.tsx: -------------------------------------------------------------------------------- 1 | import FlowToolbar from './FlowToolbar'; 2 | 3 | export default FlowToolbar; 4 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/koni/components/EditorToolbar/ToolbarButton.tsx: -------------------------------------------------------------------------------- 1 | import { Command } from 'gg-editor'; 2 | import React from 'react'; 3 | import { Tooltip } from 'antd'; 4 | import IconFont from '../../common/IconFont'; 5 | import styles from './index.less'; 6 | 7 | const upperFirst = (str: string) => 8 | str.toLowerCase().replace(/( |^)[a-z]/g, (l: string) => l.toUpperCase()); 9 | 10 | interface ToolbarButtonProps { 11 | command: string; 12 | icon?: string; 13 | text?: string; 14 | } 15 | const ToolbarButton: React.FC = (props) => { 16 | const { command, icon, text } = props; 17 | 18 | return ( 19 | 20 | 25 | 26 | 27 | 28 | ); 29 | }; 30 | 31 | export default ToolbarButton; 32 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/koni/components/EditorToolbar/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .toolbar { 4 | display: flex; 5 | align-items: center; 6 | :global { 7 | .command .anticon { 8 | display: inline-block; 9 | width: 27px; 10 | height: 27px; 11 | margin: 0 6px; 12 | padding-top: 6px; 13 | text-align: center; 14 | cursor: pointer; 15 | 16 | &:hover { 17 | border: 1px solid @item-active-bg; 18 | } 19 | } 20 | 21 | .disable .anticon { 22 | color: @text-color-secondary; 23 | cursor: auto; 24 | 25 | &:hover { 26 | border: 1px solid @border-color-base; 27 | } 28 | } 29 | } 30 | } 31 | 32 | .tooltip { 33 | :global { 34 | .ant-tooltip-inner { 35 | font-size: 12px; 36 | border-radius: 0; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/koni/components/EditorToolbar/index.tsx: -------------------------------------------------------------------------------- 1 | import FlowToolbar from './FlowToolbar'; 2 | import KoniToolbar from './KoniToolbar'; 3 | import MindToolbar from './MindToolbar'; 4 | 5 | export { FlowToolbar, MindToolbar, KoniToolbar }; 6 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/koni/locales/en-US.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'editorandkoni.description': 3 | 'The topology diagram refers to the network structure diagram composed of network node devices and communication media', 4 | }; 5 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/koni/locales/zh-CN.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'editorandkoni.description': '拓扑结构图是指由网络节点设备和通信介质构成的网络结构图', 3 | }; 4 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/mind/common/IconFont/index.ts: -------------------------------------------------------------------------------- 1 | import { createFromIconfontCN } from '@ant-design/icons'; 2 | 3 | const IconFont = createFromIconfontCN({ 4 | scriptUrl: 'https://at.alicdn.com/t/font_1101588_01zniftxm9yp.js', 5 | }); 6 | 7 | export default IconFont; 8 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/mind/components/EditorContextMenu/KoniContextMenu.tsx: -------------------------------------------------------------------------------- 1 | import FlowContextMenu from './FlowContextMenu'; 2 | 3 | export default FlowContextMenu; 4 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/mind/components/EditorContextMenu/MenuItem.tsx: -------------------------------------------------------------------------------- 1 | import { Command } from 'gg-editor'; 2 | import React from 'react'; 3 | import IconFont from '../../common/IconFont'; 4 | import styles from './index.less'; 5 | 6 | const upperFirst = (str: string) => 7 | str.toLowerCase().replace(/( |^)[a-z]/g, (l: string) => l.toUpperCase()); 8 | 9 | interface MenuItemProps { 10 | command: string; 11 | icon?: string; 12 | text?: string; 13 | } 14 | const MenuItem: React.FC = (props) => { 15 | const { command, icon, text } = props; 16 | 17 | return ( 18 | 19 |
20 | 21 | {text || upperFirst(command)} 22 |
23 |
24 | ); 25 | }; 26 | 27 | export default MenuItem; 28 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/mind/components/EditorContextMenu/MindContextMenu.tsx: -------------------------------------------------------------------------------- 1 | import { CanvasMenu, ContextMenu, NodeMenu } from 'gg-editor'; 2 | 3 | import React from 'react'; 4 | import MenuItem from './MenuItem'; 5 | import styles from './index.less'; 6 | 7 | const MindContextMenu = () => ( 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | ); 22 | 23 | export default MindContextMenu; 24 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/mind/components/EditorContextMenu/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .contextMenu { 4 | display: none; 5 | overflow: hidden; 6 | background: @component-background; 7 | border-radius: 4px; 8 | box-shadow: @box-shadow-base; 9 | .item { 10 | display: flex; 11 | align-items: center; 12 | padding: 5px 12px; 13 | cursor: pointer; 14 | transition: all 0.3s; 15 | user-select: none; 16 | 17 | &:hover { 18 | background: @select-item-selected-bg; 19 | } 20 | 21 | .anticon { 22 | margin-right: 8px; 23 | } 24 | } 25 | 26 | :global { 27 | .disable { 28 | :local { 29 | .item { 30 | color: @disabled-color; 31 | cursor: auto; 32 | 33 | &:hover { 34 | background: @item-hover-bg; 35 | } 36 | } 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/mind/components/EditorContextMenu/index.tsx: -------------------------------------------------------------------------------- 1 | import FlowContextMenu from './FlowContextMenu'; 2 | import KoniContextMenu from './KoniContextMenu'; 3 | import MindContextMenu from './MindContextMenu'; 4 | 5 | export { FlowContextMenu, MindContextMenu, KoniContextMenu }; 6 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/mind/components/EditorDetailPanel/FlowDetailPanel.tsx: -------------------------------------------------------------------------------- 1 | import { CanvasPanel, DetailPanel, EdgePanel, GroupPanel, MultiPanel, NodePanel } from 'gg-editor'; 2 | 3 | import { Card } from 'antd'; 4 | import React from 'react'; 5 | import DetailForm from './DetailForm'; 6 | import styles from './index.less'; 7 | 8 | const FlowDetailPanel = () => ( 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | ); 27 | 28 | export default FlowDetailPanel; 29 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/mind/components/EditorDetailPanel/KoniDetailPanel.tsx: -------------------------------------------------------------------------------- 1 | import FlowDetailPanel from './FlowDetailPanel'; 2 | 3 | export default FlowDetailPanel; 4 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/mind/components/EditorDetailPanel/MindDetailPanel.tsx: -------------------------------------------------------------------------------- 1 | import { CanvasPanel, DetailPanel, NodePanel } from 'gg-editor'; 2 | 3 | import { Card } from 'antd'; 4 | import React from 'react'; 5 | import DetailForm from './DetailForm'; 6 | import styles from './index.less'; 7 | 8 | const MindDetailPanel = () => ( 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | ); 18 | 19 | export default MindDetailPanel; 20 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/mind/components/EditorDetailPanel/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .detailPanel { 4 | flex: 1; 5 | background-color: @component-background; 6 | } 7 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/mind/components/EditorDetailPanel/index.tsx: -------------------------------------------------------------------------------- 1 | import FlowDetailPanel from './FlowDetailPanel'; 2 | import KoniDetailPanel from './KoniDetailPanel'; 3 | import MindDetailPanel from './MindDetailPanel'; 4 | 5 | export { FlowDetailPanel, MindDetailPanel, KoniDetailPanel }; 6 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/mind/components/EditorItemPanel/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .itemPanel { 4 | flex: 1; 5 | 6 | :global { 7 | .ant-card { 8 | height: 100%; 9 | } 10 | .ant-card-body { 11 | display: flex; 12 | flex-direction: column; 13 | align-items: center; 14 | > div { 15 | margin-bottom: 16px; 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/mind/components/EditorItemPanel/index.tsx: -------------------------------------------------------------------------------- 1 | import FlowItemPanel from './FlowItemPanel'; 2 | import KoniItemPanel from './KoniItemPanel'; 3 | 4 | export { FlowItemPanel, KoniItemPanel }; 5 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/mind/components/EditorMinimap/index.tsx: -------------------------------------------------------------------------------- 1 | import { Card } from 'antd'; 2 | import { Minimap } from 'gg-editor'; 3 | import React from 'react'; 4 | 5 | const EditorMinimap = () => ( 6 | 7 | 8 | 9 | ); 10 | 11 | export default EditorMinimap; 12 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/mind/components/EditorToolbar/KoniToolbar.tsx: -------------------------------------------------------------------------------- 1 | import FlowToolbar from './FlowToolbar'; 2 | 3 | export default FlowToolbar; 4 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/mind/components/EditorToolbar/ToolbarButton.tsx: -------------------------------------------------------------------------------- 1 | import { Command } from 'gg-editor'; 2 | import React from 'react'; 3 | import { Tooltip } from 'antd'; 4 | import IconFont from '../../common/IconFont'; 5 | import styles from './index.less'; 6 | 7 | const upperFirst = (str: string) => 8 | str.toLowerCase().replace(/( |^)[a-z]/g, (l: string) => l.toUpperCase()); 9 | 10 | interface ToolbarButtonProps { 11 | command: string; 12 | icon?: string; 13 | text?: string; 14 | } 15 | const ToolbarButton: React.FC = (props) => { 16 | const { command, icon, text } = props; 17 | 18 | return ( 19 | 20 | 25 | 26 | 27 | 28 | ); 29 | }; 30 | 31 | export default ToolbarButton; 32 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/mind/components/EditorToolbar/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .toolbar { 4 | display: flex; 5 | align-items: center; 6 | 7 | :global { 8 | .command .anticon { 9 | display: inline-block; 10 | width: 27px; 11 | height: 27px; 12 | margin: 0 6px; 13 | padding-top: 6px; 14 | text-align: center; 15 | cursor: pointer; 16 | 17 | &:hover { 18 | border: 1px solid @item-active-bg; 19 | } 20 | } 21 | 22 | .disable .anticon { 23 | color: @text-color-secondary; 24 | cursor: auto; 25 | 26 | &:hover { 27 | border: 1px solid @border-color-base; 28 | } 29 | } 30 | } 31 | } 32 | 33 | .tooltip { 34 | :global { 35 | .ant-tooltip-inner { 36 | font-size: 12px; 37 | border-radius: 0; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/mind/components/EditorToolbar/index.tsx: -------------------------------------------------------------------------------- 1 | import FlowToolbar from './FlowToolbar'; 2 | import KoniToolbar from './KoniToolbar'; 3 | import MindToolbar from './MindToolbar'; 4 | 5 | export { FlowToolbar, MindToolbar, KoniToolbar }; 6 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/mind/locales/en-US.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'editorandmind.description': 3 | 'The brain map is an effective graphical thinking tool for expressing divergent thinking. It is simple but effective and is a practical thinking tool', 4 | }; 5 | -------------------------------------------------------------------------------- /7.4admin/src/pages/editor/mind/locales/zh-CN.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'editorandmind.description': 3 | '脑图是表达发散性思维的有效图形思维工具 ,它简单却又很有效,是一种实用性的思维工具', 4 | }; 5 | -------------------------------------------------------------------------------- /7.4admin/src/pages/exception/403/index.tsx: -------------------------------------------------------------------------------- 1 | import { Link } from 'umi'; 2 | import { Result, Button } from 'antd'; 3 | import React from 'react'; 4 | 5 | export default () => ( 6 | 15 | 16 | 17 | } 18 | /> 19 | ); 20 | -------------------------------------------------------------------------------- /7.4admin/src/pages/exception/404/index.tsx: -------------------------------------------------------------------------------- 1 | import { Link } from 'umi'; 2 | import { Result, Button } from 'antd'; 3 | import React from 'react'; 4 | 5 | export default () => ( 6 | 15 | 16 | 17 | } 18 | /> 19 | ); 20 | -------------------------------------------------------------------------------- /7.4admin/src/pages/exception/500/index.tsx: -------------------------------------------------------------------------------- 1 | import { Link } from 'umi'; 2 | import { Result, Button } from 'antd'; 3 | import React from 'react'; 4 | 5 | export default () => ( 6 | 15 | 16 | 17 | } 18 | /> 19 | ); 20 | -------------------------------------------------------------------------------- /7.4admin/src/pages/exception/500/locales/en-US.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'exceptionand500.exception.back': 'Back to home', 3 | 'exceptionand500.description.500': 'Sorry, the server is reporting an error.', 4 | }; 5 | -------------------------------------------------------------------------------- /7.4admin/src/pages/exception/500/locales/pt-BR.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'exceptionand500.exception.back': 'Voltar para Início', 3 | 'exceptionand500.description.500': 'Desculpe, o servidor está reportando um erro.', 4 | }; 5 | -------------------------------------------------------------------------------- /7.4admin/src/pages/exception/500/locales/zh-CN.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'exceptionand500.exception.back': '返回首页', 3 | 'exceptionand500.description.500': '抱歉,服务器出错了。', 4 | }; 5 | -------------------------------------------------------------------------------- /7.4admin/src/pages/exception/500/locales/zh-TW.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'exceptionand500.exception.back': '返回首頁', 3 | 'exceptionand500.description.500': '抱歉,服務器出錯了。', 4 | }; 5 | -------------------------------------------------------------------------------- /7.4admin/src/pages/form/advanced-form/_mock.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line import/no-extraneous-dependencies 2 | import { Request, Response } from 'express'; 3 | 4 | export default { 5 | 'POST /api/forms': (_: Request, res: Response) => { 6 | res.send({ message: 'Ok' }); 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /7.4admin/src/pages/form/advanced-form/model.ts: -------------------------------------------------------------------------------- 1 | import { Effect } from 'umi'; 2 | import { message } from 'antd'; 3 | import { fakeSubmitForm } from './service'; 4 | 5 | export interface ModelType { 6 | namespace: string; 7 | state: {}; 8 | effects: { 9 | submitAdvancedForm: Effect; 10 | }; 11 | } 12 | 13 | const Model: ModelType = { 14 | namespace: 'formAndadvancedForm', 15 | 16 | state: {}, 17 | 18 | effects: { 19 | *submitAdvancedForm({ payload }, { call }) { 20 | yield call(fakeSubmitForm, payload); 21 | message.success('提交成功'); 22 | }, 23 | }, 24 | }; 25 | 26 | export default Model; 27 | -------------------------------------------------------------------------------- /7.4admin/src/pages/form/advanced-form/service.ts: -------------------------------------------------------------------------------- 1 | import request from 'umi-request'; 2 | 3 | export async function fakeSubmitForm(params: any) { 4 | return request('/api/forms', { 5 | method: 'POST', 6 | data: params, 7 | }); 8 | } 9 | -------------------------------------------------------------------------------- /7.4admin/src/pages/form/basic-form/_mock.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line import/no-extraneous-dependencies 2 | import { Request, Response } from 'express'; 3 | 4 | export default { 5 | 'POST /api/forms': (_: Request, res: Response) => { 6 | res.send({ message: 'Ok' }); 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /7.4admin/src/pages/form/basic-form/model.ts: -------------------------------------------------------------------------------- 1 | import { Effect } from 'umi'; 2 | import { message } from 'antd'; 3 | import { fakeSubmitForm } from './service'; 4 | 5 | export interface ModelType { 6 | namespace: string; 7 | state: {}; 8 | effects: { 9 | submitRegularForm: Effect; 10 | }; 11 | } 12 | const Model: ModelType = { 13 | namespace: 'formAndbasicForm', 14 | 15 | state: {}, 16 | 17 | effects: { 18 | *submitRegularForm({ payload }, { call }) { 19 | yield call(fakeSubmitForm, payload); 20 | message.success('提交成功'); 21 | }, 22 | }, 23 | }; 24 | 25 | export default Model; 26 | -------------------------------------------------------------------------------- /7.4admin/src/pages/form/basic-form/service.ts: -------------------------------------------------------------------------------- 1 | import request from 'umi-request'; 2 | 3 | export async function fakeSubmitForm(params: any) { 4 | return request('/api/forms', { 5 | method: 'POST', 6 | data: params, 7 | }); 8 | } 9 | -------------------------------------------------------------------------------- /7.4admin/src/pages/form/step-form/_mock.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line import/no-extraneous-dependencies 2 | import { Request, Response } from 'express'; 3 | 4 | export default { 5 | 'POST /api/forms': (_: Request, res: Response) => { 6 | res.send({ message: 'Ok' }); 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /7.4admin/src/pages/form/step-form/service.ts: -------------------------------------------------------------------------------- 1 | import request from 'umi-request'; 2 | 3 | export async function fakeSubmitForm(params: any) { 4 | return request('/api/forms', { 5 | method: 'POST', 6 | data: params, 7 | }); 8 | } 9 | -------------------------------------------------------------------------------- /7.4admin/src/pages/list/basic-list/data.d.ts: -------------------------------------------------------------------------------- 1 | export interface Member { 2 | avatar: string; 3 | name: string; 4 | id: string; 5 | } 6 | 7 | export interface BasicListItemDataType { 8 | id: string; 9 | owner: string; 10 | title: string; 11 | avatar: string; 12 | cover: string; 13 | status: 'normal' | 'exception' | 'active' | 'success'; 14 | percent: number; 15 | logo: string; 16 | href: string; 17 | body?: any; 18 | updatedAt: number; 19 | createdAt: number; 20 | subDescription: string; 21 | description: string; 22 | activeUser: number; 23 | newUser: number; 24 | star: number; 25 | like: number; 26 | message: number; 27 | content: string; 28 | members: Member[]; 29 | } 30 | -------------------------------------------------------------------------------- /7.4admin/src/pages/list/card-list/data.d.ts: -------------------------------------------------------------------------------- 1 | export interface Member { 2 | avatar: string; 3 | name: string; 4 | id: string; 5 | } 6 | 7 | export interface CardListItemDataType { 8 | id: string; 9 | owner: string; 10 | title: string; 11 | avatar: string; 12 | cover: string; 13 | status: 'normal' | 'exception' | 'active' | 'success'; 14 | percent: number; 15 | logo: string; 16 | href: string; 17 | body?: any; 18 | updatedAt: number; 19 | createdAt: number; 20 | subDescription: string; 21 | description: string; 22 | activeUser: number; 23 | newUser: number; 24 | star: number; 25 | like: number; 26 | message: number; 27 | content: string; 28 | members: Member[]; 29 | } 30 | -------------------------------------------------------------------------------- /7.4admin/src/pages/list/card-list/service.ts: -------------------------------------------------------------------------------- 1 | import request from 'umi-request'; 2 | 3 | export async function queryFakeList(params: { count: number }) { 4 | return request('/api/fake_list', { 5 | params, 6 | }); 7 | } 8 | -------------------------------------------------------------------------------- /7.4admin/src/pages/list/search/applications/components/TagSelect/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .tagSelect { 4 | position: relative; 5 | max-height: 32px; 6 | margin-left: -8px; 7 | overflow: hidden; 8 | line-height: 32px; 9 | transition: all 0.3s; 10 | user-select: none; 11 | :global { 12 | .ant-tag { 13 | margin-right: 24px; 14 | padding: 0 8px; 15 | font-size: @font-size-base; 16 | } 17 | } 18 | &.expanded { 19 | max-height: 200px; 20 | transition: all 0.3s; 21 | } 22 | .trigger { 23 | position: absolute; 24 | top: 0; 25 | right: 0; 26 | 27 | span.anticon { 28 | font-size: 12px; 29 | } 30 | } 31 | &.hasExpandTag { 32 | padding-right: 50px; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /7.4admin/src/pages/list/search/applications/data.d.ts: -------------------------------------------------------------------------------- 1 | export interface Member { 2 | avatar: string; 3 | name: string; 4 | id: string; 5 | } 6 | 7 | export interface ListItemDataType { 8 | id: string; 9 | owner: string; 10 | title: string; 11 | avatar: string; 12 | cover: string; 13 | status: 'normal' | 'exception' | 'active' | 'success'; 14 | percent: number; 15 | logo: string; 16 | href: string; 17 | body?: any; 18 | updatedAt: number; 19 | createdAt: number; 20 | subDescription: string; 21 | description: string; 22 | activeUser: number; 23 | newUser: number; 24 | star: number; 25 | like: number; 26 | message: number; 27 | content: string; 28 | members: Member[]; 29 | } 30 | -------------------------------------------------------------------------------- /7.4admin/src/pages/list/search/applications/service.ts: -------------------------------------------------------------------------------- 1 | import request from 'umi-request'; 2 | import { ListItemDataType } from './data.d'; 3 | 4 | export async function queryFakeList(params: ListItemDataType) { 5 | return request('/api/fake_list', { 6 | params, 7 | }); 8 | } 9 | -------------------------------------------------------------------------------- /7.4admin/src/pages/list/search/articles/components/ArticleListContent/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .listContent { 4 | .description { 5 | max-width: 720px; 6 | line-height: 22px; 7 | } 8 | .extra { 9 | margin-top: 16px; 10 | color: @text-color-secondary; 11 | line-height: 22px; 12 | & > :global(.ant-avatar) { 13 | position: relative; 14 | top: 1px; 15 | width: 20px; 16 | height: 20px; 17 | margin-right: 8px; 18 | vertical-align: top; 19 | } 20 | & > em { 21 | margin-left: 16px; 22 | color: @disabled-color; 23 | font-style: normal; 24 | } 25 | } 26 | } 27 | 28 | @media screen and (max-width: @screen-xs) { 29 | .listContent { 30 | .extra { 31 | & > em { 32 | display: block; 33 | margin-top: 8px; 34 | margin-left: 0; 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /7.4admin/src/pages/list/search/articles/components/ArticleListContent/index.tsx: -------------------------------------------------------------------------------- 1 | import { Avatar } from 'antd'; 2 | import React from 'react'; 3 | import moment from 'moment'; 4 | import styles from './index.less'; 5 | 6 | interface ArticleListContentProps { 7 | data: { 8 | content: React.ReactNode; 9 | updatedAt: number; 10 | avatar: string; 11 | owner: string; 12 | href: string; 13 | }; 14 | } 15 | 16 | const ArticleListContent: React.FC = ({ 17 | data: { content, updatedAt, avatar, owner, href }, 18 | }) => ( 19 |
20 |
{content}
21 |
22 | 23 | {owner} 发布在 {href} 24 | {moment(updatedAt).format('YYYY-MM-DD HH:mm')} 25 |
26 |
27 | ); 28 | 29 | export default ArticleListContent; 30 | -------------------------------------------------------------------------------- /7.4admin/src/pages/list/search/articles/components/TagSelect/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .tagSelect { 4 | position: relative; 5 | max-height: 32px; 6 | margin-left: -8px; 7 | overflow: hidden; 8 | line-height: 32px; 9 | transition: all 0.3s; 10 | user-select: none; 11 | :global { 12 | .ant-tag { 13 | margin-right: 24px; 14 | padding: 0 8px; 15 | font-size: @font-size-base; 16 | } 17 | } 18 | &.expanded { 19 | max-height: 200px; 20 | transition: all 0.3s; 21 | } 22 | .trigger { 23 | position: absolute; 24 | top: 0; 25 | right: 0; 26 | span.anticon { 27 | font-size: 12px; 28 | } 29 | } 30 | &.hasExpandTag { 31 | padding-right: 50px; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /7.4admin/src/pages/list/search/articles/data.d.ts: -------------------------------------------------------------------------------- 1 | export interface Member { 2 | avatar: string; 3 | name: string; 4 | id: string; 5 | } 6 | 7 | export interface ListItemDataType { 8 | id: string; 9 | owner: string; 10 | title: string; 11 | avatar: string; 12 | cover: string; 13 | status: 'normal' | 'exception' | 'active' | 'success'; 14 | percent: number; 15 | logo: string; 16 | href: string; 17 | body?: any; 18 | updatedAt: number; 19 | createdAt: number; 20 | subDescription: string; 21 | description: string; 22 | activeUser: number; 23 | newUser: number; 24 | star: number; 25 | like: number; 26 | message: number; 27 | content: string; 28 | members: Member[]; 29 | } 30 | -------------------------------------------------------------------------------- /7.4admin/src/pages/list/search/articles/service.ts: -------------------------------------------------------------------------------- 1 | import request from 'umi-request'; 2 | import { ListItemDataType } from './data.d'; 3 | 4 | export async function queryFakeList(params: ListItemDataType) { 5 | return request('/api/fake_list', { 6 | params, 7 | }); 8 | } 9 | -------------------------------------------------------------------------------- /7.4admin/src/pages/list/search/articles/style.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | a.listItemMetaTitle { 4 | color: @heading-color; 5 | } 6 | .listItemExtra { 7 | width: 272px; 8 | height: 1px; 9 | } 10 | .selfTrigger { 11 | margin-left: 12px; 12 | } 13 | 14 | @media screen and (max-width: @screen-xs) { 15 | .selfTrigger { 16 | display: block; 17 | margin-left: 0; 18 | } 19 | } 20 | @media screen and (max-width: @screen-md) { 21 | .selfTrigger { 22 | display: block; 23 | margin-left: 0; 24 | } 25 | } 26 | @media screen and (max-width: @screen-lg) { 27 | .listItemExtra { 28 | width: 0; 29 | height: 1px; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /7.4admin/src/pages/list/search/projects/components/TagSelect/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .tagSelect { 4 | position: relative; 5 | max-height: 32px; 6 | margin-left: -8px; 7 | overflow: hidden; 8 | line-height: 32px; 9 | transition: all 0.3s; 10 | user-select: none; 11 | :global { 12 | .ant-tag { 13 | margin-right: 24px; 14 | padding: 0 8px; 15 | font-size: @font-size-base; 16 | } 17 | } 18 | &.expanded { 19 | max-height: 200px; 20 | transition: all 0.3s; 21 | } 22 | .trigger { 23 | position: absolute; 24 | top: 0; 25 | right: 0; 26 | span.anticon { 27 | font-size: 12px; 28 | } 29 | } 30 | &.hasExpandTag { 31 | padding-right: 50px; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /7.4admin/src/pages/list/search/projects/data.d.ts: -------------------------------------------------------------------------------- 1 | export interface Member { 2 | avatar: string; 3 | name: string; 4 | id: string; 5 | } 6 | 7 | export interface ListItemDataType { 8 | id: string; 9 | owner: string; 10 | title: string; 11 | avatar: string; 12 | cover: string; 13 | status: 'normal' | 'exception' | 'active' | 'success'; 14 | percent: number; 15 | logo: string; 16 | href: string; 17 | body?: any; 18 | updatedAt: number; 19 | createdAt: number; 20 | subDescription: string; 21 | description: string; 22 | activeUser: number; 23 | newUser: number; 24 | star: number; 25 | like: number; 26 | message: number; 27 | content: string; 28 | members: Member[]; 29 | } 30 | -------------------------------------------------------------------------------- /7.4admin/src/pages/list/search/projects/service.ts: -------------------------------------------------------------------------------- 1 | import request from 'umi-request'; 2 | 3 | export async function queryFakeList(params: { count: number }) { 4 | return request('/api/fake_list', { 5 | params, 6 | }); 7 | } 8 | -------------------------------------------------------------------------------- /7.4admin/src/pages/list/table-list/components/CreateForm.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Modal } from 'antd'; 3 | 4 | interface CreateFormProps { 5 | modalVisible: boolean; 6 | onCancel: () => void; 7 | } 8 | 9 | const CreateForm: React.FC = (props) => { 10 | const { modalVisible, onCancel } = props; 11 | 12 | return ( 13 | onCancel()} 18 | footer={null} 19 | > 20 | {props.children} 21 | 22 | ); 23 | }; 24 | 25 | export default CreateForm; 26 | -------------------------------------------------------------------------------- /7.4admin/src/pages/list/table-list/data.d.ts: -------------------------------------------------------------------------------- 1 | export interface TableListItem { 2 | key: number; 3 | disabled?: boolean; 4 | href: string; 5 | avatar: string; 6 | name: string; 7 | owner: string; 8 | desc: string; 9 | callNo: number; 10 | status: string; 11 | updatedAt: Date; 12 | createdAt: Date; 13 | progress: number; 14 | } 15 | 16 | export interface TableListPagination { 17 | total: number; 18 | pageSize: number; 19 | current: number; 20 | } 21 | 22 | export interface TableListData { 23 | list: TableListItem[]; 24 | pagination: Partial; 25 | } 26 | 27 | export interface TableListParams { 28 | status?: string; 29 | name?: string; 30 | desc?: string; 31 | key?: number; 32 | pageSize?: number; 33 | currentPage?: number; 34 | filter?: { [key: string]: any[] }; 35 | sorter?: { [key: string]: any }; 36 | } 37 | -------------------------------------------------------------------------------- /7.4admin/src/pages/list/table-list/service.ts: -------------------------------------------------------------------------------- 1 | import request from 'umi-request'; 2 | import { TableListParams } from './data.d'; 3 | 4 | export async function queryRule(params?: TableListParams) { 5 | return request('/api/rule', { 6 | params, 7 | }); 8 | } 9 | 10 | export async function removeRule(params: { key: number[] }) { 11 | return request('/api/rule', { 12 | method: 'POST', 13 | data: { 14 | ...params, 15 | method: 'delete', 16 | }, 17 | }); 18 | } 19 | 20 | export async function addRule(params: TableListParams) { 21 | return request('/api/rule', { 22 | method: 'POST', 23 | data: { 24 | ...params, 25 | method: 'post', 26 | }, 27 | }); 28 | } 29 | 30 | export async function updateRule(params: TableListParams) { 31 | return request('/api/rule', { 32 | method: 'POST', 33 | data: { 34 | ...params, 35 | method: 'update', 36 | }, 37 | }); 38 | } 39 | -------------------------------------------------------------------------------- /7.4admin/src/pages/profile/advanced/data.d.ts: -------------------------------------------------------------------------------- 1 | export interface AdvancedOperation1 { 2 | key: string; 3 | type: string; 4 | name: string; 5 | status: string; 6 | updatedAt: string; 7 | memo: string; 8 | } 9 | 10 | export interface AdvancedOperation2 { 11 | key: string; 12 | type: string; 13 | name: string; 14 | status: string; 15 | updatedAt: string; 16 | memo: string; 17 | } 18 | 19 | export interface AdvancedOperation3 { 20 | key: string; 21 | type: string; 22 | name: string; 23 | status: string; 24 | updatedAt: string; 25 | memo: string; 26 | } 27 | 28 | export interface AdvancedProfileData { 29 | advancedOperation1: AdvancedOperation1[]; 30 | advancedOperation2: AdvancedOperation2[]; 31 | advancedOperation3: AdvancedOperation3[]; 32 | } 33 | -------------------------------------------------------------------------------- /7.4admin/src/pages/profile/advanced/service.ts: -------------------------------------------------------------------------------- 1 | import request from 'umi-request'; 2 | 3 | export async function queryAdvancedProfile() { 4 | return request('/api/profile/advanced'); 5 | } 6 | -------------------------------------------------------------------------------- /7.4admin/src/pages/profile/basic/data.d.ts: -------------------------------------------------------------------------------- 1 | export interface BasicGood { 2 | id: string; 3 | name?: string; 4 | barcode?: string; 5 | price?: string; 6 | num?: string | number; 7 | amount?: string | number; 8 | } 9 | 10 | export interface BasicProgress { 11 | key: string; 12 | time: string; 13 | rate: string; 14 | status: string; 15 | operator: string; 16 | cost: string; 17 | } 18 | 19 | export interface BasicProfileDataType { 20 | basicGoods: BasicGood[]; 21 | basicProgress: BasicProgress[]; 22 | } 23 | -------------------------------------------------------------------------------- /7.4admin/src/pages/profile/basic/model.ts: -------------------------------------------------------------------------------- 1 | import { Effect, Reducer } from 'umi'; 2 | 3 | import { BasicGood } from './data.d'; 4 | import { queryBasicProfile } from './service'; 5 | 6 | export interface StateType { 7 | basicGoods: BasicGood[]; 8 | } 9 | 10 | export interface ModelType { 11 | namespace: string; 12 | state: StateType; 13 | effects: { 14 | fetchBasic: Effect; 15 | }; 16 | reducers: { 17 | show: Reducer; 18 | }; 19 | } 20 | 21 | const Model: ModelType = { 22 | namespace: 'profileAndbasic', 23 | 24 | state: { 25 | basicGoods: [], 26 | }, 27 | 28 | effects: { 29 | *fetchBasic(_, { call, put }) { 30 | const response = yield call(queryBasicProfile); 31 | yield put({ 32 | type: 'show', 33 | payload: response, 34 | }); 35 | }, 36 | }, 37 | 38 | reducers: { 39 | show(state, { payload }) { 40 | return { 41 | ...state, 42 | ...payload, 43 | }; 44 | }, 45 | }, 46 | }; 47 | 48 | export default Model; 49 | -------------------------------------------------------------------------------- /7.4admin/src/pages/profile/basic/service.ts: -------------------------------------------------------------------------------- 1 | import request from 'umi-request'; 2 | 3 | export async function queryBasicProfile() { 4 | return request('/api/profile/basic'); 5 | } 6 | -------------------------------------------------------------------------------- /7.4admin/src/pages/profile/basic/style.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .title { 4 | margin-bottom: 16px; 5 | color: @heading-color; 6 | font-weight: 500; 7 | font-size: 16px; 8 | } 9 | -------------------------------------------------------------------------------- /7.4admin/src/pages/result/fail/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .error_icon { 4 | color: @highlight-color; 5 | } 6 | .title { 7 | margin-bottom: 16px; 8 | color: @heading-color; 9 | font-weight: 500; 10 | font-size: 16px; 11 | } 12 | -------------------------------------------------------------------------------- /7.4admin/src/pages/result/fail/locales/en-US.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'resultandfail.error.title': 'Submission Failed', 3 | 'resultandfail.error.description': 4 | 'Please check and modify the following information before resubmitting.', 5 | 'resultandfail.error.hint-title': 'The content you submitted has the following error:', 6 | 'resultandfail.error.hint-text1': 'Your account has been frozen', 7 | 'resultandfail.error.hint-btn1': 'Thaw immediately', 8 | 'resultandfail.error.hint-text2': 'Your account is not yet eligible to apply', 9 | 'resultandfail.error.hint-btn2': 'Upgrade immediately', 10 | 'resultandfail.error.btn-text': 'Return to modify', 11 | }; 12 | -------------------------------------------------------------------------------- /7.4admin/src/pages/result/fail/locales/zh-CN.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'resultandfail.error.title': '提交失败', 3 | 'resultandfail.error.description': '请核对并修改以下信息后,再重新提交。', 4 | 'resultandfail.error.hint-title': '您提交的内容有如下错误:', 5 | 'resultandfail.error.hint-text1': '您的账户已被冻结', 6 | 'resultandfail.error.hint-btn1': '立即解冻', 7 | 'resultandfail.error.hint-text2': '您的账户还不具备申请资格', 8 | 'resultandfail.error.hint-btn2': '立即升级', 9 | 'resultandfail.error.btn-text': '返回修改', 10 | }; 11 | -------------------------------------------------------------------------------- /7.4admin/src/pages/result/fail/locales/zh-TW.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'resultandfail.error.title': '提交失敗', 3 | 'resultandfail.error.description': '請核對並修改以下信息後,再重新提交。', 4 | 'resultandfail.error.hint-title': '您提交的內容有如下錯誤:', 5 | 'resultandfail.error.hint-text1': '您的賬戶已被凍結', 6 | 'resultandfail.error.hint-btn1': '立即解凍', 7 | 'resultandfail.error.hint-text2': '您的賬戶還不具備申請資格', 8 | 'resultandfail.error.hint-btn2': '立即升級', 9 | 'resultandfail.error.btn-text': '返回修改', 10 | }; 11 | -------------------------------------------------------------------------------- /7.4admin/src/pages/result/success/index.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .title { 4 | position: relative; 5 | color: @text-color; 6 | font-size: 12px; 7 | text-align: center; 8 | } 9 | 10 | .head-title { 11 | margin-bottom: 20px; 12 | color: @heading-color; 13 | font-weight: 500px; 14 | font-size: 16px; 15 | } 16 | -------------------------------------------------------------------------------- /7.4admin/src/pages/result/success/locales/zh-CN.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'resultandsuccess.success.title': '提交成功', 3 | 'resultandsuccess.success.description': 4 | '提交结果页用于反馈一系列操作任务的处理结果, 如果仅是简单操作,使用 Message 全局提示反馈即可。 本文字区域可以展示简单的补充说明,如果有类似展示 “单据”的需求,下面这个灰色区域可以呈现比较复杂的内容。', 5 | 'resultandsuccess.success.operate-title': '项目名称', 6 | 'resultandsuccess.success.operate-id': '项目 ID', 7 | 'resultandsuccess.success.principal': '负责人', 8 | 'resultandsuccess.success.operate-time': '生效时间', 9 | 'resultandsuccess.success.step1-title': '创建项目', 10 | 'resultandsuccess.success.step1-operator': '曲丽丽', 11 | 'resultandsuccess.success.step2-title': '部门初审', 12 | 'resultandsuccess.success.step2-operator': '周毛毛', 13 | 'resultandsuccess.success.step2-extra': '催一下', 14 | 'resultandsuccess.success.step3-title': '财务复核', 15 | 'resultandsuccess.success.step4-title': '完成', 16 | 'resultandsuccess.success.btn-return': '返回列表', 17 | 'resultandsuccess.success.btn-project': '查看项目', 18 | 'resultandsuccess.success.btn-print': '打印', 19 | }; 20 | -------------------------------------------------------------------------------- /7.4admin/src/pages/result/success/locales/zh-TW.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'resultandsuccess.success.title': '提交成功', 3 | 'resultandsuccess.success.description': 4 | '提交結果頁用於反饋壹系列操作任務的處理結果, 如果僅是簡單操作,使用 Message 全局提示反饋即可。 本文字區域可以展示簡單的補充說明,如果有類似展示 “單據”的需求,下面這個灰色區域可以呈現比較復雜的內容。', 5 | 'resultandsuccess.success.operate-title': '項目名稱', 6 | 'resultandsuccess.success.operate-id': '項目 ID', 7 | 'resultandsuccess.success.principal': '負責人', 8 | 'resultandsuccess.success.operate-time': '生效時間', 9 | 'resultandsuccess.success.step1-title': '創建項目', 10 | 'resultandsuccess.success.step1-operator': '曲麗麗', 11 | 'resultandsuccess.success.step2-title': '部門初審', 12 | 'resultandsuccess.success.step2-operator': '周毛毛', 13 | 'resultandsuccess.success.step2-extra': '催壹下', 14 | 'resultandsuccess.success.step3-title': '財務復核', 15 | 'resultandsuccess.success.step4-title': '完成', 16 | 'resultandsuccess.success.btn-return': '返回列表', 17 | 'resultandsuccess.success.btn-project': '查看項目', 18 | 'resultandsuccess.success.btn-print': '打印', 19 | }; 20 | -------------------------------------------------------------------------------- /7.4admin/src/services/login.ts: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | 3 | export type LoginParamsType = { 4 | userName: string; 5 | password: string; 6 | mobile: string; 7 | captcha: string; 8 | }; 9 | 10 | export async function fakeAccountLogin(params: LoginParamsType) { 11 | return request('/api/login/account', { 12 | method: 'POST', 13 | data: params, 14 | }); 15 | } 16 | 17 | export async function getFakeCaptcha(mobile: string) { 18 | return request(`/api/login/captcha?mobile=${mobile}`); 19 | } 20 | -------------------------------------------------------------------------------- /7.4admin/src/services/user.ts: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | 3 | export async function query(): Promise { 4 | return request('/api/users'); 5 | } 6 | 7 | export async function queryCurrent(): Promise { 8 | return request('/api/currentUser'); 9 | } 10 | 11 | export async function queryNotices(): Promise { 12 | return request('/api/notices'); 13 | } 14 | -------------------------------------------------------------------------------- /7.4admin/src/utils/Authorized.ts: -------------------------------------------------------------------------------- 1 | import RenderAuthorize from '@/components/Authorized'; 2 | import { getAuthority } from './authority'; 3 | /* eslint-disable eslint-comments/disable-enable-pair */ 4 | /* eslint-disable import/no-mutable-exports */ 5 | let Authorized = RenderAuthorize(getAuthority()); 6 | 7 | // Reload the rights component 8 | const reloadAuthorized = (): void => { 9 | Authorized = RenderAuthorize(getAuthority()); 10 | }; 11 | 12 | /** 13 | * hard code 14 | * block need it。 15 | */ 16 | window.reloadAuthorized = reloadAuthorized; 17 | 18 | export { reloadAuthorized }; 19 | export default Authorized; 20 | -------------------------------------------------------------------------------- /7.4admin/src/utils/utils.less: -------------------------------------------------------------------------------- 1 | // mixins for clearfix 2 | // ------------------------ 3 | .clearfix() { 4 | zoom: 1; 5 | &::before, 6 | &::after { 7 | display: table; 8 | content: ' '; 9 | } 10 | &::after { 11 | clear: both; 12 | height: 0; 13 | font-size: 0; 14 | visibility: hidden; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /7.4admin/src/utils/utils.ts: -------------------------------------------------------------------------------- 1 | import { parse } from 'querystring'; 2 | 3 | /* eslint no-useless-escape:0 import/prefer-default-export:0 */ 4 | const reg = /(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/; 5 | 6 | export const isUrl = (path: string): boolean => reg.test(path); 7 | 8 | export const isAntDesignPro = (): boolean => { 9 | if (ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION === 'site') { 10 | return true; 11 | } 12 | return window.location.hostname === 'preview.pro.ant.design'; 13 | }; 14 | 15 | // 给官方演示站点用,用于关闭真实开发环境不需要使用的特性 16 | export const isAntDesignProOrDev = (): boolean => { 17 | const { NODE_ENV } = process.env; 18 | if (NODE_ENV === 'development') { 19 | return true; 20 | } 21 | return isAntDesignPro(); 22 | }; 23 | 24 | export const getPageQuery = () => parse(window.location.href.split('?')[1]); 25 | -------------------------------------------------------------------------------- /other/demo01.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | DOM 渲染是否异步 7 | 8 | 9 | 10 |
默认文本
11 | 26 | 27 | --------------------------------------------------------------------------------