/** * 页面装修业务逻辑模块 * 参考CRMEB项目,提供完整的装修管理功能 */ /** * 装修页面数据接口 */ export interface DesignItem { id: string | number name: string type: 'homepage' | 'category' | 'product' | 'custom' status: 0 | 1 // 0: 草稿, 1: 已发布 categoryId?: string | number categoryName?: string path?: string preview_url?: string content: DesignComponent[] version?: string created_at?: string updated_at?: string } /** * 装修组件接口 */ export interface DesignComponent { id: string type: 'image' | 'text' | 'product' | 'carousel' | 'divider' | 'spacer' | 'button' | 'form' name: string icon: string description?: string componentName?: string config?: Record children?: DesignComponent[] } /** * 装修模板接口 */ export interface DesignTemplate { id: string | number name: string description: string type: string preview: string content: DesignComponent[] created_at?: string } /** * 获取装修页面列表 * @param params 查询参数 * @returns 装修页面列表 */ export function getDesignList(params?: Record): Promise { return new Promise((resolve, reject) => { // TODO: 实际应调用后端API const designList: DesignItem[] = [ { id: 1, name: '首页装修', type: 'homepage', status: 1, content: [], updated_at: '2026-01-30 14:30:00' }, { id: 2, name: '年货节活动页', type: 'custom', status: 1, content: [], updated_at: '2026-01-28 10:15:00' } ] setTimeout(() => resolve(designList), 300) }) } /** * 获取首页装修详情 * @returns 首页装修数据 */ export function getHomePageDesign(): Promise { return new Promise((resolve, reject) => { const homepage: DesignItem = { id: 'homepage', name: '首页装修', type: 'homepage', status: 1, content: [ { id: 'carousel-1', type: 'carousel', name: '轮播图', icon: 'C', description: '首页顶部轮播图展示', config: { autoplay: true, duration: 5000, height: 300 } }, { id: 'product-1', type: 'product', name: '商品展示', icon: 'P', description: '热销商品列表', config: { count: 8, columns: 2, layout: 'grid' } } ], version: '1.0.0', updated_at: '2026-01-30 14:30:00' } setTimeout(() => resolve(homepage), 300) }) } /** * 获取商品页装修详情 * @returns 商品页装修数据 */ export function getProductPageDesign(): Promise { return new Promise((resolve, reject) => { const productPage: DesignItem = { id: 'product', name: '商品页装修', type: 'product', status: 1, content: [ { id: 'image-1', type: 'image', name: '商品图', icon: 'I', description: '商品主图展示' }, { id: 'product-info', type: 'text', name: '商品信息', icon: 'T', description: '商品名称和价格' } ], version: '1.0.0', updated_at: '2026-01-30 14:30:00' } setTimeout(() => resolve(productPage), 300) }) } /** * 获取分类装修列表 * @returns 分类装修列表 */ export function getCategoryDesigns(): Promise { return new Promise((resolve, reject) => { const categories: DesignItem[] = [ { id: 1, name: '默认分类装修', type: 'category', status: 1, categoryId: 0, categoryName: '全部分类', content: [], updated_at: '2026-01-30 14:30:00' }, { id: 2, name: '热销商品分类', type: 'category', status: 0, categoryId: 1, categoryName: '推荐分类', content: [], updated_at: '2026-01-29 10:15:00' } ] setTimeout(() => resolve(categories), 300) }) } /** * 获取自定义页面列表 * @returns 自定义页面列表 */ export function getCustomPages(): Promise { return new Promise((resolve, reject) => { const customPages: DesignItem[] = [ { id: 1, name: '新年促销页', type: 'custom', status: 1, path: '/pages/promotion/newyear', content: [], updated_at: '2026-01-28 09:00:00' } ] setTimeout(() => resolve(customPages), 300) }) } /** * 获取页面模板库 * @returns 模板列表 */ export function getTemplateLibrary(): Promise { return new Promise((resolve, reject) => { const templates: DesignTemplate[] = [ { id: 1, name: '电商风格A', description: '简洁现代的电商布局', type: 'homepage', preview: '@/static/images/template-a.png', content: [] }, { id: 2, name: '电商风格B', description: '豪华展示的电商布局', type: 'homepage', preview: '@/static/images/template-b.png', content: [] }, { id: 3, name: '精品风格', description: '精品商品展示布局', type: 'homepage', preview: '@/static/images/template-c.png', content: [] }, { id: 4, name: '商城风格', description: '完整商城功能布局', type: 'homepage', preview: '@/static/images/template-d.png', content: [] } ] setTimeout(() => resolve(templates), 300) }) } /** * 获取可用组件库 * @returns 组件列表 */ export function getAvailableComponents(): Promise { return new Promise((resolve, reject) => { const components: DesignComponent[] = [ { id: 'image', type: 'image', name: '图片组件', icon: 'I', description: '展示图片和图片轮播', componentName: 'ImageComponent', config: { defaultWidth: '100%', defaultHeight: 'auto' } }, { id: 'text', type: 'text', name: '文本组件', icon: 'T', description: '展示文本内容和段落', componentName: 'TextComponent' }, { id: 'product', type: 'product', name: '商品组件', icon: 'P', description: '展示商品列表和推荐', componentName: 'ProductComponent', config: { defaultCount: 6, defaultColumns: 2 } }, { id: 'carousel', type: 'carousel', name: '轮播组件', icon: 'C', description: '图片和内容轮播', componentName: 'CarouselComponent', config: { autoplay: true, duration: 5000 } }, { id: 'divider', type: 'divider', name: '分割线', icon: 'D', description: '分割不同内容区域', componentName: 'DividerComponent' }, { id: 'spacer', type: 'spacer', name: '间距组件', icon: 'S', description: '调整元素间距', componentName: 'SpacerComponent', config: { defaultHeight: 16 } }, { id: 'button', type: 'button', name: '按钮组件', icon: 'B', description: '创建点击按钮', componentName: 'ButtonComponent' }, { id: 'form', type: 'form', name: '表单组件', icon: 'F', description: '收集用户输入数据', componentName: 'FormComponent' } ] setTimeout(() => resolve(components), 300) }) } /** * 保存装修页面 * @param design 装修数据 * @returns 保存结果 */ export function saveDesign(design: DesignItem): Promise<{ id: string | number; message: string }> { return new Promise((resolve, reject) => { if (!design.name || design.name.trim() === '') { reject(new Error('装修名称不能为空')) return } if (!design.type) { reject(new Error('装修类型不能为空')) return } // TODO: 实际应调用后端API保存 const result = { id: design.id || Math.random().toString(36).substr(2, 9), message: '保存成功' } setTimeout(() => resolve(result), 500) }) } /** * 发布装修页面 * @param designId 装修页面ID * @returns 发布结果 */ export function publishDesign(designId: string | number): Promise<{ message: string }> { return new Promise((resolve, reject) => { if (!designId) { reject(new Error('装修ID不能为空')) return } // TODO: 实际应调用后端API发布 setTimeout(() => { resolve({ message: '发布成功' }) }, 500) }) } /** * 删除装修页面 * @param designId 装修页面ID * @returns 删除结果 */ export function deleteDesign(designId: string | number): Promise<{ message: string }> { return new Promise((resolve, reject) => { if (!designId) { reject(new Error('装修ID不能为空')) return } // TODO: 实际应调用后端API删除 setTimeout(() => { resolve({ message: '删除成功' }) }, 500) }) } /** * 获取装修预览URL * @param designId 装修ID * @returns 预览URL */ export function getDesignPreviewUrl(designId: string | number): string { return `/pages/mall/design/preview/${designId}` } /** * 获取装修编辑URL * @param designId 装修ID * @returns 编辑URL */ export function getDesignEditorUrl(designId: string | number): string { return `/pages/mall/admin/design/editor?id=${designId}` } /** * 格式化日期时间 * @param dateStr 日期字符串 * @returns 格式化后的日期 */ export function formatDateTime(dateStr?: string): string { if (!dateStr) return '--' try { const date = new Date(dateStr) const year = date.getFullYear() const month = String(date.getMonth() + 1).padStart(2, '0') const day = String(date.getDate()).padStart(2, '0') const hours = String(date.getHours()).padStart(2, '0') const minutes = String(date.getMinutes()).padStart(2, '0') return `${year}-${month}-${day} ${hours}:${minutes}` } catch { return dateStr } } /** * 验证组件配置 * @param component 组件配置 * @returns 验证结果 */ export function validateComponent(component: DesignComponent): { valid: boolean; errors: string[] } { const errors: string[] = [] if (!component.id) { errors.push('组件ID不能为空') } if (!component.type) { errors.push('组件类型不能为空') } if (!component.name) { errors.push('组件名称不能为空') } return { valid: errors.length === 0, errors } } /** * 生成组件ID * @param type 组件类型 * @returns 生成的组件ID */ export function generateComponentId(type: string): string { const timestamp = Date.now().toString(36) const random = Math.random().toString(36).substr(2, 5) return `${type}-${timestamp}-${random}` } /** * 获取装修约束条件 * @returns 约束条件对象 */ export function getDesignConstraints(): DesignConstraints { return { maxComponents: 50, allowedComponentTypes: ['image', 'text', 'product', 'carousel', 'divider', 'spacer', 'button', 'form'], maxImageSize: 5242880, // 5MB supportedImageFormats: ['jpg', 'jpeg', 'png', 'gif', 'webp'] } } /** * 深度克隆装修数据 * @param design 装修数据 * @returns 克隆后的数据 */ export function cloneDesign(design: DesignItem): DesignItem { return JSON.parse(JSON.stringify(design)) } /** * 验证装修数据完整性 * @param design 装修数据 * @returns 验证结果 */ export function validateDesign(design: DesignItem): { valid: boolean; message: string } { if (!design.name || design.name.trim() === '') { return { valid: false, message: '装修名称不能为空' } } if (!design.type) { return { valid: false, message: '装修类型不能为空' } } if (!Array.isArray(design.content)) { return { valid: false, message: '装修内容格式错误' } } if (design.content.length > getDesignConstraints().maxComponents) { return { valid: false, message: `组件数量超过限制(最多${getDesignConstraints().maxComponents}个)` } } return { valid: true, message: '验证通过' } } /** * 导出装修为JSON * @param design 装修数据 * @returns JSON字符串 */ export function exportDesignJSON(design: DesignItem): string { return JSON.stringify(design, null, 2) } /** * 从JSON导入装修 * @param jsonStr JSON字符串 * @returns 装修数据 */ export function importDesignJSON(jsonStr: string): DesignItem { try { return JSON.parse(jsonStr) as DesignItem } catch (error) { throw new Error('JSON格式错误,无法导入') } }