<template>
<div class="modal" v-if="model">
<div class="modal-content">
<div class="modal-header">
<h3>编辑模型: {{ model.name }}</h3>
<button class="close-btn" @click="$emit('close')">×</button>
</div>
<!-- 添加配置选择页 -->
<div class="add-config-selector">
<button
class="selector-btn"
:class="{ active: activeTab === 'variable' }"
@click="activeTab = 'variable'"
>
添加变量组
</button>
<button
class="selector-btn"
:class="{ active: activeTab === 'algorithm' }"
@click="activeTab = 'algorithm'"
>
添加算法
</button>
</div>
<!-- 变量组配置 -->
<div v-if="activeTab === 'variable'" class="config-section variable-group">
<div class="section-header">
<span class="section-icon">📊</span>
<h4>添加变量组配置</h4>
</div>
<div class="form-container">
<div class="form-item">
<label>选择变量组:</label>
<select v-model="newVariableGroup.name">
<option v-for="vg in availableVariableGroups" :key="vg.id" :value="vg.name">
{{ vg.name }} ({{ vg.variables.length }} 变量)
</option>
</select>
</div>
<div class="form-row">
<div class="form-item">
<label>执行周期 (秒):</label>
<input type="number" v-model="newVariableGroup.period" min="0.1" step="0.1" />
</div>
<div class="form-item">
<label>读取数据行数:</label>
<input type="number" v-model="newVariableGroup.rowLimit" min="1" max="10000" />
</div>
</div>
<button class="btn add-config-btn" @click="addVariableGroup">添加变量组</button>
</div>
</div>
<!-- 算法组配置 -->
<div v-if="activeTab === 'algorithm'" class="config-section algorithm-group">
<div class="section-header">
<span class="section-icon">⚙️</span>
<h4>添加算法配置</h4>
</div>
<div class="form-container">
<div class="form-item">
<label>选择算法脚本:</label>
<select v-model="newAlgorithm.name">
<option v-for="alg in availableAlgorithms" :key="alg.id" :value="alg.name">
{{ alg.name }} (v{{ alg.version }})
</option>
</select>
</div>
<div class="form-item">
<label>输入变量:</label>
<div class="variables-selection">
<select v-model="newAlgorithm.inputVariable">
<option v-for="vg in availableVariableGroups" :key="vg.id" :value="vg.name">
{{ vg.name }}
</option>
</select>
<button
class="add-variable-btn"
@click="addInputVariable"
:disabled="!newAlgorithm.inputVariable || binding.variableGroups.length === 0"
>
+
</button>
</div>
<div class="selected-variables">
<span v-for="(varName, index) in newAlgorithm.inputVariables" :key="index" class="variable-tag">
{{ varName }}
<span class="remove-tag" @click="removeInputVariable(index)">×</span>
</span>
<div v-if="newAlgorithm.inputVariables.length === 0" class="no-variables">
未添加变量组
</div>
</div>
</div>
<div class="form-row">
<div class="form-item">
<label>执行周期 (秒):</label>
<input type="number" v-model="newAlgorithm.period" min="0.1" step="0.1" />
</div>
<div class="form-item">
<label>读取数据行数:</label>
<input type="number" v-model="newAlgorithm.rowLimit" min="1" max="10000" />
</div>
</div>
<button class="btn add-config-btn" @click="addAlgorithm">添加算法</button>
</div>
</div>
<!-- 已添加配置项 -->
<div class="added-configs">
<!-- 已添加变量组 -->
<div v-if="binding.variableGroups.length > 0" class="config-section added-variable-group">
<div class="section-header">
<span class="section-icon">📊</span>
<h4>已添加变量组</h4>
</div>
<div v-for="(group, index) in binding.variableGroups" :key="index" class="config-item">
<div class="item-header">
<span>{{ group.name }}</span>
<button class="remove-btn" @click="removeVariableGroup(index)">×</button>
</div>
<div class="item-details">
<div>执行周期: {{ group.period }} 秒</div>
<div>读取行数: {{ group.rowLimit }} 行</div>
</div>
</div>
</div>
<!-- 已添加算法 -->
<div v-if="binding.algorithms.length > 0" class="config-section added-algorithm-group">
<div class="section-header">
<span class="section-icon">⚙️</span>
<h4>已添加算法</h4>
</div>
<div v-for="(algo, index) in binding.algorithms" :key="index" class="config-item">
<div class="item-header">
<span>{{ algo.name }}</span>
<button class="remove-btn" @click="removeAlgorithm(index)">×</button>
</div>
<div class="item-details">
<div>输入变量: {{ algo.inputVariables.join(', ') }}</div>
<div>执行周期: {{ algo.period }} 秒</div>
<div>读取行数: {{ algo.rowLimit }} 行</div>
</div>
</div>
</div>
</div>
<div class="buttons">
<button class="btn cancel-btn" @click="$emit('close')">取消</button>
<button class="btn save-btn" @click="save">保存配置</button>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue';
const props = defineProps<{
model: any;
}>();
const emit = defineEmits(['close', 'save']);
// 当前激活的配置页
const activeTab = ref<'variable' | 'algorithm'>('variable');
// 可用的变量组和算法(模拟数据)
const availableVariableGroups = ref([
{ id: 'vg1', name: '温度传感器', variables: ['temp1', 'temp2', 'temp3'] },
{ id: 'vg2', name: '压力传感器', variables: ['pressure1', 'pressure2'] },
{ id: 'vg3', name: '流量计', variables: ['flow1', 'flow2'] },
{ id: 'vg4', name: '阀门状态', variables: ['valve1', 'valve2', 'valve3'] },
]);
const availableAlgorithms = ref([
{ id: 'alg1', name: '温度预测模型', version: '1.2' },
{ id: 'alg2', name: '异常检测算法', version: '2.0' },
{ id: 'alg3', name: '优化控制策略', version: '1.5' },
{ id: 'alg4', name: '能效分析模型', version: '3.1' },
]);
// 绑定数据模型
const binding = reactive({
variableGroups: [] as Array<{
name: string;
period: number;
rowLimit: number;
}>,
algorithms: [] as Array<{
name: string;
period: number;
rowLimit: number;
inputVariables: string[];
}>,
});
// 新变量组配置
const newVariableGroup = reactive({
name: '',
period: 1,
rowLimit: 1000,
});
// 新算法配置
const newAlgorithm = reactive({
name: '',
period: 5,
rowLimit: 2000,
inputVariables: [] as string[],
inputVariable: '' // 当前选择的变量组
});
// 初始化绑定数据
onMounted(() => {
// 设置默认值
if (availableVariableGroups.value.length > 0) {
newVariableGroup.name = availableVariableGroups.value[0].name;
}
if (availableAlgorithms.value.length > 0) {
newAlgorithm.name = availableAlgorithms.value[0].name;
}
if (availableVariableGroups.value.length > 0) {
newAlgorithm.inputVariable = availableVariableGroups.value[0].name;
}
// 这里可以从props.model中加载现有配置
if (props.model?.config) {
// 实际项目中应根据模型数据初始化
binding.variableGroups = props.model.config.variableGroups || [];
binding.algorithms = props.model.config.algorithms || [];
}
});
// 添加变量组
const addVariableGroup = () => {
binding.variableGroups.push({ ...newVariableGroup });
// 重置表单
newVariableGroup.name = availableVariableGroups.value[0].name;
newVariableGroup.period = 1;
newVariableGroup.rowLimit = 1000;
// 切换到算法页
activeTab.value = 'algorithm';
};
// 移除变量组
const removeVariableGroup = (index: number) => {
binding.variableGroups.splice(index, 1);
// 从所有算法中移除该变量组引用
binding.algorithms.forEach(algo => {
const groupName = binding.variableGroups[index]?.name;
if (groupName) {
const idx = algo.inputVariables.indexOf(groupName);
if (idx !== -1) {
algo.inputVariables.splice(idx, 1);
}
}
});
};
// 添加输入变量
const addInputVariable = () => {
if (newAlgorithm.inputVariable &&
!newAlgorithm.inputVariables.includes(newAlgorithm.inputVariable)) {
newAlgorithm.inputVariables.push(newAlgorithm.inputVariable);
}
};
// 移除输入变量
const removeInputVariable = (index: number) => {
newAlgorithm.inputVariables.splice(index, 1);
};
// 添加算法
const addAlgorithm = () => {
if (newAlgorithm.inputVariables.length === 0) {
alert('请至少添加一个输入变量组');
return;
}
binding.algorithms.push({
name: newAlgorithm.name,
period: newAlgorithm.period,
rowLimit: newAlgorithm.rowLimit,
inputVariables: [...newAlgorithm.inputVariables]
});
// 重置表单
newAlgorithm.name = availableAlgorithms.value[0].name;
newAlgorithm.period = 5;
newAlgorithm.rowLimit = 2000;
newAlgorithm.inputVariables = [];
newAlgorithm.inputVariable = availableVariableGroups.value[0]?.name || '';
// 切换回变量组页
activeTab.value = 'variable';
};
// 移除算法
const removeAlgorithm = (index: number) => {
binding.algorithms.splice(index, 1);
};
// 保存配置
const save = () => {
// 实际项目中可能需要进行验证
if (binding.variableGroups.length === 0) {
alert('请至少添加一个变量组');
return;
}
if (binding.algorithms.length === 0) {
alert('请至少添加一个算法');
return;
}
// 验证所有算法至少选择了一个变量组
for (const algo of binding.algorithms) {
if (algo.inputVariables.length === 0) {
alert(`算法 "${algo.name}" 需要至少选择一个输入变量组`);
return;
}
}
emit('save', { ...binding });
emit('close');
};
</script>
<style scoped>
/* 基础样式保持不变,只添加新样式 */
/* 添加配置选择页 */
.add-config-selector {
display: flex;
background: #f1f5f9;
border-radius: 8px;
padding: 5px;
margin-bottom: 20px;
}
.selector-btn {
flex: 1;
padding: 12px;
background: transparent;
border: none;
border-radius: 6px;
cursor: pointer;
font-weight: 500;
transition: all 0.3s ease;
font-size: 1rem;
}
.selector-btn.active {
background: white;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
/* 表单容器 */
.form-container {
background: white;
border: 1px solid #e2e8f0;
border-radius: 8px;
padding: 20px;
margin-bottom: 20px;
}
/* 添加配置按钮 */
.add-config-btn {
background: #10b981;
color: white;
width: 100%;
padding: 12px;
margin-top: 15px;
font-size: 1rem;
font-weight: 500;
}
.add-config-btn:hover {
background: #059669;
}
/* 变量选择区域 */
.variables-selection {
display: flex;
gap: 10px;
margin-top: 5px;
}
.variables-selection select {
flex: 1;
}
.add-variable-btn {
background: #3b82f6;
color: white;
border: none;
border-radius: 6px;
width: 40px;
font-size: 1.2rem;
cursor: pointer;
transition: background 0.2s;
}
.add-variable-btn:hover {
background: #2563eb;
}
.add-variable-btn:disabled {
background: #94a3b8;
cursor: not-allowed;
}
/* 已选变量标签 */
.selected-variables {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: 10px;
min-height: 36px;
}
.variable-tag {
background: #dbeafe;
color: #1e40af;
padding: 6px 12px;
border-radius: 20px;
font-size: 0.9rem;
display: flex;
align-items: center;
gap: 5px;
}
.remove-tag {
cursor: pointer;
font-size: 1.2rem;
line-height: 1;
color: #ef4444;
}
.remove-tag:hover {
color: #dc2626;
}
/* 已添加配置项 */
.added-configs {
margin-top: 20px;
}
.config-item {
background: white;
border: 1px solid #e2e8f0;
border-radius: 8px;
padding: 15px;
margin-bottom: 15px;
transition: all 0.2s;
}
.config-item:hover {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
transform: translateY(-2px);
}
.item-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.item-header span {
font-weight: 600;
color: #1e293b;
font-size: 1rem;
}
.item-details {
color: #475569;
font-size: 0.9rem;
line-height: 1.6;
}
.item-details div {
margin-top: 5px;
}
/* 移除按钮样式 */
.remove-btn {
background: #fee2e2;
color: #ef4444;
border: none;
width: 28px;
height: 28px;
border-radius: 50%;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
font-size: 1.2rem;
}
.remove-btn:hover {
background: #fecaca;
}
/* 无变量提示 */
.no-variables {
color: #94a3b8;
font-style: italic;
font-size: 0.9rem;
padding: 8px 0;
}
</style>
这需要是一个弹框页面