13 changed files with 747 additions and 365 deletions
-
4src/components/audit/History.vue
-
242src/components/formula/FormulaConfig.vue
-
62src/components/formula/FormulaTable.vue
-
188src/components/formula/HomeFormulaConfig.vue
-
343src/components/formula/SettingFormulaConfig.vue
-
32src/components/home/HomeSetting.vue
-
9src/components/home/config.vue
-
15src/components/setting/User.vue
-
180src/stores/formulaStore.ts
-
1src/types/formula.d.ts
-
8src/views/formula/index.vue
-
2src/views/home/chart.vue
-
12src/views/setting/index.vue
@ -0,0 +1,188 @@ |
|||
<script lang="ts" setup> |
|||
import { formulaNameMap } from 'libs/constant' |
|||
import { inject, onMounted, ref, watchEffect } from 'vue' |
|||
|
|||
import { convertValuesToInt, convertValuesToString } from '@/libs/utils' |
|||
import { useFormulaStore } from '@/stores/formulaStore' |
|||
|
|||
const props = defineProps<{ |
|||
formulaNameVisible: boolean |
|||
}>() |
|||
const formulaStore = useFormulaStore() |
|||
/** |
|||
* 获取当前表单数据,将值转换为字符串格式 |
|||
* @returns {Record<string, string>} 转换后的表单数据 |
|||
*/ |
|||
const getFormData = () => { |
|||
return convertValuesToString(formData.value, 'name') |
|||
} |
|||
/** |
|||
* 注册孙子组件方法的注入函数 |
|||
*/ |
|||
const registerGrandsonMethods = inject<(methods: any) => void>('registerGrandsonMethods', () => {}) |
|||
onMounted(() => { |
|||
registerGrandsonMethods && registerGrandsonMethods({ getFormData }) |
|||
}) |
|||
/** |
|||
* 当前表单数据 |
|||
* - home: 当前选中的配方 或者默认配方 |
|||
*/ |
|||
const formData = ref<Record<string, any>>({}) |
|||
/** |
|||
* 标签单位映射表,用于显示各参数的单位 |
|||
*/ |
|||
const labelUnitMap: Record<string, any> = formulaStore.labelUnitMap |
|||
/** |
|||
* 监听事件 |
|||
*/ |
|||
watchEffect(() => { |
|||
formData.value = formulaStore.selectedFormulaInfo !== null ? convertValuesToInt(formulaStore.selectedFormulaInfo) : convertValuesToInt(formulaStore.defaultFormulaInfo) |
|||
}) |
|||
/** |
|||
* 配方配置列表 |
|||
*/ |
|||
const formulaConfigList = formulaStore.formulaConfigList |
|||
const size = 'default' |
|||
</script> |
|||
|
|||
<template> |
|||
<div class="formula-form"> |
|||
<el-form |
|||
:disabled="true" |
|||
:model="formData" |
|||
label-width="auto" |
|||
label-position="right" |
|||
:size="size" |
|||
inline |
|||
> |
|||
<el-form-item v-if="props.formulaNameVisible" label="配方名称" style="width: 93%"> |
|||
<el-input |
|||
v-model="formData.name" |
|||
v-prevent-keyboard |
|||
name="name" |
|||
placeholder="配方名称" |
|||
:disabled="true" |
|||
/> |
|||
</el-form-item> |
|||
<el-form-item |
|||
v-for="item in formulaConfigList" |
|||
:key="item.setting_id" |
|||
:label="formulaNameMap[item.setting_id]" |
|||
style="width: 50%" |
|||
> |
|||
<template v-if="item.is_visible_in_rt_page && item.val_type === 'int'"> |
|||
<el-input |
|||
v-model.number="formData[item.setting_id]" |
|||
v-prevent-keyboard |
|||
style="width: 80%" |
|||
type="number" |
|||
:name="item.setting_id" |
|||
:controls="false" |
|||
:disabled="!item.is_editable" |
|||
> |
|||
<template v-if="labelUnitMap[item.setting_id]" #append> |
|||
{{ labelUnitMap[item.setting_id] }} |
|||
</template> |
|||
</el-input> |
|||
</template> |
|||
<template v-if="item.is_visible_in_rt_page && item.val_type === 'float'"> |
|||
<el-input |
|||
v-model.number="formData[item.setting_id]" |
|||
v-prevent-keyboard |
|||
style="width: 80%" |
|||
type="number" |
|||
:name="item.setting_id" |
|||
:controls="false" |
|||
:disabled="!item.is_editable" |
|||
> |
|||
<template v-if="labelUnitMap[item.setting_id]" #append> |
|||
{{ labelUnitMap[item.setting_id] }} |
|||
</template> |
|||
</el-input> |
|||
</template> |
|||
<template v-else-if="item.is_visible_in_rt_page && item.val_type === 'enum'"> |
|||
<el-input |
|||
v-model="formData[item.setting_id]" |
|||
v-prevent-keyboard |
|||
style="width: 80%" |
|||
placeholder="请选择" |
|||
readonly |
|||
:disabled="!item.is_editable" |
|||
> |
|||
<template #append> |
|||
{{ labelUnitMap[item.setting_id] }} |
|||
</template> |
|||
</el-input> |
|||
</template> |
|||
<template v-else-if="item.is_visible_in_rt_page && item.val_type === 'boolean'"> |
|||
<el-radio-group v-model="formData[item.setting_id]" :disabled="!item.is_editable"> |
|||
<el-radio :label="true"> |
|||
是 |
|||
</el-radio> |
|||
<el-radio :label="false"> |
|||
否 |
|||
</el-radio> |
|||
</el-radio-group> |
|||
</template> |
|||
</el-form-item> |
|||
</el-form> |
|||
</div> |
|||
</template> |
|||
|
|||
<style lang="scss" scoped> |
|||
.formula-form { |
|||
font-size: 20px !important; |
|||
padding: 5px; |
|||
padding-left: 15px; |
|||
align-items: center; |
|||
.default-btn { |
|||
margin-top: 1rem; |
|||
} |
|||
.config-btn { |
|||
height: 3rem; |
|||
width: 8rem; |
|||
} |
|||
} |
|||
|
|||
.formula-form-item { |
|||
display: grid; |
|||
grid-template-columns: 1fr 1fr; |
|||
} |
|||
|
|||
.formData-input-config { |
|||
width: 10vw; |
|||
} |
|||
:deep(.el-input__inner) { |
|||
text-align: left; |
|||
height: 40px; |
|||
} |
|||
:deep(.el-form-item) { |
|||
margin-right: 0; |
|||
align-items: center; |
|||
} |
|||
|
|||
/* 进入动画的初始状态 */ |
|||
.slide-right-enter-from { |
|||
transform: translateX(100%); |
|||
} |
|||
/* 进入动画的结束状态(也可以理解为激活状态) */ |
|||
.slide-right-enter-to { |
|||
transform: translateX(0); |
|||
} |
|||
/* 进入动画的过渡曲线等 */ |
|||
.slide-right-enter-active { |
|||
transition: transform 0.3s ease-in-out; |
|||
} |
|||
/* 离开动画的初始状态(激活状态) */ |
|||
.slide-right-leave-from { |
|||
transform: translateX(0); |
|||
} |
|||
/* 离开动画的结束状态 */ |
|||
.slide-right-leave-to { |
|||
transform: translateX(100%); |
|||
} |
|||
/* 离开动画的过渡曲线等 */ |
|||
.slide-right-leave-active { |
|||
transition: transform 0.3s ease-in-out; |
|||
} |
|||
</style> |
@ -0,0 +1,343 @@ |
|||
<script lang="ts" setup> |
|||
import SelectModal from 'components/common/SelectModal/index.vue' |
|||
import SoftKeyboard from 'components/common/SoftKeyboard/index.vue' |
|||
import { formulaNameMap } from 'libs/constant' |
|||
import { cloneDeep } from 'lodash' |
|||
import { onMounted, ref, watch, watchEffect } from 'vue' |
|||
|
|||
import { FtMessage } from '@/libs/message' |
|||
import { compareJSON, convertValuesToInt } from '@/libs/utils' |
|||
import { useFormulaStore } from '@/stores/formulaStore' |
|||
|
|||
const props = defineProps<{ |
|||
editable: boolean |
|||
}>() |
|||
const formulaStore = useFormulaStore() |
|||
|
|||
const targetInputRef = ref<HTMLInputElement | null>(null) |
|||
|
|||
/** |
|||
* 当前表单数据 |
|||
* 不同模式下有不同的初始值: |
|||
* - home: 当前选中的配方 |
|||
* - setting: 默认配方信息 |
|||
* - formula: 当前选中的配方或默认配方 |
|||
*/ |
|||
const formData = ref<Record<string, any>>({ |
|||
...formulaStore.defaultFormulaInfo, |
|||
}) |
|||
|
|||
/** |
|||
* 软键盘当前输入值 |
|||
*/ |
|||
const inputValue = ref<string>('') |
|||
|
|||
/** |
|||
* 软键盘是否可见 |
|||
*/ |
|||
const keyboardVisible = ref(false) |
|||
|
|||
/** |
|||
* 软键盘类型:'text' 或 'number' |
|||
*/ |
|||
const keyboardType = ref<'text' | 'number'>('number') |
|||
|
|||
/** |
|||
* 软键盘组件引用 |
|||
*/ |
|||
const softKeyboardRef = ref() |
|||
|
|||
/** |
|||
* 当前聚焦的输入字段名称 |
|||
*/ |
|||
const focusedInput = ref<string | null>(null) |
|||
|
|||
/** |
|||
* 日志级别选项列表 |
|||
*/ |
|||
const options = ref(formulaStore.logLevelOptions) |
|||
|
|||
/** |
|||
* 标签单位映射表,用于显示各参数的单位 |
|||
*/ |
|||
const labelUnitMap: Record<string, any> = formulaStore.labelUnitMap |
|||
/** |
|||
* 配方配置列表 |
|||
*/ |
|||
const formulaConfigList = ref(formulaStore.formulaConfigList) |
|||
/** |
|||
* 组件挂载时注册方法供父组件调用 |
|||
*/ |
|||
watchEffect(() => { |
|||
formData.value = cloneDeep(formulaStore.defaultFormulaInfo) |
|||
formData.value = convertValuesToInt(formData.value) |
|||
}) |
|||
/** |
|||
* 模态框是否打开 |
|||
*/ |
|||
const isModalOpen = ref(false) |
|||
|
|||
/** |
|||
* 打开模态框 |
|||
*/ |
|||
const openModal = () => { |
|||
isModalOpen.value = true |
|||
} |
|||
const currentFormulaItem = ref() |
|||
/** |
|||
* 监听软键盘输入值变化,更新表单数据 |
|||
* @param {string | number} newVal - 新的输入值 |
|||
*/ |
|||
watch(inputValue, (newVal: string | number) => { |
|||
if (focusedInput.value) { |
|||
newVal = Number(newVal) |
|||
if (currentFormulaItem.value && newVal > currentFormulaItem.value.val_upper_limit) { |
|||
newVal = currentFormulaItem.value.val_upper_limit |
|||
} |
|||
formData.value[focusedInput.value] = newVal |
|||
} |
|||
}) |
|||
/** |
|||
* 监听表单数据变化,同步更新软键盘输入值 |
|||
* @param {Record<string, any>} newValue - 新的表单数据 |
|||
*/ |
|||
watch( |
|||
formData, |
|||
(newValue) => { |
|||
if (focusedInput.value) { |
|||
inputValue.value = newValue[focusedInput.value].toString() |
|||
} |
|||
}, |
|||
{ deep: true }, |
|||
) |
|||
const formRef = ref(null) |
|||
// 挂载 |
|||
onMounted(() => { |
|||
formulaStore.getFormualDefaultData() |
|||
}) |
|||
/** |
|||
* 处理表单提交 |
|||
* 根据不同的type属性值执行不同的保存逻辑 |
|||
*/ |
|||
const handleSubmit = () => { |
|||
// 修改默认值 |
|||
const diff = compareJSON(formulaStore.defaultFormulaInfo, formData.value) |
|||
const diffKeys = Object.keys(diff) |
|||
if (diffKeys.length) { |
|||
Promise.all( |
|||
diffKeys.map(async (key) => { |
|||
await formulaStore.setSettingFormulaConfig(key, diff[key].newVal || diff[key].obj2) |
|||
}), |
|||
) |
|||
FtMessage.success('配方修改成功') |
|||
} |
|||
formulaStore.getFormualDefaultData() |
|||
} |
|||
/** |
|||
* 打开软键盘 |
|||
* @param {Event} e - 事件对象 |
|||
* @param item |
|||
*/ |
|||
const openKeyboard = (e: any, item: Formula.FormulaItem) => { |
|||
setTimeout(() => { |
|||
keyboardVisible.value = true |
|||
const labelName: string = e.target.name |
|||
openKeyboardType(labelName) |
|||
const formValue = formData.value[labelName] |
|||
inputValue.value = formValue.toString() |
|||
focusedInput.value = e.target.name |
|||
currentFormulaItem.value = item |
|||
|
|||
const inputDom = e.target as HTMLInputElement |
|||
targetInputRef.value = inputDom |
|||
}, 100) |
|||
} |
|||
/** |
|||
* 确认输入值 |
|||
* @param {string} value - 输入值 |
|||
*/ |
|||
const handleConfirm = (value: string) => { |
|||
console.log('确认输入:', value) |
|||
} |
|||
/** |
|||
* 确认日志级别选择 |
|||
* @param {any} value - 选择的值 |
|||
*/ |
|||
const handleLogConfirm = (value: any) => { |
|||
isModalOpen.value = false |
|||
formData.value.loglevel = value |
|||
formulaStore.updateLogLevel(value) |
|||
} |
|||
|
|||
/** |
|||
* 取消日志级别选择 |
|||
*/ |
|||
const handleLogCancel = () => { |
|||
isModalOpen.value = false |
|||
} |
|||
|
|||
/** |
|||
* 根据标签名称确定软键盘类型 |
|||
* @param {string} labelName - 标签名称 |
|||
*/ |
|||
const openKeyboardType = (labelName: string) => { |
|||
keyboardType.value = labelName === 'name' ? 'text' : 'number' |
|||
} |
|||
const size = 'default' |
|||
</script> |
|||
|
|||
<template> |
|||
<div class="formula-form"> |
|||
<el-form |
|||
ref="formRef" |
|||
:disabled="props.editable" |
|||
:model="formData" |
|||
label-width="auto" |
|||
label-position="right" |
|||
:size="size" |
|||
inline |
|||
> |
|||
<el-form-item |
|||
v-for="item in formulaConfigList" |
|||
:key="item.setting_id" |
|||
:label="formulaNameMap[item.setting_id]" |
|||
style="width: 50%" |
|||
> |
|||
<template v-if="item.is_visible_in_setting_page && item.val_type === 'int'"> |
|||
<el-input |
|||
v-model.number="formData[item.setting_id]" |
|||
v-prevent-keyboard |
|||
style="width: 80%" |
|||
type="number" |
|||
:name="item.setting_id" |
|||
:controls="false" |
|||
:disabled="!props.editable" |
|||
@focus="e => openKeyboard(e, item)" |
|||
> |
|||
<template v-if="labelUnitMap[item.setting_id]" #append> |
|||
{{ labelUnitMap[item.setting_id] }} |
|||
</template> |
|||
</el-input> |
|||
</template> |
|||
<template v-if="item.is_visible_in_setting_page && item.val_type === 'float'"> |
|||
<el-input |
|||
v-model.number="formData[item.setting_id]" |
|||
v-prevent-keyboard |
|||
style="width: 80%" |
|||
type="number" |
|||
:name="item.setting_id" |
|||
:controls="false" |
|||
:disabled="!props.editable" |
|||
@focus="e => openKeyboard(e, item)" |
|||
> |
|||
<template v-if="labelUnitMap[item.setting_id]" #append> |
|||
{{ labelUnitMap[item.setting_id] }} |
|||
</template> |
|||
</el-input> |
|||
</template> |
|||
<template v-else-if="item.is_visible_in_setting_page && item.val_type === 'enum'"> |
|||
<el-input |
|||
v-model="formData[item.setting_id]" |
|||
v-prevent-keyboard |
|||
style="width: 80%" |
|||
placeholder="请选择" |
|||
readonly |
|||
:disabled="!props.editable" |
|||
@focus="openModal" |
|||
> |
|||
<template #append> |
|||
{{ labelUnitMap[item.setting_id] }} |
|||
</template> |
|||
</el-input> |
|||
</template> |
|||
</el-form-item> |
|||
</el-form> |
|||
<div :style="{ marginLeft: '33%' }"> |
|||
<slot name="formulaBtn"> |
|||
<div class="default-btn"> |
|||
<el-button v-if="editable" type="primary" class="config-btn" @click="handleSubmit"> |
|||
确定 |
|||
</el-button> |
|||
</div> |
|||
</slot> |
|||
</div> |
|||
<Teleport to="body"> |
|||
<SoftKeyboard |
|||
ref="softKeyboardRef" |
|||
v-model="inputValue" |
|||
:is-visible="keyboardVisible" |
|||
:keyboard-type="keyboardType" |
|||
:target-input="targetInputRef" |
|||
@confirm="handleConfirm" |
|||
@update-keyboard-visible="visible => (keyboardVisible = visible)" |
|||
@close="keyboardVisible = false" |
|||
/> |
|||
</Teleport> |
|||
<SelectModal |
|||
v-if="isModalOpen" |
|||
:options="options" |
|||
:selected-value="formData.loglevel" |
|||
placeholder="请选择" |
|||
@confirm="handleLogConfirm" |
|||
@cancel="handleLogCancel" |
|||
/> |
|||
</div> |
|||
</template> |
|||
|
|||
<style lang="scss" scoped> |
|||
.formula-form { |
|||
font-size: 20px !important; |
|||
padding: 5px; |
|||
padding-left: 15px; |
|||
align-items: center; |
|||
.default-btn { |
|||
margin-top: 1rem; |
|||
} |
|||
.config-btn { |
|||
height: 3rem; |
|||
width: 8rem; |
|||
} |
|||
} |
|||
|
|||
.formula-form-item { |
|||
display: grid; |
|||
grid-template-columns: 1fr 1fr; |
|||
} |
|||
|
|||
.formData-input-config { |
|||
width: 10vw; |
|||
} |
|||
:deep(.el-input__inner) { |
|||
text-align: left; |
|||
height: 40px; |
|||
} |
|||
:deep(.el-form-item) { |
|||
margin-right: 0; |
|||
align-items: center; |
|||
} |
|||
|
|||
/* 进入动画的初始状态 */ |
|||
.slide-right-enter-from { |
|||
transform: translateX(100%); |
|||
} |
|||
/* 进入动画的结束状态(也可以理解为激活状态) */ |
|||
.slide-right-enter-to { |
|||
transform: translateX(0); |
|||
} |
|||
/* 进入动画的过渡曲线等 */ |
|||
.slide-right-enter-active { |
|||
transition: transform 0.3s ease-in-out; |
|||
} |
|||
/* 离开动画的初始状态(激活状态) */ |
|||
.slide-right-leave-from { |
|||
transform: translateX(0); |
|||
} |
|||
/* 离开动画的结束状态 */ |
|||
.slide-right-leave-to { |
|||
transform: translateX(100%); |
|||
} |
|||
/* 离开动画的过渡曲线等 */ |
|||
.slide-right-leave-active { |
|||
transition: transform 0.3s ease-in-out; |
|||
} |
|||
</style> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue