master
yujialong 4 years ago
commit 1e27956393
  1. 3
      .browserslistrc
  2. 22
      .gitignore
  3. 6
      .prettierrc
  4. 21
      LICENSE
  5. 197
      README.md
  6. 196
      README_EN.md
  7. 5
      babel.config.js
  8. 13480
      package-lock.json
  9. 37
      package.json
  10. 5
      postcss.config.js
  11. 18
      public/index.html
  12. BIN
      screenshots/wms1.png
  13. BIN
      screenshots/wms2.png
  14. BIN
      screenshots/wms3.png
  15. 23
      src/App.vue
  16. 39
      src/api/index.js
  17. BIN
      src/assets/font/YouSheBiaoTiHei.ttf
  18. BIN
      src/assets/img/account.png
  19. BIN
      src/assets/img/arrow-down.png
  20. BIN
      src/assets/img/backstage-bg.png
  21. BIN
      src/assets/img/course-bg.png
  22. BIN
      src/assets/img/info-bg.png
  23. BIN
      src/assets/img/login_bg.png
  24. BIN
      src/assets/img/logo-fill.png
  25. BIN
      src/assets/img/logo-full.png
  26. BIN
      src/assets/img/logo.png
  27. BIN
      src/assets/img/match-banner.png
  28. BIN
      src/assets/img/match-bg.png
  29. BIN
      src/assets/img/none.png
  30. BIN
      src/assets/img/password.png
  31. BIN
      src/assets/img/red-dot.png
  32. BIN
      src/assets/img/search.png
  33. BIN
      src/assets/img/station1.png
  34. BIN
      src/assets/img/station2.png
  35. BIN
      src/assets/img/station3.png
  36. BIN
      src/assets/img/station4.png
  37. BIN
      src/assets/img/station5.png
  38. BIN
      src/assets/img/system-fullname.png
  39. BIN
      src/assets/img/system-name.png
  40. BIN
      src/assets/img/upload.png
  41. 124
      src/components/pdf/index.vue
  42. 30
      src/i18n/index.js
  43. 42
      src/layouts/footer/index.vue
  44. 141
      src/layouts/header/index.vue
  45. 92
      src/layouts/home/index.vue
  46. 79
      src/layouts/navbar/index.vue
  47. 186
      src/layouts/tags/index.vue
  48. 25
      src/libs/auth/generateBtnPermission.js
  49. 6
      src/libs/bus.js
  50. 202
      src/libs/core.js
  51. 16
      src/libs/resize/index.js
  52. 34
      src/libs/route/addRoutes.js
  53. 26
      src/libs/route/generateRoutes.js
  54. 6
      src/libs/route/resetRouter.js
  55. 42
      src/main.js
  56. 56
      src/pages/403.vue
  57. 56
      src/pages/404.vue
  58. 134
      src/pages/article.vue
  59. 227
      src/pages/course.vue
  60. 452
      src/pages/courseSection.vue
  61. 111
      src/pages/dashboard.vue
  62. 46
      src/pages/i18n.vue
  63. 225
      src/pages/icon.vue
  64. 302
      src/pages/information.vue
  65. 215
      src/pages/login.vue
  66. 496
      src/pages/match.vue
  67. 370
      src/pages/matchDetail.vue
  68. 439
      src/pages/personalCenter.vue
  69. 311
      src/pages/registerForm.vue
  70. 137
      src/pages/station.vue
  71. 1
      src/plugins/aliplayer/aliplayer-min.css
  72. 2
      src/plugins/aliplayer/aliplayer-min.js
  73. 25
      src/plugins/auth/index.js
  74. 14
      src/plugins/index.js
  75. 367
      src/plugins/requests/index.js
  76. 18
      src/plugins/throttle/index.js
  77. 22
      src/router/index.js
  78. 28
      src/router/permission.js
  79. 100
      src/router/routes.js
  80. 21
      src/setting.env.js
  81. 116
      src/setting.js
  82. 110
      src/store/index.js
  83. 183
      src/styles/common.scss
  84. 7
      src/styles/default/index.scss
  85. 539
      src/styles/font/icon/demo.css
  86. 446
      src/styles/font/icon/demo_index.html
  87. 71
      src/styles/font/icon/iconfont.css
  88. BIN
      src/styles/font/icon/iconfont.eot
  89. 1
      src/styles/font/icon/iconfont.js
  90. 93
      src/styles/font/icon/iconfont.json
  91. 62
      src/styles/font/icon/iconfont.svg
  92. BIN
      src/styles/font/icon/iconfont.ttf
  93. BIN
      src/styles/font/icon/iconfont.woff
  94. BIN
      src/styles/font/icon/iconfont.woff2
  95. 3
      src/styles/font/iconfont.css
  96. 6
      src/styles/index.scss
  97. 14
      src/styles/layout/index.scss
  98. 7
      src/styles/lib/_background.scss
  99. 78
      src/styles/lib/_border.scss
  100. 56
      src/styles/lib/_box.scss
  101. Some files were not shown because too many files have changed in this diff Show More

@ -0,0 +1,3 @@
> 1%
last 2 versions
not ie <= 8

22
.gitignore vendored

@ -0,0 +1,22 @@
.DS_Store
node_modules
/dist
example.html
favicon.ico
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw*

@ -0,0 +1,6 @@
{
"tabWidth": 4,
"singleQuote": true,
"trailingComma": "none",
"printWidth": 140
}

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2016-2019 vue-manage-system
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

