Просмотр исходного кода

校本课纲共编以及分享功能

OnePsycho 4 лет назад
Родитель
Сommit
29917fe393

+ 25 - 4
TEAMModelOS/ClientApp/src/components/syllabus/DragTree.vue

@@ -10,11 +10,11 @@
 						<!-- {{data.id}} -->
 						<Icon type="md-cube" :title="$t('syllabus.tree.hasResource')" v-if="data.rnodes && data.rnodes.length" />
 					</span>
-					<span class="custom-tree-tools" v-if="editable">
+					<span class="custom-tree-tools" v-if="(hasEditAuth(data) || $access.can('admin.*|Syllabus_Edit'))">
 						<Icon type="md-create" size="16" :title="$t('syllabus.tree.edit')" @click="onEditItem(node,data,$event)" />
 						<Icon type="md-add" size="16" :title="$t('syllabus.tree.add')" @click="onAddNode(node,data,$event)" />
-						<Icon type="md-remove" size="16" :title="$t('syllabus.tree.remove')" @click="remove(node,data)" />
-						<Icon type="md-share" v-if="isFirstLevel(data)" :title="isSchool ? $t('syllabus.tree.coEdit') : $t('syllabus.tree.share')"
+						<Icon type="md-remove" size="16" :title="$t('syllabus.tree.remove')" @click="remove(node,data)" v-if="!isFirstLevel(data) ||  (canDeleteChapter(data) && isFirstLevel(data))"/>
+						<Icon type="md-share" v-if="isFirstLevel(data) && canDeleteChapter(data)" :title="isSchool ? $t('syllabus.tree.coEdit') : $t('syllabus.tree.share')"
 							@click="doShare(data)" />
 					</span>
 				</span>
@@ -79,6 +79,7 @@
 					version: '',
 					type: '1',
 					children: [],
+					creatorId: this.$store.state.userInfo.TEAMModelId,
 					remark: '',
 					nodeKey: '',
 					pid: '',
@@ -233,6 +234,7 @@
 					newChild.nodeKey = newChild.id
 					newChild.pid = parentNode.id
 					newChild.code = parentNode.code
+					newChild.creatorId = this.$store.state.userInfo.TEAMModelId
 					newChild.children = []
 					newChild.resources = []
 					newChild.knowledges = []
@@ -286,11 +288,29 @@
 
 		},
 		computed: {
+			// 判断是否为一级节点
 			isFirstLevel() {
 				return data => {
 					return data.pid === this.volume.id
 				}
 			},
+			// 判断当前用户是否有当前节点的编辑权限(如果父节点有权限则下面的子节点相应都有操作权限)
+			hasEditAuth(){
+				return nodeData => {
+					let userId = this.$store.state.userInfo.TEAMModelId
+					// 判断是否为一级节点,如果是二级节点则需要拿对应的一级节点去做判断
+					let chapterId = nodeData.pid === this.volume.id ? nodeData.id : this.getChapterIdById(nodeData.id)
+					let chapterNode = this.treeDatas.find(i => i.id === chapterId)
+					console.log(this.volume);
+					return this.volume.creatorId === userId || (chapterNode.auth && chapterNode.auth.length && chapterNode.auth.map(i => i.tmdid).includes(userId))
+				}
+			},
+			// 判断当前用户是否可以删除当前章节
+			canDeleteChapter(){
+				return nodeData => {
+					return nodeData.creatorId === this.$store.state.userInfo.TEAMModelId
+				}
+			}
 		},
 		watch: {
 			// 监听课纲数据变化
@@ -307,7 +327,8 @@
 						firstNode.click();
 					})
 				},
