riku
2026-01-22 f14ea940fb32105de8b592992e3f53c62f31d84d
2026.1.22

1. 新增台账上传pdf,word,excel,ppt文件功能.
已修改21个文件
已添加6个文件
1646 ■■■■■ 文件已修改
component/filegrid/index.js 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
component/filegrid/index.json 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
component/filegrid/index.wxml 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
component/filegrid/index.wxss 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
component/uploader/uploader.js 868 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
component/uploader/uploader.wxml 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
component/uploader/uploader.wxss 66 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
libs/weui.wxss 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/mExtra/pSupervisionchangeDetail/pSupervisionchangeDetail.wxml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/mLedger/behaviors/bUploadLedger.js 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/mLedger/behaviors/bUploadSelfPatrol.js 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/mLedger/ledgerhistory/ledgerhistory.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/mLedger/ledgerhistory/ledgerhistory.json 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/mLedger/ledgerhistory/ledgerhistory.wxml 35 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/mLedger/ledgerhistory/ledgerhistory.wxss 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/mLedger/ledgerhistory/utils.wxs 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/mLedger/ledgerupload/ledgerupload.js 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/mLedger/ledgerupload/ledgerupload.json 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/mLedger/ledgerupload/ledgerupload.wxml 67 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/mLedger/ledgerupload/ledgerupload.wxss 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/mSelfPatrol/components/self-patrol/index.js 61 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/mSelfPatrol/patrolpromise/index.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/mSelfPatrol/patrolpromise/index.wxml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/baserequest.js 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/ledgerservice.js 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/selfpatrolservice.js 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/serviceutils.js 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
component/filegrid/index.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,115 @@
// component/filegrid/index.js
Component({
  options: {
    addGlobalClass: true,
  },
  /**
   * ç»„件的属性列表
   */
  properties: {
    files: {
      type: Array,
      value: [],
      observer(newVal) {
        this.formatFiles(newVal);
      },
    },
    gridHeight: {
      type: String,
      value: '29vw',
    },
    gridWidth: {
      type: String,
      value: '29vw',
    },
  },
  /**
   * ç»„件的初始数据
   */
  data: {
    currentFiles: [],
  },
  /**
   * ç»„件的方法列表
   */
  methods: {
    formatFiles(value) {
      const currentFiles = value.map(f => {
        // æ ¹æ®æ–‡ä»¶ç±»åž‹é€‰æ‹©ä¸åŒæ ·å¼
        let extensionClass = '';
        switch (f.ext) {
          case 'xls':
          case 'xlsx':
          case 'csv':
            extensionClass = 'file_xlsx';
            break;
          case 'doc':
          case 'docx':
            extensionClass = 'file_word';
            break;
          case 'pdf':
            extensionClass = 'file_pdf';
            break;
          case 'ppt':
          case 'pptx':
            extensionClass = 'file_ppt';
            break;
          default:
            break;
        }
        return { ...f, styleClass: extensionClass };
      });
      this.setData({ currentFiles });
    },
    //图片放大预览
    previewImage(e) {
      const { index } = e.currentTarget.dataset;
      const f = this.data.currentFiles[index];
      const previewImageUrls = this.data.currentFiles
        .filter(f => f.type == 'image')
        .map(f => f.url);
      const i = previewImageUrls.indexOf(f.url);
      this.setData({
        previewImageUrls,
        previewCurrent: i,
        showPreview: true,
      });
    },
    // æŸ¥çœ‹æ–‡ä»¶
    previewFile(e) {
      const { index } = e.currentTarget.dataset;
      const file = this.data.currentFiles[index];
      if (file.url.indexOf('http') != -1) {
        wx.showLoading({
          title: '下载文件中',
          mask: true,
        });
        wx.downloadFile({
          url: file.url,
          success: res => {
            wx.hideLoading();
            if (res.statusCode === 200) {
              const filePath = res.tempFilePath;
              wx.openDocument({ filePath: filePath });
            } else {
              wx.showToast({
                title: '文件下载失败',
                icon: 'error',
              });
            }
          },
          fail(err) {
            wx.showToast({
              title: '文件下载失败',
              icon: 'error',
            });
          },
        });
      } else {
        wx.openDocument({ filePath: file.url });
      }
    },
  },
});
component/filegrid/index.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,6 @@
{
  "component": true,
  "usingComponents": {
    "my-gallery": "/component/mygallery/mygallery"
  }
}
component/filegrid/index.wxml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,46 @@
<!--component/filegrid/index.wxml-->
<view class="img-group">
  <block wx:for="{{currentFiles}}" wx:key="index">
    <!-- å›¾ç‰‡ -->
    <image
      wx:if="{{item.type == 'image'}}"
      class="img-group_img"
      style="{{'width:'+gridWidth+';height:'+gridHeight+';'}}"
      src="{{item.url}}"
      mode="aspectFill"
      bindtap="previewImage"
      data-index="{{index}}"
      show-menu-by-longpress="{{true}}"
    ></image>
    <!-- å¸¸è§office文件 -->
    <view
      wx:elif="{{item.type == 'file'}}"
      data-index="{{index}}"
      bindtap="previewFile"
      class="img-group_img"
      style="{{'width:'+gridWidth+';height:'+gridHeight+';'}}"
    >
      <view class="{{'uploader-preview__file ' + item.styleClass}}">
        <view class="wrap">
          <span class="{{'txt ' + item.styleClass}}">{{item.name}}</span>
        </view>
        <text class="unit" data-ext="{{item.ext}}">{{item.size}}</text>
      </view>
    </view>
    <!-- å…¶ä»– -->
    <view
      wx:else
      data-index="{{index}}"
      class="img-group_img uploader-preview__file"
    >
      <t-icon name="close-circle" size="36rpx" />
    </view>
  </block>
</view>
<my-gallery
  hide-on-click="{{true}}"
  show-delete="{{false}}"
  show="{{showPreview}}"
  img-urls="{{previewImageUrls}}"
  current="{{previewCurrent}}"
