浏览代码

删除调试内容

wuyunfeng 1 年之前
父节点
当前提交
8ab9327cf4
共有 36 个文件被更改,包括 1764 次插入336 次删除
  1. 0 0
      dist/static/fonts/element-icons.535877f5.woff
  2. 35 1
      languages/message-center/zh-CN.js
  3. 1 0
      public/domain.js
  4. 58 0
      src/api/message_template.js
  5. 58 0
      src/api/messages.js
  6. 67 0
      src/api/template_paramer.js
  7. 64 0
      src/components/AgGridCellRender/TagsCellRender.vue
  8. 4 4
      src/components/EditorjsTools/AudioTool/index.js
  9. 7 7
      src/components/EditorjsTools/ImageTool/index.js
  10. 32 16
      src/components/EditorjsTools/VideoTool/index.js
  11. 10 10
      src/components/FileManager/VueFinder.vue
  12. 8 8
      src/components/FileManager/components/Breadcrumb.vue
  13. 9 9
      src/components/FileManager/components/ContextMenu.vue
  14. 6 6
      src/components/FileManager/components/Explorer.vue
  15. 3 3
      src/components/FileManager/components/Toolbar.vue
  16. 1 1
      src/components/FileManager/components/modals/ModalDelete.vue
  17. 3 3
      src/components/FileManager/components/modals/ModalMove.vue
  18. 1 1
      src/components/FileManager/components/modals/ModalPreview.vue
  19. 6 6
      src/components/FileManager/components/modals/ModalUpload.vue
  20. 1 1
      src/components/FileManager/components/previews/Image.vue
  21. 3 2
      src/components/FileManager/components/previews/Text.vue
  22. 1 0
      src/icons/svg/messageTemplate.svg
  23. 1 0
      src/icons/svg/templateParamer.svg
  24. 1 0
      src/layout/components/TagsView/index.vue
  25. 12 13
      src/router/index.js
  26. 17 0
      src/store/modules/tagsView.js
  27. 3 1
      src/utils/enum/ErrorEnum.js
  28. 8 0
      src/utils/enum/MessageStatusEnum.js
  29. 0 181
      src/views/article-manager/index.vue
  30. 564 0
      src/views/message-center/message-template/index.vue
  31. 4 4
      src/views/message-center/message-type/index.vue
  32. 65 37
      src/views/message-center/messages/index.vue
  33. 127 19
      src/views/message-center/messages/message-edit.vue
  34. 581 0
      src/views/message-center/template-paramer/index.vue
  35. 0 1
      src/views/ncs-device/components/deviceManager.vue
  36. 3 2
      src/views/ncs-file-manager/index.vue

+ 0 - 0
dist/static/fonts/element-icons.535877f5.woff


+ 35 - 1
languages/message-center/zh-CN.js