@ -0,0 +1,197 @@
# vue-manage-system
<a href="https://github.com/vuejs/vue">
<img src="https://img.shields.io/badge/vue-2.6.10-brightgreen.svg" alt="vue">
</a>
<a href="https://github.com/ElemeFE/element">
<img src="https://img.shields.io/badge/element--ui-2.8.2-brightgreen.svg" alt="element-ui">
</a>
<a href="https://github.com/lin-xin/vue-manage-system/blob/master/LICENSE">
<img src="https://img.shields.io/github/license/mashape/apistatus.svg" alt="license">
</a>
<a href="https://github.com/lin-xin/vue-manage-system/releases">
<img src="https://img.shields.io/github/release/lin-xin/vue-manage-system.svg" alt="GitHub release">
</a>
<a href="https://lin-xin.gitee.io/example/work/#/donate">
<img src="https://img.shields.io/badge/%24-donate-ff69b4.svg" alt="donate">
</a>
基于 Vue + Element UI 的后台管理系统解决方案。[线上地址](https://lin-xin.gitee.io/example/work/)
> React + Ant Design 的版本正在开发中,仓库地址:[react-manage-system](https://github.com/lin-xin/react-manage-system)
[English document](https://github.com/lin-xin/manage-system/blob/master/README_EN.md)
## 项目截图
### 登录
![Image text](https://github.com/lin-xin/manage-system/raw/master/screenshots/wms3.png)
### 默认皮肤
![Image text](https://github.com/lin-xin/manage-system/raw/master/screenshots/wms1.png)
### 浅绿色皮肤
![Image text](https://github.com/lin-xin/manage-system/raw/master/screenshots/wms2.png)
## 赞赏
请作者喝杯咖啡吧!(微信号:linxin_20)
![微信扫一扫](https://lin-xin.gitee.io/images/weixin.jpg)
## 特别鸣谢
- [实验楼](https://www.shiyanlou.com?source=vue-manage-system)
## 前言
该方案作为一套多功能的后台框架模板,适用于绝大部分的后台管理系统(Web Management System)开发。基于 vue.js,使用 vue-cli3 脚手架,引用 Element UI 组件库,方便开发快速简洁好看的组件。分离颜色样式,支持手动切换主题色,而且很方便使用自定义主题色。
## 功能
- [x] Element UI
- [x] 登录/注销
- [x] Dashboard
- [x] 表格
- [x] Tab 选项卡
- [x] 表单
- [x] 图表 :bar_chart:
- [x] 富文本编辑器
- [x] markdown 编辑器
- [x] 图片拖拽/裁剪上传
- [x] 支持切换主题色 :sparkles:
- [x] 列表拖拽排序
- [x] 权限测试
- [x] 404 / 403
- [x] 三级菜单
- [x] 自定义图标
- [x] 可拖拽弹窗
- [x] 国际化
## 安装步骤
```
git clone https://github.com/lin-xin/vue-manage-system.git // 把模板下载到本地
cd vue-manage-system // 进入模板目录
npm install // 安装项目依赖,等待安装完成之后,安装失败可用 cnpm 或 yarn
// 开启服务器,浏览器访问 http://localhost:8080
npm run serve
// 执行构建命令,生成的dist文件夹放在服务器下即可访问
npm run build
```
## 组件使用说明与演示
### vue-schart
vue.js 封装 sChart.js 的图表组件。访问地址:[vue-schart](https://github.com/linxin/vue-schart)
<p><a href="https://www.npmjs.com/package/vue-schart"><img src="https://img.shields.io/npm/dm/vue-schart.svg" alt="Downloads"></a></p>
```html
<template>
<div>
<schart class="wrapper" canvasId="myCanvas" :options="options"></schart>
</div>
</template>
<script>
import Schart from 'vue-schart'; // 导入Schart组件
export default {
data() {
return {
options: {
type: 'bar',
title: {
text: '最近一周各品类销售图'
},
labels: ['周一', '周二', '周三', '周四', '周五'],
datasets: [
{
label: '家电',
data: [234, 278, 270, 190, 230]
},
{
label: '百货',
data: [164, 178, 190, 135, 160]
},
{
label: '食品',
data: [144, 198, 150, 235, 120]
}
]
}
};
},
components: {
Schart
}
};
</script>
<style>
.wrapper {
width: 7rem;
height: 5rem;
}
</style>
```
## 其他注意事项
### 一、如果我不想用到上面的某些组件呢,那我怎么在模板中删除掉不影响到其他功能呢?
举个栗子,我不想用 Vue-Quill-Editor 这个组件,那我需要分四步走。
第一步:删除该组件的路由,在目录 src/router/index.js 中,找到引入改组件的路由,删除下面这段代码。
```JavaScript
{
// 富文本编辑器组件
path: '/editor',
component: resolve => require(['../components/page/VueEditor.vue'], resolve)
},
```
第二步:删除引入该组件的文件。在目录 src/components/page/ 删除 VueEditor.vue 文件。
第三步:删除该页面的入口。在目录 src/components/common/Sidebar.vue 中,找到该入口,删除下面这段代码。
```js
{
index: 'editor',
title: '富文本编辑器'
},
```
第四步:卸载该组件。执行以下命令:
npm un vue-quill-editor -S
完成。
### 二、如何切换主题色呢?
第一步:打开 src/main.js 文件,找到引入 element 样式的地方,换成浅绿色主题。
```javascript
import 'element-ui/lib/theme-default/index.css'; // 默认主题
// import './assets/css/theme-green/index.css'; // 浅绿色主题
```
第二步:打开 src/App.vue 文件,找到 style 标签引入样式的地方,切换成浅绿色主题。
```javascript
@import "./assets/css/main.css";
@import "./assets/css/color-dark.css"; /*深色主题*/
/*@import "./assets/css/theme-green/color-green.css"; !*浅绿色主题*!*/
```
第三步:打开 src/components/common/Sidebar.vue 文件,找到 el-menu 标签,把 background-color/text-color/active-text-color 属性去掉即可。
## License
[MIT](https://github.com/lin-xin/vue-manage-system/blob/master/LICENSE)

@ -0,0 +1,196 @@
# vue-manage-system
<a href="https://github.com/vuejs/vue">
<img src="https://img.shields.io/badge/vue-2.6.10-brightgreen.svg" alt="vue">
</a>
<a href="https://github.com/ElemeFE/element">
<img src="https://img.shields.io/badge/element--ui-2.8.2-brightgreen.svg" alt="element-ui">
</a>
<a href="https://github.com/lin-xin/vue-manage-system/blob/master/LICENSE">
<img src="https://img.shields.io/github/license/mashape/apistatus.svg" alt="license">
</a>
<a href="https://github.com/lin-xin/vue-manage-system/releases">
<img src="https://img.shields.io/github/release/lin-xin/vue-manage-system.svg" alt="GitHub release">
</a>
<a href="https://lin-xin.gitee.io/example/work/#/donate">
<img src="https://img.shields.io/badge/%24-donate-ff69b4.svg" alt="donate">
</a>
The web management system solution based on Vue2 and Element-UI。[live demo](https://lin-xin.gitee.io/example/work/)
## Donation
![WeChat](https://lin-xin.gitee.io/images/weixin.jpg)
## Preface
The scheme as a set of multi-function background frame templates, suitable for most of the WEB management system development. Convenient development fast simple good components based on Vue2 and Element-UI. Color separation of color style, support manual switch themes, and it is convenient to use a custom theme color.
## Function
- [x] Element-UI
- [x] Login/Logout
- [x] Dashboard
- [x] Table
- [x] Tabs
- [x] From
- [x] Chart :bar_chart:
- [x] Editor
- [x] Markdown
- [x] Upload pictures by clipping or dragging
- [x] Support manual switch themes :sparkles:
- [x] List drag sort
- [x] Permission
- [x] 404 / 403
- [x] Three level menu
- [x] Custom icon
## Installation steps
git clone https://github.com/lin-xin/vue-manage-system.git // Clone templates
cd vue-manage-system // Enter template directory
npm install // Installation dependency
## Local development
// Open server and access http://localhost:8080 in browser
npm run serve
## Constructing production
// Constructing project
npm run build
## Component description and presentation
### vue-schart
Vue.js wrapper for sChart.js. Github : [vue-schart](https://github.com/linxin/vue-schart)
```html
<template>
<div>
<schart class="wrapper" canvasId="myCanvas" :options="options"></schart>
</div>
</template>
<script>
import Schart from 'vue-schart'; // 导入Schart组件
export default {
data() {
return {
options: {
type: 'bar',
title: {
text: '最近一周各品类销售图'
},
labels: ['周一', '周二', '周三', '周四', '周五'],
datasets: [
{
label: '家电',
data: [234, 278, 270, 190, 230]
},
{
label: '百货',
data: [164, 178, 190, 135, 160]
},
{
label: '食品',
data: [144, 198, 150, 235, 120]
}
]
}
};
},
components: {
Schart
}
};
</script>
<style>
.wrapper {
width: 7rem;
height: 5rem;
}
</style>
```
### element-ui
A desktop component library based on vue.js2.0 . Github : [element](http://element.eleme.io/#/zh-CN/component/layout)
### Vue-Quill-Editor
Quill editor component for Vue2. Github : [vue-quill-editor](https://github.com/surmon-china/vue-quill-editor)
### mavonEditor
A markdown editor based on Vue that supports a variety of personalized features. Github: [mavonEditor](https://github.com/hinesboy/mavonEditor)
### vue-cropperjs
A Vue wrapper component for cropperjs. Github: [vue-cropperjs](https://github.com/Agontuk/vue-cropperjs)
## Notice
### 一、If I don't want to use some components, how can I delete it?
For example, I don't want to use the Vue-Quill-Editor component, I need to take four steps.
The first step to remove the component of the routing. Enter 'src/router/index.js' and delete the code below.
```JavaScript
{
path: '/editor',
component: resolve => require(['../components/page/VueEditor.vue'], resolve)
},
```
Second,delete the component files. Enter 'src/components/page/' and delete 'VueEditor.vue' file.
The third step is to delete the entry. Enter 'src/components/common/Sidebar.vue' and delete the code below.
```js
{
index: 'editor',
title: '富文本编辑器'
},
```
Finally, uninstall this component.
npm un vue-quill-editor -S
Complete!
### 二、How to switch themes?
The first step to enter 'src/main.js' and change into green theme.
```javascript
import 'element-ui/lib/theme-default/index.css'; // default theme
// import '../static/css/theme-green/index.css'; // green theme
```
The second step to enter 'src/App.vue' and change into green theme.
```javascript
@import "../static/css/main.css";
@import "../static/css/color-dark.css"; /*深色主题*/
/*@import "../static/css/theme-green/color-green.css"; !*浅绿色主题*!*/
```
Finally,enter 'src/components/common/Sidebar.vue' and find el-menu Tags,delete 'background-color/text-color/active-text-color'。
## Screenshot
### Default theme
![Image text](https://github.com/lin-xin/manage-system/raw/master/screenshots/wms1.png)
### Green theme
![Image text](https://github.com/lin-xin/manage-system/raw/master/screenshots/wms2.png)
## License
[MIT](https://github.com/lin-xin/vue-manage-system/blob/master/LICENSE)

@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/app'
]
}

13480
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -0,0 +1,37 @@
{
"name": "vue-manage-system",
"version": "4.2.0",
"private": true,
"scripts": {
"dev": "npm run serve",
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
},
"dependencies": {
"axios": "^0.18.0",
"babel-polyfill": "^6.26.0",
"echarts": "^4.8.0",
"element-theme": "^2.0.1",
"element-ui": "^2.13.0",
"mavon-editor": "^2.6.17",
"postcss-px2rem": "^0.3.0",
"px2rem-loader": "^0.1.9",
"vue": "^2.6.10",
"vue-cropperjs": "^3.0.0",
"vue-i18n": "^8.10.0",
"vue-pdf": "^4.2.0",
"vue-quill-editor": "^3.0.6",
"vue-router": "^3.0.3",
"vue-schart": "^2.0.0",
"vuedraggable": "^2.17.0",
"vuex": "^3.4.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.9.0",
"@vue/cli-service": "^3.9.0",
"element-theme-chalk": "^2.13.0",
"node-sass": "^4.13.0",
"sass-loader": "^8.0.0",
"vue-template-compiler": "^2.6.10"
}
}

@ -0,0 +1,5 @@
module.exports = {
plugins: {
autoprefixer: {}
}
}

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="//at.alicdn.com/t/font_830376_qzecyukz0s.css">
<title>电子竞技在线教学资源管理平台</title>
</head>
<body>
<noscript>
<strong>We're sorry but vms doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

@ -0,0 +1,23 @@
<template>
<div id="app" >
<router-view></router-view>
</div>
</template>
<script>
import Setting from '@/setting';
export default {
name: 'App',
created () {
//sessionStorage
if (sessionStorage.getItem(Setting.storeKey) ) {
this.$store.replaceState(Object.assign({}, this.$store.state,JSON.parse(sessionStorage.getItem(Setting.storeKey))))
}
//vuexsessionStorage
window.addEventListener("beforeunload",()=>{
sessionStorage.getItem(Setting.usernameKey) && sessionStorage.setItem(Setting.storeKey,JSON.stringify(this.$store.state))
})
}
}
</script>

@ -0,0 +1,39 @@
import Setting from '@/setting';
let host = Setting.apiBaseURL
let loginhost = 'http://www.liuwanr.cn/liuwanr'
// let host = 'http://192.168.31.117'//宁本地
export default {
host,
logins: `${host}/management/userInfo/login`, //登录 
save: `${host}/management/userInfo/add`, //注册
queryPhone: `${loginhost}/userInfo/queryPhone`, //查询电话是否存在
uploadUserAvatars: `http://www.liuwanr.cn/liuwanr/user/uploadUserAvatars`,
queryProvince: `${host}/enterprise/province/queryProvince`,
queryCity: `${host}/enterprise/city/queryCity`,
queryClient: `${host}/enterprise/client/list`,
userinfoUpdate:`${host}/management/userInfo/update`,//个人中心信息修改
userinfo:`${host}/management/userInfo/getUserInfo`,//个人中心信息展示
getAccount:`${host}/management/userInfo/getAccount`,//账号判重
queryCourseByCondition: `${host}/management/edu/course/queryCourseByCondition`,
getCourse: `${host}/management/edu/course/getCourse`,
getPlayAuth: `${host}/oss/manage/getPlayAuth`,
queryContestByCondition: `${host}/enterprise/match/contest/queryContestByCondition`,
queryAllClassification: `${host}/management/edu/courseClassification/queryGlClassification`,
queryAllColumns: `${host}/enterprise/information/column/queryAllColumns`,
getArticle: `${host}/enterprise/information/article/getArticle`,
getArticles: `${host}/enterprise/information/article/getArticles`,
queryArticleByCondition: `${host}/enterprise/information/article/queryArticleByCondition`,
onlineContestQuery: `${host}/enterprise/match/onlineContest/onlineContestQuery`,
getContest: `${host}/enterprise/match/contest/getContest`,
addApplicant: `${host}/enterprise/match/applicant/addApplicant`,
getContestProgress: `${host}/enterprise/match/contest-progress/getContestProgress`,
queryChaptersAndSubsections: `${host}/management/edu/courseChapter/queryChaptersAndSubsections`,
getSubsection: `${host}/management/edu/courseSubsection/getSubsection`, //根据小节id获取预览文件地址
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 764 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 995 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 449 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 528 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

@ -0,0 +1,124 @@
<template>
<div>
<el-dialog
custom-class="pdf-dia"
:close-on-click-modal="false"
:visible.sync="visible"
@close="closePdf"
:fullscreen="true"
:modal="false"
:append-to-body="true">
<div>
<button type="button" aria-label="Close" class="el-dialog__headerbtn" @click="closePdf"><i class="el-dialog__close el-icon el-icon-close"></i></button>
<div class="pdf">
<p class="arrow">
<span @click="changePdfPage(0)" class="turn el-icon-arrow-left" :class="{grey: currentPage==1}"></span>
{{currentPage}} / {{pageCount}}
<span @click="changePdfPage(1)" class="turn el-icon-arrow-right" :class="{grey: currentPage==pageCount}"></span>
</p>
<pdf
class="pdf-wrap"
:src="src"
:page="currentPage"
@num-pages="pageCount=$event"
@page-loaded="currentPage=$event"
@loaded="loadPdfHandler"
>
</pdf>
</div>
</div>
</el-dialog>
</div>
</template>
<script>
import pdf from "vue-pdf";
export default {
props: ['visible','src'],
data() {
return {
pdfVisible: false,
pdfSrc: '',
currentPage: 0,
pageCount: 0,
fileType: 'pdf',
};
},
components: { pdf },
mounted(){
this.addEvent()
},
methods: {
closePdf(){
this.$emit('update:visible',false)
this.$emit('update:src','')
this.currentPage = 1
},
changePdfPage (val) {
if (val === 0 && this.currentPage > 1) {
this.currentPage--
}
if (val === 1 && this.currentPage < this.pageCount) {
this.currentPage++
}
},
loadPdfHandler (e) {
this.currentPage = 1
},
addEvent(){
document.onkeydown = e => {
let key = window.event.keyCode
if(key == 37){
this.changePdfPage(0)
}else if(key == 39){
this.changePdfPage(1)
}
}
this.$once('hook:beforeDestroy',() => {
document.onkeydown = null
})
}
}
};
</script>
<style lang="scss" scoped>
/deep/.pdf-dia{
border-radius: 0 !important;
.el-dialog__header{
display: none;
}
.el-dialog__body{
padding: 0;
}
.el-dialog__headerbtn{
top: 10px;
.el-dialog__close{
color: #fff;
font-size: 16px;
}
}
.pdf{
.arrow{
display: flex;
justify-content: center;
align-items: center;
width: 100%;
padding: 10px 0;
font-size: 16px;
color: #fff;
background-color: #333;
.turn{
margin: 0 10px;
font-size: 18px;
cursor: pointer;
}
}
.pdf-wrap{
height: calc(100vh - 45px);
margin: 0 auto;
overflow: auto;
}
}
}
</style>

@ -0,0 +1,30 @@
export const messages = {
'zh': {
i18n: {
breadcrumb: '国际化产品',
tips: '通过切换语言按钮,来改变当前内容的语言。',
btn: '切换英文',
title1: '常用用法',
p1: '要是你把你的秘密告诉了风,那就别怪风把它带给树。',
p2: '没有什么比信念更能支撑我们度过艰难的时光了。',
p3: '只要能把自己的事做好,并让自己快乐,你就领先于大多数人了。',
title2: '组件插值',
info: 'Element组件需要国际化,请参考 {action}。',
value: '文档'
}
},
'en': {
i18n: {
breadcrumb: 'International Products',
tips: 'Click on the button to change the current language. ',
btn: 'Switch Chinese',
title1: 'Common usage',
p1: "If you reveal your secrets to the wind you should not blame the wind for revealing them to the trees.",
p2: "Nothing can help us endure dark times better than our faith. ",
p3: "If you can do what you do best and be happy, you're further along in life than most people.",
title2: 'Component interpolation',
info: 'The default language of Element is Chinese. If you wish to use another language, please refer to the {action}.',
value: 'documentation'
}
}
}

@ -0,0 +1,42 @@
<template>
<div>
<div class="copyright" :class="{transparent: isWhite}">广州超竞教育投资有限公司版权所有</div>
</div>
</template>
<script>
export default {
data() {
return {
isWhite: false
};
},
mounted(){
},
methods: {
setBg(name){
console.log(1111,name)
if(name == 'backstage'){
this.isWhite = true
}else{
this.isWhite = false
}
}
},
};
</script>
<style lang="scss" scoped>
.copyright{
line-height: 60px;
color: rgba(0, 0, 0, 0.45);
font-size: 12px;
text-align: center;
background-color: #fff;
border-top: 1px solid rgba(0, 0, 0, 0.06);
&.transparent{
color: rgba(255, 255, 255, 0.65);
background-color: #141414;
border-top-color: transparent;
}
}
</style>

@ -0,0 +1,141 @@
<template>
<div>
<div class="header" :class="{white: isWhite}">
<div class="inner">
<img class="logo" :src="logo">
<v-navbar class="nav" :isWhite="isWhite"></v-navbar>
<div class="right">
<el-dropdown @command="userCommand">
<div class="user">
<el-avatar :size="40" :src="avatar"></el-avatar>
<span class="username">{{username}}</span>
</div>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="help">用户手册</el-dropdown-item>
<el-dropdown-item command="person">个人资料</el-dropdown-item>
<el-dropdown-item command="logout">退出登录</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</div>
<pdf :visible.sync="pdfVisible" :src.sync="pdfSrc"></pdf>
</div>
</template>
<script>
import bus from '@/libs/bus';
import Setting from '@/setting';
import pdf from '@/components/pdf'
import vNavbar from '../navbar/index.vue'
export default {
data() {
return {
pdfVisible: false,
pdfSrc: '',
username: this.$store.state.name,
avatar: this.$store.state.avatar,
showBackList: Setting.layout.hideNavList,
isWhite: false,
logo: require('../../assets/img/logo.png')
};
},
components: { pdf,vNavbar },
computed: {
showBack(){
let route = this.$route.name
if(this.showBackList.includes(route)) return true
return false
}
},
mounted(){
bus.$on('updateAvatar',avatar => {
this.avatar = avatar
})
},
methods: {
loginout() {
sessionStorage.removeItem(Setting.usernameKey);
sessionStorage.removeItem(Setting.storeKey);
this.$router.push('login');
},
back(){
this.$router.back()
},
userCommand(command){
if(command == 'help'){
this.pdfVisible = true
this.pdfSrc = 'https://huoran.oss-cn-shenzhen.aliyuncs.com/20201125/pdf/1331504360072962048.pdf'
}else if(command == 'person'){
this.$router.push('personalCenter')
}else{
this.loginout()
}
},
setLogo(name){
if(name == 'none'){
this.isWhite = true
this.logo = require('../../assets/img/logo-fill.png')
}else{
this.isWhite = false
this.logo = require('../../assets/img/system-fullname.png')
}
}
},
};
</script>
<style lang="scss" scoped>
.header {
z-index: 2;
background-color: transparent;
.inner{
position: relative;
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 24px;
margin: 0 auto;
font-size: 16px;
color: #333;
.logo {
@media(max-width: 1420px){
width: 350px;
}
}
.nav{
position: absolute;
left: 50%;
transform: translateX(-50%);
}
.right {
display: flex;
height: 70px;
align-items: center;
.user{
display: inline-flex;
align-items: center;
cursor: pointer;
.username{
margin-left: 10px;
color: #fff;
font-size: 16px;
}
}
}
}
&.white{
background-color: #fff;
border-bottom: rgba(0, 0, 0, 0.06);
.inner{
.right {
.user{
.username{
color: rgba(0, 0, 0, 0.85);
}
}
}
}
}
}
</style>

@ -0,0 +1,92 @@
<template>
<div class="wrapper" :class="curModule">
<v-head ref="header"></v-head>
<div class="content-box" :class="{'content-collapse':collapse}">
<div class="content">
<transition name="move" mode="out-in">
<keep-alive :include="tagsList">
<router-view></router-view>
</keep-alive>
</transition>
<el-backtop target=".content"></el-backtop>
</div>
</div>
<v-footer ref="footer"></v-footer>
</div>
</template>
<script>
import vHead from '../header'
import vFooter from '../footer'
import bus from '@/libs/bus';
import Setting from '@/setting';
export default {
data() {
return {
curModule: '',
tagsList: [],
collapse: false,
hideNavList: Setting.layout.hideNavList
};
},
components: {
vHead,
vFooter
},
computed: {
hideNavbar() {
let route = this.$route.name
if(this.hideNavList.includes(route)) return false
return true
}
},
created() {
bus.$on('collapse-content', msg => {
this.collapse = msg;
});
bus.$on('setBg', name => {
this.curModule = name
this.$refs.header.setLogo(name)
this.$refs.footer.setBg(name)
})
// 使keep-alive
bus.$on('tags', msg => {
let arr = [];
for (let i = 0, len = msg.length; i < len; i++) {
msg[i].name && arr.push(msg[i].name);
}
this.tagsList = arr;
});
}
};
</script>
<style lang="scss" scoped>
body{
background-color: #141414;
}
.wrapper{
min-width: 1180px;
background: url() no-repeat;
&.course{
background-size: 100% 560px;
@include set-bg('../../assets/img/course-bg.png')
}
&.info{
background-size: 100% 400px;
@include set-bg('../../assets/img/info-bg.png')
}
&.match{
background-size: 100% 400px;
@include set-bg('../../assets/img/match-bg.png')
}
&.backstage{
background-size: cover;
@include set-bg('../../assets/img/backstage-bg.png')
}
.content-box{
min-height: calc(100% - 152px);
}
}
</style>

@ -0,0 +1,79 @@
<template>
<div>
<ul class="tab" :class="{white: isWhite}">
<li v-for="(item,index) in tabs" :key="index" :class="{active: active == item.index}" @click="tabChange(item.index)">{{item.title}}</li>
</ul>
</div>
</template>
<script>
export default {
props: ['isWhite'],
data() {
return {
active: this.$route.name,
tabs: [
{
index: 'course',
title: '课程学习'
},
{
index: 'information',
title: '最新资讯'
},
{
index: 'match',
title: '赛事报名'
},
{
index: 'dashboard',
title: '仿真实训'
},
],
};
},
methods: {
tabChange(index){
this.active = index
location.hash = index
this.$router.push(index)
},
}
};
</script>
<style lang="scss" scoped>
.tab{
display: flex;
align-items: center;
margin-top: -20px;
li{
padding: 28px 5px;
margin: 0 23px;
color: #fff;
font-size: 16px;
line-height: 1;
border-bottom: 3px solid transparent;
cursor: pointer;
&:hover{
opacity: .9;
}
&.active{
border-bottom-color: #fff;
}
@media(max-width: 1420px){
padding: 25px 0;
}
}
&.white{
li{
color: rgba(0, 0, 0, 0.85);
&.active{
color: #CC221C;
border-bottom-color: #CC221C;
}
}
}
}
</style>

@ -0,0 +1,186 @@
<template>
<div class="tags" v-if="showTags">
<ul>
<li class="tags-li" v-for="(item,index) in tagsList" :class="{'active': isActive(item.path)}" :key="index">
<router-link :to="item.path" class="tags-li-title">
{{item.title}}
</router-link>
<span class="tags-li-icon" @click="closeTags(index)"><i class="el-icon-close"></i></span>
</li>
</ul>
<div class="tags-close-box">
<el-dropdown @command="handleTags">
<el-button size="mini" type="primary">
标签选项<i class="el-icon-arrow-down el-icon--right"></i>
</el-button>
<el-dropdown-menu size="small" slot="dropdown">
<el-dropdown-item command="other">关闭其他</el-dropdown-item>
<el-dropdown-item command="all">关闭所有</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</template>
<script>
import bus from '@/libs/bus';
export default {
data() {
return {
tagsList: []
}
},
methods: {
isActive(path) {
return path === this.$route.fullPath;
},
//
closeTags(index) {
const delItem = this.tagsList.splice(index, 1)[0];
const item = this.tagsList[index] ? this.tagsList[index] : this.tagsList[index - 1];
if (item) {
delItem.path === this.$route.fullPath && this.$router.push(item.path);
}else{
this.$router.push('/');
}
},
//
closeAll(){
this.tagsList = [];
this.$router.push('/');
},
//
closeOther(){
const curItem = this.tagsList.filter(item => {
return item.path === this.$route.fullPath;
})
this.tagsList = curItem;
},
//
setTags(route){
const isExist = this.tagsList.some(item => {
return item.path === route.fullPath;
})
if(!isExist){
if(this.tagsList.length >= 8){
this.tagsList.shift();
}
this.tagsList.push({
title: route.meta.title,
path: route.fullPath,
name: route.matched[1].components.default.name
})
}
bus.$emit('tags', this.tagsList);
},
handleTags(command){
command === 'other' ? this.closeOther() : this.closeAll();
}
},
computed: {
showTags() {
return this.tagsList.length > 0;
}
},
watch:{
$route(newValue, oldValue){
this.setTags(newValue);
}
},
created(){
this.setTags(this.$route);
//
bus.$on('close_current_tags', () => {
for (let i = 0, len = this.tagsList.length; i < len; i++) {
const item = this.tagsList[i];
if(item.path === this.$route.fullPath){
if(i < len - 1){
this.$router.push(this.tagsList[i+1].path);
}else if(i > 0){
this.$router.push(this.tagsList[i-1].path);
}else{
this.$router.push('/');
}
this.tagsList.splice(i, 1);
break;
}
}
})
}
}
</script>
<style>
.tags {
position: relative;
height: 30px;
overflow: hidden;
background: #fff;
padding-right: 120px;
box-shadow: 0 5px 10px #ddd;
}
.tags ul {
box-sizing: border-box;
width: 100%;
height: 100%;
}
.tags-li {
float: left;
margin: 3px 5px 2px 3px;
border-radius: 3px;
font-size: 12px;
overflow: hidden;
cursor: pointer;
height: 23px;
line-height: 23px;
border: 1px solid #e9eaec;
background: #fff;
padding: 0 5px 0 12px;
vertical-align: middle;
color: #666;
-webkit-transition: all .3s ease-in;
-moz-transition: all .3s ease-in;
transition: all .3s ease-in;
}
.tags-li:not(.active):hover {
background: #f8f8f8;
}
.tags-li.active {
color: #fff;
}
.tags-li-title {
float: left;
max-width: 80px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
margin-right: 5px;
color: #666;
}
.tags-li.active .tags-li-title {
color: #fff;
}
.tags-close-box {
position: absolute;
right: 0;
top: 0;
box-sizing: border-box;
padding-top: 1px;
text-align: center;
width: 110px;
height: 30px;
background: #fff;
box-shadow: -3px 0 15px 3px rgba(0, 0, 0, .1);
z-index: 10;
}
</style>

@ -0,0 +1,25 @@
/**
* @description 生成按钮级别权限组
* */
import store from '@/store';
export default function(data){
let result = []
data.map(e => {
if(e.select){
e.children.map(n => {
if(n.select){
if(n.children.length){
result.push(`${e.name}:${n.name}`)
n.children.map(j => {
j.select && (e.component ? result.push(`${e.component}:${n.name}:${j.name}`) : result.push(`${n.component}:${j.name}`))
})
}else{
result.push(`${e.component}:${n.name}`)
}
}
})
}
})
store.commit('addBtnPerData',{btnPermissions: result})
}

@ -0,0 +1,6 @@
import Vue from 'vue';
// 使用 Event Bus
const bus = new Vue();
export default bus;

@ -0,0 +1,202 @@
const pad2 = str => ('0' + str).substr(-2)
function fMoney (s, n) {
n = n > 0 && n <= 20 ? n : 2
s = parseFloat((s + '').replace(/[^\d\.-]/g, '')).toFixed(n) + ''
let l = s.split('.')[0].split('').reverse()
let r = s.split('.')[1]
let t = ''
for(let i = 0; i < l.length; i ++ ) {
t += l[i] + ((i + 1) % 3 == 0 && (i + 1) != l.length ? ',' : '')
}
return t.split('').reverse().join('') + '.' + r
}
function toDateTime (date, time) {
if (!date) return ''
date = date.toString()
time = time ? time.toString() : ''
let str = `${date.substr(0, 4)}-${date.substr(4, 2)}-${date.substr(6, 2)}`
if (date.length == 14) {
str += ` ${date.substr(8, 2)}:${date.substr(10, 2)}:${date.substr(12, 2)}`
} else if (date.length == 6) {
str = `${date.substr(0, 2)}:${date.substr(2, 2)}:${date.substr(4, 2)}`
} else if (time) {
str += ` ${time.substr(0, 2)}:${time.substr(2, 2)}:${time.substr(4, 2)}`
}
return str
}
function fMoney2 (m) {
return parseFloat(m).toFixed(2)
}
function orderreleaseType (sts) {
const status = {
'0': '手动发布',
'1': '定时发布',
}
return status[sts] || '未知状态'
}
function orderflag (sts) {
const status = {
'0': true,
'1': false,
}
return status[sts] || '未知状态'
}
function orderassesmentState (sts) {
const status = {
'0': '待开始',
'1': '进行中',
'2': '已结束',
}
return status[sts] || '未知状态'
}
function orderfounder (sts) {
const status = {
'0': '系统',
'1': '老师'
}
return status[sts] || '未知状态'
}
function projectPermissions (sts) {
const status = {
'1': '考核',
'2': '竞赛',
'0': '练习'
}
return status[sts] || '未知状态'
}
function roleType (type) {
const types = {
'2': '管理员',
'3': '老师',
'4': '学生'
}
return types[type] || '未知类型'
}
function educationDegreeList (id) {
const list = [
{
     name: '专科',
    value: 1
},
{
  name: '本科',
  value: 2
},
{
  name: '硕士',
  value: 3
},
{
  name: '博士',
  value: 4
},
{
  name: '其他',
  value: 5
}
]
let educationdegree = list.find((n,k) => {
return n.value == id
}).name
return educationdegree
}
//返回格式化时间,传参例如:"yyyy-MM-dd hh:mm:ss"
function formatDate(fmt,date) {
var date = date ? date : new Date()
var o = {
"M+" : date.getMonth()+1, //月份
"d+" : date.getDate(), //日
"h+" : date.getHours(), //小时
"m+" : date.getMinutes(), //分
"s+" : date.getSeconds(), //秒
"q+" : Math.floor((date.getMonth()+3)/3), //季度
"S" : date.getMilliseconds() //毫秒
};
if(/(y+)/.test(fmt)) {
fmt=fmt.replace(RegExp.$1, (date.getFullYear()+"").substr(4 - RegExp.$1.length));
}
for(var k in o) {
if(new RegExp("("+ k +")").test(fmt)){
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length)));
}
}
return fmt;
}
function removeByValue(arr, val) {
for(var i=0; i<arr.length; i++) {
if(arr[i] == val) {
arr.splice(i, 1);
break;
}
}
}
function formateTime(num) {
return num < 10 ? `0${num}` : num
}
function getCaption(obj){
var index=obj.lastIndexOf("\h");
obj=obj.substring(index+1,obj.length);
return obj;
}
// new Date('2020-11-12 00:00:00') 在IE下失效,因此把-替换成/
function dateCompatible(date) {
return date.replace(/\-/g, '/')
}
// 是否IE
function isIE() {
if (!!window.ActiveXObject || "ActiveXObject" in window) return true
return false
}
// 是否edge
function isEdge() {
let userAgent = navigator.userAgent
if (userAgent.includes("Edge")) return true
return false
}
// 是否火狐
function isFirefox() {
let userAgent = navigator.userAgent
if (userAgent.indexOf("Firefox") > -1) return true
return false
}
export default{
orderfounder,
projectPermissions,
orderassesmentState,
fMoney,
fMoney2,
toDateTime,
orderreleaseType,
orderflag,
roleType,
educationDegreeList,
removeByValue,
formateTime,
getCaption,
formatDate,
isIE,
isFirefox,
isEdge,
dateCompatible
}

@ -0,0 +1,16 @@
// rem等比适配配置文件
// 基准大小
const baseSize = 16
// 设置 rem 函数
function setRem () {
// 当前页面宽度相对于 1920宽的缩放比例,可根据自己需要修改。
const scale = document.documentElement.clientWidth / 1920
// 设置页面根节点字体大小(“Math.min(scale, 2)” 指最高放大比例为2,可根据实际业务需求调整)
document.documentElement.style.fontSize = baseSize * Math.min(scale, 2) + 'px'
}
// 初始化
setRem()
// 改变窗口大小时重新设置 rem
window.onresize = function () {
setRem()
}

@ -0,0 +1,34 @@
import store from '@/store';
import router from '@/router';
import generateBtnPermission from '../auth/generateBtnPermission';
const newRoutes = []
function createMeta(item){
let meta = { title: item.name }
return meta
}
function createRoute(data){
data.map(e => {
if(e.select && e.component){
let meta = createMeta(e)
newRoutes.push({
name: e.component,
path: e.component,
component: () => import(`@/pages/${e.component}.vue`),
meta
})
}
e.children && e.children.length && createRoute(e.children)
})
}
export default function(data,path){
generateBtnPermission(data)
createRoute(data)
let routes = router.options.routes
routes[1].children = [...routes[1].children,...newRoutes]
store.commit("addRoutesData", { routes })
router.addRoutes(routes)
}

@ -0,0 +1,26 @@
import store from '@/store';
import router from '@/router';
export default function(){
setTimeout(() => {
let routes = store.state.routes
routes.forEach(e => {
if(e.path == '/'){
e.component = () => import('@/layouts/home/index.vue')
}else{
e.component = () => import(`@/pages/${e.path}.vue`)
}
e.children && e.children.forEach(n => {
n.path && (n.component = () => import(`@/pages/${n.path}.vue`))
})
})
routes.push({
path: '*',
redirect: '404'
})
router.addRoutes(routes)
},500)
}

@ -0,0 +1,6 @@
import router from '@/router';
export default function(){
const newRouter = createRouter()
router.matcher = newRouter.matcher
}

@ -0,0 +1,42 @@
import Vue from 'vue';
import App from '@/App.vue';
import router from '@/router';
import ElementUI from 'element-ui';
import '@/styles/index.scss'
import VueI18n from 'vue-i18n';
import { messages } from '@/i18n';
import 'babel-polyfill';
import '@/libs/resize';
import {post,get,del,put} from '@/plugins/requests/index.js';
import api from '@/api';
import store from '@/store'
import core from '@/libs/core'
import Setting from '@/setting';
import permission from '@/router/permission';
// 插件
import plugins from '@/plugins';
Vue.use(plugins);
Vue.prototype.api = api;
Vue.prototype.$get = get;
Vue.prototype.$post = post;
Vue.prototype.$del = del;
Vue.prototype.$put = put;
Vue.prototype.core = core
Vue.config.productionTip = false;
Vue.use(VueI18n);
Vue.use(ElementUI);
const i18n = new VueI18n({
locale: Setting.i18n.default,
messages
});
new Vue({
router,
i18n,
store,
render: h => h(App)
}).$mount('#app');

@ -0,0 +1,56 @@
<template>
<div class="error-page">
<div class="error-code">4<span>0</span>3</div>
<div class="error-desc">啊哦~ 你没有权限访问该页面哦</div>
<div class="error-handle">
<router-link to="/">
<el-button type="primary" size="large">返回首页</el-button>
</router-link>
<el-button class="error-btn" type="primary" size="large" @click="goBack">返回上一页</el-button>
</div>
</div>
</template>
<script>
export default {
methods: {
goBack(){
this.$router.go(-1);
}
}
}
</script>
<style scoped>
.error-page{
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
width: 100%;
height: 100%;
background: #f3f3f3;
box-sizing: border-box;
}
.error-code{
line-height: 1;
font-size: 250px;
font-weight: bolder;
color: #f02d2d;
}
.error-code span{
color: #00a854;
}
.error-desc{
font-size: 30px;
color: #777;
}
.error-handle{
margin-top: 30px;
padding-bottom: 200px;
}
.error-btn{
margin-left: 100px;
}
</style>

@ -0,0 +1,56 @@
<template>
<div class="error-page">
<div class="error-code">4<span>0</span>4</div>
<div class="error-desc">啊哦~ 你所访问的页面不存在</div>
<div class="error-handle">
<router-link to="/">
<el-button type="primary" size="large">返回首页</el-button>
</router-link>
<el-button class="error-btn" type="primary" size="large" @click="goBack">返回上一页</el-button>
</div>
</div>
</template>
<script>
export default {
methods: {
goBack(){
this.$router.go(-1);
}
}
}
</script>
<style scoped>
.error-page{
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
width: 100%;
height: 100%;
background: #f3f3f3;
box-sizing: border-box;
}
.error-code{
line-height: 1;
font-size: 250px;
font-weight: bolder;
color: #2d8cf0;
}
.error-code span{
color: #00a854;
}
.error-desc{
font-size: 30px;
color: #777;
}
.error-handle{
margin-top: 30px;
padding-bottom: 200px;
}
.error-btn{
margin-left: 100px;
}
</style>

@ -0,0 +1,134 @@
<template>
<div style="padding-bottom: 20px">
<div class="article">
<div class="breadcrumb">
<span class="cur">当前位置</span>
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/' }">学生用户端</el-breadcrumb-item>
<el-breadcrumb-item :to="{ path: '/information' }">最新资讯</el-breadcrumb-item>
<el-breadcrumb-item>{{firstName}}</el-breadcrumb-item>
<el-breadcrumb-item v-if="secondName">{{secondName}}</el-breadcrumb-item>
<el-breadcrumb-item>资讯详情</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="page">
<h6 class="title">{{title}}</h6>
<div class="metas">
<span>作者 {{author}}</span>
<span>{{date.replace(' 00:00:00','')}}</span>
<span>浏览量{{viewCount}}</span>
</div>
<div class="cover">
<img :src="coverUrl" alt="">
</div>
<div class="content ql-editor" v-html="content"></div>
</div>
</div>
</div>
</template>
<script>
import { Loading } from 'element-ui';
import 'quill/dist/quill.core.css';
import 'quill/dist/quill.snow.css';
import 'quill/dist/quill.bubble.css';
export default {
name: 'article',
data() {
return {
userId: this.$store.state.userId,
firstName: this.$route.query.first,
secondName: this.$route.query.second,
id: this.$route.query.id,
coverUrl: '',
author: '',
date: '',
title: '',
content: '',
viewCount: 0,
loadIns: null
}
},
mounted() {
this.getData()
},
methods: {
getData() {
this.loadIns = Loading.service()
this.$get(`${this.api.getArticle}/${this.id}`)
.then(res => {
let data = res.data.article
this.coverUrl = data.coverUrl
this.author = data.author
this.date = data.date
this.title = data.title
this.content = data.content
this.viewCount = data.viewCount
this.loadIns.close()
})
.catch(err => {
this.loadIns.close()
});
},
}
};
</script>
<style lang="scss" scoped>
.article{
width: 70%;
margin: 0 auto;
padding-top: 265px;
.page{
padding: 40px;
border-radius: 8px;
background-color: #fff;
.title{
text-align: center;
font-size: 24px;
font-weight: 500;
color: rgba(0, 0, 0, 0.85);
}
.metas{
display: flex;
justify-content: center;
align-items: center;
padding-bottom: 32px;
margin: 16px 0 32px;
border-bottom: 1px solid rgba(0, 0, 0, 0.06);
span{
display: inline-flex;
align-items: center;
margin-left: 20px;
color: rgba(0, 0, 0, 0.45);
font-size: 12px;
img{
width: 18px;
margin-right: 5px;
}
}
}
.cover{
margin: 20px 0;
text-align: center;
img{
width: 800px;
}
}
.content{
line-height: 1.8;
font-size: 16px;
text-indent: 2em;
/deep/img{
display: block;
width: 600px;
margin-left: auto;
margin-right: auto;
}
}
}
}
</style>

@ -0,0 +1,227 @@
<template>
<div class="box">
<div class="search">
<input type="text" placeholder="请输入课程名称" v-model="keyword" />
<button><img src="../assets/img/search.png" alt=""> 搜索</button>
</div>
<div class="main">
<div class="filter">
<dl>
<dt>课程分类</dt>
<dd>
<el-select v-model="classificationId" clearable placeholder="请选择课程分类" size="small" @change="getData">
<el-option label="不限" value=""></el-option>
<el-option v-for="(item,index) in classificationList" :key="index" :label="item.name" :value="item.id"></el-option>
</el-select>
</dd>
</dl>
</div>
<div class="courses">
<template v-if="courseData.length">
<ul>
<li v-for="(item, index) in courseData" :key="index" @click="toDetail(item.id)">
<img :src="item.coverUrl" alt="" />
<div class="title">{{ item.name }}</div>
<div class="desc" :class="{ie: core.isIE(),ie: core.isFirefox()}" v-html="item.description"></div>
</li>
</ul>
<div class="pagination">
<el-pagination background layout="total, prev, pager, next" :total="totals" @current-change="handleCurrentChange" :current-page="pageNo">
</el-pagination>
</div>
</template>
<template v-else>
<div class="empty">
<div>
<img src="../assets/img/none.png" alt="">
<p>暂无课程</p>
</div>
</div>
</template>
</div>
</div>
</div>
</template>
<script>
import { Loading } from 'element-ui';
import bus from '@/libs/bus'
export default {
name: 'course',
data() {
return {
userId: this.$store.state.userId,
schoolId: this.$store.state.schoolId,
classificationId: '',
classificationList: [],
courseData: [],
keyword: '',
totals: 0,
pageNo: 1,
pageSize: 8,
searchTimer: null,
loadIns: null
};
},
mounted() {
bus.$emit('setBg','course')
this.getClassification()
this.getData()
},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.initData()
},500)
}
},
methods: {
getData() {
this.loadIns = Loading.service()
let data = {
classificationId: this.classificationId,
name: this.keyword,
port: 0,
schoolId: this.schoolId
}
this.$get(`${this.api.queryCourseByCondition}/${this.pageNo}/${this.pageSize}`,data).then(res => {
this.courseData = res.data.courseList
this.totals = res.data.total
this.courseData.map(n => {
n.description = n.description.replace(/<img.*?(?:>|\/>)/gi,'')
})
this.loadIns.close()
}).catch(res => {
this.loadIns.close()
});
},
initData(){
this.pageNo = 1
this.getData()
},
getClassification() {
this.$get(`${this.api.queryAllClassification}?schoolId=${this.schoolId}`).then(res => {
this.classificationList = res.data.classificationList
}).catch(res => {});
},
changeType(type) {
this.classificationId = type
this.initData()
},
handleCurrentChange(val) {
this.pageNo = val;
this.getData();
},
toDetail(id) {
this.$router.push(`courseSection?id=${id}`);
}
}
};
</script>
<style lang="scss" scoped>
.box{
padding-top: 108px;
.search{
margin-bottom: 108px;
}
.main{
width: 70%;
min-width: 920px;
padding: 40px;
margin: 0 auto;
border-radius: 16px;
background-color: #fdfdfd;
box-sizing: border-box;
.filter {
margin-bottom: 10px;
dl {
display: flex;
line-height: 30px;
dt {
color: rgba(0,0,0,.85);
font-size: 14px;
}
dd {
display: inline-flex;
align-items: center;
span {
padding: 2px 10px;
margin: 0 10px;
color: rgba(0,0,0,.65);
font-size: 14px;
cursor: pointer;
&:hover {
color: #CC221C;
}
&.classification {
border-radius: 4px;
color: #fff;
background-color: #CC221C;
}
}
}
}
}
.courses {
ul {
display: flex;
flex-wrap: wrap;
li {
width: 24%;
min-height: 250px;
overflow: hidden;
padding: 10px;
margin: 10px .5%;
box-sizing: border-box;
cursor: pointer;
border-radius: 8px;
background-color: #fff;
transition: all 0.3s;
img {
width: 100%;
height: 165px;
}
.title {
margin: 10px 0 5px;
color: #333;
font-size: 16px;
word-wrap: break-word;
word-break: break-all;
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
}
.desc span{
color: #f00;
font-size: 14px;
background-color: #f00;
}
.desc {
color: #999;
font-size: 14px;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
&.ie{
height: 80px;
text-overflow: ellipsis;
white-space: nowrap;
}
}
&:hover{
box-shadow: 0px 5px 12px 4px rgba(204,34,28,0.09), 0px 3px 6px 0px rgba(204,34,28,0.12), 0px 1px 2px -2px rgba(204,34,28,0.16);
}
}
}
}
}
}
</style>

@ -0,0 +1,452 @@
<template>
<div>
<div class="flex p-40">
<div class="cover" :class="{'is-word': showMask1}">
<img v-if="coverUrl" :src="coverUrl" alt="" width="100%" height="100%">
<template v-else-if="iframeSrc">
<iframe class="inner fileIframe" id="fileIframe" :src="iframeSrc" frameborder="0"></iframe>
<template v-if="showMask">
<div class="mask" style="width: 500px;height: 30px;top: 53px;right: 320px"></div>
<div class="mask" style="width: 175px;height: 30px;top: 53px;right: 5px"></div>
</template>
<template v-if="showMask1">
<div class="word-mask" style="height: 40px;"></div>
<div class="word-mask2" style="top: 55px;left: 28%;width: 44%;height: calc(100% - 80px);"></div>
</template>
<template v-if="showMask2">
<div class="excel-mask1" style="height: 48px;"></div>
</template>
</template>
<div class="pdf inner" v-else-if="pdfSrc">
<p class="arrow">
<span @click="changePdfPage(0)" class="turn el-icon-arrow-left" :class="{grey: currentPage==1}"></span>
{{currentPage}} / {{pageCount}}
<span @click="changePdfPage(1)" class="turn el-icon-arrow-right" :class="{grey: currentPage==pageCount}"></span>
</p>
<pdf
class="pdf-wrap"
:src="pdfSrc"
:page="currentPage"
@num-pages="pageCount=$event"
@page-loaded="currentPage=$event"
@loaded="loadPdfHandler">
</pdf>
</div>
<div class="inner" v-else-if="playAuth">
<div class="video_wid" id="player"></div>
</div>
</div>
<div class="catalog flex-1">
<div class="list">
<h4 class="title">{{courseName}}</h4>
<div class="desc-wrap">
<div class="desc" :class="{active: desShrink}" v-html="description"></div>
<i class="arrow" :class="{active: desShrink}" v-if="description.length > 40">
<span>...</span>
<img src="../assets/img/arrow-down.png" alt="" @click="desShrink = !desShrink">
</i>
</div>
<div class="chapters">
<template v-if="videoList.length">
<div class="chapter" v-for="(item,index) in videoList" :key="index">
<div class="chapterName">{{item.name}}</div>
<div class="section" v-if="item.subsectionList.length">
<div class="sectionName" v-for="(section,i) in item.subsectionList" :key="i" @click="preview(section)">{{section.name}}</div>
</div>
</div>
</template>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapState } from 'vuex';
import pdf from "vue-pdf";
import 'quill/dist/quill.core.css';
import 'quill/dist/quill.snow.css';
import 'quill/dist/quill.bubble.css';
import bus from '@/libs/bus'
export default {
data() {
return {
id: this.$route.query.id,
video: 'http://liuwanr.oss-cn-shenzhen.aliyuncs.com/mp4/20200519/1589871025648.mp4',
videoSrc: '',
userId: this.$store.state.userId,
videoList: [],
courseName: '',
description: '',
coverUrl: '',
playAuth: '',
player: null,
previewImg: '',
iframeSrc: '',
isWord: false,
isPPT: false,
isExcel: false,
showMask: false,
showMask1: false,
showMask2: false,
closePosi: {
top: '80px'
},
pdfVisible: false,
pdfSrc: '',
currentPage: 0, // pdf
pageCount: 0, // pdf
fileType: 'pdf', //
desShrink: false
};
},
computed: {
...mapState({
courseId: state => state.courseId,
classId: state => state.classId,
}),
},
components: { pdf },
mounted() {
bus.$emit('setBg','none')
this.insertScript()
this.getData()
this.getChapter()
},
methods: {
async getData(){
let res = await this.$get(`${this.api.getCourse}/${this.id}`)
this.courseName = res.data.course.name
this.description = res.data.course.description
this.coverUrl = res.data.course.coverUrl
},
async getChapter(){
let res = await this.$get(`${this.api.queryChaptersAndSubsections}/${this.id}`)
this.videoList = res.data.chapterList
},
insertScript(){
const linkTag = document.createElement('link');
linkTag.rel = 'stylesheet';
linkTag.href = 'https://g.alicdn.com/de/prismplayer/2.8.2/skins/default/aliplayer-min.css';
document.body.appendChild(linkTag);
const scriptTag = document.createElement('script');
scriptTag.type = 'text/javascript';
scriptTag.src = 'https://g.alicdn.com/de/prismplayer/2.8.2/aliplayer-min.js';
document.body.appendChild(scriptTag);
},
transferType(ext){
if('jpg,jpeg,png,gif,svg,psd'.includes(ext)) return '图片'
if('mp4,3gp,mov,m4v,avi,dat,mkv,flv,vob,rmvb,rm,qlv'.includes(ext)) return '视频'
return ext
},
preview(row){
this.player = null
this.playauth = ''
this.coverUrl = ''
this.pdfSrc = ''
this.iframeSrc = ''
this.isPPT = false
this.isWord = false
this.isExcel = false
if(this.transferType(row.fileType) == '视频'){
this.$get(`${this.api.getPlayAuth}/${row.fileId}`).then(res => {
this.playAuth = res.data.playAuth
this.$nextTick(() => {
if(this.player){
this.player.replayByVidAndPlayAuth(row.fileId,this.playAuth)
}else{
this.player = new Aliplayer({
id: 'player',
width: '100%',
autoplay: false,
vid : row.fileId,
playauth : this.playAuth,
encryptType:1, //
})
}
})
}).catch(res => {})
}else if(this.transferType(row.fileType) == '图片'){
this.coverUrl = row.fileUrl
}else if(row.fileType == 'pdf'){
this.pdfSrc = row.fileUrl
this.pdfVisible = true
}else{
this.$get(`${this.api.getSubsection}/${row.id}`).then(res => {
if(row.fileType == 'pptx'){
this.isPPT = true
this.isWord = false
this.isExcel = false
}else if(row.fileType == 'doc' || row.fileType == 'docx'){
this.isPPT = false
this.isWord = true
this.isExcel = false
}else if(row.fileType == 'xls' || row.fileType == 'xlsx'){
this.isExcel = true
this.isPPT = false
this.isWord = false
}else{
this.isPPT = false
this.isWord = false
this.isExcel = false
}
if(this.isPPT){
this.showMask = true
}else{
this.showMask = false
}
if(this.isWord){
this.showMask1 = true
}else{
this.showMask1 = false
}
if(this.isExcel){
this.showMask2 = true
}else{
this.showMask2 = false
}
this.iframeSrc = res.data.previewUrl
})
.catch(err => {
});
}
},
closePlayer(){
this.playAuth = ''
this.player.pause()
},
closeIframe(){
this.iframeSrc = ''
this.showMask = false
this.showMask1 = false
},
closePdf(){
this.pdfSrc = ''
this.currentPage = 1
},
changePdfPage (val) {
if (val === 0 && this.currentPage > 1) {
this.currentPage--
}
if (val === 1 && this.currentPage < this.pageCount) {
this.currentPage++
}
},
loadPdfHandler (e) {
this.currentPage = 1
}
}
};
</script>
<style lang="scss" scoped>
$height: 700px;
.video_wid,.cover{
position: relative;
width: 76%;
max-width: 1400px;
height: $height !important;
border: 0;
}
.cover{
img{
border-radius: 8px;
}
&.is-word{
overflow: hidden;
}
}
.fileIframe{
height: $height !important;
}
.video_wid,.inner{
width: 100%;
height: 100% !important;
border: 0;
overflow: auto;
}
.cover.is-word{
.inner{
height: calc(100% + 38px) !important;
margin-top: -38px;
}
}
.video_wid:focus{
outline: none;
}
.catalog{
margin-left: 40px;
}
.list{
height: $height;
overflow-y: auto;
padding: 24px 16px;
background: #fff;
.title{
margin-bottom: 8px;
color: rgba(0, 0, 0, 0.85);
font-size: 20px;
}
.desc-wrap{
position: relative;
.desc{
font-size: 14px;
color: rgba(0, 0, 0, 0.65);
line-height: 22px;
@include mul-ellipsis(2);
&.active{
display: block;
overflow: visible;
}
}
.arrow{
position: absolute;
bottom: 2px;
right: 0;
display: flex;
justify-content: space-between;
width: 46px;
background-color: #fff;
span{
font-size: 14px;
color: rgba(0, 0, 0, 0.65);
}
img{
width: 16px;
cursor: pointer;
}
&.active{
span{
opacity: 0;
}
img{
transform: rotate(180deg);
}
}
}
}
.chapters{
margin-top: 16px;
max-height: calc(100% - 53px);
overflow: auto;
}
.chapter{
margin-bottom: 20px;
.chapterName{
color: rgba(0, 0, 0, 0.85);
font-size: 16px;
}
.section{
padding: 5px 15px;
margin-top: 8px;
background: rgba(0, 0, 0, 0.02);
.sectionName{
margin: 10px 0;
font-size: 14px;
color: rgba(0, 0, 0, 0.65);
cursor: pointer;
@include ellipsis;
}
}
}
}
.el-image-viewer__wrapper{
transform: translateY(-10px);
transition: transform .5s;
&.active{
transform: translateY(0)
}
}
.el-image-viewer__close{
z-index: 2000;
top: 15px;
right: 15px;
&.doc-close{
i{
color: #000 !important;
}
}
}
.list::-webkit-scrollbar {
width: 4px;
}
.list::-webkit-scrollbar-thumb {
border-radius: 10px;
background: rgba(0, 0, 0, 0.06);
}
.mask{
z-index: 9;
position: absolute;
background-color: rgb(57,58,61);
}
.word-mask{
z-index: 9;
position: absolute;
top: 0;
right: 0;
width: 100%;
background-color: rgb(243,242,241);
}
.word-mask1{
z-index: 9;
position: absolute;
top: 0;
right: 0;
width: 100%;
background-color: #185abd;
}
.word-mask2{
z-index: 9;
position: absolute;
background-color: transparent;
}
.excel-mask1{
z-index: 9;
position: absolute;
top: 0;
left: 20%;
width: 60%;
background-color: #107c41;
}
/deep/.pdf-dia{
border-radius: 0 !important;
.el-dialog__header{
display: none;
}
.el-dialog__body{
padding: 0;
}
.el-dialog__headerbtn{
top: 10px;
.el-dialog__close{
color: #fff;
font-size: 16px;
}
}
}
.pdf{
.arrow{
padding: 10px 0;
display: flex;
justify-content: center;
align-items: center;
font-size: 16px;
color: #fff;
background-color: #333;
.turn{
margin: 0 10px;
font-size: 18px;
cursor: pointer;
}
}
.pdf-wrap{
width: 80%;
margin: 0 auto;
}
}
</style>

@ -0,0 +1,111 @@
<template>
<div>
<ul class="list">
<li :class="{active: active == 1}" @click="toSystem(1)">
<img src="../assets/img/station1.png" alt="">
<p class="name">运营与管理</p>
<p class="text">电竞赛事运营与管理仿真实训系统</p>
</li>
<li :class="{active: active == 2}" @click="toSystem(2)">
<img src="../assets/img/station2.png" alt="">
<p class="name">编导</p>
<p class="text">电竞赛事编导仿真实训系统</p>
</li>
<li :class="{active: active == 3}" @click="toSystem(3)">
<img src="../assets/img/station3.png" alt="">
<p class="name">主持与解说</p>
<p class="text">电竞赛事主持与解说仿真实训系统</p>
</li>
<li :class="{active: active == 4}" @click="toSystem(4)">
<img src="../assets/img/station4.png" alt="">
<p class="name">数据分析</p>
<p class="text">电竞数据分析仿真实训系统</p>
</li>
<li :class="{active: active == 5}" @click="toSystem(5)">
<img src="../assets/img/station5.png" alt="">
<p class="name">品牌与运营</p>
<p class="text">电竞品牌运营与管理仿真实训系统</p>
</li>
</ul>
</div>
</template>
<script>
import bus from '@/libs/bus'
export default {
name: 'dashboard',
data() {
return {
active: 0
};
},
mounted() {
bus.$emit('setBg','backstage')
},
methods: {
toSystem(index){
}
}
};
</script>
<style lang="scss" scoped>
.list{
display: flex;
justify-content: center;
align-items: center;
height: calc(100vh - 120px);
li{
margin: 0 20px;
cursor: pointer;
&:nth-child(even){
margin-top: 200px;
}
.name{
margin-top: 10px;
line-height: 1;
font-size: 36px;
color: #fff;
font-family: youshe;
}
.text{
font-size: 14px;
color: rgba($color: #fff, $alpha: 0.85);
transition: .2s;
}
img{
max-width: 232px;
border: 3px solid transparent;
transition: .2s;
}
&:hover{
img{
border-color: #CC221C;
}
.name,.text{
color: #CC221C;
}
}
}
}
@media(max-width: 1630px){
.list{
li{
margin: 0 10px;
.name{
font-size: 30px;
}
.text{
font-size: 12px;
}
img{
max-width: 160px;
}
}
}
}
</style>

@ -0,0 +1,46 @@
<template>
<section class="main">
<div class="crumbs">
<el-breadcrumb separator="/">
<el-breadcrumb-item><i class="el-icon-lx-global"></i> {{$t('i18n.breadcrumb')}}</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="container">
<span>{{$t('i18n.tips')}}</span>
<el-button type="primary" @click="$i18n.locale = $i18n.locale === 'zh'?'en':'zh';">{{$t('i18n.btn')}}</el-button>
<div class="list">
<h2>{{$t('i18n.title1')}}</h2>
<p>{{$t('i18n.p1')}}</p>
<p>{{$t('i18n.p2')}}</p>
<p>{{$t('i18n.p3')}}</p>
</div>
<h2>{{$t('i18n.title2')}}</h2>
<div>
<i18n path="i18n.info" tag="p">
<a place="action" href="https://element.eleme.cn/2.0/#/zh-CN/component/i18n">{{ $t('i18n.value') }}</a>
</i18n>
</div>
</div>
</section>
</template>
<script>
export default {
data(){
return {
}
}
}
</script>
<style scoped>
.list{
padding: 30px 0;
}
.list p{
margin-bottom: 20px;
}
a{
color: #cb221c;
}
</style>

@ -0,0 +1,225 @@
<template>
<div>
<div class="crumbs">
<el-breadcrumb separator="/">
<el-breadcrumb-item><i class="el-icon-lx-emoji"></i> 自定义图标</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="container">
<h2>使用方法</h2>
<p style="line-height: 50px;">
直接通过设置类名为 el-icon-lx-iconName 来使用即可例如{{iconList.length}}个图标
</p>
<p class="example-p">
<i class="el-icon-lx-redpacket_fill" style="font-size: 30px;color: #ff5900"></i>
<span>&lt;i class=&quot;el-icon-lx-redpacket_fill&quot;&gt;&lt;/i&gt;</span>
</p>
<p class="example-p">
<i class="el-icon-lx-weibo" style="font-size: 30px;color:#fd5656"></i>
<span>&lt;i class=&quot;el-icon-lx-weibo&quot;&gt;&lt;/i&gt;</span>
</p>
<p class="example-p">
<i class="el-icon-lx-emojifill" style="font-size: 30px;color: #ffc300"></i>
<span>&lt;i class=&quot;el-icon-lx-emojifill&quot;&gt;&lt;/i&gt;</span>
</p>
<br>
<h2>图标</h2>
<div class="search-box">
<el-input class="search" size="large" v-model="keyword" clearable placeholder="请输入图标名称"></el-input>
</div>
<ul>
<li class="icon-li" v-for="(item,index) in list" :key="index">
<div class="icon-li-content">
<i :class="`el-icon-lx-${item}`"></i>
<span>{{item}}</span>
</div>
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
data: function(){
return {
keyword: '',
iconList: [
'attentionforbid',
'attentionforbidfill',
'attention',
'attentionfill',
'tag',
'tagfill',
'people',
'peoplefill',
'notice',
'noticefill',
'mobile',
'mobilefill',
'voice',
'voicefill',
'unlock',
'lock',
'home',
'homefill',
'delete',
'deletefill',
'notification',
'notificationfill',
'notificationforbidfill',
'like',
'likefill',
'comment',
'commentfill',
'camera',
'camerafill',
'warn',
'warnfill',
'time',
'timefill',
'location',
'locationfill',
'favor',
'favorfill',
'skin',
'skinfill',
'news',
'newsfill',
'record',
'recordfill',
'emoji',
'emojifill',
'message',
'messagefill',
'goods',
'goodsfill',
'crown',
'crownfill',
'move',
'add',
'hot',
'hotfill',
'service',
'servicefill',
'present',
'presentfill',
'pic',
'picfill',
'rank',
'rankfill',
'male',
'female',
'down',
'top',
'recharge',
'rechargefill',
'forward',
'forwardfill',
'info',
'infofill',
'redpacket',
'redpacket_fill',
'roundadd',
'roundaddfill',
'friendadd',
'friendaddfill',
'cart',
'cartfill',
'more',
'moreandroid',
'back',
'right',
'shop',
'shopfill',
'question',
'questionfill',
'roundclose',
'roundclosefill',
'roundcheck',
'roundcheckfill',
'global',
'mail',
'punch',
'exit',
'upload',
'read',
'file',
'link',
'full',
'group',
'friend',
'profile',
'addressbook',
'calendar',
'text',
'copy',
'share',
'wifi',
'vipcard',
'weibo',
'remind',
'refresh',
'filter',
'settings',
'scan',
'qrcode',
'cascades',
'apps',
'sort',
'searchlist',
'search',
'edit'
]
}
},
computed: {
list(){
return this.iconList.filter((item) => {
return item.indexOf(this.keyword) !== -1;
})
}
}
}
</script>
<style scoped>
.example-p{
height: 45px;
display: flex;
align-items: center;
}
.search-box{
text-align: center;
margin-top: 10px;
}
.search{
width: 300px;
}
ul,li{
list-style: none;
}
.icon-li{
display: inline-block;
padding: 10px;
width: 120px;
height: 120px;
}
.icon-li-content{
display: flex;
height: 100%;
flex-direction: column;
align-items: center;
justify-content: center;
cursor: pointer;
}
.icon-li-content i{
font-size: 36px;
color: #606266;
}
.icon-li-content span{
margin-top: 10px;
color: #787878;
}
</style>

@ -0,0 +1,302 @@
<template>
<div>
<div class="main">
<div class="nav">
<div class="sub-title">最新资讯</div>
<el-menu
v-if="menuList.length"
:default-active="defaultIndex"
class="sidebar"
@select="initData">
<template v-for="item in menuList">
<template v-if="item.secondColumn.length">
<el-submenu :index="item.id" :key="item.id">
<template slot="title">
<i :class="item.icon"></i>
<span slot="title">{{ item.name }}</span>
</template>
<template v-for="subItem in item.secondColumn">
<el-menu-item
:index="subItem.id"
:key="subItem.id"
>{{ subItem.name }}</el-menu-item>
</template>
</el-submenu>
</template>
<template v-else>
<el-menu-item :index="item.id" :key="item.id">
<i :class="item.icon"></i>
<span slot="title">{{ item.name }}</span>
</el-menu-item>
</template>
</template>
</el-menu>
</div>
<div class="list-wrap">
<div class="breadcrumb">
<span class="cur">当前位置</span>
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/' }">学生用户端</el-breadcrumb-item>
<el-breadcrumb-item :to="{ path: '/information' }">最新资讯</el-breadcrumb-item>
<el-breadcrumb-item>{{firstName}}</el-breadcrumb-item>
<el-breadcrumb-item v-if="secondName">{{secondName}}</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="list">
<template v-if="listData.length">
<ul>
<li v-for="(item,index) in listData" :key="index" @click="toArticle(item.id)">
<img :src="item.coverUrl" alt="">
<div class="text">
<div class="title">{{item.title}}</div>
<div class="desc" :class="{ie: core.isIE() || core.isEdge(),firefox: core.isFirefox() || core.isEdge()}" v-html="item.content"></div>
<div class="metas">
<span>作者{{item.author}}</span>
<span>{{item.date.replace(' 00:00:00','')}}</span>
</div>
</div>
</li>
</ul>
<div class="pagination">
<el-pagination background layout="total, prev, pager, next" :total="totals" @current-change="handleCurrentChange" :current-page="pageNo">
</el-pagination>
</div>
</template>
<template v-else>
<div class="empty">
<div>
<img src="../assets/img/none.png" alt="">
<p>暂无资讯</p>
</div>
</div>
</template>
</div>
</div>
</div>
</div>
</template>
<script>
import { Loading } from 'element-ui';
import bus from '@/libs/bus'
export default {
name: 'information',
data() {
return {
keyword: '',
userId: this.$store.state.userId,
historyId: this.$store.state.columnId,
defaultIndex: '',
menuList: [],
pageNo: 1,
pageSize: 10,
totals: 0,
listData: [],
loadIns: null,
columnId: '',
firstName: '',
secondName: ''
};
},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.getData()
},500)
}
},
mounted() {
bus.$emit('setBg','info')
this.getData()
},
methods: {
getData() {
this.$store.commit('addInfoData',{columnId: ''})
let data = {
page: this.pageNo,
size: this.pageSize
}
this.loadIns = Loading.service()
this.$get(this.api.queryAllColumns,data).then(res => {
this.menuList = res.data.columnTree
if(this.historyId){
this.defaultIndex = this.historyId
this.getContent(this.historyId)
}else{
if(this.menuList[0].secondColumn.length){
this.getContent(this.menuList[0].secondColumn[0].id)
this.defaultIndex = this.menuList[0].secondColumn[0].id
}else{
this.getContent(this.menuList[0].id)
this.defaultIndex = this.menuList[0].id
}
}
}).catch(res => {
this.loadIns.close()
});
},
initData(index,indexPath){
this.pageNo = 1
this.getContent(index,indexPath)
},
getContent(index,indexPath){
if(indexPath) this.loadIns = Loading.service()
this.columnId = index
let data = {
name: this.keyword,
columnId: index,
port: 0
}
let list = this.menuList
list.map(n => {
if(n.secondColumn.length){
n.secondColumn.map(e => {
if(e.id == index){
this.firstName = n.name
this.secondName = e.name
}
})
}else{
if(n.id == index){
this.firstName = n.name
this.secondName = ''
}
}
})
this.$get(`${this.api.queryArticleByCondition}/${this.pageNo}/${this.pageSize}`,data).then(res => {
this.listData = res.data.articleList
this.totals = res.data.total
this.listData.map(n => {
n.content = n.content.replace(/<img.*?(?:>|\/>)/gi,'')
})
this.loadIns.close()
}).catch(res => {
this.loadIns.close()
});
},
handleCurrentChange(val) {
this.pageNo = val;
this.getContent(this.columnId);
},
toArticle(id){
this.$store.commit('addInfoData',{columnId: this.columnId})
this.$router.push(`article?id=${id}&first=${this.firstName}&second=${this.secondName}`)
}
}
};
</script>
<style lang="scss" scoped>
.main{
display: flex;
justify-content: center;
align-items:flex-start;
padding: 265px 0 40px;
.nav{
width: 220px;
border-radius: 8px;
overflow: hidden;
.sub-title{
line-height: 88px;
color: #fff;
font-size: 24px;
text-align: center;
background: #CC221C;
}
/deep/.sidebar{
border-right: 0;
.el-submenu__title,.el-menu-item{
span{
font-size: 18px;
color: rgba(0,0,0,.85);
}
.el-submenu__icon-arrow{
font-size: 18px;
}
}
}
}
.list-wrap{
width: 50%;
margin-left: 40px;
.list{
padding: 32px;
background-color: #fff;
border-radius: 8px;
li{
display: flex;
padding-bottom: 24px;
margin-bottom: 20px;
border-bottom: 1px solid rgba(0, 0, 0, 0.06);
cursor: pointer;
transition: all 0.3s;
background-color: #fff;
overflow: hidden;
img{
width: 200px;
height: 120px;
border: 0;
}
.text{
width: calc(100% - 340px);
display: inline-flex;
flex: 1;
flex-direction: column;
justify-content: space-between;
padding: 0 24px;
.title{
font-size: 20px;
color: rgba(0,0,0,.85);
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
}
.desc{
font-size: 14px;
color: rgba(0,0,0,.65);
display: -webkit-box;
display:-moz-box;
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
-webkit-line-clamp: 2;
-moz-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
&.ie{
height: 80px;
text-overflow: ellipsis;
white-space: nowrap;
}
&.firefox{
height: 76px;
}
}
.metas{
display: inline-flex;
align-items: center;
width: 100%;
font-size: 12px;
color: rgba(0,0,0,.45);
span:first-child{
margin-right: 16px;
}
}
}
&:hover{
.text{
.title{
color: #CC221C;
}
}
border-bottom-color: #CC221C;
}
}
}
}
}
</style>

@ -0,0 +1,215 @@
<template>
<div class="wrap">
<div class="left">
<img class="logo" src="../assets/img/logo-full.png" alt="">
<img class="name" src="../assets/img/system-name.png" alt="">
</div>
<div class="right">
<div v-if="!isReg">
<h2>密码登录</h2>
<el-form :model="loginForm" :rules="loginRules" ref="login" label-width="0px">
<el-form-item prop="username">
<label class="account"></label>
<el-input v-model="loginForm.username" placeholder="请输入账号/手机号" @keyup.enter.native="submitForm()"></el-input>
</el-form-item>
<el-form-item prop="password">
<label class="password"></label>
<el-input type="password" placeholder="请输入密码" v-model="loginForm.password" @keyup.enter.native="submitForm()"></el-input>
</el-form-item>
<el-button class="submit" type="primary" @click="submitForm">登录</el-button>
</el-form>
</div>
<register v-else :isReg.sync="isReg" @updateInfo="updateInfo"></register>
</div>
</div>
</template>
<script>
import register from './registerForm';
import Setting from '@/setting';
export default {
data: function() {
return {
isReg: false,
loginForm: {
username: '',
// password: 'huoran123',
password: '',
},
loginRules: {
username: [{ required: true, message: '请输入账号', trigger: 'blur' }],
password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
},
roleDialog: false,
userId: '',
schoolId: '',
schoolName: '',
roleId: '',
roleList: []
};
},
components: {
register
},
mounted(){
},
methods: {
updateInfo(data){
this.loginForm.username = data.username
this.loginForm.password = data.password
},
submitForm() {
this.$refs.login.validate(valid => {
if (valid) {
let data = {
account: this.loginForm.username,
password: this.loginForm.password
}
this.$get(this.api.logins,data).then(res => {
if(res.success){
let user = res.data.userInfo
if(user.roleId == 4){
let routes = res.data.permissions[0].children
sessionStorage.setItem(Setting.usernameKey, this.loginForm.username);
user.userAvatars && this.$store.commit("setAvatarData", { avatar : user.userAvatars});
this.$store.commit("userLoginData", { userId : user.userId,accountRole: user.roleId});
this.$store.commit("userInfo", { name : user.userName,account: user.account,phone: user.phone,schoolId: user.clientId,schoolName: user.clientName});
this.$message.success('登录成功');
let redirect = decodeURIComponent(this.$route.query.redirect || '/course')
this.$router.replace(redirect)
}else{
this.$message.error('该用户没有权限')
}
}else{
this.$message.error(res.message)
}
}).catch(res => {});
}
});
},
toReg() {
this.isReg = true
},
},
};
</script>
<style scoped lang="scss">
.wrap {
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
background: url(../assets/img/login_bg.png) 0 0/100% 100% no-repeat;
overflow: hidden;
.left{
margin-right: 200px;
img{
display: block;
}
.logo{
max-width: 242px;
margin-bottom: 60px;
}
.name{
max-width: 663px;
}
}
.right{
padding: 40px 70px 50px;
background-color: #fff;
box-sizing: border-box;
border-radius: 16px;
h2{
font-size: 24px;
color: rgba(0, 0, 0, 0.85);
text-align: center;
font-weight: 400;
}
.el-form{
margin-top: 30px;
.label{
margin-bottom: 10px;
color: #105CB2;
}
/deep/.el-input__inner{
position: relative;
width: 320px;
height: 46px;
padding: 0 20px 0 40px;
line-height: 46px;
border: 1px solid #E6E6E6;
border-radius: 8px !important;
}
.account,.password{
z-index: 10;
position: absolute;
top: 11px;
left: 12px;
width: 24px;
height: 24px;
background: url(../assets/img/account.png) 0 0/100% 100% no-repeat;
}
.password{
background-image: url(../assets/img/password.png);
}
/deep/.el-form-item__error{
top: 105%;
left: auto;
right: 0;
color: #FFA94E;
}
.submit{
width: 100%;
height: 48px;
margin-top: 30px;
line-height: 48px;
padding: 0;
font-size: 20px;
background-color: #cb221c;
border-radius: 23px;
border: 0;
}
.links{
margin: 20px 0 20px;
}
.ques{
color: #cb221c;
font-size: 14px;
}
.forget{
color: #ffa94e;
font-size: 14px;
}
.login-tips{
margin-bottom: 20px;
font-size: 16px;
color: #105CB2;
text-align: center;
}
.thirdParty{
.item{
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 20px;
padding: 10px 0;
color: #AFB5BB;
font-size: 16px;
background-color: #eff0f1;
border-radius: 36px;
cursor: pointer;
img{
width: 40px;
margin-right: 10px;
}
}
}
}
}
}
</style>

@ -0,0 +1,496 @@
<template>
<div class="box">
<div class="search">
<input type="text" placeholder="请输入竞赛名称" v-model="keyword" />
<button><img src="../assets/img/search.png" alt=""> 搜索</button>
</div>
<div class="main">
<div class="nav">
<div class="sub-title">赛事报名</div>
<div class="sidebar">
<div class="item" :class="{ active: way === item.id }" v-for="(item, index) in typeList" :key="index" @click="changeType(item.id)">{{item.name}}</div>
</div>
</div>
<div class="list-wrap">
<div class="breadcrumb">
<span class="cur">当前位置</span>
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/' }">学生用户端</el-breadcrumb-item>
<el-breadcrumb-item :to="{ path: '/match' }">赛事报名</el-breadcrumb-item>
<el-breadcrumb-item>{{typeList.find(n => n.id === way).name}}</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="list">
<template v-if="listData.length">
<ul>
<li v-for="(item,index) in listData" :key="index" @click="toDetail(item)">
<div class="left">
<div class="cover">
<img :src="item.coverUrl" alt="">
</div>
<div class="info">
<div class="title">{{item.name}}</div>
<div class="metas">
<p :class="{'flex-top': item.sponsor.split(',').length > 1}">
<span class="label">主办方</span>
<template v-if="item.sponsor.split(',').length > 1">
<div>
<span v-for="(sponsor,index) in item.sponsor.split(',')" :key="index" class="val a-line">{{sponsor}}</span>
</div>
</template>
<span v-else class="val">{{item.sponsor}}</span>
</p>
<p :class="{'flex-top': item.undertaker.split(',').length > 1}">
<span class="label">承办方</span>
<template v-if="item.undertaker.split(',').length > 1">
<div>
<span v-for="(undertaker,index) in item.undertaker.split(',')" :key="index" class="val a-line">{{undertaker}}</span>
</div>
</template>
<span v-else class="val">{{item.undertaker}}</span>
</p>
<p><span class="label">报名时间</span><span class="val">{{item.signUpStartTime}} ~ {{item.signUpEndTime}}</span></p>
<p><span class="label">比赛时间</span><span class="val">{{item.playStartTime}} ~ {{item.playEndTime}}</span></p>
</div>
</div>
</div>
<div class="right">
<p class="status" :class="{wait: item.status == 0 || item.status == 4,signing: item.status == 2,signed: item.status == 1,finish: item.status == 3 || item.status == 5}" @click.stop="signup(item)">{{statusList[item.status]}}</p>
<p class="end-text" v-if="item.status != 5">距离{{endList[item.status]}}还有<template v-if="item.end > 0">{{item.end}}天</template><em v-else v-countdown="index">{{item.end}}</em></p>
</div>
</li>
</ul>
<div class="pagination">
<el-pagination background layout="total, prev, pager, next" :total="totals" @current-change="handleCurrentChange" :current-page="pageNo">
</el-pagination>
</div>
</template>
<template v-else>
<div class="empty">
<div>
<img src="../assets/img/none.png" alt="">
<p>暂无赛事</p>
</div>
</div>
</template>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
import { Loading } from 'element-ui';
import bus from '@/libs/bus'
export default {
name: 'match',
data() {
return {
way: '',
statusList: ['等待报名','已报名','立即报名','报名截止','比赛中','已结束'],
endList: ['报名开始','报名截止','报名截止','竞赛开始','竞赛结束',''],
typeList: [
{
id: '',
name: '近期报名'
},
{
id: 0,
name: '最近更新'
},
{
id: 1,
name: '已报名'
}
],
keyword: '',
searchTimer: null,
pageNo: 1,
pageSize: 10,
totals: 0,
listData: [],
covers: [],
loadIns: null,
contestIds: [],
isFirst: true,
timerList: [],
}
},
computed: {
...mapState([
'userId',
'name',
'account',
'phone',
'schoolName'
]),
},
directives: {
countdown: {
bind: function(el,binding,vnode) {
let that = vnode.context
let item = that.listData[binding.value]
let time = ''
let second = 1000
let minute = second * 60
let hour = minute * 60
let now = new Date().getTime()
let signUpStartTime = new Date(that.core.dateCompatible(item.signUpStartTime)).getTime()
let signUpEndTime = new Date(that.core.dateCompatible(item.signUpEndTime)).getTime()
let playStartTime = new Date(that.core.dateCompatible(item.playStartTime)).getTime()
let playEndTime = new Date(that.core.dateCompatible(item.playEndTime)).getTime()
switch(item.status){
case 0:
if(now > signUpStartTime){
item.status = 1
}else{
time = signUpStartTime - now
}
break
case 1:
if(now > signUpEndTime){
item.status = 3
}else{
time = signUpEndTime - now
}
break
case 2:
if(now > signUpEndTime){
item.status = 3
}else{
time = signUpEndTime - now
}
break
case 3:
if(now > playStartTime){
item.status = 4
}else{
time = playStartTime - now
}
break
case 4:
if(now > playEndTime){
item.status = 5
}else{
time = playEndTime - now
}
break
}
time = `${Math.floor(time / hour)}:${Math.floor(time % hour / minute)}:${Math.floor(time % hour % minute / second)}`
let timer = setInterval(() => {
let timeList = time.split(':')
let total = Number.parseInt(timeList[0] * 60 * 60) + Number.parseInt(timeList[1] * 60) + Number.parseInt(timeList[2])
if(total > 0){
--total
let hours = Math.floor(total / (60 * 60))
let minutes = Math.floor(total % (60 * 60) / 60)
let seconds = Math.floor(total % (60 * 60) % 60)
time = `${that.core.formateTime(hours)}:${that.core.formateTime(minutes)}:${that.core.formateTime(seconds)}`
}else{
clearInterval(timer)
}
el.innerHTML = time
},1000)
that.timerList.push(timer)
}
}
},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.getData()
},500)
}
},
mounted() {
bus.$emit('setBg','match')
this.getData()
this.$once('hook:beforeDestroy', function () {
this.timerList.forEach((n,k) => {
clearInterval(n)
})
this.timerList = []
})
},
methods: {
getData() {
let data = {
name: this.keyword,
way: this.way,
userId: this.userId
}
this.loadIns = Loading.service()
this.$get(`${this.api.onlineContestQuery}/${this.pageNo}/${this.pageSize }`,data).then(res => {
this.listData = res.data.contestList
let contestIds = res.data.contestIds
this.contestIds = contestIds
let time = 60 * 60 * 1000 * 24
let covers = []
this.listData.forEach((n,k) => {
let now = new Date().getTime()
let signUpStartTime = new Date(this.core.dateCompatible(n.signUpStartTime)).getTime()
let signUpEndTime = new Date(this.core.dateCompatible(n.signUpEndTime)).getTime()
let playStartTime = new Date(this.core.dateCompatible(n.playStartTime)).getTime()
let playEndTime = new Date(this.core.dateCompatible(n.playEndTime)).getTime()
if(now < signUpStartTime){
n.status = 0
n.end = Math.floor((signUpStartTime - now) / time)
}else if(now > signUpStartTime && now < signUpEndTime){
n.status = 1
n.end = Math.floor((signUpEndTime - now) / time)
}else if(now > signUpEndTime && now < playStartTime){
n.status = 3
n.end = Math.floor((playStartTime - now) / time)
}else if(now > playStartTime && now < playEndTime){
n.status = 4
n.end = Math.floor((playEndTime - now) / time)
}else if(now > playEndTime){
n.status = 5
}
let isInclude = contestIds.includes(n.id)
if(n.status == 1 && !isInclude){
n.status = 2
n.signup = true
}else{
n.signup = false
}
(covers.length < 3 && n.carouselUrl) && covers.push(n)
})
if(this.isFirst) this.covers = covers
this.totals = res.data.total
this.loadIns.close()
this.isFirst = false
}).catch(res => {
this.loadIns.close()
});
},
changeType(type) {
this.way = type;
if(type != 1){
this.getData()
}else{
let listData = this.listData
let result = []
listData.forEach((n,k) => {
let isInclude = this.contestIds.includes(n.id)
if(n.status == 1 && isInclude){
result.push(n)
}
})
this.listData = result
this.totals = this.listData.length
}
},
toDetail(item) {
let status = item.status == 1 ? (item.signup ? true : false) : 'hide'
this.$store.commit("matchSignup", { matchId : item.id,matchSignupStatus: status})
this.$router.push(`matchDetail`)
},
handleCurrentChange(val) {
this.pageNo = val
this.getData()
},
signup(item){
if(item.status == 2 && item.signup){
let data = {
contestId: item.id,
account: this.account,
phone: this.phone,
school: this.schoolName,
userId: this.userId,
username: this.name
}
this.$post(this.api.addApplicant,data).then(res => {
if(res.success){
this.$message.success('报名成功')
this.getData()
}else{
this.$message.error(res.message)
}
}).catch(res => {})
}
}
}
};
</script>
<style lang="scss" scoped>
.box{
padding-top: 108px;
.search{
margin-bottom: 108px;
}
.main{
display: flex;
justify-content: center;
align-items:flex-start;
padding-bottom: 40px;
margin-top: 20px;
.nav{
width: 220px;
border-radius: 8px;
overflow: hidden;
.sub-title{
line-height: 88px;
color: #fff;
font-size: 24px;
text-align: center;
background: #CC221C;
}
/deep/.sidebar{
background-color: #fff;
.item{
padding: 15px 0;
color: rgba(0,0,0,.85);
font-size: 18px;
text-align: center;
cursor: pointer;
&.active{
color: #CC221C;
}
&:hover{
background-color: #fae9e8;
}
}
}
}
.list-wrap{
width: 50%;
min-width: 790px;
margin-left: 40px;
.list{
padding: 32px;
background-color: #fff;
border-radius: 8px;
li{
display: flex;
justify-content: space-between;
padding-bottom: 24px;
margin-bottom: 20px;
border-bottom: 1px solid rgba(0, 0, 0, 0.06);
transition: all 0.3s;
cursor: pointer;
.left{
display: inline-flex;
.cover{
img{
width: 200px;
height: 120px;
border-radius: 4px;
}
}
.info{
display: inline-flex;
flex-direction: column;
justify-content: space-between;
margin-left: 20px;
.title{
font-size: 20px;
color: rgba(0,0,0,.85);
}
.metas{
font-size: 14px;
color: #999;
p{
display: flex;
align-items: center;
margin-bottom: 5px;
&.flex-top{
align-items: flex-start;
}
}
.label,.val{
font-size: 14px;
color: rgba(0,0,0,.65);
white-space: nowrap;
}
.val{
max-width: 350px;
}
.a-line{
display: block;
}
}
.desc{
font-size: 14px;
}
}
}
.right{
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-end;
flex: 1;
.status{
padding: 0 15px;
line-height: 32px;
font-size: 12px;
color: #fff;
background-color: #52C41A;
border-radius: 4px;
&.wait{
background-color: #FAAD14;
}
&.signing{
background-color: #CC221C;
}
&.signed{
background-color: #52C41A;
}
&.finish{
background-color: rgba(0,0,0,.45);
}
}
.btn{
padding: 12px 20px;
color: #fff;
background-color: #cb221c;
border-radius: 4px;
cursor: pointer;
&:hover{
opacity: .9;
}
&.disabled{
cursor: not-allowed;
background-color: #969696;
}
}
.end-text{
margin-top: 10px;
color: rgba(0,0,0,.65);
font-size: 14px;
white-space: nowrap;
em{
font-size: 20px;
font-style: normal;
font-weight: bold;
color: #cb221c;
}
}
}
&:hover{
.left{
.info{
.title{
color: #CC221C;
}
}
}
border-bottom-color: #CC221C;
}
}
}
}
}
}
</style>

@ -0,0 +1,370 @@
<template>
<div>
<div class="main">
<div class="nav">
<div class="sub-title">赛事报名</div>
<div class="sidebar">
<div class="item" :class="{ active: curType === item.id }" v-for="(item, index) in typeList" :key="index" @click="tabChange(item.id)">{{item.name}}</div>
</div>
</div>
<div class="content-wrap">
<div class="breadcrumb">
<span class="cur">当前位置</span>
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/' }">学生用户端</el-breadcrumb-item>
<el-breadcrumb-item :to="{ path: '/match' }">赛事报名</el-breadcrumb-item>
<el-breadcrumb-item>{{typeList.find(n => n.id == curType).name}}</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="content">
<h6 class="title">{{title}}</h6>
<div class="meta">最近编辑时间{{gmtModified}}</div>
<div class="texts ql-editor" v-html="description" v-if="curType == 1"></div>
<div v-else>
<ul class="progress" v-if="progress.length">
<li v-for="(item,index) in progress" :key="index">
<i class="dot" :class="[item.status == 0 ? 'not' : (item.status == 1 ? 'ing' : 'done el-icon-circle-check')]"></i>
<p class="name">{{item.title}}</p>
<p class="desc">{{item.description}}</p>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
import { Loading } from 'element-ui';
import 'quill/dist/quill.core.css';
import 'quill/dist/quill.snow.css';
import 'quill/dist/quill.bubble.css';
import bus from '@/libs/bus'
export default {
name: 'matchdetail',
data() {
return {
id: this.$store.state.matchId,
showSignup: this.$store.state.matchSignupStatus,
coverUrl: '',
title: '',
time: '',
curType: 1,
typeList: [
{
id: 1,
icon: 'el-icon-document',
name: '竞赛信息'
},
{
id: 2,
icon: 'el-icon-setting',
name: '竞赛进展'
}
],
description: '',
gmtModified: '',
progress: [],
end: '',
status: 0,
statusList: ['准备报名','正在报名','准备竞赛','竞赛中','竞赛结束'],
endList: ['报名开始','报名截止','竞赛开始','竞赛结束',''],
loadIns: null
};
},
computed: {
...mapState([
'userId',
'name',
'account',
'phone',
'schoolName'
]),
},
mounted() {
bus.$emit('setBg','match')
this.getData()
this.getProgress()
},
methods: {
getData() {
this.loadIns = Loading.service()
this.$get(this.api.getContest + '/' + this.id)
.then(res => {
let data = res.data.contest
this.coverUrl = data.carouselUrl
this.description = data.description
this.title = data.name
this.gmtModified = data.gmtModified
let time = 60 * 60 * 1000 * 24
let now = new Date().getTime()
let signUpStartTime = new Date(data.signUpStartTime).getTime()
let signUpEndTime = new Date(data.signUpEndTime).getTime()
let playStartTime = new Date(data.playStartTime).getTime()
let playEndTime = new Date(data.playEndTime).getTime()
if(now < signUpStartTime){
this.status = 0
this.end = Math.floor((signUpStartTime - now) / time)
this.time = `报名开始时间:${data.signUpStartTime}`
}else if(now > signUpStartTime && now < signUpEndTime){
this.status = 1
this.end = Math.floor((signUpEndTime - now) / time)
this.time = `报名结束时间:${data.signUpEndTime}`
}else if(now > signUpEndTime && now < playStartTime){
this.status = 2
this.end = Math.floor((playStartTime - now) / time)
this.time = `竞赛开始时间:${data.playStartTime}`
}else if(now > playStartTime && now < playEndTime){
this.status = 3
this.end = Math.floor((playEndTime - now) / time)
this.time = `竞赛结束时间:${data.playEndTime}`
}else if(now > playEndTime){
this.status = 4
this.time = '竞赛结束'
}
this.loadIns.close()
})
.catch(err => {
this.loadIns.close()
});
},
getProgress() {
this.$get(this.api.getContestProgress + '/' + this.id)
.then(res => {
this.progress = res.data.contestProgressList
})
.catch(err => {
});
},
toArticle(id){
this.$router.push('article?id=' + id)
},
tabChange(index){
this.curType = index
},
signup(){
let data = {
contestId: this.id,
account: this.account,
phone: this.phone,
school: this.schoolName,
userId: this.userId,
userName: this.name
}
this.$post(this.api.addApplicant,data).then(res => {
if(res.success){
this.$message.success('报名成功')
this.$store.commit("matchSignup", { matchId : this.id,matchSignupStatus: false })
this.showSignup = false
}else{
this.$message.error(res.message)
}
}).catch(res => {})
}
}
};
</script>
<style lang="scss" scoped>
.main{
display: flex;
justify-content: center;
align-items:flex-start;
padding: 265px 0 20px;
.nav{
width: 220px;
border-radius: 8px;
overflow: hidden;
.sub-title{
line-height: 88px;
color: #fff;
font-size: 24px;
text-align: center;
background: #CC221C;
}
/deep/.sidebar{
background-color: #fff;
.item{
padding: 15px 0;
color: rgba(0,0,0,.85);
font-size: 18px;
text-align: center;
cursor: pointer;
&.active{
color: #CC221C;
}
&:hover{
background-color: #fae9e8;
}
}
}
}
.content-wrap{
width: 950px;
margin-left: 40px;
@media(max-width: 1300px){
width: 700px;
}
.content{
position: relative;
padding: 20px 60px;
background-color: #fff;
border-radius: 8px;
.title{
width: 67%;
margin: 0 auto;
font-size: 24px;
text-align: center;
color: rgba(0, 0, 0, 0.85);
}
.meta{
padding: 16px 0 32px;
font-size: 12px;
color: rgba(0, 0, 0, 0.45);
text-align: center;
border-bottom: 1px solid rgba(0, 0, 0, 0.06);
}
.texts{
margin: 20px 0 50px;
font-size: 16px;
line-height: 1.6;
text-indent: 2em;
overflow: hidden;
/deep/img{
max-width: 100%;
}
}
.progress{
position: relative;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
padding: 50px 0;
margin: 40px 0 20px;
&:before{
content: '';
position: absolute;
left: 413px;
width: 1px;
height: 100%;
background-color: #E6E6E6;
@media(max-width: 1300px){
left: 289px;
}
}
li{
position: relative;
display: inline-flex;
align-items: center;
width: 90%;
margin-bottom: 40px;
.dot{
position: absolute;
left: 366px;
width: 13px;
height: 13px;
background-color: #fff;
&.not{
border-radius: 50%;
background-color: #fff;
border: 1px solid #cb221c;
}
&.ing{
width: 13px;
height: 13px;
padding: 1px;
border: 1px solid #cb221c;
border-radius: 50%;
background-color: #cb221c;
background-clip: content-box;
}
&.done{
left: 365px;
color: #cb221c;
font-size: 16px;
}
@media(max-width: 1300px){
left: 254px;
&.done{
left: 253px;
}
}
}
.name{
width: 43%;
font-size: 24px;
color: rgba(0, 0, 0, 0.85);
}
.desc{
position: relative;
padding: 24px 30px;
text-align: center;
color: rgba(0, 0, 0, 0.85);
font-size: 16px;
background-color: #fff;
border: 1px solid #E6E6E6;
border-radius: 8px;
&:before{
content: '';
z-index: 2;
position: absolute;
top: 28px;
left: -16px;
border: 8px solid transparent;
border-right-color: #fff;
}
&:after{
content: '';
z-index: 1;
position: absolute;
top: 27px;
left: -18px;
border: 9px solid transparent;
border-right-color: #E6E6E6;
}
}
&:nth-child(even){
flex-direction: row-reverse;
.name{
margin-left: 16%;
text-align: left;
}
.desc{
&:before{
left: auto;
right: -16px;
border: 8px solid transparent;
border-left-color: #fff;
}
&:after{
left: auto;
right: -18px;
border: 9px solid transparent;
border-left-color: #E6E6E6;
}
}
}
&:nth-child(odd){
.name{
margin-right: 16%;
text-align: right;
}
}
&:last-child{
margin-bottom: 0;
}
}
}
}
}
}
</style>

@ -0,0 +1,439 @@
<template>
<div>
<div class="page">
<div class="tabs">
<a class="item" v-for="(item,index) in tabs" :key="index" :class="{active: index == active}" @click="tabChange(index)">{{item}}</a>
</div>
<div class="page-content">
<div v-if="active == 'first'">
<el-form>
<ul class="list">
<li>
<label>头像</label>
<div class="avatar-wrap">
<img :src="this.$store.state.avatar" class="avatar" />
<el-upload :action="this.api.uploadUserAvatars" :data="{userId:this.userId}" name="file" :limit="3" :on-success="getRes">
<el-button size="small"><img src="../assets/img/upload.png" alt=""> 上传头像</el-button>
</el-upload>
</div>
</li>
<li>
<label>姓名</label>
<div>
<el-input v-model="personalInformation.userName" clearable></el-input>
</div>
</li>
<li>
<label>性别</label>
<div>
<el-select v-model="personalInformation.sex">
<el-option v-for="item in sexList" :key="item.value" :label="item.name" :value="item.value"></el-option>
</el-select>
</div>
</li>
<li>
<label>所在国家</label>
<div>
<el-select
v-model="personalInformation.countries"
placeholder
>
<el-option
v-for="item in countryList"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</div>
</li>
<li>
<label>所在省份</label>
<div>
<el-select
v-model="personalInformation.provinceId"
placeholder
@change="id => getCity(id,1)"
>
<el-option
v-for="item in provinceList"
:key="item.provinceId"
:label="item.provinceName"
:value="item.provinceId"
></el-option>
</el-select>
</div>
</li>
<li>
<label>所在省市</label>
<div>
<el-select
v-model="personalInformation.cityId"
placeholder
:disabled="personalInformation.provinceId ? false : true"
>
<el-option
v-for="item in cityList"
:key="item.cityId"
:label="item.cityName"
:value="item.cityId"
></el-option>
</el-select>
</div>
</li>
<li>
<label>出生年月日</label>
<div>
<el-date-picker
v-model="personalInformation.dateBirth"
:clearable="false"
class="block-right"
type="date">
</el-date-picker>
</div>
</li>
<li>
<label>证件</label>
<div>
<el-input v-model="personalInformation.idnumber" clearable></el-input>
</div>
</li>
<li>
<label>教育程度</label>
<div>
<el-select
v-model="personalInformation.educationDegree"
placeholder="请选择教育程度"
>
<el-option
v-for="(item,index) in educationDegreeList"
:key="index"
:label="item.name"
:value="item.value"
></el-option>
</el-select>
</div>
</li>
</ul>
</el-form>
</div>
<div v-else>
<ul class="list">
<li>
<label>用户账号</label>
<div>
<el-input v-model="personalInformation.account" clearable></el-input>
</div>
</li>
<li>
<label>手机号</label>
<div>
<el-input v-model="personalInformation.phone" clearable></el-input>
</div>
</li>
<li>
<label>邮箱</label>
<div>
<el-input v-model="personalInformation.email" clearable></el-input>
</div>
</li>
<li>
<label>密码</label>
<div>
<el-button size="small" @click="bindPassword">更换密码</el-button>
</div>
</li>
</ul>
</div>
<div style="margin-top: 32px">
<el-button type="primary" size="small" v-throttle @click="save">更新</el-button>
</div>
</div>
</div>
<el-dialog
title="更换密码"
:visible.sync="passwordVisible"
:close-on-click-modal="false"
@close="closePassword"
width="30%">
<el-form ref="passwordForm" :model="form" label-width="60px">
<el-form-item label="原密码">
<el-input type="password" v-model="passwordForm.password" placeholder="请输入原密码"></el-input>
</el-form-item>
<el-form-item label="新密码">
<el-input type="password" v-model="passwordForm.newPassword" placeholder="请输入新密码" @keyup.enter.native="editPassword"></el-input>
</el-form-item>
<el-form-item label="新密码">
<el-input type="password" v-model="passwordForm.reNewPassword" placeholder="请确认新密码" @keyup.enter.native="editPassword"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="passwordVisible = false"> </el-button>
<el-button type="primary" @click="editPassword"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import _ from 'lodash';
import bus from '@/libs/bus'
export default {
data() {
return {
active: 'first',
tabs: {
first: '用户信息',
second: '账号信息'
},
userId: this.$store.state.userId,
personalInformation: {
name:'',
workNumber:'',
password:"",
phone:'',
email:'',
provinceName:'',
cityName:'',
schoolName:'',
professionalName:'',
},
passwordVisible: false,
passwordForm: {
password: '',
newPassword: '',
reNewPassword: ''
},
sexList: [
{
name: '男',
value: 1
},
{
name: '女',
value: 2
}
],
countryList: [
{
label: '中国'
}
],
form: {},
provinceList: this.$store.state.provinceList, //
cityList: [], //
//
educationDegreeList: [
{
name: '专科',
value: 1
},
{
name: '本科',
value: 2
},
{
name: '硕士',
value: 3
},
{
name: '博士',
value: 4
},
{
name: '其他',
value: 5
}
],
schoolList: [],
curPassword: '',
accountRepeat: false
};
},
mounted() {
bus.$emit('setBg','course')
this.getdata();
this.getProvince()
this.getSchoolData()
},
methods: {
tabChange(index){
this.active = index
},
getProvince(){
this.$get(this.api.queryProvince).then(res => {
this.provinceList = res.data.list
this.$store.commit("provinceData", { provinceList : this.provinceList});
}).catch(res => {});
},
//
getCity(){
this.personalInformation.cityId = 1
this.getCityData()
},
getCityData(){
console.log(33,this.personalInformation.provinceId)
let provinceId = this.personalInformation.provinceId
this.$get(this.api.queryCity,{provinceId}).then(res => {
this.cityList = res.data.list
}).catch(res => {});
},
//
getSchoolData(){
let data = {
searchContent: '',
provinceId: '',
cityId: ''
}
this.$get(`${this.api.queryClient}/1/1000`,data).then(res => {
this.schoolList = res.data.list
}).catch(res => {});
},
accountChange(){
this.$get(`${this.api.getAccount}?account=${this.form.account}`).then(res => {
if(res.data.userInfo){
this.accountRepeat = true
this.$message.warning('该账号已存在')
}else{
this.accountRepeat = false
}
}).catch(res => {});
},
//
getRes(res) {
this.$store.commit('setAvatarData',{avatar:res.message})
bus.$emit('updateAvatar',res.message)
let data = {
userId: this.userId,
userAvatars: res.message
}
this.$post(this.api.userinfoUpdate,data).then(res => {}).catch(res => {})
},
uploadHeadImg: function() {
this.$el.querySelector('.hiddenInput').click();
},
getdata() {
this.$get(`${this.api.userinfo}?userId=${this.userId}`)
.then(res => {
this.personalInformation = res.data.userInfo
this.personalInformation.countries = '中国'
this.curPassword = this.personalInformation.password
this.$nextTick(() => {
if(this.personalInformation.provinceId){
this.getCityData()
}
})
})
.catch(err => {
console.log(err);
});
},
bindPassword() {
this.passwordVisible = true
},
editPassword() {
if(!this.passwordForm.password) return this.$message.warning('请输入原密码')
if(!this.passwordForm.newPassword) return this.$message.warning('请输入新密码')
if(!this.passwordForm.reNewPassword) return this.$message.warning('请确认新密码')
if(this.passwordForm.newPassword.length < 6 || this.passwordForm.reNewPassword.length < 6) return this.$message.warning('请输入6位数以上的密码')
if(this.passwordForm.newPassword !== this.passwordForm.reNewPassword) return this.$message.warning('输入的新密码不一致,请重新确认')
if(this.curPassword === this.passwordForm.newPassword) return this.$message.warning('原密码跟新密码不能一致')
let data = {
userId: this.personalInformation.userId,
password: this.passwordForm.password
}
this.$post(this.api.userinfoUpdate,data)
.then(res => {
if(res.success){
this.$message.success('更换成功')
this.curPassword = this.passwordForm.newPassword
this.passwordVisible = false
}else{
this.$message.error('更换失败')
}
})
.catch(err => {
console.log(err);
});
},
closePassword() {
this.passwordForm = {
password: '',
newPassword: '',
reNewPassword: ''
}
},
save() {
if(this.personalInformation.idnumber && !/(^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$)/.test(this.personalInformation.idnumber)) return this.$message.warning('请输入正确的证件号码')
if(this.accountRepeat) return this.$message.warning('该账号已存在')
if(this.personalInformation.phone && !/^1[3456789]\d{9}$/.test(this.personalInformation.phone)) return this.$message.warning('请输入正确的手机号')
if(this.personalInformation.email && !/^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/.test(this.personalInformation.email)) return this.$message.warning('请输入正确的邮箱')
this.personalInformation.clientName = this.schoolList.find(n => n.id == this.personalInformation.clientId).clientName
let personalInformation = this.personalInformation
let userInfoEntity = {
idnumber: personalInformation.idnumber,
account: personalInformation.account,
cityId: personalInformation.cityId,
countries: personalInformation.countries,
dateBirth: personalInformation.dateBirth,
educationDegree: personalInformation.educationDegree,
email: personalInformation.email,
phone: personalInformation.phone,
provinceId: personalInformation.provinceId,
clientId: personalInformation.clientId,
clientName: personalInformation.clientName,
sex: personalInformation.sex,
userId: personalInformation.userId,
userName: personalInformation.userName,
}
let data = userInfoEntity
this.$post(this.api.userinfoUpdate,data).then(res => {
if(res.success){
this.$message.success('提交成功')
this.$router.back()
}else{
this.$message.error('提交失败')
}
}).catch(res => {})
}
}
};
</script>
<style lang="scss" scoped>
/deep/.page{
width: 70%;
margin: 50px auto 20px;
.page-content{
padding-top: 0;
.list{
li{
display: flex;
align-items: center;
padding: 16px 0;
border-bottom: 1px solid rgba(0, 0, 0, 0.06);
label{
width: 180px;
color: rgba(0, 0, 0, 0.85);
font-size: 16px;
}
.avatar-wrap{
display: inline-flex;
align-items: center;
.avatar{
width: 64px;
height: 64px;
margin-right: 24px;
border-radius: 100%;
}
}
.el-input{
width: 320px;
}
}
}
}
}
</style>

@ -0,0 +1,311 @@
<template>
<div>
<!-- <h2>学生注册 <div class="back" @click="toLogin">返回登录</div></h2> -->
<h2>学生注册</h2>
<el-form class="register" :model="regForm" :rules="regRules" ref="reg" label-width="0px">
<div class="line">
<el-form-item prop="userName">
<p class="label">*学生姓名</p>
<el-input v-model="regForm.userName" placeholder="姓名"></el-input>
</el-form-item>
<!-- <el-form-item prop="workNumber" style="margin-right: 5%">
<p class="label">学生学号</p>
<el-input v-model="regForm.workNumber" placeholder="学生学号" @change="worknumberChange"></el-input>
</el-form-item> -->
<el-form-item prop="phone">
<p class="label">*手机号</p>
<el-input v-model="regForm.phone" placeholder="手机号" maxlength="11" @change="phoneChange"></el-input>
</el-form-item>
</div>
<p class="label">*学校</p>
<div class="line">
<el-form-item prop="provinceId">
<p class="prop">省份</p>
<el-select v-model="regForm.provinceId" placeholder="省份" @change="getCity">
<el-option
v-for="item in provinceList"
:key="item.value"
:label="item.provinceName"
:value="item.provinceId"
></el-option>
</el-select>
</el-form-item>
<el-form-item prop="cityId" style="margin-right: 5%">
<p class="prop">城市</p>
<el-select v-model="regForm.cityId" placeholder="城市" :disabled="regForm.provinceId == ''">
<el-option
v-for="item in cityList"
:key="item.value"
:label="item.cityName"
:value="item.cityId"
></el-option>
</el-select>
</el-form-item>
<el-form-item prop="clientId">
<p class="prop">学校</p>
<el-select v-model="regForm.clientId" placeholder="学校名称">
<el-option v-for="(item,index) in schoolList" :key="index" :label="item.clientName" :value="item.id"></el-option>
</el-select>
</el-form-item>
</div>
<!-- <div class="line">
<el-form-item prop="phone">
<p class="label">手机号</p>
<el-input v-model="regForm.phone" placeholder="请输入手机号"></el-input>
</el-form-item>
<el-form-item style="margin-right: 5%">
<button type="button" class="code-btn">发送验证码</button>
</el-form-item>
<el-form-item prop="code">
<el-input v-model="regForm.code" placeholder="输入验证码"></el-input>
</el-form-item>
</div> -->
<div class="line">
<el-form-item prop="password">
<p class="label">*密码设置</p>
<el-input type="password" v-model="regForm.password" placeholder="请输入密码"></el-input>
</el-form-item>
<el-form-item prop="rePassword">
<el-input type="password" v-model="regForm.rePassword" placeholder="请再次输入密码" @keyup.enter.native="registerForm"></el-input>
</el-form-item>
</div>
<el-button class="submit" type="primary" @click="registerForm">注册</el-button>
</el-form>
</div>
</template>
<script>
export default {
data: function() {
return {
regForm: {
userName: '',
// workNumber: '',
provinceId: '',
cityId: '',
clientId: '',
phone: '',
password: '',
rePassword: '',
roleId: 4
},
regRules: {
userName: [{ required: true, message: '请输入学生姓名', trigger: 'blur' }],
// workNumber: [{ required: true, message: '', trigger: 'blur' }],
provinceId: [{ required: true, message: '请选择省份', trigger: 'change' }],
cityId: [{ required: true, message: '请选择城市', trigger: 'change' }],
clientId: [{ required: true, message: '请选择学校', trigger: 'change' }],
phone: [
{ required: true, message: '请输入手机号', trigger: 'blur' },
{ pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ pattern: /^.{6,}$/, message: '请输入6位数以上的密码', trigger: 'blur' }
],
rePassword: [
{ required: true, message: '请再次输入密码', trigger: 'blur' },
{ pattern: /^.{6,}$/, message: '请输入6位数以上的密码', trigger: 'blur' }
]
},
provinceList: this.$store.state.provinceList, //
cityList: [], //
schoolList: [],
phoneRepeat: false,
workNumberReapeat: false
};
},
mounted() {
this.getProvince()
this.getSchoolData()
},
methods: {
getProvince(){
this.$get(this.api.queryProvince).then(res => {
this.provinceList = res.data.list
this.$store.commit("provinceData", { provinceList : res.data.list})
}).catch(res => {});
},
//
getCity(){
if(this.regForm.provinceId){
this.getCityData()
}
},
getCityData(){
this.$get(this.api.queryCity,{provinceId: this.regForm.provinceId}).then(res => {
this.cityList = res.data.list
}).catch(res => {});
},
//
getSchoolData(){
let data = {
searchContent: '',
provinceId: '',
cityId: ''
}
this.$get(`${this.api.queryClient}/1/1000`,data).then(res => {
this.schoolList = res.data.list
}).catch(res => {});
},
registerForm() {
this.$refs.reg.validate(valid => {
if (valid) {
if(this.phoneRepeat) return this.$message.warning('该手机号已存在')
if(this.workNumberReapeat) return this.$message.warning('该学生学号已存在')
if(this.regForm.password !== this.regForm.rePassword) return this.$message.warning('两次输入的密码不一致,请重新输入')
let data = this.regForm
data.clientName = this.schoolList.find(n => n.id == this.regForm.clientId).clientName
data.account = data.phone
data.uniqueIdentificationAccount = new Date().getTime()
data.creationTime = this.core.formatDate("yyyy-MM-dd hh:mm:ss",new Date())
this.$post(this.api.save,data).then(res => {
if(res.success){
this.$message.success('注册成功')
this.$emit('update:isReg',false)
this.$emit('updateInfo',{username: this.regForm.phone,password: this.regForm.password})
this.$refs.reg.resetFields()
}else{
this.$message.error('注册失败');
}
}).catch(res => {});
}
});
},
async phoneChange(){
let res = await this.$get(this.api.queryPhone, { phone: this.regForm.phone });
if(res.message.length != 0){
this.$message.warning('该手机号已存在');
this.phoneRepeat = true
}else{
this.phoneRepeat = false
}
},
toLogin() {
this.$emit('update:isReg',false)
}
},
};
</script>
<style scoped lang="scss">
.wrap {
.right{
h2{
position: relative;
padding-bottom: 10px;
font-size: 24px;
font-weight: 400;
color: #303d4c;
text-align: center;
border-bottom: 1px solid #E5E5E5;
.back{
position: absolute;
top: 5px;
right: 0;
font-size: 12px;
color: #ccc;
cursor: pointer;
}
}
.el-form{
margin-top: 30px;
.label{
margin-bottom: 10px;
color: #cb221c;
font-size: 14px;
}
/deep/.el-input__inner{
height: 46px;
padding: 0 23px;
line-height: 46px;
border: 1px solid #AFB5BB;
border-radius: 23px !important;
}
/deep/.el-form-item__error{
top: 105%;
left: auto;
right: 0;
color: #FFA94E;
}
.submit{
width: 100%;
height: 48px;
margin-top: 30px;
line-height: 48px;
padding: 0;
font-size: 20px;
background-color: #cb221c;
border-radius: 23px;
border: 0;
}
.links{
margin: 20px 0 20px;
}
.ques{
color: #cb221c;
font-size: 14px;
}
.forget{
color: #ffa94e;
font-size: 14px;
}
.login-tips{
margin-bottom: 20px;
font-size: 16px;
color: #105CB2;
text-align: center;
}
.thirdParty{
.item{
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 20px;
padding: 10px 0;
color: #AFB5BB;
font-size: 16px;
background-color: #eff0f1;
border-radius: 36px;
cursor: pointer;
img{
width: 40px;
margin-right: 10px;
}
}
}
}
.register{
.line{
display: flex;
justify-content: space-between;
align-items: flex-end;
}
.el-form-item{
&:first-child{
margin-right: 5%;
}
}
.label{
margin-bottom: 0;
}
.code-btn{
min-width: 120px;
height: 46px;
padding: 0 10px;
line-height: 46px;
color: #fff;
font-size: 14px;
border-radius: 23px;
border: 0;
background-color: #105cb2;
}
}
}
}
</style>

@ -0,0 +1,137 @@
<template>
<div class="box pd20">
<el-card shadow="hover" class="mgb20">
<div class="search">
<!-- <el-input placeholder="请输入关键词" v-model="input3" class="input-with-select">
<el-button slot="append" icon="el-icon-search"></el-button>
</el-input> -->
<input type="text" placeholder="请输入关键词">
<button>搜索</button>
</div>
<div class="wrap">
<a class="item" @click="jump">
<div class="icon">
<img src="../assets/img/station1.png" alt="">
</div>
<p class="text">Python程序设计</p>
</a>
<a class="item" @click="jump">
<div class="icon" style="background-color: #60b8f6">
<img src="../assets/img/station2.png" alt="">
</div>
<p class="text">银行实践平台</p>
</a>
<a class="item" @click="jump">
<div class="icon" style="background-color: #fbbb6e">
<img src="../assets/img/station3.png" alt="">
</div>
<p class="text">大数据平台</p>
</a>
<a class="item" @click="jump">
<div class="icon" style="background-color: #ec92e0">
<img src="../assets/img/station4.png" alt="">
</div>
<p class="text">可视化实践平台</p>
</a>
<a class="item" @click="jump">
<div class="icon" style="background-color: #f9746a">
<img src="../assets/img/station5.png" alt="">
</div>
<p class="text">数据清洗平台</p>
</a>
</div>
</el-card>
</div>
</template>
<script>
export default {
name: 'station',
data() {
return {
userId: this.$store.state.userId,
};
},
mounted() {
},
methods: {
jump(){
location.href = 'http://www.liuwanr.cn:8080/pythonProject/#/'
}
}
};
</script>
<style lang="scss" scoped>
.search{
position: relative;
width: 30%;
margin: 100px auto 100px;
border-radius: 30px;
border: 1px solid #cb221c;
border-right: 0;
overflow: hidden;
input{
width: 100%;
height: 44px;
line-height: 44px;
padding: 0 20px;
font-size: 14px;
color: #333;
border: 0;
outline: none !important;
box-sizing: border-box;
}
button{
position: absolute;
top: 0;
right: 0;
padding: 0 20px;
line-height: 44px;
color: #fff;
background-color: #cb221c;
border: 0;
outline: none !important;
}
}
.wrap{
display: flex;
justify-content: center;
padding: 20px;
min-height: calc(100vh - 520px);
.item{
margin: 0 50px;
cursor: pointer;
&:first-child{
margin-left: 0;
}
&:last-child{
margin-right: 0;
}
&:hover{
opacity: .9;
}
.icon{
display: flex;
justify-content: center;
align-items: center;
width: 100px;
height: 100px;
margin: 0 auto 6px;
border-radius: 12px;
background-color: #ff803c;
img{
width: 50px;
}
}
.text{
font-size: 14px;
text-align: center;
color: #333;
}
}
}
</style>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,25 @@
/**
* @description 鉴权指令
* 当传入的权限当前用户没有时会移除该组件
* 用例<Tag v-auth">text</Tag> 或者:<Tag v-auth="'user:编辑'">text</Tag>
* */
import store from '@/store';
export default {
inserted (el, binding, vnode) {
let btnText = ''
if(binding.value){
btnText = binding.value
}else{
btnText = `${vnode.context.$route.name}:${el.innerText}`
}
const btnPermissions = store.state.btnPermissions;
if (btnText && btnPermissions && btnPermissions.length) {
const isPermission = btnPermissions.includes(btnText);
if (!isPermission) {
el.parentNode && el.parentNode.removeChild(el);
}
}
}
}

@ -0,0 +1,14 @@
/**
* 插件
* */
import directiveAuth from '@/plugins/auth';
import throttle from '@/plugins/throttle';
export default {
async install (Vue, options) {
// 指令
Vue.directive('auth', directiveAuth);
Vue.directive('throttle', throttle);
}
}

@ -0,0 +1,367 @@
import axios from 'axios';
import QS from 'qs';
// import store from '../store/index'
import { Message } from 'element-ui'
import router from '@/router'
// 环境的切换
// if (process.env.NODE_ENV == 'development') {
// axios.defaults.baseURL = '/api';
// } else if (process.env.NODE_ENV == 'debug') {
// axios.defaults.baseURL = '';
// } else if (process.env.NODE_ENV == 'production') {
// axios.defaults.baseURL = 'http://api.123dailu.com/';
// }
// 请求超时时间
axios.defaults.timeout = 30000;
// post请求头
axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';
axios.defaults.headers.Pragma = 'no-cache'
// 请求拦截器
// axios.interceptors.request.use(config => {
// if (sessionStorage.getItem('token')) {
// // 存在将token写入 request header
// config.headers.Authorization = `${sessionStorage.getItem('token')}`;
// }
// return config;
// }, err => {
// Message.error({
// message: '退出登陆',
// onClose: function () {
// router.push({name: 'login'});
// }
// })
// return Promise.reject(err);
// })
// 响应拦截器
// axios.interceptors.response.use(
// response => {
// consol.log(response.status)
// if (response.status === 200) {
// return Promise.resolve(response);
// } else {
// return Promise.reject(response);
// }
// },
// // 服务器状态码不是200的情况
// error => {
// if (error.response.status) {
// switch (error.response.status) {
// // 401: 未登录
// // 未登录则跳转登录页面,并携带当前页面的路径
// // 在登录成功后返回当前页面,这一步需要在登录页操作。
// case 500:
// router.replace({
// path: '/login',
// // query: { redirect: router.currentRoute.fullPath }
// });
// break;
// // 403 token过期
// // 登录过期对用户进行提示
// // 清除本地token和清空vuex中token对象
// // 跳转登录页面
// case 403:
// // Toast({
// // message: '登录过期,请重新登录',
// // duration: 1000,
// // forbidClick: true
// // });
// // 清除token
// sessionStorage.removeItem('token');
// store.commit('loginSuccess', null);
// // 跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面
// setTimeout(() => {
// router.replace({
// path: '/login',
// query: {
// redirect: router.currentRoute.fullPath
// }
// });
// }, 1000);
// break;
// // 404请求不存在
// case 404:
// router.replace({
// path: '/404',
// });
// break;
// // 其他错误,直接抛出错误提示
// default:
// router.replace({
// path: '/500',
// });
// }
// return Promise.reject(error.response);
// }
// }
// );
/**
* get方法对应get请求
*/
export function get(url, params){
return new Promise((resolve, reject) =>{
axios.get(url, {
params: params
})
.then(res => {
if (res.data.status) {
switch (res.data.status) {
case 200:
resolve(res.data);
break;
case 10000:
resolve(res.data);
break;
case 300:
this.$message.error(
res.data.errmessage
);
break;
case 500:
this.$message.error(
res.data.errmessage
);
break;
case 404:
this.$message.error(
res.data.errmessage
);
break;
case 403:
this.$message.error(
res.data.errmessage
);
break;
case 401:
Message.error("token失效,请重新登录");
sessionStorage.removeItem('token');
router.replace('/login')
break;
case 405:
this.$message.error(
res.data.errmessage
);
break;
case 406:
this.$message.error(
res.data.errmessage
);
break;
}
}else{
resolve(res.data);
}
})
.catch(err => {
reject(err.data)
this.$message({
showClose: true,
message: '请求失败,请刷新页面重新进行请求',
type: 'error'
});
})
});
}
/**
* post方法对应post请求
*/
export function post(url, params) {
return new Promise((resolve, reject) => {
axios.post(url,params)
.then(res => {
if (res.data.status) {
switch (res.data.status) {
case 200:
resolve(res.data);
break;
case 300:
this.$message.error(
res.data.errmessage
);
break;
case 500:
this.$message.error(
res.data.errmessage
);
break;
case 404:
this.$message.error(
res.data.errmessage
);
break;
case 403:
this.$message.error(
res.data.errmessage
);
break;
case 401:
Message.error("token失效,请重新登录");
sessionStorage.removeItem('token');
router.replace('/login')
break;
case 405:
this.$message.error(
res.data.errmessage
);
break;
case 406:
this.$message.error(
res.data.errmessage
);
break;
}
}else{
resolve(res.data);
}
})
.catch(err => {
reject(err.data)
this.$message({
showClose: true,
message: '请求失败,请刷新页面重新进行请求',
type: 'error'
});
})
});
}
/**
* delete方法对应delete请求
*/
export function del(url, params){
return new Promise((resolve, reject) =>{
axios.delete(url, {
params: params
})
.then(res => {
if (res.data.status) {
switch (res.data.status) {
case 200:
resolve(res.data);
break;
case 300:
this.$message.error(
res.data.errmessage
);
break;
case 500:
this.$message.error(
res.data.errmessage
);
break;
case 404:
this.$message.error(
res.data.errmessage
);
router.replace({
path: '/404',
});
break;
case 403:
this.$message.error(
res.data.errmessage
);
break;
case 401:
Message.error("token失效,请重新登录");
sessionStorage.removeItem('token');
router.replace('/login')
break;
case 405:
this.$message.error(
res.data.errmessage
);
break;
case 406:
this.$message.error(
res.data.errmessage
);
break;
}
}else{
resolve(res.data);
}
})
.catch(err => {
reject(err.data)
this.$message({
showClose: true,
message: '请求失败,请刷新页面重新进行请求',
type: 'error'
});
})
});
}
/**
* put修改
* @param {} url
* @param {*} params
*/
export function put(url, params){
return new Promise((resolve, reject) =>{
axios.put(url, params)
.then(res => {
if (res.data.status) {
switch (res.data.status) {
case 200:
resolve(res.data);
break;
case 300:
this.$message.error(
res.data.errmessage
);
break;
case 500:
this.$message.error(
res.data.errmessage
);
break;
case 404:
this.$message.error(
res.data.errmessage
);
break;
case 403:
this.$message.error(
res.data.errmessage
);
break;
case 401:
Message.error("token失效,请重新登录");
sessionStorage.removeItem('token');
router.replace('/login')
break;
case 405:
this.$message.error(
res.data.errmessage
);
break;
case 406:
this.$message.error(
res.data.errmessage
);
break;
}
}else{
resolve(res.data);
}
})
.catch(err => {
reject(err.data)
this.$message({
showClose: true,
message: '请求失败,请刷新页面重新进行请求',
type: 'error'
});
})
});
}

@ -0,0 +1,18 @@
/**
* @description 节流指令
* 限制连续快速点击按钮
* 用例<Tag v-throttle>text</Tag>
* */
export default{
inserted (el, binding, vnode) {
el.addEventListener('click', () => {
if (!el.disabled) {
el.disabled = true
setTimeout(() => {
el.disabled = false
}, binding.value || 1000)
}
})
}
}

@ -0,0 +1,22 @@
import Vue from 'vue';
import Router from 'vue-router';
import routes from './routes';
import Setting from '@/setting';
Vue.use(Router);
const createRouter = () => new Router({
mode: Setting.routerMode,
    base: process.env.BASE_URL,
scrollBehavior: () => ({ y: 0 }),
routes
})
export function resetRouter () {
const newRouter = createRouter()
router.matcher = newRouter.matcher
}
let router = createRouter()
export default router

@ -0,0 +1,28 @@
import router from './index';
import Setting from '@/setting';
router.beforeEach((to, from, next) => {
document.title = Setting.titleSuffix;
const role = sessionStorage.getItem(Setting.usernameKey);
if (!role && to.path !== '/login') {
next('login')
// if(to.fullPath != '/404' && to.fullPath != '/'){
// next({
// path: 'login',
// query: {redirect: to.fullPath}
// })
// }else{
// next('login')
// }
} else if(role && to.path == '/login') {
next('dashboard')
} else {
if (navigator.userAgent.indexOf('MSIE') > -1 && to.path === '/editor') {
Vue.prototype.$alert('vue-quill-editor组件不兼容IE10及以下浏览器,请使用更高版本的浏览器查看', '浏览器不兼容通知', {
confirmButtonText: '确定'
});
} else {
next();
}
}
});

@ -0,0 +1,100 @@
export default [
{
path: '/',
redirect: '/login',
},
{
path: '/',
component: () => import('@/layouts/home/index.vue'),
meta: { title: '自述文件' },
children: [
{
name: 'personalCenter',
path: 'personalCenter',
component: () => import('@/pages/personalCenter.vue'),
meta: {
title: '个人中心'
}
},
{
name: 'dashboard',
path: 'dashboard',
component: () => import('@/pages/dashboard.vue'),
meta: { title: '管理员' }
},
{
path: 'station',
component: () => import('@/pages/station.vue'),
meta: { title: '实验台' }
},
{
name: 'course',
path: 'course',
component: () => import('@/pages/course.vue'),
meta: { title: '课程学习' }
},
{
name: 'courseSection',
path: 'courseSection',
component: () => import('@/pages/courseSection.vue'),
meta: { title: '课程学习' }
},
{
name: 'information',
path: 'information',
component: () => import('@/pages/information.vue'),
meta: { title: '资讯' }
},
{
name: 'article',
path: 'article',
component: () => import('@/pages/article.vue'),
meta: { title: '文章' }
},
{
name: 'match',
path: 'match',
component: () => import('@/pages/match.vue'),
meta: { title: '线上赛事' }
},
{
name: 'matchDetail',
path: 'matchDetail',
component: () => import('@/pages/matchDetail.vue'),
meta: { title: '大赛详情' }
},
{
path: 'icon',
component: () => import('@/pages/icon.vue'),
meta: { title: '自定义图标' }
},
{
// 国际化组件
path: 'i18n',
component: () => import('@/pages/i18n.vue'),
meta: { title: '国际化' }
},
{
path: '404',
component: () => import('@/pages/404.vue'),
meta: { title: '404' }
},
{
path: '403',
component: () => import('@/pages/403.vue'),
meta: { title: '403' }
}
]
},
{
path: '/login',
component: () => import('@/pages/login.vue'),
meta: { title: '登录' }
},
{
path: '*',
redirect: '/404'
}
]

@ -0,0 +1,21 @@
/**
* 开发配置
* */
const env = process.env.NODE_ENV;
const Setting = {
// 是否使用 Mock 的数据,默认 开发环境为 true,生产环境为 false
isMock: true,
// 部署应用包时的基本 URL
publicPath: env === 'development' ? './' : '',
// 生产环境构建文件的目录名
outputDir: 'dist',
// 放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录。
assetsDir: 'static',
// 开发环境每次保存时 lint 代码,会将 lint 错误输出为编译警告
// true || false || error
lintOnSave: true,
};
module.exports = Setting;

@ -0,0 +1,116 @@
/**
* 业务配置
* */
const env = process.env.NODE_ENV;
const Setting = {
/**
* 基础配置
* */
// 网页标题的后缀
titleSuffix: '电子竞技在线教学资源管理平台-用户端',
// 路由模式,可选值为 history 或 hash
routerMode: 'hash',
// 页面切换时,是否显示模拟的进度条
showProgressBar: true,
// 接口请求地址
// apiBaseURL: env === 'development' ? 'http://192.168.31.137:8001' : 'http://8.134.8.197:8000',
apiBaseURL: env === 'development' ? 'http://8.134.8.197:8001' : 'http://8.134.8.197:8001',
// 接口请求返回错误时,弹窗的持续时间,单位:秒
modalDuration: 3,
// 接口请求返回错误时,弹窗的类型,可选值为 Message 或 Notice
errorModalType: 'Message',
// Cookies 默认保存时间,单位:天
cookiesExpires: 1,
/**
* sessionStorage里state的key
*/
storeKey: 'gz_user_store',
/**
* sessionStorage里username的key
*/
usernameKey: 'gz_user_username',
/**
* 默认密码
*/
initialPassword: '111aaa',
/**
* 多语言配置
* */
i18n: {
// 默认语言
default: 'zh',
// 是否根据用户电脑配置自动设置语言(仅第一次有效)
auto: false
},
/**
* 布局配置
* */
// 侧边菜单宽度,单位 px,不可动态修改,需与 setting.less 的 @menuSideWidth 保持一致
menuSideWidth: 256,
layout: {
// 需要隐藏顶栏的页面路径
hideNavList: ['article','matchDetail','courseSection','personalCenter'],
// 侧边栏风格,可选值为 dark 或 light
siderTheme: 'dark',
// 顶栏风格,可选值为 light、dark 或 primary
headerTheme: 'light',
// 顶栏是否置顶,开启后会覆盖侧边栏,需开启 headerFix
headerStick: false,
// 是否开启多 Tabs 页签
tabs: true,
// 多 Tabs 页签是否显示图标,开启 tabs 时有效
showTabsIcon: true,
// 是否固定多 Tabs 多页签
tabsFix: true,
// 是否固定侧边栏
siderFix: true,
// 是否固定顶栏
headerFix: true,
// 是否在下滑时隐藏顶栏,需开启 headerFix,如果开启了 tabsFix,Tabs 也会被隐藏
headerHide: false,
// 是否显示顶部菜单栏
// 一般来说,侧边的菜单栏足以满足大部分业务,如需动态切换侧边栏,可开启此选项启用顶部一级菜单,此时侧边栏将作为二级菜单
headerMenu: false,
// 侧边菜单栏是否开启手风琴模式
menuAccordion: true,
// 是否显示折叠侧边栏按钮,移动端下会自动强制开启
showSiderCollapse: true,
// 侧边菜单栏是否默认折起
menuCollapse: false,
// 侧边菜单折起时,是否在子菜单前显示父级菜单名称
showCollapseMenuTitle: false,
// 是否显示重载按钮
showReload: true,
// 是否显示搜索
showSearch: true,
// 是否显示通知
showNotice: true,
// 是否显示全屏
showFullscreen: true,
// 在手机访问时,是否在顶部显示小尺寸 logo
showMobileLogo: true,
// 是否显示全局面包屑,开启 headerMenu 时不可用
showBreadcrumb: true,
// 全局面包屑是否显示图标,开启 showBreadcrumb 时有效
showBreadcrumbIcon: false,
// 是否显示日志入口,开启与否,不影响日志记录,如不希望用户看到可关闭
showLog: true,
// 是否显示多语言
showI18n: true,
// 是否支持动态修改布局配置,移动端下会自动强制关闭
enableSetting: true,
// 退出登录时,是否二次确认
logoutConfirm: true
},
/**
* 功能配置
* */
// 相同路由,不同参数间进行切换,是否强力更新
sameRouteForceUpdate: false,
// 是否使用动态路由
dynamicRoute: false
};
export default Setting;

@ -0,0 +1,110 @@
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
avatar: 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png',
customerId:'',
mobile:'',
status:'',
newsid:'',
newTypeid:'',
manager:{},
resultId: '',
classId: '',
className: '',
schoolName: '',
provinceId: '',
cityId: '',
staffstateProfessId: '',
staffstateId: '',
userId: '',
accountRole: '',
name:'',
account:'',
phone:'',
schoolId: '',
courseId:'',
assesmentId: '',
staffId: '',
studentId: '',
schoolName: '',
answerHistory: [],
matchId: '',
matchSignupStatus: '',
columnId: ''
},
mutations:{
courseIdData(state,payload){
state.courseId = payload.courseId
},
userInfo(state,payload){
state.name = payload.name
state.account = payload.account
state.phone = payload.phone
state.schoolId = payload.schoolId
state.schoolName = payload.schoolName
},
userPhoto(state,payload){
state.userPhoto = payload.userPhoto
},
customerData (state, payload) {
state.customerId = payload.customer_id
},
addNews (state, payload) {
state.newsid = payload.newsid,
state.newTypeid = payload.newTypeid
},
managerData (state, payload) {
state.manager = payload.form
},
resultData (state, payload) {
state.resultId = payload.resultId
},
classData (state, payload) {
state.classId = payload.classId
state.className = payload.className
},
schoolData (state, payload) {
state.schoolId = payload.schoolId
state.schoolName = payload.schoolName
state.provinceId = payload.provinceId
state.cityId = payload.cityId
state.accountRole = payload.accountRole
},
platformId (state, payload) {
state.platformId = payload.platformId
},
staffProfessIdData (state, payload) {
state.staffstateProfessId = payload.staffstateProfessId
state.staffstateId = payload.staffstateId
},
setAvatarData (state, payload) {
state.avatar = payload.avatar
},
userLoginData (state, payload) {
state.userId = payload.userId
state.accountRole = payload.accountRole
// state.staffId = payload.staffId
// state.studentId = payload.studentId
},
assesmentData (state, payload) {
state.assesmentId = payload.assesmentId
},
provinceData (state, payload) {
state.provinceList = payload.provinceList
},
answerHistoryData (state, payload) {
state.answerHistory = payload.answerHistory
},
addInfoData (state, payload) {
state.columnId = payload.columnId
},
matchSignup (state, payload) {
state.matchId = payload.matchId
state.matchSignupStatus = payload.matchSignupStatus
},
}
});
export default store;

