Commit 5517cfe7 authored by zhangsan's avatar zhangsan

'1'

parents
Pipeline #54 failed with stages
module.exports = {
root: true,
env: {
node: true
},
extends: [
'plugin:vue/vue3-essential',
'@vue/standard'
],
parserOptions: {
parser: '@babel/eslint-parser'
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'space-before-function-paren': 'off'
}
}
\ No newline at end of file
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
# Dependencies
node_modules
.pnpm-store
.yarn
# Build output
dist
dist-ssr
*.local
stats.html
# Editor directories and files
.vscode/*
!.vscode/extensions.json
!.vscode/settings.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
.DS_Store
# Environment files
.env
.env.*
!.env.example
# Testing
coverage
/cypress/videos/
/cypress/screenshots/
# Cache files
.cache
.temp
.eslintcache
.stylelintcache
*.tsbuildinfo
# Vite
vite.config.ts.timestamp-*
# Vue
*.vue.js
*.vue.jsx
*.vue.ts
*.vue.tsx
# Temporary files
*.tmp
*.bak
*.swp
*~
# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# Yarn
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
.pnp.*
\ No newline at end of file
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
export {}
declare module 'vue' {
export interface GlobalComponents {
NavBar: typeof import('./src/components/NavBar.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
VanButton: typeof import('vant/es')['Button']
VanCard: typeof import('vant/es')['Card']
VanCell: typeof import('vant/es')['Cell']
VanCellGroup: typeof import('vant/es')['CellGroup']
VanField: typeof import('vant/es')['Field']
VanForm: typeof import('vant/es')['Form']
VanGoodsAction: typeof import('vant/es')['GoodsAction']
VanGoodsActionButton: typeof import('vant/es')['GoodsActionButton']
VanGoodsActionIcon: typeof import('vant/es')['GoodsActionIcon']
VanGrid: typeof import('vant/es')['Grid']
VanGridItem: typeof import('vant/es')['GridItem']
VanImage: typeof import('vant/es')['Image']
VanNavBar: typeof import('vant/es')['NavBar']
VanSearch: typeof import('vant/es')['Search']
VanSwipe: typeof import('vant/es')['Swipe']
VanSwipeItem: typeof import('vant/es')['SwipeItem']
VanTabbar: typeof import('vant/es')['Tabbar']
VanTabbarItem: typeof import('vant/es')['TabbarItem']
VanTreeSelect: typeof import('vant/es')['TreeSelect']
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>Vue App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
\ No newline at end of file
{
"name": "vue-auto-update-app",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "vite --host 0.0.0.0 --port 3006",
"build": "vite build",
"type-check": "vue-tsc --noEmit",
"preview": "vite preview"
},
"dependencies": {
"@varlet/icons": "^2.22.8",
"@varlet/touch-emulator": "^2.22.8",
"@varlet/ui": "^2.22.8",
"axios": "^1.6.2",
"core-js": "^3.30.0",
"crypto-js": "^4.2.0",
"nprogress": "^0.2.0",
"qrcode": "^1.5.4",
"vant": "^4.8.0",
"vue": "^3.2.47",
"vue-router": "^4.2.0"
},
"devDependencies": {
"@types/crypto-js": "^4.2.2",
"@types/node": "^18.0.0",
"@types/nprogress": "^0.2.3",
"@vant/auto-import-resolver": "^1.0.1",
"@vitejs/plugin-legacy": "^5.0.0",
"@vitejs/plugin-vue": "^4.5.0",
"postcss": "^8.4.31",
"postcss-px-to-viewport": "^1.1.1",
"sass": "^1.84.0",
"terser": "^5.24.0",
"typescript": "^5.0.4",
"unplugin-auto-import": "^0.16.7",
"unplugin-vue-components": "^0.25.2",
"vite": "^5.0.0",
"vite-plugin-bundle-obfuscator": "^1.4.1",
"vue-tsc": "^1.6.4"
},
"browserslist": [
"Android >= 4.0",
"iOS >= 8",
"Chrome >= 49",
"Firefox >= 52",
"Safari >= 10",
"> 1%",
"last 2 versions",
"not dead"
],
"resolutions": {
"@varlet/ui": "^2.22.8"
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
\ No newline at end of file
<template>
<div class="app">
<router-view v-slot="{ Component }">
<keep-alive :include="['home', 'category', 'user']">
<component :is="Component" />
</keep-alive>
</router-view>
<page-loading />
</div>
</template>
<script lang="ts" setup>
import PageLoading from '@/components/PageLoading.vue'
</script>
<style>
/* 移动端适配 */
html {
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: transparent;
}
body {
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
user-select: none;
-webkit-user-select: none;
}
.app {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
}
/* 适配刘海屏 */
@supports (padding-top: constant(safe-area-inset-top)) {
.app {
padding-top: constant(safe-area-inset-top);
padding-bottom: constant(safe-area-inset-bottom);
}
}
@supports (padding-top: env(safe-area-inset-top)) {
.app {
padding-top: env(safe-area-inset-top);
padding-bottom: env(safe-area-inset-bottom);
}
}
</style>
\ No newline at end of file
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// noinspection JSUnusedGlobalSymbols
// Generated by unplugin-auto-import
export {}
declare global {
const EffectScope: typeof import('vue')['EffectScope']
const computed: typeof import('vue')['computed']
const createApp: typeof import('vue')['createApp']
const customRef: typeof import('vue')['customRef']
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
const defineComponent: typeof import('vue')['defineComponent']
const effectScope: typeof import('vue')['effectScope']
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
const getCurrentScope: typeof import('vue')['getCurrentScope']
const h: typeof import('vue')['h']
const inject: typeof import('vue')['inject']
const isProxy: typeof import('vue')['isProxy']
const isReactive: typeof import('vue')['isReactive']
const isReadonly: typeof import('vue')['isReadonly']
const isRef: typeof import('vue')['isRef']
const markRaw: typeof import('vue')['markRaw']
const nextTick: typeof import('vue')['nextTick']
const onActivated: typeof import('vue')['onActivated']
const onBeforeMount: typeof import('vue')['onBeforeMount']
const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave']
const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate']
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
const onDeactivated: typeof import('vue')['onDeactivated']
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
const onMounted: typeof import('vue')['onMounted']
const onRenderTracked: typeof import('vue')['onRenderTracked']
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
const onScopeDispose: typeof import('vue')['onScopeDispose']
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
const onUnmounted: typeof import('vue')['onUnmounted']
const onUpdated: typeof import('vue')['onUpdated']
const onWatcherCleanup: typeof import('vue')['onWatcherCleanup']
const provide: typeof import('vue')['provide']
const reactive: typeof import('vue')['reactive']
const readonly: typeof import('vue')['readonly']
const ref: typeof import('vue')['ref']
const resolveComponent: typeof import('vue')['resolveComponent']
const shallowReactive: typeof import('vue')['shallowReactive']
const shallowReadonly: typeof import('vue')['shallowReadonly']
const shallowRef: typeof import('vue')['shallowRef']
const showConfirmDialog: typeof import('vant/es')['showConfirmDialog']
const showDialog: typeof import('vant')['showDialog']
const showFailToast: typeof import('vant/es')['showFailToast']
const showNotify: typeof import('vant')['showNotify']
const showSuccessToast: typeof import('vant/es')['showSuccessToast']
const showToast: typeof import('vant/es')['showToast']
const toRaw: typeof import('vue')['toRaw']
const toRef: typeof import('vue')['toRef']
const toRefs: typeof import('vue')['toRefs']
const toValue: typeof import('vue')['toValue']
const triggerRef: typeof import('vue')['triggerRef']
const unref: typeof import('vue')['unref']
const useAttrs: typeof import('vue')['useAttrs']
const useCssModule: typeof import('vue')['useCssModule']
const useCssVars: typeof import('vue')['useCssVars']
const useId: typeof import('vue')['useId']
const useLink: typeof import('vue-router')['useLink']
const useModel: typeof import('vue')['useModel']
const useRoute: typeof import('vue-router')['useRoute']
const useRouter: typeof import('vue-router')['useRouter']
const useSlots: typeof import('vue')['useSlots']
const useTemplateRef: typeof import('vue')['useTemplateRef']
const watch: typeof import('vue')['watch']
const watchEffect: typeof import('vue')['watchEffect']
const watchPostEffect: typeof import('vue')['watchPostEffect']
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
}
// for type re-export
declare global {
// @ts-ignore
export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
import('vue')
}
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
export {}
declare module 'vue' {
export interface GlobalComponents {
GuideModal: typeof import('./components/GuideModal.vue')['default']
NavBar: typeof import('./components/NavBar.vue')['default']
NewsCard: typeof import('./components/NewsCard.vue')['default']
PageLoading: typeof import('./components/PageLoading.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
SignIn: typeof import('./components/signIn.vue')['default']
VanButton: typeof import('vant/es')['Button']
VanCell: typeof import('vant/es')['Cell']
VanCellGroup: typeof import('vant/es')['CellGroup']
VanField: typeof import('vant/es')['Field']
VanIcon: typeof import('vant/es')['Icon']
VanList: typeof import('vant/es')['List']
VanLoading: typeof import('vant/es')['Loading']
VanNavBar: typeof import('vant/es')['NavBar']
VanSwipe: typeof import('vant/es')['Swipe']
VanSwipeItem: typeof import('vant/es')['SwipeItem']
VanTabbar: typeof import('vant/es')['Tabbar']
VanTabbarItem: typeof import('vant/es')['TabbarItem']
VarButton: typeof import('@varlet/ui')['Button']
VarCard: typeof import('@varlet/ui')['Card']
VarCell: typeof import('@varlet/ui')['Cell']
VarCellGroup: typeof import('@varlet/ui')['CellGroup']
VarForm: typeof import('@varlet/ui')['Form']
VarIcon: typeof import('@varlet/ui')['Icon']
VarInput: typeof import('@varlet/ui')['Input']
VarPaper: typeof import('@varlet/ui')['Paper']
VarPopup: typeof import('@varlet/ui')['Popup']
VarRadio: typeof import('@varlet/ui')['Radio']
VarRadioGroup: typeof import('@varlet/ui')['RadioGroup']
VarSpace: typeof import('@varlet/ui')['Space']
VarTab: typeof import('@varlet/ui')['Tab']
VarTabs: typeof import('@varlet/ui')['Tabs']
}
export interface ComponentCustomProperties {
vRipple: typeof import('@varlet/ui')['Ripple']
}
}
<template>
<Teleport to="body">
<Transition name="fade">
<div v-if="visible" class="guide-modal-overlay" @click.self="handleClose">
<Transition :name="transitionName" mode="out-in" @before-leave="beforeLeave" @after-leave="afterLeave">
<div class="guide-modal" :key="currentIndex">
<!-- 使用插槽或v-html展示内容 -->
<div class="guide-content">
<slot :index="currentIndex">
<div v-html="guideList[currentIndex]?.notictBody"></div>
</slot>
</div>
<div class="guide-footer">
<button class="guide-button" @click="handleAction">
{{ isLastPage ? '我知道了' : '下一页' }}
</button>
</div>
</div>
</Transition>
</div>
</Transition>
</Teleport>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
interface Props {
guideList: string[]
modelValue: boolean
}
const props = defineProps<Props>()
const emit = defineEmits(['update:modelValue'])
const currentIndex = ref(0)
const slideDirection = ref('next')
const transitionName = computed(() => `slide-${slideDirection.value}`)
const visible = computed({
get: () => props.modelValue,
set: (value) => emit('update:modelValue', value)
})
const isLastPage = computed(() => currentIndex.value === props.guideList.length - 1)
const handleAction = () => {
if (isLastPage.value) {
handleClose()
} else {
slideDirection.value = 'next'
currentIndex.value++
}
}
const handleClose = () => {
visible.value = false
// 重置状态
setTimeout(() => {
currentIndex.value = 0
slideDirection.value = 'next'
}, 300)
}
const beforeLeave = () => {
document.body.style.overflow = 'hidden'
}
const afterLeave = () => {
document.body.style.overflow = ''
}
</script>
<style lang="scss" scoped>
.guide-modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
.guide-modal {
background: #fff;
border-radius: 5px;
width: 100%; // 调整宽度为90%
height: 80vh; // 设置高度为视口高度的70%
position: relative;
display: flex;
flex-direction: column;
overflow: hidden; // 防止内容溢出
}
.guide-content {
flex: 1;
overflow-y: auto; // 内容过多时可滚动
padding: 20px;
// 允许v-html内容继承样式
:deep(*) {
max-width: 100%;
height: auto;
}
}
.guide-footer {
background: #fff; // 确保底部背景色
border-top: 1px solid #eee;
}
.guide-button {
width: 100%; // 按钮宽度设为90%
margin: 0 auto;
display: block;
background: red;
color: #fff;
border: none;
padding: 12px 0;
font-size: 16px;
cursor: pointer;
transition: opacity 0.3s;
}
// 淡入淡出动画
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
// 滑动动画
.slide-next-enter-active,
.slide-next-leave-active,
.slide-prev-enter-active,
.slide-prev-leave-active {
transition: all 0.3s ease-out;
}
.slide-next-enter-from {
transform: translateX(100%);
opacity: 0;
}
.slide-next-leave-to {
transform: translateX(-100%);
opacity: 0;
}
.slide-prev-enter-from {
transform: translateX(-100%);
opacity: 0;
}
.slide-prev-leave-to {
transform: translateX(100%);
opacity: 0;
}
</style>
\ No newline at end of file
<template>
<van-nav-bar
:title="title"
left-arrow
@click-left="onClickLeft"
fixed
placeholder
/>
</template>
<script lang="ts" setup>
import { useRouter } from 'vue-router'
defineProps({
title: {
type: String,
default: ''
}
})
const router = useRouter()
const onClickLeft = () => {
router.back()
}
</script>
<style lang="scss" scoped>
:deep(.van-nav-bar) {
background-color: $primary-color;
.van-nav-bar__title {
color: #fff;
}
.van-icon {
color: #fff;
}
}
</style>
\ No newline at end of file
<template>
<div class="padding-box">
<div class="news-card">
<div v-for="item in props.content3" :key="item.id" class="news-item" @click="handleNewsClick(item)">
<div class="image-wrapper">
<img :src="getImageUrl(item.photo)" :alt="item.title" loading="lazy" />
</div>
<div class="content">
<h3 class="title">{{ item.title }}</h3>
<time class="subtitle">{{item.createTime}}</time>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
interface NewsItem {
id: number | string
noticeTitle: string
remark: string
// 添加其他需要的属性
}
// Props 定义
interface Props {
content3: NewsItem[]
action?: string
}
const props = withDefaults(defineProps<Props>(), {
content3: () => [],
action: ''
})
// 事件
const emit = defineEmits<{
(e: 'itemClick', item: NewsItem): void
}>()
// 获取完整图片URL
const getImageUrl = (remark: string) => {
return 'http://118.107.9.143:8080/jeecg-boot/' + remark
}
// 处理新闻点击
const handleNewsClick = (item: NewsItem) => {
emit('itemClick', item)
}
</script>
<style lang="scss" scoped>
.news-card {
margin: 7.5px 0; // 15rpx / 2
padding: 0;
border-radius: 5px; // 10rpx / 2
font-family: pingfang;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.news-item {
display: flex;
padding: 15px;
gap: 15px;
cursor: pointer;
transition: background-color 0.3s ease;
&:hover {
background-color: rgba(0, 0, 0, 0.02);
}
&:active {
background-color: rgba(0, 0, 0, 0.05);
}
&:not(:last-child) {
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
}
}
.image-wrapper {
flex-shrink: 0;
width: 80px;
height: 80px;
border-radius: 4px;
overflow: hidden;
img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s ease;
&:hover {
transform: scale(1.05);
}
}
}
.content {
flex: 1;
min-width: 0; // 防止文本溢出
display: flex;
flex-direction: column;
justify-content: space-between;
}
.title {
margin: 0;
font-size: 16px;
font-weight: 500;
color: #333;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
line-height: 1.4;
}
.subtitle {
font-size: 14px;
color: #999;
margin-top: auto;
}
</style>
\ No newline at end of file
<template>
<div v-if="loading" class="page-loading">
<van-loading type="spinner" color="#1989fa" size="36">
<span class="loading-text">{{ loadingText }}</span>
</van-loading>
</div>
</template>
<script lang="ts" setup>
import { computed } from 'vue'
import { useLoading } from '@/hooks/useLoading'
const { loading, loadingCount } = useLoading()
const loadingText = computed(() => loadingCount.value > 1 ? `加载中(${loadingCount.value})` : '加载中')
</script>
<style lang="scss" scoped>
.page-loading {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: 16px 24px;
background: rgba(0, 0, 0, 0.6);
border-radius: 8px;
z-index: 9999;
.loading-text {
display: block;
margin-top: 8px;
color: #fff;
font-size: 14px;
}
}
</style>
\ No newline at end of file
<script setup>
import { ref, computed, watch, onMounted } from 'vue'
// Props 定义
const props = defineProps({
lang: { type: String, default: 'zh' },
type: { type: String, default: 'calendar' },
checkDate: { type: Boolean, default: false },
bgweek: { type: String, default: '#FF8F22' },
bgday: { type: String, default: '#FF8F22' },
signin_but_bg: { type: String, default: '#909399' },
supplementary: { type: Boolean, default: true },
already: { type: Array, default: () => [] },
checkinDays: { type: [Number, String], default: 0 },
integral: { type: [Number, String], default: 0 },
isIntegral: { type: Boolean, default: false }
})
// Emits
const emit = defineEmits(['shift', 'change'])
// 响应式数据
const weeked = ref('')
const dayArr = ref([])
const localDate = ref('')
const currentDate = new Date()
const year = ref(currentDate.getFullYear())
const month = ref(currentDate.getMonth() + 1)
const day = ref(currentDate.getDate())
const aheadDay = ref(0)
const prv = ref(true)
const next = ref(true)
const is_day_signin = ref(false)
// 计算属性
const weekArr = computed(() =>
props.lang === 'zh' ? ['', '', '', '', '', '', ''] : ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
)
const thisMonth = computed(() => currentDate.getMonth() + 1)
// 格式化数字
const formatNum = (num) => num < 10 ? `0${num}` : num
// 初始化日期
const initDate = () => {
dayArr.value = []
const totalDay = new Date(year.value, month.value, 0).getDate()
for (let i = 1; i <= totalDay; i++) {
const value = new Date(year.value, month.value - 1, i).getDay()
if (i === 1 && value !== 0) {
addBefore(value)
aheadDay.value = value
}
const dateObj = {
date: `${year.value}-${formatNum(month.value)}-${formatNum(i)}`,
day: i,
flag: false
}
dayArr.value.push(dateObj)
if (i === totalDay && value !== 6) {
addAfter(value)
}
}
}
// 补充前空白日期
const addBefore = (value) => {
const totalDay = new Date(year.value, month.value - 1, 0).getDate()
for (let i = 0; i < value; i++) {
dayArr.value.push({
date: '',
day: totalDay - (value - i) + 1
})
}
}
// 补充后空白日期
const addAfter = (value) => {
for (let i = 0; i < (6 - value); i++) {
dayArr.value.push({
date: '',
day: i + 1
})
}
}
// 签到处理
const daySign = (obj) => {
const index = aheadDay.value + day.value - 1
if (dayArr.value[index].flag) return false
dayArr.value[index].flag = true
emit('change', obj.date)
is_day_signin.value = true
showSuccessToast('已签到')
}
// 补签处理
const signToday = (obj, index) => {
if (props.type === 'calendar') return
if (currentDate.getMonth() + 1 !== parseInt(obj.date.split('-')[1])) return
if (obj.date && obj.day < day.value) {
if (dayArr.value[index].flag) {
showFailToast('已签到')
} else {
if (day.value > obj.day && !props.supplementary) return
showSuccessToast(day.value > obj.day ? '补签成功' : '签到成功')
dayArr.value[index].flag = true
emit('change', obj.date)
}
}
}
// 月份切换
const changeMonth = (direction) => {
if (direction === 'prev') {
if (month.value === 1) {
year.value--
month.value = 12
} else {
month.value--
}
} else {
if (month.value === 12) {
year.value++
month.value = 1
} else {
month.value++
}
}
initDate()
updateNavigationButtons()
}
// 更新导航按钮状态
const updateNavigationButtons = () => {
prv.value = year.value >= currentDate.getFullYear() || month.value > currentDate.getMonth() + 2
next.value = year.value <= currentDate.getFullYear() || month.value < currentDate.getMonth()
}
// 监听已签到数据变化
watch(() => props.already, (newVal) => {
dayArr.value.forEach((day, index) => {
day.flag = newVal.includes(day.date)
if (day.flag && day.date === localDate.value) {
is_day_signin.value = true
}
})
}, { deep: true })
// 初始化
onMounted(() => {
initDate()
localDate.value = `${year.value}-${formatNum(month.value)}-${formatNum(day.value)}`
weeked.value = weekArr.value[currentDate.getDay()]
if (props.type !== 'calendar') {
dayArr.value.forEach(day => day.flag = false)
}
})
</script>
<template>
<div class="calendar-container">
<!-- 头部信息 -->
<div class="header">
<div class="checkin-info">
<h4>已连续签到 <span>{{ checkinDays }}</span></h4>
<p v-if="isIntegral">今日获得+{{ integral }}积分</p>
</div>
<!-- <div class="actions">
<span v-if="supplementary" class="makeup-btn" @click="$emit('shift')">
补签
</span>
</div> -->
</div>
<!-- 日历主体 -->
<div class="calendar-body">
<!-- 月份导航 -->
<div class="month-nav">
<div class="nav-btn" @click="changeMonth('prev')">
<span v-show="prv">上月</span>
</div>
<div class="current-month">{{ year }}{{ month }}</div>
<div class="nav-btn" @click="changeMonth('next')">
<span v-show="next">下月</span>
</div>
</div>
<!-- 星期栏 -->
<div class="week-row">
<div v-for="week in weekArr" :key="week" class="week-cell" :style="{ color: week === weeked ? bgweek : '' }">
{{ week }}
</div>
</div>
<!-- 日期格子 -->
<div class="date-grid">
<div v-for="(date, index) in dayArr" :key="index" class="date-cell" :class="{
'empty': date.date === '',
'selected': date.date === localDate || date.flag
}" :style="{
background: (date.date === localDate || date.flag) ? bgday : ''
}">
<!-- @click="signToday(date, index)" -->
{{ date.day }}
<div :class="{
'dot': date.flag,
'makeup': date.day < day,
'today': date.day === day
}" />
</div>
</div>
</div>
<!-- 签到按钮 -->
<div class="sign-button">
<button :disabled="thisMonth !== month" :style="{
background: is_day_signin ?
signin_but_bg :
(thisMonth === month ? bgday : signin_but_bg)
}" @click="daySign(dayArr[aheadDay + day - 1])">
签到
</button>
</div>
</div>
</template>
<style lang="scss" scoped>
.calendar-container {
width: 100%;
display: flex;
flex-direction: column;
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px;
background: #fff;
border-radius: 10px;
margin-bottom: 8px;
.checkin-info {
h4 {
font-weight: 600;
font-size: 18px;
line-height: 25px;
span {
color: #FF871E;
margin: 0 5px;
font-size: 16px;
}
}
p {
font-size: 14px;
line-height: 20px;
color: #FF871E;
}
}
.makeup-btn {
font-size: 12px;
color: #FF871E;
border: 1px solid #FF871E;
padding: 5px 10px;
border-radius: 16px;
&:active {
opacity: 0.8;
}
}
}
.calendar-body {
padding: 10px 20px;
background: #fff;
border-radius: 12px;
.month-nav {
display: flex;
justify-content: space-between;
align-items: center;
margin: 15px 0;
.nav-btn {
min-width: 35px;
cursor: pointer;
&:active {
opacity: 0.8;
}
}
}
.week-row {
display: flex;
justify-content: space-between;
.week-cell {
width: 35px;
height: 35px;
display: flex;
align-items: center;
justify-content: center;
}
}
.date-grid {
display: flex;
flex-wrap: wrap;
.date-cell {
width: 35px;
height: 35px;
margin: 5px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
&.empty {
color: #999;
}
&.selected {
color: #fff;
border-radius: 50%;
}
.dot {
width: 5px;
height: 5px;
border-radius: 50%;
position: absolute;
bottom: 5%;
left: 50%;
transform: translateX(-50%);
background: #fff;
}
}
}
}
.sign-button {
display: flex;
justify-content: center;
margin-top: 40px;
button {
width: 325px;
height: 40px;
border-radius: 15px;
border: none;
outline: none;
color: #fff;
font-size: 16px;
&:active {
opacity: 0.9;
}
&:disabled {
opacity: 0.6;
}
}
}
}
</style>
\ No newline at end of file
import { App } from 'vue'
import { onMounted, onUnmounted, onActivated, onDeactivated } from 'vue'
import { $loading } from '@/hooks/useLoading'
// 全局组合式函数
export function onPageShow(fn: () => void | Promise<void>) {
const handleVisibilityChange = () => {
if (document.visibilityState === 'visible') {
fn()
}
}
onMounted(() => {
fn()
document.addEventListener('visibilitychange', handleVisibilityChange, false)
})
onUnmounted(() => {
document.removeEventListener('visibilitychange', handleVisibilityChange, false)
})
onActivated(() => {
fn()
document.addEventListener('visibilitychange', handleVisibilityChange, false)
})
onDeactivated(() => {
document.removeEventListener('visibilitychange', handleVisibilityChange, false)
})
}
export function onPageHide(fn: () => void) {
const handleVisibilityChange = () => {
if (document.visibilityState === 'hidden') {
fn()
}
}
onMounted(() => {
document.addEventListener('visibilitychange', handleVisibilityChange, false)
})
onUnmounted(() => {
fn()
document.removeEventListener('visibilitychange', handleVisibilityChange, false)
})
onActivated(() => {
document.addEventListener('visibilitychange', handleVisibilityChange, false)
})
onDeactivated(() => {
fn()
document.removeEventListener('visibilitychange', handleVisibilityChange, false)
})
}
// 注册全局组合式函数
export function setupGlobalComposables(app: App) {
// 添加到全局属性中
app.config.globalProperties.$onPageShow = onPageShow
app.config.globalProperties.$onPageHide = onPageHide
app.config.globalProperties.$loading = $loading
}
\ No newline at end of file
import { ref, onMounted } from 'vue'
import request from '@/utils/request'
export interface UserInfo {
sysUser: {
identityId: string
realname: string
username: string
yqm: string
}
// ... 其他字段
}
const userInfo = ref<UserInfo | null>(null)
export const useUserInfo = () => {
const getUserInfo = async () => {
try {
const token = sessionStorage.getItem('token')
if (!token) return null
// 先从 sessionStorage 获取
const cached = sessionStorage.getItem('userInfo')
if (cached) {
userInfo.value = JSON.parse(cached)
return userInfo.value
}
// 如果没有则请求接口
const res: any = await request.get('/business/businessWallet/getInfo')
if (res?.code === 200) {
userInfo.value = res.result
sessionStorage.setItem('userInfo', JSON.stringify(res.result))
return res.result
}
return null
} catch (error) {
console.error('获取用户信息失败:', error)
return null
}
}
// 更新用户信息
const updateUserInfo = (newInfo: Partial<UserInfo>) => {
if (userInfo.value) {
userInfo.value = { ...userInfo.value, ...newInfo }
sessionStorage.setItem('userInfo', JSON.stringify(userInfo.value))
}
}
// 检查实名认证状态
const checkAuthStatus = () => {
if (userInfo.value?.sysUser?.identityId === 'true') {
return true
}
return false
}
// 清除用户信息
const clearUserInfo = () => {
userInfo.value = null
sessionStorage.removeItem('userInfo')
sessionStorage.removeItem('token')
}
return {
userInfo,
getUserInfo,
updateUserInfo,
checkAuthStatus,
clearUserInfo
}
}
\ No newline at end of file
import { ref } from 'vue'
const loading = ref(false)
const loadingCount = ref(0)
export function useLoading() {
const showLoading = () => {
loadingCount.value++
loading.value = true
}
const hideLoading = () => {
loadingCount.value = Math.max(0, loadingCount.value - 1)
if (loadingCount.value === 0) {
loading.value = false
}
}
return {
loading,
loadingCount,
showLoading,
hideLoading
}
}
// 全局方法
export const $loading = {
show: () => useLoading().showLoading(),
hide: () => useLoading().hideLoading()
}
\ No newline at end of file
import { onMounted, onUnmounted, onActivated, onDeactivated } from 'vue'
export function usePageHook(options: {
onPageShow?: () => void | Promise<void>
onPageHide?: () => void
}) {
const { onPageShow, onPageHide } = options
// 处理页面显示
const handleVisibilityChange = () => {
if (document.visibilityState === 'visible') {
onPageShow?.()
} else {
onPageHide?.()
}
}
onMounted(() => {
// 首次加载执行
onPageShow?.()
// 添加可见性监听
document.addEventListener('visibilitychange', handleVisibilityChange)
})
onUnmounted(() => {
// 移除监听
document.removeEventListener('visibilitychange', handleVisibilityChange)
})
// keep-alive 激活/停用时触发
onActivated(() => {
onPageShow?.()
})
onDeactivated(() => {
onPageHide?.()
})
}
\ No newline at end of file
<template>
<div class="base-layout">
<router-view />
</div>
</template>
<script setup lang="ts">
</script>
\ No newline at end of file
<template>
<div class="header-layout">
<div class="header">
<van-nav-bar
:title="$route.meta.title"
left-arrow
@click-left="onClickLeft"
/>
</div>
<div class="content">
<router-view />
</div>
</div>
</template>
<script setup lang="ts">
import { useRouter } from 'vue-router';
const router = useRouter();
const onClickLeft = () => {
router.back();
};
</script>
<style lang="scss" scoped>
.header-layout {
min-height: 100vh;
display: flex;
flex-direction: column;
.header {
height: 46px;
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 1000;
}
.content {
flex: 1;
margin-top: 46px;
height: calc(100vh - 46px);
overflow-y: auto;
background-color: var(--bg-color);
}
}
</style>
\ No newline at end of file
<template>
<div class="tabbar-layout">
<div class="content">
<router-view v-slot="{ Component }">
<component :is="Component"/>
</router-view>
</div>
<div class="tab-view">
<div
v-for="item in tabItems"
:key="item.path"
:class="route.name === item.name ? 'tab-item tab-item-active' : 'tab-item'"
@click="handleChange(item.path)"
>
<img class="tab-item-icon" v-if="route.name === item.name" :src="item.iconActive" alt="">
<img class="tab-item-icon" v-else :src="item.icon" alt="">
<span>{{ item.title }}</span>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { useRouter, useRoute } from 'vue-router';
import tab1 from '@/static/tabbar/1.png';
import tab1Active from '@/static/tabbar/a1.png';
import tab2 from '@/static/tabbar/2.png';
import tab2Active from '@/static/tabbar/a2.png';
import tab3 from '@/static/tabbar/3.png';
import tab3Active from '@/static/tabbar/a3.png';
import tab4 from '@/static/tabbar/4.png';
import tab4Active from '@/static/tabbar/a4.png';
const router = useRouter();
const route = useRoute();
const tabItems = [
{ name: 'home', path: '/home', title: '首页', icon: tab1, iconActive: tab1Active },
{ name: 'kpsl', path: '/kpsl', title: '卡片申领', icon: tab2, iconActive: tab2Active },
{ name: 'ryds', path: '/ryds', title: '荣誉董事', icon: tab3, iconActive: tab3Active },
{ name: 'user', path: '/user', title: '个人中心', icon: tab4, iconActive: tab4Active },
];
const handleChange = (path: string) => {
router.push(path);
};
</script>
<style lang="scss" scoped>
.tabbar-layout {
height: 100vh;
display: flex;
flex-direction: column;
.content {
height: calc(100% - 50px);
overflow-y: auto;
background-color: var(--bg-color);
}
.tab-view {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 50px;
display: flex;
justify-content: space-around;
align-items: center;
background-color: #fff;
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
z-index: 999;
.tab-item {
flex: 1;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.tab-item-icon{
width: 25px;
height: 25px;
}
span {
margin-top: 3px;
font-size: 14px;
color: #666;
}
}
.tab-item-active {
flex: 1;
text-align: center;
span {
color: #ff6b35;
}
}
}
}
</style>
\ No newline at end of file
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import Varlet from '@varlet/ui'
import '@varlet/ui/es/style'
import '@varlet/touch-emulator'
import '@/styles/index.scss'
const app = createApp(App)
app.use(router)
app.use(Varlet)
app.mount('#app')
\ No newline at end of file
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
import { checkVersion } from "@/services/version";
import NProgress from "nprogress";
import "nprogress/nprogress.css";
import { generateRoutes } from "@/utils/generateRoutes";
import { useUserInfo } from "@/composables/useUserInfo";
const routes = generateRoutes();
const router = createRouter({
history: createWebHistory(),
routes,
});
NProgress.configure({ showSpinner: false });
const { getUserInfo } = useUserInfo();
router.beforeEach(async (to, from, next) => {
NProgress.start();
document.title = (to.meta.title as string) || "Vue App";
// 检查版本更新
if (process.env.NODE_ENV === "production") {
try {
const { version } = await checkVersion();
if (version) {
const storedVersion = sessionStorage.getItem("app_version");
if (version !== storedVersion) {
sessionStorage.setItem("app_version", version);
window.location.href = to.fullPath;
return;
}
}
} catch (error) {
console.error("Version check failed:", error);
}
}
const token = sessionStorage.getItem("token");
// 登录页面判断
if (to.path === "/login") {
if (token) {
next("/");
return;
}
} else {
if (!token && to.path !== "/register") {
next("/login");
return;
}
}
next();
// 获取用户信息
if (token) {
await getUserInfo();
}
});
router.afterEach(() => {
NProgress.done();
});
export default router;
import axios from 'axios'
import request from '@/utils/request'
export interface VersionResponse {
version: string
}
// 这里使用 nginx 配置的代理路径
export const checkVersion = async (): Promise<VersionResponse> => {
const response = await request.get<VersionResponse>('/business/businessConfig/queryConfigByCode?code=appVersion')
return response.data
}
\ No newline at end of file
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="39" height="39" viewBox="0 0 39 39">
<g id="组_124315" data-name="组 124315" transform="translate(-167 -179)">
<path id="直线_4727" data-name="直线 4727" d="M36,1.5H0A1.5,1.5,0,0,1-1.5,0,1.5,1.5,0,0,1,0-1.5H36A1.5,1.5,0,0,1,37.5,0,1.5,1.5,0,0,1,36,1.5Z" transform="translate(168.5 198.5)" fill="#777"/>
<path id="直线_4728" data-name="直线 4728" d="M36,1.5H0A1.5,1.5,0,0,1-1.5,0,1.5,1.5,0,0,1,0-1.5H36A1.5,1.5,0,0,1,37.5,0,1.5,1.5,0,0,1,36,1.5Z" transform="translate(186.5 180.5) rotate(90)" fill="#777"/>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="9" viewBox="0 0 14 9">
<path id="多边形_2" data-name="多边形 2" d="M6.211,1.015a1,1,0,0,1,1.579,0l4.955,6.371A1,1,0,0,1,11.955,9H2.045a1,1,0,0,1-.789-1.614Z" fill="#333"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="9" viewBox="0 0 14 9">
<path id="多边形_4" data-name="多边形 4" d="M6.211,1.015a1,1,0,0,1,1.579,0l4.955,6.371A1,1,0,0,1,11.955,9H2.045a1,1,0,0,1-.789-1.614Z" transform="translate(14 9) rotate(180)" fill="#777"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="10.588" viewBox="0 0 12 10.588">
<path id="选择" d="M132.1,198.745l-5.032-5.242,1.29-1.059,2.91,2.337a32.472,32.472,0,0,1,7.493-6.623l.307.727a31.754,31.754,0,0,0-6.968,9.861Zm0,0" transform="translate(-127.068 -188.158)" fill="#e60012"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="74" height="74" viewBox="0 0 74 74">
<g id="组_124121" data-name="组 124121" transform="translate(-158 -467)">
<rect id="矩形_54153" data-name="矩形 54153" width="74" height="74" rx="16" transform="translate(158 467)" fill="#f5d94c"/>
<g id="收益_1_" data-name="收益 (1)" transform="translate(110 420.6)">
<path id="路径_4859" data-name="路径 4859" d="M93.029,78.411A12.719,12.719,0,1,0,105.748,91.13,12.708,12.708,0,0,0,93.029,78.411Zm2.843,11a1.859,1.859,0,0,0,.6.075h1.945a.533.533,0,0,1,.449.224.647.647,0,0,1,.224.449v1.422c0,.3-.224.374-.6.374H95.124a1.063,1.063,0,0,0-.449.15.411.411,0,0,0-.224.374v.973c0,.224.224.3.6.224h3.292c.374,0,.6.15.6.524v1.2c0,.374-.3.6-.823.6H95.049a.534.534,0,0,0-.524.6v2.319c0,.224-.15.3-.449.3h-1.8c-.524,0-.748-.224-.748-.6v-2.02c0-.224,0-.3-.075-.374,0-.075-.15-.075-.374-.075H87.642c-.524,0-.748-.224-.748-.748a1.316,1.316,0,0,0-.075-.449.639.639,0,0,1,0-.524,4.769,4.769,0,0,1,.15-.524.333.333,0,0,1,.449-.15h3.816c.075,0,.075-.075.075-.3V92.327c0-.224-.224-.3-.673-.3H86.969c-.15,0-.15-.15-.15-.3v-.823a1.661,1.661,0,0,0-.075-.673.582.582,0,0,1,.15-.6,1.264,1.264,0,0,1,.748-.224,2.135,2.135,0,0,0,.973,0h1.5q.337,0,.224-.224-.112-.112-.673-.9c-.374-.524-.748-1.047-1.2-1.571-.524-.673-1.047-1.347-1.721-2.17a.671.671,0,0,1,.15-1.047,4.15,4.15,0,0,1,.6-.449c.224-.15.449-.3.748-.524.374-.224.748,0,1.047.6.15.15.3.449.673.823.3.374.673.823.973,1.272a14.384,14.384,0,0,0,.973,1.272c.3.374.449.6.524.673a.687.687,0,0,0,.449.3.333.333,0,0,0,.449-.15c0-.075.224-.3.449-.748.3-.374.6-.823.973-1.347s.673-.973.973-1.422a8.054,8.054,0,0,1,.6-.823,4.479,4.479,0,0,1,.449-.524.755.755,0,0,1,.673.075,2.625,2.625,0,0,1,.6.374,2.849,2.849,0,0,1,.449.374c.449.449.524.823.374,1.122-.075.15-.3.374-.6.9-.374.449-.748.973-1.122,1.5a18.152,18.152,0,0,0-1.047,1.5,5.331,5.331,0,0,0-.524.823c.075.15.075.224.3.3ZM79.712,62.4C71.033,62.4,64,65.916,64,70.181s7.033,7.781,15.712,7.781,15.712-3.516,15.712-7.781C95.348,65.916,88.316,62.4,79.712,62.4Z" fill="#fff"/>
<path id="路径_4860" data-name="路径 4860" d="M84.65,322.486a34.8,34.8,0,0,1-4.938.374c-7.482,0-13.692-2.619-15.263-6.06A3.691,3.691,0,0,0,64,318.521c0,4.265,7.033,7.781,15.712,7.781h1.272A11.9,11.9,0,0,1,84.65,322.486Zm10.325-2.17a3.984,3.984,0,0,0,.449-1.8,4.438,4.438,0,0,0-.374-1.721,8.634,8.634,0,0,1-3.292,3.292h.673A15.274,15.274,0,0,1,94.974,320.316Z" transform="translate(0 -242.504)" fill="#fff"/>
<path id="路径_4861" data-name="路径 4861" d="M79.712,433.26c-7.482,0-13.692-2.619-15.263-6.06A3.475,3.475,0,0,0,64,428.921c0,4.19,6.659,7.557,14.963,7.781a13.138,13.138,0,0,1,1.047-3.442Z" transform="translate(0 -347.742)" fill="#fff"/>
<path id="路径_4862" data-name="路径 4862" d="M78.814,542.06c-7.108-.224-12.869-2.693-14.44-6.06A4.752,4.752,0,0,0,64,537.721c0,4.19,6.734,7.631,15.113,7.781a12.886,12.886,0,0,1-.3-2.918,1.223,1.223,0,0,1,0-.524Z" transform="translate(0 -451.454)" fill="#fff"/>
<path id="路径_4863" data-name="路径 4863" d="M64.374,646.4A4.438,4.438,0,0,0,64,648.121c0,4.265,7.033,7.781,15.712,7.781a13.242,13.242,0,0,0,1.721-.075,13.673,13.673,0,0,1-1.8-3.442C72.155,652.385,65.945,649.842,64.374,646.4Z" transform="translate(0 -556.692)" fill="#fff"/>
<path id="路径_4864" data-name="路径 4864" d="M82.779,761.11c-.973.075-2.02.15-3.068.15-7.482,0-13.692-2.619-15.263-6.06A3.475,3.475,0,0,0,64,756.921c0,4.265,7.033,7.781,15.712,7.781a30.372,30.372,0,0,0,7.108-.823A12.926,12.926,0,0,1,82.779,761.11Z" transform="translate(0 -660.404)" fill="#fff"/>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="52" height="52" viewBox="0 0 52 52">
<defs>
<style>
.cls-1 {
fill: #ffd065;
}
.cls-2 {
fill: #fff;
}
</style>
</defs>
<g id="组_124309" data-name="组 124309" transform="translate(-40 -555)">
<rect id="矩形_54127" data-name="矩形 54127" class="cls-1" width="52" height="52" rx="8" transform="translate(40 555)"/>
<path id="激励金账户" class="cls-2" d="M94.929,23.843a2.9,2.9,0,0,0-2.165-.957H81.839a2.915,2.915,0,0,0-2.1.881c-3.432,3.56-6.6,8.644-6.6,12.35,0,3.268,3.317,7.395,7.409,7.395H93.236c4.092,0,7.409-4.092,7.409-7.395,0-3.774-2.546-8.713-5.716-12.274Zm-4.541,5.3-1.811,3.14a.415.415,0,0,0,.378.614h.513a.415.415,0,1,1,0,.83H88.177a.445.445,0,0,0-.456.433v.2a.425.425,0,0,0,.435.415h1.314a.415.415,0,1,1,0,.83H88.155a.425.425,0,0,0-.434.415v1.054a.426.426,0,0,1-.434.416H86.5a.426.426,0,0,1-.434-.415V36.025a.426.426,0,0,0-.435-.416h-1.3a.415.415,0,1,1,0-.83h1.3a.428.428,0,0,0,.437-.415l0-.2a.444.444,0,0,0-.455-.438H84.331a.415.415,0,1,1,0-.83h.5a.415.415,0,0,0,.379-.615L83.4,29.14a.415.415,0,0,1,.379-.614h.863a.434.434,0,0,1,.387.228l1.474,2.81a.445.445,0,0,0,.776,0l1.475-2.811a.436.436,0,0,1,.387-.227H90a.419.419,0,0,1,.384.617Zm-8.062-7.786a2.254,2.254,0,0,1-1.742-.851c-1.093-1.34-2.093-2.955-2.093-4.15,0-2.958,2.325-2.48,3.979-2.5,1.417-.016,1.678-1.664,3.694-1.664,1.113,0,1.429,1.664,2.414,1.664,1.44,0,2.31-1.664,4.042-1.664A3.425,3.425,0,0,1,96,16.356a9.821,9.821,0,0,1-2.181,4.179,2.192,2.192,0,0,1-1.717.823h-9.78Z" transform="translate(-21.143 552.81)"/>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
<defs>
<style>
.cls-1 {
fill: #fff;
stroke: #707070;
}
.cls-2 {
fill: #48b338;
}
.cls-3 {
stroke: none;
}
.cls-4 {
fill: none;
}
</style>
</defs>
<g id="微信支付" transform="translate(0 -1)">
<g id="矩形_2340" data-name="矩形 2340" class="cls-1" transform="translate(1 2)">
<rect class="cls-3" width="18" height="18"/>
<rect class="cls-4" x="0.5" y="0.5" width="17" height="17"/>
</g>
<path id="支付-微信支付" class="cls-2" d="M17.5,0H2.5A2.507,2.507,0,0,0,0,2.5v15A2.507,2.507,0,0,0,2.5,20h15A2.507,2.507,0,0,0,20,17.5V2.5A2.507,2.507,0,0,0,17.5,0ZM10,15.375A7.276,7.276,0,0,1,7.625,15c-.5.25-1.25.875-1.5,1-.5.25-.375-.25-.375-.25L6,14.25A5.242,5.242,0,0,1,3.625,9.875C3.625,6.75,6.5,4.25,10,4.25a6.947,6.947,0,0,1,5.25,2.375L9,9.5a.993.993,0,0,1-1-.125l-1-.75S6.25,8,6.625,9l1,2.25s.125.625.875.25c.625-.25,5.25-3.125,7.25-4.25a5.688,5.688,0,0,1,.625,2.5c0,3-2.875,5.625-6.375,5.625Z" transform="translate(0 1)"/>
</g>
</svg>
<svg id="银联" xmlns="http://www.w3.org/2000/svg" width="19.65" height="19.65" viewBox="0 0 19.65 19.65">
<rect id="矩形_207" data-name="矩形 207" width="19.65" height="19.65" fill="none"/>
<g id="支付宝支付" transform="translate(1.824 1.829)">
<g id="银联-2" data-name="银联" transform="translate(-1.082 -1.09)">
<path id="路径_4969" data-name="路径 4969" d="M4.077,4.153A1.4,1.4,0,0,0,3,5.035c-.1.275-1.909,8.065-1.918,8.206a.722.722,0,0,0,.606.782c.143.033,4.735.033,4.887,0a1.38,1.38,0,0,0,1-.841c.059-.158,1.926-8.1,1.926-8.231a.757.757,0,0,0-.564-.791c-.084-.017-4.668-.033-4.861-.008Z" fill="#e60012"/>
<path id="路径_4970" data-name="路径 4970" d="M8.358,4.153a1.4,1.4,0,0,0-1.077.882c-.093.275-1.909,8.065-1.909,8.206a.722.722,0,0,0,.606.782c.143.033,4.735.033,4.887,0a1.38,1.38,0,0,0,1-.841c.059-.158,1.926-8.1,1.926-8.231a.757.757,0,0,0-.563-.791c-.093-.017-4.676-.033-4.87-.008Z" fill="#00508e"/>
<path id="路径_4971" data-name="路径 4971" d="M12.824,4.153a1.4,1.4,0,0,0-1.077.882c-.092.275-1.909,8.065-1.909,8.206a.722.722,0,0,0,.606.782c.143.033,3.558.033,3.709,0a1.38,1.38,0,0,0,1-.841c.059-.158,1.926-8.1,1.926-8.231a.757.757,0,0,0-.564-.791c-.084-.025-3.919-.042-4.113-.017h.421v.008Z" fill="#00908c"/>
<path id="路径_4972" data-name="路径 4972" d="M3.934,6.683a.546.546,0,0,1-.025.108,9.026,9.026,0,0,0-.362,1.631c.067.325.547.3.715-.042.05-.092.412-1.615.412-1.723,0-.008.572,0,.572.008a.177.177,0,0,1-.008.05c-.008.025-.1.374-.2.791a3.5,3.5,0,0,1-.37,1.148c-.387.566-1.682.549-1.783-.025a13.349,13.349,0,0,1,.379-1.956,3.637,3.637,0,0,1,.673.008Zm8.6,0c.387.083.5.391.328.849s-.555.657-1.22.657c-.2,0-.185-.033-.311.591-.025.117-.05.225-.05.241a1.444,1.444,0,0,1-.6,0c.5-2.139.547-2.322.547-2.339l.008-.025h.606a5.585,5.585,0,0,1,.69.025Zm-5.189.824a.167.167,0,0,1,.143.142c0,.208-.429.35-.589.191s.168-.4.446-.333Zm-1.489.158c0,.017-.008.05-.008.075l-.008.033.1-.05c.269-.133.53-.108.614.058.05.1.042.158-.093.774-.025.108-.059.258-.067.333-.034.167-.008.158-.311.158-.261,0-.261,0-.252-.025s.034-.15.067-.308c.135-.591.143-.674.025-.674a.243.243,0,0,0-.168.067c-.017.058-.168.782-.177.849l-.017.075L5.3,9.046c-.32.008-.294.033-.227-.25a8.176,8.176,0,0,0,.177-.857c.042-.25.017-.225.252-.258.109-.017.219-.033.252-.042.084-.025.1-.017.1.025Zm4-.008c0,.017-.008.05-.008.075l-.008.042.1-.05c.521-.266.723-.05.572.633-.034.15-.076.366-.1.466a.883.883,0,0,1-.05.208,1.56,1.56,0,0,1-.522,0c0-.017.034-.15.067-.3.143-.608.143-.682.017-.682-.1,0-.151.033-.168.108-.025.092-.151.691-.168.8l-.017.092L9.3,9.055c-.32.008-.294.042-.219-.266.084-.333.143-.641.185-.866s.008-.191.219-.225c.093-.017.21-.033.252-.042.084-.042.109-.033.109,0Zm5.105-.008c.034.508.042.657.042.666a2.879,2.879,0,0,0,.16-.291c.168-.333.135-.3.32-.325.05-.008.151-.025.227-.042.185-.033.185-.05-.025.316-.286.491-.681,1.182-.824,1.432-.429.774-.429.774-.791.782l-.219.008.017-.058c.008-.033.034-.1.042-.15l.025-.092h.067c.076,0,.092-.017.16-.133a1.339,1.339,0,0,0,.084-.15c.025-.042.109-.175.177-.308l.135-.233-.034-.308c-.042-.358-.092-.782-.118-.907s-.017-.117.135-.133c.067-.008.177-.033.236-.042.16-.05.177-.05.185-.033Zm-6.342.008c.648.117.421,1.232-.286,1.39-.479.108-.807-.075-.807-.441a.909.909,0,0,1,1.093-.949Zm4.845.033a.505.505,0,0,1,.109.075c.042.042.042.042.042.017s0-.033.336-.083c.269-.042.261-.042.244.033-.109.466-.2.874-.244,1.074-.059.3-.017.266-.345.258h-.278V9.03c0-.033-.017-.05-.034-.025-.093.15-.547.092-.673-.092-.311-.466.353-1.448.841-1.223Zm-6.039.241a.362.362,0,0,1-.008.075c-.067.266-.185.807-.21.907l-.025.125-.278.008c-.328.008-.311.025-.244-.175A4.255,4.255,0,0,0,6.8,8.2c.034-.216,0-.183.244-.216.109-.017.227-.033.252-.042.067-.017.109-.017.118-.008ZM8.888,9.654a.343.343,0,0,1-.042.083.372.372,0,0,1-.042.075c.5.008.513.008.5.033l-.092.3H8.493l-.042.033c-.093.083-.58.191-.58.125l.093-.3H8.03c.118,0,.143-.025.244-.2l.084-.158a2.47,2.47,0,0,1,.53.008Zm1.1,0a.52.52,0,0,1-.025.1.373.373,0,0,0-.025.092.388.388,0,0,0,.092-.058c.185-.125.345-.15.816-.15a2.893,2.893,0,0,1,.353.008c.008.017-.269.916-.311,1a.423.423,0,0,1-.21.208l-.084.033-.479.008-.479.008-.084.283c-.168.541-.168.5.076.474.193-.017.185-.033.126.166l-.05.166H9.46c-.53.008-.6-.025-.547-.241.025-.108.631-2.089.639-2.106a2.555,2.555,0,0,1,.437.008Zm2.212,0c0,.008-.008.033-.017.067-.025.083-.025.083.084.025a3.366,3.366,0,0,1,1.169-.1h.219v.1c0,.117.008.125.109.141l.076.008-.042.15-.042.15h-.151c-.387.008-.446-.033-.454-.258V9.829l-.025.075-.025.083h-.084c-.042,0-.084,0-.084.008s-.412,1.356-.471,1.548c-.008.017,0,.025.05.025.076,0,.076,0,.05.066s-.025.075.059.075a.232.232,0,0,0,.135-.033c.059-.033.059-.025.328-.4l.109-.158h-.227c-.278,0-.252.017-.2-.15l.042-.133h.555c.05-.175.067-.225.067-.233a1.53,1.53,0,0,0-.269-.008h-.269l.084-.3h.757c.412,0,.757,0,.757.008a1.133,1.133,0,0,1-.042.15l-.042.141-.252.008-.252.008c-.042.125-.059.183-.067.2l-.008.033h.244c.286,0,.269-.017.21.15l-.042.133h-.555l-.084.1h.219l.034.2c.034.225.034.225.143.225.084,0,.084-.017.025.183L13.968,12h-.16c-.278,0-.328-.042-.379-.325l-.025-.183-.1.133c-.278.374-.294.383-.648.383-.227,0-.227,0-.193-.067.008-.033.008-.033-.059-.033s-.067,0-.084.05l-.008.05H11.84l.008-.025c.025-.083.067-.075-.446-.075-.446,0-.471,0-.463-.025l.042-.15c.05-.15.042-.15.092-.15s.042,0,.059-.058c.4-1.307.522-1.723.538-1.781l.034-.108h.236a1.037,1.037,0,0,1,.261.017Zm-2.986.716-.093.291h-.5a2.439,2.439,0,0,1-.076.233c-.008.025.008.025.252.025.143,0,.261.008.261.008a.326.326,0,0,1-.017.05,1.392,1.392,0,0,0-.042.15l-.034.108H8.442l-.059.2c-.084.283-.076.291.244.25.135-.017.126-.033.067.166l-.05.166H8.291c-.555,0-.563-.017-.412-.491.042-.15.084-.275.084-.275a1.128,1.128,0,0,0-.143-.008.458.458,0,0,1-.143-.008c.059-.208.084-.275.084-.291s.025-.025.151-.025h.143l.067-.258H7.988c-.1,0-.135,0-.135-.017s.076-.258.084-.283,1.287-.008,1.278.008Zm1.632.6c0,.017-.017.067-.025.108-.051.233-.118.283-.387.3l-.177.017a.664.664,0,0,0,0,.258l.025.033.168-.008c.093-.008.168-.008.168-.008,0,.017-.093.308-.1.316a2.954,2.954,0,0,1-.6-.017c-.1-.033-.1-.025-.093-.549l.008-.458h.429v.175h.084c.092,0,.1-.008.143-.125l.025-.067h.168C10.839,10.952,10.856,10.952,10.848,10.969Zm.791-3.562-.093.4h.126c.648.017.917-.724.286-.774l-.2-.017c-.025,0-.025.025-.118.391Zm-3.348.566c-.16.067-.311.666-.185.757.092.075.227-.05.294-.258C8.51,8.089,8.476,7.906,8.291,7.973Zm5.013.042c-.168.083-.294.674-.168.741.168.092.387-.225.387-.566C13.523,8.031,13.43,7.956,13.3,8.014ZM9.906,10l-.042.15a1.4,1.4,0,0,1-.05.15c0,.008.042-.008.1-.042a.845.845,0,0,1,.463-.108l.21-.008a.828.828,0,0,0,.042-.15A7.026,7.026,0,0,0,9.906,10Zm-.143.483-.034.133.723-.008.042-.133C9.923,10.47,9.763,10.47,9.763,10.478Zm2.288-.3a.81.81,0,0,0-.05.191l.1-.033a1.631,1.631,0,0,1,.193-.05c.05-.008.092-.017.1-.017s.084-.258.084-.266S12.4,10,12.295,10H12.11l-.059.183Zm-.135.424c0,.008-.034.092-.059.191s-.059.191-.059.191.042-.008.1-.033a1.01,1.01,0,0,1,.193-.058c.109-.017.118-.025.126-.067.008-.017.025-.083.042-.133l.034-.1H12.11a.841.841,0,0,0-.193.008Zm-.294.957.37.008c.076-.25.1-.333.1-.341l-.37-.017-.1.35Z" fill="#fff"/>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="74" height="74" viewBox="0 0 74 74">
<g id="组_124120" data-name="组 124120" transform="translate(-38 -467)">
<rect id="矩形_54154" data-name="矩形 54154" width="74" height="74" rx="16" transform="translate(38 467)" fill="#ffb538"/>
<path id="收益_2_" data-name="收益 (2)" d="M192.3,138.358l13.827-.039c.638-.074,2.993-2.8,3.536-5.688.522-2.726-1.049-3.591-4.982-3.591s-3.126,3.826-3.918,3.826c-.462,0-.881-2.937-2.674-4.183-1.285-.892-3.059,1.4-4.758,1.417-1.984.018-4.57-.234-4.57,2.684,0,2.418,2.861,5.574,3.54,5.574Zm-.569.425a.824.824,0,1,0,0,1.617h15.119a.824.824,0,1,0,0-1.617Zm15.944,3.031H191.06a20.243,20.243,0,0,0-9.974,17.524c0,8.985,8.559,11.035,18.331,11.035s17.91-2.148,17.91-11.141a20.139,20.139,0,0,0-9.648-17.418Zm-4.86,11.5a1.161,1.161,0,1,1,0,2.318h-2.473v1.161h2.473a1.161,1.161,0,1,1,0,2.318h-2.473v2.438a1.239,1.239,0,0,1-2.473,0v-2.438H195.4a1.162,1.162,0,1,1,0-2.318h2.472v-1.161H195.4a1.162,1.162,0,1,1,0-2.318h2.472v-.678l-3.468-3.145a1.11,1.11,0,0,1-.029-1.64,1.3,1.3,0,0,1,1.748-.027l3.081,2.8,3.081-2.8a1.3,1.3,0,0,1,1.748.027,1.112,1.112,0,0,1-.028,1.64l-3.66,3.318v.5h2.473Z" transform="translate(-124.086 354.525)" fill="#fff"/>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
<defs>
<style>
.cls-1 {
fill: #fff;
}
.cls-2 {
fill: #009fe8;
}
</style>
</defs>
<g id="支付宝支付" transform="translate(2 1)">
<rect id="矩形_2341" data-name="矩形 2341" class="cls-1" width="20" height="20" rx="4" transform="translate(-2 -1)"/>
<path id="路径_4973" data-name="路径 4973" class="cls-2" d="M20,13.691V3.845A3.847,3.847,0,0,0,16.154,0H3.845A3.847,3.847,0,0,0,0,3.845V16.154A3.846,3.846,0,0,0,3.845,20H16.154a3.85,3.85,0,0,0,3.786-3.166c-1.02-.442-5.44-2.35-7.743-3.45-1.752,2.123-3.588,3.4-6.354,3.4s-4.613-1.7-4.391-3.79c.146-1.368,1.085-3.6,5.162-3.222A18.37,18.37,0,0,1,11.5,10.95a13.885,13.885,0,0,0,1.116-2.72H4.845v-.77H8.691V6.077H4V5.23H8.69V3.235a.372.372,0,0,1,.387-.312H11V5.23h5v.848H11V7.46h4.079a15.741,15.741,0,0,1-1.657,4.154c1.185.43,6.578,2.078,6.578,2.078ZM5.538,15.46c-2.923,0-3.385-1.845-3.23-2.616a2.5,2.5,0,0,1,2.625-1.77,12.19,12.19,0,0,1,5.548,1.456c-1.41,1.836-3.143,2.93-4.943,2.93Z" transform="translate(-2 -1)"/>
</g>
</svg>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment