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

View File

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

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

View File

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

View File

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