提交 f075d9a3 authored 作者: 王鹏飞's avatar 王鹏飞

merge

......@@ -1169,6 +1169,16 @@
"to-fast-properties": "^2.0.0"
}
},
"@ckeditor/ckeditor5-build-classic": {
"version": "24.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-build-classic/-/ckeditor5-build-classic-24.0.0.tgz",
"integrity": "sha512-659ZAYbuQbPj3ElqrTSV7aqPtW4vt30Th0PiheFei7adIgmu1bFTHgcM3hqm7XGRzGmBRV6C07xSwUptxn3cvQ=="
},
"@ckeditor/ckeditor5-vue2": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-vue2/-/ckeditor5-vue2-1.0.5.tgz",
"integrity": "sha512-snsNB/2oWfKw0drGJAmMGpTatmt//L1rQsOwkBw+1uKUuOJPKN3xwyUZVWT906VguIMXm4E9OHzquZ3bdkijiA=="
},
"@types/anymatch": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz",
......@@ -1922,11 +1932,18 @@
"dev": true
},
"axios": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz",
"integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==",
"version": "0.21.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.0.tgz",
"integrity": "sha512-fmkJBknJKoZwem3/IKSSLpkdNXZeBu5Q7GA/aRsr2btgrptmSCxi2oFjZHqGdK9DoTil9PIHlPIZw2EcRJXRvw==",
"requires": {
"follow-redirects": "1.5.10"
"follow-redirects": "^1.10.0"
},
"dependencies": {
"follow-redirects": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz",
"integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA=="
}
}
},
"babel-eslint": {
......@@ -1999,9 +2016,9 @@
},
"dependencies": {
"core-js": {
"version": "2.6.11",
"resolved": "https://registry.npm.taobao.org/core-js/download/core-js-2.6.11.tgz",
"integrity": "sha1-OIMUafmSK97Y7iHJ3EaYXgOZMIw="
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
"integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ=="
}
}
},
......@@ -3077,9 +3094,9 @@
}
},
"core-js": {
"version": "3.6.5",
"resolved": "https://registry.npm.taobao.org/core-js/download/core-js-3.6.5.tgz",
"integrity": "sha1-c5XcJzrzf7LlDpvT2f6EEoUjHRo="
"version": "3.8.1",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.1.tgz",
"integrity": "sha512-9Id2xHY1W7m8hCl8NkhQn5CufmF/WuR30BTRewvCXc1aZd3kMECwNZ69ndLbekKfakw9Rf2Xyc+QR6E7Gg+obg=="
},
"core-js-compat": {
"version": "3.6.5",
......@@ -3197,9 +3214,9 @@
}
},
"cross-env": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.2.tgz",
"integrity": "sha512-KZP/bMEOJEDCkDQAyRhu3RL2ZO/SUVrxQVI0G3YEQ+OLbRA3c6zgixe8Mq8a/z7+HKlNEjo8oiLUs8iRijY2Rw==",
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
"integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==",
"requires": {
"cross-spawn": "^7.0.1"
}
......@@ -3393,6 +3410,7 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"dev": true,
"requires": {
"ms": "2.0.0"
}
......@@ -3791,9 +3809,9 @@
"dev": true
},
"element-ui": {
"version": "2.13.2",
"resolved": "https://registry.npmjs.org/element-ui/-/element-ui-2.13.2.tgz",
"integrity": "sha512-r761DRPssMPKDiJZWFlG+4e4vr0cRG/atKr3Eqr8Xi0tQMNbtmYU1QXvFnKiFPFFGkgJ6zS6ASkG+sellcoHlQ==",
"version": "2.14.1",
"resolved": "https://registry.npmjs.org/element-ui/-/element-ui-2.14.1.tgz",
"integrity": "sha512-Uje0J12dBaXdyvt/EtuDA8diFbYTdO7uI4QCfl7zmEJmE1WxgCSVKhlRRoL8MDonO8pyNVhB4n0AFAR14g56nw==",
"requires": {
"async-validator": "~1.8.1",
"babel-helper-vue-jsx-merge-props": "^2.0.0",
......@@ -5038,6 +5056,7 @@
"version": "1.5.10",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
"integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
"dev": true,
"requires": {
"debug": "=3.1.0"
}
......@@ -7002,7 +7021,8 @@
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"dev": true
},
"multicast-dns": {
"version": "6.2.3",
......@@ -8194,6 +8214,11 @@
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
"dev": true
},
"qrcode.vue": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/qrcode.vue/-/qrcode.vue-1.7.0.tgz",
"integrity": "sha512-R7t6Y3fDDtcU7L4rtqwGUDP9xD64gJhIwpfjhRCTKmBoYF6SS49PIJHRJ048cse6OI7iwTwgyy2C46N9Ygoc6g=="
},
"qs": {
"version": "6.9.4",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz",
......@@ -10596,14 +10621,14 @@
"integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog=="
},
"vue-i18n": {
"version": "8.22.0",
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.22.0.tgz",
"integrity": "sha512-2tYS0bYDPJHKAWPy01aDe5h3wcXDGjhJmboHKOfi2OEYR+6gyXaIzdua1smZCQwOeWdlGsLntwdIgkXWrnLjxg=="
"version": "8.22.2",
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.22.2.tgz",
"integrity": "sha512-rb569fVJInPUgS/bbCxEQ9DrAoFTntuJvYoK4Fpk2VfNbA09WzdTKk57ppjz3S+ps9hW+p9H+2ASgMvojedkow=="
},
"vue-loader": {
"version": "15.9.3",
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.3.tgz",
"integrity": "sha512-Y67VnGGgVLH5Voostx8JBZgPQTlDQeOVBLOEsjc2cXbCYBKexSKEpOA56x0YZofoDOTszrLnIShyOX1p9uCEHA==",
"version": "15.9.5",
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.5.tgz",
"integrity": "sha512-oeMOs2b5o5gRqkxfds10bCx6JeXYTwivRgbb8hzOrcThD2z1+GqEKE3EX9A2SGbsYDf4rXwRg6D5n1w0jO5SwA==",
"requires": {
"@vue/component-compiler-utils": "^3.1.0",
"hash-sum": "^1.0.2",
......@@ -10633,9 +10658,9 @@
}
},
"vue-router": {
"version": "3.4.6",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.4.6.tgz",
"integrity": "sha512-kaXnB3pfFxhAJl/Mp+XG1HJMyFqrL/xPqV7oXlpXn4AwMmm6VNgf0nllW8ksflmZANfI4kdo0bVn/FYSsAolPQ=="
"version": "3.4.9",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.4.9.tgz",
"integrity": "sha512-CGAKWN44RqXW06oC+u4mPgHLQQi2t6vLD/JbGRDAXm0YpMv0bgpKuU5bBd7AvMgfTz9kXVRIWKHqRwGEb8xFkA=="
},
"vue-style-loader": {
"version": "4.1.2",
......@@ -10661,9 +10686,9 @@
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw=="
},
"vuex": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/vuex/-/vuex-3.5.1.tgz",
"integrity": "sha512-w7oJzmHQs0FM9LXodfskhw9wgKBiaB+totOdb8sNzbTB2KDCEEwEs29NzBZFh/lmEK1t5tDmM1vtsO7ubG1DFw=="
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/vuex/-/vuex-3.6.0.tgz",
"integrity": "sha512-W74OO2vCJPs9/YjNjW8lLbj+jzT24waTo2KShI8jLvJW8OaIkgb3wuAMA7D+ZiUxDOx3ubwSZTaJBip9G8a3aQ=="
},
"watchpack": {
"version": "1.7.4",
......
......@@ -72,19 +72,22 @@
"@babel/runtime-corejs3": "^7.11.2"
},
"dependencies": {
"axios": "^0.19.2",
"cross-env": "^7.0.2",
"element-ui": "^2.13.0",
"@ckeditor/ckeditor5-build-classic": "^24.0.0",
"@ckeditor/ckeditor5-vue2": "^1.0.5",
"axios": "^0.21.0",
"core-js": "^3.8.1",
"cross-env": "^7.0.3",
"element-ui": "^2.14.1",
"js-cookie": "^2.2.1",
"lodash": "^4.17.15",
"lodash": "^4.17.20",
"qrcode.vue": "^1.7.0",
"qs": "^6.9.4",
"vue": "^2.6.11",
"vue-i18n": "^8.16.0",
"vue-loader": "^15.9.1",
"vue": "^2.6.12",
"vue-i18n": "^8.22.2",
"vue-loader": "^15.9.5",
"vue-meta-info": "^0.1.7",
"vue-router": "^3.1.6",
"vue-template-compiler": "^2.6.11",
"vuex": "^3.1.3",
"core-js": "^3.6.5"
"vue-router": "^3.4.9",
"vue-template-compiler": "^2.6.12",
"vuex": "^3.6.0"
}
}
......@@ -139,28 +139,28 @@ export default class CourseAction extends BaseACTION {
__.live.live_status = parseInt(__.live.live_status)
let str = ''
switch (__.live.live_status) {
case 1: str = '直播未开始'; break
case 2: str = '正在直播'; break
case 3: str = '直播结束'; break
case 4: str = '即将开始'; break
case 5: str = '直播结束'; break
default: str = '直播未开始'
case 1: str = _vIn.$t('live.notStarted'); break
case 2: str = _vIn.$t('live.liveStreaming'); break
case 3: str = _vIn.$t('live.liveEnd'); break
case 4: str = _vIn.$t('live.start'); break
case 5: str = _vIn.$t('live.liveEnd'); break
default: str = _vIn.$t('live.notStarted')
}
// 5分钟内显示“即将开始”,5~1小时内“N分钟后开始”,1~24小时内“N小时后开始”,1天以上“N天后开始”天就显示年月日
if (__.live.live_status === 1 && __.live.start_time) {
const time = (new Date(__.live.start_time).getTime() - new Date().getTime()) / 1000
if (time <= 5 * 60) {
str = '即将开始'
str = _vIn.$t('live.start')
} else if (time <= 1 * 60 * 60) {
str = parseInt(time / 60) + '分钟后开始'
str = _vIn.$t('live.startInMinutes', { minutes: parseInt(time / 60) })
} else if (time <= 24 * 60 * 60) {
str = parseInt(time / (60 * 60)) + '小时' + parseInt(time / 60 % 60) + '分钟后开始'
str = _vIn.$t('live.startInHours', { h: parseInt(time / (60 * 60)), min: parseInt(time / 60 % 60) })
} else {
str = parseInt(time / (24 * 60 * 60)) + '天后开始'
str = _vIn.$t('live.startInDay', { day: parseInt(time / (24 * 60 * 60)) })
}
}
if (__.live.live_status === 3 && __.live.enable_record && __.live.record_url) {
str = '观看回放'
str = _vIn.$t('live.watchReplay')
}
__.live.statusStr = str
}
......@@ -184,7 +184,7 @@ export default class CourseAction extends BaseACTION {
})
}
json.tabs1ChapterList.course.push({
title: '课程大作业',
title: _vIn.$t('action.courseAction.courseWork'),
isUp: true,
chapters: [],
id: 'course_work',
......@@ -193,7 +193,7 @@ export default class CourseAction extends BaseACTION {
type: 99
})
json.tabs1ChapterList.course.push({
title: '课程资料',
title: _vIn.$t('action.courseAction.courseData'),
isUp: true,
chapters: [],
id: 'course_info',
......@@ -202,7 +202,7 @@ export default class CourseAction extends BaseACTION {
type: 100
})
json.tabs1ChapterList.course.push({
title: '教学评估',
title: _vIn.$t('action.courseAction.teachingEvaluation'),
isUp: true,
chapters: [],
id: 'teach_evaluation',
......@@ -212,7 +212,7 @@ export default class CourseAction extends BaseACTION {
})
if (cur.course_examination) {
let courseExamChildren = []
if (data.exist_examination.length > 1) {
if (data.exist_examination && data.exist_examination.length > 1) {
courseExamChildren = data.exist_examination.map((item, index) => {
const map = ['一', '二', '三']
return {
......@@ -227,7 +227,7 @@ export default class CourseAction extends BaseACTION {
})
}
json.tabs1ChapterList.course.push({
title: '课程考试',
title: _vIn.$t('action.courseAction.courseExam'),
isUp: true,
chapters: courseExamChildren,
id: 'course_exam',
......
import BaseAPI from '@/api/base_api'
const httpRequest = new BaseAPI(webConf)
/**
* 上传文件
*/
export function uploadFile(data) {
return httpRequest.post('/api/lms/util/upload-file', data, {
headers: { 'Content-Type': 'multipart/form-data' }
})
}
<template>
<div style="height: 100%; width: 100%;">
<div style="height: 100%; width: 100%">
<router-view></router-view>
</div>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
</style>
import { uploadFile } from '@/api/common'
export default class MyUploadAdapter {
constructor(loader) {
// The file loader instance to use during the upload.
this.loader = loader
}
// Starts the upload process.
upload() {
return this.loader.file.then(
file =>
new Promise((resolve, reject) => {
this._sendRequest(resolve, reject, file)
})
)
}
_sendRequest(resolve, reject, file) {
uploadFile({ file })
.then(response => {
if (response.success) {
resolve({ default: response.url })
} else {
return reject(response.message)
}
})
.catch(response => {
return reject(response.message)
})
}
}
<template>
<div class="ckeditor">
<ckeditor
:editor="editor"
:value="value"
:disabled="disabled"
:config="editorConfig"
@ready="onEditorReady"
@input="onEditorInput"
></ckeditor>
</div>
</template>
<script>
import CKEditor from '@ckeditor/ckeditor5-vue2'
import ClassicEditor from '@ckeditor/ckeditor5-build-classic'
import '@ckeditor/ckeditor5-build-classic/build/translations/zh-cn'
import MyUploadAdapter from './MyUploadAdapter'
export default {
components: {
ckeditor: CKEditor.component
},
props: {
value: { type: String },
disabled: { type: Boolean, default: false }
},
data() {
return {
editor: ClassicEditor,
editorConfig: {
language: this.$i18n.locale.toLocaleLowerCase()
}
}
},
methods: {
onEditorReady(editor) {
const FileRepository = editor.plugins.get('FileRepository')
// 自定义上传图片插件
FileRepository.createUploadAdapter = loader => {
return new MyUploadAdapter(loader)
}
},
onEditorInput(value) {
this.$emit('input', value)
}
}
}
</script>
<style>
.ck-content {
min-height: 300px;
max-height: 500px;
word-break: break-word;
}
.ck-sticky-panel__content {
position: unset !important;
}
</style>
......@@ -54,7 +54,7 @@ export default {
data () { return { isWatch: true } },
methods: {
getList () {
const loading = this.$loading({ lock: true, text: '数据加载中,请稍后。。。', background: 'rgba(0, 0, 0, 0.7)' })
const loading = this.$loading({ lock: true, background: 'rgba(0, 0, 0, 0.7)' })
const obj = this.objFn.paramsFn(this)
while (this.tableData.length) {
this.tableData.pop()
......
......@@ -51,7 +51,7 @@ export default {
id: _data.val,
name: item.name
}
this.$emit('tapParam', param)
this.$emit('tapParam', param, item)
}
}
}
......
<template>
<div class="editor">
<textarea name="editor" :id="textareaElementId" :disabled="disabled"></textarea>
</div>
</template>
<script>
import { uniqueId } from 'lodash'
export default {
name: 'VEditor',
props: {
value: { type: String },
disabled: { type: Boolean, default: false }
},
data() {
return {
textareaElementId: uniqueId('editor_'),
ckEditor: null
}
},
watch: {
value(val) {
if (this.ckEditor && this.ckEditor.getData() !== val) {
this.ckEditor.setData(val)
}
},
disabled(val) {
if (this.ckEditor && this.ckEditor.instanceReady) {
this.ckEditor.setReadOnly(val)
}
}
},
methods: {
createEditor() {
const config = {
height: 400,
uiColor: '#eeeeee',
filebrowserImageUploadUrl: '/api/ck/form/ckeditor-upload',
fileTools_requestHeaders: { tenant: 'sofia' },
// resize_enabled: typeof this.props.resizable === 'boolean' ? this.props.resizable : true,
toolbar: [
// { name: 'document', items: ['Source', '-', 'Save', 'NewPage', 'Preview'] },
{ name: 'styles', items: ['Styles', 'Format', 'Font', 'FontSize'] },
{ name: 'colors', items: ['TextColor', 'BGColor'] },
{ name: 'tools', items: ['Maximize', 'ShowBlocks'] },
// { name: 'clipboard', items: ['Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo'] },
{ name: 'editing', items: ['Find', 'Replace'] },
// { name: 'forms', items: ['Form', 'Checkbox', 'Radio', 'TextField', 'Textarea', 'Select', 'Button', 'ImageButton', 'HiddenField'] },
'/',
{
name: 'basicstyles',
items: ['Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat']
},
{
name: 'paragraph',
items: [
'NumberedList',
'BulletedList',
'-',
'Outdent',
'Indent',
'-',
'Blockquote',
'CreateDiv',
'-',
'JustifyLeft',
'JustifyCenter',
'JustifyRight',
'JustifyBlock',
'-',
'BidiLtr',
'BidiRtl'
]
},
{ name: 'links', items: ['Link', 'Unlink', 'Anchor'] },
{ name: 'insert', items: ['Image', 'Table', 'HorizontalRule'] }
]
}
// if (this.disabled !== null) {
// console.log(this.disabled)
// config.readOnly = this.disabled
// }
const editor = (this.ckEditor = CKEDITOR.replace(this.textareaElementId, config))
editor.on('instanceReady', () => {
const data = this.value
editor.fire('lockSnapshot')
editor.setData(data, {
callback: () => {
this.bindEvent()
const newData = editor.getData()
// Locking the snapshot prevents the 'change' event.
// Trigger it manually to update the bound data.
if (data !== newData) {
this.$once('input', () => {
this.$emit('ready', editor)
})
this.$emit('input', newData)
} else {
this.$emit('ready', editor)
}
editor.fire('unlockSnapshot')
}
})
editor.setReadOnly(this.disabled)
})
},
bindEvent() {
const editor = this.ckEditor
editor.on('change', evt => {
const data = editor.getData()
if (this.value !== data) {
this.$emit('input', data, evt, editor)
}
})
editor.on('focus', evt => {
this.$emit('focus', evt, editor)
})
editor.on('blur', evt => {
this.$emit('blur', evt, editor)
})
}
},
mounted() {
this.createEditor()
},
beforeDestroy() {
this.ckEditor && this.ckEditor.destroy()
this.ckEditor = null
}
}
</script>
<style lang="scss" scoped>
* {
margin: 0;
padding: 0;
}
</style>
<template>
<div class="tap-language-switch">
<el-menu class="el-menu-demo" mode="horizontal" @select="handleSelect">
<el-submenu index="1">
<template slot="title">{{ show }}</template>
<template v-for="item in language.arr">
<template v-for="(v, k) in item">
<el-menu-item :key="k" :index="k">{{v}}</el-menu-item>
</template>
</template>
</el-submenu>
</el-menu>
</div>
<div class="language-switch">
<el-select size="medium" v-model="value" @change="handleChange">
<el-option v-for="item in languages" :key="item.value" :label="item.name" :value="item.value"> </el-option>
</el-select>
</div>
</template>
<script>
import Cookies from 'js-cookie'
import language from '@/assets/languages/language'
export default {
name: 'sLanguage',
componentName: 'sLanguage',
data () {
const _defaultLocale = 'zh-CN'
const _lang = Cookies.get('lang') || window.navigator.language || window.navigator.userLanguage || ''
if (_lang) {
if (language[_lang]) {
this.$i18n.locale = _lang
} else {
let flag = true
/* 做一下 兼容性处理 */
for (const k in language) {
const reg = new RegExp(k, 'gi')
if (reg.test(_lang)) {
this.$i18n.locale = k
flag = false
break
}
}
if (flag) {
/* 当前语言版本 - 不再我们的语言库中,那么默认 en */
this.$i18n.locale = _defaultLocale
Cookies.set('lang', _defaultLocale, { expires: 30, domain: '.ezijing.com' })
}
}
} else {
this.$i18n.locale = _defaultLocale
Cookies.set('lang', _defaultLocale, { expires: 30, domain: '.ezijing.com' })
}
let show = language[this.$i18n.locale].show
language[this.$i18n.locale].arr.forEach((item, i) => {
if (item[this.$i18n.locale]) {
show = item[this.$i18n.locale]
}
})
name: 'LanguageSwitch',
data() {
return {
show: show,
language: language[this.$i18n.locale]
value: this.$i18n.locale,
languages: [
{ name: '中文', value: 'zh-CN' },
{ name: 'English', value: 'en' }
]
}
},
mounted () {},
methods: {
handleSelect (key, val) {
Cookies.set('lang', key, { expires: 30, domain: '.ezijing.com' })
this.$i18n.locale = key
handleChange(value) {
Cookies.set('lang', value, { expires: 30, domain: '.ezijing.com' })
this.$i18n.locale = value
/* 刷新页面 */
this.$router.go(0)
}
......@@ -71,15 +32,11 @@ export default {
</script>
<style lang="scss" scoped>
.tap-language-switch {
position: absolute;
right: 100px;
.el-menu {
border: none;
.language-switch {
width: 100px;
::v-deep .el-input__inner {
background: transparent;
}
.el-menu--horizontal > .el-submenu.is-active .el-submenu__title {
border: none;
border: 0;
}
}
</style>
......@@ -4,45 +4,42 @@
<img class="logo" src="@/assets/images/logo-header.png" alt="logo" />
<div class="text-title" @click="setStatus">{{ $t('components.learnSysLayout.navigation.title') }}</div>
</div>
<!-- <s-language></s-language> -->
<div class="notify" @click="goNotify()">{{ $t('components.learnSysLayout.navigation.tip') }}
<div class="num" v-if="this.$store.getters.myMsg !=0">{{ this.$store.getters.myMsg }}</div>
<div class="nav-right">
<div class="notify" @click="goNotify()">
{{ $t('components.learnSysLayout.navigation.tip') }}
<div class="num" v-if="this.$store.getters.myMsg != 0">{{ this.$store.getters.myMsg }}</div>
</div>
<!-- <language-switch /> -->
</div>
</div>
</template>
<script>
// import sLanguage from '@/components/languageSwitch/index.vue'
import LanguageSwitch from '@/components/languageSwitch/index.vue'
import cAction from '../../action'
export default {
components: {},
data () {
components: { LanguageSwitch },
data() {
return {
num: this.$store.getters.myMsg
}
},
mounted () {
// request({
// component: this,
// actionName: 'Other',
// functionName: 'getNavMsg',
// data: {},
// thenCallback: data => {
// this.$store.commit('myMsg', data.num)
// },
// catchCallback: () => {},
// finallyCallback: () => {}
// })
cAction.Other.getNavMsg().then(data => {
mounted() {
cAction.Other.getNavMsg()
.then(data => {
this.$store.commit('myMsg', data.num)
}).catch(e => { this.$message.error(e.message) }).finally(() => { })
})
.catch(e => {
this.$message.error(e.message)
})
.finally(() => {})
},
methods: {
goNotify () {
goNotify() {
this.$router.push({ path: '/app/other/message' })
},
setStatus () {
setStatus() {
if (this.status) {
this.status = false
} else {
......@@ -56,9 +53,10 @@ export default {
<style scoped lang="scss">
.menu {
width: 100%;
height: 100%;
color: #ffffff;
display: flex;
align-items: center;
justify-content: space-between;
color: #fff;
.nav-left {
float: left;
position: relative;
......@@ -78,6 +76,10 @@ export default {
font-size: 16px;
}
}
.nav-right {
display: flex;
align-items: center;
}
.notify {
position: relative;
float: right;
......
......@@ -110,7 +110,7 @@ export default {
case '1-3': this.$router.push({ path: '/app/learn/report-active-list' }); break
case '2-1': this.$router.push({ path: '/app/grade/credit' }); break
case '3': this.$router.push({ path: '/app/feedback/feedback-list' }); break
case '4': this.$router.push({ path: '/app/affairs-hall/hall' }); break
case '4': this.$router.push({ path: '/app/offices' }); break
}
},
/* 修改头像 - 跳转方法 */
......
## 组件简介
| 字段值 | 说明 | 字段属性 | 默认值 |
| ------- | ------------------------- | ------- | ----- |
| `type` | 类型:`String`; 说明:组件类型名 | 自定义字段 | `upload-form` |
| `action` | 类型:`String`; 说明:上传请求接口path | 自定义字段 | `` |
| `deleteAction` | 类型:`String`; 说明:删除请求接口path | 自定义字段 | `` |
| `html` | 类型:`String`; 说明:上传说明,支持html | 自定义字段 | `` |
| `label` | 类型:`String`; 说明:组件左侧显示名称 | element-ui el-form-item对应字段 | `''` |
| `label-width` | 类型:`String`; 说明:组件左侧显示名称宽度(加单位),父级设置可以子级继承 | element-ui el-form-item对应字段 | `''` |
| `required` | 类型:`Boolean`; 说明:标识是否必填 | element-ui el-form-item对应字段 | `false` |
| `disabled` | 类型:`Boolean`; 说明:标识是否只读 | element-ui el-form-item对应字段 | `false` |
| `model` | 类型:`String`; 说明:表单提交name值和回显对照字段 | 自定义字段 | `''` |
| `placeholder` | 类型:`String`; 说明:组件input框中,默认提示文字 | element-ui el-input对应字段 | `''` |
| `attrs` | 类型:`Object`; 说明:定义标签上Data属性值 | element-ui对应字段 | `{}` |
| `rules` | 类型:`Array`; 说明:组件错误提示规则 | element-ui el-form-item对应字段 | `[]` |
### Demo Example:
``` js
return {
type: 'upload-form',
label: '姓名',
labeWidth: '160px',
required: true,
disabled: false,
model: 'uploadArrs',
action: '',
data: {
},
deleteAction: '',
deleteData: {
},
html: `
<div style="color: #72818c; font-size: 14px;">
<p style="margin: 0;">申请者需要将有效身份证件原件扫描或者拍照后提交。</p>
<p style="margin: 0;">请您提供有效身份证件的扫描件,身份证与台港澳居民大陆通行证应包括正反两面扫描件。</p>
<p style="margin: 0;">只上传一个文件,多份文件需合并到一个文件后打印出来检查无误后再上传。</p>
<p style="margin: 0;">上传文件仅限“jpg,jpeg,gif,png”格式,文件小于10MB。</p>
</div>
`,
attrs: {
multiple: false,
limit: 1
},
rules: [
{
required: true,
message: '请上传',
trigger: 'blur'
}
]
}
```
* 其他属性 [参考文档]([https://](https://element.eleme.cn/#/zh-CN/component/input))
import Upload from './src/uploadForm.vue'
/* istanbul ignore next */
Upload.install = function (Vue) {
Vue.component(Upload.name, Upload)
}
export default Upload
function getError (action, option, xhr) {
let msg
if (xhr.response) {
msg = `${xhr.response.error || xhr.response}`
} else if (xhr.responseText) {
msg = `${xhr.responseText}`
} else {
msg = `fail to post ${action} ${xhr.status}`
}
const err = new Error(msg)
err.status = xhr.status
err.method = 'post'
err.url = action
return err
}
function getBody (xhr) {
const text = xhr.responseText || xhr.response
if (!text) {
return text
}
try {
return JSON.parse(text)
} catch (e) {
return text
}
}
export function deleteFile (option) {
if (typeof XMLHttpRequest === 'undefined') {
return
}
// eslint-disable-next-line no-undef
const xhr = new XMLHttpRequest()
let action = option.action
xhr.onerror = function error (e) {
option.onError(e)
}
xhr.onload = function onload () {
if (xhr.status < 200 || xhr.status >= 300) {
return option.onError(getError(action, option, xhr))
}
option.onSuccess(getBody(xhr))
}
xhr.open('delete', action, true)
if (option.withCredentials && 'withCredentials' in xhr) {
xhr.withCredentials = true
}
const headers = option.headers || {}
for (let item in headers) {
if (headers.hasOwnProperty(item) && headers[item] !== null) {
xhr.setRequestHeader(item, headers[item])
}
}
xhr.send()
return xhr
}
export default function upload (option) {
if (typeof XMLHttpRequest === 'undefined') {
return
}
// eslint-disable-next-line no-undef
const xhr = new XMLHttpRequest()
const action = option.action
if (xhr.upload) {
xhr.upload.onprogress = function progress (e) {
if (e.total > 0) {
e.percent = e.loaded / e.total * 100
}
option.onProgress(e)
}
}
// eslint-disable-next-line no-undef
const formData = new FormData()
if (option.data) {
Object.keys(option.data).forEach(key => {
formData.append(key, option.data[key])
})
}
formData.append(option.filename, option.file, option.file.name)
xhr.onerror = function error (e) {
option.onError(e)
}
xhr.onload = function onload () {
if (xhr.status < 200 || xhr.status >= 300) {
return option.onError(getError(action, option, xhr))
}
option.onSuccess(getBody(xhr))
}
xhr.open('post', action, true)
if (option.withCredentials && 'withCredentials' in xhr) {
xhr.withCredentials = true
}
const headers = option.headers || {}
for (let item in headers) {
if (headers.hasOwnProperty(item) && headers[item] !== null) {
xhr.setRequestHeader(item, headers[item])
}
}
xhr.send(formData)
return xhr
}
<template>
<div class="upload-form">
<div class="u-babel">{{ item.label }}</div>
<el-upload style="display: inline-block;"
:action="item.action"
:data="item.data"
:before-upload="beforeUploadFile"
:on-success="onSuccessFile"
:with-credentials="true"
:show-file-list="false"
:disabled="(item.disabled || false) || !isUpload"
v-bind="item.attrs || {}"
>
<el-button type="primary" size="small" :disabled="!isUpload">点击上传</el-button>
<template v-if="formData[item.model] !== null && formData[item.model] !== '' && formData[item.model] !== undefined">
<div class="self-icon el-icon-circle-check" style="color: #237f00;"></div>
</template>
<div class="self-icon el-icon-circle-close" style="color: #b01c40;"></div>
</el-upload>
<div style="overflow: hidden; padding: 10px 0 0 0;">
<template v-if="filesArr.length">
<!-- 遍历显示文件 -->
<template v-for="(item, index) in filesArr">
<template v-if="/(jpeg)|(jpg)|(png)|(gif)/gi.test(item.url)">
<div v-bind:key="item.id" class="show-file">
<template v-if="!(item.disabled || false) && isUpload">
<div class="close" @click="deleteFiles(index)">X</div>
</template>
<el-avatar shape="square" :size="100" fit="contain" :src="item.url"></el-avatar>
<span class="title">{{ item.sso_file_name }}</span>
<div class="hover">
<a target="_blank" :href="item.url">下载</a>
</div>
</div>
</template>
<template v-else>
<div v-bind:key="item.id" class="show-file">
<template v-if="!(item.disabled || false) && isUpload">
<div class="close" @click="deleteFiles(index)">X</div>
</template>
<el-avatar shape="square" :size="100" fit="contain" :src="item.url"></el-avatar>
<span class="title">{{ item.sso_file_name }}</span>
<div class="hover">
<a target="_blank" :href="item.url">下载</a>
</div>
</div>
</template>
</template>
</template>
</div>
<div class='info' style="line-height: 1.5;" v-html="item.html"></div>
</div>
</template>
<script>
// import { deleteFile } from './ajax'
export default {
name: 'UploadForm',
componentName: 'UploadForm',
props: {
item: {
type: Object,
default () {
return {}
}
},
formData: {
type: Object,
default () {
return {}
}
},
isUpload: {
type: Boolean,
default () {
return true
}
}
},
data () {
const tmpArr = this.formData[this.item.model] || []
this.formData[this.item.model] = tmpArr
return {
project_id: '',
filesArr: tmpArr
}
},
methods: {
beforeUploadFile (file) {},
onSuccessFile (response, file, fileList) {
response.url = response.url || response.file || ''
response.sso_file_name = file.name
this.filesArr.push(response)
// this.$emit('onSubmit')
},
deleteFiles (index) {
this.filesArr.splice(index, 1)
// let temp = this.filesArr[index]
// deleteFile({
// action: this.item.deleteAction + '/' + temp.id + '?project_id=' + this.item.data.project_id,
// onError: () => {},
// onSuccess: (res) => {
// if (res.status === 200) {
// this.filesArr.splice(index, 1)
// }
// }
// })
}
},
watch: {
filesArr: {
immediate: true,
deep: true,
handler (value) {
if (this.formData[this.item.model].length !== value.length) {
this.formData[this.item.model] = value
}
}
}
}
}
</script>
<style lang="scss">
.u-babel {
display: inline-block;
margin-right: 10px;
}
.self-icon {
display: none !important;
vertical-align: middle;
margin-left: 10px;
font-size: 21px;
line-height: 22px;
}
.is-error .self-icon.el-icon-circle-close { display: inline-block !important; }
.is-success .self-icon.el-icon-circle-check { display: inline-block !important; }
.show-file {
position: relative;
float: left;
margin-right: 10px;
.close {
position: absolute;
z-index: 10;
right: -10px;
top: -10px;
width: 20px;
height: 20px;
color: #fff;
font-size: 12px;
line-height: 20px;
text-align: center;
background: #efefef;
border-radius: 50%;
cursor: pointer;
}
.el-avatar {
img {
width: 100%;
}
}
.title {
position: absolute;
left: 0;
bottom: 8px;
width: 100%;
padding-left: 5px;
font-size: 12px;
line-height: 20px;
background: #efefef;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
word-break: break-all;
box-sizing: border-box;
}
.hover {
display: none;
position: absolute;
z-index: 9;
top: 0;
left: 0;
height: 100px;
width: 100%;
background: rgba(0, 0, 0, 0.2);
line-height: 100px;
text-align: center;
a {
color: #f1f1f1;
}
}
&:hover {
.hover {
display: block;
}
}
}
</style>
......@@ -7,7 +7,7 @@
<title>紫荆教育MBA学习系统</title>
<meta name="viewport" id="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, shrink-to-fit=no">
<!-- 直接引入aliyun播放插件 CSS -->
<link rel="stylesheet" href="https://g.alicdn.com/de/prismplayer/2.8.8/skins/default/aliplayer-min.css" />
<link rel="stylesheet" href="https://g.alicdn.com/de/prismplayer/2.9.1/skins/default/aliplayer-min.css" />
</head>
<body>
<div id="app"></div>
......@@ -15,16 +15,17 @@
<!-- <script type="text/javascript" src="https://zws-imgs-pub.ezijing.com/static/build/learn-mba/static/compatible/es5-shim.min.js"></script>
<script type="text/javascript" src="https://zws-imgs-pub.ezijing.com/static/build/learn-mba/static/compatible/es5-sham.min.js"></script> -->
<!-- 三方插件引入 -->
<script type="text/javascript" src="https://zws-imgs-pub.ezijing.com/static/build/learn-mba/static/ckeditor/ckeditor.js"></script>
<script type="text/javascript" src="https://zws-imgs-pub.ezijing.com/static/build/learn-mba/static/videoJs/videoJs.js"></script>
<!-- <script type="text/javascript" src="https://zws-imgs-pub.ezijing.com/static/build/learn-mba/static/ckeditor/ckeditor.js"></script>
<script type="text/javascript" src="https://zws-imgs-pub.ezijing.com/static/build/learn-mba/static/videoJs/videoJs.js"></script> -->
<!-- common -->
<script type="text/javascript" src="https://zws-imgs-pub.ezijing.com/static/build/learn-mba/static/common/base64.js"></script>
<script type="text/javascript" src="https://zws-imgs-pub.ezijing.com/static/build/learn-mba/static/common/md5.js"></script>
<script type="text/javascript" src="https://zws-imgs-pub.ezijing.com/static/build/learn-mba/static/common/jQuery-2.1.4.min.js"></script>
<script type="text/javascript" src="https://zws-imgs-pub.ezijing.com/static/build/learn-mba/static/common/runtime.js"></script>
<!-- 直接引入aliyun播放插件 JS -->
<script type="text/javascript" charset="utf-8" src="https://g.alicdn.com/de/prismplayer/2.8.8/aliplayer-min.js"></script>
<script type="text/javascript" charset="utf-8" src="https://player.alicdn.com/aliplayer/presentation/js/aliplayercomponents.min.js"></script> <!-- 解决iframe嵌套,CC视频在safri中打开免登陆兼容问题 -->
<script type="text/javascript" charset="utf-8" src="https://g.alicdn.com/de/prismplayer/2.9.1/aliplayer-min.js"></script>
<script type="text/javascript" charset="utf-8" src="https://player.alicdn.com/aliplayer/presentation/js/aliplayercomponents.min.js"></script>
<!-- 解决iframe嵌套,CC视频在safri中打开免登陆兼容问题 -->
<script src="//view.csslcloud.net/js/_fix_.js"></script>
<script src="//view.csslcloud.net/js/jquery-1.9.0.min.js" type="text/javascript"></script>
<script src="//view.csslcloud.net/js/sdk/3.1.0/liveSDK.js" type="text/javascript"></script>
......
import Vue from 'vue' // 引入vue框架
import VueRouter from 'vue-router' // 使用 vue-router
import createRouter from './router' // router定义
import router from './router' // router定义
import VueI18n from 'vue-i18n' // 使用 国际化
import createI18n from './assets/languages' // 国际化定义
import store from './store'
import App from './app.vue' // 初始化 vue页面
import UploadForm from './components/upload-form'
import './style.scss' // 公共样式
import MetaInfo from 'vue-meta-info'
import Element from 'element-ui'
import modules from './modules'
import Modules from '@/modules'
import createBefore from './components/beforeEnter'
import store from './store'
import _ from 'lodash'
Vue.prototype.$_ = _
Vue.use(VueRouter)
Vue.use(UploadForm)
Vue.component(UploadForm.name, UploadForm)
const router = createRouter()
Vue.use(VueI18n)
const i18n = createI18n()
Vue.use(MetaInfo)
Vue.use(Element, { i18n: (key, value) => i18n.t(key, value) })
Vue.use(modules, { i18n })
Vue.use(Modules, { i18n, router })
/* 设置全局变量 */
window.G = Vue.prototype.$GLOBAL = {
VERSION: 'PC-1.0.0'
}
// window.Promise = Promise
/**
* 定义全局变量 - 用作全局事件发布订阅
* 使用 vue自带事件 $emit 和 $on 进行发布订阅
*/
Vue.prototype.VueEvent = new Vue()
/* 创建实例之前,通过导航守卫,处理部分逻辑,如:是否直接进入系统 */
const before = createBefore()
const routerBefore = createBefore()
/* 导航守卫 */
router.beforeEach((to, from, next) => {
before.update(to, from, next)
routerBefore.update(to, from, next)
// next()
})
......
......@@ -20,7 +20,7 @@
{{ $t('pages.learn.discussDetail.discuss') }}({{ data.comments.length }})
</div>
<div class="right-txt" @click="$emit('btnlike', { tagId: data.tag ? data.tag.id : null, ansId: data.id })">
点赞({{ data.tag_count }})
{{ $t('pages.learn.discussDetail.like') }}({{ data.tag_count }})
</div>
</div>
<template v-if="commentVisible">
......
......@@ -22,7 +22,7 @@
</div>
</template>
<template v-if='!discussList.length'>
<div class='no-data'>暂无相关讨论</div>
<div class='no-data'>{{ $t('DiscussModule.DiscussList.noData') }}</div>
</template>
</div>
</template>
......
......@@ -143,7 +143,7 @@ export default {
// 通过点击不同的回复按钮 拼成所要提交不同的参数
replyComposeParam (obj, answer) {
this.$refs.focusTextarea.focus()
this.inputStatus.placeholder = obj.to !== undefined ? `回复${obj.to}:` : '回复:'
this.inputStatus.placeholder = obj.to !== undefined ? `${this.$t('DiscussModule.DiscussDetail.reply')}${obj.to}:` : `${this.$t('DiscussModule.DiscussDetail.reply')}:`
this.answer = answer || false
const commonParam = {
questionId: this.detail.id,
......
/* Automatically generated by './build/bin/build-entry.js' */
/* 模块基于 element-ui,一定在 element-ui后加载 */
import LoginModule from './login-module'
import Discuss from './discuss'
import Viewer from './viewer'
import Offices from './offices'
const components = [
LoginModule,
Discuss
]
const components = [Discuss, Viewer, Offices]
const install = function (Vue, opts = {}) {
const install = function(Vue, opts = {}) {
components.forEach(component => {
Vue.use(component, opts)
})
......@@ -20,8 +15,4 @@ if (typeof window !== 'undefined' && window.Vue) {
install(window.Vue)
}
export default {
install,
LoginModule,
Discuss
}
export default { install, ...components }
import BaseACTION from '@/action/base_action'
import { Login } from '../api'
export default class LoginAction extends BaseACTION {
/**
* 当前登录用户,检测是否该系统有权限
*/
getInfo () { return Login.getInfo().then(res => res) }
/**
* 调用登录接口
*/
userLogin (obj) {
return Login.userLogin(obj).then(res => {
if (res && res.url === undefined) {
res.url = webConf.others.url || ''
}
return res
})
}
/**
* 调用验证码登录
*/
codeLogin (obj) {
return Login.codeLogin(obj).then(res => {
if (res && res.url === undefined) {
res.url = webConf.others.url || ''
}
return res
})
}
/* 调用退出登录接口 */
outLogin () { return Login.outLogin().then(res => res) }
/**
* 调用获取验证码
*/
sendCode (obj) { return Login.sendCode(obj).then(res => res) }
/**
* 调用发送重置密码验证码
*/
sendResetPwdCode (obj) { return Login.sendResetPwdCode(obj).then(res => res) }
/**
* 调用重置密码验证码确认
*/
validateCode (obj) { return Login.validateCode(obj).then(res => res) }
/**
* 调用重置密码
*/
resetPwd (obj) { return Login.resetPwd(obj).then(res => res) }
/**
* 清空cookies
*/
clearCookies (obj) { return Login.clearCookies(obj).then(res => res) }
}
import LoginAction from './LoginAction'
const Login = new LoginAction()
export default Login
import LoginAPI from './login_api'
const Login = new LoginAPI(webConf)
export {
Login
}
import BaseAPI from '@/api/base_api'
export default class LoginAPI extends BaseAPI {
/**
* 调用登录接口
* @param {[string]} obj.login_name 用户名
* @param {[string]} obj.password 密码 md5加密
* @param {[string]} obj.service 传当前域名
*/
userLogin = (obj = {}) => this.post('/api/passport/rest/login', obj, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
/**
* 调用退出登录
*/
outLogin = () => this.get('/api/passport/rest/logout', {}, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
/**
* 当前登录用户,检测是否该系统有权限
*/
getInfo = () => this.get('/api/passport/account/get-user-info', {}, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
/**
* 发送验证码
* @param {[string]} obj.mobile 手机号
* @param {[string]} obj.service 传当前域名
*/
sendCode = (obj = {}) => this.post('/api/usercenter/user/send-code', obj, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
/**
* 验证码登录
* @param {[string]} obj.mobile 手机号
* @param {[string]} obj.code 验证码
* @param {[string]} obj.service 传当前域名
*/
codeLogin = (obj = {}) => this.post('/api/passport/rest/login', obj, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
/**
* 发送重置密码验证码
* @param {[string]} obj.contact 手机号/邮箱
* @param {[string]} obj.source_type 值为 3
* @param {[string]} obj.service 传当前域名
*/
sendResetPwdCode = (obj = {}) => this.post('/api/usercenter/user/send-code', obj, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
/**
* 重置密码验证码确认
* @param {[string]} obj.contact 手机号/邮箱
* @param {[string]} obj.code 验证码
* @param {[string]} obj.service 传当前域名
*/
validateCode = (obj = {}) => this.post('/api/passport/user_center/validate_code', obj, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
/**
* 重置密码
* @param {[string]} obj.contact 手机号/邮箱
* @param {[string]} obj.code 验证码
* @param {[string]} obj.new_password 新的密码
* @param {[string]} obj.service 传当前域名
*/
resetPwd = (obj = {}) => this.post('/api/usercenter/user/update-pwd', obj, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
/**
* 个人信息 - 修改密码
* @param {[string]} obj.old_password 验证码
* @param {[string]} obj.new_password 新的密码
* @param {[string]} obj.service 传当前域名
*/
updatePwd = (obj = {}) => this.post('/api/usercenter/user/change-pwd-by-cookie', obj, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
/**
* 清空所有cookies
*/
clearCookies = (obj = {}) => this.post('https://learn-pbcsf.ezijing.com/api/clear/cookie', obj, { headers: { 'Content-Type': 'multipart/form-data' } })
}
/* 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;
}
@font-face {font-family: "selfAllIcon";
src: url('iconfont.eot?t=1585881159034'); /* IE9 */
src: url('iconfont.eot?t=1585881159034#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'),
url('iconfont.woff?t=1585881159034') format('woff'),
url('iconfont.ttf?t=1585881159034') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
url('iconfont.svg?t=1585881159034#selfAllIcon') format('svg'); /* iOS 4.1- */
}
.selfAllIcon {
font-family: "selfAllIcon" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.el-icon-self-fankuiyijian:before {
content: "\e68f";
}
.el-icon-self-icon-test:before {
content: "\e655";
}
.el-icon-self-shipinjinzhi:before {
content: "\e60b";
}
.el-icon-self-shipinbofang:before {
content: "\e60c";
}
.el-icon-self-tuichu:before {
content: "\e606";
}
.el-icon-self-star_full:before {
content: "\e627";
}
.el-icon-self-wujiaoxing:before {
content: "\e614";
}
.el-icon-self-guanbi:before {
content: "\e611";
}
.el-icon-self-xuexiao:before {
content: "\e632";
}
.el-icon-self-quanping:before {
content: "\e743";
}
.el-icon-self-shipin:before {
content: "\e60e";
}
.el-icon-self-iconset0481:before {
content: "\e768";
}
.el-icon-self-wenjian:before {
content: "\e650";
}
.el-icon-self-PPT:before {
content: "\e602";
}
.el-icon-self-13:before {
content: "\e6ce";
}
.el-icon-self-cc-book:before {
content: "\e615";
}
.el-icon-self-grade:before {
content: "\e66c";
}
.el-icon-self-xuexi-:before {
content: "\e609";
}
.el-icon-self-nav:before {
content: "\e66b";
}
.el-icon-self-mima:before {
content: "\e607";
}
.el-icon-self-character:before {
content: "\e62e";
}
.el-icon-self-statistic:before {
content: "\e601";
}
.el-icon-self-discover:before {
content: "\e67e";
}
.el-icon-self-settings:before {
content: "\e68a";
}
.el-icon-self-new:before {
content: "\e71e";
}
.el-icon-self-album:before {
content: "\e734";
}
{
"id": "948269",
"name": "self-all",
"font_family": "selfAllIcon",
"css_prefix_text": "el-icon-self-",
"description": "所有外包项目,图标库",
"glyphs": [
{
"icon_id": "1546564",
"name": "反馈意见",
"font_class": "fankuiyijian",
"unicode": "e68f",
"unicode_decimal": 59023
},
{
"icon_id": "8777427",
"name": "help",
"font_class": "icon-test",
"unicode": "e655",
"unicode_decimal": 58965
},
{
"icon_id": "11720124",
"name": "视频禁止",
"font_class": "shipinjinzhi",
"unicode": "e60b",
"unicode_decimal": 58891
},
{
"icon_id": "11720125",
"name": "视频播放",
"font_class": "shipinbofang",
"unicode": "e60c",
"unicode_decimal": 58892
},
{
"icon_id": "11717677",
"name": "退出",
"font_class": "tuichu",
"unicode": "e606",
"unicode_decimal": 58886
},
{
"icon_id": "551615",
"name": "五角星",
"font_class": "star_full",
"unicode": "e627",
"unicode_decimal": 58919
},
{
"icon_id": "2681717",
"name": "五角星",
"font_class": "wujiaoxing",
"unicode": "e614",
"unicode_decimal": 58900
},
{
"icon_id": "632985",
"name": "关闭",
"font_class": "guanbi",
"unicode": "e611",
"unicode_decimal": 58897
},
{
"icon_id": "646387",
"name": "刷新",
"font_class": "xuexiao",
"unicode": "e632",
"unicode_decimal": 58930
},
{
"icon_id": "1010014",
"name": "全屏",
"font_class": "quanping",
"unicode": "e743",
"unicode_decimal": 59203
},
{
"icon_id": "2198788",
"name": "视频",
"font_class": "shipin",
"unicode": "e60e",
"unicode_decimal": 58894
},
{
"icon_id": "554517",
"name": "播放",
"font_class": "iconset0481",
"unicode": "e768",
"unicode_decimal": 59240
},
{
"icon_id": "4251768",
"name": "文件",
"font_class": "wenjian",
"unicode": "e650",
"unicode_decimal": 58960
},
{
"icon_id": "5620349",
"name": "PPT",
"font_class": "PPT",
"unicode": "e602",
"unicode_decimal": 58882
},
{
"icon_id": "720044",
"name": "image-o",
"font_class": "13",
"unicode": "e6ce",
"unicode_decimal": 59086
},
{
"icon_id": "372115",
"name": "cc-book",
"font_class": "cc-book",
"unicode": "e615",
"unicode_decimal": 58901
},
{
"icon_id": "938307",
"name": "Grade",
"font_class": "grade",
"unicode": "e66c",
"unicode_decimal": 58988
},
{
"icon_id": "4657687",
"name": "学习",
"font_class": "xuexi-",
"unicode": "e609",
"unicode_decimal": 58889
},
{
"icon_id": "1174321",
"name": "nav",
"font_class": "nav",
"unicode": "e66b",
"unicode_decimal": 58987
},
{
"icon_id": "1418216",
"name": "密码",
"font_class": "mima",
"unicode": "e607",
"unicode_decimal": 58887
},
{
"icon_id": "3090318",
"name": "人物",
"font_class": "character",
"unicode": "e62e",
"unicode_decimal": 58926
},
{
"icon_id": "6918240",
"name": "statistic",
"font_class": "statistic",
"unicode": "e601",
"unicode_decimal": 58881
},
{
"icon_id": "30446",
"name": "discover",
"font_class": "discover",
"unicode": "e67e",
"unicode_decimal": 59006
},
{
"icon_id": "30480",
"name": "settings",
"font_class": "settings",
"unicode": "e68a",
"unicode_decimal": 59018
},
{
"icon_id": "90850",
"name": "new",
"font_class": "new",
"unicode": "e71e",
"unicode_decimal": 59166
},
{
"icon_id": "151470",
"name": "album",
"font_class": "album",
"unicode": "e734",
"unicode_decimal": 59188
}
]
}
{
"LoginModule": {
"CodeLogin": {
"iphone": "Mobile Phone number",
"inputIphone": "Please enter Mobile Phone number",
"rightIphoneStr": "Please enter the right format Mobile Phone number",
"code": "SMS verification code",
"sendCode": "Send code",
"inputCode": "Please enter SMS verification code",
"afterMiniutes": "s before resend",
"isRemember": "Remember Me",
"submitbtn": "Log In"
},
"ForgetLogin": {
"step1": "Step 1",
"step2": "Step 2",
"step3": "Step 3",
"inputStr": "Please enter Register Mobile Phone number Or Mail",
"rightStr": "Please enter the right Format Mobile Phone number Or Mail",
"checkRightStr": "Please check whether the Mobile Phone number or Email",
"sendCode": "Send",
"codeSuccess": "The verification code has been successfully sent. No more then five times every day.",
"codeStr": "Code arrive to :",
"iphoneCode": "Iphone Code",
"mailCode": "Mail Code",
"input4Code": "Input Four Number Code",
"afterMiniutes": "s before resend",
"prev": "Prev",
"next": "Next",
"newPwd": "New Password",
"placeholder": "Please enter 6-20 letters, numbers and punctuation marks, not just numbers",
"repeatNewPwd": "Repeat New Password",
"repeatPlaceholder": "Please repeat enter new password",
"checkPwd": "Input twice is not same",
"finish": "Finish",
"tipStr": "Password set success",
"goLogin": "Log In"
},
"NormalLogin": {
"account": "Account",
"inputAccount": "Please enter Email or UserID",
"password": "Password",
"inputPassword": "Please enter Password",
"isRemember": "Remember Me",
"submitbtn": "Log In"
},
"Others": {
"noSysRole": "You do not have system permissions, please contact the system administrator",
"outloginStr": "The account has been signed out, please change the account",
"formCheckStr": "Please check",
"tip": "Tips",
"right": "Confirm"
}
}
}
import Cookies from 'js-cookie'
import VueI18n from 'vue-i18n'
import language from './language'
import zhCNLocale from 'element-ui/lib/locale/lang/zh-CN'
import enLocale from 'element-ui/lib/locale/lang/en'
export default () => {
let _locale = 'zh-CN'
/* 国际化初始化 */
const _defaultLocale = 'zh-CN'
const _lang = Cookies.get('lang') || window.navigator.language || window.navigator.userLanguage || ''
if (_lang) {
if (language[_lang]) {
_locale = _lang
} else {
let flag = true
/* 做一下 兼容性处理 */
for (const k in language) {
const reg = new RegExp(k, 'gi')
if (reg.test(_lang)) {
_locale = k
flag = false
break
}
}
if (flag) {
/* 当前语言版本 - 不再我们的语言库中,那么默认 en */
_locale = _defaultLocale
Cookies.set('lang', _defaultLocale, { expires: 30, domain: '.ezijing.com' })
}
}
}
return new VueI18n({
locale: _locale, // 定义默认语言为中文
messages: {
'zh-CN': Object.assign(require('./zh-CN.json'), zhCNLocale),
en: Object.assign(require('./en.json'), enLocale)
}
})
}
/* 定义语言模型 - key 值定义 跟 languages i18n 中 保持一致 */
const language = {
'zh-CN': { show: '语言', arr: [{ 'zh-CN': '中文' }, { en: 'English' }] },
en: { show: 'Language', arr: [{ 'zh-CN': '中文' }, { en: 'English' }] }
}
export default language
{
"LoginModule": {
"CodeLogin": {
"iphone": "手机号",
"inputIphone": "请输入手机号",
"rightIphoneStr": "请输入正确格式的手机号",
"code": "短信验证码",
"sendCode": "发送验证码",
"inputCode": "请输入短信验证码",
"afterMiniutes": "s后重发",
"isRemember": "记住我",
"submitbtn": "登录"
},
"ForgetLogin": {
"step1": "步骤1",
"step2": "步骤2",
"step3": "步骤3",
"inputStr": "请输入注册手机号/邮箱",
"rightStr": "请输入正确格式的手机号/邮箱",
"checkRightStr": "请检查手机号或邮箱是否输入正确",
"sendCode": "发送验证码",
"codeSuccess": "验证码已成功发送,请耐心等待。每天最高发送5次",
"codeStr": "验证码已发送至:",
"iphoneCode": "手机验证码",
"mailCode": "邮箱验证码",
"input4Code": "请输入4位验证码",
"afterMiniutes": "s后重发",
"prev": "上一步",
"next": "下一步",
"newPwd": "新密码",
"placeholder": "请输入6-20个字母、数字及标点符号,不可仅数字",
"repeatNewPwd": "重复新密码",
"repeatPlaceholder": "请重新输入新密码",
"checkPwd": "两次输入密码不一致",
"finish": "完成",
"tipStr": "密码设置成功",
"goLogin": "登 录"
},
"NormalLogin": {
"account": "账号",
"inputAccount": "请输入手机号",
"password": "密码",
"inputPassword": "请输入密码",
"isRemember": "记住我",
"submitbtn": "登录"
},
"Others": {
"noSysRole": "您当前没有系统权限,请联络系统管理员",
"outloginStr": "账号已退出,请更换账号",
"formCheckStr": "请根据输入框提示,检查输入项。",
"tip": "提示",
"right": "确定"
}
}
}
import './index.scss'
import NormalLogin from './src/NormalLogin.vue'
import CodeLogin from './src/CodeLogin.vue'
import ForgetLogin from './src/ForgetLogin.vue'
const components = [
NormalLogin,
CodeLogin,
ForgetLogin
]
const install = function (Vue, opts = {}) {
/* 存在国际化 */
if (opts.i18n) {
const msgs = opts.i18n.messages
for (const k in msgs) {
opts.i18n.setLocaleMessage(k, Object.assign(msgs[k], require('./assets/languages/' + k + '.json')))
}
}
components.forEach(component => {
Vue.component(component.name, component)
})
}
/* istanbul ignore if */
if (typeof window !== 'undefined' && window.Vue) {
install(window.Vue)
}
export default {
install,
NormalLogin,
CodeLogin,
ForgetLogin
}
/* Extra small devices (portrait phones, less than 576px) */
@media (max-width: 575px) {}
/* Small devices (landscape phones, 576px and up) */
@media (min-width: 576px) and (max-width: 767px) {}
/* Medium devices (tablets, 768px and up) */
@media (min-width: 768px) and (max-width: 991px) {}
/* Large devices (desktops, 992px and up) */
@media (min-width: 992px) and (max-width: 1199px) {}
/* Extra large devices (large desktops, 1200px and up) */
@media (min-width: 1200px) {}
<template>
<el-form ref="setAccountform" :model="setAccount" :rules="accountRules">
<el-form-item prop="user">
<el-input class="self-input" v-model="setAccount.user" type="text" :placeholder="$t('LoginModule.CodeLogin.iphone')" @keyup.enter.native="onSubmitSetAccount">
</el-input>
</el-form-item>
<el-form-item prop="pwd" style="margin-bottom: 4px;">
<el-input v-model="setAccount.pwd" :disabled="isSendDisable" type="text" :placeholder="$t('LoginModule.CodeLogin.code')" @keyup.enter.native="onSubmitSetAccount">
<el-button slot="suffix" size="mini" :disabled="isSendDisable || isSendCode" @click="sendCode">{{sendBtnText}}</el-button>
</el-input>
</el-form-item>
<el-form-item prop="isRemember" style="margin-bottom: 0px; text-align: left;">
<el-checkbox v-model="setAccount.isRemember" :label="$t('LoginModule.NormalLogin.isRemember')" name="type"></el-checkbox>
</el-form-item>
<el-form-item>
<el-button type="primary" class="login-btn" @click="onSubmitSetAccount">{{$t('LoginModule.CodeLogin.submitbtn')}}</el-button>
</el-form-item>
<slot name="text"></slot>
</el-form>
</template>
<script>
import Login from '../action'
export default {
name: 'CodeLogin',
componentName: 'CodeLogin',
props: {
attr: {
type: Object,
required: false,
default () {
return {}
}
},
query: {
type: Object,
required: false,
default () {
return {}
}
}
},
data () {
/* 账号输入正确时,才能获取验证码 */
const checkAccount = (rule, value, callback) => {
/* 手机格式 */
if (/^1[3-9]\d{9}$/.test(value)) {
this.isSendDisable = false
callback()
} else {
this.isSendDisable = true
callback(new Error(this.$t('LoginModule.CodeLogin.rightIphoneStr')))
}
}
return {
isSendDisable: true, // 是否可以发送
isSendCode: false, // 是否已发送验证码
timeInterval: null, // 定时器,倒计时
sendBtnText: this.$t('LoginModule.CodeLogin.sendCode'), // 按钮 文字
setAccount: {},
accountRules: {
user: [
{ required: true, message: this.$t('LoginModule.CodeLogin.inputIphone'), trigger: 'blur' },
{ validator: checkAccount, trigger: 'change' }
],
pwd: [
{ required: true, message: this.$t('LoginModule.CodeLogin.inputCode'), trigger: 'blur' }
]
}
}
},
beforeDestroy () { /* 清空倒计时 */ this.clearTime() },
methods: {
/* 发送验证码 */
sendCode () {
if (!this.isSendCode) {
// const loading = this.$loading({ lock: true, text: '', spinner: '', background: 'rgba(255, 255, 255, 0.9)' })
Login.sendCode({
/* 老版发送验证码 */
mobile: this.setAccount.user,
/* 新版发送验证码 */
account: this.setAccount.user
}).then(res => {
/* 发送验证码不管是否成功,都开始倒计时 */
let time = 60
this.isSendCode = true
this.sendBtnText = '60' + this.$t('LoginModule.CodeLogin.afterMiniutes')
this.timeInterval = setInterval(() => {
if (time-- > 0) {
this.sendBtnText = time + this.$t('LoginModule.CodeLogin.afterMiniutes')
} else {
this.isSendCode = false
this.sendBtnText = this.$t('LoginModule.CodeLogin.sendCode')
clearInterval(this.timeInterval)
}
}, 1000)
}).catch(error => {
this.$message.error(error.message)
})
}
},
/* 清空倒计时 */
clearTime () {
this.isSendCode = true
this.sendBtnText = this.$t('LoginModule.CodeLogin.sendCode')
clearInterval(this.timeInterval)
},
onSubmitSetAccount () {
this.$refs.setAccountform.validate((valid) => {
if (valid) {
Login.codeLogin({
/* 新版 */
account: this.setAccount.user,
password: this.setAccount.pwd,
type: 2,
RememberMe: this.setAccount.isRemember ? 'true' : 'false',
service: window.location.origin
}).then(data => {
if (data.code !== 0) { return }
if (data.url) {
/* 查询上次跳转信息,并跳转回去 */
if (this.query.rd) {
window.location.href = data.url + decodeURIComponent(this.query.rd)
} else {
window.location.href = data.url
}
} else {
this.$alert(this.$t('LoginModule.Others.noSysRole'), this.$t('LoginModule.Others.tip'), {
confirmButtonText: this.$t('LoginModule.Others.right'),
callback: action => {
Login.outLogin().then(res => {
this.$message({
type: 'info',
message: this.$t('LoginModule.Others.outloginStr')
})
})
}
})
}
}).catch(error => {
this.$message.error(error.message)
})
} else {
this.$message.error(this.$t('LoginModule.Others.formCheckStr'))
return false
}
})
}
}
}
</script>
<style lang="scss" scoped>
.login-btn { margin-top: 0; width: 100%; }
</style>
<template>
<div class="content-s">
<div class="step3">
<el-form ref="form3" label-width="100px" :model="accountSet" :rules="accountRules" label-position="top">
<el-row type="flex" class="row-bg" justify="center">
<el-col :xs="24" :md="10">
<el-form-item prop="account" :label="$t('LoginModule.NormalLogin.account')">
<el-input v-model="accountSet.account" type="text" :placeholder="$t('LoginModule.ForgetLogin.inputStr')"></el-input>
</el-form-item>
<el-form-item prop="code" :label="(accountSet.type ? $t('LoginModule.ForgetLogin.mailCode') : $t('LoginModule.ForgetLogin.iphoneCode'))">
<el-input v-model="accountSet.code" type="text" :placeholder="$t('LoginModule.ForgetLogin.input4Code')">
<el-button slot="append" type="primary" @click="sendCode">{{sendBtnText}}</el-button>
</el-input>
</el-form-item>
<el-form-item prop="newpwd" :label="$t('LoginModule.ForgetLogin.newPwd')">
<el-input v-model="accountSet.newpwd" type="password" :placeholder="$t('LoginModule.ForgetLogin.placeholder')"></el-input>
</el-form-item>
<el-form-item prop="repwd" :label="$t('LoginModule.ForgetLogin.repeatNewPwd')">
<el-input v-model="accountSet.repwd" type="password" :placeholder="$t('LoginModule.ForgetLogin.repeatPlaceholder')"></el-input>
</el-form-item>
<el-form-item>
<el-button style="width: 100%;" type="primary" @click="onSubmitForm">{{$t('LoginModule.ForgetLogin.finish')}}</el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
<slot name="go-back"></slot>
</div>
<el-dialog
title=""
:visible.sync="centerDialogVisible"
width="30%"
center append-to-body>
<i class="el-icon-success" style="display: block; font-size: 0.6rem; text-align: center; color: #67c23a;"></i>
<span style="display: block; margin-top: 0.2rem; text-align: center;">{{$t('LoginModule.ForgetLogin.tipStr')}}</span>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="goLogin">{{$t('LoginModule.ForgetLogin.goLogin')}}</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import Login from '../action'
export default {
name: 'ForgetLogin',
componentName: 'ForgetLogin',
props: {
attr: {
type: Object,
required: false,
default () {
return {}
}
},
query: {
type: Object,
required: false,
default () {
return {}
}
}
},
data () {
/* 检查账号格式 */
const checkAccount = (rule, value, callback) => {
if (!/^(1[3-9]\d{9}|[\w\.]+@\w+(\.\w+)+)$/.test(value)) { // eslint-disable-line
callback(new Error(this.$t('LoginModule.ForgetLogin.rightStr')))
} else {
/* 手机格式 */
if (/^(1[3-9]\d{9}$)/.test(value)) {
this.accountSet.type = 0
}
/* 邮箱格式 */
if (/^([\w\.]+@\w+(\.\w+)+)/.test(value)) { // eslint-disable-line
this.accountSet.type = 1
}
callback()
}
}
/* 检查密码 */
const checkPwd = (rule, value, callback) => {
if (value === this.accountSet.newpwd) {
callback()
} else {
callback(new Error(this.$t('LoginModule.ForgetLogin.checkPwd')))
}
}
return {
isSendCode: false, // 是否已发送验证码
timeInterval: null, // 定时器,倒计时
sendBtnText: this.$t('LoginModule.ForgetLogin.sendCode'), // 按钮 文字
accountSet: {
type: 0, // 0:表示手机格式,1:表示邮箱格式
account: '',
code: ''
},
accountRules: {
account: [
{ required: true, message: this.$t('LoginModule.ForgetLogin.inputStr'), trigger: 'blur' },
{ validator: checkAccount, trigger: 'change' }
],
code: [
{ required: true, message: this.$t('LoginModule.ForgetLogin.input4Code'), trigger: 'blur' },
{ pattern: /^(\d{4})$/, message: this.$t('LoginModule.ForgetLogin.input4Code'), trigger: 'change' }
],
newpwd: [
{ required: true, message: this.$t('LoginModule.ForgetLogin.newPwd'), trigger: 'blur' },
{ pattern: /^.*[^\d]+.*$/, message: this.$t('LoginModule.ForgetLogin.placeholder'), trigger: 'blur' }
],
repwd: [
{ required: true, message: this.$t('LoginModule.ForgetLogin.repeatPlaceholder'), trigger: 'blur' },
{ validator: checkPwd, trigger: 'change' }
]
},
centerDialogVisible: false // 修改密码成功弹框
}
},
beforeDestroy () { /* 清空倒计时 */ this.clearTime() },
methods: {
/* 发送验证码 */
sendCode () {
if (!this.isSendCode) {
Login.sendResetPwdCode({ account: this.accountSet.account }).then(res => {
if (res.code === 0) {
/* 发送验证码不管是否成功,都开始倒计时 */
let time = 60
this.isSendCode = true
this.sendBtnText = '60' + this.$t('LoginModule.ForgetLogin.afterMiniutes')
this.timeInterval = setInterval(() => {
if (time-- > 0) {
this.sendBtnText = time + this.$t('LoginModule.ForgetLogin.afterMiniutes')
} else {
this.isSendCode = false
this.sendBtnText = this.$t('LoginModule.ForgetLogin.sendCode')
clearInterval(this.timeInterval)
}
}, 1000)
this.$message({
type: 'success',
message: this.$t('LoginModule.ForgetLogin.codeSuccess'),
duration: 10000
})
} else {
return new Error(JSON.stringify(res))
}
})
}
},
/* 清空倒计时 */
clearTime () {
this.isSendCode = false
this.sendBtnText = this.$t('LoginModule.ForgetLogin.sendCode')
clearInterval(this.timeInterval)
},
/* 第三步 提交 */
onSubmitForm () {
this.$refs.form3.validate((valid) => {
if (valid) {
Login.resetPwd({
account: this.accountSet.account,
code: this.accountSet.code,
password: this.accountSet.newpwd,
passwordR: this.accountSet.repwd
}).then(data => {
if (data.code === 0) {
this.centerDialogVisible = true
} else {
return new Error(JSON.stringify(data))
}
})
} else {
this.$message.error(this.$t('LoginModule.Others.formCheckStr'))
return false
}
})
},
/**
* 关闭弹框时,跳转 登录页
*/
goLogin () {
this.centerDialogVisible = false
/* 跳转到 登录 */
this.$router.push({ path: '/login/index' })
}
}
}
</script>
<style lang="scss" scoped>
.content-s {
position: absolute;
left: 50%;
top: 22%;
padding: 20px 0;
width: calc(100% - 20px);
max-width: 1000px;
box-shadow: 0px 3px 10px rgba(0, 0, 0, 0.3);
transform: translateX(-50%);
background: #fff;
}
/* forget 登录 */
.step1 { font-size: 16px; width: 90%; margin: 20px auto 0 auto; }
.step2 { font-size: 16px; width: 71%; margin: 20px auto 0 auto; }
.step2 .txt-title { margin-bottom: 0.3rem; color: #999; text-align: center; }
.step2 .operate { margin-top: 0.2rem; }
.step3 { font-size: 16px; margin: 10px 20px 0; text-align: left;}
::v-deep .el-form-item__label{ line-height:1; }
</style>
<template>
<el-form ref="setAccountform" :model="setAccount" :rules="accountRules">
<el-form-item prop="user">
<el-input class="self-input" v-model="setAccount.user" type="text" :placeholder="$t('LoginModule.NormalLogin.account')" @keyup.enter.native="onSubmitSetAccount">
<i slot="prefix" class="el-input__icon el-icon-self-character"></i>
</el-input>
</el-form-item>
<el-form-item prop="pwd" style="margin-bottom: 4px;">
<el-input v-model="setAccount.pwd" type="password" :placeholder="$t('LoginModule.NormalLogin.password')" @keyup.enter.native="onSubmitSetAccount">
<i slot="prefix" class="el-input__icon el-icon-self-mima"></i>
</el-input>
</el-form-item>
<el-form-item prop="isRemember" style="margin-bottom: 0px; text-align: left;">
<el-checkbox v-model="setAccount.isRemember" :label="$t('LoginModule.NormalLogin.isRemember')" name="type"></el-checkbox>
</el-form-item>
<el-form-item>
<el-button type="primary" class="login-btn" @click="onSubmitSetAccount">{{$t('LoginModule.NormalLogin.submitbtn')}}</el-button>
</el-form-item>
<slot name="text"></slot>
</el-form>
</template>
<script>
import Login from '../action'
export default {
name: 'NormalLogin',
componentName: 'NormalLogin',
props: {
attr: {
type: Object,
required: false,
default () {
return {}
}
},
query: {
type: Object,
required: false,
default () {
return {}
}
}
},
data () {
return {
// rememberMe:
setAccount: {},
accountRules: {
user: [
{ required: true, message: this.$t('LoginModule.NormalLogin.inputAccount'), trigger: 'blur' }
// { pattern: /^(1[3-9]\d{9}|[\w\.]+@\w+(\.\w+)+)$/, message: '请输入正确格式的手机号/邮箱', trigger: 'change' } // eslint-disable-line
],
pwd: [
{ required: true, message: this.$t('LoginModule.NormalLogin.inputPassword'), trigger: 'blur' }
]
}
}
},
mounted () {
// Login.clearCookies({}).then(res => res)
},
methods: {
onSubmitSetAccount () {
this.$refs.setAccountform.validate((valid) => {
if (valid) {
Login.userLogin({
/* 老版登录 */
// login_name: this.setAccount.user,
// password: md5('uokoaduw' + this.setAccount.pwd.split('').reverse().join('') + 'auhgniq'),
/* 新版登录 */
account: this.setAccount.user,
password: this.setAccount.pwd,
type: 1,
RememberMe: this.setAccount.isRemember ? 'true' : 'false',
service: window.location.origin
}).then(res => {
if (res.code !== 0) { return }
if (this.attr.url) {
window.location.href = this.attr.url
return
}
if (res.url) {
/* 查询上次跳转信息,并跳转回去 */
if (this.query.rd) {
window.location.href = res.url + decodeURIComponent(this.query.rd)
} else {
window.location.href = res.url
}
} else {
this.$alert(this.$t('LoginModule.Others.noSysRole'), this.$t('LoginModule.Others.tip'), {
confirmButtonText: this.$t('LoginModule.Others.right'),
callback: action => {
Login.outLogin().then(res => {
this.$message({
type: 'info',
message: this.$t('LoginModule.Others.outloginStr')
})
})
}
})
}
/* 重置账号、密码 */
// this.$refs['setAccountform'].resetFields()
}).catch(e => {
this.$message({
type: 'error',
message: e.message
})
})
} else {
this.$message.error(this.$t('LoginModule.Others.formCheckStr'))
return false
}
})
}
}
}
</script>
<style lang="scss" scoped>
.login-btn { margin-top: 0; width: 100%; }
</style>
import BaseAPI from '@/api/base_api'
const httpRequest = new BaseAPI(webConf)
// 获取事务类型列表
export function getAffairType() {
return httpRequest.get('/api/lms/v2/lobby/affairs')
}
// 获取事务列表
export function getAffairList(params) {
return httpRequest.get('/api/lms/v2/lobby/processes', params).then(response => {
const status = {
'-1': '待审批',
0: '未通过',
1: '审批通过',
2: '审批中'
}
if (response.list) {
response.list = response.list.map(item => {
item.status_name = status[item.status]
return item
})
}
return response
})
}
// 获取事务详情
export function getAffair(id) {
return httpRequest.get(`/api/lms/v2/lobby/processes/${id}`)
}
// 创建事务
export function createAffair(data) {
return httpRequest.post('/api/lms/v2/lobby/processes', data)
}
// 更新事务
export function updateAffair(id, data) {
return httpRequest.post(`/api/lms/v2/lobby/processes/${id}`, data)
}
// 删除事务
export function deleteAffair(id) {
return httpRequest.delete(`/api/lms/v2/lobby/processes/${id}`)
}
// 上传文件
export function upload(data) {
return httpRequest.post('/api/lms/v2/lobby/tools/upload', data, {
headers: { 'Content-Type': 'multipart/form-data' }
})
}
// 获取学期
export function getSemesters() {
return httpRequest.get('/api/lms/v2/lobby/semesters')
}
// 获取课程
export function getCourses(sid) {
return httpRequest.get(`/api/lms/v2/lobby/semesters/${sid}/courses`)
}
// 获取成绩单
export function getReport(params) {
return httpRequest.get('/api/lms/v2/lobby/havereport', params)
}
// 获取学生
export function getStudent() {
return httpRequest.get('/api/lms/v2/lobby/student')
}
// 获取重修课程
export function getRetakeCourses() {
return httpRequest.get('/api/lms/v2/lobby/courses')
}
// 更改事务状态
export function changeStatus(data) {
return httpRequest.post('/api/lms/v2/lobby/changestatus', data)
}
// 创建微信支付订单
export function createWxpayOrder(identity, productId, params) {
return httpRequest.get(`/api/pay/v1/wechat/qr/${identity}/${productId}`, params)
}
// 创建支付宝支付订单
export function createAlipayOrder(productId, params) {
return httpRequest.get(`/api/pay/v1/ali/unified-order/${productId}`, params)
}
// 获取订单
export function getOrder(orderId) {
return httpRequest.get(`/api/pay/v1/order/status/${orderId}`)
}
// 支付成功回调
export function paySuccess(id) {
return httpRequest.get(`/api/lms/v2/lobby/update-status-api/${id}`)
}
// 获取学术活动报告列表
export function getAcitivityReportList(id) {
return httpRequest.get(`/api/lms/v2/education/symposium/${id}/report`)
}
// 上传文件
export function uploadFile(data) {
return httpRequest.post('/api/lms/v2/lobby/tools/upload', data, {
headers: { 'Content-Type': 'multipart/form-data' }
})
}
<template>
<div class="pay">
<!-- 微信 -->
<div class="qr-pay" v-if="payment === '2'">
<qrcode-vue :value="qrcodeValue" size="200"></qrcode-vue>
<p class="tips">微信扫一扫支付</p>
</div>
<!-- 支付宝 -->
<div class="qr-pay" v-else-if="payment === '1'">
<qrcode-vue :value="qrcodeValue" size="200"></qrcode-vue>
<p class="tips">支付宝扫一扫支付</p>
</div>
<!-- 银行转账 -->
<div class="bank-pay" v-else>
<p>银行账户名称:清控紫荆(北京)教育科技股份有限公司</p>
<p>银行帐号:694485289</p>
<p>开户行:中国民生银行股份有限公司北京魏公村支行</p>
<div class="is-center">
<el-button type="primary" @click="$emit('success')">我已支付成功,已告知教务老师</el-button>
</div>
</div>
</div>
</template>
<script>
import * as api from '../api'
import QrcodeVue from 'qrcode.vue'
export default {
props: {
payment: { type: String }, // 支付方式
productId: { type: String, required: true }, // 商品ID
num: { type: [Number, String], default: 1 } // 购买数量
},
components: { QrcodeVue },
data() {
return {
order: {}, // 创建订单返回的数据
rawOrder: {}, // 获取订单返回的数据
timer: null
}
},
computed: {
qrcodeValue() {
return this.order.url
}
},
methods: {
// 创建微信订单
createWxPayOrder(productId, num = 1) {
return api.createWxpayOrder('ezijing', productId, { num }).then(response => {
this.order = response
return response
})
},
// 创建支付宝订单
createAliPayOrder(productId, num = 1) {
return api.createAlipayOrder(productId, { type: 2, num }).then(response => {
this.order = response
return response
})
},
getOrder() {
return api.getOrder(this.order.order_no).then(response => {
const { order } = response
this.rawOrder = order
return order
})
},
setTimer() {
this.timer = setInterval(() => {
this.getOrder().then(response => {
// 支付成功
if (response.status === 1) {
this.$emit('success')
this.clearTimer()
}
})
}, 5000)
},
clearTimer() {
this.timer && clearInterval(this.timer)
}
},
mounted() {
if (this.payment === '2') {
// 微信支付
this.createWxPayOrder(this.productId, this.num).then(this.setTimer)
} else if (this.payment === '1') {
// 支付宝支付
this.createAliPayOrder(this.productId, this.num).then(this.setTimer)
}
},
destroyed() {
this.clearTimer()
}
}
</script>
<style lang="scss" scoped>
.qr-pay {
text-align: center;
}
.tips {
color: #999;
}
.bank-pay {
line-height: 30px;
p {
margin: 0;
}
.el-button {
margin-top: 20px;
}
}
.is-center {
text-align: center;
}
</style>
import Offices from './src/index.vue'
import Routes from './routes'
import zhCN from './languages/zh-CN'
import en from './languages/en'
Offices.install = function(Vue, opts = {}) {
// 国际化
if (opts.i18n) {
opts.i18n.mergeLocaleMessage('zh-CN', zhCN)
opts.i18n.mergeLocaleMessage('en', en)
}
// 路由
if (opts.router) {
opts.router.addRoutes(Routes)
}
}
export default Offices
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论