></my-gallery>
component/filegrid/index.wxss
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,74 @@
/* component/filegrid/index.wxss */
.img-group {
  display: flex;
  flex-wrap: wrap;
}
.img-group .img-group_img {
  /* width: attr(data-width);
  height: attr(data-height); */
  margin-bottom: 8px;
  margin-right: 8px;
}
.uploader-preview__file {
  --default-bg-color: #888888;
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  background-color: var(--default-bg-color);
  color: white;
  height: 100%;
  font-size: 12px;
}
.wrap {
  height: 3em;
  line-height: 1.5;
  overflow: hidden;
  /* background-color: rgb(0, 104, 104); */
  margin: 8rpx 8rpx 0 8rpx;
  text-align: justify;
}
.wrap .txt {
  max-height: 3em;
  /* background-color: rgb(88, 104, 0); */
  /* margin: 8rpx 8rpx 0 8rpx; */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
}
.unit {
  margin: 0rpx 8rpx 8rpx 8rpx;
}
.unit::after {
  content: attr(data-ext);
  position: absolute;
  bottom: 0rpx;
  right: 10rpx;
  font-size: 30px;
  color: #ffffff38;
}
.file_xlsx {
  background-color: #278553;
}
.file_word {
  background-color: #3980C0;
}
.file_pdf {
  background-color: #C84E39;
}
.file_ppt {
  background-color: #FF7A42;
}
component/uploader/uploader.js
@@ -1,13 +1,12 @@
module.exports =
  /******/
  (function (modules) { // webpackBootstrap
  (function (modules) {
    // webpackBootstrap
    /******/ // The module cache
    /******/
    var installedModules = {};
    var installedModules = {}; /******/ // The require function
    /******/
    /******/ // The require function
    /******/
    function __webpack_require__(moduleId) {
    /******/ function __webpack_require__(moduleId) {
      /******/
      /******/ // Check if module is in cache
      /******/
@@ -15,88 +14,72 @@
        /******/
        return installedModules[moduleId].exports;
        /******/
      }
      /******/ // Create a new module (and put it into the cache)
      /******/
      var module = installedModules[moduleId] = {
      } /******/ // Create a new module (and put it into the cache)
      /******/ var module = (installedModules[moduleId] = {
        /******/
        i: moduleId,
        /******/
        l: false,
        /******/
        exports: {}
        exports: {},
        /******/
      };
      }); /******/ // Execute the module function
      /******/
      /******/ // Execute the module function
      /******/ modules[moduleId].call(
        module.exports,
        module,
        module.exports,
        __webpack_require__,
      ); /******/ // Flag the module as loaded
      /******/
      modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
      /******/ module.l = true; /******/ // Return the exports of the module
      /******/
      /******/ // Flag the module as loaded
      /******/ return module.exports;
      /******/
      module.l = true;
      /******/
      /******/ // Return the exports of the module
      /******/
      return module.exports;
      /******/
    }
    } /******/ // expose the modules object (__webpack_modules__)
    /******/
    /******/
    /******/ // expose the modules object (__webpack_modules__)
    /******/ __webpack_require__.m = modules; /******/ // expose the module cache
    /******/
    __webpack_require__.m = modules;
    /******/ __webpack_require__.c = installedModules; /******/ // define getter function for harmony exports
    /******/
    /******/ // expose the module cache
    /******/
    __webpack_require__.c = installedModules;
    /******/
    /******/ // define getter function for harmony exports
    /******/
    __webpack_require__.d = function (exports, name, getter) {
    /******/ __webpack_require__.d = function (exports, name, getter) {
      /******/
      if (!__webpack_require__.o(exports, name)) {
        /******/
        Object.defineProperty(exports, name, {
          enumerable: true,
          get: getter
          get: getter,
        });
        /******/
      }
      /******/
    };
    }; /******/ // define __esModule on exports
    /******/
    /******/ // define __esModule on exports
    /******/
    __webpack_require__.r = function (exports) {
    /******/ __webpack_require__.r = function (exports) {
      /******/
      if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {
        /******/
        Object.defineProperty(exports, Symbol.toStringTag, {
          value: 'Module'
          value: 'Module',
        });
        /******/
      }
      /******/
      Object.defineProperty(exports, '__esModule', {
        value: true
        value: true,
      });
      /******/
    };
    }; /******/ /******/ /******/ /******/ /******/ // create a fake namespace object // mode & 1: value is a module id, require it // mode & 2: merge all properties of value into the ns // mode & 4: return value when already ns object // mode & 8|1: behave like require
    /******/
    /******/ // create a fake namespace object
    /******/ // mode & 1: value is a module id, require it
    /******/ // mode & 2: merge all properties of value into the ns
    /******/ // mode & 4: return value when already ns object
    /******/ // mode & 8|1: behave like require
    /******/
    __webpack_require__.t = function (value, mode) {
    /******/ __webpack_require__.t = function (value, mode) {
      /******/
      if (mode & 1) value = __webpack_require__(value);
      /******/
      if (mode & 8) return value;
      /******/
      if ((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
      if (mode & 4 && typeof value === 'object' && value && value.__esModule)
        return value;
      /******/
      var ns = Object.create(null);
      /******/
@@ -104,407 +87,436 @@
      /******/
      Object.defineProperty(ns, 'default', {
        enumerable: true,
        value: value
        value: value,
      });
      /******/
      if (mode & 2 && typeof value != 'string')
        for (var key in value) __webpack_require__.d(ns, key, function (key) {
          return value[key];
        }.bind(null, key));
        for (var key in value)
          __webpack_require__.d(
            ns,
            key,
            function (key) {
              return value[key];
            }.bind(null, key),
          );
      /******/
      return ns;
      /******/
    };
    }; /******/ // getDefaultExport function for compatibility with non-harmony modules
    /******/
    /******/ // getDefaultExport function for compatibility with non-harmony modules
    /******/
    __webpack_require__.n = function (module) {
    /******/ __webpack_require__.n = function (module) {
      /******/
      var getter = module && module.__esModule ?
        /******/
        function getDefault() {
          return module['default'];
        } :
        /******/
        function getModuleExports() {
          return module;
        };
      var getter =
        module && module.__esModule
          ? /******/
            function getDefault() {
              return module['default'];
            }
          : /******/
            function getModuleExports() {
              return module;
            };
      /******/
      __webpack_require__.d(getter, 'a', getter);
      /******/
      return getter;
      /******/
    };
    }; /******/ // Object.prototype.hasOwnProperty.call
    /******/
    /******/ // Object.prototype.hasOwnProperty.call
    /******/
    __webpack_require__.o = function (object, property) {
    /******/ __webpack_require__.o = function (object, property) {
      return Object.prototype.hasOwnProperty.call(object, property);
    };
    }; /******/ // __webpack_public_path__
    /******/
    /******/ // __webpack_public_path__
    /******/
    __webpack_require__.p = "";
    /******/ __webpack_require__.p = ''; /******/ // Load entry module and return exports
    /******/
    /******/
    /******/ // Load entry module and return exports
    /******/ return __webpack_require__((__webpack_require__.s = 22));
    /******/
    return __webpack_require__(__webpack_require__.s = 22);
  })(
    /************************************************************************/
    /******/
  })
/************************************************************************/
/******/
({
  /***/
  22:
    /***/
    (function (module, exports, __webpack_require__) {
      "use strict";
      Component({
        options: {
          addGlobalClass: true
        },
        properties: {
          title: {
            type: String,
            value: ''
          },
          titleClass: {
            type: "String",
            value: ""
          },
          sizeType: {
            type: Array,
            value: ['original', 'compressed']
          },
          sourceType: {
            type: Array,
            value: ['album', 'camera']
          },
          maxSize: {
            type: Number,
            value: 5 * 1024 * 1024
          },
          maxCount: {
            // æœ€å¤šä¸Šä¼ å¤šå°‘个文件
            type: Number,
            value: 1
          },
          countInfo: {
            type: String,
            value: ""
          },
          files: {
            // å½“前的图片列表, {url, error, loading}
            type: Array,
            value: [],
            observer(newVal) {
              this.setData({
                currentFiles: newVal
              });
            }
          },
          select: {
            // è¿‡æ»¤æŸä¸ªæ–‡ä»¶
            type: null,
            value: null
          },
          upload: {
            // è¿”回Promise的一个文件上传的函数
            type: null,
            value: () => {}
          },
          tips: {
            type: String,
            value: ''
          },
          extClass: {
            type: String,
            value: ''
          },
          showDelete: {
            // æ˜¯å¦æ˜¾ç¤ºdelete按钮
            type: Boolean,
            value: true
          }
        },
        data: {
          currentFiles: [],
          showPreview: false,
          previewImageUrls: [],
          groups: [{
            text: '选择图片',
            value: 0
          }, {
            text: '从聊天记录选择文件',
            value: 1
          }],
        },
        ready() {},
        methods: {
          showActionSheet() {
            this.setData({
              showSheet: true
            })
          },
          previewImage(e) {
            const {
              index
            } = e.currentTarget.dataset;
            const previewImageUrls = [];
            this.data.files.forEach(item => {
              previewImageUrls.push(item.url);
            });
            this.setData({
              previewImageUrls,
              previewCurrent: index,
              showPreview: true
            });
          },
          previewFile(e) {
            const {
              index
            } = e.currentTarget.dataset;
            const file = this.data.files[index]
            wx.openDocument({
              filePath: file.url,
            });
          },
          actionClick(e) {
            switch (e.detail.value) {
              case 0:
                this.chooseImage()
                break;
              case 1:
                this.chooseMessageFile()
                break;
              default:
                this.chooseImage()
                break;
            }
            this.setData({
              showSheet: false
            })
          },
          chooseImage() {
            if (this.uploading) return;
            wx.chooseMedia({
              count: this.data.maxCount - this.data.files.length,
              sizeType: ['compressed'],
              mediaType: ['image'],
              success: res => {
                console.log('chooseImage resp', res)
                // é¦–先检查文件大小
                let invalidIndex = -1; // @ts-ignore
                res.tempFilePaths = res.tempFiles.map(item => item.tempFilePath)
                res.tempFiles.forEach((item, index) => {
                  if (item.size > this.data.maxSize) {
                    invalidIndex = index;
                  }
                });
                if (typeof this.data.select === 'function') {
                  const ret = this.data.select(res);
                  if (ret === false) {
                    return;
                  }
                }
                if (invalidIndex >= 0) {
                  this.triggerEvent('fail', {
                    type: 1,
                    errMsg: `chooseImage:fail size exceed ${this.data.maxSize}`,
                    total: res.tempFilePaths.length,
                    index: invalidIndex
                  }, {});
                  return;
                } // èŽ·å–æ–‡ä»¶å†…å®¹
                const mgr = wx.getFileSystemManager();
                const contents = res.tempFilePaths.map(item => {
                  // @ts-ignore
                  const fileContent = mgr.readFileSync(item);
                  return fileContent;
                });
                const obj = {
                  tempFilePaths: res.tempFilePaths,
                  tempFiles: res.tempFiles,
                  contents
                }; // è§¦å‘选中的事件,开发者根据内容来上传文件,上传了把上传的结果反馈到files属性里面
                this.triggerEvent('select', obj, {});
                let files = res.tempFiles.map((item, i) => ({
                  loading: true,
                  url: item.tempFilePath,
                  type: item.fileType,
                }))
                //压缩图片
                wx.compressImage({
                  src: files[0].url,
                  quality: 20,
                  success(data) {
                    console.log('compressImage', data)
                  },
                  fail() {
                  }
                })
                if (!files || !files.length) return;
                const newFiles = this.data.files.concat(files);
                this.setData({
                  files: newFiles,
                  currentFiles: newFiles
                });
                this.triggerEvent('uploadImg', {
                  newFiles
                }, {})
              },
              fail: fail => {
                if (fail.errMsg.indexOf('chooseImage:fail cancel') >= 0) {
                  this.triggerEvent('cancel', {}, {});
                  return;
                }
                fail.type = 2;
                this.triggerEvent('fail', fail, {});
              }
            });
          },
          chooseMessageFile() {
            if (this.uploading) return;
            wx.chooseMessageFile({
              count: this.data.maxCount - this.data.files.length,
              type: 'file',
              extension: ['xls', 'xlsx', 'csv', 'doc', 'docx', 'pdf', 'ppt', 'pptx'],
              success: res => {
                console.log('chooseMessageFile', res)
                // é¦–先检查文件大小
                let invalidIndex = -1; // @ts-ignore
                res.tempFilePaths = res.tempFiles.map(item => item.path)
                res.tempFiles.forEach((item, index) => {
                  if (item.size > this.data.maxSize) {
                    invalidIndex = index;
                  }
                });
                if (typeof this.data.select === 'function') {
                  const ret = this.data.select(res);
                  if (ret === false) {
                    return;
                  }
                }
                if (invalidIndex >= 0) {
                  this.triggerEvent('fail', {
                    type: 1,
                    errMsg: `chooseMessageFile:fail size exceed ${this.data.maxSize}`,
                    total: res.tempFilePaths.length,
                    index: invalidIndex
                  }, {});
                  return;
                } // èŽ·å–æ–‡ä»¶å†…å®¹
                const mgr = wx.getFileSystemManager();
                const contents = res.tempFilePaths.map(item => {
                  // @ts-ignore
                  const fileContent = mgr.readFileSync(item);
                  return fileContent;
                });
                const obj = {
                  tempFilePaths: res.tempFilePaths,
                  tempFiles: res.tempFiles,
                  contents
                }; // è§¦å‘选中的事件,开发者根据内容来上传文件,上传了把上传的结果反馈到files属性里面
                this.triggerEvent('select', obj, {});
                let files = res.tempFiles.map((item, i) => {
                  // åˆ¤æ–­æ–‡ä»¶ç±»åž‹ï¼Œå¯¹åº”不同样式
                  let extensionClass = ''
                  switch (item.name.split('.')[1]) {
                    case 'xls':
                    case 'xlsx':
                    case 'csv':
                      extensionClass = 'file_xlsx'
                      break;
                    case 'doc':
                    case 'docx':
                      extensionClass = 'file_word'
                      break;
                    case 'pdf':
                      extensionClass = 'file_pdf'
                      break;
                    case 'ppt':
                    case 'pptx':
                      extensionClass = 'file_ppt'
                      break;
                    default:
                      break;
                  }
                  // æ‹†åˆ†æ–‡ä»¶åç§°ï¼Œå®žçŽ°æ–‡æœ¬è¿‡é•¿æ—¶ï¼Œä¸­é—´çœç•¥
                  const ellipsisName = {
                    start: item.name.slice(0, -5),
                    // å–末尾5个字符常态显示
                    end: item.name.substr(-5, 5)
                  }
                  // æ–‡ä»¶å¤§å°æ ¼å¼åŒ–
                  let size = parseInt(item.size / 1024)
                  if (size > 1024) {
                    size = parseInt(size / 1024) + ' MB'
                  } else {
                    size += ' KB'
                  }
                  return {
                    loading: true,
                    url: item.path,
                    name: item.name,
                    ellipsisName,
                    styleClass: extensionClass,
                    type: item.type,
                    time: item.time,
                    size
                  }
                })
                if (!files || !files.length) return;
                const newFiles = this.data.files.concat(files);
                this.setData({
                  files: newFiles,
                  currentFiles: newFiles
                });
                this.triggerEvent('uploadImg', {
                  newFiles
                }, {})
              }
            })
          },
          deletePic(e) {
            const index = e.detail.index;
            const files = this.data.files;
            const file = files.splice(index, 1);
            this.setData({
              files,
              currentFiles: files
            });
            this.triggerEvent('delete', {
              index,
              item: file[0]
            });
          },
        }
      });
    {
      /***/
    })
      22:
        /***/
        function (module, exports, __webpack_require__) {
          'use strict';
  /******/
});
          Component({
            options: {
              addGlobalClass: true,
            },
            properties: {
              title: {
                type: String,
                value: '',
              },
              titleClass: {
                type: 'String',
                value: '',
              },
              sizeType: {
                type: Array,
                value: ['original', 'compressed'],
              },
              sourceType: {
                type: Array,
                value: ['album', 'camera'],
              },
              maxSize: {
                type: Number,
                value: 5 * 1024 * 1024,
              },
              maxCount: {
                // æœ€å¤šä¸Šä¼ å¤šå°‘个文件
                type: Number,
                value: 1,
              },
              countInfo: {
                type: String,
                value: '',
              },
              files: {
                // å½“前的图片列表, {url, error, loading}
                type: Array,
                value: [],
                observer(newVal) {
                  this.setData({
                    currentFiles: newVal,
                  });
                },
              },
              select: {
                // è¿‡æ»¤æŸä¸ªæ–‡ä»¶
                type: null,
                value: null,
              },
              upload: {
                // è¿”回Promise的一个文件上传的函数
                type: null,
                value: () => {},
              },
              tips: {
                type: String,
                value: '',
              },
              extClass: {
                type: String,
                value: '',
              },
              showDelete: {
                // æ˜¯å¦æ˜¾ç¤ºdelete按钮
                type: Boolean,
                value: true,
              },
              allowFiles: {
                // æ˜¯å¦å…è®¸é€‰æ‹©å›¾ç‰‡ä¹‹å¤–的其他格式文件
                type: Boolean,
                value: false,
              },
            },
            data: {
              currentFiles: [],
              showPreview: false,
              previewImageUrls: [],
              groups: [
                {
                  text: '选择图片',
                  value: 0,
                },
                {
                  text: '从聊天记录选择文件',
                  value: 1,
                },
              ],
            },
            ready() {},
            methods: {
              showActionSheet() {
                if (this.data.allowFiles) {
                  this.setData({
                    showSheet: true,
                  });
                } else {
                  this.chooseImage();
                }
              },
              previewImage(e) {
                const { index } = e.currentTarget.dataset;
                const f = this.data.files[index];
                const previewImageUrls = this.data.files
                  .filter(f => f.type == 'image')
                  .map(f => f.url);
                const i = previewImageUrls.indexOf(f.url);
                this.setData({
                  previewImageUrls,
                  previewCurrent: i,
                  showPreview: true,
                });
              },
              previewFile(e) {
                const { index } = e.currentTarget.dataset;
                const file = this.data.files[index];
                wx.openDocument({
                  filePath: file.url,
                });
              },
              actionClick(e) {
                switch (e.detail.value) {
                  case 0:
                    this.chooseImage();
                    break;
                  case 1:
                    this.chooseMessageFile();
                    break;
                  default:
                    this.chooseImage();
                    break;
                }
                this.setData({
                  showSheet: false,
                });
              },
              chooseImage() {
                if (this.uploading) return;
                wx.chooseMedia({
                  count: this.data.maxCount - this.data.files.length,
                  sizeType: ['compressed'],
                  mediaType: ['image'],
                  success: res => {
                    console.log('chooseImage resp', res);
                    // é¦–先检查文件大小
                    let invalidIndex = -1; // @ts-ignore
                    res.tempFilePaths = res.tempFiles.map(
                      item => item.tempFilePath,
                    );
                    res.tempFiles.forEach((item, index) => {
                      if (item.size > this.data.maxSize) {
                        invalidIndex = index;
                      }
                    });
                    if (typeof this.data.select === 'function') {
                      const ret = this.data.select(res);
                      if (ret === false) {
                        return;
                      }
                    }
                    if (invalidIndex >= 0) {
                      this.triggerEvent(
                        'fail',
                        {
                          type: 1,
                          errMsg: `chooseImage:fail size exceed ${this.data.maxSize}`,
                          total: res.tempFilePaths.length,
                          index: invalidIndex,
                        },
                        {},
                      );
                      return;
                    } // èŽ·å–æ–‡ä»¶å†…å®¹
                    const mgr = wx.getFileSystemManager();
                    const contents = res.tempFilePaths.map(item => {
                      // @ts-ignore
                      const fileContent = mgr.readFileSync(item);
                      return fileContent;
                    });
                    const obj = {
                      tempFilePaths: res.tempFilePaths,
                      tempFiles: res.tempFiles,
                      contents,
                    }; // è§¦å‘选中的事件,开发者根据内容来上传文件,上传了把上传的结果反馈到files属性里面
                    this.triggerEvent('select', obj, {});
                    let files = res.tempFiles.map((item, i) => ({
                      loading: true,
                      url: item.tempFilePath,
                      type: item.fileType,
                    }));
                    //压缩图片
                    wx.compressImage({
                      src: files[0].url,
                      quality: 20,
                      success(data) {
                        console.log('compressImage', data);
                      },
                      fail() {},
                    });
                    if (!files || !files.length) return;
                    const newFiles = this.data.files.concat(files);
                    this.setData({
                      files: newFiles,
                      currentFiles: newFiles,
                    });
                    this.triggerEvent(
                      'uploadImg',
                      {
                        newFiles,
                      },
                      {},
                    );
                  },
                  fail: fail => {
                    if (fail.errMsg.indexOf('chooseImage:fail cancel') >= 0) {
                      this.triggerEvent('cancel', {}, {});
                      return;
                    }
                    fail.type = 2;
                    this.triggerEvent('fail', fail, {});
                  },
                });
              },
              chooseMessageFile() {
                if (this.uploading) return;
                wx.chooseMessageFile({
                  count: this.data.maxCount - this.data.files.length,
                  type: 'file',
                  extension: [
                    'xls',
                    'xlsx',
                    'csv',
                    'doc',
                    'docx',
                    'pdf',
                    'ppt',
                    'pptx',
                  ],
                  success: res => {
                    console.log('chooseMessageFile', res);
                    // é¦–先检查文件大小
                    let invalidIndex = -1; // @ts-ignore
                    res.tempFilePaths = res.tempFiles.map(item => item.path);
                    res.tempFiles.forEach((item, index) => {
                      if (item.size > this.data.maxSize) {
                        invalidIndex = index;
                      }
                    });
                    if (typeof this.data.select === 'function') {
                      const ret = this.data.select(res);
                      if (ret === false) {
                        return;
                      }
                    }
                    if (invalidIndex >= 0) {
                      this.triggerEvent(
                        'fail',
                        {
                          type: 1,
                          errMsg: `chooseMessageFile:fail size exceed ${this.data.maxSize}`,
                          total: res.tempFilePaths.length,
                          index: invalidIndex,
                        },
                        {},
                      );
                      return;
                    } // èŽ·å–æ–‡ä»¶å†…å®¹
                    const mgr = wx.getFileSystemManager();
                    const contents = res.tempFilePaths.map(item => {
                      // @ts-ignore
                      const fileContent = mgr.readFileSync(item);
                      return fileContent;
                    });
                    const obj = {
                      tempFilePaths: res.tempFilePaths,
                      tempFiles: res.tempFiles,
                      contents,
                    }; // è§¦å‘选中的事件,开发者根据内容来上传文件,上传了把上传的结果反馈到files属性里面
                    this.triggerEvent('select', obj, {});
                    let files = res.tempFiles.map((item, i) => {
                      // åˆ¤æ–­æ–‡ä»¶ç±»åž‹ï¼Œå¯¹åº”不同样式
                      const list = item.name.split('.');
                      const ext = list[list.length - 1];
                      let extensionClass = '';
                      switch (ext) {
                        case 'xls':
                        case 'xlsx':
                        case 'csv':
                          extensionClass = 'file_xlsx';
                          break;
                        case 'doc':
                        case 'docx':
                          extensionClass = 'file_word';
                          break;
                        case 'pdf':
                          extensionClass = 'file_pdf';
                          break;
                        case 'ppt':
                        case 'pptx':
                          extensionClass = 'file_ppt';
                          break;
                        default:
                          break;
                      }
                      // æ–‡ä»¶å¤§å°æ ¼å¼åŒ–
                      let size = parseInt(item.size / 1024);
                      if (size > 1024) {
                        size = (size / 1024).toFixed(1) + ' MB';
                      } else {
                        size += ' KB';
                      }
                      return {
                        loading: true,
                        url: item.path,
                        name: item.name,
                        ext: ext ?? '',
                        styleClass: extensionClass,
                        type: item.type,
                        time: item.time,
                        size,
                      };
                    });
                    if (!files || !files.length) return;
                    const newFiles = this.data.files.concat(files);
                    this.setData({
                      files: newFiles,
                      currentFiles: newFiles,
                    });
                    this.triggerEvent(
                      'uploadImg',
                      {
                        newFiles,
                      },
                      {},
                    );
                  },
                });
              },
              deletePic(e) {
                const index = e.detail.index;
                this._delete(index);
              },
              deleteFile(e) {
                const { index } = e.currentTarget.dataset;
                this._delete(index);
              },
              _delete(index) {
                const files = this.data.files;
                const file = files.splice(index, 1);
                this.setData({
                  files,
                  currentFiles: files,
                });
                this.triggerEvent('delete', {
                  index,
                  item: file[0],
                });
              },
            },
          });
          /***/
        },
      /******/
    },
  );
