├── dist ├── web │ └── .gitkeep └── electron │ └── .gitkeep ├── static └── .gitkeep ├── src ├── renderer │ ├── assets │ │ ├── .gitkeep │ │ ├── img │ │ │ ├── china.png │ │ │ ├── world.png │ │ │ └── excel_example.png │ │ └── my-theme │ │ │ ├── components │ │ │ ├── checkbox.less │ │ │ ├── affix.less │ │ │ ├── circle.less │ │ │ ├── loading-bar.less │ │ │ ├── select-dropdown.less │ │ │ ├── dropdown.less │ │ │ ├── back-top.less │ │ │ ├── index.less │ │ │ ├── tooltip.less │ │ │ ├── card.less │ │ │ ├── message.less │ │ │ ├── collapse.less │ │ │ ├── badge.less │ │ │ ├── spin.less │ │ │ ├── input.less │ │ │ ├── rate.less │ │ │ ├── form.less │ │ │ ├── progress.less │ │ │ ├── upload.less │ │ │ ├── timeline.less │ │ │ ├── cascader.less │ │ │ ├── alert.less │ │ │ ├── slider.less │ │ │ ├── switch.less │ │ │ ├── modal.less │ │ │ ├── notice.less │ │ │ ├── button.less │ │ │ ├── transfer.less │ │ │ ├── carousel.less │ │ │ ├── poptip.less │ │ │ ├── tree.less │ │ │ ├── input-number.less │ │ │ ├── tag.less │ │ │ ├── tabs.less │ │ │ ├── time-picker.less │ │ │ ├── select.less │ │ │ └── menu.less │ │ │ ├── common │ │ │ ├── index.less │ │ │ ├── iconfont │ │ │ │ ├── ionicons.less │ │ │ │ ├── fonts │ │ │ │ │ ├── ionicons.eot │ │ │ │ │ ├── ionicons.ttf │ │ │ │ │ └── ionicons.woff │ │ │ │ └── _ionicons-font.less │ │ │ ├── article.less │ │ │ ├── base.less │ │ │ └── layout.less │ │ │ ├── dist │ │ │ └── fonts │ │ │ │ ├── ionicons.eot │ │ │ │ ├── ionicons.ttf │ │ │ │ └── ionicons.woff │ │ │ ├── copyright.less │ │ │ ├── README.md │ │ │ ├── index.less │ │ │ ├── mixins │ │ │ ├── close.less │ │ │ ├── loading.less │ │ │ ├── mask.less │ │ │ ├── clearfix.less │ │ │ ├── index.less │ │ │ ├── size.less │ │ │ ├── breadcrumb.less │ │ │ ├── common.less │ │ │ ├── caret.less │ │ │ ├── content.less │ │ │ ├── select.less │ │ │ ├── layout.less │ │ │ ├── tooltip.less │ │ │ └── checkbox.less │ │ │ ├── animation │ │ │ ├── fade.less │ │ │ ├── index.less │ │ │ ├── ease.less │ │ │ ├── slide.less │ │ │ └── move.less │ │ │ └── custom.css │ ├── version │ │ └── version.js │ ├── key │ │ └── mapApiKey.js │ ├── filter │ │ └── index.js │ ├── store │ │ ├── mutations_types.js │ │ ├── modules │ │ │ ├── map.js │ │ │ ├── user_info.js │ │ │ └── excel.js │ │ ├── index.js │ │ └── actions.js │ ├── App.vue │ ├── server │ │ ├── url.js │ │ └── ajax.js │ ├── main.js │ ├── tool │ │ └── index.js │ ├── components │ │ ├── Page │ │ │ ├── Auth.vue │ │ │ ├── Map.vue │ │ │ ├── Register.vue │ │ │ ├── ForgetPassword.vue │ │ │ ├── Help.vue │ │ │ ├── MyProject.vue │ │ │ └── Login.vue │ │ ├── Layout │ │ │ └── Header.vue │ │ └── Ui │ │ │ ├── DelPointModal.vue │ │ │ ├── EditPointModal.vue │ │ │ └── AddPointModal.vue │ ├── router │ │ └── index.js │ └── data │ │ └── map.js ├── main │ ├── index.dev.js │ └── index.js └── index.ejs ├── .gitattributes ├── .gitignore ├── .electron-vue ├── build.config.js ├── dev-client.js ├── webpack.main.config.js ├── webpack.web.config.js ├── build.js ├── dev-runner.js └── webpack.renderer.config.js ├── .babelrc ├── LICENSE ├── README.md └── package.json /dist/web/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dist/electron/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/renderer/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/renderer/version/version.js: -------------------------------------------------------------------------------- 1 | export default { 2 | VERSION: '0.0.3-beta' 3 | } 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.css linguist-language=JavaScript 2 | *.less linguist-language=JavaScript 3 | -------------------------------------------------------------------------------- /src/renderer/assets/img/china.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-Map/iMap/HEAD/src/renderer/assets/img/china.png -------------------------------------------------------------------------------- /src/renderer/assets/img/world.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-Map/iMap/HEAD/src/renderer/assets/img/world.png -------------------------------------------------------------------------------- /src/renderer/key/mapApiKey.js: -------------------------------------------------------------------------------- 1 | export default { 2 | GOOGLE: 'AIzaSyDyfBSBmSsUsGO3iVPc4xXpCPKJ1j5__HY' 3 | } 4 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/checkbox.less: -------------------------------------------------------------------------------- 1 | @checkbox-prefix-cls: ~"@{css-prefix}checkbox"; 2 | .checkboxFn(); -------------------------------------------------------------------------------- /src/renderer/assets/img/excel_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-Map/iMap/HEAD/src/renderer/assets/img/excel_example.png -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/affix.less: -------------------------------------------------------------------------------- 1 | .ivu-affix { 2 | position: fixed; 3 | z-index: @zindex-affix; 4 | } 5 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/common/index.less: -------------------------------------------------------------------------------- 1 | @import "base"; 2 | @import "iconfont/ionicons"; 3 | @import "layout"; 4 | @import "article"; -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/dist/fonts/ionicons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-Map/iMap/HEAD/src/renderer/assets/my-theme/dist/fonts/ionicons.eot -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/dist/fonts/ionicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-Map/iMap/HEAD/src/renderer/assets/my-theme/dist/fonts/ionicons.ttf -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/dist/fonts/ionicons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-Map/iMap/HEAD/src/renderer/assets/my-theme/dist/fonts/ionicons.woff -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/common/iconfont/ionicons.less: -------------------------------------------------------------------------------- 1 | @import "_ionicons-variables"; 2 | @import "_ionicons-font"; 3 | @import "_ionicons-icons"; 4 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/copyright.less: -------------------------------------------------------------------------------- 1 | /*! 2 | * iView 3 | * Web: https://www.iviewui.com 4 | * Github: https://github.com/iview/iview 5 | * Author: Aresn 6 | */ -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/common/iconfont/fonts/ionicons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-Map/iMap/HEAD/src/renderer/assets/my-theme/common/iconfont/fonts/ionicons.eot -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/common/iconfont/fonts/ionicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-Map/iMap/HEAD/src/renderer/assets/my-theme/common/iconfont/fonts/ionicons.ttf -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/common/iconfont/fonts/ionicons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i-Map/iMap/HEAD/src/renderer/assets/my-theme/common/iconfont/fonts/ionicons.woff -------------------------------------------------------------------------------- /src/renderer/filter/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | Vue.filter('dateFormat', time => { 4 | if(time === '') 5 | return '暂无数据' 6 | else 7 | return time 8 | }) 9 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/README.md: -------------------------------------------------------------------------------- 1 | # 样式库说明 2 | 3 | ## 目录 4 | 5 | |-- animation (动画) 6 | 7 | |-- common (全局样式) 8 | 9 | |-- components (组件样式) 10 | 11 | |-- mixins (混入) 12 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/index.less: -------------------------------------------------------------------------------- 1 | @import "./custom"; 2 | @import "./mixins/index"; 3 | @import "./common/index"; 4 | @import "./animation/index"; 5 | @import "./components/index"; 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vscode 3 | dist/electron/* 4 | dist/web/* 5 | build/* 6 | !build/icons 7 | node_modules/ 8 | npm-debug.log 9 | npm-debug.log.* 10 | thumbs.db 11 | !.gitkeep 12 | -------------------------------------------------------------------------------- /src/renderer/store/mutations_types.js: -------------------------------------------------------------------------------- 1 | export const SET_USER_INFO = 'SET_USER_INFO' 2 | export const SET_EXCEL_DATA = 'SET_EXCEL_DATA' 3 | export const ADD_EXCEL_DATA = 'ADD_EXCEL_DATA' 4 | export const EDIT_EXCEL_DATA = 'EDIT_EXCEL_DATA' 5 | export const DEL_EXCEL_DATA = 'DEL_EXCEL_DATA' 6 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/mixins/close.less: -------------------------------------------------------------------------------- 1 | .close-base(@top: 0, @icon-font-size: 22px) { 2 | font-size: @icon-font-size; 3 | color: @legend-color; 4 | transition: color @transition-time ease; 5 | position: relative; 6 | top: @top; 7 | &:hover { 8 | color: #444; 9 | } 10 | } -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/mixins/loading.less: -------------------------------------------------------------------------------- 1 | // Loading for loop 2 | .ivu-load-loop{ 3 | animation: ani-load-loop 1s linear infinite; 4 | } 5 | 6 | @keyframes ani-load-loop { 7 | from { transform: rotate(0deg);} 8 | 50% { transform: rotate(180deg);} 9 | to { transform: rotate(360deg);} 10 | } 11 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/mixins/mask.less: -------------------------------------------------------------------------------- 1 | .mask() { 2 | position: fixed; 3 | top: 0; 4 | bottom: 0; 5 | left: 0; 6 | right: 0; 7 | background-color: rgba(55, 55, 55, 0.6); 8 | height: 100%; 9 | z-index: @zindex-modal; 10 | 11 | &-hidden { 12 | display: none; 13 | } 14 | } -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/mixins/clearfix.less: -------------------------------------------------------------------------------- 1 | .clearfix() { 2 | zoom: 1; 3 | &:before, 4 | &:after { 5 | content: ""; 6 | display: table; 7 | } 8 | &:after { 9 | clear: both; 10 | visibility: hidden; 11 | font-size: 0; 12 | height: 0; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/renderer/store/modules/map.js: -------------------------------------------------------------------------------- 1 | import * as types from '../mutations_types' 2 | 3 | // state 4 | const state = { 5 | mapType: '' 6 | } 7 | 8 | // mutations 9 | const mutations = { 10 | // 设置mapType 11 | [types.SET_MAP_TYPE] (state, data) { 12 | state.mapType = data 13 | } 14 | } 15 | 16 | // 导出state, mutations 17 | export default { 18 | state, 19 | mutations 20 | } 21 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/mixins/index.less: -------------------------------------------------------------------------------- 1 | @import "common"; 2 | @import "clearfix"; 3 | @import "button"; 4 | @import "layout"; 5 | @import "size"; 6 | @import "loading"; 7 | @import "close"; 8 | @import "checkbox"; 9 | @import "input"; 10 | @import "breadcrumb"; 11 | @import "mask"; 12 | @import "content"; // card、modal 13 | @import "tooltip"; 14 | @import "select"; 15 | @import "caret"; -------------------------------------------------------------------------------- /src/renderer/store/modules/user_info.js: -------------------------------------------------------------------------------- 1 | import * as types from '../mutations_types' 2 | 3 | // state 4 | const state = { 5 | userInfo: {} 6 | } 7 | 8 | // mutations 9 | const mutations = { 10 | // 设置userInfo 11 | [types.SET_USER_INFO] (state, data) { 12 | state.userInfo = data 13 | } 14 | } 15 | 16 | // 导出state, mutations 17 | export default { 18 | state, 19 | mutations 20 | } -------------------------------------------------------------------------------- /src/renderer/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 21 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/circle.less: -------------------------------------------------------------------------------- 1 | @circle-prefix-cls: ~"@{css-prefix}chart-circle"; 2 | 3 | .@{circle-prefix-cls}{ 4 | display: inline-block; 5 | position: relative; 6 | 7 | &-inner { 8 | width: 100%; 9 | text-align: center; 10 | position: absolute; 11 | left: 0; 12 | top: 50%; 13 | transform: translateY(-50%); 14 | line-height: 1; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/renderer/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import * as actions from './actions' 4 | import userInfo from './modules/user_info' 5 | import excel from './modules/excel' 6 | 7 | Vue.use(Vuex) 8 | 9 | const debug = process.env.NODE_ENV !== 'production' 10 | 11 | export default new Vuex.Store({ 12 | actions, 13 | modules: { 14 | userInfo, 15 | excel 16 | }, 17 | strict: debug 18 | }) 19 | -------------------------------------------------------------------------------- /.electron-vue/build.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | 3 | /** 4 | * `electron-packager` options 5 | * https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-electron-packager.html 6 | */ 7 | module.exports = { 8 | arch: 'x64', 9 | asar: true, 10 | dir: path.join(__dirname, '../'), 11 | icon: path.join(__dirname, '../build/icons/icon'), 12 | ignore: /(^\/(src|test|\.[a-z]+|README|yarn|static|dist\/web))|\.gitkeep/, 13 | out: path.join(__dirname, '../build'), 14 | overwrite: true, 15 | platform: process.env.BUILD_TARGET || 'all' 16 | } 17 | -------------------------------------------------------------------------------- /src/renderer/server/url.js: -------------------------------------------------------------------------------- 1 | export default { 2 | REGISTER : '/api/v1/auth/register', 3 | EMAILLOGIN : '/api/v1/auth/login', 4 | ASKCODE : '/api/v1/auth/login/askCode', 5 | PHONELOGIN : '/api/v1/auth/login/phone', 6 | FORGETPASSWORD : '/api/v1/auth/forgetPassword', 7 | RESOLVEEXCEL : '/api/v1/resolveExcel', 8 | ASYNC_UPLOAD : '/api/v1/async/upload', 9 | ASYNC_DOWNLOAD : '/api/v1/async/download', 10 | DELMAPDATA : '/api/v1/delMapData', 11 | GETLOCATION_WORLD: 'https://google.cn/maps/api/geocode/json' 12 | } 13 | -------------------------------------------------------------------------------- /src/renderer/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | import App from './App' 4 | import router from './router' 5 | import store from './store' 6 | import iView from 'iview' 7 | import '@/filter/index.js' 8 | import 'iview/dist/styles/iview.css' 9 | import '@/assets/my-theme/dist/iview.css' 10 | 11 | 12 | if (!process.env.IS_WEB) Vue.use(require('vue-electron')) 13 | Vue.config.productionTip = false 14 | Vue.use(iView) 15 | 16 | /* eslint-disable no-new */ 17 | new Vue({ 18 | components: { App }, 19 | router, 20 | store, 21 | template: '' 22 | }).$mount('#app') 23 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/loading-bar.less: -------------------------------------------------------------------------------- 1 | @loading-bar-prefix-cls: ~"@{css-prefix}loading-bar"; 2 | 3 | .@{loading-bar-prefix-cls} { 4 | width: 100%; 5 | position: fixed; 6 | top: 0; 7 | left: 0; 8 | right: 0; 9 | z-index: @zindex-loading-bar; 10 | 11 | &-inner { 12 | transition: width @transition-time linear; 13 | 14 | &-color-primary { 15 | background-color: @primary-color; 16 | } 17 | 18 | &-failed-color-error { 19 | background-color: @error-color; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/select-dropdown.less: -------------------------------------------------------------------------------- 1 | @select-dropdown-prefix-cls: ~"@{css-prefix}select-dropdown"; 2 | 3 | .@{select-dropdown-prefix-cls} { 4 | width: inherit; 5 | max-height: 200px; 6 | overflow: auto; 7 | margin: 5px 0; 8 | padding: 5px 0; 9 | background-color: #fff; 10 | box-sizing: border-box; 11 | //border: 1px solid @border-color-split; 12 | border-radius: @btn-border-radius; 13 | //box-shadow: 0 1px 3px rgba(0,0,0,.2); 14 | box-shadow: @shadow-base; 15 | position: absolute; 16 | z-index: @zindex-select; 17 | } -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "comments": false, 3 | "env": { 4 | "main": { 5 | "presets": [ 6 | ["env", { 7 | "targets": { "node": 7 } 8 | }], 9 | "stage-0" 10 | ] 11 | }, 12 | "renderer": { 13 | "presets": [ 14 | ["env", { 15 | "modules": false 16 | }], 17 | "stage-0" 18 | ] 19 | }, 20 | "web": { 21 | "presets": [ 22 | ["env", { 23 | "modules": false 24 | }], 25 | "stage-0" 26 | ] 27 | } 28 | }, 29 | "plugins": ["transform-runtime"] 30 | } 31 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/mixins/size.less: -------------------------------------------------------------------------------- 1 | .size(@width; @height) { 2 | width: @width; 3 | height: @height; 4 | } 5 | 6 | .square(@size) { 7 | .size(@size; @size); 8 | } 9 | 10 | // fix chrome 12px bug, support ie 11 | .iconfont-size-under-12px(@size, @rotate: 0deg) { 12 | display: inline-block; 13 | @font-scale: unit(@size / @font-size-base); 14 | font-size: @font-size-base; 15 | font-size: ~"@{size} \9"; // ie8-9 16 | transform: scale(@font-scale) rotate(@rotate); 17 | :root & { 18 | font-size: @font-size-base; // reset ie9 and above 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/renderer/tool/index.js: -------------------------------------------------------------------------------- 1 | const REGEX_EMAIL = /^(\w)+(\.\w+)*@(\w)+((\.\w{2,3}){1,3})$/, 2 | REGEX_PASSWORD = /^(\w){6,20}$/, 3 | REGEX_PHONE = /^1[34578]\d{9}$/, 4 | REGEX_NUM = /[\d.]/ 5 | 6 | export default { 7 | judgeEmail(value) { 8 | return REGEX_EMAIL.test(value) 9 | }, 10 | judgePassword(value) { 11 | return REGEX_PASSWORD.exec(value) 12 | }, 13 | judgePhone(value) { 14 | return REGEX_PHONE.test(value) 15 | }, 16 | judgeNum(value) { 17 | if(!/[\d.]/.test(value)) 18 | return false 19 | else if(isNaN(value)) 20 | return false 21 | else 22 | return true 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/animation/fade.less: -------------------------------------------------------------------------------- 1 | .fade-motion(@className, @keyframeName) { 2 | .make-motion(@className, @keyframeName); 3 | .@{className}-enter, .@{className}-appear { 4 | opacity: 0; 5 | animation-timing-function: linear; 6 | } 7 | .@{className}-leave { 8 | animation-timing-function: linear; 9 | } 10 | } 11 | 12 | .fade-motion(fade, ivuFade); 13 | 14 | @keyframes ivuFadeIn { 15 | 0% { 16 | opacity: 0; 17 | } 18 | 100% { 19 | opacity: 1; 20 | } 21 | } 22 | 23 | @keyframes ivuFadeOut { 24 | 0% { 25 | opacity: 1; 26 | } 27 | 100% { 28 | opacity: 0; 29 | } 30 | } -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/dropdown.less: -------------------------------------------------------------------------------- 1 | @dropdown-prefix-cls: ~"@{css-prefix}dropdown"; 2 | @dropdown-item-prefix-cls: ~"@{dropdown-prefix-cls}-item"; 3 | 4 | .@{dropdown-prefix-cls} { 5 | display: inline-block; 6 | //position: relative; 7 | 8 | .@{select-dropdown-prefix-cls} { 9 | overflow: visible; 10 | max-height: none; 11 | } 12 | .@{dropdown-prefix-cls} { 13 | width: 100%; 14 | } 15 | 16 | &-rel{ 17 | display: inline-block; 18 | position: relative; 19 | } 20 | 21 | &-menu{ 22 | min-width: 100px; 23 | } 24 | } 25 | 26 | .select-item(@dropdown-prefix-cls, @dropdown-item-prefix-cls); -------------------------------------------------------------------------------- /src/renderer/components/Page/Auth.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 17 | 18 | 19 | 33 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/back-top.less: -------------------------------------------------------------------------------- 1 | @backtop-prefix-cls: ~"@{css-prefix}back-top"; 2 | 3 | .@{backtop-prefix-cls} { 4 | z-index: @zindex-back-top; 5 | position: fixed; 6 | cursor: pointer; 7 | display: none; 8 | 9 | &.@{backtop-prefix-cls}-show { 10 | display: block; 11 | } 12 | 13 | &-inner { 14 | background-color: rgba(0,0,0,.6); 15 | border-radius: 2px; 16 | box-shadow: 0 1px 3px rgba(0,0,0,.2); 17 | transition: all @transition-time @ease-in-out; 18 | 19 | &:hover { 20 | background-color: rgba(0,0,0,.7); 21 | } 22 | } 23 | 24 | i{ 25 | color: #fff; 26 | font-size: 24px; 27 | padding: 8px 12px; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/animation/index.less: -------------------------------------------------------------------------------- 1 | .motion-common() { 2 | animation-duration: @animation-time; 3 | animation-fill-mode: both; 4 | } 5 | 6 | .make-motion(@className, @keyframeName) { 7 | .@{className}-enter, .@{className}-appear { 8 | .motion-common(); 9 | animation-play-state: paused; 10 | } 11 | .@{className}-leave { 12 | .motion-common(); 13 | animation-play-state: paused; 14 | } 15 | .@{className}-enter, .@{className}-appear { 16 | animation-name: ~"@{keyframeName}In"; 17 | animation-play-state: running; 18 | } 19 | .@{className}-leave { 20 | animation-name: ~"@{keyframeName}Out"; 21 | animation-play-state: running; 22 | } 23 | } 24 | 25 | @import "fade"; 26 | @import "move"; 27 | @import "ease"; 28 | @import "slide"; -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/mixins/breadcrumb.less: -------------------------------------------------------------------------------- 1 | @breadcrumb-prefix-cls: ~"@{css-prefix}breadcrumb"; 2 | 3 | .@{breadcrumb-prefix-cls} { 4 | color: #999; 5 | font-size: @font-size-base; 6 | 7 | a { 8 | color: @text-color; 9 | transition: color @transition-time @ease-in-out; 10 | &:hover { 11 | color: tint(@primary-color, 20%); 12 | } 13 | } 14 | 15 | & > span:last-child { 16 | font-weight: bold; 17 | color: @text-color; 18 | } 19 | 20 | & > span:last-child &-item-separator { 21 | display: none; 22 | } 23 | 24 | &-item-separator { 25 | margin: 0 8px; 26 | color: @border-color-base; 27 | } 28 | 29 | &-item-link { 30 | > .ivu-icon + span { 31 | margin-left: 4px; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/mixins/common.less: -------------------------------------------------------------------------------- 1 | .placeholder(@color: @input-placeholder-color) { 2 | // Firefox 3 | &::-moz-placeholder { 4 | color: @color; 5 | opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526 6 | } 7 | // Internet Explorer 10+ 8 | &:-ms-input-placeholder { 9 | color: @color; 10 | } 11 | // Safari and Chrome 12 | &::-webkit-input-placeholder { 13 | color: @color; 14 | } 15 | } 16 | 17 | // for select and input like component's arrow 18 | .inner-arrow() { 19 | position: absolute; 20 | top: 50%; 21 | right: 8px; 22 | line-height: 1; 23 | margin-top: -7px; 24 | font-size: @font-size-base; 25 | color: @subsidiary-color; 26 | transition: all @transition-time @ease-in-out; 27 | } 28 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/mixins/caret.less: -------------------------------------------------------------------------------- 1 | // sortable 2 | .sortable() { 3 | display: inline-block; 4 | width: 9px; 5 | height: 12px; 6 | margin-left: 4px; 7 | margin-top: -1px; 8 | vertical-align: middle; 9 | overflow: hidden; 10 | cursor: pointer; 11 | position: relative; 12 | 13 | i { 14 | display: block; 15 | height: 6px; 16 | line-height: 6px; 17 | overflow: hidden; 18 | position: absolute; 19 | color: @btn-disable-color; 20 | transition: color @transition-time @ease-in-out; 21 | 22 | &:hover{ 23 | color: inherit; 24 | } 25 | 26 | &.on{ 27 | color: @primary-color; 28 | } 29 | 30 | &:first-child{ 31 | top: 0; 32 | } 33 | &:last-child{ 34 | bottom: 0; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/animation/ease.less: -------------------------------------------------------------------------------- 1 | .ease-motion(@className, @keyframeName) { 2 | .make-motion(@className, @keyframeName); 3 | .@{className}-enter, .@{className}-appear { 4 | opacity: 0; 5 | animation-timing-function: linear; 6 | animation-duration: @transition-time; 7 | } 8 | .@{className}-leave { 9 | animation-timing-function: linear; 10 | animation-duration: @transition-time; 11 | } 12 | } 13 | 14 | .ease-motion(ease, ivuEase); 15 | 16 | @keyframes ivuEaseIn { 17 | 0% { 18 | opacity: 0; 19 | transform: scale(0.9); 20 | } 21 | 100% { 22 | opacity: 1; 23 | transform: scale(1); 24 | } 25 | } 26 | 27 | @keyframes ivuEaseOut { 28 | 0% { 29 | opacity: 1; 30 | transform: scale(1); 31 | } 32 | 100% { 33 | opacity: 0; 34 | transform: scale(0.9); 35 | } 36 | } -------------------------------------------------------------------------------- /src/main/index.dev.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is used specifically and only for development. It installs 3 | * `electron-debug` & `vue-devtools`. There shouldn't be any need to 4 | * modify this file, but it can be used to extend your development 5 | * environment. 6 | */ 7 | 8 | /* eslint-disable */ 9 | 10 | // Set environment for development 11 | process.env.NODE_ENV = 'development' 12 | 13 | // Install `electron-debug` with `devtron` 14 | require('electron-debug')({ showDevTools: true }) 15 | 16 | // Install `vue-devtools` 17 | require('electron').app.on('ready', () => { 18 | let installExtension = require('electron-devtools-installer') 19 | installExtension.default(installExtension.VUEJS_DEVTOOLS) 20 | .then(() => {}) 21 | .catch(err => { 22 | console.log('Unable to install `vue-devtools`: \n', err) 23 | }) 24 | }) 25 | 26 | // Require `main` process to boot app 27 | require('./index') 28 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/mixins/content.less: -------------------------------------------------------------------------------- 1 | @icon-prefix-cls: ~"@{css-prefix}icon"; 2 | 3 | .content-header() { 4 | border-bottom: 1px solid @border-color-split; 5 | padding: 14px 16px; 6 | line-height: 1; 7 | 8 | p, 9 | &-inner 10 | { 11 | display: inline-block; 12 | width: 100%; 13 | height: 20px; 14 | line-height: 20px; 15 | font-size: @font-size-base; 16 | color: @title-color; 17 | font-weight: bold; 18 | overflow: hidden; 19 | text-overflow: ellipsis; 20 | white-space: nowrap; 21 | } 22 | } 23 | 24 | .content-close(@top: 0, @icon-font-size: 22px) { 25 | font-size: @font-size-small; 26 | position: absolute; 27 | right: 16px; 28 | top: 8px; 29 | overflow: hidden; 30 | cursor: pointer; 31 | 32 | .@{icon-prefix-cls}-ios-close-empty { 33 | .close-base(@top, @icon-font-size); 34 | } 35 | } -------------------------------------------------------------------------------- /src/renderer/store/actions.js: -------------------------------------------------------------------------------- 1 | import * as types from './mutations_types' 2 | 3 | /** 4 | * 保存用户信息 5 | * @param {Object} data 6 | */ 7 | export const setUserInfo = ({ commit }, data) => { 8 | commit(types.SET_USER_INFO, data) 9 | } 10 | 11 | /** 12 | * 保存Excel数据 13 | * @param {Object} data 14 | */ 15 | export const setExcelData = ({ commit }, data) => { 16 | commit(types.SET_EXCEL_DATA, data) 17 | } 18 | 19 | /** 20 | * 添加Excel数据 21 | * @param {Array} data 22 | */ 23 | export const addExcelData = ({ commit }, data) => { 24 | commit(types.ADD_EXCEL_DATA, data) 25 | } 26 | 27 | /** 28 | * 修改Excel数据 29 | * @param {Array} data 30 | */ 31 | export const editExcelData = ({ commit }, data) => { 32 | commit(types.EDIT_EXCEL_DATA, data) 33 | } 34 | 35 | /** 36 | * 删除Excel数据 37 | * @param {Array} data 38 | */ 39 | export const delExcelData = ({ commit }, data) => { 40 | commit(types.DEL_EXCEL_DATA, data) 41 | } 42 | -------------------------------------------------------------------------------- /src/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | iMap 6 | 7 | <% if (htmlWebpackPlugin.options.nodeModules) { %> 8 | 9 | 12 | <% } %> 13 | 14 | 15 |
16 | 17 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/index.less: -------------------------------------------------------------------------------- 1 | @import "button"; 2 | @import "affix"; 3 | @import "back-top"; 4 | @import "badge"; 5 | @import "circle"; 6 | @import "spin"; 7 | @import "alert"; 8 | @import "collapse"; 9 | @import "card"; 10 | @import "message"; 11 | @import "notice"; 12 | @import "radio"; 13 | @import "checkbox"; 14 | @import "switch"; 15 | @import "input-number"; 16 | @import "tag"; 17 | @import "loading-bar"; 18 | @import "progress"; 19 | @import "timeline"; 20 | @import "page"; 21 | @import "steps"; 22 | @import "modal"; 23 | @import "select"; 24 | @import "select-dropdown"; 25 | @import "tooltip"; 26 | @import "poptip"; 27 | @import "input"; 28 | @import "slider"; 29 | @import "cascader"; 30 | @import "transfer"; 31 | @import "table"; 32 | @import "dropdown"; 33 | @import "tabs"; 34 | @import "menu"; 35 | @import "date-picker"; 36 | @import "time-picker"; 37 | @import "form"; 38 | @import "carousel"; 39 | @import "rate"; 40 | @import "upload"; 41 | @import "tree"; -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/common/iconfont/_ionicons-font.less: -------------------------------------------------------------------------------- 1 | // Ionicons Font Path 2 | // -------------------------- 3 | 4 | @font-face { 5 | font-family: @ionicons-font-family; 6 | src:url("@{ionicons-font-path}/ionicons.eot?v=@{ionicons-version}"); 7 | src:url("@{ionicons-font-path}/ionicons.eot?v=@{ionicons-version}#iefix") format("embedded-opentype"), 8 | url("@{ionicons-font-path}/ionicons.ttf?v=@{ionicons-version}") format("truetype"), 9 | url("@{ionicons-font-path}/ionicons.woff?v=@{ionicons-version}") format("woff"), 10 | url("@{ionicons-font-path}/ionicons.svg?v=@{ionicons-version}#Ionicons") format("svg"); 11 | font-weight: normal; 12 | font-style: normal; 13 | } 14 | 15 | .ivu-icon() { 16 | display: inline-block; 17 | font-family: @ionicons-font-family; 18 | speak: none; 19 | font-style: normal; 20 | font-weight: normal; 21 | font-variant: normal; 22 | text-transform: none; 23 | text-rendering: auto; 24 | line-height: 1; 25 | -webkit-font-smoothing: antialiased; 26 | -moz-osx-font-smoothing: grayscale; 27 | } 28 | 29 | .ivu-icon { 30 | .ivu-icon(); 31 | } -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/tooltip.less: -------------------------------------------------------------------------------- 1 | @tooltip-prefix-cls: ~"@{css-prefix}tooltip"; 2 | @tooltip-arrow: ~"@{tooltip-prefix-cls}-arrow"; 3 | @tooltip-max-width: 250px; 4 | @tooltip-arrow-width: 5px; 5 | @tooltip-distance: @tooltip-arrow-width - 1 + 4; 6 | 7 | .@{tooltip-prefix-cls} { 8 | display: inline-block; 9 | 10 | &-rel{ 11 | display: inline-block; 12 | position: relative; 13 | } 14 | 15 | &-popper{ 16 | .popper(@tooltip-arrow, @tooltip-arrow-width, @tooltip-distance, @tooltip-bg); 17 | } 18 | 19 | &-inner{ 20 | max-width: @tooltip-max-width; 21 | min-height: 34px; 22 | padding: 8px 12px; 23 | color: @tooltip-color; 24 | text-align: left; 25 | text-decoration: none; 26 | background-color: @tooltip-bg; 27 | border-radius: @border-radius-small; 28 | box-shadow: @shadow-base; 29 | white-space: nowrap; 30 | } 31 | 32 | &-arrow{ 33 | position: absolute; 34 | width: 0; 35 | height: 0; 36 | border-color: transparent; 37 | border-style: solid; 38 | } 39 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017-present iMap 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.electron-vue/dev-client.js: -------------------------------------------------------------------------------- 1 | const hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') 2 | 3 | hotClient.subscribe(event => { 4 | /** 5 | * Reload browser when HTMLWebpackPlugin emits a new index.html 6 | */ 7 | if (event.action === 'reload') { 8 | window.location.reload() 9 | } 10 | 11 | /** 12 | * Notify `mainWindow` when `main` process is compiling, 13 | * giving notice for an expected reload of the `electron` process 14 | */ 15 | if (event.action === 'compiling') { 16 | document.body.innerHTML += ` 17 | 30 | 31 |
32 | Compiling Main Process... 33 |
34 | ` 35 | } 36 | }) 37 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/card.less: -------------------------------------------------------------------------------- 1 | @card-prefix-cls: ~"@{css-prefix}card"; 2 | 3 | .@{card-prefix-cls}{ 4 | background: #fff; 5 | border-radius: @border-radius-small; 6 | font-size: @font-size-base; 7 | position: relative; 8 | //overflow: hidden; 9 | transition: all @transition-time @ease-in-out; 10 | 11 | &-bordered { 12 | border: 1px solid @border-color-base; 13 | border-color: @border-color-split; 14 | } 15 | 16 | &-shadow{ 17 | box-shadow: @shadow-card; 18 | } 19 | 20 | &:hover { 21 | box-shadow: @shadow-base; 22 | border-color: #eee; 23 | } 24 | &&-dis-hover:hover{ 25 | box-shadow: none; 26 | border-color: transparent; 27 | } 28 | 29 | &&-dis-hover&-bordered:hover{ 30 | border-color: @border-color-split; 31 | } 32 | 33 | &&-shadow:hover{ 34 | box-shadow: @shadow-card; 35 | } 36 | 37 | &-head { 38 | .content-header; 39 | } 40 | 41 | &-extra { 42 | position: absolute; 43 | right: 16px; 44 | top: 14px; 45 | } 46 | 47 | &-body { 48 | padding: 16px; 49 | } 50 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iMap 2 | 3 | ![地图页](http://ojiq40lzd.bkt.clouddn.com/5.png) 4 | 5 | 开源 6 | 7 | 跨平台(MacOS,Linux,Windows) 8 | 9 | 一款基于electron和Echarts的旅行地图生成器 10 | 11 | [![https://github.com/HuangXiZhou/iMap/releases](https://img.shields.io/badge/releases-beta%20V2-blue.svg)](https://github.com/HuangXiZhou/iMap/releases) 12 | 13 | ## 下载 14 | [MacOS](https://github.com/HuangXiZhou/iMap/releases/download/0.0.2-beta/iMap-0.0.2-beta-mac.zip) 15 | [Windows](https://github.com/HuangXiZhou/iMap/releases/download/0.0.2-beta/iMap-0.0.2-beta-win32.zip) 16 | [Linux](https://github.com/HuangXiZhou/iMap/releases/download/0.0.2-beta/iMap-0.0.2-beta-linux.zip) 17 | 18 | ###### 你可以在 [github.com/HuangXiZhou/iMap/releases](https://github.com/HuangXiZhou/iMap/releases) 上浏览全部的releases 19 | 20 | ## 启动项目 21 | ```bash 22 | #install dependencies 23 | yarn 24 | 25 | #serve with hot reload at localhost:8090 26 | yarn run dev 27 | 28 | #build for production(mas, darwin, win32, linux) 29 | npm run build 30 | ``` 31 | 32 | ## 更新日志 33 | 0.0.3-Beta 34 | 35 | * 修复若干bug 36 | * 暂时移除应用内更新 37 | * 添加海外城市坐标支持 38 | * 支持地图放大、拖动 39 | 40 | ## 下版本更新 41 | * 集成旅行日记 42 | * 添加海外国家地图 43 | 44 | ## 求一份工作 45 | [我的简历](https://huangxizhou.com/resume) 46 | 47 | ## License 48 | [MIT](https://opensource.org/licenses/MIT) 49 | 50 | Copyright © 2017-present, Trevor 51 | -------------------------------------------------------------------------------- /src/main/index.js: -------------------------------------------------------------------------------- 1 | import { app, BrowserWindow } from 'electron' 2 | 3 | /** 4 | * Set `__static` path to static files in production 5 | * https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-static-assets.html 6 | */ 7 | if (process.env.NODE_ENV !== 'development') { 8 | global.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\') 9 | } 10 | 11 | let mainWindow 12 | const winURL = process.env.NODE_ENV === 'development' 13 | ? `http://localhost:9080` 14 | : `file://${__dirname}/index.html` 15 | 16 | function createWindow () { 17 | /** 18 | * Initial window options 19 | */ 20 | mainWindow = new BrowserWindow({ 21 | show: false, 22 | height: 563, 23 | useContentSize: true, 24 | width: 1000, 25 | resizable: false, 26 | fullscreen: false, 27 | fullscreenable: false 28 | }) 29 | 30 | mainWindow.loadURL(winURL) 31 | 32 | mainWindow.on('ready-to-show', function() { 33 | mainWindow.show(); 34 | mainWindow.focus(); 35 | }); 36 | 37 | mainWindow.on('closed', () => { 38 | mainWindow = null 39 | }) 40 | } 41 | 42 | app.on('ready', createWindow) 43 | 44 | app.on('window-all-closed', () => { 45 | if (process.platform !== 'darwin') { 46 | app.quit() 47 | } 48 | }) 49 | 50 | app.on('activate', () => { 51 | if (mainWindow === null) { 52 | createWindow() 53 | } 54 | }) 55 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/message.less: -------------------------------------------------------------------------------- 1 | @message-prefix-cls: ~"@{css-prefix}message"; 2 | @icon-prefix-cls: ~"@{css-prefix}icon"; 3 | 4 | .@{message-prefix-cls} { 5 | font-size: @font-size-small; 6 | position: fixed; 7 | z-index: @zindex-message; 8 | width: 100%; 9 | top: 16px; 10 | left: 0; 11 | 12 | &-notice { 13 | width: auto; 14 | vertical-align: middle; 15 | position: absolute; 16 | left: 50%; 17 | } 18 | 19 | &-notice-content { 20 | position: relative; 21 | right: 50%; 22 | padding: 8px 16px; 23 | //border: 1px solid @border-color-split; 24 | border-radius: @border-radius-small; 25 | box-shadow: @shadow-base; 26 | background: #fff; 27 | display: block; 28 | } 29 | 30 | &-success .@{icon-prefix-cls} { 31 | color: @success-color; 32 | } 33 | 34 | &-error .@{icon-prefix-cls} { 35 | color: @error-color; 36 | } 37 | 38 | &-warning .@{icon-prefix-cls} { 39 | color: @warning-color; 40 | } 41 | 42 | &-info .@{icon-prefix-cls}, 43 | &-loading .@{icon-prefix-cls} { 44 | color: @primary-color; 45 | } 46 | 47 | .@{icon-prefix-cls} { 48 | margin-right: 8px; 49 | font-size: 14px; 50 | top: 1px; 51 | position: relative; 52 | } 53 | } -------------------------------------------------------------------------------- /src/renderer/store/modules/excel.js: -------------------------------------------------------------------------------- 1 | import * as types from '../mutations_types' 2 | import _ from 'lodash' 3 | 4 | // state 5 | const state = { 6 | excelData: {} 7 | } 8 | 9 | // mutations 10 | const mutations = { 11 | // 设置excelData 12 | [types.SET_EXCEL_DATA] (state, data) { 13 | if(data.data) 14 | state.excelData = data 15 | else { 16 | state.excelData.data = [] 17 | state.excelData.data.length = 0 18 | state.excelData.data.push(data) 19 | } 20 | }, 21 | // 添加excelData 22 | [types.ADD_EXCEL_DATA] (state, data) { 23 | state.excelData.data.push(data) 24 | }, 25 | // 修改excelData 26 | [types.EDIT_EXCEL_DATA] (state, data) { 27 | let newArr = state.excelData.data.map((item, idx) => { 28 | if(item[0] === data[0]) { 29 | item[1] = data[1] 30 | item[2] = data[2] 31 | item[3] = data[3] 32 | } 33 | if(item[1] === data[1] && item[2] === data[2]) { 34 | item[0] = data[0] 35 | } 36 | return item 37 | }) 38 | state.excelData.data = newArr 39 | }, 40 | // 删除excelData 41 | [types.DEL_EXCEL_DATA] (state, data) { 42 | let newArr = _.remove(state.excelData.data, n => { 43 | return n[0] !== data[0] 44 | }) 45 | state.excelData.data = newArr 46 | }, 47 | } 48 | 49 | // 导出state, mutations 50 | export default { 51 | state, 52 | mutations 53 | } 54 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/common/article.less: -------------------------------------------------------------------------------- 1 | .ivu-article { 2 | h1{ 3 | font-size: 26px; 4 | font-weight: normal; 5 | } 6 | h2{ 7 | font-size: 20px; 8 | font-weight: normal; 9 | } 10 | h3{ 11 | font-size: 16px; 12 | font-weight: normal; 13 | } 14 | h4{ 15 | font-size: 14px; 16 | font-weight: normal; 17 | } 18 | h5{ 19 | font-size: 12px; 20 | font-weight: normal; 21 | } 22 | h6{ 23 | font-size: 12px; 24 | font-weight: normal; 25 | } 26 | 27 | blockquote{ 28 | padding: 5px 5px 3px 10px; 29 | line-height: 1.5; 30 | border-left: 4px solid #ddd; 31 | margin-bottom: 20px; 32 | color: #666; 33 | font-size: 14px; 34 | } 35 | 36 | ul:not([class^="ivu-"]){ 37 | padding-left: 40px; 38 | list-style-type: disc; 39 | } 40 | li:not([class^="ivu-"]){ 41 | margin-bottom: 5px; 42 | font-size: 14px; 43 | } 44 | ul ul:not([class^="ivu-"]), ol ul:not([class^="ivu-"]){ 45 | list-style-type: circle; 46 | } 47 | 48 | p{ 49 | margin: 5px; 50 | font-size: 14px; 51 | } 52 | 53 | a[target="_blank"]:after{ 54 | content: "\F220"; 55 | font-family: Ionicons; 56 | color: #aaa; 57 | margin-left: 3px; 58 | } 59 | } -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/collapse.less: -------------------------------------------------------------------------------- 1 | @collapse-prefix-cls: ~"@{css-prefix}collapse"; 2 | 3 | .@{collapse-prefix-cls}{ 4 | background-color: @background-color-base; 5 | border-radius: 3px; 6 | border: 1px solid @border-color-base; 7 | 8 | & > &-item{ 9 | border-top: 1px solid @border-color-base; 10 | &:first-child { 11 | border-top: 0; 12 | } 13 | 14 | > .@{collapse-prefix-cls}-header{ 15 | height: 38px; 16 | line-height: 38px; 17 | padding-left: 32px; 18 | color: #666; 19 | cursor: pointer; 20 | position: relative; 21 | 22 | > i{ 23 | transition: transform @transition-time @ease-in-out; 24 | } 25 | } 26 | } 27 | & > &-item&-item-active > &-header > i{ 28 | transform: rotate(90deg); 29 | } 30 | 31 | &-content{ 32 | //display: none; 33 | overflow: hidden; 34 | color: @text-color; 35 | padding: 0 16px; 36 | background-color: #fff; 37 | 38 | & > &-box { 39 | padding-top: 16px; 40 | padding-bottom: 16px; 41 | } 42 | } 43 | &-item-active > &-content{ 44 | //display: block; 45 | } 46 | &-item:last-child { 47 | > .@{collapse-prefix-cls}-content { 48 | border-radius: 0 0 3px 3px; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/renderer/components/Page/Map.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 36 | 37 | 38 | 60 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/badge.less: -------------------------------------------------------------------------------- 1 | @badge-prefix-cls: ~"@{css-prefix}badge"; 2 | 3 | .@{badge-prefix-cls} { 4 | position: relative; 5 | display: inline-block; 6 | line-height: 1; 7 | vertical-align: middle; 8 | 9 | &-count { 10 | position: absolute; 11 | transform: translateX(50%); 12 | top: -10px; 13 | right: 0; 14 | height: 20px; 15 | border-radius: 10px; 16 | min-width: 20px; 17 | background: @error-color; 18 | border: 1px solid transparent; 19 | color: #fff; 20 | line-height: 18px; 21 | text-align: center; 22 | padding: 0 6px; 23 | font-size: 12px; 24 | white-space: nowrap; 25 | transform-origin: -10% center; 26 | z-index: 10; 27 | box-shadow: 0 0 0 1px #fff; 28 | 29 | a, 30 | a:hover { 31 | color: #fff; 32 | } 33 | 34 | &-alone { 35 | top: auto; 36 | display: block; 37 | position: relative; 38 | transform: translateX(0); 39 | } 40 | } 41 | 42 | &-dot { 43 | position: absolute; 44 | transform: translateX(-50%); 45 | transform-origin: 0 center; 46 | top: -4px; 47 | right: -8px; 48 | height: 8px; 49 | width: 8px; 50 | border-radius: 100%; 51 | background: @error-color; 52 | z-index: 10; 53 | box-shadow: 0 0 0 1px #fff; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/spin.less: -------------------------------------------------------------------------------- 1 | @spin-prefix-cls: ~"@{css-prefix}spin"; 2 | @spin-dot-size-small: 12px; 3 | @spin-dot-size: 20px; 4 | @spin-dot-size-large: 32px; 5 | 6 | .@{spin-prefix-cls} { 7 | color: @primary-color; 8 | vertical-align: middle; 9 | text-align: center; 10 | 11 | &-dot { 12 | position: relative; 13 | display: block; 14 | border-radius: 50%; 15 | background-color: @primary-color; 16 | .square(@spin-dot-size); 17 | animation: ani-spin-bounce 1s 0s ease-in-out infinite; 18 | } 19 | 20 | &-large &-dot { 21 | .square(@spin-dot-size-large); 22 | } 23 | 24 | &-small &-dot { 25 | .square(@spin-dot-size-small); 26 | } 27 | 28 | &-fix { 29 | position: absolute; 30 | top: 0; 31 | bottom: 0; 32 | left: 0; 33 | right: 0; 34 | z-index: @zindex-spin; 35 | display: table; 36 | .square(100%); 37 | background-color: #fff; 38 | } 39 | 40 | &-fix &-main { 41 | display: table-cell; 42 | vertical-align: middle; 43 | .square(inherit); 44 | } 45 | 46 | &-fix &-dot { 47 | display: inline-block; 48 | } 49 | 50 | &-text, 51 | &-show-text &-dot { 52 | display: none; 53 | } 54 | 55 | &-show-text &-text { 56 | display: block; 57 | } 58 | } 59 | 60 | @keyframes ani-spin-bounce { 61 | 0% { 62 | transform: scale(0); 63 | } 64 | 65 | 100% { 66 | transform: scale(1); 67 | opacity: 0; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/input.less: -------------------------------------------------------------------------------- 1 | @input-prefix-cls: ~"@{css-prefix}input"; 2 | 3 | .@{input-prefix-cls} { 4 | .input; 5 | &-wrapper{ 6 | display: inline-block; 7 | width: 100%; 8 | position: relative; 9 | vertical-align: middle; 10 | } 11 | &-icon { 12 | width: 32px; 13 | height: @input-height-base; 14 | line-height: @input-height-base; 15 | font-size: 16px; 16 | text-align: center; 17 | color: @subsidiary-color; 18 | position: absolute; 19 | right: 0; 20 | z-index: 1; 21 | } 22 | &-icon-validate{ 23 | display: none; 24 | } 25 | 26 | &-icon + &{ 27 | padding-right: 32px; 28 | } 29 | 30 | &-wrapper-large &-icon{ 31 | font-size: 18px; 32 | height: @input-height-large; 33 | line-height: @input-height-large; 34 | } 35 | &-wrapper-small &-icon{ 36 | width: 24px; 37 | font-size: 14px; 38 | height: @input-height-small; 39 | line-height: @input-height-small; 40 | 41 | + .@{input-prefix-cls} { 42 | padding-right: 24px; 43 | } 44 | } 45 | } 46 | 47 | .@{input-prefix-cls}-group{ 48 | .input-group(~"@{input-prefix-cls}"); 49 | } 50 | 51 | .@{form-item-prefix-cls}-error{ 52 | .@{input-prefix-cls}{ 53 | .input-error; 54 | &-icon{ 55 | color: @error-color; 56 | } 57 | } 58 | .@{input-prefix-cls}-group{ 59 | .input-group-error; 60 | } 61 | } 62 | .@{form-item-prefix-cls}-validating{ 63 | .@{input-prefix-cls}{ 64 | &-icon-validate{ 65 | display: inline-block; 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/custom.css: -------------------------------------------------------------------------------- 1 | .ivu-menu-horizontal { 2 | height: 51px; 3 | line-height: 51px; 4 | } 5 | .ivu-menu-horizontal .ivu-menu-item, 6 | .ivu-menu-horizontal .ivu-menu-submenu { 7 | float: right; 8 | } 9 | .ivu-select-dropdown { 10 | background-color: #262529; 11 | } 12 | .ivu-menu-horizontal { 13 | height: 51px; 14 | line-height: 51px; 15 | } 16 | .ivu-menu-horizontal .ivu-menu-item, 17 | .ivu-menu-horizontal .ivu-menu-submenu { 18 | float: right; 19 | } 20 | .ivu-select-dropdown { 21 | background-color: #262529; 22 | } 23 | .ivu-input { 24 | border: none; 25 | } 26 | .ivu-input { 27 | margin-bottom: 12px; 28 | } 29 | .ivu-input:hover { 30 | border: none; 31 | background-color: #131414; 32 | } 33 | .ivu-input:focus { 34 | background: #131414; 35 | } 36 | .ivu-icon.ivu-icon-android-map { 37 | margin-right: 10px; 38 | } 39 | .ivu-input-group { 40 | margin-bottom: 12px; 41 | margin-left: auto; 42 | margin-right: auto; 43 | } 44 | .ivu-input-group-append { 45 | background-color: #1E1E21; 46 | } 47 | .ivu-select-selection { 48 | border: 0; 49 | background-color: #222222; 50 | } 51 | .ivu-select-single .ivu-select-selection { 52 | border: 0; 53 | background-color: #222222; 54 | } 55 | .ivu-spin-large .ivu-spin-dot { 56 | width: 55px; 57 | height: 55px; 58 | } 59 | .ivu-spin-dot { 60 | position: fixed; 61 | top: 42%; 62 | left: 48%; 63 | transform: translate(-50%, -50%); 64 | background-color: #ff3300; 65 | } 66 | .ivu-spin-fix { 67 | opacity: .9; 68 | background-color: #222222; 69 | } 70 | .ivu-modal-content { 71 | background-color: #1D1C1F; 72 | } 73 | .ivu-modal-header { 74 | border-bottom: 0; 75 | } 76 | .ivu-modal-footer { 77 | border-top: 0; 78 | } 79 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/common/base.less: -------------------------------------------------------------------------------- 1 | @import "normalize"; 2 | 3 | * { 4 | box-sizing: border-box; 5 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 6 | } 7 | 8 | *:before, 9 | *:after { 10 | box-sizing: border-box; 11 | } 12 | 13 | body { 14 | font-family: @font-family; 15 | font-size: @font-size-small; 16 | line-height: @line-height-base; 17 | color: @text-color; 18 | background-color: @body-background; 19 | -webkit-font-smoothing: antialiased; 20 | -moz-osx-font-smoothing: grayscale; 21 | } 22 | 23 | body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, form, fieldset, legend, input, textarea, p, blockquote, th, td, hr, button, article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { 24 | margin: 0; 25 | padding: 0; 26 | } 27 | 28 | button, input, select, textarea { 29 | font-family: inherit; 30 | font-size: inherit; 31 | line-height: inherit; 32 | } 33 | 34 | ul, 35 | ol { 36 | list-style: none; 37 | } 38 | 39 | input::-ms-clear, input::-ms-reveal { 40 | display: none; 41 | } 42 | 43 | a { 44 | color: @link-color; 45 | background: transparent; 46 | text-decoration: none; 47 | outline: none; 48 | cursor: pointer; 49 | transition: color @transition-time ease; 50 | 51 | &:hover { 52 | color: @link-hover-color; 53 | } 54 | 55 | &:active { 56 | color: @link-active-color; 57 | } 58 | 59 | &:active, 60 | &:hover { 61 | outline: 0; 62 | text-decoration: none; 63 | } 64 | 65 | &[disabled] { 66 | color: #ccc; 67 | cursor: @cursor-disabled; 68 | pointer-events: none; 69 | } 70 | } 71 | 72 | code, 73 | kbd, 74 | pre, 75 | samp { 76 | font-family: @code-family; 77 | } 78 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/mixins/select.less: -------------------------------------------------------------------------------- 1 | .select-item(@size-class, @item-class) { 2 | .@{item-class} { 3 | margin: 0; 4 | padding: 7px 16px; 5 | clear: both; 6 | color: @text-color; 7 | font-size: @font-size-small !important; 8 | white-space: nowrap; 9 | list-style: none; 10 | cursor: pointer; 11 | transition: background @transition-time @ease-in-out; 12 | 13 | &:hover{ 14 | background: @background-color-select-hover; 15 | } 16 | 17 | &-focus { 18 | background: @background-color-select-hover; 19 | } 20 | 21 | &-disabled { 22 | color: @btn-disable-color; 23 | cursor: @cursor-disabled; 24 | 25 | &:hover { 26 | color: @btn-disable-color; 27 | background-color: #fff; 28 | cursor: @cursor-disabled; 29 | } 30 | } 31 | 32 | &-selected ,&-selected:hover{ 33 | color: #fff; 34 | background: @selected-color; 35 | } 36 | 37 | &-selected&-focus { 38 | background: shade(@selected-color, 10%); 39 | } 40 | 41 | &-divided{ 42 | margin-top: 5px; 43 | border-top: 1px solid @border-color-split; 44 | &:before{ 45 | content: ''; 46 | height: 5px; 47 | display: block; 48 | margin: 0 -16px; 49 | background-color: #fff; 50 | position: relative; 51 | top: -7px; 52 | } 53 | } 54 | } 55 | 56 | .@{size-class}-large .@{item-class} { 57 | padding: 7px 16px 8px; 58 | font-size: @font-size-base !important; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /.electron-vue/webpack.main.config.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | process.env.BABEL_ENV = 'main' 4 | 5 | const path = require('path') 6 | const { dependencies } = require('../package.json') 7 | const webpack = require('webpack') 8 | 9 | const BabiliWebpackPlugin = require('babili-webpack-plugin') 10 | 11 | let mainConfig = { 12 | entry: { 13 | main: path.join(__dirname, '../src/main/index.js') 14 | }, 15 | externals: [ 16 | ...Object.keys(dependencies || {}) 17 | ], 18 | module: { 19 | rules: [ 20 | { 21 | test: /\.js$/, 22 | use: 'babel-loader', 23 | exclude: /node_modules/ 24 | }, 25 | { 26 | test: /\.node$/, 27 | use: 'node-loader' 28 | } 29 | ] 30 | }, 31 | node: { 32 | __dirname: process.env.NODE_ENV !== 'production', 33 | __filename: process.env.NODE_ENV !== 'production' 34 | }, 35 | output: { 36 | filename: '[name].js', 37 | libraryTarget: 'commonjs2', 38 | path: path.join(__dirname, '../dist/electron') 39 | }, 40 | plugins: [ 41 | new webpack.NoEmitOnErrorsPlugin() 42 | ], 43 | resolve: { 44 | extensions: ['.js', '.json', '.node'] 45 | }, 46 | target: 'electron-main' 47 | } 48 | 49 | /** 50 | * Adjust mainConfig for development settings 51 | */ 52 | if (process.env.NODE_ENV !== 'production') { 53 | mainConfig.plugins.push( 54 | new webpack.DefinePlugin({ 55 | '__static': `"${path.join(__dirname, '../static').replace(/\\/g, '\\\\')}"` 56 | }) 57 | ) 58 | } 59 | 60 | /** 61 | * Adjust mainConfig for production settings 62 | */ 63 | if (process.env.NODE_ENV === 'production') { 64 | mainConfig.plugins.push( 65 | new BabiliWebpackPlugin(), 66 | new webpack.DefinePlugin({ 67 | 'process.env.NODE_ENV': '"production"' 68 | }) 69 | ) 70 | } 71 | 72 | module.exports = mainConfig 73 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/rate.less: -------------------------------------------------------------------------------- 1 | @rate-prefix-cls: ~"@{css-prefix}rate"; 2 | 3 | .@{rate-prefix-cls} { 4 | display: inline-block; 5 | margin: 0; 6 | padding: 0; 7 | font-size: 20px; 8 | vertical-align: middle; 9 | font-weight: normal; 10 | font-style: normal; 11 | 12 | &-disabled &-star { 13 | &:before, 14 | &-content:before { 15 | cursor: default; 16 | } 17 | &:hover { 18 | transform: scale(1); 19 | } 20 | } 21 | 22 | &-star { 23 | display: inline-block; 24 | margin: 0; 25 | padding: 0; 26 | margin-right: 8px; 27 | position: relative; 28 | font-family: 'Ionicons'; 29 | transition: all 0.3s ease; 30 | 31 | &:hover { 32 | transform: scale(1.1); 33 | } 34 | 35 | &:before, 36 | &-content:before { 37 | color: #e9e9e9; 38 | cursor: pointer; 39 | content: "\F4B3"; 40 | transition: all @transition-time @ease-in-out; 41 | display: block; 42 | } 43 | 44 | &-content { 45 | position: absolute; 46 | left: 0; 47 | top: 0; 48 | width: 50%; 49 | height: 100%; 50 | overflow: hidden; 51 | &:before { 52 | color: transparent; 53 | } 54 | } 55 | 56 | &-half &-content:before, 57 | &-full:before { 58 | color: @rate-star-color; 59 | } 60 | 61 | &-half:hover &-content:before, 62 | &-full:hover:before { 63 | color: tint(@rate-star-color, 20%); 64 | } 65 | } 66 | &-text { 67 | margin-left: 8px; 68 | vertical-align: middle; 69 | display: inline-block; 70 | font-size: @font-size-small; 71 | } 72 | } -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/form.less: -------------------------------------------------------------------------------- 1 | @form-prefix-cls: ~"@{css-prefix}form"; 2 | @form-item-prefix-cls: ~"@{form-prefix-cls}-item"; 3 | 4 | .@{form-prefix-cls} { 5 | .@{form-item-prefix-cls}-label { 6 | text-align: right; 7 | vertical-align: middle; 8 | float: left; 9 | font-size: @font-size-small; 10 | color: @text-color; 11 | line-height: 1; 12 | padding: 10px 12px 10px 0; 13 | box-sizing: border-box; 14 | } 15 | &-label-left .@{form-item-prefix-cls}-label { 16 | text-align: left; 17 | } 18 | &-label-top .@{form-item-prefix-cls}-label { 19 | float: none; 20 | display: inline-block; 21 | padding: 0 0 10px 0; 22 | } 23 | &-inline{ 24 | .@{form-item-prefix-cls} { 25 | display: inline-block; 26 | margin-right: 10px; 27 | vertical-align: top; 28 | } 29 | } 30 | } 31 | 32 | .@{form-item-prefix-cls} { 33 | margin-bottom: 24px; 34 | vertical-align: top; 35 | .clearfix(); 36 | &-content { 37 | position: relative; 38 | line-height: 32px; 39 | font-size: @font-size-small; 40 | } 41 | & & { 42 | margin-bottom: 0; 43 | } 44 | & & &-content { 45 | margin-left: 0!important; 46 | } 47 | 48 | &-error-tip{ 49 | position: absolute; 50 | top: 100%; 51 | left: 0; 52 | line-height: 1; 53 | padding-top: 6px; 54 | color: @error-color; 55 | } 56 | 57 | &-required { 58 | .@{form-item-prefix-cls}-label:before { 59 | content: '*'; 60 | display: inline-block; 61 | margin-right: 4px; 62 | line-height: 1; 63 | font-family: SimSun; 64 | font-size: @font-size-small; 65 | color: @error-color; 66 | } 67 | } 68 | &-error { 69 | // todo 70 | } 71 | } -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/common/layout.less: -------------------------------------------------------------------------------- 1 | .@{row-prefix-cls} { 2 | .make-row(); 3 | display: block; 4 | 5 | &-flex { 6 | display: flex; 7 | flex-direction: row; 8 | flex-wrap: wrap; 9 | 10 | &:before, 11 | &:after { 12 | display: flex; 13 | } 14 | // x轴原点 15 | &-start { 16 | justify-content: flex-start; 17 | } 18 | // x轴居中 19 | &-center { 20 | justify-content: center; 21 | } 22 | // x轴反方向 23 | &-end { 24 | justify-content: flex-end; 25 | } 26 | // x轴平分 27 | &-space-between { 28 | justify-content: space-between; 29 | } 30 | // x轴有间隔地平分 31 | &-space-around { 32 | justify-content: space-around; 33 | } 34 | // 顶部对齐 35 | &-top { 36 | align-items: flex-start; 37 | } 38 | // 居中对齐 39 | &-middle { 40 | align-items: center; 41 | } 42 | // 底部对齐 43 | &-bottom { 44 | align-items: flex-end; 45 | } 46 | }; 47 | } 48 | 49 | .@{col-prefix-cls} { 50 | position: relative; 51 | display: block; 52 | } 53 | 54 | .make-grid(); 55 | 56 | // Extra small grid 57 | // 58 | // Columns, offsets, pushes, and pulls for extra small devices like 59 | // smartphones. 60 | 61 | .make-grid(-xs); 62 | 63 | // Small grid 64 | // 65 | // Columns, offsets, pushes, and pulls for the small device range, from phones 66 | // to tablets. 67 | 68 | @media (min-width: @screen-sm-min) { 69 | .make-grid(-sm); 70 | } 71 | 72 | 73 | // Medium grid 74 | // 75 | // Columns, offsets, pushes, and pulls for the desktop device range. 76 | 77 | @media (min-width: @screen-md-min) { 78 | .make-grid(-md); 79 | } 80 | 81 | 82 | // Large grid 83 | // 84 | // Columns, offsets, pushes, and pulls for the large desktop device range. 85 | 86 | @media (min-width: @screen-lg-min) { 87 | .make-grid(-lg); 88 | } 89 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/mixins/layout.less: -------------------------------------------------------------------------------- 1 | @row-prefix-cls: ~"@{css-prefix}row"; 2 | @col-prefix-cls: ~"@{css-prefix}col"; 3 | 4 | .make-row(@gutter: @grid-gutter-width) { 5 | position: relative; 6 | margin-left: (@gutter / -2); 7 | margin-right: (@gutter / -2); 8 | height: auto; 9 | .clearfix; 10 | } 11 | 12 | .float-grid-columns(@class) { 13 | .col(@index) { // initial 14 | @item: ~".@{col-prefix-cls}-span@{class}-@{index}"; 15 | .col((@index + 1), @item); 16 | } 17 | .col(@index, @list) when (@index =< @grid-columns) { // general 18 | @item: ~".@{col-prefix-cls}-span@{class}-@{index}"; 19 | .col((@index + 1), ~"@{list}, @{item}"); 20 | } 21 | .col(@index, @list) when (@index > @grid-columns) { // terminal 22 | @{list} { 23 | float: left; 24 | flex: 0 0 auto; 25 | } 26 | } 27 | .col(1); // kickstart it 28 | } 29 | 30 | .loop-grid-columns(@index, @class) when (@index > 0) { 31 | .@{col-prefix-cls}-span@{class}-@{index} { 32 | display: block; 33 | width: percentage((@index / @grid-columns)); 34 | } 35 | .@{col-prefix-cls}@{class}-push-@{index} { 36 | left: percentage((@index / @grid-columns)); 37 | } 38 | .@{col-prefix-cls}@{class}-pull-@{index} { 39 | right: percentage((@index / @grid-columns)); 40 | } 41 | .@{col-prefix-cls}@{class}-offset-@{index} { 42 | margin-left: percentage((@index / @grid-columns)); 43 | } 44 | .@{col-prefix-cls}@{class}-order-@{index} { 45 | order: @index; 46 | } 47 | .loop-grid-columns((@index - 1), @class); 48 | } 49 | 50 | .loop-grid-columns(@index, @class) when (@index = 0) { 51 | .@{col-prefix-cls}-span@{class}-@{index} { 52 | display: none; 53 | } 54 | .@{col-prefix-cls}@{class}-push-@{index} { 55 | left: auto; 56 | } 57 | .@{col-prefix-cls}@{class}-pull-@{index} { 58 | right: auto; 59 | } 60 | } 61 | 62 | .make-grid(@class: ~'') { 63 | .float-grid-columns(@class); 64 | .loop-grid-columns(@grid-columns, @class); 65 | } -------------------------------------------------------------------------------- /src/renderer/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import storage from 'store' 4 | import Home from '@/components/Page/Home' 5 | 6 | Vue.use(Router) 7 | 8 | const router = new Router({ 9 | routes: [ 10 | { 11 | path: '/', 12 | name: 'Home', 13 | component: Home, 14 | meta: { requiresAuth: true } 15 | }, { 16 | path: '/auth', 17 | name: 'Auth', 18 | component: resolve => require(['@/components/Page/Auth'], resolve), 19 | children: [ 20 | { 21 | path: '/auth/login', 22 | name: 'Login', 23 | component: resolve => require(['@/components/Page/Login'], resolve) 24 | }, { 25 | path: '/auth/register', 26 | name: 'Register', 27 | component: resolve => require(['@/components/Page/Register'], resolve) 28 | }, { 29 | path: '/auth/forgetPassword', 30 | name: 'ForgetPassword', 31 | component: resolve => require(['@/components/Page/ForgetPassword'], resolve) 32 | } 33 | ] 34 | }, { 35 | path: '/chart', 36 | name: 'Chart', 37 | component: resolve => require(['@/components/Page/Chart'], resolve) 38 | }, { 39 | path: '/myProject', 40 | name: 'MyProject', 41 | component: resolve => require(['@/components/Page/MyProject'], resolve) 42 | }, { 43 | path: '/map', 44 | name: 'Map', 45 | component: resolve => require(['@/components/Page/Map'], resolve) 46 | }, { 47 | path: '/help', 48 | name: 'Help', 49 | component: resolve => require(['@/components/Page/Help'], resolve) 50 | }, { 51 | path: '*', 52 | redirect: '/' 53 | } 54 | ] 55 | }) 56 | 57 | router.beforeEach((to, from, next) => { 58 | let token = storage.get('accessToken') 59 | if (to.matched.some(record => record.meta.requiresAuth)) { 60 | if (!token) { 61 | next({ 62 | path: '/auth/login', 63 | query: { redirect: to.fullPath } 64 | }) 65 | } else { 66 | next() 67 | } 68 | } else { 69 | next() 70 | } 71 | }) 72 | 73 | export default router 74 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/progress.less: -------------------------------------------------------------------------------- 1 | @progress-prefix-cls: ~"@{css-prefix}progress"; 2 | 3 | .@{progress-prefix-cls} { 4 | display: inline-block; 5 | width: 100%; 6 | font-size: @font-size-small; 7 | position: relative; 8 | 9 | &-outer { 10 | display: inline-block; 11 | width: 100%; 12 | margin-right: 0; 13 | padding-right: 0; 14 | 15 | .@{progress-prefix-cls}-show-info & { 16 | padding-right: 55px; 17 | margin-right: -55px; 18 | } 19 | } 20 | 21 | &-inner { 22 | display: inline-block; 23 | width: 100%; 24 | background-color: #f3f3f3; 25 | border-radius: 100px; 26 | vertical-align: middle; 27 | } 28 | 29 | &-bg { 30 | border-radius: 100px; 31 | background-color: @info-color; 32 | transition: all @transition-time linear; 33 | position: relative; 34 | } 35 | 36 | &-text { 37 | display: inline-block; 38 | margin-left: 5px; 39 | text-align: left; 40 | font-size: 1em; 41 | vertical-align: middle; 42 | } 43 | 44 | &-active { 45 | .@{progress-prefix-cls}-bg:before { 46 | content: ''; 47 | opacity: 0; 48 | position: absolute; 49 | top: 0; 50 | left: 0; 51 | right: 0; 52 | bottom: 0; 53 | background: #fff; 54 | border-radius: 10px; 55 | animation: ivu-progress-active 2s @ease-in-out infinite; 56 | } 57 | } 58 | 59 | &-wrong { 60 | .@{progress-prefix-cls}-bg { 61 | background-color: @error-color; 62 | } 63 | .@{progress-prefix-cls}-text { 64 | color: @error-color; 65 | } 66 | } 67 | 68 | &-success { 69 | .@{progress-prefix-cls}-bg { 70 | background-color: @success-color; 71 | } 72 | .@{progress-prefix-cls}-text { 73 | color: @success-color; 74 | } 75 | } 76 | } 77 | 78 | @keyframes ivu-progress-active { 79 | 0% { 80 | opacity: .3; 81 | width: 0; 82 | } 83 | 100% { 84 | opacity: 0; 85 | width: 100%; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/renderer/components/Layout/Header.vue: -------------------------------------------------------------------------------- 1 | 27 | 28 | 29 | 71 | 72 | 73 | 81 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/upload.less: -------------------------------------------------------------------------------- 1 | @upload-prefix-cls: ~"@{css-prefix}upload"; 2 | 3 | .@{upload-prefix-cls} { 4 | input[type="file"]{ 5 | display: none; 6 | } 7 | 8 | &-list{ 9 | margin-top: 8px; 10 | 11 | &-file{ 12 | padding: 4px; 13 | color: @text-color; 14 | border-radius: @border-radius-small; 15 | transition: background-color @transition-time @ease-in-out; 16 | overflow: hidden; 17 | position: relative; 18 | 19 | & > span{ 20 | cursor: pointer; 21 | transition: color @transition-time @ease-in-out; 22 | i{ 23 | display: inline-block; 24 | width: @font-size-small; 25 | height: @font-size-small; 26 | color: @text-color; 27 | text-align: center; 28 | } 29 | } 30 | 31 | &:hover{ 32 | background: @input-disabled-bg; 33 | & > span{ 34 | color: @primary-color; 35 | i{ 36 | color: @text-color; 37 | } 38 | } 39 | .@{upload-prefix-cls}-list-remove{ 40 | opacity: 1; 41 | } 42 | } 43 | } 44 | &-remove{ 45 | opacity: 0; 46 | font-size: 18px; 47 | cursor: pointer; 48 | float: right; 49 | margin-right: 4px; 50 | color: @legend-color; 51 | transition: all @transition-time ease; 52 | &:hover{ 53 | color: #444; 54 | } 55 | } 56 | } 57 | 58 | &-drag{ 59 | background: #fff; 60 | border: 1px dashed @border-color-base; 61 | border-radius: @border-radius-small; 62 | text-align: center; 63 | cursor: pointer; 64 | position: relative; 65 | overflow: hidden; 66 | transition: border-color @transition-time ease; 67 | 68 | &:hover{ 69 | border: 1px dashed @primary-color; 70 | } 71 | } 72 | &-dragOver{ 73 | border: 2px dashed @primary-color; 74 | } 75 | } -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/timeline.less: -------------------------------------------------------------------------------- 1 | @timeline-prefix-cls: ~"@{css-prefix}timeline"; 2 | @timeline-color: @border-color-split; 3 | 4 | .@{timeline-prefix-cls} { 5 | list-style: none; 6 | margin: 0; 7 | padding: 0; 8 | 9 | &-item { 10 | margin: 0 !important; 11 | padding: 0 0 12px 0; 12 | list-style: none; 13 | position: relative; 14 | 15 | &-tail { 16 | height: 100%; 17 | border-left: 1px solid @timeline-color; 18 | position: absolute; 19 | left: 6px; 20 | top: 0; 21 | } 22 | 23 | &-pending &-tail { 24 | display: none; 25 | } 26 | 27 | &-head { 28 | width: 13px; 29 | height: 13px; 30 | background-color: #fff; 31 | border-radius: 50%; 32 | border: 1px solid transparent; 33 | position: absolute; 34 | 35 | &-blue { 36 | border-color: @primary-color; 37 | color: @primary-color; 38 | } 39 | &-red { 40 | border-color: @error-color; 41 | color: @error-color; 42 | } 43 | &-green { 44 | border-color: @success-color; 45 | color: @success-color; 46 | } 47 | } 48 | 49 | &-head-custom { 50 | width: 40px; 51 | height: auto; 52 | margin-top: 6px; 53 | padding: 3px 0; 54 | text-align: center; 55 | line-height: 1; 56 | border: 0; 57 | border-radius: 0; 58 | font-size: @font-size-base; 59 | position: absolute; 60 | left: -13px; 61 | transform: translateY(-50%); 62 | } 63 | 64 | &-content { 65 | padding: 1px 1px 10px 24px; 66 | font-size: @font-size-small; 67 | position: relative; 68 | top: -3px; 69 | } 70 | 71 | &:last-child { 72 | .@{timeline-prefix-cls}-item-tail { 73 | display: none; 74 | } 75 | } 76 | } 77 | 78 | &&-pending &-item:nth-last-of-type(2) { 79 | 80 | .@{timeline-prefix-cls}-item-tail { 81 | border-left: 1px dotted @timeline-color; 82 | } 83 | .@{timeline-prefix-cls}-item-content { 84 | min-height: 48px; 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/renderer/server/ajax.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | import { Message } from 'iview' 3 | import jsonp from 'jsonp' 4 | import qs from 'qs' 5 | axios.defaults.timeout = 1000000; //响应时间 6 | axios.defaults.headers.post['Content-Type'] = 'application/json' //通信格式 7 | // axios.defaults.baseURL = 'http://127.0.0.1:7001' //配置接口地址 8 | // axios.defaults.baseURL = 'https://api.imap.trevor.top' //配置接口地址 9 | axios.defaults.baseURL = 'https://imap.leanapp.cn' //配置接口地址 10 | 11 | export default { 12 | // POST请求 13 | post({...obj}) { 14 | return new Promise((resolve,reject) => { 15 | axios.post(obj.url, obj.data).then(data => { 16 | if(data.data.code === 0) { 17 | Message.success(data.data.msg) 18 | resolve(data.data) 19 | } else if (data.data.code === 1) { 20 | Message.warning(data.data.msg) 21 | resolve(data.data) 22 | } else if (data.data.code === 2) { 23 | Message.error(data.data.msg) 24 | resolve(data.data) 25 | } else { 26 | Message.error(data.data.msg) 27 | resolve(data.data) 28 | } 29 | }).catch(data => { 30 | reject(data) 31 | }) 32 | }) 33 | }, 34 | // GET请求 35 | get({...obj}) { 36 | return new Promise((resolve,reject) => { 37 | axios.get(obj.url, { params: obj.data }).then(data => { 38 | if(data.status === 200) { 39 | resolve(data.data) 40 | } else if(data.data.code === 0) { 41 | resolve(data.data) 42 | } else if (data.data.code === 1) { 43 | Message.warning(data.data.msg) 44 | resolve(data.data) 45 | } else if (data.data.code === 2) { 46 | Message.error(data.data.msg) 47 | resolve(data.data) 48 | } else { 49 | Message.error(data.data.msg) 50 | resolve(data.data) 51 | } 52 | }).catch(data => { 53 | reject(data) 54 | }) 55 | }) 56 | }, 57 | // jsonp 58 | jsonp({...obj}) { 59 | return new Promise((resolve, reject) => { 60 | jsonp(obj.url + '?' + qs.stringify(obj.data) , null, (err, data) => { 61 | if (err) { 62 | Message.error('请求错误') 63 | } else if(data.status === 0) { 64 | resolve(data) 65 | } else if(data.code === 0) { 66 | resolve(data) 67 | } else { 68 | if(getUrlRelativePath() === '/') 69 | resolve(data) 70 | else 71 | Message.error('请求错误') 72 | } 73 | }) 74 | }) 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/cascader.less: -------------------------------------------------------------------------------- 1 | @cascader-prefix-cls: ~"@{css-prefix}cascader"; 2 | @cascader-item-prefix-cls: ~"@{css-prefix}cascader-menu-item"; 3 | 4 | .@{cascader-prefix-cls} { 5 | //position: relative; 6 | line-height: normal; 7 | 8 | &-rel{ 9 | position: relative; 10 | } 11 | 12 | .@{css-prefix}input{ 13 | display: block; 14 | cursor: pointer; 15 | } 16 | &-disabled .@{css-prefix}input{ 17 | cursor: @cursor-disabled; 18 | } 19 | 20 | .@{cascader-prefix-cls}-arrow:nth-of-type(1) { 21 | display: none; 22 | cursor: pointer; 23 | } 24 | 25 | &:hover { 26 | .@{cascader-prefix-cls}-arrow:nth-of-type(1) { 27 | display: inline-block; 28 | } 29 | } 30 | &-show-clear:hover .@{cascader-prefix-cls}-arrow:nth-of-type(2){ 31 | display: none; 32 | } 33 | 34 | &-arrow { 35 | .inner-arrow(); 36 | } 37 | &-visible &-arrow:nth-of-type(2) { 38 | transform: rotate(180deg); 39 | } 40 | 41 | .@{select-dropdown-prefix-cls} { 42 | width: auto; 43 | padding: 0; 44 | white-space: nowrap; 45 | overflow: visible; 46 | } 47 | 48 | .select-item(@cascader-prefix-cls, @cascader-item-prefix-cls); 49 | 50 | &-menu{ 51 | display: inline-block; 52 | min-width: 100px; 53 | height: 180px; 54 | margin: 0; 55 | padding: 5px 0 !important; 56 | vertical-align: top; 57 | list-style: none; 58 | border-right: 1px solid @border-color-split; 59 | overflow: auto; 60 | 61 | &:first-child { 62 | 63 | } 64 | &:last-child { 65 | border-right-color: transparent; 66 | margin-right: -1px; 67 | } 68 | &:only-child { 69 | 70 | } 71 | 72 | & &-item{ 73 | position: relative; 74 | padding-right: 24px; 75 | transition: all @transition-time @ease-in-out; 76 | 77 | i{ 78 | font-size: @font-size-small; 79 | position: absolute; 80 | right: 15px; 81 | top: 50%; 82 | margin-top: -6px; 83 | } 84 | 85 | &-active{ 86 | background-color: @background-color-select-hover; 87 | color: @primary-color; 88 | } 89 | } 90 | } 91 | } 92 | 93 | .@{form-item-prefix-cls}-error{ 94 | .@{cascader-prefix-cls} { 95 | &-arrow{ 96 | color: @error-color; 97 | } 98 | } 99 | } -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/mixins/tooltip.less: -------------------------------------------------------------------------------- 1 | .popper(@arrow, @arrow-width, @arrow-distance, @bg){ 2 | display: block; 3 | visibility: visible; 4 | font-size: @font-size-small; 5 | line-height: @line-height-base; 6 | position: absolute; 7 | z-index: @zindex-tooltip; 8 | 9 | &[x-placement^="top"] { 10 | padding: @arrow-width 0 @arrow-distance 0; 11 | } 12 | &[x-placement^="right"] { 13 | padding: 0 @arrow-width 0 @arrow-distance; 14 | } 15 | &[x-placement^="bottom"] { 16 | padding: @arrow-distance 0 @arrow-width 0; 17 | } 18 | &[x-placement^="left"] { 19 | padding: 0 @arrow-distance 0 @arrow-width; 20 | } 21 | 22 | &[x-placement^="top"] .@{arrow} { 23 | bottom: @arrow-distance - @arrow-width; 24 | border-width: @arrow-width @arrow-width 0; 25 | border-top-color: @bg; 26 | } 27 | &[x-placement="top"] .@{arrow} { 28 | left: 50%; 29 | margin-left: -@arrow-width; 30 | } 31 | &[x-placement="top-start"] .@{arrow} { 32 | left: 16px; 33 | } 34 | &[x-placement="top-end"] .@{arrow} { 35 | right: 16px; 36 | } 37 | 38 | &[x-placement^="right"] .@{arrow} { 39 | left: @arrow-distance - @arrow-width; 40 | border-width: @arrow-width @arrow-width @arrow-width 0; 41 | border-right-color: @bg; 42 | } 43 | &[x-placement="right"] .@{arrow} { 44 | top: 50%; 45 | margin-top: -@arrow-width; 46 | } 47 | &[x-placement="right-start"] .@{arrow} { 48 | top: 8px; 49 | } 50 | &[x-placement="right-end"] .@{arrow} { 51 | bottom: 8px; 52 | } 53 | 54 | &[x-placement^="left"] .@{arrow} { 55 | right: @arrow-distance - @arrow-width; 56 | border-width: @arrow-width 0 @arrow-width @arrow-width; 57 | border-left-color: @bg; 58 | } 59 | &[x-placement="left"] .@{arrow} { 60 | top: 50%; 61 | margin-top: -@arrow-width; 62 | } 63 | &[x-placement="left-start"] .@{arrow} { 64 | top: 8px; 65 | } 66 | &[x-placement="left-end"] .@{arrow} { 67 | bottom: 8px; 68 | } 69 | 70 | &[x-placement^="bottom"] .@{arrow} { 71 | top: @arrow-distance - @arrow-width; 72 | border-width: 0 @arrow-width @arrow-width; 73 | border-bottom-color: @bg; 74 | } 75 | &[x-placement="bottom"] .@{arrow} { 76 | left: 50%; 77 | margin-left: -@arrow-width; 78 | } 79 | &[x-placement="bottom-start"] .@{arrow} { 80 | left: 16px; 81 | } 82 | &[x-placement="bottom-end"] .@{arrow} { 83 | right: 16px; 84 | } 85 | } -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/alert.less: -------------------------------------------------------------------------------- 1 | @alert-prefix-cls: ~"@{css-prefix}alert"; 2 | @icon-prefix-cls: ~"@{css-prefix}icon"; 3 | 4 | .@{alert-prefix-cls}{ 5 | position: relative; 6 | padding: 8px 48px 8px 16px; 7 | border-radius: @border-radius-base; 8 | color: @text-color; 9 | font-size: @font-size-small; 10 | line-height: 16px; 11 | margin-bottom: 10px; 12 | 13 | &&-with-icon{ 14 | padding: 8px 48px 8px 38px; 15 | } 16 | 17 | &-icon { 18 | font-size: @font-size-base; 19 | top: 8px; 20 | left: 16px; 21 | position: absolute; 22 | } 23 | 24 | &-desc { 25 | font-size: @font-size-small; 26 | color: @text-color; 27 | line-height: 21px; 28 | display: none; 29 | text-align: justify; 30 | } 31 | 32 | &-success { 33 | border: 1px solid tint(@success-color, 80%); 34 | background-color: tint(@success-color, 90%); 35 | .@{alert-prefix-cls}-icon { 36 | color: @success-color; 37 | } 38 | } 39 | 40 | &-info { 41 | border: 1px solid tint(@primary-color, 80%); 42 | background-color: tint(@primary-color, 90%); 43 | .@{alert-prefix-cls}-icon { 44 | color: @primary-color; 45 | } 46 | } 47 | 48 | &-warning { 49 | border: 1px solid tint(@warning-color, 80%); 50 | background-color: tint(@warning-color, 90%); 51 | .@{alert-prefix-cls}-icon { 52 | color: @warning-color; 53 | } 54 | } 55 | 56 | &-error { 57 | border: 1px solid tint(@error-color, 80%); 58 | background-color: tint(@error-color, 90%); 59 | .@{alert-prefix-cls}-icon { 60 | color: @error-color; 61 | } 62 | } 63 | 64 | &-close { 65 | .content-close(-3px); 66 | } 67 | 68 | &-with-desc { 69 | padding: 16px; 70 | position: relative; 71 | border-radius: @border-radius-base; 72 | margin-bottom: 10px; 73 | color: @text-color; 74 | line-height: 1.5; 75 | } 76 | 77 | &-with-desc&-with-icon{ 78 | padding: 16px 16px 16px 69px; 79 | } 80 | 81 | &-with-desc &-desc{ 82 | display: block; 83 | } 84 | 85 | &-with-desc &-message { 86 | font-size: 14px; 87 | color: @title-color; 88 | display: block; 89 | } 90 | 91 | &-with-desc &-icon { 92 | top: 50%; 93 | left: 24px; 94 | margin-top: -21px; 95 | font-size: 28px; 96 | } 97 | 98 | &-with-banner{ 99 | border-radius: 0; 100 | } 101 | } -------------------------------------------------------------------------------- /src/renderer/components/Ui/DelPointModal.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 95 | 96 | 97 | 103 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "imap", 3 | "productName": "iMap", 4 | "version": "0.0.3-beta", 5 | "author": "xizhouh@gmail.com", 6 | "description": "iMap让你生成专属你的旅行地图", 7 | "license": "MIT", 8 | "main": "./dist/electron/main.js", 9 | "scripts": { 10 | "build": "node .electron-vue/build.js", 11 | "build:darwin": "cross-env BUILD_TARGET=darwin node .electron-vue/build.js", 12 | "build:linux": "cross-env BUILD_TARGET=linux node .electron-vue/build.js", 13 | "build:mas": "cross-env BUILD_TARGET=mas node .electron-vue/build.js", 14 | "build:win32": "cross-env BUILD_TARGET=win32 node .electron-vue/build.js", 15 | "build:clean": "cross-env BUILD_TARGET=clean node .electron-vue/build.js", 16 | "build:web": "cross-env BUILD_TARGET=web node .electron-vue/build.js", 17 | "dev": "node .electron-vue/dev-runner.js", 18 | "pack": "npm run pack:main && npm run pack:renderer", 19 | "pack:main": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.main.config.js", 20 | "pack:renderer": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.renderer.config.js", 21 | "postinstall": "" 22 | }, 23 | "dependencies": { 24 | "axios": "^0.16.1", 25 | "iview": "^2.4.0", 26 | "jsonp": "^0.2.1", 27 | "left-pad": "1.1.3", 28 | "less": "^2.7.2", 29 | "less-loader": "^4.0.5", 30 | "lodash": "^4.17.4", 31 | "particles.js": "^2.0.0", 32 | "qs": "^6.5.1", 33 | "store": "^2.0.12", 34 | "vue": "^2.3.3", 35 | "vue-echarts": "^2.4.1", 36 | "vue-electron": "^1.0.6", 37 | "vue-particles": "^1.0.9", 38 | "vue-router": "^2.5.3", 39 | "vuex": "^2.3.1" 40 | }, 41 | "devDependencies": { 42 | "babel-core": "^6.25.0", 43 | "babel-loader": "^7.1.1", 44 | "babel-plugin-transform-runtime": "^6.23.0", 45 | "babel-preset-env": "^1.6.0", 46 | "babel-preset-stage-0": "^6.24.1", 47 | "babel-register": "^6.24.1", 48 | "babili-webpack-plugin": "^0.1.2", 49 | "cfonts": "^1.1.3", 50 | "chalk": "^2.1.0", 51 | "copy-webpack-plugin": "^4.2.0", 52 | "cross-env": "^5.0.5", 53 | "css-loader": "^0.28.4", 54 | "del": "^3.0.0", 55 | "devtron": "^1.4.0", 56 | "electron": "^1.7.5", 57 | "electron-debug": "^1.4.0", 58 | "electron-devtools-installer": "^2.2.0", 59 | "electron-packager": "^8.5.0", 60 | "electron-rebuild": "^1.1.3", 61 | "extract-text-webpack-plugin": "^3.0.0", 62 | "file-loader": "^0.11.2", 63 | "html-webpack-plugin": "^2.30.1", 64 | "multispinner": "^0.2.1", 65 | "node-loader": "^0.6.0", 66 | "style-loader": "^0.18.2", 67 | "url-loader": "^0.5.9", 68 | "vue-html-loader": "^1.2.4", 69 | "vue-loader": "^13.0.5", 70 | "vue-style-loader": "^3.0.1", 71 | "vue-template-compiler": "^2.4.2", 72 | "webpack": "^3.5.2", 73 | "webpack-dev-server": "^2.7.1", 74 | "webpack-hot-middleware": "^2.18.2" 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/animation/slide.less: -------------------------------------------------------------------------------- 1 | .slide-motion(@className, @keyframeName) { 2 | .make-motion(@className, @keyframeName); 3 | .@{className}-enter, .@{className}-appear { 4 | opacity: 0; 5 | animation-timing-function: @ease-in-out; 6 | } 7 | .@{className}-leave { 8 | animation-timing-function: @ease-in-out; 9 | } 10 | } 11 | 12 | .slide-motion(slide-up, ivuSlideUp); 13 | .slide-motion(slide-down, ivuSlideDown); 14 | .slide-motion(slide-left, ivuSlideLeft); 15 | .slide-motion(slide-right, ivuSlideRight); 16 | 17 | @keyframes ivuSlideUpIn { 18 | 0% { 19 | opacity: 0; 20 | transform-origin: 0% 0%; 21 | transform: scaleY(.8); 22 | } 23 | 100% { 24 | opacity: 1; 25 | transform-origin: 0% 0%; 26 | transform: scaleY(1); 27 | } 28 | } 29 | 30 | @keyframes ivuSlideUpOut { 31 | 0% { 32 | opacity: 1; 33 | transform-origin: 0% 0%; 34 | transform: scaleY(1); 35 | } 36 | 100% { 37 | opacity: 0; 38 | transform-origin: 0% 0%; 39 | transform: scaleY(.8); 40 | } 41 | } 42 | 43 | @keyframes ivuSlideDownIn { 44 | 0% { 45 | opacity: 0; 46 | transform-origin: 100% 100%; 47 | transform: scaleY(.8); 48 | } 49 | 100% { 50 | opacity: 1; 51 | transform-origin: 100% 100%; 52 | transform: scaleY(1); 53 | } 54 | } 55 | 56 | @keyframes ivuSlideDownOut { 57 | 0% { 58 | opacity: 1; 59 | transform-origin: 100% 100%; 60 | transform: scaleY(1); 61 | } 62 | 100% { 63 | opacity: 0; 64 | transform-origin: 100% 100%; 65 | transform: scaleY(.8); 66 | } 67 | } 68 | 69 | @keyframes ivuSlideLeftIn { 70 | 0% { 71 | opacity: 0; 72 | transform-origin: 0% 0%; 73 | transform: scaleX(.8); 74 | } 75 | 100% { 76 | opacity: 1; 77 | transform-origin: 0% 0%; 78 | transform: scaleX(1); 79 | } 80 | } 81 | 82 | @keyframes ivuSlideLeftOut { 83 | 0% { 84 | opacity: 1; 85 | transform-origin: 0% 0%; 86 | transform: scaleX(1); 87 | } 88 | 100% { 89 | opacity: 0; 90 | transform-origin: 0% 0%; 91 | transform: scaleX(.8); 92 | } 93 | } 94 | 95 | @keyframes ivuSlideRightIn { 96 | 0% { 97 | opacity: 0; 98 | transform-origin: 100% 0%; 99 | transform: scaleX(.8); 100 | } 101 | 100% { 102 | opacity: 1; 103 | transform-origin: 100% 0%; 104 | transform: scaleX(1); 105 | } 106 | } 107 | 108 | @keyframes ivuSlideRightOut { 109 | 0% { 110 | opacity: 1; 111 | transform-origin: 100% 0%; 112 | transform: scaleX(1); 113 | } 114 | 100% { 115 | opacity: 0; 116 | transform-origin: 100% 0%; 117 | transform: scaleX(.8); 118 | } 119 | } -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/slider.less: -------------------------------------------------------------------------------- 1 | @slider-prefix-cls: ~"@{css-prefix}slider"; 2 | 3 | .@{slider-prefix-cls} { 4 | line-height: normal; 5 | &-wrap{ 6 | width: 100%; 7 | height: @slider-height; 8 | margin: @slider-margin; 9 | background-color: @border-color-split; 10 | border-radius: @btn-border-radius-small; 11 | vertical-align: middle; 12 | position: relative; 13 | cursor: pointer; 14 | } 15 | 16 | &-button-wrap{ 17 | .square(@slider-button-wrap-size); 18 | text-align: center; 19 | background-color: transparent; 20 | position: absolute; 21 | top: @slider-button-wrap-offset; 22 | transform: translateX(-50%); 23 | 24 | .@{tooltip-prefix-cls} { 25 | display: block; 26 | user-select: none; 27 | } 28 | } 29 | 30 | &-button{ 31 | width: 12px; 32 | height: 12px; 33 | border: 2px solid @slider-color; 34 | border-radius: 50%; 35 | background-color: #fff; 36 | transition: all @transition-time linear; 37 | 38 | &:hover, 39 | &-dragging 40 | { 41 | border-color: @primary-color; 42 | transform: scale(1.5); 43 | } 44 | 45 | &:hover{ 46 | cursor: grab; 47 | } 48 | &-dragging, 49 | &-dragging:hover 50 | { 51 | cursor: grabbing; 52 | } 53 | } 54 | 55 | &-bar{ 56 | height: @slider-height; 57 | background: @slider-color; 58 | border-radius: @btn-border-radius-small; 59 | position: absolute; 60 | } 61 | 62 | &-stop{ 63 | position: absolute; 64 | .square(@slider-height); 65 | border-radius: 50%; 66 | background-color: @slider-disabled-color; 67 | transform: translateX(-50%); 68 | } 69 | } 70 | 71 | .@{slider-prefix-cls}-disabled{ 72 | cursor: @cursor-disabled; 73 | 74 | .@{slider-prefix-cls}-wrap{ 75 | background-color: @slider-disabled-color; 76 | cursor: @cursor-disabled; 77 | } 78 | .@{slider-prefix-cls}-bar{ 79 | background-color: @slider-disabled-color; 80 | } 81 | 82 | .@{slider-prefix-cls}-button{ 83 | border-color: @slider-disabled-color; 84 | 85 | &:hover, 86 | &-dragging 87 | { 88 | border-color: @slider-disabled-color; 89 | } 90 | &:hover{ 91 | cursor: @cursor-disabled; 92 | } 93 | &-dragging, 94 | &-dragging:hover 95 | { 96 | cursor: @cursor-disabled; 97 | } 98 | } 99 | } 100 | 101 | .@{slider-prefix-cls}-input{ 102 | .@{slider-prefix-cls}-wrap{ 103 | width: auto; 104 | margin-right: 100px; 105 | } 106 | 107 | .@{input-number-prefix-cls}{ 108 | float: right; 109 | margin-top: -14px; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/switch.less: -------------------------------------------------------------------------------- 1 | @switch-prefix-cls: ~"@{css-prefix}switch"; 2 | 3 | .@{switch-prefix-cls} { 4 | display: inline-block; 5 | width: 48px; 6 | height: 24px; 7 | line-height: 22px; 8 | border-radius: 24px; 9 | vertical-align: middle; 10 | border: 1px solid #ccc; 11 | background-color: #ccc; 12 | position: relative; 13 | cursor: pointer; 14 | user-select: none; 15 | transition: all @transition-time @ease-in-out; 16 | 17 | &-inner { 18 | color: #fff; 19 | font-size: @font-size-small; 20 | position: absolute; 21 | left: 25px; 22 | 23 | i { 24 | width: 12px; 25 | height: 12px; 26 | text-align: center; 27 | } 28 | } 29 | 30 | &:after { 31 | content: ''; 32 | width: 20px; 33 | height: 20px; 34 | border-radius: 20px; 35 | background-color: #fff; 36 | position: absolute; 37 | left: 1px; 38 | top: 1px; 39 | cursor: pointer; 40 | transition: left @transition-time @ease-in-out, width @transition-time @ease-in-out; 41 | } 42 | 43 | &:active:after { 44 | width: 26px; 45 | } 46 | 47 | &:focus { 48 | box-shadow: 0 0 0 2px fade(@primary-color, 20%); 49 | outline: 0; 50 | } 51 | 52 | &:focus:hover { 53 | box-shadow: none; 54 | } 55 | 56 | &-small { 57 | width: 24px; 58 | height: 12px; 59 | line-height: 10px; 60 | &:after { 61 | width: 10px; 62 | height: 10px; 63 | top: 0; 64 | left: 0; 65 | } 66 | &:active:after { 67 | width: 14px; 68 | } 69 | } 70 | 71 | &-small&-checked:after { 72 | left: 12px; 73 | } 74 | 75 | &-small:active&-checked:after { 76 | left: 8px; 77 | } 78 | 79 | &-large{ 80 | width: 60px; 81 | &:active:after { 82 | width: 26px; 83 | } 84 | } 85 | 86 | &-large:active:after { 87 | width: 32px; 88 | } 89 | 90 | &-large&-checked:after { 91 | left: 37px; 92 | } 93 | 94 | &-large:active&-checked:after { 95 | left: 25px; 96 | } 97 | 98 | &-checked { 99 | border-color: @primary-color; 100 | background-color: @primary-color; 101 | 102 | .@{switch-prefix-cls}-inner { 103 | left: 8px; 104 | } 105 | 106 | &:after { 107 | left: 25px; 108 | } 109 | 110 | &:active:after { 111 | left: 19px; 112 | } 113 | } 114 | 115 | &-disabled { 116 | cursor: @cursor-disabled; 117 | background: #f3f3f3; 118 | border-color: #f3f3f3; 119 | 120 | &:after { 121 | background: #ccc; 122 | cursor: not-allowed; 123 | } 124 | 125 | .@{switch-prefix-cls}-inner { 126 | color: #ccc; 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/renderer/data/map.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash' 2 | 3 | let data = [] 4 | let geoCoordMap = [] 5 | 6 | /** 7 | * 赋值函数 8 | * @param {Array} data 9 | */ 10 | const convertData = data => { 11 | let res = [] 12 | for(let i = 0; i < data.length; i++) { 13 | let geoCoord = _.last(geoCoordMap[i]) 14 | if(geoCoord) { 15 | res.push({ 16 | name: data[i].name, 17 | value: geoCoord.concat(data[i].value).concat(data[i].time) 18 | }) 19 | } 20 | } 21 | return res 22 | } 23 | 24 | export default { 25 | /** 26 | * 返回地图数据 27 | * @param {Object} obj 28 | * @param {Object} options 29 | */ 30 | getMapData({...obj}, options) { 31 | data = [] 32 | geoCoordMap = [] 33 | let geoModel = [] 34 | try { 35 | obj.data.forEach((item, idx) => { 36 | let dataModel = { 37 | name: '', 38 | value: 84, 39 | time: '' 40 | } 41 | geoModel.push(item[0]) 42 | let itemArr = [+item[1], +item[2]] 43 | geoModel.push(itemArr) 44 | dataModel.name = item[0] 45 | dataModel.time = item[3] 46 | data.push(dataModel) 47 | }) 48 | geoCoordMap = _.chunk(geoModel, 2) 49 | return { 50 | backgroundColor: '#302F33', 51 | title: { 52 | text: '我的足迹', 53 | subtext: 'My footprints', 54 | left: 'center', 55 | textStyle: { 56 | color: '#fff' 57 | } 58 | }, 59 | tooltip: { 60 | trigger: 'item' 61 | }, 62 | toolbox: { 63 | show: true, 64 | right: '40', 65 | feature: { 66 | saveAsImage: { 67 | show: true, 68 | pixelRatio: 3 69 | } 70 | } 71 | }, 72 | legend: { 73 | orient: 'vertical', 74 | y: 'bottom', 75 | x: 'right', 76 | data: ['去过的地点'], 77 | textStyle: { 78 | color: '#fff' 79 | } 80 | }, 81 | geo: { 82 | map: options.mapType, 83 | zoom: options.zoom, 84 | roam: options.roam ? 'move' : false, 85 | label: { 86 | emphasis: { 87 | show: false 88 | } 89 | }, 90 | itemStyle: { 91 | normal: { 92 | areaColor: '#323c48', 93 | borderColor: '#111' 94 | }, 95 | emphasis: { 96 | areaColor: '#2a333d' 97 | } 98 | } 99 | }, 100 | series: [ 101 | { 102 | name: '去过的地点', 103 | type: 'effectScatter', 104 | coordinateSystem: 'geo', 105 | data: convertData(data), 106 | symbolSize: val => val[2] / 10, 107 | showEffectOn: 'render', 108 | rippleEffect: { 109 | brushType: 'stroke' 110 | }, 111 | hoverAnimation: true, 112 | label: { 113 | normal: { 114 | formatter: '{b}', 115 | position: 'right', 116 | show: true 117 | } 118 | }, 119 | itemStyle: { 120 | normal: { 121 | color: '#f4e925', 122 | shadowBlur: 10, 123 | shadowColor: '#333' 124 | } 125 | }, 126 | zlevel: 1 127 | } 128 | ] 129 | } 130 | } catch(error) { 131 | this.$Message.error('Excel内容格式错误') 132 | } 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/renderer/components/Page/Register.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/renderer/components/Page/ForgetPassword.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /src/renderer/components/Ui/EditPointModal.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 23 | 105 | 106 | 107 | 113 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/modal.less: -------------------------------------------------------------------------------- 1 | @modal-prefix-cls: ~"@{css-prefix}modal"; 2 | @confirm-prefix-cls: ~"@{css-prefix}modal-confirm"; 3 | 4 | .@{modal-prefix-cls} { 5 | width: auto; 6 | margin: 0 auto; 7 | position: relative; 8 | outline: none; 9 | top: 100px; 10 | 11 | &-hidden { 12 | display: none !important; 13 | } 14 | 15 | &-wrap { 16 | position: fixed; 17 | overflow: auto; 18 | top: 0; 19 | right: 0; 20 | bottom: 0; 21 | left: 0; 22 | z-index: @zindex-modal; 23 | -webkit-overflow-scrolling: touch; 24 | outline: 0; 25 | } 26 | 27 | &-wrap * { 28 | box-sizing: border-box; 29 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 30 | } 31 | 32 | &-mask { 33 | .mask; 34 | } 35 | 36 | &-content { 37 | position: relative; 38 | background-color: #fff; 39 | border: 0; 40 | border-radius: @border-radius-base; 41 | background-clip: padding-box; 42 | } 43 | 44 | &-header { 45 | .content-header; 46 | } 47 | 48 | &-close { 49 | .content-close(1px, 31px); 50 | } 51 | 52 | &-body { 53 | padding: 16px; 54 | font-size: 12px; 55 | line-height: 1.5; 56 | } 57 | 58 | &-footer { 59 | border-top: 1px solid @border-color-split; 60 | padding: 12px 18px 12px 18px; 61 | text-align: right; 62 | button + button { 63 | margin-left: 8px; 64 | margin-bottom: 0; 65 | } 66 | } 67 | } 68 | 69 | @media (max-width: 768px) { 70 | .@{modal-prefix-cls} { 71 | width: auto !important; 72 | margin: 10px; 73 | } 74 | .vertical-center-modal { 75 | .@{modal-prefix-cls} { 76 | flex: 1; 77 | } 78 | } 79 | } 80 | 81 | .@{confirm-prefix-cls} { 82 | padding: 0 4px; 83 | &-head { 84 | 85 | &-title { 86 | display: inline-block; 87 | font-size: @font-size-base; 88 | color: @title-color; 89 | font-weight: 700; 90 | } 91 | } 92 | 93 | &-body{ 94 | margin-top: 6px; 95 | padding-left: 48px; 96 | padding-top: 18px; 97 | font-size: @font-size-small; 98 | color: @text-color; 99 | position: relative; 100 | 101 | &-icon { 102 | font-size: 36px; 103 | position: absolute; 104 | top: 0; 105 | left: 0; 106 | 107 | &-info { 108 | color: @primary-color; 109 | } 110 | &-success { 111 | color: @success-color; 112 | } 113 | &-warning { 114 | color: @warning-color; 115 | } 116 | &-error { 117 | color: @error-color; 118 | } 119 | &-confirm { 120 | color: @warning-color; 121 | } 122 | } 123 | } 124 | 125 | &-footer{ 126 | margin-top: 40px; 127 | text-align: right; 128 | 129 | button + button { 130 | margin-left: 8px; 131 | margin-bottom: 0; 132 | } 133 | } 134 | } -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/notice.less: -------------------------------------------------------------------------------- 1 | @notice-prefix-cls: ~"@{css-prefix}notice"; 2 | @icon-prefix-cls: ~"@{css-prefix}icon"; 3 | 4 | @notice-width: 335px; 5 | @notice-padding: 16px; 6 | @notice-margin-bottom: 10px; 7 | 8 | .@{notice-prefix-cls} { 9 | width: @notice-width; 10 | margin-right: 24px; 11 | position: fixed; 12 | z-index: @zindex-notification; 13 | 14 | &-notice { 15 | margin-bottom: @notice-margin-bottom; 16 | padding: @notice-padding; 17 | //border: 1px solid @border-color-split; 18 | border-radius: @border-radius-small; 19 | box-shadow: @shadow-base; 20 | background: #fff; 21 | line-height: 1; 22 | position: relative; 23 | overflow: hidden; 24 | 25 | &-close { 26 | position: absolute; 27 | right: 16px; 28 | top: 15px; 29 | color: #999; 30 | outline: none; 31 | 32 | i{ 33 | .close-base(-3px); 34 | } 35 | } 36 | 37 | &-with-desc{ 38 | .@{notice-prefix-cls}-notice-close{ 39 | top: 11px; 40 | } 41 | } 42 | } 43 | 44 | &-title { 45 | font-size: @font-size-base; 46 | color: @title-color; 47 | padding-right: 10px; 48 | overflow: hidden; 49 | text-overflow: ellipsis; 50 | white-space: nowrap; 51 | } 52 | &-with-desc &-title{ 53 | margin-bottom: 8px; 54 | } 55 | &-with-desc&-with-icon &-title{ 56 | margin-left: 51px; 57 | } 58 | 59 | &-desc { 60 | font-size: 12px; 61 | color: @legend-color; 62 | text-align: justify; 63 | line-height: 1.5; 64 | } 65 | &-with-desc&-with-icon &-desc{ 66 | margin-left: 51px; 67 | } 68 | 69 | &-with-icon &-title{ 70 | margin-left: 26px; 71 | } 72 | 73 | &-icon { 74 | position: absolute; 75 | left: 20px; 76 | margin-top: -1px; 77 | font-size: 16px; 78 | 79 | &-success { 80 | color: @success-color; 81 | } 82 | &-info { 83 | color: @primary-color; 84 | } 85 | &-warning { 86 | color: @warning-color; 87 | } 88 | &-error { 89 | color: @error-color; 90 | } 91 | } 92 | &-with-desc &-icon{ 93 | font-size: 36px; 94 | } 95 | 96 | &-custom-content{ 97 | &:after{ 98 | content: ""; 99 | display: block; 100 | width: 4px; 101 | position: absolute; 102 | top: 0; 103 | bottom: 0; 104 | left: 0; 105 | } 106 | } 107 | &-with-normal{ 108 | &:after{ 109 | background: @primary-color; 110 | } 111 | } 112 | &-with-info{ 113 | &:after{ 114 | background: @primary-color; 115 | } 116 | } 117 | &-with-success{ 118 | &:after{ 119 | background: @success-color; 120 | } 121 | } 122 | &-with-warning{ 123 | &:after{ 124 | background: @warning-color; 125 | } 126 | } 127 | &-with-error{ 128 | &:after{ 129 | background: @error-color; 130 | } 131 | } 132 | } -------------------------------------------------------------------------------- /src/renderer/components/Page/Help.vue: -------------------------------------------------------------------------------- 1 | 55 | 56 | 57 | 73 | 74 | 75 | 126 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/button.less: -------------------------------------------------------------------------------- 1 | @btn-prefix-cls: ~"@{css-prefix}btn"; 2 | 3 | .@{btn-prefix-cls} { 4 | .btn; 5 | .btn-default; 6 | 7 | &-long{ 8 | width: 100%; 9 | } 10 | 11 | & > .ivu-icon + span, & > span + .ivu-icon{ 12 | margin-left: 4px; 13 | } 14 | 15 | &-primary { 16 | .btn-primary; 17 | 18 | .@{btn-prefix-cls}-group:not(.@{btn-prefix-cls}-group-vertical) &:not(:first-child):not(:last-child) { 19 | border-right-color: @btn-group-border; 20 | border-left-color: @btn-group-border; 21 | } 22 | 23 | .@{btn-prefix-cls}-group:not(.@{btn-prefix-cls}-group-vertical) &:first-child { 24 | &:not(:last-child) { 25 | border-right-color: @btn-group-border; 26 | &[disabled] { 27 | border-right-color: @btn-default-border; 28 | } 29 | } 30 | } 31 | 32 | .@{btn-prefix-cls}-group:not(.@{btn-prefix-cls}-group-vertical) &:last-child:not(:first-child), 33 | .@{btn-prefix-cls}-group:not(.@{btn-prefix-cls}-group-vertical) & + .@{btn-prefix-cls} { 34 | border-left-color: @btn-group-border; 35 | &[disabled] { 36 | border-left-color: @btn-default-border; 37 | } 38 | } 39 | 40 | .@{btn-prefix-cls}-group-vertical &:not(:first-child):not(:last-child) { 41 | border-top-color: @btn-group-border; 42 | border-bottom-color: @btn-group-border; 43 | } 44 | 45 | .@{btn-prefix-cls}-group-vertical &:first-child { 46 | &:not(:last-child) { 47 | border-bottom-color: @btn-group-border; 48 | &[disabled] { 49 | border-top-color: @btn-default-border; 50 | } 51 | } 52 | } 53 | 54 | .@{btn-prefix-cls}-group-vertical &:last-child:not(:first-child), 55 | .@{btn-prefix-cls}-group-vertical & + .@{btn-prefix-cls} { 56 | border-top-color: @btn-group-border; 57 | &[disabled] { 58 | border-bottom-color: @btn-default-border; 59 | } 60 | } 61 | } 62 | 63 | &-ghost { 64 | .btn-ghost; 65 | } 66 | 67 | &-dashed{ 68 | .btn-dashed; 69 | } 70 | 71 | &-text{ 72 | .btn-text; 73 | } 74 | 75 | &-success { 76 | .btn-color(@success-color); 77 | } 78 | 79 | &-warning { 80 | .btn-color(@warning-color); 81 | } 82 | 83 | &-error { 84 | .btn-color(@error-color); 85 | } 86 | 87 | &-info { 88 | .btn-color(@info-color); 89 | } 90 | 91 | &-circle, 92 | &-circle-outline { 93 | .btn-circle(@btn-prefix-cls); 94 | } 95 | 96 | &:before { 97 | position: absolute; 98 | top: -1px; 99 | left: -1px; 100 | bottom: -1px; 101 | right: -1px; 102 | background: #fff; 103 | opacity: 0.35; 104 | content: ''; 105 | border-radius: inherit; 106 | z-index: 1; 107 | transition: opacity @transition-time; 108 | pointer-events: none; 109 | display: none; 110 | } 111 | 112 | &&-loading { 113 | pointer-events: none; 114 | position: relative; 115 | 116 | &:before { 117 | display: block; 118 | } 119 | } 120 | 121 | &-group { 122 | .btn-group(@btn-prefix-cls); 123 | } 124 | 125 | &-group-vertical { 126 | .btn-group-vertical(@btn-prefix-cls); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /.electron-vue/webpack.web.config.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | process.env.BABEL_ENV = 'web' 4 | 5 | const path = require('path') 6 | const webpack = require('webpack') 7 | 8 | const BabiliWebpackPlugin = require('babili-webpack-plugin') 9 | const CopyWebpackPlugin = require('copy-webpack-plugin') 10 | const ExtractTextPlugin = require('extract-text-webpack-plugin') 11 | const HtmlWebpackPlugin = require('html-webpack-plugin') 12 | 13 | let webConfig = { 14 | devtool: '#cheap-module-eval-source-map', 15 | entry: { 16 | web: path.join(__dirname, '../src/renderer/main.js') 17 | }, 18 | module: { 19 | rules: [ 20 | { 21 | test: /\.css$/, 22 | use: ExtractTextPlugin.extract({ 23 | fallback: 'style-loader', 24 | use: 'css-loader' 25 | }) 26 | }, 27 | { 28 | test: /\.html$/, 29 | use: 'vue-html-loader' 30 | }, 31 | { 32 | test: /\.js$/, 33 | use: 'babel-loader', 34 | include: [ path.resolve(__dirname, '../src/renderer') ], 35 | exclude: /node_modules/ 36 | }, 37 | { 38 | test: /\.vue$/, 39 | use: { 40 | loader: 'vue-loader', 41 | options: { 42 | extractCSS: true, 43 | loaders: { 44 | sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax=1', 45 | scss: 'vue-style-loader!css-loader!sass-loader' 46 | } 47 | } 48 | } 49 | }, 50 | { 51 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 52 | use: { 53 | loader: 'url-loader', 54 | query: { 55 | limit: 10000, 56 | name: 'imgs/[name].[ext]' 57 | } 58 | } 59 | }, 60 | { 61 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 62 | use: { 63 | loader: 'url-loader', 64 | query: { 65 | limit: 10000, 66 | name: 'fonts/[name].[ext]' 67 | } 68 | } 69 | } 70 | ] 71 | }, 72 | plugins: [ 73 | new ExtractTextPlugin('styles.css'), 74 | new HtmlWebpackPlugin({ 75 | filename: 'index.html', 76 | template: path.resolve(__dirname, '../src/index.ejs'), 77 | minify: { 78 | collapseWhitespace: true, 79 | removeAttributeQuotes: true, 80 | removeComments: true 81 | }, 82 | nodeModules: false 83 | }), 84 | new webpack.DefinePlugin({ 85 | 'process.env.IS_WEB': 'true' 86 | }), 87 | new webpack.HotModuleReplacementPlugin(), 88 | new webpack.NoEmitOnErrorsPlugin() 89 | ], 90 | output: { 91 | filename: '[name].js', 92 | path: path.join(__dirname, '../dist/web') 93 | }, 94 | resolve: { 95 | alias: { 96 | '@': path.join(__dirname, '../src/renderer'), 97 | 'vue$': 'vue/dist/vue.esm.js' 98 | }, 99 | extensions: ['.js', '.vue', '.json', '.css'] 100 | }, 101 | target: 'web' 102 | } 103 | 104 | /** 105 | * Adjust webConfig for production settings 106 | */ 107 | if (process.env.NODE_ENV === 'production') { 108 | webConfig.devtool = '' 109 | 110 | webConfig.plugins.push( 111 | new BabiliWebpackPlugin(), 112 | new CopyWebpackPlugin([ 113 | { 114 | from: path.join(__dirname, '../static'), 115 | to: path.join(__dirname, '../dist/web/static'), 116 | ignore: ['.*'] 117 | } 118 | ]), 119 | new webpack.DefinePlugin({ 120 | 'process.env.NODE_ENV': '"production"' 121 | }), 122 | new webpack.LoaderOptionsPlugin({ 123 | minimize: true 124 | }) 125 | ) 126 | } 127 | 128 | module.exports = webConfig 129 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/transfer.less: -------------------------------------------------------------------------------- 1 | @transfer-prefix-cls: ~"@{css-prefix}transfer"; 2 | @transfer-item-prefix-cls: ~"@{css-prefix}transfer-list-content-item"; 3 | 4 | .@{transfer-prefix-cls} { 5 | position: relative; 6 | line-height: @line-height-base; 7 | 8 | &-list{ 9 | display: inline-block; 10 | width: 180px; 11 | height: 210px; 12 | font-size: @font-size-small; 13 | vertical-align: middle; 14 | position: relative; 15 | padding-top: 35px; 16 | 17 | &-with-footer{ 18 | padding-bottom: 35px; 19 | } 20 | 21 | &-header { 22 | padding: 8px 16px; 23 | background: @head-bg; 24 | color: @text-color; 25 | border: 1px solid @border-color-base; 26 | border-bottom: 1px solid @border-color-split; 27 | border-radius: @border-radius-base @border-radius-base 0 0; 28 | overflow: hidden; 29 | position: absolute; 30 | top: 0; 31 | left: 0; 32 | width: 100%; 33 | 34 | & > span{ 35 | padding-left: 4px; 36 | } 37 | 38 | &-count { 39 | margin: 0 !important; 40 | float: right; 41 | } 42 | } 43 | 44 | &-body{ 45 | height: 100%; 46 | border: 1px solid @border-color-base; 47 | border-top: none; 48 | border-radius: 0 0 @border-radius-base @border-radius-base; 49 | position: relative; 50 | overflow: hidden; 51 | 52 | &-with-search{ 53 | padding-top: 34px; 54 | } 55 | &-with-footer{ 56 | border-radius: 0; 57 | } 58 | } 59 | 60 | &-content{ 61 | height: 100%; 62 | padding: 4px 0; 63 | overflow: auto; 64 | 65 | &-item{ 66 | overflow: hidden; 67 | white-space: nowrap; 68 | text-overflow: ellipsis; 69 | 70 | & > span{ 71 | padding-left: 4px; 72 | } 73 | } 74 | 75 | &-not-found{ 76 | display: none; 77 | text-align: center; 78 | color: @btn-disable-color; 79 | } 80 | li&-not-found:only-child{ 81 | display: block; 82 | } 83 | } 84 | &-body-with-search &-content{ 85 | padding: 6px 0 0; 86 | } 87 | 88 | &-body-search-wrapper{ 89 | padding: 8px 8px 0; 90 | position: absolute; 91 | top: 0; 92 | left: 0; 93 | right: 0; 94 | } 95 | 96 | &-search{ 97 | position: relative; 98 | } 99 | 100 | &-footer{ 101 | border: 1px solid @border-color-base; 102 | border-top: none; 103 | border-radius: 0 0 @border-radius-base @border-radius-base; 104 | position: absolute; 105 | bottom: 0; 106 | left: 0; 107 | right: 0; 108 | 109 | .clearfix(); 110 | } 111 | } 112 | &-operation { 113 | display: inline-block; 114 | overflow: hidden; 115 | margin: 0 16px; 116 | vertical-align: middle; 117 | 118 | .@{btn-prefix-cls} { 119 | display: block; 120 | min-width: @btn-circle-size-small; 121 | 122 | &:first-child { 123 | margin-bottom: 12px; 124 | } 125 | } 126 | } 127 | } 128 | .select-item(@transfer-prefix-cls, @transfer-item-prefix-cls); -------------------------------------------------------------------------------- /src/renderer/components/Page/MyProject.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 28 | 95 | 96 | 97 | 145 | -------------------------------------------------------------------------------- /.electron-vue/build.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | process.env.NODE_ENV = 'production' 4 | 5 | const { say } = require('cfonts') 6 | const chalk = require('chalk') 7 | const del = require('del') 8 | const packager = require('electron-packager') 9 | const webpack = require('webpack') 10 | const Multispinner = require('multispinner') 11 | 12 | const buildConfig = require('./build.config') 13 | const mainConfig = require('./webpack.main.config') 14 | const rendererConfig = require('./webpack.renderer.config') 15 | const webConfig = require('./webpack.web.config') 16 | 17 | const doneLog = chalk.bgGreen.white(' DONE ') + ' ' 18 | const errorLog = chalk.bgRed.white(' ERROR ') + ' ' 19 | const okayLog = chalk.bgBlue.white(' OKAY ') + ' ' 20 | const isCI = process.env.CI || false 21 | 22 | if (process.env.BUILD_TARGET === 'clean') clean() 23 | else if (process.env.BUILD_TARGET === 'web') web() 24 | else build() 25 | 26 | function clean () { 27 | del.sync(['build/*', '!build/icons', '!build/icons/icon.*']) 28 | console.log(`\n${doneLog}\n`) 29 | process.exit() 30 | } 31 | 32 | function build () { 33 | greeting() 34 | 35 | del.sync(['dist/electron/*', '!.gitkeep']) 36 | 37 | const tasks = ['main', 'renderer'] 38 | const m = new Multispinner(tasks, { 39 | preText: 'building', 40 | postText: 'process' 41 | }) 42 | 43 | let results = '' 44 | 45 | m.on('success', () => { 46 | process.stdout.write('\x1B[2J\x1B[0f') 47 | console.log(`\n\n${results}`) 48 | console.log(`${okayLog}take it away ${chalk.yellow('`electron-packager`')}\n`) 49 | bundleApp() 50 | }) 51 | 52 | pack(mainConfig).then(result => { 53 | results += result + '\n\n' 54 | m.success('main') 55 | }).catch(err => { 56 | m.error('main') 57 | console.log(`\n ${errorLog}failed to build main process`) 58 | console.error(`\n${err}\n`) 59 | process.exit(1) 60 | }) 61 | 62 | pack(rendererConfig).then(result => { 63 | results += result + '\n\n' 64 | m.success('renderer') 65 | }).catch(err => { 66 | m.error('renderer') 67 | console.log(`\n ${errorLog}failed to build renderer process`) 68 | console.error(`\n${err}\n`) 69 | process.exit(1) 70 | }) 71 | } 72 | 73 | function pack (config) { 74 | return new Promise((resolve, reject) => { 75 | webpack(config, (err, stats) => { 76 | if (err) reject(err.stack || err) 77 | else if (stats.hasErrors()) { 78 | let err = '' 79 | 80 | stats.toString({ 81 | chunks: false, 82 | colors: true 83 | }) 84 | .split(/\r?\n/) 85 | .forEach(line => { 86 | err += ` ${line}\n` 87 | }) 88 | 89 | reject(err) 90 | } else { 91 | resolve(stats.toString({ 92 | chunks: false, 93 | colors: true 94 | })) 95 | } 96 | }) 97 | }) 98 | } 99 | 100 | function bundleApp () { 101 | packager(buildConfig, (err, appPaths) => { 102 | if (err) { 103 | console.log(`\n${errorLog}${chalk.yellow('`electron-packager`')} says...\n`) 104 | console.log(err + '\n') 105 | } else { 106 | console.log(`\n${doneLog}\n`) 107 | } 108 | }) 109 | } 110 | 111 | function web () { 112 | del.sync(['dist/web/*', '!.gitkeep']) 113 | webpack(webConfig, (err, stats) => { 114 | if (err || stats.hasErrors()) console.log(err) 115 | 116 | console.log(stats.toString({ 117 | chunks: false, 118 | colors: true 119 | })) 120 | 121 | process.exit() 122 | }) 123 | } 124 | 125 | function greeting () { 126 | const cols = process.stdout.columns 127 | let text = '' 128 | 129 | if (cols > 85) text = 'lets-build' 130 | else if (cols > 60) text = 'lets-|build' 131 | else text = false 132 | 133 | if (text && !isCI) { 134 | say(text, { 135 | colors: ['yellow'], 136 | font: 'simple3d', 137 | space: false 138 | }) 139 | } else console.log(chalk.yellow.bold('\n lets-build')) 140 | console.log() 141 | } 142 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/animation/move.less: -------------------------------------------------------------------------------- 1 | .move-motion(@className, @keyframeName) { 2 | .make-motion(@className, @keyframeName); 3 | .@{className}-enter, .@{className}-appear { 4 | opacity: 0; 5 | animation-timing-function: @ease-in-out; 6 | } 7 | .@{className}-leave { 8 | animation-timing-function: @ease-in-out; 9 | } 10 | } 11 | 12 | .move-motion(move-up, ivuMoveUp); 13 | .move-motion(move-down, ivuMoveDown); 14 | .move-motion(move-left, ivuMoveLeft); 15 | .move-motion(move-right, ivuMoveRight); 16 | 17 | @keyframes ivuMoveDownIn { 18 | 0% { 19 | transform-origin: 0 0; 20 | transform: translateY(100%); 21 | opacity: 0; 22 | } 23 | 100% { 24 | transform-origin: 0 0; 25 | transform: translateY(0%); 26 | opacity: 1; 27 | } 28 | } 29 | 30 | @keyframes ivuMoveDownOut { 31 | 0% { 32 | transform-origin: 0 0; 33 | transform: translateY(0%); 34 | opacity: 1; 35 | } 36 | 100% { 37 | transform-origin: 0 0; 38 | transform: translateY(100%); 39 | opacity: 0; 40 | } 41 | } 42 | 43 | @keyframes ivuMoveLeftIn { 44 | 0% { 45 | transform-origin: 0 0; 46 | transform: translateX(-100%); 47 | opacity: 0; 48 | } 49 | 100% { 50 | transform-origin: 0 0; 51 | transform: translateX(0%); 52 | opacity: 1; 53 | } 54 | } 55 | 56 | @keyframes ivuMoveLeftOut { 57 | 0% { 58 | transform-origin: 0 0; 59 | transform: translateX(0%); 60 | opacity: 1; 61 | } 62 | 100% { 63 | transform-origin: 0 0; 64 | transform: translateX(-100%); 65 | opacity: 0; 66 | } 67 | } 68 | 69 | @keyframes ivuMoveRightIn { 70 | 0% { 71 | opacity: 0; 72 | transform-origin: 0 0; 73 | transform: translateX(100%); 74 | } 75 | 100% { 76 | opacity: 1; 77 | transform-origin: 0 0; 78 | transform: translateX(0%); 79 | } 80 | } 81 | 82 | @keyframes ivuMoveRightOut { 83 | 0% { 84 | transform-origin: 0 0; 85 | transform: translateX(0%); 86 | opacity: 1; 87 | } 88 | 100% { 89 | transform-origin: 0 0; 90 | transform: translateX(100%); 91 | opacity: 0; 92 | } 93 | } 94 | 95 | @keyframes ivuMoveUpIn { 96 | 0% { 97 | transform-origin: 0 0; 98 | transform: translateY(-100%); 99 | opacity: 0; 100 | } 101 | 100% { 102 | transform-origin: 0 0; 103 | transform: translateY(0%); 104 | opacity: 1; 105 | } 106 | } 107 | 108 | @keyframes ivuMoveUpOut { 109 | 0% { 110 | transform-origin: 0 0; 111 | transform: translateY(0%); 112 | opacity: 1; 113 | } 114 | 100% { 115 | transform-origin: 0 0; 116 | transform: translateY(-100%); 117 | opacity: 0; 118 | } 119 | } 120 | 121 | // specific transition for Notice 122 | 123 | .move-motion(move-notice, ivuMoveNotice); 124 | @import '../components/notice.less'; 125 | 126 | @keyframes ivuMoveNoticeIn { 127 | 0% { 128 | opacity: 0; 129 | transform-origin: 0 0; 130 | transform: translateX(100%); 131 | } 132 | 100% { 133 | opacity: 1; 134 | transform-origin: 0 0; 135 | transform: translateX(0%); 136 | } 137 | } 138 | 139 | @keyframes ivuMoveNoticeOut { 140 | 0% { 141 | transform-origin: 0 0; 142 | transform: translateX(0%); 143 | opacity: 1; 144 | } 145 | 70% { 146 | transform-origin: 0 0; 147 | transform: translateX(100%); 148 | height: auto; 149 | padding: @notice-padding; 150 | margin-bottom: @notice-margin-bottom; 151 | opacity: 0; 152 | } 153 | 100% { 154 | transform-origin: 0 0; 155 | transform: translateX(100%); 156 | height: 0; 157 | padding: 0; 158 | margin-bottom: 0; 159 | opacity: 0; 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/carousel.less: -------------------------------------------------------------------------------- 1 | @carousel-prefix-cls: ~"@{css-prefix}carousel"; 2 | @carousel-item-prefix-cls: ~"@{css-prefix}carousel-item"; 3 | 4 | .@{carousel-prefix-cls} { 5 | position: relative; 6 | display: block; 7 | box-sizing: border-box; 8 | user-select: none; 9 | touch-action: pan-y; 10 | -webkit-tap-highlight-color: transparent; 11 | 12 | &-track, &-list { 13 | transform: translate3d(0, 0, 0); 14 | } 15 | 16 | &-list { 17 | position: relative; 18 | display: block; 19 | overflow: hidden; 20 | 21 | margin: 0; 22 | padding: 0; 23 | } 24 | 25 | &-track { 26 | position: relative; 27 | top: 0; 28 | left: 0; 29 | display: block; 30 | 31 | overflow: hidden; 32 | 33 | z-index: 1; 34 | } 35 | 36 | &-item { 37 | float: left; 38 | height: 100%; 39 | min-height: 1px; 40 | display: block; 41 | } 42 | 43 | &-arrow { 44 | 45 | border: none; 46 | outline: none; 47 | 48 | padding: 0; 49 | margin: 0; 50 | 51 | width: 36px; 52 | height: 36px; 53 | border-radius: 50%; 54 | 55 | cursor: pointer; 56 | 57 | display: none; 58 | 59 | position: absolute; 60 | top: 50%; 61 | z-index: 10; 62 | transform: translateY(-50%); 63 | 64 | transition: @transition-time; 65 | background-color: rgba(31, 45, 61, .11); 66 | color: #fff; 67 | 68 | &:hover { 69 | background-color: rgba(31, 45, 61, 0.5); 70 | } 71 | 72 | text-align: center; 73 | font-size: 1em; 74 | 75 | font-family: inherit; 76 | line-height: inherit; 77 | 78 | & > * { 79 | vertical-align: baseline; 80 | } 81 | 82 | &.left { 83 | left: 16px; 84 | } 85 | 86 | &.right { 87 | right: 16px; 88 | } 89 | 90 | &-always { 91 | display: inherit; 92 | } 93 | 94 | &-hover { 95 | display: inherit; 96 | 97 | opacity: 0; 98 | } 99 | } 100 | 101 | &:hover &-arrow-hover { 102 | opacity: 1; 103 | } 104 | 105 | &-dots { 106 | z-index: 10; 107 | 108 | @padding: 7px; 109 | 110 | display: none; 111 | 112 | position: relative; 113 | &-inside { 114 | display: block; 115 | position: absolute; 116 | bottom: 10px - @padding; 117 | } 118 | 119 | &-outside { 120 | display: block; 121 | margin-top: 10px - @padding; 122 | } 123 | 124 | list-style: none; 125 | 126 | text-align: center; 127 | 128 | padding: 0; 129 | width: 100%; 130 | height: 3px + @padding * 2; 131 | 132 | li { 133 | position: relative; 134 | display: inline-block; 135 | 136 | vertical-align: top; 137 | text-align: center; 138 | 139 | margin: 0 2px; 140 | padding: @padding 0; 141 | 142 | cursor: pointer; 143 | 144 | button { 145 | border: 0; 146 | cursor: pointer; 147 | 148 | background: #8391a5; 149 | opacity: 0.3; 150 | 151 | display: block; 152 | width: 16px; 153 | height: 3px; 154 | 155 | border-radius: 1px; 156 | outline: none; 157 | 158 | font-size: 0; 159 | color: transparent; 160 | 161 | transition: all .5s; 162 | } 163 | 164 | &:hover > button { 165 | opacity: 0.7; 166 | } 167 | 168 | &.@{carousel-prefix-cls}-active > button { 169 | opacity: 1; 170 | width: 24px; 171 | } 172 | } 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/poptip.less: -------------------------------------------------------------------------------- 1 | @poptip-prefix-cls: ~"@{css-prefix}poptip"; 2 | @poptip-arrow: ~"@{poptip-prefix-cls}-arrow"; 3 | @poptip-max-width: 250px; 4 | @poptip-arrow-width: 5px; 5 | @poptip-arrow-outer-width: (@poptip-arrow-width + 1); 6 | @poptip-distance: @poptip-arrow-width - 1 + 4; 7 | //@poptip-arrow-color: fadein(@border-color-base, 5%); 8 | @poptip-arrow-color: hsla(0,0%,85%,.5); 9 | 10 | .@{poptip-prefix-cls} { 11 | display: inline-block; 12 | 13 | &-rel{ 14 | display: inline-block; 15 | position: relative; 16 | } 17 | 18 | &-title { 19 | margin: 0; 20 | padding: 8px 16px; 21 | position: relative; 22 | 23 | &:after{ 24 | content: ''; 25 | display: block; 26 | height: 1px; 27 | position: absolute; 28 | left: 8px; 29 | right: 8px; 30 | bottom: 0; 31 | background-color: @border-color-split; 32 | } 33 | 34 | &-inner{ 35 | color: @title-color; 36 | font-size: @font-size-base; 37 | } 38 | } 39 | 40 | &-body{ 41 | padding: 8px 16px; 42 | 43 | &-content{ 44 | overflow: auto; 45 | 46 | &-inner{ 47 | color: @text-color; 48 | } 49 | } 50 | } 51 | 52 | &-inner{ 53 | width: 100%; 54 | background-color: #fff; 55 | background-clip: padding-box; 56 | //border: 1px solid @border-color-split; 57 | border-radius: @border-radius-small; 58 | box-shadow: @shadow-base; 59 | white-space: nowrap; 60 | } 61 | 62 | &-popper{ 63 | min-width: 150px; 64 | font-size: @font-size-small; 65 | .popper(@poptip-arrow, @poptip-arrow-width, @poptip-distance, @poptip-arrow-color); 66 | 67 | &[x-placement^="top"] .@{poptip-arrow}:after { 68 | content: " "; 69 | bottom: 1px; 70 | margin-left: -@poptip-arrow-width; 71 | border-bottom-width: 0; 72 | border-top-color: #fff; 73 | } 74 | 75 | &[x-placement^="right"] .@{poptip-arrow}:after { 76 | content: " "; 77 | left: 1px; 78 | bottom: -@poptip-arrow-width; 79 | border-left-width: 0; 80 | border-right-color: #fff; 81 | } 82 | 83 | &[x-placement^="bottom"] .@{poptip-arrow}:after { 84 | content: " "; 85 | top: 1px; 86 | margin-left: -@poptip-arrow-width; 87 | border-top-width: 0; 88 | border-bottom-color: #fff; 89 | } 90 | 91 | &[x-placement^="left"] .@{poptip-arrow}:after { 92 | content: " "; 93 | right: 1px; 94 | border-right-width: 0; 95 | border-left-color: #fff; 96 | bottom: -@poptip-arrow-width; 97 | } 98 | } 99 | 100 | &-arrow{ 101 | &, &:after{ 102 | display: block; 103 | width: 0; 104 | height: 0; 105 | position: absolute; 106 | border-color: transparent; 107 | border-style: solid; 108 | } 109 | } 110 | &-arrow { 111 | border-width: @poptip-arrow-outer-width; 112 | } 113 | &-arrow:after{ 114 | content: ""; 115 | border-width: @poptip-arrow-width; 116 | } 117 | 118 | &-confirm &-popper{ 119 | max-width: 300px; 120 | } 121 | &-confirm &-inner{ 122 | white-space: normal; 123 | } 124 | 125 | &-confirm &-body{ 126 | padding: 16px 16px 8px; 127 | .ivu-icon{ 128 | font-size: 16px; 129 | color: @warning-color; 130 | line-height: 18px; 131 | position: absolute; 132 | } 133 | 134 | &-message{ 135 | padding-left: 20px; 136 | } 137 | } 138 | 139 | &-confirm &-footer{ 140 | text-align: right; 141 | padding: 8px 16px 16px; 142 | button { 143 | margin-left: 4px; 144 | } 145 | } 146 | } -------------------------------------------------------------------------------- /src/renderer/components/Page/Login.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 108 | 109 | 110 | 154 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/tree.less: -------------------------------------------------------------------------------- 1 | @tree-prefix-cls: ~"@{css-prefix}tree"; 2 | 3 | .@{tree-prefix-cls} { 4 | margin: 0; 5 | padding: 5px; 6 | font-size: @font-size-small; 7 | li { 8 | padding: 0; 9 | margin: 8px 0; 10 | list-style: none; 11 | white-space: nowrap; 12 | outline: 0; 13 | a[draggable], 14 | a[draggable="true"] { 15 | user-select: none; 16 | /* Required to make elements draggable in old WebKit */ 17 | -khtml-user-drag: element; 18 | -webkit-user-drag: element; 19 | } 20 | &.drag-over { 21 | > a[draggable] { 22 | background-color: @primary-color; 23 | color: white; 24 | opacity: 0.8; 25 | } 26 | } 27 | &.drag-over-gap-top { 28 | > a[draggable] { 29 | border-top: 2px @primary-color solid; 30 | } 31 | } 32 | &.drag-over-gap-bottom { 33 | > a[draggable] { 34 | border-bottom: 2px @primary-color solid; 35 | } 36 | } 37 | &.filter-node { 38 | > a { 39 | color: @error-color!important; 40 | font-weight: bold!important; 41 | } 42 | } 43 | ul { 44 | margin: 0; 45 | padding: 0 0 0 18px; 46 | } 47 | a { 48 | display: inline-block; 49 | margin: 0; 50 | padding: 0 4px; 51 | border-radius: @btn-border-radius-small; 52 | cursor: pointer; 53 | text-decoration: none; 54 | vertical-align: top; 55 | color: @text-color; 56 | transition: all @transition-time @ease-in-out; 57 | &:hover { 58 | background-color: tint(@primary-color, 90%); 59 | } 60 | &.@{tree-prefix-cls}-node-selected { 61 | background-color: tint(@primary-color, 80%); 62 | } 63 | } 64 | .@{checkbox-prefix-cls}-wrapper{ 65 | margin-right: 4px; 66 | } 67 | span { 68 | &.@{tree-prefix-cls}-switcher, 69 | &.@{tree-prefix-cls}-iconEle { 70 | display: inline-block; 71 | text-align: center; 72 | width: 16px; 73 | height: 16px; 74 | line-height: 16px; 75 | margin: 0; 76 | vertical-align: middle; 77 | border: 0 none; 78 | cursor: pointer; 79 | outline: none; 80 | } 81 | //&.@{tree-prefix-cls}-icon_loading { 82 | // &:after { 83 | // display: inline-block; 84 | // //.iconfont-font("\e6a1"); 85 | // animation: loadingCircle 1s infinite linear; 86 | // color: @primary-color; 87 | // } 88 | //} 89 | &.@{tree-prefix-cls}-switcher { 90 | i{ 91 | transition: all @transition-time @ease-in-out; 92 | } 93 | &.@{tree-prefix-cls}-switcher-noop { 94 | display: none; 95 | cursor: auto; 96 | i{ 97 | display: none; 98 | } 99 | } 100 | &.@{tree-prefix-cls}-roots_open, 101 | &.@{tree-prefix-cls}-center_open, 102 | &.@{tree-prefix-cls}-bottom_open, 103 | &.@{tree-prefix-cls}-noline_open { 104 | i { 105 | transform: rotate(90deg); 106 | } 107 | } 108 | &.@{tree-prefix-cls}-roots_close, 109 | &.@{tree-prefix-cls}-center_close, 110 | &.@{tree-prefix-cls}-bottom_close, 111 | &.@{tree-prefix-cls}-noline_close { 112 | 113 | } 114 | } 115 | } 116 | } 117 | &-child-tree { 118 | display: none; 119 | &-open { 120 | display: block; 121 | } 122 | } 123 | &-treenode-disabled { 124 | >span, 125 | >a, 126 | >a span { 127 | color: @input-disabled-bg; 128 | cursor: not-allowed; 129 | } 130 | } 131 | &-icon__open { 132 | margin-right: 2px; 133 | vertical-align: top; 134 | } 135 | &-icon__close { 136 | margin-right: 2px; 137 | vertical-align: top; 138 | } 139 | } -------------------------------------------------------------------------------- /src/renderer/components/Ui/AddPointModal.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 25 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /.electron-vue/dev-runner.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const chalk = require('chalk') 4 | const electron = require('electron') 5 | const path = require('path') 6 | const { say } = require('cfonts') 7 | const { spawn } = require('child_process') 8 | const webpack = require('webpack') 9 | const WebpackDevServer = require('webpack-dev-server') 10 | const webpackHotMiddleware = require('webpack-hot-middleware') 11 | 12 | const mainConfig = require('./webpack.main.config') 13 | const rendererConfig = require('./webpack.renderer.config') 14 | 15 | let electronProcess = null 16 | let manualRestart = false 17 | let hotMiddleware 18 | 19 | function logStats (proc, data) { 20 | let log = '' 21 | 22 | log += chalk.yellow.bold(`┏ ${proc} Process ${new Array((19 - proc.length) + 1).join('-')}`) 23 | log += '\n\n' 24 | 25 | if (typeof data === 'object') { 26 | data.toString({ 27 | colors: true, 28 | chunks: false 29 | }).split(/\r?\n/).forEach(line => { 30 | log += ' ' + line + '\n' 31 | }) 32 | } else { 33 | log += ` ${data}\n` 34 | } 35 | 36 | log += '\n' + chalk.yellow.bold(`┗ ${new Array(28 + 1).join('-')}`) + '\n' 37 | 38 | console.log(log) 39 | } 40 | 41 | function startRenderer () { 42 | return new Promise((resolve, reject) => { 43 | rendererConfig.entry.renderer = [path.join(__dirname, 'dev-client')].concat(rendererConfig.entry.renderer) 44 | 45 | const compiler = webpack(rendererConfig) 46 | hotMiddleware = webpackHotMiddleware(compiler, { 47 | log: false, 48 | heartbeat: 2500 49 | }) 50 | 51 | compiler.plugin('compilation', compilation => { 52 | compilation.plugin('html-webpack-plugin-after-emit', (data, cb) => { 53 | hotMiddleware.publish({ action: 'reload' }) 54 | cb() 55 | }) 56 | }) 57 | 58 | compiler.plugin('done', stats => { 59 | logStats('Renderer', stats) 60 | }) 61 | 62 | const server = new WebpackDevServer( 63 | compiler, 64 | { 65 | contentBase: path.join(__dirname, '../'), 66 | quiet: true, 67 | setup (app, ctx) { 68 | app.use(hotMiddleware) 69 | ctx.middleware.waitUntilValid(() => { 70 | resolve() 71 | }) 72 | } 73 | } 74 | ) 75 | 76 | server.listen(9080) 77 | }) 78 | } 79 | 80 | function startMain () { 81 | return new Promise((resolve, reject) => { 82 | mainConfig.entry.main = [path.join(__dirname, '../src/main/index.dev.js')].concat(mainConfig.entry.main) 83 | 84 | const compiler = webpack(mainConfig) 85 | 86 | compiler.plugin('watch-run', (compilation, done) => { 87 | logStats('Main', chalk.white.bold('compiling...')) 88 | hotMiddleware.publish({ action: 'compiling' }) 89 | done() 90 | }) 91 | 92 | compiler.watch({}, (err, stats) => { 93 | if (err) { 94 | console.log(err) 95 | return 96 | } 97 | 98 | logStats('Main', stats) 99 | 100 | if (electronProcess && electronProcess.kill) { 101 | manualRestart = true 102 | process.kill(electronProcess.pid) 103 | electronProcess = null 104 | startElectron() 105 | 106 | setTimeout(() => { 107 | manualRestart = false 108 | }, 5000) 109 | } 110 | 111 | resolve() 112 | }) 113 | }) 114 | } 115 | 116 | function startElectron () { 117 | electronProcess = spawn(electron, ['--inspect=5858', path.join(__dirname, '../dist/electron/main.js')]) 118 | 119 | electronProcess.stdout.on('data', data => { 120 | electronLog(data, 'blue') 121 | }) 122 | electronProcess.stderr.on('data', data => { 123 | electronLog(data, 'red') 124 | }) 125 | 126 | electronProcess.on('close', () => { 127 | if (!manualRestart) process.exit() 128 | }) 129 | } 130 | 131 | function electronLog (data, color) { 132 | let log = '' 133 | data = data.toString().split(/\r?\n/) 134 | data.forEach(line => { 135 | log += ` ${line}\n` 136 | }) 137 | if (/[0-9A-z]+/.test(log)) { 138 | console.log( 139 | chalk[color].bold('┏ Electron -------------------') + 140 | '\n\n' + 141 | log + 142 | chalk[color].bold('┗ ----------------------------') + 143 | '\n' 144 | ) 145 | } 146 | } 147 | 148 | function greeting () { 149 | const cols = process.stdout.columns 150 | let text = '' 151 | 152 | if (cols > 104) text = 'electron-vue' 153 | else if (cols > 76) text = 'electron-|vue' 154 | else text = false 155 | 156 | if (text) { 157 | say(text, { 158 | colors: ['yellow'], 159 | font: 'simple3d', 160 | space: false 161 | }) 162 | } else console.log(chalk.yellow.bold('\n electron-vue')) 163 | console.log(chalk.blue(' getting ready...') + '\n') 164 | } 165 | 166 | function init () { 167 | greeting() 168 | 169 | Promise.all([startRenderer(), startMain()]) 170 | .then(() => { 171 | startElectron() 172 | }) 173 | .catch(err => { 174 | console.error(err) 175 | }) 176 | } 177 | 178 | init() 179 | -------------------------------------------------------------------------------- /.electron-vue/webpack.renderer.config.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | process.env.BABEL_ENV = 'renderer' 4 | 5 | const path = require('path') 6 | const { dependencies } = require('../package.json') 7 | const webpack = require('webpack') 8 | 9 | const BabiliWebpackPlugin = require('babili-webpack-plugin') 10 | const CopyWebpackPlugin = require('copy-webpack-plugin') 11 | const ExtractTextPlugin = require('extract-text-webpack-plugin') 12 | const HtmlWebpackPlugin = require('html-webpack-plugin') 13 | 14 | /** 15 | * List of node_modules to include in webpack bundle 16 | * 17 | * Required for specific packages like Vue UI libraries 18 | * that provide pure *.vue files that need compiling 19 | * https://simulatedgreg.gitbooks.io/electron-vue/content/en/webpack-configurations.html#white-listing-externals 20 | */ 21 | let whiteListedModules = ['vue'] 22 | 23 | let rendererConfig = { 24 | devtool: '#cheap-module-eval-source-map', 25 | entry: { 26 | renderer: path.join(__dirname, '../src/renderer/main.js') 27 | }, 28 | externals: [ 29 | ...Object.keys(dependencies || {}).filter(d => !whiteListedModules.includes(d)) 30 | ], 31 | module: { 32 | rules: [ 33 | { 34 | test: /\.css$/, 35 | use: ExtractTextPlugin.extract({ 36 | fallback: 'style-loader', 37 | use: 'css-loader' 38 | }) 39 | }, 40 | { 41 | test: /\.html$/, 42 | use: 'vue-html-loader' 43 | }, 44 | { 45 | test: /\.js$/, 46 | use: 'babel-loader', 47 | exclude: /node_modules/ 48 | }, 49 | { 50 | test: /\.node$/, 51 | use: 'node-loader' 52 | }, 53 | { 54 | test: /\.vue$/, 55 | use: { 56 | loader: 'vue-loader', 57 | options: { 58 | extractCSS: process.env.NODE_ENV === 'production', 59 | loaders: { 60 | sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax=1', 61 | scss: 'vue-style-loader!css-loader!sass-loader' 62 | } 63 | } 64 | } 65 | }, 66 | { 67 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 68 | use: { 69 | loader: 'url-loader', 70 | query: { 71 | limit: 10000, 72 | name: 'imgs/[name]--[folder].[ext]' 73 | } 74 | } 75 | }, 76 | { 77 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, 78 | loader: 'url-loader', 79 | options: { 80 | limit: 10000, 81 | name: 'media/[name]--[folder].[ext]' 82 | } 83 | }, 84 | { 85 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 86 | use: { 87 | loader: 'url-loader', 88 | query: { 89 | limit: 10000, 90 | name: 'fonts/[name]--[folder].[ext]' 91 | } 92 | } 93 | } 94 | ] 95 | }, 96 | node: { 97 | __dirname: process.env.NODE_ENV !== 'production', 98 | __filename: process.env.NODE_ENV !== 'production' 99 | }, 100 | plugins: [ 101 | new ExtractTextPlugin('styles.css'), 102 | new HtmlWebpackPlugin({ 103 | filename: 'index.html', 104 | template: path.resolve(__dirname, '../src/index.ejs'), 105 | minify: { 106 | collapseWhitespace: true, 107 | removeAttributeQuotes: true, 108 | removeComments: true 109 | }, 110 | nodeModules: process.env.NODE_ENV !== 'production' 111 | ? path.resolve(__dirname, '../node_modules') 112 | : false 113 | }), 114 | new webpack.HotModuleReplacementPlugin(), 115 | new webpack.NoEmitOnErrorsPlugin() 116 | ], 117 | output: { 118 | filename: '[name].js', 119 | libraryTarget: 'commonjs2', 120 | path: path.join(__dirname, '../dist/electron') 121 | }, 122 | resolve: { 123 | alias: { 124 | '@': path.join(__dirname, '../src/renderer'), 125 | 'vue$': 'vue/dist/vue.esm.js' 126 | }, 127 | extensions: ['.js', '.vue', '.json', '.css', '.node'] 128 | }, 129 | target: 'electron-renderer' 130 | } 131 | 132 | /** 133 | * Adjust rendererConfig for development settings 134 | */ 135 | if (process.env.NODE_ENV !== 'production') { 136 | rendererConfig.plugins.push( 137 | new webpack.DefinePlugin({ 138 | '__static': `"${path.join(__dirname, '../static').replace(/\\/g, '\\\\')}"` 139 | }) 140 | ) 141 | } 142 | 143 | /** 144 | * Adjust rendererConfig for production settings 145 | */ 146 | if (process.env.NODE_ENV === 'production') { 147 | rendererConfig.devtool = '' 148 | 149 | rendererConfig.plugins.push( 150 | new BabiliWebpackPlugin(), 151 | new CopyWebpackPlugin([ 152 | { 153 | from: path.join(__dirname, '../static'), 154 | to: path.join(__dirname, '../dist/electron/static'), 155 | ignore: ['.*'] 156 | } 157 | ]), 158 | new webpack.DefinePlugin({ 159 | 'process.env.NODE_ENV': '"production"' 160 | }), 161 | new webpack.LoaderOptionsPlugin({ 162 | minimize: true 163 | }) 164 | ) 165 | } 166 | 167 | module.exports = rendererConfig 168 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/input-number.less: -------------------------------------------------------------------------------- 1 | @input-number-prefix-cls: ~"@{css-prefix}input-number"; 2 | 3 | .handler-disabled() { 4 | opacity: 0.72; 5 | color: #ccc !important; 6 | cursor: @cursor-disabled; 7 | } 8 | 9 | .@{input-number-prefix-cls} { 10 | @radius-wrap: 0 @btn-border-radius @btn-border-radius 0; 11 | 12 | .input; 13 | margin: 0; 14 | padding: 0; 15 | width: 80px; 16 | height: @input-height-base; 17 | line-height: @input-height-base; 18 | vertical-align: middle; 19 | border: 1px solid @border-color-base; 20 | border-radius: @btn-border-radius; 21 | overflow: hidden; 22 | 23 | &-handler-wrap { 24 | width: 22px; 25 | height: 100%; 26 | border-left: 1px solid @border-color-base; 27 | border-radius: @radius-wrap; 28 | background: #fff; 29 | position: absolute; 30 | top: 0; 31 | right: 0; 32 | opacity: 0; 33 | transition: opacity @transition-time @ease-in-out; 34 | } 35 | 36 | &:hover &-handler-wrap { 37 | opacity: 1; 38 | } 39 | 40 | &-handler-up { 41 | cursor: pointer; 42 | &-inner { 43 | top: 1px; 44 | } 45 | } 46 | 47 | &-handler-down { 48 | border-top: 1px solid @border-color-base; 49 | top: -1px; 50 | cursor: pointer; 51 | } 52 | 53 | &-handler { 54 | display: block; 55 | width: 100%; 56 | height: @input-height-base / 2; 57 | line-height: 0; 58 | text-align: center; 59 | overflow: hidden; 60 | color: #999; 61 | position: relative; 62 | 63 | &:hover &-up-inner, 64 | &:hover &-down-inner { 65 | color: tint(@primary-color, 20%); 66 | } 67 | } 68 | 69 | &-handler-up-inner, 70 | &-handler-down-inner { 71 | width: 12px; 72 | height: 12px; 73 | line-height: 12px; 74 | font-size: 14px; 75 | color: #999; 76 | user-select: none; 77 | position: absolute; 78 | right: 4px; 79 | transition: all @transition-time linear; 80 | } 81 | 82 | &:hover { 83 | .hover(); 84 | } 85 | 86 | &-focused { 87 | .active(); 88 | } 89 | 90 | &-disabled { 91 | .disabled(); 92 | } 93 | 94 | &-input-wrap { 95 | overflow: hidden; 96 | height: @input-height-base; 97 | } 98 | 99 | &-input { 100 | width: 100%; 101 | height: @input-height-base; 102 | line-height: @input-height-base; 103 | padding: 0 7px; 104 | text-align: left; 105 | outline: 0; 106 | -moz-appearance: textfield; 107 | color: #666; 108 | border: 0; 109 | border-radius: @btn-border-radius; 110 | transition: all @transition-time linear; 111 | 112 | &[disabled] { 113 | .disabled(); 114 | } 115 | } 116 | 117 | &-large { 118 | padding: 0; 119 | .@{input-number-prefix-cls}-input-wrap { 120 | height: @input-height-large; 121 | } 122 | .@{input-number-prefix-cls}-handler { 123 | height: @input-height-large / 2; 124 | } 125 | 126 | input { 127 | height: @input-height-large; 128 | line-height: @input-height-large; 129 | } 130 | 131 | .@{input-number-prefix-cls}-handler-up-inner { 132 | top: 2px; 133 | } 134 | .@{input-number-prefix-cls}-handler-down-inner { 135 | bottom: 2px; 136 | } 137 | } 138 | 139 | &-small { 140 | padding: 0; 141 | .@{input-number-prefix-cls}-input-wrap { 142 | height: @input-height-small; 143 | } 144 | .@{input-number-prefix-cls}-handler { 145 | height: @input-height-small / 2; 146 | } 147 | 148 | input { 149 | height: @input-height-small; 150 | line-height: @input-height-small; 151 | margin-top: -1px; 152 | vertical-align: top; 153 | } 154 | .@{input-number-prefix-cls}-handler-up-inner { 155 | top: -1px; 156 | } 157 | .@{input-number-prefix-cls}-handler-down-inner { 158 | bottom: -1px; 159 | } 160 | } 161 | 162 | 163 | 164 | &-handler-down-disabled, 165 | &-handler-up-disabled, 166 | &-disabled { 167 | .@{input-number-prefix-cls}-handler-down-inner, 168 | .@{input-number-prefix-cls}-handler-up-inner { 169 | .handler-disabled(); 170 | } 171 | } 172 | 173 | &-disabled { 174 | .@{input-number-prefix-cls}-input { 175 | opacity: 0.72; 176 | cursor: @cursor-disabled; 177 | background-color: #f3f3f3; 178 | } 179 | .@{input-number-prefix-cls}-handler-wrap { 180 | display: none; 181 | } 182 | .@{input-number-prefix-cls}-handler { 183 | .handler-disabled(); 184 | } 185 | } 186 | } 187 | 188 | .@{form-item-prefix-cls}-error { 189 | .@{input-number-prefix-cls}{ 190 | .input-error; 191 | &-focused { 192 | .active-error; 193 | } 194 | } 195 | } -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/tag.less: -------------------------------------------------------------------------------- 1 | @tag-prefix-cls: ~"@{css-prefix}tag"; 2 | @tag-close-prefix-cls: ivu-icon-ios-close-empty; 3 | 4 | .@{tag-prefix-cls} { 5 | display: inline-block; 6 | height: 22px; 7 | line-height: 22px; 8 | margin: 2px 4px 2px 0; 9 | padding: 0 8px; 10 | border: 1px solid @border-color-split; 11 | border-radius: @btn-border-radius-small; 12 | background: @background-color-base; 13 | font-size: @tag-font-size; 14 | vertical-align: middle; 15 | opacity: 1; 16 | overflow: hidden; 17 | cursor: pointer; 18 | //transition: all @transition-time @ease-in-out; 19 | 20 | &-dot{ 21 | height: 32px; 22 | line-height: 32px; 23 | border: 1px solid @border-color-split !important; 24 | color: @text-color !important; 25 | background: #fff !important; 26 | padding: 0 12px; 27 | 28 | &-inner{ 29 | display: inline-block; 30 | width: 12px; 31 | height: 12px; 32 | margin-right: 8px; 33 | border-radius: 50%; 34 | background: @border-color-split; 35 | position: relative; 36 | top: 1px; 37 | } 38 | .@{tag-close-prefix-cls} { 39 | color: #666 !important; 40 | margin-left: 12px !important; 41 | } 42 | } 43 | 44 | &-border{ 45 | height: 24px; 46 | line-height: 24px; 47 | border: 1px solid @border-color-split !important; 48 | color: @text-color !important; 49 | background: #fff !important; 50 | position: relative; 51 | 52 | .@{tag-close-prefix-cls} { 53 | color: #666 !important; 54 | margin-left: 12px !important; 55 | } 56 | 57 | &:after{ 58 | content: ""; 59 | display: none; 60 | width: 1px; 61 | background: @border-color-split; 62 | position: absolute; 63 | top: 0; 64 | bottom: 0; 65 | right: 22px; 66 | } 67 | 68 | &.@{tag-prefix-cls}-closable { 69 | &:after{ 70 | display: block; 71 | } 72 | .@{tag-close-prefix-cls} { 73 | margin-left: 18px !important; 74 | } 75 | } 76 | 77 | &.@{tag-prefix-cls}-blue { 78 | color: @link-color !important; 79 | border: 1px solid @link-color !important; 80 | 81 | &:after{ 82 | background: @link-color; 83 | } 84 | .@{tag-close-prefix-cls}{ 85 | color: @link-color !important; 86 | } 87 | } 88 | &.@{tag-prefix-cls}-green { 89 | color: @success-color !important; 90 | border: 1px solid @success-color !important; 91 | 92 | &:after{ 93 | background: @success-color; 94 | } 95 | .@{tag-close-prefix-cls}{ 96 | color: @success-color !important; 97 | } 98 | } 99 | &.@{tag-prefix-cls}-yellow { 100 | color: @warning-color !important; 101 | border: 1px solid @warning-color !important; 102 | 103 | &:after{ 104 | background: @warning-color; 105 | } 106 | .@{tag-close-prefix-cls}{ 107 | color: @warning-color !important; 108 | } 109 | } 110 | &.@{tag-prefix-cls}-red { 111 | color: @error-color !important; 112 | border: 1px solid @error-color !important; 113 | 114 | &:after{ 115 | background: @error-color; 116 | } 117 | .@{tag-close-prefix-cls}{ 118 | color: @error-color !important; 119 | } 120 | } 121 | } 122 | 123 | &:hover { 124 | opacity: 0.85; 125 | } 126 | 127 | &, 128 | a, 129 | a:hover { 130 | color: @text-color; 131 | } 132 | 133 | &-text { 134 | a:first-child:last-child { 135 | display: inline-block; 136 | margin: 0 -8px; 137 | padding: 0 8px; 138 | } 139 | } 140 | 141 | .@{tag-close-prefix-cls} { 142 | .iconfont-size-under-12px(20px); 143 | cursor: pointer; 144 | margin-left: 8px; 145 | color: #666; 146 | opacity: 0.66; 147 | position: relative; 148 | top: 1px; 149 | //transition: all @transition-time @ease-in-out; 150 | 151 | &:hover { 152 | opacity: 1; 153 | } 154 | } 155 | 156 | &-blue, 157 | &-green, 158 | &-yellow, 159 | &-red { 160 | border: 0; 161 | &, 162 | a, 163 | a:hover, 164 | .@{tag-close-prefix-cls}, 165 | .@{tag-close-prefix-cls}:hover { 166 | color: #fff; 167 | } 168 | } 169 | 170 | &-blue, 171 | &-blue&-dot &-dot-inner 172 | { 173 | background: @link-color; 174 | } 175 | 176 | &-green, 177 | &-green&-dot &-dot-inner 178 | { 179 | background: @success-color; 180 | } 181 | 182 | &-yellow, 183 | &-yellow&-dot &-dot-inner 184 | { 185 | background: @warning-color; 186 | } 187 | 188 | &-red, 189 | &-red&-dot &-dot-inner 190 | { 191 | background: @error-color; 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/mixins/checkbox.less: -------------------------------------------------------------------------------- 1 | .checkboxFn(@checkbox-prefix-cls: ~"@{css-prefix}checkbox") { 2 | @checkbox-inner-prefix-cls: ~"@{checkbox-prefix-cls}-inner"; 3 | 4 | // 普通状态 5 | .@{checkbox-prefix-cls} { 6 | display: inline-block; 7 | vertical-align: middle; 8 | white-space: nowrap; 9 | cursor: pointer; 10 | outline: none; 11 | line-height: 1; 12 | position: relative; 13 | 14 | &-disabled{ 15 | cursor: @cursor-disabled; 16 | } 17 | 18 | &:hover { 19 | .@{checkbox-inner-prefix-cls} { 20 | border-color: #bcbcbc; 21 | } 22 | } 23 | 24 | &-inner { 25 | display: inline-block; 26 | width: 14px; 27 | height: 14px; 28 | position: relative; 29 | top: 0; 30 | left: 0; 31 | border: 1px solid @border-color-base; 32 | border-radius: 2px; 33 | background-color: #fff; 34 | transition: border-color @transition-time @ease-in-out, background-color @transition-time @ease-in-out; 35 | 36 | &:after { 37 | content: ''; 38 | display: table; 39 | width: 4px; 40 | height: 8px; 41 | position: absolute; 42 | top: 1px; 43 | left: 4px; 44 | border: 2px solid #fff; 45 | border-top: 0; 46 | border-left: 0; 47 | transform: rotate(45deg) scale(0); 48 | transition: all @transition-time @ease-in-out; 49 | } 50 | } 51 | 52 | &-input { 53 | width: 100%; 54 | height: 100%; 55 | position: absolute; 56 | top: 0; 57 | bottom: 0; 58 | left: 0; 59 | right: 0; 60 | z-index: 1; 61 | cursor: pointer; 62 | opacity: 0; 63 | 64 | &[disabled]{ 65 | cursor: @cursor-disabled; 66 | } 67 | } 68 | } 69 | 70 | // 选中状态 71 | .@{checkbox-prefix-cls}-checked { 72 | 73 | &:hover { 74 | .@{checkbox-inner-prefix-cls} { 75 | border-color: @primary-color; 76 | } 77 | } 78 | 79 | .@{checkbox-inner-prefix-cls} { 80 | border-color: @primary-color; 81 | background-color: @primary-color; 82 | 83 | &:after { 84 | content: ''; 85 | display: table; 86 | width: 4px; 87 | height: 8px; 88 | position: absolute; 89 | top: 1px; 90 | left: 4px; 91 | border: 2px solid #fff; 92 | border-top: 0; 93 | border-left: 0; 94 | transform: rotate(45deg) scale(1); 95 | transition: all @transition-time @ease-in-out; 96 | } 97 | } 98 | } 99 | 100 | // 禁用 101 | .@{checkbox-prefix-cls}-disabled { 102 | &.@{checkbox-prefix-cls}-checked { 103 | &:hover { 104 | .@{checkbox-inner-prefix-cls} { 105 | border-color: @border-color-base; 106 | } 107 | } 108 | 109 | .@{checkbox-inner-prefix-cls} { 110 | background-color: #f3f3f3; 111 | border-color: @border-color-base; 112 | 113 | &:after { 114 | animation-name: none; 115 | border-color: #ccc; 116 | } 117 | } 118 | } 119 | 120 | &:hover { 121 | .@{checkbox-inner-prefix-cls} { 122 | border-color: @border-color-base; 123 | } 124 | } 125 | 126 | .@{checkbox-inner-prefix-cls} { 127 | border-color: @border-color-base; 128 | background-color: #f3f3f3; 129 | &:after { 130 | animation-name: none; 131 | border-color: #f3f3f3; 132 | } 133 | } 134 | 135 | .@{checkbox-inner-prefix-cls}-input { 136 | cursor: default; 137 | } 138 | 139 | & + span { 140 | color: #ccc; 141 | cursor: @cursor-disabled; 142 | } 143 | } 144 | 145 | // 半选状态 146 | .@{checkbox-prefix-cls}-indeterminate{ 147 | .@{checkbox-inner-prefix-cls}:after{ 148 | content: ''; 149 | width: 8px; 150 | height: 1px; 151 | transform: scale(1); 152 | position: absolute; 153 | left: 2px; 154 | top: 5px; 155 | } 156 | 157 | &:hover { 158 | .@{checkbox-inner-prefix-cls} { 159 | border-color: @primary-color; 160 | } 161 | } 162 | .@{checkbox-inner-prefix-cls}{ 163 | background-color: @primary-color; 164 | border-color: @primary-color; 165 | } 166 | } 167 | 168 | .@{checkbox-prefix-cls}-wrapper { 169 | cursor: pointer; 170 | font-size: @font-size-small; 171 | display: inline-block; 172 | margin-right: 8px; 173 | &-disabled{ 174 | cursor: @cursor-disabled; 175 | } 176 | } 177 | 178 | .@{checkbox-prefix-cls}-wrapper + span, 179 | .@{checkbox-prefix-cls} + span { 180 | //margin-left: 4px; 181 | margin-right: 4px; 182 | } 183 | 184 | .@{checkbox-prefix-cls}-group { 185 | font-size: @font-size-base; 186 | &-item { 187 | display: inline-block; 188 | } 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/tabs.less: -------------------------------------------------------------------------------- 1 | @tabs-prefix-cls: ~"@{css-prefix}tabs"; 2 | 3 | .@{tabs-prefix-cls} { 4 | box-sizing: border-box; 5 | position: relative; 6 | overflow: hidden; 7 | color: @text-color; 8 | .clearfix; 9 | 10 | &-bar { 11 | outline: none; 12 | } 13 | 14 | &-ink-bar { 15 | height: 2px; 16 | box-sizing: border-box; 17 | background-color: @primary-color; 18 | position: absolute; 19 | left: 0; 20 | bottom: 1px; 21 | z-index: 1; 22 | transition: transform .3s @ease-in-out; 23 | transform-origin: 0 0; 24 | } 25 | 26 | &-bar { 27 | border-bottom: 1px solid @border-color-base; 28 | margin-bottom: 16px; 29 | } 30 | 31 | &-nav-container { 32 | margin-bottom: -1px; 33 | line-height: @line-height-base; 34 | font-size: @font-size-base; 35 | box-sizing: border-box; 36 | white-space: nowrap; 37 | overflow: hidden; 38 | position: relative; 39 | .clearfix; 40 | } 41 | 42 | &-nav-container-scrolling { 43 | padding-left: 32px; 44 | padding-right: 32px; 45 | } 46 | 47 | &-nav-wrap { 48 | overflow: hidden; 49 | margin-bottom: -1px; 50 | } 51 | 52 | &-nav-scroll { 53 | overflow: hidden; 54 | white-space: nowrap; 55 | } 56 | 57 | &-nav { 58 | padding-left: 0; 59 | margin: 0; 60 | float: left; 61 | list-style: none; 62 | box-sizing: border-box; 63 | position: relative; 64 | transition: transform 0.5s @ease-in-out; 65 | 66 | &:before, 67 | &:after { 68 | display: table; 69 | content: " "; 70 | } 71 | 72 | &:after { 73 | clear: both; 74 | } 75 | 76 | .@{tabs-prefix-cls}-tab-disabled { 77 | pointer-events: none; 78 | cursor: default; 79 | color: #ccc; 80 | } 81 | 82 | .@{tabs-prefix-cls}-tab { 83 | display: inline-block; 84 | height: 100%; 85 | padding: 8px 16px; 86 | margin-right: 16px; 87 | box-sizing: border-box; 88 | cursor: pointer; 89 | text-decoration: none; 90 | position: relative; 91 | transition: color .3s @ease-in-out; 92 | 93 | &:hover { 94 | color: @link-hover-color; 95 | } 96 | 97 | &:active { 98 | color: @link-active-color; 99 | } 100 | .@{css-prefix-iconfont} { 101 | width: 14px; 102 | height: 14px; 103 | margin-right: 8px; 104 | } 105 | } 106 | 107 | .@{tabs-prefix-cls}-tab-active { 108 | color: @primary-color; 109 | } 110 | } 111 | &-mini &-nav-container { 112 | font-size: @font-size-base; 113 | } 114 | 115 | &-mini &-tab { 116 | margin-right: 0; 117 | padding: 8px 16px; 118 | font-size: @font-size-small; 119 | } 120 | 121 | & { 122 | .@{tabs-prefix-cls}-content-animated { 123 | display: flex; 124 | flex-direction: row; 125 | will-change: transform; 126 | transition: transform .3s @ease-in-out; 127 | } 128 | 129 | .@{tabs-prefix-cls}-tabpane { 130 | flex-shrink: 0; 131 | width: 100%; 132 | transition: opacity .3s; 133 | opacity: 1; 134 | } 135 | 136 | .@{tabs-prefix-cls}-tabpane-inactive { 137 | opacity: 0; 138 | height: 0; 139 | } 140 | } 141 | 142 | // card style 143 | &&-card > &-bar &-nav-container { 144 | height: 32px; 145 | } 146 | &&-card > &-bar &-ink-bar { 147 | visibility: hidden; 148 | } 149 | &&-card > &-bar &-tab { 150 | margin: 0; 151 | margin-right: 4px; 152 | height: 31px; 153 | padding: 5px 16px 4px; 154 | border: 1px solid @border-color-base; 155 | border-bottom: 0; 156 | border-radius: @btn-border-radius @btn-border-radius 0 0; 157 | transition: all 0.3s @ease-in-out; 158 | background: @table-thead-bg; 159 | } 160 | &&-card > &-bar &-tab-active { 161 | height: 32px; 162 | padding-bottom: 5px; 163 | background: #fff; 164 | transform: translateZ(0); 165 | border-color: @border-color-base; 166 | color: @primary-color; 167 | } 168 | &&-card > &-bar &-nav-wrap { 169 | margin-bottom: 0; 170 | } 171 | &&-card > &-bar &-tab .@{css-prefix-iconfont}-ios-close-empty { 172 | width: 0; 173 | height: 22px; 174 | font-size: 22px; 175 | margin-right: 0; 176 | color: @legend-color; 177 | text-align: right; 178 | vertical-align: middle; 179 | overflow: hidden; 180 | position: relative; 181 | top: -1px; 182 | transform-origin: 100% 50%; 183 | transition: all 0.3s @ease-in-out; 184 | &:hover { 185 | color: #444; 186 | } 187 | } 188 | 189 | &&-card > &-bar &-tab-active .@{css-prefix-iconfont}-ios-close-empty, 190 | &&-card > &-bar &-tab:hover .@{css-prefix-iconfont}-ios-close-empty { 191 | width: 14px; 192 | transform: translateZ(0); 193 | } 194 | } 195 | 196 | .@{tabs-prefix-cls}-no-animation{ 197 | .@{tabs-prefix-cls}-content { 198 | transform: none!important; 199 | 200 | > .@{tabs-prefix-cls}-tabpane-inactive { 201 | display: none; 202 | } 203 | } 204 | } -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/time-picker.less: -------------------------------------------------------------------------------- 1 | @time-picker-prefix-cls: ~"@{css-prefix}time-picker"; 2 | @time-picker-cells-width-base: 56px; 3 | @time-picker-cells-width-with-date-base: 72px; 4 | @time-picker-cells-width: @time-picker-cells-width-base * 2; 5 | @time-picker-cells-width-with-seconds: @time-picker-cells-width-base *3; 6 | @time-picker-cells-width-with-date: @time-picker-cells-width-with-date-base * 2; 7 | @time-picker-cells-width-with-date-with-seconds: @time-picker-cells-width-with-date-base * 3; 8 | 9 | .@{time-picker-prefix-cls} { 10 | &-cells{ 11 | min-width: @time-picker-cells-width; 12 | &-with-seconds{ 13 | min-width: @time-picker-cells-width-with-seconds; 14 | } 15 | 16 | &-list{ 17 | width: @time-picker-cells-width-base; 18 | max-height: 144px; 19 | float: left; 20 | overflow: hidden; 21 | border-left: 1px solid @border-color-split; 22 | position: relative; 23 | &:hover{ 24 | overflow-y: auto; 25 | } 26 | 27 | &:first-child{ 28 | border-left: none; 29 | border-radius: @btn-border-radius 0 0 @btn-border-radius; 30 | } 31 | &:last-child{ 32 | border-radius: 0 @btn-border-radius @btn-border-radius 0; 33 | } 34 | ul{ 35 | width: 100%; 36 | margin: 0; 37 | padding: 0 0 120px 0; 38 | list-style: none; 39 | li{ 40 | width: 100%; 41 | height: 24px; 42 | line-height: 24px; 43 | margin: 0; 44 | padding: 0 0 0 16px; 45 | box-sizing: content-box; 46 | text-align: left; 47 | user-select: none; 48 | cursor: pointer; 49 | list-style: none; 50 | transition: background @transition-time @ease-in-out; 51 | 52 | } 53 | } 54 | } 55 | &-cell{ 56 | &:hover{ 57 | background: @background-color-select-hover; 58 | } 59 | &-disabled { 60 | color: @btn-disable-color; 61 | cursor: @cursor-disabled; 62 | 63 | &:hover { 64 | color: @btn-disable-color; 65 | background-color: #fff; 66 | cursor: @cursor-disabled; 67 | } 68 | } 69 | &-selected ,&-selected:hover{ 70 | color: @primary-color; 71 | background: @background-color-select-hover; 72 | } 73 | } 74 | } 75 | 76 | &-header{ 77 | height: 32px; 78 | line-height: 32px; 79 | text-align: center; 80 | border-bottom: 1px solid @border-color-split; 81 | } 82 | 83 | &-with-range{ 84 | .@{picker-prefix-cls}-panel{ 85 | &-body{ 86 | min-width: @time-picker-cells-width * 2 + 4px; 87 | } 88 | &-content{ 89 | float: left; 90 | position: relative; 91 | 92 | &:after{ 93 | content: ''; 94 | display: block; 95 | width: 2px; 96 | position: absolute; 97 | top: 31px; 98 | bottom: 0; 99 | right: -2px; 100 | background: @border-color-split; 101 | z-index: 1; 102 | } 103 | 104 | &-right{ 105 | float: right; 106 | &:after{ 107 | right: auto; 108 | left: -2px; 109 | } 110 | } 111 | } 112 | } 113 | .@{time-picker-prefix-cls}-cells{ 114 | &-list{ 115 | &:first-child{ 116 | border-radius: 0; 117 | } 118 | &:last-child{ 119 | border-radius: 0; 120 | } 121 | } 122 | } 123 | } 124 | &-with-range&-with-seconds{ 125 | .@{picker-prefix-cls}-panel{ 126 | &-body{ 127 | min-width: @time-picker-cells-width-with-seconds * 2 + 4px; 128 | } 129 | } 130 | } 131 | } 132 | 133 | .@{picker-prefix-cls}-panel-content{ 134 | .@{picker-prefix-cls}-panel-content{ 135 | .@{time-picker-prefix-cls}{ 136 | &-cells{ 137 | min-width: @time-picker-cells-width-with-date-with-seconds; 138 | &-with-seconds{ 139 | min-width: @time-picker-cells-width-with-date-with-seconds; 140 | .@{time-picker-prefix-cls}-cells-list{ 141 | width: @time-picker-cells-width-with-date-with-seconds / 3; 142 | ul{ 143 | li{ 144 | padding: 0 0 0 28px; 145 | } 146 | } 147 | } 148 | } 149 | &-list { 150 | width: @time-picker-cells-width-with-date-with-seconds / 2; 151 | max-height: 216px; 152 | &:first-child{ 153 | border-radius: 0; 154 | } 155 | &:last-child{ 156 | border-radius: 0; 157 | } 158 | ul{ 159 | padding: 0 0 192px 0; 160 | li{ 161 | padding: 0 0 0 46px; 162 | } 163 | } 164 | } 165 | } 166 | } 167 | } 168 | } -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/select.less: -------------------------------------------------------------------------------- 1 | @select-prefix-cls: ~"@{css-prefix}select"; 2 | @select-item-prefix-cls: ~"@{css-prefix}select-item"; 3 | @select-group-prefix-cls: ~"@{css-prefix}select-group"; 4 | 5 | .@{select-prefix-cls} { 6 | display: inline-block; 7 | width: 100%; 8 | box-sizing: border-box; 9 | vertical-align: middle; 10 | color: @text-color; 11 | font-size: @font-size-base; 12 | //position: relative; 13 | line-height: normal; 14 | 15 | &-selection { 16 | display: block; 17 | box-sizing: border-box; 18 | outline: none; 19 | user-select: none; 20 | cursor: pointer; 21 | position: relative; 22 | 23 | background-color: #fff; 24 | border-radius: @btn-border-radius; 25 | border: 1px solid @border-color-base; 26 | transition: all @transition-time @ease-in-out; 27 | 28 | .@{select-prefix-cls}-arrow:nth-of-type(1) { 29 | display: none; 30 | cursor: pointer; 31 | } 32 | 33 | &:hover { 34 | .hover(); 35 | .@{select-prefix-cls}-arrow:nth-of-type(1) { 36 | display: inline-block; 37 | } 38 | } 39 | } 40 | 41 | &-show-clear &-selection:hover .@{select-prefix-cls}-arrow:nth-of-type(2){ 42 | display: none; 43 | } 44 | 45 | &-arrow { 46 | .inner-arrow(); 47 | } 48 | 49 | &-visible{ 50 | .@{select-prefix-cls}-selection{ 51 | .active(); 52 | } 53 | 54 | .@{select-prefix-cls}-arrow:nth-of-type(2) { 55 | transform: rotate(180deg); 56 | } 57 | } 58 | 59 | &-disabled { 60 | .@{select-prefix-cls}-selection { 61 | .disabled(); 62 | 63 | .@{select-prefix-cls}-arrow:nth-of-type(1) { 64 | display: none; 65 | } 66 | 67 | &:hover { 68 | border-color: @border-color-base; 69 | box-shadow: none; 70 | 71 | .@{select-prefix-cls}-arrow:nth-of-type(2) { 72 | display: inline-block; 73 | } 74 | } 75 | } 76 | } 77 | 78 | &-single &-selection{ 79 | height: @input-height-base; 80 | position: relative; 81 | 82 | .@{select-prefix-cls}-placeholder{ 83 | color: @input-placeholder-color; 84 | } 85 | 86 | .@{select-prefix-cls}-placeholder, .@{select-prefix-cls}-selected-value{ 87 | display: block; 88 | height: @input-height-base - 2px; 89 | line-height: @input-height-base - 2px; 90 | font-size: @font-size-small; 91 | overflow: hidden; 92 | text-overflow: ellipsis; 93 | white-space: nowrap; 94 | padding-left: 8px; 95 | padding-right: 24px; 96 | } 97 | } 98 | 99 | &-large&-single &-selection{ 100 | height: @input-height-large; 101 | 102 | .@{select-prefix-cls}-placeholder, .@{select-prefix-cls}-selected-value{ 103 | height: @input-height-large - 2px; 104 | line-height: @input-height-large - 2px; 105 | font-size: @font-size-base; 106 | } 107 | } 108 | 109 | &-small&-single &-selection{ 110 | height: @input-height-small; 111 | border-radius: @btn-border-radius-small; 112 | 113 | .@{select-prefix-cls}-placeholder, .@{select-prefix-cls}-selected-value{ 114 | height: @input-height-small - 2px; 115 | line-height: @input-height-small - 2px; 116 | } 117 | } 118 | 119 | &-multiple &-selection{ 120 | padding: 0 24px 0 4px; 121 | min-height: @input-height-base; 122 | 123 | .@{select-prefix-cls}-placeholder{ 124 | display: block; 125 | height: @input-height-base - 2px; 126 | line-height: @input-height-base - 2px; 127 | color: @input-placeholder-color; 128 | font-size: @font-size-small; 129 | overflow: hidden; 130 | text-overflow: ellipsis; 131 | white-space: nowrap; 132 | padding-left: 4px; 133 | padding-right: 22px; 134 | } 135 | } 136 | 137 | // input 138 | &-input{ 139 | display: inline-block; 140 | height: @input-height-base; 141 | line-height: @input-height-base; 142 | padding: 0 24px 0 8px; 143 | font-size: @font-size-small; 144 | outline: none; 145 | border: none; 146 | box-sizing: border-box; 147 | color: @input-color; 148 | background-color: transparent; 149 | position: relative; 150 | cursor: pointer; 151 | .placeholder(); 152 | } 153 | 154 | &-single &-input{ 155 | width: 100%; 156 | } 157 | 158 | &-large &-input{ 159 | font-size: @font-size-base; 160 | height: @input-height-large; 161 | } 162 | 163 | &-small &-input{ 164 | height: @input-height-small; 165 | } 166 | 167 | &-multiple &-input{ 168 | height: @input-height-base - 3px; 169 | line-height: @input-height-base; 170 | padding: 0 0 0 4px; 171 | } 172 | 173 | &-not-found{ 174 | text-align: center; 175 | color: @btn-disable-color; 176 | } 177 | 178 | &-multiple .@{css-prefix}tag{ 179 | margin: 3px 4px 2px 0; 180 | } 181 | } 182 | 183 | .select-item(@select-prefix-cls, @select-item-prefix-cls); 184 | 185 | .@{select-prefix-cls}-multiple .@{select-item-prefix-cls} { 186 | &-selected{ 187 | color: @selected-color; 188 | background: #fff; 189 | } 190 | &-focus,&-selected:hover{ 191 | background: @background-color-select-hover; 192 | } 193 | 194 | &-selected&-focus { 195 | color: shade(@selected-color, 10%); 196 | background: #fff; 197 | } 198 | 199 | &-selected:after{ 200 | .ivu-icon(); 201 | float: right; 202 | font-size: 24px; 203 | content: '\F3FD'; 204 | color: @selected-color; 205 | } 206 | } 207 | 208 | .@{select-group-prefix-cls} { 209 | list-style: none; 210 | margin: 0; 211 | padding: 0; 212 | 213 | &-title { 214 | padding-left: 8px; 215 | font-size: 12px; 216 | color: @legend-color; 217 | height: 30px; 218 | line-height: 30px; 219 | } 220 | } 221 | 222 | .@{form-item-prefix-cls}-error{ 223 | .@{select-prefix-cls}{ 224 | &-selection{ 225 | border: 1px solid @error-color; 226 | } 227 | &-arrow{ 228 | color: @error-color; 229 | } 230 | &-visible .@{select-prefix-cls}-selection{ 231 | .active-error; 232 | } 233 | } 234 | } -------------------------------------------------------------------------------- /src/renderer/assets/my-theme/components/menu.less: -------------------------------------------------------------------------------- 1 | @menu-prefix-cls: ~"@{css-prefix}menu"; 2 | @menu-dropdown-item-prefix-cls: ~"@{menu-prefix-cls}-horizontal .@{menu-prefix-cls}-submenu .@{select-dropdown-prefix-cls} .@{menu-prefix-cls}-item"; 3 | 4 | .@{menu-prefix-cls} { 5 | display: block; 6 | margin: 0; 7 | padding: 0; 8 | outline: none; 9 | list-style: none; 10 | color: @text-color; 11 | font-size: @font-size-base; 12 | position: relative; 13 | 14 | &-horizontal{ 15 | height: 60px; 16 | line-height: 60px; 17 | 18 | &.@{menu-prefix-cls}-light{ 19 | &:after{ 20 | content: ''; 21 | display: block; 22 | width: 100%; 23 | height: 1px; 24 | background: @border-color-base; 25 | position: absolute; 26 | bottom: 0; 27 | left: 0; 28 | } 29 | } 30 | } 31 | &-vertical{ 32 | &.@{menu-prefix-cls}-light{ 33 | &:after{ 34 | content: ''; 35 | display: block; 36 | width: 1px; 37 | height: 100%; 38 | background: @border-color-base; 39 | position: absolute; 40 | top: 0; 41 | bottom: 0; 42 | right: 0; 43 | z-index: 1; 44 | } 45 | } 46 | } 47 | 48 | &-light{ 49 | background: #fff; 50 | } 51 | &-dark{ 52 | background: @title-color; 53 | } 54 | &-primary{ 55 | background: @primary-color; 56 | } 57 | 58 | &-item{ 59 | display: block; 60 | outline: none; 61 | list-style: none; 62 | font-size: @font-size-base; 63 | position: relative; 64 | z-index: 1; 65 | cursor: pointer; 66 | transition: all @transition-time @ease-in-out; 67 | } 68 | &-item > i{ 69 | margin-right: 6px; 70 | } 71 | &-submenu-title > i, &-submenu-title span > i{ 72 | margin-right: 8px; 73 | } 74 | 75 | &-horizontal &-item, 76 | &-horizontal &-submenu 77 | { 78 | float: left; 79 | padding: 0 20px; 80 | position: relative; 81 | cursor: pointer; 82 | z-index: 3; 83 | transition: all @transition-time @ease-in-out; 84 | } 85 | 86 | &-light&-horizontal &-item, &-light&-horizontal &-submenu{ 87 | height: inherit; 88 | line-height: inherit; 89 | border-bottom: 2px solid transparent; 90 | color: @text-color; 91 | &-active, &:hover{ 92 | color: @primary-color; 93 | border-bottom: 2px solid @primary-color; 94 | } 95 | } 96 | 97 | &-dark&-horizontal &-item, &-dark&-horizontal &-submenu{ 98 | color: @subsidiary-color; 99 | &-active, &:hover{ 100 | color: #fff; 101 | } 102 | } 103 | 104 | &-primary&-horizontal &-item, &-primary&-horizontal &-submenu{ 105 | color: #fff; 106 | &-active, &:hover{ 107 | background: @link-active-color; 108 | } 109 | } 110 | 111 | &-horizontal &-submenu .@{select-dropdown-prefix-cls} { 112 | min-width: 100%; 113 | width: auto; 114 | max-height: none; 115 | .@{menu-prefix-cls}-item{ 116 | height: auto; 117 | line-height: normal; 118 | border-bottom: 0; 119 | float: none; 120 | } 121 | } 122 | 123 | &-item-group{ 124 | line-height: normal; 125 | &-title { 126 | height: 30px; 127 | line-height: 30px; 128 | padding-left: 8px; 129 | font-size: @font-size-small; 130 | color: @legend-color; 131 | } 132 | 133 | & > ul{ 134 | padding: 0 !important; 135 | list-style: none !important; 136 | } 137 | } 138 | 139 | // vertical 140 | &-vertical &-item, 141 | &-vertical &-submenu-title 142 | { 143 | padding: 14px 24px; 144 | position: relative; 145 | cursor: pointer; 146 | z-index: 1; 147 | transition: all @transition-time @ease-in-out; 148 | 149 | &:hover{ 150 | background: @background-color-select-hover; 151 | } 152 | } 153 | 154 | &-vertical &-submenu-title-icon{ 155 | float: right; 156 | position: relative; 157 | top: 4px; 158 | } 159 | &-submenu-title-icon { 160 | transition: transform @transition-time @ease-in-out; 161 | } 162 | &-opened &-submenu-title-icon{ 163 | transform: rotate(180deg); 164 | } 165 | 166 | &-vertical &-submenu &-item{ 167 | padding-left: 43px; 168 | } 169 | &-vertical &-item-group{ 170 | &-title{ 171 | height: 48px; 172 | line-height: 48px; 173 | font-size: @font-size-base; 174 | padding-left: 28px; 175 | } 176 | } 177 | &-dark&-vertical &-item-group{ 178 | &-title{ 179 | color: @text-color; 180 | } 181 | } 182 | 183 | &-light&-vertical &-item{ 184 | border-right: 2px solid transparent; 185 | &-active:not(.@{menu-prefix-cls}-submenu){ 186 | color: @primary-color; 187 | border-right: 2px solid @primary-color; 188 | z-index: 2; 189 | } 190 | } 191 | 192 | &-dark&-vertical &-item, &-dark&-vertical &-submenu-title{ 193 | color: @subsidiary-color; 194 | &-active:not(.@{menu-prefix-cls}-submenu), 195 | &-active:not(.@{menu-prefix-cls}-submenu):hover 196 | { 197 | background: @menu-dark-active-bg; 198 | } 199 | &:hover{ 200 | color: #fff; 201 | background: @title-color; 202 | } 203 | &-active:not(.@{menu-prefix-cls}-submenu){ 204 | color: @primary-color; 205 | border-right: 2px solid @primary-color; 206 | } 207 | } 208 | &-dark&-vertical &-submenu &-item{ 209 | &:hover{ 210 | color: #fff; 211 | background: transparent !important; 212 | } 213 | &-active,&-active:hover{ 214 | border-right: none; 215 | color: #fff; 216 | background: @primary-color !important; 217 | } 218 | } 219 | &-dark&-vertical &-item-active &-submenu-title{ 220 | color: #fff; 221 | } 222 | 223 | &-dark&-vertical &-opened{ 224 | background: @menu-dark-active-bg; 225 | .@{menu-prefix-cls}-submenu-title{ 226 | background: @title-color; 227 | } 228 | } 229 | } 230 | .select-item(@menu-prefix-cls, @menu-dropdown-item-prefix-cls); 231 | 232 | .@{menu-dropdown-item-prefix-cls} { 233 | padding: 7px 16px 8px; 234 | font-size: @font-size-base !important; 235 | } --------------------------------------------------------------------------------