From 2166ce3e4e90f1d23b78594e30b246b48ffc5898 Mon Sep 17 00:00:00 2001 From: lrl <252048765@qq.com> Date: Mon, 4 Aug 2025 09:09:39 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E5=A4=9A=E4=B8=AA?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E5=B9=B6=E4=BC=98=E5=8C=96=E4=BC=98=E6=83=A0?= =?UTF-8?q?=E5=88=B8=E7=9B=B8=E5=85=B3=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 AppLinkSelectDialog 组件,用于选择 APP 链接- 新增 NavigationBarCellProperty组件,用于导航栏单元格属性设置 - 新增 CombinationShowcase 和 CombinationTableSelect 组件,用于拼团活动展示和选择- 优化优惠券相关组件,导出所有优惠券相关组件 - 新增 ComponentContainer 组件,用于包裹和样式化 DIY 组件 --- apps/web-ele/package.json | 4 +- .../combination/combinationActivity.ts | 2 + .../src/api/mall/promotion/diy/page.ts | 2 +- .../mall/promotion/seckill/seckillActivity.ts | 2 + .../app-link-input/app-link-select-dialog.vue | 236 +++++++ .../src/components/app-link-input/data.ts | 236 +++++++ .../src/components/app-link-input/index.vue | 43 ++ .../components/ComponentContainer.vue | 255 +++++++ .../components/ComponentContainerProperty.vue | 180 +++++ .../components/ComponentLibrary.vue | 219 ++++++ .../components/mobile/Carousel/config.ts | 61 ++ .../components/mobile/Carousel/index.vue | 46 ++ .../components/mobile/Carousel/property.vue | 112 +++ .../mobile/CouponCard/CouponDiscount.tsx | 35 + .../mobile/CouponCard/CouponDiscountDesc.tsx | 35 + .../mobile/CouponCard/CouponValidTerm.tsx | 29 + .../mobile/CouponCard/component.tsx | 4 + .../components/mobile/CouponCard/config.ts | 50 ++ .../components/mobile/CouponCard/index.vue | 163 +++++ .../components/mobile/CouponCard/property.vue | 147 ++++ .../components/mobile/Divider/config.ts | 29 + .../components/mobile/Divider/index.vue | 29 + .../components/mobile/Divider/property.vue | 93 +++ .../mobile/FloatingActionButton/config.ts | 36 + .../mobile/FloatingActionButton/index.vue | 86 +++ .../mobile/FloatingActionButton/property.vue | 48 ++ .../HotZoneEditDialog/controller.ts | 175 +++++ .../components/HotZoneEditDialog/index.vue | 280 ++++++++ .../components/mobile/HotZone/config.ts | 46 ++ .../components/mobile/HotZone/index.vue | 45 ++ .../components/mobile/HotZone/property.vue | 81 +++ .../components/mobile/ImageBar/config.ts | 30 + .../components/mobile/ImageBar/index.vue | 27 + .../components/mobile/ImageBar/property.vue | 35 + .../components/mobile/MagicCube/config.ts | 52 ++ .../components/mobile/MagicCube/index.vue | 80 +++ .../components/mobile/MagicCube/property.vue | 79 +++ .../components/mobile/MenuGrid/config.ts | 83 +++ .../components/mobile/MenuGrid/index.vue | 45 ++ .../components/mobile/MenuGrid/property.vue | 74 ++ .../components/mobile/MenuList/config.ts | 52 ++ .../components/mobile/MenuList/index.vue | 40 ++ .../components/mobile/MenuList/property.vue | 54 ++ .../components/mobile/MenuSwiper/config.ts | 70 ++ .../components/mobile/MenuSwiper/index.vue | 135 ++++ .../components/mobile/MenuSwiper/property.vue | 83 +++ .../NavigationBar/components/CellProperty.vue | 115 ++++ .../components/mobile/NavigationBar/config.ts | 82 +++ .../components/mobile/NavigationBar/index.vue | 111 +++ .../mobile/NavigationBar/property.vue | 116 ++++ .../components/mobile/NoticeBar/config.ts | 49 ++ .../components/mobile/NoticeBar/index.vue | 34 + .../components/mobile/NoticeBar/property.vue | 50 ++ .../components/mobile/PageConfig/config.ts | 23 + .../components/mobile/PageConfig/property.vue | 38 + .../components/mobile/Popover/config.ts | 26 + .../components/mobile/Popover/index.vue | 40 ++ .../components/mobile/Popover/property.vue | 42 ++ .../components/mobile/ProductCard/config.ts | 100 +++ .../components/mobile/ProductCard/index.vue | 188 +++++ .../mobile/ProductCard/property.vue | 159 +++++ .../components/mobile/ProductList/config.ts | 67 ++ .../components/mobile/ProductList/index.vue | 148 ++++ .../mobile/ProductList/property.vue | 105 +++ .../mobile/PromotionArticle/config.ts | 28 + .../mobile/PromotionArticle/index.vue | 33 + .../mobile/PromotionArticle/property.vue | 66 ++ .../mobile/PromotionCombination/config.ts | 99 +++ .../mobile/PromotionCombination/index.vue | 231 +++++++ .../mobile/PromotionCombination/property.vue | 180 +++++ .../mobile/PromotionPoint/config.ts | 99 +++ .../mobile/PromotionPoint/index.vue | 232 +++++++ .../mobile/PromotionPoint/property.vue | 164 +++++ .../mobile/PromotionSeckill/config.ts | 99 +++ .../mobile/PromotionSeckill/index.vue | 227 ++++++ .../mobile/PromotionSeckill/property.vue | 180 +++++ .../components/mobile/SearchBar/config.ts | 46 ++ .../components/mobile/SearchBar/index.vue | 78 +++ .../components/mobile/SearchBar/property.vue | 100 +++ .../components/mobile/TabBar/config.ts | 172 +++++ .../components/mobile/TabBar/index.vue | 75 ++ .../components/mobile/TabBar/property.vue | 123 ++++ .../components/mobile/TitleBar/config.ts | 76 ++ .../components/mobile/TitleBar/index.vue | 84 +++ .../components/mobile/TitleBar/property.vue | 145 ++++ .../components/mobile/UserCard/config.ts | 24 + .../components/mobile/UserCard/index.vue | 31 + .../components/mobile/UserCard/property.vue | 18 + .../components/mobile/UserCoupon/config.ts | 26 + .../components/mobile/UserCoupon/index.vue | 15 + .../components/mobile/UserCoupon/property.vue | 18 + .../components/mobile/UserOrder/config.ts | 26 + .../components/mobile/UserOrder/index.vue | 15 + .../components/mobile/UserOrder/property.vue | 18 + .../components/mobile/UserWallet/config.ts | 26 + .../components/mobile/UserWallet/index.vue | 15 + .../components/mobile/UserWallet/property.vue | 18 + .../components/mobile/VideoPlayer/config.ts | 40 ++ .../components/mobile/VideoPlayer/index.vue | 34 + .../mobile/VideoPlayer/property.vue | 56 ++ .../diy-editor/components/mobile/index.ts | 69 ++ .../src/components/diy-editor/index.vue | 648 ++++++++++++++++++ .../web-ele/src/components/diy-editor/util.ts | 129 ++++ apps/web-ele/src/router/routes/modules/diy.ts | 38 + .../components/product-category-select.vue | 69 ++ .../product/spu/components/spu-showcase.vue | 162 +++++ .../spu/components/spu-table-select.vue | 345 ++++++++++ .../components/combination-showcase.vue | 175 +++++ .../components/combination-table-select.vue | 392 +++++++++++ .../coupon/components/coupon-select.vue | 219 ++++++ .../promotion/diy/page/modules/decorate.vue | 75 ++ .../diy/template/modules/decorate.vue | 217 ++++++ .../point/components/point-showcase.vue | 176 +++++ .../point/components/point-table-select.vue | 351 ++++++++++ .../seckill/components/seckill-showcase.vue | 173 +++++ .../components/seckill-table-select.vue | 385 +++++++++++ .../member/components/member-region-card.vue | 7 +- .../product/components/product-rank.vue | 8 +- packages/@core/base/shared/src/utils/date.ts | 11 + .../base/shared/src/utils/formatNumber.ts | 5 + packages/@core/base/shared/src/utils/util.ts | 28 +- pnpm-lock.yaml | 9 + pnpm-workspace.yaml | 1 + 123 files changed, 11829 insertions(+), 21 deletions(-) create mode 100644 apps/web-ele/src/components/app-link-input/app-link-select-dialog.vue create mode 100644 apps/web-ele/src/components/app-link-input/data.ts create mode 100644 apps/web-ele/src/components/app-link-input/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/ComponentContainer.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/ComponentContainerProperty.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/ComponentLibrary.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/Carousel/config.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/Carousel/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/Carousel/property.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/CouponCard/CouponDiscount.tsx create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/CouponCard/CouponDiscountDesc.tsx create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/CouponCard/CouponValidTerm.tsx create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/CouponCard/component.tsx create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/CouponCard/config.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/CouponCard/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/CouponCard/property.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/Divider/config.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/Divider/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/Divider/property.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/FloatingActionButton/config.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/FloatingActionButton/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/FloatingActionButton/property.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/HotZone/components/HotZoneEditDialog/controller.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/HotZone/components/HotZoneEditDialog/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/HotZone/config.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/HotZone/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/HotZone/property.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/ImageBar/config.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/ImageBar/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/ImageBar/property.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/MagicCube/config.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/MagicCube/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/MagicCube/property.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/MenuGrid/config.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/MenuGrid/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/MenuGrid/property.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/MenuList/config.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/MenuList/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/MenuList/property.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/MenuSwiper/config.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/MenuSwiper/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/MenuSwiper/property.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/NavigationBar/components/CellProperty.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/NavigationBar/config.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/NavigationBar/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/NavigationBar/property.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/NoticeBar/config.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/NoticeBar/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/NoticeBar/property.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/PageConfig/config.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/PageConfig/property.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/Popover/config.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/Popover/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/Popover/property.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/ProductCard/config.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/ProductCard/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/ProductCard/property.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/ProductList/config.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/ProductList/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/ProductList/property.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/PromotionArticle/config.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/PromotionArticle/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/PromotionArticle/property.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/PromotionCombination/config.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/PromotionCombination/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/PromotionCombination/property.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/PromotionPoint/config.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/PromotionPoint/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/PromotionPoint/property.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/PromotionSeckill/config.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/PromotionSeckill/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/PromotionSeckill/property.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/SearchBar/config.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/SearchBar/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/SearchBar/property.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/TabBar/config.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/TabBar/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/TabBar/property.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/TitleBar/config.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/TitleBar/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/TitleBar/property.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/UserCard/config.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/UserCard/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/UserCard/property.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/UserCoupon/config.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/UserCoupon/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/UserCoupon/property.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/UserOrder/config.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/UserOrder/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/UserOrder/property.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/UserWallet/config.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/UserWallet/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/UserWallet/property.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/VideoPlayer/config.ts create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/VideoPlayer/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/VideoPlayer/property.vue create mode 100644 apps/web-ele/src/components/diy-editor/components/mobile/index.ts create mode 100644 apps/web-ele/src/components/diy-editor/index.vue create mode 100644 apps/web-ele/src/components/diy-editor/util.ts create mode 100644 apps/web-ele/src/router/routes/modules/diy.ts create mode 100644 apps/web-ele/src/views/mall/product/category/components/product-category-select.vue create mode 100644 apps/web-ele/src/views/mall/product/spu/components/spu-showcase.vue create mode 100644 apps/web-ele/src/views/mall/product/spu/components/spu-table-select.vue create mode 100644 apps/web-ele/src/views/mall/promotion/combination/components/combination-showcase.vue create mode 100644 apps/web-ele/src/views/mall/promotion/combination/components/combination-table-select.vue create mode 100644 apps/web-ele/src/views/mall/promotion/coupon/components/coupon-select.vue create mode 100644 apps/web-ele/src/views/mall/promotion/diy/page/modules/decorate.vue create mode 100644 apps/web-ele/src/views/mall/promotion/diy/template/modules/decorate.vue create mode 100644 apps/web-ele/src/views/mall/promotion/point/components/point-showcase.vue create mode 100644 apps/web-ele/src/views/mall/promotion/point/components/point-table-select.vue create mode 100644 apps/web-ele/src/views/mall/promotion/seckill/components/seckill-showcase.vue create mode 100644 apps/web-ele/src/views/mall/promotion/seckill/components/seckill-table-select.vue diff --git a/apps/web-ele/package.json b/apps/web-ele/package.json index a2d84f231..fddb1f8b4 100644 --- a/apps/web-ele/package.json +++ b/apps/web-ele/package.json @@ -51,7 +51,9 @@ "highlight.js": "catalog:", "pinia": "catalog:", "vue": "catalog:", - "vue-router": "catalog:" + "vue-dompurify-html": "catalog:", + "vue-router": "catalog:", + "vuedraggable": "catalog:" }, "devDependencies": { "unplugin-element-plus": "catalog:" diff --git a/apps/web-ele/src/api/mall/promotion/combination/combinationActivity.ts b/apps/web-ele/src/api/mall/promotion/combination/combinationActivity.ts index c0d53d6b2..486f05aa6 100644 --- a/apps/web-ele/src/api/mall/promotion/combination/combinationActivity.ts +++ b/apps/web-ele/src/api/mall/promotion/combination/combinationActivity.ts @@ -48,6 +48,8 @@ export namespace MallCombinationActivityApi { combinationPrice?: number; /** 商品列表 */ products: CombinationProduct[]; + /** 图片 */ + picUrl?: string; } /** 扩展 SKU 配置 */ diff --git a/apps/web-ele/src/api/mall/promotion/diy/page.ts b/apps/web-ele/src/api/mall/promotion/diy/page.ts index daa5e4b06..afdface5a 100644 --- a/apps/web-ele/src/api/mall/promotion/diy/page.ts +++ b/apps/web-ele/src/api/mall/promotion/diy/page.ts @@ -52,7 +52,7 @@ export function deleteDiyPage(id: number) { /** 获得装修页面属性 */ export function getDiyPageProperty(id: number) { - return requestClient.get(`/promotion/diy-page/get-property?id=${id}`); + return requestClient.get(`/promotion/diy-page/get-property?id=${id}`); } /** 更新装修页面属性 */ diff --git a/apps/web-ele/src/api/mall/promotion/seckill/seckillActivity.ts b/apps/web-ele/src/api/mall/promotion/seckill/seckillActivity.ts index e11e8828a..9a7e121dd 100644 --- a/apps/web-ele/src/api/mall/promotion/seckill/seckillActivity.ts +++ b/apps/web-ele/src/api/mall/promotion/seckill/seckillActivity.ts @@ -55,6 +55,8 @@ export namespace MallSeckillActivityApi { seckillPrice?: number; /** 秒杀商品列表 */ products?: SeckillProduct[]; + /** 图片 */ + picUrl?: string; } /** 扩展 SKU 配置 */ diff --git a/apps/web-ele/src/components/app-link-input/app-link-select-dialog.vue b/apps/web-ele/src/components/app-link-input/app-link-select-dialog.vue new file mode 100644 index 000000000..a1a106a79 --- /dev/null +++ b/apps/web-ele/src/components/app-link-input/app-link-select-dialog.vue @@ -0,0 +1,236 @@ + + + diff --git a/apps/web-ele/src/components/app-link-input/data.ts b/apps/web-ele/src/components/app-link-input/data.ts new file mode 100644 index 000000000..550b88d76 --- /dev/null +++ b/apps/web-ele/src/components/app-link-input/data.ts @@ -0,0 +1,236 @@ +// APP 链接分组 +export interface AppLinkGroup { + // 分组名称 + name: string; + // 链接列表 + links: AppLink[]; +} + +// APP 链接 +export interface AppLink { + // 链接名称 + name: string; + // 链接地址 + path: string; + // 链接的类型 + type?: APP_LINK_TYPE_ENUM; +} + +// APP 链接类型(需要特殊处理,例如商品详情) +export enum APP_LINK_TYPE_ENUM { + // 拼团活动 + ACTIVITY_COMBINATION, + // 积分商城活动 + ACTIVITY_POINT, + // 秒杀活动 + ACTIVITY_SECKILL, + // 文章详情 + ARTICLE_DETAIL, + // 优惠券详情 + COUPON_DETAIL, + // 自定义页面详情 + DIY_PAGE_DETAIL, + // 品类列表 + PRODUCT_CATEGORY_LIST, + // 拼团商品详情 + PRODUCT_DETAIL_COMBINATION, + // 商品详情 + PRODUCT_DETAIL_NORMAL, + // 秒杀商品详情 + PRODUCT_DETAIL_SECKILL, + // 商品列表 + PRODUCT_LIST, +} + +// APP 链接列表(做一下持久化?) +export const APP_LINK_GROUP_LIST = [ + { + name: '商城', + links: [ + { + name: '首页', + path: '/pages/index/index', + }, + { + name: '商品分类', + path: '/pages/index/category', + type: APP_LINK_TYPE_ENUM.PRODUCT_CATEGORY_LIST, + }, + { + name: '购物车', + path: '/pages/index/cart', + }, + { + name: '个人中心', + path: '/pages/index/user', + }, + { + name: '商品搜索', + path: '/pages/index/search', + }, + { + name: '自定义页面', + path: '/pages/index/page', + type: APP_LINK_TYPE_ENUM.DIY_PAGE_DETAIL, + }, + { + name: '客服', + path: '/pages/chat/index', + }, + { + name: '系统设置', + path: '/pages/public/setting', + }, + { + name: '常见问题', + path: '/pages/public/faq', + }, + ], + }, + { + name: '商品', + links: [ + { + name: '商品列表', + path: '/pages/goods/list', + type: APP_LINK_TYPE_ENUM.PRODUCT_LIST, + }, + { + name: '商品详情', + path: '/pages/goods/index', + type: APP_LINK_TYPE_ENUM.PRODUCT_DETAIL_NORMAL, + }, + { + name: '拼团商品详情', + path: '/pages/goods/groupon', + type: APP_LINK_TYPE_ENUM.PRODUCT_DETAIL_COMBINATION, + }, + { + name: '秒杀商品详情', + path: '/pages/goods/seckill', + type: APP_LINK_TYPE_ENUM.PRODUCT_DETAIL_SECKILL, + }, + ], + }, + { + name: '营销活动', + links: [ + { + name: '拼团订单', + path: '/pages/activity/groupon/order', + }, + { + name: '营销商品', + path: '/pages/activity/index', + }, + { + name: '拼团活动', + path: '/pages/activity/groupon/list', + type: APP_LINK_TYPE_ENUM.ACTIVITY_COMBINATION, + }, + { + name: '秒杀活动', + path: '/pages/activity/seckill/list', + type: APP_LINK_TYPE_ENUM.ACTIVITY_SECKILL, + }, + { + name: '积分商城活动', + path: '/pages/activity/point/list', + type: APP_LINK_TYPE_ENUM.ACTIVITY_POINT, + }, + { + name: '签到中心', + path: '/pages/app/sign', + }, + { + name: '优惠券中心', + path: '/pages/coupon/list', + }, + { + name: '优惠券详情', + path: '/pages/coupon/detail', + type: APP_LINK_TYPE_ENUM.COUPON_DETAIL, + }, + { + name: '文章详情', + path: '/pages/public/richtext', + type: APP_LINK_TYPE_ENUM.ARTICLE_DETAIL, + }, + ], + }, + { + name: '分销商城', + links: [ + { + name: '分销中心', + path: '/pages/commission/index', + }, + { + name: '推广商品', + path: '/pages/commission/goods', + }, + { + name: '分销订单', + path: '/pages/commission/order', + }, + { + name: '我的团队', + path: '/pages/commission/team', + }, + ], + }, + { + name: '支付', + links: [ + { + name: '充值余额', + path: '/pages/pay/recharge', + }, + { + name: '充值记录', + path: '/pages/pay/recharge-log', + }, + ], + }, + { + name: '用户中心', + links: [ + { + name: '用户信息', + path: '/pages/user/info', + }, + { + name: '用户订单', + path: '/pages/order/list', + }, + { + name: '售后订单', + path: '/pages/order/aftersale/list', + }, + { + name: '商品收藏', + path: '/pages/user/goods-collect', + }, + { + name: '浏览记录', + path: '/pages/user/goods-log', + }, + { + name: '地址管理', + path: '/pages/user/address/list', + }, + { + name: '用户佣金', + path: '/pages/user/wallet/commission', + }, + { + name: '用户余额', + path: '/pages/user/wallet/money', + }, + { + name: '用户积分', + path: '/pages/user/wallet/score', + }, + ], + }, +] as AppLinkGroup[]; diff --git a/apps/web-ele/src/components/app-link-input/index.vue b/apps/web-ele/src/components/app-link-input/index.vue new file mode 100644 index 000000000..45938d6f2 --- /dev/null +++ b/apps/web-ele/src/components/app-link-input/index.vue @@ -0,0 +1,43 @@ + + diff --git a/apps/web-ele/src/components/diy-editor/components/ComponentContainer.vue b/apps/web-ele/src/components/diy-editor/components/ComponentContainer.vue new file mode 100644 index 000000000..cc7b76a42 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/ComponentContainer.vue @@ -0,0 +1,255 @@ + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/ComponentContainerProperty.vue b/apps/web-ele/src/components/diy-editor/components/ComponentContainerProperty.vue new file mode 100644 index 000000000..becfe404e --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/ComponentContainerProperty.vue @@ -0,0 +1,180 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/ComponentLibrary.vue b/apps/web-ele/src/components/diy-editor/components/ComponentLibrary.vue new file mode 100644 index 000000000..9f89a15fc --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/ComponentLibrary.vue @@ -0,0 +1,219 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/Carousel/config.ts b/apps/web-ele/src/components/diy-editor/components/mobile/Carousel/config.ts new file mode 100644 index 000000000..749d36a32 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/Carousel/config.ts @@ -0,0 +1,61 @@ +import type { + ComponentStyle, + DiyComponent, +} from '#/components/diy-editor/util'; + +/** 轮播图属性 */ +export interface CarouselProperty { + // 类型:默认 | 卡片 + type: 'card' | 'default'; + // 指示器样式:点 | 数字 + indicator: 'dot' | 'number'; + // 是否自动播放 + autoplay: boolean; + // 播放间隔 + interval: number; + // 轮播内容 + items: CarouselItemProperty[]; + // 组件样式 + style: ComponentStyle; +} +// 轮播内容属性 +export interface CarouselItemProperty { + // 类型:图片 | 视频 + type: 'img' | 'video'; + // 图片链接 + imgUrl: string; + // 视频链接 + videoUrl: string; + // 跳转链接 + url: string; +} + +// 定义组件 +export const component = { + id: 'Carousel', + name: '轮播图', + icon: 'system-uicons:carousel', + property: { + type: 'default', + indicator: 'dot', + autoplay: false, + interval: 3, + items: [ + { + type: 'img', + imgUrl: 'https://static.iocoder.cn/mall/banner-01.jpg', + videoUrl: '', + }, + { + type: 'img', + imgUrl: 'https://static.iocoder.cn/mall/banner-02.jpg', + videoUrl: '', + }, + ] as CarouselItemProperty[], + style: { + bgType: 'color', + bgColor: '#fff', + marginBottom: 8, + } as ComponentStyle, + }, +} as DiyComponent; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/Carousel/index.vue b/apps/web-ele/src/components/diy-editor/components/mobile/Carousel/index.vue new file mode 100644 index 000000000..a4fa08f1e --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/Carousel/index.vue @@ -0,0 +1,46 @@ + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/Carousel/property.vue b/apps/web-ele/src/components/diy-editor/components/mobile/Carousel/property.vue new file mode 100644 index 000000000..f2d9b6e59 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/Carousel/property.vue @@ -0,0 +1,112 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/CouponCard/CouponDiscount.tsx b/apps/web-ele/src/components/diy-editor/components/mobile/CouponCard/CouponDiscount.tsx new file mode 100644 index 000000000..bde532e4a --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/CouponCard/CouponDiscount.tsx @@ -0,0 +1,35 @@ +import type { MallCouponTemplateApi } from '#/api/mall/promotion/coupon/couponTemplate'; + +import { defineComponent } from 'vue'; + +import { floatToFixed2 } from '@vben/utils'; + +import { PromotionDiscountTypeEnum } from '#/utils/constants'; + +// 优惠值 +export const CouponDiscount = defineComponent({ + name: 'CouponDiscount', + props: { + coupon: { + type: Object as () => MallCouponTemplateApi.CouponTemplate, + required: true, + }, + }, + setup(props) { + const coupon = props.coupon as MallCouponTemplateApi.CouponTemplate; + // 折扣 + let value = `${coupon.discountPercent / 10}`; + let suffix = ' 折'; + // 满减 + if (coupon.discountType === PromotionDiscountTypeEnum.PRICE.type) { + value = floatToFixed2(coupon.discountPrice); + suffix = ' 元'; + } + return () => ( +
+ {value} + {suffix} +
+ ); + }, +}); diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/CouponCard/CouponDiscountDesc.tsx b/apps/web-ele/src/components/diy-editor/components/mobile/CouponCard/CouponDiscountDesc.tsx new file mode 100644 index 000000000..634cb88c6 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/CouponCard/CouponDiscountDesc.tsx @@ -0,0 +1,35 @@ +import type { MallCouponTemplateApi } from '#/api/mall/promotion/coupon/couponTemplate'; + +import { defineComponent } from 'vue'; + +import { floatToFixed2 } from '@vben/utils'; + +import { PromotionDiscountTypeEnum } from '#/utils/constants'; + +// 优惠描述 +export const CouponDiscountDesc = defineComponent({ + name: 'CouponDiscountDesc', + props: { + coupon: { + type: Object as () => MallCouponTemplateApi.CouponTemplate, + required: true, + }, + }, + setup(props) { + const coupon = props.coupon as MallCouponTemplateApi.CouponTemplate; + // 使用条件 + const useCondition = + coupon.usePrice > 0 ? `满${floatToFixed2(coupon.usePrice)}元,` : ''; + // 优惠描述 + const discountDesc = + coupon.discountType === PromotionDiscountTypeEnum.PRICE.type + ? `减${floatToFixed2(coupon.discountPrice)}元` + : `打${coupon.discountPercent / 10}折`; + return () => ( +
+ {useCondition} + {discountDesc} +
+ ); + }, +}); diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/CouponCard/CouponValidTerm.tsx b/apps/web-ele/src/components/diy-editor/components/mobile/CouponCard/CouponValidTerm.tsx new file mode 100644 index 000000000..c96903f15 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/CouponCard/CouponValidTerm.tsx @@ -0,0 +1,29 @@ +import type { MallCouponTemplateApi } from '#/api/mall/promotion/coupon/couponTemplate'; + +import { defineComponent } from 'vue'; + +import { formatDate } from '@vben/utils'; + +import { CouponTemplateValidityTypeEnum } from '#/utils/constants'; + +// 有效期 +export const CouponValidTerm = defineComponent({ + name: 'CouponValidTerm', + props: { + coupon: { + type: Object as () => MallCouponTemplateApi.CouponTemplate, + required: true, + }, + }, + setup(props) { + const coupon = props.coupon as MallCouponTemplateApi.CouponTemplate; + const text = + coupon.validityType === CouponTemplateValidityTypeEnum.DATE.type + ? `有效期:${formatDate(coupon.validStartTime, 'YYYY-MM-DD')} 至 ${formatDate( + coupon.validEndTime, + 'YYYY-MM-DD', + )}` + : `领取后第 ${coupon.fixedStartTerm} - ${coupon.fixedEndTerm} 天内可用`; + return () =>
{text}
; + }, +}); diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/CouponCard/component.tsx b/apps/web-ele/src/components/diy-editor/components/mobile/CouponCard/component.tsx new file mode 100644 index 000000000..26aca2399 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/CouponCard/component.tsx @@ -0,0 +1,4 @@ +// 导出所有优惠券相关组件 +export { CouponDiscount } from './CouponDiscount'; +export { CouponDiscountDesc } from './CouponDiscountDesc'; +export { CouponValidTerm } from './CouponValidTerm'; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/CouponCard/config.ts b/apps/web-ele/src/components/diy-editor/components/mobile/CouponCard/config.ts new file mode 100644 index 000000000..ddfc1857a --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/CouponCard/config.ts @@ -0,0 +1,50 @@ +import type { + ComponentStyle, + DiyComponent, +} from '#/components/diy-editor/util'; + +/** 商品卡片属性 */ +export interface CouponCardProperty { + // 列数 + columns: number; + // 背景图 + bgImg: string; + // 文字颜色 + textColor: string; + // 按钮样式 + button: { + // 背景颜色 + bgColor: string; + // 颜色 + color: string; + }; + // 间距 + space: number; + // 优惠券编号列表 + couponIds: number[]; + // 组件样式 + style: ComponentStyle; +} + +// 定义组件 +export const component = { + id: 'CouponCard', + name: '优惠券', + icon: 'ep:ticket', + property: { + columns: 1, + bgImg: '', + textColor: '#E9B461', + button: { + color: '#434343', + bgColor: '', + }, + space: 0, + couponIds: [], + style: { + bgType: 'color', + bgColor: '', + marginBottom: 8, + } as ComponentStyle, + }, +} as DiyComponent; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/CouponCard/index.vue b/apps/web-ele/src/components/diy-editor/components/mobile/CouponCard/index.vue new file mode 100644 index 000000000..450d64d01 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/CouponCard/index.vue @@ -0,0 +1,163 @@ + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/CouponCard/property.vue b/apps/web-ele/src/components/diy-editor/components/mobile/CouponCard/property.vue new file mode 100644 index 000000000..3b65e91ae --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/CouponCard/property.vue @@ -0,0 +1,147 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/Divider/config.ts b/apps/web-ele/src/components/diy-editor/components/mobile/Divider/config.ts new file mode 100644 index 000000000..7147ef9b2 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/Divider/config.ts @@ -0,0 +1,29 @@ +import type { DiyComponent } from '#/components/diy-editor/util'; + +/** 分割线属性 */ +export interface DividerProperty { + // 高度 + height: number; + // 线宽 + lineWidth: number; + // 边距类型 + paddingType: 'horizontal' | 'none'; + // 颜色 + lineColor: string; + // 类型 + borderType: 'dashed' | 'dotted' | 'none' | 'solid'; +} + +// 定义组件 +export const component = { + id: 'Divider', + name: '分割线', + icon: 'tdesign:component-divider-vertical', + property: { + height: 30, + lineWidth: 1, + paddingType: 'none', + lineColor: '#dcdfe6', + borderType: 'solid', + }, +} as DiyComponent; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/Divider/index.vue b/apps/web-ele/src/components/diy-editor/components/mobile/Divider/index.vue new file mode 100644 index 000000000..1736db389 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/Divider/index.vue @@ -0,0 +1,29 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/Divider/property.vue b/apps/web-ele/src/components/diy-editor/components/mobile/Divider/property.vue new file mode 100644 index 000000000..84daffae5 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/Divider/property.vue @@ -0,0 +1,93 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/FloatingActionButton/config.ts b/apps/web-ele/src/components/diy-editor/components/mobile/FloatingActionButton/config.ts new file mode 100644 index 000000000..7972bd3bc --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/FloatingActionButton/config.ts @@ -0,0 +1,36 @@ +import type { DiyComponent } from '#/components/diy-editor/util'; + +// 悬浮按钮属性 +export interface FloatingActionButtonProperty { + // 展开方向 + direction: 'horizontal' | 'vertical'; + // 是否显示文字 + showText: boolean; + // 按钮列表 + list: FloatingActionButtonItemProperty[]; +} + +// 悬浮按钮项属性 +export interface FloatingActionButtonItemProperty { + // 图片地址 + imgUrl: string; + // 跳转连接 + url: string; + // 文字 + text: string; + // 文字颜色 + textColor: string; +} + +// 定义组件 +export const component = { + id: 'FloatingActionButton', + name: '悬浮按钮', + icon: 'tabler:float-right', + position: 'fixed', + property: { + direction: 'vertical', + showText: true, + list: [{ textColor: '#fff' }], + }, +} as DiyComponent; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/FloatingActionButton/index.vue b/apps/web-ele/src/components/diy-editor/components/mobile/FloatingActionButton/index.vue new file mode 100644 index 000000000..9eaba6c92 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/FloatingActionButton/index.vue @@ -0,0 +1,86 @@ + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/FloatingActionButton/property.vue b/apps/web-ele/src/components/diy-editor/components/mobile/FloatingActionButton/property.vue new file mode 100644 index 000000000..9808838c4 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/FloatingActionButton/property.vue @@ -0,0 +1,48 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/HotZone/components/HotZoneEditDialog/controller.ts b/apps/web-ele/src/components/diy-editor/components/mobile/HotZone/components/HotZoneEditDialog/controller.ts new file mode 100644 index 000000000..93a264b5e --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/HotZone/components/HotZoneEditDialog/controller.ts @@ -0,0 +1,175 @@ +import type { StyleValue } from 'vue'; + +import type { HotZoneItemProperty } from '#/components/diy-editor/components/mobile/HotZone/config'; + +// 热区的最小宽高 +export const HOT_ZONE_MIN_SIZE = 100; + +// 控制的类型 +export enum CONTROL_TYPE_ENUM { + LEFT, + TOP, + WIDTH, + HEIGHT, +} + +// 定义热区的控制点 +export interface ControlDot { + position: string; + types: CONTROL_TYPE_ENUM[]; + style: StyleValue; +} + +// 热区的8个控制点 +export const CONTROL_DOT_LIST = [ + { + position: '左上角', + types: [ + CONTROL_TYPE_ENUM.LEFT, + CONTROL_TYPE_ENUM.TOP, + CONTROL_TYPE_ENUM.WIDTH, + CONTROL_TYPE_ENUM.HEIGHT, + ], + style: { left: '-5px', top: '-5px', cursor: 'nwse-resize' }, + }, + { + position: '上方中间', + types: [CONTROL_TYPE_ENUM.TOP, CONTROL_TYPE_ENUM.HEIGHT], + style: { + left: '50%', + top: '-5px', + cursor: 'n-resize', + transform: 'translateX(-50%)', + }, + }, + { + position: '右上角', + types: [ + CONTROL_TYPE_ENUM.TOP, + CONTROL_TYPE_ENUM.WIDTH, + CONTROL_TYPE_ENUM.HEIGHT, + ], + style: { right: '-5px', top: '-5px', cursor: 'nesw-resize' }, + }, + { + position: '右侧中间', + types: [CONTROL_TYPE_ENUM.WIDTH], + style: { + right: '-5px', + top: '50%', + cursor: 'e-resize', + transform: 'translateX(-50%)', + }, + }, + { + position: '右下角', + types: [CONTROL_TYPE_ENUM.WIDTH, CONTROL_TYPE_ENUM.HEIGHT], + style: { right: '-5px', bottom: '-5px', cursor: 'nwse-resize' }, + }, + { + position: '下方中间', + types: [CONTROL_TYPE_ENUM.HEIGHT], + style: { + left: '50%', + bottom: '-5px', + cursor: 's-resize', + transform: 'translateX(-50%)', + }, + }, + { + position: '左下角', + types: [ + CONTROL_TYPE_ENUM.LEFT, + CONTROL_TYPE_ENUM.WIDTH, + CONTROL_TYPE_ENUM.HEIGHT, + ], + style: { left: '-5px', bottom: '-5px', cursor: 'nesw-resize' }, + }, + { + position: '左侧中间', + types: [CONTROL_TYPE_ENUM.LEFT, CONTROL_TYPE_ENUM.WIDTH], + style: { + left: '-5px', + top: '50%', + cursor: 'w-resize', + transform: 'translateX(-50%)', + }, + }, +] as ControlDot[]; + +// region 热区的缩放 +// 热区的缩放比例 +export const HOT_ZONE_SCALE_RATE = 2; +// 缩小:缩回适合手机屏幕的大小 +export const zoomOut = (list?: HotZoneItemProperty[]) => { + return ( + list?.map((hotZone) => ({ + ...hotZone, + left: (hotZone.left /= HOT_ZONE_SCALE_RATE), + top: (hotZone.top /= HOT_ZONE_SCALE_RATE), + width: (hotZone.width /= HOT_ZONE_SCALE_RATE), + height: (hotZone.height /= HOT_ZONE_SCALE_RATE), + })) || [] + ); +}; +// 放大:作用是为了方便在电脑屏幕上编辑 +export const zoomIn = (list?: HotZoneItemProperty[]) => { + return ( + list?.map((hotZone) => ({ + ...hotZone, + left: (hotZone.left *= HOT_ZONE_SCALE_RATE), + top: (hotZone.top *= HOT_ZONE_SCALE_RATE), + width: (hotZone.width *= HOT_ZONE_SCALE_RATE), + height: (hotZone.height *= HOT_ZONE_SCALE_RATE), + })) || [] + ); +}; +// endregion + +/** + * 封装热区拖拽 + * + * 注:为什么不使用vueuse的useDraggable。在本场景下,其使用方式比较复杂 + * @param hotZone 热区 + * @param downEvent 鼠标按下事件 + * @param callback 回调函数 + */ +export const useDraggable = ( + hotZone: HotZoneItemProperty, + downEvent: MouseEvent, + callback: ( + left: number, + top: number, + width: number, + height: number, + moveWidth: number, + moveHeight: number, + ) => void, +) => { + // 阻止事件冒泡 + downEvent.stopPropagation(); + + // 移动前的鼠标坐标 + const { clientX: startX, clientY: startY } = downEvent; + // 移动前的热区坐标、大小 + const { left, top, width, height } = hotZone; + + // 监听鼠标移动 + const handleMouseMove = (e: MouseEvent) => { + // 移动宽度 + const moveWidth = e.clientX - startX; + // 移动高度 + const moveHeight = e.clientY - startY; + // 移动回调 + callback(left, top, width, height, moveWidth, moveHeight); + }; + + // 松开鼠标后,结束拖拽 + const handleMouseUp = () => { + document.removeEventListener('mousemove', handleMouseMove); + document.removeEventListener('mouseup', handleMouseUp); + }; + + document.addEventListener('mousemove', handleMouseMove); + document.addEventListener('mouseup', handleMouseUp); +}; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/HotZone/components/HotZoneEditDialog/index.vue b/apps/web-ele/src/components/diy-editor/components/mobile/HotZone/components/HotZoneEditDialog/index.vue new file mode 100644 index 000000000..7cd1b5fc8 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/HotZone/components/HotZoneEditDialog/index.vue @@ -0,0 +1,280 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/HotZone/config.ts b/apps/web-ele/src/components/diy-editor/components/mobile/HotZone/config.ts new file mode 100644 index 000000000..71e39d9cd --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/HotZone/config.ts @@ -0,0 +1,46 @@ +import type { + ComponentStyle, + DiyComponent, +} from '#/components/diy-editor/util'; + +/** 热区属性 */ +export interface HotZoneProperty { + // 图片地址 + imgUrl: string; + // 导航菜单列表 + list: HotZoneItemProperty[]; + // 组件样式 + style: ComponentStyle; +} + +/** 热区项目属性 */ +export interface HotZoneItemProperty { + // 链接的名称 + name: string; + // 链接 + url: string; + // 宽 + width: number; + // 高 + height: number; + // 上 + top: number; + // 左 + left: number; +} + +// 定义组件 +export const component = { + id: 'HotZone', + name: '热区', + icon: 'tabler:hand-click', + property: { + imgUrl: '', + list: [] as HotZoneItemProperty[], + style: { + bgType: 'color', + bgColor: '#fff', + marginBottom: 8, + } as ComponentStyle, + }, +} as DiyComponent; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/HotZone/index.vue b/apps/web-ele/src/components/diy-editor/components/mobile/HotZone/index.vue new file mode 100644 index 000000000..abaf9f3c2 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/HotZone/index.vue @@ -0,0 +1,45 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/HotZone/property.vue b/apps/web-ele/src/components/diy-editor/components/mobile/HotZone/property.vue new file mode 100644 index 000000000..9937f8657 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/HotZone/property.vue @@ -0,0 +1,81 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/ImageBar/config.ts b/apps/web-ele/src/components/diy-editor/components/mobile/ImageBar/config.ts new file mode 100644 index 000000000..53a87403c --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/ImageBar/config.ts @@ -0,0 +1,30 @@ +import type { + ComponentStyle, + DiyComponent, +} from '#/components/diy-editor/util'; + +/** 图片展示属性 */ +export interface ImageBarProperty { + // 图片链接 + imgUrl: string; + // 跳转链接 + url: string; + // 组件样式 + style: ComponentStyle; +} + +// 定义组件 +export const component = { + id: 'ImageBar', + name: '图片展示', + icon: 'ep:picture', + property: { + imgUrl: '', + url: '', + style: { + bgType: 'color', + bgColor: '#fff', + marginBottom: 8, + } as ComponentStyle, + }, +} as DiyComponent; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/ImageBar/index.vue b/apps/web-ele/src/components/diy-editor/components/mobile/ImageBar/index.vue new file mode 100644 index 000000000..cd958df87 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/ImageBar/index.vue @@ -0,0 +1,27 @@ + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/ImageBar/property.vue b/apps/web-ele/src/components/diy-editor/components/mobile/ImageBar/property.vue new file mode 100644 index 000000000..9b330a324 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/ImageBar/property.vue @@ -0,0 +1,35 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/MagicCube/config.ts b/apps/web-ele/src/components/diy-editor/components/mobile/MagicCube/config.ts new file mode 100644 index 000000000..278751025 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/MagicCube/config.ts @@ -0,0 +1,52 @@ +import type { + ComponentStyle, + DiyComponent, +} from '#/components/diy-editor/util'; + +/** 广告魔方属性 */ +export interface MagicCubeProperty { + // 上圆角 + borderRadiusTop: number; + // 下圆角 + borderRadiusBottom: number; + // 间隔 + space: number; + // 导航菜单列表 + list: MagicCubeItemProperty[]; + // 组件样式 + style: ComponentStyle; +} + +/** 广告魔方项目属性 */ +export interface MagicCubeItemProperty { + // 图标链接 + imgUrl: string; + // 链接 + url: string; + // 宽 + width: number; + // 高 + height: number; + // 上 + top: number; + // 左 + left: number; +} + +// 定义组件 +export const component = { + id: 'MagicCube', + name: '广告魔方', + icon: 'bi:columns', + property: { + borderRadiusTop: 0, + borderRadiusBottom: 0, + space: 0, + list: [], + style: { + bgType: 'color', + bgColor: '#fff', + marginBottom: 8, + } as ComponentStyle, + }, +} as DiyComponent; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/MagicCube/index.vue b/apps/web-ele/src/components/diy-editor/components/mobile/MagicCube/index.vue new file mode 100644 index 000000000..7127625f9 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/MagicCube/index.vue @@ -0,0 +1,80 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/MagicCube/property.vue b/apps/web-ele/src/components/diy-editor/components/mobile/MagicCube/property.vue new file mode 100644 index 000000000..e2b12c69d --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/MagicCube/property.vue @@ -0,0 +1,79 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/MenuGrid/config.ts b/apps/web-ele/src/components/diy-editor/components/mobile/MenuGrid/config.ts new file mode 100644 index 000000000..4ae675a49 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/MenuGrid/config.ts @@ -0,0 +1,83 @@ +import type { + ComponentStyle, + DiyComponent, +} from '#/components/diy-editor/util'; + +import { cloneDeep } from '@vben/utils'; + +/** 宫格导航属性 */ +export interface MenuGridProperty { + // 列数 + column: number; + // 导航菜单列表 + list: MenuGridItemProperty[]; + // 组件样式 + style: ComponentStyle; +} + +/** 宫格导航项目属性 */ +export interface MenuGridItemProperty { + // 图标链接 + iconUrl: string; + // 标题 + title: string; + // 标题颜色 + titleColor: string; + // 副标题 + subtitle: string; + // 副标题颜色 + subtitleColor: string; + // 链接 + url: string; + // 角标 + badge: { + // 角标背景颜色 + bgColor: string; + // 是否显示 + show: boolean; + // 角标文字 + text: string; + // 角标文字颜色 + textColor: string; + }; +} + +export const EMPTY_MENU_GRID_ITEM_PROPERTY = { + title: '标题', + titleColor: '#333', + subtitle: '副标题', + subtitleColor: '#bbb', + badge: { + show: false, + textColor: '#fff', + bgColor: '#FF6000', + }, +} as MenuGridItemProperty; + +// 定义组件 +export const component = { + id: 'MenuGrid', + name: '宫格导航', + icon: 'bi:grid-3x3-gap', + property: { + column: 3, + list: [cloneDeep(EMPTY_MENU_GRID_ITEM_PROPERTY)], + style: { + bgType: 'color', + bgColor: '#fff', + marginBottom: 8, + marginLeft: 8, + marginRight: 8, + padding: 8, + paddingTop: 8, + paddingRight: 8, + paddingBottom: 8, + paddingLeft: 8, + borderRadius: 8, + borderTopLeftRadius: 8, + borderTopRightRadius: 8, + borderBottomRightRadius: 8, + borderBottomLeftRadius: 8, + } as ComponentStyle, + }, +} as DiyComponent; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/MenuGrid/index.vue b/apps/web-ele/src/components/diy-editor/components/mobile/MenuGrid/index.vue new file mode 100644 index 000000000..a788ca722 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/MenuGrid/index.vue @@ -0,0 +1,45 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/MenuGrid/property.vue b/apps/web-ele/src/components/diy-editor/components/mobile/MenuGrid/property.vue new file mode 100644 index 000000000..c74c6b14a --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/MenuGrid/property.vue @@ -0,0 +1,74 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/MenuList/config.ts b/apps/web-ele/src/components/diy-editor/components/mobile/MenuList/config.ts new file mode 100644 index 000000000..4be256749 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/MenuList/config.ts @@ -0,0 +1,52 @@ +import type { + ComponentStyle, + DiyComponent, +} from '#/components/diy-editor/util'; + +import { cloneDeep } from '@vben/utils'; + +/** 列表导航属性 */ +export interface MenuListProperty { + // 导航菜单列表 + list: MenuListItemProperty[]; + // 组件样式 + style: ComponentStyle; +} + +/** 列表导航项目属性 */ +export interface MenuListItemProperty { + // 图标链接 + iconUrl: string; + // 标题 + title: string; + // 标题颜色 + titleColor: string; + // 副标题 + subtitle: string; + // 副标题颜色 + subtitleColor: string; + // 链接 + url: string; +} + +export const EMPTY_MENU_LIST_ITEM_PROPERTY = { + title: '标题', + titleColor: '#333', + subtitle: '副标题', + subtitleColor: '#bbb', +}; + +// 定义组件 +export const component = { + id: 'MenuList', + name: '列表导航', + icon: 'fa-solid:list', + property: { + list: [cloneDeep(EMPTY_MENU_LIST_ITEM_PROPERTY)], + style: { + bgType: 'color', + bgColor: '#fff', + marginBottom: 8, + } as ComponentStyle, + }, +} as DiyComponent; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/MenuList/index.vue b/apps/web-ele/src/components/diy-editor/components/mobile/MenuList/index.vue new file mode 100644 index 000000000..faec56f51 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/MenuList/index.vue @@ -0,0 +1,40 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/MenuList/property.vue b/apps/web-ele/src/components/diy-editor/components/mobile/MenuList/property.vue new file mode 100644 index 000000000..56bb6ae53 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/MenuList/property.vue @@ -0,0 +1,54 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/MenuSwiper/config.ts b/apps/web-ele/src/components/diy-editor/components/mobile/MenuSwiper/config.ts new file mode 100644 index 000000000..535287d40 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/MenuSwiper/config.ts @@ -0,0 +1,70 @@ +import type { + ComponentStyle, + DiyComponent, +} from '#/components/diy-editor/util'; + +import { cloneDeep } from '@vben/utils'; + +/** 菜单导航属性 */ +export interface MenuSwiperProperty { + // 布局: 图标+文字 | 图标 + layout: 'icon' | 'iconText'; + // 行数 + row: number; + // 列数 + column: number; + // 导航菜单列表 + list: MenuSwiperItemProperty[]; + // 组件样式 + style: ComponentStyle; +} +/** 菜单导航项目属性 */ +export interface MenuSwiperItemProperty { + // 图标链接 + iconUrl: string; + // 标题 + title: string; + // 标题颜色 + titleColor: string; + // 链接 + url: string; + // 角标 + badge: { + // 角标背景颜色 + bgColor: string; + // 是否显示 + show: boolean; + // 角标文字 + text: string; + // 角标文字颜色 + textColor: string; + }; +} + +export const EMPTY_MENU_SWIPER_ITEM_PROPERTY = { + title: '标题', + titleColor: '#333', + badge: { + show: false, + textColor: '#fff', + bgColor: '#FF6000', + }, +} as MenuSwiperItemProperty; + +// 定义组件 +export const component = { + id: 'MenuSwiper', + name: '菜单导航', + icon: 'bi:grid-3x2-gap', + property: { + layout: 'iconText', + row: 1, + column: 3, + list: [cloneDeep(EMPTY_MENU_SWIPER_ITEM_PROPERTY)], + style: { + bgType: 'color', + bgColor: '#fff', + marginBottom: 8, + } as ComponentStyle, + }, +} as DiyComponent; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/MenuSwiper/index.vue b/apps/web-ele/src/components/diy-editor/components/mobile/MenuSwiper/index.vue new file mode 100644 index 000000000..0f64d0457 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/MenuSwiper/index.vue @@ -0,0 +1,135 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/MenuSwiper/property.vue b/apps/web-ele/src/components/diy-editor/components/mobile/MenuSwiper/property.vue new file mode 100644 index 000000000..e6cfcf455 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/MenuSwiper/property.vue @@ -0,0 +1,83 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/NavigationBar/components/CellProperty.vue b/apps/web-ele/src/components/diy-editor/components/mobile/NavigationBar/components/CellProperty.vue new file mode 100644 index 000000000..61ba60cba --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/NavigationBar/components/CellProperty.vue @@ -0,0 +1,115 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/NavigationBar/config.ts b/apps/web-ele/src/components/diy-editor/components/mobile/NavigationBar/config.ts new file mode 100644 index 000000000..38325d5a9 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/NavigationBar/config.ts @@ -0,0 +1,82 @@ +import type { DiyComponent } from '#/components/diy-editor/util'; + +/** 顶部导航栏属性 */ +export interface NavigationBarProperty { + // 背景类型 + bgType: 'color' | 'img'; + // 背景颜色 + bgColor: string; + // 图片链接 + bgImg: string; + // 样式类型:默认 | 沉浸式 + styleType: 'inner' | 'normal'; + // 常驻显示 + alwaysShow: boolean; + // 小程序单元格列表 + mpCells: NavigationBarCellProperty[]; + // 其它平台单元格列表 + otherCells: NavigationBarCellProperty[]; + // 本地变量 + _local: { + // 预览顶部导航(小程序) + previewMp: boolean; + // 预览顶部导航(非小程序) + previewOther: boolean; + }; +} + +/** 顶部导航栏 - 单元格 属性 */ +export interface NavigationBarCellProperty { + // 类型:文字 | 图片 | 搜索框 + type: 'image' | 'search' | 'text'; + // 宽度 + width: number; + // 高度 + height: number; + // 顶部位置 + top: number; + // 左侧位置 + left: number; + // 文字内容 + text: string; + // 文字颜色 + textColor: string; + // 图片地址 + imgUrl: string; + // 图片链接 + url: string; + // 搜索框:提示文字 + placeholder: string; + // 搜索框:边框圆角半径 + borderRadius: number; +} + +// 定义组件 +export const component = { + id: 'NavigationBar', + name: '顶部导航栏', + icon: 'tabler:layout-navbar', + property: { + bgType: 'color', + bgColor: '#fff', + bgImg: '', + styleType: 'normal', + alwaysShow: true, + mpCells: [ + { + type: 'text', + textColor: '#111111', + }, + ], + otherCells: [ + { + type: 'text', + textColor: '#111111', + }, + ], + _local: { + previewMp: true, + previewOther: false, + }, + }, +} as DiyComponent; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/NavigationBar/index.vue b/apps/web-ele/src/components/diy-editor/components/mobile/NavigationBar/index.vue new file mode 100644 index 000000000..456dcd2ee --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/NavigationBar/index.vue @@ -0,0 +1,111 @@ + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/NavigationBar/property.vue b/apps/web-ele/src/components/diy-editor/components/mobile/NavigationBar/property.vue new file mode 100644 index 000000000..69eb2157e --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/NavigationBar/property.vue @@ -0,0 +1,116 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/NoticeBar/config.ts b/apps/web-ele/src/components/diy-editor/components/mobile/NoticeBar/config.ts new file mode 100644 index 000000000..31dc13794 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/NoticeBar/config.ts @@ -0,0 +1,49 @@ +import type { + ComponentStyle, + DiyComponent, +} from '#/components/diy-editor/util'; + +/** 公告栏属性 */ +export interface NoticeBarProperty { + // 图标地址 + iconUrl: string; + // 公告内容列表 + contents: NoticeContentProperty[]; + // 背景颜色 + backgroundColor: string; + // 文字颜色 + textColor: string; + // 组件样式 + style: ComponentStyle; +} + +/** 内容属性 */ +export interface NoticeContentProperty { + // 内容文字 + text: string; + // 链接地址 + url: string; +} + +// 定义组件 +export const component = { + id: 'NoticeBar', + name: '公告栏', + icon: 'ep:bell', + property: { + iconUrl: 'http://mall.yudao.iocoder.cn/static/images/xinjian.png', + contents: [ + { + text: '', + url: '', + }, + ], + backgroundColor: '#fff', + textColor: '#333', + style: { + bgType: 'color', + bgColor: '#fff', + marginBottom: 8, + } as ComponentStyle, + }, +} as DiyComponent; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/NoticeBar/index.vue b/apps/web-ele/src/components/diy-editor/components/mobile/NoticeBar/index.vue new file mode 100644 index 000000000..a7258056c --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/NoticeBar/index.vue @@ -0,0 +1,34 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/NoticeBar/property.vue b/apps/web-ele/src/components/diy-editor/components/mobile/NoticeBar/property.vue new file mode 100644 index 000000000..543f62e5f --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/NoticeBar/property.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/PageConfig/config.ts b/apps/web-ele/src/components/diy-editor/components/mobile/PageConfig/config.ts new file mode 100644 index 000000000..29855bb73 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/PageConfig/config.ts @@ -0,0 +1,23 @@ +import type { DiyComponent } from '#/components/diy-editor/util'; + +/** 页面设置属性 */ +export interface PageConfigProperty { + // 页面描述 + description: string; + // 页面背景颜色 + backgroundColor: string; + // 页面背景图片 + backgroundImage: string; +} + +// 定义页面组件 +export const component = { + id: 'PageConfig', + name: '页面设置', + icon: 'ep:document', + property: { + description: '', + backgroundColor: '#f5f5f5', + backgroundImage: '', + }, +} as DiyComponent; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/PageConfig/property.vue b/apps/web-ele/src/components/diy-editor/components/mobile/PageConfig/property.vue new file mode 100644 index 000000000..ad877cf5a --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/PageConfig/property.vue @@ -0,0 +1,38 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/Popover/config.ts b/apps/web-ele/src/components/diy-editor/components/mobile/Popover/config.ts new file mode 100644 index 000000000..b842d19f5 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/Popover/config.ts @@ -0,0 +1,26 @@ +import type { DiyComponent } from '#/components/diy-editor/util'; + +/** 弹窗广告属性 */ +export interface PopoverProperty { + list: PopoverItemProperty[]; +} + +export interface PopoverItemProperty { + // 图片地址 + imgUrl: string; + // 跳转连接 + url: string; + // 显示类型:仅显示一次、每次启动都会显示 + showType: 'always' | 'once'; +} + +// 定义组件 +export const component = { + id: 'Popover', + name: '弹窗广告', + icon: 'carbon:popup', + position: 'fixed', + property: { + list: [{ showType: 'once' }], + }, +} as DiyComponent; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/Popover/index.vue b/apps/web-ele/src/components/diy-editor/components/mobile/Popover/index.vue new file mode 100644 index 000000000..8bcd7eeae --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/Popover/index.vue @@ -0,0 +1,40 @@ + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/Popover/property.vue b/apps/web-ele/src/components/diy-editor/components/mobile/Popover/property.vue new file mode 100644 index 000000000..a8bc949f7 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/Popover/property.vue @@ -0,0 +1,42 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/ProductCard/config.ts b/apps/web-ele/src/components/diy-editor/components/mobile/ProductCard/config.ts new file mode 100644 index 000000000..ea3c9e4da --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/ProductCard/config.ts @@ -0,0 +1,100 @@ +import type { + ComponentStyle, + DiyComponent, +} from '#/components/diy-editor/util'; + +/** 商品卡片属性 */ +export interface ProductCardProperty { + // 布局类型:单列大图 | 单列小图 | 双列 + layoutType: 'oneColBigImg' | 'oneColSmallImg' | 'twoCol'; + // 商品字段 + fields: { + // 商品简介 + introduction: ProductCardFieldProperty; + // 商品市场价 + marketPrice: ProductCardFieldProperty; + // 商品名称 + name: ProductCardFieldProperty; + // 商品价格 + price: ProductCardFieldProperty; + // 商品销量 + salesCount: ProductCardFieldProperty; + // 商品库存 + stock: ProductCardFieldProperty; + }; + // 角标 + badge: { + // 角标图片 + imgUrl: string; + // 是否显示 + show: boolean; + }; + // 按钮 + btnBuy: { + // 文字按钮:背景渐变起始颜色 + bgBeginColor: string; + // 文字按钮:背景渐变结束颜色 + bgEndColor: string; + // 图片按钮:图片地址 + imgUrl: string; + // 文字 + text: string; + // 类型:文字 | 图片 + type: 'img' | 'text'; + }; + // 上圆角 + borderRadiusTop: number; + // 下圆角 + borderRadiusBottom: number; + // 间距 + space: number; + // 商品编号列表 + spuIds: number[]; + // 组件样式 + style: ComponentStyle; +} +// 商品字段 +export interface ProductCardFieldProperty { + // 是否显示 + show: boolean; + // 颜色 + color: string; +} + +// 定义组件 +export const component = { + id: 'ProductCard', + name: '商品卡片', + icon: 'fluent:text-column-two-left-24-filled', + property: { + layoutType: 'oneColBigImg', + fields: { + name: { show: true, color: '#000' }, + introduction: { show: true, color: '#999' }, + price: { show: true, color: '#ff3000' }, + marketPrice: { show: true, color: '#c4c4c4' }, + salesCount: { show: true, color: '#c4c4c4' }, + stock: { show: false, color: '#c4c4c4' }, + }, + badge: { show: false, imgUrl: '' }, + btnBuy: { + type: 'text', + text: '立即购买', + // todo: @owen 根据主题色配置 + bgBeginColor: '#FF6000', + bgEndColor: '#FE832A', + imgUrl: '', + }, + borderRadiusTop: 6, + borderRadiusBottom: 6, + space: 8, + spuIds: [], + style: { + bgType: 'color', + bgColor: '', + marginLeft: 8, + marginRight: 8, + marginBottom: 8, + } as ComponentStyle, + }, +} as DiyComponent; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/ProductCard/index.vue b/apps/web-ele/src/components/diy-editor/components/mobile/ProductCard/index.vue new file mode 100644 index 000000000..79b9b36ae --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/ProductCard/index.vue @@ -0,0 +1,188 @@ + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/ProductCard/property.vue b/apps/web-ele/src/components/diy-editor/components/mobile/ProductCard/property.vue new file mode 100644 index 000000000..3b71f5243 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/ProductCard/property.vue @@ -0,0 +1,159 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/ProductList/config.ts b/apps/web-ele/src/components/diy-editor/components/mobile/ProductList/config.ts new file mode 100644 index 000000000..0f68a515f --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/ProductList/config.ts @@ -0,0 +1,67 @@ +import type { + ComponentStyle, + DiyComponent, +} from '#/components/diy-editor/util'; + +/** 商品栏属性 */ +export interface ProductListProperty { + // 布局类型:双列 | 三列 | 水平滑动 + layoutType: 'horizSwiper' | 'threeCol' | 'twoCol'; + // 商品字段 + fields: { + // 商品名称 + name: ProductListFieldProperty; + // 商品价格 + price: ProductListFieldProperty; + }; + // 角标 + badge: { + // 角标图片 + imgUrl: string; + // 是否显示 + show: boolean; + }; + // 上圆角 + borderRadiusTop: number; + // 下圆角 + borderRadiusBottom: number; + // 间距 + space: number; + // 商品编号列表 + spuIds: number[]; + // 组件样式 + style: ComponentStyle; +} +// 商品字段 +export interface ProductListFieldProperty { + // 是否显示 + show: boolean; + // 颜色 + color: string; +} + +// 定义组件 +export const component = { + id: 'ProductList', + name: '商品栏', + icon: 'fluent:text-column-two-24-filled', + property: { + layoutType: 'twoCol', + fields: { + name: { show: true, color: '#000' }, + price: { show: true, color: '#ff3000' }, + }, + badge: { show: false, imgUrl: '' }, + borderRadiusTop: 8, + borderRadiusBottom: 8, + space: 8, + spuIds: [], + style: { + bgType: 'color', + bgColor: '', + marginLeft: 8, + marginRight: 8, + marginBottom: 8, + } as ComponentStyle, + }, +} as DiyComponent; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/ProductList/index.vue b/apps/web-ele/src/components/diy-editor/components/mobile/ProductList/index.vue new file mode 100644 index 000000000..9093bcbc5 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/ProductList/index.vue @@ -0,0 +1,148 @@ + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/ProductList/property.vue b/apps/web-ele/src/components/diy-editor/components/mobile/ProductList/property.vue new file mode 100644 index 000000000..4db98a481 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/ProductList/property.vue @@ -0,0 +1,105 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/PromotionArticle/config.ts b/apps/web-ele/src/components/diy-editor/components/mobile/PromotionArticle/config.ts new file mode 100644 index 000000000..9ad0304bc --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/PromotionArticle/config.ts @@ -0,0 +1,28 @@ +import type { + ComponentStyle, + DiyComponent, +} from '#/components/diy-editor/util'; + +/** 营销文章属性 */ +export interface PromotionArticleProperty { + // 文章编号 + id: number; + // 组件样式 + style: ComponentStyle; +} + +// 定义组件 +export const component = { + id: 'PromotionArticle', + name: '营销文章', + icon: 'ph:article-medium', + property: { + style: { + bgType: 'color', + bgColor: '', + marginLeft: 8, + marginRight: 8, + marginBottom: 8, + } as ComponentStyle, + }, +} as DiyComponent; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/PromotionArticle/index.vue b/apps/web-ele/src/components/diy-editor/components/mobile/PromotionArticle/index.vue new file mode 100644 index 000000000..412bd44a3 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/PromotionArticle/index.vue @@ -0,0 +1,33 @@ + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/PromotionArticle/property.vue b/apps/web-ele/src/components/diy-editor/components/mobile/PromotionArticle/property.vue new file mode 100644 index 000000000..b080e69ac --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/PromotionArticle/property.vue @@ -0,0 +1,66 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/PromotionCombination/config.ts b/apps/web-ele/src/components/diy-editor/components/mobile/PromotionCombination/config.ts new file mode 100644 index 000000000..fba3a4a85 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/PromotionCombination/config.ts @@ -0,0 +1,99 @@ +import type { + ComponentStyle, + DiyComponent, +} from '#/components/diy-editor/util'; + +/** 拼团属性 */ +export interface PromotionCombinationProperty { + // 布局类型:单列 | 三列 + layoutType: 'oneColBigImg' | 'oneColSmallImg' | 'twoCol'; + // 商品字段 + fields: { + // 商品简介 + introduction: PromotionCombinationFieldProperty; + // 市场价 + marketPrice: PromotionCombinationFieldProperty; + // 商品名称 + name: PromotionCombinationFieldProperty; + // 商品价格 + price: PromotionCombinationFieldProperty; + // 商品销量 + salesCount: PromotionCombinationFieldProperty; + // 商品库存 + stock: PromotionCombinationFieldProperty; + }; + // 角标 + badge: { + // 角标图片 + imgUrl: string; + // 是否显示 + show: boolean; + }; + // 按钮 + btnBuy: { + // 文字按钮:背景渐变起始颜色 + bgBeginColor: string; + // 文字按钮:背景渐变结束颜色 + bgEndColor: string; + // 图片按钮:图片地址 + imgUrl: string; + // 文字 + text: string; + // 类型:文字 | 图片 + type: 'img' | 'text'; + }; + // 上圆角 + borderRadiusTop: number; + // 下圆角 + borderRadiusBottom: number; + // 间距 + space: number; + // 拼团活动编号 + activityIds: number[]; + // 组件样式 + style: ComponentStyle; +} + +// 商品字段 +export interface PromotionCombinationFieldProperty { + // 是否显示 + show: boolean; + // 颜色 + color: string; +} + +// 定义组件 +export const component = { + id: 'PromotionCombination', + name: '拼团', + icon: 'mdi:account-group', + property: { + layoutType: 'oneColBigImg', + fields: { + name: { show: true, color: '#000' }, + introduction: { show: true, color: '#999' }, + price: { show: true, color: '#ff3000' }, + marketPrice: { show: true, color: '#c4c4c4' }, + salesCount: { show: true, color: '#c4c4c4' }, + stock: { show: false, color: '#c4c4c4' }, + }, + badge: { show: false, imgUrl: '' }, + btnBuy: { + type: 'text', + text: '去拼团', + bgBeginColor: '#FF6000', + bgEndColor: '#FE832A', + imgUrl: '', + }, + borderRadiusTop: 8, + borderRadiusBottom: 8, + space: 8, + style: { + bgType: 'color', + bgColor: '', + marginLeft: 8, + marginRight: 8, + marginBottom: 8, + } as ComponentStyle, + }, +} as DiyComponent; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/PromotionCombination/index.vue b/apps/web-ele/src/components/diy-editor/components/mobile/PromotionCombination/index.vue new file mode 100644 index 000000000..553a4f486 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/PromotionCombination/index.vue @@ -0,0 +1,231 @@ + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/PromotionCombination/property.vue b/apps/web-ele/src/components/diy-editor/components/mobile/PromotionCombination/property.vue new file mode 100644 index 000000000..171ee3ec4 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/PromotionCombination/property.vue @@ -0,0 +1,180 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/PromotionPoint/config.ts b/apps/web-ele/src/components/diy-editor/components/mobile/PromotionPoint/config.ts new file mode 100644 index 000000000..4484f3125 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/PromotionPoint/config.ts @@ -0,0 +1,99 @@ +import type { + ComponentStyle, + DiyComponent, +} from '#/components/diy-editor/util'; + +/** 积分商城属性 */ +export interface PromotionPointProperty { + // 布局类型:单列 | 三列 + layoutType: 'oneColBigImg' | 'oneColSmallImg' | 'twoCol'; + // 商品字段 + fields: { + // 商品简介 + introduction: PromotionPointFieldProperty; + // 市场价 + marketPrice: PromotionPointFieldProperty; + // 商品名称 + name: PromotionPointFieldProperty; + // 商品价格 + price: PromotionPointFieldProperty; + // 商品销量 + salesCount: PromotionPointFieldProperty; + // 商品库存 + stock: PromotionPointFieldProperty; + }; + // 角标 + badge: { + // 角标图片 + imgUrl: string; + // 是否显示 + show: boolean; + }; + // 按钮 + btnBuy: { + // 文字按钮:背景渐变起始颜色 + bgBeginColor: string; + // 文字按钮:背景渐变结束颜色 + bgEndColor: string; + // 图片按钮:图片地址 + imgUrl: string; + // 文字 + text: string; + // 类型:文字 | 图片 + type: 'img' | 'text'; + }; + // 上圆角 + borderRadiusTop: number; + // 下圆角 + borderRadiusBottom: number; + // 间距 + space: number; + // 秒杀活动编号 + activityIds: number[]; + // 组件样式 + style: ComponentStyle; +} + +// 商品字段 +export interface PromotionPointFieldProperty { + // 是否显示 + show: boolean; + // 颜色 + color: string; +} + +// 定义组件 +export const component = { + id: 'PromotionPoint', + name: '积分商城', + icon: 'ep:present', + property: { + layoutType: 'oneColBigImg', + fields: { + name: { show: true, color: '#000' }, + introduction: { show: true, color: '#999' }, + price: { show: true, color: '#ff3000' }, + marketPrice: { show: true, color: '#c4c4c4' }, + salesCount: { show: true, color: '#c4c4c4' }, + stock: { show: false, color: '#c4c4c4' }, + }, + badge: { show: false, imgUrl: '' }, + btnBuy: { + type: 'text', + text: '立即兑换', + bgBeginColor: '#FF6000', + bgEndColor: '#FE832A', + imgUrl: '', + }, + borderRadiusTop: 8, + borderRadiusBottom: 8, + space: 8, + style: { + bgType: 'color', + bgColor: '', + marginLeft: 8, + marginRight: 8, + marginBottom: 8, + } as ComponentStyle, + }, +} as DiyComponent; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/PromotionPoint/index.vue b/apps/web-ele/src/components/diy-editor/components/mobile/PromotionPoint/index.vue new file mode 100644 index 000000000..32da8e69a --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/PromotionPoint/index.vue @@ -0,0 +1,232 @@ + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/PromotionPoint/property.vue b/apps/web-ele/src/components/diy-editor/components/mobile/PromotionPoint/property.vue new file mode 100644 index 000000000..72f65a204 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/PromotionPoint/property.vue @@ -0,0 +1,164 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/PromotionSeckill/config.ts b/apps/web-ele/src/components/diy-editor/components/mobile/PromotionSeckill/config.ts new file mode 100644 index 000000000..fcba6c7e0 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/PromotionSeckill/config.ts @@ -0,0 +1,99 @@ +import type { + ComponentStyle, + DiyComponent, +} from '#/components/diy-editor/util'; + +/** 秒杀属性 */ +export interface PromotionSeckillProperty { + // 布局类型:单列 | 三列 + layoutType: 'oneColBigImg' | 'oneColSmallImg' | 'twoCol'; + // 商品字段 + fields: { + // 商品简介 + introduction: PromotionSeckillFieldProperty; + // 市场价 + marketPrice: PromotionSeckillFieldProperty; + // 商品名称 + name: PromotionSeckillFieldProperty; + // 商品价格 + price: PromotionSeckillFieldProperty; + // 商品销量 + salesCount: PromotionSeckillFieldProperty; + // 商品库存 + stock: PromotionSeckillFieldProperty; + }; + // 角标 + badge: { + // 角标图片 + imgUrl: string; + // 是否显示 + show: boolean; + }; + // 按钮 + btnBuy: { + // 文字按钮:背景渐变起始颜色 + bgBeginColor: string; + // 文字按钮:背景渐变结束颜色 + bgEndColor: string; + // 图片按钮:图片地址 + imgUrl: string; + // 文字 + text: string; + // 类型:文字 | 图片 + type: 'img' | 'text'; + }; + // 上圆角 + borderRadiusTop: number; + // 下圆角 + borderRadiusBottom: number; + // 间距 + space: number; + // 秒杀活动编号 + activityIds: number[]; + // 组件样式 + style: ComponentStyle; +} + +// 商品字段 +export interface PromotionSeckillFieldProperty { + // 是否显示 + show: boolean; + // 颜色 + color: string; +} + +// 定义组件 +export const component = { + id: 'PromotionSeckill', + name: '秒杀', + icon: 'mdi:calendar-time', + property: { + layoutType: 'oneColBigImg', + fields: { + name: { show: true, color: '#000' }, + introduction: { show: true, color: '#999' }, + price: { show: true, color: '#ff3000' }, + marketPrice: { show: true, color: '#c4c4c4' }, + salesCount: { show: true, color: '#c4c4c4' }, + stock: { show: false, color: '#c4c4c4' }, + }, + badge: { show: false, imgUrl: '' }, + btnBuy: { + type: 'text', + text: '立即秒杀', + bgBeginColor: '#FF6000', + bgEndColor: '#FE832A', + imgUrl: '', + }, + borderRadiusTop: 8, + borderRadiusBottom: 8, + space: 8, + style: { + bgType: 'color', + bgColor: '', + marginLeft: 8, + marginRight: 8, + marginBottom: 8, + } as ComponentStyle, + }, +} as DiyComponent; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/PromotionSeckill/index.vue b/apps/web-ele/src/components/diy-editor/components/mobile/PromotionSeckill/index.vue new file mode 100644 index 000000000..5662f073c --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/PromotionSeckill/index.vue @@ -0,0 +1,227 @@ + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/PromotionSeckill/property.vue b/apps/web-ele/src/components/diy-editor/components/mobile/PromotionSeckill/property.vue new file mode 100644 index 000000000..f87928641 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/PromotionSeckill/property.vue @@ -0,0 +1,180 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/SearchBar/config.ts b/apps/web-ele/src/components/diy-editor/components/mobile/SearchBar/config.ts new file mode 100644 index 000000000..64ab098a4 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/SearchBar/config.ts @@ -0,0 +1,46 @@ +import type { + ComponentStyle, + DiyComponent, +} from '#/components/diy-editor/util'; + +/** 搜索框属性 */ +export interface SearchProperty { + height: number; // 搜索栏高度 + showScan: boolean; // 显示扫一扫 + borderRadius: number; // 框体样式 + placeholder: string; // 占位文字 + placeholderPosition: PlaceholderPosition; // 占位文字位置 + backgroundColor: string; // 框体颜色 + textColor: string; // 字体颜色 + hotKeywords: string[]; // 热词 + style: ComponentStyle; +} + +// 文字位置 +export type PlaceholderPosition = 'center' | 'left'; + +// 定义组件 +export const component = { + id: 'SearchBar', + name: '搜索框', + icon: 'ep:search', + property: { + height: 28, + showScan: false, + borderRadius: 0, + placeholder: '搜索商品', + placeholderPosition: 'left', + backgroundColor: 'rgb(238, 238, 238)', + textColor: 'rgb(150, 151, 153)', + hotKeywords: [], + style: { + bgType: 'color', + bgColor: '#fff', + marginBottom: 8, + paddingTop: 8, + paddingRight: 8, + paddingBottom: 8, + paddingLeft: 8, + } as ComponentStyle, + }, +} as DiyComponent; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/SearchBar/index.vue b/apps/web-ele/src/components/diy-editor/components/mobile/SearchBar/index.vue new file mode 100644 index 000000000..89994c4e8 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/SearchBar/index.vue @@ -0,0 +1,78 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/SearchBar/property.vue b/apps/web-ele/src/components/diy-editor/components/mobile/SearchBar/property.vue new file mode 100644 index 000000000..fc1532ce4 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/SearchBar/property.vue @@ -0,0 +1,100 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/TabBar/config.ts b/apps/web-ele/src/components/diy-editor/components/mobile/TabBar/config.ts new file mode 100644 index 000000000..bc9488e1c --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/TabBar/config.ts @@ -0,0 +1,172 @@ +import type { DiyComponent } from '#/components/diy-editor/util'; + +/** 底部导航菜单属性 */ +export interface TabBarProperty { + // 选项列表 + items: TabBarItemProperty[]; + // 主题 + theme: string; + // 样式 + style: TabBarStyle; +} + +// 选项属性 +export interface TabBarItemProperty { + // 标签文字 + text: string; + // 链接 + url: string; + // 默认图标链接 + iconUrl: string; + // 选中的图标链接 + activeIconUrl: string; +} + +// 样式 +export interface TabBarStyle { + // 背景类型 + bgType: 'color' | 'img'; + // 背景颜色 + bgColor: string; + // 图片链接 + bgImg: string; + // 默认颜色 + color: string; + // 选中的颜色 + activeColor: string; +} + +// 定义组件 +export const component = { + id: 'TabBar', + name: '底部导航', + icon: 'fluent:table-bottom-row-16-filled', + property: { + theme: 'red', + style: { + bgType: 'color', + bgColor: '#fff', + color: '#282828', + activeColor: '#fc4141', + }, + items: [ + { + text: '首页', + url: '/pages/index/index', + iconUrl: 'http://mall.yudao.iocoder.cn/static/images/1-001.png', + activeIconUrl: 'http://mall.yudao.iocoder.cn/static/images/1-002.png', + }, + { + text: '分类', + url: '/pages/index/category?id=3', + iconUrl: 'http://mall.yudao.iocoder.cn/static/images/2-001.png', + activeIconUrl: 'http://mall.yudao.iocoder.cn/static/images/2-002.png', + }, + { + text: '购物车', + url: '/pages/index/cart', + iconUrl: 'http://mall.yudao.iocoder.cn/static/images/3-001.png', + activeIconUrl: 'http://mall.yudao.iocoder.cn/static/images/3-002.png', + }, + { + text: '我的', + url: '/pages/index/user', + iconUrl: 'http://mall.yudao.iocoder.cn/static/images/4-001.png', + activeIconUrl: 'http://mall.yudao.iocoder.cn/static/images/4-002.png', + }, + ], + }, +} as DiyComponent; + +export const THEME_LIST = [ + { + id: 'red', + name: '中国红', + icon: 'icon-park-twotone:theme', + color: '#d10019', + }, + { + id: 'orange', + name: '桔橙', + icon: 'icon-park-twotone:theme', + color: '#f37b1d', + }, + { + id: 'gold', + name: '明黄', + icon: 'icon-park-twotone:theme', + color: '#fbbd08', + }, + { + id: 'green', + name: '橄榄绿', + icon: 'icon-park-twotone:theme', + color: '#8dc63f', + }, + { + id: 'cyan', + name: '天青', + icon: 'icon-park-twotone:theme', + color: '#1cbbb4', + }, + { + id: 'blue', + name: '海蓝', + icon: 'icon-park-twotone:theme', + color: '#0081ff', + }, + { + id: 'purple', + name: '姹紫', + icon: 'icon-park-twotone:theme', + color: '#6739b6', + }, + { + id: 'brightRed', + name: '嫣红', + icon: 'icon-park-twotone:theme', + color: '#e54d42', + }, + { + id: 'forestGreen', + name: '森绿', + icon: 'icon-park-twotone:theme', + color: '#39b54a', + }, + { + id: 'mauve', + name: '木槿', + icon: 'icon-park-twotone:theme', + color: '#9c26b0', + }, + { + id: 'pink', + name: '桃粉', + icon: 'icon-park-twotone:theme', + color: '#e03997', + }, + { + id: 'brown', + name: '棕褐', + icon: 'icon-park-twotone:theme', + color: '#a5673f', + }, + { + id: 'grey', + name: '玄灰', + icon: 'icon-park-twotone:theme', + color: '#8799a3', + }, + { + id: 'gray', + name: '草灰', + icon: 'icon-park-twotone:theme', + color: '#aaaaaa', + }, + { + id: 'black', + name: '墨黑', + icon: 'icon-park-twotone:theme', + color: '#333333', + }, +]; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/TabBar/index.vue b/apps/web-ele/src/components/diy-editor/components/mobile/TabBar/index.vue new file mode 100644 index 000000000..f5d515109 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/TabBar/index.vue @@ -0,0 +1,75 @@ + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/TabBar/property.vue b/apps/web-ele/src/components/diy-editor/components/mobile/TabBar/property.vue new file mode 100644 index 000000000..851049d09 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/TabBar/property.vue @@ -0,0 +1,123 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/TitleBar/config.ts b/apps/web-ele/src/components/diy-editor/components/mobile/TitleBar/config.ts new file mode 100644 index 000000000..64d49ad6c --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/TitleBar/config.ts @@ -0,0 +1,76 @@ +import type { + ComponentStyle, + DiyComponent, +} from '#/components/diy-editor/util'; + +/** 标题栏属性 */ +export interface TitleBarProperty { + // 背景图 + bgImgUrl: string; + // 偏移 + marginLeft: number; + // 显示位置 + textAlign: 'center' | 'left'; + // 主标题 + title: string; + // 副标题 + description: string; + // 标题大小 + titleSize: number; + // 描述大小 + descriptionSize: number; + // 标题粗细 + titleWeight: number; + // 描述粗细 + descriptionWeight: number; + // 标题颜色 + titleColor: string; + // 描述颜色 + descriptionColor: string; + // 高度 + height: number; + // 查看更多 + more: { + // 是否显示查看更多 + show: false; + // 自定义文字 + text: string; + // 样式选择 + type: 'all' | 'icon' | 'text'; + // 链接 + url: string; + }; + // 组件样式 + style: ComponentStyle; +} + +// 定义组件 +export const component = { + id: 'TitleBar', + name: '标题栏', + icon: 'material-symbols:line-start', + property: { + title: '主标题', + description: '副标题', + titleSize: 16, + descriptionSize: 12, + titleWeight: 400, + textAlign: 'left', + descriptionWeight: 200, + titleColor: 'rgba(50, 50, 51, 10)', + descriptionColor: 'rgba(150, 151, 153, 10)', + marginLeft: 0, + height: 40, + more: { + // 查看更多 + show: false, + type: 'icon', + text: '查看更多', + url: '', + }, + style: { + bgType: 'color', + bgColor: '#fff', + } as ComponentStyle, + }, +} as DiyComponent; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/TitleBar/index.vue b/apps/web-ele/src/components/diy-editor/components/mobile/TitleBar/index.vue new file mode 100644 index 000000000..d1abc8131 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/TitleBar/index.vue @@ -0,0 +1,84 @@ + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/TitleBar/property.vue b/apps/web-ele/src/components/diy-editor/components/mobile/TitleBar/property.vue new file mode 100644 index 000000000..7b5a830a0 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/TitleBar/property.vue @@ -0,0 +1,145 @@ + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/UserCard/config.ts b/apps/web-ele/src/components/diy-editor/components/mobile/UserCard/config.ts new file mode 100644 index 000000000..e674a0a32 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/UserCard/config.ts @@ -0,0 +1,24 @@ +import type { + ComponentStyle, + DiyComponent, +} from '#/components/diy-editor/util'; + +/** 用户卡片属性 */ +export interface UserCardProperty { + // 组件样式 + style: ComponentStyle; +} + +// 定义组件 +export const component = { + id: 'UserCard', + name: '用户卡片', + icon: 'mdi:user-card-details', + property: { + style: { + bgType: 'color', + bgColor: '', + marginBottom: 8, + } as ComponentStyle, + }, +} as DiyComponent; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/UserCard/index.vue b/apps/web-ele/src/components/diy-editor/components/mobile/UserCard/index.vue new file mode 100644 index 000000000..174d29392 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/UserCard/index.vue @@ -0,0 +1,31 @@ + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/UserCard/property.vue b/apps/web-ele/src/components/diy-editor/components/mobile/UserCard/property.vue new file mode 100644 index 000000000..c7b7de1aa --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/UserCard/property.vue @@ -0,0 +1,18 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/UserCoupon/config.ts b/apps/web-ele/src/components/diy-editor/components/mobile/UserCoupon/config.ts new file mode 100644 index 000000000..efcb7f2ef --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/UserCoupon/config.ts @@ -0,0 +1,26 @@ +import type { + ComponentStyle, + DiyComponent, +} from '#/components/diy-editor/util'; + +/** 用户卡券属性 */ +export interface UserCouponProperty { + // 组件样式 + style: ComponentStyle; +} + +// 定义组件 +export const component = { + id: 'UserCoupon', + name: '用户卡券', + icon: 'ep:ticket', + property: { + style: { + bgType: 'color', + bgColor: '', + marginLeft: 8, + marginRight: 8, + marginBottom: 8, + } as ComponentStyle, + }, +} as DiyComponent; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/UserCoupon/index.vue b/apps/web-ele/src/components/diy-editor/components/mobile/UserCoupon/index.vue new file mode 100644 index 000000000..ba43a7258 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/UserCoupon/index.vue @@ -0,0 +1,15 @@ + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/UserCoupon/property.vue b/apps/web-ele/src/components/diy-editor/components/mobile/UserCoupon/property.vue new file mode 100644 index 000000000..4ad4a304f --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/UserCoupon/property.vue @@ -0,0 +1,18 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/UserOrder/config.ts b/apps/web-ele/src/components/diy-editor/components/mobile/UserOrder/config.ts new file mode 100644 index 000000000..0c2e825a3 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/UserOrder/config.ts @@ -0,0 +1,26 @@ +import type { + ComponentStyle, + DiyComponent, +} from '#/components/diy-editor/util'; + +/** 用户订单属性 */ +export interface UserOrderProperty { + // 组件样式 + style: ComponentStyle; +} + +// 定义组件 +export const component = { + id: 'UserOrder', + name: '用户订单', + icon: 'ep:list', + property: { + style: { + bgType: 'color', + bgColor: '', + marginLeft: 8, + marginRight: 8, + marginBottom: 8, + } as ComponentStyle, + }, +} as DiyComponent; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/UserOrder/index.vue b/apps/web-ele/src/components/diy-editor/components/mobile/UserOrder/index.vue new file mode 100644 index 000000000..77cb3883f --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/UserOrder/index.vue @@ -0,0 +1,15 @@ + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/UserOrder/property.vue b/apps/web-ele/src/components/diy-editor/components/mobile/UserOrder/property.vue new file mode 100644 index 000000000..44fe906e9 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/UserOrder/property.vue @@ -0,0 +1,18 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/UserWallet/config.ts b/apps/web-ele/src/components/diy-editor/components/mobile/UserWallet/config.ts new file mode 100644 index 000000000..8393760b4 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/UserWallet/config.ts @@ -0,0 +1,26 @@ +import type { + ComponentStyle, + DiyComponent, +} from '#/components/diy-editor/util'; + +/** 用户资产属性 */ +export interface UserWalletProperty { + // 组件样式 + style: ComponentStyle; +} + +// 定义组件 +export const component = { + id: 'UserWallet', + name: '用户资产', + icon: 'ep:wallet-filled', + property: { + style: { + bgType: 'color', + bgColor: '', + marginLeft: 8, + marginRight: 8, + marginBottom: 8, + } as ComponentStyle, + }, +} as DiyComponent; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/UserWallet/index.vue b/apps/web-ele/src/components/diy-editor/components/mobile/UserWallet/index.vue new file mode 100644 index 000000000..cb91df303 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/UserWallet/index.vue @@ -0,0 +1,15 @@ + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/UserWallet/property.vue b/apps/web-ele/src/components/diy-editor/components/mobile/UserWallet/property.vue new file mode 100644 index 000000000..776783a3a --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/UserWallet/property.vue @@ -0,0 +1,18 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/VideoPlayer/config.ts b/apps/web-ele/src/components/diy-editor/components/mobile/VideoPlayer/config.ts new file mode 100644 index 000000000..dc2dd8866 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/VideoPlayer/config.ts @@ -0,0 +1,40 @@ +import type { + ComponentStyle, + DiyComponent, +} from '#/components/diy-editor/util'; + +/** 视频播放属性 */ +export interface VideoPlayerProperty { + // 视频链接 + videoUrl: string; + // 封面链接 + posterUrl: string; + // 是否自动播放 + autoplay: boolean; + // 组件样式 + style: VideoPlayerStyle; +} + +// 视频播放样式 +export interface VideoPlayerStyle extends ComponentStyle { + // 视频高度 + height: number; +} + +// 定义组件 +export const component = { + id: 'VideoPlayer', + name: '视频播放', + icon: 'ep:video-play', + property: { + videoUrl: '', + posterUrl: '', + autoplay: false, + style: { + bgType: 'color', + bgColor: '#fff', + marginBottom: 8, + height: 300, + } as VideoPlayerStyle, + }, +} as DiyComponent; diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/VideoPlayer/index.vue b/apps/web-ele/src/components/diy-editor/components/mobile/VideoPlayer/index.vue new file mode 100644 index 000000000..fe205ca05 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/VideoPlayer/index.vue @@ -0,0 +1,34 @@ + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/VideoPlayer/property.vue b/apps/web-ele/src/components/diy-editor/components/mobile/VideoPlayer/property.vue new file mode 100644 index 000000000..c4e4f8c37 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/VideoPlayer/property.vue @@ -0,0 +1,56 @@ + + + + + diff --git a/apps/web-ele/src/components/diy-editor/components/mobile/index.ts b/apps/web-ele/src/components/diy-editor/components/mobile/index.ts new file mode 100644 index 000000000..454e06a0b --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/components/mobile/index.ts @@ -0,0 +1,69 @@ +import { defineAsyncComponent } from 'vue'; + +/* + * 组件注册 + * + * 组件规范: + * 1. 每个子目录就是一个独立的组件,每个目录包括以下三个文件: + * 2. config.ts:组件配置,必选,用于定义组件、组件默认的属性、定义属性的类型 + * 3. index.vue:组件展示,用于展示组件的渲染效果。可以不提供,如 Page(页面设置),只需要属性配置表单即可 + * 4. property.vue:组件属性表单,用于配置组件,必选, + * + * 注: + * 组件ID以config.ts中配置的id为准,与组件目录的名称无关,但还是建议组件目录的名称与组件ID保持一致 + */ + +// 导入组件界面模块 +const viewModules: Record = import.meta.glob('./*/*.vue'); +// 导入配置模块 +const configModules: Record = import.meta.glob('./*/config.ts', { + eager: true, +}); + +// 界面模块 +const components: Record = {}; +// 组件配置模块 +const componentConfigs: Record = {}; + +// 组件界面的类型 +type ViewType = 'index' | 'property'; + +/** + * 注册组件的界面模块 + * + * @param componentId 组件ID + * @param configPath 配置模块的文件路径 + * @param viewType 组件界面的类型 + */ +const registerComponentViewModule = ( + componentId: string, + configPath: string, + viewType: ViewType, +) => { + const viewPath = configPath.replace('config.ts', `${viewType}.vue`); + const viewModule = viewModules[viewPath]; + if (viewModule) { + // 定义异步组件 + components[componentId] = defineAsyncComponent(viewModule); + } +}; + +// 注册 +Object.keys(configModules).forEach((modulePath: string) => { + const component = configModules[modulePath].component; + const componentId = component?.id; + if (componentId) { + // 注册组件 + componentConfigs[componentId] = component; + // 注册预览界面 + registerComponentViewModule(componentId, modulePath, 'index'); + // 注册属性配置表单 + registerComponentViewModule( + `${componentId}Property`, + modulePath, + 'property', + ); + } +}); + +export { componentConfigs, components }; diff --git a/apps/web-ele/src/components/diy-editor/index.vue b/apps/web-ele/src/components/diy-editor/index.vue new file mode 100644 index 000000000..aee995fe5 --- /dev/null +++ b/apps/web-ele/src/components/diy-editor/index.vue @@ -0,0 +1,648 @@ + +