master
lion 2 years ago
parent 9dda1e1de2
commit 05da90437c

@ -0,0 +1,836 @@
<template>
<view class="htz-image-upload-list">
<view class="htz-image-upload-Item" v-for="(item,index) in uploadLists" :key="index">
<view class="htz-image-upload-Item-video" v-if="isVideo(item)">
<!-- #ifndef APP-PLUS -->
<video :disabled="false" :controls="false" :src="getFileUrl(item)">
<cover-view class="htz-image-upload-Item-video-fixed" @click="previewVideo(getFileUrl(item))">
</cover-view>
<cover-view class="htz-image-upload-Item-del-cover" v-if="remove && previewVideoSrc==''" @click="imgDel(index)">×</cover-view>
</video>
<!-- #endif -->
<!-- #ifdef APP-PLUS -->
<view class="htz-image-upload-Item-video-fixed" @click="previewVideo(getFileUrl(item))"></view>
<image v-if="dataType==1 && item.cover" class="htz-image-upload-Item-video-app-poster" mode="widthFix" :src="item.cover"></image>
<image v-else class="htz-image-upload-Item-video-app-poster" mode="widthFix" :src="appVideoPoster"></image>
<!-- #endif -->
</view>
<image v-else :src="getFileUrl(item)" @click="imgPreview(getFileUrl(item))"></image>
<view class="htz-image-upload-Item-del" v-if="remove" @click="imgDel(index)">×</view>
</view>
<view class="htz-image-upload-Item htz-image-upload-Item-add" v-if="uploadLists.length<max && add" @click="chooseFile">
+
</view>
<view class="preview-full" v-if="previewVideoSrc!=''">
<video :autoplay="true" :src="previewVideoSrc" :show-fullscreen-btn="false">
<cover-view class="preview-full-close" @click="previewVideoClose"> ×
</cover-view>
</video>
</view>
<!-- -->
</view>
</template>
<style>
.ceshi {
width: 100%;
height: 100%;
position: relative;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: #FFFFFF;
color: #2C405A;
opacity: 0.5;
z-index: 100;
}
</style>
<script>
export default {
name: 'htz-image-upload',
props: {
max: { //
type: Number,
default: 1,
},
chooseNum: { //
type: Number,
default: 9,
},
name: { //
type: String,
default: 'file',
},
dataType: { //v-model
type: Number,
default: 0, // 0: ['http://xxxx.jpg','http://xxxx.jpg'] 1:[{type:0,url:'http://xxxx.jpg'}] type 0 1 url 使
},
remove: { //
type: Boolean,
default: true,
},
add: { //
type: Boolean,
default: true,
},
disabled: { //
type: Boolean,
default: false,
},
sourceType: { // psH5
type: Array,
default: () => ['album', 'camera'],
},
action: { // 使uniClouduniCloud
type: String,
default: '',
},
headers: { //
type: Object,
default: () => {},
},
formData: { //HTTP form data
type: Object,
default: () => {},
},
compress: { //
type: Boolean,
default: true,
},
quality: { //0100
type: Number,
default: 80,
},
// #ifndef VUE3
value: { //
type: Array,
default: () => [],
},
// #endif
// #ifdef VUE3
modelValue: { //
type: Array,
default: () => [],
},
// #endif
uploadSuccess: {
default: (res) => {
return {
success: false,
url: ''
}
},
},
mediaType: { // image/video/all
type: String,
default: 'image',
},
maxDuration: { // 60 ()
type: Number,
default: 60,
},
camera: { //'front''back''back'()
type: String,
default: 'back',
},
appVideoPoster: { //app app
type: String,
default: '/static/htz-image-upload/play.png',
},
},
data() {
return {
uploadLists: [],
mediaTypeData: ['image', 'video', 'all'],
previewVideoSrc: '',
}
},
mounted: function() {
this.$nextTick(function() {
// #ifndef VUE3
this.uploadLists = this.value;
// #endif
// #ifdef VUE3
this.uploadLists = this.modelValue;
// #endif
if (this.mediaTypeData.indexOf(this.mediaType) == -1) {
uni.showModal({
title: '提示',
content: 'mediaType参数不正确',
showCancel: false,
success: function(res) {
if (res.confirm) {
//console.log('');
} else if (res.cancel) {
//console.log('');
}
}
});
}
});
},
watch: {
// #ifndef VUE3
value(val, oldVal) {
//console.log('value',val, oldVal)
this.uploadLists = val;
},
// #endif
// #ifdef VUE3
modelValue(val, oldVal) {
//console.log('value',val, oldVal)
this.uploadLists = val;
},
// #endif
},
methods: {
isVideo(item) {
let isPass = false
if ((!/.(gif|jpg|jpeg|png|gif|jpg|png)$/i.test(item) && this.dataType == 0) || (this.dataType == 1 && item
.type == 1)) {
isPass = true
}
return isPass
},
getFileUrl(item) {
var url = item;
if (this.dataType == 1) {
url = item.url
}
//console.log('url', url)
return url
},
previewVideo(src) {
this.previewVideoSrc = src;
// this.previewVideoSrc =
// 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-fbd63a76-dc76-485c-b711-f79f2986daeb/ba804d82-860b-4d1a-a706-5a4c8ce137c3.mp4'
},
previewVideoClose() {
this.previewVideoSrc = ''
//console.log('previewVideoClose', this.previewVideoSrc)
},
imgDel(index) {
uni.showModal({
title: '提示',
content: '您确定要删除么?',
success: (res) => {
if (res.confirm) {
// this.uploadLists.splice(index, 1)
// this.$emit("input", this.uploadLists);
// this.$emit("imgDelete", this.uploadLists);
let delUrl = this.uploadLists[index]
this.uploadLists.splice(index, 1)
// #ifndef VUE3
this.$emit("input", this.uploadLists);
// #endif
// #ifdef VUE3
this.$emit("update:modelValue", this.uploadLists);
// #endif
this.$emit("imgDelete", {
del: delUrl,
tempFilePaths: this.uploadLists
});
} else if (res.cancel) {}
}
});
},
imgPreview(index) {
var imgData = []
this.uploadLists.forEach(item => {
if (!this.isVideo(item)) {
imgData.push(this.getFileUrl(item))
}
})
//console.log('imgPreview', imgData)
uni.previewImage({
urls: imgData,
current: index,
loop: true,
});
},
chooseFile() {
if (this.disabled) {
return false;
}
switch (this.mediaTypeData.indexOf(this.mediaType)) {
case 1: //
this.videoAdd();
break;
case 2: //
uni.showActionSheet({
itemList: ['相册', '视频'],
success: (res) => {
if (res.tapIndex == 1) {
this.videoAdd();
} else if (res.tapIndex == 0) {
this.imgAdd();
}
},
fail: (res) => {
console.log(res.errMsg);
}
});
break;
default: //
this.imgAdd();
break;
}
//if(this.mediaType=='image'){
},
videoAdd() {
//console.log('videoAdd')
let nowNum = Math.abs(this.uploadLists.length - this.max);
let thisNum = (this.chooseNum > nowNum ? nowNum : this.chooseNum) //
uni.chooseVideo({
compressed: this.compress,
sourceType: this.sourceType,
camera: this.camera,
maxDuration: this.maxDuration,
success: (res) => {
// console.log('videoAdd', res)
// console.log(res.tempFilePath)
this.chooseSuccessMethod([res.tempFilePath], 1)
//this.imgUpload([res.tempFilePath]);
//console.log('tempFiles', res)
// if (this.action == '') { //
// this.$emit("chooseSuccess", res.tempFilePaths);
// } else {
// if (this.compress && (res.tempFiles[0].size / 1024 > 1025)) { // 1M
// this.imgCompress(res.tempFilePaths);
// } else {
// this.imgUpload(res.tempFilePaths);
// }
// }
}
});
},
imgAdd() {
//console.log('imgAdd')
let nowNum = Math.abs(this.uploadLists.length - this.max);
let thisNum = (this.chooseNum > nowNum ? nowNum : this.chooseNum) //
//console.log('nowNum', nowNum)
//console.log('thisNum', thisNum)
// #ifdef APP-PLUS
if (this.sourceType.length > 1) {
uni.showActionSheet({
itemList: ['拍摄', '从手机相册选择'],
success: (res) => {
if (res.tapIndex == 1) {
this.appGallery(thisNum);
} else if (res.tapIndex == 0) {
this.appCamera();
}
},
fail: (res) => {
console.log(res.errMsg);
}
});
}
if (this.sourceType.length == 1 && this.sourceType.indexOf('album') > -1) {
this.appGallery(thisNum);
}
if (this.sourceType.length == 1 && this.sourceType.indexOf('camera') > -1) {
this.appCamera();
}
// #endif
//#ifndef APP-PLUS
uni.chooseImage({
count: thisNum,
sizeType: ['original', 'compressed'], //
sourceType: this.sourceType,
success: (res) => {
this.chooseSuccessMethod(res.tempFilePaths, 0)
//console.log('tempFiles', res)
// if (this.action == '') { //
// this.$emit("chooseSuccess", res.tempFilePaths);
// } else {
// if (this.compress && (res.tempFiles[0].size / 1024 > 1025)) { // 1M
// this.imgCompress(res.tempFilePaths);
// } else {
// this.imgUpload(res.tempFilePaths);
// }
// }
}
});
// #endif
},
appCamera() {
var cmr = plus.camera.getCamera();
var res = cmr.supportedImageResolutions[0];
var fmt = cmr.supportedImageFormats[0];
//console.log("Resolution: " + res + ", Format: " + fmt);
cmr.captureImage((path) => {
//alert("Capture image success: " + path);
this.chooseSuccessMethod([path], 0)
},
(error) => {
//alert("Capture image failed: " + error.message);
console.log("Capture image failed: " + error.message)
}, {
resolution: res,
format: fmt
}
);
},
appGallery(maxNum) {
plus.gallery.pick((res) => {
this.chooseSuccessMethod(res.files, 0)
}, function(e) {
//console.log("");
}, {
filter: "image",
multiple: true,
maximum: maxNum
});
},
chooseSuccessMethod(filePaths, type) {
if (this.action == '') { //
this.$emit("chooseSuccess", filePaths, type); //filePaths type 0 1
} else {
if (type == 1) {
this.imgUpload(filePaths, type);
} else {
if (this.compress) { //
this.imgCompress(filePaths, type);
} else {
this.imgUpload(filePaths, type);
}
}
}
},
imgCompress(tempFilePaths, type) { //type 0 1
uni.showLoading({
title: '压缩中...'
});
let compressImgs = [];
let results = [];
tempFilePaths.forEach((item, index) => {
compressImgs.push(new Promise((resolve, reject) => {
// #ifndef H5
uni.compressImage({
src: item,
quality: this.quality,
success: res => {
//console.log('compressImage', res.tempFilePath)
results.push(res.tempFilePath);
resolve(res.tempFilePath);
},
fail: (err) => {
//console.log(err.errMsg);
reject(err);
},
complete: () => {
//uni.hideLoading();
}
})
// #endif
// #ifdef H5
this.canvasDataURL(item, {
quality: this.quality / 100
}, (base64Codes) => {
//this.imgUpload(base64Codes);
results.push(base64Codes);
resolve(base64Codes);
})
// #endif
}))
})
Promise.all(compressImgs) //
.then((results) => {
uni.hideLoading();
//console.log('imgCompress', type)
this.imgUpload(results, type);
})
.catch((res, object) => {
uni.hideLoading();
});
},
imgUpload(tempFilePaths, type) { //type 0 1
// if (this.action == '') {
// uni.showToast({
// title: '',
// icon: 'none',
// duration: 2000
// });
// return false;
// }
if (this.action == 'uniCloud') {
this.uniCloudUpload(tempFilePaths, type)
return
}
uni.showLoading({
title: '上传中'
});
//console.log('imgUpload', tempFilePaths)
let uploadImgs = [];
tempFilePaths.forEach((item, index) => {
uploadImgs.push(new Promise((resolve, reject) => {
//console.log(index, item)
const uploadTask = uni.uploadFile({
url: this.action, //
filePath: item,
name: this.name,
fileType: 'image',
formData: this.formData,
header: this.headers,
success: (uploadFileRes) => {
//uni.hideLoading();
//console.log(typeof this.uploadSuccess)
//console.log('')
uploadFileRes.fileType = type
if (typeof this.uploadSuccess == 'function') {
let thisUploadSuccess = this.uploadSuccess(
uploadFileRes)
if (thisUploadSuccess.success) {
let keyName = '';
// #ifndef VUE3
keyName = 'value'
// #endif
// #ifdef VUE3
keyName = 'modelValue'
// #endif
if (this.dataType == 0) {
this[keyName].push(thisUploadSuccess.url)
} else {
this[keyName].push({
type: type,
url: thisUploadSuccess.url,
...thisUploadSuccess
})
}
//this.$emit("input", this.uploadLists);
// #ifndef VUE3
this.$emit("input", this.uploadLists);
// #endif
// #ifdef VUE3
this.$emit("update:modelValue", this.uploadLists);
// #endif
}
}
resolve(uploadFileRes);
this.$emit("uploadSuccess", uploadFileRes);
},
fail: (err) => {
console.log(err);
//uni.hideLoading();
reject(err);
this.$emit("uploadFail", err);
},
complete: () => {
//uni.hideLoading();
}
});
}))
})
Promise.all(uploadImgs) //
.then((results) => {
uni.hideLoading();
})
.catch((res, object) => {
uni.hideLoading();
this.$emit("uploadFail", res);
});
// uploadTask.onProgressUpdate((res) => {
// //console.log('',)
// uni.showLoading({
// title: '' + res.progress + '%'
// });
// if (res.progress == 100) {
// uni.hideLoading();
// }
// });
},
uniCloudUpload(tempFilePaths, type) {
uni.showLoading({
title: '上传中'
});
console.log('uniCloudUpload', tempFilePaths);
let uploadImgs = [];
tempFilePaths.forEach((item, index) => {
uploadImgs.push(new Promise((resolve, reject) => {
uniCloud.uploadFile({
filePath: item,
cloudPath: this.guid() + '.' + this.getFileType(item, type),
success(uploadFileRes) {
if (uploadFileRes.success) {
resolve(uploadFileRes.fileID);
}
},
fail(err) {
console.log(err);
reject(err);
},
complete() {}
});
}))
})
Promise.all(uploadImgs) //
.then((results) => {
uni.hideLoading();
// console.log('then', results)
uniCloud.getTempFileURL({
fileList: results,
success: (res) => {
//console.log('success',res.fileList)
res.fileList.forEach(item => {
//console.log(item.tempFileURL)
//this.value.push(item.tempFileURL)
// #ifndef VUE3
this.value.push(item.tempFileURL)
this.$emit("input", this.value);
// #endif
// #ifdef VUE3
this.modelValue.push(item.tempFileURL)
this.$emit("update:modelValue", this.modelValue);
// #endif
})
},
fail() {},
complete() {}
});
})
.catch((res, object) => {
uni.hideLoading();
});
},
getFileType(path, type) { //jpg mp4
// #ifdef H5
var result = type == 0 ? 'jpg' : 'mp4';
// #endif
// #ifndef H5
var result = path.split('.').pop().toLowerCase();
// #ifdef MP
if (this.compress) { //
result = type == 0 ? 'jpg' : 'mp4';
}
// #endif
// #endif
return result;
},
guid() {
return 'xxxxxxxx-date-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0,
v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
}).replace(/date/g, function(c) {
return Date.parse(new Date());
});
},
canvasDataURL(path, obj, callback) {
var img = new Image();
img.src = path;
img.onload = function() {
var that = this;
//
var w = that.width,
h = that.height,
scale = w / h;
w = obj.width || w;
h = obj.height || (w / scale);
var quality = 0.8; // 0.8
//canvas
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
//
var anw = document.createAttribute("width");
anw.nodeValue = w;
var anh = document.createAttribute("height");
anh.nodeValue = h;
canvas.setAttributeNode(anw);
canvas.setAttributeNode(anh);
ctx.drawImage(that, 0, 0, w, h);
//
if (obj.quality && obj.quality <= 1 && obj.quality > 0) {
quality = obj.quality;
}
// quality
var base64 = canvas.toDataURL('image/jpeg', quality);
// base64
callback(base64);
}
},
}
}
</script>
<style>
.preview-full {
position: fixed;
top: 0;
left: 0;
bottom: 0;
width: 100%;
height: 100%;
z-index: 1002;
}
.preview-full video {
width: 100%;
height: 100%;
z-index: 1002;
}
.preview-full-close {
position: fixed;
right: 32rpx;
top: 25rpx;
width: 80rpx;
height: 80rpx;
line-height: 60rpx;
text-align: center;
z-index: 1003;
/* background-color: #808080; */
color: #fff;
font-size: 65rpx;
font-weight: bold;
text-shadow: 1px 2px 5px rgb(0 0 0);
}
/* .preview-full-close-before,
.preview-full-close-after {
position: absolute;
top: 50%;
left: 50%;
content: '';
height: 60rpx;
margin-top: -30rpx;
width: 6rpx;
margin-left: -3rpx;
background-color: #FFFFFF;
z-index: 20000;
}
.preview-full-close-before {
transform: rotate(45deg);
}
.preview-full-close-after {
transform: rotate(-45deg);
} */
.htz-image-upload-list {
display: flex;
flex-wrap: wrap;
}
.htz-image-upload-Item {
width: 160rpx;
height: 160rpx;
margin: 13rpx;
border-radius: 10rpx;
position: relative;
}
.htz-image-upload-Item image {
width: 100%;
height: 100%;
border-radius: 10rpx;
}
.htz-image-upload-Item-video {
width: 100%;
height: 100%;
border-radius: 10rpx;
position: relative;
}
.htz-image-upload-Item-video-fixed {
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 100%;
height: 100%;
border-radius: 10rpx;
z-index: 996;
}
.htz-image-upload-Item video {
width: 100%;
height: 100%;
border-radius: 10rpx;
}
.htz-image-upload-Item-add {
font-size: 105rpx;
/* line-height: 160rpx; */
text-align: center;
border: 1px dashed #d9d9d9;
color: #d9d9d9;
}
.htz-image-upload-Item-del {
background-color: #f5222d;
font-size: 24rpx;
position: absolute;
width: 35rpx;
height: 35rpx;
line-height: 35rpx;
text-align: center;
top: 0;
right: 0;
z-index: 997;
color: #fff;
}
.htz-image-upload-Item-del-cover {
background-color: #f5222d;
font-size: 24rpx;
position: absolute;
width: 35rpx;
height: 35rpx;
text-align: center;
top: 0;
right: 0;
color: #fff;
/* #ifdef APP-PLUS */
line-height: 25rpx;
/* #endif */
/* #ifndef APP-PLUS */
line-height: 35rpx;
/* #endif */
z-index: 997;
}
.htz-image-upload-Item-video-app-poster {
width: 100%;
height: 100%;
}
</style>

