├── .all-contributorsrc ├── .browserslistrc ├── .eslintrc.js ├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── question.md │ └── suggestion.md ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── babel.config.js ├── build ├── bin │ └── gen-cssfile.js └── docs-deploy.sh ├── components.json ├── docs ├── .vuepress │ ├── config.js │ ├── enhanceApp.js │ └── layout.vue ├── README.md └── component │ ├── README.md │ ├── basic │ ├── deepexi-card.md │ ├── list-container.md │ └── markdown-view.md │ ├── guide │ ├── guide.md │ └── introduction.md │ └── hoc │ ├── loading-button.md │ ├── loading-dialog.md │ ├── prompt-form.md │ ├── search-input.md │ └── text-tooltip.md ├── package.json ├── plop-templates ├── component │ ├── css.hbs │ ├── export.hbs │ ├── index.hbs │ ├── md.hbs │ └── prompt.js ├── utils.js └── writeJsonAndBuildEntry.js ├── plopfile.js ├── public ├── demo.html ├── favicon.ico ├── index.html └── test.html ├── src ├── components │ ├── deepexi-card │ │ ├── index.js │ │ └── index.vue │ ├── list-container │ │ ├── index.js │ │ └── index.vue │ ├── loading-button │ │ ├── index.js │ │ └── index.vue │ ├── loading-dialog │ │ ├── index.js │ │ ├── index.vue │ │ └── render.js │ ├── markdown-view │ │ ├── index.js │ │ ├── index.vue │ │ └── utils.js │ ├── prompt-form │ │ ├── drawer.vue │ │ ├── gene-wrapper.js │ │ └── index.js │ ├── search-input │ │ ├── index.js │ │ └── index.vue │ └── text-tooltip │ │ ├── index.js │ │ └── index.vue ├── index.js ├── mixins │ └── emitter.js ├── theme-chalk │ ├── gulpfile.js │ └── src │ │ ├── common │ │ ├── markdown-preview.less │ │ └── var.less │ │ ├── deepexi-card.less │ │ ├── index.less │ │ ├── list-container.less │ │ ├── loading-button.less │ │ ├── loading-dialog.less │ │ ├── markdown-view.less │ │ ├── search-input.less │ │ └── text-tooltip.less └── utils │ └── assist.js ├── vue.config.js └── yarn.lock /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "projectName": "deep-ui", 3 | "projectOwner": "cjfff", 4 | "repoType": "github", 5 | "repoHost": "https://github.com", 6 | "files": [ 7 | "README.md" 8 | ], 9 | "imageSize": 100, 10 | "commit": true, 11 | "commitConvention": "gitmoji", 12 | "contributors": [ 13 | { 14 | "login": "cjfff", 15 | "name": "cjfff", 16 | "avatar_url": "https://avatars1.githubusercontent.com/u/20502762?v=4", 17 | "profile": "http://www.ccc1996.cn", 18 | "contributions": [ 19 | "doc", 20 | "bug", 21 | "example", 22 | "ideas", 23 | "maintenance", 24 | "code" 25 | ] 26 | }, 27 | { 28 | "login": "JE-lee", 29 | "name": "lee", 30 | "avatar_url": "https://avatars0.githubusercontent.com/u/19794813?v=4", 31 | "profile": "https://github.com/JE-lee", 32 | "contributions": [ 33 | "code", 34 | "doc", 35 | "example" 36 | ] 37 | } 38 | ], 39 | "contributorsPerLine": 7 40 | } 41 | -------------------------------------------------------------------------------- /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | extends: ["plugin:vue/essential", "eslint:recommended", "@vue/prettier"], 7 | parserOptions: { 8 | parser: "babel-eslint" 9 | }, 10 | rules: { 11 | "no-console": process.env.NODE_ENV === "production" ? "error" : "off", 12 | "no-debugger": process.env.NODE_ENV === "production" ? "error" : "off" 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 'Bug Report' 3 | about: '创建错误报告以帮助我们改进。' 4 | title: '[bug]' 5 | labels: 'bug' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 13 | 14 | ## 问题描述 15 | 16 | 17 | ## 最小可复现仓库 18 | > 请创建最小可复现代码,并上传到你的 GitHub 仓库 19 | 20 | 21 | ## 预期的行为和实际行为 22 | 23 | 24 | ## 复现步骤,具体代码 25 | 26 | 27 | 28 | 29 | 30 | 31 | ## 相关环境信息 32 | - **操作系统**: 33 | - **Node 版本**: 34 | - **deep-ui 版本**: 35 | - **Vue 版本**: 36 | - **引用方式**: CDN / NPM ? -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: 问我们一个关于这个项目的问题 4 | title: '[question]' 5 | labels: 'question' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | ## 你想知道什么? 12 | 13 | 14 | 你好,我想知道这个项目是否可以... 15 | 16 | ## 描述你考虑过的替代方案 17 | 18 | 19 | 我想... 20 | 21 | ## 其它 22 | 23 | 无 -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/suggestion.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Suggestion 3 | about: 为这个项目提出一个建议 4 | title: '[suggest]' 5 | labels: 'help wanted' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## 你建议我们做什么? 11 | 12 | 13 | 现在... 14 | 15 | 如果你能... 16 | 17 | 它将使... 18 | 19 | ## 其它 20 | 21 | 无 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw? 22 | 23 | lib/* -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - lts/* 4 | install: 5 | - yarn install # npm ci 6 | script: npm run docs:deploy -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018-present, Vivint, Inc. 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 13 | all 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 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # deep-ui 2 | 3 | [![Build Status](https://travis-ci.com/cjfff/deep-ui.svg?branch=master)](https://travis-ci.com/cjfff/deep-ui) 4 | [![NPM License](https://badgen.net/npm/license/@femessage/el-data-table)](https://github.com/cjfff/deep-ui/raw/master/LICENSE) 5 | [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/cjfff/deep-ui/pulls) 6 | 7 | 8 | ## 介绍 9 | 10 | 每家公司/每个团队,在持续协作维护项目的过程中,总会产出一些较为通用性的组件,或者 UI 会设计一些样式组件。 11 | 12 | 但是如果放在项目里的话,大家其实都不会去翻文件看,那这时候有个文档记录一下这些通用组件的话,会让大家协作的意愿更强烈。:fire: 13 | 14 | 更重要的是,可以提高代码的复用性, 打包编译发布到 `npm` 上,告别多项目的复制粘贴。 :beers: 15 | 16 | 使用及其简单的方式 (vue-cli3 以及 vuepress) 维护 团队/个人的 组件库。:tada::tada::tada: 17 | 18 | ## Features 19 | 20 | - [x] 代码打包 📦 npm lib 即可 21 | - [x] 代码即文档,代码里面加注释即可解决文档问题 22 | - [x] `yarn new` 交互式创建新组件文件,不用再繁琐的写 `template` 23 | - [x] 按需加载 css [栗子仓库](https://github.com/cjfff/deep-ui-demo) 24 | - [ ] 添加 eslint 25 | - [ ] standard-version 26 | - [ ] 自动生成 release logs 27 | 28 | ## Project setup 29 | 30 | 由于 `vuepress` 依赖的是 `core-js` 是 2.x 版本,而 `vue-cli3` 中依赖的是 3.x 版本. 31 | 32 | 所以 `vuepress` 需要进行全局安装。 33 | 34 | ```js 35 | 36 | npm i -g vuepress core-js@2.6.11 37 | 38 | ``` 39 | 40 | ``` 41 | git clone 42 | 43 | yarn install 44 | 45 | yarn docs:dev // 启动开发模式 46 | 47 | yarn new // 创建新组件 48 | ``` 49 | 50 | ## 发布 51 | 52 | 现在还没有自动化... 53 | 54 | ```shell 55 | yarn pub 56 | 57 | # 更新 package.json 然后 58 | 59 | npm publish 60 | "pub": "yarn build:lib && yarn build:theme", 61 | ``` 62 | 63 | ### 参考链接 64 | - https://github.com/vue-styleguidist/vuepress-plugin-live 65 | - https://github.com/BuptStEve/markdown-it-vuese 66 | - https://github.com/shuidi-fed/vuese 67 | - https://markdown-it.github.io/markdown-it/ 68 | - https://github.com/koca/vue-prism-editor 69 | - https://juejin.im/post/5dd234635188254a1f44646a#heading-27 70 | - https://segmentfault.com/a/1190000015261753 71 | 72 | 73 | 74 | ## Contributors ✨ 75 | 76 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 |

cjfff

📖 🐛 💡 🤔 🚧 💻

lee

💻 📖 💡
87 | 88 | 89 | 90 | 91 | 92 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! 93 | 94 | 95 | [![All Contributors](https://img.shields.io/badge/all_contributors-2-orange.svg?style=flat-square)](#contributors-) 96 | 97 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ["@vue/cli-plugin-babel/preset"] 3 | }; 4 | -------------------------------------------------------------------------------- /build/bin/gen-cssfile.js: -------------------------------------------------------------------------------- 1 | var fs = require("fs"); 2 | var path = require("path"); 3 | var Components = require("../../components.json"); 4 | var themes = ["theme-chalk"]; 5 | Components = Object.keys(Components); 6 | var basepath = path.resolve(__dirname, "../../src/"); 7 | 8 | function fileExists(filePath) { 9 | try { 10 | return fs.statSync(filePath).isFile(); 11 | } catch (err) { 12 | return false; 13 | } 14 | } 15 | 16 | themes.forEach(theme => { 17 | var isSCSS = theme !== "theme-default"; 18 | var indexContent = isSCSS 19 | ? '@import "./common/var.less";\n' 20 | : '@import "./base.css";\n'; 21 | Components.forEach(function(key) { 22 | if (["icon", "option", "option-group"].indexOf(key) > -1) return; 23 | var fileName = key + (isSCSS ? ".less" : ".css"); 24 | indexContent += '@import "./' + fileName + '";\n'; 25 | var filePath = path.resolve(basepath, theme, "src", fileName); 26 | if (!fileExists(filePath)) { 27 | fs.writeFileSync(filePath, "", "utf8"); 28 | console.log(theme, " 创建遗漏的 ", fileName, " 文件"); 29 | } 30 | }); 31 | fs.writeFileSync( 32 | path.resolve(basepath, theme, "src", isSCSS ? "index.less" : "index.css"), 33 | indexContent 34 | ); 35 | }); 36 | -------------------------------------------------------------------------------- /build/docs-deploy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 确保脚本抛出遇到的错误 4 | set -e 5 | 6 | # 安装 vuepress 和 core-js 依赖 7 | npm i -g vuepress core-js@2.6.11 --registry=https://registry.npm.taobao.org 8 | 9 | # 生成静态文件 10 | npm run docs:build 11 | 12 | 13 | mkdir temp_web 14 | cd temp_web 15 | 16 | 17 | git clone --depth 1 -b gh-pages --single-branch https://${GITHUB_TOKEN}@github.com/cjfff/deep-ui.git && cd deep-ui 18 | 19 | rm -rf ./deep-ui/* 20 | 21 | cp -rf ../../dist/* . 22 | 23 | git add -A . 24 | git commit -m "deploy" 25 | git push origin gh-pages 26 | 27 | cd ../../ 28 | rm -rf temp_web 29 | 30 | -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "text-tooltip": "./components/text-tooltip/index.js", 3 | "search-input": "./components/search-input/index.js", 4 | "list-container": "./components/list-container/index.js", 5 | "deepexi-card": "./components/deepexi-card/index.js", 6 | "loading-dialog": "./components/loading-dialog/index.js", 7 | "markdown-view": "./components/markdown-view/index.js", 8 | "loading-button": "./components/loading-button/index.js" 9 | } -------------------------------------------------------------------------------- /docs/.vuepress/config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const glob = require('glob'); 3 | 4 | const getPath = (path) => path.replace(/.*component\//, '') 5 | 6 | const getDocs = (dir = 'basic') => { 7 | 8 | const docs = glob 9 | .sync(path.resolve(__dirname, `../component/${dir}/*.md`)) 10 | .map(p => getPath(p)) 11 | 12 | return docs 13 | } 14 | 15 | module.exports = { 16 | title: 'DeepUi', 17 | base: `/deep-ui/`, 18 | dest: 'dist', 19 | description: 'deepexi.com 中台研发团队的组件库', 20 | port: 8083, 21 | head: [ 22 | ['link', { rel: 'stylesheet', href: 'https://cdn.jsdelivr.net/npm/vue-prism-editor@0.5.1/dist/VuePrismEditor.css' }], 23 | ['link', { rel: 'stylesheet', href: 'https://cdn.jsdelivr.net/npm/@femessage/element-ui@2.16.0/lib/theme-chalk/index.css' }], 24 | ], 25 | plugins: [ 26 | '@vuepress/last-updated', 27 | '@vuepress/back-to-top', 28 | [ 29 | 'live', 30 | { 31 | // to use a custom layout for your vue components 32 | layout: path.resolve(__dirname, './layout.vue'), 33 | editorProps: { 34 | lineNumbers: true, 35 | } 36 | } 37 | ], 38 | ], 39 | configureWebpack: { 40 | resolve: { 41 | alias: { 42 | '@component': path.resolve(__dirname, '../../src'), 43 | '@': path.resolve(__dirname, '../../src'), 44 | '~': path.resolve(__dirname, '../../src') 45 | } 46 | }, 47 | }, 48 | themeConfig: { 49 | nav: [ 50 | { text: '主页', link: '/' }, 51 | { text: '组件', link: '/component/guide/introduction' }, 52 | { text: 'GitHub', link: 'https://github.com/cjfff/deep-ui' }, 53 | ], 54 | sidebar: { 55 | '/component/': [ 56 | { 57 | title: '开发指南', 58 | collapsable: false, 59 | children: getDocs('guide') 60 | }, 61 | { 62 | title: '基础组件', 63 | collapsable: false, 64 | children: getDocs('basic') 65 | }, 66 | { 67 | title: '高阶组件', 68 | collapsable: false, 69 | children: getDocs('hoc') 70 | }, 71 | { 72 | title: '布局组件', 73 | collapsable: false, 74 | children: getDocs('layout') 75 | }, 76 | ] 77 | } 78 | }, 79 | markdown: { 80 | extendMarkdown: (md) => { 81 | md.use(require('markdown-it-vuese/src/index.js'), { 82 | root: `${process.cwd()}/src/components/`, 83 | useRender: (vueseRender) => { 84 | const renderRes = vueseRender.render() 85 | // 格式转换可以去这里查看详情 https://vuese.org/zh/markdown-render/#%E5%AE%9E%E4%BE%8B%E6%96%B9%E6%B3%95-render 86 | return Object.entries(renderRes).reduce((acc, [title, value]) => acc.concat(`## ${title}\r ${value}`) 87 | , []).join('\r') 88 | }, 89 | }) 90 | 91 | } 92 | } 93 | } -------------------------------------------------------------------------------- /docs/.vuepress/enhanceApp.js: -------------------------------------------------------------------------------- 1 | import FormRenderer from '@femessage/el-form-renderer'; 2 | import ELEMENT from '@femessage/element-ui' 3 | import DeepUi from '../../src/index.js' 4 | import '../../src/theme-chalk/src/index.less' 5 | 6 | export default ({ 7 | Vue, 8 | options, 9 | router 10 | }) => { 11 | Vue.use(ELEMENT) 12 | Vue.use(DeepUi) 13 | Vue.component(FormRenderer.name, FormRenderer) 14 | } -------------------------------------------------------------------------------- /docs/.vuepress/layout.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 70 | 71 | 319 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | home: true 3 | heroImage: 4 | actionText: 开始使用 → 5 | actionLink: /component/guide/introduction 6 | features: 7 | - title: 基于Vue2.X 8 | details: 享受 Vue + webpack 的开发体验,在 Markdown 中使用 Vue 组件,同时可以使用 Vue 来开发自定义主题。 9 | - title: 轻量级UI 10 | details: 该UI使用了非常轻量级的设计理念,视觉感官更强烈 11 | - title: 高可用性 12 | details: 良好的API接口设计,统一的使用习惯 13 | footer: MIT Licensed | Copyright © 2020-cjfff 14 | --- -------------------------------------------------------------------------------- /docs/component/README.md: -------------------------------------------------------------------------------- 1 | ## 阅读 -------------------------------------------------------------------------------- /docs/component/basic/deepexi-card.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: deepexi-card 3 | --- 4 | # deepexi-card 5 | 6 | ## 基本使用 7 | 8 | ```vue live lineNumbers 9 | 17 | 18 | 47 | ``` 48 | 49 | <[vuese](deepexi-card/index.vue) 50 | -------------------------------------------------------------------------------- /docs/component/basic/list-container.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: list-container 3 | --- 4 | # list-container 5 | 6 | 简单易用的形式实现 `tab` 点击切换效果,无论是配合动态组件渲染还是内容修改,都及其容易扩展! 7 | 8 | ## 基本使用 9 | 10 | ```vue live lineNumbers 11 | 22 | 23 | 51 | ``` 52 | 53 | 54 | 55 | ## slot header 56 | 57 | ```vue live 58 | 73 | 74 | 102 | ``` 103 | 104 | <[vuese](list-container/index.vue) 105 | -------------------------------------------------------------------------------- /docs/component/basic/markdown-view.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: markdown-view 3 | --- 4 | # markdown-view 5 | 6 | 快速渲染 markdown 内容以及 toc 标题生成 7 | 8 | ## 基本使用 9 | 10 | ```vue live 11 | 16 | 17 | 259 | ``` 260 | 261 | 262 | <[vuese](markdown-view/index.vue) -------------------------------------------------------------------------------- /docs/component/guide/guide.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 安装 3 | --- 4 | # 开发指南 5 | 6 | 输入下列命令可以安装 deep-ui 7 | ``` 8 | npm install deep-ui --save 9 | ``` -------------------------------------------------------------------------------- /docs/component/guide/introduction.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 介绍 3 | --- 4 | # 介绍 5 | 6 | 由于 `vuepress` 依赖的是 `core-js` 是 2.x 版本,而 `vue-cli3` 中依赖的是 3.x 版本. 7 | 8 | 所以写文档的时候,需要你去全局安装一下 `vuepress` 以及 `core-js@2.6.11` 9 | 10 | ```js 11 | npm i -g vuepress core-js@2.6.11 12 | ``` -------------------------------------------------------------------------------- /docs/component/hoc/loading-button.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: loading-button 3 | --- 4 | # loading-button 5 | 6 | 懒人专用,小写一个 `loading` 效果,传入 `promise` 就会在 `promise pending` 期间产生 `loading` 的效果,`resolve` 或者 `rejected` 后结束。 7 | 8 | ## 基本使用 9 | 10 | ```vue live 11 | 14 | 15 | 27 | ``` 28 | 29 | <[vuese](@/loading-button/index.vue) -------------------------------------------------------------------------------- /docs/component/hoc/loading-dialog.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: loading-dialog 3 | --- 4 | # loading-dialog 5 | 6 | 该组件内置了 `el-footer`,以及发送请求自动对 `confirm` 按钮进行 `loading`, 从细节上减少您的工作量~ 7 | 8 | ```vue live lineNumbers 9 | 22 | 23 | 58 | ``` 59 | 60 | 61 | <[vuese](loading-dialog/index.vue) -------------------------------------------------------------------------------- /docs/component/hoc/prompt-form.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: prompt-form 3 | --- 4 | # prompt-form 5 | 提供Vue.prototype.$promptDialog和Vue.prototype.$prompDrawer方法,用来向用户确认信息。 6 | 类似于window.prompt方法,让用户在弹窗中填写相关信息。好处是,不需要写那么多HTML模板。 7 | 8 | ## Arguments 9 | - [Array | Object] formOpt: 10 | - [el-form-renderer](https://github.com/FEMessage/el-form-renderer)组件接受的属性content, 11 | - 或者是el-form-render 可接受属性的对象。eg: { content: [], width: '170px'} 12 | - [String] title: 默认为'提示' 13 | - [Number] width: el-form-render的宽度, 默认是600 14 | 15 | ## 基本使用 16 | 17 | ```vue live 18 | 24 | 25 | 53 | ``` 54 | 55 | ## 提交信息到服务器 56 | 可以指定弹窗关闭前调用的函数,这个函数需要返回一个Promise. 只有当该Promise resolve之后,弹窗才会关闭。 57 | 你可以在这个函数提交信息到服务器。当然你也可以在关闭弹窗之后在后台提交到服务器,但是如果提交失败,用户就必须重新输入 58 | 之前的表单信息了。 59 | 60 | ```vue live 61 | 66 | 67 | 101 | ``` 102 | -------------------------------------------------------------------------------- /docs/component/hoc/search-input.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: search-input 3 | --- 4 | # search-input 5 | 6 | 这是一个 UI 样式组件 7 | 8 | ```vue live lineNumbers 9 | 12 | 13 | 22 | ``` 23 | 24 | 25 | <[vuese](search-input/index.vue) -------------------------------------------------------------------------------- /docs/component/hoc/text-tooltip.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: text-tooltip 3 | --- 4 | # text-tooltip 5 | 6 | 当一些内容固定宽度,然后需要超出宽度部分隐藏的时候,为了防止重复书写这种 css....特产出此组件 7 | 8 | ## 基本使用 9 | 10 | ```vue live lineNumbers 11 | 16 | ``` 17 | 18 | ## 多行截断 19 | 20 | ```vue live 21 | 26 | ``` 27 | 28 | <[vuese](text-tooltip/index.vue) 29 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "deep-ui", 3 | "version": "1.0.0", 4 | "private": false, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "yarn lib", 8 | "lint": "vue-cli-service lint", 9 | "clean": "rimraf lib && rimraf src/*/lib", 10 | "build:theme": "node build/bin/gen-cssfile && gulp build --gulpfile src/theme-chalk/gulpfile.js && cp-cli src/theme-chalk/lib lib/theme-chalk", 11 | "build:lib": "vue-cli-service build --target lib --name deep-ui --dest lib src/index.js", 12 | "pub": "yarn build:lib && yarn build:theme", 13 | "docs:build": "vuepress build docs", 14 | "docs:dev": "vuepress dev docs", 15 | "docs:deploy": "bash build/docs-deploy.sh", 16 | "contributors:add": "all-contributors add", 17 | "contributors:generate": "all-contributors generate", 18 | "new": "plop" 19 | }, 20 | "description": "A Component Library for Vue.js.", 21 | "author": "cjfff ", 22 | "contributors": [ 23 | "https://github.com/cjfff" 24 | ], 25 | "repository": { 26 | "type": "git", 27 | "url": "https://github.com/cjfff/deep-ui.git" 28 | }, 29 | "homepage": "https://github.com/deep-ui/README.md", 30 | "files": [ 31 | "lib", 32 | "src" 33 | ], 34 | "keywords": [ 35 | "deep-ui", 36 | "vue", 37 | "components" 38 | ], 39 | "license": "MIT", 40 | "main": "lib/deep-ui.umd.min.js", 41 | "unpkg": "src/index.js", 42 | "style": "lib/theme-chalk/index.css", 43 | "devDependencies": { 44 | "@femessage/el-form-renderer": "^1.14.6", 45 | "@femessage/element-ui": "^2.16.0", 46 | "@vue/babel-preset-app": "^4.1.0", 47 | "@vue/cli-plugin-babel": "~4.2.0", 48 | "@vue/cli-plugin-eslint": "~4.2.0", 49 | "@vue/cli-plugin-router": "~4.2.0", 50 | "@vue/cli-service": "^4.2.3", 51 | "@vue/eslint-config-prettier": "^6.0.0", 52 | "all-contributors-cli": "^6.14.0", 53 | "babel-eslint": "^10.0.3", 54 | "cp-cli": "^2.0.0", 55 | "eslint": "^6.7.2", 56 | "eslint-plugin-prettier": "^3.1.1", 57 | "eslint-plugin-vue": "^6.1.2", 58 | "glob": "^7.1.6", 59 | "gulp": "^4.0.2", 60 | "gulp-autoprefixer": "^7.0.1", 61 | "gulp-cssmin": "^0.2.0", 62 | "gulp-less": "^4.0.1", 63 | "json-templater": "^1.2.0", 64 | "less": "^3.11.1", 65 | "less-loader": "^5.0.0", 66 | "markdown-it-vuese": "^0.4.0", 67 | "plop": "^2.6.0", 68 | "prettier": "^1.19.1", 69 | "vue": "^2.6.11", 70 | "vue-template-compiler": "^2.6.11", 71 | "vuepress-plugin-live": "^1.5.1" 72 | }, 73 | "dependencies": { 74 | "core-js": "3.x" 75 | } 76 | } -------------------------------------------------------------------------------- /plop-templates/component/css.hbs: -------------------------------------------------------------------------------- 1 | @import './common/var.less' -------------------------------------------------------------------------------- /plop-templates/component/export.hbs: -------------------------------------------------------------------------------- 1 | import {{ componentName }} from "./index.vue"; 2 | 3 | {{ componentName }}.install = function(Vue) { 4 | Vue.component({{ componentName }}.name, {{ componentName }}); 5 | }; 6 | 7 | export default {{ componentName }}; -------------------------------------------------------------------------------- /plop-templates/component/index.hbs: -------------------------------------------------------------------------------- 1 | {{#if template}} 2 | 5 | {{/if}} 6 | 7 | {{#if script}} 8 | 18 | {{/if}} 19 | -------------------------------------------------------------------------------- /plop-templates/component/md.hbs: -------------------------------------------------------------------------------- 1 | --- 2 | title: {{ name }} 3 | --- 4 | # {{ name }} 5 | 6 | ## 基本使用 7 | 8 | ```vue live 9 | 12 | ``` 13 | 14 | <[vuese]({{name}}/index.vue) -------------------------------------------------------------------------------- /plop-templates/component/prompt.js: -------------------------------------------------------------------------------- 1 | const { notEmpty, kebabCase, camelCase } = require("../utils.js"); 2 | 3 | module.exports = { 4 | description: "generate a component", 5 | prompts: [ 6 | { 7 | type: "input", 8 | name: "name", 9 | message: "请输入组件名字(请以驼峰命名)", 10 | validate: notEmpty("组件名字") 11 | }, 12 | { 13 | type: "list", 14 | name: "type", 15 | message: "请选择组件类型", 16 | choices: [ 17 | { 18 | name: "基础组件", 19 | value: "basic" 20 | }, 21 | { 22 | name: "高阶组件", 23 | value: "hoc" 24 | }, 25 | { 26 | name: "布局组件", 27 | value: "layout" 28 | } 29 | ] 30 | } 31 | ], 32 | actions: data => { 33 | const kebabName = kebabCase(data.name); 34 | const componentName = camelCase(data.name); 35 | 36 | const actions = [ 37 | { 38 | type: "add", 39 | path: `src/components/${kebabName}/index.vue`, 40 | templateFile: "plop-templates/component/index.hbs", 41 | data: { 42 | componentName, 43 | name: kebabName, 44 | template: true, 45 | script: true, 46 | style: true 47 | } 48 | }, 49 | { 50 | type: "add", 51 | path: `src/components/${kebabName}/index.js`, 52 | templateFile: "plop-templates/component/export.hbs", 53 | data: { 54 | componentName 55 | } 56 | }, 57 | { 58 | type: "add", 59 | path: `docs/component/${data.type}/${kebabName}.md`, 60 | templateFile: "plop-templates/component/md.hbs", 61 | data: { 62 | name: kebabName 63 | } 64 | }, 65 | { 66 | type: "add", 67 | path: `src/theme-chalk/src/${kebabName}.less`, 68 | templateFile: "plop-templates/component/css.hbs" 69 | }, 70 | { 71 | type: "writeJsonAndBuildEntry", 72 | data: { 73 | name: data.name 74 | } 75 | } 76 | ]; 77 | 78 | return actions; 79 | } 80 | }; 81 | -------------------------------------------------------------------------------- /plop-templates/utils.js: -------------------------------------------------------------------------------- 1 | exports.notEmpty = name => { 2 | return v => { 3 | if (!v || v.trim === "") { 4 | return `${name} 必须填写`; 5 | } 6 | return true; 7 | }; 8 | }; 9 | 10 | // 下划线转换驼峰 11 | function camelCase(name) { 12 | return name 13 | .replace(/[\_|-](\w)/g, function(all, letter) { 14 | return letter.toUpperCase(); 15 | }) 16 | .replace(/./, _ => _.toUpperCase()); 17 | } 18 | // 驼峰转换中划线 19 | function kebabCase(name) { 20 | return name.replace(/([A-Z])/g, "-$1").toLowerCase(); 21 | } 22 | 23 | exports.camelCase = camelCase; 24 | exports.kebabCase = kebabCase; 25 | -------------------------------------------------------------------------------- /plop-templates/writeJsonAndBuildEntry.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const path = require("path"); 3 | const render = require("json-templater/string"); 4 | const { kebabCase, camelCase } = require("./utils.js"); 5 | 6 | const componentsFileName = "components.json"; 7 | const fcomponentsFileNameFilePath = path.resolve( 8 | __dirname, 9 | `../${componentsFileName}` 10 | ); 11 | 12 | const INDEX_OUTPUT_PATH = path.resolve(__dirname, "../src/index.js"); 13 | 14 | const endOfLine = require("os").EOL; 15 | 16 | const IMPORT_TEMPLATE = `import {{name}} from "{{path}}";`; 17 | const INSTALL_COMPONENT_TEMPLATE = " {{name}}"; 18 | const MAIN_TEMPLATE = `/* Automatically generated by plop buildEntryData action */ 19 | 20 | {{componentsImport}} 21 | 22 | // 存储组件列表 23 | const components = [ 24 | {{componentNames}} 25 | ]; 26 | 27 | // 定义 install 方法,接收 Vue 作为参数。如果使用 use 注册插件,则所有的组件都将被注册 28 | const install = function(Vue) { 29 | // 判断是否安装 30 | if (install.installed) return; 31 | // 遍历注册全局组件 32 | components.forEach(component => Vue.component(component.name, component)); 33 | }; 34 | 35 | // 判断是否是直接引入文件 36 | if (typeof window !== "undefined" && window.Vue) { 37 | install(window.Vue); 38 | } 39 | 40 | export default { 41 | // 导出的对象必须具有 install,才能被 Vue.use() 方法安装 42 | install, 43 | // 以下是具体的组件列表 44 | {{componentNames}} 45 | }; 46 | `; 47 | module.exports = function({ name }) { 48 | const componentJson = require(fcomponentsFileNameFilePath); 49 | 50 | const kebName = kebabCase(name); 51 | 52 | componentJson[kebName] = `./components/${kebName}/index.js`; 53 | 54 | const componetsEntries = Object.entries(componentJson); 55 | 56 | const componentsImport = componetsEntries 57 | .map(([name, path]) => 58 | render(IMPORT_TEMPLATE, { 59 | name: camelCase(name), 60 | path 61 | }) 62 | ) 63 | .join(endOfLine); 64 | 65 | const componentNames = componetsEntries 66 | .map(([name]) => 67 | render(INSTALL_COMPONENT_TEMPLATE, { name: camelCase(name) }) 68 | ) 69 | .join(`,${endOfLine}`); 70 | 71 | fs.writeFileSync( 72 | fcomponentsFileNameFilePath, 73 | JSON.stringify(componentJson, null, " "), 74 | "utf-8" 75 | ); 76 | 77 | fs.writeFileSync( 78 | INDEX_OUTPUT_PATH, 79 | render(MAIN_TEMPLATE, { 80 | componentNames, 81 | componentsImport 82 | }), 83 | "utf-8" 84 | ); 85 | 86 | return "write component.json and index.js is ok"; 87 | }; 88 | -------------------------------------------------------------------------------- /plopfile.js: -------------------------------------------------------------------------------- 1 | const componentGenerator = require("./plop-templates/component/prompt"); 2 | const writeJsonAndBuildEntry = require("./plop-templates/writeJsonAndBuildEntry"); 3 | 4 | module.exports = plop => { 5 | // 增加一种 action 6 | plop.setActionType("writeJsonAndBuildEntry", writeJsonAndBuildEntry); 7 | 8 | plop.setGenerator("component", componentGenerator); 9 | }; 10 | -------------------------------------------------------------------------------- /public/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | <%= htmlWebpackPlugin.options.title %> 12 | 13 | 14 | 17 |
18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjfff/deep-ui/5efa3ef655d6d26bc298acc40d07da715d21c909/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /public/test.html: -------------------------------------------------------------------------------- 1 | 2 | deepexi demo 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | {{msg}} 12 | 13 |
14 | 15 | -------------------------------------------------------------------------------- /src/components/deepexi-card/index.js: -------------------------------------------------------------------------------- 1 | import DeepexiCard from "./index.vue"; 2 | 3 | DeepexiCard.install = function(Vue) { 4 | Vue.component(DeepexiCard.name, DeepexiCard); 5 | }; 6 | 7 | export default DeepexiCard; 8 | -------------------------------------------------------------------------------- /src/components/deepexi-card/index.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 20 | -------------------------------------------------------------------------------- /src/components/list-container/index.js: -------------------------------------------------------------------------------- 1 | import ListContainer from "./index.vue"; 2 | 3 | ListContainer.install = function(Vue) { 4 | Vue.component(ListContainer.name, ListContainer); 5 | }; 6 | 7 | export default ListContainer; 8 | -------------------------------------------------------------------------------- /src/components/list-container/index.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 115 | -------------------------------------------------------------------------------- /src/components/loading-button/index.js: -------------------------------------------------------------------------------- 1 | import LoadingButton from "./index.vue"; 2 | 3 | LoadingButton.install = function(Vue) { 4 | Vue.component(LoadingButton.name, LoadingButton); 5 | }; 6 | 7 | export default LoadingButton; 8 | -------------------------------------------------------------------------------- /src/components/loading-button/index.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 39 | -------------------------------------------------------------------------------- /src/components/loading-dialog/index.js: -------------------------------------------------------------------------------- 1 | import LoadingDialog from "./index.vue"; 2 | 3 | LoadingDialog.install = function(Vue) { 4 | Vue.component(LoadingDialog.name, LoadingDialog); 5 | }; 6 | 7 | export default LoadingDialog; 8 | -------------------------------------------------------------------------------- /src/components/loading-dialog/index.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 136 | -------------------------------------------------------------------------------- /src/components/loading-dialog/render.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: "render", 3 | functional: true, 4 | props: { 5 | render: Function, 6 | data: Object, 7 | node: Array 8 | }, 9 | render: (h, ctx) => { 10 | const params = { 11 | data: ctx.props.data 12 | }; 13 | const { render } = ctx.props; 14 | 15 | return typeof render === "object" ? render : render(h, params); 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /src/components/markdown-view/index.js: -------------------------------------------------------------------------------- 1 | export { default } from "./index.vue"; 2 | -------------------------------------------------------------------------------- /src/components/markdown-view/index.vue: -------------------------------------------------------------------------------- 1 | 37 | 38 | 326 | -------------------------------------------------------------------------------- /src/components/markdown-view/utils.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /** 3 | * 生成带有 id 的标题 DOM 4 | * @param {*} param0 5 | */ 6 | export const renderTitle = ({level, id, content}) => `${content}`; 7 | 8 | /** 9 | * 生成带有 height & width 的 img DOM 10 | * @param {*} param0 11 | */ 12 | export const renderImage = ({src, height, width}) => 13 | ``; 14 | 15 | /** 16 | * 生成随机值的 id 17 | * @param {*} name 18 | */ 19 | export const ganerateId = name => 20 | name + (Math.random().toString(16) + Date.now()).toString(16).slice(2); 21 | 22 | // 进行 23 | export const handleMenuReplace = (html, menuList) => 24 | menuList.reduce((content, {origin, htmlContent}) => content.replace(origin, htmlContent), html); 25 | 26 | // 批量对图片节点进行替换 27 | export const handleImageList = async (content, maxImageWidth) => { 28 | let imageList = []; 29 | 30 | try { 31 | imageList = await handleContentImage(content, maxImageWidth); // 批量获取图片宽高 32 | } catch (error) { 33 | console.error(error); 34 | return imageList; 35 | } 36 | 37 | return imageList.reduce( 38 | (html, {origin, src, height, width}) => html.replace(origin, renderImage({src, height, width})), 39 | content, 40 | ); 41 | }; 42 | 43 | /** 44 | * 获取图片高度宽度 45 | * @param {*} param0 46 | * @param {*} maxImageWidth 47 | */ 48 | export const getImageWidthAndHeight = ({src, dom}, maxImageWidth = 746) => { 49 | return new Promise(resolve => { 50 | const image = new Image(); 51 | image.referrerPolicy = 'no-referrer'; 52 | image.src = src; 53 | image.onload = () => { 54 | const {width, height} = image; 55 | const rate = width > maxImageWidth ? parseFloat((image.width / maxImageWidth).toFixed(2)) : 1; 56 | const isOrigin = rate === 1; 57 | resolve({ 58 | src, 59 | origin: dom, 60 | width: isOrigin ? width : maxImageWidth, 61 | height: isOrigin ? height : ~~(height / rate), 62 | }); 63 | }; 64 | }); 65 | }; 66 | 67 | export const handleContentImage = async (content, maxImageWidth = 746) => { 68 | const imgRegExp = //i; 69 | // 取得内容中所有的 img 标签字符 70 | 71 | const imgListReg = RegExp(imgRegExp.source, 'ig'); 72 | const imgList = content.match(imgListReg); 73 | 74 | if (!imgList) return []; 75 | 76 | // 这个正则是用来取得 src="" 里面的链接的 77 | const srcRegexp = RegExp(imgRegExp.source, 'i'); 78 | 79 | return Promise.all( 80 | imgList.map(imgItem => { 81 | const [dom, src] = srcRegexp.exec(imgItem); 82 | return getImageWidthAndHeight( 83 | { 84 | dom, 85 | src, 86 | }, 87 | maxImageWidth, 88 | ); 89 | }), 90 | ); 91 | }; 92 | 93 | export const handleMenuList = html => { 94 | const TITLE_REGEXP = /(.*)<\/h\1>/; 95 | 96 | // 匹配到所有的 title 97 | const titleListRegexep = RegExp(TITLE_REGEXP.source, 'g'); 98 | 99 | const titleList = html.match(titleListRegexep); 100 | 101 | const titleRegExp = RegExp(TITLE_REGEXP.source, 'i'); 102 | 103 | const menuList = (titleList || []).reduce((acc, item) => { 104 | const id = ganerateId('menu_'); 105 | 106 | const [str, level, _content] = titleRegExp.exec(item); 107 | 108 | // 只提取标签内的内容 109 | const content = _content.replace(/<[^>]+>/gi, '').replace(/ /g, ' '); 110 | 111 | if (level && content) { 112 | const htmlContent = renderTitle({level, content, id}); 113 | acc.push({ 114 | origin: str, 115 | htmlContent, 116 | level, 117 | content, 118 | id, 119 | }); 120 | } 121 | return acc; 122 | }, []); 123 | return menuList; 124 | }; 125 | 126 | /** 127 | * 节流,一段时间只运行一次 128 | * @param {*} fn 回调函数 129 | * @param {*} wait 130 | */ 131 | export const throttle = (fn, wait) => { 132 | let inThrottle, lastFn, lastTime; 133 | return function() { 134 | const context = this, 135 | args = arguments; 136 | if (!inThrottle) { 137 | fn.apply(context, args); 138 | lastTime = Date.now(); 139 | inThrottle = true; 140 | } else { 141 | clearTimeout(lastFn); 142 | lastFn = setTimeout(function() { 143 | if (Date.now() - lastTime >= wait) { 144 | fn.apply(context, args); 145 | lastTime = Date.now(); 146 | } 147 | }, Math.max(wait - (Date.now() - lastTime), 0)); 148 | } 149 | }; 150 | }; 151 | 152 | /** 153 | * 获取element元素对于target元素的相对高度 154 | * @param {*} element 155 | */ 156 | export function getElementViewTop(element, isRelative = false) { 157 | let actualTop = element.offsetTop; 158 | let current = element.offsetParent; 159 | if (!isRelative) { 160 | while (current !== null && current !== parent) { 161 | actualTop += current.offsetTop; 162 | current = current.offsetParent; 163 | } 164 | } 165 | let elementScrollTop = 0; 166 | if (document.compatMode == 'BackCompat') { 167 | elementScrollTop = document.body.scrollTop; 168 | } else { 169 | elementScrollTop = document.documentElement.scrollTop; 170 | } 171 | return actualTop - elementScrollTop; 172 | } 173 | -------------------------------------------------------------------------------- /src/components/prompt-form/drawer.vue: -------------------------------------------------------------------------------- 1 | 22 | 35 | 57 | -------------------------------------------------------------------------------- /src/components/prompt-form/gene-wrapper.js: -------------------------------------------------------------------------------- 1 | import Drawer from "./drawer"; // hack: 因为 el-drawer对超过屏幕的内容不会应用滚动条 2 | 3 | export function geneDialogWrapper(width = 600) { 4 | return { 5 | props: { 6 | visible: Boolean, 7 | title: String, 8 | sureLoading: Boolean 9 | }, 10 | methods: { 11 | proxyEvent(eventType, ...rest) { 12 | return () => this.$emit(eventType, rest); 13 | } 14 | }, 15 | render() { 16 | const footerStyle = { 17 | textAlign: "right" 18 | }; 19 | const handleUpdateVisible = val => { 20 | this.proxyEvent("update:visible", val)(); 21 | }; 22 | const visiListener = { 23 | on: { 24 | "update:visible": handleUpdateVisible 25 | } 26 | }; 27 | return ( 28 | 35 |
36 | {this.$slots.default} 37 |
38 |
39 | 取 消 40 | 45 | 确 定 46 | 47 |
48 |
49 | ); 50 | } 51 | }; 52 | } 53 | 54 | export function geneDrawerWrapper(width = 600) { 55 | return { 56 | props: { 57 | visible: Boolean, 58 | title: String 59 | }, 60 | components: { 61 | Drawer 62 | }, 63 | methods: { 64 | proxyEvent(eventType, ...rest) { 65 | return () => this.$emit(eventType, rest); 66 | }, 67 | sureHandler() { 68 | this.proxyEvent("sure")(); 69 | return Promise.resolve(); 70 | } 71 | }, 72 | render() { 73 | const _this = this; 74 | const spread = { 75 | on: { 76 | "update:visible"(val) { 77 | _this.proxyEvent("update:visible", val)(); 78 | } 79 | } 80 | }; 81 | return ( 82 | 90 |
91 | {this.$slots.default} 92 |
93 |
94 | ); 95 | } 96 | }; 97 | } 98 | -------------------------------------------------------------------------------- /src/components/prompt-form/index.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import { geneDialogWrapper, geneDrawerWrapper } from "./gene-wrapper"; 3 | let boxId = 0; 4 | 5 | // eslint-disable-next-line no-unused-vars 6 | function createPrompt(PromptWrapper, title, formOpt) { 7 | // formOpt的处理 8 | const formOpts = []; 9 | if (Array.isArray(formOpt.content)) { 10 | formOpts.push(formOpt); 11 | } 12 | const geneRef = i => `form${i}`; 13 | const geneVueOpt = (resolve, reject) => { 14 | return { 15 | data() { 16 | return { 17 | visible: false, 18 | id: `prompt-${boxId++}`, 19 | defaultLoading: false, 20 | sureLoading: false 21 | }; 22 | }, 23 | destroyed() { 24 | const child = document.getElementById(this.id); 25 | child && document.body.removeChild(child); 26 | }, 27 | methods: { 28 | prompt() { 29 | this.visible = true; 30 | }, 31 | shutdown() { 32 | this.visible = false; 33 | }, 34 | handleClosed() { 35 | this.$destroy(); 36 | // dialog 或者 drawer关闭的时候一律reject 37 | // 根据Promise的状态不可逆,这不会影响到已经resolve状态的Promise 38 | reject(new Error("cancel")); 39 | }, 40 | async handleSure() { 41 | let forms = []; 42 | 43 | try { 44 | if (formOpts.length <= 1) { 45 | const ref = this.$refs[geneRef(0)]; 46 | forms = ref.getFormValue(); 47 | await ref.validate(); 48 | } 49 | } catch { 50 | return; 51 | } 52 | 53 | if (typeof formOpt.beforeClose === "function") { 54 | this.sureLoading = true; 55 | await formOpt.beforeClose(forms).finally(() => { 56 | this.sureLoading = false; 57 | }); 58 | } 59 | resolve(forms); 60 | this.shutdown(); 61 | } 62 | }, 63 | mounted() { 64 | // TODO: 将rule validator函数绑定this到当前form 65 | /* formOpts.forEach((opt) => { 66 | (opt.content || []).forEach(item => { 67 | (item.rules || []).forEach(rule => { 68 | if (typeof rule.validator === 'function') { 69 | const validator = rule.validator 70 | rule.validator = (...rest) => { 71 | validator.call({}, ...rest); 72 | }; 73 | } 74 | }); 75 | }); 76 | }); */ 77 | }, 78 | components: { PromptWrapper }, 79 | render() { 80 | const _this = this; 81 | const visiListener = { 82 | on: { 83 | "update:visible"() { 84 | _this.shutdown(); 85 | } 86 | } 87 | }; 88 | const renderForm = (opt, ref) => { 89 | const { labelWidth = "120px", content, ...rest } = opt; 90 | return ( 91 | 99 | ); 100 | }; 101 | 102 | let body = null; 103 | // 单个表单 104 | if (formOpts.length <= 1) { 105 | body = renderForm(formOpts[0], geneRef(0)); 106 | } 107 | return ( 108 | 118 | {body} 119 | 120 | ); 121 | } 122 | }; 123 | }; 124 | return new Promise((resolve, reject) => { 125 | const box = document.createElement("div"); 126 | document.body.appendChild(box); 127 | // 实例化并且挂载 128 | const comp = (window.comp = new Vue(geneVueOpt(resolve, reject))); 129 | comp.$mount(box); 130 | 131 | comp.prompt(); 132 | // nextTick 确保el-form-render已经渲染 133 | Vue.nextTick(() => { 134 | const initDefaultValue = (opt, index) => { 135 | const ref = comp.$refs[geneRef(index)]; 136 | const defaultValue = opt.defaultValue; 137 | if (typeof defaultValue === "function") { 138 | comp.defaultLoading = true; 139 | defaultValue() 140 | .then(res => ref.updateForm(res)) 141 | .finally(() => (comp.defaultLoading = false)); 142 | } else { 143 | ref.updateForm(defaultValue || {}); 144 | } 145 | }; 146 | // 设置每个表单的初始值 147 | formOpts.forEach((form, index) => initDefaultValue(form, index)); 148 | }); 149 | }); 150 | } 151 | 152 | /** 153 | * 154 | * @param {*} formOpt | el-form-render 配置对象 或者是 155 | * { 156 | * beforeClose: fn, //点击确定之后调用的函数,必须得返回一个promise, promise resolve 后将会关闭对话框 157 | * content: el-form-render 配置对象, 158 | * defaultValue: 表单的初始值 159 | * } 160 | * @param {*} title 161 | */ 162 | export function promptDialog(formOpt, title, width) { 163 | const opt = Array.isArray(formOpt) ? { content: formOpt } : formOpt; 164 | return createPrompt(geneDialogWrapper(width), formOpt.title || title, opt); 165 | } 166 | 167 | /** 168 | * @param {*} formOpt | el-form-render 配置对象 或者是 169 | * { 170 | * beforeClose: fn, //点击确定之后调用的函数,必须得返回一个promise, promise resolve 后将会关闭对话框 171 | * content: el-form-render 配置对象, 172 | * defaultValue: 表单的初始值 173 | * } 174 | * @param {*} title 175 | */ 176 | export function promptDrawer(formOpt, title, width) { 177 | const opt = Array.isArray(formOpt) ? { content: formOpt } : formOpt; 178 | return createPrompt(geneDrawerWrapper(width), formOpt.title || title, opt); 179 | } 180 | -------------------------------------------------------------------------------- /src/components/search-input/index.js: -------------------------------------------------------------------------------- 1 | import SearchInput from "./index.vue"; 2 | 3 | SearchInput.install = function(Vue) { 4 | Vue.component(SearchInput.name, SearchInput); 5 | }; 6 | 7 | export default SearchInput; 8 | -------------------------------------------------------------------------------- /src/components/search-input/index.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 50 | -------------------------------------------------------------------------------- /src/components/text-tooltip/index.js: -------------------------------------------------------------------------------- 1 | import textTooltip from "./index.vue"; 2 | 3 | textTooltip.install = function(Vue) { 4 | Vue.component(textTooltip.name, textTooltip); 5 | }; 6 | 7 | export default textTooltip; 8 | -------------------------------------------------------------------------------- /src/components/text-tooltip/index.vue: -------------------------------------------------------------------------------- 1 | 97 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | /* Automatically generated by plop buildEntryData action */ 2 | 3 | import TextTooltip from "./components/text-tooltip/index.js"; 4 | import SearchInput from "./components/search-input/index.js"; 5 | import ListContainer from "./components/list-container/index.js"; 6 | import DeepexiCard from "./components/deepexi-card/index.js"; 7 | import LoadingDialog from "./components/loading-dialog/index.js"; 8 | import MarkdownView from "./components/markdown-view/index.js"; 9 | import LoadingButton from "./components/loading-button/index.js"; 10 | import { promptDialog, promptDrawer } from "./components/prompt-form"; 11 | 12 | // 存储组件列表 13 | const components = [ 14 | TextTooltip, 15 | SearchInput, 16 | ListContainer, 17 | DeepexiCard, 18 | LoadingDialog, 19 | MarkdownView, 20 | LoadingButton 21 | ]; 22 | 23 | // 定义 install 方法,接收 Vue 作为参数。如果使用 use 注册插件,则所有的组件都将被注册 24 | const install = function(Vue) { 25 | // 判断是否安装 26 | if (install.installed) return; 27 | // 遍历注册全局组件 28 | components.forEach(component => Vue.component(component.name, component)); 29 | // prompt-form 方法 30 | Vue.prototype.$promptDialog = promptDialog; 31 | Vue.prototype.$promptDrawer = promptDrawer; 32 | }; 33 | 34 | // 判断是否是直接引入文件 35 | if (typeof window !== "undefined" && window.Vue) { 36 | install(window.Vue); 37 | } 38 | 39 | export default { 40 | // 导出的对象必须具有 install,才能被 Vue.use() 方法安装 41 | install, 42 | // 以下是具体的组件列表 43 | TextTooltip, 44 | SearchInput, 45 | ListContainer, 46 | DeepexiCard, 47 | LoadingDialog, 48 | MarkdownView, 49 | LoadingButton 50 | }; 51 | -------------------------------------------------------------------------------- /src/mixins/emitter.js: -------------------------------------------------------------------------------- 1 | function broadcast(componentName, eventName, params) { 2 | this.$children.forEach(child => { 3 | const name = child.$options.name; 4 | 5 | if (name === componentName) { 6 | child.$emit.apply(child, [eventName].concat(params)); 7 | } else { 8 | broadcast.apply(child, [componentName, eventName].concat([params])); 9 | } 10 | }); 11 | } 12 | export default { 13 | methods: { 14 | dispatch(componentName, eventName, params) { 15 | let parent = this.$parent || this.$root; 16 | let name = parent.$options.name; 17 | 18 | while (parent && (!name || name !== componentName)) { 19 | parent = parent.$parent; 20 | 21 | if (parent) { 22 | name = parent.$options.name; 23 | } 24 | } 25 | if (parent) { 26 | parent.$emit.apply(parent, [eventName].concat(params)); 27 | } 28 | }, 29 | broadcast(componentName, eventName, params) { 30 | broadcast.call(this, componentName, eventName, params); 31 | } 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /src/theme-chalk/gulpfile.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const { series, src, dest } = require("gulp"); 4 | const less = require("gulp-less"); 5 | const autoprefixer = require("gulp-autoprefixer"); 6 | const cssmin = require("gulp-cssmin"); 7 | 8 | function compile() { 9 | return src("./src/*.less") 10 | .pipe( 11 | less({ 12 | plugins: [ 13 | autoprefixer({ 14 | browsers: ["ie > 9", "last 2 versions"], 15 | cascade: false 16 | }) 17 | ] 18 | }) 19 | ) 20 | .pipe(cssmin()) 21 | .pipe(dest("./lib")); 22 | } 23 | 24 | // function copyfont() { 25 | // return src("./src/fonts/**") 26 | // .pipe(cssmin()) 27 | // .pipe(dest("./lib/fonts")); 28 | // } 29 | 30 | exports.build = series(compile); 31 | -------------------------------------------------------------------------------- /src/theme-chalk/src/common/markdown-preview.less: -------------------------------------------------------------------------------- 1 | @margin: 8px 0; 2 | //主体颜色 3 | @primary: #292d35; 4 | @light-primary: #323741; 5 | @dark-primary: #1c1e24; 6 | // 7 | @info: #007acc; 8 | @success: #19be6b; 9 | @warning: #ff9900; 10 | @error: #ed3f14; 11 | // 12 | @title: #252525; 13 | @content: #555; 14 | @sub-color: #80848f; 15 | @disabled: #bbbec4; 16 | @border: #dddee1; 17 | @divider: #e9eaec; 18 | @background: #f7f7f7; 19 | @tip: #c1c1c1; 20 | @primary-rgba: rgba(49, 204, 102, 0.2); 21 | @mask: rgba(0, 0, 0, 0.3); 22 | @blue-rgba: rgba(0, 122, 204, 0.2); 23 | @dark-info: #0169af; 24 | @line-height: 1.8rem; 25 | 26 | 27 | pre { 28 | padding: 20px 20px 30px !important; 29 | display: block; 30 | color: #abb2bf; 31 | font-family: Menlo, Consolas, "Courier New", Courier, FreeMono, monospace; 32 | background: #292c34; 33 | border-radius: 4px; 34 | overflow-y: hidden !important; 35 | overflow-x: auto !important; 36 | margin: 20px 0 !important; 37 | 38 | * { 39 | line-height: 1.6 !important; 40 | font-size: 14px; 41 | font-family: Menlo, Consolas, "Courier New", Courier, FreeMono, 42 | monospace; 43 | } 44 | } 45 | 46 | .hljs-comment, 47 | .hljs-quote { 48 | color: #5c6370; 49 | font-style: italic; 50 | } 51 | 52 | .hljs-doctag, 53 | .hljs-formula, 54 | .hljs-keyword { 55 | color: #c678dd; 56 | } 57 | 58 | .hljs-deletion, 59 | .hljs-name, 60 | .hljs-section, 61 | .hljs-selector-tag, 62 | .hljs-subst { 63 | color: #e06c75; 64 | } 65 | 66 | .hljs-literal { 67 | color: #56b6c2; 68 | } 69 | 70 | .hljs-addition, 71 | .hljs-attribute, 72 | .hljs-meta-string, 73 | .hljs-regexp, 74 | .hljs-string { 75 | color: #98c379; 76 | } 77 | 78 | .hljs-built_in, 79 | .hljs-class .hljs-title { 80 | color: #e6c07b; 81 | } 82 | 83 | .hljs-attr, 84 | .hljs-number, 85 | .hljs-selector-attr, 86 | .hljs-selector-class, 87 | .hljs-selector-pseudo, 88 | .hljs-template-variable, 89 | .hljs-type, 90 | .hljs-variable { 91 | color: #d19a66; 92 | } 93 | 94 | .hljs-bullet, 95 | .hljs-link, 96 | .hljs-meta, 97 | .hljs-selector-id, 98 | .hljs-symbol, 99 | .hljs-title { 100 | color: #61aeee; 101 | } 102 | 103 | .hljs-emphasis { 104 | font-style: italic; 105 | } 106 | 107 | .hljs-strong { 108 | font-weight: bold; 109 | } 110 | 111 | .hljs-link { 112 | text-decoration: underline; 113 | } 114 | 115 | .markdown-preview { 116 | flex: 1; 117 | overflow: hidden; 118 | background: #fff; 119 | // padding: 20px 12px !important; 120 | font-family: "Open Sans", 121 | "Helvetica Neue", 122 | Helvetica, 123 | Arial, 124 | sans-serif; 125 | 126 | 127 | >div { 128 | padding: 10px 12px !important; 129 | background: #fff; 130 | 131 | &::-webkit-scrollbar { 132 | display: none; 133 | } 134 | } 135 | 136 | &::-webkit-scrollbar { 137 | display: none; 138 | } 139 | 140 | ul { 141 | list-style: none; 142 | padding: 0 20px; 143 | 144 | li { 145 | position: relative; 146 | 147 | &:after { 148 | display: block; 149 | content: ""; 150 | width: 8px; 151 | height: 8px; 152 | border-radius: 50%; 153 | position: absolute; 154 | z-index: 99; 155 | top: 7px; 156 | left: -20px; 157 | background: @content; 158 | } 159 | } 160 | } 161 | 162 | ol, 163 | ul { 164 | margin: 20px 0; 165 | padding: 0 40px; 166 | 167 | li { 168 | font-size: 14px !important; 169 | color: @content; 170 | margin-bottom: 10px; 171 | line-height: 24px; 172 | padding-left: 12px; 173 | 174 | input[type="checkbox"] { 175 | position: relative; 176 | cursor: pointer; 177 | overflow: visible; 178 | position: absolute; 179 | left: 0; 180 | top: 0; 181 | 182 | &:after { 183 | display: block; 184 | content: ""; 185 | width: 16px; 186 | height: 16px; 187 | position: absolute; 188 | z-index: 99999; 189 | background: #fff; 190 | top: 0; 191 | right: 0; 192 | } 193 | 194 | &:before { 195 | display: block; 196 | width: 18px; 197 | height: 18px; 198 | position: absolute; 199 | content: ""; 200 | top: 2px; 201 | left: -25px; 202 | z-index: 999999; 203 | background-position: center; 204 | background: url("data:image/jpeg;base64,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AAAATmd0dmJvb2wAAAAAAEVtbERib29sAAAAAABJbnRyYm9vbAAAAAAAQmNrZ09iamMAAAABAAAAAAAAUkdCQwAAAAMAAAAAUmQgIGRvdWJAb+AAAAAAAAAAAABHcm4gZG91YkBv4AAAAAAAAAAAAEJsICBkb3ViQG/gAAAAAAAAAAAAQnJkVFVudEYjUmx0AAAAAAAAAAAAAAAAQmxkIFVudEYjUmx0AAAAAAAAAAAAAAAAUnNsdFVudEYjUHhsQFIAAAAAAAAAAAAKdmVjdG9yRGF0YWJvb2wBAAAAAFBnUHNlbnVtAAAAAFBnUHMAAAAAUGdQQwAAAABMZWZ0VW50RiNSbHQAAAAAAAAAAAAAAABUb3AgVW50RiNSbHQAAAAAAAAAAAAAAABTY2wgVW50RiNQcmNAWQAAAAAAAAAAABBjcm9wV2hlblByaW50aW5nYm9vbAAAAAAOY3JvcFJlY3RCb3R0b21sb25nAAAAAAAAAAxjcm9wUmVjdExlZnRsb25nAAAAAAAAAA1jcm9wUmVjdFJpZ2h0bG9uZwAAAAAAAAALY3JvcFJlY3RUb3Bsb25nAAAAAAA4QklNA+0AAAAAABAASAAAAAEAAgBIAAAAAQACOEJJTQQmAAAAAAAOAAAAAAAAAAAAAD+AAAA4QklNBA0AAAAAAAQAAAAeOEJJTQQZAAAAAAAEAAAAHjhCSU0D8wAAAAAACQAAAAAAAAAAAQA4QklNJxAAAAAAAAoAAQAAAAAAAAACOEJJTQP1AAAAAABIAC9mZgABAGxmZgAGAAAAAAABAC9mZgABAKGZmgAGAAAAAAABADIAAAABAFoAAAAGAAAAAAABADUAAAABAC0AAAAGAAAAAAABOEJJTQP4AAAAAABwAAD/////////////////////////////A+gAAAAA/////////////////////////////wPoAAAAAP////////////////////////////8D6AAAAAD/////////////////////////////A+gAADhCSU0EAAAAAAAAAgAAOEJJTQQCAAAAAAACAAA4QklNBDAAAAAAAAEBADhCSU0ELQAAAAAABgABAAAAAjhCSU0ECAAAAAAAEAAAAAEAAAJAAAACQAAAAAA4QklNBB4AAAAAAAQAAAAAOEJJTQQaAAAAAANDAAAA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OjM4KzA4OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAxOC0wOS0xM1QxNjo1NjozOCswODowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAxOC0wOS0xM1QxNjo1NjozOCswODowMCIgZGM6Zm9ybWF0PSJpbWFnZS9qcGVnIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIiBwaG90b3Nob3A6SUNDUHJvZmlsZT0ic1JHQiBJRUM2MTk2Ni0yLjEiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6YmFlYmVlNTQtODI3My00MTJhLTk0NDgtZTdhYzU1MjFjMWZkIiB4bXBNTTpEb2N1bWVudElEPSJhZG9iZTpkb2NpZDpwaG90b3Nob3A6NjBlZDg0MmItNjZjMy1hNDRlLTgxNGItYWVjM2JiMjg1Mjg3IiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6MTQyYTk3NzMtZjA2NC00N2Q3LTllMDMtOWI5YzhhYzc0YWI5Ij4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDoxNDJhOTc3My1mMDY0LTQ3ZDctOWUwMy05YjljOGFjNzRhYjkiIHN0RXZ0OndoZW49IjIwMTgtMDktMDVUMTg6MjE6MzgrMDg6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAoTWFjaW50b3NoKSIvPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY29udmVydGVkIiBzdEV2dDpwYXJhbWV0ZXJzPSJmcm9tIGltYWdlL3BuZyB0byBpbWFnZS9qcGVnIi8+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDpiYWViZWU1NC04MjczLTQxMmEtOTQ0OC1lN2FjNTUyMWMxZmQiIHN0RXZ0OndoZW49IjIwMTgtMDktMTNUMTY6NTY6MzgrMDg6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAoTWFjaW50b3NoKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPD94cGFja2V0IGVuZD0idyI/Pv/iDFhJQ0NfUFJPRklMRQABAQAADEhMaW5vAhAAAG1udHJSR0IgWFlaIAfOAAIACQAGADEAAGFjc3BNU0ZUAAAAAElFQyBzUkdCAAAAAAAAAAAAAAAAAAD21gABAAAAANMtSFAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEWNwcnQAAAFQAAAAM2Rlc2MAAAGEAAAAbHd0cHQAAAHwAAAAFGJrcHQAAAIEAAAAFHJYWVoAAAIYAAAAFGdYWVoAAAIsAAAAFGJYWVoAAAJAAAAAFGRtbmQAAAJUAAAAcGRtZGQAAALEAAAAiHZ1ZWQAAANMAAAAhnZpZXcAAAPUAAAAJGx1bWkAAAP4AAAAFG1lYXMAAAQMAAAAJHRlY2gAAAQwAAAADHJUUkMAAAQ8AAAIDGdUUkMAAAQ8AAAIDGJUUkMAAAQ8AAAIDHRleHQAAAAAQ29weXJpZ2h0IChjKSAxOTk4IEhld2xldHQtUGFja2FyZCBDb21wYW55AABkZXNjAAAAAAAAABJzUkdCIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAAEnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYWVogAAAAAAAA81EAAQAAAAEWzFhZWiAAAAAAAAAAAAAAAAAAAAAAWFla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") no-repeat; 205 | background-size: contain; 206 | } 207 | } 208 | 209 | input[type="checkbox"]:checked { 210 | &:before { 211 | background: url("data:image/jpeg;base64,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WQAAAAAAAAAAABBjcm9wV2hlblByaW50aW5nYm9vbAAAAAAOY3JvcFJlY3RCb3R0b21sb25nAAAAAAAAAAxjcm9wUmVjdExlZnRsb25nAAAAAAAAAA1jcm9wUmVjdFJpZ2h0bG9uZwAAAAAAAAALY3JvcFJlY3RUb3Bsb25nAAAAAAA4QklNA+0AAAAAABAASAAAAAEAAgBIAAAAAQACOEJJTQQmAAAAAAAOAAAAAAAAAAAAAD+AAAA4QklNBA0AAAAAAAQAAAAeOEJJTQQZAAAAAAAEAAAAHjhCSU0D8wAAAAAACQAAAAAAAAAAAQA4QklNJxAAAAAAAAoAAQAAAAAAAAACOEJJTQP1AAAAAABIAC9mZgABAGxmZgAGAAAAAAABAC9mZgABAKGZmgAGAAAAAAABADIAAAABAFoAAAAGAAAAAAABADUAAAABAC0AAAAGAAAAAAABOEJJTQP4AAAAAABwAAD/////////////////////////////A+gAAAAA/////////////////////////////wPoAAAAAP////////////////////////////8D6AAAAAD/////////////////////////////A+gAADhCSU0EAAAAAAAAAgAAOEJJTQQCAAAAAAACAAA4QklNBDAAAAAAAAEBADhCSU0ELQAAAAAABgABAAAAAjhCSU0ECAAAAAAAEAAAAAEAAAJAAAACQAAAAAA4QklNBB4AAAAAAAQAAAAAOEJJTQQaAAAAAANDAAAABgAAAAAAAAAAAAAAgAAAAIAAAAAHAGMAaABlAGMAawBlAGQAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAIAAAACAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAEAAAAAAABudWxsAAAAAgAAAAZib3VuZHNPYmpjAAAAAQAAAAAAAFJjdDEAAAAEAAAAAFRvcCBsb25nAAAAAAAAAABMZWZ0bG9uZwAAAAAAAAAAQnRvbWxvbmcAAACAAAAAAFJnaHRsb25nAAAAgAAAAAZzbGljZXNWbExzAAAAAU9iamMAAAABAAAAAAAFc2xpY2UAAAASAAAAB3NsaWNlSURsb25nAAAAAAAAAAdncm91cElEbG9uZwAAAAAAAAAGb3Jp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dHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgKE1hY2ludG9zaCkiIHhtcDpDcmVhdGVEYXRlPSIyMDE4LTA5LTA1VDE4OjIxOjM4KzA4OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAxOC0wOS0xM1QxNjo1NTo0OSswODowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAxOC0wOS0xM1QxNjo1NTo0OSswODowMCIgZGM6Zm9ybWF0PSJpbWFnZS9qcGVnIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIiBwaG90b3Nob3A6SUNDUHJvZmlsZT0ic1JHQiBJRUM2MTk2Ni0yLjEiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MTMwY2QwMDgtODA3Zi00NDk4LTlkYjctMjZjYWI2ZWI1ODM3IiB4bXBNTTpEb2N1bWVudElEPSJhZG9iZTpkb2NpZDpwaG90b3Nob3A6MWNkYzYwM2UtNmVhNy0wYjQ0LThhMTEtZDk4YTFlODhkMTVlIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6M2EwNjc1YjItZTY3MC00NWU0LThhZmUtN2UzYzU1ZTRjNTEyIj4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDozYTA2NzViMi1lNjcwLTQ1ZTQtOGFmZS03ZTNjNTVlNGM1MTIiIHN0RXZ0OndoZW49IjIwMTgtMDktMDVUMTg6MjE6MzgrMDg6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAoTWFjaW50b3NoKSIvPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY29udmVydGVkIiBzdEV2dDpwYXJhbWV0ZXJzPSJmcm9tIGltYWdlL3BuZyB0byBpbWFnZS9qcGVnIi8+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDoxMzBjZDAwOC04MDdmLTQ0OTgtOWRiNy0yNmNhYjZlYjU4MzciIHN0RXZ0OndoZW49IjIwMTgtMDktMTNUMTY6NTU6NDkrMDg6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAoTWFjaW50b3NoKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPD94cGFja2V0IGVuZD0idyI/Pv/iDFhJQ0NfUFJPRklMRQABAQAADEhMaW5vAhAAAG1udHJSR0IgWFlaIAfOAAIACQAGADEAAGFjc3BNU0ZUAAAAAElFQyBzUkdCAAAAAAAAAAAAAAAAAAD21gABAAAAANMtSFAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEWNwcnQAAAFQAAAAM2Rlc2MAAAGEAAAAbHd0cHQAAAHwAAAAFGJrcHQAAAIEAAAAFHJYWVoAAAIYAAAAFGdYWVoAAAIsAAAAFGJYWVoAAAJAAAAAFGRtbmQAAAJUAAAAcGRtZGQAAALEAAAAiHZ1ZWQAAANMAAAAhnZpZXcAAAPUAAAAJGx1bWkAAAP4AAAAFG1lYXMAAAQMAAAAJHRlY2gAAAQwAAAADHJUUkMAAAQ8AAAIDGdUUkMAAAQ8AAAIDGJUUkMAAAQ8AAAIDHRleHQAAAAAQ29weXJpZ2h0IChjKSAxOTk4IEhld2xldHQtUGFja2FyZCBDb21wYW55AABkZXNjAAAAAAAAABJzUkdCIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAAEnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYWVogAAAAAAAA81EAAQAAAAEWzFhZWiAAAAAAAAAAAAAAAAAAAAAAWFlaIAAAAAAAAG+iAAA49QAAA5BYWVogAAAAAAAAYpkAALeFAAAY2lhZWiAAAAAAAAAkoAAAD4QAALbPZGVzYwAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAAAAAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGRlc2MAAAAAAAAALklFQyA2MTk2Ni0yLjEgRGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAALklFQyA2MTk2Ni0yLjEgRGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAAAAAAAAAAAAAAAABkZXNjAAAAAAAAACxSZWZlcmVuY2UgVmlld2luZyBDb25kaXRpb24gaW4gSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAsUmVmZXJlbmNlIFZpZXdpbmcgQ29uZGl0aW9uIGluIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdmlldwAAAAAAE6T+ABRfLgAQzxQAA+3MAAQTCwADXJ4AAAABWFlaIAAAAAAATAlWAFAAAABXH+dtZWFzAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAACjwAAAAJzaWcgAAAAAENSVCBjdXJ2AAAAAAAABAAAAAAFAAoADwAUABkAHgAjACgALQAyADcAOwBAAEUASgBPAFQAWQBeAGMAaABtAHIAdwB8AIEAhgCLAJAAlQCaAJ8ApACpAK4AsgC3ALwAwQDGAMsA0ADVANsA4ADlAOsA8AD2APsBAQEHAQ0BEwEZAR8BJQErATIBOAE+AUUBTAFSAVkBYAFnAW4BdQF8AYMBiwGSAZoBoQGpAbEBuQHBAckB0QHZAeEB6QHyAfoCAwIMAhQCHQImAi8COAJBAksCVAJdAmcCcQJ6AoQCjgKYAqICrAK2AsECywLVAuAC6wL1AwADCwMWAyEDLQM4A0MDTwNaA2YDcgN+A4oDlgOiA64DugPHA9MD4APsA/kEBgQTBCAELQQ7BEgEVQRjBHEEfgSMBJoEqAS2BMQE0wThBPAE/gUNBRwFKwU6BUkFWAVnBXcFhgWWBaYFtQXFBdUF5QX2BgYGFgYnBjcGSAZZBmoGewaMBp0GrwbABtEG4wb1BwcHGQcrBz0HTwdhB3QHhgeZB6wHvwfSB+UH+AgLCB8IMghGCFoIbgiCCJYIqgi+CNII5wj7CRAJJQk6CU8JZAl5CY8JpAm6Cc8J5Qn7ChEKJwo9ClQKagqBCpgKrgrFCtwK8wsLCyILOQtRC2kLgAuYC7ALyAvhC/kMEgwqDEMMXAx1DI4MpwzADNkM8w0NDSYNQA1aDXQNjg2pDcMN3g34DhMOLg5JDmQOfw6bDrYO0g7uDwkPJQ9BD14Peg+WD7MPzw/sEAkQJhBDEGEQfhCbELkQ1xD1ERMRMRFPEW0RjBGqEckR6BIHEiYSRRJkEoQSoxLDEuMTAxMjE0MTYxODE6QTxRPlFAYUJxRJFGoUixStFM4U8BUSFTQVVhV4FZsVvRXgFgMWJhZJFmwWjxayFtYW+hcdF0EXZReJF64X0hf3GBsYQBhlGIoYrxjVGPoZIBlFGWsZkRm3Gd0aBBoqGlEadxqeGsUa7BsUGzsbYxuKG7Ib2hwCHCocUhx7HKMczBz1HR4dRx1wHZkdwx3sHhYeQB5qHpQevh7pHxMfPh9pH5Qfvx/qIBUgQSBsIJggxCDwIRwhSCF1IaEhziH7IiciVSKCIq8i3SMKIzgjZiOUI8Ij8CQfJE0kfCSrJNolCSU4JWgllyXHJfcmJyZXJocmtyboJxgnSSd6J6sn3CgNKD8ocSiiKNQpBik4KWspnSnQKgIqNSpoKpsqzysCKzYraSudK9EsBSw5LG4soizXLQwtQS12Last4S4WLkwugi63Lu4vJC9aL5Evxy/+MDUwbDCkMNsxEjFKMYIxujHyMioyYzKbMtQzDTNGM38zuDPxNCs0ZTSeNNg1EzVNNYc1wjX9Njc2cjauNuk3JDdgN5w31zgUOFA4jDjIOQU5Qjl/Obw5+To2OnQ6sjrvOy07azuqO+g8JzxlPKQ84z0iPWE9oT3gPiA+YD6gPuA/IT9hP6I/4kAjQGRApkDnQSlBakGsQe5CMEJyQrVC90M6Q31DwEQDREdEikTORRJFVUWaRd5GIkZnRqtG8Ec1R3tHwEgFSEtIkUjXSR1JY0mpSfBKN0p9SsRLDEtTS5pL4kwqTHJMuk0CTUpNk03cTiVObk63TwBPSU+TT91QJ1BxULtRBlFQUZtR5lIxUnxSx1MTU19TqlP2VEJUj1TbVShVdVXCVg9WXFapVvdXRFeSV+BYL1h9WMtZGllpWbhaB1pWWqZa9VtFW5Vb5Vw1XIZc1l0nXXhdyV4aXmxevV8PX2Ffs2AFYFdgqmD8YU9homH1YklinGLwY0Njl2PrZEBklGTpZT1lkmXnZj1mkmboZz1nk2fpaD9olmjsaUNpmmnxakhqn2r3a09rp2v/bFdsr20IbWBtuW4SbmtuxG8eb3hv0XArcIZw4HE6cZVx8HJLcqZzAXNdc7h0FHRwdMx1KHWFdeF2Pnabdvh3VnezeBF4bnjMeSp5iXnnekZ6pXsEe2N7wnwhfIF84X1BfaF+AX5ifsJ/I3+Ef+WAR4CogQqBa4HNgjCCkoL0g1eDuoQdhICE44VHhauGDoZyhteHO4efiASIaYjOiTOJmYn+imSKyoswi5aL/IxjjMqNMY2Yjf+OZo7OjzaPnpAGkG6Q1pE/kaiSEZJ6kuOTTZO2lCCUipT0lV+VyZY0lp+XCpd1l+CYTJi4mSSZkJn8mmia1ZtCm6+cHJyJnPedZJ3SnkCerp8dn4uf+qBpoNihR6G2oiailqMGo3aj5qRWpMelOKWpphqmi6b9p26n4KhSqMSpN6mpqhyqj6sCq3Wr6axcrNCtRK24ri2uoa8Wr4uwALB1sOqxYLHWskuywrM4s660JbSctRO1irYBtnm28Ldot+C4WbjRuUq5wro7urW7LrunvCG8m70VvY++Cr6Evv+/er/1wHDA7MFnwePCX8Lbw1jD1MRRxM7FS8XIxkbGw8dBx7/IPci8yTrJuco4yrfLNsu2zDXMtc01zbXONs62zzfPuNA50LrRPNG+0j/SwdNE08bUSdTL1U7V0dZV1tjXXNfg2GTY6Nls2fHadtr724DcBdyK3RDdlt4c3qLfKd+v4DbgveFE4cziU+Lb42Pj6+Rz5PzlhOYN5pbnH+ep6DLovOlG6dDqW+rl63Dr++yG7RHtnO4o7rTvQO/M8Fjw5fFy8f/yjPMZ86f0NPTC9VD13vZt9vv3ivgZ+Kj5OPnH+lf65/t3/Af8mP0p/br+S/7c/23////uACFBZG9iZQBkQAAAAAEDABADAgMGAAAAAAAAAAAAAAAA/9sAhAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAgICAgICAgICAgIDAwMDAwMDAwMDAQEBAQEBAQEBAQECAgECAgMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwP/wgARCACAAIADAREAAhEBAxEB/8QAqwABAQEBAAICAwAAAAAAAAAAAAkICgYHAgQBAwUBAQAAAAAAAAAAAAAAAAAAAAAQAAAFAgUEAwEBAAAAAAAAAAAGBwgJBTgBAgQ1GBADFxkgMIBAFREAAQQBAgIECQkGAwkAAAAAAgEDBAUGAAcREhAhEzcxk7MUtNSWdwgwInSU1Xa21jggQVEjJCVAFTVxgaFCQ6UWNhcSAQAAAAAAAAAAAAAAAAAAAID/2gAMAwEBAhEDEQAAAO/gAAAAAAAA8RIlHr8AAAAHyN5FLwRpPCCkAAAAABAI6Sj3ARANQlHgAAAADm8LUGmyIBqEo8AAAD4GETZxzvlqDTZEA1CUeAAAPic+5HE6BjJxag02RANQlHgAAfggORgNNnVcQLLUGmyIBqE3Ic7BW83kAQXInmmzqsPaJzeFqDTZEA1CaiOP0/cdQJvchWQ7NNnVYe0Qc3hag02RANQlHidxzIH2Sm5Kc02dVh7RAObwtQabIgGoSjwJ1HMkfyTTh1VntEAHN4WoNNkQDUJR4AnKSkOiU9oAAHN4WoNNkQDUJR4AAAAA5vC1BpsiEaRKWAAAAAHMWXbNMmJzmePMAAAAAfoPsnXKeRA/inj4AAAAB5kfYP/aAAgBAgABBQD8Af/aAAgBAwABBQD8Af/aAAgBAQABBQD+E+nwppiUFAmOr+NZ9xK5D3ErkPcSuQ9xK5D3ErkPcSuQ9xK5D3ErkPcSuQ9xK5DJMSt+GdqMkxBcCYukxxuq9OT2NtmyJKYkPBtpI4NtJHBtpI4NtJHBtpI4NtJHBtpI4NtJHBtpI4NtJGLG2k44P7RErNpcY3491FTkPEzu3RWWk/XL9cwzC1MTO7dFZaT9Hc7nb7PbMclLRS2ZyibywfS3L9cwzC1MTO7dFZaT882bLkyyDv8A8x67ghwqZk1CbS/XMMwtTEzu3RWWk/LHHDDCQmQDE2Zg1trZ9dGfUeSAioWQZfrmGYWpiZ3borLSVNUIvpOn5vlec7WTQyx8BYdHROshUgH+3iGttbProz6jqOkJCSEJfrmGYWpiZ3borLSXRpXUlrb+Yi7XSjXSoazGRjGyR7Rbc8WxIZIBjqMQ1trZ9dGfUdR0hISQukv1zDMLUxM7t0VlpIfMxuiOToRgL9bKlbKZsMhFMi0ykKEpaIhrbWz66M+o6jpCQkhdZfrmGYWpiZ3borLSej6GM0VyNEr1BrRXrQa01o+OjPiOo6QkJIfwl+uYZhamJnduistJ6vlYhSnLaFPYtHSmU3I8jxDQoh/GX65hmFqYmd26Ky0n65frmGYWpiZ3LmxpkUdT0Gsan9cqR8LJ2dIzPLmyNUD8Gya1zSM0o1rk3YzcwHSjmA6UcwHSjmA6UcwHSjmA6UcwHSjmA6UcwHSjmA6Ual3DoNXp25tnU9zp6KJXo5HKnSsFsumHJ4vTMeL0zHi9Mx4vTMeL0zHi9Mx4vTMeL0zHi9Mx4vTMYJemmA0mk0mg04//2gAIAQICBj8AAH//2gAIAQMCBj8AAH//2gAIAQEBBj8A/wADfZ5nN1Fx/FcagnYW9pLU1BlkSFppplloXH5c2ZIcBmOw0JvPvuC22JGSIstja3aKlbx9h824VlnlrPlWtiwK/Mkv1FA7Ai1JuJ/0UmTOHh7RfAndjtR4vL/zNrux2o8Xl/5m13Y7UeLy/wDM2u7HajxeX/mbXdjtR4vL/wAza7sdqPF5f+Ztd2O1Hi8v/M2u7HajxeX/AJm13Y7UeLy/8za7sdqPF5f+ZtCrm1+1RtoSc4gOXNmQ8etBMsicECVPAqiXD+GoW3maUCbZbhWh9hj4FaJaYvlUtB4pX11k9Ggyau6kcF7GJIAwfVEBt83iFpejZvCoklxmoyrKcovLdlsyBJb2I11NHrGX+VU7WO2eUOuchcRVwALhzAKpN3b3SxdjO7m3ye5o6estZM4KSkqqYIkc3ErokmM1Os501x0idf7UW2hbRoQLtCPuIwb6rO9e13EYN9Vneva7iMG+qzvXtdxGDfVZ3r2u4jBvqs717XcRg31Wd69ruIwb6rO9e13EYN9Vneva7iMG+qzvXtdxGDfVZ3r2lT/4Rg3X1dUaci/7lSciouotRtc5Po6S5xeh3GooTU6UcjFJ8q8vq0odVYuOLYCzEsMbWRGI3DdZRxB515EXW0+4FwIjc5ZgOM3FyrYC205cSauP/mrzLYfNajv2AuG2P/KBIn7uj4d/pu6fkNvtUv34zb09j5TDfchjH453I1sH7tMc9F6Ph3+m7p+Q2+1S/fjNvT2PkTddMGmmgJxxxwhBttsBUjMzJUEAAUVVVV4ImncYf3CnWpRpXmc29x/GL24xuI8LpNPKNpFhqtnHY4cyvQW5TRiv8sjXiiVGX4Ze12SYzexRm1N1VSAkwpjCkTZKBj85t5l4CbdaNBdZdAgMRMSFMN9yGMfjncjWwfu0xz0Xo+Hf6bun5Db7VL9+M29PY+QIzIQABUiIlQRERTiRES8EERROKqvg1c7F7IXKjhDRvVue5zWvqi5m4Cq3KxzHpbRIqYk2SKEqSC/3RUVsF8z5il63iqppyDxOszLHpGP9oRkw1dWVPM/8mYjc3EQ4RYVY4Yj1cznMqcS4rhvuQxj8c7ka2D92mOei9Hw7/Td0/Ibfapfvxm3p7H7aqqoiInFVXqRETwqq/uRNXew+xt1wxUVkVe4ee1b/AF5QYkTMzFsamMl/60KooTZja/3HraaXzTnKVpvGcZbOrxmrONJzbNpMY3avGat0y5REeZsbC9sBbMYUITE3jEiIm2W3XW6XbjbyqSsoKdsjN10hesrmzfEPP7y7mCDazrexcbRXHOUQERFtsW2m22ww33IYx+OdyNbB+7THPRej4d/pu6fkNvtUv34zb09jWX7kZSbwUGG0c68sAigDkuSERvixAhNuG00c6xlEEdgTMAV1wUIhTiqP2uKnh2G42EtSr8VbxyHeAsEH1Nhm3ubZHbKbMcY4A+7GKEBrxVttrqRHaK9ZrcU3go4xP3WLRnnQrr2vbURLIcS88eflOwBIkSTFNx1+EapzEbZA4XTd7CbF3f8AZEV+r3F3AqpP+tKnMzNxLF5rBf6Mi8W581sv6xeZhpfN+0KRpvGcZbOrxmrONJzbNpMY3avGat0y5REeZsbC9sBbMYUITE3jEiIm2W3XW6jbvbuoCroqsO0ffc5HbS7tHQbGde3s4W2ysLewJtFccVBAAEWmhbZbbbDWG+5DGPxzuRrYP3aY56L0fDv9N3T8ht9ql+/Gbensa3R2xpXmmbvJsd4UavuoxHeu6ewhX9PDkyCVBjxp9lVNMOOLxRsHFJUVE4atsYyepnUWQUU+RWXFRZRzizq+fFcVt+NJYcRCAwJPD1oScFRVRUXVNl2I3M7H8lx+czZU1zWvKxMgzGFXlcbLgomBiqg42aE262RAYkBEKhj2QnBx/eXHoAHkOPgSMRMkiMIDTmU4u24Sk5DcNU87iopOQXS4LzNE24WrzYLYy6VI6LJqNyc/q30/qeomJ2H4vNZLqjp85qxmtrxcXjHaXk7Qj03jOMtnV4zVnGk5tm0mMbtXjNW6ZcoiPM2Nhe2AtmMKEJibxiRETbLbrrdRt3t3UBV0VWHaPvucjtpd2joNjOvb2cLbZWFvYE2iuOKggACLTQtsttth0Yb7kMY/HO5Gtg/dpjnovR8O/wBN3T8ht9ql+/GbensdD2a4UxBpN66KDywJxK3Eg5xAiN/ysdyF7gINzW2x5IE4+tleDTq9gqEza41ktVOo7+jnSKy3qLOO5En10+I4rUiLKjuoJtutmPDr6lTrTiiouqbL8QuZ2PZNj05myprmteVmZBmMqvKYFwIHG3AJQcbNCaeaIgMSAiFaXb3GqZ3B86uoD1bujmdZJFpmXEBPN1YwkGnCmVCZCzxOYbio5EFSYYI0Lth03jOMtnV4zVnGk5tm0mMbtXjNW6ZcoiPM2Nhe2AtmMKEJibxiRETbLbrrdRt3t3UBV0VWHaPvucjtpd2joNjOvb2cLbZWFvYE2iuOKggACLTQtsttth04b7kMY/HO5Gtg/dpjnovR8O/03dPyG32qX78Zt6ex0v5zg7EKl3rooHLDlF2cSBndfEbVWcev3l5G2rFoB5IE81/ldTLy9hymxaY5kdXOpL6knSay3qLOM7En10+I6TMmJLjPCLjLzLgqioqf8OhvGsabOqxeqONJzbNpMY3azGax0y5QAeZsbC9sBbMYUITEniFTNW2W3XQqNu9uqcKqiqxVx55xQetLu0dBsZt7ezhbbKwt55NorjioIAAi00LbLbbYfsYb7kMY/HO5Gtg/dpjnovR8O/03dPyG32qX78Zt6ex+w1nGBOVOM7y07ARymTRKNT51UsggNVOQyIzLz0a2rwFPMJ/I5wDjGfFWladi19TnGOVG3OKrJbK3yydlWJ5B2UAHQSSlVTYzeW1jNszY5lYbfCKwRoiOPNp16p9u9u6cKqhqgVx11xQds7qzdBsZ17ezhbbKwt7Am0VxxUEQERbbFtlttsP2cN9yGMfjncjWwfu0xz0Xo+Hf6bun5Db7VL9+M29PY+Uw33IYx+OdyNbB+7THPRej4eDQV5Bn7oCRcPmoRx8AURVfAikgLw/2LqPBiy2HplRuBl8ayjNuCT0J6SUCwjg+2i87fbw5QGKqnAkXq8C/KLDxuelgeA4DRYHkbrY/07GTQL7Kr2wgMPIRDIWvj5Cwy8qcOzlA60qcza62CQhUVXbLGiRFTgvKcMTAuv8AcQEip/FF6FpsZWMG4OGWS5RhaSnW4zFo+kV2Ja409LeVGYgXcM0Vpw1FsZbDHaGDXOSX1LTX+4u0GU8W4OR1MKfd4nPfSKTqxm7WCDkXzxtlXTJg3BMUQ1JteBcV/UBuv7aXXrWv1Abr+2l161r9QG6/tpdeta/UBuv7aXXrWv1Abr+2l161r9QG6/tpdeta/UBuv7aXXrWv1Abr+2l161r9QG6/tpdeta/UBuv7aXXrWn4r+/27JMSWnGHhHN75oiadFQMUcZmA6HMKqnESRU/jqJR4rWWA0f8AmDTmZZ9NjPuUeNwHXkcmy5k91Qan3TzREseEDiyJTnX81tHHQxrDMfYKNRYlQVGN00cyQzZq6SBHrYIOGggjjoxow8xcE5i4r+/pbbv6GlvG2VVWW7irg2YNKXBVVsZrD4gqqiceHDwa7u8F9kaD7P13d4L7I0H2fru7wX2RoPs/Xd3gvsjQfZ+u7vBfZGg+z9d3eC+yNB9n67u8F9kaD7P13d4L7I0H2fru7wX2RoPs/Xd3gvsjQfZ+uKbd4Kip1oqYlQdX/b9NRIMWPDiMDyMRYjLceOyHFV5WmWRBtseK+BEROj//2Q==") no-repeat; 212 | background-size: contain; 213 | } 214 | } 215 | } 216 | } 217 | 218 | ol { 219 | list-style-type: decimal; 220 | } 221 | 222 | hr { 223 | color: @border; 224 | height: 1px; 225 | border: 0; 226 | border-top: 1px solid @border; 227 | margin: 20px 0; 228 | padding: 0; 229 | } 230 | 231 | del, 232 | em, 233 | strong { 234 | display: inline-block; 235 | margin: @margin; 236 | } 237 | 238 | blockquote { 239 | position: relative; 240 | background: @background; 241 | padding: 6px 12px; 242 | border-left: 5px solid @divider; 243 | border-radius: 2px; 244 | margin: @margin; 245 | } 246 | 247 | /*基本样式*/ 248 | 249 | h1, 250 | h2, 251 | h3, 252 | h4, 253 | h5, 254 | h6 { 255 | color: @title; 256 | } 257 | 258 | h1 { 259 | font-size: 28px; 260 | border-bottom: 1px solid @border; 261 | //text-align: center; 262 | } 263 | 264 | h2 { 265 | font-size: 24px; 266 | } 267 | 268 | h3 { 269 | font-size: 18px; 270 | } 271 | 272 | h4 { 273 | font-size: 16px; 274 | } 275 | 276 | h5 { 277 | font-size: 14px; 278 | } 279 | 280 | h6 { 281 | font-size: 12px; 282 | } 283 | 284 | h1, 285 | h2, 286 | h3, 287 | h4, 288 | h5, 289 | h6 { 290 | /* border-bottom: 1px solid @border; */ 291 | padding: 20px 0; 292 | font-weight: 600; 293 | } 294 | 295 | p { 296 | font-size: 14px !important; 297 | color: @content; 298 | margin: @margin; 299 | line-height: @line-height; 300 | } 301 | 302 | img { 303 | display: block; 304 | width: 90%; 305 | cursor: pointer; 306 | } 307 | 308 | table { 309 | width: 100%; 310 | border: 1px solid @border; 311 | border-bottom: 0; 312 | background: #fff; 313 | border-spacing: 0; 314 | border-collapse: collapse; 315 | margin: 20px 0; 316 | 317 | tr { 318 | -webkit-transition: background 0.1s; 319 | transition: background 0.1s; 320 | text-align: nav; 321 | } 322 | 323 | tr td, 324 | tr th { 325 | padding: 0 8px; 326 | font-size: 14px; 327 | line-height: 39px; 328 | color: #333; 329 | border-bottom: 1px solid @border; 330 | cursor: pointer; 331 | } 332 | 333 | th { 334 | background: #f8f8f9; 335 | text-align: left; 336 | font-weight: bold; 337 | } 338 | 339 | tr:nth-of-type(even) { 340 | td { 341 | background: #f8f8f9; 342 | } 343 | } 344 | 345 | tr { 346 | &:hover { 347 | td { 348 | background: #eaf5f6; 349 | } 350 | } 351 | } 352 | 353 | td, 354 | th { 355 | border: 1px solid @border; 356 | } 357 | } 358 | 359 | input[type="checkbox"] { 360 | display: inline-block; 361 | border-radius: 0; 362 | margin-right: 8px; 363 | } 364 | 365 | a { 366 | text-decoration: none; 367 | color: @info; 368 | font-size: 14px; 369 | line-height: @line-height; 370 | } 371 | } 372 | -------------------------------------------------------------------------------- /src/theme-chalk/src/common/var.less: -------------------------------------------------------------------------------- 1 | /* 2 | 支持自动引入less变量表,使用时无需手动引入 3 | */ 4 | 5 | @primary-color: #5D81F9; 6 | // base color 7 | /// color|1|BrandColor|0 8 | @--color-primary: #5D81F9; // 9 | /// color|1|SecondaryColor|1 10 | @--color-success: #02C5E2; 11 | /// color|1|SecondaryColor|1 12 | @--color-warning: #F5A623; 13 | /// color|1|SecondaryColor|1 14 | @--color-danger: #E24156; 15 | /// color|1|SecondaryColor|1 16 | @--color-info: #6A6E7B; 17 | 18 | /// color|1|FontColor|2 19 | @--color-text-primary: #2D303B; 20 | /// color|1|FontColor|2 21 | @--color-text-regular: #2D303B; 22 | /// color|1|FontColor|2 23 | @--color-text-secondary: #93959b; 24 | /// color|1|FontColor|2 25 | @--color-text-placeholder: #9CA6C7; 26 | /// color|1|BorderColor|3 27 | @--border-color-base: #CAD1E8; 28 | /// color|1|BorderColor|3 29 | @--border-color-light: #CAD1E8; 30 | /// color|1|BorderColor|3 31 | @--border-color-lighter: #EBEEF5; 32 | /// color|1|BorderColor|3 33 | @--border-color-extra-light: #F2F6FC; 34 | 35 | @--font-color-disabled-base: #bbb; 36 | 37 | // Background 38 | /// color|1|BackgroundColor|4 39 | @--background-color-base: #f5f7fa; 40 | 41 | //sidebar 42 | @menuText: rgba(255, 255, 255, 1); 43 | @menuFontColor: rgba(255, 255, 255, 0.7); 44 | @menuActiveText: #fff; 45 | @subMenuActiveText:#f4f4f5; //https://github.com/ElemeFE/element/issues/12951 46 | 47 | @menuBg: rgba(51, 54, 67, 1); 48 | 49 | @subMenuBg:#1f2d3d; 50 | @subMenuHover:#001528; 51 | 52 | @sideBarMaxWidth: 200px; // 侧边栏的最大宽度 53 | @sideBarMinWidth: 64px; // 侧边栏的最小宽度 54 | 55 | @padding-size: 24px; 56 | @margin-size: 16px; 57 | 58 | @cyan: #02C5E2; 59 | @black: #2D303B; 60 | @white: #fff; 61 | @gray: #9CA6C7; 62 | @error: #E24156; 63 | 64 | @font-l: 16px; 65 | @font-m: 14px; 66 | @font-s: 12px; 67 | 68 | @border-color: #CAD1E8; 69 | @bg-color: #F0F2F5; 70 | @bg-code: #f6f8fa; 71 | 72 | @basic-font-family: PingFangSC-Regular; 73 | @font-weight: 400; 74 | .setFontHidden { 75 | // 字体超出显示省略号 76 | white-space: nowrap; 77 | overflow: hidden; 78 | text-overflow: ellipsis; 79 | } 80 | -------------------------------------------------------------------------------- /src/theme-chalk/src/deepexi-card.less: -------------------------------------------------------------------------------- 1 | @import './common/var'; 2 | 3 | .deepexi-card { 4 | background: #fff; 5 | border-radius: 4px; 6 | & + .deepexi-card { 7 | margin-top: @margin-size; 8 | } 9 | &-title { 10 | height: 48px; 11 | line-height: 48px; 12 | border-bottom: 1px solid #e4e8f3; 13 | padding: 0 @padding-size; 14 | font-size: 14px; 15 | font-weight: 500; 16 | color: rgba(106, 108, 115, 1); 17 | } 18 | &-content { 19 | padding: @padding-size; 20 | } 21 | } -------------------------------------------------------------------------------- /src/theme-chalk/src/index.less: -------------------------------------------------------------------------------- 1 | @import "./common/var.less"; 2 | @import "./text-tooltip.less"; 3 | @import "./search-input.less"; 4 | @import "./list-container.less"; 5 | @import "./deepexi-card.less"; 6 | @import "./loading-dialog.less"; 7 | @import "./markdown-view.less"; 8 | @import "./loading-button.less"; 9 | -------------------------------------------------------------------------------- /src/theme-chalk/src/list-container.less: -------------------------------------------------------------------------------- 1 | @import './common/var'; 2 | 3 | .list-container { 4 | @lineHeight: 60px; 5 | 6 | &-header { 7 | position: relative; 8 | display: flex; 9 | border-bottom: 1px solid #eee; 10 | background: #fff; 11 | overflow-x: auto; 12 | 13 | .tab-active-bar { 14 | position: absolute; 15 | bottom: 0; 16 | left: 0; 17 | z-index: 1; 18 | width: 80px; 19 | height: 2px; 20 | background: @primary-color; 21 | 22 | &.animation { 23 | transition: 0.3s cubic-bezier(0.645, 0.045, 0.355, 1); // element.ui tabbar 的动画 24 | } 25 | } 26 | 27 | .tab-like-box { 28 | list-style: none; 29 | padding: 0; 30 | font-weight: 400; 31 | display: inherit; 32 | width: auto; 33 | white-space: nowrap; 34 | 35 | .tab { 36 | padding: 0 16px; 37 | line-height: @lineHeight; 38 | display: inline-block; 39 | cursor: pointer; 40 | color: #000; 41 | 42 | &.is-active { 43 | color: @primary-color; 44 | } 45 | } 46 | } 47 | 48 | .right-part { 49 | line-height: @lineHeight; 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /src/theme-chalk/src/loading-button.less: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjfff/deep-ui/5efa3ef655d6d26bc298acc40d07da715d21c909/src/theme-chalk/src/loading-button.less -------------------------------------------------------------------------------- /src/theme-chalk/src/loading-dialog.less: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjfff/deep-ui/5efa3ef655d6d26bc298acc40d07da715d21c909/src/theme-chalk/src/loading-dialog.less -------------------------------------------------------------------------------- /src/theme-chalk/src/markdown-view.less: -------------------------------------------------------------------------------- 1 | @import './common/var'; 2 | @import "./common/markdown-preview.less"; 3 | 4 | .mardkdown-view { 5 | position: relative; 6 | background: #fff; 7 | display: flex; 8 | 9 | .left-content { 10 | width: 100%; 11 | min-width: 300px; 12 | margin-right: 80px; 13 | 14 | .markdown-preview { 15 | h1 { 16 | border-bottom: none; 17 | } 18 | } 19 | } 20 | 21 | .right-content { 22 | width: 230px; 23 | } 24 | 25 | .deepexi-scrollbar-wrap { 26 | position: relative; 27 | transform: translateX(-20px); 28 | 29 | &.fixed { 30 | top: 0; 31 | right: 0; 32 | position: fixed; 33 | } 34 | } 35 | 36 | .deepexi-scrollbar { 37 | overflow-y: auto; 38 | width: 200px; 39 | 40 | &::-webkit-scrollbar { 41 | width: 4px; 42 | height: 20px; 43 | } 44 | 45 | &::-webkit-scrollbar-track { 46 | box-shadow: inset 0 0 6px #e5e5e5; 47 | border-radius: 5px; 48 | } 49 | 50 | &::-webkit-scrollbar-thumb { 51 | border-radius: 5px; 52 | box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.2); 53 | } 54 | } 55 | 56 | .fe-menu { 57 | list-style: none; 58 | position: relative; 59 | padding: 0; 60 | 61 | &-item { 62 | cursor: pointer; 63 | position: relative; 64 | line-height: 2; 65 | font-size: 12px; 66 | width: 100%; 67 | overflow: hidden; /* 超出部分隐藏 */ 68 | white-space: nowrap; 69 | text-overflow: ellipsis; /* 适用IE */ 70 | padding: 0 10px; 71 | transition: color 0.5s; 72 | border-left: 2px solid #e8e8e8; 73 | 74 | &:hover { 75 | opacity: 0.8; 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/theme-chalk/src/search-input.less: -------------------------------------------------------------------------------- 1 | .search-input { 2 | width : 240px; 3 | z-index: 10; 4 | 5 | .search-icon /deep/ { 6 | display : inline-block; 7 | width : 14px; 8 | margin-left: 5px; 9 | background : url("https://deepexi.oss-cn-shenzhen.aliyuncs.com/deepexi-services-dashboard/common/search.svg") center / contain no-repeat; 10 | } 11 | 12 | .el-icon-search:before { 13 | font-size: 20px; 14 | color : #eee; 15 | } 16 | 17 | .el-input__inner { 18 | padding-left: 34px; 19 | border : none; 20 | border : 1px solid #eee; 21 | 22 | &:focus { 23 | border: 1px solid #bcc3d9; 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/theme-chalk/src/text-tooltip.less: -------------------------------------------------------------------------------- 1 | .text-tooltip { 2 | display : inline-block; 3 | overflow: hidden; 4 | width : 100%; 5 | 6 | &.ellipsis { 7 | text-overflow: ellipsis; 8 | white-space : nowrap; 9 | } 10 | } -------------------------------------------------------------------------------- /src/utils/assist.js: -------------------------------------------------------------------------------- 1 | export function oneOf(value, validList) { 2 | for (let i = 0; i < validList.length; i++) { 3 | if (value === validList[i]) { 4 | return true; 5 | } 6 | } 7 | return false; 8 | } 9 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | 3 | const buildMode = process.env.BUILD_MODE; 4 | 5 | console.log(buildMode); 6 | 7 | module.exports = { 8 | productionSourceMap: false, 9 | pages: { 10 | index: { 11 | entry: "src/index.js", 12 | template: "public/index.html", 13 | filename: "index.html" 14 | } 15 | }, 16 | configureWebpack: { 17 | externals: { 18 | "@femessage/element-ui": "Element", 19 | vue: { 20 | root: "Vue", 21 | commonjs: "vue", 22 | commonjs2: "vue", 23 | amd: "vue" 24 | } 25 | } 26 | }, 27 | chainWebpack: config => { 28 | if (process.env.NODE_ENV === "development") { 29 | config.devtool = "source-map"; 30 | } 31 | } 32 | }; 33 | --------------------------------------------------------------------------------