feat: add interactive demos for AI history, Auth design, and Git intro
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
// auth-design 公共组件配置
|
||||
|
||||
// 生成按钮类名
|
||||
export const getButtonClasses = (variant = 'primary', disabled = false, size = 'medium') => {
|
||||
const base = 'auth-demo-btn'
|
||||
const classes = [base]
|
||||
|
||||
// 变体
|
||||
classes.push(`${base}-${variant}`)
|
||||
|
||||
// 状态
|
||||
if (disabled) classes.push(`${base}-disabled`)
|
||||
|
||||
// 大小
|
||||
classes.push(`${base}-${size}`)
|
||||
|
||||
return classes.join(' ')
|
||||
}
|
||||
|
||||
// 生成卡片类名
|
||||
export const getCardClasses = (variant = 'default', clickable = false) => {
|
||||
const base = 'auth-demo-card'
|
||||
const classes = [base]
|
||||
|
||||
if (variant !== 'default') {
|
||||
classes.push(`${base}-${variant}`)
|
||||
}
|
||||
|
||||
if (clickable) {
|
||||
classes.push(`${base}-clickable`)
|
||||
}
|
||||
|
||||
return classes.join(' ')
|
||||
}
|
||||
|
||||
// 生成状态徽章类名
|
||||
export const getBadgeClasses = (type = 'info') => {
|
||||
const types = {
|
||||
success: 'auth-badge-success',
|
||||
warning: 'auth-badge-warning',
|
||||
danger: 'auth-badge-danger',
|
||||
info: 'auth-badge-info',
|
||||
purple: 'auth-badge-purple'
|
||||
}
|
||||
|
||||
return types[type] || types.info
|
||||
}
|
||||
|
||||
// 生成进度条类名
|
||||
export const getProgressClasses = (variant = 'primary') => {
|
||||
return `auth-progress auth-progress-${variant}`
|
||||
}
|
||||
|
||||
// 格式化代码示例
|
||||
export const formatCodeExample = (code, language = 'javascript') => {
|
||||
if (typeof code !== 'string') return ''
|
||||
return code.trim()
|
||||
}
|
||||
|
||||
// 生成流程步骤类名
|
||||
export const getStepClasses = (index, currentIndex, totalSteps) => {
|
||||
const classes = ['auth-step']
|
||||
|
||||
if (index < currentIndex) {
|
||||
classes.push('auth-step-completed')
|
||||
} else if (index === currentIndex) {
|
||||
classes.push('auth-step-active')
|
||||
} else {
|
||||
classes.push('auth-step-pending')
|
||||
}
|
||||
|
||||
return classes.join(' ')
|
||||
}
|
||||
|
||||
// 生成表格行类名
|
||||
export const getTableRowClasses = (highlight = false, index = 0) => {
|
||||
const classes = ['auth-table-row']
|
||||
|
||||
if (highlight) classes.push('auth-table-row-highlight')
|
||||
if (index % 2 === 0) classes.push('auth-table-row-even')
|
||||
|
||||
return classes.join(' ')
|
||||
}
|
||||
|
||||
// 生成图标容器类名
|
||||
export const getIconContainerClasses = (size = 'medium', variant = 'default') => {
|
||||
return `auth-icon-container auth-icon-container-${size} auth-icon-container-${variant}`
|
||||
}
|
||||
|
||||
// 生成输入框类名
|
||||
export const getInputClasses = (state = 'default', size = 'medium') => {
|
||||
const classes = ['auth-input']
|
||||
|
||||
if (state !== 'default') {
|
||||
classes.push(`auth-input-${state}`)
|
||||
}
|
||||
|
||||
if (size !== 'medium') {
|
||||
classes.push(`auth-input-${size}`)
|
||||
}
|
||||
|
||||
return classes.join(' ')
|
||||
}
|
||||
|
||||
// 生成通知/提示框类名
|
||||
export const getAlertClasses = (type = 'info', dismissible = false) => {
|
||||
const classes = ['auth-alert', `auth-alert-${type}`]
|
||||
|
||||
if (dismissible) {
|
||||
classes.push('auth-alert-dismissible')
|
||||
}
|
||||
|
||||
return classes.join(' ')
|
||||
}
|
||||
|
||||
// 生成标签类名
|
||||
export const getTagClasses = (variant = 'default', size = 'medium') => {
|
||||
return `auth-tag auth-tag-${variant} auth-tag-${size}`
|
||||
}
|
||||
|
||||
// 生成加载器类名
|
||||
export const getSpinnerClasses = (size = 'medium') => {
|
||||
return `auth-spinner auth-spinner-${size}`
|
||||
}
|
||||
|
||||
// 生成下拉菜单类名
|
||||
export const getDropdownClasses = (isOpen = false, direction = 'down') => {
|
||||
const classes = ['auth-dropdown']
|
||||
|
||||
if (isOpen) classes.push('auth-dropdown-open')
|
||||
classes.push(`auth-dropdown-${direction}`)
|
||||
|
||||
return classes.join(' ')
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
// auth-design 公共组合式函数
|
||||
import { ref, computed, onMounted, onUnmounted } from 'vue'
|
||||
|
||||
/**
|
||||
* 延迟函数
|
||||
* @param {number} ms - 延迟毫秒数
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
export const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
|
||||
|
||||
/**
|
||||
* 防抖函数
|
||||
* @param {Function} fn - 要防抖的函数
|
||||
* @param {number} wait - 等待时间(毫秒)
|
||||
* @returns {Function}
|
||||
*/
|
||||
export const useDebounce = (fn, wait = 300) => {
|
||||
let timeout = null
|
||||
return (...args) => {
|
||||
clearTimeout(timeout)
|
||||
timeout = setTimeout(() => fn(...args), wait)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 步骤流程管理
|
||||
* @param {Array} steps - 步骤数组
|
||||
* @param {number} stepDelay - 每步延迟时间
|
||||
* @returns {Object}
|
||||
*/
|
||||
export const useStepFlow = (steps, stepDelay = 800) => {
|
||||
const currentStep = ref(0)
|
||||
const isProcessing = ref(false)
|
||||
|
||||
const startFlow = async () => {
|
||||
isProcessing.value = true
|
||||
for (let i = 0; i < steps.length; i++) {
|
||||
currentStep.value = i + 1
|
||||
await delay(stepDelay)
|
||||
}
|
||||
isProcessing.value = false
|
||||
}
|
||||
|
||||
const resetFlow = () => {
|
||||
currentStep.value = 0
|
||||
isProcessing.value = false
|
||||
}
|
||||
|
||||
return {
|
||||
currentStep,
|
||||
isProcessing,
|
||||
startFlow,
|
||||
resetFlow
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步操作状态管理
|
||||
* @returns {Object}
|
||||
*/
|
||||
export const useAsyncState = () => {
|
||||
const isLoading = ref(false)
|
||||
const error = ref(null)
|
||||
const data = ref(null)
|
||||
|
||||
const execute = async (fn) => {
|
||||
isLoading.value = true
|
||||
error.value = null
|
||||
try {
|
||||
const result = await fn()
|
||||
data.value = result
|
||||
return result
|
||||
} catch (err) {
|
||||
error.value = err
|
||||
throw err
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const reset = () => {
|
||||
isLoading.value = false
|
||||
error.value = null
|
||||
data.value = null
|
||||
}
|
||||
|
||||
return {
|
||||
isLoading,
|
||||
error,
|
||||
data,
|
||||
execute,
|
||||
reset
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 定时器管理
|
||||
* @returns {Object}
|
||||
*/
|
||||
export const useTimer = () => {
|
||||
const timer = ref(null)
|
||||
const isRunning = ref(false)
|
||||
|
||||
const start = (callback, interval) => {
|
||||
if (timer.value) clearInterval(timer.value)
|
||||
isRunning.value = true
|
||||
timer.value = setInterval(callback, interval)
|
||||
}
|
||||
|
||||
const stop = () => {
|
||||
if (timer.value) {
|
||||
clearInterval(timer.value)
|
||||
timer.value = null
|
||||
isRunning.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
stop()
|
||||
})
|
||||
|
||||
return {
|
||||
isRunning,
|
||||
start,
|
||||
stop
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换状态
|
||||
* @param {boolean} initialValue - 初始值
|
||||
* @returns {Object}
|
||||
*/
|
||||
export const useToggle = (initialValue = false) => {
|
||||
const value = ref(initialValue)
|
||||
|
||||
const toggle = () => {
|
||||
value.value = !value.value
|
||||
}
|
||||
|
||||
const setTrue = () => {
|
||||
value.value = true
|
||||
}
|
||||
|
||||
const setFalse = () => {
|
||||
value.value = false
|
||||
}
|
||||
|
||||
return {
|
||||
value,
|
||||
toggle,
|
||||
setTrue,
|
||||
setFalse
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 动画控制
|
||||
* @param {number} duration - 动画持续时间(毫秒)
|
||||
* @returns {Object}
|
||||
*/
|
||||
export const useAnimation = (duration = 300) => {
|
||||
const isAnimating = ref(false)
|
||||
|
||||
const animate = async (callback) => {
|
||||
isAnimating.value = true
|
||||
await callback()
|
||||
await delay(duration)
|
||||
isAnimating.value = false
|
||||
}
|
||||
|
||||
return {
|
||||
isAnimating,
|
||||
animate
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成随机 ID
|
||||
* @param {string} prefix - 前缀
|
||||
* @returns {string}
|
||||
*/
|
||||
export const generateId = (prefix = 'id') => {
|
||||
return `${prefix}_${Math.random().toString(36).substring(2, 15)}`
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化时间戳
|
||||
* @param {number} timestamp - 时间戳
|
||||
* @returns {string}
|
||||
*/
|
||||
export const formatTimestamp = (timestamp) => {
|
||||
const date = new Date(timestamp)
|
||||
return date.toLocaleTimeString()
|
||||
}
|
||||
|
||||
/**
|
||||
* 深拷贝对象
|
||||
* @param {*} obj - 要拷贝的对象
|
||||
* @returns {*}
|
||||
*/
|
||||
export const deepClone = (obj) => {
|
||||
if (obj === null || typeof obj !== 'object') return obj
|
||||
if (obj instanceof Date) return new Date(obj.getTime())
|
||||
if (obj instanceof Array) return obj.map((item) => deepClone(item))
|
||||
if (obj instanceof Object) {
|
||||
const clonedObj = {}
|
||||
for (const key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
clonedObj[key] = deepClone(obj[key])
|
||||
}
|
||||
}
|
||||
return clonedObj
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量更新状态
|
||||
* @param {Object} stateRef - 状态引用
|
||||
* @param {Object} updates - 更新内容
|
||||
*/
|
||||
export const batchUpdate = (stateRef, updates) => {
|
||||
Object.assign(stateRef.value, updates)
|
||||
}
|
||||
|
||||
/**
|
||||
* 评分转换为星星
|
||||
* @param {number} score - 评分 (1-5)
|
||||
* @returns {string}
|
||||
*/
|
||||
export const scoreToStars = (score) => {
|
||||
return '⭐'.repeat(Math.floor(score))
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
// auth-design 公共样式配置
|
||||
export const commonStyles = {
|
||||
// 容器样式
|
||||
container: {
|
||||
base: 'auth-demo-container',
|
||||
classes: {
|
||||
border: '1px solid var(--vp-c-divider)',
|
||||
background: 'var(--vp-c-bg-soft)',
|
||||
borderRadius: '12px',
|
||||
padding: '1.5rem',
|
||||
margin: '1.5rem 0',
|
||||
fontFamily: 'var(--vp-font-family-base)'
|
||||
}
|
||||
},
|
||||
|
||||
// 标题样式
|
||||
header: {
|
||||
title: {
|
||||
fontWeight: '700',
|
||||
fontSize: '1.2rem',
|
||||
marginBottom: '0.3rem',
|
||||
background: 'linear-gradient(120deg, var(--vp-c-brand), #9c27b0)',
|
||||
WebkitBackgroundClip: 'text',
|
||||
WebkitTextFillColor: 'transparent'
|
||||
},
|
||||
subtitle: {
|
||||
color: 'var(--vp-c-text-2)',
|
||||
fontSize: '0.9rem'
|
||||
}
|
||||
},
|
||||
|
||||
// 按钮样式
|
||||
button: {
|
||||
base: 'auth-demo-btn',
|
||||
primary: 'auth-demo-btn-primary',
|
||||
variants: {
|
||||
primary: {
|
||||
background: 'var(--vp-c-brand)',
|
||||
color: 'white'
|
||||
},
|
||||
success: {
|
||||
background: '#22c55e',
|
||||
color: 'white'
|
||||
},
|
||||
danger: {
|
||||
background: '#ef4444',
|
||||
color: 'white'
|
||||
},
|
||||
secondary: {
|
||||
background: '#64748b',
|
||||
color: 'white'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 卡片样式
|
||||
card: {
|
||||
base: 'auth-demo-card',
|
||||
background: 'var(--vp-c-bg)',
|
||||
border: '1px solid var(--vp-c-divider)',
|
||||
borderRadius: '10px',
|
||||
padding: '1.25rem'
|
||||
},
|
||||
|
||||
// 代码块样式
|
||||
codeBlock: {
|
||||
background: '#1e293b',
|
||||
color: '#e2e8f0',
|
||||
fontFamily: "'Courier New', monospace",
|
||||
fontSize: '0.8rem',
|
||||
lineHeight: '1.6',
|
||||
padding: '0.75rem',
|
||||
borderRadius: '6px'
|
||||
}
|
||||
}
|
||||
|
||||
// 动画配置
|
||||
export const animations = {
|
||||
fadeIn: {
|
||||
name: 'fadeIn',
|
||||
css: `
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
`
|
||||
},
|
||||
slideIn: {
|
||||
name: 'slideIn',
|
||||
css: `
|
||||
@keyframes slideIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
`
|
||||
},
|
||||
pulse: {
|
||||
name: 'pulse',
|
||||
css: `
|
||||
@keyframes pulse {
|
||||
0%, 100% { transform: scale(1); }
|
||||
50% { transform: scale(1.05); }
|
||||
}
|
||||
`
|
||||
},
|
||||
bounce: {
|
||||
name: 'bounce',
|
||||
css: `
|
||||
@keyframes bounce {
|
||||
0%, 100% { transform: translateX(-50%) translateY(0); }
|
||||
50% { transform: translateX(-50%) translateY(-5px); }
|
||||
}
|
||||
`
|
||||
},
|
||||
spin: {
|
||||
name: 'spin',
|
||||
css: `
|
||||
@keyframes spin {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
// 颜色配置
|
||||
export const colors = {
|
||||
success: '#22c55e',
|
||||
warning: '#f59e0b',
|
||||
danger: '#ef4444',
|
||||
info: '#3b82f6',
|
||||
purple: '#8b5cf6'
|
||||
}
|
||||
|
||||
// 响应式断点
|
||||
export const breakpoints = {
|
||||
mobile: '768px'
|
||||
}
|
||||
Reference in New Issue
Block a user