Compare commits
8 Commits
Author | SHA1 | Date |
---|---|---|
jia | 082badc787 | |
jia | 7c349b94e9 | |
jia | a95ef0427a | |
jia | 154abe3887 | |
weipengfei | 6415fae765 | |
weipengfei | ebed1f6087 | |
weipengfei | d5d5500290 | |
weipengfei | 43c75b62fd |
|
@ -1,5 +1,6 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
unpackage*
|
||||
/dist
|
||||
.hbuilderx
|
||||
|
||||
|
|
|
@ -1,16 +1,24 @@
|
|||
{ // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
|
||||
// launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数
|
||||
"version": "0.0",
|
||||
"configurations": [{
|
||||
"app-plus" :
|
||||
{
|
||||
"launchtype" : "local"
|
||||
},
|
||||
"default" :
|
||||
{
|
||||
"launchtype" : "local"
|
||||
},
|
||||
"type" : "uniCloud"
|
||||
}
|
||||
{
|
||||
// launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
|
||||
// launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数
|
||||
"version" : "0.0",
|
||||
"configurations" : [
|
||||
{
|
||||
"app-plus" : {
|
||||
"launchtype" : "local"
|
||||
},
|
||||
"default" : {
|
||||
"launchtype" : "local"
|
||||
},
|
||||
"type" : "uniCloud"
|
||||
},
|
||||
{
|
||||
"playground" : "standard",
|
||||
"type" : "uni-app:app-android"
|
||||
},
|
||||
{
|
||||
"playground" : "custom",
|
||||
"type" : "uni-app:app-ios"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
6
App.vue
|
@ -2,6 +2,11 @@
|
|||
export default {
|
||||
onLaunch: function(info) {
|
||||
console.log('App Launch');
|
||||
uni.sendHostEvent('log',info, (ret) => {
|
||||
//发送消息成功回调
|
||||
console.log('消息成功app' + JSON.stringify(info));
|
||||
|
||||
});
|
||||
if (info.referrerInfo?.extraData?.uniMP) {
|
||||
uni.setStorageSync('uniMP', info.referrerInfo?.extraData?.uniMP);
|
||||
uni.setStorageSync('APP_token', info.referrerInfo?.extraData?.token);
|
||||
|
@ -24,4 +29,5 @@
|
|||
|
||||
<style>
|
||||
/*每个页面公共css */
|
||||
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
import request from "@/config/request.js";
|
||||
import requesta from "@/config/requesta.js";
|
||||
|
||||
export function xuiat(data) {
|
||||
return request.post(`xun_fei/tts`, data);
|
||||
}
|
||||
|
||||
export function feiiat(data) {
|
||||
return request.post(`xun_fei/iat`, data);
|
||||
}
|
||||
|
||||
export function iatWss(data) {
|
||||
return request.post(`xun_fei/iatWss`, data);
|
||||
}
|
||||
// http://chat.lihaink.cn/index/tts
|
||||
//文字转语音
|
||||
export function ttWss(data) {
|
||||
return requesta.post(`index/tts`, data);
|
||||
}
|
||||
|
||||
//图片识别
|
||||
export function ttocr(data) {
|
||||
return request.post(`xun_fei/ocr`, data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// base64 转 二进制流(blob)
|
||||
export function dataURLtoBlob(dataurl) {
|
||||
// console.log(dataurl);
|
||||
// let str = "data:audio/wav;base64," + dataurl.slice(2)
|
||||
// console.log(str);
|
||||
let mime = "audio/wav"
|
||||
// var arr = str.split(","),
|
||||
// mime = arr[0].match(/:(.*?);/),
|
||||
// let bstr = atob(arr[1])
|
||||
let bstr = atob(dataurl)
|
||||
let n = bstr.length
|
||||
let u8arr = new Uint8Array(n);
|
||||
while (n--) {
|
||||
u8arr[n] = bstr.charCodeAt(n);
|
||||
}
|
||||
console.log(u8arr)
|
||||
// return new Blob([u8arr], {
|
||||
// type: mime,
|
||||
// });
|
||||
}
|
||||
|
||||
|
||||
// -防抖
|
||||
export function debounce(fn, wait) {
|
||||
let delay = wait || 500
|
||||
let timer
|
||||
return function() {
|
||||
let args = arguments;
|
||||
if (timer) {
|
||||
clearTimeout(timer)
|
||||
console.log('拦截')
|
||||
}
|
||||
let callNow = !timer
|
||||
timer = setTimeout(() => {
|
||||
console.log('发送')
|
||||
timer = null
|
||||
}, delay)
|
||||
if (callNow) fn.apply(this, args)
|
||||
}
|
||||
}
|
||||
|
||||
// -节流
|
||||
export function throttle(fn, wait) {
|
||||
let delay = wait || 500
|
||||
let timer = null
|
||||
return function() {
|
||||
if (timer) {
|
||||
console.log('拦截');
|
||||
return
|
||||
}
|
||||
timer = setTimeout(() => {
|
||||
console.log('发送');
|
||||
fn.apply(this, arguments)
|
||||
timer = null
|
||||
}, delay)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
<template>
|
||||
<view class="contentgb">
|
||||
<view class="return_top">
|
||||
<view class="z-bootm-img1" @click="returnbom()">
|
||||
<image src="@/static/icon/fb1.png" mode="aspectFit"></image>
|
||||
</view>
|
||||
<view class="z-bootm-l"></view>
|
||||
<view class="z-bootm-img2" @click="returnbom()">
|
||||
<image src="@/static/icon/fb2.png" mode="aspectFit"></image>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
returnbom() {
|
||||
uni.sendHostEvent('closeApp', (ret) => {
|
||||
//发送消息成功回调
|
||||
console.log('关闭应用' + JSON.stringify(ret));
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.contentgb {
|
||||
|
||||
width: 166rpx;
|
||||
height: 56rpx;
|
||||
|
||||
.return_top {
|
||||
width: 166rpx;
|
||||
height: 56rpx;
|
||||
background: rgba(255, 255, 255, 0.6);
|
||||
border-radius: 44rpx 44rpx;
|
||||
|
||||
position: relative;
|
||||
|
||||
.z-bootm-img1 {
|
||||
width: 41rpx;
|
||||
height: 13rpx;
|
||||
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
left: 25rpx;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.z-bootm-l {
|
||||
width: 1px;
|
||||
height: 32rpx;
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
margin: auto 0;
|
||||
|
||||
position: absolute;
|
||||
top: 10rpx;
|
||||
left: 85rpx;
|
||||
}
|
||||
|
||||
.z-bootm-img2 {
|
||||
width: 38rpx;
|
||||
height: 34rpx;
|
||||
margin-top: -15rpx;
|
||||
margin-left: -15rpx;
|
||||
position: absolute;
|
||||
right: 25rpx;
|
||||
top: 25rpx;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 1.9 KiB |
|
@ -0,0 +1,595 @@
|
|||
<template>
|
||||
<view class="qiqb-ctx" v-bind:class="{'on':show}">
|
||||
|
||||
<view class="qiqb-ctx-box">
|
||||
<!-- <text @click="show=false"></text> -->
|
||||
<canvas canvas-id="ctx"
|
||||
:style="{'width':'340px','height':cliceHeight+'px','opacity':img_show?1:0}"></canvas>
|
||||
</view>
|
||||
|
||||
<view class="qiqb-ctx-img">
|
||||
<!-- <image :src="tempImage" mode="aspectFit" ></image> -->
|
||||
<img :src="tempImage">
|
||||
</view>
|
||||
<view class="qiqb-ctx-btns u-border-bottom">
|
||||
<view>分享至</view>
|
||||
<view>长按海报可转发分享</view>
|
||||
<view>
|
||||
<!-- <text>微信好友</text><text>分享朋友圈</text> -->
|
||||
<text @click="down">保存图片</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="qiqb-ctx-close" @click="close()">取消</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
HTTP_REQUEST_URL
|
||||
|
||||
} from '@/config/app';
|
||||
|
||||
export default {
|
||||
name: "share",
|
||||
|
||||
|
||||
data() {
|
||||
return {
|
||||
show: false,
|
||||
tempImage: '',
|
||||
img_show: true,
|
||||
mode: 'img',
|
||||
list: [],
|
||||
len1: 0,
|
||||
len2: 0,
|
||||
cliceHeight: 0,
|
||||
pext1: '',
|
||||
pext2: '',
|
||||
theight: 0
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
onLoad() {
|
||||
|
||||
},
|
||||
|
||||
|
||||
mounted() {},
|
||||
|
||||
|
||||
methods: {
|
||||
|
||||
//关闭
|
||||
close() {
|
||||
this.show = false
|
||||
this.img_show = true
|
||||
},
|
||||
//子组件接受参数
|
||||
refresh(index, item, height) {
|
||||
this.list = index;
|
||||
this.pext1 = index[index.length - 2].content
|
||||
this.pext2 = index[index.length - 1].content
|
||||
this.cliceHeight = item
|
||||
this.theight = height
|
||||
// console.log(index, item, height)
|
||||
},
|
||||
init() { // 通过opt传参数
|
||||
|
||||
uni.showLoading({
|
||||
title: '生成中'
|
||||
})
|
||||
let self = this
|
||||
let ctx = uni.createCanvasContext('ctx')
|
||||
// 绘制背景 宽度 高度 圆角 颜色
|
||||
self.drawBg(ctx, 340, this.cliceHeight, 8, '#fff')
|
||||
|
||||
// console.log(self.pext1, self.pext2)
|
||||
self.drawTxtOne(ctx, '农业咨询小程序', 220, 35, 100,
|
||||
'#222', 12, false)
|
||||
// 绘制圆角头像 图片地址 距离左边 距离上边 宽度 高度 圆角
|
||||
self.drawImg(ctx,
|
||||
'https://lihai001.oss-cn-chengdu.aliyuncs.com/storage/202310/20231013091310.png',
|
||||
170, 10, 40, 40, 20)
|
||||
self.drawImg(ctx,
|
||||
'https://lihai001.oss-cn-chengdu.aliyuncs.com/storage/202310/20231013091059.png',
|
||||
10, 50, 40, 40, 20)
|
||||
|
||||
self.drawImg(ctx,
|
||||
'https://lihai001.oss-cn-chengdu.aliyuncs.com/storage/202310/20231013091310.png',
|
||||
10, self.theight - 15, 40, 40, 20)
|
||||
|
||||
// 绘制封面图 图片地址 距离左边 距离上边 宽度 高度 圆角
|
||||
// self.drawImg(ctx, img, 10, 120, 210, 260, 8)
|
||||
|
||||
// 绘制二维码 图片地址 距离左边 距离上边 宽度 高度 圆角
|
||||
self.drawImg(ctx,
|
||||
'https://lihai001.oss-cn-chengdu.aliyuncs.com/storage/202310/ai_qr_20231013091327.jpg',
|
||||
174, self.cliceHeight - 125, 100, 100,
|
||||
0)
|
||||
|
||||
// 绘制单行文字 图片地址 距离左边 距离上边 宽度 颜色 字号 加粗
|
||||
// self.drawTxtOne(ctx, self.pext1, 60, 70, 100,
|
||||
// '#222', 12, false)
|
||||
self.drawTxtFour(ctx,
|
||||
self.pext1,
|
||||
60, 70,
|
||||
250, 20, '#222', 12)
|
||||
// self.drawTxtTwo(ctx, self.pext1, 60, 64, 80,
|
||||
// '#222', 13)
|
||||
// self.drawTxtTwo(ctx, self.pext1, 60,64,
|
||||
// 190, 20, '#222', 12)
|
||||
// 绘制单行文字 图片地址 距离左边 距离上边 宽度 颜色 字号 加粗
|
||||
// self.drawTxtOne(ctx, '邀请您一起购好物', 60, 80, 100,
|
||||
// '#666', 9, false)
|
||||
|
||||
// 绘制两行文字 图片地址 距离左边 距离上边 宽度 行高 颜色 字号
|
||||
self.drawTxtFour(ctx,
|
||||
self.pext2,
|
||||
60, self.theight,
|
||||
250, 20, '#222', 12)
|
||||
// 绘制单行文字 图片地址 距离左边 距离上边 宽度 颜色 字号 加粗
|
||||
self.drawTxtOne(ctx, '下载二维码', 15, self
|
||||
.cliceHeight - 85, 100,
|
||||
'#666', 11, false)
|
||||
|
||||
// 绘制单行文字 图片地址 距离左边 距离上边 宽度 颜色 字号 加粗
|
||||
// self.drawTxtOne(ctx, '今日特价:¥', 15, 350, 100,
|
||||
// '#ED3327', 11, false)
|
||||
|
||||
// 绘制单行文字 图片地址 距离左边 距离上边 宽度 颜色 字号 加粗
|
||||
// self.drawTxtOne(ctx, '86.00', 82, 350, 100,
|
||||
// '#ED3327', 11, true)
|
||||
|
||||
// 绘制删除文字 图片地址 距离左边 距离上边 行高 颜色 字号 加粗
|
||||
// self.drawTxtDel(ctx, '原价:20', 15, 370, 4,
|
||||
// '#818181', 10, false)
|
||||
|
||||
// 结束绘制
|
||||
ctx.draw()
|
||||
|
||||
// 绘制图片
|
||||
|
||||
self.img_show = false
|
||||
setTimeout(() => {
|
||||
uni.canvasToTempFilePath({
|
||||
canvasId: 'ctx',
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 340,
|
||||
height: this.cliceHeight,
|
||||
destWidth: 340,
|
||||
destHeight: this.cliceHeight,
|
||||
success: res => {
|
||||
|
||||
// #ifdef H5
|
||||
uni.hideLoading()
|
||||
self.tempImage = res.tempFilePath
|
||||
self.show = true
|
||||
//#endif
|
||||
// #ifdef APP-PLUS||MP
|
||||
self.imgfile(res.tempFilePath)
|
||||
//#endif
|
||||
|
||||
|
||||
},
|
||||
}, this);
|
||||
}, 3000)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
},
|
||||
//文件上传
|
||||
imgfile(tempFilePath) {
|
||||
let that = this
|
||||
|
||||
uni.uploadFile({
|
||||
url: HTTP_REQUEST_URL + '/api/upload/image', // 上传地址
|
||||
filePath: tempFilePath, // 要上传的文件路径
|
||||
name: 'file', // 上传文件对应的 key 值
|
||||
header: {
|
||||
'content-type': 'multipart/form-data'
|
||||
},
|
||||
success: function(res) {
|
||||
|
||||
let data = JSON.parse(res.data)
|
||||
// console.log( data.data.uri)
|
||||
if (data.code == 1) {
|
||||
uni.hideLoading()
|
||||
that.tempImage = data.data.uri
|
||||
that.show = true
|
||||
console.log('上传成功', that.tempImage)
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
fail: function(error) {
|
||||
// 上传失败处理逻辑
|
||||
uni.hideLoading()
|
||||
console.log(error, 11);
|
||||
|
||||
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
|
||||
down() {
|
||||
uni.showLoading({
|
||||
title: '保存中'
|
||||
})
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: this.tempImage,
|
||||
success: (res) => {
|
||||
console.log('保存')
|
||||
uni.hideLoading()
|
||||
this.close()
|
||||
uni.showModal({
|
||||
title: '保存成功'
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
// 绘制背景 宽度 高度 圆角 颜色
|
||||
drawBg(ctx, w, h, r, color) {
|
||||
let x = 0
|
||||
let y = 0
|
||||
ctx.setFillStyle(color)
|
||||
ctx.save()
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(x + r, y)
|
||||
ctx.arcTo(x + w, y, x + w, y + h, r)
|
||||
ctx.arcTo(x + w, y + h, x, y + h, r)
|
||||
ctx.arcTo(x, y + h, x, y, r)
|
||||
ctx.arcTo(x, y, x + w, y, r)
|
||||
ctx.closePath()
|
||||
ctx.fill()
|
||||
},
|
||||
// 绘制图片 图片地址 距离左边 距离上边 宽度 高度 圆角
|
||||
drawImg(ctx, img, x, y, w, h, r) {
|
||||
let self = this
|
||||
ctx.save()
|
||||
ctx.beginPath()
|
||||
ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5)
|
||||
ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2)
|
||||
ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5)
|
||||
ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI)
|
||||
ctx.clip()
|
||||
ctx.drawImage(img, x, y, w, h)
|
||||
ctx.restore()
|
||||
},
|
||||
// 绘制单行文字 图片地址 距离左边 距离上边 宽度 颜色 字号 加粗
|
||||
drawTxtOne(ctx, text, x, y, maxWidth, color, size, bold) {
|
||||
ctx.save()
|
||||
ctx.beginPath()
|
||||
let chr = text.split("")
|
||||
let temp = ""
|
||||
let row = []
|
||||
ctx.setFontSize(size)
|
||||
ctx.setFillStyle(color)
|
||||
for (let a = 0; a < chr.length; a++) {
|
||||
if (ctx.measureText(temp).width < maxWidth) {
|
||||
temp += chr[a]
|
||||
}
|
||||
}
|
||||
row.push(temp)
|
||||
if (ctx.measureText(temp).width > maxWidth) row[0] = row[0] + '...'
|
||||
|
||||
for (var b = 0; b < row.length; b++) {
|
||||
ctx.fillStyle = color
|
||||
if (bold) {
|
||||
ctx.font = 'normal bold ' + size + 'px sans-serif'
|
||||
} else {
|
||||
ctx.font = 'normal ' + size + 'px sans-serif'
|
||||
}
|
||||
ctx.fillText(row[b], x, y)
|
||||
}
|
||||
},
|
||||
// 绘制两行文字 图片地址 距离左边 距离上边 宽度 行高 颜色 字号
|
||||
drawTxtTwo(ctx, text, x, y, maxWidth, lineHeight, color, size) {
|
||||
ctx.save()
|
||||
ctx.beginPath()
|
||||
let chr = text.split("")
|
||||
let temp = ""
|
||||
let row = []
|
||||
ctx.setFontSize(size)
|
||||
ctx.setFillStyle(color)
|
||||
for (let a = 0; a < chr.length; a++) {
|
||||
if (ctx.measureText(temp).width < maxWidth) {
|
||||
temp += chr[a];
|
||||
} else {
|
||||
a--
|
||||
row.push(temp)
|
||||
temp = ""
|
||||
}
|
||||
}
|
||||
row.push(temp)
|
||||
if (row.length > 2) {
|
||||
let rowCut = row.slice(0, 2)
|
||||
let rowPart = rowCut[1]
|
||||
let test = ""
|
||||
let empty = []
|
||||
for (var a = 0; a < rowPart.length; a++) {
|
||||
if (ctx.measureText(test).width < maxWidth) {
|
||||
test += rowPart[a]
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
empty.push(test)
|
||||
var group = empty[0] + "..."
|
||||
rowCut.splice(1, 1, group)
|
||||
row = rowCut
|
||||
}
|
||||
for (var b = 0; b < row.length; b++) {
|
||||
ctx.fillStyle = color
|
||||
ctx.font = 'normal ' + size + 'px sans-serif'
|
||||
ctx.fillText(row[b], x, y + b * lineHeight, 300)
|
||||
}
|
||||
},
|
||||
drawTxtFour(ctx, text, x, y, maxWidth, lineHeight, color, size) {
|
||||
ctx.save()
|
||||
ctx.beginPath()
|
||||
let chr = text.split("")
|
||||
let temp = ""
|
||||
let row = []
|
||||
ctx.setFontSize(size)
|
||||
ctx.setFillStyle(color)
|
||||
for (let a = 0; a < chr.length; a++) {
|
||||
if (ctx.measureText(temp).width < maxWidth) {
|
||||
temp += chr[a];
|
||||
} else {
|
||||
a--
|
||||
row.push(temp)
|
||||
temp = ""
|
||||
}
|
||||
}
|
||||
row.push(temp)
|
||||
console.log(row[0].length)
|
||||
if (row.length > row.length) {
|
||||
let rowCut = row.slice(0, row.length)
|
||||
let rowPart = rowCut[1]
|
||||
let test = ""
|
||||
let empty = []
|
||||
for (var a = 0; a < rowPart.length; a++) {
|
||||
if (ctx.measureText(test).width < maxWidth) {
|
||||
test += rowPart[a]
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
empty.push(test)
|
||||
var group = empty[0] + "..."
|
||||
rowCut.splice(1, 1, group)
|
||||
row = rowCut
|
||||
}
|
||||
for (var b = 0; b < row.length; b++) {
|
||||
ctx.fillStyle = color
|
||||
ctx.font = 'normal ' + size + 'px sans-serif'
|
||||
ctx.fillText(row[b], x, y + b * lineHeight, 300)
|
||||
}
|
||||
},
|
||||
drawTxtFour1(ctx, text, x, y, maxWidth, lineHeight, color, size, type) {
|
||||
ctx.save()
|
||||
ctx.beginPath()
|
||||
let chr = text.split("")
|
||||
let temp = ""
|
||||
let row = []
|
||||
ctx.setFontSize(size)
|
||||
ctx.setFillStyle(color)
|
||||
for (let a = 0; a < chr.length; a++) {
|
||||
if (ctx.measureText(temp).width < maxWidth) {
|
||||
temp += chr[a];
|
||||
} else {
|
||||
a--
|
||||
row.push(temp)
|
||||
temp = ""
|
||||
}
|
||||
}
|
||||
row.push(temp)
|
||||
|
||||
|
||||
if (row.length > row.length) {
|
||||
let rowCut = row.slice(0, row.length)
|
||||
let rowPart = rowCut[1]
|
||||
let test = ""
|
||||
let empty = []
|
||||
for (var a = 0; a < rowPart.length; a++) {
|
||||
if (ctx.measureText(test).width < maxWidth) {
|
||||
test += rowPart[a]
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
empty.push(test)
|
||||
var group = empty[0] + "..."
|
||||
rowCut.splice(1, 1, group)
|
||||
row = rowCut
|
||||
}
|
||||
for (var b = 0; b < row.length; b++) {
|
||||
ctx.fillStyle = color
|
||||
ctx.font = 'normal ' + size + 'px sans-serif'
|
||||
ctx.fillText(row[b], x, y + b * lineHeight, 300)
|
||||
// console.log(row[b], x, y + b * lineHeight)
|
||||
if (type == 1) {
|
||||
this.len1 = y + b * lineHeight
|
||||
} else {
|
||||
this.len2 = y + b * lineHeight
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// console.log(this.len1,this.len2,type)
|
||||
|
||||
|
||||
},
|
||||
|
||||
// 绘制删除线文字 图片地址 距离左边 距离上边 行高 颜色 字号 加粗
|
||||
drawTxtDel(ctx, txt, x, y, h, color, size) {
|
||||
ctx.fillStyle = color
|
||||
ctx.font = 'normal ' + size + 'px sans-serif'
|
||||
ctx.fillText(txt, x, y)
|
||||
|
||||
ctx.beginPath()
|
||||
let width = ctx.measureText(txt).width;
|
||||
ctx.rect(x, y - h, width, 1)
|
||||
ctx.fillStyle = color
|
||||
ctx.fill()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.qiqb-ctx-img {
|
||||
position: fixed;
|
||||
top: 30rpx;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
transition: all .3s;
|
||||
|
||||
z-index: 9999;
|
||||
width: 600rpx;
|
||||
height: 750rpx;
|
||||
left: 50%;
|
||||
margin-left: -300rpx;
|
||||
|
||||
|
||||
img {
|
||||
width: 600rpx;
|
||||
height: 750rpx;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
|
||||
.qiqb-ctx {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: -1;
|
||||
display: flex;
|
||||
background: rgba(0, 0, 0, .6);
|
||||
opacity: 0;
|
||||
transition: all .3s;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
justify-content: flex-end
|
||||
}
|
||||
|
||||
.qiqb-ctx.on {
|
||||
z-index: 2000;
|
||||
opacity: 1
|
||||
}
|
||||
|
||||
.qiqb-ctx-box {
|
||||
position: relative;
|
||||
display: flex;
|
||||
padding: 30upx 0 40upx;
|
||||
width: 750upx;
|
||||
justify-content: center
|
||||
}
|
||||
|
||||
.qiqb-ctx-box text {
|
||||
position: absolute;
|
||||
top: -40upx;
|
||||
right: 145upx;
|
||||
display: inline-flex;
|
||||
width: 47upx;
|
||||
height: 47upx;
|
||||
background: url('img/close.png');
|
||||
background-size: 100% 100%
|
||||
}
|
||||
|
||||
.qiqb-ctx-btns {
|
||||
display: flex;
|
||||
width: 750upx;
|
||||
height: 330upx;
|
||||
border-radius: 20upx 20upx 0 0;
|
||||
background: #fff;
|
||||
flex-direction: row;
|
||||
flex-direction: column;
|
||||
align-items: center
|
||||
}
|
||||
|
||||
.qiqb-ctx-btns view:nth-child(1) {
|
||||
display: flex;
|
||||
padding-top: 10upx;
|
||||
height: 80upx;
|
||||
font-weight: 700;
|
||||
font-size: 30upx;
|
||||
align-items: center
|
||||
}
|
||||
|
||||
.qiqb-ctx-btns view:nth-child(2) {
|
||||
height: 80upx;
|
||||
color: #666;
|
||||
font-size: 24upx
|
||||
}
|
||||
|
||||
.qiqb-ctx-btns view:nth-child(3) {
|
||||
display: flex;
|
||||
padding-bottom: 30upx;
|
||||
font-size: 26upx;
|
||||
flex-direction: row;
|
||||
align-items: center
|
||||
}
|
||||
|
||||
.qiqb-ctx-btns view:nth-child(3) text {
|
||||
display: flex;
|
||||
width: 250upx;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center
|
||||
}
|
||||
|
||||
.qiqb-ctx-btns view:nth-child(3) text:nth-child(1)::before {
|
||||
display: inline-flex;
|
||||
margin-bottom: 20upx;
|
||||
width: 86upx;
|
||||
height: 86upx;
|
||||
background: url('img/3.png');
|
||||
background-size: 100% 100%;
|
||||
content: ''
|
||||
}
|
||||
|
||||
.qiqb-ctx-btns view:nth-child(3) text:nth-child(2)::before {
|
||||
display: inline-flex;
|
||||
margin-bottom: 20upx;
|
||||
width: 86upx;
|
||||
height: 86upx;
|
||||
background: url('img/1.png');
|
||||
background-size: 100% 100%;
|
||||
content: ''
|
||||
}
|
||||
|
||||
.qiqb-ctx-btns view:nth-child(3) text:nth-child(3)::before {
|
||||
display: inline-flex;
|
||||
margin-bottom: 20upx;
|
||||
width: 86upx;
|
||||
height: 86upx;
|
||||
background: url('img/2.png');
|
||||
background-size: 100% 100%;
|
||||
content: ''
|
||||
}
|
||||
|
||||
.qiqb-ctx-close {
|
||||
display: flex;
|
||||
padding-bottom: 50upx;
|
||||
width: 100%;
|
||||
height: 150upx;
|
||||
background: #fff;
|
||||
font-size: 32upx;
|
||||
align-items: center;
|
||||
justify-content: center
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,444 @@
|
|||
<template>
|
||||
<view class="qiqb-ctx" v-bind:class="{'on':show}">
|
||||
<view class="qiqb-ctx-box">
|
||||
<!-- <text @click="show=false"></text> -->
|
||||
<canvas canvas-id="ctx" style="width:330px;height:300px" v-show="img_show"></canvas>
|
||||
</view>
|
||||
<view class="qiqb-ctx-btns u-border-bottom">
|
||||
<view>分享至</view>
|
||||
<view>长按海报可转发分享</view>
|
||||
<view>
|
||||
<!-- <text>微信好友</text><text>分享朋友圈</text> -->
|
||||
<text @click="down">保存图片</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="qiqb-ctx-close" @click="show=false">取消</view>
|
||||
</view>
|
||||
</template>
|
||||
<!-- https://crmeb-test.shop.lihaink.cn/api/upload/image/field -->
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "share",
|
||||
|
||||
data() {
|
||||
return {
|
||||
show: false,
|
||||
img_show: true,
|
||||
mode: 'img',
|
||||
list: [],
|
||||
pext1: '',
|
||||
pext2: ''
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
uni.$on('add', function(res) {
|
||||
console.log(res.listData) // 为 B 页面传过来的值
|
||||
})
|
||||
},
|
||||
mounted() {
|
||||
// console.log(this.list,'222222')
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
//子组件接受参数
|
||||
refresh(index) {
|
||||
this.list = index;
|
||||
this.pext1 = index[index.length - 2].content
|
||||
this.pext2 = index[index.length - 1].content
|
||||
// console.log(this.list)
|
||||
},
|
||||
init() { // 通过opt传参数
|
||||
|
||||
uni.showLoading({
|
||||
title: '生成中'
|
||||
})
|
||||
let self = this
|
||||
let ctx = uni.createCanvasContext('ctx')
|
||||
// 绘制背景 宽度 高度 圆角 颜色
|
||||
self.drawBg(ctx, 330, 300, 8, '#fff')
|
||||
|
||||
// 需要用到的图片提前循环下载好,本地除外
|
||||
uni.downloadFile({
|
||||
url: 'http://banbai.oss-cn-beijing.aliyuncs.com/20230524/96e80fb572e35d4acebdce67dbd41f30.jpg',
|
||||
success: function(e) {
|
||||
let img = e.tempFilePath // 封面图
|
||||
uni.downloadFile({
|
||||
url: 'http://banbai.oss-cn-beijing.aliyuncs.com/20230524/96e80fb572e35d4acebdce67dbd41f30.jpg',
|
||||
success: function(e) {
|
||||
let photo = e.tempFilePath // 头像
|
||||
uni.downloadFile({
|
||||
url: 'http://banbai.oss-cn-beijing.aliyuncs.com/20230606/f0738e1ff432c08b369ca5e4b906a34a.png',
|
||||
success: function(e) {
|
||||
uni.hideLoading()
|
||||
let qrcode = e.tempFilePath // 二维码
|
||||
self.drawTxtOne(ctx, '农业咨询小程序', 220, 35, 100,
|
||||
'#222', 12, false)
|
||||
// 绘制圆角头像 图片地址 距离左边 距离上边 宽度 高度 圆角
|
||||
self.drawImg(ctx,
|
||||
'https://lihai001.oss-cn-chengdu.aliyuncs.com/storage/202310/20231013091310.png',
|
||||
170, 10, 40, 40, 20)
|
||||
self.drawImg(ctx,
|
||||
'https://lihai001.oss-cn-chengdu.aliyuncs.com/storage/202310/20231013091059.png',
|
||||
10, 50, 40, 40, 20)
|
||||
|
||||
self.drawImg(ctx,
|
||||
'https://lihai001.oss-cn-chengdu.aliyuncs.com/storage/202310/20231013091310.png',
|
||||
10, 118, 40, 40, 20)
|
||||
|
||||
// 绘制封面图 图片地址 距离左边 距离上边 宽度 高度 圆角
|
||||
// self.drawImg(ctx, img, 10, 120, 210, 260, 8)
|
||||
|
||||
// 绘制二维码 图片地址 距离左边 距离上边 宽度 高度 圆角
|
||||
self.drawImg(ctx,
|
||||
'https://lihai001.oss-cn-chengdu.aliyuncs.com/storage/202310/ai_qr_20231013091327.jpg',
|
||||
174, 195, 100, 100, 0)
|
||||
|
||||
// 绘制单行文字 图片地址 距离左边 距离上边 宽度 颜色 字号 加粗
|
||||
self.drawTxtOne(ctx, self.pext1, 60, 70, 100,
|
||||
'#222', 12, false)
|
||||
// self.drawTxtTwo(ctx, self.pext1, 60, 64, 80,
|
||||
// '#222', 13)
|
||||
// self.drawTxtTwo(ctx, self.pext1, 60,64,
|
||||
// 190, 20, '#222', 12)
|
||||
// 绘制单行文字 图片地址 距离左边 距离上边 宽度 颜色 字号 加粗
|
||||
// self.drawTxtOne(ctx, '邀请您一起购好物', 60, 80, 100,
|
||||
// '#666', 9, false)
|
||||
|
||||
// 绘制两行文字 图片地址 距离左边 距离上边 宽度 行高 颜色 字号
|
||||
self.drawTxtFour(ctx,
|
||||
self.pext2,
|
||||
60, 120,
|
||||
190, 20, '#222', 12)
|
||||
|
||||
// 绘制单行文字 图片地址 距离左边 距离上边 宽度 颜色 字号 加粗
|
||||
self.drawTxtOne(ctx, '下载二维码', 15, 250, 100,
|
||||
'#666', 11, false)
|
||||
|
||||
// 绘制单行文字 图片地址 距离左边 距离上边 宽度 颜色 字号 加粗
|
||||
// self.drawTxtOne(ctx, '今日特价:¥', 15, 350, 100,
|
||||
// '#ED3327', 11, false)
|
||||
|
||||
// 绘制单行文字 图片地址 距离左边 距离上边 宽度 颜色 字号 加粗
|
||||
// self.drawTxtOne(ctx, '86.00', 82, 350, 100,
|
||||
// '#ED3327', 11, true)
|
||||
|
||||
// 绘制删除文字 图片地址 距离左边 距离上边 行高 颜色 字号 加粗
|
||||
// self.drawTxtDel(ctx, '原价:20', 15, 370, 4,
|
||||
// '#818181', 10, false)
|
||||
|
||||
// 结束绘制
|
||||
ctx.draw()
|
||||
self.show = true
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
down() {
|
||||
uni.showLoading({
|
||||
title: '保存中'
|
||||
})
|
||||
uni.canvasToTempFilePath({
|
||||
canvasId: 'ctx',
|
||||
quality: 1,
|
||||
success: (res) => {
|
||||
uni.hideLoading()
|
||||
console.log(res)
|
||||
this.$emit('down', res)
|
||||
this.show = false
|
||||
// 保存到相册 自定义实现
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: res.tempFilePath,
|
||||
success: (res) => {
|
||||
console.log('保存')
|
||||
uni.showModal({
|
||||
title: '保存成功'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
// 绘制背景 宽度 高度 圆角 颜色
|
||||
drawBg(ctx, w, h, r, color) {
|
||||
let x = 0
|
||||
let y = 0
|
||||
ctx.setFillStyle(color)
|
||||
ctx.save()
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(x + r, y)
|
||||
ctx.arcTo(x + w, y, x + w, y + h, r)
|
||||
ctx.arcTo(x + w, y + h, x, y + h, r)
|
||||
ctx.arcTo(x, y + h, x, y, r)
|
||||
ctx.arcTo(x, y, x + w, y, r)
|
||||
ctx.closePath()
|
||||
ctx.fill()
|
||||
},
|
||||
// 绘制图片 图片地址 距离左边 距离上边 宽度 高度 圆角
|
||||
drawImg(ctx, img, x, y, w, h, r) {
|
||||
let self = this
|
||||
ctx.save()
|
||||
ctx.beginPath()
|
||||
ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5)
|
||||
ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2)
|
||||
ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5)
|
||||
ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI)
|
||||
ctx.clip()
|
||||
ctx.drawImage(img, x, y, w, h)
|
||||
ctx.restore()
|
||||
},
|
||||
// 绘制单行文字 图片地址 距离左边 距离上边 宽度 颜色 字号 加粗
|
||||
drawTxtOne(ctx, text, x, y, maxWidth, color, size, bold) {
|
||||
ctx.save()
|
||||
ctx.beginPath()
|
||||
let chr = text.split("")
|
||||
let temp = ""
|
||||
let row = []
|
||||
ctx.setFontSize(size)
|
||||
ctx.setFillStyle(color)
|
||||
for (let a = 0; a < chr.length; a++) {
|
||||
if (ctx.measureText(temp).width < maxWidth) {
|
||||
temp += chr[a]
|
||||
}
|
||||
}
|
||||
row.push(temp)
|
||||
if (ctx.measureText(temp).width > maxWidth) row[0] = row[0] + '...'
|
||||
|
||||
for (var b = 0; b < row.length; b++) {
|
||||
ctx.fillStyle = color
|
||||
if (bold) {
|
||||
ctx.font = 'normal bold ' + size + 'px sans-serif'
|
||||
} else {
|
||||
ctx.font = 'normal ' + size + 'px sans-serif'
|
||||
}
|
||||
ctx.fillText(row[b], x, y)
|
||||
}
|
||||
},
|
||||
// 绘制两行文字 图片地址 距离左边 距离上边 宽度 行高 颜色 字号
|
||||
drawTxtTwo(ctx, text, x, y, maxWidth, lineHeight, color, size) {
|
||||
ctx.save()
|
||||
ctx.beginPath()
|
||||
let chr = text.split("")
|
||||
let temp = ""
|
||||
let row = []
|
||||
ctx.setFontSize(size)
|
||||
ctx.setFillStyle(color)
|
||||
for (let a = 0; a < chr.length; a++) {
|
||||
if (ctx.measureText(temp).width < maxWidth) {
|
||||
temp += chr[a];
|
||||
} else {
|
||||
a--
|
||||
row.push(temp)
|
||||
temp = ""
|
||||
}
|
||||
}
|
||||
row.push(temp)
|
||||
if (row.length > 2) {
|
||||
let rowCut = row.slice(0, 2)
|
||||
let rowPart = rowCut[1]
|
||||
let test = ""
|
||||
let empty = []
|
||||
for (var a = 0; a < rowPart.length; a++) {
|
||||
if (ctx.measureText(test).width < maxWidth) {
|
||||
test += rowPart[a]
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
empty.push(test)
|
||||
var group = empty[0] + "..."
|
||||
rowCut.splice(1, 1, group)
|
||||
row = rowCut
|
||||
}
|
||||
for (var b = 0; b < row.length; b++) {
|
||||
ctx.fillStyle = color
|
||||
ctx.font = 'normal ' + size + 'px sans-serif'
|
||||
ctx.fillText(row[b], x, y + b * lineHeight, 300)
|
||||
}
|
||||
},
|
||||
drawTxtFour(ctx, text, x, y, maxWidth, lineHeight, color, size) {
|
||||
ctx.save()
|
||||
ctx.beginPath()
|
||||
let chr = text.split("")
|
||||
let temp = ""
|
||||
let row = []
|
||||
ctx.setFontSize(size)
|
||||
ctx.setFillStyle(color)
|
||||
for (let a = 0; a < chr.length; a++) {
|
||||
if (ctx.measureText(temp).width < maxWidth) {
|
||||
temp += chr[a];
|
||||
} else {
|
||||
a--
|
||||
row.push(temp)
|
||||
temp = ""
|
||||
}
|
||||
}
|
||||
row.push(temp)
|
||||
if (row.length > 4) {
|
||||
let rowCut = row.slice(0, 4)
|
||||
let rowPart = rowCut[1]
|
||||
let test = ""
|
||||
let empty = []
|
||||
for (var a = 0; a < rowPart.length; a++) {
|
||||
if (ctx.measureText(test).width < maxWidth) {
|
||||
test += rowPart[a]
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
empty.push(test)
|
||||
var group = empty[0] + "..."
|
||||
rowCut.splice(1, 1, group)
|
||||
row = rowCut
|
||||
}
|
||||
for (var b = 0; b < row.length; b++) {
|
||||
ctx.fillStyle = color
|
||||
ctx.font = 'normal ' + size + 'px sans-serif'
|
||||
ctx.fillText(row[b], x, y + b * lineHeight, 300)
|
||||
}
|
||||
},
|
||||
// 绘制删除线文字 图片地址 距离左边 距离上边 行高 颜色 字号 加粗
|
||||
drawTxtDel(ctx, txt, x, y, h, color, size) {
|
||||
ctx.fillStyle = color
|
||||
ctx.font = 'normal ' + size + 'px sans-serif'
|
||||
ctx.fillText(txt, x, y)
|
||||
|
||||
ctx.beginPath()
|
||||
let width = ctx.measureText(txt).width;
|
||||
ctx.rect(x, y - h, width, 1)
|
||||
ctx.fillStyle = color
|
||||
ctx.fill()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.qiqb-ctx {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: -1;
|
||||
display: flex;
|
||||
background: rgba(0, 0, 0, .6);
|
||||
opacity: 0;
|
||||
transition: all .3s;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
justify-content: flex-end
|
||||
}
|
||||
|
||||
.qiqb-ctx.on {
|
||||
z-index: 2000;
|
||||
opacity: 1
|
||||
}
|
||||
|
||||
.qiqb-ctx-box {
|
||||
position: relative;
|
||||
display: flex;
|
||||
padding: 30upx 0 40upx;
|
||||
width: 750upx;
|
||||
justify-content: center
|
||||
}
|
||||
|
||||
.qiqb-ctx-box text {
|
||||
position: absolute;
|
||||
top: -40upx;
|
||||
right: 145upx;
|
||||
display: inline-flex;
|
||||
width: 47upx;
|
||||
height: 47upx;
|
||||
background: url('img/close.png');
|
||||
background-size: 100% 100%
|
||||
}
|
||||
|
||||
.qiqb-ctx-btns {
|
||||
display: flex;
|
||||
width: 750upx;
|
||||
height: 330upx;
|
||||
border-radius: 20upx 20upx 0 0;
|
||||
background: #fff;
|
||||
flex-direction: row;
|
||||
flex-direction: column;
|
||||
align-items: center
|
||||
}
|
||||
|
||||
.qiqb-ctx-btns view:nth-child(1) {
|
||||
display: flex;
|
||||
padding-top: 10upx;
|
||||
height: 80upx;
|
||||
font-weight: 700;
|
||||
font-size: 30upx;
|
||||
align-items: center
|
||||
}
|
||||
|
||||
.qiqb-ctx-btns view:nth-child(2) {
|
||||
height: 80upx;
|
||||
color: #666;
|
||||
font-size: 24upx
|
||||
}
|
||||
|
||||
.qiqb-ctx-btns view:nth-child(3) {
|
||||
display: flex;
|
||||
padding-bottom: 30upx;
|
||||
font-size: 26upx;
|
||||
flex-direction: row;
|
||||
align-items: center
|
||||
}
|
||||
|
||||
.qiqb-ctx-btns view:nth-child(3) text {
|
||||
display: flex;
|
||||
width: 250upx;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center
|
||||
}
|
||||
|
||||
.qiqb-ctx-btns view:nth-child(3) text:nth-child(1)::before {
|
||||
display: inline-flex;
|
||||
margin-bottom: 20upx;
|
||||
width: 86upx;
|
||||
height: 86upx;
|
||||
background: url('img/3.png');
|
||||
background-size: 100% 100%;
|
||||
content: ''
|
||||
}
|
||||
|
||||
.qiqb-ctx-btns view:nth-child(3) text:nth-child(2)::before {
|
||||
display: inline-flex;
|
||||
margin-bottom: 20upx;
|
||||
width: 86upx;
|
||||
height: 86upx;
|
||||
background: url('img/1.png');
|
||||
background-size: 100% 100%;
|
||||
content: ''
|
||||
}
|
||||
|
||||
.qiqb-ctx-btns view:nth-child(3) text:nth-child(3)::before {
|
||||
display: inline-flex;
|
||||
margin-bottom: 20upx;
|
||||
width: 86upx;
|
||||
height: 86upx;
|
||||
background: url('img/2.png');
|
||||
background-size: 100% 100%;
|
||||
content: ''
|
||||
}
|
||||
|
||||
.qiqb-ctx-close {
|
||||
display: flex;
|
||||
padding-bottom: 50upx;
|
||||
width: 100%;
|
||||
height: 150upx;
|
||||
background: #fff;
|
||||
font-size: 32upx;
|
||||
align-items: center;
|
||||
justify-content: center
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,44 @@
|
|||
|
||||
let httpApi
|
||||
|
||||
// 在打包之前请检查当前环境是否正确
|
||||
const env = 'dev'; // 开发
|
||||
// const env = 'prod'; // 生产
|
||||
// const env = 'prew'; // 预上线
|
||||
|
||||
switch (env) {
|
||||
case 'prod':
|
||||
httpApi = 'https://worker-task.lihaink.cn' // 生产
|
||||
|
||||
break;
|
||||
case 'prew':
|
||||
httpApi ='https://preview-worker-task.lihaink.cn' //预发布环境
|
||||
|
||||
break;
|
||||
default:
|
||||
httpApi = "https://ceshi-worker-task.lihaink.cn" // 测试
|
||||
httpApione = "https://chat.lihaink.cn" // 测试
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
module.exports = {
|
||||
// 请求域名 格式: https://您的域名
|
||||
|
||||
HTTP_REQUEST_URL: httpApi,
|
||||
HTTP_REQUEST_URL_ONE: httpApione,
|
||||
HEADER: {
|
||||
'content-type': 'application/json',
|
||||
//#ifdef MP
|
||||
'Form-type': 'routine',
|
||||
//#endif
|
||||
//#ifdef APP-PLUS
|
||||
'Form-type': 'app',
|
||||
//#endif
|
||||
},
|
||||
// 回话密钥名称 请勿修改此配置
|
||||
TOKENNAME: 'X-Token',
|
||||
// 缓存时间 0 永久
|
||||
EXPIRE: 0,
|
||||
};
|
|
@ -0,0 +1,79 @@
|
|||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
import {
|
||||
HTTP_REQUEST_URL,
|
||||
HEADER,
|
||||
TOKENNAME
|
||||
} from '@/config/app';
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 发送请求
|
||||
*/
|
||||
function baseRequest(url, method, data, {
|
||||
noAuth = false,
|
||||
noVerify = false
|
||||
}) {
|
||||
let Url = HTTP_REQUEST_URL,
|
||||
header = HEADER;
|
||||
|
||||
|
||||
|
||||
// if (store.state.app.token) header[TOKENNAME] = 'Bearer ' + store.state.app.token;
|
||||
|
||||
return new Promise((reslove, reject) => {
|
||||
uni.request({
|
||||
url: Url + '/api/' + url,
|
||||
method: method || 'GET',
|
||||
header: header,
|
||||
data: data || {},
|
||||
success: (res) => {
|
||||
// #ifdef APP-PLUS
|
||||
|
||||
|
||||
// #endif
|
||||
if (noVerify)
|
||||
reslove(res.data, res);
|
||||
else if (res.data.status == 200)
|
||||
reslove(res.data, res);
|
||||
else if ([410000, 410001, 410002, 40000].indexOf(res.data.status) !== -1) {
|
||||
|
||||
reject(res.data);
|
||||
}else if (res.data.code == 0||1) {
|
||||
|
||||
reslove(res.data, res);
|
||||
} else if (res.data.status == 501) {
|
||||
uni.reLaunch({
|
||||
url: '/pages/error/index'
|
||||
})
|
||||
reject(res.data);
|
||||
} else
|
||||
reject(res.data.message || '系统错误');
|
||||
},
|
||||
fail: (message) => {
|
||||
console.log(message,'3333333333');
|
||||
reject('请求失败');
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
const request = {};
|
||||
|
||||
['options', 'get', 'post', 'put', 'head', 'delete', 'trace', 'connect'].forEach((method) => {
|
||||
request[method] = (api, data, opt) => baseRequest(api, method, data, opt || {})
|
||||
});
|
||||
|
||||
|
||||
|
||||
export default request;
|
|
@ -0,0 +1,80 @@
|
|||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
import {
|
||||
HTTP_REQUEST_URL_ONE,
|
||||
HEADER,
|
||||
TOKENNAME
|
||||
} from '@/config/app';
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 发送请求
|
||||
*/
|
||||
function baseRequest(url, method, data, {
|
||||
noAuth = false,
|
||||
noVerify = false
|
||||
}) {
|
||||
let Url = HTTP_REQUEST_URL_ONE,
|
||||
header = HEADER;
|
||||
|
||||
|
||||
|
||||
// if (store.state.app.token) header[TOKENNAME] = 'Bearer ' + store.state.app.token;
|
||||
|
||||
return new Promise((reslove, reject) => {
|
||||
uni.request({
|
||||
url: Url + '/' + url,
|
||||
method: method || 'GET',
|
||||
header: header,
|
||||
data: data || {},
|
||||
success: (res) => {
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
console.log('app', Url + '/api/' + url, res.data);
|
||||
|
||||
// #endif
|
||||
if (noVerify)
|
||||
reslove(res.data, res);
|
||||
else if (res.data.status == 200)
|
||||
reslove(res.data, res);
|
||||
else if ([410000, 410001, 410002, 40000].indexOf(res.data.status) !== -1) {
|
||||
|
||||
reject(res.data);
|
||||
}else if (res.data.code == 0||res.data.code ==1) {
|
||||
|
||||
reslove(res.data, res);
|
||||
} else if (res.data.status == 501) {
|
||||
uni.reLaunch({
|
||||
url: '/pages/error/index'
|
||||
})
|
||||
reject(res.data);
|
||||
} else
|
||||
reject(res.data.message || '系统错误');
|
||||
},
|
||||
fail: (message) => {
|
||||
console.log(message,'3333333333');
|
||||
reject('请求失败');
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
const request = {};
|
||||
|
||||
['options', 'get', 'post', 'put', 'head', 'delete', 'trace', 'connect'].forEach((method) => {
|
||||
request[method] = (api, data, opt) => baseRequest(api, method, data, opt || {})
|
||||
});
|
||||
|
||||
|
||||
|
||||
export default request;
|
|
@ -0,0 +1,196 @@
|
|||
function getLocalFilePath(path) {
|
||||
if (path.indexOf('_www') === 0 || path.indexOf('_doc') === 0 || path.indexOf('_documents') === 0 || path.indexOf('_downloads') === 0) {
|
||||
return path
|
||||
}
|
||||
if (path.indexOf('file://') === 0) {
|
||||
return path
|
||||
}
|
||||
if (path.indexOf('/storage/emulated/0/') === 0) {
|
||||
return path
|
||||
}
|
||||
if (path.indexOf('/') === 0) {
|
||||
var localFilePath = plus.io.convertAbsoluteFileSystem(path)
|
||||
if (localFilePath !== path) {
|
||||
return localFilePath
|
||||
} else {
|
||||
path = path.substr(1)
|
||||
}
|
||||
}
|
||||
return '_www/' + path
|
||||
}
|
||||
|
||||
function dataUrlToBase64(str) {
|
||||
var array = str.split(',')
|
||||
return array[array.length - 1]
|
||||
}
|
||||
|
||||
var index = 0
|
||||
function getNewFileId() {
|
||||
return Date.now() + String(index++)
|
||||
}
|
||||
|
||||
function biggerThan(v1, v2) {
|
||||
var v1Array = v1.split('.')
|
||||
var v2Array = v2.split('.')
|
||||
var update = false
|
||||
for (var index = 0; index < v2Array.length; index++) {
|
||||
var diff = v1Array[index] - v2Array[index]
|
||||
if (diff !== 0) {
|
||||
update = diff > 0
|
||||
break
|
||||
}
|
||||
}
|
||||
return update
|
||||
}
|
||||
|
||||
export function pathToBase64(path) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
if (typeof window === 'object' && 'document' in window) {
|
||||
if (typeof FileReader === 'function') {
|
||||
var xhr = new XMLHttpRequest()
|
||||
xhr.open('GET', path, true)
|
||||
xhr.responseType = 'blob'
|
||||
xhr.onload = function() {
|
||||
if (this.status === 200) {
|
||||
let fileReader = new FileReader()
|
||||
fileReader.onload = function(e) {
|
||||
resolve(e.target.result)
|
||||
}
|
||||
fileReader.onerror = reject
|
||||
fileReader.readAsDataURL(this.response)
|
||||
}
|
||||
}
|
||||
xhr.onerror = reject
|
||||
xhr.send()
|
||||
return
|
||||
}
|
||||
var canvas = document.createElement('canvas')
|
||||
var c2x = canvas.getContext('2d')
|
||||
var img = new Image
|
||||
img.onload = function() {
|
||||
canvas.width = img.width
|
||||
canvas.height = img.height
|
||||
c2x.drawImage(img, 0, 0)
|
||||
resolve(canvas.toDataURL())
|
||||
canvas.height = canvas.width = 0
|
||||
}
|
||||
img.onerror = reject
|
||||
img.src = path
|
||||
return
|
||||
}
|
||||
if (typeof plus === 'object') {
|
||||
plus.io.resolveLocalFileSystemURL(getLocalFilePath(path), function(entry) {
|
||||
entry.file(function(file) {
|
||||
var fileReader = new plus.io.FileReader()
|
||||
fileReader.onload = function(data) {
|
||||
resolve(data.target.result)
|
||||
}
|
||||
fileReader.onerror = function(error) {
|
||||
reject(error)
|
||||
}
|
||||
fileReader.readAsDataURL(file)
|
||||
}, function(error) {
|
||||
reject(error)
|
||||
})
|
||||
}, function(error) {
|
||||
reject(error)
|
||||
})
|
||||
return
|
||||
}
|
||||
if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
|
||||
wx.getFileSystemManager().readFile({
|
||||
filePath: path,
|
||||
encoding: 'base64',
|
||||
success: function(res) {
|
||||
resolve('data:image/png;base64,' + res.data)
|
||||
},
|
||||
fail: function(error) {
|
||||
reject(error)
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
reject(new Error('not support'))
|
||||
})
|
||||
}
|
||||
|
||||
export function base64ToPath(base64) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
if (typeof window === 'object' && 'document' in window) {
|
||||
base64 = base64.split(',')
|
||||
var type = base64[0].match(/:(.*?);/)[1]
|
||||
var str = atob(base64[1])
|
||||
var n = str.length
|
||||
var array = new Uint8Array(n)
|
||||
while (n--) {
|
||||
array[n] = str.charCodeAt(n)
|
||||
}
|
||||
return resolve((window.URL || window.webkitURL).createObjectURL(new Blob([array], { type: type })))
|
||||
}
|
||||
var extName = base64.split(',')[0].match(/data\:\S+\/(\S+);/)
|
||||
if (extName) {
|
||||
extName = extName[1]
|
||||
} else {
|
||||
reject(new Error('base64 error'))
|
||||
}
|
||||
var fileName = getNewFileId() + '.' + extName
|
||||
if (typeof plus === 'object') {
|
||||
var basePath = '_doc'
|
||||
var dirPath = 'uniapp_temp'
|
||||
var filePath = basePath + '/' + dirPath + '/' + fileName
|
||||
if (!biggerThan(plus.os.name === 'Android' ? '1.9.9.80627' : '1.9.9.80472', plus.runtime.innerVersion)) {
|
||||
plus.io.resolveLocalFileSystemURL(basePath, function(entry) {
|
||||
entry.getDirectory(dirPath, {
|
||||
create: true,
|
||||
exclusive: false,
|
||||
}, function(entry) {
|
||||
entry.getFile(fileName, {
|
||||
create: true,
|
||||
exclusive: false,
|
||||
}, function(entry) {
|
||||
entry.createWriter(function(writer) {
|
||||
writer.onwrite = function() {
|
||||
resolve(filePath)
|
||||
}
|
||||
writer.onerror = reject
|
||||
writer.seek(0)
|
||||
writer.writeAsBinary(dataUrlToBase64(base64))
|
||||
}, reject)
|
||||
}, reject)
|
||||
}, reject)
|
||||
}, reject)
|
||||
return
|
||||
}
|
||||
var bitmap = new plus.nativeObj.Bitmap(fileName)
|
||||
bitmap.loadBase64Data(base64, function() {
|
||||
bitmap.save(filePath, {}, function() {
|
||||
bitmap.clear()
|
||||
resolve(filePath)
|
||||
}, function(error) {
|
||||
bitmap.clear()
|
||||
reject(error)
|
||||
})
|
||||
}, function(error) {
|
||||
bitmap.clear()
|
||||
reject(error)
|
||||
})
|
||||
return
|
||||
}
|
||||
if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
|
||||
var filePath = wx.env.USER_DATA_PATH + '/' + fileName
|
||||
wx.getFileSystemManager().writeFile({
|
||||
filePath: filePath,
|
||||
data: dataUrlToBase64(base64),
|
||||
encoding: 'base64',
|
||||
success: function() {
|
||||
resolve(filePath)
|
||||
},
|
||||
fail: function(error) {
|
||||
reject(error)
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
reject(new Error('not support'))
|
||||
})
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"id": "mmmm-image-tools",
|
||||
"name": "image-tools",
|
||||
"version": "1.4.0",
|
||||
"description": "图像转换工具,可用于图像和base64的转换",
|
||||
"keywords": [
|
||||
"base64",
|
||||
"保存",
|
||||
"图像"
|
||||
]
|
||||
}
|
|
@ -17,26 +17,34 @@
|
|||
"delay" : 0
|
||||
},
|
||||
/* 模块配置 */
|
||||
"modules" : {},
|
||||
"modules" : {
|
||||
"Record" : {},
|
||||
"Speech" : {},
|
||||
"Camera" : {}
|
||||
},
|
||||
/* 应用发布信息 */
|
||||
"distribute" : {
|
||||
/* android打包配置 */
|
||||
"android" : {
|
||||
"permissions" : [
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
||||
"<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.GET_ACCOUNTS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
|
||||
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
||||
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.INTERNET\"/>",
|
||||
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\"/>",
|
||||
"<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_EXTERNAL_STORAGE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
|
||||
],
|
||||
"abiFilters" : [ "armeabi-v7a", "arm64-v8a", "x86" ]
|
||||
|
@ -47,7 +55,25 @@
|
|||
},
|
||||
/* SDK配置 */
|
||||
"sdkConfigs" : {
|
||||
"ad" : {}
|
||||
"ad" : {},
|
||||
"speech" : {},
|
||||
"share" : {}
|
||||
}
|
||||
},
|
||||
"nativePlugins" : {
|
||||
"YL-SpeechRecognition" : {
|
||||
"__plugin_info__" : {
|
||||
"name" : "YL-SpeechRecognition-语音合成,语音听写,基于科大讯飞,双端 - [试用版,仅用于自定义调试基座]",
|
||||
"description" : "语音合成,语音听写,基于科大讯飞,双端(QQ:453503875,微信同)",
|
||||
"platforms" : "Android,iOS",
|
||||
"url" : "https://ext.dcloud.net.cn/plugin?id=9512",
|
||||
"android_package_name" : "",
|
||||
"ios_bundle_id" : "",
|
||||
"isCloud" : true,
|
||||
"bought" : 0,
|
||||
"pid" : "9512",
|
||||
"parameters" : {}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -55,7 +81,7 @@
|
|||
"quickapp" : {},
|
||||
/* 小程序特有相关 */
|
||||
"mp-weixin" : {
|
||||
"appid" : "",
|
||||
"appid" : "wx3267f87bc81f2890",
|
||||
"setting" : {
|
||||
"urlCheck" : false
|
||||
},
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
{
|
||||
"path": "pages/index/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "农业咨询",
|
||||
"navigationBarTitleText": "教育咨询",
|
||||
"navigationStyle": "custom",
|
||||
"bounce": "none"
|
||||
// "softinputMode": "adjustResize"
|
||||
}
|
||||
|
|
After Width: | Height: | Size: 7.9 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 8.6 KiB |
After Width: | Height: | Size: 9.9 KiB |
After Width: | Height: | Size: 7.0 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 756 B |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 5.4 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 446 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 6.9 KiB |
After Width: | Height: | Size: 9.1 KiB |
After Width: | Height: | Size: 5.3 KiB |
|
@ -0,0 +1,6 @@
|
|||
!function(){"use strict";
|
||||
/*!
|
||||
* vtils v2.59.0
|
||||
* (c) Jay Fong <fjc0kb@gmail.com> (https://github.com/fjc0k)
|
||||
* Released under the MIT License.
|
||||
*/var e,t,r,n=function(){this.listeners=Object.create(null)};function s(e){return new Promise((t,r)=>{const n=new FileReader;n.onload=()=>{t(function(e,t,r){let n="";const s=new Uint8Array(e),o=s.byteLength;for(let e=0;e<o;e++)n+=String.fromCharCode(s[e]);return{__APP_AGENT_BASE64_FILE__:!0,base64:btoa(n),name:t,type:r}}(n.result,e.name,e.type))},n.onerror=e=>r(e),n.readAsArrayBuffer(e)})}function o(e,t,r){return new Promise((n,s)=>{const o=new FileReader;o.onload=()=>{n(o.result)},o.onerror=e=>s(e);const a=new Blob([e]);"dataUrl"===t&&o.readAsDataURL(a),"text"===t&&o.readAsText(a,r)})}n.prototype.on=function(e,t){var r=this;this.listeners[e]||(this.listeners[e]=[]);var n=this.listeners[e];return-1===n.indexOf(t)&&n.push(t),function(){return r.off(e,t)}},n.prototype.once=function(e,t){var r=this.on(e,(function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];r(),t.apply(void 0,e)}));return r},n.prototype.off=function(e,t){if(t){var r=this.listeners[e],n=r.indexOf(t);n>-1&&r.splice(n,1)}else delete this.listeners[e]},n.prototype.emit=function(e){for(var t=[],r=arguments.length-1;r-- >0;)t[r]=arguments[r+1];return(this.listeners[e]||[]).map((function(e){return e.apply(void 0,t)}))},function(e){e.open="open",e.closed="closed",e.leftOpenRightClosed="leftOpenRightClosed",e.leftClosedRightOpen="leftClosedRightOpen"}(e||(e={})),function(e){e.css="css",e.js="js",e.img="img",e.video="video",e.audio="audio"}(t||(t={})),function(e){e.desc="desc",e.asc="asc"}(r||(r={}));let a=0;const i=new n;document.addEventListener("__APP_AGENT_HTTP_RESPONSE_LISTENER__",e=>{const t=JSON.parse(JSON.stringify(e.detail||{}));t.response.arrayBuffer=e.detail.response.arrayBuffer,i.emit("response",t)}),document.addEventListener("__APP_AGENT_HTTP_RESPONSE_START_LISTENER__",e=>{const t=JSON.parse(JSON.stringify(e.detail||{}));i.emit("onstart",t)}),document.addEventListener("__APP_AGENT_HTTP_RESPONSE_DATA_LISTENER__",e=>{const t=JSON.parse(JSON.stringify(e.detail||{}));i.emit("ondata",t)});window.foxAgentCrossRequestVersion=function(){return{version:"0.0.1"}},window.foxAgentCrossRequest=async function(e){const t=e.headers["Content-Type"]||e.headers["content-type"]||e.headers["Content-type"]||"text/plain",r=null==e.data?void 0:(e=>"application/x-www-form-urlencoded"===e?"form":e.startsWith("multipart/form-data")?"file":"application/json"===e?"json":"application/x-msgpack"===e?"arraybuffer":"raw")(t);let n;n="arraybuffer"===r?{__ARRAY_BUFFER_KEY__:!0,data:Array.from(e.data)}:"file"!==r?e.data:{__APP_AGENT_FILE_BODY__:!0,...e.data||{},...Object.fromEntries(await Promise.all(Object.entries(e.files||{}).map(async([e,t])=>Array.isArray(t)?[e,await Promise.all(t.map(s))]:[e,t&&await s(t)])))};const d=`${location.href}____${a++}`,u=i.on("onstart",async({id:t,request:r,response:n})=>{var s;t===d&&(null===(s=e.onstart)||void 0===s||s.call(e,{request:r,response:n}),u())}),l=i.on("ondata",async({id:t,data:r})=>{var n;t===d&&(null===(n=e.ondata)||void 0===n||n.call(e,r))}),c=i.on("response",async({id:t,response:r})=>{if(t===d){if(r.error)return e.error("",void 0,new Error(r.error.message)),c(),u(),void l();const t={header:r.headers,status:r.status,statusText:r.statusText,body:r.arrayBuffer,getBodyAsDataUrl:async()=>o(r.arrayBuffer,"dataUrl"),async getBodyAsText(){var e;return o(r.arrayBuffer,"text",(null===(e=(r.headers["content-type"]||"").match(/charset=(.*)\b/i))||void 0===e?void 0:e[1])||"utf-8")}},n={req:e,res:t,runTime:(new Date).getTime()};r.ok?e.success(t.body,t.header,n):e.error(t.statusText,t.header,n),c(),u(),l()}}),{timeout:_=3e5}=e;return document.dispatchEvent(new CustomEvent("__APP_AGENT_HTTP_REQUEST_LISTENER__",{detail:{id:d,options:{url:e.url,method:e.method,headers:{...e.headers,"Content-Type":t},requestBodyType:r,requestBody:n},runtimeOptions:{requestId:d,timeout:_}}})),{version:"0.0.1",requestId:d,abort:()=>{document.dispatchEvent(new CustomEvent("__APP_AGENT_HTTP_REQUEST_ABORT_LISTENER__",{detail:{id:d,runtimeOptions:{requestId:d,timeout:_}}}))}}}}();
|
|
@ -0,0 +1,7 @@
|
|||
!function(){"use strict";function e(e){if(!e||"object"!=typeof e)return!1;var t=Object.getPrototypeOf(e);if(null===t)return!0;var o=t.constructor;return"function"==typeof o&&o instanceof o}var t,o,n;!function(e){e.open="open",e.closed="closed",e.leftOpenRightClosed="leftOpenRightClosed",e.leftClosedRightOpen="leftClosedRightOpen"}(t||(t={})),function(e){e.css="css",e.js="js",e.img="img",e.video="video",e.audio="audio"}(o||(o={})),function(e){e.desc="desc",e.asc="asc"}(n||(n={}));const r={},s=t=>e(t)?!0===t.__APP_AGENT_BASE64_FILE__?function(e){const t=atob(e.base64);let o=t.length;const n=new Uint8Array(o);for(;o--;)n[o]=t.charCodeAt(o);return new File([n],e.name,{type:e.type})}(t):JSON.stringify(t):t;chrome.runtime.onMessage.addListener((t,o,n)=>{
|
||||
/*!
|
||||
* vtils v2.59.0
|
||||
* (c) Jay Fong <fjc0kb@gmail.com> (https://github.com/fjc0k)
|
||||
* Released under the MIT License.
|
||||
*/
|
||||
var a;return(a=async()=>{var a,i,c,d;switch(t.type){case"__APP_AGENT_BACKGROUND_HTTP_REQUEST__":const _=null===(a=o.tab)||void 0===a?void 0:a.id;if(e(t.options.body)&&!0===t.options.body.__APP_AGENT_FILE_BODY__){const{__APP_AGENT_FILE_BODY__:e,...o}=t.options.body,n=new FormData;for(const[e,t]of Object.entries(o))Array.isArray(t)?t.forEach(t=>n.append(e,s(t))):n.append(e,s(t));t.options.body=n;const r=t.options.headers;r&&delete r["Content-Type"]}if(e(t.options.body)&&!0===t.options.body.__ARRAY_BUFFER_KEY__){const{data:e}=t.options.body;t.options.body=new Uint8Array(e).buffer,t.options.headers}const l=new URL(t.options.url).origin;t.options.headers&&(t.options.headers["Referrer-Policy"]="no-referrer, strict-origin-when-cross-origin",t.options.headers.Referer=l,t.options.headers.Origin=l,t.options.mode="cors",delete t.options.headers.cookie);const p=new AbortController,{requestId:u=0,timeout:f=3e4}=null!==(i=t.runtimeOptions)&&void 0!==i?i:{},y=setTimeout(()=>p.abort(),f);r[u]={abortId:y,abortController:p};const h=await fetch(t.options.url,{...t.options,redirect:"follow",signal:p.signal});clearTimeout(y);const A=new Headers(h.headers),b=A.get("x-app-agent-http-headers");if(null!=b){A.delete("x-app-agent-http-headers");for(const[e,t]of Object.entries(JSON.parse(b)))A.set(e,t)}const T=Object.fromEntries(A.entries()),E="file",g=T["content-type"]||"application/octet-stream";let P=new Uint8Array;h.body?(_&&chrome.tabs.sendMessage(_,{type:"__APP_AGENT_HTTP_RESPONSE_START_LISTENER__",id:u,request:{url:t.options.url},response:{headers:T,status:h.status,statusText:h.statusText,url:h.url,ok:h.ok,redirected:h.redirected,type:h.type}}),await async function(e,t,o){const n=(e,t)=>{const o=new Uint8Array(e.length+t.length);return o.set(e,0),o.set(t,e.length),o};let r=new Uint8Array;const s=e.getReader();for(;;){const{done:e,value:a}=await s.read();if(e){o(r);break}r=n(r,a),t(a)}}(h.body,e=>{_&&chrome.tabs.sendMessage(_,{type:"__APP_AGENT_HTTP_RESPONSE_DATA_LISTENER__",id:u,data:[...e]})},e=>{P=e})):P=await h.arrayBuffer(),delete r[u];const m=function(e,t,o){let n="";const r=new Uint8Array(e),s=r.byteLength;for(let e=0;e<s;e++)n+=String.fromCharCode(r[e]);return{__APP_AGENT_BASE64_FILE__:!0,base64:btoa(n),name:t,type:o}}(P,E,g),{ok:R,status:O,statusText:w}=h;n({error:null,data:{ok:R,status:O,statusText:w,headers:T,base64File:m,arrayBuffer:new Uint8Array}});break;case"__APP_AGENT_HTTP_REQUEST_ABORT_LISTENER__":const{requestId:N=0}=null!==(c=t.runtimeOptions)&&void 0!==c?c:{},{abortId:S,abortController:v}=null!==(d=r[N])&&void 0!==d?d:{};S&&clearTimeout(S),v&&v.abort(),delete r[N]}},a()).catch(e=>{n({error:{message:String(e)}})}),!0}),chrome.action.onClicked.addListener((function(e){chrome.tabs.create({url:"https://app.apifox.com"})}))}();
|
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 7.9 KiB |
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"name": "Apifox Browser Extension",
|
||||
"description": "API 文档、API 调试、API Mock、API 自动化测试",
|
||||
"version": "1.0.6",
|
||||
"manifest_version": 3,
|
||||
"icons": {
|
||||
"96": "logo-96.png",
|
||||
"128": "logo-128.png"
|
||||
},
|
||||
"permissions": [],
|
||||
"host_permissions": [
|
||||
"*://*/"
|
||||
],
|
||||
"background": {
|
||||
"service_worker": "background.js"
|
||||
},
|
||||
"action": {
|
||||
"default_title": "Apifox",
|
||||
"default_icon": "logo-96.png"
|
||||
},
|
||||
"web_accessible_resources": [
|
||||
{
|
||||
"matches": [
|
||||
"*://*/*"
|
||||
],
|
||||
"resources": [
|
||||
"adapter.js"
|
||||
]
|
||||
}
|
||||
],
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": [
|
||||
"*://*/*"
|
||||
],
|
||||
"js": [
|
||||
"runtime.js"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
!function(){"use strict";function e(e,t,n){return new Promise((r,a)=>{const o=new FileReader;o.onload=()=>{r(o.result)},o.onerror=e=>a(e);const s=function(e){const t=atob(e.base64);let n=t.length;const r=new Uint8Array(n);for(;n--;)r[n]=t.charCodeAt(n);return new File([r],e.name,{type:e.type})}(e);"dataUrl"===t?o.readAsDataURL(s):"arrayBuffer"===t?o.readAsArrayBuffer(s):o.readAsText(s,n)})}!function(e){const t=document.createElement("script");t.src=chrome.runtime.getURL(e),t.onload=()=>t.remove(),(document.head||document.documentElement).appendChild(t)}("adapter.js"),chrome.runtime.onMessage.addListener(e=>{e&&"object"==typeof e&&"string"==typeof e.type&&["__APP_AGENT_HTTP_RESPONSE_START_LISTENER__","__APP_AGENT_HTTP_RESPONSE_DATA_LISTENER__"].includes(e.type)&&document.dispatchEvent(new CustomEvent(e.type,{detail:e}))}),document.addEventListener("__APP_AGENT_HTTP_REQUEST_LISTENER__",async t=>{var n;const r=t.detail||{};let a;try{a=await async function(t,n){const r={url:t.url,method:t.method.toUpperCase(),headers:t.headers||{},body:t.requestBody};return await new Promise((t,a)=>{chrome.runtime.sendMessage({type:"__APP_AGENT_BACKGROUND_HTTP_REQUEST__",options:r,runtimeOptions:n},(async function(n){null==n?a(chrome.runtime.lastError):null!=n.error?a(n.error):(n.data.arrayBuffer=await e(n.data.base64File,"arrayBuffer",n.data.base64File.type),t(n.data))}))})}(r.options,r.runtimeOptions)}catch(e){a={error:{message:String(null!==(n=e.message)&&void 0!==n?n:e)}}}document.dispatchEvent(new CustomEvent("__APP_AGENT_HTTP_RESPONSE_LISTENER__",{detail:{id:r.id,response:a}}))}),document.addEventListener("__APP_AGENT_HTTP_REQUEST_ABORT_LISTENER__",async e=>{const{runtimeOptions:t}=JSON.parse(JSON.stringify(e.detail||{}));chrome.runtime.sendMessage({type:"__APP_AGENT_HTTP_REQUEST_ABORT_LISTENER__",runtimeOptions:t})})}();
|
|
@ -0,0 +1,47 @@
|
|||
# 讯飞星火大模型 小程序文档
|
||||
|
||||
### 农业咨询
|
||||
|
||||
参数:nongye
|
||||
|
||||
APPID:uni.UNI9620511
|
||||
|
||||
|
||||
|
||||
### 教育咨询
|
||||
|
||||
参数:jiaoyu
|
||||
|
||||
APPID:uni.UNI7AA205C
|
||||
|
||||
|
||||
|
||||
### 法律咨询
|
||||
|
||||
参数:falv
|
||||
|
||||
APPID:uni.UNI358D505
|
||||
|
||||
|
||||
|
||||
### 情感咨询
|
||||
|
||||
参数:qinggan
|
||||
|
||||
APPID:uni.UNI8080F14
|
||||
|
||||
|
||||
|
||||
### 种植分析
|
||||
|
||||
参数:zhongzhi
|
||||
|
||||
APPID:uni.UNI9EDFE40
|
||||
|
||||
|
||||
|
||||
### 养殖分析
|
||||
|
||||
参数:yangzhi
|
||||
|
||||
APPID:uni.UNIEEA7DC9
|
|
@ -0,0 +1,37 @@
|
|||
## 1.6.2(2021-08-24)
|
||||
- 新增 支持国际化
|
||||
## 1.6.1(2021-07-30)
|
||||
- 优化 vue3下事件警告的问题
|
||||
## 1.6.0(2021-07-13)
|
||||
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
|
||||
## 1.5.0(2021-06-23)
|
||||
- 新增 mask-click 遮罩层点击事件
|
||||
## 1.4.5(2021-06-22)
|
||||
- 修复 nvue 平台中间弹出后,点击内容,再点击遮罩无法关闭的Bug
|
||||
## 1.4.4(2021-06-18)
|
||||
- 修复 H5平台中间弹出后,点击内容,再点击遮罩无法关闭的Bug
|
||||
## 1.4.3(2021-06-08)
|
||||
- 修复 错误的 watch 字段
|
||||
- 修复 safeArea 属性不生效的问题
|
||||
- 修复 点击内容,再点击遮罩无法关闭的Bug
|
||||
## 1.4.2(2021-05-12)
|
||||
- 新增 组件示例地址
|
||||
## 1.4.1(2021-04-29)
|
||||
- 修复 组件内放置 input 、textarea 组件,无法聚焦的问题
|
||||
## 1.4.0 (2021-04-29)
|
||||
- 新增 type 属性的 left\right 值,支持左右弹出
|
||||
- 新增 open(String:type) 方法参数 ,可以省略 type 属性 ,直接传入类型打开指定弹窗
|
||||
- 新增 backgroundColor 属性,可定义主窗口背景色,默认不显示背景色
|
||||
- 新增 safeArea 属性,是否适配底部安全区
|
||||
- 修复 App\h5\微信小程序底部安全区占位不对的Bug
|
||||
- 修复 App 端弹出等待的Bug
|
||||
- 优化 提升低配设备性能,优化动画卡顿问题
|
||||
- 优化 更简单的组件自定义方式
|
||||
## 1.2.9(2021-02-05)
|
||||
- 优化 组件引用关系,通过uni_modules引用组件
|
||||
## 1.2.8(2021-02-05)
|
||||
- 调整为uni_modules目录规范
|
||||
## 1.2.7(2021-02-05)
|
||||
- 调整为uni_modules目录规范
|
||||
- 新增 支持 PC 端
|
||||
- 新增 uni-popup-message 、uni-popup-dialog扩展组件支持 PC 端
|
|
@ -0,0 +1,45 @@
|
|||
// #ifdef H5
|
||||
export default {
|
||||
name: 'Keypress',
|
||||
props: {
|
||||
disable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
const keyNames = {
|
||||
esc: ['Esc', 'Escape'],
|
||||
tab: 'Tab',
|
||||
enter: 'Enter',
|
||||
space: [' ', 'Spacebar'],
|
||||
up: ['Up', 'ArrowUp'],
|
||||
left: ['Left', 'ArrowLeft'],
|
||||
right: ['Right', 'ArrowRight'],
|
||||
down: ['Down', 'ArrowDown'],
|
||||
delete: ['Backspace', 'Delete', 'Del']
|
||||
}
|
||||
const listener = ($event) => {
|
||||
if (this.disable) {
|
||||
return
|
||||
}
|
||||
const keyName = Object.keys(keyNames).find(key => {
|
||||
const keyName = $event.key
|
||||
const value = keyNames[key]
|
||||
return value === keyName || (Array.isArray(value) && value.includes(keyName))
|
||||
})
|
||||
if (keyName) {
|
||||
// 避免和其他按键事件冲突
|
||||
setTimeout(() => {
|
||||
this.$emit(keyName, {})
|
||||
}, 0)
|
||||
}
|
||||
}
|
||||
document.addEventListener('keyup', listener)
|
||||
this.$once('hook:beforeDestroy', () => {
|
||||
document.removeEventListener('keyup', listener)
|
||||
})
|
||||
},
|
||||
render: () => {}
|
||||
}
|
||||
// #endif
|
|
@ -0,0 +1,263 @@
|
|||
<template>
|
||||
<view class="uni-popup-dialog">
|
||||
<view class="uni-dialog-title">
|
||||
<text class="uni-dialog-title-text" :class="['uni-popup__'+dialogType]">{{titleText}}</text>
|
||||
</view>
|
||||
<view v-if="mode === 'base'" class="uni-dialog-content">
|
||||
<slot>
|
||||
<text class="uni-dialog-content-text">{{content}}</text>
|
||||
</slot>
|
||||
</view>
|
||||
<view v-else class="uni-dialog-content">
|
||||
<slot>
|
||||
<input class="uni-dialog-input" v-model="val" type="text" :placeholder="placeholderText" :focus="focus" >
|
||||
</slot>
|
||||
</view>
|
||||
<view class="uni-dialog-button-group">
|
||||
<view class="uni-dialog-button" @click="closeDialog">
|
||||
<text class="uni-dialog-button-text">{{cancelText}}</text>
|
||||
</view>
|
||||
<view class="uni-dialog-button uni-border-left" @click="onOk">
|
||||
<text class="uni-dialog-button-text uni-button-color">{{okText}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import popup from '../uni-popup/popup.js'
|
||||
import {
|
||||
initVueI18n
|
||||
} from '@dcloudio/uni-i18n'
|
||||
import messages from '../uni-popup/i18n/index.js'
|
||||
const { t } = initVueI18n(messages)
|
||||
/**
|
||||
* PopUp 弹出层-对话框样式
|
||||
* @description 弹出层-对话框样式
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=329
|
||||
* @property {String} value input 模式下的默认值
|
||||
* @property {String} placeholder input 模式下输入提示
|
||||
* @property {String} type = [success|warning|info|error] 主题样式
|
||||
* @value success 成功
|
||||
* @value warning 提示
|
||||
* @value info 消息
|
||||
* @value error 错误
|
||||
* @property {String} mode = [base|input] 模式、
|
||||
* @value base 基础对话框
|
||||
* @value input 可输入对话框
|
||||
* @property {String} content 对话框内容
|
||||
* @property {Boolean} beforeClose 是否拦截取消事件
|
||||
* @event {Function} confirm 点击确认按钮触发
|
||||
* @event {Function} close 点击取消按钮触发
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: "uniPopupDialog",
|
||||
mixins: [popup],
|
||||
emits:['confirm','close'],
|
||||
props: {
|
||||
value: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
placeholder: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'error'
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'base'
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
content: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
beforeClose: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialogType: 'error',
|
||||
focus: false,
|
||||
val: ""
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
okText() {
|
||||
return t("uni-popup.ok")
|
||||
},
|
||||
cancelText() {
|
||||
return t("uni-popup.cancel")
|
||||
},
|
||||
placeholderText() {
|
||||
return this.placeholder || t("uni-popup.placeholder")
|
||||
},
|
||||
titleText() {
|
||||
return this.title || t("uni-popup.title")
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
type(val) {
|
||||
this.dialogType = val
|
||||
},
|
||||
mode(val) {
|
||||
if (val === 'input') {
|
||||
this.dialogType = 'info'
|
||||
}
|
||||
},
|
||||
value(val) {
|
||||
this.val = val
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// 对话框遮罩不可点击
|
||||
this.popup.disableMask()
|
||||
// this.popup.closeMask()
|
||||
if (this.mode === 'input') {
|
||||
this.dialogType = 'info'
|
||||
this.val = this.value
|
||||
} else {
|
||||
this.dialogType = this.type
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.focus = true
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 点击确认按钮
|
||||
*/
|
||||
onOk() {
|
||||
if (this.mode === 'input'){
|
||||
this.$emit('confirm', this.val)
|
||||
}else{
|
||||
this.$emit('confirm')
|
||||
}
|
||||
if(this.beforeClose) return
|
||||
this.popup.close()
|
||||
},
|
||||
/**
|
||||
* 点击取消按钮
|
||||
*/
|
||||
closeDialog() {
|
||||
this.$emit('close')
|
||||
if(this.beforeClose) return
|
||||
this.popup.close()
|
||||
},
|
||||
close(){
|
||||
this.popup.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.uni-popup-dialog {
|
||||
width: 300px;
|
||||
border-radius: 15px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.uni-dialog-title {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
padding-top: 15px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.uni-dialog-title-text {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.uni-dialog-content {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 5px 15px 15px 15px;
|
||||
}
|
||||
|
||||
.uni-dialog-content-text {
|
||||
font-size: 14px;
|
||||
color: #6e6e6e;
|
||||
}
|
||||
|
||||
.uni-dialog-button-group {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
border-top-color: #f5f5f5;
|
||||
border-top-style: solid;
|
||||
border-top-width: 1px;
|
||||
}
|
||||
|
||||
.uni-dialog-button {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
|
||||
flex: 1;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 45px;
|
||||
}
|
||||
|
||||
.uni-border-left {
|
||||
border-left-color: #f0f0f0;
|
||||
border-left-style: solid;
|
||||
border-left-width: 1px;
|
||||
}
|
||||
|
||||
.uni-dialog-button-text {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.uni-button-color {
|
||||
color: #007aff;
|
||||
}
|
||||
|
||||
.uni-dialog-input {
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
border: 1px #eee solid;
|
||||
height: 40px;
|
||||
padding: 0 10px;
|
||||
border-radius: 5px;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.uni-popup__success {
|
||||
color: #4cd964;
|
||||
}
|
||||
|
||||
.uni-popup__warn {
|
||||
color: #f0ad4e;
|
||||
}
|
||||
|
||||
.uni-popup__error {
|
||||
color: #dd524d;
|
||||
}
|
||||
|
||||
.uni-popup__info {
|
||||
color: #909399;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,143 @@
|
|||
<template>
|
||||
<view class="uni-popup-message">
|
||||
<view class="uni-popup-message__box fixforpc-width" :class="'uni-popup__'+type">
|
||||
<slot>
|
||||
<text class="uni-popup-message-text" :class="'uni-popup__'+type+'-text'">{{message}}</text>
|
||||
</slot>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import popup from '../uni-popup/popup.js'
|
||||
/**
|
||||
* PopUp 弹出层-消息提示
|
||||
* @description 弹出层-消息提示
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=329
|
||||
* @property {String} type = [success|warning|info|error] 主题样式
|
||||
* @value success 成功
|
||||
* @value warning 提示
|
||||
* @value info 消息
|
||||
* @value error 错误
|
||||
* @property {String} message 消息提示文字
|
||||
* @property {String} duration 显示时间,设置为 0 则不会自动关闭
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: 'uniPopupMessage',
|
||||
mixins:[popup],
|
||||
props: {
|
||||
/**
|
||||
* 主题 success/warning/info/error 默认 success
|
||||
*/
|
||||
type: {
|
||||
type: String,
|
||||
default: 'success'
|
||||
},
|
||||
/**
|
||||
* 消息文字
|
||||
*/
|
||||
message: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
/**
|
||||
* 显示时间,设置为 0 则不会自动关闭
|
||||
*/
|
||||
duration: {
|
||||
type: Number,
|
||||
default: 3000
|
||||
},
|
||||
maskShow:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
created() {
|
||||
this.popup.maskShow = this.maskShow
|
||||
this.popup.messageChild = this
|
||||
},
|
||||
methods: {
|
||||
timerClose(){
|
||||
if(this.duration === 0) return
|
||||
clearTimeout(this.timer)
|
||||
this.timer = setTimeout(()=>{
|
||||
this.popup.close()
|
||||
},this.duration)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.uni-popup-message {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.uni-popup-message__box {
|
||||
background-color: #e1f3d8;
|
||||
padding: 10px 15px;
|
||||
border-color: #eee;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 500px) {
|
||||
.fixforpc-width {
|
||||
margin-top: 20px;
|
||||
border-radius: 4px;
|
||||
flex: none;
|
||||
min-width: 380px;
|
||||
/* #ifndef APP-NVUE */
|
||||
max-width: 50%;
|
||||
/* #endif */
|
||||
/* #ifdef APP-NVUE */
|
||||
max-width: 500px;
|
||||
/* #endif */
|
||||
}
|
||||
}
|
||||
|
||||
.uni-popup-message-text {
|
||||
font-size: 14px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.uni-popup__success {
|
||||
background-color: #e1f3d8;
|
||||
}
|
||||
|
||||
.uni-popup__success-text {
|
||||
color: #67C23A;
|
||||
}
|
||||
|
||||
.uni-popup__warn {
|
||||
background-color: #faecd8;
|
||||
}
|
||||
|
||||
.uni-popup__warn-text {
|
||||
color: #E6A23C;
|
||||
}
|
||||
|
||||
.uni-popup__error {
|
||||
background-color: #fde2e2;
|
||||
}
|
||||
|
||||
.uni-popup__error-text {
|
||||
color: #F56C6C;
|
||||
}
|
||||
|
||||
.uni-popup__info {
|
||||
background-color: #F2F6FC;
|
||||
}
|
||||
|
||||
.uni-popup__info-text {
|
||||
color: #909399;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,185 @@
|
|||
<template>
|
||||
<view class="uni-popup-share">
|
||||
<view class="uni-share-title"><text class="uni-share-title-text">{{shareTitleText}}</text></view>
|
||||
<view class="uni-share-content">
|
||||
<view class="uni-share-content-box">
|
||||
<view class="uni-share-content-item" v-for="(item,index) in bottomData" :key="index" @click.stop="select(item,index)">
|
||||
<image class="uni-share-image" :src="item.icon" mode="aspectFill"></image>
|
||||
<text class="uni-share-text">{{item.text}}</text>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<view class="uni-share-button-box">
|
||||
<button class="uni-share-button" @click="close">{{cancelText}}</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import popup from '../uni-popup/popup.js'
|
||||
import {
|
||||
initVueI18n
|
||||
} from '@dcloudio/uni-i18n'
|
||||
import messages from '../uni-popup/i18n/index.js'
|
||||
const { t } = initVueI18n(messages)
|
||||
export default {
|
||||
name: 'UniPopupShare',
|
||||
mixins:[popup],
|
||||
emits:['select'],
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
beforeClose: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
bottomData: [{
|
||||
text: '微信',
|
||||
icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/c2b17470-50be-11eb-b680-7980c8a877b8.png',
|
||||
name: 'wx'
|
||||
},
|
||||
{
|
||||
text: '支付宝',
|
||||
icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/d684ae40-50be-11eb-8ff1-d5dcf8779628.png',
|
||||
name: 'wx'
|
||||
},
|
||||
{
|
||||
text: 'QQ',
|
||||
icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/e7a79520-50be-11eb-b997-9918a5dda011.png',
|
||||
name: 'qq'
|
||||
},
|
||||
{
|
||||
text: '新浪',
|
||||
icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/0dacdbe0-50bf-11eb-8ff1-d5dcf8779628.png',
|
||||
name: 'sina'
|
||||
},
|
||||
{
|
||||
text: '百度',
|
||||
icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/1ec6e920-50bf-11eb-8a36-ebb87efcf8c0.png',
|
||||
name: 'copy'
|
||||
},
|
||||
{
|
||||
text: '其他',
|
||||
icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/2e0fdfe0-50bf-11eb-b997-9918a5dda011.png',
|
||||
name: 'more'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
created() {},
|
||||
computed: {
|
||||
cancelText() {
|
||||
return t("uni-popup.cancel")
|
||||
},
|
||||
shareTitleText() {
|
||||
return this.title || t("uni-popup.shareTitle")
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 选择内容
|
||||
*/
|
||||
select(item, index) {
|
||||
this.$emit('select', {
|
||||
item,
|
||||
index
|
||||
})
|
||||
this.close()
|
||||
|
||||
},
|
||||
/**
|
||||
* 关闭窗口
|
||||
*/
|
||||
close() {
|
||||
if(this.beforeClose) return
|
||||
this.popup.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.uni-popup-share {
|
||||
background-color: #fff;
|
||||
}
|
||||
.uni-share-title {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 40px;
|
||||
}
|
||||
.uni-share-title-text {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
.uni-share-content {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.uni-share-content-box {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
width: 360px;
|
||||
}
|
||||
|
||||
.uni-share-content-item {
|
||||
width: 90px;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding: 10px 0;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.uni-share-content-item:active {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.uni-share-image {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.uni-share-text {
|
||||
margin-top: 10px;
|
||||
font-size: 14px;
|
||||
color: #3B4144;
|
||||
}
|
||||
|
||||
.uni-share-button-box {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
padding: 10px 15px;
|
||||
}
|
||||
|
||||
.uni-share-button {
|
||||
flex: 1;
|
||||
border-radius: 50px;
|
||||
color: #666;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.uni-share-button::after {
|
||||
border-radius: 50px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"uni-popup.cancel": "cancel",
|
||||
"uni-popup.ok": "ok",
|
||||
"uni-popup.placeholder": "pleace enter",
|
||||
"uni-popup.title": "Hint",
|
||||
"uni-popup.shareTitle": "Share to"
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
import en from './en.json'
|
||||
import zhHans from './zh-Hans.json'
|
||||
import zhHant from './zh-Hant.json'
|
||||
export default {
|
||||
en,
|
||||
'zh-Hans': zhHans,
|
||||
'zh-Hant': zhHant
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"uni-popup.cancel": "取消",
|
||||
"uni-popup.ok": "确定",
|
||||
"uni-popup.placeholder": "请输入",
|
||||
"uni-popup.title": "提示",
|
||||
"uni-popup.shareTitle": "分享到"
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"uni-popup.cancel": "取消",
|
||||
"uni-popup.ok": "確定",
|
||||
"uni-popup.placeholder": "請輸入",
|
||||
"uni-popup.title": "提示",
|
||||
"uni-popup.shareTitle": "分享到"
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
// #ifdef H5
|
||||
export default {
|
||||
name: 'Keypress',
|
||||
props: {
|
||||
disable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
const keyNames = {
|
||||
esc: ['Esc', 'Escape'],
|
||||
tab: 'Tab',
|
||||
enter: 'Enter',
|
||||
space: [' ', 'Spacebar'],
|
||||
up: ['Up', 'ArrowUp'],
|
||||
left: ['Left', 'ArrowLeft'],
|
||||
right: ['Right', 'ArrowRight'],
|
||||
down: ['Down', 'ArrowDown'],
|
||||
delete: ['Backspace', 'Delete', 'Del']
|
||||
}
|
||||
const listener = ($event) => {
|
||||
if (this.disable) {
|
||||
return
|
||||
}
|
||||
const keyName = Object.keys(keyNames).find(key => {
|
||||
const keyName = $event.key
|
||||
const value = keyNames[key]
|
||||
return value === keyName || (Array.isArray(value) && value.includes(keyName))
|
||||
})
|
||||
if (keyName) {
|
||||
// 避免和其他按键事件冲突
|
||||
setTimeout(() => {
|
||||
this.$emit(keyName, {})
|
||||
}, 0)
|
||||
}
|
||||
}
|
||||
document.addEventListener('keyup', listener)
|
||||
// this.$once('hook:beforeDestroy', () => {
|
||||
// document.removeEventListener('keyup', listener)
|
||||
// })
|
||||
},
|
||||
render: () => {}
|
||||
}
|
||||
// #endif
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
created(){
|
||||
this.popup = this.getParent()
|
||||
},
|
||||
methods:{
|
||||
/**
|
||||
* 获取父元素实例
|
||||
*/
|
||||
getParent(name = 'uniPopup') {
|
||||
let parent = this.$parent;
|
||||
let parentName = parent.$options.name;
|
||||
while (parentName !== name) {
|
||||
parent = parent.$parent;
|
||||
if (!parent) return false
|
||||
parentName = parent.$options.name;
|
||||
}
|
||||
return parent;
|
||||
},
|
||||
}
|
||||
}
|
|
@ -0,0 +1,403 @@
|
|||
<template>
|
||||
<view v-if="showPopup" class="uni-popup" :class="[popupstyle, isDesktop ? 'fixforpc-z-index' : '']" @touchmove.stop.prevent="clear">
|
||||
<view @touchstart="touchstart" >
|
||||
<uni-transition key="1" v-if="maskShow" name="mask" mode-class="fade" :styles="maskClass" :duration="duration" :show="showTrans" @click="onTap" />
|
||||
<uni-transition key="2" :mode-class="ani" name="content" :styles="transClass" :duration="duration" :show="showTrans" @click="onTap">
|
||||
<view class="uni-popup__wrapper" :style="{ backgroundColor: bg }" :class="[popupstyle]" @click="clear"><slot /></view>
|
||||
</uni-transition>
|
||||
</view>
|
||||
<!-- #ifdef H5 -->
|
||||
<keypress v-if="maskShow" @esc="onTap" />
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// #ifdef H5
|
||||
import keypress from './keypress.js'
|
||||
// #endif
|
||||
|
||||
/**
|
||||
* PopUp 弹出层
|
||||
* @description 弹出层组件,为了解决遮罩弹层的问题
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=329
|
||||
* @property {String} type = [top|center|bottom|left|right|message|dialog|share] 弹出方式
|
||||
* @value top 顶部弹出
|
||||
* @value center 中间弹出
|
||||
* @value bottom 底部弹出
|
||||
* @value left 左侧弹出
|
||||
* @value right 右侧弹出
|
||||
* @value message 消息提示
|
||||
* @value dialog 对话框
|
||||
* @value share 底部分享示例
|
||||
* @property {Boolean} animation = [ture|false] 是否开启动画
|
||||
* @property {Boolean} maskClick = [ture|false] 蒙版点击是否关闭弹窗
|
||||
* @property {String} backgroundColor 主窗口背景色
|
||||
* @property {Boolean} safeArea 是否适配底部安全区
|
||||
* @event {Function} change 打开关闭弹窗触发,e={show: false}
|
||||
* @event {Function} maskClick 点击遮罩触发
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: 'uniPopup',
|
||||
components: {
|
||||
// #ifdef H5
|
||||
keypress
|
||||
// #endif
|
||||
},
|
||||
emits:['change','maskClick'],
|
||||
props: {
|
||||
// 开启动画
|
||||
animation: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 弹出层类型,可选值,top: 顶部弹出层;bottom:底部弹出层;center:全屏弹出层
|
||||
// message: 消息提示 ; dialog : 对话框
|
||||
type: {
|
||||
type: String,
|
||||
default: 'center'
|
||||
},
|
||||
// maskClick
|
||||
maskClick: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
backgroundColor: {
|
||||
type: String,
|
||||
default: 'none'
|
||||
},
|
||||
safeArea:{
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
/**
|
||||
* 监听type类型
|
||||
*/
|
||||
type: {
|
||||
handler: function(type) {
|
||||
if (!this.config[type]) return
|
||||
this[this.config[type]](true)
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
isDesktop: {
|
||||
handler: function(newVal) {
|
||||
if (!this.config[newVal]) return
|
||||
this[this.config[this.type]](true)
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
/**
|
||||
* 监听遮罩是否可点击
|
||||
* @param {Object} val
|
||||
*/
|
||||
maskClick: {
|
||||
handler: function(val) {
|
||||
this.mkclick = val
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
duration: 300,
|
||||
ani: [],
|
||||
showPopup: false,
|
||||
showTrans: false,
|
||||
popupWidth: 0,
|
||||
popupHeight: 0,
|
||||
config: {
|
||||
top: 'top',
|
||||
bottom: 'bottom',
|
||||
center: 'center',
|
||||
left: 'left',
|
||||
right: 'right',
|
||||
message: 'top',
|
||||
dialog: 'center',
|
||||
share: 'bottom'
|
||||
},
|
||||
maskClass: {
|
||||
position: 'fixed',
|
||||
bottom: 0,
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.4)'
|
||||
},
|
||||
transClass: {
|
||||
position: 'fixed',
|
||||
left: 0,
|
||||
right: 0
|
||||
},
|
||||
maskShow: true,
|
||||
mkclick: true,
|
||||
popupstyle: this.isDesktop ? 'fixforpc-top' : 'top'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isDesktop() {
|
||||
return this.popupWidth >= 500 && this.popupHeight >= 500
|
||||
},
|
||||
bg() {
|
||||
if (this.backgroundColor === '' || this.backgroundColor === 'none') {
|
||||
return 'transparent'
|
||||
}
|
||||
return this.backgroundColor
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const fixSize = () => {
|
||||
const { windowWidth, windowHeight, windowTop, safeAreaInsets } = uni.getSystemInfoSync()
|
||||
this.popupWidth = windowWidth
|
||||
this.popupHeight = windowHeight + windowTop
|
||||
// 是否适配底部安全区
|
||||
if(this.safeArea){
|
||||
this.safeAreaInsets = safeAreaInsets
|
||||
}else{
|
||||
this.safeAreaInsets = 0
|
||||
}
|
||||
}
|
||||
fixSize()
|
||||
// #ifdef H5
|
||||
// window.addEventListener('resize', fixSize)
|
||||
// this.$once('hook:beforeDestroy', () => {
|
||||
// window.removeEventListener('resize', fixSize)
|
||||
// })
|
||||
// #endif
|
||||
},
|
||||
created() {
|
||||
this.mkclick = this.maskClick
|
||||
if (this.animation) {
|
||||
this.duration = 300
|
||||
} else {
|
||||
this.duration = 0
|
||||
}
|
||||
// TODO 处理 message 组件生命周期异常的问题
|
||||
this.messageChild = null
|
||||
// TODO 解决头条冒泡的问题
|
||||
this.clearPropagation = false
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 公用方法,不显示遮罩层
|
||||
*/
|
||||
closeMask() {
|
||||
this.maskShow = false
|
||||
},
|
||||
/**
|
||||
* 公用方法,遮罩层禁止点击
|
||||
*/
|
||||
disableMask() {
|
||||
this.mkclick = false
|
||||
},
|
||||
// TODO nvue 取消冒泡
|
||||
clear(e) {
|
||||
// #ifndef APP-NVUE
|
||||
e.stopPropagation()
|
||||
// #endif
|
||||
this.clearPropagation = true
|
||||
},
|
||||
|
||||
open(direction) {
|
||||
let innerType = ['top', 'center', 'bottom', 'left', 'right', 'message', 'dialog', 'share']
|
||||
if (!(direction && innerType.indexOf(direction) !== -1)) {
|
||||
direction = this.type
|
||||
}
|
||||
if (!this.config[direction]) {
|
||||
console.error('缺少类型:', direction)
|
||||
return
|
||||
}
|
||||
this[this.config[direction]]()
|
||||
this.$emit('change', {
|
||||
show: true,
|
||||
type: direction
|
||||
})
|
||||
},
|
||||
close(type) {
|
||||
this.showTrans = false
|
||||
this.$emit('change', {
|
||||
show: false,
|
||||
type: this.type
|
||||
})
|
||||
clearTimeout(this.timer)
|
||||
// // 自定义关闭事件
|
||||
// this.customOpen && this.customClose()
|
||||
this.timer = setTimeout(() => {
|
||||
this.showPopup = false
|
||||
}, 300)
|
||||
},
|
||||
// TODO 处理冒泡事件,头条的冒泡事件有问题 ,先这样兼容
|
||||
touchstart(){
|
||||
this.clearPropagation = false
|
||||
},
|
||||
|
||||
onTap() {
|
||||
if (this.clearPropagation) {
|
||||
// fix by mehaotian 兼容 nvue
|
||||
this.clearPropagation = false
|
||||
return
|
||||
}
|
||||
this.$emit('maskClick')
|
||||
if (!this.mkclick) return
|
||||
this.close()
|
||||
},
|
||||
/**
|
||||
* 顶部弹出样式处理
|
||||
*/
|
||||
top(type) {
|
||||
this.popupstyle = this.isDesktop ? 'fixforpc-top' : 'top'
|
||||
this.ani = ['slide-top']
|
||||
this.transClass = {
|
||||
position: 'fixed',
|
||||
left: 0,
|
||||
right: 0,
|
||||
backgroundColor: this.bg
|
||||
}
|
||||
// TODO 兼容 type 属性 ,后续会废弃
|
||||
if (type) return
|
||||
this.showPopup = true
|
||||
this.showTrans = true
|
||||
this.$nextTick(() => {
|
||||
if (this.messageChild && this.type === 'message') {
|
||||
this.messageChild.timerClose()
|
||||
}
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 底部弹出样式处理
|
||||
*/
|
||||
bottom(type) {
|
||||
this.popupstyle = 'bottom'
|
||||
this.ani = ['slide-bottom']
|
||||
|
||||
this.transClass = {
|
||||
position: 'fixed',
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
paddingBottom: (this.safeAreaInsets && this.safeAreaInsets.bottom) || 0,
|
||||
backgroundColor: this.bg
|
||||
}
|
||||
// TODO 兼容 type 属性 ,后续会废弃
|
||||
if (type) return
|
||||
this.showPopup = true
|
||||
this.showTrans = true
|
||||
},
|
||||
/**
|
||||
* 中间弹出样式处理
|
||||
*/
|
||||
center(type) {
|
||||
this.popupstyle = 'center'
|
||||
this.ani = ['zoom-out', 'fade']
|
||||
this.transClass = {
|
||||
position: 'fixed',
|
||||
/* #ifndef APP-NVUE */
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
/* #endif */
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center'
|
||||
}
|
||||
// TODO 兼容 type 属性 ,后续会废弃
|
||||
if (type) return
|
||||
this.showPopup = true
|
||||
this.showTrans = true
|
||||
},
|
||||
left(type) {
|
||||
this.popupstyle = 'left'
|
||||
this.ani = ['slide-left']
|
||||
this.transClass = {
|
||||
position: 'fixed',
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
top: 0,
|
||||
backgroundColor: this.bg,
|
||||
/* #ifndef APP-NVUE */
|
||||
display: 'flex',
|
||||
flexDirection: 'column'
|
||||
/* #endif */
|
||||
}
|
||||
// TODO 兼容 type 属性 ,后续会废弃
|
||||
if (type) return
|
||||
this.showPopup = true
|
||||
this.showTrans = true
|
||||
},
|
||||
right(type) {
|
||||
this.popupstyle = 'right'
|
||||
this.ani = ['slide-right']
|
||||
this.transClass = {
|
||||
position: 'fixed',
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
backgroundColor: this.bg,
|
||||
/* #ifndef APP-NVUE */
|
||||
display: 'flex',
|
||||
flexDirection: 'column'
|
||||
/* #endif */
|
||||
}
|
||||
// TODO 兼容 type 属性 ,后续会废弃
|
||||
if (type) return
|
||||
this.showPopup = true
|
||||
this.showTrans = true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.uni-popup {
|
||||
position: fixed;
|
||||
/* #ifndef APP-NVUE */
|
||||
z-index: 99;
|
||||
/* #endif */
|
||||
&.top,
|
||||
&.left,
|
||||
&.right {
|
||||
/* #ifdef H5 */
|
||||
top: var(--window-top);
|
||||
/* #endif */
|
||||
/* #ifndef H5 */
|
||||
top: 0;
|
||||
/* #endif */
|
||||
}
|
||||
.uni-popup__wrapper {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: block;
|
||||
/* #endif */
|
||||
position: relative;
|
||||
/* iphonex 等安全区设置,底部安全区适配 */
|
||||
/* #ifndef APP-NVUE */
|
||||
// padding-bottom: constant(safe-area-inset-bottom);
|
||||
// padding-bottom: env(safe-area-inset-bottom);
|
||||
/* #endif */
|
||||
&.left,
|
||||
&.right {
|
||||
/* #ifdef H5 */
|
||||
padding-top: var(--window-top);
|
||||
/* #endif */
|
||||
/* #ifndef H5 */
|
||||
padding-top: 0;
|
||||
/* #endif */
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fixforpc-z-index {
|
||||
/* #ifndef APP-NVUE */
|
||||
z-index: 999;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.fixforpc-top {
|
||||
top: 0;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,89 @@
|
|||
{
|
||||
"id": "uni-popup",
|
||||
"displayName": "uni-popup 弹出层",
|
||||
"version": "1.6.2",
|
||||
"description": " Popup 组件,提供常用的弹层",
|
||||
"keywords": [
|
||||
"uni-ui",
|
||||
"弹出层",
|
||||
"弹窗",
|
||||
"popup",
|
||||
"弹框"
|
||||
],
|
||||
"repository": "https://github.com/dcloudio/uni-ui",
|
||||
"engines": {
|
||||
"HBuilderX": ""
|
||||
},
|
||||
"directories": {
|
||||
"example": "../../temps/example_temps"
|
||||
},
|
||||
"dcloudext": {
|
||||
"category": [
|
||||
"前端组件",
|
||||
"通用组件"
|
||||
],
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uni-transition"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
},
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,296 @@
|
|||
|
||||
|
||||
## Popup 弹出层
|
||||
> **组件名:uni-popup**
|
||||
> 代码块: `uPopup`
|
||||
> 关联组件:`uni-popup-dialog`,`uni-popup-message`,`uni-popup-share`,`uni-transition`
|
||||
|
||||
|
||||
弹出层组件,在应用中弹出一个消息提示窗口、提示框等
|
||||
|
||||
|
||||
> **注意事项**
|
||||
> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。
|
||||
> - 组件需要依赖 `sass` 插件 ,请自行手动安装
|
||||
> - `uni-popup-message` 、 `uni-popup-dialog` 等扩展ui组件,需要和 `uni-popup` 配套使用,暂不支持单独使用
|
||||
> - `nvue` 中使用 `uni-popup` 时,尽量将组件置于其他元素后面,避免出现层级问题
|
||||
> - `uni-popup` 并不能完全阻止页面滚动,可在打开 `uni-popup` 的时候手动去做一些处理,禁止页面滚动
|
||||
> - 如果想在页面渲染完毕后就打开 `uni-popup` ,请在 `onReady` 或 `mounted` 生命周期内调用,确保组件渲染完毕
|
||||
> - 在微信小程序开发者工具中,启用真机调试,popup 会延时出现,是因为 setTimeout 在真机调试中的延时问题导致的,预览和发布小程序不会出现此问题
|
||||
> - 使用 `npm` 方式引入组件,如果确认引用正确,但是提示未注册组件或显示不正常,请尝试重新编译项目
|
||||
> - `uni-popup` 中尽量不要使用 `scroll-view` 嵌套过多的内容,可能会影响组件的性能,导致组件无法打开或者打开卡顿
|
||||
> - `uni-popup` 不会覆盖原生 tabbar 和原生导航栏
|
||||
> - 组件支持 nvue ,需要在 `manifest.json > app-plus` 节点下配置 `"nvueStyleCompiler" : "uni-app"`
|
||||
> - 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
|
||||
|
||||
|
||||
|
||||
### 安装方式
|
||||
|
||||
本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。
|
||||
|
||||
如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
|
||||
|
||||
|
||||
### 基本用法
|
||||
|
||||
**示例**
|
||||
|
||||
```html
|
||||
<button @click="open">打开弹窗</button>
|
||||
<uni-popup ref="popup" type="bottom">底部弹出 Popup</uni-popup>
|
||||
```
|
||||
|
||||
```javascript
|
||||
export default {
|
||||
methods:{
|
||||
open(){
|
||||
// 通过组件定义的ref调用uni-popup方法 ,如果传入参数 ,type 属性将失效 ,仅支持 ['top','left','bottom','right','center']
|
||||
this.$refs.popup.open('top')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### 设置主窗口背景色
|
||||
|
||||
在大多数场景下,并不需要设置 `background-color` 属性,因为`uni-popup`的主窗口默认是透明的,在向里面插入内容的时候 ,样式完全交由用户定制,如果设置了背景色 ,例如 `uni-popup-dialog` 中的圆角就很难去实现,不设置背景色,更适合用户去自由发挥。
|
||||
|
||||
而也有特例,需要我们主动去设置背景色,例如 `type = 'bottom'` 的时候 ,在异型屏中遇到了底部安全区问题(如 iphone 11),因为 `uni-popup`的主要内容避开了安全区(设置`safe-area:true`),导致底部的颜色我们无法自定义,这时候使用 `background-color` 就可以解决这个问题。
|
||||
|
||||
**示例**
|
||||
|
||||
```html
|
||||
<button @click="open">打开弹窗</button>
|
||||
<uni-popup ref="popup" type="bottom" background-color="#fff">底部弹出 Popup</uni-popup>
|
||||
```
|
||||
|
||||
### 禁用打开动画
|
||||
在某些场景 ,可能不希望弹层有动画效果 ,只需要将 `animation` 属性设置为 `false` 即可以关闭动画。
|
||||
|
||||
**示例**
|
||||
|
||||
```html
|
||||
<button @click="open">打开弹窗</button>
|
||||
<uni-popup ref="popup" type="center" :animation="false">中间弹出 Popup</uni-popup>
|
||||
```
|
||||
|
||||
### 禁用点击遮罩关闭
|
||||
默认情况下,点击遮罩会自动关闭`uni-popup`,如不想点击关闭,只需将`mask-click`设置为`false`,这时候要关闭`uni-popup`,只能手动调用 `close` 方法。
|
||||
|
||||
**示例**
|
||||
|
||||
```html
|
||||
<button @click="open">打开弹窗</button>
|
||||
<uni-popup ref="popup" :mask-click="false">
|
||||
<text>Popup</text>
|
||||
<button @click="close">关闭</button>
|
||||
</uni-popup>
|
||||
```
|
||||
|
||||
```javascript
|
||||
export default {
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
onReady() {},
|
||||
methods: {
|
||||
open() {
|
||||
this.$refs.popup.open('top')
|
||||
},
|
||||
close() {
|
||||
this.$refs.popup.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### Popup Props
|
||||
|
||||
|属性名|类型|默认值|说明|
|
||||
|:-:|:-:|:-:|:-:|
|
||||
|animation|Boolean|true|是否开启动画|
|
||||
|type|String|'center'|弹出方式|
|
||||
|mask-click|Boolean|true|蒙版点击是否关闭弹窗|
|
||||
|background-color|String|'none'|主窗口背景色|
|
||||
|safe-area|Boolean|true|是否适配底部安全区|
|
||||
|
||||
#### Type Options
|
||||
|
||||
|属性名|说明|
|
||||
|:-:| :-:|
|
||||
|top|顶部弹出 |
|
||||
|center|居中弹出|
|
||||
|bottom|底部弹出|
|
||||
|left|左侧弹出|
|
||||
|right|右侧弹出|
|
||||
|message|预置样式 :消息提示|
|
||||
|dialog|预置样式 :对话框|
|
||||
|share|预置样式 :底部弹出分享示例 |
|
||||
|
||||
|
||||
### Popup Methods
|
||||
|
||||
|方法称名 |说明|参数|
|
||||
|:-:|:-:|:-:|
|
||||
|open|打开弹出层|open(String:type) ,如果参数可代替 type 属性|
|
||||
|close|关闭弹出层 |-|
|
||||
|
||||
|
||||
### Popup Events
|
||||
|
||||
|事件称名|说明|返回值|
|
||||
|:-:|:-:|:-:|
|
||||
|change|组件状态发生变化触发|e={show: true|false,type:当前模式}|
|
||||
|maskClick|点击遮罩层触发|-|
|
||||
|
||||
|
||||
## 扩展组件说明
|
||||
`uni-popup` 其实并没有任何样式,只提供基础的动画效果,给用户一个弹出层解决方案,仅仅是这样并不能满足开发需求,所以我们提供了三种基础扩展样式
|
||||
|
||||
### uni-popup-message 提示信息
|
||||
|
||||
将 `uni-popup` 的`type`属性改为 `message`,并引入对应组件即可使用消息提示 ,*该组件不支持单独使用*
|
||||
|
||||
**示例**
|
||||
|
||||
```html
|
||||
<uni-popup ref="popup" type="message">
|
||||
<uni-popup-message type="success" message="成功消息" :duration="2000"></uni-popup-message>
|
||||
</uni-popup>
|
||||
```
|
||||
|
||||
### PopupMessage Props
|
||||
|
||||
|属性名|类型|默认值|说明|
|
||||
|:-:|:-:|:-:|:-:|
|
||||
|type|String|success|消息提示主题|
|
||||
|message|String|-|消息提示文字|
|
||||
|duration|Number|3000|消息显示时间,超过显示时间组件自动关闭,设置为0 将不会关闭,需手动调用 close 方法关闭|
|
||||
|
||||
#### Type Options
|
||||
|
||||
|属性名|说明|
|
||||
|:-:| :-:|
|
||||
|success|成功 |
|
||||
|warn|警告|
|
||||
|error|失败|
|
||||
|info|消息|
|
||||
|
||||
### PopupMessage Slots
|
||||
|
||||
|名称|说明|
|
||||
|:-:|:-:|
|
||||
|default|消息内容,会覆盖 message 属性|
|
||||
|
||||
### uni-popup-dialog 对话框
|
||||
|
||||
将 `uni-popup` 的`type`属性改为 `dialog`,并引入对应组件即可使用对话框 ,*该组件不支持单独使用*
|
||||
|
||||
**示例**
|
||||
|
||||
```html
|
||||
<button @click="open">打开弹窗</button>
|
||||
<uni-popup ref="popup" type="dialog">
|
||||
<uni-popup-dialog mode="input" message="成功消息" :duration="2000" :before-close="true" @close="close" @confirm="confirm"></uni-popup-dialog>
|
||||
</uni-popup>
|
||||
```
|
||||
|
||||
```javascript
|
||||
export default {
|
||||
methods: {
|
||||
open() {
|
||||
this.$refs.popup.open()
|
||||
},
|
||||
/**
|
||||
* 点击取消按钮触发
|
||||
* @param {Object} done
|
||||
*/
|
||||
close() {
|
||||
// TODO 做一些其他的事情,before-close 为true的情况下,手动执行 close 才会关闭对话框
|
||||
// ...
|
||||
this.$refs.popup.close()
|
||||
},
|
||||
/**
|
||||
* 点击确认按钮触发
|
||||
* @param {Object} done
|
||||
* @param {Object} value
|
||||
*/
|
||||
confirm(value) {
|
||||
// 输入框的值
|
||||
// console.log(value)
|
||||
// TODO 做一些其他的事情,手动执行 close 才会关闭对话框
|
||||
// ...
|
||||
this.$refs.popup.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### PopupDialog Props
|
||||
|
||||
|属性名|类型|默认值|说明|
|
||||
|:-:|:-:|:-:|:-:|
|
||||
|type|String|success|对话框标题主题,可选值: success/warn/info/error|
|
||||
|mode|String|base| 对话框模式,可选值:base(提示对话框)/input(可输入对话框)|
|
||||
|title|String|-|对话框标题|
|
||||
|content|String|-|对话框内容,base模式下生效|
|
||||
|value| String\Number|-|输入框默认值,input模式下生效|
|
||||
|placeholder|String|-|输入框提示文字,input模式下生效|
|
||||
|before-close|Boolean|false | 是否拦截按钮事件,如为true,则不会关闭对话框,关闭需要手动执行 uni-popup 的 close 方法|
|
||||
|
||||
#### PopupDialog Events
|
||||
|
||||
|事件称名 |说明|返回值|
|
||||
|:-:|:-:|:-:|
|
||||
|close|点击dialog取消按钮触发|-|
|
||||
|confirm|点击dialog确定按钮触发|e={value:input模式下输入框的值}|
|
||||
|
||||
### PopupDialog Slots
|
||||
|
||||
|名称|说明|
|
||||
|:-:|:-:|
|
||||
|default|自定义内容,回覆盖原有的内容显示|
|
||||
|
||||
### uni-popup-share 分享示例
|
||||
|
||||
分享示例,不作为最终可使用的组件,只做为样式组件,供用户自行修改,`后续的开发计划是实现实际的分享逻辑,参数可配置`。
|
||||
|
||||
将 `uni-popup` 的 `type` 属性改为 `share`,并引入对应组件即可使用 ,*该组件不支持单独使用*
|
||||
|
||||
**示例**
|
||||
|
||||
```html
|
||||
<uni-popup ref="popup" type="share">
|
||||
<uni-popup-share title="分享到" @select="select"></uni-popup-share>
|
||||
</uni-popup>
|
||||
```
|
||||
|
||||
### PopupShare Props
|
||||
|
||||
|属性名|类型|默认值|说明|
|
||||
|:-:|:-:|:-:| :-: |
|
||||
|title|String|-|分享弹窗标题|
|
||||
|before-close|Boolean|false | 是否拦截按钮事件,如为true,则不会关闭对话框,关闭需要手动执行 uni-popup 的 close 方法|
|
||||
|
||||
### PopupShare Events
|
||||
|
||||
|事件称名|说明|返回值|
|
||||
|:-:|:-:|:-:|
|
||||
|select|选择触发|e = {item,index}:所选参数|
|
||||
|
||||
**Tips**
|
||||
- share 分享组件,只是作为一个扩展示例,如果需要修改数据源,请到组件内修改
|
||||
|
||||
## 帮助
|
||||
在使用中如遇到无法解决的问题,请提 [Issues](https://github.com/dcloudio/uni-ui/issues) 给我们。
|
||||
|
||||
|
||||
|
||||
## 组件示例
|
||||
|
||||
点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/popup/popup](https://hellouniapp.dcloud.net.cn/pages/extUI/popup/popup)
|
Before Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 2.0 KiB |
|
@ -1,25 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<script>
|
||||
var __UniViewStartTime__ = Date.now();
|
||||
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
|
||||
CSS.supports('top: constant(a)'))
|
||||
document.write(
|
||||
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
|
||||
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
|
||||
</script>
|
||||
<title>View</title>
|
||||
<link rel="stylesheet" href="view.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script src="__uniappes6.js"></script>
|
||||
<script src="view.umd.min.js"></script>
|
||||
<script src="app-view.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,8 +0,0 @@
|
|||
|
||||
var isReady=false;var onReadyCallbacks=[];
|
||||
var isServiceReady=false;var onServiceReadyCallbacks=[];
|
||||
var __uniConfig = {"pages":["pages/index/index"],"window":{"navigationBarTextStyle":"black","navigationBarTitleText":"人工智能","navigationBarBackgroundColor":"#F8F8F8","backgroundColor":"#F8F8F8"},"darkmode":false,"nvueCompiler":"uni-app","nvueStyleCompiler":"uni-app","renderer":"auto","splashscreen":{"alwaysShowBeforeRender":true,"autoclose":false},"appname":"农业咨询","compilerVersion":"3.8.12","entryPagePath":"pages/index/index","networkTimeout":{"request":60000,"connectSocket":60000,"uploadFile":60000,"downloadFile":60000}};
|
||||
var __uniRoutes = [{"path":"/pages/index/index","meta":{"isQuit":true},"window":{"navigationBarTitleText":"农业咨询","bounce":"none"}}];
|
||||
__uniConfig.onReady=function(callback){if(__uniConfig.ready){callback()}else{onReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"ready",{get:function(){return isReady},set:function(val){isReady=val;if(!isReady){return}const callbacks=onReadyCallbacks.slice(0);onReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
|
||||
__uniConfig.onServiceReady=function(callback){if(__uniConfig.serviceReady){callback()}else{onServiceReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"serviceReady",{get:function(){return isServiceReady},set:function(val){isServiceReady=val;if(!isServiceReady){return}const callbacks=onServiceReadyCallbacks.slice(0);onServiceReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
|
||||
service.register("uni-app-config",{create(a,b,c){if(!__uniConfig.viewport){var d=b.weex.config.env.scale,e=b.weex.config.env.deviceWidth,f=Math.ceil(e/d);Object.assign(__uniConfig,{viewport:f,defaultFontSize:Math.round(f/20)})}return{instance:{__uniConfig:__uniConfig,__uniRoutes:__uniRoutes,global:void 0,window:void 0,document:void 0,frames:void 0,self:void 0,location:void 0,navigator:void 0,localStorage:void 0,history:void 0,Caches:void 0,screen:void 0,alert:void 0,confirm:void 0,prompt:void 0,fetch:void 0,XMLHttpRequest:void 0,WebSocket:void 0,webkit:void 0,print:void 0}}}});
|
|
@ -1,154 +0,0 @@
|
|||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // install a JSONP callback for chunk loading
|
||||
/******/ function webpackJsonpCallback(data) {
|
||||
/******/ var chunkIds = data[0];
|
||||
/******/ var moreModules = data[1];
|
||||
/******/ var executeModules = data[2];
|
||||
/******/
|
||||
/******/ // add "moreModules" to the modules object,
|
||||
/******/ // then flag all "chunkIds" as loaded and fire callback
|
||||
/******/ var moduleId, chunkId, i = 0, resolves = [];
|
||||
/******/ for(;i < chunkIds.length; i++) {
|
||||
/******/ chunkId = chunkIds[i];
|
||||
/******/ if(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {
|
||||
/******/ resolves.push(installedChunks[chunkId][0]);
|
||||
/******/ }
|
||||
/******/ installedChunks[chunkId] = 0;
|
||||
/******/ }
|
||||
/******/ for(moduleId in moreModules) {
|
||||
/******/ if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
|
||||
/******/ modules[moduleId] = moreModules[moduleId];
|
||||
/******/ }
|
||||
/******/ }
|
||||
/******/ if(parentJsonpFunction) parentJsonpFunction(data);
|
||||
/******/
|
||||
/******/ while(resolves.length) {
|
||||
/******/ resolves.shift()();
|
||||
/******/ }
|
||||
/******/
|
||||
/******/ // add entry modules from loaded chunk to deferred list
|
||||
/******/ deferredModules.push.apply(deferredModules, executeModules || []);
|
||||
/******/
|
||||
/******/ // run deferred modules when all chunks ready
|
||||
/******/ return checkDeferredModules();
|
||||
/******/ };
|
||||
/******/ function checkDeferredModules() {
|
||||
/******/ var result;
|
||||
/******/ for(var i = 0; i < deferredModules.length; i++) {
|
||||
/******/ var deferredModule = deferredModules[i];
|
||||
/******/ var fulfilled = true;
|
||||
/******/ for(var j = 1; j < deferredModule.length; j++) {
|
||||
/******/ var depId = deferredModule[j];
|
||||
/******/ if(installedChunks[depId] !== 0) fulfilled = false;
|
||||
/******/ }
|
||||
/******/ if(fulfilled) {
|
||||
/******/ deferredModules.splice(i--, 1);
|
||||
/******/ result = __webpack_require__(__webpack_require__.s = deferredModule[0]);
|
||||
/******/ }
|
||||
/******/ }
|
||||
/******/
|
||||
/******/ return result;
|
||||
/******/ }
|
||||
/******/
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
/******/
|
||||
/******/ // object to store loaded and loading chunks
|
||||
/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched
|
||||
/******/ // Promise = chunk loading, 0 = chunk loaded
|
||||
/******/ var installedChunks = {
|
||||
/******/ "app-config": 0
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ var deferredModules = [];
|
||||
/******/
|
||||
/******/ // 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] = {
|
||||
/******/ i: moduleId,
|
||||
/******/ l: false,
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.l = 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;
|
||||
/******/
|
||||
/******/ // define getter function for harmony exports
|
||||
/******/ __webpack_require__.d = function(exports, name, getter) {
|
||||
/******/ if(!__webpack_require__.o(exports, name)) {
|
||||
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // define __esModule on exports
|
||||
/******/ __webpack_require__.r = function(exports) {
|
||||
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
||||
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
||||
/******/ }
|
||||
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // create a fake namespace object
|
||||
/******/ // mode & 1: value is a module id, require it
|
||||
/******/ // mode & 2: merge all properties of value into the ns
|
||||
/******/ // mode & 4: return value when already ns object
|
||||
/******/ // mode & 8|1: behave like require
|
||||
/******/ __webpack_require__.t = function(value, mode) {
|
||||
/******/ if(mode & 1) value = __webpack_require__(value);
|
||||
/******/ if(mode & 8) return value;
|
||||
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
|
||||
/******/ var ns = Object.create(null);
|
||||
/******/ __webpack_require__.r(ns);
|
||||
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
|
||||
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
|
||||
/******/ return ns;
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||
/******/ __webpack_require__.n = function(module) {
|
||||
/******/ var getter = module && module.__esModule ?
|
||||
/******/ function getDefault() { return module['default']; } :
|
||||
/******/ function getModuleExports() { return module; };
|
||||
/******/ __webpack_require__.d(getter, 'a', getter);
|
||||
/******/ return getter;
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Object.prototype.hasOwnProperty.call
|
||||
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
||||
/******/
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "/";
|
||||
/******/
|
||||
/******/ var jsonpArray = this["webpackJsonp"] = this["webpackJsonp"] || [];
|
||||
/******/ var oldJsonpFunction = jsonpArray.push.bind(jsonpArray);
|
||||
/******/ jsonpArray.push = webpackJsonpCallback;
|
||||
/******/ jsonpArray = jsonpArray.slice();
|
||||
/******/ for(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);
|
||||
/******/ var parentJsonpFunction = oldJsonpFunction;
|
||||
/******/
|
||||
/******/
|
||||
/******/ // run deferred modules from other chunks
|
||||
/******/ checkDeferredModules();
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ([]);
|
|
@ -1 +0,0 @@
|
|||
{"@platforms":["android","iPhone","iPad"],"id":"__UNI__9620511","name":"农业咨询","version":{"name":"1.0.0","code":"100"},"description":"","launch_path":"__uniappview.html","developer":{"name":"","email":"","url":""},"permissions":{"UniNView":{"description":"UniNView原生渲染"}},"plus":{"useragent":{"value":"uni-app","concatenate":true},"splashscreen":{"target":"id:1","autoclose":true,"waiting":true,"delay":0},"popGesture":"close","launchwebview":{"render":"always","id":"1","kernel":"WKWebview"},"statusbar":{"immersed":"supportedDevice","style":"dark","background":"#F8F8F8"},"usingComponents":true,"nvueStyleCompiler":"uni-app","compilerVersion":3,"distribute":{"google":{"permissions":["<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>","<uses-permission android:name=\"android.permission.VIBRATE\"/>","<uses-permission android:name=\"android.permission.READ_LOGS\"/>","<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>","<uses-feature android:name=\"android.hardware.camera.autofocus\"/>","<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.CAMERA\"/>","<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>","<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>","<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>","<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>","<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>","<uses-feature android:name=\"android.hardware.camera\"/>","<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"],"abiFilters":["armeabi-v7a","arm64-v8a","x86"]},"apple":{"dSYMs":false},"plugins":{"ad":{},"audio":{"mp3":{"description":"Android平台录音支持MP3格式文件"}}}},"uniStatistics":{"enable":false},"arguments":"{\"name\":\"\",\"path\":\"\",\"query\":\"\",\"id\":0}","allowsInlineMediaPlayback":true,"uni-app":{"compilerVersion":"3.8.12","control":"uni-v3","nvueCompiler":"uni-app","renderer":"auto","nvue":{"flex-direction":"column"},"nvueLaunchMode":"normal"},"launch_path":"__uniappview.html"}}
|
Before Width: | Height: | Size: 13 KiB |
|
@ -1,28 +0,0 @@
|
|||
# Contribution
|
||||
|
||||
# Git Flow
|
||||
|
||||
The crypto-js project uses [git flow](https://github.com/nvie/gitflow) to manage branches.
|
||||
Do your changes on the `develop` or even better on a `feature/*` branch. Don't do any changes on the `master` branch.
|
||||
|
||||
# Pull request
|
||||
|
||||
Target your pull request on `develop` branch. Other pull request won't be accepted.
|
||||
|
||||
# How to build
|
||||
|
||||
1. Clone
|
||||
|
||||
2. Run
|
||||
|
||||
```sh
|
||||
npm install
|
||||
```
|
||||
|
||||
3. Run
|
||||
|
||||
```sh
|
||||
npm run build
|
||||
```
|
||||
|
||||
4. Check `build` folder
|
|
@ -1,24 +0,0 @@
|
|||
# License
|
||||
|
||||
[The MIT License (MIT)](http://opensource.org/licenses/MIT)
|
||||
|
||||
Copyright (c) 2009-2013 Jeff Mott
|
||||
Copyright (c) 2013-2016 Evan Vosberg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
|
@ -1,249 +0,0 @@
|
|||
# crypto-js [![Build Status](https://travis-ci.org/brix/crypto-js.svg?branch=develop)](https://travis-ci.org/brix/crypto-js)
|
||||
|
||||
JavaScript library of crypto standards.
|
||||
|
||||
## Node.js (Install)
|
||||
|
||||
Requirements:
|
||||
|
||||
- Node.js
|
||||
- npm (Node.js package manager)
|
||||
|
||||
```bash
|
||||
npm install crypto-js
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
ES6 import for typical API call signing use case:
|
||||
|
||||
```javascript
|
||||
import sha256 from 'crypto-js/sha256';
|
||||
import hmacSHA512 from 'crypto-js/hmac-sha512';
|
||||
import Base64 from 'crypto-js/enc-base64';
|
||||
|
||||
const message, nonce, path, privateKey; // ...
|
||||
const hashDigest = sha256(nonce + message);
|
||||
const hmacDigest = Base64.stringify(hmacSHA512(path + hashDigest, privateKey));
|
||||
```
|
||||
|
||||
Modular include:
|
||||
|
||||
```javascript
|
||||
var AES = require("crypto-js/aes");
|
||||
var SHA256 = require("crypto-js/sha256");
|
||||
...
|
||||
console.log(SHA256("Message"));
|
||||
```
|
||||
|
||||
Including all libraries, for access to extra methods:
|
||||
|
||||
```javascript
|
||||
var CryptoJS = require("crypto-js");
|
||||
console.log(CryptoJS.HmacSHA1("Message", "Key"));
|
||||
```
|
||||
|
||||
## Client (browser)
|
||||
|
||||
Requirements:
|
||||
|
||||
- Node.js
|
||||
- Bower (package manager for frontend)
|
||||
|
||||
```bash
|
||||
bower install crypto-js
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
Modular include:
|
||||
|
||||
```javascript
|
||||
require.config({
|
||||
packages: [
|
||||
{
|
||||
name: 'crypto-js',
|
||||
location: 'path-to/bower_components/crypto-js',
|
||||
main: 'index'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
require(["crypto-js/aes", "crypto-js/sha256"], function (AES, SHA256) {
|
||||
console.log(SHA256("Message"));
|
||||
});
|
||||
```
|
||||
|
||||
Including all libraries, for access to extra methods:
|
||||
|
||||
```javascript
|
||||
// Above-mentioned will work or use this simple form
|
||||
require.config({
|
||||
paths: {
|
||||
'crypto-js': 'path-to/bower_components/crypto-js/crypto-js'
|
||||
}
|
||||
});
|
||||
|
||||
require(["crypto-js"], function (CryptoJS) {
|
||||
console.log(CryptoJS.HmacSHA1("Message", "Key"));
|
||||
});
|
||||
```
|
||||
|
||||
### Usage without RequireJS
|
||||
|
||||
```html
|
||||
<script type="text/javascript" src="path-to/bower_components/crypto-js/crypto-js.js"></script>
|
||||
<script type="text/javascript">
|
||||
var encrypted = CryptoJS.AES(...);
|
||||
var encrypted = CryptoJS.SHA256(...);
|
||||
</script>
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
See: https://cryptojs.gitbook.io/docs/
|
||||
|
||||
### AES Encryption
|
||||
|
||||
#### Plain text encryption
|
||||
|
||||
```javascript
|
||||
var CryptoJS = require("crypto-js");
|
||||
|
||||
// Encrypt
|
||||
var ciphertext = CryptoJS.AES.encrypt('my message', 'secret key 123').toString();
|
||||
|
||||
// Decrypt
|
||||
var bytes = CryptoJS.AES.decrypt(ciphertext, 'secret key 123');
|
||||
var originalText = bytes.toString(CryptoJS.enc.Utf8);
|
||||
|
||||
console.log(originalText); // 'my message'
|
||||
```
|
||||
|
||||
#### Object encryption
|
||||
|
||||
```javascript
|
||||
var CryptoJS = require("crypto-js");
|
||||
|
||||
var data = [{id: 1}, {id: 2}]
|
||||
|
||||
// Encrypt
|
||||
var ciphertext = CryptoJS.AES.encrypt(JSON.stringify(data), 'secret key 123').toString();
|
||||
|
||||
// Decrypt
|
||||
var bytes = CryptoJS.AES.decrypt(ciphertext, 'secret key 123');
|
||||
var decryptedData = JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
|
||||
|
||||
console.log(decryptedData); // [{id: 1}, {id: 2}]
|
||||
```
|
||||
|
||||
### List of modules
|
||||
|
||||
|
||||
- ```crypto-js/core```
|
||||
- ```crypto-js/x64-core```
|
||||
- ```crypto-js/lib-typedarrays```
|
||||
|
||||
---
|
||||
|
||||
- ```crypto-js/md5```
|
||||
- ```crypto-js/sha1```
|
||||
- ```crypto-js/sha256```
|
||||
- ```crypto-js/sha224```
|
||||
- ```crypto-js/sha512```
|
||||
- ```crypto-js/sha384```
|
||||
- ```crypto-js/sha3```
|
||||
- ```crypto-js/ripemd160```
|
||||
|
||||
---
|
||||
|
||||
- ```crypto-js/hmac-md5```
|
||||
- ```crypto-js/hmac-sha1```
|
||||
- ```crypto-js/hmac-sha256```
|
||||
- ```crypto-js/hmac-sha224```
|
||||
- ```crypto-js/hmac-sha512```
|
||||
- ```crypto-js/hmac-sha384```
|
||||
- ```crypto-js/hmac-sha3```
|
||||
- ```crypto-js/hmac-ripemd160```
|
||||
|
||||
---
|
||||
|
||||
- ```crypto-js/pbkdf2```
|
||||
|
||||
---
|
||||
|
||||
- ```crypto-js/aes```
|
||||
- ```crypto-js/tripledes```
|
||||
- ```crypto-js/rc4```
|
||||
- ```crypto-js/rabbit```
|
||||
- ```crypto-js/rabbit-legacy```
|
||||
- ```crypto-js/evpkdf```
|
||||
|
||||
---
|
||||
|
||||
- ```crypto-js/format-openssl```
|
||||
- ```crypto-js/format-hex```
|
||||
|
||||
---
|
||||
|
||||
- ```crypto-js/enc-latin1```
|
||||
- ```crypto-js/enc-utf8```
|
||||
- ```crypto-js/enc-hex```
|
||||
- ```crypto-js/enc-utf16```
|
||||
- ```crypto-js/enc-base64```
|
||||
|
||||
---
|
||||
|
||||
- ```crypto-js/mode-cfb```
|
||||
- ```crypto-js/mode-ctr```
|
||||
- ```crypto-js/mode-ctr-gladman```
|
||||
- ```crypto-js/mode-ofb```
|
||||
- ```crypto-js/mode-ecb```
|
||||
|
||||
---
|
||||
|
||||
- ```crypto-js/pad-pkcs7```
|
||||
- ```crypto-js/pad-ansix923```
|
||||
- ```crypto-js/pad-iso10126```
|
||||
- ```crypto-js/pad-iso97971```
|
||||
- ```crypto-js/pad-zeropadding```
|
||||
- ```crypto-js/pad-nopadding```
|
||||
|
||||
|
||||
## Release notes
|
||||
|
||||
### 4.0.0
|
||||
|
||||
This is an update including breaking changes for some environments.
|
||||
|
||||
In this version `Math.random()` has been replaced by the random methods of the native crypto module.
|
||||
|
||||
For this reason CryptoJS might does not run in some JavaScript environments without native crypto module. Such as IE 10 or before or React Native.
|
||||
|
||||
### 3.3.0
|
||||
|
||||
Rollback, `3.3.0` is the same as `3.1.9-1`.
|
||||
|
||||
The move of using native secure crypto module will be shifted to a new `4.x.x` version. As it is a breaking change the impact is too big for a minor release.
|
||||
|
||||
### 3.2.1
|
||||
|
||||
The usage of the native crypto module has been fixed. The import and access of the native crypto module has been improved.
|
||||
|
||||
### 3.2.0
|
||||
|
||||
In this version `Math.random()` has been replaced by the random methods of the native crypto module.
|
||||
|
||||
For this reason CryptoJS might does not run in some JavaScript environments without native crypto module. Such as IE 10 or before.
|
||||
|
||||
If it's absolute required to run CryptoJS in such an environment, stay with `3.1.x` version. Encrypting and decrypting stays compatible. But keep in mind `3.1.x` versions still use `Math.random()` which is cryptographically not secure, as it's not random enough.
|
||||
|
||||
This version came along with `CRITICAL` `BUG`.
|
||||
|
||||
DO NOT USE THIS VERSION! Please, go for a newer version!
|
||||
|
||||
### 3.1.x
|
||||
|
||||
The `3.1.x` are based on the original CryptoJS, wrapped in CommonJS modules.
|
||||
|
||||
|
|
@ -1,234 +0,0 @@
|
|||
;(function (root, factory, undef) {
|
||||
if (typeof exports === "object") {
|
||||
// CommonJS
|
||||
module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core"));
|
||||
}
|
||||
else if (typeof define === "function" && define.amd) {
|
||||
// AMD
|
||||
define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory);
|
||||
}
|
||||
else {
|
||||
// Global (browser)
|
||||
factory(root.CryptoJS);
|
||||
}
|
||||
}(this, function (CryptoJS) {
|
||||
|
||||
(function () {
|
||||
// Shortcuts
|
||||
var C = CryptoJS;
|
||||
var C_lib = C.lib;
|
||||
var BlockCipher = C_lib.BlockCipher;
|
||||
var C_algo = C.algo;
|
||||
|
||||
// Lookup tables
|
||||
var SBOX = [];
|
||||
var INV_SBOX = [];
|
||||
var SUB_MIX_0 = [];
|
||||
var SUB_MIX_1 = [];
|
||||
var SUB_MIX_2 = [];
|
||||
var SUB_MIX_3 = [];
|
||||
var INV_SUB_MIX_0 = [];
|
||||
var INV_SUB_MIX_1 = [];
|
||||
var INV_SUB_MIX_2 = [];
|
||||
var INV_SUB_MIX_3 = [];
|
||||
|
||||
// Compute lookup tables
|
||||
(function () {
|
||||
// Compute double table
|
||||
var d = [];
|
||||
for (var i = 0; i < 256; i++) {
|
||||
if (i < 128) {
|
||||
d[i] = i << 1;
|
||||
} else {
|
||||
d[i] = (i << 1) ^ 0x11b;
|
||||
}
|
||||
}
|
||||
|
||||
// Walk GF(2^8)
|
||||
var x = 0;
|
||||
var xi = 0;
|
||||
for (var i = 0; i < 256; i++) {
|
||||
// Compute sbox
|
||||
var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4);
|
||||
sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63;
|
||||
SBOX[x] = sx;
|
||||
INV_SBOX[sx] = x;
|
||||
|
||||
// Compute multiplication
|
||||
var x2 = d[x];
|
||||
var x4 = d[x2];
|
||||
var x8 = d[x4];
|
||||
|
||||
// Compute sub bytes, mix columns tables
|
||||
var t = (d[sx] * 0x101) ^ (sx * 0x1010100);
|
||||
SUB_MIX_0[x] = (t << 24) | (t >>> 8);
|
||||
SUB_MIX_1[x] = (t << 16) | (t >>> 16);
|
||||
SUB_MIX_2[x] = (t << 8) | (t >>> 24);
|
||||
SUB_MIX_3[x] = t;
|
||||
|
||||
// Compute inv sub bytes, inv mix columns tables
|
||||
var t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100);
|
||||
INV_SUB_MIX_0[sx] = (t << 24) | (t >>> 8);
|
||||
INV_SUB_MIX_1[sx] = (t << 16) | (t >>> 16);
|
||||
INV_SUB_MIX_2[sx] = (t << 8) | (t >>> 24);
|
||||
INV_SUB_MIX_3[sx] = t;
|
||||
|
||||
// Compute next counter
|
||||
if (!x) {
|
||||
x = xi = 1;
|
||||
} else {
|
||||
x = x2 ^ d[d[d[x8 ^ x2]]];
|
||||
xi ^= d[d[xi]];
|
||||
}
|
||||
}
|
||||
}());
|
||||
|
||||
// Precomputed Rcon lookup
|
||||
var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36];
|
||||
|
||||
/**
|
||||
* AES block cipher algorithm.
|
||||
*/
|
||||
var AES = C_algo.AES = BlockCipher.extend({
|
||||
_doReset: function () {
|
||||
var t;
|
||||
|
||||
// Skip reset of nRounds has been set before and key did not change
|
||||
if (this._nRounds && this._keyPriorReset === this._key) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Shortcuts
|
||||
var key = this._keyPriorReset = this._key;
|
||||
var keyWords = key.words;
|
||||
var keySize = key.sigBytes / 4;
|
||||
|
||||
// Compute number of rounds
|
||||
var nRounds = this._nRounds = keySize + 6;
|
||||
|
||||
// Compute number of key schedule rows
|
||||
var ksRows = (nRounds + 1) * 4;
|
||||
|
||||
// Compute key schedule
|
||||
var keySchedule = this._keySchedule = [];
|
||||
for (var ksRow = 0; ksRow < ksRows; ksRow++) {
|
||||
if (ksRow < keySize) {
|
||||
keySchedule[ksRow] = keyWords[ksRow];
|
||||
} else {
|
||||
t = keySchedule[ksRow - 1];
|
||||
|
||||
if (!(ksRow % keySize)) {
|
||||
// Rot word
|
||||
t = (t << 8) | (t >>> 24);
|
||||
|
||||
// Sub word
|
||||
t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff];
|
||||
|
||||
// Mix Rcon
|
||||
t ^= RCON[(ksRow / keySize) | 0] << 24;
|
||||
} else if (keySize > 6 && ksRow % keySize == 4) {
|
||||
// Sub word
|
||||
t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff];
|
||||
}
|
||||
|
||||
keySchedule[ksRow] = keySchedule[ksRow - keySize] ^ t;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute inv key schedule
|
||||
var invKeySchedule = this._invKeySchedule = [];
|
||||
for (var invKsRow = 0; invKsRow < ksRows; invKsRow++) {
|
||||
var ksRow = ksRows - invKsRow;
|
||||
|
||||
if (invKsRow % 4) {
|
||||
var t = keySchedule[ksRow];
|
||||
} else {
|
||||
var t = keySchedule[ksRow - 4];
|
||||
}
|
||||
|
||||
if (invKsRow < 4 || ksRow <= 4) {
|
||||
invKeySchedule[invKsRow] = t;
|
||||
} else {
|
||||
invKeySchedule[invKsRow] = INV_SUB_MIX_0[SBOX[t >>> 24]] ^ INV_SUB_MIX_1[SBOX[(t >>> 16) & 0xff]] ^
|
||||
INV_SUB_MIX_2[SBOX[(t >>> 8) & 0xff]] ^ INV_SUB_MIX_3[SBOX[t & 0xff]];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
encryptBlock: function (M, offset) {
|
||||
this._doCryptBlock(M, offset, this._keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX);
|
||||
},
|
||||
|
||||
decryptBlock: function (M, offset) {
|
||||
// Swap 2nd and 4th rows
|
||||
var t = M[offset + 1];
|
||||
M[offset + 1] = M[offset + 3];
|
||||
M[offset + 3] = t;
|
||||
|
||||
this._doCryptBlock(M, offset, this._invKeySchedule, INV_SUB_MIX_0, INV_SUB_MIX_1, INV_SUB_MIX_2, INV_SUB_MIX_3, INV_SBOX);
|
||||
|
||||
// Inv swap 2nd and 4th rows
|
||||
var t = M[offset + 1];
|
||||
M[offset + 1] = M[offset + 3];
|
||||
M[offset + 3] = t;
|
||||
},
|
||||
|
||||
_doCryptBlock: function (M, offset, keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX) {
|
||||
// Shortcut
|
||||
var nRounds = this._nRounds;
|
||||
|
||||
// Get input, add round key
|
||||
var s0 = M[offset] ^ keySchedule[0];
|
||||
var s1 = M[offset + 1] ^ keySchedule[1];
|
||||
var s2 = M[offset + 2] ^ keySchedule[2];
|
||||
var s3 = M[offset + 3] ^ keySchedule[3];
|
||||
|
||||
// Key schedule row counter
|
||||
var ksRow = 4;
|
||||
|
||||
// Rounds
|
||||
for (var round = 1; round < nRounds; round++) {
|
||||
// Shift rows, sub bytes, mix columns, add round key
|
||||
var t0 = SUB_MIX_0[s0 >>> 24] ^ SUB_MIX_1[(s1 >>> 16) & 0xff] ^ SUB_MIX_2[(s2 >>> 8) & 0xff] ^ SUB_MIX_3[s3 & 0xff] ^ keySchedule[ksRow++];
|
||||
var t1 = SUB_MIX_0[s1 >>> 24] ^ SUB_MIX_1[(s2 >>> 16) & 0xff] ^ SUB_MIX_2[(s3 >>> 8) & 0xff] ^ SUB_MIX_3[s0 & 0xff] ^ keySchedule[ksRow++];
|
||||
var t2 = SUB_MIX_0[s2 >>> 24] ^ SUB_MIX_1[(s3 >>> 16) & 0xff] ^ SUB_MIX_2[(s0 >>> 8) & 0xff] ^ SUB_MIX_3[s1 & 0xff] ^ keySchedule[ksRow++];
|
||||
var t3 = SUB_MIX_0[s3 >>> 24] ^ SUB_MIX_1[(s0 >>> 16) & 0xff] ^ SUB_MIX_2[(s1 >>> 8) & 0xff] ^ SUB_MIX_3[s2 & 0xff] ^ keySchedule[ksRow++];
|
||||
|
||||
// Update state
|
||||
s0 = t0;
|
||||
s1 = t1;
|
||||
s2 = t2;
|
||||
s3 = t3;
|
||||
}
|
||||
|
||||
// Shift rows, sub bytes, add round key
|
||||
var t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++];
|
||||
var t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++];
|
||||
var t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++];
|
||||
var t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++];
|
||||
|
||||
// Set output
|
||||
M[offset] = t0;
|
||||
M[offset + 1] = t1;
|
||||
M[offset + 2] = t2;
|
||||
M[offset + 3] = t3;
|
||||
},
|
||||
|
||||
keySize: 256/32
|
||||
});
|
||||
|
||||
/**
|
||||
* Shortcut functions to the cipher's object interface.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var ciphertext = CryptoJS.AES.encrypt(message, key, cfg);
|
||||
* var plaintext = CryptoJS.AES.decrypt(ciphertext, key, cfg);
|
||||
*/
|
||||
C.AES = BlockCipher._createHelper(AES);
|
||||
}());
|
||||
|
||||
|
||||
return CryptoJS.AES;
|
||||
|
||||
}));
|
|
@ -1,35 +0,0 @@
|
|||
{
|
||||
"name": "crypto-js",
|
||||
"version": "4.0.0",
|
||||
"description": "JavaScript library of crypto standards.",
|
||||
"license": "MIT",
|
||||
"homepage": "http://github.com/brix/crypto-js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "http://github.com/brix/crypto-js.git"
|
||||
},
|
||||
"keywords": [
|
||||
"security",
|
||||
"crypto",
|
||||
"Hash",
|
||||
"MD5",
|
||||
"SHA1",
|
||||
"SHA-1",
|
||||
"SHA256",
|
||||
"SHA-256",
|
||||
"RC4",
|
||||
"Rabbit",
|
||||
"AES",
|
||||
"DES",
|
||||
"PBKDF2",
|
||||
"HMAC",
|
||||
"OFB",
|
||||
"CFB",
|
||||
"CTR",
|
||||
"CBC",
|
||||
"Base64"
|
||||
],
|
||||
"main": "index.js",
|
||||
"dependencies": {},
|
||||
"ignore": []
|
||||
}
|
|
@ -1,890 +0,0 @@
|
|||
;(function (root, factory, undef) {
|
||||
if (typeof exports === "object") {
|
||||
// CommonJS
|
||||
module.exports = exports = factory(require("./core"), require("./evpkdf"));
|
||||
}
|
||||
else if (typeof define === "function" && define.amd) {
|
||||
// AMD
|
||||
define(["./core", "./evpkdf"], factory);
|
||||
}
|
||||
else {
|
||||
// Global (browser)
|
||||
factory(root.CryptoJS);
|
||||
}
|
||||
}(this, function (CryptoJS) {
|
||||
|
||||
/**
|
||||
* Cipher core components.
|
||||
*/
|
||||
CryptoJS.lib.Cipher || (function (undefined) {
|
||||
// Shortcuts
|
||||
var C = CryptoJS;
|
||||
var C_lib = C.lib;
|
||||
var Base = C_lib.Base;
|
||||
var WordArray = C_lib.WordArray;
|
||||
var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm;
|
||||
var C_enc = C.enc;
|
||||
var Utf8 = C_enc.Utf8;
|
||||
var Base64 = C_enc.Base64;
|
||||
var C_algo = C.algo;
|
||||
var EvpKDF = C_algo.EvpKDF;
|
||||
|
||||
/**
|
||||
* Abstract base cipher template.
|
||||
*
|
||||
* @property {number} keySize This cipher's key size. Default: 4 (128 bits)
|
||||
* @property {number} ivSize This cipher's IV size. Default: 4 (128 bits)
|
||||
* @property {number} _ENC_XFORM_MODE A constant representing encryption mode.
|
||||
* @property {number} _DEC_XFORM_MODE A constant representing decryption mode.
|
||||
*/
|
||||
var Cipher = C_lib.Cipher = BufferedBlockAlgorithm.extend({
|
||||
/**
|
||||
* Configuration options.
|
||||
*
|
||||
* @property {WordArray} iv The IV to use for this operation.
|
||||
*/
|
||||
cfg: Base.extend(),
|
||||
|
||||
/**
|
||||
* Creates this cipher in encryption mode.
|
||||
*
|
||||
* @param {WordArray} key The key.
|
||||
* @param {Object} cfg (Optional) The configuration options to use for this operation.
|
||||
*
|
||||
* @return {Cipher} A cipher instance.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var cipher = CryptoJS.algo.AES.createEncryptor(keyWordArray, { iv: ivWordArray });
|
||||
*/
|
||||
createEncryptor: function (key, cfg) {
|
||||
return this.create(this._ENC_XFORM_MODE, key, cfg);
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates this cipher in decryption mode.
|
||||
*
|
||||
* @param {WordArray} key The key.
|
||||
* @param {Object} cfg (Optional) The configuration options to use for this operation.
|
||||
*
|
||||
* @return {Cipher} A cipher instance.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var cipher = CryptoJS.algo.AES.createDecryptor(keyWordArray, { iv: ivWordArray });
|
||||
*/
|
||||
createDecryptor: function (key, cfg) {
|
||||
return this.create(this._DEC_XFORM_MODE, key, cfg);
|
||||
},
|
||||
|
||||
/**
|
||||
* Initializes a newly created cipher.
|
||||
*
|
||||
* @param {number} xformMode Either the encryption or decryption transormation mode constant.
|
||||
* @param {WordArray} key The key.
|
||||
* @param {Object} cfg (Optional) The configuration options to use for this operation.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var cipher = CryptoJS.algo.AES.create(CryptoJS.algo.AES._ENC_XFORM_MODE, keyWordArray, { iv: ivWordArray });
|
||||
*/
|
||||
init: function (xformMode, key, cfg) {
|
||||
// Apply config defaults
|
||||
this.cfg = this.cfg.extend(cfg);
|
||||
|
||||
// Store transform mode and key
|
||||
this._xformMode = xformMode;
|
||||
this._key = key;
|
||||
|
||||
// Set initial values
|
||||
this.reset();
|
||||
},
|
||||
|
||||
/**
|
||||
* Resets this cipher to its initial state.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* cipher.reset();
|
||||
*/
|
||||
reset: function () {
|
||||
// Reset data buffer
|
||||
BufferedBlockAlgorithm.reset.call(this);
|
||||
|
||||
// Perform concrete-cipher logic
|
||||
this._doReset();
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds data to be encrypted or decrypted.
|
||||
*
|
||||
* @param {WordArray|string} dataUpdate The data to encrypt or decrypt.
|
||||
*
|
||||
* @return {WordArray} The data after processing.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var encrypted = cipher.process('data');
|
||||
* var encrypted = cipher.process(wordArray);
|
||||
*/
|
||||
process: function (dataUpdate) {
|
||||
// Append
|
||||
this._append(dataUpdate);
|
||||
|
||||
// Process available blocks
|
||||
return this._process();
|
||||
},
|
||||
|
||||
/**
|
||||
* Finalizes the encryption or decryption process.
|
||||
* Note that the finalize operation is effectively a destructive, read-once operation.
|
||||
*
|
||||
* @param {WordArray|string} dataUpdate The final data to encrypt or decrypt.
|
||||
*
|
||||
* @return {WordArray} The data after final processing.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var encrypted = cipher.finalize();
|
||||
* var encrypted = cipher.finalize('data');
|
||||
* var encrypted = cipher.finalize(wordArray);
|
||||
*/
|
||||
finalize: function (dataUpdate) {
|
||||
// Final data update
|
||||
if (dataUpdate) {
|
||||
this._append(dataUpdate);
|
||||
}
|
||||
|
||||
// Perform concrete-cipher logic
|
||||
var finalProcessedData = this._doFinalize();
|
||||
|
||||
return finalProcessedData;
|
||||
},
|
||||
|
||||
keySize: 128/32,
|
||||
|
||||
ivSize: 128/32,
|
||||
|
||||
_ENC_XFORM_MODE: 1,
|
||||
|
||||
_DEC_XFORM_MODE: 2,
|
||||
|
||||
/**
|
||||
* Creates shortcut functions to a cipher's object interface.
|
||||
*
|
||||
* @param {Cipher} cipher The cipher to create a helper for.
|
||||
*
|
||||
* @return {Object} An object with encrypt and decrypt shortcut functions.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var AES = CryptoJS.lib.Cipher._createHelper(CryptoJS.algo.AES);
|
||||
*/
|
||||
_createHelper: (function () {
|
||||
function selectCipherStrategy(key) {
|
||||
if (typeof key == 'string') {
|
||||
return PasswordBasedCipher;
|
||||
} else {
|
||||
return SerializableCipher;
|
||||
}
|
||||
}
|
||||
|
||||
return function (cipher) {
|
||||
return {
|
||||
encrypt: function (message, key, cfg) {
|
||||
return selectCipherStrategy(key).encrypt(cipher, message, key, cfg);
|
||||
},
|
||||
|
||||
decrypt: function (ciphertext, key, cfg) {
|
||||
return selectCipherStrategy(key).decrypt(cipher, ciphertext, key, cfg);
|
||||
}
|
||||
};
|
||||
};
|
||||
}())
|
||||
});
|
||||
|
||||
/**
|
||||
* Abstract base stream cipher template.
|
||||
*
|
||||
* @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 1 (32 bits)
|
||||
*/
|
||||
var StreamCipher = C_lib.StreamCipher = Cipher.extend({
|
||||
_doFinalize: function () {
|
||||
// Process partial blocks
|
||||
var finalProcessedBlocks = this._process(!!'flush');
|
||||
|
||||
return finalProcessedBlocks;
|
||||
},
|
||||
|
||||
blockSize: 1
|
||||
});
|
||||
|
||||
/**
|
||||
* Mode namespace.
|
||||
*/
|
||||
var C_mode = C.mode = {};
|
||||
|
||||
/**
|
||||
* Abstract base block cipher mode template.
|
||||
*/
|
||||
var BlockCipherMode = C_lib.BlockCipherMode = Base.extend({
|
||||
/**
|
||||
* Creates this mode for encryption.
|
||||
*
|
||||
* @param {Cipher} cipher A block cipher instance.
|
||||
* @param {Array} iv The IV words.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var mode = CryptoJS.mode.CBC.createEncryptor(cipher, iv.words);
|
||||
*/
|
||||
createEncryptor: function (cipher, iv) {
|
||||
return this.Encryptor.create(cipher, iv);
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates this mode for decryption.
|
||||
*
|
||||
* @param {Cipher} cipher A block cipher instance.
|
||||
* @param {Array} iv The IV words.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var mode = CryptoJS.mode.CBC.createDecryptor(cipher, iv.words);
|
||||
*/
|
||||
createDecryptor: function (cipher, iv) {
|
||||
return this.Decryptor.create(cipher, iv);
|
||||
},
|
||||
|
||||
/**
|
||||
* Initializes a newly created mode.
|
||||
*
|
||||
* @param {Cipher} cipher A block cipher instance.
|
||||
* @param {Array} iv The IV words.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var mode = CryptoJS.mode.CBC.Encryptor.create(cipher, iv.words);
|
||||
*/
|
||||
init: function (cipher, iv) {
|
||||
this._cipher = cipher;
|
||||
this._iv = iv;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Cipher Block Chaining mode.
|
||||
*/
|
||||
var CBC = C_mode.CBC = (function () {
|
||||
/**
|
||||
* Abstract base CBC mode.
|
||||
*/
|
||||
var CBC = BlockCipherMode.extend();
|
||||
|
||||
/**
|
||||
* CBC encryptor.
|
||||
*/
|
||||
CBC.Encryptor = CBC.extend({
|
||||
/**
|
||||
* Processes the data block at offset.
|
||||
*
|
||||
* @param {Array} words The data words to operate on.
|
||||
* @param {number} offset The offset where the block starts.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* mode.processBlock(data.words, offset);
|
||||
*/
|
||||
processBlock: function (words, offset) {
|
||||
// Shortcuts
|
||||
var cipher = this._cipher;
|
||||
var blockSize = cipher.blockSize;
|
||||
|
||||
// XOR and encrypt
|
||||
xorBlock.call(this, words, offset, blockSize);
|
||||
cipher.encryptBlock(words, offset);
|
||||
|
||||
// Remember this block to use with next block
|
||||
this._prevBlock = words.slice(offset, offset + blockSize);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* CBC decryptor.
|
||||
*/
|
||||
CBC.Decryptor = CBC.extend({
|
||||
/**
|
||||
* Processes the data block at offset.
|
||||
*
|
||||
* @param {Array} words The data words to operate on.
|
||||
* @param {number} offset The offset where the block starts.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* mode.processBlock(data.words, offset);
|
||||
*/
|
||||
processBlock: function (words, offset) {
|
||||
// Shortcuts
|
||||
var cipher = this._cipher;
|
||||
var blockSize = cipher.blockSize;
|
||||
|
||||
// Remember this block to use with next block
|
||||
var thisBlock = words.slice(offset, offset + blockSize);
|
||||
|
||||
// Decrypt and XOR
|
||||
cipher.decryptBlock(words, offset);
|
||||
xorBlock.call(this, words, offset, blockSize);
|
||||
|
||||
// This block becomes the previous block
|
||||
this._prevBlock = thisBlock;
|
||||
}
|
||||
});
|
||||
|
||||
function xorBlock(words, offset, blockSize) {
|
||||
var block;
|
||||
|
||||
// Shortcut
|
||||
var iv = this._iv;
|
||||
|
||||
// Choose mixing block
|
||||
if (iv) {
|
||||
block = iv;
|
||||
|
||||
// Remove IV for subsequent blocks
|
||||
this._iv = undefined;
|
||||
} else {
|
||||
block = this._prevBlock;
|
||||
}
|
||||
|
||||
// XOR blocks
|
||||
for (var i = 0; i < blockSize; i++) {
|
||||
words[offset + i] ^= block[i];
|
||||
}
|
||||
}
|
||||
|
||||
return CBC;
|
||||
}());
|
||||
|
||||
/**
|
||||
* Padding namespace.
|
||||
*/
|
||||
var C_pad = C.pad = {};
|
||||
|
||||
/**
|
||||
* PKCS #5/7 padding strategy.
|
||||
*/
|
||||
var Pkcs7 = C_pad.Pkcs7 = {
|
||||
/**
|
||||
* Pads data using the algorithm defined in PKCS #5/7.
|
||||
*
|
||||
* @param {WordArray} data The data to pad.
|
||||
* @param {number} blockSize The multiple that the data should be padded to.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* CryptoJS.pad.Pkcs7.pad(wordArray, 4);
|
||||
*/
|
||||
pad: function (data, blockSize) {
|
||||
// Shortcut
|
||||
var blockSizeBytes = blockSize * 4;
|
||||
|
||||
// Count padding bytes
|
||||
var nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes;
|
||||
|
||||
// Create padding word
|
||||
var paddingWord = (nPaddingBytes << 24) | (nPaddingBytes << 16) | (nPaddingBytes << 8) | nPaddingBytes;
|
||||
|
||||
// Create padding
|
||||
var paddingWords = [];
|
||||
for (var i = 0; i < nPaddingBytes; i += 4) {
|
||||
paddingWords.push(paddingWord);
|
||||
}
|
||||
var padding = WordArray.create(paddingWords, nPaddingBytes);
|
||||
|
||||
// Add padding
|
||||
data.concat(padding);
|
||||
},
|
||||
|
||||
/**
|
||||
* Unpads data that had been padded using the algorithm defined in PKCS #5/7.
|
||||
*
|
||||
* @param {WordArray} data The data to unpad.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* CryptoJS.pad.Pkcs7.unpad(wordArray);
|
||||
*/
|
||||
unpad: function (data) {
|
||||
// Get number of padding bytes from last byte
|
||||
var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff;
|
||||
|
||||
// Remove padding
|
||||
data.sigBytes -= nPaddingBytes;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Abstract base block cipher template.
|
||||
*
|
||||
* @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 4 (128 bits)
|
||||
*/
|
||||
var BlockCipher = C_lib.BlockCipher = Cipher.extend({
|
||||
/**
|
||||
* Configuration options.
|
||||
*
|
||||
* @property {Mode} mode The block mode to use. Default: CBC
|
||||
* @property {Padding} padding The padding strategy to use. Default: Pkcs7
|
||||
*/
|
||||
cfg: Cipher.cfg.extend({
|
||||
mode: CBC,
|
||||
padding: Pkcs7
|
||||
}),
|
||||
|
||||
reset: function () {
|
||||
var modeCreator;
|
||||
|
||||
// Reset cipher
|
||||
Cipher.reset.call(this);
|
||||
|
||||
// Shortcuts
|
||||
var cfg = this.cfg;
|
||||
var iv = cfg.iv;
|
||||
var mode = cfg.mode;
|
||||
|
||||
// Reset block mode
|
||||
if (this._xformMode == this._ENC_XFORM_MODE) {
|
||||
modeCreator = mode.createEncryptor;
|
||||
} else /* if (this._xformMode == this._DEC_XFORM_MODE) */ {
|
||||
modeCreator = mode.createDecryptor;
|
||||
// Keep at least one block in the buffer for unpadding
|
||||
this._minBufferSize = 1;
|
||||
}
|
||||
|
||||
if (this._mode && this._mode.__creator == modeCreator) {
|
||||
this._mode.init(this, iv && iv.words);
|
||||
} else {
|
||||
this._mode = modeCreator.call(mode, this, iv && iv.words);
|
||||
this._mode.__creator = modeCreator;
|
||||
}
|
||||
},
|
||||
|
||||
_doProcessBlock: function (words, offset) {
|
||||
this._mode.processBlock(words, offset);
|
||||
},
|
||||
|
||||
_doFinalize: function () {
|
||||
var finalProcessedBlocks;
|
||||
|
||||
// Shortcut
|
||||
var padding = this.cfg.padding;
|
||||
|
||||
// Finalize
|
||||
if (this._xformMode == this._ENC_XFORM_MODE) {
|
||||
// Pad data
|
||||
padding.pad(this._data, this.blockSize);
|
||||
|
||||
// Process final blocks
|
||||
finalProcessedBlocks = this._process(!!'flush');
|
||||
} else /* if (this._xformMode == this._DEC_XFORM_MODE) */ {
|
||||
// Process final blocks
|
||||
finalProcessedBlocks = this._process(!!'flush');
|
||||
|
||||
// Unpad data
|
||||
padding.unpad(finalProcessedBlocks);
|
||||
}
|
||||
|
||||
return finalProcessedBlocks;
|
||||
},
|
||||
|
||||
blockSize: 128/32
|
||||
});
|
||||
|
||||
/**
|
||||
* A collection of cipher parameters.
|
||||
*
|
||||
* @property {WordArray} ciphertext The raw ciphertext.
|
||||
* @property {WordArray} key The key to this ciphertext.
|
||||
* @property {WordArray} iv The IV used in the ciphering operation.
|
||||
* @property {WordArray} salt The salt used with a key derivation function.
|
||||
* @property {Cipher} algorithm The cipher algorithm.
|
||||
* @property {Mode} mode The block mode used in the ciphering operation.
|
||||
* @property {Padding} padding The padding scheme used in the ciphering operation.
|
||||
* @property {number} blockSize The block size of the cipher.
|
||||
* @property {Format} formatter The default formatting strategy to convert this cipher params object to a string.
|
||||
*/
|
||||
var CipherParams = C_lib.CipherParams = Base.extend({
|
||||
/**
|
||||
* Initializes a newly created cipher params object.
|
||||
*
|
||||
* @param {Object} cipherParams An object with any of the possible cipher parameters.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var cipherParams = CryptoJS.lib.CipherParams.create({
|
||||
* ciphertext: ciphertextWordArray,
|
||||
* key: keyWordArray,
|
||||
* iv: ivWordArray,
|
||||
* salt: saltWordArray,
|
||||
* algorithm: CryptoJS.algo.AES,
|
||||
* mode: CryptoJS.mode.CBC,
|
||||
* padding: CryptoJS.pad.PKCS7,
|
||||
* blockSize: 4,
|
||||
* formatter: CryptoJS.format.OpenSSL
|
||||
* });
|
||||
*/
|
||||
init: function (cipherParams) {
|
||||
this.mixIn(cipherParams);
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts this cipher params object to a string.
|
||||
*
|
||||
* @param {Format} formatter (Optional) The formatting strategy to use.
|
||||
*
|
||||
* @return {string} The stringified cipher params.
|
||||
*
|
||||
* @throws Error If neither the formatter nor the default formatter is set.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var string = cipherParams + '';
|
||||
* var string = cipherParams.toString();
|
||||
* var string = cipherParams.toString(CryptoJS.format.OpenSSL);
|
||||
*/
|
||||
toString: function (formatter) {
|
||||
return (formatter || this.formatter).stringify(this);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Format namespace.
|
||||
*/
|
||||
var C_format = C.format = {};
|
||||
|
||||
/**
|
||||
* OpenSSL formatting strategy.
|
||||
*/
|
||||
var OpenSSLFormatter = C_format.OpenSSL = {
|
||||
/**
|
||||
* Converts a cipher params object to an OpenSSL-compatible string.
|
||||
*
|
||||
* @param {CipherParams} cipherParams The cipher params object.
|
||||
*
|
||||
* @return {string} The OpenSSL-compatible string.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var openSSLString = CryptoJS.format.OpenSSL.stringify(cipherParams);
|
||||
*/
|
||||
stringify: function (cipherParams) {
|
||||
var wordArray;
|
||||
|
||||
// Shortcuts
|
||||
var ciphertext = cipherParams.ciphertext;
|
||||
var salt = cipherParams.salt;
|
||||
|
||||
// Format
|
||||
if (salt) {
|
||||
wordArray = WordArray.create([0x53616c74, 0x65645f5f]).concat(salt).concat(ciphertext);
|
||||
} else {
|
||||
wordArray = ciphertext;
|
||||
}
|
||||
|
||||
return wordArray.toString(Base64);
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts an OpenSSL-compatible string to a cipher params object.
|
||||
*
|
||||
* @param {string} openSSLStr The OpenSSL-compatible string.
|
||||
*
|
||||
* @return {CipherParams} The cipher params object.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var cipherParams = CryptoJS.format.OpenSSL.parse(openSSLString);
|
||||
*/
|
||||
parse: function (openSSLStr) {
|
||||
var salt;
|
||||
|
||||
// Parse base64
|
||||
var ciphertext = Base64.parse(openSSLStr);
|
||||
|
||||
// Shortcut
|
||||
var ciphertextWords = ciphertext.words;
|
||||
|
||||
// Test for salt
|
||||
if (ciphertextWords[0] == 0x53616c74 && ciphertextWords[1] == 0x65645f5f) {
|
||||
// Extract salt
|
||||
salt = WordArray.create(ciphertextWords.slice(2, 4));
|
||||
|
||||
// Remove salt from ciphertext
|
||||
ciphertextWords.splice(0, 4);
|
||||
ciphertext.sigBytes -= 16;
|
||||
}
|
||||
|
||||
return CipherParams.create({ ciphertext: ciphertext, salt: salt });
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A cipher wrapper that returns ciphertext as a serializable cipher params object.
|
||||
*/
|
||||
var SerializableCipher = C_lib.SerializableCipher = Base.extend({
|
||||
/**
|
||||
* Configuration options.
|
||||
*
|
||||
* @property {Formatter} format The formatting strategy to convert cipher param objects to and from a string. Default: OpenSSL
|
||||
*/
|
||||
cfg: Base.extend({
|
||||
format: OpenSSLFormatter
|
||||
}),
|
||||
|
||||
/**
|
||||
* Encrypts a message.
|
||||
*
|
||||
* @param {Cipher} cipher The cipher algorithm to use.
|
||||
* @param {WordArray|string} message The message to encrypt.
|
||||
* @param {WordArray} key The key.
|
||||
* @param {Object} cfg (Optional) The configuration options to use for this operation.
|
||||
*
|
||||
* @return {CipherParams} A cipher params object.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key);
|
||||
* var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv });
|
||||
* var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv, format: CryptoJS.format.OpenSSL });
|
||||
*/
|
||||
encrypt: function (cipher, message, key, cfg) {
|
||||
// Apply config defaults
|
||||
cfg = this.cfg.extend(cfg);
|
||||
|
||||
// Encrypt
|
||||
var encryptor = cipher.createEncryptor(key, cfg);
|
||||
var ciphertext = encryptor.finalize(message);
|
||||
|
||||
// Shortcut
|
||||
var cipherCfg = encryptor.cfg;
|
||||
|
||||
// Create and return serializable cipher params
|
||||
return CipherParams.create({
|
||||
ciphertext: ciphertext,
|
||||
key: key,
|
||||
iv: cipherCfg.iv,
|
||||
algorithm: cipher,
|
||||
mode: cipherCfg.mode,
|
||||
padding: cipherCfg.padding,
|
||||
blockSize: cipher.blockSize,
|
||||
formatter: cfg.format
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Decrypts serialized ciphertext.
|
||||
*
|
||||
* @param {Cipher} cipher The cipher algorithm to use.
|
||||
* @param {CipherParams|string} ciphertext The ciphertext to decrypt.
|
||||
* @param {WordArray} key The key.
|
||||
* @param {Object} cfg (Optional) The configuration options to use for this operation.
|
||||
*
|
||||
* @return {WordArray} The plaintext.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, key, { iv: iv, format: CryptoJS.format.OpenSSL });
|
||||
* var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, key, { iv: iv, format: CryptoJS.format.OpenSSL });
|
||||
*/
|
||||
decrypt: function (cipher, ciphertext, key, cfg) {
|
||||
// Apply config defaults
|
||||
cfg = this.cfg.extend(cfg);
|
||||
|
||||
// Convert string to CipherParams
|
||||
ciphertext = this._parse(ciphertext, cfg.format);
|
||||
|
||||
// Decrypt
|
||||
var plaintext = cipher.createDecryptor(key, cfg).finalize(ciphertext.ciphertext);
|
||||
|
||||
return plaintext;
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts serialized ciphertext to CipherParams,
|
||||
* else assumed CipherParams already and returns ciphertext unchanged.
|
||||
*
|
||||
* @param {CipherParams|string} ciphertext The ciphertext.
|
||||
* @param {Formatter} format The formatting strategy to use to parse serialized ciphertext.
|
||||
*
|
||||
* @return {CipherParams} The unserialized ciphertext.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var ciphertextParams = CryptoJS.lib.SerializableCipher._parse(ciphertextStringOrParams, format);
|
||||
*/
|
||||
_parse: function (ciphertext, format) {
|
||||
if (typeof ciphertext == 'string') {
|
||||
return format.parse(ciphertext, this);
|
||||
} else {
|
||||
return ciphertext;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Key derivation function namespace.
|
||||
*/
|
||||
var C_kdf = C.kdf = {};
|
||||
|
||||
/**
|
||||
* OpenSSL key derivation function.
|
||||
*/
|
||||
var OpenSSLKdf = C_kdf.OpenSSL = {
|
||||
/**
|
||||
* Derives a key and IV from a password.
|
||||
*
|
||||
* @param {string} password The password to derive from.
|
||||
* @param {number} keySize The size in words of the key to generate.
|
||||
* @param {number} ivSize The size in words of the IV to generate.
|
||||
* @param {WordArray|string} salt (Optional) A 64-bit salt to use. If omitted, a salt will be generated randomly.
|
||||
*
|
||||
* @return {CipherParams} A cipher params object with the key, IV, and salt.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32);
|
||||
* var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32, 'saltsalt');
|
||||
*/
|
||||
execute: function (password, keySize, ivSize, salt) {
|
||||
// Generate random salt
|
||||
if (!salt) {
|
||||
salt = WordArray.random(64/8);
|
||||
}
|
||||
|
||||
// Derive key and IV
|
||||
var key = EvpKDF.create({ keySize: keySize + ivSize }).compute(password, salt);
|
||||
|
||||
// Separate key and IV
|
||||
var iv = WordArray.create(key.words.slice(keySize), ivSize * 4);
|
||||
key.sigBytes = keySize * 4;
|
||||
|
||||
// Return params
|
||||
return CipherParams.create({ key: key, iv: iv, salt: salt });
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A serializable cipher wrapper that derives the key from a password,
|
||||
* and returns ciphertext as a serializable cipher params object.
|
||||
*/
|
||||
var PasswordBasedCipher = C_lib.PasswordBasedCipher = SerializableCipher.extend({
|
||||
/**
|
||||
* Configuration options.
|
||||
*
|
||||
* @property {KDF} kdf The key derivation function to use to generate a key and IV from a password. Default: OpenSSL
|
||||
*/
|
||||
cfg: SerializableCipher.cfg.extend({
|
||||
kdf: OpenSSLKdf
|
||||
}),
|
||||
|
||||
/**
|
||||
* Encrypts a message using a password.
|
||||
*
|
||||
* @param {Cipher} cipher The cipher algorithm to use.
|
||||
* @param {WordArray|string} message The message to encrypt.
|
||||
* @param {string} password The password.
|
||||
* @param {Object} cfg (Optional) The configuration options to use for this operation.
|
||||
*
|
||||
* @return {CipherParams} A cipher params object.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password');
|
||||
* var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password', { format: CryptoJS.format.OpenSSL });
|
||||
*/
|
||||
encrypt: function (cipher, message, password, cfg) {
|
||||
// Apply config defaults
|
||||
cfg = this.cfg.extend(cfg);
|
||||
|
||||
// Derive key and other params
|
||||
var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize);
|
||||
|
||||
// Add IV to config
|
||||
cfg.iv = derivedParams.iv;
|
||||
|
||||
// Encrypt
|
||||
var ciphertext = SerializableCipher.encrypt.call(this, cipher, message, derivedParams.key, cfg);
|
||||
|
||||
// Mix in derived params
|
||||
ciphertext.mixIn(derivedParams);
|
||||
|
||||
return ciphertext;
|
||||
},
|
||||
|
||||
/**
|
||||
* Decrypts serialized ciphertext using a password.
|
||||
*
|
||||
* @param {Cipher} cipher The cipher algorithm to use.
|
||||
* @param {CipherParams|string} ciphertext The ciphertext to decrypt.
|
||||
* @param {string} password The password.
|
||||
* @param {Object} cfg (Optional) The configuration options to use for this operation.
|
||||
*
|
||||
* @return {WordArray} The plaintext.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, 'password', { format: CryptoJS.format.OpenSSL });
|
||||
* var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, 'password', { format: CryptoJS.format.OpenSSL });
|
||||
*/
|
||||
decrypt: function (cipher, ciphertext, password, cfg) {
|
||||
// Apply config defaults
|
||||
cfg = this.cfg.extend(cfg);
|
||||
|
||||
// Convert string to CipherParams
|
||||
ciphertext = this._parse(ciphertext, cfg.format);
|
||||
|
||||
// Derive key and other params
|
||||
var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, ciphertext.salt);
|
||||
|
||||
// Add IV to config
|
||||
cfg.iv = derivedParams.iv;
|
||||
|
||||
// Decrypt
|
||||
var plaintext = SerializableCipher.decrypt.call(this, cipher, ciphertext, derivedParams.key, cfg);
|
||||
|
||||
return plaintext;
|
||||
}
|
||||
});
|
||||
}());
|
||||
|
||||
|
||||
}));
|
|
@ -1,797 +0,0 @@
|
|||
;(function (root, factory) {
|
||||
if (typeof exports === "object") {
|
||||
// CommonJS
|
||||
module.exports = exports = factory();
|
||||
}
|
||||
else if (typeof define === "function" && define.amd) {
|
||||
// AMD
|
||||
define([], factory);
|
||||
}
|
||||
else {
|
||||
// Global (browser)
|
||||
root.CryptoJS = factory();
|
||||
}
|
||||
}(this, function () {
|
||||
|
||||
/*globals window, global, require*/
|
||||
|
||||
/**
|
||||
* CryptoJS core components.
|
||||
*/
|
||||
var CryptoJS = CryptoJS || (function (Math, undefined) {
|
||||
|
||||
var crypto;
|
||||
|
||||
// Native crypto from window (Browser)
|
||||
if (typeof window !== 'undefined' && window.crypto) {
|
||||
crypto = window.crypto;
|
||||
}
|
||||
|
||||
// Native (experimental IE 11) crypto from window (Browser)
|
||||
if (!crypto && typeof window !== 'undefined' && window.msCrypto) {
|
||||
crypto = window.msCrypto;
|
||||
}
|
||||
|
||||
// Native crypto from global (NodeJS)
|
||||
if (!crypto && typeof global !== 'undefined' && global.crypto) {
|
||||
crypto = global.crypto;
|
||||
}
|
||||
|
||||
// Native crypto import via require (NodeJS)
|
||||
if (!crypto && typeof require === 'function') {
|
||||
try {
|
||||
crypto = require('crypto');
|
||||
} catch (err) {}
|
||||
}
|
||||
|
||||
/*
|
||||
* Cryptographically secure pseudorandom number generator
|
||||
*
|
||||
* As Math.random() is cryptographically not safe to use
|
||||
*/
|
||||
var cryptoSecureRandomInt = function () {
|
||||
if (crypto) {
|
||||
// Use getRandomValues method (Browser)
|
||||
if (typeof crypto.getRandomValues === 'function') {
|
||||
try {
|
||||
return crypto.getRandomValues(new Uint32Array(1))[0];
|
||||
} catch (err) {}
|
||||
}
|
||||
|
||||
// Use randomBytes method (NodeJS)
|
||||
if (typeof crypto.randomBytes === 'function') {
|
||||
try {
|
||||
return crypto.randomBytes(4).readInt32LE();
|
||||
} catch (err) {}
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error('Native crypto module could not be used to get secure random number.');
|
||||
};
|
||||
|
||||
/*
|
||||
* Local polyfill of Object.create
|
||||
|
||||
*/
|
||||
var create = Object.create || (function () {
|
||||
function F() {}
|
||||
|
||||
return function (obj) {
|
||||
var subtype;
|
||||
|
||||
F.prototype = obj;
|
||||
|
||||
subtype = new F();
|
||||
|
||||
F.prototype = null;
|
||||
|
||||
return subtype;
|
||||
};
|
||||
}())
|
||||
|
||||
/**
|
||||
* CryptoJS namespace.
|
||||
*/
|
||||
var C = {};
|
||||
|
||||
/**
|
||||
* Library namespace.
|
||||
*/
|
||||
var C_lib = C.lib = {};
|
||||
|
||||
/**
|
||||
* Base object for prototypal inheritance.
|
||||
*/
|
||||
var Base = C_lib.Base = (function () {
|
||||
|
||||
|
||||
return {
|
||||
/**
|
||||
* Creates a new object that inherits from this object.
|
||||
*
|
||||
* @param {Object} overrides Properties to copy into the new object.
|
||||
*
|
||||
* @return {Object} The new object.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var MyType = CryptoJS.lib.Base.extend({
|
||||
* field: 'value',
|
||||
*
|
||||
* method: function () {
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
extend: function (overrides) {
|
||||
// Spawn
|
||||
var subtype = create(this);
|
||||
|
||||
// Augment
|
||||
if (overrides) {
|
||||
subtype.mixIn(overrides);
|
||||
}
|
||||
|
||||
// Create default initializer
|
||||
if (!subtype.hasOwnProperty('init') || this.init === subtype.init) {
|
||||
subtype.init = function () {
|
||||
subtype.$super.init.apply(this, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
// Initializer's prototype is the subtype object
|
||||
subtype.init.prototype = subtype;
|
||||
|
||||
// Reference supertype
|
||||
subtype.$super = this;
|
||||
|
||||
return subtype;
|
||||
},
|
||||
|
||||
/**
|
||||
* Extends this object and runs the init method.
|
||||
* Arguments to create() will be passed to init().
|
||||
*
|
||||
* @return {Object} The new object.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var instance = MyType.create();
|
||||
*/
|
||||
create: function () {
|
||||
var instance = this.extend();
|
||||
instance.init.apply(instance, arguments);
|
||||
|
||||
return instance;
|
||||
},
|
||||
|
||||
/**
|
||||
* Initializes a newly created object.
|
||||
* Override this method to add some logic when your objects are created.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var MyType = CryptoJS.lib.Base.extend({
|
||||
* init: function () {
|
||||
* // ...
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
init: function () {
|
||||
},
|
||||
|
||||
/**
|
||||
* Copies properties into this object.
|
||||
*
|
||||
* @param {Object} properties The properties to mix in.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* MyType.mixIn({
|
||||
* field: 'value'
|
||||
* });
|
||||
*/
|
||||
mixIn: function (properties) {
|
||||
for (var propertyName in properties) {
|
||||
if (properties.hasOwnProperty(propertyName)) {
|
||||
this[propertyName] = properties[propertyName];
|
||||
}
|
||||
}
|
||||
|
||||
// IE won't copy toString using the loop above
|
||||
if (properties.hasOwnProperty('toString')) {
|
||||
this.toString = properties.toString;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a copy of this object.
|
||||
*
|
||||
* @return {Object} The clone.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var clone = instance.clone();
|
||||
*/
|
||||
clone: function () {
|
||||
return this.init.prototype.extend(this);
|
||||
}
|
||||
};
|
||||
}());
|
||||
|
||||
/**
|
||||
* An array of 32-bit words.
|
||||
*
|
||||
* @property {Array} words The array of 32-bit words.
|
||||
* @property {number} sigBytes The number of significant bytes in this word array.
|
||||
*/
|
||||
var WordArray = C_lib.WordArray = Base.extend({
|
||||
/**
|
||||
* Initializes a newly created word array.
|
||||
*
|
||||
* @param {Array} words (Optional) An array of 32-bit words.
|
||||
* @param {number} sigBytes (Optional) The number of significant bytes in the words.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var wordArray = CryptoJS.lib.WordArray.create();
|
||||
* var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]);
|
||||
* var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6);
|
||||
*/
|
||||
init: function (words, sigBytes) {
|
||||
words = this.words = words || [];
|
||||
|
||||
if (sigBytes != undefined) {
|
||||
this.sigBytes = sigBytes;
|
||||
} else {
|
||||
this.sigBytes = words.length * 4;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts this word array to a string.
|
||||
*
|
||||
* @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex
|
||||
*
|
||||
* @return {string} The stringified word array.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var string = wordArray + '';
|
||||
* var string = wordArray.toString();
|
||||
* var string = wordArray.toString(CryptoJS.enc.Utf8);
|
||||
*/
|
||||
toString: function (encoder) {
|
||||
return (encoder || Hex).stringify(this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Concatenates a word array to this word array.
|
||||
*
|
||||
* @param {WordArray} wordArray The word array to append.
|
||||
*
|
||||
* @return {WordArray} This word array.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* wordArray1.concat(wordArray2);
|
||||
*/
|
||||
concat: function (wordArray) {
|
||||
// Shortcuts
|
||||
var thisWords = this.words;
|
||||
var thatWords = wordArray.words;
|
||||
var thisSigBytes = this.sigBytes;
|
||||
var thatSigBytes = wordArray.sigBytes;
|
||||
|
||||
// Clamp excess bits
|
||||
this.clamp();
|
||||
|
||||
// Concat
|
||||
if (thisSigBytes % 4) {
|
||||
// Copy one byte at a time
|
||||
for (var i = 0; i < thatSigBytes; i++) {
|
||||
var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
|
||||
thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8);
|
||||
}
|
||||
} else {
|
||||
// Copy one word at a time
|
||||
for (var i = 0; i < thatSigBytes; i += 4) {
|
||||
thisWords[(thisSigBytes + i) >>> 2] = thatWords[i >>> 2];
|
||||
}
|
||||
}
|
||||
this.sigBytes += thatSigBytes;
|
||||
|
||||
// Chainable
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes insignificant bits.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* wordArray.clamp();
|
||||
*/
|
||||
clamp: function () {
|
||||
// Shortcuts
|
||||
var words = this.words;
|
||||
var sigBytes = this.sigBytes;
|
||||
|
||||
// Clamp
|
||||
words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8);
|
||||
words.length = Math.ceil(sigBytes / 4);
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a copy of this word array.
|
||||
*
|
||||
* @return {WordArray} The clone.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var clone = wordArray.clone();
|
||||
*/
|
||||
clone: function () {
|
||||
var clone = Base.clone.call(this);
|
||||
clone.words = this.words.slice(0);
|
||||
|
||||
return clone;
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a word array filled with random bytes.
|
||||
*
|
||||
* @param {number} nBytes The number of random bytes to generate.
|
||||
*
|
||||
* @return {WordArray} The random word array.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var wordArray = CryptoJS.lib.WordArray.random(16);
|
||||
*/
|
||||
random: function (nBytes) {
|
||||
var words = [];
|
||||
|
||||
for (var i = 0; i < nBytes; i += 4) {
|
||||
words.push(cryptoSecureRandomInt());
|
||||
}
|
||||
|
||||
return new WordArray.init(words, nBytes);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Encoder namespace.
|
||||
*/
|
||||
var C_enc = C.enc = {};
|
||||
|
||||
/**
|
||||
* Hex encoding strategy.
|
||||
*/
|
||||
var Hex = C_enc.Hex = {
|
||||
/**
|
||||
* Converts a word array to a hex string.
|
||||
*
|
||||
* @param {WordArray} wordArray The word array.
|
||||
*
|
||||
* @return {string} The hex string.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hexString = CryptoJS.enc.Hex.stringify(wordArray);
|
||||
*/
|
||||
stringify: function (wordArray) {
|
||||
// Shortcuts
|
||||
var words = wordArray.words;
|
||||
var sigBytes = wordArray.sigBytes;
|
||||
|
||||
// Convert
|
||||
var hexChars = [];
|
||||
for (var i = 0; i < sigBytes; i++) {
|
||||
var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
|
||||
hexChars.push((bite >>> 4).toString(16));
|
||||
hexChars.push((bite & 0x0f).toString(16));
|
||||
}
|
||||
|
||||
return hexChars.join('');
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a hex string to a word array.
|
||||
*
|
||||
* @param {string} hexStr The hex string.
|
||||
*
|
||||
* @return {WordArray} The word array.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var wordArray = CryptoJS.enc.Hex.parse(hexString);
|
||||
*/
|
||||
parse: function (hexStr) {
|
||||
// Shortcut
|
||||
var hexStrLength = hexStr.length;
|
||||
|
||||
// Convert
|
||||
var words = [];
|
||||
for (var i = 0; i < hexStrLength; i += 2) {
|
||||
words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4);
|
||||
}
|
||||
|
||||
return new WordArray.init(words, hexStrLength / 2);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Latin1 encoding strategy.
|
||||
*/
|
||||
var Latin1 = C_enc.Latin1 = {
|
||||
/**
|
||||
* Converts a word array to a Latin1 string.
|
||||
*
|
||||
* @param {WordArray} wordArray The word array.
|
||||
*
|
||||
* @return {string} The Latin1 string.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var latin1String = CryptoJS.enc.Latin1.stringify(wordArray);
|
||||
*/
|
||||
stringify: function (wordArray) {
|
||||
// Shortcuts
|
||||
var words = wordArray.words;
|
||||
var sigBytes = wordArray.sigBytes;
|
||||
|
||||
// Convert
|
||||
var latin1Chars = [];
|
||||
for (var i = 0; i < sigBytes; i++) {
|
||||
var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
|
||||
latin1Chars.push(String.fromCharCode(bite));
|
||||
}
|
||||
|
||||
return latin1Chars.join('');
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a Latin1 string to a word array.
|
||||
*
|
||||
* @param {string} latin1Str The Latin1 string.
|
||||
*
|
||||
* @return {WordArray} The word array.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var wordArray = CryptoJS.enc.Latin1.parse(latin1String);
|
||||
*/
|
||||
parse: function (latin1Str) {
|
||||
// Shortcut
|
||||
var latin1StrLength = latin1Str.length;
|
||||
|
||||
// Convert
|
||||
var words = [];
|
||||
for (var i = 0; i < latin1StrLength; i++) {
|
||||
words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8);
|
||||
}
|
||||
|
||||
return new WordArray.init(words, latin1StrLength);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* UTF-8 encoding strategy.
|
||||
*/
|
||||
var Utf8 = C_enc.Utf8 = {
|
||||
/**
|
||||
* Converts a word array to a UTF-8 string.
|
||||
*
|
||||
* @param {WordArray} wordArray The word array.
|
||||
*
|
||||
* @return {string} The UTF-8 string.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var utf8String = CryptoJS.enc.Utf8.stringify(wordArray);
|
||||
*/
|
||||
stringify: function (wordArray) {
|
||||
try {
|
||||
return decodeURIComponent(escape(Latin1.stringify(wordArray)));
|
||||
} catch (e) {
|
||||
throw new Error('Malformed UTF-8 data');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a UTF-8 string to a word array.
|
||||
*
|
||||
* @param {string} utf8Str The UTF-8 string.
|
||||
*
|
||||
* @return {WordArray} The word array.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var wordArray = CryptoJS.enc.Utf8.parse(utf8String);
|
||||
*/
|
||||
parse: function (utf8Str) {
|
||||
return Latin1.parse(unescape(encodeURIComponent(utf8Str)));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Abstract buffered block algorithm template.
|
||||
*
|
||||
* The property blockSize must be implemented in a concrete subtype.
|
||||
*
|
||||
* @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0
|
||||
*/
|
||||
var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({
|
||||
/**
|
||||
* Resets this block algorithm's data buffer to its initial state.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* bufferedBlockAlgorithm.reset();
|
||||
*/
|
||||
reset: function () {
|
||||
// Initial values
|
||||
this._data = new WordArray.init();
|
||||
this._nDataBytes = 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds new data to this block algorithm's buffer.
|
||||
*
|
||||
* @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* bufferedBlockAlgorithm._append('data');
|
||||
* bufferedBlockAlgorithm._append(wordArray);
|
||||
*/
|
||||
_append: function (data) {
|
||||
// Convert string to WordArray, else assume WordArray already
|
||||
if (typeof data == 'string') {
|
||||
data = Utf8.parse(data);
|
||||
}
|
||||
|
||||
// Append
|
||||
this._data.concat(data);
|
||||
this._nDataBytes += data.sigBytes;
|
||||
},
|
||||
|
||||
/**
|
||||
* Processes available data blocks.
|
||||
*
|
||||
* This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype.
|
||||
*
|
||||
* @param {boolean} doFlush Whether all blocks and partial blocks should be processed.
|
||||
*
|
||||
* @return {WordArray} The processed data.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var processedData = bufferedBlockAlgorithm._process();
|
||||
* var processedData = bufferedBlockAlgorithm._process(!!'flush');
|
||||
*/
|
||||
_process: function (doFlush) {
|
||||
var processedWords;
|
||||
|
||||
// Shortcuts
|
||||
var data = this._data;
|
||||
var dataWords = data.words;
|
||||
var dataSigBytes = data.sigBytes;
|
||||
var blockSize = this.blockSize;
|
||||
var blockSizeBytes = blockSize * 4;
|
||||
|
||||
// Count blocks ready
|
||||
var nBlocksReady = dataSigBytes / blockSizeBytes;
|
||||
if (doFlush) {
|
||||
// Round up to include partial blocks
|
||||
nBlocksReady = Math.ceil(nBlocksReady);
|
||||
} else {
|
||||
// Round down to include only full blocks,
|
||||
// less the number of blocks that must remain in the buffer
|
||||
nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0);
|
||||
}
|
||||
|
||||
// Count words ready
|
||||
var nWordsReady = nBlocksReady * blockSize;
|
||||
|
||||
// Count bytes ready
|
||||
var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes);
|
||||
|
||||
// Process blocks
|
||||
if (nWordsReady) {
|
||||
for (var offset = 0; offset < nWordsReady; offset += blockSize) {
|
||||
// Perform concrete-algorithm logic
|
||||
this._doProcessBlock(dataWords, offset);
|
||||
}
|
||||
|
||||
// Remove processed words
|
||||
processedWords = dataWords.splice(0, nWordsReady);
|
||||
data.sigBytes -= nBytesReady;
|
||||
}
|
||||
|
||||
// Return processed words
|
||||
return new WordArray.init(processedWords, nBytesReady);
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a copy of this object.
|
||||
*
|
||||
* @return {Object} The clone.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var clone = bufferedBlockAlgorithm.clone();
|
||||
*/
|
||||
clone: function () {
|
||||
var clone = Base.clone.call(this);
|
||||
clone._data = this._data.clone();
|
||||
|
||||
return clone;
|
||||
},
|
||||
|
||||
_minBufferSize: 0
|
||||
});
|
||||
|
||||
/**
|
||||
* Abstract hasher template.
|
||||
*
|
||||
* @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits)
|
||||
*/
|
||||
var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({
|
||||
/**
|
||||
* Configuration options.
|
||||
*/
|
||||
cfg: Base.extend(),
|
||||
|
||||
/**
|
||||
* Initializes a newly created hasher.
|
||||
*
|
||||
* @param {Object} cfg (Optional) The configuration options to use for this hash computation.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hasher = CryptoJS.algo.SHA256.create();
|
||||
*/
|
||||
init: function (cfg) {
|
||||
// Apply config defaults
|
||||
this.cfg = this.cfg.extend(cfg);
|
||||
|
||||
// Set initial values
|
||||
this.reset();
|
||||
},
|
||||
|
||||
/**
|
||||
* Resets this hasher to its initial state.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* hasher.reset();
|
||||
*/
|
||||
reset: function () {
|
||||
// Reset data buffer
|
||||
BufferedBlockAlgorithm.reset.call(this);
|
||||
|
||||
// Perform concrete-hasher logic
|
||||
this._doReset();
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates this hasher with a message.
|
||||
*
|
||||
* @param {WordArray|string} messageUpdate The message to append.
|
||||
*
|
||||
* @return {Hasher} This hasher.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* hasher.update('message');
|
||||
* hasher.update(wordArray);
|
||||
*/
|
||||
update: function (messageUpdate) {
|
||||
// Append
|
||||
this._append(messageUpdate);
|
||||
|
||||
// Update the hash
|
||||
this._process();
|
||||
|
||||
// Chainable
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Finalizes the hash computation.
|
||||
* Note that the finalize operation is effectively a destructive, read-once operation.
|
||||
*
|
||||
* @param {WordArray|string} messageUpdate (Optional) A final message update.
|
||||
*
|
||||
* @return {WordArray} The hash.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hash = hasher.finalize();
|
||||
* var hash = hasher.finalize('message');
|
||||
* var hash = hasher.finalize(wordArray);
|
||||
*/
|
||||
finalize: function (messageUpdate) {
|
||||
// Final message update
|
||||
if (messageUpdate) {
|
||||
this._append(messageUpdate);
|
||||
}
|
||||
|
||||
// Perform concrete-hasher logic
|
||||
var hash = this._doFinalize();
|
||||
|
||||
return hash;
|
||||
},
|
||||
|
||||
blockSize: 512/32,
|
||||
|
||||
/**
|
||||
* Creates a shortcut function to a hasher's object interface.
|
||||
*
|
||||
* @param {Hasher} hasher The hasher to create a helper for.
|
||||
*
|
||||
* @return {Function} The shortcut function.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256);
|
||||
*/
|
||||
_createHelper: function (hasher) {
|
||||
return function (message, cfg) {
|
||||
return new hasher.init(cfg).finalize(message);
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a shortcut function to the HMAC's object interface.
|
||||
*
|
||||
* @param {Hasher} hasher The hasher to use in this HMAC helper.
|
||||
*
|
||||
* @return {Function} The shortcut function.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256);
|
||||
*/
|
||||
_createHmacHelper: function (hasher) {
|
||||
return function (message, key) {
|
||||
return new C_algo.HMAC.init(hasher, key).finalize(message);
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Algorithm namespace.
|
||||
*/
|
||||
var C_algo = C.algo = {};
|
||||
|
||||
return C;
|
||||
}(Math));
|
||||
|
||||
|
||||
return CryptoJS;
|
||||
|
||||
}));
|
|
@ -1,470 +0,0 @@
|
|||
<wiki:toc/>
|
||||
|
||||
----
|
||||
|
||||
= Quick-start Guide =
|
||||
|
||||
== Hashers ==
|
||||
|
||||
=== The Hasher Algorithms ===
|
||||
|
||||
==== MD5 ====
|
||||
|
||||
MD5 is a widely used hash function. It's been used in a variety of security applications and is also commonly used to check the integrity of files. Though, MD5 is not collision resistant, and it isn't suitable for applications like SSL certificates or digital signatures that rely on this property.
|
||||
|
||||
{{{
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/md5.js"></script>
|
||||
<script>
|
||||
var hash = CryptoJS.MD5("Message");
|
||||
</script>
|
||||
}}}
|
||||
|
||||
==== SHA-1 ====
|
||||
|
||||
The SHA hash functions were designed by the National Security Agency (NSA). SHA-1 is the most established of the existing SHA hash functions, and it's used in a variety of security applications and protocols. Though, SHA-1's collision resistance has been weakening as new attacks are discovered or improved.
|
||||
|
||||
{{{
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/sha1.js"></script>
|
||||
<script>
|
||||
var hash = CryptoJS.SHA1("Message");
|
||||
</script>
|
||||
}}}
|
||||
|
||||
==== SHA-2 ====
|
||||
|
||||
SHA-256 is one of the four variants in the SHA-2 set. It isn't as widely used as SHA-1, though it appears to provide much better security.
|
||||
|
||||
{{{
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/sha256.js"></script>
|
||||
<script>
|
||||
var hash = CryptoJS.SHA256("Message");
|
||||
</script>
|
||||
}}}
|
||||
|
||||
SHA-512 is largely identical to SHA-256 but operates on 64-bit words rather than 32.
|
||||
|
||||
{{{
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/sha512.js"></script>
|
||||
<script>
|
||||
var hash = CryptoJS.SHA512("Message");
|
||||
</script>
|
||||
}}}
|
||||
|
||||
CryptoJS also supports SHA-224 and SHA-384, which are largely identical but truncated versions of SHA-256 and SHA-512 respectively.
|
||||
|
||||
==== SHA-3 ====
|
||||
|
||||
SHA-3 is the winner of a five-year competition to select a new cryptographic hash algorithm where 64 competing designs were evaluated.
|
||||
|
||||
{{{
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/sha3.js"></script>
|
||||
<script>
|
||||
var hash = CryptoJS.SHA3("Message");
|
||||
</script>
|
||||
}}}
|
||||
|
||||
SHA-3 can be configured to output hash lengths of one of 224, 256, 384, or 512 bits. The default is 512 bits.
|
||||
|
||||
{{{
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/sha3.js"></script>
|
||||
<script>
|
||||
var hash = CryptoJS.SHA3("Message", { outputLength: 512 });
|
||||
var hash = CryptoJS.SHA3("Message", { outputLength: 384 });
|
||||
var hash = CryptoJS.SHA3("Message", { outputLength: 256 });
|
||||
var hash = CryptoJS.SHA3("Message", { outputLength: 224 });
|
||||
</script>
|
||||
}}}
|
||||
|
||||
==== RIPEMD-160 ====
|
||||
|
||||
{{{
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/ripemd160.js"></script>
|
||||
<script>
|
||||
var hash = CryptoJS.RIPEMD160("Message");
|
||||
</script>
|
||||
}}}
|
||||
|
||||
=== The Hasher Input ===
|
||||
|
||||
The hash algorithms accept either strings or instances of CryptoJS.lib.WordArray. A WordArray object represents an array of 32-bit words. When you pass a string, it's automatically converted to a WordArray encoded as UTF-8.
|
||||
|
||||
=== The Hasher Output ===
|
||||
|
||||
The hash you get back isn't a string yet. It's a WordArray object. When you use a WordArray object in a string context, it's automatically converted to a hex string.
|
||||
|
||||
{{{
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/sha256.js"></script>
|
||||
<script>
|
||||
var hash = CryptoJS.SHA256("Message");
|
||||
|
||||
alert(typeof hash); // object
|
||||
|
||||
alert(hash); // 2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91
|
||||
</script>
|
||||
}}}
|
||||
|
||||
You can convert a WordArray object to other formats by explicitly calling the toString method and passing an encoder.
|
||||
|
||||
{{{
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/sha256.js"></script>
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/enc-base64-min.js"></script>
|
||||
<script>
|
||||
var hash = CryptoJS.SHA256("Message");
|
||||
|
||||
alert(hash.toString(CryptoJS.enc.Base64)); // L3dmip37+NWEi57rSnFFypTG7ZI25Kdz9tyvpRMrL5E=
|
||||
|
||||
alert(hash.toString(CryptoJS.enc.Latin1)); // /wf<77><66>ûøÕ<C3B8><C395><EFBFBD>ëJqEÊ<45>Æí<C386>6ä§söܯ¥+/<2F>
|
||||
|
||||
alert(hash.toString(CryptoJS.enc.Hex)); // 2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91
|
||||
</script>
|
||||
}}}
|
||||
|
||||
=== Progressive Hashing ===
|
||||
|
||||
{{{
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/sha256.js"></script>
|
||||
<script>
|
||||
var sha256 = CryptoJS.algo.SHA256.create();
|
||||
|
||||
sha256.update("Message Part 1");
|
||||
sha256.update("Message Part 2");
|
||||
sha256.update("Message Part 3");
|
||||
|
||||
var hash = sha256.finalize();
|
||||
</script>
|
||||
}}}
|
||||
|
||||
== HMAC ==
|
||||
|
||||
Keyed-hash message authentication codes (HMAC) is a mechanism for message authentication using cryptographic hash functions.
|
||||
|
||||
HMAC can be used in combination with any iterated cryptographic hash function.
|
||||
|
||||
{{{
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/hmac-md5.js"></script>
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/hmac-sha1.js"></script>
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/hmac-sha256.js"></script>
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/hmac-sha512.js"></script>
|
||||
<script>
|
||||
var hash = CryptoJS.HmacMD5("Message", "Secret Passphrase");
|
||||
var hash = CryptoJS.HmacSHA1("Message", "Secret Passphrase");
|
||||
var hash = CryptoJS.HmacSHA256("Message", "Secret Passphrase");
|
||||
var hash = CryptoJS.HmacSHA512("Message", "Secret Passphrase");
|
||||
</script>
|
||||
}}}
|
||||
|
||||
=== Progressive HMAC Hashing ===
|
||||
|
||||
{{{
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/hmac-sha256.js"></script>
|
||||
<script>
|
||||
var hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, "Secret Passphrase");
|
||||
|
||||
hmac.update("Message Part 1");
|
||||
hmac.update("Message Part 2");
|
||||
hmac.update("Message Part 3");
|
||||
|
||||
var hash = hmac.finalize();
|
||||
</script>
|
||||
}}}
|
||||
|
||||
== PBKDF2 ==
|
||||
|
||||
PBKDF2 is a password-based key derivation function. In many applications of cryptography, user security is ultimately dependent on a password, and because a password usually can't be used directly as a cryptographic key, some processing is required.
|
||||
|
||||
A salt provides a large set of keys for any given password, and an iteration count increases the cost of producing keys from a password, thereby also increasing the difficulty of attack.
|
||||
|
||||
{{{
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/pbkdf2.js"></script>
|
||||
<script>
|
||||
var salt = CryptoJS.lib.WordArray.random(128/8);
|
||||
|
||||
var key128Bits = CryptoJS.PBKDF2("Secret Passphrase", salt, { keySize: 128/32 });
|
||||
var key256Bits = CryptoJS.PBKDF2("Secret Passphrase", salt, { keySize: 256/32 });
|
||||
var key512Bits = CryptoJS.PBKDF2("Secret Passphrase", salt, { keySize: 512/32 });
|
||||
|
||||
var key512Bits1000Iterations = CryptoJS.PBKDF2("Secret Passphrase", salt, { keySize: 512/32, iterations: 1000 });
|
||||
</script>
|
||||
}}}
|
||||
|
||||
== Ciphers ==
|
||||
|
||||
=== The Cipher Algorithms ===
|
||||
|
||||
==== AES ====
|
||||
|
||||
The Advanced Encryption Standard (AES) is a U.S. Federal Information Processing Standard (FIPS). It was selected after a 5-year process where 15 competing designs were evaluated.
|
||||
|
||||
{{{
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/aes.js"></script>
|
||||
<script>
|
||||
var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase");
|
||||
|
||||
var decrypted = CryptoJS.AES.decrypt(encrypted, "Secret Passphrase");
|
||||
</script>
|
||||
}}}
|
||||
|
||||
CryptoJS supports AES-128, AES-192, and AES-256. It will pick the variant by the size of the key you pass in. If you use a passphrase, then it will generate a 256-bit key.
|
||||
|
||||
==== DES, Triple DES ====
|
||||
|
||||
DES is a previously dominant algorithm for encryption, and was published as an official Federal Information Processing Standard (FIPS). DES is now considered to be insecure due to the small key size.
|
||||
|
||||
{{{
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/tripledes.js"></script>
|
||||
<script>
|
||||
var encrypted = CryptoJS.DES.encrypt("Message", "Secret Passphrase");
|
||||
|
||||
var decrypted = CryptoJS.DES.decrypt(encrypted, "Secret Passphrase");
|
||||
</script>
|
||||
}}}
|
||||
|
||||
Triple DES applies DES three times to each block to increase the key size. The algorithm is believed to be secure in this form.
|
||||
|
||||
{{{
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/tripledes.js"></script>
|
||||
<script>
|
||||
var encrypted = CryptoJS.TripleDES.encrypt("Message", "Secret Passphrase");
|
||||
|
||||
var decrypted = CryptoJS.TripleDES.decrypt(encrypted, "Secret Passphrase");
|
||||
</script>
|
||||
}}}
|
||||
|
||||
==== Rabbit ====
|
||||
|
||||
Rabbit is a high-performance stream cipher and a finalist in the eSTREAM Portfolio. It is one of the four designs selected after a 3 1/2-year process where 22 designs were evaluated.
|
||||
|
||||
{{{
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/rabbit.js"></script>
|
||||
<script>
|
||||
var encrypted = CryptoJS.Rabbit.encrypt("Message", "Secret Passphrase");
|
||||
|
||||
var decrypted = CryptoJS.Rabbit.decrypt(encrypted, "Secret Passphrase");
|
||||
</script>
|
||||
}}}
|
||||
|
||||
==== RC4, RC4Drop ====
|
||||
|
||||
RC4 is a widely-used stream cipher. It's used in popular protocols such as SSL and WEP. Although remarkable for its simplicity and speed, the algorithm's history doesn't inspire confidence in its security.
|
||||
|
||||
{{{
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/rc4.js"></script>
|
||||
<script>
|
||||
var encrypted = CryptoJS.RC4.encrypt("Message", "Secret Passphrase");
|
||||
|
||||
var decrypted = CryptoJS.RC4.decrypt(encrypted, "Secret Passphrase");
|
||||
</script>
|
||||
}}}
|
||||
|
||||
It was discovered that the first few bytes of keystream are strongly non-random and leak information about the key. We can defend against this attack by discarding the initial portion of the keystream. This modified algorithm is traditionally called RC4-drop.
|
||||
|
||||
By default, 192 words (768 bytes) are dropped, but you can configure the algorithm to drop any number of words.
|
||||
|
||||
{{{
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/rc4.js"></script>
|
||||
<script>
|
||||
var encrypted = CryptoJS.RC4Drop.encrypt("Message", "Secret Passphrase");
|
||||
|
||||
var encrypted = CryptoJS.RC4Drop.encrypt("Message", "Secret Passphrase", { drop: 3072/4 });
|
||||
|
||||
var decrypted = CryptoJS.RC4Drop.decrypt(encrypted, "Secret Passphrase", { drop: 3072/4 });
|
||||
</script>
|
||||
}}}
|
||||
|
||||
=== Custom Key and IV ===
|
||||
|
||||
{{{
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/aes.js"></script>
|
||||
<script>
|
||||
var key = CryptoJS.enc.Hex.parse('000102030405060708090a0b0c0d0e0f');
|
||||
var iv = CryptoJS.enc.Hex.parse('101112131415161718191a1b1c1d1e1f');
|
||||
|
||||
var encrypted = CryptoJS.AES.encrypt("Message", key, { iv: iv });
|
||||
</script>
|
||||
}}}
|
||||
|
||||
=== Block Modes and Padding ===
|
||||
|
||||
{{{
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/aes.js"></script>
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/mode-cfb-min.js"></script>
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/pad-ansix923-min.js"></script>
|
||||
<script>
|
||||
var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase", { mode: CryptoJS.mode.CFB, padding: CryptoJS.pad.AnsiX923 });
|
||||
</script>
|
||||
}}}
|
||||
|
||||
CryptoJS supports the following modes:
|
||||
|
||||
* CBC (the default)
|
||||
* CFB
|
||||
* CTR
|
||||
* OFB
|
||||
* ECB
|
||||
|
||||
And CryptoJS supports the following padding schemes:
|
||||
|
||||
* Pkcs7 (the default)
|
||||
* Iso97971
|
||||
* AnsiX923
|
||||
* Iso10126
|
||||
* ZeroPadding
|
||||
* NoPadding
|
||||
|
||||
=== The Cipher Input ===
|
||||
|
||||
For the plaintext message, the cipher algorithms accept either strings or instances of CryptoJS.lib.WordArray.
|
||||
|
||||
For the key, when you pass a string, it's treated as a passphrase and used to derive an actual key and IV. Or you can pass a WordArray that represents the actual key. If you pass the actual key, you must also pass the actual IV.
|
||||
|
||||
For the ciphertext, the cipher algorithms accept either strings or instances of CryptoJS.lib.CipherParams. A CipherParams object represents a collection of parameters such as the IV, a salt, and the raw ciphertext itself. When you pass a string, it's automatically converted to a CipherParams object according to a configurable format strategy.
|
||||
|
||||
=== The Cipher Output ===
|
||||
|
||||
The plaintext you get back after decryption is a WordArray object. See Hashers' Output for more detail.
|
||||
|
||||
The ciphertext you get back after encryption isn't a string yet. It's a CipherParams object. A CipherParams object gives you access to all the parameters used during encryption. When you use a CipherParams object in a string context, it's automatically converted to a string according to a format strategy. The default is an OpenSSL-compatible format.
|
||||
|
||||
{{{
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/aes.js"></script>
|
||||
<script>
|
||||
var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase");
|
||||
|
||||
alert(encrypted.key); // 74eb593087a982e2a6f5dded54ecd96d1fd0f3d44a58728cdcd40c55227522223
|
||||
alert(encrypted.iv); // 7781157e2629b094f0e3dd48c4d786115
|
||||
alert(encrypted.salt); // 7a25f9132ec6a8b34
|
||||
alert(encrypted.ciphertext); // 73e54154a15d1beeb509d9e12f1e462a0
|
||||
|
||||
alert(encrypted); // U2FsdGVkX1+iX5Ey7GqLND5UFUoV0b7rUJ2eEvHkYqA=
|
||||
</script>
|
||||
}}}
|
||||
|
||||
You can define your own formats in order to be compatible with other crypto implementations. A format is an object with two methods—stringify and parse—that converts between CipherParams objects and ciphertext strings.
|
||||
|
||||
Here's how you might write a JSON formatter:
|
||||
|
||||
{{{
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/aes.js"></script>
|
||||
<script>
|
||||
var JsonFormatter = {
|
||||
stringify: function (cipherParams) {
|
||||
// create json object with ciphertext
|
||||
var jsonObj = {
|
||||
ct: cipherParams.ciphertext.toString(CryptoJS.enc.Base64)
|
||||
};
|
||||
|
||||
// optionally add iv and salt
|
||||
if (cipherParams.iv) {
|
||||
jsonObj.iv = cipherParams.iv.toString();
|
||||
}
|
||||
if (cipherParams.salt) {
|
||||
jsonObj.s = cipherParams.salt.toString();
|
||||
}
|
||||
|
||||
// stringify json object
|
||||
return JSON.stringify(jsonObj);
|
||||
},
|
||||
|
||||
parse: function (jsonStr) {
|
||||
// parse json string
|
||||
var jsonObj = JSON.parse(jsonStr);
|
||||
|
||||
// extract ciphertext from json object, and create cipher params object
|
||||
var cipherParams = CryptoJS.lib.CipherParams.create({
|
||||
ciphertext: CryptoJS.enc.Base64.parse(jsonObj.ct)
|
||||
});
|
||||
|
||||
// optionally extract iv and salt
|
||||
if (jsonObj.iv) {
|
||||
cipherParams.iv = CryptoJS.enc.Hex.parse(jsonObj.iv)
|
||||
}
|
||||
if (jsonObj.s) {
|
||||
cipherParams.salt = CryptoJS.enc.Hex.parse(jsonObj.s)
|
||||
}
|
||||
|
||||
return cipherParams;
|
||||
}
|
||||
};
|
||||
|
||||
var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase", { format: JsonFormatter });
|
||||
|
||||
alert(encrypted); // {"ct":"tZ4MsEnfbcDOwqau68aOrQ==","iv":"8a8c8fd8fe33743d3638737ea4a00698","s":"ba06373c8f57179c"}
|
||||
|
||||
var decrypted = CryptoJS.AES.decrypt(encrypted, "Secret Passphrase", { format: JsonFormatter });
|
||||
|
||||
alert(decrypted.toString(CryptoJS.enc.Utf8)); // Message
|
||||
</script>
|
||||
}}}
|
||||
|
||||
=== Progressive Ciphering ===
|
||||
|
||||
{{{
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/aes.js"></script>
|
||||
<script>
|
||||
var key = CryptoJS.enc.Hex.parse('000102030405060708090a0b0c0d0e0f');
|
||||
var iv = CryptoJS.enc.Hex.parse('101112131415161718191a1b1c1d1e1f');
|
||||
|
||||
var aesEncryptor = CryptoJS.algo.AES.createEncryptor(key, { iv: iv });
|
||||
|
||||
var ciphertextPart1 = aesEncryptor.process("Message Part 1");
|
||||
var ciphertextPart2 = aesEncryptor.process("Message Part 2");
|
||||
var ciphertextPart3 = aesEncryptor.process("Message Part 3");
|
||||
var ciphertextPart4 = aesEncryptor.finalize();
|
||||
|
||||
var aesDecryptor = CryptoJS.algo.AES.createDecryptor(key, { iv: iv });
|
||||
|
||||
var plaintextPart1 = aesDecryptor.process(ciphertextPart1);
|
||||
var plaintextPart2 = aesDecryptor.process(ciphertextPart2);
|
||||
var plaintextPart3 = aesDecryptor.process(ciphertextPart3);
|
||||
var plaintextPart4 = aesDecryptor.process(ciphertextPart4);
|
||||
var plaintextPart5 = aesDecryptor.finalize();
|
||||
</script>
|
||||
}}}
|
||||
|
||||
=== Interoperability ===
|
||||
|
||||
==== With OpenSSL ====
|
||||
|
||||
Encrypt with OpenSSL:
|
||||
|
||||
{{{
|
||||
openssl enc -aes-256-cbc -in infile -out outfile -pass pass:"Secret Passphrase" -e -base64
|
||||
}}}
|
||||
|
||||
Decrypt with CryptoJS:
|
||||
|
||||
{{{
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/aes.js"></script>
|
||||
<script>
|
||||
var decrypted = CryptoJS.AES.decrypt(openSSLEncrypted, "Secret Passphrase");
|
||||
</script>
|
||||
}}}
|
||||
|
||||
== Encoders ==
|
||||
|
||||
CryptoJS can convert from encoding formats such as Base64, Latin1 or Hex to WordArray objects and vica versa.
|
||||
|
||||
{{{
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/core-min.js"></script>
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/enc-utf16-min.js"></script>
|
||||
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/enc-base64-min.js"></script>
|
||||
<script>
|
||||
var words = CryptoJS.enc.Base64.parse('SGVsbG8sIFdvcmxkIQ==');
|
||||
var base64 = CryptoJS.enc.Base64.stringify(words);
|
||||
|
||||
var words = CryptoJS.enc.Latin1.parse('Hello, World!');
|
||||
var latin1 = CryptoJS.enc.Latin1.stringify(words);
|
||||
|
||||
var words = CryptoJS.enc.Hex.parse('48656c6c6f2c20576f726c6421');
|
||||
var hex = CryptoJS.enc.Hex.stringify(words);
|
||||
|
||||
var words = CryptoJS.enc.Utf8.parse('𤭢');
|
||||
var utf8 = CryptoJS.enc.Utf8.stringify(words);
|
||||
|
||||
var words = CryptoJS.enc.Utf16.parse('Hello, World!');
|
||||
var utf16 = CryptoJS.enc.Utf16.stringify(words);
|
||||
|
||||
var words = CryptoJS.enc.Utf16LE.parse('Hello, World!');
|
||||
var utf16 = CryptoJS.enc.Utf16LE.stringify(words);
|
||||
</script>
|
||||
}}}
|
|
@ -1,136 +0,0 @@
|
|||
;(function (root, factory) {
|
||||
if (typeof exports === "object") {
|
||||
// CommonJS
|
||||
module.exports = exports = factory(require("./core"));
|
||||
}
|
||||
else if (typeof define === "function" && define.amd) {
|
||||
// AMD
|
||||
define(["./core"], factory);
|
||||
}
|
||||
else {
|
||||
// Global (browser)
|
||||
factory(root.CryptoJS);
|
||||
}
|
||||
}(this, function (CryptoJS) {
|
||||
|
||||
(function () {
|
||||
// Shortcuts
|
||||
var C = CryptoJS;
|
||||
var C_lib = C.lib;
|
||||
var WordArray = C_lib.WordArray;
|
||||
var C_enc = C.enc;
|
||||
|
||||
/**
|
||||
* Base64 encoding strategy.
|
||||
*/
|
||||
var Base64 = C_enc.Base64 = {
|
||||
/**
|
||||
* Converts a word array to a Base64 string.
|
||||
*
|
||||
* @param {WordArray} wordArray The word array.
|
||||
*
|
||||
* @return {string} The Base64 string.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var base64String = CryptoJS.enc.Base64.stringify(wordArray);
|
||||
*/
|
||||
stringify: function (wordArray) {
|
||||
// Shortcuts
|
||||
var words = wordArray.words;
|
||||
var sigBytes = wordArray.sigBytes;
|
||||
var map = this._map;
|
||||
|
||||
// Clamp excess bits
|
||||
wordArray.clamp();
|
||||
|
||||
// Convert
|
||||
var base64Chars = [];
|
||||
for (var i = 0; i < sigBytes; i += 3) {
|
||||
var byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
|
||||
var byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff;
|
||||
var byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff;
|
||||
|
||||
var triplet = (byte1 << 16) | (byte2 << 8) | byte3;
|
||||
|
||||
for (var j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j++) {
|
||||
base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f));
|
||||
}
|
||||
}
|
||||
|
||||
// Add padding
|
||||
var paddingChar = map.charAt(64);
|
||||
if (paddingChar) {
|
||||
while (base64Chars.length % 4) {
|
||||
base64Chars.push(paddingChar);
|
||||
}
|
||||
}
|
||||
|
||||
return base64Chars.join('');
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a Base64 string to a word array.
|
||||
*
|
||||
* @param {string} base64Str The Base64 string.
|
||||
*
|
||||
* @return {WordArray} The word array.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var wordArray = CryptoJS.enc.Base64.parse(base64String);
|
||||
*/
|
||||
parse: function (base64Str) {
|
||||
// Shortcuts
|
||||
var base64StrLength = base64Str.length;
|
||||
var map = this._map;
|
||||
var reverseMap = this._reverseMap;
|
||||
|
||||
if (!reverseMap) {
|
||||
reverseMap = this._reverseMap = [];
|
||||
for (var j = 0; j < map.length; j++) {
|
||||
reverseMap[map.charCodeAt(j)] = j;
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore padding
|
||||
var paddingChar = map.charAt(64);
|
||||
if (paddingChar) {
|
||||
var paddingIndex = base64Str.indexOf(paddingChar);
|
||||
if (paddingIndex !== -1) {
|
||||
base64StrLength = paddingIndex;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert
|
||||
return parseLoop(base64Str, base64StrLength, reverseMap);
|
||||
|
||||
},
|
||||
|
||||
_map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
|
||||
};
|
||||
|
||||
function parseLoop(base64Str, base64StrLength, reverseMap) {
|
||||
var words = [];
|
||||
var nBytes = 0;
|
||||
for (var i = 0; i < base64StrLength; i++) {
|
||||
if (i % 4) {
|
||||
var bits1 = reverseMap[base64Str.charCodeAt(i - 1)] << ((i % 4) * 2);
|
||||
var bits2 = reverseMap[base64Str.charCodeAt(i)] >>> (6 - (i % 4) * 2);
|
||||
var bitsCombined = bits1 | bits2;
|
||||
words[nBytes >>> 2] |= bitsCombined << (24 - (nBytes % 4) * 8);
|
||||
nBytes++;
|
||||
}
|
||||
}
|
||||
return WordArray.create(words, nBytes);
|
||||
}
|
||||
}());
|
||||
|
||||
|
||||
return CryptoJS.enc.Base64;
|
||||
|
||||
}));
|
|
@ -1,18 +0,0 @@
|
|||
;(function (root, factory) {
|
||||
if (typeof exports === "object") {
|
||||
// CommonJS
|
||||
module.exports = exports = factory(require("./core"));
|
||||
}
|
||||
else if (typeof define === "function" && define.amd) {
|
||||
// AMD
|
||||
define(["./core"], factory);
|
||||
}
|
||||
else {
|
||||
// Global (browser)
|
||||
factory(root.CryptoJS);
|
||||
}
|
||||
}(this, function (CryptoJS) {
|
||||
|
||||
return CryptoJS.enc.Hex;
|
||||
|
||||
}));
|
|
@ -1,18 +0,0 @@
|
|||
;(function (root, factory) {
|
||||
if (typeof exports === "object") {
|
||||
// CommonJS
|
||||
module.exports = exports = factory(require("./core"));
|
||||
}
|
||||
else if (typeof define === "function" && define.amd) {
|
||||
// AMD
|
||||
define(["./core"], factory);
|
||||
}
|
||||
else {
|
||||
// Global (browser)
|
||||
factory(root.CryptoJS);
|
||||
}
|
||||
}(this, function (CryptoJS) {
|
||||
|
||||
return CryptoJS.enc.Latin1;
|
||||
|
||||
}));
|
|
@ -1,149 +0,0 @@
|
|||
;(function (root, factory) {
|
||||
if (typeof exports === "object") {
|
||||
// CommonJS
|
||||
module.exports = exports = factory(require("./core"));
|
||||
}
|
||||
else if (typeof define === "function" && define.amd) {
|
||||
// AMD
|
||||
define(["./core"], factory);
|
||||
}
|
||||
else {
|
||||
// Global (browser)
|
||||
factory(root.CryptoJS);
|
||||
}
|
||||
}(this, function (CryptoJS) {
|
||||
|
||||
(function () {
|
||||
// Shortcuts
|
||||
var C = CryptoJS;
|
||||
var C_lib = C.lib;
|
||||
var WordArray = C_lib.WordArray;
|
||||
var C_enc = C.enc;
|
||||
|
||||
/**
|
||||
* UTF-16 BE encoding strategy.
|
||||
*/
|
||||
var Utf16BE = C_enc.Utf16 = C_enc.Utf16BE = {
|
||||
/**
|
||||
* Converts a word array to a UTF-16 BE string.
|
||||
*
|
||||
* @param {WordArray} wordArray The word array.
|
||||
*
|
||||
* @return {string} The UTF-16 BE string.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var utf16String = CryptoJS.enc.Utf16.stringify(wordArray);
|
||||
*/
|
||||
stringify: function (wordArray) {
|
||||
// Shortcuts
|
||||
var words = wordArray.words;
|
||||
var sigBytes = wordArray.sigBytes;
|
||||
|
||||
// Convert
|
||||
var utf16Chars = [];
|
||||
for (var i = 0; i < sigBytes; i += 2) {
|
||||
var codePoint = (words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff;
|
||||
utf16Chars.push(String.fromCharCode(codePoint));
|
||||
}
|
||||
|
||||
return utf16Chars.join('');
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a UTF-16 BE string to a word array.
|
||||
*
|
||||
* @param {string} utf16Str The UTF-16 BE string.
|
||||
*
|
||||
* @return {WordArray} The word array.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var wordArray = CryptoJS.enc.Utf16.parse(utf16String);
|
||||
*/
|
||||
parse: function (utf16Str) {
|
||||
// Shortcut
|
||||
var utf16StrLength = utf16Str.length;
|
||||
|
||||
// Convert
|
||||
var words = [];
|
||||
for (var i = 0; i < utf16StrLength; i++) {
|
||||
words[i >>> 1] |= utf16Str.charCodeAt(i) << (16 - (i % 2) * 16);
|
||||
}
|
||||
|
||||
return WordArray.create(words, utf16StrLength * 2);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* UTF-16 LE encoding strategy.
|
||||
*/
|
||||
C_enc.Utf16LE = {
|
||||
/**
|
||||
* Converts a word array to a UTF-16 LE string.
|
||||
*
|
||||
* @param {WordArray} wordArray The word array.
|
||||
*
|
||||
* @return {string} The UTF-16 LE string.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var utf16Str = CryptoJS.enc.Utf16LE.stringify(wordArray);
|
||||
*/
|
||||
stringify: function (wordArray) {
|
||||
// Shortcuts
|
||||
var words = wordArray.words;
|
||||
var sigBytes = wordArray.sigBytes;
|
||||
|
||||
// Convert
|
||||
var utf16Chars = [];
|
||||
for (var i = 0; i < sigBytes; i += 2) {
|
||||
var codePoint = swapEndian((words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff);
|
||||
utf16Chars.push(String.fromCharCode(codePoint));
|
||||
}
|
||||
|
||||
return utf16Chars.join('');
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a UTF-16 LE string to a word array.
|
||||
*
|
||||
* @param {string} utf16Str The UTF-16 LE string.
|
||||
*
|
||||
* @return {WordArray} The word array.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var wordArray = CryptoJS.enc.Utf16LE.parse(utf16Str);
|
||||
*/
|
||||
parse: function (utf16Str) {
|
||||
// Shortcut
|
||||
var utf16StrLength = utf16Str.length;
|
||||
|
||||
// Convert
|
||||
var words = [];
|
||||
for (var i = 0; i < utf16StrLength; i++) {
|
||||
words[i >>> 1] |= swapEndian(utf16Str.charCodeAt(i) << (16 - (i % 2) * 16));
|
||||
}
|
||||
|
||||
return WordArray.create(words, utf16StrLength * 2);
|
||||
}
|
||||
};
|
||||
|
||||
function swapEndian(word) {
|
||||
return ((word << 8) & 0xff00ff00) | ((word >>> 8) & 0x00ff00ff);
|
||||
}
|
||||
}());
|
||||
|
||||
|
||||
return CryptoJS.enc.Utf16;
|
||||
|
||||
}));
|
|
@ -1,18 +0,0 @@
|
|||
;(function (root, factory) {
|
||||
if (typeof exports === "object") {
|
||||
// CommonJS
|
||||
module.exports = exports = factory(require("./core"));
|
||||
}
|
||||
else if (typeof define === "function" && define.amd) {
|
||||
// AMD
|
||||
define(["./core"], factory);
|
||||
}
|
||||
else {
|
||||
// Global (browser)
|
||||
factory(root.CryptoJS);
|
||||
}
|
||||
}(this, function (CryptoJS) {
|
||||
|
||||
return CryptoJS.enc.Utf8;
|
||||
|
||||
}));
|
|
@ -1,134 +0,0 @@
|
|||
;(function (root, factory, undef) {
|
||||
if (typeof exports === "object") {
|
||||
// CommonJS
|
||||
module.exports = exports = factory(require("./core"), require("./sha1"), require("./hmac"));
|
||||
}
|
||||
else if (typeof define === "function" && define.amd) {
|
||||
// AMD
|
||||
define(["./core", "./sha1", "./hmac"], factory);
|
||||
}
|
||||
else {
|
||||
// Global (browser)
|
||||
factory(root.CryptoJS);
|
||||
}
|
||||
}(this, function (CryptoJS) {
|
||||
|
||||
(function () {
|
||||
// Shortcuts
|
||||
var C = CryptoJS;
|
||||
var C_lib = C.lib;
|
||||
var Base = C_lib.Base;
|
||||
var WordArray = C_lib.WordArray;
|
||||
var C_algo = C.algo;
|
||||
var MD5 = C_algo.MD5;
|
||||
|
||||
/**
|
||||
* This key derivation function is meant to conform with EVP_BytesToKey.
|
||||
* www.openssl.org/docs/crypto/EVP_BytesToKey.html
|
||||
*/
|
||||
var EvpKDF = C_algo.EvpKDF = Base.extend({
|
||||
/**
|
||||
* Configuration options.
|
||||
*
|
||||
* @property {number} keySize The key size in words to generate. Default: 4 (128 bits)
|
||||
* @property {Hasher} hasher The hash algorithm to use. Default: MD5
|
||||
* @property {number} iterations The number of iterations to perform. Default: 1
|
||||
*/
|
||||
cfg: Base.extend({
|
||||
keySize: 128/32,
|
||||
hasher: MD5,
|
||||
iterations: 1
|
||||
}),
|
||||
|
||||
/**
|
||||
* Initializes a newly created key derivation function.
|
||||
*
|
||||
* @param {Object} cfg (Optional) The configuration options to use for the derivation.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var kdf = CryptoJS.algo.EvpKDF.create();
|
||||
* var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8 });
|
||||
* var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8, iterations: 1000 });
|
||||
*/
|
||||
init: function (cfg) {
|
||||
this.cfg = this.cfg.extend(cfg);
|
||||
},
|
||||
|
||||
/**
|
||||
* Derives a key from a password.
|
||||
*
|
||||
* @param {WordArray|string} password The password.
|
||||
* @param {WordArray|string} salt A salt.
|
||||
*
|
||||
* @return {WordArray} The derived key.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var key = kdf.compute(password, salt);
|
||||
*/
|
||||
compute: function (password, salt) {
|
||||
var block;
|
||||
|
||||
// Shortcut
|
||||
var cfg = this.cfg;
|
||||
|
||||
// Init hasher
|
||||
var hasher = cfg.hasher.create();
|
||||
|
||||
// Initial values
|
||||
var derivedKey = WordArray.create();
|
||||
|
||||
// Shortcuts
|
||||
var derivedKeyWords = derivedKey.words;
|
||||
var keySize = cfg.keySize;
|
||||
var iterations = cfg.iterations;
|
||||
|
||||
// Generate key
|
||||
while (derivedKeyWords.length < keySize) {
|
||||
if (block) {
|
||||
hasher.update(block);
|
||||
}
|
||||
block = hasher.update(password).finalize(salt);
|
||||
hasher.reset();
|
||||
|
||||
// Iterations
|
||||
for (var i = 1; i < iterations; i++) {
|
||||
block = hasher.finalize(block);
|
||||
hasher.reset();
|
||||
}
|
||||
|
||||
derivedKey.concat(block);
|
||||
}
|
||||
derivedKey.sigBytes = keySize * 4;
|
||||
|
||||
return derivedKey;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Derives a key from a password.
|
||||
*
|
||||
* @param {WordArray|string} password The password.
|
||||
* @param {WordArray|string} salt A salt.
|
||||
* @param {Object} cfg (Optional) The configuration options to use for this computation.
|
||||
*
|
||||
* @return {WordArray} The derived key.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var key = CryptoJS.EvpKDF(password, salt);
|
||||
* var key = CryptoJS.EvpKDF(password, salt, { keySize: 8 });
|
||||
* var key = CryptoJS.EvpKDF(password, salt, { keySize: 8, iterations: 1000 });
|
||||
*/
|
||||
C.EvpKDF = function (password, salt, cfg) {
|
||||
return EvpKDF.create(cfg).compute(password, salt);
|
||||
};
|
||||
}());
|
||||
|
||||
|
||||
return CryptoJS.EvpKDF;
|
||||
|
||||
}));
|
|
@ -1,66 +0,0 @@
|
|||
;(function (root, factory, undef) {
|
||||
if (typeof exports === "object") {
|
||||
// CommonJS
|
||||
module.exports = exports = factory(require("./core"), require("./cipher-core"));
|
||||
}
|
||||
else if (typeof define === "function" && define.amd) {
|
||||
// AMD
|
||||
define(["./core", "./cipher-core"], factory);
|
||||
}
|
||||
else {
|
||||
// Global (browser)
|
||||
factory(root.CryptoJS);
|
||||
}
|
||||
}(this, function (CryptoJS) {
|
||||
|
||||
(function (undefined) {
|
||||
// Shortcuts
|
||||
var C = CryptoJS;
|
||||
var C_lib = C.lib;
|
||||
var CipherParams = C_lib.CipherParams;
|
||||
var C_enc = C.enc;
|
||||
var Hex = C_enc.Hex;
|
||||
var C_format = C.format;
|
||||
|
||||
var HexFormatter = C_format.Hex = {
|
||||
/**
|
||||
* Converts the ciphertext of a cipher params object to a hexadecimally encoded string.
|
||||
*
|
||||
* @param {CipherParams} cipherParams The cipher params object.
|
||||
*
|
||||
* @return {string} The hexadecimally encoded string.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hexString = CryptoJS.format.Hex.stringify(cipherParams);
|
||||
*/
|
||||
stringify: function (cipherParams) {
|
||||
return cipherParams.ciphertext.toString(Hex);
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a hexadecimally encoded ciphertext string to a cipher params object.
|
||||
*
|
||||
* @param {string} input The hexadecimally encoded string.
|
||||
*
|
||||
* @return {CipherParams} The cipher params object.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var cipherParams = CryptoJS.format.Hex.parse(hexString);
|
||||
*/
|
||||
parse: function (input) {
|
||||
var ciphertext = Hex.parse(input);
|
||||
return CipherParams.create({ ciphertext: ciphertext });
|
||||
}
|
||||
};
|
||||
}());
|
||||
|
||||
|
||||
return CryptoJS.format.Hex;
|
||||
|
||||
}));
|
|
@ -1,18 +0,0 @@
|
|||
;(function (root, factory, undef) {
|
||||
if (typeof exports === "object") {
|
||||
// CommonJS
|
||||
module.exports = exports = factory(require("./core"), require("./cipher-core"));
|
||||
}
|
||||
else if (typeof define === "function" && define.amd) {
|
||||
// AMD
|
||||
define(["./core", "./cipher-core"], factory);
|
||||
}
|
||||
else {
|
||||
// Global (browser)
|
||||
factory(root.CryptoJS);
|
||||
}
|
||||
}(this, function (CryptoJS) {
|
||||
|
||||
return CryptoJS.format.OpenSSL;
|
||||
|
||||
}));
|
|
@ -1,18 +0,0 @@
|
|||
;(function (root, factory, undef) {
|
||||
if (typeof exports === "object") {
|
||||
// CommonJS
|
||||
module.exports = exports = factory(require("./core"), require("./md5"), require("./hmac"));
|
||||
}
|
||||
else if (typeof define === "function" && define.amd) {
|
||||
// AMD
|
||||
define(["./core", "./md5", "./hmac"], factory);
|
||||
}
|
||||
else {
|
||||
// Global (browser)
|
||||
factory(root.CryptoJS);
|
||||
}
|
||||
}(this, function (CryptoJS) {
|
||||
|
||||
return CryptoJS.HmacMD5;
|
||||
|
||||
}));
|
|
@ -1,18 +0,0 @@
|
|||
;(function (root, factory, undef) {
|
||||
if (typeof exports === "object") {
|
||||
// CommonJS
|
||||
module.exports = exports = factory(require("./core"), require("./ripemd160"), require("./hmac"));
|
||||
}
|
||||
else if (typeof define === "function" && define.amd) {
|
||||
// AMD
|
||||
define(["./core", "./ripemd160", "./hmac"], factory);
|
||||
}
|
||||
else {
|
||||
// Global (browser)
|
||||
factory(root.CryptoJS);
|
||||
}
|
||||
}(this, function (CryptoJS) {
|
||||
|
||||
return CryptoJS.HmacRIPEMD160;
|
||||
|
||||
}));
|
|
@ -1,18 +0,0 @@
|
|||
;(function (root, factory, undef) {
|
||||
if (typeof exports === "object") {
|
||||
// CommonJS
|
||||
module.exports = exports = factory(require("./core"), require("./sha1"), require("./hmac"));
|
||||
}
|
||||
else if (typeof define === "function" && define.amd) {
|
||||
// AMD
|
||||
define(["./core", "./sha1", "./hmac"], factory);
|
||||
}
|
||||
else {
|
||||
// Global (browser)
|
||||
factory(root.CryptoJS);
|
||||
}
|
||||
}(this, function (CryptoJS) {
|
||||
|
||||
return CryptoJS.HmacSHA1;
|
||||
|
||||
}));
|
|
@ -1,18 +0,0 @@
|
|||
;(function (root, factory, undef) {
|
||||
if (typeof exports === "object") {
|
||||
// CommonJS
|
||||
module.exports = exports = factory(require("./core"), require("./sha256"), require("./sha224"), require("./hmac"));
|
||||
}
|
||||
else if (typeof define === "function" && define.amd) {
|
||||
// AMD
|
||||
define(["./core", "./sha256", "./sha224", "./hmac"], factory);
|
||||
}
|
||||
else {
|
||||
// Global (browser)
|
||||
factory(root.CryptoJS);
|
||||
}
|
||||
}(this, function (CryptoJS) {
|
||||
|
||||
return CryptoJS.HmacSHA224;
|
||||
|
||||
}));
|
|
@ -1,18 +0,0 @@
|
|||
;(function (root, factory, undef) {
|
||||
if (typeof exports === "object") {
|
||||
// CommonJS
|
||||
module.exports = exports = factory(require("./core"), require("./sha256"), require("./hmac"));
|
||||
}
|
||||
else if (typeof define === "function" && define.amd) {
|
||||
// AMD
|
||||
define(["./core", "./sha256", "./hmac"], factory);
|
||||
}
|
||||
else {
|
||||
// Global (browser)
|
||||
factory(root.CryptoJS);
|
||||
}
|
||||
}(this, function (CryptoJS) {
|
||||
|
||||
return CryptoJS.HmacSHA256;
|
||||
|
||||
}));
|
|
@ -1,18 +0,0 @@
|
|||
;(function (root, factory, undef) {
|
||||
if (typeof exports === "object") {
|
||||
// CommonJS
|
||||
module.exports = exports = factory(require("./core"), require("./x64-core"), require("./sha3"), require("./hmac"));
|
||||
}
|
||||
else if (typeof define === "function" && define.amd) {
|
||||
// AMD
|
||||
define(["./core", "./x64-core", "./sha3", "./hmac"], factory);
|
||||
}
|
||||
else {
|
||||
// Global (browser)
|
||||
factory(root.CryptoJS);
|
||||
}
|
||||
}(this, function (CryptoJS) {
|
||||
|
||||
return CryptoJS.HmacSHA3;
|
||||
|
||||
}));
|