Commit e3506c0f authored by 罗超's avatar 罗超

新增版章节

parent 58a79dac
......@@ -32,13 +32,12 @@ module.exports = function (ctx) {
// https://github.com/quasarframework/quasar/tree/dev/extras
extras: [
// 'ionicons-v4',
// 'mdi-v5',
'mdi-v5',
// 'fontawesome-v5',
// 'eva-icons',
// 'themify',
// 'line-awesome',
// 'roboto-font-latin-ext', // this or either 'roboto-font', NEVER both!
'roboto-font', // optional, you are not bound to it
'material-icons' // optional, you are not bound to it
],
......@@ -49,8 +48,8 @@ module.exports = function (ctx) {
env: ctx.dev ? {
//API: 'http://192.168.1.36:8300/api'
API: 'https://localhost:5001/api',
// API: 'http://192.168.20.24:8300/api',
// API: 'https://localhost:5001/api',
API: 'http://192.168.20.51:8088/api',
// API: 'http://testeduapi.oytour.com/api',
// API: 'http://192.168.20.9:8085/api',
// API: 'http://192.168.20.17:8017/api',
......@@ -158,7 +157,9 @@ module.exports = function (ctx) {
'QRadio',
'QBtnGroup'
],
// directives: [],
directives: [
'ClosePopup'
],
// Quasar plugins
plugins: [
......
......@@ -12,7 +12,7 @@ export default {
<style>
@import url('~assets/css/font.css');
@import url('//at.alicdn.com/t/font_2077629_1jbxfhyh7ir.css');
@import url('//at.alicdn.com/t/font_2077629_lgl3u1kdk1a.css');
html,
body,
......@@ -23,6 +23,9 @@ body,
font-family: -apple-system,BlinkMacSystemFont,'pingfang',' Microsoft YaHei',"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";
color: #3f4254;
}
.fullscreen{
z-index: 99999;
}
.q-position-engine{
z-index: 9999;
}
......
......@@ -203,6 +203,78 @@ export function queryChapterTree(data) {
})
}
/**
* 保存课程章节
* @param {JSON参数} data
*/
export function saveChapter(data) {
return request({
url: "/Course/SetChapter",
method: 'post',
data
})
}
/**
* 保存课程章节
* @param {JSON参数} data
*/
export function getCourseRate(data) {
return request({
url: "/Course/GetCourseRateEnumList",
method: 'post',
data
})
}
/**
* 保存课程章节
* @param {JSON参数} data
*/
export function deleteChapters(data) {
return request({
url: "/Course/BatchRemoveChapter",
method: 'post',
data
})
}
/**
* 保存课程章节
* @param {JSON参数} data
*/
export function setChaptersRate(data) {
return request({
url: "/Course/BatchSetChapterRate",
method: 'post',
data
})
}
/**
* 批量更新章节编号和ID
* @param {JSON参数} data
*/
export function batchUpdateChapterNo(data) {
return request({
url: "/Course/SetBatchChapterNo",
method: 'post',
data
})
}
/**
* 修改章节名称
* @param {JSON参数} data
*/
export function updateChapterName(data) {
return request({
url: "/Course/SetChapterName",
method: 'post',
data
})
}
/**
* 获取课程销售端口
*/
......
......@@ -69,7 +69,8 @@
},
watch: {
value(newVal, oldVal) {
if (!this.isInputChange && newVal) {
console.log("监听到变化1",newVal,this.ue.isReady,this.isInputChange)
if (!this.isInputChange) {
if (this.ue) {
if (this.ue.isReady !== 1) {
let self = this;
......@@ -84,6 +85,7 @@
}, 100);
return;
}
console.log("监听到变化",newVal)
this.ue.setContent(newVal);
} else {
this.tempContent = newVal;
......@@ -222,6 +224,9 @@
fileType +
'" class="ans-insertaudio-module" module="_insertaudio">' + ' </iframe></p>';
},
reloadNewValue(){
this.isInputChange=false
},
loadUe() {
const _this = this;
//上传附件
......
<template>
<div class="page-body">
<div class="page-body" style="height: calc(100% - 30px);">
<div class="page-search row items-center">
<div class="col row wrap q-mr-lg q-col-gutter-md">
</div>
<div class="col row wrap q-mr-lg q-col-gutter-md"></div>
<div class="page-option">
<q-btn color="accent" size="sm" class="q-mr-md" icon="add" label="编辑章节" @click="EditChapter(null)" />
<q-btn
color="accent"
size="sm"
class="q-mr-md"
icon="add"
label="编辑章节"
@click="EditChapter(null)"
/>
</div>
</div>
<div class="page-content">
<div class="q-table-container q-table-dense">
<el-table :data="data" style="width: 100%;margin-bottom: 20px;" row-key="ChapterId" border default-expand-all
:tree-props="{children: 'ChildList'}">
<el-table-column prop="ChapterName" label="目录">
<div class="page-content" style="height:calc(100% - 42px)">
<q-scroll-area
:thumb-style="thumbStyle"
:content-style="contentStyle"
:content-active-style="contentActiveStyle"
style="height: 100%; width: 100%;"
>
<el-table
:data="dataList"
v-loading="loading"
:expand-row-keys="expandKeys"
:default-expand-all="true"
:row-class-name="tableRowClassName"
class="tree-tab-chapter"
style="width: 100%;margin-bottom: 20px;"
row-key="ChapterId"
ref="chapterTab"
@row-click="rowsClick"
:tree-props="{ children: 'ChildList', hasChildren: 'hasChildren' }"
>
<el-table-column prop="date" label="章节" width="450">
<template slot-scope="scope">
<span>{{scope.row.ChapterNo}} {{scope.row.ChapterName}}</span>
<div style="display: inline-block;">
<div class="flex q-ml-md">
<div
class="catalog_num"
v-if="scope.row.ChapterNo.indexOf('.') == -1"
>
<span>
<i>{{ scope.row.ChapterNo }}</i>
</span>
</div>
<div
style="margin-left: 15px;"
v-if="scope.row.ChapterNo.indexOf('.') == -1"
>
{{ scope.row.ChapterName }}
</div>
<div
v-if="scope.row.ChapterNo.indexOf('.') != -1"
:style="{ marginLeft: 20 * (scope.row.level - 2) + 'px' }"
>
{{ scope.row.ChapterNo }}
</div>
<div
v-if="scope.row.ChapterNo.indexOf('.') != -1"
style="margin-left: 12px;"
>
{{ scope.row.ChapterName }}
</div>
</div>
</div>
</template>
</el-table-column>
<el-table-column prop="OpenStatus" label="开发状态" width="200">
<template slot-scope="scope" v-if="scope.row.OpenStatus==1||scope.row.OpenStatus==2">
<span>开放</span>
<el-table-column prop="name" label="课时" sortable width="100">
<template slot-scope="scope">
{{ scope.row.StudyHours }}课时
</template>
</el-table-column>
<el-table-column prop="address" label="章节详情" width="200">
<template slot-scope="scope">
<q-btn flat color="primary" v-if="scope.row.ChapterNo.indexOf('.') != -1" @click.stop="viewDetail(scope.row)">章节详情</q-btn>
</template>
</el-table-column>
<el-table-column prop="Progress" label="进度" width="200">
<el-table-column prop="address" label="状态" width="100">
<template slot-scope="scope">
<q-linear-progress stripe size="10px" :value="scope.row.Progress/100.0" />
<div class="text-negative" v-if="scope.row.OpenStatus == 0">
隐藏
</div>
<div class="text-dark" v-if="scope.row.OpenStatus == 1">开放</div>
</template>
</el-table-column>
<el-table-column label="操作" width="200">
<el-table-column label="操作">
<template slot-scope="scope">
<a>编辑</a>
&nbsp;
<a>设置</a>
<div class="text-right op-box">
<q-btn
size="xs"
class="q-mr-md"
color="dark"
@click.stop="EditChapter(scope.row.ChapterId)"
>修改</q-btn
>
<!--<q-btn
size="xs"
flat
color="primary"
@click.stop=""
class="q-mr-md"
>设置</q-btn
>-->
<q-btn
size="xs"
flat
color="negative"
@click.stop="deleteObj(scope.row)"
>删除</q-btn
>
</div>
</template>
</el-table-column>
</el-table>
</div>
</q-scroll-area>
</div>
<q-dialog v-model="isViewer" v-if="viewObj" style="width:70%;max-height:80%;">
<q-card>
<q-card-section class="row items-center q-pb-none">
<div class="text-h6">{{ viewObj.ChapterName }}</div>
<q-space />
<q-btn icon="close" flat round dense v-close-popup />
</q-card-section>
<q-card-section>
<div class="text-subtitle1 q-mb-md">章节学习内容</div>
<div v-html="viewObj.ChapterContent" v-if="viewObj.ChapterContent!=''" class="q-pa-md bg-grey-2 rounded-borders"></div>
<div class="text-grey-3 text-center" v-else>未添加内容</div>
</q-card-section>
<q-card-section>
<div class="text-subtitle1 q-mb-md">教学重点</div>
<div v-html="viewObj.Objectives" v-if="viewObj.ChapterContent!=''"></div>
<div class="text-grey-3 text-center" v-else>未添加内容</div>
</q-card-section>
<q-card-section>
<div class="text-subtitle1 q-mb-md">学生学习要求</div>
<div v-html="viewObj.Requirement" v-if="viewObj.ChapterContent!=''"></div>
<div class="text-grey-3 text-center" v-else>未添加内容</div>
</q-card-section>
</q-card>
</q-dialog>
</div>
</template>
<script>
import {
queryChapterTree
} from '../../api/course/index'
import {
queryChapterTree,
batchUpdateChapterNo,
deleteChapters
} from "../../api/course/index";
import { openURL } from "quasar";
export default {
meta: {
title: "章节管理"
},
computed: {},
watch: {},
data() {
return {
currentUrl: "",
selectedRowID: {},
dataList: [],
loading: true,
msg: {
CourseId: 0
},
CourseId: 0,
contentStyle: {
backgroundColor: "rgba(0,0,0,0.02)",
color: "#555"
},
contentActiveStyle: {
backgroundColor: "#eee",
color: "black"
},
export default {
meta: {
title: "章节管理"
thumbStyle: {
right: "2px",
borderRadius: "5px",
backgroundColor: "#027be3",
width: "5px",
opacity: 0.75
},
expandKeys: [],
updateChapters: [],
updateNo: false,
viewObj: null,
isViewer:false
};
},
created() {
if (this.$route.query.CourseId) {
this.CourseId = this.$route.query.CourseId;
this.msg.CourseId = this.CourseId;
}
},
mounted() {
this.currentUrl = this.$route.path;
this.getchaperTree();
},
methods: {
viewDetail(obj){
try {
obj.ChapterContent=decodeURIComponent(obj.ChapterContent)
obj.Objectives=decodeURIComponent(obj.Objectives)
obj.Requirement=decodeURIComponent(obj.Requirement)
} catch (error) {
}
this.viewObj=obj
this.isViewer=true
},
components: {
tableRowClassName({ row, rowIndex }) {
if (row.ChapterNo.indexOf(".") == -1) {
return "first-level-node";
}
return "";
},
computed: {
deleteObj(data) {
this.$q
.dialog({
title: "删除确认",
message:
"删除章节节点将会连同下属章节也会一并删除且无法恢复,你确定要这样执行吗",
cancel: {
label: "取消删除",
flat: true
},
ok: {
label: "确认",
flat: true,
focus: true,
color: "negative"
}
})
.onOk(() => {
deleteChapters({
CourseId: this.msg.CourseId,
ChapterNo: data.ChapterNo + ".",
ChapterId: data.ChapterId
}).then(r => {
this.updateNo = true;
this.getchaperTree();
//this.$refs.chapterTree.remove(data.ChapterId);
this.$q.notify({
icon: "iconfont icon-chenggong",
color: "accent",
timeout: 2000,
message: "删除成功!",
position: "top"
});
});
})
.onCancel(() => {
// console.log('>>>> Cancel')
});
},
watch: {
batchUpdate() {
batchUpdateChapterNo(this.updateChapters).then(r => {});
},
data() {
return {
currentUrl: "",
selectedRowID: {},
data: [],
loading: true,
msg: {
CourseId: 0,
},
CourseId: 0,
}
genernalNo(parentNo, list) {
list.forEach((x, i) => {
if (parentNo != "") {
x.ChapterNo = parentNo + "." + (i + 1);
} else {
x.ChapterNo = (i + 1).toString();
}
this.updateChapters.push({
ChapterNo: x.ChapterNo,
ChapterId: x.ChapterId,
ParentId: x.ParentId
});
if (x.ChildList && x.ChildList.length > 0) {
x.ChildList = this.genernalNo(x.ChapterNo, x.ChildList);
}
});
return list;
},
created() {
if (this.$route.query.CourseId) {
this.CourseId = this.$route.query.CourseId
this.msg.CourseId = this.CourseId;
}
rowsClick(row, column, event) {
//console.log(row,event)
this.$refs.chapterTab.toggleRowExpansion(row);
},
mounted() {
this.currentUrl = this.$route.path
this.getchaperTree();
//新增修改章节
EditChapter(obj) {
// this.$router.push({
// path: '/chapter-editor?courseId='+this.CourseId
// });
if (!obj) {
openURL(
window.location.origin +
"/#/course/chapter-editor?courseId=" +
this.CourseId
);
} else {
openURL(
window.location.origin +
"/#/course/chapter-editor?courseId=" +
this.CourseId +
"&chapter=" +
obj
);
}
},
methods: {
//新增修改章节
EditChapter(obj) {
//获取菜单分页列表
getchaperTree() {
this.loading = true;
queryChapterTree(this.msg)
.then(res => {
this.loading = false;
res.Data.forEach(x => {
this.expandKeys.push(x.ChapterId);
});
console.log(this.expandKeys);
},
//获取菜单分页列表
getchaperTree() {
this.loading = true;
queryChapterTree(this.msg).then(res => {
this.loading = false
this.data = res.Data;
}).catch(() => {
this.loading = false
this.dataList = res.Data;
if (this.updateNo) {
this.updateNo = false;
this.updateChapters = [];
this.genernalNo("", this.dataList);
if (this.updateChapters && this.updateChapters.length > 0) {
this.batchUpdate();
}
}
})
},
.catch(() => {
this.loading = false;
});
}
}
};
</script>
<style lang="sass">
@import url('~assets/css/table.sass')
<style>
.tree-tab-chapter thead {
display: none;
}
.tree-tab-chapter td {
border-bottom: none !important;
padding: 5px 0 !important;
}
.tree-tab-chapter::before {
display: none !important;
}
.tree-tab-chapter .el-table__expand-icon {
/* display: none !important; */
margin-right: 0 !important;
}
.tree-tab-chapter .catalog_num {
height: 20px;
padding-left: 14px;
background: #d0d5db;
border-radius: 10px;
margin: 10px 20px 0 0;
position: absolute;
left: 15px;
top: 50%;
margin-top: -10px;
}
.tree-tab-chapter .catalog_num > span {
min-width: 24px;
height: 24px;
padding: 4px;
margin: -2px -4px 0 0;
background: #d0d5db;
display: block;
border-radius: 20px;
}
.tree-tab-chapter .catalog_num > span > i {
min-width: 16px;
height: 16px;
padding: 0 2px;
line-height: 16px;
background: #fff;
font-size: 12px;
font-family: Arial;
color: #a8a8b3;
border-radius: 20px;
display: block;
text-align: center;
font-style: normal;
}
.tree-tab-chapter .first-level-node {
background-color: #f5f7fa !important;
}
.tree-tab-chapter .first-level-node td:first-child {
border-top-left-radius: 12px;
border-bottom-left-radius: 12px;
}
.tree-tab-chapter .first-level-node td:last-child {
border-top-right-radius: 12px;
border-bottom-right-radius: 12px;
}
.tree-tab-chapter tr .op-box {
display: none;
}
.tree-tab-chapter tr:hover .op-box {
display: block;
}
/**@import url('~assets/css/table.sass')*/
</style>
<template>
<div class="flex flex-start window-height">
<div class="q-pa-lg full-height" style="border-right:1px solid #f5f5f5;width:390px;">
<q-card class="q-pa-md bg-dark text-white q-mb-lg">
<span>{{courseInfo.CourseName}}</span>
</q-card>
<div class="q-gutter-xs q-pb-lg" style="border-bottom:1px solid #f5f5f5;">
<q-btn color="primary" size="xs" unelevated label="同级目录" @click="addSameLevel"></q-btn>
<q-btn color="primary" size="xs" unelevated label="子目录" @click="addChildLevel"></q-btn>
<q-btn color="primary" size="xs" title="向上移动" :disable="!canUp" @click="moveUp" outline icon="iconfont icon-up"></q-btn>
<q-btn color="primary" size="xs" title="向下移动" :disable="!canDown" @click="moveDown" outline icon="iconfont icon-down1"></q-btn>
<q-btn color="primary" size="xs" title="导入 ..." unelevated label="导入 ..."></q-btn>
</div>
<div class="q-mt-lg" style="height:calc(100% - 140px)">
<q-scroll-area
:thumb-style="thumbStyle"
:content-style="contentStyle"
:content-active-style="contentActiveStyle"
style="height: 100%; width: 100%;"
>
<el-tree ref="chapterTree" :default-expanded-keys="defaultChapterId" @node-click="changeNode" v-loading="canOptions" class="chapter-tree" :data="dataList" empty-text="暂无章节数据,请点击”添加同级“开始录入开始吧" :props="defaultProps" node-key="ChapterId" @node-drag-start="handleDragStart" @node-drag-enter="handleDragEnter" @node-drag-leave="handleDragLeave" @node-drag-over="handleDragOver" @node-drag-end="handleDragEnd" @node-drop="handleDrop" draggable :allow-drop="allowDrop" :allow-drag="allowDrag">
<div class="row chapter-node full-width" slot-scope="{ node, data }">
<div class="q-mr-md">{{ data.ChapterNo.length>1?data.ChapterNo:`0${data.ChapterNo}` }}</div>
<div class="col q-mr-xs" v-if="editorNodeId==data.ChapterId">
<input type="text" @click.stop="" @blur="changeChapterName(data)" maxlength="100" class="tree-input" v-focus v-model="data.ChapterName" @focus="selectValue($event)" />
</div>
<div class="col q-mr-md ellipsis" v-if="editorNodeId!=data.ChapterId">{{data.ChapterName}}</div>
<div class="oops-box q-mr-xs" v-if="editorNodeId!=data.ChapterId">
<q-btn size="xs" flat color="primary" label="编辑" @click.stop="editorNodeId=data.ChapterId"></q-btn>
<q-btn size="xs" flat color="negative" label="删除" @click.stop="deleteObj(data)"></q-btn>
</div>
<div class="q-mr-xs rate-box">
<q-badge class="bg-white text-grey-8">
{{data.CourseRateName.replace('课程','')}}
</q-badge>
<q-badge class="q-ml-xs bg-grey-3 text-dark">{{data.StudyHours}}课时</q-badge>
</div>
</div>
</el-tree>
</q-scroll-area>
</div>
</div>
<div class="col full-height q-pa-lg chapter-content scroll">
<div v-if="chapter">
<div class="text-h6 q-mb-md">章节学习内容</div>
<div class="row q-mb-md">
<div class="col q-mr-md">
<q-input square filled label="消耗课时" v-model="chapter.StudyHours" suffix="课时" mask="#" fill-mask="0" reverse-fill-mask></q-input>
</div>
<div class="col">
<q-select :options="rateList" option-label="Name" option-value="Id" square filled label="关联等级" v-model="defauRateObj"></q-select>
</div>
</div>
<div v-if="chapter.ParentId!=0">
<div class="text-h6 q-mb-md">章节学习内容</div>
<div class="q-mb-md">
<editor v-model="chapter.ChapterContent" @blur="changeContent" placeHolder="请输入章节学习内容" :config="config" ref="chapterContent"></editor>
</div>
<div class="text-h6 q-mb-md">教学重点</div>
<div class="q-mb-md">
<editor v-model="chapter.Objectives" placeHolder="请输入章节教学重点" :config="config" ref="objectives"></editor>
</div>
<div class="text-h6 q-mb-md">学生学习要求</div>
<div class="q-mb-md">
<editor v-model="chapter.Requirement" placeHolder="请输入章节学生学习要求" :config="config" ref="requirement"></editor>
</div>
</div>
<div v-else class="text-center text-h5 text-grey-4 q-mt-lg">单元节点不支持编辑相关内容</div>
</div>
</div>
<q-btn round padding="md" v-if="chapter && chapter.ChapterId>0" @click="saveChapterUpdate" :loading="submiting" color="primary" class="fixed-bottom-right" label="保存" style="z-index:9999999;right:20px;bottom:100px;">
<template v-slot:loading>
<q-spinner-ios />
</template>
</q-btn>
</div>
</template>
<script>
import editor from "../../components/editor/UeEditor";
import {
queryChapterTree,
saveChapter,
batchUpdateChapterNo,
updateChapterName,
getCourseRate,
queryCourseInfo,
deleteChapters,
setChaptersRate
} from "../../api/course/index";
import {compareObject} from '../../utils/validate'
import { extend } from 'quasar'
export default {
meta: {
title: "课程章节详情"
},
components: {
editor
},
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus()
}
}
},
data() {
return {
chapter: null,
config: {
initialFrameWidth: null,
initialFrameHeight: 400
},
showContent: true,
courseId: 0,
dataList: [],
defaultProps: {
children: 'ChildList',
label: 'ChapterName'
},
currentNode: null,
canOptions: true,
updateChapters: [],
editorNodeId: 0,
canUp:false,
canDown:false,
rateList:[],
defauRateObj:{
Id:8,
Name:"其它"
},
courseInfo:{},
submiting:false,
bakObj:{},
contentStyle: {
backgroundColor: 'rgba(0,0,0,0.02)',
color: '#555'
},
contentActiveStyle: {
backgroundColor: '#eee',
color: 'black'
},
thumbStyle: {
right: '2px',
borderRadius: '5px',
backgroundColor: '#027be3',
width: '5px',
opacity: 0.75
},
defaultChapterId:0
};
},
created() {
if(this.$route.query.chapter){
this.defaultChapterId=this.$route.query.chapter
}
console.log(this.$route.query);
if (this.$route.query.courseId) {
this.courseId = this.$route.query.courseId;
this.initTree();
this.initRateList();
this.getCourseInfo();
}
},
mounted() {
this.showContent = false;
setTimeout(() => {
this.showContent = true;
}, 3000);
},
methods: {
changeContent(){
},
getCourseInfo() {
queryCourseInfo({
CourseId: this.courseId
}).then(res => {
this.courseInfo = res.Data;
})
},
initRateList(){
getCourseRate({}).then(r=>{
this.rateList=r.Data
})
},
changeNode(data,node,ev){
if(this.chapter && this.chapter.ChapterId>0){
if(this.defauRateObj.Id!=0){
this.chapter.CourseRate=this.defauRateObj.Id
this.chapter.CourseRateName=this.defauRateObj.Name
}
if(!compareObject(this.bakObj,this.chapter,false)){
this.saveChapterUpdate()
if(this.bakObj.CourseRate!=this.chapter.CourseRate){
if(this.chapter.ChildList && this.chapter.ChildList.length>0){
this.updateRate()
this.updateRateNode(this.chapter.ChildList)
}
}
}
}
try {
data.ChapterContent=decodeURIComponent(data.ChapterContent)
data.Objectives=decodeURIComponent(data.Objectives)
data.Requirement=decodeURIComponent(data.Requirement)
} catch (error) {
}
data.StudyHours=data.StudyHours.toString()
this.chapter=data
extend(this.bakObj,data)
if(this.$refs.chapterContent){
this.$refs.chapterContent.reloadNewValue()
this.$refs.objectives.reloadNewValue()
this.$refs.requirement.reloadNewValue()
}
this.checkMove(node)
this.rateList.forEach(x=>{
if(x.Id==data.CourseRate){
this.defauRateObj=x
}
})
},
updateRate(){
setChaptersRate({
CourseRate:this.defauRateObj.CourseRate,
CourseId:this.courseId,
ChapterNo:this.chapter.ChapterNo+"."
}).then(r=>{
//this.initTree()
})
},
updateRateNode(arr){
arr.forEach(x=>{
x.CourseRate=this.defauRateObj.Id
x.CourseRateName=this.defauRateObj.Name
if(x.ChildList && x.ChildList.length>0){
this.updateRateNode(x.ChildList)
}
})
},
deleteObj(data){
this.$q.dialog({
title: '删除确认',
message: '删除章节节点将会连同下属章节也会一并删除且无法恢复,你确定要这样执行吗',
cancel: {
label: "取消删除",
flat: true
},
ok: {
label: "确认",
flat: true,
focus: true,
color:"negative"
}
}).onOk(() => {
deleteChapters({
CourseId:this.courseId,
ChapterNo:data.ChapterNo+".",
ChapterId:data.ChapterId
}).then(r=>{
//this.initTree()
this.$refs.chapterTree.remove(data.ChapterId)
this.updateChapters = []
this.genernalNo("",this.dataList)
if (this.updateChapters && this.updateChapters.length > 0) {
this.batchUpdate()
}
this.$q.notify({
icon: 'iconfont icon-chenggong',
color: 'accent',
timeout: 2000,
message: '删除成功!',
position: 'top'
})
})
}).onCancel(() => {
// console.log('>>>> Cancel')
})
},
saveChapterUpdate(){
if(!this.submiting){
this.submiting=true
if(this.defauRateObj.Id!=0){
this.chapter.CourseRate=this.defauRateObj.Id
this.chapter.CourseRateName=this.defauRateObj.Name
}
let msg={}
extend(msg,this.chapter)
msg.ChapterContent=encodeURIComponent(msg.ChapterContent)
msg.Objectives=encodeURIComponent(msg.Objectives)
msg.Requirement=encodeURIComponent(msg.Requirement)
saveChapter(msg).then(r => {
this.submiting=false
if(this.bakObj.CourseRate!=this.defauRateObj.Id){
if(this.chapter.ChildList && this.chapter.ChildList.length>0){
this.updateRate()
this.updateRateNode(this.chapter.ChildList)
}
extend(this.bakObj,this.chapter)
}
}).catch(e=>{
this.submiting=false
})
}
},
checkMove(node){
let noTemp=node.data.ChapterNo.split('.')
let no=parseInt(noTemp[noTemp.length-1])
let p=node.parent.data
this.canUp=no!=1
this.canDown=no!=p.length
},
moveUp(){
let data = this.$refs.chapterTree.getCurrentNode()
let node=this.$refs.chapterTree.getNode(data.ChapterId)
console.log(data)
if(node){
let noTemp=data.ChapterNo.toString().split('.')
let no=parseInt(noTemp[noTemp.length-1])-1
let p=node.parent.data
if(data.ParentId==0){
p=this.swapArray(p,no,no-1)
}else{
p.ChildList=this.swapArray(p.ChildList,no,no-1)
}
node.parent.childNodes=this.swapArray(node.parent.childNodes,no,no-1)
this.updateChapters = []
this.genernalNo("", this.dataList)
this.checkMove(this.$refs.chapterTree.getNode(data.ChapterId))
if (this.updateChapters && this.updateChapters.length > 0) {
this.batchUpdate()
}
}
},
moveDown(){
let data = this.$refs.chapterTree.getCurrentNode()
let node=this.$refs.chapterTree.getNode(data.ChapterId)
console.log(data)
if(node){
let noTemp=data.ChapterNo.toString().split('.')
let no=parseInt(noTemp[noTemp.length-1])-1
let p=node.parent.data
if(data.ParentId==0){
p=this.swapArray(p,no,no+1)
}else{
p.ChildList=this.swapArray(p.ChildList,no,no+1)
}
node.parent.childNodes=this.swapArray(node.parent.childNodes,no,no+1)
this.updateChapters = []
this.genernalNo("", this.dataList)
this.checkMove(this.$refs.chapterTree.getNode(data.ChapterId))
if (this.updateChapters && this.updateChapters.length > 0) {
this.batchUpdate()
}
}
},
swapArray(arr, index1, index2) {
arr[index1] = arr.splice(index2, 1, arr[index1])[0];
return arr;
},
selectValue(e) {
e.currentTarget.select();
},
changeChapterName(data){
this.editorNodeId=0
let msg={
ChapterId:data.ChapterId,
ChapterName:data.ChapterName
}
updateChapterName(msg).then(r=>{
})
},
addSameLevel() {
let temp = this.$refs.chapterTree.getCurrentNode()
if (!temp || temp.ParentId == 0) {
let no = this.dataList && this.dataList.length > 0 ? (this.dataList.length + 1) : 1
let t = this.createNewNode(0, no,8,'其它')
saveChapter(t).then(r => {
t.ChapterId=r.Data.ChapterId
this.dataList.push(t)
})
} else {
let parentTemp = this.$refs.chapterTree.getNode(temp.ParentId).data
let no = parentTemp.ChildList && parentTemp.ChildList.length > 0 ? (parentTemp.ChildList.length + 1) : 1
no = parentTemp.ChapterNo + "." + no
let t=this.createNewNode(parentTemp.ChapterId,no,parentTemp.CourseRate,parentTemp.CourseRateName)
saveChapter(t).then(r=>{
t.ChapterId=r.Data.ChapterId
parentTemp.ChildList.push(t)
})
}
},
addChildLevel() {
let temp = this.$refs.chapterTree.getCurrentNode()
if (!temp) {
let no = this.dataList && this.dataList.length > 0 ? (this.dataList.length + 1) : 1
let t = this.createNewNode(0, no, 8,'其它')
saveChapter(t).then(r => {
t.ChapterId=r.Data.ChapterId
this.dataList.push(t)
})
} else {
if (!temp.ChildList) {
this.$set(temp, 'ChildList', [])
}
let no = temp.ChildList && temp.ChildList.length > 0 ? (temp.ChildList.length + 1) : 1
no = temp.ChapterNo + "." + no
let t = this.createNewNode(temp.ChapterId, no,temp.CourseRate,temp.CourseRateName)
saveChapter(t).then(r => {
t.ChapterId=r.Data.ChapterId
temp.ChildList.push(t)
})
}
},
handleDragStart(node, ev) {
console.log('drag start', node);
},
handleDragEnter(draggingNode, dropNode, ev) {
console.log('tree drag enter: ', dropNode.label);
},
handleDragLeave(draggingNode, dropNode, ev) {
console.log('tree drag leave: ', dropNode.label);
},
handleDragOver(draggingNode, dropNode, ev) {
console.log('tree drag over: ', dropNode.label);
},
handleDragEnd(draggingNode, dropNode, dropType, ev) {
console.log(draggingNode, dropNode, dropType)
this.updateChapters = []
if (dropType == 'inner') {
draggingNode.data.ParentId = dropNode.data.ChapterId
} else {
draggingNode.data.ParentId = dropNode.data.ParentId
}
this.genernalNo("", this.dataList)
if (this.updateChapters && this.updateChapters.length > 0) {
this.batchUpdate()
}
},
handleDrop(draggingNode, dropNode, dropType, ev) {},
allowDrop(draggingNode, dropNode, type) {
// if (dropNode.data.ChapterName === '二级 3-1') {
// return type !== 'inner';
// } else {
return true;
//}
},
allowDrag(draggingNode) {
return true;
},
initTree() {
this.canOptions = true
queryChapterTree({
CourseId: this.courseId
}).then(r => {
console.log(r);
this.dataList = r.Data
this.canOptions = false
if(this.defaultChapterId!=0){
setTimeout(() => {
this.$refs.chapterTree.setCurrentKey(this.defaultChapterId)
let t=this.$refs.chapterTree.getNode(this.defaultChapterId)
this.changeNode(t.data,t,null)
}, 1000);
}
});
},
createNewNode(pid, no,rate,crn) {
if (this.canOptions) return;
let name = ""
if (pid == 0) {
name = `第${this.toChinesNum(no)}单元`
} else {
let d = no.split('.')
name = `第${this.toChinesNum(d[d.length-1])}课时`
}
return {
ChapterId: 0,
ParentId: pid,
ChapterContent: "",
ChapterName: name,
CourseId: this.courseId,
ChapterNo: no.toString(),
OpenStatus: 1,
Progress: 0,
Objectives: "",
Requirement: "",
StudyHours: 0,
ChildList: [],
CourseRate: rate,
CourseRateName:crn
}
},
toChinesNum(num) {
let changeNum = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']; //changeNum[0] = "零"
let unit = ["", "十", "百", "千", "万"];
num = parseInt(num);
let getWan = (temp) => {
let strArr = temp.toString().split("").reverse();
let newNum = "";
for (var i = 0; i < strArr.length; i++) {
newNum = (i == 0 && strArr[i] == 0 ? "" : (i > 0 && strArr[i] == 0 && strArr[i - 1] == 0 ? "" : changeNum[strArr[i]] + (strArr[i] == 0 ? unit[0] : unit[i]))) + newNum;
}
return newNum;
}
let overWan = Math.floor(num / 10000);
let noWan = num % 10000;
if (noWan.toString().length < 4) noWan = "0" + noWan;
return overWan ? getWan(overWan) + "万" + getWan(noWan) : getWan(num);
},
genernalNo(parentNo, list) {
list.forEach((x, i) => {
if (parentNo != "") {
x.ChapterNo = parentNo + "." + (i + 1)
} else {
x.ChapterNo = (i + 1).toString()
}
this.updateChapters.push({
ChapterNo: x.ChapterNo,
ChapterId: x.ChapterId,
ParentId: x.ParentId
})
if (x.ChildList && x.ChildList.length > 0) {
x.ChildList = this.genernalNo(x.ChapterNo, x.ChildList)
}
})
return list
},
batchUpdate() {
batchUpdateChapterNo(this.updateChapters).then(r => {
console.log(x)
})
}
}
};
</script>
<style>
.chapter-tree .chapter-node .oops-box,
.chapter-tree .chapter-node:hover .rate-box{
display: none;
}
.chapter-tree .chapter-node:hover .oops-box,
.chapter-tree .chapter-node .rate-box {
display: block;
}
.chapter-tree .el-tree-node__content {
height: 32px !important;
}
.chapter-tree .el-tree-node__content:hover,
.chapter-tree .is-current>.el-tree-node__content {
background: #eaeff7 !important;
}
.chapter-tree .el-tree-node__content{
border-radius: 4px;
}
.chapter-tree .tree-input {
outline: none;
border: none;
padding: 0 5px;
font-size: 14px;
width: 100%
}
</style>
......@@ -144,7 +144,7 @@
<q-item-label>恢复</q-item-label>
</q-item-section>
</q-item>
<q-item style="display:none;" clickable v-close-popup @click="goMycourse(props.row)">
<q-item clickable v-close-popup @click="goMycourse(props.row)">
<q-item-section>
<q-item-label>详情</q-item-label>
</q-item-section>
......
......@@ -84,15 +84,15 @@
<!-- <li :class="{'checkedLi':commonIndex==1}" @click="gotoPage('question',1)">
<i class="iconfont icon-tiku"></i>题库
</li> -->
<li :class="{'checkedLi':commonIndex==2}" @click="gotoPage('teachplan',2)">
<!-- <li :class="{'checkedLi':commonIndex==2}" @click="gotoPage('teachplan',2)">
<i style="font-size:20px;" class="iconfont icon-PPT"></i>教案
</li>
</li> -->
<li :class="{'checkedLi':commonIndex==3}" @click="gotoPage('chapter',3)">
<i class="iconfont icon-icon_zhangjielianxi"></i>章节
</li>
<li :class="{'checkedLi':commonIndex==4}" @click="gotoPage('coursejob',4)">
<!-- <li :class="{'checkedLi':commonIndex==4}" @click="gotoPage('coursejob',4)">
<i class="iconfont icon-icon_zhangjielianxi"></i>作业
</li>
</li> -->
</ul>
</div>
</q-list>
......
......@@ -698,6 +698,7 @@ const routes = [{
component: () =>
import("pages/course/chapter.vue")
},
{
path: "/course/coursejob", //作业管理
component: () =>
......@@ -845,7 +846,11 @@ const routes = [{
title: '资产管理'
},
},
{
path: "/course/chapter-editor", //章节管理
component: () =>
import("pages/course/chapterEditor.vue")
},
{
path: "*",
component: () =>
......
......@@ -24,4 +24,49 @@ export function validateUpperCase(str) {
export function validatAlphabets(str) {
const reg = /^[A-Za-z]+$/
return reg.test(str)
}
/** 比对数组是否相同 */
export function compareArray(arrA, arrB) {
let isSame = true
if (arrA.length !== arrB.length) {
return false
} else {
arrA.some((el, idx) => {
if (el !== arrB[idx]) {
isSame = false
return true
}
})
}
return isSame
}
/** 比对对象是否相同 */
export function compareObject(objA, objB,ignoreArray, endLoop) {
let isSame = true
let isArray = '[object Array]'
let isObject = '[object Object]'
for (var key in objA) {
if (objB[key] !== '' && !objB[key] && typeof objB[key] !== 'number') {
isSame = false
break
}
let type = Object.prototype.toString.call(objA[key])
if (type === isArray && ignoreArray) {
isSame = compareArray(objA[key], objB[key])
} else if (type === isObject) {
isSame = compareObject(objA[key], objB[key],ignoreArray)
} else if (objA[key] !== objB[key]) {
isSame = false
}
if (!isSame) {
return isSame
}
}
if (isSame && !endLoop) {
isSame = compareObject(objB, objA,ignoreArray, true)
}
return isSame
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment