h5相机功能

h5相机功能

利用vant + input file

<template>
	<div class="mb10">
		<div
			v-for="(item, index) in info.imgList"
			:key="index"
			class="imgItem f32 mr20"
			@click="preview(item, index)"
		>
			<img :src="doFileUrl(item)" alt="" srcset="" />
			<van-icon
				v-if="!disabled"
				class="close f34 txt-f6"
				name="close"
				@click.stop="deleteImg(item, index)"
			/>
		</div>
		<div
			v-show="info.imgList.length < maxCount && !disabled"
			class="btnUpload f32 mr10"
			@click="clickUpload"
		>
			<van-icon name="plus" />
			<input
				ref="camera"
				class="cameraInput"
				type="file"
				name="file"
				accept="image/*"
				capture="camera"
				@change="uploadImg"
			/>
		</div>
	</div>

	<!-- 底部弹出 -->
	<van-action-sheet
		v-model:show="showChoose"
		:actions="info.actions"
		cancel-text="取消"
		close-on-click-action
		@cancel="onCancel"
		@select="selectAction"
	/>
</template>

<script lang="ts" setup>
import { ref, getCurrentInstance, reactive, onMounted, defineExpose } from 'vue'
import { Action, InfoInterface } from './config'
import { fileUpload } from '@/utils/fileHttp'

const emit = defineEmits(['chooseFIle'])
/**
 * @description: 传参
 * @return {*}
 * @Date Changed:
 */
interface Props {
	// 文件list
	fileList: string | null | any[]
	// 上传数量
	maxCount?: number
	//尺寸  这个暂时没用
	maxSize?: number
	// 缩略图大小 px 和 rem
	disabled?: boolean
	// 图片类型
	accept?: string[]

	type?: number[]
	// 是否全部允许
	allowAllAccept?: boolean

	isRequire?: boolean

	//
}
const props = withDefaults(defineProps<Props>(), {
	fileList: () => [],
	maxCount: 1,
	maxSize: 5 * 1024 * 1024,
	disabled: false,
	accept: () => ['image'],
	type: () => [0],
	allowAllAccept: false,
	isRequire: false
})

/**
 * @description: 通用参数
 * @return {*}
 * @Date Changed:
 */
const { proxy }: any = getCurrentInstance()
const router = proxy.commond.router()
const route = proxy.commond.route()
const { Toast } = proxy.commond

const info = reactive<InfoInterface>({
	imgList: [],
	actions: []
	// aaaaaa: []
})
let toastLoading: any = null
const token = proxy.commond.getToken()

/**
 * @description: 生命周期
 * @return {*}
 * @Date Changed:
 */
onMounted(() => {
	init()
})
const init = () => {
	// 拍照模式
	const arr: Action[] = []
	props.type.forEach((item: number) => {
		arr.push(list[item])
	})
	info.actions = arr
}

//----------------------------------------------------------- 底部弹出选择拍照模式
const showChoose = ref(false)
const list: Action[] = [
	{
		name: '拍照',
		type: 'ShowView',
		value: 'CameraView'
	},
	{
		name: '相册',
		type: 'ShowView',
		value: 'PhotoView'
	},
	{
		name: '文件上传',
		type: 'uploadFile',
		value: 'fileView'
	}
]
const clickUpload = () => {
	showChoose.value = true
}
const onCancel = () => {
	showChoose.value = false
}
const selectAction = async (action: Action, index: number) => {
	if (action.value === 'CameraView') {
		// 拍照
		console.log(proxy.$refs.camera)

		proxy.$refs.camera.click()
		showChoose.value = false
	}

	// if (res.length > 0) {
	// 	const arr = proxy.commond.deepClone(info.imgList)
	// 	res.map((ele) => {
	// 		arr.push(`OSS_FILE_${ele.resourcesId}/${ele.fullFileName}`)
	// 	})
	// 	emit('success', arr)
	// 	showChoose.value = false
	// }
}

