feat:配方配置-对接接口
parent
a51f19db91
commit
c49e2fed52
@ -0,0 +1,31 @@
|
|||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
|
export interface RecipePointVO {
|
||||||
|
id: number
|
||||||
|
recipeId: string | number
|
||||||
|
name?: string
|
||||||
|
max?: string | number
|
||||||
|
min?: string | number
|
||||||
|
dataType?: string
|
||||||
|
dataUnit?: string
|
||||||
|
remark?: string
|
||||||
|
createTime?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const RecipePointApi = {
|
||||||
|
getRecipePointPage: async (params: any) => {
|
||||||
|
return await request.get({ url: `/iot/recipe-point/page`, params })
|
||||||
|
},
|
||||||
|
|
||||||
|
createRecipePoint: async (params: Partial<RecipePointVO>) => {
|
||||||
|
return await request.post({ url: `/iot/recipe-point/create`, data: params })
|
||||||
|
},
|
||||||
|
|
||||||
|
updateRecipePoint: async (params: Partial<RecipePointVO>) => {
|
||||||
|
return await request.put({ url: `/iot/recipe-point/update`, data: params })
|
||||||
|
},
|
||||||
|
|
||||||
|
deleteRecipePoint: async (id: number) => {
|
||||||
|
return await request.delete({ url: `/iot/recipe-point/delete`, params: { id } })
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,332 @@
|
|||||||
|
<template>
|
||||||
|
<ContentWrap v-if="visible">
|
||||||
|
<el-tabs v-model="activeTab" class="mb-12px">
|
||||||
|
<template #extra>
|
||||||
|
<el-button link type="info" @click="handleClose">收起</el-button>
|
||||||
|
</template>
|
||||||
|
<el-tab-pane :label="`详情:${recipeCode} - ${name}`" name="detail">
|
||||||
|
<div class="mb-12px text-left">
|
||||||
|
<el-button type="primary" @click="handleConfig">配置</el-button>
|
||||||
|
</div>
|
||||||
|
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" row-key="id">
|
||||||
|
<el-table-column label="序号" align="center" width="80">
|
||||||
|
<template #default="scope">
|
||||||
|
{{ (queryParams.pageNo - 1) * queryParams.pageSize + scope.$index + 1 }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="点位名称" align="center" prop="pointName" />
|
||||||
|
<el-table-column label="点位类型" align="center" prop="pointType" />
|
||||||
|
<el-table-column label="数据类型" align="center" prop="dataType" />
|
||||||
|
<el-table-column label="单位" align="center" prop="dataUnit" />
|
||||||
|
</el-table>
|
||||||
|
<Pagination
|
||||||
|
:total="total"
|
||||||
|
v-model:page="queryParams.pageNo"
|
||||||
|
v-model:limit="queryParams.pageSize"
|
||||||
|
@pagination="handlePagination"
|
||||||
|
/>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<el-tab-pane label="手动录入参数" name="manual">
|
||||||
|
<div class="mb-12px flex justify-start">
|
||||||
|
<el-button type="primary" @click="openManualDialog('create')">新增</el-button>
|
||||||
|
</div>
|
||||||
|
<el-table
|
||||||
|
v-loading="manualLoading"
|
||||||
|
:data="manualList"
|
||||||
|
:stripe="true"
|
||||||
|
:show-overflow-tooltip="true"
|
||||||
|
row-key="id"
|
||||||
|
>
|
||||||
|
<el-table-column label="名称" align="center" prop="name" />
|
||||||
|
<el-table-column label="上限" align="center" prop="max" />
|
||||||
|
<el-table-column label="下限" align="center" prop="min" />
|
||||||
|
<el-table-column label="单位" align="center" prop="dataUnit" />
|
||||||
|
<el-table-column label="备注" align="center" prop="remark" />
|
||||||
|
<el-table-column label="操作" align="center" width="150px" fixed="right">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button link type="primary" @click="openManualDialog('update', scope.row)">编辑</el-button>
|
||||||
|
<el-button link type="danger" @click="handleManualDelete(scope.row)">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<Pagination
|
||||||
|
:total="manualTotal"
|
||||||
|
v-model:page="manualQueryParams.pageNo"
|
||||||
|
v-model:limit="manualQueryParams.pageSize"
|
||||||
|
@pagination="handleManualPagination"
|
||||||
|
/>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
|
||||||
|
<Dialog
|
||||||
|
:title="manualDialogMode === 'create' ? '新增参数' : '编辑参数'"
|
||||||
|
v-model="manualDialogVisible"
|
||||||
|
width="640px"
|
||||||
|
>
|
||||||
|
<el-form
|
||||||
|
ref="manualFormRef"
|
||||||
|
:model="manualForm"
|
||||||
|
:rules="manualRules"
|
||||||
|
label-width="90px"
|
||||||
|
v-loading="manualDialogLoading"
|
||||||
|
>
|
||||||
|
<el-form-item label="名称" prop="name">
|
||||||
|
<el-input v-model="manualForm.name" placeholder="请输入名称" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="上限" prop="max">
|
||||||
|
<el-input v-model="manualForm.max" placeholder="请输入上限" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="下限" prop="min">
|
||||||
|
<el-input v-model="manualForm.min" placeholder="请输入下限" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="数据类型" prop="dataType">
|
||||||
|
<el-select v-model="manualForm.dataType" placeholder="请选择数据类型" clearable filterable class="!w-full">
|
||||||
|
<el-option
|
||||||
|
v-for="dict in dataTypeDictOptions"
|
||||||
|
:key="dict.value"
|
||||||
|
:label="dict.label"
|
||||||
|
:value="dict.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="单位" prop="dataUnit">
|
||||||
|
<el-select v-model="manualForm.dataUnit" placeholder="请选择单位" clearable filterable class="!w-full">
|
||||||
|
<el-option
|
||||||
|
v-for="dict in unitDictOptions"
|
||||||
|
:key="dict.value"
|
||||||
|
:label="dict.label"
|
||||||
|
:value="dict.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="备注" prop="remark">
|
||||||
|
<el-input v-model="manualForm.remark" placeholder="请输入备注" clearable type="textarea" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="manualDialogVisible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" :disabled="manualDialogLoading" @click="submitManualDialog">保 存</el-button>
|
||||||
|
</template>
|
||||||
|
</Dialog>
|
||||||
|
</ContentWrap>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { RecipeConfigApi, RecipePointDetailVO } from '@/api/iot/recipeConfig'
|
||||||
|
import { RecipePointApi, RecipePointVO } from '@/api/iot/recipePoint'
|
||||||
|
import { getStrDictOptions } from '@/utils/dict'
|
||||||
|
|
||||||
|
defineOptions({ name: 'RecipeDetailList' })
|
||||||
|
|
||||||
|
const message = useMessage()
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
visible: boolean
|
||||||
|
recipeId?: string
|
||||||
|
manualRecipeId?: string | number
|
||||||
|
recipeCode: string
|
||||||
|
name: string
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'close'): void
|
||||||
|
(e: 'config'): void
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const activeTab = ref('detail')
|
||||||
|
const loading = ref(false)
|
||||||
|
const list = ref<RecipePointDetailVO[]>([])
|
||||||
|
const total = ref(0)
|
||||||
|
const queryParams = reactive({
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 10
|
||||||
|
})
|
||||||
|
|
||||||
|
const manualLoading = ref(false)
|
||||||
|
const manualList = ref<RecipePointVO[]>([])
|
||||||
|
const manualTotal = ref(0)
|
||||||
|
const manualQueryParams = reactive({
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 10
|
||||||
|
})
|
||||||
|
|
||||||
|
type ManualDialogMode = 'create' | 'update'
|
||||||
|
const manualDialogVisible = ref(false)
|
||||||
|
const manualDialogMode = ref<ManualDialogMode>('create')
|
||||||
|
const manualDialogLoading = ref(false)
|
||||||
|
const manualFormRef = ref()
|
||||||
|
const manualForm = reactive({
|
||||||
|
id: undefined as number | undefined,
|
||||||
|
name: '',
|
||||||
|
max: '' as string | undefined,
|
||||||
|
min: '' as string | undefined,
|
||||||
|
dataType: '' as string | undefined,
|
||||||
|
dataUnit: '' as string | undefined,
|
||||||
|
remark: '' as string | undefined
|
||||||
|
})
|
||||||
|
const manualRules = reactive({
|
||||||
|
name: [{ required: true, message: '名称不能为空', trigger: 'blur' }],
|
||||||
|
max: [{ required: true, message: '上限不能为空', trigger: 'blur' }],
|
||||||
|
min: [{ required: true, message: '下限不能为空', trigger: 'blur' }],
|
||||||
|
dataType: [{ required: true, message: '数据类型不能为空', trigger: 'change' }],
|
||||||
|
dataUnit: [{ required: true, message: '单位不能为空', trigger: 'change' }]
|
||||||
|
})
|
||||||
|
|
||||||
|
const dataTypeDictOptions = computed(() => getStrDictOptions('iot_device_data_type'))
|
||||||
|
const unitDictOptions = computed(() => getStrDictOptions('iot_device_attribute_unit'))
|
||||||
|
|
||||||
|
const normalizeDetail = (item: any): RecipePointDetailVO => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
pointName: item.pointName ?? item.attributeName,
|
||||||
|
pointType: item.pointType ?? item.attributeType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getList = async () => {
|
||||||
|
if (!props.recipeId) return
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const pageSize = Math.min(100, Math.max(1, Number(queryParams.pageSize) || 10))
|
||||||
|
const data = await RecipeConfigApi.getRecipePointDetailPage({
|
||||||
|
pageNo: queryParams.pageNo,
|
||||||
|
pageSize,
|
||||||
|
recipeId: props.recipeId
|
||||||
|
})
|
||||||
|
list.value = (data.list ?? []).map(normalizeDetail)
|
||||||
|
total.value = data.total
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handlePagination = () => {
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
const getManualList = async () => {
|
||||||
|
if (!props.manualRecipeId) return
|
||||||
|
manualLoading.value = true
|
||||||
|
try {
|
||||||
|
const pageSize = Math.min(100, Math.max(1, Number(manualQueryParams.pageSize) || 10))
|
||||||
|
const data = await RecipePointApi.getRecipePointPage({
|
||||||
|
pageNo: manualQueryParams.pageNo,
|
||||||
|
pageSize,
|
||||||
|
recipeId: props.manualRecipeId
|
||||||
|
})
|
||||||
|
manualList.value = data.list ?? []
|
||||||
|
manualTotal.value = data.total
|
||||||
|
} finally {
|
||||||
|
manualLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleManualPagination = () => {
|
||||||
|
getManualList()
|
||||||
|
}
|
||||||
|
|
||||||
|
const openManualDialog = (mode: ManualDialogMode, row?: RecipePointVO) => {
|
||||||
|
manualDialogMode.value = mode
|
||||||
|
manualDialogVisible.value = true
|
||||||
|
nextTick(() => {
|
||||||
|
manualFormRef.value?.clearValidate?.()
|
||||||
|
})
|
||||||
|
if (mode === 'create') {
|
||||||
|
manualForm.id = undefined
|
||||||
|
manualForm.name = ''
|
||||||
|
manualForm.max = ''
|
||||||
|
manualForm.min = ''
|
||||||
|
manualForm.dataType = ''
|
||||||
|
manualForm.dataUnit = ''
|
||||||
|
manualForm.remark = ''
|
||||||
|
return
|
||||||
|
}
|
||||||
|
manualForm.id = row?.id
|
||||||
|
manualForm.name = row?.name ?? ''
|
||||||
|
manualForm.max = row?.max === undefined || row?.max === null ? '' : String(row.max)
|
||||||
|
manualForm.min = row?.min === undefined || row?.min === null ? '' : String(row.min)
|
||||||
|
manualForm.dataType = row?.dataType === undefined || row?.dataType === null ? '' : String(row.dataType)
|
||||||
|
manualForm.dataUnit = row?.dataUnit ?? ''
|
||||||
|
manualForm.remark = row?.remark ?? ''
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitManualDialog = async () => {
|
||||||
|
if (!props.manualRecipeId) return
|
||||||
|
await manualFormRef.value?.validate?.()
|
||||||
|
manualDialogLoading.value = true
|
||||||
|
try {
|
||||||
|
const params = {
|
||||||
|
id: manualForm.id,
|
||||||
|
recipeId: props.manualRecipeId,
|
||||||
|
name: manualForm.name,
|
||||||
|
max: manualForm.max,
|
||||||
|
min: manualForm.min,
|
||||||
|
dataType: manualForm.dataType,
|
||||||
|
dataUnit: manualForm.dataUnit,
|
||||||
|
remark: manualForm.remark
|
||||||
|
}
|
||||||
|
if (manualDialogMode.value === 'create') {
|
||||||
|
await RecipePointApi.createRecipePoint(params)
|
||||||
|
message.success(t('common.createSuccess'))
|
||||||
|
} else {
|
||||||
|
await RecipePointApi.updateRecipePoint(params)
|
||||||
|
message.success(t('common.updateSuccess'))
|
||||||
|
}
|
||||||
|
manualDialogVisible.value = false
|
||||||
|
await getManualList()
|
||||||
|
} finally {
|
||||||
|
manualDialogLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleManualDelete = async (row: RecipePointVO) => {
|
||||||
|
try {
|
||||||
|
await message.delConfirm()
|
||||||
|
await RecipePointApi.deleteRecipePoint(row.id)
|
||||||
|
message.success(t('common.delSuccess'))
|
||||||
|
await getManualList()
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
emit('close')
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleConfig = () => {
|
||||||
|
emit('config')
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => [props.visible, props.recipeId],
|
||||||
|
([visible]) => {
|
||||||
|
if (!visible) return
|
||||||
|
queryParams.pageNo = 1
|
||||||
|
manualQueryParams.pageNo = 1
|
||||||
|
activeTab.value = 'detail'
|
||||||
|
getList()
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => activeTab.value,
|
||||||
|
(tab) => {
|
||||||
|
if (!props.visible) return
|
||||||
|
if (tab === 'manual') {
|
||||||
|
getManualList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const refresh = async () => {
|
||||||
|
if (activeTab.value === 'manual') {
|
||||||
|
await getManualList()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
await getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({ refresh })
|
||||||
|
</script>
|
||||||
Loading…
Reference in New Issue