Browse Source

feat: Refactor model list components and API integration

- Updated ModelItem interface to include createTime property.
- Refactored index.vue to improve code readability and structure.
- Enhanced Step1.vue to handle form submission and validation.
- Simplified Step2.vue and Step3.vue for better data handling and user experience.
- Removed Step5.vue as it was redundant.
- Introduced new API models and methods for better data management.
- Updated form schemas for steps to reflect new requirements and improve validation logic.
- Improved styling and layout for better user interface consistency.
pull/22/head
Jiale 8 months ago
parent
commit
345158e8ad
  1. 7
      .vscode/settings.json
  2. 15162
      pnpm-lock.yaml
  3. 38
      src/api/alert/model/model/models.ts
  4. 31
      src/api/alert/model/model/optionsModel.ts
  5. 33
      src/api/alert/model/models.ts
  6. 42
      src/api/alert/model/select.ts
  7. 4
      src/utils/http/axios/Axios.ts
  8. 156
      src/views/model/list/CreateModel.vue
  9. 119
      src/views/model/list/ModelCard.vue
  10. 171
      src/views/model/list/UnitSelect.vue
  11. 25
      src/views/model/list/data.tsx
  12. 51
      src/views/model/list/index.vue
  13. 75
      src/views/model/list/step/Step1.vue
  14. 106
      src/views/model/list/step/Step2.vue
  15. 182
      src/views/model/list/step/Step3.vue
  16. 224
      src/views/model/list/step/Step4.vue
  17. 62
      src/views/model/list/step/Step5.vue
  18. 114
      src/views/model/list/step/data.tsx

7
.vscode/settings.json

@ -94,10 +94,10 @@
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "rvest.vs-code-prettier-eslint"
"editor.defaultFormatter": "vscode.typescript-language-features"
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
"editor.defaultFormatter": "vscode.typescript-language-features"
},
"[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
@ -119,7 +119,8 @@
"source.fixAll.eslint": "explicit",
"source.organizeImports": "never",
"source.fixAll.stylelint": "explicit"
}
},
"editor.defaultFormatter": "stylelint.vscode-stylelint"
},
"i18n-ally.localesPaths": ["src/locales/lang"],
"i18n-ally.keystyle": "nested",

15162
pnpm-lock.yaml

File diff suppressed because it is too large

38
src/api/alert/model/model/models.ts

@ -0,0 +1,38 @@
export interface ModelCardItem {
id: number
name: string
status: number
algorithm: string
creator: string
createTime: string
}
interface MovingWindows {
windowLength: number
samplingInterval: number
movingSpeed: number
}
export interface ModelInfo {
id: number
btmState: string
unitID: string
createName: string
createTime: string
modelName: string
movingWindows: MovingWindows
steadyPoint: any[]
targetParameter: any
relationParameter: any[]
boundaryParameter: any[]
}
export interface ModelQueryParams {
unitId: number
typeId: number
systemId: number
name?: string | null
status?: number | null
visible?: number | null
trash?: number | null
}

31
src/api/alert/model/model/optionsModel.ts

@ -0,0 +1,31 @@
import { BasicFetchResult } from '/@/api/model/baseModel';
export interface OptionsItem {
id: number;
name: string;
}
export interface AllOptionsItem {
units: OptionsItem[];
types: OptionsItem[];
systems: OptionsItem[];
}
export interface DemoOptionsItem {
name: string;
id: string;
}
export interface selectParams {
id: number | string;
}
export interface systemSelectParams {
unitId: number | null;
typeId: number | null;
}
/**
* @description: Request list return value
*/
export type DemoOptionsGetResultModel = BasicFetchResult<DemoOptionsItem>;

33
src/api/alert/model/models.ts

@ -0,0 +1,33 @@
import type { ModelCardItem, ModelInfo, ModelQueryParams } from './model/models'
import { defHttp } from '@/utils/http/axios'
enum Api {
MODEL_CARD_LIST = '/alert/model/card/list',
MODEL_INFO = '/alert/model/info/',
MODEL_SAVE = '/alert/model/',
MODEL_DATA = '/alert/model/data/',
CALCULATE_BACK = '/alert/model/data/calculate/',
OPTIMISTIC = '/alert/optimistic',
}
export function modelCardListApi(params?: ModelQueryParams) {
return defHttp.get<ModelCardItem[]>({ url: Api.MODEL_CARD_LIST, params })
}
export const modelInfoApi = (id: any) => defHttp.get<ModelInfo>({ url: Api.MODEL_INFO + id })
export function updateModelInfo(params: any) {
return defHttp.patch<boolean>({ url: Api.MODEL_INFO, params })
}
export function modelSaveApi(params?: any) {
return defHttp.post<number>({ url: Api.MODEL_SAVE, data: params })
}
export function modelDataApi(id: any, params: any) {
return defHttp.get<any>({ url: Api.MODEL_DATA + id, params })
}
export function calculateBackApi(id: any, params: any) {
return defHttp.post<boolean>({ url: Api.CALCULATE_BACK + id, params })
}
export const getOptimisticApi = (params: any) => defHttp.get<any>({ url: Api.OPTIMISTIC, params })

42
src/api/alert/model/select.ts

@ -0,0 +1,42 @@
import type {
AllOptionsItem,
DemoOptionsItem,
OptionsItem,
selectParams,
systemSelectParams,
} from './model/optionsModel'
import { defHttp } from '@/utils/http/axios'
enum Api {
LIST = '/alert/select/list',
UNIT_LIST = '/alert/select/unit/options',
SYSTEM_LIST = '/alert/select/system/options',
POINT_LIST = '/alert/select/point/options',
}
export const optionListApi = () => defHttp.get<AllOptionsItem>({ url: Api.LIST })
/**
* @description:
*/
export function unitListApi(params?: selectParams) {
return defHttp.get<DemoOptionsItem[]>({ url: Api.UNIT_LIST, params })
}
/**
* @description:
*/
export function systemListApi(params?: selectParams) {
return defHttp.get<DemoOptionsItem[]>({ url: Api.UNIT_LIST, params })
}
/**
* @description:
*/
export function subSystemListApi(params?: systemSelectParams) {
return defHttp.get<OptionsItem[]>({ url: Api.SYSTEM_LIST, params })
}
export function pointListApi(params?: string) {
return defHttp.get<OptionsItem[]>({ url: Api.POINT_LIST, params })
}

