Compare commits

..

2 Commits

Author SHA1 Message Date
前端小啊白 22dc129d8f Merge branch 'master' of http://123.60.153.169:3006/fucai/fucai-marriage-h5-register 2025-11-17 10:41:30 +08:00
前端小啊白 64d9f26c62 refactor: 移除Dialog组件及相关文件并调整页面背景样式
移除不再使用的Dialog组件及其相关文件(dialog.ts, Dialog.vue, loading.md),同时调整index.html和home页面的背景样式,将背景色统一设置为#FCEEF3
2025-11-17 10:41:27 +08:00
5 changed files with 2 additions and 719 deletions

View File

@ -1,5 +1,5 @@
<!doctype html>
<html lang="en">
<html lang="en" class="bg-[#FCEEF3]">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />

View File

@ -1,251 +0,0 @@
<template>
<Teleport to="body">
<Transition name="dialog">
<div v-if="visible" class="dialog-overlay" @click.self="handleOverlayClick">
<div class="dialog-container">
<!-- 对话框头部 -->
<div class="dialog-header" v-if="title || $slots.title">
<slot name="title">{{ title }}</slot>
<button v-if="closable" class="dialog-close" @click="handleClose">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 4L4 12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
<path d="M4 4L12 12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
</svg>
</button>
</div>
<!-- 对话框内容 -->
<div class="dialog-body">
<slot>{{ message }}</slot>
</div>
<!-- 对话框底部按钮区域 -->
<div class="dialog-footer" v-if="showFooter">
<slot name="footer">
<button v-if="showCancelButton" class="dialog-button dialog-button-cancel" @click="handleCancel">
{{ cancelButtonText }}
</button>
<button class="dialog-button dialog-button-confirm" @click="handleConfirm">
{{ confirmButtonText }}
</button>
</slot>
</div>
</div>
</div>
</Transition>
</Teleport>
</template>
<script setup lang="ts">
import { defineProps, defineEmits } from 'vue'
// Props
const props = defineProps({
//
visible: {
type: Boolean,
default: false
},
//
title: {
type: String,
default: ''
},
//
message: {
type: String,
default: ''
},
//
closable: {
type: Boolean,
default: true
},
//
showFooter: {
type: Boolean,
default: true
},
//
showCancelButton: {
type: Boolean,
default: true
},
//
confirmButtonText: {
type: String,
default: '确认'
},
//
cancelButtonText: {
type: String,
default: '取消'
},
//
closeOnClickOverlay: {
type: Boolean,
default: true
}
})
// Emits
const emit = defineEmits<{
//
close: []
//
confirm: []
//
cancel: []
}>()
//
const handleClose = () => {
emit('close')
}
//
const handleConfirm = () => {
emit('confirm')
}
//
const handleCancel = () => {
emit('cancel')
}
//
const handleOverlayClick = () => {
if (props.closeOnClickOverlay) {
emit('close')
}
}
</script>
<style scoped>
/* 遮罩层样式 */
.dialog-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}
/* 对话框容器样式 */
.dialog-container {
background-color: #ffffff;
border-radius: 8px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
width: 90%;
max-width: 500px;
max-height: 80vh;
overflow: hidden;
display: flex;
flex-direction: column;
}
/* 对话框头部样式 */
.dialog-header {
padding: 16px 20px;
border-bottom: 1px solid #f0f0f0;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 16px;
font-weight: 500;
color: #333;
}
/* 关闭按钮样式 */
.dialog-close {
background: none;
border: none;
padding: 4px;
cursor: pointer;
color: #999;
display: flex;
align-items: center;
justify-content: center;
transition: color 0.2s;
}
.dialog-close:hover {
color: #333;
}
/* 对话框内容样式 */
.dialog-body {
padding: 20px;
flex: 1;
overflow-y: auto;
color: #666;
line-height: 1.5;
}
/* 对话框底部样式 */
.dialog-footer {
padding: 16px 20px;
border-top: 1px solid #f0f0f0;
display: flex;
justify-content: flex-end;
gap: 12px;
}
/* 按钮样式 */
.dialog-button {
padding: 8px 16px;
border-radius: 4px;
border: none;
font-size: 14px;
cursor: pointer;
transition: all 0.2s;
outline: none;
}
.dialog-button-cancel {
background-color: #f5f5f5;
color: #666;
}
.dialog-button-cancel:hover {
background-color: #e8e8e8;
}
.dialog-button-confirm {
background-color: #1890ff;
color: #fff;
}
.dialog-button-confirm:hover {
background-color: #40a9ff;
}
/* 动画样式 */
.dialog-enter-active,
.dialog-leave-active {
transition: opacity 0.3s ease;
}
.dialog-enter-from,
.dialog-leave-to {
opacity: 0;
}
.dialog-enter-active .dialog-container,
.dialog-leave-active .dialog-container {
transition: transform 0.3s ease;
}
.dialog-enter-from .dialog-container {
transform: scale(0.9);
}
.dialog-leave-to .dialog-container {
transform: scale(0.9);
}
</style>

