Merge remote-tracking branch 'origin/dev' into dev
# Conflicts: # apps/web-antd/src/views/mall/promotion/point/activity/data.ts # apps/web-antd/src/views/mall/promotion/point/activity/index.vue
This commit is contained in:
@@ -18,7 +18,8 @@ const routes: RouteRecordRaw[] = [
|
|||||||
title: '产品详情',
|
title: '产品详情',
|
||||||
activePath: '/iot/device/product',
|
activePath: '/iot/device/product',
|
||||||
},
|
},
|
||||||
component: () => import('#/views/iot/product/product/modules/detail/index.vue'),
|
component: () =>
|
||||||
|
import('#/views/iot/product/product/modules/detail/index.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'device/detail/:id',
|
path: 'device/detail/:id',
|
||||||
@@ -27,7 +28,8 @@ const routes: RouteRecordRaw[] = [
|
|||||||
title: '设备详情',
|
title: '设备详情',
|
||||||
activePath: '/iot/device/device',
|
activePath: '/iot/device/device',
|
||||||
},
|
},
|
||||||
component: () => import('#/views/iot/device/device/modules/detail/index.vue'),
|
component: () =>
|
||||||
|
import('#/views/iot/device/device/modules/detail/index.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'ota/firmware/detail/:id',
|
path: 'ota/firmware/detail/:id',
|
||||||
@@ -36,11 +38,11 @@ const routes: RouteRecordRaw[] = [
|
|||||||
title: '固件详情',
|
title: '固件详情',
|
||||||
activePath: '/iot/ota',
|
activePath: '/iot/ota',
|
||||||
},
|
},
|
||||||
component: () => import('#/views/iot/ota/modules/firmware-detail/index.vue'),
|
component: () =>
|
||||||
|
import('#/views/iot/ota/modules/firmware-detail/index.vue'),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export default routes;
|
export default routes;
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ const [Grid] = useVbenVxeGrid({
|
|||||||
{
|
{
|
||||||
fieldName: 'followUpStatus',
|
fieldName: 'followUpStatus',
|
||||||
label: '状态',
|
label: '状态',
|
||||||
component: 'Select',
|
component: 'RadioGroup',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
allowClear: true,
|
allowClear: true,
|
||||||
options: FOLLOWUP_STATUS,
|
options: FOLLOWUP_STATUS,
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ const [Grid] = useVbenVxeGrid({
|
|||||||
{
|
{
|
||||||
fieldName: 'followUpStatus',
|
fieldName: 'followUpStatus',
|
||||||
label: '状态',
|
label: '状态',
|
||||||
component: 'Select',
|
component: 'RadioGroup',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
allowClear: true,
|
allowClear: true,
|
||||||
options: FOLLOWUP_STATUS,
|
options: FOLLOWUP_STATUS,
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
{
|
{
|
||||||
fieldName: 'transformStatus',
|
fieldName: 'transformStatus',
|
||||||
label: '转化状态',
|
label: '转化状态',
|
||||||
component: 'Select',
|
component: 'RadioGroup',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
options: [
|
options: [
|
||||||
{ label: '未转化', value: false },
|
{ label: '未转化', value: false },
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ export function useFormSchema(): VbenFormSchema[] {
|
|||||||
label: '接收的用户',
|
label: '接收的用户',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: () => getSimpleUserList(),
|
api: getSimpleUserList,
|
||||||
labelField: 'nickname',
|
labelField: 'nickname',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
mode: 'multiple',
|
mode: 'multiple',
|
||||||
@@ -124,7 +124,10 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
fieldName: 'createTime',
|
fieldName: 'createTime',
|
||||||
label: '创建时间',
|
label: '创建时间',
|
||||||
component: 'RangePicker',
|
component: 'RangePicker',
|
||||||
componentProps: getRangePickerDefaultProps(),
|
componentProps: {
|
||||||
|
...getRangePickerDefaultProps(),
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
label: '告警配置',
|
label: '告警配置',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: () => getSimpleAlertConfigList(),
|
api: getSimpleAlertConfigList,
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '请选择告警配置',
|
placeholder: '请选择告警配置',
|
||||||
@@ -40,7 +40,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
label: '产品',
|
label: '产品',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: () => getSimpleProductList(),
|
api: getSimpleProductList,
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '请选择产品',
|
placeholder: '请选择产品',
|
||||||
@@ -53,7 +53,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
label: '设备',
|
label: '设备',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: () => getSimpleDeviceList(),
|
api: getSimpleDeviceList,
|
||||||
labelField: 'deviceName',
|
labelField: 'deviceName',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '请选择设备',
|
placeholder: '请选择设备',
|
||||||
@@ -75,7 +75,10 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
fieldName: 'createTime',
|
fieldName: 'createTime',
|
||||||
label: '创建时间',
|
label: '创建时间',
|
||||||
component: 'RangePicker',
|
component: 'RangePicker',
|
||||||
componentProps: getRangePickerDefaultProps(),
|
componentProps: {
|
||||||
|
...getRangePickerDefaultProps(),
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export function useFormSchema(): VbenFormSchema[] {
|
|||||||
label: '产品',
|
label: '产品',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: () => getSimpleProductList(),
|
api: getSimpleProductList,
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '请选择产品',
|
placeholder: '请选择产品',
|
||||||
@@ -89,7 +89,7 @@ export function useFormSchema(): VbenFormSchema[] {
|
|||||||
label: '设备分组',
|
label: '设备分组',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: () => getSimpleDeviceGroupList(),
|
api: getSimpleDeviceGroupList,
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
mode: 'multiple',
|
mode: 'multiple',
|
||||||
@@ -156,7 +156,7 @@ export function useGroupFormSchema(): VbenFormSchema[] {
|
|||||||
label: '设备分组',
|
label: '设备分组',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: () => getSimpleDeviceGroupList(),
|
api: getSimpleDeviceGroupList,
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
mode: 'multiple',
|
mode: 'multiple',
|
||||||
@@ -199,7 +199,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
label: '产品',
|
label: '产品',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: () => getSimpleProductList(),
|
api: getSimpleProductList,
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '请选择产品',
|
placeholder: '请选择产品',
|
||||||
@@ -249,7 +249,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
label: '设备分组',
|
label: '设备分组',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: () => getSimpleDeviceGroupList(),
|
api: getSimpleDeviceGroupList,
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '请选择设备分组',
|
placeholder: '请选择设备分组',
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export function useFormSchema(): VbenFormSchema[] {
|
|||||||
label: '父级分组',
|
label: '父级分组',
|
||||||
component: 'ApiTreeSelect',
|
component: 'ApiTreeSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: () => getSimpleDeviceGroupList(),
|
api: getSimpleDeviceGroupList,
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '请选择父级分组',
|
placeholder: '请选择父级分组',
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export function useFormSchema(): VbenFormSchema[] {
|
|||||||
label: '所属产品',
|
label: '所属产品',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: () => getSimpleProductList(),
|
api: getSimpleProductList,
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '请选择产品',
|
placeholder: '请选择产品',
|
||||||
@@ -85,7 +85,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
label: '产品',
|
label: '产品',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: () => getSimpleProductList(),
|
api: getSimpleProductList,
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '请选择产品',
|
placeholder: '请选择产品',
|
||||||
@@ -96,7 +96,10 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
fieldName: 'createTime',
|
fieldName: 'createTime',
|
||||||
label: '创建时间',
|
label: '创建时间',
|
||||||
component: 'RangePicker',
|
component: 'RangePicker',
|
||||||
componentProps: getRangePickerDefaultProps(),
|
componentProps: {
|
||||||
|
...getRangePickerDefaultProps(),
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export function useFormSchema(): VbenFormSchema[] {
|
|||||||
label: '所属产品',
|
label: '所属产品',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: () => getSimpleProductList(),
|
api: getSimpleProductList,
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '请选择产品',
|
placeholder: '请选择产品',
|
||||||
@@ -86,7 +86,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
label: '产品',
|
label: '产品',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: () => getSimpleProductList(),
|
api: getSimpleProductList,
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '请选择产品',
|
placeholder: '请选择产品',
|
||||||
@@ -97,7 +97,10 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
fieldName: 'createTime',
|
fieldName: 'createTime',
|
||||||
label: '创建时间',
|
label: '创建时间',
|
||||||
component: 'RangePicker',
|
component: 'RangePicker',
|
||||||
componentProps: getRangePickerDefaultProps(),
|
componentProps: {
|
||||||
|
...getRangePickerDefaultProps(),
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,10 @@
|
|||||||
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
import type { IoTOtaFirmwareApi } from '#/api/iot/ota/firmware';
|
import type { IoTOtaFirmwareApi } from '#/api/iot/ota/firmware';
|
||||||
|
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { Page, useVbenModal } from '@vben/common-ui';
|
||||||
import { IconifyIcon } from '@vben/icons';
|
import { IconifyIcon } from '@vben/icons';
|
||||||
import { useRouter } from 'vue-router';
|
|
||||||
|
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
@@ -39,7 +40,6 @@ function handleEdit(row: IoTOtaFirmwareApi.Firmware) {
|
|||||||
formModalApi.setData({ type: 'update', id: row.id }).open();
|
formModalApi.setData({ type: 'update', id: row.id }).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** 删除固件 */
|
/** 删除固件 */
|
||||||
async function handleDelete(row: IoTOtaFirmwareApi.Firmware) {
|
async function handleDelete(row: IoTOtaFirmwareApi.Firmware) {
|
||||||
const hideLoading = message.loading({
|
const hideLoading = message.loading({
|
||||||
@@ -117,19 +117,25 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||||||
|
|
||||||
<!-- 固件文件列 -->
|
<!-- 固件文件列 -->
|
||||||
<template #fileUrl="{ row }">
|
<template #fileUrl="{ row }">
|
||||||
<div v-if="row.fileUrl" class="inline-flex items-center gap-1.5 align-middle leading-none">
|
<div
|
||||||
<IconifyIcon icon="ant-design:download-outlined" class="shrink-0 text-base align-middle text-primary" />
|
v-if="row.fileUrl"
|
||||||
<a
|
class="inline-flex items-center gap-1.5 align-middle leading-none"
|
||||||
:href="row.fileUrl"
|
>
|
||||||
target="_blank"
|
<IconifyIcon
|
||||||
download
|
icon="ant-design:download-outlined"
|
||||||
class="text-primary cursor-pointer hover:underline align-middle"
|
class="text-primary shrink-0 align-middle text-base"
|
||||||
>
|
/>
|
||||||
下载固件
|
<a
|
||||||
</a>
|
:href="row.fileUrl"
|
||||||
</div>
|
target="_blank"
|
||||||
<span v-else class="text-gray-400">无文件</span>
|
download
|
||||||
</template>
|
class="text-primary cursor-pointer align-middle hover:underline"
|
||||||
|
>
|
||||||
|
下载固件
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<span v-else class="text-gray-400">无文件</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
<!-- 操作列 -->
|
<!-- 操作列 -->
|
||||||
<template #actions="{ row }">
|
<template #actions="{ row }">
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export function useFormSchema(): VbenFormSchema[] {
|
|||||||
label: '父级分类',
|
label: '父级分类',
|
||||||
component: 'ApiTreeSelect',
|
component: 'ApiTreeSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: () => getSimpleProductCategoryList(),
|
api: getSimpleProductCategoryList,
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '请选择父级分类',
|
placeholder: '请选择父级分类',
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ export function useFormSchema(formApi?: any): VbenFormSchema[] {
|
|||||||
label: '产品分类',
|
label: '产品分类',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: () => getSimpleProductCategoryList(),
|
api: getSimpleProductCategoryList,
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '请选择产品分类',
|
placeholder: '请选择产品分类',
|
||||||
@@ -246,7 +246,7 @@ export function useBasicFormSchema(formApi?: any): VbenFormSchema[] {
|
|||||||
label: '产品分类',
|
label: '产品分类',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: () => getSimpleProductCategoryList(),
|
api: getSimpleProductCategoryList,
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '请选择产品分类',
|
placeholder: '请选择产品分类',
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
label: '产品',
|
label: '产品',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: () => getSimpleProductList(),
|
api: getSimpleProductList,
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
placeholder: '请选择产品',
|
placeholder: '请选择产品',
|
||||||
@@ -45,7 +45,10 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
fieldName: 'createTime',
|
fieldName: 'createTime',
|
||||||
label: '创建时间',
|
label: '创建时间',
|
||||||
component: 'RangePicker',
|
component: 'RangePicker',
|
||||||
componentProps: getRangePickerDefaultProps(),
|
componentProps: {
|
||||||
|
...getRangePickerDefaultProps(),
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,10 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
fieldName: 'createTime',
|
fieldName: 'createTime',
|
||||||
label: '创建时间',
|
label: '创建时间',
|
||||||
component: 'RangePicker',
|
component: 'RangePicker',
|
||||||
componentProps: getRangePickerDefaultProps(),
|
componentProps: {
|
||||||
|
...getRangePickerDefaultProps(),
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,10 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
fieldName: 'createTime',
|
fieldName: 'createTime',
|
||||||
label: '创建时间',
|
label: '创建时间',
|
||||||
component: 'RangePicker',
|
component: 'RangePicker',
|
||||||
componentProps: getRangePickerDefaultProps(),
|
componentProps: {
|
||||||
|
...getRangePickerDefaultProps(),
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,10 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
fieldName: 'createTime',
|
fieldName: 'createTime',
|
||||||
label: '创建时间',
|
label: '创建时间',
|
||||||
component: 'RangePicker',
|
component: 'RangePicker',
|
||||||
componentProps: getRangePickerDefaultProps(),
|
componentProps: {
|
||||||
|
...getRangePickerDefaultProps(),
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
{
|
{
|
||||||
fieldName: 'replyStatus',
|
fieldName: 'replyStatus',
|
||||||
label: '回复状态',
|
label: '回复状态',
|
||||||
component: 'Select',
|
component: 'RadioGroup',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
options: [
|
options: [
|
||||||
{ label: '已回复', value: true },
|
{ label: '已回复', value: true },
|
||||||
|
|||||||
@@ -283,7 +283,7 @@ function openPropertyAddForm() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 调用 SkuList generateTableData 方法*/
|
/** 调用 SkuList generateTableData 方法*/
|
||||||
function generateSkus(propertyList: any[]) {
|
function generateSkus(propertyList: PropertyAndValues[]) {
|
||||||
skuListRef.value.generateTableData(propertyList);
|
skuListRef.value.generateTableData(propertyList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ import type { MallPropertyApi } from '#/api/mall/product/property';
|
|||||||
|
|
||||||
import { computed, ref, watch } from 'vue';
|
import { computed, ref, watch } from 'vue';
|
||||||
|
|
||||||
import { Button, Col, Divider, message, Select, Tag } from 'ant-design-vue';
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
|
||||||
|
import { Col, Divider, message, Select, Tag } from 'ant-design-vue';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
createPropertyValue,
|
createPropertyValue,
|
||||||
@@ -80,13 +82,19 @@ watch(
|
|||||||
);
|
);
|
||||||
|
|
||||||
/** 删除属性值 */
|
/** 删除属性值 */
|
||||||
function handleCloseValue(index: number, valueIndex: number) {
|
function handleCloseValue(index: number, value: PropertyAndValues) {
|
||||||
attributeList.value?.[index]?.values?.splice(valueIndex, 1);
|
if (attributeList.value[index]) {
|
||||||
|
attributeList.value[index].values = attributeList.value?.[
|
||||||
|
index
|
||||||
|
]?.values?.filter((item) => item.id !== value.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除属性 */
|
/** 删除属性 */
|
||||||
function handleCloseProperty(index: number) {
|
function handleCloseProperty(item: PropertyAndValues) {
|
||||||
attributeList.value?.splice(index, 1);
|
attributeList.value = attributeList.value.filter(
|
||||||
|
(attribute) => attribute.id !== item.id,
|
||||||
|
);
|
||||||
emit('success', attributeList.value);
|
emit('success', attributeList.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,27 +166,28 @@ async function getAttributeOptions(propertyId: number) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Col v-for="(item, index) in attributeList" :key="index">
|
<Col v-for="(attribute, index) in attributeList" :key="index">
|
||||||
|
<Divider class="my-4" />
|
||||||
<!-- TODO @puhui999:1)间隙可以看看;2)vue3 + element-plus 添加属性这个按钮,是和属性名在一排,感觉更好看点。 -->
|
<!-- TODO @puhui999:1)间隙可以看看;2)vue3 + element-plus 添加属性这个按钮,是和属性名在一排,感觉更好看点。 -->
|
||||||
<div>
|
<div class="mt-1">
|
||||||
<span class="mx-1">属性名:</span>
|
<span class="mx-1">属性名:</span>
|
||||||
<Tag
|
<Tag
|
||||||
:closable="!isDetail"
|
:closable="!isDetail"
|
||||||
class="mx-1"
|
class="mx-1"
|
||||||
color="success"
|
color="success"
|
||||||
@close="handleCloseProperty(index)"
|
@close="handleCloseProperty(attribute)"
|
||||||
>
|
>
|
||||||
{{ item.name }}
|
{{ attribute.name }}
|
||||||
</Tag>
|
</Tag>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div class="mt-2">
|
||||||
<span class="mx-1">属性值:</span>
|
<span class="mx-1">属性值:</span>
|
||||||
<Tag
|
<Tag
|
||||||
v-for="(value, valueIndex) in item.values"
|
v-for="(value, valueIndex) in attribute.values"
|
||||||
:key="value.id"
|
:key="valueIndex"
|
||||||
:closable="!isDetail"
|
:closable="!isDetail"
|
||||||
class="mx-1"
|
class="mx-1"
|
||||||
@close="handleCloseValue(index, valueIndex)"
|
@close="handleCloseValue(index, value)"
|
||||||
>
|
>
|
||||||
<!-- TODO @puhui999:这里貌似爆红?!idea -->
|
<!-- TODO @puhui999:这里貌似爆红?!idea -->
|
||||||
{{ value.name }}
|
{{ value.name }}
|
||||||
@@ -194,9 +203,9 @@ async function getAttributeOptions(propertyId: number) {
|
|||||||
:filter-option="true"
|
:filter-option="true"
|
||||||
size="small"
|
size="small"
|
||||||
style="width: 100px"
|
style="width: 100px"
|
||||||
@blur="handleInputConfirm(index, item.id)"
|
@blur="handleInputConfirm(index, attribute.id)"
|
||||||
@change="handleInputConfirm(index, item.id)"
|
@change="handleInputConfirm(index, attribute.id)"
|
||||||
@keyup.enter="handleInputConfirm(index, item.id)"
|
@keyup.enter="handleInputConfirm(index, attribute.id)"
|
||||||
>
|
>
|
||||||
<Select.Option
|
<Select.Option
|
||||||
v-for="item2 in attributeOptions"
|
v-for="item2 in attributeOptions"
|
||||||
@@ -206,15 +215,16 @@ async function getAttributeOptions(propertyId: number) {
|
|||||||
{{ item2.name }}
|
{{ item2.name }}
|
||||||
</Select.Option>
|
</Select.Option>
|
||||||
</Select>
|
</Select>
|
||||||
<Button
|
<Tag
|
||||||
v-show="!inputVisible(index)"
|
v-show="!inputVisible(index)"
|
||||||
class="button-new-tag ml-1"
|
|
||||||
size="small"
|
|
||||||
@click="showInput(index)"
|
@click="showInput(index)"
|
||||||
|
class="mx-1 border-dashed bg-gray-100"
|
||||||
>
|
>
|
||||||
+ 添加
|
<div class="flex items-center">
|
||||||
</Button>
|
<IconifyIcon class="mr-2" icon="lucide:plus" />
|
||||||
|
添加
|
||||||
|
</div>
|
||||||
|
</Tag>
|
||||||
</div>
|
</div>
|
||||||
<Divider class="my-10px" />
|
|
||||||
</Col>
|
</Col>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -64,7 +64,6 @@ const formSchema: VbenFormSchema[] = [
|
|||||||
filterOption: true,
|
filterOption: true,
|
||||||
placeholder: '请选择属性名称。如果不存在,可手动输入选择',
|
placeholder: '请选择属性名称。如果不存在,可手动输入选择',
|
||||||
mode: 'tags',
|
mode: 'tags',
|
||||||
maxTagCount: 1,
|
|
||||||
allowClear: true,
|
allowClear: true,
|
||||||
},
|
},
|
||||||
rules: 'required',
|
rules: 'required',
|
||||||
@@ -77,7 +76,7 @@ const [Form, formApi] = useVbenForm({
|
|||||||
class: 'w-full',
|
class: 'w-full',
|
||||||
},
|
},
|
||||||
formItemClass: 'col-span-2',
|
formItemClass: 'col-span-2',
|
||||||
labelWidth: 120,
|
labelWidth: 80,
|
||||||
},
|
},
|
||||||
layout: 'horizontal',
|
layout: 'horizontal',
|
||||||
schema: formSchema,
|
schema: formSchema,
|
||||||
@@ -91,51 +90,47 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
if (!valid) {
|
if (!valid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
modalApi.lock();
|
||||||
const values = await formApi.getValues();
|
const values = await formApi.getValues();
|
||||||
const name = Array.isArray(values.name) ? values.name[0] : values.name;
|
// name 为数组,遍历数组,进行重复添加校验
|
||||||
// 重复添加校验
|
const names = values.name;
|
||||||
for (const attrItem of attributeList.value) {
|
for (const name of names) {
|
||||||
if (attrItem.name === name) {
|
// 重复添加校验
|
||||||
message.error('该属性已存在,请勿重复添加');
|
for (const attrItem of attributeList.value) {
|
||||||
return;
|
if (attrItem.name === name) {
|
||||||
|
message.error('该属性已存在,请勿重复添加');
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO @puhui999:modalApi.lock(); 这种写法;
|
for (const name of names) {
|
||||||
|
const existProperty = attributeOptions.value.find(
|
||||||
// 情况一:属性名已存在,则直接使用
|
(item: MallPropertyApi.Property) => item.name === name,
|
||||||
const existProperty = attributeOptions.value.find(
|
);
|
||||||
(item: MallPropertyApi.Property) => item.name === name,
|
if (existProperty) {
|
||||||
);
|
// 情况一:如果属性已存在,则直接使用并结束
|
||||||
if (existProperty) {
|
attributeList.value.push({
|
||||||
attributeList.value.push({
|
id: existProperty.id,
|
||||||
id: existProperty.id,
|
name,
|
||||||
name,
|
values: [],
|
||||||
values: [],
|
});
|
||||||
});
|
} else {
|
||||||
// TODO @puhui999:这里要不 if else;这样 await modalApi.close(); emit('success'); 可以复用?另外,感觉甚至可以情况二:add 后,成为 existProperty,可以进一步简化?
|
// 情况二:如果是不存在的属性,则需要执行新增
|
||||||
await modalApi.close();
|
const propertyId = await createProperty({ name });
|
||||||
emit('success');
|
attributeList.value.push({
|
||||||
return;
|
id: propertyId,
|
||||||
}
|
name,
|
||||||
|
values: [],
|
||||||
// 情况二:如果是不存在的属性,则需要执行新增
|
});
|
||||||
try {
|
}
|
||||||
const data = { name } as MallPropertyApi.Property;
|
|
||||||
const propertyId = await createProperty(data);
|
|
||||||
// 添加到属性列表
|
|
||||||
attributeList.value.push({
|
|
||||||
id: propertyId,
|
|
||||||
name,
|
|
||||||
values: [],
|
|
||||||
});
|
|
||||||
message.success($t('ui.actionMessage.operationSuccess'));
|
|
||||||
await modalApi.close();
|
|
||||||
emit('success');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('添加属性失败:', error);
|
|
||||||
}
|
}
|
||||||
|
message.success($t('ui.actionMessage.operationSuccess'));
|
||||||
|
modalApi.unlock();
|
||||||
|
await modalApi.close();
|
||||||
|
emit('success');
|
||||||
},
|
},
|
||||||
|
|
||||||
async onOpenChange(isOpen: boolean) {
|
async onOpenChange(isOpen: boolean) {
|
||||||
if (!isOpen) {
|
if (!isOpen) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ export function useGridColumns(): VxeTableGridOptions['columns'] {
|
|||||||
field: 'status',
|
field: 'status',
|
||||||
minWidth: 150,
|
minWidth: 150,
|
||||||
cellRender: {
|
cellRender: {
|
||||||
name: 'CellDictTag',
|
name: 'CellDict',
|
||||||
props: {
|
props: {
|
||||||
dictType: DICT_TYPE.COMMON_STATUS,
|
dictType: DICT_TYPE.COMMON_STATUS,
|
||||||
},
|
},
|
||||||
@@ -154,7 +154,7 @@ export function useGridColumns(): VxeTableGridOptions['columns'] {
|
|||||||
field: 'position',
|
field: 'position',
|
||||||
minWidth: 150,
|
minWidth: 150,
|
||||||
cellRender: {
|
cellRender: {
|
||||||
name: 'CellDictTag',
|
name: 'CellDict',
|
||||||
props: {
|
props: {
|
||||||
dictType: DICT_TYPE.PROMOTION_BANNER_POSITION,
|
dictType: DICT_TYPE.PROMOTION_BANNER_POSITION,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -197,15 +197,9 @@ function selectSku(skus: MallSpuApi.Sku[]) {
|
|||||||
selectedSkuIds.value = [];
|
selectedSkuIds.value = [];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
props.radio
|
||||||
// TODO @puhui999:有 idea 告警
|
? (selectedSkuIds.value = [skus[0]?.id!])
|
||||||
if (props.radio) {
|
: (selectedSkuIds.value = skus.map((sku) => sku.id!));
|
||||||
// 单选模式
|
|
||||||
selectedSkuIds.value = [skus[0]?.id!];
|
|
||||||
} else {
|
|
||||||
// 多选模式
|
|
||||||
selectedSkuIds.value = skus.map((sku) => sku.id!);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 展开行,加载 SKU 列表 */
|
/** 展开行,加载 SKU 列表 */
|
||||||
@@ -280,7 +274,10 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
await gridApi.query();
|
await gridApi.query();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
defineExpose({
|
||||||
|
open: modalApi.open,
|
||||||
|
close: modalApi.close,
|
||||||
|
});
|
||||||
/** 初始化分类数据 */
|
/** 初始化分类数据 */
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
categoryList.value = await getCategoryList({});
|
categoryList.value = await getCategoryList({});
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||||||
label: $t('ui.actionTitle.create', ['积分活动']),
|
label: $t('ui.actionTitle.create', ['积分活动']),
|
||||||
type: 'primary',
|
type: 'primary',
|
||||||
icon: ACTION_ICON.ADD,
|
icon: ACTION_ICON.ADD,
|
||||||
|
auth: ['promotion:point-activity:create'],
|
||||||
onClick: handleCreate,
|
onClick: handleCreate,
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
@@ -122,6 +123,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||||||
label: $t('common.edit'),
|
label: $t('common.edit'),
|
||||||
type: 'link',
|
type: 'link',
|
||||||
icon: ACTION_ICON.EDIT,
|
icon: ACTION_ICON.EDIT,
|
||||||
|
auth: ['promotion:point-activity:update'],
|
||||||
onClick: handleEdit.bind(null, row),
|
onClick: handleEdit.bind(null, row),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -130,6 +132,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||||||
danger: true,
|
danger: true,
|
||||||
icon: ACTION_ICON.CLOSE,
|
icon: ACTION_ICON.CLOSE,
|
||||||
ifShow: row.status === 0,
|
ifShow: row.status === 0,
|
||||||
|
auth: ['promotion:point-activity:close'],
|
||||||
popConfirm: {
|
popConfirm: {
|
||||||
title: '确认关闭该积分商城活动吗?',
|
title: '确认关闭该积分商城活动吗?',
|
||||||
confirm: handleClose.bind(null, row),
|
confirm: handleClose.bind(null, row),
|
||||||
@@ -141,6 +144,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||||||
danger: true,
|
danger: true,
|
||||||
icon: ACTION_ICON.DELETE,
|
icon: ACTION_ICON.DELETE,
|
||||||
ifShow: row.status !== 0,
|
ifShow: row.status !== 0,
|
||||||
|
auth: ['promotion:point-activity:delete'],
|
||||||
popConfirm: {
|
popConfirm: {
|
||||||
title: $t('ui.actionMessage.deleteConfirm', [row.spuName]),
|
title: $t('ui.actionMessage.deleteConfirm', [row.spuName]),
|
||||||
confirm: handleDelete.bind(null, row),
|
confirm: handleDelete.bind(null, row),
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ const gridColumns = computed<VxeGridProps['columns']>(() => {
|
|||||||
field: 'marketPrice',
|
field: 'marketPrice',
|
||||||
title: '原价',
|
title: '原价',
|
||||||
minWidth: 100,
|
minWidth: 100,
|
||||||
formatter: 'formatAmount',
|
formatter: 'formatAmount2',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'status',
|
field: 'status',
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ export function useGridColumns(): VxeTableGridOptions['columns'] {
|
|||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
cellRender: {
|
cellRender: {
|
||||||
name: 'CellDictTag',
|
name: 'CellDict',
|
||||||
props: { type: DICT_TYPE.PROMOTION_PRODUCT_SCOPE },
|
props: { type: DICT_TYPE.PROMOTION_PRODUCT_SCOPE },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -88,7 +88,7 @@ export function useGridColumns(): VxeTableGridOptions['columns'] {
|
|||||||
minWidth: 100,
|
minWidth: 100,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
cellRender: {
|
cellRender: {
|
||||||
name: 'CellDictTag',
|
name: 'CellDict',
|
||||||
props: { type: DICT_TYPE.COMMON_STATUS },
|
props: { type: DICT_TYPE.COMMON_STATUS },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -53,7 +53,9 @@ async function handleClose(row: MallRewardActivityApi.RewardActivity) {
|
|||||||
|
|
||||||
async function handleDelete(row: MallRewardActivityApi.RewardActivity) {
|
async function handleDelete(row: MallRewardActivityApi.RewardActivity) {
|
||||||
await deleteRewardActivity(row.id!);
|
await deleteRewardActivity(row.id!);
|
||||||
message.success($t('common.delSuccess'));
|
message.success({
|
||||||
|
content: $t('ui.actionMessage.deleteSuccess', [row.id]),
|
||||||
|
});
|
||||||
handleRefresh();
|
handleRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ export function useGridColumns(): VxeGridPropTypes.Columns {
|
|||||||
width: 100,
|
width: 100,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
cellRender: {
|
cellRender: {
|
||||||
name: 'CellDictTag',
|
name: 'CellDict',
|
||||||
props: {
|
props: {
|
||||||
dictType: DICT_TYPE.TRADE_AFTER_SALE_STATUS,
|
dictType: DICT_TYPE.TRADE_AFTER_SALE_STATUS,
|
||||||
},
|
},
|
||||||
@@ -158,7 +158,7 @@ export function useGridColumns(): VxeGridPropTypes.Columns {
|
|||||||
width: 100,
|
width: 100,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
cellRender: {
|
cellRender: {
|
||||||
name: 'CellDictTag',
|
name: 'CellDict',
|
||||||
props: {
|
props: {
|
||||||
dictType: DICT_TYPE.TRADE_AFTER_SALE_WAY,
|
dictType: DICT_TYPE.TRADE_AFTER_SALE_WAY,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
{
|
{
|
||||||
fieldName: 'brokerageEnabled',
|
fieldName: 'brokerageEnabled',
|
||||||
label: '推广资格',
|
label: '推广资格',
|
||||||
component: 'Select',
|
component: 'RadioGroup',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
placeholder: '请选择推广资格',
|
placeholder: '请选择推广资格',
|
||||||
allowClear: true,
|
allowClear: true,
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ export function useGridColumns(): VxeTableGridOptions['columns'] {
|
|||||||
field: 'status',
|
field: 'status',
|
||||||
minWidth: 150,
|
minWidth: 150,
|
||||||
cellRender: {
|
cellRender: {
|
||||||
name: 'CellDictTag',
|
name: 'CellDict',
|
||||||
props: {
|
props: {
|
||||||
dictType: DICT_TYPE.COMMON_STATUS,
|
dictType: DICT_TYPE.COMMON_STATUS,
|
||||||
},
|
},
|
||||||
@@ -150,7 +150,7 @@ export function useGridColumns(): VxeTableGridOptions['columns'] {
|
|||||||
field: 'position',
|
field: 'position',
|
||||||
minWidth: 150,
|
minWidth: 150,
|
||||||
cellRender: {
|
cellRender: {
|
||||||
name: 'CellDictTag',
|
name: 'CellDict',
|
||||||
props: {
|
props: {
|
||||||
dictType: DICT_TYPE.PROMOTION_BANNER_POSITION,
|
dictType: DICT_TYPE.PROMOTION_BANNER_POSITION,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ export function useGridColumns(): VxeGridPropTypes.Columns {
|
|||||||
width: 100,
|
width: 100,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
cellRender: {
|
cellRender: {
|
||||||
name: 'CellDictTag',
|
name: 'CellDict',
|
||||||
props: {
|
props: {
|
||||||
dictType: DICT_TYPE.TRADE_AFTER_SALE_STATUS,
|
dictType: DICT_TYPE.TRADE_AFTER_SALE_STATUS,
|
||||||
},
|
},
|
||||||
@@ -158,7 +158,7 @@ export function useGridColumns(): VxeGridPropTypes.Columns {
|
|||||||
width: 100,
|
width: 100,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
cellRender: {
|
cellRender: {
|
||||||
name: 'CellDictTag',
|
name: 'CellDict',
|
||||||
props: {
|
props: {
|
||||||
dictType: DICT_TYPE.TRADE_AFTER_SALE_WAY,
|
dictType: DICT_TYPE.TRADE_AFTER_SALE_WAY,
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user