feat: 操作以及指标

This commit is contained in:
zhanghao 2026-01-30 14:53:55 +08:00
parent a6aa3cc514
commit ad75493b3e
11 changed files with 229 additions and 121 deletions

View File

@ -0,0 +1,47 @@
import request from "@/utils/request";
// 查询根据层级指标库
export function getIndicatorByParentId(parentId) {
return request({
url: `/evaluate/indicator/getIndicatorByParentId/${parentId}`,
method: "get",
});
}
/**
* 新增指标
* @param {*} data
* @returns
*/
export function addIndicator(data) {
return request({
url: `/evaluate/indicator/indicator/insert`,
method: "post",
data
});
}
/**
* 删除指标
* @param {*} id
* @returns
*/
export function deleteIndicator(id) {
return request({
url: `/evaluate/indicator/${id}`,
method: "delete",
});
}
/**
* 修改指标
* @param {*} id
* @returns
*/
export function updateIndicator(data) {
return request({
url: `/evaluate/indicator`,
method: "put",
data
});
}

View File

@ -1,6 +1,6 @@
<!-- MetricCategory.vue - 一级指标组件 -->
<template>
<div class="metric-category">
<div class="metric-category" @click="activeCategory(category.id)" :class="{ activeCategory: activeId === category.id }">
<el-card class="category-card">
<div class="card-container">
<div class="category-info">
@ -19,12 +19,13 @@
<MetricForm
ref="metricFormRef"
:metric="editingCategory"
@submit="handleUpdateCategory"
:isNew="false"
@refresh="handleRefresh"
/>
<template #footer>
<span class="dialog-footer">
<el-button @click="showEditDialog = false">取消</el-button>
<el-button type="primary" @click="submitMetricForm">确认</el-button>
<el-button type="primary" @click="submitMetricForm">确认111</el-button>
</span>
</template>
</el-dialog>
@ -40,10 +41,15 @@ const props = defineProps({
category: {
type: Object,
required: true
},
// propsID//
activeId: {
type: [String, Number],
default: ''
}
})
const emit = defineEmits(['update-category', 'add-submetric', 'remove-category'])
const emit = defineEmits(['update-category', 'remove-category', 'active'])
const showEditDialog = ref(false)
const metricFormRef = ref(null)
@ -65,17 +71,22 @@ const submitMetricForm = () => {
}
}
const handleUpdateCategory = (metricData) => {
emit('update-category', {
...props.category,
...metricData
})
const handleRefresh = () => {
emit('refresh')
showEditDialog.value = false
}
const activeCategory = (categoryId) => {
//
console.log("点击了一级指标:", categoryId);
emit('active', categoryId) // ID
}
</script>
<style lang="scss" scoped>
.metric-category {
cursor: pointer;
.category-card {
border-radius: 8px;
@ -98,4 +109,9 @@ const handleUpdateCategory = (metricData) => {
}
}
.activeCategory {
border: 2px solid #409EFF;
border-radius: 8px;
}
</style>

View File

@ -15,15 +15,21 @@
<script setup>
import { ref, reactive } from 'vue'
import { addIndicator, updateIndicator } from '@/api/evaluate/indicator'
import { ElMessage } from 'element-plus'
const props = defineProps({
metric: {
type: Object,
required: true
},
isNew: {
type: Boolean,
required: true
}
})
const emit = defineEmits(['submit'])
const emit = defineEmits(['refresh'])
const formRef = ref(null)
@ -35,10 +41,25 @@ const rules = reactive({
const submitForm = () => {
if (!formRef.value) return
formRef.value.validate((valid) => {
formRef.value.validate(async (valid) => {
if (valid) {
emit('submit', { ...props.metric })
if (props.isNew) {
const res = await addIndicator({ name: props.metric.name, parentId: 0, level: 1 })
if (res.code === 200) {
ElMessage.success('指标添加成功')
emit('refresh')
} else {
ElMessage.error(res.message || '指标添加失败')
}
} else {
const res = await updateIndicator({ id: props.metric.id, name: props.metric.name })
if (res.code === 200) {
ElMessage.success('指标修改成功')
emit('refresh')
} else {
ElMessage.error(res.message || '指标修改失败')
}
}
}
})
}

View File

@ -1,7 +1,7 @@
<template>
<div class="evaluation-metrics">
<div class="left">
<Indicator />
<Indicator @activeMetricCategory="handleActiveMetricCategory" />
</div>
<div class="right">
<div class="title">
@ -11,8 +11,8 @@
添加二级指标
</el-button>
</div>
<div class="secondaryIndicator-container">
<SecondaryIndicator v-for="value in 3" />
<div class="secondaryIndicator-container" v-if="listData.length > 0">
<SecondaryIndicator v-for="value in listData" :key="value.id" :title="value.title" :weight="value.weight" />
</div>
</div>
</div>
@ -21,7 +21,35 @@
<script setup>
import Indicator from './indicator.vue';
import SecondaryIndicator from './secondaryIndicator.vue';
import { getIndicatorByParentId } from "@/api/evaluate/indicator";
const activeIndicatorId = ref(null);
const listData = ref([])
/**
*
{ id: 1, title: '无噪声唤醒', weight: 30 },
{ id: 2, title: '有噪声唤醒', weight: 40 },
{ id: 3, title: '免唤醒', weight: 50 },
{ id: 4, title: '误唤醒', weight: 30 }
*/
const handleActiveMetricCategory = (data) => {
activeIndicatorId.value = data;
getIndicatorByParentIdData(data);
};
const getIndicatorByParentIdData = async (parentId) => {
try {
const res = await getIndicatorByParentId(parentId);
if (res.code === 200) {
listData.value = res.data;
}
} catch (error) {
console.error("获取指标数据失败:", error);
}
};
</script>
<style lang="scss" scoped>

View File

@ -15,14 +15,15 @@
v-for="category in metricCategories"
:key="category.id"
:category="category"
@update-category="updateCategory"
@add-submetric="addSubmetric"
:active-id="activeCategoryId"
@active="activeCategory"
@refresh="handleRefresh"
@remove-category="removeCategory"
/>
</div>
<!-- 添加一级指标对话框 -->
<el-dialog v-model="showAddDialog" title="添加一级指标" width="500px">
<MetricForm ref="metricFormRef" :metric="newMetric" @submit="handleAddCategory" />
<MetricForm ref="metricFormRef" :isNew="true" :metric="newMetric" @refresh="handleRefresh" />
<template #footer>
<span class="dialog-footer">
<el-button @click="showAddDialog = false">取消</el-button>
@ -36,90 +37,54 @@
import { Plus } from "@element-plus/icons-vue";
import MetricCategory from "./components/MetricCategory.vue";
import MetricForm from "./components/MetricForm.vue";
import { getIndicatorByParentId, deleteIndicator } from "@/api/evaluate/indicator";
import { ElMessage, ElMessageBox } from "element-plus";
const emit = defineEmits(['activeMetricCategory'])
//
const metricCategories = ref([
{
id: 1,
name: "语音唤醒",
weight: 30,
subMetrics: [
{
id: 11,
name: "指挥名称:无噪声唤醒",
weight: 30,
},
],
},
{
id: 2,
name: "语音识别",
weight: 20,
subMetrics: [],
},
{
id: 3,
name: "智能交互",
weight: 20,
subMetrics: [],
},
{
id: 4,
name: "数据分析",
weight: 10,
subMetrics: [],
},
{
id: 5,
name: "能智能力",
weight: 50,
subMetrics: [
{
id: 51,
name: "情绪分析:免唤醒",
weight: 50,
},
],
},
]);
const metricCategories = ref([]);
const activeCategoryId = ref('')
const handleAddMetric = () => {
newMetric.name = "";
newMetric.weight = 0;
newMetric.subMetrics = [];
showAddDialog.value = true;
};
const updateCategory = (updatedCategory) => {
const index = metricCategories.value.findIndex((cat) => cat.id === updatedCategory.id);
if (index !== -1) {
metricCategories.value[index] = updatedCategory;
}
};
const addSubmetric = (categoryId, submetric) => {
const category = metricCategories.value.find((cat) => cat.id === categoryId);
if (category) {
category.subMetrics.push({
id: Date.now(),
...submetric,
});
}
};
const removeCategory = (categoryId) => {
const index = metricCategories.value.findIndex((cat) => cat.id === categoryId);
if (index !== -1) {
metricCategories.value.splice(index, 1);
console.log("-----------",categoryId)
ElMessageBox.confirm(
"确定要删除该指标及其所有子指标吗?",
"删除确认",
{
confirmButtonText: "确认",
cancelButtonText: "取消",
type: "warning",
}
).then(async () => {
try {
const res = await deleteIndicator(categoryId);
if (res.code === 200) {
ElMessage.success("指标删除成功");
getIndicatorByParentIdData(0);
} else {
ElMessage.error(res.message || "指标删除失败");
}
} catch (error) {
console.error("删除指标失败:", error);
ElMessage.error("删除指标失败");
}
}).catch(() => {
//
});
};
const showAddDialog = ref(false);
const metricFormRef = ref(null);
const newMetric = reactive({
name: "",
weight: 0,
subMetrics: [],
name: ""
});
const submitMetricForm = () => {
@ -128,14 +93,32 @@ const submitMetricForm = () => {
}
};
const handleAddCategory = (metricData) => {
const newCategory = {
id: Date.now(),
...metricData,
};
metricCategories.value.push(newCategory);
const handleRefresh = () => {
getIndicatorByParentIdData(0);
showAddDialog.value = false;
};
const getIndicatorByParentIdData = async (parentId) => {
try {
const res = await getIndicatorByParentId(parentId);
if (res.code === 200) {
metricCategories.value = res.data;
emit('activeMetricCategory', res.data[0]?.id || null)
activeCategoryId.value = res.data[0]?.id || null;
}
} catch (error) {
console.error("获取指标数据失败:", error);
}
};
const activeCategory = (data) => {
activeCategoryId.value = data;
emit('activeMetricCategory', data); //
};
onMounted(() => {
getIndicatorByParentIdData(0); //
});
</script>
<style lang="scss" scoped>
.container {

View File

@ -4,9 +4,9 @@
<div class="title-container">
<div class="title-left">
<el-tag>二级指标</el-tag>
<div class="title">指标名称:<span class="text">无噪声唤醒</span></div>
<div class="title">指标名称:<span class="text">{{ props.title }}</span></div>
</div>
<div>指标权重:30.00%</div>
<div>指标权重:{{ props.weight }}%</div>
<div>
<el-button size="small" :icon="Edit" />
<el-button size="small" type="danger" :icon="Delete" />
@ -31,6 +31,18 @@
<script setup>
import { Delete, Edit } from "@element-plus/icons-vue";
import ScoreTable from "./components/ScoreTable.vue";
const props = defineProps({
title: {
type: String,
default: "无噪声唤醒",
},
weight: {
type: Number,
default: 30,
},
});
const activeTab = ref('1');
const tabList = ref([

View File

@ -12,7 +12,7 @@
</el-button>
</div>
<div class="secondaryIndicator-container">
<SecondaryIndicator v-for="value in 3" />
<SecondaryIndicator v-for="value in listData" :key="value.id" :title="value.title" :weight="value.weight" />
</div>
</div>
</div>
@ -22,6 +22,13 @@
import Indicator from './indicator.vue';
import SecondaryIndicator from './secondaryIndicator.vue';
const listData = ref([
{ id: 1, title: '无噪声唤醒', weight: 30 },
{ id: 2, title: '有噪声唤醒', weight: 40 },
{ id: 3, title: '免唤醒', weight: 50 },
{ id: 4, title: '误唤醒', weight: 30 }
])
</script>
<style lang="scss" scoped>

View File

@ -62,25 +62,7 @@ const metricCategories = ref([
name: "智能交互",
weight: 20,
subMetrics: [],
},
{
id: 4,
name: "数据分析",
weight: 10,
subMetrics: [],
},
{
id: 5,
name: "能智能力",
weight: 50,
subMetrics: [
{
id: 51,
name: "情绪分析:免唤醒",
weight: 50,
},
],
},
}
]);
const handleAddMetric = () => {

View File

@ -4,9 +4,9 @@
<div class="title-container">
<div class="title-left">
<el-tag>二级指标</el-tag>
<div class="title">指标名称:<span class="text">无噪声唤醒</span></div>
<div class="title">指标名称:<span class="text">{{ props.title }}</span></div>
</div>
<div>指标权重:30.00%</div>
<div>指标权重:{{ props.weight }}%</div>
<div>
<el-button size="small" :icon="Edit" />
<el-button size="small" type="danger" :icon="Delete" />
@ -31,6 +31,18 @@
<script setup>
import { Delete, Edit } from "@element-plus/icons-vue";
import ScoreTable from "./components/ScoreTable.vue";
const props = defineProps({
title: {
type: String,
default: "无噪声唤醒",
},
weight: {
type: Number,
default: 30,
},
});
const activeTab = ref('1');
const tabList = ref([

View File

@ -285,7 +285,7 @@ export const collapseList = [
action: 'MICROPHONE_START',
nodeType: 'EDGE',
nodeParams: [
{ name: "deviceId", type: "input", input: "", componentType: 'select', selectOptions: deviceOptions(), disabled: true }
{ name: "deviceId", type: "input", input: "", componentType: 'select', selectOptions: audioOptions(), disabled: true }
],
outputType: 'json'
},
@ -297,7 +297,7 @@ export const collapseList = [
action: 'MICROPHONE_START',
nodeType: 'EDGE',
nodeParams: [
{ name: "deviceId", type: "input", input: "", componentType: 'select', selectOptions: deviceOptions(), disabled: true }
{ name: "deviceId", type: "input", input: "", componentType: 'select', selectOptions: audioOptions(), disabled: true }
],
outputType: 'json'
},

View File

@ -36,7 +36,7 @@ export default defineConfig(({mode, command}) => {
//赵 http://10.148.108.58:13080
// dev http://10.148.20.34:13080
// target: VITE_API_URL,
target: command === 'build' ? VITE_API_URL : 'http://192.168.0.10:13080',
target: command === 'build' ? VITE_API_URL : 'http://192.168.0.21:13081',
changeOrigin: true,
rewrite: (p) => p.replace(/^\/dev-api/, '')
}