fix: 冲突
This commit is contained in:
@@ -1 +1 @@
|
||||
export { default as ProductCategorySelect } from './category-select.vue';
|
||||
export { default as ProductCategorySelect } from './select.vue';
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script lang="ts" setup>
|
||||
// TODO @AI:一些 modal 是否使用 Modal 组件,而不是 el-modal?
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
import { ElButton, ElInput } from 'element-plus';
|
||||
|
||||
@@ -27,7 +27,7 @@ const props = defineProps<{ modelValue: ComponentStyle }>();
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
const formData = useVModel(props, 'modelValue', emit);
|
||||
|
||||
const treeData = [
|
||||
const treeData: any[] = [
|
||||
{
|
||||
label: '外部边距',
|
||||
prop: 'margin',
|
||||
@@ -96,7 +96,7 @@ const treeData = [
|
||||
},
|
||||
];
|
||||
|
||||
const handleSliderChange = (prop: string) => {
|
||||
function handleSliderChange(prop: string) {
|
||||
switch (prop) {
|
||||
case 'borderRadius': {
|
||||
formData.value.borderTopLeftRadius = formData.value.borderRadius;
|
||||
@@ -120,7 +120,7 @@ const handleSliderChange = (prop: string) => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -53,11 +53,11 @@ watch(
|
||||
);
|
||||
|
||||
/** 克隆组件 */
|
||||
const handleCloneComponent = (component: DiyComponent<any>) => {
|
||||
function handleCloneComponent(component: DiyComponent<any>) {
|
||||
const instance = cloneDeep(component);
|
||||
instance.uid = Date.now();
|
||||
return instance;
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -24,7 +24,7 @@ import { AppLinkInput, Draggable } from '#/views/mall/promotion/components';
|
||||
|
||||
import ComponentContainerProperty from '../../component-container-property.vue';
|
||||
|
||||
// 轮播图属性面板
|
||||
/** 轮播图属性面板 */
|
||||
defineOptions({ name: 'CarouselProperty' });
|
||||
|
||||
const props = defineProps<{ modelValue: CarouselProperty }>();
|
||||
|
||||
@@ -7,7 +7,7 @@ import { onMounted, ref, watch } from 'vue';
|
||||
|
||||
import { ElScrollbar } from 'element-plus';
|
||||
|
||||
import * as CouponTemplateApi from '#/api/mall/promotion/coupon/couponTemplate';
|
||||
import { getCouponTemplateList } from '#/api/mall/promotion/coupon/couponTemplate';
|
||||
|
||||
import {
|
||||
CouponDiscount,
|
||||
@@ -32,9 +32,7 @@ watch(
|
||||
() => props.property.couponIds,
|
||||
async () => {
|
||||
if (props.property.couponIds?.length > 0) {
|
||||
couponList.value = await CouponTemplateApi.getCouponTemplateList(
|
||||
props.property.couponIds,
|
||||
);
|
||||
couponList.value = await getCouponTemplateList(props.property.couponIds);
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -39,7 +39,7 @@ function handleToggleFab() {
|
||||
<ElImage :src="item.imgUrl" fit="contain" class="h-7 w-7">
|
||||
<template #error>
|
||||
<div class="flex h-full w-full items-center justify-center">
|
||||
<IconifyIcon icon="ep:picture" :color="item.textColor" />
|
||||
<IconifyIcon icon="lucide:image" :color="item.textColor" />
|
||||
</div>
|
||||
</template>
|
||||
</ElImage>
|
||||
@@ -55,7 +55,7 @@ function handleToggleFab() {
|
||||
<!-- todo: @owen 使用APP主题色 -->
|
||||
<ElButton type="primary" size="large" circle @click="handleToggleFab">
|
||||
<IconifyIcon
|
||||
icon="ep:plus"
|
||||
icon="lucide:plus"
|
||||
class="transition-transform duration-300"
|
||||
:class="expanded ? 'rotate-[135deg]' : 'rotate-0'"
|
||||
/>
|
||||
|
||||
@@ -23,9 +23,9 @@ const formData = useVModel(props, 'modelValue', emit);
|
||||
const editDialogRef = ref(); // 热区编辑对话框
|
||||
|
||||
/** 打开热区编辑对话框 */
|
||||
const handleOpenEditDialog = () => {
|
||||
function handleOpenEditDialog() {
|
||||
editDialogRef.value.open();
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -11,7 +11,7 @@ export interface ImageBarProperty {
|
||||
export const component = {
|
||||
id: 'ImageBar',
|
||||
name: '图片展示',
|
||||
icon: 'ep:picture',
|
||||
icon: 'lucide:image',
|
||||
property: {
|
||||
imgUrl: '',
|
||||
url: '',
|
||||
|
||||
@@ -13,7 +13,9 @@ import ComponentContainerProperty from '../../component-container-property.vue';
|
||||
defineOptions({ name: 'ImageBarProperty' });
|
||||
|
||||
const props = defineProps<{ modelValue: ImageBarProperty }>();
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
||||
const formData = useVModel(props, 'modelValue', emit);
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,32 +1,25 @@
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
|
||||
/*
|
||||
/**
|
||||
* 组件注册
|
||||
*
|
||||
* 组件规范:
|
||||
* 1. 每个子目录就是一个独立的组件,每个目录包括以下三个文件:
|
||||
* 2. config.ts:组件配置,必选,用于定义组件、组件默认的属性、定义属性的类型
|
||||
* 3. index.vue:组件展示,用于展示组件的渲染效果。可以不提供,如 Page(页面设置),只需要属性配置表单即可
|
||||
* 4. property.vue:组件属性表单,用于配置组件,必选,
|
||||
* 组件规范:每个子目录就是一个独立的组件,每个目录包括以下三个文件:
|
||||
* 1. config.ts:组件配置,必选,用于定义组件、组件默认的属性、定义属性的类型
|
||||
* 2. index.vue:组件展示,用于展示组件的渲染效果。可以不提供,如 Page(页面设置),只需要属性配置表单即可
|
||||
* 3. property.vue:组件属性表单,用于配置组件,必选,
|
||||
*
|
||||
* 注:
|
||||
* 组件ID以config.ts中配置的id为准,与组件目录的名称无关,但还是建议组件目录的名称与组件ID保持一致
|
||||
* 组件 ID 以 config.ts 中配置的 id 为准,与组件目录的名称无关,但还是建议组件目录的名称与组件 ID 保持一致
|
||||
*/
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
|
||||
// 导入组件界面模块
|
||||
const viewModules: Record<string, any> = import.meta.glob('./*/*.vue');
|
||||
// 导入配置模块
|
||||
const viewModules: Record<string, any> = import.meta.glob('./*/*.vue'); // 导入组件界面模块
|
||||
const configModules: Record<string, any> = import.meta.glob('./*/config.ts', {
|
||||
eager: true,
|
||||
});
|
||||
}); // 导入配置模块
|
||||
|
||||
// 界面模块
|
||||
const components: Record<string, any> = {};
|
||||
// 组件配置模块
|
||||
const componentConfigs: Record<string, any> = {};
|
||||
const components: Record<string, any> = {}; // 界面模块
|
||||
const componentConfigs: Record<string, any> = {}; // 组件配置模块
|
||||
|
||||
// 组件界面的类型
|
||||
type ViewType = 'index' | 'property';
|
||||
type ViewType = 'index' | 'property'; // 组件界面的类型
|
||||
|
||||
/**
|
||||
* 注册组件的界面模块
|
||||
|
||||
@@ -19,7 +19,7 @@ export interface NoticeContentProperty {
|
||||
export const component = {
|
||||
id: 'NoticeBar',
|
||||
name: '公告栏',
|
||||
icon: 'ep:bell',
|
||||
icon: 'lucide:bell',
|
||||
property: {
|
||||
iconUrl: 'http://mall.yudao.iocoder.cn/static/images/xinjian.png',
|
||||
contents: [
|
||||
|
||||
@@ -11,7 +11,7 @@ export interface PageConfigProperty {
|
||||
export const component = {
|
||||
id: 'PageConfig',
|
||||
name: '页面设置',
|
||||
icon: 'ep:document',
|
||||
icon: 'lucide:file-text',
|
||||
property: {
|
||||
description: '',
|
||||
backgroundColor: '#f5f5f5',
|
||||
|
||||
@@ -19,7 +19,6 @@ function handleActive(index: number) {
|
||||
activeIndex.value = index;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
v-for="(item, index) in props.property.list"
|
||||
@@ -35,7 +34,7 @@ function handleActive(index: number) {
|
||||
<ElImage :src="item.imgUrl" fit="contain" class="h-full w-full">
|
||||
<template #error>
|
||||
<div class="flex h-full w-full items-center justify-center">
|
||||
<IconifyIcon icon="ep:picture" />
|
||||
<IconifyIcon icon="lucide:image" />
|
||||
</div>
|
||||
</template>
|
||||
</ElImage>
|
||||
|
||||
@@ -39,7 +39,7 @@ export interface ProductCardFieldProperty {
|
||||
export const component = {
|
||||
id: 'ProductCard',
|
||||
name: '商品卡片',
|
||||
icon: 'fluent:text-column-two-left-24-filled',
|
||||
icon: 'lucide:grid-3x3',
|
||||
property: {
|
||||
layoutType: 'oneColBigImg',
|
||||
fields: {
|
||||
|
||||
@@ -9,19 +9,19 @@ import { fenToYuan } from '@vben/utils';
|
||||
|
||||
import { ElImage } from 'element-plus';
|
||||
|
||||
import * as ProductSpuApi from '#/api/mall/product/spu';
|
||||
import { getSpuDetailList } from '#/api/mall/product/spu';
|
||||
|
||||
/** 商品卡片 */
|
||||
defineOptions({ name: 'ProductCard' });
|
||||
|
||||
const props = defineProps<{ property: ProductCardProperty }>();
|
||||
|
||||
const spuList = ref<MallSpuApi.Spu[]>([]);
|
||||
const spuList = ref<MallSpuApi.Spu[]>([]); // 商品列表
|
||||
|
||||
watch(
|
||||
() => props.property.spuIds,
|
||||
async () => {
|
||||
spuList.value = await ProductSpuApi.getSpuDetailList(props.property.spuIds);
|
||||
spuList.value = await getSpuDetailList(props.property.spuIds);
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
@@ -37,17 +37,17 @@ function calculateSpace(index: number) {
|
||||
return { marginLeft, marginTop };
|
||||
}
|
||||
|
||||
const containerRef = ref();
|
||||
const containerRef = ref(); // 容器
|
||||
|
||||
/** 计算商品的宽度 */
|
||||
const calculateWidth = () => {
|
||||
function calculateWidth() {
|
||||
let width = '100%';
|
||||
if (props.property.layoutType === 'twoCol') {
|
||||
// 双列时每列的宽度为:(总宽度 - 间距)/ 2
|
||||
width = `${(containerRef.value.offsetWidth - props.property.space) / 2}px`;
|
||||
}
|
||||
return { width };
|
||||
};
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<div
|
||||
|
||||
@@ -9,7 +9,7 @@ import { fenToYuan } from '@vben/utils';
|
||||
|
||||
import { ElImage, ElScrollbar } from 'element-plus';
|
||||
|
||||
import * as ProductSpuApi from '#/api/mall/product/spu';
|
||||
import { getSpuDetailList } from '#/api/mall/product/spu';
|
||||
|
||||
/** 商品栏 */
|
||||
defineOptions({ name: 'ProductList' });
|
||||
@@ -21,7 +21,7 @@ const spuList = ref<MallSpuApi.Spu[]>([]);
|
||||
watch(
|
||||
() => props.property.spuIds,
|
||||
async () => {
|
||||
spuList.value = await ProductSpuApi.getSpuDetailList(props.property.spuIds);
|
||||
spuList.value = await getSpuDetailList(props.property.spuIds);
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
|
||||
@@ -5,7 +5,7 @@ import type { MallArticleApi } from '#/api/mall/promotion/article';
|
||||
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
import * as ArticleApi from '#/api/mall/promotion/article/index';
|
||||
import { getArticle } from '#/api/mall/promotion/article';
|
||||
|
||||
/** 营销文章 */
|
||||
defineOptions({ name: 'PromotionArticle' });
|
||||
@@ -18,7 +18,7 @@ watch(
|
||||
() => props.property.id,
|
||||
async () => {
|
||||
if (props.property.id) {
|
||||
article.value = await ArticleApi.getArticle(props.property.id);
|
||||
article.value = await getArticle(props.property.id);
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -10,8 +10,8 @@ import { fenToYuan } from '@vben/utils';
|
||||
|
||||
import { ElImage } from 'element-plus';
|
||||
|
||||
import * as ProductSpuApi from '#/api/mall/product/spu';
|
||||
import * as CombinationActivityApi from '#/api/mall/promotion/combination/combinationActivity';
|
||||
import { getSpuDetailList } from '#/api/mall/product/spu';
|
||||
import { getCombinationActivityListByIds } from '#/api/mall/promotion/combination/combinationActivity';
|
||||
|
||||
/** 拼团卡片 */
|
||||
defineOptions({ name: 'PromotionCombination' });
|
||||
@@ -34,9 +34,7 @@ watch(
|
||||
if (Array.isArray(activityIds) && activityIds.length > 0) {
|
||||
// 获取拼团活动详情列表
|
||||
combinationActivityList.value =
|
||||
await CombinationActivityApi.getCombinationActivityListByIds(
|
||||
activityIds,
|
||||
);
|
||||
await getCombinationActivityListByIds(activityIds);
|
||||
|
||||
// 获取拼团活动的 SPU 详情列表
|
||||
spuList.value = [];
|
||||
@@ -44,7 +42,7 @@ watch(
|
||||
.map((activity) => activity.spuId)
|
||||
.filter((spuId): spuId is number => typeof spuId === 'number');
|
||||
if (spuIdList.value.length > 0) {
|
||||
spuList.value = await ProductSpuApi.getSpuDetailList(spuIdList.value);
|
||||
spuList.value = await getSpuDetailList(spuIdList.value);
|
||||
}
|
||||
|
||||
// 更新 SPU 的最低价格
|
||||
@@ -78,7 +76,7 @@ function calculateSpace(index: number) {
|
||||
return { marginLeft, marginTop };
|
||||
}
|
||||
|
||||
const containerRef = ref();
|
||||
const containerRef = ref(); // 容器
|
||||
|
||||
/** 计算商品的宽度 */
|
||||
function calculateWidth() {
|
||||
|
||||
@@ -74,7 +74,7 @@ function calculateSpace(index: number) {
|
||||
return { marginLeft, marginTop };
|
||||
}
|
||||
|
||||
const containerRef = ref();
|
||||
const containerRef = ref(); // 容器
|
||||
|
||||
/** 计算商品的宽度 */
|
||||
function calculateWidth() {
|
||||
|
||||
@@ -54,11 +54,6 @@ const formData = useVModel(props, 'modelValue', emit);
|
||||
<IconifyIcon icon="fluent:text-column-two-24-filled" />
|
||||
</ElRadioButton>
|
||||
</ElTooltip>
|
||||
<!--<ElTooltip class="item" content="三列" placement="bottom">
|
||||
<ElRadioButton value="threeCol">
|
||||
<IconifyIcon icon="fluent:text-column-three-24-filled" />
|
||||
</ElRadioButton>
|
||||
</ElTooltip>-->
|
||||
</ElRadioGroup>
|
||||
</ElFormItem>
|
||||
<ElFormItem label="商品名称" prop="fields.name.show">
|
||||
|
||||
@@ -10,8 +10,8 @@ import { fenToYuan } from '@vben/utils';
|
||||
|
||||
import { ElImage } from 'element-plus';
|
||||
|
||||
import * as ProductSpuApi from '#/api/mall/product/spu';
|
||||
import * as SeckillActivityApi from '#/api/mall/promotion/seckill/seckillActivity';
|
||||
import { getSpuDetailList } from '#/api/mall/product/spu';
|
||||
import { getSeckillActivityListByIds } from '#/api/mall/promotion/seckill/seckillActivity';
|
||||
|
||||
/** 秒杀卡片 */
|
||||
defineOptions({ name: 'PromotionSeckill' });
|
||||
@@ -31,7 +31,7 @@ watch(
|
||||
if (Array.isArray(activityIds) && activityIds.length > 0) {
|
||||
// 获取秒杀活动详情列表
|
||||
seckillActivityList.value =
|
||||
await SeckillActivityApi.getSeckillActivityListByIds(activityIds);
|
||||
await getSeckillActivityListByIds(activityIds);
|
||||
|
||||
// 获取秒杀活动的 SPU 详情列表
|
||||
spuList.value = [];
|
||||
@@ -39,7 +39,7 @@ watch(
|
||||
.map((activity) => activity.spuId)
|
||||
.filter((spuId): spuId is number => typeof spuId === 'number');
|
||||
if (spuIdList.value.length > 0) {
|
||||
spuList.value = await ProductSpuApi.getSpuDetailList(spuIdList.value);
|
||||
spuList.value = await getSpuDetailList(spuIdList.value);
|
||||
}
|
||||
|
||||
// 更新 SPU 的最低价格
|
||||
@@ -73,7 +73,7 @@ function calculateSpace(index: number) {
|
||||
return { marginLeft, marginTop };
|
||||
}
|
||||
|
||||
const containerRef = ref();
|
||||
const containerRef = ref(); // 容器
|
||||
|
||||
/** 计算商品的宽度 */
|
||||
function calculateWidth() {
|
||||
|
||||
@@ -20,7 +20,7 @@ export type PlaceholderPosition = 'center' | 'left';
|
||||
export const component = {
|
||||
id: 'SearchBar',
|
||||
name: '搜索框',
|
||||
icon: 'ep:search',
|
||||
icon: 'lucide:search',
|
||||
property: {
|
||||
height: 28,
|
||||
showScan: false,
|
||||
|
||||
@@ -30,7 +30,7 @@ defineProps<{ property: SearchProperty }>();
|
||||
justifyContent: property.placeholderPosition,
|
||||
}"
|
||||
>
|
||||
<IconifyIcon icon="ep:search" />
|
||||
<IconifyIcon icon="lucide:search" />
|
||||
<span>{{ property.placeholder || '搜索商品' }}</span>
|
||||
</div>
|
||||
<div class="absolute right-2 flex items-center justify-center gap-2">
|
||||
@@ -39,10 +39,7 @@ defineProps<{ property: SearchProperty }>();
|
||||
{{ keyword }}
|
||||
</span>
|
||||
<!-- 扫一扫 -->
|
||||
<IconifyIcon
|
||||
icon="ant-design:scan-outlined"
|
||||
v-show="property.showScan"
|
||||
/>
|
||||
<IconifyIcon icon="lucide:scan-barcode" v-show="property.showScan" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,7 @@ import { IconifyIcon } from '@vben/icons';
|
||||
|
||||
import { ElImage } from 'element-plus';
|
||||
|
||||
/** 底部导航 */
|
||||
/** 页面底部导航栏 */
|
||||
defineOptions({ name: 'TabBar' });
|
||||
|
||||
defineProps<{ property: TabBarProperty }>();
|
||||
@@ -26,7 +26,7 @@ defineProps<{ property: TabBarProperty }>();
|
||||
<div
|
||||
v-for="(item, index) in property.items"
|
||||
:key="index"
|
||||
class="tab-bar-item flex w-full flex-col items-center justify-center text-xs"
|
||||
class="flex w-full flex-col items-center justify-center text-xs"
|
||||
>
|
||||
<ElImage
|
||||
:src="index === 0 ? item.activeIconUrl : item.iconUrl"
|
||||
@@ -35,7 +35,7 @@ defineProps<{ property: TabBarProperty }>();
|
||||
<template #error>
|
||||
<div class="flex h-full w-full items-center justify-center">
|
||||
<IconifyIcon
|
||||
icon="ep:picture"
|
||||
icon="lucide:image"
|
||||
class="h-[26px] w-[26px] rounded"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -44,7 +44,7 @@ const handleThemeChange = () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="tab-bar">
|
||||
<div>
|
||||
<ElForm :model="formData" label-width="80px">
|
||||
<ElFormItem label="主题" prop="theme">
|
||||
<ElSelect v-model="formData!.theme" @change="handleThemeChange">
|
||||
|
||||
@@ -63,7 +63,10 @@ defineProps<{ property: TitleBarProperty }>();
|
||||
<span v-if="property.more.type !== 'icon'">
|
||||
{{ property.more.text }}
|
||||
</span>
|
||||
<IconifyIcon icon="ep:arrow-right" v-if="property.more.type !== 'text'" />
|
||||
<IconifyIcon
|
||||
icon="lucide:arrow-right"
|
||||
v-if="property.more.type !== 'text'"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -2,15 +2,14 @@ import type { ComponentStyle, DiyComponent } from '../../../util';
|
||||
|
||||
/** 用户卡券属性 */
|
||||
export interface UserCouponProperty {
|
||||
// 组件样式
|
||||
style: ComponentStyle;
|
||||
style: ComponentStyle; // 组件样式
|
||||
}
|
||||
|
||||
// 定义组件
|
||||
/** 定义组件 */
|
||||
export const component = {
|
||||
id: 'UserCoupon',
|
||||
name: '用户卡券',
|
||||
icon: 'ep:ticket',
|
||||
icon: 'lucide:ticket',
|
||||
property: {
|
||||
style: {
|
||||
bgType: 'color',
|
||||
|
||||
@@ -9,7 +9,7 @@ export interface UserOrderProperty {
|
||||
export const component = {
|
||||
id: 'UserOrder',
|
||||
name: '用户订单',
|
||||
icon: 'ep:list',
|
||||
icon: 'lucide:clipboard-list',
|
||||
property: {
|
||||
style: {
|
||||
bgType: 'color',
|
||||
|
||||
@@ -9,7 +9,7 @@ export interface UserWalletProperty {
|
||||
export const component = {
|
||||
id: 'UserWallet',
|
||||
name: '用户资产',
|
||||
icon: 'ep:wallet-filled',
|
||||
icon: 'lucide:wallet',
|
||||
property: {
|
||||
style: {
|
||||
bgType: 'color',
|
||||
|
||||
@@ -17,7 +17,7 @@ export interface VideoPlayerStyle extends ComponentStyle {
|
||||
export const component = {
|
||||
id: 'VideoPlayer',
|
||||
name: '视频播放',
|
||||
icon: 'ep:video-play',
|
||||
icon: 'lucide:video',
|
||||
property: {
|
||||
videoUrl: '',
|
||||
posterUrl: '',
|
||||
|
||||
@@ -27,14 +27,11 @@ export interface DiyComponentLibrary {
|
||||
components: string[]; // 组件列表
|
||||
}
|
||||
|
||||
// 组件样式
|
||||
/** 组件样式 */
|
||||
export interface ComponentStyle {
|
||||
// 背景类型
|
||||
bgType: 'color' | 'img';
|
||||
// 背景颜色
|
||||
bgColor: string;
|
||||
// 背景图片
|
||||
bgImg: string;
|
||||
bgType: 'color' | 'img'; // 背景类型
|
||||
bgColor: string; // 背景颜色
|
||||
bgImg: string; // 背景图片
|
||||
// 外边距
|
||||
margin: number;
|
||||
marginTop: number;
|
||||
|
||||
@@ -63,9 +63,8 @@ const handleDelete = function (index: number) {
|
||||
>
|
||||
<ElTooltip content="拖动排序">
|
||||
<IconifyIcon
|
||||
icon="ic:round-drag-indicator"
|
||||
class="drag-icon cursor-move"
|
||||
style="color: #8a909c"
|
||||
icon="lucide:move"
|
||||
class="drag-icon cursor-move text-gray-500"
|
||||
/>
|
||||
</ElTooltip>
|
||||
<ElTooltip content="删除">
|
||||
@@ -90,7 +89,7 @@ const handleDelete = function (index: number) {
|
||||
:disabled="limit > 0 && formData.length >= limit"
|
||||
@click="handleAdd"
|
||||
>
|
||||
<IconifyIcon icon="ep:plus" /><span>添加</span>
|
||||
<IconifyIcon icon="lucide:plus" /><span>添加</span>
|
||||
</ElButton>
|
||||
</ElTooltip>
|
||||
</template>
|
||||
|
||||
@@ -183,7 +183,7 @@ function exitHotAreaSelectMode() {
|
||||
* 迭代魔方矩阵
|
||||
* @param callback 回调
|
||||
*/
|
||||
const eachCube = (callback: (x: number, y: number, cube: Cube) => void) => {
|
||||
function eachCube(callback: (x: number, y: number, cube: Cube) => void) {
|
||||
for (const [x, row] of cubes.value.entries()) {
|
||||
if (!row) continue;
|
||||
for (const [y, cube] of row.entries()) {
|
||||
@@ -192,7 +192,7 @@ const eachCube = (callback: (x: number, y: number, cube: Cube) => void) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<div class="relative">
|
||||
|
||||
@@ -133,7 +133,7 @@ function emitActivityChange() {
|
||||
class="hover:border-primary hover:bg-primary/5 flex h-[60px] w-[60px] cursor-pointer items-center justify-center rounded-lg border-2 border-dashed transition-colors"
|
||||
@click="handleOpenActivitySelect"
|
||||
>
|
||||
<IconifyIcon icon="ep:plus" class="text-xl text-gray-400" />
|
||||
<IconifyIcon icon="lucide:plus" class="text-xl text-gray-400" />
|
||||
</div>
|
||||
</ElTooltip>
|
||||
</div>
|
||||
|
||||
@@ -81,11 +81,12 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||
|
||||
<template>
|
||||
<Page auto-content-height>
|
||||
<DocAlert
|
||||
title="会员等级、积分、签到"
|
||||
url="https://doc.iocoder.cn/member/level/"
|
||||
/>
|
||||
|
||||
<template #doc>
|
||||
<DocAlert
|
||||
title="会员等级、积分、签到"
|
||||
url="https://doc.iocoder.cn/member/level/"
|
||||
/>
|
||||
</template>
|
||||
<FormModal @success="handleRefresh" />
|
||||
<Grid table-title="等级列表">
|
||||
<template #toolbar-tools>
|
||||
|
||||
@@ -42,10 +42,12 @@ const [Grid] = useVbenVxeGrid({
|
||||
|
||||
<template>
|
||||
<Page auto-content-height>
|
||||
<DocAlert
|
||||
title="会员等级、积分、签到"
|
||||
url="https://doc.iocoder.cn/member/level/"
|
||||
/>
|
||||
<template #doc>
|
||||
<DocAlert
|
||||
title="会员等级、积分、签到"
|
||||
url="https://doc.iocoder.cn/member/level/"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<Grid table-title="积分记录列表" />
|
||||
</Page>
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
- Copyright (C) 2018-2019
|
||||
- All rights reserved, Designed By www.joolun.com
|
||||
芋道源码:
|
||||
① 移除 avue 组件,使用 ElementUI 原生组件
|
||||
-->
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.avue-card {
|
||||
.mp-card {
|
||||
&__item {
|
||||
box-sizing: border-box;
|
||||
height: 200px;
|
||||
@@ -99,18 +99,18 @@
|
||||
}
|
||||
|
||||
/** joolun 额外加的 */
|
||||
.avue-comment__main {
|
||||
.mp-comment__main {
|
||||
flex: unset !important;
|
||||
margin: 0 8px !important;
|
||||
border-radius: 5px !important;
|
||||
}
|
||||
|
||||
.avue-comment__header {
|
||||
.mp-comment__header {
|
||||
border-top-left-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
}
|
||||
|
||||
.avue-comment__body {
|
||||
.mp-comment__body {
|
||||
border-bottom-right-radius: 5px;
|
||||
border-bottom-left-radius: 5px;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* 来自 https://github.com/nmxiaowei/avue/blob/master/styles/src/element-ui/comment.scss */
|
||||
.avue-comment {
|
||||
.mp-comment {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 30px;
|
||||
@@ -7,7 +7,7 @@
|
||||
&--reverse {
|
||||
flex-direction: row-reverse;
|
||||
|
||||
.avue-comment__main {
|
||||
.mp-comment__main {
|
||||
&::before,
|
||||
&::after {
|
||||
right: -8px;
|
||||
|
||||
@@ -55,7 +55,7 @@ const getNickname = (sendFrom: SendFromType) =>
|
||||
<div
|
||||
class="flex items-center justify-between rounded-t-[5px] border-b border-[#eee] bg-[#f8f8f8] px-[15px] py-[5px]"
|
||||
>
|
||||
<div class="avue-comment__create_time">
|
||||
<div class="mp-comment__create_time">
|
||||
{{ formatDateTime(item.createTime) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -44,18 +44,15 @@ defineExpose({
|
||||
target="_blank"
|
||||
:href="hqMusicUrl ? hqMusicUrl : musicUrl"
|
||||
>
|
||||
<div
|
||||
class="avue-card__body"
|
||||
style="padding: 10px; background-color: #fff; border-radius: 5px"
|
||||
>
|
||||
<div class="avue-card__avatar">
|
||||
<div class="mp-card__body bg-background rounded-sm p-2.5">
|
||||
<div class="mp-card__avatar">
|
||||
<img :src="thumbMediaUrl" alt="" />
|
||||
</div>
|
||||
<div class="avue-card__detail">
|
||||
<div class="avue-card__title" style="margin-bottom: unset">
|
||||
<div class="mp-card__detail">
|
||||
<div class="mp-card__title" style="margin-bottom: unset">
|
||||
{{ title }}
|
||||
</div>
|
||||
<div class="avue-card__info" style="height: unset">
|
||||
<div class="mp-card__info" style="height: unset">
|
||||
{{ description }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -6,9 +6,7 @@
|
||||
① 代码优化,补充注释,提升阅读性
|
||||
-->
|
||||
<script lang="ts" setup>
|
||||
import { ElImage } from 'element-plus';
|
||||
|
||||
defineOptions({ name: 'News' });
|
||||
defineOptions({ name: 'WxNews' });
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
@@ -31,7 +29,7 @@ defineExpose({
|
||||
<a v-if="index === 0" :href="article.url" target="_blank">
|
||||
<div class="news-main">
|
||||
<div class="news-content">
|
||||
<ElImage
|
||||
<el-image
|
||||
:src="article.picUrl || article.thumbUrl"
|
||||
class="material-img"
|
||||
style="width: 100%; height: 120px"
|
||||
@@ -48,7 +46,7 @@ defineExpose({
|
||||
<div class="news-content-item">
|
||||
<div class="news-content-item-title">{{ article.title }}</div>
|
||||
<div class="news-content-item-img">
|
||||
<ElImage
|
||||
<img
|
||||
:src="article.picUrl || article.thumbUrl"
|
||||
class="material-img"
|
||||
height="100%"
|
||||
|
||||
@@ -239,7 +239,9 @@ onMounted(async () => {
|
||||
|
||||
<template>
|
||||
<Page auto-content-height>
|
||||
<DocAlert title="公众号图文" url="https://doc.iocoder.cn/mp/article/" />
|
||||
<template #doc>
|
||||
<DocAlert title="公众号图文" url="https://doc.iocoder.cn/mp/article/" />
|
||||
</template>
|
||||
|
||||
<FormModal
|
||||
@success="
|
||||
|
||||
116
apps/web-ele/src/views/mp/modules/wx-msg/card.scss
Normal file
116
apps/web-ele/src/views/mp/modules/wx-msg/card.scss
Normal file
@@ -0,0 +1,116 @@
|
||||
.mp-card {
|
||||
&__item {
|
||||
box-sizing: border-box;
|
||||
height: 200px;
|
||||
margin-bottom: 16px;
|
||||
font-size: 14px;
|
||||
font-feature-settings: 'tnum';
|
||||
font-variant: tabular-nums;
|
||||
line-height: 1.5;
|
||||
color: rgb(0 0 0 / 65%);
|
||||
cursor: pointer;
|
||||
list-style: none;
|
||||
background-color: #fff;
|
||||
border: 1px solid #e8e8e8;
|
||||
|
||||
&:hover {
|
||||
border-color: rgb(0 0 0 / 9%);
|
||||
box-shadow: 0 2px 8px rgb(0 0 0 / 9%);
|
||||
}
|
||||
|
||||
&--add {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
font-size: 16px;
|
||||
color: rgb(0 0 0 / 45%);
|
||||
background-color: #fff;
|
||||
border: 1px dashed #000;
|
||||
border-color: #d9d9d9;
|
||||
border-radius: 2px;
|
||||
|
||||
i {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: #40a9ff;
|
||||
background-color: #fff;
|
||||
border-color: #40a9ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__body {
|
||||
display: flex;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
&__detail {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
&__avatar {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
margin-right: 12px;
|
||||
overflow: hidden;
|
||||
border-radius: 48px;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&__title {
|
||||
margin-bottom: 12px;
|
||||
font-size: 16px;
|
||||
color: rgb(0 0 0 / 85%);
|
||||
|
||||
&:hover {
|
||||
color: #1890ff;
|
||||
}
|
||||
}
|
||||
|
||||
&__info {
|
||||
display: -webkit-box;
|
||||
height: 64px;
|
||||
overflow: hidden;
|
||||
-webkit-line-clamp: 3;
|
||||
color: rgb(0 0 0 / 45%);
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
&__menu {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
color: rgb(0 0 0 / 45%);
|
||||
text-align: center;
|
||||
background: #f7f9fa;
|
||||
|
||||
&:hover {
|
||||
color: #1890ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** joolun 额外加的 */
|
||||
.mp-comment__main {
|
||||
flex: unset !important;
|
||||
margin: 0 8px !important;
|
||||
border-radius: 5px !important;
|
||||
}
|
||||
|
||||
.mp-comment__header {
|
||||
border-top-left-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
}
|
||||
|
||||
.mp-comment__body {
|
||||
border-bottom-right-radius: 5px;
|
||||
border-bottom-left-radius: 5px;
|
||||
}
|
||||
109
apps/web-ele/src/views/mp/modules/wx-msg/comment.scss
Normal file
109
apps/web-ele/src/views/mp/modules/wx-msg/comment.scss
Normal file
@@ -0,0 +1,109 @@
|
||||
/* 来自 https://github.com/nmxiaowei/avue/blob/master/styles/src/element-ui/comment.scss */
|
||||
.mp-comment {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 30px;
|
||||
|
||||
&--reverse {
|
||||
flex-direction: row-reverse;
|
||||
|
||||
.mp-comment__main {
|
||||
&::before,
|
||||
&::after {
|
||||
right: -8px;
|
||||
left: auto;
|
||||
border-width: 8px 0 8px 8px;
|
||||
}
|
||||
|
||||
&::before {
|
||||
border-left-color: #dedede;
|
||||
}
|
||||
|
||||
&::after {
|
||||
margin-right: 1px;
|
||||
margin-left: auto;
|
||||
border-left-color: #f8f8f8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__avatar {
|
||||
box-sizing: border-box;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
vertical-align: middle;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 5px 15px;
|
||||
background: #f8f8f8;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
&__author {
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
&__main {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
margin: 0 20px;
|
||||
border: 1px solid #dedede;
|
||||
border-radius: 2px;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 100%;
|
||||
left: -8px;
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
pointer-events: none;
|
||||
content: ' ';
|
||||
border-color: transparent;
|
||||
border-style: solid solid outset;
|
||||
border-width: 8px 8px 8px 0;
|
||||
}
|
||||
|
||||
&::before {
|
||||
z-index: 1;
|
||||
border-right-color: #dedede;
|
||||
}
|
||||
|
||||
&::after {
|
||||
z-index: 2;
|
||||
margin-left: 1px;
|
||||
border-right-color: #f8f8f8;
|
||||
}
|
||||
}
|
||||
|
||||
&__body {
|
||||
padding: 15px;
|
||||
overflow: hidden;
|
||||
font-family:
|
||||
'Segoe UI', 'Lucida Grande', Helvetica, Arial, 'Microsoft YaHei',
|
||||
FreeSans, Arimo, 'Droid Sans', 'wenquanyi micro hei', 'Hiragino Sans GB',
|
||||
'Hiragino Sans GB W3', FontAwesome, sans-serif;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
padding: 1px 0 1px 15px;
|
||||
margin: 0;
|
||||
font-family:
|
||||
Georgia, 'Times New Roman', Times, Kai, 'Kaiti SC', KaiTi, BiauKai,
|
||||
FontAwesome, serif;
|
||||
border-left: 4px solid #ddd;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user