|
@@ -0,0 +1,214 @@
|
|
|
+<template>
|
|
|
+ <div class="img-list" v-viewer>
|
|
|
+ <div class="img-item" v-for="(it,key) in imageList" :key="key">
|
|
|
+ <div v-if="it.blobUrl">
|
|
|
+ <img :src="it.blobUrl"/>
|
|
|
+ <ion-icon v-if="!readonly" :icon="closeCircleOutline" color="danger" class="remove-icon"
|
|
|
+ @click="deleteFile(it)"></ion-icon>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="img-item" v-if="(!isSingle || imageList.length==0) && !readonly">
|
|
|
+ <ion-button color="light" @click="takePicture()">
|
|
|
+ <ion-icon :icon="addOutline" size="large"></ion-icon>
|
|
|
+ </ion-button>
|
|
|
+ </div>
|
|
|
+ <ion-item v-if="readonly && imageList.length==0">
|
|
|
+ <ion-label style="flex: 0 0 100% !important;"><p>暂无</p></ion-label>
|
|
|
+ </ion-item>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+<script lang="ts">
|
|
|
+import {defineComponent, ref} from "vue";
|
|
|
+import {camera, cameraOutline, addOutline, closeCircleOutline} from "ionicons/icons";
|
|
|
+import {alertController, IonIcon, IonThumbnail, loadingController} from '@ionic/vue';
|
|
|
+import {Camera, CameraResultType, CameraSource} from '@capacitor/camera';
|
|
|
+import {deleteFile as deleteFileApi, getFileBase64, getList, uploadBase64} from '@/api/system/file';
|
|
|
+import {presentAlert} from "@/api/common";
|
|
|
+import {dealImage, base64ToBlob} from "@/utils/imageUtils";
|
|
|
+
|
|
|
+export default defineComponent({
|
|
|
+ name: 'b-image',
|
|
|
+ components: {IonIcon},
|
|
|
+ props: {
|
|
|
+ fileRefId: {type: String, default: ''},
|
|
|
+ fileType: {type: Number, default: 1},
|
|
|
+ readonly: {type: Boolean, default: true},
|
|
|
+ isSingle: {type: Boolean, default: false} //只能上次一张图片
|
|
|
+ },
|
|
|
+ setup(props) {
|
|
|
+ const accept = 'png,jpeg,jpg,gif';
|
|
|
+ const imageList = ref<any>([]);
|
|
|
+
|
|
|
+ const getImageList = () => {
|
|
|
+ imageList.value = [];
|
|
|
+ if (props.fileRefId)
|
|
|
+ getList({fileRefID: props.fileRefId}).then(resultList => {
|
|
|
+ imageList.value = resultList as any;
|
|
|
+ imageList.value.forEach((img: any) => {
|
|
|
+ if (!img.base64) {
|
|
|
+ getFileBase64(img.fileId).then(base64Str => {
|
|
|
+ if (base64Str)
|
|
|
+ img.blobUrl = URL.createObjectURL(base64ToBlob("data:image/png;base64," + base64Str));
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ const takePicture = async () => {
|
|
|
+ if (props.fileRefId === '' || props.fileRefId == null) {
|
|
|
+ await presentAlert("参数fileRefId为空");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ const image = await Camera.getPhoto({
|
|
|
+ quality: 90,
|
|
|
+ allowEditing: true,
|
|
|
+ source: CameraSource.Photos,
|
|
|
+ resultType: CameraResultType.Uri,
|
|
|
+ });
|
|
|
+
|
|
|
+ if (!accept?.split(',').includes(image.format)) {
|
|
|
+ await presentAlert("只能上传格式为:" + accept + "的文件");
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ dealImage(image.webPath as string, 1000, saveFile);
|
|
|
+ };
|
|
|
+
|
|
|
+ const saveFile = async (newBase64: string) => {
|
|
|
+ const formData = new FormData();
|
|
|
+ formData.append('base64Str', newBase64 as any);
|
|
|
+ formData.append("fileRefId", props.fileRefId);
|
|
|
+ formData.append("fileType", props.fileType.toString());
|
|
|
+ formData.append("isSingle", props.isSingle ? "1" : "0");
|
|
|
+
|
|
|
+ const loading = await loadingController.create({
|
|
|
+ cssClass: 'my-custom-class',
|
|
|
+ message: '正在上传,请稍等...',
|
|
|
+ duration: 2000,
|
|
|
+ });
|
|
|
+
|
|
|
+ await loading.present();
|
|
|
+
|
|
|
+ uploadBase64(formData).then((result) => {
|
|
|
+ if (result) {
|
|
|
+ presentAlert("上传成功");
|
|
|
+ /*getImageList();*/
|
|
|
+ getList({fileRefID: props.fileRefId}).then(resultList => {
|
|
|
+ const imgList = resultList as any;
|
|
|
+ imgList.forEach((img: any) => {
|
|
|
+ if (imageList.value.filter((it: any) => it.fileId === img.fileId).length == 0) {
|
|
|
+ getFileBase64(img.fileId).then(base64Str => {
|
|
|
+ if (base64Str) {
|
|
|
+ img.blobUrl = URL.createObjectURL(base64ToBlob("data:image/png;base64," + base64Str));
|
|
|
+ imageList.value.push(img);
|
|
|
+ }
|
|
|
+
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+ })
|
|
|
+ };
|
|
|
+
|
|
|
+ const deleteFile = async (item: any) => {
|
|
|
+ const alert = await alertController.create({
|
|
|
+ header: '提示!',
|
|
|
+ message: '是否确认删除?',
|
|
|
+ buttons: [
|
|
|
+ {
|
|
|
+ text: '取消',
|
|
|
+ role: 'cancel'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ text: '确认删除',
|
|
|
+ handler: async () => {
|
|
|
+ const loading = await loadingController.create({
|
|
|
+ cssClass: 'my-custom-class',
|
|
|
+ message: '正在删除,请稍等...',
|
|
|
+ duration: 2000,
|
|
|
+ });
|
|
|
+
|
|
|
+ await loading.present();
|
|
|
+
|
|
|
+ deleteFileApi({fileId: item.fileId}).then(result => {
|
|
|
+ if (result) {
|
|
|
+ imageList.value = imageList.value.filter((it: any) => it.fileId != item.fileId);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ });
|
|
|
+
|
|
|
+ await alert.present();
|
|
|
+ }
|
|
|
+
|
|
|
+ getImageList();
|
|
|
+
|
|
|
+ return {
|
|
|
+ camera,
|
|
|
+ IonThumbnail,
|
|
|
+ takePicture,
|
|
|
+ imageList,
|
|
|
+ deleteFile,
|
|
|
+ addOutline,
|
|
|
+ closeCircleOutline
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+);
|
|
|
+</script>
|
|
|
+<style lang="less">
|
|
|
+.img-list {
|
|
|
+ display: flex;
|
|
|
+ text-align: center;
|
|
|
+ flex-direction: row;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ padding: 5px 10px;
|
|
|
+
|
|
|
+ .img-item {
|
|
|
+ width: 25%;
|
|
|
+ position: relative;
|
|
|
+ padding: 0 5px;
|
|
|
+
|
|
|
+ img {
|
|
|
+ height: 73px;
|
|
|
+ object-fit: cover;
|
|
|
+ border-radius: 10px;
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+
|
|
|
+ .remove-icon {
|
|
|
+ position: absolute;
|
|
|
+ right: -3px;
|
|
|
+ top: -6px;
|
|
|
+ font-size: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ ion-button {
|
|
|
+ --box-shadow: 0px;
|
|
|
+ height: 73px;
|
|
|
+ width: 75px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.showbigimg {
|
|
|
+ z-index: 10;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ background: #e1e1e1;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center; /*在主轴上的对齐*/
|
|
|
+ align-items: center; /*在交叉轴上中心点的对齐*/
|
|
|
+
|
|
|
+ img {
|
|
|
+ opacity: 1;
|
|
|
+ vertical-align: middle;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+</style>
|