本文已参与「新人创作礼」活动,一起开启掘金创作之路。 这是为了方便操作上传图片而自定义的组件。也方便以后自己寻找,做了这么一个记录。
一自定义上传主键
vue代码
<template>
<view>
<u-upload :fileList="fileListChy" @afterRead="afterRead" @delete="deletePic" name="Chy" multiple
:previewFullImage="true" :maxCount="1" :width="chyWidth" height="chyHeight">
<image :src="chyImageUrl" mode="widthFix" style="{width: `${chyWidth}px`;height: `${chyHeight}px`}">
</image>
</u-upload>
</view>
</template>
<script>
import config from '@/common/config.js'
import props from './props.js'
export default {
name: 'chy-upload',
data() {
return {
fileListChy:[]
}
},
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
methods: {
// 删除图片
deletePic(event) {
this[`fileList${event.name}`].splice(event.index, 1)
},
async afterRead(event) {
let that =this;
//当设置 mutiple 为 true 时, file 为数组格式,否则为对象格式
let lists = [].concat(event.file)
let fileListLen = this[`fileList${event.name}`].length
//console.log(event,"event")
lists.map((item) => {
this[`fileList${event.name}`].push({
...item,
status: 'uploading',
message: '上传中'
})
})
for (let i = 0; i < lists.length; i++) {
const result = await this.uploadFilePromise(lists[i].url)
let item = this[`fileList${event.name}`][fileListLen]
this[`fileList${event.name}`].splice(fileListLen, 1, Object.assign(item, {
status: 'success',
message: JSON.parse(result).data,
url: JSON.parse(result).data.fileUrl
}))
fileListLen++
}
console.log(that.fileListChy,"fileList7")
that.chyGetImageUrl(that.fileListChy)
},
uploadFilePromise(url) {
let that=this;
return new Promise((resolve, reject) => {
let a = uni.uploadFile({
url: config.baseUrl +'/xxxxx/xxxxxx?Content-Type=multipart/form-data', // 仅为示例,非真实的接口地址
filePath: url,
name: 'file',
formData: that.chyFormData,
success: (res) => {
console.log(res,"res")
setTimeout(() => {
resolve(res.data)
}, 1000)
}
});
})
},
//获取到上传文件链接
chyGetImageUrl(dataArr){
this.$emit("imageClick",dataArr[0].url);
}
}
}
</script>
<style>
</style>
js代码
export default {
props: {
// 上传最大数量
maxCount: {
type: [Number,String],
default: 1
},
// 提示图片高度
chyHeight: {
type: [Number,String],
default: 150
},
// 提示图片宽度
chyWidth: {
type: [Number,String],
default: 250
},
//提示图片链接
chyImageUrl: {
type: String,
default: 250
},
//附加信息
chyFormData:{
type: Object,
default: ()=>{
}
}
}
}
组件使用代码
vue
userInfo是一个对象
userInfo: {
state:0,
},
formCustomer:{
keyURL:'',
tipImageUr:'提示默认图片'
}
<u-form-item label="上传图片" prop="keyURL" borderBottom required="required"
v-if="item.type==11">
<block v-if="userInfo.state==0">
<u--input v-model="formCustomer.keyURL" border="none"
placeholder="图片地址" v-show="false">
</u--input>
<chy-upload maxCount="1" chyHeight="150" chyWidth="330"
:chyImageUrl="formCustomer.tipImageUr" :chyFormData="userInfo"
@imageClick="(val)=>{ formCustomer.keyURL=val}">
</chy-upload>
</block>
<block v-else>
<u--image
:src="formCustomer.keyURL?formCustomer.keyURL:formCustomer.tipImageUr"
mode="widthFix" width="330px" height="150px"></u--image>
</block>
</u-form-item>
效果图片如下
二下拉组件
vue代码
<template>
<view class="ep-picker-box">
<!-- 蒙版区域 开始 -->
<view class="ep-mask-box" v-show="show" @click="show=false"></view>
<!-- 蒙版区域 开始 -->
<!-- 输入框区域 开始 -->
<view class="ep-input-box" @click="openOptions" :class="{'disabled':disabled}">
<view style="display: flex;align-items: center;min-height: 36px;">{{showLabel}}</view>
<text v-if="!show" class="iconfont icon-xiala"></text>
<text v-else class="iconfont icon-xialashang"></text>
</view>
<!-- 输入框区域 结束 -->
<!-- 弹出的下拉区域 开始 -->
<view v-show="show" class="ep-picker-content-wrap">
<scroll-view class="ep-picker-content" :scroll-y="true">
<!-- 展示下拉项列表 开始 -->
<view v-for="item in options" :key="item[value_key]"
:class="{'disabled':item.disabled,'active':value==item[value_key]}" class="option-item"
@click="itemClick(item)">{{item[label_key]}}</view>
<!-- 展示下拉项列表 结束 -->
<!-- 下拉列表为空 开始 -->
<view v-if="options.length==0" class="option-no-data">无数据</view>
<!-- 下拉列表为空 结束 -->
</scroll-view>
<text class="triangle"></text>
</view>
<!-- 弹出的下拉区域 结束 -->
</view>
</template>
<script>
import props from './props.js'
export default {
name: 'ep-picker-box',
data() {
return {
show: false,
left: 0,
}
},
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
model:{//https://cn.vuejs.org/v2/guide/components-custom-events.html#%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BB%84%E4%BB%B6%E7%9A%84-v-model
prop:'value',
event:"valChange"
},
methods: {
//点击选中选项
itemClick(item) {
if (item.disabled) return
//关闭
this.show = false
//修改v-model的值
this.$emit('valChange', item[this.value_key])
//将事件通知父组件
this.$emit('change', item[this.value_key])
},
//展开选项
openOptions() {
if (!this.disabled) {
this.show = true
}
}
},
computed: {
showLabel() {
var index = this.options.findIndex(item => {
return item[this.value_key] == this.value
})
if (index != -1) {
return this.options[index][this.label_key]
} else if (!this.value) {
return "请选择"
} else {
return this.value
}
}
}
}
</script>
<style scoped>
/* 引入字体图标 */
/* @import './iconfont.css';
*/
.ep-picker-box {
width: 100%;
box-sizing: border-box;
position: relative;
font-size: 14px;
color: #333;
/* max-width: 300px; */
}
.ep-mask-box {
position: fixed;
z-index: 999;
top: 0;
right: 0;
left: 0;
bottom: 0;
background: none;
}
.ep-input-box {
border: 1px solid rgb(229, 229, 229);
border-radius: 4px;
padding-left: 10px;
position: relative;
cursor: pointer;
}
/* 整个下拉组件禁用样式 */
.ep-input-box.disabled {
cursor: not-allowed;
background-color: #f5f7fa;
color: #999;
}
/* 展开收起箭头样式 */
.ep-input-box .iconfont {
position: absolute;
top: 50%;
right: 5px;
font-size: 20px;
transform: translateY(-50%);
color: #B8B8B8;
}
/* 下拉容器样式 外层 */
.ep-picker-content-wrap {
width: 100%;
position: absolute;
top: 45px;
left: 0;
z-index: 9999;
padding-top: 6px;
}
/* 下拉容器样式 内层 */
.ep-picker-content-wrap .ep-picker-content {
background-color: #fff;
padding: 3px 0;
box-shadow: 0 0 20px 5px rgb(0 0 0 / 30%);
border-radius: 5px;
max-height: 181px;
}
/* 下拉项通用样式 */
.ep-picker-content-wrap .ep-picker-content .option-item {
padding: 8px 18px;
cursor: pointer;
}
/* 无下拉项数据时样式 */
.ep-picker-content-wrap .ep-picker-content .option-no-data {
padding: 8px 18px;
cursor: text;
color: #999;
text-align: center;
}
/* 鼠标移入下拉项样式 */
.ep-picker-content-wrap .ep-picker-content .option-item:hover {
background-color: #f5f7fa;
}
/* 已选中的下拉项样式 */
.ep-picker-content-wrap .ep-picker-content .option-item.active {
color: #007AFF;
}
/* 禁用的下拉项样式 */
.ep-picker-content-wrap .ep-picker-content .option-item.disabled {
color: #c0c4cc;
}
.ep-picker-content-wrap .ep-picker-content .option-item.disabled:hover {
cursor: not-allowed;
}
/* 下拉容器指示箭头样式 */
.ep-picker-content-wrap .triangle {
width: 0;
height: 0;
border-top: 6px solid rgba(0, 0, 0, 0);
border-right: 6px solid rgba(0, 0, 0, 0);
border-bottom: 6px solid #fff;
border-left: 6px solid rgba(0, 0, 0, 0);
position: absolute;
top: -6px;
left: 50%;
transform: translateX(-50%);
box-sizing: content-box;
}
</style>
js代码
export default { //https://www.cnblogs.com/OrochiZ-/p/15910440.html
props: {
value: {
type: [String, Number],
default: ""
},
options: {
type: Array,
default: function() {
return []
}
},
value_key: {
type: String,
default: "value"
},
label_key: {
type: String,
default: "label"
},
disabled: {
type: Boolean,
default: false
}
}
}
组件使用页面代码
vue 代码
contractTemplateOptions: [
{
eqbTemplateId: "1",
label: "上海"
}, {
eqbTemplateId: "2",
label: "深圳"
}, {
eqbTemplateId: "3",
label: "广州",
},
]
<u-form-item label="合同模板" prop="eqbTemplateId" ref="item1" borderBottom required>
<ep-picker-box :disabled="signingDisabled" v-model="signingForm.eqbTemplateId"
style="width:100%" :options="contractTemplateOptions" @change="change">
</ep-picker-box>
</u-form-item>
js 代码
change(val) {
this.signingForm.eqbTemplateId = val;
},
效果图
这些组件还是很好用的。记录一下。