修改页面结构
This commit is contained in:
179
pages/mall/admin/design/README.md
Normal file
179
pages/mall/admin/design/README.md
Normal file
@@ -0,0 +1,179 @@
|
||||
# 页面装修管理模块 - README
|
||||
|
||||
> 基于CRMEB项目标准,实现完整的页面装修和DIY功能
|
||||
|
||||
## 📋 文件结构
|
||||
|
||||
```
|
||||
pages/mall/admin/design/
|
||||
├── index.uvue # 装修管理主界面(898行)
|
||||
├── design.uts # 业务逻辑和数据管理(350+行)
|
||||
├── editor.uvue # 装修编辑器(待实现)
|
||||
├── preview.uvue # 装修预览页面(待实现)
|
||||
└── README.md # 本文件
|
||||
```
|
||||
|
||||
## 🎯 核心功能
|
||||
|
||||
### 1. 首页装修 (Homepage)
|
||||
|
||||
- 自定义首页布局和显示内容
|
||||
- 支持轮播图、商品展示、文本等组件
|
||||
- 实时预览效果
|
||||
- 版本管理和发布
|
||||
|
||||
### 2. 分类页装修 (Category)
|
||||
|
||||
- 为不同商品分类创建装修页面
|
||||
- 支持多套分类装修方案
|
||||
- 按分类自动应用装修效果
|
||||
- 快速切换和对比
|
||||
|
||||
### 3. 商品页装修 (Product)
|
||||
|
||||
- 自定义商品详情页布局
|
||||
- 支持商品图、信息、评价等模块
|
||||
- 提升商品转化率
|
||||
- A/B测试支持
|
||||
|
||||
### 4. 自定义页面 (Custom)
|
||||
|
||||
- 创建和管理自定义营销页面
|
||||
- 灵活的页面路径设置
|
||||
- 独立的装修配置
|
||||
- 活动和推广专用
|
||||
|
||||
### 5. 页面模板库 (Templates)
|
||||
|
||||
- 预设4套电商风格模板
|
||||
- 一键应用模板快速建站
|
||||
- 模板库不断扩充
|
||||
- 自定义模板保存
|
||||
|
||||
### 6. 组件库 (Components)
|
||||
|
||||
- 8种预设装修组件:
|
||||
- 图片组件 (Image)
|
||||
- 文本组件 (Text)
|
||||
- 商品组件 (Product)
|
||||
- 轮播组件 (Carousel)
|
||||
- 分割线 (Divider)
|
||||
- 间距组件 (Spacer)
|
||||
- 按钮组件 (Button)
|
||||
- 表单组件 (Form)
|
||||
|
||||
## 🔧 API 函数列表
|
||||
|
||||
| 函数 | 参数 | 返回值 | 说明 |
|
||||
| -------------------------- | ---------- | -------------------------- | ---------------- |
|
||||
| `getDesignList(params?)` | 查询参数 | Promise<DesignItem[]> | 获取装修列表 |
|
||||
| `getHomePageDesign()` | 无 | Promise<DesignItem> | 获取首页装修 |
|
||||
| `getProductPageDesign()` | 无 | Promise<DesignItem> | 获取商品页装修 |
|
||||
| `getCategoryDesigns()` | 无 | Promise<DesignItem[]> | 获取分类装修列表 |
|
||||
| `getCustomPages()` | 无 | Promise<DesignItem[]> | 获取自定义页面 |
|
||||
| `getTemplateLibrary()` | 无 | Promise<DesignTemplate[]> | 获取模板库 |
|
||||
| `getAvailableComponents()` | 无 | Promise<DesignComponent[]> | 获取可用组件 |
|
||||
| `saveDesign(design)` | DesignItem | Promise<{id, message}> | 保存装修 |
|
||||
| `publishDesign(id)` | 装修ID | Promise<{message}> | 发布装修 |
|
||||
| `deleteDesign(id)` | 装修ID | Promise<{message}> | 删除装修 |
|
||||
|
||||
## 📊 数据结构
|
||||
|
||||
### DesignItem 装修页面
|
||||
|
||||
```typescript
|
||||
interface DesignItem {
|
||||
id: string | number; // 装修ID
|
||||
name: string; // 装修名称
|
||||
type: "homepage" | "category" | "product" | "custom";
|
||||
status: 0 | 1; // 0=草稿, 1=已发布
|
||||
content: DesignComponent[]; // 组件内容
|
||||
categoryId?: string | number; // 分类ID
|
||||
categoryName?: string; // 分类名称
|
||||
path?: string; // 页面路径
|
||||
version?: string; // 版本号
|
||||
created_at?: string; // 创建时间
|
||||
updated_at?: string; // 更新时间
|
||||
}
|
||||
```
|
||||
|
||||
### DesignComponent 组件配置
|
||||
|
||||
```typescript
|
||||
interface DesignComponent {
|
||||
id: string; // 组件ID
|
||||
type:
|
||||
| "image"
|
||||
| "text"
|
||||
| "product"
|
||||
| "carousel"
|
||||
| "divider"
|
||||
| "spacer"
|
||||
| "button"
|
||||
| "form";
|
||||
name: string; // 组件名称
|
||||
icon: string; // 组件图标
|
||||
description?: string; // 组件描述
|
||||
config?: Record<string, any>; // 配置参数
|
||||
children?: DesignComponent[]; // 子组件
|
||||
}
|
||||
```
|
||||
|
||||
## 💻 使用示例
|
||||
|
||||
```typescript
|
||||
// 导入服务
|
||||
import {
|
||||
getDesignList,
|
||||
saveDesign,
|
||||
publishDesign,
|
||||
getAvailableComponents,
|
||||
} from "./design.uts";
|
||||
|
||||
// 获取列表
|
||||
const designs = await getDesignList();
|
||||
|
||||
// 保存装修
|
||||
await saveDesign({
|
||||
id: 1,
|
||||
name: "首页",
|
||||
type: "homepage",
|
||||
status: 0,
|
||||
content: [],
|
||||
});
|
||||
|
||||
// 发布装修
|
||||
await publishDesign(1);
|
||||
|
||||
// 获取组件库
|
||||
const components = await getAvailableComponents();
|
||||
```
|
||||
|
||||
## 📱 菜单配置
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "design",
|
||||
"title": "设计",
|
||||
"children": [
|
||||
{
|
||||
"id": "design-home",
|
||||
"title": "页面装修",
|
||||
"path": "/pages/mall/admin/design/index"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 🚀 后续开发
|
||||
|
||||
- [ ] editor.uvue - 装修编辑器
|
||||
- [ ] preview.uvue - 装修预览
|
||||
- [ ] 拖拽排序功能
|
||||
- [ ] 版本管理
|
||||
- [ ] 模板库管理
|
||||
|
||||
---
|
||||
|
||||
**最后更新**: 2026-01-31
|
||||
**版本**: 1.0.0
|
||||
25
pages/mall/admin/design/category.uvue
Normal file
25
pages/mall/admin/design/category.uvue
Normal file
@@ -0,0 +1,25 @@
|
||||
<template>
|
||||
<AdminLayout :currentPage="currentPage">
|
||||
<view class="page">
|
||||
<view class="header">
|
||||
<text class="title">{{ title }}</text>
|
||||
<text class="sub-title">页面已修复 (UTF-8)</text>
|
||||
</view>
|
||||
</view>
|
||||
</AdminLayout>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
import AdminLayout from '@/layouts/admin/AdminLayout.uvue'
|
||||
const currentPage = ref<string>('design-category')
|
||||
const title = ref<string>('分类页装修')
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '@/uni.scss';
|
||||
.page { padding: $space-lg; }
|
||||
.header { padding: $space-lg; border-radius: $radius; background: $background-primary; box-shadow: $shadow-xs; }
|
||||
.title { font-size: $font-size-lg; font-weight: $font-weight-bold; color: $text-primary; }
|
||||
.sub-title { margin-top: $space-xs; font-size: $font-size-md; color: $text-secondary; }
|
||||
</style>
|
||||
25
pages/mall/admin/design/components.uvue
Normal file
25
pages/mall/admin/design/components.uvue
Normal file
@@ -0,0 +1,25 @@
|
||||
<template>
|
||||
<AdminLayout :currentPage="currentPage">
|
||||
<view class="page">
|
||||
<view class="header">
|
||||
<text class="title">{{ title }}</text>
|
||||
<text class="sub-title">页面已修复 (UTF-8)</text>
|
||||
</view>
|
||||
</view>
|
||||
</AdminLayout>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
import AdminLayout from '@/layouts/admin/AdminLayout.uvue'
|
||||
const currentPage = ref<string>('category')
|
||||
const title = ref<string>('category')
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '@/uni.scss';
|
||||
.page { padding: $space-lg; }
|
||||
.header { padding: $space-lg; border-radius: $radius; background: $background-primary; box-shadow: $shadow-xs; }
|
||||
.title { font-size: $font-size-lg; font-weight: $font-weight-bold; color: $text-primary; }
|
||||
.sub-title { margin-top: $space-xs; font-size: $font-size-md; color: $text-secondary; }
|
||||
</style>
|
||||
439
pages/mall/admin/design/config.uts
Normal file
439
pages/mall/admin/design/config.uts
Normal file
@@ -0,0 +1,439 @@
|
||||
/**
|
||||
* 设计模块页面路由配置与数据
|
||||
* 将 design.uts 的函数输出转换为页面路由/配置格式
|
||||
*/
|
||||
|
||||
import type { DesignItem, DesignComponent, DesignTemplate } from './design.uts'
|
||||
|
||||
/**
|
||||
* 装修页面列表路由配置
|
||||
*/
|
||||
export const designListPageConfig = {
|
||||
id: 'design-list',
|
||||
path: '/pages/mall/admin/design/list',
|
||||
name: '装修列表',
|
||||
title: '装修管理',
|
||||
data: [
|
||||
{
|
||||
id: 1,
|
||||
name: '首页装修',
|
||||
type: 'homepage' as const,
|
||||
status: 1,
|
||||
path: '/pages/mall/admin/design/index?tab=homepage',
|
||||
content: [],
|
||||
updated_at: '2026-01-30 14:30:00'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '年货节活动页',
|
||||
type: 'custom' as const,
|
||||
status: 1,
|
||||
path: '/pages/mall/admin/design/index?tab=custom',
|
||||
content: [],
|
||||
updated_at: '2026-01-28 10:15:00'
|
||||
}
|
||||
] as DesignItem[]
|
||||
}
|
||||
|
||||
/**
|
||||
* 首页装修页面路由配置
|
||||
*/
|
||||
export const designHomepagePageConfig = {
|
||||
id: 'design-homepage',
|
||||
path: '/pages/mall/admin/design/index?tab=homepage',
|
||||
name: '首页装修',
|
||||
title: '首页装修 - 打造吸引人的商城首页',
|
||||
data: {
|
||||
id: 'homepage',
|
||||
name: '首页装修',
|
||||
type: 'homepage' as const,
|
||||
status: 1,
|
||||
content: [
|
||||
{
|
||||
id: 'carousel-1',
|
||||
type: 'carousel' as const,
|
||||
name: '轮播图',
|
||||
icon: 'C',
|
||||
description: '首页顶部轮播图展示',
|
||||
config: {
|
||||
autoplay: true,
|
||||
duration: 5000,
|
||||
height: 300
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'product-1',
|
||||
type: 'product' as const,
|
||||
name: '商品展示',
|
||||
icon: 'P',
|
||||
description: '热销商品列表',
|
||||
config: {
|
||||
count: 8,
|
||||
columns: 2,
|
||||
layout: 'grid'
|
||||
}
|
||||
}
|
||||
],
|
||||
version: '1.0.0',
|
||||
updated_at: '2026-01-30 14:30:00'
|
||||
} as DesignItem
|
||||
}
|
||||
|
||||
/**
|
||||
* 分类页装修页面路由配置
|
||||
*/
|
||||
export const designCategoryPageConfig = {
|
||||
id: 'design-category',
|
||||
path: '/pages/mall/admin/design/index?tab=category',
|
||||
name: '分类页装修',
|
||||
title: '分类页装修 - 为不同分类创建独特展示',
|
||||
data: [
|
||||
{
|
||||
id: 1,
|
||||
name: '默认分类装修',
|
||||
type: 'category' as const,
|
||||
status: 1,
|
||||
categoryId: 0,
|
||||
categoryName: '全部分类',
|
||||
path: '/pages/mall/admin/design/index?tab=category&id=1',
|
||||
content: [],
|
||||
updated_at: '2026-01-30 14:30:00'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '热销商品分类',
|
||||
type: 'category' as const,
|
||||
status: 0,
|
||||
categoryId: 1,
|
||||
categoryName: '推荐分类',
|
||||
path: '/pages/mall/admin/design/index?tab=category&id=2',
|
||||
content: [],
|
||||
updated_at: '2026-01-29 10:15:00'
|
||||
}
|
||||
] as DesignItem[]
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品页装修页面路由配置
|
||||
*/
|
||||
export const designProductPageConfig = {
|
||||
id: 'design-product',
|
||||
path: '/pages/mall/admin/design/index?tab=product',
|
||||
name: '商品页装修',
|
||||
title: '商品页装修 - 自定义商品详情页展示',
|
||||
data: {
|
||||
id: 'product',
|
||||
name: '商品页装修',
|
||||
type: 'product' as const,
|
||||
status: 1,
|
||||
content: [
|
||||
{
|
||||
id: 'image-1',
|
||||
type: 'image' as const,
|
||||
name: '商品图',
|
||||
icon: 'I',
|
||||
description: '商品主图展示'
|
||||
},
|
||||
{
|
||||
id: 'product-info',
|
||||
type: 'text' as const,
|
||||
name: '商品信息',
|
||||
icon: 'T',
|
||||
description: '商品名称和价格'
|
||||
}
|
||||
],
|
||||
version: '1.0.0',
|
||||
updated_at: '2026-01-30 14:30:00'
|
||||
} as DesignItem
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义页面路由配置
|
||||
*/
|
||||
export const designCustomPageConfig = {
|
||||
id: 'design-custom',
|
||||
path: '/pages/mall/admin/design/index?tab=custom',
|
||||
name: '自定义页面',
|
||||
title: '自定义页面 - 创建特殊内容页面',
|
||||
data: [
|
||||
{
|
||||
id: 1,
|
||||
name: '新年促销页',
|
||||
type: 'custom' as const,
|
||||
status: 1,
|
||||
path: '/pages/mall/admin/design/index?tab=custom&id=1',
|
||||
content: [],
|
||||
updated_at: '2026-01-28 09:00:00'
|
||||
}
|
||||
] as DesignItem[]
|
||||
}
|
||||
|
||||
/**
|
||||
* 模板库页面路由配置
|
||||
*/
|
||||
export const designTemplatePageConfig = {
|
||||
id: 'design-templates',
|
||||
path: '/pages/mall/admin/design/index?tab=templates',
|
||||
name: '模板库',
|
||||
title: '模板库 - 选择预设装修模板',
|
||||
data: [
|
||||
{
|
||||
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: []
|
||||
}
|
||||
] as DesignTemplate[]
|
||||
}
|
||||
|
||||
/**
|
||||
* 组件库页面路由配置
|
||||
*/
|
||||
export const designComponentPageConfig = {
|
||||
id: 'design-components',
|
||||
path: '/pages/mall/admin/design/index?tab=components',
|
||||
name: '组件库',
|
||||
title: '组件库 - 丰富的页面组件',
|
||||
data: [
|
||||
{
|
||||
id: 'image',
|
||||
type: 'image' as const,
|
||||
name: '图片组件',
|
||||
icon: 'I',
|
||||
description: '展示图片和图片轮播',
|
||||
componentName: 'ImageComponent',
|
||||
config: {
|
||||
defaultWidth: '100%',
|
||||
defaultHeight: 'auto'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'text',
|
||||
type: 'text' as const,
|
||||
name: '文本组件',
|
||||
icon: 'T',
|
||||
description: '展示文本内容和段落',
|
||||
componentName: 'TextComponent'
|
||||
},
|
||||
{
|
||||
id: 'product',
|
||||
type: 'product' as const,
|
||||
name: '商品组件',
|
||||
icon: 'P',
|
||||
description: '展示商品列表和推荐',
|
||||
componentName: 'ProductComponent',
|
||||
config: {
|
||||
defaultCount: 6,
|
||||
defaultColumns: 2
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'carousel',
|
||||
type: 'carousel' as const,
|
||||
name: '轮播组件',
|
||||
icon: 'C',
|
||||
description: '图片和内容轮播',
|
||||
componentName: 'CarouselComponent',
|
||||
config: {
|
||||
autoplay: true,
|
||||
duration: 5000
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'divider',
|
||||
type: 'divider' as const,
|
||||
name: '分割线',
|
||||
icon: 'D',
|
||||
description: '分割不同内容区域',
|
||||
componentName: 'DividerComponent'
|
||||
},
|
||||
{
|
||||
id: 'spacer',
|
||||
type: 'spacer' as const,
|
||||
name: '间距组件',
|
||||
icon: 'S',
|
||||
description: '调整元素间距',
|
||||
componentName: 'SpacerComponent',
|
||||
config: {
|
||||
defaultHeight: 16
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'button',
|
||||
type: 'button' as const,
|
||||
name: '按钮组件',
|
||||
icon: 'B',
|
||||
description: '创建点击按钮',
|
||||
componentName: 'ButtonComponent'
|
||||
},
|
||||
{
|
||||
id: 'form',
|
||||
type: 'form' as const,
|
||||
name: '表单组件',
|
||||
icon: 'F',
|
||||
description: '收集用户输入数据',
|
||||
componentName: 'FormComponent'
|
||||
}
|
||||
] as DesignComponent[]
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑页面路由配置
|
||||
*/
|
||||
export const designEditorPageConfig = {
|
||||
id: 'design-editor',
|
||||
path: '/pages/mall/admin/design/editor',
|
||||
name: '装修编辑器',
|
||||
title: '装修编辑器 - 可视化编辑装修页面',
|
||||
components: [
|
||||
{
|
||||
id: 'canvas',
|
||||
name: '编辑画布',
|
||||
description: '拖拽编辑区域'
|
||||
},
|
||||
{
|
||||
id: 'sidebar',
|
||||
name: '组件侧栏',
|
||||
description: '可用组件列表'
|
||||
},
|
||||
{
|
||||
id: 'properties',
|
||||
name: '属性面板',
|
||||
description: '组件属性编辑'
|
||||
},
|
||||
{
|
||||
id: 'preview',
|
||||
name: '预览窗口',
|
||||
description: '实时效果预览'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* 预览页面路由配置
|
||||
*/
|
||||
export const designPreviewPageConfig = {
|
||||
id: 'design-preview',
|
||||
path: '/pages/mall/design/preview/:id',
|
||||
name: '装修预览',
|
||||
title: '装修效果预览',
|
||||
features: [
|
||||
'全屏预览',
|
||||
'响应式展示',
|
||||
'交互测试',
|
||||
'性能分析'
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* 所有设计页面路由配置
|
||||
*/
|
||||
export const allDesignPageConfigs = [
|
||||
designListPageConfig,
|
||||
designHomepagePageConfig,
|
||||
designCategoryPageConfig,
|
||||
designProductPageConfig,
|
||||
designCustomPageConfig,
|
||||
designTemplatePageConfig,
|
||||
designComponentPageConfig,
|
||||
designEditorPageConfig,
|
||||
designPreviewPageConfig
|
||||
]
|
||||
|
||||
/**
|
||||
* 根据 tab 获取对应的页面配置
|
||||
*/
|
||||
export function getDesignPageConfig(tab: string) {
|
||||
const configMap: Record<string, any> = {
|
||||
'homepage': designHomepagePageConfig,
|
||||
'category': designCategoryPageConfig,
|
||||
'product': designProductPageConfig,
|
||||
'custom': designCustomPageConfig,
|
||||
'templates': designTemplatePageConfig,
|
||||
'components': designComponentPageConfig,
|
||||
'editor': designEditorPageConfig,
|
||||
'preview': designPreviewPageConfig,
|
||||
'list': designListPageConfig
|
||||
}
|
||||
return configMap[tab] || designListPageConfig
|
||||
}
|
||||
|
||||
/**
|
||||
* 装修页面导航菜单结构
|
||||
*/
|
||||
export const designMenuStructure = {
|
||||
id: 'design',
|
||||
title: '设计',
|
||||
icon: '/static/design.svg',
|
||||
path: '/pages/mall/admin/design/index',
|
||||
children: [
|
||||
{
|
||||
id: 'page-decoration',
|
||||
title: '页面装修',
|
||||
children: [
|
||||
{
|
||||
id: 'design-homepage',
|
||||
title: '首页装修',
|
||||
path: '/pages/mall/admin/design/index?tab=homepage'
|
||||
},
|
||||
{
|
||||
id: 'design-category',
|
||||
title: '分类页装修',
|
||||
path: '/pages/mall/admin/design/index?tab=category'
|
||||
},
|
||||
{
|
||||
id: 'design-product',
|
||||
title: '商品页装修',
|
||||
path: '/pages/mall/admin/design/index?tab=product'
|
||||
},
|
||||
{
|
||||
id: 'design-custom',
|
||||
title: '自定义页面',
|
||||
path: '/pages/mall/admin/design/index?tab=custom'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'design-library',
|
||||
title: '设计库',
|
||||
children: [
|
||||
{
|
||||
id: 'design-templates',
|
||||
title: '模板库',
|
||||
path: '/pages/mall/admin/design/index?tab=templates'
|
||||
},
|
||||
{
|
||||
id: 'design-components',
|
||||
title: '组件库',
|
||||
path: '/pages/mall/admin/design/index?tab=components'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
25
pages/mall/admin/design/custom.uvue
Normal file
25
pages/mall/admin/design/custom.uvue
Normal file
@@ -0,0 +1,25 @@
|
||||
<template>
|
||||
<AdminLayout :currentPage="currentPage">
|
||||
<view class="page">
|
||||
<view class="header">
|
||||
<text class="title">{{ title }}</text>
|
||||
<text class="sub-title">页面已修复 (UTF-8)</text>
|
||||
</view>
|
||||
</view>
|
||||
</AdminLayout>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
import AdminLayout from '@/layouts/admin/AdminLayout.uvue'
|
||||
const currentPage = ref<string>('custom')
|
||||
const title = ref<string>('custom')
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '@/uni.scss';
|
||||
.page { padding: $space-lg; }
|
||||
.header { padding: $space-lg; border-radius: $radius; background: $background-primary; box-shadow: $shadow-xs; }
|
||||
.title { font-size: $font-size-lg; font-weight: $font-weight-bold; color: $text-primary; }
|
||||
.sub-title { margin-top: $space-xs; font-size: $font-size-md; color: $text-secondary; }
|
||||
</style>
|
||||
38
pages/mall/admin/design/data-config.uvue
Normal file
38
pages/mall/admin/design/data-config.uvue
Normal file
@@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<AdminLayout current-page="design-data">
|
||||
<view class="admin-main">
|
||||
<view class="header">
|
||||
<text class="title">数据配置</text>
|
||||
</view>
|
||||
<view class="content">
|
||||
<text>商城数据配置(建设中)</text>
|
||||
</view>
|
||||
</view>
|
||||
</AdminLayout>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import AdminLayout from '@/layouts/admin/AdminLayout.uvue'
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.admin-main {
|
||||
padding: 20px;
|
||||
}
|
||||
.header {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.title {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.content {
|
||||
background-color: #fff;
|
||||
padding: 20px;
|
||||
border-radius: 4px;
|
||||
min-height: 400px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
549
pages/mall/admin/design/design.uts
Normal file
549
pages/mall/admin/design/design.uts
Normal file
@@ -0,0 +1,549 @@
|
||||
/**
|
||||
* 页面装修业务逻辑模块
|
||||
* 参考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<string, any>
|
||||
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<string, any>): Promise<DesignItem[]> {
|
||||
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<DesignItem> {
|
||||
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<DesignItem> {
|
||||
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<DesignItem[]> {
|
||||
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<DesignItem[]> {
|
||||
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<DesignTemplate[]> {
|
||||
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<DesignComponent[]> {
|
||||
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格式错误,无法导入')
|
||||
}
|
||||
}
|
||||
25
pages/mall/admin/design/homepage.uvue
Normal file
25
pages/mall/admin/design/homepage.uvue
Normal file
@@ -0,0 +1,25 @@
|
||||
<template>
|
||||
<AdminLayout :currentPage="currentPage">
|
||||
<view class="page">
|
||||
<view class="header">
|
||||
<text class="title">{{ title }}</text>
|
||||
<text class="sub-title">页面已修复 (UTF-8)</text>
|
||||
</view>
|
||||
</view>
|
||||
</AdminLayout>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
import AdminLayout from '@/layouts/admin/AdminLayout.uvue'
|
||||
const currentPage = ref<string>('design-homepage')
|
||||
const title = ref<string>('首页装修')
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '@/uni.scss';
|
||||
.page { padding: $space-lg; }
|
||||
.header { padding: $space-lg; border-radius: $radius; background: $background-primary; box-shadow: $shadow-xs; }
|
||||
.title { font-size: $font-size-lg; font-weight: $font-weight-bold; color: $text-primary; }
|
||||
.sub-title { margin-top: $space-xs; font-size: $font-size-md; color: $text-secondary; }
|
||||
</style>
|
||||
38
pages/mall/admin/design/link-management.uvue
Normal file
38
pages/mall/admin/design/link-management.uvue
Normal file
@@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<AdminLayout current-page="design-link">
|
||||
<view class="admin-main">
|
||||
<view class="header">
|
||||
<text class="title">链接管理</text>
|
||||
</view>
|
||||
<view class="content">
|
||||
<text>商城链接管理(建设中)</text>
|
||||
</view>
|
||||
</view>
|
||||
</AdminLayout>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import AdminLayout from '@/layouts/admin/AdminLayout.uvue'
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.admin-main {
|
||||
padding: 20px;
|
||||
}
|
||||
.header {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.title {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.content {
|
||||
background-color: #fff;
|
||||
padding: 20px;
|
||||
border-radius: 4px;
|
||||
min-height: 400px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
38
pages/mall/admin/design/material.uvue
Normal file
38
pages/mall/admin/design/material.uvue
Normal file
@@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<AdminLayout current-page="design-material">
|
||||
<view class="admin-main">
|
||||
<view class="header">
|
||||
<text class="title">素材管理</text>
|
||||
</view>
|
||||
<view class="content">
|
||||
<text>商城素材管理(建设中)</text>
|
||||
</view>
|
||||
</view>
|
||||
</AdminLayout>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import AdminLayout from '@/layouts/admin/AdminLayout.uvue'
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.admin-main {
|
||||
padding: 20px;
|
||||
}
|
||||
.header {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.title {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.content {
|
||||
background-color: #fff;
|
||||
padding: 20px;
|
||||
border-radius: 4px;
|
||||
min-height: 400px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
25
pages/mall/admin/design/product.uvue
Normal file
25
pages/mall/admin/design/product.uvue
Normal file
@@ -0,0 +1,25 @@
|
||||
<template>
|
||||
<AdminLayout :currentPage="currentPage">
|
||||
<view class="page">
|
||||
<view class="header">
|
||||
<text class="title">{{ title }}</text>
|
||||
<text class="sub-title">页面已修复 (UTF-8)</text>
|
||||
</view>
|
||||
</view>
|
||||
</AdminLayout>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
import AdminLayout from '@/layouts/admin/AdminLayout.uvue'
|
||||
const currentPage = ref<string>('product')
|
||||
const title = ref<string>('product')
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '@/uni.scss';
|
||||
.page { padding: $space-lg; }
|
||||
.header { padding: $space-lg; border-radius: $radius; background: $background-primary; box-shadow: $shadow-xs; }
|
||||
.title { font-size: $font-size-lg; font-weight: $font-weight-bold; color: $text-primary; }
|
||||
.sub-title { margin-top: $space-xs; font-size: $font-size-md; color: $text-secondary; }
|
||||
</style>
|
||||
162
pages/mall/admin/design/templates.uvue
Normal file
162
pages/mall/admin/design/templates.uvue
Normal file
@@ -0,0 +1,162 @@
|
||||
<template>
|
||||
<AdminLayout :currentPage="currentPage">
|
||||
<view class="design-container">
|
||||
<view class="module-header">
|
||||
<text class="module-title">模板库</text>
|
||||
<text class="module-desc">从丰富的模板中快速创建页面</text>
|
||||
</view>
|
||||
<view class="templates-grid">
|
||||
<view v-for="template in templateLibrary" :key="template.id" class="template-card">
|
||||
<view class="template-header">
|
||||
<text class="template-name">{{ template.name }}</text>
|
||||
</view>
|
||||
<view class="template-body">
|
||||
<text class="template-desc">{{ template.description }}</text>
|
||||
<button class="btn-use" @click="handleUseTemplate(template.id)">使用模板</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</AdminLayout>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
import AdminLayout from '@/layouts/admin/AdminLayout.uvue'
|
||||
|
||||
const currentPage = ref<string>('design-templates')
|
||||
|
||||
const templateLibrary = ref<any[]>([
|
||||
{
|
||||
id: 1,
|
||||
name: '首页模板A',
|
||||
description: '经典电商首页布局'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '首页模板B',
|
||||
description: '简约风格的商城页面'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '活动模板',
|
||||
description: '活动促销页面布局'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '商品模板',
|
||||
description: '商品展示页面布局'
|
||||
}
|
||||
])
|
||||
|
||||
const handleUseTemplate = (templateId: number) => {
|
||||
console.log('使用模板', templateId)
|
||||
uni.showToast({
|
||||
title: '使用模板成功',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '@/uni.scss';
|
||||
|
||||
.design-container {
|
||||
min-height: 100vh;
|
||||
background: $background-secondary;
|
||||
padding: $space-lg;
|
||||
}
|
||||
|
||||
.module-header {
|
||||
margin-bottom: $space-xl;
|
||||
}
|
||||
|
||||
.module-title {
|
||||
font-size: $font-size-lg;
|
||||
font-weight: bold;
|
||||
color: $text-primary;
|
||||
display: block;
|
||||
margin-bottom: $space-sm;
|
||||
}
|
||||
|
||||
.module-desc {
|
||||
font-size: $font-size-sm;
|
||||
color: $text-secondary;
|
||||
}
|
||||
|
||||
.templates-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
gap: $space-lg;
|
||||
margin-bottom: $space-lg;
|
||||
}
|
||||
|
||||
.template-card {
|
||||
background: white;
|
||||
border-radius: $radius-lg;
|
||||
box-shadow: $shadow-sm;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
box-shadow: $shadow-md;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
}
|
||||
|
||||
.template-header {
|
||||
padding: $space-lg;
|
||||
background: $background-tertiary;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.template-body {
|
||||
padding: $space-lg;
|
||||
}
|
||||
|
||||
.template-name {
|
||||
font-size: $font-size-md;
|
||||
font-weight: bold;
|
||||
color: $text-primary;
|
||||
display: block;
|
||||
margin-bottom: $space-sm;
|
||||
}
|
||||
|
||||
.template-desc {
|
||||
color: $text-secondary;
|
||||
font-size: $font-size-sm;
|
||||
line-height: 1.5;
|
||||
display: block;
|
||||
margin-bottom: $space-lg;
|
||||
}
|
||||
|
||||
.btn-use {
|
||||
background: $primary-color;
|
||||
color: white;
|
||||
padding: $space-sm $space-lg;
|
||||
border-radius: $radius-sm;
|
||||
border: none;
|
||||
margin-top: $space-lg;
|
||||
font-size: $font-size-sm;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.design-container {
|
||||
padding: $space-md;
|
||||
}
|
||||
|
||||
.templates-grid {
|
||||
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.templates-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
38
pages/mall/admin/design/theme-style.uvue
Normal file
38
pages/mall/admin/design/theme-style.uvue
Normal file
@@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<AdminLayout current-page="design-theme">
|
||||
<view class="admin-main">
|
||||
<view class="header">
|
||||
<text class="title">主题风格</text>
|
||||
</view>
|
||||
<view class="content">
|
||||
<text>商城主题风格设置(建设中)</text>
|
||||
</view>
|
||||
</view>
|
||||
</AdminLayout>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import AdminLayout from '@/layouts/admin/AdminLayout.uvue'
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.admin-main {
|
||||
padding: 20px;
|
||||
}
|
||||
.header {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.title {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.content {
|
||||
background-color: #fff;
|
||||
padding: 20px;
|
||||
border-radius: 4px;
|
||||
min-height: 400px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
38
pages/mall/admin/design/user.uvue
Normal file
38
pages/mall/admin/design/user.uvue
Normal file
@@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<AdminLayout current-page="design-user">
|
||||
<view class="admin-main">
|
||||
<view class="header">
|
||||
<text class="title">个人中心装修</text>
|
||||
</view>
|
||||
<view class="content">
|
||||
<text>个人中心页面装修(建设中)</text>
|
||||
</view>
|
||||
</view>
|
||||
</AdminLayout>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import AdminLayout from '@/layouts/admin/AdminLayout.uvue'
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.admin-main {
|
||||
padding: 20px;
|
||||
}
|
||||
.header {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.title {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.content {
|
||||
background-color: #fff;
|
||||
padding: 20px;
|
||||
border-radius: 4px;
|
||||
min-height: 400px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user