component/uploader/uploader.wxml
@@ -14,7 +14,7 @@
  </view>
  <view class="weui-uploader__bd">
    <view class="weui-uploader__files">
      <block wx:for="{{currentFiles}}" wx:key="*this">
      <block wx:for="{{currentFiles}}" wx:key="index">
        <!-- å›¾ç‰‡ -->
        <block wx:if="{{item.type == 'image'}}">
          <view
@@ -58,6 +58,14 @@
              src="{{item.url}}"
              mode="aspectFill"
            />
            <view class="close-btn">
              <t-icon
                name="close"
                size="36rpx"
                data-index="{{index}}"
                catch:tap="deleteFile"
              ></t-icon>
            </view>
          </view>
        </block>
        <block wx:elif="{{item.type == 'file'}}">
@@ -66,14 +74,24 @@
            bindtap="previewFile"
            class="weui-uploader__file"
          >
            <view class="{{'weui-uploader__img uploader-preview__file ' + styleClass}}">
            <view
              class="{{'weui-uploader__img uploader-preview__file ' + item.styleClass}}"
            >
              <view class="wrap">
                <span class="{{'txt ' + styleClass}}">{{item.name}}</span>
                <span class="{{'filename ' + styleClass}}" data-title="{{item.name}}"
                <span class="{{'txt ' + item.styleClass}}">{{item.name}}</span>
                <!-- <span class="{{'filename ' + item.styleClass}}" data-title="{{item.name}}"
                  >{{item.name}}</span
                >
                > -->
              </view>
              <text class="unit">{{item.size + ' KB'}}</text>
              <text class="unit" data-ext="{{item.ext}}">{{item.size}}</text>
            </view>
            <view class="close-btn">
              <t-icon
                name="close"
                size="36rpx"
                data-index="{{index}}"
                catch:tap="deleteFile"
              ></t-icon>
            </view>
          </view>
        </block>
component/uploader/uploader.wxss
@@ -1,5 +1,23 @@
.close-btn {
  position: absolute;
  top: 0;
  right: 0;
  color: white;
  background-color: rgba(0, 0, 0, 0.3);
  padding: 2px;
  border-bottom-left-radius: 8px;
  border-top-left-radius: 2px;
  border-bottom-right-radius: 2px;
}
.weui-uploader__tips {
  font-size: 12px;
  color: #9c9c9c;
}
.uploader-preview__file {
  --default-bg-color: #888888;
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
@@ -10,37 +28,46 @@
}
.wrap {
  /* background-color: rgb(109, 109, 4); */
  height: 3em;
  line-height: 1.5;
  overflow: hidden;
  /* background-color: rgb(0, 104, 104); */
  margin: 8rpx 8rpx 0 8rpx;
  text-align: justify;
}
.wrap .txt {
  display: block;
  max-height: 3em;
  /* background-color: rgb(88, 104, 0); */
  /* margin: 8rpx 8rpx 0 8rpx; */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
}
.wrap .filename {
  position: relative;
  /* display: flex;
  text-align: justify; */
  /* display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical; */
  /* display: none; */
  top: -3em;
  background-color: rgb(115, 172, 118);
  /* background-color: var(--default-bg-color); */
  /* background-color: rgb(115, 172, 118); */
  background-color: var(--default-bg-color);
  overflow: hidden;
  /* text-overflow: ellipsis; */
  text-align: justify;
  /* white-space: nowrap; */
  text-overflow: ellipsis;
  white-space: nowrap;
  /* margin: 8rpx 8rpx 0 8rpx; */
}
.filename::before {
  content: attr(data-title);
  /* content: attr(data-title); */
  width: 100%;
  float: right;
  margin-top: 1.5em;
@@ -56,10 +83,27 @@
  margin: 0rpx 8rpx 8rpx 8rpx;
}
.file_xlsx {}
.unit::after {
  content: attr(data-ext);
  position: absolute;
  bottom: 0rpx;
  right: 10rpx;
  font-size: 30px;
  color: #ffffff38;
}
.file_word {}
.file_xlsx {
  background-color: #278553;
}
.file_pdf {}
.file_word {
  background-color: #3980C0;
}
.file_ppt {}
.file_pdf {
  background-color: #C84E39;
}
.file_ppt {
  background-color: #FF7A42;
}
libs/weui.wxss
@@ -1441,7 +1441,7 @@
   padding-bottom: 16px;
   -webkit-box-align: center;
   -webkit-align-items: center;
   align-items: center
   align-items: center;
 }
 
 .weui-uploader__title {
@@ -1465,6 +1465,7 @@
 }
 
 .weui-uploader__file {
   position: relative;
   float: left;
   margin-right: 8px;
   margin-bottom: 8px;
pages/mExtra/pSupervisionchangeDetail/pSupervisionchangeDetail.wxml
@@ -54,7 +54,7 @@
        </block>
        <block wx:else>
          <mp-upload
            title="上传台账图片"
            title="上传整改图片"
            titleClass="upload-title-class"
            max-count="3"
            files="{{imgFiles}}"
pages/mLedger/behaviors/bUploadLedger.js
@@ -27,6 +27,17 @@
        path.push(f.url);
      });
      let ledger = this.data.ledger;
      let namePairs = []
      this.data.imgFiles.forEach(f=>{
        // é™¤äº†å›¾ç‰‡å¤–的文档需要传输原始名字
        if (f.name) {
          const ulist = f.url.split('/')
          namePairs.push({
            first: ulist[ulist.length - 1], // ä¸Šä¼ çš„临时文件名字
            second: f.name // æ–‡ä»¶åŽŸå§‹åå­—
          })
        }
      })
      ledger.remark1 = this.data.remark;
      if (this.data.detail) {
        ledger.id = this.data.detail.id
@@ -34,9 +45,8 @@
      this.setData({ loading: true });
      ledgerservice.uploadLedger(
        app.globalData.accessToken.userId,
        ledger,
        path,
        app.globalData.accessToken.userId, ledger,
        namePairs, path,
        {
          success(res) {
            that.setData({ loading: false });
pages/mLedger/behaviors/bUploadSelfPatrol.js
@@ -19,21 +19,36 @@
      if (this.data.imgFiles.length == 0) return;
      var that = this;
      // æ–‡ä»¶è·¯å¾„
      let path = [];
      this.data.imgFiles.forEach(f => {
        path.push(f.url);
      });
      // åº”急自巡查台账信息
      const { ledger, taskId } = this.data;
      ledger.remark1 = this.data.remark;
      if (this.data.detail) {
        ledger.id = this.data.detail.id
      }
      // æ–‡ä»¶ä¸´æ—¶åç§°å’ŒåŽŸå§‹åç§°é…å¯¹ä¿¡æ¯
      let namePairs = []
      this.data.imgFiles.forEach(f=>{
        // é™¤äº†å›¾ç‰‡å¤–的文档需要传输原始名字
        if (f.name) {
          const ulist = f.url.split('/')
          namePairs.push({
            first: ulist[ulist.length - 1], // ä¸Šä¼ çš„临时文件名字
            second: f.name // æ–‡ä»¶åŽŸå§‹åå­—
          })
        }
      })
      this.setData({ loading: true });
      selfpatrolservice.uploadSelfPatrol(
        app.globalData.accessToken.userId,
        taskId,
        ledger,
        namePairs,
        path,
        {
          success(res) {
pages/mLedger/ledgerhistory/ledgerhistory.js
@@ -64,7 +64,6 @@
  onLoad(options) {
    var that = this
    this.initTime()
    this.getRecord()
    this.getOpenerEventChannel().on('acceptDataFromOpenerPage', function (data) {
      let ledgerMap = new Map()
      data.tabList.forEach(t => {
@@ -77,6 +76,7 @@
      that.setData({
        ledgerMap
      })
      that.getRecord()
    })
  },
pages/mLedger/ledgerhistory/ledgerhistory.json
@@ -1,8 +1,10 @@
{
  "navigationBarTitleText": "历史台账",
  "navigationBarBackgroundColor": "#57E4CB",
  "navigationBarTextStyle": "white",
  "usingComponents": {
    "mp-icon": "/component/icon/icon",
    "file-grid": "/component/filegrid/index",
    "my-gallery": "/component/mygallery/mygallery"
  }
}
pages/mLedger/ledgerhistory/ledgerhistory.wxml
@@ -1,4 +1,5 @@
<!--pages/mLedger/ledgerHistory/ledgerhistory.wxml-->
<wxs src="./utils.wxs" module="_" />
<import src="/template/nodata.wxml"></import>
<view class="page">
  <view class="page__hd">
@@ -49,18 +50,36 @@
          >
        </view>
        <view class="ledger-group">
          <view
          <block
            wx:for="{{item.ledgers}}"
            wx:for-item="ledger"
            wx:for-index="i2"
            wx:key="i2"
            class="ledger-group_item"
            bindtap="previewImage"
            data-index="{{i1}},{{i2}}"
          >
            <image class="" src="{{ledger.path1[0]}}" mode="aspectFill" show-menu-by-longpress="{{true}}"></image>
            <view>{{ledger.ledgerName}}</view>
          </view>
            <view
              wx:if="{{ledger._fileType == 'image'}}"
              class="ledger-group_item"
              bindtap="previewImage"
              data-index="{{i1}},{{i2}}"
            >
              <image
                class="ledger-group_item__file"
                src="{{ledger.path1[0]}}"
                mode="aspectFill"
                show-menu-by-longpress="{{true}}"
              ></image>
              <view>{{ledger.ledgerName}}</view>
            </view>
            <view wx:else class="ledger-group_item" data-index="{{i1}},{{i2}}">
              <file-grid
                class="ledger-group_item__file"
                files="{{ledger._files}}"
                gridHeight="{{_.styleByCount(ledger._files.length).height}}"
                gridWidth="{{_.styleByCount(ledger._files.length).width}}"
              ></file-grid>
              <view>{{ledger.ledgerName}}</view>
            </view>
          </block>
        </view>
      </view>
    </block>
pages/mLedger/ledgerhistory/ledgerhistory.wxss
@@ -69,11 +69,15 @@
.ledger-group_item{
  width: 46vw;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  font-size: 14px;
}
.ledger-group_item>image{
.ledger-group_item .ledger-group_item__file{
  width: 40vw;
  height: 40vw;
  border-radius: 8px;
pages/mLedger/ledgerhistory/utils.wxs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,37 @@
/**
 * æ ¹æ®å°è´¦æ–‡ä»¶æ•°é‡,决定每个文件的展示宽高
 * @param {Number} num
 */
function styleByCount(num) {
  var width, height;
  switch (num) {
    case 1:
      width = '40vw';
      height = '40vw';
      break;
    case 2:
      width = '40vw';
      height = '17vw';
      break;
    case 3:
    case 4:
      width = '17vw';
      height = '17vw';
      break;
    case 5:
    case 6:
      width = '17vw';
      height = '12vw';
      break;
    default:
      width = 0;
      height = 0;
      break;
  }
  return { width, height };
}
module.exports = {
  styleByCount: styleByCount,
};
pages/mLedger/ledgerupload/ledgerupload.js
@@ -30,8 +30,6 @@
    type: 0,
    // åŽ†å²æœ€æ–°è®°å½•
    lastLedger: undefined,
  },
  /**
@@ -42,12 +40,13 @@
    this.getOpenerEventChannel().on(
      'acceptDataFromOpenerPage',
      function (data) {
        data.ledger.description = data.ledger.description.replaceAll(
        data.ledger.description = data.ledger.description?.replaceAll(
          '\\n',
          '\n',
        );
        that.setData({
          ledger: data.ledger,
          time: moment(data.ledger.updateDate).format('YYYYå¹´MM月DD日'),
          indexGroup: data.indexGroup,
          type: data.type,
          taskId: data.taskId,
@@ -65,10 +64,15 @@
        // å¯¹äºŽå¯å¤åˆ¶çš„并且不是重传状态的台账,获取最新的历史记录用于复制
        if (data.ledger.copy && !data.reUpload) {
          that.getLatestLedger()
          that.getLatestLedger();
        }
      },
    );
    this.setData({
      loadingText: '上传中',
      loadCompleteText: '上传完成',
      timeoutText: '上传超时',
    });
  },
  /**
@@ -78,15 +82,15 @@
    if (this.data.reUpload) {
      //do nothing
      return;
    } else if (this.data.ledger.path1) {
      let imgFiles = this.data.ledger.path1;
    } else if (this.data.ledger._files) {
      let imgFiles = this.data.ledger._files;
      let remark = this.data.remark;
      if (this.data.ledger.remark1) remark = this.data.ledger.remark1;
      let remarkDisable = true;
      this.setData({
        imgFiles,
        remark,
        remarkDisable
        remarkDisable,
      });
    } else if (this.data.ledger.upLoad) {
      var that = this;
@@ -101,14 +105,14 @@
            if (res.length > 0) {
              let detail = res[0];
              if (detail.upLoad) {
                let imgFiles = detail.path1;
                let imgFiles = detail._files;
                let remark = detail.remark1 ? detail.remark1 : '';
                let remarkDisable = true;
                that.setData({
                  imgFiles,
                  remark,
                  remarkDisable,
                  detail
                  detail,
                });
              }
            }
@@ -120,14 +124,14 @@
            if (res.success) {
              let detail = res.data;
              if (detail.upLoad) {
                let imgFiles = detail.path1;
                let imgFiles = detail._files;
                let remark = detail.remark1 ? detail.remark1 : '';
                let remarkDisable = true;
                that.setData({
                  imgFiles,
                  remark,
                  remarkDisable,
                  detail
                  detail,
                });
              }
            }
@@ -143,33 +147,45 @@
    var typeId = this.data.ledger.ledgerSubTypeId;
    var sceneType = app.globalData.userInfo.extension2;
    this.setData({
      latestLedgerLoading: true
    })
      latestLedgerLoading: true,
    });
    ledgerservice.getLedgerDetail(userId, typeId, sceneType, null, {
      success: (res) => {
      success: res => {
        if (res.length > 0) {
          const ledger = res[0]
          const ledger = res[0];
          this.setData({
            lastLedger: {
              ...ledger,
              _updateTimeStr: moment(ledger.updateDate).format('YYYYå¹´MM月DD日')
            }
          })
              _updateTimeStr: moment(ledger.updateDate).format(
                'YYYYå¹´MM月DD日',
              ),
            },
          });
        }
      },
      complete: () => {
        this.setData({
          latestLedgerLoading: false
        })
      }
          latestLedgerLoading: false,
        });
      },
    });
  },
  uploadFileFail(e) {
    const { type, index } = e.detail;
    if (type == 1) {
      wx.showToast({
        title: `文件过大`,
        icon: 'error',
      });
    }
  },
  // ä¸Šä¼ å°è´¦
  onSubmit: function () {
    if (this.data.imgFiles.length == 0) {
      wx.showToast({
        title: '请至少选择一张图片',
        title: '请至少选择一个文件',
        icon: 'none',
      });
    } else {
@@ -191,7 +207,7 @@
  // å»¶ç”¨å¤åˆ¶å°è´¦
  onCopyLedger() {
    if (this.data.latestLedgerLoading) {
      return
      return;
    } else if (this.data.lastLedger == undefined) {
      wx.showToast({
        title: '没有可延用的记录',
@@ -227,13 +243,13 @@
        break;
      case 2:
        if (this.data.type == 0) {
          const {
            lastLedger
          } = this.data
          const copyLedgerList = [{
            subTypeId: lastLedger.ledgerSubTypeId,
            time: `${lastLedger.year}-${lastLedger.month}`
          }]
          const { lastLedger } = this.data;
          const copyLedgerList = [
            {
              subTypeId: lastLedger.ledgerSubTypeId,
              time: `${lastLedger.year}-${lastLedger.month}`,
            },
          ];
          this._uploadCopyLedger(copyLedgerList);
        }
        break;
@@ -278,10 +294,10 @@
  //图片放大预览
  previewImage(e) {
    const {
      index
    } = e.currentTarget.dataset;
    const previewImageUrls = this.data.imgFiles;
    const { index } = e.currentTarget.dataset;
    const previewImageUrls = this.data.imgFiles
      .filter(f => f.type == 'image')
      .map(f => f.url);
    this.setData({
      previewImageUrls,
      previewCurrent: index,
@@ -291,11 +307,9 @@
  // å°è´¦å¤‡æ³¨ç›‘听
  onRemarkChange(e) {
    const {
      value
    } = e.detail;
    const { value } = e.detail;
    this.setData({
      remark: value
      remark: value,
    });
  },
});
});
pages/mLedger/ledgerupload/ledgerupload.json
@@ -5,8 +5,7 @@
  "usingComponents": {
    "mp-upload":"/component/uploader/uploader",
    "c-dialog": "/component/commondialog/commondialog",
    "my-gallery": "/component/mygallery/mygallery",
    "mp-gallery": "/component/gallery/gallery",
    "file-grid": "/component/filegrid/index",
    "mp-icon": "/component/icon/icon"
  }
}
pages/mLedger/ledgerupload/ledgerupload.wxml
@@ -5,36 +5,76 @@
  </view>
  <view class="page__bd">
    <view wx:if="{{ledger.description}}" class="ledger-des">
      <view style="display: flex;align-items: center;height: 20px;margin-bottom: 10px;">
      <view class="ledger-tips">
        <mp-icon icon="info" color="" size="{{16}}"></mp-icon>
        <text>{{ledger.ledgerTypeId == -1 ? '操作提示' : '台账提示'}}</text>
      </view>
      <text>{{ledger.description}}</text>
    </view>
    <view wx:if="{{!ledger.upLoad || reUpload}}" class="weui-upload-view" style="margin-top: 16px">
      <mp-upload title="上传图片(必填)" titleClass="upload-title-class" max-count="6" files="{{imgFiles}}" binduploadImg="uploadFile" binddelete="delImg"></mp-upload>
      <textarea disabled="{{remarkDisable}}" value="{{remark}}" class="text-area" auto-height="{{false}}" name="des" placeholder="添加备注(选填)" bindinput="onRemarkChange"></textarea>
    <view
      wx:if="{{!ledger.upLoad || reUpload}}"
      class="weui-upload-view"
      style="margin-top: 16px"
    >
      <mp-upload
        title="上传文件(必填)"
        tips="文件最大不能超过5MB"
        allowFiles="{{true}}"
        titleClass="upload-title-class"
        max-count="6"
        files="{{imgFiles}}"
        binduploadImg="uploadFile"
        binddelete="delImg"
        bindfail="uploadFileFail"
      ></mp-upload>
      <textarea
        disabled="{{remarkDisable}}"
        value="{{remark}}"
        class="text-area"
        auto-height="{{false}}"
        name="des"
        placeholder="添加备注(选填)"
        bindinput="onRemarkChange"
      ></textarea>
    </view>
    <block wx:else>
      <view style="font-size: 14px; margin-top: 16px">图片</view>
      <view class="img-group">
        <image wx:for="{{imgFiles}}" wx:key="index" class="img-group_img" src="{{item}}" mode="aspectFill" bindtap="previewImage" data-index="{{index}}" show-menu-by-longpress="{{true}}"></image>
      </view>
      <view style="font-size: 14px; margin-top: 16px">台账文件</view>
      <file-grid files="{{imgFiles}}"></file-grid>
      <view style="font-size: 14px; margin-top: 16px">备注</view>
      <textarea class="text-area text-area-read" placeholder="无备注" value="{{remark}}"></textarea>
      <textarea
        disabled="{{true}}"
        class="text-area text-area-read"
        placeholder="无备注"
        value="{{remark}}"
      ></textarea>
      <view style="font-size: 12px; margin-top: 16px;color: rgb(160, 160, 160);">上传时间: {{time}}</view>
    </block>
  </view>
  <view class="page__ft">
    <view wx:if="{{!ledger.upLoad || reUpload}}" class="fix-bottom">
      <view wx:if="{{type == 0 && ledger.copy && !reUpload}}" class="submit submit-3 left" bindtap="onCopyLedger">
        <t-loading wx:if="{{latestLedgerLoading}}" theme="spinner" size="20rpx" class="wrapper" />
      <view
        wx:if="{{type == 0 && ledger.copy && !reUpload}}"
        class="submit submit-3 left"
        bindtap="onCopyLedger"
      >
        <t-loading
          wx:if="{{latestLedgerLoading}}"
          theme="spinner"
          size="20rpx"
          class="wrapper"
        />
        <text>延用</text>
        <!-- <view class="small-tag-text">
          <text wx:if="{{lastLedger}}">上次记录:{{lastLedger._updateTimeStr}}</text>
          <text wx:else>无上传记录</text>
        </view> -->
      </view>
      <view wx:if="{{ledger.notRelated}}" class="submit submit-2 left" bindtap="onSubmitNoLedger">不涉及</view>
      <view
        wx:if="{{ledger.notRelated}}"
        class="submit submit-2 left"
        bindtap="onSubmitNoLedger"
        >不涉及</view
      >
      <view class="submit right" bindtap="onSubmit">提交</view>
    </view>
    <view wx:else class="fix-bottom">
@@ -50,5 +90,4 @@
      <view>确认延用?</view>
    </view>
  </c-dialog>
  <my-gallery hide-on-click="{{true}}" show-delete="{{false}}" show="{{showPreview}}" img-urls="{{previewImageUrls}}" current="{{previewCurrent}}"></my-gallery>
</view>
</view>
pages/mLedger/ledgerupload/ledgerupload.wxss
@@ -33,11 +33,18 @@
}
.fix-bottom .right {
  flex: 2;
  flex: 2;
}
.upload-title-class {
  font-size: small;
}
.ledger-tips {
  display: flex;
  align-items: center;
  height: 20px;
  margin-bottom: 10px;
}
.text-area {
@@ -56,7 +63,7 @@
  color: var(--fyui-text-color_2);
}
.img-group {
/* .img-group {
  display: flex;
  flex-wrap: wrap;
}
@@ -71,7 +78,7 @@
  height: 29vw;
  margin-bottom: 8px;
  margin-right: 8px;
}
} */
.submit-2 {
  background: white;
@@ -119,13 +126,13 @@
  align-items: center;
}
.custom-action__bg{
.custom-action__bg {
  position: absolute;
  top: 0;
  left: 0;
}
.custom-action__tag{
.custom-action__tag {
  font-size: 14px;
  color: var(--fyui-text-color_1);
  font-weight: 600;
@@ -134,7 +141,7 @@
  z-index: 2;
}
.custom-action__tag>image{
.custom-action__tag>image {
  width: 64px;
  height: 64px;
}
pages/mSelfPatrol/components/self-patrol/index.js
@@ -1,7 +1,4 @@
import {
  parseSelfPatrol,
  refreshLedgerStatus
} from '../../../../model/ledger';
import { parseSelfPatrol, refreshLedgerStatus } from '../../../../model/ledger';
import configservice from '../../../../service/configservice';
const ledgerservice = require('../../../../service/ledgerservice');
const moment = require('../../../../utils/moment.min');
@@ -20,7 +17,7 @@
    refresh: false,
    thisMonth: '',
    tags1: {
      count: 0
      count: 0,
    },
    pageList1: [],
    // æ˜¯å¦æœ‰æƒé™å¯ä»¥è¿›è¡Œè‡ªå·¡æŸ¥æ‰¿è¯º
@@ -44,7 +41,7 @@
      const nowStr = now.format('YYYY-MM-DD');
      const thisMonth = now.format('YYYYå¹´MM月');
      this.setData({
        thisMonth
        thisMonth,
      });
      this.getLedgerType(nowStr, r => {
        this.setData({
@@ -58,7 +55,7 @@
          refresh: false,
        });
      });
      this.getPromise()
      this.getPromise();
    },
    /**
@@ -66,15 +63,20 @@
     */
    getPromise() {
      if (this.data.promiseValid) {
        configservice.fetchUserSettingRecord(app.globalData.accessToken.userId, {
          success: res => {
            const nowYear = moment().year()
            const promiseYear = moment(res.data?.lastPromisedTime).year()
            this.setData({
              promised: (res.data?.selfPatrolPromised == true) && (nowYear == promiseYear)
            })
        configservice.fetchUserSettingRecord(
          app.globalData.accessToken.userId,
          {
            success: res => {
              const nowYear = moment().year();
              const promiseYear = moment(res.data?.lastPromisedTime).year();
              this.setData({
                promised:
                  res.data?.selfPatrolPromised == true &&
                  nowYear == promiseYear,
              });
            },
          },
        })
        );
      }
    },
@@ -83,7 +85,8 @@
      ledgerservice.getLedgerSummary(
        app.globalData.accessToken.userId,
        app.globalData.userInfo.extension2,
        time, {
        time,
        {
          success(res) {
            let r = parseSelfPatrol(res);
            success(r);
@@ -93,9 +96,7 @@
    },
    gotoLedgerDetail(e) {
      const {
        index
      } = e.currentTarget.dataset;
      const { index } = e.currentTarget.dataset;
      const indexGroup = index;
      var ledger = this.data.pageList1[index];
      var that = this;
@@ -145,17 +146,17 @@
      wx.navigateTo({
        url: '/pages/mSelfPatrol/patrolpromise/index',
        events: {
          doPromiseDone: (data)=> {
          doPromiseDone: data => {
            this.setData({
              promised: data.promised
            })
              promised: data.promised,
            });
          },
        },
        success: (res)=> {
        success: res => {
          // é€šè¿‡ eventChannel å‘被打开页面传送数据
          // res.eventChannel.emit('acceptDataFromOpenerPage', {
          // });
          res.eventChannel.emit('acceptDataFromOpenerPage', {
            review: false,
          });
        },
      });
    },
@@ -166,13 +167,13 @@
    reviewPromise() {
      wx.navigateTo({
        url: '/pages/mSelfPatrol/patrolpromise/index',
        success: (res)=> {
        success: res => {
          // é€šè¿‡ eventChannel å‘被打开页面传送数据
          res.eventChannel.emit('acceptDataFromOpenerPage', {
            review: true
            review: true,
          });
        },
      });
    }
    },
  },
});
});
pages/mSelfPatrol/patrolpromise/index.js
@@ -33,6 +33,7 @@
    this.getOpenerEventChannel().on(
      'acceptDataFromOpenerPage',
      (data) => {
        console.log('acceptDataFromOpenerPage', data);
        this.setData({
          isReview: data.review
        })
pages/mSelfPatrol/patrolpromise/index.wxml
@@ -11,7 +11,7 @@
    </view>
  </view>
  <view class="page__ft">
    <template wx:if="{{!isReview}}">
    <block wx:if="{{!isReview}}">
      <view class="weui-agree">
        <label bindtap="checkboxChange">
          <checkbox
@@ -26,7 +26,7 @@
        </label>
      </view>
      <view class="submit" bindtap="showCheckDialog">签署</view>
    </template>
    </block>
  </view>
</view>
<t-dialog
service/baserequest.js
@@ -10,8 +10,8 @@
const util = require('../utils/util.js');
// å°ç¨‹åºåŽå°
const baseUrl = "http://192.168.1.9:8082"
// const baseUrl = 'https://fyami.com.cn';
// const baseUrl = "http://192.168.1.9:8082"
const baseUrl = 'https://fyami.com.cn';
const bu = 'https://fyami.com.cn';
const basePicUrl = `${bu}/images/`;
const baseIconUrl = `${bu}/images/weixin/eplaw/`;
@@ -22,8 +22,8 @@
const spBu = "https://fyami.com.cn:447"
const spPicUrl = `${spBu}/images/`;
const mode = 'debug';
// const mode = 'prod';
// const mode = 'debug';
const mode = 'prod';
function request(fun, hostUrl) {
  const bUrl = hostUrl ? hostUrl : baseUrl;
service/ledgerservice.js
@@ -1,3 +1,4 @@
import serviceutils from "./serviceutils";
const Multipart = require('../utils/Multipart.min');
const $f = require('./baserequest');
const util = require('../utils/util');
@@ -25,12 +26,16 @@
  },
  //上传台账
  uploadLedger: function (userId, ledger, paths, fun) {
  uploadLedger: function (userId, ledger, namePairs, paths, fun) {
    const fields = [
      {
        name: 'params',
        value: JSON.stringify([ledger]),
      },
      {
        name: 'fileNames',
        value: JSON.stringify(namePairs),
      }
    ];
    const files = [];
    paths.forEach(p => {
@@ -87,6 +92,8 @@
        r.path1 = r.path1.split(';').map((value, index) => {
          return $f.basePicUrl + value;
        });
        r._files = serviceutils.formatLedgerPath(r.path1)
        r._fileType = serviceutils.judgeLedgerFileType(r._files)
      });
      cb.success(res);
    };
service/selfpatrolservice.js
@@ -1,6 +1,8 @@
import serviceutils from "./serviceutils";
const Multipart = require('../utils/Multipart.min');
const $f = require('./baserequest');
const util = require('../utils/util');
module.exports = {
  /**
@@ -47,8 +49,8 @@
    $f.get(fun1);
  },
  //上传自巡查
  uploadSelfPatrol: function (userId, taskId, selfPatrol, paths, fun) {
  //上传应急自巡查
  uploadSelfPatrol: function (userId, taskId, selfPatrol,namePairs, paths, fun) {
    const fields = [{
        name: 'params',
        value: JSON.stringify([selfPatrol]),
@@ -61,6 +63,10 @@
        name: 'taskId',
        value: taskId,
      },
      {
        name: 'fileNames',
        value: JSON.stringify(namePairs),
      }
    ];
    const files = [];
    paths.forEach(p => {
@@ -122,6 +128,8 @@
        r.path1 = r.path1.split(';').map((value, index) => {
          return $f.basePicUrl + value;
        });
        r._files = serviceutils.formatLedgerPath(r.path1)
        r._fileType = serviceutils.judgeLedgerFileType(r._files)
      }
      cb.success(res);
    };
service/serviceutils.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,47 @@
export default {
  /**
   * æ ¼å¼åŒ–台账文件路径数组
   * @param {Array} pathList å°è´¦æ–‡ä»¶çš„路径数组
   */
  formatLedgerPath(pathList) {
    return pathList.map((value, index) => {
      // æ–‡ä»¶å
      const plist = value.split('/');
      const fileName = plist[plist.length - 1];
      // æ–‡ä»¶æ‰©å±•名
      const nList = fileName.split('.');
      const ext = nList[nList.length - 1];
      let fileType = 'file';
      if (
        ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'].indexOf(ext) != -1
      ) {
        fileType = 'image';
      }
      return {
        name: fileName,
        type: fileType,
        ext,
        url: value,
      };
    });
  },
  /**
   * ç¡®å®šå°è´¦çš„æ–‡ä»¶ç±»åž‹ç»„成,['image', 'file', 'mix']
   */
  judgeLedgerFileType(files) {
    let type = '';
    for (let i = 0; i < files.length; i++) {
      const f = files[i];
      if (f.type != type) {
        if (type == '') {
          type = f.type;
        } else {
          type = 'mix';
          break;
        }
      }
    }
    return type;
  },
};