This commit is contained in:
zlwu committed 2026-08-11 11:13:01 +08:00
1 parent 80138c6388
commit 693e8a678e
682 files changed
+211375 -5306

No files matched your search

+73
View File
@@ -0,0 +1,73 @@
<template>
<view
v-if="show"
class="confirm-dialog"
@touchmove.stop.prevent="noop"
>
<view class="confirm-dialog__mask" @click="onCancel" />
<view class="confirm-dialog__panel">
<view class="confirm-dialog__body">
<view class="confirm-dialog__title">{{ title }}</view>
<view class="confirm-dialog__content">
<slot>{{ content }}</slot>
</view>
</view>
<view class="confirm-dialog__actions">
<view
class="confirm-dialog__btn confirm-dialog__btn--cancel"
@click="onCancel"
>
{{ cancelText }}
</view>
<!-- 微信 getPhoneNumber 必须由用户点击 button 触发,不可编程唤起 -->
<button
v-if="confirmOpenType"
class="confirm-dialog__btn confirm-dialog__btn--confirm confirm-dialog__btn--native"
hover-class="none"
:open-type="confirmOpenType"
@getphonenumber="onConfirmPhone"
>
{{ confirmText }}
</button>
<view
v-else
class="confirm-dialog__btn confirm-dialog__btn--confirm"
@click="onConfirm"
>
{{ confirmText }}
</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'ConfirmDialog',
props: {
show: { type: Boolean, default: false },
title: { type: String, default: '请先同意协议' },
content: { type: String, default: '' },
cancelText: { type: String, default: '取消' },
confirmText: { type: String, default: '同意并登录' },
/** 如 getPhoneNumber:确认键渲染为原生 button,同一次点击可拉起微信授权 */
confirmOpenType: { type: String, default: '' }
},
methods: {
noop() {},
onCancel() {
this.$emit('update:show', false)
this.$emit('cancel')
},
onConfirm() {
this.$emit('update:show', false)
this.$emit('confirm')
},
onConfirmPhone(e) {
this.$emit('update:show', false)
this.$emit('confirm')
this.$emit('getphonenumber', e)
}
}
}
</script>
+4 -1
View File
@@ -7,7 +7,7 @@
@click="$emit('select', m)"
>
<view class="menu-icon" :class="m.tone || ''">
<van-icon :name="m.icon" />
<VanIcon :name="m.icon" />
</view>
<text class="menu-title">{{ m.title }}</text>
</view>
@@ -15,8 +15,11 @@
</template>
<script>
import VanIcon from './van-icon/van-icon.vue'
export default {
name: 'MenuGrid',
components: { VanIcon },
props: {
menus: { type: Array, default: () => [] }
},
+9 -5
View File
@@ -7,17 +7,17 @@
<view style="padding: 24rpx">
<view class="todo-stats">
<view class="todo-stat tone-warn" @click="$emit('stat-click', 'approve')">
<view class="stat-icon"><van-icon name="passed" /></view>
<view class="stat-icon"><VanIcon name="passed" /></view>
<text class="num">{{ stats.approve }}</text>
<text class="label">待审批</text>
</view>
<view class="todo-stat tone-pay" @click="$emit('stat-click', 'pay')">
<view class="stat-icon"><van-icon name="balance-list-o" /></view>
<view class="stat-icon"><VanIcon name="balance-list-o" /></view>
<text class="num">{{ stats.pay }}</text>
<text class="label">待确认缴费</text>
</view>
<view class="todo-stat tone-danger" @click="$emit('stat-click', 'alert')">
<view class="stat-icon"><van-icon name="warning-o" /></view>
<view class="stat-icon"><VanIcon name="warning-o" /></view>
<text class="num">{{ stats.alert }}</text>
<text class="label">异常提醒</text>
</view>
@@ -30,14 +30,14 @@
@click="$emit('item-click', t)"
>
<view class="ti-icon" :class="t.iconClass">
<van-icon :name="t.icon" />
<VanIcon :name="t.icon" />
</view>
<view class="ti-body">
<view class="ti-title">{{ t.title }}</view>
<view class="ti-desc">{{ t.desc }}</view>
</view>
<view class="ti-right">
<van-tag :type="t.tagType" plain>{{ t.tag }}</van-tag>
<VanTag :type="t.tagType" plain>{{ t.tag }}</VanTag>
<text class="ti-time">{{ t.time }}</text>
</view>
</view>
@@ -47,8 +47,12 @@
</template>
<script>
import VanIcon from './van-icon/van-icon.vue'
import VanTag from './van-tag/van-tag.vue'
export default {
name: 'TodoPanel',
components: { VanIcon, VanTag },
props: {
stats: {
type: Object,
+7 -32
View File
@@ -2,10 +2,11 @@
<view class="v-empty">
<view class="v-empty__card">
<view class="v-empty__blob">
<view class="v-empty__inbox">
<view class="v-empty__inbox-tray" />
<view class="v-empty__inbox-slot" />
</view>
<image
class="v-empty__icon"
src="/static/empty-inbox.svg"
mode="aspectFit"
/>
</view>
<text class="v-empty__desc">{{ description || '暂无数据' }}</text>
<text v-if="tip" class="v-empty__tip">{{ tip }}</text>
@@ -55,35 +56,9 @@
justify-content: center;
}
/* CSS 近似 inbox,避免 inline SVG 在部分端兼容问题 */
.v-empty__inbox {
position: relative;
.v-empty__icon {
width: 56rpx;
height: 48rpx;
}
.v-empty__inbox-tray {
position: absolute;
left: 0;
right: 0;
top: 8rpx;
bottom: 0;
border: 4rpx solid #0a9f6d;
border-radius: 6rpx 6rpx 10rpx 10rpx;
box-sizing: border-box;
}
.v-empty__inbox-slot {
position: absolute;
left: 8rpx;
right: 8rpx;
top: 0;
height: 20rpx;
border: 4rpx solid #0a9f6d;
border-bottom: none;
border-radius: 6rpx 6rpx 0 0;
box-sizing: border-box;
background: radial-gradient(circle at 35% 30%, #ffffff, #d8f3e7 70%);
height: 56rpx;
}
.v-empty__desc {
@@ -0,0 +1,65 @@
<template>
<text class="v-icon" :style="iconStyle">{{ glyph }}</text>
</template>
<script>
/** H5 兼容:替代 @vant/weapp van-icon(weapp 组件无法在 Vite H5 下 ESM 导入) */
const GLYPHS = {
'todo-list-o': '☰',
'orders-o': '▤',
'balance-list-o': '¥',
logistics: '🚚',
certificate: '✓',
'cluster-o': '◈',
'send-gift-o': '↗',
'apps-o': '▦',
passed: '✓',
'warning-o': '!',
plus: '+',
arrow: '›',
'eye-o': '◎',
down: '↓',
checked: '✓',
'manager-o': '☺',
'clock-o': '◷',
'description': '📄',
'photo-o': '▣',
'video-o': '▶',
'music-o': '♪',
'bag-o': '▣',
'records': '☰'
}
export default {
name: 'VanIconShim',
props: {
name: { type: String, default: '' },
size: { type: [String, Number], default: '' },
color: { type: String, default: '' }
},
computed: {
glyph() {
return GLYPHS[this.name] || '●'
},
iconStyle() {
const style = {}
if (this.size) {
const s = String(this.size)
style.fontSize = /px|rpx|em|rem|%$/.test(s) ? s : `${s}px`
}
if (this.color) style.color = this.color
return style
}
}
}
</script>
<style scoped>
.v-icon {
display: inline-flex;
align-items: center;
justify-content: center;
line-height: 1;
font-style: normal;
}
</style>
+103
View File
@@ -0,0 +1,103 @@
<template>
<text class="v-tag" :class="tagClass" :style="tagStyle">
<slot />
</text>
</template>
<script>
/** H5 兼容:替代 @vant/weapp van-tag */
export default {
name: 'VanTagShim',
props: {
type: { type: String, default: 'default' },
plain: { type: Boolean, default: false },
round: { type: Boolean, default: false },
color: { type: String, default: '' }
},
computed: {
tagClass() {
return [
`is-${this.type || 'default'}`,
{ 'is-plain': this.plain, 'is-round': this.round }
]
},
tagStyle() {
if (!this.color) return {}
if (this.plain) {
return { color: this.color, borderColor: this.color, background: 'transparent' }
}
return { background: this.color, borderColor: this.color, color: '#fff' }
}
}
}
</script>
<style scoped>
.v-tag {
display: inline-flex;
align-items: center;
justify-content: center;
height: 36rpx;
padding: 0 12rpx;
font-size: 22rpx;
line-height: 1;
border-radius: 6rpx;
border: 1rpx solid transparent;
box-sizing: border-box;
white-space: nowrap;
}
.v-tag.is-round {
border-radius: 999rpx;
}
.v-tag.is-default {
background: #f2f5f4;
color: #3d524a;
}
.v-tag.is-primary {
background: #e9f9f2;
color: #087f57;
}
.v-tag.is-success {
background: #e9f9f2;
color: #189b65;
}
.v-tag.is-warning {
background: #fff7e8;
color: #cf8a19;
}
.v-tag.is-danger {
background: #fdecec;
color: #d14343;
}
.v-tag.is-plain.is-primary,
.v-tag.is-plain.is-success {
background: transparent;
border-color: #0a9f6d;
color: #0a9f6d;
}
.v-tag.is-plain.is-warning {
background: transparent;
border-color: #cf8a19;
color: #cf8a19;
}
.v-tag.is-plain.is-danger {
background: transparent;
border-color: #d14343;
color: #d14343;
}
.v-tag.is-plain.is-default {
background: transparent;
border-color: #c5d4cd;
color: #3d524a;
}
</style>