documentPage.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. <template>
  2. <!-- 文档管理 -->
  3. <div class="document-file-page-wrap">
  4. <!-- 目录栏 -->
  5. <div class="catalog-wrap page-block-wrap catalog-block" id="left">
  6. <div class="btn-box">
  7. <el-button v-permission="permissionBtn.semanticPermission.docPage_save"
  8. type="primary" @click="toPage('addFile')">{{$t('SemanticsManage.DocumentManagement.add_document_btn')}}</el-button>
  9. </div>
  10. <div class="select-wrap">
  11. <el-select
  12. filterable remote
  13. :placeholder="$t('SemanticsManage.DocumentComparison.input_enter_fiel_content')"
  14. v-model="searchTitle"
  15. :remote-method="searchHandle"
  16. value-key="SaDocId"
  17. clearable
  18. >
  19. <i slot="prefix" class="el-input__icon el-icon-search"></i>
  20. <el-option
  21. v-for="item in searchOptions"
  22. :key="item.SaDocId"
  23. :label="item.Title"
  24. :value="item"
  25. >
  26. </el-option>
  27. </el-select>
  28. </div>
  29. <div class="catalog-list-wrap">
  30. <div class="catalog-list">
  31. <el-tree
  32. ref="catalogTree"
  33. class="catalog-tree other-tree"
  34. empty-text="暂无分类"
  35. :data="listData"
  36. node-key="nodeKeyId"
  37. :expand-on-click-node="true"
  38. :default-expanded-keys="expandKeys"
  39. draggable
  40. :allow-drag="checkAllowDrag"
  41. :allow-drop="checkAllowDrop"
  42. @node-drop="handleDropOver"
  43. @node-expand="handleNodeExpand"
  44. @node-collapse="handleNodeCollapse"
  45. @current-change="(data,node)=>{nodeChange(data,node)}"
  46. >
  47. <span class="custom-tree-node" slot-scope="{ data,node }"
  48. >
  49. <span class="tree-label">{{ data.label }}</span>
  50. <span style="display: flex; align-items: center"
  51. v-if="data.nodeKeyId===selectNodeKey"
  52. >
  53. <img
  54. :src="require('@/assets/img/set_m/edit.png')"
  55. alt="" v-if="node.level!==2&&isShowTreeBtn(node.level,'edit')"
  56. style="width: 14px; height: 14px; margin-right: 5px"
  57. @click.stop="clickNodeHandle('edit', data)"
  58. />
  59. <img
  60. :src="require('@/assets/img/data_m/move_ico.png')"
  61. alt="" v-if="node.level === 2"
  62. style="width: 14px; height: 14px; margin-right: 5px"
  63. />
  64. <img
  65. :src="require('@/assets/img/set_m/del.png')"
  66. alt="" v-if="isShowTreeBtn(node.level,'delete')"
  67. style="width: 14px; height: 14px; margin-right: 5px"
  68. @click.stop="clickNodeHandle('del', data)"
  69. />
  70. </span>
  71. </span>
  72. </el-tree>
  73. </div>
  74. </div>
  75. <div class="catalog-tool">
  76. <div class="add-catalog" @click="isModifyClassifyShow=true" v-if="isShowTreeBtn(1,'edit')">
  77. <img
  78. src="~@/assets/img/set_m/add_ico.png"
  79. alt=""
  80. style="width: 16px; height: 16px; margin-right: 6px"
  81. />
  82. <span>{{$t('SemanticsManage.DocumentManagement.add_category')}}</span>
  83. </div>
  84. <span class="total-text" v-if="selectNode&&model==='list'">
  85. {{$t('SemanticsManage.DocumentManagement.all_num_document',{num:catalogList.length})}}</span>
  86. </div>
  87. <span class="move-btn resize" v-drag id="resize"></span>
  88. </div>
  89. <div class="detail-wrap page-block-wrap catalog-block" id="right">
  90. <!-- 列表栏 -->
  91. <div class="detail-list overflow-hide-scrollbar" v-if="model==='list'">
  92. <!-- 选择一级分类不再展示列表 -->
  93. <!-- <draggable
  94. class="drag-cont"
  95. v-model="catalogList"
  96. animation="300"
  97. @start="dragStartHandler"
  98. @update="dragenter"
  99. @end="moveListItem"
  100. :disabled="true">
  101. <div class="list-item"
  102. v-for="item in catalogList" :key="item.nodeKeyId"
  103. @click="changeModel('file',item)"
  104. >
  105. <div class="item-title">
  106. <span>{{item.label}}</span>
  107. <img
  108. src="~@/assets/img/data_m/move_ico.png"
  109. style="width: 14px; height: 14px; margin-right: 8px"
  110. />
  111. </div>
  112. <div style="height:1px;background:#ECECEC;margin:0 -10px;"></div>
  113. <div class="item-image" :style="`background-image:url(${item.CoverImg?item.CoverImg:require('@/assets/img/document_m/default-img.png')})`"></div>
  114. <div style="height:1px;background:#ECECEC;margin:0 -10px;"></div>
  115. <div class="item-info">
  116. <span style="font-size:14px;">{{item.Theme}}</span>
  117. <span @click.stop>
  118. <el-dropdown @command="handleOperateCommand" trigger="click">
  119. <span class="el-dropdown-link">
  120. <i class="el-icon-more" style="font-size: 16px;cursor: pointer"/>
  121. </span>
  122. <el-dropdown-menu slot="dropdown">
  123. <el-dropdown-item :command="{key:'edit',data:item}">编辑</el-dropdown-item>
  124. <el-dropdown-item :command="{key:'del',data:item}">删除</el-dropdown-item>
  125. </el-dropdown-menu>
  126. </el-dropdown>
  127. </span>
  128. </div>
  129. </div>
  130. </draggable> -->
  131. <div class="empty" v-if="catalogList.length===0">
  132. <tableNoData :text="$t('Table.prompt_slogan')"/>
  133. </div>
  134. </div>
  135. <!-- 文件详情 -->
  136. <div class="detail-file" v-else>
  137. <div class="file-info">
  138. <ul>
  139. <li class="name">{{$t('SemanticsManage.DocumentManagement.document_name')}}:{{docInfo.Title}}</li>
  140. <!-- <li>文档主题:{{docInfo.Theme}}</li> -->
  141. <li>{{$t('SemanticsManage.DocumentManagement.document_category')}}:{{docInfo.ClassifyName}}</li>
  142. </ul>
  143. <el-button v-permission="permissionBtn.semanticPermission.docPage_save"
  144. type="primary" @click="handleEdit('file',selectNode)">{{$t('Table.edit_btn')}}</el-button>
  145. </div>
  146. <div class="file-content overflow-hide-scrollbar">
  147. <p v-for="block in docInfo.SectionList" :key="block.SaDocSectionId">{{block.innerText}}</p>
  148. </div>
  149. </div>
  150. </div>
  151. <!-- 添加/编辑分类弹窗 -->
  152. <el-dialog
  153. :title="classifyForm.classify_id? $t('SemanticsManage.DocumentManagement.edit_category') : $t('SemanticsManage.DocumentManagement.add_category') "
  154. :visible.sync="isModifyClassifyShow"
  155. :close-on-click-modal="false"
  156. :modal-append-to-body="false"
  157. @close="clearForm"
  158. width="589px"
  159. v-dialogDrag
  160. center
  161. >
  162. <div class="dialog-container">
  163. <el-form
  164. ref="formRef"
  165. label-position="left"
  166. hide-required-asterisk
  167. :model="classifyForm"
  168. :rules="classifyFormRules"
  169. >
  170. <el-form-item label-width="118px" :label="$t('SemanticsManage.DocumentManagement.add_category_name')" prop="classify_name">
  171. <el-input
  172. v-model="classifyForm.classify_name"
  173. style="width: 80%"
  174. :placeholder="$t('SemanticsManage.DocumentManagement.add_category_input_name')"
  175. />
  176. </el-form-item>
  177. <!-- 文档分类的封面图取消 -->
  178. <!-- <el-form-item label="封面图" prop="classify_img" ref="uploadImg">
  179. <el-upload
  180. action=""
  181. accept="image/png,image/jpg,image/jpeg"
  182. :http-request="handleUploadImg"
  183. :show-file-list="false"
  184. :key="uploadKey"
  185. >
  186. <div class="upload-box">
  187. <template v-if="!classifyForm.classify_img">
  188. <i class="el-icon-plus" style="font-size: 24px;"></i>
  189. <p class="form-hint">点击上传图片</p>
  190. </template>
  191. <template v-else>
  192. <img
  193. class="upload-img"
  194. :src="classifyForm.classify_img" alt="封面图"
  195. >
  196. <span class="upload-mask">
  197. <span
  198. class="mask-icon"
  199. @click.stop="handleRemove(file)"
  200. >
  201. <i class="el-icon-delete"></i>
  202. </span>
  203. </span>
  204. </template>
  205. </div>
  206. </el-upload>
  207. <p class="form-hint">支持格式:PNG、JPEG</p>
  208. </el-form-item> -->
  209. </el-form>
  210. </div>
  211. <div class="foot-container">
  212. <el-button @click="clearForm">{{ $t('Dialog.cancel_btn')}}</el-button>
  213. <el-button type="primary" @click="modifyClassify">{{ $t('Dialog.confirm_btn')}}</el-button>
  214. </div>
  215. </el-dialog>
  216. </div>
  217. </template>
  218. <script>
  219. /* js */
  220. import catalogMixin from "./mixins/catalogMixin";
  221. import { formatArr,formatFile } from './utils/index';
  222. /* components */
  223. //import draggable from 'vuedraggable';
  224. /* api */
  225. import {customInterence} from '@/api/api.js'
  226. import {documentInterface} from '@/api/modules/semanticsApi.js';
  227. export default {
  228. mixins:[catalogMixin],
  229. data() {
  230. return {
  231. classifyForm:{},//分类信息
  232. isModifyClassifyShow:false,//控制分类显示弹窗
  233. uploadKey:0,//刷新上传图片
  234. docInfo:{},//文档详情
  235. };
  236. },
  237. watch:{
  238. searchTitle(newVal){ //选中搜索结果
  239. const {SaDocId,ClassifyId} = newVal
  240. if(SaDocId&&ClassifyId){ //展开对应项
  241. this.handleNodeExpand({nodeKeyId:ClassifyId+''})
  242. this.nodeChange({SaDocId,nodeKeyId:`children_${SaDocId}`},{level:2})
  243. this.searchOptions = []
  244. }
  245. }
  246. },
  247. methods: {
  248. //搜索文档
  249. searchHandle(keyword){
  250. documentInterface.getDocumentList({
  251. PageSize:1000,
  252. CurrentIndex:1,
  253. Keyword:keyword
  254. }).then(res=>{
  255. if(res.Ret!==200) return
  256. this.searchOptions = res.Data.List||[]
  257. })
  258. },
  259. //获取分类列表
  260. async getListData(){
  261. await documentInterface.getClassifyList().then(res=>{
  262. if(res.Ret!==200) return
  263. this.listData = formatArr(res.Data||[])
  264. })
  265. },
  266. //获取文档详情
  267. getDetail(data){
  268. const {SaDocId} = data
  269. documentInterface.getDocumentDetail({
  270. DocId:Number(SaDocId)
  271. }).then(res=>{
  272. if(res.Ret!==200) return
  273. this.docInfo = formatFile(res.Data)
  274. })
  275. },
  276. //新增/编辑分类
  277. async modifyClassify(){
  278. let res = null
  279. let flag = false
  280. const {classify_id,classify_name,/* classify_img */} = this.classifyForm
  281. this.$refs.formRef.validate((valid) => {
  282. flag = valid
  283. })
  284. if(!flag) return
  285. if(classify_id){
  286. res = await documentInterface.editClassify({
  287. SaDocClassifyId:Number(classify_id),
  288. ClassifyName:classify_name,
  289. /* CoverImg:classify_img */
  290. })
  291. }else{
  292. res = await documentInterface.addNewClassify({
  293. ClassifyName:classify_name,
  294. /* CoverImg:classify_img */
  295. })
  296. }
  297. if(res.Ret!==200) return
  298. this.$message.success(`${classify_id ? this.$t('MsgPrompt.edit_msg') : this.$t('MsgPrompt.add_msg') }`)
  299. await this.getListData()
  300. if(classify_id){//编辑后,重新选中该分类
  301. const catalog = this.listData.find(item=>{return item.nodeKeyId===classify_id})
  302. catalog&&this.nodeChange(catalog,{level:1})
  303. }
  304. this.clearForm()
  305. },
  306. //删除分类
  307. async deleteClassify(data){
  308. await documentInterface.deleteClassify({
  309. SaDocClassifyId:Number(data.SaDocClassifyId)
  310. }).then(res=>{
  311. if(res.Ret!==200) return
  312. this.$message.success(this.$t('MsgPrompt.delete_msg'))
  313. this.clearForm()
  314. })
  315. },
  316. //删除文档
  317. async deleteDocument(data){
  318. await documentInterface.deleteDocument({
  319. SaDocId:Number(data.SaDocId)
  320. }).then(async res=>{
  321. if(res.Ret!==200) return
  322. this.$message.success(this.$t('MsgPrompt.delete_msg'))
  323. this.chooseDataClassify(data)
  324. })
  325. },
  326. /**
  327. * 文档分类封面图相关的代码,由于封面图取消这部分代码都没用到,不过还是留着吧
  328. */
  329. //删除已上传的图片
  330. handleRemove(e){
  331. this.classifyForm.classify_img=''
  332. this.uploadKey++
  333. },
  334. //上传图片
  335. async handleUploadImg(e){
  336. //console.log('upload',e.file);
  337. //验证图片类型
  338. if(!['image/png','image/jpg','image/jpeg'].includes(e.file.type)){
  339. this.$message.warning(this.$t('SemanticsManage.DocumentManagement.select_img_mag') )
  340. return
  341. }
  342. let form = new FormData()
  343. form.append("file", e.file)
  344. const res=await customInterence.upload(form)
  345. if(res.Ret===200){
  346. this.$refs.formRef&&this.$refs.formRef.clearValidate();
  347. this.classifyForm.classify_img=res.Data.ResourceUrl
  348. this.uploadKey++
  349. }
  350. },
  351. checkImg(rule,value,callback){
  352. if(!this.classifyForm.classify_img){
  353. return callback(new Error(this.$t('SemanticsManage.DocumentManagement.img_no_empty_msg') ))
  354. }else{
  355. callback()
  356. }
  357. },
  358. /**------------------ */
  359. //切换页面
  360. toPage(pageName,params){
  361. const routerPathMap = {
  362. 'addFile':'/addDocument',
  363. 'editFile':'/editDocument',
  364. 'tag':'/tagPage'
  365. }
  366. this.$router.push({
  367. path:routerPathMap[pageName],
  368. query:params||{}
  369. })
  370. },
  371. //移动文档
  372. moveDocument(moveParams){
  373. documentInterface.moveDocument(moveParams).then(async res=>{
  374. if(res.Ret!==200) return
  375. await this.getListData()
  376. this.handleNodeExpand({
  377. nodeKeyId: moveParams.SaDocClassifyId
  378. })
  379. this.nodeChange({
  380. SaDocId:moveParams.SaDocId,
  381. nodeKeyId:`children_${moveParams.SaDocId}`},
  382. {
  383. level:2
  384. })
  385. this.$message.success(this.$t('ETable.Msg.move_success_msg') )
  386. })
  387. },
  388. //根据层级判断是否展示编辑/删除按钮
  389. isShowTreeBtn(level,btnType){
  390. return level===1
  391. ?this.permissionBtn.isShowBtn('semanticPermission',`docPage_classifyOpt_${btnType}`)
  392. :this.permissionBtn.isShowBtn('semanticPermission',`docPage_${btnType==='edit'?'save':btnType}`)
  393. }
  394. },
  395. computed:{
  396. classifyFormRules(){
  397. return {
  398. classify_name:[{ required: true, message:this.$t('Chart.Vailds.classify_msg') }],
  399. }//分类校验规则
  400. }
  401. }
  402. };
  403. </script>
  404. <style lang="scss">
  405. @import "./css/catalogTree.scss";
  406. .document-file-page-wrap{
  407. .file-content{
  408. p{
  409. font-size: 16px !important;
  410. }
  411. }
  412. }
  413. </style>
  414. <style scoped lang="scss">
  415. @import "./css/basePage.scss";
  416. @import "./css/catalogPage.scss";
  417. .document-file-page-wrap{
  418. display: flex;
  419. width: 100%;
  420. .dialog-container{
  421. padding: 0 35px;
  422. .upload-box{
  423. position:relative;
  424. width:120px;
  425. height: 120px;
  426. background-color: #F5F7F9;
  427. border: 1px dashed #DCDFE6;
  428. display: flex;
  429. flex-direction: column;
  430. align-items: center;
  431. justify-content: center;
  432. &:hover{
  433. border: 1px dashed #409EFF;
  434. .upload-mask{
  435. opacity: 1;
  436. }
  437. }
  438. .upload-img,.upload-mask{
  439. width:100%;
  440. height:100%;
  441. }
  442. .upload-mask{
  443. position:absolute;
  444. left: 0;
  445. top: 0;
  446. cursor: default;
  447. text-align: center;
  448. color: #fff;
  449. opacity: 0;
  450. font-size: 20px;
  451. background-color: rgba(0,0,0,.5);
  452. transition: opacity .3s;
  453. z-index: 2;
  454. line-height: 120px;
  455. .mask-icon{
  456. cursor: pointer;
  457. }
  458. }
  459. }
  460. }
  461. .file-info{
  462. padding:20px 30px;
  463. display: flex;
  464. align-items: center;
  465. justify-content: space-between;
  466. }
  467. .file-content{
  468. padding:30px;
  469. }
  470. }
  471. </style>