master
yujialong 2 years ago
parent caf1587264
commit 982ec52326
  1. 29559
      public/UEditor/ueditor.all.js
  2. 29564
      public/UEditor/ueditor.all.min.js
  3. 18
      public/UEditor/ueditor.all.min1.js
  4. 2
      public/UEditor/ueditor.config.js
  5. 7
      src/api/index.js
  6. 4
      src/layouts/header/index.vue
  7. 198
      src/layouts/navbar/index.vue
  8. 4
      src/libs/auth/generateBtnPermission.js
  9. 14
      src/libs/route/addRoutes.js
  10. 12
      src/pages/account/login/index.vue
  11. 45
      src/pages/annex/list/index.vue
  12. 123
      src/pages/article/add/index.vue
  13. 63
      src/pages/article/list/index.vue
  14. 65
      src/pages/column/add/index.vue
  15. 17
      src/pages/column/list/index.vue
  16. 263
      src/pages/course/add/index.vue
  17. 888
      src/pages/course/contentSettings/index.vue
  18. 222
      src/pages/course/list/courseManagement/index.vue
  19. 63
      src/pages/course/list/index.vue
  20. 166
      src/pages/course/list/sortManagement/index.vue
  21. 502
      src/pages/course/preview/index.vue
  22. 15
      src/pages/page/list/index.vue
  23. 44
      src/pages/role/list/index.vue
  24. 153
      src/pages/setting/list/index.vue
  25. 1222
      src/pages/setting/list/info.vue
  26. 70
      src/pages/site/list/index.vue
  27. 54
      src/pages/user/list/index.vue
  28. 10
      src/pages/userGroup/list/index.vue
  29. 2
      src/plugins/requests/index.js
  30. 8
      src/setting.js
  31. 33
      src/store/modules/auth.js
  32. 6
      src/store/modules/content.js
  33. 16
      src/store/modules/user.js
  34. 5
      src/styles/common.scss

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -30,7 +30,7 @@
UEDITOR_HOME_URL: URL
// 服务器统一请求接口路径
, serverUrl: URL + "jsp/controller.jsp"
, serverUrl: URL + "iasf/sysFiles/upload"
//工具栏上的所有的功能按钮和下拉框,可以在new编辑器的实例时选择自己需要的重新定义
, toolbars: [[

@ -1,6 +1,6 @@
import Setting from "@/setting";
import Setting from '@/setting'
const host = Setting.apiBaseURL
const host1 = 'http://192.168.31.151:10000/'
const host1 = 'http://192.168.31.136:10000/'
export default {
logins: `iasf/sys/user/login`,
@ -13,6 +13,7 @@ export default {
depts: `iasf/sys/dept/tree`,
users: `iasf/sys/users`,
user: `iasf/sys/user`,
staffTemplate: `http://192.168.31.137:10000/iasf/sysFiles/preview/1559385019981807617`,
checkJobNumber: `iasf/sys/checkJobNumber`,
checkUsername: `iasf/sys/checkUsername`,
resetPwd: `iasf/sys/resetPwd`,
@ -25,6 +26,8 @@ export default {
groupDel: `iasf/sys/userGroup/delete`,
groupList: `iasf/sys/userGroup/list`,
groupUpdate: `iasf/sys/userGroup/update`,
site: `iasf/sys/site/list`,
updateSite: `iasf/sys/site/update`,
listWithTree: `${host1}iasf/sysColumn/listWithTree`,
saveColumn: `${host1}iasf/sysColumn/save`,
updateColumn: `${host1}iasf/sysColumn/update`,

@ -19,7 +19,7 @@
</el-dropdown-menu>
</el-dropdown>
</template>
<img class="cp" src="@/assets/img/notice.png">
<!-- <img class="cp" src="@/assets/img/notice.png"> -->
<el-dropdown class="user-wrap" @command="userCommand">
<div class="user">
<el-avatar :size="24" :src="avatar"></el-avatar>
@ -67,7 +67,6 @@ export default {
},
mounted() {
this.setContent()
// this.getUserDetail()
},
methods: {
...mapActions("user", [
@ -84,6 +83,7 @@ export default {
//
siteCommand(e) {
this.setSite(e)
this.$route.path === '/page/list' || this.$router.push('/page')
location.reload()
},
//

@ -3,7 +3,7 @@
<div v-show="!collapse" class="flex-1">
<div class="logo">
<img src="@/assets/img/logo.png" alt="">
<span>粒子研究院中文站点</span>
<span>网站管理后台</span>
</div>
<el-menu
:default-active="active"
@ -49,7 +49,7 @@
</ul>
</div>
<div class="col-menu">
<div class="name">{{ this.$store.state.content.site.name }}</div>
<div class="name">{{ site.siteName }}</div>
<el-menu
v-if="colRefresh"
:default-active="siteActive"
@ -89,102 +89,93 @@
</template>
<script>
import { mapState, mapActions } from "vuex";
import { mapState, mapActions } from 'vuex'
import Setting from '@/setting'
import addRoutes from '@/libs/route/addRoutes'
export default {
data() {
return {
collapse: false,
active: this.$route.path,
siteActive: '/page',
reloadSite: true,
menus: [
{
icon: 'site',
index: '/site/list',
title: '站点管理'
},
{
icon: 'user',
index: 'user',
title: '用户管理',
subs: [
{
index: '/user/list',
title: '组织与账号管理'
},
{
index: '/role/list',
title: '角色管理'
},
{
index: '/userGroup/list',
title: '用户组管理'
}
]
},
{
icon: 'annex',
index: '/annex/list',
title: '附件管理'
}
],
colNav: [
{
index: '/site/list',
icon: 'site-active'
},
{
index: 'user',
icon: 'user'
},
{
index: '/annex/list',
icon: 'annex'
}
],
sites: [
{
icon: 'content',
index: 'content',
title: '内容管理',
subs: [
{
index: '/page',
title: '页面管理'
},
{
index: '/column',
title: '栏目管理'
},
{
index: '/article',
title: '文章管理'
}
]
}
],
colRefresh: true,
actives: {
dashboard: ["add"],
return {
site: this.$store.state.content.site,
collapse: false,
active: this.$route.path,
siteActive: '/page',
menus: [],
defaultMenus: [
{
icon: 'site',
index: '/site/list',
title: '站点管理'
},
{
icon: 'user',
index: 'user',
title: '用户管理',
subs: [
{
index: '/user/list',
title: '组织与账号管理'
},
{
index: '/role/list',
title: '角色管理'
},
{
index: '/userGroup/list',
title: '用户组管理'
}
]
},
{
icon: 'annex',
index: '/annex/list',
title: '附件管理'
}
],
colNav: [
{
index: '/site/list',
icon: 'site-active'
},
{
index: 'user',
icon: 'user'
},
{
index: '/annex/list',
icon: 'annex'
}
],
sites: [
{
icon: 'content',
index: 'content',
title: '内容管理',
subs: [
{
index: '/page',
title: '页面管理'
},
{
index: '/column',
title: '栏目管理'
},
{
index: '/article',
title: '文章管理'
}
]
}
};
],
colRefresh: true
};
},
computed: {
...mapState('auth', [
'routes'
'btns'
])
},
watch: {
"$route"(to, from) {
let actives = this.actives;
for (let i in this.actives) {
if (actives[i].includes(this.$route.name)) this.active = `/${i}/list`;
}
let arr=this.$route.path.split("/");
let name = `/${arr[1]}/list`
this.active = name
this.active = `/${this.$route.path.split('/')[1]}/list`
const { path } = this.$route
const ori = this.collapse
this.collapse = !!this.sites[0].subs.find(e => path.includes(e.index))
@ -196,13 +187,14 @@ export default {
this.colRefresh = true
})
}
this.site = this.$store.state.content.site
}
},
created() {
const { path } = this.$route
this.collapse = !!this.sites[0].subs.find(e => path.includes(e.index))
if (this.collapse) this.siteActive = '/' + path.split('/')[1]
// this.getPer()
this.initMenu()
},
methods: {
...mapActions('user', [
@ -213,26 +205,30 @@ export default {
this.collapse = false
if (index.includes('/')) {
this.$router.push(index)
} else {
this.active = '/user/list'
this.$router.push('/user/list')
}
},
//
getPer() {
this.$get(`${this.api.getUserRolesPermissionMenu}?platformId=${Setting.platformId}`).then(res => {
const routes = res.permissionMenu[0].children
addRoutes(routes)
this.initMenu()
}).catch(({ status }) => {
status === 500 && this.logout()
})
},
//
initMenu() {
// store
if (Setting.dynamicRoute) {
const { routes } = this
const { btns } = this
const menus = []
this.defaultMenus.map(e => {
routes.find(n => n.path === e.index) && menus.push(e)
});
if (btns.find(n => n.includes(e.index) || n === e.title)) {
//
if (e.subs && e.subs.length) {
const children = []
e.subs.map((j, i) => {
btns.find(n => n.includes(j.index)) && children.push(j)
})
e.subs = children
}
menus.push(e)
}
})
this.menus = menus
} else {
this.menus = this.defaultMenus

@ -8,7 +8,7 @@ const result = []
// 递归组合权限
function createAuth(data, auth) {
data.map(e => {
const text = (auth ? auth + ':' : '') + (auth ? e.name : e.path) // 第一级是路由,取path,子级取name
const text = (auth ? auth + ':' : '') + (auth ? e.name : e.url) // 第一级是路由,取path,子级取name
result.push(text)
e.children && e.children.length && createAuth(e.children, text)
})
@ -16,5 +16,5 @@ function createAuth(data, auth) {
export default function(data) {
createAuth(data)
store.dispatch('auth/addBtnAuth', result)
store.commit('auth/addBtnAuth', result)
}

@ -10,11 +10,11 @@ function createMeta(item) {
function createRoute(data) {
data.map(e => {
const { path } = e
const { url } = e
// 有path则添加到路由里
path && newRoutes.push({
path,
meta: createMeta(e)
url && newRoutes.push({
path: url,
meta: createMeta(e)
})
// 递归生成路由集合
e.children && e.children.length && createRoute(e.children)
@ -22,7 +22,7 @@ function createRoute(data) {
}
export default function(data, path) {
generateBtnPermission(data);
createRoute(data);
store.dispatch("auth/addRoutes", newRoutes);
generateBtnPermission(data)
// createRoute(data)
// store.commit('auth/addRoutes', newRoutes)
}

@ -62,10 +62,11 @@
</template>
<script>
import { mapActions, mapMutations } from 'vuex'
import { mapMutations } from 'vuex'
import vFooter from '@/layouts/footer'
import util from '@/libs/util'
import Setting from '@/setting'
import addRoutes from '@/libs/route/addRoutes'
export default {
data: function() {
return {
@ -103,8 +104,8 @@ export default {
});
},
methods: {
...mapMutations("user", [
'SET_USERID', 'SET_USERNAME'
...mapMutations('user', [
'setUserId', 'setUserName'
]),
getVerImg() { //
this.loginForm.random = Math.floor(Math.random() * 999999999);
@ -120,9 +121,10 @@ export default {
if (valid) {
this.$post(this.api.logins, this.loginForm).then(({ data }) => {
util.local.set(Setting.tokenKey, data.accessToken, Setting.tokenExpires)
addRoutes(data.permissionList[0].children)
util.successMsg('登录成功')
this.SET_USERID(data.id)
this.SET_USERNAME(data.username)
this.setUserId(data.id)
this.setUserName(data.username)
this.$router.push('/site')
}).catch(res => {
this.getVerImg()

@ -9,8 +9,8 @@
<el-option
v-for="item in sites"
:key="item.id"
:label="item.name"
:value="item.id">
:label="item.siteName"
:value="item.siteName">
</el-option>
</el-select>
</li>
@ -37,7 +37,7 @@
:value="item.id">
</el-option>
</el-select>
<el-input class="keyword" placeholder="请输入文章名称" v-model.trim="keyword" clearable></el-input>
<el-input class="keyword" :placeholder="'请输入' + keywords.find(e => e.id === field).name" v-model.trim="keyword" clearable></el-input>
</div>
<div class="actions">
<el-button @click="batchDel">删除</el-button>
@ -47,12 +47,13 @@
<el-table ref="table" :data="list" class="table" header-align="center" @selection-change="handleSelectionChange" row-key="id">
<el-table-column type="selection" width="50" align="center" :reserve-selection="true" :selectable="row => !row.quote"></el-table-column>
<el-table-column type="index" width="60" label="ID"></el-table-column>
<el-table-column prop="site" label="站点名称" min-width="180"></el-table-column>
<el-table-column prop="type" label="文件类型" min-width="100"></el-table-column>
<el-table-column prop="format" label="格式" min-width="100"></el-table-column>
<el-table-column prop="fileSize" label="大小" min-width="100">
<el-table-column prop="site" label="站点" min-width="180"></el-table-column>
<el-table-column prop="fileName" label="名称" min-width="180"></el-table-column>
<el-table-column prop="type" label="文件类型" min-width="80"></el-table-column>
<el-table-column prop="format" label="格式" min-width="80"></el-table-column>
<el-table-column prop="fileSize" label="大小" min-width="80">
<template slot-scope="scope">
{{ scope.row.fileSize }}kb
{{ (scope.row.fileSize / 1000).toFixed(2) }}kb
</template>
</el-table-column>
<el-table-column prop="createDate" label="上传时间" min-width="150"></el-table-column>
@ -63,10 +64,11 @@
{{ scope.row.quote ? '是' : '否' }}
</template>
</el-table-column>
<el-table-column label="操作" width="170">
<el-table-column label="操作" width="150">
<template slot-scope="scope">
<el-button type="text" :disabled="scope.row.quote !== ''" @click="del(scope.row)">删除</el-button>
<el-button type="text" @click="download(scope.row, 'edit')">下载</el-button>
<el-button type="text" @click="show(scope.row, 'edit')">查看</el-button>
<el-button v-auth type="text" :disabled="scope.row.quote !== ''" @click="del(scope.row)">删除</el-button>
<el-button v-auth type="text" @click="download(scope.row)">下载</el-button>
</template>
</el-table-column>
</el-table>
@ -78,11 +80,10 @@
<script>
import util from '@/libs/util'
import ColumnConst from '@/const/column'
export default {
data() {
return {
sites: ColumnConst.sites,
sites: [],
types: [
{
name: '不限'
@ -133,12 +134,13 @@ export default {
}
},
mounted() {
this.$store.commit('user/SET_CRUMBS', [
this.$store.commit('user/setCrumbs', [
{
name: '附件管理'
}
])
this.getData()
this.getSite()
},
methods: {
getData() {
@ -156,11 +158,26 @@ export default {
this.total = +data.total
}).catch(err => {})
},
//
getSite() {
this.$post(this.api.site, {
page: 1,
limit: 1000,
siteName: ''
}).then(({ data }) => {
this.sites = data.records
}).catch(e => {})
},
initData() {
this.$refs.table.clearSelection()
this.page = 1
this.getData()
},
//
show(row) {
const format = row.format
window.open((util.isDoc(format) ? 'https://view.officeapps.live.com/op/view.aspx?src=' : '') + row.url)
},
//
download(row) {
util.downloadFile(row.fileName, row.url)

@ -1,6 +1,6 @@
<template>
<div class="page">
<p class="page-name mb">新增栏目</p>
<p class="page-name mb">{{ }}栏目</p>
<el-form :model="form" :rules="rules" class="input-form model" label-width="140px">
<el-form-item prop="title" label="标题">
<el-input
@ -73,7 +73,7 @@
:action="this.api.upload"
:data="{
quote: form.title,
site: '粒子研究院中文站点',
site: site.siteName,
uploader: userName
}"
>
@ -97,22 +97,30 @@
:action="this.api.upload"
:data="{
quote: form.title,
site: '粒子研究院中文站点',
site: site.siteName,
uploader: userName
}"
>
<img v-if="form.bannerImg" :src="form.bannerImg" class="avatar">
<img v-if="form.bannerImg" :src="form.bannerImg" class="avatar-lg">
<div class="uploader-default" v-else>
<img class="plus" src="@/assets/img/plus.png" alt="">
<p>点击上传</p>
</div>
</el-upload>
</el-form-item>
<el-form-item class="lg" prop="articleTemplate" label="独立文章模板">
<el-tooltip effect="dark" content="支持导入其它数据用于实验,总上传的文件大小不可以超过10M" placement="bottom">
<img class="info" src="@/assets/img/ques.png" alt="">
</el-tooltip>
<ul class="styles">
<el-form-item class="lg" prop="articleTemplate" label="文章模板">
<el-popover
placement="top-start"
trigger="hover"
content="默认使用栏目中设置的文章样式,如果需要为该篇文章指定专门的模板样式,可以设置此项">
<img slot="reference" class="info" src="@/assets/img/ques.png" alt="">
</el-popover>
<el-switch
v-model="form.useArticleTemplate"
:active-value="1"
:inactive-value="0">
</el-switch>
<ul v-if="form.useArticleTemplate" class="styles">
<li>
<div class="review">
<img src="@/assets/img/article2.png" alt="">
@ -139,17 +147,16 @@
</el-form-item>
<el-form-item prop="file" label="文件上传">
<el-upload
accept=".jpg,.png,.jpeg,.gif"
:on-remove="handleRemove"
:on-error="uploadError"
:on-success="uploadSuccessFile"
:limit="1"
:on-exceed="handleExceed"
:show-file-list="false"
:action="this.api.upload"
:file-list="fileList"
:data="{
quote: form.columnName,
site: '粒子研究院中文站点',
quote: form.title,
site: site.siteName,
uploader: userName
}"
>
@ -210,7 +217,7 @@
<div class="btns">
<el-button type="primary" @click="submit(1)">发布</el-button>
<el-button @click="preview">预览</el-button>
<el-button v-if="!form.id" @click="submit(0)">保存草稿</el-button>
<el-button @click="submit(0)">保存草稿</el-button>
<el-button @click="$router.back()">取消</el-button>
</div>
</div>
@ -223,7 +230,7 @@ import VueUeditorWrap from 'vue-ueditor-wrap'
export default {
data() {
return {
siteId: this.$store.state.content.site.id,
site: this.$store.state.content.site,
headers: {},
nameRepeat: false,
types: ColumnConst.types,
@ -241,7 +248,8 @@ export default {
id: this.$route.query.id || '',
founderId: +this.$store.state.user.userId,
editorId: +this.$store.state.user.userId,
articleTemplate: '',
useArticleTemplate: 0,
articleTemplate: this.$route.query.columnId ? this.$store.state.content.column.detailStyle : '',
author: '',
bannerImg: '',
columnId: +this.$route.query.columnId,
@ -270,11 +278,14 @@ export default {
mainBody: [
{ required: true, message: '请输入正文', trigger: 'blur' }
],
connectionType: [
{ required: true, message: '请选择连接类型', trigger: 'blur' }
],
},
editorConfig: {
UEDITOR_HOME_URL: '/UEditor/',
initialFrameHeight: 200,
serverUrl: 'http://192.168.31.137:10000/iasf/sysFiles/upload/' //
serverUrl: 'http://192.168.31.137:10000/iasf/sysFiles/upload' //
},
submiting: false, //
updateTime: 0
@ -289,7 +300,7 @@ export default {
VueUeditorWrap
},
mounted() {
this.$store.commit('user/SET_CRUMBS', [
this.$store.commit('user/setCrumbs', [
{
name: '站点管理',
route: '/site'
@ -309,36 +320,62 @@ export default {
this.form.id && this.getData()
},
watch: {
// ,
form: {
handler(val){
this.updateTime++
},
deep:true
// ,
form: {
handler(val){
this.updateTime++
},
deep:true
}
},
methods: {
//
getList() {
this.$post(this.api.listWithTree, {
siteId: this.siteId,
siteId: this.site.id,
columnName: '',
templateId: '',
typeId : '',
}).then(({ data }) => {
this.columns = data
this.$nextTick(() => {
// this.$refs.column.setCheckedKeys(data[0].id)
console.log("🚀 ~ file: index.vue ~ line 309 ~ this.$nextTick ~ his.$refs.column", this.$refs.column.setCheckedKeys)
})
let { columnId } = this.$route.query
// idid
if (columnId && data.length) {
columnId = +columnId
let ids = []
// id
const getId = (list, parentId) => {
for (const i in list) {
const e = list[i]
if (e.id === columnId) {
ids = [...parentId, list[i].id]
break
} else {
getId(e.children, [...parentId, e.id])
}
}
}
getId(data, [])
if (!ids.length) ids = [data[0].id] // id
this.form.columnId = ids
}
}).catch(err => {})
},
// id
getId(list, ids) {
list.forEach(e => {
e.ids = ids ? [...ids, e.id] : [e.id]
e.children.length ? this.getId(e.children, e.ids) : delete e.children
})
},
//
getData() {
this.$post(`${this.api.findArticle}?id=${this.form.id}`).then(({ data }) => {
this.form = data
if (data.articleTemplate === 3 && data.connectionType !== 2 && data.linkAddress) this.links = data.linkAddress.split(',').map(e => +e)
this.originalName = data.title
const { file } = data
if (file) this.fileList = [{name: file, url: file}]
}).catch(err => {})
},
//
@ -346,7 +383,7 @@ export default {
const { title, level, id } = this.form
if(title && title !== this.originalName){
this.$post(this.api.checkIfTheTitleIsRepeat, {
siteId: this.siteId,
siteId: this.site.id,
title,
id: id || ''
}).then(res => {
@ -357,10 +394,6 @@ export default {
}else{
this.nameRepeat = false
}
},
//
typeChange(val) {
},
//
beforeUpload(file) {
@ -389,16 +422,16 @@ export default {
util.errorMsg(`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`);
},
handleRemove(file, fileList) {
this.form.columnBanner = ''
this.form.file = ''
},
uploadSuccess(res) {
this.form.titleImg = res.data.url
this.form.titleImg = res.url
},
uploadSuccessBanner(res) {
this.form.bannerImg = res.data.url
this.form.bannerImg = res.url
},
uploadSuccessFile(res) {
this.form.file = res.data.url
this.form.file = res.url
},
//
preview() {
@ -414,24 +447,27 @@ export default {
if (typeof form.fatherId === 'object') form.fatherId = form.fatherId[form.fatherId.length - 1]
if (form.articleTemplate === 3 && form.connectionType !== 2) {
const { links } = this
if (!links.length && form.connectionType === 1) return util.errorMsg('请选择站内链接')
if (!links.length && form.connectionType === 3) return util.errorMsg('请选择栏目')
if (!links.length && form.connectionType === 1 && isRelease) return util.errorMsg('请选择站内链接')
if (!links.length && form.connectionType === 3 && isRelease) return util.errorMsg('请选择栏目')
form.linkAddress = links.join()
}
if (form.articleTemplate !== 3 && !form.mainBody && isRelease) return util.errorMsg('请输入正文')
const { columnId } = form
if (typeof columnId === 'object') form.columnId = columnId[columnId.length - 1]
form.isRelease = isRelease
this.submiting = true
if (form.id) {
delete form.children
form.editorId = +this.$store.state.user.userId
this.$post(this.api.updateArticle, form).then(res => {
util.successMsg("修改成功")
util.successMsg('修改成功')
this.$router.back()
}).catch(err => {
this.submiting = false
})
} else {
this.$post(this.api.saveArticle, form).then(res => {
util.successMsg("创建成功")
util.successMsg('创建成功')
this.$router.back()
}).catch(err => {
this.submiting = false
@ -528,7 +564,8 @@ $upload-lg-height: 102px;
}
}
.styles {
display: inline-flex;
display: flex;
margin-top: 20px;
li {
margin-right: 20px;
text-align: center;

@ -33,30 +33,35 @@
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-button type="primary" @click="add" >新增</el-button>
<el-button @click="batchDel">删除</el-button>
<el-button v-auth="'/site/list:' + siteName + ':内容管理:文章管理:新增'" type="primary" @click="add" >新增</el-button>
<el-button v-auth="'/site/list:' + siteName + ':内容管理:文章管理:删除'" @click="batchDel">删除</el-button>
</div>
</div>
<el-table :data="list" class="table" ref="table" header-align="center" @selection-change="handleSelectionChange" row-key="id">
<el-table-column v-if="settings[0].show" type="selection" width="55" align="center" :reserve-selection="true"></el-table-column>
<el-table-column type="index" width="60" label="序号" align="center"></el-table-column>
<el-table-column v-if="settings[1].show" prop="title" label="标题" align="center" min-width="100"></el-table-column>
<el-table-column v-if="settings[2].show" prop="columnName" label="栏目" align="center" min-width="100"></el-table-column>
<el-table-column v-if="settings[3].show" prop="founderName" label="录入人" align="center" min-width="80"></el-table-column>
<el-table-column v-if="settings[4].show" prop="editorName" label="修改人" align="center" min-width="80"></el-table-column>
<el-table-column v-if="settings[5].show" prop="updateTime" label="修改日期" align="center" min-width="110"></el-table-column>
<el-table-column v-if="settings[6].show" prop="releaseTime" label="发布日期" align="center" min-width="110"></el-table-column>
<el-table-column v-if="settings[7].show" prop="totalBrowsing" label="总浏览" align="center" min-width="80"></el-table-column>
<el-table-column v-if="settings[8].show" prop="workNumber" label="状态" align="center" min-width="100">
<el-table-column v-if="settings[1].show" prop="title" label="标题" align="center" min-width="150"></el-table-column>
<el-table-column v-if="settings[2].show" prop="columnName" label="栏目" align="center" min-width="120"></el-table-column>
<el-table-column v-if="settings[3].show" prop="typeId" label="栏目类型" align="center" min-width="100">
<template slot-scope="scope">
{{ types.find(e => e.id === scope.row.typeId).name }}
</template>
</el-table-column>
<el-table-column v-if="settings[4].show" prop="founderName" label="录入人" align="center" min-width="80"></el-table-column>
<el-table-column v-if="settings[5].show" prop="editorName" label="修改人" align="center" min-width="80"></el-table-column>
<el-table-column v-if="settings[6].show" prop="updateTime" label="修改日期" align="center" min-width="120"></el-table-column>
<el-table-column v-if="settings[7].show" prop="releaseTime" label="发布日期" align="center" min-width="120"></el-table-column>
<el-table-column v-if="settings[8].show" prop="totalBrowsing" label="总浏览" align="center" min-width="80"></el-table-column>
<el-table-column v-if="settings[9].show" prop="workNumber" label="状态" align="center" min-width="80">
<template slot-scope="scope">
{{ scope.row.isRelease ? '已发布' : '草稿' }}
</template>
</el-table-column>
<el-table-column v-if="settings[9].show" label="操作" align="center" width="300">
<el-table-column v-if="settings[10].show" label="操作" align="center" width="140">
<template slot-scope="scope">
<el-button v-auth type="text" @click="resetPassword(scope.row)">预览</el-button>
<el-button v-auth type="text" @click="edit(scope.row)">编辑</el-button>
<el-button v-auth type="text" @click="handleDelete(scope.row)">删除</el-button>
<el-button v-auth="'/site/list:' + siteName + ':内容管理:文章管理:预览'" type="text" @click="resetPassword(scope.row)">预览</el-button>
<el-button v-auth="'/site/list:' + siteName + ':内容管理:文章管理:编辑'" type="text" @click="edit(scope.row)">编辑</el-button>
<el-button v-auth="'/site/list:' + siteName + ':内容管理:文章管理:删除'" type="text" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
@ -69,9 +74,13 @@
<script>
import util from '@/libs/util'
import { mapMutations } from 'vuex'
import ColumnConst from '@/const/column'
export default {
data() {
return {
types: ColumnConst.types,
siteName: this.$store.state.content.site.siteName,
columns: [],
defaultProps: {
value: 'id',
@ -116,17 +125,21 @@ export default {
name: '栏目',
show: true
},
{
name: '栏目类型',
show: true
},
{
name: '录入人',
show: false
show: true
},
{
name: '修改人',
show: false
show: true
},
{
name: '修改日期',
show: false
show: true
},
{
name: '发布日期',
@ -134,7 +147,7 @@ export default {
},
{
name: '总浏览',
show: false
show: true
},
{
name: '状态',
@ -156,7 +169,7 @@ export default {
}
},
mounted() {
this.$store.commit('user/SET_CRUMBS', [
this.$store.commit('user/setCrumbs', [
{
name: '站点管理',
route: '/site'
@ -172,6 +185,9 @@ export default {
this.getColumn()
},
methods: {
...mapMutations('content', [
'setColumn'
]),
//
getColumn() {
this.$post(this.api.listWithTree, {
@ -182,16 +198,18 @@ export default {
}).then(({ data }) => {
this.columns = data
this.$nextTick(() => {
this.$refs.column.setCurrentKey(data[0].id)
this.$refs.column.setCurrentKey(this.$route.query.columnId || data[0].id)
this.getData()
})
}).catch(e => {})
},
//
getData() {
const id = this.$refs.column.getCurrentKey()
this.$router.push(`/article?columnId=${id}`).catch(e => {})
this.$post(this.api.queryArticle, {
siteId: this.$store.state.content.site.id,
columnIds: [this.$refs.column.getCurrentKey()],
columnIds: [id],
pageNum: this.page,
pageSize: this.pageSize,
title: this.keyword
@ -257,6 +275,9 @@ export default {
},
//
add() {
if (!this.columns.length) return util.errorMsg('请添加栏目')
this.setColumn(this.$refs.column.getCurrentNode())
console.log("🚀 ~ file: index.vue ~ line 267 ~ add ~ this.$refs.column.getCurrentNode()", this.$refs.column.getCurrentNode())
this.$router.push(`add?columnId=${this.$refs.column.getCurrentKey()}`)
},
//

@ -58,11 +58,11 @@
:action="this.api.upload"
:data="{
quote: form.columnName,
site: '粒子研究院中文站点',
site: site.siteName,
uploader: userName
}"
>
<img v-if="form.columnBanner" :src="form.columnBanner" class="avatar">
<img v-if="form.columnBanner" :src="form.columnBanner" class="avatar-lg">
<div class="uploader-default" v-else>
<img class="plus" src="@/assets/img/plus.png" alt="">
<p>点击上传</p>
@ -155,15 +155,16 @@
<el-option
v-for="item in sites"
:key="item.id"
:label="item.name"
:label="item.siteName"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="栏目">
<el-cascader
:options="links"
:props="{ checkStrictly: true }"
v-model="otherLink"
:options="columns"
:props="columnProps"
clearable></el-cascader>
</el-form-item>
</template>
@ -230,12 +231,12 @@ import { mapState } from 'vuex'
export default {
data() {
return {
siteId: this.$store.state.content.site.id,
site: this.$store.state.content.site,
isEdit: this.$route.query.type === 'edit',
nameRepeat: false,
types: ColumnConst.types,
templates: ColumnConst.templates,
sites: ColumnConst.sites,
sites: [],
columns: [],
columnProps: {
checkStrictly: true,
@ -243,6 +244,7 @@ export default {
label: 'columnName'
},
links: [],
otherLink: [],
form: {
siteId: this.$store.state.content.site.id,
id: this.$route.query.id || '',
@ -299,7 +301,7 @@ export default {
])
},
mounted() {
this.$store.commit('user/SET_CRUMBS', [
this.$store.commit('user/setCrumbs', [
{
name: '站点管理',
route: '/site'
@ -316,7 +318,7 @@ export default {
}
])
this.getList()
this.isEdit && this.getData()
this.getSite()
},
watch: {
// ,
@ -331,30 +333,50 @@ export default {
//
getList() {
this.$post(this.api.listWithTree, {
siteId: this.siteId,
siteId: this.site.id,
columnName: '',
templateId: '',
typeId : '',
}).then(({ data }) => {
this.columns = data
this.isEdit && this.getData()
}).catch(err => {})
},
//
getData() {
this.$post(`${this.api.findColumn}?id=${this.form.id}`).then(({ data }) => {
this.form = data
if (data.typeId === 2) {
let link = data.linkAddress
if (link) {
link = link.split(',').map(e => +e)
if (data.connectionType === 1) {
this.links = link
this.form.linkAddress = ''
} else if (data.connectionType === 3) {
this.otherLink = link
this.form.linkAddress = ''
}
}
}
}).catch(err => {})
},
//
setFatherId() {
//
getSite() {
this.$post(this.api.site, {
page: 1,
limit: 1000,
siteName: ''
}).then(({ data }) => {
this.sites = data.records
}).catch(e => {})
},
//
nameChange(){
const { columnName, level, id } = this.form
if (columnName && columnName !== this.originalName) {
this.$post(this.api.sameLevelJudgment, {
siteId: this.siteId,
siteId: this.site.id,
columnName,
level: +level,
id: +id || ''
@ -398,7 +420,7 @@ export default {
this.form.columnBanner = ''
},
uploadSuccess(res) {
this.form.columnBanner = res.data.url
this.form.columnBanner = res.url
},
//
preview() {
@ -413,10 +435,15 @@ export default {
if (!form.pageSize) return util.errorMsg('请填写分页条数')
if (typeof form.fatherId === 'object') form.fatherId = form.fatherId[form.fatherId.length - 1]
if (form.typeId === 2 && form.connectionType !== 2) {
const { links } = this
if (!links.length && form.connectionType === 1) return util.errorMsg('请选择站内链接')
if (!links.length && form.connectionType === 3) return util.errorMsg('请选择栏目')
form.linkAddress = links.join()
const { links, otherLink } = this
if (form.connectionType === 1) {
if (!links.length) return util.errorMsg('请选择站内链接')
form.linkAddress = links.join()
}
if (form.connectionType === 3) {
if (!otherLink.length) return util.errorMsg('请选择栏目')
form.linkAddress = otherLink.join()
}
}
this.submiting = true
if (this.isEdit) {

@ -18,10 +18,10 @@
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-button type="primary" @click="add" >新增</el-button>
<el-button @click="batchDel">删除</el-button>
<el-button class="lg" @click="sort">更改排序</el-button>
<el-button class="lg" @click="styleSet">导航样式设置</el-button>
<el-button v-auth="'/site/list:' + siteName + ':内容管理:栏目管理:新增'" type="primary" @click="add" >新增</el-button>
<el-button v-auth="'/site/list:' + siteName + ':内容管理:栏目管理:删除'" @click="batchDel">删除</el-button>
<el-button v-auth="'/site/list:' + siteName + ':内容管理:栏目管理:更改排序'" class="lg" @click="sort">更改排序</el-button>
<el-button v-auth="'/site/list:' + siteName + ':内容管理:栏目管理:导航样式设置'" class="lg" @click="styleSet">导航样式设置</el-button>
</div>
</div>
@ -49,9 +49,9 @@
<el-table-column v-if="settings[6].show" prop="id" label="ID" min-width="80"></el-table-column>
<el-table-column v-if="settings[7].show" label="操作" width="170">
<template slot-scope="scope">
<el-button type="text" @click="edit(scope.row, 'add')">新增下级</el-button>
<el-button type="text" @click="edit(scope.row, 'edit')">编辑</el-button>
<el-button type="text" @click="del(scope.row)">删除</el-button>
<el-button v-auth="'/site/list:' + siteName + ':内容管理:栏目管理:新增'" type="text" @click="edit(scope.row, 'add')">新增下级</el-button>
<el-button v-auth="'/site/list:' + siteName + ':内容管理:栏目管理:编辑'" type="text" @click="edit(scope.row, 'edit')">编辑</el-button>
<el-button v-auth="'/site/list:' + siteName + ':内容管理:栏目管理:删除'" type="text" @click="del(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
@ -99,6 +99,7 @@ import util from "@/libs/util";
export default {
data() {
return {
siteName: this.$store.state.content.site.siteName,
types: ColumnConst.types,
templates: ColumnConst.templates,
keyword: '',
@ -166,7 +167,7 @@ export default {
}
},
mounted() {
this.$store.commit('user/SET_CRUMBS', [
this.$store.commit('user/setCrumbs', [
{
name: '站点管理',
route: '/site'

@ -1,263 +0,0 @@
<template>
<div>
<el-card shadow="hover" class="m-b-20">
<div class="flex-between">
<el-page-header @back="back" :content="form.id ? '编辑课程' : '新增课程'"></el-page-header>
</div>
</el-card>
<el-card shadow="hover" class="m-b-20">
<el-form :disabled="isDetail" label-width="80px" label-suffix=":">
<el-form-item label="课程名称">
<div class="d-inline-block">
<el-input placeholder="请输入课程名称" v-model="form.name" clearable maxlength="25"></el-input>
</div>
</el-form-item>
<el-form-item label="课程分类">
<div class="d-inline-block">
<el-select v-model="form.classificationId" placeholder="请选择课程分类">
<el-option v-for="item in classificationList" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</div>
</el-form-item>
<el-form-item label="课程封面">
<el-upload
class="avatar-uploader"
accept=".jpg,.png,.jpeg"
:on-remove="handleRemove"
:on-error="uploadError"
:on-success="uploadSuccess"
:before-remove="beforeRemove"
:limit="1"
:on-exceed="handleExceed"
:action="this.api.fileupload"
:headers="headers"
name="file"
>
<img v-if="form.coverUrl" :src="form.coverUrl" class="avatar">
<div class="uploader-default" v-else>
<i class="el-icon-plus"></i>
<p>上传封面</p>
</div>
<div slot="tip" class="el-upload__tip">
<p>只能上传jpg/png文件</p>
<p>课程封面图将按2:1显示最佳分辨率1400*700</p>
</div>
</el-upload>
</el-form-item>
<el-form-item label="课程介绍">
<quill :border="true" :readonly="isDetail" v-model="form.description" :height="400" />
</el-form-item>
<el-form-item>
<el-button type="primary" v-throttle @click="save" v-show="!isDetail">{{ form.id ? "更新" : "创建" }}</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</template>
<script>
import util from "@/libs/util";
import Setting from "@/setting";
import quill from "@/components/quill";
export default {
name: "courseAddEdit",
data() {
return {
headers: {
token: util.local.get(Setting.tokenKey)
},
isDetail: Boolean(this.$route.query.show),
form: {
id: this.$route.query.id,
classificationId: '',
coverUrl: '',
name: '',
description: '',
distinguish: 1
},
classificationList: [],
uploadList: [],
submiting: false,
updateTime: 0
};
},
watch: {
// ,
form: {
handler(val){
this.updateTime++
},
deep:true
}
},
mounted() {
this.getClassification();
this.form.id && this.getData();
},
components: {
quill
},
methods: {
getClassification() {
this.$get(this.api.queryGlClassification).then(res => {
this.classificationList = res.classificationList;
}).catch(res => {});
},
getData() {
this.$get(`${this.api.getCourse}/${this.form.id}`).then(({ course }) => {
this.form = course
this.uploadList.push({
name: "cover.jpg",
url: course.coverUrl
})
}).catch(err => {})
},
handleExceed(files, fileList) { //
util.warningMsg("当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!");
},
uploadSuccess(res, file, fileList) {
this.form.coverUrl = res.data.filesResult.fileUrl
},
uploadError(err, file, fileList) {
this.$message({
message: "上传出错,请重试!",
type: "error",
center: true
});
},
beforeRemove(file, fileList) {
return this.$confirm(`确定移除 ${file.name}`);
},
handleRemove(file, fileList) {
let fileName = this.form.coverUrl.replace('https://huoran.oss-cn-shenzhen.aliyuncs.com/', "");
this.$del(`${this.api.fileDeletion}?keys=${fileName}`).then(res => {
this.form.coverUrl = ''
}).catch(res => {});
},
save() {
if (this.submiting) return false
const { form } = this
if (!form.name) return util.warningMsg("请填写课程名称")
if (!form.classificationId) return util.warningMsg("请选择课程分类")
if (!form.coverUrl) return util.warningMsg("请上传课程封面")
this.submiting = true
if (form.id) {
this.$put(this.api.editCourse, form).then(res => {
this.submiting = false;
util.successMsg("修改成功");
this.$router.back();
}).catch(err => {
this.submiting = false;
});
} else {
this.$post(this.api.addCourse, form).then(res => {
this.submiting = false;
this.$confirm("课程创建成功,是否马上进行课程内容设置?", "提示", {
type: "success",
confirmButtonText: "马上设置",
cancelButtonText: "稍后操作"
}).then(() => {
this.$router.push(`/course/contentSettings?id=${res.courseId}`);
}).catch(() => {
this.$router.back();
});
}).catch(err => {
this.submiting = false;
});
}
},
//
backPage() {
this.$router.back()
},
back() {
const { id } = this.form
const updateTime = this.updateTime
//
if ((id && updateTime > 2) || (!id && updateTime)) {
this.$confirm(`编辑的内容未保存,是否保存?`, '提示', {
type: 'warning'
}).then(() => {
this.save()
}).catch(() => {
this.backPage()
})
} else {
this.backPage()
}
}
}
};
</script>
<style lang="scss" scoped>
$avatar-width: 104px;
/deep/ .avatar-uploader {
.el-upload {
position: relative;
width: $avatar-width;
border: 1px dashed #d9d9d9;
border-radius: 2px;
cursor: pointer;
overflow: hidden;
&:hover {
border-color: #409EFF;
}
.uploader-default {
display: flex;
flex-direction: column;
justify-content: center;
width: $avatar-width !important;
height: $avatar-width;
text-align: center;
background: rgba(0, 0, 0, 0.04);
i {
font-size: 20px;
font-weight: bold;
color: #8c939d;
}
p {
margin-top: 10px;
font-size: 14px;
color: rgba(0, 0, 0, 0.65);
line-height: 1;
}
}
.avatar {
width: $avatar-width;
height: $avatar-width;
display: block;
}
}
.el-upload__tip {
margin-top: 0;
p {
font-size: 14px;
color: rgba(0, 0, 0, 0.45);
line-height: 1;
&:first-child {
margin-bottom: 5px;
}
}
}
}
/deep/ .d-inline-block {
width: 216px;
.el-select, .el-input {
width: 100%;
}
}
</style>

@ -1,888 +0,0 @@
<template>
<div>
<el-card shadow="hover" class="m-b-20">
<div class="flex-between">
<el-page-header @back="goBack" :content="sorting? '更改排序' : '内容设置'"></el-page-header>
</div>
</el-card>
<!--内容设置-->
<el-card shadow="hover" class="m-b-20">
<div class="page">
<div class="relative">
<div class="p-title">内容设置</div>
<div class="btns" style="top: -10px">
<template v-if="!sorting">
<el-button v-auth="'/course/list:课程管理:内容设置:添加章节'" type="primary" round v-throttle @click="addChapter">添加章节</el-button>
<el-button v-auth="'/course/list:课程管理:内容设置:编辑顺序'" type="primary" round v-throttle @click="sort">编辑顺序</el-button>
</template>
<template v-else>
<el-button type="primary" round @click="move">批量移动</el-button>
<el-button type="primary" round v-throttle @click="cancelSort">取消</el-button>
<el-button type="primary" round v-throttle @click="saveSort">保存</el-button>
</template>
</div>
</div>
<el-divider></el-divider>
<div class="page-content">
<div class="m-b-20" v-for="(chapter,index) in chapters" :key="chapter.id">
<div class="flex j-between a-center m-b-10">
<div>{{ chapter.name }}</div>
<div>
<template v-if="!sorting">
<el-button v-auth="'/course/list:课程管理:内容设置:修改章节名称'" class="action-btn" type="primary" round v-throttle @click="editChapter(chapter)">修改章节名称</el-button>
<el-button v-auth="'/course/list:课程管理:内容设置:添加小节'" class="action-btn" type="primary" round v-throttle @click="addSection(chapter.id)">添加小节</el-button>
<el-button v-auth="'/course/list:课程管理:内容设置:章节删除'" class="action-btn" type="primary" round v-throttle @click="delChapter(chapter.id)">删除</el-button>
</template>
<template v-else>
<i class="el-icon-top sort-icon" :class="{disabled: index == 0}" style="margin-right: 5px" @click="sortChapter(chapter,'up',index == 0,index)"></i>
<i class="el-icon-bottom sort-icon" :class="{disabled: index == chapters.length-1}" @click="sortChapter(chapter,'down',index == chapter.length-1,index)"></i>
</template>
</div>
</div>
<el-table :data="chapter.subsectionList" class="table" stripe header-align="center">
<el-table-column v-if="sorting" width="55" align="center">
<template slot-scope="scope">
<el-checkbox v-model="scope.row.check"></el-checkbox>
</template>
</el-table-column>
<el-table-column type="index" width="100" label="序号" align="center"></el-table-column>
<el-table-column prop="name" label="资源名称">
</el-table-column>
<el-table-column prop="fileType" label="资源类型" align="center">
<template slot-scope="scope">
{{ transferType(scope.row.fileType) }}
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="300">
<template slot-scope="scope">
<template v-if="!sorting">
<el-button v-auth="'/course/list:课程管理:内容设置:查看'" type="text" @click="preview(scope.row)">查看</el-button>
<el-button v-auth="'/course/list:课程管理:内容设置:小节删除'" type="text" @click="delSection(scope.row)">删除</el-button>
<el-button v-auth="'/course/list:课程管理:内容设置:修改小节名称'" type="text" @click="editSectionName(scope.row,chapter.id)">修改小节名称</el-button>
<el-button v-auth="'/course/list:课程管理:内容设置:更换文件'" type="text" @click="switchFile(scope.row,chapter.id)">更换文件</el-button>
</template>
<template v-else>
<i class="el-icon-top sort-icon" :class="{disabled: scope.$index == 0}" style="margin-right: 5px" @click="sortSection(index,'up',scope.$index == 0,scope.$index)"></i>
<i class="el-icon-bottom sort-icon" :class="{disabled: scope.$index == chapter.subsectionList.length-1}" @click="sortSection(index,'down',scope.$index == chapter.subsectionList.length-1,scope.$index)"></i>
</template>
</template>
</el-table-column>
</el-table>
</div>
<el-dialog :title="chapterId ? '编辑章节' : '新增章节'" :visible.sync="chapterVisible" width="24%" :close-on-click-modal="false">
<el-form>
<el-form-item>
<el-input placeholder="请输入章节名称,便于对小节归类" v-model="chapterName" maxlength="50"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="chapterVisible = false">取消</el-button>
<el-button type="primary" @click="chapterSubmit">确定</el-button>
</span>
</el-dialog>
<el-dialog title="添加小节" :visible.sync="sectionVisible" width="28%" @close="closeSection" :close-on-click-modal="false">
<el-form label-width="80px">
<el-form-item label="资源添加">
<el-upload
:before-upload="beforeUpload"
:on-remove="handleRemove"
:on-error="uploadError"
:on-success="uploadSuccess"
:before-remove="beforeRemove"
:limit="1"
:on-exceed="handleExceed"
:action="this.api.fileupload"
:file-list="uploadList"
:headers="headers"
name="file"
>
<el-button size="small"><img src="@/assets/img/upload.png" alt=""> 上传资源</el-button>
</el-upload>
</el-form-item>
<el-form-item label="小节名称">
<el-input placeholder="请输入小节名称" v-model="sectionName" maxlength="50"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="sectionVisible = false">取消</el-button>
<el-button type="primary" @click="sectionSubmit">确定</el-button>
</span>
</el-dialog>
<el-dialog title="更换文件" :visible.sync="switchVisible" width="28%" :close-on-click-modal="false" @close="closeSwitch">
<div style="text-align: center">
<el-upload
:before-upload="beforeUpload"
:on-remove="handleRemove"
:on-error="uploadError"
:on-success="uploadSuccess"
:before-remove="beforeRemove"
:limit="1"
:on-exceed="handleExceed"
:action="this.api.fileupload"
:file-list="uploadList"
:headers="headers"
name="file"
>
<el-button size="small"><img src="@/assets/img/upload.png" alt=""> 上传资源</el-button>
</el-upload>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="switchVisible = false">取消</el-button>
<el-button type="primary" @click="switchSubmit">确定</el-button>
</span>
</el-dialog>
<el-dialog title="修改小节名称" :visible.sync="sectionNameVisible" width="24%" :close-on-click-modal="false">
<el-form>
<el-form-item>
<el-input placeholder="请输入小节名称" v-model="sectionName" maxlength="50"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="sectionNameVisible = false">取消</el-button>
<el-button type="primary" @click="sectionNameSubmit">确定</el-button>
</span>
</el-dialog>
<div v-show="previewImg" class="el-image-viewer__wrapper" :class="{active: previewImg}" style="z-index: 2000">
<div class="el-image-viewer__mask"></div>
<span class="el-image-viewer__btn el-image-viewer__close" @click="previewImg = ''"><i class="el-icon-circle-close" style="color: #fff"></i></span>
<div class="el-image-viewer__canvas">
<img :src="previewImg" class="el-image-viewer__img" style="transform: scale(1) rotate(0deg);margin-top: -1px; max-height: 100%; max-width: 100%;">
</div>
</div>
<div v-show="iframeSrc" class="el-image-viewer__wrapper" :class="{active: iframeSrc}" style="z-index: 2000">
<div class="el-image-viewer__mask"></div>
<span class="el-image-viewer__btn el-image-viewer__close" :class="{'doc-close': isWord}" :style="{top: isWord ? '50px' : '5px'}" @click="closeIframe"><i class="el-icon-circle-close" style="color: #fff"></i></span>
<div class="el-image-viewer__canvas">
<iframe v-if="iframeSrc" class="fileIframe" id="fileIframe" :src="iframeSrc" frameborder="0"></iframe>
<template v-if="showMask">
<div class="mask" style="width: 200px;height: 30px;top: 53px;right: 320px"></div>
<div class="mask" style="width: 175px;height: 30px;top: 53px;right: 5px"></div>
</template>
<template v-if="showMask1">
<div class="word-mask1" style="width: 200px;height: 50px;"></div>
<div class="word-mask" style="height: 40px;top: 48px;"></div>
<div class="word-mask2" style="top: 55px;left: 28%;width: 44%;height: calc(100% - 80px);"></div>
</template>
<template v-if="showMask2 && iframeSrc">
<div class="excel-mask1" style="height: 48px;"></div>
</template>
</div>
</div>
<div v-show="playAuth" class="el-image-viewer__wrapper" :class="{active: playAuth}" style="z-index: 2000">
<div class="el-image-viewer__mask"></div>
<span class="el-image-viewer__btn el-image-viewer__close" @click="closePlayer"><i class="el-icon-circle-close" style="color: #fff"></i></span>
<div class="player" id="player"></div>
</div>
<pdf :visible.sync="pdfVisible" :src.sync="pdfSrc"></pdf>
</div>
</div>
</el-card>
<el-dialog title="资源移动" :visible.sync="moveVisible" :close-on-click-modal="false" width="330px">
<el-form>
<el-form-item label="目标章节">
<el-select v-model="moveForm.id" placeholder="请选择目标章节" @change="chapterChange">
<el-option v-for="(item, i) in chapters" :key="i" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="目标排序">
<el-select v-model="moveForm.sort" placeholder="请选择目标排序">
<el-option v-for="(item, i) in sortList" :key="i" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="moveVisible = false">取消</el-button>
<el-button type="primary" @click="moveConfirm">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import util from "@/libs/util";
import Setting from "@/setting";
import { Loading } from "element-ui";
import pdf from "@/components/pdf";
export default {
name: "contentSettings",
data() {
return {
headers: {
token: util.local.get(Setting.tokenKey)
},
id: "",
originChapters: [],
chapters: [],
sorting: false,
uploading: false,
uploadList: [],
chapterVisible: false,
chapterId: "",
chapterName: "",
sectionVisible: false,
sectionName: "",
sectionId: "",
switchVisible: false,
sectionNameVisible: false,
fileId: "",
fileName: "",
fileUrl: "",
originalFileName: "",
fileType: "",
playAuth: "",
player: null,
previewImg: "",
iframeSrc: "",
curFile: {},
isAddSection: false,
isWord: false,
isPPT: false,
isExcel: false,
showMask: false,
showMask1: false,
showMask2: false,
loadIns: null,
pdfVisible: false,
pdfSrc: "",
previewing: false,
moveVisible: false,
checkList: [],
sortList: [
{
id: 'bottom',
name: '置末'
},
{
id: 'top',
name: '置顶'
}
],
moveForm: {
id: '',
sort: 'bottom'
},
moved: false //
};
},
components: { pdf },
mounted() {
this.insertScript();
this.id = this.$route.query.id;
this.id && this.getData();
//
if (window.history && window.history.pushState) {
history.pushState(null, null, document.URL);
window.addEventListener("popstate", this.goBack, false);
}
},
destroyed() {
window.removeEventListener("popstate", this.goBack, false);
},
methods: {
getData() {
this.$get(`${this.api.queryChaptersAndSubsections}/${this.id}`)
.then(res => {
this.chapters = res.chapterList;
})
.catch(err => {
});
},
goBack() {
//
if (this.previewing) {
this.closeIframe();
} else {
//
if (this.sorting) {
//
if (this.moved) {
this.$confirm(`编辑的内容未保存,是否保存?`, '提示', {
type: 'warning'
}).then(() => {
this.saveSort()
this.moved = false
}).catch(() => {
this.sorting = false
this.chapters = JSON.parse(JSON.stringify(this.originChapters))
})
} else {
this.sorting = false
}
} else {
this.$router.back()
}
}
},
iframeOnload() {
document.querySelector("#fileIframe").onload = e => {
if (this.isPPT) {
this.showMask = true;
} else {
this.showMask = false;
}
if (this.isWord) {
this.showMask1 = true;
} else {
this.showMask1 = false;
}
if (this.isExcel) {
this.showMask2 = true;
} else {
this.showMask2 = false;
}
this.loadIns.close();
};
},
insertScript() {
const linkTag = document.createElement("link");
linkTag.rel = "stylesheet";
linkTag.href = "https://g.alicdn.com/de/prismplayer/2.8.2/skins/default/aliplayer-min.css";
document.body.appendChild(linkTag);
const scriptTag = document.createElement("script");
scriptTag.type = "text/javascript";
scriptTag.src = "https://g.alicdn.com/de/prismplayer/2.8.2/aliplayer-min.js";
document.body.appendChild(scriptTag);
},
//
beforeUpload(file) {
let type = this.transferType(file.name.substring(file.name.lastIndexOf(".") + 1));
if (type != "视频" && type != "图片" && type != "pdf" && (file.size / 1024 / 1024) > 10) {
util.errorMsg("请上传10M以内的文件");
return false;
}
this.uploading = true;
this.originalFileName = file.name;
if (this.isAddSection) this.sectionName = file.name.substring(0, file.name.lastIndexOf("."));
this.fileType = file.name.substring(file.name.lastIndexOf(".") + 1);
},
handleExceed(files, fileList) {
util.warningMsg(
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`
);
},
uploadSuccess(res, file, fileList) {
this.uploading = false;
this.fileId = res.data.filesResult.fileId;
this.fileType = res.data.filesResult.fileType;
this.fileUrl = res.data.filesResult.fileUrl;
this.fileName = res.data.filesResult.ossFileName;
},
uploadError(err, file, fileList) {
this.$message({
message: "上传出错,请重试!",
type: "error",
center: true
});
},
beforeRemove(file, fileList) {
if ((file.size / 1024 / 1024) < 10) {
return this.$confirm(`确定移除 ${file.name}`);
}
},
handleRemove(file, fileList) {
this.uploadList = fileList;
},
uploadSure() {
this.importVisible = false;
this.pageNo = 1;
this.staffGradeId = "";
this.keyword = "";
this.getTeacher();
},
goback() {
this.$router.push("course");
},
transferType(ext) {
const suf = ext.toLowerCase()
if ("jpg,jpeg,png,gif,svg,psd".includes(suf)) return "图片";
if ("mp4,3gp,mov,m4v,avi,dat,mkv,flv,vob,rmvb,rm,qlv".includes(suf)) return "视频";
return suf;
},
addChapter() {
this.chapterName = "";
this.chapterId = "";
this.chapterVisible = true;
},
sort() {
this.originChapters = JSON.parse(JSON.stringify(this.chapters))
this.sorting = true;
},
//
move() {
const list = this.chapters
const checkList = []
list.map(e => {
e.subsectionList.map(n => {
n.check && checkList.push(n)
})
})
this.checkList = checkList
if (checkList.length) {
this.moveForm = {
id: '',
sort: 'bottom'
}
this.sortList = [
{
id: 'bottom',
name: '置末'
},
{
id: 'top',
name: '置顶'
}
]
this.moveVisible = true
} else {
this.$message.warning('请选择小节!')
}
},
//
chapterChange(id) {
const list = []
//
this.chapters.find(e => e.id === id).subsectionList.map((e, i) => {
list.push({
id: i,
name: i+1
})
})
//
this.sortList = [
{
id: 'bottom',
name: '置末'
},
...list,
{
id: 'top',
name: '置顶'
}
]
},
//
moveConfirm() {
let { id, sort } = this.moveForm
if (!id) return this.$message.warning('请选择目标章节')
if (sort === '') return this.$message.warning('请选择目标排序')
if (typeof sort === 'string') sort = sort === 'top' ? 0 : this.sortList.length - 2 //
this.moveVisible = false
const list = this.checkList
list.map(e => e.check = false)
const ids = list.map(e => e.id)
const { chapters } = this
chapters.map(e => {
e.children = []
e.subsectionList.map(n => {
if (!ids.includes(n.id)) {
e.children.push(n)
}
})
e.subsectionList = e.children
delete e.children
if (e.id === id) e.subsectionList.splice(sort, 0, ...list)
})
this.moved = true
},
cancelSort() {
this.chapters = JSON.parse(JSON.stringify(this.originChapters))
this.sorting = false;
},
saveSort() {
this.chapters.forEach((n, k) => {
n.sort = k + 1;
n.subsectionList.forEach((j, i) => {
j.sort = i + 1
j.chapterId = n.id
});
});
let data = {
chapterVOList: this.chapters
};
this.$post(this.api.reorder, data).then(res => {
this.sorting = false;
}).catch(res => {
});
},
editChapter(item) {
this.chapterId = item.id;
this.chapterName = item.name;
this.chapterVisible = true;
},
delChapter(id) {
this.$confirm("此删除操作不可逆,是否确认删除选中项?", "提示", {
type: "warning"
})
.then(() => {
this.$del(`${this.api.deleteChapter}/${id}`).then(res => {
util.successMsg("删除成功");
this.getData();
}).catch(res => {
});
})
.catch(() => {
});
},
closeSection() {
this.isAddSection = false;
},
addSection(id) {
this.chapterId = id;
this.sectionName = "";
this.fileUrl = "";
this.uploadList = [];
this.sectionId = "";
this.isAddSection = true;
this.sectionVisible = true;
},
chapterSubmit() {
if (!this.chapterName) return util.warningMsg("请填写章节名称");
let data = {
courseId: this.id,
name: this.chapterName
};
if (this.chapterId) {
data.id = this.chapterId;
this.$put(this.api.editChapter, data).then(res => {
util.successMsg("修改成功");
this.chapterVisible = false;
this.getData();
})
.catch(err => {
});
} else {
this.$post(this.api.addChapter, data).then(res => {
util.successMsg("添加成功");
this.chapterVisible = false;
this.getData();
})
.catch(err => {
});
}
},
sectionSubmit() {
if (!this.sectionName) return util.warningMsg("请填写小节名称");
if (this.uploading) return util.warningMsg("资源正在上传中,请稍候");
if (!this.fileUrl && !this.fileId) return util.warningMsg("请上传资源");
let data = {
id: this.sectionId,
courseId: this.id,
chapterId: this.chapterId,
name: this.sectionName,
fileId: this.fileId,
fileUrl: this.fileUrl,
fileName: this.fileName,
fileType: this.fileType,
originalFileName: this.originalFileName
};
this.$post(this.api.addSubsection, data).then(res => {
util.successMsg("添加成功");
this.sectionVisible = false;
this.getData();
})
.catch(err => {
});
},
closeSwitch() {
this.fileId = "";
this.fileName = "";
this.fileType = "";
this.fileUrl = "";
this.sectionId = "";
},
preview(row) {
if (this.transferType(row.fileType) == "视频") {
this.$get(`${this.api.getPlayAuth}/${row.fileId}`).then(res => {
this.playAuth = res.data.playAuth;
if (this.player) {
this.player.replayByVidAndPlayAuth(row.fileId, this.playAuth);
} else {
this.player = new Aliplayer({
id: "player",
width: "100%",
autoplay: false,
vid: row.fileId,
playauth: this.playAuth,
encryptType: 1 //
});
}
}).catch(res => {
});
} else if (this.transferType(row.fileType) == "图片") {
this.previewImg = row.fileUrl;
} else if (row.fileType == "pdf") {
this.pdfSrc = row.fileUrl;
this.pdfVisible = true;
} else {
this.$get(`${this.api.getSubsection}/${row.id}`).then(res => {
this.previewing = true;
this.loadIns = Loading.service();
this.$route.fullPath.includes("#file") || history.pushState({ file: true }, "文件预览", "#" + this.$route.fullPath + "#file");
if (row.fileType == "pptx") {
this.isPPT = true;
this.isWord = false;
this.isExcel = false;
} else if (row.fileType == "doc" || row.fileType == "docx") {
this.isPPT = false;
this.isWord = true;
this.isExcel = false;
} else if (row.fileType == "xls" || row.fileType == "xlsx") {
this.isExcel = true;
this.isPPT = false;
this.isWord = false;
} else {
this.isPPT = false;
this.isWord = false;
this.isExcel = false;
}
this.iframeSrc = res.previewUrl;
this.$nextTick(() => {
this.iframeOnload();
});
})
.catch(err => {
});
}
},
editSectionName(row, chapterId) {
this.chapterId = chapterId;
this.sectionId = row.id;
this.sectionName = row.name;
this.sectionNameVisible = true;
},
switchFile(row, chapterId, sectionId) {
this.uploadList = [];
this.curFile = {
fileId: row.fileId,
fileName: row.fileName,
fileType: row.fileType,
fileUrl: row.fileUrl
};
this.chapterId = chapterId;
this.sectionId = row.id;
this.sectionName = row.sectionName;
this.switchVisible = true;
},
switchSubmitFile() {
let data = {
id: this.sectionId,
courseId: this.id,
chapterId: this.chapterId,
name: this.sectionName,
fileId: this.fileId,
fileName: this.fileName,
fileType: this.fileType,
fileUrl: this.fileUrl,
originalFileName: this.originalFileName
};
this.$put(this.api.editSubsection, data).then(res => {
util.successMsg("更换成功");
this.switchVisible = false;
this.getData();
})
.catch(err => {
});
},
switchSubmit() {
if (this.uploading) return util.warningMsg("资源正在上传中,请稍候");
if (!this.fileUrl && !this.fileId) return util.warningMsg("请上传资源");
if (this.transferType(this.curFile.fileType) == "视频") {
let data = {
videoIdList: [this.sectionId]
};
this.$del(`${this.api.removeVideo}/${this.curFile.fileId}`).then(res => {
this.switchSubmitFile();
}).catch(res => {
});
} else {
this.$del(`${this.api.fileDeletion}?keys=${this.curFile.fileName}`).then(res => {
this.switchSubmitFile();
}).catch(res => {
});
}
},
delSection(row) {
this.$confirm("此删除操作不可逆,是否确认删除选中项?", "提示", {
type: "warning"
})
.then(() => {
this.$del(`${this.api.deleteSubsection}/${row.id}`).then(res => {
util.successMsg("删除成功");
this.getData();
}).catch(res => {
});
})
.catch(() => {
});
},
sortChapter(row, type, disabled, index) {
if (!disabled) {
if (type == "up") {
let tempItem = this.chapters.splice(index - 1, 1)[0];
this.chapters.splice(index, 0, tempItem);
} else {
let tempItem = this.chapters.splice(index + 1, 1)[0];
this.chapters.splice(index, 0, tempItem);
}
}
},
sortSection(chapterIndex, type, disabled, index) {
if (!disabled) {
this.moved = true
let list = this.chapters[chapterIndex].subsectionList;
if (type == "up") {
let tempItem = list.splice(index - 1, 1)[0];
list.splice(index, 0, tempItem);
} else {
let tempItem = list.splice(index + 1, 1)[0];
list.splice(index, 0, tempItem);
}
this.chapters[chapterIndex].subsectionList = list;
}
},
sectionNameSubmit() {
if (!this.sectionName) return util.warningMsg("请填写小节名称");
let data = {
id: this.sectionId,
courseId: this.id,
chapterId: this.chapterId,
name: this.sectionName
};
this.$put(this.api.editSubsection, data).then(res => {
util.successMsg("修改成功");
this.sectionNameVisible = false;
this.getData();
})
.catch(err => {
});
},
closePlayer() {
this.playAuth = "";
this.player.pause();
},
closeIframe() {
this.iframeSrc = "";
this.showMask = false;
this.showMask1 = false;
this.showMask2 = false;
this.previewing = false;
}
}
};
</script>
<style scoped lang="scss">
.btns {
position: absolute;
top: 12px;
right: 24px;
.el-button {
font-size: 14px;
}
}
/deep/.el-progress-bar {
padding-right: 70px;
margin-right: -70px;
}
.sort-icon {
font-size: 24px;
cursor: pointer;
&.disabled {
color: #ccc;
cursor: not-allowed
}
}
.el-image-viewer__wrapper {
transform: translateY(-10px);
transition: transform .5s;
&.active {
transform: translateY(0)
}
}
.el-image-viewer__close {
z-index: 10000;
top: 15px;
right: 15px;
&.doc-close {
i {
color: #000 !important;
}
}
}
.player {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 1200px !important;
height: 600px !important;
}
.fileIframe {
z-index: 1;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
width: 100%;
height: 100%;
}
.mask {
z-index: 1000;
position: fixed;
background-color: rgb(57, 58, 61);
}
.word-mask {
z-index: 1000;
position: fixed;
right: 0;
width: 100%;
background-color: rgb(243, 242, 241);
}
.word-mask1 {
z-index: 1000;
position: fixed;
top: 0;
right: 0;
background-color: #2b579a;
}
.word-mask2 {
z-index: 1000;
position: fixed;
background-color: transparent;
}
.excel-mask1 {
z-index: 9;
position: absolute;
top: 0;
left: 20%;
width: 80%;
background-color: #107c41;
}
</style>

@ -1,222 +0,0 @@
<template>
<!-- 课程管理 -->
<div style="padding-top: 24px">
<div class="tool">
<ul class="filter" style="align-items: flex-start">
<li>
<label>课程分类</label>
<el-select v-model="classificationId" clearable placeholder="请选择课程分类" @change="getData">
<el-option label="不限" value=""></el-option>
<el-option v-for="(item,index) in classificationList" :key="index" :label="item.name" :value="item.id"></el-option>
</el-select>
</li>
<li>
<label>搜索</label>
<el-input placeholder="请输入课程名称/创建人" suffix-icon="el-icon-search" v-model="keyword" clearable size="small"></el-input>
</li>
</ul>
<div>
<el-button v-auth="'课程管理:新增'" type="info" round @click="addCourse">新增</el-button>
<el-button v-auth="'课程管理:批量删除'" type="primary" round @click="delAllData">批量删除</el-button>
</div>
</div>
<el-table :data="courseData" class="table" ref="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="id">
<el-table-column type="selection" width="80" align="center" :reserve-selection="true"></el-table-column>
<el-table-column type="index" width="100" label="序号" align="center">
<template slot-scope="scope">
{{ scope.$index + (current - 1) * pageSize + 1 }}
</template>
</el-table-column>
<el-table-column prop="name" label="课程名称">
</el-table-column>
<el-table-column prop="gmtCreate" label="创建时间" align="center">
</el-table-column>
<el-table-column prop="founder" label="创建人" align="center">
</el-table-column>
<el-table-column label="章节数" align="center">
<template slot-scope="scope">
{{ scope.row.chapterNum ? scope.row.chapterNum : 0 }}({{ scope.row.subsectionNum ? scope.row.subsectionNum : 0 }}小节)
</template>
</el-table-column>
<el-table-column prop="classification" label="课程分类">
</el-table-column>
<el-table-column label="操作" align="center" width="250">
<template slot-scope="scope">
<el-button v-auth="'课程管理:编辑信息'" type="text" @click="editCourse(scope.row)">编辑信息</el-button>
<el-divider v-auth="'课程管理:编辑信息'" direction="vertical"></el-divider>
<el-button v-auth="'课程管理:内容设置'" type="text" @click="config(scope.row)">内容设置</el-button>
<el-divider v-auth="'课程管理:内容设置'" direction="vertical"></el-divider>
<el-button v-auth="'课程管理:预览'" type="text" @click="preview(scope.row)">预览</el-button>
<el-divider v-auth="'课程管理:预览'" direction="vertical"></el-divider>
<el-button v-auth="'课程管理:删除'" type="text" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
<el-table-column label="可授权状态" align="center" width="120">
<template slot-scope="scope">
<el-switch
v-auth="'课程管理:禁用'"
v-model="scope.row.isEnable"
:active-value="0"
:inactive-value="1"
style="margin: 0 5px"
:active-text="scope.row.isEnable ? '关' : '开'"
@change="switchOff($event,scope.row,scope.$index)"
></el-switch>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background layout="total, prev, pager, next" :total="totals" @current-change="handleCurrentChange" :current-page="current">
</el-pagination>
</div>
</div>
</template>
<script>
import util from "@/libs/util";
export default {
name: "courseManagement",
data() {
return {
keyword: "",
classificationId: "",
courseData: [],
multipleSelection: [],
classificationList: [],
current: +this.$route.query.page || 1, //
pageSize: 10,
totals: 0
};
},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer);
this.searchTimer = setTimeout(() => {
this.initData();
}, 500);
}
},
mounted() {
this.getClassification();
this.getData();
},
methods: {
getData() {
let data = {
classificationId: this.classificationId,
name: this.keyword
};
this.$get(`${this.api.queryCourseByCondition}/${this.current}/${this.pageSize}`, data).then(res => {
this.courseData = res.courseList;
this.totals = res.total;
if (!this.courseData.length && this.totals) {
this.current--;
this.getData();
}
}).catch(res => {
});
},
initData() {
this.current = 1;
this.getData();
},
getClassification() {
this.$get(this.api.queryGlClassification).then(res => {
this.classificationList = res.classificationList;
}).catch(res => {
});
},
changeType(type) {
this.classificationId = type;
this.initData();
},
preview(row) {
this.$router.push(`/course/preview?id=${row.id}`);
},
config(row) {
this.$router.push(`/course/contentSettings?id=${row.id}`);
},
addCourse() {
this.$router.push("/course/add");
},
editCourse(row) {
this.$router.push(`/course/add?id=${row.id}`);
},
handleDelete(row) {
this.$confirm("此删除操作不可逆,是否确认删除选中项?", "提示", {
type: "warning"
})
.then(() => {
this.$del(`${this.api.deleteCourse}/${row.id}`).then(res => {
util.successMsg("删除成功");
this.initData();
}).catch(res => {
});
})
.catch(() => {
});
},
getRowKeys(row) {
return row.customerId;
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
delAllData() {
if (this.multipleSelection.length != "") {
let newArr = this.multipleSelection;
let delList = newArr.map(item => {
return item.id;
});
this.$confirm(`此批量删除操作不可逆,是否确认删除${newArr[0].name}${newArr.length}个选中项?`, "提示", {
type: "warning"
})
.then(() => {
let data = {
courseIds: delList.join()
};
this.$del(this.api.deleteCourses, data).then(res => {
this.multipleSelection = [];
this.$refs.table.clearSelection();
util.successMsg("删除成功");
this.initData();
}).catch(res => {
});
if(this.multipleSelection.length === this.courseData.length && this.current>1) {
this.handleCurrentChange(this.current - 1)
}
}).catch(() => {
});
} else {
util.errorMsg("请先选择数据 !");
}
},
handleCurrentChange(val) {
this.current = val;
this.$router.push(`list?page=${val}`)
this.getData();
},
switchOff(val, row, index) {
this.$put(`${this.api.enableCourse}?courseId=${row.id}&isEnable=${val}`)
.then(res => {
this.getData();
val == 1 ? util.warningMsg("该教学资源已隐藏,对学生端用户不可见") : util.successMsg("该教学资源已公开,对学生端用户可见");
})
.catch(err => {
});
}
}
};
</script>
<style lang="scss" scoped>
/deep/ .tool {
.filter {
.el-input {
min-width: 215px;
}
}
}
</style>

@ -1,63 +0,0 @@
<template>
<!-- 理论课程管理 -->
<div class="page">
<div class="tabs">
<a class="item" v-for="(item,index) in tabs" :key="index" :class="{active: index == active}" @click="tabChange(index)">{{ item }}</a>
</div>
<div class="page-content">
<!-- 课程管理 -->
<CourseManagement v-if="active == 'first'" />
<!-- 分类管理 -->
<SortManagement v-if="active == 'second'" />
</div>
</div>
</template>
<script>
import Setting from "@/setting";
import { mapState } from "vuex";
import CourseManagement from "./courseManagement";
import SortManagement from "./sortManagement";
export default {
name: "course",
components: {
CourseManagement,
SortManagement
},
data() {
return {
active: "first", //
tabs: {
first: "课程管理",
second: "分类管理"
},
showTabs: true
};
},
computed: {
...mapState("auth", [
"btns"
])
},
mounted() {
Setting.dynamicRoute && this.initTabs();
},
methods: {
tabChange(index) {
this.active = index;
},
initTabs() {
const { btns } = this
const tab1 = btns.includes('/course/list:课程管理')
const tab2 = btns.includes('/course/list:分类管理')
tab1 || delete this.tabs.first
tab2 || delete this.tabs.second
}
}
};
</script>
<style lang="scss" scoped>
</style>

@ -1,166 +0,0 @@
<template>
<!-- 分类管理 -->
<div>
<div class="tool">
<ul class="filter">
</ul>
<div style="margin-top: 24px">
<el-button v-auth="'分类管理:新增'" type="primary" round @click="addClass">新增</el-button>
</div>
</div>
<el-table :data="classificationList" class="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="id">
<el-table-column type="index" width="100" label="序号" align="center">
<template slot-scope="scope">
{{ scope.$index + (pageNo - 1) * pageSize + 1 }}
</template>
</el-table-column>
<el-table-column prop="name" label="课程分类名称">
</el-table-column>
<el-table-column label="操作" align="center" width="300">
<template slot-scope="scope">
<el-button v-auth="'分类管理:修改'" type="text" @click="editClass(scope.row)">修改</el-button>
<el-divider v-auth="'分类管理:修改'" direction="vertical"></el-divider>
<el-button v-auth="'分类管理:删除'" type="text" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog :title="isAddclass ? '添加分类' : '编辑分类'" :visible.sync="classVisible" width="400px" :close-on-click-modal="false" @close="closeColumn">
<el-form>
<el-form-item>
<el-input placeholder="分类名称" v-model="className"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="classVisible = false"> </el-button>
<el-button type="primary" @click="classSubmit"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import util from "@/libs/util";
export default {
name: "sortManagement",
data() {
return {
classificationList: [],
multipleSelection: [],
pageNo: 1,
pageSize: 10,
isAddclass: true,
classVisible: false,
curRow: {},
className: ""
};
},
mounted() {
this.getData();
},
methods: {
getData() {
this.$get(this.api.queryGlClassification).then(res => {
this.classificationList = res.classificationList;
}).catch(res => {
});
},
addCourse() {
this.$router.push("/addcourse");
},
editCourse(row) {
this.$router.push(`/addcourse?id=${row.id}`);
},
handleDelete(row) {
this.$confirm("此删除操作不可逆,是否确认删除选中项?", "提示", {
type: "warning"
})
.then(() => {
this.$del(`${this.api.deleteClassification}/${row.id}`).then(res => {
util.successMsg("删除成功");
this.getData();
}).catch(res => {
});
})
.catch(() => {
});
},
getRowKeys(row) {
return row.customerId;
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
closeColumn() {
this.className = "";
this.curRow = {};
},
delAllData() {
if (this.multipleSelection.length != "") {
let newArr = this.multipleSelection;
let delList = newArr.map(item => {
return item.id;
});
//
this.$confirm("此删除操作不可逆,是否确认删除选中项?", "提示", {
type: "warning"
})
.then(() => {
let data = delList.join();
this.$del(this.api.deleteClassification, data).then(res => {
this.multipleSelection = [];
util.successMsg("删除成功");
this.getData();
}).catch(res => {
});
}).catch(() => {
});
} else {
util.errorMsg("请先选择数据 !");
}
},
handleCurrentChange(val) {
this.pageNo = val;
this.getData();
},
addClass() {
this.isAddClass = true;
this.classVisible = true;
},
editClass(row) {
this.curRow = row;
this.className = row.name;
this.isAddClass = false;
this.classVisible = true;
},
classSubmit() {
if (!this.className) return util.warningMsg("请填写分类名称");
let data = {
name: this.className
};
if (this.curRow.id) {
data.id = this.curRow.id;
this.$put(this.api.editClassification, data).then(res => {
util.successMsg("修改成功");
this.classVisible = false;
this.getData();
}).catch(res => {
});
} else {
this.$post(`${this.api.addClassification}/${this.className}?distinguish=1`).then(res => {
util.successMsg("添加成功");
this.classVisible = false;
this.getData();
}).catch(res => {
});
}
}
}
};
</script>
<style lang="scss" scoped>
</style>

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

@ -1,7 +1,7 @@
<template>
<div class="page">
<div class="tool">
<p class="page-name">企业网站管理后台</p>
<p class="page-name">页面列表</p>
<div style="display: inline-flex;align-items: center;">
<el-dropdown class="setting" trigger="click" :hide-on-click="false">
<el-tooltip placement="top">
@ -25,7 +25,7 @@
:value="item.id">
</el-option>
</el-select>
<el-input class="keyword" placeholder="请输入栏目或模板名称" v-model.trim="keyword" clearable></el-input>
<el-input class="keyword" :placeholder="'请输入' + keywords.find(e => e.id === field).name" v-model.trim="keyword" clearable></el-input>
</div>
</div>
</div>
@ -48,9 +48,9 @@
<el-table-column v-if="settings[5].show" prop="editorName" label="编辑人" align="center"></el-table-column>
<el-table-column v-if="settings[6].show" label="操作" width="170" align="center">
<template slot-scope="scope">
<el-button type="text" @click="start(scope.row)">预览</el-button>
<el-button type="text" @click="start(scope.row)">编辑</el-button>
<el-button type="text" @click="start(scope.row)">删除</el-button>
<el-button v-auth="'/site/list:' + site.siteName + ':内容管理:页面管理:预览'" type="text" @click="start(scope.row)">预览</el-button>
<el-button v-auth="'/site/list:' + site.siteName + ':内容管理:页面管理:编辑'" type="text" @click="start(scope.row)">编辑</el-button>
<el-button v-auth="'/site/list:' + site.siteName + ':内容管理:页面管理:删除'" type="text" @click="start(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
@ -64,6 +64,7 @@
export default {
data() {
return {
site: this.$store.state.content.site,
field: 'programName',
keywords: [
{
@ -122,7 +123,7 @@ export default {
}
},
mounted() {
this.$store.commit('user/SET_CRUMBS', [
this.$store.commit('user/setCrumbs', [
{
name: '站点管理',
route: '/site'
@ -141,7 +142,7 @@ export default {
//
getData() {
this.$post(this.api.longPageColumnList, {
siteId: this.$store.state.content.site.id,
siteId: this.site.id,
pageNum: this.page,
pageSize: this.pageSize,
programName: this.field === 'programName' ? this.keyword : '',

@ -5,21 +5,21 @@
<el-input placeholder="请输入角色名称" v-model.trim="keyword" clearable></el-input>
</div>
<div class="actions">
<el-button type="primary" @click="addRole">新增</el-button>
<el-button @click="batchDel">删除</el-button>
<el-button v-auth type="primary" @click="addRole">新增</el-button>
<el-button v-auth="'批量删除'" @click="batchDel">删除</el-button>
</div>
</div>
<el-table :data="list" class="table" ref="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="id">
<el-table-column type="selection" width="55" align="center" :reserve-selection="true"></el-table-column>
<el-table-column type="selection" width="55" align="center" :reserve-selection="true" :selectable="row => row.name !== '超级管理员'"></el-table-column>
<el-table-column type="index" width="60" label="序号" align="center"></el-table-column>
<el-table-column prop="name" label="角色名称" align="center" min-width="250" show-overflow-tooltip></el-table-column>
<el-table-column prop="description" label="角色描述" min-width="400" align="center"></el-table-column>
<el-table-column label="操作" align="center" width="200">
<template slot-scope="scope">
<el-button type="text" @click="showRole(scope.row)">查看</el-button>
<el-button v-if="scope.row.name !== '超级管理员'" type="text" @click="editRole(scope.row)">编辑</el-button>
<el-button v-if="scope.row.name !== '超级管理员'" type="text" @click="handleDelete(scope.row)">删除</el-button>
<el-button v-auth type="text" @click="showRole(scope.row)">查看</el-button>
<el-button v-auth v-if="scope.row.name !== '超级管理员'" type="text" @click="editRole(scope.row)">编辑</el-button>
<el-button v-auth v-if="scope.row.name !== '超级管理员'" type="text" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
@ -67,10 +67,10 @@ export default {
keyword: "",
isDetail: false,
form: {
id: "",
name: "",
description: "",
permissions: []
id: "",
name: "",
description: "",
permissions: []
},
list: [],
defaultProps: {
@ -96,7 +96,7 @@ export default {
}
},
mounted() {
this.$store.commit('user/SET_CRUMBS', [
this.$store.commit('user/setCrumbs', [
{
name: '用户管理'
},
@ -187,6 +187,20 @@ export default {
this.permissions.length && this.$refs.per.setCheckedNodes([])
this.roleVisible = true
},
//
handleRolePer(data, permissions) {
let result = data
if (permissions.length) {
permissions.map(e => {
if (result.includes(e.id) && e.children) {
// ,idid,,,
e.children.every(n => result.includes(n)) || result.splice(result.indexOf(e.id), 1)
}
e.children && e.children.length && this.handleRolePer(data, e.children)
})
}
return result
},
//
async getDetail(row) {
this.$get(`${this.api.role}/${row.id}`).then(({ data }) => {
@ -195,8 +209,9 @@ export default {
this.form.description = role.description
this.form.id = role.id
const list = data.permissionList
list[0] === '1' && list.shift() // 11
this.$refs.per.setCheckedKeys(list)
// list[0] === '1' && list.shift() // 11
this.checkedIds = this.handleRolePer(list, this.permissions)
this.$refs.per.setCheckedNodes(this.checkedIds)
}).catch(err => {})
},
showRole(row) {
@ -214,9 +229,8 @@ export default {
const { form } = this
if (!form.name) return util.warningMsg("请填写角色名称")
if (!form.description) return util.warningMsg("请填写角色描述")
const checked = this.$refs.per.getCheckedKeys()
const checked = [...this.$refs.per.getHalfCheckedKeys(), ...this.$refs.per.getCheckedKeys()]
if (!checked.length) return util.warningMsg("请选择角色权限")
checked[0] !== '1' && checked.unshift('1')
let data = {
...form,
permissions: checked

@ -1,28 +1,23 @@
<template>
<div class="main">
<div class="wrap">
<div class="left">
<div class="inner">
<div class="text-center">
<img :src="avatar" class="avatar" />
<el-upload :headers="{token}" :action="this.api.uploadUserAvatars" name="file" :limit="10" :show-file-list="false" :on-success="changeAvatar">
<el-button type="text" size="small">点击更换头像</el-button>
</el-upload>
</div>
<ul class="menu">
<li v-for="item in typeList" :key="item.index" :class="{active: item.index == active}">
{{ item.title }}
</li>
</ul>
</div>
</div>
<div class="right">
<info ref="info" v-if="active == 1" @updateStatus="updateStatus"></info>
<download v-else></download>
</div>
<div class="main">
<div class="left">
<div class="inner">
<div class="text-center">
<img :src="avatar" class="avatar" />
<el-upload :headers="{token}" :action="this.api.uploadUserAvatars" name="file" :limit="10" :show-file-list="false" :on-success="changeAvatar">
<el-button type="text" size="small">点击更换头像</el-button>
</el-upload>
</div>
<ul class="menu">
<li v-for="item in typeList" :key="item.index" :class="{active: item.index == active}">
{{ item.title }}
</li>
</ul>
</div>
</div>
<info class="flex-1" ref="info" @updateStatus="updateStatus"></info>
</div>
</template>
<script>
@ -32,82 +27,74 @@ import info from './info'
import util from '@/libs/util'
export default {
data() {
return {
token: util.local.get(Setting.tokenKey),
typeList: [
{
index: '1',
title: '用户信息'
}
],
active: '1',
edited: false
};
return {
token: util.local.get(Setting.tokenKey),
typeList: [
{
index: '1',
title: '用户信息'
}
],
active: '1',
edited: false
};
},
components: { info },
computed: {
...mapState('user', [
'avatar'
]),
...mapState('user', [
'avatar'
]),
},
mounted() {
},
methods: {
...mapActions('user', [
'setAvatar'
]),
changeAvatar(res) {
this.setAvatar(res.message)
},
updateStatus(status){
this.edited = status
}
...mapActions('user', [
'setAvatar'
]),
changeAvatar(res) {
this.setAvatar(res.message)
},
updateStatus(status){
this.edited = status
}
}
};
</script>
<style lang="scss" scoped>
.main{
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.wrap{
display: flex;
width: $min-width;
padding: 12px 0 0;
.left{
margin-right: 12px;
background-color: #fff;
box-shadow: 2px 0px 6px 0px #EEEEEE;
.inner{
width: 170px;
padding: 20px 0;
}
.avatar{
width: 80px;
height: 80px;
border-radius: 50%;
}
.menu{
margin-top: 32px;
li{
padding: 0 20px;
color: #303133;
font-size: 14px;
line-height: 38px;
cursor: pointer;
&.active{
color: #fff;
background-color: $main-color;
}
}
}
display: flex;
width: $min-width;
padding: 12px 0 0;
margin: 0 auto;
.left{
margin-right: 12px;
background-color: #fff;
box-shadow: 2px 0px 6px 0px #EEEEEE;
.inner{
width: 170px;
padding: 20px 0;
}
.right{
flex: 1;
.avatar{
width: 80px;
height: 80px;
border-radius: 50%;
}
.menu{
margin-top: 32px;
li{
padding: 0 20px;
color: #303133;
font-size: 14px;
line-height: 38px;
cursor: pointer;
&.active{
color: #fff;
background-color: $main-color;
}
}
}
}
}
</style>

File diff suppressed because it is too large Load Diff

@ -13,12 +13,16 @@
{{ scope.$index + (page - 1) * pageSize + 1 }}
</template>
</el-table-column>
<el-table-column prop="name" label="站点名称" align="center"></el-table-column>
<el-table-column prop="domain" label="域名" align="center"></el-table-column>
<el-table-column prop="siteName" label="站点名称" align="center"></el-table-column>
<el-table-column prop="domainName" label="域名" width="400" align="center">
<template slot-scope="scope">
<el-input v-model.trim="scope.row.domainName" placeholder="请输入域名" @change="update(scope.row)"></el-input>
</template>
</el-table-column>
<el-table-column label="操作" width="170" align="center">
<template slot-scope="scope">
<el-button type="text" @click="toIndex(scope.row)">前往网站首页</el-button>
<el-button type="text" @click="content(scope.row)">内容管理</el-button>
<el-button v-auth="scope.row.siteName + ':前往网站首页'" type="text" @click="toIndex(scope.row)">前往网站首页</el-button>
<el-button v-auth="scope.row.siteName + ':内容管理'" type="text" @click="content(scope.row)">内容管理</el-button>
</template>
</el-table-column>
</el-table>
@ -29,28 +33,33 @@
</template>
<script>
import { mapMutations } from 'vuex'
import ColumnConst from '@/const/column'
import { mapState, mapMutations } from 'vuex'
export default {
data() {
return {
keyword: '',
page: +this.$route.query.page || 1,
pageSize: 10,
total: 6,
list: ColumnConst.sites
total: 0,
list: []
};
},
// watch: {
// keyword: function(val) {
// clearTimeout(this.searchTimer)
// this.searchTimer = setTimeout(() => {
// this.initData()
// }, 500)
// }
// },
computed: {
...mapState('auth', [
'btns'
])
},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.initData()
}, 500)
}
},
mounted() {
this.$store.commit('user/SET_CRUMBS', [
this.getData()
this.$store.commit('user/setCrumbs', [
{
name: '站点管理'
}
@ -61,11 +70,36 @@ export default {
'setSite'
]),
getData() {
this.$post(this.api.site, {
page: this.page,
limit: this.pageSize,
siteName: this.keyword
}).then(({ data }) => {
const { btns } = this
const result = []
data.records.map(e => {
btns.find(n => n.includes(e.siteName)) && result.push(e)
})
this.list = result
this.total = result.length
}).catch(e => {})
},
initData() {
this.page = 1
this.getData()
},
handleCurrentChange(val) {
this.page = val
},
//
update(row) {
this.$put(this.api.updateSite, {
id: row.id,
domainName: row.domainName
}).then(res => {
}).catch(e => {})
},
//
toIndex(row) {

@ -1,6 +1,6 @@
<template>
<div class="flex">
<div class="page" style="width: 320px">
<div class="page" style="width: 218px;border-right: 1px solid #EBEDF0">
<div class="m-b-20">
<p class="page-name mb">后台员工账号</p>
<el-radio-group v-model="staffType" @change="changeType">
@ -16,7 +16,7 @@
<div>
<div class="flex-between m-b-20">
<p class="page-name">组织管理</p>
<el-button type="text" @click="addOrg">添加</el-button>
<el-button v-auth="'新增部门'" type="text" @click="addOrg">添加</el-button>
</div>
<div style="height: 504px;overflow: auto">
@ -30,13 +30,13 @@
<img class="expand" src="@/assets/img/expand.png" alt="">
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>
<el-button class="org-btn" @click="() => editOrg(node, data)" type="text">编辑部门</el-button>
<el-button v-auth class="org-btn" @click="() => editOrg(node, data)" type="text">编辑部门</el-button>
</el-dropdown-item>
<el-dropdown-item>
<el-button class="org-btn add" @click="() => addOrg(node, data)" type="text">添加子部门</el-button>
<el-button v-auth="'新增部门'" class="org-btn add" @click="() => addOrg(node, data)" type="text">添加子部门</el-button>
</el-dropdown-item>
<el-dropdown-item>
<el-button class="org-btn del" @click="() => delOrg(node, data)" type="text">删除</el-button>
<el-button v-auth="'删除部门'" class="org-btn del" @click="() => delOrg(node, data)" type="text">删除</el-button>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
@ -75,9 +75,7 @@
</div>
<div class="page list-wrap">
<div class="tool">
<div class="search-wrap">
<el-input placeholder="请输入员工姓名/账号" v-model.trim="keyword" clearable></el-input>
</div>
<el-input style="width: 250px;" placeholder="请输入员工姓名/账号/工号/手机号" v-model.trim="keyword" clearable></el-input>
<div class="actions">
<el-dropdown class="setting" trigger="click" :hide-on-click="false">
<el-tooltip placement="top">
@ -92,9 +90,9 @@
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-button type="primary" @click="addStaff">新增员工</el-button>
<el-button @click="batchImport">批量导入</el-button>
<el-button @click="batchDel">批量删除</el-button>
<el-button v-auth type="primary" @click="addStaff">新增员工</el-button>
<el-button v-auth @click="batchImport">批量导入</el-button>
<el-button v-auth @click="batchDel">批量删除</el-button>
</div>
</div>
@ -103,18 +101,19 @@
<el-table-column type="index" width="60" label="序号"></el-table-column>
<el-table-column v-if="settings[1].show" prop="realName" label="员工姓名" min-width="100"></el-table-column>
<el-table-column v-if="settings[2].show" prop="username" label="账号" min-width="100"></el-table-column>
<el-table-column v-if="settings[3].show" prop="phone" label="手机号" min-width="100" show-overflow-tooltip></el-table-column>
<el-table-column v-if="settings[4].show" prop="deptArchitectureName" label="所在部门" min-width="100"></el-table-column>
<el-table-column v-if="settings[5].show" prop="createTime" label="创建日期" min-width="140"></el-table-column>
<el-table-column v-if="settings[6].show" prop="roleName" label="授权角色" min-width="100"></el-table-column>
<el-table-column v-if="settings[7].show" prop="groupName" label="用户组" min-width="100"></el-table-column>
<el-table-column v-if="settings[8].show" prop="lastLoginTime" label="最后登录时间" min-width="140"></el-table-column>
<el-table-column v-if="settings[9].show" label="操作" width="180">
<el-table-column v-if="settings[3].show" prop="jobNumber" label="工号" min-width="100"></el-table-column>
<el-table-column v-if="settings[4].show" prop="phone" label="手机号" min-width="100" show-overflow-tooltip></el-table-column>
<el-table-column v-if="settings[5].show" prop="deptArchitectureName" label="所在部门" min-width="100"></el-table-column>
<el-table-column v-if="settings[6].show" prop="createTime" label="创建日期" min-width="140"></el-table-column>
<el-table-column v-if="settings[7].show" prop="roleName" label="授权角色" min-width="100"></el-table-column>
<el-table-column v-if="settings[8].show" prop="groupName" label="用户组" min-width="100"></el-table-column>
<el-table-column v-if="settings[9].show" prop="lastLoginTime" label="最后登录时间" min-width="140"></el-table-column>
<el-table-column v-if="settings[10].show" label="操作" width="180">
<template slot-scope="scope">
<el-button type="text" @click="queryStaff(scope.row,true)">查看</el-button>
<el-button type="text" @click="queryStaff(scope.row,false)">编辑</el-button>
<el-button type="text" @click="resetPassword(scope.row)">重置密码</el-button>
<el-button type="text" @click="delStaff(scope.row)">删除</el-button>
<el-button v-auth type="text" @click="queryStaff(scope.row,true)">查看</el-button>
<el-button v-auth type="text" @click="queryStaff(scope.row,false)">编辑</el-button>
<el-button v-auth type="text" @click="resetPassword(scope.row)">重置密码</el-button>
<el-button v-auth type="text" @click="delStaff(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
@ -279,6 +278,10 @@ export default {
name: '账号',
show: true
},
{
name: '工号',
show: true
},
{
name: '手机号',
show: true
@ -377,7 +380,7 @@ export default {
};
},
mounted() {
this.$store.commit('user/SET_CRUMBS', [
this.$store.commit('user/setCrumbs', [
{
name: '用户管理'
},
@ -754,7 +757,7 @@ export default {
},
//
download() {
location.href = this.api.staffTemplate
util.downloadFile('用户导入模板.xlsx', this.api.staffTemplate)
},
//
handleExceed(files, fileList) {
@ -841,7 +844,6 @@ export default {
}
}
.list-wrap {
width: calc(100% - 340px);
margin-left: 20px;
width: calc(100% - 219px);
}
</style>

@ -5,8 +5,8 @@
<el-input placeholder="请输入用户组名称" v-model.trim="keyword" clearable></el-input>
</div>
<div class="actions">
<el-button type="primary" @click="add" >新增</el-button>
<el-button @click="batchDel">删除</el-button>
<el-button v-auth type="primary" @click="add" >新增</el-button>
<el-button v-auth @click="batchDel">删除</el-button>
</div>
</div>
@ -16,8 +16,8 @@
<el-table-column prop="description" label="角色描述" min-width="400" align="center"></el-table-column>
<el-table-column label="操作" width="170">
<template slot-scope="scope">
<el-button type="text" @click="edit(scope.row)">编辑</el-button>
<el-button type="text" @click="del(scope.row)">删除</el-button>
<el-button v-auth type="text" @click="edit(scope.row)">编辑</el-button>
<el-button v-auth type="text" @click="del(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
@ -78,7 +78,7 @@ export default {
}
},
mounted() {
this.$store.commit('user/SET_CRUMBS', [
this.$store.commit('user/setCrumbs', [
{
name: '用户管理'
},

@ -32,12 +32,10 @@ service.interceptors.request.use(config => {
service.interceptors.response.use(
response => {
const res = response.data;
console.log("🚀 ~ file: index.js ~ line 34 ~ res", res)
if (res.code == 200) {
return Promise.resolve(res).catch(e => {});
} else {
util.errorMsg(res.msg);
console.log("🚀 ~ file: index.js ~ line 39 ~ res", res)
return Promise.reject(res)
// return Promise.resolve(res).catch(e => {});
}

@ -4,11 +4,11 @@
const url = location.host;
const isDev = process.env.NODE_ENV === "development"; // 开发环境
const isPro = url.includes("occupationlab.com"); //是否生产
let host = `${location.origin}/`
let host = `${location.origin}:10000/`
if (isDev) {
// host = 'http://121.37.12.51/' // 中台测试服
host = 'http://192.168.31.136:10000/' // 测试服
// host = 'http://192.168.31.151:10000/' // 榕
host = 'http://192.168.31.137:10000/' // 赓
// host = 'http://192.168.31.137:10000/' // 赓
}
const Setting = {
@ -62,7 +62,7 @@ const Setting = {
// 相同路由,不同参数间进行切换,是否强力更新
sameRouteForceUpdate: false,
// 是否使用动态路由(即角色权限,开启了的话就会取后端返回的权限树来显示头部导肮和页面按钮)
dynamicRoute: false
dynamicRoute: true
};
export default Setting;

@ -2,25 +2,20 @@
* 权限管理
* */
export default {
namespaced: true,
state: {
btns: [],
routes: []
namespaced: true,
state: {
btns: [],
routes: []
},
mutations: {
addBtnAuth: (state, btns) => {
state.btns = btns
},
mutations: {
SET_BTN_AUTH: (state, btns) => {
state.btns = btns;
},
SET_ROUTE: (state, routes) => {
state.routes = routes;
}
},
actions: {
addBtnAuth({ state, commit }, btns) {
commit("SET_BTN_AUTH", btns);
},
addRoutes({ state, commit }, routes) {
commit("SET_ROUTE", routes);
}
addRoutes: (state, routes) => {
state.routes = routes
}
},
actions: {
}
};

@ -4,11 +4,15 @@
export default {
namespaced: true,
state: {
site: {}
site: {},
column: {} // 新增文章的时候获取的当前栏目
},
mutations: {
setSite: (state, site) => {
state.site = site
},
setColumn: (state, column) => {
state.column = column
}
},
actions: {

@ -1,8 +1,6 @@
import Setting from "@/setting";
import util from "@/libs/util";
import { post, get, del, put } from "@/plugins/requests/index.js";
import api from "@/api";
import addRoutes from "@/libs/route/addRoutes";
import Setting from '@/setting'
import util from '@/libs/util'
import addRoutes from '@/libs/route/addRoutes'
/**
* 用户信息
@ -16,16 +14,16 @@ export default {
crumbs: ''
},
mutations: {
SET_AVATAR: (state, avatar) => {
setAvatar: (state, avatar) => {
state.avatar = avatar
},
SET_USERID: (state, userId) => {
setUserId: (state, userId) => {
state.userId = userId
},
SET_USERNAME: (state, userName) => {
setUserName: (state, userName) => {
state.userName = userName
},
SET_CRUMBS: (state, crumbs) => {
setCrumbs: (state, crumbs) => {
state.crumbs = crumbs
}
},

@ -175,8 +175,11 @@
}
.el-table {
border-bottom: 0;
th, td {
height: 44px;
padding: 0;
}
td {
padding: 5px 0;
.cell {
font-size: 12px;
color: #333;

Loading…
Cancel
Save