/**
 * @description: 上传文件
 * @return {*}
 */

const uploadImg = (e: any) => {
	// 这里可以做一些限制 比如 文件大小 文件类型等
	// ----------
	const file = e.target.files[0]
	// 原生请求
	toastLoading = proxy.commond.Toast.loading({
		duration: 0,
		forbidClick: true,
		message: '开始上传...'
	})
	fileUpload(file)
		.then((data: any) => {
			const url = `OSS_FILE_${data.result.resourcesId}/${data.result.fullFileName}`
			info.imgList.push(url)
			emit('chooseFIle', info.imgList, file)
			toastLoading.clear()
			proxy.$refs.camera.value = ''
		})
		.catch((err) => {
			toastLoading.clear()
			proxy.commond.Toast(err.message)
			proxy.$refs.camera.value = ''
		})
}

const doFileUrl = (resourcesId: string): string => {
	return proxy.commond.doFileUrl(resourcesId)
}

/**
 * @description: 删除照片
 * @param {*} val
 * @param {*} index
 * @return {*}
 */
const deleteImg = (val: string, index: number) => {
	info.imgList.splice(index, 1)
	emit('chooseFIle', info.imgList, '')
}

/**
 * @description: 图片预览
 * @param {*} val
 * @param {*} index
 * @return {*}
 */
const preview = (val: string, index: number) => {
	const arr: string[] = []
	info.imgList.forEach((ele) => {
		arr.push(doFileUrl(ele))
	})
	proxy.commond.ImagePreview({
		images: arr,
		startPosition: index
	})
}

defineExpose({
	selectAction,
	preview
})
</script>

<style lang="scss" scoped>
.cameraInput {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	top: 0;
	display: none;
}

.btnUpload {
	position: relative;
	text-align: center;
	background-color: #fbfdff;
	border: 1px dashed #c0ccda;
	border-radius: 6px;
	box-sizing: border-box;
	display: inline-block;
	width: 148px;
	height: 148px;
	cursor: pointer;
	line-height: 146px;
	vertical-align: top;
}

.imgItem {
	display: inline-block;
	position: relative;
	border: 1px dashed #c0ccda;
	width: 148px;
	height: 148px;
	cursor: pointer;
	img {
		margin-top: 4px;
		width: 140px;
		height: 140px;
	}

	.close {
		position: absolute;
		right: -14px;
		top: -10px;
		background: #fff;
		border-radius: 100px;
		color: $danger;
	}
}
</style>

/**
 * @description: 上传文件景天参数
 * @return {*}
 * @Date Changed:
 */
export interface Action {
	name: string
	type: string
	value: string
}

/**
 * @description:图片返回值处理
 * @return {*}
 * @Date Changed:
 */
export interface ImgFace {
	resourcesId: string
	resourceUrl: string
	fullFileName: string
	fileName: string
	id: string
}

/**
 * @descriptioninfo
 * @return {*}
 * @Date Changed:
 */
export interface InfoInterface {
	imgList: string[]
	actions: Action[]
}

export interface fileBox {
	show: boolean
	url: string
}

使用

// 调用相机


<GlFace ref="face" :file-list="[]" @chooseFIle="chooseFIle"></GlFace>
const face = ref(null)
	face.value.selectAction({ value: 'CameraView' })
相关推荐
燃先生._.3 分钟前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖1 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
m0_748235241 小时前
前端实现获取后端返回的文件流并下载
前端·状态模式
m0_748240252 小时前
前端如何检测用户登录状态是否过期
前端
black^sugar2 小时前
纯前端实现更新检测
开发语言·前端·javascript
寻找沙漠的人3 小时前
前端知识补充—CSS
前端·css
GISer_Jing3 小时前
2025前端面试热门题目——计算机网络篇
前端·计算机网络·面试
m0_748245523 小时前
吉利前端、AI面试
前端·面试·职场和发展
理想不理想v3 小时前
webpack最基础的配置
前端·webpack·node.js