View File

@ -1,162 +0,0 @@
import { createApp, h, nextTick } from 'vue'
import Dialog from './Dialog.vue'
// 对话框配置接口
export interface DialogOptions {
// 对话框标题
title?: string
// 对话框内容
message?: string
// 是否显示关闭按钮
closable?: boolean
// 是否显示底部按钮区域
showFooter?: boolean
// 是否显示取消按钮
showCancelButton?: boolean
// 确认按钮文本
confirmButtonText?: string
// 取消按钮文本
cancelButtonText?: string
// 点击遮罩层是否可以关闭对话框
closeOnClickOverlay?: boolean
// 确认回调函数
onConfirm?: () => void
// 取消回调函数
onCancel?: () => void
// 关闭回调函数
onClose?: () => void
}
// Dialog 实例接口
interface DialogInstance {
show: () => void
hide: () => void
close: () => void
}
/**
*
* @param options
* @returns
*/
export function showDialog(options: DialogOptions): DialogInstance {
// 默认配置
const defaultOptions: DialogOptions = {
title: '',
message: '',
closable: true,
showFooter: true,
showCancelButton: true,
confirmButtonText: '确认',
cancelButtonText: '取消',
closeOnClickOverlay: true,
onConfirm: () => {},
onCancel: () => {},
onClose: () => {}
}
// 合并配置
const mergedOptions = { ...defaultOptions, ...options }
// 创建一个容器元素
const container = document.createElement('div')
// 对话框状态
let visible = true
// 创建应用实例
const app = createApp({
render() {
return h(Dialog, {
visible,
title: mergedOptions.title,
message: mergedOptions.message,
closable: mergedOptions.closable,
showFooter: mergedOptions.showFooter,
showCancelButton: mergedOptions.showCancelButton,
confirmButtonText: mergedOptions.confirmButtonText,
cancelButtonText: mergedOptions.cancelButtonText,
closeOnClickOverlay: mergedOptions.closeOnClickOverlay,
onConfirm: () => {
mergedOptions.onConfirm?.()
hideDialog()
},
onCancel: () => {
mergedOptions.onCancel?.()
hideDialog()
},
onClose: () => {
mergedOptions.onClose?.()
hideDialog()
}
})
}
})
// 隐藏对话框
function hideDialog() {
visible = false
// 等待动画完成后卸载组件
nextTick(() => {
setTimeout(() => {
app.unmount()
if (container.parentNode) {
container.parentNode.removeChild(container)
}
}, 300)
})
}
// 显示对话框(默认为显示状态)
function showDialog() {
visible = true
}
// 挂载组件
app.mount(container)
document.body.appendChild(container)
// 返回控制方法
return {
show: showDialog,
hide: hideDialog,
close: hideDialog
}
}
/**
*
* @param message
* @param title
* @param onConfirm
* @returns
*/
export function showConfirmDialog(message: string, title: string = '确认', onConfirm?: () => void): DialogInstance {
return showDialog({
title,
message,
showCancelButton: true,
onConfirm
})
}
/**
*
* @param message
* @param title
* @returns
*/
export function showAlertDialog(message: string, title: string = '提示'): DialogInstance {
return showDialog({
title,
message,
showCancelButton: false
})
}
// 默认导出
export default {
show: showDialog,
confirm: showConfirmDialog,
alert: showAlertDialog
}

