AbilityTree.vue 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825
  1. <template>
  2. <div class="ability-tree-container">
  3. <div class="left-box">
  4. <div class="chapter">
  5. <div style="width:90%">章节</div>
  6. <div class="addzy" @click="addFirstnode">
  7. <svg class="addicon" aria-hidden="true">
  8. <use xlink:href="#icon-jia"></use>
  9. </svg>
  10. </div>
  11. </div>
  12. <el-tree ref='treeRef' :data="tree" :props="defaultProps" node-key="id" :highlight-current="true" :current-node-key="pitchNow" default-expand-all :expand-on-click-node="false" :render-content="renderContent" @node-click="handleNodeClick" />
  13. </div>
  14. <div class="right-box">
  15. <div class="resource">
  16. <div class="resource-title">关联资源</div>
  17. <div class="changebtn" v-show="uploadList.length !==0" @click="changes">
  18. <el-button type="primary" size="small ">存储变更</el-button>
  19. </div>
  20. <div class="resourceadd-box">
  21. <el-dropdown>
  22. <span class="el-dropdown-link">
  23. 新增资源
  24. <el-icon class="el-icon--right">
  25. <arrow-down />
  26. </el-icon>
  27. </span>
  28. <template #dropdown>
  29. <el-dropdown-menu>
  30. <el-dropdown-item @click="openUpload"><i class="el-icon-plus" @click="editAbility"></i>本地文件</el-dropdown-item>
  31. </el-dropdown-menu>
  32. </template>
  33. </el-dropdown>
  34. </div>
  35. </div>
  36. <div class="resourcebox" v-if="datais">
  37. <div class="resource-item" v-for="(item,index) in curNode" :key="item.id">
  38. <img src="@/assets/icon/image.png" v-if="item.type === 'image'" />
  39. <img src="@/assets/icon/word.png" v-else-if="item.type === 'doc' && docType.includes(getSuffix(item.title))" />
  40. <img src="@/assets/icon/excel.png" v-else-if="item.type === 'doc' && excelType.includes(getSuffix(item.title))" />
  41. <img src="@/assets/icon/ppt.png" v-else-if="item.type === 'doc' && pptType.includes(getSuffix(item.title))" />
  42. <img src="@/assets/icon/pdf.png" v-else-if="item.type === 'doc' && getSuffix(item.title) === 'pdf'" />
  43. <img src="@/assets/icon/video.png" v-else-if="item.type === 'video'" />
  44. <img src="@/assets/icon/audio.png" v-else-if="item.type === 'audio'" />
  45. <img src="@/assets/icon/item.png" v-else-if="item.type === 'item'" />
  46. <img src="@/assets/icon/folder.png" v-else-if="item.type === 'paper'" />
  47. <img src="@/assets/icon/link.png" v-else-if="item.type === 'link'" />
  48. <img src="@/assets/icon/zip.png" v-else-if="item.type === 'res'" />
  49. <img src="@/assets/icon/image.png" v-else-if="item.type === 'thum'" />
  50. <img src="@/assets/icon/unknow.png" v-else="item.type === 'other'" />
  51. <span class="title-name" @click=details(item)>{{index+1}}、{{item.title}}</span>
  52. <div class="resource-tools">
  53. <!-- <div class="node-resource-tool" >
  54. <Icon type="md-eye" />
  55. <span>{{ $t('syllabus.preview') }}</span>
  56. </div> -->
  57. <div class="resource-tool" @click="deleteResource(item,index)">
  58. <i class="el-icon-delete-solid"></i>
  59. <span>删除</span>
  60. </div>
  61. </div>
  62. </div>
  63. </div>
  64. <div class="none-data" v-else-if="datais ===false">
  65. 暂无数据
  66. </div>
  67. </div>
  68. </div>
  69. <!--资源预览-->
  70. <div class="previewState">
  71. <el-dialog v-model="previewStates" width="60%" center :before-close="closebtn">
  72. <p class="resource-title">{{detailsInfo.title}}</p>
  73. <!-- <img :src="detailsInfo.url" v-if="detailsInfo.type==='image'"> -->
  74. <el-image class="imagepreview" :src="detailsInfo.url" :preview-src-list="srcList" :initial-index="1" v-if="detailsInfo.type==='image'">
  75. </el-image>
  76. <video v-else-if="detailsInfo.type == 'video'" id="previewVideo" ref="videobox" :src="detailsInfo.url" width="870" controls="controls" autoplay style="max-height: 800px;">
  77. {{detailsInfo.title}}
  78. </video>
  79. <audio v-else-if="detailsInfo.type == 'audio'" controls>
  80. <source :src="detailsInfo.url">
  81. {{detailsInfo.title}}
  82. </audio>
  83. <template #footer>
  84. <span class="dialog-footer">
  85. <el-button @click="closebtn">关闭</el-button>
  86. </span>
  87. </template>
  88. </el-dialog>
  89. </div>
  90. <!--资源图片预览-->
  91. <!-- <div class="demo-image__preview">
  92. <el-image style="width: 100px; height: 100px" :src="detailsInfo.url" :preview-src-list="srcList" :initial-index="1" v-if="detailsInfo.type==='image'">
  93. </el-image>
  94. </div> -->
  95. <!-- <div class="demo-image__preview">
  96. <el-image style="width: 100px; height: 100px" :src="url" :preview-src-list="srcList" :initial-index="1">
  97. </el-image>
  98. </div> -->
  99. <!--资源图片预览end-->
  100. <!--资源预览end-->
  101. <!--上传资源-->
  102. <div class="uploadFile">
  103. <el-dialog v-model="uploadFiles" title="新增资源" width="30%">
  104. <el-upload ref="uploadRef" class="upload-demo" drag action="" :auto-upload="false" :on-change="uploadResource" :file-list="nomarl">
  105. <svg class="resource-upload" aria-hidden="true">
  106. <use xlink:href="#icon-yunduanshangchuan"></use>
  107. </svg>
  108. <div class="el-upload__text">
  109. 拖动文件至区域或<em>点击选择文件也可以上传</em>
  110. </div>
  111. </el-upload>
  112. <div class="upload-submitbtn">
  113. <el-button type="primary" @click="confirmUpload(),uploadBtn=true" :loading="uploadBtn">确认上传</el-button>
  114. </div>
  115. </el-dialog>
  116. </div>
  117. <!--上传资源end-->
  118. </template>
  119. <script>
  120. import { ref, reactive, onMounted, getCurrentInstance, watch, nextTick } from 'vue'
  121. import { ElMessage, ElMessageBox } from 'element-plus'
  122. import { useStore } from 'vuex'
  123. import BlobTool from '@/until/blobTool.js'
  124. export default {
  125. props: {
  126. tree: {
  127. type: Array,
  128. default: null,
  129. },
  130. defaultinfo: {
  131. type: String,
  132. default: null,
  133. },
  134. stand: {
  135. default: null,
  136. },
  137. abilityId: {
  138. type: String,
  139. default: null,
  140. },
  141. datas: {
  142. type: Array,
  143. default: null,
  144. },
  145. areaId: {
  146. default: null,
  147. },
  148. },
  149. setup(props, context) {
  150. let curNode = ref(null)
  151. const store = useStore()
  152. let { proxy } = getCurrentInstance()
  153. let defaultProps = {
  154. children: 'children',
  155. title: 'title',
  156. id: 'id',
  157. }
  158. let pitchNow = ref('')
  159. let treeRef = ref()
  160. const docType = ['doc', 'docx']
  161. const excelType = ['xls', 'csv', 'xlsx']
  162. const pptType = ['ppt', 'pptx']
  163. console.log(props, '控件接收的值')
  164. let resourceData = reactive([])
  165. let previewStates = ref(false)
  166. let detailsInfo = ref({
  167. id: '',
  168. title: '',
  169. url: '',
  170. type: '',
  171. })
  172. let nowPitchCb = ref()
  173. let datais = ref(false)
  174. let uploadFiles = ref(false)
  175. let fileList = ref({
  176. id: '',
  177. title: '',
  178. })
  179. let uploadFileData = ref({})
  180. let uploadBtn = ref(false)
  181. let uploadList = ref([])
  182. let changeShow = ref(false)
  183. let BlobContent = ref({})
  184. //watch判断用,上传后不重新赋值
  185. let watchModel = ref(true)
  186. let uploadRef = ref()
  187. let nomarl = ref([])
  188. let videobox = ref()
  189. let srcList = ref([])
  190. onMounted(() => {
  191. resourceData = resourceData.push(...props.tree)
  192. console.log(props.tree, '树状')
  193. })
  194. //添加子节点
  195. function append(data) {
  196. console.log(data, '传进方法的内容')
  197. console.log(props, '获取到的')
  198. let datas = data
  199. let user = JSON.parse(localStorage.getItem('userData'))
  200. ElMessageBox.prompt('输入新节点名称', '新增节点', {
  201. confirmButtonText: '确认',
  202. cancelButtonText: '取消',
  203. })
  204. .then(({ value }) => {
  205. onSaveData('', 'add', data, value)
  206. })
  207. .catch(() => {})
  208. }
  209. //删除子节点defaultinfo
  210. function remove(node, data) {
  211. console.log(props, '获取现在的树状')
  212. console.log(nowPitchCb.value, '当前的数据')
  213. let user = JSON.parse(localStorage.getItem('userData'))
  214. console.log(props.stand, '删除查看当前的')
  215. console.log(node, data)
  216. ElMessageBox.confirm('确定要删除节点吗?', '温馨提示', {
  217. confirmButtonText: '确认',
  218. cancelButtonText: '取消',
  219. type: 'warning',
  220. }).then(() => {
  221. let receiveData = data
  222. const result = props.tree.every((item) => {
  223. return item.pid === receiveData.pid
  224. })
  225. console.log(result, '得到的结果')
  226. if (result) {
  227. deleteChapter(props.stand, receiveData.id, node)
  228. } else {
  229. let dataEvalue = nowPitchCb.value
  230. onSaveData(dataEvalue, 'delete')
  231. const parent = node.parent
  232. const children = parent.data.children || parent.data
  233. const index = children.findIndex((d) => d.id === data.id)
  234. children.splice(index, 1)
  235. }
  236. })
  237. }
  238. function handleNodeClick(data) {
  239. console.log(data, '当前点击的元素')
  240. curNode.value = data.rnodes
  241. console.log(curNode.value, '资源数据')
  242. fileList.value.id = data.id
  243. fileList.value.title = data.title
  244. nowPitchCb.value = data
  245. data.rnodes.length ? (datais.value = true) : (datais.value = false)
  246. // console.log(curNode.value.title)
  247. }
  248. //渲染tree
  249. function renderContent(h, { node, data }) {
  250. return h(
  251. 'span',
  252. {
  253. class: 'custom-tree-node',
  254. title: data.title,
  255. },
  256. h('span', null, data.title),
  257. h(
  258. 'i',
  259. data.rnodes && data.rnodes.length ? { class: 'tree-icon' } : { class: 'tree-none' },
  260. <svg class="treeResource" aria-hidden="true">
  261. <use xlink:href="#icon-ziyuan"></use>
  262. </svg>
  263. ),
  264. h(
  265. 'span',
  266. {
  267. class: 'tree-node-tools',
  268. },
  269. h(
  270. 'a',
  271. {
  272. onClick: (e) => {
  273. e.stopPropagation()
  274. append(data)
  275. },
  276. },
  277. <i class="el-icon-plus"></i>
  278. ),
  279. h(
  280. 'a',
  281. {
  282. onClick: () => remove(node, data),
  283. },
  284. <i class="el-icon-minus"></i>
  285. )
  286. )
  287. )
  288. }
  289. function getSuffix(name) {
  290. return name.substr(name.lastIndexOf('.') + 1)
  291. }
  292. //查看资源详情
  293. function details(val) {
  294. // detailsInfo = val
  295. console.log(val, '查看详情传进来的值')
  296. console.log(detailsInfo, '赋值过后')
  297. detailsInfo.value = {}
  298. let bolbs = JSON.parse(localStorage.getItem('blobInfo'))
  299. let host = getBlobHost(bolbs.osblob_uri)
  300. let space = bolbs.osblob_uri.slice(bolbs.osblob_uri.indexOf('cn') + 3)
  301. let urls = host + '/' + space + val.link + '?' + bolbs.osblob_sas
  302. if (getSuffix(val.title.toLowerCase()) == 'pdf') {
  303. window.open('https://www.teammodel.cn/web/viewer.html?file=' + encodeURIComponent(urls))
  304. } else if (val.type === 'doc') {
  305. window.open('https://view.officeapps.live.com/op/view.aspx?src=' + encodeURIComponent(urls))
  306. } else if (val.type === 'image') {
  307. detailsInfo.value.title = val.title
  308. detailsInfo.value.type = val.type
  309. detailsInfo.value.id = val.id
  310. detailsInfo.value.url = urls
  311. detailsInfo.value.url ? (previewStates.value = true) : ''
  312. srcList.value.push(urls)
  313. } else {
  314. detailsInfo.value.title = val.title
  315. detailsInfo.value.type = val.type
  316. detailsInfo.value.id = val.id
  317. detailsInfo.value.url = urls
  318. detailsInfo.value.url ? (previewStates.value = true) : ''
  319. }
  320. }
  321. //打开上传组件 顺便处理uploadLIst
  322. function openUpload() {
  323. nomarl.value = []
  324. uploadFiles.value = true
  325. }
  326. //上传资源
  327. function uploadResource(val) {
  328. console.log(val, '触发了')
  329. uploadFileData.value = val.raw
  330. // fileList.value.push({ name: val.raw.name, size: val.raw.size, type: val.raw.type })
  331. // fileList.value.push(val)
  332. // return true
  333. }
  334. //确认上传
  335. function confirmUpload() {
  336. watchModel.value = false
  337. let urlHost = JSON.parse(localStorage.getItem('blobInfo'))
  338. let urlheader = urlHost.osblob_uri.substring(0, urlHost.osblob_uri.indexOf('cn') + 2)
  339. let space = urlHost.osblob_uri.slice(urlHost.osblob_uri.indexOf('cn') + 3)
  340. let standard = props.stand
  341. let nowid = fileList.value.id
  342. console.log(nowid)
  343. let url = urlHost.osblob_uri + '/yxpt/' + standard + '/jyzx/' + nowid + '/' + uploadFileData.value.name + '?/' + urlHost.osblob_sas
  344. console.log(url, '上传地址')
  345. let Blobs = new BlobTool(urlheader, space, '?' + urlHost.osblob_sas, 'school')
  346. BlobContent.value = Blobs
  347. let path = 'yxpt/' + standard + '/jyzx/' + nowid
  348. Blobs.upload(uploadFileData.value, path, {}, false, props.areaId).then((res) => {
  349. console.log(res, '上传成功的返回')
  350. res.url ? ElMessage.success('上传成功') : ElMessage.error('上传失败')
  351. uploadList.value.push(res)
  352. let datas = curNode.value
  353. datas.push({ title: res.name, link: res.blob, size: res.size, type: res.type, id: proxy.$access.guid(), cntr: 'teammodelos' })
  354. curNode.value = datas
  355. uploadBtn.value = false
  356. uploadFiles.value = false
  357. console.log(props, '后面的数据')
  358. })
  359. }
  360. //存储变更
  361. async function changes() {
  362. let data = nowPitchCb.value
  363. await onSaveData(data, 'save')
  364. setTimeout((watchModel.value = true), '2000')
  365. }
  366. //删除资源
  367. function deleteResource(val, index) {
  368. watchModel.value = false
  369. console.log(watchModel.value, '删除操作的值')
  370. let urlHost = JSON.parse(localStorage.getItem('blobInfo'))
  371. let urlheader = urlHost.osblob_uri.substring(0, urlHost.osblob_uri.indexOf('cn') + 2)
  372. let space = urlHost.osblob_uri.slice(urlHost.osblob_uri.indexOf('cn') + 3)
  373. console.log(val, index, uploadList, '删除的信息')
  374. ElMessageBox.confirm('确定要移除该资源吗?', '温馨提示', {
  375. confirmButtonText: '确定',
  376. cancelButtonText: '取消',
  377. type: 'warning',
  378. })
  379. .then(() => {
  380. console.log(BlobContent.value, 'BLOB的信息')
  381. let user = JSON.parse(localStorage.getItem('userData'))
  382. let blobs = {}
  383. BlobContent.value.containerClient ? (blobs = BlobContent.value) : ((blobs = new BlobTool(urlheader, space, '?' + urlHost.osblob_sas, 'school')), (BlobContent.value = blobs))
  384. blobs.deleteBlob(val.link).then((res) => {
  385. console.log(res, '删除的返回')
  386. if (res === 200) {
  387. curNode.value.splice(index, 1)
  388. let data = nowPitchCb.value
  389. onSaveData(data, 'deleteResource')
  390. } else {
  391. ElMessage.warning('删除失败')
  392. }
  393. })
  394. })
  395. .catch(() => {})
  396. }
  397. //添加当前父节点(tree一级@章节)
  398. function addFirstnode() {
  399. let user = JSON.parse(localStorage.getItem('userData'))
  400. ElMessageBox.prompt('输入新的章节节点名称', '新增节点', {
  401. confirmButtonText: '确认',
  402. cancelButtonText: '取消',
  403. }).then(({ value }) => {
  404. watchModel.value = false
  405. let ids = proxy.$access.guid()
  406. console.log(props, '这是添加第一级用到的父ID')
  407. let datsiof = []
  408. let newChild = { title: value, children: [], rnodes: [], id: ids, cids: [], creatorId: user.tmdId, creatorName: user.tmdName, pid: props.abilityId, order: 0 }
  409. datsiof.push(newChild)
  410. props.tree.push(newChild)
  411. console.log(props.tree, '查看现在的树')
  412. let dataInfo = { abilityId: props.abilityId, auth: [], codeval: props.stand, scope: 'standard', id: newChild.id, trees: datsiof }
  413. let datas = { tmdId: user.tmdId, tmdName: user.tmdName, standard: props.stand, abilityTask: [dataInfo] }
  414. proxy.$api.addChild(datas).then((res) => {
  415. console.log(res, '这是创建第一级的父节点的API返回')
  416. res.state === 200 ? (ElMessage.success('节点创建成功'), treeRef.value.setCurrentKey(res.recordAbilityTask.abilityTask[0].id)) : ElMessage.error('节点创建失败')
  417. })
  418. console.log(datas, '参数')
  419. })
  420. setTimeout((watchModel.value = true), '2000')
  421. }
  422. //删除父节点(tree一级@章节)
  423. function deleteChapter(standard, chapterId, node) {
  424. let user = JSON.parse(localStorage.getItem('userData'))
  425. let data = { standard: standard, id: chapterId, tmdId: user.tmdId, tmdName: user.tmdName }
  426. proxy.$api.removeChildnodes(data).then((res) => {
  427. console.log(res, '删除父节点的返回')
  428. if (res.state === 200) {
  429. ElMessage.success('节点删除成功')
  430. const parent = node.parent
  431. const children = parent.data.children || parent.data
  432. const index = children.findIndex((d) => d.id === data.id)
  433. children.splice(index, 1)
  434. } else {
  435. ElMessage.error('节点删除失败')
  436. }
  437. })
  438. }
  439. //处理HOST返回截取
  440. function getBlobHost(url) {
  441. let s = url || store.state.user.userProfile.blob_uri || store.state.user.studentProfile.blob_uri
  442. let pattern = /[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\.?/
  443. return s.split('//')[0] + '//' + s.match(pattern)[0]
  444. }
  445. //最后的保存数据操作
  446. function onSaveData(value, operate, dataWork, titleName) {
  447. let dataEvalue = value
  448. let data = dataWork
  449. let user = JSON.parse(localStorage.getItem('userData'))
  450. if (operate === 'add') {
  451. let ids = proxy.$access.guid()
  452. let newChild = { title: titleName, children: [], rnodes: [], id: ids, cids: [], creatorId: user.tmdId, creatorName: user.tmdName, pid: data.id, order: 0 }
  453. console.log(newChild)
  454. if (!data.children) {
  455. data.children = []
  456. }
  457. data.cids.push(newChild.id)
  458. data.children.push(newChild)
  459. dataEvalue = data
  460. }
  461. let chidData = []
  462. //寻找最上级
  463. for (let i in props.tree) {
  464. let dataOne = props.tree[i]
  465. if (dataEvalue.id === dataOne.id) {
  466. chidData.push(dataOne)
  467. } else if (dataEvalue.id !== dataOne.id && dataOne.children.length !== 0) {
  468. for (let y in dataOne.children) {
  469. if (dataEvalue.id === dataOne.children[y].id) {
  470. chidData.push(dataOne)
  471. } else if (dataEvalue.id !== dataOne.children[y].id && dataOne.children[y].children.length !== 0) {
  472. for (let u in dataOne.children[y].children) {
  473. dataEvalue.id === dataOne.children[y].children[u].id ? chidData.push(dataOne) : ''
  474. }
  475. }
  476. }
  477. }
  478. }
  479. //准备API参数
  480. let codeVals = ''
  481. let abilityIds = ''
  482. let scopes = ''
  483. let idInfo = ''
  484. for (let x in props.datas) {
  485. if (chidData[0].id === props.datas[x].id) {
  486. codeVals = props.datas[x].codeval
  487. abilityIds = props.datas[x].abilityId
  488. scopes = props.datas[x].scope
  489. idInfo = props.datas[x].id
  490. }
  491. }
  492. let msgInfo = ''
  493. let dataInfo = { abilityId: abilityIds, auth: [], codeval: codeVals, scope: scopes, id: idInfo, trees: chidData }
  494. let datas = { tmdId: user.tmdId, tmdName: user.tmdName, standard: props.stand, abilityTask: [dataInfo] }
  495. proxy.$api.addChild(datas).then((res) => {
  496. // operate === 'delete' ? (msgInfo = '节点删除') : ''
  497. // operate === 'add' ? (msgInfo = '节点创建') : ''
  498. // res.state === 200 ? ElMessage.success(`{{msgInfo}}成功`) : ElMessage.error(`{{msgInfo}}失败`)
  499. if (operate === 'add') {
  500. res.state === 200 ? ElMessage.success('节点创建成功') : ElMessage.error('节点创建失败')
  501. } else if (operate === 'delete') {
  502. res.state === 200 ? ElMessage.success('节点删除成功') : ElMessage.error('节点删除失败')
  503. } else if (operate === 'save') {
  504. res.state === 200 ? (ElMessage.success('储存变更成功'), (uploadList.value = [])) : ElMessage.error('储存变更失败')
  505. uploadFileData.value = []
  506. } else if (operate === 'deleteResource') {
  507. console.log(watchModel.value, '删除资源当前的值')
  508. res.state === 200
  509. ? (ElMessage.success('资源删除成功'),
  510. uploadList.value.forEach((item, index) => {
  511. item.blob === val.link ? uploadList.value.splice(index, 1) : ''
  512. }),
  513. setTimeout((watchModel.value = true), '2000'))
  514. : (ElMessage.error('资源删除失败'), setTimeout((watchModel.value = true), '2000'))
  515. }
  516. })
  517. }
  518. //查看资源 关闭视频
  519. function closebtn() {
  520. previewStates.value = false
  521. console.log(videobox, '视频')
  522. videobox.value ? videobox.value.pause() : ''
  523. }
  524. watch(
  525. props,
  526. (nweProps) => {
  527. nextTick(() => {
  528. console.log(nweProps.defaultinfo, '值')
  529. if (watchModel.value) {
  530. treeRef.value.setCurrentKey(nweProps.defaultinfo)
  531. fileList.value.id = nweProps.defaultinfo
  532. // curNode.value = nweProps.tree[0].rnodes
  533. console.log(nweProps)
  534. nweProps.tree.length !== 0 && nweProps.tree[0].rnodes ? (curNode.value = nweProps.tree[0].rnodes) : (curNode.value = [])
  535. }
  536. })
  537. },
  538. { immediate: true, deep: true }
  539. )
  540. return {
  541. curNode,
  542. defaultProps,
  543. append,
  544. remove,
  545. renderContent,
  546. handleNodeClick,
  547. getSuffix,
  548. docType,
  549. excelType,
  550. pptType,
  551. previewStates,
  552. details,
  553. detailsInfo,
  554. getBlobHost,
  555. datais,
  556. resourceData,
  557. pitchNow,
  558. treeRef,
  559. uploadFiles,
  560. uploadResource,
  561. fileList,
  562. confirmUpload,
  563. addFirstnode,
  564. uploadFileData,
  565. uploadBtn,
  566. uploadList,
  567. nowPitchCb,
  568. changes,
  569. deleteResource,
  570. deleteChapter,
  571. watchModel,
  572. openUpload,
  573. nomarl,
  574. uploadRef,
  575. onSaveData,
  576. closebtn,
  577. videobox,
  578. srcList,
  579. }
  580. },
  581. }
  582. </script>
  583. <style>
  584. .ability-tree-container {
  585. width: 100%;
  586. display: flex;
  587. justify-content: space-between;
  588. }
  589. .left-box {
  590. width: 600px;
  591. border-right: 1px dashed rgb(180, 178, 178);
  592. padding-right: 20px;
  593. height: 85vh;
  594. margin-top: 35px;
  595. overflow: hidden;
  596. }
  597. .left-box:hover {
  598. overflow-y: auto;
  599. }
  600. .left-box .el-tree {
  601. width: 600px;
  602. }
  603. .right-box {
  604. width: 54%;
  605. height: 85vh;
  606. margin-top: 35px;
  607. }
  608. .el-tree-node__content {
  609. height: 40px;
  610. position: relative;
  611. }
  612. .custom-tree-node {
  613. width: 80%;
  614. font-size: 14px;
  615. height: 40px;
  616. line-height: 40px;
  617. white-space: nowrap;
  618. overflow: hidden;
  619. text-overflow: ellipsis;
  620. }
  621. .tree-node-tools {
  622. position: absolute;
  623. right: 0;
  624. color: rgb(77, 130, 245);
  625. }
  626. .tree-node-tools a {
  627. font-size: 12px;
  628. margin-right: 10px;
  629. }
  630. /*章节样式*/
  631. .chapter {
  632. /* width: 600px !important; */
  633. position: sticky !important;
  634. top: 0px;
  635. z-index: 999;
  636. }
  637. .chapter,
  638. .resource {
  639. height: 40px;
  640. width: 100%;
  641. display: flex;
  642. align-items: center;
  643. padding-left: 15px;
  644. font-size: 14px;
  645. position: sticky;
  646. top: 0px;
  647. background-color: #e9eef3;
  648. z-index: 999;
  649. }
  650. .resource-title {
  651. width: 80%;
  652. display: inline-block;
  653. }
  654. .resourceadd-box {
  655. height: 40px;
  656. width: 80px;
  657. display: inline-block;
  658. padding-left: 15px;
  659. font-size: 18px;
  660. position: sticky;
  661. background-color: #e9eef3;
  662. z-index: 999;
  663. line-height: 55px;
  664. text-align: center;
  665. margin-left: 5%;
  666. border: 1px dashed #ccc;
  667. border-radius: 5px;
  668. padding: 5px;
  669. }
  670. .chapter::before,
  671. .resource::before {
  672. content: '';
  673. display: inline-block;
  674. border: 4px solid #16c18e;
  675. border-radius: 50%;
  676. margin-right: 10px;
  677. margin-bottom: 2px;
  678. }
  679. /*资源内容*/
  680. .resourcebox {
  681. display: flex;
  682. flex-direction: column;
  683. padding: 10px 20px;
  684. overflow: auto;
  685. }
  686. .resource-item {
  687. position: relative;
  688. display: flex;
  689. align-items: center;
  690. border-bottom: 1px solid rgb(229, 229, 229);
  691. padding: 10px 20px;
  692. }
  693. .resource-item img {
  694. width: 25px;
  695. margin-right: 20px;
  696. }
  697. .resource-tools {
  698. position: absolute;
  699. right: 30px;
  700. align-items: center;
  701. display: none;
  702. font-size: 12px;
  703. }
  704. .resource-tool {
  705. display: flex;
  706. align-items: center;
  707. margin-right: 15px;
  708. cursor: pointer;
  709. }
  710. .resource-item:hover .resource-tools {
  711. display: block;
  712. }
  713. .resource-item:hover {
  714. background-color: #d6d6d6;
  715. }
  716. .title-name {
  717. max-width: 70%;
  718. cursor: pointer;
  719. font-size: 14px;
  720. line-height: 1.5;
  721. color: #515a6e;
  722. }
  723. .left-box .tree-node-tools {
  724. display: none;
  725. }
  726. .left-box .el-tree-node__content:hover .tree-node-tools {
  727. display: inline-block;
  728. }
  729. .previewState .el-dialog__body {
  730. text-align: center;
  731. }
  732. .previewState .el-dialog__body .resource-title {
  733. font-size: 16px;
  734. font-weight: 700;
  735. }
  736. .previewState .el-dialog--center {
  737. background-color: #e9eef3;
  738. }
  739. .previewState .el-dialog__body img {
  740. max-width: 1100px;
  741. max-height: 600px;
  742. }
  743. .none-data {
  744. width: 100%;
  745. height: 85vh;
  746. font-size: 28px;
  747. font-weight: 800;
  748. margin: 0 auto;
  749. display: flex;
  750. justify-content: center;
  751. flex-direction: row;
  752. align-items: center;
  753. color: #ccc;
  754. }
  755. .tree-none {
  756. opacity: 0;
  757. }
  758. .tree-icon {
  759. opacity: 1;
  760. }
  761. .treeResource {
  762. width: 1.5em;
  763. height: 1.5em;
  764. vertical-align: -0.5em;
  765. fill: currentColor;
  766. overflow: hidden;
  767. margin-bottom: 1px;
  768. margin-left: 1%;
  769. }
  770. .resource-upload {
  771. width: 8em;
  772. height: 8em;
  773. vertical-align: -0.5em;
  774. fill: currentColor;
  775. overflow: hidden;
  776. margin-bottom: 1px;
  777. margin-left: 1%;
  778. margin-top: 8%;
  779. }
  780. .upload-demo {
  781. text-align: center;
  782. }
  783. .upload-submitbtn {
  784. width: 85%;
  785. margin: 0 auto;
  786. padding: 3%;
  787. margin-top: 5%;
  788. }
  789. .upload-submitbtn .el-button {
  790. width: 100%;
  791. }
  792. .addicon {
  793. width: 0.8em;
  794. height: 0.8em;
  795. /* vertical-align: -0.5em; */
  796. fill: currentColor;
  797. overflow: hidden;
  798. margin-bottom: 1px;
  799. margin-left: 1%;
  800. /* margin-top: 8%; */
  801. }
  802. .addzy:hover {
  803. cursor: pointer;
  804. }
  805. .changebtn {
  806. width: 100px;
  807. height: 40px;
  808. line-height: 40px;
  809. }
  810. .changebtn button {
  811. width: 100%;
  812. height: 40px;
  813. }
  814. .imagepreview {
  815. margin: 0 auto;
  816. max-width: 1100px;
  817. max-height: 600px;
  818. }
  819. #previewVideo {
  820. width: 100%;
  821. }
  822. </style>