@@ -4,12 +4,15 @@ module.exports = {
     messageCenter: '消息中心',
     messages: '消息列表',
     messageType: '消息分类',
+    messageTemplate: '消息模板',
+    templateParamer: '消息模板参数',
     messageTypeModule: {
       typeName: '分类名称',
 
       addType: '添加消息分类',
       editType: '修改消息分类',
-      typeNameRequired: '分类名称必填'
+      typeNameRequired: '分类名称必填',
+      MESSAGE_TYPE_DELETE_FAILED: '分类已被消息引用,不可删除!',
     },
     messagesModule: {
       addMessage: '添加消息',
@@ -19,8 +22,39 @@ module.exports = {
       titleRequired: '消息标题必填',
       openTypeRequired: '展示类型必填',
       messageTypeRequired: '消息分类必填',
+      boolShared: '是否共享消息',
+      status: '消息状态',
+      enabledStatus: '启用消息',
+      disabled: '无效',
+      enabled: '有效',
 
     },
+    messageTemplateModule: {
+      addMessageTemplate: '添加模版',
+      templateTitle: '模版标题',
+      templateContent: '模版内容',
+      editMessageTemplate: '修改模版',
+      templateTitleRequired: '模版标题必填',
+      templateContentRequired: '模版内容必填',
+      boolShared: '是否共享模版',
+      templateContentError: '模版参数{0}无效,请使用已定义模版参数,且不要嵌套使用参数',
+      insertParamerTip: '点击鼠标右键可以插入模版参数!',
+    },
+    templateParamerModule: {
+      addTemplateParamer: '添加参数',
+      paramerName: '参数名称',
+      paramerPreInput: '参数预设值',
+      allowInput: '允许自定义输入',
+      boolDate: '是否日期类型',
+      boolTime: '是否时间类型',
+      addValue: '添加值',
+      yes: '是',
+      no: '否',
+      paramNameRequired: '参数名称必填',
+      editParamer: '修改参数',
+      addParamer: '添加参数',
+      TEMPLATE_PARAMER_DELETE_FAILED: '参数已被模版消息引用,不可删除!',
+    },
     openTypeEnum: {
       video: '视频',
       audio: '音频',

+ 1 - 0
public/domain.js

@@ -4,6 +4,7 @@ const domain = {
   mediaUrl: 'http://192.168.1.198:8004',
   OnlineSystemUrl: 'http://api.base.wdklian.com',
   gateWayUrl:'http://192.168.1.198:8889',
+  fileServer: 'http://192.168.1.54:5001',
   apiMode: 'dev',
   uiVersion: 1, // 1 医院版,2 月子中心版,3养老院版
   enableBroadcast: true, //广播使能

+ 58 - 0
src/api/message_template.js

@@ -0,0 +1,58 @@
+import request from '@/utils/request'
+
+/**
+ * 消息模版接口
+ * @param params
+ * @returns {*|Promise|Promise<unknown>}
+ */
+export function getList(params) {
+  return request({
+    baseURL: domain.gateWayUrl,
+    url: '/message-center/template-message-tpl/page',
+    method: 'POST',
+    loading: true,
+    data: params,
+    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
+  })
+}
+
+/** 新增消息模版 */
+export function add(params) {
+  return request({
+    baseURL: domain.gateWayUrl,
+    url: '/message-center/template-message-tpl',
+    method: 'POST',
+    loading: true,
+    data: params
+  })
+}
+
+/** 删除消息模版 */
+export function remove(params) {
+  const ids = params.toString()
+  return request({
+    baseURL: domain.gateWayUrl,
+    url: `/message-center/template-message-tpl/${ids}`,
+    method: 'DELETE',
+    loading: true,
+    data: params
+  })
+}
+
+/** 更新消息模版 */
+export function update(id, params) {
+  return request({
+    baseURL: domain.gateWayUrl,
+    url: `/message-center/template-message-tpl/${id}`,
+    method: 'put',
+    data: params
+  })
+}
+/** 根据id查询消息模版 */
+export function get(id) {
+  return request({
+    baseURL: domain.gateWayUrl,
+    url: `/message-center/template-message-tpl/${id}`,
+    method: 'get'
+  })
+}

+ 58 - 0
src/api/messages.js

@@ -0,0 +1,58 @@
+import request from '@/utils/request'
+
+/**
+ * 消息类型接口
+ * @param params
+ * @returns {*|Promise|Promise<unknown>}
+ */
+export function getList(params) {
+  return request({
+    baseURL: domain.gateWayUrl,
+    url: '/message-center/messages/page',
+    method: 'POST',
+    loading: true,
+    data: params,
+    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
+  })
+}
+
+/** 新增消息 */
+export function add(params) {
+  return request({
+    baseURL: domain.gateWayUrl,
+    url: '/message-center/messages',
+    method: 'POST',
+    loading: true,
+    data: params
+  })
+}
+
+/** 删除消息 */
+export function remove(params) {
+  const ids = params.toString()
+  return request({
+    baseURL: domain.gateWayUrl,
+    url: `/message-center/messages/${ids}`,
+    method: 'DELETE',
+    loading: true,
+    data: params
+  })
+}
+
+/** 更新消息 */
+export function update(id, params) {
+  return request({
+    baseURL: domain.gateWayUrl,
+    url: `/message-center/messages/${id}`,
+    method: 'put',
+    data: params
+  })
+}
+/** 根据id查询消息 */
+export function get(id) {
+  return request({
+    baseURL: domain.gateWayUrl,
+    url: `/message-center/messages/${id}`,
+    method: 'get'
+  })
+}

+ 67 - 0
src/api/template_paramer.js

@@ -0,0 +1,67 @@
+import request from '@/utils/request'
+
+/**
+ * 模版参数接口
+ * @param params
+ * @returns {*|Promise|Promise<unknown>}
+ */
+export function getList(params) {
+  return request({
+    baseURL: domain.gateWayUrl,
+    url: '/message-center/template-message-paramer/page',
+    method: 'POST',
+    loading: true,
+    data: params,
+    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
+  })
+}
+
+/** 新增模版参数 */
+export function add(params) {
+  return request({
+    baseURL: domain.gateWayUrl,
+    url: '/message-center/template-message-paramer',
+    method: 'POST',
+    loading: true,
+    data: params
+  })
+}
+
+/** 删除模版参数 */
+export function remove(params) {
+  const ids = params.toString()
+  return request({
+    baseURL: domain.gateWayUrl,
+    url: `/message-center/template-message-paramer/${ids}`,
+    method: 'DELETE',
+    loading: true,
+    data: params
+  })
+}
+
+/** 更新模版参数 */
+export function update(id, params) {
+  return request({
+    baseURL: domain.gateWayUrl,
+    url: `/message-center/template-message-paramer/${id}`,
+    method: 'put',
+    data: params
+  })
+}
+
+/** 根据id查询模版参数 */
+export function get(id) {
+  return request({
+    baseURL: domain.gateWayUrl,
+    url: `/message-center/template-message-paramer/${id}`,
+    method: 'get'
+  })
+}
+
+export function getAll() {
+  return request({
+    baseURL: domain.gateWayUrl,
+    url: '/message-center/template-message-paramer/all',
+    method: 'get'
+  })
+}

+ 64 - 0
src/components/AgGridCellRender/TagsCellRender.vue

@@ -0,0 +1,64 @@
+
+<template>
+  <div class="tag-wrap">
+    <el-tag
+        v-for="item in tagList"
+        :key="item"
+        :type="tagType"
+        :closable="closable"
+        :size="tagSize">
+      {{ item }}
+    </el-tag>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "TagsCellRender",
+  data() {
+    return {
+      tagType: 'success',
+      tagSize: 'mini',
+      closable: false,
+      tagList: []
+    }
+  },
+  beforeMount() {
+  },
+  mounted() {
+    const _this = this
+    _this.tagList = this.params.list
+    const { tagType, tagSize, closable,tagList } = this.params
+    if (tagType) {
+      this.tagType = tagType
+    }
+    if (tagSize) {
+      this.tagSize = tagSize
+    }
+    if (closable) {
+      this.closable = closable
+    }
+    this.tagList=tagList
+  },
+  methods: {
+  }
+}
+</script>
+
+
+
+<style scoped>
+.el-tag{
+  margin-right: 5px;
+  margin-top: 5px;
+}
+
+.tag-wrap{
+  display: flex;
+  width: 100%;
+  flex-wrap: wrap;
+  align-items: flex-start;
+  justify-content: flex-start;
+}
+
+</style>

+ 4 - 4
src/components/EditorjsTools/AudioTool/index.js

@@ -21,7 +21,7 @@ export default class AudioTool {
       stretched: data.stretched !== undefined ? data.stretched : false
 
     }
-    console.log('thisdata', this.data)
+    // console.log('thisdata', this.data)
     this.config = config
     this.block = block
   }
@@ -80,7 +80,7 @@ export default class AudioTool {
       this.nodes.audio.src = this.data.src
       this.nodes.plusHolder.style.display = 'none'
       this.nodes.audio.style.display = 'block'
-      console.log(this.nodes.audio)
+      // console.log(this.nodes.audio)
     } else {
       this.nodes.audio.style.display = 'none'
       this.nodes.plusHolder.style.display = 'block'
@@ -129,13 +129,13 @@ export default class AudioTool {
   }
   set data(data) {
     this._data = Object.assign({}, this.data, data)
-    console.log('_data', this._data)
+    // console.log('_data', this._data)
     if (this.nodes.audio) {
       if (this._data.src) {
         this.nodes.audio.src = this._data.src
         this.nodes.plusHolder.style.display = 'none'
         this.nodes.audio.style.display = 'block'
-        console.log(this.nodes.audio)
+        // console.log(this.nodes.audio)
       } else {
         this.nodes.audio.style.display = 'none'
         this.nodes.plusHolder.style.display = 'block'

+ 7 - 7
src/components/EditorjsTools/ImageTool/index.js

@@ -36,7 +36,7 @@ export default class ImageTool {
       imageHolder: 'cdx-simple-image__picture',
       caption: 'cdx-simple-image__caption'
     }
-    console.log('api.i18n', this.api.i18n)
+    // console.log('api.i18n', this.api.i18n)
 
     this.tunes = [
       {
@@ -62,7 +62,7 @@ export default class ImageTool {
     }
   }
   render(data) {
-    console.log(this.block)
+    // console.log(this.block)
     const wrapper = this._make('div', [this.CSS.baseClass, this.CSS.wrapper],)
     const plusHolder = this._make('div', 'cdx-plus-holder', { onclick: () => { if (!this.readOnly) { this.config.onChoose(this.block.id) } }
     })
@@ -86,7 +86,7 @@ export default class ImageTool {
     const poparrow = this._make('div', ['el-loading-spinner'])
     const rechooseButton = this._make('button', [this.CSS.buttonClass], { innerHTML: this.api.i18n.t('Reselection Image'),
       onclick: () => {
-        this.config.onChoose(this.block.id)
+        this.config.onChoose(this.block.id,this.api.blocks.getCurrentBlockIndex())
       } })
 
     poparrow.appendChild(rechooseButton)
@@ -145,11 +145,11 @@ export default class ImageTool {
      */
   set data(data) {
     this._data = Object.assign({}, this.data, data)
-    console.log('_data', this._data)
+    // console.log('_data', this._data)
     if (this.nodes.image) {
       this.nodes.image.src = this._data.url
       this.nodes.plusHolder.style.display = 'none'
-      console.log(this.nodes.image)
+      // console.log(this.nodes.image)
     }
   }
 
@@ -164,7 +164,7 @@ export default class ImageTool {
     }
   }
   save(blockContent) {
-    console.log(blockContent)
+    // console.log(blockContent)
     const image = blockContent.querySelector('img')
     // caption = blockContent.querySelector('.' + this.CSS.input);
 
@@ -176,7 +176,7 @@ export default class ImageTool {
       url: image.src
       // caption: caption.innerHTML,
     })
-    console.log('returndata', r)
+    // console.log('returndata', r)
     return r
   }
 

+ 32 - 16
src/components/EditorjsTools/VideoTool/index.js

@@ -3,7 +3,7 @@ import './index.css'
 import videojs from 'video.js'
 import 'video.js/dist/video-js.css'
 export default class VideoTool {
-  constructor({ data, block, config }) {
+  constructor({ data, block, config, api }) {
     /**
          * Nodes cache
          */
@@ -15,7 +15,8 @@ export default class VideoTool {
       popOver: null,
       videoSource: null
     }
-
+    this.api = api
+    this.player = null
     this.data = {
       src: data.src || '',
       withBorder: data.withBorder !== undefined ? data.withBorder : false,
@@ -23,10 +24,9 @@ export default class VideoTool {
       stretched: data.stretched !== undefined ? data.stretched : false
 
     }
-    console.log('thisdata', this.data)
+    // console.log('thisdata', this.data)
     this.config = config
     this.block = block
-
   }
 
   static get toolbox() {
@@ -41,16 +41,20 @@ export default class VideoTool {
       src: url
     }
   }
+  afterRender() {
+    // videojs(`vedio_${this.block.id}`)
+  }
   render() {
     this.nodes.wrapper = this._make('div', '', { style: 'height:100px;' })
     this.nodes.video = this._make('video', 'video-js', { style: 'display:none;width:100%;', id: `vedio_${this.block.id}` })
-    this.nodes.videoSource = this._make('source')
+    this.nodes.videoSource = this._make('source', '', { type: 'video/mp4' })
     this.nodes.video.appendChild(this.nodes.videoSource)
     this.nodes.wrapper.classList.add('wrapper')
-    this.nodes.video.setAttribute('controls', 'controls')
+    this.nodes.video.setAttribute('controls', '')
+    this.nodes.video.setAttribute('preload', '')
     this.nodes.plusHolder = this._make('div', 'cdx-plus-holder', {
       onclick: () => {
-        this.config.onChoose(this.block.id)
+        this.config.onChoose(this.block.id, this.api.blocks.getCurrentBlockIndex())
       }
     })
     const plus = this._make('i', ['el-icon-plus'], {})
@@ -84,14 +88,16 @@ export default class VideoTool {
       this.nodes.videoSource.src = this.data.src
       this.nodes.plusHolder.style.display = 'none'
       this.nodes.video.style.display = 'block'
-      this.nodes.wrapper.style.height='500px'
+      this.nodes.wrapper.style.height = '500px'
+      const id = this.block.id
+
       setTimeout(() => {
-        videojs(`vedio_${this.block.id}`)
-      },0)
-      console.log(this.nodes.video)
+        this.player = videojs(`vedio_${id}`)
+      }, 500)
+      //
     } else {
       this.nodes.video.style.display = 'none'
-      this.nodes.wrapper.style.height='100px'
+      this.nodes.wrapper.style.height = '100px'
       this.nodes.plusHolder.style.display = 'block'
     }
 
@@ -99,7 +105,9 @@ export default class VideoTool {
   }
 
   save(blockContent) {
-    const src = blockContent.querySelector('video').src
+    const video = blockContent.querySelector('video')
+    const src = video.querySelector('source').src
+
     return {
       src
     }
@@ -136,6 +144,7 @@ export default class VideoTool {
     return true
   }
   set data(data) {
+    // console.log('setdata')
     this._data = Object.assign({}, this.data, data)
     if (this.nodes.video && this.nodes.videoSource) {
       if (this._data.src) {
@@ -143,8 +152,11 @@ export default class VideoTool {
         this.nodes.plusHolder.style.display = 'none'
         this.nodes.video.style.display = 'block'
         this.nodes.wrapper.style.height = '500px'
-        videojs(`vedio_${this.block.id}`)
-        console.log(this.nodes.video)
+        const id = this.block.id
+        setTimeout(function() {
+          videojs(`vedio_${id}`)
+        }, 500)
+        // console.log(this.nodes.video)
       } else {
         this.nodes.video.style.display = 'none'
         this.nodes.plusHolder.style.display = 'block'
@@ -152,5 +164,9 @@ export default class VideoTool {
       }
     }
   }
-
+  destroy() {
+    if (this.player) {
+      this.player.dispose()
+    }
+  }
 }

+ 10 - 10
src/components/FileManager/VueFinder.vue

@@ -129,7 +129,7 @@
                 }
                 Object.assign(this.app.data, data);
                 }
-                console.log('getdata',this.app.data,data)
+                // console.log('getdata',this.app.data,data)
                 this.$bus.$emit('vf-nodes-selected', {});
                 this.$bus.$emit('vf-explorer-update');
             },
@@ -148,7 +148,7 @@
             }
 
             this.$bus.$on('vf-nodes-selected', (items) => {
-                console.log('node selected')
+                // console.log('node selected')
                 this.app.selectedItems = items;
                 this.$bus.$emit('select', items);
             })
@@ -167,7 +167,7 @@
                             // 读取一个数据块。这个方法返回一个 Promise,当一个数据块被读取时,这个 Promise 就会解析为一个包含 done 和 value 属性的对象。done 属性表示是否已经读取完所有数据,value 属性是一个 Uint8Array,包含了读取到的数据块。
                             return reader.read().then(function processChunk({ done, value }) {
                                 if (done) {
-                                    console.log('下载完成');
+                                    // console.log('下载完成');
                                     // 将 chunks 数组中的所有数据块复制到一个新的 Uint8Array 中,然后使用这个 Uint8Array 创建一个 Blob 对象
                                     let data = new Uint8Array(receivedLength);
                                     let position = 0;
@@ -181,12 +181,12 @@
                                 chunks.push(value);
                                 // 更新已接收的数据长度。
                                 receivedLength += value.length;
-                                console.log(`已下载:${receivedLength},总大小:${contentLength}`);
+                                // console.log(`已下载:${receivedLength},总大小:${contentLength}`);
                                 // 递归调用 reader.read(),直到读取完所有数据。
                                 return reader.read().then(processChunk);
                             });
                         } else {
-                            console.log('下载失败')
+                            // console.log('下载失败')
                         }
                     })
                     .then((blob) => {
@@ -196,7 +196,7 @@
                         aEl.download = filename
                         aEl.click()
                         window.URL.revokeObjectURL(blobUrl)
-                        console.log("下载成功")
+                        // console.log("下载成功")
                     })
                     .finally(() => {
                         // xxx
@@ -213,7 +213,7 @@
                 // $a.remove();
             });
             this.$bus.$on('vf-fetch', ({params,url='',headers=null,responseType='json', method=null, body = null, onSuccess = null, onError = null, noCloseModal = false})=>{
-                console.log('v-fetch-method',method)
+                // console.log('v-fetch-method',method)
                 if (params&&['index', 'search'].includes(params.q)) {
                     if (this.controller) {
                         this.controller.abort();
@@ -232,7 +232,7 @@
                     responseType,
                     abortSignal: signal,
                 }).then(data => {
-                    console.log('movedata',data)
+                    // console.log('movedata',data)
                     // this.app.adapter = data.adapter;
                     if(method!=='MOVE'&&method!=='DELETE'&&method!=='MKCOL'){
                         this.app.data.dirname=url
@@ -256,7 +256,7 @@
                         onSuccess(data);
                     }
                 }).catch((e) => {
-                    console.error(e)
+                    // console.error(e)
                     if (onError) {
                         onError(e);
                     }
@@ -266,7 +266,7 @@
             this.$bus.$emit('vf-fetch', {params: {json:'',q: '', adapter: this.app.adapter, ...pathExists}});
 
             this.$bus.$on('vf-modal-show', (item) => {
-                console.log('modalshow',item)
+                // console.log('modalshow',item)
                 this.app.modal.active = true;
                 this.app.modal.type = item.type;
                 this.app.modal.data = item;

+ 8 - 8
src/components/FileManager/components/Breadcrumb.vue

@@ -98,7 +98,7 @@
         },
         watch:{
           query(newQuery){
-              console.log('query',newQuery)
+              // console.log('query',newQuery)
               this.$bus.$emit('vf-toast-clear');
               this.$bus.$emit('vf-search-query', {newQuery});
           }
@@ -110,13 +110,13 @@
             this.$bus.$on('vf-explorer-update', () => {
                 let items = [], links = [];
                 this.dirname = this.ServiceContainer.data.dirname
-               console.log('update-dirname',this.dirname)
+               // console.log('update-dirname',this.dirname)
                 // if (this.dirname.length == 0) {
                 //     links = [{title: '/', href: '/'}];
                 // }
 
                 let h = '/';
-                console.log('removeSuffix',this.removeSuffix(this.dirname, '/').split('/').slice(1))
+                // console.log('removeSuffix',this.removeSuffix(this.dirname, '/').split('/').slice(1))
                 for (const p of this.removeSuffix(this.dirname, '/').split('/').slice(1)) {
                     h += p+'/'
                     links.push({title: p, href: h.slice(0, -1)});
@@ -141,7 +141,7 @@
 
                 this.breadcrumb = links;
                 this.ServiceContainer.breadcrumb=links
-                console.log('links',links)
+                // console.log('links',links)
             })
         },
         methods: {
@@ -158,14 +158,14 @@
             },
             handleDropZone(e, index = null) {
                 e.preventDefault();
-                console.log('draggedItems',draggedItems)
+                // console.log('draggedItems',draggedItems)
                 this.handleDragLeave(e);
                 if(index!==-1){
                 index ??= this.breadcrumb.length - 2;
                 }
 
                 let draggedItems = JSON.parse(e.dataTransfer.getData('items'));
-                console.log('index',this.breadcrumb[index])
+                // console.log('index',this.breadcrumb[index])
 
                 // if (draggedItems.find(item => item.storage !== app.adapter)) {
                 //     alert('Moving items between different storages is not supported yet.');
@@ -178,7 +178,7 @@
                 })
             },
             handleDragOver(e){
-                console.log('breadcrumb-dragover')
+                // console.log('breadcrumb-dragover')
                 e.preventDefault();
 
 
@@ -204,7 +204,7 @@
             },
             removeSuffix(s, p){return s.endsWith(p) ? s.substring(0, s.length - p.length) : s},
             changeDir(item){
-                console.log('item',item)
+                // console.log('item',item)
                 this.$bus.$emit('vf-fetch', {url:item.href,params:{json:'', adapter: '' }})
             },
             goUp(){

+ 9 - 9
src/components/FileManager/components/ContextMenu.vue

@@ -48,7 +48,7 @@ export default {
 
           let selectItem = null
           const lastBreadcrumb = _this.ServiceContainer.breadcrumb[_this.ServiceContainer.breadcrumb.length-1]
-          console.log('lastBreadcrumb',lastBreadcrumb)
+          // console.log('lastBreadcrumb',lastBreadcrumb)
           if(lastBreadcrumb){
             selectItem=lastBreadcrumb
           }else{
@@ -115,7 +115,7 @@ export default {
              dir =name.slice(0,name.lastIndexOf('/'))
           }
 
-          console.log('dir',dir)
+          // console.log('dir',dir)
           _this.ServiceContainer.data.dirname=dir
           // _this.$bus.$emit('vf-fetch', {url:`${dir}`,params:{json:''}});
           _this.$bus.$emit('vf-search-exit');
@@ -162,7 +162,7 @@ export default {
     })
     this.$bus.$on('vf-contextmenu-show', ({event, area, items,  target = null}) => {
       this.context.items = [];
-      console.log('target',target)
+      // console.log('target',target)
       if (this.searchQuery) {
         if (target) {
           this.context.items.push(this.menuItems.openDir);
@@ -212,7 +212,7 @@ export default {
     filteredItems(){
 
       const {features}=this.ServiceContainer
-      console.log(this.context.items)
+      // console.log(this.context.items)
       return  this.context.items.filter(item => item.key == null || features.includes(item.key))
       // console.log('features',this.ServiceContainer.features,this.context.items,[...features])
       // return this.context.items.filter(item => item.key !== null)
@@ -230,16 +230,16 @@ export default {
 
 
       this.$nextTick(() => {
-        console.log('root',this.ServiceContainer.root)
+        // console.log('root',this.ServiceContainer.root)
         const rootBbox = this.ServiceContainer.root.getBoundingClientRect();
         const areaContainer = area.getBoundingClientRect();
 
         let left = event.pageX - rootBbox.left;
         let top = event.pageY - rootBbox.top;
-        console.log(
-                'ctxmenu',
-                this.$refs.contextmenu
-        )
+        // console.log(
+        //         'ctxmenu',
+        //         this.$refs.contextmenu
+        // )
         const refContextMenu = this.$refs.contextmenu
         let menuHeight = refContextMenu?refContextMenu.offsetHeight:0;
         let menuWidth = refContextMenu?refContextMenu.offsetWidth:0;

+ 6 - 6
src/components/FileManager/components/Explorer.vue

@@ -262,8 +262,8 @@
             },
             openItem(item){
                 if (item.path_type === 'Dir') {
-                    console.log(this.ServiceContainer.data.dirname)
-                    console.log('openitem',item)
+                    // console.log(this.ServiceContainer.data.dirname)
+                    // console.log('openitem',item)
                     this.$bus.$emit('vf-search-exit');
                     this.$bus.$emit('vf-fetch', {url:`${this.ServiceContainer.data.dirname==='/'?'':this.ServiceContainer.data.dirname}/${item.name}`,params:{json:''}});
                 } else {
@@ -322,12 +322,12 @@
                 e.dataTransfer.setDragImage(this.$refs.dragImage, 0, 15);
                 e.dataTransfer.effectAllowed = 'all';
                 e.dataTransfer.dropEffect = 'copy';
-                console.log('dragstart',this.getSelectedItems())
+                // console.log('dragstart',this.getSelectedItems())
                 e.dataTransfer.setData('items', JSON.stringify(this.getSelectedItems()))
             },
             handleDropZone(e,item){
                 e.preventDefault();
-                console.log('dropzone',item)
+                // console.log('dropzone',item)
                 let draggedItems = JSON.parse(e.dataTransfer.getData('items'));
 
                 if (draggedItems.find(item => item.storage !== app.adapter)) {
@@ -361,7 +361,7 @@
                 });
 
                 this.$bus.$on('vf-explorer-update', () => this.$nextTick(() => {
-                    console.log('vf-explorer-update')
+                    // console.log('vf-explorer-update')
                     this.ds.clearSelection();
                     this.ds.setSettings({
                         selectables: document.getElementsByClassName('vf-item-' + this.randId ),
@@ -391,7 +391,7 @@
                 });
 
                 this.ds.subscribe("callback", (	{ items, event, isDragging}) => {
-                    console.log('selectitems',this.getSelectedItems())
+                    // console.log('selectitems',this.getSelectedItems())
                     this.$bus.$emit('vf-nodes-selected', this.getSelectedItems());
                     this.selectedCount = this.ds.getSelection().length;
                 })

+ 3 - 3
src/components/FileManager/components/Toolbar.vue

@@ -172,7 +172,7 @@
         },
         mounted() {
             this.$bus.$on('vf-nodes-selected', (items) => {
-                console.log('select',items)
+                // console.log('select',items)
                 this.selectedItems = items
             })
             this.$bus.$on('vf-search-query', ({newQuery}) => {
@@ -196,7 +196,7 @@
                 // console.log('selectItem',selectItem)
 
                     const lastBreadcrumb = this.ServiceContainer.breadcrumb[this.ServiceContainer.breadcrumb.length-1]
-                    console.log('lastBreadcrumb',lastBreadcrumb)
+                    // console.log('lastBreadcrumb',lastBreadcrumb)
                     if(lastBreadcrumb){
                       selectItem=lastBreadcrumb
                     }else{
@@ -214,7 +214,7 @@
             createNewFolder(){
                 let selectItem = null
                 const lastBreadcrumb = this.ServiceContainer.breadcrumb[this.ServiceContainer.breadcrumb.length-1]
-                console.log('lastBreadcrumb',lastBreadcrumb)
+                // console.log('lastBreadcrumb',lastBreadcrumb)
                 if(lastBreadcrumb){
                     selectItem=lastBreadcrumb
                 }else{

+ 1 - 1
src/components/FileManager/components/modals/ModalDelete.vue

@@ -82,7 +82,7 @@ export default {
      return this.$t(str)
     },
     close(){
-     console.log('delete',this.items)
+     // console.log('delete',this.items)
       this.$bus.$emit('vf-modal-close')
     }
   }

+ 3 - 3
src/components/FileManager/components/modals/ModalMove.vue

@@ -75,7 +75,7 @@
     },
     methods:{
       move(){
-         console.log('items',this.items)
+         // console.log('items',this.items)
         if (this.items.length) {
           this.items.forEach((item,index)=>{
             this.$bus.$emit('vf-fetch', {
@@ -89,7 +89,7 @@
               headers:{'Destination':encodeURI(`${this.toItem.href}/${item.name}`)},
               responseType:'text',
               onSuccess: () => {
-                console.log('success')
+                // console.log('success')
                 // this.$bus.$emit('vf-toast-push', {label: this.$t('Files moved.', this.ServiceContainer.modal.data.items.to.name)});
                 if(index===this.items.length-1){
                   this.$bus.$emit('vf-fetch', {url:`${this.ServiceContainer.data.dirname==='/'?'':this.ServiceContainer.data.dirname}`,params:{json:''}});
@@ -105,7 +105,7 @@
         }
       },
       cancel(){
-        console.log(this)
+        // console.log(this)
         this.$bus.$emit('vf-modal-close')
       },
       t(item,...arg){

+ 1 - 1
src/components/FileManager/components/modals/ModalPreview.vue

@@ -92,7 +92,7 @@
                 const filename = this.ServiceContainer.modal.data.item.name
                 const ext = this.ServiceContainer.modal.data.item.ext
                 const txtfile = MODES.some(p => p.extRe.test(filename))
-                console.log('txtfile', txtfile, filename)
+                // console.log('txtfile', txtfile, filename)
                 if (txtfile) {
                     return 'text-preview'
                 } else if (new Set(['jpg', 'jpeg', 'gif', 'png', 'webp', 'avif', 'svg']).has(ext)) {

+ 6 - 6
src/components/FileManager/components/modals/ModalUpload.vue

@@ -225,7 +225,7 @@ export default {
   },
 
   buildReqParams() {
-    console.log('modalData',this.ServiceContainer.modal.data)
+    // console.log('modalData',this.ServiceContainer.modal.data)
     const url =this.ServiceContainer.modal.data.items.href
     return this.ServiceContainer.requester.transformRequestParams({
       url: url,
@@ -245,7 +245,7 @@ export default {
       },
       locale: _this.$t('uppy'),
       onBeforeFileAdded(file, files) {
-        console.log('beforeFileAdd',this)
+        // console.log('beforeFileAdd',this)
         const duplicated = files[file.id] != null;
         if (duplicated) {
           const i = this.findQueueEntryIndexById(file.id);
@@ -308,15 +308,15 @@ export default {
           //开始上传时间
           entry.stime=new Date().getTime()
           entry.sloaded=0
-          console.log('reqParams',entry)
+          // console.log('reqParams',entry)
           this.uppy.setMeta({ body:entry.originalFile });
-          console.log(entry.name)
+          // console.log(entry.name)
 
           _this.uppy.setFileState(id, {
             xhrUpload: { endpoint: reqParams.url+'/' +entry.name },
           });
           // xhrPlugin.opts.endpoint = ;
-          console.log(xhrPlugin.opts.endpoint)
+          // console.log(xhrPlugin.opts.endpoint)
         })
       }
       _this.uploading = true;
@@ -338,7 +338,7 @@ export default {
       let endtime = new Date().getTime();
       if(endtime-item.stime>1000){
       const speed = ((progress.bytesUploaded-item.sloaded) / 1024 / 1024).toFixed(2); // 转换为MB/s
-      console.log(`上传速度:${speed} MB/s`);
+      // console.log(`上传速度:${speed} MB/s`);
 
       item.stime=new Date().getTime()
         item.speed=`${speed} MB/s`

+ 1 - 1
src/components/FileManager/components/previews/Image.vue

@@ -61,7 +61,7 @@ methods:{
                       this.isError = false;
                       let body = new FormData();
                       body.append('file', blob);
-                       console.log('blob',body.get('file'))
+                       // console.log('blob',body.get('file'))
                       this.ServiceContainer.requester.send({
                         url: this.ServiceContainer.modal.data.item.href,
                         method: 'PUT',

+ 3 - 2
src/components/FileManager/components/previews/Text.vue

@@ -126,7 +126,8 @@
                   this.aceEditor.setValue(data)
                   this.aceEditor.session.getUndoManager().markClean()
 
-                  console.log('editstate', this.aceEditor.session.getUndoManager().isClean(),this.aceEditor.session.getUndoManager().hasUndo())
+                  // console.log('editstate', this.aceEditor.session.getUndoManager().isClean(),this.aceEditor.session.getUndoManager().hasUndo())
+
 
                 });
       }
@@ -150,7 +151,7 @@
     // },
     mounted() {
       this.$emit('success')
-       console.log(this.textMode)
+       // console.log(this.textMode)
       const filename =this.ServiceContainer.modal.data.item.name
       const modesMatch =this.MODES.filter(p=>p.extRe.test(filename))
       this.aceEditor = ace.edit(this.$refs.ace, {

文件差异内容过多而无法显示
+ 1 - 0
src/icons/svg/messageTemplate.svg


文件差异内容过多而无法显示
+ 1 - 0
src/icons/svg/templateParamer.svg


+ 1 - 0
src/layout/components/TagsView/index.vue

@@ -135,6 +135,7 @@ export default {
       })
     },
     closeSelectedTag(view) {
+      console.log('view',view)
       this.$store.dispatch('tagsView/delView', view).then(({ visitedViews }) => {
         if (this.isActive(view)) {
           this.toLastView(visitedViews, view)

+ 12 - 13
src/router/index.js

@@ -295,19 +295,6 @@ export const partRoutes = [
       }
     ]
   },
-  {
-    path: '/article-manager',
-    component: Layout,
-    redirect: '/article-manager/index',
-    children: [
-      {
-        path: 'index',
-        component: () => import('@/views/article-manager/index'),
-        name: 'article-manager',
-        meta: { title: i18n.t('wu20240322.fileManager'), icon: 'el-icon-folder-opened', noCache: true }
-      }
-    ]
-  },
   // 任务
   {
     path: '/task',
@@ -371,6 +358,18 @@ export const partRoutes = [
         name: 'message-edit',
         meta: { title: i18n.t('mc.messagesModule.addMessage'), icon: 'messageList', noCache: true },
         hidden: true
+      },
+      {
+        path: 'template-param',
+        component: () => import('@/views/message-center/template-paramer/index'),
+        name: 'template-param',
+        meta: { title: i18n.t('mc.templateParamer'), icon: 'templateParamer', noCache: true }
+      },
+      {
+        path: 'message-template',
+        component: () => import('@/views/message-center/message-template/index'),
+        name: 'message-template',
+        meta: { title: i18n.t('mc.messageTemplate'), icon: 'messageTemplate', noCache: true }
       }
     ]
   },

+ 17 - 0
src/store/modules/tagsView.js

@@ -80,6 +80,7 @@ const actions = {
 
   delView({ dispatch, state }, view) {
     return new Promise(resolve => {
+      console.log('delView')
       dispatch('delVisitedView', view)
       dispatch('delCachedView', view)
       resolve({
@@ -149,6 +150,22 @@ const actions = {
 
   updateVisitedView({ commit }, view) {
     commit('UPDATE_VISITED_VIEW', view)
+  },
+
+  /**
+   * 关闭当前页
+   * @param commit
+   * @param state
+   * @param params
+   */
+  delCurrentViews({ commit, state }, params) {
+    commit('DEL_VISITED_VIEWS', params.view)
+    const latestView = [...state.visitedViews].slice(-1)[0]
+    if (latestView) {
+      params.$router.push(latestView)
+    } else {
+      params.$router.push('/')
+    }
   }
 }
 

+ 3 - 1
src/utils/enum/ErrorEnum.js

@@ -42,7 +42,9 @@ export const ERROR_TYPE = createEnum(
     LICENSE_FAILED: [46, i18n.t('errorType.LICENSE_FAILED')],
     FILE_UPLOAD_FAILED: [47, i18n.t('errorType.FILE_UPLOAD_FAILED')],
     FILE_FAILED: [48, i18n.t('errorType.FILE_FAILED')],
-    PERMISSION_DENIED: [49, i18n.t('errorType.PERMISSION_DENIED')]
+    PERMISSION_DENIED: [49, i18n.t('errorType.PERMISSION_DENIED')],
+    TEMPLATE_DELETE_FAILED: [50, i18n.t('mc.templateParamerModule.TEMPLATE_PARAMER_DELETE_FAILED')],
+      MESSAGE_TYPE_DELETE_FAILED: [51, i18n.t('mc.messageTypeModule.MESSAGE_TYPE_DELETE_FAILED')],
   }
 )
 

+ 8 - 0
src/utils/enum/MessageStatusEnum.js

@@ -0,0 +1,8 @@
+import createEnum from '@/utils/enum/createEnum'
+import i18n from '@/utils/i18n'
+export const MESSAGE_STATUS = createEnum(
+  {
+    ENABLED: [1, i18n.t('mc.messagesModule.enabled')],
+    DISABLED: [0, i18n.t('mc.messagesModule.disabled')]
+  }
+)

文件差异内容过多而无法显示
+ 0 - 181
src/views/article-manager/index.vue


+ 564 - 0
src/views/message-center/message-template/index.vue

@@ -0,0 +1,564 @@
+<template>
+  <div>
+    <ag-grid-layout
+        toolbar
+        :table-height="tableHeight"
+        theme="ag-theme-alpine"
+        :column-defs="columnDefs"
+        :row-data="rowData"
+        :locale-text="localeText"
+        :grid-options="gridOptions"
+        :default-col-def="defaultColDef"
+        :animate-rows="true"
+        :row-selection="rowSelection"
+        :enable-cell-change-flash="true"
+        @filterChanged="filterModifed"
+        @sortChanged="gridSortChange"
+    >
+      <!--        @rowDoubleClicked="getList"-->
+      <div slot="toolbar" class="inner-toolbar">
+        <div class="toolbar-search">
+          <en-table-search :placeholder="this.$t('action.keywords')" @search="handlerSearch"/>
+        </div>
+        <div class="toolbar-btns">
+          <el-button type="primary" size="mini" @click="createMessageType">{{
+              this.$t('mc.messageTemplateModule.addMessageTemplate')
+            }}
+          </el-button>
+        </div>
+      </div>
+      <el-pagination
+          v-if="pageData"
+          slot="pagination"
+          :current-page="pageData.page_no"
+          :page-sizes="[10, 20, 50, 100]"
+          :page-size="pageData.page_size"
+          layout="total, sizes, prev, pager, next, jumper"
+          :total="pageData.data_total"
+          @size-change="handlePageSizeChange"
+          @current-change="handlePageCurrentChange"
+      />
+    </ag-grid-layout>
+    <el-dialog :title.sync="formtitle" :visible.sync="formshow"  width="35%">
+      <div style="position: relative;" @click="closeMenu">
+        <el-form ref="editform" :rules="rules" label-width="120px" :model="formmodel">
+
+          <el-row>
+            <el-col :span="24">
+              <el-form-item :label="this.$t('mc.messageTemplateModule.templateTitle')" prop="template_title">
+                <el-input
+                    v-model="formmodel.template_title"
+                    clearable
+                    :maxlength="100"
+                    :placeholder="this.$t('mc.messageTemplateModule.templateTitle')"
+                />
+              </el-form-item>
+
+              <el-form-item   :label="this.$t('mc.messageTemplateModule.templateContent')" prop="template_content">
+                <el-input
+                    v-model="formmodel.template_content"
+                    clearable
+                    ref="template_content"
+                    type="textarea"
+                    @focus="closeMenu"
+                    @blur="recordCursorPosition"
+                    @contextmenu.prevent.native="openMenu($event)"
+                    :placeholder="this.$t('mc.messageTemplateModule.templateContent')"
+                />
+                <span>{{this.$t('mc.messageTemplateModule.insertParamerTip')}}</span>
+              </el-form-item>
+
+              <el-form-item label="" prop="bool_shared">
+                <el-checkbox v-model="formmodel.bool_shared" :true-label="1" :false-label="0">
+                  {{ this.$t('mc.messageTemplateModule.boolShared') }}
+                </el-checkbox>
+              </el-form-item>
+
+            </el-col>
+          </el-row>
+        </el-form>
+
+      </div>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="formshow = false">{{ this.$t('action.cancel') }}</el-button>
+        <el-button type="primary" :disabled="this.formmodel.part_id!==Number(this.$store.getters.partId)" @click="handlerFormSubmit('editform')">{{ this.$t('action.yes') }}</el-button>
+      </div>
+
+      <ul v-show="visible" :style="{left:left+'px',top:top+'px'}" class="contextmenu">
+        <li @click="insertAtCursor(item)" v-for="item in templateParamers" :key="item.id">{{ item.param_name }}</li>
+      </ul>
+    </el-dialog>
+
+  </div>
+</template>
+
+
+<script>
+import ButtonCellRenderList from "@/components/AgGridCellRender/ButtonCellRenderList.vue";
+import ButtonCellRender from "@/components/AgGridCellRender/ButtonCellRender.vue";
+import ListFilter from "@/components/AgGridCustomFilter/ListFilter.vue";
+import RadioFilter from "@/components/AgGridCustomFilter/RadioFilter.vue";
+import {AG_GRID_LOCALE_CN} from "@/utils/AgGridVueLocaleCn";
+import * as API_MessageTemplate from "@/api/message_template";
+import {unix2Date} from "@/utils/Foundation";
+import * as API_TemplateParamer from "@/api/template_paramer";
+
+export default {
+  name: "index",
+  components: {ButtonCellRenderList, ButtonCellRender, ListFilter, RadioFilter},
+  data() {
+    return {
+      tableData: [],
+      /** 列表参数 */
+      params: {
+        page_size: 20,
+        page_no: 1,
+        fixedCondition: ' part_id = ' + this.$store.getters.partId+' or bool_shared = 1',
+      },
+      /** 新建组织弹出参数 **/
+      formtitle: this.$t('mc.messageTemplateModule.addMessageTemplate'),
+      formshow: false,
+      /** 频道订阅设置 */
+      formSubscribe: false,
+      formmodel: {},
+      frameGroups: [],
+      rules: {
+        template_title: [
+          {required: true, message: this.$t('mc.messageTemplateModule.templateTitleRequired'), trigger: 'blur'}
+        ],
+        template_content: [
+          {required: true, message: this.$t('mc.messageTemplateModule.templateContentRequired'), trigger: 'blur'},
+{validator: this.validateContent, trigger: 'blur'}
+        ]
+      },
+
+      /** ag-grid参数 **/
+      pageData: [],
+      loading: false,
+      columnDefs: null,
+      rowData: null,
+      defaultColDef: null,
+      gridOptions: null,
+      gridApi: null,
+      columnApi: null,
+      localeText: AG_GRID_LOCALE_CN,
+      filterState: null,
+      rowSelection: null,
+      frameworkComponents: null,
+      visible:false,
+      left:0,
+      top:0,
+      selectionStart:0,
+      selectionEnd:0,
+      templateParamers: [],
+      boolTransfer: [
+        {key: this.$t('mc.templateParamerModule.yes'), value: 1},
+        {key: this.$t('mc.templateParamerModule.no'), value: 0}
+      ],
+      /** 频道订阅者情况数组 */
+      channelSubscribers: [],
+      subscribeTitle: '',
+      choiceAll: this.$t('action.choiceAll')
+    }
+  },
+  computed: {
+    tableHeight() {
+      return this.mainAreaHeight - 130
+    }
+
+  },
+  beforeMount() {
+    this.gridOptions = {}
+    this.columnDefs = [
+      {
+        headerName: '#',
+        headerCheckboxSelection: true,
+        headerCheckboxSelectionFilteredOnly: true,
+        checkboxSelection: true,
+        sortable: false, filter: false,
+        width: 100,
+        resizable: false,
+        valueGetter: this.hashValueGetter
+      },
+      {headerName: 'ID', field: 'id', sortable: true, filter: 'agNumberColumnFilter', width: 130},
+      {
+        headerName: this.$t('mc.messageTemplateModule.templateTitle'),
+        field: 'template_title',
+        filter: 'agNumberColumnFilter',
+        sortable: true,
+        flex: 1
+      },
+      {
+        headerName: this.$t('mc.messageTemplateModule.templateContent'),
+        field: 'template_content',
+        sortable: true,
+        filter: 'agTextColumnFilter',
+        flex: 1
+
+      },
+      {
+        headerName: this.$t('mc.messageTemplateModule.boolShared'),
+        field: 'bool_shared',
+        sortable: true,
+        filterFramework: 'RadioFilter',
+        filterParams: {
+          listData: this.boolTransfer
+        },
+        width: 150,
+        cellRenderer: this.booleanFormatter
+      },
+      {
+        headerName: this.$t('boardTitle.partId'), field: 'part_id', sortable: true, filter: 'agNumberColumnFilter', flex: 1
+      },
+      // lockPosition 锁定位置,会在第一列
+      // lockPinned = true 不能拖动然后固定
+      // resizeable 单元个大小是否可以调整
+
+      {
+        headerName: this.$t('action.handle'), field: 'id',
+        cellRendererFramework: 'ButtonCellRenderList',
+        cellRendererParams: param => {
+          // console.log(param,Number(this.$store.getters.partId))
+          return {
+            list: [
+              {
+                onClick: this.handleEdit,
+                label: this.$t('action.edit'),
+                buttonType: 'primary',
+                buttonSize: 'mini'
+              },
+
+              {
+                onClick: this.deleteSingle,
+                label: this.$t('action.delete'),
+                buttonType: 'danger',
+                buttonSize: 'mini',
+                disabled: param.data.part_id!==Number(this.$store.getters.partId)
+              }
+            ]
+          }
+        },
+        filter: false,
+        pinned: 'right',
+        lockPinned: true,
+        minWidth: this.$i18n.locale === 'zh' ? 310 : 350,
+        resizable: false,
+        sortable: false
+      }
+    ]
+    this.defaultColDef = {
+      sortable: true,
+      resizable: true,
+      comparator: this.dateCustomComparator,
+      filterParams: {
+        debounceMs: 200,
+        newRowsAction: 'keep',
+        textCustomComparator: this.textCustomComparator,
+        comparator: this.dateCustomComparator
+      }
+    }
+    this.rowSelection = 'multiple'
+  },
+ async mounted() {
+    window.onresize = this.windowResize
+    this.templateParamers= await API_TemplateParamer.getAll()
+    this.gridApi = this.gridOptions.api
+    this.gridColumnApi = this.gridOptions.columnApi
+    // 设置默认排序字段,应用列状态之后会触发 gridSortChange 函数,会调用getlist,后面不需要再调用this.getlist
+    this.gridColumnApi.applyColumnState({
+      state: [
+        {
+          colId: 'id',
+          sort: 'asc'
+        }
+      ]
+    })
+  },
+  methods: {
+    windowResize() {
+      this.$set(this, 'mainAreaHeight', Number(document.documentElement.clientHeight) - 84)
+    },
+    openMenu(e) {
+      // console.log(e)
+      const menuMinWidth = 105
+      const offsetLeft = e.target.offsetWidth // container margin left
+      const offsetWidth = this.$el.offsetWidth // container width
+      const maxLeft = offsetWidth - menuMinWidth // left boundary
+      const left = e.x  // 15: margin right
+       this.left=left
+      // if (left > maxLeft) {
+      //   this.left = maxLeft
+      // } else {
+      //   this.left = left
+      // }
+
+      this.top = e.y+10
+      this.visible = true
+    },
+    recordCursorPosition(e) {
+      this.selectionStart = e.srcElement.selectionStart
+      this.selectionEnd = e.srcElement.selectionEnd
+    },
+    insertAtCursor(item) {
+
+      var val = this.formmodel.template_content;
+      var start = this.selectionStart;
+      var end = this.selectionEnd;
+      // console.log('start',start,end)
+      const text='${'+item.param_name+'}'
+      this.formmodel.template_content = val.substring(0, start) + text + val.substring(end);
+      this.$refs.template_content.selectionStart = this.$refs.template_content.selectionEnd = start + text.length;
+      this.closeMenu()
+    },
+    closeMenu() {
+       this.visible = false
+    },
+
+    handlerDelete(ids) {
+      this.$confirm(this.$t('action.sureDelete'), this.$t('action.waring'), {
+        confirmButtonText: this.$t('action.yes'),
+        cancelButtonText: this.$t('action.cancel'),
+        type: 'warning'
+      }).then(() => {
+        API_MessageTemplate.remove(ids).then(
+            response => {
+              this.getList()
+              this.$message({
+                type: 'success',
+                message: this.$t('action.deleted')
+              })
+            }
+        ).catch(response => {
+          this.$message({
+            type: 'info',
+            message: response.message
+          })
+        })
+      }).catch(() => {
+        this.$message({
+          type: 'info',
+          message: this.$t('action.cancelDelete')
+        })
+      })
+    },
+    booleanFormatter(params) {
+      if (params.value === null || params.value === undefined) return ''
+      else{
+        return params.value ? `<span style="color:green;">${this.$t('mc.templateParamerModule.yes')}</span>` :`<span style="color:red;">${this.$t('mc.templateParamerModule.no')}</span>`
+      }
+    },
+    deleteSingle(row) {
+      this.handlerDelete(row.id)
+    },
+    extractParams(template) {
+      const pattern = /\$\{([^}]+)\}/g;
+      let match;
+      const params = [];
+
+      while ((match = pattern.exec(template))) {
+        params.push(match[1]); // 添加到params数组中
+      }
+
+      return params;
+    },
+
+
+    /**
+     * 创建 消息类型
+     */
+    createMessageType() {
+      this.formshow = true
+      this.formmodel = {
+      }
+      this.formtitle=this.$t('mc.messageTemplateModule.addMessageTemplate')
+    },
+    /** 分页大小发生改变 */
+    handlePageSizeChange(size) {
+      this.params.page_size = size
+      this.getList()
+    },
+
+    /** 分页页数发生改变 */
+    handlePageCurrentChange(page) {
+      this.params.page_no = page
+      this.getList()
+    },
+    /** 加载列表数据 */
+    getList() {
+      this.loading = true
+      const param = this.MixinClone(this.params)
+      this.gridApi.showLoadingOverlay()
+      API_MessageTemplate.getList(param).then(response => {
+        this.loading = false
+        // this.tableData = [...response.data]
+        this.pageData = {
+          page_no: response.page_no,
+          page_size: response.page_size,
+          data_total: response.data_total
+        }
+        this.$nextTick(() => {
+          const node = this.gridApi.getDisplayedRowAtIndex(0)
+          if (node !== null && node !== undefined) {
+            node.setSelected(true)
+          }
+        })
+        this.rowData = [...response.data]
+        this.refreshPlayStatus()
+      }).catch(() => {
+        this.loading = false
+      })
+    },
+    /** 处理搜索 */
+    handlerSearch(keywords) {
+      this.params.query = keywords
+      this.getList()
+    },
+    /** 处理字段排序 */
+    tableSort(column) {
+      if (column.order !== null) {
+        this.params.sort = column.prop
+        this.params.dir = column.order === 'ascending' ? 'asc' : 'desc'
+      } else {
+        this.params.sort = null
+        this.params.dir = null
+      }
+      this.getList()
+    },
+    /**
+     * 格式化unix时间戳
+     **/
+    unixDateFormatter(param) {
+      if (!param.value) return ''
+      return unix2Date(param.value * 1000)
+    },
+
+    gridSortChange(param) {
+      const columnState = param.columnApi.getColumnState()
+      // 排序状态
+      const sortState = columnState.filter(function (s) {
+        return s.sort != null
+      }).map(function (s) {
+        return {
+          colId: s.colId,
+          sort: s.sort,
+          sortIndex: s.sortIndex
+        }
+      }).sort(function (a, b) {
+        return a.sortIndex - b.sortIndex
+      })
+      if (sortState.length > 0) {
+        if (sortState.length === 1) {
+          this.params.sort = sortState[0].colId
+          this.params.dir = sortState[0].sort
+        } else {
+          let sortstring = ''
+          sortState.forEach(function (item) {
+            sortstring += item.colId + ' ' + item.sort + ','
+          })
+          this.params.sort = sortstring.substring(0, sortstring.length - 1)
+          this.params.dir = ' '
+        }
+      } else {
+        delete this.params.sort
+        delete this.params.dir
+      }
+      this.getList()
+    },
+
+    filterModifed(param) { // todo 通过转换后的数值过滤,需要转回原始数值
+      var model = param.api.getFilterModel()
+      this.params.filter = JSON.stringify(model)
+      this.getList()
+    },
+
+    handleEdit(row) {
+      this.formtitle = this.$t('mc.messageTemplateModule.editMessageTemplate')
+      this.formmodel = {
+        ...row
+      }
+      this.formshow = true
+    },
+    validateContent(rule, value, callback) {
+      // 自定义校验规则
+      const paramers = this.extractParams(value)
+      const _this=this
+      if(paramers.length>0){
+         paramers.forEach(item=>{
+           if(!this.templateParamers.find(i=>i.param_name===item)){
+             callback(new Error(_this.$t('mc.messageTemplateModule.templateContentError',[item])))
+           }
+         })
+        callback()
+      }else{
+        callback()
+      }
+
+    },
+    /**
+     * 提交新增表单
+     * @param formname
+     */
+    handlerFormSubmit(formName) {
+      this.$refs[formName].validate((valid) => {
+        if (valid) {
+          if (!this.formmodel.id) {
+            /** 新增 */
+            this.formmodel.part_id = this.$store.getters.partId
+
+            API_MessageTemplate.add(this.formmodel).then(() => {
+              this.formshow = false
+              this.$message.success(this.$t('action.addSuccess'))
+              this.getList()
+            })
+          } else {
+            API_MessageTemplate.update(this.formmodel.id, this.formmodel).then(() => {
+              this.formshow = false
+              this.$message.success(this.$t('action.editSuccess'))
+              this.getList()
+            })
+          }
+        } else {
+          this.$message.error(this.$t('action.fromError'))
+        }
+      })
+    },
+
+
+  }
+
+}
+</script>
+
+
+
+
+<style scoped>
+.el-dropdown-link {
+  cursor: pointer;
+  color: #409EFF;
+}
+.el-icon-arrow-down {
+  font-size: 12px;
+}
+.contextmenu {
+  margin: 0;
+  background: #fff;
+  z-index: 3000;
+  position: fixed;
+  list-style-type: none;
+  padding: 5px 0;
+  border-radius: 4px;
+  font-size: 12px;
+  font-weight: 400;
+  color: #333;
+  box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, .3);
+  li {
+    margin: 0;
+    padding: 7px 16px;
+    cursor: pointer;
+    &:hover {
+      background: #eee;
+    }
+  }
+}
+</style>

+ 4 - 4
src/views/message-center/message-type/index.vue

@@ -249,10 +249,10 @@ export default {
               })
             }
         ).catch(response => {
-          this.$message({
-            type: 'info',
-            message: response.message
-          })
+          // this.$message({
+          //   type: 'info',
+          //   message: response.message
+          // })
         })
       }).catch(() => {
         this.$message({

+ 65 - 37
src/views/message-center/messages/index.vue

@@ -51,7 +51,10 @@ import {AG_GRID_LOCALE_CN} from "@/utils/AgGridVueLocaleCn";
 import * as API_BoardTitle from "@/api/ncs_board_title";
 import {unix2Date} from "@/utils/Foundation";
 import {MESSAGE_OPEN_TYPE} from "@/utils/enum/MessageOpenTypeEnum";
-
+import {MESSAGE_STATUS} from "@/utils/enum/MessageStatusEnum";
+import * as API_Messages from '@/api/messages'
+import * as API_MessageType from '@/api/message_type'
+import {DEVICE_TYPE} from "@/utils/enum/DeviceTypeEnum";
 export default {
   name: "index",
   components: { ButtonCellRenderList, ButtonCellRender, ListFilter, RadioFilter },
@@ -62,7 +65,7 @@ export default {
       params: {
         page_size: 20,
         page_no: 1,
-        fixedCondition: ' part_id = ' + this.$store.getters.partId
+        fixedCondition: ' part_id = ' + this.$store.getters.partId+' or bool_shared = 1',
       },
       /** 新建组织弹出参数 **/
       formtitle: this.$t('boardTitle.createTitle'),
@@ -70,12 +73,14 @@ export default {
       /** 频道订阅设置 */
       formSubscribe: false,
       formmodel: {},
+      messageTypes: [],
       frameGroups: [],
       rules: {
         board_title: [
           { required: true, message: this.$t('boardTitle.titleRequire'), trigger: 'blur' }
         ]
       },
+      messageStatusTransfer: MESSAGE_STATUS.getKeyValueList(),
       /** ag-grid参数 **/
       pageData: [],
       loading: false,
@@ -121,7 +126,8 @@ export default {
         headerName: this.$t('mc.messagesModule.title'), field: 'title', sortable: true, filter: 'agTextColumnFilter', flex: 1
       },
       {
-        headerName: this.$t('mc.messageType'), field: 'message_type_id', sortable: true, filter: 'agTextColumnFilter', flex: 1
+        headerName: this.$t('mc.messageType'), field: 'message_type_id', sortable: true, filter: 'agTextColumnFilter', flex: 1,
+        valueGetter: this.messageTypeGetter
       },
       {
         headerName: this.$t('mc.messagesModule.description'), field: 'description', sortable: true, filter: 'agTextColumnFilter', flex: 1
@@ -135,6 +141,28 @@ export default {
         valueGetter: this.openTypeGetter
       },
       {
+        headerName: this.$t('mc.messagesModule.boolShared'),
+        field: 'bool_shared',
+        sortable: true,
+        filterFramework: 'RadioFilter',
+        filterParams: {
+          listData: this.boolTransfer
+        },
+        width: 150,
+        cellRenderer: this.booleanFormatter
+      },
+      {
+        headerName: this.$t('mc.messagesModule.status'),
+        field: 'status',
+        sortable: true,
+        filterFramework: 'RadioFilter',
+        filterParams: {
+          listData: this.messageStatusTransfer
+        },
+        width: 150,
+        cellRenderer: this.messageStatusFormatter
+      },
+      {
         headerName: this.$t('boardTitle.partId'), field: 'part_id', sortable: true, filter: 'agNumberColumnFilter', flex: 1
       },
 
@@ -144,25 +172,22 @@ export default {
       { headerName: this.$t('action.handle'), field: 'id',
         cellRendererFramework: 'ButtonCellRenderList',
         cellRendererParams: param => {
+
           return {
             list: [
               {
                 onClick: this.handEdit,
                 label: this.$t('action.edit'),
                 buttonType: 'primary',
-                buttonSize: 'mini'
+                buttonSize: 'mini',
+                // disabled: param.data.part_id!==Number(this.$store.getters.partId)
               },
               {
                 onClick: this.deleteSingle,
                 label: this.$t('action.delete'),
                 buttonType: 'danger',
                 buttonSize: 'mini',
-              },
-              {
-                onClick: this.toDesigner,
-                label: this.$t('boardTitle.design'),
-                buttonType: 'warning',
-                buttonSize: 'mini',
+                disabled: param.data.part_id!==Number(this.$store.getters.partId)
               }
 
             ]}
@@ -170,7 +195,7 @@ export default {
         filter: false,
         pinned: 'right',
         lockPinned: true,
-        minWidth: this.$i18n.locale === 'zh' ? 310 : 350,
+        minWidth: this.$i18n.locale === 'zh' ? 210 : 250,
         resizable: false,
         sortable: false
       }
@@ -189,8 +214,9 @@ export default {
     }
     this.rowSelection = 'multiple'
   },
-  mounted() {
+ async mounted() {
     window.onresize = this.windowResize
+    this.messageTypes = await API_MessageType.getAll()
     this.gridApi = this.gridOptions.api
     this.gridColumnApi = this.gridOptions.columnApi
     // 设置默认排序字段,应用列状态之后会触发 gridSortChange 函数,会调用getlist,后面不需要再调用this.getlist
@@ -214,7 +240,7 @@ export default {
         cancelButtonText: this.$t('action.cancel'),
         type: 'warning'
       }).then(() => {
-        API_BoardTitle.remove(ids).then(
+        API_Messages.remove(ids).then(
             response => {
               this.getList()
               this.$message({
@@ -244,11 +270,23 @@ export default {
       // return this.deviceTypeTransfer.filter(p => p.value === gridVal).map(p => p.key)
       return MESSAGE_OPEN_TYPE.getDescFromValue(gridVal)
     },
+    messageTypeGetter(params){
+      const gridVal = params.data.message_type_id
+      // return this.deviceTypeTransfer.filter(p => p.value === gridVal).map(p => p.key)
+      // console.log(this.messageTypes)
+      return this.messageTypes.find(p => p.id === gridVal).type_name||''
+    },
+    booleanFormatter(params) {
+      if (params.value === null || params.value === undefined) return ''
+      else{
+        return params.value ? `<span style="color:green;">${this.$t('mc.templateParamerModule.yes')}</span>` :`<span style="color:red;">${this.$t('mc.templateParamerModule.no')}</span>`
+      }
+    },
     /**
      * 创建频道
      */
     createChannel() {
-      this.$router.push({ name: 'message-edit', params: { id: 1 }})
+      this.$router.push({ name: 'message-edit'})
     },
     /** 分页大小发生改变 */
     handlePageSizeChange(size) {
@@ -256,6 +294,7 @@ export default {
       this.getList()
     },
 
+
     /** 分页页数发生改变 */
     handlePageCurrentChange(page) {
       this.params.page_no = page
@@ -266,7 +305,7 @@ export default {
       this.loading = true
       const param = this.MixinClone(this.params)
       this.gridApi.showLoadingOverlay()
-      API_BoardTitle.getList(param).then(response => {
+      API_Messages.getList(param).then(response => {
         this.loading = false
         // this.tableData = [...response.data]
         this.pageData = {
@@ -309,7 +348,11 @@ export default {
       if (!param.value) return ''
       return unix2Date(param.value * 1000)
     },
-
+    messageStatusFormatter(params) {
+      const gridVal = params.data.status
+      // return this.deviceTypeTransfer.filter(p => p.value === gridVal).map(p => p.key)
+      return `<span style="color:${gridVal===1?'green':'red'}">${MESSAGE_STATUS.getDescFromValue(gridVal)}</span>`
+    },
     gridSortChange(param) {
       const columnState = param.columnApi.getColumnState()
       // 排序状态
@@ -350,11 +393,12 @@ export default {
     },
 
     handEdit(row) {
-      this.formtitle=this.$t('boardTitle.editTitle')
-      this.formmodel = {
-        ...row
-      }
-      this.formshow = true
+      this.$router.push({ name: 'message-edit', params: { id:row.id }})
+      // this.formtitle=this.$t('boardTitle.editTitle')
+      // this.formmodel = {
+      //   ...row
+      // }
+      // this.formshow = true
     },
     /**
      * 提交新增表单
@@ -383,24 +427,8 @@ export default {
           this.$message.error(this.$t('action.fromError'))
         }
       })
-    },
-
-    handlerSubscribeSubmit() {
-      let subscribeIds = []
-      this.channelSubscribers.forEach(item => {
-        subscribeIds = [...item.clerks.filter(p => p.checked).map(p => p.member_id), ...subscribeIds]
-      })
-      API_BoardTitle.setChannelSubscribers({ channel_id: this.formmodel.id, member_ids: subscribeIds.length === 0 ? null : [...subscribeIds] }).then(() => {
-        this.formSubscribe = false
-        this.$message.success(this.$t('action.editSuccess'))
-      })
-    },
-
-    toDesigner(row) {
-      this.$router.push({ name: 'infoboard-designer-manager', params: { id:row.id }})
     }
 
-
   }
 
 }

+ 127 - 19
src/views/message-center/messages/message-edit.vue

@@ -1,9 +1,8 @@
 <template>
   <el-container>
-    <el-header>
-      <el-button type="primary" @click="saveEditJs">save</el-button>
-    </el-header>
+
     <el-main>
+      <el-scrollbar wrap-class="scrollbar-wrapper" :style="{height: (asideHeight)+'px'}">
       <el-form ref="editform" :rules="rules" label-width="120px" :model="formmodel">
 
         <el-row>
@@ -36,6 +35,16 @@
                            :value="item.value"/>
               </el-select>
             </el-form-item>
+            <el-form-item label="" prop="bool_shared">
+              <el-checkbox v-model="formmodel.bool_shared" :true-label="1" :false-label="0">
+                {{ this.$t('mc.messagesModule.boolShared') }}
+              </el-checkbox>
+            </el-form-item>
+            <el-form-item label="" prop="status">
+              <el-checkbox v-model="formmodel.status" :true-label="1" :false-label="0">
+                {{ this.$t('mc.messagesModule.enabledStatus') }}
+              </el-checkbox>
+            </el-form-item>
           </el-col>
         </el-row>
       </el-form>
@@ -48,9 +57,16 @@
         <div slot="title" style="display: none;">
         </div>
         <VueFinder id="vuefinder" :height="500" :select-button="handleSelectButton" theme="dark" :persist="true"
-                   max-file-size="50 GB" path="" request="http://192.168.1.54:5001"></VueFinder>
+                   max-file-size="50 GB" path="" :request="fileServer"></VueFinder>
       </el-dialog>
+        </el-scrollbar>
+      <el-footer class="toolbar">
+        <el-button type="primary" :disabled="this.formmodel.part_id!==Number(this.$store.getters.partId)" @click="saveEditJs">{{ $t('action.save') }}</el-button>
+        <el-button type="info" @click="closeView">{{ $t('action.back') }}</el-button>
+      </el-footer>
     </el-main>
+
+
   </el-container>
 </template>
 <script>
@@ -69,11 +85,17 @@ import VideoTool from "@/components/EditorjsTools/VideoTool";
 import ImageTool from "@/components/EditorjsTools/ImageTool";
 import {MESSAGE_OPEN_TYPE} from "@/utils/enum/MessageOpenTypeEnum";
 import * as API_MessageType from '@/api/message_type'
-
+import * as API_Messages from '@/api/messages'
 export default {
   name: "message-edit",
+  computed: {
+    asideHeight() {
+      return this.mainAreaHeight-100
+    }
+  },
   data() {
     return {
+      fileServer:domain.fileServer,
       editjs: null,
       customerFormVisible: false,
       imageBlockId: '',
@@ -89,10 +111,13 @@ export default {
             return;
           }
           this.fileSelect(items, event)
-          console.log(items, event);
+          // console.log(items, event);
         }
       },
-      formmodel: {},
+      formmodel: {
+        status:1,
+        part_id: Number(this.$store.getters.partId)
+      },
       messageOpenTypeEnum: MESSAGE_OPEN_TYPE.getKeyValueList(),
       messageTypes: [],
       rules: {
@@ -109,8 +134,10 @@ export default {
     }
   },
   async mounted() {
-    console.log('i18n', this.$i18n.messages[this.$i18n.locale].messages)
+    // console.log('i18n', this.$i18n.messages[this.$i18n.locale].messages)
     this.messageTypes = await API_MessageType.getAll()
+
+
     this.editjs = new EditorJS({
       holder: 'editjs',
       placeholder: '点击输入内容...',
@@ -155,9 +182,9 @@ export default {
           inlineToolbar: true,
           config: {
             onChoose: (id,index) => {
-              console.log(index)
-              console.log(this.formmodel.open_type)
-              if(this.formmodel.open_type==='VIDEO'){
+              // console.log(index)
+              // console.log(this.formmodel.open_type)
+              if(this.formmodel.open_type!=='AUDIO'&&this.formmodel.open_type!=='ARTICLE'){
                 this.editjs.blocks.delete(index)
                 return
               }
@@ -170,7 +197,11 @@ export default {
         video: {
           class: VideoTool, inlineToolbar: true,
           config: {
-            onChoose: (id) => {
+            onChoose: (id,index) => {
+              if(this.formmodel.open_type!=='VIDEO'&&this.formmodel.open_type!=='ARTICLE'){
+                this.editjs.blocks.delete(index)
+                return
+              }
               this.customerFormVisible = true
               this.imageBlockId = id
               this.handleSelectButton.filters = ['mp4']
@@ -181,7 +212,11 @@ export default {
           class: ImageTool,
           config: {
             disabled:true,
-            onChoose: (id) => {
+            onChoose: (id,index) => {
+              if(this.formmodel.open_type!=='IMAGES'&&this.formmodel.open_type!=='ARTICLE'){
+                this.editjs.blocks.delete(index)
+                return
+              }
               this.customerFormVisible = true
               this.imageBlockId = id
               this.handleSelectButton.filters = ['png', 'jpg', 'jepg', 'gif']
@@ -191,8 +226,17 @@ export default {
         blockTool: true
       },
 
-      i18n: {...this.$i18n.messages[this.$i18n.locale]}
+      i18n: {...this.$i18n.messages[this.$i18n.locale]},
+      onReady: () => {
 
+        if(this.$route.params.id){
+          // console.log('ready',this.$route.params.id)
+          this.getMessage(this.$route.params.id)
+        }else{
+
+          this.formmodel.part_id=Number(this.$store.getters.partId)
+        }
+      }
     })
 
   },
@@ -201,16 +245,57 @@ export default {
       this.customerFormVisible = false
       const imageBlock = this.editjs.blocks.getById(this.imageBlockId);
       imageBlock.call('changeImageUrl', 'http://192.168.1.54:5001' + items[0].href)
+      // imageBlock.call('afterRender')
     },
-    saveEditJs() {
-      this.editjs.save().then(output => {
-        console.log('output', JSON.stringify(output))
+
+    getMessage(id){
+      API_Messages.get(id).then(res => {
+        this.formmodel = {...res}
+        this.editjs.blocks.render(JSON.parse(res.message_body))
       }).catch(e => {
-        console.log('error', e)
+        this.$message.error(e)
+        // console.log('error', e)
       })
     },
+    saveEditJs() {
+     this.$refs.editform.validate((valid) => {
+        if (valid) {
+
+          // console.log('save', this.formmodel)
+          this.editjs.save().then(output => {
+            this.formmodel.message_body = JSON.stringify(output)
+            // console.log('output', JSON.stringify(output))
+
+            if(!this.formmodel.id) {
+              this.formmodel.part_id=this.$store.getters.partId
+              API_Messages.add(this.formmodel).then(res => {
+                this.$message.success(this.$t('action.saveSuccess'))
+                // this.$router.push({name: 'messages'})
+              }).catch(e => {
+                this.$message.error(e)
+                // console.log('error', e)
+              })
+            }else{
+              API_Messages.update(this.formmodel.id,this.formmodel).then(res=>{
+                this.$message.success(this.$t('action.saveSuccess'))
+                // this.$router.push({name: 'messages'})
+              }).catch(e => {
+                this.$message.error(e)
+                // console.log('error', e)
+              })
+            }
+
+          }).catch(e => {
+            this.$message.error(e)
+            // console.log('error', e)
+          })
+        } else {
+          return false;
+        }
+      });
+
+    },
     openTypeChange(value) {
-      console.log(this.editjs.blocks)
       // let conf = {...this.config}
       // console.log('conf',conf,this.config)
       // if(value==='VIDEO'){
@@ -229,9 +314,17 @@ export default {
       // this.editjs.destroy()
       // this.editjs = new EditorJS(conf)
     },
+    closeView(){
+      this.$store.dispatch('tagsView/delView', this.$route).then(({ visitedViews }) => {
+        this.$router.push({ name: 'messages'})
+      })
+
+
+    }
   },
 
   destroyed() {
+    this.editjs.destroy()
     // this.videoplay=null
   }
 }
@@ -239,10 +332,25 @@ export default {
 
 
 <style scoped>
+.el-main{
+  padding: 20px 0;
+}
 .el-main .el-form {
   max-width: 770px;
   position: relative;
   left: 50%;
   margin-left: -445px;
 }
+.toolbar {
+  background: #fff;
+  border-top: 1px solid #d8dce5;
+  display: flex;
+  justify-content: center;
+  flex-direction: row;
+  align-items: center;
+}
+/deep/ .scrollbar-wrapper {
+  height: 100%;
+  overflow-x: hidden;
+}
 </style>

+ 581 - 0
src/views/message-center/template-paramer/index.vue

@@ -0,0 +1,581 @@
+<template>
+  <div>
+    <ag-grid-layout
+        toolbar
+        :table-height="tableHeight"
+        theme="ag-theme-alpine"
+        :column-defs="columnDefs"
+        :row-data="rowData"
+        :locale-text="localeText"
+        :grid-options="gridOptions"
+        :default-col-def="defaultColDef"
+        :animate-rows="true"
+        :row-selection="rowSelection"
+        :enable-cell-change-flash="true"
+        @filterChanged="filterModifed"
+        @sortChanged="gridSortChange"
+        @grid-ready="onGridReady"
+        :getRowHeight="getRowHeight"
+    >
+      <!--        @rowDoubleClicked="getList"-->
+      <div slot="toolbar" class="inner-toolbar">
+        <div class="toolbar-search">
+          <en-table-search :placeholder="this.$t('action.keywords')" @search="handlerSearch"/>
+        </div>
+        <div class="toolbar-btns">
+          <el-button type="primary" size="mini" @click="createMessageType">{{
+              this.$t('mc.templateParamerModule.addTemplateParamer')
+            }}
+          </el-button>
+        </div>
+      </div>
+      <el-pagination
+          v-if="pageData"
+          slot="pagination"
+          :current-page="pageData.page_no"
+          :page-sizes="[10, 20, 50, 100]"
+          :page-size="pageData.page_size"
+          layout="total, sizes, prev, pager, next, jumper"
+          :total="pageData.data_total"
+          @size-change="handlePageSizeChange"
+          @current-change="handlePageCurrentChange"
+      />
+    </ag-grid-layout>
+    <el-dialog :title.sync="formtitle" :visible.sync="formshow" width="35%">
+      <div>
+        <el-form ref="editform" :rules="rules" label-width="120px" :model="formmodel">
+
+          <el-row>
+            <el-col :span="24">
+              <el-form-item :label="this.$t('mc.templateParamerModule.paramerName')" prop="param_name">
+                <el-input
+                    v-model="formmodel.param_name"
+                    clearable
+                    :maxlength="100"
+                    :placeholder="this.$t('mc.templateParamerModule.paramerName')"
+                />
+              </el-form-item>
+
+              <el-form-item :label="this.$t('mc.templateParamerModule.paramerPreInput')" prop="template_content">
+                <el-tag
+                    :key="tag"
+                    v-for="tag in dynamicTags"
+                    closable
+                    :disable-transitions="false"
+                    @close="handleClose(tag)">
+                  {{tag}}
+                </el-tag>
+                <el-input
+                    class="input-new-tag"
+                    v-if="inputVisible"
+                    v-model="inputValue"
+                    ref="saveTagInput"
+                    size="small"
+                    @keyup.enter.native="handleInputConfirm"
+                    @blur="handleInputConfirm"
+                >
+                </el-input>
+                <el-button v-else class="button-new-tag" size="small" @click="showInput">{{$t('mc.templateParamerModule.addValue')}}</el-button>
+              </el-form-item>
+              <el-form-item label="" prop="allow_input">
+                <el-checkbox v-model="formmodel.allow_input" @change="allowInputChange" :true-label="1" :false-label="0">
+                  {{ this.$t('mc.templateParamerModule.allowInput') }}
+                </el-checkbox>
+              </el-form-item>
+              <el-form-item label="" prop="bool_date">
+                <el-checkbox v-model="formmodel.bool_date" :true-label="1" @change="boolDateChange" :disabled="boolDateDisabled" :false-label="0">
+                  {{ this.$t('mc.templateParamerModule.boolDate') }}
+                </el-checkbox>
+              </el-form-item>
+              <el-form-item label="" prop="bool_time">
+                <el-checkbox v-model="formmodel.bool_time" :true-label="1" @change="boolTimeChange" :disabled="boolTimeDisabled" :false-label="0">
+                  {{ this.$t('mc.templateParamerModule.boolTime') }}
+                </el-checkbox>
+              </el-form-item>
+
+
+              <!--              <el-form-item :label="this.$t('mc.messageTypeModule.openType')" prop="device_type">-->
+              <!--                <el-select v-model="formmodel.open_type"-->
+              <!--                           :placeholder="this.$t('mc.messageTypeModule.openType')"-->
+              <!--                           filterable clearable>-->
+              <!--                  <el-option v-for="(item,index) in messageOpenTypeEnum" :key="index" :label="item.key"-->
+              <!--                             :value="item.value"/>-->
+              <!--                </el-select>-->
+              <!--              </el-form-item>-->
+            </el-col>
+          </el-row>
+        </el-form>
+
+      </div>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="formshow = false">{{ this.$t('action.cancel') }}</el-button>
+        <el-button type="primary" @click="handlerFormSubmit('editform')">{{ this.$t('action.yes') }}</el-button>
+      </div>
+    </el-dialog>
+
+  </div>
+</template>
+
+<script>
+import ButtonCellRenderList from "@/components/AgGridCellRender/ButtonCellRenderList.vue";
+import ButtonCellRender from "@/components/AgGridCellRender/ButtonCellRender.vue";
+import TagsCellRender from "@/components/AgGridCellRender/TagsCellRender.vue";
+import ListFilter from "@/components/AgGridCustomFilter/ListFilter.vue";
+import RadioFilter from "@/components/AgGridCustomFilter/RadioFilter.vue";
+import {AG_GRID_LOCALE_CN} from "@/utils/AgGridVueLocaleCn";
+import * as API_TemplateParamer from "@/api/template_paramer";
+import {unix2Date} from "@/utils/Foundation";
+
+export default {
+  name: "index",
+  components: {ButtonCellRenderList, ButtonCellRender, ListFilter, RadioFilter,TagsCellRender},
+  data() {
+    return {
+      tableData: [],
+      /** 列表参数 */
+      params: {
+        page_size: 20,
+        page_no: 1,
+        fixedCondition: null
+      },
+      /** 新建组织弹出参数 **/
+      formtitle: this.$t('mc.templateParamerModule.addParamer'),
+      formshow: false,
+      /** 频道订阅设置 */
+      formSubscribe: false,
+      formmodel: {},
+      dynamicTags:[],
+      inputVisible: false,
+      inputValue: '',
+      boolDateDisabled:false,
+      boolTimeDisabled:false,
+      rules: {
+        param_name: [
+          {required: true, message: this.$t('mc.templateParamerModule.paramNameRequired'), trigger: 'blur'}
+        ]
+      },
+      boolTransfer: [
+        {key: this.$t('mc.templateParamerModule.yes'), value: 1},
+        {key: this.$t('mc.templateParamerModule.no'), value: 0}
+      ],
+      /** ag-grid参数 **/
+      pageData: [],
+      loading: false,
+      columnDefs: null,
+      rowData: null,
+      defaultColDef: null,
+      gridOptions: null,
+      gridApi: null,
+      columnApi: null,
+      localeText: AG_GRID_LOCALE_CN,
+      filterState: null,
+      rowSelection: null,
+      frameworkComponents: null
+    }
+  },
+  computed: {
+    tableHeight() {
+      return this.mainAreaHeight - 130
+    }
+
+  },
+  beforeMount() {
+    this.gridOptions = {
+
+    }
+    this.columnDefs = [
+      {
+        headerName: '#',
+        headerCheckboxSelection: true,
+        headerCheckboxSelectionFilteredOnly: true,
+        checkboxSelection: true,
+        sortable: false, filter: false,
+        width: 100,
+        resizable: false,
+        valueGetter: this.hashValueGetter
+      },
+      {headerName: 'ID', field: 'id', sortable: true, filter: 'agNumberColumnFilter', width: 130},
+      {
+        headerName: this.$t('mc.templateParamerModule.paramerName'),
+        field: 'param_name',
+        filter: 'agNumberColumnFilter',
+        sortable: true,
+        width: 150
+      },
+      {
+        headerName: this.$t('mc.templateParamerModule.paramerPreInput'),
+        field: 'pre_input_option',
+        sortable: true,
+        filter: 'agTextColumnFilter',
+        flex: 1,
+        autoHeight:true,
+        wrapText:true,
+        cellRendererFramework: 'TagsCellRender',
+        cellRendererParams:param => {
+          return {
+            tagType:'primary',
+            tagList: JSON.parse(param.value)
+          }
+        }
+      },
+      {
+        headerName: this.$t('mc.templateParamerModule.allowInput'),
+        field: 'allow_input',
+        sortable: true,
+        filterFramework: 'RadioFilter',
+        filterParams: {
+          listData: this.boolTransfer
+        },
+        width: 150,
+        cellRenderer: this.booleanFormatter
+      },
+      {
+        headerName: this.$t('mc.templateParamerModule.boolDate'),
+        field: 'bool_date',
+        sortable: true,
+        filterFramework: 'RadioFilter',
+        filterParams: {
+          listData: this.boolTransfer
+        },
+        width: 150,
+        cellRenderer: this.booleanFormatter
+      },
+      {
+        headerName: this.$t('mc.templateParamerModule.boolTime'),
+        field: 'bool_time',
+        sortable: true,
+        filterFramework: 'RadioFilter',
+        filterParams: {
+          listData: this.boolTransfer
+        },
+        width: 150,
+        cellRenderer: this.booleanFormatter
+      },
+      // lockPosition 锁定位置,会在第一列
+      // lockPinned = true 不能拖动然后固定
+      // resizeable 单元个大小是否可以调整
+
+      {
+        headerName: this.$t('action.handle'), field: 'id',
+        cellRendererFramework: 'ButtonCellRenderList',
+        cellRendererParams: param => {
+          return {
+            list: [
+              {
+                onClick: this.handleEdit,
+                label: this.$t('action.edit'),
+                buttonType: 'primary',
+                buttonSize: 'mini'
+              },
+
+              {
+                onClick: this.deleteSingle,
+                label: this.$t('action.delete'),
+                buttonType: 'danger',
+                buttonSize: 'mini',
+              }
+            ]
+          }
+        },
+        filter: false,
+        pinned: 'right',
+        lockPinned: true,
+        minWidth: 200,
+        resizable: false,
+        sortable: false
+      }
+    ]
+    this.defaultColDef = {
+      sortable: true,
+      resizable: true,
+      comparator: this.dateCustomComparator,
+      filterParams: {
+        debounceMs: 200,
+        newRowsAction: 'keep',
+        textCustomComparator: this.textCustomComparator,
+        comparator: this.dateCustomComparator
+      }
+    }
+    this.rowSelection = 'multiple'
+  },
+  mounted() {
+    window.onresize = this.windowResize
+    this.gridApi = this.gridOptions.api
+    this.gridColumnApi = this.gridOptions.columnApi
+    // 设置默认排序字段,应用列状态之后会触发 gridSortChange 函数,会调用getlist,后面不需要再调用this.getlist
+    this.gridColumnApi.applyColumnState({
+      state: [
+        {
+          colId: 'id',
+          sort: 'asc'
+        }
+      ]
+    })
+
+  },
+
+  methods: {
+    onGridReady(params) {
+      this.gridApi  = params.api;
+     console.log(this.gridApi)
+      this.gridApi.resetRowHeights()
+    },
+    windowResize() {
+      this.$set(this, 'mainAreaHeight', Number(document.documentElement.clientHeight) - 84)
+    },
+    getRowHeight(param){
+      return 60
+    },
+    handlerDelete(ids) {
+      this.$confirm(this.$t('action.sureDelete'), this.$t('action.waring'), {
+        confirmButtonText: this.$t('action.yes'),
+        cancelButtonText: this.$t('action.cancel'),
+        type: 'warning'
+      }).then(() => {
+        API_TemplateParamer.remove(ids).then(
+            response => {
+              this.getList()
+              this.$message({
+                type: 'success',
+                message: this.$t('action.deleted')
+              })
+            }
+        ).catch(response => {
+          console.log(response)
+          // this.$message({
+          //   type: 'error',
+          //   message: response
+          // })
+        })
+      }).catch(() => {
+        this.$message({
+          type: 'info',
+          message: this.$t('action.cancelDelete')
+        })
+      })
+    },
+    deleteSingle(row) {
+      this.handlerDelete(row.id)
+    },
+
+    /**
+     * 创建 消息类型
+     */
+    createMessageType() {
+      this.formshow = true
+      this.formmodel = {
+
+      }
+      this.dynamicTags=[]
+      this.formtitle=this.$t('mc.templateParamerModule.addParamer')
+    },
+    /** 分页大小发生改变 */
+    handlePageSizeChange(size) {
+      this.params.page_size = size
+      this.getList()
+    },
+
+    /** 分页页数发生改变 */
+    handlePageCurrentChange(page) {
+      this.params.page_no = page
+      this.getList()
+    },
+    booleanFormatter(params) {
+      if (params.value === null || params.value === undefined) return ''
+      else{
+        return params.value ? `<span style="color:green;">${this.$t('mc.templateParamerModule.yes')}</span>` :`<span style="color:red;">${this.$t('mc.templateParamerModule.no')}</span>`
+      }
+    },
+    /** 加载列表数据 */
+    getList() {
+      this.loading = true
+      const param = this.MixinClone(this.params)
+      this.gridApi.showLoadingOverlay()
+      const _this=this
+      API_TemplateParamer.getList(param).then(response => {
+        this.loading = false
+        // this.tableData = [...response.data]
+        this.pageData = {
+          page_no: response.page_no,
+          page_size: response.page_size,
+          data_total: response.data_total
+        }
+        this.$nextTick(() => {
+          const node = this.gridApi.getDisplayedRowAtIndex(0)
+          if (node !== null && node !== undefined) {
+            node.setSelected(true)
+          }
+
+        })
+        this.rowData = [...response.data]
+
+
+      }).catch(() => {
+        this.loading = false
+      })
+    },
+    /** 处理搜索 */
+    handlerSearch(keywords) {
+      this.params.query = keywords
+      this.getList()
+    },
+    /** 处理字段排序 */
+    tableSort(column) {
+      if (column.order !== null) {
+        this.params.sort = column.prop
+        this.params.dir = column.order === 'ascending' ? 'asc' : 'desc'
+      } else {
+        this.params.sort = null
+        this.params.dir = null
+      }
+      this.getList()
+    },
+    /**
+     * 格式化unix时间戳
+     **/
+    unixDateFormatter(param) {
+      if (!param.value) return ''
+      return unix2Date(param.value * 1000)
+    },
+
+    gridSortChange(param) {
+      const columnState = param.columnApi.getColumnState()
+      // 排序状态
+      const sortState = columnState.filter(function (s) {
+        return s.sort != null
+      }).map(function (s) {
+        return {
+          colId: s.colId,
+          sort: s.sort,
+          sortIndex: s.sortIndex
+        }
+      }).sort(function (a, b) {
+        return a.sortIndex - b.sortIndex
+      })
+      if (sortState.length > 0) {
+        if (sortState.length === 1) {
+          this.params.sort = sortState[0].colId
+          this.params.dir = sortState[0].sort
+        } else {
+          let sortstring = ''
+          sortState.forEach(function (item) {
+            sortstring += item.colId + ' ' + item.sort + ','
+          })
+          this.params.sort = sortstring.substring(0, sortstring.length - 1)
+          this.params.dir = ' '
+        }
+      } else {
+        delete this.params.sort
+        delete this.params.dir
+      }
+      this.getList()
+    },
+
+    filterModifed(param) { // todo 通过转换后的数值过滤,需要转回原始数值
+      var model = param.api.getFilterModel()
+      this.params.filter = JSON.stringify(model)
+      this.getList()
+    },
+
+    handleEdit(row) {
+      this.formtitle = this.$t('mc.templateParamerModule.editParamer')
+      this.formmodel = {
+        ...row
+      }
+      this.dynamicTags = JSON.parse(row.pre_input_option)
+      this.allowInputChange(this.formmodel.allow_input)
+      this.formshow = true
+    },
+    /**
+     * 提交新增表单
+     * @param formname
+     */
+    handlerFormSubmit(formName) {
+      this.$refs[formName].validate((valid) => {
+        if (valid) {
+          this.formmodel.pre_input_option = JSON.stringify(this.dynamicTags)
+          if (!this.formmodel.id) {
+            /** 新增 */
+            API_TemplateParamer.add(this.formmodel).then(() => {
+              this.formshow = false
+              this.$message.success(this.$t('action.addSuccess'))
+              this.getList()
+            })
+          } else {
+            API_TemplateParamer.update(this.formmodel.id, this.formmodel).then(() => {
+              this.formshow = false
+              this.$message.success(this.$t('action.editSuccess'))
+              this.getList()
+            })
+          }
+        } else {
+          this.$message.error(this.$t('action.fromError'))
+        }
+      })
+    },
+    handleClose(tag) {
+      this.dynamicTags.splice(this.dynamicTags.indexOf(tag), 1);
+    },
+
+    showInput() {
+      this.inputVisible = true;
+      this.$nextTick(_ => {
+        this.$refs.saveTagInput.$refs.input.focus();
+      });
+    },
+    allowInputChange(value){
+
+      if(!value){
+        this.formmodel.bool_date=false
+        this.formmodel.bool_time=false
+        this.boolDateDisabled=true
+        this.boolTimeDisabled=true
+      }else{
+        this.boolDateDisabled=false
+        this.boolTimeDisabled=false
+      }
+    },
+    boolDateChange(value){
+      if(value){
+        this.formmodel.bool_time=false
+      }
+    },
+    boolTimeChange(value) {
+      if (value) {
+        this.formmodel.bool_date = false
+      }
+    },
+    handleInputConfirm() {
+      let inputValue = this.inputValue;
+      if (inputValue) {
+        this.dynamicTags.push(inputValue);
+      }
+      this.inputVisible = false;
+      this.inputValue = '';
+    }
+
+
+  }
+
+}
+
+</script>
+
+
+<style scoped>
+.el-tag + .el-tag {
+  margin-left: 10px;
+}
+.button-new-tag {
+  margin-left: 10px;
+  height: 32px;
+  line-height: 30px;
+  padding-top: 0;
+  padding-bottom: 0;
+}
+.input-new-tag {
+  width: 90px;
+  margin-left: 10px;
+  vertical-align: bottom;
+}
+</style>

+ 0 - 1
src/views/ncs-device/components/deviceManager.vue

@@ -364,7 +364,6 @@
                 </el-row>
             </el-form>
             <div slot="footer" class="dialog-footer">
-
                 <el-button type="primary" @click="updateDevicesServerIp()">{{ this.$t('action.yes') }}</el-button>
             </div>
         </el-dialog>

+ 3 - 2
src/views/ncs-file-manager/index.vue

@@ -1,5 +1,5 @@
 <template>
-    <VueFinder id="vuefinder" :select-button="handleSelectButton" theme="dark" :persist="true" max-file-size="50 GB" path="" request="http://192.168.1.54:5001"></VueFinder>
+    <VueFinder id="vuefinder" :select-button="handleSelectButton" theme="dark" :persist="true" max-file-size="50 GB" path="" :request="fileServer"></VueFinder>
 </template>
 
 <script>
@@ -7,6 +7,7 @@
         name: "index",
         data(){
             return{
+                fileServer:domain.fileServer,
                 handleSelectButton:{
                     // show select button
                     active: false,
@@ -20,7 +21,7 @@
                             return;
                         }
                         alert('Selected: ' + items[0].href);
-                        console.log(items, event);
+                        // console.log(items, event);
                     }
                 }
             }