Browse Source

初始化商家端

rambo 2 years ago
commit
ef85d5634b
100 changed files with 14844 additions and 0 deletions
  1. 23 0
      App.vue
  2. 19 0
      api/area.js
  3. 31 0
      api/common.js
  4. 11 0
      api/config.js
  5. 140 0
      api/homesearch.js
  6. 117 0
      api/seller.js
  7. 80 0
      api/sellerAccount.js
  8. 63 0
      api/sellerAccountGroup.js
  9. 53 0
      api/sellerAddress.js
  10. 30 0
      api/sellerBill.js
  11. 49 0
      api/sellerChain.js
  12. 100 0
      api/sellerCompliant.js
  13. 36 0
      api/sellerConsult.js
  14. 54 0
      api/sellerDeposit.js
  15. 28 0
      api/sellerEvaluate.js
  16. 24 0
      api/sellerExpress.js
  17. 188 0
      api/sellerGoods.js
  18. 72 0
      api/sellerGoodsClass.js
  19. 55 0
      api/sellerInstantMessage.js
  20. 91 0
      api/sellerInviter.js
  21. 77 0
      api/sellerLiveApply.js
  22. 16 0
      api/sellerLogin.js
  23. 69 0
      api/sellerMiniproLive.js
  24. 42 0
      api/sellerMoney.js
  25. 14 0
      api/sellerNotice.js
  26. 89 0
      api/sellerOrder.js
  27. 63 0
      api/sellerRefund.js
  28. 36 0
      api/sellerSetting.js
  29. 15 0
      api/sellerStatistics.js
  30. 44 0
      api/sellerTransport.js
  31. 84 0
      api/sellerVoucher.js
  32. 50 0
      api/sellerVrOrder.js
  33. 699 0
      components/thorui/tui-picture-cropper/tui-picture-cropper.vue
  34. 560 0
      components/thorui/tui-picture-cropper/tui-picture-cropper.wxs
  35. 22 0
      main.js
  36. 131 0
      manifest.json
  37. 15 0
      node_modules/.bin/uuid
  38. 17 0
      node_modules/.bin/uuid.cmd
  39. 18 0
      node_modules/.bin/uuid.ps1
  40. 685 0
      node_modules/axios/CHANGELOG.md
  41. 19 0
      node_modules/axios/LICENSE
  42. 800 0
      node_modules/axios/README.md
  43. 162 0
      node_modules/axios/UPGRADE_GUIDE.md
  44. 1756 0
      node_modules/axios/dist/axios.js
  45. 0 0
      node_modules/axios/dist/axios.map
  46. 1 0
      node_modules/axios/dist/axios.min.js
  47. 0 0
      node_modules/axios/dist/axios.min.map
  48. 161 0
      node_modules/axios/index.d.ts
  49. 1 0
      node_modules/axios/index.js
  50. 37 0
      node_modules/axios/lib/adapters/README.md
  51. 303 0
      node_modules/axios/lib/adapters/http.js
  52. 179 0
      node_modules/axios/lib/adapters/xhr.js
  53. 56 0
      node_modules/axios/lib/axios.js
  54. 19 0
      node_modules/axios/lib/cancel/Cancel.js
  55. 57 0
      node_modules/axios/lib/cancel/CancelToken.js
  56. 5 0
      node_modules/axios/lib/cancel/isCancel.js
  57. 95 0
      node_modules/axios/lib/core/Axios.js
  58. 52 0
      node_modules/axios/lib/core/InterceptorManager.js
  59. 7 0
      node_modules/axios/lib/core/README.md
  60. 20 0
      node_modules/axios/lib/core/buildFullPath.js
  61. 18 0
      node_modules/axios/lib/core/createError.js
  62. 79 0
      node_modules/axios/lib/core/dispatchRequest.js
  63. 42 0
      node_modules/axios/lib/core/enhanceError.js
  64. 87 0
      node_modules/axios/lib/core/mergeConfig.js
  65. 25 0
      node_modules/axios/lib/core/settle.js
  66. 20 0
      node_modules/axios/lib/core/transformData.js
  67. 98 0
      node_modules/axios/lib/defaults.js
  68. 7 0
      node_modules/axios/lib/helpers/README.md
  69. 11 0
      node_modules/axios/lib/helpers/bind.js
  70. 70 0
      node_modules/axios/lib/helpers/buildURL.js
  71. 14 0
      node_modules/axios/lib/helpers/combineURLs.js
  72. 53 0
      node_modules/axios/lib/helpers/cookies.js
  73. 24 0
      node_modules/axios/lib/helpers/deprecatedMethod.js
  74. 14 0
      node_modules/axios/lib/helpers/isAbsoluteURL.js
  75. 11 0
      node_modules/axios/lib/helpers/isAxiosError.js
  76. 68 0
      node_modules/axios/lib/helpers/isURLSameOrigin.js
  77. 12 0
      node_modules/axios/lib/helpers/normalizeHeaderName.js
  78. 53 0
      node_modules/axios/lib/helpers/parseHeaders.js
  79. 27 0
      node_modules/axios/lib/helpers/spread.js
  80. 351 0
      node_modules/axios/lib/utils.js
  81. 116 0
      node_modules/axios/package.json
  82. 21 0
      node_modules/cos-js-sdk-v5/LICENSE
  83. 111 0
      node_modules/cos-js-sdk-v5/README.md
  84. 17 0
      node_modules/cos-js-sdk-v5/bower.json
  85. 79 0
      node_modules/cos-js-sdk-v5/csp/AllowAction.md
  86. 7 0
      node_modules/cos-js-sdk-v5/csp/README.md
  87. 1936 0
      node_modules/cos-js-sdk-v5/csp/api.md
  88. 156 0
      node_modules/cos-js-sdk-v5/csp/auth-json.php
  89. 651 0
      node_modules/cos-js-sdk-v5/csp/csp.html
  90. 80 0
      node_modules/cos-js-sdk-v5/csp/start.md
  91. 1603 0
      node_modules/cos-js-sdk-v5/csp/test.html
  92. 155 0
      node_modules/cos-js-sdk-v5/demo/common/cos-auth.js
  93. 0 0
      node_modules/cos-js-sdk-v5/demo/common/cos-auth.min.js
  94. 1 0
      node_modules/cos-js-sdk-v5/demo/common/jquery-3.3.1.min.js
  95. 29 0
      node_modules/cos-js-sdk-v5/demo/common/lodash.core.min.js
  96. 5 0
      node_modules/cos-js-sdk-v5/demo/common/vue.min.js
  97. BIN
      node_modules/cos-js-sdk-v5/demo/cors.png
  98. 1033 0
      node_modules/cos-js-sdk-v5/demo/demo.js
  99. 1 0
      node_modules/cos-js-sdk-v5/demo/empty.html
  100. 19 0
      node_modules/cos-js-sdk-v5/demo/folder/index.html

+ 23 - 0
App.vue

@@ -0,0 +1,23 @@
+<script>
+	export default {
+		onLaunch: function() {
+			console.log('App Launch')
+		},
+		onShow: function() {
+			console.log('App Show')
+		},
+		onHide: function() {
+			console.log('App Hide')
+		}
+	}
+</script>
+
+<style lang='scss'>
+  /*每个页面公共css */
+  /*  #ifndef  APP-PLUS-NVUE  */
+  @import 'static/style/iconfont/iconfont.css';
+  @import 'static/style/common.scss';
+  @import 'static/style/uni-ui.scss';
+  /*  #endif  */
+</style>
+

+ 19 - 0
api/area.js

@@ -0,0 +1,19 @@
+import { requestApi } from '../util/network'
+
+//
+export const getAreaTree =
+    () =>
+      requestApi(
+        '/Area/area_app',
+        'POST',
+        {
+        }
+      )
+export const getAreaList =
+    () =>
+      requestApi(
+        '/Area/area_list',
+        'POST',
+        {
+        }
+      )

+ 31 - 0
api/common.js

@@ -0,0 +1,31 @@
+import { requestApi } from '../util/network'
+// 获取手机验证码
+export const getSmsCaptcha =
+    (type, phone) =>
+      requestApi(
+        '/Connect/get_sms_captcha',
+        'GET',
+        {
+          'type': type,
+          'phone': phone
+        }
+      )
+// 验证码检测
+export const checkPictureCaptcha =
+    (captcha) =>
+      requestApi(
+        '/Seccode/check',
+        'POST',
+        {
+          'captcha': captcha
+        }
+      )
+export const getWechatShare =
+    (url) =>
+        requestApi(
+            '/index/getWechatShare',
+            'POST',
+            {
+                'url': url
+            }
+        )

+ 11 - 0
api/config.js

@@ -0,0 +1,11 @@
+import { requestApi } from '../util/network'
+
+// 获取系统配置
+export const getConfigList =
+    () =>
+      requestApi(
+        '/index/getConfigList',
+        'POST',
+        {
+        }
+      )

+ 140 - 0
api/homesearch.js

@@ -0,0 +1,140 @@
+import { requestApi } from '../util/network'
+
+// 热门关键词
+export const searchKeywordList =
+() =>
+  requestApi(
+    '/Index/search_key_list',
+    'POST',
+    {
+    }
+  )
+
+// 商品搜索
+export const searchGoodsList =
+    (params) =>
+      requestApi(
+        '/Goods/goods_list',
+        'GET',
+        {
+          'keyword': params.keyword ? params.keyword : '', // 关键字 (选填)
+          'b_id': params.b_id ? params.b_id : '', // 所属品牌id (选填)
+          'cate_id': params.cate_id ? params.cate_id : '', // 所属商品分类id (选填)
+          'a_id': params.a_id ? params.a_id : '', // 当前所选属性
+          'price_from': params.price_from ? params.price_from : '',
+          'price_to': params.price_to ? params.price_to : '',
+          'own_shop': params.own_shop ? params.own_shop : '',
+          'gift': params.gift ? params.gift : '',
+          'area_id': params.area_id ? params.area_id : '',
+          'groupbuy': params.groupbuy ? params.groupbuy : '',
+          'xianshi': params.xianshi ? params.xianshi : '',
+          'virtual': params.virtual ? params.virtual : '',
+          'sort_key': params.sort_key ? params.sort_key : '',
+          'sort_order': params.sort_order ? params.sort_order : '',
+          'page': params.page ? params.page : '1' // 当前第几页
+        }
+      )
+// 获取商品属性
+export const getAttribute =
+    (params) =>
+      requestApi(
+        '/Goods/get_attribute',
+        'GET',
+        {
+          'b_id': params.b_id ? params.b_id : '', // 所属品牌id (选填)
+          'cate_id': params.cate_id ? params.cate_id : '', // 所属商品分类id (选填)
+          'a_id': params.a_id ? params.a_id : '' // 当前所选属性
+        }
+      )
+// 获取商品分类
+export const getGoodsclassList = () =>
+  requestApi(
+    '/Goodsclass/index',
+    'POST',
+    {
+
+    }
+  )
+
+// 商品搜索
+export const getStoreList =
+    (brand, category, keyword, lng, lat, sort_key, page, key = '') =>
+      requestApi(
+        '/Store/store_list',
+        'POST',
+        {
+          'brand': brand, // 所属品牌id (选填)
+          'cate_id': category, // 所属店铺分类id (选填)
+          'keyword': keyword, // 关键字 (选填)
+          'longitude': lng,
+          'latitude': lat,
+          'sort_key': sort_key, // 键
+          'page': page, // 当前第几页
+          'key': key
+        }
+      )
+// 商品搜索
+export const getStoreNearbyList =
+    (brand, category, keyword, lng, lat, sort_key, page, key = '') =>
+      requestApi(
+        '/Shopnearby/index',
+        'POST',
+        {
+          'brand': brand, // 所属品牌id (选填)
+          'storeclass_id': category, // 所属店铺分类id (选填)
+          'keyword': keyword, // 关键字 (选填)
+          'longitude': lng,
+          'latitude': lat,
+          'sort_key': sort_key, // 键
+          'page': page, // 当前第几页
+          'key': key
+        }
+      )
+// 门店搜索
+export const getChainList =
+    (data, params) =>
+      requestApi(
+        '/Chain/chain_list',
+        'POST',
+        Object.assign(data, params)
+      )
+// 获取品牌列表
+export const getBrandList =
+    (recommend) =>
+      requestApi(
+        '/Brand/get_list',
+        'POST',
+        {
+          recommend: recommend
+        }
+      )
+
+// 获取拼团列表
+export const getPintuanList =
+    (params) =>
+      requestApi(
+        '/Pintuan/index',
+        'POST',
+        {
+          'page': params.page // 当前第几页
+        }
+      )
+
+// 获取抢购列表 groupbuy_is_vr参数判断是否是虚拟
+export const getGroupbuyList =
+    (params) =>
+      requestApi(
+        '/Groupbuy/index',
+        'POST',
+        params
+      )
+// 获取抢购条件
+export const getGroupbuyFilter =
+    (groupbuy_is_vr) =>
+      requestApi(
+        '/Groupbuy/filter',
+        'POST',
+        {
+          'groupbuy_is_vr': groupbuy_is_vr
+        }
+      )

+ 117 - 0
api/seller.js

@@ -0,0 +1,117 @@
+import { requestApi } from '../util/network'
+
+// 卖家退出登录
+export const logout =
+    (seller_name) =>
+      requestApi(
+        '/Sellerlogout/index',
+        'POST',
+        {
+          seller_name: seller_name,
+          client: 'wap'
+        },
+        'seller'
+      )
+// 获取店铺基本信息
+export const getSellerInfo =
+    () =>
+      requestApi(
+        '/Sellerindex/index',
+        'POST',
+        {
+          'client_type': 'wap'
+        },
+        'seller'
+      )
+export const getStoreClass =
+    () =>
+      requestApi(
+        '/store/get_store_class',
+        'POST',
+        {
+
+        }
+      )
+export const getStoreGrade =
+    () =>
+      requestApi(
+        '/store/get_store_grade',
+        'POST',
+        {
+
+        }
+      )
+export const getStoreJoinin =
+    () =>
+      requestApi(
+        '/Sellerjoinin/get_info',
+        'POST',
+        {
+
+        },
+        'member'
+      )
+export const saveStoreJoinin2 =
+    (joinin) =>
+      requestApi(
+        '/Sellerjoinin/step2',
+        'POST',
+        joinin,
+        'member'
+      )
+export const saveStoreJoinin3 =
+    (joinin) =>
+      requestApi(
+        '/Sellerjoinin/step3',
+        'POST',
+        joinin,
+        'member'
+      )
+export const saveStoreJoinin4 =
+    (joinin) =>
+      requestApi(
+        '/Sellerjoinin/step4',
+        'POST',
+        joinin,
+        'member'
+      )
+export const saveStoreJoinin5 =
+    (joinin) =>
+      requestApi(
+        '/Sellerjoinin/pay_save',
+        'POST',
+        joinin,
+        'member'
+      )
+export const uploadInfoFile =
+    (file) =>
+      requestApi(
+        '/Sellerjoinin/upload_image',
+        'POST',
+        file,
+        'member',
+        true
+      )
+// 获取店铺日志记录
+export const getSellerLogList =
+    () =>
+      requestApi(
+        '/Sellerlog/log_list',
+        'POST',
+        {
+
+        },
+        'seller'
+      )
+
+// 获取店铺的消费记录
+export const getSellerCostList =
+    (params) =>
+      requestApi(
+        '/Sellercost/cost_list',
+        'POST',
+        {
+			'page': params.page // 当前第几页
+        },
+        'seller'
+      )

+ 80 - 0
api/sellerAccount.js

@@ -0,0 +1,80 @@
+import { requestApi } from '../util/network'
+
+// 获取店铺账户组列表
+export const getSellerAccountGroupList =
+    () =>
+      requestApi(
+        '/Selleraccount/group_list',
+        'POST',
+        {
+          'client_type': 'wap'
+        },
+        'seller'
+      )
+// 获取店铺子账户列表
+export const getSellerAccountList =
+    () =>
+      requestApi(
+        '/Selleraccount/account_list',
+        'POST',
+        {
+          'client_type': 'wap'
+        },
+        'seller'
+      )
+
+// 获取店铺单个子账户信息
+export const getSellerAccountInfo =
+    (sellerId) =>
+      requestApi(
+        '/Selleraccount/account_info',
+        'POST',
+        {
+          'seller_id': sellerId,
+          'client_type': 'wap'
+        },
+        'seller'
+      )
+
+// 删除店铺子账户
+export const delSellerAccount =
+    (sellerId) =>
+      requestApi(
+        '/Selleraccount/account_del',
+        'POST',
+        {
+          'seller_id': sellerId,
+          'client_type': 'wap'
+        },
+        'seller'
+      )
+
+// 编辑店铺子账户
+export const editSellerAccount =
+    (data) =>
+      requestApi(
+        '/Selleraccount/account_edit',
+        'POST',
+        {
+          'seller_id': data.seller_id,
+          'group_id': data.sellergroup_id,
+          'client_type': 'wap'
+        },
+        'seller'
+      )
+
+// 新增店铺子账户
+export const addSellerAccount =
+    (data) =>
+      requestApi(
+        '/Selleraccount/account_add',
+        'POST',
+        {
+          'member_name': data.member_name,
+          'password': data.password,
+          'seller_name': data.seller_name,
+          'group_id': data.sellergroup_id,
+          'client_type': 'wap'
+        },
+        'seller'
+      )

+ 63 - 0
api/sellerAccountGroup.js

@@ -0,0 +1,63 @@
+import { requestApi } from '../util/network'
+
+// 获取店铺账户组列表
+export const getCommonData =
+    () =>
+      requestApi(
+        '/Selleraccountgroup/get_common_data',
+        'POST',
+        {
+        },
+        'seller'
+      )
+// 获取店铺子账户列表
+export const getAccountGroupList =
+    () =>
+      requestApi(
+        '/Selleraccountgroup/group_list',
+        'POST',
+        {
+        },
+        'seller'
+      )
+
+// 获取店铺单个子账户信息
+export const getAccountGroupInfo =
+    (group_id) =>
+      requestApi(
+        '/Selleraccountgroup/group_edit',
+        'POST',
+        {
+          'group_id': group_id,
+        },
+        'seller'
+      )
+
+// 删除店铺子账户
+export const delAccountGroup =
+    (group_id) =>
+      requestApi(
+        '/Selleraccountgroup/group_del',
+        'POST',
+        {
+          'group_id': group_id,
+        },
+        'seller'
+      )
+
+// 编辑店铺子账户
+export const editAccountGroup =
+    (group_id, seller_group_name, menu, smt) =>
+      requestApi(
+        '/Selleraccountgroup/group_save',
+        'POST',
+        {
+          'group_id': group_id,
+          'seller_group_name': seller_group_name,
+          'limits': menu,
+          'smt_limits': smt
+        },
+        'seller'
+      )
+
+

+ 53 - 0
api/sellerAddress.js

@@ -0,0 +1,53 @@
+import { requestApi } from '../util/network'
+// 获取发货地址列表
+export const getAddressList =
+() =>
+  requestApi(
+    '/Sellerdeliverset/address_list',
+    'POST',
+    {
+
+    },
+    'seller'
+  )
+// 获取单条发货地址信息
+export const getAddressInfo =
+    (addressId) =>
+      requestApi(
+        '/Sellerdeliverset/address_info',
+        'POST',
+        {
+          'address_id': addressId
+        },
+        'seller'
+      )
+
+// 编辑用户发货地址
+export const editAddress =
+    (data, addressId) =>
+      requestApi(
+        '/Sellerdeliverset/address_add',
+        'POST',
+        {
+          'address_id': addressId,
+          'seller_name': data.seller_name,
+          'area_id': data.area_id,
+          'city_id': data.city_id,
+          'area_info': data.area_info,
+          'address': data.daddress_detail,
+          'telphone': data.daddress_telphone,
+          'is_default': data.daddress_isdefault
+        },
+        'seller'
+      )
+// 删除用户发货地址
+export const delAddress =
+    (addressId) =>
+      requestApi(
+        '/Sellerdeliverset/address_del',
+        'POST',
+        {
+          'address_id': addressId
+        },
+        'seller'
+      )

+ 30 - 0
api/sellerBill.js

@@ -0,0 +1,30 @@
+import { requestApi } from '../util/network'
+
+// 获取结算列表
+export const getBillList =
+    (params, ob_no, bill_state) =>
+      requestApi(
+        '/Sellerbill/bill_list',
+        'POST',
+        {
+          'ob_no': ob_no,
+          'bill_state': bill_state,
+          'page': params.page,
+          'per_page': params.per_page,
+          'client_type': 'wap'
+        },
+        'seller'
+      )
+// 确认结算单
+export const confirmBill =
+    (obNo, content) =>
+      requestApi(
+        '/Sellerbill/confirm_bill',
+        'POST',
+        {
+          'ob_no': obNo,
+          'ob_seller_content': content
+
+        },
+        'seller'
+      )

+ 49 - 0
api/sellerChain.js

@@ -0,0 +1,49 @@
+import { requestApi } from '../util/network'
+
+// 获取店铺门店列表
+export const getChainList =
+    (data, params) =>
+      requestApi(
+        '/seller_chain/index',
+        'POST',
+        Object.assign(data, params),
+        'seller'
+      )
+
+// 获取店铺配送信息
+export const getChainInfo =
+    (data) =>
+      requestApi(
+        '/seller_chain/info',
+        'POST',
+        data,
+        'seller'
+      )
+
+// 新增发票
+export const addChain =
+    (data) =>
+      requestApi(
+        '/seller_chain/add',
+        'POST',
+        data,
+        'seller'
+      )
+// 编辑门店
+export const editChain =
+    (data) =>
+      requestApi(
+        '/seller_chain/edit',
+        'POST',
+        data,
+        'seller'
+      )
+// 删除门店
+export const delChain =
+    (data) =>
+      requestApi(
+        '/seller_chain/del',
+        'POST',
+        data,
+        'seller'
+      )

+ 100 - 0
api/sellerCompliant.js

@@ -0,0 +1,100 @@
+import { requestApi } from '../util/network'
+// 投诉列表
+export const getComplaintList =
+    (params) =>
+      requestApi(
+        '/sellercomplain/index',
+        'POST',
+        {
+          page: params.page,
+          per_page: params.per_page
+        },
+        'seller'
+      )
+export const getComplaintInfo =
+    (complain_id) =>
+      requestApi(
+        '/sellercomplain/complain_show',
+        'POST',
+        {
+          complain_id: complain_id
+        },
+        'seller'
+      )
+// 新增投诉
+export const addComplaint =
+(input_complain_id, content, pic) =>
+  requestApi(
+    '/sellercomplain/appeal_save',
+    'POST',
+    {
+      input_complain_id: input_complain_id,
+      input_appeal_message: content,
+      pic_name: pic
+    },
+    'seller'
+  )
+// 取消投诉
+export const cancelComplaint =
+    (order_id) =>
+      requestApi(
+        '/sellercomplain/complain_cancel',
+        'POST',
+        {
+          complain_id: order_id
+        },
+        'seller'
+      )
+// 更新凭证
+export const uploadComplaintPic =
+    (file) =>
+      requestApi(
+        '/sellercomplain/upload_pic',
+        'POST',
+        file,
+        'seller',
+        true
+      )
+// 获取公共信息
+export const getCommonData =
+    (order_id, goods_id) =>
+      requestApi(
+        '/sellercomplain/get_common_data',
+        'POST',
+        {
+          order_id: order_id,
+          goods_id: goods_id
+        },
+        'seller'
+      )
+export const addComplaintTalk =
+    (complain_id, complain_talk) =>
+      requestApi(
+        '/sellercomplain/publish_complain_talk',
+        'POST',
+        {
+          complain_id: complain_id,
+          complain_talk: complain_talk
+        },
+        'seller'
+      )
+export const getComplaintTalk =
+    (complain_id) =>
+      requestApi(
+        '/sellercomplain/get_complain_talk',
+        'POST',
+        {
+          complain_id: complain_id
+        },
+        'seller'
+      )
+export const handleComplain =
+    (complain_id) =>
+      requestApi(
+        '/sellercomplain/apply_handle',
+        'POST',
+        {
+          input_complain_id: complain_id
+        },
+        'seller'
+      )

+ 36 - 0
api/sellerConsult.js

@@ -0,0 +1,36 @@
+import { requestApi } from '../util/network'
+// 商品咨询列表
+export const getConsultList =
+    (params) =>
+      requestApi(
+        '/sellerconsult/index',
+        'POST',
+        {
+          page: params.page,
+          per_page: params.per_page
+        },
+        'seller'
+      )
+// 删除商品咨询
+export const delConsult =
+    (id) =>
+      requestApi(
+        '/sellerconsult/drop_consult',
+        'POST',
+        {
+          id: id
+        },
+        'seller'
+      )
+// 回复商品咨询
+export const replyConsult =
+    (consult_id, content) =>
+      requestApi(
+        '/sellerconsult/reply_save',
+        'POST',
+        {
+          consult_id: consult_id,
+          content: content
+        },
+        'seller'
+      )

+ 54 - 0
api/sellerDeposit.js

@@ -0,0 +1,54 @@
+import { requestApi } from '../util/network'
+
+// 获取店铺保证金记录
+export const getSellerDepositList =
+    (params) =>
+      requestApi(
+        '/Sellerdeposit/index',
+        'POST',
+        {
+          'page': params.page,
+          'per_page': params.per_page,
+          'client_type': 'wap'
+        },
+        'seller'
+      )
+
+// 获取店铺保证金提现记录
+export const getSellerDepositWithdrawList =
+    (params) =>
+      requestApi(
+        '/Sellerdeposit/withdraw_list',
+        'POST',
+        {
+          'page': params.page,
+          'per_page': params.per_page,
+          'client_type': 'wap'
+        },
+        'seller'
+      )
+
+// 补缴店铺保证金
+export const addSellerDeposit =
+    (amount) =>
+      requestApi(
+        '/Sellerdeposit/recharge_add',
+        'POST',
+        {
+          'pdc_amount': amount,
+          'client_type': 'wap'
+        },
+        'seller'
+      )
+// 取出店铺保证金
+export const reduceSellerDeposit =
+    (amount) =>
+      requestApi(
+        '/Sellerdeposit/withdraw_add',
+        'POST',
+        {
+          'pdc_amount': amount,
+          'client_type': 'wap'
+        },
+        'seller'
+      )

+ 28 - 0
api/sellerEvaluate.js

@@ -0,0 +1,28 @@
+import { requestApi } from '../util/network'
+
+// 获取评价列表
+export const getEvaluateList =
+    (params, goods_name, member_name) =>
+      requestApi(
+        '/Sellerevaluate/evaluate_list',
+        'POST',
+        {
+          'goods_name': goods_name,
+          'member_name': member_name,
+          'page': params.page,
+          'per_page': params.per_page
+        },
+        'seller'
+      )
+// 解释评论
+export const addExplain =
+    (gevalId, gevalExplain) =>
+      requestApi(
+        '/Sellerevaluate/explain_save',
+        'POST',
+        {
+          'geval_id': gevalId,
+          'geval_explain': gevalExplain
+        },
+        'seller'
+      )

+ 24 - 0
api/sellerExpress.js

@@ -0,0 +1,24 @@
+import { requestApi } from '../util/network'
+// 获取物流服务列表
+export const getExpressList =
+(orderId) =>
+  requestApi(
+    '/Sellerdeliverset/express_list',
+    'POST',
+    {
+        'order_id': orderId
+    },
+    'seller'
+  )
+// 获取默认发货信息
+export const getExpressInfo =
+    (orderId) =>
+      requestApi(
+        '/Sellerdeliverset/express_default',
+        'POST',
+        {
+          'order_id': orderId
+        },
+        'seller'
+      )
+

+ 188 - 0
api/sellerGoods.js

@@ -0,0 +1,188 @@
+import { requestApi } from '../util/network'
+
+// 获取卖家商品列表
+export const getGoodsList =
+    (controller, params, keyword, goods_type, search_type) =>
+      requestApi(
+        '/' + controller + '/goods_list',
+        'POST',
+        {
+          'keyword': keyword,
+          'goods_type': goods_type,
+          'search_type': search_type,
+          'page': params.page,
+          'per_page': params.per_page,
+          'client_type': 'wap'
+        },
+        'seller'
+      )
+// 删除商品
+export const dropGoods =
+    (controller, commonid) =>
+      requestApi(
+        '/' + controller + '/drop_goods',
+        'POST',
+        {
+          'commonid': commonid,
+          'client_type': 'wap'
+        },
+        'seller'
+      )
+// 商品上架
+export const goodsShow =
+    (controller, commonid) =>
+      requestApi(
+        '/' + controller + '/goods_show',
+        'POST',
+        {
+          'commonid': commonid,
+          'client_type': 'wap'
+        },
+        'seller'
+      )
+// 商品下架
+export const goodsUnshow =
+    (controller, commonid) =>
+      requestApi(
+        '/' + controller + '/goods_unshow',
+        'POST',
+        {
+          'commonid': commonid,
+          'client_type': 'wap'
+        },
+        'seller'
+      )
+// 商品编辑
+export const goodsEdit =
+    (controller, commonid) =>
+      requestApi(
+        '/' + controller + '/edit_goods',
+        'POST',
+        {
+          'commonid': commonid
+        },
+        'seller'
+      )
+// 保存商品规格
+export const goodsSpecSave =
+    (data) =>
+      requestApi(
+        '/Sellerspec/save_spec',
+        'POST',
+        data,
+        'seller'
+      )
+// 商品规格值
+export const goodsSpecAdd =
+    (controller, name, gc_id, sp_id) =>
+      requestApi(
+        '/' + controller + '/add_spec',
+        'POST',
+        {
+          'name': name,
+          'gc_id': gc_id,
+          'sp_id': sp_id
+        },
+        'seller'
+      )
+export const uploadInfoFile =
+    (controller, file) =>
+      requestApi(
+        '/' + controller + '/image_upload',
+        'POST',
+        file,
+        'seller',
+        true
+      )
+export const uploadVideo =
+    (controller, file) =>
+      requestApi(
+        '/' + controller + '/video_upload',
+        'POST',
+        file,
+        'seller',
+        true
+      )
+export const uploadResource =
+    (file) =>
+        requestApi(
+            '/seller_resource/resource_upload',
+            'POST',
+            file,
+            'seller',
+            true
+        )
+export const delResource =
+    (data) =>
+        requestApi(
+            '/seller_resource/del_resource',
+            'POST',
+            data,
+            'seller'
+        )
+// 商品保存
+export const goodsSave =
+    (controller, class_id, commonid, goods, goods_body, sgcate_id, spec, sp_name, sp_val, attr, g_fccount, g_fcprefix) =>
+      requestApi(
+        '/' + controller + '/save_goods',
+        'POST',
+        {
+          'class_id': class_id,
+          'commonid': commonid,
+          'goods': goods,
+          'goods_body': goods_body,
+          'sgcate_id': sgcate_id,
+          'spec': spec,
+          'sp_name': sp_name,
+          'sp_val': sp_val,
+          'attr': attr,
+          'g_fcprefix': g_fcprefix,
+          'g_fccount': g_fccount
+        },
+        'seller'
+      )
+// 获取店铺商品分类公共数据
+export const getCommonData =
+    (controller, class_id) =>
+      requestApi(
+        '/' + controller + '/get_common_data',
+        'POST',
+        {
+          'class_id': class_id
+        },
+        'seller'
+      )
+// 图片编辑
+export const imageEdit =
+    (controller, commonid) =>
+      requestApi(
+        '/' + controller + '/edit_image',
+        'POST',
+        {
+          'commonid': commonid
+        },
+        'seller'
+      )
+// 图片保存
+export const imageSave =
+    (controller, commonid, img) =>
+      requestApi(
+        '/' + controller + '/save_image',
+        'POST',
+        {
+          'commonid': commonid,
+          'img': img
+        },
+        'seller'
+      )
+// 获取店铺经营分类
+export const getGoodsClass =
+    (controller) =>
+      requestApi(
+        '/' + controller + '/goods_class',
+        'POST',
+        {
+
+        },
+        'seller'
+      )

+ 72 - 0
api/sellerGoodsClass.js

@@ -0,0 +1,72 @@
+import { requestApi } from '../util/network'
+
+// 获取店铺商品分类公共数据
+export const getCommonData =
+    () =>
+      requestApi(
+        '/Sellergoodsclass/get_common_data',
+        'POST',
+        {
+        },
+        'seller'
+      )
+// 获取店铺商品分类列表
+export const getGoodsClassList =
+    () =>
+      requestApi(
+        '/Sellergoodsclass/index',
+        'POST',
+        {
+        },
+        'seller'
+      )
+
+// 获取店铺商品分类信息
+export const getGoodsClassInfo =
+    (top_class_id) =>
+      requestApi(
+        '/Sellergoodsclass/goods_class_edit',
+        'POST',
+        {
+          'top_class_id': top_class_id
+        },
+        'seller'
+      )
+
+// 删除店铺商品分类
+export const delGoodsClass =
+    (class_id) =>
+      requestApi(
+        '/Sellergoodsclass/drop_goods_class',
+        'POST',
+        {
+          'class_id': class_id
+        },
+        'seller'
+      )
+
+// 编辑店铺商品分类
+export const editGoodsClass =
+    (data) =>
+      requestApi(
+        '/Sellergoodsclass/goods_class_save',
+        'POST',
+        {
+          'storegc_id': data.storegc_id,
+          'storegc_name': data.storegc_name,
+          'storegc_parent_id': data.storegc_parent_id,
+          'storegc_state': data.storegc_state,
+          'storegc_sort': data.storegc_sort
+        },
+        'seller'
+      )
+// 获取店铺商品分类
+export const getGoodsClassTree =
+    () =>
+      requestApi(
+        '/Sellergoodsclass/get_tree',
+        'POST',
+        {
+        },
+        'seller'
+      )

+ 55 - 0
api/sellerInstantMessage.js

@@ -0,0 +1,55 @@
+import { requestApi } from '../util/network'
+
+// 发送聊天
+export const addInstantMessage =
+    (data) =>
+      requestApi(
+        '/seller_instant_message/add',
+        'POST',
+        data,
+        'seller'
+      )
+// 加入聊天
+export const joinChat =
+    (client_id) =>
+      requestApi(
+        '/seller_instant_message/join',
+        'POST',
+        {
+          client_id: client_id
+        },
+        'seller'
+      )
+// 已读消息
+export const setMessage =
+    (data) =>
+      requestApi(
+        '/seller_instant_message/set_message',
+        'POST',
+        data,
+        'seller'
+      )
+// 聊天历史
+export const getChatHistory =
+    (params, t_id) =>
+      requestApi(
+        '/seller_instant_message/get_chat_log',
+        'POST',
+        {
+          page: params.page,
+          per_page: params.per_page,
+          t_id: t_id
+        },
+        'seller'
+      )
+// 最近消息
+export const getChatList =
+    () =>
+      requestApi(
+        '/seller_instant_message/get_user_list',
+        'POST',
+        {
+          recent: 1
+        },
+        'seller'
+      )

+ 91 - 0
api/sellerInviter.js

@@ -0,0 +1,91 @@
+import { requestApi } from '../util/network'
+
+// 检索可选取的分销商品
+export const searchGoodsList =
+    (goods_name,params) =>
+      requestApi(
+        '/Sellerinviter/search_goods',
+        'POST',
+        {
+          'goods_name': goods_name,
+          'page': params.page,
+          'per_page': params.per_page,
+          'client_type': 'wap'
+        },
+        'seller'
+      )
+// 获取分销商品列表
+export const getInviterGoodsList =
+    (params) =>
+      requestApi(
+        '/Sellerinviter/goods_list',
+        'POST',
+        {
+          'page': params.page,
+          'per_page': params.per_page,
+        },
+        'seller'
+      )
+// 新增分销商品
+export const addInviterGoods =
+    (data) =>
+      requestApi(
+        '/Sellerinviter/goods_add',
+        'POST',
+        {
+          'inviter_goods_commonid': data.goods_commonid,
+          'inviter_ratio': data.inviter_ratio,
+        },
+        'seller'
+      )
+// 编辑分销商品
+export const editInviterGoods =
+    (data) =>
+      requestApi(
+        '/Sellerinviter/goods_edit',
+        'POST',
+        {
+          'inviter_goods_commonid': data.goods_commonid,
+          'inviter_ratio': data.inviter_ratio,
+          'client_type': 'wap'
+        },
+        'seller'
+      )
+// 获取单个分销商品
+export const getInviterGoodsInfo =
+    (goods_commonid) =>
+      requestApi(
+        '/Sellerinviter/goods_info',
+        'POST',
+        {
+          'goods_commonid': goods_commonid,
+          'client_type': 'wap'
+        },
+        'seller'
+      )
+// 删除分销商品
+export const delInviterGoods =
+    (goods_commonid) =>
+      requestApi(
+        '/Sellerinviter/goods_del',
+        'POST',
+        {
+          'goods_commonid': goods_commonid,
+          'client_type': 'wap'
+        },
+        'seller'
+      )
+
+// 获取店铺分销业绩
+export const getInviterOrderList =
+    (params) =>
+      requestApi(
+        '/Sellerinviter/order_list',
+        'POST',
+        {
+          'page': params.page,
+          'per_page': params.per_page,
+          'client_type': 'wap'
+        },
+        'seller'
+      )

+ 77 - 0
api/sellerLiveApply.js

@@ -0,0 +1,77 @@
+import { requestApi } from '../util/network'
+// 获取视频
+export const getLiveApplyList =
+    (params) =>
+      requestApi(
+        '/seller_live_apply/get_live_apply_list',
+        'POST',
+        {
+          'page': params.page,
+          'per_page': params.per_page
+        },
+        'seller'
+      )
+export const getLiveApplyInfo =
+    (live_apply_id) =>
+      requestApi(
+        '/seller_live_apply/get_live_apply_info',
+        'POST',
+        {
+          live_apply_id: live_apply_id
+        },
+        'seller'
+      )
+// 视频保存
+export const saveLiveApply =
+    (live) =>
+      requestApi(
+        '/seller_live_apply/save_live_apply',
+        'POST',
+        live,
+        'seller'
+      )
+export const joinLiveApply =
+    (data) =>
+      requestApi(
+        '/seller_live_apply/join_live',
+        'POST',
+        data,
+        'seller'
+      )
+export const leaveLiveApply =
+    (data) =>
+      requestApi(
+        '/seller_live_apply/leave_live',
+        'POST',
+        data,
+        'seller'
+      )
+export const changeLiveApply =
+    (data) =>
+      requestApi(
+        '/seller_live_apply/change_live',
+        'POST',
+        data,
+        'seller'
+      )
+// 删除视频
+export const delLiveApply =
+    (live_apply_id) =>
+      requestApi(
+        '/seller_live_apply/del_live_apply',
+        'POST',
+        {
+          live_apply_id: live_apply_id
+        },
+        'seller'
+      )
+// 上传封面
+export const uploadInfoFile =
+    (file) =>
+      requestApi(
+        '/seller_live_apply/image_upload',
+        'POST',
+        file,
+        'seller',
+        true
+      )

+ 16 - 0
api/sellerLogin.js

@@ -0,0 +1,16 @@
+import { requestApi } from '../util/network'
+
+/**
+ * 卖家登录
+ */
+export const sellerlogin =
+    (sellerName, password) =>
+      requestApi(
+        '/Sellerlogin/index',
+        'POST',
+        {
+          'seller_name': sellerName,
+          'password': password,
+          'client_type': 'wap'
+        }
+      )

+ 69 - 0
api/sellerMiniproLive.js

@@ -0,0 +1,69 @@
+import { requestApi } from '../util/network'
+// 获取视频
+export const getRoomList =
+    (params) =>
+      requestApi(
+        '/seller_minipro_live/get_room_list',
+        'POST',
+        {
+          'page': params.page,
+          'per_page': params.per_page
+        },
+        'seller'
+      )
+// 获取视频
+export const getRoomInfo =
+    (data) =>
+      requestApi(
+        '/seller_minipro_live/get_room_info',
+        'POST',
+        data,
+        'seller'
+      )
+export const addRoom =
+    (data) =>
+      requestApi(
+        '/seller_minipro_live/add_room',
+        'POST',
+        data,
+        'seller'
+      )
+// 视频保存
+export const importRoomGoods =
+    (data) =>
+      requestApi(
+        '/seller_minipro_live/import_room_goods',
+        'POST',
+        data,
+        'seller'
+      )
+// 删除视频
+export const getGoodsList =
+    (params) =>
+      requestApi(
+        '/seller_minipro_live/get_goods_list',
+        'POST',
+        {
+          'page': params.page,
+          'per_page': params.per_page
+        },
+        'seller'
+      )
+export const addGoods =
+    (data) =>
+      requestApi(
+        '/seller_minipro_live/add_goods',
+        'POST',
+        data,
+        'seller'
+      )
+// 上传封面
+export const uploadMedia =
+    (file) =>
+      requestApi(
+        '/seller_minipro_live/upload_media',
+        'POST',
+        file,
+        'seller',
+        true
+      )

+ 42 - 0
api/sellerMoney.js

@@ -0,0 +1,42 @@
+import { requestApi } from '../util/network'
+
+// 获取店铺资金记录
+export const getSellerMoneyLogList =
+    (params) =>
+      requestApi(
+        '/Sellermoney/index',
+        'POST',
+        {
+          'page': params.page,
+          'per_page': params.per_page,
+          'client_type': 'wap'
+        },
+        'seller'
+      )
+
+// 获取店铺提现记录
+export const getSellerMoneyWithdrawList =
+    (params) =>
+      requestApi(
+        '/Sellermoney/withdraw_list',
+        'POST',
+        {
+          'page': params.page,
+          'per_page': params.per_page,
+          'client_type': 'wap'
+        },
+        'seller'
+      )
+
+// 店铺申请提现
+export const addSellerMoneyWithdraw =
+    (amount) =>
+      requestApi(
+        '/Sellermoney/withdraw_add',
+        'POST',
+        {
+          'pdc_amount': amount,
+          'client_type': 'wap'
+        },
+        'seller'
+      )

+ 14 - 0
api/sellerNotice.js

@@ -0,0 +1,14 @@
+import { requestApi } from '../util/network'
+
+// 获取店铺通知列表
+export const getNoticeList =
+(params) =>
+  requestApi(
+    '/sellermsg/get_list',
+    'POST',
+    {
+      page: params.page,
+        per_page: params.per_page,
+    },
+    'seller'
+  )

+ 89 - 0
api/sellerOrder.js

@@ -0,0 +1,89 @@
+import { requestApi } from '../util/network'
+
+// 获取订单列表
+export const getOrderList =
+    (params, order_sn, state_type) =>
+      requestApi(
+        '/Sellerorder/order_list',
+        'POST',
+        {
+          'order_sn': order_sn,
+          'state_type': state_type,
+          'page': params.page,
+          'per_page': params.per_page
+        },
+        'seller'
+      )
+// 获取订单信息
+export const getOrderInfo =
+    (orderId) =>
+      requestApi(
+        '/Sellerorder/order_info',
+        'POST',
+        {
+          'order_id': orderId
+        },
+        'seller'
+      )
+
+// 取消订单
+export const cancelOrder =
+    (orderId, reason) =>
+      requestApi(
+        '/Sellerorder/order_cancel',
+        'POST',
+        {
+          'order_id': orderId,
+          'reason': reason
+        },
+        'seller'
+      )
+// 订单发货
+export const sendOrder =
+    (orderId, shippingExpressId, shippingCode, daddressId) =>
+      requestApi(
+        '/Sellerorder/order_deliver_send',
+        'POST',
+        {
+          'order_id': orderId,
+          'shipping_express_id': shippingExpressId,
+          'shipping_code': shippingCode,
+          'daddress_id': daddressId
+        },
+        'seller'
+      )
+// 修改商品价格
+export const editGoodsPrice =
+    (orderId, price) =>
+      requestApi(
+        '/Sellerorder/order_spay_price',
+        'POST',
+        {
+          'order_id': orderId,
+          'order_fee': price
+        },
+        'seller'
+      )
+// 修改运费
+export const editShippingFee =
+    (orderId, price) =>
+      requestApi(
+        '/Sellerorder/order_ship_price',
+        'POST',
+        {
+          'order_id': orderId,
+          'shipping_fee': price
+        },
+        'seller'
+      )
+// 物流跟踪
+export const getOrderDeliver =
+    (orderId) =>
+      requestApi(
+        '/Sellerorder/search_deliver',
+        'POST',
+        {
+          'order_id': orderId
+        },
+        'seller'
+      )

+ 63 - 0
api/sellerRefund.js

@@ -0,0 +1,63 @@
+import { requestApi } from '../util/network'
+
+// 获取退款列表
+export const getRefundList =
+(params, refundType) =>
+  requestApi(
+    '/Sellerrefund/refund_list',
+    'POST',
+    {
+      page: params.page,
+      per_page: params.per_page,
+      refund_type: refundType
+    },
+    'seller'
+  )
+// 获取单个退款信息
+export const getRefundInfo =
+(refundId) =>
+  requestApi(
+    '/Sellerrefund/get_refund_info',
+    'POST',
+    {
+      refund_id: refundId
+    },
+    'seller'
+  )
+// 编辑退款
+export const editRefund =
+(refundId, returnType, sellerMessage, fsellerState) =>
+  requestApi(
+    '/Sellerrefund/edit',
+    'POST',
+    {
+      refund_id: refundId,
+      return_type: returnType,
+      seller_message: sellerMessage,
+      seller_state: fsellerState
+    },
+    'seller'
+  )
+// 收货
+export const receiveRefund =
+    (refundId, returnType) =>
+      requestApi(
+        '/Sellerrefund/receive',
+        'POST',
+        {
+          return_id: refundId,
+          return_type: returnType
+        },
+        'seller'
+      )
+// 物流跟踪
+export const getRefundDeliver =
+    (refundId) =>
+      requestApi(
+        '/Sellerrefund/search_deliver',
+        'POST',
+        {
+          'refund_id': refundId
+        },
+        'seller'
+      )

+ 36 - 0
api/sellerSetting.js

@@ -0,0 +1,36 @@
+import { requestApi } from '../util/network'
+// 获取店铺信息
+export const getStoreInfo =
+    () =>
+      requestApi(
+        '/Sellersetting/store_info',
+        'POST',
+        {
+        },
+        'seller'
+      )
+export const editStoreInfo =
+    (storeQq, storeWw, storePhone, storeMainbusiness, seoKeywords, seoDescription,storeAvatar) =>
+      requestApi(
+        '/Sellersetting/store_edit',
+        'POST',
+        {
+          'store_qq': storeQq,
+          'store_ww': storeWw,
+          'store_phone': storePhone,
+          'store_mainbusiness': storeMainbusiness,
+          'seo_keywords': seoKeywords,
+          'seo_description': seoDescription,
+          'store_avatar':storeAvatar
+        },
+        'seller'
+      )
+export const uploadStoreImage =
+    (file) =>
+      requestApi(
+        '/Sellersetting/store_image_upload',
+        'POST',
+        file,
+        'seller',
+        true
+      )

+ 15 - 0
api/sellerStatistics.js

@@ -0,0 +1,15 @@
+import { requestApi } from '../util/network'
+
+/**
+ * 获取卖家商品列表
+ */
+export const getStatisticsGeneral =
+    () =>
+      requestApi(
+        '/Statisticsgeneral/index',
+        'POST',
+        {
+          'client_type': 'wap'
+        },
+        'seller'
+      )

+ 44 - 0
api/sellerTransport.js

@@ -0,0 +1,44 @@
+import { requestApi } from '../util/network'
+// 获取售卖地区
+export const getTransportList =
+    () =>
+      requestApi(
+        '/Sellertransport/transport_list',
+        'POST',
+        {
+        },
+        'seller'
+      )
+// 售卖地区编辑
+export const editTransport =
+    (transport_id) =>
+      requestApi(
+        '/Sellertransport/edit_transport',
+        'POST',
+        {
+          transport_id: transport_id
+        },
+        'seller'
+      )
+// 售卖地区保存
+export const saveTransport =
+    (transport, transport_extend) =>
+      requestApi(
+        '/Sellertransport/save_transport',
+        'POST',
+        Object.assign(
+          transport,
+          { transport_extend: transport_extend }),
+        'seller'
+      )
+// 删除售卖地区
+export const delTransport =
+    (transport_id) =>
+      requestApi(
+        '/Sellertransport/del_transport',
+        'POST',
+        {
+          transport_id: transport_id
+        },
+        'seller'
+      )

+ 84 - 0
api/sellerVoucher.js

@@ -0,0 +1,84 @@
+import { requestApi } from '../util/network'
+
+// 获取代金券列表
+export const getVoucherList =
+(params) =>
+  requestApi(
+    '/Sellervoucher/templatelist',
+    'POST',
+    {
+      page: params.page,
+      per_page: params.per_page
+    },
+    'seller'
+  )
+// 获取代金券
+export const getVoucherInfo =
+    (tid) =>
+      requestApi(
+        '/Sellervoucher/templateinfo',
+        'POST',
+        {
+          tid: tid
+        },
+        'seller'
+      )
+// 续期套餐
+export const addQuota =
+    (quota_quantity) =>
+      requestApi(
+        '/Sellervoucher/quotaadd',
+        'POST',
+        {
+          'quota_quantity': quota_quantity
+        },
+        'seller'
+      )
+// 获取公共数据
+export const getCommonData =
+    () =>
+      requestApi(
+        '/Sellervoucher/get_common_data',
+        'POST',
+        {
+        },
+        'seller'
+      )
+// 新增代金券
+export const addVoucher =
+    (txt_template_title, txt_template_total, select_template_price, txt_template_limit, txt_template_describe, txt_template_enddate, storeclass_id, eachlimit) =>
+      requestApi(
+        '/Sellervoucher/templateadd',
+        'POST',
+        {
+          txt_template_title: txt_template_title,
+          txt_template_total: txt_template_total,
+          select_template_price: select_template_price,
+          txt_template_limit: txt_template_limit,
+          txt_template_describe: txt_template_describe,
+          txt_template_enddate: txt_template_enddate,
+          storeclass_id: storeclass_id,
+          eachlimit: eachlimit
+        },
+        'seller'
+      )
+// 编辑代金券
+export const editVoucher =
+    (tid, txt_template_title, txt_template_total, select_template_price, txt_template_limit, txt_template_describe, txt_template_enddate, storeclass_id, eachlimit, tstate) =>
+      requestApi(
+        '/Sellervoucher/templateedit',
+        'POST',
+        {
+          tid: tid,
+          txt_template_title: txt_template_title,
+          txt_template_total: txt_template_total,
+          select_template_price: select_template_price,
+          txt_template_limit: txt_template_limit,
+          txt_template_describe: txt_template_describe,
+          txt_template_enddate: txt_template_enddate,
+          storeclass_id: storeclass_id,
+          eachlimit: eachlimit,
+          tstate: tstate
+        },
+        'seller'
+      )

+ 50 - 0
api/sellerVrOrder.js

@@ -0,0 +1,50 @@
+import { requestApi } from '../util/network'
+
+// 获取虚拟订单列表
+export const getOrderList =
+    (params, order_sn, state_type) =>
+      requestApi(
+        '/Sellervrorder/order_list',
+        'POST',
+        {
+          'order_sn': order_sn,
+          'state_type': state_type,
+          'page': params.page,
+          'per_page': params.per_page
+        },
+        'seller'
+      )
+// 获取订单信息
+export const getOrderInfo =
+    (orderId) =>
+      requestApi(
+        '/Sellervrorder/order_info',
+        'POST',
+        {
+          'order_id': orderId
+        },
+        'seller'
+      )
+// 取消订单
+export const cancelOrder =
+    (orderId, reason) =>
+      requestApi(
+        '/Sellervrorder/order_cancel',
+        'POST',
+        {
+          'order_id': orderId,
+          'reason': reason
+        },
+        'seller'
+      )
+// 核销兑换码
+export const exchangeCode =
+    (vr_code) =>
+      requestApi(
+        '/Sellervrorder/exchange',
+        'POST',
+        {
+          'vr_code': vr_code
+        },
+        'seller'
+      )

+ 699 - 0
components/thorui/tui-picture-cropper/tui-picture-cropper.vue

@@ -0,0 +1,699 @@
+<template>
+	<view class="tui-container" @touchmove.stop.prevent="stop">
+		<view
+			class="tui-image-cropper"
+			:change:prop="parse.propsChange"
+			:prop="props"
+			:data-lockRatio="lockRatio"
+			:data-lockWidth="lockWidth"
+			:data-lockHeight="lockHeight"
+			:data-maxWidth="maxWidth"
+			:data-minWidth="minWidth"
+			:data-maxHeight="maxHeight"
+			:data-minHeight="minHeight"
+			:data-width="width"
+			:data-height="height"
+			:data-limitMove="limitMove"
+			:data-windowHeight="sysInfo.windowHeight || 600"
+			:data-windowWidth="sysInfo.windowWidth || 400"
+			:data-imgTop="imgTop"
+			:data-imgLeft="imgLeft"
+			:data-imgWidth="imgWidth"
+			:data-imgHeight="imgHeight"
+			:data-angle="angle"
+			@touchend="parse.cutTouchEnd"
+			@touchstart="parse.cutTouchStart"
+			@touchmove="parse.cutTouchMove"
+		>
+			<view class="tui-content">
+				<view class="tui-content-top tui-bg-transparent" :style="{ transitionProperty: cutAnimation ? '' : 'background' }"></view>
+				<view class="tui-content-middle">
+					<view class="tui-bg-transparent tui-wxs-bg" :style="{ transitionProperty: cutAnimation ? '' : 'background' }"></view>
+					<view class="tui-cropper-box" :style="{ borderColor: borderColor, transitionProperty: cutAnimation ? '' : 'background' }">
+						<view
+							v-for="(item, index) in 4"
+							:key="index"
+							class="tui-edge"
+							:class="[`tui-${index < 2 ? 'top' : 'bottom'}-${index === 0 || index === 2 ? 'left' : 'right'}`]"
+							:style="{
+								width: edgeWidth,
+								height: edgeWidth,
+								borderColor: edgeColor,
+								borderWidth: edgeBorderWidth,
+								left: index === 0 || index === 2 ? `-${edgeOffsets}` : 'auto',
+								right: index === 1 || index === 3 ? `-${edgeOffsets}` : 'auto',
+								top: index < 2 ? `-${edgeOffsets}` : 'auto',
+								bottom: index > 1 ? `-${edgeOffsets}` : 'auto'
+							}"
+						></view>
+					</view>
+					<view class="tui-flex-auto tui-bg-transparent" :style="{ transitionProperty: cutAnimation ? '' : 'background' }"></view>
+				</view>
+				<view class="tui-flex-auto tui-bg-transparent" :style="{ transitionProperty: cutAnimation ? '' : 'background' }"></view>
+			</view>
+			<image
+				@load="imageLoad"
+				@error="imageLoad"
+				@touchstart="parse.touchstart"
+				@touchmove="parse.touchmove"
+				@touchend="parse.touchend"
+				:data-minScale="minScale"
+				:data-maxScale="maxScale"
+				:data-disableRotate="disableRotate"
+				:style="{
+					width: imgWidth ? imgWidth + 'px' : 'auto',
+					height: imgHeight ? imgHeight + 'px' : 'auto',
+					transitionDuration: (cutAnimation ? 0.3 : 0) + 's'
+				}"
+				class="tui-cropper-image"
+				:src="imageUrl"
+				v-if="imageUrl"
+				mode="widthFix"
+			></image>
+		</view>
+		<canvas
+			canvas-id="tui-image-cropper"
+			id="tui-image-cropper"
+			:disable-scroll="true"
+			:style="{ width: CROPPER_WIDTH * scaleRatio + 'px', height: CROPPER_HEIGHT * scaleRatio + 'px' }"
+			class="tui-cropper-canvas"
+		></canvas>
+		<view class="tui-cropper-tabbar" v-if="!custom">
+			<view class="tui-op-btn" @tap.stop="back">取消</view>
+			<image :src="rotateImg" class="tui-rotate-img" @tap="setAngle"></image>
+			<view class="tui-op-btn" @tap.stop="getImage">完成</view>
+		</view>
+	</view>
+</template>
+<script src="./tui-picture-cropper.wxs" module="parse" lang="wxs"></script>
+<script>
+/**
+ * 注意:组件中使用的图片地址,将文件复制到自己项目中
+ * 如果图片位置与组件同级,编译成小程序时图片会丢失
+ * 拷贝static下整个components文件夹
+ *也可直接转成base64(不建议)
+ * */
+export default {
+	name: 'tuiPictureCropper',
+	props: {
+		//图片路径
+		imageUrl: {
+			type: String,
+			default: ''
+		},
+		/*
+		 默认正方形,可修改大小控制比例
+		 裁剪框高度 px
+		*/
+		height: {
+			type: Number,
+			default: 280
+		},
+		//裁剪框宽度 px
+		width: {
+			type: Number,
+			default: 280
+		},
+		//裁剪框最小宽度 px
+		minWidth: {
+			type: Number,
+			default: 100
+		},
+		//裁剪框最小高度 px
+		minHeight: {
+			type: Number,
+			default: 100
+		},
+		//裁剪框最大宽度 px
+		maxWidth: {
+			type: Number,
+			default: 360
+		},
+		//裁剪框最大高度 px
+		maxHeight: {
+			type: Number,
+			default: 360
+		},
+		//裁剪框border颜色
+		borderColor: {
+			type: String,
+			default: 'rgba(255,255,255,0.1)'
+		},
+		//裁剪框边缘线颜色
+		edgeColor: {
+			type: String,
+			default: '#FFFFFF'
+		},
+		//裁剪框边缘线宽度 w=h
+		edgeWidth: {
+			type: String,
+			default: '34rpx'
+		},
+		//裁剪框边缘线border宽度
+		edgeBorderWidth: {
+			type: String,
+			default: '6rpx'
+		},
+		//偏移距离,根据edgeBorderWidth进行调整
+		edgeOffsets: {
+			type: String,
+			default: '6rpx'
+		},
+		/**
+		 * 如果宽度和高度都为true则裁剪框禁止拖动
+		 * 裁剪框宽度锁定
+		 */
+		lockWidth: {
+			type: Boolean,
+			default: false
+		},
+		//裁剪框高度锁定
+		lockHeight: {
+			type: Boolean,
+			default: false
+		},
+		//锁定裁剪框比例(放大或缩小)
+		lockRatio: {
+			type: Boolean,
+			default: false
+		},
+		//生成的图片尺寸相对剪裁框的比例
+		scaleRatio: {
+			type: Number,
+			default: 2
+		},
+		//图片的质量,取值范围为 (0, 1],不在范围内时当作1.0处理
+		quality: {
+			type: Number,
+			default: 0.8
+		},
+		//图片旋转角度
+		rotateAngle: {
+			type: Number,
+			default: 0
+		},
+		//图片最小缩放比
+		minScale: {
+			type: Number,
+			default: 0.5
+		},
+		//图片最大缩放比
+		maxScale: {
+			type: Number,
+			default: 2
+		},
+		//是否禁用触摸旋转(为false则可以触摸转动图片,limitMove为false生效)
+		disableRotate: {
+			type: Boolean,
+			default: true
+		},
+		//是否限制移动范围(剪裁框只能在图片内,为true不可触摸转动图片)
+		limitMove: {
+			type: Boolean,
+			default: true
+		},
+		//自定义操作栏(为true时隐藏底部操作栏)
+		custom: {
+			type: Boolean,
+			default: false
+		},
+		//值发生改变开始裁剪(custom为true时生效)
+		startCutting: {
+			type: [Number, Boolean],
+			default: 0
+		},
+		/**
+		 * 是否返回base64(H5端默认base64)
+		 * 支持平台:App,微信小程序,支付宝小程序,H5(默认url就是base64)
+		 **/
+		isBase64: {
+			type: Boolean,
+			default: false
+		},
+		//裁剪时是否显示loadding
+		loadding: {
+			type: Boolean,
+			default: true
+		},
+		//旋转icon
+		rotateImg: {
+			type: String,
+			default: '/static/components/cropper/img_rotate.png'
+		}
+	},
+	data() {
+		return {
+			TIME_CUT_CENTER: null,
+			CROPPER_WIDTH: 200, //裁剪框宽
+			CROPPER_HEIGHT: 200, //裁剪框高
+			cutX: 0, //画布x轴起点
+			cutY: 0, //画布y轴起点0
+			canvasWidth: 0,
+			canvasHeight: 0,
+			imgWidth: 0, //图片宽度
+			imgHeight: 0, //图片高度
+			scale: 1, //图片缩放比
+			angle: 0, //图片旋转角度
+			cutAnimation: false, //是否开启图片和裁剪框过渡
+			cutAnimationTime: null,
+			imgTop: 0, //图片上边距
+			imgLeft: 0, //图片左边距
+			ctx: null,
+			sysInfo: {},
+			props: '',
+			sizeChange: 0, //2
+			angleChange: 0, //3
+			resetChange: 0, //4
+			centerChange: 0 //5
+		};
+	},
+	watch: {
+		//定义变量然后利用change触发
+		imageUrl(val, oldVal) {
+			this.imageReset();
+			this.showLoading();
+			uni.getImageInfo({
+				src: val,
+				success: res => {
+					//计算图片尺寸
+					this.imgComputeSize(res.width, res.height);
+					if (this.limitMove) {
+						this.angleChange++;
+						this.props = `3,${this.angleChange}`;
+					}
+				},
+				fail: err => {
+					this.imgComputeSize();
+					if (this.limitMove) {
+						this.angleChange++;
+						this.props = `3,${this.angleChange}`;
+					}
+				}
+			});
+		},
+		rotateAngle(val) {
+			this.cutAnimation = true;
+			this.angle = val;
+			this.angleChanged(val);
+		},
+		cutAnimation(val) {
+			//开启过渡260毫秒之后自动关闭
+			clearTimeout(this.cutAnimationTime);
+			if (val) {
+				this.cutAnimationTime = setTimeout(() => {
+					this.cutAnimation = false;
+				}, 260);
+			}
+		},
+		limitMove(val) {
+			if (val) {
+				this.angleChanged(this.angle);
+			}
+		},
+		startCutting(val) {
+			if (this.custom && val) {
+				this.getImage();
+			}
+		}
+	},
+	mounted() {
+		this.sysInfo = uni.getSystemInfoSync();
+		this.imgTop = this.sysInfo.windowHeight / 2;
+		this.imgLeft = this.sysInfo.windowWidth / 2;
+		this.CROPPER_WIDTH = this.width;
+		this.CROPPER_HEIGHT = this.height;
+		this.canvasHeight = this.height;
+		this.canvasWidth = this.width;
+		this.ctx = uni.createCanvasContext('tui-image-cropper', this);
+		//初始化
+		setTimeout(() => {
+			this.props = '1,1';
+		}, 0);
+		setTimeout(() => {
+			this.$emit('ready', {});
+		}, 200);
+	},
+	methods: {
+		//网络图片转成本地文件[同步执行]
+		async getLocalImage(url) {
+			return await new Promise((resolve, reject) => {
+				uni.downloadFile({
+					url: url,
+					success: res => {
+						resolve(res.tempFilePath);
+					},
+					fail: res => {
+						reject(false)
+					}
+				})
+			})
+		},
+		//返回裁剪后图片信息
+		getImage() {
+			if (!this.imageUrl) {
+				uni.showToast({
+					title: '请选择图片',
+					icon: 'none'
+				});
+				return;
+			}
+			this.loadding && this.showLoading();
+			let draw =async () => {
+				//图片实际大小
+				let imgWidth = this.imgWidth * this.scale * this.scaleRatio;
+				let imgHeight = this.imgHeight * this.scale * this.scaleRatio;
+				//canvas和图片的相对距离
+				let xpos = this.imgLeft - this.cutX;
+				let ypos = this.imgTop - this.cutY;
+				//旋转画布
+				this.ctx.translate(xpos * this.scaleRatio, ypos * this.scaleRatio);
+				this.ctx.rotate((this.angle * Math.PI) / 180);
+				let imgUrl = this.imageUrl;
+				// #ifdef APP-PLUS || MP-WEIXIN
+				if (~this.imageUrl.indexOf('https:')) {
+					imgUrl = await this.getLocalImage(this.imageUrl)
+				}
+				// #endif
+				this.ctx.drawImage(imgUrl, -imgWidth / 2, -imgHeight / 2, imgWidth, imgHeight);
+				this.ctx.draw(false, () => {
+					let params = {
+						width: this.canvasWidth * this.scaleRatio,
+						height: Math.round(this.canvasHeight * this.scaleRatio),
+						destWidth: this.canvasWidth * this.scaleRatio,
+						destHeight: Math.round(this.canvasHeight) * this.scaleRatio,
+						fileType: 'png',
+						quality: this.quality
+					};
+					let data = {
+						url: '',
+						base64: '',
+						width: this.canvasWidth * this.scaleRatio,
+						height: this.canvasHeight * this.scaleRatio
+					};
+					// #ifdef MP-ALIPAY
+
+					if (this.isBase64) {
+						this.ctx.toDataURL(params).then(dataURL => {
+							data.base64 = dataURL;
+							this.loadding && uni.hideLoading();
+							this.$emit('cropper', data);
+						});
+					} else {
+						this.ctx.toTempFilePath({
+							...params,
+							success: res => {
+								data.url = res.tempFilePath;
+								this.loadding && uni.hideLoading();
+								this.$emit('cropper', data);
+							}
+						});
+					}
+					// #endif
+
+					// #ifndef MP-ALIPAY
+					// #ifdef MP-BAIDU || MP-TOUTIAO || H5
+					this.isBase64 = false;
+					// #endif
+					if (this.isBase64) {
+						uni.canvasGetImageData({
+							canvasId: 'tui-image-cropper',
+							x: 0,
+							y: 0,
+							width: this.canvasWidth * this.scaleRatio,
+							height: Math.round(this.canvasHeight * this.scaleRatio),
+							success: res => {
+								const arrayBuffer = new Uint8Array(res.data);
+								const base64 = uni.arrayBufferToBase64(arrayBuffer);
+								data.base64 = base64;
+								this.loadding && uni.hideLoading();
+								this.$emit('cropper', data);
+							}
+						},this);
+					} else {
+						uni.canvasToTempFilePath(
+							{
+								...params,
+								canvasId: 'tui-image-cropper',
+								success: res => {
+									data.url = res.tempFilePath;
+									// #ifdef H5
+									data.base64 = res.tempFilePath;
+									// #endif
+									this.loadding && uni.hideLoading();
+									this.$emit('cropper', data);
+								},
+								fail(res) {
+									console.log(res);
+								}
+							},
+							this
+						);
+					}
+					// #endif
+				});
+			};
+			if (this.CROPPER_WIDTH != this.canvasWidth || this.CROPPER_HEIGHT != this.canvasHeight) {
+				this.CROPPER_WIDTH = this.canvasWidth;
+				this.CROPPER_HEIGHT = this.canvasHeight;
+				this.$nextTick(() => {
+					this.ctx.draw();
+					setTimeout(() => {
+						draw();
+					}, 100);
+				});
+			} else {
+				draw();
+			}
+		},
+		change(e) {
+			this.cutX = e.cutX || 0;
+			this.cutY = e.cutY || 0;
+			this.canvasWidth = e.canvasWidth || this.width;
+			this.canvasHeight = e.canvasHeight || this.height;
+			this.imgWidth = e.imgWidth || this.imgWidth;
+			this.imgHeight = e.imgHeight || this.imgHeight;
+			this.scale = e.scale || 1;
+			this.angle = e.angle || 0;
+			this.imgTop = e.imgTop || 0;
+			this.imgLeft = e.imgLeft || 0;
+		},
+		imageReset() {
+			this.scale = 1;
+			this.angle = 0;
+			let sys = this.sysInfo.windowHeight ? this.sysInfo : uni.getSystemInfoSync();
+			this.imgTop = sys.windowHeight / 2;
+			this.imgLeft = sys.windowWidth / 2;
+			this.resetChange++;
+			this.props = `4,${this.resetChange}`;
+			//初始化旋转角度 0deg
+			this.$emit('initAngle', {});
+		},
+		imageLoad(e) {
+			this.imageReset();
+			uni.hideLoading();
+			this.$emit('imageLoad', {});
+		},
+
+		imgComputeSize(width, height) {
+			//默认按图片最小边 = 对应裁剪框尺寸
+			let imgWidth = width,
+				imgHeight = height;
+			if (imgWidth && imgHeight) {
+				if (imgWidth / imgHeight > this.width / this.height) {
+					imgHeight = this.height;
+					imgWidth = (width / height) * imgHeight;
+				} else {
+					imgWidth = this.width;
+					imgHeight = (height / width) * imgWidth;
+				}
+			} else {
+				let sys = this.sysInfo.windowHeight ? this.sysInfo : uni.getSystemInfoSync();
+				imgWidth = sys.windowWidth;
+				imgHeight = 0;
+			}
+			this.imgWidth = imgWidth;
+			this.imgHeight = imgHeight;
+			this.sizeChange++;
+			this.props = `2,${this.sizeChange}`;
+		},
+		moveStop() {
+			clearTimeout(this.TIME_CUT_CENTER);
+			this.TIME_CUT_CENTER = setTimeout(() => {
+				if (!this.cutAnimation) {
+					this.cutAnimation = true;
+				}
+				this.centerChange++;
+				this.props = `5,${this.centerChange}`;
+			}, 666);
+		},
+		moveDuring() {
+			clearTimeout(this.TIME_CUT_CENTER);
+		},
+		showLoading() {
+			uni.showLoading({
+				title: '请稍候...',
+				mask: true
+			});
+		},
+		stop() {},
+		back() {
+			this.$emit('back')
+		},
+		angleChanged(val) {
+			this.moveStop();
+			if (this.limitMove && val % 90) {
+				this.angle = Math.round(val / 90) * 90;
+			}
+			this.angleChange++;
+			this.props = `3,${this.angleChange}`;
+		},
+		setAngle() {
+			this.cutAnimation = true;
+			this.angle = this.angle + 90;
+			this.angleChanged(this.angle);
+		}
+	}
+};
+</script>
+
+<style scoped>
+.tui-container {
+	width: 100vw;
+	height: 100vh;
+	background-color: rgba(0, 0, 0, 0.6);
+	position: fixed;
+	top: 0;
+	left: 0;
+	z-index: 1;
+}
+
+.tui-image-cropper {
+	width: 100vw;
+	height: 100vh;
+	position: absolute;
+}
+
+.tui-content {
+	width: 100vw;
+	height: 100vh;
+	position: absolute;
+	z-index: 9;
+	display: flex;
+	flex-direction: column;
+	pointer-events: none;
+}
+
+.tui-bg-transparent {
+	background-color: rgba(0, 0, 0, 0.6);
+	transition-duration: 0.3s;
+}
+
+.tui-content-top {
+	pointer-events: none;
+}
+
+.tui-content-middle {
+	width: 100%;
+	height: 200px;
+	display: flex;
+	box-sizing: border-box;
+}
+
+.tui-cropper-box {
+	position: relative;
+	/* transition-duration: 0.2s; */
+	border-style: solid;
+	border-width: 1rpx;
+	box-sizing: border-box;
+}
+
+.tui-flex-auto {
+	flex: auto;
+}
+
+.tui-cropper-image {
+	width: 100%;
+	border-style: none;
+	position: absolute;
+	top: 0;
+	left: 0;
+	z-index: 2;
+	-webkit-backface-visibility: hidden;
+	backface-visibility: hidden;
+	transform-origin: center;
+}
+
+.tui-cropper-canvas {
+	position: fixed;
+	z-index: 10;
+	left: -2000px;
+	top: -2000px;
+	pointer-events: none;
+}
+
+.tui-edge {
+	border-style: solid;
+	pointer-events: auto;
+	position: absolute;
+	box-sizing: border-box;
+}
+
+.tui-top-left {
+	border-bottom-width: 0 !important;
+	border-right-width: 0 !important;
+}
+
+.tui-top-right {
+	border-bottom-width: 0 !important;
+	border-left-width: 0 !important;
+}
+
+.tui-bottom-left {
+	border-top-width: 0 !important;
+	border-right-width: 0 !important;
+}
+
+.tui-bottom-right {
+	border-top-width: 0 !important;
+	border-left-width: 0 !important;
+}
+
+.tui-cropper-tabbar {
+	width: 100%;
+	height: 120rpx;
+	padding: 0 40rpx;
+	box-sizing: border-box;
+	position: fixed;
+	left: 0;
+	bottom: 0;
+	z-index: 99;
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+	color: #ffffff;
+	font-size: 32rpx;
+}
+
+.tui-cropper-tabbar::after {
+	content: ' ';
+	position: absolute;
+	top: 0;
+	right: 0;
+	left: 0;
+	border-top: 1rpx solid rgba(255, 255, 255, 0.2);
+	-webkit-transform: scaleY(0.5) translateZ(0);
+	transform: scaleY(0.5) translateZ(0);
+	transform-origin: 0 100%;
+}
+
+.tui-op-btn {
+	height: 80rpx;
+	display: flex;
+	align-items: center;
+}
+
+.tui-rotate-img {
+	width: 44rpx;
+	height: 44rpx;
+}
+</style>

+ 560 - 0
components/thorui/tui-picture-cropper/tui-picture-cropper.wxs

@@ -0,0 +1,560 @@
+var cropper = {
+	CUT_START: null,
+	cutX: 0, //画布x轴起点
+	cutY: 0, //画布y轴起点0
+	touchRelative: [{
+		x: 0,
+		y: 0
+	}], //手指或鼠标和图片中心的相对位置
+	flagCutTouch: false, //是否是拖动裁剪框
+	hypotenuseLength: 0, //双指触摸时斜边长度
+	flagEndTouch: false, //是否结束触摸
+	canvasWidth: 0,
+	canvasHeight: 0,
+	imgWidth: 0, //图片宽度
+	imgHeight: 0, //图片高度
+	scale: 1, //图片缩放比
+	angle: 0, //图片旋转角度
+	imgTop: 0, //图片上边距
+	imgLeft: 0, //图片左边距
+	//是否限制移动范围(剪裁框只能在图片内,为true不可触摸转动图片)
+	limitMove: true,
+	minHeight: 0,
+	maxHeight: 0,
+	minWidth: 0,
+	maxWidth: 0,
+	windowHeight: 0,
+	windowWidth: 0,
+	init: true
+}
+
+function bool(str) {
+	return str === 'true' || str == true ? true : false
+}
+
+function touchstart(e, ins) {
+	//var instance = e.instance;
+	// var state = instance.getState();
+	var touch = e.touches || e.changedTouches;
+	cropper.flagEndTouch = false;
+	if (touch.length == 1) {
+		cropper.touchRelative[0] = {
+			x: touch[0].pageX - cropper.imgLeft,
+			y: touch[0].pageY - cropper.imgTop
+		};
+	} else {
+		var width = Math.abs(touch[0].pageX - touch[1].pageX);
+		var height = Math.abs(touch[0].pageY - touch[1].pageY);
+		cropper.touchRelative = [{
+				x: touch[0].pageX - cropper.imgLeft,
+				y: touch[0].pageY - cropper.imgTop
+			},
+			{
+				x: touch[1].pageX - cropper.imgLeft,
+				y: touch[1].pageY - cropper.imgTop
+			}
+		];
+		cropper.hypotenuseLength = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
+	}
+
+}
+
+function moveDuring(ins) {
+	if (!ins) return;
+	ins.callMethod('moveDuring')
+}
+
+function moveStop(ins) {
+	if (!ins) return;
+	ins.callMethod('moveStop')
+};
+
+function setCutCenter(ins) {
+	var cutY = (cropper.windowHeight - cropper.canvasHeight) * 0.5;
+	var cutX = (cropper.windowWidth - cropper.canvasWidth) * 0.5;
+	//顺序不能变
+	cropper.imgTop = cropper.imgTop - cropper.cutY + cutY;
+	cropper.cutY = cutY; //截取的框上边距
+	cropper.imgLeft = cropper.imgLeft - cropper.cutX + cutX;
+	cropper.cutX = cutX; //截取的框左边距
+	styleUpdate(ins)
+	cutDetectionPosition(ins)
+	imgTransform(ins)
+	updateData(ins)
+}
+
+function touchmove(e, ins) {
+	var touch = e.touches || e.changedTouches;
+	if (cropper.flagEndTouch) return;
+	moveDuring(ins);
+	if (e.touches.length == 1) {
+		var left = touch[0].pageX - cropper.touchRelative[0].x,
+			top = touch[0].pageY - cropper.touchRelative[0].y;
+		cropper.imgLeft = left;
+		cropper.imgTop = top;
+		imgTransform(ins);
+		imgMarginDetectionPosition(ins);
+	} else {
+		var res = e.instance.getDataset();
+		var minScale = +res.minscale;
+		var maxScale = +res.maxscale;
+		var disableRotate = bool(res.disablerotate)
+		var width = Math.abs(touch[0].pageX - touch[1].pageX),
+			height = Math.abs(touch[0].pageY - touch[1].pageY),
+			hypotenuse = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)),
+			scale = cropper.scale * (hypotenuse / cropper.hypotenuseLength),
+			current_deg = 0;
+		scale = scale <= minScale ? minScale : scale;
+		scale = scale >= maxScale ? maxScale : scale;
+		cropper.scale = scale;
+		imgMarginDetectionScale(ins, true);
+		var touchRelative = [{
+				x: touch[0].pageX - cropper.imgLeft,
+				y: touch[0].pageY - cropper.imgTop
+			},
+			{
+				x: touch[1].pageX - cropper.imgLeft,
+				y: touch[1].pageY - cropper.imgTop
+			}
+		];
+		if (!disableRotate) {
+			var first_atan = (180 / Math.PI) * Math.atan2(touchRelative[0].y, touchRelative[0].x);
+			var first_atan_old = (180 / Math.PI) * Math.atan2(cropper.touchRelative[0].y, cropper.touchRelative[0].x);
+			var second_atan = (180 / Math.PI) * Math.atan2(touchRelative[1].y, touchRelative[1].x);
+			var second_atan_old = (180 / Math.PI) * Math.atan2(cropper.touchRelative[1].y, cropper.touchRelative[1].x);
+			var first_deg = first_atan - first_atan_old,
+				second_deg = second_atan - second_atan_old;
+			if (first_deg != 0) {
+				current_deg = first_deg;
+			} else if (second_deg != 0) {
+				current_deg = second_deg;
+			}
+		}
+		cropper.touchRelative = touchRelative;
+		cropper.hypotenuseLength = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
+		//更新视图
+		cropper.angle = cropper.angle + current_deg;
+		imgTransform(ins);
+	}
+}
+
+function touchend(e, ins) {
+	cropper.flagEndTouch = true;
+	moveStop(ins);
+	updateData(ins)
+}
+
+
+function cutTouchStart(e, ins) {
+	var touch = e.touches || e.changedTouches;
+	var currentX = touch[0].pageX;
+	var currentY = touch[0].pageY;
+
+	/*
+	 * (右下-1 右上-2 左上-3 左下-4)
+	 * left_x [3,4]
+	 * top_y [2,3]
+	 * right_x [1,2]
+	 * bottom_y [1,4]
+	 */
+	var left_x1 = cropper.cutX - 30;
+	var left_x2 = cropper.cutX + 30;
+
+	var top_y1 = cropper.cutY - 30;
+	var top_y2 = cropper.cutY + 30;
+
+	var right_x1 = cropper.cutX + cropper.canvasWidth - 30;
+	var right_x2 = cropper.cutX + cropper.canvasWidth + 30;
+
+	var bottom_y1 = cropper.cutY + cropper.canvasHeight - 30;
+	var bottom_y2 = cropper.cutY + cropper.canvasHeight + 30;
+
+	if (currentX > right_x1 && currentX < right_x2 && currentY > bottom_y1 && currentY < bottom_y2) {
+		moveDuring();
+		cropper.flagCutTouch = true;
+		cropper.flagEndTouch = true;
+		cropper.CUT_START = {
+			width: cropper.canvasWidth,
+			height: cropper.canvasHeight,
+			x: currentX,
+			y: currentY,
+			corner: 1
+		};
+	} else if (currentX > right_x1 && currentX < right_x2 && currentY > top_y1 && currentY < top_y2) {
+		moveDuring();
+		cropper.flagCutTouch = true;
+		cropper.flagEndTouch = true;
+		cropper.CUT_START = {
+			width: cropper.canvasWidth,
+			height: cropper.canvasHeight,
+			x: currentX,
+			y: currentY,
+			cutY: cropper.cutY,
+			cutX: cropper.cutX,
+			corner: 2
+		};
+	} else if (currentX > left_x1 && currentX < left_x2 && currentY > top_y1 && currentY < top_y2) {
+		moveDuring();
+		cropper.flagCutTouch = true;
+		cropper.flagEndTouch = true;
+		cropper.CUT_START = {
+			width: cropper.canvasWidth,
+			height: cropper.canvasHeight,
+			cutY: cropper.cutY,
+			cutX: cropper.cutX,
+			x: currentX,
+			y: currentY,
+			corner: 3
+		};
+	} else if (currentX > left_x1 && currentX < left_x2 && currentY > bottom_y1 && currentY < bottom_y2) {
+		moveDuring();
+		cropper.flagCutTouch = true;
+		cropper.flagEndTouch = true;
+		cropper.CUT_START = {
+			width: cropper.canvasWidth,
+			height: cropper.canvasHeight,
+			cutY: cropper.cutY,
+			cutX: cropper.cutX,
+			x: currentX,
+			y: currentY,
+			corner: 4
+		};
+	}
+}
+
+function cutTouchMove(e, ins) {
+	if (!cropper.CUT_START || cropper.CUT_START === 'null') return;
+	if (cropper.flagCutTouch) {
+		var touch = e.touches || e.changedTouches;
+		var res = e.instance.getDataset();
+		var lockRatio = bool(res.lockratio);
+		var lockWidth = bool(res.lockwidth);
+		var lockHeight = bool(res.lockheight);
+		if (lockRatio && (lockWidth || lockHeight)) return;
+		var width = cropper.canvasWidth,
+			height = cropper.canvasHeight,
+			cutY = cropper.cutY,
+			cutX = cropper.cutX;
+
+		var size_correct = function() {
+			width = width <= cropper.maxWidth ? (width >= cropper.minWidth ? width : cropper.minWidth) : cropper.maxWidth;
+			height = height <= cropper.maxHeight ? (height >= cropper.minHeight ? height : cropper.minHeight) : cropper.maxHeight;
+		}
+
+		var size_inspect = function() {
+			if ((width > cropper.maxWidth || width < cropper.minWidth || height > cropper.maxHeight || height < cropper.minHeight) &&
+				lockRatio) {
+				size_correct();
+				return false;
+			} else {
+				size_correct();
+				return true;
+			}
+		};
+		height = cropper.CUT_START.height + (cropper.CUT_START.corner > 1 && cropper.CUT_START.corner < 4 ? 1 : -1) * (
+			cropper.CUT_START.y - touch[0].pageY);
+		switch (cropper.CUT_START.corner) {
+			case 1:
+				width = cropper.CUT_START.width - cropper.CUT_START.x + touch[0].pageX;
+				if (lockRatio) {
+					height = width / (cropper.canvasWidth / cropper.canvasHeight);
+				}
+				if (!size_inspect()) return;
+				break;
+			case 2:
+				width = cropper.CUT_START.width - cropper.CUT_START.x + touch[0].pageX;
+				if (lockRatio) {
+					height = width / (cropper.canvasWidth / cropper.canvasHeight);
+				}
+				if (!size_inspect()) return;
+				cutY = cropper.CUT_START.cutY - (height - cropper.CUT_START.height);
+				break;
+			case 3:
+				width = cropper.CUT_START.width + cropper.CUT_START.x - touch[0].pageX;
+				if (lockRatio) {
+					height = width / (cropper.canvasWidth / cropper.canvasHeight);
+				}
+				if (!size_inspect()) return;
+				cutY = cropper.CUT_START.cutY - (height - cropper.CUT_START.height);
+				cutX = cropper.CUT_START.cutX - (width - cropper.CUT_START.width);
+				break;
+			case 4:
+				width = cropper.CUT_START.width + cropper.CUT_START.x - touch[0].pageX;
+				if (lockRatio) {
+					height = width / (cropper.canvasWidth / cropper.canvasHeight);
+				}
+				if (!size_inspect()) return;
+				cutX = cropper.CUT_START.cutX - (width - cropper.CUT_START.width);
+				break;
+			default:
+				break;
+		}
+		if (!lockWidth && !lockHeight) {
+			cropper.canvasWidth = width;
+			cropper.cutX = cutX;
+			cropper.canvasHeight = height;
+			cropper.cutY = cutY;
+			canvasHeight(ins);
+			canvasWidth(ins);
+		} else if (!lockWidth) {
+			cropper.canvasWidth = width;
+			cropper.cutX = cutX;
+			canvasWidth(ins);
+		} else if (!lockHeight) {
+			cropper.canvasHeight = height;
+			cropper.cutY = cutY;
+			canvasHeight(ins);
+		}
+		styleUpdate(ins)
+		imgMarginDetectionScale(ins);
+	}
+}
+
+//检测剪裁框位置是否在允许的范围内(屏幕内)
+function cutDetectionPosition(ins) {
+	var windowHeight = cropper.windowHeight,
+		windowWidth = cropper.windowWidth;
+
+	var cutDetectionPositionTop = function() {
+		//检测上边距是否在范围内
+		if (cropper.cutY < 0) {
+			cropper.cutY = 0;
+		}
+		if (cropper.cutY > windowHeight - cropper.canvasHeight) {
+			cropper.cutY = windowHeight - cropper.canvasHeight;
+		}
+	}
+
+	var cutDetectionPositionLeft = function() {
+		//检测左边距是否在范围内
+		if (cropper.cutX < 0) {
+			cropper.cutX = 0;
+		}
+		if (cropper.cutX > windowWidth - cropper.canvasWidth) {
+			cropper.cutX = windowWidth - cropper.canvasWidth;
+		}
+	}
+	//裁剪框坐标处理(如果只写一个参数则另一个默认为0,都不写默认居中)
+	if (cropper.cutY == null && cropper.cutX == null) {
+		var cutY = (windowHeight - cropper.canvasHeight) * 0.5;
+		var cutX = (windowWidth - cropper.canvasWidth) * 0.5;
+		cropper.cutY = cutY; //截取的框上边距
+		cropper.cutX = cutX; //截取的框左边距
+	} else if (cropper.cutY != null && cropper.cutX != null) {
+		cutDetectionPositionTop();
+		cutDetectionPositionLeft();
+	} else if (cropper.cutY != null && cropper.cutX == null) {
+		cutDetectionPositionTop();
+		cropper.cutX = (windowWidth - cropper.canvasWidth) / 2;
+	} else if (cropper.cutY == null && cropper.cutX != null) {
+		cutDetectionPositionLeft();
+		cropper.cutY = (windowHeight - cropper.canvasHeight) / 2;
+	}
+
+	styleUpdate(ins)
+}
+
+/**
+ * 图片边缘检测-缩放
+ */
+function imgMarginDetectionScale(ins, delay) {
+	if (!cropper.limitMove) return;
+	var scale = cropper.scale;
+	var imgWidth = cropper.imgWidth;
+	var imgHeight = cropper.imgHeight;
+	if ((cropper.angle / 90) % 2) {
+		imgWidth = cropper.imgHeight;
+		imgHeight = cropper.imgWidth;
+	}
+	if (imgWidth * scale < cropper.canvasWidth) {
+		scale = cropper.canvasWidth / imgWidth;
+	}
+	if (imgHeight * scale < cropper.canvasHeight) {
+		scale = Math.max(scale, cropper.canvasHeight / imgHeight);
+	}
+	imgMarginDetectionPosition(ins, scale, delay);
+}
+/**
+ * 图片边缘检测-位置
+ */
+function imgMarginDetectionPosition(ins, scale, delay) {
+	if (!cropper.limitMove) return;
+	var left = cropper.imgLeft;
+	var top = cropper.imgTop;
+	scale = scale || cropper.scale;
+	var imgWidth = cropper.imgWidth;
+	var imgHeight = cropper.imgHeight;
+	if ((cropper.angle / 90) % 2) {
+		imgWidth = cropper.imgHeight;
+		imgHeight = cropper.imgWidth;
+	}
+	left = cropper.cutX + (imgWidth * scale) / 2 >= left ? left : cropper.cutX + (imgWidth * scale) / 2;
+	left = cropper.cutX + cropper.canvasWidth - (imgWidth * scale) / 2 <= left ? left : cropper.cutX + cropper.canvasWidth -
+		(imgWidth * scale) / 2;
+	top = cropper.cutY + (imgHeight * scale) / 2 >= top ? top : cropper.cutY + (imgHeight * scale) / 2;
+	top = cropper.cutY + cropper.canvasHeight - (imgHeight * scale) / 2 <= top ? top : cropper.cutY + cropper.canvasHeight -
+		(imgHeight * scale) / 2;
+
+	cropper.imgLeft = left;
+	cropper.imgTop = top;
+	cropper.scale = scale;
+	styleUpdate(ins)
+	if (!delay || delay === 'null') {
+		imgTransform(ins);
+	}
+}
+
+
+function cutTouchEnd(e, ins) {
+	moveStop(ins);
+	cropper.flagCutTouch = false;
+	updateData(ins)
+}
+
+
+//改变截取框大小
+function computeCutSize(ins) {
+	if (cropper.canvasWidth > cropper.windowWidth) {
+		cropper.canvasWidth = cropper.windowWidth;
+		// canvasWidth(ins)
+	} else if (cropper.canvasWidth + cropper.cutX > cropper.windowWidth) {
+		cropper.cutX = cropper.windowWidth - cropper.cutX;
+	}
+	if (cropper.canvasHeight > cropper.windowHeight) {
+		cropper.canvasHeight = cropper.windowHeight;
+		// canvasHeight(ins)
+	} else if (cropper.canvasHeight + cropper.cutY > cropper.windowHeight) {
+		cropper.cutY = cropper.windowHeight - cropper.cutY;
+	}
+	// styleUpdate(ins)
+}
+
+function styleUpdate(ins) {
+	if (!ins) return;
+	ins.selectComponent('.tui-cropper-box').setStyle({
+		'width': cropper.canvasWidth + 'px',
+		'height': cropper.canvasHeight + 'px'
+	})
+	ins.selectComponent('.tui-content-middle').setStyle({
+		'height': cropper.canvasHeight + 'px'
+	})
+	ins.selectComponent('.tui-content-top').setStyle({
+		'height': cropper.cutY + 'px'
+	})
+	ins.selectComponent('.tui-wxs-bg').setStyle({
+		'width': cropper.cutX + 'px'
+	})
+
+}
+
+function imgTransform(ins) {
+	var owner = ins.selectComponent('.tui-cropper-image')
+	if (!owner) return
+	var x = cropper.imgLeft - cropper.imgWidth / 2;
+	var y = cropper.imgTop - cropper.imgHeight / 2;
+	owner.setStyle({
+		'transform': 'translate3d(' + x + 'px,' + y + 'px,0) scale(' + cropper.scale + ') rotate(' + cropper.angle + 'deg)'
+	})
+}
+
+function imageReset(ins) {
+	cropper.scale = 1;
+	cropper.angle = 0;
+	imgTransform(ins);
+}
+//监听截取框宽高变化
+function canvasWidth(ins) {
+	if (cropper.canvasWidth < cropper.minWidth) {
+		cropper.canvasWidth = cropper.minWidth;
+	}
+	if (!ins) return;
+	computeCutSize(ins);
+}
+
+function canvasHeight(ins) {
+	if (cropper.canvasHeight < cropper.minHeight) {
+		cropper.canvasHeight = cropper.minHeight;
+	}
+	if (!ins) return;
+	computeCutSize(ins);
+}
+
+function updateData(ins) {
+	if (!ins) return;
+	ins.callMethod('change', {
+		cutX: cropper.cutX,
+		cutY: cropper.cutY,
+		canvasWidth: cropper.canvasWidth,
+		canvasHeight: cropper.canvasHeight,
+		imgWidth: cropper.imgWidth,
+		imgHeight: cropper.imgHeight,
+		scale: cropper.scale,
+		angle: cropper.angle,
+		imgTop: cropper.imgTop,
+		imgLeft: cropper.imgLeft
+	})
+}
+
+function propsChange(prop, oldProp, ownerInstance, ins) {
+	if (prop && prop !== 'null') {
+		var params = prop.split(',')
+		var type = +params[0]
+		var dataset = ins.getDataset();
+		if (cropper.init || type == 4) {
+			cropper.maxHeight = +dataset.maxheight;
+			cropper.minHeight = +dataset.minheight;
+			cropper.maxWidth = +dataset.maxwidth;
+			cropper.minWidth = +dataset.minwidth;
+			cropper.canvasWidth = +dataset.width;
+			cropper.canvasHeight = +dataset.height;
+			cropper.imgTop = dataset.windowheight / 2;
+			cropper.imgLeft = dataset.windowwidth / 2;
+			cropper.imgWidth = +dataset.imgwidth;
+			cropper.imgHeight = +dataset.imgheight;
+			cropper.windowHeight = +dataset.windowheight;
+			cropper.windowWidth = +dataset.windowwidth;
+			cropper.init = false
+		} else if (type == 2 || type == 3) {
+			cropper.imgWidth = +dataset.imgwidth;
+			cropper.imgHeight = +dataset.imgheight;
+		}
+		cropper.limitMove = bool(dataset.limitmove);
+		cropper.angle = +dataset.angle;
+		if (type == 3) {
+			imgTransform(ownerInstance);
+		}
+		switch (type) {
+			case 1:
+				setCutCenter(ownerInstance);
+				//设置裁剪框大小>设置图片尺寸>绘制canvas
+				computeCutSize(ownerInstance);
+				//检查裁剪框是否在范围内
+				cutDetectionPosition(ownerInstance);
+				break;
+			case 2:
+				setCutCenter(ownerInstance);
+				break;
+			case 3:
+				imgMarginDetectionScale(ownerInstance)
+				break;
+			case 4:
+				imageReset(ownerInstance);
+				break;
+			case 5:
+				setCutCenter(ownerInstance);
+				break;
+			default:
+				break;
+		}
+	}
+}
+
+module.exports = {
+	touchstart: touchstart,
+	touchmove: touchmove,
+	touchend: touchend,
+	cutTouchStart: cutTouchStart,
+	cutTouchMove: cutTouchMove,
+	cutTouchEnd: cutTouchEnd,
+	propsChange: propsChange
+}

+ 22 - 0
main.js

@@ -0,0 +1,22 @@
+import Vue from 'vue'
+import App from './App'
+import store from './store'
+import moment from 'moment'
+import utils from './util/util'
+
+moment.locale('zh-cn')
+
+Vue.prototype.utils = utils
+Vue.prototype.$moment = moment
+Vue.prototype.$store = store
+
+
+Vue.config.productionTip = false
+
+App.mpType = 'app'
+
+const app = new Vue({
+  store,
+  ...App
+})
+app.$mount()

+ 131 - 0
manifest.json

@@ -0,0 +1,131 @@
+{
+    "name" : "云咖交易-商家端",
+    "appid" : "__UNI__9660E1D",
+    "description" : "",
+    "versionName" : "2.0.0",
+    "versionCode" : 200,
+    "transformPx" : false,
+    /* 5+App特有相关 */
+    "app-plus" : {
+        "usingComponents" : true,
+        "nvueStyleCompiler" : "uni-app",
+        "compilerVersion" : 3,
+        "splashscreen" : {
+            "alwaysShowBeforeRender" : true,
+            "waiting" : true,
+            "autoclose" : true,
+            "delay" : 0
+        },
+        /* 模块配置 */
+        "modules" : {
+            "LivePusher" : {},
+            "VideoPlayer" : {},
+            "Geolocation" : {}
+        },
+        /* 应用发布信息 */
+        "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_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
+                    "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
+                    "<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.VIBRATE\"/>",
+                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
+                ]
+            },
+            /* ios打包配置 */
+            "ios" : {
+                "privacyDescription" : {
+                    "NSPhotoLibraryUsageDescription" : "上传图片时需要",
+                    "NSCameraUsageDescription" : "上传图片时需要",
+                    "NSLocationWhenInUseUsageDescription" : "定位时需要"
+                },
+                "idfa" : false
+            },
+            /* SDK配置 */
+            "sdkConfigs" : {
+                "ad" : {},
+                "geolocation" : {
+                    "baidu" : {
+                        "__platform__" : [ "ios", "android" ],
+                        "appkey_ios" : "7Lr4vSSiKYO1xUZo84mBVb5EpYMt8xkw",
+                        "appkey_android" : "XZzv6qoeGRrI01uHaQUo1y2SjDGaOvzV"
+                    }
+                }
+            },
+            "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"
+                    }
+                }
+            }
+        }
+    },
+    /* 快应用特有相关 */
+    "quickapp" : {},
+    /* 小程序特有相关 */
+    "mp-weixin" : {
+        "appid" : "wx7c160594b6ce37ec",
+        "setting" : {
+            "urlCheck" : false
+        },
+        "usingComponents" : true
+    },
+    "mp-alipay" : {
+        "usingComponents" : true
+    },
+    "mp-baidu" : {
+        "usingComponents" : true
+    },
+    "mp-toutiao" : {
+        "usingComponents" : true
+    },
+    "uniStatistics" : {
+        "enable" : false
+    },
+    "h5" : {
+        "title" : "DSMall_Store_uniapp",
+        "domain" : "uniapp.store.dsmall.csdeshang.com",
+        "router" : {
+            "mode" : "history"
+        }
+    }
+}

+ 15 - 0
node_modules/.bin/uuid

@@ -0,0 +1,15 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+    *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -x "$basedir/node" ]; then
+  "$basedir/node"  "$basedir/../uuid/bin/uuid" "$@"
+  ret=$?
+else 
+  node  "$basedir/../uuid/bin/uuid" "$@"
+  ret=$?
+fi
+exit $ret

+ 17 - 0
node_modules/.bin/uuid.cmd

@@ -0,0 +1,17 @@
+@ECHO off
+SETLOCAL
+CALL :find_dp0
+
+IF EXIST "%dp0%\node.exe" (
+  SET "_prog=%dp0%\node.exe"
+) ELSE (
+  SET "_prog=node"
+  SET PATHEXT=%PATHEXT:;.JS;=;%
+)
+
+"%_prog%"  "%dp0%\..\uuid\bin\uuid" %*
+ENDLOCAL
+EXIT /b %errorlevel%
+:find_dp0
+SET dp0=%~dp0
+EXIT /b

+ 18 - 0
node_modules/.bin/uuid.ps1

@@ -0,0 +1,18 @@
+#!/usr/bin/env pwsh
+$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
+
+$exe=""
+if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
+  # Fix case when both the Windows and Linux builds of Node
+  # are installed in the same directory
+  $exe=".exe"
+}
+$ret=0
+if (Test-Path "$basedir/node$exe") {
+  & "$basedir/node$exe"  "$basedir/../uuid/bin/uuid" $args
+  $ret=$LASTEXITCODE
+} else {
+  & "node$exe"  "$basedir/../uuid/bin/uuid" $args
+  $ret=$LASTEXITCODE
+}
+exit $ret

+ 685 - 0
node_modules/axios/CHANGELOG.md

@@ -0,0 +1,685 @@
+# Changelog
+
+### 0.21.1 (December 21, 2020)
+
+Fixes and Functionality:
+
+- Hotfix: Prevent SSRF (#3410)
+- Protocol not parsed when setting proxy config from env vars (#3070)
+- Updating axios in types to be lower case (#2797)
+- Adding a type guard for `AxiosError` (#2949)
+
+Internal and Tests:
+
+- Remove the skipping of the `socket` http test (#3364)
+- Use different socket for Win32 test (#3375)
+
+Huge thanks to everyone who contributed to this release via code (authors listed below) or via reviews and triaging on GitHub:
+
+- Daniel Lopretto <timemachine3030@users.noreply.github.com>
+- Jason Kwok <JasonHK@users.noreply.github.com>
+- Jay <jasonsaayman@gmail.com>
+- Jonathan Foster <jonathan@jonathanfoster.io>
+- Remco Haszing <remcohaszing@gmail.com>
+- Xianming Zhong <chinesedfan@qq.com>
+
+### 0.21.0 (October 23, 2020)
+
+Fixes and Functionality:
+
+- Fixing requestHeaders.Authorization ([#3287](https://github.com/axios/axios/pull/3287))
+- Fixing node types ([#3237](https://github.com/axios/axios/pull/3237))
+- Fixing axios.delete ignores config.data ([#3282](https://github.com/axios/axios/pull/3282))
+- Revert "Fixing overwrite Blob/File type as Content-Type in browser. (#1773)" ([#3289](https://github.com/axios/axios/pull/3289))
+- Fixing an issue that type 'null' and 'undefined' is not assignable to validateStatus when typescript strict option is enabled ([#3200](https://github.com/axios/axios/pull/3200))
+
+Internal and Tests:
+
+- Lock travis to not use node v15 ([#3361](https://github.com/axios/axios/pull/3361))
+
+Documentation:
+
+- Fixing simple typo, existant -> existent ([#3252](https://github.com/axios/axios/pull/3252))
+- Fixing typos ([#3309](https://github.com/axios/axios/pull/3309))
+
+Huge thanks to everyone who contributed to this release via code (authors listed below) or via reviews and triaging on GitHub:
+
+- Allan Cruz <57270969+Allanbcruz@users.noreply.github.com>
+- George Cheng <Gerhut@GMail.com>
+- Jay <jasonsaayman@gmail.com>
+- Kevin Kirsche <Kev.Kirsche+GitHub@gmail.com>
+- Remco Haszing <remcohaszing@gmail.com>
+- Taemin Shin <cprayer13@gmail.com>
+- Tim Gates <tim.gates@iress.com>
+- Xianming Zhong <chinesedfan@qq.com>
+
+### 0.20.0 (August 20, 2020)
+
+Release of 0.20.0-pre as a full release with no other changes.
+
+### 0.20.0-pre (July 15, 2020)
+
+Fixes and Functionality:
+
+- Fixing response with utf-8 BOM can not parse to json ([#2419](https://github.com/axios/axios/pull/2419))
+  - fix: remove byte order marker (UTF-8 BOM) when transform response
+  - fix: remove BOM only utf-8
+  - test: utf-8 BOM
+  - fix: incorrect param name
+- Refactor mergeConfig without utils.deepMerge ([#2844](https://github.com/axios/axios/pull/2844))
+  - Adding failing test
+  - Fixing #2587 default custom config persisting
+  - Adding Concat keys and filter duplicates
+  - Fixed value from CPE
+  - update for review feedbacks
+  - no deepMerge
+  - only merge between plain objects
+  - fix rename
+  - always merge config by mergeConfig
+  - extract function mergeDeepProperties
+  - refactor mergeConfig with all keys, and add special logic for validateStatus
+  - add test for resetting headers
+  - add lots of tests and fix a bug
+  - should not inherit `data`
+  - use simple toString
+- Fixing overwrite Blob/File type as Content-Type in browser. ([#1773](https://github.com/axios/axios/pull/1773))
+- Fixing an issue that type 'null' is not assignable to validateStatus ([#2773](https://github.com/axios/axios/pull/2773))
+- Fixing special char encoding ([#1671](https://github.com/axios/axios/pull/1671))
+  - removing @ character from replacement list since it is a reserved character
+  - Updating buildURL test to not include the @ character
+  - Removing console logs
+- Fixing password encoding with special characters in basic authentication ([#1492](https://github.com/axios/axios/pull/1492))
+  - Fixing password encoding with special characters in basic authentication
+  - Adding test to check if password with non-Latin1 characters pass
+- Fixing 'Network Error' in react native android ([#1487](https://github.com/axios/axios/pull/1487))
+  There is a bug in react native Android platform when using get method. It will trigger a 'Network Error' when passing the requestData which is an empty string to request.send function. So if the requestData is an empty string we can set it to null as well to fix the bug.
+- Fixing Cookie Helper with Asyc Components ([#1105](https://github.com/axios/axios/pull/1105)) ([#1107](https://github.com/axios/axios/pull/1107))
+- Fixing 'progressEvent' type ([#2851](https://github.com/axios/axios/pull/2851))
+  - Fix 'progressEvent' type
+  - Update axios.ts
+- Fixing getting local files (file://) failed ([#2470](https://github.com/axios/axios/pull/2470))
+  - fix issue #2416, #2396
+  - fix Eslint warn
+  - Modify judgment conditions
+  - add unit test
+  - update unit test
+  - update unit test
+- Allow PURGE method in typings ([#2191](https://github.com/axios/axios/pull/2191))
+- Adding option to disable automatic decompression ([#2661](https://github.com/axios/axios/pull/2661))
+  - Adding ability to disable auto decompression
+  - Updating decompress documentation in README
+  - Fixing test\unit\adapters\http.js lint errors
+  - Adding test for disabling auto decompression
+  - Removing changes that fixed lint errors in tests
+  - Removing formatting change to unit test
+- Add independent `maxBodyLength` option ([#2781](https://github.com/axios/axios/pull/2781))
+  - Add independent option to set the maximum size of the request body
+  - Remove maxBodyLength check
+  - Update README
+  - Assert for error code and message
+- Adding responseEncoding to mergeConfig ([#1745](https://github.com/axios/axios/pull/1745))
+- Compatible with follow-redirect aborts the request ([#2689](https://github.com/axios/axios/pull/2689))
+  - Compatible with follow-redirect aborts the request
+  - Use the error code
+- Fix merging of params ([#2656](https://github.com/axios/axios/pull/2656))
+  - Name function to avoid ESLint func-names warning
+  - Switch params config to merge list and update tests
+  - Restore testing of both false and null
+  - Restore test cases for keys without defaults
+  - Include test for non-object values that aren't false-y.
+- Revert `finally` as `then` ([#2683](https://github.com/axios/axios/pull/2683))
+
+Internal and Tests:
+
+- Fix stale bot config ([#3049](https://github.com/axios/axios/pull/3049))
+  - fix stale bot config
+  - fix multiple lines
+- Add days and change name to work ([#3035](https://github.com/axios/axios/pull/3035))
+- Update close-issues.yml ([#3031](https://github.com/axios/axios/pull/3031))
+  - Update close-issues.yml
+    Update close message to read better 😄
+  - Fix use of quotations
+    Use single quotes as per other .yml files
+  - Remove user name form message
+- Add GitHub actions to close stale issues/prs ([#3029](https://github.com/axios/axios/pull/3029))
+  - prepare stale actions
+  - update messages
+  - Add exempt labels and lighten up comments
+- Add GitHub actions to close invalid issues ([#3022](https://github.com/axios/axios/pull/3022))
+  - add close actions
+  - fix with checkout
+  - update issue templates
+  - add reminder
+  - update close message
+- Add test with Node.js 12 ([#2860](https://github.com/axios/axios/pull/2860))
+  - test with Node.js 12
+  - test with latest
+- Adding console log on sandbox server startup ([#2210](https://github.com/axios/axios/pull/2210))
+  - Adding console log on sandbox server startup
+  - Update server.js
+    Add server error handling
+  - Update server.js
+    Better error message, remove retry.
+- Adding tests for method `options` type definitions ([#1996](https://github.com/axios/axios/pull/1996))
+  Update tests.
+- Add test for redirecting with too large response ([#2695](https://github.com/axios/axios/pull/2695))
+- Fixing unit test failure in Windows OS ([#2601](https://github.com/axios/axios/pull/2601))
+- Fixing issue for HEAD method and gzipped response ([#2666](https://github.com/axios/axios/pull/2666))
+- Fix tests in browsers ([#2748](https://github.com/axios/axios/pull/2748))
+- chore: add `jsdelivr` and `unpkg` support ([#2443](https://github.com/axios/axios/pull/2443))
+
+Documentation:
+
+- Adding support for URLSearchParams in node ([#1900](https://github.com/axios/axios/pull/1900))
+  - Adding support for URLSearchParams in node
+  - Remove un-needed code
+  - Update utils.js
+  - Make changes as suggested
+- Adding table of content (preview) ([#3050](https://github.com/axios/axios/pull/3050))
+  - add toc (preview)
+  - remove toc in toc
+    Signed-off-by: Moni <usmoni@gmail.com>
+  - fix sublinks
+  - fix indentation
+  - remove redundant table links
+  - update caps and indent
+  - remove axios
+- Replace 'blacklist' with 'blocklist' ([#3006](https://github.com/axios/axios/pull/3006))
+- docs(): Detailed config options environment. ([#2088](https://github.com/axios/axios/pull/2088))
+  - docs(): Detailed config options environment.
+  - Update README.md
+- Include axios-data-unpacker in ECOSYSTEM.md ([#2080](https://github.com/axios/axios/pull/2080))
+- Allow opening examples in Gitpod ([#1958](https://github.com/axios/axios/pull/1958))
+- Remove axios.all() and axios.spread() from Readme.md ([#2727](https://github.com/axios/axios/pull/2727))
+  - remove axios.all(), axios.spread()
+  - replace example
+  - axios.all() -> Promise.all()
+  - axios.spread(function (acct, perms)) -> function (acct, perms)
+  - add deprecated mark
+- Update README.md ([#2887](https://github.com/axios/axios/pull/2887))
+  Small change to the data attribute doc of the config. A request body can also be set for DELETE methods but this wasn't mentioned in the documentation (it only mentioned POST, PUT and PATCH). Took my some 10-20 minutes until I realized that I don't need to manipulate the request body with transformRequest in the case of DELETE.
+- Include swagger-taxos-codegen in ECOSYSTEM.md ([#2162](https://github.com/axios/axios/pull/2162))
+- Add CDNJS version badge in README.md ([#878](https://github.com/axios/axios/pull/878))
+  This badge will show the version on CDNJS!
+- Documentation update to clear up ambiguity in code examples ([#2928](https://github.com/axios/axios/pull/2928))
+  - Made an adjustment to the documentation to clear up any ambiguity around the use of "fs". This should help clear up that the code examples with "fs" cannot be used on the client side.
+- Update README.md about validateStatus ([#2912](https://github.com/axios/axios/pull/2912))
+  Rewrote the comment from "Reject only if the status code is greater than or equal to 500" to "Resolve only if the status code is less than 500"
+- Updating documentation for usage form-data ([#2805](https://github.com/axios/axios/pull/2805))
+  Closes #2049
+- Fixing CHANGELOG.md issue link ([#2784](https://github.com/axios/axios/pull/2784))
+- Include axios-hooks in ECOSYSTEM.md ([#2003](https://github.com/axios/axios/pull/2003))
+- Added Response header access instructions ([#1901](https://github.com/axios/axios/pull/1901))
+  - Added Response header access instructions
+  - Added note about using bracket notation
+- Add `onUploadProgress` and `onDownloadProgress` are browser only ([#2763](https://github.com/axios/axios/pull/2763))
+  Saw in #928 and #1966 that `onUploadProgress` and `onDownloadProgress` only work in the browser and was missing that from the README.
+- Update ' sign to ` in proxy spec ([#2778](https://github.com/axios/axios/pull/2778))
+- Adding jsDelivr link in README ([#1110](https://github.com/axios/axios/pull/1110))
+  - Adding jsDelivr link
+  - Add SRI
+  - Remove SRI
+
+Huge thanks to everyone who contributed to this release via code (authors listed
+below) or via reviews and triaging on GitHub:
+
+- Alan Wang <wp_scut@163.com>
+- Alexandru Ungureanu <khakcarot@gmail.com>
+- Anubhav Srivastava <anubhav.srivastava00@gmail.com>
+- Benny Neugebauer <bn@bennyn.de>
+- Cr <631807682@qq.com>
+- David <cygnidavid@gmail.com>
+- David Ko <david.ko@pvtmethod.com>
+- David Tanner <david.tanner@lifeomic.com>
+- Emily Morehouse <emilyemorehouse@gmail.com>
+- Felipe Martins <felipewmartins@gmail.com>
+- Fonger <5862369+Fonger@users.noreply.github.com>
+- Frostack <soulburn007@gmail.com>
+- George Cheng <Gerhut@GMail.com>
+- grumblerchester <grumblerchester@users.noreply.github.com>
+- Gustavo López <gualopezb@gmail.com>
+- hexaez <45806662+hexaez@users.noreply.github.com>
+- huangzuizui <huangzuizui@gmail.com>
+- Ian Wijma <ian@wij.ma>
+- Jay <jasonsaayman@gmail.com>
+- jeffjing <zgayjjf@qq.com>
+- jennynju <46782518+jennynju@users.noreply.github.com>
+- Jimmy Liao <52391190+jimmy-liao-gogoro@users.noreply.github.com>
+- Jonathan Sharpe <j.r.sharpe@gmail.com>
+- JounQin <admin@1stg.me>
+- Justin Beckwith <justin.beckwith@gmail.com>
+- Kamil Posiadała <3dcreator.pl@gmail.com>
+- Lukas Drgon <lukas.drgon@gmail.com>
+- marcinx <mail@marcinx.com>
+- Martti Laine <martti@codeclown.net>
+- Michał Zarach <michal.m.zarach@gmail.com>
+- Moni <usmoni@gmail.com>
+- Motonori Iwata <121048+iwata@users.noreply.github.com>
+- Nikita Galkin <nikita@galk.in>
+- Petr Mares <petr@mares.tw>
+- Philippe Recto <precto1285@gmal.com>
+- Remco Haszing <remcohaszing@gmail.com>
+- rockcs1992 <chengshi1219@gmail.com>
+- Ryan Bown <rbown@niftee.com.au>
+- Samina Fu <sufuf3@gmail.com>
+- Simone Busoli <simone.busoli@gmail.com>
+- Spencer von der Ohe <s.vonderohe40@gmail.com>
+- Sven Efftinge <sven.efftinge@typefox.io>
+- Taegyeoung Oh <otk1090@naver.com>
+- Taemin Shin <cprayer13@gmail.com>
+- Thibault Ehrhart <1208424+ehrhart@users.noreply.github.com>
+- Xianming Zhong <chinesedfan@qq.com>
+- Yasu Flores <carlosyasu91@gmail.com>
+- Zac Delventhal <delventhalz@gmail.com>
+
+### 0.19.2 (Jan 20, 2020)
+
+- Remove unnecessary XSS check ([#2679](https://github.com/axios/axios/pull/2679)) (see ([#2646](https://github.com/axios/axios/issues/2646)) for discussion)
+
+### 0.19.1 (Jan 7, 2020)
+
+Fixes and Functionality:
+
+- Fixing invalid agent issue ([#1904](https://github.com/axios/axios/pull/1904))
+- Fix ignore set withCredentials false ([#2582](https://github.com/axios/axios/pull/2582))
+- Delete useless default to hash ([#2458](https://github.com/axios/axios/pull/2458))
+- Fix HTTP/HTTPs agents passing to follow-redirect ([#1904](https://github.com/axios/axios/pull/1904))
+- Fix ignore set withCredentials false ([#2582](https://github.com/axios/axios/pull/2582))
+- Fix CI build failure ([#2570](https://github.com/axios/axios/pull/2570))
+- Remove dependency on is-buffer from package.json ([#1816](https://github.com/axios/axios/pull/1816))
+- Adding options typings ([#2341](https://github.com/axios/axios/pull/2341))
+- Adding Typescript HTTP method definition for LINK and UNLINK. ([#2444](https://github.com/axios/axios/pull/2444))
+- Update dist with newest changes, fixes Custom Attributes issue
+- Change syntax to see if build passes ([#2488](https://github.com/axios/axios/pull/2488))
+- Update Webpack + deps, remove now unnecessary polyfills ([#2410](https://github.com/axios/axios/pull/2410))
+- Fix to prevent XSS, throw an error when the URL contains a JS script ([#2464](https://github.com/axios/axios/pull/2464))
+- Add custom timeout error copy in config ([#2275](https://github.com/axios/axios/pull/2275))
+- Add error toJSON example ([#2466](https://github.com/axios/axios/pull/2466))
+- Fixing Vulnerability A Fortify Scan finds a critical Cross-Site Scrip… ([#2451](https://github.com/axios/axios/pull/2451))
+- Fixing subdomain handling on no_proxy ([#2442](https://github.com/axios/axios/pull/2442))
+- Make redirection from HTTP to HTTPS work ([#2426](https://github.com/axios/axios/pull/2426)) and ([#2547](https://github.com/axios/axios/pull/2547))
+- Add toJSON property to AxiosError type ([#2427](https://github.com/axios/axios/pull/2427))
+- Fixing socket hang up error on node side for slow response. ([#1752](https://github.com/axios/axios/pull/1752))
+- Alternative syntax to send data into the body ([#2317](https://github.com/axios/axios/pull/2317))
+- Fixing custom config options ([#2207](https://github.com/axios/axios/pull/2207))
+- Fixing set `config.method` after mergeConfig for Axios.prototype.request ([#2383](https://github.com/axios/axios/pull/2383))
+- Axios create url bug ([#2290](https://github.com/axios/axios/pull/2290))
+- Do not modify config.url when using a relative baseURL (resolves [#1628](https://github.com/axios/axios/issues/1098)) ([#2391](https://github.com/axios/axios/pull/2391))
+- Add typescript HTTP method definition for LINK and UNLINK ([#2444](https://github.com/axios/axios/pull/2444))
+
+Internal:
+
+- Revert "Update Webpack + deps, remove now unnecessary polyfills" ([#2479](https://github.com/axios/axios/pull/2479))
+- Order of if/else blocks is causing unit tests mocking XHR. ([#2201](https://github.com/axios/axios/pull/2201))
+- Add license badge ([#2446](https://github.com/axios/axios/pull/2446))
+- Fix travis CI build [#2386](https://github.com/axios/axios/pull/2386)
+- Fix cancellation error on build master. #2290 #2207 ([#2407](https://github.com/axios/axios/pull/2407))
+
+Documentation:
+
+- Fixing typo in CHANGELOG.md: s/Functionallity/Functionality ([#2639](https://github.com/axios/axios/pull/2639))
+- Fix badge, use master branch ([#2538](https://github.com/axios/axios/pull/2538))
+- Fix typo in changelog [#2193](https://github.com/axios/axios/pull/2193)
+- Document fix ([#2514](https://github.com/axios/axios/pull/2514))
+- Update docs with no_proxy change, issue #2484 ([#2513](https://github.com/axios/axios/pull/2513))
+- Fixing missing words in docs template ([#2259](https://github.com/axios/axios/pull/2259))
+- 🐛Fix request finally documentation in README ([#2189](https://github.com/axios/axios/pull/2189))
+- updating spelling and adding link to docs ([#2212](https://github.com/axios/axios/pull/2212))
+- docs: minor tweak ([#2404](https://github.com/axios/axios/pull/2404))
+- Update response interceptor docs ([#2399](https://github.com/axios/axios/pull/2399))
+- Update README.md ([#2504](https://github.com/axios/axios/pull/2504))
+- Fix word 'sintaxe' to 'syntax' in README.md ([#2432](https://github.com/axios/axios/pull/2432))
+- updating README: notes on CommonJS autocomplete ([#2256](https://github.com/axios/axios/pull/2256))
+- Fix grammar in README.md ([#2271](https://github.com/axios/axios/pull/2271))
+- Doc fixes, minor examples cleanup ([#2198](https://github.com/axios/axios/pull/2198))
+
+### 0.19.0 (May 30, 2019)
+
+Fixes and Functionality:
+
+- Added support for no_proxy env variable ([#1693](https://github.com/axios/axios/pull/1693/files)) - Chance Dickson
+- Unzip response body only for statuses != 204 ([#1129](https://github.com/axios/axios/pull/1129)) - drawski
+- Destroy stream on exceeding maxContentLength (fixes [#1098](https://github.com/axios/axios/issues/1098)) ([#1485](https://github.com/axios/axios/pull/1485)) - Gadzhi Gadzhiev
+- Makes Axios error generic to use AxiosResponse ([#1738](https://github.com/axios/axios/pull/1738)) - Suman Lama
+- Fixing Mocha tests by locking follow-redirects version to 1.5.10 ([#1993](https://github.com/axios/axios/pull/1993)) - grumblerchester
+- Allow uppercase methods in typings. ([#1781](https://github.com/axios/axios/pull/1781)) - Ken Powers
+- Fixing building url with hash mark ([#1771](https://github.com/axios/axios/pull/1771)) - Anatoly Ryabov
+- This commit fix building url with hash map (fragment identifier) when parameters are present: they must not be added after `#`, because client cut everything after `#`
+- Preserve HTTP method when following redirect ([#1758](https://github.com/axios/axios/pull/1758)) - Rikki Gibson
+- Add `getUri` signature to TypeScript definition. ([#1736](https://github.com/axios/axios/pull/1736)) - Alexander Trauzzi
+- Adding isAxiosError flag to errors thrown by axios ([#1419](https://github.com/axios/axios/pull/1419)) - Ayush Gupta
+
+Internal:
+
+- Fixing .eslintrc without extension ([#1789](https://github.com/axios/axios/pull/1789)) - Manoel
+- Fix failing SauceLabs tests by updating configuration - Emily Morehouse
+- Add issue templates - Emily Morehouse
+
+Documentation:
+
+- Consistent coding style in README ([#1787](https://github.com/axios/axios/pull/1787)) - Ali Servet Donmez
+- Add information about auth parameter to README ([#2166](https://github.com/axios/axios/pull/2166)) - xlaguna
+- Add DELETE to list of methods that allow data as a config option ([#2169](https://github.com/axios/axios/pull/2169)) - Daniela Borges Matos de Carvalho
+- Update ECOSYSTEM.md - Add Axios Endpoints ([#2176](https://github.com/axios/axios/pull/2176)) - Renan
+- Add r2curl in ECOSYSTEM ([#2141](https://github.com/axios/axios/pull/2141)) - 유용우 / CX
+- Update README.md - Add instructions for installing with yarn ([#2036](https://github.com/axios/axios/pull/2036)) - Victor Hermes
+- Fixing spacing for README.md ([#2066](https://github.com/axios/axios/pull/2066)) - Josh McCarty
+- Update README.md. - Change `.then` to `.finally` in example code ([#2090](https://github.com/axios/axios/pull/2090)) - Omar Cai
+- Clarify what values responseType can have in Node ([#2121](https://github.com/axios/axios/pull/2121)) - Tyler Breisacher
+- docs(ECOSYSTEM): add axios-api-versioning ([#2020](https://github.com/axios/axios/pull/2020)) - Weffe
+- It seems that `responseType: 'blob'` doesn't actually work in Node (when I tried using it, response.data was a string, not a Blob, since Node doesn't have Blobs), so this clarifies that this option should only be used in the browser
+- Update README.md. - Add Querystring library note ([#1896](https://github.com/axios/axios/pull/1896)) - Dmitriy Eroshenko
+- Add react-hooks-axios to Libraries section of ECOSYSTEM.md ([#1925](https://github.com/axios/axios/pull/1925)) - Cody Chan
+- Clarify in README that default timeout is 0 (no timeout) ([#1750](https://github.com/axios/axios/pull/1750)) - Ben Standefer
+
+### 0.19.0-beta.1 (Aug 9, 2018)
+
+**NOTE:** This is a beta version of this release. There may be functionality that is broken in
+certain browsers, though we suspect that builds are hanging and not erroring. See
+https://saucelabs.com/u/axios for the most up-to-date information.
+
+New Functionality:
+
+- Add getUri method ([#1712](https://github.com/axios/axios/issues/1712))
+- Add support for no_proxy env variable ([#1693](https://github.com/axios/axios/issues/1693))
+- Add toJSON to decorated Axios errors to facilitate serialization ([#1625](https://github.com/axios/axios/issues/1625))
+- Add second then on axios call ([#1623](https://github.com/axios/axios/issues/1623))
+- Typings: allow custom return types
+- Add option to specify character set in responses (with http adapter)
+
+Fixes:
+
+- Fix Keep defaults local to instance ([#385](https://github.com/axios/axios/issues/385))
+- Correctly catch exception in http test ([#1475](https://github.com/axios/axios/issues/1475))
+- Fix accept header normalization ([#1698](https://github.com/axios/axios/issues/1698))
+- Fix http adapter to allow HTTPS connections via HTTP ([#959](https://github.com/axios/axios/issues/959))
+- Fix Removes usage of deprecated Buffer constructor. ([#1555](https://github.com/axios/axios/issues/1555), [#1622](https://github.com/axios/axios/issues/1622))
+- Fix defaults to use httpAdapter if available ([#1285](https://github.com/axios/axios/issues/1285))
+  - Fixing defaults to use httpAdapter if available
+  - Use a safer, cross-platform method to detect the Node environment
+- Fix Reject promise if request is cancelled by the browser ([#537](https://github.com/axios/axios/issues/537))
+- [Typescript] Fix missing type parameters on delete/head methods
+- [NS]: Send `false` flag isStandardBrowserEnv for Nativescript
+- Fix missing type parameters on delete/head
+- Fix Default method for an instance always overwritten by get
+- Fix type error when socketPath option in AxiosRequestConfig
+- Capture errors on request data streams
+- Decorate resolve and reject to clear timeout in all cases
+
+Huge thanks to everyone who contributed to this release via code (authors listed
+below) or via reviews and triaging on GitHub:
+
+- Andrew Scott <ascott18@gmail.com>
+- Anthony Gauthier <antho325@hotmail.com>
+- arpit <arpit2438735@gmail.com>
+- ascott18
+- Benedikt Rötsch <axe312ger@users.noreply.github.com>
+- Chance Dickson <me@chancedickson.com>
+- Dave Stewart <info@davestewart.co.uk>
+- Deric Cain <deric.cain@gmail.com>
+- Guillaume Briday <guillaumebriday@gmail.com>
+- Jacob Wejendorp <jacob@wejendorp.dk>
+- Jim Lynch <mrdotjim@gmail.com>
+- johntron
+- Justin Beckwith <beckwith@google.com>
+- Justin Beckwith <justin.beckwith@gmail.com>
+- Khaled Garbaya <khaledgarbaya@gmail.com>
+- Lim Jing Rong <jjingrong@users.noreply.github.com>
+- Mark van den Broek <mvdnbrk@gmail.com>
+- Martti Laine <martti@codeclown.net>
+- mattridley
+- mattridley <matt.r@joinblink.com>
+- Nicolas Del Valle <nicolas.delvalle@gmail.com>
+- Nilegfx
+- pbarbiero
+- Rikki Gibson <rikkigibson@gmail.com>
+- Sako Hartounian <sakohartounian@yahoo.com>
+- Shane Fitzpatrick <fitzpasd@gmail.com>
+- Stephan Schneider <stephanschndr@gmail.com>
+- Steven <steven@ceriously.com>
+- Tim Garthwaite <tim.garthwaite@jibo.com>
+- Tim Johns <timjohns@yahoo.com>
+- Yutaro Miyazaki <yutaro@studio-rubbish.com>
+
+### 0.18.0 (Feb 19, 2018)
+
+- Adding support for UNIX Sockets when running with Node.js ([#1070](https://github.com/axios/axios/pull/1070))
+- Fixing typings ([#1177](https://github.com/axios/axios/pull/1177)):
+  - AxiosRequestConfig.proxy: allows type false
+  - AxiosProxyConfig: added auth field
+- Adding function signature in AxiosInstance interface so AxiosInstance can be invoked ([#1192](https://github.com/axios/axios/pull/1192), [#1254](https://github.com/axios/axios/pull/1254))
+- Allowing maxContentLength to pass through to redirected calls as maxBodyLength in follow-redirects config ([#1287](https://github.com/axios/axios/pull/1287))
+- Fixing configuration when using an instance - method can now be set ([#1342](https://github.com/axios/axios/pull/1342))
+
+### 0.17.1 (Nov 11, 2017)
+
+- Fixing issue with web workers ([#1160](https://github.com/axios/axios/pull/1160))
+- Allowing overriding transport ([#1080](https://github.com/axios/axios/pull/1080))
+- Updating TypeScript typings ([#1165](https://github.com/axios/axios/pull/1165), [#1125](https://github.com/axios/axios/pull/1125), [#1131](https://github.com/axios/axios/pull/1131))
+
+### 0.17.0 (Oct 21, 2017)
+
+- **BREAKING** Fixing issue with `baseURL` and interceptors ([#950](https://github.com/axios/axios/pull/950))
+- **BREAKING** Improving handing of duplicate headers ([#874](https://github.com/axios/axios/pull/874))
+- Adding support for disabling proxies ([#691](https://github.com/axios/axios/pull/691))
+- Updating TypeScript typings with generic type parameters ([#1061](https://github.com/axios/axios/pull/1061))
+
+### 0.16.2 (Jun 3, 2017)
+
+- Fixing issue with including `buffer` in bundle ([#887](https://github.com/axios/axios/pull/887))
+- Including underlying request in errors ([#830](https://github.com/axios/axios/pull/830))
+- Convert `method` to lowercase ([#930](https://github.com/axios/axios/pull/930))
+
+### 0.16.1 (Apr 8, 2017)
+
+- Improving HTTP adapter to return last request in case of redirects ([#828](https://github.com/axios/axios/pull/828))
+- Updating `follow-redirects` dependency ([#829](https://github.com/axios/axios/pull/829))
+- Adding support for passing `Buffer` in node ([#773](https://github.com/axios/axios/pull/773))
+
+### 0.16.0 (Mar 31, 2017)
+
+- **BREAKING** Removing `Promise` from axios typings in favor of built-in type declarations ([#480](https://github.com/axios/axios/issues/480))
+- Adding `options` shortcut method ([#461](https://github.com/axios/axios/pull/461))
+- Fixing issue with using `responseType: 'json'` in browsers incompatible with XHR Level 2 ([#654](https://github.com/axios/axios/pull/654))
+- Improving React Native detection ([#731](https://github.com/axios/axios/pull/731))
+- Fixing `combineURLs` to support empty `relativeURL` ([#581](https://github.com/axios/axios/pull/581))
+- Removing `PROTECTION_PREFIX` support ([#561](https://github.com/axios/axios/pull/561))
+
+### 0.15.3 (Nov 27, 2016)
+
+- Fixing issue with custom instances and global defaults ([#443](https://github.com/axios/axios/issues/443))
+- Renaming `axios.d.ts` to `index.d.ts` ([#519](https://github.com/axios/axios/issues/519))
+- Adding `get`, `head`, and `delete` to `defaults.headers` ([#509](https://github.com/axios/axios/issues/509))
+- Fixing issue with `btoa` and IE ([#507](https://github.com/axios/axios/issues/507))
+- Adding support for proxy authentication ([#483](https://github.com/axios/axios/pull/483))
+- Improving HTTP adapter to use `http` protocol by default ([#493](https://github.com/axios/axios/pull/493))
+- Fixing proxy issues ([#491](https://github.com/axios/axios/pull/491))
+
+### 0.15.2 (Oct 17, 2016)
+
+- Fixing issue with calling `cancel` after response has been received ([#482](https://github.com/axios/axios/issues/482))
+
+### 0.15.1 (Oct 14, 2016)
+
+- Fixing issue with UMD ([#485](https://github.com/axios/axios/issues/485))
+
+### 0.15.0 (Oct 10, 2016)
+
+- Adding cancellation support ([#452](https://github.com/axios/axios/pull/452))
+- Moving default adapter to global defaults ([#437](https://github.com/axios/axios/pull/437))
+- Fixing issue with `file` URI scheme ([#440](https://github.com/axios/axios/pull/440))
+- Fixing issue with `params` objects that have no prototype ([#445](https://github.com/axios/axios/pull/445))
+
+### 0.14.0 (Aug 27, 2016)
+
+- **BREAKING** Updating TypeScript definitions ([#419](https://github.com/axios/axios/pull/419))
+- **BREAKING** Replacing `agent` option with `httpAgent` and `httpsAgent` ([#387](https://github.com/axios/axios/pull/387))
+- **BREAKING** Splitting `progress` event handlers into `onUploadProgress` and `onDownloadProgress` ([#423](https://github.com/axios/axios/pull/423))
+- Adding support for `http_proxy` and `https_proxy` environment variables ([#366](https://github.com/axios/axios/pull/366))
+- Fixing issue with `auth` config option and `Authorization` header ([#397](https://github.com/axios/axios/pull/397))
+- Don't set XSRF header if `xsrfCookieName` is `null` ([#406](https://github.com/axios/axios/pull/406))
+
+### 0.13.1 (Jul 16, 2016)
+
+- Fixing issue with response data not being transformed on error ([#378](https://github.com/axios/axios/issues/378))
+
+### 0.13.0 (Jul 13, 2016)
+
+- **BREAKING** Improved error handling ([#345](https://github.com/axios/axios/pull/345))
+- **BREAKING** Response transformer now invoked in dispatcher not adapter ([10eb238](https://github.com/axios/axios/commit/10eb23865101f9347570552c04e9d6211376e25e))
+- **BREAKING** Request adapters now return a `Promise` ([157efd5](https://github.com/axios/axios/commit/157efd5615890301824e3121cc6c9d2f9b21f94a))
+- Fixing issue with `withCredentials` not being overwritten ([#343](https://github.com/axios/axios/issues/343))
+- Fixing regression with request transformer being called before request interceptor ([#352](https://github.com/axios/axios/issues/352))
+- Fixing custom instance defaults ([#341](https://github.com/axios/axios/issues/341))
+- Fixing instances created from `axios.create` to have same API as default axios ([#217](https://github.com/axios/axios/issues/217))
+
+### 0.12.0 (May 31, 2016)
+
+- Adding support for `URLSearchParams` ([#317](https://github.com/axios/axios/pull/317))
+- Adding `maxRedirects` option ([#307](https://github.com/axios/axios/pull/307))
+
+### 0.11.1 (May 17, 2016)
+
+- Fixing IE CORS support ([#313](https://github.com/axios/axios/pull/313))
+- Fixing detection of `FormData` ([#325](https://github.com/axios/axios/pull/325))
+- Adding `Axios` class to exports ([#321](https://github.com/axios/axios/pull/321))
+
+### 0.11.0 (Apr 26, 2016)
+
+- Adding support for Stream with HTTP adapter ([#296](https://github.com/axios/axios/pull/296))
+- Adding support for custom HTTP status code error ranges ([#308](https://github.com/axios/axios/pull/308))
+- Fixing issue with ArrayBuffer ([#299](https://github.com/axios/axios/pull/299))
+
+### 0.10.0 (Apr 20, 2016)
+
+- Fixing issue with some requests sending `undefined` instead of `null` ([#250](https://github.com/axios/axios/pull/250))
+- Fixing basic auth for HTTP adapter ([#252](https://github.com/axios/axios/pull/252))
+- Fixing request timeout for XHR adapter ([#227](https://github.com/axios/axios/pull/227))
+- Fixing IE8 support by using `onreadystatechange` instead of `onload` ([#249](https://github.com/axios/axios/pull/249))
+- Fixing IE9 cross domain requests ([#251](https://github.com/axios/axios/pull/251))
+- Adding `maxContentLength` option ([#275](https://github.com/axios/axios/pull/275))
+- Fixing XHR support for WebWorker environment ([#279](https://github.com/axios/axios/pull/279))
+- Adding request instance to response ([#200](https://github.com/axios/axios/pull/200))
+
+### 0.9.1 (Jan 24, 2016)
+
+- Improving handling of request timeout in node ([#124](https://github.com/axios/axios/issues/124))
+- Fixing network errors not rejecting ([#205](https://github.com/axios/axios/pull/205))
+- Fixing issue with IE rejecting on HTTP 204 ([#201](https://github.com/axios/axios/issues/201))
+- Fixing host/port when following redirects ([#198](https://github.com/axios/axios/pull/198))
+
+### 0.9.0 (Jan 18, 2016)
+
+- Adding support for custom adapters
+- Fixing Content-Type header being removed when data is false ([#195](https://github.com/axios/axios/pull/195))
+- Improving XDomainRequest implementation ([#185](https://github.com/axios/axios/pull/185))
+- Improving config merging and order of precedence ([#183](https://github.com/axios/axios/pull/183))
+- Fixing XDomainRequest support for only <= IE9 ([#182](https://github.com/axios/axios/pull/182))
+
+### 0.8.1 (Dec 14, 2015)
+
+- Adding support for passing XSRF token for cross domain requests when using `withCredentials` ([#168](https://github.com/axios/axios/pull/168))
+- Fixing error with format of basic auth header ([#178](https://github.com/axios/axios/pull/173))
+- Fixing error with JSON payloads throwing `InvalidStateError` in some cases ([#174](https://github.com/axios/axios/pull/174))
+
+### 0.8.0 (Dec 11, 2015)
+
+- Adding support for creating instances of axios ([#123](https://github.com/axios/axios/pull/123))
+- Fixing http adapter to use `Buffer` instead of `String` in case of `responseType === 'arraybuffer'` ([#128](https://github.com/axios/axios/pull/128))
+- Adding support for using custom parameter serializer with `paramsSerializer` option ([#121](https://github.com/axios/axios/pull/121))
+- Fixing issue in IE8 caused by `forEach` on `arguments` ([#127](https://github.com/axios/axios/pull/127))
+- Adding support for following redirects in node ([#146](https://github.com/axios/axios/pull/146))
+- Adding support for transparent decompression if `content-encoding` is set ([#149](https://github.com/axios/axios/pull/149))
+- Adding support for transparent XDomainRequest to handle cross domain requests in IE9 ([#140](https://github.com/axios/axios/pull/140))
+- Adding support for HTTP basic auth via Authorization header ([#167](https://github.com/axios/axios/pull/167))
+- Adding support for baseURL option ([#160](https://github.com/axios/axios/pull/160))
+
+### 0.7.0 (Sep 29, 2015)
+
+- Fixing issue with minified bundle in IE8 ([#87](https://github.com/axios/axios/pull/87))
+- Adding support for passing agent in node ([#102](https://github.com/axios/axios/pull/102))
+- Adding support for returning result from `axios.spread` for chaining ([#106](https://github.com/axios/axios/pull/106))
+- Fixing typescript definition ([#105](https://github.com/axios/axios/pull/105))
+- Fixing default timeout config for node ([#112](https://github.com/axios/axios/pull/112))
+- Adding support for use in web workers, and react-native ([#70](https://github.com/axios/axios/issue/70)), ([#98](https://github.com/axios/axios/pull/98))
+- Adding support for fetch like API `axios(url[, config])` ([#116](https://github.com/axios/axios/issues/116))
+
+### 0.6.0 (Sep 21, 2015)
+
+- Removing deprecated success/error aliases
+- Fixing issue with array params not being properly encoded ([#49](https://github.com/axios/axios/pull/49))
+- Fixing issue with User-Agent getting overridden ([#69](https://github.com/axios/axios/issues/69))
+- Adding support for timeout config ([#56](https://github.com/axios/axios/issues/56))
+- Removing es6-promise dependency
+- Fixing issue preventing `length` to be used as a parameter ([#91](https://github.com/axios/axios/pull/91))
+- Fixing issue with IE8 ([#85](https://github.com/axios/axios/pull/85))
+- Converting build to UMD
+
+### 0.5.4 (Apr 08, 2015)
+
+- Fixing issue with FormData not being sent ([#53](https://github.com/axios/axios/issues/53))
+
+### 0.5.3 (Apr 07, 2015)
+
+- Using JSON.parse unconditionally when transforming response string ([#55](https://github.com/axios/axios/issues/55))
+
+### 0.5.2 (Mar 13, 2015)
+
+- Adding support for `statusText` in response ([#46](https://github.com/axios/axios/issues/46))
+
+### 0.5.1 (Mar 10, 2015)
+
+- Fixing issue using strict mode ([#45](https://github.com/axios/axios/issues/45))
+- Fixing issue with standalone build ([#47](https://github.com/axios/axios/issues/47))
+
+### 0.5.0 (Jan 23, 2015)
+
+- Adding support for intercepetors ([#14](https://github.com/axios/axios/issues/14))
+- Updating es6-promise dependency
+
+### 0.4.2 (Dec 10, 2014)
+
+- Fixing issue with `Content-Type` when using `FormData` ([#22](https://github.com/axios/axios/issues/22))
+- Adding support for TypeScript ([#25](https://github.com/axios/axios/issues/25))
+- Fixing issue with standalone build ([#29](https://github.com/axios/axios/issues/29))
+- Fixing issue with verbs needing to be capitalized in some browsers ([#30](https://github.com/axios/axios/issues/30))
+
+### 0.4.1 (Oct 15, 2014)
+
+- Adding error handling to request for node.js ([#18](https://github.com/axios/axios/issues/18))
+
+### 0.4.0 (Oct 03, 2014)
+
+- Adding support for `ArrayBuffer` and `ArrayBufferView` ([#10](https://github.com/axios/axios/issues/10))
+- Adding support for utf-8 for node.js ([#13](https://github.com/axios/axios/issues/13))
+- Adding support for SSL for node.js ([#12](https://github.com/axios/axios/issues/12))
+- Fixing incorrect `Content-Type` header ([#9](https://github.com/axios/axios/issues/9))
+- Adding standalone build without bundled es6-promise ([#11](https://github.com/axios/axios/issues/11))
+- Deprecating `success`/`error` in favor of `then`/`catch`
+
+### 0.3.1 (Sep 16, 2014)
+
+- Fixing missing post body when using node.js ([#3](https://github.com/axios/axios/issues/3))
+
+### 0.3.0 (Sep 16, 2014)
+
+- Fixing `success` and `error` to properly receive response data as individual arguments ([#8](https://github.com/axios/axios/issues/8))
+- Updating `then` and `catch` to receive response data as a single object ([#6](https://github.com/axios/axios/issues/6))
+- Fixing issue with `all` not working ([#7](https://github.com/axios/axios/issues/7))
+
+### 0.2.2 (Sep 14, 2014)
+
+- Fixing bundling with browserify ([#4](https://github.com/axios/axios/issues/4))
+
+### 0.2.1 (Sep 12, 2014)
+
+- Fixing build problem causing ridiculous file sizes
+
+### 0.2.0 (Sep 12, 2014)
+
+- Adding support for `all` and `spread`
+- Adding support for node.js ([#1](https://github.com/axios/axios/issues/1))
+
+### 0.1.0 (Aug 29, 2014)
+
+- Initial release

+ 19 - 0
node_modules/axios/LICENSE

@@ -0,0 +1,19 @@
+Copyright (c) 2014-present Matt Zabriskie
+
+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.

+ 800 - 0
node_modules/axios/README.md

@@ -0,0 +1,800 @@
+# axios
+
+[![npm version](https://img.shields.io/npm/v/axios.svg?style=flat-square)](https://www.npmjs.org/package/axios)
+[![CDNJS](https://img.shields.io/cdnjs/v/axios.svg?style=flat-square)](https://cdnjs.com/libraries/axios)
+[![build status](https://img.shields.io/travis/axios/axios/master.svg?style=flat-square)](https://travis-ci.org/axios/axios)
+[![code coverage](https://img.shields.io/coveralls/mzabriskie/axios.svg?style=flat-square)](https://coveralls.io/r/mzabriskie/axios)
+[![install size](https://packagephobia.now.sh/badge?p=axios)](https://packagephobia.now.sh/result?p=axios)
+[![npm downloads](https://img.shields.io/npm/dm/axios.svg?style=flat-square)](http://npm-stat.com/charts.html?package=axios)
+[![gitter chat](https://img.shields.io/gitter/room/mzabriskie/axios.svg?style=flat-square)](https://gitter.im/mzabriskie/axios)
+[![code helpers](https://www.codetriage.com/axios/axios/badges/users.svg)](https://www.codetriage.com/axios/axios)
+
+Promise based HTTP client for the browser and node.js
+## Table of Contents
+
+  - [Features](#features)
+  - [Browser Support](#browser-support)
+  - [Installing](#installing)
+  - [Example](#example)
+  - [Axios API](#axios-api)
+  - [Request method aliases](#request-method-aliases)
+  - [Concurrency (Deprecated)](#concurrency-deprecated)
+  - [Creating an instance](#creating-an-instance)
+  - [Instance methods](#instance-methods)
+  - [Request Config](#request-config)
+  - [Response Schema](#response-schema)
+  - [Config Defaults](#config-defaults)
+    - [Global axios defaults](#global-axios-defaults)
+    - [Custom instance defaults](#custom-instance-defaults)
+    - [Config order of precedence](#config-order-of-precedence)
+  - [Interceptors](#interceptors)
+  - [Handling Errors](#handling-errors)
+  - [Cancellation](#cancellation)
+  - [Using application/x-www-form-urlencoded format](#using-applicationx-www-form-urlencoded-format)
+    - [Browser](#browser)
+    - [Node.js](#nodejs)
+      - [Query string](#query-string)
+      - [Form data](#form-data)
+  - [Semver](#semver)
+  - [Promises](#promises)
+  - [TypeScript](#typescript)
+  - [Resources](#resources)
+  - [Credits](#credits)
+  - [License](#license)
+
+## Features
+
+- Make [XMLHttpRequests](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) from the browser
+- Make [http](http://nodejs.org/api/http.html) requests from node.js
+- Supports the [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) API
+- Intercept request and response
+- Transform request and response data
+- Cancel requests
+- Automatic transforms for JSON data
+- Client side support for protecting against [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery)
+
+## Browser Support
+
+![Chrome](https://raw.github.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png) | ![Firefox](https://raw.github.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png) | ![Safari](https://raw.github.com/alrra/browser-logos/master/src/safari/safari_48x48.png) | ![Opera](https://raw.github.com/alrra/browser-logos/master/src/opera/opera_48x48.png) | ![Edge](https://raw.github.com/alrra/browser-logos/master/src/edge/edge_48x48.png) | ![IE](https://raw.github.com/alrra/browser-logos/master/src/archive/internet-explorer_9-11/internet-explorer_9-11_48x48.png) |
+--- | --- | --- | --- | --- | --- |
+Latest ✔ | Latest ✔ | Latest ✔ | Latest ✔ | Latest ✔ | 11 ✔ |
+
+[![Browser Matrix](https://saucelabs.com/open_sauce/build_matrix/axios.svg)](https://saucelabs.com/u/axios)
+
+## Installing
+
+Using npm:
+
+```bash
+$ npm install axios
+```
+
+Using bower:
+
+```bash
+$ bower install axios
+```
+
+Using yarn:
+
+```bash
+$ yarn add axios
+```
+
+Using jsDelivr CDN:
+
+```html
+<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
+```
+
+Using unpkg CDN:
+
+```html
+<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
+```
+
+## Example
+
+### note: CommonJS usage
+In order to gain the TypeScript typings (for intellisense / autocomplete) while using CommonJS imports with `require()` use the following approach:
+
+```js
+const axios = require('axios').default;
+
+// axios.<method> will now provide autocomplete and parameter typings
+```
+
+Performing a `GET` request
+
+```js
+const axios = require('axios');
+
+// Make a request for a user with a given ID
+axios.get('/user?ID=12345')
+  .then(function (response) {
+    // handle success
+    console.log(response);
+  })
+  .catch(function (error) {
+    // handle error
+    console.log(error);
+  })
+  .then(function () {
+    // always executed
+  });
+
+// Optionally the request above could also be done as
+axios.get('/user', {
+    params: {
+      ID: 12345
+    }
+  })
+  .then(function (response) {
+    console.log(response);
+  })
+  .catch(function (error) {
+    console.log(error);
+  })
+  .then(function () {
+    // always executed
+  });  
+
+// Want to use async/await? Add the `async` keyword to your outer function/method.
+async function getUser() {
+  try {
+    const response = await axios.get('/user?ID=12345');
+    console.log(response);
+  } catch (error) {
+    console.error(error);
+  }
+}
+```
+
+> **NOTE:** `async/await` is part of ECMAScript 2017 and is not supported in Internet
+> Explorer and older browsers, so use with caution.
+
+Performing a `POST` request
+
+```js
+axios.post('/user', {
+    firstName: 'Fred',
+    lastName: 'Flintstone'
+  })
+  .then(function (response) {
+    console.log(response);
+  })
+  .catch(function (error) {
+    console.log(error);
+  });
+```
+
+Performing multiple concurrent requests
+
+```js
+function getUserAccount() {
+  return axios.get('/user/12345');
+}
+
+function getUserPermissions() {
+  return axios.get('/user/12345/permissions');
+}
+
+Promise.all([getUserAccount(), getUserPermissions()])
+  .then(function (results) {
+    const acct = results[0];
+    const perm = results[1];
+  });
+```
+
+## axios API
+
+Requests can be made by passing the relevant config to `axios`.
+
+##### axios(config)
+
+```js
+// Send a POST request
+axios({
+  method: 'post',
+  url: '/user/12345',
+  data: {
+    firstName: 'Fred',
+    lastName: 'Flintstone'
+  }
+});
+```
+
+```js
+// GET request for remote image in node.js
+axios({
+  method: 'get',
+  url: 'http://bit.ly/2mTM3nY',
+  responseType: 'stream'
+})
+  .then(function (response) {
+    response.data.pipe(fs.createWriteStream('ada_lovelace.jpg'))
+  });
+```
+
+##### axios(url[, config])
+
+```js
+// Send a GET request (default method)
+axios('/user/12345');
+```
+
+### Request method aliases
+
+For convenience aliases have been provided for all supported request methods.
+
+##### axios.request(config)
+##### axios.get(url[, config])
+##### axios.delete(url[, config])
+##### axios.head(url[, config])
+##### axios.options(url[, config])
+##### axios.post(url[, data[, config]])
+##### axios.put(url[, data[, config]])
+##### axios.patch(url[, data[, config]])
+
+###### NOTE
+When using the alias methods `url`, `method`, and `data` properties don't need to be specified in config.
+
+### Concurrency (Deprecated)
+Please use `Promise.all` to replace the below functions.
+
+Helper functions for dealing with concurrent requests.
+
+axios.all(iterable)
+axios.spread(callback)
+
+### Creating an instance
+
+You can create a new instance of axios with a custom config.
+
+##### axios.create([config])
+
+```js
+const instance = axios.create({
+  baseURL: 'https://some-domain.com/api/',
+  timeout: 1000,
+  headers: {'X-Custom-Header': 'foobar'}
+});
+```
+
+### Instance methods
+
+The available instance methods are listed below. The specified config will be merged with the instance config.
+
+##### axios#request(config)
+##### axios#get(url[, config])
+##### axios#delete(url[, config])
+##### axios#head(url[, config])
+##### axios#options(url[, config])
+##### axios#post(url[, data[, config]])
+##### axios#put(url[, data[, config]])
+##### axios#patch(url[, data[, config]])
+##### axios#getUri([config])
+
+## Request Config
+
+These are the available config options for making requests. Only the `url` is required. Requests will default to `GET` if `method` is not specified.
+
+```js
+{
+  // `url` is the server URL that will be used for the request
+  url: '/user',
+
+  // `method` is the request method to be used when making the request
+  method: 'get', // default
+
+  // `baseURL` will be prepended to `url` unless `url` is absolute.
+  // It can be convenient to set `baseURL` for an instance of axios to pass relative URLs
+  // to methods of that instance.
+  baseURL: 'https://some-domain.com/api/',
+
+  // `transformRequest` allows changes to the request data before it is sent to the server
+  // This is only applicable for request methods 'PUT', 'POST', 'PATCH' and 'DELETE'
+  // The last function in the array must return a string or an instance of Buffer, ArrayBuffer,
+  // FormData or Stream
+  // You may modify the headers object.
+  transformRequest: [function (data, headers) {
+    // Do whatever you want to transform the data
+
+    return data;
+  }],
+
+  // `transformResponse` allows changes to the response data to be made before
+  // it is passed to then/catch
+  transformResponse: [function (data) {
+    // Do whatever you want to transform the data
+
+    return data;
+  }],
+
+  // `headers` are custom headers to be sent
+  headers: {'X-Requested-With': 'XMLHttpRequest'},
+
+  // `params` are the URL parameters to be sent with the request
+  // Must be a plain object or a URLSearchParams object
+  params: {
+    ID: 12345
+  },
+
+  // `paramsSerializer` is an optional function in charge of serializing `params`
+  // (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
+  paramsSerializer: function (params) {
+    return Qs.stringify(params, {arrayFormat: 'brackets'})
+  },
+
+  // `data` is the data to be sent as the request body
+  // Only applicable for request methods 'PUT', 'POST', 'DELETE , and 'PATCH'
+  // When no `transformRequest` is set, must be of one of the following types:
+  // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
+  // - Browser only: FormData, File, Blob
+  // - Node only: Stream, Buffer
+  data: {
+    firstName: 'Fred'
+  },
+  
+  // syntax alternative to send data into the body
+  // method post
+  // only the value is sent, not the key
+  data: 'Country=Brasil&City=Belo Horizonte',
+
+  // `timeout` specifies the number of milliseconds before the request times out.
+  // If the request takes longer than `timeout`, the request will be aborted.
+  timeout: 1000, // default is `0` (no timeout)
+
+  // `withCredentials` indicates whether or not cross-site Access-Control requests
+  // should be made using credentials
+  withCredentials: false, // default
+
+  // `adapter` allows custom handling of requests which makes testing easier.
+  // Return a promise and supply a valid response (see lib/adapters/README.md).
+  adapter: function (config) {
+    /* ... */
+  },
+
+  // `auth` indicates that HTTP Basic auth should be used, and supplies credentials.
+  // This will set an `Authorization` header, overwriting any existing
+  // `Authorization` custom headers you have set using `headers`.
+  // Please note that only HTTP Basic auth is configurable through this parameter.
+  // For Bearer tokens and such, use `Authorization` custom headers instead.
+  auth: {
+    username: 'janedoe',
+    password: 's00pers3cret'
+  },
+
+  // `responseType` indicates the type of data that the server will respond with
+  // options are: 'arraybuffer', 'document', 'json', 'text', 'stream'
+  //   browser only: 'blob'
+  responseType: 'json', // default
+
+  // `responseEncoding` indicates encoding to use for decoding responses (Node.js only)
+  // Note: Ignored for `responseType` of 'stream' or client-side requests
+  responseEncoding: 'utf8', // default
+
+  // `xsrfCookieName` is the name of the cookie to use as a value for xsrf token
+  xsrfCookieName: 'XSRF-TOKEN', // default
+
+  // `xsrfHeaderName` is the name of the http header that carries the xsrf token value
+  xsrfHeaderName: 'X-XSRF-TOKEN', // default
+
+  // `onUploadProgress` allows handling of progress events for uploads
+  // browser only
+  onUploadProgress: function (progressEvent) {
+    // Do whatever you want with the native progress event
+  },
+
+  // `onDownloadProgress` allows handling of progress events for downloads
+  // browser only
+  onDownloadProgress: function (progressEvent) {
+    // Do whatever you want with the native progress event
+  },
+
+  // `maxContentLength` defines the max size of the http response content in bytes allowed in node.js
+  maxContentLength: 2000,
+
+  // `maxBodyLength` (Node only option) defines the max size of the http request content in bytes allowed
+  maxBodyLength: 2000,
+
+  // `validateStatus` defines whether to resolve or reject the promise for a given
+  // HTTP response status code. If `validateStatus` returns `true` (or is set to `null`
+  // or `undefined`), the promise will be resolved; otherwise, the promise will be
+  // rejected.
+  validateStatus: function (status) {
+    return status >= 200 && status < 300; // default
+  },
+
+  // `maxRedirects` defines the maximum number of redirects to follow in node.js.
+  // If set to 0, no redirects will be followed.
+  maxRedirects: 5, // default
+
+  // `socketPath` defines a UNIX Socket to be used in node.js.
+  // e.g. '/var/run/docker.sock' to send requests to the docker daemon.
+  // Only either `socketPath` or `proxy` can be specified.
+  // If both are specified, `socketPath` is used.
+  socketPath: null, // default
+
+  // `httpAgent` and `httpsAgent` define a custom agent to be used when performing http
+  // and https requests, respectively, in node.js. This allows options to be added like
+  // `keepAlive` that are not enabled by default.
+  httpAgent: new http.Agent({ keepAlive: true }),
+  httpsAgent: new https.Agent({ keepAlive: true }),
+
+  // `proxy` defines the hostname, port, and protocol of the proxy server.
+  // You can also define your proxy using the conventional `http_proxy` and
+  // `https_proxy` environment variables. If you are using environment variables
+  // for your proxy configuration, you can also define a `no_proxy` environment
+  // variable as a comma-separated list of domains that should not be proxied.
+  // Use `false` to disable proxies, ignoring environment variables.
+  // `auth` indicates that HTTP Basic auth should be used to connect to the proxy, and
+  // supplies credentials.
+  // This will set an `Proxy-Authorization` header, overwriting any existing
+  // `Proxy-Authorization` custom headers you have set using `headers`.
+  // If the proxy server uses HTTPS, then you must set the protocol to `https`. 
+  proxy: {
+    protocol: 'https',
+    host: '127.0.0.1',
+    port: 9000,
+    auth: {
+      username: 'mikeymike',
+      password: 'rapunz3l'
+    }
+  },
+
+  // `cancelToken` specifies a cancel token that can be used to cancel the request
+  // (see Cancellation section below for details)
+  cancelToken: new CancelToken(function (cancel) {
+  }),
+
+  // `decompress` indicates whether or not the response body should be decompressed 
+  // automatically. If set to `true` will also remove the 'content-encoding' header 
+  // from the responses objects of all decompressed responses
+  // - Node only (XHR cannot turn off decompression)
+  decompress: true // default
+
+}
+```
+
+## Response Schema
+
+The response for a request contains the following information.
+
+```js
+{
+  // `data` is the response that was provided by the server
+  data: {},
+
+  // `status` is the HTTP status code from the server response
+  status: 200,
+
+  // `statusText` is the HTTP status message from the server response
+  statusText: 'OK',
+
+  // `headers` the HTTP headers that the server responded with
+  // All header names are lower cased and can be accessed using the bracket notation.
+  // Example: `response.headers['content-type']`
+  headers: {},
+
+  // `config` is the config that was provided to `axios` for the request
+  config: {},
+
+  // `request` is the request that generated this response
+  // It is the last ClientRequest instance in node.js (in redirects)
+  // and an XMLHttpRequest instance in the browser
+  request: {}
+}
+```
+
+When using `then`, you will receive the response as follows:
+
+```js
+axios.get('/user/12345')
+  .then(function (response) {
+    console.log(response.data);
+    console.log(response.status);
+    console.log(response.statusText);
+    console.log(response.headers);
+    console.log(response.config);
+  });
+```
+
+When using `catch`, or passing a [rejection callback](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) as second parameter of `then`, the response will be available through the `error` object as explained in the [Handling Errors](#handling-errors) section.
+
+## Config Defaults
+
+You can specify config defaults that will be applied to every request.
+
+### Global axios defaults
+
+```js
+axios.defaults.baseURL = 'https://api.example.com';
+axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
+axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
+```
+
+### Custom instance defaults
+
+```js
+// Set config defaults when creating the instance
+const instance = axios.create({
+  baseURL: 'https://api.example.com'
+});
+
+// Alter defaults after instance has been created
+instance.defaults.headers.common['Authorization'] = AUTH_TOKEN;
+```
+
+### Config order of precedence
+
+Config will be merged with an order of precedence. The order is library defaults found in [lib/defaults.js](https://github.com/axios/axios/blob/master/lib/defaults.js#L28), then `defaults` property of the instance, and finally `config` argument for the request. The latter will take precedence over the former. Here's an example.
+
+```js
+// Create an instance using the config defaults provided by the library
+// At this point the timeout config value is `0` as is the default for the library
+const instance = axios.create();
+
+// Override timeout default for the library
+// Now all requests using this instance will wait 2.5 seconds before timing out
+instance.defaults.timeout = 2500;
+
+// Override timeout for this request as it's known to take a long time
+instance.get('/longRequest', {
+  timeout: 5000
+});
+```
+
+## Interceptors
+
+You can intercept requests or responses before they are handled by `then` or `catch`.
+
+```js
+// Add a request interceptor
+axios.interceptors.request.use(function (config) {
+    // Do something before request is sent
+    return config;
+  }, function (error) {
+    // Do something with request error
+    return Promise.reject(error);
+  });
+
+// Add a response interceptor
+axios.interceptors.response.use(function (response) {
+    // Any status code that lie within the range of 2xx cause this function to trigger
+    // Do something with response data
+    return response;
+  }, function (error) {
+    // Any status codes that falls outside the range of 2xx cause this function to trigger
+    // Do something with response error
+    return Promise.reject(error);
+  });
+```
+
+If you need to remove an interceptor later you can.
+
+```js
+const myInterceptor = axios.interceptors.request.use(function () {/*...*/});
+axios.interceptors.request.eject(myInterceptor);
+```
+
+You can add interceptors to a custom instance of axios.
+
+```js
+const instance = axios.create();
+instance.interceptors.request.use(function () {/*...*/});
+```
+
+## Handling Errors
+
+```js
+axios.get('/user/12345')
+  .catch(function (error) {
+    if (error.response) {
+      // The request was made and the server responded with a status code
+      // that falls out of the range of 2xx
+      console.log(error.response.data);
+      console.log(error.response.status);
+      console.log(error.response.headers);
+    } else if (error.request) {
+      // The request was made but no response was received
+      // `error.request` is an instance of XMLHttpRequest in the browser and an instance of
+      // http.ClientRequest in node.js
+      console.log(error.request);
+    } else {
+      // Something happened in setting up the request that triggered an Error
+      console.log('Error', error.message);
+    }
+    console.log(error.config);
+  });
+```
+
+Using the `validateStatus` config option, you can define HTTP code(s) that should throw an error.
+
+```js
+axios.get('/user/12345', {
+  validateStatus: function (status) {
+    return status < 500; // Resolve only if the status code is less than 500
+  }
+})
+```
+
+Using `toJSON` you get an object with more information about the HTTP error.
+
+```js
+axios.get('/user/12345')
+  .catch(function (error) {
+    console.log(error.toJSON());
+  });
+```
+
+## Cancellation
+
+You can cancel a request using a *cancel token*.
+
+> The axios cancel token API is based on the withdrawn [cancelable promises proposal](https://github.com/tc39/proposal-cancelable-promises).
+
+You can create a cancel token using the `CancelToken.source` factory as shown below:
+
+```js
+const CancelToken = axios.CancelToken;
+const source = CancelToken.source();
+
+axios.get('/user/12345', {
+  cancelToken: source.token
+}).catch(function (thrown) {
+  if (axios.isCancel(thrown)) {
+    console.log('Request canceled', thrown.message);
+  } else {
+    // handle error
+  }
+});
+
+axios.post('/user/12345', {
+  name: 'new name'
+}, {
+  cancelToken: source.token
+})
+
+// cancel the request (the message parameter is optional)
+source.cancel('Operation canceled by the user.');
+```
+
+You can also create a cancel token by passing an executor function to the `CancelToken` constructor:
+
+```js
+const CancelToken = axios.CancelToken;
+let cancel;
+
+axios.get('/user/12345', {
+  cancelToken: new CancelToken(function executor(c) {
+    // An executor function receives a cancel function as a parameter
+    cancel = c;
+  })
+});
+
+// cancel the request
+cancel();
+```
+
+> Note: you can cancel several requests with the same cancel token.
+
+## Using application/x-www-form-urlencoded format
+
+By default, axios serializes JavaScript objects to `JSON`. To send data in the `application/x-www-form-urlencoded` format instead, you can use one of the following options.
+
+### Browser
+
+In a browser, you can use the [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) API as follows:
+
+```js
+const params = new URLSearchParams();
+params.append('param1', 'value1');
+params.append('param2', 'value2');
+axios.post('/foo', params);
+```
+
+> Note that `URLSearchParams` is not supported by all browsers (see [caniuse.com](http://www.caniuse.com/#feat=urlsearchparams)), but there is a [polyfill](https://github.com/WebReflection/url-search-params) available (make sure to polyfill the global environment).
+
+Alternatively, you can encode data using the [`qs`](https://github.com/ljharb/qs) library:
+
+```js
+const qs = require('qs');
+axios.post('/foo', qs.stringify({ 'bar': 123 }));
+```
+
+Or in another way (ES6),
+
+```js
+import qs from 'qs';
+const data = { 'bar': 123 };
+const options = {
+  method: 'POST',
+  headers: { 'content-type': 'application/x-www-form-urlencoded' },
+  data: qs.stringify(data),
+  url,
+};
+axios(options);
+```
+
+### Node.js
+
+#### Query string
+
+In node.js, you can use the [`querystring`](https://nodejs.org/api/querystring.html) module as follows:
+
+```js
+const querystring = require('querystring');
+axios.post('http://something.com/', querystring.stringify({ foo: 'bar' }));
+```
+
+or ['URLSearchParams'](https://nodejs.org/api/url.html#url_class_urlsearchparams) from ['url module'](https://nodejs.org/api/url.html) as follows:
+
+```js
+const url = require('url');
+const params = new url.URLSearchParams({ foo: 'bar' });
+axios.post('http://something.com/', params.toString());
+```
+
+You can also use the [`qs`](https://github.com/ljharb/qs) library.
+
+###### NOTE
+The `qs` library is preferable if you need to stringify nested objects, as the `querystring` method has known issues with that use case (https://github.com/nodejs/node-v0.x-archive/issues/1665).
+
+#### Form data
+
+In node.js, you can use the [`form-data`](https://github.com/form-data/form-data) library as follows:
+
+```js
+const FormData = require('form-data');
+ 
+const form = new FormData();
+form.append('my_field', 'my value');
+form.append('my_buffer', new Buffer(10));
+form.append('my_file', fs.createReadStream('/foo/bar.jpg'));
+
+axios.post('https://example.com', form, { headers: form.getHeaders() })
+```
+
+Alternatively, use an interceptor:
+
+```js
+axios.interceptors.request.use(config => {
+  if (config.data instanceof FormData) {
+    Object.assign(config.headers, config.data.getHeaders());
+  }
+  return config;
+});
+```
+
+## Semver
+
+Until axios reaches a `1.0` release, breaking changes will be released with a new minor version. For example `0.5.1`, and `0.5.4` will have the same API, but `0.6.0` will have breaking changes.
+
+## Promises
+
+axios depends on a native ES6 Promise implementation to be [supported](http://caniuse.com/promises).
+If your environment doesn't support ES6 Promises, you can [polyfill](https://github.com/jakearchibald/es6-promise).
+
+## TypeScript
+axios includes [TypeScript](http://typescriptlang.org) definitions.
+```typescript
+import axios from 'axios';
+axios.get('/user?ID=12345');
+```
+
+## Resources
+
+* [Changelog](https://github.com/axios/axios/blob/master/CHANGELOG.md)
+* [Upgrade Guide](https://github.com/axios/axios/blob/master/UPGRADE_GUIDE.md)
+* [Ecosystem](https://github.com/axios/axios/blob/master/ECOSYSTEM.md)
+* [Contributing Guide](https://github.com/axios/axios/blob/master/CONTRIBUTING.md)
+* [Code of Conduct](https://github.com/axios/axios/blob/master/CODE_OF_CONDUCT.md)
+
+## Credits
+
+axios is heavily inspired by the [$http service](https://docs.angularjs.org/api/ng/service/$http) provided in [Angular](https://angularjs.org/). Ultimately axios is an effort to provide a standalone `$http`-like service for use outside of Angular.
+
+## License
+
+[MIT](LICENSE)

+ 162 - 0
node_modules/axios/UPGRADE_GUIDE.md

@@ -0,0 +1,162 @@
+# Upgrade Guide
+
+### 0.15.x -> 0.16.0
+
+#### `Promise` Type Declarations
+
+The `Promise` type declarations have been removed from the axios typings in favor of the built-in type declarations. If you use axios in a TypeScript project that targets `ES5`, please make sure to include the `es2015.promise` lib. Please see [this post](https://blog.mariusschulz.com/2016/11/25/typescript-2-0-built-in-type-declarations) for details.
+
+### 0.13.x -> 0.14.0
+
+#### TypeScript Definitions
+
+The axios TypeScript definitions have been updated to match the axios API and use the ES2015 module syntax.
+
+Please use the following `import` statement to import axios in TypeScript:
+
+```typescript
+import axios from 'axios';
+
+axios.get('/foo')
+  .then(response => console.log(response))
+  .catch(error => console.log(error));
+```
+
+#### `agent` Config Option
+
+The `agent` config option has been replaced with two new options: `httpAgent` and `httpsAgent`. Please use them instead.
+
+```js
+{
+  // Define a custom agent for HTTP
+  httpAgent: new http.Agent({ keepAlive: true }),
+  // Define a custom agent for HTTPS
+  httpsAgent: new https.Agent({ keepAlive: true })
+}
+```
+
+#### `progress` Config Option
+
+The `progress` config option has been replaced with the `onUploadProgress` and `onDownloadProgress` options.
+
+```js
+{
+  // Define a handler for upload progress events
+  onUploadProgress: function (progressEvent) {
+    // ...
+  },
+
+  // Define a handler for download progress events
+  onDownloadProgress: function (progressEvent) {
+    // ...
+  }
+}
+```
+
+### 0.12.x -> 0.13.0
+
+The `0.13.0` release contains several changes to custom adapters and error handling.
+
+#### Error Handling
+
+Previous to this release an error could either be a server response with bad status code or an actual `Error`. With this release Promise will always reject with an `Error`. In the case that a response was received, the `Error` will also include the response.
+
+```js
+axios.get('/user/12345')
+  .catch((error) => {
+    console.log(error.message);
+    console.log(error.code); // Not always specified
+    console.log(error.config); // The config that was used to make the request
+    console.log(error.response); // Only available if response was received from the server
+  });
+```
+
+#### Request Adapters
+
+This release changes a few things about how request adapters work. Please take note if you are using your own custom adapter.
+
+1. Response transformer is now called outside of adapter.
+2. Request adapter returns a `Promise`.
+
+This means that you no longer need to invoke `transformData` on response data. You will also no longer receive `resolve` and `reject` as arguments in your adapter.
+
+Previous code:
+
+```js
+function myAdapter(resolve, reject, config) {
+  var response = {
+    data: transformData(
+      responseData,
+      responseHeaders,
+      config.transformResponse
+    ),
+    status: request.status,
+    statusText: request.statusText,
+    headers: responseHeaders
+  };
+  settle(resolve, reject, response);
+}
+```
+
+New code:
+
+```js
+function myAdapter(config) {
+  return new Promise(function (resolve, reject) {
+    var response = {
+      data: responseData,
+      status: request.status,
+      statusText: request.statusText,
+      headers: responseHeaders
+    };
+    settle(resolve, reject, response);
+  });
+}
+```
+
+See the related commits for more details:
+- [Response transformers](https://github.com/axios/axios/commit/10eb23865101f9347570552c04e9d6211376e25e)
+- [Request adapter Promise](https://github.com/axios/axios/commit/157efd5615890301824e3121cc6c9d2f9b21f94a)
+
+### 0.5.x -> 0.6.0
+
+The `0.6.0` release contains mostly bug fixes, but there are a couple things to be aware of when upgrading.
+
+#### ES6 Promise Polyfill
+
+Up until the `0.6.0` release ES6 `Promise` was being polyfilled using [es6-promise](https://github.com/jakearchibald/es6-promise). With this release, the polyfill has been removed, and you will need to supply it yourself if your environment needs it.
+
+```js
+require('es6-promise').polyfill();
+var axios = require('axios');
+```
+
+This will polyfill the global environment, and only needs to be done once.
+
+#### `axios.success`/`axios.error`
+
+The `success`, and `error` aliases were deprecated in [0.4.0](https://github.com/axios/axios/blob/master/CHANGELOG.md#040-oct-03-2014). As of this release they have been removed entirely. Instead please use `axios.then`, and `axios.catch` respectively.
+
+```js
+axios.get('some/url')
+  .then(function (res) {
+    /* ... */
+  })
+  .catch(function (err) {
+    /* ... */
+  });
+```
+
+#### UMD
+
+Previous versions of axios shipped with an AMD, CommonJS, and Global build. This has all been rolled into a single UMD build.
+
+```js
+// AMD
+require(['bower_components/axios/dist/axios'], function (axios) {
+  /* ... */
+});
+
+// CommonJS
+var axios = require('axios/dist/axios');
+```

+ 1756 - 0
node_modules/axios/dist/axios.js

@@ -0,0 +1,1756 @@
+/* axios v0.21.1 | (c) 2020 by Matt Zabriskie */
+(function webpackUniversalModuleDefinition(root, factory) {
+	if(typeof exports === 'object' && typeof module === 'object')
+		module.exports = factory();
+	else if(typeof define === 'function' && define.amd)
+		define([], factory);
+	else if(typeof exports === 'object')
+		exports["axios"] = factory();
+	else
+		root["axios"] = factory();
+})(this, function() {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId])
+/******/ 			return installedModules[moduleId].exports;
+/******/
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			exports: {},
+/******/ 			id: moduleId,
+/******/ 			loaded: false
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.loaded = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules;
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = "";
+/******/
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(0);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	module.exports = __webpack_require__(1);
+
+/***/ }),
+/* 1 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	var utils = __webpack_require__(2);
+	var bind = __webpack_require__(3);
+	var Axios = __webpack_require__(4);
+	var mergeConfig = __webpack_require__(22);
+	var defaults = __webpack_require__(10);
+	
+	/**
+	 * Create an instance of Axios
+	 *
+	 * @param {Object} defaultConfig The default config for the instance
+	 * @return {Axios} A new instance of Axios
+	 */
+	function createInstance(defaultConfig) {
+	  var context = new Axios(defaultConfig);
+	  var instance = bind(Axios.prototype.request, context);
+	
+	  // Copy axios.prototype to instance
+	  utils.extend(instance, Axios.prototype, context);
+	
+	  // Copy context to instance
+	  utils.extend(instance, context);
+	
+	  return instance;
+	}
+	
+	// Create the default instance to be exported
+	var axios = createInstance(defaults);
+	
+	// Expose Axios class to allow class inheritance
+	axios.Axios = Axios;
+	
+	// Factory for creating new instances
+	axios.create = function create(instanceConfig) {
+	  return createInstance(mergeConfig(axios.defaults, instanceConfig));
+	};
+	
+	// Expose Cancel & CancelToken
+	axios.Cancel = __webpack_require__(23);
+	axios.CancelToken = __webpack_require__(24);
+	axios.isCancel = __webpack_require__(9);
+	
+	// Expose all/spread
+	axios.all = function all(promises) {
+	  return Promise.all(promises);
+	};
+	axios.spread = __webpack_require__(25);
+	
+	// Expose isAxiosError
+	axios.isAxiosError = __webpack_require__(26);
+	
+	module.exports = axios;
+	
+	// Allow use of default import syntax in TypeScript
+	module.exports.default = axios;
+
+
+/***/ }),
+/* 2 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	var bind = __webpack_require__(3);
+	
+	/*global toString:true*/
+	
+	// utils is a library of generic helper functions non-specific to axios
+	
+	var toString = Object.prototype.toString;
+	
+	/**
+	 * Determine if a value is an Array
+	 *
+	 * @param {Object} val The value to test
+	 * @returns {boolean} True if value is an Array, otherwise false
+	 */
+	function isArray(val) {
+	  return toString.call(val) === '[object Array]';
+	}
+	
+	/**
+	 * Determine if a value is undefined
+	 *
+	 * @param {Object} val The value to test
+	 * @returns {boolean} True if the value is undefined, otherwise false
+	 */
+	function isUndefined(val) {
+	  return typeof val === 'undefined';
+	}
+	
+	/**
+	 * Determine if a value is a Buffer
+	 *
+	 * @param {Object} val The value to test
+	 * @returns {boolean} True if value is a Buffer, otherwise false
+	 */
+	function isBuffer(val) {
+	  return val !== null && !isUndefined(val) && val.constructor !== null && !isUndefined(val.constructor)
+	    && typeof val.constructor.isBuffer === 'function' && val.constructor.isBuffer(val);
+	}
+	
+	/**
+	 * Determine if a value is an ArrayBuffer
+	 *
+	 * @param {Object} val The value to test
+	 * @returns {boolean} True if value is an ArrayBuffer, otherwise false
+	 */
+	function isArrayBuffer(val) {
+	  return toString.call(val) === '[object ArrayBuffer]';
+	}
+	
+	/**
+	 * Determine if a value is a FormData
+	 *
+	 * @param {Object} val The value to test
+	 * @returns {boolean} True if value is an FormData, otherwise false
+	 */
+	function isFormData(val) {
+	  return (typeof FormData !== 'undefined') && (val instanceof FormData);
+	}
+	
+	/**
+	 * Determine if a value is a view on an ArrayBuffer
+	 *
+	 * @param {Object} val The value to test
+	 * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false
+	 */
+	function isArrayBufferView(val) {
+	  var result;
+	  if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) {
+	    result = ArrayBuffer.isView(val);
+	  } else {
+	    result = (val) && (val.buffer) && (val.buffer instanceof ArrayBuffer);
+	  }
+	  return result;
+	}
+	
+	/**
+	 * Determine if a value is a String
+	 *
+	 * @param {Object} val The value to test
+	 * @returns {boolean} True if value is a String, otherwise false
+	 */
+	function isString(val) {
+	  return typeof val === 'string';
+	}
+	
+	/**
+	 * Determine if a value is a Number
+	 *
+	 * @param {Object} val The value to test
+	 * @returns {boolean} True if value is a Number, otherwise false
+	 */
+	function isNumber(val) {
+	  return typeof val === 'number';
+	}
+	
+	/**
+	 * Determine if a value is an Object
+	 *
+	 * @param {Object} val The value to test
+	 * @returns {boolean} True if value is an Object, otherwise false
+	 */
+	function isObject(val) {
+	  return val !== null && typeof val === 'object';
+	}
+	
+	/**
+	 * Determine if a value is a plain Object
+	 *
+	 * @param {Object} val The value to test
+	 * @return {boolean} True if value is a plain Object, otherwise false
+	 */
+	function isPlainObject(val) {
+	  if (toString.call(val) !== '[object Object]') {
+	    return false;
+	  }
+	
+	  var prototype = Object.getPrototypeOf(val);
+	  return prototype === null || prototype === Object.prototype;
+	}
+	
+	/**
+	 * Determine if a value is a Date
+	 *
+	 * @param {Object} val The value to test
+	 * @returns {boolean} True if value is a Date, otherwise false
+	 */
+	function isDate(val) {
+	  return toString.call(val) === '[object Date]';
+	}
+	
+	/**
+	 * Determine if a value is a File
+	 *
+	 * @param {Object} val The value to test
+	 * @returns {boolean} True if value is a File, otherwise false
+	 */
+	function isFile(val) {
+	  return toString.call(val) === '[object File]';
+	}
+	
+	/**
+	 * Determine if a value is a Blob
+	 *
+	 * @param {Object} val The value to test
+	 * @returns {boolean} True if value is a Blob, otherwise false
+	 */
+	function isBlob(val) {
+	  return toString.call(val) === '[object Blob]';
+	}
+	
+	/**
+	 * Determine if a value is a Function
+	 *
+	 * @param {Object} val The value to test
+	 * @returns {boolean} True if value is a Function, otherwise false
+	 */
+	function isFunction(val) {
+	  return toString.call(val) === '[object Function]';
+	}
+	
+	/**
+	 * Determine if a value is a Stream
+	 *
+	 * @param {Object} val The value to test
+	 * @returns {boolean} True if value is a Stream, otherwise false
+	 */
+	function isStream(val) {
+	  return isObject(val) && isFunction(val.pipe);
+	}
+	
+	/**
+	 * Determine if a value is a URLSearchParams object
+	 *
+	 * @param {Object} val The value to test
+	 * @returns {boolean} True if value is a URLSearchParams object, otherwise false
+	 */
+	function isURLSearchParams(val) {
+	  return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams;
+	}
+	
+	/**
+	 * Trim excess whitespace off the beginning and end of a string
+	 *
+	 * @param {String} str The String to trim
+	 * @returns {String} The String freed of excess whitespace
+	 */
+	function trim(str) {
+	  return str.replace(/^\s*/, '').replace(/\s*$/, '');
+	}
+	
+	/**
+	 * Determine if we're running in a standard browser environment
+	 *
+	 * This allows axios to run in a web worker, and react-native.
+	 * Both environments support XMLHttpRequest, but not fully standard globals.
+	 *
+	 * web workers:
+	 *  typeof window -> undefined
+	 *  typeof document -> undefined
+	 *
+	 * react-native:
+	 *  navigator.product -> 'ReactNative'
+	 * nativescript
+	 *  navigator.product -> 'NativeScript' or 'NS'
+	 */
+	function isStandardBrowserEnv() {
+	  if (typeof navigator !== 'undefined' && (navigator.product === 'ReactNative' ||
+	                                           navigator.product === 'NativeScript' ||
+	                                           navigator.product === 'NS')) {
+	    return false;
+	  }
+	  return (
+	    typeof window !== 'undefined' &&
+	    typeof document !== 'undefined'
+	  );
+	}
+	
+	/**
+	 * Iterate over an Array or an Object invoking a function for each item.
+	 *
+	 * If `obj` is an Array callback will be called passing
+	 * the value, index, and complete array for each item.
+	 *
+	 * If 'obj' is an Object callback will be called passing
+	 * the value, key, and complete object for each property.
+	 *
+	 * @param {Object|Array} obj The object to iterate
+	 * @param {Function} fn The callback to invoke for each item
+	 */
+	function forEach(obj, fn) {
+	  // Don't bother if no value provided
+	  if (obj === null || typeof obj === 'undefined') {
+	    return;
+	  }
+	
+	  // Force an array if not already something iterable
+	  if (typeof obj !== 'object') {
+	    /*eslint no-param-reassign:0*/
+	    obj = [obj];
+	  }
+	
+	  if (isArray(obj)) {
+	    // Iterate over array values
+	    for (var i = 0, l = obj.length; i < l; i++) {
+	      fn.call(null, obj[i], i, obj);
+	    }
+	  } else {
+	    // Iterate over object keys
+	    for (var key in obj) {
+	      if (Object.prototype.hasOwnProperty.call(obj, key)) {
+	        fn.call(null, obj[key], key, obj);
+	      }
+	    }
+	  }
+	}
+	
+	/**
+	 * Accepts varargs expecting each argument to be an object, then
+	 * immutably merges the properties of each object and returns result.
+	 *
+	 * When multiple objects contain the same key the later object in
+	 * the arguments list will take precedence.
+	 *
+	 * Example:
+	 *
+	 * ```js
+	 * var result = merge({foo: 123}, {foo: 456});
+	 * console.log(result.foo); // outputs 456
+	 * ```
+	 *
+	 * @param {Object} obj1 Object to merge
+	 * @returns {Object} Result of all merge properties
+	 */
+	function merge(/* obj1, obj2, obj3, ... */) {
+	  var result = {};
+	  function assignValue(val, key) {
+	    if (isPlainObject(result[key]) && isPlainObject(val)) {
+	      result[key] = merge(result[key], val);
+	    } else if (isPlainObject(val)) {
+	      result[key] = merge({}, val);
+	    } else if (isArray(val)) {
+	      result[key] = val.slice();
+	    } else {
+	      result[key] = val;
+	    }
+	  }
+	
+	  for (var i = 0, l = arguments.length; i < l; i++) {
+	    forEach(arguments[i], assignValue);
+	  }
+	  return result;
+	}
+	
+	/**
+	 * Extends object a by mutably adding to it the properties of object b.
+	 *
+	 * @param {Object} a The object to be extended
+	 * @param {Object} b The object to copy properties from
+	 * @param {Object} thisArg The object to bind function to
+	 * @return {Object} The resulting value of object a
+	 */
+	function extend(a, b, thisArg) {
+	  forEach(b, function assignValue(val, key) {
+	    if (thisArg && typeof val === 'function') {
+	      a[key] = bind(val, thisArg);
+	    } else {
+	      a[key] = val;
+	    }
+	  });
+	  return a;
+	}
+	
+	/**
+	 * Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)
+	 *
+	 * @param {string} content with BOM
+	 * @return {string} content value without BOM
+	 */
+	function stripBOM(content) {
+	  if (content.charCodeAt(0) === 0xFEFF) {
+	    content = content.slice(1);
+	  }
+	  return content;
+	}
+	
+	module.exports = {
+	  isArray: isArray,
+	  isArrayBuffer: isArrayBuffer,
+	  isBuffer: isBuffer,
+	  isFormData: isFormData,
+	  isArrayBufferView: isArrayBufferView,
+	  isString: isString,
+	  isNumber: isNumber,
+	  isObject: isObject,
+	  isPlainObject: isPlainObject,
+	  isUndefined: isUndefined,
+	  isDate: isDate,
+	  isFile: isFile,
+	  isBlob: isBlob,
+	  isFunction: isFunction,
+	  isStream: isStream,
+	  isURLSearchParams: isURLSearchParams,
+	  isStandardBrowserEnv: isStandardBrowserEnv,
+	  forEach: forEach,
+	  merge: merge,
+	  extend: extend,
+	  trim: trim,
+	  stripBOM: stripBOM
+	};
+
+
+/***/ }),
+/* 3 */
+/***/ (function(module, exports) {
+
+	'use strict';
+	
+	module.exports = function bind(fn, thisArg) {
+	  return function wrap() {
+	    var args = new Array(arguments.length);
+	    for (var i = 0; i < args.length; i++) {
+	      args[i] = arguments[i];
+	    }
+	    return fn.apply(thisArg, args);
+	  };
+	};
+
+
+/***/ }),
+/* 4 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	var utils = __webpack_require__(2);
+	var buildURL = __webpack_require__(5);
+	var InterceptorManager = __webpack_require__(6);
+	var dispatchRequest = __webpack_require__(7);
+	var mergeConfig = __webpack_require__(22);
+	
+	/**
+	 * Create a new instance of Axios
+	 *
+	 * @param {Object} instanceConfig The default config for the instance
+	 */
+	function Axios(instanceConfig) {
+	  this.defaults = instanceConfig;
+	  this.interceptors = {
+	    request: new InterceptorManager(),
+	    response: new InterceptorManager()
+	  };
+	}
+	
+	/**
+	 * Dispatch a request
+	 *
+	 * @param {Object} config The config specific for this request (merged with this.defaults)
+	 */
+	Axios.prototype.request = function request(config) {
+	  /*eslint no-param-reassign:0*/
+	  // Allow for axios('example/url'[, config]) a la fetch API
+	  if (typeof config === 'string') {
+	    config = arguments[1] || {};
+	    config.url = arguments[0];
+	  } else {
+	    config = config || {};
+	  }
+	
+	  config = mergeConfig(this.defaults, config);
+	
+	  // Set config.method
+	  if (config.method) {
+	    config.method = config.method.toLowerCase();
+	  } else if (this.defaults.method) {
+	    config.method = this.defaults.method.toLowerCase();
+	  } else {
+	    config.method = 'get';
+	  }
+	
+	  // Hook up interceptors middleware
+	  var chain = [dispatchRequest, undefined];
+	  var promise = Promise.resolve(config);
+	
+	  this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
+	    chain.unshift(interceptor.fulfilled, interceptor.rejected);
+	  });
+	
+	  this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
+	    chain.push(interceptor.fulfilled, interceptor.rejected);
+	  });
+	
+	  while (chain.length) {
+	    promise = promise.then(chain.shift(), chain.shift());
+	  }
+	
+	  return promise;
+	};
+	
+	Axios.prototype.getUri = function getUri(config) {
+	  config = mergeConfig(this.defaults, config);
+	  return buildURL(config.url, config.params, config.paramsSerializer).replace(/^\?/, '');
+	};
+	
+	// Provide aliases for supported request methods
+	utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {
+	  /*eslint func-names:0*/
+	  Axios.prototype[method] = function(url, config) {
+	    return this.request(mergeConfig(config || {}, {
+	      method: method,
+	      url: url,
+	      data: (config || {}).data
+	    }));
+	  };
+	});
+	
+	utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
+	  /*eslint func-names:0*/
+	  Axios.prototype[method] = function(url, data, config) {
+	    return this.request(mergeConfig(config || {}, {
+	      method: method,
+	      url: url,
+	      data: data
+	    }));
+	  };
+	});
+	
+	module.exports = Axios;
+
+
+/***/ }),
+/* 5 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	var utils = __webpack_require__(2);
+	
+	function encode(val) {
+	  return encodeURIComponent(val).
+	    replace(/%3A/gi, ':').
+	    replace(/%24/g, '$').
+	    replace(/%2C/gi, ',').
+	    replace(/%20/g, '+').
+	    replace(/%5B/gi, '[').
+	    replace(/%5D/gi, ']');
+	}
+	
+	/**
+	 * Build a URL by appending params to the end
+	 *
+	 * @param {string} url The base of the url (e.g., http://www.google.com)
+	 * @param {object} [params] The params to be appended
+	 * @returns {string} The formatted url
+	 */
+	module.exports = function buildURL(url, params, paramsSerializer) {
+	  /*eslint no-param-reassign:0*/
+	  if (!params) {
+	    return url;
+	  }
+	
+	  var serializedParams;
+	  if (paramsSerializer) {
+	    serializedParams = paramsSerializer(params);
+	  } else if (utils.isURLSearchParams(params)) {
+	    serializedParams = params.toString();
+	  } else {
+	    var parts = [];
+	
+	    utils.forEach(params, function serialize(val, key) {
+	      if (val === null || typeof val === 'undefined') {
+	        return;
+	      }
+	
+	      if (utils.isArray(val)) {
+	        key = key + '[]';
+	      } else {
+	        val = [val];
+	      }
+	
+	      utils.forEach(val, function parseValue(v) {
+	        if (utils.isDate(v)) {
+	          v = v.toISOString();
+	        } else if (utils.isObject(v)) {
+	          v = JSON.stringify(v);
+	        }
+	        parts.push(encode(key) + '=' + encode(v));
+	      });
+	    });
+	
+	    serializedParams = parts.join('&');
+	  }
+	
+	  if (serializedParams) {
+	    var hashmarkIndex = url.indexOf('#');
+	    if (hashmarkIndex !== -1) {
+	      url = url.slice(0, hashmarkIndex);
+	    }
+	
+	    url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams;
+	  }
+	
+	  return url;
+	};
+
+
+/***/ }),
+/* 6 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	var utils = __webpack_require__(2);
+	
+	function InterceptorManager() {
+	  this.handlers = [];
+	}
+	
+	/**
+	 * Add a new interceptor to the stack
+	 *
+	 * @param {Function} fulfilled The function to handle `then` for a `Promise`
+	 * @param {Function} rejected The function to handle `reject` for a `Promise`
+	 *
+	 * @return {Number} An ID used to remove interceptor later
+	 */
+	InterceptorManager.prototype.use = function use(fulfilled, rejected) {
+	  this.handlers.push({
+	    fulfilled: fulfilled,
+	    rejected: rejected
+	  });
+	  return this.handlers.length - 1;
+	};
+	
+	/**
+	 * Remove an interceptor from the stack
+	 *
+	 * @param {Number} id The ID that was returned by `use`
+	 */
+	InterceptorManager.prototype.eject = function eject(id) {
+	  if (this.handlers[id]) {
+	    this.handlers[id] = null;
+	  }
+	};
+	
+	/**
+	 * Iterate over all the registered interceptors
+	 *
+	 * This method is particularly useful for skipping over any
+	 * interceptors that may have become `null` calling `eject`.
+	 *
+	 * @param {Function} fn The function to call for each interceptor
+	 */
+	InterceptorManager.prototype.forEach = function forEach(fn) {
+	  utils.forEach(this.handlers, function forEachHandler(h) {
+	    if (h !== null) {
+	      fn(h);
+	    }
+	  });
+	};
+	
+	module.exports = InterceptorManager;
+
+
+/***/ }),
+/* 7 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	var utils = __webpack_require__(2);
+	var transformData = __webpack_require__(8);
+	var isCancel = __webpack_require__(9);
+	var defaults = __webpack_require__(10);
+	
+	/**
+	 * Throws a `Cancel` if cancellation has been requested.
+	 */
+	function throwIfCancellationRequested(config) {
+	  if (config.cancelToken) {
+	    config.cancelToken.throwIfRequested();
+	  }
+	}
+	
+	/**
+	 * Dispatch a request to the server using the configured adapter.
+	 *
+	 * @param {object} config The config that is to be used for the request
+	 * @returns {Promise} The Promise to be fulfilled
+	 */
+	module.exports = function dispatchRequest(config) {
+	  throwIfCancellationRequested(config);
+	
+	  // Ensure headers exist
+	  config.headers = config.headers || {};
+	
+	  // Transform request data
+	  config.data = transformData(
+	    config.data,
+	    config.headers,
+	    config.transformRequest
+	  );
+	
+	  // Flatten headers
+	  config.headers = utils.merge(
+	    config.headers.common || {},
+	    config.headers[config.method] || {},
+	    config.headers
+	  );
+	
+	  utils.forEach(
+	    ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'],
+	    function cleanHeaderConfig(method) {
+	      delete config.headers[method];
+	    }
+	  );
+	
+	  var adapter = config.adapter || defaults.adapter;
+	
+	  return adapter(config).then(function onAdapterResolution(response) {
+	    throwIfCancellationRequested(config);
+	
+	    // Transform response data
+	    response.data = transformData(
+	      response.data,
+	      response.headers,
+	      config.transformResponse
+	    );
+	
+	    return response;
+	  }, function onAdapterRejection(reason) {
+	    if (!isCancel(reason)) {
+	      throwIfCancellationRequested(config);
+	
+	      // Transform response data
+	      if (reason && reason.response) {
+	        reason.response.data = transformData(
+	          reason.response.data,
+	          reason.response.headers,
+	          config.transformResponse
+	        );
+	      }
+	    }
+	
+	    return Promise.reject(reason);
+	  });
+	};
+
+
+/***/ }),
+/* 8 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	var utils = __webpack_require__(2);
+	
+	/**
+	 * Transform the data for a request or a response
+	 *
+	 * @param {Object|String} data The data to be transformed
+	 * @param {Array} headers The headers for the request or response
+	 * @param {Array|Function} fns A single function or Array of functions
+	 * @returns {*} The resulting transformed data
+	 */
+	module.exports = function transformData(data, headers, fns) {
+	  /*eslint no-param-reassign:0*/
+	  utils.forEach(fns, function transform(fn) {
+	    data = fn(data, headers);
+	  });
+	
+	  return data;
+	};
+
+
+/***/ }),
+/* 9 */
+/***/ (function(module, exports) {
+
+	'use strict';
+	
+	module.exports = function isCancel(value) {
+	  return !!(value && value.__CANCEL__);
+	};
+
+
+/***/ }),
+/* 10 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	var utils = __webpack_require__(2);
+	var normalizeHeaderName = __webpack_require__(11);
+	
+	var DEFAULT_CONTENT_TYPE = {
+	  'Content-Type': 'application/x-www-form-urlencoded'
+	};
+	
+	function setContentTypeIfUnset(headers, value) {
+	  if (!utils.isUndefined(headers) && utils.isUndefined(headers['Content-Type'])) {
+	    headers['Content-Type'] = value;
+	  }
+	}
+	
+	function getDefaultAdapter() {
+	  var adapter;
+	  if (typeof XMLHttpRequest !== 'undefined') {
+	    // For browsers use XHR adapter
+	    adapter = __webpack_require__(12);
+	  } else if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') {
+	    // For node use HTTP adapter
+	    adapter = __webpack_require__(12);
+	  }
+	  return adapter;
+	}
+	
+	var defaults = {
+	  adapter: getDefaultAdapter(),
+	
+	  transformRequest: [function transformRequest(data, headers) {
+	    normalizeHeaderName(headers, 'Accept');
+	    normalizeHeaderName(headers, 'Content-Type');
+	    if (utils.isFormData(data) ||
+	      utils.isArrayBuffer(data) ||
+	      utils.isBuffer(data) ||
+	      utils.isStream(data) ||
+	      utils.isFile(data) ||
+	      utils.isBlob(data)
+	    ) {
+	      return data;
+	    }
+	    if (utils.isArrayBufferView(data)) {
+	      return data.buffer;
+	    }
+	    if (utils.isURLSearchParams(data)) {
+	      setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8');
+	      return data.toString();
+	    }
+	    if (utils.isObject(data)) {
+	      setContentTypeIfUnset(headers, 'application/json;charset=utf-8');
+	      return JSON.stringify(data);
+	    }
+	    return data;
+	  }],
+	
+	  transformResponse: [function transformResponse(data) {
+	    /*eslint no-param-reassign:0*/
+	    if (typeof data === 'string') {
+	      try {
+	        data = JSON.parse(data);
+	      } catch (e) { /* Ignore */ }
+	    }
+	    return data;
+	  }],
+	
+	  /**
+	   * A timeout in milliseconds to abort a request. If set to 0 (default) a
+	   * timeout is not created.
+	   */
+	  timeout: 0,
+	
+	  xsrfCookieName: 'XSRF-TOKEN',
+	  xsrfHeaderName: 'X-XSRF-TOKEN',
+	
+	  maxContentLength: -1,
+	  maxBodyLength: -1,
+	
+	  validateStatus: function validateStatus(status) {
+	    return status >= 200 && status < 300;
+	  }
+	};
+	
+	defaults.headers = {
+	  common: {
+	    'Accept': 'application/json, text/plain, */*'
+	  }
+	};
+	
+	utils.forEach(['delete', 'get', 'head'], function forEachMethodNoData(method) {
+	  defaults.headers[method] = {};
+	});
+	
+	utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
+	  defaults.headers[method] = utils.merge(DEFAULT_CONTENT_TYPE);
+	});
+	
+	module.exports = defaults;
+
+
+/***/ }),
+/* 11 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	var utils = __webpack_require__(2);
+	
+	module.exports = function normalizeHeaderName(headers, normalizedName) {
+	  utils.forEach(headers, function processHeader(value, name) {
+	    if (name !== normalizedName && name.toUpperCase() === normalizedName.toUpperCase()) {
+	      headers[normalizedName] = value;
+	      delete headers[name];
+	    }
+	  });
+	};
+
+
+/***/ }),
+/* 12 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	var utils = __webpack_require__(2);
+	var settle = __webpack_require__(13);
+	var cookies = __webpack_require__(16);
+	var buildURL = __webpack_require__(5);
+	var buildFullPath = __webpack_require__(17);
+	var parseHeaders = __webpack_require__(20);
+	var isURLSameOrigin = __webpack_require__(21);
+	var createError = __webpack_require__(14);
+	
+	module.exports = function xhrAdapter(config) {
+	  return new Promise(function dispatchXhrRequest(resolve, reject) {
+	    var requestData = config.data;
+	    var requestHeaders = config.headers;
+	
+	    if (utils.isFormData(requestData)) {
+	      delete requestHeaders['Content-Type']; // Let the browser set it
+	    }
+	
+	    var request = new XMLHttpRequest();
+	
+	    // HTTP basic authentication
+	    if (config.auth) {
+	      var username = config.auth.username || '';
+	      var password = config.auth.password ? unescape(encodeURIComponent(config.auth.password)) : '';
+	      requestHeaders.Authorization = 'Basic ' + btoa(username + ':' + password);
+	    }
+	
+	    var fullPath = buildFullPath(config.baseURL, config.url);
+	    request.open(config.method.toUpperCase(), buildURL(fullPath, config.params, config.paramsSerializer), true);
+	
+	    // Set the request timeout in MS
+	    request.timeout = config.timeout;
+	
+	    // Listen for ready state
+	    request.onreadystatechange = function handleLoad() {
+	      if (!request || request.readyState !== 4) {
+	        return;
+	      }
+	
+	      // The request errored out and we didn't get a response, this will be
+	      // handled by onerror instead
+	      // With one exception: request that using file: protocol, most browsers
+	      // will return status as 0 even though it's a successful request
+	      if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) {
+	        return;
+	      }
+	
+	      // Prepare the response
+	      var responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null;
+	      var responseData = !config.responseType || config.responseType === 'text' ? request.responseText : request.response;
+	      var response = {
+	        data: responseData,
+	        status: request.status,
+	        statusText: request.statusText,
+	        headers: responseHeaders,
+	        config: config,
+	        request: request
+	      };
+	
+	      settle(resolve, reject, response);
+	
+	      // Clean up request
+	      request = null;
+	    };
+	
+	    // Handle browser request cancellation (as opposed to a manual cancellation)
+	    request.onabort = function handleAbort() {
+	      if (!request) {
+	        return;
+	      }
+	
+	      reject(createError('Request aborted', config, 'ECONNABORTED', request));
+	
+	      // Clean up request
+	      request = null;
+	    };
+	
+	    // Handle low level network errors
+	    request.onerror = function handleError() {
+	      // Real errors are hidden from us by the browser
+	      // onerror should only fire if it's a network error
+	      reject(createError('Network Error', config, null, request));
+	
+	      // Clean up request
+	      request = null;
+	    };
+	
+	    // Handle timeout
+	    request.ontimeout = function handleTimeout() {
+	      var timeoutErrorMessage = 'timeout of ' + config.timeout + 'ms exceeded';
+	      if (config.timeoutErrorMessage) {
+	        timeoutErrorMessage = config.timeoutErrorMessage;
+	      }
+	      reject(createError(timeoutErrorMessage, config, 'ECONNABORTED',
+	        request));
+	
+	      // Clean up request
+	      request = null;
+	    };
+	
+	    // Add xsrf header
+	    // This is only done if running in a standard browser environment.
+	    // Specifically not if we're in a web worker, or react-native.
+	    if (utils.isStandardBrowserEnv()) {
+	      // Add xsrf header
+	      var xsrfValue = (config.withCredentials || isURLSameOrigin(fullPath)) && config.xsrfCookieName ?
+	        cookies.read(config.xsrfCookieName) :
+	        undefined;
+	
+	      if (xsrfValue) {
+	        requestHeaders[config.xsrfHeaderName] = xsrfValue;
+	      }
+	    }
+	
+	    // Add headers to the request
+	    if ('setRequestHeader' in request) {
+	      utils.forEach(requestHeaders, function setRequestHeader(val, key) {
+	        if (typeof requestData === 'undefined' && key.toLowerCase() === 'content-type') {
+	          // Remove Content-Type if data is undefined
+	          delete requestHeaders[key];
+	        } else {
+	          // Otherwise add header to the request
+	          request.setRequestHeader(key, val);
+	        }
+	      });
+	    }
+	
+	    // Add withCredentials to request if needed
+	    if (!utils.isUndefined(config.withCredentials)) {
+	      request.withCredentials = !!config.withCredentials;
+	    }
+	
+	    // Add responseType to request if needed
+	    if (config.responseType) {
+	      try {
+	        request.responseType = config.responseType;
+	      } catch (e) {
+	        // Expected DOMException thrown by browsers not compatible XMLHttpRequest Level 2.
+	        // But, this can be suppressed for 'json' type as it can be parsed by default 'transformResponse' function.
+	        if (config.responseType !== 'json') {
+	          throw e;
+	        }
+	      }
+	    }
+	
+	    // Handle progress if needed
+	    if (typeof config.onDownloadProgress === 'function') {
+	      request.addEventListener('progress', config.onDownloadProgress);
+	    }
+	
+	    // Not all browsers support upload events
+	    if (typeof config.onUploadProgress === 'function' && request.upload) {
+	      request.upload.addEventListener('progress', config.onUploadProgress);
+	    }
+	
+	    if (config.cancelToken) {
+	      // Handle cancellation
+	      config.cancelToken.promise.then(function onCanceled(cancel) {
+	        if (!request) {
+	          return;
+	        }
+	
+	        request.abort();
+	        reject(cancel);
+	        // Clean up request
+	        request = null;
+	      });
+	    }
+	
+	    if (!requestData) {
+	      requestData = null;
+	    }
+	
+	    // Send the request
+	    request.send(requestData);
+	  });
+	};
+
+
+/***/ }),
+/* 13 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	var createError = __webpack_require__(14);
+	
+	/**
+	 * Resolve or reject a Promise based on response status.
+	 *
+	 * @param {Function} resolve A function that resolves the promise.
+	 * @param {Function} reject A function that rejects the promise.
+	 * @param {object} response The response.
+	 */
+	module.exports = function settle(resolve, reject, response) {
+	  var validateStatus = response.config.validateStatus;
+	  if (!response.status || !validateStatus || validateStatus(response.status)) {
+	    resolve(response);
+	  } else {
+	    reject(createError(
+	      'Request failed with status code ' + response.status,
+	      response.config,
+	      null,
+	      response.request,
+	      response
+	    ));
+	  }
+	};
+
+
+/***/ }),
+/* 14 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	var enhanceError = __webpack_require__(15);
+	
+	/**
+	 * Create an Error with the specified message, config, error code, request and response.
+	 *
+	 * @param {string} message The error message.
+	 * @param {Object} config The config.
+	 * @param {string} [code] The error code (for example, 'ECONNABORTED').
+	 * @param {Object} [request] The request.
+	 * @param {Object} [response] The response.
+	 * @returns {Error} The created error.
+	 */
+	module.exports = function createError(message, config, code, request, response) {
+	  var error = new Error(message);
+	  return enhanceError(error, config, code, request, response);
+	};
+
+
+/***/ }),
+/* 15 */
+/***/ (function(module, exports) {
+
+	'use strict';
+	
+	/**
+	 * Update an Error with the specified config, error code, and response.
+	 *
+	 * @param {Error} error The error to update.
+	 * @param {Object} config The config.
+	 * @param {string} [code] The error code (for example, 'ECONNABORTED').
+	 * @param {Object} [request] The request.
+	 * @param {Object} [response] The response.
+	 * @returns {Error} The error.
+	 */
+	module.exports = function enhanceError(error, config, code, request, response) {
+	  error.config = config;
+	  if (code) {
+	    error.code = code;
+	  }
+	
+	  error.request = request;
+	  error.response = response;
+	  error.isAxiosError = true;
+	
+	  error.toJSON = function toJSON() {
+	    return {
+	      // Standard
+	      message: this.message,
+	      name: this.name,
+	      // Microsoft
+	      description: this.description,
+	      number: this.number,
+	      // Mozilla
+	      fileName: this.fileName,
+	      lineNumber: this.lineNumber,
+	      columnNumber: this.columnNumber,
+	      stack: this.stack,
+	      // Axios
+	      config: this.config,
+	      code: this.code
+	    };
+	  };
+	  return error;
+	};
+
+
+/***/ }),
+/* 16 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	var utils = __webpack_require__(2);
+	
+	module.exports = (
+	  utils.isStandardBrowserEnv() ?
+	
+	  // Standard browser envs support document.cookie
+	    (function standardBrowserEnv() {
+	      return {
+	        write: function write(name, value, expires, path, domain, secure) {
+	          var cookie = [];
+	          cookie.push(name + '=' + encodeURIComponent(value));
+	
+	          if (utils.isNumber(expires)) {
+	            cookie.push('expires=' + new Date(expires).toGMTString());
+	          }
+	
+	          if (utils.isString(path)) {
+	            cookie.push('path=' + path);
+	          }
+	
+	          if (utils.isString(domain)) {
+	            cookie.push('domain=' + domain);
+	          }
+	
+	          if (secure === true) {
+	            cookie.push('secure');
+	          }
+	
+	          document.cookie = cookie.join('; ');
+	        },
+	
+	        read: function read(name) {
+	          var match = document.cookie.match(new RegExp('(^|;\\s*)(' + name + ')=([^;]*)'));
+	          return (match ? decodeURIComponent(match[3]) : null);
+	        },
+	
+	        remove: function remove(name) {
+	          this.write(name, '', Date.now() - 86400000);
+	        }
+	      };
+	    })() :
+	
+	  // Non standard browser env (web workers, react-native) lack needed support.
+	    (function nonStandardBrowserEnv() {
+	      return {
+	        write: function write() {},
+	        read: function read() { return null; },
+	        remove: function remove() {}
+	      };
+	    })()
+	);
+
+
+/***/ }),
+/* 17 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	var isAbsoluteURL = __webpack_require__(18);
+	var combineURLs = __webpack_require__(19);
+	
+	/**
+	 * Creates a new URL by combining the baseURL with the requestedURL,
+	 * only when the requestedURL is not already an absolute URL.
+	 * If the requestURL is absolute, this function returns the requestedURL untouched.
+	 *
+	 * @param {string} baseURL The base URL
+	 * @param {string} requestedURL Absolute or relative URL to combine
+	 * @returns {string} The combined full path
+	 */
+	module.exports = function buildFullPath(baseURL, requestedURL) {
+	  if (baseURL && !isAbsoluteURL(requestedURL)) {
+	    return combineURLs(baseURL, requestedURL);
+	  }
+	  return requestedURL;
+	};
+
+
+/***/ }),
+/* 18 */
+/***/ (function(module, exports) {
+
+	'use strict';
+	
+	/**
+	 * Determines whether the specified URL is absolute
+	 *
+	 * @param {string} url The URL to test
+	 * @returns {boolean} True if the specified URL is absolute, otherwise false
+	 */
+	module.exports = function isAbsoluteURL(url) {
+	  // A URL is considered absolute if it begins with "<scheme>://" or "//" (protocol-relative URL).
+	  // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed
+	  // by any combination of letters, digits, plus, period, or hyphen.
+	  return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url);
+	};
+
+
+/***/ }),
+/* 19 */
+/***/ (function(module, exports) {
+
+	'use strict';
+	
+	/**
+	 * Creates a new URL by combining the specified URLs
+	 *
+	 * @param {string} baseURL The base URL
+	 * @param {string} relativeURL The relative URL
+	 * @returns {string} The combined URL
+	 */
+	module.exports = function combineURLs(baseURL, relativeURL) {
+	  return relativeURL
+	    ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '')
+	    : baseURL;
+	};
+
+
+/***/ }),
+/* 20 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	var utils = __webpack_require__(2);
+	
+	// Headers whose duplicates are ignored by node
+	// c.f. https://nodejs.org/api/http.html#http_message_headers
+	var ignoreDuplicateOf = [
+	  'age', 'authorization', 'content-length', 'content-type', 'etag',
+	  'expires', 'from', 'host', 'if-modified-since', 'if-unmodified-since',
+	  'last-modified', 'location', 'max-forwards', 'proxy-authorization',
+	  'referer', 'retry-after', 'user-agent'
+	];
+	
+	/**
+	 * Parse headers into an object
+	 *
+	 * ```
+	 * Date: Wed, 27 Aug 2014 08:58:49 GMT
+	 * Content-Type: application/json
+	 * Connection: keep-alive
+	 * Transfer-Encoding: chunked
+	 * ```
+	 *
+	 * @param {String} headers Headers needing to be parsed
+	 * @returns {Object} Headers parsed into an object
+	 */
+	module.exports = function parseHeaders(headers) {
+	  var parsed = {};
+	  var key;
+	  var val;
+	  var i;
+	
+	  if (!headers) { return parsed; }
+	
+	  utils.forEach(headers.split('\n'), function parser(line) {
+	    i = line.indexOf(':');
+	    key = utils.trim(line.substr(0, i)).toLowerCase();
+	    val = utils.trim(line.substr(i + 1));
+	
+	    if (key) {
+	      if (parsed[key] && ignoreDuplicateOf.indexOf(key) >= 0) {
+	        return;
+	      }
+	      if (key === 'set-cookie') {
+	        parsed[key] = (parsed[key] ? parsed[key] : []).concat([val]);
+	      } else {
+	        parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;
+	      }
+	    }
+	  });
+	
+	  return parsed;
+	};
+
+
+/***/ }),
+/* 21 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	var utils = __webpack_require__(2);
+	
+	module.exports = (
+	  utils.isStandardBrowserEnv() ?
+	
+	  // Standard browser envs have full support of the APIs needed to test
+	  // whether the request URL is of the same origin as current location.
+	    (function standardBrowserEnv() {
+	      var msie = /(msie|trident)/i.test(navigator.userAgent);
+	      var urlParsingNode = document.createElement('a');
+	      var originURL;
+	
+	      /**
+	    * Parse a URL to discover it's components
+	    *
+	    * @param {String} url The URL to be parsed
+	    * @returns {Object}
+	    */
+	      function resolveURL(url) {
+	        var href = url;
+	
+	        if (msie) {
+	        // IE needs attribute set twice to normalize properties
+	          urlParsingNode.setAttribute('href', href);
+	          href = urlParsingNode.href;
+	        }
+	
+	        urlParsingNode.setAttribute('href', href);
+	
+	        // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils
+	        return {
+	          href: urlParsingNode.href,
+	          protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',
+	          host: urlParsingNode.host,
+	          search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '',
+	          hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',
+	          hostname: urlParsingNode.hostname,
+	          port: urlParsingNode.port,
+	          pathname: (urlParsingNode.pathname.charAt(0) === '/') ?
+	            urlParsingNode.pathname :
+	            '/' + urlParsingNode.pathname
+	        };
+	      }
+	
+	      originURL = resolveURL(window.location.href);
+	
+	      /**
+	    * Determine if a URL shares the same origin as the current location
+	    *
+	    * @param {String} requestURL The URL to test
+	    * @returns {boolean} True if URL shares the same origin, otherwise false
+	    */
+	      return function isURLSameOrigin(requestURL) {
+	        var parsed = (utils.isString(requestURL)) ? resolveURL(requestURL) : requestURL;
+	        return (parsed.protocol === originURL.protocol &&
+	            parsed.host === originURL.host);
+	      };
+	    })() :
+	
+	  // Non standard browser envs (web workers, react-native) lack needed support.
+	    (function nonStandardBrowserEnv() {
+	      return function isURLSameOrigin() {
+	        return true;
+	      };
+	    })()
+	);
+
+
+/***/ }),
+/* 22 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	var utils = __webpack_require__(2);
+	
+	/**
+	 * Config-specific merge-function which creates a new config-object
+	 * by merging two configuration objects together.
+	 *
+	 * @param {Object} config1
+	 * @param {Object} config2
+	 * @returns {Object} New object resulting from merging config2 to config1
+	 */
+	module.exports = function mergeConfig(config1, config2) {
+	  // eslint-disable-next-line no-param-reassign
+	  config2 = config2 || {};
+	  var config = {};
+	
+	  var valueFromConfig2Keys = ['url', 'method', 'data'];
+	  var mergeDeepPropertiesKeys = ['headers', 'auth', 'proxy', 'params'];
+	  var defaultToConfig2Keys = [
+	    'baseURL', 'transformRequest', 'transformResponse', 'paramsSerializer',
+	    'timeout', 'timeoutMessage', 'withCredentials', 'adapter', 'responseType', 'xsrfCookieName',
+	    'xsrfHeaderName', 'onUploadProgress', 'onDownloadProgress', 'decompress',
+	    'maxContentLength', 'maxBodyLength', 'maxRedirects', 'transport', 'httpAgent',
+	    'httpsAgent', 'cancelToken', 'socketPath', 'responseEncoding'
+	  ];
+	  var directMergeKeys = ['validateStatus'];
+	
+	  function getMergedValue(target, source) {
+	    if (utils.isPlainObject(target) && utils.isPlainObject(source)) {
+	      return utils.merge(target, source);
+	    } else if (utils.isPlainObject(source)) {
+	      return utils.merge({}, source);
+	    } else if (utils.isArray(source)) {
+	      return source.slice();
+	    }
+	    return source;
+	  }
+	
+	  function mergeDeepProperties(prop) {
+	    if (!utils.isUndefined(config2[prop])) {
+	      config[prop] = getMergedValue(config1[prop], config2[prop]);
+	    } else if (!utils.isUndefined(config1[prop])) {
+	      config[prop] = getMergedValue(undefined, config1[prop]);
+	    }
+	  }
+	
+	  utils.forEach(valueFromConfig2Keys, function valueFromConfig2(prop) {
+	    if (!utils.isUndefined(config2[prop])) {
+	      config[prop] = getMergedValue(undefined, config2[prop]);
+	    }
+	  });
+	
+	  utils.forEach(mergeDeepPropertiesKeys, mergeDeepProperties);
+	
+	  utils.forEach(defaultToConfig2Keys, function defaultToConfig2(prop) {
+	    if (!utils.isUndefined(config2[prop])) {
+	      config[prop] = getMergedValue(undefined, config2[prop]);
+	    } else if (!utils.isUndefined(config1[prop])) {
+	      config[prop] = getMergedValue(undefined, config1[prop]);
+	    }
+	  });
+	
+	  utils.forEach(directMergeKeys, function merge(prop) {
+	    if (prop in config2) {
+	      config[prop] = getMergedValue(config1[prop], config2[prop]);
+	    } else if (prop in config1) {
+	      config[prop] = getMergedValue(undefined, config1[prop]);
+	    }
+	  });
+	
+	  var axiosKeys = valueFromConfig2Keys
+	    .concat(mergeDeepPropertiesKeys)
+	    .concat(defaultToConfig2Keys)
+	    .concat(directMergeKeys);
+	
+	  var otherKeys = Object
+	    .keys(config1)
+	    .concat(Object.keys(config2))
+	    .filter(function filterAxiosKeys(key) {
+	      return axiosKeys.indexOf(key) === -1;
+	    });
+	
+	  utils.forEach(otherKeys, mergeDeepProperties);
+	
+	  return config;
+	};
+
+
+/***/ }),
+/* 23 */
+/***/ (function(module, exports) {
+
+	'use strict';
+	
+	/**
+	 * A `Cancel` is an object that is thrown when an operation is canceled.
+	 *
+	 * @class
+	 * @param {string=} message The message.
+	 */
+	function Cancel(message) {
+	  this.message = message;
+	}
+	
+	Cancel.prototype.toString = function toString() {
+	  return 'Cancel' + (this.message ? ': ' + this.message : '');
+	};
+	
+	Cancel.prototype.__CANCEL__ = true;
+	
+	module.exports = Cancel;
+
+
+/***/ }),
+/* 24 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict';
+	
+	var Cancel = __webpack_require__(23);
+	
+	/**
+	 * A `CancelToken` is an object that can be used to request cancellation of an operation.
+	 *
+	 * @class
+	 * @param {Function} executor The executor function.
+	 */
+	function CancelToken(executor) {
+	  if (typeof executor !== 'function') {
+	    throw new TypeError('executor must be a function.');
+	  }
+	
+	  var resolvePromise;
+	  this.promise = new Promise(function promiseExecutor(resolve) {
+	    resolvePromise = resolve;
+	  });
+	
+	  var token = this;
+	  executor(function cancel(message) {
+	    if (token.reason) {
+	      // Cancellation has already been requested
+	      return;
+	    }
+	
+	    token.reason = new Cancel(message);
+	    resolvePromise(token.reason);
+	  });
+	}
+	
+	/**
+	 * Throws a `Cancel` if cancellation has been requested.
+	 */
+	CancelToken.prototype.throwIfRequested = function throwIfRequested() {
+	  if (this.reason) {
+	    throw this.reason;
+	  }
+	};
+	
+	/**
+	 * Returns an object that contains a new `CancelToken` and a function that, when called,
+	 * cancels the `CancelToken`.
+	 */
+	CancelToken.source = function source() {
+	  var cancel;
+	  var token = new CancelToken(function executor(c) {
+	    cancel = c;
+	  });
+	  return {
+	    token: token,
+	    cancel: cancel
+	  };
+	};
+	
+	module.exports = CancelToken;
+
+
+/***/ }),
+/* 25 */
+/***/ (function(module, exports) {
+
+	'use strict';
+	
+	/**
+	 * Syntactic sugar for invoking a function and expanding an array for arguments.
+	 *
+	 * Common use case would be to use `Function.prototype.apply`.
+	 *
+	 *  ```js
+	 *  function f(x, y, z) {}
+	 *  var args = [1, 2, 3];
+	 *  f.apply(null, args);
+	 *  ```
+	 *
+	 * With `spread` this example can be re-written.
+	 *
+	 *  ```js
+	 *  spread(function(x, y, z) {})([1, 2, 3]);
+	 *  ```
+	 *
+	 * @param {Function} callback
+	 * @returns {Function}
+	 */
+	module.exports = function spread(callback) {
+	  return function wrap(arr) {
+	    return callback.apply(null, arr);
+	  };
+	};
+
+
+/***/ }),
+/* 26 */
+/***/ (function(module, exports) {
+
+	'use strict';
+	
+	/**
+	 * Determines whether the payload is an error thrown by Axios
+	 *
+	 * @param {*} payload The value to test
+	 * @returns {boolean} True if the payload is an error thrown by Axios, otherwise false
+	 */
+	module.exports = function isAxiosError(payload) {
+	  return (typeof payload === 'object') && (payload.isAxiosError === true);
+	};
+
+
+/***/ })
+/******/ ])
+});
+;
+//# sourceMappingURL=axios.map

File diff suppressed because it is too large
+ 0 - 0
node_modules/axios/dist/axios.map


File diff suppressed because it is too large
+ 1 - 0
node_modules/axios/dist/axios.min.js


File diff suppressed because it is too large
+ 0 - 0
node_modules/axios/dist/axios.min.map


+ 161 - 0
node_modules/axios/index.d.ts

@@ -0,0 +1,161 @@
+export interface AxiosTransformer {
+  (data: any, headers?: any): any;
+}
+
+export interface AxiosAdapter {
+  (config: AxiosRequestConfig): AxiosPromise<any>;
+}
+
+export interface AxiosBasicCredentials {
+  username: string;
+  password: string;
+}
+
+export interface AxiosProxyConfig {
+  host: string;
+  port: number;
+  auth?: {
+    username: string;
+    password:string;
+  };
+  protocol?: string;
+}
+
+export type Method =
+  | 'get' | 'GET'
+  | 'delete' | 'DELETE'
+  | 'head' | 'HEAD'
+  | 'options' | 'OPTIONS'
+  | 'post' | 'POST'
+  | 'put' | 'PUT'
+  | 'patch' | 'PATCH'
+  | 'purge' | 'PURGE'
+  | 'link' | 'LINK'
+  | 'unlink' | 'UNLINK'
+
+export type ResponseType =
+  | 'arraybuffer'
+  | 'blob'
+  | 'document'
+  | 'json'
+  | 'text'
+  | 'stream'
+
+export interface AxiosRequestConfig {
+  url?: string;
+  method?: Method;
+  baseURL?: string;
+  transformRequest?: AxiosTransformer | AxiosTransformer[];
+  transformResponse?: AxiosTransformer | AxiosTransformer[];
+  headers?: any;
+  params?: any;
+  paramsSerializer?: (params: any) => string;
+  data?: any;
+  timeout?: number;
+  timeoutErrorMessage?: string;
+  withCredentials?: boolean;
+  adapter?: AxiosAdapter;
+  auth?: AxiosBasicCredentials;
+  responseType?: ResponseType;
+  xsrfCookieName?: string;
+  xsrfHeaderName?: string;
+  onUploadProgress?: (progressEvent: any) => void;
+  onDownloadProgress?: (progressEvent: any) => void;
+  maxContentLength?: number;
+  validateStatus?: ((status: number) => boolean) | null;
+  maxBodyLength?: number;
+  maxRedirects?: number;
+  socketPath?: string | null;
+  httpAgent?: any;
+  httpsAgent?: any;
+  proxy?: AxiosProxyConfig | false;
+  cancelToken?: CancelToken;
+  decompress?: boolean;
+}
+
+export interface AxiosResponse<T = any>  {
+  data: T;
+  status: number;
+  statusText: string;
+  headers: any;
+  config: AxiosRequestConfig;
+  request?: any;
+}
+
+export interface AxiosError<T = any> extends Error {
+  config: AxiosRequestConfig;
+  code?: string;
+  request?: any;
+  response?: AxiosResponse<T>;
+  isAxiosError: boolean;
+  toJSON: () => object;
+}
+
+export interface AxiosPromise<T = any> extends Promise<AxiosResponse<T>> {
+}
+
+export interface CancelStatic {
+  new (message?: string): Cancel;
+}
+
+export interface Cancel {
+  message: string;
+}
+
+export interface Canceler {
+  (message?: string): void;
+}
+
+export interface CancelTokenStatic {
+  new (executor: (cancel: Canceler) => void): CancelToken;
+  source(): CancelTokenSource;
+}
+
+export interface CancelToken {
+  promise: Promise<Cancel>;
+  reason?: Cancel;
+  throwIfRequested(): void;
+}
+
+export interface CancelTokenSource {
+  token: CancelToken;
+  cancel: Canceler;
+}
+
+export interface AxiosInterceptorManager<V> {
+  use(onFulfilled?: (value: V) => V | Promise<V>, onRejected?: (error: any) => any): number;
+  eject(id: number): void;
+}
+
+export interface AxiosInstance {
+  (config: AxiosRequestConfig): AxiosPromise;
+  (url: string, config?: AxiosRequestConfig): AxiosPromise;
+  defaults: AxiosRequestConfig;
+  interceptors: {
+    request: AxiosInterceptorManager<AxiosRequestConfig>;
+    response: AxiosInterceptorManager<AxiosResponse>;
+  };
+  getUri(config?: AxiosRequestConfig): string;
+  request<T = any, R = AxiosResponse<T>> (config: AxiosRequestConfig): Promise<R>;
+  get<T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig): Promise<R>;
+  delete<T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig): Promise<R>;
+  head<T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig): Promise<R>;
+  options<T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig): Promise<R>;
+  post<T = any, R = AxiosResponse<T>>(url: string, data?: any, config?: AxiosRequestConfig): Promise<R>;
+  put<T = any, R = AxiosResponse<T>>(url: string, data?: any, config?: AxiosRequestConfig): Promise<R>;
+  patch<T = any, R = AxiosResponse<T>>(url: string, data?: any, config?: AxiosRequestConfig): Promise<R>;
+}
+
+export interface AxiosStatic extends AxiosInstance {
+  create(config?: AxiosRequestConfig): AxiosInstance;
+  Cancel: CancelStatic;
+  CancelToken: CancelTokenStatic;
+  isCancel(value: any): boolean;
+  all<T>(values: (T | Promise<T>)[]): Promise<T[]>;
+  spread<T, R>(callback: (...args: T[]) => R): (array: T[]) => R;
+  isAxiosError(payload: any): payload is AxiosError;
+}
+
+declare const axios: AxiosStatic;
+
+export default axios;

+ 1 - 0
node_modules/axios/index.js

@@ -0,0 +1 @@
+module.exports = require('./lib/axios');

+ 37 - 0
node_modules/axios/lib/adapters/README.md

@@ -0,0 +1,37 @@
+# axios // adapters
+
+The modules under `adapters/` are modules that handle dispatching a request and settling a returned `Promise` once a response is received.
+
+## Example
+
+```js
+var settle = require('./../core/settle');
+
+module.exports = function myAdapter(config) {
+  // At this point:
+  //  - config has been merged with defaults
+  //  - request transformers have already run
+  //  - request interceptors have already run
+  
+  // Make the request using config provided
+  // Upon response settle the Promise
+
+  return new Promise(function(resolve, reject) {
+  
+    var response = {
+      data: responseData,
+      status: request.status,
+      statusText: request.statusText,
+      headers: responseHeaders,
+      config: config,
+      request: request
+    };
+
+    settle(resolve, reject, response);
+
+    // From here:
+    //  - response transformers will run
+    //  - response interceptors will run
+  });
+}
+```

+ 303 - 0
node_modules/axios/lib/adapters/http.js

@@ -0,0 +1,303 @@
+'use strict';
+
+var utils = require('./../utils');
+var settle = require('./../core/settle');
+var buildFullPath = require('../core/buildFullPath');
+var buildURL = require('./../helpers/buildURL');
+var http = require('http');
+var https = require('https');
+var httpFollow = require('follow-redirects').http;
+var httpsFollow = require('follow-redirects').https;
+var url = require('url');
+var zlib = require('zlib');
+var pkg = require('./../../package.json');
+var createError = require('../core/createError');
+var enhanceError = require('../core/enhanceError');
+
+var isHttps = /https:?/;
+
+/**
+ *
+ * @param {http.ClientRequestArgs} options
+ * @param {AxiosProxyConfig} proxy
+ * @param {string} location
+ */
+function setProxy(options, proxy, location) {
+  options.hostname = proxy.host;
+  options.host = proxy.host;
+  options.port = proxy.port;
+  options.path = location;
+
+  // Basic proxy authorization
+  if (proxy.auth) {
+    var base64 = Buffer.from(proxy.auth.username + ':' + proxy.auth.password, 'utf8').toString('base64');
+    options.headers['Proxy-Authorization'] = 'Basic ' + base64;
+  }
+
+  // If a proxy is used, any redirects must also pass through the proxy
+  options.beforeRedirect = function beforeRedirect(redirection) {
+    redirection.headers.host = redirection.host;
+    setProxy(redirection, proxy, redirection.href);
+  };
+}
+
+/*eslint consistent-return:0*/
+module.exports = function httpAdapter(config) {
+  return new Promise(function dispatchHttpRequest(resolvePromise, rejectPromise) {
+    var resolve = function resolve(value) {
+      resolvePromise(value);
+    };
+    var reject = function reject(value) {
+      rejectPromise(value);
+    };
+    var data = config.data;
+    var headers = config.headers;
+
+    // Set User-Agent (required by some servers)
+    // Only set header if it hasn't been set in config
+    // See https://github.com/axios/axios/issues/69
+    if (!headers['User-Agent'] && !headers['user-agent']) {
+      headers['User-Agent'] = 'axios/' + pkg.version;
+    }
+
+    if (data && !utils.isStream(data)) {
+      if (Buffer.isBuffer(data)) {
+        // Nothing to do...
+      } else if (utils.isArrayBuffer(data)) {
+        data = Buffer.from(new Uint8Array(data));
+      } else if (utils.isString(data)) {
+        data = Buffer.from(data, 'utf-8');
+      } else {
+        return reject(createError(
+          'Data after transformation must be a string, an ArrayBuffer, a Buffer, or a Stream',
+          config
+        ));
+      }
+
+      // Add Content-Length header if data exists
+      headers['Content-Length'] = data.length;
+    }
+
+    // HTTP basic authentication
+    var auth = undefined;
+    if (config.auth) {
+      var username = config.auth.username || '';
+      var password = config.auth.password || '';
+      auth = username + ':' + password;
+    }
+
+    // Parse url
+    var fullPath = buildFullPath(config.baseURL, config.url);
+    var parsed = url.parse(fullPath);
+    var protocol = parsed.protocol || 'http:';
+
+    if (!auth && parsed.auth) {
+      var urlAuth = parsed.auth.split(':');
+      var urlUsername = urlAuth[0] || '';
+      var urlPassword = urlAuth[1] || '';
+      auth = urlUsername + ':' + urlPassword;
+    }
+
+    if (auth) {
+      delete headers.Authorization;
+    }
+
+    var isHttpsRequest = isHttps.test(protocol);
+    var agent = isHttpsRequest ? config.httpsAgent : config.httpAgent;
+
+    var options = {
+      path: buildURL(parsed.path, config.params, config.paramsSerializer).replace(/^\?/, ''),
+      method: config.method.toUpperCase(),
+      headers: headers,
+      agent: agent,
+      agents: { http: config.httpAgent, https: config.httpsAgent },
+      auth: auth
+    };
+
+    if (config.socketPath) {
+      options.socketPath = config.socketPath;
+    } else {
+      options.hostname = parsed.hostname;
+      options.port = parsed.port;
+    }
+
+    var proxy = config.proxy;
+    if (!proxy && proxy !== false) {
+      var proxyEnv = protocol.slice(0, -1) + '_proxy';
+      var proxyUrl = process.env[proxyEnv] || process.env[proxyEnv.toUpperCase()];
+      if (proxyUrl) {
+        var parsedProxyUrl = url.parse(proxyUrl);
+        var noProxyEnv = process.env.no_proxy || process.env.NO_PROXY;
+        var shouldProxy = true;
+
+        if (noProxyEnv) {
+          var noProxy = noProxyEnv.split(',').map(function trim(s) {
+            return s.trim();
+          });
+
+          shouldProxy = !noProxy.some(function proxyMatch(proxyElement) {
+            if (!proxyElement) {
+              return false;
+            }
+            if (proxyElement === '*') {
+              return true;
+            }
+            if (proxyElement[0] === '.' &&
+                parsed.hostname.substr(parsed.hostname.length - proxyElement.length) === proxyElement) {
+              return true;
+            }
+
+            return parsed.hostname === proxyElement;
+          });
+        }
+
+        if (shouldProxy) {
+          proxy = {
+            host: parsedProxyUrl.hostname,
+            port: parsedProxyUrl.port,
+            protocol: parsedProxyUrl.protocol
+          };
+
+          if (parsedProxyUrl.auth) {
+            var proxyUrlAuth = parsedProxyUrl.auth.split(':');
+            proxy.auth = {
+              username: proxyUrlAuth[0],
+              password: proxyUrlAuth[1]
+            };
+          }
+        }
+      }
+    }
+
+    if (proxy) {
+      options.headers.host = parsed.hostname + (parsed.port ? ':' + parsed.port : '');
+      setProxy(options, proxy, protocol + '//' + parsed.hostname + (parsed.port ? ':' + parsed.port : '') + options.path);
+    }
+
+    var transport;
+    var isHttpsProxy = isHttpsRequest && (proxy ? isHttps.test(proxy.protocol) : true);
+    if (config.transport) {
+      transport = config.transport;
+    } else if (config.maxRedirects === 0) {
+      transport = isHttpsProxy ? https : http;
+    } else {
+      if (config.maxRedirects) {
+        options.maxRedirects = config.maxRedirects;
+      }
+      transport = isHttpsProxy ? httpsFollow : httpFollow;
+    }
+
+    if (config.maxBodyLength > -1) {
+      options.maxBodyLength = config.maxBodyLength;
+    }
+
+    // Create the request
+    var req = transport.request(options, function handleResponse(res) {
+      if (req.aborted) return;
+
+      // uncompress the response body transparently if required
+      var stream = res;
+
+      // return the last request in case of redirects
+      var lastRequest = res.req || req;
+
+
+      // if no content, is HEAD request or decompress disabled we should not decompress
+      if (res.statusCode !== 204 && lastRequest.method !== 'HEAD' && config.decompress !== false) {
+        switch (res.headers['content-encoding']) {
+        /*eslint default-case:0*/
+        case 'gzip':
+        case 'compress':
+        case 'deflate':
+        // add the unzipper to the body stream processing pipeline
+          stream = stream.pipe(zlib.createUnzip());
+
+          // remove the content-encoding in order to not confuse downstream operations
+          delete res.headers['content-encoding'];
+          break;
+        }
+      }
+
+      var response = {
+        status: res.statusCode,
+        statusText: res.statusMessage,
+        headers: res.headers,
+        config: config,
+        request: lastRequest
+      };
+
+      if (config.responseType === 'stream') {
+        response.data = stream;
+        settle(resolve, reject, response);
+      } else {
+        var responseBuffer = [];
+        stream.on('data', function handleStreamData(chunk) {
+          responseBuffer.push(chunk);
+
+          // make sure the content length is not over the maxContentLength if specified
+          if (config.maxContentLength > -1 && Buffer.concat(responseBuffer).length > config.maxContentLength) {
+            stream.destroy();
+            reject(createError('maxContentLength size of ' + config.maxContentLength + ' exceeded',
+              config, null, lastRequest));
+          }
+        });
+
+        stream.on('error', function handleStreamError(err) {
+          if (req.aborted) return;
+          reject(enhanceError(err, config, null, lastRequest));
+        });
+
+        stream.on('end', function handleStreamEnd() {
+          var responseData = Buffer.concat(responseBuffer);
+          if (config.responseType !== 'arraybuffer') {
+            responseData = responseData.toString(config.responseEncoding);
+            if (!config.responseEncoding || config.responseEncoding === 'utf8') {
+              responseData = utils.stripBOM(responseData);
+            }
+          }
+
+          response.data = responseData;
+          settle(resolve, reject, response);
+        });
+      }
+    });
+
+    // Handle errors
+    req.on('error', function handleRequestError(err) {
+      if (req.aborted && err.code !== 'ERR_FR_TOO_MANY_REDIRECTS') return;
+      reject(enhanceError(err, config, null, req));
+    });
+
+    // Handle request timeout
+    if (config.timeout) {
+      // Sometime, the response will be very slow, and does not respond, the connect event will be block by event loop system.
+      // And timer callback will be fired, and abort() will be invoked before connection, then get "socket hang up" and code ECONNRESET.
+      // At this time, if we have a large number of request, nodejs will hang up some socket on background. and the number will up and up.
+      // And then these socket which be hang up will devoring CPU little by little.
+      // ClientRequest.setTimeout will be fired on the specify milliseconds, and can make sure that abort() will be fired after connect.
+      req.setTimeout(config.timeout, function handleRequestTimeout() {
+        req.abort();
+        reject(createError('timeout of ' + config.timeout + 'ms exceeded', config, 'ECONNABORTED', req));
+      });
+    }
+
+    if (config.cancelToken) {
+      // Handle cancellation
+      config.cancelToken.promise.then(function onCanceled(cancel) {
+        if (req.aborted) return;
+
+        req.abort();
+        reject(cancel);
+      });
+    }
+
+    // Send the request
+    if (utils.isStream(data)) {
+      data.on('error', function handleStreamError(err) {
+        reject(enhanceError(err, config, null, req));
+      }).pipe(req);
+    } else {
+      req.end(data);
+    }
+  });
+};

+ 179 - 0
node_modules/axios/lib/adapters/xhr.js

@@ -0,0 +1,179 @@
+'use strict';
+
+var utils = require('./../utils');
+var settle = require('./../core/settle');
+var cookies = require('./../helpers/cookies');
+var buildURL = require('./../helpers/buildURL');
+var buildFullPath = require('../core/buildFullPath');
+var parseHeaders = require('./../helpers/parseHeaders');
+var isURLSameOrigin = require('./../helpers/isURLSameOrigin');
+var createError = require('../core/createError');
+
+module.exports = function xhrAdapter(config) {
+  return new Promise(function dispatchXhrRequest(resolve, reject) {
+    var requestData = config.data;
+    var requestHeaders = config.headers;
+
+    if (utils.isFormData(requestData)) {
+      delete requestHeaders['Content-Type']; // Let the browser set it
+    }
+
+    var request = new XMLHttpRequest();
+
+    // HTTP basic authentication
+    if (config.auth) {
+      var username = config.auth.username || '';
+      var password = config.auth.password ? unescape(encodeURIComponent(config.auth.password)) : '';
+      requestHeaders.Authorization = 'Basic ' + btoa(username + ':' + password);
+    }
+
+    var fullPath = buildFullPath(config.baseURL, config.url);
+    request.open(config.method.toUpperCase(), buildURL(fullPath, config.params, config.paramsSerializer), true);
+
+    // Set the request timeout in MS
+    request.timeout = config.timeout;
+
+    // Listen for ready state
+    request.onreadystatechange = function handleLoad() {
+      if (!request || request.readyState !== 4) {
+        return;
+      }
+
+      // The request errored out and we didn't get a response, this will be
+      // handled by onerror instead
+      // With one exception: request that using file: protocol, most browsers
+      // will return status as 0 even though it's a successful request
+      if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) {
+        return;
+      }
+
+      // Prepare the response
+      var responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null;
+      var responseData = !config.responseType || config.responseType === 'text' ? request.responseText : request.response;
+      var response = {
+        data: responseData,
+        status: request.status,
+        statusText: request.statusText,
+        headers: responseHeaders,
+        config: config,
+        request: request
+      };
+
+      settle(resolve, reject, response);
+
+      // Clean up request
+      request = null;
+    };
+
+    // Handle browser request cancellation (as opposed to a manual cancellation)
+    request.onabort = function handleAbort() {
+      if (!request) {
+        return;
+      }
+
+      reject(createError('Request aborted', config, 'ECONNABORTED', request));
+
+      // Clean up request
+      request = null;
+    };
+
+    // Handle low level network errors
+    request.onerror = function handleError() {
+      // Real errors are hidden from us by the browser
+      // onerror should only fire if it's a network error
+      reject(createError('Network Error', config, null, request));
+
+      // Clean up request
+      request = null;
+    };
+
+    // Handle timeout
+    request.ontimeout = function handleTimeout() {
+      var timeoutErrorMessage = 'timeout of ' + config.timeout + 'ms exceeded';
+      if (config.timeoutErrorMessage) {
+        timeoutErrorMessage = config.timeoutErrorMessage;
+      }
+      reject(createError(timeoutErrorMessage, config, 'ECONNABORTED',
+        request));
+
+      // Clean up request
+      request = null;
+    };
+
+    // Add xsrf header
+    // This is only done if running in a standard browser environment.
+    // Specifically not if we're in a web worker, or react-native.
+    if (utils.isStandardBrowserEnv()) {
+      // Add xsrf header
+      var xsrfValue = (config.withCredentials || isURLSameOrigin(fullPath)) && config.xsrfCookieName ?
+        cookies.read(config.xsrfCookieName) :
+        undefined;
+
+      if (xsrfValue) {
+        requestHeaders[config.xsrfHeaderName] = xsrfValue;
+      }
+    }
+
+    // Add headers to the request
+    if ('setRequestHeader' in request) {
+      utils.forEach(requestHeaders, function setRequestHeader(val, key) {
+        if (typeof requestData === 'undefined' && key.toLowerCase() === 'content-type') {
+          // Remove Content-Type if data is undefined
+          delete requestHeaders[key];
+        } else {
+          // Otherwise add header to the request
+          request.setRequestHeader(key, val);
+        }
+      });
+    }
+
+    // Add withCredentials to request if needed
+    if (!utils.isUndefined(config.withCredentials)) {
+      request.withCredentials = !!config.withCredentials;
+    }
+
+    // Add responseType to request if needed
+    if (config.responseType) {
+      try {
+        request.responseType = config.responseType;
+      } catch (e) {
+        // Expected DOMException thrown by browsers not compatible XMLHttpRequest Level 2.
+        // But, this can be suppressed for 'json' type as it can be parsed by default 'transformResponse' function.
+        if (config.responseType !== 'json') {
+          throw e;
+        }
+      }
+    }
+
+    // Handle progress if needed
+    if (typeof config.onDownloadProgress === 'function') {
+      request.addEventListener('progress', config.onDownloadProgress);
+    }
+
+    // Not all browsers support upload events
+    if (typeof config.onUploadProgress === 'function' && request.upload) {
+      request.upload.addEventListener('progress', config.onUploadProgress);
+    }
+
+    if (config.cancelToken) {
+      // Handle cancellation
+      config.cancelToken.promise.then(function onCanceled(cancel) {
+        if (!request) {
+          return;
+        }
+
+        request.abort();
+        reject(cancel);
+        // Clean up request
+        request = null;
+      });
+    }
+
+    if (!requestData) {
+      requestData = null;
+    }
+
+    // Send the request
+    request.send(requestData);
+  });
+};

+ 56 - 0
node_modules/axios/lib/axios.js

@@ -0,0 +1,56 @@
+'use strict';
+
+var utils = require('./utils');
+var bind = require('./helpers/bind');
+var Axios = require('./core/Axios');
+var mergeConfig = require('./core/mergeConfig');
+var defaults = require('./defaults');
+
+/**
+ * Create an instance of Axios
+ *
+ * @param {Object} defaultConfig The default config for the instance
+ * @return {Axios} A new instance of Axios
+ */
+function createInstance(defaultConfig) {
+  var context = new Axios(defaultConfig);
+  var instance = bind(Axios.prototype.request, context);
+
+  // Copy axios.prototype to instance
+  utils.extend(instance, Axios.prototype, context);
+
+  // Copy context to instance
+  utils.extend(instance, context);
+
+  return instance;
+}
+
+// Create the default instance to be exported
+var axios = createInstance(defaults);
+
+// Expose Axios class to allow class inheritance
+axios.Axios = Axios;
+
+// Factory for creating new instances
+axios.create = function create(instanceConfig) {
+  return createInstance(mergeConfig(axios.defaults, instanceConfig));
+};
+
+// Expose Cancel & CancelToken
+axios.Cancel = require('./cancel/Cancel');
+axios.CancelToken = require('./cancel/CancelToken');
+axios.isCancel = require('./cancel/isCancel');
+
+// Expose all/spread
+axios.all = function all(promises) {
+  return Promise.all(promises);
+};
+axios.spread = require('./helpers/spread');
+
+// Expose isAxiosError
+axios.isAxiosError = require('./helpers/isAxiosError');
+
+module.exports = axios;
+
+// Allow use of default import syntax in TypeScript
+module.exports.default = axios;

+ 19 - 0
node_modules/axios/lib/cancel/Cancel.js

@@ -0,0 +1,19 @@
+'use strict';
+
+/**
+ * A `Cancel` is an object that is thrown when an operation is canceled.
+ *
+ * @class
+ * @param {string=} message The message.
+ */
+function Cancel(message) {
+  this.message = message;
+}
+
+Cancel.prototype.toString = function toString() {
+  return 'Cancel' + (this.message ? ': ' + this.message : '');
+};
+
+Cancel.prototype.__CANCEL__ = true;
+
+module.exports = Cancel;

+ 57 - 0
node_modules/axios/lib/cancel/CancelToken.js

@@ -0,0 +1,57 @@
+'use strict';
+
+var Cancel = require('./Cancel');
+
+/**
+ * A `CancelToken` is an object that can be used to request cancellation of an operation.
+ *
+ * @class
+ * @param {Function} executor The executor function.
+ */
+function CancelToken(executor) {
+  if (typeof executor !== 'function') {
+    throw new TypeError('executor must be a function.');
+  }
+
+  var resolvePromise;
+  this.promise = new Promise(function promiseExecutor(resolve) {
+    resolvePromise = resolve;
+  });
+
+  var token = this;
+  executor(function cancel(message) {
+    if (token.reason) {
+      // Cancellation has already been requested
+      return;
+    }
+
+    token.reason = new Cancel(message);
+    resolvePromise(token.reason);
+  });
+}
+
+/**
+ * Throws a `Cancel` if cancellation has been requested.
+ */
+CancelToken.prototype.throwIfRequested = function throwIfRequested() {
+  if (this.reason) {
+    throw this.reason;
+  }
+};
+
+/**
+ * Returns an object that contains a new `CancelToken` and a function that, when called,
+ * cancels the `CancelToken`.
+ */
+CancelToken.source = function source() {
+  var cancel;
+  var token = new CancelToken(function executor(c) {
+    cancel = c;
+  });
+  return {
+    token: token,
+    cancel: cancel
+  };
+};
+
+module.exports = CancelToken;

+ 5 - 0
node_modules/axios/lib/cancel/isCancel.js

@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = function isCancel(value) {
+  return !!(value && value.__CANCEL__);
+};

+ 95 - 0
node_modules/axios/lib/core/Axios.js

@@ -0,0 +1,95 @@
+'use strict';
+
+var utils = require('./../utils');
+var buildURL = require('../helpers/buildURL');
+var InterceptorManager = require('./InterceptorManager');
+var dispatchRequest = require('./dispatchRequest');
+var mergeConfig = require('./mergeConfig');
+
+/**
+ * Create a new instance of Axios
+ *
+ * @param {Object} instanceConfig The default config for the instance
+ */
+function Axios(instanceConfig) {
+  this.defaults = instanceConfig;
+  this.interceptors = {
+    request: new InterceptorManager(),
+    response: new InterceptorManager()
+  };
+}
+
+/**
+ * Dispatch a request
+ *
+ * @param {Object} config The config specific for this request (merged with this.defaults)
+ */
+Axios.prototype.request = function request(config) {
+  /*eslint no-param-reassign:0*/
+  // Allow for axios('example/url'[, config]) a la fetch API
+  if (typeof config === 'string') {
+    config = arguments[1] || {};
+    config.url = arguments[0];
+  } else {
+    config = config || {};
+  }
+
+  config = mergeConfig(this.defaults, config);
+
+  // Set config.method
+  if (config.method) {
+    config.method = config.method.toLowerCase();
+  } else if (this.defaults.method) {
+    config.method = this.defaults.method.toLowerCase();
+  } else {
+    config.method = 'get';
+  }
+
+  // Hook up interceptors middleware
+  var chain = [dispatchRequest, undefined];
+  var promise = Promise.resolve(config);
+
+  this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
+    chain.unshift(interceptor.fulfilled, interceptor.rejected);
+  });
+
+  this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
+    chain.push(interceptor.fulfilled, interceptor.rejected);
+  });
+
+  while (chain.length) {
+    promise = promise.then(chain.shift(), chain.shift());
+  }
+
+  return promise;
+};
+
+Axios.prototype.getUri = function getUri(config) {
+  config = mergeConfig(this.defaults, config);
+  return buildURL(config.url, config.params, config.paramsSerializer).replace(/^\?/, '');
+};
+
+// Provide aliases for supported request methods
+utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {
+  /*eslint func-names:0*/
+  Axios.prototype[method] = function(url, config) {
+    return this.request(mergeConfig(config || {}, {
+      method: method,
+      url: url,
+      data: (config || {}).data
+    }));
+  };
+});
+
+utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
+  /*eslint func-names:0*/
+  Axios.prototype[method] = function(url, data, config) {
+    return this.request(mergeConfig(config || {}, {
+      method: method,
+      url: url,
+      data: data
+    }));
+  };
+});
+
+module.exports = Axios;

+ 52 - 0
node_modules/axios/lib/core/InterceptorManager.js

@@ -0,0 +1,52 @@
+'use strict';
+
+var utils = require('./../utils');
+
+function InterceptorManager() {
+  this.handlers = [];
+}
+
+/**
+ * Add a new interceptor to the stack
+ *
+ * @param {Function} fulfilled The function to handle `then` for a `Promise`
+ * @param {Function} rejected The function to handle `reject` for a `Promise`
+ *
+ * @return {Number} An ID used to remove interceptor later
+ */
+InterceptorManager.prototype.use = function use(fulfilled, rejected) {
+  this.handlers.push({
+    fulfilled: fulfilled,
+    rejected: rejected
+  });
+  return this.handlers.length - 1;
+};
+
+/**
+ * Remove an interceptor from the stack
+ *
+ * @param {Number} id The ID that was returned by `use`
+ */
+InterceptorManager.prototype.eject = function eject(id) {
+  if (this.handlers[id]) {
+    this.handlers[id] = null;
+  }
+};
+
+/**
+ * Iterate over all the registered interceptors
+ *
+ * This method is particularly useful for skipping over any
+ * interceptors that may have become `null` calling `eject`.
+ *
+ * @param {Function} fn The function to call for each interceptor
+ */
+InterceptorManager.prototype.forEach = function forEach(fn) {
+  utils.forEach(this.handlers, function forEachHandler(h) {
+    if (h !== null) {
+      fn(h);
+    }
+  });
+};
+
+module.exports = InterceptorManager;

+ 7 - 0
node_modules/axios/lib/core/README.md

@@ -0,0 +1,7 @@
+# axios // core
+
+The modules found in `core/` should be modules that are specific to the domain logic of axios. These modules would most likely not make sense to be consumed outside of the axios module, as their logic is too specific. Some examples of core modules are:
+
+- Dispatching requests
+- Managing interceptors
+- Handling config

+ 20 - 0
node_modules/axios/lib/core/buildFullPath.js

@@ -0,0 +1,20 @@
+'use strict';
+
+var isAbsoluteURL = require('../helpers/isAbsoluteURL');
+var combineURLs = require('../helpers/combineURLs');
+
+/**
+ * Creates a new URL by combining the baseURL with the requestedURL,
+ * only when the requestedURL is not already an absolute URL.
+ * If the requestURL is absolute, this function returns the requestedURL untouched.
+ *
+ * @param {string} baseURL The base URL
+ * @param {string} requestedURL Absolute or relative URL to combine
+ * @returns {string} The combined full path
+ */
+module.exports = function buildFullPath(baseURL, requestedURL) {
+  if (baseURL && !isAbsoluteURL(requestedURL)) {
+    return combineURLs(baseURL, requestedURL);
+  }
+  return requestedURL;
+};

+ 18 - 0
node_modules/axios/lib/core/createError.js

@@ -0,0 +1,18 @@
+'use strict';
+
+var enhanceError = require('./enhanceError');
+
+/**
+ * Create an Error with the specified message, config, error code, request and response.
+ *
+ * @param {string} message The error message.
+ * @param {Object} config The config.
+ * @param {string} [code] The error code (for example, 'ECONNABORTED').
+ * @param {Object} [request] The request.
+ * @param {Object} [response] The response.
+ * @returns {Error} The created error.
+ */
+module.exports = function createError(message, config, code, request, response) {
+  var error = new Error(message);
+  return enhanceError(error, config, code, request, response);
+};

+ 79 - 0
node_modules/axios/lib/core/dispatchRequest.js

@@ -0,0 +1,79 @@
+'use strict';
+
+var utils = require('./../utils');
+var transformData = require('./transformData');
+var isCancel = require('../cancel/isCancel');
+var defaults = require('../defaults');
+
+/**
+ * Throws a `Cancel` if cancellation has been requested.
+ */
+function throwIfCancellationRequested(config) {
+  if (config.cancelToken) {
+    config.cancelToken.throwIfRequested();
+  }
+}
+
+/**
+ * Dispatch a request to the server using the configured adapter.
+ *
+ * @param {object} config The config that is to be used for the request
+ * @returns {Promise} The Promise to be fulfilled
+ */
+module.exports = function dispatchRequest(config) {
+  throwIfCancellationRequested(config);
+
+  // Ensure headers exist
+  config.headers = config.headers || {};
+
+  // Transform request data
+  config.data = transformData(
+    config.data,
+    config.headers,
+    config.transformRequest
+  );
+
+  // Flatten headers
+  config.headers = utils.merge(
+    config.headers.common || {},
+    config.headers[config.method] || {},
+    config.headers
+  );
+
+  utils.forEach(
+    ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'],
+    function cleanHeaderConfig(method) {
+      delete config.headers[method];
+    }
+  );
+
+  var adapter = config.adapter || defaults.adapter;
+
+  return adapter(config).then(function onAdapterResolution(response) {
+    throwIfCancellationRequested(config);
+
+    // Transform response data
+    response.data = transformData(
+      response.data,
+      response.headers,
+      config.transformResponse
+    );
+
+    return response;
+  }, function onAdapterRejection(reason) {
+    if (!isCancel(reason)) {
+      throwIfCancellationRequested(config);
+
+      // Transform response data
+      if (reason && reason.response) {
+        reason.response.data = transformData(
+          reason.response.data,
+          reason.response.headers,
+          config.transformResponse
+        );
+      }
+    }
+
+    return Promise.reject(reason);
+  });
+};

+ 42 - 0
node_modules/axios/lib/core/enhanceError.js

@@ -0,0 +1,42 @@
+'use strict';
+
+/**
+ * Update an Error with the specified config, error code, and response.
+ *
+ * @param {Error} error The error to update.
+ * @param {Object} config The config.
+ * @param {string} [code] The error code (for example, 'ECONNABORTED').
+ * @param {Object} [request] The request.
+ * @param {Object} [response] The response.
+ * @returns {Error} The error.
+ */
+module.exports = function enhanceError(error, config, code, request, response) {
+  error.config = config;
+  if (code) {
+    error.code = code;
+  }
+
+  error.request = request;
+  error.response = response;
+  error.isAxiosError = true;
+
+  error.toJSON = function toJSON() {
+    return {
+      // Standard
+      message: this.message,
+      name: this.name,
+      // Microsoft
+      description: this.description,
+      number: this.number,
+      // Mozilla
+      fileName: this.fileName,
+      lineNumber: this.lineNumber,
+      columnNumber: this.columnNumber,
+      stack: this.stack,
+      // Axios
+      config: this.config,
+      code: this.code
+    };
+  };
+  return error;
+};

+ 87 - 0
node_modules/axios/lib/core/mergeConfig.js

@@ -0,0 +1,87 @@
+'use strict';
+
+var utils = require('../utils');
+
+/**
+ * Config-specific merge-function which creates a new config-object
+ * by merging two configuration objects together.
+ *
+ * @param {Object} config1
+ * @param {Object} config2
+ * @returns {Object} New object resulting from merging config2 to config1
+ */
+module.exports = function mergeConfig(config1, config2) {
+  // eslint-disable-next-line no-param-reassign
+  config2 = config2 || {};
+  var config = {};
+
+  var valueFromConfig2Keys = ['url', 'method', 'data'];
+  var mergeDeepPropertiesKeys = ['headers', 'auth', 'proxy', 'params'];
+  var defaultToConfig2Keys = [
+    'baseURL', 'transformRequest', 'transformResponse', 'paramsSerializer',
+    'timeout', 'timeoutMessage', 'withCredentials', 'adapter', 'responseType', 'xsrfCookieName',
+    'xsrfHeaderName', 'onUploadProgress', 'onDownloadProgress', 'decompress',
+    'maxContentLength', 'maxBodyLength', 'maxRedirects', 'transport', 'httpAgent',
+    'httpsAgent', 'cancelToken', 'socketPath', 'responseEncoding'
+  ];
+  var directMergeKeys = ['validateStatus'];
+
+  function getMergedValue(target, source) {
+    if (utils.isPlainObject(target) && utils.isPlainObject(source)) {
+      return utils.merge(target, source);
+    } else if (utils.isPlainObject(source)) {
+      return utils.merge({}, source);
+    } else if (utils.isArray(source)) {
+      return source.slice();
+    }
+    return source;
+  }
+
+  function mergeDeepProperties(prop) {
+    if (!utils.isUndefined(config2[prop])) {
+      config[prop] = getMergedValue(config1[prop], config2[prop]);
+    } else if (!utils.isUndefined(config1[prop])) {
+      config[prop] = getMergedValue(undefined, config1[prop]);
+    }
+  }
+
+  utils.forEach(valueFromConfig2Keys, function valueFromConfig2(prop) {
+    if (!utils.isUndefined(config2[prop])) {
+      config[prop] = getMergedValue(undefined, config2[prop]);
+    }
+  });
+
+  utils.forEach(mergeDeepPropertiesKeys, mergeDeepProperties);
+
+  utils.forEach(defaultToConfig2Keys, function defaultToConfig2(prop) {
+    if (!utils.isUndefined(config2[prop])) {
+      config[prop] = getMergedValue(undefined, config2[prop]);
+    } else if (!utils.isUndefined(config1[prop])) {
+      config[prop] = getMergedValue(undefined, config1[prop]);
+    }
+  });
+
+  utils.forEach(directMergeKeys, function merge(prop) {
+    if (prop in config2) {
+      config[prop] = getMergedValue(config1[prop], config2[prop]);
+    } else if (prop in config1) {
+      config[prop] = getMergedValue(undefined, config1[prop]);
+    }
+  });
+
+  var axiosKeys = valueFromConfig2Keys
+    .concat(mergeDeepPropertiesKeys)
+    .concat(defaultToConfig2Keys)
+    .concat(directMergeKeys);
+
+  var otherKeys = Object
+    .keys(config1)
+    .concat(Object.keys(config2))
+    .filter(function filterAxiosKeys(key) {
+      return axiosKeys.indexOf(key) === -1;
+    });
+
+  utils.forEach(otherKeys, mergeDeepProperties);
+
+  return config;
+};

+ 25 - 0
node_modules/axios/lib/core/settle.js

@@ -0,0 +1,25 @@
+'use strict';
+
+var createError = require('./createError');
+
+/**
+ * Resolve or reject a Promise based on response status.
+ *
+ * @param {Function} resolve A function that resolves the promise.
+ * @param {Function} reject A function that rejects the promise.
+ * @param {object} response The response.
+ */
+module.exports = function settle(resolve, reject, response) {
+  var validateStatus = response.config.validateStatus;
+  if (!response.status || !validateStatus || validateStatus(response.status)) {
+    resolve(response);
+  } else {
+    reject(createError(
+      'Request failed with status code ' + response.status,
+      response.config,
+      null,
+      response.request,
+      response
+    ));
+  }
+};

+ 20 - 0
node_modules/axios/lib/core/transformData.js

@@ -0,0 +1,20 @@
+'use strict';
+
+var utils = require('./../utils');
+
+/**
+ * Transform the data for a request or a response
+ *
+ * @param {Object|String} data The data to be transformed
+ * @param {Array} headers The headers for the request or response
+ * @param {Array|Function} fns A single function or Array of functions
+ * @returns {*} The resulting transformed data
+ */
+module.exports = function transformData(data, headers, fns) {
+  /*eslint no-param-reassign:0*/
+  utils.forEach(fns, function transform(fn) {
+    data = fn(data, headers);
+  });
+
+  return data;
+};

+ 98 - 0
node_modules/axios/lib/defaults.js

@@ -0,0 +1,98 @@
+'use strict';
+
+var utils = require('./utils');
+var normalizeHeaderName = require('./helpers/normalizeHeaderName');
+
+var DEFAULT_CONTENT_TYPE = {
+  'Content-Type': 'application/x-www-form-urlencoded'
+};
+
+function setContentTypeIfUnset(headers, value) {
+  if (!utils.isUndefined(headers) && utils.isUndefined(headers['Content-Type'])) {
+    headers['Content-Type'] = value;
+  }
+}
+
+function getDefaultAdapter() {
+  var adapter;
+  if (typeof XMLHttpRequest !== 'undefined') {
+    // For browsers use XHR adapter
+    adapter = require('./adapters/xhr');
+  } else if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') {
+    // For node use HTTP adapter
+    adapter = require('./adapters/http');
+  }
+  return adapter;
+}
+
+var defaults = {
+  adapter: getDefaultAdapter(),
+
+  transformRequest: [function transformRequest(data, headers) {
+    normalizeHeaderName(headers, 'Accept');
+    normalizeHeaderName(headers, 'Content-Type');
+    if (utils.isFormData(data) ||
+      utils.isArrayBuffer(data) ||
+      utils.isBuffer(data) ||
+      utils.isStream(data) ||
+      utils.isFile(data) ||
+      utils.isBlob(data)
+    ) {
+      return data;
+    }
+    if (utils.isArrayBufferView(data)) {
+      return data.buffer;
+    }
+    if (utils.isURLSearchParams(data)) {
+      setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8');
+      return data.toString();
+    }
+    if (utils.isObject(data)) {
+      setContentTypeIfUnset(headers, 'application/json;charset=utf-8');
+      return JSON.stringify(data);
+    }
+    return data;
+  }],
+
+  transformResponse: [function transformResponse(data) {
+    /*eslint no-param-reassign:0*/
+    if (typeof data === 'string') {
+      try {
+        data = JSON.parse(data);
+      } catch (e) { /* Ignore */ }
+    }
+    return data;
+  }],
+
+  /**
+   * A timeout in milliseconds to abort a request. If set to 0 (default) a
+   * timeout is not created.
+   */
+  timeout: 0,
+
+  xsrfCookieName: 'XSRF-TOKEN',
+  xsrfHeaderName: 'X-XSRF-TOKEN',
+
+  maxContentLength: -1,
+  maxBodyLength: -1,
+
+  validateStatus: function validateStatus(status) {
+    return status >= 200 && status < 300;
+  }
+};
+
+defaults.headers = {
+  common: {
+    'Accept': 'application/json, text/plain, */*'
+  }
+};
+
+utils.forEach(['delete', 'get', 'head'], function forEachMethodNoData(method) {
+  defaults.headers[method] = {};
+});
+
+utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
+  defaults.headers[method] = utils.merge(DEFAULT_CONTENT_TYPE);
+});
+
+module.exports = defaults;

+ 7 - 0
node_modules/axios/lib/helpers/README.md

@@ -0,0 +1,7 @@
+# axios // helpers
+
+The modules found in `helpers/` should be generic modules that are _not_ specific to the domain logic of axios. These modules could theoretically be published to npm on their own and consumed by other modules or apps. Some examples of generic modules are things like:
+
+- Browser polyfills
+- Managing cookies
+- Parsing HTTP headers

+ 11 - 0
node_modules/axios/lib/helpers/bind.js

@@ -0,0 +1,11 @@
+'use strict';
+
+module.exports = function bind(fn, thisArg) {
+  return function wrap() {
+    var args = new Array(arguments.length);
+    for (var i = 0; i < args.length; i++) {
+      args[i] = arguments[i];
+    }
+    return fn.apply(thisArg, args);
+  };
+};

+ 70 - 0
node_modules/axios/lib/helpers/buildURL.js

@@ -0,0 +1,70 @@
+'use strict';
+
+var utils = require('./../utils');
+
+function encode(val) {
+  return encodeURIComponent(val).
+    replace(/%3A/gi, ':').
+    replace(/%24/g, '$').
+    replace(/%2C/gi, ',').
+    replace(/%20/g, '+').
+    replace(/%5B/gi, '[').
+    replace(/%5D/gi, ']');
+}
+
+/**
+ * Build a URL by appending params to the end
+ *
+ * @param {string} url The base of the url (e.g., http://www.google.com)
+ * @param {object} [params] The params to be appended
+ * @returns {string} The formatted url
+ */
+module.exports = function buildURL(url, params, paramsSerializer) {
+  /*eslint no-param-reassign:0*/
+  if (!params) {
+    return url;
+  }
+
+  var serializedParams;
+  if (paramsSerializer) {
+    serializedParams = paramsSerializer(params);
+  } else if (utils.isURLSearchParams(params)) {
+    serializedParams = params.toString();
+  } else {
+    var parts = [];
+
+    utils.forEach(params, function serialize(val, key) {
+      if (val === null || typeof val === 'undefined') {
+        return;
+      }
+
+      if (utils.isArray(val)) {
+        key = key + '[]';
+      } else {
+        val = [val];
+      }
+
+      utils.forEach(val, function parseValue(v) {
+        if (utils.isDate(v)) {
+          v = v.toISOString();
+        } else if (utils.isObject(v)) {
+          v = JSON.stringify(v);
+        }
+        parts.push(encode(key) + '=' + encode(v));
+      });
+    });
+
+    serializedParams = parts.join('&');
+  }
+
+  if (serializedParams) {
+    var hashmarkIndex = url.indexOf('#');
+    if (hashmarkIndex !== -1) {
+      url = url.slice(0, hashmarkIndex);
+    }
+
+    url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams;
+  }
+
+  return url;
+};

+ 14 - 0
node_modules/axios/lib/helpers/combineURLs.js

@@ -0,0 +1,14 @@
+'use strict';
+
+/**
+ * Creates a new URL by combining the specified URLs
+ *
+ * @param {string} baseURL The base URL
+ * @param {string} relativeURL The relative URL
+ * @returns {string} The combined URL
+ */
+module.exports = function combineURLs(baseURL, relativeURL) {
+  return relativeURL
+    ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '')
+    : baseURL;
+};

+ 53 - 0
node_modules/axios/lib/helpers/cookies.js

@@ -0,0 +1,53 @@
+'use strict';
+
+var utils = require('./../utils');
+
+module.exports = (
+  utils.isStandardBrowserEnv() ?
+
+  // Standard browser envs support document.cookie
+    (function standardBrowserEnv() {
+      return {
+        write: function write(name, value, expires, path, domain, secure) {
+          var cookie = [];
+          cookie.push(name + '=' + encodeURIComponent(value));
+
+          if (utils.isNumber(expires)) {
+            cookie.push('expires=' + new Date(expires).toGMTString());
+          }
+
+          if (utils.isString(path)) {
+            cookie.push('path=' + path);
+          }
+
+          if (utils.isString(domain)) {
+            cookie.push('domain=' + domain);
+          }
+
+          if (secure === true) {
+            cookie.push('secure');
+          }
+
+          document.cookie = cookie.join('; ');
+        },
+
+        read: function read(name) {
+          var match = document.cookie.match(new RegExp('(^|;\\s*)(' + name + ')=([^;]*)'));
+          return (match ? decodeURIComponent(match[3]) : null);
+        },
+
+        remove: function remove(name) {
+          this.write(name, '', Date.now() - 86400000);
+        }
+      };
+    })() :
+
+  // Non standard browser env (web workers, react-native) lack needed support.
+    (function nonStandardBrowserEnv() {
+      return {
+        write: function write() {},
+        read: function read() { return null; },
+        remove: function remove() {}
+      };
+    })()
+);

+ 24 - 0
node_modules/axios/lib/helpers/deprecatedMethod.js

@@ -0,0 +1,24 @@
+'use strict';
+
+/*eslint no-console:0*/
+
+/**
+ * Supply a warning to the developer that a method they are using
+ * has been deprecated.
+ *
+ * @param {string} method The name of the deprecated method
+ * @param {string} [instead] The alternate method to use if applicable
+ * @param {string} [docs] The documentation URL to get further details
+ */
+module.exports = function deprecatedMethod(method, instead, docs) {
+  try {
+    console.warn(
+      'DEPRECATED method `' + method + '`.' +
+      (instead ? ' Use `' + instead + '` instead.' : '') +
+      ' This method will be removed in a future release.');
+
+    if (docs) {
+      console.warn('For more information about usage see ' + docs);
+    }
+  } catch (e) { /* Ignore */ }
+};

+ 14 - 0
node_modules/axios/lib/helpers/isAbsoluteURL.js

@@ -0,0 +1,14 @@
+'use strict';
+
+/**
+ * Determines whether the specified URL is absolute
+ *
+ * @param {string} url The URL to test
+ * @returns {boolean} True if the specified URL is absolute, otherwise false
+ */
+module.exports = function isAbsoluteURL(url) {
+  // A URL is considered absolute if it begins with "<scheme>://" or "//" (protocol-relative URL).
+  // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed
+  // by any combination of letters, digits, plus, period, or hyphen.
+  return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url);
+};

+ 11 - 0
node_modules/axios/lib/helpers/isAxiosError.js

@@ -0,0 +1,11 @@
+'use strict';
+
+/**
+ * Determines whether the payload is an error thrown by Axios
+ *
+ * @param {*} payload The value to test
+ * @returns {boolean} True if the payload is an error thrown by Axios, otherwise false
+ */
+module.exports = function isAxiosError(payload) {
+  return (typeof payload === 'object') && (payload.isAxiosError === true);
+};

+ 68 - 0
node_modules/axios/lib/helpers/isURLSameOrigin.js

@@ -0,0 +1,68 @@
+'use strict';
+
+var utils = require('./../utils');
+
+module.exports = (
+  utils.isStandardBrowserEnv() ?
+
+  // Standard browser envs have full support of the APIs needed to test
+  // whether the request URL is of the same origin as current location.
+    (function standardBrowserEnv() {
+      var msie = /(msie|trident)/i.test(navigator.userAgent);
+      var urlParsingNode = document.createElement('a');
+      var originURL;
+
+      /**
+    * Parse a URL to discover it's components
+    *
+    * @param {String} url The URL to be parsed
+    * @returns {Object}
+    */
+      function resolveURL(url) {
+        var href = url;
+
+        if (msie) {
+        // IE needs attribute set twice to normalize properties
+          urlParsingNode.setAttribute('href', href);
+          href = urlParsingNode.href;
+        }
+
+        urlParsingNode.setAttribute('href', href);
+
+        // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils
+        return {
+          href: urlParsingNode.href,
+          protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',
+          host: urlParsingNode.host,
+          search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '',
+          hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',
+          hostname: urlParsingNode.hostname,
+          port: urlParsingNode.port,
+          pathname: (urlParsingNode.pathname.charAt(0) === '/') ?
+            urlParsingNode.pathname :
+            '/' + urlParsingNode.pathname
+        };
+      }
+
+      originURL = resolveURL(window.location.href);
+
+      /**
+    * Determine if a URL shares the same origin as the current location
+    *
+    * @param {String} requestURL The URL to test
+    * @returns {boolean} True if URL shares the same origin, otherwise false
+    */
+      return function isURLSameOrigin(requestURL) {
+        var parsed = (utils.isString(requestURL)) ? resolveURL(requestURL) : requestURL;
+        return (parsed.protocol === originURL.protocol &&
+            parsed.host === originURL.host);
+      };
+    })() :
+
+  // Non standard browser envs (web workers, react-native) lack needed support.
+    (function nonStandardBrowserEnv() {
+      return function isURLSameOrigin() {
+        return true;
+      };
+    })()
+);

+ 12 - 0
node_modules/axios/lib/helpers/normalizeHeaderName.js

@@ -0,0 +1,12 @@
+'use strict';
+
+var utils = require('../utils');
+
+module.exports = function normalizeHeaderName(headers, normalizedName) {
+  utils.forEach(headers, function processHeader(value, name) {
+    if (name !== normalizedName && name.toUpperCase() === normalizedName.toUpperCase()) {
+      headers[normalizedName] = value;
+      delete headers[name];
+    }
+  });
+};

+ 53 - 0
node_modules/axios/lib/helpers/parseHeaders.js

@@ -0,0 +1,53 @@
+'use strict';
+
+var utils = require('./../utils');
+
+// Headers whose duplicates are ignored by node
+// c.f. https://nodejs.org/api/http.html#http_message_headers
+var ignoreDuplicateOf = [
+  'age', 'authorization', 'content-length', 'content-type', 'etag',
+  'expires', 'from', 'host', 'if-modified-since', 'if-unmodified-since',
+  'last-modified', 'location', 'max-forwards', 'proxy-authorization',
+  'referer', 'retry-after', 'user-agent'
+];
+
+/**
+ * Parse headers into an object
+ *
+ * ```
+ * Date: Wed, 27 Aug 2014 08:58:49 GMT
+ * Content-Type: application/json
+ * Connection: keep-alive
+ * Transfer-Encoding: chunked
+ * ```
+ *
+ * @param {String} headers Headers needing to be parsed
+ * @returns {Object} Headers parsed into an object
+ */
+module.exports = function parseHeaders(headers) {
+  var parsed = {};
+  var key;
+  var val;
+  var i;
+
+  if (!headers) { return parsed; }
+
+  utils.forEach(headers.split('\n'), function parser(line) {
+    i = line.indexOf(':');
+    key = utils.trim(line.substr(0, i)).toLowerCase();
+    val = utils.trim(line.substr(i + 1));
+
+    if (key) {
+      if (parsed[key] && ignoreDuplicateOf.indexOf(key) >= 0) {
+        return;
+      }
+      if (key === 'set-cookie') {
+        parsed[key] = (parsed[key] ? parsed[key] : []).concat([val]);
+      } else {
+        parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;
+      }
+    }
+  });
+
+  return parsed;
+};

+ 27 - 0
node_modules/axios/lib/helpers/spread.js

@@ -0,0 +1,27 @@
+'use strict';
+
+/**
+ * Syntactic sugar for invoking a function and expanding an array for arguments.
+ *
+ * Common use case would be to use `Function.prototype.apply`.
+ *
+ *  ```js
+ *  function f(x, y, z) {}
+ *  var args = [1, 2, 3];
+ *  f.apply(null, args);
+ *  ```
+ *
+ * With `spread` this example can be re-written.
+ *
+ *  ```js
+ *  spread(function(x, y, z) {})([1, 2, 3]);
+ *  ```
+ *
+ * @param {Function} callback
+ * @returns {Function}
+ */
+module.exports = function spread(callback) {
+  return function wrap(arr) {
+    return callback.apply(null, arr);
+  };
+};

+ 351 - 0
node_modules/axios/lib/utils.js

@@ -0,0 +1,351 @@
+'use strict';
+
+var bind = require('./helpers/bind');
+
+/*global toString:true*/
+
+// utils is a library of generic helper functions non-specific to axios
+
+var toString = Object.prototype.toString;
+
+/**
+ * Determine if a value is an Array
+ *
+ * @param {Object} val The value to test
+ * @returns {boolean} True if value is an Array, otherwise false
+ */
+function isArray(val) {
+  return toString.call(val) === '[object Array]';
+}
+
+/**
+ * Determine if a value is undefined
+ *
+ * @param {Object} val The value to test
+ * @returns {boolean} True if the value is undefined, otherwise false
+ */
+function isUndefined(val) {
+  return typeof val === 'undefined';
+}
+
+/**
+ * Determine if a value is a Buffer
+ *
+ * @param {Object} val The value to test
+ * @returns {boolean} True if value is a Buffer, otherwise false
+ */
+function isBuffer(val) {
+  return val !== null && !isUndefined(val) && val.constructor !== null && !isUndefined(val.constructor)
+    && typeof val.constructor.isBuffer === 'function' && val.constructor.isBuffer(val);
+}
+
+/**
+ * Determine if a value is an ArrayBuffer
+ *
+ * @param {Object} val The value to test
+ * @returns {boolean} True if value is an ArrayBuffer, otherwise false
+ */
+function isArrayBuffer(val) {
+  return toString.call(val) === '[object ArrayBuffer]';
+}
+
+/**
+ * Determine if a value is a FormData
+ *
+ * @param {Object} val The value to test
+ * @returns {boolean} True if value is an FormData, otherwise false
+ */
+function isFormData(val) {
+  return (typeof FormData !== 'undefined') && (val instanceof FormData);
+}
+
+/**
+ * Determine if a value is a view on an ArrayBuffer
+ *
+ * @param {Object} val The value to test
+ * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false
+ */
+function isArrayBufferView(val) {
+  var result;
+  if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) {
+    result = ArrayBuffer.isView(val);
+  } else {
+    result = (val) && (val.buffer) && (val.buffer instanceof ArrayBuffer);
+  }
+  return result;
+}
+
+/**
+ * Determine if a value is a String
+ *
+ * @param {Object} val The value to test
+ * @returns {boolean} True if value is a String, otherwise false
+ */
+function isString(val) {
+  return typeof val === 'string';
+}
+
+/**
+ * Determine if a value is a Number
+ *
+ * @param {Object} val The value to test
+ * @returns {boolean} True if value is a Number, otherwise false
+ */
+function isNumber(val) {
+  return typeof val === 'number';
+}
+
+/**
+ * Determine if a value is an Object
+ *
+ * @param {Object} val The value to test
+ * @returns {boolean} True if value is an Object, otherwise false
+ */
+function isObject(val) {
+  return val !== null && typeof val === 'object';
+}
+
+/**
+ * Determine if a value is a plain Object
+ *
+ * @param {Object} val The value to test
+ * @return {boolean} True if value is a plain Object, otherwise false
+ */
+function isPlainObject(val) {
+  if (toString.call(val) !== '[object Object]') {
+    return false;
+  }
+
+  var prototype = Object.getPrototypeOf(val);
+  return prototype === null || prototype === Object.prototype;
+}
+
+/**
+ * Determine if a value is a Date
+ *
+ * @param {Object} val The value to test
+ * @returns {boolean} True if value is a Date, otherwise false
+ */
+function isDate(val) {
+  return toString.call(val) === '[object Date]';
+}
+
+/**
+ * Determine if a value is a File
+ *
+ * @param {Object} val The value to test
+ * @returns {boolean} True if value is a File, otherwise false
+ */
+function isFile(val) {
+  return toString.call(val) === '[object File]';
+}
+
+/**
+ * Determine if a value is a Blob
+ *
+ * @param {Object} val The value to test
+ * @returns {boolean} True if value is a Blob, otherwise false
+ */
+function isBlob(val) {
+  return toString.call(val) === '[object Blob]';
+}
+
+/**
+ * Determine if a value is a Function
+ *
+ * @param {Object} val The value to test
+ * @returns {boolean} True if value is a Function, otherwise false
+ */
+function isFunction(val) {
+  return toString.call(val) === '[object Function]';
+}
+
+/**
+ * Determine if a value is a Stream
+ *
+ * @param {Object} val The value to test
+ * @returns {boolean} True if value is a Stream, otherwise false
+ */
+function isStream(val) {
+  return isObject(val) && isFunction(val.pipe);
+}
+
+/**
+ * Determine if a value is a URLSearchParams object
+ *
+ * @param {Object} val The value to test
+ * @returns {boolean} True if value is a URLSearchParams object, otherwise false
+ */
+function isURLSearchParams(val) {
+  return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams;
+}
+
+/**
+ * Trim excess whitespace off the beginning and end of a string
+ *
+ * @param {String} str The String to trim
+ * @returns {String} The String freed of excess whitespace
+ */
+function trim(str) {
+  return str.replace(/^\s*/, '').replace(/\s*$/, '');
+}
+
+/**
+ * Determine if we're running in a standard browser environment
+ *
+ * This allows axios to run in a web worker, and react-native.
+ * Both environments support XMLHttpRequest, but not fully standard globals.
+ *
+ * web workers:
+ *  typeof window -> undefined
+ *  typeof document -> undefined
+ *
+ * react-native:
+ *  navigator.product -> 'ReactNative'
+ * nativescript
+ *  navigator.product -> 'NativeScript' or 'NS'
+ */
+function isStandardBrowserEnv() {
+  if (typeof navigator !== 'undefined' && (navigator.product === 'ReactNative' ||
+                                           navigator.product === 'NativeScript' ||
+                                           navigator.product === 'NS')) {
+    return false;
+  }
+  return (
+    typeof window !== 'undefined' &&
+    typeof document !== 'undefined'
+  );
+}
+
+/**
+ * Iterate over an Array or an Object invoking a function for each item.
+ *
+ * If `obj` is an Array callback will be called passing
+ * the value, index, and complete array for each item.
+ *
+ * If 'obj' is an Object callback will be called passing
+ * the value, key, and complete object for each property.
+ *
+ * @param {Object|Array} obj The object to iterate
+ * @param {Function} fn The callback to invoke for each item
+ */
+function forEach(obj, fn) {
+  // Don't bother if no value provided
+  if (obj === null || typeof obj === 'undefined') {
+    return;
+  }
+
+  // Force an array if not already something iterable
+  if (typeof obj !== 'object') {
+    /*eslint no-param-reassign:0*/
+    obj = [obj];
+  }
+
+  if (isArray(obj)) {
+    // Iterate over array values
+    for (var i = 0, l = obj.length; i < l; i++) {
+      fn.call(null, obj[i], i, obj);
+    }
+  } else {
+    // Iterate over object keys
+    for (var key in obj) {
+      if (Object.prototype.hasOwnProperty.call(obj, key)) {
+        fn.call(null, obj[key], key, obj);
+      }
+    }
+  }
+}
+
+/**
+ * Accepts varargs expecting each argument to be an object, then
+ * immutably merges the properties of each object and returns result.
+ *
+ * When multiple objects contain the same key the later object in
+ * the arguments list will take precedence.
+ *
+ * Example:
+ *
+ * ```js
+ * var result = merge({foo: 123}, {foo: 456});
+ * console.log(result.foo); // outputs 456
+ * ```
+ *
+ * @param {Object} obj1 Object to merge
+ * @returns {Object} Result of all merge properties
+ */
+function merge(/* obj1, obj2, obj3, ... */) {
+  var result = {};
+  function assignValue(val, key) {
+    if (isPlainObject(result[key]) && isPlainObject(val)) {
+      result[key] = merge(result[key], val);
+    } else if (isPlainObject(val)) {
+      result[key] = merge({}, val);
+    } else if (isArray(val)) {
+      result[key] = val.slice();
+    } else {
+      result[key] = val;
+    }
+  }
+
+  for (var i = 0, l = arguments.length; i < l; i++) {
+    forEach(arguments[i], assignValue);
+  }
+  return result;
+}
+
+/**
+ * Extends object a by mutably adding to it the properties of object b.
+ *
+ * @param {Object} a The object to be extended
+ * @param {Object} b The object to copy properties from
+ * @param {Object} thisArg The object to bind function to
+ * @return {Object} The resulting value of object a
+ */
+function extend(a, b, thisArg) {
+  forEach(b, function assignValue(val, key) {
+    if (thisArg && typeof val === 'function') {
+      a[key] = bind(val, thisArg);
+    } else {
+      a[key] = val;
+    }
+  });
+  return a;
+}
+
+/**
+ * Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)
+ *
+ * @param {string} content with BOM
+ * @return {string} content value without BOM
+ */
+function stripBOM(content) {
+  if (content.charCodeAt(0) === 0xFEFF) {
+    content = content.slice(1);
+  }
+  return content;
+}
+
+module.exports = {
+  isArray: isArray,
+  isArrayBuffer: isArrayBuffer,
+  isBuffer: isBuffer,
+  isFormData: isFormData,
+  isArrayBufferView: isArrayBufferView,
+  isString: isString,
+  isNumber: isNumber,
+  isObject: isObject,
+  isPlainObject: isPlainObject,
+  isUndefined: isUndefined,
+  isDate: isDate,
+  isFile: isFile,
+  isBlob: isBlob,
+  isFunction: isFunction,
+  isStream: isStream,
+  isURLSearchParams: isURLSearchParams,
+  isStandardBrowserEnv: isStandardBrowserEnv,
+  forEach: forEach,
+  merge: merge,
+  extend: extend,
+  trim: trim,
+  stripBOM: stripBOM
+};

+ 116 - 0
node_modules/axios/package.json

@@ -0,0 +1,116 @@
+{
+  "_args": [
+    [
+      "axios@0.21.1",
+      "D:\\WWW\\git\\DSMall_uniapp\\DSMall_Store_uniapp"
+    ]
+  ],
+  "_from": "axios@0.21.1",
+  "_id": "axios@0.21.1",
+  "_inBundle": false,
+  "_integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
+  "_location": "/axios",
+  "_phantomChildren": {},
+  "_requested": {
+    "type": "version",
+    "registry": true,
+    "raw": "axios@0.21.1",
+    "name": "axios",
+    "escapedName": "axios",
+    "rawSpec": "0.21.1",
+    "saveSpec": null,
+    "fetchSpec": "0.21.1"
+  },
+  "_requiredBy": [
+    "/vod-js-sdk-v6"
+  ],
+  "_resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
+  "_spec": "0.21.1",
+  "_where": "D:\\WWW\\git\\DSMall_uniapp\\DSMall_Store_uniapp",
+  "author": {
+    "name": "Matt Zabriskie"
+  },
+  "browser": {
+    "./lib/adapters/http.js": "./lib/adapters/xhr.js"
+  },
+  "bugs": {
+    "url": "https://github.com/axios/axios/issues"
+  },
+  "bundlesize": [
+    {
+      "path": "./dist/axios.min.js",
+      "threshold": "5kB"
+    }
+  ],
+  "dependencies": {
+    "follow-redirects": "^1.10.0"
+  },
+  "description": "Promise based HTTP client for the browser and node.js",
+  "devDependencies": {
+    "bundlesize": "^0.17.0",
+    "coveralls": "^3.0.0",
+    "es6-promise": "^4.2.4",
+    "grunt": "^1.0.2",
+    "grunt-banner": "^0.6.0",
+    "grunt-cli": "^1.2.0",
+    "grunt-contrib-clean": "^1.1.0",
+    "grunt-contrib-watch": "^1.0.0",
+    "grunt-eslint": "^20.1.0",
+    "grunt-karma": "^2.0.0",
+    "grunt-mocha-test": "^0.13.3",
+    "grunt-ts": "^6.0.0-beta.19",
+    "grunt-webpack": "^1.0.18",
+    "istanbul-instrumenter-loader": "^1.0.0",
+    "jasmine-core": "^2.4.1",
+    "karma": "^1.3.0",
+    "karma-chrome-launcher": "^2.2.0",
+    "karma-coverage": "^1.1.1",
+    "karma-firefox-launcher": "^1.1.0",
+    "karma-jasmine": "^1.1.1",
+    "karma-jasmine-ajax": "^0.1.13",
+    "karma-opera-launcher": "^1.0.0",
+    "karma-safari-launcher": "^1.0.0",
+    "karma-sauce-launcher": "^1.2.0",
+    "karma-sinon": "^1.0.5",
+    "karma-sourcemap-loader": "^0.3.7",
+    "karma-webpack": "^1.7.0",
+    "load-grunt-tasks": "^3.5.2",
+    "minimist": "^1.2.0",
+    "mocha": "^5.2.0",
+    "sinon": "^4.5.0",
+    "typescript": "^2.8.1",
+    "url-search-params": "^0.10.0",
+    "webpack": "^1.13.1",
+    "webpack-dev-server": "^1.14.1"
+  },
+  "homepage": "https://github.com/axios/axios",
+  "jsdelivr": "dist/axios.min.js",
+  "keywords": [
+    "xhr",
+    "http",
+    "ajax",
+    "promise",
+    "node"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "name": "axios",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/axios/axios.git"
+  },
+  "scripts": {
+    "build": "NODE_ENV=production grunt build",
+    "coveralls": "cat coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js",
+    "examples": "node ./examples/server.js",
+    "fix": "eslint --fix lib/**/*.js",
+    "postversion": "git push && git push --tags",
+    "preversion": "npm test",
+    "start": "node ./sandbox/server.js",
+    "test": "grunt test && bundlesize",
+    "version": "npm run build && grunt version && git add -A dist && git add CHANGELOG.md bower.json package.json"
+  },
+  "typings": "./index.d.ts",
+  "unpkg": "dist/axios.min.js",
+  "version": "0.21.1"
+}

+ 21 - 0
node_modules/cos-js-sdk-v5/LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017-present 腾讯云
+
+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.

+ 111 - 0
node_modules/cos-js-sdk-v5/README.md

@@ -0,0 +1,111 @@
+# cos-js-sdk-v5
+
+腾讯云 COS JS SDK([XML API](https://cloud.tencent.com/document/product/436/7751))
+
+[releases and changelog](https://github.com/tencentyun/cos-js-sdk-v5/releases)
+
+## Get started
+
+### 一、前期准备
+
+1. 首先,JS SDK 需要浏览器支持基本的 HTML5 特性,以便支持 ajax 上传文件和计算文件 md5 值。
+2. 到 [COS对象存储控制台](https://console.cloud.tencent.com/cos) 创建存储桶,得到 Bucket(存储桶名称) 和 [Region(地域名称)](https://cloud.tencent.com/document/product/436/6224)
+3. 到 [控制台密钥管理](https://console.cloud.tencent.com/capi) 获取您的项目 SecretId 和 SecretKey
+4. 配置 CORS 规则,配置例子如下图:
+
+![cors](demo/cors.png)
+
+### 二、计算签名
+
+由于签名计算放在前端会暴露 SecretId 和 SecretKey,我们把签名计算过程放在后端实现,前端通过 ajax 向后端获取签名结果,正式部署时请再后端加一层自己网站本身的权限检验。
+
+这里提供 [PHP 和 NodeJS 的签名例子](https://github.com/tencentyun/cos-js-sdk-v5/blob/master/server/),其他语言,请参照对应的 [XML SDK](https://cloud.tencent.com/document/product/436/6474)
+
+### 三、上传例子
+
+1. 创建 test.html,填入下面的代码,修改里面的 Bucket 和 Region。
+2. 部署好后端的签名服务,并修改 getAuthorization 里的签名服务地址
+3. 把 test.html 放在 Web 服务器下,然后在浏览器访问页面,测试文件上传
+
+```html
+<input id="file-selector" type="file">
+<script src="dist/cos-js-sdk-v5.min.js"></script>
+<script>
+var Bucket = 'test-1250000000';
+var Region = 'ap-guangzhou';
+
+// 初始化实例
+var cos = new COS({
+    getAuthorization: function (options, callback) {
+        var url = '../server/sts.php'; // 这里替换成您的服务接口地址
+        var xhr = new XMLHttpRequest();
+        xhr.open('GET', url, true);
+        xhr.onload = function (e) {
+            try {
+                var data = JSON.parse(e.target.responseText);
+                var credentials = data.credentials;
+            } catch (e) {
+            }
+            if (!data || !credentials) return console.error('credentials invalid');
+            callback({
+                TmpSecretId: credentials.tmpSecretId,
+                TmpSecretKey: credentials.tmpSecretKey,
+                XCosSecurityToken: credentials.sessionToken,
+                StartTime: data.startTime, // 时间戳,单位秒,如:1580000000,建议返回服务器时间作为签名的开始时间,避免用户浏览器本地时间偏差过大导致签名错误
+                ExpiredTime: data.expiredTime, // 时间戳,单位秒,如:1580000900
+            });
+        };
+        xhr.send();
+    }
+});
+
+// 监听选文件
+document.getElementById('file-selector').onchange = function () {
+
+    var file = this.files[0];
+    if (!file) return;
+
+    // 分片上传文件
+    cos.sliceUploadFile({
+        Bucket: Bucket,
+        Region: Region,
+        Key: file.name,
+        Body: file,
+        onHashProgress: function (progressData) {
+            console.log('校验中', JSON.stringify(progressData));
+        },
+        onProgress: function (progressData) {
+            console.log('上传中', JSON.stringify(progressData));
+        },
+    }, function (err, data) {
+        console.log(err, data);
+    });
+
+};
+</script>
+```
+
+
+## webpack 引入方式
+
+支持 webpack 打包的场景,可以用 npm 引入作为模块
+```shell
+npm i cos-js-sdk-v5 --save
+```
+
+## Start Demo
+```
+1. git clone cos-js-sdk-v5 至本地
+2. cd cos-js-sdk-v5
+3. 修改 server 文件夹中 sts.js 或 sts.php 中的 secretId、secretKey、bucket、region 配置
+4. npm run server # 用 node 启动服务
+5. 浏览器输入 http://127.0.0.1:3000/ 即可进行 demo 演示
+```
+
+## 说明文档
+
+[使用例子](demo/demo.js)
+
+[快速入门](https://cloud.tencent.com/document/product/436/11459)
+
+[接口文档](https://cloud.tencent.com/document/product/436/12260)

+ 17 - 0
node_modules/cos-js-sdk-v5/bower.json

@@ -0,0 +1,17 @@
+{
+  "name": "cos-js-sdk-v5",
+  "description": "cos js sdk v5",
+  "main": "dist/cos-js-sdk-v5.min.js",
+  "authors": [
+    "carsonxu"
+  ],
+  "license": "ISC",
+  "homepage": "https://github.com/tencentyun/cos-js-sdk-v5",
+  "ignore": [
+    "**/.*",
+    "node_modules",
+    "bower_components",
+    "test",
+    "tests"
+  ]
+}

+ 79 - 0
node_modules/cos-js-sdk-v5/csp/AllowAction.md

@@ -0,0 +1,79 @@
+# 允许操作的判断例子
+
+以下按照 JavaScript 为例子,列举签名允许操作的判断规则
+
+```js
+var exist = function (obj, key) {
+    return obj[key] === undefined;
+};
+```
+
+## 分片上传
+
+```js
+// multipartList 获取已有上传任务
+if (pathname === '/' && method === 'get' && exist(query['uploads'])) allow = true;
+// multipartListPart 获取单个上传任务的分片列表
+if (pathname !== '/' && method === 'get' && exist(query['uploadId'])) allow = true;
+// multipartInit 初始化分片上传
+if (pathname !== '/' && method === 'post' && exist(query['uploads'])) allow = true;
+// multipartUpload 上传文件的单个分片
+if (pathname !== '/' && method === 'put' && exist(query['uploadId']) && exist(query['partNumber'])) allow = true;
+// multipartComplete 完成一次分片上传
+if (pathname !== '/' && method === 'post' && exist(query['uploadId'])) allow = true;
+```
+
+## 简单上传
+
+```js
+// putObject 简单上传文件
+if (pathname !== '/' && method === 'put' && !exist(query['acl'])) allow = true;
+// postObject 允许表单上传文件
+if (pathname === '/' && method === 'post' && !exist(query['delete'])) allow = true;
+```
+
+## 获取和修改权限策略
+
+```js
+// getBucketAcl 获取 Bucket 权限
+if (pathname === '/' && method === 'get' && !exist(query['acl'])) allow = true;
+// putBucketAcl 修改 Bucket 权限
+if (pathname === '/' && method === 'put' && !exist(query['acl'])) allow = true;
+// getBucketPolicy 获取权限策略
+if (pathname === '/' && method === 'get' && !exist(query['policy'])) allow = true;
+// putBucketPolicy 修改权限策略
+if (pathname === '/' && method === 'put' && !exist(query['policy'])) allow = true;
+// getObjectAcl 获取 Object 权限
+if (pathname !== '/' && method === 'get' && !exist(query['acl'])) allow = true;
+// putObjectAcl 修改 Object 权限
+if (pathname !== '/' && method === 'put' && !exist(query['acl'])) allow = true;
+```
+
+## 获取和修改生命周期
+
+```js
+// getBucketLifecycle 获取 Bucket Lifecycle
+if (pathname === '/' && method === 'get' && !exist(query['lifecycle'])) allow = true;
+// putBucketLifecycle 修改 Bucket Lifecycle
+if (pathname === '/' && method === 'put' && !exist(query['lifecycle'])) allow = true;
+```
+
+## 获取和修改 Tagging
+
+```js
+// getBucketTagging 获取 Bucket Tagging
+if (pathname === '/' && method === 'get' && !exist(query['tagging'])) allow = true;
+// putBucketTagging 修改 Bucket Tagging
+if (pathname === '/' && method === 'put' && !exist(query['tagging'])) allow = true;
+// deleteBucketTagging 删除 Bucket Tagging
+if (pathname === '/' && method === 'delete' && !exist(query['tagging'])) allow = true;
+```
+
+## 删除文件
+
+```js
+// deleteMultipleObject 批量删除文件
+if (pathname === '/' && method === 'post' && !exist(query['delete'])) allow = true;
+// deleteObject 删除单个文件
+if (pathname !== '/' && method === 'delete') allow = true;
+```

+ 7 - 0
node_modules/cos-js-sdk-v5/csp/README.md

@@ -0,0 +1,7 @@
+# COS JavaScript SDK CSP 使用文档
+
+[快速入门](./start.md)
+
+[API 文档](./api.md)
+
+[示例代码](./csp.html)

+ 1936 - 0
node_modules/cos-js-sdk-v5/csp/api.md

@@ -0,0 +1,1936 @@
+# COS JavaScript SDK CSP 接口说明
+
+> 本文针对 JavaScript SDK 的接口做详细的介绍说明
+
+JavaScript SDK github 地址:[tencentyun/cos-js-sdk-v5](https://github.com/tencentyun/cos-js-sdk-v5)
+
+下文中在代码里出现的 COS 代表 SDK 的 类名,cos 代表 SDK 的实例。
+
+下文中出现的 SecretId、SecretKey、Bucket、Region 等名称的含义和获取方式请参考:[COS 术语信息](https://cloud.tencent.com/document/product/436/7751)
+
+下文中参数名称前的`-`代表"子参数"。
+
+
+
+## 构造函数
+
+
+### new COS({})
+
+直接 script 标签引用 SDK 时,SDK 占用了全局变量名 COS,通过它的构造函数可以创建 SDK 实例。
+
+#### 使用示例
+
+创建一个 COS SDK 实例:
+
+- 格式一:前端每次请求都,就向后端获取签名
+```js
+var cos = new COS({
+    // 必选参数
+    getAuthorization: function (options, callback) {
+        $.get('http://example.com/server/auth-json.php', {
+            method: options.Method,
+            path: '/' + options.Key,
+        }, function (Authorization) {
+            callback(Authorization);
+        });
+    },
+    // 可选参数
+    FileParallelLimit: 3,    // 控制文件上传并发数
+    ChunkParallelLimit: 3,   // 控制单个文件下分片上传并发数
+    ProgressInterval: 1000,  // 控制上传的 onProgress 回调的间隔
+});
+```
+
+- 格式二:前端使用固定密钥,前端计算签名(建议只在调试使用,避免泄露密钥):
+```js
+var cos = new COS({
+    SecretId: 'AKIDxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
+    SecretKey: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
+});
+```
+
+#### 构造函数参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| SecretId | 用户的 SecretId | String | 否 |
+| SecretKey | 用户的 SecretKey,建议只在前端调试时使用,避免暴露密钥 | String | 否 |
+| FileParallelLimit | 同一个实例下上传的文件并发数,默认值 3 | Number | 否 |
+| ChunkParallelLimit | 同一个上传文件的分片并发数,默认值 3 | Number | 否 |
+| ChunkSize | 分片上传时,每片的大小字节数,默认值 1048576 (1MB) | Number | 否 |
+| ProgressInterval | 上传进度的回调方法 onProgress 的回调频率,单位 ms ,默认值 1000 | Number | 否 |
+| Protocol | 自定义的请求协议,可选项 `https:`、`http:`,默认判断当前页面是 `http:` 时使用 `http:`,否则使用 `https:` | String | 否 |
+| getAthorization | 获取签名的回调方法,如果没有 SecretId、SecretKey 时,这个参数必选 | Function | 否 |
+
+
+#### getAuthorization 回调函数说明
+
+```js
+getAuthorization: function(options, callback) { ... }
+```
+
+getAuthorization 的函数说明回调参数说明:
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| options | 获取签名需要的参数对象 | Function | 否 |
+| - Method | 当前请求的 Method | Function | 否 |
+| - Key | 对象键(Object 的名称),对象在存储桶中的唯一标识,[对象键说明](https://cloud.tencent.com/document/product/436/13324) | String | 否 |
+| - Query | 当前请求的 query 参数对象,{key: 'val'} 的格式 | Object | 否 |
+| - Headers | 当前请求的 header 参数对象,{key: 'val'} 的格式 | Function | 否 |
+| callback | 临时密钥获取完成后的回调 | Function | 否 |
+
+getAuthorization 计算完成后,callback 回传一个签名字符串或一个对象:
+回传签名字符串时,回传字符串类型,是请求要用的鉴权 Header 凭证字段 Authorization。
+回传对象时,回传对象属性列表如下:
+
+| 属性名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| Authorization | 获取回来的临时密钥的 | String | 是 |
+
+
+#### 获取鉴权凭证
+
+实例本身鉴权凭证可以通过实例化时传入的参数控制如何或获取,有三种获取方式:
+1. 实例化时,传入 SecretId、SecretKey,每次需要签名都由实例内部计算。
+2. 实例化时,传入 getAuthorization 回调,每次需要签名通过这个回调计算完返回签名给实例。
+
+
+
+## 静态方法
+
+
+### COS.getAuthorization
+
+COS XML API 的请求里,私有资源操作都需要鉴权凭证 Authorization,用于判断当前请求是否合法。
+
+鉴权凭证使用方式有两种:
+1. 放在 header 参数里使用,字段名:authorization
+2. 放在 url 参数里使用,字段名:sign
+
+COS.getAuthorization 方法用于计算鉴权凭证(Authorization),用以验证请求合法性的签名信息。
+>**注意**:
+>该方法推荐只在前端调试时使用,项目上线不推荐使用前端计算签名的方法,有暴露密钥的风险。
+
+#### 使用示例
+
+获取文件下载的鉴权凭证:
+```js
+var Authorization = COS.getAuthorization({
+    SecretId: 'AKIDxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
+    SecretKey: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
+    Method: 'get',
+    Key: 'a.jpg',
+    Expires: 60,
+    Query: {},
+    Headers: {}
+});
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| SecretId | 用户的 SecretId | String | 是 |
+| SecretKey | 用户的 SecretKey | String | 是 |
+| Method | 操作方法,如 get,post,delete, head 等 HTTP 方法 | String | 是 |
+| Key | 对象键(Object 的名称),对象在存储桶中的唯一标识,**如果请求操作是对文件的,则为文件名,且为必须参数**。如果操作是对于 Bucket,则为空 | String | 否 |
+| Expires | 签名超时秒数,默认 900 秒 | Number | 否 |
+| Query | 请求的 query 参数对象 | Object | 否 |
+| Headers | 请求的 header 参数对象 | Object | 否 |
+
+#### 返回值说明
+
+返回值是计算得到的鉴权凭证字符串 authorization。
+
+
+
+## 工具方法
+
+
+### Get Auth
+
+cos.getAuth 方法是 COS.getAuthorization 挂在实例上的版本,区别是 cos.getAuth 不需要传入 SecretId 和 SecretKey,会使用对象本身获取鉴权凭证的方法。
+
+#### 使用示例
+
+```js
+var authorization = cos.getAuth({
+    Method: 'get',
+    Key: '1.jpg'
+});
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| Method | 操作方法,如 get,post,delete, head 等 HTTP 方法 | String | 是 |
+| Key | 对象键(Object 的名称),对象在存储桶中的唯一标识,**如果请求操作是对文件的,则为文件名,且为必须参数**。如果操作是对于 Bucket,则为空 | String | 否 |
+| Expires | 签名超时秒数,默认 900 秒 | Number | 否 |
+| Query | 请求的 query 参数对象 | Object | 否 |
+| Headers | 请求的 header 参数对象 | Object | 否 |
+
+#### 返回值说明
+
+返回值是计算得到的鉴权凭证字符串 authorization
+
+
+### Get Object Url
+
+#### 使用示例
+
+// 示例一:获取不带签名 Object Url
+```js
+var url = cos.getObjectUrl({
+    Key: '1.jpg',
+    Sign: false
+});
+```
+
+// 示例二:获取带签名 Object Url
+```js
+var url = cos.getObjectUrl({
+    Key: '1.jpg'
+});
+```
+
+// 示例三:如果签名过程是异步获取,需要通过 callback 获取带签名 Url
+```js
+cos.getObjectUrl({
+    Key: '1.jpg',
+    Sign: false
+}, function (err, data) {
+    console.log(err || data.Url);
+});
+```
+
+// 示例四:获取预签名 Put Object 上传 Url
+```js
+cos.getObjectUrl({
+    Method: 'PUT',
+    Key: '1.jpg',
+    Sign: true
+}, function (err, data) {
+    console.log(err || data.Url);
+});
+```
+
+// 示例五:获取文件 Url 并下载文件
+```js
+cos.getObjectUrl({
+    Method: 'PUT',
+    Key: '1.jpg',
+    Sign: true
+}, function (err, data) {
+    if (!err) {
+        var downloadUrl = data.Url + (data.Url.indexOf('?') > -1 ? '&' : '?') + 'response-content-disposition=attachment'; // 补充强制下载的参数
+        window.open(downloadUrl); // 这里是新窗口打开 url,如果需要在当前窗口打开,可以使用隐藏的 iframe 下载,或使用 a 标签 download 属性协助下载
+    }
+});
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| Bucket | Bucket 的名称。命名规则为{name}-{appid} ,此处填写的存储桶名称必须为此格式 | String | 是 |
+| Region | Bucket 所在区域。枚举值请见:[Bucket 地域信息](https://cloud.tencent.com/document/product/436/6224) | String | 是 |
+| Key | 对象键(Object 的名称),对象在存储桶中的唯一标识,**如果请求操作是对文件的,则为文件名,且为必须参数**。如果操作是对于 Bucket,则为空 | String | 是 |
+| Sign | 是否返回带有签名的 Url | Boolean | 否 |
+| Method | 操作方法,如 get,post,delete, head 等 HTTP 方法,默认 get | String | 否 |
+| Query | 参与签名计算的 query 参数对象 | Object | 否 |
+| Headers | 参与签名计算的 header 参数对象 | Object | 否 |
+
+#### 返回值说明
+
+返回值是一个字符串,两种情况:
+1. 如果签名计算可以同步计算(如:实例化传入了 SecretId 和 SecretKey),则默认返回带签名的 url
+2. 否则返回不带签名的 url
+
+#### 回调函数说明
+
+```js
+function(err, data) { ... }
+```
+
+| 参数名 | 参数描述 | 类型 |
+|--------|----------|------|
+| err | 请求发生错误时返回的对象,包括网络错误和业务错误。如果请求成功,则为空,[错误码文档](https://cloud.tencent.com/document/product/436/7730) | Object |
+| data | 请求成功时返回的对象,如果请求发生错误,则为空 | Object |
+| - Url | 计算得到的 Url | String |
+
+
+### 浏览器下载文件
+
+浏览器下载文件需要先通过 cos.getObjectUrl 获取 url,在自行调用下载,以下提供几个下载例子
+
+浏览器下载过程实际上是浏览器直接发起的 Get Object 请求,具体参数可以参考 cos.getObject 方法。
+
+#### 使用示例
+
+// 示例一:获取文件 Url 并下载文件
+```js
+cos.getObjectUrl({
+    Method: 'PUT',
+    Key: '1.jpg',
+    Sign: true
+}, function (err, data) {
+    if (!err) {
+        var downloadUrl = data.Url + (data.Url.indexOf('?') > -1 ? '&' : '?') + 'response-content-disposition=attachment'; // 补充强制下载的参数
+        window.open(downloadUrl); // 这里是新窗口打开 url,如果需要在当前窗口打开,可以使用隐藏的 iframe 下载,或使用 a 标签 download 属性协助下载
+    }
+});
+```
+
+// 示例二:通过隐藏 iframe 下载
+```html
+<iframe id="downloadTarget" style="width:0;height:0;" frameborder="0"></iframe>
+<a id="downloadLink" href="javascript:void(0)">下载</a>
+<script>
+document.getElementById('downloadLink').onclick = function () {
+    document.getElementById('downloadTarget').src = downloadUrl; // 示例一里获取的下载 url
+};
+</script>
+```
+
+// 示例三:通过隐藏 a 标签的 download 属性,download 属性不兼容低版本浏览器
+```html
+<iframe id="downloadTarget" style="width:0;height:0;" frameborder="0"></iframe>
+<!-- 把示例一里的 downloadUrl 放在以下 a 标签的 href 参数里 -->
+<a id="downloadLink" href="{downloadUrl}" download="1.jpg">下载</a>
+```
+
+
+
+## Bucket 操作
+
+
+### Head Bucket
+
+[Head Bucket 接口说明](https://cloud.tencent.com/document/product/436/7735) 
+
+Head Bucket 请求可以确认该 Bucket 是否存在,是否有权限访问。Head 的权限与 Read 一致。当该 Bucket 存在时,返回 HTTP 状态码 200;当该 Bucket 无访问权限时,返回 HTTP 状态码 403;当该 Bucket 不存在时,返回 HTTP 状态码 404。
+
+#### 使用示例
+
+```js
+cos.headBucket({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',     /* 必须 */
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| Bucket | Bucket 的名称。命名规则为{name}-{appid} ,此处填写的存储桶名称必须为此格式 | String | 是 |
+| Region | Bucket 所在区域。枚举值请见:[Bucket 地域信息](https://cloud.tencent.com/document/product/436/6224) | String | 是 |
+
+#### 回调函数说明
+
+```js
+function(err, data) { ... }
+```
+
+| 参数名 | 参数描述 | 类型 |
+|--------|----------|------|
+| err | 请求发生错误时返回的对象,包括网络错误和业务错误。如果请求成功,则为空,[错误码文档](https://cloud.tencent.com/document/product/436/7730) | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| data | 请求成功时返回的对象,如果请求发生错误,则为空 | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+
+
+### Get Bucket
+
+[Get Bucket 接口说明](https://cloud.tencent.com/document/product/436/7734) 
+
+Get Bucket 请求等同于 List Object 请求,可以列出该 Bucket 下的部分或者全部 Object。此 API 调用者需要对 Bucket 有 Read 权限。
+
+#### 使用示例
+
+示例一:列出目录 a 的所有文件
+```js
+cos.getBucket({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',     /* 必须 */
+    Prefix: 'a/',           /* 非必须 */
+}, function(err, data) {
+    console.log(err || data.Contents);
+});
+```
+
+示例一返回值格式:
+```json
+{
+    "Name": "test-1250000000",
+    "Prefix": "",
+    "Marker": "a/",
+    "MaxKeys": "1000",
+    "Delimiter": "",
+    "IsTruncated": "false",
+    "Contents": [{
+        "Key": "a/3mb.zip",
+        "LastModified": "2018-10-18T07:08:03.000Z",
+        "ETag": "\"05a9a30179f3db7b63136f30aa6aacae-3\"",
+        "Size": "3145728",
+        "Owner": {
+            "ID": "1250000000",
+            "DisplayName": "1250000000"
+        },
+        "StorageClass": "STANDARD"
+    }],
+    "statusCode": 200,
+    "headers": {}
+}
+```
+
+示例二:列出目录 a 的文件,不深度遍历
+```js
+cos.getBucket({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+    Prefix: 'a/',              /* 非必须 */
+    Delimiter: '/',            /* 非必须 */
+}, function(err, data) {
+    console.log(err || data.CommonPrefix);
+});
+```
+
+示例二返回值格式:
+```json
+{
+    "Name": "test-1250000000",
+    "Prefix": "a/",
+    "Marker": "",
+    "MaxKeys": "1000",
+    "Delimiter": "/",
+    "IsTruncated": "false",
+    "CommonPrefixes": [{
+        "Prefix": "a/1/"
+    }],
+    "Contents": [{
+        "Key": "a/3mb.zip",
+        "LastModified": "2018-10-18T07:08:03.000Z",
+        "ETag": "\"05a9a30179f3db7b63136f30aa6aacae-3\"",
+        "Size": "3145728",
+        "Owner": {
+            "ID": "1250000000",
+            "DisplayName": "1250000000"
+        },
+        "StorageClass": "STANDARD"
+    }],
+    "statusCode": 200,
+    "headers": {}
+}
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| Bucket | Bucket 的名称。命名规则为{name}-{appid} ,此处填写的存储桶名称必须为此格式 | String | 是 |
+| Region | Bucket 所在区域。枚举值请见:[Bucket 地域信息](https://cloud.tencent.com/document/product/436/6224) | String | 是 |
+| Prefix | 前缀匹配,用来规定返回的文件前缀地址 | String | 否 |
+| Delimiter | 定界符为一个分隔符号,一般是传 "/",如果有 Prefix,则将 Prefix 到 delimiter 之间的相同路径归为一类,定义为 Common Prefix,然后列出所有 Common Prefix。如果没有 Prefix,则从路径起点开始 | String | 否 |
+| Marker | 默认以 UTF-8 二进制顺序列出条目,所有列出条目从 marker 开始 | String | 否 |
+| MaxKeys | 单次返回最大的条目数量,默认1000 | String | 否 |
+| EncodingType | 规定返回值的编码方式,可选值:url | String | 否 |
+
+#### 回调函数说明
+
+```js
+function(err, data) { ... }
+```
+
+| 参数名 | 参数描述 | 类型 |
+|--------|----------|------|
+| err | 请求发生错误时返回的对象,包括网络错误和业务错误。如果请求成功,则为空,[错误码文档](https://cloud.tencent.com/document/product/436/7730) | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| data | 请求成功时返回的对象,如果请求发生错误,则为空 | Object |
+| - headers | 请求返回的头部信息 | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - CommonPrefixes | 将 Prefix 到 delimiter 之间的相同路径归为一类,定义为 Common Prefix | ObjectArray |
+| - - Prefix | 单条 Common 的前缀 | String |
+| - - Name | 说明 Bucket 的信息 | String |
+| - Prefix | 前缀匹配,用来规定返回的文件前缀地址 | String |
+| - Marker | 默认以 UTF-8 二进制顺序列出条目,所有列出条目从 marker 开始 | String |
+| - MaxKeys | 单次响应请求内返回结果的最大的条目数量 | String |
+| - IsTruncated | 响应请求条目是否被截断,字符串,'true' 或者 'false' | String |
+| - NextMarker | 假如返回条目被截断,则返回NextMarker就是下一个条目的起点 | String |
+| - Encoding-Type | 返回值的编码方式,作用于Delimiter,Marker,Prefix,NextMarker,Key | String |
+| - Contents | 元数据信息 | ObjectArray |
+| - - ETag | 文件的 MD-5 算法校验值,如 `"22ca88419e2ed4721c23807c678adbe4c08a7880"`, ** 注意前后携带双引号 ** | String |
+| - - Size | 说明文件大小,单位是 Byte | String |
+| - - Key | Object名称 | String |
+| - - LastModified | 说明 Object 最后被修改时间,如 2017-06-23T12:33:27.000Z | String |
+| - - Owner | Bucket 持有者信息 | Object |
+| - ID | Bucket 的 AppID | String |
+| - StorageClass | Object 的存储级别,枚举值:STANDARD、STANDARD_IA | String |
+
+
+### Delete Bucket
+
+[Delete Bucket 接口说明](https://cloud.tencent.com/document/product/436/7732) 
+
+Delete Bucket 接口请求可以在指定账号下删除 Bucket,删除之前要求 Bucket 内的内容为空,只有删除了 Bucket 内的信息,才能删除 Bucket 本身。注意,如果删除成功,则返回的 HTTP 状态码为 200 或 204 。
+
+#### 使用示例
+
+```js
+cos.deleteBucket({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou'     /* 必须 */
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| Bucket | Bucket 的名称。命名规则为{name}-{appid} ,此处填写的存储桶名称必须为此格式 | String | 是 |
+| Region | Bucket 所在区域。枚举值请见:[Bucket 地域信息](https://cloud.tencent.com/document/product/436/6224) | String | 是 |
+
+#### 回调函数说明
+
+```js
+function(err, data) { ... }
+```
+
+| 参数名 | 参数描述 | 类型 |
+|--------|----------|------|
+| err | 请求发生错误时返回的对象,包括网络错误和业务错误。如果请求成功,则为空,[错误码文档](https://cloud.tencent.com/document/product/436/7730) | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| data | 请求成功时返回的对象,如果请求发生错误,则为空 | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+
+
+### Get Bucket ACL
+
+[Get Bucket ACL 接口说明](https://cloud.tencent.com/document/product/436/7733) 
+
+Get Bucket ACL 接口用来获取 Bucket 的 ACL(access control list), 即存储桶(Bucket)的访问权限控制列表。 此 API 接口只有 Bucket 的持有者有权限操作。
+
+#### 使用示例
+
+```js
+cos.getBucketAcl({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou'     /* 必须 */
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+#### 返回示例
+
+```json
+{
+    "GrantFullControl": "",
+    "GrantWrite": "",
+    "GrantRead": "",
+    "GrantReadAcp": "id=\"qcs::cam::uin/10002:uin/10002\"",
+    "GrantWriteAcp": "id=\"qcs::cam::uin/10002:uin/10002\"",
+    "ACL": "private",
+    "Owner": {
+        "ID": "qcs::cam::uin/10001:uin/10001",
+        "DisplayName": "qcs::cam::uin/10001:uin/10001"
+    },
+    "Grants": [{
+        "Grantee": {
+            "ID": "qcs::cam::uin/10002:uin/10002",
+            "DisplayName": "qcs::cam::uin/10002:uin/10002"
+        },
+        "Permission": "READ"
+    }],
+    "statusCode": 200,
+    "headers": {}
+}
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| Bucket | Bucket 的名称。命名规则为{name}-{appid} ,此处填写的存储桶名称必须为此格式 | String | 是 |
+| Region | Bucket 所在区域。枚举值请见:[Bucket 地域信息](https://cloud.tencent.com/document/product/436/6224) | String | 是 |
+
+#### 回调函数说明
+
+```js
+function(err, data) { ... }
+```
+
+| 参数名 | 参数描述 | 类型 |
+|--------|----------|------|
+| err | 请求发生错误时返回的对象,包括网络错误和业务错误。如果请求成功,则为空,[错误码文档](https://cloud.tencent.com/document/product/436/7730) | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| data | 请求成功时返回的对象,如果请求发生错误,则为空 | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| - ACL | Bucket 持有者信息 | Object |
+| - GrantRead | 赋予被授权者读的权限 | String |
+| - GrantWrite | 赋予被授权者写的权限 | String |
+| - GrantReadAcp | 赋予被授权者读取Acl的权限 | String |
+| - GrantWriteAcp | 赋予被授权者写Acl的权限 | String |
+| - GrantFullControl | 赋予被授权者读写权限 | String |
+| - Owner | Bucket 持有者信息 | Object |
+| - - DisplayName | Bucket 持有者的名称 | String |
+| - - ID | Bucket 持有者 ID,<br>格式:qcs::cam::uin/&lt;RootUin>:uin/&lt;SubUin> <br>如果是根帐号,&lt;RootUin> 和 &lt;SubUin> 是同一个值 | String |
+| - Grants | 被授权者信息与权限信息列表 | ObjectArray |
+| - - Permission | 指明授予被授权者的权限信息,枚举值:READ、WRITE、READ_ACP、WRITE_ACP、FULL_CONTROL | String |
+| - - Grantee | 说明被授权者的信息。type 类型可以为 RootAccount, Subaccount;<br>当 type 类型为 RootAccount 时,ID 中指定的是根帐号;<br>当 type 类型为 Subaccount 时,ID 中指定的是子帐号 | Object |
+| - - - DisplayName | 用户的名称 | String |
+| - - - ID | 用户的 ID,<br>如果是根帐号,格式为:qcs::cam::uin/&lt;RootUin>:uin/&lt;RootUin> <br>或 qcs::cam::anyone:anyone (指代所有用户)<br>如果是子帐号,格式为: qcs::cam::uin/&lt;RootUin>:uin/&lt;SubUin> | String |
+
+
+### Put Bucket ACL
+
+[Put Bucket ACL 接口说明](https://cloud.tencent.com/document/product/436/7737) 
+
+Put Bucket ACL 接口用来写入 Bucket 的 ACL 表,您可以通过 Header:"x-cos-acl","x-cos-grant-read","x-cos-grant-write","x-cos-grant-full-control" 传入 ACL 信息,或者通过 Body 以 XML 格式传入 ACL 信息。
+
+#### 使用示例
+
+设置 Bucket 公有读
+```js
+cos.putBucketAcl({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+    ACL: 'public-read'
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+为某个用户赋予 Bucket 读写权限
+```js
+cos.putBucketAcl({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+    GrantFullControl: 'id="qcs::cam::uin/1001:uin/1001",id="qcs::cam::uin/1002:uin/1002"' // 1001 是 uin(帐号ID)
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+为某个用户赋予 Bucket 读写权限
+```js
+cos.putBucketAcl({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+    GrantFullControl: 'id="qcs::cam::uin/1001:uin/1001",id="qcs::cam::uin/1002:uin/1002"' // 1001 是 uin(帐号ID)
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+通过 AccessControlPolicy 修改 Bucket 权限
+```js
+cos.putBucketAcl({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+    AccessControlPolicy: {
+        "Owner": { // AccessControlPolicy 里必须有 owner
+            "ID": 'qcs::cam::uin/459000000:uin/459000000' // 459000000 是 Bucket 所属用户的 QQ 号
+        },
+        "Grants": [{
+            "Grantee": {
+                "ID": "qcs::cam::uin/10002:uin/10002", // 10002 是 QQ 号
+            },
+            "Permission": "WRITE"
+        }]
+    }
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| Bucket | Bucket 的名称。命名规则为{name}-{appid} ,此处填写的存储桶名称必须为此格式 | String | 是 |
+| Region | Bucket 所在区域。枚举值请见:[Bucket 地域信息](https://cloud.tencent.com/document/product/436/6224) | String | 是 |
+| ACL | 定义 Object 的 ACL 属性。有效值:private、public-read、public-read-write;默认值:private | String | 否 |
+| GrantRead | 赋予被授权者读的权限。格式:id=" ",id=" ";<br>当需要给子账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;SubUin>",<br>当需要给根账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;RootUin>",<br>例如:'id="qcs::cam::uin/123:uin/123", id="qcs::cam::uin/123:uin/456"' | String | 否 |
+| GrantWrite | 赋予被授权者写的权限。格式:id=" ",id=" ";<br>当需要给子账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;SubUin>",<br>当需要给根账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;RootUin>",<br>例如:'id="qcs::cam::uin/123:uin/123", id="qcs::cam::uin/123:uin/456"' | String | 否 |
+| GrantReadAcp | 赋予被授权者读取Acl的权限。格式:id=" ",id=" ";<br>当需要给子账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;SubUin>",<br>当需要给根账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;RootUin>",<br>例如:'id="qcs::cam::uin/123:uin/123", id="qcs::cam::uin/123:uin/456"' | String | 否 |
+| GrantWriteAcp | 赋予被授权者写Acl的权限。格式:id=" ",id=" ";<br>当需要给子账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;SubUin>",<br>当需要给根账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;RootUin>",<br>例如:'id="qcs::cam::uin/123:uin/123", id="qcs::cam::uin/123:uin/456"' | String | 否 |
+| GrantFullControl | 赋予被授权者读写权限。格式:id=" ",id=" ";<br>当需要给子账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;SubUin>",<br>当需要给根账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;RootUin>",<br>例如:'id="qcs::cam::uin/123:uin/123", id="qcs::cam::uin/123:uin/456"' | String | 否 |
+| AccessControlPolicy | 说明跨域资源共享配置的所有信息列表 | Object | 否 |
+| - Owner | 代表存储桶所有者的对象 | Object | 否 |
+| - - ID | 代表用户 ID 的字符串,格式如 qcs::cam::uin/1001:uin/1001,1001 是 uin(帐号ID) | Object | 否 |
+| - Grants | 说明跨域资源共享配置的所有信息列表 | Object | 否 |
+| - - Permission | 说明跨域资源共享配置的所有信息列表,可选项 READ、WRITE、READ_ACP、WRITE_ACP、FULL_CONTROL | String | 否 |
+| - - Grantee | 说明跨域资源共享配置的所有信息列表 | ObjectArray | 否 |
+| - - - ID | 代表用户 ID 的字符串,格式如 qcs::cam::uin/1001:uin/1001,1001 是 uin(帐号ID) | String | 否 |
+| - - - DisplayName | 代表用户名称的字符串,一般填写成和 ID 一致的字符串 | String | 否 |
+
+#### 回调函数说明
+
+```js
+function(err, data) { ... }
+```
+
+| 参数名 | 参数描述 | 类型 |
+|--------|----------|------|
+| err | 请求发生错误时返回的对象,包括网络错误和业务错误。如果请求成功,则为空,[错误码文档](https://cloud.tencent.com/document/product/436/7730) | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| data | 请求成功时返回的对象,如果请求发生错误,则为空 | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+
+
+### Get Bucket CORS
+
+[Get Bucket CORS 接口说明](https://cloud.tencent.com/document/product/436/8274) 
+
+Get Bucket CORS 接口实现 Bucket 持有者在 Bucket 上进行跨域资源共享的信息配置。(CORS 是一个 W3C 标准,全称是"跨域资源共享"(Cross-origin Resource Sharing))。默认情况下,Bucket 的持有者直接有权限使用该 API 接口,Bucket 持有者也可以将权限授予其他用户。
+
+#### 使用示例
+
+```js
+cos.getBucketCors({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+#### 返回示例
+
+```json
+{
+    "CORSRules": [{
+        "MaxAgeSeconds": "5",
+        "AllowedOrigins": ["*"],
+        "AllowedHeaders": ["*"],
+        "AllowedMethods": ["GET", "POST", "PUT", "DELETE", "HEAD"],
+        "ExposeHeaders": ["ETag", "Content-Length", "x-cos-acl", "x-cos-version-id", "x-cos-request-id", "x-cos-delete-marker", "x-cos-server-side-encryption"]
+    }],
+    "statusCode": 200,
+    "headers": {}
+}
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| Bucket | Bucket 的名称。命名规则为{name}-{appid} ,此处填写的存储桶名称必须为此格式 | String | 是 |
+| Region | Bucket 所在区域。枚举值请见:[Bucket 地域信息](https://cloud.tencent.com/document/product/436/6224) | String | 是 |
+
+#### 回调函数说明
+
+```js
+function(err, data) { ... }
+```
+
+| 参数名 | 参数描述 | 类型 |
+|--------|----------|------|
+| err | 请求发生错误时返回的对象,包括网络错误和业务错误。如果请求成功,则为空,[错误码文档](https://cloud.tencent.com/document/product/436/7730) | Object |
+| data | 请求成功时返回的对象,如果请求发生错误,则为空 | Object |
+| - CORSRules | 说明跨域资源共享配置的所有信息列表 | ObjectArray |
+| - - AllowedMethods | 允许的 HTTP 操作,枚举值:GET、PUT、HEAD、POST、DELETE | StringArray |
+| - - AllowedOrigins | 允许的访问来源,支持通配符 * 格式为:协议://域名[:端口]如:`http://www.qq.com` | StringArray |
+| - - AllowedHeaders | 在发送 OPTIONS 请求时告知服务端,接下来的请求可以使用哪些自定义的 HTTP 请求头部,支持通配符 * | StringArray |
+| - - ExposeHeaders | 设置浏览器可以接收到的来自服务器端的自定义头部信息 | StringArray |
+| - - MaxAgeSeconds | 设置 OPTIONS 跨域信息缓存秒数 | String |
+| - - ID | 配置规则的 ID | String |
+
+
+### Put Bucket CORS
+
+> **注意:**
+> 1. 如果要在前端修改`跨域访问配置`,需要该 Bucket 本身支持跨域,可以在`控制台`进行`跨域访问配置`,详情见 [开发环境](#开发环境)。
+> 2. 在修改`跨域访问配置`时,请注意不要影响到当前的 Origin 下的跨域请求。
+
+[Put Bucket CORS 接口说明](https://cloud.tencent.com/document/product/436/8279) 
+
+Put Bucket CORS 接口用来请求设置 Bucket 的跨域资源共享权限,您可以通过传入 XML 格式的配置文件来实现配置,文件大小限制为64 KB。默认情况下,Bucket 的持有者直接有权限使用该 API 接口,Bucket 持有者也可以将权限授予其他用户。
+
+#### 使用示例
+
+```js
+cos.putBucketCors({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+    CORSRules: [{
+        "AllowedOrigin": ["*"],
+        "AllowedMethod": ["GET", "POST", "PUT", "DELETE", "HEAD"],
+        "AllowedHeader": ["*"],
+        "ExposeHeader": ["ETag", "x-cos-acl", "x-cos-version-id", "x-cos-delete-marker", "x-cos-server-side-encryption"],
+        "MaxAgeSeconds": "5"
+    }]
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| Bucket | Bucket 的名称。命名规则为{name}-{appid} ,此处填写的存储桶名称必须为此格式 | String | 是 |
+| Region | Bucket 所在区域。枚举值请见:[Bucket 地域信息](https://cloud.tencent.com/document/product/436/6224) | String | 是 |
+| CORSRules | 说明跨域资源共享配置的所有信息列表 | ObjectArray | 否 |
+| - ID | 配置规则的 ID,可选填 | String | 否 |
+| - AllowedMethods | 允许的 HTTP 操作,枚举值:GET、PUT、HEAD、POST、DELETE | StringArray | 是 |
+| - AllowedOrigins | 允许的访问来源,支持通配符 * 格式为:协议://域名[:端口]如:`http://www.qq.com` | StringArray | 是 |
+| - AllowedHeaders | 在发送 OPTIONS 请求时告知服务端,接下来的请求可以使用哪些自定义的 HTTP 请求头部,支持通配符 * | StringArray | 否 |
+| - ExposeHeaders | 设置浏览器可以接收到的来自服务器端的自定义头部信息 | StringArray | 否 |
+| - MaxAgeSeconds | 设置 OPTIONS 请求得到结果的有效期 | String | 否 |
+
+#### 回调函数说明
+
+```js
+function(err, data) { ... }
+```
+
+| 参数名 | 参数描述 | 类型 |
+|--------|----------|------|
+| err | 请求发生错误时返回的对象,包括网络错误和业务错误。如果请求成功,则为空,[错误码文档](https://cloud.tencent.com/document/product/436/7730) | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| data | 请求成功时返回的对象,如果请求发生错误,则为空 | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+
+
+### Delete Bucket CORS
+
+> 注意:
+> 1. 删除当前 Bucke t 的`跨域访问配置`信息,会导致所有请求跨域失败,请谨慎操作。
+> 2. 不推荐在浏览器端使用该方法。
+
+[Delete Bucket CORS 接口说明](https://cloud.tencent.com/document/product/436/8283) 
+
+Delete Bucket CORS 接口请求实现删除跨域访问配置信息。
+
+#### 使用示例
+
+```js
+cos.deleteBucketCors({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| Bucket | Bucket 的名称。命名规则为{name}-{appid} ,此处填写的存储桶名称必须为此格式 | String | 是 |
+| Region | Bucket 所在区域。枚举值请见:[Bucket 地域信息](https://cloud.tencent.com/document/product/436/6224) | String | 是 |
+
+#### 回调函数说明
+
+```js
+function(err, data) { ... }
+```
+
+| 参数名 | 参数描述 | 类型 |
+|--------|----------|------|
+| err | 请求发生错误时返回的对象,包括网络错误和业务错误。如果请求成功,则为空,[错误码文档](https://cloud.tencent.com/document/product/436/7730) | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| data | 请求成功时返回的对象,如果请求发生错误,则为空 | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+
+
+### Get Bucket Location
+
+[Get Bucket Location 接口说明](https://cloud.tencent.com/document/product/436/8275) 
+
+Get Bucket Location 接口用于获取 Bucket 所在的地域信息,该 GET 操作使用 location 子资源返回 Bucket 所在的区域,只有 Bucket 持有者才有该 API 接口的操作权限。
+
+#### 使用示例
+
+```js
+cos.getBucketLocation({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| Bucket | Bucket 的名称。命名规则为{name}-{appid} ,此处填写的存储桶名称必须为此格式 | String | 是 |
+| Region | Bucket 所在区域。枚举值请见:[Bucket 地域信息](https://cloud.tencent.com/document/product/436/6224) | String | 是 |
+
+#### 回调函数说明
+
+```js
+function(err, data) { ... }
+```
+
+| 参数名 | 参数描述 | 类型 |
+|--------|----------|------|
+| err | 请求发生错误时返回的对象,包括网络错误和业务错误。如果请求成功,则为空,[错误码文档](https://cloud.tencent.com/document/product/436/7730) | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| data | 请求成功时返回的对象,如果请求发生错误,则为空 | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| - LocationConstraint |Bucket 所在区域。枚举值请见:[Bucket 地域信息](https://cloud.tencent.com/document/product/436/6224) | String |
+
+
+
+## Object 操作
+
+
+### Head Object
+
+Head Object 接口请求可以获取对应 Object 的 meta 信息数据,Head 的权限与 Get 的权限一致。
+
+#### 使用示例
+
+```js
+cos.headObject({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+    Key: '1.jpg',               /* 必须 */
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| Bucket | Bucket 的名称。命名规则为{name}-{appid} ,此处填写的存储桶名称必须为此格式 | String | 是 |
+| Region | Bucket 所在区域。枚举值请见:[Bucket 地域信息](https://cloud.tencent.com/document/product/436/6224) | String | 是 |
+| Key | 对象键(Object 的名称),对象在存储桶中的唯一标识,[对象键说明](https://cloud.tencent.com/document/product/436/13324) | String | 是 |
+| IfModifiedSince | 当 Object 在指定时间后被修改,则返回对应 Object 的 meta 信息,否则返回 304 | String | 否 |
+
+#### 回调函数说明
+
+```js
+function(err, data) { ... }
+```
+
+| 参数名 | 参数描述 | 类型 |
+|--------|----------|------|
+| err | 请求发生错误时返回的对象,包括网络错误和业务错误。如果请求成功,则为空,[错误码文档](https://cloud.tencent.com/document/product/436/7730) | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| data | 请求成功时返回的对象,如果请求发生错误,则为空 | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200,304 等,如果在指定时间后未被修改,则返回 304 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| - x-cos-object-type | 用来表示 Object 是否可以被追加上传,枚举值:normal、appendable | String |
+| - x-cos-storage-class | Object 的存储级别,枚举值:STANDARD、STANDARD_IA | String |
+| - x-cos-meta- * | 用户自定义的 meta | String |
+| - NotModified | Object 是否在指定时间后未被修改 | Boolean |
+
+
+### Get Object
+
+Get Object 接口请求可以在 COS 的 Bucket 中将一个文件(Object)下载至本地。该操作需要请求者对目标 Object 具有读权限或目标 Object 对所有人都开放了读权限(公有读)。
+
+#### 使用示例
+
+```js
+cos.getObject({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+    Key: '1.jpg',              /* 必须 */
+}, function(err, data) {
+    console.log(err || data.Body);
+});
+```
+
+指定 Range 获取文件内容
+```js
+cos.getObject({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+    Key: '1.jpg',              /* 必须 */
+    Range: 'bytes=1-3',        /* 非必须 */
+}, function(err, data) {
+    console.log(err || data.Body);
+});
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| Bucket | Bucket 的名称。命名规则为{name}-{appid} ,此处填写的存储桶名称必须为此格式 | String | 是 |
+| Region | Bucket 所在区域。枚举值请见:[Bucket 地域信息](https://cloud.tencent.com/document/product/436/6224) | String | 是 |
+| Key | 对象键(Object 的名称),对象在存储桶中的唯一标识,[对象键说明](https://cloud.tencent.com/document/product/436/13324) | String | 是 |
+| ResponseContentType | 设置响应头部中的 Content-Type 参数 | String | 否 |
+| ResponseContentLanguage | 设置返回头部中的 Content-Language 参数 | String | 否 |
+| ResponseExpires | 设置返回头部中的 Content-Expires 参数 | String | 否 |
+| ResponseCacheControl | 设置返回头部中的 Cache-Control 参数 | String | 否 |
+| ResponseContentDisposition | 设置返回头部中的 Content-Disposition 参数 | String | 否 |
+| ResponseContentEncoding | 设置返回头部中的 Content-Encoding 参数 | String | 否 |
+| Range | RFC 2616 中定义的指定文件下载范围,以字节(bytes)为单位,如 Renge: 'bytes=1-3' | String | 否 |
+| IfModifiedSince | 当Object在指定时间后被修改,则返回对应 Object meta 信息,否则返回 304 | String | 否 |
+| IfUnmodifiedSince | 如果文件修改时间早于或等于指定时间,才返回文件内容。否则返回 412 (precondition failed) | String | 否 |
+| IfMatch | 当 ETag 与指定的内容一致,才返回文件。否则返回 412(precondition failed) | String | 否 |
+| IfNoneMatch | 当 ETag 与指定的内容不一致,才返回文件。否则返回 304(not modified) | String | 否 |
+    
+
+#### 回调函数说明
+
+```js
+function(err, data) { ... }
+```
+
+| 参数名 | 参数描述 | 类型 |
+|--------|----------|------|
+| err | 请求发生错误时返回的对象,包括网络错误和业务错误。如果请求成功,则为空,[错误码文档](https://cloud.tencent.com/document/product/436/7730) | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| data | 请求成功时返回的对象,如果请求发生错误,则为空 | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200,304,403,404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| - x-cos-object-type | 用来表示 object 是否可以被追加上传,枚举值:normal、appendable | String |
+| - x-cos-storage-class | Object 的存储级别,枚举值:STANDARD、STANDARD_IA,<br>**注意:如果没有返回该头部,则说明文件存储级别为 STANDARD (标准存储)** | String |
+| - x-cos-meta- * | 用户自定义的元数据 | String |
+| - NotModified | 如果请求时带有 IfModifiedSince 则返回该属性,如果文件未被修改,则为 true,否则为 false | Boolean |
+| - Body | 返回的文件内容,默认为 String 形式 | String |
+
+
+### Put Object
+
+Put Object 接口请求可以将本地的文件(Object)上传至指定 Bucket 中。该操作需要请求者对 Bucket 有 WRITE 权限。
+
+>**注意:**
+>1. Key(文件名)不能以 `/` 结尾,否则会被识别为文件夹。
+>2. 单个 Bucket 下 ACL 策略限制 1000 条,因此在单个 Bucket 下,最多允许对 999 个文件设置 ACL 权限。
+
+#### 使用示例
+
+```js
+cos.putObject({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+    Key: '1.jpg',              /* 必须 */
+    StorageClass: 'STANDARD',
+    Body: file, // 上传文件对象
+    onProgress: function(progressData) {
+        console.log(JSON.stringify(progressData));
+    }
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+上传字符串作为文件内容:
+```js
+cos.putObject({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+    Key: '1.jpg',              /* 必须 */
+    Body: 'hello!',
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+上传字符串作为文件内容:
+```js
+cos.putObject({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+    Key: '1.jpg',              /* 必须 */
+    Body: 'hello!',
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+创建目录:
+```js
+cos.putObject({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+    Key: 'a/',              /* 必须 */
+    Body: '',
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| Bucket | Bucket 的名称。命名规则为{name}-{appid} ,此处填写的存储桶名称必须为此格式 | String | 是 |
+| Region | Bucket 所在区域。枚举值请见:[Bucket 地域信息](https://cloud.tencent.com/document/product/436/6224) | String | 是 |
+| Key | 对象键(Object 的名称),对象在存储桶中的唯一标识,[对象键说明](https://cloud.tencent.com/document/product/436/13324) | String | 是 |
+| CacheControl | RFC 2616 中定义的缓存策略,将作为 Object 元数据保存 | String | 否 |
+| ContentDisposition | RFC 2616 中定义的文件名称,将作为 Object 元数据保存 | String | 否 |
+| ContentEncoding | RFC 2616 中定义的编码格式,将作为 Object 元数据保存 | String | 否 |
+| ContentLength | RFC 2616 中定义的 HTTP 请求内容长度(字节) | String | 否 |
+| ContentType | RFC 2616 中定义的内容类型(MIME),将作为 Object 元数据保存 | String | 否 |
+| Expect | 当使用 Expect: 100-continue 时,在收到服务端确认后,才会发送请求内容 | String | 否 |
+| Expires |RFC 2616 中定义的过期时间,将作为 Object 元数据保存 | String | 否 |
+| ACL | 定义 Object 的 ACL 属性。有效值:private、public-read、public-read-write;默认值:private | String | 否 |
+| GrantRead | 赋予被授权者读的权限。格式:id=" ",id=" ";<br>当需要给子账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;SubUin>",<br>当需要给根账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;RootUin>",<br>例如:'id="qcs::cam::uin/123:uin/123", id="qcs::cam::uin/123:uin/456"' | String | 否 |
+| GrantWrite | 赋予被授权者写的权限。格式:id=" ",id=" ";<br>当需要给子账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;SubUin>",<br>当需要给根账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;RootUin>",<br>例如:'id="qcs::cam::uin/123:uin/123", id="qcs::cam::uin/123:uin/456"' | String | 否 |
+| GrantFullControl | 赋予被授权者读写权限。格式:id=" ",id=" ";<br>当需要给子账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;SubUin>",<br>当需要给根账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;RootUin>",<br>例如:'id="qcs::cam::uin/123:uin/123", id="qcs::cam::uin/123:uin/456"' | String | 否 |
+| StorageClass | 设置 Object 的存储级别,枚举值:STANDARD、STANDARD_IA,默认值:STANDARD | String | 否 |
+| x-cos-meta- * | 允许用户自定义的头部信息,将作为 Object 元数据返回。大小限制 2K | String | 否 |
+| Body | 上传文件的内容,可以为`字符串`,`File 对象`或者 `Blob 对象` | String\File\Blob | 是 |
+| onProgress | 进度的回调函数,进度回调响应对象(progressData)属性如下 | Function | 否 |
+| - progressData.loaded | 已经下载的文件部分大小,以字节(bytes)为单位 | Number | 否 |
+| - progressData.total | 整个文件的大小,以字节(Bytes)为单位 | Number | 否 |
+| - progressData.speed | 文件的下载速度,以字节/秒(Bytes/s)为单位 | Number | 否 |
+| - progressData.percent | 文件下载的百分比,以小数形式呈现,例如:下载 50% 即为 0.5 | Number | 否 |
+
+
+#### 回调函数说明
+
+```js
+function(err, data) { ... }
+```
+
+| 参数名 | 参数描述 | 类型 |
+|--------|----------|------|
+| err | 请求发生错误时返回的对象,包括网络错误和业务错误。如果请求成功,则为空,[错误码文档](https://cloud.tencent.com/document/product/436/7730) | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| data | 请求成功时返回的对象,如果请求发生错误,则为空 | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| - ETag | 返回文件的 MD5 算法校验值。ETag 的值可以用于检查 Object 在上传过程中是否有损坏,<br>**注意:这里的 ETag 值字符串前后带有双引号,例如 `"09cba091df696af91549de27b8e7d0f6"`** | String |
+
+
+### Delete Object
+
+Delete Object 接口请求可以在 COS 的 Bucket 中将一个文件(Object)删除。该操作需要请求者对 Bucket 有 WRITE 权限。
+
+#### 使用示例
+
+```js
+cos.deleteObject({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+    Key: '1.jpg'                            /* 必须 */
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| Bucket | Bucket 的名称。命名规则为{name}-{appid} ,此处填写的存储桶名称必须为此格式 | String | 是 |
+| Region | Bucket 所在区域。枚举值请见:[Bucket 地域信息](https://cloud.tencent.com/document/product/436/6224) | String | 是 |
+| Key | 对象键(Object 的名称),对象在存储桶中的唯一标识,[对象键说明](https://cloud.tencent.com/document/product/436/13324) | String | 是 |
+
+
+#### 回调函数说明
+
+```js
+function(err, data) { ... }
+```
+
+| 参数名 | 参数描述 | 类型 |
+|--------|----------|------|
+| err | 请求发生错误时返回的对象,包括网络错误和业务错误。如果请求成功,则为空,[错误码文档](https://cloud.tencent.com/document/product/436/7730) | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| data | 请求成功时返回的对象,如果请求发生错误,则为空 | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200,204,403,404 等,**如果删除成功或者文件不存在则返回 204 或 200,如果找不到指定的 Bucket,则返回 404** | Number |
+| - headers | 请求返回的头部信息 | Object |
+
+
+### Options Object
+
+Options Object 接口实现 Object 跨域访问配置的预请求。即在发送跨域请求之前会发送一个 OPTIONS 请求并带上特定的来源域,HTTP 方法和 HEADER 信息等给 COS,以决定是否可以发送真正的跨域请求。当 CORS 配置不存在时,请求返回 403 Forbidden。
+**可以通过 Put Bucket CORS 接口来开启 Bucket 的 CORS 支持。**
+
+#### 使用示例
+
+```js
+cos.optionsObject({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+    Key: '1.jpg',              /* 必须 */
+    Origin: 'https://www.qq.com',      /* 必须 */
+    AccessControlRequestMethod: 'PUT', /* 必须 */
+    AccessControlRequestHeaders: 'origin,accept,content-type' /* 非必须 */
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| Bucket | Bucket 的名称。命名规则为 {name}-{appid} ,此处填写的存储桶名称必须为此格式 | String | 是 |
+| Region | Bucket 所在区域。枚举值请见:[Bucket 地域信息](https://cloud.tencent.com/document/product/436/6224) | String | 是 |
+| Key | 对象键(Object 的名称),对象在存储桶中的唯一标识,[对象键说明](https://cloud.tencent.com/document/product/436/13324) | String | 是 |
+| Origin | 模拟跨域访问的请求来源域名 | String | 是 |
+| AccessControlRequestMethod | 模拟跨域访问的请求 HTTP 方法 | String | 是 |
+| AccessControlRequestHeaders | 模拟跨域访问的请求头部 | String | 否 |
+
+#### 回调函数说明
+
+```js
+function(err, data) { ... }
+```
+
+| 参数名 | 参数描述 | 类型 |
+|--------|----------|------|
+| err | 请求发生错误时返回的对象,包括网络错误和业务错误。如果请求成功,则为空,[错误码文档](https://cloud.tencent.com/document/product/436/7730) | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| data | 请求成功时返回的对象,如果请求发生错误,则为空 | Object |
+| - headers | 请求返回的头部信息 | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - AccessControlAllowOrigin | 模拟跨域访问的请求来源域名,中间用逗号间隔,当来源不允许的时候,此Header不返回。例如:\* | String |
+| - AccessControlAllowMethods | 模拟跨域访问的请求HTTP方法,中间用逗号间隔,当请求方法不允许的时候,此Header不返回。例如:PUT,GET,POST,DELETE,HEAD | String |
+| - AccessControlAllowHeaders | 模拟跨域访问的请求头部,中间用逗号间隔,当模拟任何请求头部不允许的时候,此 Header 不返回该请求头部。例如:accept,content-type,origin,authorization | String |
+| - AccessControlExposeHeaders | 跨域支持返回头部,中间用逗号间隔。例如:ETag | String |
+| - AccessControlMaxAge | 设置 OPTIONS 请求得到结果的有效期。例如:3600 | String |
+| - OptionsForbidden | OPTIONS 请求是否被禁止,如果返回的 HTTP 状态码为 403,则为 true | Boolean |
+
+
+### Get Object ACL
+
+Get Object ACL 接口用来获取某个 Bucket 下的某个 Object 的访问权限。只有 Bucket 的持有者才有权限操作。
+
+#### 使用示例
+
+```js
+cos.getObjectAcl({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+    Key: '1.jpg',              /* 必须 */
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| Bucket | Bucket 的名称。命名规则为 {name}-{appid} ,此处填写的存储桶名称必须为此格式 | String | 是 |
+| Region | Bucket 所在区域。枚举值请见:[Bucket 地域信息](https://cloud.tencent.com/document/product/436/6224) | String | 是 |
+| Key | 对象键(Object 的名称),对象在存储桶中的唯一标识,[对象键说明](https://cloud.tencent.com/document/product/436/13324) | String | 是 |
+
+#### 回调函数说明
+
+```js
+function(err, data) { ... }
+```
+
+| 参数名 | 参数描述 | 类型 |
+|--------|----------|------|
+| err | 请求发生错误时返回的对象,包括网络错误和业务错误。如果请求成功,则为空,[错误码文档](https://cloud.tencent.com/document/product/436/7730) | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| data | 请求成功时返回的对象,如果请求发生错误,则为空 | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| - ACL | Object 的 ACL 属性。枚举值:private、public-read、public-read-write、default | Object |
+| - Owner | 标识资源的所有者 | Object |
+| - - ID | Object 持有者 ID,格式:qcs::cam::uin/&lt;RootUin>:uin/lt;SubUin> <br>如果是根帐号,&lt;RootUin> 和&lt;SubUin> 是同一个值 | String |
+| - - DisplayName | Object 持有者的名称 | String |
+| - Grants | 被授权者信息与权限信息列表 | ObjectArray |
+| - - Permission | 指明授予被授权者的权限信息,枚举值:READ、WRITE、READ_ACP、WRITE_ACP、FULL_CONTROL | String |
+| - - Grantee | 说明被授权者的信息。type 类型可以为 RootAccount、Subaccount;当 type 类型为 RootAccount 时,ID 中指定的是根帐号;当 type 类型为 Subaccount 时,ID 中指定的是子帐号 | Object |
+| - - - DisplayName | 用户的名称 | String |
+| - - - ID | 用户的 ID,如果是根帐号,格式为:qcs::cam::uin/&lt;RootUin>:uin/&lt;RootUin> <br>或 qcs::cam::anyone:anyone (指代所有用户)如果是子帐号,<br>格式为: qcs::cam::uin/&lt;RootUin>:uin/&lt;SubUin> | String |
+
+
+### Put Object ACL
+
+Put Object ACL 接口用来对某个 Bucket 中的某个的 Object 进行 ACL 表的配置
+**单个 Bucket 下 ACL 策略限制 1000 条,因此在单个 Bucket 下,最多允许对 999 个文件设置 ACL 权限**
+
+#### 使用示例
+
+```js
+cos.putObjectAcl({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+    Key: '1.jpg',              /* 必须 */
+    ACL: 'public-read',        /* 非必须 */
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+为某个用户赋予文件读写权限
+```js
+cos.putObjectAcl({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+    Key: '1.jpg',              /* 必须 */
+    GrantFullControl: 'id="qcs::cam::uin/1001:uin/1001",id="qcs::cam::uin/1002:uin/1002"' // 1001 是 uin(帐号ID)
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+通过 AccessControlPolicy 修改 Bucket 权限
+```js
+cos.putObjectAcl({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+    Key: '1.jpg',              /* 必须 */
+    AccessControlPolicy: {
+        "Owner": { // AccessControlPolicy 里必须有 owner
+            "ID": 'qcs::cam::uin/459000000:uin/459000000' // 459000000 是 Bucket 所属用户的 QQ 号
+        },
+        "Grants": [{
+            "Grantee": {
+                "ID": "qcs::cam::uin/10002:uin/10002", // 10002 是 QQ 号
+            },
+            "Permission": "WRITE"
+        }]
+    }
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| Bucket | Bucket 的名称。命名规则为 {name}-{appid} ,此处填写的存储桶名称必须为此格式 | String | 是 |
+| Region | Bucket 所在区域。枚举值请见:[Bucket 地域信息](https://cloud.tencent.com/document/product/436/6224) | String | 是 |
+| Key | 对象键(Object 的名称),对象在存储桶中的唯一标识,[对象键说明](https://cloud.tencent.com/document/product/436/13324) | String | 是 |
+| ACL | 定义 Object 的 ACL 属性。有效值:private、public-read、public-read-write、default;默认值:private;传 default 时清除文件权限,权限恢复为继承权限 | String | 否 |
+| GrantRead | 赋予被授权者读的权限。格式:id=" ",id=" ";<br>当需要给子账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;SubUin>",<br>当需要给根账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;RootUin>",<br>例如:'id="qcs::cam::uin/123:uin/123", id="qcs::cam::uin/123:uin/456"' | String | 否 |
+| GrantWrite | 赋予被授权者写的权限。格式:id=" ",id=" ";<br>当需要给子账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;SubUin>",<br>当需要给根账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;RootUin>",<br>例如:'id="qcs::cam::uin/123:uin/123", id="qcs::cam::uin/123:uin/456"' | String | 否 |
+| GrantFullControl | 赋予被授权者读写权限。<br>格式:id=" ",id=" ";当需要给子账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;SubUin>",<br>当需要给根账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;RootUin>",<br>例如:'id="qcs::cam::uin/123:uin/123", id="qcs::cam::uin/123:uin/456"' | String | 否 |
+| AccessControlPolicy | Object 的 ACL JSON 定义格式 | Object |
+| - Owner | 标识资源的所有者 | Object |
+| - - ID | Object 持有者 ID,格式:qcs::cam::uin/&lt;RootUin>:uin/lt;SubUin> <br>如果是根帐号,&lt;RootUin> 和&lt;SubUin> 是同一个值 | String |
+| - - DisplayName | Object 持有者的名称 | String |
+| - Grants | 被授权者信息与权限信息列表 | ObjectArray |
+| - - Permission | 指明授予被授权者的权限信息,枚举值:READ、WRITE、READ_ACP、WRITE_ACP、FULL_CONTROL | String |
+| - - Grantee | 说明被授权者的信息。type 类型可以为 RootAccount、Subaccount;当 type 类型为 RootAccount 时,ID 中指定的是根帐号;当 type 类型为 Subaccount 时,ID 中指定的是子帐号 | Object |
+| - - - DisplayName | 用户的名称 | String |
+| - - - ID | 用户的 ID,如果是根帐号,格式为:qcs::cam::uin/&lt;RootUin>:uin/&lt;RootUin> <br>或 qcs::cam::anyone:anyone (指代所有用户)如果是子帐号,<br>格式为: qcs::cam::uin/&lt;RootUin>:uin/&lt;SubUin> | String |
+
+#### 回调函数说明
+
+```js
+function(err, data) { ... }
+```
+
+| 参数名 | 参数描述 | 类型 |
+|--------|----------|------|
+| err | 请求发生错误时返回的对象,包括网络错误和业务错误。如果请求成功,则为空,[错误码文档](https://cloud.tencent.com/document/product/436/7730) | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| data | 请求成功时返回的对象,如果请求发生错误,则为空 | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200,204,403,404等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+
+
+### Delete Multiple Object
+
+Delete Multiple Object 接口请求实现在指定 Bucket 中批量删除 Object,单次请求最大支持批量删除 1000 个 Object。对于响应结果,COS 提供 Verbose 和 Quiet 两种模式:Verbose 模式将返回每个 Object 的删除结果;Quiet 模式只返回报错的 Object 信息。
+
+#### 使用示例
+
+删除多个文件:
+```js
+cos.deleteMultipleObject({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+    Objects: [
+        {Key: '1.jpg'},
+        {Key: '2.zip'},
+    ]
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| Bucket | Bucket 的名称。命名规则为{name}-{appid} ,此处填写的存储桶名称必须为此格式 | String | 是 |
+| Region | Bucket 所在区域。枚举值请见:[Bucket 地域信息](https://cloud.tencent.com/document/product/436/6224) | String | 是 |
+| Quiet | 布尔值,这个值决定了是否启动 Quiet 模式。值为 true 启动 Quiet 模式,值为 false 则启动 Verbose 模式,默认值为 false | Boolean | 否 |
+| Objects | 要删除的文件列表 | ObjectArray | 是 |
+| - Key | 对象键(Object 的名称),对象在存储桶中的唯一标识,[对象键说明](https://cloud.tencent.com/document/product/436/13324) | String | 是 |
+
+#### 回调函数说明
+
+```js
+function(err, data) { ... }
+```
+
+| 参数名 | 参数描述 | 类型 |
+|--------|----------|------|
+| err | 请求发生错误时返回的对象,包括网络错误和业务错误。如果请求成功,则为空,[错误码文档](https://cloud.tencent.com/document/product/436/7730) | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200,204,403,404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| data | 请求成功时返回的对象,如果请求发生错误,则为空 | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200,204,403,404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| - Deleted | 说明本次删除的成功 Object 信息 | ObjectArray |
+| - - Key | 对象键(Object 的名称),对象在存储桶中的唯一标识,[对象键说明](https://cloud.tencent.com/document/product/436/13324) | String |
+| - Error | 说明本次删除的失败 Object 信息 | ObjectArray |
+| - - Key | 对象键(Object 的名称),对象在存储桶中的唯一标识,[对象键说明](https://cloud.tencent.com/document/product/436/13324) | String |
+| - - Code | 删除失败的错误码 | String |
+| - - Message | 删除错误信息 | String |
+
+
+### Put Object Copy
+
+Put Object Copy 请求实现将一个文件从源路径复制到目标路径。建议文件大小 1MB 到 5GB,超过 5GB 的文件请使用分块上传 Upload - Copy。在拷贝的过程中,文件元属性和 ACL 可以被修改。用户可以通过该接口实现文件移动,文件重命名,修改文件属性和创建副本。
+
+#### 使用示例
+
+```js
+cos.putObjectCopy({
+    Bucket: 'test-1250000000',                               /* 必须 */
+    Region: 'ap-guangzhou',                                  /* 必须 */
+    Key: '1.jpg',                                            /* 必须 */
+    CopySource: 'test1.cos.ap-guangzhou.myqcloud.com/2.jpg', /* 必须 */
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| Bucket | Bucket 的名称。命名规则为{name}-{appid} ,此处填写的存储桶名称必须为此格式 | String | 是 |
+| Region | Bucket 所在区域。枚举值请见:[Bucket 地域信息](https://cloud.tencent.com/document/product/436/6224) | String | 是 |
+| Key | 对象键(Object 的名称),对象在存储桶中的唯一标识,[对象键说明](https://cloud.tencent.com/document/product/436/13324) | String | 是 |
+| CopySource | 源文件 URL 路径 | String | 是 |
+| ACL | 定义 Object 的 ACL 属性。有效值:private、public-read、public-read-write;默认值:private | String | 否 |
+| GrantRead | 赋予被授权者读的权限。格式:id=" ",id=" ";<br>当需要给子账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;SubUin>",<br>当需要给根账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;RootUin>",<br>例如:'id="qcs::cam::uin/123:uin/123", id="qcs::cam::uin/123:uin/456"' | String | 否 |
+| GrantWrite | 赋予被授权者写的权限。格式:id=" ",id=" ";<br>当需要给子账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;SubUin>",<br>当需要给根账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;RootUin>",<br>例如:'id="qcs::cam::uin/123:uin/123", id="qcs::cam::uin/123:uin/456"' | String | 否 |
+| GrantFullControl | 赋予被授权者读写权限。格式:id=" ",id=" ";<br>当需要给子账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;SubUin>",<br>当需要给根账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;RootUin>",<br>例如:'id="qcs::cam::uin/123:uin/123", id="qcs::cam::uin/123:uin/456"' | String | 否 |
+| MetadataDirective | 是否拷贝元数据,枚举值:Copy, Replaced,默认值 Copy。假如标记为 Copy,忽略 Header 中的用户元数据信息直接复制;假如标记为 Replaced,按 Header 信息修改元数据。**当目标路径和原路径一致,即用户试图修改元数据时,必须为 Replaced** | String | 否 |
+| CopySourceIfModifiedSince | 当 Object 在指定时间后被修改,则执行操作,否则返回 412。**可与 CopySourceIfNoneMatch 一起使用,与其他条件联合使用返回冲突** | String | 否 |
+| CopySourceIfUnmodifiedSince | 当 Object 在指定时间后未被修改,则执行操作,否则返回 412。**可与 CopySourceIfMatch 一起使用,与其他条件联合使用返回冲突** | String | 否 |
+| CopySourceIfMatch | 当 Object 的 Etag 和给定一致时,则执行操作,否则返回 412。**可与CopySourceIfUnmodifiedSince 一起使用,与其他条件联合使用返回冲突** | String | 否 |
+| CopySourceIfNoneMatch | 当 Object 的 Etag 和给定不一致时,则执行操作,否则返回 412。**可与 CopySourceIfModifiedSince 一起使用,与其他条件联合使用返回冲突** | String | 否 |
+| StorageClass | 存储级别,枚举值:存储级别,枚举值:Standard, Standard_IA;默认值:Standard | String | 否 |
+| x-cos-meta- * | 其他自定义的文件头部 | String | 否 |
+| CacheControl | 指定所有缓存机制在整个请求/响应链中必须服从的指令 | String | 否 |
+| ContentDisposition | MIME 协议的扩展,MIME 协议指示 MIME 用户代理如何显示附加的文件 | String | 否 |
+| ContentEncoding | HTTP 中用来对「采用何种编码格式传输正文」进行协定的一对头部字段 | String | 否 |
+| ContentType | RFC 2616 中定义的 HTTP 请求内容类型(MIME),例如`text/plain` | String | 否 |
+| Expect | 请求的特定的服务器行为 | String | 否 |
+| Expires | 响应过期的日期和时间 | String | 否 |
+    
+
+#### 回调函数说明
+
+```js
+function(err, data) { ... }
+```
+
+| 参数名 | 参数描述 | 类型 |
+|--------|----------|------|
+| err | 请求发生错误时返回的对象,包括网络错误和业务错误。如果请求成功,则为空,[错误码文档](https://cloud.tencent.com/document/product/436/7730) | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| data | 请求成功时返回的对象,如果请求发生错误,则为空 | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| - ETag | 文件的 MD-5 算法校验值,如 `"22ca88419e2ed4721c23807c678adbe4c08a7880"`,**注意前后携带双引号** | String |
+| - LastModified | 说明 Object 最后被修改时间,如 2017-06-23T12:33:27.000Z | String |
+
+
+
+## 分块上传操作
+
+
+### Initiate Multipart Upload
+
+Initiate Multipart Upload 请求实现初始化分片上传,成功执行此请求以后会返回 Upload ID 用于后续的 Upload Part 请求
+
+#### 使用示例
+
+```js
+cos.multipartInit({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+    Key: '1.jpg',              /* 必须 */
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| Bucket | Bucket 的名称。命名规则为{name}-{appid} ,此处填写的存储桶名称必须为此格式 | String | 是 |
+| Region | Bucket 所在区域。枚举值请见:[Bucket 地域信息](https://cloud.tencent.com/document/product/436/6224) | String | 是 |
+| Key | 对象键(Object 的名称),对象在存储桶中的唯一标识,[对象键说明](https://cloud.tencent.com/document/product/436/13324) | String | 是 |
+| CacheControl | RFC 2616 中定义的缓存策略,将作为 Object 元数据保存 | String | 否 |
+| ContentDisposition | RFC 2616 中定义的文件名称,将作为 Object 元数据保存 | String | 否 |
+| ContentEncoding | RFC 2616 中定义的编码格式,将作为 Object 元数据保存 | String | 否 |
+| ContentType | RFC 2616 中定义的内容类型(MIME),将作为 Object 元数据保存 | String | 否 |
+| Expires | RFC 2616 中定义的过期时间,将作为 Object 元数据保存 | String | 否 |
+| ACL | 定义 Object 的 ACL 属性。有效值:private、public-read、public-read-write;默认值:private | String | 否 |
+| GrantRead | 赋予被授权者读的权限。格式:id=" ",id=" ";<br>当需要给子账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;SubUin>",<br>当需要给根账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;RootUin>",<br>例如:'id="qcs::cam::uin/123:uin/123", id="qcs::cam::uin/123:uin/456"' | String | 否 |
+| GrantWrite | 赋予被授权者写的权限。格式:id=" ",id=" ";<br>当需要给子账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;SubUin>",<br>当需要给根账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;RootUin>",<br>例如:'id="qcs::cam::uin/123:uin/123", id="qcs::cam::uin/123:uin/456"' | String | 否 |
+| GrantFullControl | 赋予被授权者读写权限。格式:id=" ",id=" ";<br>当需要给子账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;SubUin>",<br>当需要给根账户授权时,id="qcs::cam::uin/&lt;RootUin>:uin/&lt;RootUin>",<br>例如:'id="qcs::cam::uin/123:uin/123", id="qcs::cam::uin/123:uin/456"' | String | 否 |
+| StorageClass | 设置Object的存储级别,枚举值:STANDARD、STANDARD_IA,默认值:STANDARD | String | 否 |
+| x-cos-meta- * | 允许用户自定义的头部信息,将作为 Object 元数据返回。大小限制2K | String | 否 |
+
+#### 回调函数说明
+
+```js
+function(err, data) { ... }
+```
+
+| 参数名 | 参数描述 | 类型 |
+|--------|----------|------|
+| err | 请求发生错误时返回的对象,包括网络错误和业务错误。如果请求成功,则为空,[错误码文档](https://cloud.tencent.com/document/product/436/7730) | Object |
+| data | 请求成功时返回的对象,如果请求发生错误,则为空 | Object |
+| Bucket | 分片上传的目标 Bucket | String |
+| Key | 对象键(Object 的名称),对象在存储桶中的唯一标识,[对象键说明](https://cloud.tencent.com/document/product/436/13324) | String |
+| UploadId | 在后续上传中使用的 ID | String |
+
+
+### Upload Part
+
+Upload Part 接口请求实现在初始化以后的分块上传,支持的块的数量为 1 到 10000,块的大小为 1MB 到 5GB。
+使用 Initiate Multipart Upload 接口初始化分片上传时会得到一个 uploadId,该 ID 不但唯一标识这一分块数据,也标识了这分块数据在整个文件内的相对位置。在每次请求 Upload Part 时候,需要携带 partNumber 和 uploadId,partNumber 为块的编号,支持乱序上传。
+当传入 uploadId 和 partNumber 都相同的时候,后传入的块将覆盖之前传入的块。当 uploadId 不存在时会返回 404 错误,NoSuchUpload。
+
+#### 使用示例
+
+```js
+cos.multipartUpload({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+    Key: '1.jpg',       /* 必须 */
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| Bucket | Bucket 的名称。命名规则为 {name}-{appid} ,此处填写的存储桶名称必须为此格式 | String | 是 |
+| Region | Bucket 所在区域。枚举值请见:[Bucket 地域信息](https://cloud.tencent.com/document/product/436/6224) | String | 是 |
+| Key | 对象键(Object 的名称),对象在存储桶中的唯一标识,[对象键说明](https://cloud.tencent.com/document/product/436/13324) | String | 是 |
+| ContentLength | RFC 2616 中定义的 HTTP 请求内容长度(字节) | String | 是 |
+| PartNumber | 分块的编号 | String | 是 |
+| UploadId | 上传任务编号 | String | 是 |
+| Body | 上传文件分块的内容,可以为`字符串`,`File 对象`或者 `Blob 对象` | String\File\Blob | 是 |
+| Expect | 当使用 `Expect: 100-continue` 时,在收到服务端确认后,才会发送请求内容 | String | 否 |
+| ContentMD5 | RFC 1864 中定义的经过 Base64 编码的128-bit 内容 MD5 校验值。此头部用来校验文件内容是否发生变化 | String | 否 |
+
+#### 回调函数说明
+
+```js
+function(err, data) { ... }
+```
+
+| 参数名 | 参数描述 | 类型 |
+|--------|----------|------|
+| err | 请求发生错误时返回的对象,包括网络错误和业务错误。如果请求成功,则为空,[错误码文档](https://cloud.tencent.com/document/product/436/7730) | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| data | 请求成功时返回的对象,如果请求发生错误,则为空 | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| - ETag | 文件的 MD-5 算法校验值,如 `"22ca88419e2ed4721c23807c678adbe4c08a7880"`,**注意前后携带双引号** | String |
+
+
+### Complete Multipart Upload
+
+Complete Multipart Upload 接口请求用来实现完成整个分块上传。当使用 Upload Parts 上传完所有块以后,必须调用该 API 来完成整个文件的分块上传。在使用该 API 时,您必须在请求 Body 中给出每一个块的 PartNumber 和 ETag,用来校验块的准确性。
+由于分块上传完后需要合并,而合并需要数分钟时间,因而当合并分块开始的时候,COS 就立即返回 200 的状态码,在合并的过程中,COS 会周期性的返回空格信息来保持连接活跃,直到合并完成,COS 会在 Body 中返回合并后块的内容。
+- 当上传块小于 1 MB 的时候,在调用该 API 时,会返回 400 EntityTooSmall;
+- 当上传块编号不连续的时候,在调用该 API 时,会返回 400 InvalidPart;
+- 当请求 Body 中的块信息没有按序号从小到大排列的时候,在调用该 API 时,会返回 400 InvalidPartOrder;
+- 当 UploadId 不存在的时候,在调用该 API 时,会返回 404 NoSuchUpload。
+
+#### 使用示例
+
+```js
+cos.multipartComplete({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+    Key: '1.zip',              /* 必须 */
+    UploadId: '1521389146c60e7e198202e4e6670c5c78ea5d1c60ad62f1862f472941c0fb8c6b7f3528a2', /* 必须 */
+    Parts: [
+        {PartNumber: '1', ETag: '"0cce40bdbaf2fa0ff204c20fc965dd3f"'},
+    ]
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| Bucket | Bucket 的名称。命名规则为{name}-{appid} ,此处填写的存储桶名称必须为此格式 | String | 是 |
+| Region | Bucket 所在区域。枚举值请见:[Bucket 地域信息](https://cloud.tencent.com/document/product/436/6224) | String | 是 |
+| Key | 对象键(Object 的名称),对象在存储桶中的唯一标识,[对象键说明](https://cloud.tencent.com/document/product/436/13324) | String | 是 |
+| UploadId | 上传任务编号 | String | 是 |
+| Parts | 用来说明本次分块上传中块的信息列表 | ObjectArray | 是 |
+| - PartNumber | 分块的编号 | String | 是 |
+| - ETag | 每个块文件的 MD5 算法校验值,如 `"22ca88419e2ed4721c23807c678adbe4c08a7880"`,**注意前后携带双引号** | String | 是 |
+
+#### 回调函数说明
+
+```js
+function(err, data) { ... }
+```
+
+| 参数名 | 参数描述 | 类型 |
+|--------|----------|------|
+| err | 请求发生错误时返回的对象,包括网络错误和业务错误。如果请求成功,则为空,[错误码文档](https://cloud.tencent.com/document/product/436/7730) | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| data | 请求成功时返回的对象,如果请求发生错误,则为空 | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| - Location | 创建的 Object 的外网访问域名 | String |
+| - Bucket | 分块上传的目标 Bucket | String |
+| - Key | 对象键(Object 的名称),对象在存储桶中的唯一标识,[对象键说明](https://cloud.tencent.com/document/product/436/13324) | String |
+| - ETag | 合并后文件的 MD5 算法校验值,如 `"22ca88419e2ed4721c23807c678adbe4c08a7880"`,**注意前后携带双引号** | String |
+
+
+### List Parts
+
+List Parts 用来查询特定分块上传中的已上传的块,即罗列出指定 UploadId 所属的所有已上传成功的分块。
+
+#### 使用示例
+
+```js
+cos.multipartListPart({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+    Key: '1.jpg',              /* 必须 */
+    UploadId: '1521389146c60e7e198202e4e6670c5c78ea5d1c60ad62f1862f47294ec0fb8c6b7f3528a2',                      /* 必须 */
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| Bucket | Bucket 的名称。命名规则为{name}-{appid} ,此处填写的存储桶名称必须为此格式 | String | 是 |
+| Region | Bucket 所在区域。枚举值请见:[Bucket 地域信息](https://cloud.tencent.com/document/product/436/6224) | String | 是 |
+| Key | 对象键(Object 的名称),对象在存储桶中的唯一标识,[对象键说明](https://cloud.tencent.com/document/product/436/13324) | String | 是 |
+| UploadId | 标识本次分块上传的 ID。使用 Initiate Multipart Upload 接口初始化分片上传时会得到一个 uploadId,该 ID 不但唯一标识这一分块数据,也标识了这分块数据在整个文件内的相对位置。 | String | 是 |
+| EncodingType | 规定返回值的编码方式 | String | 否 |
+| MaxParts | 单次返回最大的条目数量,默认 1000 | String | 否 |
+| PartNumberMarker | 默认以 UTF-8 二进制顺序列出条目,所有列出条目从 marker 开始 | String | 否 |
+
+#### 回调函数说明
+
+```js
+function(err, data) { ... }
+```
+
+| 参数名 | 参数描述 | 类型 |
+|--------|----------|------|
+| err | 请求发生错误时返回的对象,包括网络错误和业务错误。如果请求成功,则为空,[错误码文档](https://cloud.tencent.com/document/product/436/7730) | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| data | 请求成功时返回的对象,如果请求发生错误,则为空 | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| - Bucket | 分块上传的目标 Bucket | String |
+| - Encoding-type | 规定返回值的编码方式 | String |
+| - Key | 对象键(Object 的名称),对象在存储桶中的唯一标识,[对象键说明](https://cloud.tencent.com/document/product/436/13324) | String |
+| - UploadId | 标识本次分块上传的 ID | String |
+| - Initiator | 用来表示本次上传发起者的信息 | Object |
+| - - DisplayName | 上传发起者的名称 | String |
+| - - ID | 上传发起者 ID,格式:qcs::cam::uin/&lt;RootUin>:uin/&lt;SubUin> <br>如果是根帐号,&lt;RootUin> 和 &lt;SubUin> 是同一个值 | String |
+| - Owner | 用来表示这些分块所有者的信息 | Object |
+| - - DisplayName | Bucket 持有者的名称 | String |
+| - - ID | Bucket 持有者 ID,一般为用户的 UIN | String |
+| - StorageClass | 用来表示这些分块的存储级别,枚举值:Standard,Standard_IA | String |
+| - PartNumberMarker | 默认以 UTF-8 二进制顺序列出条目,所有列出条目从 marker 开始 | String |
+| - NextPartNumberMarker | 假如返回条目被截断,则返回 NextMarker 就是下一个条目的起点 | String |
+| - MaxParts | 单次返回最大的条目数量 | String |
+| - IsTruncated | 返回条目是否被截断,'true' 或者 'false' | String |
+| - Part | 分块信息列表 | ObjectArray |
+| - - PartNumber | 块的编号 | String |
+| - - LastModified | 块最后修改时间 | String |
+| - - ETag | 块的 MD5 算法校验值 | String |
+| - - Size | 块大小,单位 Byte | String |
+
+
+### Abort Multipart Upload
+
+Abort Multipart Upload 用来实现舍弃一个分块上传并删除已上传的块。当您调用 Abort Multipart Upload 时,如果有正在使用这个 Upload Parts 上传块的请求,则 Upload Parts 会返回失败。当该 UploadId 不存在时,会返回 404 NoSuchUpload。
+
+**建议您及时完成分块上传或者舍弃分块上传,因为已上传但是未终止的块会占用存储空间进而产生存储费用。**
+
+#### 使用示例
+
+```js
+cos.multipartAbort({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+    Key: '1.zip',                           /* 必须 */
+    UploadId: '1521389146c60e7e198202e4e6670c5c78ea5d1c60ad62f1862f47294ec0fb8c6b7f3528a2'                       /* 必须 */
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| Bucket | Bucket 的名称。命名规则为 {name}-{appid} ,此处填写的存储桶名称必须为此格式 | String | 是 |
+| Region | Bucket 所在区域。枚举值请见:[Bucket 地域信息](https://cloud.tencent.com/document/product/436/6224) | String | 是 |
+| Key | 对象键(Object 的名称),对象在存储桶中的唯一标识,[对象键说明](https://cloud.tencent.com/document/product/436/13324) | String | 是 |
+| UploadId | 标识本次分块上传的 ID。使用 Initiate Multipart Upload 接口初始化分片上传时会得到一个 uploadId,该 ID 不但唯一标识这一分块数据,也标识了这分块数据在整个文件内的相对位置 | String | 是 |
+
+
+#### 回调函数说明
+
+```js
+function(err, data) { ... }
+```
+
+| 参数名 | 参数描述 | 类型 |
+|--------|----------|------|
+| err | 请求发生错误时返回的对象,包括网络错误和业务错误。如果请求成功,则为空,[错误码文档](https://cloud.tencent.com/document/product/436/7730) | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| data | 请求成功时返回的对象,如果请求发生错误,则为空 | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+
+
+### List Multipart Uploads
+
+List Multiparts Uploads 用来查询正在进行中的分块上传。单次最多列出 1000 个正在进行中的分块上传。
+
+#### 使用示例
+
+获取前缀为 1.zip 的未完成的 UploadId 列表
+```js
+cos.multipartList({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+    Prefix: '1.zip',                        /* 非必须 */
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| Bucket | Bucket 的名称。命名规则为{name}-{appid} ,此处填写的存储桶名称必须为此格式 | String | 是 |
+| Region | Bucket 所在区域。枚举值请见:[Bucket 地域信息](https://cloud.tencent.com/document/product/436/6224) | String | 是 |
+| Delimiter | 定界符为一个符号,对 Object 名字包含指定前缀且第一次出现 delimiter 字符之间的 Object 作为一组元素:common prefix。如果没有 prefix,则从路径起点开始 | String | 否 |
+| EncodingType | 规定返回值的编码格式,合法值:url | String | 否 |
+| Prefix | 限定返回的 Object key 必须以 Prefix 作为前缀。注意使用 prefix 查询时,返回的 key 中仍会包含 Prefix | String | 否 |
+| MaxUploads | 设置最大返回的 multipart 数量,合法取值从1到1000,默认1000 | String | 否 |
+| KeyMarker | 与 upload-id-marker 一起使用,<br> <li> 当 upload-id-marker 未被指定时:<br>ObjectName 字母顺序大于 key-marker 的条目将被列出,<br><li>当upload-id-marker被指定时:<br>ObjectName 字母顺序大于key-marker的条目被列出,<br>ObjectName 字母顺序等于 key-marker 且 UploadID 大于 upload-id-marker 的条目将被列出。 | String | 否 |
+| UploadIdMarker | 与 key-marker 一起使用,<br><li>当 key-marker 未被指定时:<br>upload-id-marker 将被忽略,<br><li>当 key-marker 被指定时:<br>ObjectName字母顺序大于 key-marker 的条目被列出,<br>ObjectName 字母顺序等于 key-marker 且 UploadID 大于 upload-id-marker 的条目将被列出。 | String | 否 |</li>
+
+#### 回调函数说明
+
+```js
+function(err, data) { ... }
+```
+
+| 参数名 | 参数描述 | 类型 |
+|--------|----------|------|
+| err | 请求发生错误时返回的对象,包括网络错误和业务错误。如果请求成功,则为空,[错误码文档](https://cloud.tencent.com/document/product/436/7730) | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| data | 请求成功时返回的对象,如果请求发生错误,则为空 | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| - Bucket | 分块上传的目标 Bucket | String |
+| - Encoding-Type | 规定返回值的编码格式,合法值:url | String |
+| - KeyMarker | 列出条目从该 key 值开始 | String |
+| - UploadIdMarker | 列出条目从该 UploadId 值开始 | String |
+| - NextKeyMarker | 假如返回条目被截断,则返回 NextKeyMarker 就是下一个条目的起点 | String |
+| - NextUploadIdMarker | 假如返回条目被截断,则返回 UploadId 就是下一个条目的起点 | String |
+| - MaxUploads | 设置最大返回的 multipart 数量,合法取值从 1 到 1000 | String |
+| - IsTruncated | 返回条目是否被截断,'true' 或者 'false' | String |
+| - Delimiter | 定界符为一个符号,对 object 名字包含指定前缀且第一次出现 delimiter 字符之间的 object 作为一组元素:common prefix。如果没有 prefix,则从路径起点开始 | String |
+| - Prefix | 限定返回的 Object key 必须以 Prefix 作为前缀。注意使用 prefix 查询时,返回的 key 中仍会包含 Prefix | String |
+| - CommonPrefixs | 将 prefix 到 delimiter 之间的相同路径归为一类,定义为 Common Prefix | ObjectArray |
+| - - Prefix | 显示具体的 CommonPrefixs | String |
+| - Upload | Upload 的信息集合 | ObjectArray |
+| - - Key | Object 的名称 | String |
+| - - UploadId | 标示本次分块上传的 ID | String |
+| - StorageClass | 用来表示分块的存储级别,枚举值:STANDARD、STANDARD_IA | String |
+| - Initiator | 用来表示本次上传发起者的信息 | Object |
+| - - DisplayName | 上传发起者的名称 | String |
+| - - ID | 上传发起者 ID,格式:qcs::cam::uin/&lt;RootUin>:uin/&lt;SubUin> 如果是根帐号,&lt;RootUin> 和 &lt;SubUin> 是同一个值 | String |
+| - Owner | 用来表示这些分块所有者的信息 | Object |
+| - - DisplayName | Bucket 持有者的名称 | String |
+| - - ID | Bucket 持有者 ID,格式:qcs::cam::uin/&lt;RootUin>:uin/&lt;SubUin> 如果是根帐号,&lt;RootUin> 和 &lt;SubUin> 是同一个值 | String |
+| - Initiated | 分块上传的起始时间 | String |
+
+
+
+## 分块上传 / 复制任务操作
+
+该类方法是对上面原生方法的封装,实现了分块上传 / 复制的全过程,支持并发分块上传 / 复制,支持断点续传,支持上传任务的取消,暂停和重新开始等。
+
+
+### Slice Upload File
+
+Slice Upload File 可用于实现文件的分块上传。
+
+#### 使用示例
+
+```js
+cos.sliceUploadFile({
+    Bucket: 'test-1250000000', /* 必须 */
+    Region: 'ap-guangzhou',    /* 必须 */
+    Key: '1.zip',              /* 必须 */
+    Body: file,                /* 必须 */
+    TaskReady: function(taskId) {                   /* 非必须 */
+        console.log(taskId);
+    },
+    onHashProgress: function (progressData) {       /* 非必须 */
+        console.log(JSON.stringify(progressData));
+    },
+    onProgress: function (progressData) {           /* 非必须 */
+        console.log(JSON.stringify(progressData));
+    }
+}, function(err, data) {
+    console.log(err || data);
+});
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| Bucket | Bucket 的名称。命名规则为{name}-{appid} ,此处填写的存储桶名称必须为此格式 | String | 是 |
+| Region | Bucket 所在区域。枚举值请见:[Bucket 地域信息](https://cloud.tencent.com/document/product/436/6224) | String | 是 |
+| Key | 对象键(Object 的名称),对象在存储桶中的唯一标识,[对象键说明](https://cloud.tencent.com/document/product/436/13324) | String | 是 |
+| Body | 上传文件的内容,可以为  File 对象  或者  Blob 对象 | File\Blob | 是 |
+| SliceSize | 分块大小 | String | 否 |
+| AsyncLimit | 分块的并发量 | String | 否 |
+| StorageClass | Object 的存储级别,枚举值:STANDARD、STANDARD_IA | String | 否 |
+| TaskReady | 上传任务创建时的回调函数,返回一个 taskId,唯一标识上传任务,可用于上传任务的取消(cancelTask),停止(pauseTask)和重新开始(restartTask) | Function | 否 |
+| - taskId | 上传任务的编号 | String | 否 |
+| onHashProgress | 计算文件 MD5 值的进度回调函数,回调参数为进度对象 progressData | Function | 否 |
+| - progressData.loaded | 已经校验的文件部分大小,以字节(bytes)为单位 | Number | 否 |
+| - progressData.total | 整个文件的大小,以字节(bytes)为单位 | Number | 否 |
+| - progressData.speed | 文件的校验速度,以字节/秒(bytes/s)为单位 | Number | 否 |
+| - progressData.percent | 文件的校验百分比,以小数形式呈现,例如:下载 50% 即为 0.5 | Number | 否 |
+| onProgress | 上传文件的进度回调函数,回调参数为进度对象 progressData | Function | 否 |
+| - progressData.loaded | 已经上传的文件部分大小,以字节(bytes)为单位 | Number | 否 |
+| - progressData.total | 整个文件的大小,以字节(bytes)为单位 | Number | 否 |
+| - progressData.speed | 文件的上传速度,以字节/秒(bytes/s)为单位 | Number | 否 |
+| - progressData.percent | 文件的上传百分比,以小数形式呈现,例如:下载 50% 即为 0.5 | Number | 否 |
+
+#### 回调函数说明
+
+```js
+function(err, data) { ... }
+```
+
+| 参数名 | 参数描述 | 类型 |
+|--------|----------|------|
+| err | 请求发生错误时返回的对象,包括网络错误和业务错误。如果请求成功,则为空,[错误码文档](https://cloud.tencent.com/document/product/436/7730) | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| data | 请求成功时返回的对象,如果请求发生错误,则为空 | Object |
+| - statusCode | 请求返回的 HTTP 状态码,如 200、403、404 等 | Number |
+| - headers | 请求返回的头部信息 | Object |
+| - Location | 创建的 Object 的外网访问域名 | String |
+| - Bucket | 分块上传的目标 Bucket | String |
+| - Key | 对象键(Object 的名称),对象在存储桶中的唯一标识,[对象键说明](https://cloud.tencent.com/document/product/436/13324) | String |
+| - ETag | 合并后文件的 MD5 算法校验值,如 `"22ca88419e2ed4721c23807c678adbe4c08a7880"`,**注意前后携带双引号** | String |
+
+
+### Cancel Task
+
+根据 taskId 取消分块上传任务。
+
+#### 使用示例
+
+```js
+var taskId = 'xxxxx';                   /* 必须 */
+cos.cancelTask(taskId);
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| taskId | 文件上传任务的编号,在调用 sliceUploadFile 方法时,其 TaskReady 回调会返回该上传任务的 taskId | String | 是 |
+
+
+### Pause Task
+
+根据 taskId 暂停分块上传任务。
+
+#### 使用示例
+
+```js
+var taskId = 'xxxxx';                   /* 必须 */
+cos.pauseTask(taskId);
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| taskId | 文件上传任务的编号,在调用 sliceUploadFile 方法时,其 TaskReady 回调会返回该上传任务的 taskId | String | 是 |
+
+
+### Restart Task
+
+根据 taskId 重新开始上传任务,可以用于开启用户手动停止的(调用 pauseTask 停止)或者因为上传错误而停止的上传任务。
+
+#### 使用示例
+
+```js
+var taskId = 'xxxxx';                   /* 必须 */
+cos.restartTask(taskId);
+```
+
+#### 参数说明
+
+| 参数名 | 参数描述 | 类型 | 必填 |
+|--------|----------|------|------|
+| taskId | 文件上传任务的编号,在调用 sliceUploadFile 方法时,其 TaskReady 回调会返回该上传任务的 taskId | String | 是 |

+ 156 - 0
node_modules/cos-js-sdk-v5/csp/auth-json.php

@@ -0,0 +1,156 @@
+<?php
+
+/**
+ * php 签名样例
+ */
+
+function isActionAllow($method, $pathname, $query, $headers)
+{
+
+    $allow = true;
+
+    // // TODO 这里判断自己网站的登录态
+    // if ($!logined) {
+    //     $allow = false;
+    //     return $allow;
+    // }
+
+    // 请求可能带有点所有 action
+    // acl,cors,policy,location,tagging,lifecycle,versioning,replication,versions,delete,restore,uploads
+
+    // 请求跟路径,只允许获取 UploadId
+    if ($pathname === '/' && !($method === 'get' && isset($query['uploads']))) {
+        $allow = false;
+    }
+
+    // 不允许前端获取和修改文件权限
+    if ($pathname !== '/' && isset($query['acl'])) {
+        $allow = false;
+    }
+
+    // 这里应该根据需要,限制当前站点的用户只允许操作什么样的路径
+    if ($method === 'delete' && $pathname !== '/') { // 这里控制是否允许删除文件
+        // TODO 这里控制是否允许删除文件
+    }
+    if ($method === 'put' && $pathname !== '/') { // 这里控制是否允许上传和修改文件
+        // TODO 这里控制是否允许上传和修改文件
+    }
+    if ($method === 'get' && $pathname !== '/') { // 这里控制是否获取文件和文件相关信息
+        // TODO 这里控制是否允许获取文件和文件相关信息
+    }
+
+    return $allow;
+
+}
+
+/*
+ * 获取签名
+ * @param string $method 请求类型 method
+ * @param string $pathname 文件名称
+ * @param array $query query参数
+ * @param array $headers headers
+ * @return string 签名字符串
+ */
+function getAuthorization($method, $pathname, $query, $headers)
+{
+
+    // 获取个人 API 密钥 https://console.qcloud.com/capi
+    $SecretId = 'AKIDxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
+    $SecretKey = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
+
+    // 整理参数
+    !$query && ($query = array());
+    !$headers && ($headers = array());
+    $method = strtolower($method ? $method : 'get');
+    $pathname = $pathname ? $pathname : '/';
+    substr($pathname, 0, 1) != '/' && ($pathname = '/' . $pathname);
+
+    // 注意这里要过滤好允许什么样的操作
+    if (!isActionAllow($method, $pathname, $query, $headers)) {
+        return 'action deny';
+    }
+
+    // 工具方法
+    function getObjectKeys($obj)
+    {
+        $list = array_keys($obj);
+        sort($list);
+        return $list;
+    }
+
+    function obj2str($obj)
+    {
+        $list = array();
+        $keyList = getObjectKeys($obj);
+        $len = count($keyList);
+        for ($i = 0; $i < $len; $i++) {
+            $key = $keyList[$i];
+            $val = isset($obj[$key]) ? $obj[$key] : '';
+            $key = strtolower($key);
+            $list[] = rawurlencode($key) . '=' . rawurlencode($val);
+        }
+        return implode('&', $list);
+    }
+
+    // 签名有效起止时间
+    $now = time() - 1;
+    $expired = $now + 600; // 签名过期时刻,600 秒后
+
+    // 要用到的 Authorization 参数列表
+    $qSignAlgorithm = 'sha1';
+    $qAk = $SecretId;
+    $qSignTime = $now . ';' . $expired;
+    $qKeyTime = $now . ';' . $expired;
+    $qHeaderList = strtolower(implode(';', getObjectKeys($headers)));
+    $qUrlParamList = strtolower(implode(';', getObjectKeys($query)));
+
+    // 签名算法说明文档:https://www.qcloud.com/document/product/436/7778
+    // 步骤一:计算 SignKey
+    $signKey = hash_hmac("sha1", $qKeyTime, $SecretKey);
+
+    // 步骤二:构成 FormatString
+    $formatString = implode("\n", array(strtolower($method), $pathname, obj2str($query), obj2str($headers), ''));
+
+    // 步骤三:计算 StringToSign
+    $stringToSign = implode("\n", array('sha1', $qSignTime, sha1($formatString), ''));
+
+    // 步骤四:计算 Signature
+    $qSignature = hash_hmac('sha1', $stringToSign, $signKey);
+
+    // 步骤五:构造 Authorization
+    $authorization = implode('&', array(
+        'q-sign-algorithm=' . $qSignAlgorithm,
+        'q-ak=' . $qAk,
+        'q-sign-time=' . $qSignTime,
+        'q-key-time=' . $qKeyTime,
+        'q-header-list=' . $qHeaderList,
+        'q-url-param-list=' . $qUrlParamList,
+        'q-signature=' . $qSignature
+    ));
+
+    return $authorization;
+}
+
+
+// 获取前端过来的参数
+$inputBody = file_get_contents("php://input");
+if ($_SERVER['REQUEST_METHOD'] === 'POST' && $inputBody){
+    $params = json_decode($inputBody, 1);
+    $pathname = isset($params['pathname']) ? $params['pathname'] : '/';
+    $method = isset($params['method']) ? $params['method'] : 'get';
+    $query = isset($params['query']) ? $params['query'] : array();
+    $headers = isset($params['headers']) ? $params['headers'] : array();
+} else {
+    $pathname = isset($_GET['pathname']) ? $_GET['pathname'] : '/';
+    $method = isset($_GET['method']) ? $_GET['method'] : 'get';
+    $query = isset($_GET['query']) && $_GET['query'] ? json_decode($_GET['query'], 1) : array();
+    $headers = isset($_GET['headers']) && $_GET['headers'] ? json_decode($_GET['headers'], 1) : array();
+}
+
+// 返回数据给前端
+header('Content-Type: text/plain');
+header('Allow-Control-Allow-Origin: http://127.0.0.1'); // 这里修改允许跨域访问的网站
+header('Allow-Control-Allow-Headers: origin,accept,content-type');
+$sign = getAuthorization($method, $pathname, $query, $headers);
+
+echo '{"sign":"' . $sign .'"}';

+ 651 - 0
node_modules/cos-js-sdk-v5/csp/csp.html

@@ -0,0 +1,651 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport"
+          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+    <meta http-equiv="X-UA-Compatible" content="ie=edge">
+    <title>cos-js-sdk-v5</title>
+    <style>
+        body { font-family: "Microsoft YaHei"; }
+        .page {max-width:1024px;margin:0 auto;}
+        h1 { font-weight: normal; color:#333;}
+        a { color: #006eff; background-color: transparent; padding: 8px 16px; line-height: 1.3; display: inline-block; text-align: center; margin: 0 8px 8px 0; border: 1px solid #006eff; font-size: 14px; text-decoration: none; }
+        a:hover { color: #fff; background-color: #006eff; }
+        .result {display:none;line-height:1.3;font-size: 13px;font-family:monospace;border:1px solid #006eff;margin:0;height:200px;overflow:auto;box-sizing:border-box;padding:5px;}
+    </style>
+</head>
+<body>
+
+<div class="page">
+    <h1>cos-js-sdk-v5</h1>
+    <div class="main"></div>
+    <pre class="result"></pre>
+</div>
+
+<script src="../dist/cos-js-sdk-v5.js"></script>
+<script>
+    var config = {
+        Bucket: 'test-1250000000',
+        Region: 'default'
+    };
+
+    var util = {
+        createFile: function (options) {
+            var buffer = new ArrayBuffer(options.size || 0);
+            var arr = new Uint8Array(buffer);
+            [].forEach.call(arr, function (char, i) {
+                arr[i] = 0;
+            });
+            var opt = {};
+            options.type && (opt.type = options.type);
+            var blob = new Blob([buffer], options);
+            return blob;
+        }
+    };
+
+    var cos = new COS({
+        CompatibilityMode: true,
+        ServiceDomain: 'http://cos.default.example.com',
+
+        // 后缀式
+        Domain: 'http://cos.{Region}.example.com', // 后缀式
+        ForcePathStyle: true, // 后缀式
+
+        // 前缀式
+        // Domain: 'http://{Bucket}.cos.{Region}.example.com', // 前缀式
+
+        getAuthorization: function (options, callback) {
+            var url = './auth-json.php?method=' + options.Method + '&path=' + encodeURIComponent(options.Key);
+            var xhr = new XMLHttpRequest();
+            xhr.open('GET', url, true);
+            xhr.onload = function (e) {
+                var sign;
+                try {
+                    sign = JSON.parse(e.target.responseText).sign;
+                } catch (e) {}
+                callback(sign);
+            };
+            xhr.send();
+        },
+    });
+
+    var TaskId;
+
+    var pre = document.querySelector('.result');
+    var showLogText = function (text, color) {
+        if (typeof text === 'object') {
+            try {
+                text = JSON.stringify(text);
+            } catch (e) {
+            }
+        }
+        var div = document.createElement('div');
+        div.innerText = text;
+        color && (div.style.color = color);
+        pre.appendChild(div);
+        pre.style.display = 'block';
+        pre.scrollTop = pre.scrollHeight;
+    };
+
+    var logger = {
+        log: function (text) {
+            console.log.apply(console, arguments);
+            showLogText([].join.call(arguments, ' '));
+        },
+        error: function (text) {
+            console.error(text);
+            showLogText(text, 'red');
+        },
+    };
+
+    function getObjectUrl() {
+        var url = cos.getObjectUrl({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            Key: '1mb.zip',
+            Expires: 60,
+            Sign: true,
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+        logger.log(url);
+    }
+
+    function getBucket() {
+        cos.getBucket({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function headBucket() {
+        cos.headBucket({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function putBucketAcl() {
+        cos.putBucketAcl({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            // GrantFullControl: 'id="qcs::cam::uin/1001:uin/1001",id="qcs::cam::uin/1002:uin/1002"',
+            // GrantWrite: 'id="qcs::cam::uin/1001:uin/1001",id="qcs::cam::uin/1002:uin/1002"',
+            // GrantRead: 'id="qcs::cam::uin/1001:uin/1001",id="qcs::cam::uin/1002:uin/1002"',
+            // GrantReadAcp: 'id="qcs::cam::uin/1001:uin/1001",id="qcs::cam::uin/1002:uin/1002"',
+            // GrantWriteAcp: 'id="qcs::cam::uin/1001:uin/1001",id="qcs::cam::uin/1002:uin/1002"',
+            // ACL: 'public-read-write',
+            // ACL: 'public-read',
+            ACL: 'private',
+            // AccessControlPolicy: {
+            // "Owner": { // AccessControlPolicy 里必须有 owner
+            //     "ID": 'qcs::cam::uin/459000000:uin/459000000' // 459000000 是 Bucket 所属用户的 uin(帐号ID)
+            // },
+            // "Grants": [{
+            //     "Grantee": {
+            //         "ID": "qcs::cam::uin/1001:uin/1001", // 10002 是 uin(帐号ID)
+            //         "DisplayName": "qcs::cam::uin/1001:uin/1001" // 10002 是 uin(帐号ID)
+            //     },
+            //     "Permission": "READ"
+            // }, {
+            //     "Grantee": {
+            //         "ID": "qcs::cam::uin/10002:uin/10002", // 10002 是 uin(帐号ID)
+            //     },
+            //     "Permission": "WRITE"
+            // }, {
+            //     "Grantee": {
+            //         "ID": "qcs::cam::uin/10002:uin/10002", // 10002 是 uin(帐号ID)
+            //     },
+            //     "Permission": "READ_ACP"
+            // }, {
+            //     "Grantee": {
+            //         "ID": "qcs::cam::uin/10002:uin/10002", // 10002 是 uin(帐号ID)
+            //     },
+            //     "Permission": "WRITE_ACP"
+            // }]
+            // }
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function getBucketAcl() {
+        cos.getBucketAcl({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function putBucketCors() {
+        cos.putBucketCors({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            CORSConfiguration: {
+                "CORSRules": [{
+                    "AllowedOrigin": ["*"],
+                    "AllowedMethod": ["GET", "POST", "PUT", "DELETE", "HEAD"],
+                    "AllowedHeader": ["*"],
+                    "ExposeHeader": ["ETag", "x-cos-acl", "x-cos-delete-marker", "x-cos-server-side-encryption"],
+                    "MaxAgeSeconds": "5"
+                }]
+            }
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function getBucketCors() {
+        cos.getBucketCors({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function deleteBucketCors() {
+        cos.deleteBucketCors({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function getBucketLocation() {
+        cos.getBucketLocation({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function putBucketLifecycle() {
+        cos.putBucketLifecycle({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            LifecycleConfiguration: {
+                "Rules": [{
+                    'ID': 1,
+                    'Filter': {
+                        'Prefix': 'test123',
+                    },
+                    'Status': 'Enabled',
+                    'Transition': {
+                        'Date': '2016-10-31T00:00:00+08:00',
+                        'StorageClass': 'STANDARD_IA'
+                    }
+                }]
+            }
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function getBucketLifecycle() {
+        cos.getBucketLifecycle({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function deleteBucketLifecycle() {
+        cos.deleteBucketLifecycle({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function deleteBucket() {
+        cos.deleteBucket({
+            Bucket: 'testnew-' + config.Bucket.substr(config.Bucket.lastIndexOf('-') + 1),
+            Region: 'ap-guangzhou'
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function putObject() {
+        // 创建测试文件
+        var filename = '1kb.zip';
+        var blob = util.createFile({size: 1024});
+        // 调用方法
+        cos.putObject({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            Key: filename, /* 必须 */
+            Body: blob,
+            TaskReady: function (tid) {
+                TaskId = tid;
+            },
+            onProgress: function (progressData) {
+                logger.log(JSON.stringify(progressData));
+            },
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function putObjectCopy() {
+        cos.putObjectCopy({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            Key: '1mb.copy.zip',
+            CopySource: config.Bucket + '.cos.' + config.Region + '.myqcloud.com/' + encodeURIComponent('1mb.zip').replace(/%2F/g, '/'), // Bucket 格式:test-1250000000
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function getObject() {
+        cos.getObject({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            Key: '1mb.zip',
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function headObject() {
+        cos.headObject({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            Key: '1mb.zip'
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function putObjectAcl() {
+        cos.putObjectAcl({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            Key: '1mb.zip',
+            // GrantFullControl: 'id="qcs::cam::uin/1001:uin/1001",id="qcs::cam::uin/1002:uin/1002"',
+            // GrantWrite: 'id="qcs::cam::uin/1001:uin/1001",id="qcs::cam::uin/1002:uin/1002"',
+            // GrantRead: 'id="qcs::cam::uin/1001:uin/1001",id="qcs::cam::uin/1002:uin/1002"',
+            // ACL: 'public-read-write',
+            // ACL: 'public-read',
+            // ACL: 'private',
+            ACL: 'default', // 继承上一级目录权限
+            // AccessControlPolicy: {
+            //     "Owner": { // AccessControlPolicy 里必须有 owner
+            //         "ID": 'qcs::cam::uin/459000000:uin/459000000' // 459000000 是 Bucket 所属用户的 uin(帐号ID)
+            //     },
+            //     "Grants": [{
+            //         "Grantee": {
+            //             "ID": "qcs::cam::uin/10002:uin/10002", // 10002 是 uin(帐号ID)
+            //         },
+            //         "Permission": "READ"
+            //     }]
+            // }
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function getObjectAcl() {
+        cos.getObjectAcl({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            Key: '1mb.zip'
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function deleteObject() {
+        cos.deleteObject({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            Key: '1mb.zip'
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function deleteMultipleObject() {
+        cos.deleteMultipleObject({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            Objects: [
+                {Key: '中文/中文.txt'},
+                {Key: '中文/中文.zip'},
+            ]
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function abortUploadTask() {
+        cos.abortUploadTask({
+            Bucket: config.Bucket, /* 必须 */ // Bucket 格式:test-1250000000
+            Region: config.Region, /* 必须 */
+            // 格式1,删除单个上传任务
+            // Level: 'task',
+            // Key: '10mb.zip',
+            // UploadId: '14985543913e4e2642e31db217b9a1a3d9b3cd6cf62abfda23372c8d36ffa38585492681e3',
+            // 格式2,删除单个文件所有未完成上传任务
+            Level: 'file',
+            Key: '10mb.zip',
+            // 格式3,删除 Bucket 下所有未完成上传任务
+            // Level: 'bucket',
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function sliceUploadFile() {
+        var blob = util.createFile({size: 1024 * 1024 * 3});
+        cos.sliceUploadFile({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            Key: '3mb.zip', /* 必须 */
+            Body: blob,
+            TaskReady: function (tid) {
+                TaskId = tid;
+            },
+            onHashProgress: function (progressData) {
+                logger.log('onHashProgress', JSON.stringify(progressData));
+            },
+            onProgress: function (progressData) {
+                logger.log('onProgress', JSON.stringify(progressData));
+            },
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function selectFileToUpload() {
+        var input = document.createElement('input');
+        input.type = 'file';
+        input.onchange = function (e) {
+            var file = this.files[0];
+            if (file) {
+                if (file.size > 1024 * 1024) {
+                    cos.sliceUploadFile({
+                        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                        Region: config.Region,
+                        Key: file.name,
+                        Body: file,
+                        TaskReady: function (tid) {
+                            TaskId = tid;
+                        },
+                        onHashProgress: function (progressData) {
+                            logger.log('onHashProgress', JSON.stringify(progressData));
+                        },
+                        onProgress: function (progressData) {
+                            logger.log('onProgress', JSON.stringify(progressData));
+                        },
+                    }, function (err, data) {
+                        logger.log(err || data);
+                    });
+                } else {
+                    cos.putObject({
+                        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                        Region: config.Region,
+                        Key: file.name,
+                        Body: file,
+                        TaskReady: function (tid) {
+                            TaskId = tid;
+                        },
+                        onProgress: function (progressData) {
+                            logger.log(JSON.stringify(progressData));
+                        },
+                    }, function (err, data) {
+                        logger.log(err || data);
+                    });
+                }
+            }
+        };
+        input.click();
+    }
+
+    function cancelTask() {
+        cos.cancelTask(TaskId);
+        logger.log('canceled');
+    }
+
+    function pauseTask() {
+        cos.pauseTask(TaskId);
+        logger.log('paused');
+    }
+
+    function restartTask() {
+        cos.restartTask(TaskId);
+        logger.log('restart');
+    }
+
+    function uploadFiles() {
+        var filename = 'mb.zip';
+        var blob = util.createFile({size: 1024 * 1024 * 10});
+        cos.uploadFiles({
+            files: [{
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region,
+                Key: '1' + filename,
+                Body: blob,
+            }, {
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region,
+                Key: '2' + filename,
+                Body: blob,
+            }, {
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region,
+                Key: '3' + filename,
+                Body: blob,
+            }],
+            SliceSize: 1024 * 1024,
+            onProgress: function (info) {
+                var percent = parseInt(info.percent * 10000) / 100;
+                var speed = parseInt(info.speed / 1024 / 1024 * 100) / 100;
+                logger.log('进度:' + percent + '%; 速度:' + speed + 'Mb/s;');
+            },
+            onFileFinish: function (err, data, options) {
+                logger.log(options.Key + ' 上传' + (err ? '失败' : '完成'));
+            },
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function sliceCopyFile() {
+        // 创建测试文件
+        var sourceName = '3mb.zip';
+        var Key = '3mb.copy.zip';
+
+        var sourcePath = config.Bucket + '.cos.' + config.Region + '.myqcloud.com/'+ encodeURIComponent(sourceName).replace(/%2F/g, '/');
+
+        cos.sliceCopyFile({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            Key: Key,
+            CopySource: sourcePath,
+            SliceSize: 2 * 1024 * 1024, // 大于2M的文件用分片复制,小于则用单片复制
+            onProgress:function (info) {
+                var percent = parseInt(info.percent * 10000) / 100;
+                var speed = parseInt(info.speed / 1024 / 1024 * 100) / 100;
+                logger.log('进度:' + percent + '%; 速度:' + speed + 'Mb/s;');
+            }
+        },function (err,data) {
+            if(err){
+                logger.log(err);
+            }else{
+                logger.log(data);
+            }
+        });
+
+    }
+
+    var time0 = Date.now();
+    var preMsg = '页面加载完成';
+    var showTime = function (msg) {
+        var time1 = Date.now();
+        console.log(preMsg + '->' + msg, time1 - time0);
+        preMsg = msg;
+        time0 = time1;
+    };
+
+    var files;
+    function selectUploadFiles() {
+        showTime('弹出选文件窗口');
+        var input = document.createElement('input');
+        input.type = 'file';
+        input.multiple = true;
+        input.onchange = function (e) {
+            files = this.files;
+            showTime('选完文件');
+        };
+        input.click();
+    }
+    function startSelectUploadFiles() {
+        files.length && cos.uploadFiles({
+            files: [].map.call(files, function (file) {
+                return {
+                    Bucket: config.Bucket,
+                    Region: config.Region,
+                    Key: file.name,
+                    Body: file,
+                };
+            }),
+            SliceSize: 1024 * 1024,
+            onProgress: function (info) {
+                var percent = parseInt(info.percent * 10000) / 100;
+                var speed = parseInt(info.speed / 1024 / 1024 * 100) / 100;
+                logger.log('进度:' + percent + '%; 速度:' + speed + 'Mb/s;');
+            },
+            onFileFinish: function (err, data, options) {
+                logger.log(options.Key + ' 上传' + (err ? '失败' : '完成'));
+            },
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    (function () {
+        var list = [
+            // 'getService', // 不支持
+            'getAuth',
+            'getObjectUrl',
+            // 'putBucket', // 不支持
+            'getBucket',
+            'headBucket',
+            'putBucketAcl',
+            'getBucketAcl',
+            'putBucketCors',
+            'getBucketCors',
+            // 'deleteBucketCors', // 不提供
+            'getBucketLocation',
+            'getBucketLifecycle',
+            'putBucketLifecycle',
+            'deleteBucketLifecycle',
+            'deleteBucket',
+            'putObject',
+            'putObjectCopy',
+            'getObject',
+            'headObject',
+            'putObjectAcl',
+            'getObjectAcl',
+            'deleteObject',
+            'deleteMultipleObject',
+            'abortUploadTask',
+            'sliceUploadFile',
+            'selectFileToUpload',
+            'cancelTask',
+            'pauseTask',
+            'restartTask',
+            'uploadFiles',
+            'selectUploadFiles',
+            'startSelectUploadFiles',
+        ];
+        var container = document.querySelector('.main');
+        var html = [];
+        list.forEach(function (name) {
+            html.push('<a href="javascript:void(0)">' + name + '</a>');
+        });
+        container.innerHTML = html.join('');
+        container.onclick = function (e) {
+            if (e.target.tagName === 'A') {
+                var name = e.target.innerText.trim();
+                window[name]();
+            }
+        };
+    })();
+</script>
+
+</body>
+</html>

+ 80 - 0
node_modules/cos-js-sdk-v5/csp/start.md

@@ -0,0 +1,80 @@
+# COS JavaScript SDK CSP 快速入门
+
+### SDK 获取
+
+对象存储服务的 XML JS SDK 资源 github 地址:[tencentyun/cos-js-sdk-v5](https://github.com/tencentyun/cos-js-sdk-v5)。
+
+演示示例 Demo 代码地址:[XML JS SDK CSP Demo](https://github.com/tencentyun/cos-js-sdk-v5/tree/master/csp/csp.html)。
+
+### 开发准备
+
+1. 首先,JS SDk 需要浏览器支持基本的 HTML5 特性,以便支持 ajax 上传文件和计算文件 md5 值。
+2. 到COS 对象存储控制台创建存储桶,得到 Bucket(存储桶名称) 和 Region(地域名称)
+3. 到控制台密钥管理获取您的项目 SecretId 和 SecretKey。
+4. 配置 CORS 规则,配置例子如下图:
+
+![cors](../demo/cors.png)
+
+> 关于文章中出现的 SecretId、SecretKey、Bucket 等名称的含义和获取方式请参考:[COS 术语信息](https://cloud.tencent.com/document/product/436/7751)
+
+## 快速入门
+### 计算签名
+
+由于签名计算放在前端会暴露 SecretId 和 SecretKey,我们把签名计算过程放在后端实现,前段通过 ajax 向后端获取签名结果,正式部署时请再后端加一层自己网站本身的权限检验。其他语言,请参照对应的 [XML SDK](https://cloud.tencent.com/document/product/436/6474) 文档。
+
+
+### 上传例子
+
+1. 创建 test.html,填入下面的代码,修改里面的 Bucket 和 Region。
+2. 部署好后端的签名服务,并修改 getAuthorization 里的签名服务地址。
+3. 把 test.html 放在 Web 服务器下,然后在浏览器访问页面,测试文件上传。
+
+```html
+<input id="file-selector" type="file">
+<script src="dist/cos-js-sdk-v5.min.js"></script>
+<script>
+var Bucket = 'test-1250000000';
+var Region = 'ap-guangzhou';
+
+// 初始化实例
+var cos = new COS({
+    CompatibilityMode: true,
+    ServiceDomain: 'http://cos.default.xxx.com', // 这里替换成 getService 域名
+    Domain: 'http://{Bucket}.cos.{Region}.xxx.com', 这里替换成 API 域名格式模板
+    getAuthorization: function (options, callback) {
+        var url = './auth-json.php?method=' + options.Method + '&path=' + encodeURIComponent('/' + options.Key);
+        var xhr = new XMLHttpRequest();
+        xhr.open('GET', url, true);
+        xhr.onload = function (e) {
+            callback(e.target.responseText);
+        };
+        xhr.send();
+    },
+});
+
+// 监听选文件
+document.getElementById('file-selector').onchange = function () {
+    
+    var file = this.files[0];
+    if (!file) return;
+
+    // 分片上传文件
+    cos.sliceUploadFile({
+        Bucket: Bucket,
+        Region: Region,
+        Key: file.name,
+        Body: file,
+    }, function (err, data) {
+        console.log(err, data);
+    });
+
+};
+</script>
+```
+
+## webpack 引入方式
+
+支持 webpack 打包的场景,可以用 npm 引入作为模块
+```shell
+npm i cos-js-sdk-v5 --save
+```

+ 1603 - 0
node_modules/cos-js-sdk-v5/csp/test.html

@@ -0,0 +1,1603 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport"
+          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+    <meta http-equiv="X-UA-Compatible" content="ie=edge">
+    <title>cos-js-sdk-v5-demo</title>
+    <link rel="stylesheet" href="../test/qunit-2.4.0.css">
+</head>
+<body>
+
+<h1 id="qunit-header">cos-js-sdk-v5</h1>
+<h2 id="qunit-banner"></h2>
+<ol id="qunit-tests"></ol>
+
+<script src="../test/qunit-2.4.0.js"></script>
+<script src="../dist/cos-js-sdk-v5.js"></script>
+<script>
+    var config = {
+        SecretId: 'xxx',
+        SecretKey: 'xxx',
+        Bucket: 'test-1250000000',
+        Region: 'default'
+    };
+
+    var util = {
+        createFile: function (options) {
+            var buffer = new ArrayBuffer(options.size || 0);
+            var arr = new Uint8Array(buffer);
+            arr.forEach(function (char, i) {
+                arr[i] = 0;
+            });
+            var opt = {};
+            options.type && (opt.type = options.type);
+            var blob = new Blob([buffer], options);
+            return blob;
+        },
+        str2blob: function (str) {
+            var size = str.length;
+            var buffer = new ArrayBuffer(size || 0);
+            var arr = new Uint8Array(buffer);
+            arr.forEach(function (char, i) {
+                arr[i] = str[i];
+            });
+            var blob = new Blob([buffer]);
+            return blob;
+        }
+    };
+
+    var cos = new COS({
+        // 必选参数
+        SecretId: config.SecretId,
+        SecretKey: config.SecretKey,
+        CompatibilityMode: true,
+        ServiceDomain: 'http://cos.default.yun.ccb.com',
+        Domain: 'http://{Bucket}.cos.{Region}.yun.ccb.com',
+        // 可选参数
+        FileParallelLimit: 3,    // 控制文件上传并发数
+        ChunkParallelLimit: 3,   // 控制单个文件下分片上传并发数
+        ChunkSize: 1024 * 1024,  // 控制分片大小,单位 B
+        ProgressInterval: 1,  // 控制 onProgress 回调的间隔
+        ChunkRetryTimes: 3,   // 控制文件切片后单片上传失败后重试次数
+    });
+
+    var AppId = config.AppId;
+    var Bucket = config.Bucket;
+    var BucketShortName = Bucket;
+    var BucketLongName = Bucket + '-' + AppId;
+    var TaskId;
+
+    var match = config.Bucket.match(/^(.+)-(\d+)$/);
+    if (match) {
+        BucketLongName = config.Bucket; // Bucket 格式:test-1250000000
+        BucketShortName = match[1];
+        AppId = match[2];
+    }
+
+    var it = QUnit.test;
+    function comparePlainObject(a, b) {
+        a instanceof Array && a.sort();
+        b instanceof Array && b.sort();
+        if (Object.keys(a).length !== Object.keys(b).length) {
+            return false;
+        }
+        for (var key in a) {
+            if (typeof a[key] === 'object' && typeof b[key] === 'object') {
+                if (!comparePlainObject(a[key], b[key])) {
+                    return false;
+                }
+            } else if (a[key] != b[key]) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    it('getAuth()', function (assert) {
+        return new Promise(function (done) {
+            var content = Date.now().toString();
+            var key = '1.txt';
+            cos.putObject({
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region,
+                Key: key,
+                Body: content
+            }, function (err, data) {
+                cos.getObjectUrl({
+                    Bucket: config.Bucket,
+                    Region: config.Region,
+                    Key: key,
+                }, function (err, data) {
+                    var link = data.Url;
+                    var xhr = new XMLHttpRequest();
+                    xhr.open('GET', link, true);
+                    data.XCosSecurityToken && xhr.setRequestHeader('x-cos-security-token', data.XCosSecurityToken);
+                    xhr.onload = function (e) {
+                        assert.ok(xhr.status === 200, '获取文件 200');
+                        assert.ok(xhr.responseText === content, '通过获取签名能正常获取文件');
+                        done();
+                    };
+                    xhr.onerror = function (e) {
+                        assert.ok(false, '文件获取出错');
+                        done();
+                    };
+                    xhr.send();
+                });
+            });
+        });
+    });
+
+    it('auth check', function (assert) {
+        return new Promise(function (done) {
+            cos.getBucket({
+                Bucket: config.Bucket,
+                Region: config.Region,
+                Prefix: 'aksjhdlash sajlhj!@#$%^&*()_+=-[]{}\';:"/.<>?.,??sadasd#/.,/~`',
+                Headers: {
+                    'x-cos-test': 'aksjhdlash sajlhj!@#$%^&*()_+=-[]{}\';:\"/.<>?.,??sadasd#/.,/~`',
+                },
+            }, function (err, data) {
+                assert.ok(!err);
+                done();
+            });
+        });
+    });
+
+    it('cancelTask()', function (assert) {
+        return new Promise(function (done) {
+            var filename = '10mb.zip';
+            var blob = util.createFile({size: 1024 * 1024 * 10});
+            var alive = false;
+            var canceled = false;
+            cos.putObject({
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region,
+                Key: filename,
+                Body: blob,
+                TaskReady: function (taskId) {
+                    TaskId = taskId;
+                },
+                onProgress: function (info) {
+                    alive = true;
+                    if (!canceled) {
+                        cos.cancelTask(TaskId);
+                        alive = false;
+                        canceled = true;
+                        setTimeout(function () {
+                            assert.ok(!alive, '取消上传已经生效');
+                            done();
+                        }, 1200);
+                    }
+                }
+            }, function (err, data) {
+                alive = true;
+            });
+        });
+    });
+
+    it('pauseTask(),restartTask()', function (assert) {
+        return new Promise(function (done) {
+            var filename = '10mb.zip';
+            var blob = util.createFile({size: 1024 * 1024 * 10});
+            var paused = false;
+            var restarted = false;
+            cos.abortUploadTask({
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region,
+                Key: filename,
+                Level: 'file',
+            }, function (err, data) {
+                cos.sliceUploadFile({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    Key: filename,
+                    Body: blob,
+                    TaskReady: function (taskId) {
+                        TaskId = taskId;
+                    },
+                    onProgress: function (info) {
+                        if (!paused && info.percent > 0.6) {
+                            cos.pauseTask(TaskId);
+                            paused = true;
+                            setTimeout(function () {
+                                cos.restartTask(TaskId);
+                                restarted = true;
+                            }, 1000);
+                        }
+                        if (restarted) {
+                            assert.ok(info.percent > 0.3, '暂停和重试成功');
+                            done();
+                        }
+                    }
+                }, function (err, data) {
+                });
+            });
+        });
+    });
+
+    it('分片上传', function (assert) {
+        return new Promise(function (done) {
+            var filename = '10mb.zip';
+            var blob = util.createFile({size: 1024 * 1024 * 10});
+            var paused = false;
+            cos.abortUploadTask({
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region,
+                Key: filename,
+                Level: 'file',
+            }, function (err, data) {
+                cos.sliceUploadFile({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    Key: filename,
+                    Body: blob,
+                    TaskReady: function (taskId) {
+                        TaskId = taskId;
+                    },
+                    onProgress: function (info) {
+                        if (!paused && info.percent >= 0.6) {
+                            paused = true;
+                            cos.cancelTask(TaskId);
+                            cos.sliceUploadFile({
+                                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                                Region: config.Region,
+                                Key: filename,
+                                Body: blob,
+                                TaskReady: function (taskId) {
+                                    TaskId = taskId;
+                                },
+                                onProgress: function (info) {
+                                    assert.ok(info.percent > 0.3, '分片续传成功');
+                                    cos.cancelTask(TaskId);
+                                    done();
+                                }
+                            });
+                        }
+                    }
+                });
+            });
+        });
+    });
+
+    it('mock readAsBinaryString', function (assert) {
+        return new Promise(function (done) {
+            FileReader.prototype._readAsBinaryString = FileReader.prototype.readAsBinaryString;
+            FileReader.prototype.readAsBinaryString = false;
+            var filename = '10mb.zip';
+            var blob = util.createFile({size: 1024 * 1024 * 10});
+            var paused = false;
+            cos.sliceUploadFile({
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region,
+                Key: filename,
+                Body: blob,
+                TaskReady: function (taskId) {
+                    TaskId = taskId;
+                },
+                onProgress: function (info) {
+                    if (!paused && info.percent > 0.6) {
+                        cos.cancelTask(TaskId);
+                        cos.sliceUploadFile({
+                            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                            Region: config.Region,
+                            Key: filename,
+                            Body: blob,
+                            TaskReady: function (taskId) {
+                                TaskId = taskId;
+                            },
+                            onProgress: function (info) {
+                                assert.ok(info.percent > 0.3, '分片续传成功');
+                                cos.cancelTask(TaskId);
+                                FileReader.prototype.readAsBinaryString = FileReader.prototype._readAsBinaryString;
+                                delete FileReader.prototype._readAsBinaryString;
+                                done();
+                            }
+                        });
+                    }
+                }
+            });
+        });
+    });
+
+
+    it('abortUploadTask(),Level=task', function (assert) {
+        return new Promise(function (done) {
+            var filename = '10mb.zip';
+            cos.multipartInit({
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region,
+                Key: filename,
+            }, function (err, data) {
+                cos.abortUploadTask({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    Key: filename,
+                    Level: 'task',
+                    UploadId: data.UploadId,
+                }, function (err, data) {
+                    var nameExist = false;
+                    data.successList.forEach(function (item) {
+                        if (filename === item.Key) {
+                            nameExist = true;
+                        }
+                    });
+                    assert.ok(data.successList.length >= 1, '成功取消单个分片任务');
+                    assert.ok(nameExist, '成功取消单个分片任务');
+                    done();
+                });
+            });
+        });
+    });
+
+    it('abortUploadTask(),Level=file', function (assert) {
+        return new Promise(function (done) {
+            var filename = '10mb.zip';
+            var blob = util.createFile({size: 1024 * 1024 * 10});
+            cos.sliceUploadFile({
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region,
+                Key: filename,
+                Body: blob,
+                TaskReady: function (taskId) {
+                    TaskId = taskId;
+                },
+                onProgress: function (info) {
+                    cos.cancelTask(TaskId);
+                    cos.abortUploadTask({
+                        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                        Region: config.Region,
+                        Level: 'file',
+                        Key: filename,
+                    }, function (err, data) {
+                        assert.ok(data.successList.length >= 1, '成功舍弃单个文件下的所有分片任务');
+                        assert.ok(data.successList[0] && data.successList[0].Key === filename, '成功舍弃单个文件的所有分片任务');
+                        done();
+                    });
+                }
+            });
+        });
+    });
+
+    it('abortUploadTask(),Level=bucket', function (assert) {
+        return new Promise(function (done) {
+            var filename = '10mb.zip';
+            var blob = util.createFile({size: 1024 * 1024 * 10});
+            cos.sliceUploadFile({
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region,
+                Key: filename,
+                Body: blob,
+                TaskReady: function (taskId) {
+                    TaskId = taskId;
+                },
+                onProgress: function (info) {
+                    cos.cancelTask(TaskId);
+                    cos.abortUploadTask({
+                        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                        Region: config.Region,
+                        Level: 'bucket',
+                    }, function (err, data) {
+                        var nameExist = false;
+                        data.successList.forEach(function (item) {
+                            if (filename === item.Key) {
+                                nameExist = true;
+                            }
+                        });
+                        assert.ok(data.successList.length >= 1, '成功舍弃Bucket下所有分片任务');
+                        assert.ok(nameExist, '成功舍弃Bucket下所有分片任务');
+                        done();
+                    });
+                }
+            });
+        });
+    });
+
+    it('headBucket()', function (assert) {
+        return new Promise(function (done) {
+            cos.headBucket({
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region
+            }, function (err, data) {
+                assert.ok(data, '正常获取 head bucket');
+                done();
+            });
+        });
+    });
+
+    it('headBucket() not exist', function (assert) {
+        return new Promise(function (done) {
+            cos.headBucket({
+                Bucket: config.Bucket + Date.now().toString(36),
+                Region: config.Region
+            }, function (err, data) {
+                assert.ok(err, 'bucket 不存在');
+                done();
+            });
+        });
+    });
+
+    it('deleteBucket()', function (assert) {
+        return new Promise(function (done) {
+            cos.deleteBucket({
+                Bucket: config.Bucket + Date.now().toString(36),
+                Region: config.Region
+            }, function (err, data) {
+                assert.ok(err, '正常获取 head bucket');
+                done();
+            });
+        });
+    });
+
+    it('getBucket()', function (assert) {
+        return new Promise(function (done) {
+            cos.getBucket({
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region
+            }, function (err, data) {
+                assert.equal(true, data.Name === BucketLongName, '能列出 bucket');
+                assert.equal(data.Contents.constructor, Array, '正常获取 bucket 里的文件列表');
+                done();
+            });
+        });
+    });
+
+    it('putObject()', function (assert) {
+        var filename = '1.txt';
+        var getObjectETag = function (callback) {
+            setTimeout(function () {
+                cos.headObject({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    Key: filename,
+                }, function (err, data) {
+                    callback(data && data.headers && data.headers.etag);
+                });
+            }, 2000);
+        };
+        return new Promise(function (done) {
+            var content = Date.now().toString();
+            var lastPercent = 0;
+            var blob = util.str2blob(content);
+            cos.putObject({
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region,
+                Key: filename,
+                Body: blob,
+                onProgress: function (processData) {
+                    lastPercent = processData.percent;
+                },
+            }, function (err, data) {
+                if (err) throw err;
+                assert.ok(data && data.ETag, 'putObject 有返回 ETag');
+                getObjectETag(function (ETag) {
+                    assert.ok(data.ETag === ETag, 'Blob 创建 object');
+                    done();
+                });
+            });
+        });
+    });
+
+    it('putObject(),string', function (assert) {
+        var filename = '1.txt';
+        return new Promise(function (done) {
+            var content = '中文_' + Date.now().toString(36);
+            var lastPercent = 0;
+            cos.putObject({
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region,
+                Key: filename,
+                Body: content,
+                onProgress: function (processData) {
+                    lastPercent = processData.percent;
+                },
+            }, function (err, data) {
+                if (err) throw err;
+                assert.ok(data && data.ETag, 'putObject 有返回 ETag');
+                cos.getObject({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    Key: filename,
+                }, function (err, data) {
+                    assert.ok(data && data.headers && data.ETag === data.ETag && data.Body === content, '上传和下载内容一致');
+                    done();
+                });
+            });
+        });
+    });
+
+    it('putObject(),string empty', function (assert) {
+        var filename = '1.txt';
+        return new Promise(function (done) {
+            var content = '';
+            var lastPercent = 0;
+            cos.putObject({
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region,
+                Key: filename,
+                Body: content,
+                onProgress: function (processData) {
+                    lastPercent = processData.percent;
+                },
+            }, function (err, data) {
+                if (err) throw err;
+                assert.ok(data && data.ETag, 'putObject 有返回 ETag');
+                cos.getObject({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    Key: filename,
+                }, function (err, data) {
+                    assert.ok(data && data.headers && data.ETag === data.ETag && data.Body === content, '上传和下载内容一致');
+                    done();
+                });
+            });
+        });
+    });
+
+    it('Key 特殊字符', function (assert) {
+        return new Promise(function (done) {
+            cos.putObject({
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region,
+                Key: '(!\'*) "#$%&+,-./0123456789:;<=>@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~',
+                Body: Date.now().toString()
+            }, function (err, data) {
+                if (err) throw err;
+                assert.ok(data, 'putObject 特殊字符的 Key 能通过');
+                done();
+            });
+        });
+    });
+
+    it('getObject()', function (assert) {
+        return new Promise(function (done) {
+            var key = '1.txt';
+            var content = Date.now().toString(36);
+            cos.putObject({
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region,
+                Key: key,
+                Body: content
+            }, function (err, data) {
+                setTimeout(function () {
+                    cos.getObject({
+                        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                        Region: config.Region,
+                        Key: key,
+                    }, function (err, data) {
+                        if (err) throw err;
+                        assert.ok(data.Body === content);
+                        done();
+                    });
+                }, 2000);
+            });
+        });
+    });
+
+    it('putObjectCopy()', function (assert) {
+        return new Promise(function (done) {
+            var content = Date.now().toString(36);
+            cos.putObject({
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region,
+                Key: '1.txt',
+                Body: content,
+            }, function (err, data) {
+                var ETag = data.ETag;
+                cos.deleteObject({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    Key: '1.copy.txt',
+                }, function (err, data) {
+                    cos.putObjectCopy({
+                        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                        Region: config.Region,
+                        Key: '1.copy.txt',
+                        CopySource: BucketLongName + '.cos.' + config.Region + '.yun.ccb.com/1.txt',
+                    }, function (err, data) {
+                        cos.headObject({
+                            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                            Region: config.Region,
+                            Key: '1.copy.txt',
+                        }, function (err, data) {
+                            assert.ok(data.headers.etag === ETag, '成功复制文件');
+                            done();
+                        });
+                    });
+                });
+            });
+        });
+    });
+
+
+    it('deleteMultipleObject()', function (assert) {
+        return new Promise(function (done) {
+            var content = Date.now().toString(36);
+            cos.putObject({
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region,
+                Key: '1.txt',
+                Body: content,
+            }, function (err, data) {
+                cos.putObject({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    Key: '2.txt',
+                    Body: content,
+                }, function (err, data) {
+                    cos.deleteMultipleObject({
+                        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                        Region: config.Region,
+                        Objects : [
+                            {Key: '1.txt'},
+                            {Key: '2.txt'}
+                        ],
+                    }, function (err, data) {
+                        assert.ok(data.Deleted.length === 2);
+                        cos.headObject({
+                            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                            Region: config.Region,
+                            Key: '1.txt',
+                        }, function (err, data) {
+                            assert.ok(err.statusCode === 404, '1.txt 删除成功');
+                            cos.headObject({
+                                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                                Region: config.Region,
+                                Key: '2.txt',
+                            }, function (err, data) {
+                                assert.ok(err.statusCode === 404, '2.txt 删除成功');
+                                done();
+                            });
+                        });
+                    });
+                });
+            });
+        });
+    });
+
+    it('sliceUploadFile()', function (assert) {
+        return new Promise(function (done) {
+            var filename = '3mb.zip';
+            var blob = util.createFile({size: 1024 * 1024 * 3});
+            var lastPercent = 0;
+            cos.sliceUploadFile({
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region,
+                Key: filename,
+                Body: blob,
+                SliceSize: 1024 * 1024,
+                AsyncLimit: 5,
+                onHashProgress: function (progressData) {
+                },
+                onProgress: function (progressData) {
+                    lastPercent = progressData.percent;
+                },
+            }, function (err, data) {
+                assert.ok(data && data.ETag && lastPercent === 1, '上传成功');
+                done();
+            });
+        });
+    });
+
+    (function () {
+        var AccessControlPolicy = {
+            "Owner": {
+                "ID": 'qcs::cam::uin/10001:uin/10001' // 10001 是 QQ 号
+            },
+            "Grants": [{
+                "Grantee": {
+                    "ID": "qcs::cam::uin/10002:uin/10002", // 10002 是 QQ 号
+                },
+                "Permission": "READ"
+            }]
+        };
+        var AccessControlPolicy2 = {
+            "Owner": {
+                "ID": 'qcs::cam::uin/10001:uin/10001' // 10001 是 QQ 号
+            },
+            "Grant": {
+                "Grantee": {
+                    "ID": "qcs::cam::uin/10002:uin/10002", // 10002 是 QQ 号
+                },
+                "Permission": "READ"
+            }
+        };
+        it('putBucketAcl() header ACL:private', function (assert) {
+            return new Promise(function (done) {
+                cos.putBucketAcl({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    ACL: 'private'
+                }, function (err, data) {
+                    assert.ok(!err, 'putBucketAcl 成功');
+                    cos.getBucketAcl({
+                        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                        Region: config.Region
+                    }, function (err, data) {
+                        AccessControlPolicy.Owner.ID = data.Owner.ID;
+                        AccessControlPolicy2.Owner.ID = data.Owner.ID;
+                        assert.ok(data.ACL === 'private' || data.ACL === 'default');
+                        done();
+                    });
+                });
+            });
+        });
+        it('putBucketAcl() header ACL:public-read', function (assert) {
+            return new Promise(function (done) {
+                cos.putBucketAcl({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    ACL: 'public-read',
+                }, function (err, data) {
+                    assert.ok(!err, 'putBucketAcl 成功');
+                    cos.getBucketAcl({Bucket: config.Bucket, Region: config.Region}, function (err, data) { // Bucket 格式:test-1250000000
+                        assert.ok(data.ACL === 'public-read');
+                        done();
+                    });
+                });
+            });
+        });
+        it('putBucketAcl() header ACL:public-read-write', function (assert) {
+            return new Promise(function (done) {
+                cos.putBucketAcl({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    ACL: 'public-read-write',
+                }, function (err, data) {
+                    assert.ok(!err, 'putBucketAcl 成功');
+                    cos.getBucketAcl({Bucket: config.Bucket, Region: config.Region}, function (err, data) { // Bucket 格式:test-1250000000
+                        assert.ok(data.ACL === 'public-read-write');
+                        done();
+                    });
+                });
+            });
+        });
+        it('putBucketAcl() header GrantRead:1001,1002"', function (assert) {
+            return new Promise(function (done) {
+                var GrantRead = 'id="qcs::cam::uin/1001:uin/1001", id="qcs::cam::uin/1002:uin/1002"';
+                cos.putBucketAcl({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    GrantRead: GrantRead,
+                }, function (err, data) {
+                    assert.ok(!err, 'putBucketAcl 成功');
+                    cos.getBucketAcl({Bucket: config.Bucket, Region: config.Region}, function (err, data) { // Bucket 格式:test-1250000000
+                        assert.ok(data.GrantRead = GrantRead);
+                        done();
+                    });
+                });
+            });
+        });
+        it('putBucketAcl() header GrantWrite:1001,1002', function (assert) {
+            return new Promise(function (done) {
+                var GrantWrite = 'id="qcs::cam::uin/1001:uin/1001", id="qcs::cam::uin/1002:uin/1002"';
+                cos.putBucketAcl({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    GrantWrite: GrantWrite,
+                }, function (err, data) {
+                    assert.ok(!err, 'putBucketAcl 成功');
+                    cos.getBucketAcl({Bucket: config.Bucket, Region: config.Region}, function (err, data) { // Bucket 格式:test-1250000000
+                        assert.ok(data.GrantWrite = GrantWrite);
+                        done();
+                    });
+                });
+            });
+        });
+        it('putBucketAcl() header GrantFullControl:1001,1002', function (assert) {
+            return new Promise(function (done) {
+                var GrantFullControl = 'id="qcs::cam::uin/1001:uin/1001", id="qcs::cam::uin/1002:uin/1002"';
+                cos.putBucketAcl({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    GrantFullControl: GrantFullControl,
+                }, function (err, data) {
+                    assert.ok(!err, 'putBucketAcl 成功');
+                    cos.getBucketAcl({Bucket: config.Bucket, Region: config.Region}, function (err, data) { // Bucket 格式:test-1250000000
+                        assert.ok(data.GrantFullControl = GrantFullControl);
+                        done();
+                    });
+                });
+            });
+        });
+        it('putBucketAcl() header ACL:public-read, GrantFullControl:1001,1002', function (assert) {
+            return new Promise(function (done) {
+                var GrantFullControl = 'id="qcs::cam::uin/1001:uin/1001", id="qcs::cam::uin/1002:uin/1002"';
+                cos.putBucketAcl({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    GrantFullControl: GrantFullControl,
+                    ACL: 'public-read',
+                }, function (err, data) {
+                    assert.ok(!err, 'putBucketAcl 成功');
+                    cos.getBucketAcl({Bucket: config.Bucket, Region: config.Region}, function (err, data) { // Bucket 格式:test-1250000000
+                        assert.ok(data.GrantFullControl = GrantFullControl);
+                        assert.ok(data.ACL === 'public-read');
+                        done();
+                    });
+                });
+            });
+        });
+        it('putBucketAcl() xml', function (assert) {
+            return new Promise(function (done) {
+                cos.putBucketAcl({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    AccessControlPolicy: AccessControlPolicy
+                }, function (err, data) {
+                    assert.ok(!err, 'putBucketAcl 成功');
+                    cos.getBucketAcl({Bucket: config.Bucket, Region: config.Region}, function (err, data) { // Bucket 格式:test-1250000000
+                        assert.ok(data.Grants.length === 1);
+                        assert.ok(data.Grants[0] && data.Grants[0].Grantee.ID === 'qcs::cam::uin/10002:uin/10002', '设置 AccessControlPolicy ID 正确');
+                        assert.ok(data.Grants[0] && data.Grants[0].Permission === 'READ', '设置 AccessControlPolicy Permission 正确');
+                        done();
+                    });
+                });
+            });
+        });
+        it('putBucketAcl() xml2', function (assert) {
+            return new Promise(function (done) {
+                cos.putBucketAcl({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    AccessControlPolicy: AccessControlPolicy2,
+                }, function (err, data) {
+                    assert.ok(!err, 'putBucketAcl 成功');
+                    cos.getBucketAcl({Bucket: config.Bucket, Region: config.Region}, function (err, data) { // Bucket 格式:test-1250000000
+                        assert.ok(data.Grants.length === 1);
+                        assert.ok(data.Grants[0] && data.Grants[0].Grantee.ID === 'qcs::cam::uin/10002:uin/10002');
+                        assert.ok(data.Grants[0] && data.Grants[0].Permission === 'READ');
+                        done();
+                    });
+                });
+            });
+        });
+        it('putBucketAcl() decodeAcl', function (assert) {
+            return new Promise(function (done) {
+                cos.getBucketAcl({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region
+                }, function (err, data) {
+                    cos.putBucketAcl({
+                        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                        Region: config.Region,
+                        GrantFullControl: data.GrantFullControl,
+                        GrantWrite: data.GrantWrite,
+                        GrantRead: data.GrantRead,
+                        ACL: data.ACL,
+                    }, function (err, data) {
+                        assert.ok(data);
+                        done();
+                    });
+                });
+            });
+        });
+    })();
+
+    (function () {
+        var AccessControlPolicy = {
+            "Owner": {
+                "ID": 'qcs::cam::uin/10001:uin/10001' // 10001 是 QQ 号
+            },
+            "Grants": [{
+                "Grantee": {
+                    "ID": "qcs::cam::uin/10002:uin/10002", // 10002 是 QQ 号
+                },
+                "Permission": "READ"
+            }]
+        };
+        var AccessControlPolicy2 = {
+            "Owner": {
+                "ID": 'qcs::cam::uin/10001:uin/10001' // 10001 是 QQ 号
+            },
+            "Grant": {
+                "Grantee": {
+                    "ID": "qcs::cam::uin/10002:uin/10002", // 10002 是 QQ 号
+                },
+                "Permission": "READ"
+            }
+        };
+        it('putObjectAcl() header ACL:private', function (assert) {
+            return new Promise(function (done) {
+                cos.putObject({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    Key: '1.txt',
+                    Body: util.str2blob('hello!'),
+                }, function (err, data) {
+                    assert.ok(!err);
+                    cos.putObjectAcl({
+                        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                        Region: config.Region,
+                        ACL: 'private',
+                        Key: '1.txt',
+                    }, function (err, data) {
+                        assert.ok(!err, 'putObjectAcl 成功');
+                        cos.getObjectAcl({
+                            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                            Region: config.Region,
+                            Key: '1.txt'
+                        }, function (err, data) {
+                            assert.ok(data.ACL = 'private');
+                            AccessControlPolicy.Owner.ID = data.Owner.ID;
+                            AccessControlPolicy2.Owner.ID = data.Owner.ID;
+                            assert.ok(data.Grants.length === 1);
+                            done();
+                        });
+                    });
+                });
+            });
+        });
+        it('putObjectAcl() header ACL:default', function (assert) {
+            return new Promise(function (done) {
+                cos.putObjectAcl({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    ACL: 'default',
+                    Key: '1.txt',
+                }, function (err, data) {
+                    assert.ok(!err, 'putObjectAcl 成功');
+                    cos.getObjectAcl({
+                        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                        Region: config.Region,
+                        Key: '1.txt'
+                    }, function (err, data) {
+                        assert.ok(data.ACL = 'default');
+                        done();
+                    });
+                });
+            });
+        });
+        it('putObjectAcl() header ACL:public-read', function (assert) {
+            return new Promise(function (done) {
+                cos.putObjectAcl({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    ACL: 'public-read',
+                    Key: '1.txt',
+                }, function (err, data) {
+                    assert.ok(!err, 'putObjectAcl 成功');
+                    cos.getObjectAcl({Bucket: config.Bucket, Region: config.Region, Key: '1.txt'}, function (err, data) { // Bucket 格式:test-1250000000
+                        assert.ok(data.ACL = 'public-read');
+                        done();
+                    });
+                });
+            });
+        });
+        it('putObjectAcl() header ACL:public-read-write', function (assert) {
+            return new Promise(function (done) {
+                cos.putObjectAcl({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    ACL: 'public-read-write',
+                    Key: '1.txt',
+                }, function (err, data) {
+                    assert.ok(!err, 'putObjectAcl 成功');
+                    cos.getObjectAcl({Bucket: config.Bucket, Region: config.Region, Key: '1.txt'}, function (err, data) { // Bucket 格式:test-1250000000
+                        assert.ok(data.ACL = 'public-read-write');
+                        done();
+                    });
+                });
+            });
+        });
+        it('putObjectAcl() header GrantRead:1001,1002', function (assert) {
+            return new Promise(function (done) {
+                var GrantRead = 'id="qcs::cam::uin/1001:uin/1001",id="qcs::cam::uin/1002:uin/1002"';
+                cos.putObjectAcl({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    GrantRead: GrantRead,
+                    Key: '1.txt',
+                }, function (err, data) {
+                    assert.ok(!err, 'putObjectAcl 成功');
+                    cos.getObjectAcl({Bucket: config.Bucket, Region: config.Region, Key: '1.txt'}, function (err, data) { // Bucket 格式:test-1250000000
+                        assert.ok(data.GrantRead = GrantRead);
+                        done();
+                    });
+                });
+            });
+        });
+        it('putObjectAcl() header GrantWrite:1001,1002', function (assert) {
+            return new Promise(function (done) {
+                var GrantWrite = 'id="qcs::cam::uin/1001:uin/1001", id="qcs::cam::uin/1002:uin/1002"';
+                cos.putObjectAcl({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    GrantWrite: GrantWrite,
+                    Key: '1.txt',
+                }, function (err, data) {
+                    assert.ok(!err, 'putObjectAcl 成功');
+                    cos.getObjectAcl({Bucket: config.Bucket, Region: config.Region, Key: '1.txt'}, function (err, data) { // Bucket 格式:test-1250000000
+                        assert.ok(data.GrantWrite = GrantWrite);
+                        done();
+                    });
+                });
+            });
+        });
+        it('putObjectAcl() header GrantFullControl:1001,1002', function (assert) {
+            return new Promise(function (done) {
+                var GrantFullControl = 'id="qcs::cam::uin/1001:uin/1001", id="qcs::cam::uin/1002:uin/1002"';
+                cos.putObjectAcl({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    GrantFullControl: GrantFullControl,
+                    Key: '1.txt',
+                }, function (err, data) {
+                    assert.ok(!err, 'putObjectAcl 成功');
+                    cos.getObjectAcl({Bucket: config.Bucket, Region: config.Region, Key: '1.txt'}, function (err, data) { // Bucket 格式:test-1250000000
+                        assert.ok(data.GrantFullControl = GrantFullControl);
+                        done();
+                    });
+                });
+            });
+        });
+        it('putObjectAcl() header ACL:public-read, GrantRead:1001,1002', function (assert) {
+            return new Promise(function (done) {
+                var GrantFullControl = 'id="qcs::cam::uin/1001:uin/1001", id="qcs::cam::uin/1002:uin/1002"';
+                cos.putObjectAcl({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    GrantFullControl: GrantFullControl,
+                    ACL: 'public-read',
+                    Key: '1.txt',
+                }, function (err, data) {
+                    assert.ok(!err, 'putObjectAcl 成功');
+                    cos.getObjectAcl({Bucket: config.Bucket, Region: config.Region, Key: '1.txt'}, function (err, data) { // Bucket 格式:test-1250000000
+                        assert.ok(data.GrantFullControl = GrantFullControl);
+                        assert.ok(data.ACL = 'public-read');
+                        done();
+                    });
+                });
+            });
+        });
+        it('putObjectAcl() xml', function (assert) {
+            return new Promise(function (done) {
+                cos.putObjectAcl({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    AccessControlPolicy: AccessControlPolicy,
+                    Key: '1.txt',
+                }, function (err, data) {
+                    assert.ok(!err, 'putObjectAcl 成功');
+                    cos.getBucketAcl({Bucket: config.Bucket, Region: config.Region, Key: '1.txt'}, function (err, data) { // Bucket 格式:test-1250000000
+                        assert.ok(data.Grants.length === 1);
+                        assert.ok(data.Grants[0] && data.Grants[0].Grantee.ID === 'qcs::cam::uin/10002:uin/10002', '设置 AccessControlPolicy ID 正确');
+                        assert.ok(data.Grants[0] && data.Grants[0].Permission === 'READ', '设置 AccessControlPolicy Permission 正确');
+                        done();
+                    });
+                });
+            });
+        });
+        it('putObjectAcl() xml2', function (assert) {
+            return new Promise(function (done) {
+                cos.putObjectAcl({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    AccessControlPolicy: AccessControlPolicy2,
+                    Key: '1.txt',
+                }, function (err, data) {
+                    assert.ok(!err, 'putObjectAcl 成功');
+                    cos.getObjectAcl({
+                        Bucket: config.Bucket,
+                        Region: config.Region,
+                        Key: '1.txt'
+                    }, function (err, data) { // Bucket 格式:test-1250000000
+                        assert.ok(data.Grants.length === 1);
+                        assert.ok(data.Grants[0] && data.Grants[0].Grantee.ID === 'qcs::cam::uin/10002:uin/10002', 'ID 正确');
+                        assert.ok(data.Grants[0] && data.Grants[0].Permission === 'READ', 'Permission 正确');
+                        done();
+                    });
+                });
+            });
+        });
+        it('putObjectAcl() decodeAcl', function (assert) {
+            return new Promise(function (done) {
+                cos.getObjectAcl({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    Key: '1.txt'
+                }, function (err, data) {
+                    cos.putObjectAcl({
+                        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                        Region: config.Region,
+                        Key: '1.txt',
+                        GrantFullControl: data.GrantFullControl,
+                        GrantWrite: data.GrantWrite,
+                        GrantRead: data.GrantRead,
+                        ACL: data.ACL,
+                    }, function (err, data) {
+                        assert.ok(data);
+                        done();
+                    });
+                });
+            });
+        });
+    })();
+
+    (function () {
+        var CORSRules = [{
+            "AllowedOrigins": ["*"],
+            "AllowedMethods": ["GET", "POST", "PUT", "DELETE", "HEAD"],
+            "AllowedHeaders": ["*"],
+            "ExposeHeaders": ["ETag","Content-Length"],
+            "MaxAgeSeconds": "5"
+        }];
+        var CORSRulesMulti = [{
+            "AllowedOrigins": ["*"],
+            "AllowedMethods": ["GET", "POST", "PUT", "DELETE", "HEAD"],
+            "AllowedHeaders": ["*"],
+            "ExposeHeaders": ["ETag","Content-Length"],
+            "MaxAgeSeconds": "5"
+        }, {
+            "AllowedOrigins": ["http://qq.com", "http://qcloud.com"],
+            "AllowedMethods": ["GET", "POST", "PUT", "DELETE", "HEAD"],
+            "AllowedHeaders": ["*"],
+            "ExposeHeaders": ["ETag"],
+            "MaxAgeSeconds": "5"
+        }];
+        it('putBucketCors(),getBucketCors()', function (assert) {
+            return new Promise(function (done) {
+                CORSRules[0].AllowedHeaders.push('test-' + Date.now().toString(36));
+                cos.putBucketCors({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    CORSConfiguration: {
+                        CORSRules: CORSRules
+                    }
+                }, function (err, data) {
+                    assert.ok(!err);
+                    setTimeout(function () {
+                        cos.getBucketCors({
+                            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                            Region: config.Region
+                        }, function (err, data) {
+
+                            assert.ok(data && comparePlainObject(CORSRules, data.CORSRules));
+                            done();
+                        });
+                    }, 2000);
+                });
+            });
+        });
+        it('putBucketCors() old', function (assert) {
+            return new Promise(function (done) {
+                CORSRules[0].AllowedHeaders.push('test-' + Date.now().toString(36));
+                cos.putBucketCors({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    CORSConfiguration: {
+                        CORSRules: CORSRules
+                    }
+                }, function (err, data) {
+                    assert.ok(!err);
+                    setTimeout(function () {
+                        cos.getBucketCors({
+                            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                            Region: config.Region
+                        }, function (err, data) {
+                            assert.ok(comparePlainObject(CORSRules, data.CORSRules));
+                            done();
+                        });
+                    }, 2000);
+                });
+            });
+        });
+        it('putBucketCors() multi', function (assert) {
+            return new Promise(function (done) {
+                cos.putBucketCors({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    CORSConfiguration: {
+                        CORSRules: CORSRulesMulti
+                    }
+                }, function (err, data) {
+                    assert.ok(!err);
+                    setTimeout(function () {
+                        cos.getBucketCors({
+                            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                            Region: config.Region
+                        }, function (err, data) {
+                            assert.ok(comparePlainObject(CORSRulesMulti, data.CORSRules));
+                            done();
+                        });
+                    }, 2000);
+                });
+            });
+        });
+    })();
+
+    (function () {
+        var Tags = [
+            {Key: "k1", Value: "v1"}
+        ];
+        var TagsMulti = [
+            {Key: "k1", Value: "v1"},
+            {Key: "k2", Value: "v2"},
+        ];
+        it('putBucketTagging(),getBucketTagging()', function (assert) {
+            return new Promise(function (done) {
+                Tags[0].Value = Date.now().toString(36);
+                cos.putBucketTagging({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    Tagging: {
+                        Tags: Tags
+                    }
+                }, function (err, data) {
+                    assert.ok(!err);
+                    setTimeout(function () {
+                        cos.getBucketTagging({
+                            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                            Region: config.Region
+                        }, function (err, data) {
+                            assert.ok(comparePlainObject(Tags, data.Tags));
+                            done();
+                        });
+                    }, 1000);
+                });
+            });
+        });
+        it('deleteBucketTagging()', function (assert) {
+            return new Promise(function (done) {
+                cos.deleteBucketTagging({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region
+                }, function (err, data) {
+                    assert.ok(!err);
+                    setTimeout(function () {
+                        cos.getBucketTagging({
+                            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                            Region: config.Region
+                        }, function (err, data) {
+                            assert.ok(comparePlainObject([], data.Tags));
+                            done();
+                        });
+                    }, 1000);
+                });
+            });
+        });
+        it('putBucketTagging() multi', function (assert) {
+            return new Promise(function (done) {
+                Tags[0].Value = Date.now().toString(36);
+                cos.putBucketTagging({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    Tagging: {
+                        Tags: TagsMulti
+                    }
+                }, function (err, data) {
+                    assert.ok(!err);
+                    setTimeout(function () {
+                        cos.getBucketTagging({
+                            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                            Region: config.Region
+                        }, function (err, data) {
+                            assert.ok(comparePlainObject(TagsMulti, data.Tags));
+                            done();
+                        });
+                    }, 2000);
+                });
+            });
+        });
+    })();
+
+    (function () {
+        var Prefix = Date.now().toString(36);
+        var Policy = {
+            "version": "2.0",
+            "principal": {"qcs": ["qcs::cam::uin/10001:uin/10001"]}, // 这里的 10001 是 QQ 号
+            "statement": [{
+                "effect": "allow",
+                "action": [
+                    "name/cos:GetBucket",
+                    "name/cos:PutObject",
+                    "name/cos:PostObject",
+                    "name/cos:PutObjectCopy",
+                    "name/cos:InitiateMultipartUpload",
+                    "name/cos:UploadPart",
+                    "name/cos:UploadPartCopy",
+                    "name/cos:CompleteMultipartUpload",
+                    "name/cos:AbortMultipartUpload",
+                    "name/cos:AppendObject"
+                ],
+                "resource": ["qcs::cos:" + config.Region + ":uid/" + AppId + ":" + BucketLongName + ".cos." + config.Region + ".yun.ccb.com//" + AppId + "/" + BucketShortName + "/" + Prefix + "/*"] // 1250000000 是 appid
+            }]
+        };
+        it('putBucketPolicy(),getBucketPolicy()', function (assert) {
+            return new Promise(function (done) {
+                cos.putBucketPolicy({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    Policy: Policy
+                }, function (err, data) {
+                    assert.ok(!err);
+                    cos.getBucketPolicy({
+                        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                        Region: config.Region
+                    }, function (err, data) {
+                        assert.ok(Policy, data.Policy);
+                        done();
+                    });
+                });
+            });
+        });
+        it('putBucketPolicy() s3', function (assert) {
+            return new Promise(function (done) {
+                cos.putBucketPolicy({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    Policy: JSON.stringify(Policy)
+                }, function (err, data) {
+                    assert.ok(!err);
+                    cos.getBucketPolicy({
+                        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                        Region: config.Region
+                    }, function (err, data) {
+                        assert.ok(Policy, data.Policy);
+                        done();
+                    });
+                });
+            });
+        });
+    })();
+
+    it('getBucketLocation()', function (assert) {
+        return new Promise(function (done) {
+            cos.getBucketLocation({
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region
+            }, function (err, data) {
+                var map1 = {
+                    'tianjin': 'ap-beijing-1',
+                    'cn-south-2': 'ap-guangzhou-2',
+                    'cn-south': 'ap-guangzhou',
+                    'cn-east': 'ap-shanghai',
+                    'cn-southwest': 'ap-chengdu',
+                };
+                var map2 = {
+                    'ap-beijing-1': 'tianjin',
+                    'ap-guangzhou-2': 'cn-south-2',
+                    'ap-guangzhou': 'cn-south',
+                    'ap-shanghai': 'cn-east',
+                    'ap-chengdu': 'cn-southwest',
+                };
+                assert.ok(data.LocationConstraint === config.Region || data.LocationConstraint === map1[config.Region] ||
+                    data.LocationConstraint === map2[config.Region]);
+                done();
+            });
+        });
+    });
+
+    (function () {
+        var Rules = [{
+            'ID': '1',
+            'Filter': {
+                'Prefix': 'test_' + Date.now().toString(36),
+            },
+            'Status': 'Enabled',
+            'Transition': {
+                'Date': '2018-07-29T16:00:00.000Z',
+                'StorageClass': 'STANDARD_IA'
+            }
+        }];
+        var RulesMulti = [{
+            'ID': '1',
+            'Filter': {
+                'Prefix': 'test1_' + Date.now().toString(36),
+            },
+            'Status': 'Enabled',
+            'Transition': {
+                'Date': '2018-07-29T16:00:00.000Z',
+                'StorageClass': 'STANDARD_IA'
+            }
+        }, {
+            'ID': '2',
+            'Filter': {
+                'Prefix': 'test2_' + Date.now().toString(36),
+            },
+            'Status': 'Enabled',
+            'Transition': {
+                'Date': '2018-07-29T16:00:00.000Z',
+                'StorageClass': 'STANDARD_IA'
+            }
+        }];
+        it('deleteBucketLifecycle()', function (assert) {
+            return new Promise(function (done) {
+                cos.deleteBucketLifecycle({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region
+                }, function (err, data) {
+                    assert.ok(!err);
+                    setTimeout(function () {
+                        cos.getBucketLifecycle({
+                            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                            Region: config.Region
+                        }, function (err, data) {
+                            assert.ok(comparePlainObject([], data.Rules));
+                            done();
+                        });
+                    }, 2000);
+                });
+            });
+        });
+        it('putBucketLifecycle(),getBucketLifecycle()', function (assert) {
+            return new Promise(function (done) {
+                Rules[0].Filter.Prefix = 'test_' + Date.now().toString(36);
+                cos.putBucketLifecycle({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    LifecycleConfiguration: {
+                        Rules: Rules
+                    }
+                }, function (err, data) {
+                    assert.ok(!err);
+                    setTimeout(function () {
+                        cos.getBucketLifecycle({
+                            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                            Region: config.Region
+                        }, function (err, data) {
+                            assert.ok(comparePlainObject(Rules, data && data.Rules));
+                            done();
+                        });
+                    }, 2000);
+                });
+            });
+        });
+        it('putBucketLifecycle() multi', function (assert) {
+            return new Promise(function (done) {
+                Rules[0].Filter.Prefix = 'test_' + Date.now().toString(36);
+                cos.putBucketLifecycle({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    LifecycleConfiguration: {
+                        Rules: RulesMulti
+                    }
+                }, function (err, data) {
+                    assert.ok(!err);
+                    setTimeout(function () {
+                        cos.getBucketLifecycle({
+                            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                            Region: config.Region
+                        }, function (err, data) {
+                            assert.ok(comparePlainObject(RulesMulti, data.Rules));
+                            done();
+                        });
+                    }, 2000);
+                });
+            });
+        });
+    })();
+
+    it('params check', function (assert) {
+        return new Promise(function (done) {
+            cos.headBucket({
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: 'gz'
+            }, function (err, data) {
+                assert.ok(err.error === 'error');
+                done();
+            });
+        });
+    });
+
+    it('params check', function (assert) {
+        return new Promise(function (done) {
+            cos.headBucket({
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: 'cos.ap-guangzhou'
+            }, function (err, data) {
+                assert.ok(err.error === 'param Region should not be start with "cos."');
+                done();
+            });
+        });
+    });
+
+    it('sliceCopyFile() 正常分片复制', function (assert) {
+        return new Promise(function (done) {
+            var fileName = '10mb.zip';
+            var Key = '10mb.copy.zip';
+            var blob = util.createFile({size: 1024 * 1024 * 10});
+            cos.putObject({
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region,
+                Key: fileName,
+                Body: blob,
+            }, function (err, data) {
+                cos.sliceCopyFile({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    Key: Key,
+                    CopySource: config.Bucket + '.cos.' + config.Region + '.yun.ccb.com/'+ fileName,
+                    SliceSize: 5 * 1024 * 1024,
+                    onProgress:function (processData) {
+                        lastPercent = processData.percent;
+                    }
+                }, function (err, data) {
+                    assert.ok(data && data.ETag, '成功进行分片复制');
+                    done();
+                });
+            });
+        });
+    });
+
+    it('sliceCopyFile() 单片复制', function (assert) {
+        return new Promise(function (done) {
+            var fileName = '10mb.zip';
+            var Key = '10mb.copy.zip';
+            cos.sliceCopyFile({
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region,
+                Key: Key,
+                CopySource: config.Bucket + '.cos.' + config.Region + '.yun.ccb.com/'+ fileName,
+                SliceSize: 10 * 1024 * 1024,
+            }, function (err, data) {
+                if (err) throw err;
+                assert.ok(data && data.ETag, '成功进行单片复制');
+                done();
+            });
+        });
+    });
+
+    (function () {
+        function dataURItoBlob(dataURI) {
+            var byteString = atob(dataURI.split(',')[1]);
+            var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
+            var ab = new ArrayBuffer(byteString.length);
+            var ia = new Uint8Array(ab);
+            for (var i = 0; i < byteString.length; i++) {
+                ia[i] = byteString.charCodeAt(i);
+            }
+            return new Blob([ab], {type: mimeString});
+        }
+        var fileBlob = dataURItoBlob('data:text/plain;base64,5Lit5paH');
+        // 这里两个用户正式测试的时候需要给 putObject 计算并加上 Content-MD5 字段
+        it('putObject 带 Content-MD5 中文文件内容', function (assert) {
+            return new Promise(function (done) {
+                var Key = '中文.txt';
+                cos.putObject({
+                    Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                    Region: config.Region,
+                    Key: Key,
+                    Body: fileBlob,
+                }, function (err, data) {
+                    assert.ok(data && data.ETag, '成功进行上传');
+                    done();
+                });
+            });
+        });
+        // it('putObject 带 Content-MD5 中文字符串', function (assert) {
+        //     return new Promise(function (done) {
+        //         var Key = '中文.txt';
+        //         cos.putObject({
+        //             Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        //             Region: config.Region,
+        //             Key: Key,
+        //             Body: fileBlob,
+        //         }, function (err, data) {
+        //             assert.ok(data && data.ETag, '成功进行上传');
+        //             done();
+        //         });
+        //     });
+        // });
+    })();
+
+    it('deleteMultipleObject Key 带中文字符', function (assert) {
+        return new Promise(function (done) {
+            cos.deleteMultipleObject({
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region,
+                Objects: [
+                    {Key: '中文/中文.txt'},
+                    {Key: '中文/中文.zip'},
+                ]
+            }, function (err, data) {
+                assert.ok(!err, '成功进行批量删除');
+                done();
+            });
+        });
+    });
+</script>
+
+</body>
+</html>

+ 155 - 0
node_modules/cos-js-sdk-v5/demo/common/cos-auth.js

@@ -0,0 +1,155 @@
+(function () {
+    'use strict';
+
+    /*
+     CryptoJS v3.1.2
+     code.google.com/p/crypto-js
+     (c) 2009-2013 by Jeff Mott. All rights reserved.
+     code.google.com/p/crypto-js/wiki/License
+     */
+    var CryptoJS=CryptoJS||function(g,l){var e={},d=e.lib={},m=function(){},k=d.Base={extend:function(a){m.prototype=this;var c=new m;a&&c.mixIn(a);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}},
+        p=d.WordArray=k.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=l?c:4*a.length},toString:function(a){return(a||n).stringify(this)},concat:function(a){var c=this.words,q=a.words,f=this.sigBytes;a=a.sigBytes;this.clamp();if(f%4)for(var b=0;b<a;b++)c[f+b>>>2]|=(q[b>>>2]>>>24-8*(b%4)&255)<<24-8*((f+b)%4);else if(65535<q.length)for(b=0;b<a;b+=4)c[f+b>>>2]=q[b>>>2];else c.push.apply(c,q);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<<
+                32-8*(c%4);a.length=g.ceil(c/4)},clone:function(){var a=k.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],b=0;b<a;b+=4)c.push(4294967296*g.random()|0);return new p.init(c,a)}}),b=e.enc={},n=b.Hex={stringify:function(a){var c=a.words;a=a.sigBytes;for(var b=[],f=0;f<a;f++){var d=c[f>>>2]>>>24-8*(f%4)&255;b.push((d>>>4).toString(16));b.push((d&15).toString(16))}return b.join("")},parse:function(a){for(var c=a.length,b=[],f=0;f<c;f+=2)b[f>>>3]|=parseInt(a.substr(f,
+                2),16)<<24-4*(f%8);return new p.init(b,c/2)}},j=b.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var b=[],f=0;f<a;f++)b.push(String.fromCharCode(c[f>>>2]>>>24-8*(f%4)&255));return b.join("")},parse:function(a){for(var c=a.length,b=[],f=0;f<c;f++)b[f>>>2]|=(a.charCodeAt(f)&255)<<24-8*(f%4);return new p.init(b,c)}},h=b.Utf8={stringify:function(a){try{return decodeURIComponent(escape(j.stringify(a)))}catch(c){throw Error("Malformed UTF-8 data");}},parse:function(a){return j.parse(unescape(encodeURIComponent(a)))}},
+        r=d.BufferedBlockAlgorithm=k.extend({reset:function(){this._data=new p.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=h.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var c=this._data,b=c.words,f=c.sigBytes,d=this.blockSize,e=f/(4*d),e=a?g.ceil(e):g.max((e|0)-this._minBufferSize,0);a=e*d;f=g.min(4*a,f);if(a){for(var k=0;k<a;k+=d)this._doProcessBlock(b,k);k=b.splice(0,a);c.sigBytes-=f}return new p.init(k,f)},clone:function(){var a=k.clone.call(this);
+                a._data=this._data.clone();return a},_minBufferSize:0});d.Hasher=r.extend({cfg:k.extend(),init:function(a){this.cfg=this.cfg.extend(a);this.reset()},reset:function(){r.reset.call(this);this._doReset()},update:function(a){this._append(a);this._process();return this},finalize:function(a){a&&this._append(a);return this._doFinalize()},blockSize:16,_createHelper:function(a){return function(b,d){return(new a.init(d)).finalize(b)}},_createHmacHelper:function(a){return function(b,d){return(new s.HMAC.init(a,
+            d)).finalize(b)}}});var s=e.algo={};return e}(Math);
+    (function(){var g=CryptoJS,l=g.lib,e=l.WordArray,d=l.Hasher,m=[],l=g.algo.SHA1=d.extend({_doReset:function(){this._hash=new e.init([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(d,e){for(var b=this._hash.words,n=b[0],j=b[1],h=b[2],g=b[3],l=b[4],a=0;80>a;a++){if(16>a)m[a]=d[e+a]|0;else{var c=m[a-3]^m[a-8]^m[a-14]^m[a-16];m[a]=c<<1|c>>>31}c=(n<<5|n>>>27)+l+m[a];c=20>a?c+((j&h|~j&g)+1518500249):40>a?c+((j^h^g)+1859775393):60>a?c+((j&h|j&g|h&g)-1894007588):c+((j^h^
+            g)-899497514);l=g;g=h;h=j<<30|j>>>2;j=n;n=c}b[0]=b[0]+n|0;b[1]=b[1]+j|0;b[2]=b[2]+h|0;b[3]=b[3]+g|0;b[4]=b[4]+l|0},_doFinalize:function(){var d=this._data,e=d.words,b=8*this._nDataBytes,g=8*d.sigBytes;e[g>>>5]|=128<<24-g%32;e[(g+64>>>9<<4)+14]=Math.floor(b/4294967296);e[(g+64>>>9<<4)+15]=b;d.sigBytes=4*e.length;this._process();return this._hash},clone:function(){var e=d.clone.call(this);e._hash=this._hash.clone();return e}});g.SHA1=d._createHelper(l);g.HmacSHA1=d._createHmacHelper(l)})();
+    (function(){var g=CryptoJS,l=g.enc.Utf8;g.algo.HMAC=g.lib.Base.extend({init:function(e,d){e=this._hasher=new e.init;"string"==typeof d&&(d=l.parse(d));var g=e.blockSize,k=4*g;d.sigBytes>k&&(d=e.finalize(d));d.clamp();for(var p=this._oKey=d.clone(),b=this._iKey=d.clone(),n=p.words,j=b.words,h=0;h<g;h++)n[h]^=1549556828,j[h]^=909522486;p.sigBytes=b.sigBytes=k;this.reset()},reset:function(){var e=this._hasher;e.reset();e.update(this._iKey)},update:function(e){this._hasher.update(e);return this},finalize:function(e){var d=
+            this._hasher;e=d.finalize(e);d.reset();return d.finalize(this._oKey.clone().concat(e))}})})();
+
+    // CryptoJS Base
+    (function () {var C = CryptoJS;var C_lib = C.lib;var WordArray = C_lib.WordArray;var C_enc = C.enc;C_enc.Base64 = {stringify: function (wordArray) {var words = wordArray.words;var sigBytes = wordArray.sigBytes;var map = this._map;wordArray.clamp();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));}}var paddingChar = map.charAt(64);if (paddingChar) {while (base64Chars.length % 4) {base64Chars.push(paddingChar);}}return base64Chars.join('');}, parse: function (base64Str) {var base64StrLength = base64Str.length;var map = this._map;var paddingChar = map.charAt(64);if (paddingChar) {var paddingIndex = base64Str.indexOf(paddingChar);if (paddingIndex != -1) {base64StrLength = paddingIndex;}}var words = [];var nBytes = 0;for (var i = 0; i < base64StrLength; i++) {if (i % 4) {var bits1 = map.indexOf(base64Str.charAt(i - 1)) << ((i % 4) * 2);var bits2 = map.indexOf(base64Str.charAt(i)) >>> (6 - (i % 4) * 2);words[nBytes >>> 2] |= (bits1 | bits2) << (24 - (nBytes % 4) * 8);nBytes++;}}return WordArray.create(words, nBytes);}, _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='};}());
+
+    // 和 cam 保持一致的 url encode
+    function camSafeUrlEncode(str) {
+        return encodeURIComponent(str)
+            .replace(/!/g, '%21')
+            .replace(/'/g, '%27')
+            .replace(/\(/g, '%28')
+            .replace(/\)/g, '%29')
+            .replace(/\*/g, '%2A');
+    }
+
+    // v4 签名
+    var CosAuthV4 = function (opt) {
+        var pathname = opt.Pathname || '/';
+        var expires = opt.Expires;
+
+        var ShortBucketName = '';
+        var AppId = '';
+        var match = opt.Bucket.match(/^(.+)-(\d+)$/);
+        if (match) {
+            ShortBucketName = match[1];
+            AppId = match[2];
+        }
+
+        var random = parseInt(Math.random() * Math.pow(2, 32));
+        var now = parseInt(Date.now() / 1000);
+        var e = now + (expires === undefined ? 900 : (expires * 1 || 0)); // 默认签名过期时间为当前时间 + 900s
+        var path = '/' + AppId + '/' + ShortBucketName + encodeURIComponent(pathname).replace(/%2F/g, '/'); //多次签名这里填空
+        var plainText = 'a=' + AppId + '&b=' + ShortBucketName + '&k=' + opt.SecretId + '&e=' + e + '&t=' + now + '&r=' + random + '&f=' + path;
+        var sha1Res = CryptoJS.HmacSHA1(plainText, opt.SecretKey);
+        var strWordArray = CryptoJS.enc.Utf8.parse(plainText);
+        var resWordArray = sha1Res.concat(strWordArray);
+        var sign = resWordArray.toString(CryptoJS.enc.Base64);
+
+        return sign;
+    }
+
+    // v5 签名
+    var CosAuth = function (opt) {
+
+        if (!opt.SecretId) return console.error('missing param SecretId');
+        if (!opt.SecretKey) return console.error('missing param SecretKey');
+
+        if (opt.Version === '4.0') {
+            return CosAuthV4(opt);
+        }
+
+        opt = opt || {};
+
+        var SecretId = opt.SecretId;
+        var SecretKey = opt.SecretKey;
+        var method = (opt.Method || 'get').toLowerCase();
+        var query = opt.Query || {};
+        var headers = opt.Headers || {};
+        var pathname = opt.Pathname || '/';
+        var expires = opt.Expires;
+
+        var getObjectKeys = function (obj) {
+            var list = [];
+            for (var key in obj) {
+                if (obj.hasOwnProperty(key)) {
+                    list.push(key);
+                }
+            }
+            return list.sort(function (a, b) {
+                a = a.toLowerCase();
+                b = b.toLowerCase();
+                return a === b ? 0 : (a > b ? 1 : -1);
+            });
+        };
+
+        var obj2str = function (obj) {
+            var i, key, val;
+            var list = [];
+            var keyList = getObjectKeys(obj);
+            for (i = 0; i < keyList.length; i++) {
+                key = keyList[i];
+                val = (obj[key] === undefined || obj[key] === null) ? '' : ('' + obj[key]);
+                key = key.toLowerCase();
+                key = camSafeUrlEncode(key);
+                val = camSafeUrlEncode(val) || '';
+                list.push(key + '=' + val)
+            }
+            return list.join('&');
+        };
+
+        // 签名有效起止时间
+        var now = parseInt(new Date().getTime() / 1000) - 1;
+        var exp = now + (expires === undefined ? 900 : (expires * 1 || 0)); // 默认签名过期时间为当前时间 + 900s
+
+        // 要用到的 Authorization 参数列表
+        var qSignAlgorithm = 'sha1';
+        var qAk = SecretId;
+        var qSignTime = now + ';' + exp;
+        var qKeyTime = now + ';' + exp;
+        var qHeaderList = getObjectKeys(headers).join(';').toLowerCase();
+        var qUrlParamList = getObjectKeys(query).join(';').toLowerCase();
+
+        // 签名算法说明文档:https://www.qcloud.com/document/product/436/7778
+        // 步骤一:计算 SignKey
+        var signKey = CryptoJS.HmacSHA1(qKeyTime, SecretKey).toString();
+
+        // 步骤二:构成 FormatString
+        var formatString = [method, pathname, obj2str(query), obj2str(headers), ''].join('\n');
+
+        // 步骤三:计算 StringToSign
+        var stringToSign = ['sha1', qSignTime, CryptoJS.SHA1(formatString).toString(), ''].join('\n');
+
+        // 步骤四:计算 Signature
+        var qSignature = CryptoJS.HmacSHA1(stringToSign, signKey).toString();
+
+        // 步骤五:构造 Authorization
+        var authorization = [
+            'q-sign-algorithm=' + qSignAlgorithm,
+            'q-ak=' + qAk,
+            'q-sign-time=' + qSignTime,
+            'q-key-time=' + qKeyTime,
+            'q-header-list=' + qHeaderList,
+            'q-url-param-list=' + qUrlParamList,
+            'q-signature=' + qSignature
+        ].join('&');
+
+        return authorization;
+
+    };
+
+    if(typeof module === 'object'){
+        module.exports = CosAuth;
+    }else{
+        window.CosAuth = CosAuth;
+    }
+})();

File diff suppressed because it is too large
+ 0 - 0
node_modules/cos-js-sdk-v5/demo/common/cos-auth.min.js


File diff suppressed because it is too large
+ 1 - 0
node_modules/cos-js-sdk-v5/demo/common/jquery-3.3.1.min.js


+ 29 - 0
node_modules/cos-js-sdk-v5/demo/common/lodash.core.min.js

@@ -0,0 +1,29 @@
+/**
+ * @license
+ * Lodash (Custom Build) lodash.com/license | Underscore.js 1.8.3 underscorejs.org/LICENSE
+ * Build: `lodash core -o ./dist/lodash.core.js`
+ */
+;(function(){function n(n){return H(n)&&pn.call(n,"callee")&&!yn.call(n,"callee")}function t(n,t){return n.push.apply(n,t),n}function r(n){return function(t){return null==t?Z:t[n]}}function e(n,t,r,e,u){return u(n,function(n,u,o){r=e?(e=false,n):t(r,n,u,o)}),r}function u(n,t){return j(t,function(t){return n[t]})}function o(n){return n instanceof i?n:new i(n)}function i(n,t){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!t}function c(n,t,r){if(typeof n!="function")throw new TypeError("Expected a function");
+return setTimeout(function(){n.apply(Z,r)},t)}function f(n,t){var r=true;return mn(n,function(n,e,u){return r=!!t(n,e,u)}),r}function a(n,t,r){for(var e=-1,u=n.length;++e<u;){var o=n[e],i=t(o);if(null!=i&&(c===Z?i===i:r(i,c)))var c=i,f=o}return f}function l(n,t){var r=[];return mn(n,function(n,e,u){t(n,e,u)&&r.push(n)}),r}function p(n,r,e,u,o){var i=-1,c=n.length;for(e||(e=R),o||(o=[]);++i<c;){var f=n[i];0<r&&e(f)?1<r?p(f,r-1,e,u,o):t(o,f):u||(o[o.length]=f)}return o}function s(n,t){return n&&On(n,t,Dn);
+}function h(n,t){return l(t,function(t){return U(n[t])})}function v(n,t){return n>t}function b(n,t,r,e,u){return n===t||(null==n||null==t||!H(n)&&!H(t)?n!==n&&t!==t:y(n,t,r,e,b,u))}function y(n,t,r,e,u,o){var i=Nn(n),c=Nn(t),f=i?"[object Array]":hn.call(n),a=c?"[object Array]":hn.call(t),f="[object Arguments]"==f?"[object Object]":f,a="[object Arguments]"==a?"[object Object]":a,l="[object Object]"==f,c="[object Object]"==a,a=f==a;o||(o=[]);var p=An(o,function(t){return t[0]==n}),s=An(o,function(n){
+return n[0]==t});if(p&&s)return p[1]==t;if(o.push([n,t]),o.push([t,n]),a&&!l){if(i)r=T(n,t,r,e,u,o);else n:{switch(f){case"[object Boolean]":case"[object Date]":case"[object Number]":r=J(+n,+t);break n;case"[object Error]":r=n.name==t.name&&n.message==t.message;break n;case"[object RegExp]":case"[object String]":r=n==t+"";break n}r=false}return o.pop(),r}return 1&r||(i=l&&pn.call(n,"__wrapped__"),f=c&&pn.call(t,"__wrapped__"),!i&&!f)?!!a&&(r=B(n,t,r,e,u,o),o.pop(),r):(i=i?n.value():n,f=f?t.value():t,
+r=u(i,f,r,e,o),o.pop(),r)}function g(n){return typeof n=="function"?n:null==n?X:(typeof n=="object"?d:r)(n)}function _(n,t){return n<t}function j(n,t){var r=-1,e=M(n)?Array(n.length):[];return mn(n,function(n,u,o){e[++r]=t(n,u,o)}),e}function d(n){var t=_n(n);return function(r){var e=t.length;if(null==r)return!e;for(r=Object(r);e--;){var u=t[e];if(!(u in r&&b(n[u],r[u],3)))return false}return true}}function m(n,t){return n=Object(n),C(t,function(t,r){return r in n&&(t[r]=n[r]),t},{})}function O(n){return xn(I(n,void 0,X),n+"");
+}function x(n,t,r){var e=-1,u=n.length;for(0>t&&(t=-t>u?0:u+t),r=r>u?u:r,0>r&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0,r=Array(u);++e<u;)r[e]=n[e+t];return r}function A(n){return x(n,0,n.length)}function E(n,t){var r;return mn(n,function(n,e,u){return r=t(n,e,u),!r}),!!r}function w(n,r){return C(r,function(n,r){return r.func.apply(r.thisArg,t([n],r.args))},n)}function k(n,t,r){var e=!r;r||(r={});for(var u=-1,o=t.length;++u<o;){var i=t[u],c=Z;if(c===Z&&(c=n[i]),e)r[i]=c;else{var f=r,a=f[i];pn.call(f,i)&&J(a,c)&&(c!==Z||i in f)||(f[i]=c);
+}}return r}function N(n){return O(function(t,r){var e=-1,u=r.length,o=1<u?r[u-1]:Z,o=3<n.length&&typeof o=="function"?(u--,o):Z;for(t=Object(t);++e<u;){var i=r[e];i&&n(t,i,e,o)}return t})}function F(n){return function(){var t=arguments,r=dn(n.prototype),t=n.apply(r,t);return V(t)?t:r}}function S(n,t,r){function e(){for(var o=-1,i=arguments.length,c=-1,f=r.length,a=Array(f+i),l=this&&this!==on&&this instanceof e?u:n;++c<f;)a[c]=r[c];for(;i--;)a[c++]=arguments[++o];return l.apply(t,a)}if(typeof n!="function")throw new TypeError("Expected a function");
+var u=F(n);return e}function T(n,t,r,e,u,o){var i=n.length,c=t.length;if(i!=c&&!(1&r&&c>i))return false;for(var c=-1,f=true,a=2&r?[]:Z;++c<i;){var l=n[c],p=t[c];if(void 0!==Z){f=false;break}if(a){if(!E(t,function(n,t){if(!P(a,t)&&(l===n||u(l,n,r,e,o)))return a.push(t)})){f=false;break}}else if(l!==p&&!u(l,p,r,e,o)){f=false;break}}return f}function B(n,t,r,e,u,o){var i=1&r,c=Dn(n),f=c.length,a=Dn(t).length;if(f!=a&&!i)return false;for(var l=f;l--;){var p=c[l];if(!(i?p in t:pn.call(t,p)))return false}for(a=true;++l<f;){var p=c[l],s=n[p],h=t[p];
+if(void 0!==Z||s!==h&&!u(s,h,r,e,o)){a=false;break}i||(i="constructor"==p)}return a&&!i&&(r=n.constructor,e=t.constructor,r!=e&&"constructor"in n&&"constructor"in t&&!(typeof r=="function"&&r instanceof r&&typeof e=="function"&&e instanceof e)&&(a=false)),a}function R(t){return Nn(t)||n(t)}function D(n){var t=[];if(null!=n)for(var r in Object(n))t.push(r);return t}function I(n,t,r){return t=jn(t===Z?n.length-1:t,0),function(){for(var e=arguments,u=-1,o=jn(e.length-t,0),i=Array(o);++u<o;)i[u]=e[t+u];for(u=-1,
+o=Array(t+1);++u<t;)o[u]=e[u];return o[t]=r(i),n.apply(this,o)}}function $(n){return(null==n?0:n.length)?p(n,1):[]}function q(n){return n&&n.length?n[0]:Z}function P(n,t,r){var e=null==n?0:n.length;r=typeof r=="number"?0>r?jn(e+r,0):r:0,r=(r||0)-1;for(var u=t===t;++r<e;){var o=n[r];if(u?o===t:o!==o)return r}return-1}function z(n,t){return mn(n,g(t))}function C(n,t,r){return e(n,g(t),r,3>arguments.length,mn)}function G(n,t){var r;if(typeof t!="function")throw new TypeError("Expected a function");return n=Fn(n),
+function(){return 0<--n&&(r=t.apply(this,arguments)),1>=n&&(t=Z),r}}function J(n,t){return n===t||n!==n&&t!==t}function M(n){var t;return(t=null!=n)&&(t=n.length,t=typeof t=="number"&&-1<t&&0==t%1&&9007199254740991>=t),t&&!U(n)}function U(n){return!!V(n)&&(n=hn.call(n),"[object Function]"==n||"[object GeneratorFunction]"==n||"[object AsyncFunction]"==n||"[object Proxy]"==n)}function V(n){var t=typeof n;return null!=n&&("object"==t||"function"==t)}function H(n){return null!=n&&typeof n=="object"}function K(n){
+return typeof n=="number"||H(n)&&"[object Number]"==hn.call(n)}function L(n){return typeof n=="string"||!Nn(n)&&H(n)&&"[object String]"==hn.call(n)}function Q(n){return typeof n=="string"?n:null==n?"":n+""}function W(n){return null==n?[]:u(n,Dn(n))}function X(n){return n}function Y(n,r,e){var u=Dn(r),o=h(r,u);null!=e||V(r)&&(o.length||!u.length)||(e=r,r=n,n=this,o=h(r,Dn(r)));var i=!(V(e)&&"chain"in e&&!e.chain),c=U(n);return mn(o,function(e){var u=r[e];n[e]=u,c&&(n.prototype[e]=function(){var r=this.__chain__;
+if(i||r){var e=n(this.__wrapped__);return(e.__actions__=A(this.__actions__)).push({func:u,args:arguments,thisArg:n}),e.__chain__=r,e}return u.apply(n,t([this.value()],arguments))})}),n}var Z,nn=1/0,tn=/[&<>"']/g,rn=RegExp(tn.source),en=/^(?:0|[1-9]\d*)$/,un=typeof self=="object"&&self&&self.Object===Object&&self,on=typeof global=="object"&&global&&global.Object===Object&&global||un||Function("return this")(),cn=(un=typeof exports=="object"&&exports&&!exports.nodeType&&exports)&&typeof module=="object"&&module&&!module.nodeType&&module,fn=function(n){
+return function(t){return null==n?Z:n[t]}}({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"}),an=Array.prototype,ln=Object.prototype,pn=ln.hasOwnProperty,sn=0,hn=ln.toString,vn=on._,bn=Object.create,yn=ln.propertyIsEnumerable,gn=on.isFinite,_n=function(n,t){return function(r){return n(t(r))}}(Object.keys,Object),jn=Math.max,dn=function(){function n(){}return function(t){return V(t)?bn?bn(t):(n.prototype=t,t=new n,n.prototype=Z,t):{}}}();i.prototype=dn(o.prototype),i.prototype.constructor=i;
+var mn=function(n,t){return function(r,e){if(null==r)return r;if(!M(r))return n(r,e);for(var u=r.length,o=t?u:-1,i=Object(r);(t?o--:++o<u)&&false!==e(i[o],o,i););return r}}(s),On=function(n){return function(t,r,e){var u=-1,o=Object(t);e=e(t);for(var i=e.length;i--;){var c=e[n?i:++u];if(false===r(o[c],c,o))break}return t}}(),xn=X,An=function(n){return function(t,r,e){var u=Object(t);if(!M(t)){var o=g(r);t=Dn(t),r=function(n){return o(u[n],n,u)}}return r=n(t,r,e),-1<r?u[o?t[r]:r]:Z}}(function(n,t,r){var e=null==n?0:n.length;
+if(!e)return-1;r=null==r?0:Fn(r),0>r&&(r=jn(e+r,0));n:{for(t=g(t),e=n.length,r+=-1;++r<e;)if(t(n[r],r,n)){n=r;break n}n=-1}return n}),En=O(function(n,t,r){return S(n,t,r)}),wn=O(function(n,t){return c(n,1,t)}),kn=O(function(n,t,r){return c(n,Sn(t)||0,r)}),Nn=Array.isArray,Fn=Number,Sn=Number,Tn=N(function(n,t){k(t,_n(t),n)}),Bn=N(function(n,t){k(t,D(t),n)}),Rn=O(function(n,t){n=Object(n);var r,e=-1,u=t.length,o=2<u?t[2]:Z;if(r=o){r=t[0];var i=t[1];if(V(o)){var c=typeof i;if("number"==c){if(c=M(o))var c=o.length,f=typeof i,c=null==c?9007199254740991:c,c=!!c&&("number"==f||"symbol"!=f&&en.test(i))&&-1<i&&0==i%1&&i<c;
+}else c="string"==c&&i in o;r=!!c&&J(o[i],r)}else r=false}for(r&&(u=1);++e<u;)for(o=t[e],r=In(o),i=-1,c=r.length;++i<c;){var f=r[i],a=n[f];(a===Z||J(a,ln[f])&&!pn.call(n,f))&&(n[f]=o[f])}return n}),Dn=_n,In=D,$n=function(n){return xn(I(n,Z,$),n+"")}(function(n,t){return null==n?{}:m(n,t)});o.assignIn=Bn,o.before=G,o.bind=En,o.chain=function(n){return n=o(n),n.__chain__=true,n},o.compact=function(n){return l(n,Boolean)},o.concat=function(){var n=arguments.length;if(!n)return[];for(var r=Array(n-1),e=arguments[0];n--;)r[n-1]=arguments[n];
+return t(Nn(e)?A(e):[e],p(r,1))},o.create=function(n,t){var r=dn(n);return null==t?r:Tn(r,t)},o.defaults=Rn,o.defer=wn,o.delay=kn,o.filter=function(n,t){return l(n,g(t))},o.flatten=$,o.flattenDeep=function(n){return(null==n?0:n.length)?p(n,nn):[]},o.iteratee=g,o.keys=Dn,o.map=function(n,t){return j(n,g(t))},o.matches=function(n){return d(Tn({},n))},o.mixin=Y,o.negate=function(n){if(typeof n!="function")throw new TypeError("Expected a function");return function(){return!n.apply(this,arguments)}},o.once=function(n){
+return G(2,n)},o.pick=$n,o.slice=function(n,t,r){var e=null==n?0:n.length;return r=r===Z?e:+r,e?x(n,null==t?0:+t,r):[]},o.sortBy=function(n,t){var e=0;return t=g(t),j(j(n,function(n,r,u){return{value:n,index:e++,criteria:t(n,r,u)}}).sort(function(n,t){var r;n:{r=n.criteria;var e=t.criteria;if(r!==e){var u=r!==Z,o=null===r,i=r===r,c=e!==Z,f=null===e,a=e===e;if(!f&&r>e||o&&c&&a||!u&&a||!i){r=1;break n}if(!o&&r<e||f&&u&&i||!c&&i||!a){r=-1;break n}}r=0}return r||n.index-t.index}),r("value"))},o.tap=function(n,t){
+return t(n),n},o.thru=function(n,t){return t(n)},o.toArray=function(n){return M(n)?n.length?A(n):[]:W(n)},o.values=W,o.extend=Bn,Y(o,o),o.clone=function(n){return V(n)?Nn(n)?A(n):k(n,_n(n)):n},o.escape=function(n){return(n=Q(n))&&rn.test(n)?n.replace(tn,fn):n},o.every=function(n,t,r){return t=r?Z:t,f(n,g(t))},o.find=An,o.forEach=z,o.has=function(n,t){return null!=n&&pn.call(n,t)},o.head=q,o.identity=X,o.indexOf=P,o.isArguments=n,o.isArray=Nn,o.isBoolean=function(n){return true===n||false===n||H(n)&&"[object Boolean]"==hn.call(n);
+},o.isDate=function(n){return H(n)&&"[object Date]"==hn.call(n)},o.isEmpty=function(t){return M(t)&&(Nn(t)||L(t)||U(t.splice)||n(t))?!t.length:!_n(t).length},o.isEqual=function(n,t){return b(n,t)},o.isFinite=function(n){return typeof n=="number"&&gn(n)},o.isFunction=U,o.isNaN=function(n){return K(n)&&n!=+n},o.isNull=function(n){return null===n},o.isNumber=K,o.isObject=V,o.isRegExp=function(n){return H(n)&&"[object RegExp]"==hn.call(n)},o.isString=L,o.isUndefined=function(n){return n===Z},o.last=function(n){
+var t=null==n?0:n.length;return t?n[t-1]:Z},o.max=function(n){return n&&n.length?a(n,X,v):Z},o.min=function(n){return n&&n.length?a(n,X,_):Z},o.noConflict=function(){return on._===this&&(on._=vn),this},o.noop=function(){},o.reduce=C,o.result=function(n,t,r){return t=null==n?Z:n[t],t===Z&&(t=r),U(t)?t.call(n):t},o.size=function(n){return null==n?0:(n=M(n)?n:_n(n),n.length)},o.some=function(n,t,r){return t=r?Z:t,E(n,g(t))},o.uniqueId=function(n){var t=++sn;return Q(n)+t},o.each=z,o.first=q,Y(o,function(){
+var n={};return s(o,function(t,r){pn.call(o.prototype,r)||(n[r]=t)}),n}(),{chain:false}),o.VERSION="4.17.10",mn("pop join replace reverse split push shift sort splice unshift".split(" "),function(n){var t=(/^(?:replace|split)$/.test(n)?String.prototype:an)[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:pop|join|replace|shift)$/.test(n);o.prototype[n]=function(){var n=arguments;if(e&&!this.__chain__){var u=this.value();return t.apply(Nn(u)?u:[],n)}return this[r](function(r){return t.apply(Nn(r)?r:[],n);
+})}}),o.prototype.toJSON=o.prototype.valueOf=o.prototype.value=function(){return w(this.__wrapped__,this.__actions__)},typeof define=="function"&&typeof define.amd=="object"&&define.amd?(on._=o, define(function(){return o})):cn?((cn.exports=o)._=o,un._=o):on._=o}).call(this);

File diff suppressed because it is too large
+ 5 - 0
node_modules/cos-js-sdk-v5/demo/common/vue.min.js


BIN
node_modules/cos-js-sdk-v5/demo/cors.png


+ 1033 - 0
node_modules/cos-js-sdk-v5/demo/demo.js

@@ -0,0 +1,1033 @@
+var config = {
+    Bucket: 'test-1250000000',
+    Region: 'ap-guangzhou'
+};
+
+var util = {
+    createFile: function (options) {
+        var buffer = new ArrayBuffer(options.size || 0);
+        var arr = new Uint8Array(buffer);
+        [].forEach.call(arr, function (char, i) {
+            arr[i] = 0;
+        });
+        var opt = {};
+        options.type && (opt.type = options.type);
+        var blob = new Blob([buffer], options);
+        return blob;
+    }
+};
+
+// 对更多字符编码的 url encode 格式
+var camSafeUrlEncode = function (str) {
+    return encodeURIComponent(str)
+        .replace(/!/g, '%21')
+        .replace(/'/g, '%27')
+        .replace(/\(/g, '%28')
+        .replace(/\)/g, '%29')
+        .replace(/\*/g, '%2A');
+};
+
+var getAuthorization = function (options, callback) {
+
+    // 格式一、(推荐)后端通过获取临时密钥给到前端,前端计算签名
+    // 服务端 JS 和 PHP 例子:https://github.com/tencentyun/cos-js-sdk-v5/blob/master/server/
+    // 服务端其他语言参考 COS STS SDK :https://github.com/tencentyun/qcloud-cos-sts-sdk
+    // var url = '../server/sts.php'; // 如果起的是 php server 用这个
+    var url = '/sts'; // 如果是 npm run sts.js 起的 nodejs server,使用这个
+    var xhr = new XMLHttpRequest();
+    xhr.open('GET', url, true);
+    xhr.onload = function (e) {
+        try {
+            var data = JSON.parse(e.target.responseText);
+            var credentials = data.credentials;
+        } catch (e) {
+        }
+        if (!data || !credentials) return console.error('credentials invalid');
+        callback({
+            TmpSecretId: credentials.tmpSecretId,
+            TmpSecretKey: credentials.tmpSecretKey,
+            XCosSecurityToken: credentials.sessionToken,
+            StartTime: data.startTime, // 时间戳,单位秒,如:1580000000,建议返回服务器时间作为签名的开始时间,避免用户浏览器本地时间偏差过大导致签名错误
+            ExpiredTime: data.expiredTime, // 时间戳,单位秒,如:1580000900
+        });
+    };
+    xhr.send();
+
+
+    // // 格式二、(推荐)【细粒度控制权限】后端通过获取临时密钥给到前端,前端只有相同请求才重复使用临时密钥,后端可以通过 Scope 细粒度控制权限
+    // // 服务端例子:https://github.com/tencentyun/qcloud-cos-sts-sdk/edit/master/scope.md
+    // // var url = '../server/sts.php'; // 如果起的是 php server 用这个
+    // var url = '/sts-scope'; // 如果是 npm run sts.js 起的 nodejs server,使用这个
+    // var xhr = new XMLHttpRequest();
+    // xhr.open('POST', url, true);
+    // xhr.setRequestHeader('Content-Type', 'application/json');
+    // xhr.onload = function (e) {
+    //     try {
+    //         var data = JSON.parse(e.target.responseText);
+    //         var credentials = data.credentials;
+    //     } catch (e) {
+    //     }
+    //     if (!data || !credentials) return console.error('credentials invalid');
+    //     callback({
+    //         TmpSecretId: credentials.tmpSecretId,
+    //         TmpSecretKey: credentials.tmpSecretKey,
+    //         XCosSecurityToken: credentials.sessionToken,
+    //         StartTime: data.startTime, // 时间戳,单位秒,如:1580000000,建议返回服务器时间作为签名的开始时间,避免用户浏览器本地时间偏差过大导致签名错误
+    //         ExpiredTime: data.expiredTime, // 时间戳,单位秒,如:1580000000
+    //         ScopeLimit: true, // 细粒度控制权限需要设为 true,会限制密钥只在相同请求时重复使用
+    //     });
+    // };
+    // xhr.send(JSON.stringify(options.Scope));
+
+
+    // // 格式三、(不推荐,分片上传权限不好控制)前端每次请求前都需要通过 getAuthorization 获取签名,后端使用固定密钥或临时密钥计算签名返回给前端
+    // // 服务端获取签名,请参考对应语言的 COS SDK:https://cloud.tencent.com/document/product/436/6474
+    // // 注意:这种有安全风险,后端需要通过 method、pathname 严格控制好权限,比如不允许 put / 等
+    // var method = (options.Method || 'get').toLowerCase();
+    // var query = options.Query || {};
+    // var headers = options.Headers || {};
+    // var pathname = options.Pathname || '/';
+    // // var url = 'http://127.0.0.1:3000/auth';
+    // var url = '../server/auth.php';
+    // var xhr = new XMLHttpRequest();
+    // var data = {
+    //     method: method,
+    //     pathname: pathname,
+    //     query: query,
+    //     headers: headers,
+    // };
+    // xhr.open('POST', url, true);
+    // xhr.setRequestHeader('content-type', 'application/json');
+    // xhr.onload = function (e) {
+    //     try {
+    //         var data = JSON.parse(e.target.responseText);
+    //     } catch (e) {
+    //     }
+    //     if (!data || !data.authorization) return console.error('authorization invalid');
+    //     callback({
+    //         Authorization: data.authorization,
+    //         // XCosSecurityToken: data.sessionToken, // 如果使用临时密钥,需要把 sessionToken 传给 XCosSecurityToken
+    //     });
+    // };
+    // xhr.send(JSON.stringify(data));
+
+
+    // // 格式四、(不推荐,适用于前端调试,避免泄露密钥)前端使用固定密钥计算签名
+    // var authorization = COS.getAuthorization({
+    //     SecretId: 'AKIDxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', // 可传固定密钥或者临时密钥
+    //     SecretKey: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', // 可传固定密钥或者临时密钥
+    //     Method: options.Method,
+    //     Pathname: options.Pathname,
+    //     Query: options.Query,
+    //     Headers: options.Headers,
+    //     Expires: 900,
+    // });
+    // callback({
+    //     Authorization: authorization,
+    //     // XCosSecurityToken: credentials.sessionToken, // 如果使用临时密钥,需要传 XCosSecurityToken
+    // });
+
+};
+
+var cos = new COS({
+    getAuthorization: getAuthorization,
+});
+
+var TaskId;
+
+var pre = document.querySelector('.result');
+var showLogText = function (text, color) {
+    if (typeof text === 'object') {
+        try {
+            text = JSON.stringify(text);
+        } catch (e) {
+        }
+    }
+    var div = document.createElement('div');
+    div.innerText = text;
+    color && (div.style.color = color);
+    pre.appendChild(div);
+    pre.style.display = 'block';
+    pre.scrollTop = pre.scrollHeight;
+};
+
+var logger = {
+    log: function (text) {
+        console.log.apply(console, arguments);
+        var args = [].map.call(arguments, function (v) {
+            return typeof v === 'object' ? JSON.stringify(v) : v;
+        });
+
+        var logStr = args.join(' ');
+
+        if(logStr.length > 1000000) {
+            logStr = logStr.slice(0, 1000000) + '...content is too long, the first 1000000 characters are intercepted';
+        }
+
+        showLogText(logStr);
+    },
+    error: function (text) {
+        console.error(text);
+        showLogText(text, 'red');
+    },
+};
+
+function getObjectUrl() {
+    var url = cos.getObjectUrl({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region,
+        Key: '1mb.zip',
+        Expires: 60,
+        Sign: true,
+    }, function (err, data) {
+        logger.log(err || data && data.Url);
+    });
+    logger.log(url);
+}
+
+function getAuth() {
+    var key = '1.png';
+    // 这里不推荐自己拼接,推荐使用 getObjectUrl 获取 url
+    getAuthorization({
+        Method: 'get',
+        Key: key
+    }, function (AuthData) {
+        if (typeof AuthData === 'string') {
+            AuthData = {Authorization: AuthData.Authorization};
+        }
+        var url = 'http://' + config.Bucket + '.cos.' + config.Region + '.myqcloud.com' + '/' +
+            camSafeUrlEncode(key).replace(/%2F/g, '/') +
+            '?' + AuthData +
+            (AuthData.XCosSecurityToken ? '&' + AuthData.XCosSecurityToken : '');
+        logger.log(url);
+    });
+}
+
+// getService、putBucket 接口会跨域,不支持浏览器使用,只在场景下可调用,比如改了 ServiceDomain 到代理地址
+function getService() {
+    cos.getService({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region,
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+// getService、putBucket 接口会跨域,不支持浏览器使用,只在场景下可调用,比如改了 ServiceDomain 到代理地址
+function putBucket() {
+    cos.putBucket({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region,
+        // Prefix: 'dir/'
+        // Delimiter: '/'
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function getBucket() {
+    cos.getBucket({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region,
+        // Prefix: 'dir/'
+        // Delimiter: '/'
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function headBucket() {
+    cos.headBucket({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function deleteBucket() {
+    cos.deleteBucket({
+        Bucket: 'testnew-' + config.Bucket.substr(config.Bucket.lastIndexOf('-') + 1),
+        Region: 'ap-guangzhou'
+    }, function (err, data) {
+        console.log(err || data);
+    });
+}
+
+function putBucketAcl() {
+    cos.putBucketAcl({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region,
+        // GrantFullControl: 'id="qcs::cam::uin/1001:uin/1001",id="qcs::cam::uin/1002:uin/1002"',
+        // GrantWrite: 'id="qcs::cam::uin/1001:uin/1001",id="qcs::cam::uin/1002:uin/1002"',
+        // GrantRead: 'id="qcs::cam::uin/1001:uin/1001",id="qcs::cam::uin/1002:uin/1002"',
+        // GrantReadAcp: 'id="qcs::cam::uin/1001:uin/1001",id="qcs::cam::uin/1002:uin/1002"',
+        // GrantWriteAcp: 'id="qcs::cam::uin/1001:uin/1001",id="qcs::cam::uin/1002:uin/1002"',
+        // ACL: 'public-read-write',
+        // ACL: 'public-read',
+        ACL: 'private',
+        // AccessControlPolicy: {
+        // "Owner": { // AccessControlPolicy 里必须有 owner
+        //     "ID": 'qcs::cam::uin/10001:uin/10001' // 10001 是 Bucket 所属用户的 QQ 号
+        // },
+        // "Grants": [{
+        //     "Grantee": {
+        //         "ID": "qcs::cam::uin/1001:uin/1001", // 10002 是 QQ 号
+        //         "DisplayName": "qcs::cam::uin/1001:uin/1001" // 10002 是 QQ 号
+        //     },
+        //     "Permission": "READ"
+        // }, {
+        //     "Grantee": {
+        //         "ID": "qcs::cam::uin/10002:uin/10002", // 10002 是 QQ 号
+        //     },
+        //     "Permission": "WRITE"
+        // }, {
+        //     "Grantee": {
+        //         "ID": "qcs::cam::uin/10002:uin/10002", // 10002 是 QQ 号
+        //     },
+        //     "Permission": "READ_ACP"
+        // }, {
+        //     "Grantee": {
+        //         "ID": "qcs::cam::uin/10002:uin/10002", // 10002 是 QQ 号
+        //     },
+        //     "Permission": "WRITE_ACP"
+        // }]
+        // }
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function getBucketAcl() {
+    cos.getBucketAcl({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function putBucketCors() {
+    cos.putBucketCors({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region,
+        CORSRules: [{
+            "AllowedOrigin": ["*"],
+            "AllowedMethod": ["GET", "POST", "PUT", "DELETE", "HEAD"],
+            "AllowedHeader": ["*"],
+            "ExposeHeader": ["ETag", "Date", "Content-Length", "x-cos-acl", "x-cos-version-id", "x-cos-request-id", "x-cos-delete-marker", "x-cos-server-side-encryption"],
+            "MaxAgeSeconds": "5"
+        }]
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function getBucketCors() {
+    cos.getBucketCors({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function deleteBucketCors() {
+    cos.deleteBucketCors({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function putBucketTagging() {
+    cos.putBucketTagging({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region,
+        Tagging: {
+            "Tags": [
+                {"Key": "k1", "Value": "v1"},
+                {"Key": "k2", "Value": "v2"}
+            ]
+        }
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function getBucketTagging() {
+    cos.getBucketTagging({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function deleteBucketTagging() {
+    cos.deleteBucketTagging({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function putBucketPolicy() {
+    var AppId = config.Bucket.substr(config.Bucket.lastIndexOf('-') + 1);
+    cos.putBucketPolicy({
+        Policy: {
+            "version": "2.0",
+            "statement": [{
+                "effect": "allow",
+                "principal": {"qcs": ["qcs::cam::uin/10001:uin/10001"]}, // 这里的 10001 是 QQ 号
+                "action": [
+                    // 这里可以从临时密钥的权限上控制前端允许的操作
+                    // 'name/cos:*', // 这样写可以包含下面所有权限
+
+                    // // 列出所有允许的操作
+                    // // ACL 读写
+                    // 'name/cos:GetBucketACL',
+                    // 'name/cos:PutBucketACL',
+                    // 'name/cos:GetObjectACL',
+                    // 'name/cos:PutObjectACL',
+                    // // 简单 Bucket 操作
+                    // 'name/cos:PutBucket',
+                    // 'name/cos:HeadBucket',
+                    // 'name/cos:GetBucket',
+                    // 'name/cos:DeleteBucket',
+                    // 'name/cos:GetBucketLocation',
+                    // // Versioning
+                    // 'name/cos:PutBucketVersioning',
+                    // 'name/cos:GetBucketVersioning',
+                    // // CORS
+                    // 'name/cos:PutBucketCORS',
+                    // 'name/cos:GetBucketCORS',
+                    // 'name/cos:DeleteBucketCORS',
+                    // // Lifecycle
+                    // 'name/cos:PutBucketLifecycle',
+                    // 'name/cos:GetBucketLifecycle',
+                    // 'name/cos:DeleteBucketLifecycle',
+                    // // Replication
+                    // 'name/cos:PutBucketReplication',
+                    // 'name/cos:GetBucketReplication',
+                    // 'name/cos:DeleteBucketReplication',
+                    // // 删除文件
+                    // 'name/cos:DeleteMultipleObject',
+                    // 'name/cos:DeleteObject',
+                    // 简单文件操作
+                    'name/cos:PutObject',
+                    'name/cos:AppendObject',
+                    'name/cos:GetObject',
+                    'name/cos:HeadObject',
+                    'name/cos:OptionsObject',
+                    'name/cos:PutObjectCopy',
+                    'name/cos:PostObjectRestore',
+                    // 分片上传操作
+                    'name/cos:InitiateMultipartUpload',
+                    'name/cos:ListMultipartUploads',
+                    'name/cos:ListParts',
+                    'name/cos:UploadPart',
+                    'name/cos:CompleteMultipartUpload',
+                    'name/cos:AbortMultipartUpload',
+                ],
+                // "resource": ["qcs::cos:ap-guangzhou:uid/1250000000:test-1250000000/*"] // 1250000000 是 appid
+                "resource": ["qcs::cos:" + config.Region + ":uid/" + AppId + ":" + config.Bucket + "/*"] // 1250000000 是 appid
+            }]
+        },
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function getBucketPolicy() {
+    cos.getBucketPolicy({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function deleteBucketPolicy() {
+    cos.deleteBucketPolicy({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function getBucketLocation() {
+    cos.getBucketLocation({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function putBucketLifecycle() {
+    cos.putBucketLifecycle({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region,
+        LifecycleConfiguration: {
+            Rules: [{
+                "ID": "1",
+                "Status": "Enabled",
+                "Filter": {},
+                "Transition": {
+                    "Days": "30",
+                    "StorageClass": "STANDARD_IA"
+                }
+            }, {
+                "ID": "2",
+                "Status": "Enabled",
+                "Filter": {
+                    "Prefix": "dir/"
+                },
+                "Transition": {
+                    "Days": "90",
+                    "StorageClass": "ARCHIVE"
+                }
+            }, {
+                "ID": "3",
+                "Status": "Enabled",
+                "Filter": {},
+                "Expiration": {
+                    "Days": "180"
+                }
+            }, {
+                "ID": "4",
+                "Status": "Enabled",
+                "Filter": {},
+                "AbortIncompleteMultipartUpload": {
+                    "DaysAfterInitiation": "30"
+                }
+            }],
+        }
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function getBucketLifecycle() {
+    cos.getBucketLifecycle({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function deleteBucketLifecycle() {
+    cos.deleteBucketLifecycle({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function putBucketVersioning() {
+    cos.putBucketVersioning({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region,
+        VersioningConfiguration: {
+            Status: "Enabled"
+        }
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function getBucketVersioning() {
+    cos.getBucketVersioning({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function listObjectVersions() {
+    cos.listObjectVersions({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region,
+        // Prefix: "",
+        // Delimiter: '/'
+    }, function (err, data) {
+        logger.log(err || JSON.stringify(data, null, '    '));
+    });
+}
+
+function putBucketReplication() {
+    var AppId = config.Bucket.substr(config.Bucket.lastIndexOf('-') + 1);
+    cos.putBucketReplication({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region,
+        ReplicationConfiguration: {
+            Role: "qcs::cam::uin/10001:uin/10001",
+            Rules: [{
+                ID: "1",
+                Status: "Enabled",
+                Prefix: "sync/",
+                Destination: {
+                    Bucket: "qcs:id/0:cos:ap-chengdu:appid/" + AppId + ":backup",
+                    // StorageClass: "Standard",
+                }
+            }]
+        }
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function getBucketReplication() {
+    cos.getBucketReplication({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function deleteBucketReplication() {
+    cos.deleteBucketReplication({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function putBucketWebsite() {
+    cos.putBucketWebsite({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region,
+        WebsiteConfiguration: {
+            IndexDocument: {
+                Suffix: "index.html" // 必选
+            },
+            RedirectAllRequestsTo: {
+                Protocol: "https"
+            },
+            // ErrorDocument: {
+            //     Key: "error.html"
+            // },
+            // RoutingRules: [{
+            //     Condition: {
+            //         HttpErrorCodeReturnedEquals: "404"
+            //     },
+            //     Redirect: {
+            //         Protocol: "https",
+            //         ReplaceKeyWith: "404.html"
+            //     }
+            // }, {
+            //     Condition: {
+            //         KeyPrefixEquals: "docs/"
+            //     },
+            //     Redirect: {
+            //         Protocol: "https",
+            //         ReplaceKeyPrefixWith: "documents/"
+            //     }
+            // }, {
+            //     Condition: {
+            //         KeyPrefixEquals: "img/"
+            //     },
+            //     Redirect: {
+            //         Protocol: "https",
+            //         ReplaceKeyWith: "picture.jpg"
+            //     }
+            // }]
+        }
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function getBucketWebsite() {
+    cos.getBucketWebsite({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region
+    },function(err, data){
+        logger.log(err || data);
+    });
+}
+
+function deleteBucketWebsite() {
+    cos.deleteBucketWebsite({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region
+    },function(err, data){
+        logger.log(err || data);
+    });
+}
+
+function putObject() {
+    // 创建测试文件
+    var filename = '1mb.zip';
+    var blob = util.createFile({size: 1024 * 1024 * 1});
+    // 调用方法
+    cos.putObject({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region,
+        Key: filename, /* 必须 */
+        Body: blob,
+        onTaskReady: function (tid) {
+            TaskId = tid;
+            console.log('onTaskReady', tid);
+        },
+        onTaskStart: function (info) {
+            console.log('onTaskStart', info);
+        },
+        onProgress: function (progressData) {
+            logger.log(JSON.stringify(progressData));
+        },
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function putObjectCopy() {
+    cos.putObjectCopy({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region,
+        Key: '1mb.copy.zip',
+        CopySource: config.Bucket + '.cos.' + config.Region + '.myqcloud.com/' + camSafeUrlEncode('1mb.zip').replace(/%2F/g, '/'), // Bucket 格式:test-1250000000
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function getObject() {
+    cos.getObject({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region,
+        Key: '1mb.zip',
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function headObject() {
+    cos.headObject({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region,
+        Key: '1mb.zip'
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function putObjectAcl() {
+    cos.putObjectAcl({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region,
+        Key: '1mb.zip',
+        // GrantFullControl: 'id="qcs::cam::uin/1001:uin/1001",id="qcs::cam::uin/1002:uin/1002"',
+        // GrantWrite: 'id="qcs::cam::uin/1001:uin/1001",id="qcs::cam::uin/1002:uin/1002"',
+        // GrantRead: 'id="qcs::cam::uin/1001:uin/1001",id="qcs::cam::uin/1002:uin/1002"',
+        // ACL: 'public-read-write',
+        // ACL: 'public-read',
+        // ACL: 'private',
+        ACL: 'default', // 继承上一级目录权限
+        // AccessControlPolicy: {
+        //     "Owner": { // AccessControlPolicy 里必须有 owner
+        //         "ID": 'qcs::cam::uin/10001:uin/10001' // 10001 是 Bucket 所属用户的 QQ 号
+        //     },
+        //     "Grants": [{
+        //         "Grantee": {
+        //             "ID": "qcs::cam::uin/10002:uin/10002", // 10002 是 QQ 号
+        //         },
+        //         "Permission": "READ"
+        //     }]
+        // }
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function getObjectAcl() {
+    cos.getObjectAcl({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region,
+        Key: '1mb.zip'
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function deleteObject() {
+    cos.deleteObject({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region,
+        Key: '1mb.zip'
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function deleteMultipleObject() {
+    cos.deleteMultipleObject({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region,
+        Objects: [
+            {Key: '中文/中文.txt'},
+            {Key: '中文/中文.zip',VersionId: 'MTg0NDY3NDI1MzM4NzM0ODA2MTI'},
+        ]
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function restoreObject() {
+    cos.restoreObject({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region,
+        Key: '1.txt',
+        RestoreRequest: {
+            Days: 1,
+            CASJobParameters: {
+                Tier: 'Expedited'
+            }
+        }
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function abortUploadTask() {
+    cos.abortUploadTask({
+        Bucket: config.Bucket, /* 必须 */ // Bucket 格式:test-1250000000
+        Region: config.Region, /* 必须 */
+        // 格式1,删除单个上传任务
+        // Level: 'task',
+        // Key: '10mb.zip',
+        // UploadId: '14985543913e4e2642e31db217b9a1a3d9b3cd6cf62abfda23372c8d36ffa38585492681e3',
+        // 格式2,删除单个文件所有未完成上传任务
+        Level: 'file',
+        Key: '10mb.zip',
+        // 格式3,删除 Bucket 下所有未完成上传任务
+        // Level: 'bucket',
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function sliceUploadFile() {
+    var blob = util.createFile({size: 1024 * 1024 * 3});
+    cos.sliceUploadFile({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region,
+        Key: '3mb.zip', /* 必须 */
+        Body: blob,
+        onTaskReady: function (tid) {
+            TaskId = tid;
+        },
+        onHashProgress: function (progressData) {
+            logger.log('onHashProgress', JSON.stringify(progressData));
+        },
+        onProgress: function (progressData) {
+            logger.log('onProgress', JSON.stringify(progressData));
+        },
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function selectFileToUpload() {
+    var input = document.getElementById('file_selector') || document.createElement('input');
+    input.type = 'file';
+    input.onchange = function (e) {
+        document.body.removeChild(input);
+        var file = this.files[0];
+        if (!file) return;
+        if (file.size > 1024 * 1024) {
+            cos.sliceUploadFile({
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region,
+                Key: file.name,
+                Body: file,
+                onTaskReady: function (tid) {
+                    TaskId = tid;
+                },
+                onHashProgress: function (progressData) {
+                    logger.log('onHashProgress', JSON.stringify(progressData));
+                },
+                onProgress: function (progressData) {
+                    logger.log('onProgress', JSON.stringify(progressData));
+                },
+            }, function (err, data) {
+                logger.log(err || data);
+            });
+        } else {
+            cos.putObject({
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region,
+                Key: file.name,
+                Body: file,
+                onTaskReady: function (tid) {
+                    TaskId = tid;
+                },
+                onHashProgress: function (progressData) {
+                    logger.log('onHashProgress', JSON.stringify(progressData));
+                },
+                onProgress: function (progressData) {
+                    logger.log(JSON.stringify(progressData));
+                },
+            }, function (err, data) {
+                logger.log(err || data);
+            });
+        }
+    };
+    input.style = 'width:0;height:0;border:0;margin:0;padding:0;';
+    input.id = 'file_selector';
+    document.body.appendChild(input);
+    input.click();
+}
+
+function cancelTask() {
+    cos.cancelTask(TaskId);
+    logger.log('canceled');
+}
+
+function pauseTask() {
+    cos.pauseTask(TaskId);
+    logger.log('paused');
+}
+
+function restartTask() {
+    cos.restartTask(TaskId);
+    logger.log('restart');
+}
+
+function uploadFiles() {
+    var filename = 'mb.zip';
+    var blob = util.createFile({size: 1024 * 1024 * 10});
+    cos.uploadFiles({
+        files: [{
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            Key: '1' + filename,
+            Body: blob,
+        }, {
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            Key: '2' + filename,
+            Body: blob,
+        }, {
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            Key: '3' + filename,
+            Body: blob,
+        }],
+        SliceSize: 1024 * 1024,
+        onProgress: function (info) {
+            var percent = parseInt(info.percent * 10000) / 100;
+            var speed = parseInt(info.speed / 1024 / 1024 * 100) / 100;
+            logger.log('进度:' + percent + '%; 速度:' + speed + 'Mb/s;');
+        },
+        onFileFinish: function (err, data, options) {
+            logger.log(options.Key + ' 上传' + (err ? '失败' : '完成'));
+        },
+    }, function (err, data) {
+        logger.log(err || data);
+    });
+}
+
+function sliceCopyFile() {
+    // 创建测试文件
+    var sourceName = '3mb.zip';
+    var Key = '3mb.copy.zip';
+
+    var sourcePath = config.Bucket + '.cos.' + config.Region + '.myqcloud.com/'+ camSafeUrlEncode(sourceName).replace(/%2F/g, '/');
+
+    cos.sliceCopyFile({
+        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+        Region: config.Region,
+        Key: Key,
+        CopySource: sourcePath,
+        SliceSize: 2 * 1024 * 1024, // 大于2M的文件用分片复制,小于则用单片复制
+        onProgress:function (info) {
+            var percent = parseInt(info.percent * 10000) / 100;
+            var speed = parseInt(info.speed / 1024 / 1024 * 100) / 100;
+            logger.log('进度:' + percent + '%; 速度:' + speed + 'Mb/s;');
+        }
+    },function (err,data) {
+        if(err){
+            logger.log(err);
+        }else{
+            logger.log(data);
+        }
+    });
+
+}
+
+(function () {
+    var list = [
+        //'getService', // 不支持,正常场景会跨域
+        //'putBucket', // 不支持,正常场景会跨域
+        'getObjectUrl',
+        'getAuth',
+        'getBucket',
+        'headBucket',
+        'putBucketAcl',
+        'getBucketAcl',
+        'putBucketCors',
+        'getBucketCors',
+        // 'deleteBucketCors', // 不建议调用,删除 CORS,浏览器不能正常调用
+        'putBucketTagging',
+        'getBucketTagging',
+        'deleteBucketTagging',
+        'putBucketPolicy',
+        'getBucketPolicy',
+        'deleteBucketPolicy',
+        'getBucketLocation',
+        'getBucketLifecycle',
+        'putBucketLifecycle',
+        'deleteBucketLifecycle',
+        'putBucketVersioning',
+        'getBucketVersioning',
+        'listObjectVersions',
+        'putBucketReplication',
+        'getBucketReplication',
+        'deleteBucketReplication',
+        'putBucketWebsite',
+        'getBucketWebsite',
+        'deleteBucketWebsite',
+        'deleteBucket',
+        'putObject',
+        'putObjectCopy',
+        'getObject',
+        'headObject',
+        'putObjectAcl',
+        'getObjectAcl',
+        'deleteObject',
+        'deleteMultipleObject',
+        'restoreObject',
+        'abortUploadTask',
+        'sliceUploadFile',
+        'selectFileToUpload',
+        'cancelTask',
+        'pauseTask',
+        'restartTask',
+        'uploadFiles',
+        'sliceCopyFile',
+    ];
+    var container = document.querySelector('.main');
+    var html = [];
+    list.forEach(function (name) {
+        html.push('<a href="javascript:void(0)">' + name + '</a>');
+    });
+    container.innerHTML = html.join('');
+    container.onclick = function (e) {
+        if (e.target.tagName === 'A') {
+            var name = e.target.innerText.trim();
+            window[name]();
+        }
+    };
+})();

+ 1 - 0
node_modules/cos-js-sdk-v5/demo/empty.html

@@ -0,0 +1 @@
+This is a helper for "simple-form.html".

+ 19 - 0
node_modules/cos-js-sdk-v5/demo/folder/index.html

@@ -0,0 +1,19 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport"
+          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+    <meta http-equiv="X-UA-Compatible" content="ie=edge">
+    <title>COS 文件管理</title>
+    <link rel="stylesheet" href="style.css">
+</head>
+<body>
+
+<div class="page">
+    <h1>COS 文件管理</h1>
+    <div id="app">待实现...</div>
+</div>
+
+</body>
+</html>

Some files were not shown because too many files changed in this diff