增加前端格式检查配置
This commit is contained in:
@@ -1,256 +1,256 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, reactive, ref } from "vue";
|
||||
import { useRouter, useRoute } from "vue-router";
|
||||
import { useSessionStore } from "@/stores/session";
|
||||
import { showDialog, showToast } from "vant";
|
||||
import MobileBottomNav from "@/components/MobileBottomNav.vue";
|
||||
import { computed, onMounted, reactive, ref } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { useSessionStore } from '@/stores/session'
|
||||
import { showDialog, showToast } from 'vant'
|
||||
import MobileBottomNav from '@/components/MobileBottomNav.vue'
|
||||
|
||||
import { fetchWalletBalance, fetchWalletLedger, type WalletLedger } from "@/features/wallet/api/wallet";
|
||||
import { fetchPostRentalNotice, type PostRentalNotice } from "@/features/orders/api/orders";
|
||||
import { formatDateMinute } from "@/utils/time";
|
||||
import { uploadFile } from "@/shared/api/files";
|
||||
import {
|
||||
fetchWalletBalance,
|
||||
fetchWalletLedger,
|
||||
type WalletLedger,
|
||||
} from '@/features/wallet/api/wallet'
|
||||
import { fetchPostRentalNotice, type PostRentalNotice } from '@/features/orders/api/orders'
|
||||
import { formatDateMinute } from '@/utils/time'
|
||||
import { uploadFile } from '@/shared/api/files'
|
||||
|
||||
const session = useSessionStore();
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const session = useSessionStore()
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
/** 数据项 */
|
||||
const balance = ref(0);
|
||||
const showSettings = ref(false);
|
||||
const showProfileEditor = ref(false);
|
||||
const savingProfile = ref(false);
|
||||
const balance = ref(0)
|
||||
const showSettings = ref(false)
|
||||
const showProfileEditor = ref(false)
|
||||
const savingProfile = ref(false)
|
||||
const profileForm = reactive({
|
||||
nickname: "",
|
||||
avatar_url: "",
|
||||
});
|
||||
nickname: '',
|
||||
avatar_url: '',
|
||||
})
|
||||
|
||||
const avatarFileInput = ref<HTMLInputElement | null>(null);
|
||||
const uploadingAvatar = ref(false);
|
||||
const avatarFileInput = ref<HTMLInputElement | null>(null)
|
||||
const uploadingAvatar = ref(false)
|
||||
|
||||
function triggerAvatarUpload() {
|
||||
avatarFileInput.value?.click();
|
||||
avatarFileInput.value?.click()
|
||||
}
|
||||
|
||||
async function handleAvatarFileChange(event: Event) {
|
||||
const input = event.target as HTMLInputElement;
|
||||
const file = input.files?.[0];
|
||||
input.value = "";
|
||||
if (!file) return;
|
||||
const input = event.target as HTMLInputElement
|
||||
const file = input.files?.[0]
|
||||
input.value = ''
|
||||
if (!file) return
|
||||
|
||||
uploadingAvatar.value = true;
|
||||
uploadingAvatar.value = true
|
||||
const toast = showToast({
|
||||
type: "loading",
|
||||
message: "上传中...",
|
||||
type: 'loading',
|
||||
message: '上传中...',
|
||||
forbidClick: true,
|
||||
duration: 0,
|
||||
});
|
||||
})
|
||||
|
||||
try {
|
||||
const uploaded = await uploadFile(file, "avatar");
|
||||
profileForm.avatar_url = uploaded.url;
|
||||
showToast({ message: "上传成功", icon: "passed" });
|
||||
const uploaded = await uploadFile(file, 'avatar')
|
||||
profileForm.avatar_url = uploaded.url
|
||||
showToast({ message: '上传成功', icon: 'passed' })
|
||||
} catch (error) {
|
||||
showToast({ message: readError(error, "上传失败"), icon: "cross" });
|
||||
showToast({ message: readError(error, '上传失败'), icon: 'cross' })
|
||||
} finally {
|
||||
uploadingAvatar.value = false;
|
||||
uploadingAvatar.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 收支明细列表
|
||||
const showLedgers = ref(false);
|
||||
const loadingLedgers = ref(false);
|
||||
const ledgers = ref<WalletLedger[]>([]);
|
||||
const showLedgers = ref(false)
|
||||
const loadingLedgers = ref(false)
|
||||
const ledgers = ref<WalletLedger[]>([])
|
||||
|
||||
// 租后须知
|
||||
const showPostRentalNotice = ref(false);
|
||||
const loadingPostRentalNotice = ref(false);
|
||||
const postRentalNotice = ref<PostRentalNotice | null>(null);
|
||||
const showPostRentalNotice = ref(false)
|
||||
const loadingPostRentalNotice = ref(false)
|
||||
const postRentalNotice = ref<PostRentalNotice | null>(null)
|
||||
|
||||
const settingsGroups = [
|
||||
{
|
||||
title: "账号与安全",
|
||||
title: '账号与安全',
|
||||
items: [
|
||||
{ label: "资料更改", icon: "edit", action: "profile" },
|
||||
{ label: "实名认证", icon: "idcard", action: "realname" },
|
||||
{ label: "注销账号", icon: "delete-o", action: "cancel-account" },
|
||||
{ label: '资料更改', icon: 'edit', action: 'profile' },
|
||||
{ label: '实名认证', icon: 'idcard', action: 'realname' },
|
||||
{ label: '注销账号', icon: 'delete-o', action: 'cancel-account' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "法律与隐私",
|
||||
title: '法律与隐私',
|
||||
items: [
|
||||
{ label: "隐私政策", icon: "shield-o", action: "privacy" },
|
||||
{ label: "用户协议", icon: "description", action: "terms" },
|
||||
{ label: '隐私政策', icon: 'shield-o', action: 'privacy' },
|
||||
{ label: '用户协议', icon: 'description', action: 'terms' },
|
||||
],
|
||||
},
|
||||
];
|
||||
]
|
||||
|
||||
onMounted(() => {
|
||||
if (!isLoggedIn.value) {
|
||||
router.replace({ path: "/m/login", query: { redirect: route.fullPath } });
|
||||
router.replace({ path: '/m/login', query: { redirect: route.fullPath } })
|
||||
} else {
|
||||
loadBalance();
|
||||
loadBalance()
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
async function loadBalance() {
|
||||
try {
|
||||
const wallet = await fetchWalletBalance();
|
||||
balance.value = wallet.available_balance;
|
||||
const wallet = await fetchWalletBalance()
|
||||
balance.value = wallet.available_balance
|
||||
} catch {
|
||||
// 失败静默处理,显示为默认0
|
||||
}
|
||||
}
|
||||
|
||||
async function openLedgers() {
|
||||
showLedgers.value = true;
|
||||
loadingLedgers.value = true;
|
||||
showLedgers.value = true
|
||||
loadingLedgers.value = true
|
||||
try {
|
||||
const res = await fetchWalletLedger(1, 20);
|
||||
ledgers.value = res.items;
|
||||
const res = await fetchWalletLedger(1, 20)
|
||||
ledgers.value = res.items
|
||||
} catch {
|
||||
showToast({ message: "无法获取账单明细", icon: "cross" });
|
||||
showToast({ message: '无法获取账单明细', icon: 'cross' })
|
||||
} finally {
|
||||
loadingLedgers.value = false;
|
||||
loadingLedgers.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function openPostRentalNotice() {
|
||||
showPostRentalNotice.value = true;
|
||||
showPostRentalNotice.value = true
|
||||
if (!postRentalNotice.value) {
|
||||
loadingPostRentalNotice.value = true;
|
||||
loadingPostRentalNotice.value = true
|
||||
try {
|
||||
postRentalNotice.value = await fetchPostRentalNotice();
|
||||
postRentalNotice.value = await fetchPostRentalNotice()
|
||||
} catch {
|
||||
showToast({ message: "无法获取租后须知", icon: "cross" });
|
||||
showToast({ message: '无法获取租后须知', icon: 'cross' })
|
||||
} finally {
|
||||
loadingPostRentalNotice.value = false;
|
||||
loadingPostRentalNotice.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleWithdraw() {
|
||||
showDialog({
|
||||
title: "提现提示",
|
||||
message: "为了您的资金安全,提现请前往电脑端网页版进行操作。",
|
||||
});
|
||||
title: '提现提示',
|
||||
message: '为了您的资金安全,提现请前往电脑端网页版进行操作。',
|
||||
})
|
||||
}
|
||||
|
||||
function goOrders(tabKey: string) {
|
||||
router.push({ path: "/m/orders", query: { tab: tabKey } });
|
||||
router.push({ path: '/m/orders', query: { tab: tabKey } })
|
||||
}
|
||||
|
||||
function onSettingClick(action: string) {
|
||||
showSettings.value = false;
|
||||
showSettings.value = false
|
||||
switch (action) {
|
||||
case "profile":
|
||||
openProfileEditor();
|
||||
break;
|
||||
case "realname":
|
||||
router.push("/m/realname");
|
||||
break;
|
||||
case "cancel-account":
|
||||
case 'profile':
|
||||
openProfileEditor()
|
||||
break
|
||||
case 'realname':
|
||||
router.push('/m/realname')
|
||||
break
|
||||
case 'cancel-account':
|
||||
showDialog({
|
||||
title: "注销账号",
|
||||
message: "注销后账号数据将无法恢复,确认注销吗?",
|
||||
title: '注销账号',
|
||||
message: '注销后账号数据将无法恢复,确认注销吗?',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: "确认注销",
|
||||
confirmButtonColor: "#ee0a24",
|
||||
cancelButtonText: "再想想",
|
||||
confirmButtonText: '确认注销',
|
||||
confirmButtonColor: '#ee0a24',
|
||||
cancelButtonText: '再想想',
|
||||
})
|
||||
.then(() => {
|
||||
showToast({ message: "注销功能开发中", icon: "info-o" });
|
||||
showToast({ message: '注销功能开发中', icon: 'info-o' })
|
||||
})
|
||||
.catch(() => {});
|
||||
break;
|
||||
case "privacy":
|
||||
showToast({ message: "隐私政策页面开发中", icon: "info-o" });
|
||||
break;
|
||||
case "terms":
|
||||
showToast({ message: "用户协议页面开发中", icon: "info-o" });
|
||||
break;
|
||||
.catch(() => {})
|
||||
break
|
||||
case 'privacy':
|
||||
showToast({ message: '隐私政策页面开发中', icon: 'info-o' })
|
||||
break
|
||||
case 'terms':
|
||||
showToast({ message: '用户协议页面开发中', icon: 'info-o' })
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
function openProfileEditor() {
|
||||
profileForm.nickname = session.nickname || defaultName.value;
|
||||
profileForm.avatar_url = session.avatarUrl || "";
|
||||
showProfileEditor.value = true;
|
||||
profileForm.nickname = session.nickname || defaultName.value
|
||||
profileForm.avatar_url = session.avatarUrl || ''
|
||||
showProfileEditor.value = true
|
||||
}
|
||||
|
||||
async function saveProfile() {
|
||||
const nickname = profileForm.nickname.trim();
|
||||
const avatarURL = profileForm.avatar_url.trim();
|
||||
const nickname = profileForm.nickname.trim()
|
||||
const avatarURL = profileForm.avatar_url.trim()
|
||||
if (!nickname) {
|
||||
showToast({ message: "请输入昵称", icon: "warning-o" });
|
||||
return;
|
||||
showToast({ message: '请输入昵称', icon: 'warning-o' })
|
||||
return
|
||||
}
|
||||
if (nickname.length > 24) {
|
||||
showToast({ message: "昵称不能超过 24 个字符", icon: "warning-o" });
|
||||
return;
|
||||
showToast({ message: '昵称不能超过 24 个字符', icon: 'warning-o' })
|
||||
return
|
||||
}
|
||||
|
||||
savingProfile.value = true;
|
||||
savingProfile.value = true
|
||||
try {
|
||||
await session.updateProfile({ nickname, avatar_url: avatarURL });
|
||||
showProfileEditor.value = false;
|
||||
showToast({ message: "资料已更新", icon: "passed" });
|
||||
await loadBalance();
|
||||
await session.updateProfile({ nickname, avatar_url: avatarURL })
|
||||
showProfileEditor.value = false
|
||||
showToast({ message: '资料已更新', icon: 'passed' })
|
||||
await loadBalance()
|
||||
} catch (error) {
|
||||
showToast({ message: readError(error, "资料更新失败"), icon: "cross" });
|
||||
showToast({ message: readError(error, '资料更新失败'), icon: 'cross' })
|
||||
} finally {
|
||||
savingProfile.value = false;
|
||||
savingProfile.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function readError(error: unknown, fallback: string) {
|
||||
if (typeof error === "object" && error && "response" in error) {
|
||||
const response = (error as { response?: { data?: { message?: string } } }).response;
|
||||
return response?.data?.message || fallback;
|
||||
if (typeof error === 'object' && error && 'response' in error) {
|
||||
const response = (error as { response?: { data?: { message?: string } } }).response
|
||||
return response?.data?.message || fallback
|
||||
}
|
||||
return fallback;
|
||||
return fallback
|
||||
}
|
||||
|
||||
function confirmLogout() {
|
||||
showSettings.value = false;
|
||||
showSettings.value = false
|
||||
showDialog({
|
||||
title: "退出登录",
|
||||
message: "确定要退出当前账号吗?",
|
||||
title: '退出登录',
|
||||
message: '确定要退出当前账号吗?',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: "退出",
|
||||
confirmButtonColor: "#ee0a24",
|
||||
cancelButtonText: "取消",
|
||||
confirmButtonText: '退出',
|
||||
confirmButtonColor: '#ee0a24',
|
||||
cancelButtonText: '取消',
|
||||
})
|
||||
.then(() => {
|
||||
session.logout();
|
||||
router.replace("/m");
|
||||
session.logout()
|
||||
router.replace('/m')
|
||||
})
|
||||
.catch(() => {});
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const isLoggedIn = computed(() => Boolean(session.token));
|
||||
const isRealnameVerified = computed(() => session.realnameStatus === "verified");
|
||||
const isRealnamePending = computed(() => session.realnameStatus === "pending");
|
||||
const isLoggedIn = computed(() => Boolean(session.token))
|
||||
const isRealnameVerified = computed(() => session.realnameStatus === 'verified')
|
||||
const isRealnamePending = computed(() => session.realnameStatus === 'pending')
|
||||
|
||||
const defaultName = computed(() =>
|
||||
session.phone
|
||||
? `用户${session.phone.slice(-6)}`
|
||||
: `用户${session.userId || 883099}`
|
||||
);
|
||||
const displayName = computed(() => session.nickname || defaultName.value);
|
||||
const displayId = computed(() => session.userId || 138865);
|
||||
session.phone ? `用户${session.phone.slice(-6)}` : `用户${session.userId || 883099}`
|
||||
)
|
||||
const displayName = computed(() => session.nickname || defaultName.value)
|
||||
const displayId = computed(() => session.userId || 138865)
|
||||
const maskedPhone = computed(() =>
|
||||
session.phone
|
||||
? `${session.phone.slice(0, 3)}****${session.phone.slice(-4)}`
|
||||
: "登录后查看手机号"
|
||||
);
|
||||
const avatarText = computed(() => displayName.value.slice(0, 1));
|
||||
session.phone ? `${session.phone.slice(0, 3)}****${session.phone.slice(-4)}` : '登录后查看手机号'
|
||||
)
|
||||
const avatarText = computed(() => displayName.value.slice(0, 1))
|
||||
|
||||
function resolveAvatarURL(url: string | undefined | null) {
|
||||
if (!url) return "";
|
||||
if (url.includes("/api/files/object?key=avatar/")) {
|
||||
return url.replace("/api/files/object", "/api/public/files/object");
|
||||
if (!url) return ''
|
||||
if (url.includes('/api/files/object?key=avatar/')) {
|
||||
return url.replace('/api/files/object', '/api/public/files/object')
|
||||
}
|
||||
return url;
|
||||
return url
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -276,13 +276,32 @@ function resolveAvatarURL(url: string | undefined | null) {
|
||||
<div class="hero-user">
|
||||
<div class="name-row">
|
||||
<h1 class="user-nickname">{{ displayName }}</h1>
|
||||
<van-tag v-if="isRealnameVerified" type="success" size="medium" round class="verified-tag">
|
||||
<van-tag
|
||||
v-if="isRealnameVerified"
|
||||
type="success"
|
||||
size="medium"
|
||||
round
|
||||
class="verified-tag"
|
||||
>
|
||||
<van-icon name="shield" /> 已实名
|
||||
</van-tag>
|
||||
<van-tag v-else-if="isRealnamePending" type="warning" size="medium" round class="verified-tag">
|
||||
<van-tag
|
||||
v-else-if="isRealnamePending"
|
||||
type="warning"
|
||||
size="medium"
|
||||
round
|
||||
class="verified-tag"
|
||||
>
|
||||
审核中
|
||||
</van-tag>
|
||||
<van-tag v-else type="danger" size="medium" round class="unverified-tag" @click="router.push('/m/realname')">
|
||||
<van-tag
|
||||
v-else
|
||||
type="danger"
|
||||
size="medium"
|
||||
round
|
||||
class="unverified-tag"
|
||||
@click="router.push('/m/realname')"
|
||||
>
|
||||
未实名
|
||||
</van-tag>
|
||||
</div>
|
||||
@@ -416,7 +435,9 @@ function resolveAvatarURL(url: string | undefined | null) {
|
||||
<button class="popup-close" @click="showPostRentalNotice = false">✕</button>
|
||||
</header>
|
||||
<div class="popup-body">
|
||||
<van-loading v-if="loadingPostRentalNotice" class="center-loading" vertical>加载中...</van-loading>
|
||||
<van-loading v-if="loadingPostRentalNotice" class="center-loading" vertical
|
||||
>加载中...</van-loading
|
||||
>
|
||||
<div v-else-if="postRentalNotice" class="notice-content">
|
||||
{{ postRentalNotice.content }}
|
||||
</div>
|
||||
@@ -438,11 +459,7 @@ function resolveAvatarURL(url: string | undefined | null) {
|
||||
</button>
|
||||
</header>
|
||||
|
||||
<div
|
||||
v-for="group in settingsGroups"
|
||||
:key="group.title"
|
||||
class="settings-group"
|
||||
>
|
||||
<div v-for="group in settingsGroups" :key="group.title" class="settings-group">
|
||||
<h3 class="settings-group-title">{{ group.title }}</h3>
|
||||
<van-cell-group :border="false">
|
||||
<van-cell
|
||||
@@ -457,9 +474,7 @@ function resolveAvatarURL(url: string | undefined | null) {
|
||||
</div>
|
||||
|
||||
<div class="settings-logout">
|
||||
<van-button plain type="danger" block round @click="confirmLogout">
|
||||
退出登录
|
||||
</van-button>
|
||||
<van-button plain type="danger" block round @click="confirmLogout"> 退出登录 </van-button>
|
||||
</div>
|
||||
</div>
|
||||
</van-popup>
|
||||
@@ -481,7 +496,11 @@ function resolveAvatarURL(url: string | undefined | null) {
|
||||
|
||||
<div class="profile-preview">
|
||||
<div class="profile-preview-avatar clickable" @click="triggerAvatarUpload">
|
||||
<img v-if="profileForm.avatar_url" :src="resolveAvatarURL(profileForm.avatar_url)" alt="" />
|
||||
<img
|
||||
v-if="profileForm.avatar_url"
|
||||
:src="resolveAvatarURL(profileForm.avatar_url)"
|
||||
alt=""
|
||||
/>
|
||||
<span v-else>{{ (profileForm.nickname || defaultName).slice(0, 1) }}</span>
|
||||
<div class="avatar-upload-overlay">
|
||||
<van-icon name="photograph" :size="16" />
|
||||
@@ -516,11 +535,7 @@ function resolveAvatarURL(url: string | undefined | null) {
|
||||
|
||||
<label class="editor-field">
|
||||
<span>昵称</span>
|
||||
<input
|
||||
v-model="profileForm.nickname"
|
||||
maxlength="24"
|
||||
placeholder="请输入昵称"
|
||||
/>
|
||||
<input v-model="profileForm.nickname" maxlength="24" placeholder="请输入昵称" />
|
||||
</label>
|
||||
|
||||
<label class="editor-field">
|
||||
@@ -640,7 +655,8 @@ function resolveAvatarURL(url: string | undefined | null) {
|
||||
color: #111827;
|
||||
}
|
||||
|
||||
.verified-tag, .unverified-tag {
|
||||
.verified-tag,
|
||||
.unverified-tag {
|
||||
font-size: 10px !important;
|
||||
height: 18px;
|
||||
padding: 0 6px;
|
||||
@@ -660,7 +676,9 @@ function resolveAvatarURL(url: string | undefined | null) {
|
||||
padding: 16px;
|
||||
border-radius: 16px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.02), 0 1px 4px rgba(0, 0, 0, 0.02);
|
||||
box-shadow:
|
||||
0 4px 16px rgba(0, 0, 0, 0.02),
|
||||
0 1px 4px rgba(0, 0, 0, 0.02);
|
||||
border: 1px solid rgba(243, 244, 246, 0.9);
|
||||
}
|
||||
|
||||
@@ -699,7 +717,9 @@ function resolveAvatarURL(url: string | undefined | null) {
|
||||
padding: 0 16px;
|
||||
border-radius: 999px;
|
||||
cursor: pointer;
|
||||
transition: background 0.15s, color 0.15s;
|
||||
transition:
|
||||
background 0.15s,
|
||||
color 0.15s;
|
||||
}
|
||||
|
||||
.withdraw-btn:active {
|
||||
@@ -732,7 +752,9 @@ function resolveAvatarURL(url: string | undefined | null) {
|
||||
background: #ffffff;
|
||||
border-radius: 16px;
|
||||
padding: 16px;
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.02), 0 1px 4px rgba(0, 0, 0, 0.02);
|
||||
box-shadow:
|
||||
0 4px 16px rgba(0, 0, 0, 0.02),
|
||||
0 1px 4px rgba(0, 0, 0, 0.02);
|
||||
border: 1px solid rgba(243, 244, 246, 0.9);
|
||||
}
|
||||
|
||||
@@ -801,13 +823,34 @@ function resolveAvatarURL(url: string | undefined | null) {
|
||||
}
|
||||
|
||||
/* Vibrant pastel colors for menu icon wraps */
|
||||
.icon-wrap.warning { color: #f59e0b; background: rgba(245, 158, 11, 0.08); }
|
||||
.icon-wrap.info { color: #2563eb; background: rgba(37, 99, 235, 0.08); }
|
||||
.icon-wrap.primary { color: #1477ff; background: rgba(20, 119, 255, 0.08); }
|
||||
.icon-wrap.success { color: #10b981; background: rgba(16, 185, 129, 0.08); }
|
||||
.icon-wrap.orange { color: #ff5f00; background: rgba(255, 95, 0, 0.08); }
|
||||
.icon-wrap.purple { color: #8b5cf6; background: rgba(139, 92, 246, 0.08); }
|
||||
.icon-wrap.teal { color: #0d9488; background: rgba(13, 148, 136, 0.08); }
|
||||
.icon-wrap.warning {
|
||||
color: #f59e0b;
|
||||
background: rgba(245, 158, 11, 0.08);
|
||||
}
|
||||
.icon-wrap.info {
|
||||
color: #2563eb;
|
||||
background: rgba(37, 99, 235, 0.08);
|
||||
}
|
||||
.icon-wrap.primary {
|
||||
color: #1477ff;
|
||||
background: rgba(20, 119, 255, 0.08);
|
||||
}
|
||||
.icon-wrap.success {
|
||||
color: #10b981;
|
||||
background: rgba(16, 185, 129, 0.08);
|
||||
}
|
||||
.icon-wrap.orange {
|
||||
color: #ff5f00;
|
||||
background: rgba(255, 95, 0, 0.08);
|
||||
}
|
||||
.icon-wrap.purple {
|
||||
color: #8b5cf6;
|
||||
background: rgba(139, 92, 246, 0.08);
|
||||
}
|
||||
.icon-wrap.teal {
|
||||
color: #0d9488;
|
||||
background: rgba(13, 148, 136, 0.08);
|
||||
}
|
||||
|
||||
.grid-item span {
|
||||
font-size: 11px;
|
||||
|
||||
Reference in New Issue
Block a user