feat:【ele】【mall】diy/page 代码优化

This commit is contained in:
YunaiV
2025-10-25 21:02:09 +08:00
parent 900671babd
commit d8f4979a47
7 changed files with 86 additions and 102 deletions

View File

@@ -98,7 +98,7 @@ const routes: RouteRecordRaw[] = [
activePath: '/mall/promotion/diy-template/diy-template', activePath: '/mall/promotion/diy-template/diy-template',
}, },
component: () => component: () =>
import('#/views/mall/promotion/diy/template/modules/decorate.vue'), import('#/views/mall/promotion/diy/template/decorate/index.vue'),
}, },
{ {
path: 'page/decorate/:id', path: 'page/decorate/:id',
@@ -110,7 +110,7 @@ const routes: RouteRecordRaw[] = [
activePath: '/mall/promotion/diy-template/diy-page', activePath: '/mall/promotion/diy-template/diy-page',
}, },
component: () => component: () =>
import('#/views/mall/promotion/diy/page/modules/decorate.vue'), import('#/views/mall/promotion/diy/page/decorate/index.vue'),
}, },
], ],
}, },

View File

@@ -267,7 +267,7 @@ const handleDeleteComponent = (index: number) => {
}; };
// 注入无感刷新页面函数 // 注入无感刷新页面函数
const reload = inject<() => void>('reload'); const reload = inject<() => void>('reload'); // TODO @芋艿:是 vue3 + element-plus 独有的,可以清理掉。
// 重置 // 重置
const handleReset = () => { const handleReset = () => {
if (reload) reload(); if (reload) reload();

View File

@@ -3,6 +3,8 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { DICT_TYPE } from '@vben/constants'; import { DICT_TYPE } from '@vben/constants';
import { getRangePickerDefaultProps } from '#/utils';
/** 表单配置 */ /** 表单配置 */
export function useFormSchema(): VbenFormSchema[] { export function useFormSchema(): VbenFormSchema[] {
return [ return [
@@ -61,9 +63,8 @@ export function useGridFormSchema(): VbenFormSchema[] {
label: '创建时间', label: '创建时间',
component: 'RangePicker', component: 'RangePicker',
componentProps: { componentProps: {
placeholder: ['开始时间', '结束时间'], ...getRangePickerDefaultProps(),
clearable: true, allowClear: true,
valueFormat: 'YYYY-MM-DD HH:mm:ss',
}, },
}, },
]; ];

View File

@@ -3,67 +3,75 @@ import type { MallDiyPageApi } from '#/api/mall/promotion/diy/page';
import type { MallDiyTemplateApi } from '#/api/mall/promotion/diy/template'; import type { MallDiyTemplateApi } from '#/api/mall/promotion/diy/template';
import type { DiyComponentLibrary } from '#/views/mall/promotion/components'; // DIY DiyEditor import type { DiyComponentLibrary } from '#/views/mall/promotion/components'; // DIY DiyEditor
import { onMounted, reactive, ref, unref } from 'vue'; import { onMounted, reactive, ref } from 'vue';
import { useRouter } from 'vue-router'; import { useRoute } from 'vue-router';
import { useTabs } from '@vben/hooks';
import { IconifyIcon } from '@vben/icons'; import { IconifyIcon } from '@vben/icons';
import { useAccessStore } from '@vben/stores'; import { useAccessStore } from '@vben/stores';
import { isEmpty } from '@vben/utils'; import { isEmpty } from '@vben/utils';
import { ElMessage } from 'element-plus'; import {
ElLoading,
ElMessage,
ElRadioButton,
ElRadioGroup,
ElTooltip,
} from 'element-plus';
import * as DiyPageApi from '#/api/mall/promotion/diy/page'; import * as DiyPageApi from '#/api/mall/promotion/diy/page';
// TODO @ decorate index.vue
import * as DiyTemplateApi from '#/api/mall/promotion/diy/template'; import * as DiyTemplateApi from '#/api/mall/promotion/diy/template';
import { DiyEditor, PAGE_LIBS } from '#/views/mall/promotion/components'; import { DiyEditor, PAGE_LIBS } from '#/views/mall/promotion/components';
/** 装修模板表单 */ /** 装修模板表单 */
defineOptions({ name: 'DiyTemplateDecorate' }); defineOptions({ name: 'DiyTemplateDecorate' });
// const route = useRoute();
const { refreshTab } = useTabs();
const DIY_PAGE_INDEX_KEY = 'diy_page_index'; // reset selectedTemplateItem
const selectedTemplateItem = ref(0); const selectedTemplateItem = ref(0);
const templateItems = reactive([ const templateItems = reactive([
{ name: '基础设置', icon: 'ep:iphone' }, { name: '基础设置', icon: 'ep:iphone' },
{ name: '首页', icon: 'ep:home-filled' }, { name: '首页', icon: 'ep:home-filled' },
{ name: '我的', icon: 'ep:user-filled' }, { name: '我的', icon: 'ep:user-filled' },
]); ]); //
const formLoading = ref(false); // 12
const formData = ref<MallDiyTemplateApi.DiyTemplateProperty>(); const formData = ref<MallDiyTemplateApi.DiyTemplateProperty>();
const formRef = ref(); // Ref
//
const currentFormData = ref< const currentFormData = ref<
MallDiyPageApi.DiyPage | MallDiyTemplateApi.DiyTemplateProperty MallDiyPageApi.DiyPage | MallDiyTemplateApi.DiyTemplateProperty
>({ >({
property: '', property: '',
} as MallDiyPageApi.DiyPage); } as MallDiyPageApi.DiyPage); //
// templateItem
const currentFormDataMap = ref< const currentFormDataMap = ref<
Map<string, MallDiyPageApi.DiyPage | MallDiyTemplateApi.DiyTemplateProperty> Map<string, MallDiyPageApi.DiyPage | MallDiyTemplateApi.DiyTemplateProperty>
>(new Map()); >(new Map()); // templateItem
// H5
const previewUrl = ref('');
// const previewUrl = ref(''); // H5
const getPageDetail = async (id: any) => {
formLoading.value = true; const templateLibs = [] as DiyComponentLibrary[]; //
const libs = ref<DiyComponentLibrary[]>(templateLibs); //
/** 获取详情 */
async function getPageDetail(id: any) {
const loadingInstance = ElLoading.service({
text: '加载中...',
});
try { try {
formData.value = await DiyTemplateApi.getDiyTemplateProperty(id); formData.value = await DiyTemplateApi.getDiyTemplateProperty(id);
// //
const domain = import.meta.env.VITE_MALL_H5_DOMAIN; const domain = import.meta.env.VITE_MALL_H5_DOMAIN;
const accessStore = useAccessStore(); const accessStore = useAccessStore();
previewUrl.value = `${domain}?templateId=${formData.value.id}&${accessStore.tenantId}`; previewUrl.value = `${domain}?templateId=${formData.value.id}&${accessStore.tenantId}`;
} finally { } finally {
formLoading.value = false; loadingInstance.close();
} }
}; }
// /** 模板选项切换 */
const templateLibs = [] as DiyComponentLibrary[]; function handleTemplateItemChange(val: any) {
//
const libs = ref<DiyComponentLibrary[]>(templateLibs);
//
const handleTemplateItemChange = (val: number) => {
// //
currentFormDataMap.value.set( currentFormDataMap.value.set(
templateItems[selectedTemplateItem.value]?.name || '', templateItems[selectedTemplateItem.value]?.name || '',
@@ -74,7 +82,8 @@ const handleTemplateItemChange = (val: number) => {
// //
selectedTemplateItem.value = val; selectedTemplateItem.value = val;
//
//
if (val === 0) { if (val === 0) {
libs.value = templateLibs; libs.value = templateLibs;
currentFormData.value = (isEmpty(data) ? formData.value : data) as currentFormData.value = (isEmpty(data) ? formData.value : data) as
@@ -83,7 +92,7 @@ const handleTemplateItemChange = (val: number) => {
return; return;
} }
// //
libs.value = PAGE_LIBS; libs.value = PAGE_LIBS;
currentFormData.value = ( currentFormData.value = (
isEmpty(data) isEmpty(data)
@@ -93,14 +102,13 @@ const handleTemplateItemChange = (val: number) => {
) )
: data : data
) as MallDiyPageApi.DiyPage | MallDiyTemplateApi.DiyTemplateProperty; ) as MallDiyPageApi.DiyPage | MallDiyTemplateApi.DiyTemplateProperty;
}; }
// /** 提交表单 */
const submitForm = async () => { async function submitForm() {
// const loadingInstance = ElLoading.service({
if (!formRef.value) return; text: '保存中...',
// });
formLoading.value = true;
try { try {
// templateItems templateItem // templateItems templateItem
for (const [i, templateItem] of templateItems.entries()) { for (const [i, templateItem] of templateItems.entries()) {
@@ -109,14 +117,14 @@ const submitForm = async () => {
if (i === 0) { if (i === 0) {
// //
await DiyTemplateApi.updateDiyTemplateProperty( await DiyTemplateApi.updateDiyTemplateProperty(
isEmpty(data) ? unref(formData)! : data, isEmpty(data) ? formData.value! : data,
); );
continue; continue;
} }
// //
// //
if (currentFormData.value?.name.includes(templateItem.name)) { if (currentFormData.value?.name.includes(templateItem.name)) {
await DiyPageApi.updateDiyPageProperty(unref(currentFormData)!); await DiyPageApi.updateDiyPageProperty(currentFormData.value!);
continue; continue;
} }
// //
@@ -126,36 +134,18 @@ const submitForm = async () => {
} }
ElMessage.success('保存成功'); ElMessage.success('保存成功');
} finally { } finally {
formLoading.value = false; loadingInstance.close();
} }
}; }
// /** 刷新当前 Tab */
const resetForm = () => { function handleEditorReset() {
formData.value = {
id: undefined,
name: '',
used: false,
usedTime: undefined,
remark: '',
previewPicUrls: [],
property: '',
pages: [],
} as MallDiyTemplateApi.DiyTemplateProperty;
formRef.value?.resetFields();
};
//
const handleEditorReset = () => storePageIndex();
// #region
//
const DIY_PAGE_INDEX_KEY = 'diy_page_index';
// 1.
const storePageIndex = () =>
sessionStorage.setItem(DIY_PAGE_INDEX_KEY, `${selectedTemplateItem.value}`); sessionStorage.setItem(DIY_PAGE_INDEX_KEY, `${selectedTemplateItem.value}`);
// 2. refreshTab();
const recoverPageIndex = () => { }
/** 恢复当前 Tab 之前的 indexselectedTemplateItem */
function recoverPageIndex() {
// //
const pageIndex = Number(sessionStorage.getItem(DIY_PAGE_INDEX_KEY)) || 0; const pageIndex = Number(sessionStorage.getItem(DIY_PAGE_INDEX_KEY)) || 0;
// //
@@ -173,26 +163,24 @@ const recoverPageIndex = () => {
if (pageIndex !== selectedTemplateItem.value) { if (pageIndex !== selectedTemplateItem.value) {
handleTemplateItemChange(pageIndex); handleTemplateItemChange(pageIndex);
} }
}; }
// #endregion
/** 初始化 */ /** 初始化 */
const { currentRoute } = useRouter();
onMounted(async () => { onMounted(async () => {
resetForm(); if (!route.params.id) {
if (!currentRoute.value.params.id) {
ElMessage.warning('参数错误,页面编号不能为空!'); ElMessage.warning('参数错误,页面编号不能为空!');
return; return;
} }
// //
await getPageDetail(currentRoute.value.params.id); formData.value = {} as MallDiyTemplateApi.DiyTemplateProperty;
await getPageDetail(route.params.id);
// //
recoverPageIndex(); recoverPageIndex();
}); });
</script> </script>
<template> <template>
<DiyEditor <DiyEditor
v-if="formData && !formLoading" v-if="formData?.id"
v-model="currentFormData!.property" v-model="currentFormData!.property"
:libs="libs" :libs="libs"
:preview-url="previewUrl" :preview-url="previewUrl"
@@ -204,21 +192,21 @@ onMounted(async () => {
@save="submitForm" @save="submitForm"
> >
<template #toolBarLeft> <template #toolBarLeft>
<el-radio-group <ElRadioGroup
:model-value="selectedTemplateItem" :model-value="selectedTemplateItem"
class="h-full!" class="h-full!"
@change="handleTemplateItemChange" @change="handleTemplateItemChange"
> >
<el-tooltip <ElTooltip
v-for="(item, index) in templateItems" v-for="(item, index) in templateItems"
:key="index" :key="index"
:content="item.name" :content="item.name"
> >
<el-radio-button :value="index"> <ElRadioButton :value="index">
<IconifyIcon :icon="item.icon" :size="24" /> <IconifyIcon :icon="item.icon" :size="24" />
</el-radio-button> </ElRadioButton>
</el-tooltip> </ElTooltip>
</el-radio-group> </ElRadioGroup>
</template> </template>
</DiyEditor> </DiyEditor>
</template> </template>

View File

@@ -33,32 +33,38 @@ function handleRefresh() {
gridApi.query(); gridApi.query();
} }
/** 创建DIY模板 */ /** 创建 DIY 模板 */
function handleCreate() { function handleCreate() {
formModalApi.setData(null).open(); formModalApi.setData(null).open();
} }
/** 编辑DIY模板 */ /** 编辑 DIY 模板 */
function handleEdit(row: MallDiyTemplateApi.DiyTemplate) { function handleEdit(row: MallDiyTemplateApi.DiyTemplate) {
formModalApi.setData(row).open(); formModalApi.setData(row).open();
} }
/** 装修模板 */ /** 装修模板 */
function handleDecorate(row: MallDiyTemplateApi.DiyTemplate) { function handleDecorate(row: MallDiyTemplateApi.DiyTemplate) {
// 跳转到装修页面
router.push({ name: 'DiyTemplateDecorate', params: { id: row.id } }); router.push({ name: 'DiyTemplateDecorate', params: { id: row.id } });
} }
/** 使用模板 */ /** 使用模板 */
async function handleUse(row: MallDiyTemplateApi.DiyTemplate) { async function handleUse(row: MallDiyTemplateApi.DiyTemplate) {
await confirm(`是否使用模板"${row.name}"?`); await confirm(`是否使用模板"${row.name}"?`);
// 发起删除
await useDiyTemplate(row.id as number); const loadingInstance = ElLoading.service({
ElMessage.success('使用成功'); text: `正在使用模板"${row.name}"...`,
handleRefresh(); });
try {
await useDiyTemplate(row.id as number);
ElMessage.success('使用成功');
handleRefresh();
} finally {
loadingInstance.close();
}
} }
/** 删除DIY模板 */ /** 删除 DIY 模板 */
async function handleDelete(row: MallDiyTemplateApi.DiyTemplate) { async function handleDelete(row: MallDiyTemplateApi.DiyTemplate) {
const loadingInstance = ElLoading.service({ const loadingInstance = ElLoading.service({
text: $t('ui.actionMessage.deleting', [row.name]), text: $t('ui.actionMessage.deleting', [row.name]),

View File

@@ -16,9 +16,7 @@ import { $t } from '#/locales';
import { useFormSchema } from '../data'; import { useFormSchema } from '../data';
/** 提交表单 */
const emit = defineEmits(['success']); const emit = defineEmits(['success']);
const formData = ref<MallDiyTemplateApi.DiyTemplate>(); const formData = ref<MallDiyTemplateApi.DiyTemplate>();
const getTitle = computed(() => { const getTitle = computed(() => {
return formData.value?.id return formData.value?.id
@@ -47,15 +45,6 @@ const [Modal, modalApi] = useVbenModal({
modalApi.lock(); modalApi.lock();
// 提交表单 // 提交表单
const data = (await formApi.getValues()) as MallDiyTemplateApi.DiyTemplate; const data = (await formApi.getValues()) as MallDiyTemplateApi.DiyTemplate;
// 确保必要的默认值
if (!data.previewPicUrls) {
data.previewPicUrls = [];
}
if (data.used === undefined) {
data.used = false;
}
try { try {
await (formData.value?.id await (formData.value?.id
? updateDiyTemplate(data) ? updateDiyTemplate(data)
@@ -91,7 +80,7 @@ const [Modal, modalApi] = useVbenModal({
</script> </script>
<template> <template>
<Modal class="w-2/5" :title="getTitle"> <Modal :title="getTitle" class="w-2/5">
<Form /> <Form />
</Modal> </Modal>
</template> </template>