hldy_app_mini/pages/material/component/torytor.vue

474 lines
9.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view>
<view class="jsuq guodu">
<view class="leftsa">
<view class="shu">盘点数量</view>
<view :class="pddType!='3'? `stringShow-kuai`:`stringShow-kuai-bad`" class="kuai-margin">
<view v-for="(item,index) in stringShow" :key="index">
{{item}}
</view>
</view>
<view class="jiajian">
<view :class="pddType!='3'? `jj`:`jj-bad`" @click="jjnum(-1)" @touchstart="handleTouchStart(-1)"
@touchend="handleTouchEnd">
-
</view>
<view :class="pddType!='3'? `jj`:`jj-bad`" @click="jjnum(1)" @touchstart="handleTouchStart(1)"
@touchend="handleTouchEnd">
+
</view>
</view>
</view>
<view class="rigsbt">
<view class="calculator-father">
<view v-for="(item,index) in calculatorArray" :key="index">
<view :class="pddType!='3'?`calculator-kuai`:`calculator-kuai-bad`" v-if="item==`AC`"
@click="clickKuai(item,index)">
<image src="/static/cleanone.png" mode="aspectFill"
style="width: 50%;height: 50%;margin-left: -5rpx;"></image>
</view>
<view :class="pddType!='3'?`calculator-kuai`:`calculator-kuai-bad`" v-else
@click="clickKuai(item,index)">
{{item}}
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import { ref, watch, onBeforeUnmount } from 'vue'
const props = defineProps({
show: {
type: Boolean
},
tb: {
type: Number
},
idex: {
type: Number
},
pdsl: {
type: [Number, String]
},
pddType: {
type: String
},
pushnumber: {
type: Number,
default: 0
}
})
const emit = defineEmits(['pddjjnum'])
const calculatorArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, ".", "AC"]
const MAX_INT = 4
const MAX_DEC = 2
const MAX_VALUE = 9999.99
// 实际输入值,必须用字符串保存
const inputValue = ref('0')
// 你模板里显示用的字符串
const stringShow = ref('0')
const isZero = ref(false)
function formatDisplay(raw : string) {
const [intRaw = '0', decRaw = ''] = String(raw ?? '0').split('.')
// 整数部分固定 4 位,不足补 0
const intPart = intRaw.replace(/\D/g, '').padStart(4, '0').slice(-4)
// 小数部分固定 2 位,不足补 0
const decPart = decRaw.replace(/\D/g, '').padEnd(2, '0').slice(0, 2)
return `${intPart}.${decPart}`
}
function normalizeInput(raw : string) {
let v = String(raw ?? '').replace(/[^\d.]/g, '')
// 处理空值和单独输入小数点
if (!v) return '0'
if (v === '.') return '0.'
// 只保留第一个小数点
const dotIndex = v.indexOf('.')
if (dotIndex !== -1) {
const intRaw = v.slice(0, dotIndex)
const decRaw = v.slice(dotIndex + 1)
let intPart = intRaw.replace(/^0+(?=\d)/, '')
if (intPart === '') intPart = '0'
intPart = intPart.slice(0, MAX_INT)
const decPart = decRaw.slice(0, MAX_DEC)
return `${intPart}.${decPart}`
}
let intPart = v.replace(/^0+(?=\d)/, '')
if (intPart === '') intPart = '0'
return intPart.slice(0, MAX_INT)
}
function setValue(raw : string) {
inputValue.value = normalizeInput(raw)
stringShow.value = formatDisplay(inputValue.value)
emit('pddjjnum', Number(inputValue.value || 0))
}
watch(
() => props.show,
() => {
if (props.show) {
setValue(String(props.pdsl ?? 0))
isZero.value = false
} else {
setValue('0')
}
},
{ immediate: true }
)
watch(
() => props.pushnumber,
() => {
applyEcho()
},
{ immediate: true }
)
function applyEcho() {
// 回显优先用 pushnumber没有就用 pdsl
const echoValue = props.pushnumber?? 0
setValue(String(echoValue))
isZero.value = false
}
function appendDigit(d : number) {
const digit = String(d)
const raw = inputValue.value
// 已有小数点
if (raw.includes('.')) {
const [intPart, decPart = ''] = raw.split('.')
if (decPart.length >= MAX_DEC) return
setValue(`${intPart}.${decPart}${digit}`)
return
}
// 纯整数,且当前是 0
if (raw === '0') {
setValue(digit === '0' ? '0' : digit)
return
}
// 整数部分最多 4 位
if (raw.length >= MAX_INT) return
setValue(raw + digit)
}
function appendDot() {
if (inputValue.value.includes('.')) return
setValue(`${inputValue.value}.`)
}
function deleteOne() {
let raw = inputValue.value
if (!raw || raw === '0') {
setValue('0')
return
}
raw = raw.slice(0, -1)
// 如果删完后留下了末尾小数点,也一起去掉
if (raw.endsWith('.')) raw = raw.slice(0, -1)
if (!raw) raw = '0'
setValue(raw)
}
function stepChange(delta : number) {
let n = Number(inputValue.value || 0) + delta
if (Number.isNaN(n)) n = 0
// 限制最大值 9999.99,最小值 0
n = Math.min(MAX_VALUE, Math.max(0, Number(n.toFixed(2))))
setValue(String(n))
}
const clickKuai = (item : any) => {
if (props.pddType != '1') return
if (item === 'AC') {
deleteOne()
return
}
if (item === '.') {
appendDot()
return
}
if (item === 'AE') {
setValue(String(props.tb ?? 0))
return
}
appendDigit(Number(item))
}
const interoutId = ref<ReturnType<typeof setInterval> | null>(null)
let longPressTimer : ReturnType<typeof setTimeout> | null = null
let longPressed = false
const handleTouchStart = (e : number) => {
if (props.pddType != '1') return
longPressed = false
if (longPressTimer) {
clearTimeout(longPressTimer)
longPressTimer = null
}
longPressTimer = setTimeout(() => {
longPressTimer = null
longPressed = true
interoutId.value = setInterval(() => {
jjnum(e)
}, 120)
}, 800)
}
const handleTouchEnd = () => {
if (longPressTimer) {
clearTimeout(longPressTimer)
longPressTimer = null
return
}
if (longPressed) {
if (interoutId.value) {
clearInterval(interoutId.value)
interoutId.value = null
}
longPressed = false
}
}
const jjnum = (e : number) => {
if (props.pddType != '1') return
stepChange(e)
}
onBeforeUnmount(() => {
if (longPressTimer) {
clearTimeout(longPressTimer)
longPressTimer = null
}
if (interoutId.value) {
clearInterval(interoutId.value)
interoutId.value = null
}
})
</script>
<style scoped lang="less">
.jsuq {
width: 50vw;
display: flex;
height: 16vw;
justify-content: space-between;
// background-color: red;
margin-top: -1.5vw;
.rigsbt {
width: 25vw;
height: 100%;
margin-right: 1vw;
.calculator-father {
width: 23vw;
height: 90%;
margin: 0 auto 0;
flex-wrap: wrap;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
.calculator-kuai {
display: flex;
justify-content: center;
align-items: center;
// background-color: #F3F5F9;
background-size: 100% 100%;
font-size: 1.5vw;
font-weight: 500;
width: 4.2vw;
height: 4.2vw;
background: url('/static/index/procurement/bt.png') no-repeat;
background-size: 100% 100%;
border-radius: 25rpx;
}
.calculator-kuai:active {
background: linear-gradient(to bottom, #019cef, #0084fa);
color: #fff !important;
font-weight: 500;
display: flex;
justify-content: center;
align-items: center;
background-size: 100% 100%;
font-size: 1.5vw;
width: 4.2vw;
height: 4.2vw;
border-radius: 1.6vw;
}
.calculator-kuai-bad {
display: flex;
justify-content: center;
align-items: center;
background-color: #F3F5F9;
color: #999;
border-radius: 30rpx;
background-size: 100% 100%;
font-size: 1.5vw;
font-weight: 500;
width: 5vw;
height: 4vw;
opacity: 0.6;
}
}
}
.leftsa {
width: 21.8vw;
height: 80%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 0 1.5vw;
margin-left: 2.5vw;
.shu {
font-weight: 400;
font-size: 1.2vw;
color: #222222;
}
.stringShow-kuai {
display: flex;
align-items: center;
justify-content: end;
width: 18vw;
padding: 0 1vw;
height: 3.4vw;
background: #F3F5F9;
border-radius: 1vw;
// color: #999;
color: black;
border: 1px solid #CBCFD0;
// justify-content: space-around;
box-shadow: 0rpx 0.1vw 0.3vw 0rpx rgba(140, 143, 153, 0.17) inset;
opacity: 0.6;
view {
display: flex;
justify-content: center;
align-items: center;
font-size: 1.7vw;
font-weight: 500;
width: 2.4vw;
height: 3.4vw;
}
}
.stringShow-kuai-bad {
display: flex;
align-items: center;
justify-content: end;
width: 18vw;
height: 3.4vw;
background: #F3F5F9;
border-radius: 1vw;
color: #999;
border: 1px solid #CBCFD0;
padding: 0 1vw;
box-shadow: 0rpx 0.1vw 0.3vw 0rpx rgba(140, 143, 153, 0.17) inset;
opacity: 0.6;
view {
display: flex;
justify-content: center;
align-items: center;
font-size: 1.7vw;
font-weight: 500;
width: 2.4vw;
height: 3.4vw;
}
}
.jiajian {
display: flex;
justify-content: space-between;
align-items: center;
width: 18vw;
// flex-direction: column;
.jj-bad {
width: 4.2vw;
height: 4.2vw;
margin: 0 0.4vw;
display: flex;
justify-content: center;
align-items: center;
color: #999;
background: url('/static/index/procurement/bt.png') no-repeat;
background-size: 100% 100%;
border-radius: 25rpx;
font-size: 36rpx;
opacity: 0.6;
}
.jj {
width: 4.2vw;
height: 4.2vw;
margin: 0 1vw;
display: flex;
justify-content: center;
align-items: center;
background: url('/static/index/procurement/bt.png') no-repeat;
background-size: 100% 100%;
border-radius: 25rpx;
font-size: 36rpx;
}
.jj:active {
background: linear-gradient(to bottom, #00C9FF, #0076FF);
color: #fff;
display: flex;
justify-content: center;
align-items: center;
background-color: #DCDCEE;
font-weight: 500;
}
}
}
}
.kuai-margin {
margin: 20rpx 0;
}
</style>