@ -0,0 +1,183 @@
@import "./default/index.scss";
@font-face{
font-family: youshe;
src: url('../assets/font/YouSheBiaoTiHei.ttf');
}
[v-cloak] {
display: none;
}
::-webkit-scrollbar {
width: 6px;
}
::-webkit-scrollbar-thumb {
border-radius: 10px;
background: rgba(0, 0, 0, 0.06);
}
.page{
position: relative;
background-color: #fff;
border-radius: 8px;
.p-title{
padding-left: 24px;
line-height: 56px;
font-size: 16px;
color: rgba(0, 0, 0, 0.85);
border-bottom: 1px solid rgba(0,0,0,.06);
}
.page-content{
padding: 24px;
}
}
.tabs{
display: flex;
align-items: center;
padding: 0 24px;
margin-bottom: 20px;
border-bottom: 1px solid rgba(0,0,0,.06);
.item{
position: relative;
padding: 20px 0;
margin-right: 40px;
font-size: 16px;
color: rgba(0, 0, 0, 0.65);
cursor: pointer;
&:after{
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 3px;
border-bottom: 3px solid transparent;
border-radius: 2px;
}
&.active{
font-weight: 500;
color: rgba(0, 0, 0, 0.85);
}
&.active:after{
border-bottom-color: $--color-primary;
}
}
}
.search {
display: flex;
justify-content: space-between;
width: 30%;
padding: 4px;
margin: 0 auto;
border-radius: 24px;
overflow: hidden;
background-color: #fff;
input {
flex: 1;
height: 40px;
padding: 0 15px;
line-height: 40px;
font-size: 14px;
color: #333;
border: 0;
outline: none !important;
box-sizing: border-box;
&::-webkit-input-placeholder{
color: rgba(0,0,0,.25);
}
}
button {
display: inline-flex;
align-items: center;
padding: 0 20px;
line-height: 40px;
color: #fff;
font-size: 16px;
background: #CC221C;
border-radius: 20px;
border: 0;
outline: none !important;
img{
margin-right: 5px;
}
}
}
.breadcrumb{
display: flex;
align-items: center;
margin: 65px 0 20px;
.cur,.el-breadcrumb__inner,.el-breadcrumb__separator{
color: rgba(0,0,0,.45) !important;
font-weight: 400 !important;
font-size: 12px;
}
.el-breadcrumb__item:last-of-type .el-breadcrumb__inner{
color: rgba(0,0,0,.85) !important;
}
}
.pagination {
margin: 20px 0;
text-align: center;
button,.number{
color: rgba(0,0,0,.65) !important;
background-color: transparent !important;
border: 1px solid rgba(0, 0, 0, 0.15) !important;
border-radius: 4px !important;
}
button i{
color: #333;
}
.active{
color: #fff !important;
background-color: #CC221C !important;
}
}
.el-table{
border-radius: 8px;
border: 1px solid rgba(0, 0, 0, 0.06);
th{
background: rgba(0, 0, 0, 0.04)!important;
font-size: 14px;
color: rgba(0, 0, 0, 0.85);
font-weight: normal;
}
.el-checkbox__inner{
border-radius: 4px;
}
.el-switch__core{
background-color: #bfbfbf;
}
.el-switch__label--right{
z-index: 2;
margin-left: -18px;
color: #fff !important;
}
.el-switch__label--right.is-active{
margin-left: -32px;
}
.el-switch__label--right span{
font-size: 12px;
}
}
.empty{
display: flex;
justify-content: center;
align-items: center;
padding: 50px 0;
text-align: center;
img{
width: 471px;
}
p{
margin-top: 40px;
font-size: 18px;
color: rgba(0, 0, 0, 0.25);
}
}