4
src/utils/http/axios/Axios.ts

@ -251,6 +251,10 @@ export class VAxios {
return this.request({ ...config, method: 'GET' }, options)
}
patch<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> {
return this.request({ ...config, method: 'PATCH' }, options)
}
post<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> {
return this.request({ ...config, method: 'POST' }, options)
}

156
src/views/model/list/CreateModel.vue

@ -1,54 +1,12 @@
<template>
<BasicDrawer :isDetail="true" title="新建模型">
<PageWrapper title="新建模型" contentBackground contentClass="p-4">
<div class="step-form-form">
<a-steps :current="current">
<a-step title="填写基本信息" />
<a-step title="目标参数选择" />
<a-step title="边界参数选择" />
<a-step title="相关参数选择" />
<a-step title="完成" />
</a-steps>
</div>
<div class="mt-5">
<Step1 @next="handleStep1Next" v-show="current === 0" />
<Step2
:beforeData="step1Data"
@prev="handleStepPrev"
@next="handleStep2Next"
v-show="current === 1"
v-if="initStep2"
/>
<Step3
:beforeData="step2Data"
@prev="handleStepPrev"
@next="handleStep3Next"
v-show="current === 2"
v-if="initStep3"
/>
<Step4
:beforeData="step3Data"
:systemId="systemId"
@prev="handleStepPrev"
@next="handleStep4Next"
v-show="current === 3"
v-if="initStep4"
/>
<Step5 :modelId="step4Data" v-show="current === 4" @redo="handleRedo" v-if="initStep5" />
</div>
</PageWrapper>
</BasicDrawer>
</template>
<script lang="ts">
import { defineComponent, ref, reactive, toRefs } from 'vue';
import { BasicDrawer } from '/@/components/Drawer';
import { PageWrapper } from '/@/components/Page';
import { Steps } from 'ant-design-vue';
import Step1 from './step/Step1.vue';
import Step2 from './step/Step2.vue';
import Step3 from './step/Step3.vue';
import Step4 from './step/Step4.vue';
import Step5 from './step/Step5.vue';
import { defineComponent, reactive, ref, toRefs } from 'vue'
import { Steps } from 'ant-design-vue'
import Step1 from './step/Step1.vue'
import Step2 from './step/Step2.vue'
import Step3 from './step/Step3.vue'
import Step4 from './step/Step4.vue'
import { PageWrapper } from '@/components/Page'
import { BasicDrawer } from '@/components/Drawer'
export default defineComponent({
components: {
@ -56,7 +14,6 @@
Step2,
Step3,
Step4,
Step5,
BasicDrawer,
PageWrapper,
[Steps.name]: Steps,
@ -67,53 +24,54 @@
type: Number,
},
},
setup() {
const current = ref(0);
const step1Data = ref(null);
const step2Data = ref(null);
const step3Data = ref(null);
const step4Data = ref(null);
setup(props) {
const current = ref(0)
const step1Data = ref(null)
const step2Data = ref(null)
const step3Data = ref(null)
const step4Data = ref(null)
const state = reactive({
initStep2: false,
initStep3: false,
initStep4: false,
initStep5: false,
});
})
function handleStep1Next(step1Values: any) {
current.value++;
console.log(step1Values);
step1Data.value = step1Values;
state.initStep2 = true;
current.value++
console.log(step1Values)
step1Data.value = step1Values
state.initStep2 = true
}
function handleStepPrev() {
current.value--;
current.value--
}
function handleStep2Next(step2Values: any) {
current.value++;
step2Data.value = step2Values;
console.log(step2Values);
state.initStep3 = true;
current.value++
step2Data.value = step2Values
step2Values.systemId = props.systemId
console.log(step2Values)
state.initStep3 = true
}
function handleStep3Next(step3Values: any) {
current.value++;
step3Data.value = step3Values;
console.log(step3Values);
state.initStep4 = true;
current.value++
step3Data.value = step3Values
console.log(step3Values)
state.initStep4 = true
}
function handleStep4Next(step4Values: any) {
current.value++;
step4Data.value = step4Values;
console.log(step4Values);
state.initStep5 = true;
current.value++
step4Data.value = step4Values
console.log(step4Values)
state.initStep5 = true
}
function handleRedo() {
current.value = 0;
state.initStep2 = false;
state.initStep3 = false;
state.initStep4 = false;
state.initStep5 = false;
current.value = 0
state.initStep2 = false
state.initStep3 = false
state.initStep4 = false
state.initStep5 = false
}
return {
step1Data,
@ -128,10 +86,44 @@
handleStep3Next,
handleStep4Next,
...toRefs(state),
};
}
},
});
})
</script>
<template>
<BasicDrawer :is-detail="true" title="新建模型">
<PageWrapper title="新建模型" content-background content-class="p-4">
<div class="step-form-form">
<a-steps :current="current">
<a-step title="填写基本信息" />
<a-step title="算法参数配置" />
<a-step title="数据源选取" />
<a-step title="完成" />
</a-steps>
</div>
<div class="mt-5">
<Step1 v-show="current === 0" @next="handleStep1Next" />
<Step2
v-show="current === 1"
v-if="initStep2"
:before-data="step1Data"
@prev="handleStepPrev"
@next="handleStep2Next"
/>
<Step3
v-show="current === 2"
v-if="initStep3"
:before-data="step2Data"
@prev="handleStepPrev"
@next="handleStep3Next"
/>
<Step4 v-show="current === 3" v-if="initStep4" :model-id="step3Data" @redo="handleRedo" />
</div>
</PageWrapper>
</BasicDrawer>
</template>
<style lang="less" scoped>
.step-form-content {
padding: 24px;

119
src/views/model/list/ModelCard.vue

@ -1,43 +1,14 @@
<template>
<div class="grid md:grid-cols-4 gap-4">
<template v-for="item in modelCardList" :key="item.title">
<Card
size="small"
:loading="loading"
:title="item.title"
:hoverable="true"
:bodyStyle="item.bodyStyle"
:headStyle="item.headStyle"
@click="changeModel(item.id)"
>
<template #extra>
<Icon :icon="item.icon" :size="30" color="white" />
</template>
<div class="p-2 px-5 grid md:grid-cols-3">
<span>创建人: {{ item.creator }}</span
><span>创建时间: {{ item.creator }}</span
><span>模型状态: {{ item.status }}</span>
</div>
</Card>
</template>
<Card size="small" class="icon-card" @click="openDrawer(true)" :hoverable="true"
><Icon icon="ic:sharp-add" :size="80" color="#a7a9a7"
/></Card>
</div>
<CreateModel @register="registerDraw" :systemId="systemId" />
</template>
<script lang="ts" setup>
import Icon from '@/components/Icon/Icon.vue';
import { Card } from 'ant-design-vue';
import { ModelItem } from './data';
import { modelCardListApi } from '/@/api/benchmark/models';
import { ModelQueryParams } from '/@/api/benchmark/model/models';
import { watch, ref, PropType } from 'vue';
import { useGo } from '/@/hooks/web/usePage';
import CreateModel from './CreateModel.vue';
import { useDrawer } from '/@/components/Drawer';
const [registerDraw, { openDrawer }] = useDrawer();
import { Card } from 'ant-design-vue'
import type { PropType } from 'vue'
import { ref, watch } from 'vue'
import type { ModelItem } from './data'
import CreateModel from './CreateModel.vue'
import Icon from '@/components/Icon/index'
import { modelCardListApi } from '@/api/alert/model/models'
import type { ModelQueryParams } from '@/api/alert/model/model/models'
import { useGo } from '@/hooks/web/usePage'
import { useDrawer } from '@/components/Drawer'
const props = defineProps({
loading: {
@ -49,18 +20,20 @@
systemId: {
type: Number,
},
});
})
const [registerDraw, { openDrawer }] = useDrawer()
//
const go = useGo();
const changeModel = (id) => {
go(`/model/train/${id}`);
};
const go = useGo()
function changeModel(id) {
go(`/model/train/${id}`)
}
const modelCardList = ref<Array<ModelItem>>([]);
const colors = ['#8dc63f', '#dbb09e'];
const statusStr = ['未下装', '已下装'];
const icons = ['material-symbols:lock-open-right-outline', 'material-symbols:lock-outline'];
const modelCardList = ref<Array<ModelItem>>([])
const colors = ['#8dc63f', '#dbb09e']
const statusStr = ['未下装', '已下装']
const icons = ['material-symbols:lock-open-right-outline', 'material-symbols:lock-outline']
watch(
() => props.selectData,
@ -70,9 +43,13 @@
typeId: value?.type,
systemId: value?.system,
name: value?.name,
};
const modelList = await modelCardListApi(queryParams);
const cardList: ModelItem[] = [];
}
const modelList = await modelCardListApi(queryParams)
if (!modelList) {
modelCardList.value = []
return
}
const cardList: ModelItem[] = []
for (const modelCard of modelList) {
// modelCard.status = 0;
const card: ModelItem = {
@ -83,7 +60,8 @@
total: 1,
color: colors[modelCard.status],
status: statusStr[modelCard.status],
creator: modelCard.creatName,
creator: modelCard.creator,
createTime: modelCard.createTime,
description: modelCard.name,
headStyle: {
backgroundColor: colors[modelCard.status],
@ -93,14 +71,43 @@
borderColor: colors[modelCard.status],
borderWidth: '1px',
},
};
cardList.push(card);
}
modelCardList.value = cardList;
cardList.push(card)
}
modelCardList.value = cardList
},
);
)
</script>
<template>
<div class="enter-y">
<div class="grid gap-4 md:grid-cols-4">
<template v-for="item in modelCardList" :key="item.title">
<Card
size="small"
:loading="loading"
:title="item.title"
:hoverable="true"
:body-style="item.bodyStyle"
:head-style="item.headStyle"
@click="changeModel(item.id)"
>
<template #extra>
<Icon :icon="item.icon" :size="30" color="white" />
</template>
<div class="grid p-2 px-5 md:grid-cols-3">
<span>创建人: {{ item.creator }}</span><span>创建时间: {{ item.createTime }}</span><span>模型状态: {{ item.status }}</span>
</div>
</Card>
</template>
<Card v-show="systemId != null" size="small" class="icon-card" :hoverable="true" @click="openDrawer(true)">
<Icon icon="ic:sharp-add" :size="80" color="#a7a9a7" />
</Card>
</div>
<CreateModel :system-id="systemId" @register="registerDraw" />
</div>
</template>
<style>
.icon-card {
display: flex;

171
src/views/model/list/UnitSelect.vue

@ -1,52 +1,8 @@
<template>
<a-form layout="inline" :model="formData" :label-col="labelCol" @finish="submitForm">
<a-col :md="5">
<a-form-item label="机组" name="unit">
<a-select
v-model:value="formData.unit"
style="width: 100%"
@change="onUnitChange"
:options="unitData.map((unit) => ({ value: unit.id, label: unit.name }))"
/>
</a-form-item>
</a-col>
<a-col :md="5">
<a-form-item label="系统" name="type">
<a-select
v-model:value="formData.type"
style="width: 100%"
@change="onTypeChange"
:options="typeData.map((type) => ({ value: type.id, label: type.name }))"
/>
</a-form-item>
</a-col>
<a-col :md="5">
<a-form-item label="子系统" name="system">
<a-select
v-model:value="formData.system"
style="width: 100%"
:options="systemData.map((system) => ({ value: system.id, label: system.name }))"
/>
</a-form-item>
</a-col>
<a-col :md="5">
<a-form-item name="name">
<a-input v-model:value="formData.name" style="width: 100%" />
</a-form-item>
</a-col>
<a-col :md="3">
<a-form-item>
<a-button type="primary" html-type="submit">查询</a-button>
</a-form-item>
</a-col>
</a-form>
<a-divider />
</template>
<script lang="ts">
import { ref, onMounted } from 'vue';
import { Form, Select, Button, Col, Divider } from 'ant-design-vue';
import { optionListApi, subSystemListApi } from '/@/api/benchmark/select';
import { systemSelectParams, OptionsItem } from '/@/api/benchmark/model/optionsModel';
import { onMounted, ref } from 'vue'
import { Button, Col, Divider, Form, Select } from 'ant-design-vue'
import { optionListApi, subSystemListApi } from '@/api/alert/model/select'
import type { OptionsItem, systemSelectParams } from '@/api/alert/model/model/optionsModel'
export default {
components: {
@ -59,69 +15,69 @@
},
emits: ['optionSelected'],
setup(props, context) {
let unitData = ref<OptionsItem[]>([]);
let typeData = ref<OptionsItem[]>([]);
let systemData = ref<OptionsItem[]>([]);
const unitData = ref<OptionsItem[]>([])
const typeData = ref<OptionsItem[]>([])
const systemData = ref<OptionsItem[]>([])
const formData = ref({
unit: -1,
type: -1,
system: -1,
name: null,
});
})
onMounted(async () => {
const optionList = await optionListApi();
unitData.value = optionList.units;
typeData.value = optionList.types;
systemData.value = optionList.systems;
const optionList = await optionListApi()
unitData.value = optionList.units
typeData.value = optionList.types
systemData.value = optionList.systems
formData.value = {
unit: unitData.value[0].id,
type: typeData.value[0].id,
system: systemData.value[0].id,
name: null,
};
if (unitData.value.length > 0) {
formData.value.unit = unitData.value[0].id;
}
if (typeData.value.length > 0) {
formData.value.type = typeData.value[0].id;
}
if (systemData.value.length > 0) {
formData.value.system = systemData.value[0].id;
}
});
if (unitData.value.length > 0)
formData.value.unit = unitData.value[0].id
if (typeData.value.length > 0)
formData.value.type = typeData.value[0].id
if (systemData.value.length > 0)
formData.value.system = systemData.value[0].id
context.emit('optionSelected', formData.value)
})
//
context.emit('optionSelected', formData.value);
// context.emit('optionSelected', formData.value)
//
const submitForm = (values) => {
context.emit('optionSelected', values);
};
context.emit('optionSelected', values)
}
const onFinishFailed = (errorInfo: any) => {
console.log('Failed:', errorInfo);
};
const labelCol = { style: { width: '80px' } };
console.log('Failed:', errorInfo)
}
const labelCol = { style: { width: '80px' } }
//
const onUnitChange = async (_value) => {
const param: systemSelectParams = {
unitId: formData.value.unit,
typeId: typeData.value[0].id,
};
systemData.value = await subSystemListApi(param);
formData.value.system = systemData.value[0].id;
formData.value.type = typeData.value[0].id;
};
}
systemData.value = await subSystemListApi(param)
formData.value.system = systemData.value[0].id
formData.value.type = typeData.value[0].id
}
//
const onTypeChange = async (_value) => {
const param: systemSelectParams = {
unitId: formData.value.unit,
typeId: formData.value.type,
};
systemData.value = await subSystemListApi(param);
formData.value.system = systemData.value[0].id;
};
}
systemData.value = await subSystemListApi(param)
formData.value.system = systemData.value[0].id
}
return {
formData,
@ -133,7 +89,54 @@
labelCol,
onUnitChange,
onTypeChange,
};
}
},
};
}
</script>
<template>
<a-form layout="inline" :model="formData" :label-col="labelCol" @finish="submitForm">
<a-col :md="5">
<a-form-item label="机组" name="unit">
<a-select
v-model:value="formData.unit"
style="width: 100%"
:options="unitData.map((unit) => ({ value: unit.id, label: unit.name }))"
@change="onUnitChange"
/>
</a-form-item>
</a-col>
<a-col :md="5">
<a-form-item label="系统" name="type">
<a-select
v-model:value="formData.type"
style="width: 100%"
:options="typeData.map((type) => ({ value: type.id, label: type.name }))"
@change="onTypeChange"
/>
</a-form-item>
</a-col>
<a-col :md="5">
<a-form-item label="子系统" name="system">
<a-select
v-model:value="formData.system"
style="width: 100%"
:options="systemData.map((system) => ({ value: system.id, label: system.name }))"
/>
</a-form-item>
</a-col>
<a-col :md="5">
<a-form-item name="name">
<a-input v-model:value="formData.name" style="width: 100%" />
</a-form-item>
</a-col>
<a-col :md="3">
<a-form-item>
<a-button type="primary" html-type="submit">
查询
</a-button>
</a-form-item>
</a-col>
</a-form>
<a-divider />
</template>

