yf_elsa.cui 1 месяц назад
Сommit
f82e6eb6e9
100 измененных файлов с 37752 добавлено и 0 удалено
  1. 17 0
      .gitignore
  2. 27 0
      .hbuilderx/launch.json
  3. 28 0
      App.vue
  4. BIN
      appIcon/shop.png
  5. BIN
      appIcon/yfzk.png
  6. BIN
      appIcon/zk.png
  7. 167 0
      components/Draw/comps/Annotation.vue
  8. 148 0
      components/Draw/comps/panel.vue
  9. 131 0
      components/Draw/comps/tools.vue
  10. 676 0
      components/Draw/index.vue
  11. 125 0
      components/bazaar-city_list/citylist.json
  12. 299 0
      components/bazaar-city_list/index.vue
  13. 1063 0
      components/city.js
  14. 66 0
      components/customCard/customCard.vue
  15. 84 0
      components/equip-item/equip-item.vue
  16. 13 0
      components/js_sdk/u-charts/package.json
  17. 471 0
      components/js_sdk/u-charts/u-charts/config.js
  18. 267 0
      components/js_sdk/u-charts/u-charts/demodata.json
  19. 41 0
      components/js_sdk/u-charts/u-charts/mapdata.json
  20. 6 0
      components/js_sdk/u-charts/u-charts/readme.md
  21. 5687 0
      components/js_sdk/u-charts/u-charts/u-charts - 副本.js
  22. 7706 0
      components/js_sdk/u-charts/u-charts/u-charts.js
  23. 443 0
      components/js_sdk/u-charts/u-charts/u-charts.vue
  24. 4 0
      components/jsencrypt/jsencrypt.min.js
  25. 88 0
      components/jsencrypt/jsencrypt.vue
  26. 639 0
      components/ksp-image-cutter/ksp-image-cutter.vue
  27. 454 0
      components/linzq-citySelect/linzq-citySelect.vue
  28. 215 0
      components/mark.vue
  29. 346 0
      components/multiple-select.vue
  30. 140 0
      components/popup-layer/popup-layer.vue
  31. 96 0
      components/uni-icons/icons.js
  32. 57 0
      components/uni-icons/uni-icons.vue
  33. 224 0
      components/uni-nav-bar/uni-nav-bar.vue
  34. 25 0
      components/uni-status-bar/uni-status-bar.vue
  35. 24 0
      crypto-js/LICENSE
  36. 234 0
      crypto-js/aes.js
  37. 471 0
      crypto-js/blowfish.js
  38. 39 0
      crypto-js/bower.json
  39. 895 0
      crypto-js/cipher-core.js
  40. 807 0
      crypto-js/core.js
  41. 6657 0
      crypto-js/crypto-js.js
  42. 136 0
      crypto-js/enc-base64.js
  43. 148 0
      crypto-js/enc-base64url.js
  44. 18 0
      crypto-js/enc-hex.js
  45. 18 0
      crypto-js/enc-latin1.js
  46. 149 0
      crypto-js/enc-utf16.js
  47. 18 0
      crypto-js/enc-utf8.js
  48. 134 0
      crypto-js/evpkdf.js
  49. 66 0
      crypto-js/format-hex.js
  50. 18 0
      crypto-js/format-openssl.js
  51. 18 0
      crypto-js/hmac-md5.js
  52. 18 0
      crypto-js/hmac-ripemd160.js
  53. 18 0
      crypto-js/hmac-sha1.js
  54. 18 0
      crypto-js/hmac-sha224.js
  55. 18 0
      crypto-js/hmac-sha256.js
  56. 18 0
      crypto-js/hmac-sha3.js
  57. 18 0
      crypto-js/hmac-sha384.js
  58. 18 0
      crypto-js/hmac-sha512.js
  59. 143 0
      crypto-js/hmac.js
  60. 18 0
      crypto-js/index.js
  61. 76 0
      crypto-js/lib-typedarrays.js
  62. 268 0
      crypto-js/md5.js
  63. 80 0
      crypto-js/mode-cfb.js
  64. 116 0
      crypto-js/mode-ctr-gladman.js
  65. 58 0
      crypto-js/mode-ctr.js
  66. 40 0
      crypto-js/mode-ecb.js
  67. 54 0
      crypto-js/mode-ofb.js
  68. 42 0
      crypto-js/package.json
  69. 49 0
      crypto-js/pad-ansix923.js
  70. 44 0
      crypto-js/pad-iso10126.js
  71. 40 0
      crypto-js/pad-iso97971.js
  72. 30 0
      crypto-js/pad-nopadding.js
  73. 18 0
      crypto-js/pad-pkcs7.js
  74. 47 0
      crypto-js/pad-zeropadding.js
  75. 145 0
      crypto-js/pbkdf2.js
  76. 190 0
      crypto-js/rabbit-legacy.js
  77. 192 0
      crypto-js/rabbit.js
  78. 139 0
      crypto-js/rc4.js
  79. 267 0
      crypto-js/ripemd160.js
  80. 150 0
      crypto-js/sha1.js
  81. 80 0
      crypto-js/sha224.js
  82. 199 0
      crypto-js/sha256.js
  83. 326 0
      crypto-js/sha3.js
  84. 83 0
      crypto-js/sha384.js
  85. 326 0
      crypto-js/sha512.js
  86. 779 0
      crypto-js/tripledes.js
  87. 304 0
      crypto-js/x64-core.js
  88. 67 0
      main.js
  89. 233 0
      manifest.json
  90. 12 0
      manifest.json.rej
  91. 19 0
      package-lock.json
  92. 18 0
      package.json
  93. 1005 0
      pages.json
  94. 526 0
      pages/afterSale/addafter.vue
  95. 431 0
      pages/afterSale/index.vue
  96. 290 0
      pages/afterSale/search.vue
  97. 520 0
      pages/cb/bzy/equip-set/bzyhistoryile.vue
  98. 445 0
      pages/cb/bzy/equip-set/equip-set.vue
  99. 154 0
      pages/cb/cbd/equip-set/addimg.vue
  100. 0 0
      pages/cb/cbd/equip-set/analyse.vue

+ 17 - 0
.gitignore

@@ -0,0 +1,17 @@
+.DS_Store
+node_modules/
+/dist/
+unpackage/
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+unpackage/*
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+

+ 27 - 0
.hbuilderx/launch.json

@@ -0,0 +1,27 @@
+{
+    // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
+    // launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数
+    "version" : "0.0",
+    "configurations" : [
+        {
+            "app-plus" : {
+                "launchtype" : "local"
+            },
+            "default" : {
+                "launchtype" : "local"
+            },
+            "h5" : {
+                "launchtype" : "local"
+            },
+            "mp-weixin" : {
+                "launchtype" : "local"
+            },
+            "type" : "uniCloud"
+        },
+        {
+            "customPlaygroundType" : "local",
+            "playground" : "custom",
+            "type" : "uni-app:app-android"
+        }
+    ]
+}

+ 28 - 0
App.vue

@@ -0,0 +1,28 @@
+<script>
+	
+	export default {
+		onShow: function() {
+			console.log('App Show')
+		},
+		onHide: function() {
+			console.log('App Hide')
+		}
+	}
+</script>
+<style lang="scss">
+	@import "./static/font/iconfont.css";
+	@import "./static/iconfont/iconfont.css";
+	html {
+		box-sizing: border-box;
+		font-size: 28rpx !important;
+	}
+
+	.status_bar {
+		height: 44px;
+		width: 100%;
+		background-color: #FFFFFF;
+		position: fixed;
+		top: 0;
+		z-index: 99999;
+	}
+</style>

BIN
appIcon/shop.png


BIN
appIcon/yfzk.png


BIN
appIcon/zk.png


+ 167 - 0
components/Draw/comps/Annotation.vue

@@ -0,0 +1,167 @@
+<template>
+  <div class="tipInfo" :style="inputStyle">
+    <div class="header">
+      <span>人工标注</span>
+    </div>
+    <div class="contentBox">
+      <el-input
+        placeholder="输入标注内容"
+        v-model="currentLabel"
+        maxlength="10"
+        size="mini"
+        clearable
+        @keydown.native="handleKeyDown"
+        ref="labelInput"
+      >
+      </el-input>
+      <div class="near" v-if="nearList.length">
+        最近:
+        <el-tag
+          type="primary"
+          size="mini"
+          effect="plain"
+          v-for="pest in nearList"
+          @click="currentLabel = pest"
+          :key="pest"
+          >{{ pest }}</el-tag
+        >
+      </div>
+      <div class="btnBox">
+        <el-button size="mini" @click="deleteRect">
+          取消操作
+        </el-button>
+
+        <el-button type="primary" size="mini" @click="confirmLabel">
+          保存标注
+        </el-button>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    inputStyle: {
+      type: Object,
+      default: () => ({
+        left: `0px`,
+        top: `0px`
+        // transform: 'translate(-50%, -24px)' // 稍微下移避免遮挡
+      })
+    }
+  },
+  data() {
+    return {
+      nearList: [],
+      currentLabel: ''
+    }
+  },
+  computed: {},
+  created() {},
+  mounted() {
+    this.getNearList()
+    this.$nextTick(() => {
+      this.$refs.labelInput.focus()
+    })
+    // this.$refs.labelInput.addEventListener('keydown', this.handleKeyDown)
+  },
+  beforeDestroy() {
+    // this.$refs.labelInput.removeEventListener('keydown', this.handleKeyDown)
+  },
+  watch: {},
+  methods: {
+    handleKeyDown(e) {
+      if (e.code === 'Enter') {
+        this.confirmLabel()
+      }
+    },
+    getNearList() {
+      let nearList = localStorage.getItem('nearPestList')
+      if (nearList) {
+        this.nearList = JSON.parse(nearList)
+      }
+    },
+    deleteRect() {
+      this.$emit('deleteRect')
+    },
+    confirmLabel() {
+      if (this.currentLabel) {
+        this.$emit('confirmLabel', this.currentLabel)
+        if (this.nearList.indexOf(this.currentLabel) !== -1) {
+          this.nearList.splice(this.nearList.indexOf(this.currentLabel), 1) // 删除原来的
+        }
+        this.nearList.unshift(this.currentLabel) // 添加到最前面
+        localStorage.setItem('nearPestList', JSON.stringify(this.nearList))
+      } else {
+        this.$message({
+          message: '请输入标注内容',
+          type: 'warning'
+        })
+      }
+    }
+  },
+  components: {}
+}
+</script>
+
+<style scoped lang="less">
+.tipInfo {
+  background: #fff;
+  position: absolute;
+  z-index: 4;
+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+  border-radius: 4px;
+  border: 1px solid #ebeef5;
+  .header {
+    padding: 18px 20px;
+    border-bottom: 1px solid #ebeef5;
+    box-sizing: border-box;
+  }
+}
+.near {
+  font-size: 12px;
+  margin: 10px 0;
+  height: 20px;
+  overflow: hidden;
+  .el-tag {
+    cursor: pointer;
+    margin-right: 10px;
+  }
+}
+.contentBox {
+  width: 250px;
+  padding: 20px;
+}
+.btnBox {
+  margin-top: 10px;
+  text-align: center;
+}
+.annotation-input {
+  position: fixed;
+  z-index: 100;
+  background: white;
+  padding: 8px;
+  border-radius: 4px;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
+  display: flex;
+  align-items: center;
+  gap: 8px;
+}
+
+.annotation-input input {
+  padding: 4px 8px;
+  border: 1px solid #ddd;
+  border-radius: 3px;
+  min-width: 150px;
+}
+
+.annotation-input button {
+  padding: 4px 8px;
+  background: #4caf50;
+  color: white;
+  border: none;
+  border-radius: 3px;
+  cursor: pointer;
+}
+</style>

+ 148 - 0
components/Draw/comps/panel.vue

@@ -0,0 +1,148 @@
+<template>
+  <div class="my-panel">
+    <el-button
+      v-show="reIdentify"
+      class="resetPest"
+      @click="resetPest"
+      size="small"
+      type="primary"
+      >重新识别</el-button
+    >
+    <el-tabs type="border-card" class="infoCard">
+      <el-tab-pane label="图像识别">
+        <div class="info title">
+          <span>{{ title }}</span>
+          <span>数量</span>
+        </div>
+        <div class="info" v-for="(value, key) in pestObj" :key="key">
+          <span>{{ key }}</span>
+          <span>{{ value }}</span>
+        </div>
+      </el-tab-pane>
+    </el-tabs>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'Panel',
+  props: {
+    rectangles: {
+      type: Array,
+      default: () => [],
+    },
+    reIdentify: {
+      type: Boolean,
+      default: true,
+    },
+    title: {
+      type: String,
+      default: '目录',
+    },
+  },
+  data() {
+    return {};
+  },
+  computed: {
+    pestObj() {
+      let obj = {};
+      this.rectangles.forEach((item) => {
+        if (obj[item.text]) {
+          obj[item.text]++;
+        } else {
+          obj[item.text] = 1;
+        }
+      });
+      return obj;
+    },
+  },
+  created() {},
+  mounted() {
+    let obj = {};
+    this.rectangles.forEach((item) => {
+      if (obj[item.text]) {
+        obj[item.text]++;
+      } else {
+        obj[item.text] = 0;
+      }
+    });
+    console.log('子组件mounted', obj);
+  },
+  watch: {},
+  methods: {
+    resetPest() {
+      // 通知业务上层处理逻辑
+      this.$emit('resetPest');
+    },
+  },
+  components: {},
+};
+</script>
+
+<style scoped lang="less">
+::v-deep .custom-ffffff .el-tabs--border-card {
+  box-shadow: none;
+}
+.my-panel {
+  position: relative;
+  height: 100%;
+}
+.resetPest {
+  position: absolute;
+  top: 4px;
+  right: 9px;
+  z-index: 1;
+}
+.infoCard {
+  position: relative;
+  height: 100%;
+  overflow: auto;
+  box-sizing: border-box;
+  // box-shadow: none !important;
+  border: 1px solid #e4e7ed;
+  ::v-deep .el-tabs__content {
+    height: calc(100% - 70px);
+    overflow: auto;
+    padding: 14px 0 !important;
+    &::-webkit-scrollbar {
+      width: 8px; /* 滚动条宽度 */
+    }
+    /* 滚动条轨道 */
+    &::-webkit-scrollbar-track {
+      background: #f6f6f6; /* 轨道背景 */
+      border-radius: 8px; /* 圆角 */
+    }
+
+    /* 滚动条滑块 */
+    &::-webkit-scrollbar-thumb {
+      background: #b6b6b6; /* 滑块颜色 */
+      border-radius: 8px; /* 圆角 */
+    }
+
+    /* 鼠标悬停时的滑块样式 */
+    &::-webkit-scrollbar-thumb:hover {
+      background: #555; /* 悬停时颜色 */
+    }
+  }
+  .info {
+    display: flex;
+    padding: 10px;
+    align-items: center;
+    font-weight: 600;
+    justify-content: space-between;
+    height: 40px;
+    box-sizing: border-box;
+    color: #333;
+    // margin-top: 16px;
+    font-size: 14px;
+    border-bottom: 1px solid #e4e7ed;
+  }
+  .title {
+    background: #ebedf0;
+    margin-top: 0;
+  }
+}
+.infoCard.el-tabs--border-card {
+  box-shadow: none !important;
+}
+</style>

+ 131 - 0
components/Draw/comps/tools.vue

@@ -0,0 +1,131 @@
+<template>
+  <div class="tools float-left">
+    <button
+      title="上一个"
+      @click="changeItem('pre')"
+      class="el-icon-d-arrow-left"
+    ></button>
+    <button
+      title="下一个"
+      @click="changeItem('next')"
+      class="el-icon-d-arrow-right"
+    ></button>
+    <button
+      title="拖拽"
+      :class="[mode == 'drag' ? 'active' : '']"
+      class="yficonfont icon-zhuashou"
+      @click="mode = 'drag'"
+    ></button>
+    <button
+      title="绘制"
+      :class="[mode == 'draw' ? 'active' : '']"
+      class="el-icon-edit-outline"
+      @click="mode = 'draw'"
+    ></button>
+    <button
+      title="保存标注"
+      @click="saveLabel"
+      class="el-icon-circle-check"
+    ></button>
+    <button title="下载" @click="saveImage" class="el-icon-download"></button>
+    <button
+      title="全屏"
+      @click="fullScreen"
+      class="el-icon-full-screen"
+    ></button>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    fullScreenHtml: ['fullScreenHtml']
+  },
+  data() {
+    return {
+      mode: 'draw'
+    }
+  },
+  computed: {},
+  created() {},
+  mounted() {},
+  watch: {},
+  methods: {
+    // 切换上一个下一个
+    changeItem(type) {
+      this.$emit('changeItem', type)
+    },
+    changeMode(type) {
+      this.$emit('changeMode', type)
+    },
+    fullScreen() {
+      const container = this.fullScreenHtml
+      if (container.requestFullscreen) {
+        container.requestFullscreen()
+      } else if (container.mozRequestFullScreen) {
+        container.mozRequestFullScreen()
+      } else if (container.webkitRequestFullscreen) {
+        container.webkitRequestFullscreen()
+      } else if (container.msRequestFullscreen) {
+        container.msRequestFullscreen()
+      }
+    },
+    saveLabel() {
+      this.$emit('saveLabel')
+    }
+  },
+  components: {}
+}
+</script>
+
+<style scoped lang="less">
+@primary-color: #018b3f;
+.controls {
+  position: absolute;
+  top: 0;
+  left: 0;
+  padding: 3px 15px;
+  width: 70%;
+  box-sizing: border-box;
+  // background: rgba(0, 0, 0, 0.3);
+}
+.info {
+  width: 100%;
+  // color: #ffffff;
+  overflow: hidden;
+  .tools {
+    display: flex;
+    background-color: rgba(0, 0, 0, 0.3);
+    // gap: 10px;
+    .active {
+      background: @primary-color;
+    }
+  }
+  .float-right {
+    line-height: 24px;
+  }
+}
+
+.info span {
+  white-space: nowrap;
+  .active {
+    color: @primary-color;
+    margin-right: 5px;
+  }
+}
+
+.info button {
+  font-size: 16px;
+  padding: 4px 8px;
+  background: none;
+  color: white;
+  border: none;
+  border-radius: 3px;
+  cursor: pointer;
+  white-space: nowrap;
+}
+
+.info button:disabled {
+  cursor: not-allowed;
+}
+</style>

+ 676 - 0
components/Draw/index.vue

@@ -0,0 +1,676 @@
+<template>
+  <div class="canvas-container" ref="canvasContainer">
+    <div class="canvas float-left" ref="yfcontainer" v-loading="loading">
+      <!-- 画布 -->
+      <canvas
+        :style="{
+          width: canvasSize.width + 'px',
+          height: canvasSize.height + 'px',
+        }"
+        canvas-id="yfCanvas"
+        id="yfCanvas"
+      ></canvas>
+      <!-- 文本标签 -->
+      <!-- <div class="element-layer">
+        <span
+          class="label-link cursor"
+          v-for="tag in rectangles"
+          @click="deleteSpan($event, tag.id)"
+          :key="tag.id"
+          :style="linkStyle(tag)"
+        >
+          <span class="delete" @click.stop="deleteSpan($event, tag.id)">✖</span>
+        </span>
+      </div> -->
+    </div>
+  </div>
+</template>
+
+<script>
+import Panel from './comps/panel.vue';
+import Tools from './comps/tools.vue';
+import Annotation from './comps/Annotation.vue';
+let myRatio = 1;
+export default {
+  props: {
+    markItem: {
+      type: Object,
+      default: () => ({
+        addr: 'https://bigdata-image.oss-cn-hangzhou.aliyuncs.com/Basics/cbd/666000000000001/2025/7/11/001.jpg',
+        mark: [],
+        is_mark: 0,
+        label:
+          "[{'71': [480, 47, 520, 91, 1.0]}, {'71': [513, 102, 545, 155, 1.0]}, {'71': [690, 238, 740, 272, 1.0]}, {'71': [298, 471, 335, 514, 1.0]}, {'71': [250, 379, 300, 407, 1.0]}, {'71': [106, 40, 143, 89, 1.0]}, {'71': [46, 12, 124, 58, 0.99]}, {'71': [2, 90, 41, 133, 0.98]}, {'71': [767, 189, 799, 237, 0.98]}, {'71': [721, 175, 758, 216, 0.92]}, {'71': [685, 132, 727, 166, 0.35]}]",
+      }),
+    },
+    isInitFullScreen: {
+      type: Boolean,
+      default: false,
+    },
+    reIdentify: {
+      type: Boolean,
+      default: true,
+    },
+    title: {
+      type: String,
+      default: '目录',
+    },
+
+    typeName: {
+      type: Number,
+      default: 1, // 1: 测报灯  2:病虫害可视监测 3:吸虫塔 4:孢子仪
+    },
+  },
+  watch: {
+    markItem: {
+      handler(newVal) {
+        console.log('markItem变化:', newVal, this.ctx);
+        // 当markItem变化时,重新加载图片和标注
+        if (!newVal.addr && this.ctx) {
+          this.clearCanvas();
+          return;
+        }
+        if (this.ctx) {
+          this.loadImage();
+        }
+      },
+      deep: true,
+    },
+  },
+  components: {
+    Panel,
+    Tools,
+    Annotation,
+  },
+  name: 'Draw',
+  computed: {
+    inputStyle() {
+      return {
+        left: `${this.inputPosition.x}px`,
+        top: `${this.inputPosition.y}px`,
+      };
+    },
+    canvasStyle() {
+      return {
+        cursor: this.mode === 'draw' ? 'crosshair' : 'grab',
+      };
+    },
+    fullScreenHtml() {
+      return this.$refs.canvasContainer;
+    },
+  },
+  data() {
+    return {
+      imgTimer: false, // 图片时间戳
+      ctx: null,
+      scale: 1, // 画布的缩放
+      imageScale: 1, // 图片的原始缩放
+      markScale: 1, // 绘制的缩放
+      baseScale: 0.31,
+      offsetX: 0,
+      offsetY: 0,
+      mode: 'drag', // 'draw' / 'drag'
+      modeLabels: {
+        draw: 'D绘制',
+        drag: 'S拖拽',
+        select: '空格选择',
+      },
+      isDragging: false,
+      isDrawing: false,
+      lastX: 0,
+      lastY: 0,
+      startX: 0,
+      startY: 0,
+      rectangles: [],
+      currentRect: null,
+      selectedRect: null,
+      backgroundImage: null,
+      imageLoaded: false,
+      originalImageSize: { width: 0, height: 0 },
+      isFullScreen: false,
+      imageRect: { x: 0, y: 0, width: 0, height: 0 }, // 存储图片显示区域
+      showInput: false,
+      currentLabel: '',
+      inputPosition: { x: 0, y: 0 },
+      currentRectId: null,
+
+      lastImageScale: 1,
+      loading: true,
+      isMoving: false,
+      colorMap: {}, // 用于存储文本和颜色的映射关系
+      tempColor: '#FFFF00', // 绘制时黄色半透明
+      finalColor: '#FF0000', // 完成后红色半透明
+      changeLeftActive: false,
+      changeRightActive: false,
+      colorIndex: 0,
+      originDataLength: 0, // 用于记录原始数据长度
+      pestLibrary: {},
+      canvasSize: { width: 310, height: 279 },
+    };
+  },
+  created() {
+    this.getAllPestList();
+  },
+  mounted() {
+    // console.log('初始化markItem:', this.markItem)
+
+    uni.getSystemInfo({
+      success: (res) => {
+        this.canvasSize.width = res.windowWidth - (24 * 2 + 16 * 2);
+      },
+    });
+    this.$nextTick(() => {});
+  },
+  beforeDestroy() {},
+  methods: {
+    // 切换上一个下一个
+    changeItem(type) {
+      this.$emit('changeItem', { type: type, isFullScreen: this.isFullScreen });
+    },
+    changeMode(modeType) {
+      this.mode = modeType;
+    },
+
+    resetPest() {
+      // 通知业务上层处理逻辑
+      this.exitFullScreen();
+      this.$emit('resetPest');
+    },
+    // 查看原图
+    checkImagePreview() {
+      this.$refs.imgPreview.click();
+    },
+
+    linkStyle(tag) {
+      let x = Math.min(tag.startX, tag.endX);
+      let y = Math.min(tag.startY, tag.endY);
+
+      const top = y * this.scale + this.offsetY - 20 + 'px';
+      const left = x * this.scale + this.offsetX + 'px';
+      return {
+        top,
+        left,
+        color: tag.color,
+        'pointer-events': this.isMoving ? 'none' : 'auto',
+      };
+    },
+    initCanvas() {
+      this.ctx = uni.createCanvasContext('yfCanvas', this);
+      console.log(this.ctx);
+      this.loadImage();
+    },
+
+    loadImage() {
+      if (!this.markItem.addr) {
+        this.loading = false;
+        return;
+      }
+
+      uni.getImageInfo({
+        src: this.markItem.addr,
+        success: (res) => {
+          this.imageLoaded = true;
+          this.backgroundImage = res;
+          this.originalImageSize = {
+            width: this.backgroundImage.width,
+            height: this.backgroundImage.height,
+          };
+          this.rectangles = []; // 清除之前的标注
+          this.selectedRect = null;
+          this.adjustImagePosition();
+          this.initMarkData();
+          this.draw();
+          this.loading = false;
+        },
+        fail: (err) => {
+          this.loading = false;
+          this.$message.error('图片加载失败');
+        },
+      });
+    },
+
+    adjustImagePosition() {
+      if (!this.imageLoaded) return;
+
+      const canvas = this.canvasSize;
+      const canvasAspect = canvas.width / canvas.height;
+      const imageAspect =
+        this.originalImageSize.width / this.originalImageSize.height;
+
+      // 计算等比缩放的尺寸
+      if (imageAspect > canvasAspect) {
+        this.imageScale = canvas.width / this.originalImageSize.width;
+      } else {
+        this.imageScale = canvas.height / this.originalImageSize.height;
+      }
+      // this.imageScale = 0.8
+      // 根据图片的宽度来定义缩放比例
+      if (this.originalImageSize.width >= 5000) {
+        this.baseScale = 0.25;
+      } else if (this.originalImageSize.width >= 4000) {
+        this.baseScale = 0.31;
+      } else if (this.originalImageSize.width < 4000) {
+        this.baseScale = 0.4;
+      }
+      // 用来处理图片等比例显示
+      this.markScale = 1 - (this.baseScale - this.imageScale) / this.baseScale;
+      // 窗口大小改变的时候使用
+      myRatio = this.imageScale / this.lastImageScale;
+
+      this.lastImageScale = this.imageScale;
+      // 计算图片显示区域
+      this.imageRect = {
+        x: 0,
+        y: 0,
+        width: this.originalImageSize.width * this.imageScale,
+        height: this.originalImageSize.height * this.imageScale,
+      };
+
+      // 初始位置居中
+      this.scale = 1;
+      this.offsetX = (canvas.width - this.imageRect.width) / 2;
+      this.offsetY = (canvas.height - this.imageRect.height) / 2;
+    },
+
+    isPointInImage(x, y) {
+      return (
+        x >= 0 &&
+        x <= this.imageRect.width &&
+        y >= 0 &&
+        y <= this.imageRect.height
+      );
+    },
+    constrainRect(rect) {
+      // 确保矩形完全在图片区域内
+      const startX = Math.max(0, Math.min(this.imageRect.width, rect.startX));
+      const startY = Math.max(0, Math.min(this.imageRect.height, rect.startY));
+      const endX = Math.max(0, Math.min(this.imageRect.width, rect.endX));
+      const endY = Math.max(0, Math.min(this.imageRect.height, rect.endY));
+
+      return {
+        ...rect,
+        startX,
+        startY,
+        endX,
+        endY,
+      };
+    },
+
+    handleLabelChange() {
+      this.draw();
+    },
+
+    getRectAt(x, y) {
+      // 从后往前检查,这样最后绘制的矩形会优先被选中
+      for (let i = this.rectangles.length - 1; i >= 0; i--) {
+        const rect = this.rectangles[i];
+        const left = Math.min(rect.startX, rect.endX);
+        const right = Math.max(rect.startX, rect.endX);
+        const top = Math.min(rect.startY, rect.endY);
+        const bottom = Math.max(rect.startY, rect.endY);
+
+        if (x >= left && x <= right && y >= top && y <= bottom) {
+          return rect;
+        }
+      }
+      return null;
+    },
+
+    deleteSelected() {
+      if (this.selectedRect) {
+        this.deleteRect(this.selectedRect.id);
+        this.selectedRect = null;
+      }
+    },
+
+    deleteRect(id) {
+      this.rectangles = this.rectangles.filter((rect) => rect.id !== id);
+      if (this.selectedRect && this.selectedRect.id === id) {
+        this.selectedRect = null;
+      }
+      this.showInput = false;
+      this.currentRectId = null;
+      this.draw();
+    },
+    deleteSpan(e, id) {
+      e.preventDefault();
+      e.stopPropagation();
+      this.isDrawing = false;
+      this.deleteRect(id);
+    },
+    clearCanvas() {
+      this.loading = false;
+      this.imageLoaded = false;
+      this.rectangles = [];
+      this.selectedRect = null;
+      this.showInput = false;
+      this.currentRectId = null;
+      const canvas = this.canvasSize;
+      const ctx = this.ctx;
+
+      // 清除画布
+      ctx.clearRect(0, 0, canvas.width, canvas.height);
+    },
+    // 修改后的 draw 方法
+    draw() {
+      const canvas = this.canvasSize;
+      const ctx = this.ctx;
+
+      // 清除画布
+      ctx.clearRect(0, 0, canvas.width, canvas.height);
+      console.log(this.offsetX, this.offsetY);
+      // 保存当前状态
+      ctx.save();
+
+      // 应用变换(缩放和平移)
+      ctx.translate(this.offsetX, this.offsetY);
+      ctx.scale(this.scale, this.scale);
+
+      // 绘制背景图片(不再除以this.scale)
+      if (this.imageLoaded && this.backgroundImage) {
+        const displayWidth = this.originalImageSize.width * this.imageScale;
+        const displayHeight = this.originalImageSize.height * this.imageScale;
+        // ctx.imageSmoothingEnabled = true
+        // ctx.imageSmoothingQuality = 'high'
+        ctx.drawImage(
+          this.backgroundImage.path,
+          0,
+          0,
+          displayWidth,
+          displayHeight
+        );
+      }
+      console.log('绘制::', this.rectangles);
+      // 绘制所有已保存的矩形(添加约束)
+      this.rectangles.forEach((rect) => {
+        const constrainedRect = this.constrainRect(rect);
+        this.drawRectangle(constrainedRect, rect === this.selectedRect);
+      });
+
+      // 绘制当前正在绘制的矩形(添加约束)
+      if (this.currentRect) {
+        const constrainedRect = this.constrainRect(this.currentRect);
+        this.drawRectangle(constrainedRect, false);
+      }
+
+      // 恢复状态
+      ctx.restore();
+      ctx.draw();
+    },
+
+    drawRectangle(rect, isSelected) {
+      const ctx = this.ctx;
+
+      const x = Math.min(rect.startX, rect.endX);
+      const y = Math.min(rect.startY, rect.endY);
+      const width = Math.abs(rect.endX - rect.startX);
+      const height = Math.abs(rect.endY - rect.startY);
+
+      // 绘制矩形填充
+
+      ctx.strokeStyle = rect.color;
+      ctx.lineWidth = 2 / this.scale;
+      ctx.strokeRect(x, y, width, height);
+      // 绘制标签文本
+      if (rect.text) {
+        ctx.fillStyle = rect.color;
+        ctx.font = `${14 / this.scale}px Arial`;
+        ctx.fillText(rect.text, x + 12 / this.scale, y - 6 / this.scale);
+      }
+    },
+
+    // 获取数据
+    getData() {
+      const data = this.rectangles.map((rect) => {
+        return {
+          startX: parseFloat((rect.startX / this.markScale).toFixed(2)),
+          startY: parseFloat((rect.startY / this.markScale).toFixed(2)),
+          width: parseFloat(
+            (Math.abs(rect.startX - rect.endX) / this.markScale).toFixed(2)
+          ),
+          height: parseFloat(
+            (Math.abs(rect.startY - rect.endY) / this.markScale).toFixed(2)
+          ),
+          text: rect.text,
+        };
+      });
+      this.originDataLength = data.length;
+      return data;
+      // return JSON.stringify(data)
+    },
+    // 处理渲染数据
+    async initMarkData() {
+      const colorList = [
+        '#FF0000',
+        '#00FFC2',
+        '#FF00A8',
+        '#120080',
+        '#BDFF00',
+        '#FFB800',
+        '#5E8000',
+        '#FF5C00',
+        '#00FF75',
+        '#00F0FF',
+        '#0094FF',
+        '#FFFFFF',
+        '#007880',
+        '#00C2FF',
+        '#C74C4C',
+        '#EB00FF',
+      ];
+      if (this.markItem.is_mark === 0) {
+        // 机器标注,取label
+        let aiLabel = [];
+        if (this.markItem.label) {
+          aiLabel = JSON.parse(this.markItem.label.replace(/'/g, '"'));
+        }
+        this.rectangles = [];
+        console.log('00000', aiLabel);
+        aiLabel.forEach((item, index) => {
+          for (let key in item) {
+            const [startX, startY, endX, endY] = item[key];
+            const text = this.pestLibrary[key];
+            if (!this.colorMap[text]) {
+              this.colorMap[text] =
+                colorList[this.colorIndex % colorList.length];
+              this.colorIndex += 1;
+              if (this.colorIndex >= colorList.length) {
+                this.colorIndex = 0;
+              }
+            }
+            this.rectangles.push({
+              id: Date.now() + index,
+              text: text,
+              startX: startX * this.imageScale,
+              startY: startY * this.imageScale,
+              endX: endX * this.imageScale,
+              endY: endY * this.imageScale,
+              color: this.colorMap[text],
+              imageScale: this.imageScale,
+            });
+          }
+        });
+        this.originDataLength = this.rectangles.length;
+      } else {
+        // 人工标注,取mark
+        console.log('this.colorIndex', this.colorIndex);
+        this.rectangles = [];
+        this.markItem.mark.map((item, index) => {
+          const { startX, startY, width, height, text } = item;
+          if (!this.colorMap[text]) {
+            this.colorMap[text] = colorList[this.colorIndex % colorList.length];
+            this.colorIndex += 1;
+            if (this.colorIndex >= colorList.length) {
+              this.colorIndex = 0;
+            }
+          }
+          this.rectangles.push({
+            id: Date.now() + index,
+            text: text,
+            startX: Number(startX) * this.markScale,
+            startY: Number(startY) * this.markScale,
+            endX:
+              Number(startX) * this.markScale + Number(width) * this.markScale,
+            endY:
+              Number(startY) * this.markScale + Number(height) * this.markScale,
+            color: this.colorMap[text],
+            imageScale: this.imageScale,
+          });
+        });
+        this.originDataLength = this.rectangles.length;
+      }
+      console.log('原始rectangles', this.rectangles);
+    },
+    // 保存标注
+    saveLabel() {
+      this.$emit('saveLabel', this.getData());
+    },
+    async getAllPestList() {
+      const res = await this.$myRequest({
+        url: '/api/api_gateway?method=forecast.pest_info.pest_dict',
+        data: {
+          type_name: this.typeName,
+        },
+      });
+      // console.log('获取到的病虫害数据', res)
+      this.pestLibrary = res;
+      this.initCanvas();
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+@primary-color: #018b3f !important;
+::v-deep .el-button--primary {
+  background-color: @primary-color !important;
+}
+.canvas-container {
+  width: 100%;
+  height: 100%;
+  position: relative;
+  background: #ffffff;
+  padding-top: 10px;
+  .virtual-canvas {
+    /* 2025安全隐藏方案 */
+    position: absolute !important;
+    clip: rect(0 0 0 0) !important;
+    pointer-events: none !important;
+    opacity: 0 !important;
+    z-index: -9999 !important;
+  }
+  .canvas {
+    width: 100%;
+    height: 100%;
+    overflow: hidden;
+    background-color: #ffffff;
+    border: 1px solid #e4e7ed;
+    box-sizing: border-box;
+    position: relative;
+  }
+  .canvas-timer {
+    position: absolute;
+    left: 16px;
+    top: 16px;
+    z-index: 2;
+    color: #ffffff;
+    font-size: 23px;
+  }
+  .panel {
+    width: 30%;
+    height: calc(100% - 60px);
+    background: #ffffff;
+    padding-left: 10px;
+    box-sizing: border-box;
+    position: relative;
+    z-index: 3;
+    .save {
+      height: 60px;
+      button {
+        margin: 14px;
+      }
+    }
+  }
+  .controls {
+    // padding: 3px 15px;
+    width: 70%;
+    height: 64px;
+    box-sizing: border-box;
+    position: relative;
+    z-index: 3;
+    // background: rgba(0, 0, 0, 0.3);
+  }
+  .img-timer {
+    position: absolute;
+    left: 0;
+    top: 22px;
+  }
+  .info {
+    // width: 100%;
+    // color: #ffffff;
+    // overflow: hidden;
+    // text-align: center;
+    .tools {
+      // width: 365px;
+      height: 64px;
+      // padding: 0 10%;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      // background: rgba(0, 0, 0, 0.6);
+      border-radius: 4px;
+      gap: 10px;
+      // margin: 0 auto;
+      color: rgba(0, 0, 0, 0.6);
+      .active {
+        background: @primary-color;
+        color: #ffffff;
+      }
+      .split {
+        color: #b9b9b9;
+        margin: 0 5px;
+        font-size: 14px;
+      }
+    }
+    .float-right {
+      width: 30%;
+    }
+    .img-preview {
+      display: none;
+      width: 20px;
+      position: absolute;
+    }
+  }
+
+  .info span {
+    white-space: nowrap;
+    .active {
+      color: @primary-color;
+      margin-right: 5px;
+    }
+  }
+
+  .info button {
+    font-size: 26px;
+    padding: 2px 4px;
+    background: none;
+    border: none;
+    border-radius: 3px;
+    cursor: pointer;
+    white-space: nowrap;
+    color: #434343;
+  }
+
+  .info button:disabled {
+    cursor: not-allowed;
+  }
+  .element-layer {
+    .label-link {
+      position: absolute;
+      z-index: 2;
+      user-select: none;
+      pointer-events: auto;
+    }
+  }
+}
+</style>

Разница между файлами не показана из-за своего большого размера
+ 125 - 0
components/bazaar-city_list/citylist.json


+ 299 - 0
components/bazaar-city_list/index.vue

@@ -0,0 +1,299 @@
+<template>
+	<view class="citylist">
+		<scroll-view :style="{'height':windowH}" scroll-y="true" :scroll-top="scrollTop"  show-scrollbar="false" @scroll="scroll" >
+			<view>
+				<view class="city-list-container">
+					<!-- 定位城市 -->
+					<view class="city-list-content" id="location_city">
+						<view class="city-title">定位城市</view>
+						<view class="city-list city-list-inline" @tap="location">
+							<view class="location-city">{{locationCity}}</view>
+						</view>
+					</view>
+					<!-- 热门城市 -->
+					<view id="hotcity" class="city-list-content">
+						<view class="city-title">
+							{{hotcity.title}}
+						</view> 
+						<view class="city-list city-list-inline">
+							<view class="city-item" v-for="(item,index) in hotcity.lists" :key="`city${index}`" @tap="selectedCity(item)">
+								{{item}}
+							</view>
+						</view>
+					</view>
+					<!-- 城市列表 -->
+					<view id="citytitle" class="city-list-content">
+						<view class="city_title_wrap" v-for="(city,index) in citylist" :key="`citylist${index}`">
+							<view class="city-title city-title-letter">
+								{{city.title}}
+							</view>
+							<view class="city-list city-list-block">
+								<view class="city-item" v-for="(item,index) in city.lists" :key="`item${index}`" @tap="selectedCity(item)">
+									{{item}}
+								</view>
+							</view>
+						</view>
+					</view>
+				</view>
+			</view>
+		</scroll-view>
+		<!-- 固定顶部 -->
+		<view class="fixtitle" :style="{transform:fixedStyle}">
+			<view class="city-title">{{fixedTitle}}</view>
+		</view>
+		<!-- 侧边栏导航 -->
+		<view class="navrightcity">
+			<view class="nav-item nav-letter" @tap="scroll_to_city(0)">定</view>
+			<view class="nav-item nav-letter" @tap="scroll_to_city(1)">热</view>
+			<view v-for="(item,index) in citylist" :key="`nav${index}`" class="nav-item nav-letter" @click="scroll_to_city(index+2)">
+				{{item.title}}
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import CL from './citylist.json'
+	export default{
+		props:{
+			getCity:{
+				type:Function,
+				default:function(){}
+			}
+		},
+		computed:{
+			fixedTitle(){
+				if (this.scrollY < 0) {
+					return ''
+				}
+				return this.title && this.title[this.currentIndex]
+			}
+		},
+		watch:{
+			scrollY(newY){
+				const {tops} = this
+				const index = tops.findIndex((top, index) => {
+					this.diff = tops[index + 1] - newY
+					return newY >= top && newY < tops[index + 1]
+				})
+				this.currentIndex = index;
+			},
+			diff(newVal) {
+				let fixedTop = (newVal > 0 && newVal < 30) ? newVal - 30 : 0
+				if (this.fixedTop === fixedTop) {
+					this.fixedStyle = `translate3d(0,0,0)`
+				}
+				this.fixedTop = fixedTop
+				this.fixedStyle = `translate3d(0,${this.fixedTop}px,0)`
+			}
+		},
+		data(){
+			return{
+				scrollY:-1,//滚动记录
+				tops:[],//每一个.city-title 距离顶部的距离
+				diff:-1, // 
+				citylist:{},
+				hotcity:{},
+				currentIndex:0,
+				title:[],
+				windowH:"",
+				scrollTop:0,
+				fixedStyle:"translate3d(0,0,0)",
+				fixedTop:0,
+				locationCity:"定位中...."
+			}
+		},
+		methods:{
+			// 初始化数据列表
+			initCityList(){
+				let title = [];
+				this.hotcity = CL.hotcity;
+				this.citylist = CL.city
+				title.push("定位城市");
+				title.push(this.hotcity.title);
+				for(let i in this.citylist){
+					title.push(this.citylist[i].title)
+				}
+				this.title = title;
+				let sysInfo = uni.getSystemInfoSync();
+				this.windowH = sysInfo.windowHeight + "px"
+			} ,
+			initTop(){
+				// 1. 初始化tops
+				const query = uni.createSelectorQuery();
+				query.select('#location_city').boundingClientRect()
+				.select('#hotcity').boundingClientRect()
+				.selectAll('.city_title_wrap').boundingClientRect()
+				.exec((list)=>{
+					let tops = []
+					let top = 0
+					tops.push(top);
+					if(list[0]){
+						top += list[0].height;
+						tops.push(top)
+					}
+					if(list[1]){
+						top += list[1].height;
+						tops.push(top)
+					}
+					if(list[2].length !== 0){
+						for(let i in list[2]){
+							top+= list[2][i].height
+							tops.push(top);
+						}
+					}
+					this.tops = tops;
+				})
+			},
+			// 获取城市
+			// selectedCity({city}){
+			selectedCity(city){
+				console.log(city);
+				this.getCity&&this.getCity({city});
+			},
+			// 定位操作
+			location(){
+				let That = this;
+				uni.chooseLocation({
+				    success(res){
+						console.log(res);
+						uni.setStorage({
+							key:"location",
+							data:[res.longitude,res.latitude]
+						})
+						console.log(res.address);
+						That.locationCity = res && res.address;
+						That.locationName = res && res.name;
+						That.selectedCity({city:That.locationCity,name:That.locationName});
+				    },
+					fail(){
+						That.locationCity = "定位失败,请点击重试";
+						That.locationName = "";
+					}
+				});
+			},
+			// 滚动条Y距离
+			scroll(e){
+				this.scrollY = e.detail && e.detail.scrollTop;
+			},
+			// 滚动到指定位置
+			scroll_to_city(index){
+				this.scrollTop = this.tops[index]
+				this.scrollY = scrollY
+				this.cityScroll.scrollTo(0, -scrollY, 300)
+			}
+		},
+		// 页面挂载后进行异步操作
+		created(){
+			this.initCityList();
+		},
+		mounted(){
+			this.location();
+			this.initTop();
+		}
+	}
+</script>
+
+<style lang="less">
+	.citylist{
+		width: 100%;
+		height: 100%;
+		overflow: hidden;
+		position: relative;
+	}
+	.city-list-container{
+		width: 100%;
+		height: 100%;
+		background-color: #ebebeb;
+		font-size: 14px;
+		color: #333;
+		.city-list-content{
+			margin-right: 25px;
+		}
+		.city-title{
+			padding-left: 15px;
+			line-height: 30px;
+		}
+		.city-list{
+			padding-right: 30px;
+		}
+		.city-title-letter {
+			padding-left: 25px;
+		}
+		.city-list-block {
+			background-color: #f5f5f5;
+			.city-item {
+				height: 44px;
+				line-height: 44px;
+				margin-left: 15px;
+				border-bottom: 1px solid #c8c7cc;
+				&:last-child{
+					border: 0;
+				}
+			}
+		}
+		.city-list-inline {
+			background-color: #f5f5f5;
+			padding-bottom: 8px;
+			overflow: hidden;
+			&::after{
+				content: "";
+				clear: both;
+			}
+			.location-city,.city-item {
+				float: left;
+				background: #fff;
+				width: 29%;
+				height: 33px;
+				margin-top: 15px;
+				margin-left: 4%;
+				padding: 0 4px;
+				border: 1px solid #e6e6e6;
+				border-radius: 3px;
+				line-height: 33px;
+				text-align: center;
+				box-sizing: border-box;
+				white-space: nowrap;
+				overflow: hidden;
+				text-overflow: ellipsis;
+			}
+			.location-city{
+				width: auto;
+				min-width: 30%;
+				padding: 0 20px;
+			}
+		}
+	}
+	.navrightcity {
+		position: fixed;
+		top: 50%;
+		transform: translateY(-50%);
+		right: 0;
+		width: 35px;
+		z-index: 10;
+		text-align: center;
+		font-size: 12px;
+		.nav-item {
+			height: 16px;
+			height: 2.8vh;
+		}
+		.nav-letter {
+			width: 15px;
+			margin-left: 15px;
+		}
+	}
+	.fixtitle{
+		width: 100%;
+		position: fixed;
+		top: 0;
+		left: 0;
+		overflow: hidden;
+		.city-title{
+			padding-left: 15px;
+			line-height: 30px;
+			font-size: 14px;
+			color: #333;
+			background-color: #ebebeb;
+		}
+	}
+</style>

Разница между файлами не показана из-за своего большого размера
+ 1063 - 0
components/city.js


+ 66 - 0
components/customCard/customCard.vue

@@ -0,0 +1,66 @@
+<template>
+  <view class="custom-card">
+    <view class="custom-card-header">
+      <view class="custom-card-action">
+        <u-icon name="arrow-left" color="#333333" size="32rpx" @tap="BackPage"/>
+        <view class="custom-card-action-text">
+          <slot name="backText"></slot>
+        </view>
+      </view>
+      <view class="cu-bar-right">
+        <slot name="right"></slot>
+      </view>
+    </view>
+  </view>
+</template>
+<script>
+export default {
+  name: 'custom-card',
+  props: {},
+  data() {
+    return {};
+  },
+  methods: {
+    BackPage() {
+      uni.navigateBack({
+        delta: 1,
+      });
+    },
+  },
+};
+</script>
+<style scoped lang="scss">
+.custom-card {
+  border-radius: 16upx;
+  opacity: 1;
+  padding-top: 80rpx;
+}
+
+.custom-card-header {
+  padding: 0 20rpx;
+  height: 90rpx;
+  color: #333333;
+  font-size: 28rpx;
+  font-weight: 600;
+  font-family: 'PingFang SC';
+  line-height: 44rpx;
+  position: relative;
+  .custom-card-action {
+    display: flex;
+    align-items: center;
+    height: 90rpx;
+    line-height: 90rpx;
+    .custom-card-action-text {
+      width: 90%;
+      text-align: center;
+      color: #042118;
+      font-size: 34rpx;
+    }
+  }
+  .cu-bar-right {
+    position: absolute;
+    right: 20rpx;
+    top: 20rpx;
+  }
+}
+</style>

+ 84 - 0
components/equip-item/equip-item.vue

@@ -0,0 +1,84 @@
+<template>
+	<view class="item">
+		<template v-if="item.is_online==1">
+			<view class="tag tag-on" ></view>
+		</template>
+		<template v-else>
+			<view class="tag tag-off" ></view>
+		</template>
+		<view class="info">
+			<text class="">设备名称:{{item.device_name==""?"无":item.device_name}}</text>
+			<text v-if="item.is_online==1" class="state on">在线</text>
+			<text v-else  class="state off">离线</text>
+		</view>
+		<slot></slot>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				tagOn:'/image/tab-on.png',
+				tagOff:'/image/tab-off.png',
+			}
+		},
+		props:[
+			'item'
+		],
+		methods: {
+			
+		}
+	}
+</script>
+
+<style lang="scss">
+	.item {
+		background: #fff;
+		margin-top: 20rpx;
+		padding: 10rpx 30rpx;
+		padding-left:80rpx;
+		border-radius: 4rpx;
+		box-shadow: 0 0 4px 2px rgba(0, 0, 10, 0.05);
+		line-height: 60rpx;
+		position: relative;
+		.tag {
+			position: absolute;
+			width: 30rpx;
+			height: 60rpx;
+			top: 0;
+			left: 20rpx;
+			background-repeat: no-repeat;
+			background-size:100% auto;
+			background-position: top left;
+		}
+
+		.tag-on {
+			 background-image:url('https://s3.hnyfwlw.com/webstaticimg/bigdata_app/image/on.png');
+		}
+
+		.tag-off {
+			  background-image:url('https://s3.hnyfwlw.com/webstaticimg/bigdata_app/image/off.png');
+		}
+
+		.info {
+			border-bottom: 1px solid #F5F5F5;
+			color: #333;
+			font-size: 28rpx;
+			display: flex;
+			justify-content: space-between;
+			.on {
+				color: $uni-color-success;
+			}
+			.off{
+				color:$uni-color-error;
+			}
+
+		}
+
+		.date {
+			color: #999;
+			font-size: 24rpx;
+		}
+	}
+</style>

+ 13 - 0
components/js_sdk/u-charts/package.json

@@ -0,0 +1,13 @@
+{
+    "id": "u-charts",
+    "name": "uCharts高性能跨全端图表",
+    "version": "1.9.6.20210214",
+    "description": "支持H5、PC、APP、小程序(微信/支付宝/百度/头条/QQ/360)Vue、Taro",
+    "keywords": [
+        "echarts",
+        "canvas2d",
+        "F2",
+        "图表",
+        "跨全端"
+    ]
+}

+ 471 - 0
components/js_sdk/u-charts/u-charts/config.js

@@ -0,0 +1,471 @@
+/*
+ * uCharts组件 默认配置文件,如有修改,更新前请备份此文件!!
+ * Copyright (c) 2021 QIUN秋云 https://www.ucharts.cn All rights reserved.
+ * Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+ * 
+ * uCharts官方网站
+ * https://www.uCharts.cn
+ * 
+ * 开源地址:
+ * https://gitee.com/uCharts/uCharts
+ * 
+ * uni-app插件市场地址:
+ * http://ext.dcloud.net.cn/plugin?id=271
+ * 
+ */
+module.exports = {
+	"type":["pie","ring","rose","word","funnel","map","arcbar","line","column","area","radar","gauge","candle","mix","point","bubble"],
+	"categories":["line","column","area","radar","gauge","candle","mix","point","bubble"],
+	//以上数据请勿改动,下面是自定义默认配置,请添加项目所需的个性配置
+	"pie":{
+		type: 'pie',
+		padding:[15,15,0,15],
+		legend:{
+			show:true,
+			padding:5,
+			lineHeight:11,
+			margin:0,
+		},
+		dataLabel: true,
+		extra: {
+			pie: {
+		    border:true,
+		    borderColor:'#FFFFFF',
+		    borderWidth:3
+			}
+		}
+	},
+	"ring":{
+		type: 'ring',
+		padding:[5,5,5,5],
+		legend:{
+			show:true,
+			position:'right',
+			float:'center',
+			itemGap:10,
+			padding:5,
+			lineHeight:26,
+			margin:5,
+			borderWidth :1
+		},
+		disablePieStroke: true,
+		dataLabel: true,
+		subtitle: {
+			name: '70%',
+			color: '#7cb5ec',
+			fontSize: 25,
+		},
+		title: {
+			name: '收益率',
+			color: '#666666',
+			fontSize: 15,
+		},
+		extra: {
+			pie: {
+			  offsetAngle: 0,
+			  ringWidth: 40,
+			  labelWidth:15
+			}
+		}
+	},
+	"rose":{
+		type: 'rose',
+		padding:[15,15,0,15],
+		legend:{
+			show:true,
+			position:'left',
+			float:'center',
+			itemGap:10,
+			padding:5,
+			lineHeight:26,
+			margin:5,
+			borderWidth :1
+		},
+		dataLabel: true,
+		extra: {
+			rose: {
+				type:'area',
+				minRadius:50,
+				activeOpacity:0.5,
+				offsetAngle:0,
+				labelWidth:15
+			}
+		}
+	},
+	"word":{
+		type: 'word',
+		extra: {
+			word: {
+				type: 'normal'
+			}
+		}
+	},
+	"funnel":{
+		type: 'funnel',
+		padding:[15,15,0,15],
+		legend:{
+			show:true,
+			padding:5,
+			lineHeight:11,
+			margin:0,
+		},
+		dataLabel: true,
+		extra: {
+			funnel: {
+		    border:true,
+		    borderWidth:2,
+		    borderColor:'#FFFFFF'
+			}
+		}
+	},
+	"map":{
+		type: 'map',
+		padding:[0,0,0,0],
+		legend:{
+			show:false
+		},
+		dataLabel:true,
+		extra: {
+			map: {
+		    border:true,
+		    borderWidth:1,
+		    borderColor:'#666666',
+		    fillOpacity:0.6
+			}
+		}
+	},
+	"arcbar":{
+		type: 'arcbar',
+		legend:{show:false},
+		dataLabel: true,
+		title: {
+			name: "百分比",
+			color: '#00FF00',
+			fontSize: 25
+		},
+		subtitle: {
+			name: "默认标题",
+			color: '#666666',
+			fontSize: 15
+		},
+		extra: {
+			arcbar:{
+				type:'default',
+				width: 12,
+			}
+		}
+	},
+	"line":{
+		type: 'line',
+		padding:[15,30,0,15],
+		legend:{
+			show:true,
+			padding:5,
+			lineHeight:11,
+			margin:0,
+		},
+		dataLabel: true,
+		dataPointShape:true,
+		xAxis: {
+			disableGrid: true,
+		},
+		yAxis: {
+			gridType: 'dash',
+			gridColor: '#CCCCCC',
+			dashLength: 8,
+			splitNumber: 4,
+			format: val => {
+				return val.toFixed(0);
+			}
+		},
+		extra: {
+			line:{
+				type: 'straight'
+			}
+		}
+	},
+	"column":{
+		type: 'column',
+		padding:[15,5,0,15],
+		legend:{
+			show:true,
+			padding:5,
+			lineHeight:11,
+			margin:0,
+		},
+		animation: true,
+		dataLabel: true,
+		xAxis: {
+			disableGrid:true,
+		},
+		yAxis: {
+		  data:[{
+		    position:'right',
+				axisLine:false,
+		    format:(val)=>{return val.toFixed(0)},
+		  }]
+		},
+		extra: {
+			column: {
+				type:'group',
+				width:30
+			}
+		}
+	},
+	"area":{
+		type: 'area',
+		padding:[15,15,0,15],
+		legend:{
+			show:true,
+		},
+		dataLabel:true,
+		dataPointShape:true,
+		xAxis: {
+			disableGrid:true,
+		},
+		yAxis: {
+			gridType:'dash',
+			gridColor:'#CCCCCC',
+			dashLength:8,
+			splitNumber:5,
+		},
+		extra: {
+			area:{
+				type: 'straight',
+				opacity:0.2,
+				addLine:true,
+				width:2,
+				gradient:false
+			}
+		}
+	},
+	"radar":{
+		type: 'radar',
+		padding:[15,15,0,15],
+		legend:{
+			show:true,
+			padding:5,
+			lineHeight:11,
+			margin:0,
+		},
+		animation: true,
+		dataLabel: true,
+		extra: {
+			radar: {
+				max: 200,
+				gridType:'radar'//radar或者circle可选,网格样式,默认radar
+			}
+		}
+	},
+	"gauge":{
+		type: 'gauge',
+		legend:{show:false},
+		animation: true,
+		dataLabel: true,
+		title: {
+			name: "字符串类型",
+			color: '#00FF00',
+			fontSize: 25,
+			offsetY:50,
+		},
+		subtitle: {
+			name: "字符串类型",
+			color: '#666666',
+			fontSize: 15,
+			offsetY:-50,
+		},
+		extra: {
+			gauge:{
+				type:'default',
+				width: 30,
+				startAngle:0.75,
+				endAngle:0.25,
+				startNumber:0,
+				endNumber:100,
+				splitLine:{
+					fixRadius:0,
+					splitNumber:10,
+					width: 30,
+					color:'#FFFFFF',
+					childNumber:5,
+					childWidth:30*0.4,
+				},
+				pointer:{
+					width: 30*0.8,
+					color:'auto'
+				}
+			}
+		}
+	},
+	"candle":{
+		type: 'candle',
+		padding:[15,15,0,15],
+		legend:{
+			show:true,
+			padding:5,
+			lineHeight:11,
+			margin:8,
+		},
+		enableMarkLine: true,
+		enableScroll: true,
+		dataLabel: false,
+		dataPointShape: true,
+		xAxis: {
+			disableGrid:true,
+			labelCount:4,
+			itemCount:5,
+			scrollShow:true,
+			scrollAlign:'right',
+		},
+		yAxis: {
+			gridType:'dash',
+			splitNumber:5,
+			format:(val)=>{return val.toFixed(0)}
+		},
+		extra: {
+			candle:{
+				color:{
+					upLine:'#f04864',
+					upFill:'#f04864',
+					downLine:'#2fc25b',
+					downFill:'#2fc25b'
+				},
+				average:{
+					show:true,
+					name:['MA5','MA10','MA30'],
+					day:[5,10,20],
+					color:['#1890ff', '#2fc25b', '#facc14']
+				}
+			},
+			tooltip:{
+				bgColor:'#000000',
+				bgOpacity:0.7,
+				gridType:'dash',
+				dashLength:5,
+				gridColor:'#1890ff',
+				fontColor:'#FFFFFF',
+				horizentalLine:true,
+				xAxisLabel:true,
+				yAxisLabel:true,
+				labelBgColor:'#DFE8FF',
+				labelBgOpacity:0.95,
+				labelAlign:'left',
+				labelFontColor:'#666666'
+			},
+		  markLine: {
+		    type: 'dash',
+		    dashLength: 5,
+		    data: [{
+		      value:2150,
+		      lineColor: '#f04864',
+		      showLabel:true
+		    },{
+		      value:2350,
+		      lineColor: '#f04864',
+		      showLabel:true
+		    }]
+		  }
+		}
+	},
+	"mix":{
+		type: 'mix',
+		padding:[15,15,0,15],
+		legend:{
+			show:true,
+		  position:'bottom',
+		  float:'center',
+			padding:5,
+			lineHeight:11,
+			margin:6,
+		},
+		dataLabel: true,
+		dataPointShape: true,
+		xAxis: {
+			disableGrid:true,
+		},
+		yAxis: {
+		  data:[{
+		    calibration:true,
+		    position:'left',
+		    title:'折线',
+		    titleFontSize:12,
+		    format:(val)=>{return val.toFixed(0)+'度'}
+		  },{
+		    calibration:true,
+		    position:'right',
+		    min:0,
+		    max:200,
+		    title:'柱状图',
+		    titleFontSize:12,
+		    format:(val)=>{return val.toFixed(0)+'元'}
+		  },{
+		    calibration:true,
+		    position:'right',
+		    min:0,
+		    max:200,
+		    title:'点',
+		    titleFontSize:12
+		  }],
+		  showTitle:true,
+			gridType:'dash',
+			dashLength:4,
+			splitNumber:5
+		},
+		extra: {
+		  column:{
+		    width:20
+		  }
+		}
+	},
+	"point":{
+		type: 'point',
+		padding:[15,30,0,15],
+		legend:{
+			show:true
+		},
+		dataLabel: false,
+		dataPointShape:true,
+		xAxis: {
+			disableGrid: true,
+			labelCount: 4
+		},
+		yAxis: {
+			gridType: 'dash',
+			gridColor: '#CCCCCC',
+			dashLength: 8,
+			splitNumber: 4,
+			format: val => {
+				return val.toFixed(1);
+			}
+		},
+		extra: {
+			point:{
+			}
+		}
+	},
+	"bubble":{
+		type: 'bubble',
+		padding:[15,30,0,15],
+		legend:{
+			show:true
+		},
+		dataLabel: true,
+		xAxis: {
+			disableGrid: true,
+			labelCount: 4
+		},
+		yAxis: {
+			gridType: 'dash',
+			gridColor: '#CCCCCC',
+			dashLength: 8,
+			splitNumber: 4,
+			format: val => {
+				return val.toFixed(1);
+			}
+		},
+		extra: {
+			bubble:{
+			}
+		}
+	}
+}

+ 267 - 0
components/js_sdk/u-charts/u-charts/demodata.json

@@ -0,0 +1,267 @@
+{
+	"Column": {
+		"categories": ["2016", "2017", "2018", "2019", "2020", "2021"],
+		"series": [{
+			"name": "目标值",
+			"data": [35, 36, 31, 33, 13, 34]
+		}, {
+			"name": "完成量",
+			"data": [18, 27, 21, 24, 6, 28]
+		}]
+	},
+	"ColumnA": {
+		"categories": ["2016", "2017", "2018", "2019", "2020", "2021"],
+		"series": [{
+			"name": "成交量1",
+			"data": [15, {
+				"value": 20,
+				"color": "#f04864"
+			}, 45, 37, 43, 34]
+		}, {
+			"name": "成交量2",
+			"data": [30, {
+				"value": 40,
+				"color": "#facc14"
+			}, 25, 14, 34, 18]
+		}]
+	},
+	"Mix": {
+		"categories": ["2016", "2017", "2018", "2019", "2020", "2021"],
+		"series": [{
+			"name": "曲面",
+			"data": [70, 50, 85, 130, 64, 88],
+			"type": "area",
+			"style": "curve"
+		}, {
+			"name": "柱1",
+			"data": [40, 30, 55, 110, 24, 58],
+			"type": "column"
+		}, {
+			"name": "柱2",
+			"data": [50, 20, 75, 60, 34, 38],
+			"type": "column"
+		}, {
+			"name": "曲线",
+			"data": [70, 50, 85, 130, 64, 88],
+			"type": "line",
+			"style": "curve",
+			"color": "#1890ff",
+			"disableLegend": true
+		}, {
+			"name": "折线",
+			"data": [120, 140, 105, 170, 95, 160],
+			"type": "line",
+			"color": "#2fc25b"
+		}, {
+			"name": "点",
+			"data": [100, 80, 125, 150, 112, 132],
+			"type": "point",
+			"color": "#f04864"
+		}]
+	},
+	"Line": {
+		"categories": ["2016", "2017", "2018", "2019", "2020", "2021"],
+		"series": [{
+			"name": "成交量A",
+			"data": [35, 8, 25, 37, 4, 20]
+		}, {
+			"name": "成交量B",
+			"data": [70, 40, 65, 100, 44, 68]
+		}, {
+			"name": "成交量C",
+			"data": [100, 80, 95, 150, 112, 132]
+		}]
+	},
+	"Pie": {
+		"series": [{
+			"name": "一班",
+			"data": 50
+		}, {
+			"name": "二班",
+			"data": 30
+		}, {
+			"name": "三班",
+			"data": 20
+		}, {
+			"name": "四班",
+			"data": 18
+		}, {
+			"name": "五班",
+			"data": 8
+		}]
+	},
+	"Radar": {
+		"categories": ["维度1", "维度2", "维度3", "维度4", "维度5", "维度6"],
+		"series": [{
+			"name": "成交量1",
+			"data": [90, 110, 165, 195, 187, 172]
+		}, {
+			"name": "成交量2",
+			"data": [190, 210, 105, 35, 27, 102]
+		}]
+	},
+	"Arcbar": {
+		"series": [{
+			"name": "正确率",
+			"data": 0.29,
+			"color": "#2fc25b"
+		}]
+	},
+	"Gauge": {
+		"categories": [{
+			"value": 0.2,
+			"color": "#1890ff"
+		}, {
+			"value": 0.8,
+			"color": "#2fc25b"
+		}, {
+			"value": 1,
+			"color": "#f04864"
+		}],
+		"series": [{
+			"name": "完成率",
+			"data": 0.66
+		}]
+	},
+	"Candle": {
+		"categories": [
+			"2020/1/24", "2020/1/25", "2020/1/28", "2020/1/29", "2020/1/30",
+			"2020/1/31", "2020/2/1", "2020/2/4", "2020/2/5", "2020/2/6",
+			"2020/2/7", "2020/2/8", "2020/2/18", "2020/2/19", "2020/2/20",
+			"2020/2/21", "2020/2/22", "2020/2/25", "2020/2/26", "2020/2/27",
+			"2020/2/28", "2020/3/1", "2020/3/4", "2020/3/5", "2020/3/6",
+			"2020/3/7", "2020/3/8", "2020/3/11", "2020/3/12", "2020/3/13",
+			"2020/3/14", "2020/3/15", "2020/3/18", "2020/3/19", "2020/3/20",
+			"2020/3/21", "2020/3/22", "2020/3/25", "2020/3/26", "2020/3/27",
+			"2020/3/28", "2020/3/29", "2020/4/1", "2020/4/2", "2020/4/3",
+			"2020/4/8", "2020/4/9", "2020/4/10", "2020/4/11", "2020/4/12",
+			"2020/4/15", "2020/4/16", "2020/4/17", "2020/4/18", "2020/4/19",
+			"2020/4/22", "2020/4/23", "2020/4/24", "2020/4/25", "2020/4/26",
+			"2020/5/2", "2020/5/3", "2020/5/6", "2020/5/7", "2020/5/8",
+			"2020/5/9", "2020/5/10", "2020/5/13", "2020/5/14", "2020/5/15",
+			"2020/5/16", "2020/5/17", "2020/5/20", "2020/5/21", "2020/5/22",
+			"2020/5/23", "2020/5/24", "2020/5/27", "2020/5/28", "2020/5/29",
+			"2020/5/30", "2020/5/31", "2020/6/3", "2020/6/4", "2020/6/5",
+			"2020/6/6", "2020/6/7", "2020/6/13"
+		],
+		"series": [{
+			"name": "上证指数",
+			"data": [
+				[2320.26, 2302.6, 2287.3, 2362.94],
+				[2300, 2291.3, 2288.26, 2308.38],
+				[2295.35, 2346.5, 2295.35, 2346.92],
+				[2347.22, 2358.98, 2337.35, 2363.8],
+				[2360.75, 2382.48, 2347.89, 2383.76],
+				[2383.43, 2385.42, 2371.23, 2391.82],
+				[2377.41, 2419.02, 2369.57, 2421.15],
+				[2425.92, 2428.15, 2417.58, 2440.38],
+				[2411, 2433.13, 2403.3, 2437.42],
+				[2432.68, 2434.48, 2427.7, 2441.73],
+				[2430.69, 2418.53, 2394.22, 2433.89],
+				[2416.62, 2432.4, 2414.4, 2443.03],
+				[2441.91, 2421.56, 2415.43, 2444.8],
+				[2420.26, 2382.91, 2373.53, 2427.07],
+				[2383.49, 2397.18, 2370.61, 2397.94],
+				[2378.82, 2325.95, 2309.17, 2378.82],
+				[2322.94, 2314.16, 2308.76, 2330.88],
+				[2320.62, 2325.82, 2315.01, 2338.78],
+				[2313.74, 2293.34, 2289.89, 2340.71],
+				[2297.77, 2313.22, 2292.03, 2324.63],
+				[2322.32, 2365.59, 2308.92, 2366.16],
+				[2364.54, 2359.51, 2330.86, 2369.65],
+				[2332.08, 2273.4, 2259.25, 2333.54],
+				[2274.81, 2326.31, 2270.1, 2328.14],
+				[2333.61, 2347.18, 2321.6, 2351.44],
+				[2340.44, 2324.29, 2304.27, 2352.02],
+				[2326.42, 2318.61, 2314.59, 2333.67],
+				[2314.68, 2310.59, 2296.58, 2320.96],
+				[2309.16, 2286.6, 2264.83, 2333.29],
+				[2282.17, 2263.97, 2253.25, 2286.33],
+				[2255.77, 2270.28, 2253.31, 2276.22],
+				[2269.31, 2278.4, 2250, 2312.08],
+				[2267.29, 2240.02, 2239.21, 2276.05],
+				[2244.26, 2257.43, 2232.02, 2261.31],
+				[2257.74, 2317.37, 2257.42, 2317.86],
+				[2318.21, 2324.24, 2311.6, 2330.81],
+				[2321.4, 2328.28, 2314.97, 2332],
+				[2334.74, 2326.72, 2319.91, 2344.89],
+				[2318.58, 2297.67, 2281.12, 2319.99],
+				[2299.38, 2301.26, 2289, 2323.48],
+				[2273.55, 2236.3, 2232.91, 2273.55],
+				[2238.49, 2236.62, 2228.81, 2246.87],
+				[2229.46, 2234.4, 2227.31, 2243.95],
+				[2234.9, 2227.74, 2220.44, 2253.42],
+				[2232.69, 2225.29, 2217.25, 2241.34],
+				[2196.24, 2211.59, 2180.67, 2212.59],
+				[2215.47, 2225.77, 2215.47, 2234.73],
+				[2224.93, 2226.13, 2212.56, 2233.04],
+				[2236.98, 2219.55, 2217.26, 2242.48],
+				[2218.09, 2206.78, 2204.44, 2226.26],
+				[2199.91, 2181.94, 2177.39, 2204.99],
+				[2169.63, 2194.85, 2165.78, 2196.43],
+				[2195.03, 2193.8, 2178.47, 2197.51],
+				[2181.82, 2197.6, 2175.44, 2206.03],
+				[2201.12, 2244.64, 2200.58, 2250.11],
+				[2236.4, 2242.17, 2232.26, 2245.12],
+				[2242.62, 2184.54, 2182.81, 2242.62],
+				[2187.35, 2218.32, 2184.11, 2226.12],
+				[2213.19, 2199.31, 2191.85, 2224.63],
+				[2203.89, 2177.91, 2173.86, 2210.58],
+				[2170.78, 2174.12, 2161.14, 2179.65],
+				[2179.05, 2205.5, 2179.05, 2222.81],
+				[2212.5, 2231.17, 2212.5, 2236.07],
+				[2227.86, 2235.57, 2219.44, 2240.26],
+				[2242.39, 2246.3, 2235.42, 2255.21],
+				[2246.96, 2232.97, 2221.38, 2247.86],
+				[2228.82, 2246.83, 2225.81, 2247.67],
+				[2247.68, 2241.92, 2231.36, 2250.85],
+				[2238.9, 2217.01, 2205.87, 2239.93],
+				[2217.09, 2224.8, 2213.58, 2225.19],
+				[2221.34, 2251.81, 2210.77, 2252.87],
+				[2249.81, 2282.87, 2248.41, 2288.09],
+				[2286.33, 2299.99, 2281.9, 2309.39],
+				[2297.11, 2305.11, 2290.12, 2305.3],
+				[2303.75, 2302.4, 2292.43, 2314.18],
+				[2293.81, 2275.67, 2274.1, 2304.95],
+				[2281.45, 2288.53, 2270.25, 2292.59],
+				[2286.66, 2293.08, 2283.94, 2301.7],
+				[2293.4, 2321.32, 2281.47, 2322.1],
+				[2323.54, 2324.02, 2321.17, 2334.33],
+				[2316.25, 2317.75, 2310.49, 2325.72],
+				[2320.74, 2300.59, 2299.37, 2325.53],
+				[2300.21, 2299.25, 2294.11, 2313.43],
+				[2297.1, 2272.42, 2264.76, 2297.1],
+				[2270.71, 2270.93, 2260.87, 2276.86],
+				[2264.43, 2242.11, 2240.07, 2266.69],
+				[2242.26, 2210.9, 2205.07, 2250.63],
+				[2190.1, 2148.35, 2126.22, 2190.1]
+			]
+		}]
+	},
+	"CandleColumn": {
+		"categories": [
+			"2020/1/24", "2020/1/25", "2020/1/28", "2020/1/29", "2020/1/30",
+			"2020/1/31", "2020/2/1", "2020/2/4", "2020/2/5", "2020/2/6",
+			"2020/2/7", "2020/2/8", "2020/2/18", "2020/2/19", "2020/2/20",
+			"2020/2/21", "2020/2/22", "2020/2/25", "2020/2/26", "2020/2/27",
+			"2020/2/28", "2020/3/1", "2020/3/4", "2020/3/5", "2020/3/6",
+			"2020/3/7", "2020/3/8", "2020/3/11", "2020/3/12", "2020/3/13",
+			"2020/3/14", "2020/3/15", "2020/3/18", "2020/3/19", "2020/3/20",
+			"2020/3/21", "2020/3/22", "2020/3/25", "2020/3/26", "2020/3/27",
+			"2020/3/28", "2020/3/29", "2020/4/1", "2020/4/2", "2020/4/3",
+			"2020/4/8", "2020/4/9", "2020/4/10", "2020/4/11", "2020/4/12",
+			"2020/4/15", "2020/4/16", "2020/4/17", "2020/4/18", "2020/4/19",
+			"2020/4/22", "2020/4/23", "2020/4/24", "2020/4/25", "2020/4/26",
+			"2020/5/2", "2020/5/3", "2020/5/6", "2020/5/7", "2020/5/8",
+			"2020/5/9", "2020/5/10", "2020/5/13", "2020/5/14", "2020/5/15",
+			"2020/5/16", "2020/5/17", "2020/5/20", "2020/5/21", "2020/5/22",
+			"2020/5/23", "2020/5/24", "2020/5/27", "2020/5/28", "2020/5/29",
+			"2020/5/30", "2020/5/31", "2020/6/3", "2020/6/4", "2020/6/5",
+			"2020/6/6", "2020/6/7", "2020/6/13"
+		],
+		"series": [{
+			"name": "成交量1",
+			"data": [15, 20, 45, 37, 43, 15, 20, 45, 37, 43, 15, 20, 45, 37, 43, 15, 20, 45, 37, 43, 15, 20, 45, 37, 43, 15, 20, 45, 37, 43, 15, 20, 45, 37, 43, 15, 20, 45, 37, 43, 15, 20, 45, 37, 43, 15, 20, 45, 37, 43, 15, 20, 45, 37, 43, 15, 20, 45, 37, 43, 15, 20, 45, 37, 43, 15, 20, 45, 37, 43, 15, 20, 45, 37, 43, 15, 20, 45, 37, 43, 15, 20, 45, 37, 43, 15, 20, 45]
+		}]
+	}
+}

Разница между файлами не показана из-за своего большого размера
+ 41 - 0
components/js_sdk/u-charts/u-charts/mapdata.json


+ 6 - 0
components/js_sdk/u-charts/u-charts/readme.md

@@ -0,0 +1,6 @@
+# uCharts JSSDK说明
+1、如不使用uCharts组件,可直接引用u-charts.js,打包编译后会`自动压缩`,压缩后体积约为`90kb`。
+2、如果90kb的体积仍需压缩,请手动删除u-charts.js内您不需要的图表类型,如k线图candle。
+3、config.js为uCharts组件的用户配置文件,升级前请`自行备份config.js`文件,以免被强制覆盖。
+4、demodata.json为标准数据格式,仅供演示使用。
+5、mapdata.json为地图数据格式,遵循geoJson地图数据交换格式参考:http://datav.aliyun.com/tools/atlas/

Разница между файлами не показана из-за своего большого размера
+ 5687 - 0
components/js_sdk/u-charts/u-charts/u-charts - 副本.js


Разница между файлами не показана из-за своего большого размера
+ 7706 - 0
components/js_sdk/u-charts/u-charts/u-charts.js


+ 443 - 0
components/js_sdk/u-charts/u-charts/u-charts.vue

@@ -0,0 +1,443 @@
+<template>
+	<view class="chartsview" :style="{ background: background }">
+		<view v-show="mixinDatacomLoading"><view class="uni-icons-spinner-cycle">Loading...</view></view>
+		<view v-show="mixinDatacomErrorMessage">
+			<view class="uni-icons-info-filled">{{ mixinDatacomErrorMessage }}</view>
+		</view>
+		<canvas
+			:id="canvasId"
+			:canvas-id="canvasId"
+			:style="{ width: cWidth + 'px', height: cHeight + 'px' }"
+			:type="canvas2d?'2d':''"
+			@tap="tap"
+			@cilck="tap"
+			@touch="tap"
+			@touchstart="touchStart"
+			@touchmove="touchMove"
+			@touchend="touchEnd"
+			@mousemove="mouseMove"
+			@mousedown="mousedown"
+			@mouseup="mouseup"
+			@error="error"
+			v-show="showchart"
+		/>
+	</view>
+</template>
+
+<script>
+import qiunCharts from '../../js_sdk/u-charts/u-charts.js';
+import config from '../../js_sdk/u-charts/config.js';
+var canvases = {};
+var options = {};
+var chartdom = null;
+export default {
+	mixins: [uniCloud.mixinDatacom],
+	props: {
+		type: {
+			type: String,
+			default: null
+		},
+		canvasId: {
+			type: String,
+			default: "uchartsid"
+		},
+		canvas2d: {
+			type: Boolean,
+			default: false
+		},
+		pixelRatio: {
+			type: Number,
+			default: 1
+		},
+		background: {
+			type: String,
+			default: 'none'
+		},
+		animation:{
+			type: Boolean,
+			default: true
+		},
+		chartData: {
+			type: Object,
+			default() {
+				return {
+					categories: [],
+					series: []
+				};
+			}
+		},
+		opts: {
+			type: Object,
+			default: () => ({})
+		},
+		inScrollView:{
+			type: Boolean,
+			default: false
+		},
+		show:{
+			type: Boolean,
+			default: false
+		}
+	},
+	data() {
+		return {
+			cWidth: 375,
+			cHeight: 250,
+			showchart: false,
+			defaultOpts: {}
+		};
+	},
+	mounted() {
+		if(this.canvasId=='uchartsid'){
+			console.warn("注意:请在uCharts组件传入canvasId,以免单页多图产生图表错乱!")
+		}
+		if (this.type && config.type.includes(this.type)) {
+			this.defaultOpts = Object.assign({},config[this.type])
+			this.load()
+		} else {
+			this.mixinDatacomLoading = false
+			this.showchart = false
+			this.mixinDatacomErrorMessage = '参数错误:props参数中type类型不正确'
+		}
+		uni.onWindowResize(res => {
+			this.init()
+		})
+	},
+	watch: {
+		chartData(val, oldval) {
+			if (!this.type || !config.type.includes(this.type)) {
+				this.mixinDatacomLoading = false
+				this.showchart = false
+				this.mixinDatacomErrorMessage = '参数错误:props参数中type不正确'
+				return
+			}
+			if (typeof val === 'object') {
+				if (this.collection != '') {
+					if (config.categories.includes(this.type) && val.categories.length == 0 ) {
+						this.mixinDatacomLoading = false
+						this.showchart = false
+						this.mixinDatacomErrorMessage = '数据错误:chartData中缺少categories'
+					} else {
+						this.mixinDatacomLoading = false
+						this.mixinDatacomErrorMessage = null
+						this.$nextTick(function() {
+							this.init()
+						})
+					}
+				} else {
+					this.mixinDatacomLoading = false
+					this.mixinDatacomErrorMessage = null
+					this.$nextTick(function() {
+						this.init()
+					});
+				}
+			} else {
+				this.mixinDatacomLoading = false
+				this.showchart = false
+				this.mixinDatacomErrorMessage = '参数错误:chartData数据类型错误'
+			}
+		},
+		show(val, oldval) {
+			if (val) {
+				if (this.collection != '') {
+					if (config.categories.includes(this.type) && this.chartData.categories.length == 0 ) {
+						this.mixinDatacomLoading = false
+						this.showchart = false
+						this.mixinDatacomErrorMessage = '数据错误:chartData中缺少categories'
+					} else {
+						this.mixinDatacomLoading = false
+						this.mixinDatacomErrorMessage = null
+						this.$nextTick(function() {
+							this.init()
+						})
+					}
+				} else {
+					this.mixinDatacomLoading = false
+					this.mixinDatacomErrorMessage = null
+					this.$nextTick(function() {
+						this.init()
+					});
+				}
+			}
+		}
+	},
+	methods: {
+		load() {
+			if (this.mixinDatacomLoading == true) {
+				return
+			}
+			this.mixinDatacomLoading = true
+			if (this.collection != '') {
+				this.mixinDatacomGet()
+					.then(res => {
+						this.mixinDatacomLoading = false
+						const { data, count } = res.result
+						this.mixinDatacomResData = data
+						if (config.categories.includes(this.type) && this.chartData.categories.length == 0) {
+							this.mixinDatacomLoading = false
+							this.showchart = false
+							this.mixinDatacomErrorMessage = '数据错误:chartData中缺少categories'
+						} else {
+							this.init()
+						}
+					})
+					.catch(err => {
+						if (this.collection == '') {
+							if (this.chartData.series.length > 0) {
+								this.mixinDatacomLoading = false
+								this.init()
+							}
+						} else {
+							this.mixinDatacomLoading = false
+							this.showchart = false
+							this.mixinDatacomErrorMessage = '请求错误:' + err
+						}
+					});
+			}else{
+				if (this.chartData.series.length > 0) {
+					this.mixinDatacomLoading = false
+					this.init()
+				}
+			}
+		},
+		onMixinDatacomPropsChange(needReset, changed) {
+			if (needReset) {
+				if(options[this.canvasId] !== undefined){
+					options[this.canvasId].context.clearRect(0, 0, options[this.canvasId].width, options[this.canvasId].height)
+					options[this.canvasId].context.draw()
+				}
+				this.showchart = false;
+				this.load()
+			}
+		},
+		cloudDataInit() {
+			let temp = {}
+			let series=[]
+			let resdata = this.mixinDatacomResData
+			let categories = options[this.canvasId].categories
+			resdata.map(function (item, index) {
+				if(item.type!=undefined && !temp[item.type]){
+					series.push({name:item.type,data:[]})
+					temp[item.type] = true;
+				}
+			})
+			if(series.length==0){
+				let seriesname="默认分组"
+				if(this.chartData.series.length>0){
+					seriesname=this.chartData.series[0].name
+				}
+				series=[{name:seriesname,data:[]}]
+				for (let j = 0; j < categories.length; j++) {
+					let seriesdata = 0;
+					for (let i = 0; i < resdata.length; i++) {
+						if(resdata[i].label == categories[j]){
+							seriesdata = resdata[i].value
+						}
+					}
+					series[0].data.push(seriesdata)
+				}
+			}else{
+				for (let k = 0; k < series.length; k++) {
+					if(categories.length>0){
+						for (let j = 0; j < categories.length; j++) {
+							let seriesdata = 0;
+							for (let i = 0; i < resdata.length; i++) {
+								if(series[k].name == resdata[i].type && resdata[i].label == categories[j]){
+									seriesdata = resdata[i].value
+								}
+							}
+							series[k].data.push(seriesdata)
+						}
+					}else{
+						for (let i = 0; i < resdata.length; i++) {
+							if(series[k].name == resdata[i].type){
+								series[k].data.push(resdata[i].type)
+							}
+						}
+					}
+				}
+			}
+			return series;
+		},
+		init() {
+			chartdom = uni.createSelectorQuery().in(this).select('.chartsview');
+			chartdom.boundingClientRect(data => {
+				if(data.width>0 && data.height>0){
+					this.cWidth = data.width
+					this.cHeight = data.height
+					options[this.canvasId] = Object.assign(this.defaultOpts, this.opts)
+					options[this.canvasId].canvasId = this.canvasId
+					options[this.canvasId].categories = this.chartData.categories
+					if (this.collection == '') {
+						options[this.canvasId].series = this.chartData.series
+					}else{
+						options[this.canvasId].series = this.cloudDataInit()
+					}
+					options[this.canvasId].background = this.background == 'none' ? '#FFFFFF' : this.background
+					options[this.canvasId].pixelRatio = this.pixelRatio
+					options[this.canvasId].animation = this.animation
+					options[this.canvasId].width = data.width * this.pixelRatio
+					options[this.canvasId].height = data.height * this.pixelRatio
+					if(this.canvas2d){
+						options[this.canvasId].canvas2d = this.canvas2d
+						const query = uni.createSelectorQuery().in(this)
+						query.select('#'+this.canvasId)
+							.fields({ node: true, size: true })
+							.exec((res) => {
+								const canvas = res[0].node
+								const ctx = canvas.getContext('2d')
+								options[this.canvasId].context = ctx
+								canvas.width = data.width * this.pixelRatio
+								canvas.height = data.height * this.pixelRatio
+								canvas._width = data.width * this.pixelRatio
+								canvas._height = data.height * this.pixelRatio
+								if(!this.mixinDatacomLoading){
+									this.showchart = true
+								}
+								this.newChart()
+							})
+					}else{
+						options[this.canvasId].context = uni.createCanvasContext(this.canvasId,this)
+						if(!this.mixinDatacomLoading){
+							this.showchart = true
+						}
+						this.newChart()
+					}
+				}else{
+					this.mixinDatacomLoading = false
+					this.showchart = false
+					this.mixinDatacomErrorMessage = '布局错误:请尝试props绑定show状态'
+				}
+			}).exec();
+		},
+		newChart() {
+			canvases[this.canvasId] = new qiunCharts(options[this.canvasId])
+			canvases[this.canvasId].addEventListener('renderComplete', () => {
+				this.$emit("complete",{complete:true,charts:canvases[this.canvasId]})
+			});
+			canvases[this.canvasId].addEventListener('scrollLeft', () => {
+				this.$emit("scrollLeft",{scrollLeft:true,charts:canvases[this.canvasId]})
+			});
+			canvases[this.canvasId].addEventListener('scrollRight', () => {
+				this.$emit("scrollRight",{scrollRight:true,charts:canvases[this.canvasId]})
+			});
+		},
+		tap(e) {
+			let currentIndex=null
+			let legendIndex=null
+			if(this.inScrollView){
+				e.type = 'click'
+			}
+			if (e.type == 'click') {
+				chartdom = uni.createSelectorQuery().in(this).select('.chartsview')
+				chartdom.boundingClientRect(data => {
+					e.changedTouches.unshift({ x: e.detail.x - data.left, y: e.detail.y - data.top })
+					e.mp.changedTouches.unshift({ x: e.detail.x - data.left, y: e.detail.y - data.top })
+					canvases[this.canvasId].touchLegend(e)
+					canvases[this.canvasId].showToolTip(e, {
+						format: function(item, category) {
+							if(category){
+								return category + ' ' + item.name + ':' + item.data
+							}else{
+								return item.name + ':' + item.data
+							}
+						}
+					})
+					currentIndex=canvases[this.canvasId].getCurrentDataIndex(e)
+					legendIndex=canvases[this.canvasId].getLegendDataIndex(e) 
+					this.$emit("getIndex",{event:e,currentIndex:currentIndex,legendIndex:legendIndex,charts:canvases[this.canvasId]})
+				}).exec();
+			} else {
+				e.changedTouches.unshift({ x: e.detail.x - e.currentTarget.offsetLeft, y: e.detail.y - e.currentTarget.offsetTop })
+				e.mp.changedTouches.unshift({ x: e.detail.x - e.currentTarget.offsetLeft, y: e.detail.y - e.currentTarget.offsetTop })
+				canvases[this.canvasId].touchLegend(e)
+				canvases[this.canvasId].showToolTip(e, {
+					format: function(item, category) {
+						if(category){
+							return category + ' ' + item.name + ':' + item.data
+						}else{
+							return item.name + ':' + item.data
+						}
+					}
+				});
+				currentIndex=canvases[this.canvasId].getCurrentDataIndex(e)
+				legendIndex=canvases[this.canvasId].getLegendDataIndex(e) 
+				this.$emit("getIndex",{event:e,currentIndex:currentIndex,legendIndex:legendIndex,charts:canvases[this.canvasId]})
+			}
+		},
+		touchStart(e) {
+			canvases[this.canvasId].scrollStart(e)
+			this.$emit("touchStart",{event:e,charts:canvases[this.canvasId]})
+		},
+		touchMove(e) {
+			canvases[this.canvasId].scroll(e)
+			this.$emit("touchMove",{event:e,charts:canvases[this.canvasId]})
+		},
+		touchEnd(e) {
+			canvases[this.canvasId].scrollEnd(e)
+			this.$emit("touchEnd",{event:e,charts:canvases[this.canvasId]})
+		},
+		mousedown(e){
+			if(options[this.canvasId].enableScroll){
+				chartdom = uni.createSelectorQuery().in(this).select('.chartsview')
+				chartdom.boundingClientRect(data => {
+					e.changedTouches.unshift({ x: e.pageX - data.left, y: e.clientY-data.top })
+					e.mp.changedTouches.unshift({ x: e.pageX - data.left, y: e.clientY-data.top })
+					canvases[this.canvasId].scrollStart(e)
+					options[this.canvasId].mousedown=true;
+					this.$emit("touchStart",{event:e,charts:canvases[this.canvasId]})
+				}).exec();
+			}
+		},
+		mouseMove(e) {
+			if (options[this.canvasId].series.length > 0) {
+				chartdom = uni.createSelectorQuery().in(this).select('.chartsview')
+				chartdom.boundingClientRect(data => {
+					e.changedTouches.unshift({ x: e.pageX - data.left, y: e.clientY-data.top })
+					e.mp.changedTouches.unshift({ x: e.pageX - data.left, y: e.clientY-data.top })
+					if(options[this.canvasId].enableScroll && options[this.canvasId].mousedown){
+						canvases[this.canvasId].scroll(e)
+						this.$emit("touchMove",{event:e,charts:canvases[this.canvasId]})
+					}else{
+						canvases[this.canvasId].showToolTip(e, {
+							format: function(item, category) {
+								if(category){
+									return category + ' ' + item.name + ':' + item.data
+								}else{
+									return item.name + ':' + item.data
+								}
+							}
+						});
+					}
+				}).exec()
+			}
+		},
+		mouseup(e){
+			if(options[this.canvasId].enableScroll){
+				chartdom = uni.createSelectorQuery().in(this).select('.chartsview')
+				chartdom.boundingClientRect(data => {
+					e.changedTouches.unshift({ x: e.pageX - data.left, y: e.clientY-data.top })
+					e.mp.changedTouches.unshift({ x: e.pageX - data.left, y: e.clientY-data.top })
+					canvases[this.canvasId].scrollEnd(e)
+					options[this.canvasId].mousedown=false;
+					this.$emit("touchEnd",{event:e,charts:canvases[this.canvasId]})
+				}).exec();
+			}
+		},
+		error(e) {
+			console.log(e)
+		}
+	}
+};
+</script>
+
+<style scoped>
+.chartsview {
+	width: 100%;
+	height: 100%;
+	display: flex;
+	flex: 1;
+	justify-content: center;
+	align-items: center;
+}
+</style>

Разница между файлами не показана из-за своего большого размера
+ 4 - 0
components/jsencrypt/jsencrypt.min.js


+ 88 - 0
components/jsencrypt/jsencrypt.vue

@@ -0,0 +1,88 @@
+<template>
+	<view>
+		
+	</view>
+</template>
+
+<script>
+	import JSEncrypt from './jsencrypt.min.js';
+	export default {
+		data() {
+			return {
+				
+			}
+		},
+		methods: {
+			
+		},
+		getRealLen:function(str) {
+		    return str.replace(/[^\x00-\xff]/g, '__').length;
+			
+		},
+		setEncryptList:function(publicKey,str,max) {
+			var arr=[]
+		    
+		    var s=str,reg=/.{40}/g,ppstr=s.match(reg);
+		    ppstr.push(s.substring(ppstr.join('').length));
+			
+		    for (var nux=0;nux<ppstr.length;nux++) {
+		    	var Nax=this.getRealLen(ppstr[nux]);
+				if(Nax>116){
+					var list=this.setEncryptList(publicKey,ppstr[nux],Nax)
+					 for (var nu=0;nu<list.length;nu++) {
+						 arr.push(list[nu]);
+					 }
+				}else{
+				
+					arr.push(this.setEncrypt(publicKey,ppstr[nux]));
+				}
+		    
+		    }
+			return arr;
+		},		
+		setEncrypt:function(publicKey,data){
+				const encrypt =new JSEncrypt();
+				encrypt.setPublicKey(publicKey);
+		
+				return encrypt.encrypt(data);
+		},
+		setLongEncrypt:function(publicKey,data){
+			var s=data,reg=/.{116}/g,rs=s.match(reg);
+			rs.push(s.substring(rs.join('').length));
+			var arr=[];
+			for (var n=0;n<rs.length;n++) {
+				var max=this.getRealLen(rs[n]);
+				
+				if(max>116){
+				
+					var list=this.setEncryptList(publicKey,rs[n],max)
+					 for (var nu=0;nu<list.length;nu++) {
+						 arr.push(list[nu]);
+					 }
+				}else{
+					
+					arr.push(this.setEncrypt(publicKey,rs[n]));
+				}
+				
+			}
+			return arr;
+		},
+		setDecryptArray:function(PrivateKey,ArrayData){
+			var Decrypt="";
+			for (var n=0;n<ArrayData.length;n++) {
+				Decrypt=Decrypt+this.setDecrypt(PrivateKey,ArrayData[n]);	
+			}
+			return Decrypt;
+		},
+		setDecrypt:function(PrivateKey,data){
+				const encrypt =new JSEncrypt();
+				encrypt.setPrivateKey(PrivateKey);
+				
+				return encrypt.decrypt(data);
+		}
+	}
+</script>
+
+<style>
+
+</style>

+ 639 - 0
components/ksp-image-cutter/ksp-image-cutter.vue

@@ -0,0 +1,639 @@
+<template>
+<view v-show="url" class="ksp-image-cutter">
+	<canvas :style="{width: target.width + 'px', height: target.height + 'px'}" canvas-id="target"></canvas>
+	<view class="body">
+		<image v-if="url" class="image" @load="imageLoad" :style="{left: image.left + 'px', top: image.top + 'px', width: image.width + 'px', height: image.height + 'px'}" :src="url"></image>
+		<view v-if="mask.show" class="mask"></view>
+		<view @touchstart="touchStart($event, 'plank')" @touchmove="touchMove" @touchend="touchEnd" @touchcancel="touchCancel"  class="plank">
+			<view class="frame" @touchstart="touchStart($event, 'frame')" @touchstart.stop.prevent="touchHandle" :style="{left: frame.left + 'px', top: frame.top + 'px', width: frame.width + 'px', height: frame.height + 'px'}">
+				<canvas v-if="mask.show" class="canvas" :style="{width: frame.width + 'px', height: frame.height + 'px'}" canvas-id="canvas"></canvas>
+				<view class="rect"></view>
+				<view class="line-one"></view>
+				<view class="line-two"></view>
+				<view class="line-three"></view>
+				<view class="line-four"></view>
+				<view @touchstart="touchStart($event, 'left')" @touchstart.stop.prevent="touchHandle" class="frame-left"></view>
+				<view @touchstart="touchStart($event, 'right')" @touchstart.stop.prevent="touchHandle" class="frame-right"></view>
+				<view @touchstart="touchStart($event, 'top')" @touchstart.stop.prevent="touchHandle" class="frame-top"></view>
+				<view @touchstart="touchStart($event, 'bottom')" @touchstart.stop.prevent="touchHandle" class="frame-bottom"></view>
+				<view @touchstart="touchStart($event, 'left-top')" @touchstart.stop.prevent="touchHandle" class="frame-left-top"></view>
+				<view @touchstart="touchStart($event, 'left-bottom')" @touchstart.stop.prevent="touchHandle" class="frame-left-bottom"></view>
+				<view @touchstart="touchStart($event, 'right-top')" @touchstart.stop.prevent="touchHandle" class="frame-right-top"></view>
+				<view @touchstart="touchStart($event, 'right-bottom')" @touchstart.stop.prevent="touchHandle" class="frame-right-bottom"></view>
+			</view>
+		</view>
+	</view>
+	<view class="toolbar">
+		<button @tap="oncancle" class="btn-cancel">返回</button>
+		<button @tap="onok" class="btn-ok">确定</button>
+	</view>
+</view>
+</template>
+
+<script>
+export default {
+	props: {
+		url: {
+			type: String,
+			default: ""
+		},
+		fixed: {
+			type: Boolean,
+			default: false
+		},
+		width: {
+			type: Number,
+			default: 200
+		},
+		height: {
+			type: Number,
+			default: 200
+		},
+		maxWidth: {
+			type: Number,
+			default: 1024
+		},
+		maxHeight: {
+			type: Number,
+			default: 1024
+		},
+		blob: {
+			type: Boolean,
+			default: true
+		}
+	},
+	data() {
+		return {
+			mask: {
+				show: false
+			},
+			frame: {
+				left: 50,
+				top: 50,
+				width: this.width,
+				height: this.height
+			},
+			image: {
+				left: 20,
+				top: 20,
+				width: 300,
+				height: 400
+			},
+			real: {
+				width: 100,
+				height: 100
+			},
+			target: {
+				width: this.width,
+				height: this.height
+			},
+			touches: [],
+			type: "",
+			start: {
+				frame: {
+					left: 0,
+					top: 0,
+					width: 0,
+					height: 0
+				},
+				image: {
+					left: 0,
+					top: 0,
+					width: 0,
+					height: 0
+				},
+			},
+			timeoutId: -1,
+			context: null
+		};
+	},
+	mounted() {
+		//#ifdef H5
+		this.$el.addEventListener("touchmove", (ev) => {
+			ev.preventDefault();
+		});
+		// #endif
+		this.context = uni.createCanvasContext("canvas", this);
+		this.targetContext = uni.createCanvasContext("target", this);
+	},
+	methods: {
+		imageLoad(ev) {
+			this.mask.show = true;
+			this.real.width = ev.detail.width;
+			this.real.height = ev.detail.height;
+			this.image.width = ev.detail.width;
+			this.image.height = ev.detail.height;
+			this.frame.width = this.width;
+			this.frame.height = this.height;
+			if (!this.fixed) {
+				this.frame.width = this.image.width;
+				this.frame.height = this.image.height;
+			}
+			var query = uni.createSelectorQuery().in(this);
+			query.select(".body").boundingClientRect((data) => {
+				var bw = data.width;
+				var bh = data.height;
+				var fw = this.frame.width;
+				var fh = this.frame.height;
+				var tw = bw * 0.8;
+				var th = bh * 0.8;
+				var sx = tw / fw;
+				var sy = th / fh;
+				var scale = sx;
+				if (sx < sy) {
+					scale = sy;
+				}
+				tw = fw * scale;
+				th = fh * scale;
+				var tx = (bw - tw) / 2;
+				var ty = (bh - th) / 2;
+				this.frame.width = tw;
+				this.frame.height = th;
+				this.frame.left = tx;
+				this.frame.top = ty;
+				
+				var iw = this.image.width;
+				var ih = this.image.height;
+				sx = tw / iw;
+				sy = th / ih;
+				scale = sx;
+				if (sx < sy) {
+					scale = sy;
+				}
+				this.image.width = iw * scale;
+				this.image.height = ih * scale;
+				this.image.left = (bw - this.image.width) / 2;
+				this.image.top = (bh - this.image.height) / 2;
+				setTimeout(() => {
+					this.trimImage();
+				}, 100);
+			}).exec();
+		},
+		touchHandle() {},
+		touchStart(ev, type) {
+			this.stopTime();
+			this.mask.show = false;
+			if (this.touches.length == 0) {
+				this.type = type;
+				this.start.frame.left = this.frame.left;
+				this.start.frame.top = this.frame.top;
+				this.start.frame.width = this.frame.width;
+				this.start.frame.height = this.frame.height;
+				this.start.image.left = this.image.left;
+				this.start.image.top = this.image.top;
+				this.start.image.width = this.image.width;
+				this.start.image.height = this.image.height;
+			}
+			var touches = ev.changedTouches;
+			for(var i = 0; i < touches.length; i++) {
+				var touch = touches[i];
+				// this.touches[touch.identifier] = touch;
+				this.touches.push(touch);
+			}
+		},
+		touchMove(ev) {
+			this.stopTime();
+			ev.preventDefault();
+			var touches = ev.touches;
+			if (this.touches.length == 1) {
+				if (this.type == "plank" || this.type == "frame" || this.fixed) {
+					this.moveImage(this.touches[0], touches[0]);
+				} else {
+					this.scaleFrame(this.touches[0], touches[0], this.type);
+				}
+			} else if (this.touches.length == 2 && touches.length == 2) {
+				var ta = this.touches[0];
+				var tb = this.touches[1];
+				var tc = touches[0];
+				var td = touches[1];
+				if (ta.identifier != tc.identifier) {
+					var temp = tc;
+					tc = td;
+					td = temp;
+				}
+				this.scaleImage(ta, tb, tc, td);
+			}
+		},
+		touchEnd(ev) {
+			this.type = "";
+			this.touches = [];
+			this.startTime();
+		},
+		touchCancel(ev) {
+			this.type = "";
+			this.touches = [];
+			this.startTime();
+		},
+		startTime() {
+			this.stopTime();
+			this.timeoutId = setTimeout(() => {
+				this.trimImage();
+			}, 800);
+		},
+		stopTime() {
+			if (this.timeoutId >= 0) {
+				clearTimeout(this.timeoutId);
+				this.timeoutId = -1;
+			}
+		},
+		trimImage() {
+			this.mask.show = true;
+			var query = uni.createSelectorQuery().in(this);
+			query.select(".body").boundingClientRect((data) => {
+				var bw = data.width;
+				var bh = data.height;
+				var fw = this.frame.width;
+				var fh = this.frame.height;
+				var tw = bw * 0.8;
+				var th = bh * 0.8;
+				var sx = tw / fw;
+				var sy = th / fh;
+				var scale = sx;
+				if (sx > sy) {
+					scale = sy;
+				}
+				tw = fw * scale;
+				th = fh * scale;
+				var tx = (bw - tw) / 2;
+				var ty = (bh - th) / 2;
+				var ax = tx - this.frame.left + (this.frame.left - this.image.left) * (1 - scale);
+				var ay = ty - this.frame.top + (this.frame.top - this.image.top) * (1 - scale);
+				this.frame.width = tw;
+				this.frame.height = th;
+				this.frame.left = tx;
+				this.frame.top = ty;
+				this.image.width *= scale;
+				this.image.height *= scale;
+				this.image.left += ax;
+				this.image.top += ay;
+			}).exec();
+			setTimeout(() => {
+				var scale = this.image.width / this.real.width;
+				var x = (this.frame.left - this.image.left) / scale;
+				var y = (this.frame.top - this.image.top) / scale;
+				var width = this.frame.width / scale;
+				var height = this.frame.height / scale;
+				this.context.drawImage(this.url, x, y, width, height, 0, 0, this.frame.width, this.frame.height);
+				this.context.draw(false);
+			}, 100);
+		},
+		moveImage(ta, tb) {
+			var ax = tb.clientX - ta.clientX;
+			var ay = tb.clientY - ta.clientY;
+			this.image.left = this.start.image.left + ax;
+			this.image.top = this.start.image.top + ay;
+			if (this.image.left > this.frame.left) {
+				this.image.left = this.frame.left;
+			}
+			if (this.image.top > this.frame.top) {
+				this.image.top = this.frame.top;
+			}
+			if (this.image.left + this.image.width < this.frame.left + this.frame.width) {
+				this.image.left = this.frame.left + this.frame.width - this.image.width; 
+			}
+			if (this.image.top + this.image.height < this.frame.top + this.frame.height) {
+				this.image.top = this.frame.top + this.frame.height - this.image.height; 
+			}
+		},
+		scaleImage(ta, tb, tc, td) {
+			var x1 = ta.clientX;
+			var y1 = ta.clientY;
+			var x2 = tb.clientX;
+			var y2 = tb.clientY;
+			var x3 = tc.clientX;
+			var y3 = tc.clientY;
+			var x4 = td.clientX;
+			var y4 = td.clientY;
+			var ol = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
+			var el = Math.sqrt((x3 - x4) * (x3 - x4) + (y3 - y4) * (y3 - y4));
+			var ocx = (x1 + x2) / 2;
+			var ocy = (y1 + y2) / 2;
+			var ecx = (x3 + x4) / 2;
+			var ecy = (y3 + y4) / 2;
+			var ax = ecx - ocx;
+			var ay = ecy - ocy;
+			var scale = el / ol;
+			if (this.start.image.width * scale < this.frame.width) {
+				scale = this.frame.width / this.start.image.width;
+			}
+			if (this.start.image.height * scale < this.frame.height) {
+				scale = this.frame.height / this.start.image.height;
+			}
+			if (this.start.image.width * scale < this.frame.width) {
+				scale = this.frame.width / this.start.image.width;
+			}
+			this.image.left = this.start.image.left + ax - (ocx - this.start.image.left) * (scale - 1);
+			this.image.top = this.start.image.top + ay - (ocy - this.start.image.top) * (scale - 1);
+			this.image.width = this.start.image.width * scale;
+			this.image.height = this.start.image.height * scale;
+			if (this.image.left > this.frame.left) {
+				this.image.left = this.frame.left;
+			}
+			if (this.image.top > this.frame.top) {
+				this.image.top = this.frame.top;
+			}
+			if (this.image.left + this.image.width < this.frame.left + this.frame.width) {
+				this.image.left = this.frame.left + this.frame.width - this.image.width; 
+			}
+			if (this.image.top + this.image.height < this.frame.top + this.frame.height) {
+				this.image.top = this.frame.top + this.frame.height - this.image.height; 
+			}
+			
+		},
+		scaleFrame(ta, tb, type) {
+			var ax = tb.clientX - ta.clientX;
+			var ay = tb.clientY - ta.clientY;
+			var x1 = this.start.frame.left;
+			var y1 = this.start.frame.top;
+			var x2 = this.start.frame.left + this.start.frame.width;
+			var y2 = this.start.frame.top + this.start.frame.height;
+			if (type == "left") {
+				x1 += ax;
+			} else if (type == "right") {
+				x2 += ax;
+			} else if (type == "top") {
+				y1 += ay;
+			} else if (type == "bottom") {
+				y2 += ay;
+			} else if (type == "left-top") {
+				x1 += ax;
+				y1 += ay;
+			} else if (type == "left-bottom") {
+				x1 += ax;
+				y2 += ay;
+			} else if (type == "right-top") {
+				x2 += ax;
+				y1 += ay;
+			} else if (type == "right-bottom") {
+				x2 += ax;
+				y2 += ay;
+			}
+			if (x1 < this.image.left) {
+				x1 = this.image.left;
+			}
+			if (y1 < this.image.top) {
+				y1 = this.image.top;
+			}
+			if (x2 > this.image.left + this.image.width) {
+				x2 = this.image.left + this.image.width;
+			}
+			if (y2 > this.image.top + this.image.height) {
+				y2 = this.image.top + this.image.height;
+			}
+			this.frame.left = x1;
+			this.frame.top = y1;
+			this.frame.width = x2 - x1;
+			this.frame.height = y2 - y1;
+		},
+		parseBlob(base64) {
+			var arr = base64.split(',');
+			var mime = arr[0].match(/:(.*?);/)[1];
+			var bstr = atob(arr[1]);
+			var n = bstr.length;
+			var u8arr = new Uint8Array(n);
+			for(var i = 0; i < n; i++) {
+				u8arr[i] = bstr.charCodeAt(i);
+			}
+			var url = URL || webkitURL;
+			return url.createObjectURL(new Blob([u8arr], {type: mime}));
+		},
+		onok() {
+			var scale = this.image.width / this.real.width;
+			var x = (this.frame.left - this.image.left) / scale;
+			var y = (this.frame.top - this.image.top) / scale;
+			var width = this.frame.width / scale;
+			var height = this.frame.height / scale;
+			var tw = width;
+			var th = height;
+			if (this.fixed) {
+				tw = this.width / 2;
+				th = this.height / 2;
+			} else {
+				if (tw > this.maxWidth / 2) {
+					var sc = this.maxWidth / 2 / tw;
+					tw = tw * sc;
+					th = th * sc;
+				}
+				if (th > this.maxHeight / 2) {
+					var sc = this.maxHeight / 2 / th;
+					th = th * sc;
+					tw = tw * sc;
+				}
+			}
+			this.target.width = tw;
+			this.target.height = th;
+			uni.showLoading({
+				title: "正在裁剪"
+			});
+			setTimeout(() => {
+				this.targetContext.drawImage(this.url, x, y, width, height, 0, 0, tw, th);
+				this.targetContext.draw(false, () => {
+					uni.canvasToTempFilePath({
+						canvasId: "target",
+						success: (res) => {
+							var path = res.tempFilePath;
+							// #ifdef H5
+							if (this.blob) {
+								path = this.parseBlob(path);
+							}
+							// #endif
+							this.$emit("ok", {
+								path: path
+							});
+						},
+						fail: (ev) => {
+							console.log(ev);
+						},
+						complete: () => {
+							uni.hideLoading();
+						}
+					}, this);
+				});
+			}, 100);
+		},
+		oncancle() {
+			this.$emit("cancel");
+		}
+	}
+}
+</script>
+
+<style scoped>
+.ksp-image-cutter {
+	position: absolute;
+	width: 100%;
+	height: 100%;
+	top: 0;
+	bottom: 0;
+	z-index: 1000;
+}
+.toolbar {
+	position: absolute;
+	width: 100%;
+	height: 100upx;
+	left: 0upx;
+	bottom: 0upx;
+	box-sizing: border-box;
+	border-bottom: 1px solid #C0C0C0;
+	background: #F8F8F8;
+}
+.btn-cancel {
+	position: absolute;
+	left: 100upx;
+	top: 12upx;
+	font-size: 30upx;
+	line-height: 30upx;
+	padding: 20upx;
+	color: #333333;
+}
+.btn-ok {
+	position: absolute;
+	right: 100upx;
+	top: 12upx;
+	font-size: 30upx;
+	line-height: 30upx;
+	padding: 20upx;
+	color: #333333;
+}
+.body {
+	position: absolute;
+	left: 0upx;
+	right: 0upx;
+	top: 0upx;
+	bottom: 100upx;
+	background: black;
+	overflow: hidden;
+}
+.mask {
+	position: absolute;
+	left: 0upx;
+	right: 0upx;
+	top: 0upx;
+	bottom: 0upx;
+	background: black;
+	opacity: 0.4;
+}
+.plank {
+	position: absolute;
+	left: 0upx;
+	right: 0upx;
+	top: 0upx;
+	bottom: 0upx;
+}
+.image {
+	position: absolute;
+}
+.frame {
+	position: absolute;
+}
+.canvas {
+	position: absolute;
+	display: block;
+	left: 0px;
+	top: 0px;
+}
+.rect {
+	position: absolute;
+	left: -2px;
+	top: -2px;
+	width: 100%;
+	height: 100%;
+	border: 2px solid white;
+}
+.line-one {
+	position: absolute;
+	width: 100%;
+	height: 1px;
+	background: white;
+	left: 0;
+	top: 33.3%;
+}
+.line-two {
+	position: absolute;
+	width: 100%;
+	height: 1px;
+	background: white;
+	left: 0;
+	top: 66.7%;
+}
+.line-three {
+	position: absolute;
+	width: 1px;
+	height: 100%;
+	background: white;
+	top: 0;
+	left: 33.3%;
+}
+.line-four {
+	position: absolute;
+	width: 1px;
+	height: 100%;
+	background: white;
+	top: 0;
+	left: 66.7%;
+}
+.frame-left {
+	position: absolute;
+	height: 100%;
+	width: 8px;
+	left: -4px;
+	top: 0;
+}
+.frame-right {
+	position: absolute;
+	height: 100%;
+	width: 8px;
+	right: -4px;
+	top: 0;
+}
+.frame-top {
+	position: absolute;
+	width: 100%;
+	height: 8px;
+	top: -4px;
+	left: 0;
+}
+.frame-bottom {
+	position: absolute;
+	width: 100%;
+	height: 8px;
+	bottom: -4px;
+	left: 0;
+}
+.frame-left-top {
+	position: absolute;
+	width: 20px;
+	height: 20px;
+	left: -6px;
+	top: -6px;
+	border-left: 4px solid red;
+	border-top: 4px solid red;
+}
+.frame-left-bottom {
+	position: absolute;
+	width: 20px;
+	height: 20px;
+	left: -6px;
+	bottom: -6px;
+	border-left: 4px solid red;
+	border-bottom: 4px solid red;
+}
+.frame-right-top {
+	position: absolute;
+	width: 20px;
+	height: 20px;
+	right: -6px;
+	top: -6px;
+	border-right: 4px solid red;
+	border-top: 4px solid red;
+}
+.frame-right-bottom {
+	position: absolute;
+	width: 20px;
+	height: 20px;
+	right: -6px;
+	bottom: -6px;
+	border-right: 4px solid red;
+	border-bottom: 4px solid red;
+}
+</style>

+ 454 - 0
components/linzq-citySelect/linzq-citySelect.vue

@@ -0,0 +1,454 @@
+<template>
+	<div class="wrapper" :style="'top:'+statusBarHeight+'px'">
+		<div class="header">
+			<view class="back_div">
+				<image class="back_img" @click="back_city()" :src="$imageURL+'/bigdata_app/back_img.png'" mode=""></image>
+			</view>
+			<input class="input" @input="onInput" placeholder="中文/拼音/首字母" v-model="searchValue" />
+		</div>
+		<scroll-view class="calendar-list" scroll-y="true" :scroll-into-view="scrollIntoId">
+			<view v-if="disdingwei" id="hot">
+				<!-- 定位模块 -->
+				<view class="dingwei">
+					<view class="dingwei_Tips">
+						当前定位
+					</view>
+					<view class="dingwei_city">
+						<view class="dingwei_city_one">
+							{{position}}
+						</view>
+						<view class="dingweis_div" @click="getWarpweft">
+							<image class="dingweis" :src="$imageURL+'/bigdata_app/dingweis.png'" mode=""></image>
+							<text>{{po_tips}}</text>
+						</view>
+					</view>
+				</view>
+
+				<!-- 最近模块 -->
+				<view class="dingwei" v-if="Visit.length>=0">
+					<view class="dingwei_Tips">
+						最近访问
+					</view>
+					<view class="dingwei_city dingwei_city_zuijin">
+						<view class="dingwei_city_one toright" v-for="(item,index) in Visit" v-if="index<2" @click="back_city(item)">
+							{{item.cityName}}
+						</view> 
+					</view>
+				</view>
+
+			</view>
+
+
+			<!-- 城市列表 -->
+			<view v-if="searchValue == ''" v-for="(item, index) in list" :id="getId(index)" :key="index">
+				<view class="letter-header">{{ getId(index) }}</view>
+				<view class="city-div" v-for="(city, i) in item" :key="i" @click="back_city(city)">
+					<text class="city">{{ city.cityName }}</text>
+				</view>
+			</view>
+			<!-- 搜索结果 -->
+			<view class="city-div" v-for="(item, index) in searchList" @click="back_city(item)">
+				<text class="city">{{ item.cityName }}</text>
+			</view>
+		</scroll-view>
+
+		<!-- 右侧字母 -->
+		<view class="letters" v-if="searchValue == ''">
+			<view class="letters-item" @click="scrollTo('hot')">最近</view>
+			<view class="letters-item" v-for="item in letter" :key="item" @click="scrollTo(item)">{{ item }}</view>
+		</view>
+
+		<!-- 选中之后字母 -->
+		<view class="mask" v-if="showMask">
+			<view class="mask-r">{{selectLetter}}</view>
+		</view>
+	</div>
+</template>
+
+<script>
+	import Citys from '../city.js';
+	export default {
+		components: {},
+		props: {},
+
+		computed: {
+			hotCity() {
+				return Citys.hotCity;
+			},
+
+			citys() {
+				return Citys.cities;
+			}
+		},
+
+		data() {
+			return {
+				statusBarHeight: this.statusBarHeight,
+				ImgUrl: this.ImgUrl,
+				letter: [],
+				selectLetter: '',
+				searchValue: '',
+				scrollIntoId: '',
+				list: [],
+				tId: null,
+				searchList: [],
+				showMask: false,
+				disdingwei: true,
+				Visit: [], //最近访问
+				position: '青岛',
+				longitude: '', //经度
+				latitude: '', //纬度
+				seconds: 3,
+				po_tips: '重新定位',
+			}
+		},
+
+		created() {
+			//获取存储的最近访问
+			var that = this
+			uni.getStorage({
+				key: 'Visit_key',
+				success: function(res) {
+					that.Visit = res.data
+				}
+			});
+			//获取定位 经度纬度
+			that.getWarpweft()
+			//获取city.js 的程序字母
+			var mu = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'w', 'x', 'y',
+				'z'
+			];
+			var tmp = [];
+			for (var i = 0; i < mu.length; i++) {
+				var item = mu[i];
+				for (var j = 0; j < this.citys.length; j++) {
+					var py = this.citys[j].py;
+					if (py.substring(0, 1) == item) {
+						if (tmp.indexOf(item) == -1) {
+							this.list[i] = [this.citys[j]];
+							tmp.push(item);
+							this.letter.push(item.toUpperCase());
+						} else {
+							this.list[i].push(this.citys[j]);
+						}
+					}
+				}
+			}
+		},
+		methods: {
+			getId(index) {
+				return this.letter[index];
+			},
+
+			scrollTo(letter) {
+				this.showMask = true
+				this.selectLetter = letter == 'hot' ? '最' : letter
+				setTimeout(() => {
+					this.showMask = false
+				}, 300);
+				this.scrollIntoId = letter;
+			},
+
+
+			query(source, text) {
+				let res = [];
+				var self = this;
+				res = source.filter(item => {
+					const arr = [];
+					let isHave = false;
+					Object.keys(item).forEach(prop => {
+						const itemStr = item[prop];
+						self.isString(itemStr) &&
+							itemStr.split(',').forEach(val => {
+								arr.push(val);
+							});
+					});
+					arr.some(val => {
+						isHave = new RegExp('^' + text).test(val);
+						return isHave;
+					});
+					return isHave;
+				});
+				console.log(JSON.stringify(res));
+				return res;
+			},
+
+			isString(obj) {
+				return typeof obj === 'string';
+			},
+
+			onInput(e) {
+				const value = e.target.value;
+				console.log(value);
+				if (value !== '' && this.citys && this.citys.length > 0) {
+					const queryData = this.query(this.citys, String(value).trim());
+					this.searchList = queryData;
+					this.disdingwei = false
+				} else {
+					this.searchList = [];
+					this.disdingwei = true
+				}
+			},
+
+			back_city(item) {
+				if (item) {
+					this.$emit('back_city', item);
+					//unshift 把数据插入到首位,与push相反
+					this.Visit.unshift(item)
+					this.searchValue = "";
+					this.disdingwei = true
+					var arr = this.Visit
+					//数组去重
+					function distinct(arr) {
+						let newArr = []
+						for (let i = 0; i < arr.length; i++) {
+							if (newArr.indexOf(arr[i]) < 0) {
+								newArr.push(arr[i])
+							}
+						}
+						return newArr
+					}
+					this.Visit = distinct(arr)
+					console.log(this.Visit, "---最近访问")
+					uni.setStorage({
+						key: 'Visit_key',
+						data: this.Visit
+					});
+				} else {
+					this.$emit('back_city', 'no');
+				}
+
+			},
+			getWarpweft() {
+				var that = this
+				that.po_tips = '定位中...'
+				let countdown = setInterval(() => {
+					that.seconds--;
+					uni.getLocation({
+						type: 'wgs84',
+						success: function(res) {
+							console.log('当前位置的经度:' + res.longitude);
+							console.log('当前位置的纬度:' + res.latitude);
+							that.longitude = res.longitude
+							that.latitude = res.latitude
+						}
+					});
+					if (that.seconds <= 0) {
+						that.seconds = 3
+						that.po_tips = '重新定位'
+						clearInterval(countdown);
+					}
+				}, 1000);
+			}
+		}
+	};
+</script>
+
+<style scoped>
+	.wrapper {
+		position: fixed;
+		z-index: 999999;
+		background: #ffffff;
+		height: 100%;
+		width: 100%;
+		top: 0px;
+		left: 0px;
+	}
+
+	.mask {
+		position: absolute;
+		bottom: 0upx;
+		top: 83upx;
+		left: 0upx;
+		right: 0upx;
+		width: 750upx;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		background: rgba(0, 0, 0, 0);
+	}
+
+	.mask-r {
+		height: 120upx;
+		width: 120upx;
+		border-radius: 60upx;
+		display: flex;
+		background: rgba(0, 0, 0, 0.5);
+		justify-content: center;
+		align-items: center;
+		font-size: 40upx;
+		color: #FFFFFF
+	}
+
+	.content {
+		height: 100%;
+		width: 100%;
+		background-color: #ffffff;
+	}
+
+	.header {
+		height: 85upx;
+		display: flex;
+		justify-content: flex-start;
+		align-items: center;
+	}
+
+
+	.back_div {
+		width: 65upx;
+		height: 100%;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+	}
+
+	.back_img {
+		width: 35upx;
+		height: 35upx;
+	}
+
+	.input {
+		font-size: 28upx;
+		width: 620upx;
+		height: 55upx;
+		border-radius: 40upx;
+		background-color: #F5F5F5;
+		padding-left: 20upx;
+		padding-right: 20upx;
+		box-sizing: border-box;
+	}
+
+	.title {
+		font-size: 30upx;
+		color: white;
+	}
+
+	.show {
+		left: 0;
+		width: 100%;
+		transition: left 0.3s ease;
+	}
+
+	.hide {
+		left: 100%;
+		width: 100%;
+		transition: left 0.3s ease;
+	}
+
+
+	.title {
+		font-size: 30upx;
+		color: white;
+	}
+
+	.calendar-list {
+		position: absolute;
+		top: 83upx;
+		bottom: 0upx;
+		width: 100%;
+		background-color: #FFFFFF;
+	}
+
+	.letters {
+		position: absolute;
+		right: 30upx;
+		bottom: 0px;
+		width: 50upx;
+		top: 260upx;
+		color: #2f9bfe;
+		text-align: center;
+		font-size: 24upx;
+	}
+
+	.letters-item {
+		margin-bottom: 5upx;
+	}
+
+	.letter-header {
+		height: 45upx;
+		font-size: 22upx;
+		color: #333333;
+		padding-left: 24upx;
+		box-sizing: border-box;
+		display: flex;
+		align-items: center;
+		background-color: #ebedef;
+
+	}
+
+	.city-div {
+		width: 660upx;
+		height: 85upx;
+		margin-left: 24upx;
+		border-bottom-width: 0.5upx;
+		border-bottom-color: #ebedef;
+		border-bottom-style: solid;
+		display: flex;
+		align-items: center;
+		margin-right: 35upx;
+	}
+
+	.city {
+		font-size: 28upx;
+		color: #000000;
+		padding-left: 30upx;
+	}
+
+	.dingwei {
+		width: 100%;
+		padding-top: 25upx;
+		box-sizing: border-box;
+		margin-bottom: 26upx;
+	}
+
+	.dingwei_Tips {
+		margin-left: 24upx;
+		margin-bottom: 24upx;
+		font-size: 24upx;
+		color: #A5A5A5;
+	}
+
+	.dingwei_city {
+		width: 100%;
+		height: 60upx;
+		padding-left: 55upx;
+		padding-right: 70upx;
+		box-sizing: border-box;
+		display: flex;
+		justify-content: space-between;
+	}
+
+	.dingwei_city_one {
+		width: 185upx;
+		height: 60upx;
+		background-color: #F5F5F5;
+		border-radius: 10upx;
+		font-size: 32upx;
+		color: #333333;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+	}
+
+	.dingweis_div {
+		display: flex;
+		align-content: flex-end;
+		align-items: center;
+		font-size: 24upx;
+		color: #FD5745;
+	}
+
+	.dingweis {
+		width: 32upx;
+		height: 32upx;
+	}
+
+	.dingwei_city_zuijin {
+		display: flex;
+		justify-content: flex-start;
+	}
+
+	.toright {
+		margin-right: 25upx;
+	}
+</style>

+ 215 - 0
components/mark.vue

@@ -0,0 +1,215 @@
+<template>
+  <view class="container" ref="canvas-container">
+	  <span>组件</span>
+    <canvas 
+      canvas-id="myCanvas" 
+      id="myCanvas"
+      @touchstart="touchStart"
+      @touchmove="touchMove"
+      @touchend="touchEnd"
+      :style="{width: canvasWidth + 'px', height: canvasHeight + 'px'}"
+    ></canvas>
+  </view>
+</template>
+
+<script>
+export default {
+
+  data() {
+    return {
+      canvasWidth: 300,
+      canvasHeight: 279,
+      ctx: null,
+      bgImage: null,
+      imageLoaded: false,
+      rectX: 50,
+      rectY: 50,
+      rectWidth: 100,
+      rectHeight: 80,
+      lastDistance: 0, // 双指间距离
+      scale: 1, // 缩放比例
+      lastTouchCenter: { x: 0, y: 0 }, // 上次双指中心点
+      translateX: 0, // X轴平移
+      translateY: 0, // Y轴平移
+      isDragging: false, // 是否正在拖动
+      startDragX: 0, // 拖动开始的X坐标
+      startDragY: 0 // 拖动开始的Y坐标
+    }
+  },
+  mounted() {
+  	uni.getSystemInfo({
+  	  success: (res) => {
+		
+  	    this.canvasWidth = res.windowWidth
+  	    // this.canvasHeight = res.windowHeight * 0.5
+  	    console.log(this.canvasWidth,this.canvasHeight)
+  	    // 创建canvas上下文
+  	    this.ctx = uni.createCanvasContext('myCanvas', this)
+  	    
+  	    // 加载背景图片
+  	    this.loadImage()
+  	  }
+  	})
+  },
+  onReady() {
+	  
+    // 获取系统信息设置canvas尺寸
+    
+  },
+  methods: {
+    loadImage() {
+      // 加载网络图片示例
+      uni.getImageInfo({
+        src: 'https://bigdata-image.oss-cn-hangzhou.aliyuncs.com/Basics/cbd/666000000000001/2025/7/11/001.jpg',
+        success: (res) => {
+			console.log(res)
+          this.bgImage = res
+          this.imageLoaded = true
+          this.drawCanvas()
+        },
+        fail: (err) => {
+          console.error('图片加载失败:', err)
+        }
+      })
+      
+      // 或者使用本地临时文件
+      // uni.downloadFile({
+      //   url: 'https://example.com/background.jpg',
+      //   success: (res) => {
+      //     this.bgImage = res.tempFilePath
+      //     this.imageLoaded = true
+      //     this.drawCanvas()
+      //   }
+      // })
+    },
+    
+    drawCanvas() {
+      if (!this.imageLoaded) return
+      
+      const ctx = this.ctx
+      ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight)
+      
+      // 绘制背景图片(保持纵横比,适应canvas)
+      // const imgRatio = this.bgImage.width / this.bgImage.height
+      // const canvasRatio = this.canvasWidth / this.canvasHeight
+      // let drawWidth, drawHeight, offsetX = 0, offsetY = 0
+      
+      // if (imgRatio > canvasRatio) {
+      //   drawHeight = this.canvasHeight
+      //   drawWidth = this.bgImage.width * (drawHeight / this.bgImage.height)
+      //   offsetX = (this.canvasWidth - drawWidth) / 2
+      // } else {
+      //   drawWidth = this.canvasWidth
+      //   drawHeight = this.bgImage.height * (drawWidth / this.bgImage.width)
+      //   offsetY = (this.canvasHeight - drawHeight) / 2
+      // }
+      
+      ctx.drawImage(this.bgImage.path, 0, 0, this.bgImage.width, this.bgImage.height)
+      let scaleX = this.canvasWidth /this.bgImage.width
+	  let scaleY = this.canvasHeight /this.bgImage.height
+	  console.log(scaleX,scaleY,'----',this.translateX, this.translateY)
+      // 应用变换(缩放和平移)
+      ctx.save()
+      ctx.translate(this.translateX, this.translateY)
+      ctx.scale(2, 2)
+      
+      // 绘制矩形
+      // ctx.setStrokeStyle('#FF0000')
+      // ctx.setLineWidth(2)
+      // ctx.strokeRect(this.rectX, this.rectY, this.rectWidth, this.rectHeight)
+      
+      ctx.restore()
+      ctx.draw()
+    },
+    
+    // 处理触摸开始事件
+    touchStart(e) {
+      const touches = e.touches
+      
+      if (touches.length === 1) {
+        // 单指拖动
+        this.isDragging = true
+        this.startDragX = this.translateX
+        this.startDragY = this.translateY
+        this.rectX += e.touches[0].x - this.lastTouchCenter.x
+        this.rectY += e.touches[0].y - this.lastTouchCenter.y
+      } else if (touches.length === 2) {
+        // 双指缩放
+        this.isDragging = false
+        const dx = touches[0].x - touches[1].x
+        const dy = touches[0].y - touches[1].y
+        this.lastDistance = Math.sqrt(dx * dx + dy * dy)
+        this.lastTouchCenter = {
+          x: (touches[0].x + touches[1].x) / 2,
+          y: (touches[0].y + touches[1].y) / 2
+        }
+      }
+    },
+    
+    // 处理触摸移动事件
+    touchMove(e) {
+      const touches = e.touches
+      
+      if (this.isDragging && touches.length === 1) {
+        // 单指拖动矩形
+        this.rectX += e.touches[0].x - this.lastTouchCenter.x
+        this.rectY += e.touches[0].y - this.lastTouchCenter.y
+        this.lastTouchCenter = {
+          x: e.touches[0].x,
+          y: e.touches[0].y
+        }
+      } else if (touches.length === 2) {
+        // 双指缩放
+        const dx = touches[0].x - touches[1].x
+        const dy = touches[0].y - touches[1].y
+        const distance = Math.sqrt(dx * dx + dy * dy)
+        
+        // 计算新的缩放比例
+        let newScale = this.scale * (distance / this.lastDistance)
+        // 限制最小和最大缩放比例
+        newScale = Math.max(0.5, Math.min(3, newScale))
+        
+        // 计算缩放中心点相对于当前平移后的坐标
+        const centerX = this.lastTouchCenter.x
+        const centerY = this.lastTouchCenter.y
+        
+        // 计算相对于当前变换的本地坐标
+        // 这部分比较复杂,简化处理
+        this.rectX = centerX - (centerX - this.rectX) * (newScale / this.scale)
+        this.rectY = centerY - (centerY - this.rectY) * (newScale / this.scale)
+        this.rectWidth *= newScale / this.scale
+        this.rectHeight *= newScale / this.scale
+        
+        // 更新缩放和平移
+        this.scale = newScale
+        this.translateX = this.startDragX + (centerX - this.lastTouchCenter.x) * (this.scale - 1)
+        this.translateY = this.startDragY + (centerY - this.lastTouchCenter.y) * (this.scale - 1)
+        
+        this.lastDistance = distance
+        this.lastTouchCenter = {
+          x: centerX,
+          y: centerY
+        }
+      }
+      
+      this.drawCanvas()
+    },
+    
+    // 处理触摸结束事件
+    touchEnd(e) {
+      this.isDragging = false
+    }
+  }
+}
+</script>
+
+<style>
+.container {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+}
+</style>

+ 346 - 0
components/multiple-select.vue

@@ -0,0 +1,346 @@
+<template>
+  <view class="select-container" v-show="show" @touchmove.stop.prevent>
+    <view
+      class="mask"
+      :class="activeClass ? 'mask-show' : ''"
+      @tap="onCancel(true)"
+    ></view>
+    <view class="select-box" :class="activeClass ? 'select-box-show' : ''">
+      <view class="header">
+        <text class="cancel" @tap="onCancel">{{ cancelText }}</text>
+        <view class="all" @tap="onAllToggle" v-if="allShow">
+          <text :class="isAll ? 'all-active' : ''">全选 </text>
+        </view>
+        <text class="confirm" @tap="onConfirm">{{ confirmText }}</text>
+      </view>
+      <view class="body-warp">
+        <scroll-view class="body" scroll-y="true">
+          <slot v-if="!data.length" name="tips">
+            <view class="empty-tips">暂无数据~</view>
+          </slot>
+          <view
+            class="select-item"
+            :class="[
+              item.disabled ? 'disabled' : '',
+              selectedArr[index] ? 'selected' : '',
+            ]"
+            v-for="(item, index) in data"
+            :key="item[valueName]"
+            @tap="onSelected(index)"
+          >
+            <view class="label">{{ item.name }}</view>
+            <text v-show="selectedArr[index]" class="selected-icon">✔</text>
+          </view>
+        </scroll-view>
+      </view>
+    </view>
+  </view>
+</template>
+<!-- 多选组件 -->
+<script>
+export default {
+  model: {
+    prop: "value",
+    event: ["input"],
+  },
+ 
+  data() {
+    return {
+      show: false, //是否显示
+      activeClass: false, //激活样式状态
+      selectedArr: [], //选择对照列表
+      selectedArrOld: [], //选择对照列表上一次的数据
+    };
+  },
+  onShow() {
+    this.show = this.value;
+    console.log(this.value);
+  },
+  computed: {
+    // 返回是否全选
+    isAll() {
+      let wipeDisabledList = this.returnWipeDisabledList();
+      if (!wipeDisabledList.length) return false;
+      return !wipeDisabledList.includes(false);
+    },
+  },
+  props: {
+    // 双向绑定
+    value: {
+      type: Boolean,
+      default: false,
+    },
+    // 取消按钮文字
+    cancelText: {
+      type: String,
+      default: "取消",
+    },
+    // 确认按钮文字
+    confirmText: {
+      type: String,
+      default: "确认",
+    },
+    // label对应的key名称
+    labelName: {
+      type: String,
+      default: "label",
+    },
+    // value对应的key名称
+    valueName: {
+      type: String,
+      default: "value",
+    },
+    // 是否允许点击遮罩层关闭
+    maskCloseAble: {
+      type: Boolean,
+      default: true,
+    },
+    // 是否显示全选
+    allShow: {
+      type: Boolean,
+      default: true,
+    },
+    // 模式
+    mode: {
+      type: String,
+      default: "multiple",
+    },
+    // 默认选中值
+    defaultSelected: {
+      type: Array,
+      default: function () {
+        return [];
+      },
+    },
+    // 数据源
+    data: {
+      type: Array,
+      required: true,
+      default: () => {
+        return [];
+      },
+    },
+  },
+  created() {
+    console.log(this.data, "111111");
+	this.show = this.value;
+	console.log(this.value)
+  },
+  watch: {
+    async value(newVal) {
+      this.show = newVal;
+      await this.$nextTick();
+      this.activeClass = newVal;
+      if (newVal) {
+        this.selectedArrOld = JSON.parse(JSON.stringify(this.selectedArr));
+      }
+    },
+    async data(newVal) {
+      this.data = newVal;
+      await this.$nextTick();
+      console.log(this.data);
+    },
+    show(newVal) {
+      this.$emit("input", newVal);
+      this.$emit("change", newVal);
+    },
+    data: {
+      // 设置初始选择对照列表
+      handler(list) {
+        this.selectedArr = list.map((el) => false);
+        this.setItemActiveState();
+      },
+      deep: true,
+      immediate: true,
+    },
+    defaultSelected: {
+      handler() {
+        this.setItemActiveState();
+      },
+      deep: true,
+      immediate: true,
+    },
+  },
+  methods: {
+    // 设置默认选中通用办法
+    setItemActiveState() {
+      if (this.data.length && this.defaultSelected.length) {
+        this.data.forEach((item, i) => {
+          for (let n = 0; n < this.defaultSelected.length; n++) {
+            if (
+              !item.disabled &&
+              item[this.valueName] === this.defaultSelected[n]
+            ) {
+              this.selectedArr.splice(i, 1, true);
+              break;
+            }
+          }
+        });
+      }
+    },
+    /**
+     * 选择事件
+     * @index {Number} 点击下标
+     */
+    onSelected(index) {
+      if (this.data[index].disabled) return;
+      let index2Active = this.selectedArr[index];
+      this.selectedArr.splice(index, 1, !index2Active);
+    },
+    // 取消事件
+    onCancel(isMask) {
+      if (!isMask || this.maskCloseAble) {
+        this.show = false;
+        this.selectedArr = JSON.parse(JSON.stringify(this.selectedArrOld));
+      } else {
+        return;
+      }
+      this.$emit("cancel");
+    },
+    // 返回去除了disabled状态后的对照列表
+    returnWipeDisabledList() {
+      let arr = [];
+      this.selectedArr.forEach((el, index) => {
+        if (!this.data[index].disabled) arr.push(el);
+      });
+      return arr;
+    },
+    // 全选/非全选事件
+    onAllToggle() {
+      let wipeDisabledList = this.returnWipeDisabledList();
+      // 如果去除了disabled的对照列表有false的数据,代表未全选
+      if (wipeDisabledList.includes(false)) {
+        this.selectedArr.forEach((el, index) => {
+          if (!this.data[index].disabled)
+            this.selectedArr.splice(index, 1, true);
+        });
+      } else {
+        this.selectedArr.forEach((el, index) => {
+          if (!this.data[index].disabled)
+            el = this.selectedArr.splice(index, 1, false);
+        });
+      }
+    },
+    // 确定事件
+    onConfirm() {
+      console.log(11212);
+      this.show = false;
+      let selectedData = [];
+      this.selectedArr.forEach((el, index) => {
+        if (el) {
+          console.log(el);
+          selectedData.push(this.data[index]);
+        }
+      });
+      if (this.mode === "multiple") {
+        console.log(selectedData);
+        this.$emit("confirm", selectedData);
+      } else {
+        let backData = selectedData[0] || {};
+        this.$emit("confirm", backData);
+      }
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.select-container {
+  width: 100vw;
+  // height: 100vh;
+  position: fixed;
+  left: 0;
+  bottom: 0;
+  z-index: 999;
+  $paddingLR: 18rpx;
+  .mask {
+    width: 100%;
+    height: 100%;
+    background-color: $uni-bg-color-mask;
+    opacity: 0;
+    transition: opacity 0.3s;
+    &.mask-show {
+      opacity: 1;
+    }
+  }
+  // 选择器内容区域
+  .select-box {
+    width: 100%;
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    transform: translate3d(0px, 100%, 0px);
+    background-color: $uni-bg-color;
+    transition: all 0.3s;
+    &.select-box-show {
+      transform: translateZ(0);
+    }
+    .header {
+      display: flex;
+      box-sizing: border-box;
+      width: 100%;
+      justify-content: space-between;
+      border-bottom: 1px solid $uni-border-color;
+      line-height: 76rpx;
+      font-size: 30rpx;
+      padding: 0 $paddingLR;
+      .cancel {
+        color: $uni-text-color-grey;
+      }
+      .all {
+        color: $uni-color-success;
+        .all-active {
+          &::after {
+            display: inline-block;
+            content: "✔";
+            padding-left: 8rpx;
+          }
+        }
+      }
+      .confirm {
+        color: $uni-color-primary;
+      }
+    }
+    .body-warp {
+      width: 100%;
+      height: 30vh;
+      box-sizing: border-box;
+      padding: 20rpx $paddingLR;
+    }
+    .body {
+      width: 100%;
+      height: 100%;
+      overflow-y: auto;
+      .empty-tips {
+        margin-top: 25%;
+        text-align: center;
+        font-size: 26rpx;
+        color: $uni-color-error;
+      }
+      .select-item {
+        display: flex;
+        font-size: 26rpx;
+        line-height: 58rpx;
+        color: #303133;
+        position: relative;
+        transition: all 0.3s;
+        &.selected {
+          color: $uni-color-primary;
+        }
+        &.disabled {
+          color: $uni-text-color-disable;
+        }
+        > .label {
+          flex: 1;
+          text-align: center;
+        }
+        > .selected-icon {
+          position: absolute;
+          right: 0;
+          top: 50%;
+          transform: translateY(-50%);
+        }
+      }
+    }
+  }
+}
+</style>

+ 140 - 0
components/popup-layer/popup-layer.vue

@@ -0,0 +1,140 @@
+<template>
+	<view>
+		<view v-show="ifshow" @tap="ableClose" @touchmove.stop.prevent class="popup-layer" >
+			
+		</view>
+		<view ref="popRef"  class="popup-content"   @tap.stop="stopEvent" :style="_location">
+			<slot></slot>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'popup-layer',
+		model: {
+			prop: "showPop",
+			event: "change"
+		},
+		props: {
+			showPop:{
+				type:Boolean,
+				default:false,
+			},
+			direction: {
+				type: String,
+				default: 'top', // 方向  top,bottom,left,right 
+			},
+			autoClose: {
+				type: Boolean,
+				default: true,
+			}
+		},
+		data() {
+			return {
+				ifshow: false, // 是否展示,
+				translateValue: -100, // 位移距离
+				site:-100,
+				timer: null,
+				iftoggle: false,
+
+			};
+		},
+		computed: {
+			_translate() {
+				const transformObj = {
+					'top': `transform:translateY(${-this.translateValue}%)`,
+					'bottom': `transform:translateY(${this.translateValue}%)`,
+					'left': `transform:translateX(${-this.translateValue}%)`,
+					'right': `transform:translateX(${this.translateValue}%)`
+				};
+				return transformObj[this.direction]
+			},
+			_location() {
+				const positionValue = {
+					'top': `bottom:${this.site}%;width:100%;`,
+					'bottom': `top:${this.site}%;width:100%;`,
+					'left': `right:0px;top:0;height:100%;`,
+					'right': `left:0px;top:0;height:100%;`,
+				};
+				return positionValue[this.direction]+ this._translate;
+			}
+		},
+		mounted(){
+			if(this.showPop){
+				// console.log(222);
+				this.show();
+			}
+		},
+		watch:{
+			showPop(value){
+				console.log(value)
+				if(value){
+					this.show();
+				}else{
+					this.close();
+				}
+			}	
+		},
+		methods: {
+			stopMove(event){
+				return;
+			},
+			show(events) {
+				this.ifshow = true;
+				this.site=0;
+				let _open = setTimeout(() => {
+					this.translateValue = 0;
+					_open = null;
+				}, 100)
+				let _toggle = setTimeout(() => {
+					this.iftoggle = true;
+					_toggle = null;
+				}, 300);
+			},
+			close() {
+				if (this.timer !== null || !this.iftoggle) {
+					return;
+				}
+				this.translateValue = -100;
+				this.timer = setTimeout(() => {
+					this.ifshow = false;
+					this.timer = null;
+					this.iftoggle = false;
+					this.$emit('closeCallBack', null);
+					this.$emit('change',false)
+				}, 300);
+			},
+			ableClose() {
+				if (this.autoClose) {
+					this.close();
+				}
+			},
+			stopEvent(event) {},
+			doSome(){
+			}
+
+		}
+	}
+</script>
+
+<style lang="scss">
+	.popup-layer {
+		position: fixed;
+		z-index: 999999;
+		// background: rgba(0, 0, 0, .3);
+		height: 100%;
+		width: 100%;
+		top: 0px;
+		left: 0px;
+		overflow: hidden;
+	}
+
+	.popup-content {
+		position: fixed;
+		z-index: 1000000;
+		background: #FFFFFF;
+		transition: transform .2s ease;
+		overflow: hidden; 
+	}
+</style>

+ 96 - 0
components/uni-icons/icons.js

@@ -0,0 +1,96 @@
+export default {
+	'contact': '\ue100',
+	'person': '\ue101',
+	'personadd': '\ue102',
+	'contact-filled': '\ue130',
+	'person-filled': '\ue131',
+	'personadd-filled': '\ue132',
+	'phone': '\ue200',
+	'email': '\ue201',
+	'chatbubble': '\ue202',
+	'chatboxes': '\ue203',
+	'phone-filled': '\ue230',
+	'email-filled': '\ue231',
+	'chatbubble-filled': '\ue232',
+	'chatboxes-filled': '\ue233',
+	'weibo': '\ue260',
+	'weixin': '\ue261',
+	'pengyouquan': '\ue262',
+	'chat': '\ue263',
+	'qq': '\ue264',
+	'videocam': '\ue300',
+	'camera': '\ue301',
+	'mic': '\ue302',
+	'location': '\ue303',
+	'mic-filled': '\ue332',
+	'speech': '\ue332',
+	'location-filled': '\ue333',
+	'micoff': '\ue360',
+	'image': '\ue363',
+	'map': '\ue364',
+	'compose': '\ue400',
+	'trash': '\ue401',
+	'upload': '\ue402',
+	'download': '\ue403',
+	'close': '\ue404',
+	'redo': '\ue405',
+	'undo': '\ue406',
+	'refresh': '\ue407',
+	'star': '\ue408',
+	'plus': '\ue409',
+	'minus': '\ue410',
+	'circle': '\ue411',
+	'checkbox': '\ue411',
+	'close-filled': '\ue434',
+	'clear': '\ue434',
+	'refresh-filled': '\ue437',
+	'star-filled': '\ue438',
+	'plus-filled': '\ue439',
+	'minus-filled': '\ue440',
+	'circle-filled': '\ue441',
+	'checkbox-filled': '\ue442',
+	'closeempty': '\ue460',
+	'refreshempty': '\ue461',
+	'reload': '\ue462',
+	'starhalf': '\ue463',
+	'spinner': '\ue464',
+	'spinner-cycle': '\ue465',
+	'search': '\ue466',
+	'plusempty': '\ue468',
+	'forward': '\ue470',
+	'back': '\ue471',
+	'left-nav': '\ue471',
+	'checkmarkempty': '\ue472',
+	'home': '\ue500',
+	'navigate': '\ue501',
+	'gear': '\ue502',
+	'paperplane': '\ue503',
+	'info': '\ue504',
+	'help': '\ue505',
+	'locked': '\ue506',
+	'more': '\ue507',
+	'flag': '\ue508',
+	'home-filled': '\ue530',
+	'gear-filled': '\ue532',
+	'info-filled': '\ue534',
+	'help-filled': '\ue535',
+	'more-filled': '\ue537',
+	'settings': '\ue560',
+	'list': '\ue562',
+	'bars': '\ue563',
+	'loop': '\ue565',
+	'paperclip': '\ue567',
+	'eye': '\ue568',
+	'arrowup': '\ue580',
+	'arrowdown': '\ue581',
+	'arrowleft': '\ue582',
+	'arrowright': '\ue583',
+	'arrowthinup': '\ue584',
+	'arrowthindown': '\ue585',
+	'arrowthinleft': '\ue586',
+	'arrowthinright': '\ue587',
+	'pulldown': '\ue588',
+	'closefill': '\ue589',
+	'sound': '\ue590',
+	'scan': '\ue612'
+}

Разница между файлами не показана из-за своего большого размера
+ 57 - 0
components/uni-icons/uni-icons.vue


+ 224 - 0
components/uni-nav-bar/uni-nav-bar.vue

@@ -0,0 +1,224 @@
+<template>
+	<view class="uni-navbar">
+		<view :class="{ 'uni-navbar--fixed': fixed, 'uni-navbar--shadow': shadow, 'uni-navbar--border': border }" :style="{ 'background-color': backgroundColor }"
+		 class="uni-navbar__content">
+			<uni-status-bar v-if="statusBar" />
+			<view :style="{ color: color,backgroundColor: backgroundColor }" class="uni-navbar__header uni-navbar__content_view">
+				<view @tap="onClickLeft" class="uni-navbar__header-btns uni-navbar__header-btns-left uni-navbar__content_view">
+					<view class="uni-navbar__content_view" v-if="leftIcon.length">
+						<uni-icons :color="color" :type="leftIcon" size="24" />
+					</view>
+					<view :class="{ 'uni-navbar-btn-icon-left': !leftIcon.length }" class="uni-navbar-btn-text uni-navbar__content_view"
+					 v-if="leftText.length">
+						<text :style="{ color: color, fontSize: '14px' }">{{ leftText }}</text>
+					</view>
+					<slot name="left" />
+				</view>
+				<view class="uni-navbar__header-container uni-navbar__content_view">
+					<view class="uni-navbar__header-container-inner uni-navbar__content_view" v-if="title.length">
+						<text class="uni-nav-bar-text" :style="{color: color }">{{ title }}</text>
+					</view>
+					<!-- 标题插槽 -->
+					<slot />
+				</view>
+				<view :class="title.length ? 'uni-navbar__header-btns-right' : ''" @tap="onClickRight" class="uni-navbar__header-btns uni-navbar__content_view">
+					<view class="uni-navbar__content_view" v-if="rightIcon.length">
+						<uni-icons :color="color" :type="rightIcon" size="24" />
+					</view>
+					<!-- 优先显示图标 -->
+					<view class="uni-navbar-btn-text uni-navbar__content_view" v-if="rightText.length && !rightIcon.length">
+						<text class="uni-nav-bar-right-text">{{ rightText }}</text>
+					</view>
+					<slot name="right" />
+				</view>
+			</view>
+		</view>
+		<view class="uni-navbar__placeholder" v-if="fixed">
+			<uni-status-bar v-if="statusBar" />
+			<view class="uni-navbar__placeholder-view" />
+		</view>
+	</view>
+</template>
+
+<script>
+	import uniStatusBar from "../uni-status-bar/uni-status-bar.vue";
+	import uniIcons from "../uni-icons/uni-icons.vue";
+
+	export default {
+		name: "UniNavBar",
+		components: {
+			uniStatusBar,
+			uniIcons
+		},
+		props: {
+			title: {
+				type: String,
+				default: ""
+			},
+			leftText: {
+				type: String,
+				default: ""
+			},
+			rightText: {
+				type: String,
+				default: ""
+			},
+			leftIcon: {
+				type: String,
+				default: ""
+			},
+			rightIcon: {
+				type: String,
+				default: ""
+			},
+			fixed: {
+				type: [Boolean, String],
+				default: false
+			},
+			color: {
+				type: String,
+				default: "#000000"
+			},
+			backgroundColor: {
+				type: String,
+				default: "#FFFFFF"
+			},
+			statusBar: {
+				type: [Boolean, String],
+				default: false
+			},
+			shadow: {
+				type: [String, Boolean],
+				default: false
+			},
+			border: {
+				type: [String, Boolean],
+				default: true
+			}
+		},
+        mounted() {
+          if(uni.report && this.title !== '') {
+              uni.report('title', this.title)
+          }
+        },
+		methods: {
+			onClickLeft() {
+				this.$emit("clickLeft");
+			},
+			onClickRight() {
+				this.$emit("clickRight");
+			}
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	$nav-height: 44px;
+	.uni-nav-bar-text {
+		/* #ifdef APP-PLUS */
+		font-size: 16px;
+		/* #endif */
+		/* #ifndef APP-PLUS */
+		font-size: $uni-font-size-lg;
+		/* #endif */
+	}
+	.uni-nav-bar-right-text {
+		font-size: $uni-font-size-base;
+	}
+
+	.uni-navbar {
+		width: 100%;
+	}
+
+	.uni-navbar__content {
+		position: relative;
+		width: 750rpx;
+		background-color: $uni-bg-color;
+		overflow: hidden;
+	}
+
+	.uni-navbar__content_view {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		align-items: center;
+		flex-direction: row;
+		// background-color: #FFFFFF;
+	}
+
+	.uni-navbar__header {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		width: 750rpx;
+		height: $nav-height;
+		line-height: $nav-height;
+		font-size: 16px;
+		// background-color: #ffffff;
+	}
+
+	.uni-navbar__header-btns {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-wrap: nowrap;
+		width: 120rpx;
+		padding: 0 6px;
+		justify-content: center;
+		align-items: center;
+	}
+
+	.uni-navbar__header-btns-left {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		width: 150rpx;
+		justify-content: flex-start;
+	}
+
+	.uni-navbar__header-btns-right {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		width: 150rpx;
+		padding-right: 30rpx;
+		justify-content: flex-end;
+	}
+
+	.uni-navbar__header-container {
+		flex: 1;
+	}
+
+	.uni-navbar__header-container-inner {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex: 1;
+		align-items: center;
+		justify-content: center;
+		font-size: $uni-font-size-base;
+	}
+
+
+	.uni-navbar__placeholder-view {
+		height: $nav-height;
+	}
+
+	.uni-navbar--fixed {
+		position: fixed;
+		z-index: 998;
+	}
+
+	.uni-navbar--shadow {
+		/* #ifndef APP-NVUE */
+		box-shadow: 0 1px 6px #ccc;
+		/* #endif */
+	}
+
+	// .uni-navbar--border {
+	// 	border-bottom-width: 1rpx;
+	// 	border-bottom-style: solid;
+	// 	border-bottom-color: $uni-border-color;
+	// }
+</style>

+ 25 - 0
components/uni-status-bar/uni-status-bar.vue

@@ -0,0 +1,25 @@
+<template>
+	<view :style="{ height: statusBarHeight }" class="uni-status-bar">
+		<slot />
+	</view>
+</template>
+
+<script>
+	var statusBarHeight = uni.getSystemInfoSync().statusBarHeight + 'px'
+	export default {
+		name: 'UniStatusBar',
+		data() {
+			return {
+				statusBarHeight: statusBarHeight
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.uni-status-bar {
+		width: 750rpx;
+		height: 20px;
+		// height: var(--status-bar-height);
+	}
+</style>

+ 24 - 0
crypto-js/LICENSE

@@ -0,0 +1,24 @@
+# License
+
+[The MIT License (MIT)](http://opensource.org/licenses/MIT)
+
+Copyright (c) 2009-2013 Jeff Mott  
+Copyright (c) 2013-2016 Evan Vosberg
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

+ 234 - 0
crypto-js/aes.js

@@ -0,0 +1,234 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	(function () {
+	    // Shortcuts
+	    var C = CryptoJS;
+	    var C_lib = C.lib;
+	    var BlockCipher = C_lib.BlockCipher;
+	    var C_algo = C.algo;
+
+	    // Lookup tables
+	    var SBOX = [];
+	    var INV_SBOX = [];
+	    var SUB_MIX_0 = [];
+	    var SUB_MIX_1 = [];
+	    var SUB_MIX_2 = [];
+	    var SUB_MIX_3 = [];
+	    var INV_SUB_MIX_0 = [];
+	    var INV_SUB_MIX_1 = [];
+	    var INV_SUB_MIX_2 = [];
+	    var INV_SUB_MIX_3 = [];
+
+	    // Compute lookup tables
+	    (function () {
+	        // Compute double table
+	        var d = [];
+	        for (var i = 0; i < 256; i++) {
+	            if (i < 128) {
+	                d[i] = i << 1;
+	            } else {
+	                d[i] = (i << 1) ^ 0x11b;
+	            }
+	        }
+
+	        // Walk GF(2^8)
+	        var x = 0;
+	        var xi = 0;
+	        for (var i = 0; i < 256; i++) {
+	            // Compute sbox
+	            var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4);
+	            sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63;
+	            SBOX[x] = sx;
+	            INV_SBOX[sx] = x;
+
+	            // Compute multiplication
+	            var x2 = d[x];
+	            var x4 = d[x2];
+	            var x8 = d[x4];
+
+	            // Compute sub bytes, mix columns tables
+	            var t = (d[sx] * 0x101) ^ (sx * 0x1010100);
+	            SUB_MIX_0[x] = (t << 24) | (t >>> 8);
+	            SUB_MIX_1[x] = (t << 16) | (t >>> 16);
+	            SUB_MIX_2[x] = (t << 8)  | (t >>> 24);
+	            SUB_MIX_3[x] = t;
+
+	            // Compute inv sub bytes, inv mix columns tables
+	            var t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100);
+	            INV_SUB_MIX_0[sx] = (t << 24) | (t >>> 8);
+	            INV_SUB_MIX_1[sx] = (t << 16) | (t >>> 16);
+	            INV_SUB_MIX_2[sx] = (t << 8)  | (t >>> 24);
+	            INV_SUB_MIX_3[sx] = t;
+
+	            // Compute next counter
+	            if (!x) {
+	                x = xi = 1;
+	            } else {
+	                x = x2 ^ d[d[d[x8 ^ x2]]];
+	                xi ^= d[d[xi]];
+	            }
+	        }
+	    }());
+
+	    // Precomputed Rcon lookup
+	    var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36];
+
+	    /**
+	     * AES block cipher algorithm.
+	     */
+	    var AES = C_algo.AES = BlockCipher.extend({
+	        _doReset: function () {
+	            var t;
+
+	            // Skip reset of nRounds has been set before and key did not change
+	            if (this._nRounds && this._keyPriorReset === this._key) {
+	                return;
+	            }
+
+	            // Shortcuts
+	            var key = this._keyPriorReset = this._key;
+	            var keyWords = key.words;
+	            var keySize = key.sigBytes / 4;
+
+	            // Compute number of rounds
+	            var nRounds = this._nRounds = keySize + 6;
+
+	            // Compute number of key schedule rows
+	            var ksRows = (nRounds + 1) * 4;
+
+	            // Compute key schedule
+	            var keySchedule = this._keySchedule = [];
+	            for (var ksRow = 0; ksRow < ksRows; ksRow++) {
+	                if (ksRow < keySize) {
+	                    keySchedule[ksRow] = keyWords[ksRow];
+	                } else {
+	                    t = keySchedule[ksRow - 1];
+
+	                    if (!(ksRow % keySize)) {
+	                        // Rot word
+	                        t = (t << 8) | (t >>> 24);
+
+	                        // Sub word
+	                        t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff];
+
+	                        // Mix Rcon
+	                        t ^= RCON[(ksRow / keySize) | 0] << 24;
+	                    } else if (keySize > 6 && ksRow % keySize == 4) {
+	                        // Sub word
+	                        t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff];
+	                    }
+
+	                    keySchedule[ksRow] = keySchedule[ksRow - keySize] ^ t;
+	                }
+	            }
+
+	            // Compute inv key schedule
+	            var invKeySchedule = this._invKeySchedule = [];
+	            for (var invKsRow = 0; invKsRow < ksRows; invKsRow++) {
+	                var ksRow = ksRows - invKsRow;
+
+	                if (invKsRow % 4) {
+	                    var t = keySchedule[ksRow];
+	                } else {
+	                    var t = keySchedule[ksRow - 4];
+	                }
+
+	                if (invKsRow < 4 || ksRow <= 4) {
+	                    invKeySchedule[invKsRow] = t;
+	                } else {
+	                    invKeySchedule[invKsRow] = INV_SUB_MIX_0[SBOX[t >>> 24]] ^ INV_SUB_MIX_1[SBOX[(t >>> 16) & 0xff]] ^
+	                                               INV_SUB_MIX_2[SBOX[(t >>> 8) & 0xff]] ^ INV_SUB_MIX_3[SBOX[t & 0xff]];
+	                }
+	            }
+	        },
+
+	        encryptBlock: function (M, offset) {
+	            this._doCryptBlock(M, offset, this._keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX);
+	        },
+
+	        decryptBlock: function (M, offset) {
+	            // Swap 2nd and 4th rows
+	            var t = M[offset + 1];
+	            M[offset + 1] = M[offset + 3];
+	            M[offset + 3] = t;
+
+	            this._doCryptBlock(M, offset, this._invKeySchedule, INV_SUB_MIX_0, INV_SUB_MIX_1, INV_SUB_MIX_2, INV_SUB_MIX_3, INV_SBOX);
+
+	            // Inv swap 2nd and 4th rows
+	            var t = M[offset + 1];
+	            M[offset + 1] = M[offset + 3];
+	            M[offset + 3] = t;
+	        },
+
+	        _doCryptBlock: function (M, offset, keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX) {
+	            // Shortcut
+	            var nRounds = this._nRounds;
+
+	            // Get input, add round key
+	            var s0 = M[offset]     ^ keySchedule[0];
+	            var s1 = M[offset + 1] ^ keySchedule[1];
+	            var s2 = M[offset + 2] ^ keySchedule[2];
+	            var s3 = M[offset + 3] ^ keySchedule[3];
+
+	            // Key schedule row counter
+	            var ksRow = 4;
+
+	            // Rounds
+	            for (var round = 1; round < nRounds; round++) {
+	                // Shift rows, sub bytes, mix columns, add round key
+	                var t0 = SUB_MIX_0[s0 >>> 24] ^ SUB_MIX_1[(s1 >>> 16) & 0xff] ^ SUB_MIX_2[(s2 >>> 8) & 0xff] ^ SUB_MIX_3[s3 & 0xff] ^ keySchedule[ksRow++];
+	                var t1 = SUB_MIX_0[s1 >>> 24] ^ SUB_MIX_1[(s2 >>> 16) & 0xff] ^ SUB_MIX_2[(s3 >>> 8) & 0xff] ^ SUB_MIX_3[s0 & 0xff] ^ keySchedule[ksRow++];
+	                var t2 = SUB_MIX_0[s2 >>> 24] ^ SUB_MIX_1[(s3 >>> 16) & 0xff] ^ SUB_MIX_2[(s0 >>> 8) & 0xff] ^ SUB_MIX_3[s1 & 0xff] ^ keySchedule[ksRow++];
+	                var t3 = SUB_MIX_0[s3 >>> 24] ^ SUB_MIX_1[(s0 >>> 16) & 0xff] ^ SUB_MIX_2[(s1 >>> 8) & 0xff] ^ SUB_MIX_3[s2 & 0xff] ^ keySchedule[ksRow++];
+
+	                // Update state
+	                s0 = t0;
+	                s1 = t1;
+	                s2 = t2;
+	                s3 = t3;
+	            }
+
+	            // Shift rows, sub bytes, add round key
+	            var t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++];
+	            var t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++];
+	            var t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++];
+	            var t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++];
+
+	            // Set output
+	            M[offset]     = t0;
+	            M[offset + 1] = t1;
+	            M[offset + 2] = t2;
+	            M[offset + 3] = t3;
+	        },
+
+	        keySize: 256/32
+	    });
+
+	    /**
+	     * Shortcut functions to the cipher's object interface.
+	     *
+	     * @example
+	     *
+	     *     var ciphertext = CryptoJS.AES.encrypt(message, key, cfg);
+	     *     var plaintext  = CryptoJS.AES.decrypt(ciphertext, key, cfg);
+	     */
+	    C.AES = BlockCipher._createHelper(AES);
+	}());
+
+
+	return CryptoJS.AES;
+
+}));

+ 471 - 0
crypto-js/blowfish.js

@@ -0,0 +1,471 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	(function () {
+	    // Shortcuts
+	    var C = CryptoJS;
+	    var C_lib = C.lib;
+	    var BlockCipher = C_lib.BlockCipher;
+	    var C_algo = C.algo;
+
+	    const N = 16;
+
+	    //Origin pbox and sbox, derived from PI
+	    const ORIG_P = [
+	        0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344,
+	        0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89,
+	        0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C,
+	        0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917,
+	        0x9216D5D9, 0x8979FB1B
+	    ];
+
+	    const ORIG_S = [
+	        [   0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7,
+	            0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99,
+	            0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16,
+	            0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E,
+	            0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE,
+	            0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013,
+	            0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF,
+	            0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E,
+	            0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60,
+	            0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440,
+	            0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE,
+	            0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A,
+	            0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E,
+	            0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677,
+	            0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193,
+	            0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032,
+	            0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88,
+	            0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239,
+	            0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E,
+	            0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0,
+	            0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3,
+	            0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98,
+	            0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88,
+	            0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE,
+	            0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6,
+	            0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D,
+	            0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B,
+	            0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7,
+	            0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA,
+	            0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463,
+	            0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F,
+	            0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09,
+	            0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3,
+	            0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB,
+	            0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279,
+	            0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8,
+	            0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB,
+	            0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82,
+	            0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB,
+	            0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573,
+	            0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0,
+	            0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B,
+	            0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790,
+	            0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8,
+	            0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4,
+	            0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0,
+	            0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7,
+	            0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C,
+	            0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD,
+	            0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1,
+	            0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299,
+	            0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9,
+	            0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477,
+	            0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF,
+	            0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49,
+	            0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF,
+	            0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA,
+	            0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5,
+	            0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41,
+	            0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915,
+	            0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400,
+	            0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915,
+	            0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664,
+	            0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A   ],
+	        [   0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623,
+	            0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266,
+	            0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1,
+	            0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E,
+	            0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6,
+	            0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1,
+	            0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E,
+	            0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1,
+	            0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737,
+	            0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8,
+	            0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF,
+	            0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD,
+	            0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701,
+	            0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7,
+	            0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41,
+	            0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331,
+	            0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF,
+	            0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF,
+	            0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E,
+	            0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87,
+	            0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C,
+	            0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2,
+	            0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16,
+	            0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD,
+	            0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B,
+	            0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509,
+	            0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E,
+	            0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3,
+	            0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F,
+	            0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A,
+	            0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4,
+	            0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960,
+	            0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66,
+	            0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28,
+	            0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802,
+	            0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84,
+	            0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510,
+	            0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF,
+	            0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14,
+	            0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E,
+	            0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50,
+	            0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7,
+	            0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8,
+	            0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281,
+	            0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99,
+	            0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696,
+	            0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128,
+	            0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73,
+	            0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0,
+	            0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0,
+	            0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105,
+	            0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250,
+	            0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3,
+	            0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285,
+	            0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00,
+	            0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061,
+	            0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB,
+	            0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E,
+	            0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735,
+	            0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC,
+	            0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9,
+	            0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340,
+	            0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20,
+	            0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7   ],
+	        [   0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934,
+	            0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068,
+	            0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF,
+	            0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840,
+	            0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45,
+	            0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504,
+	            0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A,
+	            0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB,
+	            0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE,
+	            0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6,
+	            0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42,
+	            0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B,
+	            0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2,
+	            0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB,
+	            0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527,
+	            0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B,
+	            0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33,
+	            0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C,
+	            0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3,
+	            0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC,
+	            0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17,
+	            0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564,
+	            0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B,
+	            0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115,
+	            0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922,
+	            0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728,
+	            0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0,
+	            0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E,
+	            0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37,
+	            0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D,
+	            0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804,
+	            0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B,
+	            0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3,
+	            0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB,
+	            0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D,
+	            0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C,
+	            0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350,
+	            0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9,
+	            0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A,
+	            0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE,
+	            0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D,
+	            0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC,
+	            0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F,
+	            0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61,
+	            0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2,
+	            0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9,
+	            0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2,
+	            0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C,
+	            0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E,
+	            0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633,
+	            0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10,
+	            0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169,
+	            0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52,
+	            0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027,
+	            0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5,
+	            0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62,
+	            0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634,
+	            0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76,
+	            0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24,
+	            0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC,
+	            0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4,
+	            0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C,
+	            0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837,
+	            0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0  ],
+	        [   0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B,
+	            0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE,
+	            0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B,
+	            0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4,
+	            0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8,
+	            0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6,
+	            0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304,
+	            0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22,
+	            0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4,
+	            0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6,
+	            0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9,
+	            0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59,
+	            0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593,
+	            0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51,
+	            0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28,
+	            0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C,
+	            0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B,
+	            0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28,
+	            0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C,
+	            0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD,
+	            0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A,
+	            0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319,
+	            0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB,
+	            0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F,
+	            0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991,
+	            0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32,
+	            0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680,
+	            0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166,
+	            0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE,
+	            0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB,
+	            0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5,
+	            0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47,
+	            0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370,
+	            0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D,
+	            0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84,
+	            0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048,
+	            0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8,
+	            0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD,
+	            0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9,
+	            0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7,
+	            0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38,
+	            0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F,
+	            0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C,
+	            0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525,
+	            0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1,
+	            0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442,
+	            0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964,
+	            0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E,
+	            0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8,
+	            0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D,
+	            0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F,
+	            0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299,
+	            0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02,
+	            0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC,
+	            0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614,
+	            0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A,
+	            0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6,
+	            0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B,
+	            0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0,
+	            0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060,
+	            0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E,
+	            0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9,
+	            0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F,
+	            0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6  ]
+	    ];
+
+	    var BLOWFISH_CTX = {
+	        pbox: [],
+	        sbox: []
+	    }
+
+	    function F(ctx, x){
+	        let a = (x >> 24) & 0xFF;
+	        let b = (x >> 16) & 0xFF;
+	        let c = (x >> 8) & 0xFF;
+	        let d = x & 0xFF;
+
+	        let y = ctx.sbox[0][a] + ctx.sbox[1][b];
+	        y = y ^ ctx.sbox[2][c];
+	        y = y + ctx.sbox[3][d];
+
+	        return y;
+	    }
+
+	    function BlowFish_Encrypt(ctx, left, right){
+	        let Xl = left;
+	        let Xr = right;
+	        let temp;
+
+	        for(let i = 0; i < N; ++i){
+	            Xl = Xl ^ ctx.pbox[i];
+	            Xr = F(ctx, Xl) ^ Xr;
+
+	            temp = Xl;
+	            Xl = Xr;
+	            Xr = temp;
+	        }
+
+	        temp = Xl;
+	        Xl = Xr;
+	        Xr = temp;
+
+	        Xr = Xr ^ ctx.pbox[N];
+	        Xl = Xl ^ ctx.pbox[N + 1];
+
+	        return {left: Xl, right: Xr};
+	    }
+
+	    function BlowFish_Decrypt(ctx, left, right){
+	        let Xl = left;
+	        let Xr = right;
+	        let temp;
+
+	        for(let i = N + 1; i > 1; --i){
+	            Xl = Xl ^ ctx.pbox[i];
+	            Xr = F(ctx, Xl) ^ Xr;
+
+	            temp = Xl;
+	            Xl = Xr;
+	            Xr = temp;
+	        }
+
+	        temp = Xl;
+	        Xl = Xr;
+	        Xr = temp;
+
+	        Xr = Xr ^ ctx.pbox[1];
+	        Xl = Xl ^ ctx.pbox[0];
+
+	        return {left: Xl, right: Xr};
+	    }
+
+	    /**
+	     * Initialization ctx's pbox and sbox.
+	     *
+	     * @param {Object} ctx The object has pbox and sbox.
+	     * @param {Array} key An array of 32-bit words.
+	     * @param {int} keysize The length of the key.
+	     *
+	     * @example
+	     *
+	     *     BlowFishInit(BLOWFISH_CTX, key, 128/32);
+	     */
+	    function BlowFishInit(ctx, key, keysize)
+	    {
+	        for(let Row = 0; Row < 4; Row++)
+	        {
+	            ctx.sbox[Row] = [];
+	            for(let Col = 0; Col < 256; Col++)
+	            {
+	                ctx.sbox[Row][Col] = ORIG_S[Row][Col];
+	            }
+	        }
+
+	        let keyIndex = 0;
+	        for(let index = 0; index < N + 2; index++)
+	        {
+	            ctx.pbox[index] = ORIG_P[index] ^ key[keyIndex];
+	            keyIndex++;
+	            if(keyIndex >= keysize)
+	            {
+	                keyIndex = 0;
+	            }
+	        }
+
+	        let Data1 = 0;
+	        let Data2 = 0;
+	        let res = 0;
+	        for(let i = 0; i < N + 2; i += 2)
+	        {
+	            res = BlowFish_Encrypt(ctx, Data1, Data2);
+	            Data1 = res.left;
+	            Data2 = res.right;
+	            ctx.pbox[i] = Data1;
+	            ctx.pbox[i + 1] = Data2;
+	        }
+
+	        for(let i = 0; i < 4; i++)
+	        {
+	            for(let j = 0; j < 256; j += 2)
+	            {
+	                res = BlowFish_Encrypt(ctx, Data1, Data2);
+	                Data1 = res.left;
+	                Data2 = res.right;
+	                ctx.sbox[i][j] = Data1;
+	                ctx.sbox[i][j + 1] = Data2;
+	            }
+	        }
+
+	        return true;
+	    }
+
+	    /**
+	     * Blowfish block cipher algorithm.
+	     */
+	    var Blowfish = C_algo.Blowfish = BlockCipher.extend({
+	        _doReset: function () {
+	            // Skip reset of nRounds has been set before and key did not change
+	            if (this._keyPriorReset === this._key) {
+	                return;
+	            }
+
+	            // Shortcuts
+	            var key = this._keyPriorReset = this._key;
+	            var keyWords = key.words;
+	            var keySize = key.sigBytes / 4;
+
+	            //Initialization pbox and sbox
+	            BlowFishInit(BLOWFISH_CTX, keyWords, keySize);
+	        },
+
+	        encryptBlock: function (M, offset) {
+	            var res = BlowFish_Encrypt(BLOWFISH_CTX, M[offset], M[offset + 1]);
+	            M[offset] = res.left;
+	            M[offset + 1] = res.right;
+	        },
+
+	        decryptBlock: function (M, offset) {
+	            var res = BlowFish_Decrypt(BLOWFISH_CTX, M[offset], M[offset + 1]);
+	            M[offset] = res.left;
+	            M[offset + 1] = res.right;
+	        },
+
+	        blockSize: 64/32,
+
+	        keySize: 128/32,
+
+	        ivSize: 64/32
+	    });
+
+	    /**
+	     * Shortcut functions to the cipher's object interface.
+	     *
+	     * @example
+	     *
+	     *     var ciphertext = CryptoJS.Blowfish.encrypt(message, key, cfg);
+	     *     var plaintext  = CryptoJS.Blowfish.decrypt(ciphertext, key, cfg);
+	     */
+	    C.Blowfish = BlockCipher._createHelper(Blowfish);
+	}());
+
+
+	return CryptoJS.Blowfish;
+
+}));

+ 39 - 0
crypto-js/bower.json

@@ -0,0 +1,39 @@
+{
+  "name": "crypto-js",
+  "version": "4.2.0",
+  "description": "JavaScript library of crypto standards.",
+  "license": "MIT",
+  "homepage": "http://github.com/brix/crypto-js",
+  "repository": {
+    "type": "git",
+    "url": "http://github.com/brix/crypto-js.git"
+  },
+  "keywords": [
+    "security",
+    "crypto",
+    "Hash",
+    "MD5",
+    "SHA1",
+    "SHA-1",
+    "SHA256",
+    "SHA-256",
+    "RC4",
+    "Rabbit",
+    "AES",
+    "DES",
+    "PBKDF2",
+    "HMAC",
+    "OFB",
+    "CFB",
+    "CTR",
+    "CBC",
+    "Base64",
+    "Base64url"
+  ],
+  "main": "index.js",
+  "dependencies": {},
+  "browser": {
+    "crypto": false
+  },
+  "ignore": []
+}

+ 895 - 0
crypto-js/cipher-core.js

@@ -0,0 +1,895 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./evpkdf"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./evpkdf"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	/**
+	 * Cipher core components.
+	 */
+	CryptoJS.lib.Cipher || (function (undefined) {
+	    // Shortcuts
+	    var C = CryptoJS;
+	    var C_lib = C.lib;
+	    var Base = C_lib.Base;
+	    var WordArray = C_lib.WordArray;
+	    var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm;
+	    var C_enc = C.enc;
+	    var Utf8 = C_enc.Utf8;
+	    var Base64 = C_enc.Base64;
+	    var C_algo = C.algo;
+	    var EvpKDF = C_algo.EvpKDF;
+
+	    /**
+	     * Abstract base cipher template.
+	     *
+	     * @property {number} keySize This cipher's key size. Default: 4 (128 bits)
+	     * @property {number} ivSize This cipher's IV size. Default: 4 (128 bits)
+	     * @property {number} _ENC_XFORM_MODE A constant representing encryption mode.
+	     * @property {number} _DEC_XFORM_MODE A constant representing decryption mode.
+	     */
+	    var Cipher = C_lib.Cipher = BufferedBlockAlgorithm.extend({
+	        /**
+	         * Configuration options.
+	         *
+	         * @property {WordArray} iv The IV to use for this operation.
+	         */
+	        cfg: Base.extend(),
+
+	        /**
+	         * Creates this cipher in encryption mode.
+	         *
+	         * @param {WordArray} key The key.
+	         * @param {Object} cfg (Optional) The configuration options to use for this operation.
+	         *
+	         * @return {Cipher} A cipher instance.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var cipher = CryptoJS.algo.AES.createEncryptor(keyWordArray, { iv: ivWordArray });
+	         */
+	        createEncryptor: function (key, cfg) {
+	            return this.create(this._ENC_XFORM_MODE, key, cfg);
+	        },
+
+	        /**
+	         * Creates this cipher in decryption mode.
+	         *
+	         * @param {WordArray} key The key.
+	         * @param {Object} cfg (Optional) The configuration options to use for this operation.
+	         *
+	         * @return {Cipher} A cipher instance.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var cipher = CryptoJS.algo.AES.createDecryptor(keyWordArray, { iv: ivWordArray });
+	         */
+	        createDecryptor: function (key, cfg) {
+	            return this.create(this._DEC_XFORM_MODE, key, cfg);
+	        },
+
+	        /**
+	         * Initializes a newly created cipher.
+	         *
+	         * @param {number} xformMode Either the encryption or decryption transormation mode constant.
+	         * @param {WordArray} key The key.
+	         * @param {Object} cfg (Optional) The configuration options to use for this operation.
+	         *
+	         * @example
+	         *
+	         *     var cipher = CryptoJS.algo.AES.create(CryptoJS.algo.AES._ENC_XFORM_MODE, keyWordArray, { iv: ivWordArray });
+	         */
+	        init: function (xformMode, key, cfg) {
+	            // Apply config defaults
+	            this.cfg = this.cfg.extend(cfg);
+
+	            // Store transform mode and key
+	            this._xformMode = xformMode;
+	            this._key = key;
+
+	            // Set initial values
+	            this.reset();
+	        },
+
+	        /**
+	         * Resets this cipher to its initial state.
+	         *
+	         * @example
+	         *
+	         *     cipher.reset();
+	         */
+	        reset: function () {
+	            // Reset data buffer
+	            BufferedBlockAlgorithm.reset.call(this);
+
+	            // Perform concrete-cipher logic
+	            this._doReset();
+	        },
+
+	        /**
+	         * Adds data to be encrypted or decrypted.
+	         *
+	         * @param {WordArray|string} dataUpdate The data to encrypt or decrypt.
+	         *
+	         * @return {WordArray} The data after processing.
+	         *
+	         * @example
+	         *
+	         *     var encrypted = cipher.process('data');
+	         *     var encrypted = cipher.process(wordArray);
+	         */
+	        process: function (dataUpdate) {
+	            // Append
+	            this._append(dataUpdate);
+
+	            // Process available blocks
+	            return this._process();
+	        },
+
+	        /**
+	         * Finalizes the encryption or decryption process.
+	         * Note that the finalize operation is effectively a destructive, read-once operation.
+	         *
+	         * @param {WordArray|string} dataUpdate The final data to encrypt or decrypt.
+	         *
+	         * @return {WordArray} The data after final processing.
+	         *
+	         * @example
+	         *
+	         *     var encrypted = cipher.finalize();
+	         *     var encrypted = cipher.finalize('data');
+	         *     var encrypted = cipher.finalize(wordArray);
+	         */
+	        finalize: function (dataUpdate) {
+	            // Final data update
+	            if (dataUpdate) {
+	                this._append(dataUpdate);
+	            }
+
+	            // Perform concrete-cipher logic
+	            var finalProcessedData = this._doFinalize();
+
+	            return finalProcessedData;
+	        },
+
+	        keySize: 128/32,
+
+	        ivSize: 128/32,
+
+	        _ENC_XFORM_MODE: 1,
+
+	        _DEC_XFORM_MODE: 2,
+
+	        /**
+	         * Creates shortcut functions to a cipher's object interface.
+	         *
+	         * @param {Cipher} cipher The cipher to create a helper for.
+	         *
+	         * @return {Object} An object with encrypt and decrypt shortcut functions.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var AES = CryptoJS.lib.Cipher._createHelper(CryptoJS.algo.AES);
+	         */
+	        _createHelper: (function () {
+	            function selectCipherStrategy(key) {
+	                if (typeof key == 'string') {
+	                    return PasswordBasedCipher;
+	                } else {
+	                    return SerializableCipher;
+	                }
+	            }
+
+	            return function (cipher) {
+	                return {
+	                    encrypt: function (message, key, cfg) {
+	                        return selectCipherStrategy(key).encrypt(cipher, message, key, cfg);
+	                    },
+
+	                    decrypt: function (ciphertext, key, cfg) {
+	                        return selectCipherStrategy(key).decrypt(cipher, ciphertext, key, cfg);
+	                    }
+	                };
+	            };
+	        }())
+	    });
+
+	    /**
+	     * Abstract base stream cipher template.
+	     *
+	     * @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 1 (32 bits)
+	     */
+	    var StreamCipher = C_lib.StreamCipher = Cipher.extend({
+	        _doFinalize: function () {
+	            // Process partial blocks
+	            var finalProcessedBlocks = this._process(!!'flush');
+
+	            return finalProcessedBlocks;
+	        },
+
+	        blockSize: 1
+	    });
+
+	    /**
+	     * Mode namespace.
+	     */
+	    var C_mode = C.mode = {};
+
+	    /**
+	     * Abstract base block cipher mode template.
+	     */
+	    var BlockCipherMode = C_lib.BlockCipherMode = Base.extend({
+	        /**
+	         * Creates this mode for encryption.
+	         *
+	         * @param {Cipher} cipher A block cipher instance.
+	         * @param {Array} iv The IV words.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var mode = CryptoJS.mode.CBC.createEncryptor(cipher, iv.words);
+	         */
+	        createEncryptor: function (cipher, iv) {
+	            return this.Encryptor.create(cipher, iv);
+	        },
+
+	        /**
+	         * Creates this mode for decryption.
+	         *
+	         * @param {Cipher} cipher A block cipher instance.
+	         * @param {Array} iv The IV words.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var mode = CryptoJS.mode.CBC.createDecryptor(cipher, iv.words);
+	         */
+	        createDecryptor: function (cipher, iv) {
+	            return this.Decryptor.create(cipher, iv);
+	        },
+
+	        /**
+	         * Initializes a newly created mode.
+	         *
+	         * @param {Cipher} cipher A block cipher instance.
+	         * @param {Array} iv The IV words.
+	         *
+	         * @example
+	         *
+	         *     var mode = CryptoJS.mode.CBC.Encryptor.create(cipher, iv.words);
+	         */
+	        init: function (cipher, iv) {
+	            this._cipher = cipher;
+	            this._iv = iv;
+	        }
+	    });
+
+	    /**
+	     * Cipher Block Chaining mode.
+	     */
+	    var CBC = C_mode.CBC = (function () {
+	        /**
+	         * Abstract base CBC mode.
+	         */
+	        var CBC = BlockCipherMode.extend();
+
+	        /**
+	         * CBC encryptor.
+	         */
+	        CBC.Encryptor = CBC.extend({
+	            /**
+	             * Processes the data block at offset.
+	             *
+	             * @param {Array} words The data words to operate on.
+	             * @param {number} offset The offset where the block starts.
+	             *
+	             * @example
+	             *
+	             *     mode.processBlock(data.words, offset);
+	             */
+	            processBlock: function (words, offset) {
+	                // Shortcuts
+	                var cipher = this._cipher;
+	                var blockSize = cipher.blockSize;
+
+	                // XOR and encrypt
+	                xorBlock.call(this, words, offset, blockSize);
+	                cipher.encryptBlock(words, offset);
+
+	                // Remember this block to use with next block
+	                this._prevBlock = words.slice(offset, offset + blockSize);
+	            }
+	        });
+
+	        /**
+	         * CBC decryptor.
+	         */
+	        CBC.Decryptor = CBC.extend({
+	            /**
+	             * Processes the data block at offset.
+	             *
+	             * @param {Array} words The data words to operate on.
+	             * @param {number} offset The offset where the block starts.
+	             *
+	             * @example
+	             *
+	             *     mode.processBlock(data.words, offset);
+	             */
+	            processBlock: function (words, offset) {
+	                // Shortcuts
+	                var cipher = this._cipher;
+	                var blockSize = cipher.blockSize;
+
+	                // Remember this block to use with next block
+	                var thisBlock = words.slice(offset, offset + blockSize);
+
+	                // Decrypt and XOR
+	                cipher.decryptBlock(words, offset);
+	                xorBlock.call(this, words, offset, blockSize);
+
+	                // This block becomes the previous block
+	                this._prevBlock = thisBlock;
+	            }
+	        });
+
+	        function xorBlock(words, offset, blockSize) {
+	            var block;
+
+	            // Shortcut
+	            var iv = this._iv;
+
+	            // Choose mixing block
+	            if (iv) {
+	                block = iv;
+
+	                // Remove IV for subsequent blocks
+	                this._iv = undefined;
+	            } else {
+	                block = this._prevBlock;
+	            }
+
+	            // XOR blocks
+	            for (var i = 0; i < blockSize; i++) {
+	                words[offset + i] ^= block[i];
+	            }
+	        }
+
+	        return CBC;
+	    }());
+
+	    /**
+	     * Padding namespace.
+	     */
+	    var C_pad = C.pad = {};
+
+	    /**
+	     * PKCS #5/7 padding strategy.
+	     */
+	    var Pkcs7 = C_pad.Pkcs7 = {
+	        /**
+	         * Pads data using the algorithm defined in PKCS #5/7.
+	         *
+	         * @param {WordArray} data The data to pad.
+	         * @param {number} blockSize The multiple that the data should be padded to.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     CryptoJS.pad.Pkcs7.pad(wordArray, 4);
+	         */
+	        pad: function (data, blockSize) {
+	            // Shortcut
+	            var blockSizeBytes = blockSize * 4;
+
+	            // Count padding bytes
+	            var nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes;
+
+	            // Create padding word
+	            var paddingWord = (nPaddingBytes << 24) | (nPaddingBytes << 16) | (nPaddingBytes << 8) | nPaddingBytes;
+
+	            // Create padding
+	            var paddingWords = [];
+	            for (var i = 0; i < nPaddingBytes; i += 4) {
+	                paddingWords.push(paddingWord);
+	            }
+	            var padding = WordArray.create(paddingWords, nPaddingBytes);
+
+	            // Add padding
+	            data.concat(padding);
+	        },
+
+	        /**
+	         * Unpads data that had been padded using the algorithm defined in PKCS #5/7.
+	         *
+	         * @param {WordArray} data The data to unpad.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     CryptoJS.pad.Pkcs7.unpad(wordArray);
+	         */
+	        unpad: function (data) {
+	            // Get number of padding bytes from last byte
+	            var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff;
+
+	            // Remove padding
+	            data.sigBytes -= nPaddingBytes;
+	        }
+	    };
+
+	    /**
+	     * Abstract base block cipher template.
+	     *
+	     * @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 4 (128 bits)
+	     */
+	    var BlockCipher = C_lib.BlockCipher = Cipher.extend({
+	        /**
+	         * Configuration options.
+	         *
+	         * @property {Mode} mode The block mode to use. Default: CBC
+	         * @property {Padding} padding The padding strategy to use. Default: Pkcs7
+	         */
+	        cfg: Cipher.cfg.extend({
+	            mode: CBC,
+	            padding: Pkcs7
+	        }),
+
+	        reset: function () {
+	            var modeCreator;
+
+	            // Reset cipher
+	            Cipher.reset.call(this);
+
+	            // Shortcuts
+	            var cfg = this.cfg;
+	            var iv = cfg.iv;
+	            var mode = cfg.mode;
+
+	            // Reset block mode
+	            if (this._xformMode == this._ENC_XFORM_MODE) {
+	                modeCreator = mode.createEncryptor;
+	            } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ {
+	                modeCreator = mode.createDecryptor;
+	                // Keep at least one block in the buffer for unpadding
+	                this._minBufferSize = 1;
+	            }
+
+	            if (this._mode && this._mode.__creator == modeCreator) {
+	                this._mode.init(this, iv && iv.words);
+	            } else {
+	                this._mode = modeCreator.call(mode, this, iv && iv.words);
+	                this._mode.__creator = modeCreator;
+	            }
+	        },
+
+	        _doProcessBlock: function (words, offset) {
+	            this._mode.processBlock(words, offset);
+	        },
+
+	        _doFinalize: function () {
+	            var finalProcessedBlocks;
+
+	            // Shortcut
+	            var padding = this.cfg.padding;
+
+	            // Finalize
+	            if (this._xformMode == this._ENC_XFORM_MODE) {
+	                // Pad data
+	                padding.pad(this._data, this.blockSize);
+
+	                // Process final blocks
+	                finalProcessedBlocks = this._process(!!'flush');
+	            } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ {
+	                // Process final blocks
+	                finalProcessedBlocks = this._process(!!'flush');
+
+	                // Unpad data
+	                padding.unpad(finalProcessedBlocks);
+	            }
+
+	            return finalProcessedBlocks;
+	        },
+
+	        blockSize: 128/32
+	    });
+
+	    /**
+	     * A collection of cipher parameters.
+	     *
+	     * @property {WordArray} ciphertext The raw ciphertext.
+	     * @property {WordArray} key The key to this ciphertext.
+	     * @property {WordArray} iv The IV used in the ciphering operation.
+	     * @property {WordArray} salt The salt used with a key derivation function.
+	     * @property {Cipher} algorithm The cipher algorithm.
+	     * @property {Mode} mode The block mode used in the ciphering operation.
+	     * @property {Padding} padding The padding scheme used in the ciphering operation.
+	     * @property {number} blockSize The block size of the cipher.
+	     * @property {Format} formatter The default formatting strategy to convert this cipher params object to a string.
+	     */
+	    var CipherParams = C_lib.CipherParams = Base.extend({
+	        /**
+	         * Initializes a newly created cipher params object.
+	         *
+	         * @param {Object} cipherParams An object with any of the possible cipher parameters.
+	         *
+	         * @example
+	         *
+	         *     var cipherParams = CryptoJS.lib.CipherParams.create({
+	         *         ciphertext: ciphertextWordArray,
+	         *         key: keyWordArray,
+	         *         iv: ivWordArray,
+	         *         salt: saltWordArray,
+	         *         algorithm: CryptoJS.algo.AES,
+	         *         mode: CryptoJS.mode.CBC,
+	         *         padding: CryptoJS.pad.PKCS7,
+	         *         blockSize: 4,
+	         *         formatter: CryptoJS.format.OpenSSL
+	         *     });
+	         */
+	        init: function (cipherParams) {
+	            this.mixIn(cipherParams);
+	        },
+
+	        /**
+	         * Converts this cipher params object to a string.
+	         *
+	         * @param {Format} formatter (Optional) The formatting strategy to use.
+	         *
+	         * @return {string} The stringified cipher params.
+	         *
+	         * @throws Error If neither the formatter nor the default formatter is set.
+	         *
+	         * @example
+	         *
+	         *     var string = cipherParams + '';
+	         *     var string = cipherParams.toString();
+	         *     var string = cipherParams.toString(CryptoJS.format.OpenSSL);
+	         */
+	        toString: function (formatter) {
+	            return (formatter || this.formatter).stringify(this);
+	        }
+	    });
+
+	    /**
+	     * Format namespace.
+	     */
+	    var C_format = C.format = {};
+
+	    /**
+	     * OpenSSL formatting strategy.
+	     */
+	    var OpenSSLFormatter = C_format.OpenSSL = {
+	        /**
+	         * Converts a cipher params object to an OpenSSL-compatible string.
+	         *
+	         * @param {CipherParams} cipherParams The cipher params object.
+	         *
+	         * @return {string} The OpenSSL-compatible string.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var openSSLString = CryptoJS.format.OpenSSL.stringify(cipherParams);
+	         */
+	        stringify: function (cipherParams) {
+	            var wordArray;
+
+	            // Shortcuts
+	            var ciphertext = cipherParams.ciphertext;
+	            var salt = cipherParams.salt;
+
+	            // Format
+	            if (salt) {
+	                wordArray = WordArray.create([0x53616c74, 0x65645f5f]).concat(salt).concat(ciphertext);
+	            } else {
+	                wordArray = ciphertext;
+	            }
+
+	            return wordArray.toString(Base64);
+	        },
+
+	        /**
+	         * Converts an OpenSSL-compatible string to a cipher params object.
+	         *
+	         * @param {string} openSSLStr The OpenSSL-compatible string.
+	         *
+	         * @return {CipherParams} The cipher params object.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var cipherParams = CryptoJS.format.OpenSSL.parse(openSSLString);
+	         */
+	        parse: function (openSSLStr) {
+	            var salt;
+
+	            // Parse base64
+	            var ciphertext = Base64.parse(openSSLStr);
+
+	            // Shortcut
+	            var ciphertextWords = ciphertext.words;
+
+	            // Test for salt
+	            if (ciphertextWords[0] == 0x53616c74 && ciphertextWords[1] == 0x65645f5f) {
+	                // Extract salt
+	                salt = WordArray.create(ciphertextWords.slice(2, 4));
+
+	                // Remove salt from ciphertext
+	                ciphertextWords.splice(0, 4);
+	                ciphertext.sigBytes -= 16;
+	            }
+
+	            return CipherParams.create({ ciphertext: ciphertext, salt: salt });
+	        }
+	    };
+
+	    /**
+	     * A cipher wrapper that returns ciphertext as a serializable cipher params object.
+	     */
+	    var SerializableCipher = C_lib.SerializableCipher = Base.extend({
+	        /**
+	         * Configuration options.
+	         *
+	         * @property {Formatter} format The formatting strategy to convert cipher param objects to and from a string. Default: OpenSSL
+	         */
+	        cfg: Base.extend({
+	            format: OpenSSLFormatter
+	        }),
+
+	        /**
+	         * Encrypts a message.
+	         *
+	         * @param {Cipher} cipher The cipher algorithm to use.
+	         * @param {WordArray|string} message The message to encrypt.
+	         * @param {WordArray} key The key.
+	         * @param {Object} cfg (Optional) The configuration options to use for this operation.
+	         *
+	         * @return {CipherParams} A cipher params object.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key);
+	         *     var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv });
+	         *     var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv, format: CryptoJS.format.OpenSSL });
+	         */
+	        encrypt: function (cipher, message, key, cfg) {
+	            // Apply config defaults
+	            cfg = this.cfg.extend(cfg);
+
+	            // Encrypt
+	            var encryptor = cipher.createEncryptor(key, cfg);
+	            var ciphertext = encryptor.finalize(message);
+
+	            // Shortcut
+	            var cipherCfg = encryptor.cfg;
+
+	            // Create and return serializable cipher params
+	            return CipherParams.create({
+	                ciphertext: ciphertext,
+	                key: key,
+	                iv: cipherCfg.iv,
+	                algorithm: cipher,
+	                mode: cipherCfg.mode,
+	                padding: cipherCfg.padding,
+	                blockSize: cipher.blockSize,
+	                formatter: cfg.format
+	            });
+	        },
+
+	        /**
+	         * Decrypts serialized ciphertext.
+	         *
+	         * @param {Cipher} cipher The cipher algorithm to use.
+	         * @param {CipherParams|string} ciphertext The ciphertext to decrypt.
+	         * @param {WordArray} key The key.
+	         * @param {Object} cfg (Optional) The configuration options to use for this operation.
+	         *
+	         * @return {WordArray} The plaintext.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, key, { iv: iv, format: CryptoJS.format.OpenSSL });
+	         *     var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, key, { iv: iv, format: CryptoJS.format.OpenSSL });
+	         */
+	        decrypt: function (cipher, ciphertext, key, cfg) {
+	            // Apply config defaults
+	            cfg = this.cfg.extend(cfg);
+
+	            // Convert string to CipherParams
+	            ciphertext = this._parse(ciphertext, cfg.format);
+
+	            // Decrypt
+	            var plaintext = cipher.createDecryptor(key, cfg).finalize(ciphertext.ciphertext);
+
+	            return plaintext;
+	        },
+
+	        /**
+	         * Converts serialized ciphertext to CipherParams,
+	         * else assumed CipherParams already and returns ciphertext unchanged.
+	         *
+	         * @param {CipherParams|string} ciphertext The ciphertext.
+	         * @param {Formatter} format The formatting strategy to use to parse serialized ciphertext.
+	         *
+	         * @return {CipherParams} The unserialized ciphertext.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var ciphertextParams = CryptoJS.lib.SerializableCipher._parse(ciphertextStringOrParams, format);
+	         */
+	        _parse: function (ciphertext, format) {
+	            if (typeof ciphertext == 'string') {
+	                return format.parse(ciphertext, this);
+	            } else {
+	                return ciphertext;
+	            }
+	        }
+	    });
+
+	    /**
+	     * Key derivation function namespace.
+	     */
+	    var C_kdf = C.kdf = {};
+
+	    /**
+	     * OpenSSL key derivation function.
+	     */
+	    var OpenSSLKdf = C_kdf.OpenSSL = {
+	        /**
+	         * Derives a key and IV from a password.
+	         *
+	         * @param {string} password The password to derive from.
+	         * @param {number} keySize The size in words of the key to generate.
+	         * @param {number} ivSize The size in words of the IV to generate.
+	         * @param {WordArray|string} salt (Optional) A 64-bit salt to use. If omitted, a salt will be generated randomly.
+	         *
+	         * @return {CipherParams} A cipher params object with the key, IV, and salt.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32);
+	         *     var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32, 'saltsalt');
+	         */
+	        execute: function (password, keySize, ivSize, salt, hasher) {
+	            // Generate random salt
+	            if (!salt) {
+	                salt = WordArray.random(64/8);
+	            }
+
+	            // Derive key and IV
+	            if (!hasher) {
+	                var key = EvpKDF.create({ keySize: keySize + ivSize }).compute(password, salt);
+	            } else {
+	                var key = EvpKDF.create({ keySize: keySize + ivSize, hasher: hasher }).compute(password, salt);
+	            }
+
+
+	            // Separate key and IV
+	            var iv = WordArray.create(key.words.slice(keySize), ivSize * 4);
+	            key.sigBytes = keySize * 4;
+
+	            // Return params
+	            return CipherParams.create({ key: key, iv: iv, salt: salt });
+	        }
+	    };
+
+	    /**
+	     * A serializable cipher wrapper that derives the key from a password,
+	     * and returns ciphertext as a serializable cipher params object.
+	     */
+	    var PasswordBasedCipher = C_lib.PasswordBasedCipher = SerializableCipher.extend({
+	        /**
+	         * Configuration options.
+	         *
+	         * @property {KDF} kdf The key derivation function to use to generate a key and IV from a password. Default: OpenSSL
+	         */
+	        cfg: SerializableCipher.cfg.extend({
+	            kdf: OpenSSLKdf
+	        }),
+
+	        /**
+	         * Encrypts a message using a password.
+	         *
+	         * @param {Cipher} cipher The cipher algorithm to use.
+	         * @param {WordArray|string} message The message to encrypt.
+	         * @param {string} password The password.
+	         * @param {Object} cfg (Optional) The configuration options to use for this operation.
+	         *
+	         * @return {CipherParams} A cipher params object.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password');
+	         *     var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password', { format: CryptoJS.format.OpenSSL });
+	         */
+	        encrypt: function (cipher, message, password, cfg) {
+	            // Apply config defaults
+	            cfg = this.cfg.extend(cfg);
+
+	            // Derive key and other params
+	            var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, cfg.salt, cfg.hasher);
+
+	            // Add IV to config
+	            cfg.iv = derivedParams.iv;
+
+	            // Encrypt
+	            var ciphertext = SerializableCipher.encrypt.call(this, cipher, message, derivedParams.key, cfg);
+
+	            // Mix in derived params
+	            ciphertext.mixIn(derivedParams);
+
+	            return ciphertext;
+	        },
+
+	        /**
+	         * Decrypts serialized ciphertext using a password.
+	         *
+	         * @param {Cipher} cipher The cipher algorithm to use.
+	         * @param {CipherParams|string} ciphertext The ciphertext to decrypt.
+	         * @param {string} password The password.
+	         * @param {Object} cfg (Optional) The configuration options to use for this operation.
+	         *
+	         * @return {WordArray} The plaintext.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, 'password', { format: CryptoJS.format.OpenSSL });
+	         *     var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, 'password', { format: CryptoJS.format.OpenSSL });
+	         */
+	        decrypt: function (cipher, ciphertext, password, cfg) {
+	            // Apply config defaults
+	            cfg = this.cfg.extend(cfg);
+
+	            // Convert string to CipherParams
+	            ciphertext = this._parse(ciphertext, cfg.format);
+
+	            // Derive key and other params
+	            var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, ciphertext.salt, cfg.hasher);
+
+	            // Add IV to config
+	            cfg.iv = derivedParams.iv;
+
+	            // Decrypt
+	            var plaintext = SerializableCipher.decrypt.call(this, cipher, ciphertext, derivedParams.key, cfg);
+
+	            return plaintext;
+	        }
+	    });
+	}());
+
+
+}));

+ 807 - 0
crypto-js/core.js

@@ -0,0 +1,807 @@
+;(function (root, factory) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory();
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define([], factory);
+	}
+	else {
+		// Global (browser)
+		root.CryptoJS = factory();
+	}
+}(this, function () {
+
+	/*globals window, global, require*/
+
+	/**
+	 * CryptoJS core components.
+	 */
+	var CryptoJS = CryptoJS || (function (Math, undefined) {
+
+	    var crypto;
+
+	    // Native crypto from window (Browser)
+	    if (typeof window !== 'undefined' && window.crypto) {
+	        crypto = window.crypto;
+	    }
+
+	    // Native crypto in web worker (Browser)
+	    if (typeof self !== 'undefined' && self.crypto) {
+	        crypto = self.crypto;
+	    }
+
+	    // Native crypto from worker
+	    if (typeof globalThis !== 'undefined' && globalThis.crypto) {
+	        crypto = globalThis.crypto;
+	    }
+
+	    // Native (experimental IE 11) crypto from window (Browser)
+	    if (!crypto && typeof window !== 'undefined' && window.msCrypto) {
+	        crypto = window.msCrypto;
+	    }
+
+	    // Native crypto from global (NodeJS)
+	    if (!crypto && typeof global !== 'undefined' && global.crypto) {
+	        crypto = global.crypto;
+	    }
+
+	    // Native crypto import via require (NodeJS)
+	    if (!crypto && typeof require === 'function') {
+	        try {
+	            crypto = require('crypto');
+	        } catch (err) {}
+	    }
+
+	    /*
+	     * Cryptographically secure pseudorandom number generator
+	     *
+	     * As Math.random() is cryptographically not safe to use
+	     */
+	    var cryptoSecureRandomInt = function () {
+	        if (crypto) {
+	            // Use getRandomValues method (Browser)
+	            if (typeof crypto.getRandomValues === 'function') {
+	                try {
+	                    return crypto.getRandomValues(new Uint32Array(1))[0];
+	                } catch (err) {}
+	            }
+
+	            // Use randomBytes method (NodeJS)
+	            if (typeof crypto.randomBytes === 'function') {
+	                try {
+	                    return crypto.randomBytes(4).readInt32LE();
+	                } catch (err) {}
+	            }
+	        }
+
+	        throw new Error('Native crypto module could not be used to get secure random number.');
+	    };
+
+	    /*
+	     * Local polyfill of Object.create
+
+	     */
+	    var create = Object.create || (function () {
+	        function F() {}
+
+	        return function (obj) {
+	            var subtype;
+
+	            F.prototype = obj;
+
+	            subtype = new F();
+
+	            F.prototype = null;
+
+	            return subtype;
+	        };
+	    }());
+
+	    /**
+	     * CryptoJS namespace.
+	     */
+	    var C = {};
+
+	    /**
+	     * Library namespace.
+	     */
+	    var C_lib = C.lib = {};
+
+	    /**
+	     * Base object for prototypal inheritance.
+	     */
+	    var Base = C_lib.Base = (function () {
+
+
+	        return {
+	            /**
+	             * Creates a new object that inherits from this object.
+	             *
+	             * @param {Object} overrides Properties to copy into the new object.
+	             *
+	             * @return {Object} The new object.
+	             *
+	             * @static
+	             *
+	             * @example
+	             *
+	             *     var MyType = CryptoJS.lib.Base.extend({
+	             *         field: 'value',
+	             *
+	             *         method: function () {
+	             *         }
+	             *     });
+	             */
+	            extend: function (overrides) {
+	                // Spawn
+	                var subtype = create(this);
+
+	                // Augment
+	                if (overrides) {
+	                    subtype.mixIn(overrides);
+	                }
+
+	                // Create default initializer
+	                if (!subtype.hasOwnProperty('init') || this.init === subtype.init) {
+	                    subtype.init = function () {
+	                        subtype.$super.init.apply(this, arguments);
+	                    };
+	                }
+
+	                // Initializer's prototype is the subtype object
+	                subtype.init.prototype = subtype;
+
+	                // Reference supertype
+	                subtype.$super = this;
+
+	                return subtype;
+	            },
+
+	            /**
+	             * Extends this object and runs the init method.
+	             * Arguments to create() will be passed to init().
+	             *
+	             * @return {Object} The new object.
+	             *
+	             * @static
+	             *
+	             * @example
+	             *
+	             *     var instance = MyType.create();
+	             */
+	            create: function () {
+	                var instance = this.extend();
+	                instance.init.apply(instance, arguments);
+
+	                return instance;
+	            },
+
+	            /**
+	             * Initializes a newly created object.
+	             * Override this method to add some logic when your objects are created.
+	             *
+	             * @example
+	             *
+	             *     var MyType = CryptoJS.lib.Base.extend({
+	             *         init: function () {
+	             *             // ...
+	             *         }
+	             *     });
+	             */
+	            init: function () {
+	            },
+
+	            /**
+	             * Copies properties into this object.
+	             *
+	             * @param {Object} properties The properties to mix in.
+	             *
+	             * @example
+	             *
+	             *     MyType.mixIn({
+	             *         field: 'value'
+	             *     });
+	             */
+	            mixIn: function (properties) {
+	                for (var propertyName in properties) {
+	                    if (properties.hasOwnProperty(propertyName)) {
+	                        this[propertyName] = properties[propertyName];
+	                    }
+	                }
+
+	                // IE won't copy toString using the loop above
+	                if (properties.hasOwnProperty('toString')) {
+	                    this.toString = properties.toString;
+	                }
+	            },
+
+	            /**
+	             * Creates a copy of this object.
+	             *
+	             * @return {Object} The clone.
+	             *
+	             * @example
+	             *
+	             *     var clone = instance.clone();
+	             */
+	            clone: function () {
+	                return this.init.prototype.extend(this);
+	            }
+	        };
+	    }());
+
+	    /**
+	     * An array of 32-bit words.
+	     *
+	     * @property {Array} words The array of 32-bit words.
+	     * @property {number} sigBytes The number of significant bytes in this word array.
+	     */
+	    var WordArray = C_lib.WordArray = Base.extend({
+	        /**
+	         * Initializes a newly created word array.
+	         *
+	         * @param {Array} words (Optional) An array of 32-bit words.
+	         * @param {number} sigBytes (Optional) The number of significant bytes in the words.
+	         *
+	         * @example
+	         *
+	         *     var wordArray = CryptoJS.lib.WordArray.create();
+	         *     var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]);
+	         *     var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6);
+	         */
+	        init: function (words, sigBytes) {
+	            words = this.words = words || [];
+
+	            if (sigBytes != undefined) {
+	                this.sigBytes = sigBytes;
+	            } else {
+	                this.sigBytes = words.length * 4;
+	            }
+	        },
+
+	        /**
+	         * Converts this word array to a string.
+	         *
+	         * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex
+	         *
+	         * @return {string} The stringified word array.
+	         *
+	         * @example
+	         *
+	         *     var string = wordArray + '';
+	         *     var string = wordArray.toString();
+	         *     var string = wordArray.toString(CryptoJS.enc.Utf8);
+	         */
+	        toString: function (encoder) {
+	            return (encoder || Hex).stringify(this);
+	        },
+
+	        /**
+	         * Concatenates a word array to this word array.
+	         *
+	         * @param {WordArray} wordArray The word array to append.
+	         *
+	         * @return {WordArray} This word array.
+	         *
+	         * @example
+	         *
+	         *     wordArray1.concat(wordArray2);
+	         */
+	        concat: function (wordArray) {
+	            // Shortcuts
+	            var thisWords = this.words;
+	            var thatWords = wordArray.words;
+	            var thisSigBytes = this.sigBytes;
+	            var thatSigBytes = wordArray.sigBytes;
+
+	            // Clamp excess bits
+	            this.clamp();
+
+	            // Concat
+	            if (thisSigBytes % 4) {
+	                // Copy one byte at a time
+	                for (var i = 0; i < thatSigBytes; i++) {
+	                    var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
+	                    thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8);
+	                }
+	            } else {
+	                // Copy one word at a time
+	                for (var j = 0; j < thatSigBytes; j += 4) {
+	                    thisWords[(thisSigBytes + j) >>> 2] = thatWords[j >>> 2];
+	                }
+	            }
+	            this.sigBytes += thatSigBytes;
+
+	            // Chainable
+	            return this;
+	        },
+
+	        /**
+	         * Removes insignificant bits.
+	         *
+	         * @example
+	         *
+	         *     wordArray.clamp();
+	         */
+	        clamp: function () {
+	            // Shortcuts
+	            var words = this.words;
+	            var sigBytes = this.sigBytes;
+
+	            // Clamp
+	            words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8);
+	            words.length = Math.ceil(sigBytes / 4);
+	        },
+
+	        /**
+	         * Creates a copy of this word array.
+	         *
+	         * @return {WordArray} The clone.
+	         *
+	         * @example
+	         *
+	         *     var clone = wordArray.clone();
+	         */
+	        clone: function () {
+	            var clone = Base.clone.call(this);
+	            clone.words = this.words.slice(0);
+
+	            return clone;
+	        },
+
+	        /**
+	         * Creates a word array filled with random bytes.
+	         *
+	         * @param {number} nBytes The number of random bytes to generate.
+	         *
+	         * @return {WordArray} The random word array.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var wordArray = CryptoJS.lib.WordArray.random(16);
+	         */
+	        random: function (nBytes) {
+	            var words = [];
+
+	            for (var i = 0; i < nBytes; i += 4) {
+	                words.push(cryptoSecureRandomInt());
+	            }
+
+	            return new WordArray.init(words, nBytes);
+	        }
+	    });
+
+	    /**
+	     * Encoder namespace.
+	     */
+	    var C_enc = C.enc = {};
+
+	    /**
+	     * Hex encoding strategy.
+	     */
+	    var Hex = C_enc.Hex = {
+	        /**
+	         * Converts a word array to a hex string.
+	         *
+	         * @param {WordArray} wordArray The word array.
+	         *
+	         * @return {string} The hex string.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var hexString = CryptoJS.enc.Hex.stringify(wordArray);
+	         */
+	        stringify: function (wordArray) {
+	            // Shortcuts
+	            var words = wordArray.words;
+	            var sigBytes = wordArray.sigBytes;
+
+	            // Convert
+	            var hexChars = [];
+	            for (var i = 0; i < sigBytes; i++) {
+	                var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
+	                hexChars.push((bite >>> 4).toString(16));
+	                hexChars.push((bite & 0x0f).toString(16));
+	            }
+
+	            return hexChars.join('');
+	        },
+
+	        /**
+	         * Converts a hex string to a word array.
+	         *
+	         * @param {string} hexStr The hex string.
+	         *
+	         * @return {WordArray} The word array.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var wordArray = CryptoJS.enc.Hex.parse(hexString);
+	         */
+	        parse: function (hexStr) {
+	            // Shortcut
+	            var hexStrLength = hexStr.length;
+
+	            // Convert
+	            var words = [];
+	            for (var i = 0; i < hexStrLength; i += 2) {
+	                words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4);
+	            }
+
+	            return new WordArray.init(words, hexStrLength / 2);
+	        }
+	    };
+
+	    /**
+	     * Latin1 encoding strategy.
+	     */
+	    var Latin1 = C_enc.Latin1 = {
+	        /**
+	         * Converts a word array to a Latin1 string.
+	         *
+	         * @param {WordArray} wordArray The word array.
+	         *
+	         * @return {string} The Latin1 string.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var latin1String = CryptoJS.enc.Latin1.stringify(wordArray);
+	         */
+	        stringify: function (wordArray) {
+	            // Shortcuts
+	            var words = wordArray.words;
+	            var sigBytes = wordArray.sigBytes;
+
+	            // Convert
+	            var latin1Chars = [];
+	            for (var i = 0; i < sigBytes; i++) {
+	                var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
+	                latin1Chars.push(String.fromCharCode(bite));
+	            }
+
+	            return latin1Chars.join('');
+	        },
+
+	        /**
+	         * Converts a Latin1 string to a word array.
+	         *
+	         * @param {string} latin1Str The Latin1 string.
+	         *
+	         * @return {WordArray} The word array.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var wordArray = CryptoJS.enc.Latin1.parse(latin1String);
+	         */
+	        parse: function (latin1Str) {
+	            // Shortcut
+	            var latin1StrLength = latin1Str.length;
+
+	            // Convert
+	            var words = [];
+	            for (var i = 0; i < latin1StrLength; i++) {
+	                words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8);
+	            }
+
+	            return new WordArray.init(words, latin1StrLength);
+	        }
+	    };
+
+	    /**
+	     * UTF-8 encoding strategy.
+	     */
+	    var Utf8 = C_enc.Utf8 = {
+	        /**
+	         * Converts a word array to a UTF-8 string.
+	         *
+	         * @param {WordArray} wordArray The word array.
+	         *
+	         * @return {string} The UTF-8 string.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var utf8String = CryptoJS.enc.Utf8.stringify(wordArray);
+	         */
+	        stringify: function (wordArray) {
+	            try {
+	                return decodeURIComponent(escape(Latin1.stringify(wordArray)));
+	            } catch (e) {
+	                throw new Error('Malformed UTF-8 data');
+	            }
+	        },
+
+	        /**
+	         * Converts a UTF-8 string to a word array.
+	         *
+	         * @param {string} utf8Str The UTF-8 string.
+	         *
+	         * @return {WordArray} The word array.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var wordArray = CryptoJS.enc.Utf8.parse(utf8String);
+	         */
+	        parse: function (utf8Str) {
+	            return Latin1.parse(unescape(encodeURIComponent(utf8Str)));
+	        }
+	    };
+
+	    /**
+	     * Abstract buffered block algorithm template.
+	     *
+	     * The property blockSize must be implemented in a concrete subtype.
+	     *
+	     * @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0
+	     */
+	    var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({
+	        /**
+	         * Resets this block algorithm's data buffer to its initial state.
+	         *
+	         * @example
+	         *
+	         *     bufferedBlockAlgorithm.reset();
+	         */
+	        reset: function () {
+	            // Initial values
+	            this._data = new WordArray.init();
+	            this._nDataBytes = 0;
+	        },
+
+	        /**
+	         * Adds new data to this block algorithm's buffer.
+	         *
+	         * @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8.
+	         *
+	         * @example
+	         *
+	         *     bufferedBlockAlgorithm._append('data');
+	         *     bufferedBlockAlgorithm._append(wordArray);
+	         */
+	        _append: function (data) {
+	            // Convert string to WordArray, else assume WordArray already
+	            if (typeof data == 'string') {
+	                data = Utf8.parse(data);
+	            }
+
+	            // Append
+	            this._data.concat(data);
+	            this._nDataBytes += data.sigBytes;
+	        },
+
+	        /**
+	         * Processes available data blocks.
+	         *
+	         * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype.
+	         *
+	         * @param {boolean} doFlush Whether all blocks and partial blocks should be processed.
+	         *
+	         * @return {WordArray} The processed data.
+	         *
+	         * @example
+	         *
+	         *     var processedData = bufferedBlockAlgorithm._process();
+	         *     var processedData = bufferedBlockAlgorithm._process(!!'flush');
+	         */
+	        _process: function (doFlush) {
+	            var processedWords;
+
+	            // Shortcuts
+	            var data = this._data;
+	            var dataWords = data.words;
+	            var dataSigBytes = data.sigBytes;
+	            var blockSize = this.blockSize;
+	            var blockSizeBytes = blockSize * 4;
+
+	            // Count blocks ready
+	            var nBlocksReady = dataSigBytes / blockSizeBytes;
+	            if (doFlush) {
+	                // Round up to include partial blocks
+	                nBlocksReady = Math.ceil(nBlocksReady);
+	            } else {
+	                // Round down to include only full blocks,
+	                // less the number of blocks that must remain in the buffer
+	                nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0);
+	            }
+
+	            // Count words ready
+	            var nWordsReady = nBlocksReady * blockSize;
+
+	            // Count bytes ready
+	            var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes);
+
+	            // Process blocks
+	            if (nWordsReady) {
+	                for (var offset = 0; offset < nWordsReady; offset += blockSize) {
+	                    // Perform concrete-algorithm logic
+	                    this._doProcessBlock(dataWords, offset);
+	                }
+
+	                // Remove processed words
+	                processedWords = dataWords.splice(0, nWordsReady);
+	                data.sigBytes -= nBytesReady;
+	            }
+
+	            // Return processed words
+	            return new WordArray.init(processedWords, nBytesReady);
+	        },
+
+	        /**
+	         * Creates a copy of this object.
+	         *
+	         * @return {Object} The clone.
+	         *
+	         * @example
+	         *
+	         *     var clone = bufferedBlockAlgorithm.clone();
+	         */
+	        clone: function () {
+	            var clone = Base.clone.call(this);
+	            clone._data = this._data.clone();
+
+	            return clone;
+	        },
+
+	        _minBufferSize: 0
+	    });
+
+	    /**
+	     * Abstract hasher template.
+	     *
+	     * @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits)
+	     */
+	    var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({
+	        /**
+	         * Configuration options.
+	         */
+	        cfg: Base.extend(),
+
+	        /**
+	         * Initializes a newly created hasher.
+	         *
+	         * @param {Object} cfg (Optional) The configuration options to use for this hash computation.
+	         *
+	         * @example
+	         *
+	         *     var hasher = CryptoJS.algo.SHA256.create();
+	         */
+	        init: function (cfg) {
+	            // Apply config defaults
+	            this.cfg = this.cfg.extend(cfg);
+
+	            // Set initial values
+	            this.reset();
+	        },
+
+	        /**
+	         * Resets this hasher to its initial state.
+	         *
+	         * @example
+	         *
+	         *     hasher.reset();
+	         */
+	        reset: function () {
+	            // Reset data buffer
+	            BufferedBlockAlgorithm.reset.call(this);
+
+	            // Perform concrete-hasher logic
+	            this._doReset();
+	        },
+
+	        /**
+	         * Updates this hasher with a message.
+	         *
+	         * @param {WordArray|string} messageUpdate The message to append.
+	         *
+	         * @return {Hasher} This hasher.
+	         *
+	         * @example
+	         *
+	         *     hasher.update('message');
+	         *     hasher.update(wordArray);
+	         */
+	        update: function (messageUpdate) {
+	            // Append
+	            this._append(messageUpdate);
+
+	            // Update the hash
+	            this._process();
+
+	            // Chainable
+	            return this;
+	        },
+
+	        /**
+	         * Finalizes the hash computation.
+	         * Note that the finalize operation is effectively a destructive, read-once operation.
+	         *
+	         * @param {WordArray|string} messageUpdate (Optional) A final message update.
+	         *
+	         * @return {WordArray} The hash.
+	         *
+	         * @example
+	         *
+	         *     var hash = hasher.finalize();
+	         *     var hash = hasher.finalize('message');
+	         *     var hash = hasher.finalize(wordArray);
+	         */
+	        finalize: function (messageUpdate) {
+	            // Final message update
+	            if (messageUpdate) {
+	                this._append(messageUpdate);
+	            }
+
+	            // Perform concrete-hasher logic
+	            var hash = this._doFinalize();
+
+	            return hash;
+	        },
+
+	        blockSize: 512/32,
+
+	        /**
+	         * Creates a shortcut function to a hasher's object interface.
+	         *
+	         * @param {Hasher} hasher The hasher to create a helper for.
+	         *
+	         * @return {Function} The shortcut function.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256);
+	         */
+	        _createHelper: function (hasher) {
+	            return function (message, cfg) {
+	                return new hasher.init(cfg).finalize(message);
+	            };
+	        },
+
+	        /**
+	         * Creates a shortcut function to the HMAC's object interface.
+	         *
+	         * @param {Hasher} hasher The hasher to use in this HMAC helper.
+	         *
+	         * @return {Function} The shortcut function.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256);
+	         */
+	        _createHmacHelper: function (hasher) {
+	            return function (message, key) {
+	                return new C_algo.HMAC.init(hasher, key).finalize(message);
+	            };
+	        }
+	    });
+
+	    /**
+	     * Algorithm namespace.
+	     */
+	    var C_algo = C.algo = {};
+
+	    return C;
+	}(Math));
+
+
+	return CryptoJS;
+
+}));

Разница между файлами не показана из-за своего большого размера
+ 6657 - 0
crypto-js/crypto-js.js


+ 136 - 0
crypto-js/enc-base64.js

@@ -0,0 +1,136 @@
+;(function (root, factory) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	(function () {
+	    // Shortcuts
+	    var C = CryptoJS;
+	    var C_lib = C.lib;
+	    var WordArray = C_lib.WordArray;
+	    var C_enc = C.enc;
+
+	    /**
+	     * Base64 encoding strategy.
+	     */
+	    var Base64 = C_enc.Base64 = {
+	        /**
+	         * Converts a word array to a Base64 string.
+	         *
+	         * @param {WordArray} wordArray The word array.
+	         *
+	         * @return {string} The Base64 string.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var base64String = CryptoJS.enc.Base64.stringify(wordArray);
+	         */
+	        stringify: function (wordArray) {
+	            // Shortcuts
+	            var words = wordArray.words;
+	            var sigBytes = wordArray.sigBytes;
+	            var map = this._map;
+
+	            // Clamp excess bits
+	            wordArray.clamp();
+
+	            // Convert
+	            var base64Chars = [];
+	            for (var i = 0; i < sigBytes; i += 3) {
+	                var byte1 = (words[i >>> 2]       >>> (24 - (i % 4) * 8))       & 0xff;
+	                var byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff;
+	                var byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff;
+
+	                var triplet = (byte1 << 16) | (byte2 << 8) | byte3;
+
+	                for (var j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j++) {
+	                    base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f));
+	                }
+	            }
+
+	            // Add padding
+	            var paddingChar = map.charAt(64);
+	            if (paddingChar) {
+	                while (base64Chars.length % 4) {
+	                    base64Chars.push(paddingChar);
+	                }
+	            }
+
+	            return base64Chars.join('');
+	        },
+
+	        /**
+	         * Converts a Base64 string to a word array.
+	         *
+	         * @param {string} base64Str The Base64 string.
+	         *
+	         * @return {WordArray} The word array.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var wordArray = CryptoJS.enc.Base64.parse(base64String);
+	         */
+	        parse: function (base64Str) {
+	            // Shortcuts
+	            var base64StrLength = base64Str.length;
+	            var map = this._map;
+	            var reverseMap = this._reverseMap;
+
+	            if (!reverseMap) {
+	                    reverseMap = this._reverseMap = [];
+	                    for (var j = 0; j < map.length; j++) {
+	                        reverseMap[map.charCodeAt(j)] = j;
+	                    }
+	            }
+
+	            // Ignore padding
+	            var paddingChar = map.charAt(64);
+	            if (paddingChar) {
+	                var paddingIndex = base64Str.indexOf(paddingChar);
+	                if (paddingIndex !== -1) {
+	                    base64StrLength = paddingIndex;
+	                }
+	            }
+
+	            // Convert
+	            return parseLoop(base64Str, base64StrLength, reverseMap);
+
+	        },
+
+	        _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
+	    };
+
+	    function parseLoop(base64Str, base64StrLength, reverseMap) {
+	      var words = [];
+	      var nBytes = 0;
+	      for (var i = 0; i < base64StrLength; i++) {
+	          if (i % 4) {
+	              var bits1 = reverseMap[base64Str.charCodeAt(i - 1)] << ((i % 4) * 2);
+	              var bits2 = reverseMap[base64Str.charCodeAt(i)] >>> (6 - (i % 4) * 2);
+	              var bitsCombined = bits1 | bits2;
+	              words[nBytes >>> 2] |= bitsCombined << (24 - (nBytes % 4) * 8);
+	              nBytes++;
+	          }
+	      }
+	      return WordArray.create(words, nBytes);
+	    }
+	}());
+
+
+	return CryptoJS.enc.Base64;
+
+}));

+ 148 - 0
crypto-js/enc-base64url.js

@@ -0,0 +1,148 @@
+;(function (root, factory) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	(function () {
+	    // Shortcuts
+	    var C = CryptoJS;
+	    var C_lib = C.lib;
+	    var WordArray = C_lib.WordArray;
+	    var C_enc = C.enc;
+
+	    /**
+	     * Base64url encoding strategy.
+	     */
+	    var Base64url = C_enc.Base64url = {
+	        /**
+	         * Converts a word array to a Base64url string.
+	         *
+	         * @param {WordArray} wordArray The word array.
+	         *
+	         * @param {boolean} urlSafe Whether to use url safe
+	         *
+	         * @return {string} The Base64url string.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var base64String = CryptoJS.enc.Base64url.stringify(wordArray);
+	         */
+	        stringify: function (wordArray, urlSafe) {
+	            if (urlSafe === undefined) {
+	                urlSafe = true
+	            }
+	            // Shortcuts
+	            var words = wordArray.words;
+	            var sigBytes = wordArray.sigBytes;
+	            var map = urlSafe ? this._safe_map : this._map;
+
+	            // Clamp excess bits
+	            wordArray.clamp();
+
+	            // Convert
+	            var base64Chars = [];
+	            for (var i = 0; i < sigBytes; i += 3) {
+	                var byte1 = (words[i >>> 2]       >>> (24 - (i % 4) * 8))       & 0xff;
+	                var byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff;
+	                var byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff;
+
+	                var triplet = (byte1 << 16) | (byte2 << 8) | byte3;
+
+	                for (var j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j++) {
+	                    base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f));
+	                }
+	            }
+
+	            // Add padding
+	            var paddingChar = map.charAt(64);
+	            if (paddingChar) {
+	                while (base64Chars.length % 4) {
+	                    base64Chars.push(paddingChar);
+	                }
+	            }
+
+	            return base64Chars.join('');
+	        },
+
+	        /**
+	         * Converts a Base64url string to a word array.
+	         *
+	         * @param {string} base64Str The Base64url string.
+	         *
+	         * @param {boolean} urlSafe Whether to use url safe
+	         *
+	         * @return {WordArray} The word array.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var wordArray = CryptoJS.enc.Base64url.parse(base64String);
+	         */
+	        parse: function (base64Str, urlSafe) {
+	            if (urlSafe === undefined) {
+	                urlSafe = true
+	            }
+
+	            // Shortcuts
+	            var base64StrLength = base64Str.length;
+	            var map = urlSafe ? this._safe_map : this._map;
+	            var reverseMap = this._reverseMap;
+
+	            if (!reverseMap) {
+	                reverseMap = this._reverseMap = [];
+	                for (var j = 0; j < map.length; j++) {
+	                    reverseMap[map.charCodeAt(j)] = j;
+	                }
+	            }
+
+	            // Ignore padding
+	            var paddingChar = map.charAt(64);
+	            if (paddingChar) {
+	                var paddingIndex = base64Str.indexOf(paddingChar);
+	                if (paddingIndex !== -1) {
+	                    base64StrLength = paddingIndex;
+	                }
+	            }
+
+	            // Convert
+	            return parseLoop(base64Str, base64StrLength, reverseMap);
+
+	        },
+
+	        _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',
+	        _safe_map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_',
+	    };
+
+	    function parseLoop(base64Str, base64StrLength, reverseMap) {
+	        var words = [];
+	        var nBytes = 0;
+	        for (var i = 0; i < base64StrLength; i++) {
+	            if (i % 4) {
+	                var bits1 = reverseMap[base64Str.charCodeAt(i - 1)] << ((i % 4) * 2);
+	                var bits2 = reverseMap[base64Str.charCodeAt(i)] >>> (6 - (i % 4) * 2);
+	                var bitsCombined = bits1 | bits2;
+	                words[nBytes >>> 2] |= bitsCombined << (24 - (nBytes % 4) * 8);
+	                nBytes++;
+	            }
+	        }
+	        return WordArray.create(words, nBytes);
+	    }
+	}());
+
+
+	return CryptoJS.enc.Base64url;
+
+}));

+ 18 - 0
crypto-js/enc-hex.js

@@ -0,0 +1,18 @@
+;(function (root, factory) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	return CryptoJS.enc.Hex;
+
+}));

+ 18 - 0
crypto-js/enc-latin1.js

@@ -0,0 +1,18 @@
+;(function (root, factory) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	return CryptoJS.enc.Latin1;
+
+}));

+ 149 - 0
crypto-js/enc-utf16.js

@@ -0,0 +1,149 @@
+;(function (root, factory) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	(function () {
+	    // Shortcuts
+	    var C = CryptoJS;
+	    var C_lib = C.lib;
+	    var WordArray = C_lib.WordArray;
+	    var C_enc = C.enc;
+
+	    /**
+	     * UTF-16 BE encoding strategy.
+	     */
+	    var Utf16BE = C_enc.Utf16 = C_enc.Utf16BE = {
+	        /**
+	         * Converts a word array to a UTF-16 BE string.
+	         *
+	         * @param {WordArray} wordArray The word array.
+	         *
+	         * @return {string} The UTF-16 BE string.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var utf16String = CryptoJS.enc.Utf16.stringify(wordArray);
+	         */
+	        stringify: function (wordArray) {
+	            // Shortcuts
+	            var words = wordArray.words;
+	            var sigBytes = wordArray.sigBytes;
+
+	            // Convert
+	            var utf16Chars = [];
+	            for (var i = 0; i < sigBytes; i += 2) {
+	                var codePoint = (words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff;
+	                utf16Chars.push(String.fromCharCode(codePoint));
+	            }
+
+	            return utf16Chars.join('');
+	        },
+
+	        /**
+	         * Converts a UTF-16 BE string to a word array.
+	         *
+	         * @param {string} utf16Str The UTF-16 BE string.
+	         *
+	         * @return {WordArray} The word array.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var wordArray = CryptoJS.enc.Utf16.parse(utf16String);
+	         */
+	        parse: function (utf16Str) {
+	            // Shortcut
+	            var utf16StrLength = utf16Str.length;
+
+	            // Convert
+	            var words = [];
+	            for (var i = 0; i < utf16StrLength; i++) {
+	                words[i >>> 1] |= utf16Str.charCodeAt(i) << (16 - (i % 2) * 16);
+	            }
+
+	            return WordArray.create(words, utf16StrLength * 2);
+	        }
+	    };
+
+	    /**
+	     * UTF-16 LE encoding strategy.
+	     */
+	    C_enc.Utf16LE = {
+	        /**
+	         * Converts a word array to a UTF-16 LE string.
+	         *
+	         * @param {WordArray} wordArray The word array.
+	         *
+	         * @return {string} The UTF-16 LE string.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var utf16Str = CryptoJS.enc.Utf16LE.stringify(wordArray);
+	         */
+	        stringify: function (wordArray) {
+	            // Shortcuts
+	            var words = wordArray.words;
+	            var sigBytes = wordArray.sigBytes;
+
+	            // Convert
+	            var utf16Chars = [];
+	            for (var i = 0; i < sigBytes; i += 2) {
+	                var codePoint = swapEndian((words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff);
+	                utf16Chars.push(String.fromCharCode(codePoint));
+	            }
+
+	            return utf16Chars.join('');
+	        },
+
+	        /**
+	         * Converts a UTF-16 LE string to a word array.
+	         *
+	         * @param {string} utf16Str The UTF-16 LE string.
+	         *
+	         * @return {WordArray} The word array.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var wordArray = CryptoJS.enc.Utf16LE.parse(utf16Str);
+	         */
+	        parse: function (utf16Str) {
+	            // Shortcut
+	            var utf16StrLength = utf16Str.length;
+
+	            // Convert
+	            var words = [];
+	            for (var i = 0; i < utf16StrLength; i++) {
+	                words[i >>> 1] |= swapEndian(utf16Str.charCodeAt(i) << (16 - (i % 2) * 16));
+	            }
+
+	            return WordArray.create(words, utf16StrLength * 2);
+	        }
+	    };
+
+	    function swapEndian(word) {
+	        return ((word << 8) & 0xff00ff00) | ((word >>> 8) & 0x00ff00ff);
+	    }
+	}());
+
+
+	return CryptoJS.enc.Utf16;
+
+}));

+ 18 - 0
crypto-js/enc-utf8.js

@@ -0,0 +1,18 @@
+;(function (root, factory) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	return CryptoJS.enc.Utf8;
+
+}));

+ 134 - 0
crypto-js/evpkdf.js

@@ -0,0 +1,134 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./sha1"), require("./hmac"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./sha1", "./hmac"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	(function () {
+	    // Shortcuts
+	    var C = CryptoJS;
+	    var C_lib = C.lib;
+	    var Base = C_lib.Base;
+	    var WordArray = C_lib.WordArray;
+	    var C_algo = C.algo;
+	    var MD5 = C_algo.MD5;
+
+	    /**
+	     * This key derivation function is meant to conform with EVP_BytesToKey.
+	     * www.openssl.org/docs/crypto/EVP_BytesToKey.html
+	     */
+	    var EvpKDF = C_algo.EvpKDF = Base.extend({
+	        /**
+	         * Configuration options.
+	         *
+	         * @property {number} keySize The key size in words to generate. Default: 4 (128 bits)
+	         * @property {Hasher} hasher The hash algorithm to use. Default: MD5
+	         * @property {number} iterations The number of iterations to perform. Default: 1
+	         */
+	        cfg: Base.extend({
+	            keySize: 128/32,
+	            hasher: MD5,
+	            iterations: 1
+	        }),
+
+	        /**
+	         * Initializes a newly created key derivation function.
+	         *
+	         * @param {Object} cfg (Optional) The configuration options to use for the derivation.
+	         *
+	         * @example
+	         *
+	         *     var kdf = CryptoJS.algo.EvpKDF.create();
+	         *     var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8 });
+	         *     var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8, iterations: 1000 });
+	         */
+	        init: function (cfg) {
+	            this.cfg = this.cfg.extend(cfg);
+	        },
+
+	        /**
+	         * Derives a key from a password.
+	         *
+	         * @param {WordArray|string} password The password.
+	         * @param {WordArray|string} salt A salt.
+	         *
+	         * @return {WordArray} The derived key.
+	         *
+	         * @example
+	         *
+	         *     var key = kdf.compute(password, salt);
+	         */
+	        compute: function (password, salt) {
+	            var block;
+
+	            // Shortcut
+	            var cfg = this.cfg;
+
+	            // Init hasher
+	            var hasher = cfg.hasher.create();
+
+	            // Initial values
+	            var derivedKey = WordArray.create();
+
+	            // Shortcuts
+	            var derivedKeyWords = derivedKey.words;
+	            var keySize = cfg.keySize;
+	            var iterations = cfg.iterations;
+
+	            // Generate key
+	            while (derivedKeyWords.length < keySize) {
+	                if (block) {
+	                    hasher.update(block);
+	                }
+	                block = hasher.update(password).finalize(salt);
+	                hasher.reset();
+
+	                // Iterations
+	                for (var i = 1; i < iterations; i++) {
+	                    block = hasher.finalize(block);
+	                    hasher.reset();
+	                }
+
+	                derivedKey.concat(block);
+	            }
+	            derivedKey.sigBytes = keySize * 4;
+
+	            return derivedKey;
+	        }
+	    });
+
+	    /**
+	     * Derives a key from a password.
+	     *
+	     * @param {WordArray|string} password The password.
+	     * @param {WordArray|string} salt A salt.
+	     * @param {Object} cfg (Optional) The configuration options to use for this computation.
+	     *
+	     * @return {WordArray} The derived key.
+	     *
+	     * @static
+	     *
+	     * @example
+	     *
+	     *     var key = CryptoJS.EvpKDF(password, salt);
+	     *     var key = CryptoJS.EvpKDF(password, salt, { keySize: 8 });
+	     *     var key = CryptoJS.EvpKDF(password, salt, { keySize: 8, iterations: 1000 });
+	     */
+	    C.EvpKDF = function (password, salt, cfg) {
+	        return EvpKDF.create(cfg).compute(password, salt);
+	    };
+	}());
+
+
+	return CryptoJS.EvpKDF;
+
+}));

+ 66 - 0
crypto-js/format-hex.js

@@ -0,0 +1,66 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./cipher-core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./cipher-core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	(function (undefined) {
+	    // Shortcuts
+	    var C = CryptoJS;
+	    var C_lib = C.lib;
+	    var CipherParams = C_lib.CipherParams;
+	    var C_enc = C.enc;
+	    var Hex = C_enc.Hex;
+	    var C_format = C.format;
+
+	    var HexFormatter = C_format.Hex = {
+	        /**
+	         * Converts the ciphertext of a cipher params object to a hexadecimally encoded string.
+	         *
+	         * @param {CipherParams} cipherParams The cipher params object.
+	         *
+	         * @return {string} The hexadecimally encoded string.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var hexString = CryptoJS.format.Hex.stringify(cipherParams);
+	         */
+	        stringify: function (cipherParams) {
+	            return cipherParams.ciphertext.toString(Hex);
+	        },
+
+	        /**
+	         * Converts a hexadecimally encoded ciphertext string to a cipher params object.
+	         *
+	         * @param {string} input The hexadecimally encoded string.
+	         *
+	         * @return {CipherParams} The cipher params object.
+	         *
+	         * @static
+	         *
+	         * @example
+	         *
+	         *     var cipherParams = CryptoJS.format.Hex.parse(hexString);
+	         */
+	        parse: function (input) {
+	            var ciphertext = Hex.parse(input);
+	            return CipherParams.create({ ciphertext: ciphertext });
+	        }
+	    };
+	}());
+
+
+	return CryptoJS.format.Hex;
+
+}));

+ 18 - 0
crypto-js/format-openssl.js

@@ -0,0 +1,18 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./cipher-core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./cipher-core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	return CryptoJS.format.OpenSSL;
+
+}));

+ 18 - 0
crypto-js/hmac-md5.js

@@ -0,0 +1,18 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./md5"), require("./hmac"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./md5", "./hmac"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	return CryptoJS.HmacMD5;
+
+}));

+ 18 - 0
crypto-js/hmac-ripemd160.js

@@ -0,0 +1,18 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./ripemd160"), require("./hmac"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./ripemd160", "./hmac"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	return CryptoJS.HmacRIPEMD160;
+
+}));

+ 18 - 0
crypto-js/hmac-sha1.js

@@ -0,0 +1,18 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./sha1"), require("./hmac"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./sha1", "./hmac"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	return CryptoJS.HmacSHA1;
+
+}));

+ 18 - 0
crypto-js/hmac-sha224.js

@@ -0,0 +1,18 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./sha256"), require("./sha224"), require("./hmac"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./sha256", "./sha224", "./hmac"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	return CryptoJS.HmacSHA224;
+
+}));

+ 18 - 0
crypto-js/hmac-sha256.js

@@ -0,0 +1,18 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./sha256"), require("./hmac"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./sha256", "./hmac"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	return CryptoJS.HmacSHA256;
+
+}));

+ 18 - 0
crypto-js/hmac-sha3.js

@@ -0,0 +1,18 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./x64-core"), require("./sha3"), require("./hmac"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./x64-core", "./sha3", "./hmac"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	return CryptoJS.HmacSHA3;
+
+}));

+ 18 - 0
crypto-js/hmac-sha384.js

@@ -0,0 +1,18 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./x64-core"), require("./sha512"), require("./sha384"), require("./hmac"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./x64-core", "./sha512", "./sha384", "./hmac"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	return CryptoJS.HmacSHA384;
+
+}));

+ 18 - 0
crypto-js/hmac-sha512.js

@@ -0,0 +1,18 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./x64-core"), require("./sha512"), require("./hmac"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./x64-core", "./sha512", "./hmac"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	return CryptoJS.HmacSHA512;
+
+}));

+ 143 - 0
crypto-js/hmac.js

@@ -0,0 +1,143 @@
+;(function (root, factory) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	(function () {
+	    // Shortcuts
+	    var C = CryptoJS;
+	    var C_lib = C.lib;
+	    var Base = C_lib.Base;
+	    var C_enc = C.enc;
+	    var Utf8 = C_enc.Utf8;
+	    var C_algo = C.algo;
+
+	    /**
+	     * HMAC algorithm.
+	     */
+	    var HMAC = C_algo.HMAC = Base.extend({
+	        /**
+	         * Initializes a newly created HMAC.
+	         *
+	         * @param {Hasher} hasher The hash algorithm to use.
+	         * @param {WordArray|string} key The secret key.
+	         *
+	         * @example
+	         *
+	         *     var hmacHasher = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key);
+	         */
+	        init: function (hasher, key) {
+	            // Init hasher
+	            hasher = this._hasher = new hasher.init();
+
+	            // Convert string to WordArray, else assume WordArray already
+	            if (typeof key == 'string') {
+	                key = Utf8.parse(key);
+	            }
+
+	            // Shortcuts
+	            var hasherBlockSize = hasher.blockSize;
+	            var hasherBlockSizeBytes = hasherBlockSize * 4;
+
+	            // Allow arbitrary length keys
+	            if (key.sigBytes > hasherBlockSizeBytes) {
+	                key = hasher.finalize(key);
+	            }
+
+	            // Clamp excess bits
+	            key.clamp();
+
+	            // Clone key for inner and outer pads
+	            var oKey = this._oKey = key.clone();
+	            var iKey = this._iKey = key.clone();
+
+	            // Shortcuts
+	            var oKeyWords = oKey.words;
+	            var iKeyWords = iKey.words;
+
+	            // XOR keys with pad constants
+	            for (var i = 0; i < hasherBlockSize; i++) {
+	                oKeyWords[i] ^= 0x5c5c5c5c;
+	                iKeyWords[i] ^= 0x36363636;
+	            }
+	            oKey.sigBytes = iKey.sigBytes = hasherBlockSizeBytes;
+
+	            // Set initial values
+	            this.reset();
+	        },
+
+	        /**
+	         * Resets this HMAC to its initial state.
+	         *
+	         * @example
+	         *
+	         *     hmacHasher.reset();
+	         */
+	        reset: function () {
+	            // Shortcut
+	            var hasher = this._hasher;
+
+	            // Reset
+	            hasher.reset();
+	            hasher.update(this._iKey);
+	        },
+
+	        /**
+	         * Updates this HMAC with a message.
+	         *
+	         * @param {WordArray|string} messageUpdate The message to append.
+	         *
+	         * @return {HMAC} This HMAC instance.
+	         *
+	         * @example
+	         *
+	         *     hmacHasher.update('message');
+	         *     hmacHasher.update(wordArray);
+	         */
+	        update: function (messageUpdate) {
+	            this._hasher.update(messageUpdate);
+
+	            // Chainable
+	            return this;
+	        },
+
+	        /**
+	         * Finalizes the HMAC computation.
+	         * Note that the finalize operation is effectively a destructive, read-once operation.
+	         *
+	         * @param {WordArray|string} messageUpdate (Optional) A final message update.
+	         *
+	         * @return {WordArray} The HMAC.
+	         *
+	         * @example
+	         *
+	         *     var hmac = hmacHasher.finalize();
+	         *     var hmac = hmacHasher.finalize('message');
+	         *     var hmac = hmacHasher.finalize(wordArray);
+	         */
+	        finalize: function (messageUpdate) {
+	            // Shortcut
+	            var hasher = this._hasher;
+
+	            // Compute HMAC
+	            var innerHash = hasher.finalize(messageUpdate);
+	            hasher.reset();
+	            var hmac = hasher.finalize(this._oKey.clone().concat(innerHash));
+
+	            return hmac;
+	        }
+	    });
+	}());
+
+
+}));

Разница между файлами не показана из-за своего большого размера
+ 18 - 0
crypto-js/index.js


+ 76 - 0
crypto-js/lib-typedarrays.js

@@ -0,0 +1,76 @@
+;(function (root, factory) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	(function () {
+	    // Check if typed arrays are supported
+	    if (typeof ArrayBuffer != 'function') {
+	        return;
+	    }
+
+	    // Shortcuts
+	    var C = CryptoJS;
+	    var C_lib = C.lib;
+	    var WordArray = C_lib.WordArray;
+
+	    // Reference original init
+	    var superInit = WordArray.init;
+
+	    // Augment WordArray.init to handle typed arrays
+	    var subInit = WordArray.init = function (typedArray) {
+	        // Convert buffers to uint8
+	        if (typedArray instanceof ArrayBuffer) {
+	            typedArray = new Uint8Array(typedArray);
+	        }
+
+	        // Convert other array views to uint8
+	        if (
+	            typedArray instanceof Int8Array ||
+	            (typeof Uint8ClampedArray !== "undefined" && typedArray instanceof Uint8ClampedArray) ||
+	            typedArray instanceof Int16Array ||
+	            typedArray instanceof Uint16Array ||
+	            typedArray instanceof Int32Array ||
+	            typedArray instanceof Uint32Array ||
+	            typedArray instanceof Float32Array ||
+	            typedArray instanceof Float64Array
+	        ) {
+	            typedArray = new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength);
+	        }
+
+	        // Handle Uint8Array
+	        if (typedArray instanceof Uint8Array) {
+	            // Shortcut
+	            var typedArrayByteLength = typedArray.byteLength;
+
+	            // Extract bytes
+	            var words = [];
+	            for (var i = 0; i < typedArrayByteLength; i++) {
+	                words[i >>> 2] |= typedArray[i] << (24 - (i % 4) * 8);
+	            }
+
+	            // Initialize this word array
+	            superInit.call(this, words, typedArrayByteLength);
+	        } else {
+	            // Else call normal init
+	            superInit.apply(this, arguments);
+	        }
+	    };
+
+	    subInit.prototype = WordArray;
+	}());
+
+
+	return CryptoJS.lib.WordArray;
+
+}));

+ 268 - 0
crypto-js/md5.js

@@ -0,0 +1,268 @@
+;(function (root, factory) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	(function (Math) {
+	    // Shortcuts
+	    var C = CryptoJS;
+	    var C_lib = C.lib;
+	    var WordArray = C_lib.WordArray;
+	    var Hasher = C_lib.Hasher;
+	    var C_algo = C.algo;
+
+	    // Constants table
+	    var T = [];
+
+	    // Compute constants
+	    (function () {
+	        for (var i = 0; i < 64; i++) {
+	            T[i] = (Math.abs(Math.sin(i + 1)) * 0x100000000) | 0;
+	        }
+	    }());
+
+	    /**
+	     * MD5 hash algorithm.
+	     */
+	    var MD5 = C_algo.MD5 = Hasher.extend({
+	        _doReset: function () {
+	            this._hash = new WordArray.init([
+	                0x67452301, 0xefcdab89,
+	                0x98badcfe, 0x10325476
+	            ]);
+	        },
+
+	        _doProcessBlock: function (M, offset) {
+	            // Swap endian
+	            for (var i = 0; i < 16; i++) {
+	                // Shortcuts
+	                var offset_i = offset + i;
+	                var M_offset_i = M[offset_i];
+
+	                M[offset_i] = (
+	                    (((M_offset_i << 8)  | (M_offset_i >>> 24)) & 0x00ff00ff) |
+	                    (((M_offset_i << 24) | (M_offset_i >>> 8))  & 0xff00ff00)
+	                );
+	            }
+
+	            // Shortcuts
+	            var H = this._hash.words;
+
+	            var M_offset_0  = M[offset + 0];
+	            var M_offset_1  = M[offset + 1];
+	            var M_offset_2  = M[offset + 2];
+	            var M_offset_3  = M[offset + 3];
+	            var M_offset_4  = M[offset + 4];
+	            var M_offset_5  = M[offset + 5];
+	            var M_offset_6  = M[offset + 6];
+	            var M_offset_7  = M[offset + 7];
+	            var M_offset_8  = M[offset + 8];
+	            var M_offset_9  = M[offset + 9];
+	            var M_offset_10 = M[offset + 10];
+	            var M_offset_11 = M[offset + 11];
+	            var M_offset_12 = M[offset + 12];
+	            var M_offset_13 = M[offset + 13];
+	            var M_offset_14 = M[offset + 14];
+	            var M_offset_15 = M[offset + 15];
+
+	            // Working variables
+	            var a = H[0];
+	            var b = H[1];
+	            var c = H[2];
+	            var d = H[3];
+
+	            // Computation
+	            a = FF(a, b, c, d, M_offset_0,  7,  T[0]);
+	            d = FF(d, a, b, c, M_offset_1,  12, T[1]);
+	            c = FF(c, d, a, b, M_offset_2,  17, T[2]);
+	            b = FF(b, c, d, a, M_offset_3,  22, T[3]);
+	            a = FF(a, b, c, d, M_offset_4,  7,  T[4]);
+	            d = FF(d, a, b, c, M_offset_5,  12, T[5]);
+	            c = FF(c, d, a, b, M_offset_6,  17, T[6]);
+	            b = FF(b, c, d, a, M_offset_7,  22, T[7]);
+	            a = FF(a, b, c, d, M_offset_8,  7,  T[8]);
+	            d = FF(d, a, b, c, M_offset_9,  12, T[9]);
+	            c = FF(c, d, a, b, M_offset_10, 17, T[10]);
+	            b = FF(b, c, d, a, M_offset_11, 22, T[11]);
+	            a = FF(a, b, c, d, M_offset_12, 7,  T[12]);
+	            d = FF(d, a, b, c, M_offset_13, 12, T[13]);
+	            c = FF(c, d, a, b, M_offset_14, 17, T[14]);
+	            b = FF(b, c, d, a, M_offset_15, 22, T[15]);
+
+	            a = GG(a, b, c, d, M_offset_1,  5,  T[16]);
+	            d = GG(d, a, b, c, M_offset_6,  9,  T[17]);
+	            c = GG(c, d, a, b, M_offset_11, 14, T[18]);
+	            b = GG(b, c, d, a, M_offset_0,  20, T[19]);
+	            a = GG(a, b, c, d, M_offset_5,  5,  T[20]);
+	            d = GG(d, a, b, c, M_offset_10, 9,  T[21]);
+	            c = GG(c, d, a, b, M_offset_15, 14, T[22]);
+	            b = GG(b, c, d, a, M_offset_4,  20, T[23]);
+	            a = GG(a, b, c, d, M_offset_9,  5,  T[24]);
+	            d = GG(d, a, b, c, M_offset_14, 9,  T[25]);
+	            c = GG(c, d, a, b, M_offset_3,  14, T[26]);
+	            b = GG(b, c, d, a, M_offset_8,  20, T[27]);
+	            a = GG(a, b, c, d, M_offset_13, 5,  T[28]);
+	            d = GG(d, a, b, c, M_offset_2,  9,  T[29]);
+	            c = GG(c, d, a, b, M_offset_7,  14, T[30]);
+	            b = GG(b, c, d, a, M_offset_12, 20, T[31]);
+
+	            a = HH(a, b, c, d, M_offset_5,  4,  T[32]);
+	            d = HH(d, a, b, c, M_offset_8,  11, T[33]);
+	            c = HH(c, d, a, b, M_offset_11, 16, T[34]);
+	            b = HH(b, c, d, a, M_offset_14, 23, T[35]);
+	            a = HH(a, b, c, d, M_offset_1,  4,  T[36]);
+	            d = HH(d, a, b, c, M_offset_4,  11, T[37]);
+	            c = HH(c, d, a, b, M_offset_7,  16, T[38]);
+	            b = HH(b, c, d, a, M_offset_10, 23, T[39]);
+	            a = HH(a, b, c, d, M_offset_13, 4,  T[40]);
+	            d = HH(d, a, b, c, M_offset_0,  11, T[41]);
+	            c = HH(c, d, a, b, M_offset_3,  16, T[42]);
+	            b = HH(b, c, d, a, M_offset_6,  23, T[43]);
+	            a = HH(a, b, c, d, M_offset_9,  4,  T[44]);
+	            d = HH(d, a, b, c, M_offset_12, 11, T[45]);
+	            c = HH(c, d, a, b, M_offset_15, 16, T[46]);
+	            b = HH(b, c, d, a, M_offset_2,  23, T[47]);
+
+	            a = II(a, b, c, d, M_offset_0,  6,  T[48]);
+	            d = II(d, a, b, c, M_offset_7,  10, T[49]);
+	            c = II(c, d, a, b, M_offset_14, 15, T[50]);
+	            b = II(b, c, d, a, M_offset_5,  21, T[51]);
+	            a = II(a, b, c, d, M_offset_12, 6,  T[52]);
+	            d = II(d, a, b, c, M_offset_3,  10, T[53]);
+	            c = II(c, d, a, b, M_offset_10, 15, T[54]);
+	            b = II(b, c, d, a, M_offset_1,  21, T[55]);
+	            a = II(a, b, c, d, M_offset_8,  6,  T[56]);
+	            d = II(d, a, b, c, M_offset_15, 10, T[57]);
+	            c = II(c, d, a, b, M_offset_6,  15, T[58]);
+	            b = II(b, c, d, a, M_offset_13, 21, T[59]);
+	            a = II(a, b, c, d, M_offset_4,  6,  T[60]);
+	            d = II(d, a, b, c, M_offset_11, 10, T[61]);
+	            c = II(c, d, a, b, M_offset_2,  15, T[62]);
+	            b = II(b, c, d, a, M_offset_9,  21, T[63]);
+
+	            // Intermediate hash value
+	            H[0] = (H[0] + a) | 0;
+	            H[1] = (H[1] + b) | 0;
+	            H[2] = (H[2] + c) | 0;
+	            H[3] = (H[3] + d) | 0;
+	        },
+
+	        _doFinalize: function () {
+	            // Shortcuts
+	            var data = this._data;
+	            var dataWords = data.words;
+
+	            var nBitsTotal = this._nDataBytes * 8;
+	            var nBitsLeft = data.sigBytes * 8;
+
+	            // Add padding
+	            dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
+
+	            var nBitsTotalH = Math.floor(nBitsTotal / 0x100000000);
+	            var nBitsTotalL = nBitsTotal;
+	            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = (
+	                (((nBitsTotalH << 8)  | (nBitsTotalH >>> 24)) & 0x00ff00ff) |
+	                (((nBitsTotalH << 24) | (nBitsTotalH >>> 8))  & 0xff00ff00)
+	            );
+	            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = (
+	                (((nBitsTotalL << 8)  | (nBitsTotalL >>> 24)) & 0x00ff00ff) |
+	                (((nBitsTotalL << 24) | (nBitsTotalL >>> 8))  & 0xff00ff00)
+	            );
+
+	            data.sigBytes = (dataWords.length + 1) * 4;
+
+	            // Hash final blocks
+	            this._process();
+
+	            // Shortcuts
+	            var hash = this._hash;
+	            var H = hash.words;
+
+	            // Swap endian
+	            for (var i = 0; i < 4; i++) {
+	                // Shortcut
+	                var H_i = H[i];
+
+	                H[i] = (((H_i << 8)  | (H_i >>> 24)) & 0x00ff00ff) |
+	                       (((H_i << 24) | (H_i >>> 8))  & 0xff00ff00);
+	            }
+
+	            // Return final computed hash
+	            return hash;
+	        },
+
+	        clone: function () {
+	            var clone = Hasher.clone.call(this);
+	            clone._hash = this._hash.clone();
+
+	            return clone;
+	        }
+	    });
+
+	    function FF(a, b, c, d, x, s, t) {
+	        var n = a + ((b & c) | (~b & d)) + x + t;
+	        return ((n << s) | (n >>> (32 - s))) + b;
+	    }
+
+	    function GG(a, b, c, d, x, s, t) {
+	        var n = a + ((b & d) | (c & ~d)) + x + t;
+	        return ((n << s) | (n >>> (32 - s))) + b;
+	    }
+
+	    function HH(a, b, c, d, x, s, t) {
+	        var n = a + (b ^ c ^ d) + x + t;
+	        return ((n << s) | (n >>> (32 - s))) + b;
+	    }
+
+	    function II(a, b, c, d, x, s, t) {
+	        var n = a + (c ^ (b | ~d)) + x + t;
+	        return ((n << s) | (n >>> (32 - s))) + b;
+	    }
+
+	    /**
+	     * Shortcut function to the hasher's object interface.
+	     *
+	     * @param {WordArray|string} message The message to hash.
+	     *
+	     * @return {WordArray} The hash.
+	     *
+	     * @static
+	     *
+	     * @example
+	     *
+	     *     var hash = CryptoJS.MD5('message');
+	     *     var hash = CryptoJS.MD5(wordArray);
+	     */
+	    C.MD5 = Hasher._createHelper(MD5);
+
+	    /**
+	     * Shortcut function to the HMAC's object interface.
+	     *
+	     * @param {WordArray|string} message The message to hash.
+	     * @param {WordArray|string} key The secret key.
+	     *
+	     * @return {WordArray} The HMAC.
+	     *
+	     * @static
+	     *
+	     * @example
+	     *
+	     *     var hmac = CryptoJS.HmacMD5(message, key);
+	     */
+	    C.HmacMD5 = Hasher._createHmacHelper(MD5);
+	}(Math));
+
+
+	return CryptoJS.MD5;
+
+}));

+ 80 - 0
crypto-js/mode-cfb.js

@@ -0,0 +1,80 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./cipher-core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./cipher-core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	/**
+	 * Cipher Feedback block mode.
+	 */
+	CryptoJS.mode.CFB = (function () {
+	    var CFB = CryptoJS.lib.BlockCipherMode.extend();
+
+	    CFB.Encryptor = CFB.extend({
+	        processBlock: function (words, offset) {
+	            // Shortcuts
+	            var cipher = this._cipher;
+	            var blockSize = cipher.blockSize;
+
+	            generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher);
+
+	            // Remember this block to use with next block
+	            this._prevBlock = words.slice(offset, offset + blockSize);
+	        }
+	    });
+
+	    CFB.Decryptor = CFB.extend({
+	        processBlock: function (words, offset) {
+	            // Shortcuts
+	            var cipher = this._cipher;
+	            var blockSize = cipher.blockSize;
+
+	            // Remember this block to use with next block
+	            var thisBlock = words.slice(offset, offset + blockSize);
+
+	            generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher);
+
+	            // This block becomes the previous block
+	            this._prevBlock = thisBlock;
+	        }
+	    });
+
+	    function generateKeystreamAndEncrypt(words, offset, blockSize, cipher) {
+	        var keystream;
+
+	        // Shortcut
+	        var iv = this._iv;
+
+	        // Generate keystream
+	        if (iv) {
+	            keystream = iv.slice(0);
+
+	            // Remove IV for subsequent blocks
+	            this._iv = undefined;
+	        } else {
+	            keystream = this._prevBlock;
+	        }
+	        cipher.encryptBlock(keystream, 0);
+
+	        // Encrypt
+	        for (var i = 0; i < blockSize; i++) {
+	            words[offset + i] ^= keystream[i];
+	        }
+	    }
+
+	    return CFB;
+	}());
+
+
+	return CryptoJS.mode.CFB;
+
+}));

+ 116 - 0
crypto-js/mode-ctr-gladman.js

@@ -0,0 +1,116 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./cipher-core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./cipher-core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	/** @preserve
+	 * Counter block mode compatible with  Dr Brian Gladman fileenc.c
+	 * derived from CryptoJS.mode.CTR
+	 * Jan Hruby jhruby.web@gmail.com
+	 */
+	CryptoJS.mode.CTRGladman = (function () {
+	    var CTRGladman = CryptoJS.lib.BlockCipherMode.extend();
+
+		function incWord(word)
+		{
+			if (((word >> 24) & 0xff) === 0xff) { //overflow
+			var b1 = (word >> 16)&0xff;
+			var b2 = (word >> 8)&0xff;
+			var b3 = word & 0xff;
+
+			if (b1 === 0xff) // overflow b1
+			{
+			b1 = 0;
+			if (b2 === 0xff)
+			{
+				b2 = 0;
+				if (b3 === 0xff)
+				{
+					b3 = 0;
+				}
+				else
+				{
+					++b3;
+				}
+			}
+			else
+			{
+				++b2;
+			}
+			}
+			else
+			{
+			++b1;
+			}
+
+			word = 0;
+			word += (b1 << 16);
+			word += (b2 << 8);
+			word += b3;
+			}
+			else
+			{
+			word += (0x01 << 24);
+			}
+			return word;
+		}
+
+		function incCounter(counter)
+		{
+			if ((counter[0] = incWord(counter[0])) === 0)
+			{
+				// encr_data in fileenc.c from  Dr Brian Gladman's counts only with DWORD j < 8
+				counter[1] = incWord(counter[1]);
+			}
+			return counter;
+		}
+
+	    var Encryptor = CTRGladman.Encryptor = CTRGladman.extend({
+	        processBlock: function (words, offset) {
+	            // Shortcuts
+	            var cipher = this._cipher
+	            var blockSize = cipher.blockSize;
+	            var iv = this._iv;
+	            var counter = this._counter;
+
+	            // Generate keystream
+	            if (iv) {
+	                counter = this._counter = iv.slice(0);
+
+	                // Remove IV for subsequent blocks
+	                this._iv = undefined;
+	            }
+
+				incCounter(counter);
+
+				var keystream = counter.slice(0);
+	            cipher.encryptBlock(keystream, 0);
+
+	            // Encrypt
+	            for (var i = 0; i < blockSize; i++) {
+	                words[offset + i] ^= keystream[i];
+	            }
+	        }
+	    });
+
+	    CTRGladman.Decryptor = Encryptor;
+
+	    return CTRGladman;
+	}());
+
+
+
+
+	return CryptoJS.mode.CTRGladman;
+
+}));

+ 58 - 0
crypto-js/mode-ctr.js

@@ -0,0 +1,58 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./cipher-core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./cipher-core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	/**
+	 * Counter block mode.
+	 */
+	CryptoJS.mode.CTR = (function () {
+	    var CTR = CryptoJS.lib.BlockCipherMode.extend();
+
+	    var Encryptor = CTR.Encryptor = CTR.extend({
+	        processBlock: function (words, offset) {
+	            // Shortcuts
+	            var cipher = this._cipher
+	            var blockSize = cipher.blockSize;
+	            var iv = this._iv;
+	            var counter = this._counter;
+
+	            // Generate keystream
+	            if (iv) {
+	                counter = this._counter = iv.slice(0);
+
+	                // Remove IV for subsequent blocks
+	                this._iv = undefined;
+	            }
+	            var keystream = counter.slice(0);
+	            cipher.encryptBlock(keystream, 0);
+
+	            // Increment counter
+	            counter[blockSize - 1] = (counter[blockSize - 1] + 1) | 0
+
+	            // Encrypt
+	            for (var i = 0; i < blockSize; i++) {
+	                words[offset + i] ^= keystream[i];
+	            }
+	        }
+	    });
+
+	    CTR.Decryptor = Encryptor;
+
+	    return CTR;
+	}());
+
+
+	return CryptoJS.mode.CTR;
+
+}));

+ 40 - 0
crypto-js/mode-ecb.js

@@ -0,0 +1,40 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./cipher-core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./cipher-core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	/**
+	 * Electronic Codebook block mode.
+	 */
+	CryptoJS.mode.ECB = (function () {
+	    var ECB = CryptoJS.lib.BlockCipherMode.extend();
+
+	    ECB.Encryptor = ECB.extend({
+	        processBlock: function (words, offset) {
+	            this._cipher.encryptBlock(words, offset);
+	        }
+	    });
+
+	    ECB.Decryptor = ECB.extend({
+	        processBlock: function (words, offset) {
+	            this._cipher.decryptBlock(words, offset);
+	        }
+	    });
+
+	    return ECB;
+	}());
+
+
+	return CryptoJS.mode.ECB;
+
+}));

+ 54 - 0
crypto-js/mode-ofb.js

@@ -0,0 +1,54 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./cipher-core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./cipher-core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	/**
+	 * Output Feedback block mode.
+	 */
+	CryptoJS.mode.OFB = (function () {
+	    var OFB = CryptoJS.lib.BlockCipherMode.extend();
+
+	    var Encryptor = OFB.Encryptor = OFB.extend({
+	        processBlock: function (words, offset) {
+	            // Shortcuts
+	            var cipher = this._cipher
+	            var blockSize = cipher.blockSize;
+	            var iv = this._iv;
+	            var keystream = this._keystream;
+
+	            // Generate keystream
+	            if (iv) {
+	                keystream = this._keystream = iv.slice(0);
+
+	                // Remove IV for subsequent blocks
+	                this._iv = undefined;
+	            }
+	            cipher.encryptBlock(keystream, 0);
+
+	            // Encrypt
+	            for (var i = 0; i < blockSize; i++) {
+	                words[offset + i] ^= keystream[i];
+	            }
+	        }
+	    });
+
+	    OFB.Decryptor = Encryptor;
+
+	    return OFB;
+	}());
+
+
+	return CryptoJS.mode.OFB;
+
+}));

+ 42 - 0
crypto-js/package.json

@@ -0,0 +1,42 @@
+{
+  "name": "crypto-js",
+  "version": "4.2.0",
+  "description": "JavaScript library of crypto standards.",
+  "license": "MIT",
+  "author": {
+    "name": "Evan Vosberg",
+    "url": "http://github.com/evanvosberg"
+  },
+  "homepage": "http://github.com/brix/crypto-js",
+  "repository": {
+    "type": "git",
+    "url": "http://github.com/brix/crypto-js.git"
+  },
+  "keywords": [
+    "security",
+    "crypto",
+    "Hash",
+    "MD5",
+    "SHA1",
+    "SHA-1",
+    "SHA256",
+    "SHA-256",
+    "RC4",
+    "Rabbit",
+    "AES",
+    "DES",
+    "PBKDF2",
+    "HMAC",
+    "OFB",
+    "CFB",
+    "CTR",
+    "CBC",
+    "Base64",
+    "Base64url"
+  ],
+  "main": "index.js",
+  "dependencies": {},
+  "browser": {
+    "crypto": false
+  }
+}

+ 49 - 0
crypto-js/pad-ansix923.js

@@ -0,0 +1,49 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./cipher-core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./cipher-core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	/**
+	 * ANSI X.923 padding strategy.
+	 */
+	CryptoJS.pad.AnsiX923 = {
+	    pad: function (data, blockSize) {
+	        // Shortcuts
+	        var dataSigBytes = data.sigBytes;
+	        var blockSizeBytes = blockSize * 4;
+
+	        // Count padding bytes
+	        var nPaddingBytes = blockSizeBytes - dataSigBytes % blockSizeBytes;
+
+	        // Compute last byte position
+	        var lastBytePos = dataSigBytes + nPaddingBytes - 1;
+
+	        // Pad
+	        data.clamp();
+	        data.words[lastBytePos >>> 2] |= nPaddingBytes << (24 - (lastBytePos % 4) * 8);
+	        data.sigBytes += nPaddingBytes;
+	    },
+
+	    unpad: function (data) {
+	        // Get number of padding bytes from last byte
+	        var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff;
+
+	        // Remove padding
+	        data.sigBytes -= nPaddingBytes;
+	    }
+	};
+
+
+	return CryptoJS.pad.Ansix923;
+
+}));

+ 44 - 0
crypto-js/pad-iso10126.js

@@ -0,0 +1,44 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./cipher-core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./cipher-core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	/**
+	 * ISO 10126 padding strategy.
+	 */
+	CryptoJS.pad.Iso10126 = {
+	    pad: function (data, blockSize) {
+	        // Shortcut
+	        var blockSizeBytes = blockSize * 4;
+
+	        // Count padding bytes
+	        var nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes;
+
+	        // Pad
+	        data.concat(CryptoJS.lib.WordArray.random(nPaddingBytes - 1)).
+	             concat(CryptoJS.lib.WordArray.create([nPaddingBytes << 24], 1));
+	    },
+
+	    unpad: function (data) {
+	        // Get number of padding bytes from last byte
+	        var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff;
+
+	        // Remove padding
+	        data.sigBytes -= nPaddingBytes;
+	    }
+	};
+
+
+	return CryptoJS.pad.Iso10126;
+
+}));

+ 40 - 0
crypto-js/pad-iso97971.js

@@ -0,0 +1,40 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./cipher-core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./cipher-core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	/**
+	 * ISO/IEC 9797-1 Padding Method 2.
+	 */
+	CryptoJS.pad.Iso97971 = {
+	    pad: function (data, blockSize) {
+	        // Add 0x80 byte
+	        data.concat(CryptoJS.lib.WordArray.create([0x80000000], 1));
+
+	        // Zero pad the rest
+	        CryptoJS.pad.ZeroPadding.pad(data, blockSize);
+	    },
+
+	    unpad: function (data) {
+	        // Remove zero padding
+	        CryptoJS.pad.ZeroPadding.unpad(data);
+
+	        // Remove one more byte -- the 0x80 byte
+	        data.sigBytes--;
+	    }
+	};
+
+
+	return CryptoJS.pad.Iso97971;
+
+}));

+ 30 - 0
crypto-js/pad-nopadding.js

@@ -0,0 +1,30 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./cipher-core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./cipher-core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	/**
+	 * A noop padding strategy.
+	 */
+	CryptoJS.pad.NoPadding = {
+	    pad: function () {
+	    },
+
+	    unpad: function () {
+	    }
+	};
+
+
+	return CryptoJS.pad.NoPadding;
+
+}));

+ 18 - 0
crypto-js/pad-pkcs7.js

@@ -0,0 +1,18 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./cipher-core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./cipher-core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	return CryptoJS.pad.Pkcs7;
+
+}));

+ 47 - 0
crypto-js/pad-zeropadding.js

@@ -0,0 +1,47 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./cipher-core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./cipher-core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	/**
+	 * Zero padding strategy.
+	 */
+	CryptoJS.pad.ZeroPadding = {
+	    pad: function (data, blockSize) {
+	        // Shortcut
+	        var blockSizeBytes = blockSize * 4;
+
+	        // Pad
+	        data.clamp();
+	        data.sigBytes += blockSizeBytes - ((data.sigBytes % blockSizeBytes) || blockSizeBytes);
+	    },
+
+	    unpad: function (data) {
+	        // Shortcut
+	        var dataWords = data.words;
+
+	        // Unpad
+	        var i = data.sigBytes - 1;
+	        for (var i = data.sigBytes - 1; i >= 0; i--) {
+	            if (((dataWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff)) {
+	                data.sigBytes = i + 1;
+	                break;
+	            }
+	        }
+	    }
+	};
+
+
+	return CryptoJS.pad.ZeroPadding;
+
+}));

+ 145 - 0
crypto-js/pbkdf2.js

@@ -0,0 +1,145 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./sha256"), require("./hmac"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./sha256", "./hmac"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	(function () {
+	    // Shortcuts
+	    var C = CryptoJS;
+	    var C_lib = C.lib;
+	    var Base = C_lib.Base;
+	    var WordArray = C_lib.WordArray;
+	    var C_algo = C.algo;
+	    var SHA256 = C_algo.SHA256;
+	    var HMAC = C_algo.HMAC;
+
+	    /**
+	     * Password-Based Key Derivation Function 2 algorithm.
+	     */
+	    var PBKDF2 = C_algo.PBKDF2 = Base.extend({
+	        /**
+	         * Configuration options.
+	         *
+	         * @property {number} keySize The key size in words to generate. Default: 4 (128 bits)
+	         * @property {Hasher} hasher The hasher to use. Default: SHA256
+	         * @property {number} iterations The number of iterations to perform. Default: 250000
+	         */
+	        cfg: Base.extend({
+	            keySize: 128/32,
+	            hasher: SHA256,
+	            iterations: 250000
+	        }),
+
+	        /**
+	         * Initializes a newly created key derivation function.
+	         *
+	         * @param {Object} cfg (Optional) The configuration options to use for the derivation.
+	         *
+	         * @example
+	         *
+	         *     var kdf = CryptoJS.algo.PBKDF2.create();
+	         *     var kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8 });
+	         *     var kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8, iterations: 1000 });
+	         */
+	        init: function (cfg) {
+	            this.cfg = this.cfg.extend(cfg);
+	        },
+
+	        /**
+	         * Computes the Password-Based Key Derivation Function 2.
+	         *
+	         * @param {WordArray|string} password The password.
+	         * @param {WordArray|string} salt A salt.
+	         *
+	         * @return {WordArray} The derived key.
+	         *
+	         * @example
+	         *
+	         *     var key = kdf.compute(password, salt);
+	         */
+	        compute: function (password, salt) {
+	            // Shortcut
+	            var cfg = this.cfg;
+
+	            // Init HMAC
+	            var hmac = HMAC.create(cfg.hasher, password);
+
+	            // Initial values
+	            var derivedKey = WordArray.create();
+	            var blockIndex = WordArray.create([0x00000001]);
+
+	            // Shortcuts
+	            var derivedKeyWords = derivedKey.words;
+	            var blockIndexWords = blockIndex.words;
+	            var keySize = cfg.keySize;
+	            var iterations = cfg.iterations;
+
+	            // Generate key
+	            while (derivedKeyWords.length < keySize) {
+	                var block = hmac.update(salt).finalize(blockIndex);
+	                hmac.reset();
+
+	                // Shortcuts
+	                var blockWords = block.words;
+	                var blockWordsLength = blockWords.length;
+
+	                // Iterations
+	                var intermediate = block;
+	                for (var i = 1; i < iterations; i++) {
+	                    intermediate = hmac.finalize(intermediate);
+	                    hmac.reset();
+
+	                    // Shortcut
+	                    var intermediateWords = intermediate.words;
+
+	                    // XOR intermediate with block
+	                    for (var j = 0; j < blockWordsLength; j++) {
+	                        blockWords[j] ^= intermediateWords[j];
+	                    }
+	                }
+
+	                derivedKey.concat(block);
+	                blockIndexWords[0]++;
+	            }
+	            derivedKey.sigBytes = keySize * 4;
+
+	            return derivedKey;
+	        }
+	    });
+
+	    /**
+	     * Computes the Password-Based Key Derivation Function 2.
+	     *
+	     * @param {WordArray|string} password The password.
+	     * @param {WordArray|string} salt A salt.
+	     * @param {Object} cfg (Optional) The configuration options to use for this computation.
+	     *
+	     * @return {WordArray} The derived key.
+	     *
+	     * @static
+	     *
+	     * @example
+	     *
+	     *     var key = CryptoJS.PBKDF2(password, salt);
+	     *     var key = CryptoJS.PBKDF2(password, salt, { keySize: 8 });
+	     *     var key = CryptoJS.PBKDF2(password, salt, { keySize: 8, iterations: 1000 });
+	     */
+	    C.PBKDF2 = function (password, salt, cfg) {
+	        return PBKDF2.create(cfg).compute(password, salt);
+	    };
+	}());
+
+
+	return CryptoJS.PBKDF2;
+
+}));

+ 190 - 0
crypto-js/rabbit-legacy.js

@@ -0,0 +1,190 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	(function () {
+	    // Shortcuts
+	    var C = CryptoJS;
+	    var C_lib = C.lib;
+	    var StreamCipher = C_lib.StreamCipher;
+	    var C_algo = C.algo;
+
+	    // Reusable objects
+	    var S  = [];
+	    var C_ = [];
+	    var G  = [];
+
+	    /**
+	     * Rabbit stream cipher algorithm.
+	     *
+	     * This is a legacy version that neglected to convert the key to little-endian.
+	     * This error doesn't affect the cipher's security,
+	     * but it does affect its compatibility with other implementations.
+	     */
+	    var RabbitLegacy = C_algo.RabbitLegacy = StreamCipher.extend({
+	        _doReset: function () {
+	            // Shortcuts
+	            var K = this._key.words;
+	            var iv = this.cfg.iv;
+
+	            // Generate initial state values
+	            var X = this._X = [
+	                K[0], (K[3] << 16) | (K[2] >>> 16),
+	                K[1], (K[0] << 16) | (K[3] >>> 16),
+	                K[2], (K[1] << 16) | (K[0] >>> 16),
+	                K[3], (K[2] << 16) | (K[1] >>> 16)
+	            ];
+
+	            // Generate initial counter values
+	            var C = this._C = [
+	                (K[2] << 16) | (K[2] >>> 16), (K[0] & 0xffff0000) | (K[1] & 0x0000ffff),
+	                (K[3] << 16) | (K[3] >>> 16), (K[1] & 0xffff0000) | (K[2] & 0x0000ffff),
+	                (K[0] << 16) | (K[0] >>> 16), (K[2] & 0xffff0000) | (K[3] & 0x0000ffff),
+	                (K[1] << 16) | (K[1] >>> 16), (K[3] & 0xffff0000) | (K[0] & 0x0000ffff)
+	            ];
+
+	            // Carry bit
+	            this._b = 0;
+
+	            // Iterate the system four times
+	            for (var i = 0; i < 4; i++) {
+	                nextState.call(this);
+	            }
+
+	            // Modify the counters
+	            for (var i = 0; i < 8; i++) {
+	                C[i] ^= X[(i + 4) & 7];
+	            }
+
+	            // IV setup
+	            if (iv) {
+	                // Shortcuts
+	                var IV = iv.words;
+	                var IV_0 = IV[0];
+	                var IV_1 = IV[1];
+
+	                // Generate four subvectors
+	                var i0 = (((IV_0 << 8) | (IV_0 >>> 24)) & 0x00ff00ff) | (((IV_0 << 24) | (IV_0 >>> 8)) & 0xff00ff00);
+	                var i2 = (((IV_1 << 8) | (IV_1 >>> 24)) & 0x00ff00ff) | (((IV_1 << 24) | (IV_1 >>> 8)) & 0xff00ff00);
+	                var i1 = (i0 >>> 16) | (i2 & 0xffff0000);
+	                var i3 = (i2 << 16)  | (i0 & 0x0000ffff);
+
+	                // Modify counter values
+	                C[0] ^= i0;
+	                C[1] ^= i1;
+	                C[2] ^= i2;
+	                C[3] ^= i3;
+	                C[4] ^= i0;
+	                C[5] ^= i1;
+	                C[6] ^= i2;
+	                C[7] ^= i3;
+
+	                // Iterate the system four times
+	                for (var i = 0; i < 4; i++) {
+	                    nextState.call(this);
+	                }
+	            }
+	        },
+
+	        _doProcessBlock: function (M, offset) {
+	            // Shortcut
+	            var X = this._X;
+
+	            // Iterate the system
+	            nextState.call(this);
+
+	            // Generate four keystream words
+	            S[0] = X[0] ^ (X[5] >>> 16) ^ (X[3] << 16);
+	            S[1] = X[2] ^ (X[7] >>> 16) ^ (X[5] << 16);
+	            S[2] = X[4] ^ (X[1] >>> 16) ^ (X[7] << 16);
+	            S[3] = X[6] ^ (X[3] >>> 16) ^ (X[1] << 16);
+
+	            for (var i = 0; i < 4; i++) {
+	                // Swap endian
+	                S[i] = (((S[i] << 8)  | (S[i] >>> 24)) & 0x00ff00ff) |
+	                       (((S[i] << 24) | (S[i] >>> 8))  & 0xff00ff00);
+
+	                // Encrypt
+	                M[offset + i] ^= S[i];
+	            }
+	        },
+
+	        blockSize: 128/32,
+
+	        ivSize: 64/32
+	    });
+
+	    function nextState() {
+	        // Shortcuts
+	        var X = this._X;
+	        var C = this._C;
+
+	        // Save old counter values
+	        for (var i = 0; i < 8; i++) {
+	            C_[i] = C[i];
+	        }
+
+	        // Calculate new counter values
+	        C[0] = (C[0] + 0x4d34d34d + this._b) | 0;
+	        C[1] = (C[1] + 0xd34d34d3 + ((C[0] >>> 0) < (C_[0] >>> 0) ? 1 : 0)) | 0;
+	        C[2] = (C[2] + 0x34d34d34 + ((C[1] >>> 0) < (C_[1] >>> 0) ? 1 : 0)) | 0;
+	        C[3] = (C[3] + 0x4d34d34d + ((C[2] >>> 0) < (C_[2] >>> 0) ? 1 : 0)) | 0;
+	        C[4] = (C[4] + 0xd34d34d3 + ((C[3] >>> 0) < (C_[3] >>> 0) ? 1 : 0)) | 0;
+	        C[5] = (C[5] + 0x34d34d34 + ((C[4] >>> 0) < (C_[4] >>> 0) ? 1 : 0)) | 0;
+	        C[6] = (C[6] + 0x4d34d34d + ((C[5] >>> 0) < (C_[5] >>> 0) ? 1 : 0)) | 0;
+	        C[7] = (C[7] + 0xd34d34d3 + ((C[6] >>> 0) < (C_[6] >>> 0) ? 1 : 0)) | 0;
+	        this._b = (C[7] >>> 0) < (C_[7] >>> 0) ? 1 : 0;
+
+	        // Calculate the g-values
+	        for (var i = 0; i < 8; i++) {
+	            var gx = X[i] + C[i];
+
+	            // Construct high and low argument for squaring
+	            var ga = gx & 0xffff;
+	            var gb = gx >>> 16;
+
+	            // Calculate high and low result of squaring
+	            var gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb;
+	            var gl = (((gx & 0xffff0000) * gx) | 0) + (((gx & 0x0000ffff) * gx) | 0);
+
+	            // High XOR low
+	            G[i] = gh ^ gl;
+	        }
+
+	        // Calculate new state values
+	        X[0] = (G[0] + ((G[7] << 16) | (G[7] >>> 16)) + ((G[6] << 16) | (G[6] >>> 16))) | 0;
+	        X[1] = (G[1] + ((G[0] << 8)  | (G[0] >>> 24)) + G[7]) | 0;
+	        X[2] = (G[2] + ((G[1] << 16) | (G[1] >>> 16)) + ((G[0] << 16) | (G[0] >>> 16))) | 0;
+	        X[3] = (G[3] + ((G[2] << 8)  | (G[2] >>> 24)) + G[1]) | 0;
+	        X[4] = (G[4] + ((G[3] << 16) | (G[3] >>> 16)) + ((G[2] << 16) | (G[2] >>> 16))) | 0;
+	        X[5] = (G[5] + ((G[4] << 8)  | (G[4] >>> 24)) + G[3]) | 0;
+	        X[6] = (G[6] + ((G[5] << 16) | (G[5] >>> 16)) + ((G[4] << 16) | (G[4] >>> 16))) | 0;
+	        X[7] = (G[7] + ((G[6] << 8)  | (G[6] >>> 24)) + G[5]) | 0;
+	    }
+
+	    /**
+	     * Shortcut functions to the cipher's object interface.
+	     *
+	     * @example
+	     *
+	     *     var ciphertext = CryptoJS.RabbitLegacy.encrypt(message, key, cfg);
+	     *     var plaintext  = CryptoJS.RabbitLegacy.decrypt(ciphertext, key, cfg);
+	     */
+	    C.RabbitLegacy = StreamCipher._createHelper(RabbitLegacy);
+	}());
+
+
+	return CryptoJS.RabbitLegacy;
+
+}));

+ 192 - 0
crypto-js/rabbit.js

@@ -0,0 +1,192 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	(function () {
+	    // Shortcuts
+	    var C = CryptoJS;
+	    var C_lib = C.lib;
+	    var StreamCipher = C_lib.StreamCipher;
+	    var C_algo = C.algo;
+
+	    // Reusable objects
+	    var S  = [];
+	    var C_ = [];
+	    var G  = [];
+
+	    /**
+	     * Rabbit stream cipher algorithm
+	     */
+	    var Rabbit = C_algo.Rabbit = StreamCipher.extend({
+	        _doReset: function () {
+	            // Shortcuts
+	            var K = this._key.words;
+	            var iv = this.cfg.iv;
+
+	            // Swap endian
+	            for (var i = 0; i < 4; i++) {
+	                K[i] = (((K[i] << 8)  | (K[i] >>> 24)) & 0x00ff00ff) |
+	                       (((K[i] << 24) | (K[i] >>> 8))  & 0xff00ff00);
+	            }
+
+	            // Generate initial state values
+	            var X = this._X = [
+	                K[0], (K[3] << 16) | (K[2] >>> 16),
+	                K[1], (K[0] << 16) | (K[3] >>> 16),
+	                K[2], (K[1] << 16) | (K[0] >>> 16),
+	                K[3], (K[2] << 16) | (K[1] >>> 16)
+	            ];
+
+	            // Generate initial counter values
+	            var C = this._C = [
+	                (K[2] << 16) | (K[2] >>> 16), (K[0] & 0xffff0000) | (K[1] & 0x0000ffff),
+	                (K[3] << 16) | (K[3] >>> 16), (K[1] & 0xffff0000) | (K[2] & 0x0000ffff),
+	                (K[0] << 16) | (K[0] >>> 16), (K[2] & 0xffff0000) | (K[3] & 0x0000ffff),
+	                (K[1] << 16) | (K[1] >>> 16), (K[3] & 0xffff0000) | (K[0] & 0x0000ffff)
+	            ];
+
+	            // Carry bit
+	            this._b = 0;
+
+	            // Iterate the system four times
+	            for (var i = 0; i < 4; i++) {
+	                nextState.call(this);
+	            }
+
+	            // Modify the counters
+	            for (var i = 0; i < 8; i++) {
+	                C[i] ^= X[(i + 4) & 7];
+	            }
+
+	            // IV setup
+	            if (iv) {
+	                // Shortcuts
+	                var IV = iv.words;
+	                var IV_0 = IV[0];
+	                var IV_1 = IV[1];
+
+	                // Generate four subvectors
+	                var i0 = (((IV_0 << 8) | (IV_0 >>> 24)) & 0x00ff00ff) | (((IV_0 << 24) | (IV_0 >>> 8)) & 0xff00ff00);
+	                var i2 = (((IV_1 << 8) | (IV_1 >>> 24)) & 0x00ff00ff) | (((IV_1 << 24) | (IV_1 >>> 8)) & 0xff00ff00);
+	                var i1 = (i0 >>> 16) | (i2 & 0xffff0000);
+	                var i3 = (i2 << 16)  | (i0 & 0x0000ffff);
+
+	                // Modify counter values
+	                C[0] ^= i0;
+	                C[1] ^= i1;
+	                C[2] ^= i2;
+	                C[3] ^= i3;
+	                C[4] ^= i0;
+	                C[5] ^= i1;
+	                C[6] ^= i2;
+	                C[7] ^= i3;
+
+	                // Iterate the system four times
+	                for (var i = 0; i < 4; i++) {
+	                    nextState.call(this);
+	                }
+	            }
+	        },
+
+	        _doProcessBlock: function (M, offset) {
+	            // Shortcut
+	            var X = this._X;
+
+	            // Iterate the system
+	            nextState.call(this);
+
+	            // Generate four keystream words
+	            S[0] = X[0] ^ (X[5] >>> 16) ^ (X[3] << 16);
+	            S[1] = X[2] ^ (X[7] >>> 16) ^ (X[5] << 16);
+	            S[2] = X[4] ^ (X[1] >>> 16) ^ (X[7] << 16);
+	            S[3] = X[6] ^ (X[3] >>> 16) ^ (X[1] << 16);
+
+	            for (var i = 0; i < 4; i++) {
+	                // Swap endian
+	                S[i] = (((S[i] << 8)  | (S[i] >>> 24)) & 0x00ff00ff) |
+	                       (((S[i] << 24) | (S[i] >>> 8))  & 0xff00ff00);
+
+	                // Encrypt
+	                M[offset + i] ^= S[i];
+	            }
+	        },
+
+	        blockSize: 128/32,
+
+	        ivSize: 64/32
+	    });
+
+	    function nextState() {
+	        // Shortcuts
+	        var X = this._X;
+	        var C = this._C;
+
+	        // Save old counter values
+	        for (var i = 0; i < 8; i++) {
+	            C_[i] = C[i];
+	        }
+
+	        // Calculate new counter values
+	        C[0] = (C[0] + 0x4d34d34d + this._b) | 0;
+	        C[1] = (C[1] + 0xd34d34d3 + ((C[0] >>> 0) < (C_[0] >>> 0) ? 1 : 0)) | 0;
+	        C[2] = (C[2] + 0x34d34d34 + ((C[1] >>> 0) < (C_[1] >>> 0) ? 1 : 0)) | 0;
+	        C[3] = (C[3] + 0x4d34d34d + ((C[2] >>> 0) < (C_[2] >>> 0) ? 1 : 0)) | 0;
+	        C[4] = (C[4] + 0xd34d34d3 + ((C[3] >>> 0) < (C_[3] >>> 0) ? 1 : 0)) | 0;
+	        C[5] = (C[5] + 0x34d34d34 + ((C[4] >>> 0) < (C_[4] >>> 0) ? 1 : 0)) | 0;
+	        C[6] = (C[6] + 0x4d34d34d + ((C[5] >>> 0) < (C_[5] >>> 0) ? 1 : 0)) | 0;
+	        C[7] = (C[7] + 0xd34d34d3 + ((C[6] >>> 0) < (C_[6] >>> 0) ? 1 : 0)) | 0;
+	        this._b = (C[7] >>> 0) < (C_[7] >>> 0) ? 1 : 0;
+
+	        // Calculate the g-values
+	        for (var i = 0; i < 8; i++) {
+	            var gx = X[i] + C[i];
+
+	            // Construct high and low argument for squaring
+	            var ga = gx & 0xffff;
+	            var gb = gx >>> 16;
+
+	            // Calculate high and low result of squaring
+	            var gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb;
+	            var gl = (((gx & 0xffff0000) * gx) | 0) + (((gx & 0x0000ffff) * gx) | 0);
+
+	            // High XOR low
+	            G[i] = gh ^ gl;
+	        }
+
+	        // Calculate new state values
+	        X[0] = (G[0] + ((G[7] << 16) | (G[7] >>> 16)) + ((G[6] << 16) | (G[6] >>> 16))) | 0;
+	        X[1] = (G[1] + ((G[0] << 8)  | (G[0] >>> 24)) + G[7]) | 0;
+	        X[2] = (G[2] + ((G[1] << 16) | (G[1] >>> 16)) + ((G[0] << 16) | (G[0] >>> 16))) | 0;
+	        X[3] = (G[3] + ((G[2] << 8)  | (G[2] >>> 24)) + G[1]) | 0;
+	        X[4] = (G[4] + ((G[3] << 16) | (G[3] >>> 16)) + ((G[2] << 16) | (G[2] >>> 16))) | 0;
+	        X[5] = (G[5] + ((G[4] << 8)  | (G[4] >>> 24)) + G[3]) | 0;
+	        X[6] = (G[6] + ((G[5] << 16) | (G[5] >>> 16)) + ((G[4] << 16) | (G[4] >>> 16))) | 0;
+	        X[7] = (G[7] + ((G[6] << 8)  | (G[6] >>> 24)) + G[5]) | 0;
+	    }
+
+	    /**
+	     * Shortcut functions to the cipher's object interface.
+	     *
+	     * @example
+	     *
+	     *     var ciphertext = CryptoJS.Rabbit.encrypt(message, key, cfg);
+	     *     var plaintext  = CryptoJS.Rabbit.decrypt(ciphertext, key, cfg);
+	     */
+	    C.Rabbit = StreamCipher._createHelper(Rabbit);
+	}());
+
+
+	return CryptoJS.Rabbit;
+
+}));

+ 139 - 0
crypto-js/rc4.js

@@ -0,0 +1,139 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	(function () {
+	    // Shortcuts
+	    var C = CryptoJS;
+	    var C_lib = C.lib;
+	    var StreamCipher = C_lib.StreamCipher;
+	    var C_algo = C.algo;
+
+	    /**
+	     * RC4 stream cipher algorithm.
+	     */
+	    var RC4 = C_algo.RC4 = StreamCipher.extend({
+	        _doReset: function () {
+	            // Shortcuts
+	            var key = this._key;
+	            var keyWords = key.words;
+	            var keySigBytes = key.sigBytes;
+
+	            // Init sbox
+	            var S = this._S = [];
+	            for (var i = 0; i < 256; i++) {
+	                S[i] = i;
+	            }
+
+	            // Key setup
+	            for (var i = 0, j = 0; i < 256; i++) {
+	                var keyByteIndex = i % keySigBytes;
+	                var keyByte = (keyWords[keyByteIndex >>> 2] >>> (24 - (keyByteIndex % 4) * 8)) & 0xff;
+
+	                j = (j + S[i] + keyByte) % 256;
+
+	                // Swap
+	                var t = S[i];
+	                S[i] = S[j];
+	                S[j] = t;
+	            }
+
+	            // Counters
+	            this._i = this._j = 0;
+	        },
+
+	        _doProcessBlock: function (M, offset) {
+	            M[offset] ^= generateKeystreamWord.call(this);
+	        },
+
+	        keySize: 256/32,
+
+	        ivSize: 0
+	    });
+
+	    function generateKeystreamWord() {
+	        // Shortcuts
+	        var S = this._S;
+	        var i = this._i;
+	        var j = this._j;
+
+	        // Generate keystream word
+	        var keystreamWord = 0;
+	        for (var n = 0; n < 4; n++) {
+	            i = (i + 1) % 256;
+	            j = (j + S[i]) % 256;
+
+	            // Swap
+	            var t = S[i];
+	            S[i] = S[j];
+	            S[j] = t;
+
+	            keystreamWord |= S[(S[i] + S[j]) % 256] << (24 - n * 8);
+	        }
+
+	        // Update counters
+	        this._i = i;
+	        this._j = j;
+
+	        return keystreamWord;
+	    }
+
+	    /**
+	     * Shortcut functions to the cipher's object interface.
+	     *
+	     * @example
+	     *
+	     *     var ciphertext = CryptoJS.RC4.encrypt(message, key, cfg);
+	     *     var plaintext  = CryptoJS.RC4.decrypt(ciphertext, key, cfg);
+	     */
+	    C.RC4 = StreamCipher._createHelper(RC4);
+
+	    /**
+	     * Modified RC4 stream cipher algorithm.
+	     */
+	    var RC4Drop = C_algo.RC4Drop = RC4.extend({
+	        /**
+	         * Configuration options.
+	         *
+	         * @property {number} drop The number of keystream words to drop. Default 192
+	         */
+	        cfg: RC4.cfg.extend({
+	            drop: 192
+	        }),
+
+	        _doReset: function () {
+	            RC4._doReset.call(this);
+
+	            // Drop
+	            for (var i = this.cfg.drop; i > 0; i--) {
+	                generateKeystreamWord.call(this);
+	            }
+	        }
+	    });
+
+	    /**
+	     * Shortcut functions to the cipher's object interface.
+	     *
+	     * @example
+	     *
+	     *     var ciphertext = CryptoJS.RC4Drop.encrypt(message, key, cfg);
+	     *     var plaintext  = CryptoJS.RC4Drop.decrypt(ciphertext, key, cfg);
+	     */
+	    C.RC4Drop = StreamCipher._createHelper(RC4Drop);
+	}());
+
+
+	return CryptoJS.RC4;
+
+}));

Разница между файлами не показана из-за своего большого размера
+ 267 - 0
crypto-js/ripemd160.js


+ 150 - 0
crypto-js/sha1.js

@@ -0,0 +1,150 @@
+;(function (root, factory) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	(function () {
+	    // Shortcuts
+	    var C = CryptoJS;
+	    var C_lib = C.lib;
+	    var WordArray = C_lib.WordArray;
+	    var Hasher = C_lib.Hasher;
+	    var C_algo = C.algo;
+
+	    // Reusable object
+	    var W = [];
+
+	    /**
+	     * SHA-1 hash algorithm.
+	     */
+	    var SHA1 = C_algo.SHA1 = Hasher.extend({
+	        _doReset: function () {
+	            this._hash = new WordArray.init([
+	                0x67452301, 0xefcdab89,
+	                0x98badcfe, 0x10325476,
+	                0xc3d2e1f0
+	            ]);
+	        },
+
+	        _doProcessBlock: function (M, offset) {
+	            // Shortcut
+	            var H = this._hash.words;
+
+	            // Working variables
+	            var a = H[0];
+	            var b = H[1];
+	            var c = H[2];
+	            var d = H[3];
+	            var e = H[4];
+
+	            // Computation
+	            for (var i = 0; i < 80; i++) {
+	                if (i < 16) {
+	                    W[i] = M[offset + i] | 0;
+	                } else {
+	                    var n = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];
+	                    W[i] = (n << 1) | (n >>> 31);
+	                }
+
+	                var t = ((a << 5) | (a >>> 27)) + e + W[i];
+	                if (i < 20) {
+	                    t += ((b & c) | (~b & d)) + 0x5a827999;
+	                } else if (i < 40) {
+	                    t += (b ^ c ^ d) + 0x6ed9eba1;
+	                } else if (i < 60) {
+	                    t += ((b & c) | (b & d) | (c & d)) - 0x70e44324;
+	                } else /* if (i < 80) */ {
+	                    t += (b ^ c ^ d) - 0x359d3e2a;
+	                }
+
+	                e = d;
+	                d = c;
+	                c = (b << 30) | (b >>> 2);
+	                b = a;
+	                a = t;
+	            }
+
+	            // Intermediate hash value
+	            H[0] = (H[0] + a) | 0;
+	            H[1] = (H[1] + b) | 0;
+	            H[2] = (H[2] + c) | 0;
+	            H[3] = (H[3] + d) | 0;
+	            H[4] = (H[4] + e) | 0;
+	        },
+
+	        _doFinalize: function () {
+	            // Shortcuts
+	            var data = this._data;
+	            var dataWords = data.words;
+
+	            var nBitsTotal = this._nDataBytes * 8;
+	            var nBitsLeft = data.sigBytes * 8;
+
+	            // Add padding
+	            dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
+	            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000);
+	            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal;
+	            data.sigBytes = dataWords.length * 4;
+
+	            // Hash final blocks
+	            this._process();
+
+	            // Return final computed hash
+	            return this._hash;
+	        },
+
+	        clone: function () {
+	            var clone = Hasher.clone.call(this);
+	            clone._hash = this._hash.clone();
+
+	            return clone;
+	        }
+	    });
+
+	    /**
+	     * Shortcut function to the hasher's object interface.
+	     *
+	     * @param {WordArray|string} message The message to hash.
+	     *
+	     * @return {WordArray} The hash.
+	     *
+	     * @static
+	     *
+	     * @example
+	     *
+	     *     var hash = CryptoJS.SHA1('message');
+	     *     var hash = CryptoJS.SHA1(wordArray);
+	     */
+	    C.SHA1 = Hasher._createHelper(SHA1);
+
+	    /**
+	     * Shortcut function to the HMAC's object interface.
+	     *
+	     * @param {WordArray|string} message The message to hash.
+	     * @param {WordArray|string} key The secret key.
+	     *
+	     * @return {WordArray} The HMAC.
+	     *
+	     * @static
+	     *
+	     * @example
+	     *
+	     *     var hmac = CryptoJS.HmacSHA1(message, key);
+	     */
+	    C.HmacSHA1 = Hasher._createHmacHelper(SHA1);
+	}());
+
+
+	return CryptoJS.SHA1;
+
+}));

+ 80 - 0
crypto-js/sha224.js

@@ -0,0 +1,80 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./sha256"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./sha256"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	(function () {
+	    // Shortcuts
+	    var C = CryptoJS;
+	    var C_lib = C.lib;
+	    var WordArray = C_lib.WordArray;
+	    var C_algo = C.algo;
+	    var SHA256 = C_algo.SHA256;
+
+	    /**
+	     * SHA-224 hash algorithm.
+	     */
+	    var SHA224 = C_algo.SHA224 = SHA256.extend({
+	        _doReset: function () {
+	            this._hash = new WordArray.init([
+	                0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
+	                0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4
+	            ]);
+	        },
+
+	        _doFinalize: function () {
+	            var hash = SHA256._doFinalize.call(this);
+
+	            hash.sigBytes -= 4;
+
+	            return hash;
+	        }
+	    });
+
+	    /**
+	     * Shortcut function to the hasher's object interface.
+	     *
+	     * @param {WordArray|string} message The message to hash.
+	     *
+	     * @return {WordArray} The hash.
+	     *
+	     * @static
+	     *
+	     * @example
+	     *
+	     *     var hash = CryptoJS.SHA224('message');
+	     *     var hash = CryptoJS.SHA224(wordArray);
+	     */
+	    C.SHA224 = SHA256._createHelper(SHA224);
+
+	    /**
+	     * Shortcut function to the HMAC's object interface.
+	     *
+	     * @param {WordArray|string} message The message to hash.
+	     * @param {WordArray|string} key The secret key.
+	     *
+	     * @return {WordArray} The HMAC.
+	     *
+	     * @static
+	     *
+	     * @example
+	     *
+	     *     var hmac = CryptoJS.HmacSHA224(message, key);
+	     */
+	    C.HmacSHA224 = SHA256._createHmacHelper(SHA224);
+	}());
+
+
+	return CryptoJS.SHA224;
+
+}));

+ 199 - 0
crypto-js/sha256.js

@@ -0,0 +1,199 @@
+;(function (root, factory) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	(function (Math) {
+	    // Shortcuts
+	    var C = CryptoJS;
+	    var C_lib = C.lib;
+	    var WordArray = C_lib.WordArray;
+	    var Hasher = C_lib.Hasher;
+	    var C_algo = C.algo;
+
+	    // Initialization and round constants tables
+	    var H = [];
+	    var K = [];
+
+	    // Compute constants
+	    (function () {
+	        function isPrime(n) {
+	            var sqrtN = Math.sqrt(n);
+	            for (var factor = 2; factor <= sqrtN; factor++) {
+	                if (!(n % factor)) {
+	                    return false;
+	                }
+	            }
+
+	            return true;
+	        }
+
+	        function getFractionalBits(n) {
+	            return ((n - (n | 0)) * 0x100000000) | 0;
+	        }
+
+	        var n = 2;
+	        var nPrime = 0;
+	        while (nPrime < 64) {
+	            if (isPrime(n)) {
+	                if (nPrime < 8) {
+	                    H[nPrime] = getFractionalBits(Math.pow(n, 1 / 2));
+	                }
+	                K[nPrime] = getFractionalBits(Math.pow(n, 1 / 3));
+
+	                nPrime++;
+	            }
+
+	            n++;
+	        }
+	    }());
+
+	    // Reusable object
+	    var W = [];
+
+	    /**
+	     * SHA-256 hash algorithm.
+	     */
+	    var SHA256 = C_algo.SHA256 = Hasher.extend({
+	        _doReset: function () {
+	            this._hash = new WordArray.init(H.slice(0));
+	        },
+
+	        _doProcessBlock: function (M, offset) {
+	            // Shortcut
+	            var H = this._hash.words;
+
+	            // Working variables
+	            var a = H[0];
+	            var b = H[1];
+	            var c = H[2];
+	            var d = H[3];
+	            var e = H[4];
+	            var f = H[5];
+	            var g = H[6];
+	            var h = H[7];
+
+	            // Computation
+	            for (var i = 0; i < 64; i++) {
+	                if (i < 16) {
+	                    W[i] = M[offset + i] | 0;
+	                } else {
+	                    var gamma0x = W[i - 15];
+	                    var gamma0  = ((gamma0x << 25) | (gamma0x >>> 7))  ^
+	                                  ((gamma0x << 14) | (gamma0x >>> 18)) ^
+	                                   (gamma0x >>> 3);
+
+	                    var gamma1x = W[i - 2];
+	                    var gamma1  = ((gamma1x << 15) | (gamma1x >>> 17)) ^
+	                                  ((gamma1x << 13) | (gamma1x >>> 19)) ^
+	                                   (gamma1x >>> 10);
+
+	                    W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16];
+	                }
+
+	                var ch  = (e & f) ^ (~e & g);
+	                var maj = (a & b) ^ (a & c) ^ (b & c);
+
+	                var sigma0 = ((a << 30) | (a >>> 2)) ^ ((a << 19) | (a >>> 13)) ^ ((a << 10) | (a >>> 22));
+	                var sigma1 = ((e << 26) | (e >>> 6)) ^ ((e << 21) | (e >>> 11)) ^ ((e << 7)  | (e >>> 25));
+
+	                var t1 = h + sigma1 + ch + K[i] + W[i];
+	                var t2 = sigma0 + maj;
+
+	                h = g;
+	                g = f;
+	                f = e;
+	                e = (d + t1) | 0;
+	                d = c;
+	                c = b;
+	                b = a;
+	                a = (t1 + t2) | 0;
+	            }
+
+	            // Intermediate hash value
+	            H[0] = (H[0] + a) | 0;
+	            H[1] = (H[1] + b) | 0;
+	            H[2] = (H[2] + c) | 0;
+	            H[3] = (H[3] + d) | 0;
+	            H[4] = (H[4] + e) | 0;
+	            H[5] = (H[5] + f) | 0;
+	            H[6] = (H[6] + g) | 0;
+	            H[7] = (H[7] + h) | 0;
+	        },
+
+	        _doFinalize: function () {
+	            // Shortcuts
+	            var data = this._data;
+	            var dataWords = data.words;
+
+	            var nBitsTotal = this._nDataBytes * 8;
+	            var nBitsLeft = data.sigBytes * 8;
+
+	            // Add padding
+	            dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
+	            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000);
+	            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal;
+	            data.sigBytes = dataWords.length * 4;
+
+	            // Hash final blocks
+	            this._process();
+
+	            // Return final computed hash
+	            return this._hash;
+	        },
+
+	        clone: function () {
+	            var clone = Hasher.clone.call(this);
+	            clone._hash = this._hash.clone();
+
+	            return clone;
+	        }
+	    });
+
+	    /**
+	     * Shortcut function to the hasher's object interface.
+	     *
+	     * @param {WordArray|string} message The message to hash.
+	     *
+	     * @return {WordArray} The hash.
+	     *
+	     * @static
+	     *
+	     * @example
+	     *
+	     *     var hash = CryptoJS.SHA256('message');
+	     *     var hash = CryptoJS.SHA256(wordArray);
+	     */
+	    C.SHA256 = Hasher._createHelper(SHA256);
+
+	    /**
+	     * Shortcut function to the HMAC's object interface.
+	     *
+	     * @param {WordArray|string} message The message to hash.
+	     * @param {WordArray|string} key The secret key.
+	     *
+	     * @return {WordArray} The HMAC.
+	     *
+	     * @static
+	     *
+	     * @example
+	     *
+	     *     var hmac = CryptoJS.HmacSHA256(message, key);
+	     */
+	    C.HmacSHA256 = Hasher._createHmacHelper(SHA256);
+	}(Math));
+
+
+	return CryptoJS.SHA256;
+
+}));

+ 326 - 0
crypto-js/sha3.js

@@ -0,0 +1,326 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./x64-core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./x64-core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	(function (Math) {
+	    // Shortcuts
+	    var C = CryptoJS;
+	    var C_lib = C.lib;
+	    var WordArray = C_lib.WordArray;
+	    var Hasher = C_lib.Hasher;
+	    var C_x64 = C.x64;
+	    var X64Word = C_x64.Word;
+	    var C_algo = C.algo;
+
+	    // Constants tables
+	    var RHO_OFFSETS = [];
+	    var PI_INDEXES  = [];
+	    var ROUND_CONSTANTS = [];
+
+	    // Compute Constants
+	    (function () {
+	        // Compute rho offset constants
+	        var x = 1, y = 0;
+	        for (var t = 0; t < 24; t++) {
+	            RHO_OFFSETS[x + 5 * y] = ((t + 1) * (t + 2) / 2) % 64;
+
+	            var newX = y % 5;
+	            var newY = (2 * x + 3 * y) % 5;
+	            x = newX;
+	            y = newY;
+	        }
+
+	        // Compute pi index constants
+	        for (var x = 0; x < 5; x++) {
+	            for (var y = 0; y < 5; y++) {
+	                PI_INDEXES[x + 5 * y] = y + ((2 * x + 3 * y) % 5) * 5;
+	            }
+	        }
+
+	        // Compute round constants
+	        var LFSR = 0x01;
+	        for (var i = 0; i < 24; i++) {
+	            var roundConstantMsw = 0;
+	            var roundConstantLsw = 0;
+
+	            for (var j = 0; j < 7; j++) {
+	                if (LFSR & 0x01) {
+	                    var bitPosition = (1 << j) - 1;
+	                    if (bitPosition < 32) {
+	                        roundConstantLsw ^= 1 << bitPosition;
+	                    } else /* if (bitPosition >= 32) */ {
+	                        roundConstantMsw ^= 1 << (bitPosition - 32);
+	                    }
+	                }
+
+	                // Compute next LFSR
+	                if (LFSR & 0x80) {
+	                    // Primitive polynomial over GF(2): x^8 + x^6 + x^5 + x^4 + 1
+	                    LFSR = (LFSR << 1) ^ 0x71;
+	                } else {
+	                    LFSR <<= 1;
+	                }
+	            }
+
+	            ROUND_CONSTANTS[i] = X64Word.create(roundConstantMsw, roundConstantLsw);
+	        }
+	    }());
+
+	    // Reusable objects for temporary values
+	    var T = [];
+	    (function () {
+	        for (var i = 0; i < 25; i++) {
+	            T[i] = X64Word.create();
+	        }
+	    }());
+
+	    /**
+	     * SHA-3 hash algorithm.
+	     */
+	    var SHA3 = C_algo.SHA3 = Hasher.extend({
+	        /**
+	         * Configuration options.
+	         *
+	         * @property {number} outputLength
+	         *   The desired number of bits in the output hash.
+	         *   Only values permitted are: 224, 256, 384, 512.
+	         *   Default: 512
+	         */
+	        cfg: Hasher.cfg.extend({
+	            outputLength: 512
+	        }),
+
+	        _doReset: function () {
+	            var state = this._state = []
+	            for (var i = 0; i < 25; i++) {
+	                state[i] = new X64Word.init();
+	            }
+
+	            this.blockSize = (1600 - 2 * this.cfg.outputLength) / 32;
+	        },
+
+	        _doProcessBlock: function (M, offset) {
+	            // Shortcuts
+	            var state = this._state;
+	            var nBlockSizeLanes = this.blockSize / 2;
+
+	            // Absorb
+	            for (var i = 0; i < nBlockSizeLanes; i++) {
+	                // Shortcuts
+	                var M2i  = M[offset + 2 * i];
+	                var M2i1 = M[offset + 2 * i + 1];
+
+	                // Swap endian
+	                M2i = (
+	                    (((M2i << 8)  | (M2i >>> 24)) & 0x00ff00ff) |
+	                    (((M2i << 24) | (M2i >>> 8))  & 0xff00ff00)
+	                );
+	                M2i1 = (
+	                    (((M2i1 << 8)  | (M2i1 >>> 24)) & 0x00ff00ff) |
+	                    (((M2i1 << 24) | (M2i1 >>> 8))  & 0xff00ff00)
+	                );
+
+	                // Absorb message into state
+	                var lane = state[i];
+	                lane.high ^= M2i1;
+	                lane.low  ^= M2i;
+	            }
+
+	            // Rounds
+	            for (var round = 0; round < 24; round++) {
+	                // Theta
+	                for (var x = 0; x < 5; x++) {
+	                    // Mix column lanes
+	                    var tMsw = 0, tLsw = 0;
+	                    for (var y = 0; y < 5; y++) {
+	                        var lane = state[x + 5 * y];
+	                        tMsw ^= lane.high;
+	                        tLsw ^= lane.low;
+	                    }
+
+	                    // Temporary values
+	                    var Tx = T[x];
+	                    Tx.high = tMsw;
+	                    Tx.low  = tLsw;
+	                }
+	                for (var x = 0; x < 5; x++) {
+	                    // Shortcuts
+	                    var Tx4 = T[(x + 4) % 5];
+	                    var Tx1 = T[(x + 1) % 5];
+	                    var Tx1Msw = Tx1.high;
+	                    var Tx1Lsw = Tx1.low;
+
+	                    // Mix surrounding columns
+	                    var tMsw = Tx4.high ^ ((Tx1Msw << 1) | (Tx1Lsw >>> 31));
+	                    var tLsw = Tx4.low  ^ ((Tx1Lsw << 1) | (Tx1Msw >>> 31));
+	                    for (var y = 0; y < 5; y++) {
+	                        var lane = state[x + 5 * y];
+	                        lane.high ^= tMsw;
+	                        lane.low  ^= tLsw;
+	                    }
+	                }
+
+	                // Rho Pi
+	                for (var laneIndex = 1; laneIndex < 25; laneIndex++) {
+	                    var tMsw;
+	                    var tLsw;
+
+	                    // Shortcuts
+	                    var lane = state[laneIndex];
+	                    var laneMsw = lane.high;
+	                    var laneLsw = lane.low;
+	                    var rhoOffset = RHO_OFFSETS[laneIndex];
+
+	                    // Rotate lanes
+	                    if (rhoOffset < 32) {
+	                        tMsw = (laneMsw << rhoOffset) | (laneLsw >>> (32 - rhoOffset));
+	                        tLsw = (laneLsw << rhoOffset) | (laneMsw >>> (32 - rhoOffset));
+	                    } else /* if (rhoOffset >= 32) */ {
+	                        tMsw = (laneLsw << (rhoOffset - 32)) | (laneMsw >>> (64 - rhoOffset));
+	                        tLsw = (laneMsw << (rhoOffset - 32)) | (laneLsw >>> (64 - rhoOffset));
+	                    }
+
+	                    // Transpose lanes
+	                    var TPiLane = T[PI_INDEXES[laneIndex]];
+	                    TPiLane.high = tMsw;
+	                    TPiLane.low  = tLsw;
+	                }
+
+	                // Rho pi at x = y = 0
+	                var T0 = T[0];
+	                var state0 = state[0];
+	                T0.high = state0.high;
+	                T0.low  = state0.low;
+
+	                // Chi
+	                for (var x = 0; x < 5; x++) {
+	                    for (var y = 0; y < 5; y++) {
+	                        // Shortcuts
+	                        var laneIndex = x + 5 * y;
+	                        var lane = state[laneIndex];
+	                        var TLane = T[laneIndex];
+	                        var Tx1Lane = T[((x + 1) % 5) + 5 * y];
+	                        var Tx2Lane = T[((x + 2) % 5) + 5 * y];
+
+	                        // Mix rows
+	                        lane.high = TLane.high ^ (~Tx1Lane.high & Tx2Lane.high);
+	                        lane.low  = TLane.low  ^ (~Tx1Lane.low  & Tx2Lane.low);
+	                    }
+	                }
+
+	                // Iota
+	                var lane = state[0];
+	                var roundConstant = ROUND_CONSTANTS[round];
+	                lane.high ^= roundConstant.high;
+	                lane.low  ^= roundConstant.low;
+	            }
+	        },
+
+	        _doFinalize: function () {
+	            // Shortcuts
+	            var data = this._data;
+	            var dataWords = data.words;
+	            var nBitsTotal = this._nDataBytes * 8;
+	            var nBitsLeft = data.sigBytes * 8;
+	            var blockSizeBits = this.blockSize * 32;
+
+	            // Add padding
+	            dataWords[nBitsLeft >>> 5] |= 0x1 << (24 - nBitsLeft % 32);
+	            dataWords[((Math.ceil((nBitsLeft + 1) / blockSizeBits) * blockSizeBits) >>> 5) - 1] |= 0x80;
+	            data.sigBytes = dataWords.length * 4;
+
+	            // Hash final blocks
+	            this._process();
+
+	            // Shortcuts
+	            var state = this._state;
+	            var outputLengthBytes = this.cfg.outputLength / 8;
+	            var outputLengthLanes = outputLengthBytes / 8;
+
+	            // Squeeze
+	            var hashWords = [];
+	            for (var i = 0; i < outputLengthLanes; i++) {
+	                // Shortcuts
+	                var lane = state[i];
+	                var laneMsw = lane.high;
+	                var laneLsw = lane.low;
+
+	                // Swap endian
+	                laneMsw = (
+	                    (((laneMsw << 8)  | (laneMsw >>> 24)) & 0x00ff00ff) |
+	                    (((laneMsw << 24) | (laneMsw >>> 8))  & 0xff00ff00)
+	                );
+	                laneLsw = (
+	                    (((laneLsw << 8)  | (laneLsw >>> 24)) & 0x00ff00ff) |
+	                    (((laneLsw << 24) | (laneLsw >>> 8))  & 0xff00ff00)
+	                );
+
+	                // Squeeze state to retrieve hash
+	                hashWords.push(laneLsw);
+	                hashWords.push(laneMsw);
+	            }
+
+	            // Return final computed hash
+	            return new WordArray.init(hashWords, outputLengthBytes);
+	        },
+
+	        clone: function () {
+	            var clone = Hasher.clone.call(this);
+
+	            var state = clone._state = this._state.slice(0);
+	            for (var i = 0; i < 25; i++) {
+	                state[i] = state[i].clone();
+	            }
+
+	            return clone;
+	        }
+	    });
+
+	    /**
+	     * Shortcut function to the hasher's object interface.
+	     *
+	     * @param {WordArray|string} message The message to hash.
+	     *
+	     * @return {WordArray} The hash.
+	     *
+	     * @static
+	     *
+	     * @example
+	     *
+	     *     var hash = CryptoJS.SHA3('message');
+	     *     var hash = CryptoJS.SHA3(wordArray);
+	     */
+	    C.SHA3 = Hasher._createHelper(SHA3);
+
+	    /**
+	     * Shortcut function to the HMAC's object interface.
+	     *
+	     * @param {WordArray|string} message The message to hash.
+	     * @param {WordArray|string} key The secret key.
+	     *
+	     * @return {WordArray} The HMAC.
+	     *
+	     * @static
+	     *
+	     * @example
+	     *
+	     *     var hmac = CryptoJS.HmacSHA3(message, key);
+	     */
+	    C.HmacSHA3 = Hasher._createHmacHelper(SHA3);
+	}(Math));
+
+
+	return CryptoJS.SHA3;
+
+}));

+ 83 - 0
crypto-js/sha384.js

@@ -0,0 +1,83 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./x64-core"), require("./sha512"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./x64-core", "./sha512"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	(function () {
+	    // Shortcuts
+	    var C = CryptoJS;
+	    var C_x64 = C.x64;
+	    var X64Word = C_x64.Word;
+	    var X64WordArray = C_x64.WordArray;
+	    var C_algo = C.algo;
+	    var SHA512 = C_algo.SHA512;
+
+	    /**
+	     * SHA-384 hash algorithm.
+	     */
+	    var SHA384 = C_algo.SHA384 = SHA512.extend({
+	        _doReset: function () {
+	            this._hash = new X64WordArray.init([
+	                new X64Word.init(0xcbbb9d5d, 0xc1059ed8), new X64Word.init(0x629a292a, 0x367cd507),
+	                new X64Word.init(0x9159015a, 0x3070dd17), new X64Word.init(0x152fecd8, 0xf70e5939),
+	                new X64Word.init(0x67332667, 0xffc00b31), new X64Word.init(0x8eb44a87, 0x68581511),
+	                new X64Word.init(0xdb0c2e0d, 0x64f98fa7), new X64Word.init(0x47b5481d, 0xbefa4fa4)
+	            ]);
+	        },
+
+	        _doFinalize: function () {
+	            var hash = SHA512._doFinalize.call(this);
+
+	            hash.sigBytes -= 16;
+
+	            return hash;
+	        }
+	    });
+
+	    /**
+	     * Shortcut function to the hasher's object interface.
+	     *
+	     * @param {WordArray|string} message The message to hash.
+	     *
+	     * @return {WordArray} The hash.
+	     *
+	     * @static
+	     *
+	     * @example
+	     *
+	     *     var hash = CryptoJS.SHA384('message');
+	     *     var hash = CryptoJS.SHA384(wordArray);
+	     */
+	    C.SHA384 = SHA512._createHelper(SHA384);
+
+	    /**
+	     * Shortcut function to the HMAC's object interface.
+	     *
+	     * @param {WordArray|string} message The message to hash.
+	     * @param {WordArray|string} key The secret key.
+	     *
+	     * @return {WordArray} The HMAC.
+	     *
+	     * @static
+	     *
+	     * @example
+	     *
+	     *     var hmac = CryptoJS.HmacSHA384(message, key);
+	     */
+	    C.HmacSHA384 = SHA512._createHmacHelper(SHA384);
+	}());
+
+
+	return CryptoJS.SHA384;
+
+}));

+ 326 - 0
crypto-js/sha512.js

@@ -0,0 +1,326 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./x64-core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./x64-core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	(function () {
+	    // Shortcuts
+	    var C = CryptoJS;
+	    var C_lib = C.lib;
+	    var Hasher = C_lib.Hasher;
+	    var C_x64 = C.x64;
+	    var X64Word = C_x64.Word;
+	    var X64WordArray = C_x64.WordArray;
+	    var C_algo = C.algo;
+
+	    function X64Word_create() {
+	        return X64Word.create.apply(X64Word, arguments);
+	    }
+
+	    // Constants
+	    var K = [
+	        X64Word_create(0x428a2f98, 0xd728ae22), X64Word_create(0x71374491, 0x23ef65cd),
+	        X64Word_create(0xb5c0fbcf, 0xec4d3b2f), X64Word_create(0xe9b5dba5, 0x8189dbbc),
+	        X64Word_create(0x3956c25b, 0xf348b538), X64Word_create(0x59f111f1, 0xb605d019),
+	        X64Word_create(0x923f82a4, 0xaf194f9b), X64Word_create(0xab1c5ed5, 0xda6d8118),
+	        X64Word_create(0xd807aa98, 0xa3030242), X64Word_create(0x12835b01, 0x45706fbe),
+	        X64Word_create(0x243185be, 0x4ee4b28c), X64Word_create(0x550c7dc3, 0xd5ffb4e2),
+	        X64Word_create(0x72be5d74, 0xf27b896f), X64Word_create(0x80deb1fe, 0x3b1696b1),
+	        X64Word_create(0x9bdc06a7, 0x25c71235), X64Word_create(0xc19bf174, 0xcf692694),
+	        X64Word_create(0xe49b69c1, 0x9ef14ad2), X64Word_create(0xefbe4786, 0x384f25e3),
+	        X64Word_create(0x0fc19dc6, 0x8b8cd5b5), X64Word_create(0x240ca1cc, 0x77ac9c65),
+	        X64Word_create(0x2de92c6f, 0x592b0275), X64Word_create(0x4a7484aa, 0x6ea6e483),
+	        X64Word_create(0x5cb0a9dc, 0xbd41fbd4), X64Word_create(0x76f988da, 0x831153b5),
+	        X64Word_create(0x983e5152, 0xee66dfab), X64Word_create(0xa831c66d, 0x2db43210),
+	        X64Word_create(0xb00327c8, 0x98fb213f), X64Word_create(0xbf597fc7, 0xbeef0ee4),
+	        X64Word_create(0xc6e00bf3, 0x3da88fc2), X64Word_create(0xd5a79147, 0x930aa725),
+	        X64Word_create(0x06ca6351, 0xe003826f), X64Word_create(0x14292967, 0x0a0e6e70),
+	        X64Word_create(0x27b70a85, 0x46d22ffc), X64Word_create(0x2e1b2138, 0x5c26c926),
+	        X64Word_create(0x4d2c6dfc, 0x5ac42aed), X64Word_create(0x53380d13, 0x9d95b3df),
+	        X64Word_create(0x650a7354, 0x8baf63de), X64Word_create(0x766a0abb, 0x3c77b2a8),
+	        X64Word_create(0x81c2c92e, 0x47edaee6), X64Word_create(0x92722c85, 0x1482353b),
+	        X64Word_create(0xa2bfe8a1, 0x4cf10364), X64Word_create(0xa81a664b, 0xbc423001),
+	        X64Word_create(0xc24b8b70, 0xd0f89791), X64Word_create(0xc76c51a3, 0x0654be30),
+	        X64Word_create(0xd192e819, 0xd6ef5218), X64Word_create(0xd6990624, 0x5565a910),
+	        X64Word_create(0xf40e3585, 0x5771202a), X64Word_create(0x106aa070, 0x32bbd1b8),
+	        X64Word_create(0x19a4c116, 0xb8d2d0c8), X64Word_create(0x1e376c08, 0x5141ab53),
+	        X64Word_create(0x2748774c, 0xdf8eeb99), X64Word_create(0x34b0bcb5, 0xe19b48a8),
+	        X64Word_create(0x391c0cb3, 0xc5c95a63), X64Word_create(0x4ed8aa4a, 0xe3418acb),
+	        X64Word_create(0x5b9cca4f, 0x7763e373), X64Word_create(0x682e6ff3, 0xd6b2b8a3),
+	        X64Word_create(0x748f82ee, 0x5defb2fc), X64Word_create(0x78a5636f, 0x43172f60),
+	        X64Word_create(0x84c87814, 0xa1f0ab72), X64Word_create(0x8cc70208, 0x1a6439ec),
+	        X64Word_create(0x90befffa, 0x23631e28), X64Word_create(0xa4506ceb, 0xde82bde9),
+	        X64Word_create(0xbef9a3f7, 0xb2c67915), X64Word_create(0xc67178f2, 0xe372532b),
+	        X64Word_create(0xca273ece, 0xea26619c), X64Word_create(0xd186b8c7, 0x21c0c207),
+	        X64Word_create(0xeada7dd6, 0xcde0eb1e), X64Word_create(0xf57d4f7f, 0xee6ed178),
+	        X64Word_create(0x06f067aa, 0x72176fba), X64Word_create(0x0a637dc5, 0xa2c898a6),
+	        X64Word_create(0x113f9804, 0xbef90dae), X64Word_create(0x1b710b35, 0x131c471b),
+	        X64Word_create(0x28db77f5, 0x23047d84), X64Word_create(0x32caab7b, 0x40c72493),
+	        X64Word_create(0x3c9ebe0a, 0x15c9bebc), X64Word_create(0x431d67c4, 0x9c100d4c),
+	        X64Word_create(0x4cc5d4be, 0xcb3e42b6), X64Word_create(0x597f299c, 0xfc657e2a),
+	        X64Word_create(0x5fcb6fab, 0x3ad6faec), X64Word_create(0x6c44198c, 0x4a475817)
+	    ];
+
+	    // Reusable objects
+	    var W = [];
+	    (function () {
+	        for (var i = 0; i < 80; i++) {
+	            W[i] = X64Word_create();
+	        }
+	    }());
+
+	    /**
+	     * SHA-512 hash algorithm.
+	     */
+	    var SHA512 = C_algo.SHA512 = Hasher.extend({
+	        _doReset: function () {
+	            this._hash = new X64WordArray.init([
+	                new X64Word.init(0x6a09e667, 0xf3bcc908), new X64Word.init(0xbb67ae85, 0x84caa73b),
+	                new X64Word.init(0x3c6ef372, 0xfe94f82b), new X64Word.init(0xa54ff53a, 0x5f1d36f1),
+	                new X64Word.init(0x510e527f, 0xade682d1), new X64Word.init(0x9b05688c, 0x2b3e6c1f),
+	                new X64Word.init(0x1f83d9ab, 0xfb41bd6b), new X64Word.init(0x5be0cd19, 0x137e2179)
+	            ]);
+	        },
+
+	        _doProcessBlock: function (M, offset) {
+	            // Shortcuts
+	            var H = this._hash.words;
+
+	            var H0 = H[0];
+	            var H1 = H[1];
+	            var H2 = H[2];
+	            var H3 = H[3];
+	            var H4 = H[4];
+	            var H5 = H[5];
+	            var H6 = H[6];
+	            var H7 = H[7];
+
+	            var H0h = H0.high;
+	            var H0l = H0.low;
+	            var H1h = H1.high;
+	            var H1l = H1.low;
+	            var H2h = H2.high;
+	            var H2l = H2.low;
+	            var H3h = H3.high;
+	            var H3l = H3.low;
+	            var H4h = H4.high;
+	            var H4l = H4.low;
+	            var H5h = H5.high;
+	            var H5l = H5.low;
+	            var H6h = H6.high;
+	            var H6l = H6.low;
+	            var H7h = H7.high;
+	            var H7l = H7.low;
+
+	            // Working variables
+	            var ah = H0h;
+	            var al = H0l;
+	            var bh = H1h;
+	            var bl = H1l;
+	            var ch = H2h;
+	            var cl = H2l;
+	            var dh = H3h;
+	            var dl = H3l;
+	            var eh = H4h;
+	            var el = H4l;
+	            var fh = H5h;
+	            var fl = H5l;
+	            var gh = H6h;
+	            var gl = H6l;
+	            var hh = H7h;
+	            var hl = H7l;
+
+	            // Rounds
+	            for (var i = 0; i < 80; i++) {
+	                var Wil;
+	                var Wih;
+
+	                // Shortcut
+	                var Wi = W[i];
+
+	                // Extend message
+	                if (i < 16) {
+	                    Wih = Wi.high = M[offset + i * 2]     | 0;
+	                    Wil = Wi.low  = M[offset + i * 2 + 1] | 0;
+	                } else {
+	                    // Gamma0
+	                    var gamma0x  = W[i - 15];
+	                    var gamma0xh = gamma0x.high;
+	                    var gamma0xl = gamma0x.low;
+	                    var gamma0h  = ((gamma0xh >>> 1) | (gamma0xl << 31)) ^ ((gamma0xh >>> 8) | (gamma0xl << 24)) ^ (gamma0xh >>> 7);
+	                    var gamma0l  = ((gamma0xl >>> 1) | (gamma0xh << 31)) ^ ((gamma0xl >>> 8) | (gamma0xh << 24)) ^ ((gamma0xl >>> 7) | (gamma0xh << 25));
+
+	                    // Gamma1
+	                    var gamma1x  = W[i - 2];
+	                    var gamma1xh = gamma1x.high;
+	                    var gamma1xl = gamma1x.low;
+	                    var gamma1h  = ((gamma1xh >>> 19) | (gamma1xl << 13)) ^ ((gamma1xh << 3) | (gamma1xl >>> 29)) ^ (gamma1xh >>> 6);
+	                    var gamma1l  = ((gamma1xl >>> 19) | (gamma1xh << 13)) ^ ((gamma1xl << 3) | (gamma1xh >>> 29)) ^ ((gamma1xl >>> 6) | (gamma1xh << 26));
+
+	                    // W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16]
+	                    var Wi7  = W[i - 7];
+	                    var Wi7h = Wi7.high;
+	                    var Wi7l = Wi7.low;
+
+	                    var Wi16  = W[i - 16];
+	                    var Wi16h = Wi16.high;
+	                    var Wi16l = Wi16.low;
+
+	                    Wil = gamma0l + Wi7l;
+	                    Wih = gamma0h + Wi7h + ((Wil >>> 0) < (gamma0l >>> 0) ? 1 : 0);
+	                    Wil = Wil + gamma1l;
+	                    Wih = Wih + gamma1h + ((Wil >>> 0) < (gamma1l >>> 0) ? 1 : 0);
+	                    Wil = Wil + Wi16l;
+	                    Wih = Wih + Wi16h + ((Wil >>> 0) < (Wi16l >>> 0) ? 1 : 0);
+
+	                    Wi.high = Wih;
+	                    Wi.low  = Wil;
+	                }
+
+	                var chh  = (eh & fh) ^ (~eh & gh);
+	                var chl  = (el & fl) ^ (~el & gl);
+	                var majh = (ah & bh) ^ (ah & ch) ^ (bh & ch);
+	                var majl = (al & bl) ^ (al & cl) ^ (bl & cl);
+
+	                var sigma0h = ((ah >>> 28) | (al << 4))  ^ ((ah << 30)  | (al >>> 2)) ^ ((ah << 25) | (al >>> 7));
+	                var sigma0l = ((al >>> 28) | (ah << 4))  ^ ((al << 30)  | (ah >>> 2)) ^ ((al << 25) | (ah >>> 7));
+	                var sigma1h = ((eh >>> 14) | (el << 18)) ^ ((eh >>> 18) | (el << 14)) ^ ((eh << 23) | (el >>> 9));
+	                var sigma1l = ((el >>> 14) | (eh << 18)) ^ ((el >>> 18) | (eh << 14)) ^ ((el << 23) | (eh >>> 9));
+
+	                // t1 = h + sigma1 + ch + K[i] + W[i]
+	                var Ki  = K[i];
+	                var Kih = Ki.high;
+	                var Kil = Ki.low;
+
+	                var t1l = hl + sigma1l;
+	                var t1h = hh + sigma1h + ((t1l >>> 0) < (hl >>> 0) ? 1 : 0);
+	                var t1l = t1l + chl;
+	                var t1h = t1h + chh + ((t1l >>> 0) < (chl >>> 0) ? 1 : 0);
+	                var t1l = t1l + Kil;
+	                var t1h = t1h + Kih + ((t1l >>> 0) < (Kil >>> 0) ? 1 : 0);
+	                var t1l = t1l + Wil;
+	                var t1h = t1h + Wih + ((t1l >>> 0) < (Wil >>> 0) ? 1 : 0);
+
+	                // t2 = sigma0 + maj
+	                var t2l = sigma0l + majl;
+	                var t2h = sigma0h + majh + ((t2l >>> 0) < (sigma0l >>> 0) ? 1 : 0);
+
+	                // Update working variables
+	                hh = gh;
+	                hl = gl;
+	                gh = fh;
+	                gl = fl;
+	                fh = eh;
+	                fl = el;
+	                el = (dl + t1l) | 0;
+	                eh = (dh + t1h + ((el >>> 0) < (dl >>> 0) ? 1 : 0)) | 0;
+	                dh = ch;
+	                dl = cl;
+	                ch = bh;
+	                cl = bl;
+	                bh = ah;
+	                bl = al;
+	                al = (t1l + t2l) | 0;
+	                ah = (t1h + t2h + ((al >>> 0) < (t1l >>> 0) ? 1 : 0)) | 0;
+	            }
+
+	            // Intermediate hash value
+	            H0l = H0.low  = (H0l + al);
+	            H0.high = (H0h + ah + ((H0l >>> 0) < (al >>> 0) ? 1 : 0));
+	            H1l = H1.low  = (H1l + bl);
+	            H1.high = (H1h + bh + ((H1l >>> 0) < (bl >>> 0) ? 1 : 0));
+	            H2l = H2.low  = (H2l + cl);
+	            H2.high = (H2h + ch + ((H2l >>> 0) < (cl >>> 0) ? 1 : 0));
+	            H3l = H3.low  = (H3l + dl);
+	            H3.high = (H3h + dh + ((H3l >>> 0) < (dl >>> 0) ? 1 : 0));
+	            H4l = H4.low  = (H4l + el);
+	            H4.high = (H4h + eh + ((H4l >>> 0) < (el >>> 0) ? 1 : 0));
+	            H5l = H5.low  = (H5l + fl);
+	            H5.high = (H5h + fh + ((H5l >>> 0) < (fl >>> 0) ? 1 : 0));
+	            H6l = H6.low  = (H6l + gl);
+	            H6.high = (H6h + gh + ((H6l >>> 0) < (gl >>> 0) ? 1 : 0));
+	            H7l = H7.low  = (H7l + hl);
+	            H7.high = (H7h + hh + ((H7l >>> 0) < (hl >>> 0) ? 1 : 0));
+	        },
+
+	        _doFinalize: function () {
+	            // Shortcuts
+	            var data = this._data;
+	            var dataWords = data.words;
+
+	            var nBitsTotal = this._nDataBytes * 8;
+	            var nBitsLeft = data.sigBytes * 8;
+
+	            // Add padding
+	            dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
+	            dataWords[(((nBitsLeft + 128) >>> 10) << 5) + 30] = Math.floor(nBitsTotal / 0x100000000);
+	            dataWords[(((nBitsLeft + 128) >>> 10) << 5) + 31] = nBitsTotal;
+	            data.sigBytes = dataWords.length * 4;
+
+	            // Hash final blocks
+	            this._process();
+
+	            // Convert hash to 32-bit word array before returning
+	            var hash = this._hash.toX32();
+
+	            // Return final computed hash
+	            return hash;
+	        },
+
+	        clone: function () {
+	            var clone = Hasher.clone.call(this);
+	            clone._hash = this._hash.clone();
+
+	            return clone;
+	        },
+
+	        blockSize: 1024/32
+	    });
+
+	    /**
+	     * Shortcut function to the hasher's object interface.
+	     *
+	     * @param {WordArray|string} message The message to hash.
+	     *
+	     * @return {WordArray} The hash.
+	     *
+	     * @static
+	     *
+	     * @example
+	     *
+	     *     var hash = CryptoJS.SHA512('message');
+	     *     var hash = CryptoJS.SHA512(wordArray);
+	     */
+	    C.SHA512 = Hasher._createHelper(SHA512);
+
+	    /**
+	     * Shortcut function to the HMAC's object interface.
+	     *
+	     * @param {WordArray|string} message The message to hash.
+	     * @param {WordArray|string} key The secret key.
+	     *
+	     * @return {WordArray} The HMAC.
+	     *
+	     * @static
+	     *
+	     * @example
+	     *
+	     *     var hmac = CryptoJS.HmacSHA512(message, key);
+	     */
+	    C.HmacSHA512 = Hasher._createHmacHelper(SHA512);
+	}());
+
+
+	return CryptoJS.SHA512;
+
+}));

+ 779 - 0
crypto-js/tripledes.js

@@ -0,0 +1,779 @@
+;(function (root, factory, undef) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	(function () {
+	    // Shortcuts
+	    var C = CryptoJS;
+	    var C_lib = C.lib;
+	    var WordArray = C_lib.WordArray;
+	    var BlockCipher = C_lib.BlockCipher;
+	    var C_algo = C.algo;
+
+	    // Permuted Choice 1 constants
+	    var PC1 = [
+	        57, 49, 41, 33, 25, 17, 9,  1,
+	        58, 50, 42, 34, 26, 18, 10, 2,
+	        59, 51, 43, 35, 27, 19, 11, 3,
+	        60, 52, 44, 36, 63, 55, 47, 39,
+	        31, 23, 15, 7,  62, 54, 46, 38,
+	        30, 22, 14, 6,  61, 53, 45, 37,
+	        29, 21, 13, 5,  28, 20, 12, 4
+	    ];
+
+	    // Permuted Choice 2 constants
+	    var PC2 = [
+	        14, 17, 11, 24, 1,  5,
+	        3,  28, 15, 6,  21, 10,
+	        23, 19, 12, 4,  26, 8,
+	        16, 7,  27, 20, 13, 2,
+	        41, 52, 31, 37, 47, 55,
+	        30, 40, 51, 45, 33, 48,
+	        44, 49, 39, 56, 34, 53,
+	        46, 42, 50, 36, 29, 32
+	    ];
+
+	    // Cumulative bit shift constants
+	    var BIT_SHIFTS = [1,  2,  4,  6,  8,  10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28];
+
+	    // SBOXes and round permutation constants
+	    var SBOX_P = [
+	        {
+	            0x0: 0x808200,
+	            0x10000000: 0x8000,
+	            0x20000000: 0x808002,
+	            0x30000000: 0x2,
+	            0x40000000: 0x200,
+	            0x50000000: 0x808202,
+	            0x60000000: 0x800202,
+	            0x70000000: 0x800000,
+	            0x80000000: 0x202,
+	            0x90000000: 0x800200,
+	            0xa0000000: 0x8200,
+	            0xb0000000: 0x808000,
+	            0xc0000000: 0x8002,
+	            0xd0000000: 0x800002,
+	            0xe0000000: 0x0,
+	            0xf0000000: 0x8202,
+	            0x8000000: 0x0,
+	            0x18000000: 0x808202,
+	            0x28000000: 0x8202,
+	            0x38000000: 0x8000,
+	            0x48000000: 0x808200,
+	            0x58000000: 0x200,
+	            0x68000000: 0x808002,
+	            0x78000000: 0x2,
+	            0x88000000: 0x800200,
+	            0x98000000: 0x8200,
+	            0xa8000000: 0x808000,
+	            0xb8000000: 0x800202,
+	            0xc8000000: 0x800002,
+	            0xd8000000: 0x8002,
+	            0xe8000000: 0x202,
+	            0xf8000000: 0x800000,
+	            0x1: 0x8000,
+	            0x10000001: 0x2,
+	            0x20000001: 0x808200,
+	            0x30000001: 0x800000,
+	            0x40000001: 0x808002,
+	            0x50000001: 0x8200,
+	            0x60000001: 0x200,
+	            0x70000001: 0x800202,
+	            0x80000001: 0x808202,
+	            0x90000001: 0x808000,
+	            0xa0000001: 0x800002,
+	            0xb0000001: 0x8202,
+	            0xc0000001: 0x202,
+	            0xd0000001: 0x800200,
+	            0xe0000001: 0x8002,
+	            0xf0000001: 0x0,
+	            0x8000001: 0x808202,
+	            0x18000001: 0x808000,
+	            0x28000001: 0x800000,
+	            0x38000001: 0x200,
+	            0x48000001: 0x8000,
+	            0x58000001: 0x800002,
+	            0x68000001: 0x2,
+	            0x78000001: 0x8202,
+	            0x88000001: 0x8002,
+	            0x98000001: 0x800202,
+	            0xa8000001: 0x202,
+	            0xb8000001: 0x808200,
+	            0xc8000001: 0x800200,
+	            0xd8000001: 0x0,
+	            0xe8000001: 0x8200,
+	            0xf8000001: 0x808002
+	        },
+	        {
+	            0x0: 0x40084010,
+	            0x1000000: 0x4000,
+	            0x2000000: 0x80000,
+	            0x3000000: 0x40080010,
+	            0x4000000: 0x40000010,
+	            0x5000000: 0x40084000,
+	            0x6000000: 0x40004000,
+	            0x7000000: 0x10,
+	            0x8000000: 0x84000,
+	            0x9000000: 0x40004010,
+	            0xa000000: 0x40000000,
+	            0xb000000: 0x84010,
+	            0xc000000: 0x80010,
+	            0xd000000: 0x0,
+	            0xe000000: 0x4010,
+	            0xf000000: 0x40080000,
+	            0x800000: 0x40004000,
+	            0x1800000: 0x84010,
+	            0x2800000: 0x10,
+	            0x3800000: 0x40004010,
+	            0x4800000: 0x40084010,
+	            0x5800000: 0x40000000,
+	            0x6800000: 0x80000,
+	            0x7800000: 0x40080010,
+	            0x8800000: 0x80010,
+	            0x9800000: 0x0,
+	            0xa800000: 0x4000,
+	            0xb800000: 0x40080000,
+	            0xc800000: 0x40000010,
+	            0xd800000: 0x84000,
+	            0xe800000: 0x40084000,
+	            0xf800000: 0x4010,
+	            0x10000000: 0x0,
+	            0x11000000: 0x40080010,
+	            0x12000000: 0x40004010,
+	            0x13000000: 0x40084000,
+	            0x14000000: 0x40080000,
+	            0x15000000: 0x10,
+	            0x16000000: 0x84010,
+	            0x17000000: 0x4000,
+	            0x18000000: 0x4010,
+	            0x19000000: 0x80000,
+	            0x1a000000: 0x80010,
+	            0x1b000000: 0x40000010,
+	            0x1c000000: 0x84000,
+	            0x1d000000: 0x40004000,
+	            0x1e000000: 0x40000000,
+	            0x1f000000: 0x40084010,
+	            0x10800000: 0x84010,
+	            0x11800000: 0x80000,
+	            0x12800000: 0x40080000,
+	            0x13800000: 0x4000,
+	            0x14800000: 0x40004000,
+	            0x15800000: 0x40084010,
+	            0x16800000: 0x10,
+	            0x17800000: 0x40000000,
+	            0x18800000: 0x40084000,
+	            0x19800000: 0x40000010,
+	            0x1a800000: 0x40004010,
+	            0x1b800000: 0x80010,
+	            0x1c800000: 0x0,
+	            0x1d800000: 0x4010,
+	            0x1e800000: 0x40080010,
+	            0x1f800000: 0x84000
+	        },
+	        {
+	            0x0: 0x104,
+	            0x100000: 0x0,
+	            0x200000: 0x4000100,
+	            0x300000: 0x10104,
+	            0x400000: 0x10004,
+	            0x500000: 0x4000004,
+	            0x600000: 0x4010104,
+	            0x700000: 0x4010000,
+	            0x800000: 0x4000000,
+	            0x900000: 0x4010100,
+	            0xa00000: 0x10100,
+	            0xb00000: 0x4010004,
+	            0xc00000: 0x4000104,
+	            0xd00000: 0x10000,
+	            0xe00000: 0x4,
+	            0xf00000: 0x100,
+	            0x80000: 0x4010100,
+	            0x180000: 0x4010004,
+	            0x280000: 0x0,
+	            0x380000: 0x4000100,
+	            0x480000: 0x4000004,
+	            0x580000: 0x10000,
+	            0x680000: 0x10004,
+	            0x780000: 0x104,
+	            0x880000: 0x4,
+	            0x980000: 0x100,
+	            0xa80000: 0x4010000,
+	            0xb80000: 0x10104,
+	            0xc80000: 0x10100,
+	            0xd80000: 0x4000104,
+	            0xe80000: 0x4010104,
+	            0xf80000: 0x4000000,
+	            0x1000000: 0x4010100,
+	            0x1100000: 0x10004,
+	            0x1200000: 0x10000,
+	            0x1300000: 0x4000100,
+	            0x1400000: 0x100,
+	            0x1500000: 0x4010104,
+	            0x1600000: 0x4000004,
+	            0x1700000: 0x0,
+	            0x1800000: 0x4000104,
+	            0x1900000: 0x4000000,
+	            0x1a00000: 0x4,
+	            0x1b00000: 0x10100,
+	            0x1c00000: 0x4010000,
+	            0x1d00000: 0x104,
+	            0x1e00000: 0x10104,
+	            0x1f00000: 0x4010004,
+	            0x1080000: 0x4000000,
+	            0x1180000: 0x104,
+	            0x1280000: 0x4010100,
+	            0x1380000: 0x0,
+	            0x1480000: 0x10004,
+	            0x1580000: 0x4000100,
+	            0x1680000: 0x100,
+	            0x1780000: 0x4010004,
+	            0x1880000: 0x10000,
+	            0x1980000: 0x4010104,
+	            0x1a80000: 0x10104,
+	            0x1b80000: 0x4000004,
+	            0x1c80000: 0x4000104,
+	            0x1d80000: 0x4010000,
+	            0x1e80000: 0x4,
+	            0x1f80000: 0x10100
+	        },
+	        {
+	            0x0: 0x80401000,
+	            0x10000: 0x80001040,
+	            0x20000: 0x401040,
+	            0x30000: 0x80400000,
+	            0x40000: 0x0,
+	            0x50000: 0x401000,
+	            0x60000: 0x80000040,
+	            0x70000: 0x400040,
+	            0x80000: 0x80000000,
+	            0x90000: 0x400000,
+	            0xa0000: 0x40,
+	            0xb0000: 0x80001000,
+	            0xc0000: 0x80400040,
+	            0xd0000: 0x1040,
+	            0xe0000: 0x1000,
+	            0xf0000: 0x80401040,
+	            0x8000: 0x80001040,
+	            0x18000: 0x40,
+	            0x28000: 0x80400040,
+	            0x38000: 0x80001000,
+	            0x48000: 0x401000,
+	            0x58000: 0x80401040,
+	            0x68000: 0x0,
+	            0x78000: 0x80400000,
+	            0x88000: 0x1000,
+	            0x98000: 0x80401000,
+	            0xa8000: 0x400000,
+	            0xb8000: 0x1040,
+	            0xc8000: 0x80000000,
+	            0xd8000: 0x400040,
+	            0xe8000: 0x401040,
+	            0xf8000: 0x80000040,
+	            0x100000: 0x400040,
+	            0x110000: 0x401000,
+	            0x120000: 0x80000040,
+	            0x130000: 0x0,
+	            0x140000: 0x1040,
+	            0x150000: 0x80400040,
+	            0x160000: 0x80401000,
+	            0x170000: 0x80001040,
+	            0x180000: 0x80401040,
+	            0x190000: 0x80000000,
+	            0x1a0000: 0x80400000,
+	            0x1b0000: 0x401040,
+	            0x1c0000: 0x80001000,
+	            0x1d0000: 0x400000,
+	            0x1e0000: 0x40,
+	            0x1f0000: 0x1000,
+	            0x108000: 0x80400000,
+	            0x118000: 0x80401040,
+	            0x128000: 0x0,
+	            0x138000: 0x401000,
+	            0x148000: 0x400040,
+	            0x158000: 0x80000000,
+	            0x168000: 0x80001040,
+	            0x178000: 0x40,
+	            0x188000: 0x80000040,
+	            0x198000: 0x1000,
+	            0x1a8000: 0x80001000,
+	            0x1b8000: 0x80400040,
+	            0x1c8000: 0x1040,
+	            0x1d8000: 0x80401000,
+	            0x1e8000: 0x400000,
+	            0x1f8000: 0x401040
+	        },
+	        {
+	            0x0: 0x80,
+	            0x1000: 0x1040000,
+	            0x2000: 0x40000,
+	            0x3000: 0x20000000,
+	            0x4000: 0x20040080,
+	            0x5000: 0x1000080,
+	            0x6000: 0x21000080,
+	            0x7000: 0x40080,
+	            0x8000: 0x1000000,
+	            0x9000: 0x20040000,
+	            0xa000: 0x20000080,
+	            0xb000: 0x21040080,
+	            0xc000: 0x21040000,
+	            0xd000: 0x0,
+	            0xe000: 0x1040080,
+	            0xf000: 0x21000000,
+	            0x800: 0x1040080,
+	            0x1800: 0x21000080,
+	            0x2800: 0x80,
+	            0x3800: 0x1040000,
+	            0x4800: 0x40000,
+	            0x5800: 0x20040080,
+	            0x6800: 0x21040000,
+	            0x7800: 0x20000000,
+	            0x8800: 0x20040000,
+	            0x9800: 0x0,
+	            0xa800: 0x21040080,
+	            0xb800: 0x1000080,
+	            0xc800: 0x20000080,
+	            0xd800: 0x21000000,
+	            0xe800: 0x1000000,
+	            0xf800: 0x40080,
+	            0x10000: 0x40000,
+	            0x11000: 0x80,
+	            0x12000: 0x20000000,
+	            0x13000: 0x21000080,
+	            0x14000: 0x1000080,
+	            0x15000: 0x21040000,
+	            0x16000: 0x20040080,
+	            0x17000: 0x1000000,
+	            0x18000: 0x21040080,
+	            0x19000: 0x21000000,
+	            0x1a000: 0x1040000,
+	            0x1b000: 0x20040000,
+	            0x1c000: 0x40080,
+	            0x1d000: 0x20000080,
+	            0x1e000: 0x0,
+	            0x1f000: 0x1040080,
+	            0x10800: 0x21000080,
+	            0x11800: 0x1000000,
+	            0x12800: 0x1040000,
+	            0x13800: 0x20040080,
+	            0x14800: 0x20000000,
+	            0x15800: 0x1040080,
+	            0x16800: 0x80,
+	            0x17800: 0x21040000,
+	            0x18800: 0x40080,
+	            0x19800: 0x21040080,
+	            0x1a800: 0x0,
+	            0x1b800: 0x21000000,
+	            0x1c800: 0x1000080,
+	            0x1d800: 0x40000,
+	            0x1e800: 0x20040000,
+	            0x1f800: 0x20000080
+	        },
+	        {
+	            0x0: 0x10000008,
+	            0x100: 0x2000,
+	            0x200: 0x10200000,
+	            0x300: 0x10202008,
+	            0x400: 0x10002000,
+	            0x500: 0x200000,
+	            0x600: 0x200008,
+	            0x700: 0x10000000,
+	            0x800: 0x0,
+	            0x900: 0x10002008,
+	            0xa00: 0x202000,
+	            0xb00: 0x8,
+	            0xc00: 0x10200008,
+	            0xd00: 0x202008,
+	            0xe00: 0x2008,
+	            0xf00: 0x10202000,
+	            0x80: 0x10200000,
+	            0x180: 0x10202008,
+	            0x280: 0x8,
+	            0x380: 0x200000,
+	            0x480: 0x202008,
+	            0x580: 0x10000008,
+	            0x680: 0x10002000,
+	            0x780: 0x2008,
+	            0x880: 0x200008,
+	            0x980: 0x2000,
+	            0xa80: 0x10002008,
+	            0xb80: 0x10200008,
+	            0xc80: 0x0,
+	            0xd80: 0x10202000,
+	            0xe80: 0x202000,
+	            0xf80: 0x10000000,
+	            0x1000: 0x10002000,
+	            0x1100: 0x10200008,
+	            0x1200: 0x10202008,
+	            0x1300: 0x2008,
+	            0x1400: 0x200000,
+	            0x1500: 0x10000000,
+	            0x1600: 0x10000008,
+	            0x1700: 0x202000,
+	            0x1800: 0x202008,
+	            0x1900: 0x0,
+	            0x1a00: 0x8,
+	            0x1b00: 0x10200000,
+	            0x1c00: 0x2000,
+	            0x1d00: 0x10002008,
+	            0x1e00: 0x10202000,
+	            0x1f00: 0x200008,
+	            0x1080: 0x8,
+	            0x1180: 0x202000,
+	            0x1280: 0x200000,
+	            0x1380: 0x10000008,
+	            0x1480: 0x10002000,
+	            0x1580: 0x2008,
+	            0x1680: 0x10202008,
+	            0x1780: 0x10200000,
+	            0x1880: 0x10202000,
+	            0x1980: 0x10200008,
+	            0x1a80: 0x2000,
+	            0x1b80: 0x202008,
+	            0x1c80: 0x200008,
+	            0x1d80: 0x0,
+	            0x1e80: 0x10000000,
+	            0x1f80: 0x10002008
+	        },
+	        {
+	            0x0: 0x100000,
+	            0x10: 0x2000401,
+	            0x20: 0x400,
+	            0x30: 0x100401,
+	            0x40: 0x2100401,
+	            0x50: 0x0,
+	            0x60: 0x1,
+	            0x70: 0x2100001,
+	            0x80: 0x2000400,
+	            0x90: 0x100001,
+	            0xa0: 0x2000001,
+	            0xb0: 0x2100400,
+	            0xc0: 0x2100000,
+	            0xd0: 0x401,
+	            0xe0: 0x100400,
+	            0xf0: 0x2000000,
+	            0x8: 0x2100001,
+	            0x18: 0x0,
+	            0x28: 0x2000401,
+	            0x38: 0x2100400,
+	            0x48: 0x100000,
+	            0x58: 0x2000001,
+	            0x68: 0x2000000,
+	            0x78: 0x401,
+	            0x88: 0x100401,
+	            0x98: 0x2000400,
+	            0xa8: 0x2100000,
+	            0xb8: 0x100001,
+	            0xc8: 0x400,
+	            0xd8: 0x2100401,
+	            0xe8: 0x1,
+	            0xf8: 0x100400,
+	            0x100: 0x2000000,
+	            0x110: 0x100000,
+	            0x120: 0x2000401,
+	            0x130: 0x2100001,
+	            0x140: 0x100001,
+	            0x150: 0x2000400,
+	            0x160: 0x2100400,
+	            0x170: 0x100401,
+	            0x180: 0x401,
+	            0x190: 0x2100401,
+	            0x1a0: 0x100400,
+	            0x1b0: 0x1,
+	            0x1c0: 0x0,
+	            0x1d0: 0x2100000,
+	            0x1e0: 0x2000001,
+	            0x1f0: 0x400,
+	            0x108: 0x100400,
+	            0x118: 0x2000401,
+	            0x128: 0x2100001,
+	            0x138: 0x1,
+	            0x148: 0x2000000,
+	            0x158: 0x100000,
+	            0x168: 0x401,
+	            0x178: 0x2100400,
+	            0x188: 0x2000001,
+	            0x198: 0x2100000,
+	            0x1a8: 0x0,
+	            0x1b8: 0x2100401,
+	            0x1c8: 0x100401,
+	            0x1d8: 0x400,
+	            0x1e8: 0x2000400,
+	            0x1f8: 0x100001
+	        },
+	        {
+	            0x0: 0x8000820,
+	            0x1: 0x20000,
+	            0x2: 0x8000000,
+	            0x3: 0x20,
+	            0x4: 0x20020,
+	            0x5: 0x8020820,
+	            0x6: 0x8020800,
+	            0x7: 0x800,
+	            0x8: 0x8020000,
+	            0x9: 0x8000800,
+	            0xa: 0x20800,
+	            0xb: 0x8020020,
+	            0xc: 0x820,
+	            0xd: 0x0,
+	            0xe: 0x8000020,
+	            0xf: 0x20820,
+	            0x80000000: 0x800,
+	            0x80000001: 0x8020820,
+	            0x80000002: 0x8000820,
+	            0x80000003: 0x8000000,
+	            0x80000004: 0x8020000,
+	            0x80000005: 0x20800,
+	            0x80000006: 0x20820,
+	            0x80000007: 0x20,
+	            0x80000008: 0x8000020,
+	            0x80000009: 0x820,
+	            0x8000000a: 0x20020,
+	            0x8000000b: 0x8020800,
+	            0x8000000c: 0x0,
+	            0x8000000d: 0x8020020,
+	            0x8000000e: 0x8000800,
+	            0x8000000f: 0x20000,
+	            0x10: 0x20820,
+	            0x11: 0x8020800,
+	            0x12: 0x20,
+	            0x13: 0x800,
+	            0x14: 0x8000800,
+	            0x15: 0x8000020,
+	            0x16: 0x8020020,
+	            0x17: 0x20000,
+	            0x18: 0x0,
+	            0x19: 0x20020,
+	            0x1a: 0x8020000,
+	            0x1b: 0x8000820,
+	            0x1c: 0x8020820,
+	            0x1d: 0x20800,
+	            0x1e: 0x820,
+	            0x1f: 0x8000000,
+	            0x80000010: 0x20000,
+	            0x80000011: 0x800,
+	            0x80000012: 0x8020020,
+	            0x80000013: 0x20820,
+	            0x80000014: 0x20,
+	            0x80000015: 0x8020000,
+	            0x80000016: 0x8000000,
+	            0x80000017: 0x8000820,
+	            0x80000018: 0x8020820,
+	            0x80000019: 0x8000020,
+	            0x8000001a: 0x8000800,
+	            0x8000001b: 0x0,
+	            0x8000001c: 0x20800,
+	            0x8000001d: 0x820,
+	            0x8000001e: 0x20020,
+	            0x8000001f: 0x8020800
+	        }
+	    ];
+
+	    // Masks that select the SBOX input
+	    var SBOX_MASK = [
+	        0xf8000001, 0x1f800000, 0x01f80000, 0x001f8000,
+	        0x0001f800, 0x00001f80, 0x000001f8, 0x8000001f
+	    ];
+
+	    /**
+	     * DES block cipher algorithm.
+	     */
+	    var DES = C_algo.DES = BlockCipher.extend({
+	        _doReset: function () {
+	            // Shortcuts
+	            var key = this._key;
+	            var keyWords = key.words;
+
+	            // Select 56 bits according to PC1
+	            var keyBits = [];
+	            for (var i = 0; i < 56; i++) {
+	                var keyBitPos = PC1[i] - 1;
+	                keyBits[i] = (keyWords[keyBitPos >>> 5] >>> (31 - keyBitPos % 32)) & 1;
+	            }
+
+	            // Assemble 16 subkeys
+	            var subKeys = this._subKeys = [];
+	            for (var nSubKey = 0; nSubKey < 16; nSubKey++) {
+	                // Create subkey
+	                var subKey = subKeys[nSubKey] = [];
+
+	                // Shortcut
+	                var bitShift = BIT_SHIFTS[nSubKey];
+
+	                // Select 48 bits according to PC2
+	                for (var i = 0; i < 24; i++) {
+	                    // Select from the left 28 key bits
+	                    subKey[(i / 6) | 0] |= keyBits[((PC2[i] - 1) + bitShift) % 28] << (31 - i % 6);
+
+	                    // Select from the right 28 key bits
+	                    subKey[4 + ((i / 6) | 0)] |= keyBits[28 + (((PC2[i + 24] - 1) + bitShift) % 28)] << (31 - i % 6);
+	                }
+
+	                // Since each subkey is applied to an expanded 32-bit input,
+	                // the subkey can be broken into 8 values scaled to 32-bits,
+	                // which allows the key to be used without expansion
+	                subKey[0] = (subKey[0] << 1) | (subKey[0] >>> 31);
+	                for (var i = 1; i < 7; i++) {
+	                    subKey[i] = subKey[i] >>> ((i - 1) * 4 + 3);
+	                }
+	                subKey[7] = (subKey[7] << 5) | (subKey[7] >>> 27);
+	            }
+
+	            // Compute inverse subkeys
+	            var invSubKeys = this._invSubKeys = [];
+	            for (var i = 0; i < 16; i++) {
+	                invSubKeys[i] = subKeys[15 - i];
+	            }
+	        },
+
+	        encryptBlock: function (M, offset) {
+	            this._doCryptBlock(M, offset, this._subKeys);
+	        },
+
+	        decryptBlock: function (M, offset) {
+	            this._doCryptBlock(M, offset, this._invSubKeys);
+	        },
+
+	        _doCryptBlock: function (M, offset, subKeys) {
+	            // Get input
+	            this._lBlock = M[offset];
+	            this._rBlock = M[offset + 1];
+
+	            // Initial permutation
+	            exchangeLR.call(this, 4,  0x0f0f0f0f);
+	            exchangeLR.call(this, 16, 0x0000ffff);
+	            exchangeRL.call(this, 2,  0x33333333);
+	            exchangeRL.call(this, 8,  0x00ff00ff);
+	            exchangeLR.call(this, 1,  0x55555555);
+
+	            // Rounds
+	            for (var round = 0; round < 16; round++) {
+	                // Shortcuts
+	                var subKey = subKeys[round];
+	                var lBlock = this._lBlock;
+	                var rBlock = this._rBlock;
+
+	                // Feistel function
+	                var f = 0;
+	                for (var i = 0; i < 8; i++) {
+	                    f |= SBOX_P[i][((rBlock ^ subKey[i]) & SBOX_MASK[i]) >>> 0];
+	                }
+	                this._lBlock = rBlock;
+	                this._rBlock = lBlock ^ f;
+	            }
+
+	            // Undo swap from last round
+	            var t = this._lBlock;
+	            this._lBlock = this._rBlock;
+	            this._rBlock = t;
+
+	            // Final permutation
+	            exchangeLR.call(this, 1,  0x55555555);
+	            exchangeRL.call(this, 8,  0x00ff00ff);
+	            exchangeRL.call(this, 2,  0x33333333);
+	            exchangeLR.call(this, 16, 0x0000ffff);
+	            exchangeLR.call(this, 4,  0x0f0f0f0f);
+
+	            // Set output
+	            M[offset] = this._lBlock;
+	            M[offset + 1] = this._rBlock;
+	        },
+
+	        keySize: 64/32,
+
+	        ivSize: 64/32,
+
+	        blockSize: 64/32
+	    });
+
+	    // Swap bits across the left and right words
+	    function exchangeLR(offset, mask) {
+	        var t = ((this._lBlock >>> offset) ^ this._rBlock) & mask;
+	        this._rBlock ^= t;
+	        this._lBlock ^= t << offset;
+	    }
+
+	    function exchangeRL(offset, mask) {
+	        var t = ((this._rBlock >>> offset) ^ this._lBlock) & mask;
+	        this._lBlock ^= t;
+	        this._rBlock ^= t << offset;
+	    }
+
+	    /**
+	     * Shortcut functions to the cipher's object interface.
+	     *
+	     * @example
+	     *
+	     *     var ciphertext = CryptoJS.DES.encrypt(message, key, cfg);
+	     *     var plaintext  = CryptoJS.DES.decrypt(ciphertext, key, cfg);
+	     */
+	    C.DES = BlockCipher._createHelper(DES);
+
+	    /**
+	     * Triple-DES block cipher algorithm.
+	     */
+	    var TripleDES = C_algo.TripleDES = BlockCipher.extend({
+	        _doReset: function () {
+	            // Shortcuts
+	            var key = this._key;
+	            var keyWords = key.words;
+	            // Make sure the key length is valid (64, 128 or >= 192 bit)
+	            if (keyWords.length !== 2 && keyWords.length !== 4 && keyWords.length < 6) {
+	                throw new Error('Invalid key length - 3DES requires the key length to be 64, 128, 192 or >192.');
+	            }
+
+	            // Extend the key according to the keying options defined in 3DES standard
+	            var key1 = keyWords.slice(0, 2);
+	            var key2 = keyWords.length < 4 ? keyWords.slice(0, 2) : keyWords.slice(2, 4);
+	            var key3 = keyWords.length < 6 ? keyWords.slice(0, 2) : keyWords.slice(4, 6);
+
+	            // Create DES instances
+	            this._des1 = DES.createEncryptor(WordArray.create(key1));
+	            this._des2 = DES.createEncryptor(WordArray.create(key2));
+	            this._des3 = DES.createEncryptor(WordArray.create(key3));
+	        },
+
+	        encryptBlock: function (M, offset) {
+	            this._des1.encryptBlock(M, offset);
+	            this._des2.decryptBlock(M, offset);
+	            this._des3.encryptBlock(M, offset);
+	        },
+
+	        decryptBlock: function (M, offset) {
+	            this._des3.decryptBlock(M, offset);
+	            this._des2.encryptBlock(M, offset);
+	            this._des1.decryptBlock(M, offset);
+	        },
+
+	        keySize: 192/32,
+
+	        ivSize: 64/32,
+
+	        blockSize: 64/32
+	    });
+
+	    /**
+	     * Shortcut functions to the cipher's object interface.
+	     *
+	     * @example
+	     *
+	     *     var ciphertext = CryptoJS.TripleDES.encrypt(message, key, cfg);
+	     *     var plaintext  = CryptoJS.TripleDES.decrypt(ciphertext, key, cfg);
+	     */
+	    C.TripleDES = BlockCipher._createHelper(TripleDES);
+	}());
+
+
+	return CryptoJS.TripleDES;
+
+}));

+ 304 - 0
crypto-js/x64-core.js

@@ -0,0 +1,304 @@
+;(function (root, factory) {
+	if (typeof exports === "object") {
+		// CommonJS
+		module.exports = exports = factory(require("./core"));
+	}
+	else if (typeof define === "function" && define.amd) {
+		// AMD
+		define(["./core"], factory);
+	}
+	else {
+		// Global (browser)
+		factory(root.CryptoJS);
+	}
+}(this, function (CryptoJS) {
+
+	(function (undefined) {
+	    // Shortcuts
+	    var C = CryptoJS;
+	    var C_lib = C.lib;
+	    var Base = C_lib.Base;
+	    var X32WordArray = C_lib.WordArray;
+
+	    /**
+	     * x64 namespace.
+	     */
+	    var C_x64 = C.x64 = {};
+
+	    /**
+	     * A 64-bit word.
+	     */
+	    var X64Word = C_x64.Word = Base.extend({
+	        /**
+	         * Initializes a newly created 64-bit word.
+	         *
+	         * @param {number} high The high 32 bits.
+	         * @param {number} low The low 32 bits.
+	         *
+	         * @example
+	         *
+	         *     var x64Word = CryptoJS.x64.Word.create(0x00010203, 0x04050607);
+	         */
+	        init: function (high, low) {
+	            this.high = high;
+	            this.low = low;
+	        }
+
+	        /**
+	         * Bitwise NOTs this word.
+	         *
+	         * @return {X64Word} A new x64-Word object after negating.
+	         *
+	         * @example
+	         *
+	         *     var negated = x64Word.not();
+	         */
+	        // not: function () {
+	            // var high = ~this.high;
+	            // var low = ~this.low;
+
+	            // return X64Word.create(high, low);
+	        // },
+
+	        /**
+	         * Bitwise ANDs this word with the passed word.
+	         *
+	         * @param {X64Word} word The x64-Word to AND with this word.
+	         *
+	         * @return {X64Word} A new x64-Word object after ANDing.
+	         *
+	         * @example
+	         *
+	         *     var anded = x64Word.and(anotherX64Word);
+	         */
+	        // and: function (word) {
+	            // var high = this.high & word.high;
+	            // var low = this.low & word.low;
+
+	            // return X64Word.create(high, low);
+	        // },
+
+	        /**
+	         * Bitwise ORs this word with the passed word.
+	         *
+	         * @param {X64Word} word The x64-Word to OR with this word.
+	         *
+	         * @return {X64Word} A new x64-Word object after ORing.
+	         *
+	         * @example
+	         *
+	         *     var ored = x64Word.or(anotherX64Word);
+	         */
+	        // or: function (word) {
+	            // var high = this.high | word.high;
+	            // var low = this.low | word.low;
+
+	            // return X64Word.create(high, low);
+	        // },
+
+	        /**
+	         * Bitwise XORs this word with the passed word.
+	         *
+	         * @param {X64Word} word The x64-Word to XOR with this word.
+	         *
+	         * @return {X64Word} A new x64-Word object after XORing.
+	         *
+	         * @example
+	         *
+	         *     var xored = x64Word.xor(anotherX64Word);
+	         */
+	        // xor: function (word) {
+	            // var high = this.high ^ word.high;
+	            // var low = this.low ^ word.low;
+
+	            // return X64Word.create(high, low);
+	        // },
+
+	        /**
+	         * Shifts this word n bits to the left.
+	         *
+	         * @param {number} n The number of bits to shift.
+	         *
+	         * @return {X64Word} A new x64-Word object after shifting.
+	         *
+	         * @example
+	         *
+	         *     var shifted = x64Word.shiftL(25);
+	         */
+	        // shiftL: function (n) {
+	            // if (n < 32) {
+	                // var high = (this.high << n) | (this.low >>> (32 - n));
+	                // var low = this.low << n;
+	            // } else {
+	                // var high = this.low << (n - 32);
+	                // var low = 0;
+	            // }
+
+	            // return X64Word.create(high, low);
+	        // },
+
+	        /**
+	         * Shifts this word n bits to the right.
+	         *
+	         * @param {number} n The number of bits to shift.
+	         *
+	         * @return {X64Word} A new x64-Word object after shifting.
+	         *
+	         * @example
+	         *
+	         *     var shifted = x64Word.shiftR(7);
+	         */
+	        // shiftR: function (n) {
+	            // if (n < 32) {
+	                // var low = (this.low >>> n) | (this.high << (32 - n));
+	                // var high = this.high >>> n;
+	            // } else {
+	                // var low = this.high >>> (n - 32);
+	                // var high = 0;
+	            // }
+
+	            // return X64Word.create(high, low);
+	        // },
+
+	        /**
+	         * Rotates this word n bits to the left.
+	         *
+	         * @param {number} n The number of bits to rotate.
+	         *
+	         * @return {X64Word} A new x64-Word object after rotating.
+	         *
+	         * @example
+	         *
+	         *     var rotated = x64Word.rotL(25);
+	         */
+	        // rotL: function (n) {
+	            // return this.shiftL(n).or(this.shiftR(64 - n));
+	        // },
+
+	        /**
+	         * Rotates this word n bits to the right.
+	         *
+	         * @param {number} n The number of bits to rotate.
+	         *
+	         * @return {X64Word} A new x64-Word object after rotating.
+	         *
+	         * @example
+	         *
+	         *     var rotated = x64Word.rotR(7);
+	         */
+	        // rotR: function (n) {
+	            // return this.shiftR(n).or(this.shiftL(64 - n));
+	        // },
+
+	        /**
+	         * Adds this word with the passed word.
+	         *
+	         * @param {X64Word} word The x64-Word to add with this word.
+	         *
+	         * @return {X64Word} A new x64-Word object after adding.
+	         *
+	         * @example
+	         *
+	         *     var added = x64Word.add(anotherX64Word);
+	         */
+	        // add: function (word) {
+	            // var low = (this.low + word.low) | 0;
+	            // var carry = (low >>> 0) < (this.low >>> 0) ? 1 : 0;
+	            // var high = (this.high + word.high + carry) | 0;
+
+	            // return X64Word.create(high, low);
+	        // }
+	    });
+
+	    /**
+	     * An array of 64-bit words.
+	     *
+	     * @property {Array} words The array of CryptoJS.x64.Word objects.
+	     * @property {number} sigBytes The number of significant bytes in this word array.
+	     */
+	    var X64WordArray = C_x64.WordArray = Base.extend({
+	        /**
+	         * Initializes a newly created word array.
+	         *
+	         * @param {Array} words (Optional) An array of CryptoJS.x64.Word objects.
+	         * @param {number} sigBytes (Optional) The number of significant bytes in the words.
+	         *
+	         * @example
+	         *
+	         *     var wordArray = CryptoJS.x64.WordArray.create();
+	         *
+	         *     var wordArray = CryptoJS.x64.WordArray.create([
+	         *         CryptoJS.x64.Word.create(0x00010203, 0x04050607),
+	         *         CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f)
+	         *     ]);
+	         *
+	         *     var wordArray = CryptoJS.x64.WordArray.create([
+	         *         CryptoJS.x64.Word.create(0x00010203, 0x04050607),
+	         *         CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f)
+	         *     ], 10);
+	         */
+	        init: function (words, sigBytes) {
+	            words = this.words = words || [];
+
+	            if (sigBytes != undefined) {
+	                this.sigBytes = sigBytes;
+	            } else {
+	                this.sigBytes = words.length * 8;
+	            }
+	        },
+
+	        /**
+	         * Converts this 64-bit word array to a 32-bit word array.
+	         *
+	         * @return {CryptoJS.lib.WordArray} This word array's data as a 32-bit word array.
+	         *
+	         * @example
+	         *
+	         *     var x32WordArray = x64WordArray.toX32();
+	         */
+	        toX32: function () {
+	            // Shortcuts
+	            var x64Words = this.words;
+	            var x64WordsLength = x64Words.length;
+
+	            // Convert
+	            var x32Words = [];
+	            for (var i = 0; i < x64WordsLength; i++) {
+	                var x64Word = x64Words[i];
+	                x32Words.push(x64Word.high);
+	                x32Words.push(x64Word.low);
+	            }
+
+	            return X32WordArray.create(x32Words, this.sigBytes);
+	        },
+
+	        /**
+	         * Creates a copy of this word array.
+	         *
+	         * @return {X64WordArray} The clone.
+	         *
+	         * @example
+	         *
+	         *     var clone = x64WordArray.clone();
+	         */
+	        clone: function () {
+	            var clone = Base.clone.call(this);
+
+	            // Clone "words" array
+	            var words = clone.words = this.words.slice(0);
+
+	            // Clone each X64Word object
+	            var wordsLength = words.length;
+	            for (var i = 0; i < wordsLength; i++) {
+	                words[i] = words[i].clone();
+	            }
+
+	            return clone;
+	        }
+	    });
+	}());
+
+
+	return CryptoJS;
+
+}));

+ 67 - 0
main.js

@@ -0,0 +1,67 @@
+import Vue from 'vue';
+import App from './App';
+import uView from 'uview-ui';
+Vue.use(uView);
+import { myRequest } from './util/api.js';
+Vue.prototype.$myRequest = myRequest;
+
+Vue.config.productionTip = false;
+
+App.mpType = 'app';
+
+import config from './util/neutral.js';
+Vue.prototype.$isneutral = config.isneutral;
+Vue.prototype.$imageURL = config.imageURL;// 线上图片服务器路径常量
+
+import { QueryPermission } from './util/QueryPermission.js';
+
+Vue.prototype.$QueryPermission = QueryPermission;
+// 自定义卡片
+import customCard from './components/customCard/customCard.vue';
+Vue.component('customCard', customCard);
+Vue.filter('timeFormat', function (time) {
+  function fun(a) {
+    return String(a).length == 1 ? '0' + a : a;
+  }
+  let date = new Date(time * 1000);
+  let y = date.getFullYear();
+  let m = date.getMonth() + 1;
+  let d = date.getDate();
+  let h = date.getHours();
+  let min = date.getMinutes();
+  let sec = date.getSeconds();
+  return `${y}-${fun(m)}-${fun(d)} ${fun(h)}:${fun(min)}:${fun(sec)}`;
+});
+
+Vue.prototype.formatTime = function (thistime, fmt = 'yyyy-MM-dd hh:mm:ss') {
+  let $this = new Date(thistime);
+  let o = {
+    'M+': $this.getMonth() + 1,
+    'd+': $this.getDate(),
+    'h+': $this.getHours(),
+    'm+': $this.getMinutes(),
+    's+': $this.getSeconds(),
+    'q+': Math.floor(($this.getMonth() + 3) / 3),
+    S: $this.getMilliseconds(),
+  };
+  if (/(y+)/.test(fmt)) {
+    fmt = fmt.replace(
+      RegExp.$1,
+      ($this.getFullYear() + '').substr(4 - RegExp.$1.length)
+    );
+  }
+  for (var k in o) {
+    if (new RegExp('(' + k + ')').test(fmt)) {
+      fmt = fmt.replace(
+        RegExp.$1,
+        RegExp.$1.length === 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length)
+      );
+    }
+  }
+  return fmt;
+};
+
+const app = new Vue({
+  ...App,
+});
+app.$mount();

+ 233 - 0
manifest.json

@@ -0,0 +1,233 @@
+{
+    "name" : "智控",
+    "appid" : "__UNI__DBA6730",
+    "description" : "",
+    "versionName" : "1.14.10",
+    "versionCode" : 11410,
+    "transformPx" : false,
+    "sassImplementationName" : "node-sass",
+    /* 5+App特有相关 */
+    "app-plus" : {
+        "softinput" : {
+            "mode" : "adjustPan",
+            "softinputMode" : "adjustResize"
+        },
+        "usingComponents" : true,
+        "nvueCompiler" : "uni-app",
+        "compilerVersion" : 3,
+        "splashscreen" : {
+            "alwaysShowBeforeRender" : true,
+            "waiting" : true,
+            "autoclose" : true,
+            "delay" : 0
+        },
+        "compatible" : {
+            "ignoreVersion" : true //true表示忽略版本检查提示框,HBuilderX1.9.0及以上版本支持
+        },
+        /* 模块配置 */
+        "modules" : {
+            "Webview-x5" : {},
+            "Maps" : {},
+            "VideoPlayer" : {},
+            "LivePusher" : {},
+            "Geolocation" : {},
+            "Camera" : {}
+        },
+        /* 应用发布信息 */
+        "distribute" : {
+            /* android打包配置 */
+            "android" : {
+                "permissions" : [
+                    "<uses-feature android:name=\"android.hardware.camera\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
+                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_COMPONENT_ENABLED_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.DISABLE_KEYGUARD\"/>",
+                    "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
+                    "<uses-permission android:name=\"android.permission.INSTALL_LOCATION_PROVIDER\"/>",
+                    "<uses-permission android:name=\"android.permission.INSTALL_PACKAGES\"/>",
+                    "<uses-permission android:name=\"android.permission.INSTALL_SHORTCUT\"/>",
+                    "<uses-permission android:name=\"android.permission.INTERNET\"/>",
+                    "<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
+                    "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
+                    "<uses-permission android:name=\"android.permission.UPDATE_DEVICE_STATS\"/>",
+                    "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
+                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
+                ],
+                "abiFilters" : [ "armeabi-v7a", "arm64-v8a", "x86" ],
+                "targetSdkVersion" : 30
+            },
+            /* ios打包配置 */
+            "ios" : {
+                "dSYMs" : false
+            },
+            /* SDK配置 */
+            "sdkConfigs" : {
+                "geolocation" : {
+                    "amap" : {
+                        "__platform__" : [ "ios", "android" ],
+                        "appkey_ios" : "25716a10d462140d75820fd9f5b342a5",
+                        "appkey_android" : "25716a10d462140d75820fd9f5b342a5"
+                    }
+                },
+                "maps" : {
+                    "amap" : {
+                        "appkey_ios" : "25716a10d462140d75820fd9f5b342a5",
+                        "appkey_android" : "25716a10d462140d75820fd9f5b342a5"
+                    }
+                },
+                "ad" : {}
+            },
+            "icons" : {
+                "android" : {
+                    "hdpi" : "unpackage/res/icons/72x72.png",
+                    "xhdpi" : "unpackage/res/icons/96x96.png",
+                    "xxhdpi" : "unpackage/res/icons/144x144.png",
+                    "xxxhdpi" : "unpackage/res/icons/192x192.png"
+                },
+                "ios" : {
+                    "appstore" : "unpackage/res/icons/1024x1024.png",
+                    "ipad" : {
+                        "app" : "unpackage/res/icons/76x76.png",
+                        "app@2x" : "unpackage/res/icons/152x152.png",
+                        "notification" : "unpackage/res/icons/20x20.png",
+                        "notification@2x" : "unpackage/res/icons/40x40.png",
+                        "proapp@2x" : "unpackage/res/icons/167x167.png",
+                        "settings" : "unpackage/res/icons/29x29.png",
+                        "settings@2x" : "unpackage/res/icons/58x58.png",
+                        "spotlight" : "unpackage/res/icons/40x40.png",
+                        "spotlight@2x" : "unpackage/res/icons/80x80.png"
+                    },
+                    "iphone" : {
+                        "app@2x" : "unpackage/res/icons/120x120.png",
+                        "app@3x" : "unpackage/res/icons/180x180.png",
+                        "notification@2x" : "unpackage/res/icons/40x40.png",
+                        "notification@3x" : "unpackage/res/icons/60x60.png",
+                        "settings@2x" : "unpackage/res/icons/58x58.png",
+                        "settings@3x" : "unpackage/res/icons/87x87.png",
+                        "spotlight@2x" : "unpackage/res/icons/80x80.png",
+                        "spotlight@3x" : "unpackage/res/icons/120x120.png"
+                    }
+                }
+            }
+        },
+        "uniStatistics" : {
+            "enable" : true,
+            "version" : "2"
+        }
+    },
+    /* 快应用特有相关 */
+    "quickapp" : {},
+    /* 小程序特有相关 */
+    "mp-weixin" : {
+        "appid" : "wx1cabf67f460e3a14",
+        "setting" : {
+            "urlCheck" : false,
+            "minified" : true,
+            "postcss" : false,
+            "es6" : true
+        },
+        "usingComponents" : true,
+        "uniStatistics" : {
+            "enable" : true
+        }
+    },
+    "mp-alipay" : {
+        "usingComponents" : true,
+        "uniStatistics" : {
+            "enable" : true
+        }
+    },
+    "mp-baidu" : {
+        "usingComponents" : true,
+        "uniStatistics" : {
+            "enable" : true
+        }
+    },
+    "mp-toutiao" : {
+        "usingComponents" : true,
+        "uniStatistics" : {
+            "enable" : true
+        }
+    },
+    "uniStatistics" : {
+        "enable" : true,
+        "version" : "2"
+    },
+    "h5" : {
+        "devServer" : {
+            "port" : 8000,
+            "disableHostCheck" : true,
+            "proxy" : {
+                "/ksy" : {
+                    "target" : "http://114.115.147.140:8002",
+                    "changeOrigin" : true,
+                    "ws" : true,
+                    "pathRewrite" : {
+                        "^/ksy" : "ksy"
+                    }
+                }
+            }
+        },
+        "template" : "static/tempalate.html",
+        "sdkConfigs" : {
+            "maps" : {
+                "qqmap" : {
+                    "key" : "XGQBZ-MSGW6-KNDSO-MVOIJ-OM6LO-JXBKB"
+                }
+            }
+        },
+        "uniStatistics" : {
+            "enable" : true
+        }
+    },
+    "mp-jd" : {
+        "uniStatistics" : {
+            "enable" : true
+        }
+    },
+    "mp-kuaishou" : {
+        "uniStatistics" : {
+            "enable" : true
+        }
+    },
+    "mp-lark" : {
+        "uniStatistics" : {
+            "enable" : true
+        }
+    },
+    "mp-qq" : {
+        "uniStatistics" : {
+            "enable" : true
+        }
+    },
+    "quickapp-webview-huawei" : {
+        "uniStatistics" : {
+            "enable" : true
+        }
+    },
+    "quickapp-webview-union" : {
+        "uniStatistics" : {
+            "enable" : true
+        }
+    }
+}
+// "sdkConfigs" : {
+//     "maps" : {
+//         "qqmap" : {
+//             "key" : "B2EBZ-2UW6P-RDJDG-LCMLE-AIQUS-CGFMJ"
+//         }
+//     }
+// }
+

+ 12 - 0
manifest.json.rej

@@ -0,0 +1,12 @@
+diff a/manifest.json b/manifest.json	(rejected hunks)
+@@ -2,8 +2,8 @@
+     "name" : "云飞智控",
+     "appid" : "__UNI__DBA6730",
+     "description" : "",
+-    "versionName" : "1.5.7",
+-    "versionCode" : 157,
++    "versionName" : "1.5.8",
++    "versionCode" : 158,
+     "transformPx" : false,
+     /* 5+App特有相关 */
+     "app-plus" : {

+ 19 - 0
package-lock.json

@@ -0,0 +1,19 @@
+{
+  "requires": true,
+  "lockfileVersion": 1,
+  "dependencies": {
+    "tslib": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
+      "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ=="
+    },
+    "zrender": {
+      "version": "5.0.4",
+      "resolved": "https://registry.npmjs.org/zrender/-/zrender-5.0.4.tgz",
+      "integrity": "sha512-DJpy0yrHYY5CuH6vhb9IINWbjvBUe/56J8aH86Jb7O8rRPAYZ3M2E469Qf5B3EOIfM3o3aUrO5edRQfLJ+l1Qw==",
+      "requires": {
+        "tslib": "2.0.3"
+      }
+    }
+  }
+}

+ 18 - 0
package.json

@@ -0,0 +1,18 @@
+{
+  "dependencies": {
+	    "name": "gulp",
+	    "version": "1.0.0",
+	    "description": "",
+	    "main": "index.js",
+	    "dependencies": {
+	      "gulp": "^4.0.2",
+	      "gulp-uglify": "^3.0.2"
+	    },
+	    "devDependencies": {},
+	    "scripts": {
+	      "test": "echo \"Error: no test specified\" && exit 1"
+	    },
+	    "author": "",
+	    "license": "ISC"
+  }
+}

Разница между файлами не показана из-за своего большого размера
+ 1005 - 0
pages.json


+ 526 - 0
pages/afterSale/addafter.vue

@@ -0,0 +1,526 @@
+<template>
+	<view>
+		<view class="status_bar"></view>
+		<view class="" style="position: relative;top: 44px;">
+			<view style="position: fixed;z-index: 100;">
+				<uni-nav-bar @clickLeft="clickLeft" left-icon="back" left-text="返回" title="设备报修"></uni-nav-bar>
+			</view>
+			<view class="addafter_con">
+				<view class="addafter_con_top">
+					<p>基本信息</p>
+					<view class="" style="display: flex;margin-top: 20rpx;">
+						<span style="color: #ff0000;">*</span>
+						<input type="number" v-model="adddata.id" placeholder="请填写设备ID" placeholder-style="color: #62BF89;font-size:24rpx"
+						 @blur="addID" />
+					</view>
+					<view class="" style="display: flex;margin-top: 20rpx;">
+						<span style="color: #ff0000;">*</span>
+						<input type="select" v-model="adddata.type" placeholder="请选择设备类型" placeholder-style="color: #62BF89;font-size:24rpx"
+						 @click="show = true" disabled />
+					</view>
+					<view class="" style="display: flex;margin-top: 20rpx;">
+						<span style="color: #fff;">*</span>
+						<input type="text" v-model="adddata.name" placeholder="请填写联系人名称" placeholder-style="color: #62BF89;font-size:24rpx" />
+					</view>
+					<view class="" style="display: flex;margin-top: 20rpx;">
+						<span style="color: #ff0000;">*</span>
+						<input type="number" v-model="adddata.phone" placeholder="请填写联系人电话" placeholder-style="color: #62BF89;font-size:24rpx"
+						 @blur="iphone" />
+					</view>
+					<view class="" style="display: flex;margin-top: 20rpx;">
+						<span style="color: #fff;">*</span>
+						<input type="text" v-model="adddata.site" placeholder="请填写联系人地址" placeholder-style="color: #62BF89;font-size:24rpx" />
+					</view>
+					<u-action-sheet :list="actionSheetList" v-model="show" @click="actionSheetCallback"></u-action-sheet>
+				</view>
+				<view class="addafter_con_connect">
+					<image :src="$imageURL+'/bigdata_app/image/afterSale/5d9b8db91f11175aa5277fef40581ab.png'" mode=""></image>
+					<image :src="$imageURL+'/bigdata_app/image/afterSale/5d9b8db91f11175aa5277fef40581ab.png'" mode=""></image>
+				</view>
+				<view class="addafter_con_bot">
+					<p class="addafter_con_bot_title">保修详情</p>
+					<textarea v-model="adddata.text" placeholder="请描述设备问题" class="textarea" placeholder-style="color: #62BF89;font-size:26rpx" />
+					<p style="color: #808080;font-size: 24rpx;">{{adddata.text.length}}/140</p>
+					<view class="imgvideo">
+						<view class="imgvideo_img" v-for="(item,index) in 3">
+							<view @click="gainimg(index)">
+								<image :src="$imageURL+'/bigdata_app/image/afterSale/eee1e84bb85f6f6ff5c5866a3a42779.png'" mode="" v-if="!uploadingTF[index]"></image>
+							</view>
+							<view class="sim_info_loding" v-if="loding">
+								<image src="../../static/images/cb/6286299.gif" mode="" class="img"></image>
+							</view>
+							<view class="uploading" v-if="uploadingTF[index]">
+								<u-icon name="close" class="delete" @click="deletes(index)"></u-icon>
+								<image :src="imageList[index]" mode="" class="uploading" @click="examine(imageList[index])"></image>
+							</view>
+						</view>
+						<view class="imgvideo_video" v-for="(item,index) in 1">
+							<view @click="gainvideo(index)">
+								<image :src="$imageURL+'/bigdata_app/image/afterSale/80314eaa07c32e9c76537a8a8224130.png'" mode="" v-if="!uploadingTF[index+3]"></image>
+							</view>
+							<view class="uploading" v-if="uploadingTF[index+3]">
+								<video :src="BASE_URL+selfList" :controls="false" class="uploading" ></video>
+								<view class="yulan" @click="yulan(index)">
+									预览
+								</view>
+								<view class="deletes" @click="deletes(index+3)">
+									删除
+								</view>
+							</view>
+						</view>
+					</view>
+					<button @click="btn" :disabled="btnisTorF">提 交</button>
+				</view>
+		</view>
+		</view>
+		<kps-image-cutter @ok="onok" @cancel="oncancle" :url="imgs" :fixed="false" :blob="false" :maxWidth="500" :maxHeight="500"></kps-image-cutter>
+		<u-modal v-model="videoshow" :mask-close-able="true" :show-confirm-button="false" title="视频预览" class="model">
+			<view class="model_box">
+				<video :src="'http://8.136.98.49:8002'+selfList" controls style="width:90%;"></video>
+			</view>
+		</u-modal>
+	</view>
+</template>
+<script>
+	import kpsImageCutter from "@/components/ksp-image-cutter/ksp-image-cutter.vue";
+	export default {
+		components:{
+			kpsImageCutter
+		},
+		data() {
+			return {
+				BASE_URL: 'http://8.136.98.49:8002',
+				adddata:{//设备参数
+					id:'',
+					name:'',
+					phone:'',
+					text:'',
+					site:'',
+					type:'',
+					type_id:''
+				},
+				loding:false,
+				imageList:[],//图片链接
+				uploadingTF:[false,false,false,false,false,false],//图片的删除
+				selfList:'',//视频链接
+				actionSheetList: [//设备选项
+					{
+						text: '杀虫灯',
+						id:2
+					},
+					{
+						text: '测报灯',
+						id:3
+					},
+					{
+						text: '智能性诱',
+						id:4
+					},
+					{
+						text: '环境监测',
+						id:5
+					},
+					{
+						text: '监控设备',
+						id:6
+					},
+					{
+						text: '孢子仪',
+						id:7
+					},
+					{
+						text: '性诱2.0',
+						id:10
+					},
+					{
+						text: '水肥一体化',
+						id:13
+					},
+					{
+						text: '天牛监测设备',
+						id:32
+					},{
+						text: '色诱测报设备2.0',
+						id:33
+					},{
+						text: '色诱测报设备1.0',
+						id:34
+					},{
+						text: '虫情测报设备5.0',
+						id:35
+					},
+				],
+				show:false,//选择器的显示
+				btnisTorF:false,
+				deviceid:false,//设备号判断
+				imageFile:[],
+				phoneTF:true,//手机号判断
+				imgs:'',
+				imgindex:null,
+				videoindex:0,
+				videoshow:false
+			}
+		},
+		onLoad(option) {
+			if(option.device_id){
+				console.log(option)
+				this.adddata.id = option.device_id
+				var typedata = this.actionSheetList.filter((item)=>{
+					return item.id == Number(option.device_type)
+				})
+				console.log(typedata)
+				this.adddata.type = typedata[0].text
+				this.adddata.type_id = typedata[0].id
+			}
+		},
+		methods: {
+			clickLeft(){//返回
+				uni.navigateBack({
+					delta:1
+				})
+			},
+			gainimg(index){//添加图片
+				this.imgindex = index
+				uni.chooseImage({
+				    count: 1, //默认9
+				    sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
+				    sourceType: ['album','camera'], //从相册选择
+				    success: (res)=> {
+						this.imgs = res.tempFilePaths[0]
+						this.loding = true
+					}
+				});
+			},
+			gainvideo(index){//添加视频
+				uni.chooseVideo({
+				    count: 1,
+					sourceType:['album', 'camera'],
+				    success:(res)=> {
+						console.log(res)
+						uni.uploadFile({
+						    url: 'http://8.136.98.49:8002/api/api_gateway?method=after_sale.after_sale_manage.video_upload', //仅为示例,非真实的接口地址
+						    filePath: res.tempFilePath,
+						    name: 'upload',
+							fileType:"video",
+						    formData: {
+						        'user': 'test'
+						    },
+						    success: (uploadFileRes) => {
+								console.log(uploadFileRes)
+								if(uploadFileRes.statusCode == 200){
+									this.selfList=JSON.parse(uploadFileRes.data).data.data.src
+									this.$forceUpdate() //强制刷新视图
+									this.uploadingTF[index+3] = true
+								}else{
+									uni.showToast({
+									    title: '请将视频压缩后上传!',
+									    duration: 2000,
+										icon:"none"
+									});
+								}
+						    }
+						});
+				    }
+				});
+			},
+			deletes(index){//删除
+				this.uploadingTF[index]=false
+				if(index==3){
+					this.selfList = ""
+				}else{
+					this.imageList.splice(index,1)
+				}
+				this.$forceUpdate() //强制刷新视图
+			},
+			async getaddafter(data) {//提交数据
+				const res = await this.$myRequest({
+					url: '/api/api_gateway?method=after_sale.after_sale_manage.aftersale_apply',
+					data:{
+						    device_id:data.id,
+						    d_type:data.type,
+						    errordesc:data.text,
+						    errorimg:data.imageList,
+							errorvideo:data.selfList,
+						    addr:data.site,
+						    user:data.name,
+						    userphone:data.phone,
+						    is_pc:0
+					}
+				})
+				console.log(res)
+				if(res){
+					uni.showToast({
+					    title: '提交成功',
+					    duration: 2000,
+					});
+					setTimeout(()=>{
+						uni.navigateBack({
+							delta:1
+						})
+					},1000)
+				}else{
+					uni.showToast({
+					    title: '提交失败',
+					    duration: 2000,
+						icon:"none"
+					});
+				}
+			},
+			async getID(data) {
+				const res = await this.$myRequest({
+					url: '/api/api_gateway?method=after_sale.after_sale_manage.device_check',
+					data:{
+						device_id:data
+					}
+				})
+				if(res!=''){
+					this.deviceid=false
+				}else{
+					this.deviceid=true
+				}
+			},
+			btn(){//提交按钮
+				this.getID(this.adddata.id)
+				let obj ={}
+				obj.id=this.adddata.id
+				obj.type=this.adddata.type_id
+				obj.text=this.adddata.text
+				if(this.imageList.length==0){
+					obj.imageList=""
+				}else{
+					obj.imageList=JSON.stringify(this.imageList)
+				}
+				obj.site=this.adddata.site
+				obj.name=this.adddata.name
+				obj.phone=this.adddata.phone
+				obj.selfList=this.selfList
+				console.log(this.selfList)
+				// 设备号错误
+				if(this.deviceid){
+					uni.showToast({
+					    title: '设备号错误',
+					    duration: 2000,
+						icon:"none"
+					});
+				}else if(this.adddata.type_id ==''){
+					uni.showToast({
+					    title: '设备类型不能为空',
+					    duration: 2000,
+						icon:"none"
+					});
+				}else if(this.phoneTF){
+					uni.showToast({
+					    title: '请输入正确的手机号',
+					    duration: 2000,
+						icon:'none'
+					});
+				}else{
+					console.log(obj)
+					this.getaddafter(obj)
+				}
+			},
+			actionSheetCallback(index) {//选择器选择
+				this.adddata.type = this.actionSheetList[index].text;
+				this.adddata.type_id = this.actionSheetList[index].id
+			},
+			iphone(){//检测手机
+				if(!/^1[23456789]\d{9}$/.test(this.adddata.phone)){
+					uni.showToast({
+					    title: '手机号格式不正确',
+					    duration: 2000,
+						icon:'none'
+					});
+					this.phoneTF=true
+				}else{
+					this.phoneTF=false
+				}
+			},
+			addID(){
+				this.getID(this.adddata.id)
+			},
+			examine(url) {
+				var imgarr =[]
+				imgarr.push(url)
+				console.log(imgarr)
+				uni.previewImage({
+					urls: imgarr
+				});
+			},
+			onok(ev){
+				uni.uploadFile({
+				    url: 'http://8.136.98.49:8002/api/api_gateway?method=base.bases.base_photo', //仅为示例,非真实的接口地址
+					filePath: ev.path,
+				    name: 'img_file',
+				    formData: {
+				        'user': 'test'
+				    },
+				    success: (uploadFileRes) => {
+						this.imageList[this.imgindex]=JSON.parse(uploadFileRes.data).data.src
+						this.$forceUpdate() //强制刷新视图
+						this.uploadingTF[this.imgindex]=true
+						this.loding = false
+				    }
+				});
+				this.imgs = ""
+			},
+			oncancle(){
+				this.imgs = ""
+			},
+			yulan(index){
+				this.videoindex = index
+				this.videoshow = !this.videoshow
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	page{
+		background-color: #71CD9A;
+	}
+	.addafter_con{
+		width: 100%;
+		position: absolute;
+		top: 54px;
+		.addafter_con_top{
+			width: 90%;
+			margin: 0 auto;
+			background-color: #FFFFFF;
+			padding: 16rpx 30rpx 36rpx;
+			border-radius: 20rpx;
+			box-sizing: border-box;
+			p{
+				text-align: center;
+				font-size: 30rpx;
+				color: #62BF89;
+			}
+			input{
+				width: 95%;
+				background-color: #F1FAF5;
+				color: #62BF89;
+				font-size:26rpx;
+				padding: 8rpx 26rpx;
+				border-radius: 20rpx;
+			}
+		}
+		.addafter_con_connect{
+			width: 90%;
+			margin: -20rpx auto;
+			display: flex;
+			justify-content: space-between;
+			padding: 0 16rpx;
+			box-sizing: border-box;
+			image{
+				width: 20rpx;
+				height: 60rpx;
+			}
+		}
+		.addafter_con_bot{
+			width: 90%;
+			margin: 0 auto;
+			background-color: #FFFFFF;
+			padding: 30rpx;
+			border-radius: 20rpx;
+			box-sizing: border-box;
+			.addafter_con_bot_title{
+				text-align: center;
+				font-size: 30rpx;
+				color: #62BF89;
+			}
+			.textarea{
+				width: 94%;
+				height: 240rpx;
+				padding: 20rpx;
+				background-color: #F1FAF5;
+				margin-top: 20rpx;
+				font-size: 26rpx;
+				border-radius: 20rpx;
+				color: #62BF89;  
+			}
+		}
+		.imgvideo{
+			width: 100%;
+			margin-top: 20rpx;
+			background-color: #FFFFFF;
+			display: flex;
+			flex-wrap: wrap;
+			.imgvideo_img,.imgvideo_video{
+				width: 30%;
+				height: 160rpx;
+				border: 2rpx dashed #A3DABD;
+				text-align: center;
+				line-height: 160rpx;
+				margin:0 8rpx 20rpx 8rpx;
+				position: relative;
+				image{
+					width: 40rpx;
+					height: 32rpx;
+				}
+				.sim_info_loding{
+					width: 100%;
+					height: 160rpx;
+					position: absolute;
+					top: 0;
+					left: 0;
+					image{
+						width: 100%;
+						height: 100%;
+					}
+				}
+				.uploading{
+					width: 100%;
+					height: 160rpx;
+					position: absolute;
+					top: 0;
+					left: 0;
+				}
+				.delete{
+					position: absolute;
+					top: -12rpx;
+					right: -12rpx;
+					font-size: 36rpx;
+					background-color: #FE0000;
+					border-radius: 50%;
+					color: #ffffff;
+					z-index: 50;
+				}
+				.deletes{
+					width: 80%;
+					height: 50rpx;
+					margin-left: 110%;
+					font-size: 24rpx;
+					background-color: #FE0000;
+					color: #FFFDEF;
+					line-height: 50rpx;
+				}
+				.yulan{
+					width: 80%;
+					height: 50rpx;
+					margin: 0 0 20rpx 110%;
+					font-size: 24rpx;
+					background-color: #62BF89;
+					color: #FFFDEF;
+					line-height: 50rpx;
+				}
+			}
+		}
+		button{
+			width: 100%;
+			height: 60rpx;
+			font-size: 30rpx;
+			line-height: 60rpx;
+			color: #FFFFFF;
+			background-color: #50CE87;
+			margin-top: 60rpx;
+		}
+	}
+	.model {
+		width: 90%;
+		.model_box {
+			width: 90%;
+			margin: 40rpx auto 48rpx;
+			display: flex;
+			justify-content: center;
+		}
+	}
+</style>

+ 431 - 0
pages/afterSale/index.vue

@@ -0,0 +1,431 @@
+<template>
+	<view>
+		<view class="status_bar"></view>
+		<view style="position: fixed;z-index: 100;top: 44px;">
+			<uni-nav-bar @clickLeft="clickLeft" left-icon="back" left-text="返回" title="售后系统" rightIcon="search"
+				@clickRight="clickRight"></uni-nav-bar>
+			<view class="inputs" :style="{'width':width+'rpx'}">
+				<input type="text" value="" placeholder="请输入设备ID或设备名称" v-model="imports" @input="searchinp"
+					class="inputbox" :clearable="false" />
+				<u-icon name="search" size="40" class="icon" @click="search"></u-icon>
+			</view>
+		</view>
+		<image :src="$imageURL+'/bigdata_app/image/afterSale/dcd7147f4b15d00c5c90006738b8453.png'"
+			class="expertimages"></image>
+		<view class="loading" v-if="loadingtf">
+			<image src="../../static/images/ajax-loader.gif" mode="" class="img"></image>
+		</view>
+		<view class="aftersaleTF" v-if="aftersaleTF">
+			暂无数据
+		</view>
+		<view class="aftersale" v-else>
+			<view class="aftersale_item" v-for="(item,index) in faultdata" :key="index">
+				<view class="aftersale_item_title">
+					<u-icon name="calendar" color="#71D8AF" size="34"></u-icon>
+					<span>设备 ID:{{item.device_id}}</span>
+				</view>
+				<view class="aftersale_item_con">
+					<p>设备类型:{{devtype[item.device_type]}}</p>
+					<p>联系人:{{item.user?item.user:"无"}}</p>
+					<p>联系电话:{{item.userphone?item.userphone:"无"}}</p>
+					<p>位置:{{item.addr?item.addr:"无"}}</p>
+					<!-- <p>故障上报时间:{{item.uptime|timeFormat()}}</p> -->
+					<p>故障信息:{{item.errordesc}}</p>
+				</view>
+				<view class="aftersale_item_operate">
+					<view class="aftersale_item_operate_tiem">
+						{{item.uptime|timeFormat()}}
+					</view>
+					<view class="aftersale_item_operate_btn">
+						<button :class="item.errorimg.length!=0?'imgs':'none'" :disabled="item.errorimg.length==0"
+							@click="faultImg(item.errorimg)">图片</button>
+						<button :class="item.errorvideo?'video':'none'" :disabled="!item.errorvideo"
+							@click="faultVideo(item.errorvideo)">视频</button>
+					</view>
+					<!-- <button :class="item.errordesc?'fault':'none'" :disabled="!item.errordesc"
+						@click="fault(item.errordesc)">故障原因</button> -->
+
+				</view>
+
+			</view>
+		</view>
+		<view class="addindent" @click="addf">
+			新 增 售 后 单
+		</view>
+		<u-modal v-model="show" :mask-close-able="maskcloseable" :show-confirm-button="showconfirmbutton" :title="title"
+			class="model">
+			<view class="model_box">
+				<p v-if="faultinfo_tf">{{faultinfo}}</p>
+				<u-swiper :list="faultimg" v-if="faultimg_tf" class="uswiper" height="400" style="width: 100%;"
+					@click="examine(faultimg)"></u-swiper>
+				<video :src="BASE_URL+faultvideo" controls v-if="faultvideo_tf" style="width:90%;"></video>
+			</view>
+		</u-modal>
+		<view class="top" v-if="isTop" @click="top">
+			<image :src="$imageURL+'/bigdata_app/image/6209a98f0cb3b5086f2ca36152c9269.png'" mode="">
+			</image>
+		</view>
+	</view>
+</template>
+<script>
+	import {
+		Debounce,
+		Throttle
+	} from "../../util/anitthro.js"
+	export default {
+		data() {
+			return {
+				BASE_URL: 'http://8.136.98.49:8002',
+				faultdata: [],
+				title: "", //弹框标题
+				show: false, //弹框先显示
+				maskcloseable: true,
+				showconfirmbutton: false,
+				faultinfo: '', //故障信息
+				faultinfo_tf: false, //故障信息显示
+				faultvideo: '', //故障视频
+				faultvideo_tf: false, //故障视频显示
+				faultimg: [], //故障图片
+				faultimg_tf: false, //故障图片显示
+				page: 1,
+				aftersaleTF: true,
+				isTop: false,
+				imports: "", //搜索设备id
+				width: 0, //顶部搜索框的宽度
+				loadingtf: false, //loading
+				devtype: {
+
+				}
+			}
+		},
+		methods: {
+			async getAftersale() {
+				this.loadingtf = true
+				const res = await this.$myRequest({
+					url: '/api/api_gateway?method=after_sale.after_sale_manage.aftersale_info',
+					data: {
+						page: this.page,
+						f_id: Number(this.imports)
+					}
+				})
+				this.loadingtf = false
+				if (res.counts == 0) {
+					this.aftersaleTF = true
+				} else {
+					this.aftersaleTF = false
+				}
+				this.faultdata = this.faultdata.concat(res.data)
+				for (var i = 0; i < this.faultdata.length; i++) {
+					if (this.faultdata[i].errorimg) {
+						if (!Array.isArray(this.faultdata[i].errorimg)) {
+							this.faultdata[i].errorimg = JSON.parse(this.faultdata[i].errorimg)
+						}
+					} else {
+						this.faultdata[i].errorimg = []
+					}
+				}
+				console.log(res)
+			},
+			fault(info) { //查看故障信息
+				this.title = "故障信息"
+				this.show = true
+				this.faultinfo = info
+				this.faultimg_tf = false
+				this.faultinfo_tf = true
+				this.faultvideo_tf = false
+			},
+			faultImg(info) { //查看故障图片
+				this.faultimg = []
+				for (var i = 0; i < info.length; i++) {
+					let obj = {}
+					obj.image = info[i]
+					this.faultimg.push(obj)
+				}
+				console.log(this.faultimg)
+				this.title = "故障图片"
+				this.show = true
+				this.faultimg_tf = true
+				this.faultinfo_tf = false
+				this.faultvideo_tf = false
+			},
+			faultVideo(info) { //查看故障视频
+				this.title = "故障视频"
+				if (info.indexOf("[") != -1) {
+					this.faultvideo = JSON.parse(info)[0]
+				} else {
+					this.faultvideo = info
+				}
+				console.log(this.faultvideo)
+				this.show = true
+				this.faultimg_tf = false
+				this.faultinfo_tf = false
+				this.faultvideo_tf = true
+			},
+			clickRight() { //搜索
+				this.width = 600
+			},
+			addf() { //添加
+				uni.navigateTo({
+					url: "./addafter"
+				})
+			},
+			clickLeft() {
+				uni.switchTab({
+					url: "../index/index"
+				})
+			},
+			examine(url) {
+				var imgarr = []
+				for (var i = 0; i < url.length; i++) {
+					imgarr.push(url[i].image)
+				}
+				console.log(imgarr)
+				uni.previewImage({
+					urls: imgarr
+				});
+			},
+			top() {
+				uni.pageScrollTo({
+					scrollTop: 0,
+					duration: 500
+				})
+			},
+			search() { //搜索按钮搜索
+				this.faultdata = []
+				this.getAftersale()
+			},
+			searchinp() { //自动搜索
+				Debounce(() => {
+					this.faultdata = []
+					this.getAftersale()
+				}, 1000)()
+			},
+			async getdevtype() {
+				const res = await this.$myRequest({
+					url: '/api/api_gateway?method=home.homes.user_device_type',
+					data: {}
+				})
+				console.log(res)
+				for (var i = 0; i < res.length; i++) {
+					this.devtype[res[i].id] = res[i].type_name
+				}
+				console.log(this.devtype)
+			}
+		},
+		onLoad() {
+			this.getdevtype()
+		},
+		onShow() {
+			this.page = 1
+			this.faultdata = []
+			this.getAftersale()
+		},
+		onReachBottom() {
+			this.page++
+			this.getAftersale()
+		},
+		onPageScroll(e) { //nvue暂不支持滚动监听,可用bindingx代替
+			if (e.scrollTop > 200) { //距离大于200时显示
+				this.isTop = true
+			} else { //距离小于200时隐藏
+				this.isTop = false
+			}
+		},
+	}
+</script>
+
+<style lang="scss">
+	.expertimages {
+		width: 100%;
+		height: 154rpx;
+		position: fixed;
+		top: 88px;
+		z-index: 100;
+	}
+
+	.aftersale_search {
+		position: fixed;
+		z-index: 100;
+		top: 104rpx;
+		right: 20rpx;
+
+		.sp_icon {
+			font-size: 36rpx;
+			margin-left: 16rpx;
+		}
+	}
+
+	.aftersaleTF {
+		width: 100%;
+		position: relative;
+		top: 340rpx;
+		text-align: center;
+		padding-top: 40rpx;
+		font-size: 20px;
+	}
+
+	.loading {
+		position: fixed;
+		top: 440px;
+		width: 95%;
+		left: 2.5%;
+		text-align: center;
+
+		.img {
+			width: 300rpx;
+			height: 40rpx;
+		}
+	}
+
+	.inputs {
+		height: 54rpx;
+		background-color: #E4E4E4;
+		border-radius: 27rpx;
+		position: absolute;
+		right: 20rpx;
+		top: 24rpx;
+		transition: width 0.5s;
+		overflow: hidden;
+		padding-top: 8rpx;
+		box-sizing: border-box;
+
+		.inputbox {
+			width: 85%;
+			text-indent: 1rem;
+			font-size: 26rpx;
+		}
+
+		.icon {
+			position: absolute;
+			top: 8rpx;
+			right: 26rpx;
+		}
+	}
+
+	.aftersale {
+		width: 100%;
+		position: relative;
+		top: 340rpx;
+		margin-bottom: 80rpx;
+
+		.aftersale_item {
+			width: 90%;
+			margin: 0 auto 30rpx;
+			box-shadow: 0 0 10rpx #bcb9ca;
+			padding: 30rpx 20rpx 20rpx;
+			position: relative;
+			box-sizing: border-box;
+
+			.aftersale_item_title {
+				width: 100%;
+
+				span {
+					margin-left: 16rpx;
+					font-weight: 700;
+				}
+			}
+
+			.aftersale_item_con {
+				width: 92%;
+				margin-left: 8%;
+				margin-top: 20rpx;
+
+				p {
+					// height: 48rpx;
+					line-height: 48rpx;
+					font-size: 24rpx;
+					color: #7d7d7d;
+				}
+			}
+
+			.aftersale_item_operate {
+				width: 100%;
+				display: flex;
+				justify-content: space-between;
+				margin-top: 20rpx;
+				.aftersale_item_operate_btn{
+					display: flex;
+				}
+				.aftersale_item_operate_tiem{
+					// line-height: 60rpx;
+					height: 60rpx;
+					padding-top: 30rpx;
+					color: #BEBEBE;
+					font-size: 12px;
+					box-sizing: border-box;
+				}
+				button {
+					width: 130rpx;
+					padding: 0;
+					font-size: 24rpx;
+					color: #FFFFFF;
+					margin-left: 20rpx;
+				}
+
+				.fault {
+					background-color: #F78E01;
+				}
+
+				.imgs {
+					background-color: #71CD9A;
+				}
+
+				.video {
+					background-color: #53C6E6;
+				}
+
+				.none {
+					background-color: #F3F3F3;
+					color: #B4B4B4;
+				}
+			}
+
+			.aftersale_item_icon {
+				position: absolute;
+				top: 0;
+				right: 36rpx;
+
+				image {
+					width: 68rpx;
+					height: 64rpx;
+				}
+			}
+		}
+	}
+
+	.model {
+		width: 90%;
+
+		.model_box {
+			width: 90%;
+			margin: 40rpx auto 48rpx;
+			display: flex;
+			justify-content: center;
+		}
+	}
+
+	.top {
+		position: fixed;
+		right: 30px;
+		bottom: 100px;
+		z-index: 100;
+
+		image {
+			width: 100rpx;
+			height: 100rpx;
+		}
+	}
+
+	.addindent {
+		width: 100%;
+		position: fixed;
+		bottom: 0;
+		left: 0;
+		height: 80rpx;
+		text-align: center;
+		line-height: 80rpx;
+		background-color: #71cd9a;
+		color: #ffffff;
+		font-size: 16px;
+	}
+</style>

+ 290 - 0
pages/afterSale/search.vue

@@ -0,0 +1,290 @@
+<template>
+	<view>
+		<view class="status_bar"></view>
+		<view style="position: fixed;z-index: 100;top: 44px;">
+			<uni-nav-bar @clickLeft="clickLeft" left-icon="back" left-text="返回"></uni-nav-bar>
+			<view class="search_top_input">
+				<input type="text" value="" placeholder="请输入设备ID"  v-model="imports" @input="searchinp"/>
+				<u-icon name="search" size="40" class="icon" @click="search"></u-icon>
+			</view>
+		</view>
+		<view class="aftersaleinfo" v-if="aftersaleinfotf">
+			暂无此设备信息
+		</view>
+		<view class="aftersale" v-else>
+			<view class="aftersale_item" v-for="(item,index) in faultdata" :key="index">
+				<view class="aftersale_item_title">
+					<u-icon name="calendar" color="#71D8AF" size="34"></u-icon>
+					<span>设备 ID:{{item.device_id}}</span>
+				</view>
+				<view class="aftersale_item_con">
+					<p>联系人:{{item.user}}</p>
+					<p>联系电话:{{item.userphone}}</p>
+					<p>位置:{{item.addr}}</p>
+					<p>故障上报时间:{{item.uptime|timeFormat()}}</p>
+				</view>
+				<view class="aftersale_item_operate">
+					<button class="fault" @click="fault(item.errordesc)">故障原因</button>
+					<button :class="item.errorimg.length!=0?'imgs':'none'" :disabled="item.errorimg.length==0" @click="faultImg(item.errorimg)">图片</button>
+					<button :class="item.errorvideo?'video':'none'" :disabled="!item.errorvideo" @click="faultVideo(item.errorvideo)">视频</button>
+				</view>
+				<view class="aftersale_item_icon">
+					<image :src="'http://static.yfpyx.com/bigdata_app'+aftersale_icon[Number(item.device_type)-2].src" mode=""></image>
+				</view>
+			</view>
+		</view>
+		<u-modal v-model="show" :mask-close-able="maskcloseable" :show-confirm-button="showconfirmbutton" :title="title" class="model">
+			<view class="model_box">
+				<p v-if="faultinfo_tf">{{faultinfo}}</p>
+				<u-swiper :list="faultimg" v-if="faultimg_tf" class="uswiper" height="400" style="width: 100%;" @click="examine(faultimg)"></u-swiper>
+				<video :src="BASE_URL+faultvideo" controls v-if="faultvideo_tf" style="width: 90%;"></video>
+			</view>
+		</u-modal>
+	</view>
+</template>
+<script>
+	import {
+		Debounce,
+		Throttle
+	} from "../../util/anitthro.js"
+	export default {
+		data() {
+			return {
+				imports:'',
+				BASE_URL: 'http://182.92.193.64:8002',
+				faultdata:[],
+				aftersale_icon: [{
+						src: '/image/afterSale/6.png'
+					},
+					{
+						src: '/image/afterSale/1.png'
+					},
+					{
+						src: '/image/afterSale/4.png'
+					},
+					{
+						src: '/image/afterSale/3.png'
+					},
+					{
+						src: '/image/afterSale/5.png'
+					},
+					{
+						src: '/image/afterSale/2.png'
+					}
+				],
+				title:"",//弹框标题
+				show: false,//弹框先显示
+				maskcloseable: true,
+				showconfirmbutton: false,
+				faultinfo: '',//故障信息
+				faultinfo_tf:false,//故障信息显示
+				faultvideo: '',//故障视频
+				faultvideo_tf:false,//故障视频显示
+				faultimg: [],//故障图片
+				faultimg_tf: false,//故障图片显示
+				aftersaleinfotf:'',
+				page:1
+			}
+		},
+		methods: {
+			async getAftersale(num) {
+				const res = await this.$myRequest({
+					url: '/api/api_gateway?method=after_sale.after_sale_manage.aftersale_info',
+					data:{
+						f_id:num,
+						page:this.page
+					}
+				})
+				this.faultdata =this.faultdata.concat(res.data)
+				console.log(this.faultdata)
+				if(this.faultdata.length==0){
+					this.aftersaleinfotf = true
+				}else{
+					this.aftersaleinfotf = false
+				}
+				for (var i = 0; i < this.faultdata.length; i++) {
+					this.faultdata[i].errorimg = JSON.parse(this.faultdata[i].errorimg)
+					if (this.faultdata[i].errorimg == null) {
+						this.faultdata[i].errorimg = []
+					}
+				}
+			},
+			search(){
+				this.getAftersale(Number(this.imports))
+			},
+			fault(info) { //查看故障信息
+				this.title="故障信息"
+				this.show = true
+				this.faultinfo = info
+				this.faultimg_tf = false
+				this.faultinfo_tf=true
+				this.faultvideo_tf=false
+			},
+			faultImg(info) { //查看故障图片
+				this.faultimg=[]
+				for (var i = 0; i < info.length; i++) {
+					let obj = {}
+					obj.image = info[i]
+					this.faultimg.push(obj)
+				}
+				console.log(this.faultimg)
+				this.title="故障图片"
+				this.show = true
+				this.faultimg_tf = true
+				this.faultinfo_tf=false
+				this.faultvideo_tf=false
+			},
+			faultVideo(info) { //查看故障视频
+			this.title="故障视频"
+				this.faultvideo=info
+				this.show = true
+				this.faultimg_tf = false
+				this.faultinfo_tf=false
+				this.faultvideo_tf=true
+			},
+			clickLeft(){
+				uni.navigateTo({
+					url:"./index"
+				})
+			},
+			searchinp() {
+				Debounce(() => {
+					this.eqlistdata = []
+					this.search()
+				}, 1000)()
+			},
+			examine(url) {
+				var imgarr =[]
+				for(var i=0;i<url.length;i++){
+					imgarr.push(url[i].image)
+				}
+				console.log(imgarr)
+				uni.previewImage({
+					urls: imgarr
+				});
+			},
+		},
+		onReachBottom() {
+			this.page++
+			this.getAftersale(Number(this.imports))
+		}
+	}
+</script>
+<style lang="scss">
+	.search_top_input{
+		width: 80%;
+		height: 54rpx;
+		background-color: #E4E4E4;
+		border-radius: 27rpx;
+		position: absolute;
+		top: 18rpx;
+		right: 18rpx;
+		padding-top: 8rpx;
+		box-sizing: border-box;
+		input{
+			width: 85%;
+			text-indent: 1rem;
+			font-size: 26rpx;
+		}
+		.icon{
+			position: absolute;
+			top: 8rpx;
+			right: 26rpx;
+		}
+	}
+	.aftersaleinfo{
+		width: 100%;
+		position: relative;
+		top: 98px;
+		height: 100rpx;
+		text-align: center;
+		line-height: 100rpx;
+		font-size: 32rpx;
+	}
+	.aftersale {
+		width: 100%;
+		// margin-top: 20rpx;
+		position: relative;
+		top: 98px;
+	
+		.aftersale_item {
+			width: 90%;
+			margin: 0 auto 30rpx;
+			box-shadow: 0 0 10rpx #bcb9ca;
+			padding: 30rpx 20rpx 20rpx;
+			position: relative;
+			box-sizing: border-box;
+			.aftersale_item_title {
+				width: 100%;
+	
+				span {
+					margin-left: 16rpx;
+					font-weight: 700;
+				}
+			}
+	
+			.aftersale_item_con {
+				width: 92%;
+				margin-left: 8%;
+				margin-top: 20rpx;
+	
+				p {
+					height: 48rpx;
+					font-size: 24rpx;
+					color: #BEBEBE;
+				}
+			}
+	
+			.aftersale_item_operate {
+				width: 70%;
+				display: flex;
+				margin: 18rpx 0 0 30%;
+	
+				button {
+					width: 130rpx;
+					padding: 0;
+					font-size: 24rpx;
+					color: #FFFFFF;
+				}
+	
+				.fault {
+					background-color: #F78E01;
+				}
+	
+				.imgs {
+					background-color: #71CD9A;
+				}
+	
+				.video {
+					background-color: #53C6E6;
+				}
+	
+				.none {
+					background-color: #F3F3F3;
+					color: #B4B4B4;
+				}
+			}
+	
+			.aftersale_item_icon {
+				position: absolute;
+				top: 0;
+				right: 36rpx;
+	
+				image {
+					width: 68rpx;
+					height: 64rpx;
+				}
+			}
+		}
+	}
+	.model {
+		width: 90%;
+		.model_box {
+			width: 90%;
+			margin: 20rpx auto 48rpx;
+			display: flex;
+			justify-content: center;
+		}
+	}
+</style>
+

+ 520 - 0
pages/cb/bzy/equip-set/bzyhistoryile.vue

@@ -0,0 +1,520 @@
+<template>
+	<view>
+		<view class="status_bar"></view>
+		<view class="" style="position: relative;top: 44px;">
+			<view style="position: fixed;z-index: 100;">
+				<uni-nav-bar @clickLeft="clickLeft" left-icon="back" title="历史数据"></uni-nav-bar>
+			</view>
+			<view class="shuju_one">
+				<view class="shuju_one_title">
+					<view :class="titleidnex==index?'title_text_color':'tltle_text'" v-for="(item,index) in titletext"
+						:key="index" @click="changeindex(index)">
+						{{item}}
+					</view>
+				</view>
+				<view class="canvastishi" v-if="!canvastishiTF && !dataloadingtf">
+					暂无数据
+				</view>
+				<view class="canvastishi" v-if="dataloadingtf">
+					<p class="dataloading">加载中</p>
+				</view>
+				<canvas v-if="canvastishiTF" canvas-id="canvasColumnA" id="canvasColumnA" class="charts"
+					@touchstart="touchLineA($event)" @touchmove="moveLineA($event)" @touchend="touchEndLineA($event)"
+					disable-scroll=true
+					:style="{'width':cWidth*pixelRatio+'px','height':cHeight*pixelRatio+'px', 'transform': 'scale('+(1/pixelRatio)+')','margin-left':-cWidth*(pixelRatio-1)/2+'px','margin-top':-cHeight*(pixelRatio-1)/2+'px'}"></canvas>
+			</view>
+			<view class="refresh" @click="refresh">
+				刷 新
+			</view>
+			<view class="condition">
+				<scroll-view scroll-x="true" class="scroll-X" scroll-top="0">
+					<table class="table" v-if="$QueryPermission(265) ||$QueryPermission(304) ||$QueryPermission(313)">
+						<tr class="tr">
+							<th class="th" v-for="(item,index) in thdata" :key="index" v-if="(!isShowBwc && item.indexOf('保温仓') < 0) || isShowBwc">{{item}}</th>
+						</tr>
+						<tr class="tr" v-for="(items,indexs) in historylistdata" :key="indexs" v-if="!forbidden">
+							<td class="td">{{items.d_h_t.addtime|timeFormat()}}</td>
+							<td class="td">{{items.d_h_t.ds==0?"关":"开"}}</td>
+							<td class="td">{{items.d_h_t.at}}</td>
+							<td class="td">{{items.d_h_t.ah}}</td>
+							<td class="td" v-if="isShowBwc">{{items.d_h_t.set_temp}}</td>
+							<td class="td" v-if="isShowBwc">{{items.d_h_t.pre_temp}}</td>
+							<td class="td">{{items.d_h_t.batStatus==0?"正常":"欠压"}}</td>
+							<!-- <td class="td">{{items.d_h_t.rps==0?"正常":"雨控"}}</td> -->
+							<td class="td">{{Circulation.work_sta.value[items.d_h_t.work_sta]}}</td>
+							<td class="td">{{items.d_h_t.csq}}</td>
+							<td class="td">{{items.d_h_t.current}}</td>
+							<td class="td">{{items.d_h_t.vbat}}</td>
+							<td class="td">{{items.d_h_t.dver}}</td>
+						</tr>
+						<tr class="tr" v-if="forbidden">
+							
+							<td class="td" v-for="(item,index) in thdata" :key="index" v-if="(!isShowBwc && item.indexOf('保温仓') < 0) || isShowBwc">暂无数据</td>
+						</tr>
+					</table>
+					<table class="table" v-else>
+						<tr class="tr">
+							<th class="th" v-for="(item,index) in thdata2" :key="index" v-if="(!isShowBwc && item.indexOf('保温仓') < 0) || isShowBwc">{{item}}</th>
+						</tr>
+						<tr class="tr" v-for="(items,indexs) in historylistdata" :key="indexs" v-if="!forbidden">
+							<td class="td">{{items.d_h_t.addtime|timeFormat()}}</td>
+							<td class="td">{{items.d_h_t.ds==0?"关":"开"}}</td>
+							<td class="td">{{items.d_h_t.at}}</td>
+							<td class="td">{{items.d_h_t.ah}}</td>
+							<td class="td" v-if="isShowBwc">{{items.d_h_t.set_temp}}</td>
+							<td class="td" v-if="isShowBwc">{{items.d_h_t.pre_temp}}</td>
+							<td class="td">{{items.d_h_t.batStatus==0?"正常":"欠压"}}</td>
+							<!-- <td class="td">{{items.d_h_t.rps==0?"正常":"雨控"}}</td> -->
+							<td class="td">{{Circulation.work_sta.value[items.d_h_t.work_sta]}}</td>
+							<td class="td">{{items.d_h_t.dver}}</td>
+						</tr>
+						<tr class="tr" v-if="forbidden">
+							
+							<td class="td" v-for="(item,index) in thdata2" :key="index" v-if="(!isShowBwc && item.indexOf('保温仓') < 0) || isShowBwc">暂无数据</td>
+						</tr>
+					</table>
+				</scroll-view>
+				<view class="pagenumber">
+					<button @click="prev">上一页</button>
+					<view class="pagenumber_page">
+						第 {{page}} 页
+					</view>
+					<view class="pagenumber_page">
+						共 {{pagesum}} 页
+					</view>
+					<button @click="next" :disabled="forbidden">下一页</button>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import uCharts from '../../../../components/js_sdk/u-charts/u-charts/u-charts.js';
+	import Circulation from "../../../../static/js/equipState_dict.json"
+	var canvaColumnA = null;
+	export default {
+		data() {
+			return {
+				isShowBwc: false,
+				styles: {
+					// width: "650rpx",
+					height: "400rpx"
+				},
+				d_id: '',
+				start_time: "",
+				end_time: "",
+				historydatas: [],
+				titletext: ["24小时", "近一个月", "近半年", "近一年"],
+				titleidnex: 0,
+				device_id: '',
+				page: 1,
+				pagesum: 1,
+				historylistdata: [],
+				thdata: ["上报时间", "设备开关", "环境温度(°C)", "环境湿度(%)", "保温仓设定温度(°C)", "保温仓当前温度(°C)", "电池状态", "工作状态",
+					"信号强度", "电流(mA)", "电压(V)", "设备版本"
+				],
+				thdata2: ["上报时间", "设备开关", "环境温度(°C)", "环境湿度(%)", "保温仓设定温度(°C)", "保温仓当前温度(°C)", "电池状态", "工作状态",
+					"设备版本"
+				],
+				forbidden: false,
+				canvastishiTF: false, //暂无数据提示
+				dataloadingtf: true, //加载中提示
+				cWidth: '400',
+				cHeight: '400',
+				pixelRatio: 1,
+				Circulation:Circulation
+			}
+		},
+		methods: {
+			//forecast.worm_lamp.device_polyline_data 历史数据折线图
+			// device_type_id          必传(string)                  设备类型  3虫情测报灯 7孢子仪 4智能性诱 2杀虫灯  9糖醋测报灯  10测报灯rtu
+			//    d_id                    必传                            设备id
+			//    start_time              非必传(string 时间戳)           开始时间    (用于时间搜索)
+			//    end_time
+			async history() {
+				this.dataloadingtf = true
+				const res = await this.$myRequest({
+					url: '/api/api_gateway?method=forecast.worm_lamp.device_polyline_data',
+					data: {
+						device_type_id: 7,
+						d_id: this.d_id,
+						start_time: parseInt(this.start_time / 1000),
+						end_time: parseInt(this.end_time / 1000)
+					}
+				})
+				this.dataloadingtf = false
+				console.log(res)
+				this.historydatas = res
+				console.log(this.historydatas)
+				if (this.historydatas.length == 0) {
+					this.canvastishiTF = false
+				} else {
+					this.canvastishiTF = true
+
+					var arr1 = []
+					var arr2 = []
+					var arr3 = []
+					var xtitle = []
+					for (var i = 0; i < res.length; i++) {
+						var times = new Date(res[i].addtime * 1000)
+						xtitle.push(times.getMonth() + 1 + "/" + times.getDate() + "-" + times.getHours() + ":" +
+							times.getMinutes())
+						arr1.push(res[i].temperature == "" ? "0" : res[i].temperature)
+						arr2.push(res[i].humidity == "" ? "0" : res[i].humidity)
+						if(res[i].others) {
+							arr3.push(res[i].others)
+						} else {
+							if(res[i].others == "") {
+								arr3.push(0)
+							}
+						}
+					}
+					var obj = [{
+						name: '温度',
+						data: arr1,
+						color: '#00E29D'
+					}, {
+						name: '湿度',
+						data: arr2,
+						color: '#6CBBFF'
+					}]
+					if(arr3.length > 0) {
+						obj.push({
+						name: '保温仓温度',
+						data: arr3,
+						color: '#FF3F3F'
+					})
+					}
+					this.showColumn("canvasColumnA", xtitle, obj)
+				}
+			},
+			//forecast.worm_lamp.device_history_data历史数据列表
+			async historylist() { 
+				const res = await this.$myRequest({
+					url: '/api/api_gateway?method=forecast.worm_lamp.device_history_data',
+					data: {
+						device_type_id: 7,
+						device_id: this.device_id,
+						start_time: parseInt(this.start_time / 1000),
+						end_time: parseInt(this.end_time / 1000),
+						page: this.page
+					}
+				})
+				this.historylistdata = res.data
+				this.pagesum = Math.ceil(res.counts / 10) || 1
+				if (res.data.length == 0) {
+					this.forbidden = true
+					console.log(res.data.length)
+				} else {
+					if(res.data[0].d_h_t.set_temp) {
+						this.isShowBwc = true
+					} else {
+						this.isShowBwc = false;
+					}
+					this.forbidden = false
+					console.log(res.data.length)
+				}
+			},
+			changeindex(index) {
+				this.titleidnex = index
+				var now = new Date()
+				this.$forceUpdate()
+				if (index == 0) {
+					this.start_time = this.end_time - 24 * 60 * 60 * 1000
+					this.history()
+					this.historylist()
+				} else if (index == 1) {
+					var oldtime = now.setMonth(now.getMonth() - 1)
+					this.start_time = parseInt(oldtime)
+					this.history()
+					this.historylist()
+				} else if (index == 2) {
+					var oldtime = now.setMonth(now.getMonth() - 6)
+					this.start_time = parseInt(oldtime)
+					this.history()
+					this.historylist()
+				} else if (index == 3) {
+					var oldtime = now.setFullYear(now.getFullYear() - 1)
+					this.start_time = parseInt(oldtime)
+					this.history()
+					this.historylist()
+				}
+			},
+			prev() { //上一页
+				if (this.page > 1) {
+					this.page--
+					this.historylist()
+				}
+			},
+			next() { //下一页
+				if (this.page < this.pagesum) {
+					this.page++
+					this.historylist()
+				}
+			},
+			clickLeft() {
+				uni.navigateBack({
+					delta: 1
+				})
+			},
+			showColumn(id, xtitle, xinfo) {
+				var _self = this;
+				console.log(_self.cWidth, '_self.cWidth');
+				const ctx = uni.createCanvasContext(id, this);
+				canvaColumnA = new uCharts({
+					context: ctx,
+					type: 'line',
+					legend: {
+						position: "top"
+					},
+					fontSize: 11,
+					background: '#FFFFFF',
+					pixelRatio: 1,
+					animation: true,
+					dataLabel: false,
+					categories: xtitle,
+					series: xinfo,
+					enableScroll: true, //开启图表拖拽功能
+					xAxis: {
+						disableGrid: true,
+						type: 'grid',
+						gridType: 'dash',
+						itemCount: 4, //x轴单屏显示数据的数量,默认为5个
+						scrollShow: true, //新增是否显示滚动条,默认false
+						// scrollAlign: 'left', //滚动条初始位置
+						scrollBackgroundColor: '#F7F7FF', //默认为 #EFEBEF
+						scrollColor: '#DEE7F7', //默认为 #A6A6A6
+					},
+					yAxis: {},
+					width: _self.cWidth * 1,
+					height: _self.cHeight * 1,
+					extra: {
+						line: {
+							type: 'curve'
+						}
+					}
+				});
+			},
+			touchLineA(e) {
+				console.log(e)
+				canvaColumnA.scrollStart(e);
+			},
+			moveLineA(e) {
+				canvaColumnA.scroll(e);
+			},
+			touchEndLineA(e) {
+				canvaColumnA.scrollEnd(e);
+				//下面是toolTip事件,如果滚动后不需要显示,可不填写
+				canvaColumnA.showToolTip(e, {
+					format: function(item, category) {
+						return category + ' ' + item.name + ':' + item.data
+					}
+				});
+			},
+			async newdata() {
+				const res = await this.$myRequest({
+					url: '/api/api_gateway?method=forecast.send_control.get_device_config',
+					data: {
+						device_type_id: 7,
+						d_id: this.d_id,
+						control_type: "data"
+					}
+				})
+				if (res) {
+					uni.showToast({
+						title: '刷新成功',
+						duration: 2000,
+						icon: "none"
+					});
+				} else {
+					uni.showToast({
+						title: '刷新失败',
+						duration: 2000,
+						icon: "none"
+					});
+				}
+			},
+			refresh() { //获取当前时间的数据
+				this.newdata()
+			},
+		},
+		onLoad(option) {
+			this.d_id = option.d_id
+			this.device_id = option.device_id
+			this.cWidth = uni.upx2px(650);
+			this.cHeight = uni.upx2px(500);
+		},
+		onShow() {
+			this.end_time = +new Date()
+			this.start_time = this.end_time - 24 * 60 * 60 * 1000
+			setTimeout(() => {
+				this.history()
+				this.historylist()
+			}, 1000)
+		},
+		onPullDownRefresh() {
+			console.log('refresh');
+			this.this.historydatas = []
+			this.this.historylistdata = []
+			this.history()
+			this.historylist()
+			setTimeout(function() {
+				uni.stopPullDownRefresh();
+			}, 1000);
+		}
+	}
+</script>
+
+<style lang="scss">
+	.shuju_one,
+	.shuju_two {
+		position: absolute;
+		top: 54px;
+		width: 90%;
+		left: 5%;
+		box-shadow: 0 0 10rpx #bcb9ca;
+		padding-top: 20rpx;
+		height: 550rpx;
+
+		.canvastishi {
+			font-size: 32rpx;
+			position: absolute;
+			top: 50%;
+			left: 50%;
+			margin-left: -64rpx;
+			margin-top: -21rpx;
+
+			.dataloading:after {
+				overflow: hidden;
+				display: inline-block;
+				vertical-align: bottom;
+				animation: ellipsis 2s infinite;
+				content: "\2026";
+			}
+
+			@keyframes ellipsis {
+				from {
+					width: 2px;
+				}
+
+				to {
+					width: 15px;
+				}
+			}
+		}
+
+		.shuju_one_title {
+			width: 70%;
+			margin: 0 auto;
+			display: flex;
+
+			.tltle_text {
+				width: 25%;
+				border: 2rpx solid #B2B2B2;
+				color: #57c878;
+				text-align: center;
+				font-size: 24rpx;
+				height: 50rpx;
+				line-height: 50rpx;
+			}
+
+			.title_text_color {
+				width: 25%;
+				border: 2rpx solid #57c878;
+				background-color: #57c878;
+				color: #fff;
+				text-align: center;
+				font-size: 24rpx;
+				height: 50rpx;
+				line-height: 50rpx;
+			}
+		}
+	}
+
+	.refresh {
+		position: absolute;
+		top: 700rpx;
+		left: 5%;
+		width: 160rpx;
+		height: 50rpx;
+		background-color: #57c878;
+		color: #FFFFFF;
+		line-height: 50rpx;
+		text-align: center;
+	}
+
+	.condition {
+		position: absolute;
+		top: 770rpx;
+		display: flex;
+		flex-wrap: wrap;
+		width: 90%;
+		left: 5%;
+		box-shadow: 0 0 10rpx #bcb9ca;
+		margin-bottom: 30rpx;
+
+		.scroll-X {
+			width: 95%;
+			margin: 20rpx auto;
+
+			.table {
+				width: 1672px;
+			}
+
+			.tr {
+				display: flex;
+				overflow: hidden;
+
+				.th,
+				.td {
+					display: inline-block;
+					padding: 5rpx;
+					width: 300rpx;
+					text-align: center;
+					height: 52rpx;
+					line-height: 52rpx;
+					border: 2rpx solid #F1F1F1;
+				}
+
+				.th:first-child,
+				.td:first-child {
+					width: 350rpx;
+				}
+			}
+
+			.tr:nth-child(2n-1) {
+				background-color: #f5fff8;
+			}
+
+			.tr:first-child {
+				background-color: #57c878;
+				color: #fff;
+			}
+		}
+
+		.pagenumber {
+			display: flex;
+			margin: 20rpx auto;
+
+			button {
+				width: 150rpx;
+				height: 50rpx;
+				line-height: 50rpx;
+				font-size: 26rpx;
+				text-align: center;
+				background-color: #57c878;
+				color: #FFFFFF;
+				margin: 0 10rpx;
+			}
+
+			.pagenumber_page {
+				width: 100rpx;
+				height: 50rpx;
+				line-height: 50rpx;
+				font-size: 26rpx;
+				text-align: center;
+			}
+		}
+	}
+</style>

+ 445 - 0
pages/cb/bzy/equip-set/equip-set.vue

@@ -0,0 +1,445 @@
+<template>
+	<view>
+		<view class="" v-if="myuser_type">
+			<view class="tit adminTit">
+				操作
+			</view>
+			<view class="btns">
+				 <button type="warn" @click="equipBtnControl('dtu_update')" size="mini">升级</button>
+				 <button type="warn" @click="equipBtnControl('dtu_reboot')" size="mini">重启</button>
+				 <button type="warn" @click="equipBtnControl('takephoto')" size="mini">立即拍照</button>
+				 <button type="warn" @click="equipBtnControl('autotakephoto')" size="mini">对焦拍照</button>
+				 <button type="warn" @click="equipBtnControl('turn')" size="mini">转仓</button>
+			</view>
+			<view class="tit adminTit">
+				设备开关
+			</view>
+			<view class="uni-list-cell"  @click="onoff">
+				<text class="uni-input">{{on_off=="0"?'关闭':'开机'}}</text>
+				<view class="arrow"></view>
+				<u-select v-model="on_off_show" mode="single-column" :list="on_off_list" @confirm="confirm($event,'on_off')"></u-select>
+			</view>
+		</view>
+		<view class="tit">
+			载玻片滴液时间
+		</view>
+		<view class="uni-list-cell" @click="selectFun('drop_time')">
+			<text class="uni-input">{{setFrom.drop_time}}</text>
+			<view class="arrow"></view>
+			<u-select v-model="drop_time_show" mode="single-column" :list="drop_time_List" @confirm="confirm($event,'drop')"></u-select>
+		</view>
+		<view class="tit">
+			孢子培养时间(h)
+		</view>
+		<view class="">
+			<slider :value="setFrom.cul_time" show-value="true" :min="1" :max="24" @change="sliderChange($event,'cul_time')"  block-color="#57C878" activeColor="#57C878" step="1" />
+		</view>
+		<view class="tit">
+			保温仓设定温度(℃)
+		</view>
+		<view class="">
+			<slider :value="setFrom.set_temp" show-value="true" :min="10" :max="40" @change="sliderChange($event,'set_temp')"  block-color="#57C878" activeColor="#57C878" step="1" />
+		</view>
+		<view class="tit">
+			数据上传时间间隔(min)
+		</view>
+		<view class="">
+			<slider :value="setFrom.datt" show-value="true" :min="10" :max="60" @change="sliderChange($event,'datt')"  block-color="#57C878" activeColor="#57C878" step="1" />
+		</view>
+		<view class="tit">
+			采集开启和关闭时间
+		</view>
+		<view class="selectTime">
+			<view class="uni-list-cell time" @click="selectTime('st1')">
+				<text>{{coll_time.time01||'开始时间'}}</text>
+				<u-icon name="clock"></u-icon>
+			</view>
+			<text class="line">-</text>
+			<view class="uni-list-cell time" @click="selectTime('et1')">
+				<text>{{coll_time.time02||'结束时间'}}</text>
+				<u-icon name="clock"></u-icon>
+			</view>
+		</view>
+		<view class="selectTime">
+			<view class="uni-list-cell time" @click="selectTime('st2')">
+				<text>{{coll_time.time03||'开始时间'}}</text>
+				<u-icon name="clock"></u-icon>
+			</view>
+			<text class="line">-</text>
+			<view class="uni-list-cell time" @click="selectTime('et2')">
+				<text>{{coll_time.time04||'结束时间'}}</text>
+				<u-icon name="clock"></u-icon>
+			</view>
+		</view>
+		<view class="selectTime">
+			<view class="uni-list-cell time" @click="selectTime('st3')">
+				<text>{{coll_time.time05||'开始时间'}}</text>
+				<u-icon name="clock"></u-icon>
+			</view>
+			<text class="line">-</text>
+			<view class="uni-list-cell time" @click="selectTime('et3')">
+				<text>{{coll_time.time06||'结束时间'}}</text>
+				<u-icon name="clock"></u-icon>
+			</view>
+		</view>
+		<view class="submit-box">
+			<u-button  @click="submit" type="success">确定</u-button>
+		</view>
+		<u-select v-model="collShow" mode="single-column" :list="timeList" @confirm="collConfirm($event,timeType)"></u-select>
+		<u-toast ref="toast" />
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				d_id:'',
+				on_off_show:false,
+				on_off:null,//设备开关
+				on_off_list:[{
+					value:0,
+					label:'关闭'
+				},{
+					value:1,
+					label:'开机'
+				}],
+				drop_time_show:false,
+				drop_time_List:[],
+			    setFrom: {
+					drop_time: "1", //载玻片滴液时间
+					cul_time: 1, //孢子培养时间
+					set_temp: 10, //保温仓设定温度
+					datt: 10, //数据上传时间间隔(h)-m
+					coll_time: [], //采集开启和关闭时间
+				 },
+				coll_time: {
+			        time01: "",
+			        time02: "",
+			        time03: "",
+			        time04: "",
+			        time05: "",
+			        time06: "",
+					value01: "",
+					value02: "",
+					value03: "",
+					value04: "",
+					value05: "",
+					value06: "",
+			      },
+				timeList:[] ,
+				collShow:false,
+				timeType:'',
+				myuser_type:false
+			}
+		},
+		onLoad(option){
+			this.d_id=option.d_id
+			this.equipOperation()
+			this.equipSet()
+			uni.getStorage({
+				key:"myuser_type",
+				success:(res)=>{
+					if(Number(res.data) == 1){
+						this.myuser_type = true
+					}
+				}
+			})
+		},
+		methods: {
+			//回显设备控制参数
+			async equipSet(){
+				let res=await this.$myRequest({
+					url:'/api/api_gateway?method=forecast.send_control.device_control_info',
+					data:{
+						d_id:this.d_id,
+						cmd: "paramconf" 
+					}
+				})
+				this.setFrom.drop_time=res.drop_time 
+				this.setFrom.cul_time=res.cul_time
+				this.setFrom.set_temp=res.set_temp
+				this.setFrom.datt=res.datt
+				let coll_time=res.coll_time 
+				for (let i in coll_time) {
+					if (i == 0) {
+					  let arr = coll_time[i].split("-");
+					  this.coll_time.time01 =
+						Number(arr[0]) < 10 ? "0" + arr[0] + ":00" : arr[0] + ":00";
+					  this.coll_time.time02 =
+						Number(arr[1]) < 10 ? "0" + arr[1] + ":00" : arr[1] + ":00";
+					  this.coll_time.value01=Number(arr[0])
+					  this.coll_time.value02=Number(arr[1])
+					} else if (i == 1) {
+					  let arr = coll_time[i].split("-");
+					  this.coll_time.time03 =
+						Number(arr[0]) < 10 ? "0" + arr[0] + ":00" : arr[0] + ":00";
+					  this.coll_time.time04 =
+						Number(arr[1]) < 10 ? "0" + arr[1] + ":00" : arr[1] + ":00";
+						this.coll_time.value03=Number(arr[0])
+						this.coll_time.value04=Number(arr[1])
+					} else if (i == 2) {
+					  let arr = coll_time[i].split("-");
+					  this.coll_time.time05 =
+						Number(arr[0]) < 10 ? "0" + arr[0] + ":00" : arr[0] + ":00";
+					  this.coll_time.time06 =
+						Number(arr[1]) < 10 ? "0" + arr[1] + ":00" : arr[1] + ":00";
+						this.coll_time.value05=Number(arr[0])
+						this.coll_time.value06=Number(arr[1])
+					}
+				 }
+			console.log(this.setFrom)	
+			},
+			//回显设备开关状态
+			async equipOperation(){
+				let res=await this.$myRequest({
+					url:'/api/api_gateway?method=forecast.worm_lamp.bzy_device',
+					data:{
+						d_id: this.d_id
+					}
+				})
+				this.on_off=res.on_off
+			},
+			//管理员操作
+			async equipBtnControl(cmd){
+					let res=await this.$myRequest({
+						url:'/api/api_gateway?method=forecast.send_control.admin_device_control',
+						data:{
+							cmd,
+							device_type_id: 7,
+							d_id: this.d_id
+						}
+					})
+					if(res){
+						this.$refs.toast.show({
+							title: '指令下发成功!',
+							type: 'success',
+						})
+					}
+			},
+			onoff(){
+					this.on_off_show=true
+			},
+			confirm(e,a){
+				switch(a){
+					case "on_off":
+						if(e[0].value){
+							 this.equipControl("poweron",e[0].value);
+						}else{
+							this.equipControl("poweroff",e[0].value);
+						}
+						break;
+					case "drop":
+						this.setFrom.drop_time=e[0].value;
+						break;
+				}
+			},
+			async equipControl(cmd,val){
+				let res=await this.$myRequest({
+					url:'/api/api_gateway?method=forecast.send_control.admin_device_control',
+					data:{
+						cmd,
+						device_type_id: 7,
+						d_id: this.d_id
+					}
+				})
+				this.on_off=val;
+			},
+			selectFun(a){
+				switch(a){
+					case 'drop_time':
+						for(let i=1;i<31;i++){
+							this.drop_time_List.push({
+								value:i,
+								label:i
+							})
+						}
+						this.drop_time_show=true;
+				}
+			},
+			sliderChange(e,a){
+				switch(a){
+					case 'cul_time':
+					  this.setFrom.cul_time=e.detail.value;
+					  break;
+					case 'set_temp':
+					   this.setFrom.set_temp=e.detail.value;
+					   break;
+					case 'datt':
+					  this.setFrom.datt=e.detail.value;
+					  break;
+				}
+			},
+			selectTime(a){
+				this.timeType=a
+				let arr=[]
+				if(a=='st1'){
+					for(let i=1;i<25;i++){
+						let label=i<10?`0${i}:00`:`${i}:00`
+						arr.push({
+							value:i,
+							label
+						})
+					}
+					this.timeList=arr
+				}else if(a=='et1'){
+					for(let i=this.coll_time.value01+1;i<25;i++){
+						let label=i<10?`0${i}:00`:`${i}:00`
+						arr.push({
+							value:i,
+							label
+						})
+					}
+					this.timeList=arr
+				}else if(a=='st2'){
+					for(let i=this.coll_time.value02+1;i<25;i++){
+						let label=i<10?`0${i}:00`:`${i}:00`
+						arr.push({
+							value:i,
+							label
+						})
+					}
+					this.timeList=arr
+				}else if(a=='et2'){
+					for(let i=this.coll_time.value03+1;i<25;i++){
+						let label=i<10?`0${i}:00`:`${i}:00`
+						arr.push({
+							value:i,
+							label
+						})
+					}
+					this.timeList=arr
+				}else if(a=='st3'){
+					for(let i=this.coll_time.value04+1;i<25;i++){
+						let label=i<10?`0${i}:00`:`${i}:00`
+						arr.push({
+							value:i,
+							label
+						})
+					}
+					this.timeList=arr
+				}else if(a=='et3'){
+					for(let i=this.coll_time.value05+1;i<25;i++){
+						let label=i<10?`0${i}:00`:`${i}:00`
+						arr.push({
+							value:i,
+							label
+						})
+					}
+					this.timeList=arr
+				}
+				this.collShow=true
+			},
+			collConfirm(e,a){
+				if(a=='st1'){
+					this.coll_time.time01=e[0].label
+					this.coll_time.value01=e[0].value
+				}else if(a=='et1'){
+					this.coll_time.time02=e[0].label
+					this.coll_time.value02=e[0].value
+				}else if(a=='st2'){
+					this.coll_time.time03=e[0].label
+					this.coll_time.value03=e[0].value
+				}else if(a=='et2'){
+					this.coll_time.time04=e[0].label
+					this.coll_time.value04=e[0].value
+				}else if(a=='st3'){
+					this.coll_time.time05=e[0].label
+					this.coll_time.value05=e[0].value
+				}else if(a=='et3'){
+					this.coll_time.time06=e[0].label
+					this.coll_time.value06=e[0].value
+				}
+			},
+			async submit(){
+				let arr=[]
+				if(this.coll_time.value01&&this.coll_time.value02){
+					arr.push(`${this.coll_time.value01}-${this.coll_time.value02}`)
+				}
+				if(this.coll_time.value03&&this.coll_time.value04){
+					arr.push(`${this.coll_time.value03}-${this.coll_time.value04}`)
+				}
+				if(this.coll_time.value05&&this.coll_time.value06){
+					arr.push(`${this.coll_time.value05}-${this.coll_time.value06}`)
+				}
+				this.setFrom.coll_time=arr
+				console.log(this.setFrom)
+				let res=await this.$myRequest({
+					url:'/api/api_gateway?method=forecast.send_control.device_control',
+					data:{
+						device_type_id: 7,
+						d_id: this.d_id,
+						config: JSON.stringify(this.setFrom),
+					}
+				})
+				// console.log(res);
+				if(res === true){
+					this.$refs.toast.show({
+						title: '指令下发成功',
+						type: 'success',
+						callback:function(){
+							uni.navigateBack({
+								delta: 1
+							});	
+						}
+					})
+				} else {
+					this.$refs.toast.show({
+						title: '服务出错了',
+						type: 'error'
+					})
+				}
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	page{
+		padding:20rpx;
+		box-sizing: border-box;
+	.tit{
+		line-height:30rpx;
+		font-size:30rpx;
+		padding-left:20rpx;
+		border-left-width:2px;
+		border-left-style: solid;
+		border-left-color:$uni-color-success;
+		margin:30rpx 0;
+		}
+	.adminTit{border-left-color:#e64340;}
+	.btns{
+		display:flex;
+		justify-content: flex-start;
+		flex-wrap:no-wrap;
+		button{margin:0;margin-right:10rpx;padding:0 25rpx;}
+	}
+	.uni-list-cell{
+		background:#F7F8FA;
+		padding:10rpx 40rpx;
+		font-size:28rpx;
+		box-sizing: border-box;
+		.arrow{
+			display:inline-block;
+			border-width:12rpx 8rpx ;
+			border-style: solid;
+			float:right;
+			margin-top:10rpx;
+			border-color:#888 transparent transparent transparent;
+		}
+	}
+	.selectTime{
+		display:flex;
+		margin-bottom:20rpx;
+		.time{
+			width:350rpx;
+			display:flex;
+			justify-content: space-between;
+		}
+		.line{width:50rpx;text-align: center;}
+	}
+	.submit-box{
+		margin-top:60rpx
+	}
+	}
+</style>

+ 154 - 0
pages/cb/cbd/equip-set/addimg.vue

@@ -0,0 +1,154 @@
+<template>
+	<view>
+		<view class="status_bar"></view>
+		<view class="" style="position: relative;top: 44px;">
+			<view style="position: fixed;z-index: 100;">
+				<uni-nav-bar @clickLeft="clickLeft" left-icon="back" title="手动添加"></uni-nav-bar>
+			</view>
+			<view class="imgform">
+				<u-form :model="form" ref="uForm">
+					<u-form-item label="害虫名称" :required="requireds" label-width="150rpx" prop="pest_name" class="form_item">
+						<u-input v-model="form.pest_name" />
+					</u-form-item>
+					<u-form-item label="害虫数量" :required="requireds" label-width="150rpx" prop="pest_num" class="form_item">
+						<u-input v-model="form.pest_num" type="number" />
+					</u-form-item>
+					<u-form-item label="作物种类" label-width="150rpx" class="form_item">
+						<u-input v-model="form.crop_name" />
+					</u-form-item>
+					<u-form-item label="虫害阶段" label-width="150rpx" class="form_item">
+						<u-input v-model="form.pest_case" />
+					</u-form-item>
+				</u-form>
+				<view class="imgform_btn">
+					<button @click="ensure">确定</button>
+					<button @click="cancel">取消</button>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				requireds: true,
+				form: {
+					pest_name: '',
+					pest_num: "",
+					crop_name: '',
+					pest_case: ""
+				},
+				rules: {
+					pest_name: [{
+						required: true,
+						message: '请输入害虫名称',
+						trigger: ['blur', 'change'],
+					}],
+					pest_num: [{
+						required: true,
+						message: '请输入害虫数量',
+						trigger: ['blur', 'change'],
+					}],
+				},
+				id: '',
+				device_id: "",
+				addtime:1
+
+			}
+		},
+		methods: {
+			//describe: "{"pest_num":"1","crop_name":"水稻","pest_case":"1","pest_name":"七星瓢虫"}"
+			// device_id: "819"
+			// img_id: "2396"
+			async species(id) { //统计
+				var time = +new Date()
+				const res = await this.$myRequest({
+					url: '/api/api_gateway?method=forecast.forecast_system.equip_photo_describe',
+					data: {
+						ret: "add_desc",
+						img_id: this.id,
+						describe: JSON.stringify(this.form),
+						device_id:this.device_id,
+						photo_time:this.addtime,
+						time: time,
+					}
+				})
+				console.log(res)
+				if(res){
+					uni.showToast({
+						title: '添加成功',
+						duration: 1000,
+						image: ""
+					});
+				}
+			},
+			clickLeft() {
+				uni.navigateBack({
+					delta: 1
+				})
+			},
+			cancel() { //取消
+				this.clickLeft()
+			},
+			ensure() {
+				if (this.form.pest_name.length == 0) {
+					uni.showToast({
+						title: '请输入害虫名称',
+						duration: 1000,
+						image: ""
+					});
+				} else if (this.form.pest_num.length == 0) {
+					uni.showToast({
+						title: '请输入害虫数量',
+						duration: 1000,
+						image: ""
+					});
+				} else {
+					this.species()
+					// this.clickLeft()
+				}
+			}
+		},
+		onReady() {
+			this.$refs.uForm.setRules(this.rules);
+		},
+		onLoad(option) {
+			console.log(option)
+			this.id = option.id
+			this.device_id = option.device_id
+			this.addtime = option.addtime
+		}
+	}
+</script>
+
+<style lang="scss">
+	.imgform {
+		position: absolute;
+		top: 54px;
+		width: 90%;
+		left: 5%;
+		.form_item{
+			width: 90%;
+			margin: 0 auto;
+			border-bottom: 2rpx solid #dedede;
+		}
+		.imgform_btn {
+			margin-top: 40rpx;
+			display: flex;
+
+			button {
+				width: 300rpx;
+				font-size: 28rpx;
+				height: 60rpx;
+				line-height: 60rpx;
+			}
+
+			button:first-child {
+				color: #FFFFFF;
+				background-color: #14A478;
+			}
+		}
+	}
+</style>

+ 0 - 0
pages/cb/cbd/equip-set/analyse.vue


Некоторые файлы не были показаны из-за большого количества измененных файлов