feat: 首页顶部的搭建
This commit is contained in:
122
src/pages/Home/components/HomeWelcome.vue
Normal file
122
src/pages/Home/components/HomeWelcome.vue
Normal file
@@ -0,0 +1,122 @@
|
||||
<template>
|
||||
<view class="flex border-box w-full">
|
||||
<SpriteAnimator
|
||||
:src="spriteStyle.ipLargeImage"
|
||||
:frameWidth="spriteStyle.frameWidth"
|
||||
:frameHeight="spriteStyle.frameHeight"
|
||||
:totalFrames="spriteStyle.totalFrames"
|
||||
:columns="spriteStyle.columns"
|
||||
:displayWidth="spriteStyle.displayWidth"
|
||||
:fps="16"
|
||||
/>
|
||||
|
||||
<view class="flex flex-col flex-full">
|
||||
<view class="flex flex-row flex-items-center flex-justify-between">
|
||||
<text class="font-size-20 font-500 color-white"> 小七欢迎你~ </text>
|
||||
<text class="font-size-20 font-500 color-white mt-4"> 26°C ☀️ </text>
|
||||
</view>
|
||||
|
||||
<swiper
|
||||
@change="onSwiperChange"
|
||||
class="swiper"
|
||||
circular
|
||||
:autoplay="autoplay"
|
||||
:interval="interval"
|
||||
:duration="duration"
|
||||
:indicator-dots="false"
|
||||
>
|
||||
<swiper-item v-for="item in bannerList" :key="item.title">
|
||||
<view
|
||||
class="swiper-item flex flex-col flex-items-start flex-justify-between px-10"
|
||||
>
|
||||
<text class="font-size-12 font-600 color-B45309">
|
||||
{{ item.title }}
|
||||
</text>
|
||||
<view class="flex flex-row flex-justify-between">
|
||||
<text class="font-size-10 font-500 color-D97706">
|
||||
发布时间:{{ item.time }}
|
||||
</text>
|
||||
<text class="font-size-10 font-500 color-B45309 underline-text">
|
||||
详情
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
|
||||
<yo-indicator-dot
|
||||
:current-index="currentIndex"
|
||||
:length="bannerList.length"
|
||||
:duration="duration"
|
||||
default-width="4px"
|
||||
active-width="16px"
|
||||
dot-height="4px"
|
||||
shape="circle"
|
||||
default-color="rgba(255,255,255,0.5)"
|
||||
active-color="rgba(255,255,255,1)"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import { defineProps, computed } from "vue";
|
||||
import SpriteAnimator from "@/components/Sprite/SpriteAnimator.vue";
|
||||
|
||||
const autoplay = ref(true);
|
||||
const interval = ref(7000);
|
||||
const duration = ref(500);
|
||||
|
||||
const currentIndex = ref(0);
|
||||
const bannerList = ref([
|
||||
{
|
||||
title: "小七欢迎你~",
|
||||
time: "2025年7月12日 09:30",
|
||||
},
|
||||
{
|
||||
title: "小8欢迎你~",
|
||||
time: "2025年7月13日 09:30",
|
||||
},
|
||||
{
|
||||
title: "小9欢迎你~",
|
||||
time: "2025年7月15日 09:30",
|
||||
},
|
||||
]);
|
||||
|
||||
const spriteStyle = computed(() => {
|
||||
return {
|
||||
ipLargeImage:
|
||||
"https://one-feel-image-bucket.oss-cn-chengdu.aliyuncs.com/onefeel/2045694865984802818.webp",
|
||||
frameWidth: 353,
|
||||
frameHeight: 353,
|
||||
totalFrames: 96,
|
||||
columns: 10,
|
||||
displayWidth: 105,
|
||||
};
|
||||
});
|
||||
|
||||
const onSwiperChange = (e) => {
|
||||
currentIndex.value = e.detail.current;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.swiper {
|
||||
height: 50px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.swiper-item {
|
||||
display: block;
|
||||
height: 46px;
|
||||
background: #fffbeb;
|
||||
box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.05);
|
||||
border-radius: 12px;
|
||||
border: 2px solid #fef3c7;
|
||||
}
|
||||
|
||||
.underline-text {
|
||||
text-decoration: underline;
|
||||
text-decoration-color: #b45309;
|
||||
}
|
||||
</style>
|
||||
@@ -1,35 +1,54 @@
|
||||
<template>
|
||||
<view class="relative flex flex-col h-screen">
|
||||
<view class="absolute top-0 left-0 w-full z-10" :style="{ paddingTop: statusBarHeight + 'px' }">
|
||||
<view
|
||||
class="absolute top-0 left-0 w-full z-10"
|
||||
:style="{ paddingTop: statusBarHeight + 'px' }"
|
||||
>
|
||||
<HomeNavBar />
|
||||
</view>
|
||||
|
||||
<view class="content relative flex-1">
|
||||
<view class="relative flex-full">
|
||||
<view class="relative">
|
||||
<image class="w-full" src="https://images.unsplash.com/photo-1506744038136-46273834b3fb?w=800&q=80"
|
||||
mode="widthFix" />
|
||||
<view class="absolute bottom-0 left-0 right-0 w-full head-content ">
|
||||
|
||||
<image
|
||||
class="w-full block"
|
||||
src="https://images.unsplash.com/photo-1506744038136-46273834b3fb?w=800&q=80"
|
||||
mode="widthFix"
|
||||
/>
|
||||
<view
|
||||
class="absolute bottom-0 left-0 right-0 flex-full px-12 pt-12 pb-4"
|
||||
>
|
||||
<HomeWelcome />
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<AiTabSwitch v-model="tabIndex" :list="['探索发现', 'AI伴游']" @change="handleChange" />
|
||||
|
||||
<AiTabSwitch
|
||||
v-model="tabIndex"
|
||||
:list="['探索发现', 'AI伴游']"
|
||||
@change="handleChange"
|
||||
/>
|
||||
|
||||
<view>
|
||||
<view class="absolute top-0 left-0 w-full h-full flex flex-col items-center justify-center">
|
||||
<text class="font-size-24 font-bold color-white mb-4">欢迎来到AI助手</text>
|
||||
<text class="font-size-16 color-white mb-8">您的智能聊天伴侣,随时为您提供帮助</text>
|
||||
<view
|
||||
class="absolute top-0 left-0 w-full h-full flex flex-col items-center justify-center"
|
||||
>
|
||||
<text class="font-size-24 font-bold color-white mb-4"
|
||||
>欢迎来到AI助手</text
|
||||
>
|
||||
<text class="font-size-16 color-white mb-8"
|
||||
>您的智能聊天伴侣,随时为您提供帮助</text
|
||||
>
|
||||
<view class="flex space-x-4">
|
||||
<view class="px-6 py-2 bg-green-500 text-white rounded-lg">开始聊天</view>
|
||||
<view class="px-6 py-2 bg-gray-300 text-gray-700 rounded-lg">了解更多</view>
|
||||
<view class="px-6 py-2 bg-green-500 text-white rounded-lg"
|
||||
>开始聊天</view
|
||||
>
|
||||
<view class="px-6 py-2 bg-gray-300 text-gray-700 rounded-lg"
|
||||
>了解更多</view
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
@@ -37,10 +56,10 @@ import { ref } from "vue";
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
|
||||
import HomeNavBar from "./components/HomeNavBar.vue";
|
||||
import HomeWelcome from "./components/HomeWelcome.vue";
|
||||
|
||||
import AiTabSwitch from "@/components/AiTabSwitch/index.vue";
|
||||
|
||||
|
||||
const tabIndex = ref(0);
|
||||
|
||||
const handleChange = (i) => {
|
||||
@@ -58,18 +77,10 @@ onLoad(() => {
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped>
|
||||
|
||||
.head-content {
|
||||
.bg-color {
|
||||
background: red;
|
||||
height: 104px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
@@ -56,6 +56,14 @@
|
||||
color: #fa7319;
|
||||
}
|
||||
|
||||
.color-B45309 {
|
||||
color: #b45309;
|
||||
}
|
||||
|
||||
.color-D97706 {
|
||||
color: #d97706;
|
||||
}
|
||||
|
||||
// text 颜色
|
||||
.text-color-900 {
|
||||
color: $text-color-900; // #181B25
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
|
||||
|
||||
.p-6 {
|
||||
padding: 6px;
|
||||
}
|
||||
@@ -88,7 +87,6 @@
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
|
||||
|
||||
.p-8 {
|
||||
padding: 8px;
|
||||
}
|
||||
@@ -149,7 +147,6 @@
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
|
||||
.p-12 {
|
||||
padding: 12px;
|
||||
}
|
||||
@@ -204,7 +201,6 @@
|
||||
padding-bottom: 14px;
|
||||
}
|
||||
|
||||
|
||||
.p-16 {
|
||||
padding: 16px;
|
||||
}
|
||||
@@ -235,7 +231,6 @@
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
|
||||
.p-20 {
|
||||
padding: 20px;
|
||||
}
|
||||
@@ -266,7 +261,6 @@
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
|
||||
.p-24 {
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
27
src/uni_modules/yo-indicator-dot/changelog.md
Normal file
27
src/uni_modules/yo-indicator-dot/changelog.md
Normal file
@@ -0,0 +1,27 @@
|
||||
## 2.0.0(2025-10-09)
|
||||
### ✨ 新功能
|
||||
- 新增多种显示模式:dots(点状)、numbers(数字)、progress(进度条)、thumbnails(缩略图)
|
||||
- 新增多种形状:circle(圆形)、square(方形)、diamond(菱形)、bar(条形)、custom(自定义)
|
||||
- 新增丰富动画效果:scale(缩放)、rotate(旋转)、bounce(弹性)、pulse(脉冲)、fade(淡入淡出)、none(无动画)
|
||||
- 新增位置布局选项:top(顶部)、bottom(底部)、left(左侧)、right(右侧)、inside(内嵌)
|
||||
- 新增交互功能:点击跳转、悬停效果
|
||||
- 新增事件支持:change、click、hover
|
||||
- 新增插槽支持:indicator、thumbnail
|
||||
|
||||
### 🔧 改进
|
||||
- 保持向后兼容,现有代码无需修改
|
||||
- 优化API设计,支持渐进式增强
|
||||
- 完善响应式设计,适配各种屏幕尺寸
|
||||
- 增强无障碍支持
|
||||
|
||||
### 📚 文档
|
||||
- 完善使用文档和API说明
|
||||
- 新增丰富的演示示例
|
||||
- 提供使用技巧和最佳实践
|
||||
## 1.0.0(2025-09-11)
|
||||
|
||||
### 🎉 初始版本
|
||||
- 基础点状指示器功能
|
||||
- 支持自定义颜色和尺寸
|
||||
- 支持平滑过渡动画
|
||||
- 支持所有UniApp平台
|
||||
@@ -0,0 +1,516 @@
|
||||
<template>
|
||||
<view
|
||||
class="yo-indicator-dot"
|
||||
:class="[
|
||||
`yo-indicator-dot--${position}`,
|
||||
`yo-indicator-dot--${mode}`,
|
||||
{ 'yo-indicator-dot--clickable': clickable }
|
||||
]"
|
||||
:style="containerStyle"
|
||||
>
|
||||
<!-- 点状指示器 -->
|
||||
<template v-if="mode === 'dots'">
|
||||
<view
|
||||
v-for="(item, index) in length"
|
||||
:key="index"
|
||||
class="indicator-dot"
|
||||
:class="[
|
||||
`indicator-dot--${shape}`,
|
||||
`indicator-dot--${animation}`,
|
||||
{ active: index === currentIndex }
|
||||
]"
|
||||
:style="getDotStyle(index)"
|
||||
@click="handleDotClick(index)"
|
||||
@mouseenter="handleDotHover(index, true)"
|
||||
@mouseleave="handleDotHover(index, false)"
|
||||
>
|
||||
<!-- 自定义形状内容 -->
|
||||
<view v-if="shape === 'custom' && customContent" class="indicator-custom">
|
||||
<slot name="indicator" :index="index" :isActive="index === currentIndex">
|
||||
<text class="indicator-text">{{ index + 1 }}</text>
|
||||
</slot>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<!-- 数字指示器 -->
|
||||
<template v-else-if="mode === 'numbers'">
|
||||
<view class="indicator-numbers">
|
||||
<text class="numbers-text">{{ currentIndex + 1 }} / {{ length }}</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<!-- 进度条指示器 -->
|
||||
<template v-else-if="mode === 'progress'">
|
||||
<view class="indicator-progress">
|
||||
<view class="progress-track" :style="progressTrackStyle">
|
||||
<view
|
||||
class="progress-fill"
|
||||
:style="progressFillStyle"
|
||||
></view>
|
||||
</view>
|
||||
<text class="progress-text">{{ Math.round(progressPercentage) }}%</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<!-- 缩略图指示器 -->
|
||||
<template v-else-if="mode === 'thumbnails'">
|
||||
<view class="indicator-thumbnails">
|
||||
<view
|
||||
v-for="(item, index) in length"
|
||||
:key="index"
|
||||
class="indicator-thumbnail"
|
||||
:class="{ active: index === currentIndex }"
|
||||
@click="handleDotClick(index)"
|
||||
>
|
||||
<slot name="thumbnail" :index="index" :isActive="index === currentIndex">
|
||||
<view class="thumbnail-placeholder">{{ index + 1 }}</view>
|
||||
</slot>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineProps, defineEmits, computed, ref } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
// === 基础参数(保持向后兼容) ===
|
||||
// 当前轮播的下标
|
||||
currentIndex: {
|
||||
type: Number,
|
||||
required: true,
|
||||
default: 0
|
||||
},
|
||||
// 轮播数据的长度
|
||||
length: {
|
||||
type: Number,
|
||||
required: true,
|
||||
default: 0
|
||||
},
|
||||
// 默认指示点的颜色
|
||||
defaultColor: {
|
||||
type: String,
|
||||
default: '#cccccc'
|
||||
},
|
||||
// 选中指示点的颜色
|
||||
activeColor: {
|
||||
type: String,
|
||||
default: '#007aff'
|
||||
},
|
||||
// 默认指示点宽度
|
||||
defaultWidth: {
|
||||
type: String,
|
||||
default: '12rpx'
|
||||
},
|
||||
// 选中指示点宽度
|
||||
activeWidth: {
|
||||
type: String,
|
||||
default: '20rpx'
|
||||
},
|
||||
// 指示点高度
|
||||
dotHeight: {
|
||||
type: String,
|
||||
default: '12rpx'
|
||||
},
|
||||
// 指示点间距
|
||||
gap: {
|
||||
type: String,
|
||||
default: '12rpx'
|
||||
},
|
||||
// 动画持续时间
|
||||
duration: {
|
||||
type: String,
|
||||
default: '0.3s'
|
||||
},
|
||||
|
||||
// === 新增功能参数(简单易用) ===
|
||||
// 显示模式:dots(点状) | numbers(数字) | progress(进度条) | thumbnails(缩略图)
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'dots',
|
||||
validator: value => ['dots', 'numbers', 'progress', 'thumbnails'].includes(value)
|
||||
},
|
||||
// 指示器形状:circle(圆形) | square(方形) | diamond(菱形) | bar(条形) | custom(自定义)
|
||||
shape: {
|
||||
type: String,
|
||||
default: 'circle',
|
||||
validator: value => ['circle', 'square', 'diamond', 'bar', 'custom'].includes(value)
|
||||
},
|
||||
// 动画效果:scale(缩放) | rotate(旋转) | bounce(弹性) | pulse(脉冲) | fade(淡入淡出)
|
||||
animation: {
|
||||
type: String,
|
||||
default: 'scale',
|
||||
validator: value => ['scale', 'rotate', 'bounce', 'pulse', 'fade', 'none'].includes(value)
|
||||
},
|
||||
// 位置:top(顶部) | bottom(底部) | left(左侧) | right(右侧) | inside(内嵌)
|
||||
position: {
|
||||
type: String,
|
||||
default: 'bottom',
|
||||
validator: value => ['top', 'bottom', 'left', 'right', 'inside'].includes(value)
|
||||
},
|
||||
// 是否可点击
|
||||
clickable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 是否显示悬停效果
|
||||
hoverable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 自定义内容(用于custom形状)
|
||||
customContent: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 进度条高度(progress模式)
|
||||
progressHeight: {
|
||||
type: String,
|
||||
default: '6rpx'
|
||||
},
|
||||
// 缩略图尺寸(thumbnails模式)
|
||||
thumbnailSize: {
|
||||
type: String,
|
||||
default: '60rpx'
|
||||
}
|
||||
})
|
||||
|
||||
// 事件定义
|
||||
const emit = defineEmits(['change', 'click', 'hover'])
|
||||
|
||||
// 响应式数据
|
||||
const hoveredIndex = ref(-1)
|
||||
|
||||
// 计算属性
|
||||
const progressPercentage = computed(() => {
|
||||
if (props.length === 0) return 0
|
||||
return ((props.currentIndex + 1) / props.length) * 100
|
||||
})
|
||||
|
||||
const containerStyle = computed(() => {
|
||||
const styles = {}
|
||||
|
||||
// 位置样式
|
||||
if (props.position === 'left' || props.position === 'right') {
|
||||
styles.flexDirection = 'column'
|
||||
styles.gap = props.gap
|
||||
} else {
|
||||
styles.gap = props.gap
|
||||
}
|
||||
|
||||
return styles
|
||||
})
|
||||
|
||||
const progressTrackStyle = computed(() => ({
|
||||
height: props.progressHeight,
|
||||
backgroundColor: props.defaultColor,
|
||||
borderRadius: props.progressHeight
|
||||
}))
|
||||
|
||||
const progressFillStyle = computed(() => ({
|
||||
height: '100%',
|
||||
width: `${progressPercentage.value}%`,
|
||||
backgroundColor: props.activeColor,
|
||||
borderRadius: props.progressHeight,
|
||||
transition: `width ${props.duration} ease`
|
||||
}))
|
||||
|
||||
// 方法
|
||||
const getDotStyle = (index) => {
|
||||
const isActive = index === props.currentIndex
|
||||
const isHovered = props.hoverable && hoveredIndex.value === index
|
||||
|
||||
const style = {
|
||||
backgroundColor: isActive ? props.activeColor : props.defaultColor,
|
||||
width: isActive ? props.activeWidth : props.defaultWidth,
|
||||
height: props.dotHeight,
|
||||
transition: `all ${props.duration} ease`
|
||||
}
|
||||
|
||||
// 智能形状调整:当宽度和高度差异较大时,自动使用条形样式
|
||||
const defaultWidthNum = parseFloat(props.defaultWidth)
|
||||
const activeWidthNum = parseFloat(props.activeWidth)
|
||||
const heightNum = parseFloat(props.dotHeight)
|
||||
|
||||
// 如果宽度是高度的2倍以上,使用条形样式
|
||||
if (activeWidthNum / heightNum >= 2 || defaultWidthNum / heightNum >= 2) {
|
||||
style.borderRadius = `${heightNum / 2}rpx`
|
||||
}
|
||||
|
||||
// 悬停效果
|
||||
if (isHovered && !isActive) {
|
||||
style.backgroundColor = props.activeColor
|
||||
style.opacity = '0.7'
|
||||
}
|
||||
|
||||
return style
|
||||
}
|
||||
|
||||
const handleDotClick = (index) => {
|
||||
if (!props.clickable) return
|
||||
|
||||
emit('click', index)
|
||||
if (index !== props.currentIndex) {
|
||||
emit('change', index)
|
||||
}
|
||||
}
|
||||
|
||||
const handleDotHover = (index, isHover) => {
|
||||
if (!props.hoverable) return
|
||||
|
||||
hoveredIndex.value = isHover ? index : -1
|
||||
emit('hover', { index, isHover })
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* === 基础容器样式 === */
|
||||
.yo-indicator-dot {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* === 位置样式 === */
|
||||
.yo-indicator-dot--top {
|
||||
order: -1;
|
||||
}
|
||||
|
||||
.yo-indicator-dot--bottom {
|
||||
order: 1;
|
||||
}
|
||||
|
||||
.yo-indicator-dot--left {
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
|
||||
.yo-indicator-dot--right {
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: flex-end;
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
|
||||
.yo-indicator-dot--inside {
|
||||
position: absolute;
|
||||
bottom: 20rpx;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
padding: 10rpx 20rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
/* === 点状指示器样式 === */
|
||||
.indicator-dot {
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
transition: all v-bind(duration) ease;
|
||||
}
|
||||
|
||||
/* 形状样式 */
|
||||
.indicator-dot--circle {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.indicator-dot--square {
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.indicator-dot--diamond {
|
||||
border-radius: 0;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.indicator-dot--bar {
|
||||
border-radius: 6rpx;
|
||||
}
|
||||
|
||||
.indicator-dot--custom {
|
||||
border-radius: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* 动画效果 */
|
||||
.indicator-dot--scale.active {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
.indicator-dot--rotate.active {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.indicator-dot--bounce.active {
|
||||
animation: bounce 0.6s ease;
|
||||
}
|
||||
|
||||
.indicator-dot--pulse.active {
|
||||
animation: pulse 2s infinite;
|
||||
}
|
||||
|
||||
.indicator-dot--fade.active {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.indicator-dot--fade:not(.active) {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.indicator-dot--none {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
/* 悬停效果 */
|
||||
.yo-indicator-dot--clickable .indicator-dot:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
/* === 数字指示器样式 === */
|
||||
.indicator-numbers {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.numbers-text {
|
||||
font-size: 28rpx;
|
||||
color: v-bind(activeColor);
|
||||
font-weight: 500;
|
||||
padding: 8rpx 16rpx;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
/* === 进度条指示器样式 === */
|
||||
.indicator-progress {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.progress-track {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.progress-fill {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.progress-text {
|
||||
font-size: 24rpx;
|
||||
color: v-bind(activeColor);
|
||||
font-weight: 500;
|
||||
min-width: 60rpx;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* === 缩略图指示器样式 === */
|
||||
.indicator-thumbnails {
|
||||
display: flex;
|
||||
gap: 12rpx;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.indicator-thumbnail {
|
||||
width: v-bind(thumbnailSize);
|
||||
height: v-bind(thumbnailSize);
|
||||
border-radius: 8rpx;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
border: 2rpx solid transparent;
|
||||
transition: all v-bind(duration) ease;
|
||||
}
|
||||
|
||||
.indicator-thumbnail.active {
|
||||
border-color: v-bind(activeColor);
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.thumbnail-placeholder {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: v-bind(defaultColor);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 20rpx;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* === 自定义内容样式 === */
|
||||
.indicator-custom {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.indicator-text {
|
||||
font-size: 20rpx;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* === 动画关键帧 === */
|
||||
@keyframes bounce {
|
||||
0%, 20%, 53%, 80%, 100% {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
40%, 43% {
|
||||
transform: translate3d(0, -8rpx, 0);
|
||||
}
|
||||
70% {
|
||||
transform: translate3d(0, -4rpx, 0);
|
||||
}
|
||||
90% {
|
||||
transform: translate3d(0, -2rpx, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0% {
|
||||
box-shadow: 0 0 0 0 rgba(0, 123, 255, 0.7);
|
||||
}
|
||||
70% {
|
||||
box-shadow: 0 0 0 10rpx rgba(0, 123, 255, 0);
|
||||
}
|
||||
100% {
|
||||
box-shadow: 0 0 0 0 rgba(0, 123, 255, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* === 响应式设计 === */
|
||||
@media screen and (max-width: 750rpx) {
|
||||
.yo-indicator-dot--inside {
|
||||
bottom: 10rpx;
|
||||
padding: 8rpx 16rpx;
|
||||
}
|
||||
|
||||
.numbers-text {
|
||||
font-size: 24rpx;
|
||||
padding: 6rpx 12rpx;
|
||||
}
|
||||
|
||||
.progress-text {
|
||||
font-size: 20rpx;
|
||||
min-width: 50rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
101
src/uni_modules/yo-indicator-dot/package.json
Normal file
101
src/uni_modules/yo-indicator-dot/package.json
Normal file
@@ -0,0 +1,101 @@
|
||||
{
|
||||
"id": "yo-indicator-dot",
|
||||
"displayName": "轮播指示器组件",
|
||||
"version": "2.0.0",
|
||||
"description": "一个美观的uniapp轮播指示器组件,支持自定义颜色和平滑过渡动画",
|
||||
"keywords": [
|
||||
"uniapp",
|
||||
"轮播",
|
||||
"指示器",
|
||||
"indicator",
|
||||
"swiper"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.0.0",
|
||||
"uni-app": "^4.07",
|
||||
"uni-app-x": "^4.07"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": "",
|
||||
"darkmode": "x",
|
||||
"i18n": "x",
|
||||
"widescreen": "√"
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "√",
|
||||
"aliyun": "√",
|
||||
"alipay": "x"
|
||||
},
|
||||
"client": {
|
||||
"uni-app": {
|
||||
"vue": {
|
||||
"vue2": "√",
|
||||
"vue3": "√"
|
||||
},
|
||||
"web": {
|
||||
"safari": "√",
|
||||
"chrome": "√"
|
||||
},
|
||||
"app": {
|
||||
"vue": "√",
|
||||
"nvue": "√",
|
||||
"android": "√",
|
||||
"ios": "√",
|
||||
"harmony": "√"
|
||||
},
|
||||
"mp": {
|
||||
"weixin": "√",
|
||||
"alipay": "√",
|
||||
"toutiao": "√",
|
||||
"baidu": "√",
|
||||
"kuaishou": "√",
|
||||
"jd": "√",
|
||||
"harmony": "√",
|
||||
"qq": "√",
|
||||
"lark": "√"
|
||||
},
|
||||
"quickapp": {
|
||||
"huawei": "√",
|
||||
"union": "√"
|
||||
}
|
||||
},
|
||||
"uni-app-x": {
|
||||
"web": {
|
||||
"safari": "-",
|
||||
"chrome": "-"
|
||||
},
|
||||
"app": {
|
||||
"android": "-",
|
||||
"ios": "-",
|
||||
"harmony": "-"
|
||||
},
|
||||
"mp": {
|
||||
"weixin": "-"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
299
src/uni_modules/yo-indicator-dot/readme.md
Normal file
299
src/uni_modules/yo-indicator-dot/readme.md
Normal file
@@ -0,0 +1,299 @@
|
||||
# yo-indicator-dot
|
||||
|
||||
🚀 功能强大的轮播指示器组件,支持多种显示模式、形状和动画效果
|
||||
|
||||
## ✨ 功能特点
|
||||
|
||||
- 🎯 **零配置开箱即用** - 不传任何参数就能正常工作
|
||||
- 🎨 **多种显示模式** - 点状、数字、进度条、缩略图
|
||||
- 🔷 **多种形状** - 圆形、方形、菱形、条形、自定义
|
||||
- ⚡️ **丰富动画** - 缩放、旋转、弹性、脉冲、淡入淡出
|
||||
- 📍 **灵活位置** - 顶部、底部、左侧、右侧、内嵌
|
||||
- 🖱️ **交互功能** - 点击跳转、悬停效果
|
||||
- 📱 **全平台支持** - H5、小程序、App
|
||||
- 🔄 **向后兼容** - 现有代码升级无压力
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
### 1. 安装
|
||||
|
||||
通过 HBuilderX 插件市场安装:
|
||||
|
||||
1. 打开 HBuilderX
|
||||
2. 点击菜单栏 `工具` → `插件安装`
|
||||
3. 搜索 `yo-indicator-dot` 并安装
|
||||
4. 或直接下载 uni_modules 文件夹到项目中
|
||||
|
||||
### 2. 基础使用
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<view>
|
||||
<swiper @change="onSwiperChange" indicator-dots="false">
|
||||
<swiper-item v-for="(item, index) in bannerList" :key="index">
|
||||
<view>{{ item.title }}</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
|
||||
<!-- 最简单的使用方式 -->
|
||||
<yo-indicator-dot
|
||||
:current-index="currentIndex"
|
||||
:length="bannerList.length"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
const currentIndex = ref(0)
|
||||
const bannerList = ref([
|
||||
{ title: '轮播图 1' },
|
||||
{ title: '轮播图 2' },
|
||||
{ title: '轮播图 3' }
|
||||
])
|
||||
|
||||
const onSwiperChange = (e) => {
|
||||
currentIndex.value = e.detail.current
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
## 🎨 显示模式
|
||||
|
||||
### 点状模式(默认)
|
||||
```vue
|
||||
<yo-indicator-dot
|
||||
:current-index="currentIndex"
|
||||
:length="length"
|
||||
mode="dots"
|
||||
shape="circle"
|
||||
animation="scale"
|
||||
/>
|
||||
```
|
||||
|
||||
### 数字模式
|
||||
```vue
|
||||
<yo-indicator-dot
|
||||
:current-index="currentIndex"
|
||||
:length="length"
|
||||
mode="numbers"
|
||||
active-color="#00cc66"
|
||||
/>
|
||||
```
|
||||
|
||||
### 进度条模式
|
||||
```vue
|
||||
<yo-indicator-dot
|
||||
:current-index="currentIndex"
|
||||
:length="length"
|
||||
mode="progress"
|
||||
default-color="#e5e5e5"
|
||||
active-color="#ff6b6b"
|
||||
progress-height="8rpx"
|
||||
/>
|
||||
```
|
||||
|
||||
### 缩略图模式
|
||||
```vue
|
||||
<yo-indicator-dot
|
||||
:current-index="currentIndex"
|
||||
:length="length"
|
||||
mode="thumbnails"
|
||||
thumbnail-size="60rpx"
|
||||
>
|
||||
<template #thumbnail="{ index, isActive }">
|
||||
<image :src="thumbnails[index]" />
|
||||
</template>
|
||||
</yo-indicator-dot>
|
||||
```
|
||||
|
||||
## 🔷 形状样式
|
||||
|
||||
```vue
|
||||
<!-- 圆形(默认) -->
|
||||
<yo-indicator-dot shape="circle" />
|
||||
|
||||
<!-- 方形 -->
|
||||
<yo-indicator-dot shape="square" />
|
||||
|
||||
<!-- 菱形 -->
|
||||
<yo-indicator-dot shape="diamond" />
|
||||
|
||||
<!-- 条形 -->
|
||||
<yo-indicator-dot shape="bar" />
|
||||
|
||||
<!-- 自定义 -->
|
||||
<yo-indicator-dot shape="custom" custom-content>
|
||||
<template #indicator="{ index, isActive }">
|
||||
<text>{{ index + 1 }}</text>
|
||||
</template>
|
||||
</yo-indicator-dot>
|
||||
```
|
||||
|
||||
## ⚡️ 动画效果
|
||||
|
||||
```vue
|
||||
<!-- 缩放动画(默认) -->
|
||||
<yo-indicator-dot animation="scale" />
|
||||
|
||||
<!-- 旋转动画 -->
|
||||
<yo-indicator-dot animation="rotate" />
|
||||
|
||||
<!-- 弹性动画 -->
|
||||
<yo-indicator-dot animation="bounce" />
|
||||
|
||||
<!-- 脉冲动画 -->
|
||||
<yo-indicator-dot animation="pulse" />
|
||||
|
||||
<!-- 淡入淡出 -->
|
||||
<yo-indicator-dot animation="fade" />
|
||||
|
||||
<!-- 无动画 -->
|
||||
<yo-indicator-dot animation="none" />
|
||||
```
|
||||
|
||||
## 📍 位置布局
|
||||
|
||||
```vue
|
||||
<!-- 底部(默认) -->
|
||||
<yo-indicator-dot position="bottom" />
|
||||
|
||||
<!-- 顶部 -->
|
||||
<yo-indicator-dot position="top" />
|
||||
|
||||
<!-- 左侧 -->
|
||||
<yo-indicator-dot position="left" />
|
||||
|
||||
<!-- 右侧 -->
|
||||
<yo-indicator-dot position="right" />
|
||||
|
||||
<!-- 内嵌 -->
|
||||
<yo-indicator-dot position="inside" />
|
||||
```
|
||||
|
||||
## 🖱️ 交互功能
|
||||
|
||||
```vue
|
||||
<yo-indicator-dot
|
||||
:current-index="currentIndex"
|
||||
:length="length"
|
||||
:clickable="true"
|
||||
:hoverable="true"
|
||||
@click="onIndicatorClick"
|
||||
@change="onIndicatorChange"
|
||||
@hover="onIndicatorHover"
|
||||
/>
|
||||
```
|
||||
|
||||
## 📋 完整参数
|
||||
|
||||
### 基础参数(向后兼容)
|
||||
|
||||
| 参数 | 类型 | 默认值 | 说明 |
|
||||
|------|------|--------|------|
|
||||
| current-index | Number | 0 | 当前轮播的下标 |
|
||||
| length | Number | 0 | 轮播数据的长度 |
|
||||
| default-color | String | #cccccc | 默认指示点的颜色 |
|
||||
| active-color | String | #007aff | 选中指示点的颜色 |
|
||||
| default-width | String | 12rpx | 默认指示点宽度 |
|
||||
| active-width | String | 20rpx | 选中指示点宽度 |
|
||||
| dot-height | String | 12rpx | 指示点高度 |
|
||||
| gap | String | 12rpx | 指示点间距 |
|
||||
| duration | String | 0.3s | 动画持续时间 |
|
||||
|
||||
> **💡 智能形状提示**: 当 `active-width` 或 `default-width` 是 `dot-height` 的2倍以上时,组件会自动使用条形样式,确保视觉效果更佳。
|
||||
|
||||
### 新增功能参数
|
||||
|
||||
| 参数 | 类型 | 默认值 | 说明 |
|
||||
|------|------|--------|------|
|
||||
| mode | String | dots | 显示模式:dots/numbers/progress/thumbnails |
|
||||
| shape | String | circle | 指示器形状:circle/square/diamond/bar/custom |
|
||||
| animation | String | scale | 动画效果:scale/rotate/bounce/pulse/fade/none |
|
||||
| position | String | bottom | 位置:top/bottom/left/right/inside |
|
||||
| clickable | Boolean | true | 是否可点击 |
|
||||
| hoverable | Boolean | true | 是否显示悬停效果 |
|
||||
| custom-content | Boolean | false | 自定义内容(用于custom形状) |
|
||||
| progress-height | String | 6rpx | 进度条高度(progress模式) |
|
||||
| thumbnail-size | String | 60rpx | 缩略图尺寸(thumbnails模式) |
|
||||
|
||||
## 🎯 事件
|
||||
|
||||
| 事件名 | 说明 | 参数 |
|
||||
|--------|------|------|
|
||||
| change | 指示器切换时触发 | index: 新的下标 |
|
||||
| click | 点击指示器时触发 | index: 点击的下标 |
|
||||
| hover | 悬停指示器时触发 | { index, isHover } |
|
||||
|
||||
## 🔧 插槽
|
||||
|
||||
| 插槽名 | 说明 | 参数 |
|
||||
|--------|------|------|
|
||||
| indicator | 自定义指示器内容 | { index, isActive } |
|
||||
| thumbnail | 自定义缩略图内容 | { index, isActive } |
|
||||
|
||||
## 💡 使用技巧
|
||||
|
||||
### 1. 渐进式增强
|
||||
```vue
|
||||
<!-- 基础使用 -->
|
||||
<yo-indicator-dot :current-index="index" :length="length" />
|
||||
|
||||
<!-- 需要更多功能时再添加参数 -->
|
||||
<yo-indicator-dot
|
||||
:current-index="index"
|
||||
:length="length"
|
||||
mode="numbers"
|
||||
animation="bounce"
|
||||
/>
|
||||
```
|
||||
|
||||
### 2. 主题定制
|
||||
```vue
|
||||
<yo-indicator-dot
|
||||
:current-index="index"
|
||||
:length="length"
|
||||
default-color="rgba(255,255,255,0.3)"
|
||||
active-color="rgba(255,255,255,0.9)"
|
||||
position="inside"
|
||||
/>
|
||||
```
|
||||
|
||||
### 3. 响应式设计
|
||||
```vue
|
||||
<yo-indicator-dot
|
||||
:current-index="index"
|
||||
:length="length"
|
||||
:gap="isMobile ? '8rpx' : '12rpx'"
|
||||
:dot-height="isMobile ? '8rpx' : '12rpx'"
|
||||
/>
|
||||
```
|
||||
|
||||
## 📱 平台支持
|
||||
|
||||
- ✅ H5(Safari、Chrome、Firefox)
|
||||
- ✅ App(Android、iOS、HarmonyOS)
|
||||
- ✅ 微信小程序、支付宝小程序、百度小程序
|
||||
- ✅ 字节跳动小程序、QQ小程序、快手小程序
|
||||
- ✅ 钉钉小程序、京东小程序
|
||||
|
||||
## 🔄 更新日志
|
||||
|
||||
### v2.0.0
|
||||
- ✨ 新增多种显示模式(数字、进度条、缩略图)
|
||||
- ✨ 新增多种形状(方形、菱形、条形、自定义)
|
||||
- ✨ 新增丰富动画效果
|
||||
- ✨ 新增位置布局选项
|
||||
- ✨ 新增交互功能(点击、悬停)
|
||||
- 🔧 保持向后兼容,现有代码无需修改
|
||||
- 📚 完善文档和演示
|
||||
|
||||
### v1.0.0
|
||||
- 🎉 初始版本发布
|
||||
- 基础点状指示器功能
|
||||
- 支持自定义颜色和尺寸
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
8
src/uni_modules/yo-indicator-dot/uni_modules.config.json
Normal file
8
src/uni_modules/yo-indicator-dot/uni_modules.config.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"easycom": {
|
||||
"autoscan": true,
|
||||
"custom": {
|
||||
"^yo-indicator-dot$": "@/uni_modules/yo-indicator-dot/components/yo-indicator-dot/yo-indicator-dot.vue"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user