增加带单位的输入框组件,修改
This commit is contained in:
parent
c7b4db67bf
commit
7274dd2ade
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'
|
||||||
|
})
|
||||||
|
}
|
@ -1,5 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="normal-login-container">
|
<view class="normal-login-container">
|
||||||
|
<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' }"
|
||||||
|
></yjly-inputunit>
|
||||||
<view class="logo-content align-center justify-center flex">
|
<view class="logo-content align-center justify-center flex">
|
||||||
<image style="width: 100rpx; height: 100rpx" :src="globalConfig.appInfo.logo" mode="widthFix"></image>
|
<image style="width: 100rpx; height: 100rpx" :src="globalConfig.appInfo.logo" mode="widthFix"></image>
|
||||||
<text class="title">若依移动端登录</text>
|
<text class="title">若依移动端登录</text>
|
||||||
@ -42,6 +51,8 @@ import { getCodeImg } from '@/api/login';
|
|||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
mylength: 10,
|
||||||
|
myunitname: '',
|
||||||
codeUrl: '',
|
codeUrl: '',
|
||||||
captchaEnabled: true,
|
captchaEnabled: true,
|
||||||
// 用户注册开关
|
// 用户注册开关
|
||||||
|
4
uni_modules/yjly-inputunit/changelog.md
Normal file
4
uni_modules/yjly-inputunit/changelog.md
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
## 1.0.1(2025-02-15)
|
||||||
|
修改单位类型默认值
|
||||||
|
## 1.0.0(2025-02-15)
|
||||||
|
1.0.0
|
@ -0,0 +1,422 @@
|
|||||||
|
<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
|
||||||
|
};
|
||||||
|
},
|
||||||
|
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) {
|
||||||
|
console.log(newVal);
|
||||||
|
this.inputValue = newVal;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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.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 next = (index + 1) % this.sortedUnits.length;
|
||||||
|
const oldUnit = this.currentUnit;
|
||||||
|
const newUnit = this.sortedUnits[next];
|
||||||
|
|
||||||
|
this.currentUnit = newUnit;
|
||||||
|
this.textUnitName = this.showEnglishOnly ? newUnit.unitName.split('(')[0].trim() : newUnit.unitName;
|
||||||
|
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.updateInputWidth();
|
||||||
|
this.convertAndEmit(oldUnit, newUnit);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleUnitSelector() {
|
||||||
|
this.showUnitSelector = !this.showUnitSelector;
|
||||||
|
if (this.showUnitSelector) {
|
||||||
|
this.positionUnitSelector();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
selectUnit(unit) {
|
||||||
|
const oldUnit = this.currentUnit;
|
||||||
|
this.currentUnit = unit;
|
||||||
|
this.showUnitSelector = false;
|
||||||
|
this.textUnitName = this.showEnglishOnly ? unit.unitName.split('(')[0].trim() : unit.unitName;
|
||||||
|
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.updateInputWidth();
|
||||||
|
this.convertAndEmit(oldUnit, unit);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
handleInputChange() {
|
||||||
|
this.$emit('input', this.inputValue);
|
||||||
|
this.convertAndEmit(this.currentUnit, this.currentUnit);
|
||||||
|
},
|
||||||
|
|
||||||
|
convertAndEmit(oldUnit, newUnit) {
|
||||||
|
if (!newUnit || !oldUnit || !this.baseUnit) return;
|
||||||
|
|
||||||
|
let newValue = 0;
|
||||||
|
if (this.unitType === 'temperature') {
|
||||||
|
newValue = this.handleTemperatureConversion(oldUnit, newUnit);
|
||||||
|
} else {
|
||||||
|
const baseValue = this.inputValue / oldUnit.conversionFactor;
|
||||||
|
newValue = baseValue * newUnit.conversionFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
const roundedValue = this.roundValue(newValue);
|
||||||
|
this.inputValue = roundedValue;
|
||||||
|
this.$emit('input', roundedValue);
|
||||||
|
this.$emit('update:unitOrder', newUnit.unitOrder);
|
||||||
|
|
||||||
|
this.$emit('conversion', {
|
||||||
|
initialValue: this.value,
|
||||||
|
newValue: roundedValue,
|
||||||
|
oldUnit: oldUnit.unitName,
|
||||||
|
newUnit: newUnit.unitName,
|
||||||
|
oldOrder: oldUnit.unitOrder,
|
||||||
|
newOrder: newUnit.unitOrder
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 温度单位换算
|
||||||
|
handleTemperatureConversion(oldUnit, newUnit) {
|
||||||
|
const oldUnitOrder = oldUnit.unitOrder;
|
||||||
|
const newUnitOrder = newUnit.unitOrder;
|
||||||
|
|
||||||
|
// console.log(oldUnitOrder, newUnitOrder);
|
||||||
|
|
||||||
|
// 先将值转换为摄氏度作为中间单位
|
||||||
|
let celsius;
|
||||||
|
switch (oldUnitOrder) {
|
||||||
|
case 0:
|
||||||
|
celsius = this.inputValue;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
celsius = (this.inputValue - 32) * (5 / 9);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
celsius = this.inputValue - 273.15;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error(`不支持的旧温度单位: ${oldUnit.unitName}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 再将摄氏度转换为新单位
|
||||||
|
let result;
|
||||||
|
switch (newUnitOrder) {
|
||||||
|
case 0:
|
||||||
|
result = celsius;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
result = celsius * (9 / 5) + 32;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
result = celsius + 273.15;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error(`不支持的新温度单位: ${newUnit.unitName}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 四舍六入五成双
|
||||||
|
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;
|
86
uni_modules/yjly-inputunit/package.json
Normal file
86
uni_modules/yjly-inputunit/package.json
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
{
|
||||||
|
"id": "yjly-inputunit",
|
||||||
|
"displayName": "yjly-inputunit",
|
||||||
|
"version": "1.0.1",
|
||||||
|
"description": "单位转换组件 支持双向数值绑定 内置单位换算逻辑 支持单位循环切换/弹窗选择两种模式 兼容 Vue2/Vue3 和 UniApp 多平台 支持自定义单位显示 可配置小数位数精度",
|
||||||
|
"keywords": [
|
||||||
|
"单位转换组件",
|
||||||
|
"双向数值绑定",
|
||||||
|
"自定义单位显示"
|
||||||
|
],
|
||||||
|
"repository": "",
|
||||||
|
"engines": {
|
||||||
|
"HBuilderX": "^3.1.0"
|
||||||
|
},
|
||||||
|
"dcloudext": {
|
||||||
|
"type": "component-vue",
|
||||||
|
"sale": {
|
||||||
|
"regular": {
|
||||||
|
"price": "0.00"
|
||||||
|
},
|
||||||
|
"sourcecode": {
|
||||||
|
"price": "0.00"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"contact": {
|
||||||
|
"qq": ""
|
||||||
|
},
|
||||||
|
"declaration": {
|
||||||
|
"ads": "无",
|
||||||
|
"data": "无",
|
||||||
|
"permissions": "无"
|
||||||
|
},
|
||||||
|
"npmurl": ""
|
||||||
|
},
|
||||||
|
"uni_modules": {
|
||||||
|
"dependencies": [],
|
||||||
|
"encrypt": [],
|
||||||
|
"platforms": {
|
||||||
|
"cloud": {
|
||||||
|
"tcb": "y",
|
||||||
|
"aliyun": "y",
|
||||||
|
"alipay": "y"
|
||||||
|
},
|
||||||
|
"client": {
|
||||||
|
"Vue": {
|
||||||
|
"vue2": "y",
|
||||||
|
"vue3": "y"
|
||||||
|
},
|
||||||
|
"App": {
|
||||||
|
"app-vue": "y",
|
||||||
|
"app-nvue": "u",
|
||||||
|
"app-uvue": "u",
|
||||||
|
"app-harmony": "u"
|
||||||
|
},
|
||||||
|
"H5-mobile": {
|
||||||
|
"Safari": "u",
|
||||||
|
"Android Browser": "u",
|
||||||
|
"微信浏览器(Android)": "y",
|
||||||
|
"QQ浏览器(Android)": "y"
|
||||||
|
},
|
||||||
|
"H5-pc": {
|
||||||
|
"Chrome": "y",
|
||||||
|
"IE": "u",
|
||||||
|
"Edge": "y",
|
||||||
|
"Firefox": "u",
|
||||||
|
"Safari": "u"
|
||||||
|
},
|
||||||
|
"小程序": {
|
||||||
|
"微信": "y",
|
||||||
|
"阿里": "y",
|
||||||
|
"百度": "u",
|
||||||
|
"字节跳动": "u",
|
||||||
|
"QQ": "u",
|
||||||
|
"钉钉": "u",
|
||||||
|
"快手": "u",
|
||||||
|
"飞书": "u",
|
||||||
|
"京东": "u"
|
||||||
|
},
|
||||||
|
"快应用": {
|
||||||
|
"华为": "u",
|
||||||
|
"联盟": "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 覆盖默认样式
|
||||||
|
|
Loading…
Reference in New Issue
Block a user