f
This commit is contained in:
56
src/views/AccountCancelAgreement.vue
Normal file
56
src/views/AccountCancelAgreement.vue
Normal file
@@ -0,0 +1,56 @@
|
||||
<script setup>
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<article class="user-agreement p-4 text-sm text-gray-800 leading-relaxed">
|
||||
<h1 class="mb-4 text-center text-lg text-gray-900 font-semibold">
|
||||
帐号注销协议
|
||||
</h1>
|
||||
<p class="mb-3 text-justify">
|
||||
您在申请注销流程中点击同意前,应当认真阅读《帐号注销协议》(以下简称“本协议”)。特别提醒您,当您成功提交注销申请后,即表示您已充分阅读、理解并接受本协议的全部内容。阅读本协议的过程中,如果您不同意相关任何条款,请您立即停止帐号注销程序。如您对本协议有任何疑问,可联系我们的客服。
|
||||
</p>
|
||||
|
||||
<p class="mb-3 text-justify">
|
||||
1. 如果您仍欲继续注销帐号,您的帐号需同时满足以下条件:
|
||||
</p>
|
||||
<p class="mb-2 ml-2 text-justify">
|
||||
(1)帐号不在处罚状态中,且能正常登录;
|
||||
</p>
|
||||
<p class="mb-3 ml-2 text-justify">
|
||||
(2)帐号最近一个月内并无修改密码、修改关联手机、绑定手机记录。
|
||||
</p>
|
||||
|
||||
<p class="mb-3 text-justify">
|
||||
2. 您应确保您有权决定该帐号的注销事宜,不侵犯任何第三方的合法权益,如因此引发任何争议,由您自行承担。
|
||||
</p>
|
||||
|
||||
<p class="mb-3 text-justify">
|
||||
3. 您理解并同意,账号注销后我们无法协助您重新恢复前述服务。请您在申请注销前自行备份您欲保留的本帐号信息和数据。
|
||||
</p>
|
||||
|
||||
<p class="mb-3 text-justify">
|
||||
4. 帐号注销后,已绑定的手机号、认证信息将会消失且无法注册。
|
||||
</p>
|
||||
|
||||
<p class="mb-3 text-justify">
|
||||
5. 注销帐号后,您将无法再使用本帐号,也将无法找回您帐号中及与帐号相关的任何内容或信息,包括但不限于:
|
||||
</p>
|
||||
<p class="mb-2 ml-2 text-justify">
|
||||
(1)您将无法继续使用该帐号进行登录;
|
||||
</p>
|
||||
<p class="mb-2 ml-2 text-justify">
|
||||
(2)您帐号的个人资料和历史信息(包含昵称、头像、消费记录、查询报告等)都将无法找回;
|
||||
</p>
|
||||
<p class="mb-3 ml-2 text-justify">
|
||||
(3)您理解并同意注销帐号后,您曾获得的充值余额、贝壳币及其他虚拟财产等将视为您自愿、主动放弃,无法继续使用,由此引起一切纠纷由您自行处理,我们不承担任何责任。
|
||||
</p>
|
||||
|
||||
<p class="mb-3 text-justify">
|
||||
6. 在帐号注销期间,如果您的帐号被他人投诉、被国家机关调查或者正处于诉讼、仲裁程序中,我们有权自行终止您的帐号注销程序,而无需另行得到您的同意。
|
||||
</p>
|
||||
|
||||
<p class="mb-3 text-justify">
|
||||
7. 请注意,注销您的帐号并不代表本帐号注销前的帐号行为和相关责任得到豁免或减轻。
|
||||
</p>
|
||||
</article>
|
||||
</template>
|
||||
@@ -105,86 +105,17 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 活跃下级奖励 -->
|
||||
<!-- 团队奖励明细与下级 -->
|
||||
<div class="rounded-xl shadow-lg bg-gradient-to-r from-success-50/50 to-success-100/40 p-6">
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<div class="flex items-center">
|
||||
<van-icon name="friends" class="text-xl mr-2" style="color: var(--color-success);" />
|
||||
<span class="text-lg font-bold" style="color: var(--van-text-color);">活跃下级奖励</span>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<div class="text-2xl font-bold" style="color: var(--color-success);">
|
||||
¥
|
||||
{{
|
||||
(data?.active_reward?.total_reward || 0).toFixed(2)
|
||||
}}
|
||||
</div>
|
||||
<div class="text-sm mt-1" style="color: var(--van-text-color-2);">活跃下级 0 位</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 日期选择 -->
|
||||
<div class="grid grid-cols-3 gap-2 mb-6">
|
||||
<button v-for="item in activeDateOptions" :key="item.value" @click="selectedActiveDate = item.value"
|
||||
class="rounded-full transition-all py-1 px-4 text-sm" :class="[
|
||||
selectedActiveDate === item.value
|
||||
? 'text-white shadow-md'
|
||||
: 'bg-white/90 border',
|
||||
]" :style="selectedActiveDate === item.value
|
||||
? 'background-color: var(--color-success);'
|
||||
: 'color: var(--van-text-color-2); border-color: var(--van-border-color);'">
|
||||
{{ item.label }}
|
||||
<div class="grid grid-cols-1 gap-3 sm:grid-cols-2">
|
||||
<button type="button" @click="goToRewardsDetail"
|
||||
class="w-full rounded-full border bg-white/90 py-3 px-4 shadow-sm flex items-center justify-center"
|
||||
style="color: var(--van-text-color-2); border-color: var(--van-border-color);">
|
||||
<van-icon name="records" class="mr-1" />
|
||||
团队奖励明细
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-2 gap-2 mb-6">
|
||||
<div class="p-3 rounded-lg backdrop-blur-sm" style="background-color: rgba(16, 185, 129, 0.08);">
|
||||
<div class="flex items-center text-sm" style="color: var(--van-text-color-2);">
|
||||
<van-icon name="medal" class="mr-1" />本日奖励
|
||||
</div>
|
||||
<div class="text-xl font-bold mt-1" style="color: var(--color-success);">
|
||||
¥
|
||||
{{ (currentActiveData.active_reward || 0).toFixed(2) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-3 rounded-lg backdrop-blur-sm" style="background-color: rgba(16, 185, 129, 0.08);">
|
||||
<div class="flex items-center text-sm" style="color: var(--van-text-color-2);">
|
||||
<van-icon name="discount" class="mr-1" />下级推广奖励
|
||||
</div>
|
||||
<div class="text-xl font-bold mt-1" style="color: var(--color-success);">
|
||||
¥
|
||||
{{
|
||||
(currentActiveData.sub_promote_reward || 0).toFixed(
|
||||
2
|
||||
)
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-3 rounded-lg backdrop-blur-sm" style="background-color: rgba(16, 185, 129, 0.08);">
|
||||
<div class="flex items-center text-sm" style="color: var(--van-text-color-2);">
|
||||
<van-icon name="fire" class="mr-1" />下级转化奖励
|
||||
</div>
|
||||
<div class="text-xl font-bold mt-1" style="color: var(--color-success);">
|
||||
¥
|
||||
{{
|
||||
(
|
||||
currentActiveData.sub_withdraw_reward || 0
|
||||
).toFixed(2)
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between text-sm font-semibold cursor-pointer pt-4"
|
||||
style="color: var(--color-success);" @click="goToActiveDetail">
|
||||
<span>查看奖励明细</span>
|
||||
<span class="text-lg">→</span>
|
||||
</div>
|
||||
|
||||
<!-- 添加查看下级按钮 -->
|
||||
<div class="mt-4">
|
||||
<button @click="toSubordinateList"
|
||||
class="w-full text-white rounded-full py-2 px-4 shadow-md flex items-center justify-center bg-success"
|
||||
<button type="button" @click="toSubordinateList"
|
||||
class="w-full rounded-full py-3 px-4 shadow-md flex items-center justify-center text-white"
|
||||
style="background: linear-gradient(135deg, var(--color-success), var(--color-success-600));">
|
||||
<van-icon name="friends" class="mr-1" />
|
||||
查看我的下级
|
||||
@@ -219,33 +150,12 @@ const promoteDateOptions = [
|
||||
];
|
||||
const selectedPromoteDate = ref("today");
|
||||
|
||||
// 活跃下级数据
|
||||
const activeDateOptions = [
|
||||
{ label: "今日", value: "today" },
|
||||
{ label: "近7天", value: "week" },
|
||||
{ label: "近1月", value: "month" },
|
||||
];
|
||||
const selectedActiveDate = ref("today");
|
||||
|
||||
// 计算当前直推数据
|
||||
const currentPromoteData = computed(() => {
|
||||
const range = dateRangeMap[selectedPromoteDate.value];
|
||||
return data.value?.direct_push?.[range] || { commission: 0, report: 0 };
|
||||
});
|
||||
|
||||
// 计算当前活跃数据
|
||||
const currentActiveData = computed(() => {
|
||||
const range = dateRangeMap[selectedActiveDate.value];
|
||||
return (
|
||||
data.value?.active_reward?.[range] || {
|
||||
active_reward: 0,
|
||||
sub_promote_reward: 0,
|
||||
sub_upgrade_reward: 0,
|
||||
sub_withdraw_reward: 0,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
const getData = async () => {
|
||||
const { data: res, error } = await useApiFetch("/agent/revenue")
|
||||
.get()
|
||||
@@ -264,7 +174,7 @@ onMounted(() => {
|
||||
|
||||
// 路由跳转
|
||||
const goToPromoteDetail = () => router.push({ name: "promoteDetails" });
|
||||
const goToActiveDetail = () => router.push({ name: "rewardsDetails" });
|
||||
const goToRewardsDetail = () => router.push({ name: "rewardsDetails" });
|
||||
|
||||
const toWithdraw = () => router.push({ name: "withdraw" });
|
||||
|
||||
|
||||
@@ -88,18 +88,9 @@ const getData = async () => {
|
||||
if (res.value?.code === 200 && !error.value) {
|
||||
if (page.value === 1) {
|
||||
data.value = res.value.data
|
||||
// 策略A:前端下线“新增活跃/月度活跃奖励”
|
||||
if (Array.isArray(data.value.list)) {
|
||||
data.value.list = data.value.list.filter(
|
||||
i => i.type !== 'descendant_new_active' && i.type !== 'descendant_stay_active'
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if (Array.isArray(res.value.data.list)) {
|
||||
const list = res.value.data.list.filter(
|
||||
i => i.type !== 'descendant_new_active' && i.type !== 'descendant_stay_active'
|
||||
)
|
||||
data.value.list.push(...list)
|
||||
data.value.list.push(...res.value.data.list)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -642,6 +642,13 @@ const buttonClass = computed(() => {
|
||||
// VIP价格配置
|
||||
const vipConfig = reactive({})
|
||||
|
||||
function toFiniteNumber(value, fallback = 0) {
|
||||
if (value === null || value === undefined || value === '')
|
||||
return fallback
|
||||
const n = typeof value === 'number' ? value : Number(value)
|
||||
return Number.isFinite(n) ? n : fallback
|
||||
}
|
||||
|
||||
// 计算得出的收益数据
|
||||
const revenueData = computed(() => {
|
||||
const baseOrders = 300 // 基础订单数
|
||||
@@ -741,20 +748,17 @@ onMounted(async () => {
|
||||
|
||||
const selectedType = ref('vip') // 默认选择VIP
|
||||
const showPayment = ref(false)
|
||||
const payData = ref({
|
||||
product_name: `${selectedType.value.toUpperCase()}代理`,
|
||||
sell_price: vipConfig.price,
|
||||
})
|
||||
const payID = ref('')
|
||||
const payData = computed(() => ({
|
||||
product_name: `${selectedType.value === 'vip' ? 'VIP' : 'SVIP'}代理`,
|
||||
sell_price: selectedType.value === 'vip'
|
||||
? toFiniteNumber(vipConfig.price)
|
||||
: toFiniteNumber(vipConfig.svipPrice),
|
||||
}))
|
||||
|
||||
// 选择代理类型
|
||||
function selectType(type) {
|
||||
selectedType.value = type
|
||||
// 更新payData中的价格和产品名称
|
||||
payData.value = {
|
||||
product_name: `${type === 'vip' ? 'VIP' : 'SVIP'}代理`,
|
||||
sell_price: type === 'vip' ? vipConfig.price : vipConfig.svipPrice,
|
||||
}
|
||||
}
|
||||
|
||||
// 申请VIP或SVIP
|
||||
@@ -771,6 +775,11 @@ async function applyVip() {
|
||||
return
|
||||
}
|
||||
|
||||
if (toFiniteNumber(payData.value.sell_price) <= 0) {
|
||||
showToast('会员价格加载中,请稍后重试')
|
||||
return
|
||||
}
|
||||
|
||||
const { data, error } = await useApiFetch('/agent/membership/activate')
|
||||
.post({
|
||||
type: selectedType.value.toUpperCase(),
|
||||
|
||||
@@ -176,23 +176,14 @@ import { ref, reactive, computed, onMounted } from "vue";
|
||||
import { showToast } from "vant";
|
||||
import { settings } from "nprogress";
|
||||
|
||||
// 报告类型选项
|
||||
const reportOptions = [
|
||||
{ text: "小微企业", value: "companyinfo", id: 2 },
|
||||
{ text: "贷前风险", value: "preloanbackgroundcheck", id: 5 },
|
||||
{ text: "个人大数据", value: "personaldata", id: 27 },
|
||||
{ text: "入职风险", value: "backgroundcheck", id: 1 },
|
||||
{ text: "家政风险", value: "homeservice", id: 3 },
|
||||
{ text: "婚恋风险", value: "marriage", id: 4 },
|
||||
// { text: "租赁风险", value: "rentalrisk", id: 6 },
|
||||
// { text: "个人风险", value: "riskassessment", id: 7 },
|
||||
];
|
||||
// 报告类型选项:完全由后端返回
|
||||
const reportOptions = ref([]);
|
||||
|
||||
// 状态管理
|
||||
const showPicker = ref(false);
|
||||
const selectedReport = ref(reportOptions[0]);
|
||||
const selectedReportText = ref(reportOptions[0].text);
|
||||
const selectedReportId = ref(reportOptions[0].id);
|
||||
const selectedReport = ref(null);
|
||||
const selectedReportText = ref("");
|
||||
const selectedReportId = ref(null);
|
||||
|
||||
const configData = ref({});
|
||||
const productConfigData = ref({});
|
||||
@@ -347,6 +338,7 @@ const validateRatio = () => {
|
||||
|
||||
// 获取配置
|
||||
const getConfig = async () => {
|
||||
if (!selectedReportId.value) return;
|
||||
try {
|
||||
const { data, error } = await useApiFetch(
|
||||
"/agent/membership/user_config?product_id=" + selectedReportId.value
|
||||
@@ -474,9 +466,11 @@ const finalValidation = () => {
|
||||
|
||||
// 选择器确认
|
||||
const onConfirm = ({ selectedOptions }) => {
|
||||
selectedReport.value = selectedOptions[0];
|
||||
selectedReportText.value = selectedOptions[0].text;
|
||||
selectedReportId.value = selectedOptions[0].id;
|
||||
const picked = selectedOptions?.[0];
|
||||
if (!picked) return;
|
||||
selectedReport.value = picked;
|
||||
selectedReportText.value = picked.text;
|
||||
selectedReportId.value = picked.value;
|
||||
showPicker.value = false;
|
||||
// 重置错误状态
|
||||
rangeError.value = false;
|
||||
@@ -490,8 +484,32 @@ const closeRangeError = () => {
|
||||
rangeError.value = false;
|
||||
}, 2000);
|
||||
};
|
||||
onMounted(() => {
|
||||
getConfig();
|
||||
|
||||
const loadReportOptions = async () => {
|
||||
try {
|
||||
const { data, error } = await useApiFetch("/agent/product_config").get().json();
|
||||
if (error.value || data.value?.code !== 200) return;
|
||||
const list = data.value?.data?.agent_product_config || data.value?.data?.AgentProductConfig || [];
|
||||
reportOptions.value = list
|
||||
.map((p) => ({
|
||||
text: p.product_name || `报告${p.product_id}`,
|
||||
value: p.product_id,
|
||||
}))
|
||||
.filter((p) => p.value != null);
|
||||
if (reportOptions.value.length > 0) {
|
||||
const first = reportOptions.value[0];
|
||||
selectedReport.value = first;
|
||||
selectedReportText.value = first.text;
|
||||
selectedReportId.value = first.value;
|
||||
}
|
||||
} catch (e) { }
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
await loadReportOptions();
|
||||
if (selectedReportId.value) {
|
||||
getConfig();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
278
src/views/CancelAccount.vue
Normal file
278
src/views/CancelAccount.vue
Normal file
@@ -0,0 +1,278 @@
|
||||
<script setup>
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
||||
import { showConfirmDialog, showToast } from 'vant'
|
||||
import AccountCancelAgreement from '@/views/AccountCancelAgreement.vue'
|
||||
import useApiFetch from '@/composables/useApiFetch'
|
||||
import { useAgentStore } from '@/stores/agentStore'
|
||||
import { useUserStore } from '@/stores/userStore'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const userStore = useUserStore()
|
||||
const agentStore = useAgentStore()
|
||||
const { mobile } = storeToRefs(userStore)
|
||||
const { isAgent, level } = storeToRefs(agentStore)
|
||||
|
||||
const loading = ref(true)
|
||||
const revenueData = ref(null)
|
||||
|
||||
const showSmsModal = ref(false)
|
||||
const cancelAccountCode = ref('')
|
||||
const cancelSmsCountdown = ref(0)
|
||||
let cancelSmsTimer = null
|
||||
|
||||
function maskName(name) {
|
||||
if (!name || name.length < 11)
|
||||
return name
|
||||
return `${name.substring(0, 3)}****${name.substring(7)}`
|
||||
}
|
||||
|
||||
const hasWalletBalance = computed(() => {
|
||||
const b = Number(revenueData.value?.balance ?? 0)
|
||||
const f = Number(revenueData.value?.frozen_balance ?? 0)
|
||||
return b > 0 || f > 0
|
||||
})
|
||||
const showBalanceWarning = computed(() => isAgent.value && hasWalletBalance.value)
|
||||
|
||||
const showVipLevelReminder = computed(() =>
|
||||
isAgent.value && (level.value === 'VIP' || level.value === 'SVIP'),
|
||||
)
|
||||
const vipLevelLabel = computed(() => (level.value === 'SVIP' ? 'SVIP' : 'VIP'))
|
||||
|
||||
const showAnyReminder = computed(() => showBalanceWarning.value || showVipLevelReminder.value)
|
||||
|
||||
onMounted(async () => {
|
||||
await userStore.fetchUserInfo()
|
||||
if (!userStore.mobile) {
|
||||
loading.value = false
|
||||
showToast('请先绑定手机号')
|
||||
setTimeout(() => router.back(), 1500)
|
||||
return
|
||||
}
|
||||
try {
|
||||
await agentStore.fetchAgentStatus()
|
||||
if (agentStore.isAgent) {
|
||||
const { data, error } = await useApiFetch('/agent/revenue').get().json()
|
||||
if (!error.value && data.value?.code === 200)
|
||||
revenueData.value = data.value.data
|
||||
}
|
||||
}
|
||||
catch {
|
||||
/* ignore */
|
||||
}
|
||||
finally {
|
||||
loading.value = false
|
||||
}
|
||||
})
|
||||
|
||||
function onExit() {
|
||||
router.back()
|
||||
}
|
||||
|
||||
function startCancelSmsCountdown() {
|
||||
cancelSmsCountdown.value = 60
|
||||
if (cancelSmsTimer)
|
||||
clearInterval(cancelSmsTimer)
|
||||
cancelSmsTimer = setInterval(() => {
|
||||
if (cancelSmsCountdown.value > 0)
|
||||
cancelSmsCountdown.value--
|
||||
else
|
||||
clearInterval(cancelSmsTimer)
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
if (cancelSmsTimer)
|
||||
clearInterval(cancelSmsTimer)
|
||||
})
|
||||
|
||||
function openSmsModal() {
|
||||
cancelAccountCode.value = ''
|
||||
showSmsModal.value = true
|
||||
}
|
||||
|
||||
function onConfirmTap() {
|
||||
if (showBalanceWarning.value) {
|
||||
showConfirmDialog({
|
||||
title: '确认注销',
|
||||
message: '您的代理账户仍有余额或待结账金额,注销后将无法通过本账号提现,确定继续注销?',
|
||||
confirmButtonText: '继续',
|
||||
cancelButtonText: '取消',
|
||||
})
|
||||
.then(() => openSmsModal())
|
||||
.catch(() => {})
|
||||
}
|
||||
else {
|
||||
openSmsModal()
|
||||
}
|
||||
}
|
||||
|
||||
function closeSmsModal() {
|
||||
showSmsModal.value = false
|
||||
cancelAccountCode.value = ''
|
||||
}
|
||||
|
||||
async function sendCancelAccountSms() {
|
||||
if (!mobile.value) {
|
||||
showToast('请先绑定手机号')
|
||||
return
|
||||
}
|
||||
if (cancelSmsCountdown.value > 0)
|
||||
return
|
||||
const { data, error } = await useApiFetch('/auth/sendSms')
|
||||
.post({ mobile: mobile.value, actionType: 'cancelAccount', captchaVerifyParam: '' })
|
||||
.json()
|
||||
if (!error.value && data.value?.code === 200) {
|
||||
showToast({ message: '验证码已发送' })
|
||||
startCancelSmsCountdown()
|
||||
}
|
||||
else {
|
||||
showToast({ message: data.value?.msg || '发送失败' })
|
||||
}
|
||||
}
|
||||
|
||||
function clearAuthAndGoHome() {
|
||||
localStorage.removeItem('token')
|
||||
localStorage.removeItem('refreshAfter')
|
||||
localStorage.removeItem('accessExpire')
|
||||
localStorage.removeItem('userInfo')
|
||||
localStorage.removeItem('agentInfo')
|
||||
userStore.resetUser()
|
||||
agentStore.resetAgent()
|
||||
window.location.href = '/'
|
||||
}
|
||||
|
||||
async function submitCancelAccount() {
|
||||
if (cancelAccountCode.value.length !== 6) {
|
||||
showToast('请输入6位验证码')
|
||||
return
|
||||
}
|
||||
const { data, error } = await useApiFetch('/user/cancelOut')
|
||||
.post({ code: cancelAccountCode.value })
|
||||
.json()
|
||||
if (!error.value && data.value?.code === 200) {
|
||||
showToast({ message: '账号已注销' })
|
||||
closeSmsModal()
|
||||
clearAuthAndGoHome()
|
||||
}
|
||||
else {
|
||||
showToast({ message: data.value?.msg || '注销失败' })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- 减导航栏占位高度,避免整页超出视口(与 PageLayout 的 van-nav-bar placeholder 配合) -->
|
||||
<div
|
||||
class="box-border flex flex-col bg-gray-50"
|
||||
style="min-height: calc(100vh - var(--van-nav-bar-height, 46px)); height: calc(100vh - var(--van-nav-bar-height, 46px));"
|
||||
>
|
||||
<div v-if="loading" class="flex flex-1 items-center justify-center py-20 text-gray-500">
|
||||
加载中...
|
||||
</div>
|
||||
<template v-else>
|
||||
<div class="flex min-h-0 min-w-0 flex-1 flex-col">
|
||||
<div class="min-h-0 flex-1 overflow-y-auto border-b border-gray-100 bg-white">
|
||||
<AccountCancelAgreement />
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="showAnyReminder"
|
||||
class="flex-shrink-0 space-y-2 border-t border-gray-100 bg-gray-50 px-4 py-3"
|
||||
>
|
||||
<div
|
||||
v-if="showBalanceWarning"
|
||||
class="rounded-lg border border-amber-200 bg-amber-50 p-3 text-sm text-amber-900"
|
||||
>
|
||||
<p class="font-medium">
|
||||
钱包提示
|
||||
</p>
|
||||
<p class="mt-1 leading-relaxed">
|
||||
检测到您为代理且账户仍有余额(¥{{ (revenueData?.balance ?? 0).toFixed(2) }})或待结账金额(¥{{ (revenueData?.frozen_balance ?? 0).toFixed(2) }})。注销后将无法通过本账号提现,请确认已了解风险。
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
v-if="showVipLevelReminder"
|
||||
class="rounded-lg border border-violet-200 bg-violet-50 p-3 text-sm text-violet-900"
|
||||
>
|
||||
<p class="font-medium">
|
||||
会员提示
|
||||
</p>
|
||||
<p class="mt-1 leading-relaxed">
|
||||
您当前为 {{ vipLevelLabel }} 代理会员,注销后该账号下的代理身份与相关权益将按平台规则终止,请确认已了解风险。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex-shrink-0 border-t border-gray-200 bg-gray-50 px-4 pb-[max(1rem,env(safe-area-inset-bottom))] pt-3">
|
||||
<div class="flex gap-3">
|
||||
<button
|
||||
type="button"
|
||||
class="flex-1 rounded-lg border border-gray-300 bg-white py-3 text-gray-800"
|
||||
@click="onExit"
|
||||
>
|
||||
退出
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="flex-1 rounded-lg bg-red-500 py-3 text-white"
|
||||
@click="onConfirmTap"
|
||||
>
|
||||
确认
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div
|
||||
v-if="showSmsModal"
|
||||
class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4"
|
||||
@click.self="closeSmsModal"
|
||||
>
|
||||
<div class="w-full max-w-sm rounded-xl bg-white p-5 shadow-lg" @click.stop>
|
||||
<p class="mb-2 text-base font-medium text-gray-800">
|
||||
验证手机号
|
||||
</p>
|
||||
<p class="mb-4 text-sm text-gray-500">
|
||||
将向 {{ maskName(mobile) }} 发送验证码。
|
||||
</p>
|
||||
<input
|
||||
v-model="cancelAccountCode"
|
||||
type="text"
|
||||
maxlength="6"
|
||||
inputmode="numeric"
|
||||
placeholder="请输入6位验证码"
|
||||
class="mb-4 w-full rounded-lg border border-gray-200 px-3 py-2 text-base"
|
||||
>
|
||||
<div class="mb-4">
|
||||
<button
|
||||
type="button"
|
||||
class="w-full rounded-lg bg-gray-100 py-2 text-sm text-gray-700 disabled:opacity-50"
|
||||
:disabled="cancelSmsCountdown > 0"
|
||||
@click="sendCancelAccountSms"
|
||||
>
|
||||
{{ cancelSmsCountdown > 0 ? `${cancelSmsCountdown}s` : '获取验证码' }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<button
|
||||
type="button"
|
||||
class="flex-1 rounded-lg bg-gray-200 py-2 text-gray-800"
|
||||
@click="closeSmsModal"
|
||||
>
|
||||
取消
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="flex-1 rounded-lg bg-red-500 py-2 text-white"
|
||||
@click="submitCancelAccount"
|
||||
>
|
||||
确认注销
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -124,6 +124,15 @@
|
||||
</div>
|
||||
<img src="@/assets/images/me/right.png" class="w-4 h-4" alt="右箭头" />
|
||||
</button>
|
||||
<button v-if="isLoggedIn && mobile"
|
||||
class="w-full flex items-center justify-between border-b border-gray-100 px-6 py-4 hover:bg-red-50 transition-colors"
|
||||
@click="goCancelAccountPage">
|
||||
<div class="flex items-center gap-3">
|
||||
<img src="@/assets/images/me/cancelAccount.svg" class="w-6 h-6" alt="注销账号" />
|
||||
<span class="text-gray-700 font-medium">注销账号</span>
|
||||
</div>
|
||||
<img src="@/assets/images/me/right.png" class="w-4 h-4" alt="右箭头" />
|
||||
</button>
|
||||
<button v-if="isLoggedIn && !isWeChat"
|
||||
class="w-full flex items-center justify-between px-6 py-4 hover:bg-red-50 transition-colors"
|
||||
@click="handleLogout">
|
||||
@@ -142,13 +151,13 @@
|
||||
<script setup>
|
||||
import { storeToRefs } from "pinia";
|
||||
import { ref, computed, onBeforeMount } from "vue";
|
||||
import { showToast } from "vant";
|
||||
const router = useRouter();
|
||||
import headShot from "@/assets/images/head_shot.webp";
|
||||
import { useAgentStore } from "@/stores/agentStore";
|
||||
import { useUserStore } from "@/stores/userStore";
|
||||
import { useEnv } from "@/composables/useEnv";
|
||||
import { useDialogStore } from "@/stores/dialogStore";
|
||||
import useApiFetch from "@/composables/useApiFetch";
|
||||
const agentStore = useAgentStore();
|
||||
const userStore = useUserStore();
|
||||
const dialogStore = useDialogStore();
|
||||
@@ -235,22 +244,12 @@ function handleLogout() {
|
||||
location.reload();
|
||||
}
|
||||
|
||||
function handleCancelAccount() {
|
||||
// 账号注销功能
|
||||
if (confirm("注销账号后,您的所有数据将被清除且无法恢复,确定要继续吗?")) {
|
||||
useApiFetch("/user/cancelOut")
|
||||
.post()
|
||||
.json()
|
||||
.then(({ data, error }) => {
|
||||
if (!error && data.value && data.value.code === 200) {
|
||||
alert("账号已注销");
|
||||
handleLogout();
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("注销账号失败:", error);
|
||||
});
|
||||
function goCancelAccountPage() {
|
||||
if (!mobile.value) {
|
||||
showToast("请先绑定手机号");
|
||||
return;
|
||||
}
|
||||
router.push({ name: "cancelAccount" });
|
||||
}
|
||||
|
||||
function toService() {
|
||||
|
||||
@@ -35,9 +35,9 @@
|
||||
:product-config="pickerProductConfig" @change="onPriceChange" />
|
||||
<div class="flex items-center justify-between my-2">
|
||||
<div class="text-sm text-gray-500">推广收益为 <span class="text-orange-500">{{ promotionRevenue
|
||||
}}</span> 元</div>
|
||||
}}</span> 元</div>
|
||||
<div class="text-sm text-gray-500">我的成本为 <span class="text-orange-500">{{ costPrice
|
||||
}}</span> 元</div>
|
||||
}}</span> 元</div>
|
||||
</div>
|
||||
</van-cell-group>
|
||||
</div>
|
||||
@@ -87,16 +87,6 @@
|
||||
<script setup>
|
||||
import PriceInputPopup from '@/components/PriceInputPopup.vue';
|
||||
import VipBanner from '@/components/VipBanner.vue';
|
||||
const reportTypes = [
|
||||
{ text: "小微企业", value: "companyinfo", id: 2 },
|
||||
{ text: "贷前风险", value: "preloanbackgroundcheck", id: 5 },
|
||||
{ text: "个人大数据", value: "personaldata", id: 27 },
|
||||
{ text: '入职风险', value: 'backgroundcheck', id: 1 },
|
||||
{ text: '家政风险', value: 'homeservice', id: 3 },
|
||||
{ text: '婚恋风险', value: 'marriage', id: 4 },
|
||||
{ text: '租赁风险', value: 'rentalrisk', id: 6 },
|
||||
|
||||
];
|
||||
const showTypePicker = ref(false);
|
||||
const showApplyPopup = ref(false); // 用来控制申请代理弹窗的显示
|
||||
const showPricePicker = ref(false);
|
||||
@@ -107,6 +97,16 @@ const selectedReportType = ref([]);
|
||||
const clientPrice = ref(null);
|
||||
const productConfig = ref(null);
|
||||
const linkIdentifier = ref("")
|
||||
const reportTypes = computed(() => {
|
||||
if (!productConfig.value?.length) return []
|
||||
return productConfig.value
|
||||
.map(item => ({
|
||||
id: item.product_id,
|
||||
text: item.product_name || `产品${item.product_id}`,
|
||||
value: item.product_en || '',
|
||||
}))
|
||||
.filter(item => !!item.value)
|
||||
})
|
||||
|
||||
|
||||
|
||||
@@ -185,10 +185,10 @@ onMounted(() => {
|
||||
// getAgentInfo();
|
||||
});
|
||||
const SelectTypePicker = (reportType) => {
|
||||
selectedReportType.value = [reportType];
|
||||
selectedReportType.value = [reportType.value];
|
||||
pickerFieldText.value = reportType.text;
|
||||
pickerFieldVal.value = reportType.value;
|
||||
for (let i of productConfig.value) {
|
||||
for (let i of (productConfig.value || [])) {
|
||||
if (i.product_id === reportType.id) {
|
||||
pickerProductConfig.value = i
|
||||
clientPrice.value = i.cost_price
|
||||
@@ -202,8 +202,16 @@ const getPromoteConfig = async () => {
|
||||
|
||||
if (data.value && !error.value) {
|
||||
if (data.value.code === 200) {
|
||||
productConfig.value = data.value.data.AgentProductConfig;
|
||||
SelectTypePicker(reportTypes[0])
|
||||
productConfig.value = data.value.data.AgentProductConfig || [];
|
||||
if (reportTypes.value.length > 0) {
|
||||
SelectTypePicker(reportTypes.value[0])
|
||||
} else {
|
||||
pickerProductConfig.value = null
|
||||
pickerFieldText.value = ''
|
||||
pickerFieldVal.value = null
|
||||
clientPrice.value = null
|
||||
showToast({ message: '暂无可推广产品' });
|
||||
}
|
||||
} else {
|
||||
console.log("Error fetching agent info", data.value);
|
||||
}
|
||||
|
||||
@@ -119,9 +119,7 @@ const fetchRewardDetails = async () => {
|
||||
}
|
||||
// 处理列表数据
|
||||
if (data.value.data.list) {
|
||||
const list = data.value.data.list.filter(
|
||||
i => i.type !== 'descendant_new_active' && i.type !== 'descendant_stay_active',
|
||||
)
|
||||
const list = data.value.data.list
|
||||
if (page.value === 1) {
|
||||
rewardDetails.value = list
|
||||
} else {
|
||||
|
||||
@@ -16,6 +16,12 @@ import rentalinfo from "@/assets/images/index/rentalinfo_bg.png";
|
||||
import bannerImg from "@/assets/images/index/banner_1.png";
|
||||
import bannerImg2 from "@/assets/images/index/banner_2.png";
|
||||
import bannerImg3 from "@/assets/images/index/banner_3.png";
|
||||
import indexPromoteIcon from "@/assets/images/index/tgbg.png";
|
||||
import indexInvitationIcon from "@/assets/images/index/yqhy.png";
|
||||
import indexMyReportIcon from "@/assets/images/index/wdbg.png";
|
||||
import { useAppConfig } from "@/composables/useAppConfig";
|
||||
const { appConfig, loadAppConfig } = useAppConfig();
|
||||
void loadAppConfig();
|
||||
function toInquire(name) {
|
||||
router.push(`/inquire/${name}`);
|
||||
}
|
||||
@@ -115,7 +121,9 @@ const banners = ref([
|
||||
<div class="text-center flex flex-col justify-center items-center" @click="toPromote">
|
||||
<div
|
||||
class="h-16 w-16 p-1 box-content bg-gradient-to-b from-white to-blue-100/10 rounded-full shadow-lg flex items-center justify-center">
|
||||
<img src="@/assets/images/index/tgbg.png" alt="推广报告" class="h-12 w-12" />
|
||||
<div class="h-12 w-12 shrink-0 bg-contain bg-center bg-no-repeat select-none"
|
||||
role="img" aria-label="推广报告"
|
||||
:style="{ backgroundImage: `url(${indexPromoteIcon})` }" />
|
||||
</div>
|
||||
<div class="text-center mt-1 font-bold ">推广报告</div>
|
||||
</div>
|
||||
@@ -123,7 +131,9 @@ const banners = ref([
|
||||
<div class="text-center flex flex-col justify-center items-center" @click="toInvitation">
|
||||
<div
|
||||
class="h-16 w-16 p-1 box-content bg-gradient-to-b from-white to-blue-100/10 rounded-full shadow-lg flex items-center justify-center">
|
||||
<img src="@/assets/images/index/yqhy.png" alt="邀请下级" class="h-12 w-12" />
|
||||
<div class="h-12 w-12 shrink-0 bg-contain bg-center bg-no-repeat select-none"
|
||||
role="img" aria-label="邀请下级"
|
||||
:style="{ backgroundImage: `url(${indexInvitationIcon})` }" />
|
||||
</div>
|
||||
<div class="text-center mt-1 font-bold ">邀请下级</div>
|
||||
</div>
|
||||
@@ -137,7 +147,9 @@ const banners = ref([
|
||||
<div class="text-center flex flex-col justify-center items-center" @click="toHistory">
|
||||
<div
|
||||
class="h-16 w-16 p-1 box-content bg-gradient-to-b from-white to-blue-100/10 rounded-full shadow-lg flex items-center justify-center">
|
||||
<img src="@/assets/images/index/wdbg.png" alt="我的报告" class="h-12 w-12" />
|
||||
<div class="h-12 w-12 shrink-0 bg-contain bg-center bg-no-repeat select-none"
|
||||
role="img" aria-label="我的报告"
|
||||
:style="{ backgroundImage: `url(${indexMyReportIcon})` }" />
|
||||
</div>
|
||||
<div class="text-center mt-1 font-bold ">我的报告</div>
|
||||
</div>
|
||||
@@ -195,7 +207,7 @@ const banners = ref([
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<div class="text-gray-800">我的历史查询记录</div>
|
||||
<div class="text-xs text-gray-500">查询记录有效期为30天</div>
|
||||
<div class="text-xs text-gray-500">查询记录有效期为{{ appConfig.query.retention_days }}天</div>
|
||||
</div>
|
||||
<img src="@/assets/images/index/right.png" alt="右箭头" class="h-6 w-6" />
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user