hldy_app_mini/pages/material/component/calculator.vue

328 lines
6.7 KiB
Vue

<template>
<view class="plsbuy-contain">
<view class="title">
<view></view>
修改价格
</view>
<view class="calculator-father">
<view v-for="(item, index) in calculatorArray" :key="index">
<view :class="blueNumber == index ? 'calculator-kuai-target' : 'calculator-kuai'"
@click="clickKuai(item, index)">
<image v-if="item === 'AC'" src="/static/cleanone.png" mode="aspectFill"
style="width: 50%; height: 50%;" />
<text v-else>{{ item }}</text>
</view>
</view>
</view>
<view class="qinggou-font">
销售价格
</view>
<view class="stringShow-father">
<view v-for="(item, index) in stringShow" :key="index">
<view class="stringShow-kuai">
{{ item }}
</view>
</view>
</view>
<view class="plsbuy-bottom">
<view class="quxiao" @click="colse">取消</view>
<view class="plsbuy-bottom-blue" @click="closeIt">确认</view>
</view>
</view>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue'
const emit = defineEmits(['right','close'])
const props = defineProps({
// doOnce: {
// type: Number,
// required: true,
// },
translateNumber: {
type: Number,
required: true,
},
})
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 blueNumber = ref(-1)
// 实际输入值:字符串保存,避免小数精度问题
const inputValue = ref('0')
// 显示值:固定显示 4 位整数 + 2 位小数
const stringShow = ref('0000.00')
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)
}
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 clickKuai(item : any, index : number) {
blueNumber.value = index
setTimeout(() => {
blueNumber.value = -1
}, 300)
if (item === 'AC') {
deleteOne()
return
}
if (item === '.') {
appendDot()
return
}
appendDigit(Number(item))
}
function closeIt() {
emit('right', Number(inputValue.value || 0))
}
function colse() {
// 如果父组件需要关闭事件,可以改成:
emit('close')
}
// 初始回显 / 外部刷新
// watch(
// () => props.doOnce,
// () => {
// setValue(String(props.translateNumber ?? 0))
// },
// { immediate: true }
// )
// translateNumber 变化时同步
watch(
() => props.translateNumber,
() => {
setValue(String(props.translateNumber ?? 0))
}
)
</script>
<style lang="less" scoped>
.plsbuy-contain {
display: flex;
align-items: center;
flex-direction: column;
width: 100%;
height: 100%;
background: rgba(250, 251, 252, 1);
overflow: hidden;
border-radius: 2.2vw;
.title {
font-size: 1.7vw;
color: #222222;
display: flex;
width: 100%;
margin-top: 40rpx;
margin-left: 100rpx;
align-items: center;
view {
width: 0.5vw;
height: 1.4vw;
background: radial-gradient(0% 0% at 0% 0%, #006DC9 7.25%, #0385FA 100%), #F7F7F7;
border-radius: 0.2vw;
margin-right: 1vw;
}
}
}
.plsbuy-bottom {
width: 70%;
margin-top: 50rpx;
height: 70rpx;
display: flex;
justify-content: space-around;
font-size: 35rpx;
margin-left: 5%;
view {
display: flex;
justify-content: center;
align-items: center;
width: 180rpx;
height: 70rpx;
color: rgba(92, 121, 146, 1);
border-radius: 35rpx;
font-size: 30rpx;
border: 1px solid #A2B4CF;
}
.quxiao {
background: #FFFFFF;
}
.plsbuy-bottom-blue {
background: linear-gradient(-61deg, #EAF5FF, #CBE7FF);
}
}
.calculator-father {
width: 420rpx;
height: 500rpx;
margin-top: 20rpx;
flex-wrap: wrap;
display: flex;
.calculator-kuai {
display: flex;
justify-content: center;
align-items: center;
background: url('/static/index/warehouse/procurement/bt.png') no-repeat;
background-size: 100% 100%;
border-radius: 25rpx;
font-size: 42rpx;
font-weight: 500;
margin: 15rpx 20rpx 0 20rpx;
width: 100rpx;
height: 100rpx;
}
.calculator-kuai-target {
background: linear-gradient(to bottom, #00C9FF, #0076FF);
color: #fff;
display: flex;
justify-content: center;
align-items: center;
background-color: #DCDCEE;
border-radius: 25rpx;
font-size: 45rpx;
font-weight: 500;
margin: 15rpx 20rpx 0 20rpx;
width: 100rpx;
height: 100rpx;
}
}
.stringShow-father {
width: 630rpx;
height: 70rpx;
margin-top: 20rpx;
// margin-left: 23rpx;
// flex-wrap: wrap;
display: flex;
.stringShow-kuai {
display: flex;
justify-content: center;
align-items: center;
// background-color: #DCDCEE;
border-radius: 25rpx;
// border-radius: 15rpx;
font-size: 42rpx;
font-weight: 500;
margin: 0 10rpx;
width: 70rpx;
height: 70rpx;
border: 2rpx solid rgba(203, 207, 208, 1);
}
}
.qinggou-font {
font-size: 27rpx;
font-weight: 500;
margin-top: 30rpx;
}
</style>