25
src/views/model/list/data.tsx

@ -1,15 +1,16 @@
import { CSSProperties } from 'vue';
import type { CSSProperties } from 'vue'
export interface ModelItem {
id: number;
icon: string;
title: string;
value: number;
total: number;
color: string;
status: string;
creator: string;
description: string;
headStyle: CSSProperties;
bodyStyle: CSSProperties;
id: number
icon: string
title: string
value: number
total: number
color: string
status: string
creator: string
createTime: string
description: string
headStyle: CSSProperties
bodyStyle: CSSProperties
}

51
src/views/model/list/index.vue

@ -1,37 +1,29 @@
<template>
<PageWrapper contentFullHeight>
<a-card>
<UnitSelect @option-selected="handleOptionSelected" />
<ModelCard :loading="loading" :systemId="systemId" :selectData="selectData" class="enter-y" />
</a-card>
</PageWrapper>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
import { PageWrapper } from '/@/components/Page';
import ModelCard from './ModelCard.vue';
import UnitSelect from './UnitSelect.vue';
import { Card } from 'ant-design-vue';
import { defineComponent, ref } from 'vue'
import { Card } from 'ant-design-vue'
import ModelCard from './ModelCard.vue'
import UnitSelect from './UnitSelect.vue'
import { PageWrapper } from '@/components/Page'
const loading = ref(true);
const selectData = ref(null);
const systemId = ref(null);
const loading = ref(true)
const selectData = ref(null)
const systemId = ref(null)
const handleOptionSelected = (values) => {
selectData.value = values;
systemId.value = values['system'];
};
function handleOptionSelected(values) {
selectData.value = values
systemId.value = values.system
}
setTimeout(() => {
loading.value = false;
}, 1500);
loading.value = false
}, 1500)
export default defineComponent({
components: {
PageWrapper,
ModelCard,
UnitSelect,
ACard: Card,
PageWrapper,
},
setup() {
return {
@ -39,7 +31,16 @@
handleOptionSelected,
selectData,
systemId,
};
}
},
});
})
</script>
<template>
<PageWrapper content-full-height>
<a-card>
<UnitSelect @option-selected="handleOptionSelected" />
<ModelCard :loading="loading" :system-id="systemId" :select-data="selectData" class="enter-y" />
</a-card>
</PageWrapper>
</template>