@ -0,0 +1,7 @@
/* 改变主题色变量 */
$--color-primary: #CC221C;
/* 改变 icon 字体路径变量,必需 */
$--font-path: '~element-ui/lib/theme-chalk/fonts';
@import "~element-ui/packages/theme-chalk/src/index";

@ -0,0 +1,539 @@
/* Logo 字体 */
@font-face {
font-family: "iconfont logo";
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
}
.logo {
font-family: "iconfont logo";
font-size: 160px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* tabs */
.nav-tabs {
position: relative;
}
.nav-tabs .nav-more {
position: absolute;
right: 0;
bottom: 0;
height: 42px;
line-height: 42px;
color: #666;
}
#tabs {
border-bottom: 1px solid #eee;
}
#tabs li {
cursor: pointer;
width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 16px;
border-bottom: 2px solid transparent;
position: relative;
z-index: 1;
margin-bottom: -1px;
color: #666;
}
#tabs .active {
border-bottom-color: #f00;
color: #222;
}
.tab-container .content {
display: none;
}
/* 页面布局 */
.main {
padding: 30px 100px;
width: 960px;
margin: 0 auto;
}
.main .logo {
color: #333;
text-align: left;
margin-bottom: 30px;
line-height: 1;
height: 110px;
margin-top: -50px;
overflow: hidden;
*zoom: 1;
}
.main .logo a {
font-size: 160px;
color: #333;
}
.helps {
margin-top: 40px;
}
.helps pre {
padding: 20px;
margin: 10px 0;
border: solid 1px #e7e1cd;
background-color: #fffdef;
overflow: auto;
}
.icon_lists {
width: 100% !important;
overflow: hidden;
*zoom: 1;
}
.icon_lists li {
width: 100px;
margin-bottom: 10px;
margin-right: 20px;
text-align: center;
list-style: none !important;
cursor: default;
}
.icon_lists li .code-name {
line-height: 1.2;
}
.icon_lists .icon {
display: block;
height: 100px;
line-height: 100px;
font-size: 42px;
margin: 10px auto;
color: #333;
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
-moz-transition: font-size 0.25s linear, width 0.25s linear;
transition: font-size 0.25s linear, width 0.25s linear;
}
.icon_lists .icon:hover {
font-size: 100px;
}
.icon_lists .svg-icon {
/* 通过设置 font-size 来改变图标大小 */
width: 1em;
/* 图标和文字相邻时,垂直对齐 */
vertical-align: -0.15em;
/* 通过设置 color 来改变 SVG 的颜色/fill */
fill: currentColor;
/* path stroke 溢出 viewBox 部分在 IE 下会显示
normalize.css 中也包含这行 */
overflow: hidden;
}
.icon_lists li .name,
.icon_lists li .code-name {
color: #666;
}
/* markdown 样式 */
.markdown {
color: #666;
font-size: 14px;
line-height: 1.8;
}
.highlight {
line-height: 1.5;
}
.markdown img {
vertical-align: middle;
max-width: 100%;
}
.markdown h1 {
color: #404040;
font-weight: 500;
line-height: 40px;
margin-bottom: 24px;
}
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
color: #404040;
margin: 1.6em 0 0.6em 0;
font-weight: 500;
clear: both;
}
.markdown h1 {
font-size: 28px;
}
.markdown h2 {
font-size: 22px;
}
.markdown h3 {
font-size: 16px;
}
.markdown h4 {
font-size: 14px;
}
.markdown h5 {
font-size: 12px;
}
.markdown h6 {
font-size: 12px;
}
.markdown hr {
height: 1px;
border: 0;
background: #e9e9e9;
margin: 16px 0;
clear: both;
}
.markdown p {
margin: 1em 0;
}
.markdown>p,
.markdown>blockquote,
.markdown>.highlight,
.markdown>ol,
.markdown>ul {
width: 80%;
}
.markdown ul>li {
list-style: circle;
}
.markdown>ul li,
.markdown blockquote ul>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown>ul li p,
.markdown>ol li p {
margin: 0.6em 0;
}
.markdown ol>li {
list-style: decimal;
}
.markdown>ol li,
.markdown blockquote ol>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown code {
margin: 0 3px;
padding: 0 5px;
background: #eee;
border-radius: 3px;
}
.markdown strong,
.markdown b {
font-weight: 600;
}
.markdown>table {
border-collapse: collapse;
border-spacing: 0px;
empty-cells: show;
border: 1px solid #e9e9e9;
width: 95%;
margin-bottom: 24px;
}
.markdown>table th {
white-space: nowrap;
color: #333;
font-weight: 600;
}
.markdown>table th,
.markdown>table td {
border: 1px solid #e9e9e9;
padding: 8px 16px;
text-align: left;
}
.markdown>table th {
background: #F7F7F7;
}
.markdown blockquote {
font-size: 90%;
color: #999;
border-left: 4px solid #e9e9e9;
padding-left: 0.8em;
margin: 1em 0;
}
.markdown blockquote p {
margin: 0;
}
.markdown .anchor {
opacity: 0;
transition: opacity 0.3s ease;
margin-left: 8px;
}
.markdown .waiting {
color: #ccc;
}
.markdown h1:hover .anchor,
.markdown h2:hover .anchor,
.markdown h3:hover .anchor,
.markdown h4:hover .anchor,
.markdown h5:hover .anchor,
.markdown h6:hover .anchor {
opacity: 1;
display: inline-block;
}
.markdown>br,
.markdown>p>br {
clear: both;
}
.hljs {
display: block;
background: white;
padding: 0.5em;
color: #333333;
overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
color: #969896;
}
.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #a71d5d;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}
.hljs-section,
.hljs-name {
color: #63a35c;
}
.hljs-tag {
color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #795da3;
}
.hljs-addition {
color: #55a532;
background-color: #eaffea;
}
.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}
.hljs-link {
text-decoration: underline;
}
/* 代码高亮 */
/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection,
code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre)>code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre)>code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}