View File

@ -1,304 +0,0 @@
# Loading 组件使用文档
## 组件介绍
Loading 组件是一个灵活的加载动画组件,支持多种动画类型、自定义大小、颜色等配置,可用于页面加载、数据请求等场景。
## 组件类型
- `spinner`:旋转圆环(默认)
- `dots`:点状加载动画
- `pulse`:脉冲加载动画
- `ring`:环形旋转动画
## 使用方式
### 方式一:组件方式使用
```vue
<template>
<div>
<!-- 基本使用 -->
<Loading :visible="loadingVisible" />
<!-- 自定义配置 -->
<Loading
:visible="loadingVisible"
type="dots"
size="60"
color="#1890ff"
text="加载中..."
:fullscreen="true"
background="rgba(0, 0, 0, 0.7)"
:opacity="0.8"
:strokeWidth="4"
strokeLinecap="round"
/>
<button @click="showLoading">显示加载</button>
<button @click="hideLoading">隐藏加载</button>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import Loading from './Loading.vue'
const loadingVisible = ref(false)
function showLoading() {
loadingVisible.value = true
}
function hideLoading() {
loadingVisible.value = false
}
</script>
```
### 方式二:编程方式使用
```vue
<template>
<div>
<button @click="showFullscreenLoading">显示全屏加载</button>
<button @click="showLoadingWithText">显示带文本的加载</button>
<button @click="showInlineLoading">显示内联加载</button>
<button @click="hideAllLoading">隐藏所有加载</button>
</div>
</template>
<script setup lang="ts">
import { showLoading, hideLoading, showLoadingWithText, showInlineLoading } from './loading'
import type { LoadingInstance } from './loading'
// 保存加载实例
let loadingInstance: LoadingInstance | null = null
// 显示全屏加载
function showFullscreenLoading() {
loadingInstance = showLoading({
type: 'spinner',
size: 50,
color: '#1890ff',
fullscreen: true,
background: 'rgba(255, 255, 255, 0.9)'
})
}
// 显示带文本的加载
function showLoadingWithText() {
loadingInstance = showLoadingWithText('数据加载中,请稍候...', '#52c41a')
}
// 显示内联加载
function showInlineLoading() {
loadingInstance = showInlineLoading(32, '#fa8c16', 'dots')
}
// 隐藏所有加载
function hideAllLoading() {
// 方式1隐藏特定实例
if (loadingInstance) {
loadingInstance.hide()
loadingInstance = null
}
// 方式2隐藏当前活动的全屏加载如果有的话
hideLoading()
}
// 模拟异步请求
function mockAsyncRequest() {
const loading = showLoadingWithText('处理中...')
setTimeout(() => {
// 请求完成后隐藏加载
loading.hide()
console.log('请求完成')
}, 3000)
}
</script>
```
## API 文档
### Loading 组件 Props
| 属性名 | 类型 | 默认值 | 说明 |
|-------|------|-------|------|
| visible | boolean | false | 是否显示加载组件 |
| type | 'spinner' \| 'dots' \| 'pulse' \| 'ring' | 'spinner' | 加载动画类型 |
| size | number \| string | 40 | 加载动画大小 |
| color | string | '#1890ff' | 加载动画颜色 |
| fullscreen | boolean | true | 是否全屏显示 |
| text | string | '' | 加载文本 |
| background | string | 'rgba(255, 255, 255, 0.9)' | 遮罩层背景色(全屏模式下) |
| opacity | number | 1 | 遮罩层透明度(全屏模式下) |
| strokeWidth | number | 3 | 线条宽度仅适用于spinner和ring类型 |
| strokeLinecap | 'round' \| 'butt' \| 'square' | 'round' | 线条末端样式仅适用于spinner类型 |
### loading.ts 函数API
#### showLoading(options?: LoadingOptions): LoadingInstance
创建并显示一个加载组件。
**参数**
- options: LoadingOptions - 加载组件配置选项与组件Props相同
**返回值**
- LoadingInstance - 加载组件实例,包含 show()、hide()、close() 方法
#### hideLoading(): void
隐藏当前活动的全屏加载组件。
#### showLoadingWithText(text: string, color?: string): LoadingInstance
显示一个带有文本的全屏加载组件。
**参数**
- text: string - 加载文本
- color: string - 加载动画颜色,默认为 '#1890ff'
**返回值**
- LoadingInstance - 加载组件实例
#### showInlineLoading(size?: number, color?: string, type?: LoadingType): LoadingInstance
显示一个小型内联加载组件。
**参数**
- size: number - 加载组件大小,默认为 24
- color: string - 加载动画颜色,默认为 '#1890ff'
- type: LoadingType - 加载动画类型,默认为 'spinner'
**返回值**
- LoadingInstance - 加载组件实例
### LoadingInstance 接口
| 方法名 | 说明 |
|-------|------|
| show() | 显示加载组件 |
| hide() | 隐藏加载组件并卸载 |
| close() | 同 hide(),隐藏加载组件并卸载 |
## 示例代码
### 场景1页面加载
```vue
<template>
<div v-if="!loading">
<!-- 页面内容 -->
</div>
<Loading v-else :visible="loading" text="页面加载中..." />
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import Loading from './components/Loading.vue'
const loading = ref(true)
onMounted(() => {
// 模拟页面数据加载
setTimeout(() => {
loading.value = false
}, 2000)
})
</script>
```
### 场景2API请求加载
```vue
<template>
<div>
<button @click="fetchData" :disabled="loading">获取数据</button>
<div v-if="data">
<!-- 数据展示 -->
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { showLoading, hideLoading } from './components/loading'
const loading = ref(false)
const data = ref(null)
async function fetchData() {
loading.value = true
try {
// 显示加载
const loadingInstance = showLoadingWithText('数据请求中...')
// 模拟API请求
await new Promise(resolve => setTimeout(resolve, 2000))
// 获取数据
data.value = { /* 数据内容 */ }
} catch (error) {
console.error('请求失败:', error)
} finally {
loading.value = false
// 隐藏加载
hideLoading()
}
}
</script>
```
### 场景3提交表单时的加载
```vue
<template>
<form @submit.prevent="submitForm">
<!-- 表单内容 -->
<button type="submit" :disabled="submitting">
{{ submitting ? '提交中...' : '提交' }}
<Loading
v-if="submitting"
:visible="true"
:fullscreen="false"
type="spinner"
:size="16"
style="display: inline-block; margin-left: 8px;"
/>
</button>
</form>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import Loading from './components/Loading.vue'
const submitting = ref(false)
async function submitForm() {
submitting.value = true
try {
// 模拟表单提交
await new Promise(resolve => setTimeout(resolve, 1500))
console.log('表单提交成功')
} catch (error) {
console.error('表单提交失败:', error)
} finally {
submitting.value = false
}
}
</script>
```
## 注意事项
1. 当使用编程方式创建多个全屏加载组件时,最新创建的会替换之前的。
2. 请确保在不需要加载动画时调用 hide() 方法来卸载组件,避免内存泄漏。
3. 对于长时间运行的操作,建议添加加载文本以提高用户体验。
4. 内联加载组件不会自动居中,需要根据具体场景调整其位置。

View File

@ -1,5 +1,5 @@
<template>
<div class="min-h-screen bg-[#FCEEF3] overflow-hidden">
<div class="h-full bg-[#FCEEF3] overflow-hidden">
<!-- 顶部头图 -->
<div class="w-full overflow-hidden relative">
<img src="/头图.png" alt="活动宣传" class="w-full h-auto" />