@ -71,6 +71,9 @@
"serviceHost" : ""
}
}
},
"router" : {
"base" : "/h5/"
}
}
}

@ -1,121 +1,185 @@
<template>
<view class="wrap">
<uni-section title="个人信息" type="line">
<view class="personinfo">
<view class="justify-between">
<view class="flex-item">所属街道</view>
<view class="flex-item">{{form.street}}</view>
<view class="wrap">
<uni-segmented-control :current="current" :values="items" @clickItem="onClickItem" styleType="text" activeColor="#b21f1f"></uni-segmented-control>
<view class="content">
<view v-show="current === 0">
<uni-section title="个人信息" type="line">
<view class="personinfo">
<view class="justify-between">
<view class="flex-item">所属街道</view>
<view class="flex-item">{{form.jiedao}}</view>
</view>
<view class="justify-between">
<view class="flex-item">姓名</view>
<view class="flex-item">{{form.name}}</view>
</view>
<view class="justify-between">
<view class="flex-item">民族</view>
<view class="flex-item">{{form.nation}}</view>
</view>
<view class="justify-between">
<view class="flex-item">性别</view>
<view class="flex-item">{{form.sex}}</view>
</view>
<view class="justify-between">
<view class="flex-item">婚姻状况</view>
<view class="flex-item">{{form.marry}}</view>
</view>
<view class="justify-between">
<view class="flex-item">出生年月</view>
<view class="flex-item">{{form.birthday}}</view>
</view>
<view class="justify-between">
<view class="flex-item">身份证</view>
<view class="flex-item">{{form.idcard}}</view>
</view>
<view class="justify-between">
<view class="flex-item">联系电话</view>
<view class="flex-item">{{form.mobile}}</view>
</view>
<view class="justify-between">
<view class="flex-item">固话</view>
<view class="flex-item">{{form.telephone}}</view>
</view>
<view class="justify-between">
<view class="flex-item">文化程度</view>
<view class="flex-item">{{form.education}}</view>
</view>
<view class="justify-between">
<view class="flex-item">特长</view>
<view class="flex-item">{{form.hobily}}</view>
</view>
<view class="justify-between">
<view class="flex-item">就业情况</view>
<view class="flex-item">{{form.isjob}}</view>
</view>
<view class="justify-between">
<view class="flex-item">就业单位</view>
<view class="flex-item">{{form.company}}</view>
</view>
<view class="justify-between">
<view class="flex-item">户口性质</view>
<view class="flex-item">{{form.household}}</view>
</view>
<view class="justify-between justify-column">
<view class="flex-item">户籍地址</view>
<view class="flex-item">{{form.address}}</view>
</view>
<view class="justify-between justify-column">
<view class="flex-item">现居住地</view>
<view class="flex-item">{{form.reside}}</view>
</view>
</view>
</uni-section>
<uni-section title="残疾证信息" type="line">
<view class="justify-between">
<view class="flex-item">残疾证</view>
<view class="flex-item">{{form.number}}</view>
</view>
<view class="justify-between">
<view class="flex-item">残疾类别</view>
<view class="flex-item">{{form.disabilitytype}}</view>
</view>
<view class="justify-between">
<view class="flex-item">残疾等级</view>
<view class="flex-item">{{form.disabilitylevel}}</view>
</view>
<view class="justify-between justify-column">
<view class="flex-item">残疾详情</view>
<view class="flex-item">{{form.disabilitydetail}}</view>
</view>
<view class="justify-between">
<view class="flex-item">首次办证日期</view>
<view class="flex-item">{{form.start_time?form.start_time.substring(0,10):''}}</view>
</view>
<view class="justify-between">
<view class="flex-item">有效期至</view>
<view class="flex-item">{{form.validity?form.validity.substring(0,10):''}}</view>
</view>
<view class="justify-between">
<view class="flex-item">最后审核时间</view>
<view class="flex-item">{{form.end_time?form.end_time.substring(0,10):''}}</view>
</view>
<view class="justify-between">
<view class="flex-item">最后修改时间</view>
<view class="flex-item">{{form.end_change?form.end_change.substring(0,10):''}}</view>
</view>
</uni-section>
<uni-section title="监护人信息" type="line">
<view class="justify-between">
<view class="flex-item">监护人</view>
<view class="flex-item">{{form.guardian}}</view>
</view>
<view class="justify-between">
<view class="flex-item">与监护人关系</view>
<view class="flex-item">{{form.relationship}}</view>
</view>
<view class="justify-between">
<view class="flex-item">联系电话</view>
<view class="flex-item">{{form.guardian_mobile}}</view>
</view>
<view class="justify-between">
<view class="flex-item">固话</view>
<view class="flex-item">{{form.guardian_telephone}}</view>
</view>
<view class="justify-between justify-column">
<view class="flex-item">备注</view>
<view class="flex-item">{{form.remark}}</view>
</view>
</uni-section>
</view>
<view class="justify-between">
<view class="flex-item">姓名</view>
<view class="flex-item">{{form.name}}</view>
<view v-show="current === 1">
<block v-if="workflows.length>0">
<uni-section :title="item.guanlianbiaoming" type="line" v-for="item in workflows">
<view class="personinfo">
<view class="justify-between">
<view class="flex-item">业务年份</view>
<view class="flex-item">{{item.detail['year']}}</view>
</view>
<block v-for="(tab,key) of tableShow">
<block v-for="(tabl,keyl) of tab">
<view class="justify-between" v-if="item.guanlianbiao==key">
<view class="flex-item">{{tabl}}</view>
<view class="flex-item">{{item.detail[keyl]}}</view>
</view>
</block>
</block>
</view>
</uni-section>
</block>
<block v-else>
暂无业务信息
</block>
</view>
<view class="justify-between">
<view class="flex-item">民族</view>
<view class="flex-item">{{form.nation}}</view>
<view v-show="current === 2">
<block v-if="viewrecords.length>0">
<uni-section :title="item.viewtime" type="line" v-for="item in viewrecords">
<view class="personinfo">
<view class="justify-between">
<view class="flex-item">访视情景</view>
<view class="flex-item">{{item.viewscene}}</view>
</view>
</view>
<view class="personinfo">
<view class="justify-between">
<view class="flex-item">人员状态</view>
<view class="flex-item">{{item.viewstatus}}</view>
</view>
</view>
</uni-section>
</block>
<block v-else>
暂无业务信息
</block>
</view>
<view class="justify-between">
<view class="flex-item">性别</view>
<view class="flex-item">{{form.sex}}</view>
</view>
<view class="justify-between">
<view class="flex-item">婚姻状况</view>
<view class="flex-item">{{form.marry}}</view>
</view>
<view class="justify-between">
<view class="flex-item">出生年月</view>
<view class="flex-item">{{form.birthday}}</view>
</view>
<view class="justify-between">
<view class="flex-item">身份证</view>
<view class="flex-item">{{form.idcard}}</view>
</view>
<view class="justify-between">
<view class="flex-item">联系电话</view>
<view class="flex-item">{{form.mobile}}</view>
</view>
<view class="justify-between">
<view class="flex-item">固话</view>
<view class="flex-item">{{form.telephone}}</view>
</view>
<view class="justify-between">
<view class="flex-item">文化程度</view>
<view class="flex-item">{{form.education}}</view>
</view>
<view class="justify-between">
<view class="flex-item">户口性质</view>
<view class="flex-item">{{form.household}}</view>
</view>
<view class="justify-between justify-column">
<view class="flex-item">户籍地址</view>
<view class="flex-item">{{form.address}}</view>
</view>
<view class="justify-between justify-column">
<view class="flex-item">现居住地</view>
<view class="flex-item">{{form.reside}}</view>
</view>
</view>
</uni-section>
<uni-section title="残疾证信息" type="line">
<view class="justify-between">
<view class="flex-item">残疾证</view>
<view class="flex-item">{{form.number}}</view>
</view>
<view class="justify-between">
<view class="flex-item">残疾类别</view>
<view class="flex-item">{{form.disabilitytype}}</view>
</view>
<view class="justify-between">
<view class="flex-item">残疾等级</view>
<view class="flex-item">{{form.disabilitylevel}}</view>
</view>
<view class="justify-between justify-column">
<view class="flex-item">残疾详情</view>
<view class="flex-item">{{form.disabilitydetail}}</view>
</view>
<view class="justify-between">
<view class="flex-item">首次办证日期</view>
<view class="flex-item">{{form.start_time?form.start_time.substring(0,10):''}}</view>
</view>
<view class="justify-between">
<view class="flex-item">有效期至</view>
<view class="flex-item">{{form.validity?form.validity.substring(0,10):''}}</view>
</view>
<view class="justify-between">
<view class="flex-item">最后审核时间</view>
<view class="flex-item">{{form.end_time?form.end_time.substring(0,10):''}}</view>
</view>
<view class="justify-between">
<view class="flex-item">最后修改时间</view>
<view class="flex-item">{{form.end_change?form.end_change.substring(0,10):''}}</view>
</view>
</uni-section>
<uni-section title="监护人信息" type="line">
<view class="justify-between">
<view class="flex-item">监护人</view>
<view class="flex-item">{{form.guardian}}</view>
</view>
<view class="justify-between">
<view class="flex-item">与监护人关系</view>
<view class="flex-item">{{form.relationship}}</view>
</view>
<view class="justify-between">
<view class="flex-item">联系电话</view>
<view class="flex-item">{{form.guardian_mobile}}</view>
</view>
<view class="justify-between">
<view class="flex-item">固话</view>
<view class="flex-item">{{form.guardian_telephone}}</view>
</view>
<view class="justify-between justify-column">
<view class="flex-item">备注</view>
<view class="flex-item">{{form.remark}}</view>
</view>
</uni-section>
</view>
</template>
@ -123,12 +187,92 @@
export default {
data() {
return {
current:0,
items:['个人信息','业务信息','访视信息'],
select:{
id:'',
tableName:'records',
show_relation:['admin','department'],
},
form:{}
form:{},
workflows:[],
viewrecords:[],
tableShow:{
fuels:{
money:'补贴金额'
},
reforms:{
reform_case:'改造方案'
},
medicines:{},
childrens:{
nianlingduan:'年龄段',
dingdianjigou:'定点机构'
},
assists:{
shenqingnianxian:'申请年限',
guanlinianxian:'管理年限',
sub_type:'辅具类别',
sum_num:'辅具数量',
apply_money:'可申请补贴金额',
get_money:'已申请补贴金额',
surplus_money:'结余金额'
},
communities:{
fuwuneirong:'服务内容',
tijianniandu:'体检年度',
tijianfangshi:'体检方式',
is_success:'是否完成',
is_date:'完成时间'
},
educations:{
school:'就读学校',
xueli:'学历层次',
class:'年级',
sub_money:'补贴金额'
},
raises:{
raise_name:'托养机构',
raise_type:'托养方式'
},
starts_addresses:{
starts_address:'经营场所地址',
starts_number:'统一社会信用代码',
starts_pay:'申请补贴费用',
},
starts_subsidys:{
starts_scale:'统一社会信用代码',
starts_money:'补贴金额'
},
doubles:{
jiatingzhuangkuang:'家庭状况',
shenghuobutieleixing:'生活补贴类型',
shenghuobutiejine:'生活补贴金额',
hulibutieleixing:'护理补贴类型',
hulibutiejine:'护理补贴金额'
},
disabilities:{
disabilitytype:'残疾类别',
disabilitylevel:'残疾等级'
},
trains:{
train_name:'培训名称'
},
insures:{
lingkuanrenxingming:'领款人姓名',
chuxianriqi:'出险日期',
jieanriqi:'结案日期',
peifujine:'赔付金额'
},
cancels:{},
jobs:{
jiuyezhuangkuang:'就业状况',
congshihangye:'从事行业',
jiuyetujing:'就业途径',
danweimingcheng:'单位名称'
}
},
}
},
onLoad(options) {
@ -136,7 +280,12 @@
this.select.id = options?options.id:''
this.loadDetail()
},
methods: {
methods: {
onClickItem(e){
if (this.current !== e.currentIndex) {
this.current = e.currentIndex
}
},
loadDetail() {
let that = this
this.util.request({
@ -149,6 +298,13 @@
},
utilSuccess: function(res) {
that.form = res
if(res.idcard_workflows_idcard_relation.length>0){
that.workflows = res.idcard_workflows_idcard_relation
}
if(res.idcard_viewrecords_idcard_relation.length>0){
that.viewrecords = res.idcard_viewrecords_idcard_relation
}
for(var k in that.form){
that.form[k] = that.form[k]?that.form[k]:''
}
@ -167,6 +323,9 @@
</script>
<style scoped>
page{
background-color: #fff;
}
.wrap{
background-color: #fff;
padding:0 30rpx;

@ -14,11 +14,18 @@
<uni-data-checkbox selectedColor='#b21f1f' v-model="form.viewstatus"
:localdata="lists.viewstatusList"
@change="(e)=> selectChange(e,'viewstatus')"></uni-data-checkbox>
</uni-forms-item>
<uni-forms-item label="附件" prop="avatar" labelWidth="60px">
<htz-image-upload :max="1" v-model="avatarList" mediaType="image" :chooseNum="1"
:sourceType="['album','camera']" :compress="false" :quality="80" :formData="otherData"
:remove="true" :dataType="1" @uploadSuccess="uploadSuccess" @imgDelete="imgDelete"
@uploadFail="uploadFail" :action="action"></htz-image-upload>
<!-- <u-textarea v-model="form.avatar" placeholder="请输入内容"></u-textarea> -->
</uni-forms-item>
</uni-section>
<uni-section title="个人信息" type="line">
<uni-forms-item label="所属街道" required>
<uni-data-select selectedColor='#b21f1f' v-model="form.street" :localdata="lists.streetList"
<uni-data-select selectedColor='#b21f1f' v-model="form.jiedao" :localdata="lists.streetList"
@change="(e)=> selectChange(e,'street')"></uni-data-select>
</uni-forms-item>
<uni-forms-item label="姓名" required>
@ -51,6 +58,15 @@
<uni-forms-item label="文化程度">
<uni-data-select v-model="form.education" :localdata="lists.educationList"
@change="(e)=> selectChange(e,'education')"></uni-data-select>
</uni-forms-item>
<uni-forms-item label="特长">
<uni-easyinput type="text" v-model="form.hobily" placeholder="请输入特长"></uni-easyinput>
</uni-forms-item>
<uni-forms-item label="就业情况">
<uni-easyinput type="text" v-model="form.isjob" placeholder="请输入就业情况"></uni-easyinput>
</uni-forms-item>
<uni-forms-item label="就业单位">
<uni-easyinput type="text" v-model="form.company" placeholder="请输入就业单位"></uni-easyinput>
</uni-forms-item>
<uni-forms-item label="户口性质">
<uni-easyinput type="text" v-model="form.household" placeholder="请输入户口性质"></uni-easyinput>
@ -122,8 +138,13 @@
</view>
</template>
<script>
export default {
<script>
import htzImageUpload from '@/components/htz-image-upload/htz-image-upload.vue'
export default {
components: {
htzImageUpload
},
data() {
return {
select: {
@ -131,7 +152,12 @@
tableName: 'records',
submitName: 'viewrecords',
show_relation: ['admin', 'department'],
},
},
action: '',
otherData: {
token: ''
},
avatarList: [],
form: {},
rules: {},
lists: {
@ -148,10 +174,34 @@
}
},
onLoad(options) {
this.select.id = options ? options.id : ''
this.select.id = options ? options.id : ''
this.action = this.util.HOST + "/api/admin/upload-file"
let data =uni.getStorageSync("userInfo_token")
this.otherData.token = data['token'];
this.getLabel()
},
methods: {
methods: {
uploadSuccess(res) {
console.log("succ", res)
uni.showLoading({
title: "上传成功"
})
let data = JSON.parse(res.data)
this.form.uploads = data.id
this.avatarList = []
this.avatarList.push({
type: 0,
url: data.url
})
},
uploadFail(res) {
console.log("fail", res)
},
imgDelete(res) {
this.avatarList = res.tempFilePaths
this.form.uploads = ''
},
timeChange(e, type) {
console.log(e, type)
},
@ -306,7 +356,10 @@
show_relation: this.select.show_relation
},
utilSuccess: function(res) {
that.form = res
that.form = res
if(res.uploads_uploads_id_relation){
that.avatarList.push(res.uploads_uploads_id_relation.url)
}
console.log(that.form)
},
utilFail: function(res) {
@ -385,5 +438,8 @@
/deep/ .button {
background-color: #b21f1f;
color: #fff
}
/deep/ .htz-image-upload-Item-add{
line-height:70px;
}
</style>

@ -1,9 +1,9 @@
## 1.2.02021-11-19
- 优化 组件UI并提供设计资源详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-segmented-control](https://uniapp.dcloud.io/component/uniui/uni-segmented-control)
## 1.1.02021-07-30
- 组件兼容 vue3如何创建vue3项目详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
## 1.0.52021-05-12
- 新增 项目示例地址
## 1.0.42021-02-05
- 调整为uni_modules目录规范
## 1.1.02021-07-30
- 组件兼容 vue3如何创建vue3项目详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
## 1.0.52021-05-12
- 新增 项目示例地址
## 1.0.42021-02-05
- 调整为uni_modules目录规范

@ -5,7 +5,7 @@
index === currentIndex&&styleType === 'button' ? 'segmented-control__item--button--active': '',
index === 0&&styleType === 'button' ? 'segmented-control__item--button--first': '',
index === values.length - 1&&styleType === 'button' ? 'segmented-control__item--button--last': '' ]" :key="index"
:style="{ backgroundColor: index === currentIndex && styleType === 'button' ? activeColor : '',borderColor: index === currentIndex&&(styleType === 'text'||styleType === 'button')?activeColor:'#d9d9d9' }"
:style="{ backgroundColor: index === currentIndex && styleType === 'button' ? activeColor : '',borderColor: index === currentIndex&&styleType === 'text'||styleType === 'button'?activeColor:'transparent' }"
class="segmented-control__item" @click="_onClick(index)">
<view>
<text :style="{color:
@ -87,7 +87,7 @@
}
</script>
<style lang="scss" >
<style lang="scss" scoped>
.segmented-control {
/* #ifndef APP-NVUE */
display: flex;
@ -133,8 +133,8 @@
.segmented-control__item--text {
border-bottom-style: solid;
border-bottom-width: 2px;
padding: 6px 0;
border-bottom-width: 2px;
padding: 6px 0;
}
.segmented-control__text {
@ -142,4 +142,4 @@
line-height: 20px;
text-align: center;
}
</style>
</style>

@ -1,87 +1,87 @@
{
"id": "uni-segmented-control",
"displayName": "uni-segmented-control 分段器",
"version": "1.2.0",
"description": "分段器由至少 2 个分段控件组成,用作不同视图的显示",
"keywords": [
"uni-ui",
"uniui",
"分段器",
"segement",
"顶部选择"
],
"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-scss"],
"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": "y"
}
}
}
}
{
"id": "uni-segmented-control",
"displayName": "uni-segmented-control 分段器",
"version": "1.2.0",
"description": "分段器由至少 2 个分段控件组成,用作不同视图的显示",
"keywords": [
"uni-ui",
"uniui",
"分段器",
"segement",
"顶部选择"
],
"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-scss"],
"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": "y"
}
}
}
}
}

@ -0,0 +1,2 @@
<!DOCTYPE html><html lang=zh-CN><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><title>jintan-canlian-wx</title><script>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><link rel=stylesheet href=/h5/static/index.97465e7b.css></head><body><noscript><strong>Please enable JavaScript to continue.</strong></noscript><div id=app></div><script src=/h5/static/js/chunk-vendors.9763b41a.js></script><script src=/h5/static/js/index.cef307e0.js></script></body></html>

@ -0,0 +1,69 @@
body * {
box-sizing: border-box;
flex-shrink: 0;
}
body {
font-family: PingFangSC-Regular, Roboto, Helvetica Neue, Helvetica, Tahoma,
Arial, PingFang SC-Light, Microsoft YaHei;
}
button {
margin: 0;
padding: 0;
border: 1px solid transparent;
outline: none;
background-color: transparent;
}
button:active {
opacity: 0.6;
}
.flex-col {
display: flex;
flex-direction: column;
}
.flex-row {
display: flex;
flex-direction: row;
}
.justify-start {
display: flex;
justify-content: flex-start;
}
.justify-center {
display: flex;
justify-content: center;
}
.justify-end {
display: flex;
justify-content: flex-end;
}
.justify-evenly {
display: flex;
justify-content: space-evenly;
}
.justify-around {
display: flex;
justify-content: space-around;
}
.justify-between {
display: flex;
justify-content: space-between;
}
.justify-column{
display: flex;
flex-direction: column;
}
.align-start {
display: flex;
align-items: flex-start;
}
.align-center {
display: flex;
align-items: center;
}
.align-end {
display: flex;
align-items: flex-end;
}

@ -0,0 +1,20 @@
@font-face {
font-family: "customicons"; /* Project id 2878519 */
src:url('/static/customicons.ttf') format('truetype');
}
.customicons {
font-family: "customicons" !important;
}
.youxi:before {
content: "\e60e";
}
.wenjian:before {
content: "\e60f";
}
.zhuanfa:before {
content: "\e610";
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["pages-index-login"],{"3b51":function(t,e,n){t.exports=n.p+"static/img/logo.aa78146b.png"},"5b36":function(t,e,n){"use strict";n.d(e,"b",(function(){return o})),n.d(e,"c",(function(){return a})),n.d(e,"a",(function(){return i}));var i={uniForms:n("3e2d").default,uniFormsItem:n("e924").default,uniEasyinput:n("ac32").default},o=function(){var t=this,e=t.$createElement,i=t._self._c||e;return i("v-uni-view",{staticClass:"containers",style:{height:t.winHeight+"px"}},[i("v-uni-view",{staticClass:"logo",style:{height:.5*t.winHeight+"px",position:"relative"}},[i("v-uni-view",[i("v-uni-image",{attrs:{src:n("3b51"),mode:"widthFix"}}),i("v-uni-image",{attrs:{src:n("c8ee"),mode:"widthFix"}})],1)],1),i("v-uni-view",{staticClass:"login"},[i("uni-forms",{ref:"formdata",attrs:{model:t.form,border:!0,rules:t.rules,labelWidth:"100px","label-position":"top"}},[i("uni-forms-item",{attrs:{label:"用户名",name:"name"}},[i("uni-easyinput",{attrs:{inputBorder:!1,placeholder:"请输入用户名"},model:{value:t.form.name,callback:function(e){t.$set(t.form,"name",e)},expression:"form.name"}})],1),i("uni-forms-item",{attrs:{label:"密码",name:"password"}},[i("uni-easyinput",{attrs:{inputBorder:!1,type:"password",placeholder:"请输入密码"},model:{value:t.form.password,callback:function(e){t.$set(t.form,"password",e)},expression:"form.password"}})],1)],1),i("v-uni-view",{staticClass:"sbtn"},[i("v-uni-button",{attrs:{type:"primary",size:"large"},on:{click:function(e){arguments[0]=e=t.$handleEvent(e),t.submit.apply(void 0,arguments)}}},[t._v("登录")])],1)],1)],1)},a=[]},"71b3":function(t,e,n){"use strict";n.r(e);var i=n("5b36"),o=n("ff36");for(var a in o)["default"].indexOf(a)<0&&function(t){n.d(e,t,(function(){return o[t]}))}(a);n("aa06");var r=n("f0c5"),s=Object(r["a"])(o["default"],i["b"],i["c"],!1,null,"25b35bff",null,!1,i["a"],void 0);e["default"]=s.exports},"9a39":function(t,e,n){var i=n("e847");i.__esModule&&(i=i.default),"string"===typeof i&&(i=[[t.i,i,""]]),i.locals&&(t.exports=i.locals);var o=n("4f06").default;o("5df0e505",i,!0,{sourceMap:!1,shadowMode:!1})},aa06:function(t,e,n){"use strict";var i=n("9a39"),o=n.n(i);o.a},c8ee:function(t,e,n){t.exports=n.p+"static/img/logo-title.2ff28c5f.png"},e847:function(t,e,n){var i=n("24fb");e=i(!1),e.push([t.i,".containers[data-v-25b35bff]{background-color:#fff;padding:0 %?40?%;padding-bottom:20px}.logo uni-view[data-v-25b35bff]{position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.sbtn[data-v-25b35bff]{margin-top:%?60?%}[data-v-25b35bff] .sbtn uni-button{background-color:#b21f1f;color:#fff}",""]),t.exports=e},fcbf:function(t,e,n){"use strict";n("7a82"),Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var i={data:function(){return{winHeight:0,isLogin:"",form:{},rules:{name:{rules:[{required:!0,errorMessage:"请输入用户名"}]},password:{rules:[{required:!0,errorMessage:"请输入密码"}]}}}},onLoad:function(){this.winHeight=uni.getSystemInfoSync().screenHeight-2*uni.getSystemInfoSync().statusBarHeight-20,this.isLogin=uni.getStorageSync("userInfo_token").token,this.util.isNull(this.isLogin)||uni.redirectTo({url:"/records/list"})},methods:{submit:function(){var t=this;this.$refs["formdata"].validate().then((function(e){t.util.request({api:"/api/admin/auth/login",data:{username:t.form.name,password:t.form.password},method:"POST",utilSuccess:function(t){uni.setStorageSync("userInfo_token",{token:t.access_token}),uni.showToast({title:"登录成功",duration:2e3,success:function(){uni.redirectTo({url:"/records/list"})}})},utilFail:function(t){uni.showToast({title:t,duration:2e3,icon:"none"})}})})).catch((function(t){console.log("err",t)}))}}};e.default=i},ff36:function(t,e,n){"use strict";n.r(e);var i=n("fcbf"),o=n.n(i);for(var a in i)["default"].indexOf(a)<0&&function(t){n.d(e,t,(function(){return i[t]}))}(a);e["default"]=o.a}}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Loading…
Cancel
Save