@ -0,0 +1,446 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>IconFont Demo</title>
<link rel="shortcut icon" href="https://img.alicdn.com/tps/i4/TB1_oz6GVXXXXaFXpXXJDFnIXXX-64-64.ico" type="image/x-icon"/>
<link rel="stylesheet" href="https://g.alicdn.com/thx/cube/1.3.2/cube.min.css">
<link rel="stylesheet" href="demo.css">
<link rel="stylesheet" href="iconfont.css">
<script src="iconfont.js"></script>
<!-- jQuery -->
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js"></script>
<!-- 代码高亮 -->
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js"></script>
</head>
<body>
<div class="main">
<h1 class="logo"><a href="https://www.iconfont.cn/" title="iconfont 首页" target="_blank">&#xe86b;</a></h1>
<div class="nav-tabs">
<ul id="tabs" class="dib-box">
<li class="dib active"><span>Unicode</span></li>
<li class="dib"><span>Font class</span></li>
<li class="dib"><span>Symbol</span></li>
</ul>
<a href="https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=1540265" target="_blank" class="nav-more">查看项目</a>
</div>
<div class="tab-container">
<div class="content unicode" style="display: block;">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont">&#xe63d;</span>
<div class="name">已勾选32</div>
<div class="code-name">&amp;#xe63d;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe63e;</span>
<div class="name">未勾选32</div>
<div class="code-name">&amp;#xe63e;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe64a;</span>
<div class="name">未勾选40</div>
<div class="code-name">&amp;#xe64a;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe64b;</span>
<div class="name">已勾选40</div>
<div class="code-name">&amp;#xe64b;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe626;</span>
<div class="name">实 向右箭头-01</div>
<div class="code-name">&amp;#xe626;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe625;</span>
<div class="name">实 向下箭头-01</div>
<div class="code-name">&amp;#xe625;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe72d;</span>
<div class="name">加号-填充</div>
<div class="code-name">&amp;#xe72d;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe769;</span>
<div class="name">42指向上、上箭头</div>
<div class="code-name">&amp;#xe769;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe76b;</span>
<div class="name">44指向下、下箭头</div>
<div class="code-name">&amp;#xe76b;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe6e9;</span>
<div class="name">群蜂删除-充</div>
<div class="code-name">&amp;#xe6e9;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe614;</span>
<div class="name">qq</div>
<div class="code-name">&amp;#xe614;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe68a;</span>
<div class="name">微信-36</div>
<div class="code-name">&amp;#xe68a;</div>
</li>
</ul>
<div class="article markdown">
<h2 id="unicode-">Unicode 引用</h2>
<hr>
<p>Unicode 是字体在网页端最原始的应用方式,特点是:</p>
<ul>
<li>兼容性最好,支持 IE6+,及所有现代浏览器。</li>
<li>支持按字体的方式去动态调整图标大小,颜色等等。</li>
<li>但是因为是字体,所以不支持多色。只能使用平台里单色的图标,就算项目里有多色图标也会自动去色。</li>
</ul>
<blockquote>
<p>注意:新版 iconfont 支持多色图标,这些多色图标在 Unicode 模式下将不能使用,如果有需求建议使用symbol 的引用方式</p>
</blockquote>
<p>Unicode 使用步骤如下:</p>
<h3 id="-font-face">第一步:拷贝项目下面生成的 <code>@font-face</code></h3>
<pre><code class="language-css"
>@font-face {
font-family: 'iconfont';
src: url('iconfont.eot');
src: url('iconfont.eot?#iefix') format('embedded-opentype'),
url('iconfont.woff2') format('woff2'),
url('iconfont.woff') format('woff'),
url('iconfont.ttf') format('truetype'),
url('iconfont.svg#iconfont') format('svg');
}
</code></pre>
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
<pre><code class="language-css"
>.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3>
<pre>
<code class="language-html"
>&lt;span class="iconfont"&gt;&amp;#x33;&lt;/span&gt;
</code></pre>
<blockquote>
<p>"iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
</blockquote>
</div>
</div>
<div class="content font-class">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont icon-yigouxuan"></span>
<div class="name">
已勾选32
</div>
<div class="code-name">.icon-yigouxuan
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-weigouxuan"></span>
<div class="name">
未勾选32
</div>
<div class="code-name">.icon-weigouxuan
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-weigouxuan1"></span>
<div class="name">
未勾选40
</div>
<div class="code-name">.icon-weigouxuan1
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-yigouxuan1"></span>
<div class="name">
已勾选40
</div>
<div class="code-name">.icon-yigouxuan1
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-shixiangyoujiantou-"></span>
<div class="name">
实 向右箭头-01
</div>
<div class="code-name">.icon-shixiangyoujiantou-
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-shixiangxiajiantou-"></span>
<div class="name">
实 向下箭头-01
</div>
<div class="code-name">.icon-shixiangxiajiantou-
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-jiahao"></span>
<div class="name">
加号-填充
</div>
<div class="code-name">.icon-jiahao
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-up"></span>
<div class="name">
42指向上、上箭头
</div>
<div class="code-name">.icon-up
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-down"></span>
<div class="name">
44指向下、下箭头
</div>
<div class="code-name">.icon-down
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-delete"></span>
<div class="name">
群蜂删除-充
</div>
<div class="code-name">.icon-delete
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-qq"></span>
<div class="name">
qq
</div>
<div class="code-name">.icon-qq
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-weixin"></span>
<div class="name">
微信-36
</div>
<div class="code-name">.icon-weixin
</div>
</li>
</ul>
<div class="article markdown">
<h2 id="font-class-">font-class 引用</h2>
<hr>
<p>font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。</p>
<p>与 Unicode 使用方式相比,具有如下特点:</p>
<ul>
<li>兼容性良好,支持 IE8+,及所有现代浏览器。</li>
<li>相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。</li>
<li>因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。</li>
<li>不过因为本质上还是使用的字体,所以多色图标还是不支持的。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-fontclass-">第一步:引入项目下面生成的 fontclass 代码:</h3>
<pre><code class="language-html">&lt;link rel="stylesheet" href="./iconfont.css"&gt;
</code></pre>
<h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;span class="iconfont icon-xxx"&gt;&lt;/span&gt;
</code></pre>
<blockquote>
<p>"
iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
</blockquote>
</div>
</div>
<div class="content symbol">
<ul class="icon_lists dib-box">
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-yigouxuan"></use>
</svg>
<div class="name">已勾选32</div>
<div class="code-name">#icon-yigouxuan</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-weigouxuan"></use>
</svg>
<div class="name">未勾选32</div>
<div class="code-name">#icon-weigouxuan</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-weigouxuan1"></use>
</svg>
<div class="name">未勾选40</div>
<div class="code-name">#icon-weigouxuan1</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-yigouxuan1"></use>
</svg>
<div class="name">已勾选40</div>
<div class="code-name">#icon-yigouxuan1</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-shixiangyoujiantou-"></use>
</svg>
<div class="name">实 向右箭头-01</div>
<div class="code-name">#icon-shixiangyoujiantou-</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-shixiangxiajiantou-"></use>
</svg>
<div class="name">实 向下箭头-01</div>
<div class="code-name">#icon-shixiangxiajiantou-</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-jiahao"></use>
</svg>
<div class="name">加号-填充</div>
<div class="code-name">#icon-jiahao</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-up"></use>
</svg>
<div class="name">42指向上、上箭头</div>
<div class="code-name">#icon-up</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-down"></use>
</svg>
<div class="name">44指向下、下箭头</div>
<div class="code-name">#icon-down</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-delete"></use>
</svg>
<div class="name">群蜂删除-充</div>
<div class="code-name">#icon-delete</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-qq"></use>
</svg>
<div class="name">qq</div>
<div class="code-name">#icon-qq</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-weixin"></use>
</svg>
<div class="name">微信-36</div>
<div class="code-name">#icon-weixin</div>
</li>
</ul>
<div class="article markdown">
<h2 id="symbol-">Symbol 引用</h2>
<hr>
<p>这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇<a href="">文章</a>
这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:</p>
<ul>
<li>支持多色图标了,不再受单色限制。</li>
<li>通过一些技巧,支持像字体那样,通过 <code>font-size</code>, <code>color</code> 来调整样式。</li>
<li>兼容性较差,支持 IE9+,及现代浏览器。</li>
<li>浏览器渲染 SVG 的性能一般,还不如 png。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-symbol-">第一步:引入项目下面生成的 symbol 代码:</h3>
<pre><code class="language-html">&lt;script src="./iconfont.js"&gt;&lt;/script&gt;
</code></pre>
<h3 id="-css-">第二步:加入通用 CSS 代码(引入一次就行):</h3>
<pre><code class="language-html">&lt;style&gt;
.icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
&lt;/style&gt;
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;svg class="icon" aria-hidden="true"&gt;
&lt;use xlink:href="#icon-xxx"&gt;&lt;/use&gt;
&lt;/svg&gt;
</code></pre>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$('.tab-container .content:first').show()
$('#tabs li').click(function (e) {
var tabContent = $('.tab-container .content')
var index = $(this).index()
if ($(this).hasClass('active')) {
return
} else {
$('#tabs li').removeClass('active')
$(this).addClass('active')
tabContent.hide().eq(index).fadeIn()
}
})
})
</script>
</body>
</html>

