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