├── .gitignore ├── README.md ├── backend ├── Makefile ├── admin.db ├── config.json ├── go.mod ├── go.sum ├── main.go ├── main_test.go └── uploads │ └── a └── frontend ├── .gitignore ├── Makefile ├── admin.antdesign.db ├── admin.db ├── admin.element.db ├── config.json ├── src ├── adminlte │ ├── .babelrc │ ├── build │ │ ├── build.js │ │ ├── check-versions.js │ │ ├── dev-client.js │ │ ├── dev-server.js │ │ ├── utils.js │ │ ├── vue-loader.conf.js │ │ ├── webpack.base.conf.js │ │ ├── webpack.dev.conf.js │ │ ├── webpack.prod.conf.js │ │ └── webpack.test.conf.js │ ├── config │ │ ├── dev.env.js │ │ ├── index.js │ │ ├── prod.env.js │ │ └── test.env.js │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── App.vue │ │ ├── ContentWrap.vue │ │ ├── assets │ │ │ └── logo.png │ │ ├── components │ │ │ ├── Hello.vue │ │ │ ├── Modal.vue │ │ │ ├── Sample.vue │ │ │ ├── VAAccordion.vue │ │ │ ├── VAAlert.vue │ │ │ ├── VAButton.vue │ │ │ ├── VACallout.vue │ │ │ ├── VACarousel.vue │ │ │ ├── VAChart.vue │ │ │ ├── VACheckBox.vue │ │ │ ├── VAColorPaletteSet.vue │ │ │ ├── VACustomTab.vue │ │ │ ├── VAFormGroup.vue │ │ │ ├── VAInput.vue │ │ │ ├── VAInputGroup.vue │ │ │ ├── VAProgressBar.vue │ │ │ ├── VARadio.vue │ │ │ ├── VASelect.vue │ │ │ ├── VASlideItem.vue │ │ │ ├── VAText.vue │ │ │ ├── VATextarea.vue │ │ │ └── VATextareaGroup.vue │ │ ├── examples │ │ │ ├── APIExample.vue │ │ │ ├── AlertExample.vue │ │ │ ├── ChartExample.vue │ │ │ ├── Dashboard.v1.vue │ │ │ ├── Dashboard.v2.vue │ │ │ ├── InfoBoxExample.vue │ │ │ ├── ModalExample.vue │ │ │ └── WidgetsExample.vue │ │ ├── grid │ │ │ ├── Column.vue │ │ │ └── Row.vue │ │ ├── lib │ │ │ ├── css.js │ │ │ ├── eventBus.js │ │ │ ├── global.js │ │ │ ├── script.js │ │ │ └── slideMenuItems.js │ │ ├── main.js │ │ ├── pages │ │ │ ├── forms │ │ │ │ ├── AdvancedElements.vue │ │ │ │ └── GeneralElements.vue │ │ │ └── ui-elements │ │ │ │ ├── Buttons.vue │ │ │ │ ├── General.vue │ │ │ │ ├── Icons.vue │ │ │ │ ├── Modals.vue │ │ │ │ ├── Sliders.vue │ │ │ │ └── Timeline.vue │ │ ├── router │ │ │ └── index.js │ │ ├── vuex │ │ │ ├── actions.js │ │ │ ├── api │ │ │ │ ├── index.js │ │ │ │ └── services │ │ │ │ │ ├── index.js │ │ │ │ │ └── products.js │ │ │ ├── getters.js │ │ │ ├── modules │ │ │ │ ├── index.js │ │ │ │ ├── messages.js │ │ │ │ ├── notifications.js │ │ │ │ ├── products.js │ │ │ │ ├── tasks.js │ │ │ │ └── user.js │ │ │ ├── mutation-types.js │ │ │ └── store.js │ │ └── widgets │ │ │ ├── VABox.vue │ │ │ ├── VACalendar.vue │ │ │ ├── VAChatBox.vue │ │ │ ├── VADirectChat.vue │ │ │ ├── VADirectChatContact.vue │ │ │ ├── VADirectChatItem.vue │ │ │ ├── VAInfoBox.vue │ │ │ ├── VAQuickMail.vue │ │ │ ├── VASmallBox.vue │ │ │ ├── VASocialBox.vue │ │ │ ├── VASocialBoxComment.vue │ │ │ ├── VASocialUser.v1.vue │ │ │ ├── VASocialUser.v2.vue │ │ │ ├── VATodoList.vue │ │ │ └── VAUserList.vue │ ├── static │ │ ├── .gitkeep │ │ └── img │ │ │ ├── avatar.png │ │ │ ├── avatar04.png │ │ │ ├── avatar2.png │ │ │ ├── avatar3.png │ │ │ ├── avatar5.png │ │ │ ├── boxed-bg.jpg │ │ │ ├── boxed-bg.png │ │ │ ├── credit │ │ │ ├── american-express.png │ │ │ ├── cirrus.png │ │ │ ├── mastercard.png │ │ │ ├── mestro.png │ │ │ ├── paypal.png │ │ │ ├── paypal2.png │ │ │ └── visa.png │ │ │ ├── default-50x50.gif │ │ │ ├── icons.png │ │ │ ├── photo1.png │ │ │ ├── photo2.png │ │ │ ├── photo3.jpg │ │ │ ├── photo4.jpg │ │ │ ├── user1-128x128.jpg │ │ │ ├── user2-160x160.jpg │ │ │ ├── user3-128x128.jpg │ │ │ ├── user4-128x128.jpg │ │ │ ├── user5-128x128.jpg │ │ │ ├── user6-128x128.jpg │ │ │ ├── user7-128x128.jpg │ │ │ └── user8-128x128.jpg │ └── test │ │ ├── e2e │ │ ├── custom-assertions │ │ │ └── elementCount.js │ │ ├── nightwatch.conf.js │ │ ├── runner.js │ │ └── specs │ │ │ └── test.js │ │ └── unit │ │ ├── .eslintrc │ │ ├── index.js │ │ ├── karma.conf.js │ │ └── specs │ │ └── Hello.spec.js ├── antdesign │ ├── .editorconfig │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .gitignore │ ├── .prettierignore │ ├── .prettierrc.js │ ├── README.md │ ├── config │ │ ├── config.ts │ │ ├── defaultSettings.ts │ │ ├── oneapi.json │ │ ├── proxy.ts │ │ └── routes.ts │ ├── jest.config.ts │ ├── jsconfig.json │ ├── mock │ │ ├── analysis.mock.ts │ │ ├── listTableList.ts │ │ ├── monitor.mock.ts │ │ ├── notices.ts │ │ ├── requestRecord.mock.js │ │ ├── route.ts │ │ ├── user.ts │ │ └── workplace.mock.ts │ ├── package.json │ ├── pnpm-lock.yaml │ ├── public │ │ ├── CNAME │ │ ├── favicon.ico │ │ ├── icons │ │ │ ├── icon-128x128.png │ │ │ ├── icon-192x192.png │ │ │ └── icon-512x512.png │ │ ├── logo.svg │ │ ├── pro_icon.svg │ │ └── scripts │ │ │ └── loading.js │ ├── src │ │ ├── access.ts │ │ ├── app.tsx │ │ ├── components │ │ │ ├── Footer │ │ │ │ └── index.tsx │ │ │ ├── HeaderDropdown │ │ │ │ └── index.tsx │ │ │ ├── RightContent │ │ │ │ ├── AvatarDropdown.tsx │ │ │ │ └── index.tsx │ │ │ └── index.ts │ │ ├── global.less │ │ ├── global.style.ts │ │ ├── global.tsx │ │ ├── locales │ │ │ ├── bn-BD.ts │ │ │ ├── bn-BD │ │ │ │ ├── component.ts │ │ │ │ ├── globalHeader.ts │ │ │ │ ├── menu.ts │ │ │ │ ├── pages.ts │ │ │ │ ├── pwa.ts │ │ │ │ ├── settingDrawer.ts │ │ │ │ └── settings.ts │ │ │ ├── en-US.ts │ │ │ ├── en-US │ │ │ │ ├── component.ts │ │ │ │ ├── globalHeader.ts │ │ │ │ ├── menu.ts │ │ │ │ ├── pages.ts │ │ │ │ ├── pwa.ts │ │ │ │ ├── settingDrawer.ts │ │ │ │ └── settings.ts │ │ │ ├── fa-IR.ts │ │ │ ├── fa-IR │ │ │ │ ├── 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 │ │ │ │ ├── pages.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 │ │ │ │ ├── pages.ts │ │ │ │ ├── pwa.ts │ │ │ │ ├── settingDrawer.ts │ │ │ │ └── settings.ts │ │ ├── manifest.json │ │ ├── pages │ │ │ ├── 404.tsx │ │ │ ├── Admin.tsx │ │ │ ├── Welcome.tsx │ │ │ ├── account │ │ │ │ ├── center │ │ │ │ │ ├── Center.style.ts │ │ │ │ │ ├── _mock.ts │ │ │ │ │ ├── components │ │ │ │ │ │ ├── Applications │ │ │ │ │ │ │ ├── index.style.ts │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── ArticleListContent │ │ │ │ │ │ │ ├── index.style.ts │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── Articles │ │ │ │ │ │ │ ├── index.style.ts │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── AvatarList │ │ │ │ │ │ │ ├── index.style.ts │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ └── Projects │ │ │ │ │ │ │ ├── index.style.ts │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── data.d.ts │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── service.ts │ │ │ │ └── settings │ │ │ │ │ ├── _mock.ts │ │ │ │ │ ├── components │ │ │ │ │ ├── PhoneView.tsx │ │ │ │ │ ├── base.tsx │ │ │ │ │ ├── binding.tsx │ │ │ │ │ ├── index.style.ts │ │ │ │ │ ├── notification.tsx │ │ │ │ │ └── security.tsx │ │ │ │ │ ├── data.d.ts │ │ │ │ │ ├── geographic │ │ │ │ │ ├── city.json │ │ │ │ │ └── province.json │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── service.ts │ │ │ │ │ └── style.style.ts │ │ │ ├── dashboard │ │ │ │ ├── analysis │ │ │ │ │ ├── _mock.ts │ │ │ │ │ ├── components │ │ │ │ │ │ ├── Charts │ │ │ │ │ │ │ ├── ChartCard │ │ │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ │ │ ├── index.style.ts │ │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ │ ├── Field │ │ │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ │ │ ├── index.style.ts │ │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ │ ├── MiniProgress │ │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ │ ├── WaterWave │ │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ │ ├── index.style.ts │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── IntroduceRow.tsx │ │ │ │ │ │ ├── NumberInfo │ │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ │ ├── index.style.ts │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── OfflineData.tsx │ │ │ │ │ │ ├── PageLoading │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── ProportionSales.tsx │ │ │ │ │ │ ├── SalesCard.tsx │ │ │ │ │ │ ├── TopSearch.tsx │ │ │ │ │ │ └── Trend │ │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ │ ├── index.style.ts │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── data.d.ts │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── service.ts │ │ │ │ │ ├── style.less │ │ │ │ │ ├── style.style.ts │ │ │ │ │ └── utils │ │ │ │ │ │ ├── Yuan.tsx │ │ │ │ │ │ └── utils.ts │ │ │ │ ├── monitor │ │ │ │ │ ├── _mock.ts │ │ │ │ │ ├── components │ │ │ │ │ │ ├── ActiveChart │ │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ │ ├── index.style.ts │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── Charts │ │ │ │ │ │ │ ├── WaterWave │ │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ │ └── autoHeight.tsx │ │ │ │ │ │ └── Map │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── data.d.ts │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── service.ts │ │ │ │ │ ├── style.less │ │ │ │ │ └── style.style.ts │ │ │ │ └── workplace │ │ │ │ │ ├── _mock.ts │ │ │ │ │ ├── components │ │ │ │ │ └── EditableLinkGroup │ │ │ │ │ │ ├── index.less │ │ │ │ │ │ ├── index.style.ts │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── data.d.ts │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── service.ts │ │ │ │ │ ├── style.less │ │ │ │ │ └── style.style.ts │ │ │ ├── exception │ │ │ │ ├── 403 │ │ │ │ │ └── index.tsx │ │ │ │ ├── 404 │ │ │ │ │ └── index.tsx │ │ │ │ └── 500 │ │ │ │ │ └── index.tsx │ │ │ ├── form │ │ │ │ ├── advanced-form │ │ │ │ │ ├── _mock.ts │ │ │ │ │ ├── components │ │ │ │ │ │ └── TableForm.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── service.ts │ │ │ │ │ ├── style.less │ │ │ │ │ └── style.style.ts │ │ │ │ ├── basic-form │ │ │ │ │ ├── _mock.ts │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── service.ts │ │ │ │ │ ├── style.less │ │ │ │ │ └── style.style.ts │ │ │ │ └── step-form │ │ │ │ │ ├── _mock.ts │ │ │ │ │ ├── data.d.ts │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── service.ts │ │ │ │ │ ├── style.less │ │ │ │ │ └── style.style.ts │ │ │ ├── list │ │ │ │ ├── basic-list │ │ │ │ │ ├── _mock.ts │ │ │ │ │ ├── components │ │ │ │ │ │ └── OperationModal.tsx │ │ │ │ │ ├── data.d.ts │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── service.ts │ │ │ │ │ ├── style.style.ts │ │ │ │ │ └── utils │ │ │ │ │ │ └── utils.style.ts │ │ │ │ ├── card-list │ │ │ │ │ ├── _mock.ts │ │ │ │ │ ├── data.d.ts │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── service.ts │ │ │ │ │ ├── style.style.ts │ │ │ │ │ └── utils │ │ │ │ │ │ └── utils.style.ts │ │ │ │ ├── mock │ │ │ │ │ └── index.ts │ │ │ │ ├── search │ │ │ │ │ ├── applications │ │ │ │ │ │ ├── _mock.ts │ │ │ │ │ │ ├── components │ │ │ │ │ │ │ ├── StandardFormRow │ │ │ │ │ │ │ │ ├── index.style.ts │ │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ │ └── TagSelect │ │ │ │ │ │ │ │ ├── index.style.ts │ │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── data.d.ts │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ ├── service.ts │ │ │ │ │ │ ├── style.style.ts │ │ │ │ │ │ └── utils │ │ │ │ │ │ │ └── utils.style.ts │ │ │ │ │ ├── articles │ │ │ │ │ │ ├── _mock.ts │ │ │ │ │ │ ├── components │ │ │ │ │ │ │ ├── ArticleListContent │ │ │ │ │ │ │ │ ├── index.style.ts │ │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ │ ├── StandardFormRow │ │ │ │ │ │ │ │ ├── index.style.ts │ │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ │ └── TagSelect │ │ │ │ │ │ │ │ ├── index.style.ts │ │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── data.d.ts │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ ├── service.ts │ │ │ │ │ │ └── style.style.ts │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── projects │ │ │ │ │ │ ├── _mock.ts │ │ │ │ │ │ ├── components │ │ │ │ │ │ ├── AvatarList │ │ │ │ │ │ │ ├── index.style.ts │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── StandardFormRow │ │ │ │ │ │ │ ├── index.style.ts │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ └── TagSelect │ │ │ │ │ │ │ ├── index.style.ts │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── data.d.ts │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ ├── service.ts │ │ │ │ │ │ └── style.style.ts │ │ │ │ └── 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 │ │ │ │ │ ├── service.ts │ │ │ │ │ └── style.style.ts │ │ │ │ └── basic │ │ │ │ │ ├── _mock.ts │ │ │ │ │ ├── data.d.ts │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── service.ts │ │ │ │ │ └── style.style.ts │ │ │ ├── result │ │ │ │ ├── fail │ │ │ │ │ ├── index.style.ts │ │ │ │ │ └── index.tsx │ │ │ │ └── success │ │ │ │ │ ├── index.style.ts │ │ │ │ │ └── index.tsx │ │ │ ├── table-list │ │ │ │ ├── components │ │ │ │ │ ├── CreateForm.tsx │ │ │ │ │ └── UpdateForm.tsx │ │ │ │ └── index.tsx │ │ │ └── user │ │ │ │ ├── login │ │ │ │ ├── index.tsx │ │ │ │ └── login.test.tsx │ │ │ │ ├── register-result │ │ │ │ ├── index.tsx │ │ │ │ └── style.style.ts │ │ │ │ └── register │ │ │ │ ├── _mock.ts │ │ │ │ ├── index.tsx │ │ │ │ ├── service.ts │ │ │ │ └── style.style.ts │ │ ├── requestErrorConfig.ts │ │ ├── service-worker.js │ │ ├── services │ │ │ ├── ant-design-pro │ │ │ │ ├── api.ts │ │ │ │ ├── index.ts │ │ │ │ ├── login.ts │ │ │ │ └── typings.d.ts │ │ │ └── swagger │ │ │ │ ├── index.ts │ │ │ │ ├── pet.ts │ │ │ │ ├── store.ts │ │ │ │ ├── typings.d.ts │ │ │ │ └── user.ts │ │ └── typings.d.ts │ ├── tests │ │ └── setupTests.jsx │ ├── tsconfig.json │ └── types │ │ ├── cache │ │ ├── cache.json │ │ ├── login.cache.json │ │ └── mock │ │ │ ├── login.mock.cache.js │ │ │ └── mock.cache.js │ │ └── index.d.ts └── element │ ├── .editorconfig │ ├── .env.development │ ├── .env.production │ ├── .env.staging │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .gitignore │ ├── .travis.yml │ ├── LICENSE │ ├── README.es.md │ ├── README.ja.md │ ├── README.md │ ├── README.zh-CN.md │ ├── babel.config.js │ ├── build │ └── index.js │ ├── jest.config.js │ ├── jsconfig.json │ ├── mock │ ├── article.js │ ├── index.js │ ├── mock-server.js │ ├── remote-search.js │ ├── role │ │ ├── index.js │ │ └── routes.js │ ├── user.js │ └── utils.js │ ├── package.json │ ├── plop-templates │ ├── component │ │ ├── index.hbs │ │ └── prompt.js │ ├── store │ │ ├── index.hbs │ │ └── prompt.js │ ├── utils.js │ └── view │ │ ├── index.hbs │ │ └── prompt.js │ ├── plopfile.js │ ├── postcss.config.js │ ├── public │ ├── favicon.ico │ └── index.html │ ├── src │ ├── App.vue │ ├── api │ │ ├── article.js │ │ ├── qiniu.js │ │ ├── remote-search.js │ │ ├── role.js │ │ └── user.js │ ├── assets │ │ ├── 401_images │ │ │ └── 401.gif │ │ ├── 404_images │ │ │ ├── 404.png │ │ │ └── 404_cloud.png │ │ └── custom-theme │ │ │ ├── fonts │ │ │ ├── element-icons.ttf │ │ │ └── element-icons.woff │ │ │ └── index.css │ ├── components │ │ ├── BackToTop │ │ │ └── index.vue │ │ ├── Breadcrumb │ │ │ └── index.vue │ │ ├── Charts │ │ │ ├── Keyboard.vue │ │ │ ├── LineMarker.vue │ │ │ ├── MixChart.vue │ │ │ └── mixins │ │ │ │ └── resize.js │ │ ├── DndList │ │ │ └── index.vue │ │ ├── DragSelect │ │ │ └── index.vue │ │ ├── Dropzone │ │ │ └── index.vue │ │ ├── ErrorLog │ │ │ └── index.vue │ │ ├── GithubCorner │ │ │ └── index.vue │ │ ├── Hamburger │ │ │ └── index.vue │ │ ├── HeaderSearch │ │ │ └── index.vue │ │ ├── ImageCropper │ │ │ ├── index.vue │ │ │ └── utils │ │ │ │ ├── data2blob.js │ │ │ │ ├── effectRipple.js │ │ │ │ ├── language.js │ │ │ │ └── mimes.js │ │ ├── JsonEditor │ │ │ └── index.vue │ │ ├── Kanban │ │ │ └── index.vue │ │ ├── MDinput │ │ │ └── index.vue │ │ ├── MarkdownEditor │ │ │ ├── default-options.js │ │ │ └── index.vue │ │ ├── Pagination │ │ │ └── index.vue │ │ ├── PanThumb │ │ │ └── index.vue │ │ ├── RightPanel │ │ │ └── index.vue │ │ ├── Screenfull │ │ │ └── index.vue │ │ ├── Share │ │ │ └── DropdownMenu.vue │ │ ├── SizeSelect │ │ │ └── index.vue │ │ ├── Sticky │ │ │ └── index.vue │ │ ├── SvgIcon │ │ │ └── index.vue │ │ ├── TextHoverEffect │ │ │ └── Mallki.vue │ │ ├── ThemePicker │ │ │ └── index.vue │ │ ├── Tinymce │ │ │ ├── components │ │ │ │ └── EditorImage.vue │ │ │ ├── dynamicLoadScript.js │ │ │ ├── index.vue │ │ │ ├── plugins.js │ │ │ └── toolbar.js │ │ ├── Upload │ │ │ ├── SingleImage.vue │ │ │ ├── SingleImage2.vue │ │ │ └── SingleImage3.vue │ │ └── UploadExcel │ │ │ └── index.vue │ ├── directive │ │ ├── clipboard │ │ │ ├── clipboard.js │ │ │ └── index.js │ │ ├── el-drag-dialog │ │ │ ├── drag.js │ │ │ └── index.js │ │ ├── el-table │ │ │ ├── adaptive.js │ │ │ └── index.js │ │ ├── permission │ │ │ ├── index.js │ │ │ └── permission.js │ │ ├── sticky.js │ │ └── waves │ │ │ ├── index.js │ │ │ ├── waves.css │ │ │ └── waves.js │ ├── filters │ │ └── index.js │ ├── icons │ │ ├── index.js │ │ ├── svg │ │ │ ├── 404.svg │ │ │ ├── bug.svg │ │ │ ├── chart.svg │ │ │ ├── clipboard.svg │ │ │ ├── component.svg │ │ │ ├── dashboard.svg │ │ │ ├── documentation.svg │ │ │ ├── drag.svg │ │ │ ├── edit.svg │ │ │ ├── education.svg │ │ │ ├── email.svg │ │ │ ├── example.svg │ │ │ ├── excel.svg │ │ │ ├── exit-fullscreen.svg │ │ │ ├── eye-open.svg │ │ │ ├── eye.svg │ │ │ ├── form.svg │ │ │ ├── fullscreen.svg │ │ │ ├── guide.svg │ │ │ ├── icon.svg │ │ │ ├── international.svg │ │ │ ├── language.svg │ │ │ ├── link.svg │ │ │ ├── list.svg │ │ │ ├── lock.svg │ │ │ ├── message.svg │ │ │ ├── money.svg │ │ │ ├── nested.svg │ │ │ ├── password.svg │ │ │ ├── pdf.svg │ │ │ ├── people.svg │ │ │ ├── peoples.svg │ │ │ ├── qq.svg │ │ │ ├── search.svg │ │ │ ├── shopping.svg │ │ │ ├── size.svg │ │ │ ├── skill.svg │ │ │ ├── star.svg │ │ │ ├── tab.svg │ │ │ ├── table.svg │ │ │ ├── theme.svg │ │ │ ├── tree-table.svg │ │ │ ├── tree.svg │ │ │ ├── user.svg │ │ │ ├── wechat.svg │ │ │ └── zip.svg │ │ └── svgo.yml │ ├── layout │ │ ├── components │ │ │ ├── AppMain.vue │ │ │ ├── Navbar.vue │ │ │ ├── Settings │ │ │ │ └── index.vue │ │ │ ├── Sidebar │ │ │ │ ├── FixiOSBug.js │ │ │ │ ├── Item.vue │ │ │ │ ├── Link.vue │ │ │ │ ├── Logo.vue │ │ │ │ ├── SidebarItem.vue │ │ │ │ └── index.vue │ │ │ ├── TagsView │ │ │ │ ├── ScrollPane.vue │ │ │ │ └── index.vue │ │ │ └── index.js │ │ ├── index.vue │ │ └── mixin │ │ │ └── ResizeHandler.js │ ├── main.js │ ├── permission.js │ ├── router │ │ ├── index.js │ │ └── modules │ │ │ ├── charts.js │ │ │ ├── components.js │ │ │ ├── nested.js │ │ │ └── table.js │ ├── settings.js │ ├── store │ │ ├── getters.js │ │ ├── index.js │ │ └── modules │ │ │ ├── app.js │ │ │ ├── errorLog.js │ │ │ ├── permission.js │ │ │ ├── settings.js │ │ │ ├── tagsView.js │ │ │ └── user.js │ ├── styles │ │ ├── btn.scss │ │ ├── element-ui.scss │ │ ├── element-variables.scss │ │ ├── index.scss │ │ ├── mixin.scss │ │ ├── sidebar.scss │ │ ├── transition.scss │ │ └── variables.scss │ ├── utils │ │ ├── auth.js │ │ ├── clipboard.js │ │ ├── error-log.js │ │ ├── get-page-title.js │ │ ├── index.js │ │ ├── open-window.js │ │ ├── permission.js │ │ ├── request.js │ │ ├── scroll-to.js │ │ └── validate.js │ ├── vendor │ │ ├── Export2Excel.js │ │ └── Export2Zip.js │ └── views │ │ ├── charts │ │ ├── keyboard.vue │ │ ├── line.vue │ │ └── mix-chart.vue │ │ ├── clipboard │ │ └── index.vue │ │ ├── components-demo │ │ ├── avatar-upload.vue │ │ ├── back-to-top.vue │ │ ├── count-to.vue │ │ ├── dnd-list.vue │ │ ├── drag-dialog.vue │ │ ├── drag-kanban.vue │ │ ├── drag-select.vue │ │ ├── dropzone.vue │ │ ├── json-editor.vue │ │ ├── markdown.vue │ │ ├── mixin.vue │ │ ├── split-pane.vue │ │ ├── sticky.vue │ │ └── tinymce.vue │ │ ├── dashboard │ │ ├── admin │ │ │ ├── components │ │ │ │ ├── BarChart.vue │ │ │ │ ├── BoxCard.vue │ │ │ │ ├── LineChart.vue │ │ │ │ ├── PanelGroup.vue │ │ │ │ ├── PieChart.vue │ │ │ │ ├── RaddarChart.vue │ │ │ │ ├── TodoList │ │ │ │ │ ├── Todo.vue │ │ │ │ │ ├── index.scss │ │ │ │ │ └── index.vue │ │ │ │ ├── TransactionTable.vue │ │ │ │ └── mixins │ │ │ │ │ └── resize.js │ │ │ └── index.vue │ │ ├── editor │ │ │ └── index.vue │ │ └── index.vue │ │ ├── documentation │ │ └── index.vue │ │ ├── error-log │ │ ├── components │ │ │ ├── ErrorTestA.vue │ │ │ └── ErrorTestB.vue │ │ └── index.vue │ │ ├── error-page │ │ ├── 401.vue │ │ └── 404.vue │ │ ├── example │ │ ├── components │ │ │ ├── ArticleDetail.vue │ │ │ ├── Dropdown │ │ │ │ ├── Comment.vue │ │ │ │ ├── Platform.vue │ │ │ │ ├── SourceUrl.vue │ │ │ │ └── index.js │ │ │ └── Warning.vue │ │ ├── create.vue │ │ ├── edit.vue │ │ └── list.vue │ │ ├── excel │ │ ├── components │ │ │ ├── AutoWidthOption.vue │ │ │ ├── BookTypeOption.vue │ │ │ └── FilenameOption.vue │ │ ├── export-excel.vue │ │ ├── merge-header.vue │ │ ├── select-excel.vue │ │ └── upload-excel.vue │ │ ├── guide │ │ ├── index.vue │ │ └── steps.js │ │ ├── icons │ │ ├── element-icons.js │ │ ├── index.vue │ │ └── svg-icons.js │ │ ├── login │ │ ├── auth-redirect.vue │ │ ├── components │ │ │ └── SocialSignin.vue │ │ └── index.vue │ │ ├── nested │ │ ├── menu1 │ │ │ ├── index.vue │ │ │ ├── menu1-1 │ │ │ │ └── index.vue │ │ │ ├── menu1-2 │ │ │ │ ├── index.vue │ │ │ │ ├── menu1-2-1 │ │ │ │ │ └── index.vue │ │ │ │ └── menu1-2-2 │ │ │ │ │ └── index.vue │ │ │ └── menu1-3 │ │ │ │ └── index.vue │ │ └── menu2 │ │ │ └── index.vue │ │ ├── pdf │ │ ├── content.js │ │ ├── download.vue │ │ └── index.vue │ │ ├── permission │ │ ├── components │ │ │ └── SwitchRoles.vue │ │ ├── directive.vue │ │ ├── page.vue │ │ └── role.vue │ │ ├── profile │ │ ├── components │ │ │ ├── Account.vue │ │ │ ├── Activity.vue │ │ │ ├── Timeline.vue │ │ │ └── UserCard.vue │ │ └── index.vue │ │ ├── qiniu │ │ └── upload.vue │ │ ├── redirect │ │ └── index.vue │ │ ├── tab │ │ ├── components │ │ │ └── TabPane.vue │ │ └── index.vue │ │ ├── table │ │ ├── complex-table.vue │ │ ├── drag-table.vue │ │ ├── dynamic-table │ │ │ ├── components │ │ │ │ ├── FixedThead.vue │ │ │ │ └── UnfixedThead.vue │ │ │ └── index.vue │ │ └── inline-edit-table.vue │ │ ├── theme │ │ └── index.vue │ │ └── zip │ │ └── index.vue │ ├── tests │ └── unit │ │ ├── .eslintrc.js │ │ ├── components │ │ ├── Hamburger.spec.js │ │ └── SvgIcon.spec.js │ │ └── utils │ │ ├── formatTime.spec.js │ │ ├── param2Obj.spec.js │ │ ├── parseTime.spec.js │ │ └── validate.spec.js │ └── vue.config.js └── uploads └── a /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | node_modules 3 | frontend/backend 4 | dist 5 | npm-debug.log 6 | coverage 7 | reports 8 | selenium-debug.log -------------------------------------------------------------------------------- /backend/Makefile: -------------------------------------------------------------------------------- 1 | GOCMD=go 2 | GOBUILD=$(GOCMD) build 3 | 4 | all: build 5 | 6 | build: 7 | $(GOBUILD) -v -o ./backend . 8 | mv backend ./../frontend/ -------------------------------------------------------------------------------- /backend/admin.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/backend/admin.db -------------------------------------------------------------------------------- /backend/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "database": { 3 | "default": { 4 | "max_idle_con": 50, 5 | "max_open_con": 150, 6 | "file": "./admin.db", 7 | "driver": "sqlite" 8 | } 9 | }, 10 | "prefix": "admin", 11 | "store": { 12 | "path": "./uploads", 13 | "prefix": "uploads" 14 | }, 15 | "language": "cn", 16 | "index": "/vue", 17 | "debug": true, 18 | "color_scheme": "skin-black", 19 | "open_admin_api": true 20 | } 21 | -------------------------------------------------------------------------------- /backend/uploads/a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/backend/uploads/a -------------------------------------------------------------------------------- /frontend/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist -------------------------------------------------------------------------------- /frontend/Makefile: -------------------------------------------------------------------------------- 1 | BACKEND=./backend 2 | 3 | all: serve 4 | 5 | serve: 6 | NODE_ENV=production npm --prefix ./src/adminlte run build 7 | NODE_ENV=production $(BACKEND) 8 | 9 | serve-quiet: 10 | NODE_ENV=production npm --prefix ./src/adminlte run build 11 | NODE_ENV=production $(BACKEND) --debug=true --quiet=true 12 | 13 | serve-element: 14 | NODE_ENV=production npm --prefix ./src/element run build 15 | NODE_ENV=production $(BACKEND) --debug=true --theme=sword --ui_theme=element 16 | 17 | build: 18 | npm --prefix=./src run build 19 | 20 | help: 21 | $(BACKEND) --help 22 | -------------------------------------------------------------------------------- /frontend/admin.antdesign.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/admin.antdesign.db -------------------------------------------------------------------------------- /frontend/admin.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/admin.db -------------------------------------------------------------------------------- /frontend/admin.element.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/admin.element.db -------------------------------------------------------------------------------- /frontend/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "database": { 3 | "default": { 4 | "max_idle_con": 50, 5 | "max_open_con": 150, 6 | "file": "./admin.db", 7 | "driver": "sqlite" 8 | } 9 | }, 10 | "prefix": "admin", 11 | "store": { 12 | "path": "./uploads", 13 | "prefix": "uploads" 14 | }, 15 | "language": "en", 16 | "index": "/vue", 17 | "debug": true, 18 | "color_scheme": "skin-black", 19 | "theme": "sword", 20 | "open_admin_api": true 21 | } 22 | -------------------------------------------------------------------------------- /frontend/src/adminlte/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "transform-object-rest-spread" 4 | ] 5 | } -------------------------------------------------------------------------------- /frontend/src/adminlte/build/dev-client.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | require('eventsource-polyfill') 3 | var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') 4 | 5 | hotClient.subscribe(function (event) { 6 | if (event.action === 'reload') { 7 | window.location.reload() 8 | } 9 | }) 10 | -------------------------------------------------------------------------------- /frontend/src/adminlte/build/vue-loader.conf.js: -------------------------------------------------------------------------------- 1 | var utils = require('./utils') 2 | var config = require('../config') 3 | var isProduction = process.env.NODE_ENV === 'production' 4 | 5 | module.exports = { 6 | loaders: utils.cssLoaders({ 7 | sourceMap: isProduction 8 | ? config.build.productionSourceMap 9 | : config.dev.cssSourceMap, 10 | extract: isProduction 11 | }), 12 | postcss: [ 13 | require('autoprefixer')({ 14 | browsers: ['last 2 versions'] 15 | }) 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /frontend/src/adminlte/build/webpack.test.conf.js: -------------------------------------------------------------------------------- 1 | // This is the webpack config used for unit tests. 2 | 3 | var utils = require('./utils') 4 | var webpack = require('webpack') 5 | var merge = require('webpack-merge') 6 | var baseConfig = require('./webpack.base.conf') 7 | 8 | var webpackConfig = merge(baseConfig, { 9 | // use inline sourcemap for karma-sourcemap-loader 10 | module: { 11 | rules: utils.styleLoaders() 12 | }, 13 | devtool: '#inline-source-map', 14 | plugins: [ 15 | new webpack.DefinePlugin({ 16 | 'process.env': require('../config/test.env') 17 | }) 18 | ] 19 | }) 20 | 21 | // no need for app entry during tests 22 | delete webpackConfig.entry 23 | 24 | module.exports = webpackConfig 25 | -------------------------------------------------------------------------------- /frontend/src/adminlte/config/dev.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var prodEnv = require('./prod.env') 3 | 4 | module.exports = merge(prodEnv, { 5 | NODE_ENV: '"development"' 6 | }) 7 | -------------------------------------------------------------------------------- /frontend/src/adminlte/config/prod.env.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | NODE_ENV: '"production"' 3 | } 4 | -------------------------------------------------------------------------------- /frontend/src/adminlte/config/test.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var devEnv = require('./dev.env') 3 | 4 | module.exports = merge(devEnv, { 5 | NODE_ENV: '"testing"' 6 | }) 7 | -------------------------------------------------------------------------------- /frontend/src/adminlte/index.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /frontend/src/adminlte/src/App.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 26 | 27 | 30 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/ContentWrap.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 34 | 35 | 43 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/src/assets/logo.png -------------------------------------------------------------------------------- /frontend/src/adminlte/src/components/VAAccordion.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 41 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/components/VAAlert.vue: -------------------------------------------------------------------------------- 1 | 8 | 36 | 38 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/components/VACallout.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 39 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/components/VAChart.vue: -------------------------------------------------------------------------------- 1 | 5 | 34 | 36 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/components/VACheckBox.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 41 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/components/VAFormGroup.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 15 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/components/VARadio.vue: -------------------------------------------------------------------------------- 1 | 9 | 36 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/components/VAText.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 37 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/components/VATextarea.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 32 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/components/VATextareaGroup.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 43 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/examples/APIExample.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 27 | 28 | 30 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/grid/Column.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 21 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/grid/Row.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 15 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/lib/css.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/src/lib/css.js -------------------------------------------------------------------------------- /frontend/src/adminlte/src/lib/eventBus.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | const EventBus = new Vue() 4 | 5 | export default EventBus 6 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/lib/global.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Row from '../grid/Row' 3 | import Column from '../grid/Column' 4 | Vue.component('row', Row) 5 | Vue.component('column', Column) 6 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/lib/script.js: -------------------------------------------------------------------------------- 1 | import 'jquery-slimscroll' 2 | import 'jquery-ui/ui/widgets/sortable.js' 3 | import 'jquery-ui/ui/widgets/datepicker.js' 4 | import 'jquery-ui/themes/base/datepicker.css' 5 | 6 | import 'admin-lte' 7 | import 'chart.js' 8 | 9 | // import 'bootstrap3-wysihtml5-bower/dist/amd/bootstrap3-wysihtml5.all.js' 10 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/pages/forms/AdvancedElements.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 15 | 16 | 19 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/pages/ui-elements/Icons.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 15 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/pages/ui-elements/Modals.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 15 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/pages/ui-elements/Sliders.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 15 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/pages/ui-elements/Timeline.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 15 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/vuex/actions.js: -------------------------------------------------------------------------------- 1 | import * as types from './mutation-types' 2 | import { services } from './api' 3 | 4 | export const fetchProduct = ({ commit }) => { 5 | // API request 6 | return services.products.getAll() 7 | .then((response) => { 8 | console.log(response) 9 | commit(types.FETCH_PRODUCT, response.data) 10 | }) 11 | .catch((error) => { 12 | console.error(error) 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/vuex/api/index.js: -------------------------------------------------------------------------------- 1 | import SERVICES from './services' 2 | export const services = SERVICES 3 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/vuex/api/services/index.js: -------------------------------------------------------------------------------- 1 | import products from './products' 2 | 3 | export default { 4 | products 5 | } 6 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/vuex/api/services/products.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | 3 | export default { 4 | getAll (request = {}) { 5 | return axios.get('http://localhost:3000/products', request) 6 | .then((response) => Promise.resolve(response)) 7 | .catch((error) => Promise.reject(error)) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/vuex/getters.js: -------------------------------------------------------------------------------- 1 | export const unreadMessagesCount = state => state.messages.main.length 2 | export const unreadNotificationsCount = state => state.notifications.main.length 3 | export const remainTasksCount = state => state.tasks.main.length 4 | export const currentUser = state => state.user.main 5 | export const totalProduct = state => state.products.main 6 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/vuex/modules/index.js: -------------------------------------------------------------------------------- 1 | const files = require.context('.', false, /\.js$/) 2 | const modules = {} 3 | 4 | files.keys().forEach((key) => { 5 | if (key === './index.js') return 6 | modules[key.replace(/(\.\/|\.js)/g, '')] = files(key).default 7 | }) 8 | 9 | export default modules 10 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/vuex/modules/messages.js: -------------------------------------------------------------------------------- 1 | const state = { 2 | main: [ 3 | { 4 | id: 1, 5 | body: 'Message 1' 6 | }, 7 | { 8 | id: 2, 9 | body: 'Message 2' 10 | }, 11 | { 12 | id: 3, 13 | body: 'Message 3' 14 | }, 15 | { 16 | id: 4, 17 | body: 'Message 4' 18 | }, 19 | { 20 | id: 5, 21 | body: 'Message 5' 22 | }, 23 | { 24 | id: 5, 25 | body: 'Message 5' 26 | } 27 | ] 28 | } 29 | 30 | const mutations = { 31 | 32 | } 33 | 34 | export default { 35 | state, 36 | mutations 37 | } 38 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/vuex/modules/notifications.js: -------------------------------------------------------------------------------- 1 | const state = { 2 | main: [ 3 | { 4 | id: 1, 5 | body: 'Noti 1' 6 | }, 7 | { 8 | id: 2, 9 | body: 'Noti 2' 10 | } 11 | ] 12 | } 13 | 14 | const mutations = { 15 | 16 | } 17 | 18 | export default { 19 | state, 20 | mutations 21 | } 22 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/vuex/modules/products.js: -------------------------------------------------------------------------------- 1 | import * as types from '../mutation-types' 2 | 3 | const state = { 4 | main: [] 5 | } 6 | 7 | const mutations = { 8 | [types.FETCH_PRODUCT] (state, products) { 9 | state.main = products 10 | } 11 | } 12 | 13 | export default { 14 | state, 15 | mutations 16 | } 17 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/vuex/modules/tasks.js: -------------------------------------------------------------------------------- 1 | const state = { 2 | main: [ 3 | { 4 | id: 1, 5 | body: 'Task 1' 6 | }, 7 | { 8 | id: 2, 9 | body: 'Task 2' 10 | }, 11 | { 12 | id: 3, 13 | body: 'Task 3' 14 | }, 15 | { 16 | id: 4, 17 | body: 'Task 4' 18 | } 19 | ] 20 | } 21 | 22 | const mutations = { 23 | 24 | } 25 | 26 | export default { 27 | state, 28 | mutations 29 | } 30 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/vuex/modules/user.js: -------------------------------------------------------------------------------- 1 | const state = { 2 | main: { 3 | name: 'Alexander Pierce', 4 | position: 'Web Developer', 5 | state: { 6 | color: '#3c763d', 7 | name: 'Online' 8 | }, 9 | createdAt: new Date() 10 | } 11 | } 12 | 13 | const mutations = { 14 | 15 | } 16 | 17 | export default { 18 | state, 19 | mutations 20 | } 21 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/vuex/mutation-types.js: -------------------------------------------------------------------------------- 1 | export const FETCH_PRODUCT = 'FETCH_PRODUCT' 2 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/vuex/store.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | 4 | import * as actions from './actions' 5 | import * as getters from './getters' 6 | import modules from './modules' 7 | 8 | Vue.use(Vuex) 9 | 10 | export default new Vuex.Store({ 11 | actions, 12 | getters, 13 | modules, 14 | strict: process.env.NODE_ENV !== 'production' 15 | }) 16 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/widgets/VADirectChatContact.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 46 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/widgets/VASmallBox.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 32 | -------------------------------------------------------------------------------- /frontend/src/adminlte/src/widgets/VASocialBoxComment.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 45 | -------------------------------------------------------------------------------- /frontend/src/adminlte/static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/.gitkeep -------------------------------------------------------------------------------- /frontend/src/adminlte/static/img/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/img/avatar.png -------------------------------------------------------------------------------- /frontend/src/adminlte/static/img/avatar04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/img/avatar04.png -------------------------------------------------------------------------------- /frontend/src/adminlte/static/img/avatar2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/img/avatar2.png -------------------------------------------------------------------------------- /frontend/src/adminlte/static/img/avatar3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/img/avatar3.png -------------------------------------------------------------------------------- /frontend/src/adminlte/static/img/avatar5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/img/avatar5.png -------------------------------------------------------------------------------- /frontend/src/adminlte/static/img/boxed-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/img/boxed-bg.jpg -------------------------------------------------------------------------------- /frontend/src/adminlte/static/img/boxed-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/img/boxed-bg.png -------------------------------------------------------------------------------- /frontend/src/adminlte/static/img/credit/american-express.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/img/credit/american-express.png -------------------------------------------------------------------------------- /frontend/src/adminlte/static/img/credit/cirrus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/img/credit/cirrus.png -------------------------------------------------------------------------------- /frontend/src/adminlte/static/img/credit/mastercard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/img/credit/mastercard.png -------------------------------------------------------------------------------- /frontend/src/adminlte/static/img/credit/mestro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/img/credit/mestro.png -------------------------------------------------------------------------------- /frontend/src/adminlte/static/img/credit/paypal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/img/credit/paypal.png -------------------------------------------------------------------------------- /frontend/src/adminlte/static/img/credit/paypal2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/img/credit/paypal2.png -------------------------------------------------------------------------------- /frontend/src/adminlte/static/img/credit/visa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/img/credit/visa.png -------------------------------------------------------------------------------- /frontend/src/adminlte/static/img/default-50x50.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/img/default-50x50.gif -------------------------------------------------------------------------------- /frontend/src/adminlte/static/img/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/img/icons.png -------------------------------------------------------------------------------- /frontend/src/adminlte/static/img/photo1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/img/photo1.png -------------------------------------------------------------------------------- /frontend/src/adminlte/static/img/photo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/img/photo2.png -------------------------------------------------------------------------------- /frontend/src/adminlte/static/img/photo3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/img/photo3.jpg -------------------------------------------------------------------------------- /frontend/src/adminlte/static/img/photo4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/img/photo4.jpg -------------------------------------------------------------------------------- /frontend/src/adminlte/static/img/user1-128x128.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/img/user1-128x128.jpg -------------------------------------------------------------------------------- /frontend/src/adminlte/static/img/user2-160x160.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/img/user2-160x160.jpg -------------------------------------------------------------------------------- /frontend/src/adminlte/static/img/user3-128x128.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/img/user3-128x128.jpg -------------------------------------------------------------------------------- /frontend/src/adminlte/static/img/user4-128x128.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/img/user4-128x128.jpg -------------------------------------------------------------------------------- /frontend/src/adminlte/static/img/user5-128x128.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/img/user5-128x128.jpg -------------------------------------------------------------------------------- /frontend/src/adminlte/static/img/user6-128x128.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/img/user6-128x128.jpg -------------------------------------------------------------------------------- /frontend/src/adminlte/static/img/user7-128x128.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/img/user7-128x128.jpg -------------------------------------------------------------------------------- /frontend/src/adminlte/static/img/user8-128x128.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/adminlte/static/img/user8-128x128.jpg -------------------------------------------------------------------------------- /frontend/src/adminlte/test/e2e/custom-assertions/elementCount.js: -------------------------------------------------------------------------------- 1 | // A custom Nightwatch assertion. 2 | // the name of the method is the filename. 3 | // can be used in tests like this: 4 | // 5 | // browser.assert.elementCount(selector, count) 6 | // 7 | // for how to write custom assertions see 8 | // http://nightwatchjs.org/guide#writing-custom-assertions 9 | exports.assertion = function (selector, count) { 10 | this.message = 'Testing if element <' + selector + '> has count: ' + count 11 | this.expected = count 12 | this.pass = function (val) { 13 | return val === this.expected 14 | } 15 | this.value = function (res) { 16 | return res.value 17 | } 18 | this.command = function (cb) { 19 | var self = this 20 | return this.api.execute(function (selector) { 21 | return document.querySelectorAll(selector).length 22 | }, [selector], function (res) { 23 | cb.call(self, res) 24 | }) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /frontend/src/adminlte/test/e2e/specs/test.js: -------------------------------------------------------------------------------- 1 | // For authoring Nightwatch tests, see 2 | // http://nightwatchjs.org/guide#usage 3 | 4 | module.exports = { 5 | 'default e2e tests': function (browser) { 6 | // automatically uses dev Server port from /config.index.js 7 | // default: http://localhost:8080 8 | // see nightwatch.conf.js 9 | const devServer = browser.globals.devServerURL 10 | 11 | browser 12 | .url(devServer) 13 | .waitForElementVisible('#app', 5000) 14 | .assert.elementPresent('.hello') 15 | .assert.containsText('h1', 'Welcome to Your Vue.js App') 16 | .assert.elementCount('img', 1) 17 | .end() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /frontend/src/adminlte/test/unit/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | }, 5 | "globals": { 6 | "expect": true, 7 | "sinon": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /frontend/src/adminlte/test/unit/index.js: -------------------------------------------------------------------------------- 1 | // Polyfill fn.bind() for PhantomJS 2 | /* eslint-disable no-extend-native */ 3 | Function.prototype.bind = require('function-bind') 4 | 5 | // require all test files (files that ends with .spec.js) 6 | const testsContext = require.context('./specs', true, /\.spec$/) 7 | testsContext.keys().forEach(testsContext) 8 | 9 | // require all src files except main.js for coverage. 10 | // you can also change this to match only the subset of files that 11 | // you want coverage for. 12 | const srcContext = require.context('src', true, /^\.\/(?!main(\.js)?$)/) 13 | srcContext.keys().forEach(srcContext) 14 | -------------------------------------------------------------------------------- /frontend/src/antdesign/.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | 15 | [Makefile] 16 | indent_style = tab 17 | -------------------------------------------------------------------------------- /frontend/src/antdesign/.eslintignore: -------------------------------------------------------------------------------- 1 | /lambda/ 2 | /scripts 3 | /config 4 | .history 5 | public 6 | dist 7 | .umi 8 | mock -------------------------------------------------------------------------------- /frontend/src/antdesign/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [require.resolve('@umijs/lint/dist/config/eslint')], 3 | globals: { 4 | page: true, 5 | REACT_APP_ENV: true, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /frontend/src/antdesign/.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 | 12 | # misc 13 | .DS_Store 14 | npm-debug.log* 15 | yarn-error.log 16 | 17 | /coverage 18 | .idea 19 | yarn.lock 20 | package-lock.json 21 | *bak 22 | .vscode 23 | 24 | 25 | # visual studio code 26 | .history 27 | *.log 28 | functions/* 29 | .temp/** 30 | 31 | # umi 32 | .umi 33 | .umi-production 34 | .umi-test 35 | 36 | # screenshot 37 | screenshot 38 | .firebase 39 | .eslintcache 40 | 41 | build 42 | -------------------------------------------------------------------------------- /frontend/src/antdesign/.prettierignore: -------------------------------------------------------------------------------- 1 | **/*.svg 2 | .umi 3 | .umi-production 4 | /dist 5 | .dockerignore 6 | .DS_Store 7 | .eslintignore 8 | *.png 9 | *.toml 10 | docker 11 | .editorconfig 12 | Dockerfile* 13 | .gitignore 14 | .prettierignore 15 | LICENSE 16 | .eslintcache 17 | *.lock 18 | yarn-error.log 19 | .history 20 | CNAME 21 | /build 22 | /public 23 | -------------------------------------------------------------------------------- /frontend/src/antdesign/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | singleQuote: true, 3 | trailingComma: 'all', 4 | printWidth: 100, 5 | proseWrap: 'never', 6 | endOfLine: 'lf', 7 | overrides: [ 8 | { 9 | files: '.prettierrc', 10 | options: { 11 | parser: 'json', 12 | }, 13 | }, 14 | { 15 | files: 'document.ejs', 16 | options: { 17 | parser: 'html', 18 | }, 19 | }, 20 | ], 21 | plugins: [ 22 | 'prettier-plugin-organize-imports', 23 | 'prettier-plugin-packagejson', 24 | 'prettier-plugin-two-style-order', 25 | ], 26 | }; 27 | -------------------------------------------------------------------------------- /frontend/src/antdesign/config/defaultSettings.ts: -------------------------------------------------------------------------------- 1 | import { ProLayoutProps } from '@ant-design/pro-components'; 2 | 3 | /** 4 | * @name 5 | */ 6 | const Settings: ProLayoutProps & { 7 | pwa?: boolean; 8 | logo?: string; 9 | } = { 10 | navTheme: 'light', 11 | // 拂晓蓝 12 | colorPrimary: '#1890ff', 13 | layout: 'mix', 14 | contentWidth: 'Fluid', 15 | fixedHeader: false, 16 | fixSiderbar: true, 17 | colorWeak: false, 18 | title: 'Ant Design Pro', 19 | pwa: true, 20 | logo: 'https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg', 21 | iconfontUrl: '', 22 | token: { 23 | // 参见ts声明,demo 见文档,通过token 修改样式 24 | //https://procomponents.ant.design/components/layout#%E9%80%9A%E8%BF%87-token-%E4%BF%AE%E6%94%B9%E6%A0%B7%E5%BC%8F 25 | }, 26 | }; 27 | 28 | export default Settings; 29 | -------------------------------------------------------------------------------- /frontend/src/antdesign/jest.config.ts: -------------------------------------------------------------------------------- 1 | import { configUmiAlias, createConfig } from '@umijs/max/test'; 2 | 3 | export default async () => { 4 | const config = await configUmiAlias({ 5 | ...createConfig({ 6 | target: 'browser', 7 | }), 8 | }); 9 | console.log(JSON.stringify(config)); 10 | 11 | return { 12 | ...config, 13 | testEnvironmentOptions: { 14 | ...(config?.testEnvironmentOptions || {}), 15 | url: 'http://localhost:8000', 16 | }, 17 | setupFiles: [...(config.setupFiles || []), './tests/setupTests.jsx'], 18 | globals: { 19 | ...config.globals, 20 | localStorage: null, 21 | }, 22 | }; 23 | }; 24 | -------------------------------------------------------------------------------- /frontend/src/antdesign/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "jsx": "react-jsx", 4 | "emitDecoratorMetadata": true, 5 | "experimentalDecorators": true, 6 | "baseUrl": ".", 7 | "paths": { 8 | "@/*": ["./src/*"] 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /frontend/src/antdesign/mock/monitor.mock.ts: -------------------------------------------------------------------------------- 1 | import type { Request, Response } from 'express'; 2 | import mockjs from 'mockjs'; 3 | 4 | const getTags = (_: Request, res: Response) => { 5 | return res.json({ 6 | data: mockjs.mock({ 7 | 'list|100': [{ name: '@city', 'value|1-100': 150, 'type|0-2': 1 }], 8 | }), 9 | }); 10 | }; 11 | 12 | export default { 13 | 'GET /api/tags': getTags, 14 | }; 15 | -------------------------------------------------------------------------------- /frontend/src/antdesign/mock/route.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | '/api/auth_routes': { 3 | '/form/advanced-form': { authority: ['admin', 'user'] }, 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /frontend/src/antdesign/public/CNAME: -------------------------------------------------------------------------------- 1 | preview.pro.ant.design -------------------------------------------------------------------------------- /frontend/src/antdesign/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/antdesign/public/favicon.ico -------------------------------------------------------------------------------- /frontend/src/antdesign/public/icons/icon-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/antdesign/public/icons/icon-128x128.png -------------------------------------------------------------------------------- /frontend/src/antdesign/public/icons/icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/antdesign/public/icons/icon-192x192.png -------------------------------------------------------------------------------- /frontend/src/antdesign/public/icons/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/antdesign/public/icons/icon-512x512.png -------------------------------------------------------------------------------- /frontend/src/antdesign/public/pro_icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/access.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @see https://umijs.org/zh-CN/plugins/plugin-access 3 | * */ 4 | export default function access(initialState: { currentUser?: API.CurrentUser } | undefined) { 5 | const { currentUser } = initialState ?? {}; 6 | return { 7 | canAdmin: currentUser && currentUser.access === 'admin', 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/components/Footer/index.tsx: -------------------------------------------------------------------------------- 1 | import { GithubOutlined } from '@ant-design/icons'; 2 | import { DefaultFooter } from '@ant-design/pro-components'; 3 | import React from 'react'; 4 | 5 | const Footer: React.FC = () => { 6 | return ( 7 | , 22 | href: 'https://github.com/ant-design/ant-design-pro', 23 | blankTarget: true, 24 | }, 25 | { 26 | key: 'Ant Design', 27 | title: 'Ant Design', 28 | href: 'https://ant.design', 29 | blankTarget: true, 30 | }, 31 | ]} 32 | /> 33 | ); 34 | }; 35 | 36 | export default Footer; 37 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/components/HeaderDropdown/index.tsx: -------------------------------------------------------------------------------- 1 | import { Dropdown } from 'antd'; 2 | import { createStyles } from 'antd-style'; 3 | import type { DropDownProps } from 'antd/es/dropdown'; 4 | import classNames from 'classnames'; 5 | import React from 'react'; 6 | 7 | const useStyles = createStyles(({ token }) => { 8 | return { 9 | dropdown: { 10 | [`@media screen and (max-width: ${token.screenXS}px)`]: { 11 | width: '100%', 12 | }, 13 | }, 14 | }; 15 | }); 16 | 17 | export type HeaderDropdownProps = { 18 | overlayClassName?: string; 19 | placement?: 'bottomLeft' | 'bottomRight' | 'topLeft' | 'topCenter' | 'topRight' | 'bottomCenter'; 20 | } & Omit; 21 | 22 | const HeaderDropdown: React.FC = ({ overlayClassName: cls, ...restProps }) => { 23 | const { styles } = useStyles(); 24 | return ; 25 | }; 26 | 27 | export default HeaderDropdown; 28 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/components/RightContent/index.tsx: -------------------------------------------------------------------------------- 1 | import { QuestionCircleOutlined } from '@ant-design/icons'; 2 | import { SelectLang as UmiSelectLang } from '@umijs/max'; 3 | 4 | export type SiderTheme = 'light' | 'dark'; 5 | 6 | export const SelectLang = () => { 7 | return ; 8 | }; 9 | 10 | export const Question = () => { 11 | return ( 12 |
{ 18 | window.open('https://pro.ant.design/docs/getting-started'); 19 | }} 20 | > 21 | 22 |
23 | ); 24 | }; 25 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/components/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 这个文件作为组件的目录 3 | * 目的是统一管理对外输出的组件,方便分类 4 | */ 5 | /** 6 | * 布局组件 7 | */ 8 | import Footer from './Footer'; 9 | import { Question, SelectLang } from './RightContent'; 10 | import { AvatarDropdown, AvatarName } from './RightContent/AvatarDropdown'; 11 | 12 | export { Footer, Question, SelectLang, AvatarDropdown, AvatarName }; 13 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/global.less: -------------------------------------------------------------------------------- 1 | .colorWeak { 2 | filter: invert(80%); 3 | } 4 | 5 | .ant-layout { 6 | min-height: 100vh; 7 | } 8 | .ant-pro-sider.ant-layout-sider.ant-pro-sider-fixed { 9 | left: unset; 10 | } 11 | 12 | canvas { 13 | display: block; 14 | } 15 | 16 | body { 17 | text-rendering: optimizeLegibility; 18 | -webkit-font-smoothing: antialiased; 19 | -moz-osx-font-smoothing: grayscale; 20 | } 21 | 22 | ul, 23 | ol { 24 | list-style: none; 25 | } 26 | 27 | @media (max-width: 768px) { 28 | .ant-table { 29 | width: 100%; 30 | overflow-x: auto; 31 | &-thead > tr, 32 | &-tbody > tr { 33 | > th, 34 | > td { 35 | white-space: pre; 36 | > span { 37 | display: block; 38 | } 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/global.style.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from 'antd-style'; 2 | 3 | const useStyles = createStyles(({}) => { 4 | return { 5 | colorWeak: { 6 | filter: 'invert(80%)', 7 | }, 8 | 'ant-layout': { 9 | minHeight: '100vh', 10 | }, 11 | 'ant-pro-sider.ant-layout-sider.ant-pro-sider-fixed': { 12 | left: 'unset', 13 | }, 14 | canvas: { 15 | display: 'block', 16 | }, 17 | body: { 18 | textRendering: 'optimizeLegibility', 19 | WebkitFontSmoothing: 'antialiased', 20 | MozOsxFontSmoothing: 'grayscale', 21 | }, 22 | 'ul,ol': { 23 | listStyle: 'none', 24 | }, 25 | '@media(max-width: 768px)': { 26 | 'ant-table': { 27 | width: '100%', 28 | overflowX: 'auto', 29 | '&-thead > tr, &-tbody > tr': { 30 | '> th, > td': { 31 | whiteSpace: 'pre', 32 | '> span': { 33 | display: 'block', 34 | }, 35 | }, 36 | }, 37 | }, 38 | }, 39 | }; 40 | }); 41 | 42 | export default useStyles; 43 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/locales/bn-BD.ts: -------------------------------------------------------------------------------- 1 | import component from './bn-BD/component'; 2 | import globalHeader from './bn-BD/globalHeader'; 3 | import menu from './bn-BD/menu'; 4 | import pages from './bn-BD/pages'; 5 | import pwa from './bn-BD/pwa'; 6 | import settingDrawer from './bn-BD/settingDrawer'; 7 | import settings from './bn-BD/settings'; 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 | '`block` ডেভেলপমেন্ট এর উপর ভিত্তি করে দ্রুত স্ট্যান্ডার্ড, পৃষ্ঠাসমূহ তৈরি করুন।', 18 | ...globalHeader, 19 | ...menu, 20 | ...settingDrawer, 21 | ...settings, 22 | ...pwa, 23 | ...component, 24 | ...pages, 25 | }; 26 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/locales/bn-BD/component.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'component.tagSelect.expand': 'বিস্তৃত', 3 | 'component.tagSelect.collapse': 'সঙ্কুচিত', 4 | 'component.tagSelect.all': 'সব', 5 | }; 6 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/locales/bn-BD/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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/locales/bn-BD/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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/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 pages from './en-US/pages'; 5 | import pwa from './en-US/pwa'; 6 | import settingDrawer from './en-US/settingDrawer'; 7 | import settings from './en-US/settings'; 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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/locales/fa-IR.ts: -------------------------------------------------------------------------------- 1 | import component from './fa-IR/component'; 2 | import globalHeader from './fa-IR/globalHeader'; 3 | import menu from './fa-IR/menu'; 4 | import pages from './fa-IR/pages'; 5 | import pwa from './fa-IR/pwa'; 6 | import settingDrawer from './fa-IR/settingDrawer'; 7 | import settings from './fa-IR/settings'; 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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/locales/fa-IR/component.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'component.tagSelect.expand': 'باز', 3 | 'component.tagSelect.collapse': 'بسته ', 4 | 'component.tagSelect.all': 'همه', 5 | }; 6 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/locales/fa-IR/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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/locales/fa-IR/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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/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 pages from './id-ID/pages'; 5 | import pwa from './id-ID/pwa'; 6 | import settingDrawer from './id-ID/settingDrawer'; 7 | import settings from './id-ID/settings'; 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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/locales/ja-JP.ts: -------------------------------------------------------------------------------- 1 | import component from './ja-JP/component'; 2 | import globalHeader from './ja-JP/globalHeader'; 3 | import menu from './ja-JP/menu'; 4 | import pages from './ja-JP/pages'; 5 | import pwa from './ja-JP/pwa'; 6 | import settingDrawer from './ja-JP/settingDrawer'; 7 | import settings from './ja-JP/settings'; 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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/locales/ja-JP/component.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'component.tagSelect.expand': '展開', 3 | 'component.tagSelect.collapse': '折りたたむ', 4 | 'component.tagSelect.all': 'すべて', 5 | }; 6 | -------------------------------------------------------------------------------- /frontend/src/antdesign/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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/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 pages from './pt-BR/pages'; 5 | import pwa from './pt-BR/pwa'; 6 | import settingDrawer from './pt-BR/settingDrawer'; 7 | import settings from './pt-BR/settings'; 8 | 9 | export default { 10 | 'navBar.lang': 'Idiomas', 11 | 'layout.user.link.help': 'ajuda', 12 | 'layout.user.link.privacy': 'política de privacidade', 13 | 'layout.user.link.terms': 'termos de serviços', 14 | 'app.preview.down.block': 'Download this page to your local project', 15 | ...globalHeader, 16 | ...menu, 17 | ...settingDrawer, 18 | ...settings, 19 | ...pwa, 20 | ...component, 21 | ...pages, 22 | }; 23 | -------------------------------------------------------------------------------- /frontend/src/antdesign/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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/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.view-more': 'Veja mais', 17 | }; 18 | -------------------------------------------------------------------------------- /frontend/src/antdesign/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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/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 pages from './zh-CN/pages'; 5 | import pwa from './zh-CN/pwa'; 6 | import settingDrawer from './zh-CN/settingDrawer'; 7 | import settings from './zh-CN/settings'; 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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/locales/zh-CN/component.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'component.tagSelect.expand': '展开', 3 | 'component.tagSelect.collapse': '收起', 4 | 'component.tagSelect.all': '全部', 5 | }; 6 | -------------------------------------------------------------------------------- /frontend/src/antdesign/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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/locales/zh-TW/component.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'component.tagSelect.expand': '展開', 3 | 'component.tagSelect.collapse': '收起', 4 | 'component.tagSelect.all': '全部', 5 | }; 6 | -------------------------------------------------------------------------------- /frontend/src/antdesign/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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/404.tsx: -------------------------------------------------------------------------------- 1 | import { history, useIntl } from '@umijs/max'; 2 | import { Button, Result } from 'antd'; 3 | import React from 'react'; 4 | 5 | const NoFoundPage: React.FC = () => ( 6 | history.push('/')}> 12 | {useIntl().formatMessage({ id: 'pages.404.buttonText' })} 13 | 14 | } 15 | /> 16 | ); 17 | 18 | export default NoFoundPage; 19 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/account/center/components/ArticleListContent/index.style.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from 'antd-style'; 2 | 3 | const useStyles = createStyles(({ token }) => { 4 | return { 5 | description: { 6 | maxWidth: '720px', 7 | lineHeight: '22px', 8 | }, 9 | extra: { 10 | marginTop: '16px', 11 | color: token.colorTextSecondary, 12 | lineHeight: '22px', 13 | '& > em': { 14 | marginLeft: '16px', 15 | color: token.colorTextDisabled, 16 | fontStyle: 'normal', 17 | }, 18 | [`@media screen and (max-width: ${token.screenXS}px)`]: { 19 | '& > em': { 20 | display: 'block', 21 | marginTop: '8px', 22 | marginLeft: '0', 23 | }, 24 | }, 25 | }, 26 | }; 27 | }); 28 | 29 | export default useStyles; 30 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/account/center/components/ArticleListContent/index.tsx: -------------------------------------------------------------------------------- 1 | import { Avatar } from 'antd'; 2 | import dayjs from 'dayjs'; 3 | import React from 'react'; 4 | import useStyles from './index.style'; 5 | export type ApplicationsProps = { 6 | data: { 7 | content?: string; 8 | updatedAt?: any; 9 | avatar?: string; 10 | owner?: string; 11 | href?: string; 12 | }; 13 | }; 14 | const ArticleListContent: React.FC = ({ 15 | data: { content, updatedAt, avatar, owner, href }, 16 | }) => { 17 | const { styles } = useStyles(); 18 | return ( 19 |
20 |
{content}
21 |
22 | 23 | {owner} 发布在 {href} 24 | {dayjs(updatedAt).format('YYYY-MM-DD HH:mm')} 25 |
26 |
27 | ); 28 | }; 29 | export default ArticleListContent; 30 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/account/center/components/Articles/index.style.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from 'antd-style'; 2 | 3 | const useStyles = createStyles(({ token }) => { 4 | return { 5 | articleList: { 6 | '.ant-list-item:first-child': { paddingTop: '0' }, 7 | }, 8 | listItemMetaTitle: { 9 | color: token.colorTextHeading, 10 | }, 11 | }; 12 | }); 13 | 14 | export default useStyles; 15 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/account/center/service.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@umijs/max'; 2 | import type { CurrentUser, ListItemDataType } from './data.d'; 3 | 4 | export async function queryCurrent(): Promise<{ data: CurrentUser }> { 5 | return request('/api/currentUserDetail'); 6 | } 7 | 8 | export async function queryFakeList(params: { 9 | count: number; 10 | }): Promise<{ data: { list: ListItemDataType[] } }> { 11 | return request('/api/fake_list_Detail', { 12 | params, 13 | }); 14 | } 15 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/account/settings/components/PhoneView.tsx: -------------------------------------------------------------------------------- 1 | import { Input } from 'antd'; 2 | import React from 'react'; 3 | import useStyles from './index.style'; 4 | 5 | type PhoneViewProps = { 6 | value?: string; 7 | onChange?: (value: string) => void; 8 | }; 9 | const PhoneView: React.FC = (props) => { 10 | const { styles } = useStyles(); 11 | const { value, onChange } = props; 12 | let values = ['', '']; 13 | if (value) { 14 | values = value.split('-'); 15 | } 16 | return ( 17 | <> 18 | { 22 | if (onChange) { 23 | onChange(`${e.target.value}-${values[1]}`); 24 | } 25 | }} 26 | /> 27 | { 30 | if (onChange) { 31 | onChange(`${values[0]}-${e.target.value}`); 32 | } 33 | }} 34 | value={values[1]} 35 | /> 36 | 37 | ); 38 | }; 39 | export default PhoneView; 40 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/account/settings/data.d.ts: -------------------------------------------------------------------------------- 1 | export type TagType = { 2 | key: string; 3 | label: string; 4 | }; 5 | 6 | export type GeographicItemType = { 7 | name: string; 8 | id: string; 9 | }; 10 | 11 | export type GeographicType = { 12 | province: GeographicItemType; 13 | city: GeographicItemType; 14 | }; 15 | 16 | export type 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 type 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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/account/settings/service.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@umijs/max'; 2 | import type { CurrentUser, GeographicItemType } from './data'; 3 | 4 | export async function queryCurrent(): Promise<{ data: CurrentUser }> { 5 | return request('/api/accountSettingCurrentUser'); 6 | } 7 | 8 | export async function queryProvince(): Promise<{ data: GeographicItemType[] }> { 9 | return request('/api/geographic/province'); 10 | } 11 | 12 | export async function queryCity(province: string): Promise<{ data: GeographicItemType[] }> { 13 | return request(`/api/geographic/city/${province}`); 14 | } 15 | 16 | export async function query() { 17 | return request('/api/users'); 18 | } 19 | -------------------------------------------------------------------------------- /frontend/src/antdesign/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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/dashboard/analysis/components/Charts/Field/index.style.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from 'antd-style'; 2 | 3 | const useStyles = createStyles(({ token }) => { 4 | return { 5 | field: { 6 | margin: '0', 7 | overflow: 'hidden', 8 | whiteSpace: 'nowrap', 9 | textOverflow: 'ellipsis', 10 | }, 11 | label: { 12 | fontSize: token.fontSize, 13 | lineHeight: '22px', 14 | }, 15 | number: { 16 | marginLeft: '8px', 17 | color: token.colorTextHeading, 18 | }, 19 | }; 20 | }); 21 | 22 | export default useStyles; 23 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/dashboard/analysis/components/Charts/Field/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import useStyles from './index.style'; 3 | export type FieldProps = { 4 | label: React.ReactNode; 5 | value: React.ReactNode; 6 | style?: React.CSSProperties; 7 | }; 8 | const Field: React.FC = ({ label, value, ...rest }) => { 9 | const { styles } = useStyles(); 10 | return ( 11 |
12 | {label} 13 | {value} 14 |
15 | ); 16 | }; 17 | export default Field; 18 | -------------------------------------------------------------------------------- /frontend/src/antdesign/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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/dashboard/analysis/components/Charts/index.style.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from 'antd-style'; 2 | 3 | const useStyles = createStyles(() => { 4 | return { 5 | miniChart: { 6 | position: 'relative', 7 | width: '100%', 8 | }, 9 | chartContent: { 10 | position: 'absolute', 11 | bottom: '-28px', 12 | width: '100%', 13 | '> div': { margin: '0 -5px', overflow: 'hidden' }, 14 | }, 15 | chartLoading: { 16 | position: 'absolute', 17 | top: '16px', 18 | left: '50%', 19 | marginLeft: '-7px', 20 | }, 21 | }; 22 | }); 23 | export default useStyles; 24 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/dashboard/analysis/components/Charts/index.tsx: -------------------------------------------------------------------------------- 1 | import numeral from 'numeral'; 2 | import ChartCard from './ChartCard'; 3 | import Field from './Field'; 4 | 5 | const yuan = (val: number | string) => `¥ ${numeral(val).format('0,0')}`; 6 | 7 | const Charts = { 8 | yuan, 9 | ChartCard, 10 | Field, 11 | }; 12 | 13 | export { Charts as default, yuan, ChartCard, Field }; 14 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/dashboard/analysis/components/PageLoading/index.tsx: -------------------------------------------------------------------------------- 1 | import { Spin } from 'antd'; 2 | 3 | // loading components from code split 4 | // https://umijs.org/plugin/umi-plugin-react.html#dynamicimport 5 | export default () => ( 6 |
7 | 8 |
9 | ); 10 | -------------------------------------------------------------------------------- /frontend/src/antdesign/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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/dashboard/analysis/components/Trend/index.style.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from 'antd-style'; 2 | 3 | const useStyles = createStyles(({ token }) => { 4 | return { 5 | trendItem: { 6 | display: 'inline-block', 7 | fontSize: token.fontSize, 8 | lineHeight: '22px', 9 | }, 10 | up: { 11 | color: token['red-6'], 12 | }, 13 | down: { 14 | top: '-1px', 15 | color: token['green-6'], 16 | }, 17 | trendItemGrey: { 18 | up: { 19 | color: token.colorText, 20 | }, 21 | down: { 22 | color: token.colorText, 23 | }, 24 | }, 25 | reverseColor: { 26 | up: { color: token['green-6'] }, 27 | down: { color: token['red-6'] }, 28 | }, 29 | }; 30 | }); 31 | 32 | export default useStyles; 33 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/dashboard/analysis/data.d.ts: -------------------------------------------------------------------------------- 1 | import { DataItem } from '@antv/g2plot/esm/interface/config'; 2 | 3 | export { DataItem }; 4 | 5 | export interface VisitDataType { 6 | x: string; 7 | y: number; 8 | } 9 | 10 | export type SearchDataType = { 11 | index: number; 12 | keyword: string; 13 | count: number; 14 | range: number; 15 | status: number; 16 | }; 17 | 18 | export type OfflineDataType = { 19 | name: string; 20 | cvr: number; 21 | }; 22 | 23 | export interface OfflineChartData { 24 | date: number; 25 | type: number; 26 | value: number; 27 | } 28 | 29 | export type RadarData = { 30 | name: string; 31 | label: string; 32 | value: number; 33 | }; 34 | 35 | export interface AnalysisData { 36 | visitData: DataItem[]; 37 | visitData2: DataItem[]; 38 | salesData: DataItem[]; 39 | searchData: DataItem[]; 40 | offlineData: OfflineDataType[]; 41 | offlineChartData: DataItem[]; 42 | salesTypeData: DataItem[]; 43 | salesTypeDataOnline: DataItem[]; 44 | salesTypeDataOffline: DataItem[]; 45 | radarData: RadarData[]; 46 | } 47 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/dashboard/analysis/service.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@umijs/max'; 2 | import type { AnalysisData } from './data'; 3 | 4 | export async function fakeChartData(): Promise<{ data: AnalysisData }> { 5 | return request('/api/fake_analysis_chart_data'); 6 | } 7 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/dashboard/analysis/utils/Yuan.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { yuan } from '../components/Charts'; 3 | /** 减少使用 dangerouslySetInnerHTML */ 4 | export default class Yuan extends React.Component<{ 5 | children: React.ReactText; 6 | }> { 7 | main: HTMLSpanElement | undefined | null = null; 8 | 9 | componentDidMount() { 10 | this.renderToHtml(); 11 | } 12 | 13 | componentDidUpdate() { 14 | this.renderToHtml(); 15 | } 16 | 17 | renderToHtml = () => { 18 | const { children } = this.props; 19 | if (this.main) { 20 | this.main.innerHTML = yuan(children); 21 | } 22 | }; 23 | 24 | render() { 25 | return ( 26 | { 28 | this.main = ref; 29 | }} 30 | /> 31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/dashboard/monitor/_mock.ts: -------------------------------------------------------------------------------- 1 | import type { Request, Response } from 'express'; 2 | import mockjs from 'mockjs'; 3 | 4 | const getTags = (_: Request, res: Response) => { 5 | return res.json({ 6 | data: mockjs.mock({ 7 | 'list|100': [{ name: '@city', 'value|1-100': 150, 'type|0-2': 1 }], 8 | }), 9 | }); 10 | }; 11 | 12 | export default { 13 | 'GET /api/tags': getTags, 14 | }; 15 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/dashboard/monitor/components/ActiveChart/index.less: -------------------------------------------------------------------------------- 1 | .activeChart { 2 | position: relative; 3 | } 4 | .activeChartGrid { 5 | p { 6 | position: absolute; 7 | top: 80px; 8 | } 9 | p:last-child { 10 | top: 115px; 11 | } 12 | } 13 | .activeChartLegend { 14 | position: relative; 15 | height: 20px; 16 | margin-top: 8px; 17 | font-size: 0; 18 | line-height: 20px; 19 | span { 20 | display: inline-block; 21 | width: 33.33%; 22 | font-size: 12px; 23 | text-align: center; 24 | } 25 | span:first-child { 26 | text-align: left; 27 | } 28 | span:last-child { 29 | text-align: right; 30 | } 31 | } 32 | .dashedLine { 33 | position: relative; 34 | top: -70px; 35 | left: -3px; 36 | height: 1px; 37 | 38 | .line { 39 | position: absolute; 40 | top: 0; 41 | left: 0; 42 | width: 100%; 43 | height: 100%; 44 | background-image: linear-gradient(to right, transparent 50%, #e9e9e9 50%); 45 | background-size: 6px; 46 | } 47 | } 48 | 49 | .dashedLine:last-child { 50 | top: -36px; 51 | } 52 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/dashboard/monitor/data.d.ts: -------------------------------------------------------------------------------- 1 | export type TagType = { 2 | name: string; 3 | value: number; 4 | type: string; 5 | }; 6 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/dashboard/monitor/service.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@umijs/max'; 2 | import type { TagType } from './data'; 3 | 4 | export async function queryTags(): Promise<{ data: { list: TagType[] } }> { 5 | return request('/api/tags'); 6 | } 7 | -------------------------------------------------------------------------------- /frontend/src/antdesign/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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/dashboard/monitor/style.style.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from 'antd-style'; 2 | 3 | const useStyles = createStyles(({ token }) => { 4 | return { 5 | mapChart: { 6 | height: '452px', 7 | paddingTop: '24px', 8 | img: { display: 'inline-block', maxWidth: '100%', maxHeight: '437px' }, 9 | [`@media screen and (max-width: ${token.screenLG}px)`]: { 10 | height: 'auto', 11 | }, 12 | }, 13 | }; 14 | }); 15 | 16 | export default useStyles; 17 | -------------------------------------------------------------------------------- /frontend/src/antdesign/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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/dashboard/workplace/components/EditableLinkGroup/index.style.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from 'antd-style'; 2 | 3 | const useStyles = createStyles(({ token }) => { 4 | return { 5 | linkGroup: { 6 | padding: '20px 0 8px 24px', 7 | fontSize: '0', 8 | '& > a': { 9 | display: 'inline-block', 10 | width: '25%', 11 | marginBottom: '13px', 12 | color: token.colorText, 13 | fontSize: token.fontSize, 14 | '&:hover': { 15 | color: token.colorPrimary, 16 | }, 17 | }, 18 | }, 19 | }; 20 | }); 21 | 22 | export default useStyles; 23 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/dashboard/workplace/service.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@umijs/max'; 2 | import type { ActivitiesType, AnalysisData, NoticeType } from './data'; 3 | 4 | export async function queryProjectNotice(): Promise<{ data: NoticeType[] }> { 5 | return request('/api/project/notice'); 6 | } 7 | 8 | export async function queryActivities(): Promise<{ data: ActivitiesType[] }> { 9 | return request('/api/activities'); 10 | } 11 | 12 | export async function fakeChartData(): Promise<{ data: AnalysisData }> { 13 | return request('/api/fake_workplace_chart_data'); 14 | } 15 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/exception/403/index.tsx: -------------------------------------------------------------------------------- 1 | import { Link } from '@umijs/max'; 2 | import { Button, Result } from 'antd'; 3 | 4 | export default () => ( 5 | 11 | 12 | 13 | } 14 | /> 15 | ); 16 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/exception/404/index.tsx: -------------------------------------------------------------------------------- 1 | import { Link } from '@umijs/max'; 2 | import { Button, Result } from 'antd'; 3 | 4 | export default () => ( 5 | 11 | 12 | 13 | } 14 | /> 15 | ); 16 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/exception/500/index.tsx: -------------------------------------------------------------------------------- 1 | import { Link } from '@umijs/max'; 2 | import { Button, Result } from 'antd'; 3 | 4 | export default () => ( 5 | 11 | 12 | 13 | } 14 | /> 15 | ); 16 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/form/advanced-form/_mock.ts: -------------------------------------------------------------------------------- 1 | import type { Request, Response } from 'express'; 2 | 3 | export default { 4 | 'POST /api/advancedForm': (_: Request, res: Response) => { 5 | res.send({ data: { message: 'Ok' } }); 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/form/advanced-form/service.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@umijs/max'; 2 | 3 | export async function fakeSubmitForm(params: any) { 4 | return request('/api/advancedForm', { 5 | method: 'POST', 6 | data: params, 7 | }); 8 | } 9 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/form/basic-form/_mock.ts: -------------------------------------------------------------------------------- 1 | import type { Request, Response } from 'express'; 2 | 3 | export default { 4 | 'POST /api/basicForm': (_: Request, res: Response) => { 5 | res.send({ data: { message: 'Ok' } }); 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/form/basic-form/service.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@umijs/max'; 2 | 3 | export async function fakeSubmitForm(params: any) { 4 | return request('/api/basicForm', { 5 | method: 'POST', 6 | data: params, 7 | }); 8 | } 9 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/form/basic-form/style.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .optional { 4 | color: @text-color-secondary; 5 | font-style: normal; 6 | } 7 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/form/basic-form/style.style.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from 'antd-style'; 2 | 3 | const useStyles = createStyles(({ token }) => { 4 | return { 5 | optional: { 6 | color: token.colorTextSecondary, 7 | fontStyle: 'normal', 8 | }, 9 | }; 10 | }); 11 | 12 | export default useStyles; 13 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/form/step-form/_mock.ts: -------------------------------------------------------------------------------- 1 | import type { Request, Response } from 'express'; 2 | 3 | export default { 4 | 'POST /api/stepForm': (_: Request, res: Response) => { 5 | res.send({ data: { message: 'Ok' } }); 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/form/step-form/data.d.ts: -------------------------------------------------------------------------------- 1 | export interface StepDataType { 2 | payAccount: string; 3 | receiverAccount: string; 4 | receiverName: string; 5 | amount: string; 6 | receiverMode: string; 7 | } 8 | 9 | export type CurrentTypes = 'base' | 'confirm' | 'result'; 10 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/form/step-form/service.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@umijs/max'; 2 | 3 | export async function fakeSubmitForm(params: any) { 4 | return request('/api/stepForm', { 5 | method: 'POST', 6 | data: params, 7 | }); 8 | } 9 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/form/step-form/style.less: -------------------------------------------------------------------------------- 1 | @import '~antd/es/style/themes/default.less'; 2 | 3 | .card { 4 | margin-bottom: 24px; 5 | } 6 | 7 | .result { 8 | max-width: 560px; 9 | margin: 0 auto; 10 | padding: 24px 0 8px; 11 | } 12 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/form/step-form/style.style.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from 'antd-style'; 2 | 3 | const useStyles = createStyles(() => { 4 | return { 5 | card: { 6 | marginBottom: '24px', 7 | }, 8 | result: { 9 | maxWidth: '560px', 10 | margin: '0 auto', 11 | padding: '24px 0 8px', 12 | }, 13 | }; 14 | }); 15 | export default useStyles; 16 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/list/basic-list/data.d.ts: -------------------------------------------------------------------------------- 1 | export type Member = { 2 | avatar: string; 3 | name: string; 4 | id: string; 5 | }; 6 | 7 | export type 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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/list/basic-list/utils/utils.style.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from 'antd-style'; 2 | 3 | const useStyles = createStyles(() => { 4 | return {}; 5 | }); 6 | export default useStyles; 7 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/list/card-list/data.d.ts: -------------------------------------------------------------------------------- 1 | export type Member = { 2 | avatar: string; 3 | name: string; 4 | id: string; 5 | }; 6 | 7 | export type 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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/list/card-list/service.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@umijs/max'; 2 | import type { CardListItemDataType } from './data.d'; 3 | 4 | export async function queryFakeList(params: { 5 | count: number; 6 | }): Promise<{ data: { list: CardListItemDataType[] } }> { 7 | return request('/api/card_fake_list', { 8 | params, 9 | }); 10 | } 11 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/list/card-list/utils/utils.style.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from 'antd-style'; 2 | 3 | const useStyles = createStyles(() => { 4 | return {}; 5 | }); 6 | export default useStyles; 7 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/list/mock/index.ts: -------------------------------------------------------------------------------- 1 | import { DefaultOptionType } from 'antd/es/select'; 2 | 3 | export const categoryOptions: DefaultOptionType[] = Array.from({ length: 12 }).map((_, index) => ({ 4 | value: `cat${index + 1}`, 5 | label: `类目${index + 1}`, 6 | })); 7 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/list/search/applications/components/StandardFormRow/index.tsx: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | import useStyles from './index.style'; 4 | type StandardFormRowProps = { 5 | title?: string; 6 | last?: boolean; 7 | block?: boolean; 8 | grid?: boolean; 9 | style?: React.CSSProperties; 10 | children?: React.ReactNode; 11 | }; 12 | const StandardFormRow: React.FC = ({ 13 | title, 14 | children, 15 | last, 16 | block, 17 | grid, 18 | ...rest 19 | }) => { 20 | const { styles } = useStyles(); 21 | const cls = classNames(styles.standardFormRow, { 22 | [styles.standardFormRowBlock]: block, 23 | [styles.standardFormRowLast]: last, 24 | [styles.standardFormRowGrid]: grid, 25 | }); 26 | return ( 27 |
28 | {title && ( 29 |
30 | {title} 31 |
32 | )} 33 |
{children}
34 |
35 | ); 36 | }; 37 | export default StandardFormRow; 38 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/list/search/applications/components/TagSelect/index.style.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from 'antd-style'; 2 | 3 | const useStyles = createStyles(({ token }) => { 4 | return { 5 | tagSelect: { 6 | position: 'relative', 7 | maxHeight: '32px', 8 | marginLeft: '-8px', 9 | overflow: 'hidden', 10 | lineHeight: '32px', 11 | transition: 'all 0.3s', 12 | userSelect: 'none', 13 | '.ant-tag': { 14 | marginRight: '24px', 15 | padding: '0 8px', 16 | fontSize: token.fontSize, 17 | }, 18 | }, 19 | trigger: { 20 | position: 'absolute', 21 | top: '0', 22 | right: '0', 23 | 'span.anticon': { fontSize: '12px' }, 24 | }, 25 | expanded: { 26 | maxHeight: '200px', 27 | transition: 'all 0.3s', 28 | }, 29 | hasExpandTag: { 30 | paddingRight: '50px', 31 | }, 32 | }; 33 | }); 34 | 35 | export default useStyles; 36 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/list/search/applications/data.d.ts: -------------------------------------------------------------------------------- 1 | export type Member = { 2 | avatar: string; 3 | name: string; 4 | id: string; 5 | }; 6 | 7 | export interface Params { 8 | count: number; 9 | } 10 | 11 | export interface ListItemDataType { 12 | id: string; 13 | owner: string; 14 | title: string; 15 | avatar: string; 16 | cover: string; 17 | status: 'normal' | 'exception' | 'active' | 'success'; 18 | percent: number; 19 | logo: string; 20 | href: string; 21 | body?: any; 22 | updatedAt: number; 23 | createdAt: number; 24 | subDescription: string; 25 | description: string; 26 | activeUser: number; 27 | newUser: number; 28 | star: number; 29 | like: number; 30 | message: number; 31 | content: string; 32 | members: Member[]; 33 | } 34 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/list/search/applications/service.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@umijs/max'; 2 | import type { ListItemDataType, Params } from './data.d'; 3 | 4 | export async function queryFakeList( 5 | params: Params, 6 | ): Promise<{ data: { list: ListItemDataType[] } }> { 7 | return request('/api/fake_list', { 8 | params, 9 | }); 10 | } 11 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/list/search/applications/utils/utils.style.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from 'antd-style'; 2 | 3 | const useStyles = createStyles(() => { 4 | return {}; 5 | }); 6 | export default useStyles; 7 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/list/search/articles/components/ArticleListContent/index.style.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from 'antd-style'; 2 | 3 | const useStyles = createStyles(({ token }) => { 4 | return { 5 | description: { 6 | maxWidth: '720px', 7 | lineHeight: '22px', 8 | }, 9 | extra: { 10 | marginTop: '16px', 11 | color: token.colorTextSecondary, 12 | lineHeight: '22px', 13 | '& > em': { 14 | marginLeft: '16px', 15 | color: token.colorTextDisabled, 16 | fontStyle: 'normal', 17 | }, 18 | [`@media screen and (max-width: ${token.screenXS}px)`]: { 19 | '& > em': { 20 | display: 'block', 21 | marginTop: '8px', 22 | marginLeft: '0', 23 | }, 24 | }, 25 | }, 26 | }; 27 | }); 28 | 29 | export default useStyles; 30 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/list/search/articles/components/ArticleListContent/index.tsx: -------------------------------------------------------------------------------- 1 | import { Avatar } from 'antd'; 2 | import dayjs from 'dayjs'; 3 | import React from 'react'; 4 | import useStyles from './index.style'; 5 | type ArticleListContentProps = { 6 | data: { 7 | content: React.ReactNode; 8 | updatedAt: number; 9 | avatar: string; 10 | owner: string; 11 | href: string; 12 | }; 13 | }; 14 | const ArticleListContent: React.FC = ({ 15 | data: { content, updatedAt, avatar, owner, href }, 16 | }) => { 17 | const { styles } = useStyles(); 18 | return ( 19 |
20 |
{content}
21 |
22 | 23 | {owner} 发布在 {href} 24 | {dayjs(updatedAt).format('YYYY-MM-DD HH:mm')} 25 |
26 |
27 | ); 28 | }; 29 | export default ArticleListContent; 30 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/list/search/articles/components/StandardFormRow/index.tsx: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | import useStyles from './index.style'; 4 | type StandardFormRowProps = { 5 | title?: string; 6 | last?: boolean; 7 | block?: boolean; 8 | grid?: boolean; 9 | children?: React.ReactNode; 10 | style?: React.CSSProperties; 11 | }; 12 | const StandardFormRow: React.FC = ({ 13 | title, 14 | children, 15 | last, 16 | block, 17 | grid, 18 | ...rest 19 | }) => { 20 | const { styles } = useStyles(); 21 | const cls = classNames(styles.standardFormRow, { 22 | [styles.standardFormRowBlock]: block, 23 | [styles.standardFormRowLast]: last, 24 | [styles.standardFormRowGrid]: grid, 25 | }); 26 | return ( 27 |
28 | {title && ( 29 |
30 | {title} 31 |
32 | )} 33 |
{children}
34 |
35 | ); 36 | }; 37 | export default StandardFormRow; 38 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/list/search/articles/components/TagSelect/index.style.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from 'antd-style'; 2 | 3 | const useStyles = createStyles(({ token }) => { 4 | return { 5 | tagSelect: { 6 | position: 'relative', 7 | maxHeight: '32px', 8 | marginLeft: '-8px', 9 | overflow: 'hidden', 10 | lineHeight: '32px', 11 | transition: 'all 0.3s', 12 | userSelect: 'none', 13 | '.ant-tag': { 14 | marginRight: '24px', 15 | padding: '0 8px', 16 | fontSize: token.fontSize, 17 | }, 18 | }, 19 | trigger: { 20 | position: 'absolute', 21 | top: '0', 22 | right: '0', 23 | 'span.anticon': { fontSize: '12px' }, 24 | }, 25 | expanded: { 26 | maxHeight: '200px', 27 | transition: 'all 0.3s', 28 | }, 29 | hasExpandTag: { 30 | paddingRight: '50px', 31 | }, 32 | }; 33 | }); 34 | 35 | export default useStyles; 36 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/list/search/articles/data.d.ts: -------------------------------------------------------------------------------- 1 | export type Member = { 2 | avatar: string; 3 | name: string; 4 | id: string; 5 | }; 6 | 7 | export interface Params { 8 | count: number; 9 | } 10 | export interface ListItemDataType { 11 | id: string; 12 | owner: string; 13 | title: string; 14 | avatar: string; 15 | cover: string; 16 | status: 'normal' | 'exception' | 'active' | 'success'; 17 | percent: number; 18 | logo: string; 19 | href: string; 20 | body?: any; 21 | updatedAt: number; 22 | createdAt: number; 23 | subDescription: string; 24 | description: string; 25 | activeUser: number; 26 | newUser: number; 27 | star: number; 28 | like: number; 29 | message: number; 30 | content: string; 31 | members: Member[]; 32 | } 33 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/list/search/articles/service.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@umijs/max'; 2 | import type { ListItemDataType, Params } from './data.d'; 3 | 4 | export async function queryFakeList( 5 | params: Params, 6 | ): Promise<{ data: { list: ListItemDataType[] } }> { 7 | return request('/api/fake_list', { 8 | params, 9 | }); 10 | } 11 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/list/search/articles/style.style.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from 'antd-style'; 2 | 3 | const useStyles = createStyles(({ token }) => { 4 | return { 5 | listItemMetaTitle: { 6 | color: token.colorTextHeading, 7 | }, 8 | listItemExtra: { 9 | width: '272px', 10 | height: '1px', 11 | [`@media screen and (max-width: ${token.screenLG}px)`]: { 12 | width: '0', 13 | height: '1px', 14 | }, 15 | }, 16 | selfTrigger: { 17 | marginLeft: '12px', 18 | [`@media screen and (max-width: ${token.screenXS}px)`]: { 19 | display: 'block', 20 | marginLeft: '0', 21 | }, 22 | [`@media screen and (max-width: ${token.screenMD}px)`]: { 23 | display: 'block', 24 | marginLeft: '0', 25 | }, 26 | }, 27 | }; 28 | }); 29 | 30 | export default useStyles; 31 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/list/search/projects/components/StandardFormRow/index.tsx: -------------------------------------------------------------------------------- 1 | import classNames from 'classnames'; 2 | import React from 'react'; 3 | import useStyles from './index.style'; 4 | type StandardFormRowProps = { 5 | title?: string; 6 | last?: boolean; 7 | block?: boolean; 8 | grid?: boolean; 9 | children?: React.ReactNode; 10 | style?: React.CSSProperties; 11 | }; 12 | const StandardFormRow: React.FC = ({ 13 | title, 14 | children, 15 | last, 16 | block, 17 | grid, 18 | ...rest 19 | }) => { 20 | const { styles } = useStyles(); 21 | const cls = classNames(styles.standardFormRow, { 22 | [styles.standardFormRowBlock]: block, 23 | [styles.standardFormRowLast]: last, 24 | [styles.standardFormRowGrid]: grid, 25 | }); 26 | return ( 27 |
28 | {title && ( 29 |
30 | {title} 31 |
32 | )} 33 |
{children}
34 |
35 | ); 36 | }; 37 | export default StandardFormRow; 38 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/list/search/projects/components/TagSelect/index.style.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from 'antd-style'; 2 | 3 | const useStyles = createStyles(({ token }) => { 4 | return { 5 | tagSelect: { 6 | position: 'relative', 7 | maxHeight: '32px', 8 | marginLeft: '-8px', 9 | overflow: 'hidden', 10 | lineHeight: '32px', 11 | transition: 'all 0.3s', 12 | userSelect: 'none', 13 | '.ant-tag': { 14 | marginRight: '24px', 15 | padding: '0 8px', 16 | fontSize: token.fontSize, 17 | }, 18 | }, 19 | trigger: { 20 | position: 'absolute', 21 | top: '0', 22 | right: '0', 23 | 'span.anticon': { fontSize: '12px' }, 24 | }, 25 | expanded: { 26 | maxHeight: '200px', 27 | transition: 'all 0.3s', 28 | }, 29 | hasExpandTag: { 30 | paddingRight: '50px', 31 | }, 32 | }; 33 | }); 34 | 35 | export default useStyles; 36 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/list/search/projects/data.d.ts: -------------------------------------------------------------------------------- 1 | export type Member = { 2 | avatar: string; 3 | name: string; 4 | id: string; 5 | }; 6 | 7 | export interface Params { 8 | count: number; 9 | } 10 | export interface ListItemDataType { 11 | id: string; 12 | owner: string; 13 | title: string; 14 | avatar: string; 15 | cover: string; 16 | status: 'normal' | 'exception' | 'active' | 'success'; 17 | percent: number; 18 | logo: string; 19 | href: string; 20 | body?: any; 21 | updatedAt: number; 22 | createdAt: number; 23 | subDescription: string; 24 | description: string; 25 | activeUser: number; 26 | newUser: number; 27 | star: number; 28 | like: number; 29 | message: number; 30 | content: string; 31 | members: Member[]; 32 | } 33 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/list/search/projects/service.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@umijs/max'; 2 | import type { ListItemDataType, Params } from './data'; 3 | 4 | export async function queryFakeList( 5 | params: Params, 6 | ): Promise<{ data: { list: ListItemDataType[] } }> { 7 | return request('/api/fake_list', { 8 | params, 9 | }); 10 | } 11 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/list/table-list/components/CreateForm.tsx: -------------------------------------------------------------------------------- 1 | import { Modal } from 'antd'; 2 | import React from 'react'; 3 | 4 | type CreateFormProps = { 5 | modalVisible: boolean; 6 | children?: React.ReactNode; 7 | onCancel: () => void; 8 | }; 9 | 10 | const CreateForm: React.FC = (props) => { 11 | const { modalVisible, onCancel } = props; 12 | 13 | return ( 14 | onCancel()} 19 | footer={null} 20 | > 21 | {props.children} 22 | 23 | ); 24 | }; 25 | 26 | export default CreateForm; 27 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/list/table-list/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: string; 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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/profile/advanced/data.d.ts: -------------------------------------------------------------------------------- 1 | export type AdvancedOperation1 = { 2 | key: string; 3 | type: string; 4 | name: string; 5 | status: string; 6 | updatedAt: string; 7 | memo: string; 8 | }; 9 | 10 | export type AdvancedOperation2 = { 11 | key: string; 12 | type: string; 13 | name: string; 14 | status: string; 15 | updatedAt: string; 16 | memo: string; 17 | }; 18 | 19 | export type 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 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/profile/advanced/service.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@umijs/max'; 2 | 3 | export async function queryAdvancedProfile() { 4 | return request('/api/profile/advanced'); 5 | } 6 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/profile/basic/data.d.ts: -------------------------------------------------------------------------------- 1 | export type 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 type BasicProgress = { 11 | key: string; 12 | time: string; 13 | rate: string; 14 | status: string; 15 | operator: string; 16 | cost: string; 17 | }; 18 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/profile/basic/service.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@umijs/max'; 2 | import type { BasicGood, BasicProgress } from './data.d'; 3 | 4 | export async function queryBasicProfile(): Promise<{ 5 | data: { 6 | basicProgress: BasicProgress[]; 7 | basicGoods: BasicGood[]; 8 | }; 9 | }> { 10 | return request('/api/profile/basic'); 11 | } 12 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/profile/basic/style.style.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from 'antd-style'; 2 | 3 | const useStyles = createStyles(({ token }) => { 4 | return { 5 | title: { 6 | marginBottom: '16px', 7 | color: token.colorTextHeading, 8 | fontWeight: '500', 9 | fontSize: '16px', 10 | }, 11 | }; 12 | }); 13 | 14 | export default useStyles; 15 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/result/fail/index.style.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from 'antd-style'; 2 | 3 | const useStyles = createStyles(({ token }) => { 4 | return { 5 | error_icon: { 6 | color: token.colorBgTextActive, 7 | }, 8 | title: { 9 | marginBottom: '16px', 10 | color: token.colorTextHeading, 11 | fontWeight: '500', 12 | fontSize: '16px', 13 | }, 14 | }; 15 | }); 16 | 17 | export default useStyles; 18 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/result/success/index.style.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from 'antd-style'; 2 | 3 | const useStyles = createStyles(({ token }) => { 4 | return { 5 | title: { 6 | position: 'relative', 7 | color: token.colorText, 8 | fontSize: '12px', 9 | textAlign: 'center', 10 | }, 11 | 'head-title': { 12 | marginBottom: '20px', 13 | color: token.colorTextHeading, 14 | fontWeight: '500px', 15 | fontSize: '16px', 16 | }, 17 | }; 18 | }); 19 | 20 | export default useStyles; 21 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/user/register-result/style.style.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from 'antd-style'; 2 | 3 | const useStyles = createStyles(() => { 4 | return { 5 | registerResult: { 6 | width: '800px', 7 | minHeight: '400px', 8 | margin: 'auto', 9 | padding: '80px', 10 | background: 'none', 11 | }, 12 | anticon: { 13 | fontSize: '64px', 14 | }, 15 | title: { 16 | marginTop: '32px', 17 | fontSize: '20px', 18 | lineHeight: '28px', 19 | }, 20 | actions: { 21 | marginTop: '40px', 22 | 'a + a': { marginLeft: '8px' }, 23 | }, 24 | }; 25 | }); 26 | export default useStyles; 27 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/user/register/_mock.ts: -------------------------------------------------------------------------------- 1 | import type { Request, Response } from 'express'; 2 | 3 | export default { 4 | 'POST /api/register': (_: Request, res: Response) => { 5 | res.send({ 6 | data: { status: 'ok', currentAuthority: 'user' }, 7 | }); 8 | }, 9 | }; 10 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/pages/user/register/service.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@umijs/max'; 2 | 3 | export interface StateType { 4 | status?: 'ok' | 'error'; 5 | currentAuthority?: 'user' | 'guest' | 'admin'; 6 | } 7 | 8 | export interface UserRegisterParams { 9 | mail: string; 10 | password: string; 11 | confirm: string; 12 | mobile: string; 13 | captcha: string; 14 | prefix: string; 15 | } 16 | 17 | export async function fakeRegister(params: UserRegisterParams) { 18 | return request('/api/register', { 19 | method: 'POST', 20 | data: params, 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/services/ant-design-pro/index.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | /* eslint-disable */ 3 | // API 更新时间: 4 | // API 唯一标识: 5 | import * as api from './api'; 6 | import * as login from './login'; 7 | export default { 8 | api, 9 | login, 10 | }; 11 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/services/ant-design-pro/login.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | /* eslint-disable */ 3 | import { request } from '@umijs/max'; 4 | 5 | /** 发送验证码 POST /api/login/captcha */ 6 | export async function getFakeCaptcha( 7 | params: { 8 | // query 9 | /** 手机号 */ 10 | phone?: string; 11 | }, 12 | options?: { [key: string]: any }, 13 | ) { 14 | return request('/api/login/captcha', { 15 | method: 'GET', 16 | params: { 17 | ...params, 18 | }, 19 | ...(options || {}), 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/services/swagger/index.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | /* eslint-disable */ 3 | // API 更新时间: 4 | // API 唯一标识: 5 | import * as pet from './pet'; 6 | import * as store from './store'; 7 | import * as user from './user'; 8 | export default { 9 | pet, 10 | store, 11 | user, 12 | }; 13 | -------------------------------------------------------------------------------- /frontend/src/antdesign/src/typings.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'slash2'; 2 | declare module '*.css'; 3 | declare module '*.less'; 4 | declare module '*.scss'; 5 | declare module '*.sass'; 6 | declare module '*.svg'; 7 | declare module '*.png'; 8 | declare module '*.jpg'; 9 | declare module '*.jpeg'; 10 | declare module '*.gif'; 11 | declare module '*.bmp'; 12 | declare module '*.tiff'; 13 | declare module 'omit.js'; 14 | declare module 'numeral'; 15 | declare module 'mockjs'; 16 | declare module 'react-fittext'; 17 | 18 | declare const REACT_APP_ENV: 'test' | 'dev' | 'pre' | false; 19 | -------------------------------------------------------------------------------- /frontend/src/antdesign/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": "./", 4 | "target": "esnext", 5 | "moduleResolution": "node", 6 | "jsx": "react-jsx", 7 | "esModuleInterop": true, 8 | "experimentalDecorators": true, 9 | "strict": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "noImplicitReturns": true, 12 | "suppressImplicitAnyIndexErrors": true, 13 | "declaration": true, 14 | "skipLibCheck": true, 15 | "resolveJsonModule": true, 16 | "paths": { 17 | "@/*": ["./src/*"], 18 | "@@/*": ["./src/.umi/*"], 19 | "@@test/*": ["./src/.umi-test/*"] 20 | } 21 | }, 22 | "include": ["./**/*.d.ts", "./**/*.ts", "./**/*.tsx"] 23 | } 24 | -------------------------------------------------------------------------------- /frontend/src/antdesign/types/cache/cache.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /frontend/src/antdesign/types/cache/mock/mock.cache.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/antdesign/types/cache/mock/mock.cache.js -------------------------------------------------------------------------------- /frontend/src/element/.editorconfig: -------------------------------------------------------------------------------- 1 | # https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | end_of_line = lf 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | [*.md] 13 | insert_final_newline = false 14 | trim_trailing_whitespace = false 15 | -------------------------------------------------------------------------------- /frontend/src/element/.env.development: -------------------------------------------------------------------------------- 1 | # just a flag 2 | ENV = 'development' 3 | 4 | # base api 5 | VUE_APP_BASE_API = '/dev-api' 6 | -------------------------------------------------------------------------------- /frontend/src/element/.env.production: -------------------------------------------------------------------------------- 1 | # just a flag 2 | ENV = 'production' 3 | 4 | # base api 5 | VUE_APP_BASE_API = '/prod-api' 6 | 7 | -------------------------------------------------------------------------------- /frontend/src/element/.env.staging: -------------------------------------------------------------------------------- 1 | NODE_ENV = production 2 | 3 | # just a flag 4 | ENV = 'staging' 5 | 6 | # base api 7 | VUE_APP_BASE_API = '/stage-api' 8 | 9 | -------------------------------------------------------------------------------- /frontend/src/element/.eslintignore: -------------------------------------------------------------------------------- 1 | build/*.js 2 | src/assets 3 | public 4 | dist 5 | -------------------------------------------------------------------------------- /frontend/src/element/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | **/*.log 8 | 9 | tests/**/coverage/ 10 | tests/e2e/reports 11 | selenium-debug.log 12 | 13 | # Editor directories and files 14 | .idea 15 | .vscode 16 | *.suo 17 | *.ntvs* 18 | *.njsproj 19 | *.sln 20 | *.local 21 | 22 | package-lock.json 23 | yarn.lock 24 | -------------------------------------------------------------------------------- /frontend/src/element/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 10 3 | script: npm run test 4 | notifications: 5 | email: false 6 | -------------------------------------------------------------------------------- /frontend/src/element/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | // https://github.com/vuejs/vue-cli/tree/master/packages/@vue/babel-preset-app 4 | '@vue/cli-plugin-babel/preset' 5 | ], 6 | 'env': { 7 | 'development': { 8 | // babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require(). 9 | // This plugin can significantly increase the speed of hot updates, when you have a large number of pages. 10 | // https://panjiachen.github.io/vue-element-admin-site/guide/advanced/lazy-loading.html 11 | 'plugins': ['dynamic-import-node'] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /frontend/src/element/build/index.js: -------------------------------------------------------------------------------- 1 | const { run } = require('runjs') 2 | const chalk = require('chalk') 3 | const config = require('../vue.config.js') 4 | const rawArgv = process.argv.slice(2) 5 | const args = rawArgv.join(' ') 6 | 7 | if (process.env.npm_config_preview || rawArgv.includes('--preview')) { 8 | const report = rawArgv.includes('--report') 9 | 10 | run(`vue-cli-service build ${args}`) 11 | 12 | const port = 9526 13 | const publicPath = config.publicPath 14 | 15 | var connect = require('connect') 16 | var serveStatic = require('serve-static') 17 | const app = connect() 18 | 19 | app.use( 20 | publicPath, 21 | serveStatic('./dist', { 22 | index: ['index.html', '/'] 23 | }) 24 | ) 25 | 26 | app.listen(port, function () { 27 | console.log(chalk.green(`> Preview at http://localhost:${port}${publicPath}`)) 28 | if (report) { 29 | console.log(chalk.green(`> Report at http://localhost:${port}${publicPath}report.html`)) 30 | } 31 | 32 | }) 33 | } else { 34 | run(`vue-cli-service build ${args}`) 35 | } 36 | -------------------------------------------------------------------------------- /frontend/src/element/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleFileExtensions: ['js', 'jsx', 'json', 'vue'], 3 | transform: { 4 | '^.+\\.vue$': 'vue-jest', 5 | '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 6 | 'jest-transform-stub', 7 | '^.+\\.jsx?$': 'babel-jest' 8 | }, 9 | moduleNameMapper: { 10 | '^@/(.*)$': '/src/$1' 11 | }, 12 | snapshotSerializers: ['jest-serializer-vue'], 13 | testMatch: [ 14 | '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)' 15 | ], 16 | collectCoverageFrom: ['src/utils/**/*.{js,vue}', '!src/utils/auth.js', '!src/utils/request.js', 'src/components/**/*.{js,vue}'], 17 | coverageDirectory: '/tests/unit/coverage', 18 | // 'collectCoverage': true, 19 | 'coverageReporters': [ 20 | 'lcov', 21 | 'text-summary' 22 | ], 23 | testURL: 'http://localhost/' 24 | } 25 | -------------------------------------------------------------------------------- /frontend/src/element/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": "./", 4 | "paths": { 5 | "@/*": ["src/*"] 6 | } 7 | }, 8 | "exclude": ["node_modules", "dist"] 9 | } -------------------------------------------------------------------------------- /frontend/src/element/plop-templates/component/index.hbs: -------------------------------------------------------------------------------- 1 | {{#if template}} 2 | 5 | {{/if}} 6 | 7 | {{#if script}} 8 | 20 | {{/if}} 21 | 22 | {{#if style}} 23 | 26 | {{/if}} 27 | -------------------------------------------------------------------------------- /frontend/src/element/plop-templates/store/index.hbs: -------------------------------------------------------------------------------- 1 | {{#if state}} 2 | const state = {} 3 | {{/if}} 4 | 5 | {{#if mutations}} 6 | const mutations = {} 7 | {{/if}} 8 | 9 | {{#if actions}} 10 | const actions = {} 11 | {{/if}} 12 | 13 | export default { 14 | namespaced: true, 15 | {{options}} 16 | } 17 | -------------------------------------------------------------------------------- /frontend/src/element/plop-templates/utils.js: -------------------------------------------------------------------------------- 1 | exports.notEmpty = name => v => 2 | !v || v.trim() === '' ? `${name} is required` : true 3 | -------------------------------------------------------------------------------- /frontend/src/element/plop-templates/view/index.hbs: -------------------------------------------------------------------------------- 1 | {{#if template}} 2 | 5 | {{/if}} 6 | 7 | {{#if script}} 8 | 20 | {{/if}} 21 | 22 | {{#if style}} 23 | 26 | {{/if}} 27 | -------------------------------------------------------------------------------- /frontend/src/element/plopfile.js: -------------------------------------------------------------------------------- 1 | const viewGenerator = require('./plop-templates/view/prompt') 2 | const componentGenerator = require('./plop-templates/component/prompt') 3 | const storeGenerator = require('./plop-templates/store/prompt.js') 4 | 5 | module.exports = function(plop) { 6 | plop.setGenerator('view', viewGenerator) 7 | plop.setGenerator('component', componentGenerator) 8 | plop.setGenerator('store', storeGenerator) 9 | } 10 | -------------------------------------------------------------------------------- /frontend/src/element/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | autoprefixer: {} 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /frontend/src/element/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/element/public/favicon.ico -------------------------------------------------------------------------------- /frontend/src/element/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | <%= webpackConfig.name %> 10 | 11 | 12 |
13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /frontend/src/element/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /frontend/src/element/src/api/article.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | export function fetchList(query) { 4 | return request({ 5 | url: '/vue-element-admin/article/list', 6 | method: 'get', 7 | params: query 8 | }) 9 | } 10 | 11 | export function fetchArticle(id) { 12 | return request({ 13 | url: '/vue-element-admin/article/detail', 14 | method: 'get', 15 | params: { id } 16 | }) 17 | } 18 | 19 | export function fetchPv(pv) { 20 | return request({ 21 | url: '/vue-element-admin/article/pv', 22 | method: 'get', 23 | params: { pv } 24 | }) 25 | } 26 | 27 | export function createArticle(data) { 28 | return request({ 29 | url: '/vue-element-admin/article/create', 30 | method: 'post', 31 | data 32 | }) 33 | } 34 | 35 | export function updateArticle(data) { 36 | return request({ 37 | url: '/vue-element-admin/article/update', 38 | method: 'post', 39 | data 40 | }) 41 | } 42 | -------------------------------------------------------------------------------- /frontend/src/element/src/api/qiniu.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | export function getToken() { 4 | return request({ 5 | url: '/qiniu/upload/token', // 假地址 自行替换 6 | method: 'get' 7 | }) 8 | } 9 | -------------------------------------------------------------------------------- /frontend/src/element/src/api/remote-search.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | export function searchUser(name) { 4 | return request({ 5 | url: '/vue-element-admin/search/user', 6 | method: 'get', 7 | params: { name } 8 | }) 9 | } 10 | 11 | export function transactionList(query) { 12 | return request({ 13 | url: '/vue-element-admin/transaction/list', 14 | method: 'get', 15 | params: query 16 | }) 17 | } 18 | -------------------------------------------------------------------------------- /frontend/src/element/src/api/role.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | export function getRoutes() { 4 | return request({ 5 | url: '/vue-element-admin/routes', 6 | method: 'get' 7 | }) 8 | } 9 | 10 | export function getRoles() { 11 | return request({ 12 | url: '/vue-element-admin/roles', 13 | method: 'get' 14 | }) 15 | } 16 | 17 | export function addRole(data) { 18 | return request({ 19 | url: '/vue-element-admin/role', 20 | method: 'post', 21 | data 22 | }) 23 | } 24 | 25 | export function updateRole(id, data) { 26 | return request({ 27 | url: `/vue-element-admin/role/${id}`, 28 | method: 'put', 29 | data 30 | }) 31 | } 32 | 33 | export function deleteRole(id) { 34 | return request({ 35 | url: `/vue-element-admin/role/${id}`, 36 | method: 'delete' 37 | }) 38 | } 39 | -------------------------------------------------------------------------------- /frontend/src/element/src/api/user.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | export function login(data) { 4 | return request({ 5 | url: '/vue-element-admin/user/login', 6 | method: 'post', 7 | data 8 | }) 9 | } 10 | 11 | export function getInfo(token) { 12 | return request({ 13 | url: '/vue-element-admin/user/info', 14 | method: 'get', 15 | params: { token } 16 | }) 17 | } 18 | 19 | export function logout() { 20 | return request({ 21 | url: '/vue-element-admin/user/logout', 22 | method: 'post' 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /frontend/src/element/src/assets/401_images/401.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/element/src/assets/401_images/401.gif -------------------------------------------------------------------------------- /frontend/src/element/src/assets/404_images/404.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/element/src/assets/404_images/404.png -------------------------------------------------------------------------------- /frontend/src/element/src/assets/404_images/404_cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/element/src/assets/404_images/404_cloud.png -------------------------------------------------------------------------------- /frontend/src/element/src/assets/custom-theme/fonts/element-icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/element/src/assets/custom-theme/fonts/element-icons.ttf -------------------------------------------------------------------------------- /frontend/src/element/src/assets/custom-theme/fonts/element-icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/src/element/src/assets/custom-theme/fonts/element-icons.woff -------------------------------------------------------------------------------- /frontend/src/element/src/components/ImageCropper/utils/data2blob.js: -------------------------------------------------------------------------------- 1 | /** 2 | * database64文件格式转换为2进制 3 | * 4 | * @param {[String]} data dataURL 的格式为 “data:image/png;base64,****”,逗号之前都是一些说明性的文字,我们只需要逗号之后的就行了 5 | * @param {[String]} mime [description] 6 | * @return {[blob]} [description] 7 | */ 8 | export default function(data, mime) { 9 | data = data.split(',')[1] 10 | data = window.atob(data) 11 | var ia = new Uint8Array(data.length) 12 | for (var i = 0; i < data.length; i++) { 13 | ia[i] = data.charCodeAt(i) 14 | } 15 | // canvas.toDataURL 返回的默认格式就是 image/png 16 | return new Blob([ia], { 17 | type: mime 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /frontend/src/element/src/components/ImageCropper/utils/mimes.js: -------------------------------------------------------------------------------- 1 | export default { 2 | 'jpg': 'image/jpeg', 3 | 'png': 'image/png', 4 | 'gif': 'image/gif', 5 | 'svg': 'image/svg+xml', 6 | 'psd': 'image/photoshop' 7 | } 8 | -------------------------------------------------------------------------------- /frontend/src/element/src/components/MarkdownEditor/default-options.js: -------------------------------------------------------------------------------- 1 | // doc: https://nhnent.github.io/tui.editor/api/latest/ToastUIEditor.html#ToastUIEditor 2 | export default { 3 | minHeight: '200px', 4 | previewStyle: 'vertical', 5 | useCommandShortcut: true, 6 | useDefaultHTMLSanitizer: true, 7 | usageStatistics: false, 8 | hideModeSwitch: false, 9 | toolbarItems: [ 10 | 'heading', 11 | 'bold', 12 | 'italic', 13 | 'strike', 14 | 'divider', 15 | 'hr', 16 | 'quote', 17 | 'divider', 18 | 'ul', 19 | 'ol', 20 | 'task', 21 | 'indent', 22 | 'outdent', 23 | 'divider', 24 | 'table', 25 | 'image', 26 | 'link', 27 | 'divider', 28 | 'code', 29 | 'codeblock' 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /frontend/src/element/src/components/Tinymce/plugins.js: -------------------------------------------------------------------------------- 1 | // Any plugins you want to use has to be imported 2 | // Detail plugins list see https://www.tinymce.com/docs/plugins/ 3 | // Custom builds see https://www.tinymce.com/download/custom-builds/ 4 | 5 | const plugins = ['advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount'] 6 | 7 | export default plugins 8 | -------------------------------------------------------------------------------- /frontend/src/element/src/components/Tinymce/toolbar.js: -------------------------------------------------------------------------------- 1 | // Here is a list of the toolbar 2 | // Detail list see https://www.tinymce.com/docs/advanced/editor-control-identifiers/#toolbarcontrols 3 | 4 | const toolbar = ['searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote undo redo removeformat subscript superscript code codesample', 'hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen'] 5 | 6 | export default toolbar 7 | -------------------------------------------------------------------------------- /frontend/src/element/src/directive/clipboard/index.js: -------------------------------------------------------------------------------- 1 | import Clipboard from './clipboard' 2 | 3 | const install = function(Vue) { 4 | Vue.directive('Clipboard', Clipboard) 5 | } 6 | 7 | if (window.Vue) { 8 | window.clipboard = Clipboard 9 | Vue.use(install); // eslint-disable-line 10 | } 11 | 12 | Clipboard.install = install 13 | export default Clipboard 14 | -------------------------------------------------------------------------------- /frontend/src/element/src/directive/el-drag-dialog/index.js: -------------------------------------------------------------------------------- 1 | import drag from './drag' 2 | 3 | const install = function(Vue) { 4 | Vue.directive('el-drag-dialog', drag) 5 | } 6 | 7 | if (window.Vue) { 8 | window['el-drag-dialog'] = drag 9 | Vue.use(install); // eslint-disable-line 10 | } 11 | 12 | drag.install = install 13 | export default drag 14 | -------------------------------------------------------------------------------- /frontend/src/element/src/directive/el-table/index.js: -------------------------------------------------------------------------------- 1 | import adaptive from './adaptive' 2 | 3 | const install = function(Vue) { 4 | Vue.directive('el-height-adaptive-table', adaptive) 5 | } 6 | 7 | if (window.Vue) { 8 | window['el-height-adaptive-table'] = adaptive 9 | Vue.use(install); // eslint-disable-line 10 | } 11 | 12 | adaptive.install = install 13 | export default adaptive 14 | -------------------------------------------------------------------------------- /frontend/src/element/src/directive/permission/index.js: -------------------------------------------------------------------------------- 1 | import permission from './permission' 2 | 3 | const install = function(Vue) { 4 | Vue.directive('permission', permission) 5 | } 6 | 7 | if (window.Vue) { 8 | window['permission'] = permission 9 | Vue.use(install); // eslint-disable-line 10 | } 11 | 12 | permission.install = install 13 | export default permission 14 | -------------------------------------------------------------------------------- /frontend/src/element/src/directive/permission/permission.js: -------------------------------------------------------------------------------- 1 | import store from '@/store' 2 | 3 | function checkPermission(el, binding) { 4 | const { value } = binding 5 | const roles = store.getters && store.getters.roles 6 | 7 | if (value && value instanceof Array) { 8 | if (value.length > 0) { 9 | const permissionRoles = value 10 | 11 | const hasPermission = roles.some(role => { 12 | return permissionRoles.includes(role) 13 | }) 14 | 15 | if (!hasPermission) { 16 | el.parentNode && el.parentNode.removeChild(el) 17 | } 18 | } 19 | } else { 20 | throw new Error(`need roles! Like v-permission="['admin','editor']"`) 21 | } 22 | } 23 | 24 | export default { 25 | inserted(el, binding) { 26 | checkPermission(el, binding) 27 | }, 28 | update(el, binding) { 29 | checkPermission(el, binding) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /frontend/src/element/src/directive/waves/index.js: -------------------------------------------------------------------------------- 1 | import waves from './waves' 2 | 3 | const install = function(Vue) { 4 | Vue.directive('waves', waves) 5 | } 6 | 7 | if (window.Vue) { 8 | window.waves = waves 9 | Vue.use(install); // eslint-disable-line 10 | } 11 | 12 | waves.install = install 13 | export default waves 14 | -------------------------------------------------------------------------------- /frontend/src/element/src/directive/waves/waves.css: -------------------------------------------------------------------------------- 1 | .waves-ripple { 2 | position: absolute; 3 | border-radius: 100%; 4 | background-color: rgba(0, 0, 0, 0.15); 5 | background-clip: padding-box; 6 | pointer-events: none; 7 | -webkit-user-select: none; 8 | -moz-user-select: none; 9 | -ms-user-select: none; 10 | user-select: none; 11 | -webkit-transform: scale(0); 12 | -ms-transform: scale(0); 13 | transform: scale(0); 14 | opacity: 1; 15 | } 16 | 17 | .waves-ripple.z-active { 18 | opacity: 0; 19 | -webkit-transform: scale(2); 20 | -ms-transform: scale(2); 21 | transform: scale(2); 22 | -webkit-transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out; 23 | transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out; 24 | transition: opacity 1.2s ease-out, transform 0.6s ease-out; 25 | transition: opacity 1.2s ease-out, transform 0.6s ease-out, -webkit-transform 0.6s ease-out; 26 | } -------------------------------------------------------------------------------- /frontend/src/element/src/icons/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import SvgIcon from '@/components/SvgIcon'// svg component 3 | 4 | // register globally 5 | Vue.component('svg-icon', SvgIcon) 6 | 7 | const req = require.context('./svg', false, /\.svg$/) 8 | const requireAll = requireContext => requireContext.keys().map(requireContext) 9 | requireAll(req) 10 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/chart.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/clipboard.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/component.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/documentation.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/drag.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/edit.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/education.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/email.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/example.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/excel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/eye.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/fullscreen.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/guide.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/link.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/list.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/lock.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/message.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/money.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/nested.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/password.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/peoples.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/search.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/size.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/star.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/tab.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/table.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/theme.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/tree-table.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svg/user.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/element/src/icons/svgo.yml: -------------------------------------------------------------------------------- 1 | # replace default config 2 | 3 | # multipass: true 4 | # full: true 5 | 6 | plugins: 7 | 8 | # - name 9 | # 10 | # or: 11 | # - name: false 12 | # - name: true 13 | # 14 | # or: 15 | # - name: 16 | # param1: 1 17 | # param2: 2 18 | 19 | - removeAttrs: 20 | attrs: 21 | - 'fill' 22 | - 'fill-rule' 23 | -------------------------------------------------------------------------------- /frontend/src/element/src/layout/components/Sidebar/FixiOSBug.js: -------------------------------------------------------------------------------- 1 | export default { 2 | computed: { 3 | device() { 4 | return this.$store.state.app.device 5 | } 6 | }, 7 | mounted() { 8 | // In order to fix the click on menu on the ios device will trigger the mouseleave bug 9 | // https://github.com/PanJiaChen/vue-element-admin/issues/1135 10 | this.fixBugIniOS() 11 | }, 12 | methods: { 13 | fixBugIniOS() { 14 | const $subMenu = this.$refs.subMenu 15 | if ($subMenu) { 16 | const handleMouseleave = $subMenu.handleMouseleave 17 | $subMenu.handleMouseleave = (e) => { 18 | if (this.device === 'mobile') { 19 | return 20 | } 21 | handleMouseleave(e) 22 | } 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /frontend/src/element/src/layout/components/Sidebar/Item.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 42 | -------------------------------------------------------------------------------- /frontend/src/element/src/layout/components/Sidebar/Link.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 44 | -------------------------------------------------------------------------------- /frontend/src/element/src/layout/components/index.js: -------------------------------------------------------------------------------- 1 | export { default as AppMain } from './AppMain' 2 | export { default as Navbar } from './Navbar' 3 | export { default as Settings } from './Settings' 4 | export { default as Sidebar } from './Sidebar/index.vue' 5 | export { default as TagsView } from './TagsView/index.vue' 6 | -------------------------------------------------------------------------------- /frontend/src/element/src/router/modules/charts.js: -------------------------------------------------------------------------------- 1 | /** When your routing table is too long, you can split it into small modules**/ 2 | 3 | import Layout from '@/layout' 4 | 5 | const chartsRouter = { 6 | path: '/charts', 7 | component: Layout, 8 | redirect: 'noRedirect', 9 | name: 'Charts', 10 | meta: { 11 | title: 'Charts', 12 | icon: 'chart' 13 | }, 14 | children: [ 15 | { 16 | path: 'keyboard', 17 | component: () => import('@/views/charts/keyboard'), 18 | name: 'KeyboardChart', 19 | meta: { title: 'Keyboard Chart', noCache: true } 20 | }, 21 | { 22 | path: 'line', 23 | component: () => import('@/views/charts/line'), 24 | name: 'LineChart', 25 | meta: { title: 'Line Chart', noCache: true } 26 | }, 27 | { 28 | path: 'mix-chart', 29 | component: () => import('@/views/charts/mix-chart'), 30 | name: 'MixChart', 31 | meta: { title: 'Mix Chart', noCache: true } 32 | } 33 | ] 34 | } 35 | 36 | export default chartsRouter 37 | -------------------------------------------------------------------------------- /frontend/src/element/src/settings.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | title: 'Vue Element Admin', 3 | 4 | /** 5 | * @type {boolean} true | false 6 | * @description Whether show the settings right-panel 7 | */ 8 | showSettings: true, 9 | 10 | /** 11 | * @type {boolean} true | false 12 | * @description Whether need tagsView 13 | */ 14 | tagsView: true, 15 | 16 | /** 17 | * @type {boolean} true | false 18 | * @description Whether fix the header 19 | */ 20 | fixedHeader: false, 21 | 22 | /** 23 | * @type {boolean} true | false 24 | * @description Whether show the logo in sidebar 25 | */ 26 | sidebarLogo: false, 27 | 28 | /** 29 | * @type {string | array} 'production' | ['production', 'development'] 30 | * @description Need show err logs component. 31 | * The default is only used in the production env 32 | * If you want to also use it in dev, you can pass ['production', 'development'] 33 | */ 34 | errorLog: 'production' 35 | } 36 | -------------------------------------------------------------------------------- /frontend/src/element/src/store/getters.js: -------------------------------------------------------------------------------- 1 | const getters = { 2 | sidebar: state => state.app.sidebar, 3 | size: state => state.app.size, 4 | device: state => state.app.device, 5 | visitedViews: state => state.tagsView.visitedViews, 6 | cachedViews: state => state.tagsView.cachedViews, 7 | token: state => state.user.token, 8 | avatar: state => state.user.avatar, 9 | name: state => state.user.name, 10 | introduction: state => state.user.introduction, 11 | roles: state => state.user.roles, 12 | permission_routes: state => state.permission.routes, 13 | errorLogs: state => state.errorLog.logs 14 | } 15 | export default getters 16 | -------------------------------------------------------------------------------- /frontend/src/element/src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import getters from './getters' 4 | 5 | Vue.use(Vuex) 6 | 7 | // https://webpack.js.org/guides/dependency-management/#requirecontext 8 | const modulesFiles = require.context('./modules', true, /\.js$/) 9 | 10 | // you do not need `import app from './modules/app'` 11 | // it will auto require all vuex module from modules file 12 | const modules = modulesFiles.keys().reduce((modules, modulePath) => { 13 | // set './app.js' => 'app' 14 | const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1') 15 | const value = modulesFiles(modulePath) 16 | modules[moduleName] = value.default 17 | return modules 18 | }, {}) 19 | 20 | const store = new Vuex.Store({ 21 | modules, 22 | getters 23 | }) 24 | 25 | export default store 26 | -------------------------------------------------------------------------------- /frontend/src/element/src/store/modules/errorLog.js: -------------------------------------------------------------------------------- 1 | const state = { 2 | logs: [] 3 | } 4 | 5 | const mutations = { 6 | ADD_ERROR_LOG: (state, log) => { 7 | state.logs.push(log) 8 | }, 9 | CLEAR_ERROR_LOG: (state) => { 10 | state.logs.splice(0) 11 | } 12 | } 13 | 14 | const actions = { 15 | addErrorLog({ commit }, log) { 16 | commit('ADD_ERROR_LOG', log) 17 | }, 18 | clearErrorLog({ commit }) { 19 | commit('CLEAR_ERROR_LOG') 20 | } 21 | } 22 | 23 | export default { 24 | namespaced: true, 25 | state, 26 | mutations, 27 | actions 28 | } 29 | -------------------------------------------------------------------------------- /frontend/src/element/src/store/modules/settings.js: -------------------------------------------------------------------------------- 1 | import variables from '@/styles/element-variables.scss' 2 | import defaultSettings from '@/settings' 3 | 4 | const { showSettings, tagsView, fixedHeader, sidebarLogo } = defaultSettings 5 | 6 | const state = { 7 | theme: variables.theme, 8 | showSettings: showSettings, 9 | tagsView: tagsView, 10 | fixedHeader: fixedHeader, 11 | sidebarLogo: sidebarLogo 12 | } 13 | 14 | const mutations = { 15 | CHANGE_SETTING: (state, { key, value }) => { 16 | // eslint-disable-next-line no-prototype-builtins 17 | if (state.hasOwnProperty(key)) { 18 | state[key] = value 19 | } 20 | } 21 | } 22 | 23 | const actions = { 24 | changeSetting({ commit }, data) { 25 | commit('CHANGE_SETTING', data) 26 | } 27 | } 28 | 29 | export default { 30 | namespaced: true, 31 | state, 32 | mutations, 33 | actions 34 | } 35 | 36 | -------------------------------------------------------------------------------- /frontend/src/element/src/styles/element-variables.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * I think element-ui's default theme color is too light for long-term use. 3 | * So I modified the default color and you can modify it to your liking. 4 | **/ 5 | 6 | /* theme color */ 7 | $--color-primary: #1890ff; 8 | $--color-success: #13ce66; 9 | $--color-warning: #ffba00; 10 | $--color-danger: #ff4949; 11 | // $--color-info: #1E1E1E; 12 | 13 | $--button-font-weight: 400; 14 | 15 | // $--color-text-regular: #1f2d3d; 16 | 17 | $--border-color-light: #dfe4ed; 18 | $--border-color-lighter: #e6ebf5; 19 | 20 | $--table-border: 1px solid #dfe6ec; 21 | 22 | /* icon font path, required */ 23 | $--font-path: "~element-ui/lib/theme-chalk/fonts"; 24 | 25 | @import "~element-ui/packages/theme-chalk/src/index"; 26 | 27 | // the :export directive is the magic sauce for webpack 28 | // https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass 29 | :export { 30 | theme: $--color-primary; 31 | } 32 | -------------------------------------------------------------------------------- /frontend/src/element/src/styles/transition.scss: -------------------------------------------------------------------------------- 1 | // global transition css 2 | 3 | /* fade */ 4 | .fade-enter-active, 5 | .fade-leave-active { 6 | transition: opacity 0.28s; 7 | } 8 | 9 | .fade-enter, 10 | .fade-leave-active { 11 | opacity: 0; 12 | } 13 | 14 | /* fade-transform */ 15 | .fade-transform-leave-active, 16 | .fade-transform-enter-active { 17 | transition: all .5s; 18 | } 19 | 20 | .fade-transform-enter { 21 | opacity: 0; 22 | transform: translateX(-30px); 23 | } 24 | 25 | .fade-transform-leave-to { 26 | opacity: 0; 27 | transform: translateX(30px); 28 | } 29 | 30 | /* breadcrumb transition */ 31 | .breadcrumb-enter-active, 32 | .breadcrumb-leave-active { 33 | transition: all .5s; 34 | } 35 | 36 | .breadcrumb-enter, 37 | .breadcrumb-leave-active { 38 | opacity: 0; 39 | transform: translateX(20px); 40 | } 41 | 42 | .breadcrumb-move { 43 | transition: all .5s; 44 | } 45 | 46 | .breadcrumb-leave-active { 47 | position: absolute; 48 | } 49 | -------------------------------------------------------------------------------- /frontend/src/element/src/styles/variables.scss: -------------------------------------------------------------------------------- 1 | // base color 2 | $blue:#324157; 3 | $light-blue:#3A71A8; 4 | $red:#C03639; 5 | $pink: #E65D6E; 6 | $green: #30B08F; 7 | $tiffany: #4AB7BD; 8 | $yellow:#FEC171; 9 | $panGreen: #30B08F; 10 | 11 | // sidebar 12 | $menuText:#bfcbd9; 13 | $menuActiveText:#409EFF; 14 | $subMenuActiveText:#f4f4f5; // https://github.com/ElemeFE/element/issues/12951 15 | 16 | $menuBg:#304156; 17 | $menuHover:#263445; 18 | 19 | $subMenuBg:#1f2d3d; 20 | $subMenuHover:#001528; 21 | 22 | $sideBarWidth: 210px; 23 | 24 | // the :export directive is the magic sauce for webpack 25 | // https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass 26 | :export { 27 | menuText: $menuText; 28 | menuActiveText: $menuActiveText; 29 | subMenuActiveText: $subMenuActiveText; 30 | menuBg: $menuBg; 31 | menuHover: $menuHover; 32 | subMenuBg: $subMenuBg; 33 | subMenuHover: $subMenuHover; 34 | sideBarWidth: $sideBarWidth; 35 | } 36 | -------------------------------------------------------------------------------- /frontend/src/element/src/utils/auth.js: -------------------------------------------------------------------------------- 1 | import Cookies from 'js-cookie' 2 | 3 | const TokenKey = 'Admin-Token' 4 | 5 | export function getToken() { 6 | return Cookies.get(TokenKey) 7 | } 8 | 9 | export function setToken(token) { 10 | return Cookies.set(TokenKey, token) 11 | } 12 | 13 | export function removeToken() { 14 | return Cookies.remove(TokenKey) 15 | } 16 | -------------------------------------------------------------------------------- /frontend/src/element/src/utils/clipboard.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Clipboard from 'clipboard' 3 | 4 | function clipboardSuccess() { 5 | Vue.prototype.$message({ 6 | message: 'Copy successfully', 7 | type: 'success', 8 | duration: 1500 9 | }) 10 | } 11 | 12 | function clipboardError() { 13 | Vue.prototype.$message({ 14 | message: 'Copy failed', 15 | type: 'error' 16 | }) 17 | } 18 | 19 | export default function handleClipboard(text, event) { 20 | const clipboard = new Clipboard(event.target, { 21 | text: () => text 22 | }) 23 | clipboard.on('success', () => { 24 | clipboardSuccess() 25 | clipboard.destroy() 26 | }) 27 | clipboard.on('error', () => { 28 | clipboardError() 29 | clipboard.destroy() 30 | }) 31 | clipboard.onClick(event) 32 | } 33 | -------------------------------------------------------------------------------- /frontend/src/element/src/utils/error-log.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import store from '@/store' 3 | import { isString, isArray } from '@/utils/validate' 4 | import settings from '@/settings' 5 | 6 | // you can set in settings.js 7 | // errorLog:'production' | ['production', 'development'] 8 | const { errorLog: needErrorLog } = settings 9 | 10 | function checkNeed() { 11 | const env = process.env.NODE_ENV 12 | if (isString(needErrorLog)) { 13 | return env === needErrorLog 14 | } 15 | if (isArray(needErrorLog)) { 16 | return needErrorLog.includes(env) 17 | } 18 | return false 19 | } 20 | 21 | if (checkNeed()) { 22 | Vue.config.errorHandler = function(err, vm, info, a) { 23 | // Don't ask me why I use Vue.nextTick, it just a hack. 24 | // detail see https://forum.vuejs.org/t/dispatch-in-vue-config-errorhandler-has-some-problem/23500 25 | Vue.nextTick(() => { 26 | store.dispatch('errorLog/addErrorLog', { 27 | err, 28 | vm, 29 | info, 30 | url: window.location.href 31 | }) 32 | console.error(err, info) 33 | }) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /frontend/src/element/src/utils/get-page-title.js: -------------------------------------------------------------------------------- 1 | import defaultSettings from '@/settings' 2 | 3 | const title = defaultSettings.title || 'Vue Element Admin' 4 | 5 | export default function getPageTitle(pageTitle) { 6 | if (pageTitle) { 7 | return `${pageTitle} - ${title}` 8 | } 9 | return `${title}` 10 | } 11 | -------------------------------------------------------------------------------- /frontend/src/element/src/utils/permission.js: -------------------------------------------------------------------------------- 1 | import store from '@/store' 2 | 3 | /** 4 | * @param {Array} value 5 | * @returns {Boolean} 6 | * @example see @/views/permission/directive.vue 7 | */ 8 | export default function checkPermission(value) { 9 | if (value && value instanceof Array && value.length > 0) { 10 | const roles = store.getters && store.getters.roles 11 | const permissionRoles = value 12 | 13 | const hasPermission = roles.some(role => { 14 | return permissionRoles.includes(role) 15 | }) 16 | return hasPermission 17 | } else { 18 | console.error(`need roles! Like v-permission="['admin','editor']"`) 19 | return false 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /frontend/src/element/src/vendor/Export2Zip.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { saveAs } from 'file-saver' 3 | import JSZip from 'jszip' 4 | 5 | export function export_txt_to_zip(th, jsonData, txtName, zipName) { 6 | const zip = new JSZip() 7 | const txt_name = txtName || 'file' 8 | const zip_name = zipName || 'file' 9 | const data = jsonData 10 | let txtData = `${th}\r\n` 11 | data.forEach((row) => { 12 | let tempStr = '' 13 | tempStr = row.toString() 14 | txtData += `${tempStr}\r\n` 15 | }) 16 | zip.file(`${txt_name}.txt`, txtData) 17 | zip.generateAsync({ 18 | type: "blob" 19 | }).then((blob) => { 20 | saveAs(blob, `${zip_name}.zip`) 21 | }, (err) => { 22 | alert('导出失败') 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/charts/keyboard.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 15 | 16 | 23 | 24 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/charts/line.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 15 | 16 | 23 | 24 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/charts/mix-chart.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 15 | 16 | 23 | 24 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/components-demo/dnd-list.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 39 | 40 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/dashboard/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 32 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/error-log/components/ErrorTestA.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/error-log/components/ErrorTestB.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 12 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/example/components/Dropdown/SourceUrl.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 39 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/example/components/Dropdown/index.js: -------------------------------------------------------------------------------- 1 | export { default as CommentDropdown } from './Comment' 2 | export { default as PlatformDropdown } from './Platform' 3 | export { default as SourceUrlDropdown } from './SourceUrl' 4 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/example/components/Warning.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/example/create.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 13 | 14 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/example/edit.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 13 | 14 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/excel/components/AutoWidthOption.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 35 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/excel/components/BookTypeOption.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 40 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/excel/components/FilenameOption.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 28 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/guide/index.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 37 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/icons/svg-icons.js: -------------------------------------------------------------------------------- 1 | const req = require.context('../../icons/svg', false, /\.svg$/) 2 | const requireAll = requireContext => requireContext.keys() 3 | 4 | const re = /\.\/(.*)\.svg/ 5 | 6 | const svgIcons = requireAll(req).map(i => { 7 | return i.match(re)[1] 8 | }) 9 | 10 | export default svgIcons 11 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/login/auth-redirect.vue: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/nested/menu1/index.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/nested/menu1/menu1-1/index.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/nested/menu1/menu1-2/index.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/nested/menu1/menu1-2/menu1-2-1/index.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/nested/menu1/menu1-2/menu1-2-2/index.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/nested/menu1/menu1-3/index.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/nested/menu2/index.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/pdf/index.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/permission/components/SwitchRoles.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 33 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/permission/page.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 20 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/profile/components/Account.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 39 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/redirect/index.vue: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /frontend/src/element/src/views/table/dynamic-table/index.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 24 | 25 | -------------------------------------------------------------------------------- /frontend/src/element/tests/unit/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | jest: true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /frontend/src/element/tests/unit/components/Hamburger.spec.js: -------------------------------------------------------------------------------- 1 | import { shallowMount } from '@vue/test-utils' 2 | import Hamburger from '@/components/Hamburger/index.vue' 3 | describe('Hamburger.vue', () => { 4 | it('toggle click', () => { 5 | const wrapper = shallowMount(Hamburger) 6 | const mockFn = jest.fn() 7 | wrapper.vm.$on('toggleClick', mockFn) 8 | wrapper.find('.hamburger').trigger('click') 9 | expect(mockFn).toBeCalled() 10 | }) 11 | it('prop isActive', () => { 12 | const wrapper = shallowMount(Hamburger) 13 | wrapper.setProps({ isActive: true }) 14 | expect(wrapper.contains('.is-active')).toBe(true) 15 | wrapper.setProps({ isActive: false }) 16 | expect(wrapper.contains('.is-active')).toBe(false) 17 | }) 18 | }) 19 | -------------------------------------------------------------------------------- /frontend/src/element/tests/unit/components/SvgIcon.spec.js: -------------------------------------------------------------------------------- 1 | import { shallowMount } from '@vue/test-utils' 2 | import SvgIcon from '@/components/SvgIcon/index.vue' 3 | describe('SvgIcon.vue', () => { 4 | it('iconClass', () => { 5 | const wrapper = shallowMount(SvgIcon, { 6 | propsData: { 7 | iconClass: 'test' 8 | } 9 | }) 10 | expect(wrapper.find('use').attributes().href).toBe('#icon-test') 11 | }) 12 | it('className', () => { 13 | const wrapper = shallowMount(SvgIcon, { 14 | propsData: { 15 | iconClass: 'test' 16 | } 17 | }) 18 | expect(wrapper.classes().length).toBe(1) 19 | wrapper.setProps({ className: 'test' }) 20 | expect(wrapper.classes().includes('test')).toBe(true) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /frontend/src/element/tests/unit/utils/param2Obj.spec.js: -------------------------------------------------------------------------------- 1 | import { param2Obj } from '@/utils/index.js' 2 | describe('Utils:param2Obj', () => { 3 | const url = 'https://github.com/PanJiaChen/vue-element-admin?name=bill&age=29&sex=1&field=dGVzdA==&key=%E6%B5%8B%E8%AF%95' 4 | 5 | it('param2Obj test', () => { 6 | expect(param2Obj(url)).toEqual({ 7 | name: 'bill', 8 | age: '29', 9 | sex: '1', 10 | field: window.btoa('test'), 11 | key: '测试' 12 | }) 13 | }) 14 | }) 15 | -------------------------------------------------------------------------------- /frontend/uploads/a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoAdminGroup/example_with_vue/558f255bd82cb011ae022ff886366b73f7e24ea1/frontend/uploads/a --------------------------------------------------------------------------------