@ -0,0 +1,71 @@
@font-face {font-family: "iconfont";
src: url('iconfont.eot?t=1589437921018'); /* IE9 */
src: url('iconfont.eot?t=1589437921018#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAdgAAsAAAAADwwAAAcTAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCESgqOeIt2ATYCJAM0CxwABCAFhG0HgTMbpQxRlHBSFNlX2JThXqSJ4cz0aLyxzNkVgYOP2N97wQhUeQbPDZA1QByDeHha+9+5M7PrD1FpdI8mCSqJLulDJPFDxCQTvUQS6Qtka3ukU0/kuK8wfBBwMr1kmeTIb8hUohVh6lTeCHDCrRPPf5v6f+sQfS+QqgmpiZLNw+ZI6zMXZGL3nXY47elJFnjALaE4zjzyjJN773yuzM/7H4oZ9NV+v/q1g1ddvP1QmE5JlPRM7uAv5klMk0vWTBWTLpoJEUIja6hWSkNhOklN/ds4n0BvhyLMuZ6hKdArLC1Q4a4iG0Gfi1JaHEMbXtfsW8S8SpsepzuAJ+HLx28hoSepMmvby3e6LdC2EN2eV0ykW36MR/MlQFiJjGNAEej7WvtLgB6aM6evXtwH1glnTloW1snRYnBhky+LxyuL9glaGNmaDbRsJYR1tl+seImrgUGtEtLc//GMeo1WR9QYfUSrp7nohWgXDRrJBqpBcoAqkGagAGkBSiADQBlkEKiAbAI/N/mCYHoWi1HDEgWoBbGjlg7M/OpbgEMgnUf0fxab8kjK0tvq8cZ6/dpKwk4bNsXFx4bHR4RHcty4LVnR4xp/2TFxDN42tgefhUpEMeeqppXCU50JyT/gkVCD+EiEgl56LOkMN+6cAfyKs3dvomHU7fvnq96Uc/duIXMMqWmhNRoax1m8jNWfPorp2jlqumvHrolfe/2TcuIPCt3K589dhUNiT5OSEh4KoM9Jp1vK2GMnFjDdyaeFMrd06ki1gn9CmEz3OErpebmp+GzyAN+lMLw6dwkKh6Ve5dOnzp4W0+Y25TTfhHB10isXpxIB5GHDKcggnof+NCpCD+okAFyTPNGuRVgahmhLjZo1rnqnMlpD0ORJSluuY6jT+gPWHtaIeDKOaoradNDPruOQzulPGcBtz0C2YdbLrSFPIMGTrcNRDGC3YnJOm1JLceYK2sCWY5lqxICXIEU0gki2nkPFUteBwoqLMyTdKE7ZlOzE3yHfdSyOU2shl8RoxPJlx1bQ6C0Li3DLg+Sdi+c5evEkhtF3rBdfXpe0IiNcfW27+x6u5U4vs8zZZdu1R7Gblyc6AV9OB4Xp65HRDqcvw0Pi1DGbddntOKzYgkbhXJq+Y4bRVqszl746KdRPFV5FxSUb6XmKomd1yCb0nJbpz+aOIZskx0phXx8sHfNKyRjPsM8LGU/xJ9Qrv2JugdVBkBg/ZpUIDvpN0jfHD550XPKNDgkKEZ46l4dwq0sOxIecJlX2pxxA8GTwkCGMFqxVFf5PRZplCky9uCIQL/s/RFabTYZNkhtkQXFR28vKXwKUP5rZbFg+s3VAFTu5dBZG4G07t5tHuM2cFirh2BisrHKYoE8lzO1h/LkwjSD+VZF0qs1hQVK+d0xHOLN80q4B/P9utxQDmGt4DaEKE6Lc5lnI6VxDf/35owQHCAuKw95VG6l1bvXPY3J1slpepPBXdCx8EM+ubbd2tV48b2UtWLtYb89PZhvg2jsq5+zkBdIVVTFHfhEwNv0CxNiT02LKVxGSus1dt9VsXDZulogOJB1AkGQVg4e833uzaWatx7bPrLKyhBeBqlC3xGqNoe3MVQHmDmBs4jm+xFjW/sjcAgOiPOFawwe3bUeTa20vGNZgbV6tCtL/qEL/fmiFLjqCCDpZdQpkdKgx6tSuzlCdqnrMFsLMhWn9sKH4ezmjmvpp9Selw9oCS0Vtcbox4f967yYpc1lNwUzPAUT3N0R32yz0bof5Wblw2jzkuw4VkWFptzoKckHRUwszvHJS8IgkAfys2IvKr/LtZBa1LzvfHBmFD6/V9enLD7LLJD2tz7n3E8BkFcwVyA/DL8P0fCpXAdLntBfy9tQCpuUP2QBAWkwyYccYGYFWWc/HS8Of6pVNf1r8p8n48bn+wPLzm5gyWoneAh3ivzATiiRKljoz8hQTN3S0itSojpnbgvjFod7uBf2Rtsa7dej63gKVRdenkDS2Q9baZyzWY1AZnIBa6yT0juo9eLCWhhOlwxFrCYRVjkKywhfIVrlrLNa3UNngB9RWBQe9mxF1zMGBUFCnRoyUWLBpCStm1SU5sRRFFSeI7HUYtawUeswQzaNk4PKSsmJBL3ERbY4dPD65glIJS5rqxD3kYsThULFbU23ETEuslLobSkuluh1LzKoTkLM0hBH1A1pgJku2CjOVizQ+hUrPP4GQeTkYaS0tarYzCI2HMnusXImyHsZe3dWrxb1U9/CRVaBMggS79TUqJ6yHSSAcdq4Kc9evZUOYUSWsI7LdGpQy7Ul99ZL1qfObT4CedX+zSJGjRBV1NNFGF30MMcYsVugeKLLqDXiNLuQnSQjRvRwtrRzlsSoBxeiSl1SvLVQoF1FcZj0Jqi46odWosl43b1H9Lp2FOAgl7OKibs6cgOICAA==') format('woff2'),
url('iconfont.woff?t=1589437921018') format('woff'),
url('iconfont.ttf?t=1589437921018') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
url('iconfont.svg?t=1589437921018#iconfont') format('svg'); /* iOS 4.1- */
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-yigouxuan:before {
content: "\e63d";
}
.icon-weigouxuan:before {
content: "\e63e";
}
.icon-weigouxuan1:before {
content: "\e64a";
}
.icon-yigouxuan1:before {
content: "\e64b";
}
.icon-shixiangyoujiantou-:before {
content: "\e626";
}
.icon-shixiangxiajiantou-:before {
content: "\e625";
}
.icon-jiahao:before {
content: "\e72d";
}
.icon-up:before {
content: "\e769";
}
.icon-down:before {
content: "\e76b";
}
.icon-delete:before {
content: "\e6e9";
}
.icon-qq:before {
content: "\e614";
font-size: 60px;
color: #22aaf8;
margin-left: 32px;
}
.icon-weixin:before {
content: "\e68a";
font-size: 60px;
color: #10b747;
margin-right: 32px;
}

Binary file not shown.

File diff suppressed because one or more lines are too long

@ -0,0 +1,93 @@
{
"id": "1540265",
"name": "education",
"font_family": "iconfont",
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "2716513",
"name": "已勾选32",
"font_class": "yigouxuan",
"unicode": "e63d",
"unicode_decimal": 58941
},
{
"icon_id": "2716516",
"name": "未勾选32",
"font_class": "weigouxuan",
"unicode": "e63e",
"unicode_decimal": 58942
},
{
"icon_id": "2892929",
"name": "未勾选40",
"font_class": "weigouxuan1",
"unicode": "e64a",
"unicode_decimal": 58954
},
{
"icon_id": "2892954",
"name": "已勾选40",
"font_class": "yigouxuan1",
"unicode": "e64b",
"unicode_decimal": 58955
},
{
"icon_id": "5979965",
"name": "实 向右箭头-01",
"font_class": "shixiangyoujiantou-",
"unicode": "e626",
"unicode_decimal": 58918
},
{
"icon_id": "5979966",
"name": "实 向下箭头-01",
"font_class": "shixiangxiajiantou-",
"unicode": "e625",
"unicode_decimal": 58917
},
{
"icon_id": "8349103",
"name": "加号-填充",
"font_class": "jiahao",
"unicode": "e72d",
"unicode_decimal": 59181
},
{
"icon_id": "6129078",
"name": "42指向上、上箭头",
"font_class": "up",
"unicode": "e769",
"unicode_decimal": 59241
},
{
"icon_id": "6129081",
"name": "44指向下、下箭头",
"font_class": "down",
"unicode": "e76b",
"unicode_decimal": 59243
},
{
"icon_id": "410692",
"name": "群蜂删除-充",
"font_class": "delete",
"unicode": "e6e9",
"unicode_decimal": 59113
},
{
"icon_id": "468193",
"name": "qq",
"font_class": "qq",
"unicode": "e614",
"unicode_decimal": 58900
},
{
"icon_id": "7009153",
"name": "微信-36",
"font_class": "weixin",
"unicode": "e68a",
"unicode_decimal": 59018
}
]
}

