ruoyi-geek-App/pages_caltools/components/NGCom.vue
2025-11-30 22:19:19 +08:00

501 lines
9.8 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="form-container">
<view class="button-group">
<button type="primary" size="mini" @click="clearForm" class="action-button">全部清零</button>
<button type="primary" size="mini" @click="copyForm" class="action-button">复制组分</button>
<button type="primary" size="mini" @click="pasteForm" class="action-button">粘贴组分</button>
</view>
<scroll-view scroll-y :style="{ height: scrollViewHeight + 'px' }" class="scroll-area">
<view class="form-content">
<view class="form-grid">
<!-- 常用组分 -->
<view class="form-item ">
<view class="form-label">常用组分</view>
<view class="form-control">
<uni-data-select class="data-select" v-model="selectedComponent"
@change="handleComponentChange" placeholder="请选择常用组分" :clear="true"
:localdata="componentOptions" />
</view>
</view>
<!-- 组合合计 -->
<view class="form-item ">
<view class="form-label">组合合计</view>
<view class="form-control">
<uni-easyinput class="input-class" :value="totalPercentage" disabled />
</view>
</view>
<!-- 动态生成的组分字段 -->
<view class="form-item" v-for="field in componentFields" :key="field.prop">
<view class="form-label">{{field.label}}</view>
<view class="form-control">
<uni-easyinput class="input-class" v-model="formData[field.prop]" type="digit"
@input="handleValueChange" :placeholder="'请输入'+field.label" />
</view>
</view>
</view>
</view>
</scroll-view>
</view>
</template>
<style scoped>
.form-container {
padding: 10rpx;
box-sizing: border-box;
width: 100%;
}
.button-group {
display: flex;
justify-content: center;
gap: 20rpx;
margin-top: 30rpx;
margin-bottom: 30rpx;
padding: 0 20rpx;
}
.action-button {
flex: 1;
max-width: 200rpx;
}
.scroll-area {
width: 100%;
}
.form-content {
padding-left: 40rpx;
padding-right: 40rpx;
box-sizing: border-box;
}
.form-grid {
display: grid;
gap: 20rpx;
}
.form-item {
width: 100%;
display: flex;
flex-direction: column;
}
.form-label {
font-size: 12px;
color: #606266;
margin-bottom: 8rpx;
font-weight: 300;
}
.form-control {
width: 100%;
}
.input-class {
background-color: white;
font-weight: 400;
width: 100%;
}
.data-select {
width: 100%;
background-color: white;
}
/* 默认移动端2列 */
@media screen and (max-width: 768px) {
.form-grid {
grid-template-columns: repeat(2, 1fr);
}
}
/* 桌面3列 */
@media screen and (min-width: 1200px) {
.form-grid {
grid-template-columns: repeat(3, 1fr);
}
}
/* 确保组件在小程序中正常显示 */
.uni-data-select,
.uni-easyinput {
width: 100%;
}
</style>
<script setup>
import {
ref,
watch,
onMounted,
computed,
nextTick
} from 'vue';
import {
onLoad
} from '@dcloudio/uni-app';
import {
useDict
} from '@/utils/dict'
// 使用字典Hook获取ngtools_cyzf字典数据
const {
ngtools_cyzf
} = useDict('ngtools_cyzf')
const dictLoading = ref(false)
// 计算属性:将字典数据转换为下拉框需要的格式
const componentOptions = computed(() => {
return (ngtools_cyzf.value || []).map(item => ({
value: item.value,
text: item.label
}))
})
// 字段配置元数据
const COMPONENT_FIELDS = [{
prop: 'ngC1',
label: '甲烷C1'
},
{
prop: 'ngN2',
label: '氮气N2'
},
{
prop: 'ngCo2',
label: '二氧化碳CO2'
},
{
prop: 'ngC2',
label: '乙烷C2'
},
{
prop: 'ngC3',
label: '丙烷C3'
},
{
prop: 'ngH2o',
label: '水H2O'
},
{
prop: 'ngH2s',
label: '硫化氢H2S'
},
{
prop: 'ngH2',
label: '氢气H2'
},
{
prop: 'ngCo',
label: '一氧化碳CO'
},
{
prop: 'ngO2',
label: '氧气O2'
},
{
prop: 'ngIc4',
label: '异丁烷iC4'
},
{
prop: 'ngNc4',
label: '正丁烷nC4'
},
{
prop: 'ngIc5',
label: '异戊烷iC5'
},
{
prop: 'ngNc5',
label: '正戊烷nC5'
},
{
prop: 'ngC6',
label: '己烷C6'
},
{
prop: 'ngC7',
label: '庚烷C7'
},
{
prop: 'ngC8',
label: '辛烷C8'
},
{
prop: 'ngC9',
label: '壬烷C9'
},
{
prop: 'ngC10',
label: '癸烷C10'
},
{
prop: 'ngHe',
label: '氦气He'
},
{
prop: 'ngAr',
label: '氩气Ar'
}
];
// 定义 props
const props = defineProps({
modelValue: {
type: String,
default: ''
},
elFormWidth: {
type: Number,
default: 180
},
otherComHeight: {
type: Number,
default: 120
},
});
// 定义 emits
const emits = defineEmits(['update:modelValue']);
// 定义响应式数据
const selectWidth = ref(0);
const selectedComponent = ref(null);
const formData = ref(initFormData());
const componentFields = ref(COMPONENT_FIELDS);
watch(
() => props.otherComHeight,
(newVal) => {
nextTick(() => {
calculateScrollViewHeight(newVal)
})
})
// 定义响应式数据
const scrollViewHeight = ref(0);
const btnHeight = ref(0);
// 获取屏幕高度并计算scroll-view高度
const calculateScrollViewHeight = (h) => {
try {
let systemInfo = {};
// #ifdef MP-WEIXIN
// 微信小程序平台
try {
// 获取窗口信息
const windowInfo = wx.getWindowInfo();
// 获取设备信息
const deviceInfo = wx.getDeviceInfo();
// 将两个新API获取到的信息合并成一个对象方便使用
systemInfo = {
...windowInfo,
...deviceInfo
};
// 注意:如果你还需要获取系统设置或授权信息,可以按需添加
// const systemSetting = wx.getSystemSetting();
// const appAuthorizeSetting = wx.getAppAuthorizeSetting();
// systemInfo = { ...systemInfo, ...systemSetting, ...appAuthorizeSetting };
} catch (e) {
console.error("获取微信小程序系统信息失败:", e);
}
// #endif
// #ifdef H5 || APP-PLUS
// H5 或 App 平台
try {
systemInfo = uni.getSystemInfoSync();
} catch (e) {
console.error("获取系统信息失败:", e);
}
// #endif
const screenHeight = systemInfo.windowHeight;
// 计算scroll-view高度
scrollViewHeight.value = screenHeight - h - 80;
} catch (error) {
console.error('获取系统信息失败:', error);
// 设置默认高度
scrollViewHeight.value = 400;
}
};
// 页面加载
onMounted(() => {
selectWidth.value = props.elFormWidth;
});
// 计算属性
const totalPercentage = computed(() => {
return Object.values(formData.value)
.reduce((sum, val) => sum + (parseFloat(val) || 0), 0)
.toFixed(4);
});
// 初始化表单数据
function initFormData() {
return COMPONENT_FIELDS.reduce((acc, field) => {
acc[field.prop] = 0;
return acc;
}, {});
}
/**
* 清零表单
*/
function clearForm() {
console.log(componentFields.value, formData.value)
componentFields.value.forEach(field => {
formData.value[field.prop] = 0;
});
}
/**
* 复制表单数据到剪贴板
*/
function copyForm() {
// 将表单数据转为JSON字符串便于剪贴板存储
const formStr = JSON.stringify(formData.value);
uni.setClipboardData({
data: formStr,
success: () => {
uni.showToast({
title: '表单数据已复制',
icon: 'none'
});
},
fail: (err) => {
uni.showToast({
title: '复制失败',
icon: 'none'
});
console.error('复制失败:', err);
}
});
}
/**
* 从剪贴板粘贴数据到表单
*/
function pasteForm() {
uni.getClipboardData({
success: (res) => {
try {
// 解析剪贴板中的JSON字符串
const pastedData = JSON.parse(res.data);
console.log(pastedData)
// 合并粘贴的数据到表单(仅保留表单已定义的字段)
componentFields.value.forEach(field => {
if (pastedData.hasOwnProperty(field.prop)) {
formData.value[field.prop] = pastedData[field.prop];
}
});
uni.showToast({
title: '数据已粘贴',
icon: 'none'
});
} catch (e) {
uni.showToast({
title: '粘贴失败,请检查数据格式',
icon: 'none'
});
console.error('粘贴失败:', e);
}
},
fail: (err) => {
uni.showToast({
title: '获取剪贴板数据失败',
icon: 'none'
});
console.error('获取剪贴板数据失败:', err);
}
});
}
// 解析传入的字符串值
function parseValueString(valueStr) {
const values = (valueStr || '').split('_');
componentFields.value.forEach((field, index) => {
const value = parseFloat(values[index]) || 0;
formData.value[field.prop] = value;
});
}
// 生成要输出的字符串值
function generateValueString() {
return Object.values(formData.value)
.map((v) => v.toFixed(4))
.join('_');
}
// 处理组件选择变化
function handleComponentChange(value) {
if (!value) return;
try {
// console.log(value)
const componentData = JSON.parse(value);
Object.keys(formData.value).forEach((key) => {
formData.value[key] = parseFloat(componentData[key]) || 0;
});
emitUpdate();
} catch (error) {
uni.showToast({
title: '获取标准组分失败',
icon: 'none'
});
console.error(error);
}
}
// 处理值变化
function handleValueChange() {
nextTick(() => {
emitUpdate();
});
}
// 触发更新事件
function emitUpdate() {
if (Math.abs(parseFloat(totalPercentage.value) - 100) > 0.0001) {
uni.showToast({
title: '组分合计不等于100%,请检查输入',
icon: 'none'
});
}
emits('update:modelValue', generateValueString());
}
// 监听 elFormWidth 的变化
watch(
() => props.elFormWidth,
(newVal) => {
selectWidth.value = newVal;
}, {
deep: true
}
);
// 监听 value 的变化
watch(
() => props.modelValue,
(newVal) => {
parseValueString(newVal);
}, {
immediate: true
}
);
</script>