update for Warranty plugin
This commit is contained in:
parent
6cbd431edb
commit
681262c33e
|
@ -24,14 +24,8 @@
|
|||
<div class="scanner-corner bottom-left"></div>
|
||||
<div class="scanner-corner bottom-right"></div>
|
||||
</div>
|
||||
<qrcode-stream
|
||||
:camera="camera"
|
||||
:torch="isFlashOn"
|
||||
:formats="formats"
|
||||
:track="overlay ? paintOutline : undefined"
|
||||
@detect="onDetect"
|
||||
@init="onInit"
|
||||
/>
|
||||
<qrcode-stream :camera="camera" :torch="isFlashOn" :formats="formats"
|
||||
:track="overlay ? paintOutline : undefined" @detect="onDetect" @init="onInit" />
|
||||
</div>
|
||||
</v-card-text>
|
||||
|
||||
|
@ -48,36 +42,36 @@
|
|||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, onMounted } from 'vue'
|
||||
import { QrcodeStream } from 'vue3-qrcode-reader'
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, onMounted } from 'vue'
|
||||
import { QrcodeStream } from 'vue3-qrcode-reader'
|
||||
|
||||
const props = defineProps({
|
||||
const props = defineProps({
|
||||
modelValue: Boolean,
|
||||
formats: { type: Array as () => string[], default: () => ['QR_CODE', 'EAN_13', 'CODE_128'] },
|
||||
overlay: { type: Boolean, default: true }
|
||||
})
|
||||
const emit = defineEmits<{
|
||||
})
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value: boolean): void
|
||||
(e: 'detected', barcode: string): void
|
||||
(e: 'error', error: Error): void
|
||||
(e: 'close'): void
|
||||
}>()
|
||||
}>()
|
||||
|
||||
const internalShow = ref(props.modelValue)
|
||||
watch(() => props.modelValue, val => internalShow.value = val)
|
||||
watch(internalShow, val => emit('update:modelValue', val))
|
||||
const internalShow = ref(props.modelValue)
|
||||
watch(() => props.modelValue, val => internalShow.value = val)
|
||||
watch(internalShow, val => emit('update:modelValue', val))
|
||||
|
||||
const camera = ref<'auto' | 'off' | 'user' | 'environment'>('environment')
|
||||
const isFlashOn = ref(false)
|
||||
const availableCameras = ref<MediaDeviceInfo[]>([])
|
||||
const isBackCamera = ref(true)
|
||||
const errorMessage = ref('')
|
||||
const canRetry = ref(false)
|
||||
const camera = ref<'auto' | 'off' | 'user' | 'environment'>('environment')
|
||||
const isFlashOn = ref(false)
|
||||
const availableCameras = ref<MediaDeviceInfo[]>([])
|
||||
const isBackCamera = ref(true)
|
||||
const errorMessage = ref('')
|
||||
const canRetry = ref(false)
|
||||
|
||||
const paintOutline = (location: any, ctx: CanvasRenderingContext2D) => {
|
||||
const paintOutline = (location: any, ctx: CanvasRenderingContext2D) => {
|
||||
if (!location) return
|
||||
const { topLeftCorner, topRightCorner, bottomLeftCorner, bottomRightCorner } = location
|
||||
ctx.strokeStyle = '#00ff00'
|
||||
|
@ -89,9 +83,9 @@
|
|||
ctx.lineTo(bottomLeftCorner.x, bottomLeftCorner.y)
|
||||
ctx.closePath()
|
||||
ctx.stroke()
|
||||
}
|
||||
}
|
||||
|
||||
const onInit = async (promise: Promise<void>) => {
|
||||
const onInit = async (promise: Promise<void>) => {
|
||||
try {
|
||||
await promise
|
||||
errorMessage.value = ''
|
||||
|
@ -113,9 +107,9 @@
|
|||
canRetry.value = false
|
||||
emit('error', new Error(errorMessage.value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const onDetect = (promise: Promise<any>) => {
|
||||
const onDetect = (promise: Promise<any>) => {
|
||||
promise.then(result => {
|
||||
if (result?.content) {
|
||||
emit('detected', result.content)
|
||||
|
@ -124,14 +118,14 @@
|
|||
}).catch(err => {
|
||||
console.error('Error decoding QR:', err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const toggleFlash = () => isFlashOn.value = !isFlashOn.value
|
||||
const toggleCamera = () => {
|
||||
const toggleFlash = () => isFlashOn.value = !isFlashOn.value
|
||||
const toggleCamera = () => {
|
||||
camera.value = camera.value === 'environment' ? 'user' : 'environment'
|
||||
isBackCamera.value = camera.value === 'environment'
|
||||
}
|
||||
const requestPermission = async () => {
|
||||
}
|
||||
const requestPermission = async () => {
|
||||
try {
|
||||
await navigator.mediaDevices.getUserMedia({ video: true })
|
||||
errorMessage.value = ''
|
||||
|
@ -140,13 +134,13 @@
|
|||
errorMessage.value = 'دسترسی به دوربین رد شد.'
|
||||
canRetry.value = true
|
||||
}
|
||||
}
|
||||
const close = () => {
|
||||
}
|
||||
const close = () => {
|
||||
internalShow.value = false
|
||||
emit('close')
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
onMounted(async () => {
|
||||
try {
|
||||
const devices = await navigator.mediaDevices.enumerateDevices()
|
||||
availableCameras.value = devices.filter(device => device.kind === 'videoinput')
|
||||
|
@ -160,11 +154,11 @@
|
|||
canRetry.value = false
|
||||
emit('error', new Error(errorMessage.value))
|
||||
}
|
||||
})
|
||||
</script>
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.scanner-container {
|
||||
<style scoped>
|
||||
.scanner-container {
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
background: #000;
|
||||
|
@ -174,13 +168,15 @@
|
|||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.scanner-container video {
|
||||
}
|
||||
|
||||
.scanner-container video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
.scanner-overlay {
|
||||
}
|
||||
|
||||
.scanner-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
@ -188,8 +184,9 @@
|
|||
bottom: 0;
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
}
|
||||
.scanner-line {
|
||||
}
|
||||
|
||||
.scanner-line {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
|
@ -197,27 +194,62 @@
|
|||
height: 2px;
|
||||
background: #00ff00;
|
||||
animation: scan 2s linear infinite;
|
||||
}
|
||||
.scanner-corner {
|
||||
}
|
||||
|
||||
.scanner-corner {
|
||||
position: absolute;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-color: #00ff00;
|
||||
border-style: solid;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
.scanner-corner.top-left {
|
||||
top: 20%;
|
||||
left: 20%;
|
||||
border-top-width: 4px;
|
||||
border-left-width: 4px;
|
||||
}
|
||||
|
||||
.scanner-corner.top-right {
|
||||
top: 20%;
|
||||
right: 20%;
|
||||
border-top-width: 4px;
|
||||
border-right-width: 4px;
|
||||
}
|
||||
|
||||
.scanner-corner.bottom-left {
|
||||
bottom: 20%;
|
||||
left: 20%;
|
||||
border-bottom-width: 4px;
|
||||
border-left-width: 4px;
|
||||
}
|
||||
|
||||
.scanner-corner.bottom-right {
|
||||
bottom: 20%;
|
||||
right: 20%;
|
||||
border-bottom-width: 4px;
|
||||
border-right-width: 4px;
|
||||
}
|
||||
|
||||
@keyframes scan {
|
||||
0% {
|
||||
transform: translateY(-50px);
|
||||
}
|
||||
.scanner-corner.top-left { top: 20%; left: 20%; border-top-width: 4px; border-left-width: 4px; }
|
||||
.scanner-corner.top-right { top: 20%; right: 20%; border-top-width: 4px; border-right-width: 4px; }
|
||||
.scanner-corner.bottom-left { bottom: 20%; left: 20%; border-bottom-width: 4px; border-left-width: 4px; }
|
||||
.scanner-corner.bottom-right { bottom: 20%; right: 20%; border-bottom-width: 4px; border-right-width: 4px; }
|
||||
@keyframes scan {
|
||||
0% { transform: translateY(-50px); }
|
||||
50% { transform: translateY(50px); }
|
||||
100% { transform: translateY(-50px); }
|
||||
|
||||
50% {
|
||||
transform: translateY(50px);
|
||||
}
|
||||
.error-box {
|
||||
|
||||
100% {
|
||||
transform: translateY(-50px);
|
||||
}
|
||||
}
|
||||
|
||||
.error-box {
|
||||
padding: 16px;
|
||||
color: red;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
}
|
||||
</style>
|
|
@ -343,6 +343,10 @@ const submit = async () => {
|
|||
const errors: string[] = []
|
||||
let totalCount = 0
|
||||
|
||||
items.value.forEach((row) => {
|
||||
totalCount += Number(row.ticketCount || 0)
|
||||
})
|
||||
|
||||
if (totalCount === 0) errors.push('هیچ کالایی برای خروج انتخاب نشده است')
|
||||
|
||||
if (errors.length) {
|
||||
|
|
Loading…
Reference in a new issue