This commit is contained in:
gyj
2024-02-05 13:52:55 +08:00
parent accf8e8c3f
commit decd8e6edb
10 changed files with 2068 additions and 1828 deletions
+35
View File
@@ -77,4 +77,39 @@ export function updateBooking(data) {
method: 'post', method: 'post',
data: data data: data
}) })
}
// 根据机构id查询模板
export function getTemplate(data) {
return request({
url: `/deptIdentify/getTemplate`,
method: 'get',
params: data
})
}
// 根据身份证获取生日和性别
export function getInfoByIdCard(query) {
return request({
url: '/caseApplication/getInfoByIdCard',
method: 'get',
params: query
})
}
/** 新增案件 */
export function caseApplicationInsert(data) {
return request({
url: '/caseApplication/insert',
method: 'post',
data: data
})
}
// 修改立案申请接口
export function updateComfire(data) {
return request({
url: "/caseApplication/update",
method: "post",
data: data,
})
} }
+221 -53
View File
@@ -12,11 +12,13 @@
<uni-forms-item label="案件标的:" name="caseSubjectAmount" label-width="120px" required> <uni-forms-item label="案件标的:" name="caseSubjectAmount" label-width="120px" required>
<uni-easyinput v-model="formData.caseSubjectAmount" type="text" placeholder="请输入案件标的" /> <uni-easyinput v-model="formData.caseSubjectAmount" type="text" placeholder="请输入案件标的" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="调解模板:" label-width="120px" required> <uni-forms-item label="模板:" name="templateId" label-width="120px" required
<uni-data-select></uni-data-select> :rules="[{'required': true,errorMessage: '模板不能为空'}]"
>
<uni-data-select :localdata="templateList" v-model="formData.templateId"></uni-data-select>
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="申请人案件证据资料上传:" name="headImage" label-width="120px"> <uni-forms-item label="申请人案件证据资料上传:" name="headImage" label-width="120px">
<uni-file-picker ref="files" :auto-upload="false" @select="select" :limit='1' /> <uni-file-picker ref="files" file-mediatype="all" :auto-upload="false" @select="select" :limit='1' />
</uni-forms-item> </uni-forms-item>
<uni-section title="双方信息" type="line" padding></uni-section> <uni-section title="双方信息" type="line" padding></uni-section>
<uni-forms-item label="选择机构或自然人" label-width="120px" name="objectiJuris"> <uni-forms-item label="选择机构或自然人" label-width="120px" name="objectiJuris">
@@ -25,85 +27,145 @@
v-model="formData.affiliate.organizeFlag" v-model="formData.affiliate.organizeFlag"
@change='clearValidate'></uni-data-checkbox> @change='clearValidate'></uni-data-checkbox>
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="申请人:" label-width="120px" required v-if="formData.affiliate.organizeFlag==0"> <uni-forms-item label="申请人:" name="affiliate.applicationName"
<uni-easyinput type="text" placeholder="请输入申请人名称" /> :rules="[{'required': true,errorMessage: '申请人不能为空'}]"
label-width="120px" required v-if="formData.affiliate.organizeFlag==0">
<uni-easyinput v-model="formData.affiliate.applicationName" type="text" placeholder="请输入申请人名称" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="申请人机构名称:" label-width="120px" required <uni-forms-item label="申请人机构名称:" name="affiliate.applicationName" label-width="120px"
:rules="[{'required': true,errorMessage: '申请人机构名称为空'}]" required
v-if="formData.affiliate.organizeFlag==1" v-if="formData.affiliate.organizeFlag==1"
> >
<uni-easyinput type="text" placeholder="请输入申请人机构名称" /> <uni-easyinput v-model="formData.affiliate.applicationName"
type="text" placeholder="请输入申请人机构名称" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="申请人身份证号码:" label-width="120px" required <uni-forms-item label="申请人身份证号码:" name="affiliate.code" label-width="120px" required
:rules="[
{'required': true,errorMessage: '申请人身份证号码为空'},
{pattern:'^[1-9]\\d{5}(18|19|([23]\\d))\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$',errorMessage:'申请人身份证格式错误'}
]"
v-if="formData.affiliate.organizeFlag==0" v-if="formData.affiliate.organizeFlag==0"
> >
<uni-easyinput type="text" placeholder="请输入申请人身份证号码" /> <uni-easyinput v-model="formData.affiliate.code" type="text" placeholder="请输入申请人身份证号码" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="统一社会信用代码:" label-width="120px" required <uni-forms-item label="统一社会信用代码:" name="affiliate.code" label-width="120px" required
:rules="[{'required': true,errorMessage: '统一社会信用代码为空'}]"
v-if="formData.affiliate.organizeFlag==1" v-if="formData.affiliate.organizeFlag==1"
> >
<uni-easyinput type="text" placeholder="请输入统一社会信用代码:" /> <uni-easyinput type="text" v-model="formData.affiliate.code" placeholder="请输入统一社会信用代码:" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="申请人邮箱:" label-width="120px" required> <uni-forms-item label="申请人邮箱:" name="affiliate.applicationEmail" label-width="120px" required
<uni-easyinput type="text" placeholder="请输入申请人邮箱" /> :rules="[
{'required': true,errorMessage: '申请人邮箱不能为空'},
{pattern:'^\\S+?@\\S+?\\.\\S+?$',errorMessage:'邮箱格式不正确'}
]"
>
<uni-easyinput v-model="formData.affiliate.applicationEmail"
type="text" placeholder="请输入申请人邮箱" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="申请人电话:" label-width="120px" required> <uni-forms-item label="申请人电话:" name="affiliate.applicationPhone" label-width="120px" required
<uni-easyinput type="text" placeholder="请输入申请人电话" /> :rules="[
{'required': true,errorMessage: '申请人电话不能为空'},
{pattern:'^[1][3,4,5,6,7,8,9][0-9]{9}$',errorMessage:'申请人电话格式不正确'}
]"
>
<uni-easyinput v-model="formData.affiliate.applicationPhone" type="text" placeholder="请输入申请人电话" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="法定代表人:" label-width="120px" required> <uni-forms-item label="法定代表人:" name="affiliate.compLegalPerson" label-width="120px" required
<uni-easyinput type="text" placeholder="请输入法定代表人" /> :rules="[{'required': true,errorMessage: '法定代表人不能为空'}]"
>
<uni-easyinput v-model="formData.affiliate.compLegalPerson" type="text" placeholder="请输入法定代表人" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="申请人住所:" label-width="120px" required> <uni-forms-item label="申请人住所:" name="affiliate.applicantHome" label-width="120px" required
<uni-easyinput type="text" placeholder="请输入申请人住所" /> :rules="[{'required': true,errorMessage: '申请人住所不能为空'}]"
>
<uni-easyinput v-model="formData.affiliate.applicantHome" type="text" placeholder="请输入申请人住所" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="申请人联系地址:" label-width="120px" required> <uni-forms-item label="申请人联系地址:" name="affiliate.applicantAddress" label-width="120px" required
<uni-easyinput type="text" placeholder="请输入申请人联系地址" /> :rules="[{'required': true,errorMessage: '申请人联系地址不能为空'}]"
>
<uni-easyinput v-model="formData.affiliate.applicantAddress" type="text" placeholder="请输入申请人联系地址" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="代理人联系电话:" label-width="120px" v-if="formData.affiliate.organizeFlag==0"> <uni-forms-item label="代理人联系电话:" name="affiliate.contactTelphoneAgent" label-width="120px"
<uni-easyinput type="text" placeholder="请输入代理人联系电话" />
v-if="formData.affiliate.organizeFlag==0">
<uni-easyinput v-model="formData.affiliate.contactTelphoneAgent" type="text" placeholder="请输入代理人联系电话" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="代理人联系电话:" label-width="120px" required <uni-forms-item label="代理人联系电话:" name="affiliate.contactTelphoneAgent" label-width="120px" required
:rules="[
{'required': true,errorMessage: '代理人联系电话不能为空'},
{pattern:'^[1][3,4,5,6,7,8,9][0-9]{9}$',errorMessage:'代理人联系电话格式不正确'}
]"
v-if="formData.affiliate.organizeFlag==1" v-if="formData.affiliate.organizeFlag==1"
> >
<uni-easyinput type="text" placeholder="请输入代理人联系电话" /> <uni-easyinput v-model="formData.affiliate.contactTelphoneAgent" type="text" placeholder="请输入代理人联系电话" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="委托代理人姓名:" label-width="120px" v-if="formData.affiliate.organizeFlag==0"> <uni-forms-item label="委托代理人姓名:" name="affiliate.nameAgent" label-width="120px" v-if="formData.affiliate.organizeFlag==0">
<uni-easyinput type="text" placeholder="请输入委托代理人姓名" /> <uni-easyinput v-model="formData.affiliate.nameAgent" type="text" placeholder="请输入委托代理人姓名" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="委托代理人姓名:" label-width="120px" required <uni-forms-item label="委托代理人姓名:" name="affiliate.nameAgent" label-width="120px" required
:rules="[{'required': true,errorMessage: '委托代理人姓名不能为空'}]"
v-if="formData.affiliate.organizeFlag==1" v-if="formData.affiliate.organizeFlag==1"
> >
<uni-easyinput type="text" placeholder="请输入委托代理人姓名" /> <uni-easyinput v-model="formData.affiliate.nameAgent" type="text" placeholder="请输入委托代理人姓名" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="代理人邮箱:" label-width="120px" v-if="formData.affiliate.organizeFlag==0"> <uni-forms-item label="代理人邮箱:" name="affiliate.agentEmail" label-width="120px" v-if="formData.affiliate.organizeFlag==0">
<uni-easyinput type="text" placeholder="请输入代理人邮箱" /> <uni-easyinput v-model="formData.affiliate.agentEmail" type="text" placeholder="请输入代理人邮箱" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="代理人邮箱:" label-width="120px" required <uni-forms-item label="代理人邮箱:" name="affiliate.agentEmail" label-width="120px" required
:rules="[
{'required': true,errorMessage: '代理人邮箱不能为空'},
{pattern:'^\\S+?@\\S+?\\.\\S+?$',errorMessage:'邮箱格式不正确'}
]"
v-if="formData.affiliate.organizeFlag==1" v-if="formData.affiliate.organizeFlag==1"
> >
<uni-easyinput type="text" placeholder="请输入代理人邮箱" /> <uni-easyinput v-model="formData.affiliate.agentEmail" type="text" placeholder="请输入代理人邮箱" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="被申请人姓名:" label-width="120px" required> <uni-forms-item label="被申请人姓名:" name="affiliate.respondentName" label-width="120px" required
<uni-easyinput type="text" placeholder="请输入被申请人姓名" /> :rules="[{'required': true,errorMessage: '被申请人姓名不能为空'}]"
>
<uni-easyinput v-model="formData.affiliate.respondentName" type="text" placeholder="请输入被申请人姓名" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="被申请人联系电话:" label-width="120px" required> <uni-forms-item label="被申请人联系电话:" name="affiliate.respondentPhone" label-width="120px" required
<uni-easyinput type="text" placeholder="请输入被申请人联系电话" /> :rules="[
{'required': true,errorMessage: '被申请人联系电话不能为空'},
{pattern:'^[1][3,4,5,6,7,8,9][0-9]{9}$',errorMessage:'被申请人联系电话格式不正确'}
]"
>
<uni-easyinput v-model="formData.affiliate.respondentPhone" type="text" placeholder="请输入被申请人联系电话" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="被申请人身份证号:" label-width="120px" required> <uni-forms-item label="被申请人身份证号:" name="affiliate.respondentIdentityNum" label-width="120px" required
<uni-easyinput type="text" placeholder="请输入被申请人身份证号" /> :rules="[
{'required': true,errorMessage: '被申请人身份证号不能为空'},
{pattern:'^[1-9]\\d{5}(18|19|([23]\\d))\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$',errorMessage:'被申请人身份证格式错误'}
]"
>
<uni-easyinput v-model="formData.affiliate.respondentIdentityNum" @blur="handleBlur" type="text" placeholder="请输入被申请人身份证号" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="被申请人性别" label-width="120px" required> <uni-forms-item label="被申请人性别" label-width="120px" required>
<uni-data-checkbox class='checkbox' <uni-data-checkbox class='checkbox'
:disabled='true'
v-model="formData.affiliate.respondentSex" v-model="formData.affiliate.respondentSex"
:localdata="respondentSexy"></uni-data-checkbox> :localdata="respondentSexy"></uni-data-checkbox>
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="被申请人出生年月日" label-width="120px" > <uni-forms-item label="被申请人出生年月日" label-width="120px">
<uni-datetime-picker type="date" :clear-icon="false" /> <uni-datetime-picker v-model="formData.affiliate.respondentBirth" :disabled='true' type="date" :clear-icon="false" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="被申请人住所:" label-width="120px" required> <uni-forms-item label="被申请人住所:" name="affiliate.respondentHome" label-width="120px" required
<uni-easyinput type="text" placeholder="请输入被申请人住所" /> :rules="[{'required': true,errorMessage: '被申请人住所不能为空'}]"
>
<uni-easyinput v-model="formData.affiliate.respondentHome" type="text" placeholder="请输入被申请人住所" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="被申请人邮箱:" label-width="120px" required> <uni-forms-item label="被申请人邮箱:" name="affiliate.respondentEmail" label-width="120px" required
<uni-easyinput type="text" placeholder="请输入被申请人住所" /> :rules="[
{'required': true,errorMessage: '被申请人邮箱不能为空'},
{pattern:'^\\S+?@\\S+?\\.\\S+?$',errorMessage:'邮箱格式不正确'}
]"
>
<uni-easyinput v-model="formData.affiliate.respondentEmail" type="text" placeholder="请输入被申请人邮箱" />
</uni-forms-item> </uni-forms-item>
</uni-forms> </uni-forms>
<view class="determine" style="text-align: center;"> <view class="determine" style="text-align: center;">
@@ -119,6 +181,11 @@
</template> </template>
<script> <script>
import {getTemplate,getInfoByIdCard,caseApplicationInsert,updateComfire} from '../../../api/handlecase/index.js'
import {
getToken
} from '@/utils/auth'
import config from '@/config'
export default { export default {
data() { data() {
return { return {
@@ -126,9 +193,12 @@
affiliate:{ affiliate:{
organizeFlag: 0, organizeFlag: 0,
respondentSex: 0, respondentSex: 0,
} },
columnValueList: [],
caseAttachList: [],
}, },
tempFilePaths: null,
templateList:[],
objectiJurisArr: [{ objectiJurisArr: [{
text: '自然人', text: '自然人',
value: 0 value: 0
@@ -150,7 +220,7 @@
rules:[ rules:[
{ {
required: true, required: true,
errorMessage: '请输入申请人调解请求', errorMessage: '申请人调解请求不能为空',
}, },
], ],
}, },
@@ -158,7 +228,7 @@
rules:[ rules:[
{ {
required: true, required: true,
errorMessage: '请输入事实和理由', errorMessage: '事实和理由不能空',
}, },
], ],
}, },
@@ -166,10 +236,19 @@
rules:[ rules:[
{ {
required: true, required: true,
errorMessage: '请输入案件标的', errorMessage: '案件标的不能为空',
}, },
], ],
} },
respondentEmail:{
rules:[
{
required: true,
errorMessage: '邮箱不能为空',
}
],
},
} }
} }
@@ -177,20 +256,109 @@
}, },
methods:{ methods:{
clearValidate(val){ clearValidate(val){
this.$refs["form"].clearValidate()
}, },
submitReasont(){ submitReasont(){
this.$refs.form.validate().then(res=>{ this.$refs.form.validate().then(res=>{
this.insertFn(this.formData)
}).catch(err =>{ }).catch(err =>{
}) })
}, },
/** 获取裁决书模板 */
getTemplateFn(data) {
getTemplate(data).then((res) => {
//this.templateList = res.rows;
res.rows.forEach(item=>{
this.templateList.push({value:item.id,text:item.temName})
})
});
},
// 被申请人获取性别喝出生年月
handleBlur(){
let idCards = {
idCard: this.formData.affiliate.respondentIdentityNum,
};
getInfoByIdCard(idCards).then(res=>{
this.formData.affiliate.respondentSex = Number(res.respondentSex);
this.formData.affiliate.respondentBirth = res.respondentBirth;
})
},
// 新增案件
insertFn(data) {
caseApplicationInsert(data).then((res) => {
uni.showToast({
title: '成功',
icon: 'none',
duration: 1000
})
uni.navigateBack({
delta: 1
})
});
},
//修改案件
modifyData(data) {
updateComfire(data).then((res) => {
uni.showToast({
title: '成功',
icon: 'none',
duration: 1000
})
uni.navigateBack({
delta: 1
})
});
},
// 文件上传
select(e) {
this.tempFilePaths = e.tempFilePaths;
// loading
uni.showLoading({
title: '上传中'
});
uni.uploadFile({
url: config.baseUrlTJ + "/common/upload",
filePath: this.tempFilePaths[0],
header: {
Authorization: getToken() || '',
},
formData: {
annexType: 2,
id: this.formData.id
},
name: 'file',
success: (res) => {
let result = JSON.parse(res.data)
this.formData.caseAttachList.push({
annexId: result.annexId,
});
console.log(result.annexId)
uni.showToast({
title: '上传成功',
icon: 'none',
duration: 1000
})
uni.hideLoading();
},
fail: (err) => {
uni.showToast({
title: '上传失败',
icon: 'none',
duration: 1000
})
uni.hideLoading()
}
})
},
cencalBut(){ cencalBut(){
uni.navigateBack({ uni.navigateBack({
delta: 1 delta: 1
}) })
} }
},
onLoad(data) {
this.getTemplateFn()
} }
} }
+71 -67
View File
@@ -1,67 +1,71 @@
## 1.0.4(2023-03-29) ## 1.0.6(2024-01-06)
- 修复 手动上传删除一个文件后不能再上传的bug - 新增 微信小程序不再调用chooseImage,而是调用chooseMedia
## 1.0.3(2022-12-19) ## 1.0.5(2024-01-03)
- 新增 sourceType 属性, 可以自定义图片和视频选择的来源 - 新增 上传文件至云存储携带本地文件名称
## 1.0.2(2022-07-04) ## 1.0.4(2023-03-29)
- 修复 在uni-forms下样式不生效的bug - 修复 手动上传删除一个文件后不能再上传的bug
## 1.0.1(2021-11-23) ## 1.0.3(2022-12-19)
- 修复 参数为对象的情况下,url在某些情况显示错误的bug - 新增 sourceType 属性, 可以自定义图片和视频选择的来源
## 1.0.0(2021-11-19) ## 1.0.2(2022-07-04)
- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) - 修复 在uni-forms下样式不生效的bug
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-file-picker](https://uniapp.dcloud.io/component/uniui/uni-file-picker) ## 1.0.1(2021-11-23)
## 0.2.16(2021-11-08) - 修复 参数为对象的情况下,url在某些情况显示错误的bug
- 修复 传入空对象 ,显示错误的Bug ## 1.0.0(2021-11-19)
## 0.2.15(2021-08-30) - 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
- 修复 return-type="object" 时且存在v-model时,无法删除文件的Bug - 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-file-picker](https://uniapp.dcloud.io/component/uniui/uni-file-picker)
## 0.2.14(2021-08-23) ## 0.2.16(2021-11-08)
- 新增 参数中返回 fileID 字段 - 修复 传入空对象 ,显示错误的Bug
## 0.2.13(2021-08-23) ## 0.2.15(2021-08-30)
- 修复 腾讯云传入fileID 不能回显的bug - 修复 return-type="object" 时且存在v-model时,无法删除文件的Bug
- 修复 选择图片后,不能放大的问题 ## 0.2.14(2021-08-23)
## 0.2.12(2021-08-17) - 新增 参数中返回 fileID 字段
- 修复 由于 0.2.11 版本引起的不能回显图片的Bug ## 0.2.13(2021-08-23)
## 0.2.11(2021-08-16) - 修复 腾讯云传入fileID 不能回显的bug
- 新增 clearFiles(index) 方法,可以手动删除指定文件 - 修复 选择图片后,不能放大的问题
- 修复 v-model 值设为 null 报错的Bug ## 0.2.12(2021-08-17)
## 0.2.10(2021-08-13) - 修复 由于 0.2.11 版本引起的不能回显图片的Bug
- 修复 return-type="object" 时,无法删除文件的Bug ## 0.2.11(2021-08-16)
## 0.2.9(2021-08-03) - 新增 clearFiles(index) 方法,可以手动删除指定文件
- 修复 auto-upload 属性失效的Bug - 修复 v-model 值设为 null 报错的Bug
## 0.2.8(2021-07-31) ## 0.2.10(2021-08-13)
- 修复 fileExtname属性不指定值报错的Bug - 修复 return-type="object" 时,无法删除文件的Bug
## 0.2.7(2021-07-31) ## 0.2.9(2021-08-03)
- 修复 在某种场景下图片不回显的Bug - 修复 auto-upload 属性失效的Bug
## 0.2.6(2021-07-30) ## 0.2.8(2021-07-31)
- 修复 return-type为object下,返回值不正确的Bug - 修复 fileExtname属性不指定值报错的Bug
## 0.2.5(2021-07-30) ## 0.2.7(2021-07-31)
- 修复(重要) H5 平台下如果和uni-forms组件一同使用导致页面卡死的问题 - 修复 在某种场景下图片不回显的Bug
## 0.2.3(2021-07-28) ## 0.2.6(2021-07-30)
- 优化 调整示例代码 - 修复 return-type为object下,返回值不正确的Bug
## 0.2.2(2021-07-27) ## 0.2.5(2021-07-30)
- 修复 vue3 下赋值错误的Bug - 修复(重要) H5 平台下如果和uni-forms组件一同使用导致页面卡死的问题
- 优化 h5平台下上传文件导致页面卡死的问题 ## 0.2.3(2021-07-28)
## 0.2.0(2021-07-13) - 优化 调整示例代码
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) ## 0.2.2(2021-07-27)
## 0.1.1(2021-07-02) - 修复 vue3 下赋值错误的Bug
- 修复 sourceType 缺少默认值导致 ios 无法选择文件 - 优化 h5平台下上传文件导致页面卡死的问题
## 0.1.0(2021-06-30) ## 0.2.0(2021-07-13)
- 优化 解耦与uniCloud的强绑定关系 ,如不绑定服务空间,默认autoUpload为false且不可更改 - 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
## 0.0.11(2021-06-30) ## 0.1.1(2021-07-02)
- 修复 由 0.0.10 版本引发的 returnType 属性失效的问题 - 修复 sourceType 缺少默认值导致 ios 无法选择文件
## 0.0.10(2021-06-29) ## 0.1.0(2021-06-30)
- 优化 文件上传后进度条消失时机 - 优化 解耦与uniCloud的强绑定关系 ,如不绑定服务空间,默认autoUpload为false且不可更改
## 0.0.9(2021-06-29) ## 0.0.11(2021-06-30)
- 修复 在uni-forms 中,删除文件 ,获取的值不对的Bug - 修复 由 0.0.10 版本引发的 returnType 属性失效的问题
## 0.0.8(2021-06-15) ## 0.0.10(2021-06-29)
- 修复 删除文件时无法触发 v-model 的Bug - 优化 文件上传后进度条消失时机
## 0.0.7(2021-05-12) ## 0.0.9(2021-06-29)
- 新增 组件示例地址 - 修复 在uni-forms 中,删除文件 ,获取的值不对的Bug
## 0.0.6(2021-04-09) ## 0.0.8(2021-06-15)
- 修复 选择的文件非 file-extname 字段指定的扩展名报错的Bug - 修复 删除文件时无法触发 v-model 的Bug
## 0.0.5(2021-04-09) ## 0.0.7(2021-05-12)
- 优化 更新组件示例 - 新增 组件示例地址
## 0.0.4(2021-04-09) ## 0.0.6(2021-04-09)
- 优化 file-extname 字段支持字符串写法,多个扩展名需要用逗号分隔 - 修复 选择的文件非 file-extname 字段指定的扩展名报错的Bug
## 0.0.3(2021-02-05) ## 0.0.5(2021-04-09)
- 调整为uni_modules目录规范 - 优化 更新组件示例
- 修复 微信小程序不指定 fileExtname 属性选择失败的Bug ## 0.0.4(2021-04-09)
- 优化 file-extname 字段支持字符串写法,多个扩展名需要用逗号分隔
## 0.0.3(2021-02-05)
- 调整为uni_modules目录规范
- 修复 微信小程序不指定 fileExtname 属性选择失败的Bug
@@ -1,224 +1,247 @@
'use strict'; 'use strict';
const ERR_MSG_OK = 'chooseAndUploadFile:ok'; const ERR_MSG_OK = 'chooseAndUploadFile:ok';
const ERR_MSG_FAIL = 'chooseAndUploadFile:fail'; const ERR_MSG_FAIL = 'chooseAndUploadFile:fail';
function chooseImage(opts) { function chooseImage(opts) {
const { const {
count, count,
sizeType = ['original', 'compressed'], sizeType = ['original', 'compressed'],
sourceType, sourceType,
extension extension
} = opts } = opts
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
uni.chooseImage({ // #ifdef MP-WEIXIN
count, uni.chooseMedia({
sizeType, count,
sourceType, sizeType,
extension, sourceType,
success(res) { mediaType: ['image'],
resolve(normalizeChooseAndUploadFileRes(res, 'image')); extension,
}, success(res) {
fail(res) { res.tempFiles.forEach(item => {
reject({ item.path = item.tempFilePath;
errMsg: res.errMsg.replace('chooseImage:fail', ERR_MSG_FAIL), })
}); resolve(normalizeChooseAndUploadFileRes(res, 'image'));
}, },
}); fail(res) {
}); reject({
} errMsg: res.errMsg.replace('chooseImage:fail', ERR_MSG_FAIL),
});
function chooseVideo(opts) { },
const { })
camera, // #endif
compressed, // #ifndef MP-WEIXIN
maxDuration, uni.chooseImage({
sourceType, count,
extension sizeType,
} = opts; sourceType,
return new Promise((resolve, reject) => { extension,
uni.chooseVideo({ success(res) {
camera, resolve(normalizeChooseAndUploadFileRes(res, 'image'));
compressed, },
maxDuration, fail(res) {
sourceType, reject({
extension, errMsg: res.errMsg.replace('chooseImage:fail', ERR_MSG_FAIL),
success(res) { });
const { },
tempFilePath, });
duration, // #endif
size,
height, });
width }
} = res;
resolve(normalizeChooseAndUploadFileRes({ function chooseVideo(opts) {
errMsg: 'chooseVideo:ok', const {
tempFilePaths: [tempFilePath], camera,
tempFiles: [ compressed,
{ maxDuration,
name: (res.tempFile && res.tempFile.name) || '', sourceType,
path: tempFilePath, extension
size, } = opts;
type: (res.tempFile && res.tempFile.type) || '', return new Promise((resolve, reject) => {
width, uni.chooseVideo({
height, camera,
duration, compressed,
fileType: 'video', maxDuration,
cloudPath: '', sourceType,
}, ], extension,
}, 'video')); success(res) {
}, const {
fail(res) { tempFilePath,
reject({ duration,
errMsg: res.errMsg.replace('chooseVideo:fail', ERR_MSG_FAIL), size,
}); height,
}, width
}); } = res;
}); resolve(normalizeChooseAndUploadFileRes({
} errMsg: 'chooseVideo:ok',
tempFilePaths: [tempFilePath],
function chooseAll(opts) { tempFiles: [
const { {
count, name: (res.tempFile && res.tempFile.name) || '',
extension path: tempFilePath,
} = opts; size,
return new Promise((resolve, reject) => { type: (res.tempFile && res.tempFile.type) || '',
let chooseFile = uni.chooseFile; width,
if (typeof wx !== 'undefined' && height,
typeof wx.chooseMessageFile === 'function') { duration,
chooseFile = wx.chooseMessageFile; fileType: 'video',
} cloudPath: '',
if (typeof chooseFile !== 'function') { }, ],
return reject({ }, 'video'));
errMsg: ERR_MSG_FAIL + ' 请指定 type 类型,该平台仅支持选择 image 或 video。', },
}); fail(res) {
} reject({
chooseFile({ errMsg: res.errMsg.replace('chooseVideo:fail', ERR_MSG_FAIL),
type: 'all', });
count, },
extension, });
success(res) { });
resolve(normalizeChooseAndUploadFileRes(res)); }
},
fail(res) { function chooseAll(opts) {
reject({ const {
errMsg: res.errMsg.replace('chooseFile:fail', ERR_MSG_FAIL), count,
}); extension
}, } = opts;
}); return new Promise((resolve, reject) => {
}); let chooseFile = uni.chooseFile;
} if (typeof wx !== 'undefined' &&
typeof wx.chooseMessageFile === 'function') {
function normalizeChooseAndUploadFileRes(res, fileType) { chooseFile = wx.chooseMessageFile;
res.tempFiles.forEach((item, index) => { }
if (!item.name) { if (typeof chooseFile !== 'function') {
item.name = item.path.substring(item.path.lastIndexOf('/') + 1); return reject({
} errMsg: ERR_MSG_FAIL + ' 请指定 type 类型,该平台仅支持选择 image 或 video。',
if (fileType) { });
item.fileType = fileType; }
} chooseFile({
item.cloudPath = type: 'all',
Date.now() + '_' + index + item.name.substring(item.name.lastIndexOf('.')); count,
}); extension,
if (!res.tempFilePaths) { success(res) {
res.tempFilePaths = res.tempFiles.map((file) => file.path); resolve(normalizeChooseAndUploadFileRes(res));
} },
return res; fail(res) {
} reject({
errMsg: res.errMsg.replace('chooseFile:fail', ERR_MSG_FAIL),
function uploadCloudFiles(files, max = 5, onUploadProgress) { });
files = JSON.parse(JSON.stringify(files)) },
const len = files.length });
let count = 0 });
let self = this }
return new Promise(resolve => {
while (count < max) { function normalizeChooseAndUploadFileRes(res, fileType) {
next() res.tempFiles.forEach((item, index) => {
} if (!item.name) {
item.name = item.path.substring(item.path.lastIndexOf('/') + 1);
function next() { }
let cur = count++ if (fileType) {
if (cur >= len) { item.fileType = fileType;
!files.find(item => !item.url && !item.errMsg) && resolve(files) }
return item.cloudPath =
} Date.now() + '_' + index + item.name.substring(item.name.lastIndexOf('.'));
const fileItem = files[cur] });
const index = self.files.findIndex(v => v.uuid === fileItem.uuid) if (!res.tempFilePaths) {
fileItem.url = '' res.tempFilePaths = res.tempFiles.map((file) => file.path);
delete fileItem.errMsg }
return res;
uniCloud }
.uploadFile({
filePath: fileItem.path, function uploadCloudFiles(files, max = 5, onUploadProgress) {
cloudPath: fileItem.cloudPath, files = JSON.parse(JSON.stringify(files))
fileType: fileItem.fileType, const len = files.length
onUploadProgress: res => { let count = 0
res.index = index let self = this
onUploadProgress && onUploadProgress(res) return new Promise(resolve => {
} while (count < max) {
}) next()
.then(res => { }
fileItem.url = res.fileID
fileItem.index = index function next() {
if (cur < len) { let cur = count++
next() if (cur >= len) {
} !files.find(item => !item.url && !item.errMsg) && resolve(files)
}) return
.catch(res => { }
fileItem.errMsg = res.errMsg || res.message const fileItem = files[cur]
fileItem.index = index const index = self.files.findIndex(v => v.uuid === fileItem.uuid)
if (cur < len) { fileItem.url = ''
next() delete fileItem.errMsg
}
}) uniCloud
} .uploadFile({
}) filePath: fileItem.path,
} cloudPath: fileItem.cloudPath,
fileType: fileItem.fileType,
onUploadProgress: res => {
res.index = index
onUploadProgress && onUploadProgress(res)
}
function uploadFiles(choosePromise, { })
onChooseFile, .then(res => {
onUploadProgress fileItem.url = res.fileID
}) { fileItem.index = index
return choosePromise if (cur < len) {
.then((res) => { next()
if (onChooseFile) { }
const customChooseRes = onChooseFile(res); })
if (typeof customChooseRes !== 'undefined') { .catch(res => {
return Promise.resolve(customChooseRes).then((chooseRes) => typeof chooseRes === 'undefined' ? fileItem.errMsg = res.errMsg || res.message
res : chooseRes); fileItem.index = index
} if (cur < len) {
} next()
return res; }
}) })
.then((res) => { }
if (res === false) { })
return { }
errMsg: ERR_MSG_OK,
tempFilePaths: [],
tempFiles: [],
};
}
return res function uploadFiles(choosePromise, {
}) onChooseFile,
} onUploadProgress
}) {
function chooseAndUploadFile(opts = { return choosePromise
type: 'all' .then((res) => {
}) { if (onChooseFile) {
if (opts.type === 'image') { const customChooseRes = onChooseFile(res);
return uploadFiles(chooseImage(opts), opts); if (typeof customChooseRes !== 'undefined') {
} return Promise.resolve(customChooseRes).then((chooseRes) => typeof chooseRes === 'undefined' ?
else if (opts.type === 'video') { res : chooseRes);
return uploadFiles(chooseVideo(opts), opts); }
} }
return uploadFiles(chooseAll(opts), opts); return res;
} })
.then((res) => {
export { if (res === false) {
chooseAndUploadFile, return {
uploadCloudFiles errMsg: ERR_MSG_OK,
}; tempFilePaths: [],
tempFiles: [],
};
}
return res
})
}
function chooseAndUploadFile(opts = {
type: 'all'
}) {
if (opts.type === 'image') {
return uploadFiles(chooseImage(opts), opts);
}
else if (opts.type === 'video') {
return uploadFiles(chooseVideo(opts), opts);
}
return uploadFiles(chooseAll(opts), opts);
}
export {
chooseAndUploadFile,
uploadCloudFiles
};
File diff suppressed because it is too large Load Diff
@@ -1,325 +1,325 @@
<template> <template>
<view class="uni-file-picker__files"> <view class="uni-file-picker__files">
<view v-if="!readonly" class="files-button" @click="choose"> <view v-if="!readonly" class="files-button" @click="choose">
<slot></slot> <slot></slot>
</view> </view>
<!-- :class="{'is-text-box':showType === 'list'}" --> <!-- :class="{'is-text-box':showType === 'list'}" -->
<view v-if="list.length > 0" class="uni-file-picker__lists is-text-box" :style="borderStyle"> <view v-if="list.length > 0" class="uni-file-picker__lists is-text-box" :style="borderStyle">
<!-- ,'is-list-card':showType === 'list-card' --> <!-- ,'is-list-card':showType === 'list-card' -->
<view class="uni-file-picker__lists-box" v-for="(item ,index) in list" :key="index" :class="{ <view class="uni-file-picker__lists-box" v-for="(item ,index) in list" :key="index" :class="{
'files-border':index !== 0 && styles.dividline}" 'files-border':index !== 0 && styles.dividline}"
:style="index !== 0 && styles.dividline &&borderLineStyle"> :style="index !== 0 && styles.dividline &&borderLineStyle">
<view class="uni-file-picker__item"> <view class="uni-file-picker__item">
<!-- :class="{'is-text-image':showType === 'list'}" --> <!-- :class="{'is-text-image':showType === 'list'}" -->
<!-- <view class="files__image is-text-image"> <!-- <view class="files__image is-text-image">
<image class="header-image" :src="item.logo" mode="aspectFit"></image> <image class="header-image" :src="item.logo" mode="aspectFit"></image>
</view> --> </view> -->
<view class="files__name">{{item.name}}</view> <view class="files__name">{{item.name}}</view>
<view v-if="delIcon&&!readonly" class="icon-del-box icon-files" @click="delFile(index)"> <view v-if="delIcon&&!readonly" class="icon-del-box icon-files" @click="delFile(index)">
<view class="icon-del icon-files"></view> <view class="icon-del icon-files"></view>
<view class="icon-del rotate"></view> <view class="icon-del rotate"></view>
</view> </view>
</view> </view>
<view v-if="(item.progress && item.progress !== 100) ||item.progress===0 " class="file-picker__progress"> <view v-if="(item.progress && item.progress !== 100) ||item.progress===0 " class="file-picker__progress">
<progress class="file-picker__progress-item" :percent="item.progress === -1?0:item.progress" stroke-width="4" <progress class="file-picker__progress-item" :percent="item.progress === -1?0:item.progress" stroke-width="4"
:backgroundColor="item.errMsg?'#ff5a5f':'#EBEBEB'" /> :backgroundColor="item.errMsg?'#ff5a5f':'#EBEBEB'" />
</view> </view>
<view v-if="item.status === 'error'" class="file-picker__mask" @click.stop="uploadFiles(item,index)"> <view v-if="item.status === 'error'" class="file-picker__mask" @click.stop="uploadFiles(item,index)">
点击重试 点击重试
</view> </view>
</view> </view>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
export default { export default {
name: "uploadFile", name: "uploadFile",
emits:['uploadFiles','choose','delFile'], emits:['uploadFiles','choose','delFile'],
props: { props: {
filesList: { filesList: {
type: Array, type: Array,
default () { default () {
return [] return []
} }
}, },
delIcon: { delIcon: {
type: Boolean, type: Boolean,
default: true default: true
}, },
limit: { limit: {
type: [Number, String], type: [Number, String],
default: 9 default: 9
}, },
showType: { showType: {
type: String, type: String,
default: '' default: ''
}, },
listStyles: { listStyles: {
type: Object, type: Object,
default () { default () {
return { return {
// 是否显示边框 // 是否显示边框
border: true, border: true,
// 是否显示分隔线 // 是否显示分隔线
dividline: true, dividline: true,
// 线条样式 // 线条样式
borderStyle: {} borderStyle: {}
} }
} }
}, },
readonly:{ readonly:{
type:Boolean, type:Boolean,
default:false default:false
} }
}, },
computed: { computed: {
list() { list() {
let files = [] let files = []
this.filesList.forEach(v => { this.filesList.forEach(v => {
files.push(v) files.push(v)
}) })
return files return files
}, },
styles() { styles() {
let styles = { let styles = {
border: true, border: true,
dividline: true, dividline: true,
'border-style': {} 'border-style': {}
} }
return Object.assign(styles, this.listStyles) return Object.assign(styles, this.listStyles)
}, },
borderStyle() { borderStyle() {
let { let {
borderStyle, borderStyle,
border border
} = this.styles } = this.styles
let obj = {} let obj = {}
if (!border) { if (!border) {
obj.border = 'none' obj.border = 'none'
} else { } else {
let width = (borderStyle && borderStyle.width) || 1 let width = (borderStyle && borderStyle.width) || 1
width = this.value2px(width) width = this.value2px(width)
let radius = (borderStyle && borderStyle.radius) || 5 let radius = (borderStyle && borderStyle.radius) || 5
radius = this.value2px(radius) radius = this.value2px(radius)
obj = { obj = {
'border-width': width, 'border-width': width,
'border-style': (borderStyle && borderStyle.style) || 'solid', 'border-style': (borderStyle && borderStyle.style) || 'solid',
'border-color': (borderStyle && borderStyle.color) || '#eee', 'border-color': (borderStyle && borderStyle.color) || '#eee',
'border-radius': radius 'border-radius': radius
} }
} }
let classles = '' let classles = ''
for (let i in obj) { for (let i in obj) {
classles += `${i}:${obj[i]};` classles += `${i}:${obj[i]};`
} }
return classles return classles
}, },
borderLineStyle() { borderLineStyle() {
let obj = {} let obj = {}
let { let {
borderStyle borderStyle
} = this.styles } = this.styles
if (borderStyle && borderStyle.color) { if (borderStyle && borderStyle.color) {
obj['border-color'] = borderStyle.color obj['border-color'] = borderStyle.color
} }
if (borderStyle && borderStyle.width) { if (borderStyle && borderStyle.width) {
let width = borderStyle && borderStyle.width || 1 let width = borderStyle && borderStyle.width || 1
let style = borderStyle && borderStyle.style || 0 let style = borderStyle && borderStyle.style || 0
if (typeof width === 'number') { if (typeof width === 'number') {
width += 'px' width += 'px'
} else { } else {
width = width.indexOf('px') ? width : width + 'px' width = width.indexOf('px') ? width : width + 'px'
} }
obj['border-width'] = width obj['border-width'] = width
if (typeof style === 'number') { if (typeof style === 'number') {
style += 'px' style += 'px'
} else { } else {
style = style.indexOf('px') ? style : style + 'px' style = style.indexOf('px') ? style : style + 'px'
} }
obj['border-top-style'] = style obj['border-top-style'] = style
} }
let classles = '' let classles = ''
for (let i in obj) { for (let i in obj) {
classles += `${i}:${obj[i]};` classles += `${i}:${obj[i]};`
} }
return classles return classles
} }
}, },
methods: { methods: {
uploadFiles(item, index) { uploadFiles(item, index) {
this.$emit("uploadFiles", { this.$emit("uploadFiles", {
item, item,
index index
}) })
}, },
choose() { choose() {
this.$emit("choose") this.$emit("choose")
}, },
delFile(index) { delFile(index) {
this.$emit('delFile', index) this.$emit('delFile', index)
}, },
value2px(value) { value2px(value) {
if (typeof value === 'number') { if (typeof value === 'number') {
value += 'px' value += 'px'
} else { } else {
value = value.indexOf('px') !== -1 ? value : value + 'px' value = value.indexOf('px') !== -1 ? value : value + 'px'
} }
return value return value
} }
} }
} }
</script> </script>
<style lang="scss"> <style lang="scss">
.uni-file-picker__files { .uni-file-picker__files {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: flex; display: flex;
/* #endif */ /* #endif */
flex-direction: column; flex-direction: column;
justify-content: flex-start; justify-content: flex-start;
} }
.files-button { .files-button {
// border: 1px red solid; // border: 1px red solid;
} }
.uni-file-picker__lists { .uni-file-picker__lists {
position: relative; position: relative;
margin-top: 5px; margin-top: 5px;
overflow: hidden; overflow: hidden;
} }
.file-picker__mask { .file-picker__mask {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: flex; display: flex;
/* #endif */ /* #endif */
justify-content: center; justify-content: center;
align-items: center; align-items: center;
position: absolute; position: absolute;
right: 0; right: 0;
top: 0; top: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
color: #fff; color: #fff;
font-size: 14px; font-size: 14px;
background-color: rgba(0, 0, 0, 0.4); background-color: rgba(0, 0, 0, 0.4);
} }
.uni-file-picker__lists-box { .uni-file-picker__lists-box {
position: relative; position: relative;
} }
.uni-file-picker__item { .uni-file-picker__item {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: flex; display: flex;
/* #endif */ /* #endif */
align-items: center; align-items: center;
padding: 8px 10px; padding: 8px 10px;
padding-right: 5px; padding-right: 5px;
padding-left: 10px; padding-left: 10px;
} }
.files-border { .files-border {
border-top: 1px #eee solid; border-top: 1px #eee solid;
} }
.files__name { .files__name {
flex: 1; flex: 1;
font-size: 14px; font-size: 14px;
color: #666; color: #666;
margin-right: 25px; margin-right: 25px;
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
word-break: break-all; word-break: break-all;
word-wrap: break-word; word-wrap: break-word;
/* #endif */ /* #endif */
} }
.icon-files { .icon-files {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
position: static; position: static;
background-color: initial; background-color: initial;
/* #endif */ /* #endif */
} }
// .icon-files .icon-del { // .icon-files .icon-del {
// background-color: #333; // background-color: #333;
// width: 12px; // width: 12px;
// height: 1px; // height: 1px;
// } // }
.is-list-card { .is-list-card {
border: 1px #eee solid; border: 1px #eee solid;
margin-bottom: 5px; margin-bottom: 5px;
border-radius: 5px; border-radius: 5px;
box-shadow: 0 0 2px 0px rgba(0, 0, 0, 0.1); box-shadow: 0 0 2px 0px rgba(0, 0, 0, 0.1);
padding: 5px; padding: 5px;
} }
.files__image { .files__image {
width: 40px; width: 40px;
height: 40px; height: 40px;
margin-right: 10px; margin-right: 10px;
} }
.header-image { .header-image {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
.is-text-box { .is-text-box {
border: 1px #eee solid; border: 1px #eee solid;
border-radius: 5px; border-radius: 5px;
} }
.is-text-image { .is-text-image {
width: 25px; width: 25px;
height: 25px; height: 25px;
margin-left: 5px; margin-left: 5px;
} }
.rotate { .rotate {
position: absolute; position: absolute;
transform: rotate(90deg); transform: rotate(90deg);
} }
.icon-del-box { .icon-del-box {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: flex; display: flex;
margin: auto 0; margin: auto 0;
/* #endif */ /* #endif */
align-items: center; align-items: center;
justify-content: center; justify-content: center;
position: absolute; position: absolute;
top: 0px; top: 0px;
bottom: 0; bottom: 0;
right: 5px; right: 5px;
height: 26px; height: 26px;
width: 26px; width: 26px;
// border-radius: 50%; // border-radius: 50%;
// background-color: rgba(0, 0, 0, 0.5); // background-color: rgba(0, 0, 0, 0.5);
z-index: 2; z-index: 2;
transform: rotate(-45deg); transform: rotate(-45deg);
} }
.icon-del { .icon-del {
width: 15px; width: 15px;
height: 1px; height: 1px;
background-color: #333; background-color: #333;
// border-radius: 1px; // border-radius: 1px;
} }
/* #ifdef H5 */ /* #ifdef H5 */
@media all and (min-width: 768px) { @media all and (min-width: 768px) {
.uni-file-picker__files { .uni-file-picker__files {
max-width: 375px; max-width: 375px;
} }
} }
/* #endif */ /* #endif */
</style> </style>
@@ -1,292 +1,292 @@
<template> <template>
<view class="uni-file-picker__container"> <view class="uni-file-picker__container">
<view class="file-picker__box" v-for="(item,index) in filesList" :key="index" :style="boxStyle"> <view class="file-picker__box" v-for="(item,index) in filesList" :key="index" :style="boxStyle">
<view class="file-picker__box-content" :style="borderStyle"> <view class="file-picker__box-content" :style="borderStyle">
<image class="file-image" :src="item.url" mode="aspectFill" @click.stop="prviewImage(item,index)"></image> <image class="file-image" :src="item.url" mode="aspectFill" @click.stop="prviewImage(item,index)"></image>
<view v-if="delIcon && !readonly" class="icon-del-box" @click.stop="delFile(index)"> <view v-if="delIcon && !readonly" class="icon-del-box" @click.stop="delFile(index)">
<view class="icon-del"></view> <view class="icon-del"></view>
<view class="icon-del rotate"></view> <view class="icon-del rotate"></view>
</view> </view>
<view v-if="(item.progress && item.progress !== 100) ||item.progress===0 " class="file-picker__progress"> <view v-if="(item.progress && item.progress !== 100) ||item.progress===0 " class="file-picker__progress">
<progress class="file-picker__progress-item" :percent="item.progress === -1?0:item.progress" stroke-width="4" <progress class="file-picker__progress-item" :percent="item.progress === -1?0:item.progress" stroke-width="4"
:backgroundColor="item.errMsg?'#ff5a5f':'#EBEBEB'" /> :backgroundColor="item.errMsg?'#ff5a5f':'#EBEBEB'" />
</view> </view>
<view v-if="item.errMsg" class="file-picker__mask" @click.stop="uploadFiles(item,index)"> <view v-if="item.errMsg" class="file-picker__mask" @click.stop="uploadFiles(item,index)">
点击重试 点击重试
</view> </view>
</view> </view>
</view> </view>
<view v-if="filesList.length < limit && !readonly" class="file-picker__box" :style="boxStyle"> <view v-if="filesList.length < limit && !readonly" class="file-picker__box" :style="boxStyle">
<view class="file-picker__box-content is-add" :style="borderStyle" @click="choose"> <view class="file-picker__box-content is-add" :style="borderStyle" @click="choose">
<slot> <slot>
<view class="icon-add"></view> <view class="icon-add"></view>
<view class="icon-add rotate"></view> <view class="icon-add rotate"></view>
</slot> </slot>
</view> </view>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
export default { export default {
name: "uploadImage", name: "uploadImage",
emits:['uploadFiles','choose','delFile'], emits:['uploadFiles','choose','delFile'],
props: { props: {
filesList: { filesList: {
type: Array, type: Array,
default () { default () {
return [] return []
} }
}, },
disabled:{ disabled:{
type: Boolean, type: Boolean,
default: false default: false
}, },
disablePreview: { disablePreview: {
type: Boolean, type: Boolean,
default: false default: false
}, },
limit: { limit: {
type: [Number, String], type: [Number, String],
default: 9 default: 9
}, },
imageStyles: { imageStyles: {
type: Object, type: Object,
default () { default () {
return { return {
width: 'auto', width: 'auto',
height: 'auto', height: 'auto',
border: {} border: {}
} }
} }
}, },
delIcon: { delIcon: {
type: Boolean, type: Boolean,
default: true default: true
}, },
readonly:{ readonly:{
type:Boolean, type:Boolean,
default:false default:false
} }
}, },
computed: { computed: {
styles() { styles() {
let styles = { let styles = {
width: 'auto', width: 'auto',
height: 'auto', height: 'auto',
border: {} border: {}
} }
return Object.assign(styles, this.imageStyles) return Object.assign(styles, this.imageStyles)
}, },
boxStyle() { boxStyle() {
const { const {
width = 'auto', width = 'auto',
height = 'auto' height = 'auto'
} = this.styles } = this.styles
let obj = {} let obj = {}
if (height === 'auto') { if (height === 'auto') {
if (width !== 'auto') { if (width !== 'auto') {
obj.height = this.value2px(width) obj.height = this.value2px(width)
obj['padding-top'] = 0 obj['padding-top'] = 0
} else { } else {
obj.height = 0 obj.height = 0
} }
} else { } else {
obj.height = this.value2px(height) obj.height = this.value2px(height)
obj['padding-top'] = 0 obj['padding-top'] = 0
} }
if (width === 'auto') { if (width === 'auto') {
if (height !== 'auto') { if (height !== 'auto') {
obj.width = this.value2px(height) obj.width = this.value2px(height)
} else { } else {
obj.width = '33.3%' obj.width = '33.3%'
} }
} else { } else {
obj.width = this.value2px(width) obj.width = this.value2px(width)
} }
let classles = '' let classles = ''
for(let i in obj){ for(let i in obj){
classles+= `${i}:${obj[i]};` classles+= `${i}:${obj[i]};`
} }
return classles return classles
}, },
borderStyle() { borderStyle() {
let { let {
border border
} = this.styles } = this.styles
let obj = {} let obj = {}
const widthDefaultValue = 1 const widthDefaultValue = 1
const radiusDefaultValue = 3 const radiusDefaultValue = 3
if (typeof border === 'boolean') { if (typeof border === 'boolean') {
obj.border = border ? '1px #eee solid' : 'none' obj.border = border ? '1px #eee solid' : 'none'
} else { } else {
let width = (border && border.width) || widthDefaultValue let width = (border && border.width) || widthDefaultValue
width = this.value2px(width) width = this.value2px(width)
let radius = (border && border.radius) || radiusDefaultValue let radius = (border && border.radius) || radiusDefaultValue
radius = this.value2px(radius) radius = this.value2px(radius)
obj = { obj = {
'border-width': width, 'border-width': width,
'border-style': (border && border.style) || 'solid', 'border-style': (border && border.style) || 'solid',
'border-color': (border && border.color) || '#eee', 'border-color': (border && border.color) || '#eee',
'border-radius': radius 'border-radius': radius
} }
} }
let classles = '' let classles = ''
for(let i in obj){ for(let i in obj){
classles+= `${i}:${obj[i]};` classles+= `${i}:${obj[i]};`
} }
return classles return classles
} }
}, },
methods: { methods: {
uploadFiles(item, index) { uploadFiles(item, index) {
this.$emit("uploadFiles", item) this.$emit("uploadFiles", item)
}, },
choose() { choose() {
this.$emit("choose") this.$emit("choose")
}, },
delFile(index) { delFile(index) {
this.$emit('delFile', index) this.$emit('delFile', index)
}, },
prviewImage(img, index) { prviewImage(img, index) {
let urls = [] let urls = []
if(Number(this.limit) === 1&&this.disablePreview&&!this.disabled){ if(Number(this.limit) === 1&&this.disablePreview&&!this.disabled){
this.$emit("choose") this.$emit("choose")
} }
if(this.disablePreview) return if(this.disablePreview) return
this.filesList.forEach(i => { this.filesList.forEach(i => {
urls.push(i.url) urls.push(i.url)
}) })
uni.previewImage({ uni.previewImage({
urls: urls, urls: urls,
current: index current: index
}); });
}, },
value2px(value) { value2px(value) {
if (typeof value === 'number') { if (typeof value === 'number') {
value += 'px' value += 'px'
} else { } else {
if (value.indexOf('%') === -1) { if (value.indexOf('%') === -1) {
value = value.indexOf('px') !== -1 ? value : value + 'px' value = value.indexOf('px') !== -1 ? value : value + 'px'
} }
} }
return value return value
} }
} }
} }
</script> </script>
<style lang="scss"> <style lang="scss">
.uni-file-picker__container { .uni-file-picker__container {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: flex; display: flex;
box-sizing: border-box; box-sizing: border-box;
/* #endif */ /* #endif */
flex-wrap: wrap; flex-wrap: wrap;
margin: -5px; margin: -5px;
} }
.file-picker__box { .file-picker__box {
position: relative; position: relative;
// flex: 0 0 33.3%; // flex: 0 0 33.3%;
width: 33.3%; width: 33.3%;
height: 0; height: 0;
padding-top: 33.33%; padding-top: 33.33%;
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
box-sizing: border-box; box-sizing: border-box;
/* #endif */ /* #endif */
} }
.file-picker__box-content { .file-picker__box-content {
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
margin: 5px; margin: 5px;
border: 1px #eee solid; border: 1px #eee solid;
border-radius: 5px; border-radius: 5px;
overflow: hidden; overflow: hidden;
} }
.file-picker__progress { .file-picker__progress {
position: absolute; position: absolute;
bottom: 0; bottom: 0;
left: 0; left: 0;
right: 0; right: 0;
/* border: 1px red solid; */ /* border: 1px red solid; */
z-index: 2; z-index: 2;
} }
.file-picker__progress-item { .file-picker__progress-item {
width: 100%; width: 100%;
} }
.file-picker__mask { .file-picker__mask {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: flex; display: flex;
/* #endif */ /* #endif */
justify-content: center; justify-content: center;
align-items: center; align-items: center;
position: absolute; position: absolute;
right: 0; right: 0;
top: 0; top: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
color: #fff; color: #fff;
font-size: 12px; font-size: 12px;
background-color: rgba(0, 0, 0, 0.4); background-color: rgba(0, 0, 0, 0.4);
} }
.file-image { .file-image {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
.is-add { .is-add {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: flex; display: flex;
/* #endif */ /* #endif */
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
.icon-add { .icon-add {
width: 50px; width: 50px;
height: 5px; height: 5px;
background-color: #f1f1f1; background-color: #f1f1f1;
border-radius: 2px; border-radius: 2px;
} }
.rotate { .rotate {
position: absolute; position: absolute;
transform: rotate(90deg); transform: rotate(90deg);
} }
.icon-del-box { .icon-del-box {
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
display: flex; display: flex;
/* #endif */ /* #endif */
align-items: center; align-items: center;
justify-content: center; justify-content: center;
position: absolute; position: absolute;
top: 3px; top: 3px;
right: 3px; right: 3px;
height: 26px; height: 26px;
width: 26px; width: 26px;
border-radius: 50%; border-radius: 50%;
background-color: rgba(0, 0, 0, 0.5); background-color: rgba(0, 0, 0, 0.5);
z-index: 2; z-index: 2;
transform: rotate(-45deg); transform: rotate(-45deg);
} }
.icon-del { .icon-del {
width: 15px; width: 15px;
height: 2px; height: 2px;
background-color: #fff; background-color: #fff;
border-radius: 2px; border-radius: 2px;
} }
</style> </style>
@@ -1,109 +1,109 @@
/** /**
* 获取文件名和后缀 * 获取文件名和后缀
* @param {String} name * @param {String} name
*/ */
export const get_file_ext = (name) => { export const get_file_ext = (name) => {
const last_len = name.lastIndexOf('.') const last_len = name.lastIndexOf('.')
const len = name.length const len = name.length
return { return {
name: name.substring(0, last_len), name: name.substring(0, last_len),
ext: name.substring(last_len + 1, len) ext: name.substring(last_len + 1, len)
} }
} }
/** /**
* 获取扩展名 * 获取扩展名
* @param {Array} fileExtname * @param {Array} fileExtname
*/ */
export const get_extname = (fileExtname) => { export const get_extname = (fileExtname) => {
if (!Array.isArray(fileExtname)) { if (!Array.isArray(fileExtname)) {
let extname = fileExtname.replace(/(\[|\])/g, '') let extname = fileExtname.replace(/(\[|\])/g, '')
return extname.split(',') return extname.split(',')
} else { } else {
return fileExtname return fileExtname
} }
return [] return []
} }
/** /**
* 获取文件和检测是否可选 * 获取文件和检测是否可选
*/ */
export const get_files_and_is_max = (res, _extname) => { export const get_files_and_is_max = (res, _extname) => {
let filePaths = [] let filePaths = []
let files = [] let files = []
if(!_extname || _extname.length === 0){ if(!_extname || _extname.length === 0){
return { return {
filePaths, filePaths,
files files
} }
} }
res.tempFiles.forEach(v => { res.tempFiles.forEach(v => {
let fileFullName = get_file_ext(v.name) let fileFullName = get_file_ext(v.name)
const extname = fileFullName.ext.toLowerCase() const extname = fileFullName.ext.toLowerCase()
if (_extname.indexOf(extname) !== -1) { if (_extname.indexOf(extname) !== -1) {
files.push(v) files.push(v)
filePaths.push(v.path) filePaths.push(v.path)
} }
}) })
if (files.length !== res.tempFiles.length) { if (files.length !== res.tempFiles.length) {
uni.showToast({ uni.showToast({
title: `当前选择了${res.tempFiles.length}个文件 ,${res.tempFiles.length - files.length} 个文件格式不正确`, title: `当前选择了${res.tempFiles.length}个文件 ,${res.tempFiles.length - files.length} 个文件格式不正确`,
icon: 'none', icon: 'none',
duration: 5000 duration: 5000
}) })
} }
return { return {
filePaths, filePaths,
files files
} }
} }
/** /**
* 获取图片信息 * 获取图片信息
* @param {Object} filepath * @param {Object} filepath
*/ */
export const get_file_info = (filepath) => { export const get_file_info = (filepath) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
uni.getImageInfo({ uni.getImageInfo({
src: filepath, src: filepath,
success(res) { success(res) {
resolve(res) resolve(res)
}, },
fail(err) { fail(err) {
reject(err) reject(err)
} }
}) })
}) })
} }
/** /**
* 获取封装数据 * 获取封装数据
*/ */
export const get_file_data = async (files, type = 'image') => { export const get_file_data = async (files, type = 'image') => {
// 最终需要上传数据库的数据 // 最终需要上传数据库的数据
let fileFullName = get_file_ext(files.name) let fileFullName = get_file_ext(files.name)
const extname = fileFullName.ext.toLowerCase() const extname = fileFullName.ext.toLowerCase()
let filedata = { let filedata = {
name: files.name, name: files.name,
uuid: files.uuid, uuid: files.uuid,
extname: extname || '', extname: extname || '',
cloudPath: files.cloudPath, cloudPath: files.cloudPath,
fileType: files.fileType, fileType: files.fileType,
url: files.path || files.path, url: files.path || files.path,
size: files.size, //单位是字节 size: files.size, //单位是字节
image: {}, image: {},
path: files.path, path: files.path,
video: {} video: {}
} }
if (type === 'image') { if (type === 'image') {
const imageinfo = await get_file_info(files.path) const imageinfo = await get_file_info(files.path)
delete filedata.video delete filedata.video
filedata.image.width = imageinfo.width filedata.image.width = imageinfo.width
filedata.image.height = imageinfo.height filedata.image.height = imageinfo.height
filedata.image.location = imageinfo.path filedata.image.location = imageinfo.path
} else { } else {
delete filedata.image delete filedata.image
} }
return filedata return filedata
} }
+83 -83
View File
@@ -1,83 +1,83 @@
{ {
"id": "uni-file-picker", "id": "uni-file-picker",
"displayName": "uni-file-picker 文件选择上传", "displayName": "uni-file-picker 文件选择上传",
"version": "1.0.4", "version": "1.0.6",
"description": "文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间", "description": "文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间",
"keywords": [ "keywords": [
"uni-ui", "uni-ui",
"uniui", "uniui",
"图片上传", "图片上传",
"文件上传" "文件上传"
], ],
"repository": "https://github.com/dcloudio/uni-ui", "repository": "https://github.com/dcloudio/uni-ui",
"engines": { "engines": {
"HBuilderX": "" "HBuilderX": ""
}, },
"directories": { "directories": {
"example": "../../temps/example_temps" "example": "../../temps/example_temps"
}, },
"dcloudext": { "dcloudext": {
"sale": { "sale": {
"regular": { "regular": {
"price": "0.00" "price": "0.00"
}, },
"sourcecode": { "sourcecode": {
"price": "0.00" "price": "0.00"
} }
}, },
"contact": { "contact": {
"qq": "" "qq": ""
}, },
"declaration": { "declaration": {
"ads": "无", "ads": "无",
"data": "无", "data": "无",
"permissions": "无" "permissions": "无"
}, },
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
"type": "component-vue" "type": "component-vue"
}, },
"uni_modules": { "uni_modules": {
"dependencies": ["uni-scss"], "dependencies": ["uni-scss"],
"encrypt": [], "encrypt": [],
"platforms": { "platforms": {
"cloud": { "cloud": {
"tcb": "y", "tcb": "y",
"aliyun": "y" "aliyun": "y"
}, },
"client": { "client": {
"App": { "App": {
"app-vue": "y", "app-vue": "y",
"app-nvue": "n" "app-nvue": "n"
}, },
"H5-mobile": { "H5-mobile": {
"Safari": "y", "Safari": "y",
"Android Browser": "y", "Android Browser": "y",
"微信浏览器(Android)": "y", "微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y" "QQ浏览器(Android)": "y"
}, },
"H5-pc": { "H5-pc": {
"Chrome": "y", "Chrome": "y",
"IE": "y", "IE": "y",
"Edge": "y", "Edge": "y",
"Firefox": "y", "Firefox": "y",
"Safari": "y" "Safari": "y"
}, },
"小程序": { "小程序": {
"微信": "y", "微信": "y",
"阿里": "y", "阿里": "y",
"百度": "y", "百度": "y",
"字节跳动": "y", "字节跳动": "y",
"QQ": "y" "QQ": "y"
}, },
"快应用": { "快应用": {
"华为": "u", "华为": "u",
"联盟": "u" "联盟": "u"
}, },
"Vue": { "Vue": {
"vue2": "y", "vue2": "y",
"vue3": "y" "vue3": "y"
} }
} }
} }
} }
} }
+10 -10
View File
@@ -1,11 +1,11 @@
## FilePicker 文件选择上传 ## FilePicker 文件选择上传
> **组件名:uni-file-picker** > **组件名:uni-file-picker**
> 代码块: `uFilePicker` > 代码块: `uFilePicker`
文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间 文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-file-picker) ### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-file-picker)
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 #### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839