Files
ccdi/ruoyi-ui/src/views/ccdiProject/components/detail/ParamConfig.vue

320 lines
8.0 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>
<div class="param-config-container" v-loading="loading" element-loading-text="加载中...">
<div v-if="isProjectTagging" class="readonly-tip">
项目正在进行银行流水打标参数暂不可修改
</div>
<!-- 模型参数卡片组垂直堆叠 -->
<div class="model-cards-container" v-if="!loading && modelGroups.length > 0">
<div
v-for="model in modelGroups"
:key="model.modelCode"
class="model-card"
>
<!-- 模型标题 -->
<div class="model-header">
<h3>{{ model.modelName }}</h3>
</div>
<!-- 参数表格 -->
<el-table :data="model.params" border style="width: 100%">
<el-table-column label="监测项" prop="paramName" width="200" />
<el-table-column label="描述" prop="paramDesc" />
<el-table-column label="阈值设置" width="200">
<template #default="{ row }">
<el-input
v-model="row.paramValue"
:disabled="isProjectTagging"
placeholder="请输入阈值"
@input="markAsModified(model.modelCode, row)"
/>
</template>
</el-table-column>
<el-table-column label="单位" prop="paramUnit" width="120" />
</el-table>
</div>
</div>
<!-- 空状态 -->
<div class="empty-state" v-if="!loading && modelGroups.length === 0">
<el-empty description="暂无参数配置数据"></el-empty>
</div>
<!-- 统一保存按钮 -->
<div class="button-section" v-if="!loading && modelGroups.length > 0">
<el-button type="primary" :disabled="isProjectTagging || saving" @click="handleSaveAll" :loading="saving">
保存所有修改
</el-button>
<span v-if="modifiedCount > 0" class="modified-tip">
已修改 {{ modifiedCount }} 个参数
</span>
</div>
</div>
</template>
<script>
import { listAllParams, saveAllParams } from "@/api/ccdi/modelParam";
export default {
name: 'ParamConfig',
props: {
projectId: {
type: [String, Number],
required: true
},
projectInfo: {
type: Object,
default: () => ({})
}
},
data() {
return {
modelGroups: [],
modifiedParams: {},
originalParamValues: {},
loading: false,
saving: false
}
},
computed: {
modifiedCount() {
return Object.keys(this.modifiedParams).length;
},
isProjectTagging() {
return String(this.projectInfo.projectStatus) === "3";
}
},
watch: {
projectId(newVal) {
if (newVal) {
this.loadAllParams();
} else {
this.modelGroups = [];
this.modifiedParams = {};
this.originalParamValues = {};
}
}
},
created() {
if (this.projectId) {
this.loadAllParams();
}
},
methods: {
buildModifiedKey(modelCode, paramCode) {
return `${modelCode}:${paramCode}`
},
normalizeParamValue(value) {
return value === null || value === undefined ? '' : String(value)
},
normalizeModelGroups(models) {
if (!Array.isArray(models)) {
return []
}
return models.map(model => ({
...model,
params: Array.isArray(model.params) ? model.params : []
}))
},
resetModifiedState() {
this.modifiedParams = {}
this.originalParamValues = {}
this.modelGroups.forEach(model => {
model.params.forEach(row => {
const key = this.buildModifiedKey(model.modelCode, row.paramCode)
this.$set(this.originalParamValues, key, this.normalizeParamValue(row.paramValue))
})
})
},
async loadAllParams() {
this.loading = true;
try {
const res = await listAllParams({ projectId: this.projectId });
this.modelGroups = this.normalizeModelGroups(res.data && res.data.models);
this.resetModifiedState();
} catch (error) {
this.$message.error('加载参数失败:' + error.message);
console.error('加载参数失败', error);
} finally {
this.loading = false;
}
},
markAsModified(modelCode, row) {
const modifiedKey = this.buildModifiedKey(modelCode, row.paramCode);
const currentValue = this.normalizeParamValue(row.paramValue);
const originalValue = this.originalParamValues[modifiedKey];
if (currentValue === originalValue) {
if (this.modifiedParams[modifiedKey]) {
this.$delete(this.modifiedParams, modifiedKey);
}
return;
}
this.$set(this.modifiedParams, modifiedKey, {
modelCode,
paramCode: row.paramCode,
paramValue: row.paramValue
});
},
async handleSaveAll() {
if (this.isProjectTagging) {
this.$message.warning("项目正在进行银行流水打标,参数暂不可修改");
return;
}
if (this.modifiedCount === 0) {
this.$message.info('没有需要保存的修改');
return;
}
const modelMap = {};
Object.values(this.modifiedParams).forEach(item => {
if (!modelMap[item.modelCode]) {
modelMap[item.modelCode] = {
modelCode: item.modelCode,
params: []
};
}
modelMap[item.modelCode].params.push({
paramCode: item.paramCode,
paramValue: item.paramValue
});
});
const saveDTO = {
projectId: this.projectId,
models: Object.values(modelMap)
};
try {
await this.$confirm(
'保存参数后将进行项目内流水重新打标,是否继续?',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
)
} catch (error) {
return
}
this.saving = true;
try {
await saveAllParams(saveDTO);
this.$modal.msgSuccess('保存成功,已开始项目内流水重新打标');
await this.loadAllParams();
this.$emit('refresh-project');
} catch (error) {
if (error.response && error.response.data && error.response.data.msg) {
this.$message.error('保存失败:' + error.response.data.msg);
} else {
this.$message.error('保存失败:' + error.message);
}
console.error('保存失败', error);
} finally {
this.saving = false;
}
}
}
}
</script>
<style scoped lang="scss">
.param-config-container {
padding: 20px;
background-color: #fff;
min-height: 400px;
}
.readonly-tip {
margin-bottom: 16px;
padding: 12px 16px;
color: #ad6800;
background: #fff7e6;
border: 1px solid #ffd591;
border-radius: 6px;
}
.model-cards-container {
margin-bottom: 20px;
min-height: 300px;
padding-bottom: 92px;
}
.model-card {
background: #fff;
border-radius: 4px;
padding: 20px;
margin-bottom: 20px;
border: 1px solid #e4e7ed;
.model-header {
margin-bottom: 15px;
h3 {
font-size: 16px;
font-weight: bold;
color: #333;
margin: 0;
}
}
}
.empty-state {
padding: 40px;
text-align: center;
background: #fff;
border-radius: 4px;
}
.button-section {
position: sticky;
bottom: 0;
z-index: 20;
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: 12px 16px;
margin-top: 24px;
padding: 16px 20px;
padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px));
background: rgba(255, 255, 255, 0.96);
border-top: 1px solid #ebeef5;
border-radius: 12px 12px 0 0;
box-shadow: 0 -6px 18px rgba(0, 0, 0, 0.08);
text-align: left;
.el-button {
flex-shrink: 0;
}
.modified-tip {
color: #909399;
font-size: 14px;
line-height: 1.5;
}
}
@media (max-width: 768px) {
.param-config-container {
padding: 16px;
}
.model-cards-container {
padding-bottom: 104px;
}
.button-section {
padding: 14px 16px;
padding-bottom: calc(14px + env(safe-area-inset-bottom, 0px));
.el-button {
width: 100%;
}
}
}
</style>