chore: crm product detail
parent
5af9be3814
commit
b705a81eb0
|
@ -1,11 +1,20 @@
|
||||||
import type { VbenFormSchema } from '#/adapter/form';
|
import type { VbenFormSchema } from '#/adapter/form';
|
||||||
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
|
import type { DescriptionItemSchema } from '#/components/description';
|
||||||
|
|
||||||
|
import { h } from 'vue';
|
||||||
|
|
||||||
import { handleTree } from '@vben/utils';
|
import { handleTree } from '@vben/utils';
|
||||||
|
|
||||||
import { z } from '#/adapter/form';
|
import { z } from '#/adapter/form';
|
||||||
import { getProductCategoryList } from '#/api/crm/product/category';
|
import { getProductCategoryList } from '#/api/crm/product/category';
|
||||||
import { CommonStatusEnum, DICT_TYPE, getDictOptions } from '#/utils';
|
import { DictTag } from '#/components/dict-tag';
|
||||||
|
import {
|
||||||
|
CommonStatusEnum,
|
||||||
|
DICT_TYPE,
|
||||||
|
erpPriceInputFormatter,
|
||||||
|
getDictOptions,
|
||||||
|
} from '#/utils';
|
||||||
|
|
||||||
/** 新增/修改的表单 */
|
/** 新增/修改的表单 */
|
||||||
export function useFormSchema(): VbenFormSchema[] {
|
export function useFormSchema(): VbenFormSchema[] {
|
||||||
|
@ -174,3 +183,67 @@ export function useGridColumns(): VxeTableGridOptions['columns'] {
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 详情页的字段 */
|
||||||
|
export function useDetailSchema(): DescriptionItemSchema[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
field: 'categoryName',
|
||||||
|
label: '产品类别',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'unit',
|
||||||
|
label: '产品单位',
|
||||||
|
content: (data) =>
|
||||||
|
h(DictTag, { type: DICT_TYPE.CRM_PRODUCT_UNIT, value: data?.unit }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'price',
|
||||||
|
label: '产品价格',
|
||||||
|
content: (data) => erpPriceInputFormatter(data.price),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'no',
|
||||||
|
label: '产品编码',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 详情页的基础字段 */
|
||||||
|
export function useDetailBaseSchema(): DescriptionItemSchema[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
field: 'name',
|
||||||
|
label: '产品名称',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'no',
|
||||||
|
label: '产品编码',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'price',
|
||||||
|
label: '价格(元)',
|
||||||
|
content: (data) => erpPriceInputFormatter(data.price),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'description',
|
||||||
|
label: '产品描述',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'categoryName',
|
||||||
|
label: '产品类型',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'status',
|
||||||
|
label: '是否上下架',
|
||||||
|
content: (data) =>
|
||||||
|
h(DictTag, { type: DICT_TYPE.CRM_PRODUCT_STATUS, value: data?.status }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'unit',
|
||||||
|
label: '产品单位',
|
||||||
|
content: (data) =>
|
||||||
|
h(DictTag, { type: DICT_TYPE.CRM_PRODUCT_UNIT, value: data?.unit }),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,29 @@
|
||||||
<script lang="ts" setup></script>
|
<script lang="ts" setup>
|
||||||
|
import type { CrmProductApi } from '#/api/crm/product';
|
||||||
|
|
||||||
|
import { useDescription } from '#/components/description';
|
||||||
|
|
||||||
|
import { useDetailBaseSchema } from '../data';
|
||||||
|
|
||||||
|
defineOptions({ name: 'CrmProductDetailsInfo' });
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
product: CrmProductApi.Product; // 产品信息
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const [ProductDescription] = useDescription({
|
||||||
|
componentProps: {
|
||||||
|
title: '基本信息',
|
||||||
|
bordered: false,
|
||||||
|
column: 4,
|
||||||
|
class: 'mx-4',
|
||||||
|
},
|
||||||
|
schema: useDetailBaseSchema(),
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>productInfo</div>
|
<div class="p-4">
|
||||||
|
<ProductDescription :data="product" />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
<script lang="ts" setup></script>
|
|
||||||
<template>
|
|
||||||
<div>productList</div>
|
|
||||||
</template>
|
|
|
@ -1,7 +1,94 @@
|
||||||
<script lang="ts" setup></script>
|
<script setup lang="ts">
|
||||||
|
import type { CrmProductApi } from '#/api/crm/product';
|
||||||
|
import type { SystemOperateLogApi } from '#/api/system/operate-log';
|
||||||
|
|
||||||
|
import { defineAsyncComponent, onMounted, ref } from 'vue';
|
||||||
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
import { Page } from '@vben/common-ui';
|
||||||
|
import { useTabs } from '@vben/hooks';
|
||||||
|
|
||||||
|
import { Button, Card, Tabs } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { getOperateLogPage } from '#/api/crm/operateLog';
|
||||||
|
import { BizTypeEnum } from '#/api/crm/permission';
|
||||||
|
import { getProduct } from '#/api/crm/product';
|
||||||
|
import { useDescription } from '#/components/description';
|
||||||
|
|
||||||
|
import { useDetailSchema } from '../data';
|
||||||
|
|
||||||
|
const ProductDetailsInfo = defineAsyncComponent(
|
||||||
|
() => import('./detail-info.vue'),
|
||||||
|
);
|
||||||
|
|
||||||
|
const OperateLog = defineAsyncComponent(
|
||||||
|
() => import('#/components/operate-log'),
|
||||||
|
);
|
||||||
|
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const router = useRouter();
|
||||||
|
const tabs = useTabs();
|
||||||
|
|
||||||
|
const productId = ref(0);
|
||||||
|
|
||||||
|
const product = ref<CrmProductApi.Product>({} as CrmProductApi.Product);
|
||||||
|
const productLogList = ref<SystemOperateLogApi.OperateLog[]>([]);
|
||||||
|
|
||||||
|
const [Description] = useDescription({
|
||||||
|
componentProps: {
|
||||||
|
bordered: false,
|
||||||
|
column: 4,
|
||||||
|
class: 'mx-4',
|
||||||
|
},
|
||||||
|
schema: useDetailSchema(),
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 加载详情 */
|
||||||
|
async function loadProductDetail() {
|
||||||
|
loading.value = true;
|
||||||
|
const data = await getProduct(productId.value);
|
||||||
|
const logList = await getOperateLogPage({
|
||||||
|
bizType: BizTypeEnum.CRM_PRODUCT,
|
||||||
|
bizId: productId.value,
|
||||||
|
});
|
||||||
|
productLogList.value = logList.list;
|
||||||
|
product.value = data;
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 返回列表页 */
|
||||||
|
function handleBack() {
|
||||||
|
tabs.closeCurrentTab();
|
||||||
|
router.push('/crm/product');
|
||||||
|
}
|
||||||
|
// 加载数据
|
||||||
|
onMounted(async () => {
|
||||||
|
productId.value = Number(route.params.id);
|
||||||
|
await loadProductDetail();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<Page auto-content-height :title="product?.name" :loading="loading">
|
||||||
<p>待完成</p>
|
<template #extra>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<Button @click="handleBack"> 返回 </Button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<Card class="min-h-[10%]">
|
||||||
|
<Description :data="product" />
|
||||||
|
</Card>
|
||||||
|
<Card class="mt-4 min-h-[60%]">
|
||||||
|
<Tabs>
|
||||||
|
<Tabs.TabPane tab="详细资料" key="1" :force-render="true">
|
||||||
|
<ProductDetailsInfo :product="product" />
|
||||||
|
</Tabs.TabPane>
|
||||||
|
<Tabs.TabPane tab="操作日志" key="2" :force-render="true">
|
||||||
|
<OperateLog :log-list="productLogList" />
|
||||||
|
</Tabs.TabPane>
|
||||||
|
</Tabs>
|
||||||
|
</Card>
|
||||||
|
</Page>
|
||||||
|
</template>
|
||||||
|
|
Loading…
Reference in New Issue