@ -0,0 +1,62 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<!--
2013-9-30: Created.
-->
<svg>
<metadata>
Created by iconfont
</metadata>
<defs>
<font id="iconfont" horiz-adv-x="1024" >
<font-face
font-family="iconfont"
font-weight="500"
font-stretch="normal"
units-per-em="1024"
ascent="896"
descent="-128"
/>
<missing-glyph />
<glyph glyph-name="yigouxuan" unicode="&#58941;" d="M196.923077 896h630.153846a196.923077 196.923077 0 0 0 196.923077-196.923077v-630.153846a196.923077 196.923077 0 0 0-196.923077-196.923077H196.923077a196.923077 196.923077 0 0 0-196.923077 196.923077V699.076923a196.923077 196.923077 0 0 0 196.923077 196.923077z m0-78.769231a118.153846 118.153846 0 0 1-118.153846-118.153846v-630.153846a118.153846 118.153846 0 0 1 118.153846-118.153846h630.153846a118.153846 118.153846 0 0 1 118.153846 118.153846V699.076923a118.153846 118.153846 0 0 1-118.153846 118.153846H196.923077z m584.900923-258.205538a36.509538 36.509538 0 0 0 1.260308-51.633231l-299.480616-313.107692c-0.118154-0.157538-0.393846-0.236308-0.630154-0.472616l-0.393846-0.551384c-2.166154-2.126769-4.726154-3.229538-7.207384-4.726154-1.575385-0.866462-2.796308-2.166154-4.411077-2.835692a35.800615 35.800615 0 0 0-27.490462-0.07877c-1.260308 0.512-2.284308 1.614769-3.544615 2.284308-2.756923 1.457231-5.592615 2.835692-8.034462 5.12-0.196923 0.157538-0.275692 0.433231-0.512 0.669538-0.196923 0.118154-0.393846 0.196923-0.551384 0.354462l-150.843077 156.593231a36.430769 36.430769 0 0 0 0.945231 51.633231 36.391385 36.391385 0 0 0 51.63323-0.945231l124.455385-129.102769 273.092923 285.61723a36.548923 36.548923 0 0 0 51.712 1.181539z" horiz-adv-x="1024" />
<glyph glyph-name="weigouxuan" unicode="&#58942;" d="M196.923077 817.230769a118.153846 118.153846 0 0 1-118.153846-118.153846v-630.153846a118.153846 118.153846 0 0 1 118.153846-118.153846h630.153846a118.153846 118.153846 0 0 1 118.153846 118.153846V699.076923a118.153846 118.153846 0 0 1-118.153846 118.153846H196.923077z m0 78.769231h630.153846a196.923077 196.923077 0 0 0 196.923077-196.923077v-630.153846a196.923077 196.923077 0 0 0-196.923077-196.923077H196.923077a196.923077 196.923077 0 0 0-196.923077 196.923077V699.076923a196.923077 196.923077 0 0 0 196.923077 196.923077z" horiz-adv-x="1024" />
<glyph glyph-name="weigouxuan1" unicode="&#58954;" d="M256 768a128 128 0 0 1-128-128v-512a128 128 0 0 1 128-128h512a128 128 0 0 1 128 128V640a128 128 0 0 1-128 128H256z m0 51.2h512a179.2 179.2 0 0 0 179.2-179.2v-512a179.2 179.2 0 0 0-179.2-179.2H256a179.2 179.2 0 0 0-179.2 179.2V640a179.2 179.2 0 0 0 179.2 179.2z" horiz-adv-x="1024" />
<glyph glyph-name="yigouxuan1" unicode="&#58955;" d="M796.912941 598.437647L407.491765 203.294118l-156.611765 172.272941a30.177882 30.177882 0 0 1-44.574118-40.658824L361.411765 161.430588a60.235294 60.235294 0 0 1 85.232941-3.915294l2.409412 2.409412 390.927058 396.348235a30.117647 30.117647 0 1 1-43.068235 42.164706zM813.176471 896H210.823529a210.823529 210.823529 0 0 1-210.823529-210.823529v-602.352942a210.823529 210.823529 0 0 1 210.823529-210.823529h602.352942a210.823529 210.823529 0 0 1 210.823529 210.823529V685.176471a210.823529 210.823529 0 0 1-210.823529 210.823529z m150.588235-813.176471a150.588235 150.588235 0 0 0-150.588235-150.588235H210.823529a150.588235 150.588235 0 0 0-150.588235 150.588235V685.176471a150.588235 150.588235 0 0 0 150.588235 150.588235h602.352942a150.588235 150.588235 0 0 0 150.588235-150.588235z" horiz-adv-x="1024" />
<glyph glyph-name="shixiangyoujiantou-" unicode="&#58918;" d="M701.44 384L322.56 99.413V668.587L701.44 384z" horiz-adv-x="1024" />
<glyph glyph-name="shixiangxiajiantou-" unicode="&#58917;" d="M512 194.56L227.413 573.44h569.174L512 194.56z" horiz-adv-x="1024" />
<glyph glyph-name="jiahao" unicode="&#59181;" d="M512 864C246.4 864 32 649.6 32 384s214.4-480 480-480 480 214.4 480 480S777.6 864 512 864z m256-512h-224v-224c0-19.2-12.8-32-32-32s-32 12.8-32 32v224H256c-19.2 0-32 12.8-32 32s12.8 32 32 32h224V640c0 19.2 12.8 32 32 32s32-12.8 32-32v-224h224c19.2 0 32-12.8 32-32s-12.8-32-32-32z" horiz-adv-x="1024" />
<glyph glyph-name="up" unicode="&#59241;" d="M508.4 445.9l1.8 1.8-1.8-1.8zM508.2 447.9l2.2-2.2c-0.7 0.8-1.4 1.5-2.2 2.2zM511.1 485l1.8-1.8-1.8 1.8zM510.9 483l2.2 2.2c-0.8-0.7-1.5-1.4-2.2-2.2zM544 521.3v-336c0-17.6-14.4-32-32-32s-32 14.4-32 32v336c0 17.6 14.4 32 32 32s32-14.4 32-32zM511.9 614.7c-8.3 0-15.8-3.1-21.5-8.3l-2.2-2.2-21.5-21.5L291 407c-12.4-12.4-12.4-32.8 0-45.3 12.4-12.4 32.8-12.4 45.3 0L512 537.5l175.8-175.7c12.4-12.4 32.8-12.4 45.3 0 12.4 12.4 12.4 32.8-0.1 45.2L557.3 582.7l-21.8 21.8-1.8 1.8c-5.7 5.3-13.4 8.5-21.8 8.4z" horiz-adv-x="1024" />
<glyph glyph-name="down" unicode="&#59243;" d="M515.6 322.1l-1.8-1.8 1.8 1.8zM515.8 320.1l-2.2 2.2c0.7-0.8 1.4-1.5 2.2-2.2zM512.9 283l-1.8 1.8 1.8-1.8zM513.1 285l-2.2-2.2c0.8 0.7 1.5 1.4 2.2 2.2zM480 246.70000000000005v336c0 17.6 14.4 32 32 32s32-14.4 32-32v-336c0-17.6-14.4-32-32-32s-32 14.4-32 32zM512.1 153.29999999999995c8.3 0 15.8 3.1 21.5 8.3l2.2 2.2 21.5 21.5L733 361c12.4 12.4 12.4 32.8 0 45.3-12.4 12.4-32.8 12.4-45.3 0L512 230.5 336.2 406.2c-12.4 12.4-32.8 12.4-45.3 0-12.4-12.4-12.4-32.8 0.1-45.2l175.7-175.7 21.8-21.8 1.8-1.8c5.7-5.3 13.4-8.5 21.8-8.4z" horiz-adv-x="1024" />
<glyph glyph-name="delete" unicode="&#59113;" d="M512.019034 896C229.689856 896 0 666.310144 0 383.98096599999997c0-282.306337 229.689856-511.980966 512.019034-511.980966 282.321564 0 512.01142 229.67463 512.01142 511.980966C1024.030454 666.310144 794.340597 896 512.019034 896zM713.257467 174.96921199999997c-0.007613-22.109428-17.92965-40.107599-39.955331-40.107599L352.936215 134.86161200000004c-22.02568 0-39.940104 17.990558-39.940104 40.107599L312.996111 493.911419c0 7.704801 6.265861 13.978275 13.978275 13.978275 7.704801 0 13.970661-6.273474 13.970661-13.978275l0-318.942208c0-6.70744 5.382702-12.158663 11.991167-12.158663l320.365921 0c6.608465 0 11.991167 5.451223 11.991167 12.158663L685.293303 493.911419c0 7.704801 6.265861 13.978275 13.978275 13.978275s13.978275-6.273474 13.978275-13.978275L713.249853 174.96921199999997zM431.956104 216.02087700000004L431.956104 493.911419c0 7.704801 6.265861 13.978275 13.970661 13.978275 7.712414 0 13.978275-6.273474 13.978275-13.978275l0-277.882928c0-7.712414-6.265861-13.978275-13.978275-13.978275C438.229578 202.05021599999998 431.956104 208.31607699999995 431.956104 216.02087700000004zM566.340924 216.02087700000004L566.340924 493.911419c0 7.704801 6.265861 13.978275 13.978275 13.978275 7.704801 0 13.970661-6.273474 13.970661-13.978275l0-277.882928c0-7.712414-6.265861-13.978275-13.970661-13.978275C572.606785 202.05021599999998 566.340924 208.31607699999995 566.340924 216.02087700000004zM762.059614 549.002268L615.554197 549.002268c-3.730585 0-7.240381 1.454167-9.882244 4.09603l-52.08354 52.08354L471.987569 605.181838l-62.17896-52.844884c-2.497208-2.139377-5.717693-3.334687-9.044766-3.334687L261.978453 549.002268c-7.712414 0-13.978275 6.273474-13.978275 13.978275s6.265861 13.978275 13.978275 13.978275l133.653931 0 62.171347 52.844884c2.535275 2.14699 5.748147 3.327073 9.05238 3.327073l92.518517 0c3.730585 0 7.240381-1.454167 9.882244-4.09603l52.08354-52.08354 140.711589 0c7.712414 0 13.978275-6.265861 13.978275-13.970661C776.037889 555.275742 769.764415 549.002268 762.059614 549.002268z" horiz-adv-x="1025" />
<glyph glyph-name="qq" unicode="&#58900;" d="M512-128C229.226667-128 0 101.22666700000002 0 384 0 666.773333 229.226667 896 512 896 794.773333 896 1024 666.773333 1024 384 1024 101.22666700000002 794.773333-128 512-128ZM693.333333 437.333333C689.024 457.365333 682.666667 469.333333 682.666667 469.333333 682.666667 469.333333 682.944 498.666667 650.666667 565.333333 618.389333 632 522.666667 640 522.666667 640L512 640C512 640 416.277333 632 384 565.333333 351.722667 498.666667 352 469.333333 352 469.333333 352 469.333333 345.642667 457.365333 341.333333 437.333333 337.024 417.301333 341.333333 405.333333 341.333333 405.333333 341.333333 405.333333 286.656 349.578667 288 309.33333300000004 289.344 269.08799999999997 299.221333 243.45600000000002 320 266.66666699999996 340.778667 289.877333 341.333333 288 341.333333 288 341.333333 288 340.970667 270.66666699999996 352 256 363.029333 241.33333300000004 373.333333 234.66666699999996 373.333333 234.66666699999996 373.333333 234.66666699999996 317.386667 206.965333 330.666667 170.66666699999996 343.946667 134.36800000000005 384.874667 127.71199999999999 416 128 447.125333 128.288 512 149.33333300000004 512 149.33333300000004L522.666667 149.33333300000004C522.666667 149.33333300000004 587.541333 128.288 618.666667 128 649.792 127.71199999999999 690.72 134.36800000000005 704 170.66666699999996 717.28 206.965333 661.333333 234.66666699999996 661.333333 234.66666699999996 661.333333 234.66666699999996 671.637333 241.33333300000004 682.666667 256 693.696 270.66666699999996 693.333333 288 693.333333 288 693.333333 288 693.888 289.877333 714.666667 266.66666699999996 735.445333 243.45600000000002 745.322667 269.08799999999997 746.666667 309.33333300000004 748.010667 349.578667 693.333333 405.333333 693.333333 405.333333 693.333333 405.333333 697.642667 417.301333 693.333333 437.333333Z" horiz-adv-x="1024" />
<glyph glyph-name="weixin" unicode="&#59018;" d="M512-128C229.2-128 0 101.20000000000005 0 384S229.2 896 512 896s512-229.2 512-512-229.2-512-512-512z m105.6 582.1c-91.1 0-164.9-63.6-164.9-139.3 0-81.5 73.8-145.1 164.9-148.6 25.8 3.5 50.1 8.7 73.3 18.6l45.8-27.9-9.2 46.4c32.6 26.8 54.9 65.4 54.9 111.4 0.1 75.7-73.7 139.4-164.8 139.4z m-54.9-111.4c-17.2 0-27.5 10.4-27.5 27.9 0 8.2 10.3 18.6 27.5 18.6 8.1 0 18.3-10.4 18.3-18.6 0-17.5-10.2-27.9-18.3-27.9z m109.9 0c-8 0-18.3 10.4-18.3 27.9 0 8.2 10.3 18.6 18.3 18.6 17.2 0 27.5-10.4 27.5-18.6 0-17.5-10.2-27.9-27.5-27.9z m-55 130c2.5-3.1 5.9-3.4 9.2 0-13.7 77.2-94 139.3-192.4 139.3C328.6 612 242 537.1 242 444.9c0-53 28.3-99.9 73.3-130l-18.3-65 64.1 37.1c25.5-5.2 49.4-9.5 73.3-9.3 4-0.2 6.8 0 9.2 0-3 12-5 24.4-9.2 37.1 4.2 85.6 84 154.8 183.2 157.9z m-109.9 55.7c17.2 0 27.5-10.4 27.5-18.6 0-17.5-10.3-27.9-27.5-27.9-8 0-18.3 10.4-18.3 27.9 0 8.2 10.2 18.6 18.3 18.6z m-174.1-18.5c0 8.2 10.3 18.6 18.3 18.6 17.2 0 27.5-10.4 27.5-18.6 0-17.5-10.3-27.9-27.5-27.9-8 0-18.3 10.4-18.3 27.9z" horiz-adv-x="1024" />
</font>
</defs></svg>

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

