10 changed files with 677 additions and 3 deletions
@ -0,0 +1,58 @@ |
|||||||
|
import type { GetModelAttributeListParams, ModelAttribute, ModelAttributeWithForm, ModelService } from './types' |
||||||
|
import { defHttp } from '@/utils/http/axios' |
||||||
|
|
||||||
|
export function getAllModelServices(productId: string) { |
||||||
|
return defHttp.get<ModelService[]>({ |
||||||
|
url: '/thingModel/select', |
||||||
|
params: { |
||||||
|
productId, |
||||||
|
}, |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
export function createModelService(data: Partial<ModelService>) { |
||||||
|
return defHttp.post({ |
||||||
|
url: '/thingModel/save', |
||||||
|
data, |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
export function updateModelService(data: Partial<ModelService>) { |
||||||
|
return defHttp.post({ |
||||||
|
url: '/thingModel/update', |
||||||
|
data, |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
export function deleteModelService(id: string) { |
||||||
|
return defHttp.post({ |
||||||
|
url: `/thingModel/remove?id=${id}`, |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
export function getModelAttributeList(params: GetModelAttributeListParams) { |
||||||
|
return defHttp.get<PageResult<ModelAttribute>>({ |
||||||
|
url: '/thingModel/item/page', |
||||||
|
params, |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
export function createModelAttribute(data: ModelAttributeWithForm) { |
||||||
|
return defHttp.post({ |
||||||
|
url: '/thingModel/item/save', |
||||||
|
data, |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
export function updateModelAttribute(data: ModelAttributeWithForm) { |
||||||
|
return defHttp.post({ |
||||||
|
url: '/thingModel/item/update', |
||||||
|
data, |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
export function deleteModelAttribute(id: string) { |
||||||
|
return defHttp.post({ |
||||||
|
url: `/thingModel/item/remove?id=${id}`, |
||||||
|
}) |
||||||
|
} |
@ -0,0 +1,133 @@ |
|||||||
|
<script setup lang='ts'> |
||||||
|
import { Alert, Popconfirm } from 'ant-design-vue' |
||||||
|
import { useRoute } from 'vue-router' |
||||||
|
import { EyeOutlined, PlusOutlined, SyncOutlined } from '@ant-design/icons-vue' |
||||||
|
import { useModelService } from './composables/useModelService' |
||||||
|
import { useModelAttribute } from './composables/useModelAttribute' |
||||||
|
import ModelServiceFormModal from './ModelServiceFormModal.vue' |
||||||
|
import ModelAttributeFormModal from './ModelAttributeFormModal.vue' |
||||||
|
import { BasicTable, TableAction } from '@/components/Table' |
||||||
|
import type { ModelAttribute } from '@/api/product/types' |
||||||
|
import JsonPreviewModal from '@/components/JsonPreviewModal' |
||||||
|
|
||||||
|
defineProps<{ tsl?: string }>() |
||||||
|
|
||||||
|
const route = useRoute() |
||||||
|
const { |
||||||
|
selectedModelId, |
||||||
|
setSelectedModelId, |
||||||
|
modelServiceList, |
||||||
|
handleDeleteModelService, |
||||||
|
registerModelServiceModal, |
||||||
|
openModelServiceModal, |
||||||
|
reloadModelService, |
||||||
|
} = useModelService(route.params.id as string) |
||||||
|
|
||||||
|
const { |
||||||
|
registerModelAttributeTable, |
||||||
|
registerModelAttributeModal, |
||||||
|
openModelAttributeModal, |
||||||
|
reloadModalAttribute, |
||||||
|
handleDeleteModelAttribute, |
||||||
|
} = useModelAttribute(route.params.id as string, selectedModelId) |
||||||
|
</script> |
||||||
|
|
||||||
|
<template> |
||||||
|
<div> |
||||||
|
<div mb="12px"> |
||||||
|
<JsonPreviewModal title="物模型 TSL" :data="tsl || ''"> |
||||||
|
<a-button type="primary"> |
||||||
|
<EyeOutlined /> |
||||||
|
物模型 TSL |
||||||
|
</a-button> |
||||||
|
</JsonPreviewModal> |
||||||
|
</div> |
||||||
|
<Alert icon type="info" show-icon class="py-4px text-13px" message="产品模型用于描述设备具备的能力和特性。通过定义产品模型,在平台构建一款设备的抽象模型,使平台理解该款设备支持的服务、属性、命令等信息,如颜色、开关等。当定义完一款产品模型后,在进行注册设备时,就可以使用在控制台上定义的产品模型。" /> |
||||||
|
|
||||||
|
<div flex="~ gap-12px" mt="12px"> |
||||||
|
<div w="20%"> |
||||||
|
<div flex="~ items-center justify-between" border="0 b-1 solid gray-200" class="mb-12px box-border h-40px px-10px"> |
||||||
|
<div font-bold> |
||||||
|
服务列表 |
||||||
|
</div> |
||||||
|
<div class="i-ant-design:plus-outlined cursor-pointer text-20px" @click="openModelServiceModal()" /> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div |
||||||
|
v-for="item in modelServiceList" :key="item.id" |
||||||
|
flex="~ items-center justify-between" |
||||||
|
class="box-border h-60px cursor-pointer pl-10px hover:bg-gray-100" |
||||||
|
border="0 b-1 solid gray-50" |
||||||
|
:class="selectedModelId === item.id ? 'bg-gray-100' : ''" |
||||||
|
@click="setSelectedModelId(item.id)" |
||||||
|
> |
||||||
|
<div w-0 flex-1> |
||||||
|
<div truncate> |
||||||
|
{{ item.serviceId }} |
||||||
|
</div> |
||||||
|
<div mt="5px" text="12px gray-500" truncate :title="item.description"> |
||||||
|
{{ item.description }} |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div v-if="item.serviceId !== 'DEFAULT'"> |
||||||
|
<a-button type="link" size="small" @click="openModelServiceModal(true, item)"> |
||||||
|
<span class="i-ant-design:edit-outlined" /> |
||||||
|
</a-button> |
||||||
|
<Popconfirm title="是否要删除数据?" @confirm="handleDeleteModelService(item.id)"> |
||||||
|
<a-button type="link" size="small" danger> |
||||||
|
<span class="i-ant-design:delete-outlined" /> |
||||||
|
</a-button> |
||||||
|
</Popconfirm> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div w-0 flex-1> |
||||||
|
<BasicTable :api="async () => ([] as ModelAttribute[])" @register="registerModelAttributeTable"> |
||||||
|
<template #tableTitle> |
||||||
|
<a-button type="primary" @click="openModelAttributeModal"> |
||||||
|
<PlusOutlined /> |
||||||
|
新增属性 |
||||||
|
</a-button> |
||||||
|
</template> |
||||||
|
|
||||||
|
<template #toolbar> |
||||||
|
<a-button size="small" @click="reloadModalAttribute"> |
||||||
|
<template #icon> |
||||||
|
<SyncOutlined /> |
||||||
|
</template> |
||||||
|
刷新 |
||||||
|
</a-button> |
||||||
|
</template> |
||||||
|
|
||||||
|
<template #bodyCell="{ column, record }"> |
||||||
|
<template v-if="column.key === 'action'"> |
||||||
|
<TableAction |
||||||
|
:actions="[ |
||||||
|
{ |
||||||
|
icon: 'i-ant-design:edit-outlined', |
||||||
|
label: '编辑', |
||||||
|
onClick: () => openModelAttributeModal(true, record), |
||||||
|
}, |
||||||
|
{ |
||||||
|
icon: 'i-ant-design:delete-outlined', |
||||||
|
danger: true, |
||||||
|
label: '删除', |
||||||
|
popConfirm: { |
||||||
|
title: '是否要删除数据?', |
||||||
|
placement: 'left', |
||||||
|
confirm: () => handleDeleteModelAttribute(record.id), |
||||||
|
}, |
||||||
|
}, |
||||||
|
]" |
||||||
|
/> |
||||||
|
</template> |
||||||
|
</template> |
||||||
|
</BasicTable> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<ModelServiceFormModal @register="registerModelServiceModal" @success="reloadModelService" /> |
||||||
|
<ModelAttributeFormModal :model-id="selectedModelId || ''" @register="registerModelAttributeModal" @success="reloadModalAttribute" /> |
||||||
|
</div> |
||||||
|
</template> |
@ -0,0 +1,241 @@ |
|||||||
|
<script lang="ts" setup> |
||||||
|
import { ref } from 'vue' |
||||||
|
import { FormItem, Input, InputNumber } from 'ant-design-vue' |
||||||
|
import { useMessage } from '@/hooks/web/useMessage' |
||||||
|
import { BasicForm, useForm } from '@/components/Form' |
||||||
|
import { BasicModal, useModalInner } from '@/components/Modal' |
||||||
|
import { createModelAttribute, updateModelAttribute } from '@/api/product/model' |
||||||
|
import type { ModelAttribute, ModelAttributeWithForm } from '@/api/product/types' |
||||||
|
|
||||||
|
defineOptions({ name: 'ModelAttributeFormModal' }) |
||||||
|
const props = defineProps<{ modelId: string }>() |
||||||
|
|
||||||
|
const emit = defineEmits(['success', 'register']) |
||||||
|
|
||||||
|
enum DataTypesEnum { |
||||||
|
Int32 = 'int32', |
||||||
|
Float = 'float', |
||||||
|
Bool = 'bool', |
||||||
|
Text = 'text', |
||||||
|
} |
||||||
|
|
||||||
|
const isUpdate = ref(false) |
||||||
|
const [registerForm, { setFieldsValue, validate }] = useForm({ |
||||||
|
labelWidth: 80, |
||||||
|
baseColProps: { span: 24 }, |
||||||
|
schemas: [ |
||||||
|
{ |
||||||
|
field: 'id', |
||||||
|
show: false, |
||||||
|
component: 'Input', |
||||||
|
}, |
||||||
|
{ |
||||||
|
field: 'itemType', |
||||||
|
label: '功能类型', |
||||||
|
required: true, |
||||||
|
component: 'Select', |
||||||
|
defaultValue: 1, |
||||||
|
componentProps: { |
||||||
|
options: [ |
||||||
|
{ label: '属性', value: 1 }, |
||||||
|
{ label: '命令', value: 2 }, |
||||||
|
], |
||||||
|
}, |
||||||
|
dynamicDisabled: () => isUpdate.value, |
||||||
|
}, |
||||||
|
{ |
||||||
|
field: 'name', |
||||||
|
label: '功能名称', |
||||||
|
required: true, |
||||||
|
component: 'Input', |
||||||
|
}, |
||||||
|
{ |
||||||
|
field: 'identifier', |
||||||
|
label: '标识符', |
||||||
|
required: true, |
||||||
|
component: 'Input', |
||||||
|
}, |
||||||
|
{ |
||||||
|
field: 'dataType', |
||||||
|
label: '数据类型', |
||||||
|
required: true, |
||||||
|
component: 'Select', |
||||||
|
componentProps: { |
||||||
|
options: Object.values(DataTypesEnum).map(value => ({ label: value, value })), |
||||||
|
}, |
||||||
|
dynamicDisabled: () => isUpdate.value, |
||||||
|
}, |
||||||
|
|
||||||
|
// int32 / float schemas |
||||||
|
{ |
||||||
|
field: 'valueScope', |
||||||
|
fields: ['min', 'max'], |
||||||
|
label: '取值范围', |
||||||
|
slot: 'ValueScope', |
||||||
|
required: true, |
||||||
|
itemProps: { |
||||||
|
autoLink: false, |
||||||
|
}, |
||||||
|
defaultValue: '_', // skip the required check |
||||||
|
ifShow: ({ values }) => [DataTypesEnum.Int32, DataTypesEnum.Float].includes(values.dataType), |
||||||
|
}, |
||||||
|
{ |
||||||
|
field: 'scale', |
||||||
|
label: '精度', |
||||||
|
required: true, |
||||||
|
helpMessage: '小数位', |
||||||
|
component: 'InputNumber', |
||||||
|
componentProps: { |
||||||
|
precision: 0, |
||||||
|
}, |
||||||
|
ifShow: ({ values }) => values.dataType === DataTypesEnum.Float, |
||||||
|
}, |
||||||
|
{ |
||||||
|
field: 'unit', |
||||||
|
label: '单位', |
||||||
|
component: 'Input', |
||||||
|
ifShow: ({ values }) => [DataTypesEnum.Int32, DataTypesEnum.Float].includes(values.dataType), |
||||||
|
}, |
||||||
|
|
||||||
|
// bool schemas |
||||||
|
{ |
||||||
|
field: 'bool', |
||||||
|
fields: ['trueDesc', 'falseDesc'], |
||||||
|
label: '布尔值', |
||||||
|
slot: 'Bool', |
||||||
|
required: true, |
||||||
|
itemProps: { |
||||||
|
autoLink: false, |
||||||
|
}, |
||||||
|
defaultValue: '_', // skip the required check |
||||||
|
ifShow: ({ values }) => values.dataType === DataTypesEnum.Bool, |
||||||
|
}, |
||||||
|
|
||||||
|
// text schemas |
||||||
|
{ |
||||||
|
field: 'maxLength', |
||||||
|
label: '数据长度', |
||||||
|
required: true, |
||||||
|
component: 'InputNumber', |
||||||
|
componentProps: { |
||||||
|
precision: 0, |
||||||
|
}, |
||||||
|
ifShow: ({ values }) => values.dataType === DataTypesEnum.Text, |
||||||
|
}, |
||||||
|
|
||||||
|
{ |
||||||
|
field: 'method', |
||||||
|
label: '读写', |
||||||
|
component: 'Select', |
||||||
|
defaultValue: 'r', |
||||||
|
componentProps: { |
||||||
|
options: [ |
||||||
|
{ label: '只读', value: 'r' }, |
||||||
|
{ label: '读写', value: 'rw' }, |
||||||
|
], |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
field: 'sort', |
||||||
|
label: '排序', |
||||||
|
component: 'InputNumber', |
||||||
|
componentProps: { |
||||||
|
precision: 0, |
||||||
|
}, |
||||||
|
}, |
||||||
|
], |
||||||
|
showActionButtonGroup: false, |
||||||
|
actionColOptions: { span: 23 }, |
||||||
|
}) |
||||||
|
|
||||||
|
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data: ModelAttribute) => { |
||||||
|
isUpdate.value = true |
||||||
|
setFieldsValue({ ...data, ...(data.dataSpecs || {}) }) |
||||||
|
}) |
||||||
|
|
||||||
|
async function handleSubmit() { |
||||||
|
try { |
||||||
|
const values = await validate<ModelAttributeWithForm>() |
||||||
|
setModalProps({ confirmLoading: true }) |
||||||
|
values.modelId = props.modelId |
||||||
|
await (isUpdate.value ? updateModelAttribute(values) : createModelAttribute(values)) |
||||||
|
closeModal() |
||||||
|
emit('success') |
||||||
|
useMessage().createMessage.success('保存成功') |
||||||
|
} |
||||||
|
catch {} |
||||||
|
finally { |
||||||
|
setModalProps({ confirmLoading: false }) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function validatorValueScope(value1: number, value2: number) { |
||||||
|
// eslint-disable-next-line prefer-promise-reject-errors |
||||||
|
return value1 > value2 ? Promise.reject() : Promise.resolve() |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<template> |
||||||
|
<BasicModal |
||||||
|
v-bind="$attrs" |
||||||
|
width="40%" |
||||||
|
:min-height="100" |
||||||
|
:title="isUpdate ? '编辑' : '新增'" |
||||||
|
:after-close="() => isUpdate = false" |
||||||
|
@register="registerModal" |
||||||
|
@ok="handleSubmit" |
||||||
|
> |
||||||
|
<BasicForm @register="registerForm"> |
||||||
|
<template #ValueScope="{ model }"> |
||||||
|
<div flex="~ justify-between gap-12px" class="custom-form-slot"> |
||||||
|
<FormItem |
||||||
|
name="min" |
||||||
|
:rules="[ |
||||||
|
{ required: true, message: '请填写最小值' }, |
||||||
|
{ validator: (_, min) => validatorValueScope(min, model.max), message: '最小值不能大于最大值' }, |
||||||
|
]" |
||||||
|
> |
||||||
|
<InputNumber v-model:value="model.min" placeholder="最小值" /> |
||||||
|
</FormItem> |
||||||
|
|
||||||
|
<span mt="5px">-</span> |
||||||
|
|
||||||
|
<FormItem |
||||||
|
name="max" |
||||||
|
:rules="[ |
||||||
|
{ required: true, message: '请填写最大值' }, |
||||||
|
{ validator: (_, max) => validatorValueScope(model.min, max), message: '最大值不能小于最小值' }, |
||||||
|
]" |
||||||
|
> |
||||||
|
<InputNumber v-model:value="model.max" placeholder="最大值" /> |
||||||
|
</FormItem> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<template #Bool="{ model }"> |
||||||
|
<div flex="~ justify-between gap-12px" class="custom-form-slot"> |
||||||
|
<FormItem name="trueDesc" :rules="[{ required: true, message: '请填写布尔值' }]"> |
||||||
|
<Input v-model:value="model.trueDesc" addon-before="0" placeholder="如:是" /> |
||||||
|
</FormItem> |
||||||
|
|
||||||
|
<span mt="5px">-</span> |
||||||
|
|
||||||
|
<FormItem name="falseDesc" :rules="[{ required: true, message: '请填写布尔值' }]"> |
||||||
|
<Input v-model:value="model.falseDesc" addon-before="1" placeholder="如:否" /> |
||||||
|
</FormItem> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
</BasicForm> |
||||||
|
</BasicModal> |
||||||
|
</template> |
||||||
|
|
||||||
|
<style scoped lang="less"> |
||||||
|
.custom-form-slot .ant-form-item { |
||||||
|
margin-bottom: 0; |
||||||
|
flex: 1; |
||||||
|
|
||||||
|
:deep(.ant-form-item-explain-error) { |
||||||
|
position: absolute; |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,79 @@ |
|||||||
|
<script lang="ts" setup> |
||||||
|
import { ref } from 'vue' |
||||||
|
import { useRoute } from 'vue-router' |
||||||
|
import { useMessage } from '@/hooks/web/useMessage' |
||||||
|
import { BasicForm, useForm } from '@/components/Form' |
||||||
|
import { BasicModal, useModalInner } from '@/components/Modal' |
||||||
|
import { createModelService, updateModelService } from '@/api/product/model' |
||||||
|
import type { ModelService } from '@/api/product/types' |
||||||
|
|
||||||
|
defineOptions({ name: 'ModelServiceFormModal' }) |
||||||
|
|
||||||
|
const emit = defineEmits(['success', 'register']) |
||||||
|
|
||||||
|
const isUpdate = ref(false) |
||||||
|
const [registerForm, { setFieldsValue, validate }] = useForm({ |
||||||
|
labelWidth: 80, |
||||||
|
baseColProps: { span: 24 }, |
||||||
|
schemas: [ |
||||||
|
{ |
||||||
|
field: 'id', |
||||||
|
show: false, |
||||||
|
component: 'Input', |
||||||
|
}, |
||||||
|
{ |
||||||
|
field: 'serviceId', |
||||||
|
label: '服务 ID', |
||||||
|
required: true, |
||||||
|
component: 'Input', |
||||||
|
componentProps: { |
||||||
|
maxlength: 30, |
||||||
|
showCount: true, |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
field: 'description', |
||||||
|
label: '服务描述', |
||||||
|
required: true, |
||||||
|
component: 'InputTextArea', |
||||||
|
}, |
||||||
|
], |
||||||
|
showActionButtonGroup: false, |
||||||
|
actionColOptions: { span: 23 }, |
||||||
|
}) |
||||||
|
|
||||||
|
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data: ModelService) => { |
||||||
|
isUpdate.value = true |
||||||
|
setFieldsValue({ ...data }) |
||||||
|
}) |
||||||
|
|
||||||
|
const route = useRoute() |
||||||
|
async function handleSubmit() { |
||||||
|
try { |
||||||
|
const values = await validate<ModelService>() |
||||||
|
setModalProps({ confirmLoading: true }) |
||||||
|
values.productId = route.params.id as string |
||||||
|
await (isUpdate.value ? updateModelService(values) : createModelService(values)) |
||||||
|
closeModal() |
||||||
|
emit('success') |
||||||
|
useMessage().createMessage.success('保存成功') |
||||||
|
} |
||||||
|
finally { |
||||||
|
setModalProps({ confirmLoading: false }) |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<template> |
||||||
|
<BasicModal |
||||||
|
v-bind="$attrs" |
||||||
|
width="30%" |
||||||
|
:min-height="100" |
||||||
|
:title="isUpdate ? '编辑' : '新增'" |
||||||
|
:after-close="() => isUpdate = false" |
||||||
|
@register="registerModal" |
||||||
|
@ok="handleSubmit" |
||||||
|
> |
||||||
|
<BasicForm @register="registerForm" /> |
||||||
|
</BasicModal> |
||||||
|
</template> |
@ -0,0 +1,73 @@ |
|||||||
|
import { unref, watch } from 'vue' |
||||||
|
import type { MaybeRef, Ref } from 'vue' |
||||||
|
import { useTable } from '@/components/Table' |
||||||
|
import { deleteModelAttribute, getModelAttributeList } from '@/api/product/model' |
||||||
|
import { useModal } from '@/components/Modal' |
||||||
|
import type { ModelAttribute } from '@/api/product/types' |
||||||
|
import { useMessage } from '@/hooks/web/useMessage' |
||||||
|
|
||||||
|
export function useModelAttribute(productId: MaybeRef<string>, modelId: Ref<string | undefined>) { |
||||||
|
const [registerModelAttributeTable, { reload, setPagination }] = useTable({ |
||||||
|
async api(params) { |
||||||
|
if (!unref(modelId)) |
||||||
|
return [] |
||||||
|
|
||||||
|
return getModelAttributeList({ |
||||||
|
...params, |
||||||
|
productId: unref(productId), |
||||||
|
modelId: unref(modelId), |
||||||
|
}) |
||||||
|
}, |
||||||
|
columns: [ |
||||||
|
{ |
||||||
|
title: '功能类型', |
||||||
|
dataIndex: 'itemType', |
||||||
|
customRender: ({ value }) => ({ 1: '属性', 2: '命令' }[value]), |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '功能名称', |
||||||
|
dataIndex: 'name', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '标识符', |
||||||
|
dataIndex: 'identifier', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '数据类型', |
||||||
|
dataIndex: 'dataType', |
||||||
|
}, |
||||||
|
], |
||||||
|
bordered: true, |
||||||
|
inset: true, |
||||||
|
canResize: false, |
||||||
|
actionColumn: { |
||||||
|
width: 150, |
||||||
|
title: '操作', |
||||||
|
dataIndex: 'action', |
||||||
|
fixed: 'right', |
||||||
|
}, |
||||||
|
}) |
||||||
|
watch(modelId, () => { |
||||||
|
setPagination({ current: 1 }) |
||||||
|
reload() |
||||||
|
}) |
||||||
|
|
||||||
|
const [registerModelAttributeModal, { openModal: openModelAttributeModal }] = useModal<ModelAttribute>() |
||||||
|
|
||||||
|
async function handleDeleteModelAttribute(id: string) { |
||||||
|
try { |
||||||
|
await deleteModelAttribute(id) |
||||||
|
useMessage().createMessage.success('删除成功') |
||||||
|
reload() |
||||||
|
} |
||||||
|
catch {} |
||||||
|
} |
||||||
|
|
||||||
|
return { |
||||||
|
registerModelAttributeTable, |
||||||
|
registerModelAttributeModal, |
||||||
|
openModelAttributeModal, |
||||||
|
reloadModalAttribute: reload, |
||||||
|
handleDeleteModelAttribute, |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
import { useAsyncState, watchOnce } from '@vueuse/core' |
||||||
|
import type { MaybeRef } from 'vue' |
||||||
|
import { ref, unref } from 'vue' |
||||||
|
import { deleteModelService, getAllModelServices } from '@/api/product/model' |
||||||
|
import { useMessage } from '@/hooks/web/useMessage' |
||||||
|
import { useModal } from '@/components/Modal' |
||||||
|
import type { ModelService } from '@/api/product/types' |
||||||
|
|
||||||
|
export function useModelService(productId: MaybeRef<string>) { |
||||||
|
const selectedModelId = ref<string>() |
||||||
|
|
||||||
|
const { state, execute } = useAsyncState(() => getAllModelServices(unref(productId)), [], { resetOnExecute: false }) |
||||||
|
|
||||||
|
watchOnce(state, () => { |
||||||
|
if (state.value.length > 0) |
||||||
|
selectedModelId.value = state.value[0].id |
||||||
|
}) |
||||||
|
|
||||||
|
const [registerModelServiceModal, { openModal }] = useModal<ModelService>() |
||||||
|
|
||||||
|
async function handleDeleteModelService(id: string) { |
||||||
|
try { |
||||||
|
await deleteModelService(id) |
||||||
|
useMessage().createMessage.success('删除成功') |
||||||
|
execute() |
||||||
|
} |
||||||
|
catch {} |
||||||
|
} |
||||||
|
|
||||||
|
return { |
||||||
|
selectedModelId, |
||||||
|
setSelectedModelId: (id: string) => selectedModelId.value = id, |
||||||
|
reloadModelService: execute, |
||||||
|
modelServiceList: state, |
||||||
|
handleDeleteModelService, |
||||||
|
registerModelServiceModal, |
||||||
|
openModelServiceModal: openModal, |
||||||
|
} |
||||||
|
} |
@ -1 +1,2 @@ |
|||||||
export { default as TopicManage } from './TopicManage.vue' |
export { default as TopicManage } from './TopicManage.vue' |
||||||
|
export { default as Model } from './Model.vue' |
||||||
|
Loading…
Reference in new issue