修改带单位的输入框组件,解决转换精度问题。
This commit is contained in:
parent
c7b4db67bf
commit
a57f1d6b6d
44
api/system/sysUnitConvert.js
Normal file
44
api/system/sysUnitConvert.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 查询单位换算列表
|
||||||
|
export function listSysUnitConvert(query) {
|
||||||
|
return request({
|
||||||
|
url: '/system/sysUnitConvert/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询单位换算详细
|
||||||
|
export function getSysUnitConvert(id) {
|
||||||
|
return request({
|
||||||
|
url: '/system/sysUnitConvert/' + id,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增单位换算
|
||||||
|
export function addSysUnitConvert(data) {
|
||||||
|
return request({
|
||||||
|
url: '/system/sysUnitConvert',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改单位换算
|
||||||
|
export function updateSysUnitConvert(data) {
|
||||||
|
return request({
|
||||||
|
url: '/system/sysUnitConvert',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除单位换算
|
||||||
|
export function delSysUnitConvert(id) {
|
||||||
|
return request({
|
||||||
|
url: '/system/sysUnitConvert/' + id,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
105
pages/index.vue
105
pages/index.vue
@ -1,43 +1,84 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="content">
|
<view class="content">
|
||||||
<image class="logo" src="@/static/logo.png"></image>
|
<image class="logo" src="@/static/logo.png"></image>
|
||||||
<view class="text-area">
|
{{ 'initialValue' + initialValue }}
|
||||||
<text class="title">Hello RuoYi</text>
|
{{ 'newValue' + newValue }}
|
||||||
</view>
|
{{ 'oldUnit' + oldUnit }}
|
||||||
</view>
|
{{ 'newUnit' + newUnit }}
|
||||||
|
{{ 'oldOrder' + oldOrder }}
|
||||||
|
{{ 'newOrder' + newOrder }}
|
||||||
|
|
||||||
|
<view class="text-area">
|
||||||
|
<yjly-inputunit
|
||||||
|
v-model="mylength"
|
||||||
|
:unit-type="'length'"
|
||||||
|
:unit-order.sync="myunitname"
|
||||||
|
:show-english-only="false"
|
||||||
|
:decimal-places="5"
|
||||||
|
:width="200"
|
||||||
|
:style="{ width: 200 + 'px' }"
|
||||||
|
@conversion="onchange"
|
||||||
|
></yjly-inputunit>
|
||||||
|
|
||||||
|
<text class="title">Hello RuoYi</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
onLoad: function() {
|
onLoad: function () {},
|
||||||
}
|
data() {
|
||||||
}
|
return {
|
||||||
|
mylength: 10,
|
||||||
|
myunitname: 1,
|
||||||
|
|
||||||
|
initialValue: 0,
|
||||||
|
newValue: 0,
|
||||||
|
oldUnit: '',
|
||||||
|
newUnit: '',
|
||||||
|
oldOrder: 0,
|
||||||
|
newOrder: 0
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
onchange(e) {
|
||||||
|
this.initialValue = e.initialValue;
|
||||||
|
this.newValue = e.newValue;
|
||||||
|
this.oldUnit = e.oldUnit;
|
||||||
|
this.newUnit = e.newUnit;
|
||||||
|
this.oldOrder = e.oldOrder;
|
||||||
|
this.newOrder = e.newOrder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.content {
|
.content {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
height: 200rpx;
|
height: 200rpx;
|
||||||
width: 200rpx;
|
width: 200rpx;
|
||||||
margin-top: 200rpx;
|
margin-top: 200rpx;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
margin-bottom: 50rpx;
|
margin-bottom: 50rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-area {
|
.text-area {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-size: 36rpx;
|
font-size: 36rpx;
|
||||||
color: #8f8f94;
|
color: #8f8f94;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
6
uni_modules/yjly-inputunit/changelog.md
Normal file
6
uni_modules/yjly-inputunit/changelog.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
## 1.0.2(2025-02-19)
|
||||||
|
修改单位转换精度,将原始单位和值暂存,换算到基准单位值,再换算到新单位值。
|
||||||
|
## 1.0.1(2025-02-15)
|
||||||
|
修改单位类型默认值
|
||||||
|
## 1.0.0(2025-02-15)
|
||||||
|
1.0.0
|
@ -0,0 +1,430 @@
|
|||||||
|
<template>
|
||||||
|
<view class="unit-converter" :style="{ width: width + 'px' }">
|
||||||
|
<!-- 数值输入框 -->
|
||||||
|
<input
|
||||||
|
v-model.number="inputValue"
|
||||||
|
class="input-field"
|
||||||
|
type="number"
|
||||||
|
:ref="'inputRef'"
|
||||||
|
:style="{
|
||||||
|
width: inputWidth + 'px',
|
||||||
|
height: height + 'px',
|
||||||
|
lineHeight: height + 'px'
|
||||||
|
}"
|
||||||
|
@input="handleInputChange"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 单位标签 -->
|
||||||
|
<view
|
||||||
|
v-if="enableConvert"
|
||||||
|
:ref="'unitLabel'"
|
||||||
|
class="unit-label"
|
||||||
|
:style="{
|
||||||
|
color: 'blue',
|
||||||
|
height: height + 'px',
|
||||||
|
lineHeight: height + 'px'
|
||||||
|
}"
|
||||||
|
@tap="cycleUnit"
|
||||||
|
@longpress="handleLongPress"
|
||||||
|
>
|
||||||
|
{{ textUnitName }}
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
v-else
|
||||||
|
class="unit-label"
|
||||||
|
:style="{
|
||||||
|
color: 'blue',
|
||||||
|
height: height + 'px',
|
||||||
|
lineHeight: height + 'px'
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ textUnitName }}
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 单位选择弹出窗口 -->
|
||||||
|
<view
|
||||||
|
v-if="showUnitSelector"
|
||||||
|
class="unit-selector"
|
||||||
|
:style="{
|
||||||
|
left: unitSelectorLeft + 'px',
|
||||||
|
top: unitSelectorTop + 'px'
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<scroll-view scroll-y :style="{ maxHeight: '200px' }">
|
||||||
|
<view v-for="unit in sortedUnits" :key="unit.id" class="unit-option" @tap="selectUnit(unit)">
|
||||||
|
{{ showEnglishOnly ? unit.unitName.split('(')[0] : unit.unitName }}
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// 兼容 Vue2/Vue3 的写法
|
||||||
|
import unitDatalist from './yjlyUnitData';
|
||||||
|
export default {
|
||||||
|
name: 'UniUnitConverter',
|
||||||
|
emits: ['input', 'update:unitOrder', 'conversion'],
|
||||||
|
props: {
|
||||||
|
unitType: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
default: 'length'
|
||||||
|
},
|
||||||
|
unitOrder: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
showEnglishOnly: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
decimalPlaces: {
|
||||||
|
type: Number,
|
||||||
|
default: 5,
|
||||||
|
validator: (v) => v >= 0 && v <= 10
|
||||||
|
},
|
||||||
|
width: {
|
||||||
|
type: Number,
|
||||||
|
default: 180
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: Number,
|
||||||
|
default: 32
|
||||||
|
},
|
||||||
|
enableConvert: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
userDefined: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
userDefinedunitName: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
inputValue: this.value,
|
||||||
|
unitData: [],
|
||||||
|
showUnitSelector: false,
|
||||||
|
currentUnit: null,
|
||||||
|
baseUnit: null,
|
||||||
|
inputWidth: 100,
|
||||||
|
textUnitName: '',
|
||||||
|
unitSelectorLeft: 0,
|
||||||
|
unitSelectorTop: 0,
|
||||||
|
|
||||||
|
/* 新增三个数据项 */
|
||||||
|
originalValue: this.value, // 原始输入值
|
||||||
|
originalUnit: null, // 原始输入单位
|
||||||
|
isInternalUpdate: false // 更新锁定标志
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.initComponent();
|
||||||
|
this.setGlobalClickHandler();
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
this.removeGlobalClickHandler();
|
||||||
|
unitOrder;
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
sortedUnits() {
|
||||||
|
return this.unitData.filter((u) => u.unitType === this.unitType).sort((a, b) => a.unitOrder - b.unitOrder);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
unitType: {
|
||||||
|
immediate: true,
|
||||||
|
async handler(newType) {
|
||||||
|
if (this.userDefined) {
|
||||||
|
this.textUnitName = this.userDefinedunitName;
|
||||||
|
this.$nextTick(() => this.updateInputWidth());
|
||||||
|
} else {
|
||||||
|
await this.loadUnits(newType);
|
||||||
|
this.initCurrentUnit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
unitOrder(newOrder) {
|
||||||
|
if (this.userDefined) {
|
||||||
|
this.textUnitName = this.userDefinedunitName;
|
||||||
|
this.$nextTick(() => this.updateInputWidth());
|
||||||
|
} else {
|
||||||
|
const target = this.sortedUnits.find((u) => u.unitOrder === newOrder);
|
||||||
|
if (target) {
|
||||||
|
this.currentUnit = target;
|
||||||
|
this.textUnitName = this.showEnglishOnly ? target.unitName.split('(')[0].trim() : target.unitName;
|
||||||
|
this.$nextTick(() => this.updateInputWidth());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value(newVal) {
|
||||||
|
if (!this.isInternalUpdate) {
|
||||||
|
// 外部更新时重置原始值
|
||||||
|
this.originalValue = newVal;
|
||||||
|
this.originalUnit = this.currentUnit;
|
||||||
|
this.inputValue = newVal;
|
||||||
|
}
|
||||||
|
this.isInternalUpdate = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async initComponent() {
|
||||||
|
await this.$nextTick();
|
||||||
|
this.updateInputWidth();
|
||||||
|
},
|
||||||
|
|
||||||
|
setGlobalClickHandler() {
|
||||||
|
if (typeof document !== 'undefined') {
|
||||||
|
document.addEventListener('click', this.handleClickOutside);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
removeGlobalClickHandler() {
|
||||||
|
if (typeof document !== 'undefined') {
|
||||||
|
document.removeEventListener('click', this.handleClickOutside);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleClickOutside(event) {
|
||||||
|
if (!this.showUnitSelector) return;
|
||||||
|
|
||||||
|
const selector = this.$refs.unitSelector;
|
||||||
|
if (!selector) return;
|
||||||
|
|
||||||
|
const isOutside = !selector.$el.contains(event.target);
|
||||||
|
if (isOutside) {
|
||||||
|
this.showUnitSelector = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async loadUnits(unitType) {
|
||||||
|
try {
|
||||||
|
// 后台的API可自行开发,这里提供了js数据格式
|
||||||
|
// const res = await listSysUnitConvert({ unitType: unitType, status: 'Y' });
|
||||||
|
// this.unitData = res.rows;
|
||||||
|
this.unitData = unitDatalist[unitType];
|
||||||
|
console.log(this.unitData);
|
||||||
|
this.baseUnit = this.unitData.find((u) => u.baseUnit === 'Y');
|
||||||
|
console.log(this.baseUnit);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('单位数据加载失败:', e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/* 初始化当前单位补充 */
|
||||||
|
initCurrentUnit() {
|
||||||
|
const target = this.sortedUnits.find((u) => u.unitOrder === this.unitOrder);
|
||||||
|
this.currentUnit = target || this.baseUnit || this.sortedUnits[0];
|
||||||
|
// 初始化原始单位
|
||||||
|
this.originalUnit = this.currentUnit;
|
||||||
|
this.textUnitName = this.showEnglishOnly ? this.currentUnit.unitName.split('(')[0].trim() : this.currentUnit.unitName;
|
||||||
|
this.$nextTick(() => this.updateInputWidth());
|
||||||
|
},
|
||||||
|
|
||||||
|
updateInputWidth() {
|
||||||
|
const query = uni.createSelectorQuery().in(this);
|
||||||
|
query
|
||||||
|
.select('.unit-label')
|
||||||
|
.boundingClientRect((res) => {
|
||||||
|
if (res) {
|
||||||
|
this.inputWidth = this.width - res.width - 4;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.exec();
|
||||||
|
},
|
||||||
|
|
||||||
|
handleLongPress() {
|
||||||
|
this.toggleUnitSelector();
|
||||||
|
this.positionUnitSelector();
|
||||||
|
},
|
||||||
|
|
||||||
|
positionUnitSelector() {
|
||||||
|
const query = uni.createSelectorQuery().in(this);
|
||||||
|
query
|
||||||
|
.select('.unit-label')
|
||||||
|
.boundingClientRect((res) => {
|
||||||
|
if (res) {
|
||||||
|
this.unitSelectorLeft = res.left;
|
||||||
|
this.unitSelectorTop = res.bottom + 5;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.exec();
|
||||||
|
},
|
||||||
|
|
||||||
|
/* 修改单位切换方法 */
|
||||||
|
cycleUnit() {
|
||||||
|
const index = this.sortedUnits.findIndex((u) => u === this.currentUnit);
|
||||||
|
const newUnit = this.sortedUnits[(index + 1) % this.sortedUnits.length];
|
||||||
|
this.currentUnit = newUnit;
|
||||||
|
this.textUnitName = this.showEnglishOnly ? newUnit.unitName.split('(')[0].trim() : newUnit.unitName;
|
||||||
|
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.updateInputWidth();
|
||||||
|
this.convertAndEmit();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleUnitSelector() {
|
||||||
|
this.showUnitSelector = !this.showUnitSelector;
|
||||||
|
if (this.showUnitSelector) {
|
||||||
|
this.positionUnitSelector();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/* 修改单位选择方法 */
|
||||||
|
selectUnit(unit) {
|
||||||
|
this.currentUnit = unit;
|
||||||
|
this.showUnitSelector = false;
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.updateInputWidth();
|
||||||
|
this.convertAndEmit();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/* 修改输入处理 */
|
||||||
|
handleInputChange() {
|
||||||
|
// 记录原始值和单位
|
||||||
|
this.originalValue = this.inputValue;
|
||||||
|
this.originalUnit = this.currentUnit;
|
||||||
|
this.$emit('input', this.inputValue);
|
||||||
|
},
|
||||||
|
|
||||||
|
/* 优化后的转换方法 */
|
||||||
|
convertAndEmit() {
|
||||||
|
if (!this.currentUnit || !this.baseUnit || !this.originalUnit) return;
|
||||||
|
|
||||||
|
let newValue = 0;
|
||||||
|
if (this.unitType === 'temperature') {
|
||||||
|
newValue = this.handleTemperatureConversion();
|
||||||
|
} else {
|
||||||
|
// 通过基准单位进行两次精确转换
|
||||||
|
const baseValue = this.originalValue / this.originalUnit.conversionFactor;
|
||||||
|
newValue = baseValue * this.currentUnit.conversionFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
const roundedValue = this.roundValue(newValue);
|
||||||
|
this.isInternalUpdate = true; // 锁定更新
|
||||||
|
this.inputValue = roundedValue;
|
||||||
|
this.$emit('input', roundedValue);
|
||||||
|
this.$emit('update:unitOrder', this.currentUnit.unitOrder);
|
||||||
|
|
||||||
|
this.$emit('conversion', {
|
||||||
|
initialValue: this.originalValue,
|
||||||
|
newValue: roundedValue,
|
||||||
|
oldUnit: this.originalUnit.unitName,
|
||||||
|
newUnit: this.currentUnit.unitName,
|
||||||
|
oldOrder: this.originalUnit.unitOrder,
|
||||||
|
newOrder: this.currentUnit.unitOrder
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/* 优化温度转换方法 */
|
||||||
|
handleTemperatureConversion() {
|
||||||
|
const oldUnit = this.originalUnit;
|
||||||
|
const newUnit = this.currentUnit;
|
||||||
|
const oldOrder = oldUnit.unitOrder;
|
||||||
|
const newOrder = newUnit.unitOrder;
|
||||||
|
|
||||||
|
// 使用原始值计算
|
||||||
|
let celsius;
|
||||||
|
switch (oldOrder) {
|
||||||
|
case 0:
|
||||||
|
celsius = this.originalValue;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
celsius = ((this.originalValue - 32) * 5) / 9;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
celsius = this.originalValue - 273.15;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error('无效温度单位');
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (newOrder) {
|
||||||
|
case 0:
|
||||||
|
return celsius;
|
||||||
|
case 1:
|
||||||
|
return (celsius * 9) / 5 + 32;
|
||||||
|
case 2:
|
||||||
|
return celsius + 273.15;
|
||||||
|
default:
|
||||||
|
throw new Error('无效温度单位');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 四舍六入五成双
|
||||||
|
roundValue(value) {
|
||||||
|
const multiplier = Math.pow(10, this.decimalPlaces);
|
||||||
|
const val = value * multiplier;
|
||||||
|
const intVal = Math.trunc(val);
|
||||||
|
const decimalPart = val - intVal;
|
||||||
|
if (decimalPart < 0.5) {
|
||||||
|
return intVal / multiplier;
|
||||||
|
} else if (decimalPart > 0.5) {
|
||||||
|
return (intVal + 1) / multiplier;
|
||||||
|
} else {
|
||||||
|
return intVal % 2 === 0 ? intVal / multiplier : (intVal + 1) / multiplier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.unit-converter {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-field {
|
||||||
|
border: 1px solid #d6d5d5;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unit-label {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 10px;
|
||||||
|
border: 1px solid #d6d5d5;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
white-space: nowrap;
|
||||||
|
margin-left: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unit-selector {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 9999;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border: 1px solid #cccccc;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
min-width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unit-option {
|
||||||
|
padding: 8px 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unit-option:hover {
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
scroll-view {
|
||||||
|
max-height: 200px;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,122 @@
|
|||||||
|
const unitData = {
|
||||||
|
pressure: [{
|
||||||
|
|
||||||
|
"id": 66,
|
||||||
|
"unitType": "pressure",
|
||||||
|
"unitName": "Pa(帕斯卡)",
|
||||||
|
"baseUnit": "Y",
|
||||||
|
"conversionFactor": 1,
|
||||||
|
"unitTypeName": "压力",
|
||||||
|
"status": "Y",
|
||||||
|
"unitOrder": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
|
||||||
|
"id": 67,
|
||||||
|
"unitType": "pressure",
|
||||||
|
"unitName": "kPa(千帕)",
|
||||||
|
"baseUnit": "N",
|
||||||
|
"conversionFactor": 0.001,
|
||||||
|
"unitTypeName": "压力",
|
||||||
|
"status": "Y",
|
||||||
|
"unitOrder": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
|
||||||
|
"id": 68,
|
||||||
|
"unitType": "pressure",
|
||||||
|
"unitName": "MPa(兆帕)",
|
||||||
|
"baseUnit": "N",
|
||||||
|
"conversionFactor": 0.000001,
|
||||||
|
"unitTypeName": "压力",
|
||||||
|
"status": "Y",
|
||||||
|
"unitOrder": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
|
||||||
|
"id": 69,
|
||||||
|
"unitType": "pressure",
|
||||||
|
"unitName": "atm(标准大气压)",
|
||||||
|
"baseUnit": "N",
|
||||||
|
"conversionFactor": 0.0000098692326671601,
|
||||||
|
"unitTypeName": "压力",
|
||||||
|
"status": "Y",
|
||||||
|
"unitOrder": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
|
||||||
|
"id": 70,
|
||||||
|
"unitType": "pressure",
|
||||||
|
"unitName": "bar(巴)",
|
||||||
|
"baseUnit": "N",
|
||||||
|
"conversionFactor": 0.00001,
|
||||||
|
"unitTypeName": "压力",
|
||||||
|
"status": "Y",
|
||||||
|
"unitOrder": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
|
||||||
|
"id": 71,
|
||||||
|
"unitType": "pressure",
|
||||||
|
"unitName": "mbar(毫巴)",
|
||||||
|
"baseUnit": "N",
|
||||||
|
"conversionFactor": 0.01,
|
||||||
|
"unitTypeName": "压力",
|
||||||
|
"status": "Y",
|
||||||
|
"unitOrder": 5
|
||||||
|
}
|
||||||
|
],
|
||||||
|
length: [{
|
||||||
|
"id": 1,
|
||||||
|
"unitType": "length",
|
||||||
|
"unitName": "m(米)",
|
||||||
|
"baseUnit": "Y",
|
||||||
|
"conversionFactor": 1,
|
||||||
|
"unitTypeName": "长度",
|
||||||
|
"status": "Y",
|
||||||
|
"unitOrder": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"unitType": "length",
|
||||||
|
"unitName": "dm(分米)",
|
||||||
|
"baseUnit": "N",
|
||||||
|
"conversionFactor": 10,
|
||||||
|
"unitTypeName": "长度",
|
||||||
|
"status": "Y",
|
||||||
|
"unitOrder": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"unitType": "length",
|
||||||
|
"unitName": "cm(厘米)",
|
||||||
|
"baseUnit": "N",
|
||||||
|
"conversionFactor": 100,
|
||||||
|
"unitTypeName": "长度",
|
||||||
|
"status": "Y",
|
||||||
|
"unitOrder": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"unitType": "length",
|
||||||
|
"unitName": "mm(毫米)",
|
||||||
|
"baseUnit": "N",
|
||||||
|
"conversionFactor": 1000,
|
||||||
|
"unitTypeName": "长度",
|
||||||
|
"status": "Y",
|
||||||
|
"unitOrder": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"unitType": "length",
|
||||||
|
"unitName": "km(千米)",
|
||||||
|
"baseUnit": "N",
|
||||||
|
"conversionFactor": 0.001,
|
||||||
|
"unitTypeName": "长度",
|
||||||
|
"status": "Y",
|
||||||
|
"unitOrder": 4
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default unitData;
|
@ -1,14 +1,15 @@
|
|||||||
{
|
{
|
||||||
"id": "yjly-number_unit",
|
"id": "yjly-inputunit",
|
||||||
"displayName": "yjly-number_unit",
|
"displayName": "单位转换组件,双向数值绑定,单位循环切换、弹窗选择,支持自定义单位显示",
|
||||||
"version": "1.0.0",
|
"version": "1.0.2",
|
||||||
"description": "yjly-number_unit",
|
"description": "单位转换组件 支持双向数值绑定 内置单位换算逻辑 支持单位循环切换/弹窗选择两种模式 兼容 Vue2/Vue3 和 UniApp 多平台 支持自定义单位显示 可配置小数位数精度",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"yjly-number_unit"
|
"单位转换组件",
|
||||||
|
"双向数值绑定",
|
||||||
|
"自定义单位显示"
|
||||||
],
|
],
|
||||||
"repository": "",
|
"repository": "",
|
||||||
"engines": {
|
"engines": {
|
||||||
"HBuilderX": "^3.1.0"
|
|
||||||
},
|
},
|
||||||
"dcloudext": {
|
"dcloudext": {
|
||||||
"type": "component-vue",
|
"type": "component-vue",
|
||||||
@ -24,9 +25,9 @@
|
|||||||
"qq": ""
|
"qq": ""
|
||||||
},
|
},
|
||||||
"declaration": {
|
"declaration": {
|
||||||
"ads": "",
|
"ads": "无",
|
||||||
"data": "",
|
"data": "无",
|
||||||
"permissions": ""
|
"permissions": "无"
|
||||||
},
|
},
|
||||||
"npmurl": ""
|
"npmurl": ""
|
||||||
},
|
},
|
||||||
@ -35,36 +36,37 @@
|
|||||||
"encrypt": [],
|
"encrypt": [],
|
||||||
"platforms": {
|
"platforms": {
|
||||||
"cloud": {
|
"cloud": {
|
||||||
"tcb": "u",
|
"tcb": "y",
|
||||||
"aliyun": "u",
|
"aliyun": "y",
|
||||||
"alipay": "u"
|
"alipay": "y"
|
||||||
},
|
},
|
||||||
"client": {
|
"client": {
|
||||||
"Vue": {
|
"Vue": {
|
||||||
"vue2": "u",
|
"vue2": "y",
|
||||||
"vue3": "u"
|
"vue3": "y"
|
||||||
},
|
},
|
||||||
"App": {
|
"App": {
|
||||||
"app-vue": "u",
|
"app-vue": "y",
|
||||||
"app-nvue": "u",
|
"app-nvue": "u",
|
||||||
"app-uvue": "u"
|
"app-uvue": "u",
|
||||||
|
"app-harmony": "u"
|
||||||
},
|
},
|
||||||
"H5-mobile": {
|
"H5-mobile": {
|
||||||
"Safari": "u",
|
"Safari": "u",
|
||||||
"Android Browser": "u",
|
"Android Browser": "u",
|
||||||
"微信浏览器(Android)": "u",
|
"微信浏览器(Android)": "y",
|
||||||
"QQ浏览器(Android)": "u"
|
"QQ浏览器(Android)": "y"
|
||||||
},
|
},
|
||||||
"H5-pc": {
|
"H5-pc": {
|
||||||
"Chrome": "u",
|
"Chrome": "y",
|
||||||
"IE": "u",
|
"IE": "u",
|
||||||
"Edge": "u",
|
"Edge": "y",
|
||||||
"Firefox": "u",
|
"Firefox": "u",
|
||||||
"Safari": "u"
|
"Safari": "u"
|
||||||
},
|
},
|
||||||
"小程序": {
|
"小程序": {
|
||||||
"微信": "u",
|
"微信": "y",
|
||||||
"阿里": "u",
|
"阿里": "y",
|
||||||
"百度": "u",
|
"百度": "u",
|
||||||
"字节跳动": "u",
|
"字节跳动": "u",
|
||||||
"QQ": "u",
|
"QQ": "u",
|
158
uni_modules/yjly-inputunit/readme.md
Normal file
158
uni_modules/yjly-inputunit/readme.md
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
# yjyl-input-unit 单位转换组件使用说明
|
||||||
|
功能特性
|
||||||
|
支持双向数值绑定
|
||||||
|
内置单位换算逻辑(含温度特殊处理)
|
||||||
|
支持单位循环切换/弹窗选择两种模式
|
||||||
|
兼容 Vue2/Vue3 和 UniApp 多平台
|
||||||
|
支持自定义单位显示
|
||||||
|
可配置小数位数精度
|
||||||
|
|
||||||
|
符合uni-modules标准,直接使用
|
||||||
|
|
||||||
|
|
||||||
|
Props 配置
|
||||||
|
|属性名 |类型 |必填 |默认值 |说明 |
|
||||||
|
|:-: |:-: |:-: |:-: |:-: |
|
||||||
|
|unitType |String |是 |- |单位类型(例:'length', 'weight', 'temperature') |
|
||||||
|
|unitOrder |Number |否 |0 |当前单位序号(需配合 .sync 修饰符使用) |
|
||||||
|
|value |Number |是 |- |输入数值(使用 v-model 双向绑定) |
|
||||||
|
|showEnglishOnly |Boolean|否 |false |是否只显示英文单位(例:'kg' 代替 ' 千克 (kg)') |
|
||||||
|
|decimalPlaces |Number |否 |5 |小数位数(0 - 10) |
|
||||||
|
|width |Number |否 |180 |组件总宽度(px) |
|
||||||
|
|height |Number |否 |32 |组件高度(px) |
|
||||||
|
|enableConvert |Boolean|否 |true |是否允许单位转换 |
|
||||||
|
|userDefined |Boolean|否 |false |是否使用自定义单位 |
|
||||||
|
|userDefinedunitName|String |否 |'' |自定义单位显示名称(需 userDefined = true 生效) |
|
||||||
|
|
||||||
|
|
||||||
|
事件说明
|
||||||
|
| 事件名称 | 说明 | 回调参数 |
|
||||||
|
| input | 数值变化时触发 | (newValue: number) |
|
||||||
|
| update:unitOrder | 单位序号变化时触发 | (newOrder: number) |
|
||||||
|
| conversion | 完成单位转换时触发 | { initialValue, newValue, oldUnit, newUnit, oldOrder, newOrder } 的 Object |
|
||||||
|
使用示例
|
||||||
|
基本用法
|
||||||
|
vue
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<UniUnitConverter
|
||||||
|
v-model="value"
|
||||||
|
:unit-type="length"
|
||||||
|
:unit-order.sync="currentOrder"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value: 100,
|
||||||
|
currentOrder: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
禁用转换模式
|
||||||
|
|
||||||
|
<UniUnitConverter
|
||||||
|
v-model="fixedValue"
|
||||||
|
:unit-type="weight"
|
||||||
|
:enable-convert="false"
|
||||||
|
user-defined
|
||||||
|
:user-definedunit-name="'特殊单位'"
|
||||||
|
/>
|
||||||
|
事件处理
|
||||||
|
vue
|
||||||
|
复制
|
||||||
|
<template>
|
||||||
|
<UniUnitConverter
|
||||||
|
v-model="tempValue"
|
||||||
|
:unit-type="temperature"
|
||||||
|
@conversion="handleConversion"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
handleConversion({ oldUnit, newUnit, newValue }) {
|
||||||
|
console.log(`单位从 ${oldUnit} 转换为 ${newUnit},新值:${newValue}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
API 需自己开发,按照下面的数据格式进行组织,参考unitData.js
|
||||||
|
组件依赖 listSysUnitConvert API 获取单位数据,需实现以下格式的接口:
|
||||||
|
|
||||||
|
javascript
|
||||||
|
{
|
||||||
|
rows: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
unitType: 'length',
|
||||||
|
unitName: '米(m)',
|
||||||
|
conversionFactor: 1,
|
||||||
|
baseUnit: 'Y',
|
||||||
|
unitOrder: 0
|
||||||
|
},
|
||||||
|
// ...其他单位数据
|
||||||
|
]
|
||||||
|
}
|
||||||
|
样式调整
|
||||||
|
可通过以下 CSS 类名自定义样式:
|
||||||
|
|
||||||
|
.unit-converter - 组件容器
|
||||||
|
|
||||||
|
.input-field - 输入框
|
||||||
|
|
||||||
|
.unit-label - 单位标签
|
||||||
|
|
||||||
|
.unit-selector - 单位选择器
|
||||||
|
|
||||||
|
.unit-option - 单位选项
|
||||||
|
|
||||||
|
平台差异
|
||||||
|
|
||||||
|
小程序端使用 longpress 事件触发选择器(长按代替双击)
|
||||||
|
|
||||||
|
H5 端自动适配点击事件
|
||||||
|
|
||||||
|
单位转换规则
|
||||||
|
|
||||||
|
温度单位需按约定顺序定义:
|
||||||
|
|
||||||
|
javascript
|
||||||
|
复制
|
||||||
|
[
|
||||||
|
{ unitOrder: 0, unitName: '℃' }, // 摄氏度
|
||||||
|
{ unitOrder: 1, unitName: '℉' }, // 华氏度
|
||||||
|
{ unitOrder: 2, unitName: 'K' } // 开尔文
|
||||||
|
]
|
||||||
|
自定义单位时需确保与现有换算逻辑兼容
|
||||||
|
|
||||||
|
常见问题
|
||||||
|
Q1: 单位选择器不显示
|
||||||
|
|
||||||
|
检查 enableConvert 是否为 true
|
||||||
|
|
||||||
|
确认单位数据加载成功
|
||||||
|
|
||||||
|
查看控制台是否有 API 错误
|
||||||
|
|
||||||
|
Q2: 数值更新不及时
|
||||||
|
|
||||||
|
确保使用 v-model 进行双向绑定
|
||||||
|
|
||||||
|
检查小数位数配置是否符合预期
|
||||||
|
|
||||||
|
确认没有在父组件中覆盖转换后的值
|
||||||
|
|
||||||
|
Q3: 样式显示异常
|
||||||
|
|
||||||
|
检查是否父容器有冲突的布局样式
|
||||||
|
|
||||||
|
确认单位标签宽度计算正确(通过 updateInputWidth 方法)
|
||||||
|
|
||||||
|
在小程序端添加 !important 覆盖默认样式
|
||||||
|
|
@ -1,272 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="unit-converter">
|
|
||||||
<!-- 数值输入框 -->
|
|
||||||
<input v-model="inputValue" type="number" @input="handleInputChange" class="input-field" :style="{ width: width + 'px' }" />
|
|
||||||
<!-- 单位标签 -->
|
|
||||||
<text @click="toggleUnit" @dblclick="openUnitSelector" class="unit-label" :style="{ color: 'blue' }">
|
|
||||||
{{ displayUnitName }}
|
|
||||||
</text>
|
|
||||||
<!-- 单位选择弹出窗口 -->
|
|
||||||
<!-- uni-popup 弹窗 -->
|
|
||||||
<uni-popup ref="unitSelectorPopup" type="bottom" :show="showUnitSelector" @close="onPopupClose">
|
|
||||||
<view class="unit-selector">
|
|
||||||
<view v-for="unit in filteredUnitList" :key="unit.id" @click="selectUnit(unit)" class="unit-option">
|
|
||||||
{{ showEnglishOnly ? unit.unitName.split('(')[0] : unit.unitName }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</uni-popup>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { listConversion } from '@/api/system/conversion.js';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
// 单位类型
|
|
||||||
unitType: {
|
|
||||||
type: String,
|
|
||||||
default: 'length'
|
|
||||||
},
|
|
||||||
// 是否只显示英文部分
|
|
||||||
showEnglishOnly: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
// 当前单位名称
|
|
||||||
unitName: {
|
|
||||||
type: String,
|
|
||||||
required: false,
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
// 当前数值
|
|
||||||
value: {
|
|
||||||
type: Number,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
// 小数点位数
|
|
||||||
decimalPlaces: {
|
|
||||||
type: Number,
|
|
||||||
default: 2
|
|
||||||
},
|
|
||||||
width: {
|
|
||||||
type: Number,
|
|
||||||
required: false,
|
|
||||||
default: 80
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
inputValue: this.value, // 输入的数值
|
|
||||||
currentUnit: null, // 当前单位
|
|
||||||
unitList: [], // 单位列表
|
|
||||||
showUnitSelector: false // 是否显示单位选择窗口
|
|
||||||
};
|
|
||||||
},
|
|
||||||
onLoad() {
|
|
||||||
// 在页面加载时添加全局点击事件监听器
|
|
||||||
uni.$on('globalClick', this.handleClickOutside);
|
|
||||||
},
|
|
||||||
onUnload() {
|
|
||||||
// 在页面卸载时移除全局点击事件监听器
|
|
||||||
uni.$off('globalClick', this.handleClickOutside);
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
// 显示的单位名称
|
|
||||||
displayUnitName() {
|
|
||||||
if (!this.currentUnit) return '';
|
|
||||||
return this.showEnglishOnly ? this.currentUnit.unitName.split('(')[0] : this.currentUnit.unitName;
|
|
||||||
},
|
|
||||||
// 过滤后的单位列表(排除当前单位)
|
|
||||||
filteredUnitList() {
|
|
||||||
return this.unitList.filter((unit) => unit.unitName !== this.currentUnit?.unitName);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
// 监听 unitType 变化,重新加载单位列表
|
|
||||||
unitType: {
|
|
||||||
immediate: true,
|
|
||||||
handler(newVal) {
|
|
||||||
this.loadUnitList(newVal);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 监听 unitName 变化,更新当前单位
|
|
||||||
unitName: {
|
|
||||||
immediate: true,
|
|
||||||
handler(newVal) {
|
|
||||||
console.log(newVal);
|
|
||||||
this.currentUnit = this.unitList.find((unit) => unit.unitName == newVal);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 监听 value 变化,更新输入框的值
|
|
||||||
value: {
|
|
||||||
immediate: true,
|
|
||||||
handler(newVal) {
|
|
||||||
this.inputValue = newVal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
// 处理全局点击事件
|
|
||||||
handleClickOutside(event) {
|
|
||||||
if (this.$refs.unitSelector && !this.$refs.unitSelector.contains(event.target)) {
|
|
||||||
this.showUnitSelector = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 切换单位选择器的显示状态
|
|
||||||
toggleUnitSelector() {
|
|
||||||
this.showUnitSelector = !this.showUnitSelector;
|
|
||||||
},
|
|
||||||
// 加载单位列表
|
|
||||||
async loadUnitList(unitType) {
|
|
||||||
try {
|
|
||||||
const response = await listConversion({ pageSize: 100, unitType: unitType });
|
|
||||||
console.log(response);
|
|
||||||
this.unitList = response.rows;
|
|
||||||
if (this.unitName == '') {
|
|
||||||
// 处理默认基准单位
|
|
||||||
this.currentUnit = this.unitList.find((unit) => unit.baseUnit == 1);
|
|
||||||
console.log(this.currentUnit);
|
|
||||||
} else {
|
|
||||||
this.currentUnit = this.unitList.find((unit) => unit.unitName == this.unitName);
|
|
||||||
console.log(this.currentUnit);
|
|
||||||
if (this.currentUnit === undefined) {
|
|
||||||
this.currentUnit = this.unitList.find((unit) => unit.baseUnit === 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to load unit list:', error);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 处理输入框变化
|
|
||||||
handleInputChange() {
|
|
||||||
this.$emit('input', this.inputValue); // 将输入值同步到父组件
|
|
||||||
this.convertAndEmit();
|
|
||||||
},
|
|
||||||
// 切换单位
|
|
||||||
toggleUnit() {
|
|
||||||
const currentIndex = this.unitList.indexOf(this.currentUnit);
|
|
||||||
const nextIndex = (currentIndex + 1) % this.unitList.length;
|
|
||||||
let oldUnit = this.currentUnit;
|
|
||||||
let newUnit = this.unitList[nextIndex];
|
|
||||||
this.currentUnit = newUnit;
|
|
||||||
// console.log('切换单位', currentIndex, nextIndex, this.currentUnit);
|
|
||||||
this.convertAndEmit(oldUnit, newUnit);
|
|
||||||
},
|
|
||||||
// 打开单位选择窗口
|
|
||||||
openUnitSelector() {
|
|
||||||
this.showUnitSelector = true;
|
|
||||||
},
|
|
||||||
// 选择单位
|
|
||||||
selectUnit(unit) {
|
|
||||||
console.log('所选择的单位', unit);
|
|
||||||
let oldUnit = this.currentUnit;
|
|
||||||
let newUnit = unit;
|
|
||||||
this.currentUnit = unit;
|
|
||||||
this.showUnitSelector = false;
|
|
||||||
this.convertAndEmit(oldUnit, newUnit);
|
|
||||||
},
|
|
||||||
// 换算并提交结果
|
|
||||||
convertAndEmit(oldUnit, newUnit) {
|
|
||||||
if (!newUnit) return;
|
|
||||||
// 获取基准单位
|
|
||||||
const baseUnit = this.unitList.find((unit) => unit.baseUnit === 1);
|
|
||||||
if (!baseUnit) return;
|
|
||||||
// 将输入值转换为基准单位的值
|
|
||||||
const baseValue = this.inputValue / oldUnit.conversionFactor;
|
|
||||||
// 将基准单位的值转换为新单位的值
|
|
||||||
const newValue = baseValue * newUnit.conversionFactor;
|
|
||||||
|
|
||||||
console.log('转换值', newUnit.unitName, this.inputValue, baseValue, newValue);
|
|
||||||
|
|
||||||
let roundedValue;
|
|
||||||
if (newUnit.unitName === 'ly(光年)') {
|
|
||||||
// 对于光年,使用科学计数法显示结果
|
|
||||||
roundedValue = newValue.toExponential();
|
|
||||||
} else {
|
|
||||||
roundedValue = this.roundToDecimalPlaces(newValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 提交结果给父组件
|
|
||||||
this.$emit('conversion', {
|
|
||||||
initialValue: this.inputValue,
|
|
||||||
newValue: roundedValue,
|
|
||||||
oldUnit: oldUnit.unitName,
|
|
||||||
newUnit: newUnit.unitName
|
|
||||||
});
|
|
||||||
|
|
||||||
this.inputValue = parseFloat(roundedValue);
|
|
||||||
|
|
||||||
// 更新父组件的 unitName
|
|
||||||
this.$emit('update:unitName', this.currentUnit.unitName);
|
|
||||||
},
|
|
||||||
// 四舍六入五留双
|
|
||||||
// 按照四舍六入五留双处理结果 conversionFactor
|
|
||||||
roundToDecimalPlaces(value) {
|
|
||||||
const multiplier = Math.pow(10, this.decimalPlaces);
|
|
||||||
const val = value * multiplier;
|
|
||||||
const intVal = Math.trunc(val);
|
|
||||||
const decimalPart = val - intVal;
|
|
||||||
if (decimalPart < 0.5) {
|
|
||||||
return intVal / multiplier;
|
|
||||||
} else if (decimalPart > 0.5) {
|
|
||||||
return (intVal + 1) / multiplier;
|
|
||||||
} else {
|
|
||||||
return intVal % 2 === 0 ? intVal / multiplier : (intVal + 1) / multiplier;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.unit-converter {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 10px;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-field {
|
|
||||||
padding: 2px;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unit-label {
|
|
||||||
cursor: pointer;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unit-selector {
|
|
||||||
/* 设置容器的最大高度,当内容超出这个高度时会出现滚动条 */
|
|
||||||
max-height: 200px;
|
|
||||||
/* 超出内容时显示纵向滚动条 */
|
|
||||||
overflow-y: auto;
|
|
||||||
/* 横向内容不溢出,隐藏多余部分 */
|
|
||||||
overflow-x: hidden;
|
|
||||||
/* 其他样式保持不变 */
|
|
||||||
position: absolute;
|
|
||||||
z-index: 1000;
|
|
||||||
background-color: white;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 4px;
|
|
||||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
||||||
padding: 2px 0;
|
|
||||||
min-width: 100px;
|
|
||||||
list-style-type: none;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unit-option {
|
|
||||||
padding: 2px 10px;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unit-option:hover {
|
|
||||||
background-color: #f0f0f0;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1 +0,0 @@
|
|||||||
# yjly-number_unit
|
|
Loading…
Reference in New Issue
Block a user