@ -0,0 +1,3 @@ |
||||
> 1% |
||||
last 2 versions |
||||
not ie <= 8 |
@ -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' |
||||
] |
||||
} |
@ -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> |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 81 KiB |
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)))) |
||||
} |
||||
|
||||
//在页面刷新时将vuex里的信息保存到sessionStorage里 |
||||
window.addEventListener("beforeunload",()=>{ |
||||
sessionStorage.getItem(Setting.usernameKey) && sessionStorage.setItem(Setting.storeKey,JSON.stringify(this.$store.state)) |
||||
}) |
||||
} |
||||
} |
||||
</script> |
After Width: | Height: | Size: 672 B |
After Width: | Height: | Size: 239 B |
After Width: | Height: | Size: 163 KiB |
After Width: | Height: | Size: 764 KiB |
After Width: | Height: | Size: 1.1 MiB |
After Width: | Height: | Size: 209 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 8.1 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 323 KiB |
After Width: | Height: | Size: 995 KiB |
After Width: | Height: | Size: 43 KiB |
After Width: | Height: | Size: 449 B |
After Width: | Height: | Size: 314 B |
After Width: | Height: | Size: 528 B |
After Width: | Height: | Size: 213 KiB |
After Width: | Height: | Size: 196 KiB |
After Width: | Height: | Size: 206 KiB |
After Width: | Height: | Size: 217 KiB |
After Width: | Height: | Size: 196 KiB |
After Width: | Height: | Size: 9.8 KiB |
After Width: | Height: | Size: 20 KiB |
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,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><i class="el-icon-lx-redpacket_fill"></i></span> |
||||
</p> |
||||
<p class="example-p"> |
||||
<i class="el-icon-lx-weibo" style="font-size: 30px;color:#fd5656"></i> |
||||
<span><i class="el-icon-lx-weibo"></i></span> |
||||
</p> |
||||
<p class="example-p"> |
||||
<i class="el-icon-lx-emojifill" style="font-size: 30px;color: #ffc300"></i> |
||||
<span><i class="el-icon-lx-emojifill"></i></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> |
||||
|
@ -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,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"></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"></span> |
||||
<div class="name">已勾选32</div> |
||||
<div class="code-name">&#xe63d;</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont"></span> |
||||
<div class="name">未勾选32</div> |
||||
<div class="code-name">&#xe63e;</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont"></span> |
||||
<div class="name">未勾选40</div> |
||||
<div class="code-name">&#xe64a;</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont"></span> |
||||
<div class="name">已勾选40</div> |
||||
<div class="code-name">&#xe64b;</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont"></span> |
||||
<div class="name">实 向右箭头-01</div> |
||||
<div class="code-name">&#xe626;</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont"></span> |
||||
<div class="name">实 向下箭头-01</div> |
||||
<div class="code-name">&#xe625;</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont"></span> |
||||
<div class="name">加号-填充</div> |
||||
<div class="code-name">&#xe72d;</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont"></span> |
||||
<div class="name">42指向上、上箭头</div> |
||||
<div class="code-name">&#xe769;</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont"></span> |
||||
<div class="name">44指向下、下箭头</div> |
||||
<div class="code-name">&#xe76b;</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont"></span> |
||||
<div class="name">群蜂删除-充</div> |
||||
<div class="code-name">&#xe6e9;</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont"></span> |
||||
<div class="name">qq</div> |
||||
<div class="code-name">&#xe614;</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont"></span> |
||||
<div class="name">微信-36</div> |
||||
<div class="code-name">&#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" |
||||
><span class="iconfont">&#x33;</span> |
||||
</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"><link rel="stylesheet" href="./iconfont.css"> |
||||
</code></pre> |
||||
<h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3> |
||||
<pre><code class="language-html"><span class="iconfont icon-xxx"></span> |
||||
</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"><script src="./iconfont.js"></script> |
||||
</code></pre> |
||||
<h3 id="-css-">第二步:加入通用 CSS 代码(引入一次就行):</h3> |
||||
<pre><code class="language-html"><style> |
||||
.icon { |
||||
width: 1em; |
||||
height: 1em; |
||||
vertical-align: -0.15em; |
||||
fill: currentColor; |
||||
overflow: hidden; |
||||
} |
||||
</style> |
||||
</code></pre> |
||||
<h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3> |
||||
<pre><code class="language-html"><svg class="icon" aria-hidden="true"> |
||||
<use xlink:href="#icon-xxx"></use> |
||||
</svg> |
||||
</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; |
||||
} |
||||
|
@ -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 |
||||
} |
||||
] |
||||
} |
After Width: | Height: | Size: 10 KiB |
@ -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; |
||||
} |
||||
} |
||||
} |
||||
} |