refactor:【antd】【iot】产品详情修改路径到 detail
This commit is contained in:
@@ -19,7 +19,7 @@ const routes: RouteRecordRaw[] = [
|
|||||||
activePath: '/iot/device/product',
|
activePath: '/iot/device/product',
|
||||||
},
|
},
|
||||||
component: () =>
|
component: () =>
|
||||||
import('#/views/iot/product/product/modules/detail/index.vue'),
|
import('#/views/iot/product/product/detail/index.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'device/detail/:id',
|
path: 'device/detail/:id',
|
||||||
|
|||||||
@@ -14,18 +14,13 @@ import { getSimpleProductCategoryList } from '#/api/iot/product/category';
|
|||||||
|
|
||||||
/** 产品分类列表缓存 */
|
/** 产品分类列表缓存 */
|
||||||
let categoryList: IotProductCategoryApi.ProductCategory[] = [];
|
let categoryList: IotProductCategoryApi.ProductCategory[] = [];
|
||||||
|
getSimpleProductCategoryList().then((data) => (categoryList = data));
|
||||||
/** 加载产品分类数据 */
|
|
||||||
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();
|
|
||||||
|
|
||||||
/** 新增/修改产品的表单 */
|
/** 新增/修改产品的表单 */
|
||||||
export function useFormSchema(formApi?: any): VbenFormSchema[] {
|
export function useFormSchema(
|
||||||
|
formApi?: any,
|
||||||
|
generateProductKey?: () => string,
|
||||||
|
): VbenFormSchema[] {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
component: 'Input',
|
component: 'Input',
|
||||||
@@ -59,7 +54,9 @@ export function useFormSchema(formApi?: any): VbenFormSchema[] {
|
|||||||
{
|
{
|
||||||
type: 'default',
|
type: 'default',
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
formApi?.setFieldValue('productKey', generateProductKey());
|
if (generateProductKey) {
|
||||||
|
formApi?.setFieldValue('productKey', generateProductKey());
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ default: () => '重新生成' },
|
{ 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 [
|
return [
|
||||||
{
|
{
|
||||||
component: 'Input',
|
component: 'Input',
|
||||||
@@ -208,7 +208,9 @@ export function useBasicFormSchema(formApi?: any): VbenFormSchema[] {
|
|||||||
{
|
{
|
||||||
type: 'default',
|
type: 'default',
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
formApi?.setFieldValue('productKey', generateProductKey());
|
if (generateProductKey) {
|
||||||
|
formApi?.setFieldValue('productKey', generateProductKey());
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ default: () => '重新生成' },
|
{ default: () => '重新生成' },
|
||||||
@@ -299,6 +301,7 @@ export function useBasicFormSchema(formApi?: any): VbenFormSchema[] {
|
|||||||
buttonStyle: 'solid',
|
buttonStyle: 'solid',
|
||||||
optionType: 'button',
|
optionType: 'button',
|
||||||
},
|
},
|
||||||
|
defaultValue: 0,
|
||||||
rules: 'required',
|
rules: 'required',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -339,7 +342,6 @@ export function useAdvancedFormSchema(): VbenFormSchema[] {
|
|||||||
placeholder: '请输入产品描述',
|
placeholder: '请输入产品描述',
|
||||||
rows: 3,
|
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;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ const activeTab = ref('info');
|
|||||||
provide('product', product); // 提供产品信息给子组件
|
provide('product', product); // 提供产品信息给子组件
|
||||||
|
|
||||||
/** 获取产品详情 */
|
/** 获取产品详情 */
|
||||||
// TODO @haohao:因为 detail 是独立界面,所以不放在 modules 里,应该放在 web-antd/src/views/iot/product/product/detail/index.vue 里,更合理一些哈。
|
|
||||||
async function getProductData(productId: number) {
|
async function getProductData(productId: number) {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
@@ -91,3 +90,4 @@ onMounted(async () => {
|
|||||||
</Tabs>
|
</Tabs>
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ import { Button, Card, Descriptions, message, Modal } from 'ant-design-vue';
|
|||||||
|
|
||||||
import { updateProductStatus } from '#/api/iot/product/product';
|
import { updateProductStatus } from '#/api/iot/product/product';
|
||||||
|
|
||||||
import Form from '../../form.vue';
|
import Form from '../../modules/form.vue';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
product: IotProductApi.Product;
|
product: IotProductApi.Product;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { IotProductApi } from '#/api/iot/product/product';
|
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';
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
|
|
||||||
@@ -15,11 +15,18 @@ import {
|
|||||||
} from '#/api/iot/product/product';
|
} from '#/api/iot/product/product';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
||||||
import {
|
import { useAdvancedFormSchema, useBasicFormSchema } from '../data';
|
||||||
generateProductKey,
|
|
||||||
useAdvancedFormSchema,
|
/** 生成 ProductKey(包含大小写字母和数字) */
|
||||||
useBasicFormSchema,
|
function generateProductKey(): string {
|
||||||
} from '../data';
|
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 emit = defineEmits(['success']);
|
||||||
const formData = ref<IotProductApi.Product>();
|
const formData = ref<IotProductApi.Product>();
|
||||||
@@ -37,10 +44,9 @@ const [Form, formApi] = useVbenForm({
|
|||||||
layout: 'horizontal',
|
layout: 'horizontal',
|
||||||
schema: [],
|
schema: [],
|
||||||
showDefaultActions: false,
|
showDefaultActions: false,
|
||||||
wrapperClass: 'grid-cols-2',
|
wrapperClass: 'grid-cols-1',
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO @haohao:这个要不还是一行一个?这样样式好看点哈。
|
|
||||||
const [AdvancedForm, advancedFormApi] = useVbenForm({
|
const [AdvancedForm, advancedFormApi] = useVbenForm({
|
||||||
commonConfig: {
|
commonConfig: {
|
||||||
componentProps: { class: 'w-full' },
|
componentProps: { class: 'w-full' },
|
||||||
@@ -48,12 +54,24 @@ const [AdvancedForm, advancedFormApi] = useVbenForm({
|
|||||||
layout: 'horizontal',
|
layout: 'horizontal',
|
||||||
schema: useAdvancedFormSchema(),
|
schema: useAdvancedFormSchema(),
|
||||||
showDefaultActions: false,
|
showDefaultActions: false,
|
||||||
wrapperClass: 'grid-cols-2',
|
wrapperClass: 'grid-cols-1',
|
||||||
});
|
});
|
||||||
|
|
||||||
/** 基础表单需要 formApi 引用,所以通过 setState 设置 schema */
|
/** 基础表单需要 formApi 引用,所以通过 setState 设置 schema */
|
||||||
// TODO haohao:@haohao:要不要把 generateProductKey 拿到这个 vue 里,作为参数传递到 useBasicFormSchema 里?
|
formApi.setState({ schema: useBasicFormSchema(formApi, generateProductKey) });
|
||||||
formApi.setState({ schema: useBasicFormSchema(formApi) });
|
|
||||||
|
/** 获取高级表单的值(如果表单未挂载,则从 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({
|
const [Modal, modalApi] = useVbenModal({
|
||||||
async onConfirm() {
|
async onConfirm() {
|
||||||
@@ -62,18 +80,9 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
modalApi.lock();
|
modalApi.lock();
|
||||||
// 合并两个表单的值
|
// 合并两个表单的值(字段不冲突,可直接合并)
|
||||||
const basicValues = await formApi.getValues();
|
const basicValues = await formApi.getValues();
|
||||||
// TODO @haohao:有 linter 修复下;“formData.value?.id”;另外,这里直接两个表单合并,是不是就可以了呀?因为 2 个 schema 本身不同,字段就不同,不会冲突。
|
const advancedValues = await getAdvancedFormValues();
|
||||||
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 data = {
|
const data = {
|
||||||
...basicValues,
|
...basicValues,
|
||||||
...advancedValues,
|
...advancedValues,
|
||||||
@@ -96,12 +105,9 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
// 加载数据
|
// 加载数据
|
||||||
const data = modalApi.getData<IotProductApi.Product>();
|
const data = modalApi.getData<IotProductApi.Product>();
|
||||||
if (!data || !data.id) {
|
if (!data || !data.id) {
|
||||||
// 新增:设置默认值
|
// 新增:设置默认值(status 通过 schema 中的 defaultValue 自动设置为 0)
|
||||||
// TODO @AI:
|
|
||||||
await formApi.setValues({
|
await formApi.setValues({
|
||||||
// TODO @haohao:要不要把 generateProductKey 拿到这个 vue 里,作为参数传递到 useBasicFormSchema 里?
|
|
||||||
productKey: generateProductKey(),
|
productKey: generateProductKey(),
|
||||||
status: 0, // TODO @haohao:通过 defaultValue 即可;
|
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -110,22 +116,10 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
try {
|
try {
|
||||||
formData.value = await getProduct(data.id);
|
formData.value = await getProduct(data.id);
|
||||||
await formApi.setValues(formData.value);
|
await formApi.setValues(formData.value);
|
||||||
// 设置高级表单(不等待)
|
// 设置高级表单(如果已挂载)
|
||||||
// TODO @haohao:直接把 formData 传过去?没关系的哈。因为会 filter 掉不存在的值,可以试试哈。
|
await nextTick();
|
||||||
// TODO @haohao:这里是不是要 await 下呀?有黄色的告警;
|
if (advancedFormApi.isMounted) {
|
||||||
advancedFormApi.setValues({
|
await advancedFormApi.setValues(formData.value);
|
||||||
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'];
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
modalApi.unlock();
|
modalApi.unlock();
|
||||||
|
|||||||
Reference in New Issue
Block a user