Selaa lähdekoodia

新增CURD评论

liangzhicheng 2 vuotta sitten
vanhempi
sitoutus
bcf20f9063

+ 1 - 1
package.json

@@ -1,7 +1,7 @@
 {
   "name": "client-base-v4",
   "description": "Leanwo Prodog Client",
-  "version": "3.0.94",
+  "version": "3.0.95",
   "author": "yangzhijie1488 <yangzhijie1488@163.com>",
   "scripts": {
     "dev": "cross-env webpack serve --config ./webpack.dev.js",

+ 4 - 2
public/index-debug.html

@@ -28,7 +28,7 @@
 
 	<link nonce="*NONCE_TOKEN_CSS*" rel="stylesheet" type="text/css" href="/static/jQuery-ResizableColumns/jQuery.resizableColumns.css">
 
-
+	<link nonce="*NONCE_TOKEN_CSS*" rel="stylesheet" type="text/css" href="/static/summernote/dist/summernote.min.css">
 
 	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/jquery/dist/jquery.js"></script>
 
@@ -43,10 +43,12 @@
 
 	
 
-
 	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/jQuery-ResizableColumns/jQuery.resizableColumns.js"></script>
 	<!-- <script src="../static/js/api.js"></script> -->
 
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/summernote/dist/summernote.min.js"></script>
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/summernote/dist/lang/summernote-zh-CN.min.js"></script>
+
 	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/moment/moment.js"></script>
 	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/moment/locale/zh-cn.js"></script>
 

+ 72 - 0
src/common/UpladFile.js

@@ -0,0 +1,72 @@
+export default{
+  /**
+	 *三个参数
+	 *  file:一个是文件(类型是图片格式),
+	 * w:一个是文件压缩的后宽度,宽度越小,字节越小
+	 *  objDiv:一个是容器或者回调函数
+	 *  photoCompress()
+	 */
+  photoCompress: function(file, w, objDiv) {
+    var _self = this;
+    var ready = new FileReader();
+    /*开始读取指定的Blob对象或File对象中的内容. 当读取操作完成时,readyState属性的值会成为DONE,如果设置了onloadend事件处理程序,则调用之.同时,result属性中将包含一个data: URL格式的字符串以表示所读取文件的内容.*/
+    ready.readAsDataURL(file);
+    ready.onload = function() {
+      var re = this.result;
+      _self.canvasDataURL(re, w, objDiv);
+    };
+  },
+  canvasDataURL: function(path, obj, callback) {
+    var img = new Image();
+    img.src = path;
+    img.onload = function() {
+      var that = this;
+      // 默认按比例压缩
+      var w = that.width,
+        h = that.height,
+        scale = w / h;
+      w = obj.width || w;
+      h = obj.height || (w / scale);
+      var quality = 0.7; // 默认图片质量为0.7
+      //生成canvas
+      var canvas = document.createElement('canvas');
+      var ctx = canvas.getContext('2d');
+      // 创建属性节点
+      var anw = document.createAttribute('width');
+      anw.nodeValue = w;
+      var anh = document.createAttribute('height');
+      anh.nodeValue = h;
+      canvas.setAttributeNode(anw);
+      canvas.setAttributeNode(anh);
+      ctx.drawImage(that, 0, 0, w, h);
+      // 图像质量
+      if(obj.quality && obj.quality <= 1 && obj.quality > 0) {
+        quality = obj.quality;
+      }
+      // quality值越小,所绘制出的图像越模糊
+      var base64 = canvas.toDataURL('image/jpeg', quality);
+      // 回调函数返回base64的值
+      callback(base64);
+    };
+  },
+
+  /**  
+	 * 将以base64的图片url数据转换为Blob  
+	 * @param urlData  
+	 *            用url方式表示的base64图片数据  
+	 */
+  convertBase64UrlToBlob: function(urlData) {
+    var arr = urlData.split(','),
+      mime = arr[0].match(/:(.*?);/)[1],
+      bstr = atob(arr[1]),
+      n = bstr.length,
+      u8arr = new Uint8Array(n);
+    while(n--) {
+      u8arr[n] = bstr.charCodeAt(n);
+    }
+    return new Blob([u8arr], {
+      type: mime,
+    });
+  },
+
+};

+ 165 - 0
src/window/tabFormView/CurdWindowComment.vue

@@ -0,0 +1,165 @@
+<!--
+	作者:yangzhijie1488@163.com
+	时间:2017-12-12
+	描述:追踪日志
+-->
+
+<template>
+  <div>
+    <div v-for="items in traceComments" :key="items" class="media">
+      <h4 class="media-heading headDiv">
+        {{ items.createdName
+        }}<a class="fa-pull-right" @click="edit(items)">编辑</a>
+      </h4>
+      <div class="media-body">
+        <div>
+          <!-- eslint-disable-next-line -->
+          <div v-html="items.content" />
+          
+        </div>
+        <div v-if="items.attachments != '' && items.attachments != undefined">
+          <div
+            v-for="item in split(items.attachments)"
+            :key="item"
+            @click="download(item)"
+          >
+            <a>{{ item }}</a>
+          </div>
+        </div>
+        <br />
+        {{ items.created }}
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import Common from '../../common/Common.js';
+import { DownloadService } from 'pc-component-v3';
+export default {
+  components: {
+    
+    DownloadService,
+  },
+  // props: ['traceId', 'trace'],
+  props: {
+    traceId: {
+      type: String,
+      default: null,
+    }, 
+    trace: {
+      type: String,
+      default: null,
+    },
+  },
+
+  data: function () {
+    return {
+      traceComments: [],
+      className: 'com.leanwo.prodog.trace.model.TraceComment',
+      uuid: '',
+    };
+  },
+
+  watch: {
+    traceId: function (curVal, oldVal) {
+      if (curVal != undefined) {
+        this.getTraceComment();
+      }
+    },
+  },
+
+  mounted: function () {
+    this.uuid = this.$route.params.uuid;
+    if (this.traceId != undefined) {
+      this.getTraceComment();
+    }
+  },
+  methods: {
+    /**
+     * 根据追踪表Id获取评论
+     * @author GuoZhiBo 20171201
+     */
+    getTraceComment: function () {
+      var _self = this;
+      $.ajax({
+        url: Common.getApiURL('CurdWindowCommentResource/queryCurdWindowComment'),
+        type: 'get',
+        dataType: 'json',
+        async: false,
+        data: {
+          traceId: _self.traceId,
+        },
+        beforeSend: function (request) {
+          Common.addTokenToRequest(request);
+        },
+        success: function (data) {
+          _self.traceComments = data;
+        },
+        error: function (XMLHttpRequest, textStatus, errorThrown) {
+          Common.processException(XMLHttpRequest, textStatus, errorThrown);
+        },
+      });
+    },
+
+    /**
+     * 将字符串以”,“进行分割成字符串
+     * @author GuoZhiBo 20171201
+     */
+    split: function (items) {
+      if (items != null && items != '') {
+        return items.split(',');
+      } else {
+        return null;
+      }
+    },
+    /**
+     * 下载文件
+     * @param  {String} fileName 文件名
+     * @return {void}
+     */
+    download: function (fileName) {
+      var _self = this;
+      DownloadService.fileDownload(_self.className, fileName);
+    },
+    /**
+     * 获取图片地址
+     * @param  {String} item 图片名称
+     * @return {String}      图片URL地址
+     */
+    getImageSrc: function (item) {
+      var _self = this;
+      if (item != undefined && item != null) {
+        return Common.getImageSrc(
+          'com.leanwo.prodog.trace.model.TraceComment',
+          item,
+        );
+      } else {
+        return '';
+      }
+    },
+    /**
+     * 获取图片地址
+     */
+    getImageSrcName: function (imageName) {
+      return Common.getImageSrc('com.leanwo.prodog.model.base.User', imageName);
+    },
+
+    /**
+     * 打开评论界面进行评论
+     * @author GuoZhiBo 20171201
+     */
+    edit: function (item) {
+      this.$router.push('/trace/traceCommentEdit/' + item.id);
+    },
+  },
+};
+</script>
+
+<style scoped>
+.headDiv{
+  display: flex;
+  justify-content: space-between;
+  font-size: 14px;
+}
+</style>

+ 637 - 0
src/window/tabFormView/CurdWindowCommentCreate.vue

@@ -0,0 +1,637 @@
+<template>
+  <div>
+    <div>
+      <Navbar title="创建评论" />
+      <div>
+        <div class="form-group">
+          <label for="exampleInputEmail2">接收人</label>
+          <a-select
+            v-model:value="userIds"
+            mode="multiple"
+            style="width: 100%"
+            placeholder="选择抄送人"
+            :options="options"
+            :filter-option="false"
+            auto-clear-search-value
+            @change="handleChange"
+            @search="listInGroupCompanyByCondition"
+          />
+        </div>
+
+        <div class="form-group">
+          <label for="exampleInputEmail2">
+            主题:
+          </label>
+          <input
+            v-model="theme"
+            autocomplete="off"
+            type="text"
+            class="form-control"
+          />
+        </div>
+        
+        <div class="form-group">
+          <label for="exampleInputEmail2">评论内容</label>
+          <div id="summernote" />
+          <!-- <textarea style="width: 100%;"
+                              id="hcqk"
+                              class="form-control"
+                              rows="5"
+                              v-model="content"></textarea> -->
+        </div>
+        <div>
+          <input
+            ref="fileInput"
+            autocomplete="off"
+            type="file"
+            class="form-control file-input"
+            @change="onFileChanges"
+          />
+          <label for="attachment">
+            <a
+              role="button"
+              class="btn btn-primary btn-sm"
+              @click="clickButton"
+            >
+              <i class="fa fa-upload" />
+              &nbsp; 上传附件
+            </a>
+          </label>
+        </div>
+
+        <div style="margin-top: 10px">
+          <ul class="list-group">
+            <li v-for="item in files" :key="item" class="list-group-item">
+              <span class="badge" @click="download(item)">下载</span>
+              <span class="badge" @click="removeFile(item)">删除</span>
+              {{ item }}
+            </li>
+          </ul>
+        </div>
+        <!-- <div>
+          <div style="margin-top: 10px">
+            <button type="text" class="btn btn-default" @click="photograph">
+              确认
+            </button>
+            <button type="text" class="btn btn-default" @click="back">
+              取消
+            </button>
+          </div>
+        </div> -->
+      </div>
+    </div>
+    <Loading v-if="loading" />
+  </div>
+</template>
+<script>
+
+
+import UpladFile from '../../common/UpladFile.js';
+
+import Common from '../../common/Common.js';
+import { Notify } from 'pc-component-v3';
+import { DownloadService } from 'pc-component-v3';
+import { message } from 'ant-design-vue';
+import UserResource from '../../api/base/UserResource.js';
+
+export default {
+  components: {
+    UpladFile,
+  },
+
+  props: {
+
+    traceId: {
+      type: String,
+      default: null,
+    }, 
+
+    windowNo: {
+      type: String,
+      default: null,
+    }, 
+
+  },
+
+  data: function () {
+    return {
+      // traceId: null,
+      content: '',
+      images: [],
+      className: 'com.leanwo.prodog.system.model.CurdWindowComment',
+      files: [],
+      traceConfigDto: {},
+      summernoteInitSuccess: false, // summernote初始化成功
+      loading: false,
+      options: [],
+      userIds: [],
+      theme: '',
+    };
+  },
+
+  mounted: function () {
+    var _self = this;
+    $('.input-tan').focus(function () {
+      document.activeElement.blur();
+    });
+    this.initData();
+    // this.getTraceConfig();
+    $('#summernote').summernote({
+      toolbar: [
+        [
+          'insert',
+          [
+            'link',
+            'picture',
+            'video',
+            'audio',
+            'hr',
+            'table', //插件
+            'fontname',
+            'fontsize',
+            'color',
+            'bold',
+            'italic',
+            'underline',
+            'strikethrough',
+            'clear', //字体样式
+            'style',
+            'ol',
+            'ul',
+            'paragraph',
+            'height', //段落样式
+            'fullscreen',
+            'codeview',
+            'undo',
+            'redo',
+            'help', //Misc
+          ],
+        ],
+      ],
+      height: 400,
+      minHeight: 300,
+      maxHeight: 500,
+      focus: true,
+      lang: 'zh-CN',
+      callbacks: {
+        onImageUpload: function (files, editor, $editable) {
+          _self.sendFile(files[0], editor, $editable);
+        },
+      },
+    });
+    _self.summernoteInitSuccess = true;
+
+    this.listInGroupCompanyByCondition(null);
+  },
+  beforeUnmount: function () {
+    if (this.summernoteInitSuccess == true) {
+      $('#summernote').summernote('destroy');
+    }
+  },
+  methods: {
+
+    /**
+         * 根据姓名获取抄送人用户集合
+         */
+    listInGroupCompanyByCondition: function (search) {
+      let _self = this;
+      const searchQueryParam = {
+        range: {
+          start: 0,
+          length: 100,
+        },
+        conditional: search,
+      };
+
+      // console.log('copyUserIds:' + _self.copyUserIds);
+      //修复审批节点选择人员显示文件编码bug
+      // var selectList = [];
+      // if (this.copyUserIds != undefined
+      //           && this.copyUserList != undefined
+      //           && this.copyUserList.length > 0
+      //           && this.copyUserIds.length > 0) {
+      //   this.copyUserList.forEach(function (value, index) {
+      //     var id = value.id;
+      //     _self.copyUserIds.forEach(function (item) {
+      //       if (item == id) {
+      //         selectList.push(value);
+      //       }
+      //     });
+      //   });
+      // }
+      var userDtos = [];
+      UserResource.listInGroupCompanyByCondition(searchQueryParam).then(successData => {
+        if (successData != null && successData.resultList != null) {
+          successData.resultList.forEach(function (user) {
+            var userDto = {};
+
+            user.text = user.name + '(';
+            if(user.organizations != null && user.organizations.length > 0){
+              let isFirst = true;
+              user.organizations.forEach(item => {
+                if(isFirst === true){
+                  user.text += item.organizationName;
+                  isFirst = false;
+                }else{
+                  user.text += (',' +  item.organizationName);
+                }
+              });
+            }
+            user.text += ')';
+
+            userDto.value = user.id;
+            userDto.label = user.text;
+            userDtos.push(userDto);
+          });
+          _self.options = userDtos;
+          console.log(_self.options);
+        } else {
+          _self.options = [];
+          console.log(_self.options);
+        }
+      }, errorData => {
+        Common.processException(errorData);
+      });
+    },
+
+    handleChange(value) {
+      let _self = this;
+      console.log(this.userIds);
+      _self.listInGroupCompanyByCondition(null);
+    },
+
+    /**
+     * 点击上传按钮事件
+     * @return {[type]} [description]
+     */
+    clickButton: function () {
+      $(this.$refs.fileInput).click();
+    },
+    /**
+     * 初始化数据
+     * @author GuoZhiBo 20171201
+     */
+    initData: function () {
+      var _self = this;
+      // this.traceId = Number(this.$route.params.traceId);
+      console.log(_self.traceId);
+    },
+    /**
+     * 监听文件改变事件
+     * @author GuoZhiBo 20171201
+     */
+    onFileChange(e) {
+      var _self = this;
+      var files = e.target.files || e.dataTransfer.files;
+      if (!files.length) return;
+      _self.uploadImage(files[0]);
+    },
+    /**
+     * 上传图片
+     * @author GuoZhiBo 20171201
+     */
+    uploadImage: function (selectedFile) {
+      var _self = this;
+      if (selectedFile == undefined) {
+        return;
+      }
+      if (!/image\/\w+/.test(selectedFile.type)) {
+        Notify.error('提示', '请确保文件为图像类型!');
+        return;
+      }
+      UpladFile.photoCompress(
+        selectedFile,
+        {
+          quality: 0.2,
+        },
+        function (base64Codes) {
+          var bl = UpladFile.convertBase64UrlToBlob(base64Codes);
+          var rst = new FormData();
+          rst.append('images', bl, 'file_' + Date.parse(new Date()) + '.jpg');
+          rst.append('className', 'com.leanwo.prodog.system.model.CurdWindowComment');
+          _self.loading=true;
+          $.ajax({
+            url: Common.getApiURL('file/imageUpload'),
+            type: 'post',
+            beforeSend: function (request) {
+              Common.addTokenToRequest(request);
+            },
+            data: rst,
+            contentType: false,
+            processData: false,
+            success: function (data) {
+              _self.loading=false;
+              if (data.errorCode == 0) {
+                if (data.datas) {
+                  var imageName = data.datas[0];
+                  _self.addImg(imageName);
+                }
+              } else {
+                message.error(data.errorMessage);
+              }
+            },
+            error: function (XMLHttpRequest, textStatus, errorThrown) {
+              _self.loading=false;
+              Common.processException(XMLHttpRequest, textStatus, errorThrown);
+            },
+          });
+          return rst.file;
+        },
+      );
+    },
+    /**
+     * 添加图片
+     * @author GuoZhiBo 20171201
+     */
+    addImg: function (imageName) {
+      var _self = this;
+      _self.images.push(imageName);
+    },
+    /**
+     * 获取图片地址
+     * @param  {String} item 图片名称
+     * @return {String}      图片URL地址
+     */
+    getImageSrc: function (item) {
+      var _self = this;
+      if (item != undefined && item != null) {
+        return Common.getResourceUrl(
+          'image',
+          'com.leanwo.prodog.system.model.CurdWindowComment',
+          item,
+        );
+      } else {
+        return '';
+      }
+    },
+    /**
+     * 获取图片路径供外部调用
+     * @return {Array} 图片地址
+     */
+    getImages: function () {
+      return this.images;
+    },
+    /**
+     * 删除图片
+     *@author GuoZhiBo 20171201
+     */
+    deleteImg(index) {
+      var _self = this;
+      _self.images.splice(index, 1);
+    },
+    //----------文件------------
+    /**
+     * 删除文件
+     * @param  {String} item 文件Name
+     */
+    removeFile: function (index) {
+      var _self = this;
+      _self.files.splice(index, 1);
+    },
+    /**
+     * 选择文件发生改变
+     * @param  {[type]} e [description]
+     * @return {[type]}   [description]
+     */
+    onFileChanges: function (e) {
+      var files = e.target.files || e.dataTransfer.files;
+      if (!files.length) return;
+      this.uploadFile(files[0]);
+    },
+
+    /**
+     * 上传文件
+     * @param  {File} selectedFile 选择的文件
+     */
+    uploadFile: function (selectedFile) {
+      var _self = this;
+      if (selectedFile == undefined) {
+        return;
+      }
+      var size = undefined;
+      if (
+        _self.traceConfigDto.commentAttachmentSize != undefined &&
+        _self.traceConfigDto.commentAttachmentSize != null
+      ) {
+        size = _self.traceConfigDto.commentAttachmentSize;
+      }
+      //当系统没有配置附件大小时默认8m
+      if (size == undefined) {
+        size = 8;
+      }
+      if (selectedFile.size != undefined && selectedFile.size != null) {
+        if (selectedFile.size / 1024 <= 1024 * size) {
+          var formData = new FormData();
+          formData.append('files', selectedFile);
+          formData.append('className', _self.className);
+          _self.loading=true;
+          $.ajax({
+            url: Common.getApiURL('file/classFileUpload'),
+            type: 'post',
+            beforeSend: function (request) {
+              Common.addTokenToRequest(request);
+            },
+            data: formData,
+            contentType: false,
+            processData: false,
+            success: function (data) {
+              _self.loading=false;
+              if (data.errorCode == 0) {
+                if (data.datas) {
+                  var fileName = data.datas[0];
+                  _self.files.push(fileName);
+                }
+              } else {
+                message.error(data.errorMessage);
+              }
+
+            },
+            error: function (XMLHttpRequest, textStatus, errorThrown) {
+              _self.loading=false;
+              Common.processException(XMLHttpRequest, textStatus, errorThrown);
+            },
+          });
+        } else {
+          Notify.error(
+            '提示',
+            '文件大小不能超过' + size + 'M,可在任务配置功能中配置!',
+          );
+        }
+      } else {
+        Notify.error('提示', '上传的文件为空!');
+      }
+    },
+    /**
+     * 获取任务管理配置
+     */
+    getTraceConfig: function () {
+      var _self = this;
+      $.ajax({
+        url: Common.getApiURL('TraceConfigResource/queryTraceConfigDto'),
+        type: 'get',
+        dataType: 'json',
+        beforeSend: function (request) {
+          Common.addTokenToRequest(request);
+        },
+
+        success: function (data) {
+          _self.traceConfigDto = data;
+        },
+        error: function (XMLHttpRequest, textStatus, errorThrown) {
+          Common.processException(XMLHttpRequest, textStatus, errorThrown);
+        },
+      });
+    },
+    /**
+     * 获取文件地址
+     * @param  {String} item 图片名称
+     * @return {String}      图片URL地址
+     */
+    getFileSrc: function (item) {
+      var _self = this;
+      if (item != undefined && item != null) {
+        return Common.getResourceUrl('file', _self.className, item);
+      } else {
+        return '';
+      }
+    },
+
+    /**
+     * 下载文件
+     * @param  {String} fileName 文件名
+     * @return {void}
+     */
+    download: function (fileName) {
+      var _self = this;
+      DownloadService.fileDownload(_self.className, fileName);
+    },
+
+    //内容图片上传
+    sendFile: function (file, editor, $editable) {
+      var _self = this;
+      UpladFile.photoCompress(
+        file,
+        {
+          quality: 1,
+        },
+        function (base64Codes) {
+          var bl = UpladFile.convertBase64UrlToBlob(base64Codes);
+          var rst = new FormData();
+          rst.append('images', bl, 'file_' + Date.parse(new Date()) + '.jpg');
+          rst.append('className', _self.className);
+          $.ajax({
+            url: Common.getApiURL('file/imageUpload'),
+            type: 'post',
+            data: rst,
+            contentType: false,
+            processData: false,
+            beforeSend: function (request) {
+              Common.addTokenToRequest(request);
+            },
+            success: function (data) {
+              if (data.errorCode == 0) {
+                if (data.datas) {
+                  var imageName = data.datas[0];
+                  $('#summernote').summernote(
+                    'insertImage',
+                    Common.getResourceUrl('image', _self.className, imageName),
+                    'image name',
+                  );
+                }
+              } else {
+                message.error(data.errorMessage);
+              }
+            },
+            error: function () {
+              Notify.error('提示', '上传失败!');
+              return;
+            },
+          });
+          return rst.file;
+        },
+      );
+    },
+
+    /**
+     * 保存评论表数据
+     * @author GuoZhiBo 20171201
+     */
+    photograph: function () {
+      var _self = this;
+      _self.content = $('#summernote').summernote('code');
+      if (_self.content != '' && _self.content != null) {
+        var traceComment = {
+          traceId: _self.traceId,
+          content: _self.content,
+          attachments: _self.files.join(','),
+          carbonCopyUserIds: _self.userIds.join(','),
+          windowNo: _self.windowNo,
+        };
+        _self.loading=true;
+        $.ajax({
+          url: Common.getApiURL('CurdWindowCommentResource/saveCurdWindowComment'),
+          type: 'post',
+          contentType: 'application/json',
+          beforeSend: function (request) {
+            Common.addTokenToRequest(request);
+          },
+          data: JSON.stringify(traceComment),
+          success: function (data) {
+            _self.loading=false;
+            // _self.back();
+          },
+          error: function (XMLHttpRequest, textStatus, errorThrown) {
+            _self.loading=false;
+            Common.processException(XMLHttpRequest, textStatus, errorThrown);
+          },
+        });
+      } else {
+        Notify.error('提示', '请填写评论内容!');
+      }
+
+      
+    },
+
+    back: function () {
+      history.back();
+    },
+
+    // 获取通知(供外部调用)
+    getNotification: function () {
+      var _self = this;
+      var contentText = _self.content;
+      if(contentText.indexOf('<img src=') != -1 || _self.files.length > 0) {
+        contentText = '您有份文件评论,请在“待审阅”中查看。';
+      } else {
+        var regex = /<[^>]+>/g;
+        contentText = contentText.replace(regex, '');
+      }
+      console.log(contentText);
+      var notification = {
+        userIds: _self.userIds,
+        theme: _self.theme,
+        contentText: contentText,
+      };
+      return notification;
+    },
+  },
+};
+</script>
+<style scoped>
+.mui-divs3 {
+  margin-top: 10px;
+}
+.file-input {
+  width: 0.1px;
+  height: 0.1px;
+  opacity: 0;
+  overflow: hidden;
+  position: absolute;
+  z-index: -1;
+}
+.badge {
+  cursor: pointer;
+  background-color: #428bca;
+  color: white;
+}
+</style>

+ 127 - 0
src/window/tabFormView/TabFormView.vue

@@ -295,6 +295,35 @@
       <TabAudit v-if="showAuditPanel" :window-no="windowNo" :tab-index="tabIndex" :tab="tab" :model-data="modelData" />
     </Modal>
 
+    <Modal v-model:show="modal3" :large="true" :show-canel-button="false" :show-ok-button="false">
+      <TraceCommentCreate ref="traceCommentCreate" :trace-id="modelData.id" :window-no="modelData.windowNo" />
+      <template #footer>
+        <button type="submit" class="btn btn-default" @click="saveAndSendNotification">
+          推送
+        </button>
+        <button type="button" class="btn btn-default" @click="cancelNotification">
+          取消
+        </button>
+      </template>
+    </Modal>
+
+    <div>
+      <button
+        type="button"
+        style="width: 100%; margin-top: 5px"
+        class="btn btn-default"
+        aria-label="Left Align"
+        @click="openTraceComment"
+      >
+        <span class="glyphicon glyphicon-pencil" aria-hidden="true" />评论
+      </button>
+    </div>
+    <div>
+      <div class="page-header">
+        <h4>评论信息</h4>
+      </div>
+      <TraceComment ref="traceComment" :trace-id="modelData.id" />
+    </div>
     <Loading v-if="loading" />
   </div>
 </template>
@@ -331,6 +360,11 @@ import CurdWindowEditResource from '../../api/dic/CurdWindowEditResource.js';
 import JsUtil from '../../common/JsUtil.js';
 import { Notify, Uuid } from 'pc-component-v3';
 
+
+import TraceComment from './CurdWindowComment.vue';
+import TraceCommentCreate from './CurdWindowCommentCreate.vue';
+import NotificationPanel from '../../customer/NotificationPanel.vue';
+
 export default {
 
   components: {
@@ -345,7 +379,11 @@ export default {
     ApproveComment,
     TabAudit,
     WorkflowUserDefine,
+    TraceComment,
+    TraceCommentCreate,
+    NotificationPanel,
   },
+
   data: function () {
     this.Language = Language;
     return {
@@ -392,10 +430,13 @@ export default {
       jsUrl: null,
       loading: false,
       modal2: false,
+      modal3: false,
+      notificationModal: false,
     };
   },
 
   computed: {
+
     /**
      * 是否显示审批按钮
      */
@@ -733,6 +774,92 @@ export default {
   },
 
   methods: {
+
+    /**
+     * 打开评论界面进行评论
+     * @author GuoZhiBo 20171201
+     */
+    openTraceComment: function () {
+      var _self = this;
+      // this.$router.push('/trace/traceCommentCreate/' + _self.recordId);
+      _self.modal3 = true;
+      console.log(_self.modelData);
+      console.log(_self.modelData.id);
+    },
+
+    saveAndSendNotification: function () {
+      var _self = this;
+      var status = _self.$refs.traceCommentCreate.photograph();
+      console.log('11111111111 '+ status);
+      _self.sendNotification();
+    },
+
+    // 发送通知
+    sendNotification: function () {
+      var _self = this;
+      var notification = _self.$refs.traceCommentCreate.getNotification();
+      var recordIds = [];
+      recordIds.push(_self.modelData.id);
+      if (recordIds.length == 0) {
+        Notify.error(_self.$t('lang.Notify.error'), _self.$t('lang.tabButton.describe7'), true);
+        return;
+      }
+      if (notification.userIds == null || notification.userIds.length == 0) {
+        Notify.error(_self.$t('lang.Notify.error'), _self.$t('lang.tabButton.describe8'), true);
+        return;
+      }
+      if (notification.theme == null || notification.theme.trim() == '') {
+        Notify.error(_self.$t('lang.Notify.error'), _self.$t('lang.tabButton.describe9'), true);
+        return;
+      }
+      if (notification.contentText == null || notification.contentText.trim() == '') {
+        Notify.error(_self.$t('lang.Notify.error'), _self.$t('lang.tabButton.describe10'), true);
+        return;
+      }
+      notification.windowNo = _self.modelData.windowNo;
+      notification.tabIndex = _self.tabIndex;
+      notification.recordIds = recordIds;
+      notification.className = _self.tab.tabDataSource.className;
+      notification.category = 'CurdWindow';
+      notification.documentName = 'view';
+      if(_self.modelData.data.processInstanceId != undefined || _self.modelData.data.processInstanceId != null) {
+        notification.processInstanceId = _self.modelData.data.processInstanceId.displayValue[0];
+      }
+      if(_self.modelData.data.documentNo != undefined || _self.modelData.data.documentNo != null) {
+        notification.documentNo = _self.modelData.data.documentNo.displayValue[0];
+      }
+      if(_self.modelData.data.documentCreateUser != undefined || _self.modelData.data.documentCreateUser != null) {
+        notification.documentUserNickName = _self.modelData.data.documentCreateUser.displayValue[0];
+      }
+
+      _self.loading=true;
+      $.ajax({
+        url: Common.getApiURL('notificationResource/send'),
+        type: 'post',
+        beforeSend: function (request) {
+          Common.addTokenToRequest(request);
+        },
+        contentType: 'application/json',
+        data: JSON.stringify(notification),
+        success: function (data) {
+          _self.loading=false;
+          Notify.success(_self.$t('lang.tabButton.describe11'), _self.$t('lang.tabButton.describe12'), true);
+          _self.modal3 = false;
+          _self.$refs.traceComment.getTraceComment();
+        },
+        error: function (XMLHttpRequest, textStatus, errorThrown) {
+          _self.loading=false;
+          Common.processException(XMLHttpRequest, textStatus, errorThrown);
+        },
+      });
+    },
+
+    // 取消发送
+    cancelNotification: function () {
+      var _self = this;
+      _self.modal3 = false;
+    },
+
     /**
          * 获取审批图片
          */