|
@@ -1,3 +1,206 @@
|
|
|
|
|
+import { StatusBadge } from "@/components/ui/status-badge";
|
|
|
|
|
+import UIButton from "@/components/ui/ui-button";
|
|
|
|
|
+import { Colors } from "@/constants/theme";
|
|
|
|
|
+import api from "@/utils/api";
|
|
|
|
|
+import { useSWC } from "@/utils/cache";
|
|
|
|
|
+import { Icon, Toast } from "@ant-design/react-native";
|
|
|
|
|
+import { Ionicons } from "@expo/vector-icons";
|
|
|
|
|
+import dayjs from 'dayjs';
|
|
|
|
|
+import { Link, Stack, useLocalSearchParams, useRouter } from "expo-router";
|
|
|
|
|
+import { useCallback, useEffect } from "react";
|
|
|
|
|
+import { ScrollView, Text, View } from "react-native";
|
|
|
|
|
+import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
|
|
|
+
|
|
|
|
|
+type Credit = {
|
|
|
|
|
+ id: string;
|
|
|
|
|
+ customer_id?: string;
|
|
|
|
|
+ name?: string;
|
|
|
|
|
+ updatetime?: number;
|
|
|
|
|
+ tags?: string[];
|
|
|
|
|
+ recommend?: string[];
|
|
|
|
|
+ suggestions?: string[];
|
|
|
|
|
+ level?: string;
|
|
|
|
|
+ amount?: string;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const tagsBg = ["primary", "tertiary", "error", "success"];
|
|
|
|
|
+
|
|
|
|
|
+type Metric = {
|
|
|
|
|
+ label: string;
|
|
|
|
|
+ value: string;
|
|
|
|
|
+ hint?: string;
|
|
|
|
|
+ tone?: "default" | "warn" | "danger" | "ok";
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+type Suggestion = {
|
|
|
|
|
+ title: string;
|
|
|
|
|
+ desc: string;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+const METRICS: Metric[] = [
|
|
|
|
|
+ { label: "近3个月查询次数", value: "8", hint: "次", tone: "warn" },
|
|
|
|
|
+ { label: "信用卡使用率", value: "72", hint: "%", tone: "warn" },
|
|
|
|
|
+ { label: "当前逾期", value: "无", tone: "ok" },
|
|
|
|
|
+ { label: "在用信贷账户", value: "6", hint: "户", tone: "default" },
|
|
|
|
|
+];
|
|
|
|
|
+
|
|
|
|
|
+const SUGGESTIONS: Suggestion[] = [
|
|
|
|
|
+ {
|
|
|
|
|
+ title: "控制近1个月新增查询",
|
|
|
|
|
+ desc: "短期内避免再次申请信用卡或网贷,降低硬查询次数。",
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ title: "优先匹配看重流水稳定的产品",
|
|
|
|
|
+ desc: "结合工资流水稳定的优势,选择对查询容忍度更高的产品。",
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ title: "降低信用卡使用率至 50% 以下",
|
|
|
|
|
+ desc: "适当还款或申请提额,使用率下降后可显著提升评分。",
|
|
|
|
|
+ },
|
|
|
|
|
+];
|
|
|
|
|
+
|
|
|
|
|
+const toneStyles: Record<NonNullable<Metric["tone"]>, { box: string; value: string }> = {
|
|
|
|
|
+ default: { box: "bg-surface-container-low border-outline-variant", value: "text-on-surface" },
|
|
|
|
|
+ ok: { box: "bg-green-50 border-green-100", value: "text-green-700" },
|
|
|
|
|
+ warn: { box: "bg-tertiary-fixed border-tertiary-fixed-dim", value: "text-on-tertiary-fixed" },
|
|
|
|
|
+ danger: { box: "bg-error-container border-error-container", value: "text-on-error-container" },
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
export default function CreditDetail() {
|
|
export default function CreditDetail() {
|
|
|
|
|
+ const insets = useSafeAreaInsets();
|
|
|
|
|
+ const router = useRouter();
|
|
|
|
|
+ const { id, customer_id, name } = useLocalSearchParams() as { id?: string; customer_id: string; name?: string };
|
|
|
|
|
+ const { data: detail, loading, error } = useSWC<Credit>("credit_" + (id ? id : "cid_" + customer_id), async () => {
|
|
|
|
|
+ return await api.post("credit/detail", {
|
|
|
|
|
+ id,
|
|
|
|
|
+ customer_id
|
|
|
|
|
+ })
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const randTags = useCallback(() => {
|
|
|
|
|
+ const len = tagsBg.length;
|
|
|
|
|
+ return tagsBg[Math.floor(Math.random() * len)];
|
|
|
|
|
+ }, []);
|
|
|
|
|
+ const nav = useRouter();
|
|
|
|
|
+ useEffect(() => {
|
|
|
|
|
+ if (!loading && !detail) {
|
|
|
|
|
+ Toast.offline(error ? '加载征信信息失败' : "没有找到相关征信信息!");
|
|
|
|
|
+ // nav.dismiss();
|
|
|
|
|
+ }
|
|
|
|
|
+ if (detail?.id + "" == "-99") {
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+ }, [error, detail, loading]);
|
|
|
|
|
+ return (
|
|
|
|
|
+ <View className="flex-1 bg-surface">
|
|
|
|
|
+ <Stack.Screen options={{ title: "征信报告", headerRight: customer_id || detail?.customer_id ? () => <Link className="items-center" href={{ pathname: '/customer', params: { id: customer_id || detail?.customer_id } }}><Icon color={Colors.tint} size={17} name="exclamation-circle" /></Link> : undefined }} />
|
|
|
|
|
+ <ScrollView
|
|
|
|
|
+ className="flex-1"
|
|
|
|
|
+ contentContainerStyle={{
|
|
|
|
|
+ paddingTop: insets.top + 60,
|
|
|
|
|
+ paddingBottom: insets.bottom + 32,
|
|
|
|
|
+ paddingHorizontal: 20,
|
|
|
|
|
+ }}
|
|
|
|
|
+ showsVerticalScrollIndicator={false}
|
|
|
|
|
+ >
|
|
|
|
|
+
|
|
|
|
|
+ <Text className="mb-5 text-sm leading-6 text-on-surface-variant">
|
|
|
|
|
+ 客户:{detail?.name || name} · 最近更新 {detail?.updatetime ? dayjs(detail!.updatetime).toString() : '...'}
|
|
|
|
|
+ </Text>
|
|
|
|
|
+
|
|
|
|
|
+ {/* 评分卡片 */}
|
|
|
|
|
+ <View className="mb-3 rounded-3xl border border-outline-variant bg-surface-container-lowest px-5 py-6">
|
|
|
|
|
+ <View className="items-center">
|
|
|
|
|
+ <View className="h-28 w-28 items-center justify-center rounded-full border-[10px] border-primary-fixed bg-primary-fixed/30">
|
|
|
|
|
+ <Text className="text-4xl font-extrabold text-primary">{detail?.level??"??"}</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <Text className="mt-4 text-sm text-on-surface-variant">建议可申请额度</Text>
|
|
|
|
|
+ <Text className="mt-1 text-2xl font-extrabold text-on-surface">...</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <View className="mt-5 flex-row flex-wrap justify-center gap-2">
|
|
|
|
|
+ {(detail?.tags || ['...']).map((tag) => (
|
|
|
|
|
+ <StatusBadge key={tag} text={tag} variant={randTags() as any} />
|
|
|
|
|
+ ))}
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </View>
|
|
|
|
|
+
|
|
|
|
|
+ {/* 综合评估 */}
|
|
|
|
|
+ <View className="mb-3 rounded-3xl border border-outline-variant bg-surface-container-lowest px-5 py-5">
|
|
|
|
|
+ <View className="mb-3 flex-row items-center">
|
|
|
|
|
+ <Ionicons name="analytics-outline" size={18} color={Colors.tint} />
|
|
|
|
|
+ <Text className="ml-2 text-base font-bold text-on-surface">关键指标</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ {(detail?.recommend || ['...']).map((item, idx) => <Text key={idx} className="text-sm leading-6 text-on-surface-variant">
|
|
|
|
|
+ {item}
|
|
|
|
|
+ </Text>)}
|
|
|
|
|
+ </View>
|
|
|
|
|
+
|
|
|
|
|
+ <View className="mb-3 rounded-3xl border border-outline-variant bg-surface-container-lowest px-5 py-5">
|
|
|
|
|
+ <View className="mb-3 flex-row items-center">
|
|
|
|
|
+ <Ionicons name="analytics-outline" size={18} color={Colors.tint} />
|
|
|
|
|
+ <Text className="ml-2 text-base font-bold text-on-surface">关键指标</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ {(detail?.recommend || ['...']).map((item, idx) => <Text key={idx} className="text-sm leading-6 text-on-surface-variant">
|
|
|
|
|
+ {item}
|
|
|
|
|
+ </Text>)}
|
|
|
|
|
+ </View>
|
|
|
|
|
+
|
|
|
|
|
+ {/* 关键指标 */}
|
|
|
|
|
+ {/* <View className="mb-3 rounded-3xl border border-outline-variant bg-surface-container-lowest px-5 py-5">
|
|
|
|
|
+ <View className="mb-4 flex-row items-center">
|
|
|
|
|
+ <Ionicons name="stats-chart-outline" size={18} color={Colors.tint} />
|
|
|
|
|
+ <Text className="ml-2 text-base font-bold text-on-surface">关键指标</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <View className="flex-row flex-wrap -mx-1">
|
|
|
|
|
+ {METRICS.map((m) => {
|
|
|
|
|
+ const tone = toneStyles[m.tone ?? "default"];
|
|
|
|
|
+ return (
|
|
|
|
|
+ <View key={m.label} className="w-1/2 px-1 mb-2">
|
|
|
|
|
+ <View className={`rounded-2xl border px-3 py-3 ${tone.box}`}>
|
|
|
|
|
+ <Text className="text-xs text-on-surface-variant" numberOfLines={1}>
|
|
|
|
|
+ {m.label}
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ <View className="mt-1 flex-row items-baseline">
|
|
|
|
|
+ <Text className={`text-2xl font-extrabold ${tone.value}`}>{m.value}</Text>
|
|
|
|
|
+ {m.hint ? (
|
|
|
|
|
+ <Text className={`ml-1 text-sm font-semibold ${tone.value}`}>{m.hint}</Text>
|
|
|
|
|
+ ) : null}
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ );
|
|
|
|
|
+ })}
|
|
|
|
|
+ </View>
|
|
|
|
|
+
|
|
|
|
|
+ <View className="mt-2">
|
|
|
|
|
+ <View className="mb-1 flex-row items-center justify-between">
|
|
|
|
|
+ <Text className="text-sm text-on-surface-variant">负债率</Text>
|
|
|
|
|
+ <Text className="text-sm font-bold text-on-tertiary-fixed">68%</Text>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ <View className="h-2 overflow-hidden rounded-full bg-surface-container">
|
|
|
|
|
+ <View className="h-full rounded-full bg-tertiary" style={{ width: "68%" }} />
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ </View> */}
|
|
|
|
|
+
|
|
|
|
|
+ {/* 建议动作 */}
|
|
|
|
|
+
|
|
|
|
|
|
|
|
-}
|
|
|
|
|
|
|
+ <UIButton
|
|
|
|
|
+ type="primary"
|
|
|
|
|
+ icon="thunderbolt"
|
|
|
|
|
+ onPress={() => router.push("/credit/select")}
|
|
|
|
|
+ >
|
|
|
|
|
+ 智能匹配银行产品
|
|
|
|
|
+ </UIButton>
|
|
|
|
|
+ <View className="h-3" />
|
|
|
|
|
+ <UIButton type="second" icon="reload" onPress={() => router.back()}>
|
|
|
|
|
+ 重新上传征信
|
|
|
|
|
+ </UIButton>
|
|
|
|
|
+ </ScrollView>
|
|
|
|
|
+ </View>
|
|
|
|
|
+ );
|
|
|
|
|
+}
|