62 changed files with 580 additions and 1911 deletions
@ -1,12 +1,22 @@ |
|||
# 告诉EditorConfig插件,这是根文件,不用继续往上查找 |
|||
root = true |
|||
|
|||
# 匹配全部文件 |
|||
[*] |
|||
# 设置字符集 |
|||
charset = utf-8 |
|||
# 缩进风格,可选space、tab |
|||
indent_style = space |
|||
indent_size = 4 |
|||
# 缩进的空格数 |
|||
indent_size = 2 |
|||
# 结尾换行符,可选lf、cr、crlf |
|||
end_of_line = lf |
|||
# 在文件结尾插入新行 |
|||
insert_final_newline = true |
|||
# 删除一行中的前后空格 |
|||
trim_trailing_whitespace = true |
|||
|
|||
# 匹配md结尾的文件 |
|||
[*.md] |
|||
insert_final_newline = false |
|||
trim_trailing_whitespace = false |
|||
|
|||
@ -1,5 +0,0 @@ |
|||
{ |
|||
"hooks": { |
|||
"pre-commit": "lint-staged" |
|||
} |
|||
} |
|||
@ -1,6 +0,0 @@ |
|||
{ |
|||
"src/**/*.{js,vue}": [ |
|||
"vue-cli-service lint", |
|||
"vue-cli-service lint:style" |
|||
] |
|||
} |
|||
@ -1,6 +0,0 @@ |
|||
dist/ |
|||
node_modules/ |
|||
src/assets/sprites/ |
|||
src/theme/ |
|||
src/components/FontIcon/ |
|||
src/components/verifition |
|||
@ -1,18 +0,0 @@ |
|||
{ |
|||
"extends": [ |
|||
"stylelint-config-standard", |
|||
"stylelint-config-recommended-scss" |
|||
], |
|||
"plugins": [ |
|||
"stylelint-scss" |
|||
], |
|||
"rules": { |
|||
"indentation": 4, |
|||
"rule-empty-line-before": "never", |
|||
"at-rule-empty-line-before": "never", |
|||
"no-descending-specificity": null, |
|||
"selector-pseudo-class-no-unknown": null, |
|||
"selector-pseudo-element-no-unknown": [true, { "ignorePseudoElements": ["v-deep"] }], |
|||
"property-no-unknown": null |
|||
} |
|||
} |
|||
@ -1,10 +1,13 @@ |
|||
module.exports = { |
|||
presets: [ |
|||
// https://github.com/vuejs/vue-cli/tree/master/packages/@vue/babel-preset-app
|
|||
'@vue/cli-plugin-babel/preset' |
|||
], |
|||
env: { |
|||
development: { |
|||
plugins: ['dynamic-import-node'] |
|||
'env': { |
|||
'development': { |
|||
// babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require().
|
|||
// This plugin can significantly increase the speed of hot updates, when you have a large number of pages.
|
|||
'plugins': ['dynamic-import-node'] |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,56 +0,0 @@ |
|||
module.exports = [ |
|||
{ |
|||
name: 'vue', |
|||
library: 'Vue', |
|||
js: 'https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.min.js', |
|||
css: '' |
|||
}, |
|||
{ |
|||
name: 'vue-router', |
|||
library: 'VueRouter', |
|||
js: 'https://cdn.jsdelivr.net/npm/vue-router@3.3.4/dist/vue-router.min.js', |
|||
css: '' |
|||
}, |
|||
{ |
|||
name: 'vuex', |
|||
library: 'Vuex', |
|||
js: 'https://cdn.jsdelivr.net/npm/vuex@3.5.1/dist/vuex.min.js', |
|||
css: '' |
|||
}, |
|||
{ |
|||
name: 'axios', |
|||
library: 'axios', |
|||
js: 'https://cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js', |
|||
css: '' |
|||
}, |
|||
{ |
|||
name: 'qs', |
|||
library: 'Qs', |
|||
js: 'https://cdn.jsdelivr.net/npm/qs@6.9.3/dist/qs.js', |
|||
css: '' |
|||
}, |
|||
{ |
|||
name: 'nprogress', |
|||
library: 'NProgress', |
|||
js: 'https://cdn.jsdelivr.net/npm/nprogress@0.2.0/nprogress.min.js', |
|||
css: 'https://cdn.jsdelivr.net/npm/nprogress@0.2.0/nprogress.css' |
|||
}, |
|||
{ |
|||
name: 'vue-meta', |
|||
library: 'VueMeta', |
|||
js: 'https://cdn.jsdelivr.net/npm/vue-meta@2.4.0/dist/vue-meta.min.js', |
|||
css: '' |
|||
}, |
|||
{ |
|||
name: 'js-cookie', |
|||
library: 'Cookies', |
|||
js: 'https://cdn.jsdelivr.net/npm/js-cookie@2.2.1/src/js.cookie.min.js', |
|||
css: '' |
|||
}, |
|||
{ |
|||
name: 'dayjs', |
|||
library: 'dayjs', |
|||
js: 'https://cdn.jsdelivr.net/npm/dayjs@1.8.29/dayjs.min.js', |
|||
css: '' |
|||
} |
|||
] |
|||
@ -1,30 +0,0 @@ |
|||
# 关于 vue-automation |
|||
|
|||
## 这是什么 |
|||
|
|||
一款开箱即用的 Vue 项目模版,基于 Vue CLI |
|||
|
|||
## 特点 |
|||
|
|||
- 默认集成 vue-router 和 vuex |
|||
- 全局 SASS 资源自动引入 |
|||
- 精灵图自动生成 |
|||
- 全局组件自动注册 |
|||
- CDN支持,优化打包体积 |
|||
- 轻松实现团队代码规范 |
|||
|
|||
## 支持 |
|||
|
|||
给个小 ❤️ 吧~ |
|||
|
|||
[](https://github.com/hooray/vue-automation/stargazers) |
|||
|
|||
[](https://gitee.com/eoner/vue-automation/stargazers) |
|||
|
|||
## 生态 |
|||
|
|||
[](https://hooray.gitee.io/fantastic-admin) |
|||
|
|||
[Fantastic-admin](https://hooray.gitee.io/fantastic-admin) |
|||
|
|||
一款开箱即用的 Vue 中后台管理系统框架 |
|||
@ -1,7 +0,0 @@ |
|||
# vue-automation |
|||
|
|||
> 一款开箱即用的 Vue 项目模版 |
|||
|
|||
[开始使用](#关于-vue-automation) |
|||
[项目 Github 地址](https://github.com/hooray/vue-automation) |
|||
[项目 Gitee 地址](https://gitee.com/eoner/vue-automation) |
|||
@ -1,2 +0,0 @@ |
|||
* [Fantastic-admin](https://hooray.gitee.io/fantastic-admin) |
|||
* [文档打开慢?试试 Gitee 地址](http://eoner.gitee.io/vue-automation) |
|||
@ -1,14 +0,0 @@ |
|||
* [使用](start) |
|||
* [配置](configure) |
|||
* [全局 SASS 资源](sass-resources) |
|||
* [精灵图](sprite) |
|||
* [SVG图标](svg) |
|||
* [全局组件](global-component) |
|||
* [Vue-router](vue-router) |
|||
* [Vuex](vuex) |
|||
* [Axios拦截器](axios) |
|||
* [快速创建文件](plop) |
|||
* [代码规范](coding-standard.md) |
|||
* 扩展 |
|||
* [CDN支持](cdn.md) |
|||
* [移动端支持](mobile-support.md) |
|||
@ -1,11 +0,0 @@ |
|||
# Axios拦截器 |
|||
|
|||
拦截器的用处就是拦截每一次的请求和响应,然后做一些全局的处理。 |
|||
|
|||
例如接口响应报错,可以在拦截器里用统一的报错提示来展示,方便业务开发。 |
|||
|
|||
本框架提供了一份拦截器参考代码 `src/api/index.js` ,因为每个公司提供的接口标准不同,所以该文件需要开发者根据各自公司的接口去定制对应的拦截器。 |
|||
|
|||
代码很简单,首先初始化 `axios` 对象,然后 `axios.interceptors.request.use()` 和 `axios.interceptors.response.use()` 就分别是请求和响应的拦截代码了。 |
|||
|
|||
参考代码里只做了简单的拦截处理,例如请求的时候会自动带上 `token` ,响应的时候会根据错误信息判断是登录失效还是接口报错。 |
|||
@ -1,27 +0,0 @@ |
|||
# CDN支持 |
|||
|
|||
开启 CDN 的好处在于,项目中引用的一些第三方库不会打包进项目内,从而减小打包出的文件体积,同时借用 CDN 的优势,大大提高项目加载速度。 |
|||
|
|||
CDN 支持默认不开启,如果需要开启,则在 `.env.production` 生产环境配置文件中修改: |
|||
|
|||
``` |
|||
VUE_APP_CDN = ON |
|||
``` |
|||
|
|||
CDN 配置文件存放在项目根目录下的 `dependencies.cdn.js` 文件里,可按照标准格式自行扩展配置。 |
|||
|
|||
```js |
|||
{ |
|||
name: '', |
|||
library: '', |
|||
js: '', |
|||
css: '' |
|||
} |
|||
``` |
|||
|
|||
其中 `name` 和 `library` 最终会转成 webpack 中 externals 的配置项, `name` 是引入的包名, `library` 是全局变量。 |
|||
|
|||
这里需要注意以下两点: |
|||
|
|||
1. 如果只在生产环境开启 CDN 支持,请确保第三方库的 CDN 版本与本地依赖包的版本一致,以免出现开发环境是正常的,但生产环境缺不行的情况,也就是因为版本不同造成的 bug |
|||
2. 开发环境开启 CDN 支持后会导致 [Vue.js devtools](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd) 无法使用,所以不建议开发环境开启 |
|||
@ -1,77 +0,0 @@ |
|||
# 代码规范 |
|||
|
|||
## IDE 编辑器 |
|||
|
|||
为保证代码风格统一,统一使用 [VS Code](https://code.visualstudio.com/) 做为开发 IDE ,并安装以下扩展: |
|||
|
|||
- [EditorConfig for VS Code](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig) |
|||
- [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) |
|||
- [Vetur](https://marketplace.visualstudio.com/items?itemName=octref.vetur) |
|||
- [Prettier - Code formatter](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) |
|||
- [stylelint](https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint) |
|||
|
|||
安装完后在 `settings.json` 中增加如下配置: |
|||
|
|||
```json |
|||
"editor.codeActionsOnSave": { |
|||
"source.fixAll.eslint": true, |
|||
"source.fixAll.stylelint": true |
|||
} |
|||
``` |
|||
|
|||
最终效果为,在保存时,会自动对当前文件进行代码格式化操作。 |
|||
|
|||
## Git 钩子 |
|||
|
|||
上述操作仅对代码的写法规范进行格式化,例如缩进、空格、结尾的分号等。 |
|||
|
|||
而在提交代码时, Git 的钩子会检查代码中是否有错误,这些错误是 IDE 无法自动修复的,例如出现未使用过的变量。如果有错误,则会取消此次提交,直到开发者修复完所有错误后才允许提交成功,确保仓库里的代码绝对正确。 |
|||
|
|||
> 可通过修改 `.eslintignore` 和 `.stylelintignore` 忽略无需做代码规范的文件,例如在项目中引用了一些第三方的插件或组件,我们就可以将其忽略 |
|||
|
|||
如果 `git init` 仓库初始化是在依赖包安装之后执行的,则无法初始化 Git 钩子,建议在 `git init` 之后再执行一遍 `yarn` 或者 `npm i` ,重新安装一遍依赖包。 |
|||
|
|||
## 配置代码规范 |
|||
|
|||
配置文件主要有 3 处,分别为 IDE 配置(`.editorconfig`)、ESLint 配置(`.eslintrc.js` 和 `.eslintignore`)、StyleLint 配置(`.stylelintrc` 和 `.stylelintignore`)。 |
|||
|
|||
以代码缩进举例,本模版默认是以 4 空格进行缩进,如果要调整为 2 空格,则需要在 `.editorconfig` 里修改: |
|||
|
|||
``` |
|||
indent_size = 2 |
|||
``` |
|||
|
|||
在 `.eslintrc.js` 里修改: |
|||
|
|||
``` |
|||
'indent': [2, 2, { |
|||
'SwitchCase': 1 |
|||
}], |
|||
|
|||
... |
|||
|
|||
'vue/html-indent': [2, 2], |
|||
|
|||
... |
|||
|
|||
'vue/script-indent': [2, 2, { |
|||
'switchCase': 1 |
|||
}] |
|||
``` |
|||
|
|||
在 `.stylelintrc` 里修改: |
|||
|
|||
``` |
|||
"indentation": 2 |
|||
``` |
|||
|
|||
修改完毕后,再分别执行下面两句命令: |
|||
|
|||
```bash |
|||
yarn run lint |
|||
yarn run stylelint |
|||
``` |
|||
|
|||
该操作会将代码进行一次格式校验,如果规则支持自动修复,则会将不符合规则的代码自动进行格式化。 |
|||
|
|||
以上面的例子,当缩进规则调整后,我们无需手动去每个文件调整,通过命令可以自动应用新的缩进规则。 |
|||
@ -1,5 +0,0 @@ |
|||
# 配置 |
|||
|
|||
默认提供开发环境和生产环境两套配置,分别在根目录下 `.env.development` 和 `.env.production` 文件里,可配置项有网站标题、接口请求地址和是否开启CDN支持。 |
|||
|
|||
开发者可根据实际业务需求进行扩展,如果对这块不熟悉,可阅读 Vue CLI [环境变量和模式](https://cli.vuejs.org/zh/guide/mode-and-env.html) 章节。 |
|||
@ -1,11 +0,0 @@ |
|||
# 全局组件 |
|||
|
|||
全局组件存放在 `components/global/` 目录下,需要注意各个组件按文件夹区分。 |
|||
|
|||
每个组件的文件夹内至少保留一个文件名为 `index` 的组件入口,例如 `index.vue` 。 |
|||
|
|||
组件必须设置 `name` 并保证其唯一,自动注册会将组件的 `name` 设为组件名,可参考 SvgIcon 组件写法。 |
|||
|
|||
虽然文件夹名称和 `name` 无关联,但建议与 `name` 保持一致。 |
|||
|
|||
如果组件是通过 js 进行调用,则确保组件入口文件为 `index.js`,可参考 ExampleNotice 组件。 |
|||
@ -1,39 +0,0 @@ |
|||
<!DOCTYPE html> |
|||
<html lang="en"> |
|||
<head> |
|||
<meta charset="UTF-8"> |
|||
<title>vue-automation</title> |
|||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> |
|||
<meta name="description" content="Description"> |
|||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> |
|||
<!-- <link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css"> --> |
|||
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify-themeable@0/dist/css/theme-simple-dark.css"> |
|||
</head> |
|||
<body> |
|||
<div id="app">载入中...</div> |
|||
<script> |
|||
window.$docsify = { |
|||
name: 'vue-automation', |
|||
repo: '', |
|||
auto2top: true, |
|||
loadNavbar: true, |
|||
loadSidebar: true, |
|||
maxLevel: 4, |
|||
subMaxLevel: 2, |
|||
coverpage: true, |
|||
copyCode: { |
|||
buttonText : '点击复制', |
|||
errorText : '错误', |
|||
successText: '复制成功' |
|||
}, |
|||
disqus: 'vue-automation' |
|||
} |
|||
</script> |
|||
<script src="//cdn.jsdelivr.net/npm/docsify/lib/docsify.min.js"></script> |
|||
<script src="//cdn.jsdelivr.net/npm/docsify-copy-code/dist/docsify-copy-code.min.js"></script> |
|||
<script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/zoom-image.min.js"></script> |
|||
<script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/emoji.min.js"></script> |
|||
<script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/disqus.min.js"></script> |
|||
<script src="//cdn.jsdelivr.net/npm/docsify-themeable@0"></script> |
|||
</body> |
|||
</html> |
|||
@ -1,39 +0,0 @@ |
|||
# 移动端支持 |
|||
|
|||
移动端各司都有自己的解决方案,以下为我司为例,做为参考: |
|||
|
|||
我司统一使用 vw/vh 做为移动端的布局单位,单位转换通过 [postcss-px-to-viewport](https://www.npmjs.com/package/postcss-px-to-viewport) 进行处理。 |
|||
|
|||
首先安装依赖: |
|||
|
|||
`yarn add -D postcss-px-to-viewport` |
|||
|
|||
然后在 `vue.config.js` 里进行配置,具体配置信息可根据项目实际调整: |
|||
|
|||
```js |
|||
module.exports = { |
|||
css: { |
|||
loaderOptions: { |
|||
postcss: { |
|||
plugins: [ |
|||
require('postcss-px-to-viewport')({ |
|||
'unitToConvert': 'px', |
|||
'viewportWidth': 750, |
|||
'unitPrecision': 3, |
|||
'viewportUnit': 'vw', |
|||
'selectorBlackList': [ |
|||
'ignore', |
|||
'van', |
|||
'mescroll' |
|||
], |
|||
'minPixelValue': 1, |
|||
'mediaQuery': false |
|||
}) |
|||
] |
|||
} |
|||
} |
|||
} |
|||
} |
|||
``` |
|||
|
|||
最后在开发中就可以直接使用 px 了,最终输出就是 vw 。 |
|||
@ -1,13 +0,0 @@ |
|||
# 快速创建文件 |
|||
|
|||
开发过程中,避免不了手动去频繁创建页面、组件等文件,并且还要在文件里写一些必要的代码,是不是觉得很麻烦?现在你可以用更简洁的方式来处理这一切。 |
|||
|
|||
 |
|||
|
|||
> 该功能基于 [plop](https://www.npmjs.com/package/plop) 实现。 |
|||
|
|||
模版默认提供了 page(页面/布局) 、component(组件) 、store(全局状态) 三个模版文件,通过 `yarn new` 指令可以自行选择。 |
|||
|
|||
在实际项目开发中,建议根据项目定制适合项目的模版文件,可以大大提高开发效率,当多人协作开发时,也能统一部分标准。 |
|||
|
|||
模版目录为 `./plop-templates/` ,如果是新建模版,记得在项目根目录 `plopfile.js` 里引用一下。 |
|||
@ -1,9 +0,0 @@ |
|||
# 全局 SASS 资源 |
|||
|
|||
> 全局 SASS 资源并不是全局样式,是变量、@mixin 、@function 这些东西 |
|||
|
|||
在 `assets/styles/resources/` 目录下存放全局的 SASS 资源,也就是说在这个目录里的文件,无需在页面上引用即可生效并使用。 |
|||
|
|||
项目中默认存放了 `utils.scss` 文件,里面有几个 `@mixin` 和 `%` ,你可以尝试在页面中使用它们看看效果。 |
|||
|
|||
同样,[精灵图](sprite)目录下生成的 SASS 资源也是全局可调用的。 |
|||
@ -1,59 +0,0 @@ |
|||
# 精灵图 |
|||
|
|||
> 又称雪碧图,原理是将多张小图合并到一张大图上,以便减少 HTTP 请求,提高网站访问速度。 |
|||
|
|||
精灵图原始图片的存放位置位于 `assets/sprites/` 目录下,注意按文件夹区分。 |
|||
|
|||
项目运行前会根据文件夹生成对应的精灵图文件(精灵图图片和 `.scss` 文件),多个文件夹则会生成多个精灵图文件。需要注意的是,在项目运行时,修改文件夹里的图片,会重新生成相关精灵图文件,但如果新建文件夹,则需要重新运行项目才会生成对应精灵图文件。 |
|||
|
|||
在 `.vue` 文件中可通过 `@include` 直接使用精灵图,无需手动引入 `.scss` 文件: |
|||
|
|||
```scss |
|||
// 方法 1 |
|||
// @include [文件夹名称]-sprite([文件名称]); |
|||
.icon { |
|||
@include example-sprite(address); |
|||
} |
|||
|
|||
// 方法 2 |
|||
// @include all-[文件夹名称]-sprites; |
|||
@include all-example-sprites; |
|||
``` |
|||
|
|||
最终输出如下: |
|||
|
|||
```css |
|||
/* 方法 1 */ |
|||
.icon { |
|||
background-image: url(img/example.326b35aec20837b9c08563c654422fe6.326b35ae.png); |
|||
background-position: 0px 0px; |
|||
background-size: 210px 210px; |
|||
width: 100px; |
|||
height: 100px; |
|||
} |
|||
|
|||
/* 方法 2 */ |
|||
.example-address-sprites { |
|||
background-image: url(img/example.326b35aec20837b9c08563c654422fe6.326b35ae.png); |
|||
background-position: 0 0; |
|||
background-size: 210px 210px; |
|||
width: 100px; |
|||
height: 100px; |
|||
} |
|||
.example-feedback-sprites { |
|||
background-image: url(img/example.326b35aec20837b9c08563c654422fe6.326b35ae.png); |
|||
background-position: -110px 0; |
|||
background-size: 210px 210px; |
|||
width: 100px; |
|||
height: 100px; |
|||
} |
|||
.example-payment-sprites { |
|||
background-image: url(img/example.326b35aec20837b9c08563c654422fe6.326b35ae.png); |
|||
background-position: 0 -110px; |
|||
background-size: 210px 210px; |
|||
width: 100px; |
|||
height: 100px; |
|||
} |
|||
``` |
|||
|
|||
如果是小型项目,静态图标不多,可全部放在一个文件夹内;如果是中大型项目,文件夹可按模块来划分,这样不同的模块最终会生成各自的精灵图文件。 |
|||
@ -1,35 +0,0 @@ |
|||
# 使用 |
|||
|
|||
使用前确保本地环境已安装 [Vue CLI](https://cli.vuejs.org/zh/) 。 |
|||
|
|||
## 方法 1 |
|||
|
|||
> 适用于初学者快速上手,项目里包含演示文件,方便学习 |
|||
|
|||
```bash |
|||
git clone https://gitee.com/eoner/vue-automation.git |
|||
cd vue-automation |
|||
yarn install |
|||
``` |
|||
|
|||
拉取该项目到本地,安装依赖包后即可运行。 |
|||
|
|||
运行后,可以看到功能演示,同时项目目录里带有 `example` 的均为演示代码。 |
|||
|
|||
## 方法 2 |
|||
|
|||
> 适用于已熟练使用的老手,项目里无演代码,方便快速开展工作 |
|||
|
|||
安装并使用 [1one-project](https://www.npmjs.com/package/1one-project) 进行项目初始化。 |
|||
|
|||
## 注意事项 |
|||
|
|||
~~值得一提的是,如果安装过程出现 sass 相关的安装错误,请在安装 [mirror-config-china](https://www.npmjs.com/package/mirror-config-china) 后重试。~~ |
|||
|
|||
~~```yarn global add mirror-config-china```~~ |
|||
|
|||
大部分安装报错都是因为 `node-sass` 依赖导致,尤其是 Windows 用户,它会强制安装 `python2` 和 `Visual Studio` 才能编译成功。 |
|||
|
|||
目前本模版已将 `node-sass` 替换为 `sass` ,简化用户安装成本,同时 Sass 官方也已经将 `dart-sass` 作为未来主要的的开发方向了。 |
|||
|
|||
参考《[Node Sass to Dart Sass](https://panjiachen.gitee.io/vue-element-admin-site/zh/guide/advanced/sass.html)》 |
|||
@ -1,11 +0,0 @@ |
|||
# SVG图标 |
|||
|
|||
现在越来越多项目开始使用 SVG 图标做为精灵图的替代品,本框架也提供了 SVG 图标支持,方便使用。推荐去[阿里巴巴矢量图标库](https://www.iconfont.cn/)下载高质量 SVG 图标 |
|||
|
|||
首先将 svg 文件放到 `src/assets/icons/` 目录下,然后在页面中就可以使用了,`name` 就是 svg 文件名 |
|||
|
|||
```html |
|||
<svg-icon name="example" /> |
|||
``` |
|||
|
|||
> `<svg-icon />` 组件为全局组件,所以无需注册即可使用 |
|||
@ -1,5 +0,0 @@ |
|||
# Vue-router |
|||
|
|||
路由也实现了自动注册,但因为有优先级的概念,先定义的会先匹配,所以同一模块下的路由需要放在一个路由配置文件里。 |
|||
|
|||
开发者只需关心 `router/modules/` 目录下的文件,一个模块对应一个 `.js` 文件,可参考 `router/modules/example.js` 文件。 |
|||
@ -1,31 +0,0 @@ |
|||
# Vuex |
|||
|
|||
Vuex 同样实现了自动注册,开发只需关注 `store/modules/` 文件夹里的文件即可,同样也按照模块区分文件。 |
|||
|
|||
新建模版: |
|||
|
|||
```js |
|||
// example.js |
|||
const state = {} |
|||
const getters = {} |
|||
const actions = {} |
|||
const mutations = {} |
|||
export default { |
|||
namespaced: true, |
|||
state, |
|||
actions, |
|||
getters, |
|||
mutations |
|||
} |
|||
``` |
|||
|
|||
文件默认开启命名空间,文件名会默认注册为模块名。 |
|||
|
|||
使用方法: |
|||
|
|||
```js |
|||
this.$store.state.example.xxx; |
|||
this.$store.getters['example/xxx']; |
|||
this.$store.dispatch('example/xxx'); |
|||
this.$store.commit('example/xxx'); |
|||
``` |
|||
@ -1,23 +0,0 @@ |
|||
<template> |
|||
<div> |
|||
<!-- 组件内容区 --> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
{{#if isGlobal}} |
|||
name: '{{ properCase name }}', |
|||
{{/if}} |
|||
props: {}, |
|||
data() { |
|||
return {} |
|||
}, |
|||
mounted() {}, |
|||
methods: {} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
// scss |
|||
</style> |
|||
@ -1,63 +0,0 @@ |
|||
const fs = require('fs') |
|||
|
|||
function getFolder(path) { |
|||
let components = [] |
|||
const files = fs.readdirSync(path) |
|||
files.forEach(function(item) { |
|||
let stat = fs.lstatSync(path + '/' + item) |
|||
if (stat.isDirectory() === true && item != 'components') { |
|||
components.push(path + '/' + item) |
|||
components.push.apply(components, getFolder(path + '/' + item)) |
|||
} |
|||
}) |
|||
return components |
|||
} |
|||
|
|||
module.exports = { |
|||
description: '创建组件', |
|||
prompts: [ |
|||
{ |
|||
type: 'confirm', |
|||
name: 'isGlobal', |
|||
message: '是否为全局组件', |
|||
default: false |
|||
}, |
|||
{ |
|||
type: 'list', |
|||
name: 'path', |
|||
message: '请选择组件创建目录', |
|||
choices: getFolder('src/views'), |
|||
when: answers => { |
|||
return !answers.isGlobal |
|||
} |
|||
}, |
|||
{ |
|||
type: 'input', |
|||
name: 'name', |
|||
message: '请输入组件名称', |
|||
validate: v => { |
|||
if (!v || v.trim === '') { |
|||
return '组件名称不能为空' |
|||
} else { |
|||
return true |
|||
} |
|||
} |
|||
} |
|||
], |
|||
actions: data => { |
|||
let path = '' |
|||
if (data.isGlobal) { |
|||
path = 'src/components/{{properCase name}}/oldIndex.vue' |
|||
} else { |
|||
path = `${data.path}/components/{{properCase name}}/index.vue` |
|||
} |
|||
const actions = [ |
|||
{ |
|||
type: 'add', |
|||
path: path, |
|||
templateFile: 'plop-templates/component/index.hbs' |
|||
} |
|||
] |
|||
return actions |
|||
} |
|||
} |
|||
@ -1,20 +0,0 @@ |
|||
<template> |
|||
<div> |
|||
页面内容区域 |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: '{{ properCase componentName }}', |
|||
data() { |
|||
return {} |
|||
}, |
|||
mounted() {}, |
|||
methods: {} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
// scss |
|||
</style> |
|||
@ -1,53 +0,0 @@ |
|||
const path = require('path') |
|||
const fs = require('fs') |
|||
|
|||
function getFolder(path) { |
|||
let components = [] |
|||
const files = fs.readdirSync(path) |
|||
files.forEach(function(item) { |
|||
let stat = fs.lstatSync(path + '/' + item) |
|||
if (stat.isDirectory() === true && item != 'components') { |
|||
components.push(path + '/' + item) |
|||
components.push.apply(components, getFolder(path + '/' + item)) |
|||
} |
|||
}) |
|||
return components |
|||
} |
|||
|
|||
module.exports = { |
|||
description: '创建页面', |
|||
prompts: [ |
|||
{ |
|||
type: 'list', |
|||
name: 'path', |
|||
message: '请选择页面创建目录', |
|||
choices: getFolder('src/views') |
|||
}, |
|||
{ |
|||
type: 'input', |
|||
name: 'name', |
|||
message: '请输入文件名', |
|||
validate: v => { |
|||
if (!v || v.trim === '') { |
|||
return '文件名不能为空' |
|||
} else { |
|||
return true |
|||
} |
|||
} |
|||
} |
|||
], |
|||
actions: data => { |
|||
let relativePath = path.relative('src/views', data.path) |
|||
const actions = [ |
|||
{ |
|||
type: 'add', |
|||
path: `${data.path}/{{dotCase name}}.vue`, |
|||
templateFile: 'plop-templates/page/index.hbs', |
|||
data: { |
|||
componentName: `${relativePath} ${data.name}` |
|||
} |
|||
} |
|||
] |
|||
return actions |
|||
} |
|||
} |
|||
@ -1,15 +0,0 @@ |
|||
const state = {} |
|||
|
|||
const getters = {} |
|||
|
|||
const actions = {} |
|||
|
|||
const mutations = {} |
|||
|
|||
export default { |
|||
namespaced: true, |
|||
state, |
|||
actions, |
|||
getters, |
|||
mutations |
|||
} |
|||
@ -1,27 +0,0 @@ |
|||
module.exports = { |
|||
description: '创建全局状态', |
|||
prompts: [ |
|||
{ |
|||
type: 'input', |
|||
name: 'name', |
|||
message: '请输入模块名称', |
|||
validate: v => { |
|||
if (!v || v.trim === '') { |
|||
return '模块名称不能为空' |
|||
} else { |
|||
return true |
|||
} |
|||
} |
|||
} |
|||
], |
|||
actions: data => { |
|||
const actions = [ |
|||
{ |
|||
type: 'add', |
|||
path: `src/store/modules/${data.name}.js`, |
|||
templateFile: 'plop-templates/store/index.hbs' |
|||
} |
|||
] |
|||
return actions |
|||
} |
|||
} |
|||
@ -1,6 +0,0 @@ |
|||
module.exports = function(plop) { |
|||
plop.setWelcomeMessage('请选择需要创建的模式:') |
|||
plop.setGenerator('page', require('./plop-templates/page/prompt')) |
|||
plop.setGenerator('component', require('./plop-templates/component/prompt')) |
|||
plop.setGenerator('store', require('./plop-templates/store/prompt')) |
|||
} |
|||
@ -1,66 +0,0 @@ |
|||
{ |
|||
// Default options |
|||
'functions': true, |
|||
'variableNameTransforms': ['dasherize'] |
|||
} |
|||
|
|||
{{#block "sprites"}} |
|||
{{#each sprites}} |
|||
${{../spritesheet_info.strings.name}}-sprite-{{strings.name}}: ({{px.x}}, {{px.y}}, {{px.offset_x}}, {{px.offset_y}}, {{px.width}}, {{px.height}}, {{px.total_width}}, {{px.total_height}}, '{{{escaped_image}}}', '{{name}}'); |
|||
{{/each}} |
|||
|
|||
${{spritesheet_info.strings.name}}-sprites: ( |
|||
{{#each sprites}} |
|||
{{strings.name}}: ${{../spritesheet_info.strings.name}}-sprite-{{strings.name}}, |
|||
{{/each}} |
|||
); |
|||
{{/block}} |
|||
|
|||
{{#block "sprite-functions"}} |
|||
{{#if options.functions}} |
|||
@mixin {{spritesheet_info.strings.name}}-sprite-width($sprite) { |
|||
width: nth($sprite, 5); |
|||
} |
|||
|
|||
@mixin {{spritesheet_info.strings.name}}-sprite-height($sprite) { |
|||
height: nth($sprite, 6); |
|||
} |
|||
|
|||
@mixin {{spritesheet_info.strings.name}}-sprite-position($sprite) { |
|||
$sprite-offset-x: nth($sprite, 3); |
|||
$sprite-offset-y: nth($sprite, 4); |
|||
background-position: $sprite-offset-x $sprite-offset-y; |
|||
} |
|||
|
|||
@mixin {{spritesheet_info.strings.name}}-sprite-size($sprite) { |
|||
background-size: nth($sprite, 7) nth($sprite, 8); |
|||
} |
|||
|
|||
@mixin {{spritesheet_info.strings.name}}-sprite-image($sprite) { |
|||
$sprite-image: nth($sprite, 9); |
|||
background-image: url(#{$sprite-image}); |
|||
} |
|||
|
|||
@mixin {{spritesheet_info.strings.name}}-sprite($name) { |
|||
@include {{spritesheet_info.strings.name}}-sprite-image(map-get(${{spritesheet_info.strings.name}}-sprites, #{$name})); |
|||
@include {{spritesheet_info.strings.name}}-sprite-position(map-get(${{spritesheet_info.strings.name}}-sprites, #{$name})); |
|||
@include {{spritesheet_info.strings.name}}-sprite-size(map-get(${{spritesheet_info.strings.name}}-sprites, #{$name})); |
|||
@include {{spritesheet_info.strings.name}}-sprite-width(map-get(${{spritesheet_info.strings.name}}-sprites, #{$name})); |
|||
@include {{spritesheet_info.strings.name}}-sprite-height(map-get(${{spritesheet_info.strings.name}}-sprites, #{$name})); |
|||
background-repeat: no-repeat; |
|||
} |
|||
{{/if}} |
|||
{{/block}} |
|||
|
|||
{{#block "spritesheet-functions"}} |
|||
{{#if options.functions}} |
|||
@mixin all-{{spritesheet_info.strings.name}}-sprites() { |
|||
@each $key, $val in ${{spritesheet_info.strings.name}}-sprites { |
|||
$sprite-name: nth($val, 10); |
|||
.{{spritesheet_info.strings.name}}-#{$sprite-name}-sprites { |
|||
@include {{spritesheet_info.strings.name}}-sprite($key); |
|||
} |
|||
} |
|||
} |
|||
{{/if}} |
|||
{{/block}} |
|||
|
After Width: | Height: | Size: 219 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 4.4 KiB |
@ -1,85 +0,0 @@ |
|||
<!--<template>--> |
|||
<!-- <div class="container" style="overflow-y: hidden !important;">--> |
|||
<!-- <el-row type="flex" align="middle" justify="justify">--> |
|||
<!-- <el-col :offset="1" :span="4">--> |
|||
<!-- <el-button size="mini" round @click="$router.back(-1)">--> |
|||
<!-- <i class="el-icon-arrow-left" />--> |
|||
<!-- 返回--> |
|||
<!-- </el-button>--> |
|||
<!-- </el-col>--> |
|||
<!-- <el-col :span="10" :offset="3">--> |
|||
<!-- <el-menu :default-active="activeTab" style="background-color: transparent;" mode="horizontal"--> |
|||
<!-- @select="handleSelect"--> |
|||
<!-- >--> |
|||
<!-- <el-menu-item index="editor">编辑</el-menu-item>--> |
|||
<!-- <el-menu-item index="logic">逻辑</el-menu-item>--> |
|||
<!-- <el-menu-item index="theme">外观</el-menu-item>--> |
|||
<!-- <el-menu-item index="setting">设置</el-menu-item>--> |
|||
<!-- <el-menu-item index="publish">发布</el-menu-item>--> |
|||
<!-- <el-menu-item index="statistics">统计</el-menu-item>--> |
|||
<!-- </el-menu>--> |
|||
<!-- </el-col>--> |
|||
<!-- </el-row>--> |
|||
<!-- <div v-if="projectKey">--> |
|||
<!-- <editor v-if="activeTab=='editor'" :project-key="projectKey" :is-edit="isEdit" />--> |
|||
<!-- <logic v-if="activeTab=='logic'" :project-key="projectKey" />--> |
|||
<!-- <theme v-if="activeTab=='theme'" :project-key="projectKey" />--> |
|||
<!-- <setting v-if="activeTab=='setting'" :project-key="projectKey" />--> |
|||
<!-- <publish v-if="activeTab=='publish'" :project-key="projectKey" />--> |
|||
<!-- <statistics v-if="activeTab=='statistics'" :project-key="projectKey" />--> |
|||
<!-- </div>--> |
|||
<!-- </div>--> |
|||
<!--</template>--> |
|||
|
|||
<!--<script>--> |
|||
<!--import editor from './editor'--> |
|||
<!--import theme from './theme'--> |
|||
<!--import setting from './setting'--> |
|||
<!--import publish from './publish'--> |
|||
<!--import statistics from './statistics'--> |
|||
<!--import logic from './logic'--> |
|||
|
|||
<!--export default {--> |
|||
<!-- components: {--> |
|||
<!-- editor,--> |
|||
<!-- theme,--> |
|||
<!-- setting,--> |
|||
<!-- publish,--> |
|||
<!-- statistics,--> |
|||
<!-- logic--> |
|||
<!-- },--> |
|||
<!-- data() {--> |
|||
<!-- return {--> |
|||
<!-- activeTab: 'editor',--> |
|||
<!-- isEdit: false,--> |
|||
<!-- projectKey: ''--> |
|||
<!-- }--> |
|||
<!-- },--> |
|||
<!-- computed: {},--> |
|||
<!-- watch: {},--> |
|||
<!-- mounted() {--> |
|||
<!-- this.projectKey = this.$route.query.key--> |
|||
<!-- this.isEdit = !!this.$route.query.active--> |
|||
<!-- if (this.$route.query.active) {--> |
|||
<!-- this.activeTab = this.$route.query.active--> |
|||
<!-- }--> |
|||
<!-- },--> |
|||
<!-- methods: {--> |
|||
<!-- handleSelect(type) {--> |
|||
<!-- if (type) {--> |
|||
<!-- this.activeTab = type--> |
|||
<!-- this.$router.replace({path: '/project/form', query: {key: this.projectKey, active: type}})--> |
|||
<!-- }--> |
|||
<!-- }--> |
|||
<!-- }--> |
|||
<!--}--> |
|||
<!--</script>--> |
|||
|
|||
<!--<style lang='scss'>--> |
|||
<!--.container {--> |
|||
<!-- position: relative;--> |
|||
<!-- width: 100%;--> |
|||
<!-- height: 100%;--> |
|||
<!-- //overflow-y: hidden;--> |
|||
<!--}--> |
|||
<!--</style>--> |
|||
@ -0,0 +1,149 @@ |
|||
<template> |
|||
<el-dialog :visible.sync="dialogVisible" center title="筛选"> |
|||
<p>点击添加筛选项:</p> |
|||
<el-row> |
|||
<el-col :span="6" class="filter-left"> |
|||
<p v-for="(field,index) in fields" :key="field.id" |
|||
:class="{'selected':field.selected}" |
|||
class="filter-item-label" |
|||
@click="selectedFieldHandle(index,field)" |
|||
> |
|||
{{ |
|||
field.label |
|||
}} |
|||
</p> |
|||
</el-col> |
|||
<el-col :span="18" class="filter-right"> |
|||
<data-empty v-if="!selectedFields||selectedFields.length==0" :desc="'请在左侧选择筛选项'" /> |
|||
<div v-for="field in selectedFields" :key="field.id"> |
|||
<div class="filter-item"> |
|||
<label>{{ field.label }}</label> |
|||
<div v-if="['SELECT','RADIO','CHECKBOX','IMAGE_SELECT'].includes(field.type)"> |
|||
<p class="compare"> |
|||
选择 |
|||
</p> |
|||
<el-select v-model="filterParams[`filed${field.formItemId}`]"> |
|||
<el-option |
|||
v-for="item in field.expand.options" |
|||
:key="item.id" |
|||
:label="item.label" |
|||
:value="item.id" |
|||
/> |
|||
</el-select> |
|||
</div> |
|||
<div v-else> |
|||
<p class="compare"> |
|||
包含 |
|||
</p> |
|||
<el-input v-model="filterParams[`filed${field.formItemId}`]" /> |
|||
</div> |
|||
<i class="el-icon-delete" @click="removeSelectedFieldHandle" /> |
|||
</div> |
|||
<el-divider /> |
|||
</div> |
|||
</el-col> |
|||
</el-row> |
|||
<span slot="footer" class="dialog-footer"> |
|||
<el-button @click="dialogVisible = false">取 消</el-button> |
|||
<el-button :disabled="selectedFields.length==0" type="primary" @click="submitFilterHandle">确 定</el-button> |
|||
</span> |
|||
</el-dialog> |
|||
</template> |
|||
|
|||
<script> |
|||
import DataEmpty from '@/components/DataEmpty' |
|||
|
|||
export default { |
|||
name: 'StatisticsFilter', |
|||
components: {DataEmpty}, |
|||
props: { |
|||
fields: null |
|||
}, |
|||
data() { |
|||
return { |
|||
dialogVisible: true, |
|||
selectedFields: [], |
|||
filterParams: {} |
|||
} |
|||
}, |
|||
methods: { |
|||
showDialogHandle() { |
|||
this.dialogVisible = true |
|||
}, |
|||
removeSelectedFieldHandle(index, item) { |
|||
this.selectedFields.splice(index, 1) |
|||
item.selected = false |
|||
this.$set(this.fields, item.leftIndex, item) |
|||
}, |
|||
submitFilterHandle() { |
|||
this.$emit('filter', this.filterParams) |
|||
this.dialogVisible = false |
|||
}, |
|||
selectedFieldHandle(index, item) { |
|||
if (item.selected) { |
|||
return |
|||
} |
|||
item.selected = true |
|||
this.$set(this.fields, index, item) |
|||
item.leftIndex = index |
|||
this.selectedFields.push(item) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.filter-left { |
|||
border-right: 1px solid #dcdfe6; |
|||
|
|||
.selected { |
|||
color: $--color-primary !important; |
|||
|
|||
&:hover { |
|||
cursor: none !important; |
|||
} |
|||
} |
|||
|
|||
.filter-item-label { |
|||
color: #606266; |
|||
line-height: 25px; |
|||
|
|||
&:hover { |
|||
color: $--color-primary; |
|||
cursor: pointer; |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
.filter-right { |
|||
padding: 20px; |
|||
|
|||
.filter-item { |
|||
display: flex; |
|||
flex-direction: row; |
|||
align-items: center; |
|||
justify-content: space-evenly; |
|||
|
|||
& :first-child p { |
|||
width: 100px; |
|||
} |
|||
|
|||
.compare { |
|||
width: 100px; |
|||
margin: 0px; |
|||
} |
|||
|
|||
& .el-icon-delete:hover { |
|||
color: $--color-danger; |
|||
} |
|||
|
|||
& > div { |
|||
display: flex; |
|||
flex-direction: row; |
|||
align-items: center; |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
|
|||
@ -1,45 +0,0 @@ |
|||
<template> |
|||
<el-row> |
|||
<el-col :offset="2" :span="5"> |
|||
<el-button class="home-fun-btn" @click="$router.push({path:'/project/create'})"> |
|||
新建项目 <i class="el-icon-plus" /> |
|||
</el-button> |
|||
</el-col> |
|||
<el-col :span="5"> |
|||
<el-button class="home-fun-btn" @click="$router.push({path:'/project/my'})"> |
|||
我的项目<i class="el-icon-s-custom" /> |
|||
</el-button> |
|||
</el-col> |
|||
<el-col :span="5"> |
|||
<el-button class="home-fun-btn" @click="$router.push({path:'/project/create'})"> |
|||
行业模板<i class="el-icon-s-management" /> |
|||
</el-button> |
|||
</el-col> |
|||
<el-col :span="5"> |
|||
<el-button class="home-fun-btn" @click="$router.push({path:'/project/recycle'})"> |
|||
回收站<i class="el-icon-delete-solid" /> |
|||
</el-button> |
|||
</el-col> |
|||
</el-row> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'HomeFunction' |
|||
} |
|||
</script> |
|||
<style scoped> |
|||
.home-fun-btn { |
|||
width: 70%; |
|||
height: 145px; |
|||
line-height: 20px; |
|||
border-radius: 15px; |
|||
font-weight: 580; |
|||
background-color: rgba(255, 255, 255, 100); |
|||
color: rgba(16, 16, 16, 100); |
|||
font-size: 14px; |
|||
text-align: center; |
|||
border: 1px solid rgba(187, 187, 187, 100); |
|||
} |
|||
</style> |
|||
|
|||
@ -1,28 +0,0 @@ |
|||
<template> |
|||
<el-row> |
|||
<!-- 轮播·1--> |
|||
<!-- <el-row>--> |
|||
<!-- <el-col :span="24">--> |
|||
<!-- <el-carousel height="55px">--> |
|||
<!-- <el-carousel-item v-for="item in 2" :key="item">--> |
|||
<!-- <img style="height: 55px; width: 100%;"--> |
|||
<!-- src="https://freebrio.oss-cn-shanghai.aliyuncs.com/t/v2_q2c4aj.png"--> |
|||
<!-- >--> |
|||
<!-- </el-carousel-item>--> |
|||
<!-- </el-carousel>--> |
|||
<!-- </el-col>--> |
|||
<!-- </el-row>--> |
|||
<Dashboard /> |
|||
<HomeFunction /> |
|||
</el-row> |
|||
</template> |
|||
|
|||
<script> |
|||
import HomeFunction from './HomButton' |
|||
import Dashboard from '../form/statistics/chart' |
|||
|
|||
export default { |
|||
name: 'HomeView', |
|||
components: {HomeFunction, Dashboard} |
|||
} |
|||
</script> |
|||
@ -1,205 +0,0 @@ |
|||
<template> |
|||
<div> |
|||
<el-container> |
|||
<el-header height="92" class="home-header-view"> |
|||
<el-row type="flex" align="middle" justify="center"> |
|||
<el-col :span="4" :offset="1"> |
|||
<img src="@/assets/images/indexLogo.png" class="header-logo-img" |
|||
@click="$router.push({path:'/'})" |
|||
> |
|||
</el-col> |
|||
<el-col :span="10"> |
|||
<el-menu :default-active="menuIndex" mode="horizontal" |
|||
text-color="#205BB5" |
|||
active-text-color="#205BB5" |
|||
@select="activeMenuHandle" |
|||
> |
|||
<el-menu-item v-for="(item, index) in menuRouters" |
|||
:key="oldIndex" |
|||
:index="item.routerPath" |
|||
class="menu-item" |
|||
> |
|||
{{ item.title }} |
|||
</el-menu-item> |
|||
</el-menu> |
|||
</el-col> |
|||
<el-col :span="1"> |
|||
<!-- <el-button round>升级</el-button>--> |
|||
</el-col> |
|||
<el-col :span="1"> |
|||
<div style="display: flex; |
|||
align-items: center; |
|||
justify-content: center;" |
|||
> |
|||
<!-- <svg-icon name="loginWx" style="width: 24px; height: 24px;" />--> |
|||
</div> |
|||
</el-col> |
|||
<el-col :span="1"> |
|||
<el-link href="https://gitee.com/TDuckApp/tduck-platform/wikis/%E6%9C%AC%E5%9C%B0%E8%BF%90%E8%A1%8C?sort_id=3681729" target="_blank">帮助</el-link> |
|||
</el-col> |
|||
<el-col :span="3"> |
|||
<el-popover |
|||
placement="bottom-end" |
|||
width="200" |
|||
trigger="click" |
|||
> |
|||
<div class="user-person-menu"> |
|||
<div> |
|||
<p v-if="getUserInfo" class="nick-name">{{ getUserInfo.name }}</p> |
|||
</div> |
|||
<div class="person-menu-divider" /> |
|||
<div> |
|||
<p class="person-menu-item" @click="$router.push({path: '/home/member'})"> |
|||
<font-icon class="fab fa-get-pocket" /> |
|||
我的账户 |
|||
</p> |
|||
<div class="person-menu-divider" /> |
|||
<p class="person-menu-item" @click="logoutHandle"> |
|||
<font-icon class="fas fa-sign-out" /> |
|||
退出登录 |
|||
</p> |
|||
</div> |
|||
</div> |
|||
<div slot="reference" style="display: flex; align-items: center; justify-content: center;"> |
|||
<img v-if="getUserInfo" :src="getUserInfo.avatar" class="user-avatar"> |
|||
</div> |
|||
</el-popover> |
|||
</el-col> |
|||
</el-row> |
|||
</el-header> |
|||
<el-main class="home-main-view"> |
|||
<router-view /> |
|||
</el-main> |
|||
</el-container> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
import store from '@/store/index.js' |
|||
import FontIcon from '@/components/FontIcon' |
|||
import router from '@/router' |
|||
import {openUrl, checkIsUrl} from '@/utils/index' |
|||
|
|||
export default { |
|||
name: 'Home', |
|||
components: {FontIcon}, |
|||
data() { |
|||
return { |
|||
menuIndex: null, |
|||
menuRouters: [ |
|||
{ |
|||
routerPath: 'https://gitee.com/TDuckApp/tduck-platform?time=1', |
|||
title: '免费模板' |
|||
}, |
|||
{ |
|||
routerPath: 'https://gitee.com/TDuckApp/tduck-platform', |
|||
title: '开源项目' |
|||
}, |
|||
{ |
|||
routerPath: 'https://gitee.com/TDuckApp/tduck-platform/issues', |
|||
title: '提出建议' |
|||
} |
|||
] |
|||
} |
|||
}, |
|||
computed: { |
|||
getStore() { |
|||
return store |
|||
}, |
|||
getUserInfo() { |
|||
let user = JSON.parse(this.getStore.getters['user/userInfo']) |
|||
return user |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.menuIndex = this.$route.path |
|||
}, |
|||
methods: { |
|||
activeMenuHandle(routerPath) { |
|||
if (checkIsUrl(routerPath)) { |
|||
openUrl(routerPath) |
|||
} else { |
|||
this.menuIndex = routerPath |
|||
} |
|||
}, |
|||
logoutHandle() { |
|||
this.$confirm('您确定要退出登录吗?', '退出确认', { |
|||
confirmButtonText: '确定', |
|||
cancelButtonText: '取消', |
|||
type: 'warning' |
|||
}).then(() => { |
|||
this.$store.dispatch('user/logout').then(() => { |
|||
router.push({ |
|||
path: '/login', |
|||
query: { |
|||
redirect: router.currentRoute.fullPath |
|||
} |
|||
}) |
|||
}) |
|||
}).catch(() => { |
|||
|
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss" scoped> |
|||
|
|||
.menu-item { |
|||
line-height: 80px; |
|||
height: 80px; |
|||
text-align: left; |
|||
font-weight: 550; |
|||
color: rgba(32, 91, 181, 100); |
|||
font-size: 20px; |
|||
&:hover { |
|||
cursor: pointer; |
|||
} |
|||
} |
|||
.el-menu.el-menu--horizontal { |
|||
border-bottom: none; |
|||
} |
|||
.home-header-view { |
|||
line-height: 92px; |
|||
height: 92px; |
|||
min-width: 1024px; |
|||
background-color: rgba(255, 255, 255, 100); |
|||
color: rgba(16, 16, 16, 100); |
|||
font-size: 14px; |
|||
text-align: center; |
|||
.header-logo-img { |
|||
width: 90%; |
|||
height: 90%; |
|||
float: left; |
|||
} |
|||
} |
|||
.user-person-menu { |
|||
.nick-name { |
|||
height: 16px; |
|||
color: rgba(70, 70, 70, 86); |
|||
font-size: 14px; |
|||
line-height: 16px; |
|||
text-align: left; |
|||
} |
|||
.person-menu-item { |
|||
color: rgba(70, 70, 70, 86); |
|||
font-size: 14px; |
|||
text-align: left; |
|||
} |
|||
.person-menu-item:hover { |
|||
cursor: pointer; |
|||
color: rgba(32, 91, 181, 100); |
|||
} |
|||
} |
|||
.user-avatar { |
|||
width: 50px; |
|||
height: 50px; |
|||
border-radius: 100px; |
|||
cursor: pointer; |
|||
} |
|||
.home-main-view { |
|||
height: calc(100vh - 92px); |
|||
min-width: 1024px; |
|||
background-color: #f7f7f7; |
|||
padding: 0; |
|||
} |
|||
</style> |
|||
@ -1,13 +0,0 @@ |
|||
<template> |
|||
<div id="enterprise"> |
|||
企业部署 |
|||
</div> |
|||
</template> |
|||
<script> |
|||
export default { |
|||
name: 'Enterprise', |
|||
data() { |
|||
return { } |
|||
} |
|||
} |
|||
</script> |
|||
@ -1,270 +0,0 @@ |
|||
<!--<template>--> |
|||
<!-- <div class="introduction">--> |
|||
<!-- <div class="introduction-body">--> |
|||
<!-- <div class="view-container">--> |
|||
<!-- <div class="view-container-content">--> |
|||
<!-- <el-row type="flex" justify="center" align="middle">--> |
|||
<!-- <el-col :span="10" :offset="1">--> |
|||
<!-- <div class="view-container-content">--> |
|||
<!-- <p class="body-title">TDuck - 填鸭表单</p>--> |
|||
<!-- <p class="body-slogan">有你所想,有你所得。</p>--> |
|||
<!-- <p class="body-sloganEn">TDuck - Have what you want, get you income.</p>--> |
|||
<!-- <p class="body-detail">TDuck填鸭,是一款在线制作表单的应用工具,通过填鸭表单可以收集任何你想得到的信息。</p>--> |
|||
<!-- <p class="body-detail">简单易用,灵活的反馈数据筛选;统计图表一目了然</p>--> |
|||
<!-- <div>--> |
|||
<!-- <el-button class="body-btn primary" type="primary"--> |
|||
<!-- @click="$router.push({path:'/login'})"--> |
|||
<!-- >--> |
|||
<!-- 免费使用--> |
|||
<!-- </el-button>--> |
|||
<!-- <el-button class="body-btn">在线体验</el-button>--> |
|||
<!-- </div>--> |
|||
<!-- </div>--> |
|||
<!-- </el-col>--> |
|||
<!-- <el-col :span="10">--> |
|||
<!-- <div>--> |
|||
<!-- <img class="body-right-img"--> |
|||
<!-- src="@/assets/images/official/v2_q2woer.png"--> |
|||
<!-- >--> |
|||
<!-- </div>--> |
|||
<!-- </el-col>--> |
|||
<!-- </el-row>--> |
|||
<!-- </div>--> |
|||
<!-- </div>--> |
|||
<!-- <el-divider />--> |
|||
<!-- <div class="view-container">--> |
|||
<!-- <div class="view-container-content">--> |
|||
<!-- <el-row type="flex" justify="center" align="middle">--> |
|||
<!-- <el-col :span="10" :offset="1">--> |
|||
<!-- <div>--> |
|||
<!-- <img class="body-right-img"--> |
|||
<!-- src="@/assets/images/official/v2_q2wstp.png"--> |
|||
<!-- >--> |
|||
<!-- </div>--> |
|||
<!-- </el-col>--> |
|||
<!-- <el-col :offset="1" :span="12">--> |
|||
<!-- <div>--> |
|||
<!-- <p style="font-size: 28px;">杂乱的工作界面也会影响心情鸭!</p>--> |
|||
<!-- <p class="body-title">TDuck,化繁为简,给你最好的体验。</p>--> |
|||
<!-- <p class="body-sloganEn">TDuck -So Easy。</p>--> |
|||
<!-- <p class="body-detail">·超多表单组件供您选择</p>--> |
|||
<!-- <p class="body-detail">·逻辑设置,让您的表单更灵活</p>--> |
|||
<!-- <p class="body-detail"> ·Element UI,饿了么同款UI组建,表单也要美美哒</p>--> |
|||
<!-- <p class="body-detail"> ·多样化数据统计;懂你,胜过另一半</p>--> |
|||
<!-- <div style="width: 42px;" class="title-divider-line" />--> |
|||
<!-- </div>--> |
|||
<!-- </el-col>--> |
|||
<!-- </el-row>--> |
|||
<!-- </div>--> |
|||
<!-- </div>--> |
|||
<!-- <el-divider />--> |
|||
<!-- <div class="view-container">--> |
|||
<!-- <div class="view-container-content" style="width: 80%;">--> |
|||
<!-- <el-row type="flex" align="middle">--> |
|||
<!-- <el-col :span="10" :offset="5">--> |
|||
<!-- <p style="font-size: 28px;">TDuck - 填鸭表单</p>--> |
|||
<!-- <p class="body-title">社区版 / 开源版 / 企业部署 </p>--> |
|||
<!-- <p class="body-detail">Technology changes the world ——用技术改变世界</p>--> |
|||
<!-- </el-col>--> |
|||
<!-- <el-col :span="8">--> |
|||
<!-- <p class="body-detail"> ·人人都是我们的用户 </p>--> |
|||
<!-- <p class="body-detail">·基于Apache开源协议,开发者的福音</p>--> |
|||
<!-- <p class="body-detail">·成熟的技术支持,企业表单问卷系统解决方案</p>--> |
|||
<!-- <p class="body-detail">·更新速度快,总为您奉上不一样的惊喜</p>--> |
|||
<!-- <div style="width: 112px;" class="title-divider-line" />--> |
|||
<!-- <p style="font-size: 20px; font-weight: 550;">联系我们</p>--> |
|||
<!-- </el-col>--> |
|||
<!-- </el-row>--> |
|||
<!-- </div>--> |
|||
<!-- <div>--> |
|||
<!-- <img style="height: 478px;"--> |
|||
<!-- src="@/assets/images/official/v2_q2wxu6.gif"--> |
|||
<!-- >--> |
|||
<!-- </div>--> |
|||
<!-- </div>--> |
|||
<!-- <div class="introduction-footer">--> |
|||
<!-- <el-row>--> |
|||
<!-- <el-col :span="3" :offset="2">--> |
|||
<!-- <p class="title">关于我们</p>--> |
|||
<!-- <p class="subtitle" style="width: 182px;">--> |
|||
<!-- TDuck — 是一款能够帮助--> |
|||
<!-- 你进行信息收集、市场开拓、--> |
|||
<!-- 客户挖掘并展开持续营销活--> |
|||
<!-- 动的管理平台。--> |
|||
<!-- </p>--> |
|||
<!-- </el-col>--> |
|||
<!-- <el-col :span="3">--> |
|||
<!-- <p class="title"> 项目地址</p>--> |
|||
<!-- <p class="subtitle">--> |
|||
<!-- <svg-icon name="gitee" style="width: 14px; height: 14px;" />--> |
|||
<!-- <a href="https://gitee.com/TDuckApp/tduck-platform" target="_blank"> 码云</a>--> |
|||
<!-- </p>--> |
|||
<!-- <p class="subtitle">--> |
|||
<!-- <svg-icon name="github" style="width: 12px; height: 12px;" />--> |
|||
<!-- <a href="https://github.com/TDuckCloud/tduck-platform" target="_blank"> Github</a>--> |
|||
<!-- </p>--> |
|||
<!-- </el-col>--> |
|||
<!-- <el-col :span="4">--> |
|||
<!-- <p class="title"> 联系方式</p>--> |
|||
<!-- <p class="subtitle">--> |
|||
<!-- <i class="el-icon-message" />--> |
|||
<!-- pr@tduckapp.com--> |
|||
<!-- </p>--> |
|||
<!-- <p class="subtitle">--> |
|||
<!-- <i class="el-icon-phone" /> +86 15080929435--> |
|||
<!-- </p>--> |
|||
<!-- </el-col>--> |
|||
<!-- <el-col :span="3">--> |
|||
<!-- <p class="title"> 友情地址</p>--> |
|||
<!-- <p class="subtitle">--> |
|||
<!-- <a href="https://element.eleme.cn/#/zh-CN/" target="_blank">Element UI</a>--> |
|||
<!-- </p>--> |
|||
<!-- <p class="subtitle">--> |
|||
<!-- <a href="https://gitee.com/mrhj/form-generator" target="_blank"> form-generator</a>--> |
|||
<!-- </p>--> |
|||
<!-- </el-col>--> |
|||
<!-- <el-col :span="3" :offset="3">--> |
|||
<!-- <img style="width: 130px; height: 130px;"--> |
|||
<!-- src="https://freebrio.oss-cn-shanghai.aliyuncs.com/t/v2_q2x0aj.png"--> |
|||
<!-- >--> |
|||
<!-- <p class="title">微信公众号/关注我们</p>--> |
|||
<!-- </el-col>--> |
|||
<!-- </el-row>--> |
|||
<!-- <el-divider />--> |
|||
<!-- <div class="copyright">--> |
|||
<!-- <a target="_blank" href="https://www.upyun.com/?utm_source=lianmeng&utm_medium=referral">--> |
|||
<!-- <img--> |
|||
<!-- style="height: 30px;"--> |
|||
<!-- src="http://tduck.test.upcdn.net/%E5%8F%88%E6%8B%8D%E4%BA%91_logo2.png"--> |
|||
<!-- >--> |
|||
<!-- </a>--> |
|||
<!-- <p class="subtitle" style="text-align: center;">--> |
|||
<!-- 本站由 又拍云 提供CDN加速/云储存服务--> |
|||
<!-- </p>--> |
|||
<!-- <p class="subtitle" style="text-align: center;">--> |
|||
<!-- Copyright © 2021 TDuckApp. All Rights Reserved. 湘ICP备18023961号-2 版权所有--> |
|||
<!-- </p>--> |
|||
<!-- </div>--> |
|||
<!-- </div>--> |
|||
<!-- </div>--> |
|||
<!-- </div>--> |
|||
<!--</template>--> |
|||
<!--<script>--> |
|||
|
|||
<!--export default {--> |
|||
<!-- data() {--> |
|||
<!-- return {}--> |
|||
<!-- },--> |
|||
<!-- computed: {},--> |
|||
<!-- watch: {},--> |
|||
<!-- mounted() {--> |
|||
<!-- }--> |
|||
<!--}--> |
|||
<!--</script>--> |
|||
<!--<style scoped>--> |
|||
<!--.body-btn {--> |
|||
<!-- margin: 30px 20px 0 0;--> |
|||
<!-- font-size: 20px;--> |
|||
<!-- padding-left: 20px;--> |
|||
<!-- padding-right: 20px;--> |
|||
<!--}--> |
|||
<!--.header-btn,--> |
|||
<!--.body-btn {--> |
|||
<!-- color: #205bb5;--> |
|||
<!-- border-color: #205bb5;--> |
|||
<!--}--> |
|||
<!--.primary {--> |
|||
<!-- color: #fff;--> |
|||
<!-- background-color: #205bb5;--> |
|||
<!--}--> |
|||
<!--.header-btn:focus,--> |
|||
<!--.header-btn:hover,--> |
|||
<!--.body-btn:focus,--> |
|||
<!--.body-btn:hover {--> |
|||
<!-- border-color: #205bb5;--> |
|||
<!-- color: #205bb5;--> |
|||
<!--}--> |
|||
<!--.primary:focus,--> |
|||
<!--.primary:hover {--> |
|||
<!-- border-color: #205bb5;--> |
|||
<!-- color: #fff;--> |
|||
<!--}--> |
|||
<!--.introduction {--> |
|||
<!-- background: url('~@/assets/images/official/offcial-bg01.png') repeat-x;--> |
|||
<!--}--> |
|||
<!--.introduction-body {--> |
|||
<!-- /* padding-top: 112px; */--> |
|||
<!--}--> |
|||
<!--.view-container {--> |
|||
<!-- height: 800px;--> |
|||
<!-- display: flex;--> |
|||
<!-- justify-content: center;--> |
|||
<!-- align-content: center;--> |
|||
<!-- align-items: center;--> |
|||
<!-- justify-items: center;--> |
|||
<!-- flex-direction: column;--> |
|||
<!--}--> |
|||
<!--.view-container-content {--> |
|||
<!-- background-color: transparent;--> |
|||
<!--}--> |
|||
<!--.view-container-content p {--> |
|||
<!-- color: #205bb5;--> |
|||
<!--}--> |
|||
<!--.body-title {--> |
|||
<!-- font-size: 35px;--> |
|||
<!-- font-weight: 900;--> |
|||
<!-- line-height: 25px;--> |
|||
<!-- margin: 0 0 30px 0;--> |
|||
<!--}--> |
|||
<!--.body-slogan {--> |
|||
<!-- font-size: 45px;--> |
|||
<!-- font-weight: 900;--> |
|||
<!-- line-height: 45px;--> |
|||
<!-- margin: 0 0 5px 0;--> |
|||
<!--}--> |
|||
<!--.body-sloganEn {--> |
|||
<!-- line-height: 15px;--> |
|||
<!-- margin: 0 0 25px 0;--> |
|||
<!--}--> |
|||
<!--.body-detail {--> |
|||
<!-- line-height: 15px;--> |
|||
<!-- margin: 0 0 10px 0;--> |
|||
<!--}--> |
|||
<!--.body-sloganEn,--> |
|||
<!--.body-detail {--> |
|||
<!-- font-size: 15px;--> |
|||
<!--}--> |
|||
<!--.body-right-img {--> |
|||
<!-- /* height: 665px; */--> |
|||
<!-- width: 100%;--> |
|||
<!-- height: 100%;--> |
|||
<!--}--> |
|||
<!--.title-divider-line {--> |
|||
<!-- height: 3px;--> |
|||
<!-- line-height: 20px;--> |
|||
<!-- background-color: rgba(32, 91, 181, 100);--> |
|||
<!-- text-align: center;--> |
|||
<!-- border: 1px solid rgba(255, 255, 255, 100);--> |
|||
<!--}--> |
|||
<!--.introduction-footer {--> |
|||
<!-- height: 420px;--> |
|||
<!-- line-height: 20px;--> |
|||
<!-- background-color: rgba(32, 91, 181, 100);--> |
|||
<!-- text-align: center;--> |
|||
<!-- border: 1px solid rgba(187, 187, 187, 100);--> |
|||
<!-- padding: 69px 0 0 0;--> |
|||
<!--}--> |
|||
<!--.introduction-footer .title {--> |
|||
<!-- color: rgba(255, 255, 255, 100);--> |
|||
<!-- font-size: 20px;--> |
|||
<!-- text-align: left;--> |
|||
<!--}--> |
|||
<!--.introduction-footer .subtitle {--> |
|||
<!-- color: rgba(255, 255, 255, 100);--> |
|||
<!-- font-size: 14px;--> |
|||
<!-- text-align: left;--> |
|||
<!--}--> |
|||
<!--.copyright {--> |
|||
<!-- height: 95px;--> |
|||
<!--}--> |
|||
<!--</style>--> |
|||
@ -1,13 +0,0 @@ |
|||
<template> |
|||
<div id="proposal"> |
|||
提出建议 |
|||
</div> |
|||
</template> |
|||
<script> |
|||
export default { |
|||
name: 'Proposal', |
|||
data() { |
|||
return { } |
|||
} |
|||
} |
|||
</script> |
|||
@ -1,13 +0,0 @@ |
|||
<template> |
|||
<div id="sources"> |
|||
开源版本 |
|||
</div> |
|||
</template> |
|||
<script> |
|||
export default { |
|||
name: 'Sources', |
|||
data() { |
|||
return { } |
|||
} |
|||
} |
|||
</script> |
|||
Loading…
Reference in new issue