refactor:【antd】【iot】产品详情修改路径到 detail

This commit is contained in:
haohao
2025-12-15 22:48:09 +08:00
parent 5cb412a4da
commit 3744069aa2
6 changed files with 55 additions and 69 deletions

View File

@@ -19,7 +19,7 @@ const routes: RouteRecordRaw[] = [
activePath: '/iot/device/product',
},
component: () =>
import('#/views/iot/product/product/modules/detail/index.vue'),
import('#/views/iot/product/product/detail/index.vue'),
},
{
path: 'device/detail/:id',

View File

@@ -14,18 +14,13 @@ import { getSimpleProductCategoryList } from '#/api/iot/product/category';
/** 产品分类列表缓存 */
let categoryList: IotProductCategoryApi.ProductCategory[] = [];
/** 加载产品分类数据 */
async function loadCategoryData() {
categoryList = await getSimpleProductCategoryList();
}
// 初始化加载分类数据
// TODO @haohao可以参考 /Users/yunai/Java/yudao-ui-admin-vben-v5/apps/web-antd/src/views/system/tenant/data.ts 简洁一点。
loadCategoryData();
getSimpleProductCategoryList().then((data) => (categoryList = data));
/** 新增/修改产品的表单 */
export function useFormSchema(formApi?: any): VbenFormSchema[] {
export function useFormSchema(
formApi?: any,
generateProductKey?: () => string,
): VbenFormSchema[] {
return [
{
component: 'Input',
@@ -59,7 +54,9 @@ export function useFormSchema(formApi?: any): VbenFormSchema[] {
{
type: 'default',
onClick: () => {
formApi?.setFieldValue('productKey', generateProductKey());
if (generateProductKey) {
formApi?.setFieldValue('productKey', generateProductKey());
}
},
},
{ default: () => '重新生成' },
@@ -175,7 +172,10 @@ export function useFormSchema(formApi?: any): VbenFormSchema[] {
}
/** 基础表单字段(不含图标、图片、描述) */
export function useBasicFormSchema(formApi?: any): VbenFormSchema[] {
export function useBasicFormSchema(
formApi?: any,
generateProductKey?: () => string,
): VbenFormSchema[] {
return [
{
component: 'Input',
@@ -208,7 +208,9 @@ export function useBasicFormSchema(formApi?: any): VbenFormSchema[] {
{
type: 'default',
onClick: () => {
formApi?.setFieldValue('productKey', generateProductKey());
if (generateProductKey) {
formApi?.setFieldValue('productKey', generateProductKey());
}
},
},
{ default: () => '重新生成' },
@@ -299,6 +301,7 @@ export function useBasicFormSchema(formApi?: any): VbenFormSchema[] {
buttonStyle: 'solid',
optionType: 'button',
},
defaultValue: 0,
rules: 'required',
},
{
@@ -339,7 +342,6 @@ export function useAdvancedFormSchema(): VbenFormSchema[] {
placeholder: '请输入产品描述',
rows: 3,
},
formItemClass: 'col-span-2', // 让描述占满两列
},
];
}
@@ -404,13 +406,3 @@ export function useGridColumns(): VxeTableGridOptions['columns'] {
];
}
/** 生成 ProductKey包含大小写字母和数字 */
export function generateProductKey(): string {
const chars =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
for (let i = 0; i < 16; i++) {
result += chars.charAt(Math.floor(Math.random() * chars.length));
}
return result;
}

View File

@@ -28,7 +28,6 @@ const activeTab = ref('info');
provide('product', product); //
/** 获取产品详情 */
// TODO @haohao detail modules web-antd/src/views/iot/product/product/detail/index.vue
async function getProductData(productId: number) {
loading.value = true;
try {
@@ -91,3 +90,4 @@ onMounted(async () => {
</Tabs>
</Page>
</template>

View File

@@ -10,7 +10,7 @@ import { Button, Card, Descriptions, message, Modal } from 'ant-design-vue';
import { updateProductStatus } from '#/api/iot/product/product';
import Form from '../../form.vue';
import Form from '../../modules/form.vue';
interface Props {
product: IotProductApi.Product;

View File

@@ -1,7 +1,7 @@
<script lang="ts" setup>
import type { IotProductApi } from '#/api/iot/product/product';
import { computed, ref } from 'vue';
import { computed, nextTick, ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
@@ -15,11 +15,18 @@ import {
} from '#/api/iot/product/product';
import { $t } from '#/locales';
import {
generateProductKey,
useAdvancedFormSchema,
useBasicFormSchema,
} from '../data';
import { useAdvancedFormSchema, useBasicFormSchema } from '../data';
/** 生成 ProductKey包含大小写字母和数字 */
function generateProductKey(): string {
const chars =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
for (let i = 0; i < 16; i++) {
result += chars.charAt(Math.floor(Math.random() * chars.length));
}
return result;
}
const emit = defineEmits(['success']);
const formData = ref<IotProductApi.Product>();
@@ -37,10 +44,9 @@ const [Form, formApi] = useVbenForm({
layout: 'horizontal',
schema: [],
showDefaultActions: false,
wrapperClass: 'grid-cols-2',
wrapperClass: 'grid-cols-1',
});
// TODO @haohao这个要不还是一行一个这样样式好看点哈。
const [AdvancedForm, advancedFormApi] = useVbenForm({
commonConfig: {
componentProps: { class: 'w-full' },
@@ -48,12 +54,24 @@ const [AdvancedForm, advancedFormApi] = useVbenForm({
layout: 'horizontal',
schema: useAdvancedFormSchema(),
showDefaultActions: false,
wrapperClass: 'grid-cols-2',
wrapperClass: 'grid-cols-1',
});
/** 基础表单需要 formApi 引用,所以通过 setState 设置 schema */
// TODO haohao@haohao要不要把 generateProductKey 拿到这个 vue 里,作为参数传递到 useBasicFormSchema 里?
formApi.setState({ schema: useBasicFormSchema(formApi) });
formApi.setState({ schema: useBasicFormSchema(formApi, generateProductKey) });
/** 获取高级表单的值(如果表单未挂载,则从 formData 中获取) */
async function getAdvancedFormValues() {
if (advancedFormApi.isMounted) {
return await advancedFormApi.getValues();
}
// 表单未挂载(折叠状态),从 formData 中获取
return {
icon: formData.value?.icon,
picUrl: formData.value?.picUrl,
description: formData.value?.description,
};
}
const [Modal, modalApi] = useVbenModal({
async onConfirm() {
@@ -62,18 +80,9 @@ const [Modal, modalApi] = useVbenModal({
return;
}
modalApi.lock();
// 合并两个表单的值
// 合并两个表单的值(字段不冲突,可直接合并)
const basicValues = await formApi.getValues();
// TODO @haohao有 linter 修复下“formData.value?.id”另外这里直接两个表单合并是不是就可以了呀因为 2 个 schema 本身不同,字段就不同,不会冲突。
const advancedValues = activeKey.value.includes('advanced')
? await advancedFormApi.getValues()
: formData.value?.id
? {
icon: formData.value.icon,
picUrl: formData.value.picUrl,
description: formData.value.description,
}
: {};
const advancedValues = await getAdvancedFormValues();
const data = {
...basicValues,
...advancedValues,
@@ -96,12 +105,9 @@ const [Modal, modalApi] = useVbenModal({
// 加载数据
const data = modalApi.getData<IotProductApi.Product>();
if (!data || !data.id) {
// 新增:设置默认值
// TODO @AI
// 新增:设置默认值status 通过 schema 中的 defaultValue 自动设置为 0
await formApi.setValues({
// TODO @haohao要不要把 generateProductKey 拿到这个 vue 里,作为参数传递到 useBasicFormSchema 里?
productKey: generateProductKey(),
status: 0, // TODO @haohao通过 defaultValue 即可;
});
return;
}
@@ -110,22 +116,10 @@ const [Modal, modalApi] = useVbenModal({
try {
formData.value = await getProduct(data.id);
await formApi.setValues(formData.value);
// 设置高级表单(不等待
// TODO @haohao直接把 formData 传过去?没关系的哈。因为会 filter 掉不存在的值,可以试试哈。
// TODO @haohao这里是不是要 await 下呀?有黄色的告警;
advancedFormApi.setValues({
icon: formData.value.icon,
picUrl: formData.value.picUrl,
description: formData.value.description,
});
// 有高级字段时自动展开
// TODO @haohao默认不用展开哈。
if (
formData.value.icon ||
formData.value.picUrl ||
formData.value.description
) {
activeKey.value = ['advanced'];
// 设置高级表单(如果已挂载
await nextTick();
if (advancedFormApi.isMounted) {
await advancedFormApi.setValues(formData.value);
}
} finally {
modalApi.unlock();