UNPKG

@wfrog/vc

Version:

vue3 组件库 vc

413 lines (406 loc) 15.7 kB
import './index.css' import '../../chunk/E_WRn0OP.mjs'; import { v as vLoading } from '../../chunk/BeMzzYc5.mjs'; import { E as ElButton } from '../../chunk/BT7IBuxS.mjs'; import '../../chunk/Bm4zCpG6.mjs'; import { E as ElSelect, a as ElOption } from '../../chunk/DVg9glNI.mjs'; import '../../chunk/CJQcPuNK.mjs'; import '../../chunk/DUd8IaU9.mjs'; import { E as ElAlert } from '../../chunk/DS5HrvQK.mjs'; import { E as ElImage } from '../../chunk/D3Dgi5XT.mjs'; import { ref, defineComponent, useTemplateRef, reactive, computed, watch, createBlock, openBlock, unref, isRef, withCtx, withDirectives, createElementBlock, normalizeStyle, normalizeClass, createCommentVNode, createVNode, vShow, createElementVNode, Transition, Fragment, renderList, createTextVNode } from 'vue'; import { Camera, Upload } from '@element-plus/icons-vue'; import { d as defaultWindow, f as file } from '../../chunk/BdDihk0t.mjs'; import { C as Component$3 } from '../cropper/cropper.mjs'; import { C as Component$1 } from '../dialog/dialog.mjs'; import { C as Component$2 } from '../upload-file/upload-file.mjs'; import { a as useUserMedia } from '../../chunk/eQT9aAiW.mjs'; import { E as ElIcon } from '../../chunk/m2vp1CCf.mjs'; import { _ as _export_sfc } from '../../chunk/pcqpp-6-.mjs'; const TYPE_UPLOAD = "upload"; const TYPE_CAMERA = "camera"; const WINDOW_IMAGE = "image"; const WINDOW_VIDEO = "video"; const WINDOW_CANVAS = "canvas"; const WINDOW_PLACEHOLDER = "placeholder"; function useVideosList() { const cameras = ref([]); const getVideosList = async () => { const temp = await navigator.mediaDevices.getUserMedia({ video: true }); temp.getTracks().forEach((t) => t.stop()); const devs = await navigator.mediaDevices.enumerateDevices(); cameras.value = devs.filter((d) => d.deviceId && d.kind === "videoinput"); }; return { cameras, getVideosList }; } const _hoisted_1 = ["width", "height"]; const _hoisted_2 = ["width", "height"]; const _hoisted_3 = { key: 1 }; const TIPS_SHOOT_SUCCESS = "照片拍摄成功"; const _sfc_main = /* @__PURE__ */ defineComponent({ __name: "dialog-camera-upload", props: { visible: { type: Boolean }, type: { default: () => [TYPE_UPLOAD, TYPE_CAMERA] }, width: { default: 600 }, fixWidth: { default: 32 }, height: { default: 400 }, accept: { default: ".jpg,.jpeg,.png" }, cropper: { type: Boolean, default: true }, cropperOption: {} }, emits: ["update:visible", "close", "error", "save"], setup(__props, { emit: __emit }) { const props = __props; const emits = __emit; const currentCamera = ref(); const { cameras, getVideosList } = useVideosList(); const { stream, start, stop, enabled } = useUserMedia({ constraints: { video: { width: props.width, height: props.height, deviceId: currentCamera.value }, audio: false } }); const videoRef = useTemplateRef("videoRef"); const canvasRef = useTemplateRef("canvasRef"); const currentWindow = ref(""); const blobImage = ref(""); const loading = ref(false); const cropperVisible = ref(false); const alert = reactive({ visible: false, type: "success", description: "" }); let myFile; const dialogWidth = computed(() => `${props.width + props.fixWidth}px`); const windowStyle = computed(() => ({ width: `${props.width}px`, height: `${props.height}px` })); const cameraVisible = computed(() => props.type.includes(TYPE_CAMERA) && currentCamera.value); const uploadVisible = computed(() => props.type.includes(TYPE_UPLOAD)); const imageVisible = computed(() => currentWindow.value === WINDOW_IMAGE); const canvasVisible = computed(() => currentWindow.value === WINDOW_CANVAS); const videoVisible = computed(() => currentWindow.value === WINDOW_VIDEO); const placeholderVisible = computed(() => currentWindow.value === WINDOW_PLACEHOLDER || imageVisible.value || canvasVisible.value); const placeholderOpacity = computed(() => currentWindow.value === WINDOW_PLACEHOLDER); const confirmVisible = computed(() => { const haveSource = !!blobImage.value; const myWindow = [WINDOW_CANVAS, WINDOW_IMAGE].includes(currentWindow.value); return haveSource && myWindow; }); watch(stream, () => { if (videoRef.value && stream.value) { videoRef.value.srcObject = stream.value; videoRef.value.play(); loading.value = false; } }); const dialogVisible = computed({ get: () => props.visible, set: (val) => { emits("update:visible", val); if (!val) { emits("close"); } } }); function showAlert(type, description) { alert.visible = true; alert.description = description; alert.type = type; setTimeout(() => { alert.visible = false; }, 1500); } function handleClose() { dialogVisible.value = false; } function toggleWindow(type) { currentWindow.value = type; } async function initWindow() { try { if (props.type.includes(TYPE_CAMERA)) { await getVideosList(); if (cameras.value.length) { currentCamera.value = cameras.value[0].deviceId; } } } catch { console.error(new Error("获取摄像头失败")); } toggleWindow(WINDOW_PLACEHOLDER); blobImage.value = ""; } watch(dialogVisible, (val) => { val ? initWindow() : stop(); }); function handleBack() { if (blobImage.value) { toggleWindow(WINDOW_IMAGE); return; } toggleWindow(WINDOW_PLACEHOLDER); } function handleSave() { emits("save", myFile, blobImage.value); handleClose(); } function handleOpenCamera() { loading.value = true; toggleWindow(WINDOW_VIDEO); if (enabled.value) { loading.value = false; return; } start(); } function handleShoot() { if (!defaultWindow || !canvasRef.value || !videoRef.value) { return; } toggleWindow(WINDOW_CANVAS); const context = canvasRef.value.getContext("2d"); context.drawImage(videoRef.value, 0, 0, props.width, props.height); myFile = file.dataURLToFile(canvasRef.value.toDataURL(), "camera.png"); const localUrl = defaultWindow.URL.createObjectURL(myFile); blobImage.value = localUrl; showAlert("success", TIPS_SHOOT_SUCCESS); } function handleHttpRequest(file2, done, localUrl) { done(); toggleWindow(WINDOW_IMAGE); blobImage.value = localUrl; myFile = file2; } const handleError = (message) => emits("error", message); function handleCropperOpen() { cropperVisible.value = true; } function handleFinished(_canvas, blob) { if (!defaultWindow) { return; } myFile = file.blobToFile(blob, "cropper.png"); const localUrl = defaultWindow.URL.createObjectURL(myFile); blobImage.value = localUrl; toggleWindow(WINDOW_IMAGE); } return (_ctx, _cache) => { const _component_ElImage = ElImage; const _component_ElAlert = ElAlert; const _component_ElIcon = ElIcon; const _component_ElOption = ElOption; const _component_ElSelect = ElSelect; const _component_ElButton = ElButton; const _directive_loading = vLoading; return openBlock(), createBlock(Component$1, { modelValue: unref(dialogVisible), "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => isRef(dialogVisible) ? dialogVisible.value = $event : null), title: "拍照上传", "close-on-click-modal": false, width: unref(dialogWidth), "show-close": false, "append-to-body": "", "destroy-on-close": "", "show-fullscreen": false, lazy: "" }, { footer: withCtx(() => [ createElementVNode("div", { class: normalizeClass(_ctx.$style.footer) }, [ unref(cameraVisible) ? (openBlock(), createBlock(_component_ElSelect, { key: 0, modelValue: unref(currentCamera), "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => isRef(currentCamera) ? currentCamera.value = $event : null), class: normalizeClass(_ctx.$style.select) }, { default: withCtx(() => [ (openBlock(true), createElementBlock(Fragment, null, renderList(unref(cameras), (item) => { return openBlock(), createBlock(_component_ElOption, { key: item.deviceId, label: item.label, value: item.deviceId }, null, 8, ["label", "value"]); }), 128)) ]), _: 1 }, 8, ["modelValue", "class"])) : (openBlock(), createElementBlock("span", _hoisted_3)), createElementVNode("div", null, [ withDirectives(createVNode(_component_ElButton, { onClick: handleClose }, { default: withCtx(() => [..._cache[3] || (_cache[3] = [ createTextVNode("取消", -1) ])]), _: 1 }, 512), [ [vShow, !unref(videoVisible)] ]), withDirectives(createVNode(_component_ElButton, { loading: unref(loading), onClick: handleBack }, { default: withCtx(() => [..._cache[4] || (_cache[4] = [ createTextVNode("返回", -1) ])]), _: 1 }, 8, ["loading"]), [ [vShow, unref(videoVisible)] ]), withDirectives(createVNode(_component_ElButton, { loading: unref(loading), type: "primary", onClick: handleShoot }, { default: withCtx(() => [..._cache[5] || (_cache[5] = [ createTextVNode("拍摄", -1) ])]), _: 1 }, 8, ["loading"]), [ [vShow, unref(videoVisible)] ]), withDirectives(createVNode(_component_ElButton, { onClick: handleCropperOpen }, { default: withCtx(() => [..._cache[6] || (_cache[6] = [ createTextVNode("裁剪", -1) ])]), _: 1 }, 512), [ [vShow, unref(confirmVisible) && __props.cropper] ]), withDirectives(createVNode(_component_ElButton, { loading: unref(loading), type: "primary", onClick: handleSave }, { default: withCtx(() => [..._cache[7] || (_cache[7] = [ createTextVNode("保存", -1) ])]), _: 1 }, 8, ["loading"]), [ [vShow, unref(confirmVisible)] ]) ]) ], 2) ]), default: withCtx(() => [ withDirectives((openBlock(), createElementBlock("div", { class: normalizeClass(_ctx.$style.window), style: normalizeStyle(unref(windowStyle)) }, [ withDirectives(createVNode(_component_ElImage, { src: unref(blobImage), fit: "contain" }, null, 8, ["src"]), [ [vShow, unref(imageVisible)] ]), withDirectives(createElementVNode("video", { ref_key: "videoRef", ref: videoRef, width: __props.width, height: __props.height, muted: "", onClick: handleShoot }, null, 8, _hoisted_1), [ [vShow, unref(videoVisible)] ]), withDirectives(createElementVNode("canvas", { ref_key: "canvasRef", ref: canvasRef, width: __props.width, height: __props.height }, null, 8, _hoisted_2), [ [vShow, unref(canvasVisible)] ]), withDirectives(createElementVNode("div", { class: normalizeClass(_ctx.$style.alert) }, [ createVNode(Transition, { mode: "out-in" }, { default: withCtx(() => [ createVNode(_component_ElAlert, { title: "提示", type: unref(alert).type, center: "", "show-icon": "", closable: false, description: unref(alert).description }, null, 8, ["type", "description"]) ]), _: 1 }) ], 2), [ [vShow, unref(alert).visible] ]), withDirectives(createElementVNode("div", { class: normalizeClass([{ [_ctx.$style["placeholder-opacity"]]: unref(placeholderOpacity) }, _ctx.$style.placeholder]) }, [ unref(cameraVisible) ? (openBlock(), createElementBlock("div", { key: 0, onClick: handleOpenCamera }, [ createVNode(_component_ElIcon, null, { default: withCtx(() => [ createVNode(unref(Camera)) ]), _: 1 }) ])) : createCommentVNode("", true), unref(uploadVisible) ? (openBlock(), createBlock(Component$2, { key: 1, "http-request": handleHttpRequest, type: "button", onError: handleError }, { default: withCtx(() => [ createElementVNode("span", null, [ createVNode(_component_ElIcon, null, { default: withCtx(() => [ createVNode(unref(Upload)) ]), _: 1 }) ]) ]), _: 1 })) : createCommentVNode("", true) ], 2), [ [vShow, unref(placeholderVisible)] ]), __props.cropper ? (openBlock(), createBlock(Component$3, { key: 0, visible: unref(cropperVisible), "onUpdate:visible": _cache[0] || (_cache[0] = ($event) => isRef(cropperVisible) ? cropperVisible.value = $event : null), image: unref(blobImage), option: __props.cropperOption, dialog: "", onFinished: handleFinished }, null, 8, ["visible", "image", "option"])) : createCommentVNode("", true) ], 6)), [ [_directive_loading, unref(loading)] ]) ]), _: 1 }, 8, ["modelValue", "width"]); }; } }); /* unplugin-vue-components disabled */const window = "_window_2ntq2_1"; const alert = "_alert_2ntq2_13"; const placeholder = "_placeholder_2ntq2_23"; const footer = "_footer_2ntq2_63"; const select = "_select_2ntq2_68"; const style0 = { window: window, alert: alert, placeholder: placeholder, "placeholder-opacity": "_placeholder-opacity_2ntq2_59", footer: footer, select: select }; const cssModules = { "$style": style0 }; const Component = /* @__PURE__ */ _export_sfc(_sfc_main, [["__cssModules", cssModules]]); const __vite_glob_0_10 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({ __proto__: null, default: Component }, Symbol.toStringTag, { value: 'Module' })); export { Component as C, __vite_glob_0_10 as _ };