@wfrog/vc
Version:
vue3 组件库 vc
413 lines (406 loc) • 15.7 kB
JavaScript
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 _ };