-				immediate: true
+				immediate: true,
+				deep:true
 			},
 			// 监听课纲数据变化
 			volume: {

+ 95 - 28
TEAMModelOS/ClientApp/src/components/syllabus/InviteTeacher.vue

@@ -3,6 +3,14 @@
 		<div class="node-info">
 			<span>当前选择章节:</span>
 			<span class="node-name">{{ nodeInfo.title }}</span>
+			<br>
+			<br>
+			<div style="display: inline-block;" v-if="!isSchool">
+				<span>当前章节已分享教师:</span>
+				<!-- <span v-for="(item,index) in nodeInfo.auth" :key="item.tmdid" class="share-item">{{ item.tmdname }}( {{ item.tmdid }})</span> -->
+				<span v-if="!nodeInfo.auth || !nodeInfo.auth.length" style="color: #dacaca;">暂无数据</span>
+				<Tag closable color="success" v-for="(item,index) in nodeInfo.auth" :key="item.tmdid" @on-close="doDelShare(item,index)">{{ item.tmdname }}( {{ item.tmdid }})</Tag>
+			</div>
 		</div>
 		<div class="search-wrap" v-if="isSchool">
 			<Input v-model="searchVal"  placeholder="输入教师名字或ID查询..."
@@ -34,7 +42,7 @@
 					</div>
 					<p v-if="!curTeacher && hasSearchResult" class="search-none">暂未查询到相关结果</p>
 					<p v-if="hasSearchResult" class="re-search" @click="onReSearch">重新搜索</p>
-					<Button type="success" v-if="hasSearchResult"  @click="doShare">确认分享</Button>
+					<Button type="success" :laading="isShareLoading" v-if="hasSearchResult"  @click="doShare">确认分享</Button>
 				</div>
 			</div>
 		</div>
@@ -60,6 +68,7 @@
 		data() {
 			return {
 				isSchool:false,
+				isShareLoading:false,
 				hasSearchResult:false,
 				searchVal:'',
 				searchIdVal:'',
@@ -166,49 +175,100 @@
 				});
 			},
 			/* 修改共编权限 */
