hldy_app_mini/pages/material/component/torytor.vue

474 lines
9.9 KiB
Vue
Raw Normal View History

2026-04-20 08:57:36 +08:00
<template>
<view>
<view class="jsuq guodu">
2026-04-20 08:57:36 +08:00
<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}}
2026-04-20 08:57:36 +08:00
</view>
</view>
<view class="jiajian">
<view :class="pddType!='3'? `jj`:`jj-bad`" @click="jjnum(-1)" @touchstart="handleTouchStart(-1)"
@touchend="handleTouchEnd">
-
2026-04-20 08:57:36 +08:00
</view>
<view :class="pddType!='3'? `jj`:`jj-bad`" @click="jjnum(1)" @touchstart="handleTouchStart(1)"
@touchend="handleTouchEnd">
2026-04-20 08:57:36 +08:00
+
</view>
</view>
2026-04-20 08:57:36 +08:00
</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)">
2026-04-20 08:57:36 +08:00
<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
2026-04-20 08:57:36 +08:00
@click="clickKuai(item,index)">
{{item}}
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import { ref, watch, onBeforeUnmount } from 'vue'
2026-04-20 08:57:36 +08:00
const props = defineProps({
show: {
type: Boolean
},
tb: {
type: Number
},
idex: {
type: Number
},
pdsl: {
type: [Number, String]
2026-04-20 08:57:36 +08:00
},
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,
2026-04-20 08:57:36 +08:00
() => {
if (props.show) {
setValue(String(props.pdsl ?? 0))
2026-04-20 08:57:36 +08:00
isZero.value = false
} else {
setValue('0')
2026-04-20 08:57:36 +08:00
}
},
{ 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')
2026-04-20 08:57:36 +08:00
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()
2026-04-20 08:57:36 +08:00
return
}
if (item === '.') {
appendDot()
2026-04-20 08:57:36 +08:00
return
}
if (item === 'AE') {
setValue(String(props.tb ?? 0))
return
2026-04-20 08:57:36 +08:00
}
appendDigit(Number(item))
2026-04-20 08:57:36 +08:00
}
const interoutId = ref<ReturnType<typeof setInterval> | null>(null)
let longPressTimer : ReturnType<typeof setTimeout> | null = null
let longPressed = false
2026-04-20 08:57:36 +08:00
const handleTouchStart = (e : number) => {
if (props.pddType != '1') return
longPressed = false
2026-04-20 08:57:36 +08:00
if (longPressTimer) {
clearTimeout(longPressTimer)
longPressTimer = null
2026-04-20 08:57:36 +08:00
}
2026-04-20 08:57:36 +08:00
longPressTimer = setTimeout(() => {
longPressTimer = null
longPressed = true
interoutId.value = setInterval(() => {
jjnum(e)
}, 120)
}, 800)
2026-04-20 08:57:36 +08:00
}
2026-04-20 08:57:36 +08:00
const handleTouchEnd = () => {
if (longPressTimer) {
clearTimeout(longPressTimer)
longPressTimer = null
return
2026-04-20 08:57:36 +08:00
}
if (longPressed) {
if (interoutId.value) {
clearInterval(interoutId.value)
interoutId.value = null
}
longPressed = false
2026-04-20 08:57:36 +08:00
}
}
2026-04-20 08:57:36 +08:00
const jjnum = (e : number) => {
if (props.pddType != '1') return
stepChange(e)
2026-04-20 08:57:36 +08:00
}
onBeforeUnmount(() => {
if (longPressTimer) {
clearTimeout(longPressTimer)
longPressTimer = null
}
if (interoutId.value) {
clearInterval(interoutId.value)
interoutId.value = null
}
})
2026-04-20 08:57:36 +08:00
</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 {
2026-04-29 17:30:41 +08:00
width: 20vw;
2026-04-20 08:57:36 +08:00
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 {
2026-04-20 08:57:36 +08:00
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;
2026-04-20 08:57:36 +08:00
height: 3.4vw;
background: #F3F5F9;
border-radius: 1vw;
// color: #999;
color: black;
border: 1px solid #CBCFD0;
// justify-content: space-around;
2026-04-20 08:57:36 +08:00
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;
2026-04-20 08:57:36 +08:00
height: 3.4vw;
}
}
2026-04-20 08:57:36 +08:00
.stringShow-kuai-bad {
display: flex;
align-items: center;
justify-content: end;
width: 18vw;
2026-04-20 08:57:36 +08:00
height: 3.4vw;
background: #F3F5F9;
border-radius: 1vw;
color: #999;
border: 1px solid #CBCFD0;
padding: 0 1vw;
2026-04-20 08:57:36 +08:00
box-shadow: 0rpx 0.1vw 0.3vw 0rpx rgba(140, 143, 153, 0.17) inset;
opacity: 0.6;
2026-04-20 08:57:36 +08:00
view {
display: flex;
justify-content: center;
align-items: center;
font-size: 1.7vw;
font-weight: 500;
width: 2.4vw;
2026-04-20 08:57:36 +08:00
height: 3.4vw;
}
}
2026-04-20 08:57:36 +08:00
.jiajian {
display: flex;
justify-content: space-between;
align-items: center;
width: 18vw;
// flex-direction: column;
.jj-bad {
2026-04-20 08:57:36 +08:00
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;
}
2026-04-20 08:57:36 +08:00
</style>