75
src/views/model/list/step/Step1.vue

@ -1,28 +1,8 @@
<template>
<div class="step1">
<div class="step1-form">
<BasicForm @register="register" />
</div>
<a-divider />
<h3>说明</h3>
<h4>建模参数</h4>
<p>
如果需要可以放建模信息说明. 如果需要可以放建模信息说明. 如果需要可以放建模信息说明.
如果需要可以放建模信息说明. 如果需要可以放建模信息说明. 如果需要可以放建模信息说明.
</p>
<h4>滑动窗参数</h4>
<p>
如果需要可以放建模信息说明. 如果需要可以放建模信息说明. 如果需要可以放建模信息说明.
如果需要可以放建模信息说明. 如果需要可以放建模信息说明. 如果需要可以放建模信息说明.
</p>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { BasicForm, useForm } from '/@/components/Form';
import { step1Schemas } from './data';
import { Select, Input, Divider } from 'ant-design-vue';
import { defineComponent } from 'vue'
import { Divider, Input, Select } from 'ant-design-vue'
import { step1Schemas } from './data'
import { BasicForm, useForm } from '@/components/Form'
export default defineComponent({
components: {
@ -45,30 +25,47 @@
text: '下一步',
},
submitFunc: customSubmitFunc,
});
})
async function customSubmitFunc() {
try {
const values = await validate();
const values = await validate()
const modelInfo = {
modelName: values.modelName,
movingWindows: {
movingSpeed: values.movingSpeed,
samplingInterval: values.samplingInterval,
windowLength: values.windowLength,
},
condition: null,
};
emit('next', modelInfo);
} catch (error) {
description: values.description,
}
emit('next', modelInfo)
}
catch (error) {
//
}
}
return { register };
return { register }
},
});
})
</script>
<template>
<div class="step1">
<div class="step1-form">
<BasicForm @register="register" />
</div>
<a-divider />
<h3>说明</h3>
<h4>建模参数</h4>
<p>
如果需要可以放建模信息说明. 如果需要可以放建模信息说明. 如果需要可以放建模信息说明.
如果需要可以放建模信息说明. 如果需要可以放建模信息说明. 如果需要可以放建模信息说明.
</p>
<h4>滑动窗参数</h4>
<p>
如果需要可以放建模信息说明. 如果需要可以放建模信息说明. 如果需要可以放建模信息说明.
如果需要可以放建模信息说明. 如果需要可以放建模信息说明. 如果需要可以放建模信息说明.
</p>
</div>
</template>
<style lang="less" scoped>
.step1 {
&-form {
@ -78,16 +75,16 @@
h3 {
margin: 0 0 12px;
color: @text-color;
font-size: 16px;
line-height: 32px;
color: @text-color;
}
h4 {
margin: 0 0 4px;
color: @text-color;
font-size: 14px;
line-height: 22px;
color: @text-color;
}
p {

106
src/views/model/list/step/Step2.vue

@ -1,44 +1,12 @@
<template>
<div class="step2">
<a-alert message="选择系统测点作为模型输出。" show-icon />
<a-descriptions :column="2" class="mt-5">
<a-descriptions-item label="模型名称"> {{ beforeData.modelName }} </a-descriptions-item>
<a-descriptions-item label="目标参数名称"> {{ beforeData.targetName }} </a-descriptions-item>
<a-descriptions-item label="滑动窗速度">
{{ beforeData.movingWindows.movingSpeed }}
</a-descriptions-item>
<a-descriptions-item label="滑动窗长度">
{{ beforeData.movingWindows.windowLength }}
</a-descriptions-item>
<a-descriptions-item label="取样间隔">
{{ beforeData.movingWindows.samplingInterval }}
</a-descriptions-item>
</a-descriptions>
<a-divider />
<BasicForm @register="register">
<template #remoteSearch="{ model, field }">
<ApiSelect
:api="pointListApi"
showSearch
v-model:value="model[field]"
:filterOption="false"
resultField="list"
labelField="name"
valueField="id"
:params="searchParams"
@search="onSearch"
/> </template
></BasicForm>
</div>
</template>
<script lang="ts">
import { defineComponent, computed, unref, ref, PropType, toRaw } from 'vue';
import { BasicForm, useForm, ApiSelect } from '/@/components/Form';
import { step2Schemas } from './data';
import { Alert, Divider, Descriptions } from 'ant-design-vue';
import { pointListApi } from '/@/api/benchmark/select';
import { type Recordable } from '@vben/types';
import { useDebounceFn } from '@vueuse/core';
import type { PropType } from 'vue'
import { computed, defineComponent, ref, toRaw, unref } from 'vue'
import { Alert, Descriptions, Divider } from 'ant-design-vue'
import type { Recordable } from '@vben/types'
import { useDebounceFn } from '@vueuse/core'
import { step2Schemas } from './data'
import { ApiSelect, BasicForm, useForm } from '@/components/Form'
import { pointListApi } from '@/api/alert/model/select'
export default defineComponent({
components: {
@ -70,39 +38,34 @@
},
resetFunc: customResetFunc,
submitFunc: customSubmitFunc,
});
})
async function customResetFunc() {
emit('prev');
emit('prev')
}
async function customSubmitFunc() {
try {
const values = await validate();
const target = values['targetPoint'].split('|');
const targetParameter = {
description: target[0],
targetPoint: target[1],
unit: target[2],
upperlimit: target[3],
lowerlimit: target[4],
};
const values = await validate()
const modelInfo = toRaw(props.beforeData);
modelInfo['targetParameter'] = targetParameter;
emit('next', modelInfo);
} catch (error) {
console.error(error);
const modelInfo = toRaw(props.beforeData)
modelInfo.algorithm = values.algorithm
modelInfo.sampling = values.sampling
modelInfo.rate = values.rate
emit('next', modelInfo)
}
catch (error) {
console.error(error)
}
}
const keyword = ref<string>('');
const keyword = ref<string>('')
const searchParams = computed<Recordable>(() => {
return { keyword: unref(keyword) };
});
return { keyword: unref(keyword) }
})
function onSearch(value: string) {
keyword.value = value;
keyword.value = value
}
return {
@ -111,12 +74,29 @@
onSearch: useDebounceFn(onSearch, 300),
searchParams,
handleReset: () => {
keyword.value = '';
keyword.value = ''
},
};
}
},
});
})
</script>
<template>
<div class="step2">
<a-alert message="选择模型算法,并配置相关参数" show-icon />
<a-descriptions :column="2" class="mt-5">
<a-descriptions-item label="模型名称">
{{ beforeData.modelName }}
</a-descriptions-item>
<a-descriptions-item label="描述">
{{ beforeData.description }}
</a-descriptions-item>
</a-descriptions>
<a-divider />
<BasicForm @register="register" />
</div>
</template>
<style lang="less" scoped>
.step2 {
width: 450px;

182
src/views/model/list/step/Step3.vue

@ -1,44 +1,14 @@
<template>
<div class="step3">
<a-alert message="选择系统测点作为模型输出。" show-icon />
<a-descriptions :column="1" class="mt-5">
<a-descriptions-item label="模型名称"> 测试模型 </a-descriptions-item>
<a-descriptions-item label="目标参数名称"> 送风机电流 </a-descriptions-item>
<a-descriptions-item label="滑动窗速度"> 600 </a-descriptions-item>
<a-descriptions-item label="滑动窗长度"> 120 </a-descriptions-item>
<a-descriptions-item label="取样间隔"> 30 </a-descriptions-item>
</a-descriptions>
<a-divider />
<BasicForm @register="register">
<template #remoteSearch="{ model, field }">
<ApiSelect
:api="pointListApi"
showSearch
v-model:value="model[field]"
:filterOption="false"
resultField="list"
labelField="name"
valueField="id"
:params="searchParams"
@search="onSearch"
/>
</template>
<template #add="{ field }">
<Button v-if="Number(field) === 0" @click="add">+</Button>
<Button v-if="field > 0" @click="del(field)">-</Button>
</template></BasicForm
>
</div>
</template>
<script lang="ts">
import { defineComponent, ref, computed, unref, PropType, toRaw } from 'vue';
import { BasicForm, useForm, ApiSelect } from '/@/components/Form';
import { step3Schemas } from './data';
import { Alert, Divider, Descriptions } from 'ant-design-vue';
import { Button } from '/@/components/Button';
import { pointListApi } from '/@/api/benchmark/select';
import { type Recordable } from '@vben/types';
import { useDebounceFn } from '@vueuse/core';
import type { PropType } from 'vue'
import { computed, defineComponent, ref, toRaw, unref } from 'vue'
import { Alert, Descriptions, Divider } from 'ant-design-vue'
import type { Recordable } from '@vben/types'
import { useDebounceFn } from '@vueuse/core'
import { step3Schemas } from './data'
import { ApiSelect, BasicForm, useForm } from '@/components/Form'
import { Button } from '@/components/Button'
import { pointListApi } from '@/api/alert/model/select'
import { modelSaveApi } from '@/api/alert/model/models'
export default defineComponent({
components: {
@ -54,10 +24,13 @@
beforeData: {
type: Object as PropType<Record<string, any> | null | undefined>,
},
systemId: {
type: Number,
},
},
emits: ['next', 'prev'],
setup(props, { emit }) {
const [register, { appendSchemaByField, removeSchemaByField, validate, _props }] = useForm({
const [register, { appendSchemaByField, removeSchemaByField, validate, setProps }] = useForm({
labelWidth: 100,
schemas: step3Schemas,
actionColOptions: {
@ -67,12 +40,12 @@
text: '上一步',
},
submitButtonOptions: {
text: '下一步',
text: '创建模型',
},
resetFunc: customResetFunc,
submitFunc: customSubmitFunc,
});
const n = ref(1);
})
const n = ref(4)
function add() {
appendSchemaByField(
@ -80,11 +53,11 @@
{
field: `point${n.value}`,
component: 'Input',
label: '边界参数' + n.value,
label: `参数${n.value}`,
required: true,
slot: 'remoteSearch',
colProps: {
span: 16,
span: 23,
},
},
{
@ -93,57 +66,76 @@
label: ' ',
slot: 'add',
colProps: {
span: 2,
span: 1,
},
},
],
'',
);
n.value++;
)
n.value++
}
function del(field) {
removeSchemaByField([`point${field}`, `${field}`]);
n.value--;
removeSchemaByField([`point${field}`, `${field}`])
n.value--
}
async function customResetFunc() {
emit('prev');
emit('prev')
}
async function customSubmitFunc() {
try {
const values = await validate();
const boundaryParameter = [];
const values = await validate()
const pointInfo = []
for (const key in values) {
if (key.startsWith('point')) {
const point = values[key].split('|');
const point = values[key].split('|')
const p = {
description: point[0],
targetPoint: point[1],
unit: point[2],
upperlimit: point[3],
lowerlimit: point[4],
};
boundaryParameter.push(p);
}
pointInfo.push(p)
}
}
const modelInfo = toRaw(props.beforeData)
const modelId = await modelSaveApi(modelInfo)
setProps({
submitButtonOptions: {
loading: true,
},
})
setTimeout(() => {
setProps({
submitButtonOptions: {
loading: false,
},
})
emit('next', modelId)
}, 1500)
}
console.log(props.beforeData);
const modelInfo = toRaw(props.beforeData);
modelInfo['boundaryParameter'] = boundaryParameter;
emit('next', modelInfo);
} catch (error) {
console.error(error);
catch (error) {
console.error(error)
}
}
const keyword = ref<string>('');
const keyword = ref<string>('')
const searchParams = computed<Recordable>(() => {
return { keyword: unref(keyword) };
});
return { keyword: unref(keyword) }
})
function onSearch(value: string) {
keyword.value = value;
keyword.value = value
}
async function searchPoint(params) {
if (params.keyword) {
const data = await pointListApi(params)
return data
}
}
return {
@ -152,14 +144,62 @@
add,
onSearch: useDebounceFn(onSearch, 300),
searchParams,
pointListApi,
searchPoint,
handleReset: () => {
keyword.value = '';
keyword.value = ''
},
};
}
},
});
})
</script>
<template>
<div class="step3">
<a-alert message="选择系统测点作为模型数据源。" show-icon />
<a-descriptions :column="1" class="mt-5">
<a-descriptions-item label="模型名称">
{{ beforeData.modelName }}
</a-descriptions-item>
<a-descriptions-item label="描述">
{{ beforeData.description }}
</a-descriptions-item>
<a-descriptions-item label="模型算法">
{{ beforeData.algorithm }}
</a-descriptions-item>
<a-descriptions-item label="训练采样间隔">
{{ beforeData.sampling }}
</a-descriptions-item>
<a-descriptions-item label="最小主元贡献率">
{{ beforeData.rate }}
</a-descriptions-item>
</a-descriptions>
<a-divider />
<BasicForm @register="register">
<template #remoteSearch="{ model, field }">
<ApiSelect
v-model:value="model[field]"
:api="searchPoint"
show-search
:filter-option="false"
result-field="list"
label-field="name"
value-field="id"
:params="searchParams"
@search="onSearch"
/>
</template>
<template #add="{ field }">
<Button v-if="Number(field) === 0" @click="add">
+
</Button>
<Button v-if="field > 0" @click="del(field)">
-
</Button>
</template>
</BasicForm>
</div>
</template>
<style lang="less" scoped>
.step3 {
width: 450px;

224
src/views/model/list/step/Step4.vue

@ -1,190 +1,78 @@
<template>
<div class="step4">
<a-alert message="选择系统测点作为模型输出。" show-icon />
<a-descriptions :column="1" class="mt-5">
<a-descriptions-item label="模型名称"> 测试模型 </a-descriptions-item>
<a-descriptions-item label="目标参数名称"> 送风机电流 </a-descriptions-item>
<a-descriptions-item label="滑动窗速度"> 600 </a-descriptions-item>
<a-descriptions-item label="滑动窗长度"> 120 </a-descriptions-item>
<a-descriptions-item label="取样间隔"> 30 </a-descriptions-item>
</a-descriptions>
<a-divider />
<BasicForm @register="register">
<template #remoteSearch="{ model, field }">
<ApiSelect
:api="pointListApi"
showSearch
v-model:value="model[field]"
:filterOption="false"
resultField="list"
labelField="name"
valueField="id"
:params="searchParams"
@search="onSearch"
/>
</template>
<template #add="{ field }">
<Button v-if="Number(field) === 0" @click="add">+</Button>
<Button v-if="field > 0" @click="del(field)">-</Button>
</template></BasicForm
>
</div>
</template>
<script lang="ts">
import { defineComponent, ref, computed, unref, PropType, toRaw } from 'vue';
import { BasicForm, useForm, ApiSelect } from '/@/components/Form';
import { step4Schemas } from './data';
import { Alert, Divider, Descriptions } from 'ant-design-vue';
import { Button } from '/@/components/Button';
import { pointListApi } from '/@/api/benchmark/select';
import { modelSaveApi } from '/@/api/benchmark/models';
import { type Recordable } from '@vben/types';
import { useDebounceFn } from '@vueuse/core';
import { defineComponent } from 'vue'
import { Descriptions, Result } from 'ant-design-vue'
import { useGo } from '@/hooks/web/usePage'
export default defineComponent({
components: {
Button,
BasicForm,
ApiSelect,
[Alert.name]: Alert,
[Divider.name]: Divider,
[Result.name]: Result,
[Descriptions.name]: Descriptions,
[Descriptions.Item.name]: Descriptions.Item,
},
props: {
beforeData: {
type: Object as PropType<Record<string, any> | null | undefined>,
},
systemId: {
modelId: {
type: Number,
},
},
emits: ['next', 'prev'],
emits: ['redo'],
setup(props, { emit }) {
const [register, { appendSchemaByField, removeSchemaByField, validate, setProps }] = useForm({
labelWidth: 100,
schemas: step4Schemas,
actionColOptions: {
span: 14,
},
resetButtonOptions: {
text: '上一步',
},
submitButtonOptions: {
text: '创建模型',
},
resetFunc: customResetFunc,
submitFunc: customSubmitFunc,
});
const n = ref(1);
function add() {
appendSchemaByField(
[
{
field: `point${n.value}`,
component: 'Input',
label: '边界参数' + n.value,
required: true,
slot: 'remoteSearch',
colProps: {
span: 16,
},
},
{
field: `${n.value}`,
component: 'Input',
label: ' ',
slot: 'add',
colProps: {
span: 2,
},
},
],
'',
);
n.value++;
}
function del(field) {
removeSchemaByField([`point${field}`, `${field}`]);
n.value--;
}
async function customResetFunc() {
emit('prev');
}
async function customSubmitFunc() {
try {
const values = await validate();
const relationParameter = [];
for (const key in values) {
if (key.startsWith('point')) {
const point = values[key].split('|');
const p = {
description: point[0],
targetPoint: point[1],
unit: point[2],
upperlimit: point[3],
lowerlimit: point[4],
};
relationParameter.push(p);
const go = useGo()
const goTrain = () => {
go(`/model/train/${props.modelId}`)
}
}
const systemId = props.systemId;
const modelInfo = toRaw(props.beforeData);
modelInfo['relationParameter'] = relationParameter;
console.log(modelInfo);
const model = {
systemId: systemId,
modelInfo: modelInfo,
};
const modelId = await modelSaveApi(model);
setProps({
submitButtonOptions: {
loading: true,
},
});
setTimeout(() => {
setProps({
submitButtonOptions: {
loading: false,
},
});
emit('next', modelId);
}, 1500);
} catch (error) {
console.error(error);
}
}
const keyword = ref<string>('');
const searchParams = computed<Recordable>(() => {
return { keyword: unref(keyword) };
});
function onSearch(value: string) {
keyword.value = value;
}
return {
register,
del,
add,
onSearch: useDebounceFn(onSearch, 300),
searchParams,
pointListApi,
handleReset: () => {
keyword.value = '';
redo: () => {
emit('redo')
},
};
goTrain,
}
},
});
})
</script>
<template>
<div class="step4">
<a-result status="success" title="新建成功" sub-title="可查看模型进行编辑">
<template #extra>
<a-button type="primary" @click="redo">
再建一个
</a-button>
<a-button @click="goTrain">
查看模型
</a-button>
</template>
</a-result>
<div class="desc-wrap">
<a-descriptions :column="1" class="mt-5">
<a-descriptions-item label="模型名称">
测试模型
</a-descriptions-item>
<a-descriptions-item label="目标参数名称">
送风机电流
</a-descriptions-item>
<a-descriptions-item label="滑动窗速度">
600
</a-descriptions-item>
<a-descriptions-item label="滑动窗长度">
120
</a-descriptions-item>
<a-descriptions-item label="取样间隔">
30
</a-descriptions-item>
</a-descriptions>
</div>
</div>
</template>
<style lang="less" scoped>
.step4 {
width: 450px;
width: 600px;
margin: 0 auto;
}
.desc-wrap {
padding: 24px 40px;
margin-top: 24px;
background-color: @background-color-light;
}
</style>

62
src/views/model/list/step/Step5.vue

@ -1,62 +0,0 @@
<template>
<div class="step5">
<a-result status="success" title="新建成功" sub-title="可查看模型进行编辑">
<template #extra>
<a-button type="primary" @click="redo"> 再建一个 </a-button>
<a-button @click="goTrain"> 查看模型 </a-button>
</template>
</a-result>
<div class="desc-wrap">
<a-descriptions :column="1" class="mt-5">
<a-descriptions-item label="模型名称"> 测试模型 </a-descriptions-item>
<a-descriptions-item label="目标参数名称"> 送风机电流 </a-descriptions-item>
<a-descriptions-item label="滑动窗速度"> 600 </a-descriptions-item>
<a-descriptions-item label="滑动窗长度"> 120 </a-descriptions-item>
<a-descriptions-item label="取样间隔"> 30 </a-descriptions-item>
</a-descriptions>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { Result, Descriptions } from 'ant-design-vue';
import { useGo } from '/@/hooks/web/usePage';
export default defineComponent({
components: {
[Result.name]: Result,
[Descriptions.name]: Descriptions,
[Descriptions.Item.name]: Descriptions.Item,
},
props: {
modelId: {
type: Number,
},
},
emits: ['redo'],
setup(props, { emit }) {
const go = useGo();
const goTrain = () => {
go(`/model/train/${props.modelId}`);
};
return {
redo: () => {
emit('redo');
},
goTrain,
};
},
});
</script>
<style lang="less" scoped>
.step5 {
width: 600px;
margin: 0 auto;
}
.desc-wrap {
margin-top: 24px;
padding: 24px 40px;
background-color: @background-color-light;
}
</style>

114
src/views/model/list/step/data.tsx

@ -1,4 +1,4 @@
import { FormSchema } from '/@/components/Form';
import type { FormSchema } from '@/components/Form'
export const step1Schemas: FormSchema[] = [
{
@ -12,81 +12,113 @@ export const step1Schemas: FormSchema[] = [
},
},
{
field: 'targetName',
field: 'description',
component: 'Input',
label: '目标参数名称',
required: true,
label: '描述',
colProps: {
span: 24,
},
},
]
export const step2Schemas: FormSchema[] = [
{
field: 'movingSpeed',
component: 'InputNumber',
label: '滑动窗速度',
defaultValue: 600,
field: 'algorithm',
component: 'Select',
label: '算法',
required: true,
defaultValue: 'PCA',
componentProps: {
options: [
{ label: 'PCA', value: 'PCA' },
{ label: 'ANN', value: 'ANN' },
],
},
colProps: { span: 24 },
labelWidth: 120, // 增大label宽度
},
{
field: 'windowLength',
field: 'sampling',
component: 'InputNumber',
label: '滑动窗长度',
label: '训练采样间隔',
required: true,
defaultValue: 120,
defaultValue: 300,
colProps: { span: 24 },
labelWidth: 120, // 增大label宽度
},
{
field: 'samplingInterval',
field: 'rate',
component: 'InputNumber',
label: '取样间隔',
required: true,
defaultValue: 30,
label: '最小主元贡献率',
defaultValue: 0.85,
componentProps: {
step: 0.01,
},
];
export const step2Schemas: FormSchema[] = [
{
field: 'targetPoint',
component: 'Input',
label: '目标参数',
helpMessage: ['输入关键词搜索点号'],
required: true,
slot: 'remoteSearch',
colProps: {
span: 24,
required: ({ values }) => values.algorithm === 'PCA',
ifShow: ({ values }) => values.algorithm === 'PCA',
colProps: { span: 24 },
labelWidth: 120, // 增大label宽度
},
{
field: 'iteration',
component: 'InputNumber',
label: '迭代次数',
defaultValue: 300,
required: ({ values }) => values.algorithm === 'ANN',
ifShow: ({ values }) => values.algorithm === 'ANN',
colProps: { span: 24 },
labelWidth: 120, // 增大label宽度
},
];
{
field: 'hiddenLayer',
component: 'Input',
label: '隐藏层结构',
defaultValue: '5',
required: ({ values }) => values.algorithm === 'ANN',
ifShow: ({ values }) => values.algorithm === 'ANN',
colProps: { span: 24 },
labelWidth: 120, // 增大label宽度
},
]
export const step3Schemas: FormSchema[] = [
{
field: 'point0',
component: 'Input',
label: '边界参数1',
label: '参数1',
required: true,
slot: 'remoteSearch',
componentProps: {
style: { width: '180px' },
},
colProps: {
span: 16,
span: 23,
},
},
{
field: '0',
field: 'point1',
component: 'Input',
label: ' ',
slot: 'add',
label: '参数2',
required: true,
slot: 'remoteSearch',
componentProps: {
style: { width: '180px' },
},
colProps: {
span: 2,
span: 23,
},
},
];
export const step4Schemas: FormSchema[] = [
{
field: 'point0',
field: 'point2',
component: 'Input',
label: '相关参数1',
label: '参数3',
required: true,
slot: 'remoteSearch',
componentProps: {
style: { width: '180px' },
},
colProps: {
span: 16,
span: 23,
},
},
{
@ -95,7 +127,7 @@ export const step4Schemas: FormSchema[] = [
label: ' ',
slot: 'add',
colProps: {
span: 2,
span: 1,
},
},
];
]

Loading…
Cancel
Save