-			onSwitchChange(val,e){
-				let curVolume = this.$parent.$parent.curVolume
-				this.$api.syllabus.ShareTree({
-					"school": curVolume.school,
-					"scope": curVolume.scope,
-					"tmdInfo": [
-						{
-							"tmdid": val.id,
-							"tmdname": val.name
-						}
-					],
-					"coedit": true,
-					"share": false,
-					"issuer": this.$store.state.userInfo.TEAMModelId,
-					"opt": e ? 'add' : 'del',
-					"syllabusId": this.nodeInfo.id,
-					"syllabusName": this.nodeInfo.title,
-					"volumeId": curVolume.id,
-					"volumeName": curVolume.name
-				}).then(res => {
-					if(res.code === 200){
-						this.$Message.success('操作成功!')
+			onSwitchChange(val,isAdd){
+				this.sendShareApi(val.id,val.name,false,isAdd).then(res => {
+					this.$Message.success(isAdd ? '授权成功!' : '取消授权成功!')
+					if(isAdd){
+						this.nodeInfo.auth.push({
+							tmdid:val.id,
+							tmdname:val.name,
+							share:false,
+							coedit:true
+						})
+					}else{
+						this.nodeInfo.auth.splice(this.nodeInfo.auth.map(i => i.tmdid).indexOf(val.id),1)
 					}
-				}).catch(err => {
-					this.$Message.error(err)
 				})
 			},
 			/* 分享课纲操作 */
 			doShare(){
-				console.log(this.curTeacher);
-			}
+				let val = this.curTeacher
+				this.isShareLoading = true
+				this.sendShareApi(val.id,val.name,true,true).then(res => {
+					setTimeout(() => {
+						this.$Message.success('分享成功!')
+						this.nodeInfo.auth.push({
+							tmdid:val.id,
+							tmdname:val.name,
+							share:true,
+							coedit:false
+						})
+						this.isShareLoading = false
+						this.curTeacher = null
+						this.hasSearchResult = false
+						this.searchIdVal = ''
+					},500)
+				})
+			},
+			/* 取消分享操作 */
+			doDelShare(val,index){
+				this.$Modal.confirm({
+					title: '取消分享',
+					content: '确认取消对' + val.tmdname + '的分享?',
+					onOk: () => {
+						this.sendShareApi(val.tmdid,val.tmdname,true,false).then(res => {
+							this.nodeInfo.auth.splice(index,1)
+							this.$Message.success('取消分享成功!')
+							this.$forceUpdate()
+						})
+					}
+				});
+			},
+			/* 发送共编或者分享API请求 */
+			sendShareApi(toId,toName,isShare,isAdd){
+				return new Promise((r,j) => {
+					let curVolume = this.$parent.$parent.curVolume
+					this.$api.syllabus.ShareTree({
+						"school": curVolume.school,
+						"scope": curVolume.scope,
+						"tmdInfo": [
+							{
+								"tmdid": toId,
+								"tmdname": toName
+							}
+						],
+						"coedit": !isShare,
+						"share": isShare,
+						"issuer": this.$store.state.userInfo.TEAMModelId,
+						"opt": isAdd ? 'add' : 'del',
+						"syllabusId": this.nodeInfo.id,
+						"syllabusName": this.nodeInfo.title,
+						"volumeId": curVolume.id,
+						"volumeName": curVolume.name
+					}).then(res => {
+						if(res.code === 200){
+							r(200)
+						}
+					}).catch(err => {
+						this.$Message.error(err)
+						j(err)
+					})
+				})
+				
+			},
+			
 		},
 		mounted() {
 			this.isSchool && this.getAllTeacher()
 		},
 		computed:{
+			/* 判断当前用户是否已被授权 */
 			hasAuth(){
 				return id => {
 					if(!this.nodeInfo.auth){
 						return false
 					}else{
 						let matchItem = this.nodeInfo.auth.filter(i => i.tmdid === id)
-						console.log(matchItem)
 						if(matchItem.length && matchItem[0].coedit){
 							return true
 						}else{
@@ -241,6 +301,13 @@
 			}
 		}
 		
+		.share-item{
+			display: inline-block;
+			margin-left: 10px;
+			padding: 2px 5px;
+			background-color: #005C5F;
+		}
+		
 		.search-wrap{
 			.ivu-input-wrapper{
 				width: 300px;

+ 73 - 9
TEAMModelOS/ClientApp/src/view/syllabus/Syllabus.vue

@@ -17,7 +17,7 @@
 				<span style="color: #F0F0F0;font-size: 18px;font-weight: bolder;">个人课纲</span>
 			</div>
 			<Button @click="onSaveSyllabus" class="btn-save-modify" icon="md-folder"
-				v-if="$access.can('admin.*|Syllabus_Edit') && hasModify">存储变更</Button>
+				v-if="(hasSyllabusAuth || hasEditAuth(curNode)) && hasModify">存储变更</Button>
 		</div>
 		<div class="syllabus-content">
 			<div class="syllabus-left">
@@ -26,9 +26,9 @@
 						<span>册别清单</span>
 						<span class="syllabus-content-header-tools">
 							<Icon type="md-search" @click="doSearchVolume" />
-							<Icon type="md-create" @click="doEditVolume" v-if="$access.can('admin.*|Syllabus_Edit')"/>
-							<Icon type="md-trash" @click="doDeleteVolume" v-if="$access.can('admin.*|Syllabus_Edit')"/>
-							<Icon type="md-add" @click="doAddVolume" v-if="$access.can('admin.*|Syllabus_Edit')"/>
+							<Icon type="md-create" @click="doEditVolume" v-if="hasSyllabusAuth"/>
+							<Icon type="md-trash" @click="doDeleteVolume" v-if="hasSyllabusAuth"/>
+							<Icon type="md-add" @click="doAddVolume" v-if="hasSyllabusAuth"/>
 						</span>
 					</div>
 					<div style="width: 90%;" v-else>
@@ -56,13 +56,13 @@
 				<div class="syllabus-content-header">
 					<span>课纲目录</span>
 					<span class="syllabus-content-header-tools">
-						<Icon type="md-add" @click="isAddTreeModal = true" v-if="$access.can('admin.*|Syllabus_Edit')"/>
+						<Icon type="md-add" @click="isAddTreeModal = true" v-if="hasSyllabusAuth"/>
 					</span>
 				</div>
 				<div class="syllabus-tree-box">
 					<EmptyData :top="-240" v-if="!treeOrigin.length"></EmptyData>
 					<Tree ref="treeRef" :treeData="treeOrigin" :volume="curVolume"
-						:editable="$access.can('admin.*|Syllabus_Edit')" @onNodeClick="onNodeClick" @doShare="doShare" @addModifyId="addModifyId"v-else></Tree>
+						:editable="hasSyllabusAuth || hasEditAuth(curNode)" @onNodeClick="onNodeClick" @doShare="doShare" @addModifyId="addModifyId"v-else></Tree>
 				</div>
 			</div>
 			<div class="syllabus-right">
@@ -70,7 +70,7 @@
 					<span>关联资源</span>
 					<span class="syllabus-content-header-tools">
 						<!-- <Icon type="md-add" @click="onAddResource" v-if="curNode.id"/> -->
-						<Dropdown @on-click="onAddResource" v-if="curNode.id">
+						<Dropdown @on-click="onAddResource" v-if="curNode.id && (hasSyllabusAuth || hasEditAuth(curNode))">
 							<a href="javascript:void(0)" style="color: #ddd;">
 								添加资源
 								<Icon type="ios-arrow-down"></Icon>
@@ -312,11 +312,13 @@
 					"id": "",
 					"pid": "",
 					"title": "",
+					"creatorId": this.$store.state.userInfo.TEAMModelId,
 					"type": 1,
 					"children": [],
 					"rnodes": []
 				},
-				modifyIdArr:[]
+				modifyIdArr:[],
+				flatArr:[]
 			}
 		},
 		created() {
@@ -452,6 +454,9 @@
 						}).then((res) => {
 							if (res) {
 								this.volumeList.splice(this.activeVolumeIndex, 1);
+								this.treeOrigin = []
+								this.curNode.rnodes = []
+								this.curNode.id = ''
 								this.$Message.success("删除成功");
 								this.onVolumeClick(this.volumeList.length ? this.volumeList[this
 									.activeVolumeIndex] : null, this.activeVolumeIndex)
@@ -474,6 +479,10 @@
 				}).then(res => {
 					if (!res.error) {
 						this.treeOrigin = res.tree
+						this.getAllChild(this.treeOrigin.map(i => {
+							i.trees[0].auth = i.auth
+							return i.trees[0]
+						}))
 					} else {
 						this.$Message.warning(res.error);
 						this.treeOrigin = []
@@ -488,6 +497,7 @@
 			onAddTreeNode() {
 				this.nodeInfo.id = this.$tools.guid()
 				this.nodeInfo.pid = this.curVolume.id
+				this.nodeInfo.creatorId = this.$store.state.userInfo.TEAMModelId
 				// 统一传给树形组件的数据结构
 				this.treeOrigin.push({
 					auth:null,
@@ -846,7 +856,7 @@
 						"status": 1,
 						"name": this.addVolumeForm.name || this.getDefaultVolumeName,
 						"creatorId": this.$store.state.userInfo.TEAMModelId,
-						"school": this.$store.state.userInfo.schoolCode,
+						"school": this.isSchool ? this.$store.state.userInfo.schoolCode : '',
 						"scope": this.curScope,
 						"syllabusIds":[]
 					}
@@ -854,6 +864,7 @@
 						addVolumeParams.id = this.curVolume.id
 						addVolumeParams.name = this.curVolume.name
 						addVolumeParams.syllabusIds = this.allChapterIds || []
+						addVolumeParams.creatorId = this.curVolume.creatorId
 					}
 					// 发送新增或者编辑册别请求
 					this.$api.syllabus.SaveOrUpdateVolume(addVolumeParams).then(res => {
@@ -872,6 +883,45 @@
 					})
 				})
 				
+			},
+			
+			/* 获取整个树的章节与子节点归属 */
+			getAllChild(arr){
+				let result = []
+				arr.forEach(item => {
+					result.push({
+						chapterId:item.id,
+						children:this.flatChildren(item.children)
+					})
+				})
+				this.flatArr = result
+			},
+			
+			/* 递归拉平所有children */
+			flatChildren(children){
+				let result = []
+				const fn = (source)=>{
+				    source.forEach(i => {
+				    	result.push(i.id)
+				    	if(i.children.length){
+				    		fn(i.children)
+				    	}
+				    })
+				}
+				fn(children)
+				return result
+			},
+			
+			/* 根据某个节点ID换取它对应的章节ID */
+			getChapterIdById(id){
+				if(this.flatArr.map(i => i.chapterId).includes(id)){
+					return id
+				}else{
+					console.log(this.flatArr)
+					console.log(id);
+					let targetChapter = this.flatArr.find(i => i.children.includes(id))
+					return targetChapter.chapterId
+				}
 			}
 		},
 		computed: {
@@ -906,6 +956,20 @@
 				return item => {
 					return item.type !== 'item' && item.type !== 'paper' && item.type !== 'link'
 				}
+			},
+			hasEditAuth(){
+				return nodeData => {
+					if(!nodeData.id) return false
+					let userId = this.$store.state.userInfo.TEAMModelId
+					// 判断是否为一级节点,如果是二级节点则需要拿对应的一级节点去做判断
+					let chapterId = nodeData.pid === this.curVolume.id ? nodeData.id : this.getChapterIdById(nodeData.id)
+					let chapterNode = this.treeOrigin.find(i => i.id === chapterId)
+					return this.curVolume.creatorId === userId || (chapterNode.auth && chapterNode.auth.length && chapterNode.auth.map(i => i.tmdid).includes(userId))
+				}
+			},
+			// 是否可以操作课纲模块(个人课纲或者管理员或者有课纲权限)
+			hasSyllabusAuth(){
+				return !this.isSchool || this.$access.can('admin.*|Syllabus_Edit')
 			}
 		},
 	}