refactor: view image dialog

This commit is contained in:
puriphatt 2024-12-24 13:24:15 +07:00
parent bfe5da2565
commit 718a28642d
3 changed files with 126 additions and 1 deletions

View file

@ -6,7 +6,11 @@ import { storeToRefs } from 'pinia';
import WorkerItem from './WorkerItem.vue';
import DeleteButton from '../button/DeleteButton.vue';
import { precisionRound } from 'src/utils/arithmetic';
import { ProductServiceList, QuotationPayload } from 'stores/quotations/types';
import {
ProductRelation,
ProductServiceList,
QuotationPayload,
} from 'stores/quotations/types';
import { formatNumberDecimal, commaInput } from 'stores/utils';
import { useConfigStore } from 'stores/config';
@ -29,6 +33,7 @@ const props = defineProps<{
}>();
defineEmits<{
(e: 'viewFile', data: ProductRelation): void;
(e: 'delete', index: number): void;
(
e: 'updateTable',
@ -449,6 +454,7 @@ watch(
background-color: hsla(var(--positive-bg) / 0.1);
color: hsl(var(--positive-bg));
"
@click="$emit('viewFile', props.row.product)"
/>
<DeleteButton
v-if="!readonly"

View file

@ -0,0 +1,99 @@
<script lang="ts" setup>
import { reactive } from 'vue';
import DialogFormContainer from './DialogFormContainer.vue';
import DialogHeader from './DialogHeader.vue';
import MainButton from '../button/MainButton.vue';
import NoData from '../NoData.vue';
defineProps<{
title: string;
url?: string;
}>();
const open = defineModel<boolean>({ default: false });
const state = reactive({
imageZoom: 100,
});
function openDialog() {
state.imageZoom = 100;
}
</script>
<template>
<DialogFormContainer v-model="open" v-on:open="openDialog">
<template #header>
<DialogHeader :title="title" />
</template>
<main class="column full-height">
<section
style="background: var(--gray-3)"
class="q-py-sm row justify-center"
>
<div class="surface-2 q-px-md q-py-sm rounded row no-wrap items-center">
<MainButton
icon="mdi-minus"
color="0 0% 0%"
icon-only
@click="
() => {
if (state.imageZoom > 0) state.imageZoom -= 10;
}
"
/>
<q-input
dense
outlined
class="q-px-sm"
input-class="text-center text-caption"
:model-value="state.imageZoom"
@update:model-value="
(val) => {
const numVal = Number(val);
if (numVal > 500 || numVal < 0) {
state.imageZoom = 100;
} else {
state.imageZoom = numVal || 100;
}
}
"
></q-input>
<MainButton
icon="mdi-plus"
color="0 0% 0%"
icon-only
@click="
() => {
if (state.imageZoom < 500) state.imageZoom += 10;
}
"
/>
</div>
</section>
<div
:class="{ 'cursor-pointer': state.imageZoom > 100 }"
class="full-height full-width flex justify-center items-center col scroll q-pa-md"
v-dragscroll
>
<q-img
v-if="url"
class="full-height"
:src="url"
fit="contain"
:style="{ transform: `scale(${state.imageZoom / 100})` }"
style="transform-origin: 0 0"
/>
<NoData v-else />
</div>
</main>
</DialogFormContainer>
</template>
<style scoped>
:deep(.q-field__control.relative-position.row.no-wrap) {
width: 60px;
height: 30px;
}
</style>

View file

@ -29,6 +29,7 @@ import { View } from './types.ts';
import {
EmployeeWorker,
PayCondition,
ProductRelation,
ProductServiceList,
QuotationPayload,
} from 'src/stores/quotations/types';
@ -64,6 +65,7 @@ import QuotationFormInfo from './QuotationFormInfo.vue';
import QuotationFormWorkerSelect from './QuotationFormWorkerSelect.vue';
import QuotationFormWorkerAddDialog from './QuotationFormWorkerAddDialog.vue';
import UploadFileSection from 'src/components/upload-file/UploadFileSection.vue';
import DialogViewFile from 'src/components/dialog/DialogViewFile.vue';
import { columnPaySplit } from './constants';
import { precisionRound } from 'src/utils/arithmetic';
@ -291,6 +293,9 @@ const pageState = reactive({
employeeModal: false,
productServiceModal: false,
remarkWrite: true,
imageDialog: false,
imageDialogTitle: '',
imageDialogUrl: '',
});
const productList = ref<Partial<Record<ProductGroupId, Product[]>>>({});
@ -956,6 +961,14 @@ async function uploadAttachment(file?: File) {
if (ret) await getAttachment();
}
function viewProductFile(data: ProductRelation) {
const base64 = data.detail.match(/src="([^"]+)"/);
pageState.imageDialog = true;
pageState.imageDialogTitle = data.name;
pageState.imageDialogUrl = base64 ? base64[1] : '';
}
const sessionData = ref<Record<string, any>>();
onMounted(async () => {
@ -1539,6 +1552,7 @@ watch(
}
"
@update-table="handleUpdateProductTable"
@view-file="viewProductFile"
/>
</div>
</q-expansion-item>
@ -2262,6 +2276,12 @@ watch(
fetchQuotation();
"
/>
<DialogViewFile
:title="pageState.imageDialogTitle"
:url="pageState.imageDialogUrl"
v-model="pageState.imageDialog"
/>
</template>
<style scoped>