This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* 佣金模块 API (代理端)
|
||||
*/
|
||||
import { get, post } from '@/utils/request'
|
||||
import { get } from '@/utils/request'
|
||||
|
||||
/**
|
||||
* 资金概览 (代理端主页用)
|
||||
@@ -141,7 +141,7 @@ export interface ListResponse<T> {
|
||||
}
|
||||
|
||||
export interface FundSummaryParams {
|
||||
shop_name?: string
|
||||
username?: string
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,7 +151,7 @@ export interface FundSummaryParams {
|
||||
export function getFundSummary(params?: FundSummaryParams) {
|
||||
return get<{ items: FundSummary[] }>(
|
||||
'/api/admin/shops/fund-summary',
|
||||
params?.shop_name ? { params } : undefined
|
||||
params?.username ? { params } : undefined
|
||||
).then(res => res.items?.[0])
|
||||
}
|
||||
|
||||
|
||||
88
src/components/AgentFundSummaryCard.vue
Normal file
88
src/components/AgentFundSummaryCard.vue
Normal file
@@ -0,0 +1,88 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import type { FundSummary } from '@/api/commission'
|
||||
|
||||
type SummaryMetric = {
|
||||
label: string
|
||||
amount?: number | null
|
||||
cardClass: string
|
||||
labelClass: string
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
summary?: FundSummary | null
|
||||
}>()
|
||||
|
||||
const metrics = computed<SummaryMetric[]>(() => [
|
||||
{
|
||||
label: '预充值余额',
|
||||
amount: props.summary?.main_balance,
|
||||
cardClass: 'bg-[#f4fbf5] border border-[#e3f2e6]',
|
||||
labelClass: 'text-[#2f7d32]',
|
||||
},
|
||||
{
|
||||
label: '累计佣金',
|
||||
amount: props.summary?.total_commission,
|
||||
cardClass: 'bg-[#f8fafc] border border-[#eef2f6]',
|
||||
labelClass: 'text-[#6b7280]',
|
||||
},
|
||||
{
|
||||
label: '已提现',
|
||||
amount: props.summary?.withdrawn_commission,
|
||||
cardClass: 'bg-[#f8fafc] border border-[#eef2f6]',
|
||||
labelClass: 'text-[#6b7280]',
|
||||
},
|
||||
{
|
||||
label: '冻结',
|
||||
amount: props.summary?.frozen_commission,
|
||||
cardClass: 'bg-[#f8fafc] border border-[#eef2f6]',
|
||||
labelClass: 'text-[#6b7280]',
|
||||
},
|
||||
])
|
||||
|
||||
function formatAmount(amount: number) {
|
||||
const yuan = (amount / 100).toFixed(2)
|
||||
const parts = yuan.split('.')
|
||||
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',')
|
||||
return `¥${parts.join('.')}`
|
||||
}
|
||||
|
||||
function formatAmountDisplay(amount?: number | null) {
|
||||
return typeof amount === 'number' ? formatAmount(amount) : '--'
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="bg-white rounded-20px shadow-[0_8px_24px_rgba(15,23,42,0.06)] p-5">
|
||||
<view class="rounded-18px bg-gradient-to-br from-[#f5fbf5] via-white to-[#f8fafc] p-4">
|
||||
<view class="flex items-start justify-between gap-3">
|
||||
<view class="min-w-0 flex-1">
|
||||
<view class="inline-flex items-center gap-1 rounded-full bg-[#e8f5e9] px-2.5 py-1">
|
||||
<i class="i-mdi-wallet-outline text-13px text-[#2f7d32]" />
|
||||
<text class="text-11px font-600 text-[#2f7d32]">可提现佣金</text>
|
||||
</view>
|
||||
<text class="text-34px font-700 leading-none text-[#1f2937] block mt-3 break-all">
|
||||
{{ formatAmountDisplay(summary?.available_commission) }}
|
||||
</text>
|
||||
</view>
|
||||
<image src="@/static/icons/佣金中心.png" class="w-16 h-16 shrink-0" mode="aspectFit" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="grid grid-cols-2 gap-3 mt-4">
|
||||
<view
|
||||
v-for="metric in metrics"
|
||||
:key="metric.label"
|
||||
:class="metric.cardClass"
|
||||
class="rounded-16px px-3 py-3"
|
||||
>
|
||||
<text :class="metric.labelClass" class="text-11px block">
|
||||
{{ metric.label }}
|
||||
</text>
|
||||
<text class="text-15px font-700 text-[#1f2937] block mt-2 break-all">
|
||||
{{ formatAmountDisplay(metric.amount) }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@@ -340,14 +340,6 @@
|
||||
</text>
|
||||
</view>
|
||||
|
||||
<!-- 运营商ID -->
|
||||
<view v-if="cardInfo.carrier_id" class="flex items-start justify-between">
|
||||
<text class="text-12px text-[#999] w-70px">运营商ID</text>
|
||||
<text class="flex-1 text-13px text-[#212121] text-right">
|
||||
{{ cardInfo.carrier_id }}
|
||||
</text>
|
||||
</view>
|
||||
|
||||
<!-- 卡类型 -->
|
||||
<view v-if="cardInfo.card_category" class="flex items-start justify-between">
|
||||
<text class="text-12px text-[#999] w-70px">卡类型</text>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { getFundSummary, getCommissionRecords, getCommissionStats } from '@/api/commission'
|
||||
import type { FundSummary, CommissionRecord, CommissionStats } from '@/api/commission'
|
||||
import AgentFundSummaryCard from '@/components/AgentFundSummaryCard.vue'
|
||||
import SimplePicker from '@/components/SimplePicker.vue'
|
||||
|
||||
type LoginUserInfo = {
|
||||
@@ -13,7 +14,6 @@ const commissionSummary = ref<FundSummary | null>(null)
|
||||
const shopId = ref<number>(0)
|
||||
const commissionRecords = ref<CommissionRecord[]>([])
|
||||
const commissionStats = ref<CommissionStats | null>(null)
|
||||
const loading = ref(false)
|
||||
const loadingRecords = ref(false)
|
||||
const page = ref(1)
|
||||
const pageSize = 20
|
||||
@@ -86,7 +86,7 @@ onMounted(() => {
|
||||
async function loadCommissionSummary() {
|
||||
try {
|
||||
const userInfo = getLoginUserInfo()
|
||||
commissionSummary.value = await getFundSummary(userInfo?.username ? { shop_name: userInfo.username } : undefined)
|
||||
commissionSummary.value = await getFundSummary(userInfo?.username ? { username: userInfo.username } : undefined)
|
||||
} catch (error) {
|
||||
console.error('加载佣金概览失败:', error)
|
||||
}
|
||||
@@ -153,12 +153,6 @@ function loadMore() {
|
||||
}
|
||||
}
|
||||
|
||||
function onScroll(e: any) {
|
||||
const { scrollTop, scrollHeight, clientHeight } = e.target
|
||||
if (scrollHeight - scrollTop - clientHeight < 100) {
|
||||
loadMore()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -205,37 +199,7 @@ function onScroll(e: any) {
|
||||
<!-- 内容区域 -->
|
||||
<view class="px-4 pb-4">
|
||||
<!-- 概览卡片 -->
|
||||
<view class="bg-white rounded-16px p-5 mt-4 shadow-[0_2px_12px_rgba(0,0,0,0.08)]">
|
||||
<view class="flex items-center justify-between">
|
||||
<view>
|
||||
<text class="text-12px text-[#999]">可提现佣金</text>
|
||||
<text class="text-32px font-700 text-[#212121] block mt-1">
|
||||
{{ commissionSummary ? formatAmount(commissionSummary.available_commission) : '--' }}
|
||||
</text>
|
||||
</view>
|
||||
<image src="@/static/icons/佣金中心.png" class="w-12 h-12 rounded-12px" mode="aspectFit" />
|
||||
</view>
|
||||
<view class="flex gap-3 mt-4 pt-4 border-t border-[#f5f5f5]">
|
||||
<view class="flex-1 text-center">
|
||||
<text class="text-11px text-[#999]">累计佣金</text>
|
||||
<text class="text-14px font-600 text-[#212121] block mt-1">
|
||||
{{ commissionSummary ? formatAmount(commissionSummary.total_commission) : '--' }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="flex-1 text-center border-l border-[#f5f5f5]">
|
||||
<text class="text-11px text-[#999]">已提现</text>
|
||||
<text class="text-14px font-600 text-[#52c41a] block mt-1">
|
||||
{{ commissionSummary ? formatAmount(commissionSummary.withdrawn_commission) : '--' }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="flex-1 text-center border-l border-[#f5f5f5]">
|
||||
<text class="text-11px text-[#999]">冻结</text>
|
||||
<text class="text-14px font-600 text-[#ff4d4f] block mt-1">
|
||||
{{ commissionSummary ? formatAmount(commissionSummary.frozen_commission) : '--' }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<AgentFundSummaryCard class="mt-4" :summary="commissionSummary" />
|
||||
|
||||
<!-- 佣金统计 -->
|
||||
<view class="bg-white rounded-16px p-4 mt-3 shadow-[0_2px_8px_rgba(0,0,0,0.04)]">
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
import type { UserInfo } from '@/api/auth'
|
||||
import { getFundSummary, getCommissionDailyStats } from '@/api/commission'
|
||||
import type { FundSummary, DailyCommissionStats } from '@/api/commission'
|
||||
import AgentFundSummaryCard from '@/components/AgentFundSummaryCard.vue'
|
||||
|
||||
|
||||
// 用户信息
|
||||
@@ -36,10 +37,6 @@
|
||||
return `¥${parts.join('.')}`
|
||||
}
|
||||
|
||||
function formatAmountDisplay(amount?: number | null) {
|
||||
return typeof amount === 'number' ? formatAmount(amount) : '--'
|
||||
}
|
||||
|
||||
// 格式化日期 (MM-DD)
|
||||
// 根据用户类型动态生成菜单
|
||||
function formatDate(dateStr : string) {
|
||||
@@ -49,72 +46,15 @@
|
||||
return `${month}-${day}`
|
||||
}
|
||||
|
||||
function getTodayDate() {
|
||||
const today = new Date()
|
||||
const year = today.getFullYear()
|
||||
const month = String(today.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(today.getDate()).padStart(2, '0')
|
||||
return `${year}-${month}-${day}`
|
||||
}
|
||||
|
||||
const menuItems = computed(() => {
|
||||
const menus = [
|
||||
{
|
||||
title: '资产列表',
|
||||
desc: userInfo.value?.user_type === 3 ? '代理资产列表' : '企业资产列表',
|
||||
icon: '/static/icons/资产列表.png',
|
||||
path: '/pages/agent-system/assets/index',
|
||||
},
|
||||
]
|
||||
|
||||
// 企业端显示授权卡和授权设备 (仅 user_type === 4)
|
||||
if (userInfo.value?.user_type === 4) {
|
||||
menus.push(
|
||||
{
|
||||
title: '授权卡列表',
|
||||
desc: '企业授权IoT卡',
|
||||
icon: '/static/icons/授权卡列表.png',
|
||||
path: '/pages/agent-system/enterprise-cards/index',
|
||||
},
|
||||
{
|
||||
title: '授权设备列表',
|
||||
desc: '企业授权设备',
|
||||
icon: '/static/icons/授权设备列表.png',
|
||||
path: '/pages/agent-system/enterprise-devices/index',
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// 仅代理端显示佣金和提现
|
||||
if (userInfo.value?.user_type === 3) {
|
||||
menus.push(
|
||||
{
|
||||
title: '佣金中心',
|
||||
desc: '收益统计',
|
||||
icon: '/static/icons/佣金中心.png',
|
||||
path: '/pages/agent-system/commission-center/index',
|
||||
},
|
||||
{
|
||||
title: '提现管理',
|
||||
desc: '申请提现',
|
||||
icon: '/static/icons/提现管理.png',
|
||||
path: '/pages/agent-system/withdraw/index',
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return menus
|
||||
})
|
||||
|
||||
// 加载佣金数据
|
||||
async function loadCommissionData(shopName?: string) {
|
||||
async function loadCommissionData(username?: string) {
|
||||
if (!isAgent.value) return
|
||||
|
||||
loadingCommission.value = true
|
||||
|
||||
try {
|
||||
// 1. 加载佣金概览 (新接口 /shops/fund-summary)
|
||||
const summary = await getFundSummary(shopName ? { shop_name: shopName } : undefined)
|
||||
const summary = await getFundSummary(username ? { username } : undefined)
|
||||
commissionSummary.value = summary
|
||||
|
||||
if (!shopId.value) {
|
||||
@@ -122,11 +62,8 @@
|
||||
return
|
||||
}
|
||||
|
||||
const today = getTodayDate()
|
||||
const todayStats = await getCommissionDailyStats(shopId.value, {
|
||||
days: 1,
|
||||
start_date: today,
|
||||
end_date: today,
|
||||
})
|
||||
dailyStats.value = todayStats || []
|
||||
return
|
||||
@@ -155,19 +92,20 @@
|
||||
// 设置店铺ID
|
||||
const loginUserInfo = getLoginUserInfo()
|
||||
shopId.value = user.shop_id || loginUserInfo?.shop_id || 0
|
||||
const fundSummaryShopName = loginUserInfo?.username || user.username
|
||||
const fundSummaryUsername = loginUserInfo?.username || user.username
|
||||
|
||||
console.log('首页数据加载成功:', { user })
|
||||
|
||||
// 如果是代理账号,加载佣金数据
|
||||
if (user.user_type === 3) {
|
||||
await loadCommissionData(fundSummaryShopName)
|
||||
await loadCommissionData(fundSummaryUsername)
|
||||
}
|
||||
}
|
||||
catch (error : any) {
|
||||
console.error('加载首页数据失败:', error)
|
||||
// 如果是前端逻辑错误(非 API 错误),需要手动显示提示
|
||||
if (error instanceof Error && error.message && !error.statusCode) {
|
||||
const errorWithStatus = error as { statusCode?: number } | undefined
|
||||
if (error instanceof Error && error.message && !errorWithStatus?.statusCode) {
|
||||
uni.$u.toast(error.message)
|
||||
}
|
||||
// API 请求错误已由拦截器统一处理
|
||||
@@ -253,54 +191,16 @@
|
||||
|
||||
<!-- 代理端: 佣金展示 -->
|
||||
<view v-if="isAgent" class="px-4 pt-4">
|
||||
<view
|
||||
class="bg-white rounded-16px shadow-[0_2px_12px_rgba(0,0,0,0.06)] p-5 mb-3"
|
||||
<AgentFundSummaryCard
|
||||
class="mb-3"
|
||||
:summary="commissionSummary"
|
||||
@click="navigateTo('/pages/agent-system/commission-center/index')"
|
||||
>
|
||||
<view class="flex items-center justify-between gap-3">
|
||||
<view class="min-w-0 flex-1">
|
||||
<text class="text-12px text-[#999]">可提现佣金</text>
|
||||
<text class="text-32px font-700 text-[#212121] block mt-1 break-all">
|
||||
{{ formatAmountDisplay(commissionSummary?.available_commission) }}
|
||||
</text>
|
||||
<text class="text-11px text-[#999] block mt-2">
|
||||
当前可直接发起提现的佣金金额
|
||||
</text>
|
||||
</view>
|
||||
<view class="flex flex-col items-end gap-2">
|
||||
<image src="@/static/icons/佣金中心.png" class="w-12 h-12 rounded-12px" mode="aspectFit" />
|
||||
<view class="flex items-center gap-1">
|
||||
<text class="text-12px text-[#999]">佣金中心</text>
|
||||
<i class="i-mdi-chevron-right text-16px text-[#cbd5e1]" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex gap-3 mt-4 pt-4 border-t border-[#f5f5f5]">
|
||||
<view class="flex-1 text-center">
|
||||
<text class="text-11px text-[#999]">累计佣金</text>
|
||||
<text class="text-14px font-600 text-[#212121] block mt-1">
|
||||
{{ formatAmountDisplay(commissionSummary?.total_commission) }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="flex-1 text-center border-l border-[#f5f5f5]">
|
||||
<text class="text-11px text-[#999]">已提现</text>
|
||||
<text class="text-14px font-600 text-[#52c41a] block mt-1">
|
||||
{{ formatAmountDisplay(commissionSummary?.withdrawn_commission) }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="flex-1 text-center border-l border-[#f5f5f5]">
|
||||
<text class="text-11px text-[#999]">冻结</text>
|
||||
<text class="text-14px font-600 text-[#ff4d4f] block mt-1">
|
||||
{{ formatAmountDisplay(commissionSummary?.frozen_commission) }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
/>
|
||||
|
||||
<!-- 今日佣金 -->
|
||||
<!-- 最近一天佣金 -->
|
||||
<view>
|
||||
<view class="flex items-center justify-between mb-3">
|
||||
<text class="text-16px font-700 text-[#212121]">今日佣金</text>
|
||||
<text class="text-16px font-700 text-[#212121]">最近一天佣金</text>
|
||||
<text class="text-13px text-[#999]" @click="navigateTo('/pages/agent-system/commission-center/index')">明细</text>
|
||||
</view>
|
||||
<view class="bg-white rounded-16px shadow-[0_2px_12px_rgba(0,0,0,0.06)] p-4">
|
||||
@@ -325,7 +225,7 @@
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="!todayStat" class="mt-3 pt-3 border-t border-[#f5f5f5] text-center">
|
||||
<text class="text-12px text-[#999]">今日暂无佣金数据</text>
|
||||
<text class="text-12px text-[#999]">最近一天暂无佣金数据</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -26,6 +26,7 @@ const pageSize = 20
|
||||
const total = ref(0)
|
||||
const statusFilter = ref<number | undefined>(undefined)
|
||||
const showStatusPicker = ref(false)
|
||||
const MIN_WITHDRAW_AMOUNT = 100
|
||||
|
||||
const statusOptions = [
|
||||
{ label: '全部状态', value: undefined },
|
||||
@@ -41,7 +42,7 @@ const selectedStatusName = computed(() => {
|
||||
return option?.label || '状态'
|
||||
})
|
||||
|
||||
const tabs = [
|
||||
const tabs: Array<{ key: 'apply' | 'records', label: string }> = [
|
||||
{ key: 'apply', label: '申请提现' },
|
||||
{ key: 'records', label: '提现记录' },
|
||||
]
|
||||
@@ -51,6 +52,8 @@ const availableAmount = computed(() => {
|
||||
return commissionSummary.value.available_commission / 100
|
||||
})
|
||||
|
||||
const canWithdrawByMinAmount = computed(() => availableAmount.value >= MIN_WITHDRAW_AMOUNT)
|
||||
|
||||
function formatAmount(amount: number) {
|
||||
const yuan = (amount / 100).toFixed(2)
|
||||
const parts = yuan.split('.')
|
||||
@@ -95,7 +98,7 @@ async function loadCommissionSummary() {
|
||||
loading.value = true
|
||||
try {
|
||||
const userInfo = getLoginUserInfo()
|
||||
commissionSummary.value = await getFundSummary(userInfo?.username ? { shop_name: userInfo.username } : undefined)
|
||||
commissionSummary.value = await getFundSummary(userInfo?.username ? { username: userInfo.username } : undefined)
|
||||
withdrawAmount.value = availableAmount.value.toFixed(2)
|
||||
} catch (error) {
|
||||
console.error('加载佣金概览失败:', error)
|
||||
@@ -144,6 +147,10 @@ async function handleSubmit() {
|
||||
uni.$u.toast('请输入提现金额')
|
||||
return
|
||||
}
|
||||
if (amount < MIN_WITHDRAW_AMOUNT) {
|
||||
uni.$u.toast(`满${MIN_WITHDRAW_AMOUNT}元才可提现`)
|
||||
return
|
||||
}
|
||||
if (amount > availableAmount.value) {
|
||||
uni.$u.toast('提现金额超过可用余额')
|
||||
return
|
||||
@@ -200,12 +207,6 @@ function loadMore() {
|
||||
}
|
||||
}
|
||||
|
||||
function onScroll(e: any) {
|
||||
const { scrollTop, scrollHeight, clientHeight } = e.target
|
||||
if (scrollHeight - scrollTop - clientHeight < 100) {
|
||||
loadMore()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -293,10 +294,17 @@ function onScroll(e: any) {
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="mt-6 mb-3 flex items-center gap-1.5 px-3 py-2 rounded-12px bg-[var(--color-warning-bg)]">
|
||||
<i class="i-mdi-information-outline text-14px text-warning" />
|
||||
<text class="text-12px" :class="canWithdrawByMinAmount ? 'text-warning' : 'text-error'">
|
||||
满100元才可提现
|
||||
</text>
|
||||
</view>
|
||||
|
||||
<!-- 提交按钮 -->
|
||||
<view
|
||||
class="bg-brand rounded-full py-4 text-center text-16px font-600 text-white mt-6"
|
||||
:class="{ 'opacity-50': submitting }"
|
||||
class="bg-brand rounded-full py-4 text-center text-16px font-600 text-white"
|
||||
:class="{ 'opacity-50': submitting || !canWithdrawByMinAmount }"
|
||||
@click="handleSubmit"
|
||||
>
|
||||
{{ submitting ? '提交中...' : '确认提现' }}
|
||||
|
||||
@@ -6,47 +6,49 @@
|
||||
:root,
|
||||
page {
|
||||
/* === 品牌色 Brand Colors === */
|
||||
--brand-primary: #1677ff; /* 主色 - 蓝色 */
|
||||
--brand-primary-light: #4096ff; /* 主色浅 */
|
||||
--brand-primary-dark: #0958d9; /* 主色深 */
|
||||
--brand-secondary: #1e293b; /* 辅色 - 深灰/黑色 */
|
||||
--brand-accent: #ffffff; /* 强调 - 白色 */
|
||||
--brand-primary: #2f7d32; /* 主色 */
|
||||
--brand-primary-light: #5a9f5d; /* 主色浅 */
|
||||
--brand-primary-dark: #245f27; /* 主色深 */
|
||||
--brand-secondary: #1f2937; /* 辅色 */
|
||||
--brand-tertiary: #f4fbf5; /* 次色 */
|
||||
--brand-accent: #ffffff; /* 强调白 */
|
||||
|
||||
/* === 语义色 Semantic Colors === */
|
||||
--color-success: #52c41a; /* 成功 - Green */
|
||||
--color-success-bg: #f6ffed; /* 成功背景 */
|
||||
--color-warning: #faad14; /* 警告 - Amber */
|
||||
--color-warning-bg: #fffbe6; /* 警告背景 */
|
||||
--color-error: #ff4d4f; /* 错误 - Red */
|
||||
--color-error-bg: #fff2f0; /* 错误背景 */
|
||||
--color-info: #1677ff; /* 信息 - Blue(同主色) */
|
||||
--color-info-bg: #e6f7ff; /* 信息背景 */
|
||||
--color-success: #2f7d32;
|
||||
--color-success-bg: #edf7ee;
|
||||
--color-warning: #b7791f;
|
||||
--color-warning-bg: #fff7e6;
|
||||
--color-error: #c24141;
|
||||
--color-error-bg: #fdf1f1;
|
||||
--color-info: var(--brand-primary);
|
||||
--color-info-bg: var(--brand-tertiary);
|
||||
|
||||
/* === 文字色阶 Text Colors === */
|
||||
--text-primary: #212121; /* 标题/重要文字 */
|
||||
--text-secondary: #666666; /* 正文 */
|
||||
--text-tertiary: #999999; /* 辅助信息 */
|
||||
--text-quaternary: #cccccc; /* 禁用/占位符 */
|
||||
--text-inverse: #ffffff; /* 反色文字 */
|
||||
--text-primary: #1f2937;
|
||||
--text-secondary: #4b5563;
|
||||
--text-tertiary: #6b7280;
|
||||
--text-quaternary: #9ca3af;
|
||||
--text-inverse: #ffffff;
|
||||
|
||||
/* === 背景色 Background Colors === */
|
||||
--bg-page: #faf0f5; /* 页面背景 */
|
||||
--bg-container: #ffffff; /* 容器/卡片背景 */
|
||||
--bg-elevated: #ffffff; /* 悬浮层背景 */
|
||||
--bg-muted: #f5f5f5; /* 静音背景 */
|
||||
--bg-overlay: rgba(0, 0, 0, 0.45); /* 遮罩层 */
|
||||
--bg-page: var(--brand-tertiary);
|
||||
--bg-container: #ffffff;
|
||||
--bg-elevated: #ffffff;
|
||||
--bg-muted: #f8faf8;
|
||||
--bg-overlay: rgba(31, 41, 55, 0.45);
|
||||
|
||||
/* === 边框色 Border Colors === */
|
||||
--border-primary: #e8e8e8; /* 主边框 */
|
||||
--border-secondary: #f0f0f0; /* 次边框 */
|
||||
--border-light: #fafafa; /* 浅边框 */
|
||||
--border-primary: #e3ece4;
|
||||
--border-secondary: #edf2ee;
|
||||
--border-light: #f7faf7;
|
||||
|
||||
/* === 阴影 Shadows === */
|
||||
--shadow-sm: 0 1px 3px 0 rgba(0, 0, 0, 0.06);
|
||||
--shadow-md: 0 2px 8px 0 rgba(0, 0, 0, 0.08);
|
||||
--shadow-lg: 0 4px 16px 0 rgba(0, 0, 0, 0.12);
|
||||
--shadow-xl: 0 8px 24px 0 rgba(0, 0, 0, 0.15);
|
||||
--shadow-brand: 0 4px 12px 0 rgba(22, 119, 255, 0.2);
|
||||
--shadow-xs: 0 1px 2px 0 rgba(31, 41, 55, 0.04);
|
||||
--shadow-sm: 0 1px 3px 0 rgba(31, 41, 55, 0.06);
|
||||
--shadow-md: 0 4px 12px 0 rgba(31, 41, 55, 0.08);
|
||||
--shadow-lg: 0 8px 20px 0 rgba(31, 41, 55, 0.12);
|
||||
--shadow-xl: 0 12px 28px 0 rgba(31, 41, 55, 0.16);
|
||||
--shadow-brand: 0 6px 18px 0 rgba(47, 125, 50, 0.18);
|
||||
|
||||
/* === 圆角 Radius === */
|
||||
--radius-xs: 4px;
|
||||
@@ -96,38 +98,53 @@ page {
|
||||
--z-popover: 1060;
|
||||
--z-tooltip: 1070;
|
||||
--z-toast: 1080;
|
||||
|
||||
/* === 兼容主题别名 Compatibility Theme Aliases === */
|
||||
--theme-primary: var(--brand-primary);
|
||||
--theme-primary-light: var(--brand-primary-light);
|
||||
--theme-primary-dark: var(--brand-primary-dark);
|
||||
--theme-success: var(--color-success);
|
||||
--theme-warning: var(--color-warning);
|
||||
--theme-error: var(--color-error);
|
||||
--theme-main-color: var(--text-primary);
|
||||
--theme-content-color: var(--text-secondary);
|
||||
--theme-tips-color: var(--text-tertiary);
|
||||
--theme-light-color: var(--text-quaternary);
|
||||
--theme-disabled-color: var(--text-quaternary);
|
||||
--theme-bg-color: var(--bg-page);
|
||||
--theme-bg-color-secondary: var(--bg-container);
|
||||
--theme-border-color: var(--border-primary);
|
||||
}
|
||||
|
||||
/* === 暗色主题 Dark Theme === */
|
||||
.theme-dark {
|
||||
--brand-primary: #4b9cff; /* 暗色下蓝色更柔和 */
|
||||
--brand-primary-light: #69b1ff;
|
||||
--brand-primary-dark: #1668dc;
|
||||
--color-success: #73d13d;
|
||||
--color-warning: #ffc53d;
|
||||
--color-error: #ff7875;
|
||||
--color-info: #4b9cff;
|
||||
--brand-primary-light: #74b377;
|
||||
--brand-primary-dark: #245f27;
|
||||
--color-warning: #f0b451;
|
||||
--color-error: #ef7f7f;
|
||||
|
||||
--text-primary: #ffffff;
|
||||
--text-secondary: #b0b8c1;
|
||||
--text-tertiary: #8a8f95;
|
||||
--text-quaternary: #6c757d;
|
||||
--text-inverse: #1a1a1a;
|
||||
--text-primary: #f8fafc;
|
||||
--text-secondary: #cbd5e1;
|
||||
--text-tertiary: #94a3b8;
|
||||
--text-quaternary: #64748b;
|
||||
--text-inverse: #111827;
|
||||
|
||||
--bg-page: #1a1a1a;
|
||||
--bg-container: #2d2d2d;
|
||||
--bg-elevated: #3a3a3a;
|
||||
--bg-muted: #242424;
|
||||
--bg-page: #111827;
|
||||
--bg-container: #1f2937;
|
||||
--bg-elevated: #273548;
|
||||
--bg-muted: #182232;
|
||||
--bg-overlay: rgba(0, 0, 0, 0.65);
|
||||
|
||||
--border-primary: #3a3a3a;
|
||||
--border-secondary: #2d2d2d;
|
||||
--border-light: #242424;
|
||||
--border-primary: #314155;
|
||||
--border-secondary: #273548;
|
||||
--border-light: #1f2937;
|
||||
|
||||
--shadow-xs: 0 1px 2px 0 rgba(0, 0, 0, 0.2);
|
||||
--shadow-sm: 0 1px 3px 0 rgba(0, 0, 0, 0.3);
|
||||
--shadow-md: 0 2px 8px 0 rgba(0, 0, 0, 0.4);
|
||||
--shadow-lg: 0 4px 16px 0 rgba(0, 0, 0, 0.5);
|
||||
--shadow-xl: 0 8px 24px 0 rgba(0, 0, 0, 0.6);
|
||||
--shadow-md: 0 4px 12px 0 rgba(0, 0, 0, 0.35);
|
||||
--shadow-lg: 0 8px 20px 0 rgba(0, 0, 0, 0.45);
|
||||
--shadow-xl: 0 12px 28px 0 rgba(0, 0, 0, 0.55);
|
||||
--shadow-brand: 0 6px 18px 0 rgba(47, 125, 50, 0.22);
|
||||
}
|
||||
|
||||
/* === 全局重置 Global Resets === */
|
||||
@@ -144,7 +161,9 @@ page {
|
||||
.text-primary { color: var(--text-primary); }
|
||||
.text-secondary { color: var(--text-secondary); }
|
||||
.text-tertiary { color: var(--text-tertiary); }
|
||||
.text-quaternary { color: var(--text-quaternary); }
|
||||
.text-brand { color: var(--brand-primary); }
|
||||
.text-brand-secondary { color: var(--brand-secondary); }
|
||||
.text-success { color: var(--color-success); }
|
||||
.text-warning { color: var(--color-warning); }
|
||||
.text-error { color: var(--color-error); }
|
||||
@@ -153,13 +172,15 @@ page {
|
||||
.bg-container { background-color: var(--bg-container); }
|
||||
.bg-muted { background-color: var(--bg-muted); }
|
||||
.bg-brand { background-color: var(--brand-primary); }
|
||||
.bg-brand-secondary { background-color: var(--brand-secondary); }
|
||||
.bg-brand-tertiary { background-color: var(--brand-tertiary); }
|
||||
.bg-brand-light { background-color: var(--brand-primary-light); }
|
||||
.bg-brand-dark { background-color: var(--brand-primary-dark); }
|
||||
|
||||
.bg-gradient-brand { background: linear-gradient(135deg, var(--brand-primary), var(--brand-primary-light)); }
|
||||
.shadow-brand-colored { box-shadow: 0 4px 16px rgba(22, 119, 255, 0.3); }
|
||||
.shadow-brand-sm { box-shadow: 0 2px 12px rgba(22, 119, 255, 0.15); }
|
||||
.shadow-brand-xs { box-shadow: 0 2px 8px rgba(22, 119, 255, 0.2); }
|
||||
.shadow-brand-colored { box-shadow: 0 8px 22px rgba(47, 125, 50, 0.22); }
|
||||
.shadow-brand-sm { box-shadow: 0 4px 14px rgba(47, 125, 50, 0.14); }
|
||||
.shadow-brand-xs { box-shadow: 0 2px 8px rgba(47, 125, 50, 0.16); }
|
||||
|
||||
.border-brand { border-color: var(--brand-primary); }
|
||||
|
||||
@@ -241,7 +262,7 @@ page {
|
||||
.input:focus {
|
||||
border-color: var(--brand-primary);
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 3px rgba(22, 119, 255, 0.1);
|
||||
box-shadow: 0 0 0 3px rgba(47, 125, 50, 0.12);
|
||||
}
|
||||
|
||||
.input::placeholder {
|
||||
|
||||
24
src/uni.scss
24
src/uni.scss
@@ -4,24 +4,24 @@
|
||||
/* 颜色变量 - 使用CSS变量支持主题切换 */
|
||||
|
||||
/* 行为相关颜色 */
|
||||
$u-primary: var(--theme-primary);
|
||||
$u-primary-dark: var(--theme-primary-dark);
|
||||
$u-success: var(--theme-success);
|
||||
$u-warning: var(--theme-warning);
|
||||
$u-error: var(--theme-error);
|
||||
$u-primary: var(--brand-primary);
|
||||
$u-primary-dark: var(--brand-primary-dark);
|
||||
$u-success: var(--color-success);
|
||||
$u-warning: var(--color-warning);
|
||||
$u-error: var(--color-error);
|
||||
|
||||
/* 文字基本颜色 */
|
||||
$u-main-color: var(--theme-main-color);
|
||||
$u-content-color: var(--theme-content-color);
|
||||
$u-tips-color: var(--theme-tips-color);
|
||||
$u-light-color: var(--theme-light-color);
|
||||
$u-disabled-color: var(--theme-disabled-color);
|
||||
$u-main-color: var(--text-primary);
|
||||
$u-content-color: var(--text-secondary);
|
||||
$u-tips-color: var(--text-tertiary);
|
||||
$u-light-color: var(--text-quaternary);
|
||||
$u-disabled-color: var(--text-quaternary);
|
||||
|
||||
/* 背景颜色 */
|
||||
$u-bg-color: var(--theme-bg-color);
|
||||
$u-bg-color: var(--bg-page);
|
||||
|
||||
/* 边框颜色 */
|
||||
$u-border-color: var(--theme-border-color);
|
||||
$u-border-color: var(--border-primary);
|
||||
|
||||
/* 尺寸变量 */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user