@ -0,0 +1,3 @@
[class*=" icon-"], [class^=icon-] {
font-family: iconfont!important;
}

@ -0,0 +1,6 @@
@import "./default/index.scss";
@import "./font/iconfont.css";
@import "./font/icon/iconfont.css";
@import "./lib/index.scss";
@import "./layout/index.scss";
@import "./common.scss";

@ -0,0 +1,14 @@
@import "lib/var";
html,
body,
#app,
.wrapper {
width: 100%;
height: 100%;
}
body {
font-family: 'PingFang SC', "Helvetica Neue", Helvetica, "microsoft yahei", arial, STHeiTi, sans-serif;
font-size: 14px;
background: rgba(0, 0, 0, 0.02);
}

@ -0,0 +1,7 @@
@import "var";
@each $name, $color in $bg-colors {
.bg-#{$name} {
background-color: $color;
}
}

@ -0,0 +1,78 @@
@import "var";
.border {
border: 1px solid $color-border;
}
// vertical
.b-v {
border-top: 1px solid $color-border;
border-bottom: 1px solid $color-border;
}
// horizontal
.b-h {
border-left: 1px solid $color-border;
border-right: 1px solid $color-border;
}
// border double
.b-double {
border: double $color-border;
}
.b-w-thin {
border-width: 0.55px;
}
.b-round {
border-radius: 50%;
}
.b-none {
border: none;
}
@each $side in left, right, top, bottom {
.b-#{str-slice($side, 0, 1)} {
border-#{$side}: 1px solid $color-border;
}
}
// border-style
@each $style in dotted, dashed {
.border-#{$style} {
border: 1px $style $color-border
}
.b-v-#{$style} {
border-top: 1px $style $color-border;
border-bottom: 1px $style $color-border;
}
.b-h-#{$style} {
border-left: 1px $style $color-border;
border-right: 1px $style $color-border;
}
@each $side in left, right, top, bottom {
.b-#{str-slice($side, 0, 1)}-#{$style} {
border-#{$side}: 1px $style $color-border;
}
}
}
@for $size from 0 through $border-width-through {
.b-#{$size} {
border-width: #{$size}px;
}
}
@for $size from 0 through $border-radius-through {
.b-radius-#{$size}, .b-r-#{$size} {
border-radius: #{$size}px;
}
}
@each $name, $color in $border-colors {
.b-#{$name} {
border-color: $color;
}
}

@ -0,0 +1,56 @@
@import "var";
/**
* margin padding
* @each 循环多次保证优先级
*/
.m-auto {
margin-left: auto;
margin-right: auto;
}
@each $size in $box-sizes {
.m-#{$size}, .margin-#{$size} {
margin: #{$size}px;
}
@if $size >= 0 {
.p-#{$size}, .padding-#{$size} {
padding: #{$size}px;
}
}
}
@each $size in $box-sizes {
.m-h-#{$size} {
margin-left: #{$size}px;
margin-right: #{$size}px;
}
.m-v-#{$size} {
margin-top: #{$size}px;
margin-bottom: #{$size}px;
}
@if $size >= 0 {
.p-h-#{$size} {
padding-left: #{$size}px;
padding-right: #{$size}px;
}
.p-v-#{$size} {
padding-top: #{$size}px;
padding-bottom: #{$size}px;
}
}
}
@each $size in $box-sizes {
@each $side in top right bottom left {
.m-#{str-slice($side, 0, 1)}-#{$size} {
margin-#{$side}: #{$size}px;
}
@if $size >= 0 {
.p-#{str-slice($side, 0, 1)}-#{$size} {
padding-#{$side}: #{$size}px;
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save