parent
b917f98738
commit
025e59ad5d
20 changed files with 2405 additions and 363 deletions
@ -0,0 +1,299 @@ |
||||
<template> |
||||
<view class="page-css"> |
||||
<view class="info"> |
||||
<view class="info_title">基本信息</view> |
||||
<view class="info_item"> |
||||
<text class="item_left_txt">单位名称:</text> |
||||
<text class="item_right_txt">{{ detailForm.deptName }}</text> |
||||
</view> |
||||
<view class="info_item"> |
||||
<text class="item_left_txt">巡检内容:</text> |
||||
<text class="item_right_txt">{{ detailForm.taskContent }}</text> |
||||
</view> |
||||
</view> |
||||
<view class="info"> |
||||
<view class="info_title">巡检配置</view> |
||||
<view class="info_item"> |
||||
<text class="item_left_txt">巡检内容:</text> |
||||
<text class="item_right_txt">{{ detailForm.taskContent }}</text> |
||||
</view> |
||||
<view class="info_item"> |
||||
<text class="item_left_txt">任务开始时间:</text> |
||||
<text class="item_right_txt">{{ detailForm.startTime }}</text> |
||||
</view> |
||||
<view class="info_item" v-if="!(detailForm.taskStatus == 0 || detailForm.taskStatus == 1)"> |
||||
<text class="item_left_txt">预约上门时间:</text> |
||||
<text class="item_right_txt">{{ detailForm.reservationTime }}</text> |
||||
</view> |
||||
</view> |
||||
|
||||
<view class="info"> |
||||
<view class="info_title">巡检任务</view> |
||||
<u-collapse :accordion="false"> |
||||
<u-collapse-item v-for="(item, index) in detailForm.details" :key="index" :open="true"> |
||||
<view slot="title"> |
||||
<text class="collapse-title">实验室楼层:{{ item.floorName }}</text> |
||||
</view> |
||||
<view v-for="(v, vindex) in item.details" :key="vindex" class="collapse-room"> |
||||
<view>房间名称:{{ v.deptName }}</view> |
||||
<view v-for="(s, sindex) in v.details" :key="sindex" class="n-box"> |
||||
<u-tag :text="sindex + 1" type="info" class="left-tag" /> |
||||
<view class="n-box-title"> {{ s.checkContent }}</view> |
||||
<view class="n-box-info"> {{ s.craft }}</view> |
||||
<view class="info_item"> |
||||
<text class="item_left_txt">巡检周期:</text> |
||||
<text class="item_right_txt"> |
||||
{{ periodName(s.period) }} |
||||
</text> |
||||
</view> |
||||
<view class="info_item" v-if="s.status >= 0"> |
||||
<text class="item_left_txt">状态:</text> |
||||
<text class="item_right_txt"> |
||||
{{ s.status == '0' ? '正常' : '异常' }} |
||||
</text> |
||||
</view> |
||||
<view class="info_item" v-if="s.picUrl != ''"> |
||||
<text class="item_left_txt">现场照片:</text> |
||||
<text class="item_right_txt"> |
||||
<image class="item_right_img" :src="s.picUrl"></image> |
||||
</text> |
||||
</view> |
||||
<view class="info_item" v-if="s.signUrl != ''"> |
||||
<text class="item_left_txt">签字:</text> |
||||
<text class="item_right_txt"> |
||||
{{ s.signUrl }} |
||||
</text> |
||||
</view> |
||||
<view class="info_item" v-if="s.remark != ''"> |
||||
<text class="item_left_txt">备注:</text> |
||||
<text class="item_right_txt"> |
||||
{{ s.remark }} |
||||
</text> |
||||
</view> |
||||
<view class="info_item" v-if="s.price >= 0"> |
||||
<text class="item_left_txt">价格:</text> |
||||
<text class="item_right_txt"> |
||||
{{ s.price }} |
||||
</text> |
||||
</view> |
||||
<view class="info_item" v-if="s.isRepair >= 0"> |
||||
<text class="item_left_txt">是否维修:</text> |
||||
<text class="item_right_txt"> |
||||
{{ s.status == '0' ? '否' : '是' }} |
||||
</text> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
</u-collapse-item> |
||||
</u-collapse> |
||||
</view> |
||||
|
||||
</view> |
||||
</template> |
||||
<script> |
||||
export default { |
||||
props:{ |
||||
data:{ |
||||
type:Object, |
||||
default:{} |
||||
}, |
||||
detailId:{ |
||||
type:String, |
||||
default:'' |
||||
} |
||||
}, |
||||
computed: { |
||||
dataTypes() { |
||||
return this.$store.state.dataType |
||||
}, |
||||
}, |
||||
data() { |
||||
return { |
||||
detailForm: {}, |
||||
optionsType: '',//可操作类型 |
||||
planOrderId: '',// |
||||
} |
||||
}, |
||||
|
||||
mounted(){ |
||||
this.getDetails() |
||||
}, |
||||
methods: { |
||||
getDetails() { |
||||
let query_ = { |
||||
id: this.detailId |
||||
} |
||||
this.$u.api.getTaskDetail(query_).then(res => { |
||||
if (res.code == 200) { |
||||
this.detailForm = res.data |
||||
|
||||
} |
||||
}) |
||||
}, |
||||
// 巡检周期 |
||||
periodName(value) { |
||||
if (value == 1) { |
||||
return '月' |
||||
} |
||||
if (value == 2) { |
||||
return '季度' |
||||
} |
||||
if (value == 3) { |
||||
return '半年' |
||||
} |
||||
}, |
||||
} |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.page-css { |
||||
width: 100%; |
||||
padding: 0; |
||||
padding-top: 26rpx; |
||||
|
||||
.info { |
||||
margin: 0 24rpx 20rpx; |
||||
border-radius: 20rpx; |
||||
background-color: rgba(255, 255, 255, 1); |
||||
padding: 6rpx 0 34rpx; |
||||
|
||||
.info_title { |
||||
line-height: 60rpx; |
||||
color: rgba(0, 0, 0, 1); |
||||
font-size: 32rpx; |
||||
text-align: left; |
||||
font-family: SourceHanSansSC-bold; |
||||
margin: 18rpx 0 0rpx 20rpx; |
||||
font-weight: bold; |
||||
} |
||||
|
||||
.info_item { |
||||
padding: 4rpx 20rpx 0; |
||||
|
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: space-between; |
||||
|
||||
.item_left_txt { |
||||
color: rgba(108, 108, 108, 1); |
||||
font-size: 28rpx; |
||||
text-align: left; |
||||
font-family: SourceHanSansSC-regular; |
||||
width: 210rpx; |
||||
margin-right: 20rpx; |
||||
line-height: 60rpx; |
||||
} |
||||
|
||||
.item_right_txt { |
||||
max-width: calc(100% - 220rpx); |
||||
color: rgba(0, 0, 0, 1); |
||||
font-size: 28rpx; |
||||
// text-align: left; |
||||
text-align: justify; |
||||
font-family: SourceHanSansSC-regular; |
||||
image{ |
||||
width: 100rpx; |
||||
height: 100rpx; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
.repair-btn { |
||||
width: 100%; |
||||
height: 150rpx; |
||||
display: flex; |
||||
justify-content: space-between; |
||||
/* 水平均匀分布 */ |
||||
margin-top: 32rpx; |
||||
padding: 0 32rpx; |
||||
|
||||
/deep/.u-btn { |
||||
width: 48%; |
||||
} |
||||
} |
||||
|
||||
.n-box { |
||||
border: 1px solid rgba(239, 239, 239, 1); |
||||
padding: 32rpx 54rpx 0; |
||||
margin-top: 24rpx; |
||||
margin-bottom: 24rpx; |
||||
position: relative; |
||||
|
||||
.right-tag { |
||||
position: absolute; |
||||
right: 0; |
||||
top: 0; |
||||
} |
||||
|
||||
.left-tag { |
||||
position: absolute; |
||||
left: 0; |
||||
top: 0; |
||||
padding-left: 10rpx; |
||||
padding-right: 10rpx; |
||||
} |
||||
|
||||
.n-box-title { |
||||
color: rgba(0, 0, 0, 1); |
||||
font-size: 28rpx; |
||||
text-align: left; |
||||
} |
||||
|
||||
.n-box-info { |
||||
line-height: 32rpx; |
||||
color: rgba(154, 154, 154, 1); |
||||
font-size: 24rpx; |
||||
padding-top: 12rpx; |
||||
padding-bottom: 12rpx; |
||||
} |
||||
|
||||
.info_item { |
||||
width: 100%; |
||||
display: flex; |
||||
flex-direction: row; |
||||
margin: 0rpx 0 0; |
||||
|
||||
.item_left_txt { |
||||
color: rgba(108, 108, 108, 1); |
||||
font-size: 28rpx; |
||||
text-align: left; |
||||
width: 170rpx; |
||||
margin-right: 20rpx; |
||||
line-height: 60rpx; |
||||
} |
||||
|
||||
.item_right_txt { |
||||
flex: 1; |
||||
max-width: calc(100% - 220rpx); |
||||
color: rgba(0, 0, 0, 1); |
||||
font-size: 28rpx; |
||||
// text-align: left; |
||||
text-align: justify; |
||||
font-family: SourceHanSansSC-regular; |
||||
|
||||
/deep/.u-radio-group { |
||||
flex-wrap: nowrap; |
||||
padding-right: 48rpx; |
||||
} |
||||
|
||||
.btn { |
||||
width: 260rpx; |
||||
height: 60rpx; |
||||
line-height: 60rpx; |
||||
border-radius: 8rpx; |
||||
background-color: rgba(255, 255, 255, 1); |
||||
color: rgba(58, 98, 215, 1); |
||||
font-size: 28rpx; |
||||
text-align: center; |
||||
border: 2rpx dashed rgba(58, 98, 215, 1); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/deep/.u-collapse { |
||||
padding: 0 16rpx; |
||||
} |
||||
} |
||||
</style> |
||||
@ -0,0 +1,538 @@ |
||||
<template> |
||||
<view class="page-css" |
||||
:style="{ 'padding-bottom': (detailForm.status == 5 && dataTypes == 1) ? '180rpx' : '20rpx' }" |
||||
ref="contentToExport"> |
||||
<view class=""> |
||||
<view class="repair_detail"> |
||||
<view class="repair_title">{{ dataTypes == 1 ? '故障信息' : '故障详情' }}</view> |
||||
<view class="detail_item"> |
||||
<text class="item_left_txt">故障描述:</text> |
||||
<text class="item_right_txt reason">{{ detailForm.faultDescribe }}</text> |
||||
</view> |
||||
<view class="detail_item"> |
||||
<text class="item_left_txt">故障位置:</text> |
||||
<text class="item_right_txt">{{ detailForm.faultLocation }}</text> |
||||
</view> |
||||
<view class="detail_item"> |
||||
<text class="item_left_txt">设备名称:</text> |
||||
<text class="item_right_txt">{{ detailForm.deviceName }}</text> |
||||
</view> |
||||
<view class="detail_item"> |
||||
<text class="item_left_txt">故障类别:</text> |
||||
<text class="item_right_txt">{{ detailForm.faultType }}</text> |
||||
</view> |
||||
<view class="detail_item"> |
||||
<text class="item_left_txt">故障视频:</text> |
||||
<view class="item_right_txt video"> |
||||
<video v-show="videoUrl != ''" :src="videoUrl" style="width: 450rpx; height: 320rpx" |
||||
controls></video> |
||||
<video v-if="detailForm.videoAttaches && detailForm.videoAttaches.length > 0" |
||||
:src="detailForm.videoAttaches[0].link" style="width: 148px; height: 148px" |
||||
controls></video> |
||||
</view> |
||||
</view> |
||||
<view class="detail_item"> |
||||
<text class="item_left_txt">故障图片:</text> |
||||
<view class="item_right_txt video"> |
||||
<image style="width: 130rpx;height: 140rpx;margin-bottom: 10rpx;" |
||||
v-for="item in detailForm.picAttaches" :key="item.id" :src="item.link" alt="" /> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
<!-- 维修详情 --> |
||||
<view class="repair_detail" |
||||
v-if="(dataTypes == 1 || dataTypes == 2) && (detailForm.status == 5 || detailForm.status == 6 || detailForm.status == 7 || detailForm.status == 8 || detailForm.status == 9) || (dataTypes == 4 && !(detailForm.status == 0 || detailForm.status == 1 || detailForm.status == 2)) || (dataTypes == 3) && (detailForm.closeReason == '')"> |
||||
<view class="repair_title">维修详情</view> |
||||
<view class="detail_item"> |
||||
<text class="item_left_txt">维修人:</text> |
||||
<text class="item_right_txt">{{ detailForm.repairPersonName }}</text> |
||||
</view> |
||||
<view class="detail_item"> |
||||
<text class="item_left_txt">设备名称:</text> |
||||
<text class="item_right_txt">{{ detailForm.deviceName }}</text> |
||||
</view> |
||||
<view class="detail_item"> |
||||
<text class="item_left_txt">故障原因:</text> |
||||
<text class="item_right_txt reason">{{ detailForm.faultCause }}</text> |
||||
</view> |
||||
<view class="detail_item" style="margin-top: 10rpx;"> |
||||
<text class="item_left_txt">处理方法:</text> |
||||
<text class="item_right_txt reason">{{ detailForm.processMethod }}</text> |
||||
</view> |
||||
<view class="detail_item" v-show="detailForm.materials && detailForm.materials.length != 0"> |
||||
<text class="item_left_txt">维修材料:</text> |
||||
<view class="item_right_table"> |
||||
<view class="table_box"> |
||||
<view class="table_txt left">物料名称</view> |
||||
<view class="table_txt right">金额</view> |
||||
</view> |
||||
<view class="table_box table_item" v-for="item in detailForm.materials" :key="item.id"> |
||||
<view class="table_txt left">{{ item.materialName }}</view> |
||||
<view class="table_txt right">{{ item.materialPrice }}</view> |
||||
</view> |
||||
<view class="table_box table_sub"> |
||||
<view class="table_txt left">合计</view> |
||||
<view class="table_txt right">{{ totalPrice }}</view> |
||||
</view> |
||||
<view class="table_box table_sub"> |
||||
<view class="table_txt left">折扣</view> |
||||
<view class="table_txt right">{{ discount }}<text v-show="discount != ''">折</text></view> |
||||
</view> |
||||
<view class="table_box table_sub"> |
||||
<view class="table_txt left">折后价格</view> |
||||
<view class="table_txt right">{{ discountPrice }}</view> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
<!-- 客服查看派单详情 --> |
||||
<view class="repair_detail" |
||||
v-if="((detailForm.status != 0) && dataTypes == 2) || (dataTypes == 1 && !(detailForm.status == 0 || detailForm.status == -1)) || dataTypes == 4"> |
||||
<view class="repair_title">处理情况</view> |
||||
<view class="detail_item"> |
||||
<text class="item_left_txt">接单时间:</text> |
||||
<text class="item_right_txt reason">{{ detailForm.dispatchTime }}</text> |
||||
</view> |
||||
<view class="detail_item" v-if="dataTypes != 1"> |
||||
<text class="item_left_txt">计划完成时间:</text> |
||||
<text class="item_right_txt reason">{{ detailForm.planCompleteTime }}</text> |
||||
</view> |
||||
<view class="detail_item"> |
||||
<text class="item_left_txt">客服意见:</text> |
||||
<text class="item_right_txt reason">{{ detailForm.customerOpinion }}</text> |
||||
</view> |
||||
</view> |
||||
<!-- 关闭详情 --> |
||||
<view class="repair_detail" v-if="detailForm.closeReason != ''"> |
||||
<view class="repair_title">关闭详情</view> |
||||
<view class="detail_item"> |
||||
<text class="item_left_txt">关闭原因:</text> |
||||
<text class="item_right_txt">{{ detailForm.closeReason }}</text> |
||||
</view> |
||||
</view> |
||||
<!-- 驳回 --> |
||||
<view class="repair_detail" v-if="detailForm.repaiRejectReason != ''"> |
||||
<view class="repair_title">驳回详情</view> |
||||
<view class="detail_item"> |
||||
<text class="item_left_txt">驳回原因:</text> |
||||
<text class="item_right_txt">{{ detailForm.repaiRejectReason }}</text> |
||||
</view> |
||||
</view> |
||||
|
||||
<view class="repair_detail" v-if="detailForm.status != -1"> |
||||
<view class="repair_title">其他信息</view> |
||||
<view class="detail_item"> |
||||
<text class="item_left_txt">提报人:</text> |
||||
<text class="item_right_txt">{{ detailForm.informantName }}</text> |
||||
</view> |
||||
<view class="detail_item"> |
||||
<text class="item_left_txt">提报人电话:</text> |
||||
<text class="item_right_txt">{{ detailForm.informantPhone }}</text> |
||||
</view> |
||||
<view class="detail_item"> |
||||
<text class="item_left_txt">提报单号:</text> |
||||
<text class="item_right_txt">{{ detailForm.requirementCode }}</text> |
||||
</view> |
||||
<view class="detail_item"> |
||||
<text class="item_left_txt">提报时间:</text> |
||||
<text class="item_right_txt">{{ detailForm.createTime }}</text> |
||||
</view> |
||||
|
||||
</view> |
||||
|
||||
</view> |
||||
|
||||
|
||||
</view> |
||||
</template> |
||||
<script> |
||||
export default { |
||||
props:{ |
||||
data:{ |
||||
type:Object, |
||||
default:{} |
||||
}, |
||||
detailId:{ |
||||
type:String, |
||||
default:'' |
||||
} |
||||
}, |
||||
computed: { |
||||
dataTypes() { |
||||
return this.$store.state.dataType |
||||
}, |
||||
}, |
||||
data() { |
||||
return { |
||||
totalPrice: '1084.00', |
||||
discount: '9', |
||||
discountPrice: '975.60', |
||||
detailForm: {}, |
||||
videoUrl: '', |
||||
userInfo: {}, |
||||
repairDetails: { |
||||
reportPeople: '',//填报人 |
||||
deviceName: '',//设备名称 |
||||
faultReason: '',//故障原因 |
||||
dealMethods: '',//处理方法 |
||||
isMaterial: null,//是否申领物料 |
||||
materialTable: [],//物料数据 |
||||
}, |
||||
imageSrc: '',//图片路径 |
||||
} |
||||
}, |
||||
|
||||
mounted() { |
||||
// 获取用户信息 |
||||
this.userInfo = uni.getStorageSync("userinfo"); |
||||
this.getDetail() |
||||
// 动态详情查看 |
||||
}, |
||||
methods: { |
||||
getDetail() { |
||||
let query_ = { |
||||
id: this.detailId |
||||
} |
||||
this.$u.api.getBreakdownInfo(query_).then(res => { |
||||
if (res.code == 200) { |
||||
this.detailForm = res.data |
||||
this.videoUrl = res.data.videoAttaches && res.data.videoAttaches.length > 0 ? res.data.videoAttaches[0].link : '' |
||||
this.totalPrice = res.data.totalPrice == -1 ? res.data.materials.reduce((sum, item) => sum + item.materialPrice, 0) : res.data.totalPrice |
||||
this.discount = res.data.discount == -1 ? '' : res.data.discount |
||||
this.discountPrice = res.data.discountPrice == -1 ? '' : res.data.discountPrice |
||||
|
||||
this.repairDetails.reportPeople = this.detailForm.repairPersonName //填报人 |
||||
this.repairDetails.deviceName = this.detailForm.deviceName //填报人 |
||||
} |
||||
}) |
||||
} |
||||
|
||||
} |
||||
} |
||||
|
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.page-css { |
||||
|
||||
width: 100%; |
||||
padding: 0; |
||||
padding-top: 26rpx; |
||||
padding-bottom: 180rpx; |
||||
|
||||
.status_box { |
||||
margin: 0 24rpx 20rpx; |
||||
height: 180rpx; |
||||
border-radius: 20rpx; |
||||
background-color: rgba(255, 255, 255, 1); |
||||
color: rgba(16, 16, 16, 1); |
||||
font-size: 36rpx; |
||||
text-align: left; |
||||
font-family: -bold; |
||||
|
||||
.status_top { |
||||
width: 100%; |
||||
padding: 40rpx 20rpx 30rpx 30rpx; |
||||
// background-color: red; |
||||
display: flex; |
||||
justify-content: space-between; |
||||
align-items: center; |
||||
|
||||
.status_txt { |
||||
color: rgba(0, 0, 0, 1); |
||||
font-size: 36rpx; |
||||
text-align: left; |
||||
font-family: SourceHanSansSC-bold; |
||||
font-weight: bold; |
||||
} |
||||
|
||||
.load_more { |
||||
color: rgba(108, 108, 108, 1); |
||||
font-size: 28rpx; |
||||
text-align: left; |
||||
font-family: SourceHanSansSC-regular; |
||||
display: flex; |
||||
align-items: center; |
||||
} |
||||
} |
||||
|
||||
.status_bottom { |
||||
display: flex; |
||||
justify-content: space-between; |
||||
align-items: center; |
||||
color: rgba(190, 190, 190, 1); |
||||
font-size: 28rpx; |
||||
text-align: left; |
||||
font-family: SourceHanSansSC-regular; |
||||
|
||||
.status_date { |
||||
margin-right: 22rpx; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.fault_detail { |
||||
margin: 0 24rpx 20rpx; |
||||
height: 180rpx; |
||||
border-radius: 20rpx; |
||||
background-color: rgba(255, 255, 255, 1); |
||||
} |
||||
|
||||
.repair_detail { |
||||
margin: 0 24rpx 20rpx; |
||||
border-radius: 20rpx; |
||||
background-color: rgba(255, 255, 255, 1); |
||||
padding: 6rpx 0 34rpx; |
||||
|
||||
.repair_title { |
||||
line-height: 60rpx; |
||||
color: rgba(0, 0, 0, 1); |
||||
font-size: 32rpx; |
||||
text-align: left; |
||||
font-family: SourceHanSansSC-bold; |
||||
margin: 18rpx 0 0rpx 20rpx; |
||||
font-weight: bold; |
||||
} |
||||
|
||||
.detail_item { |
||||
padding: 4rpx 20rpx 0; |
||||
|
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: space-between; |
||||
|
||||
.item_left_txt { |
||||
color: rgba(108, 108, 108, 1); |
||||
font-size: 28rpx; |
||||
text-align: left; |
||||
font-family: SourceHanSansSC-regular; |
||||
width: 210rpx; |
||||
margin-right: 20rpx; |
||||
line-height: 60rpx; |
||||
} |
||||
|
||||
.item_right_txt { |
||||
max-width: calc(100% - 220rpx); |
||||
color: rgba(0, 0, 0, 1); |
||||
font-size: 28rpx; |
||||
// text-align: left; |
||||
text-align: justify; |
||||
font-family: SourceHanSansSC-regular; |
||||
} |
||||
|
||||
.item_right_table { |
||||
width: calc(100% - 220rpx); |
||||
margin-top: 10rpx; |
||||
|
||||
.table_box { |
||||
width: 100%; |
||||
height: 60rpx; |
||||
background-color: #e8e8e8; |
||||
border: 1px solid #bbbbbb; |
||||
font-size: 14px; |
||||
color: #101010; |
||||
line-height: 60rpx; |
||||
display: flex; |
||||
|
||||
.left { |
||||
width: 72%; |
||||
height: 100%; |
||||
text-align: center; |
||||
border-right: 2rpx solid #bbbbbb; |
||||
} |
||||
|
||||
.right { |
||||
width: 28%; |
||||
height: 100%; |
||||
text-align: center; |
||||
} |
||||
} |
||||
|
||||
.table_item { |
||||
background-color: #fff; |
||||
border-top: none; |
||||
} |
||||
|
||||
.table_sub { |
||||
border-top: none; |
||||
background-color: #fff; |
||||
} |
||||
} |
||||
|
||||
.reason { |
||||
word-wrap: warp; |
||||
text-overflow: ellipsis; |
||||
display: -webkit-box; |
||||
-webkit-box-orient: vertical; |
||||
-webkit-line-clamp: 3; |
||||
/* 定义显示的行数 */ |
||||
overflow: hidden; |
||||
text-overflow: ellipsis; |
||||
} |
||||
|
||||
.video { |
||||
margin-top: 10rpx; |
||||
display: flex; |
||||
flex-wrap: wrap; |
||||
align-items: center; |
||||
justify-content: space-between; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.evaluate_box { |
||||
width: 100%; |
||||
height: 154rpx; |
||||
bottom: 0; |
||||
position: fixed; |
||||
background: #fff; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: flex-end; |
||||
|
||||
.evaluate_btn { |
||||
width: 160rpx; |
||||
height: 60rpx; |
||||
border-radius: 8rpx; |
||||
background-color: rgba(255, 255, 255, 1); |
||||
color: rgba(58, 98, 215, 1); |
||||
font-size: 24rpx; |
||||
text-align: center; |
||||
font-family: PingFangSC-regular; |
||||
border: 2rpx solid rgba(58, 98, 215, 1); |
||||
margin-right: 26rpx; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: center; |
||||
} |
||||
} |
||||
|
||||
.repair_form { |
||||
padding: 0 32rpx; |
||||
} |
||||
|
||||
.repair-btn { |
||||
width: 100%; |
||||
display: flex; |
||||
justify-content: space-around; |
||||
/* 水平均匀分布 */ |
||||
margin-top: 32rpx; |
||||
padding: 0 32rpx; |
||||
|
||||
/deep/.u-btn { |
||||
width: 100%; |
||||
} |
||||
} |
||||
|
||||
/deep/.popup-content { |
||||
display: flex; |
||||
flex-direction: column; |
||||
overflow: hidden; |
||||
} |
||||
|
||||
.select-box { |
||||
width: 100%; |
||||
|
||||
.select-box-item { |
||||
width: 100%; |
||||
border-radius: 20rpx; |
||||
background-color: rgba(249, 249, 249, 1); |
||||
margin-bottom: 32rpx; |
||||
line-height: 60rpx; |
||||
color: rgba(108, 108, 108, 1); |
||||
font-size: 28rpx; |
||||
padding: 24rpx; |
||||
} |
||||
} |
||||
|
||||
.material-box { |
||||
flex: 1; |
||||
background: #fff; |
||||
margin: 0; |
||||
overflow: auto; |
||||
// padding-bottom: 32rpx; |
||||
|
||||
.material-item { |
||||
height: 300rpx; |
||||
border-radius: 20rpx; |
||||
background-color: rgba(249, 249, 249, 1); |
||||
margin: 32rpx 0 0; |
||||
padding: 32rpx; |
||||
display: flex; |
||||
flex-direction: row; |
||||
|
||||
.title-wrapper {} |
||||
|
||||
.item-right { |
||||
flex: 1; |
||||
|
||||
.material-title { |
||||
display: flex; |
||||
flex-direction: row; |
||||
color: rgba(108, 108, 108, 1); |
||||
font-size: 28rpx; |
||||
line-height: 60rpx; |
||||
|
||||
.material-title-name { |
||||
color: rgba(51, 51, 51, 1); |
||||
font-size: 36rpx; |
||||
font-weight: 550; |
||||
padding-right: 16rpx; |
||||
} |
||||
|
||||
.material-title-code { |
||||
flex: 1; |
||||
} |
||||
} |
||||
|
||||
.material-text { |
||||
line-height: 60rpx; |
||||
color: rgba(108, 108, 108, 1); |
||||
font-size: 28rpx; |
||||
} |
||||
|
||||
.material-num { |
||||
display: flex; |
||||
flex-direction: row; |
||||
justify-content: space-between; |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
} |
||||
|
||||
.material-btn { |
||||
width: 100%; |
||||
display: flex; |
||||
justify-content: space-between; |
||||
/* 水平均匀分布 */ |
||||
margin-top: 32rpx; |
||||
padding: 0 32rpx; |
||||
|
||||
/deep/.u-btn { |
||||
width: 48%; |
||||
} |
||||
} |
||||
|
||||
.selectForm { |
||||
width: 100%; |
||||
padding: 26rpx; |
||||
|
||||
.form-item { |
||||
float: left; |
||||
width: calc(100% - 26rpx - 26rpx - 140rpx); |
||||
|
||||
.material-text { |
||||
width: 50%; |
||||
float: left; |
||||
} |
||||
} |
||||
|
||||
.form-label { |
||||
width: 140rpx; |
||||
text-align: center; |
||||
} |
||||
} |
||||
} |
||||
</style> |
||||
@ -0,0 +1,57 @@ |
||||
## 1.2.3(2024-09-19) |
||||
1. 更新示例工程 |
||||
## 1.2.2(2024-05-08) |
||||
1. 修改util.js路径为@/uni_modules/sp-html2canvas-render/utils/index.js |
||||
## 1.2.1(2024-05-08) |
||||
1. 更新示例工程 |
||||
## 1.2.0(2024-04-30) |
||||
1. 示例工程中示例二已更新解决截图模糊的问题,请参考 |
||||
## 1.1.9(2024-04-30) |
||||
1.更新示例工程 |
||||
## 1.1.8(2024-04-30) |
||||
1. 优化了报错提示 |
||||
2. domId设为必填 |
||||
## 1.1.7(2024-04-29) |
||||
1. h2c配置项更新 |
||||
## 1.1.6(2024-03-08) |
||||
1. 更新示例工程 |
||||
2. 更新文档 |
||||
## 1.1.5(2024-02-29) |
||||
1. 更新示例工程示例四:横向长截图 |
||||
## 1.1.4(2024-02-27) |
||||
1. 更新base64ToPath方法,以供需要用临时路径保存文件的小伙伴,见示例一中使用 |
||||
## 1.1.3(2024-02-24) |
||||
1. 更新示例工程:示例3:动态domid,可动态选择单独导出指定dom |
||||
## 1.1.2(2024-02-06) |
||||
1. 更新文档 |
||||
## 1.1.1(2024-02-06) |
||||
1. 重大更新,详见文档 |
||||
2. 更新示例工程 |
||||
## 1.1.0(2024-02-05) |
||||
1. 更新文档 |
||||
## 1.0.9(2024-02-05) |
||||
1. 重要更新:插件更新内置了urlToBase64工具方法,图片报错toDataURL on HTMLCanvasElement或其他问题导致图片无法正常渲染的,可以使用该工具方法将图片路径(支持网络路径和本地相对路径)转换为base64格式 |
||||
## 1.0.8(2024-02-04) |
||||
1. 更新示例工程 |
||||
## 1.0.7(2024-01-24) |
||||
1. 更新示例工程延迟渲染示例 |
||||
## 1.0.6(2024-01-16) |
||||
1. 更新示例工程 |
||||
2. 更新文档 |
||||
## 1.0.5(2024-01-15) |
||||
1. 更新示例工程 |
||||
## 1.0.4(2023-12-08) |
||||
1. 更新html2canvas中部分配置 |
||||
2. 重新上传示例工程,还请麻烦用hbuilderx一键导入示例,不要使用zip下载的方式 |
||||
3. 更新文档说明,很多人问toDataURL on HTMLCanvasElement的问题,有的人哪怕直接使用实例工程也会报错,有的人却一切正常,我对此提供了部分解决方式。 |
||||
## 1.0.3(2023-11-29) |
||||
1.更新示例工程,内联使用方式详见inner页面 |
||||
## 1.0.2(2023-11-27) |
||||
1.更新示例工程样例 |
||||
## 1.0.1(2023-11-27) |
||||
1.解决在vue2的ap真机环境下可能出现的报错 |
||||
|
||||
2.更新示例代码,兼容vue2/3写法,支持图片生成样例 |
||||
## 1.0.0(2023-10-20) |
||||
1. 组件更新,使用方式详见README |
||||
2. 更新示例项目 |
||||
@ -0,0 +1,110 @@ |
||||
<template> |
||||
<!-- prop是自定义的数据字段名,要与chang后的保持一致,h2cRender是renderjs的module名称 --> |
||||
<view class="sp-html2canvas-render" :prop="domId" :change:prop="h2cRender.watchDomId"> |
||||
<slot></slot> |
||||
<text :prop="expOver" :change:prop="h2cRender.watchExpOver"></text> |
||||
</view> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
props: { |
||||
// 要渲染dom的id |
||||
domId: { |
||||
type: String, |
||||
default: '', |
||||
require: true |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
expOver: 0, |
||||
// #ifdef VUE2 |
||||
// #ifdef APP |
||||
// 只有在Vue2的APP真机中需要先声明h2cRender,否则会报错,若未报错建议删除此处代码 |
||||
h2cRender: null |
||||
// #endif |
||||
// #endif |
||||
} |
||||
}, |
||||
methods: { |
||||
renderOver(e) { |
||||
// 监听渲染生成完成 |
||||
this.$emit('renderOver', e) |
||||
}, |
||||
h2cRenderDom() { |
||||
// #ifdef H5 |
||||
this.renderDom() |
||||
// #endif |
||||
// #ifndef H5 |
||||
// 控制expOver变量改变以触发RenderJs中渲染方法。 |
||||
this.expOver++ |
||||
// 处理你自己的逻辑..... |
||||
// #endif |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<!-- renderjs目前仅支持内联使用 --> |
||||
<script module="h2cRender" lang="renderjs"> |
||||
import html2canvas from 'html2canvas'; |
||||
export default { |
||||
data() { |
||||
return { |
||||
domIdValue: '' |
||||
} |
||||
}, |
||||
methods: { |
||||
async renderDom() { |
||||
// app无法通过传参获取domId,也无法直接获取到script中data或props数据 |
||||
// 必须通过特定的监听方式,与script通信,获取其data |
||||
try { |
||||
const el = document.getElementById(this.domIdValue); |
||||
if(!el) { |
||||
console.error('dom盒子未加载成功,请先确保dom渲染完成,再检查你的domId是否有误'); |
||||
return |
||||
} |
||||
/** |
||||
* 配置说明 |
||||
* 1. allowTaint:true和useCORS:true都是解决跨域问题的方式(不一定完全能解决跨域),不同的是使用allowTaint会对canvas造成污染,导致无法使用canvas.toDataURL方法 |
||||
* 2. 想要完美解决跨域,还得需要后端服务器设置access-control-allow-origin: *,允许资源跨域访问,前端设置useCORS:true |
||||
* 2. scale通过放大倍率来调整画质清晰度,但是只调整这一个参数可能不是最优解 |
||||
*/ |
||||
const canvas = await html2canvas(el, { |
||||
width: el.offsetWidth, |
||||
height: el.offsetHeight, |
||||
x: 0, |
||||
y: 0, |
||||
logging: true, |
||||
useCORS: true, |
||||
// allowTaint: true, |
||||
// async: false, |
||||
scale: 2, // 2倍,增强清晰度 |
||||
// foreignObjectRendering: true, // 兼容性问题,慎用 |
||||
}); |
||||
const base64 = canvas.toDataURL('image/png', 1); |
||||
this.$ownerInstance.callMethod('renderOver', base64); |
||||
} catch(err) { |
||||
console.log('==== err :', err.message); |
||||
} |
||||
}, |
||||
// 监听方式,与script通信,获取其data |
||||
watchDomId(newValue, oldValue, ownerInstance, instance) { |
||||
this.domIdValue = newValue |
||||
}, |
||||
watchExpOver(newValue, oldValue, ownerInstance, instance) { |
||||
if(newValue !== 0){ |
||||
// 初始不做监听,避免默认第一次就自动渲染 |
||||
this.renderDom() |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style> |
||||
.sp-html2canvas-render { |
||||
position: relative; |
||||
} |
||||
</style> |
||||
@ -0,0 +1,86 @@ |
||||
{ |
||||
"id": "sp-html2canvas-render", |
||||
"displayName": "基于html2canvas和renderjs 指定盒子截图 截屏 截长屏", |
||||
"version": "1.2.3", |
||||
"description": "基于html2canvas和renderjs的页面指定盒子截图,截屏,可截长屏,页面生成图片", |
||||
"keywords": [ |
||||
"截图", |
||||
"截屏", |
||||
"截长屏", |
||||
"生成图片", |
||||
"html2canvas" |
||||
], |
||||
"repository": "", |
||||
"engines": { |
||||
"HBuilderX": "^3.8.0" |
||||
}, |
||||
"dcloudext": { |
||||
"type": "component-vue", |
||||
"sale": { |
||||
"regular": { |
||||
"price": "0.00" |
||||
}, |
||||
"sourcecode": { |
||||
"price": "0.00" |
||||
} |
||||
}, |
||||
"contact": { |
||||
"qq": "" |
||||
}, |
||||
"declaration": { |
||||
"ads": "无", |
||||
"data": "插件不采集任何数据", |
||||
"permissions": "无" |
||||
}, |
||||
"npmurl": "" |
||||
}, |
||||
"uni_modules": { |
||||
"dependencies": [], |
||||
"encrypt": [], |
||||
"platforms": { |
||||
"cloud": { |
||||
"tcb": "y", |
||||
"aliyun": "y", |
||||
"alipay": "n" |
||||
}, |
||||
"client": { |
||||
"Vue": { |
||||
"vue2": "y", |
||||
"vue3": "y" |
||||
}, |
||||
"App": { |
||||
"app-vue": "y", |
||||
"app-nvue": "u" |
||||
}, |
||||
"H5-mobile": { |
||||
"Safari": "y", |
||||
"Android Browser": "y", |
||||
"微信浏览器(Android)": "y", |
||||
"QQ浏览器(Android)": "y" |
||||
}, |
||||
"H5-pc": { |
||||
"Chrome": "y", |
||||
"IE": "y", |
||||
"Edge": "y", |
||||
"Firefox": "y", |
||||
"Safari": "y" |
||||
}, |
||||
"小程序": { |
||||
"微信": "u", |
||||
"阿里": "u", |
||||
"百度": "u", |
||||
"字节跳动": "u", |
||||
"QQ": "u", |
||||
"钉钉": "u", |
||||
"快手": "u", |
||||
"飞书": "u", |
||||
"京东": "u" |
||||
}, |
||||
"快应用": { |
||||
"华为": "u", |
||||
"联盟": "u" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,11 @@ |
||||
# sp-html2canvas-render |
||||
|
||||
### 文档迁移 |
||||
|
||||
> 防止文档失效,提供下列五个地址,内容一致 |
||||
|
||||
- [地址一](https://sonvee.github.io/sv-app-docs/docs-github/src/plugins/sp-html2canvas-render/sp-html2canvas-render.html) |
||||
- [地址二](https://sv-app-docs.pages.dev/src/plugins/sp-html2canvas-render/sp-html2canvas-render.html) |
||||
- [地址三](https://sv-app-docs.4everland.app/src/plugins/sp-html2canvas-render/sp-html2canvas-render.html) |
||||
- [地址四](https://sv-app-docs.vercel.app/src/plugins/sp-html2canvas-render/sp-html2canvas-render.html) (需要梯子) |
||||
- [地址五](https://static-mp-74bfcbac-6ba6-4f39-8513-8831390ff75a.next.bspapp.com/docs-uni/src/plugins/sp-html2canvas-render/sp-html2canvas-render.html) (有IP限制) |
||||
@ -0,0 +1,255 @@ |
||||
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) { |
||||
let localFilePath = plus.io.convertAbsoluteFileSystem(path) |
||||
if (localFilePath !== path) { |
||||
return localFilePath |
||||
} else { |
||||
path = path.substr(1) |
||||
} |
||||
} |
||||
return '_www/' + path |
||||
} |
||||
|
||||
function dataUrlToBase64(str) { |
||||
let array = str.split(',') |
||||
return array[array.length - 1] |
||||
} |
||||
|
||||
let index = 0 |
||||
|
||||
function getNewFileId() { |
||||
return Date.now() + String(index++) |
||||
} |
||||
|
||||
function biggerThan(v1, v2) { |
||||
let v1Array = v1.split('.') |
||||
let v2Array = v2.split('.') |
||||
let update = false |
||||
for (let index = 0; index < v2Array.length; index++) { |
||||
let 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') { |
||||
let 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 |
||||
} |
||||
let canvas = document.createElement('canvas') |
||||
let c2x = canvas.getContext('2d') |
||||
let 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) { |
||||
let 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(',') |
||||
let type = base64[0].match(/:(.*?);/)[1] |
||||
let str = atob(base64[1]) |
||||
let n = str.length |
||||
let array = new Uint8Array(n) |
||||
while (n--) { |
||||
array[n] = str.charCodeAt(n) |
||||
} |
||||
return resolve((window.URL || window.webkitURL).createObjectURL(new Blob([array], { |
||||
type: type |
||||
}))) |
||||
} |
||||
let extName = base64.split(',')[0].match(/data\:\S+\/(\S+);/) |
||||
if (extName) { |
||||
extName = extName[1] |
||||
} else { |
||||
reject(new Error('base64 error')) |
||||
} |
||||
let fileName = getNewFileId() + '.' + extName |
||||
if (typeof plus === 'object') { |
||||
let basePath = '_doc' |
||||
let dirPath = 'uniapp_temp' |
||||
let 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 |
||||
} |
||||
let 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')) { |
||||
let 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')) |
||||
}) |
||||
} |
||||
|
||||
/** |
||||
* 图片地址转换为base64格式图片 |
||||
* @param {string} url 图片地址 网络地址 本地相对路径 |
||||
* @param {string} type base64图片类型 默认png |
||||
*/ |
||||
export function urlToBase64(url, type = 'png') { |
||||
let promises |
||||
|
||||
// 网络地址 或者h5端本地相对路径 可使用request方式
|
||||
promises = new Promise((resolve, reject) => { |
||||
uni.request({ |
||||
url: url, |
||||
method: 'GET', |
||||
responseType: 'arraybuffer', |
||||
success: (res) => { |
||||
const base64 = `data:image/${type};base64,${uni.arrayBufferToBase64(res.data)}` |
||||
resolve(base64); |
||||
}, |
||||
fail: (err) => { |
||||
reject(err); |
||||
}, |
||||
}) |
||||
}) |
||||
|
||||
// #ifdef APP
|
||||
if (!url.startsWith('http')) { |
||||
// app真机本地相对路径
|
||||
promises = new Promise((resolve, reject) => { |
||||
// 使用compressImage获取到安卓本地路径file:///...
|
||||
uni.compressImage({ |
||||
src: url, |
||||
quality: 100, |
||||
success: (res) => { |
||||
const tempUrl = res.tempFilePath |
||||
plus.io.resolveLocalFileSystemURL(tempUrl, (entry) => { |
||||
entry.file((e) => { |
||||
let fileReader = new plus.io.FileReader(); |
||||
fileReader.onload = (r) => { |
||||
resolve(r.target.result) |
||||
} |
||||
fileReader.readAsDataURL(e) |
||||
}) |
||||
}) |
||||
}, |
||||
fail: (err) => { |
||||
reject(err); |
||||
}, |
||||
}) |
||||
}) |
||||
} |
||||
// #endif
|
||||
|
||||
return promises |
||||
} |
||||
@ -0,0 +1,34 @@ |
||||
## 1.1.2(2024-06-06) |
||||
1. pdf添加页头页尾占位 |
||||
## 1.1.1(2024-06-05) |
||||
1. 修复ios无法导出的问题 |
||||
## 1.1.0(2024-05-13) |
||||
1. 新增openPDF实例事件,以便于关闭autoOpen的之后,方便在任何时机一键重新打开文档 |
||||
## 1.0.9(2024-05-13) |
||||
1. 处理加载loading有延时问题和部分场景下未正常关闭问题 |
||||
## 1.0.8(2024-05-08) |
||||
1. 修改原util.js路径为@/uni_modules/sp-html2pdf-render/utils/index.js |
||||
## 1.0.7(2024-05-08) |
||||
1. 更新示例工程 |
||||
2. 修改原renderCanvas事件名为renderOver |
||||
3. 移除原afterSavePDF事件 |
||||
4. 新增autoOpen属性 |
||||
5. 文档迁移 |
||||
## 1.0.6(2024-03-18) |
||||
1. 新增pdfFileName属性,以自定义导出pdf的文件名,为空则默认以当前时间戳命名 |
||||
2. 更新文档 |
||||
## 1.0.5(2024-02-06) |
||||
1. 更新文档 |
||||
## 1.0.4(2024-02-06) |
||||
1. 重大更新,详情见文档 |
||||
2. 示例工程更新 |
||||
## 1.0.3(2024-02-06) |
||||
1. 更新文档 |
||||
## 1.0.2(2024-02-06) |
||||
1. 更新示例工程 |
||||
2. 插件优化,建议时刻保持最新版插件 |
||||
## 1.0.1(2024-02-05) |
||||
1. 更新示例工程,包括但不限于内联使用示例 |
||||
## 1.0.0(2023-10-24) |
||||
1. 发布插件 |
||||
2. 使用方式详见下文或示例项目 |
||||
@ -0,0 +1,277 @@ |
||||
<template> |
||||
<!-- prop是自定义的数据字段名,要与chang后的保持一致,h2pRender是renderjs的module名称 --> |
||||
<view class="sp-html2pdf-render" :prop="domId" :change:prop="h2pRender.watchDomId"> |
||||
<!-- 导出的PDF会撑满宽度,所以请事先规范好要渲染盒子的宽度,PDF以一般A4纸大小尺寸,会自动分页 --> |
||||
<!-- 默认带有插槽,但是具体是否要将渲染的dom盒子放入插槽中由开发者自行决定,导出结果只与domId有关 --> |
||||
<slot></slot> |
||||
<text :prop="expOver" :change:prop="h2pRender.watchExpOver"></text> |
||||
</view> |
||||
</template> |
||||
|
||||
<script> |
||||
import { base64ToPath } from '../../utils/index.js' |
||||
export default { |
||||
props: { |
||||
// 要渲染dom的id |
||||
domId: { |
||||
type: String, |
||||
default: '', |
||||
require: true |
||||
}, |
||||
// 是否显示导出loading |
||||
showLoading: { |
||||
type: Boolean, |
||||
default: true |
||||
}, |
||||
// 导出的pdf文件名,默认使用当前时间戳,已自动拼接后缀 |
||||
pdfFileName: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
// 是否自动打开文档 |
||||
autoOpen: { |
||||
type: Boolean, |
||||
default: true |
||||
} |
||||
}, |
||||
data() { |
||||
return { |
||||
expOver: 0, |
||||
// #ifdef VUE2 |
||||
// #ifdef APP |
||||
// 只有在Vue2的APP真机中需要先声明h2pRender,否则会报错,若未报错建议删除此处代码 |
||||
h2pRender: null |
||||
// #endif |
||||
// #endif |
||||
} |
||||
}, |
||||
methods: { |
||||
renderOver(e) { |
||||
// canvas渲染图片完成 |
||||
this.$emit('renderOver', e) |
||||
}, |
||||
savePDF(e) { |
||||
// pdf生成完成 |
||||
if (this.showLoading) uni.showLoading({ title: '导出中' }) |
||||
|
||||
this.$emit('beforeSavePDF', e) |
||||
|
||||
// 判断是否开启自动打开文件 |
||||
if (!this.autoOpen) { |
||||
if (this.showLoading) uni.hideLoading() |
||||
return |
||||
} |
||||
|
||||
this.openPDF(e) |
||||
}, |
||||
/** |
||||
* 手动打开pdf文档 |
||||
* @param {Object} e pdf的base64字符串 |
||||
*/ |
||||
openPDF(e) { |
||||
/** |
||||
* base64ToPath |
||||
* @param {Object} e base64字符串 |
||||
* @param {String} name 导出的文件名(未命名则以当前时间戳命名,已自动拼接后缀) |
||||
*/ |
||||
base64ToPath(e, this.pdfFileName) |
||||
.then((path) => { |
||||
uni.openDocument({ |
||||
filePath: path, |
||||
success: () => { |
||||
this.$emit('successSavePDF', path) |
||||
}, |
||||
fail: (err) => { |
||||
console.error('openDocument error', err) |
||||
} |
||||
}) |
||||
}) |
||||
.catch((error) => { |
||||
console.error('base64ToPath error', error) |
||||
}) |
||||
.finally(() => { |
||||
if (this.showLoading) uni.hideLoading() |
||||
}) |
||||
}, |
||||
// 渲染事件 |
||||
async h2pRenderDom() { |
||||
uni.showLoading({ title: '加载中' }) |
||||
|
||||
// #ifdef H5 |
||||
await this.renderDom() |
||||
// #endif |
||||
// #ifndef H5 |
||||
// 控制expOver变量改变以触发RenderJs中渲染方法。 |
||||
this.expOver++ |
||||
// 处理你自己的逻辑..... |
||||
// #endif |
||||
|
||||
uni.hideLoading() |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<!-- renderjs目前仅支持内联使用 --> |
||||
<script module="h2pRender" lang="renderjs"> |
||||
import html2canvas from 'html2canvas'; |
||||
import JsPDF from 'jspdf' |
||||
|
||||
export default { |
||||
data() { |
||||
return { |
||||
domIdValue: '' |
||||
} |
||||
}, |
||||
methods: { |
||||
async renderDom() { |
||||
// app无法通过传参获取domId,也无法直接获取到script中data或props数据 |
||||
// 必须通过特定的监听方式,与script通信,获取其data |
||||
try { |
||||
const el = document.getElementById(this.domIdValue); |
||||
if(!el) { |
||||
console.error('dom盒子未加载成功,请先确保dom渲染完成,再检查你的domId是否有误'); |
||||
return |
||||
} |
||||
/** |
||||
* 配置说明 |
||||
* 1. allowTaint:true和useCORS:true都是解决跨域问题的方式(不一定完全能解决跨域),不同的是使用allowTaint会对canvas造成污染,导致无法使用canvas.toDataURL方法 |
||||
* 2. 想要完美解决跨域,还得需要后端服务器设置access-control-allow-origin: *,允许资源跨域访问,前端设置useCORS:true |
||||
* 2. scale通过放大倍率来调整画质清晰度,但是只调整这一个参数可能不是最优解 |
||||
*/ |
||||
const canvas = await html2canvas(el, { |
||||
width: el.offsetWidth, |
||||
height: el.offsetHeight, |
||||
x: 0, |
||||
y: 0, |
||||
logging: true, |
||||
useCORS: true, |
||||
// allowTaint: true, |
||||
// async: false, |
||||
scale: 2, // 2倍,增强清晰度 |
||||
// foreignObjectRendering: true, // 兼容性问题,慎用 |
||||
}); |
||||
const base64 = canvas.toDataURL('image/png', 1); |
||||
this.$ownerInstance.callMethod('renderOver', base64); |
||||
// 创建PDF |
||||
|
||||
// 页头页脚 |
||||
let divNode = document.createElement("div") |
||||
divNode.style.width = '100%' // 设置div的宽度为100% |
||||
divNode.style.height = '20px' // 设置div的高度为20px,用于页头页脚的高度 |
||||
document.body.appendChild(divNode) |
||||
const divCanvas = await html2canvas(divNode, { |
||||
width: divNode.offsetWidth, |
||||
height: divNode.offsetHeight, |
||||
x: 0, |
||||
y: 0, |
||||
scale: 0.5, // 2倍,增强清晰度 |
||||
backgroundColor: '#ffffff', // 背景色,防止出现透明部分导致pdf背景色异常 |
||||
}); |
||||
|
||||
this.createPDF(canvas, divCanvas) |
||||
} catch(err) { |
||||
console.log('==== err :', err); |
||||
} |
||||
}, |
||||
// 监听方式,与script通信,获取其data |
||||
watchDomId(newValue, oldValue, ownerInstance, instance) { |
||||
this.domIdValue = newValue |
||||
}, |
||||
watchExpOver(newValue, oldValue, ownerInstance, instance) { |
||||
if(newValue !== 0){ |
||||
// 初始不做监听,避免默认第一次就自动渲染 |
||||
this.renderDom() |
||||
} |
||||
}, |
||||
createPDF(canvas, divCanvas) { |
||||
const a4width = 592.28; // A4纸宽度 |
||||
const a4height = 841.89; // A4纸高度 |
||||
const divheight = 20; // 页头页脚高度 |
||||
|
||||
// 生成PDF |
||||
let contentWidth = canvas.width |
||||
let contentHeight = canvas.height |
||||
// 一页pdf显示html页面生成的canvas高度; |
||||
let pageHeight = (contentWidth / a4width) * a4height - divheight * 2 |
||||
// 未生成pdf的html页面高度 |
||||
let leftHeight = contentHeight |
||||
// 页面偏移 |
||||
let position = 0 |
||||
// a4纸的尺寸[a4width,a4height],html页面生成的canvas在pdf中图片的宽高 |
||||
let imgWidth = a4width |
||||
let imgHeight = (a4width / contentWidth) * contentHeight |
||||
let pageData = canvas.toDataURL('image/png', 1.0) |
||||
let divData = divCanvas.toDataURL('image/png', 1.0) |
||||
let pdf = new JsPDF('', 'pt', 'a4') |
||||
// 有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(a4height) |
||||
// 当内容未超过pdf一页显示的范围,无需分页 |
||||
if (leftHeight < pageHeight) { |
||||
// 在pdf.addImage(pageData, 'JPEG', 左,上,宽度,高度)设置在pdf中显示; |
||||
pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight) |
||||
} else { |
||||
// 分页 |
||||
while (leftHeight > 0) { |
||||
pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight) |
||||
// 页头页尾占位 |
||||
pdf.addImage(divData, 'JPEG', 0, 0, imgWidth, divheight) |
||||
pdf.addImage(divData, 'JPEG', 0, a4height - divheight, imgWidth, divheight) |
||||
leftHeight -= pageHeight |
||||
position -= a4height - divheight * 2 |
||||
// 避免添加空白页 |
||||
if (leftHeight > 0) { |
||||
pdf.addPage() |
||||
} |
||||
} |
||||
} |
||||
// #ifdef H5 |
||||
//调用依赖获取读写手机储存权限的代码 |
||||
// pdf.save('PDF文件名') |
||||
let base64Str = pdf.output('dataurlstring'); |
||||
this.$ownerInstance.callMethod('savePDF', base64Str) |
||||
// #endif |
||||
|
||||
// #ifdef APP |
||||
if(plus.os.name == 'Android') { |
||||
plus.android.requestPermissions(['android.permission.WRITE_EXTERNAL_STORAGE'], (e) => { |
||||
if (e.deniedAlways.length > 0) { //权限被永久拒绝 |
||||
// 弹出提示框解释为何需要读写手机储存权限,引导用户打开设置页面开启 |
||||
uni.showModal({ |
||||
title: '存储权限', |
||||
content: '您拒绝了存储权限,请去设置-应用开启存储权限。', |
||||
success: function(res) { |
||||
if (res.confirm) { |
||||
// console.log('用户点击确定'); |
||||
} else if (res.cancel) { |
||||
// console.log('用户点击取消'); |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
if (e.deniedPresent.length > 0) { //权限被临时拒绝 |
||||
// 弹出提示框解释为何需要读写手机储存权限,可再次调用plus.android.requestPermissions申请权限 |
||||
plus.android.requestPermissions(['android.permission.WRITE_EXTERNAL_STORAGE']) |
||||
} |
||||
if (e.granted.length > 0) { //权限被允许 |
||||
//调用依赖获取读写手机储存权限的代码 |
||||
let base64Str = pdf.output('dataurlstring'); |
||||
this.$ownerInstance.callMethod('savePDF', base64Str) |
||||
} |
||||
}, function(e) { |
||||
}); |
||||
} else { |
||||
// ios无须读写手机存储权限 |
||||
let base64Str = pdf.output('dataurlstring'); |
||||
this.$ownerInstance.callMethod('savePDF', base64Str) |
||||
} |
||||
// #endif |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style> |
||||
.sp-html2pdf-render { |
||||
position: relative; |
||||
} |
||||
</style> |
||||
@ -0,0 +1,85 @@ |
||||
{ |
||||
"id": "sp-html2pdf-render", |
||||
"displayName": "基于html2canvas+jspdf的截图导出成pdf", |
||||
"version": "1.1.2", |
||||
"description": "html转pdf,html转canvas,pdf文件保存导出分享,指定渲染的盒子导出图片截图或者pdf文件。", |
||||
"keywords": [ |
||||
"html2pdf", |
||||
"html2canvas", |
||||
"pdf", |
||||
"canvas" |
||||
], |
||||
"repository": "", |
||||
"engines": { |
||||
"HBuilderX": "^3.1.0" |
||||
}, |
||||
"dcloudext": { |
||||
"type": "component-vue", |
||||
"sale": { |
||||
"regular": { |
||||
"price": "0.00" |
||||
}, |
||||
"sourcecode": { |
||||
"price": "0.00" |
||||
} |
||||
}, |
||||
"contact": { |
||||
"qq": "" |
||||
}, |
||||
"declaration": { |
||||
"ads": "无", |
||||
"data": "插件不采集任何数据", |
||||
"permissions": "无" |
||||
}, |
||||
"npmurl": "" |
||||
}, |
||||
"uni_modules": { |
||||
"dependencies": [], |
||||
"encrypt": [], |
||||
"platforms": { |
||||
"cloud": { |
||||
"tcb": "y", |
||||
"aliyun": "y", |
||||
"alipay": "n" |
||||
}, |
||||
"client": { |
||||
"Vue": { |
||||
"vue2": "y", |
||||
"vue3": "y" |
||||
}, |
||||
"App": { |
||||
"app-vue": "y", |
||||
"app-nvue": "u" |
||||
}, |
||||
"H5-mobile": { |
||||
"Safari": "y", |
||||
"Android Browser": "y", |
||||
"微信浏览器(Android)": "y", |
||||
"QQ浏览器(Android)": "y" |
||||
}, |
||||
"H5-pc": { |
||||
"Chrome": "y", |
||||
"IE": "u", |
||||
"Edge": "y", |
||||
"Firefox": "y", |
||||
"Safari": "y" |
||||
}, |
||||
"小程序": { |
||||
"微信": "u", |
||||
"阿里": "u", |
||||
"百度": "u", |
||||
"字节跳动": "u", |
||||
"QQ": "u", |
||||
"钉钉": "u", |
||||
"快手": "u", |
||||
"飞书": "u", |
||||
"京东": "u" |
||||
}, |
||||
"快应用": { |
||||
"华为": "u", |
||||
"联盟": "u" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,11 @@ |
||||
# sp-html2pdf-render |
||||
|
||||
### 文档迁移 |
||||
|
||||
> 防止文档失效,提供下列五个地址,内容一致 |
||||
|
||||
- [地址一](https://sonvee.github.io/sv-app-docs/docs-github/src/plugins/sp-html2pdf-render/sp-html2pdf-render.html) |
||||
- [地址二](https://sv-app-docs.pages.dev/src/plugins/sp-html2pdf-render/sp-html2pdf-render.html) |
||||
- [地址三](https://sv-app-docs.4everland.app/src/plugins/sp-html2pdf-render/sp-html2pdf-render.html) |
||||
- [地址四](https://sv-app-docs.vercel.app/src/plugins/sp-html2pdf-render/sp-html2pdf-render.html) (需要梯子) |
||||
- [地址五](https://static-mp-74bfcbac-6ba6-4f39-8513-8831390ff75a.next.bspapp.com/docs-uni/src/plugins/sp-html2pdf-render/sp-html2pdf-render.html) (有IP限制) |
||||
@ -0,0 +1,261 @@ |
||||
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) { |
||||
let localFilePath = plus.io.convertAbsoluteFileSystem(path) |
||||
if (localFilePath !== path) { |
||||
return localFilePath |
||||
} else { |
||||
path = path.substr(1) |
||||
} |
||||
} |
||||
return '_www/' + path |
||||
} |
||||
|
||||
function dataUrlToBase64(str) { |
||||
let array = str.split(',') |
||||
return array[array.length - 1] |
||||
} |
||||
|
||||
let index = 0 |
||||
|
||||
function getNewFileId() { |
||||
return Date.now() + String(index++) |
||||
} |
||||
|
||||
function biggerThan(v1, v2) { |
||||
let v1Array = v1.split('.') |
||||
let v2Array = v2.split('.') |
||||
let update = false |
||||
for (let index = 0; index < v2Array.length; index++) { |
||||
let 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') { |
||||
let 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 |
||||
} |
||||
let canvas = document.createElement('canvas') |
||||
let c2x = canvas.getContext('2d') |
||||
let 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) { |
||||
let 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, filename) { |
||||
return new Promise(function(resolve, reject) { |
||||
// web端
|
||||
if (typeof window === 'object' && 'document' in window) { |
||||
base64 = base64.split(',') |
||||
let type = base64[0].match(/:(.*?);/)[1] |
||||
let str = atob(base64[1]) |
||||
let n = str.length |
||||
let array = new Uint8Array(n) |
||||
while (n--) { |
||||
array[n] = str.charCodeAt(n) |
||||
} |
||||
return resolve((window.URL || window.webkitURL).createObjectURL(new Blob([array], { |
||||
type: type |
||||
}))) |
||||
} |
||||
|
||||
// 移动端
|
||||
let extName = base64.split(',')[0].match(/data\:\S+\/(\S+);/) |
||||
// extName 示例为 ["data:application/pdf;filename=generated.pdf;", "pdf;filename=generated.pdf"]
|
||||
if (extName) { |
||||
extName = extName[1].split(';')[0] |
||||
} else { |
||||
reject(new Error('base64 error')) |
||||
} |
||||
|
||||
let fileName = (filename || Date.now()) + '.' + extName |
||||
|
||||
if (typeof plus === 'object') { |
||||
let basePath = '_doc' |
||||
let dirPath = 'uniapp_temp' |
||||
let 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 |
||||
} |
||||
let 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')) { |
||||
let 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')) |
||||
}) |
||||
} |
||||
|
||||
/** |
||||
* 图片地址转换为base64格式图片 |
||||
* @param {string} url 图片地址 网络地址 本地相对路径 |
||||
* @param {string} type base64图片类型 默认png |
||||
*/ |
||||
export function urlToBase64(url, type = 'png') { |
||||
let promises |
||||
|
||||
// 网络地址 或者h5端本地相对路径 可使用request方式
|
||||
promises = new Promise((resolve, reject) => { |
||||
uni.request({ |
||||
url: url, |
||||
method: 'GET', |
||||
responseType: 'arraybuffer', |
||||
success: (res) => { |
||||
const base64 = `data:image/${type};base64,${uni.arrayBufferToBase64(res.data)}` |
||||
resolve(base64); |
||||
}, |
||||
fail: (err) => { |
||||
reject(err); |
||||
}, |
||||
}) |
||||
}) |
||||
|
||||
// #ifdef APP
|
||||
if (!url.startsWith('http')) { |
||||
// app真机本地相对路径
|
||||
promises = new Promise((resolve, reject) => { |
||||
// 使用compressImage获取到安卓本地路径file:///...
|
||||
uni.compressImage({ |
||||
src: url, |
||||
quality: 100, |
||||
success: (res) => { |
||||
const tempUrl = res.tempFilePath |
||||
plus.io.resolveLocalFileSystemURL(tempUrl, (entry) => { |
||||
entry.file((e) => { |
||||
let fileReader = new plus.io.FileReader(); |
||||
fileReader.onload = (r) => { |
||||
resolve(r.target.result) |
||||
} |
||||
fileReader.readAsDataURL(e) |
||||
}) |
||||
}) |
||||
}, |
||||
fail: (err) => { |
||||
reject(err); |
||||
}, |
||||
}) |
||||
}) |
||||
} |
||||
// #endif
|
||||
|
||||
return promises |
||||
} |
||||
Loading…
Reference in new issue