|
@@ -1,111 +1,150 @@
|
|
|
<template>
|
|
|
- <el-scrollbar style="width: 100%; height: 100%; padding: 20px 0">
|
|
|
- <div class="media-container">
|
|
|
- <CameraUpload
|
|
|
- @reset-select="clickReset"
|
|
|
- @upload-finish="finish"
|
|
|
- @delete-all="clickDeleteAll"
|
|
|
- @camera-ohos="camera_ohos"
|
|
|
- @select-ohos="select_ohos"
|
|
|
+ <div class="body">
|
|
|
+ <div class="itemRow">
|
|
|
+ <el-scrollbar @click.stop style="height: calc(100vh - 260px)">
|
|
|
+ <div
|
|
|
+ :class="selectItem === true ? 'itembox itemSelect' : 'itembox'"
|
|
|
+ @click="toCamera"
|
|
|
+ >
|
|
|
+ <svg-icon icon-class="paizhao" size="130" />
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ :class="selectItem === index ? 'itembox itemSelect' : 'itembox'"
|
|
|
+ @click.stop="toShowImg(index)"
|
|
|
+ v-for="(item, index) in medias"
|
|
|
+ >
|
|
|
+ <el-image
|
|
|
+ :src="getImgurl(item)"
|
|
|
+ :zoom-rate="1"
|
|
|
+ class="imgBox"
|
|
|
+ fit="cover"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </el-scrollbar>
|
|
|
+ </div>
|
|
|
+ <div class="view" id="show">
|
|
|
+ <!-- 展示图片或者照相 -->
|
|
|
+ <video
|
|
|
+ id="video"
|
|
|
+ v-if="selectItem === true"
|
|
|
+ height="100%"
|
|
|
+ width="100%"
|
|
|
+ autoplay="autoplay"
|
|
|
+ ></video>
|
|
|
+ <el-image
|
|
|
+ v-if="selectItem !== true && selectItem !== null"
|
|
|
+ :initial-index="selectItem"
|
|
|
+ :max-scale="7"
|
|
|
+ :min-scale="0.2"
|
|
|
+ :preview-src-list="urlList"
|
|
|
+ :src="getImgurl(medias[selectItem])"
|
|
|
+ :zoom-rate="1"
|
|
|
+ style="width: 100%; height: 100%"
|
|
|
+ fit="cover"
|
|
|
/>
|
|
|
- <div
|
|
|
- v-for="(item, index) in medias.filter((item: any) => item.filePath)"
|
|
|
- :key="index"
|
|
|
- class="media-item"
|
|
|
- @click="item.isSelected = !item.isSelected"
|
|
|
- >
|
|
|
- <!-- <img :src="getImgurl(item)" alt="" class="img-box" object-fit="cover" />-->
|
|
|
- <el-image
|
|
|
- :initial-index="index"
|
|
|
- :max-scale="7"
|
|
|
- :min-scale="0.2"
|
|
|
- :preview-src-list="urlList"
|
|
|
- :src="getImgurl(item)"
|
|
|
- :zoom-rate="1.2"
|
|
|
- class="img-box"
|
|
|
- fit="cover"
|
|
|
- />
|
|
|
- <div class="checkB-border"></div>
|
|
|
- <i-ep-delete
|
|
|
- v-show="item.isSelected"
|
|
|
- class="check"
|
|
|
- color="#ff4d4f"
|
|
|
- size="20px"
|
|
|
- />
|
|
|
+ <canvas
|
|
|
+ v-show="false"
|
|
|
+ id="canvas"
|
|
|
+ style="height: 100%; width: 100%"
|
|
|
+ ></canvas>
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ class="itemRow"
|
|
|
+ style="
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ justify-content: space-between;
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <div class="operate">
|
|
|
+ <el-button
|
|
|
+ v-if="selectItem === true"
|
|
|
+ style="width: 100%"
|
|
|
+ type="primary"
|
|
|
+ @click="takePhoto"
|
|
|
+ >拍照</el-button
|
|
|
+ >
|
|
|
+
|
|
|
+ <div class="flashlightBox" v-if="selectItem === true">
|
|
|
+ <div style="margin-top: 5px">闪光灯:</div>
|
|
|
+
|
|
|
+ <el-switch
|
|
|
+ v-model="flashlight"
|
|
|
+ class="mt-2"
|
|
|
+ inline-prompt
|
|
|
+ style="
|
|
|
+ --el-switch-on-color: #13ce66;
|
|
|
+ --el-switch-off-color: #ff4949;
|
|
|
+ "
|
|
|
+ :active-icon="Check"
|
|
|
+ :inactive-icon="Close"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="operate">
|
|
|
+ <el-button style="width: 100%" type="primary">提交</el-button>
|
|
|
</div>
|
|
|
</div>
|
|
|
- </el-scrollbar>
|
|
|
+ </div>
|
|
|
</template>
|
|
|
|
|
|
-<script lang="ts" setup>
|
|
|
+<script setup>
|
|
|
+defineOptions({
|
|
|
+ name: "duomeiticaiji",
|
|
|
+});
|
|
|
import { useProcessStore } from "@/store";
|
|
|
import { addMedia, deleteMedias, pageMedias } from "@/api/prosteps/medias";
|
|
|
-
|
|
|
-import CameraUpload from "@/components/Upload/CameraUpload.vue";
|
|
|
-
|
|
|
+import { Check, Close } from "@element-plus/icons-vue";
|
|
|
+import { uploadFileApi } from "@/api/file";
|
|
|
const proStore = useProcessStore();
|
|
|
-const medias = ref<any>([]);
|
|
|
-const urlList = ref<string[]>([]);
|
|
|
-
|
|
|
-defineOptions({
|
|
|
- name: "Wuliaocaiji",
|
|
|
-});
|
|
|
-
|
|
|
-const input = ref("");
|
|
|
-
|
|
|
-const finish = (value: string) => {
|
|
|
- addMedia({
|
|
|
- filePath: value,
|
|
|
- operationMediaId: proStore.odersData.operationId,
|
|
|
- processId: proStore.scanInfo.id,
|
|
|
- seqNo: proStore.scanInfo.seqNo,
|
|
|
- }).then((res) => {
|
|
|
- getListData();
|
|
|
- ElMessage.success("上传成功");
|
|
|
- });
|
|
|
+const toShowImg = (index) => {
|
|
|
+ console.log(index);
|
|
|
+ selectItem.value = index;
|
|
|
};
|
|
|
-
|
|
|
-onMounted(() => {
|
|
|
- getListData();
|
|
|
-});
|
|
|
-
|
|
|
-const getListData = () => {
|
|
|
- pageMedias(
|
|
|
- proStore.odersData.operationId,
|
|
|
- proStore.scanInfo.id,
|
|
|
- proStore.scanInfo.seqNo
|
|
|
- ).then((res: any) => {
|
|
|
- medias.value = res.data.records || [];
|
|
|
- urlList.value = res.data.records.map((item: any) => {
|
|
|
- return import.meta.env.VITE_APP_UPLOAD_URL + item.filePath;
|
|
|
- });
|
|
|
- });
|
|
|
-};
|
|
|
-
|
|
|
-const getImgurl = (item: any) => {
|
|
|
+//true为切换到视频流 其余则为切换展示图片
|
|
|
+const selectItem = ref(null);
|
|
|
+const flashlight = ref(false);
|
|
|
+const medias = ref([]);
|
|
|
+const urlList = ref([]);
|
|
|
+const getImgurl = (item) => {
|
|
|
let url = import.meta.env.VITE_APP_UPLOAD_URL + item.filePath;
|
|
|
return url;
|
|
|
};
|
|
|
-
|
|
|
-const clickReset = () => {
|
|
|
- // medias.value.forEach((item: any) => {
|
|
|
- // item.isSelected = false;
|
|
|
- // });
|
|
|
- getListData();
|
|
|
+//切换视频流
|
|
|
+const toCamera = () => {
|
|
|
+ if (selectItem.value != true) {
|
|
|
+ selectItem.value = true;
|
|
|
+ ElMessage.success("切换到拍照模式");
|
|
|
+ openMedia();
|
|
|
+ }
|
|
|
};
|
|
|
-
|
|
|
-const clickDeleteAll = () => {
|
|
|
- let ids = medias.value
|
|
|
- .filter((item: any) => item.isSelected)
|
|
|
- .map((item: any) => item.id);
|
|
|
-
|
|
|
- ids &&
|
|
|
- ids.length > 0 &&
|
|
|
- deleteMedias(ids).then(() => {
|
|
|
- getListData();
|
|
|
+let mediaStreamTrack = null; // 视频对象(全局)
|
|
|
+let video;
|
|
|
+const openMedia = async () => {
|
|
|
+ if (window.openHarmonyBridge && window.openHarmonyBridge.startCamera) {
|
|
|
+ camera_ohos();
|
|
|
+ } else {
|
|
|
+ nextTick(() => {
|
|
|
+ let show = document.getElementById("show");
|
|
|
+ let constraints = {
|
|
|
+ video: { width: show.clientWidth, height: show.clientHeight },
|
|
|
+ audio: false,
|
|
|
+ };
|
|
|
+ //获得video摄像头
|
|
|
+ video = document.getElementById("video");
|
|
|
+ navigator.mediaDevices
|
|
|
+ .getUserMedia(constraints)
|
|
|
+ .then(async (mediaStream) => {
|
|
|
+ mediaStreamTrack = mediaStream.getVideoTracks();
|
|
|
+ video.srcObject = mediaStream;
|
|
|
+ video.play();
|
|
|
+ })
|
|
|
+ .catch((error) => {
|
|
|
+ ElMessage.error("没有找到设备,或者没有权限");
|
|
|
+ });
|
|
|
});
|
|
|
+ }
|
|
|
};
|
|
|
-
|
|
|
const select_ohos = () => {
|
|
|
let p = {
|
|
|
token: localStorage.getItem("token"),
|
|
@@ -139,61 +178,117 @@ const camera_ohos = () => {
|
|
|
window.openHarmonyBridge.startCamera(JSON.stringify(p));
|
|
|
}
|
|
|
};
|
|
|
+// 拍照
|
|
|
+function takePhoto() {
|
|
|
+ //获得Canvas对象
|
|
|
+ let video = document.getElementById("video");
|
|
|
+ let canvas = document.getElementById("canvas");
|
|
|
+ let show = document.getElementById("show");
|
|
|
+ canvas.width = show.clientWidth; // 实际渲染像素
|
|
|
+ canvas.height = show.clientHeight; // 实际渲染像素
|
|
|
+ let ctx = canvas.getContext("2d");
|
|
|
+ ctx.imageSmoothingEnabled = false; //关闭抗锯齿
|
|
|
+ ctx.drawImage(video, 0, 0, show.clientWidth, show.clientHeight);
|
|
|
+ let base64Data = document.getElementById("canvas").toDataURL();
|
|
|
+ let blob = dataURItoBlob(base64Data);
|
|
|
+ let file = new File([blob], `photo.png`, { type: "image/png" });
|
|
|
+ uploadFileApi(file).then((res) => {
|
|
|
+ finish(res.data.fileUrl);
|
|
|
+ });
|
|
|
+}
|
|
|
+function dataURItoBlob(base64Data) {
|
|
|
+ var byteString;
|
|
|
+ if (base64Data.split(",")[0].indexOf("base64") >= 0)
|
|
|
+ byteString = atob(base64Data.split(",")[1]);
|
|
|
+ else byteString = unescape(base64Data.split(",")[1]);
|
|
|
+ var mimeString = base64Data.split(",")[0].split(":")[1].split(";")[0];
|
|
|
+ var ia = new Uint8Array(byteString.length);
|
|
|
+ for (var i = 0; i < byteString.length; i++) {
|
|
|
+ ia[i] = byteString.charCodeAt(i);
|
|
|
+ }
|
|
|
+ return new Blob([ia], { type: mimeString });
|
|
|
+}
|
|
|
+const finish = (value) => {
|
|
|
+ addMedia({
|
|
|
+ filePath: value,
|
|
|
+ operationMediaId: proStore.odersData.operationId,
|
|
|
+ processId: proStore.scanInfo.id,
|
|
|
+ seqNo: proStore.scanInfo.seqNo,
|
|
|
+ }).then((res) => {
|
|
|
+ getListData();
|
|
|
+ ElMessage.success("上传成功");
|
|
|
+ });
|
|
|
+};
|
|
|
+// 关闭摄像头
|
|
|
+function closeMedia() {
|
|
|
+ let stream = document.getElementById("video").srcObject;
|
|
|
+ if (stream) {
|
|
|
+ let tracks = stream.getTracks();
|
|
|
+ tracks?.forEach(function (track) {
|
|
|
+ track.stop();
|
|
|
+ });
|
|
|
+ }
|
|
|
+ document.getElementById("video").srcObject = null;
|
|
|
+}
|
|
|
+const getListData = () => {
|
|
|
+ pageMedias(
|
|
|
+ proStore.odersData.operationId,
|
|
|
+ proStore.scanInfo.id,
|
|
|
+ proStore.scanInfo.seqNo
|
|
|
+ ).then((res) => {
|
|
|
+ medias.value = res.data.records || [];
|
|
|
+ urlList.value = res.data.records.map((item) => {
|
|
|
+ return import.meta.env.VITE_APP_UPLOAD_URL + item.filePath;
|
|
|
+ });
|
|
|
+ });
|
|
|
+};
|
|
|
|
|
|
-// window.addEventListener("message", (event) => {
|
|
|
-// const data = JSON.parse(event.data);
|
|
|
-// if (data.fullUrl && data.messageKey && data.messageKey === "refreshView") {
|
|
|
-// getListData();
|
|
|
-// }
|
|
|
-// });
|
|
|
+onMounted(() => {
|
|
|
+ getListData();
|
|
|
+});
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
-.media-container {
|
|
|
+.body {
|
|
|
width: 100%;
|
|
|
- display: grid;
|
|
|
- /*行间距*/
|
|
|
- //grid-row-gap: 24px;
|
|
|
- ///*列间距*/
|
|
|
- //grid-column-gap: 24px;
|
|
|
- /*每3行有2个行间距,所以每个格子的宽高都要减去(24*2) / 3 */
|
|
|
- //grid-template-columns: repeat(4, calc(33.33% - 16px));
|
|
|
- //grid-template-rows: repeat(4, calc(33.33% - 16px));
|
|
|
- //grid-template-columns: 1fr 1fr 1fr 1fr;
|
|
|
- grid-template-columns: repeat(auto-fit, 300px);
|
|
|
- grid-auto-rows: 300px;
|
|
|
- grid-gap: 24px; /* 设置元素之间的间距 */
|
|
|
- overflow-y: auto;
|
|
|
-}
|
|
|
-
|
|
|
-.media-item {
|
|
|
- width: 292px;
|
|
|
- height: 292px;
|
|
|
- flex-shrink: 0;
|
|
|
- margin-bottom: 49px;
|
|
|
- border: 1px solid #ccc;
|
|
|
- border-radius: 16px 16px 16px 16px;
|
|
|
- overflow: hidden;
|
|
|
- position: relative;
|
|
|
-
|
|
|
- .img-box {
|
|
|
- width: 292px;
|
|
|
- height: 292px;
|
|
|
+ height: calc(100vh - 240px);
|
|
|
+ border: 1px solid;
|
|
|
+ display: flex;
|
|
|
+ .itemRow {
|
|
|
+ width: 180px;
|
|
|
+ background-color: #d5dade;
|
|
|
+ padding: 20px;
|
|
|
+ .itembox {
|
|
|
+ width: 140px;
|
|
|
+ height: 140px;
|
|
|
+ border-radius: 10px;
|
|
|
+ background-color: #f2f2f2;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ overflow: hidden;
|
|
|
+ .imgBox {
|
|
|
+ width: 140px;
|
|
|
+ height: 140px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .itemSelect {
|
|
|
+ border: 1px solid greenyellow;
|
|
|
+ box-sizing: border-box;
|
|
|
+ }
|
|
|
+ .operate {
|
|
|
+ margin: 10px 0;
|
|
|
+ .flashlightBox {
|
|
|
+ height: 40px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: start;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- .checkB-border {
|
|
|
- position: absolute;
|
|
|
- top: 20px;
|
|
|
- right: 20px;
|
|
|
- width: 40px;
|
|
|
- height: 40px;
|
|
|
- border: 2px solid #1482f0;
|
|
|
- }
|
|
|
-
|
|
|
- .check {
|
|
|
- position: absolute;
|
|
|
- top: 30px;
|
|
|
- right: 30px;
|
|
|
+ .view {
|
|
|
+ flex: 1;
|
|
|
}
|
|
|
}
|
|
|
</style>
|