JewelryMall/miniprogram/pages/calculator/index.vue
2026-03-05 00:43:04 +08:00

376 lines
12 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 class="calculator-page">
<!-- 自定义导航栏 -->
<view class="custom-navbar" :style="{ paddingTop: statusBarHeight + 'px' }">
<view class="custom-navbar__content" :style="{ height: navBarHeight + 'px' }">
<image class="custom-navbar__back" src="/static/ic_back.png" mode="aspectFit" @click="goBack" />
<text class="custom-navbar__title">金工石计算器</text>
<view class="custom-navbar__placeholder" />
</view>
</view>
<view :style="{ height: (statusBarHeight + navBarHeight) + 'px' }" />
<!-- 第1行净金重 = 金重 - 主石重×0.2 - 副石重×0.2 -->
<view class="calc-row calc-row--first">
<view class="calc-col">
<view class="field-row">
<text class="field-label">金重</text>
<input class="field-input" type="digit" v-model="row1.goldWeight" />
<text class="field-unit">g</text>
</view>
<view class="field-row">
<text class="field-label">主石量</text>
<input class="field-input" type="digit" v-model="row1.mainStoneWeight" />
<text class="field-unit">ct</text>
</view>
<view class="field-row">
<text class="field-label">副石重</text>
<input class="field-input" type="digit" v-model="row1.sideStoneWeight" />
<text class="field-unit">ct</text>
</view>
</view>
<view class="calc-col calc-col--result">
<view class="result-item">
<text class="result-label">净金重</text>
<text class="result-value">{{ res1 }}</text>
<text class="result-unit">克</text>
</view>
</view>
</view>
<!-- 第2行含耗重 = 净金重 × 损耗 -->
<view class="calc-row">
<view class="calc-col">
<view class="field-row">
<text class="field-label">净金重</text>
<input class="field-input" type="digit" v-model="row2.netGoldWeight" />
<text class="field-unit">g</text>
</view>
<view class="field-row">
<text class="field-label">损耗</text>
<input class="field-input" type="digit" v-model="row2.lossRate" />
<text class="field-unit">%</text>
</view>
</view>
<view class="calc-col calc-col--result">
<view class="result-item">
<text class="result-label">含耗重</text>
<text class="result-value">{{ res2 }}</text>
<text class="result-unit">克</text>
</view>
</view>
</view>
<!-- 第3行金值 = 含耗重 × 倒模金价 -->
<view class="calc-row">
<view class="calc-col">
<view class="field-row">
<text class="field-label">含耗重</text>
<input class="field-input" type="digit" v-model="row3.weightWithLoss" />
<text class="field-unit">g</text>
</view>
<view class="field-row">
<text class="field-label">倒模金价</text>
<input class="field-input" type="digit" v-model="row3.moldGoldPrice" />
<text class="field-unit">元</text>
</view>
</view>
<view class="calc-col calc-col--result">
<view class="result-item">
<text class="result-label">金值</text>
<text class="result-value">{{ res3 }}</text>
<text class="result-unit">元</text>
</view>
</view>
</view>
<!-- 第4行主石总价 = 主石重 × 主石单价 -->
<view class="calc-row">
<view class="calc-col">
<view class="field-row">
<text class="field-label">主石重</text>
<input class="field-input" type="digit" v-model="row4.mainStoneWeight" />
<text class="field-unit">ct</text>
</view>
<view class="field-row">
<text class="field-label">主石单价</text>
<input class="field-input" type="digit" v-model="row4.mainStoneUnitPrice" />
<text class="field-unit">元</text>
</view>
</view>
<view class="calc-col calc-col--result">
<view class="result-item">
<text class="result-label">主石总价</text>
<text class="result-value">{{ res4 }}</text>
<text class="result-unit">元</text>
</view>
</view>
</view>
<!-- 第5行副石总价 = 副石重 × 副石单价 -->
<view class="calc-row">
<view class="calc-col">
<view class="field-row">
<text class="field-label">副石重</text>
<input class="field-input" type="digit" v-model="row5.sideStoneWeight" />
<text class="field-unit">ct</text>
</view>
<view class="field-row">
<text class="field-label">副石单价</text>
<input class="field-input" type="digit" v-model="row5.sideStoneUnitPrice" />
<text class="field-unit">元</text>
</view>
</view>
<view class="calc-col calc-col--result">
<view class="result-item">
<text class="result-label">副石总价</text>
<text class="result-value">{{ res5 }}</text>
<text class="result-unit">元</text>
</view>
</view>
</view>
<!-- 第6行微镶总价 = 副石粒数 × 微镶费 -->
<view class="calc-row">
<view class="calc-col">
<view class="field-row">
<text class="field-label">副石粒数</text>
<input class="field-input" type="digit" v-model="row6.sideStoneCount" />
<text class="field-unit">p</text>
</view>
<view class="field-row">
<text class="field-label">微镶费</text>
<input class="field-input" type="digit" v-model="row6.microSettingFee" />
<text class="field-unit">元</text>
</view>
</view>
<view class="calc-col calc-col--result">
<view class="result-item">
<text class="result-label">微镶总价</text>
<text class="result-value">{{ res6 }}</text>
<text class="result-unit">元</text>
</view>
</view>
</view>
<!-- 第7行总价汇总 -->
<view class="calc-row calc-row--last">
<view class="calc-col">
<view class="field-row">
<text class="field-label">金值</text>
<input class="field-input" type="digit" v-model="row7.goldValue" />
<text class="field-unit">元</text>
</view>
<view class="field-row">
<text class="field-label">主石总价</text>
<input class="field-input" type="digit" v-model="row7.mainStoneTotal" />
<text class="field-unit">元</text>
</view>
<view class="field-row">
<text class="field-label">副石总价</text>
<input class="field-input" type="digit" v-model="row7.sideStoneTotal" />
<text class="field-unit">元</text>
</view>
<view class="field-row">
<text class="field-label">主石镶费</text>
<input class="field-input" type="digit" v-model="row7.mainStoneSettingFee" />
<text class="field-unit">元</text>
</view>
<view class="field-row">
<text class="field-label">微镶总价</text>
<input class="field-input" type="digit" v-model="row7.microSettingTotal" />
<text class="field-unit">元</text>
</view>
<view class="field-row">
<text class="field-label">3D起版费</text>
<input class="field-input" type="digit" v-model="row7.threeDFee" />
<text class="field-unit">元</text>
</view>
<view class="field-row">
<text class="field-label">基本工费</text>
<input class="field-input" type="digit" v-model="row7.basicLaborCost" />
<text class="field-unit">元</text>
</view>
<view class="field-row">
<text class="field-label">其他费用</text>
<input class="field-input" type="digit" v-model="row7.otherCost" />
<text class="field-unit">元</text>
</view>
</view>
<view class="calc-col calc-col--result">
<view class="result-item result-item--total">
<text class="result-label">总价</text>
<text class="result-value result-value--total">{{ res7 }}</text>
<text class="result-unit">元</text>
</view>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import { ref, reactive, computed } from 'vue'
const statusBarHeight = ref(20)
const navBarHeight = ref(44)
try {
const sysInfo = uni.getSystemInfoSync()
statusBarHeight.value = sysInfo.statusBarHeight || 20
// #ifdef MP-WEIXIN
const menuBtn = uni.getMenuButtonBoundingClientRect()
navBarHeight.value = (menuBtn.top - (sysInfo.statusBarHeight || 20)) * 2 + menuBtn.height
// #endif
} catch { /* fallback */ }
function goBack() {
uni.navigateBack({ delta: 1 })
}
function n(v: string | number): number {
const num = Number(v)
return isNaN(num) ? 0 : num
}
function fmt(v: number): string {
return v.toFixed(2)
}
// 每行独立的输入数据
const row1 = reactive({ goldWeight: '0', mainStoneWeight: '0', sideStoneWeight: '0' })
const row2 = reactive({ netGoldWeight: '0', lossRate: '0' })
const row3 = reactive({ weightWithLoss: '0', moldGoldPrice: '0' })
const row4 = reactive({ mainStoneWeight: '0', mainStoneUnitPrice: '0' })
const row5 = reactive({ sideStoneWeight: '0', sideStoneUnitPrice: '0' })
const row6 = reactive({ sideStoneCount: '0', microSettingFee: '3.5' })
const row7 = reactive({
goldValue: '0', mainStoneTotal: '0', sideStoneTotal: '0',
mainStoneSettingFee: '0', microSettingTotal: '0',
threeDFee: '0', basicLaborCost: '0', otherCost: '0',
})
// 公式1: 净金重 = 金重 - 主石重×0.2 - 副石重×0.2
const res1 = computed(() => fmt(n(row1.goldWeight) - n(row1.mainStoneWeight) * 0.2 - n(row1.sideStoneWeight) * 0.2))
// 公式2: 含耗重 = 净金重 × 损耗
const res2 = computed(() => fmt(n(row2.netGoldWeight) * n(row2.lossRate)))
// 公式3: 金值 = 含耗重 × 倒模金价
const res3 = computed(() => fmt(n(row3.weightWithLoss) * n(row3.moldGoldPrice)))
// 公式4: 主石总价 = 主石重 × 主石单价
const res4 = computed(() => fmt(n(row4.mainStoneWeight) * n(row4.mainStoneUnitPrice)))
// 公式5: 副石总价 = 副石重 × 副石单价
const res5 = computed(() => fmt(n(row5.sideStoneWeight) * n(row5.sideStoneUnitPrice)))
// 公式6: 微镶总价 = 副石粒数 × 微镶费
const res6 = computed(() => fmt(n(row6.sideStoneCount) * n(row6.microSettingFee)))
// 公式7: 总价 = 金值 + 主石总价 + 副石总价 + 主石镶费 + 微镶总价 + 3D起版费 + 基本工费 + 其他费用
const res7 = computed(() => fmt(
n(row7.goldValue) + n(row7.mainStoneTotal) + n(row7.sideStoneTotal)
+ n(row7.mainStoneSettingFee) + n(row7.microSettingTotal)
+ n(row7.threeDFee) + n(row7.basicLaborCost) + n(row7.otherCost)
))
</script>
<style scoped>
.calculator-page {
min-height: 100vh;
background: #f5f5f5;
}
.custom-navbar {
background: linear-gradient(to right, #FFCFDE, #FFA6C4);
position: fixed; top: 0; left: 0; right: 0; z-index: 100;
}
.custom-navbar__content {
display: flex; align-items: center; padding: 0 24rpx;
}
.custom-navbar__back { width: 44rpx; height: 44rpx; }
.custom-navbar__title {
flex: 1; text-align: center; font-size: 34rpx; font-weight: bold; color: #333;
}
.custom-navbar__placeholder { width: 44rpx; }
.calc-row {
display: flex;
background: #fff;
margin: 0 24rpx;
border-bottom: 1rpx solid #f0f0f0;
}
.calc-row--first {
margin-top: 16rpx;
border-radius: 16rpx 16rpx 0 0;
}
.calc-row--last {
border-radius: 0 0 16rpx 16rpx;
border-bottom: none;
margin-bottom: 32rpx;
}
.calc-col {
flex: 1;
padding: 20rpx 24rpx;
}
.calc-col--result {
flex: 0 0 260rpx;
display: flex;
align-items: center;
justify-content: center;
border-left: 1rpx solid #f0f0f0;
}
.field-row {
display: flex;
align-items: center;
padding: 12rpx 0;
}
.field-label {
font-size: 26rpx;
color: #333;
width: 140rpx;
flex-shrink: 0;
font-weight: 500;
}
.field-input {
flex: 1;
height: 56rpx;
background: #fff5f8;
border: none;
border-radius: 8rpx;
padding: 0 16rpx;
font-size: 28rpx;
color: #e91e63;
text-align: center;
font-weight: 600;
}
.field-unit {
font-size: 24rpx;
color: #999;
margin-left: 8rpx;
width: 40rpx;
flex-shrink: 0;
}
.result-item {
text-align: center;
}
.result-label {
font-size: 24rpx;
color: #999;
display: block;
margin-bottom: 8rpx;
}
.result-value {
font-size: 36rpx;
color: #e91e63;
font-weight: 700;
display: block;
}
.result-value--total {
font-size: 44rpx;
}
.result-unit {
font-size: 22rpx;
color: #999;
margin-left: 4rpx;
}
</style>