feat: add account profile, search, help and security features

1. add default avatar and multiple notification icons
2. update finance archive note and add form styles
3. add new pages: edit-profile, security, password, change-phone, search, help
4. refactor navigation action layout to support multiple actions
5. add search button to home page
6. add security code component and account service APIs
7. add help and search content services
8. update message notice to use svg icons
9. update asset section in finance assessment
10. update manifest appid and pack options
This commit is contained in:
hujun
2026-09-21 15:04:59 +08:00
parent 046a03e5e9
commit 4a69357606
28 changed files with 846 additions and 116 deletions
@@ -0,0 +1,31 @@
<template>
<view class="code-field"><input class="code-input" :value="modelValue" :disabled="disabled" type="number" maxlength="6" placeholder="请输入 6 位验证码" @input="emit('update:modelValue', $event.detail.value)" /><button class="code-button" :disabled="disabled || sending || countdown > 0" @click="send">{{ sending ? '发送中…' : (countdown > 0 ? countdown + 's 后重试' : '获取验证码') }}</button></view>
</template>
<script setup lang="uts">
import { requestSecurityCode } from '@/packages/account/services/account.uts'
const props = defineProps({ modelValue: { type: String, default: '' }, purpose: { type: String, default: 'password' }, phone: { type: String, default: '' }, disabled: { type: Boolean, default: false } })
const emit = defineEmits(['update:modelValue', 'error', 'sent'])
const sending = ref(false); const countdown = ref(0)
let timer = 0; let version = 0; let expiresAt = 0
const reset = () => { version++; clearInterval(timer); countdown.value = 0; sending.value = false }
const targetPhone = computed((): string => props.phone)
watch(targetPhone, () => { reset(); emit('update:modelValue', '') })
const send = async () => {
if (props.disabled || sending.value || countdown.value > 0) return
const current = ++version; sending.value = true
try {
await requestSecurityCode(props.purpose, props.phone)
if (current != version) return
expiresAt = Date.now() + 60000; countdown.value = 60
timer = setInterval(() => { countdown.value = Math.max(0, Math.ceil((expiresAt - Date.now()) / 1000)); if (countdown.value == 0) clearInterval(timer) }, 1000)
emit('sent'); uni.showToast({ title: '验证码已发送', icon: 'none' })
} catch (error) { if (current == version) emit('error', error instanceof Error ? error.message : '发送失败,请稍后重试') }
finally { if (current == version) sending.value = false }
}
onUnmounted(() => reset())
</script>
<style>
.code-field { flex-direction: row; align-items: center; height: 96rpx; border-bottom: 1rpx solid #edf1f6; }
.code-input { flex: 1; min-width: 0; font-size: 27rpx; color: #23344e; }
.code-button { flex-shrink: 0; padding: 0 12rpx; margin: 0 0 0 12rpx; height: 72rpx; line-height: 72rpx; font-size: 24rpx; color: #0868f7; background-color: transparent; }
</style>