This commit is contained in:
2024-11-24 15:21:01 +08:00
commit 08b8825abd
160 changed files with 34913 additions and 0 deletions

4
src/App.vue Normal file
View File

@@ -0,0 +1,4 @@
<script setup>
onLaunch(() => {
})
</script>

40
src/androidPrivacy.json Normal file
View File

@@ -0,0 +1,40 @@
{
"prompt": "template",
"title": "用户协议和隐私政策",
"message": "感谢您使用全能查APP! 我们非常重视您的隐私保护和个人信息保护在您使用全能查APP前请您仔细阅读、充分理解<a href=\"/pages/userAgreement\">《用户协议》</a>和<a href=\"/pages/privacyPolicy\">《隐私政策》</a>的各项条款。如果您同意,请点击下方按钮开始接受我们的服务。",
"buttonAccept": "同意并继续",
"buttonRefuse": "退出应用",
"hrefLoader": "default",
"second": {
"title": "确认提示",
"message": "您点击同意并继续视为您已同意上诉协议的全部内容",
"buttonAccept": "同意并继续",
"buttonRefuse": "退出"
},
"styles": {
"backgroundColor": "#FFFFFF",
"borderRadius": "10px",
"title": {
"color": "#333333",
"fontSize": "18px",
"fontWeight": "bold"
},
"message": {
"color": "#666666",
"fontSize": "14px",
"lineHeight": "1.5"
},
"buttonAccept": {
"color": "#333333",
"backgroundColor": "#007AFF",
"borderRadius": "5px",
"padding": "10px 20px"
},
"buttonRefuse": {
"color": "#333333",
"backgroundColor": "#FF3B30",
"borderRadius": "5px",
"padding": "10px 20px"
}
}
}

114
src/api/apis.js Normal file
View File

@@ -0,0 +1,114 @@
// api/index.js
import request from '@/utils/request.js'
export function getUserInfo(data) {
return request({
url: '/user/detail',
method: 'GET',
data,
})
}
export function login(data) {
return request({
url: '/user/mobileCodeLogin',
method: 'POST',
data,
})
}
export function getCode(data) {
return request({
url: '/auth/sendSms',
method: 'POST',
data,
})
}
export function getProduct(en) {
return request({
url: `/product/en/${en}`,
method: 'GET',
})
}
export function queryExample(params) {
return request({
url: `/query/example`,
method: 'GET',
params,
})
}
export function queryMarriage(data) {
return request({
url: `/query/marriage`,
method: 'POST',
data,
})
}
export function queryhomeService(data) {
return request({
url: `/query/homeService`,
method: 'POST',
data,
})
}
export function queryriskAssessment(data) {
return request({
url: `/query/riskAssessment`,
method: 'POST',
data,
})
}
export function querycompanyInfo(data) {
return request({
url: `/query/companyInfo`,
method: 'POST',
data,
})
}
export function queryrentalInfo(data) {
return request({
url: `/query/rentalInfo`,
method: 'POST',
data,
})
}
export function querypreLoanBackgroundCheck(data) {
return request({
url: `/query/preLoanBackgroundCheck`,
method: 'POST',
data,
})
}
export function querybackgroundCheck(data) {
return request({
url: `/query/backgroundCheck`,
method: 'POST',
data,
})
}
export function queryResultByOrder(orderID) {
return request({
url: `/query/orderId/${orderID}`,
method: 'GET',
})
}
export function queryList(params) {
return request({
url: `/query/list`,
method: 'GET',
params,
})
}
export function queryProvisionalOrder(id) {
return request({
url: `/query/provisional_order/${id}`,
method: 'GET',
})
}
export function payment(data) {
return request({
url: `/pay/payment`,
method: 'POST',
data,
})
}

42
src/app.scss Normal file
View File

@@ -0,0 +1,42 @@
:root {
--dark-bg: #18181c;
}
html {
font-size: 4px; // * 方便unocss计算1单位 = 0.25rem = 1px
}
body {
font-size: 16px;
}
html,
body,
page,
#app {
height: 100%;
margin: 0;
padding: 0;
background: #f8f8f8
}
html.dark {
background: var(--dark-bg);
}
.card{
@apply border border-gray-200 rounded-xl bg-white p-6 shadow-md;
}
.card-p-0{
@apply border border-gray-200 rounded-xl bg-white shadow-md;
}
.title {
@apply mx-auto mt-2 w-68 border rounded-3xl bg-gradient-to-r from-blue-400 via-green-500 to-teal-500 py-2 text-center text-white font-bold;
}
.scrollbar-hidden {
scrollbar-width: none; /* Firefox */
}
.scrollbar-hidden::-webkit-scrollbar {
display: none; /* Chrome, Safari, and Edge */
}

634
src/auto-imports.d.ts vendored Normal file
View File

@@ -0,0 +1,634 @@
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// noinspection JSUnusedGlobalSymbols
// Generated by unplugin-auto-import
// biome-ignore lint: disable
export {}
declare global {
const EffectScope: typeof import('vue')['EffectScope']
const aesDecrypt: typeof import('./utils/crypto.js')['aesDecrypt']
const aesEncrypt: typeof import('./utils/crypto.js')['aesEncrypt']
const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
const autoResetRef: typeof import('@vueuse/core')['autoResetRef']
const computed: typeof import('vue')['computed']
const computedAsync: typeof import('@vueuse/core')['computedAsync']
const computedEager: typeof import('@vueuse/core')['computedEager']
const computedInject: typeof import('@vueuse/core')['computedInject']
const computedWithControl: typeof import('@vueuse/core')['computedWithControl']
const controlledComputed: typeof import('@vueuse/core')['controlledComputed']
const controlledRef: typeof import('@vueuse/core')['controlledRef']
const createApp: typeof import('vue')['createApp']
const createEventHook: typeof import('@vueuse/core')['createEventHook']
const createGlobalState: typeof import('@vueuse/core')['createGlobalState']
const createInjectionState: typeof import('@vueuse/core')['createInjectionState']
const createReactiveFn: typeof import('@vueuse/core')['createReactiveFn']
const createReusableTemplate: typeof import('@vueuse/core')['createReusableTemplate']
const createSharedComposable: typeof import('@vueuse/core')['createSharedComposable']
const createTemplatePromise: typeof import('@vueuse/core')['createTemplatePromise']
const createUnrefFn: typeof import('@vueuse/core')['createUnrefFn']
const customRef: typeof import('vue')['customRef']
const debouncedRef: typeof import('@vueuse/core')['debouncedRef']
const debouncedWatch: typeof import('@vueuse/core')['debouncedWatch']
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
const defineComponent: typeof import('vue')['defineComponent']
const eagerComputed: typeof import('@vueuse/core')['eagerComputed']
const effectScope: typeof import('vue')['effectScope']
const extendRef: typeof import('@vueuse/core')['extendRef']
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
const getCurrentScope: typeof import('vue')['getCurrentScope']
const h: typeof import('vue')['h']
const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
const inject: typeof import('vue')['inject']
const injectLocal: typeof import('@vueuse/core')['injectLocal']
const isDefined: typeof import('@vueuse/core')['isDefined']
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 makeDestructurable: typeof import('@vueuse/core')['makeDestructurable']
const markRaw: typeof import('vue')['markRaw']
const nextTick: typeof import('vue')['nextTick']
const onActivated: typeof import('vue')['onActivated']
const onAddToFavorites: typeof import('@dcloudio/uni-app')['onAddToFavorites']
const onBackPress: typeof import('@dcloudio/uni-app')['onBackPress']
const onBeforeMount: typeof import('vue')['onBeforeMount']
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
const onClickOutside: typeof import('@vueuse/core')['onClickOutside']
const onDeactivated: typeof import('vue')['onDeactivated']
const onError: typeof import('@dcloudio/uni-app')['onError']
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
const onHide: typeof import('@dcloudio/uni-app')['onHide']
const onKeyStroke: typeof import('@vueuse/core')['onKeyStroke']
const onLaunch: typeof import('@dcloudio/uni-app')['onLaunch']
const onLoad: typeof import('@dcloudio/uni-app')['onLoad']
const onLongPress: typeof import('@vueuse/core')['onLongPress']
const onMounted: typeof import('vue')['onMounted']
const onNavigationBarButtonTap: typeof import('@dcloudio/uni-app')['onNavigationBarButtonTap']
const onNavigationBarSearchInputChanged: typeof import('@dcloudio/uni-app')['onNavigationBarSearchInputChanged']
const onNavigationBarSearchInputClicked: typeof import('@dcloudio/uni-app')['onNavigationBarSearchInputClicked']
const onNavigationBarSearchInputConfirmed: typeof import('@dcloudio/uni-app')['onNavigationBarSearchInputConfirmed']
const onNavigationBarSearchInputFocusChanged: typeof import('@dcloudio/uni-app')['onNavigationBarSearchInputFocusChanged']
const onPageNotFound: typeof import('@dcloudio/uni-app')['onPageNotFound']
const onPageScroll: typeof import('@dcloudio/uni-app')['onPageScroll']
const onPullDownRefresh: typeof import('@dcloudio/uni-app')['onPullDownRefresh']
const onReachBottom: typeof import('@dcloudio/uni-app')['onReachBottom']
const onReady: typeof import('@dcloudio/uni-app')['onReady']
const onRenderTracked: typeof import('vue')['onRenderTracked']
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
const onResize: typeof import('@dcloudio/uni-app')['onResize']
const onScopeDispose: typeof import('vue')['onScopeDispose']
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
const onShareAppMessage: typeof import('@dcloudio/uni-app')['onShareAppMessage']
const onShareTimeline: typeof import('@dcloudio/uni-app')['onShareTimeline']
const onShow: typeof import('@dcloudio/uni-app')['onShow']
const onStartTyping: typeof import('@vueuse/core')['onStartTyping']
const onTabItemTap: typeof import('@dcloudio/uni-app')['onTabItemTap']
const onThemeChange: typeof import('@dcloudio/uni-app')['onThemeChange']
const onUnhandledRejection: typeof import('@dcloudio/uni-app')['onUnhandledRejection']
const onUnload: typeof import('@dcloudio/uni-app')['onUnload']
const onUnmounted: typeof import('vue')['onUnmounted']
const onUpdated: typeof import('vue')['onUpdated']
const onWatcherCleanup: typeof import('vue')['onWatcherCleanup']
const pausableWatch: typeof import('@vueuse/core')['pausableWatch']
const provide: typeof import('vue')['provide']
const provideLocal: typeof import('@vueuse/core')['provideLocal']
const reactify: typeof import('@vueuse/core')['reactify']
const reactifyObject: typeof import('@vueuse/core')['reactifyObject']
const reactive: typeof import('vue')['reactive']
const reactiveComputed: typeof import('@vueuse/core')['reactiveComputed']
const reactiveOmit: typeof import('@vueuse/core')['reactiveOmit']
const reactivePick: typeof import('@vueuse/core')['reactivePick']
const readonly: typeof import('vue')['readonly']
const ref: typeof import('vue')['ref']
const refAutoReset: typeof import('@vueuse/core')['refAutoReset']
const refDebounced: typeof import('@vueuse/core')['refDebounced']
const refDefault: typeof import('@vueuse/core')['refDefault']
const refThrottled: typeof import('@vueuse/core')['refThrottled']
const refWithControl: typeof import('@vueuse/core')['refWithControl']
const request: typeof import('./utils/request.js')['default']
const resolveComponent: typeof import('vue')['resolveComponent']
const resolveRef: typeof import('@vueuse/core')['resolveRef']
const resolveUnref: typeof import('@vueuse/core')['resolveUnref']
const shallowReactive: typeof import('vue')['shallowReactive']
const shallowReadonly: typeof import('vue')['shallowReadonly']
const shallowRef: typeof import('vue')['shallowRef']
const syncRef: typeof import('@vueuse/core')['syncRef']
const syncRefs: typeof import('@vueuse/core')['syncRefs']
const templateRef: typeof import('@vueuse/core')['templateRef']
const throttledRef: typeof import('@vueuse/core')['throttledRef']
const throttledWatch: typeof import('@vueuse/core')['throttledWatch']
const toRaw: typeof import('vue')['toRaw']
const toReactive: typeof import('@vueuse/core')['toReactive']
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 tryOnBeforeMount: typeof import('@vueuse/core')['tryOnBeforeMount']
const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount']
const tryOnMounted: typeof import('@vueuse/core')['tryOnMounted']
const tryOnScopeDispose: typeof import('@vueuse/core')['tryOnScopeDispose']
const tryOnUnmounted: typeof import('@vueuse/core')['tryOnUnmounted']
const unref: typeof import('vue')['unref']
const unrefElement: typeof import('@vueuse/core')['unrefElement']
const until: typeof import('@vueuse/core')['until']
const useActiveElement: typeof import('@vueuse/core')['useActiveElement']
const useAnimate: typeof import('@vueuse/core')['useAnimate']
const useArrayDifference: typeof import('@vueuse/core')['useArrayDifference']
const useArrayEvery: typeof import('@vueuse/core')['useArrayEvery']
const useArrayFilter: typeof import('@vueuse/core')['useArrayFilter']
const useArrayFind: typeof import('@vueuse/core')['useArrayFind']
const useArrayFindIndex: typeof import('@vueuse/core')['useArrayFindIndex']
const useArrayFindLast: typeof import('@vueuse/core')['useArrayFindLast']
const useArrayIncludes: typeof import('@vueuse/core')['useArrayIncludes']
const useArrayJoin: typeof import('@vueuse/core')['useArrayJoin']
const useArrayMap: typeof import('@vueuse/core')['useArrayMap']
const useArrayReduce: typeof import('@vueuse/core')['useArrayReduce']
const useArraySome: typeof import('@vueuse/core')['useArraySome']
const useArrayUnique: typeof import('@vueuse/core')['useArrayUnique']
const useAsyncQueue: typeof import('@vueuse/core')['useAsyncQueue']
const useAsyncState: typeof import('@vueuse/core')['useAsyncState']
const useAttrs: typeof import('vue')['useAttrs']
const useBase64: typeof import('@vueuse/core')['useBase64']
const useBattery: typeof import('@vueuse/core')['useBattery']
const useBluetooth: typeof import('@vueuse/core')['useBluetooth']
const useBreakpoints: typeof import('@vueuse/core')['useBreakpoints']
const useBroadcastChannel: typeof import('@vueuse/core')['useBroadcastChannel']
const useBrowserLocation: typeof import('@vueuse/core')['useBrowserLocation']
const useCached: typeof import('@vueuse/core')['useCached']
const useClipboard: typeof import('@vueuse/core')['useClipboard']
const useClipboardItems: typeof import('@vueuse/core')['useClipboardItems']
const useCloned: typeof import('@vueuse/core')['useCloned']
const useColorMode: typeof import('@vueuse/core')['useColorMode']
const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog']
const useCount: typeof import('./composables/useCount')['useCount']
const useCounter: typeof import('@vueuse/core')['useCounter']
const useCssModule: typeof import('vue')['useCssModule']
const useCssVar: typeof import('@vueuse/core')['useCssVar']
const useCssVars: typeof import('vue')['useCssVars']
const useCurrentElement: typeof import('@vueuse/core')['useCurrentElement']
const useCycleList: typeof import('@vueuse/core')['useCycleList']
const useDark: typeof import('@vueuse/core')['useDark']
const useDateFormat: typeof import('@vueuse/core')['useDateFormat']
const useDebounce: typeof import('@vueuse/core')['useDebounce']
const useDebounceFn: typeof import('@vueuse/core')['useDebounceFn']
const useDebouncedRefHistory: typeof import('@vueuse/core')['useDebouncedRefHistory']
const useDeviceMotion: typeof import('@vueuse/core')['useDeviceMotion']
const useDeviceOrientation: typeof import('@vueuse/core')['useDeviceOrientation']
const useDevicePixelRatio: typeof import('@vueuse/core')['useDevicePixelRatio']
const useDevicesList: typeof import('@vueuse/core')['useDevicesList']
const useDisplayMedia: typeof import('@vueuse/core')['useDisplayMedia']
const useDocumentVisibility: typeof import('@vueuse/core')['useDocumentVisibility']
const useDraggable: typeof import('@vueuse/core')['useDraggable']
const useDropZone: typeof import('@vueuse/core')['useDropZone']
const useElementBounding: typeof import('@vueuse/core')['useElementBounding']
const useElementByPoint: typeof import('@vueuse/core')['useElementByPoint']
const useElementHover: typeof import('@vueuse/core')['useElementHover']
const useElementSize: typeof import('@vueuse/core')['useElementSize']
const useElementVisibility: typeof import('@vueuse/core')['useElementVisibility']
const useEventBus: typeof import('@vueuse/core')['useEventBus']
const useEventListener: typeof import('@vueuse/core')['useEventListener']
const useEventSource: typeof import('@vueuse/core')['useEventSource']
const useEyeDropper: typeof import('@vueuse/core')['useEyeDropper']
const useFavicon: typeof import('@vueuse/core')['useFavicon']
const useFetch: typeof import('@vueuse/core')['useFetch']
const useFileDialog: typeof import('@vueuse/core')['useFileDialog']
const useFileSystemAccess: typeof import('@vueuse/core')['useFileSystemAccess']
const useFocus: typeof import('@vueuse/core')['useFocus']
const useFocusWithin: typeof import('@vueuse/core')['useFocusWithin']
const useFps: typeof import('@vueuse/core')['useFps']
const useFullscreen: typeof import('@vueuse/core')['useFullscreen']
const useGamepad: typeof import('@vueuse/core')['useGamepad']
const useGeolocation: typeof import('@vueuse/core')['useGeolocation']
const useId: typeof import('vue')['useId']
const useIdle: typeof import('@vueuse/core')['useIdle']
const useImage: typeof import('@vueuse/core')['useImage']
const useInfiniteScroll: typeof import('@vueuse/core')['useInfiniteScroll']
const useIntersectionObserver: typeof import('@vueuse/core')['useIntersectionObserver']
const useInterval: typeof import('@vueuse/core')['useInterval']
const useIntervalFn: typeof import('@vueuse/core')['useIntervalFn']
const useKeyModifier: typeof import('@vueuse/core')['useKeyModifier']
const useLastChanged: typeof import('@vueuse/core')['useLastChanged']
const useLocalStorage: typeof import('@vueuse/core')['useLocalStorage']
const useMagicKeys: typeof import('@vueuse/core')['useMagicKeys']
const useManualRefHistory: typeof import('@vueuse/core')['useManualRefHistory']
const useMediaControls: typeof import('@vueuse/core')['useMediaControls']
const useMediaQuery: typeof import('@vueuse/core')['useMediaQuery']
const useMemoize: typeof import('@vueuse/core')['useMemoize']
const useMemory: typeof import('@vueuse/core')['useMemory']
const useModel: typeof import('vue')['useModel']
const useMounted: typeof import('@vueuse/core')['useMounted']
const useMouse: typeof import('@vueuse/core')['useMouse']
const useMouseInElement: typeof import('@vueuse/core')['useMouseInElement']
const useMousePressed: typeof import('@vueuse/core')['useMousePressed']
const useMutationObserver: typeof import('@vueuse/core')['useMutationObserver']
const useNavigatorLanguage: typeof import('@vueuse/core')['useNavigatorLanguage']
const useNetwork: typeof import('@vueuse/core')['useNetwork']
const useNow: typeof import('@vueuse/core')['useNow']
const useObjectUrl: typeof import('@vueuse/core')['useObjectUrl']
const useOffsetPagination: typeof import('@vueuse/core')['useOffsetPagination']
const useOnline: typeof import('@vueuse/core')['useOnline']
const usePageLeave: typeof import('@vueuse/core')['usePageLeave']
const useParallax: typeof import('@vueuse/core')['useParallax']
const useParentElement: typeof import('@vueuse/core')['useParentElement']
const usePerformanceObserver: typeof import('@vueuse/core')['usePerformanceObserver']
const usePermission: typeof import('@vueuse/core')['usePermission']
const usePointer: typeof import('@vueuse/core')['usePointer']
const usePointerLock: typeof import('@vueuse/core')['usePointerLock']
const usePointerSwipe: typeof import('@vueuse/core')['usePointerSwipe']
const usePreferredColorScheme: typeof import('@vueuse/core')['usePreferredColorScheme']
const usePreferredContrast: typeof import('@vueuse/core')['usePreferredContrast']
const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark']
const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages']
const usePreferredReducedMotion: typeof import('@vueuse/core')['usePreferredReducedMotion']
const usePrevious: typeof import('@vueuse/core')['usePrevious']
const useQuery: typeof import('./composables/useQuery')['useQuery']
const useRafFn: typeof import('@vueuse/core')['useRafFn']
const useRefHistory: typeof import('@vueuse/core')['useRefHistory']
const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver']
const useScreenOrientation: typeof import('@vueuse/core')['useScreenOrientation']
const useScreenSafeArea: typeof import('@vueuse/core')['useScreenSafeArea']
const useScriptTag: typeof import('@vueuse/core')['useScriptTag']
const useScroll: typeof import('@vueuse/core')['useScroll']
const useScrollLock: typeof import('@vueuse/core')['useScrollLock']
const useSessionStorage: typeof import('@vueuse/core')['useSessionStorage']
const useShare: typeof import('@vueuse/core')['useShare']
const useSlots: typeof import('vue')['useSlots']
const useSorted: typeof import('@vueuse/core')['useSorted']
const useSpeechRecognition: typeof import('@vueuse/core')['useSpeechRecognition']
const useSpeechSynthesis: typeof import('@vueuse/core')['useSpeechSynthesis']
const useStepper: typeof import('@vueuse/core')['useStepper']
const useStorage: typeof import('@vueuse/core')['useStorage']
const useStorageAsync: typeof import('@vueuse/core')['useStorageAsync']
const useStyleTag: typeof import('@vueuse/core')['useStyleTag']
const useSupported: typeof import('@vueuse/core')['useSupported']
const useSwipe: typeof import('@vueuse/core')['useSwipe']
const useTemplateRef: typeof import('vue')['useTemplateRef']
const useTemplateRefsList: typeof import('@vueuse/core')['useTemplateRefsList']
const useTextDirection: typeof import('@vueuse/core')['useTextDirection']
const useTextSelection: typeof import('@vueuse/core')['useTextSelection']
const useTextareaAutosize: typeof import('@vueuse/core')['useTextareaAutosize']
const useThrottle: typeof import('@vueuse/core')['useThrottle']
const useThrottleFn: typeof import('@vueuse/core')['useThrottleFn']
const useThrottledRefHistory: typeof import('@vueuse/core')['useThrottledRefHistory']
const useTimeAgo: typeof import('@vueuse/core')['useTimeAgo']
const useTimeout: typeof import('@vueuse/core')['useTimeout']
const useTimeoutFn: typeof import('@vueuse/core')['useTimeoutFn']
const useTimeoutPoll: typeof import('@vueuse/core')['useTimeoutPoll']
const useTimestamp: typeof import('@vueuse/core')['useTimestamp']
const useTitle: typeof import('@vueuse/core')['useTitle']
const useToNumber: typeof import('@vueuse/core')['useToNumber']
const useToString: typeof import('@vueuse/core')['useToString']
const useToggle: typeof import('@vueuse/core')['useToggle']
const useTransition: typeof import('@vueuse/core')['useTransition']
const useUrlSearchParams: typeof import('@vueuse/core')['useUrlSearchParams']
const useUserMedia: typeof import('@vueuse/core')['useUserMedia']
const useVModel: typeof import('@vueuse/core')['useVModel']
const useVModels: typeof import('@vueuse/core')['useVModels']
const useVibrate: typeof import('@vueuse/core')['useVibrate']
const useVirtualList: typeof import('@vueuse/core')['useVirtualList']
const useWakeLock: typeof import('@vueuse/core')['useWakeLock']
const useWebNotification: typeof import('@vueuse/core')['useWebNotification']
const useWebSocket: typeof import('@vueuse/core')['useWebSocket']
const useWebWorker: typeof import('@vueuse/core')['useWebWorker']
const useWebWorkerFn: typeof import('@vueuse/core')['useWebWorkerFn']
const useWindowFocus: typeof import('@vueuse/core')['useWindowFocus']
const useWindowScroll: typeof import('@vueuse/core')['useWindowScroll']
const useWindowSize: typeof import('@vueuse/core')['useWindowSize']
const watch: typeof import('vue')['watch']
const watchArray: typeof import('@vueuse/core')['watchArray']
const watchAtMost: typeof import('@vueuse/core')['watchAtMost']
const watchDebounced: typeof import('@vueuse/core')['watchDebounced']
const watchDeep: typeof import('@vueuse/core')['watchDeep']
const watchEffect: typeof import('vue')['watchEffect']
const watchIgnorable: typeof import('@vueuse/core')['watchIgnorable']
const watchImmediate: typeof import('@vueuse/core')['watchImmediate']
const watchOnce: typeof import('@vueuse/core')['watchOnce']
const watchPausable: typeof import('@vueuse/core')['watchPausable']
const watchPostEffect: typeof import('vue')['watchPostEffect']
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
const watchThrottled: typeof import('@vueuse/core')['watchThrottled']
const watchTriggerable: typeof import('@vueuse/core')['watchTriggerable']
const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter']
const whenever: typeof import('@vueuse/core')['whenever']
}
// 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')
}
// for vue template auto import
import { UnwrapRef } from 'vue'
declare module 'vue' {
interface GlobalComponents {}
interface ComponentCustomProperties {
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
readonly aesDecrypt: UnwrapRef<typeof import('./utils/crypto.js')['aesDecrypt']>
readonly aesEncrypt: UnwrapRef<typeof import('./utils/crypto.js')['aesEncrypt']>
readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']>
readonly autoResetRef: UnwrapRef<typeof import('@vueuse/core')['autoResetRef']>
readonly computed: UnwrapRef<typeof import('vue')['computed']>
readonly computedAsync: UnwrapRef<typeof import('@vueuse/core')['computedAsync']>
readonly computedEager: UnwrapRef<typeof import('@vueuse/core')['computedEager']>
readonly computedInject: UnwrapRef<typeof import('@vueuse/core')['computedInject']>
readonly computedWithControl: UnwrapRef<typeof import('@vueuse/core')['computedWithControl']>
readonly controlledComputed: UnwrapRef<typeof import('@vueuse/core')['controlledComputed']>
readonly controlledRef: UnwrapRef<typeof import('@vueuse/core')['controlledRef']>
readonly createApp: UnwrapRef<typeof import('vue')['createApp']>
readonly createEventHook: UnwrapRef<typeof import('@vueuse/core')['createEventHook']>
readonly createGlobalState: UnwrapRef<typeof import('@vueuse/core')['createGlobalState']>
readonly createInjectionState: UnwrapRef<typeof import('@vueuse/core')['createInjectionState']>
readonly createReactiveFn: UnwrapRef<typeof import('@vueuse/core')['createReactiveFn']>
readonly createReusableTemplate: UnwrapRef<typeof import('@vueuse/core')['createReusableTemplate']>
readonly createSharedComposable: UnwrapRef<typeof import('@vueuse/core')['createSharedComposable']>
readonly createTemplatePromise: UnwrapRef<typeof import('@vueuse/core')['createTemplatePromise']>
readonly createUnrefFn: UnwrapRef<typeof import('@vueuse/core')['createUnrefFn']>
readonly customRef: UnwrapRef<typeof import('vue')['customRef']>
readonly debouncedRef: UnwrapRef<typeof import('@vueuse/core')['debouncedRef']>
readonly debouncedWatch: UnwrapRef<typeof import('@vueuse/core')['debouncedWatch']>
readonly defineAsyncComponent: UnwrapRef<typeof import('vue')['defineAsyncComponent']>
readonly defineComponent: UnwrapRef<typeof import('vue')['defineComponent']>
readonly eagerComputed: UnwrapRef<typeof import('@vueuse/core')['eagerComputed']>
readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']>
readonly extendRef: UnwrapRef<typeof import('@vueuse/core')['extendRef']>
readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
readonly h: UnwrapRef<typeof import('vue')['h']>
readonly ignorableWatch: UnwrapRef<typeof import('@vueuse/core')['ignorableWatch']>
readonly inject: UnwrapRef<typeof import('vue')['inject']>
readonly injectLocal: UnwrapRef<typeof import('@vueuse/core')['injectLocal']>
readonly isDefined: UnwrapRef<typeof import('@vueuse/core')['isDefined']>
readonly isProxy: UnwrapRef<typeof import('vue')['isProxy']>
readonly isReactive: UnwrapRef<typeof import('vue')['isReactive']>
readonly isReadonly: UnwrapRef<typeof import('vue')['isReadonly']>
readonly isRef: UnwrapRef<typeof import('vue')['isRef']>
readonly makeDestructurable: UnwrapRef<typeof import('@vueuse/core')['makeDestructurable']>
readonly markRaw: UnwrapRef<typeof import('vue')['markRaw']>
readonly nextTick: UnwrapRef<typeof import('vue')['nextTick']>
readonly onActivated: UnwrapRef<typeof import('vue')['onActivated']>
readonly onAddToFavorites: UnwrapRef<typeof import('@dcloudio/uni-app')['onAddToFavorites']>
readonly onBackPress: UnwrapRef<typeof import('@dcloudio/uni-app')['onBackPress']>
readonly onBeforeMount: UnwrapRef<typeof import('vue')['onBeforeMount']>
readonly onBeforeUnmount: UnwrapRef<typeof import('vue')['onBeforeUnmount']>
readonly onBeforeUpdate: UnwrapRef<typeof import('vue')['onBeforeUpdate']>
readonly onClickOutside: UnwrapRef<typeof import('@vueuse/core')['onClickOutside']>
readonly onDeactivated: UnwrapRef<typeof import('vue')['onDeactivated']>
readonly onError: UnwrapRef<typeof import('@dcloudio/uni-app')['onError']>
readonly onErrorCaptured: UnwrapRef<typeof import('vue')['onErrorCaptured']>
readonly onHide: UnwrapRef<typeof import('@dcloudio/uni-app')['onHide']>
readonly onKeyStroke: UnwrapRef<typeof import('@vueuse/core')['onKeyStroke']>
readonly onLaunch: UnwrapRef<typeof import('@dcloudio/uni-app')['onLaunch']>
readonly onLoad: UnwrapRef<typeof import('@dcloudio/uni-app')['onLoad']>
readonly onLongPress: UnwrapRef<typeof import('@vueuse/core')['onLongPress']>
readonly onMounted: UnwrapRef<typeof import('vue')['onMounted']>
readonly onNavigationBarButtonTap: UnwrapRef<typeof import('@dcloudio/uni-app')['onNavigationBarButtonTap']>
readonly onNavigationBarSearchInputChanged: UnwrapRef<typeof import('@dcloudio/uni-app')['onNavigationBarSearchInputChanged']>
readonly onNavigationBarSearchInputClicked: UnwrapRef<typeof import('@dcloudio/uni-app')['onNavigationBarSearchInputClicked']>
readonly onNavigationBarSearchInputConfirmed: UnwrapRef<typeof import('@dcloudio/uni-app')['onNavigationBarSearchInputConfirmed']>
readonly onNavigationBarSearchInputFocusChanged: UnwrapRef<typeof import('@dcloudio/uni-app')['onNavigationBarSearchInputFocusChanged']>
readonly onPageNotFound: UnwrapRef<typeof import('@dcloudio/uni-app')['onPageNotFound']>
readonly onPageScroll: UnwrapRef<typeof import('@dcloudio/uni-app')['onPageScroll']>
readonly onPullDownRefresh: UnwrapRef<typeof import('@dcloudio/uni-app')['onPullDownRefresh']>
readonly onReachBottom: UnwrapRef<typeof import('@dcloudio/uni-app')['onReachBottom']>
readonly onReady: UnwrapRef<typeof import('@dcloudio/uni-app')['onReady']>
readonly onRenderTracked: UnwrapRef<typeof import('vue')['onRenderTracked']>
readonly onRenderTriggered: UnwrapRef<typeof import('vue')['onRenderTriggered']>
readonly onResize: UnwrapRef<typeof import('@dcloudio/uni-app')['onResize']>
readonly onScopeDispose: UnwrapRef<typeof import('vue')['onScopeDispose']>
readonly onServerPrefetch: UnwrapRef<typeof import('vue')['onServerPrefetch']>
readonly onShareAppMessage: UnwrapRef<typeof import('@dcloudio/uni-app')['onShareAppMessage']>
readonly onShareTimeline: UnwrapRef<typeof import('@dcloudio/uni-app')['onShareTimeline']>
readonly onShow: UnwrapRef<typeof import('@dcloudio/uni-app')['onShow']>
readonly onStartTyping: UnwrapRef<typeof import('@vueuse/core')['onStartTyping']>
readonly onTabItemTap: UnwrapRef<typeof import('@dcloudio/uni-app')['onTabItemTap']>
readonly onThemeChange: UnwrapRef<typeof import('@dcloudio/uni-app')['onThemeChange']>
readonly onUnhandledRejection: UnwrapRef<typeof import('@dcloudio/uni-app')['onUnhandledRejection']>
readonly onUnload: UnwrapRef<typeof import('@dcloudio/uni-app')['onUnload']>
readonly onUnmounted: UnwrapRef<typeof import('vue')['onUnmounted']>
readonly onUpdated: UnwrapRef<typeof import('vue')['onUpdated']>
readonly onWatcherCleanup: UnwrapRef<typeof import('vue')['onWatcherCleanup']>
readonly pausableWatch: UnwrapRef<typeof import('@vueuse/core')['pausableWatch']>
readonly provide: UnwrapRef<typeof import('vue')['provide']>
readonly provideLocal: UnwrapRef<typeof import('@vueuse/core')['provideLocal']>
readonly reactify: UnwrapRef<typeof import('@vueuse/core')['reactify']>
readonly reactifyObject: UnwrapRef<typeof import('@vueuse/core')['reactifyObject']>
readonly reactive: UnwrapRef<typeof import('vue')['reactive']>
readonly reactiveComputed: UnwrapRef<typeof import('@vueuse/core')['reactiveComputed']>
readonly reactiveOmit: UnwrapRef<typeof import('@vueuse/core')['reactiveOmit']>
readonly reactivePick: UnwrapRef<typeof import('@vueuse/core')['reactivePick']>
readonly readonly: UnwrapRef<typeof import('vue')['readonly']>
readonly ref: UnwrapRef<typeof import('vue')['ref']>
readonly refAutoReset: UnwrapRef<typeof import('@vueuse/core')['refAutoReset']>
readonly refDebounced: UnwrapRef<typeof import('@vueuse/core')['refDebounced']>
readonly refDefault: UnwrapRef<typeof import('@vueuse/core')['refDefault']>
readonly refThrottled: UnwrapRef<typeof import('@vueuse/core')['refThrottled']>
readonly refWithControl: UnwrapRef<typeof import('@vueuse/core')['refWithControl']>
readonly request: UnwrapRef<typeof import('./utils/request.js')['default']>
readonly resolveComponent: UnwrapRef<typeof import('vue')['resolveComponent']>
readonly resolveRef: UnwrapRef<typeof import('@vueuse/core')['resolveRef']>
readonly resolveUnref: UnwrapRef<typeof import('@vueuse/core')['resolveUnref']>
readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']>
readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']>
readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']>
readonly syncRef: UnwrapRef<typeof import('@vueuse/core')['syncRef']>
readonly syncRefs: UnwrapRef<typeof import('@vueuse/core')['syncRefs']>
readonly templateRef: UnwrapRef<typeof import('@vueuse/core')['templateRef']>
readonly throttledRef: UnwrapRef<typeof import('@vueuse/core')['throttledRef']>
readonly throttledWatch: UnwrapRef<typeof import('@vueuse/core')['throttledWatch']>
readonly toRaw: UnwrapRef<typeof import('vue')['toRaw']>
readonly toReactive: UnwrapRef<typeof import('@vueuse/core')['toReactive']>
readonly toRef: UnwrapRef<typeof import('vue')['toRef']>
readonly toRefs: UnwrapRef<typeof import('vue')['toRefs']>
readonly toValue: UnwrapRef<typeof import('vue')['toValue']>
readonly triggerRef: UnwrapRef<typeof import('vue')['triggerRef']>
readonly tryOnBeforeMount: UnwrapRef<typeof import('@vueuse/core')['tryOnBeforeMount']>
readonly tryOnBeforeUnmount: UnwrapRef<typeof import('@vueuse/core')['tryOnBeforeUnmount']>
readonly tryOnMounted: UnwrapRef<typeof import('@vueuse/core')['tryOnMounted']>
readonly tryOnScopeDispose: UnwrapRef<typeof import('@vueuse/core')['tryOnScopeDispose']>
readonly tryOnUnmounted: UnwrapRef<typeof import('@vueuse/core')['tryOnUnmounted']>
readonly unref: UnwrapRef<typeof import('vue')['unref']>
readonly unrefElement: UnwrapRef<typeof import('@vueuse/core')['unrefElement']>
readonly until: UnwrapRef<typeof import('@vueuse/core')['until']>
readonly useActiveElement: UnwrapRef<typeof import('@vueuse/core')['useActiveElement']>
readonly useAnimate: UnwrapRef<typeof import('@vueuse/core')['useAnimate']>
readonly useArrayDifference: UnwrapRef<typeof import('@vueuse/core')['useArrayDifference']>
readonly useArrayEvery: UnwrapRef<typeof import('@vueuse/core')['useArrayEvery']>
readonly useArrayFilter: UnwrapRef<typeof import('@vueuse/core')['useArrayFilter']>
readonly useArrayFind: UnwrapRef<typeof import('@vueuse/core')['useArrayFind']>
readonly useArrayFindIndex: UnwrapRef<typeof import('@vueuse/core')['useArrayFindIndex']>
readonly useArrayFindLast: UnwrapRef<typeof import('@vueuse/core')['useArrayFindLast']>
readonly useArrayIncludes: UnwrapRef<typeof import('@vueuse/core')['useArrayIncludes']>
readonly useArrayJoin: UnwrapRef<typeof import('@vueuse/core')['useArrayJoin']>
readonly useArrayMap: UnwrapRef<typeof import('@vueuse/core')['useArrayMap']>
readonly useArrayReduce: UnwrapRef<typeof import('@vueuse/core')['useArrayReduce']>
readonly useArraySome: UnwrapRef<typeof import('@vueuse/core')['useArraySome']>
readonly useArrayUnique: UnwrapRef<typeof import('@vueuse/core')['useArrayUnique']>
readonly useAsyncQueue: UnwrapRef<typeof import('@vueuse/core')['useAsyncQueue']>
readonly useAsyncState: UnwrapRef<typeof import('@vueuse/core')['useAsyncState']>
readonly useAttrs: UnwrapRef<typeof import('vue')['useAttrs']>
readonly useBase64: UnwrapRef<typeof import('@vueuse/core')['useBase64']>
readonly useBattery: UnwrapRef<typeof import('@vueuse/core')['useBattery']>
readonly useBluetooth: UnwrapRef<typeof import('@vueuse/core')['useBluetooth']>
readonly useBreakpoints: UnwrapRef<typeof import('@vueuse/core')['useBreakpoints']>
readonly useBroadcastChannel: UnwrapRef<typeof import('@vueuse/core')['useBroadcastChannel']>
readonly useBrowserLocation: UnwrapRef<typeof import('@vueuse/core')['useBrowserLocation']>
readonly useCached: UnwrapRef<typeof import('@vueuse/core')['useCached']>
readonly useClipboard: UnwrapRef<typeof import('@vueuse/core')['useClipboard']>
readonly useClipboardItems: UnwrapRef<typeof import('@vueuse/core')['useClipboardItems']>
readonly useCloned: UnwrapRef<typeof import('@vueuse/core')['useCloned']>
readonly useColorMode: UnwrapRef<typeof import('@vueuse/core')['useColorMode']>
readonly useConfirmDialog: UnwrapRef<typeof import('@vueuse/core')['useConfirmDialog']>
readonly useCount: UnwrapRef<typeof import('./composables/useCount')['useCount']>
readonly useCounter: UnwrapRef<typeof import('@vueuse/core')['useCounter']>
readonly useCssModule: UnwrapRef<typeof import('vue')['useCssModule']>
readonly useCssVar: UnwrapRef<typeof import('@vueuse/core')['useCssVar']>
readonly useCssVars: UnwrapRef<typeof import('vue')['useCssVars']>
readonly useCurrentElement: UnwrapRef<typeof import('@vueuse/core')['useCurrentElement']>
readonly useCycleList: UnwrapRef<typeof import('@vueuse/core')['useCycleList']>
readonly useDark: UnwrapRef<typeof import('@vueuse/core')['useDark']>
readonly useDateFormat: UnwrapRef<typeof import('@vueuse/core')['useDateFormat']>
readonly useDebounce: UnwrapRef<typeof import('@vueuse/core')['useDebounce']>
readonly useDebounceFn: UnwrapRef<typeof import('@vueuse/core')['useDebounceFn']>
readonly useDebouncedRefHistory: UnwrapRef<typeof import('@vueuse/core')['useDebouncedRefHistory']>
readonly useDeviceMotion: UnwrapRef<typeof import('@vueuse/core')['useDeviceMotion']>
readonly useDeviceOrientation: UnwrapRef<typeof import('@vueuse/core')['useDeviceOrientation']>
readonly useDevicePixelRatio: UnwrapRef<typeof import('@vueuse/core')['useDevicePixelRatio']>
readonly useDevicesList: UnwrapRef<typeof import('@vueuse/core')['useDevicesList']>
readonly useDisplayMedia: UnwrapRef<typeof import('@vueuse/core')['useDisplayMedia']>
readonly useDocumentVisibility: UnwrapRef<typeof import('@vueuse/core')['useDocumentVisibility']>
readonly useDraggable: UnwrapRef<typeof import('@vueuse/core')['useDraggable']>
readonly useDropZone: UnwrapRef<typeof import('@vueuse/core')['useDropZone']>
readonly useElementBounding: UnwrapRef<typeof import('@vueuse/core')['useElementBounding']>
readonly useElementByPoint: UnwrapRef<typeof import('@vueuse/core')['useElementByPoint']>
readonly useElementHover: UnwrapRef<typeof import('@vueuse/core')['useElementHover']>
readonly useElementSize: UnwrapRef<typeof import('@vueuse/core')['useElementSize']>
readonly useElementVisibility: UnwrapRef<typeof import('@vueuse/core')['useElementVisibility']>
readonly useEventBus: UnwrapRef<typeof import('@vueuse/core')['useEventBus']>
readonly useEventListener: UnwrapRef<typeof import('@vueuse/core')['useEventListener']>
readonly useEventSource: UnwrapRef<typeof import('@vueuse/core')['useEventSource']>
readonly useEyeDropper: UnwrapRef<typeof import('@vueuse/core')['useEyeDropper']>
readonly useFavicon: UnwrapRef<typeof import('@vueuse/core')['useFavicon']>
readonly useFetch: UnwrapRef<typeof import('@vueuse/core')['useFetch']>
readonly useFileDialog: UnwrapRef<typeof import('@vueuse/core')['useFileDialog']>
readonly useFileSystemAccess: UnwrapRef<typeof import('@vueuse/core')['useFileSystemAccess']>
readonly useFocus: UnwrapRef<typeof import('@vueuse/core')['useFocus']>
readonly useFocusWithin: UnwrapRef<typeof import('@vueuse/core')['useFocusWithin']>
readonly useFps: UnwrapRef<typeof import('@vueuse/core')['useFps']>
readonly useFullscreen: UnwrapRef<typeof import('@vueuse/core')['useFullscreen']>
readonly useGamepad: UnwrapRef<typeof import('@vueuse/core')['useGamepad']>
readonly useGeolocation: UnwrapRef<typeof import('@vueuse/core')['useGeolocation']>
readonly useId: UnwrapRef<typeof import('vue')['useId']>
readonly useIdle: UnwrapRef<typeof import('@vueuse/core')['useIdle']>
readonly useImage: UnwrapRef<typeof import('@vueuse/core')['useImage']>
readonly useInfiniteScroll: UnwrapRef<typeof import('@vueuse/core')['useInfiniteScroll']>
readonly useIntersectionObserver: UnwrapRef<typeof import('@vueuse/core')['useIntersectionObserver']>
readonly useInterval: UnwrapRef<typeof import('@vueuse/core')['useInterval']>
readonly useIntervalFn: UnwrapRef<typeof import('@vueuse/core')['useIntervalFn']>
readonly useKeyModifier: UnwrapRef<typeof import('@vueuse/core')['useKeyModifier']>
readonly useLastChanged: UnwrapRef<typeof import('@vueuse/core')['useLastChanged']>
readonly useLocalStorage: UnwrapRef<typeof import('@vueuse/core')['useLocalStorage']>
readonly useMagicKeys: UnwrapRef<typeof import('@vueuse/core')['useMagicKeys']>
readonly useManualRefHistory: UnwrapRef<typeof import('@vueuse/core')['useManualRefHistory']>
readonly useMediaControls: UnwrapRef<typeof import('@vueuse/core')['useMediaControls']>
readonly useMediaQuery: UnwrapRef<typeof import('@vueuse/core')['useMediaQuery']>
readonly useMemoize: UnwrapRef<typeof import('@vueuse/core')['useMemoize']>
readonly useMemory: UnwrapRef<typeof import('@vueuse/core')['useMemory']>
readonly useModel: UnwrapRef<typeof import('vue')['useModel']>
readonly useMounted: UnwrapRef<typeof import('@vueuse/core')['useMounted']>
readonly useMouse: UnwrapRef<typeof import('@vueuse/core')['useMouse']>
readonly useMouseInElement: UnwrapRef<typeof import('@vueuse/core')['useMouseInElement']>
readonly useMousePressed: UnwrapRef<typeof import('@vueuse/core')['useMousePressed']>
readonly useMutationObserver: UnwrapRef<typeof import('@vueuse/core')['useMutationObserver']>
readonly useNavigatorLanguage: UnwrapRef<typeof import('@vueuse/core')['useNavigatorLanguage']>
readonly useNetwork: UnwrapRef<typeof import('@vueuse/core')['useNetwork']>
readonly useNow: UnwrapRef<typeof import('@vueuse/core')['useNow']>
readonly useObjectUrl: UnwrapRef<typeof import('@vueuse/core')['useObjectUrl']>
readonly useOffsetPagination: UnwrapRef<typeof import('@vueuse/core')['useOffsetPagination']>
readonly useOnline: UnwrapRef<typeof import('@vueuse/core')['useOnline']>
readonly usePageLeave: UnwrapRef<typeof import('@vueuse/core')['usePageLeave']>
readonly useParallax: UnwrapRef<typeof import('@vueuse/core')['useParallax']>
readonly useParentElement: UnwrapRef<typeof import('@vueuse/core')['useParentElement']>
readonly usePerformanceObserver: UnwrapRef<typeof import('@vueuse/core')['usePerformanceObserver']>
readonly usePermission: UnwrapRef<typeof import('@vueuse/core')['usePermission']>
readonly usePointer: UnwrapRef<typeof import('@vueuse/core')['usePointer']>
readonly usePointerLock: UnwrapRef<typeof import('@vueuse/core')['usePointerLock']>
readonly usePointerSwipe: UnwrapRef<typeof import('@vueuse/core')['usePointerSwipe']>
readonly usePreferredColorScheme: UnwrapRef<typeof import('@vueuse/core')['usePreferredColorScheme']>
readonly usePreferredContrast: UnwrapRef<typeof import('@vueuse/core')['usePreferredContrast']>
readonly usePreferredDark: UnwrapRef<typeof import('@vueuse/core')['usePreferredDark']>
readonly usePreferredLanguages: UnwrapRef<typeof import('@vueuse/core')['usePreferredLanguages']>
readonly usePreferredReducedMotion: UnwrapRef<typeof import('@vueuse/core')['usePreferredReducedMotion']>
readonly usePrevious: UnwrapRef<typeof import('@vueuse/core')['usePrevious']>
readonly useQuery: UnwrapRef<typeof import('./composables/useQuery')['useQuery']>
readonly useRafFn: UnwrapRef<typeof import('@vueuse/core')['useRafFn']>
readonly useRefHistory: UnwrapRef<typeof import('@vueuse/core')['useRefHistory']>
readonly useResizeObserver: UnwrapRef<typeof import('@vueuse/core')['useResizeObserver']>
readonly useScreenOrientation: UnwrapRef<typeof import('@vueuse/core')['useScreenOrientation']>
readonly useScreenSafeArea: UnwrapRef<typeof import('@vueuse/core')['useScreenSafeArea']>
readonly useScriptTag: UnwrapRef<typeof import('@vueuse/core')['useScriptTag']>
readonly useScroll: UnwrapRef<typeof import('@vueuse/core')['useScroll']>
readonly useScrollLock: UnwrapRef<typeof import('@vueuse/core')['useScrollLock']>
readonly useSessionStorage: UnwrapRef<typeof import('@vueuse/core')['useSessionStorage']>
readonly useShare: UnwrapRef<typeof import('@vueuse/core')['useShare']>
readonly useSlots: UnwrapRef<typeof import('vue')['useSlots']>
readonly useSorted: UnwrapRef<typeof import('@vueuse/core')['useSorted']>
readonly useSpeechRecognition: UnwrapRef<typeof import('@vueuse/core')['useSpeechRecognition']>
readonly useSpeechSynthesis: UnwrapRef<typeof import('@vueuse/core')['useSpeechSynthesis']>
readonly useStepper: UnwrapRef<typeof import('@vueuse/core')['useStepper']>
readonly useStorage: UnwrapRef<typeof import('@vueuse/core')['useStorage']>
readonly useStorageAsync: UnwrapRef<typeof import('@vueuse/core')['useStorageAsync']>
readonly useStyleTag: UnwrapRef<typeof import('@vueuse/core')['useStyleTag']>
readonly useSupported: UnwrapRef<typeof import('@vueuse/core')['useSupported']>
readonly useSwipe: UnwrapRef<typeof import('@vueuse/core')['useSwipe']>
readonly useTemplateRef: UnwrapRef<typeof import('vue')['useTemplateRef']>
readonly useTemplateRefsList: UnwrapRef<typeof import('@vueuse/core')['useTemplateRefsList']>
readonly useTextDirection: UnwrapRef<typeof import('@vueuse/core')['useTextDirection']>
readonly useTextSelection: UnwrapRef<typeof import('@vueuse/core')['useTextSelection']>
readonly useTextareaAutosize: UnwrapRef<typeof import('@vueuse/core')['useTextareaAutosize']>
readonly useThrottle: UnwrapRef<typeof import('@vueuse/core')['useThrottle']>
readonly useThrottleFn: UnwrapRef<typeof import('@vueuse/core')['useThrottleFn']>
readonly useThrottledRefHistory: UnwrapRef<typeof import('@vueuse/core')['useThrottledRefHistory']>
readonly useTimeAgo: UnwrapRef<typeof import('@vueuse/core')['useTimeAgo']>
readonly useTimeout: UnwrapRef<typeof import('@vueuse/core')['useTimeout']>
readonly useTimeoutFn: UnwrapRef<typeof import('@vueuse/core')['useTimeoutFn']>
readonly useTimeoutPoll: UnwrapRef<typeof import('@vueuse/core')['useTimeoutPoll']>
readonly useTimestamp: UnwrapRef<typeof import('@vueuse/core')['useTimestamp']>
readonly useTitle: UnwrapRef<typeof import('@vueuse/core')['useTitle']>
readonly useToNumber: UnwrapRef<typeof import('@vueuse/core')['useToNumber']>
readonly useToString: UnwrapRef<typeof import('@vueuse/core')['useToString']>
readonly useToggle: UnwrapRef<typeof import('@vueuse/core')['useToggle']>
readonly useTransition: UnwrapRef<typeof import('@vueuse/core')['useTransition']>
readonly useUrlSearchParams: UnwrapRef<typeof import('@vueuse/core')['useUrlSearchParams']>
readonly useUserMedia: UnwrapRef<typeof import('@vueuse/core')['useUserMedia']>
readonly useVModel: UnwrapRef<typeof import('@vueuse/core')['useVModel']>
readonly useVModels: UnwrapRef<typeof import('@vueuse/core')['useVModels']>
readonly useVibrate: UnwrapRef<typeof import('@vueuse/core')['useVibrate']>
readonly useVirtualList: UnwrapRef<typeof import('@vueuse/core')['useVirtualList']>
readonly useWakeLock: UnwrapRef<typeof import('@vueuse/core')['useWakeLock']>
readonly useWebNotification: UnwrapRef<typeof import('@vueuse/core')['useWebNotification']>
readonly useWebSocket: UnwrapRef<typeof import('@vueuse/core')['useWebSocket']>
readonly useWebWorker: UnwrapRef<typeof import('@vueuse/core')['useWebWorker']>
readonly useWebWorkerFn: UnwrapRef<typeof import('@vueuse/core')['useWebWorkerFn']>
readonly useWindowFocus: UnwrapRef<typeof import('@vueuse/core')['useWindowFocus']>
readonly useWindowScroll: UnwrapRef<typeof import('@vueuse/core')['useWindowScroll']>
readonly useWindowSize: UnwrapRef<typeof import('@vueuse/core')['useWindowSize']>
readonly watch: UnwrapRef<typeof import('vue')['watch']>
readonly watchArray: UnwrapRef<typeof import('@vueuse/core')['watchArray']>
readonly watchAtMost: UnwrapRef<typeof import('@vueuse/core')['watchAtMost']>
readonly watchDebounced: UnwrapRef<typeof import('@vueuse/core')['watchDebounced']>
readonly watchDeep: UnwrapRef<typeof import('@vueuse/core')['watchDeep']>
readonly watchEffect: UnwrapRef<typeof import('vue')['watchEffect']>
readonly watchIgnorable: UnwrapRef<typeof import('@vueuse/core')['watchIgnorable']>
readonly watchImmediate: UnwrapRef<typeof import('@vueuse/core')['watchImmediate']>
readonly watchOnce: UnwrapRef<typeof import('@vueuse/core')['watchOnce']>
readonly watchPausable: UnwrapRef<typeof import('@vueuse/core')['watchPausable']>
readonly watchPostEffect: UnwrapRef<typeof import('vue')['watchPostEffect']>
readonly watchSyncEffect: UnwrapRef<typeof import('vue')['watchSyncEffect']>
readonly watchThrottled: UnwrapRef<typeof import('@vueuse/core')['watchThrottled']>
readonly watchTriggerable: UnwrapRef<typeof import('@vueuse/core')['watchTriggerable']>
readonly watchWithFilter: UnwrapRef<typeof import('@vueuse/core')['watchWithFilter']>
readonly whenever: UnwrapRef<typeof import('@vueuse/core')['whenever']>
}
}

47
src/components.d.ts vendored Normal file
View File

@@ -0,0 +1,47 @@
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by vite-plugin-uni-components
// Read more: https://github.com/vuejs/core/pull/3399
export {}
declare module 'vue' {
export interface GlobalComponents {
AppFooter: typeof import('./components/AppFooter.vue')['default']
AppLogos: typeof import('./components/AppLogos.vue')['default']
HiCounter: typeof import('./components/HiCounter.vue')['default']
InputEntry: typeof import('./components/InputEntry.vue')['default']
LButtonGroup: typeof import('./components/LButtonGroup.vue')['default']
LExpandCollapse: typeof import('./components/LExpandCollapse.vue')['default']
LTabbar: typeof import('./components/LTabbar.vue')['default']
LTable: typeof import('./components/LTable.vue')['default']
LTitle: typeof import('./components/LTitle.vue')['default']
PrivacyModel: typeof import('./components/PrivacyModel.vue')['default']
QiunDataChartsQiunDataCharts: typeof import('./components/qiun-data-charts/qiun-data-charts.vue')['default']
QiunLoadingLoading1: typeof import('./components/qiun-loading/loading1.vue')['default']
QiunLoadingLoading2: typeof import('./components/qiun-loading/loading2.vue')['default']
QiunLoadingLoading3: typeof import('./components/qiun-loading/loading3.vue')['default']
QiunLoadingLoading4: typeof import('./components/qiun-loading/loading4.vue')['default']
QiunLoadingLoading5: typeof import('./components/qiun-loading/loading5.vue')['default']
QiunLoadingQiunLoading: typeof import('./components/qiun-loading/qiun-loading.vue')['default']
}
}
Button: typeof import('wot-design-uni/components/wd-button/wd-button.vue')['default']
WdCell: typeof import('wot-design-uni/components/wd-cell/wd-cell.vue')['default']
WdCheckbox: typeof import('wot-design-uni/components/wd-checkbox/wd-checkbox.vue')['default']
WdCollapse: typeof import('wot-design-uni/components/wd-collapse/wd-collapse.vue')['default']
WdCollapseItem: typeof import('wot-design-uni/components/wd-collapse-item/wd-collapse-item.vue')['default']
WdDivider: typeof import('wot-design-uni/components/wd-divider/wd-divider.vue')['default']
WdIcon: typeof import('wot-design-uni/components/wd-icon/wd-icon.vue')['default']
WdImg: typeof import('wot-design-uni/components/wd-img/wd-img.vue')['default']
WdInput: typeof import('wot-design-uni/components/wd-input/wd-input.vue')['default']
WdLoadmore: typeof import('wot-design-uni/components/wd-loadmore/wd-loadmore.vue')['default']
WdNavbar: typeof import('wot-design-uni/components/wd-navbar/wd-navbar.vue')['default']
WdNoticeBar: typeof import('wot-design-uni/components/wd-notice-bar/wd-notice-bar.vue')['default']
WdPopup: typeof import('wot-design-uni/components/wd-popup/wd-popup.vue')['default']
WdRadio: typeof import('wot-design-uni/components/wd-radio/wd-radio.vue')['default']
WdRadioGroup: typeof import('wot-design-uni/components/wd-radio-group/wd-radio-group.vue')['default']
WdTabbar: typeof import('wot-design-uni/components/wd-tabbar/wd-tabbar.vue')['default']
WdTabbarItem: typeof import('wot-design-uni/components/wd-tabbar-item/wd-tabbar-item.vue')['default']
}
}

View File

@@ -0,0 +1,25 @@
<script lang="ts" setup>
function handleClickGithub() {
if (window?.open) {
window.open('https://github.com/uni-helper/vitesse-uni-app')
}
else {
uni.showToast({
icon: 'none',
title: '请使用浏览器打开',
})
}
}
</script>
<template>
<view text="xl gray4" m-5 flex items-center justify-center gap-3>
<navigator url="/pages/index" open-type="redirect">
<view i-carbon-campsite />
</navigator>
<view cursor-pointer @click="handleClickGithub">
<view i-carbon:logo-github />
</view>
</view>
</template>

View File

@@ -0,0 +1,27 @@
<template>
<view inline-flex cursor-default text-2xl font-300>
<view
flex
flex-col
items-center
hover-class="drop-shadow-md drop-shadow-color-green5"
>
<image inline-block h-18 w-18 src="/static/logo.svg" />
<text mt--2 text-green5>
uni-helper
</text>
</view>
<view
text="3xl gray4"
m="x-4 y-auto"
i-carbon-add transform transition-all-500 hover:rotate-135
/>
<view flex flex-col hover-class="drop-shadow-md drop-shadow-color-purple5">
<image inline-block h-18 w-18 src="/static/vite.png" />
<text mt--2 text-purple5>
Vite
</text>
</view>
</view>
</template>

View File

@@ -0,0 +1,23 @@
<script setup lang="ts">
const { count, inc, dec } = useCount()
</script>
<template>
<view inline-flex m="y-3">
<view class="btn" @click="dec()">
<text i-carbon-subtract />
</view>
<view font="mono" w="15" m-auto inline-block>
{{ count }}
</view>
<view class="btn" @click="inc()">
<text i-carbon-add />
</view>
</view>
</template>
<style>
.btn {
--at-apply: w-8 h-8 flex items-center justify-center rounded-full bg-teal-600 text-white cursor-pointer
}
</style>

View File

@@ -0,0 +1,47 @@
<script setup lang="ts">
const name = ref('')
function go() {
if (name.value) {
uni.navigateTo({
url: `/pages/hi?name=${name.value}`,
})
}
}
</script>
<template>
<view>
<view
p="x-4 y-2"
w="250px"
m="t-5 auto"
text="center"
bg="transparent"
border="~ rounded gray-200 dark:gray-700 solid"
outline="none active:none"
box-border
w-full
>
<input
v-model="name"
placeholder="What's your name?"
type="text"
autocomplete="off"
mr-0 w-full
>
</view>
<view>
<button
:disabled="!name"
m="t-3 auto"
m-auto w-120rpx rounded bg-teal-600 px-4 py-1 text-sm text-white
hover-class="bg-teal-700"
@click="go"
>
GO
</button>
</view>
</view>
</template>

View File

@@ -0,0 +1,87 @@
<script setup>
// 接收 type 和 options props 以及 v-model
const props = defineProps({
type: {
type: String,
default: 'purple-pink', // 默认颜色渐变
},
options: {
type: Array,
required: true, // 动态传入选项
},
modelValue: {
type: String,
default: '', // v-model 绑定的值
},
})
const emit = defineEmits(['update:modelValue'])
// 选中内容绑定 v-model
const selected = ref(props.modelValue)
// 监听 v-model 的变化
watch(() => props.modelValue, (newValue) => {
selected.value = newValue
})
// 根据type动态生成分割线的类名
const lineClass = computed(() => {
switch (props.type) {
case 'blue-green':
return 'bg-gradient-to-r from-blue-400 via-green-500 to-teal-500'
case 'orange-yellow':
return 'bg-gradient-to-r from-orange-400 via-yellow-500 to-yellow-600'
case 'red-purple':
return 'bg-gradient-to-r from-red-500 via-purple-500 to-purple-600'
default:
return 'bg-gradient-to-r from-purple-400 via-pink-500 to-red-500'
}
})
// 计算滑动线的位置和宽度
const slideLineStyle = computed(() => {
const index = props.options.findIndex(option => option.value === selected.value)
const buttonWidth = 100 / props.options.length
return {
width: `${buttonWidth}%`,
transform: `translateX(${index * 100}%)`,
}
})
// 选择选项函数
function selectOption(option) {
selected.value = option.value
// 触发 v-model 的更新
emit('update:modelValue', option.value)
}
</script>
<template>
<div class="relative flex">
<div
v-for="(option, index) in options"
:key="index"
class="flex-1 shrink-0 cursor-pointer py-2 text-center text-size-sm font-bold transition-transform duration-200 ease-in-out"
:class="{ 'text-gray-900': selected === option.value, 'text-gray-500': selected !== option.value }"
@click="selectOption(option)"
>
{{ option.label }}
</div>
<div
class="absolute bottom-0 h-[3px] rounded transition-all duration-300"
:style="slideLineStyle"
:class="lineClass"
/>
</div>
</template>
<style scoped>
/* 自定义样式 */
button {
outline: none;
border: none;
cursor: pointer;
}
button:focus {
outline: none;
}
</style>

View File

@@ -0,0 +1,61 @@
<script setup>
import { computed, ref, useSlots } from 'vue'
// 接收最大长度的 prop默认值 100
const props = defineProps({
maxLength: {
type: Number,
default: 100,
},
})
// 记录当前是否展开
const isExpanded = ref(false)
// 获取 slot 内容
const slots = useSlots()
// 计算截断后的内容
const truncatedContent = computed(() => {
const slotContent = getSlotContent()
return slotContent.length > props.maxLength
? `${slotContent.slice(0, props.maxLength)}...`
: slotContent
})
// 获取 slot 内容,确保返回的内容为字符串
function getSlotContent() {
const slotVNode = slots.default ? slots.default()[0] : null
return slotVNode ? slotVNode.children.toString().trim() : '' // 获取并转化为字符串
}
// 切换展开/收起状态
function toggleExpand() {
isExpanded.value = !isExpanded.value
}
</script>
<template>
<view>
<!-- 展开/收起按钮 -->
<!-- 展开/收起的内容 -->
<text v-if="isExpanded">
<slot /> <!-- 使用 slot 来展示传递的内容 -->
</text>
<text v-else>
<text>{{ truncatedContent }}</text>
</text>
<text
:title="isExpanded ? '点击收起' : '点击展开'"
class="cursor-pointer text-blue-500"
@click="toggleExpand"
>
{{ isExpanded ? '收起' : '展开' }}
</text>
</view>
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,30 @@
<script setup>
const tabbar = ref('index')
const menu = reactive([{ title: '首页', icon: 'home', name: 'index' }, { title: 'AI律师', icon: 'chat', name: 'ai' }, { title: '我的', icon: 'user', name: 'me' }])
function tabChange({ value }) {
uni.switchTab({
url: `/pages/${value}`,
})
}
onShow(() => {
const currentPage = getCurrentPages()[getCurrentPages().length - 1].route
const pageName = currentPage.split('/').pop()
tabbar.value = pageName
})
onMounted(() => {
uni.hideTabBar()
})
</script>
<template>
<wd-tabbar v-model="tabbar" custom-class="qnc-tabbar" shape="round" safe-area-inset-bottom fixed @change="tabChange">
<wd-tabbar-item v-for="(item, index) in menu" :key="index" :name="item.name" :title="item.title" :icon="item.icon" />
</wd-tabbar>
</template>
<style scoped>
:deep(.qnc-tabbar) {
bottom: 16px !important;
}
</style>

98
src/components/LTable.vue Normal file
View File

@@ -0,0 +1,98 @@
<script setup>
import { computed } from 'vue'
// 接收表格数据和类型的 props
const props = defineProps({
data: {
type: Array,
required: true,
},
type: {
type: String,
default: 'purple-pink', // 默认渐变颜色
},
})
// 根据 type 设置不同的渐变颜色(偶数行)
const evenClass = computed(() => {
switch (props.type) {
case 'blue-green':
return 'bg-teal-100/40'
// return 'bg-gradient-to-r from-blue-50 via-green-50 to-teal-50'
case 'orange-yellow':
return 'bg-gradient-to-r from-orange-50 via-yellow-50 to-yellow-100'
case 'red-purple':
return 'bg-gradient-to-r from-red-50 via-purple-50 to-purple-100'
default:
return 'bg-gradient-to-r from-purple-50 via-pink-50 to-red-50'
}
})
// 动态计算表头的背景颜色和文本颜色
const headerClass = computed(() => {
switch (props.type) {
case 'blue-green':
return 'bg-teal-200'
// return 'bg-gradient-to-r from-blue-200 via-green-200 to-teal-200'
case 'orange-yellow':
return 'bg-gradient-to-r from-orange-200 via-yellow-200 to-yellow-200'
case 'red-purple':
return 'bg-gradient-to-r from-red-200 via-purple-200 to-purple-200'
default:
return 'bg-gradient-to-r from-purple-200 via-pink-200 to-red-200'
}
})
// 斑马纹样式,偶数行带颜色,奇数行没有颜色,且从第二行开始
function zebraClass(index) {
return index % 2 === 1 ? evenClass.value : ''
}
</script>
<template>
<div class="l-table overflow-x-auto">
<table class="min-w-full border-collapse table-auto text-center text-size-xs">
<thead :class="headerClass">
<tr>
<!-- 插槽渲染表头 -->
<slot name="header" />
</tr>
</thead>
<tbody>
<tr
v-for="(row, index) in data"
:key="index"
:class="zebraClass(index)"
class="border-t"
>
<!-- 插槽渲染每一列的内容 -->
<slot :row="row" />
</tr>
</tbody>
</table>
</div>
</template>
<style scoped>
/* 基础表格样式 */
th {
font-weight: bold;
padding: 12px;
text-align: left;
border: 1px solid #e5e7eb;
}
/* 表格行样式 */
td {
padding: 12px;
border: 1px solid #e5e7eb;
}
table {
width: 100%;
border-spacing: 0;
}
.l-table{
@apply rounded-xl;;
overflow: hidden;
}
</style>

58
src/components/LTitle.vue Normal file
View File

@@ -0,0 +1,58 @@
<script setup>
// 接收 props
const props = defineProps({
title: String,
type: {
type: String,
default: 'purple-pink', // 默认渐变
},
})
// 根据type返回不同的背景类名
const titleClass = computed(() => {
switch (props.type) {
case 'blue-green':
return 'bg-gradient-to-r from-blue-400 via-green-500 to-teal-500'
case 'orange-yellow':
return 'bg-gradient-to-r from-orange-400 via-yellow-500 to-yellow-600'
case 'red-purple':
return 'bg-gradient-to-r from-red-500 via-purple-500 to-purple-600'
default:
return 'bg-gradient-to-r from-purple-400 via-pink-500 to-red-500'
}
})
// 分割线颜色与背景对应
const lineClass = computed(() => {
switch (props.type) {
case 'blue-green':
return 'bg-gradient-to-r from-blue-400 via-green-500 to-teal-500'
case 'orange-yellow':
return 'bg-gradient-to-r from-orange-400 via-yellow-500 to-yellow-600'
case 'red-purple':
return 'bg-gradient-to-r from-red-500 via-purple-500 to-purple-600'
default:
return 'bg-gradient-to-r from-purple-400 via-pink-500 to-red-500'
}
})
</script>
<template>
<div class="relative">
<!-- 标题部分 -->
<div :class="titleClass" class="inline-block rounded-lg px-2 py-1 text-white font-bold shadow-md">
{{ title }}
</div>
<!-- 左上角修饰 -->
<div class="absolute left-0 top-0 h-4 w-4 transform rounded-full bg-white shadow-md -translate-x-2 -translate-y-2" />
<!-- 分割线 -->
<div class="relative mt-1.5">
<div :class="lineClass" class="h-[2px] w-full rounded" />
</div>
</div>
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,144 @@
<script setup>
const showPrivacyModal = ref(true)
function openPage(url) {
uni.navigateTo({ url })
}
function acceptPrivacy() {
uni.setStorageSync('privacyAccepted', true)
showPrivacyModal.value = false
}
function refusePrivacy() {
uni.showModal({
title: '确认提示',
content: '您点击同意并继续视为您已同意上述协议的全部内容。',
confirmText: '同意并继续',
cancelText: '退出',
success: (res) => {
if (res.confirm) {
acceptPrivacy()
}
else {
uni.exitApp()
}
},
})
}
// 检查隐私协议是否已经同意
onMounted(() => {
const accepted = uni.getStorageSync('privacyAccepted')
if (accepted) {
showPrivacyModal.value = false
}
})
</script>
<template>
<view v-if="showPrivacyModal" class="privacy-modal">
<view class="modal-mask" />
<view class="modal-content">
<view class="modal-title">
用户协议和隐私政策
</view>
<view class="modal-message">
感谢您使用全能查APP! 我们非常重视您的隐私保护和个人信息保护在您使用全能查APP前请您仔细阅读充分理解
<text class="link" @click="openPage('/pages/userAgreement')">
用户协议
</text>
<text class="link" @click="openPage('/pages/privacyPolicy')">
隐私政策
</text>
的各项条款如果您同意请点击下方按钮开始接受我们的服务
</view>
<view class="modal-buttons">
<view class="button refuse" @click="refusePrivacy">
退出应用
</view>
<view class="button accept" @click="acceptPrivacy">
同意并继续
</view>
</view>
</view>
</view>
</template>
<style scoped>
.privacy-modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
}
.modal-mask {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
}
.modal-content {
background: #fff;
padding: 20px;
border-radius: 10px;
width: 80%;
max-width: 320px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
z-index:1001;
}
.modal-title {
font-size: 18px;
font-weight: bold;
margin-bottom: 10px;
text-align: center;
}
.modal-message {
font-size: 14px;
line-height: 1.5;
color: #333;
margin-bottom: 20px;
}
.link {
color: #007aff;
text-decoration: underline;
cursor: pointer;
}
.modal-buttons {
display: flex;
justify-content: space-between;
}
.button {
flex: 1;
padding: 10px 0;
margin: 0 5px;
border: none;
border-radius: 5px;
font-size: 14px;
text-align: center;
}
.button.accept {
background: #007aff;
color: #fff;
}
.button.accept:active{
background: #016ee2;
color: #fff;
}
.button.refuse {
background: #f0f0f0;
color: #333;
}
.button.refuse:active {
background: #c6c6c6;
color: #333;
}
</style>

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,162 @@
<template>
<view class="container loading1">
<view class="shape shape1"></view>
<view class="shape shape2"></view>
<view class="shape shape3"></view>
<view class="shape shape4"></view>
</view>
</template>
<script>
export default {
name: 'loading1',
data() {
return {
};
}
}
</script>
<style scoped="true">
.container {
width: 30px;
height: 30px;
position: relative;
}
.container.loading1 {
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
}
.container .shape {
position: absolute;
width: 10px;
height: 10px;
border-radius: 1px;
}
.container .shape.shape1 {
left: 0;
background-color: #1890FF;
}
.container .shape.shape2 {
right: 0;
background-color: #91CB74;
}
.container .shape.shape3 {
bottom: 0;
background-color: #FAC858;
}
.container .shape.shape4 {
bottom: 0;
right: 0;
background-color: #EE6666;
}
.loading1 .shape1 {
-webkit-animation: animation1shape1 0.5s ease 0s infinite alternate;
animation: animation1shape1 0.5s ease 0s infinite alternate;
}
@-webkit-keyframes animation1shape1 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(16px, 16px);
transform: translate(16px, 16px);
}
}
@keyframes animation1shape1 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(16px, 16px);
transform: translate(16px, 16px);
}
}
.loading1 .shape2 {
-webkit-animation: animation1shape2 0.5s ease 0s infinite alternate;
animation: animation1shape2 0.5s ease 0s infinite alternate;
}
@-webkit-keyframes animation1shape2 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(-16px, 16px);
transform: translate(-16px, 16px);
}
}
@keyframes animation1shape2 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(-16px, 16px);
transform: translate(-16px, 16px);
}
}
.loading1 .shape3 {
-webkit-animation: animation1shape3 0.5s ease 0s infinite alternate;
animation: animation1shape3 0.5s ease 0s infinite alternate;
}
@-webkit-keyframes animation1shape3 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(16px, -16px);
transform: translate(16px, -16px);
}
}
@keyframes animation1shape3 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(16px, -16px);
transform: translate(16px, -16px);
}
}
.loading1 .shape4 {
-webkit-animation: animation1shape4 0.5s ease 0s infinite alternate;
animation: animation1shape4 0.5s ease 0s infinite alternate;
}
@-webkit-keyframes animation1shape4 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(-16px, -16px);
transform: translate(-16px, -16px);
}
}
@keyframes animation1shape4 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(-16px, -16px);
transform: translate(-16px, -16px);
}
}
</style>

View File

@@ -0,0 +1,170 @@
<template>
<view class="container loading2">
<view class="shape shape1"></view>
<view class="shape shape2"></view>
<view class="shape shape3"></view>
<view class="shape shape4"></view>
</view>
</template>
<script>
export default {
name: 'loading2',
data() {
return {
};
}
}
</script>
<style scoped="true">
.container {
width: 30px;
height: 30px;
position: relative;
}
.container.loading2 {
-webkit-transform: rotate(10deg);
transform: rotate(10deg);
}
.container.loading2 .shape {
border-radius: 5px;
}
.container.loading2{
-webkit-animation: rotation 1s infinite;
animation: rotation 1s infinite;
}
.container .shape {
position: absolute;
width: 10px;
height: 10px;
border-radius: 1px;
}
.container .shape.shape1 {
left: 0;
background-color: #1890FF;
}
.container .shape.shape2 {
right: 0;
background-color: #91CB74;
}
.container .shape.shape3 {
bottom: 0;
background-color: #FAC858;
}
.container .shape.shape4 {
bottom: 0;
right: 0;
background-color: #EE6666;
}
.loading2 .shape1 {
-webkit-animation: animation2shape1 0.5s ease 0s infinite alternate;
animation: animation2shape1 0.5s ease 0s infinite alternate;
}
@-webkit-keyframes animation2shape1 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(20px, 20px);
transform: translate(20px, 20px);
}
}
@keyframes animation2shape1 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(20px, 20px);
transform: translate(20px, 20px);
}
}
.loading2 .shape2 {
-webkit-animation: animation2shape2 0.5s ease 0s infinite alternate;
animation: animation2shape2 0.5s ease 0s infinite alternate;
}
@-webkit-keyframes animation2shape2 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(-20px, 20px);
transform: translate(-20px, 20px);
}
}
@keyframes animation2shape2 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(-20px, 20px);
transform: translate(-20px, 20px);
}
}
.loading2 .shape3 {
-webkit-animation: animation2shape3 0.5s ease 0s infinite alternate;
animation: animation2shape3 0.5s ease 0s infinite alternate;
}
@-webkit-keyframes animation2shape3 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(20px, -20px);
transform: translate(20px, -20px);
}
}
@keyframes animation2shape3 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(20px, -20px);
transform: translate(20px, -20px);
}
}
.loading2 .shape4 {
-webkit-animation: animation2shape4 0.5s ease 0s infinite alternate;
animation: animation2shape4 0.5s ease 0s infinite alternate;
}
@-webkit-keyframes animation2shape4 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(-20px, -20px);
transform: translate(-20px, -20px);
}
}
@keyframes animation2shape4 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(-20px, -20px);
transform: translate(-20px, -20px);
}
}
</style>

View File

@@ -0,0 +1,173 @@
<template>
<view class="container loading3">
<view class="shape shape1"></view>
<view class="shape shape2"></view>
<view class="shape shape3"></view>
<view class="shape shape4"></view>
</view>
</template>
<script>
export default {
name: 'loading3',
data() {
return {
};
}
}
</script>
<style scoped="true">
.container {
width: 30px;
height: 30px;
position: relative;
}
.container.loading3 {
-webkit-animation: rotation 1s infinite;
animation: rotation 1s infinite;
}
.container.loading3 .shape1 {
border-top-left-radius: 10px;
}
.container.loading3 .shape2 {
border-top-right-radius: 10px;
}
.container.loading3 .shape3 {
border-bottom-left-radius: 10px;
}
.container.loading3 .shape4 {
border-bottom-right-radius: 10px;
}
.container .shape {
position: absolute;
width: 10px;
height: 10px;
border-radius: 1px;
}
.container .shape.shape1 {
left: 0;
background-color: #1890FF;
}
.container .shape.shape2 {
right: 0;
background-color: #91CB74;
}
.container .shape.shape3 {
bottom: 0;
background-color: #FAC858;
}
.container .shape.shape4 {
bottom: 0;
right: 0;
background-color: #EE6666;
}
.loading3 .shape1 {
-webkit-animation: animation3shape1 0.5s ease 0s infinite alternate;
animation: animation3shape1 0.5s ease 0s infinite alternate;
}
@-webkit-keyframes animation3shape1 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(5px, 5px);
transform: translate(5px, 5px);
}
}
@keyframes animation3shape1 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(5px, 5px);
transform: translate(5px, 5px);
}
}
.loading3 .shape2 {
-webkit-animation: animation3shape2 0.5s ease 0s infinite alternate;
animation: animation3shape2 0.5s ease 0s infinite alternate;
}
@-webkit-keyframes animation3shape2 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(-5px, 5px);
transform: translate(-5px, 5px);
}
}
@keyframes animation3shape2 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(-5px, 5px);
transform: translate(-5px, 5px);
}
}
.loading3 .shape3 {
-webkit-animation: animation3shape3 0.5s ease 0s infinite alternate;
animation: animation3shape3 0.5s ease 0s infinite alternate;
}
@-webkit-keyframes animation3shape3 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(5px, -5px);
transform: translate(5px, -5px);
}
}
@keyframes animation3shape3 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(5px, -5px);
transform: translate(5px, -5px);
}
}
.loading3 .shape4 {
-webkit-animation: animation3shape4 0.5s ease 0s infinite alternate;
animation: animation3shape4 0.5s ease 0s infinite alternate;
}
@-webkit-keyframes animation3shape4 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(-5px, -5px);
transform: translate(-5px, -5px);
}
}
@keyframes animation3shape4 {
from {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
-webkit-transform: translate(-5px, -5px);
transform: translate(-5px, -5px);
}
}
</style>

View File

@@ -0,0 +1,222 @@
<template>
<view class="container loading5">
<view class="shape shape1"></view>
<view class="shape shape2"></view>
<view class="shape shape3"></view>
<view class="shape shape4"></view>
</view>
</template>
<script>
export default {
name: 'loading5',
data() {
return {
};
}
}
</script>
<style scoped="true">
.container {
width: 30px;
height: 30px;
position: relative;
}
.container.loading5 .shape {
width: 15px;
height: 15px;
}
.container .shape {
position: absolute;
width: 10px;
height: 10px;
border-radius: 1px;
}
.container .shape.shape1 {
left: 0;
background-color: #1890FF;
}
.container .shape.shape2 {
right: 0;
background-color: #91CB74;
}
.container .shape.shape3 {
bottom: 0;
background-color: #FAC858;
}
.container .shape.shape4 {
bottom: 0;
right: 0;
background-color: #EE6666;
}
.loading5 .shape1 {
animation: animation5shape1 2s ease 0s infinite reverse;
}
@-webkit-keyframes animation5shape1 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(0, 15px);
transform: translate(0, 15px);
}
50% {
-webkit-transform: translate(15px, 15px);
transform: translate(15px, 15px);
}
75% {
-webkit-transform: translate(15px, 0);
transform: translate(15px, 0);
}
}
@keyframes animation5shape1 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(0, 15px);
transform: translate(0, 15px);
}
50% {
-webkit-transform: translate(15px, 15px);
transform: translate(15px, 15px);
}
75% {
-webkit-transform: translate(15px, 0);
transform: translate(15px, 0);
}
}
.loading5 .shape2 {
animation: animation5shape2 2s ease 0s infinite reverse;
}
@-webkit-keyframes animation5shape2 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(-15px, 0);
transform: translate(-15px, 0);
}
50% {
-webkit-transform: translate(-15px, 15px);
transform: translate(-15px, 15px);
}
75% {
-webkit-transform: translate(0, 15px);
transform: translate(0, 15px);
}
}
@keyframes animation5shape2 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(-15px, 0);
transform: translate(-15px, 0);
}
50% {
-webkit-transform: translate(-15px, 15px);
transform: translate(-15px, 15px);
}
75% {
-webkit-transform: translate(0, 15px);
transform: translate(0, 15px);
}
}
.loading5 .shape3 {
animation: animation5shape3 2s ease 0s infinite reverse;
}
@-webkit-keyframes animation5shape3 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(15px, 0);
transform: translate(15px, 0);
}
50% {
-webkit-transform: translate(15px, -15px);
transform: translate(15px, -15px);
}
75% {
-webkit-transform: translate(0, -15px);
transform: translate(0, -15px);
}
}
@keyframes animation5shape3 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(15px, 0);
transform: translate(15px, 0);
}
50% {
-webkit-transform: translate(15px, -15px);
transform: translate(15px, -15px);
}
75% {
-webkit-transform: translate(0, -15px);
transform: translate(0, -15px);
}
}
.loading5 .shape4 {
animation: animation5shape4 2s ease 0s infinite reverse;
}
@-webkit-keyframes animation5shape4 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(0, -15px);
transform: translate(0, -15px);
}
50% {
-webkit-transform: translate(-15px, -15px);
transform: translate(-15px, -15px);
}
75% {
-webkit-transform: translate(-15px, 0);
transform: translate(-15px, 0);
}
}
@keyframes animation5shape4 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(0, -15px);
transform: translate(0, -15px);
}
50% {
-webkit-transform: translate(-15px, -15px);
transform: translate(-15px, -15px);
}
75% {
-webkit-transform: translate(-15px, 0);
transform: translate(-15px, 0);
}
}
</style>

View File

@@ -0,0 +1,229 @@
<template>
<view class="container loading6">
<view class="shape shape1"></view>
<view class="shape shape2"></view>
<view class="shape shape3"></view>
<view class="shape shape4"></view>
</view>
</template>
<script>
export default {
name: 'loading6',
data() {
return {
};
}
}
</script>
<style scoped="true">
.container {
width: 30px;
height: 30px;
position: relative;
}
.container.loading6 {
-webkit-animation: rotation 1s infinite;
animation: rotation 1s infinite;
}
.container.loading6 .shape {
width: 12px;
height: 12px;
border-radius: 2px;
}
.container .shape {
position: absolute;
width: 10px;
height: 10px;
border-radius: 1px;
}
.container .shape.shape1 {
left: 0;
background-color: #1890FF;
}
.container .shape.shape2 {
right: 0;
background-color: #91CB74;
}
.container .shape.shape3 {
bottom: 0;
background-color: #FAC858;
}
.container .shape.shape4 {
bottom: 0;
right: 0;
background-color: #EE6666;
}
.loading6 .shape1 {
-webkit-animation: animation6shape1 2s linear 0s infinite normal;
animation: animation6shape1 2s linear 0s infinite normal;
}
@-webkit-keyframes animation6shape1 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(0, 18px);
transform: translate(0, 18px);
}
50% {
-webkit-transform: translate(18px, 18px);
transform: translate(18px, 18px);
}
75% {
-webkit-transform: translate(18px, 0);
transform: translate(18px, 0);
}
}
@keyframes animation6shape1 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(0, 18px);
transform: translate(0, 18px);
}
50% {
-webkit-transform: translate(18px, 18px);
transform: translate(18px, 18px);
}
75% {
-webkit-transform: translate(18px, 0);
transform: translate(18px, 0);
}
}
.loading6 .shape2 {
-webkit-animation: animation6shape2 2s linear 0s infinite normal;
animation: animation6shape2 2s linear 0s infinite normal;
}
@-webkit-keyframes animation6shape2 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(-18px, 0);
transform: translate(-18px, 0);
}
50% {
-webkit-transform: translate(-18px, 18px);
transform: translate(-18px, 18px);
}
75% {
-webkit-transform: translate(0, 18px);
transform: translate(0, 18px);
}
}
@keyframes animation6shape2 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(-18px, 0);
transform: translate(-18px, 0);
}
50% {
-webkit-transform: translate(-18px, 18px);
transform: translate(-18px, 18px);
}
75% {
-webkit-transform: translate(0, 18px);
transform: translate(0, 18px);
}
}
.loading6 .shape3 {
-webkit-animation: animation6shape3 2s linear 0s infinite normal;
animation: animation6shape3 2s linear 0s infinite normal;
}
@-webkit-keyframes animation6shape3 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(18px, 0);
transform: translate(18px, 0);
}
50% {
-webkit-transform: translate(18px, -18px);
transform: translate(18px, -18px);
}
75% {
-webkit-transform: translate(0, -18px);
transform: translate(0, -18px);
}
}
@keyframes animation6shape3 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(18px, 0);
transform: translate(18px, 0);
}
50% {
-webkit-transform: translate(18px, -18px);
transform: translate(18px, -18px);
}
75% {
-webkit-transform: translate(0, -18px);
transform: translate(0, -18px);
}
}
.loading6 .shape4 {
-webkit-animation: animation6shape4 2s linear 0s infinite normal;
animation: animation6shape4 2s linear 0s infinite normal;
}
@-webkit-keyframes animation6shape4 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(0, -18px);
transform: translate(0, -18px);
}
50% {
-webkit-transform: translate(-18px, -18px);
transform: translate(-18px, -18px);
}
75% {
-webkit-transform: translate(-18px, 0);
transform: translate(-18px, 0);
}
}
@keyframes animation6shape4 {
0% {
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
25% {
-webkit-transform: translate(0, -18px);
transform: translate(0, -18px);
}
50% {
-webkit-transform: translate(-18px, -18px);
transform: translate(-18px, -18px);
}
75% {
-webkit-transform: translate(-18px, 0);
transform: translate(-18px, 0);
}
}
</style>

View File

@@ -0,0 +1,36 @@
<template>
<view>
<Loading1 v-if="loadingType==1"/>
<Loading2 v-if="loadingType==2"/>
<Loading3 v-if="loadingType==3"/>
<Loading4 v-if="loadingType==4"/>
<Loading5 v-if="loadingType==5"/>
</view>
</template>
<script>
import Loading1 from "./loading1.vue";
import Loading2 from "./loading2.vue";
import Loading3 from "./loading3.vue";
import Loading4 from "./loading4.vue";
import Loading5 from "./loading5.vue";
export default {
components:{Loading1,Loading2,Loading3,Loading4,Loading5},
name: 'qiun-loading',
props: {
loadingType: {
type: Number,
default: 2
},
},
data() {
return {
};
},
}
</script>
<style>
</style>

View File

@@ -0,0 +1,422 @@
/*
* uCharts®
* 高性能跨平台图表库支持H5、APP、小程序微信/支付宝/百度/头条/QQ/360、Vue、Taro等支持canvas的框架平台
* Copyright (c) 2021 QIUN®秋云 https://www.ucharts.cn All rights reserved.
* Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
* 复制使用请保留本段注释,感谢支持开源!
*
* uCharts®官方网站
* https://www.uCharts.cn
*
* 开源地址:
* https://gitee.com/uCharts/uCharts
*
* uni-app插件市场地址
* http://ext.dcloud.net.cn/plugin?id=271
*
*/
// 通用配置项
// 主题颜色配置如每个图表类型需要不同主题请在对应图表类型上更改color属性
const color = ['#1890FF', '#91CB74', '#FAC858', '#EE6666', '#73C0DE', '#3CA272', '#FC8452', '#9A60B4', '#ea7ccc'];
const cfe = {
//demotype为自定义图表类型
"type": ["pie", "ring", "rose", "funnel", "line", "column", "area", "radar", "gauge","candle","demotype"],
//增加自定义图表类型如果需要categories请在这里加入您的图表类型例如最后的"demotype"
"categories": ["line", "column", "area", "radar", "gauge", "candle","demotype"],
//instance为实例变量承载属性option为eopts承载属性不要删除
"instance": {},
"option": {},
//下面是自定义format配置因除H5端外的其他端无法通过props传递函数只能通过此属性对应下标的方式来替换
"formatter":{
"tooltipDemo1":function(res){
let result = ''
for (let i in res) {
if (i == 0) {
result += res[i].axisValueLabel + '年销售额'
}
let value = '--'
if (res[i].data !== null) {
value = res[i].data
}
// #ifdef H5
result += '\n' + res[i].seriesName + '' + value + ' 万元'
// #endif
// #ifdef APP-PLUS
result += '<br/>' + res[i].marker + res[i].seriesName + '' + value + ' 万元'
// #endif
}
return result;
},
legendFormat:function(name){
return "自定义图例+"+name;
},
yAxisFormatDemo:function (value, index) {
return value + '元';
},
seriesFormatDemo:function(res){
return res.name + '年' + res.value + '元';
}
},
//这里演示了自定义您的图表类型的option可以随意命名之后在组件上 type="demotype" 后组件会调用这个花括号里的option如果组件上还存在eopts参数会将demotype与eopts中option合并后渲染图表。
"demotype":{
"color": color,
//在这里填写echarts的option即可
},
//下面是自定义配置,请添加项目所需的通用配置
"column": {
"color": color,
"title": {
"text": ''
},
"tooltip": {
"trigger": 'axis'
},
"grid": {
"top": 30,
"bottom": 50,
"right": 15,
"left": 40
},
"legend": {
"bottom": 'left',
},
"toolbox": {
"show": false,
},
"xAxis": {
"type": 'category',
"axisLabel": {
"color": '#666666'
},
"axisLine": {
"lineStyle": {
"color": '#CCCCCC'
}
},
"boundaryGap": true,
"data": []
},
"yAxis": {
"type": 'value',
"axisTick": {
"show": false,
},
"axisLabel": {
"color": '#666666'
},
"axisLine": {
"lineStyle": {
"color": '#CCCCCC'
}
},
},
"seriesTemplate": {
"name": '',
"type": 'bar',
"data": [],
"barwidth": 20,
"label": {
"show": true,
"color": "#666666",
"position": 'top',
},
},
},
"line": {
"color": color,
"title": {
"text": ''
},
"tooltip": {
"trigger": 'axis'
},
"grid": {
"top": 30,
"bottom": 50,
"right": 15,
"left": 40
},
"legend": {
"bottom": 'left',
},
"toolbox": {
"show": false,
},
"xAxis": {
"type": 'category',
"axisLabel": {
"color": '#666666'
},
"axisLine": {
"lineStyle": {
"color": '#CCCCCC'
}
},
"boundaryGap": true,
"data": []
},
"yAxis": {
"type": 'value',
"axisTick": {
"show": false,
},
"axisLabel": {
"color": '#666666'
},
"axisLine": {
"lineStyle": {
"color": '#CCCCCC'
}
},
},
"seriesTemplate": {
"name": '',
"type": 'line',
"data": [],
"barwidth": 20,
"label": {
"show": true,
"color": "#666666",
"position": 'top',
},
},
},
"area": {
"color": color,
"title": {
"text": ''
},
"tooltip": {
"trigger": 'axis'
},
"grid": {
"top": 30,
"bottom": 50,
"right": 15,
"left": 40
},
"legend": {
"bottom": 'left',
},
"toolbox": {
"show": false,
},
"xAxis": {
"type": 'category',
"axisLabel": {
"color": '#666666'
},
"axisLine": {
"lineStyle": {
"color": '#CCCCCC'
}
},
"boundaryGap": true,
"data": []
},
"yAxis": {
"type": 'value',
"axisTick": {
"show": false,
},
"axisLabel": {
"color": '#666666'
},
"axisLine": {
"lineStyle": {
"color": '#CCCCCC'
}
},
},
"seriesTemplate": {
"name": '',
"type": 'line',
"data": [],
"areaStyle": {},
"label": {
"show": true,
"color": "#666666",
"position": 'top',
},
},
},
"pie": {
"color": color,
"title": {
"text": ''
},
"tooltip": {
"trigger": 'item'
},
"grid": {
"top": 40,
"bottom": 30,
"right": 15,
"left": 15
},
"legend": {
"bottom": 'left',
},
"seriesTemplate": {
"name": '',
"type": 'pie',
"data": [],
"radius": '50%',
"label": {
"show": true,
"color": "#666666",
"position": 'top',
},
},
},
"ring": {
"color": color,
"title": {
"text": ''
},
"tooltip": {
"trigger": 'item'
},
"grid": {
"top": 40,
"bottom": 30,
"right": 15,
"left": 15
},
"legend": {
"bottom": 'left',
},
"seriesTemplate": {
"name": '',
"type": 'pie',
"data": [],
"radius": ['40%', '70%'],
"avoidLabelOverlap": false,
"label": {
"show": true,
"color": "#666666",
"position": 'top',
},
"labelLine": {
"show": true
},
},
},
"rose": {
"color": color,
"title": {
"text": ''
},
"tooltip": {
"trigger": 'item'
},
"legend": {
"top": 'bottom'
},
"seriesTemplate": {
"name": '',
"type": 'pie',
"data": [],
"radius": "55%",
"center": ['50%', '50%'],
"roseType": 'area',
},
},
"funnel": {
"color": color,
"title": {
"text": ''
},
"tooltip": {
"trigger": 'item',
"formatter": "{b} : {c}%"
},
"legend": {
"top": 'bottom'
},
"seriesTemplate": {
"name": '',
"type": 'funnel',
"left": '10%',
"top": 60,
"bottom": 60,
"width": '80%',
"min": 0,
"max": 100,
"minSize": '0%',
"maxSize": '100%',
"sort": 'descending',
"gap": 2,
"label": {
"show": true,
"position": 'inside'
},
"labelLine": {
"length": 10,
"lineStyle": {
"width": 1,
"type": 'solid'
}
},
"itemStyle": {
"bordercolor": '#fff',
"borderwidth": 1
},
"emphasis": {
"label": {
"fontSize": 20
}
},
"data": [],
},
},
"gauge": {
"color": color,
"tooltip": {
"formatter": '{a} <br/>{b} : {c}%'
},
"seriesTemplate": {
"name": '业务指标',
"type": 'gauge',
"detail": {"formatter": '{value}%'},
"data": [{"value": 50, "name": '完成率'}]
},
},
"candle": {
"xAxis": {
"data": []
},
"yAxis": {},
"color": color,
"title": {
"text": ''
},
"dataZoom": [{
"type": 'inside',
"xAxisIndex": [0, 1],
"start": 10,
"end": 100
},
{
"show": true,
"xAxisIndex": [0, 1],
"type": 'slider',
"bottom": 10,
"start": 10,
"end": 100
}
],
"seriesTemplate": {
"name": '',
"type": 'k',
"data": [],
},
}
}
export default cfe;

View File

@@ -0,0 +1,606 @@
/*
* uCharts®
* 高性能跨平台图表库支持H5、APP、小程序微信/支付宝/百度/头条/QQ/360、Vue、Taro等支持canvas的框架平台
* Copyright (c) 2021 QIUN®秋云 https://www.ucharts.cn All rights reserved.
* Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
* 复制使用请保留本段注释,感谢支持开源!
*
* uCharts®官方网站
* https://www.uCharts.cn
*
* 开源地址:
* https://gitee.com/uCharts/uCharts
*
* uni-app插件市场地址
* http://ext.dcloud.net.cn/plugin?id=271
*
*/
// 主题颜色配置如每个图表类型需要不同主题请在对应图表类型上更改color属性
const color = ['#1890FF', '#91CB74', '#FAC858', '#EE6666', '#73C0DE', '#3CA272', '#FC8452', '#9A60B4', '#ea7ccc'];
//事件转换函数主要用作格式化x轴为时间轴根据需求自行修改
const formatDateTime = (timeStamp, returnType)=>{
var date = new Date();
date.setTime(timeStamp * 1000);
var y = date.getFullYear();
var m = date.getMonth() + 1;
m = m < 10 ? ('0' + m) : m;
var d = date.getDate();
d = d < 10 ? ('0' + d) : d;
var h = date.getHours();
h = h < 10 ? ('0' + h) : h;
var minute = date.getMinutes();
var second = date.getSeconds();
minute = minute < 10 ? ('0' + minute) : minute;
second = second < 10 ? ('0' + second) : second;
if(returnType == 'full'){return y + '-' + m + '-' + d + ' '+ h +':' + minute + ':' + second;}
if(returnType == 'y-m-d'){return y + '-' + m + '-' + d;}
if(returnType == 'h:m'){return h +':' + minute;}
if(returnType == 'h:m:s'){return h +':' + minute +':' + second;}
return [y, m, d, h, minute, second];
}
const cfu = {
//demotype为自定义图表类型一般不需要自定义图表类型只需要改根节点上对应的类型即可
"type":["pie","ring","rose","word","funnel","map","arcbar","line","column","mount","bar","area","radar","gauge","candle","mix","tline","tarea","scatter","bubble","demotype"],
"range":["饼状图","圆环图","玫瑰图","词云图","漏斗图","地图","圆弧进度条","折线图","柱状图","山峰图","条状图","区域图","雷达图","仪表盘","K线图","混合图","时间轴折线","时间轴区域","散点图","气泡图","自定义类型"],
//增加自定义图表类型如果需要categories请在这里加入您的图表类型例如最后的"demotype"
//自定义类型时需要注意"tline","tarea","scatter","bubble"等时间轴矢量x轴类图表没有categories不需要加入categories
"categories":["line","column","mount","bar","area","radar","gauge","candle","mix","demotype"],
//instance为实例变量承载属性不要删除
"instance":{},
//option为opts及eopts承载属性不要删除
"option":{},
//下面是自定义format配置因除H5端外的其他端无法通过props传递函数只能通过此属性对应下标的方式来替换
"formatter":{
"yAxisDemo1":function(val, index, opts){return val+'元'},
"yAxisDemo2":function(val, index, opts){return val.toFixed(2)},
"xAxisDemo1":function(val, index, opts){return val+'年';},
"xAxisDemo2":function(val, index, opts){return formatDateTime(val,'h:m')},
"seriesDemo1":function(val, index, series, opts){return val+'元'},
"tooltipDemo1":function(item, category, index, opts){
if(index==0){
return '随便用'+item.data+'年'
}else{
return '其他我没改'+item.data+'天'
}
},
"pieDemo":function(val, index, series, opts){
if(index !== undefined){
return series[index].name+''+series[index].data+'元'
}
},
},
//这里演示了自定义您的图表类型的option可以随意命名之后在组件上 type="demotype" 后组件会调用这个花括号里的option如果组件上还存在opts参数会将demotype与opts中option合并后渲染图表。
"demotype":{
//我这里把曲线图当做了自定义图表类型,您可以根据需要随意指定类型或配置
"type": "line",
"color": color,
"padding": [15,10,0,15],
"xAxis": {
"disableGrid": true,
},
"yAxis": {
"gridType": "dash",
"dashLength": 2,
},
"legend": {
},
"extra": {
"line": {
"type": "curve",
"width": 2
},
}
},
//下面是自定义配置,请添加项目所需的通用配置
"pie":{
"type": "pie",
"color": color,
"padding": [5,5,5,5],
"extra": {
"pie": {
"activeOpacity": 0.5,
"activeRadius": 10,
"offsetAngle": 0,
"labelWidth": 15,
"border": true,
"borderWidth": 3,
"borderColor": "#FFFFFF"
},
}
},
"ring":{
"type": "ring",
"color": color,
"padding": [5,5,5,5],
"rotate": false,
"dataLabel": true,
"legend": {
"show": true,
"position": "right",
"lineHeight": 25,
},
"title": {
"name": "收益率",
"fontSize": 15,
"color": "#666666"
},
"subtitle": {
"name": "70%",
"fontSize": 25,
"color": "#7cb5ec"
},
"extra": {
"ring": {
"ringWidth":30,
"activeOpacity": 0.5,
"activeRadius": 10,
"offsetAngle": 0,
"labelWidth": 15,
"border": true,
"borderWidth": 3,
"borderColor": "#FFFFFF"
},
},
},
"rose":{
"type": "rose",
"color": color,
"padding": [5,5,5,5],
"legend": {
"show": true,
"position": "left",
"lineHeight": 25,
},
"extra": {
"rose": {
"type": "area",
"minRadius": 50,
"activeOpacity": 0.5,
"activeRadius": 10,
"offsetAngle": 0,
"labelWidth": 15,
"border": false,
"borderWidth": 2,
"borderColor": "#FFFFFF"
},
}
},
"word":{
"type": "word",
"color": color,
"extra": {
"word": {
"type": "normal",
"autoColors": false
}
}
},
"funnel":{
"type": "funnel",
"color": color,
"padding": [15,15,0,15],
"extra": {
"funnel": {
"activeOpacity": 0.3,
"activeWidth": 10,
"border": true,
"borderWidth": 2,
"borderColor": "#FFFFFF",
"fillOpacity": 1,
"labelAlign": "right"
},
}
},
"map":{
"type": "map",
"color": color,
"padding": [0,0,0,0],
"dataLabel": true,
"extra": {
"map": {
"border": true,
"borderWidth": 1,
"borderColor": "#666666",
"fillOpacity": 0.6,
"activeBorderColor": "#F04864",
"activeFillColor": "#FACC14",
"activeFillOpacity": 1
},
}
},
"arcbar":{
"type": "arcbar",
"color": color,
"title": {
"name": "百分比",
"fontSize": 25,
"color": "#00FF00"
},
"subtitle": {
"name": "默认标题",
"fontSize": 15,
"color": "#666666"
},
"extra": {
"arcbar": {
"type": "default",
"width": 12,
"backgroundColor": "#E9E9E9",
"startAngle": 0.75,
"endAngle": 0.25,
"gap": 2
}
}
},
"line":{
"type": "line",
"color": color,
"padding": [15,10,0,15],
"xAxis": {
"disableGrid": true,
},
"yAxis": {
"gridType": "dash",
"dashLength": 2,
},
"legend": {
},
"extra": {
"line": {
"type": "straight",
"width": 2,
"activeType": "hollow"
},
}
},
"tline":{
"type": "line",
"color": color,
"padding": [15,10,0,15],
"xAxis": {
"disableGrid": false,
"boundaryGap":"justify",
},
"yAxis": {
"gridType": "dash",
"dashLength": 2,
"data":[
{
"min":0,
"max":80
}
]
},
"legend": {
},
"extra": {
"line": {
"type": "curve",
"width": 2,
"activeType": "hollow"
},
}
},
"tarea":{
"type": "area",
"color": color,
"padding": [15,10,0,15],
"xAxis": {
"disableGrid": true,
"boundaryGap":"justify",
},
"yAxis": {
"gridType": "dash",
"dashLength": 2,
"data":[
{
"min":0,
"max":80
}
]
},
"legend": {
},
"extra": {
"area": {
"type": "curve",
"opacity": 0.2,
"addLine": true,
"width": 2,
"gradient": true,
"activeType": "hollow"
},
}
},
"column":{
"type": "column",
"color": color,
"padding": [15,15,0,5],
"xAxis": {
"disableGrid": true,
},
"yAxis": {
"data":[{"min":0}]
},
"legend": {
},
"extra": {
"column": {
"type": "group",
"width": 30,
"activeBgColor": "#000000",
"activeBgOpacity": 0.08
},
}
},
"mount":{
"type": "mount",
"color": color,
"padding": [15,15,0,5],
"xAxis": {
"disableGrid": true,
},
"yAxis": {
"data":[{"min":0}]
},
"legend": {
},
"extra": {
"mount": {
"type": "mount",
"widthRatio": 1.5,
},
}
},
"bar":{
"type": "bar",
"color": color,
"padding": [15,30,0,5],
"xAxis": {
"boundaryGap":"justify",
"disableGrid":false,
"min":0,
"axisLine":false
},
"yAxis": {
},
"legend": {
},
"extra": {
"bar": {
"type": "group",
"width": 30,
"meterBorde": 1,
"meterFillColor": "#FFFFFF",
"activeBgColor": "#000000",
"activeBgOpacity": 0.08
},
}
},
"area":{
"type": "area",
"color": color,
"padding": [15,15,0,15],
"xAxis": {
"disableGrid": true,
},
"yAxis": {
"gridType": "dash",
"dashLength": 2,
},
"legend": {
},
"extra": {
"area": {
"type": "straight",
"opacity": 0.2,
"addLine": true,
"width": 2,
"gradient": false,
"activeType": "hollow"
},
}
},
"radar":{
"type": "radar",
"color": color,
"padding": [5,5,5,5],
"dataLabel": false,
"legend": {
"show": true,
"position": "right",
"lineHeight": 25,
},
"extra": {
"radar": {
"gridType": "radar",
"gridColor": "#CCCCCC",
"gridCount": 3,
"opacity": 0.2,
"max": 200,
"labelShow": true
},
}
},
"gauge":{
"type": "gauge",
"color": color,
"title": {
"name": "66Km/H",
"fontSize": 25,
"color": "#2fc25b",
"offsetY": 50
},
"subtitle": {
"name": "实时速度",
"fontSize": 15,
"color": "#1890ff",
"offsetY": -50
},
"extra": {
"gauge": {
"type": "default",
"width": 30,
"labelColor": "#666666",
"startAngle": 0.75,
"endAngle": 0.25,
"startNumber": 0,
"endNumber": 100,
"labelFormat": "",
"splitLine": {
"fixRadius": 0,
"splitNumber": 10,
"width": 30,
"color": "#FFFFFF",
"childNumber": 5,
"childWidth": 12
},
"pointer": {
"width": 24,
"color": "auto"
}
}
}
},
"candle":{
"type": "candle",
"color": color,
"padding": [15,15,0,15],
"enableScroll": true,
"enableMarkLine": true,
"dataLabel": false,
"xAxis": {
"labelCount": 4,
"itemCount": 40,
"disableGrid": true,
"gridColor": "#CCCCCC",
"gridType": "solid",
"dashLength": 4,
"scrollShow": true,
"scrollAlign": "left",
"scrollColor": "#A6A6A6",
"scrollBackgroundColor": "#EFEBEF"
},
"yAxis": {
},
"legend": {
},
"extra": {
"candle": {
"color": {
"upLine": "#f04864",
"upFill": "#f04864",
"downLine": "#2fc25b",
"downFill": "#2fc25b"
},
"average": {
"show": true,
"name": ["MA5","MA10","MA30"],
"day": [5,10,20],
"color": ["#1890ff","#2fc25b","#facc14"]
}
},
"markLine": {
"type": "dash",
"dashLength": 5,
"data": [
{
"value": 2150,
"lineColor": "#f04864",
"showLabel": true
},
{
"value": 2350,
"lineColor": "#f04864",
"showLabel": true
}
]
}
}
},
"mix":{
"type": "mix",
"color": color,
"padding": [15,15,0,15],
"xAxis": {
"disableGrid": true,
},
"yAxis": {
"disabled": false,
"disableGrid": false,
"splitNumber": 5,
"gridType": "dash",
"dashLength": 4,
"gridColor": "#CCCCCC",
"padding": 10,
"showTitle": true,
"data": []
},
"legend": {
},
"extra": {
"mix": {
"column": {
"width": 20
}
},
}
},
"scatter":{
"type": "scatter",
"color":color,
"padding":[15,15,0,15],
"dataLabel":false,
"xAxis": {
"disableGrid": false,
"gridType":"dash",
"splitNumber":5,
"boundaryGap":"justify",
"min":0
},
"yAxis": {
"disableGrid": false,
"gridType":"dash",
},
"legend": {
},
"extra": {
"scatter": {
},
}
},
"bubble":{
"type": "bubble",
"color":color,
"padding":[15,15,0,15],
"xAxis": {
"disableGrid": false,
"gridType":"dash",
"splitNumber":5,
"boundaryGap":"justify",
"min":0,
"max":250
},
"yAxis": {
"disableGrid": false,
"gridType":"dash",
"data":[{
"min":0,
"max":150
}]
},
"legend": {
},
"extra": {
"bubble": {
"border":2,
"opacity": 0.5,
},
}
}
}
export default cfu;

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,5 @@
# uCharts JSSDK说明
1、如不使用uCharts组件可直接引用u-charts.js打包编译后会`自动压缩`,压缩后体积约为`120kb`
2、如果120kb的体积仍需压缩请手到uCharts官网通过在线定制选择您需要的图表。
3、config-ucharts.js为uCharts组件的用户配置文件升级前请`自行备份config-ucharts.js`文件,以免被强制覆盖。
4、config-echarts.js为ECharts组件的用户配置文件升级前请`自行备份config-echarts.js`文件,以免被强制覆盖。

File diff suppressed because it is too large Load Diff

18
src/components/u-charts/u-charts.min.js vendored Normal file

File diff suppressed because one or more lines are too long

0
src/components/uCharts Normal file
View File

View File

@@ -0,0 +1,16 @@
export function useCount() {
const count = ref(Math.round(Math.random() * 20))
function inc() {
count.value += 1
}
function dec() {
count.value -= 1
}
return {
count,
inc,
dec,
}
}

View File

@@ -0,0 +1,10 @@
import type { MaybeRef } from '@vueuse/core'
export function useQuery(key?: MaybeRef<string>) {
const query = ref<AnyObject>({})
onLoad((q) => {
query.value = q || {}
})
const value = computed(() => (key ? query.value[unref(key)] : null))
return { query, value }
}

1
src/env.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
/// <reference types="vite/client" />

61
src/layouts/home.vue Normal file
View File

@@ -0,0 +1,61 @@
<script setup>
import PrivacyModal from '@/components/PrivacyModel.vue'
const tabbar = ref('index')
const menu = reactive([{ title: '首页', icon: 'home', name: 'index' }, { title: 'AI律师', icon: 'chat', name: 'ai' }, { title: '我的', icon: 'user', name: 'me' }])
function tabChange({ value }) {
uni.switchTab({
url: `/pages/${value}`,
})
}
onShow(() => {
const currentPage = getCurrentPages()[getCurrentPages().length - 1].route
const pageName = currentPage.split('/').pop()
tabbar.value = pageName
})
onMounted(() => {
uni.hideTabBar()
const currentPage = getCurrentPages()[getCurrentPages().length - 1].route
const pageName = currentPage.split('/').pop()
tabbar.value = pageName
})
function toComplaint() {
uni.navigateTo({
url: '/pages/complaint',
})
}
</script>
<script>
export default {
options: {
styleIsolation: 'shared',
},
}
</script>
<template>
<slot />
<view>
<wd-tabbar v-model="tabbar" custom-class="qnc-tabbar" shape="round" safe-area-inset-bottom fixed @change="tabChange">
<wd-tabbar-item v-for="(item, index) in menu" :key="index" :name="item.name" :title="item.title" :icon="item.icon" />
</wd-tabbar>
</view>
<view class="fixed bottom-24 right-4 z-1000 flex items-center rounded-3xl from-red-500 to-red-400 bg-gradient-to-b px-2 py-1 text-center text-white shadow-2xl">
<wd-icon name="warning" class="mr-1" size="18px" />
<view class="text-xs" @click="toComplaint">
投诉
</view>
</view>
<PrivacyModal />
</template>
<style scoped>
:deep(.qnc-tabbar) {
bottom: 16px !important;
}
</style>

31
src/layouts/login.vue Normal file
View File

@@ -0,0 +1,31 @@
<script setup>
function handleClickLeft() {
uni.reLaunch({
url: '/pages/index',
})
}
</script>
<template>
<!-- -->
<view class="h-screen bg-[#EBF1FD]">
<view class="login-layout min-h-full">
<wd-navbar
title="用户登录"
left-arrow
safe-area-inset-top
custom-style="background-color: transparent !important;"
@click-left="handleClickLeft"
/>
<slot />
</view>
</view>
</template>
<style scoped>
.login-layout{
background: url("/static/image/login_bg.png") no-repeat;
background-position: center;
background-size: cover;
}
</style>

35
src/layouts/page.vue Normal file
View File

@@ -0,0 +1,35 @@
<script setup>
import pagesJson from '@/pages.json'
const pagesConfig = pagesJson.pages
const title = ref('')
function getPageTitle() {
const pages = getCurrentPages()
const currentPage = pages[pages.length - 1] // 当前页面
const currentRoute = currentPage.route // 当前页面路径,例如 "pages/authorization"
// 根据路径查找 pages.json 中的配置
const currentPageConfig = pagesConfig.find(page => page.path === currentRoute)
console.log('currentPageConfig', currentPageConfig)
// 返回页面标题,如果未找到,则返回默认标题
return currentPageConfig?.title || ''
}
onLoad(() => {
title.value = getPageTitle()
})
function handleClickLeft() {
uni.navigateBack()
}
</script>
<template>
<wd-navbar :title="title" left-text="返回" placeholder left-arrow safe-area-inset-top fixed @click-left="handleClickLeft" />
<view class="box-border min-h-screen">
<slot />
</view>
</template>
<style scoped>
</style>

11
src/main.ts Normal file
View File

@@ -0,0 +1,11 @@
import { createSSRApp } from 'vue'
import App from './App.vue'
import 'uno.css'
import '@/app.scss'
export function createApp() {
const app = createSSRApp(App)
return {
app,
}
}

109
src/manifest.json Normal file
View File

@@ -0,0 +1,109 @@
{
"name" : "全能查",
"appid" : "__UNI__CC3DA09",
"description" : "",
"versionName" : "1.0.0",
"versionCode" : "101",
"transformPx" : false,
"app-plus" : {
"usingComponents" : true,
"nvueStyleCompiler" : "uni-app",
"compilerVersion" : 3,
"splashscreen" : {
"alwaysShowBeforeRender" : true,
"waiting" : true,
"autoclose" : true,
"delay" : 0
},
"modules" : {
"Payment" : {}
},
"distribute" : {
"android" : {
"permissions" : [
"<uses-permission android:name=\"android.permission.INTERNET\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>"
]
},
"ios" : {
"privacyDescription" : {
"NSLocalNetworkUsageDescription" : "需要访问您的网络来提供更好的服务"
},
"idfa" : false,
"dSYMs" : false
},
"sdkConfigs" : {
"payment" : {
"alipay" : {
"__platform__" : [ "ios", "android" ]
}
},
"ad" : {}
},
"icons" : {
"android" : {
"hdpi" : "src/static/icons/72x72.png",
"xhdpi" : "src/static/icons/96x96.png",
"xxhdpi" : "src/static/icons/144x144.png",
"xxxhdpi" : "src/static/icons/192x192.png"
},
"ios" : {
"appstore" : "src/static/icons/1024x1024.png",
"ipad" : {
"app" : "src/static/icons/76x76.png",
"app@2x" : "src/static/icons/152x152.png",
"notification" : "src/static/icons/20x20.png",
"notification@2x" : "src/static/icons/40x40.png",
"proapp@2x" : "src/static/icons/167x167.png",
"settings" : "src/static/icons/29x29.png",
"settings@2x" : "src/static/icons/58x58.png",
"spotlight" : "src/static/icons/40x40.png",
"spotlight@2x" : "src/static/icons/80x80.png"
},
"iphone" : {
"app@2x" : "src/static/icons/120x120.png",
"app@3x" : "src/static/icons/180x180.png",
"notification@2x" : "src/static/icons/40x40.png",
"notification@3x" : "src/static/icons/60x60.png",
"settings@2x" : "src/static/icons/58x58.png",
"settings@3x" : "src/static/icons/87x87.png",
"spotlight@2x" : "src/static/icons/80x80.png",
"spotlight@3x" : "src/static/icons/120x120.png"
}
}
}
},
"background" : "#000000",
"compatible" : {
"ignoreVersion" : true
}
},
"quickapp" : {},
"mp-weixin" : {
"appid" : "",
"setting" : {
"urlCheck" : false
},
"usingComponents" : true,
"darkmode" : false,
"themeLocation" : "theme.json"
},
"mp-alipay" : {
"usingComponents" : true
},
"mp-baidu" : {
"usingComponents" : true
},
"mp-toutiao" : {
"usingComponents" : true
},
"uniStatistics" : {
"enable" : false
},
"vueVersion" : "3",
"h5" : {
"darkmode" : false,
"themeLocation" : "theme.json"
}
}

131
src/pages.json Normal file
View File

@@ -0,0 +1,131 @@
{
"pages": [
{
"path": "pages/index",
"type": "home",
"layout": "home"
},
{
"path": "pages/ai",
"type": "page",
"layout": "home"
},
{
"path": "pages/authorization",
"type": "page",
"layout": "page",
"title": "授权书"
},
{
"path": "pages/complaint",
"type": "page",
"layout": "page",
"title": "投诉服务"
},
{
"path": "pages/example copy",
"type": "page",
"layout": "page",
"title": "报告示例"
},
{
"path": "pages/example",
"type": "page",
"layout": "page",
"title": "示例报告"
},
{
"path": "pages/inquire",
"type": "page",
"layout": "page",
"title": "报告查询"
},
{
"path": "pages/login",
"type": "page",
"layout": "login",
"title": "登录"
},
{
"path": "pages/me",
"type": "page",
"layout": "home"
},
{
"path": "pages/pay",
"type": "page",
"layout": "page",
"title": "全能查收款"
},
{
"path": "pages/privacyPolicy",
"type": "page",
"layout": "page",
"title": "隐私政策"
},
{
"path": "pages/queryHistory",
"type": "page",
"layout": "page",
"title": "历史报告"
},
{
"path": "pages/result copy",
"type": "page",
"layout": "page",
"title": "报告结果"
},
{
"path": "pages/result",
"type": "page",
"layout": "page",
"title": "报告结果"
},
{
"path": "pages/service",
"type": "page",
"layout": "page",
"title": "客户服务"
},
{
"path": "pages/userAgreement",
"type": "page",
"layout": "page",
"title": "用户协议"
}
],
"globalStyle": {
"backgroundColor": "@bgColor",
"backgroundColorBottom": "@bgColorBottom",
"backgroundColorTop": "@bgColorTop",
"backgroundTextStyle": "@bgTxtStyle",
"navigationBarBackgroundColor": "#000000",
"navigationBarTextStyle": "@navTxtStyle",
"navigationBarTitleText": "全能查",
"navigationStyle": "custom"
},
"tabBar": {
"backgroundColor": "@tabBgColor",
"borderStyle": "@tabBorderStyle",
"color": "@tabFontColor",
"selectedColor": "@tabSelectedColor",
"list": [
{
"pagePath": "pages/index",
"text": "",
"visible": false
},
{
"pagePath": "pages/ai",
"text": "",
"visible": false
},
{
"pagePath": "pages/me",
"text": "",
"visible": false
}
]
},
"subPackages": []
}

72
src/pages/ai.vue Normal file
View File

@@ -0,0 +1,72 @@
<script setup>
import { onMounted, ref } from 'vue'
const userMessage = ref('')
const messages = ref([
{ sender: 'ai', text: '欢迎!请问有什么可以帮助您的吗?' },
])
function sendMessage() {
if (userMessage.value.trim() === '')
return
messages.value.push({ sender: 'user', text: userMessage.value })
// AI 统一回复(中文套话)
setTimeout(() => {
messages.value.push({
sender: 'ai',
text: '感谢您的提问!我们会尽力为您提供帮助。',
})
}, 1000)
userMessage.value = ''
}
const safeAreaTop = ref(44)
onShow(() => {
uni.getSystemInfo({
success: (res) => {
if (res.safeArea && res.safeArea.top) {
safeAreaTop.value = res.safeArea.top // 设置安全区顶部距离
}
},
})
})
</script>
<template>
<view
class="box-border min-h-screen from-blue-100 to-white bg-gradient-to-b" style="paddingTop:44px"
>
<view class="chat-page mx-4 flex flex-col rounded-xl shadow-lg">
<view class="chat-window flex-1 overflow-auto border p-4">
<view v-for="(message, index) in messages" :key="index" class="mb-2">
<view v-if="message.sender === 'ai'" class="inline-block max-w-max rounded-xl bg-white p-2 text-left text-green-600 font-medium shadow-md">
{{ message.text }}
</view>
<view v-else class="ml-auto inline-block max-w-max rounded-xl from-sky-300 via-sky-300 to-sky-300 bg-gradient-to-r p-2 text-right text-white font-medium shadow-md">
{{ message.text }}
</view>
</view>
</view>
<view class="input-area mx-2 flex items-center gap-2 p-4">
<wd-input v-model="userMessage" placeholder="请输入您的问题..." class="flex-1" size="large" />
<wd-button custom-class="shadow" type="primary" @click="sendMessage">
发送
</wd-button>
</view>
</view>
</view>
</template>
<style lang="scss" scoped>
.chat-page {
height: calc(100vh - 108px);
}
</style>
<route lang="json">
{
"layout": "home"
}
</route>

View File

@@ -0,0 +1,54 @@
<script setup>
const webviewStyles = ref({
top: `${uni.getSystemInfoSync().statusBarHeight + 44}px`, // 距离顶部的距离
height: `${uni.getSystemInfoSync().windowHeight - uni.getSystemInfoSync().statusBarHeight - 44}px`, // 高度
position: 'absolute', // 绝对定位
dock: 'bottom', // 停靠在底部
bounce: 'vertical', // 垂直方向的回弹效果
})
const id = ref(null)
function handleMessage(event) {
const data = event.detail.data[0]
if (data.loaded) {
onWebViewLoaded()
}
else if (data.action === 'agreed') {
uni.redirectTo({ url: `/pages/pay?id=${id.value}` })
}
else if (data.action === 'cancelled') {
uni.showModal({
title: '注意',
content: '是否确认取消,退出当前页面',
success(res) {
if (res.confirm) {
uni.navigateBack()
}
},
})
}
}
function onWebViewLoaded() {
}
const src = ref('https://app.quannengcha.com/authorization')
onLoad((option) => {
if (option.id) {
src.value = `${src.value}?id=${encodeURIComponent(option.id)}&token=${encodeURIComponent(uni.getStorageSync('token'))}`
id.value = option.id
}
})
</script>
<template>
<view>
<web-view :webview-styles="webviewStyles" :src="src" @message="handleMessage" />
</view>
</template>
<route lang="json">
{
"layout": "page",
"title": "授权书"
}
</route>

22
src/pages/complaint.vue Normal file
View File

@@ -0,0 +1,22 @@
<script setup>
const webviewStyles = ref({
top: `${uni.getSystemInfoSync().statusBarHeight + 44}px`, // 距离顶部的距离
height: `${uni.getSystemInfoSync().windowHeight - uni.getSystemInfoSync().statusBarHeight - 44}px`, // 高度
position: 'absolute', // 绝对定位
dock: 'bottom', // 停靠在底部
bounce: 'vertical', // 垂直方向的回弹效果
})
</script>
<template>
<view>
<web-view :webview-styles="webviewStyles" src="https://app.quannengcha.com/complaint" />
</view>
</template>
<route lang="json">
{
"layout": "page",
"title": "投诉服务"
}
</route>

204
src/pages/example copy.vue Normal file
View File

@@ -0,0 +1,204 @@
<script setup>
import CBad from '@/ui/CBad.vue'
import CBankLoanApplication from '@/ui/CBankLoanApplication.vue'
import CBankLoanBehavior from '@/ui/CBankLoanBehavior.vue'
import CLawsuit from '@/ui/CLawsuit.vue'
import CRelatedEnterprises from '@/ui/CRelatedEnterprises.vue'
import CSpecialList from '@/ui/CSpecialList.vue'
import CTabs from '@/ui/CTabs.vue'
import { queryExample } from '@/api/apis'
import CMarriage from '@/ui/CMarriage.vue'
const productMap = {
1: '背景调查',
2: '企业报告',
3: '家政服务',
4: '婚姻状态',
5: '贷前背景调查',
6: '租赁服务',
7: '个人风险评估',
}
// 根据 product_id 获取产品名称
function getProductName(productId) {
return productMap[productId] || '未知类型'
}
const productId = ref(null)
const isDone = ref(false)
const entData = ref(null)
const lawsuitData = ref(null)
const badData = ref(null)
const specialData = ref(null)
const bankLoanApplicationData = ref(null)
const marriageData = ref(null)
const bankLoanBehavior = ref(null)
const tabs = ref([
{ label: '报告概述', value: 'overview' },
])
const reportItems = ref([
])
const sortedReportItems = computed(() => {
return reportItems.value.slice().sort((a, b) => a.sort - b.sort)
})
const sortedTabs = computed(() => {
return tabs.value.slice().sort((a, b) => a.sort - b.sort)
})
onLoad((option) => {
console.log('option', option)
const { feature } = option
if (feature) {
queryExample({ feature }).then((res) => {
console.log('res', res)
if (res.code === 200) {
productId.value = res.data.product_id
res.data.query_data.forEach((item) => {
if (item.success) {
switch (item.apiID) {
case 'G09SC02':
marriageData.value = item.data
tabs.value.push({ label: '婚姻状态', value: 'marriage', sort: 1 })
reportItems.value.push({ label: '婚姻状态', value: 'marriage', sort: 1 })
break
case 'G27BJ05':
bankLoanApplicationData.value = item.data
tabs.value.push({ label: '借贷申请记录', value: 'netloan', sort: 7 })
reportItems.value.push({ label: '借贷申请记录', value: 'netloan', sort: 7 })
break
case 'G28BJ05':
bankLoanBehavior.value = item.data
tabs.value.push({ label: '借贷记录', value: 'loan', sort: 6 })
reportItems.value.push({ label: '借贷记录', value: 'loan', sort: 6 })
break
case 'G26BJ05':
specialData.value = item.data
tabs.value.push({ label: '异常名单', value: 'special', sort: 5 })
reportItems.value.push({ label: '异常名单', value: 'special', sort: 5 })
break
case 'G05HZ01':
entData.value = item.data
tabs.value.push({ label: '关联企业', value: 'ent', sort: 4 })
reportItems.value.push({ label: '关联企业', value: 'ent', sort: 4 })
break
case 'G34BJ03':
badData.value = item.data
tabs.value.push({ label: '不良风险评估', value: 'bad', sort: 3 })
reportItems.value.push({ label: '不良风险评估', value: 'bad', sort: 3 })
break
case 'G35SC01':
lawsuitData.value = item.data
tabs.value.push({ label: '涉诉案件', value: 'lawsuit', sort: 2 })
reportItems.value.push({ label: '涉诉案件', value: 'lawsuit', sort: 2 })
break
default:
console.log(`未知的apiID: ${item.apiID}`)
}
}
})
}
}).finally(() => {
isDone.value = true
})
}
})
</script>
<template>
<div class="min-h-full from-blue-100 to-white bg-gradient-to-b">
<CTabs
:tabs="sortedTabs"
type="blue-green"
/>
<template v-if="isDone">
<div class="flex flex-col gap-y-4 p-4 pt-12">
<div id="overview" class="title">
报告概述
</div>
<div class="card">
<div class="flex flex-col gap-y-2">
<div class="flex justify-between">
<span class="text-gray-700 font-bold">报告时间</span>
<span class="text-gray-600">2024年11月18日 23:11:23</span>
</div>
<div class="flex justify-between">
<span class="text-gray-700 font-bold">报告项目</span>
<span class="text-gray-600">{{ getProductName(productId) }}</span>
</div>
</div>
<div>
<LTitle class="my-4" title="报告内容" type="blue-green" />
<div class="flex flex-col gap-y-2">
<div v-for="item in sortedReportItems" :key="item.value" class="flex justify-between">
<span class="text-gray-700 font-bold">{{ item.label }}</span>
<span class="text-green-500 font-bold">已解锁</span>
</div>
</div>
</div>
</div>
<template v-if="marriageData">
<div id="marriage" class="title">
婚姻状态
</div>
<CMarriage :data="marriageData" />
</template>
<template v-if="lawsuitData">
<div id="lawsuit" class="title">
涉诉案件
</div>
<CLawsuit :data="lawsuitData" />
</template>
<template v-if="badData">
<div id="bad" class="title">
不良风险评估
</div>
<CBad :data="badData" />
</template>
<template v-if="entData">
<div id="ent" class="title">
关联企业
</div>
<CRelatedEnterprises :data="entData" />
</template>
<template v-if="specialData">
<div id="special" class="title">
异常名单
</div>
<CSpecialList :data="specialData" />
</template>
<template v-if="bankLoanBehavior">
<div id="loan" class="title">
借贷记录
</div>
<CBankLoanBehavior :data="bankLoanBehavior" />
</template>
<template v-if="bankLoanApplicationData">
<div id="netloan" class="title">
贷款申请记录
</div>
<CBankLoanApplication :data="bankLoanApplicationData" />
</template>
<view class="card">
<view>
<view class="text-blue-500 font-bold">
报告说明
</view>
<view>本报告的数据由用户本人明确授权后我们才向相关合法存有用户个人数据的机构调取本报告相关内容本平台只做大数据的获取与分析仅向用户个人展示参考</view><p> &nbsp; &nbsp; 报告有效期<strong>30</strong>过期自动删除 </p><p> &nbsp; &nbsp; 若您的数据不全面可能是数据具有延迟性或者合作信息机构未获取到您的数据若数据有错误请联系客服</p>
</view>
</view>
</div>
</template>
</div>
</template>
<style lang="scss" scoped>
</style>
<route lang="json">
{
"layout": "page",
"title": "报告示例"
}
</route>

41
src/pages/example.vue Normal file
View File

@@ -0,0 +1,41 @@
<script setup>
const webviewStyles = ref({
top: `${uni.getSystemInfoSync().statusBarHeight + 44}px`, // 距离顶部的距离
height: `${uni.getSystemInfoSync().windowHeight - uni.getSystemInfoSync().statusBarHeight - 44}px`, // 高度
position: 'absolute', // 绝对定位
dock: 'bottom', // 停靠在底部
bounce: 'vertical', // 垂直方向的回弹效果
})
const feature = ref(null)
const token = ref(null)
const webviewSrc = ref('')
onLoad((option) => {
if (option.feature) {
feature.value = option.feature
}
token.value = uni.getStorageSync('token') || ''
const baseUrl = 'https://app.quannengcha.com/example'
webviewSrc.value = `${baseUrl}?feature=${encodeURIComponent(feature.value)}&token=${encodeURIComponent(token.value)}`
})
</script>
<template>
<view>
<!-- 使用动态构造的 WebView src -->
<web-view :webview-styles="webviewStyles" :src="webviewSrc" />
</view>
</template>
<style lang="scss" scoped>
</style>
<route lang="json">
{
"layout": "page",
"title": "示例报告"
}
</route>

114
src/pages/index.vue Normal file
View File

@@ -0,0 +1,114 @@
<script setup>
function toInquire(name) {
uni.navigateTo({
url: `/pages/inquire?feature=${name}`,
})
}
const services = ref([
{ title: '个人风险', name: 'riskassessment', subtitle: '一查全知', bg: '/static/image/index_icon_2.png', bgColor: 'bg-indigo-400', position: 'left' },
{ title: '婚恋风险', name: 'marriage', subtitle: '查婚姻状态让爱无忧', bg: '/static/image/index_icon_1.png', bgColor: ' bg-pink-400 ', position: 'right' },
{ title: '家政服务', name: 'homeservice', subtitle: '用人有保障', bg: '/static/image/index_icon_3.png', bgColor: ' bg-teal-500 ', position: 'left' },
{ title: '租赁风险', name: 'rentalinfo', subtitle: '一查明了', bg: '/static/image/index_icon_4.png', bgColor: ' bg-sky-500 ', position: 'left' },
{ title: '企业报告', name: 'companyinfo', subtitle: '合作更安心', bg: '/static/image/index_icon_5.png', bgColor: ' bg-blue-400 ', position: 'right' },
{ title: '人事背调', name: 'backgroundcheck', subtitle: '选人更放心', bg: '/static/image/index_icon_6.png', bgColor: ' bg-orange-400 ', position: 'left' },
{ title: '贷前调查', name: 'preloanbackgroundcheck', subtitle: '放心借贷', bg: '/static/image/index_icon_7.png', bgColor: ' bg-red-400 ', position: 'right' },
])
const noticeText = ref([])
function toHistory() {
uni.navigateTo({
url: '/pages/queryHistory',
})
}
</script>
<template>
<view class="box-border min-h-screen from-blue-100 to-white bg-gradient-to-b">
<view class="relative h-[190px]">
<image class="h-full w-full" src="/static/image/banner2.png" />
<image
class="absolute bottom-[-70px] right-0 w-38"
src="/static/image/banner_a.png"
mode="aspectFit"
/>
</view>
<view class="relative p-4 pb-4 pt-2">
<view class="mb-1 flex items-center">
<view class="flex-shrink-0 pl-2 font-bold">
在线信息
</view>
<wd-notice-bar
:text="noticeText" direction="vertical" :delay="5" color="#4c4c4c"
background-color="#00000000"
/>
</view>
<view class="grid grid-cols-2 gap-3">
<template v-for="(service, index) in services" :key="index">
<view
class="relative flex flex-col px-4 py-2 shadow-lg" :class="[
service.position === 'left'
? 'rounded-tl-[35px] rounded-bl-[35px] rounded-tr-lg rounded-br-lg'
: 'rounded-tr-[35px] rounded-br-[35px] rounded-tl-lg rounded-bl-lg',
service.bgColor,
service.title === '婚恋风险' ? 'row-span-2' : '',
]" :style="`background: url(${service.bg}) no-repeat; background-size: cover; background-position: center;`"
@click="toInquire(service.name)"
>
<view class="min-h-18 flex flex-col items-start px-1">
<view class="mt-1 max-w-max text-left text-gray-600 font-bold">
{{ service.title }}
</view>
<view class="max-w-max text-left text-xs text-gray-600">
<rich-text :nodes="service.subtitle" />
</view>
<view class="mt-2 rounded-2xl px-2 text-xs text-white" :class="[service.bgColor]">
GO >
</view>
</view>
</view>
</template>
</view>
<view
class="mt-4 box-border h-14 w-full flex items-center rounded-xl bg-white px-4 text-gray-700 shadow-xl"
@click="toHistory"
>
<image
class="mr-4 h-10 w-10"
src="/static/image/bg_icon.png"
mode="widthFix"
/>
<view class="">
<view class="font-bold">
我的历史查询记录
</view>
<view class="text-xs">
查询记录有效期为30天
</view>
</view>
</view>
<view
class="mb-16 mt-6 h-12 w-full flex items-center justify-center rounded-3xl from-blue-500 to-sky-400 bg-gradient-to-b text-center text-lg text-white line-height-12 shadow-xl"
>
<view>全能查邀您共赢共享数据新价值</view>
</view>
</view>
</view>
</template>
<style scoped>
.clip-left {
clip-path: polygon(0 0, 0 100%, 90% 100%, 0 100%);
}
.clip-right {
clip-path: polygon(0 0, 0 0, 90% 100%, 0 0);
}
</style>
<route type="home" lang="json">
{
"layout": "home"
}
</route>

294
src/pages/inquire.vue Normal file
View File

@@ -0,0 +1,294 @@
<script setup>
import { aesEncrypt } from '@/utils/crypto'
import { getCode, getProduct, queryMarriage, querybackgroundCheck, querycompanyInfo, queryhomeService, querypreLoanBackgroundCheck, queryrentalInfo, queryriskAssessment } from '@/api/apis'
const name = ref('')
const idCard = ref('')
const phoneNumber = ref('')
const verificationCode = ref('')
const agreeToTerms = ref(false)
const isCountingDown = ref(false)
const countdown = ref(60)
const feature = ref('')
const timer = null
const featureData = ref({})
const services = reactive([
{ title: '个人风险报告', name: 'riskassessment', subtitle: '一查全知', bg: '/static/image/index_icon_2.png', bgColor: 'bg-indigo-400', api: queryriskAssessment },
{ title: '婚恋报告', name: 'marriage', subtitle: '查婚姻状态让爱无忧', bg: '/static/image/index_icon_1.png', bgColor: ' bg-pink-400 ', api: queryMarriage },
{ title: '家政服务报告', name: 'homeservice', subtitle: '用人有保障', bg: '/static/image/index_icon_3.png', bgColor: ' bg-teal-500 ', api: queryhomeService },
{ title: '租赁服务报告', name: 'rentalinfo', subtitle: '一查明了', bg: '/static/image/index_icon_4.png', bgColor: ' bg-sky-500 ', api: queryrentalInfo },
{ title: '贷前调查报告', name: 'preloanbackgroundcheck', subtitle: '放心借贷', bg: '/static/image/index_icon_7.png', bgColor: ' bg-red-400 ', api: querypreLoanBackgroundCheck },
{ title: '人事背调报告', name: 'backgroundcheck', subtitle: '选人更放心', bg: '/static/image/index_icon_6.png', bgColor: ' bg-orange-400 ', api: querybackgroundCheck },
{ title: '企业报告', name: 'companyinfo', subtitle: '合作更安心', bg: '/static/image/index_icon_5.png', bgColor: ' bg-blue-400 ', api: querycompanyInfo },
])
const service = ref({})
onLoad((options) => {
console.log('options', options)
if (options.feature) {
feature.value = options.feature
}
else {
feature.value = 'marrige'
}
getService()
getProduct(feature.value).then((res) => {
if (res.code === 200) {
featureData.value = res.data
}
})
})
const isPhoneNumberValid = computed(() => {
return /^1[3-9]\d{9}$/.test(phoneNumber.value)
})
const isIdCardValid = computed(() => /^\d{17}[\dX]$/i.test(idCard.value))
function handleSubmit() {
if (!agreeToTerms.value) {
uni.showToast({ title: '请阅读并同意用户协议和隐私政策', icon: 'none' })
return
}
if (!name.value) {
uni.showToast({ title: '请输入姓名', icon: 'none' })
return
}
if (!isPhoneNumberValid.value) {
uni.showToast({ title: '请输入有效的手机号', icon: 'none' })
return
}
if (!isIdCardValid.value) {
uni.showToast({ title: '请输入有效的身份证号码', icon: 'none' })
return
}
if (!verificationCode.value) {
uni.showToast({ title: '请输入验证码', icon: 'none' })
return
}
submit()
}
function getService() {
for (const i of services) {
if (i.name === feature.value) {
service.value = i
}
}
}
function sendVerificationCode() {
if (isCountingDown.value || !isPhoneNumberValid.value)
return
if (!isPhoneNumberValid.value) {
uni.showToast({ title: '请输入有效的手机号', icon: 'none' })
return
}
getCode({
mobile: phoneNumber.value,
actionType: 'query',
}).then((res) => {
if (res.code === 200) {
uni.showToast({ title: '获取成功', icon: 'none' })
startCountdown()
}
})
}
function startCountdown() {
isCountingDown.value = true
countdown.value = 60
timer = setInterval(() => {
if (countdown.value > 0) {
countdown.value--
}
else {
clearInterval(timer)
isCountingDown.value = false
}
}, 1000)
}
function toExample() {
uni.navigateTo({
url: `/pages/example?feature=${feature.value}`,
})
}
function submit() {
const req = {
name: name.value,
id_card: idCard.value,
mobile: phoneNumber.value,
code: verificationCode.value,
}
const data = JSON.stringify(req)
const encodeData = aesEncrypt(data, 'ff83609b2b24fc73196aac3d3dfb874f')
service.value.api({ data: encodeData }).then((res) => {
if (res.code === 200) {
uni.navigateTo({
url: `/pages/authorization?id=${res.data.id}`,
})
}
})
}
function toUserAgreement() {
uni.navigateTo({
url: '/pages/userAgreement',
})
}
function toPrivacyPolicy() {
uni.navigateTo({
url: '/pages/privacyPolicy',
})
}
onUnmounted(() => {
if (timer) {
clearInterval(timer)
}
})
</script>
<template>
<view class="inquire-bg min-h-screen rounded-lg p-6 shadow-lg">
<view class="mb-6 text-center text-blue-800 font-extrabold">
<view class="text-blue-600">
<text class="text-2xl font-bold">
{{ service.title }}
</text>
</view>
</view>
<view class="card-p-0 px-4 py-6">
<view class="mb-4 text-xl text-gray-800 font-semibold">
基本信息
</view>
<wd-input
v-model="name" label="姓名" type="text" label-width="60px" placeholder="请输入正确的姓名"
class="mb-6 border-b border-gray-200 border-b-solid"
/>
<wd-input
v-model="idCard" label="身份证号" label-width="60px" placeholder="请输入准确的身份证号码"
class="mb-6 border-b border-gray-200 border-b-solid"
/>
<wd-input
v-model="phoneNumber" label="手机号" type="tel" label-width="60px" placeholder="输入手机号"
class="mb-6 border-b border-gray-200 border-b-solid"
/>
<view class="mb-6 flex items-center">
<wd-input
v-model="verificationCode" label="验证码" type="number" label-width="60px" placeholder="输入验证码"
class="flex-1 border-b border-gray-200 border-b-solid"
/>
<view
class="ml-2 rounded-lg border-none px-2 py-2 text-sm font-bold outline-none ring-none transition duration-300"
:class="isCountingDown || !isPhoneNumberValid ? 'cursor-not-allowed bg-gray-300 text-gray-500' : 'bg-blue-500 text-white hover:bg-blue-600'"
@click="sendVerificationCode"
>
{{ isCountingDown ? `${countdown}s重新获取` : '获取验证码' }}
</view>
</view>
<view class="mb-6 flex items-center">
<wd-checkbox v-model="agreeToTerms" />
<view class="ml-1 text-xs text-gray-400">
我已阅读并同意<text class="text-blue-500 hover:underline" @click="toUserAgreement">
用户协议
</text><text class="text-blue-500 hover:underline" @click="toPrivacyPolicy">
隐私政策
</text>
</view>
</view>
<view class="flex">
<wd-button
custom-style="border-top-right-radius: 0;
border-bottom-right-radius: 0;" plain class="w-10 py-3 text-lg font-bold" @click="toExample"
>
示例报告
</wd-button>
<wd-button
custom-style="border-top-left-radius: 0;
border-bottom-left-radius: 0;" type="primary" class="flex-1 py-3 text-lg font-bold" @click="handleSubmit"
>
立即查询 {{ featureData.sell_price }}
</wd-button>
</view>
</view>
<wd-divider class="my-4" />
<view class="card">
<!-- 报告标题 -->
<view class="mb-6 text-xl text-gray-800 font-bold">
{{ featureData.product_name }}
</view>
<!-- 报告介绍 -->
<view class="mb-4 text-gray-600 leading-relaxed">
{{ featureData.description }}
</view>
<!-- 报价信息 -->
<view class="mb-6 flex items-center justify-between">
<view class="text-lg text-gray-500">
价格
</view>
<view class="text-lg text-blue-600 font-semibold">
¥{{ featureData.sell_price }}
</view>
</view>
<!-- 报告主要内容 -->
<view class="mb-4 text-lg text-gray-800 font-semibold">
报告主要内容
</view>
<view class="grid grid-cols-2 gap-4">
<view
v-for="(feature, index) in featureData.features"
:key="feature.id"
class="rounded-lg py-2 text-center text-sm text-gray-700 font-medium"
:class="[
(Math.floor(index / 2) + (index % 2)) % 2 === 0
? 'bg-gradient-to-r from-blue-200 via-blue-200 to-blue-100'
: 'bg-gradient-to-r from-sky-200 via-sky-200 to-sky-100',
]"
>
{{ feature.name }}
</view>
</view>
</view>
</view>
</template>
<style scoped>
.icon-company,
.icon-transaction,
.icon-judicial,
.icon-penalty {
font-size: 2rem;
}
.inquire-bg {
background: url("/static/image/bg_2.png") no-repeat;
position: relative;
}
.inquire-bg::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(255, 255, 255, 0.4);
/* 使用白色的半透明覆盖层0.5 可调整为其他透明度值 */
z-index: 1;
}
.inquire-bg>* {
position: relative;
z-index: 2;
/* 确保子元素在覆盖层之上 */
}
</style>
<route lang="json">
{
"layout": "page",
"title": "报告查询"
}
</route>

203
src/pages/login.vue Normal file
View File

@@ -0,0 +1,203 @@
<script setup>
import { getCode, login } from '@/api/apis'
const phoneNumber = ref('')
const verificationCode = ref('')
const password = ref('')
const isPasswordLogin = ref(false)
const isAgreed = ref(false)
const isCountingDown = ref(false)
const countdown = ref(60)
let timer = null
// 聚焦状态变量
const phoneFocused = ref(false)
const codeFocused = ref(false)
const passwordFocused = ref(false)
const isPhoneNumberValid = computed(() => {
return /^1[3-9]\d{9}$/.test(phoneNumber.value)
})
const canLogin = computed(() => {
if (!isPhoneNumberValid.value)
return false
if (isPasswordLogin.value) {
return password.value.length >= 6
}
else {
return verificationCode.value.length === 6
}
})
function sendVerificationCode() {
if (isCountingDown.value || !isPhoneNumberValid.value)
return
if (!isPhoneNumberValid.value) {
uni.showToast({ title: '请输入有效的手机号', icon: 'none' })
return
}
getCode({
mobile: phoneNumber.value,
actionType: 'login',
}).then((res) => {
if (res.code === 200) {
uni.showToast({ title: '获取成功', icon: 'none' })
startCountdown()
}
})
}
function startCountdown() {
isCountingDown.value = true
countdown.value = 60
timer = setInterval(() => {
if (countdown.value > 0) {
countdown.value--
}
else {
clearInterval(timer)
isCountingDown.value = false
}
}, 1000)
}
function handleLogin() {
if (!canLogin.value) {
uni.showToast({ title: '请完善信息', icon: 'none' })
return
}
if (!isAgreed.value) {
uni.showToast({ title: '请先同意用户协议', icon: 'none' })
return
}
login({ mobile: phoneNumber.value, code: verificationCode.value }).then((res) => {
console.log('res.data.AccessToken', res.data.accessToken)
if (res.code === 200) {
uni.setStorageSync('token', res.data.accessToken)
uni.showToast({ title: '登录成功', icon: 'none' })
uni.reLaunch({
url: '/pages/index',
})
}
else {
uni.showToast({ title: res.msg, icon: 'none' })
}
})
}
function toUserAgreement() {
uni.navigateTo({
url: '/pages/userAgreement',
})
}
function toPrivacyPolicy() {
uni.navigateTo({
url: '/pages/privacyPolicy',
})
}
onUnmounted(() => {
if (timer) {
clearInterval(timer)
}
})
</script>
<template>
<view class="login px-8">
<view class="mb-8 pt-8 text-left">
<view class="flex flex-col items-center">
<image
class="h-18 w-18 rounded-full shadow"
src="/static/image/logo.png"
mode="scaleToFill"
/>
<image
class="mt-4 h-10"
src="/static/image/logo_title.png"
mode="aspectFit"
/>
</view>
</view>
<view class="space-y-5">
<view class="input-container bg-blue-300/20" :class="[phoneFocused ? 'focused' : '']">
<input
v-model="phoneNumber" class="input-field" type="number" placeholder="请输入手机号" maxlength="11"
@focus="phoneFocused = true" @blur="phoneFocused = false"
>
</view>
<view v-if="!isPasswordLogin">
<view class="flex items-center justify-between">
<view class="input-container bg-blue-300/20" :class="[codeFocused ? 'focused' : '']">
<input
v-model="verificationCode" class="input-field" type="number" placeholder="请输入验证码" maxlength="6"
@focus="codeFocused = true" @blur="codeFocused = false"
>
</view>
<view
class="ml-2 rounded-lg px-4 py-2 text-sm font-bold transition duration-300 focus:outline-none"
:class="isCountingDown || !isPhoneNumberValid ? 'cursor-not-allowed bg-gray-300 text-gray-500' : 'bg-blue-500 text-white hover:bg-blue-600'"
@click="sendVerificationCode"
>
{{ isCountingDown ? `${countdown}s重新获取` : '获取验证码' }}
</view>
</view>
</view>
<view v-if="isPasswordLogin" class="input-container" :class="[passwordFocused ? 'focused' : '']">
<input
v-model="password" class="input-field" type="password" placeholder="请输入密码"
@focus="passwordFocused = true" @blur="passwordFocused = false"
>
</view>
<view class="flex items-start space-x-2">
<wd-checkbox v-model="isAgreed" class="mt-1" />
<text class="text-xs text-gray-400 leading-tight">
未注册手机号登录后将自动生成账号并且代表您已阅读并同意
<text class="cursor-pointer text-blue-400" @click="toUserAgreement">
用户协议
</text>
<text class="cursor-pointer text-blue-400" @click="toPrivacyPolicy">
隐私政策
</text>
</text>
</view>
</view>
<button
class="mt-20 block w-full flex-shrink-0 rounded-full bg-blue-500 py-3 text-lg text-white font-bold transition duration-300"
@click="handleLogin"
>
登录
</button>
</view>
</template>
<style scoped>
.login{
}
.input-container {
border: 2px solid rgba(125, 211, 252, 0.0);
border-radius: 1rem;
@apply transition duration-200
}
.input-container.focused {
border: 2px solid #3b82f6;
}
.input-field {
width: 100%;
padding: 1rem;
transition: border-color 0.3s ease;
outline: none;
background: transparent;
}
</style>
<route lang="json">
{
"layout": "login",
"title": "登录"
}
</route>

125
src/pages/me.vue Normal file
View File

@@ -0,0 +1,125 @@
<script setup>
import { getUserInfo } from '@/api/apis'
const userName = ref('点击登录')
const userAvatar = ref('https://img0.baidu.com/it/u=1240274933,2284862568&fm=253&fmt=auto&app=138&f=PNG?w=180&h=180')
const isLoggedIn = ref(false)
const features = ref([
{ title: '我的报告', icon: 'list', action: () => toHistory() },
{ title: '联系客服', icon: 'service', action: () => toService() },
{ title: '用户协议', icon: 'file', action: () => toUserAgreement() },
{ title: '退出登录', icon: 'logout', action: () => handleLogout() },
])
function toHistory() {
uni.navigateTo({
url: '/pages/queryHistory',
})
}
function toUserAgreement() {
uni.navigateTo({
url: '/pages/userAgreement',
})
}
function redirectToLogin() {
uni.reLaunch({ url: '/pages/login' }) // 使用 uni-app 路由跳转到登录页
}
function handleLogout() {
uni.removeStorageSync('token')
isLoggedIn.value = false
userName.value = '点击登录'
userAvatar.value = 'https://img0.baidu.com/it/u=1240274933,2284862568&fm=253&fmt=auto&app=138&f=PNG?w=180&h=180'
}
function toService() {
uni.navigateTo({
url: '/pages/service',
})
}
async function fetchUserInfo() {
try {
// 假设通过 API 获取用户信息
getUserInfo().then((res) => {
if (res.code === 200) {
console.log('res', res)
const userinfo = res.data.userInfo
userName.value = userinfo.nickName || ''
userAvatar.value = userinfo.userAvatar || 'https://img0.baidu.com/it/u=1240274933,2284862568&fm=253&fmt=auto&app=138&f=PNG?w=180&h=180'
isLoggedIn.value = true
}
})
}
catch (error) {
console.error('获取用户信息失败', error)
}
}
const safeAreaTop = ref(0)
onMounted(() => {
const token = uni.getStorageSync('token')
if (token) {
isLoggedIn.value = true
fetchUserInfo()
}
else {
isLoggedIn.value = false
}
uni.getSystemInfo({
success: (res) => {
if (res.safeArea) {
safeAreaTop.value = res.safeArea.top
}
},
})
})
</script>
<template>
<view
class="box-border min-h-screen from-blue-100 to-white bg-gradient-to-b" style="paddingTop:44px"
>
<view class="flex flex-col p-4">
<view class="profile-section mb-4 flex items-center gap-4 rounded-md bg-white p-4 shadow-md" @click="!isLoggedIn ? redirectToLogin() : null">
<wd-img :src="userAvatar" round width="100" height="100" />
<view>
<h2 class="text-lg font-bold">
{{ isLoggedIn ? userName : '点击登录' }}
</h2>
</view>
</view>
<Wdviewider />
<view class="features-section flex flex-col gap-2">
<WdCell
v-for="(feature, index) in features"
:key="index"
:title="feature.title"
:icon="feature.icon"
class="feature-item rounded-md bg-white p-3 shadow-sm"
clickable
@click="feature.action"
/>
</view>
</view>
</view>
</template>
<style lang="scss" scoped>
.profile-section {
@apply flex items-center gap-4 p-4 bg-white rounded-md shadow-md mb-4;
}
.features-section {
@apply flex flex-col gap-2;
}
.feature-item {
@apply bg-white p-3 rounded-md shadow-sm;
}
</style>
<route lang="json">
{
"layout": "home"
}
</route>

98
src/pages/pay.vue Normal file
View File

@@ -0,0 +1,98 @@
<script setup>
import { payment, queryProvisionalOrder } from '@/api/apis'
const selectedPaymentMethod = ref('alipay')
const id = ref(null)
const order = ref({
productName: '',
price: null,
})
function handlePayment() {
if (selectedPaymentMethod.value === 'alipay') {
payment({ id: id.value, pay_method: selectedPaymentMethod.value }).then((res) => {
if (res.code === 200) {
uni.requestPayment({
provider: 'alipay', // 支付宝
orderInfo: res.data.prepay_id, // 后台返回的orderInfo
success: () => {
handlePaySuccess(res.data.order_id)
},
fail: (err) => {
console.log('支付失败:', err)
},
})
}
})
}
}
function handlePaySuccess(orderID) {
uni.redirectTo({
url: `/pages/result?id=${orderID}`,
})
}
onLoad((option) => {
if (option.id) {
id.value = option.id
queryProvisionalOrder(option.id).then((res) => {
console.log('res', res)
if (res.code === 200) {
order.value.productName = res.data.product.product_name
order.value.price = res.data.product.sell_price
}
})
}
})
</script>
<template>
<view class="min-h-screen from-blue-200 via-sky-200 to-sky-100 bg-gradient-to-b p-6">
<view class="card">
<h1 class="mb-4 text-xl font-bold">
订单支付
</h1>
<view class="my-10 text-center">
<view class="text-2xl font-bold">
¥{{ order.price }}
</view>
<view class="text-gray-600">
{{ order.productName }}
</view>
</view>
<view class="mb-4">
<label class="mb-2 block text-sm text-gray-600">支付方式</label>
<wd-radio-group v-model="selectedPaymentMethod" shape="dot" size="large">
<view class="border-3 border-blue-500 rounded-lg border-solid px-4 py-2">
<wd-radio value="alipay">
<view class="flex" items-center>
<image
src="/static/image/alipay_icon.svg"
mode="aspectFit"
class="mr-1 h-5 w-5"
/> 支付宝
</view>
</wd-radio>
</view>
</wd-radio-group>
</view>
<button
class="w-full rounded-xl from-blue-500 via-blue-500 to-blue-400 bg-gradient-to-b px-4 py-2 text-white"
@click="handlePayment"
>
立即支付
</button>
</view>
</view>
</template>
<style scoped>
:deep(.wd-radio){
margin-top: 0;
}
</style>
<route lang="json">
{
"layout": "page",
"title": "全能查收款"
}
</route>

View File

@@ -0,0 +1,22 @@
<script setup>
const webviewStyles = ref({
top: `${uni.getSystemInfoSync().statusBarHeight + 44}px`, // 距离顶部的距离
height: `${uni.getSystemInfoSync().windowHeight - uni.getSystemInfoSync().statusBarHeight - 44}px`, // 高度
position: 'absolute', // 绝对定位
dock: 'bottom', // 停靠在底部
bounce: 'vertical', // 垂直方向的回弹效果
})
</script>
<template>
<view>
<web-view :webview-styles="webviewStyles" src="https://app.quannengcha.com/privacyPolicy" @message="handleMessage" />
</view>
</template>
<route lang="json">
{
"layout": "page",
"title": "隐私政策"
}
</route>

156
src/pages/queryHistory.vue Normal file
View File

@@ -0,0 +1,156 @@
<script setup>
import { onLoad, onReachBottom } from '@dcloudio/uni-app'
import { queryList } from '@/api/apis'
// 定义字典映射 id 和 product_name
const productMap = {
1: '背景调查',
2: '企业报告',
3: '家政服务',
4: '婚姻状态',
5: '贷前背景调查',
6: '租赁服务',
7: '个人风险评估',
}
const page = ref(1)
const pageSize = ref(10)
const total = ref(0)
const reportList = ref([])
const loadingState = ref('loading')
const num = ref(0)
const max = ref(60)
// 初始加载数据
function fetchData() {
queryList({ page: page.value, page_size: pageSize.value }).then((res) => {
if (res.code === 200) {
total.value = res.data.total
if (res.data.list && res.data.list.length > 0) {
reportList.value.push(...res.data.list)
page.value += 1
}
if (reportList.value.length >= total.value) {
loadingState.value = 'finished'
}
else {
loadingState.value = 'loading'
}
}
})
}
// 根据 product_id 获取产品名称
function getProductName(productId) {
return productMap[productId] || '未知类型'
}
// 初始加载
onLoad(() => {
fetchData()
})
// 下拉触底加载更多
onReachBottom(() => {
if (loadingState.value !== 'finished') {
if (num.value >= max.value) {
loadingState.value = 'finished'
}
else {
fetchData()
}
}
})
function toDetail(item) {
if (item.query_state !== 'success')
return
uni.navigateTo({
url: `/pages/result?id=${item.order_id}`,
})
}
// 状态文字映射
function stateText(state) {
switch (state) {
case 'pending':
return '查询中'
case 'success':
return '查询成功'
case 'failed':
return '查询失败'
default:
return '未知状态'
}
}
// 状态颜色映射
function statusClass(state) {
switch (state) {
case 'pending':
return 'status-pending'
case 'success':
return 'status-success'
case 'failed':
return 'status-failed'
default:
return ''
}
}
</script>
<template>
<wd-notice-bar
text="为保证用户的隐私以及数据安全您的报告生成30天之后将自动清除请及时保存您的报告。" prefix="warn-bold" color="#007aff"
background-color="#f8f8f8"
/>
<view class="flex flex-col gap-4 p-4">
<view v-for="item in reportList" :key="item.id" class="card flex flex-col gap-2" @click="toDetail(item)">
<view class="flex items-center justify-between">
<view class="">
状态:
</view>
<view class="rounded-xl px-2 py-1" :class="[statusClass(item.query_state)]">
{{ stateText(item.query_state) }}
</view>
</view>
<view class="flex items-center justify-between">
<view class="">
报告类型
</view>
<view>
{{ getProductName(item.product_id) }}
</view>
</view>
<view class="flex items-center justify-between">
<view class="">
查询时间:
</view>
<view>
{{ item.create_time }}
</view>
</view>
</view>
<!-- 加载更多 -->
<wd-loadmore :state="loadingState" @reload="fetchData" />
</view>
</template>
<style lang="scss" scoped>
.status-pending {
@apply bg-yellow-100 text-yellow-600;
}
.status-success {
@apply bg-green-100 text-green-600;
}
.status-failed {
@apply bg-red-100 text-red-600;
}
</style>
<route lang="json">
{
"layout": "page",
"title": "历史报告"
}
</route>

204
src/pages/result copy.vue Normal file
View File

@@ -0,0 +1,204 @@
<script setup>
import CBad from '@/ui/CBad.vue'
import CBankLoanApplication from '@/ui/CBankLoanApplication.vue'
import CBankLoanBehavior from '@/ui/CBankLoanBehavior.vue'
import CLawsuit from '@/ui/CLawsuit.vue'
import CRelatedEnterprises from '@/ui/CRelatedEnterprises.vue'
import CSpecialList from '@/ui/CSpecialList.vue'
import CTabs from '@/ui/CTabs.vue'
import { queryResultByOrder } from '@/api/apis'
import CMarriage from '@/ui/CMarriage.vue'
const productMap = {
1: '背景调查',
2: '企业报告',
3: '家政服务',
4: '婚姻状态',
5: '贷前背景调查',
6: '租赁服务',
7: '个人风险评估',
}
// 根据 product_id 获取产品名称
function getProductName(productId) {
return productMap[productId] || '未知类型'
}
const productId = ref(null)
const isDone = ref(false)
const entData = ref(null)
const lawsuitData = ref(null)
const badData = ref(null)
const specialData = ref(null)
const bankLoanApplicationData = ref(null)
const marriageData = ref(null)
const bankLoanBehavior = ref(null)
const tabs = ref([
{ label: '报告概述', value: 'overview' },
])
const reportItems = ref([
])
const sortedReportItems = computed(() => {
return reportItems.value.slice().sort((a, b) => a.sort - b.sort)
})
const sortedTabs = computed(() => {
return tabs.value.slice().sort((a, b) => a.sort - b.sort)
})
onLoad((option) => {
console.log('option', option)
const { id } = option
if (id) {
queryResultByOrder(id).then((res) => {
console.log('res', res)
if (res.code === 200) {
productId.value = res.data.product_id
res.data.query_data.forEach((item) => {
if (item.success) {
switch (item.apiID) {
case 'G09SC02':
marriageData.value = item.data
tabs.value.push({ label: '婚姻状态', value: 'marriage', sort: 1 })
reportItems.value.push({ label: '婚姻状态', value: 'marriage', sort: 1 })
break
case 'G27BJ05':
bankLoanApplicationData.value = item.data
tabs.value.push({ label: '借贷申请记录', value: 'netloan', sort: 7 })
reportItems.value.push({ label: '借贷申请记录', value: 'netloan', sort: 7 })
break
case 'G28BJ05':
bankLoanBehavior.value = item.data
tabs.value.push({ label: '借贷记录', value: 'loan', sort: 6 })
reportItems.value.push({ label: '借贷记录', value: 'loan', sort: 6 })
break
case 'G26BJ05':
specialData.value = item.data
tabs.value.push({ label: '异常名单', value: 'special', sort: 5 })
reportItems.value.push({ label: '异常名单', value: 'special', sort: 5 })
break
case 'G05HZ01':
entData.value = item.data
tabs.value.push({ label: '关联企业', value: 'ent', sort: 4 })
reportItems.value.push({ label: '关联企业', value: 'ent', sort: 4 })
break
case 'G34BJ03':
badData.value = item.data
tabs.value.push({ label: '不良风险评估', value: 'bad', sort: 3 })
reportItems.value.push({ label: '不良风险评估', value: 'bad', sort: 3 })
break
case 'G35SC01':
lawsuitData.value = item.data
tabs.value.push({ label: '涉诉案件', value: 'lawsuit', sort: 2 })
reportItems.value.push({ label: '涉诉案件', value: 'lawsuit', sort: 2 })
break
default:
console.log(`未知的apiID: ${item.apiID}`)
}
}
})
}
}).finally(() => {
isDone.value = true
})
}
})
</script>
<template>
<div class="min-h-full from-blue-100 to-white bg-gradient-to-b">
<CTabs
:tabs="sortedTabs"
type="blue-green"
/>
<template v-if="isDone">
<div class="flex flex-col gap-y-4 p-4 pt-12">
<div id="overview" class="title">
报告概述
</div>
<div class="card">
<div class="flex flex-col gap-y-2">
<div class="flex justify-between">
<span class="text-gray-700 font-bold">报告时间</span>
<span class="text-gray-600">2024年11月18日 23:11:23</span>
</div>
<div class="flex justify-between">
<span class="text-gray-700 font-bold">报告项目</span>
<span class="text-gray-600">{{ getProductName(productId) }}</span>
</div>
</div>
<div>
<LTitle class="my-4" title="报告内容" type="blue-green" />
<div class="flex flex-col gap-y-2">
<div v-for="item in sortedReportItems" :key="item.value" class="flex justify-between">
<span class="text-gray-700 font-bold">{{ item.label }}</span>
<span class="text-green-500 font-bold">已解锁</span>
</div>
</div>
</div>
</div>
<template v-if="marriageData">
<div id="marriage" class="title">
婚姻状态
</div>
<CMarriage :data="marriageData" />
</template>
<template v-if="lawsuitData">
<div id="lawsuit" class="title">
涉诉案件
</div>
<CLawsuit :data="lawsuitData" />
</template>
<template v-if="badData">
<div id="bad" class="title">
不良风险评估
</div>
<CBad :data="badData" />
</template>
<template v-if="entData">
<div id="ent" class="title">
关联企业
</div>
<CRelatedEnterprises :data="entData" />
</template>
<template v-if="specialData">
<div id="special" class="title">
异常名单
</div>
<CSpecialList :data="specialData" />
</template>
<template v-if="bankLoanBehavior">
<div id="loan" class="title">
借贷记录
</div>
<CBankLoanBehavior :data="bankLoanBehavior" />
</template>
<template v-if="bankLoanApplicationData">
<div id="netloan" class="title">
贷款申请记录
</div>
<CBankLoanApplication :data="bankLoanApplicationData" />
</template>
<view class="card">
<view>
<view>
报告说明
</view>
<view>本报告的数据由用户本人明确授权后我们才向相关合法存有用户个人数据的机构调取本报告相关内容本平台只做大数据的获取与分析仅向用户个人展示参考</view><p> &nbsp; &nbsp; 报告有效期<strong>30</strong>过期自动删除 </p><p> &nbsp; &nbsp; 若您的数据不全面可能是数据具有延迟性或者合作信息机构未获取到您的数据若数据有错误请联系客服</p>
</view>
</view>
</div>
</template>
</div>
</template>
<style lang="scss" scoped>
</style>
<route lang="json">
{
"layout": "page",
"title": "报告结果"
}
</route>

40
src/pages/result.vue Normal file
View File

@@ -0,0 +1,40 @@
<script setup>
const webviewStyles = ref({
top: `${uni.getSystemInfoSync().statusBarHeight + 44}px`, // 距离顶部的距离
height: `${uni.getSystemInfoSync().windowHeight - uni.getSystemInfoSync().statusBarHeight - 44}px`, // 高度
position: 'absolute', // 绝对定位
dock: 'bottom', // 停靠在底部
bounce: 'vertical', // 垂直方向的回弹效果
})
const orderId = ref(null)
const token = ref(null)
const webviewSrc = ref('')
onLoad((option) => {
if (option.id) {
orderId.value = option.id
}
token.value = uni.getStorageSync('token') || ''
const baseUrl = 'https://app.quannengcha.com/report'
webviewSrc.value = `${baseUrl}?order_id=${encodeURIComponent(orderId.value)}&token=${encodeURIComponent(token.value)}`
})
</script>
<template>
<view>
<web-view :webview-styles="webviewStyles" :src="webviewSrc" />
</view>
</template>
<style lang="scss" scoped>
</style>
<route lang="json">
{
"layout": "page",
"title": "报告结果"
}
</route>

22
src/pages/service.vue Normal file
View File

@@ -0,0 +1,22 @@
<script setup>
const webviewStyles = ref({
top: `${uni.getSystemInfoSync().statusBarHeight + 44}px`, // 距离顶部的距离
height: `${uni.getSystemInfoSync().windowHeight - uni.getSystemInfoSync().statusBarHeight - 44}px`, // 高度
position: 'absolute', // 绝对定位
dock: 'bottom', // 停靠在底部
bounce: 'vertical', // 垂直方向的回弹效果
})
</script>
<template>
<view>
<web-view :webview-styles="webviewStyles" src="https://app.quannengcha.com/service" />
</view>
</template>
<route lang="json">
{
"layout": "page",
"title": "客户服务"
}
</route>

View File

@@ -0,0 +1,22 @@
<script setup>
const webviewStyles = ref({
top: `${uni.getSystemInfoSync().statusBarHeight + 44}px`, // 距离顶部的距离
height: `${uni.getSystemInfoSync().windowHeight - uni.getSystemInfoSync().statusBarHeight - 44}px`, // 高度
position: 'absolute', // 绝对定位
dock: 'bottom', // 停靠在底部
bounce: 'vertical', // 垂直方向的回弹效果
})
</script>
<template>
<view>
<web-view :webview-styles="webviewStyles" src="https://app.quannengcha.com/userAgreement" />
</view>
</template>
<route lang="json">
{
"layout": "page",
"title": "用户协议"
}
</route>

6
src/shims.d.ts vendored Normal file
View File

@@ -0,0 +1,6 @@
export {}
declare module 'vue' {
type Hooks = App.AppInstance & Page.PageInstance
interface ComponentCustomOptions extends Hooks {}
}

23
src/static/app-plus/echarts.min.js vendored Normal file

File diff suppressed because one or more lines are too long

23
src/static/h5/echarts.min.js vendored Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
src/static/icons/20x20.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 884 B

BIN
src/static/icons/29x29.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
src/static/icons/40x40.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
src/static/icons/58x58.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
src/static/icons/60x60.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
src/static/icons/72x72.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

BIN
src/static/icons/76x76.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

BIN
src/static/icons/80x80.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

BIN
src/static/icons/87x87.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
src/static/icons/96x96.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1732336609573" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5954" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><path d="M860.16 0C950.272 0 1024 73.889684 1024 164.163368v531.509895s-32.768-4.122947-180.224-53.355789c-40.96-14.362947-96.256-34.896842-157.696-57.478737 36.864-63.595789 65.536-137.485474 86.016-215.444211h-202.752v-71.841684h247.808V256.512h-247.808V135.437474h-100.352c-18.432 0-18.432 18.458947-18.432 18.458947v104.663579H200.704v41.040842h249.856v69.793684H243.712v41.013895H645.12c-14.336 51.307789-34.816 98.519579-57.344 141.608421-129.024-43.115789-268.288-77.985684-356.352-55.403789-55.296 14.362947-92.16 38.992842-112.64 63.595789-96.256 116.978526-26.624 295.504842 176.128 295.504842 120.832 0 237.568-67.718737 327.68-178.526316C757.76 742.858105 1024 853.692632 1024 853.692632v6.144C1024 950.110316 950.272 1024 860.16 1024H163.84C73.728 1024 0 950.137263 0 859.836632V164.163368C0 73.889684 73.728 0 163.84 0h696.32zM268.126316 553.121684c93.049263-10.374737 180.062316 26.974316 283.270737 78.874948-74.886737 95.501474-165.941895 155.701895-256.970106 155.701894-157.830737 0-204.368842-126.652632-125.466947-197.200842 26.300632-22.851368 72.838737-35.301053 99.166316-37.376z" fill="#00A0EA" p-id="5955"></path></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 KiB

BIN
src/static/image/bg_2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 507 KiB

BIN
src/static/image/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

26
src/theme.json Normal file
View File

@@ -0,0 +1,26 @@
{
"light": {
"bgColor": "#fcfcfc",
"bgColorBottom": "#fcfcfc",
"bgColorTop": "#ff6b00",
"bgTxtStyle": "dark",
"navBgColor": "#ff6b00",
"navTxtStyle": "black",
"tabBgColor": "#fcfcfc",
"tabBorderStyle": "black",
"tabFontColor": "#1f2937",
"tabSelectedColor": "#ff6b00"
},
"dark": {
"bgColor": "#181818",
"bgColorBottom": "#181818",
"bgColorTop": "#ff6b00",
"bgTxtStyle": "light",
"navBgColor": "#ff6b00",
"navTxtStyle": "white",
"tabBgColor": "#181818",
"tabBorderStyle": "white",
"tabFontColor": "#f3f4f6",
"tabSelectedColor": "#ff6b00"
}
}

155
src/ui/CBad.vue Normal file
View File

@@ -0,0 +1,155 @@
<script setup>
import { defineProps, onMounted, ref, watch } from 'vue'
const props = defineProps({
data: {
type: Object,
required: true,
},
})
const chartData = ref({})
const riskLevel = ref('')
const riskLevelText = ref('')
const riskLevelClass = ref('')
const riskInfoList = ref([
{ level: '低风险', description: '涉稳、寻衅滋事', class: 'text-lime-600' },
{ level: '中风险', description: '吸毒、涉毒、犯罪前科', class: 'text-orange-400' },
{ level: '高风险', description: '涉案人员、在逃、犯罪嫌疑人', class: 'text-red-500' },
{ level: '无风险', description: '无任何不良风险记录', class: 'text-green-600' },
])
// 图表配置项
const opts = ref({
color: ['#1890FF', '#91CB74', '#FAC858', '#EE6666', '#73C0DE', '#3CA272', '#FC8452', '#9A60B4', '#ea7ccc'],
padding: 0,
title: {
name: '',
fontSize: 25,
color: '',
offsetY: -5,
},
subtitle: {
name: '风险评估指数',
fontSize: 12,
color: '#666666',
offsetY: 0,
},
extra: {
gauge: {
type: 'progress',
width: 20,
labelColor: '#666666',
startAngle: 0.75,
endAngle: 0.25,
startNumber: 0,
endNumber: 100,
labelFormat: '',
splitLine: {
fixRadius: -10,
splitNumber: 10,
width: 15,
color: '#FFFFFF',
childNumber: 5,
childWidth: 12,
},
pointer: {
width: 24,
color: 'auto',
},
},
},
})
// 根据风险等级动态设置图表内容和样式
function setChartProperties(level) {
switch (level) {
case 'A':
riskLevelText.value = '无风险'
riskLevelClass.value = 'text-green-600'
opts.value.title.name = '无风险'
opts.value.title.color = '#10B981'
chartData.value = {
categories: [{ value: 0, color: '#10B981' }, { value: 1, color: '#10B981' }],
series: [{ data: 0.1, color: '#10B981' }],
}
break
case 'F':
riskLevelText.value = '低风险'
riskLevelClass.value = 'text-lime-600'
opts.value.title.name = '低风险'
opts.value.title.color = '#A3E635'
chartData.value = {
categories: [{ value: 0, color: '#A3E635' }, { value: 1, color: '#A3E635' }],
series: [{ data: 0.3, color: '#A3E635' }],
}
break
case 'C':
case 'D':
riskLevelText.value = '中风险'
riskLevelClass.value = 'text-orange-400'
opts.value.title.name = '中风险'
opts.value.title.color = '#F97316'
chartData.value = {
categories: [{ value: 0, color: '#F97316' }, { value: 1, color: '#F97316' }],
series: [{ data: 0.6, color: '#F97316' }],
}
break
case 'B':
case 'E':
riskLevelText.value = '高风险'
riskLevelClass.value = 'text-red-500'
opts.value.title.name = '高风险'
opts.value.title.color = '#EF4444'
chartData.value = {
categories: [{ value: 0, color: '#EF4444' }, { value: 1, color: '#EF4444' }],
series: [{ data: 0.9, color: '#EF4444' }],
}
break
default:
riskLevelText.value = '未知风险'
riskLevelClass.value = 'text-gray-500'
opts.value.title.name = '未知风险'
opts.value.title.color = '#9CA3AF'
chartData.value = {
categories: [{ value: 0, color: '#9CA3AF' }, { value: 1, color: '#9CA3AF' }],
series: [{ data: 0 }],
}
}
}
// 初始化和监听 riskLevel 的变化
onMounted(() => {
riskLevel.value = props.data.risk_level
setChartProperties(riskLevel.value)
})
watch(riskLevel, (newLevel) => {
setChartProperties(newLevel)
})
</script>
<template>
<view class="card">
<view class="text-2xl font-bold" :class="riskLevelClass">
<qiun-data-charts
type="gauge"
:opts="opts"
:chart-data="chartData"
/>
</view>
<view class="mt-6">
<LTitle title="信息解读" type="blue-green" />
<view class="mt-4 rounded-lg bg-green-100/50 px-4 py-2 space-y-4">
<view v-for="(item, index) in riskInfoList" :key="index" class="flex items-center justify-between">
<text class="font-bold" :class="[item.class]">
{{ item.level }}
</text>
<text class="text-gray-700">
{{ item.description }}
</text>
</view>
</view>
</view>
</view>
</template>

View File

@@ -0,0 +1,361 @@
<script setup>
import QiunDataCharts from '@/components/qiun-data-charts/qiun-data-charts.vue'
const props = defineProps({
data: {
type: Object,
required: true,
},
})
const { data } = props
const tableData = ref([
])
const dateTableData = ref([
])
const options = ref([
{ label: '近7日', value: 0 },
{ label: '近1月', value: 1 },
{ label: '近3月', value: 2 },
{ label: '近6月', value: 3 },
{ label: '近1年', value: 4 },
])
const dateOptions = ref([
{ label: '近7日', value: 0 },
{ label: '近1月', value: 1 },
{ label: '近3月', value: 2 },
{ label: '近6月', value: 3 },
{ label: '近1年', value: 4 },
])
const selectedOption = ref(0)
const dateSelectedOption = ref(0)
const chartData = ref({})
const opts = ref({
color: ['#FAC858', '#EE6666', '#FAC858', '#EE6666', '#73C0DE', '#3CA272', '#FC8452', '#9A60B4', '#ea7ccc'],
padding: [15, 15, 0, 5],
enableScroll: false,
legend: {},
xAxis: {
disableGrid: true,
},
yAxis: {
data: [
{
min: 0,
},
],
},
extra: {
column: {
type: 'group',
width: 15,
activeBgColor: '#000000',
activeBgOpacity: 0.08,
linearType: 'custom',
seriesGap: 5,
linearOpacity: 0.5,
barBorderCircle: true,
customColor: [
'#FA7D8D',
'#EB88E2',
],
},
},
},
)
onMounted(() => {
const seriesData = calculateTotalStats(data)
tableData.value = typeTotalStats(data)
dateTableData.value = dateTotalStats(data)
const res = {
categories: ['近7日', '近1月', '近3月', '近6月', '近1年'],
series: [
{
name: '申请次数',
data: seriesData.totalApplyCount,
},
{
name: '申请的机构数',
data: seriesData.totalOrgCount,
},
],
}
chartData.value = JSON.parse(JSON.stringify(res))
},
)
function calculateTotalStats(data) {
// 时间维度映射
const timeDimensions = {
d7: '近7日',
m1: '近1月',
m3: '近3月',
m6: '近6月',
m12: '近1年',
}
// 机构类型
const orgTypes = ['bank', 'nbank']
// 初始化结果数组
const result = {
totalApplyCount: [],
totalOrgCount: [],
}
// 遍历每个时间维度
for (const timeKey of Object.keys(timeDimensions)) {
let totalApplyCount = 0 // 每个时间维度的总申请次数
let totalOrgCount = 0 // 每个时间维度的总机构数
// 遍历每种机构类型并累加
orgTypes.forEach((orgType) => {
// 构造参数名
const applyCountKey = `als_${timeKey}_id_${orgType}_allnum`
const orgCountKey = `als_${timeKey}_id_${orgType}_orgnum`
// 检查 data 中是否存在此参数,如果不存在则跳过
if (data[applyCountKey] !== undefined && data[orgCountKey] !== undefined) {
// 累加数值(如果值为 undefined 或 null 则转换为 0
totalApplyCount += Number(data[applyCountKey] || 0)
totalOrgCount += Number(data[orgCountKey] || 0)
}
})
// 将每个时间维度的总申请次数和总机构数添加到结果数组中
result.totalApplyCount.push(totalApplyCount)
result.totalOrgCount.push(totalOrgCount)
}
return result
}
function typeTotalStats(data) {
// 时间维度映射
const timeDimensions = {
d7: '近7日',
m1: '近1月',
m3: '近3月',
m6: '近6月',
m12: '近1年',
}
// 定义机构类型和对应的映射表
const orgMappings = {
bank: '银行借贷',
mc: '小额贷款',
cf: '消费分期',
ca: '借款分期',
rel: '信用卡',
af: '汽车金融',
other: '其他',
}
const tableGroup = {
bank: [
{ code: 'bank', name: '银行机构' },
],
mc: [
{ code: 'nbank_mc', name: '小贷机构' },
// { code: 'nbank_nsloan', name: '持牌网络小贷' },
// { code: 'nbank_sloan', name: '持牌小贷机构' },
// { code: 'pdl', name: '线上小额现金贷' },
],
cf: [
{ code: 'nbank_cf', name: '消费类分期机构' },
// { code: 'coon', name: '线上消费分期' },
// { code: 'cooff', name: '线下消费分期' },
],
ca: [
{ code: 'nbank_ca', name: '现金类分期机构' },
// { code: 'caon', name: '线上现金分期' },
// { code: 'caoff', name: '线下现金分期' },
{ code: 'nbank_com', name: '代偿类分期机构' },
],
rel: [
{ code: 'rel', name: '信用卡(类信用卡)' },
],
af: [
{ code: 'af', name: '汽车金融' },
// { code: 'nbank_autofin', name: '持牌汽车金融机构' },
],
other: [
{ code: 'nbank_p2p', name: '改制机构' },
{ code: 'nbank_cons', name: '持牌消费金融机构' },
{ code: 'nbank_finlea', name: '持牌融资租赁机构' },
{ code: 'nbank_oth', name: '申请其他' },
{ code: 'nbank_else', name: '其他申请' },
// { code: 'oth', name: '申请其他' },
// { code: 'else', name: '其他申请' },
],
}
// 初始化结果数组
const result = []
// 遍历每个时间维度
for (const timeKey of Object.keys(timeDimensions)) {
const tableDataEntry = []
// 遍历每种机构类型并累加
Object.keys(orgMappings).forEach((groupOrgType) => {
const orgTypeArray = tableGroup[groupOrgType]
let totalApplyCount = 0
let totalOrgCount = 0
for (const i of orgTypeArray) {
const applyCountKey = `als_${timeKey}_id_${i.code}_allnum`
const orgCountKey = `als_${timeKey}_id_${i.code}_orgnum`
totalApplyCount = totalApplyCount + Number(data[applyCountKey] || 0)
totalOrgCount = totalOrgCount + Number(data[orgCountKey] || 0)
}
// 添加到 tableData
tableDataEntry.push({
label: orgMappings[groupOrgType],
name: groupOrgType,
totalApplyCount,
totalOrgCount,
})
})
result.push(tableDataEntry)
}
return result
}
function dateTotalStats(data) {
// 时间维度映射
const timeDimensions = {
d7: '近7日',
m1: '近1月',
m3: '近3月',
m6: '近6月',
m12: '近1年',
}
// 定义机构类型和对应的映射表
const orgMappings = {
week: '周末',
night: '夜间',
}
const tableGroup = {
week: [
{ code: 'bank_week', name: '周末银行' },
{ code: 'nbank_week', name: '周末非银' },
],
night: [
{ code: 'bank_night', name: '夜间银行' },
{ code: 'nbank_night', name: '夜间非银' },
],
}
// 初始化结果数组
const result = []
// 遍历每个时间维度
for (const timeKey of Object.keys(timeDimensions)) {
const tableDataEntry = []
// 遍历每种机构类型并累加
Object.keys(orgMappings).forEach((groupOrgType) => {
const orgTypeArray = tableGroup[groupOrgType]
let totalApplyCount = 0
let totalOrgCount = 0
for (const i of orgTypeArray) {
const applyCountKey = `als_${timeKey}_id_${i.code}_allnum`
const orgCountKey = `als_${timeKey}_id_${i.code}_orgnum`
totalApplyCount = totalApplyCount + Number(data[applyCountKey] || 0)
totalOrgCount = totalOrgCount + Number(data[orgCountKey] || 0)
}
// 添加到 tableData
tableDataEntry.push({
label: orgMappings[groupOrgType],
name: groupOrgType,
totalApplyCount,
totalOrgCount,
})
})
result.push(tableDataEntry)
}
console.log('date result', result)
return result
}
</script>
<template>
<div class="card">
<div class="flex flex-col gap-y-4">
<!-- 申请次数 -->
<LTitle title="申请次数" type="blue-green" />
<QiunDataCharts
type="column"
:opts="opts"
:chart-data="chartData"
/>
<!-- 银行类别申请记录 -->
<LTitle title="申请类别" type="blue-green" />
<LButtonGroup v-model="selectedOption" :options="options" />
<LTable :data="tableData[selectedOption]" type="blue-green">
<template #header>
<th class="border px-4 py-2">
借贷类别
</th>
<th class="border px-4 py-2">
申请次数
</th>
<th class="border px-4 py-2">
申请的机构数
</th>
</template>
<template #default="{ row }">
<td class="border px-4 py-2">
{{ row.label }}
</td>
<td class="border px-4 py-2">
{{ row.totalApplyCount }}
</td>
<td class="border px-4 py-2">
{{ row.totalOrgCount }}
</td>
</template>
</LTable>
<!-- 特殊时段申请记录 -->
<LTitle title="特殊时段申请记录" type="blue-green" />
<LButtonGroup v-model="dateSelectedOption" :options="dateOptions" />
<LTable :data="dateTableData[dateSelectedOption]" type="blue-green">
<!-- 表头 -->
<template #header>
<th class="border px-4 py-2">
时段
</th>
<th class="border px-4 py-2">
申请次数
</th>
<th class="border px-4 py-2">
申请的机构数
</th>
</template>
<!-- 渲染表格内容 -->
<template #default="{ row }">
<td class="border px-4 py-2">
{{ row.label }}
</td>
<td class="border px-4 py-2">
{{ row.totalApplyCount }}
</td>
<td class="border px-4 py-2">
{{ row.totalOrgCount }}
</td>
</template>
</LTable>
</div>
</div>
</template>
<style lang="scss" scoped>
</style>

View File

@@ -0,0 +1,181 @@
<script setup>
import QiunDataCharts from '@/components/qiun-data-charts/qiun-data-charts.vue'
const props = defineProps({
data: {
type: Object,
required: true,
},
})
const { data } = props
console.log('behavior', data)
const tableData = ref([
])
const chartData = ref({})
const opts = ref({
color: ['#FAC858', '#EE6666', '#FAC858', '#EE6666', '#73C0DE', '#3CA272', '#FC8452', '#9A60B4', '#ea7ccc'],
padding: [15, 15, 0, 5],
enableScroll: false,
legend: {},
xAxis: {
disableGrid: true,
},
yAxis: {
data: [
{
min: 0,
},
],
},
extra: {
column: {
type: 'group',
width: 15,
activeBgColor: '#000000',
activeBgOpacity: 0.08,
linearType: 'custom',
seriesGap: 5,
linearOpacity: 0.5,
barBorderCircle: true,
customColor: [
'#FA7D8D',
'#EB88E2',
],
},
},
},
)
function calculateTotalStats(data) {
// 时间维度映射
const timeDimensions = {
m3: '近3月',
m6: '近6月',
m9: '近9月',
m12: '近1年',
}
const result = []
// 遍历每个时间维度
for (const timeKey of Object.keys(timeDimensions)) {
const countKey = `tl_id_${timeKey}_nbank_passlendamt`
let money = 1
if (data[countKey] !== undefined) {
money = getLevelRange(Number(data[countKey] || 1), 3000)
}
result.push({
date: timeDimensions[timeKey],
money,
})
}
return result
}
function totalStats(data) {
// 时间维度映射
const timeDimensions = {
m3: '近3月',
m6: '近6月',
m9: '近9月',
m12: '近1年',
}
// 机构类型
// 初始化结果数组
const result = {
totalApplyCount: [],
totalOrgCount: [],
}
// 遍历每个时间维度
for (const timeKey of Object.keys(timeDimensions)) {
let totalApplyCount = 0 // 每个时间维度的总申请次数
let totalOrgCount = 0 // 每个时间维度的总机构数
const applyCountKey = `tl_id_${timeKey}_nbank_passnum`
const orgCountKey = `tl_id_${timeKey}_nbank_passorg`
// 检查 data 中是否存在此参数,如果不存在则跳过
if (data[applyCountKey] !== undefined && data[orgCountKey] !== undefined) {
// 累加数值(如果值为 undefined 或 null 则转换为 0
totalApplyCount += Number(data[applyCountKey] || 0)
totalOrgCount += Number(data[orgCountKey] || 0)
}
// 将每个时间维度的总申请次数和总机构数添加到结果数组中
result.totalApplyCount.push(totalApplyCount)
result.totalOrgCount.push(totalOrgCount)
}
return result
}
onMounted(() => {
tableData.value = calculateTotalStats(data)
console.log('calculateTotalStats(data)', calculateTotalStats(data))
const chatData = totalStats(data)
console.log('chatData', chatData)
const res = {
categories: ['近1月', '近3月', '近6月', '近1年'],
series: [
{
name: '借贷次数',
data: chatData.totalApplyCount,
},
{
name: '借贷机构数',
data: chatData.totalOrgCount,
},
],
}
chartData.value = JSON.parse(JSON.stringify(res))
},
)
function getLevelRange(level, threshold) {
const upperLimit = level * threshold
const lowerLimit = (level - 1) * threshold
return `${lowerLimit}元 - ${upperLimit}`
}
</script>
<template>
<div class="card">
<div class="flex flex-col gap-y-4">
<!-- 申请次数 -->
<LTitle title="借贷次数" type="blue-green" />
<QiunDataCharts
type="column"
:opts="opts"
:chart-data="chartData"
/>
<!-- 银行类别申请记录 -->
<LTitle title="借贷额度" type="blue-green" />
<LTable :data="tableData" type="blue-green">
<template #header>
<th class="border px-4 py-2">
时间段
</th>
<th class="border px-4 py-2">
借贷数额
</th>
</template>
<template #default="{ row }">
<td class="border px-4 py-2">
{{ row.date }}
</td>
<td class="border px-4 py-2">
{{ row.money }}
</td>
</template>
</LTable>
</div>
</div>
</template>
<style lang="scss" scoped>
</style>

203
src/ui/CLawsuit.vue Normal file
View File

@@ -0,0 +1,203 @@
<script setup>
const props = defineProps({
data: {
type: Object,
required: true,
},
})
const collapse = ref([])
const jsonData = ref({})
const chartData = ref({})
const opts = ref({
rotate: false,
rotateLock: false,
color: ['#1890FF', '#91CB74', '#FAC858', '#EE6666', '#73C0DE', '#3CA272', '#FC8452', '#9A60B4', '#ea7ccc'],
padding: [15, 15, 15, 15],
dataLabel: false,
enableScroll: false,
legend: {
show: true,
position: 'right',
lineHeight: 25,
},
title: {
name: '涉诉案件数',
fontSize: 14,
color: '#666666',
},
subtitle: {
name: '0', // 默认值为 0稍后会动态更新
fontSize: 25,
color: '#EE6666',
},
extra: {
ring: {
ringWidth: 30,
activeOpacity: 0.5,
activeRadius: 10,
offsetAngle: 0,
labelWidth: 15,
border: true,
borderWidth: 3,
borderColor: '#FFFFFF',
linearType: 'custom',
},
},
})
onMounted(() => {
jsonData.value = props.data
// 计算每种案件的数量,并生成图表数据
const caseCounts = {
criminal: jsonData.value.criminal?.cases?.length || 0,
civil: jsonData.value.civil?.cases?.length || 0,
administrative: jsonData.value.administrative?.cases?.length || 0,
preservation: jsonData.value.preservation?.cases?.length || 0,
implement: jsonData.value.implement?.cases?.length || 0,
bankrupt: jsonData.value.bankrupt?.cases?.length || 0,
}
// 生成 QiunDataCharts 图表的数据格式
chartData.value = {
series: [
{
data: [
{ name: `刑事案件${caseCounts.criminal}`, value: caseCounts.criminal, labelText: `刑事案件${caseCounts.criminal}` },
{ name: `民事案件${caseCounts.civil}`, value: caseCounts.civil, labelText: `民事案件${caseCounts.civil}` },
{ name: `行政案件${caseCounts.administrative}`, value: caseCounts.administrative, labelText: `行政案件${caseCounts.administrative}` },
{ name: `非诉保全审查${caseCounts.preservation}`, value: caseCounts.preservation, labelText: `非诉保全审查${caseCounts.preservation}` },
{ name: `执行案件${caseCounts.implement}`, value: caseCounts.implement, labelText: `执行案件${caseCounts.implement}` },
{ name: `强制清算与破产${caseCounts.bankrupt}`, value: caseCounts.bankrupt, labelText: `强制清算与破产${caseCounts.bankrupt}` },
],
},
],
}
// 计算涉诉总案件数
const totalCases = Object.values(caseCounts).reduce((sum, count) => sum + count, 0)
opts.value.subtitle.name = totalCases.toString() // 更新 subtitle 的 name 属性
})
const caseTypes = computed(() => {
const data = jsonData.value
return {
civil: data.civil?.cases || [],
criminal: data.criminal?.cases || [],
administrative: data.administrative?.cases || [],
preservation: data.preservation?.cases || [],
implement: data.implement?.cases || [],
bankrupt: data.bankrupt?.cases || [],
}
})
function getCaseTypeName(caseType) {
const caseTypeNames = {
civil: '民事',
criminal: '刑事',
administrative: '行政',
preservation: '非诉保全审查',
implement: '执行',
bankrupt: '强制清算与破产',
}
return caseTypeNames[caseType] || caseType
}
</script>
<template>
<view class="card">
<view class="flex flex-col gap-y-4">
<!-- 涉诉案件统计 -->
<LTitle title="涉诉案件统计" type="blue-green" />
<qiun-data-charts type="ring" :opts="opts" :chart-data="chartData" />
<template v-for="(caseType, typeName) in caseTypes" :key="typeName">
<LTitle :title="` ${getCaseTypeName(typeName)}案件`" type="blue-green" />
<view v-if="!caseType || caseType.length === 0">
无记录或数据未被公开
</view>
<template v-else>
<wd-collapse v-model="collapse">
<wd-collapse-item
v-for="(caseData, index) in caseType" :key="index" custom-class="collapse" :name="index"
:title="`案件: ${caseData.c_ah}`"
>
<view class="case-row">
<view class="case-label">
案号:
</view>
<view class="case-value">
{{ caseData.c_ah || '-' }}
</view>
</view>
<view class="case-row">
<view class="case-label">
案件类型:
</view>
<view class="case-value">
{{ caseData.n_ajlx || '-' }}
</view>
</view>
<view class="case-row">
<view class="case-label">
经办法院:
</view>
<view class="case-value">
{{ caseData.n_jbfy || '-' }}
</view>
</view>
<view class="case-row">
<view class="case-label">
立案日期:
</view>
<view class="case-value">
{{ caseData.d_larq || '-' }}
</view>
</view>
<view class="case-row">
<view class="case-label">
结案方式:
</view>
<view class="case-value">
{{ caseData.n_jafs || '-' }}
</view>
</view>
<view class="case-row">
<view class="case-label">
当事人信息:
</view>
<view class="case-value">
<view v-for="dsr in caseData.c_dsrxx" :key="dsr.c_mc">
{{ dsr.c_mc }} - {{ dsr.n_ssdw === '申请执行人' ? '申请执行人' : '被执行人' }}
</view>
</view>
</view>
</wd-collapse-item>
</wd-collapse>
</template>
</template>
</view>
</view>
</template>
<style lang="scss" scoped>
.case-row {
@apply flex items-start justify-between my-2;
}
.case-label {
@apply flex-shrink-0 font-bold
}
.case-value {
@apply text-right
}
/* :deep(.wd-collapse-item__header) {
padding: 0;
} */
:deep(.wd-collapse-item__body) {
padding: 0;
@apply text-sm
}
</style>

67
src/ui/CMarriage.vue Normal file
View File

@@ -0,0 +1,67 @@
<script setup>
const props = defineProps({
data: {
type: Object,
required: true,
},
})
const { data } = props
// 状态映射,包括显示的文字和样式
const statusMap = {
0: { text: '未登记', bgClass: 'bg-yellow-100', textClass: 'text-yellow-700', description: '尚未登记婚姻信息' },
1: { text: '已婚', bgClass: 'bg-green-100', textClass: 'text-green-700', description: '已登记婚姻,家庭幸福美满' },
2: { text: '离异', bgClass: 'bg-red-100', textClass: 'text-red-700', description: '离异状态,未来生活可期' },
3: { text: '离婚冷静期', bgClass: 'bg-blue-100', textClass: 'text-blue-700', description: '目前处于离婚冷静期,请谨慎决策' },
}
// 根据 `data.status` 确定当前状态,默认值为 “无相关记录”
const currentStatus = data.status !== undefined ? statusMap[data.status] || statusMap['0'] : { text: '无相关记录', bgClass: 'bg-gray-200', textClass: 'text-gray-500', description: '暂无婚姻相关记录' }
</script>
<template>
<div class="card">
<div class="status-info mb-4 flex flex-col items-center">
<div
:class="`status-label rounded-full px-6 py-3 text-center font-bold shadow-md ${currentStatus.bgClass} ${currentStatus.textClass}`"
>
{{ currentStatus.text }}
</div>
<p class="status-description mt-3 text-sm text-gray-600">
{{ currentStatus.description }}
</p>
</div>
<!-- <div class="additional-info mt-6 text-center">
<p class="text-xs text-gray-500">
<strong>数据更新时间</strong> {{ lastUpdated }}
</p>
<p class="text-xs text-gray-500">
本数据仅供参考如有疑问请联系相关部门
</p>
</div> -->
</div>
</template>
<style lang="scss" scoped>
.status-info {
text-align: center;
}
.status-label {
font-size: 1.25rem;
padding: 0.75rem 1.5rem;
border-radius: 9999px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.status-description {
color: #4a5568;
margin-top: 0.5rem;
font-weight: 500;
}
.additional-info p {
margin-top: 0.5rem;
}
</style>

View File

@@ -0,0 +1,448 @@
<script setup>
const props = defineProps({
data: {
type: Object,
required: true,
},
})
const { data } = props
const entCollapse = ref([])
</script>
<template>
<view class="">
<template v-if="data && data.datalist.length === 0">
<!-- 显示暂无关联企业信息的提示 -->
<view class="card py-10 text-center text-gray-500">
暂无关联企业信息
</view>
</template>
<template v-else>
<wd-collapse v-model="entCollapse" custom-class="space-y-5" custom-style="background: transparent; !important">
<wd-collapse-item v-for="(item, index) in data.datalist" :key="index" :name="index" class="card">
<template #title="{ expanded }">
<view class="w-full space-y-3">
<view class="text-lg text-gray-800 font-bold">
{{ item.orgName }}
</view>
<view class="text-sm text-gray-700">
查询人{{ item.pName }}
</view>
<!-- 关联关系 -->
<view class="flex items-center gap-3">
<text class="flex-shrink-0 text-gray-700 font-medium">
与企业关联关系:
</text>
<text v-for="(relation, idx) in item.relationship" :key="idx" class="flex-shrink-0 rounded-full bg-blue-100 px-3 py-1 text-xs text-blue-800">
{{ relation === 'lp' ? '法人' : relation === 'sh' ? '股东' : '高管' }}
</text>
</view>
<view class="text-center text-blue-500">
{{ expanded ? '收起' : '点击查看更多' }}
</view>
</view>
</template>
<LTitle title="关联企业信息" type="blue-green" />
<!-- 基本信息 -->
<view class="pt-4 space-y-3">
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
企业状态
</text>
<text class="text-gray-600">
{{ item.basicInfo.regStatus }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
注册资本
</text>
<text class="text-gray-600">
{{ item.basicInfo.regCapital }} {{ item.basicInfo.regCapitalCurrency }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
法人
</text>
<text class="text-gray-600">
{{ item.basicInfo.legalPersonName }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
统一社会信用代码
</text>
<text class="text-gray-600">
{{ item.basicInfo.creditCode }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
成立日期
</text>
<text class="text-gray-600">
{{ item.basicInfo.estiblishTime }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
经营范围
</text>
<text class="text-gray-600">
<LExpandCollapse :max-length="50">
{{ item.basicInfo.opscope }}
</LExpandCollapse>
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
地址
</text>
<text class="text-gray-600">
{{ item.basicInfo.province }} {{ item.basicInfo.city }} {{ item.basicInfo.district }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
行业
</text>
<text class="text-gray-600">
{{ item.basicInfo.industry }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
行业代码
</text>
<text class="text-gray-600">
{{ item.basicInfo.nic_code }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
公司类型
</text>
<text class="text-gray-600">
{{ item.basicInfo.companyOrgType }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
注册机关
</text>
<text class="text-gray-600">
{{ item.basicInfo.regorg }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
行业名称
</text>
<text class="text-gray-600">
{{ item.basicInfo.nic_name }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
注册资本币种
</text>
<text class="text-gray-600">
{{ item.basicInfo.reccapcur }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
审核日期
</text>
<text class="text-gray-600">
{{ item.basicInfo.apprdate }}
</text>
</view>
</view>
<!-- 高管信息 -->
<view v-if="item.basicInfo.staffList?.result?.length > 0" class="pt-4 space-y-3">
<LTitle title="高管信息" type="blue-green" />
<view v-for="(staff, idx) in item.basicInfo.staffList.result" :key="idx" class="space-y-3">
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
姓名
</text>
<text class="text-gray-600">
{{ staff.name }}
</text>
</view>
<view v-for="(type, typeIdx) in staff.typeJoin" :key="typeIdx" class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
职位
</text>
<text class="text-gray-600">
{{ type }}
</text>
</view>
</view>
</view>
<!-- 股东信息 -->
<view v-if="item.stockHolderItem" class="pt-4 space-y-3">
<LTitle title="股东信息" type="blue-green" />
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
股东类型
</text>
<text class="text-gray-600">
{{ item.stockHolderItem.orgHolderType }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
占比
</text>
<text class="text-gray-600">
{{ item.stockHolderItem.investRate }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
股东名称
</text>
<text class="text-gray-600">
{{ item.stockHolderItem.orgHolderName }}
</text>
</view>
</view>
<!-- 被执行人信息 -->
<!-- <view v-if="item.executedPerson?.length > 0" class="pt-4">
<LTitle title="被执行人信息" type="blue-green" />
<view v-for="(person, pidx) in item.executedPerson" :key="pidx" class="border-b border-gray-400 border-b-dashed pb-4 pt-4 space-y-3">
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
案号
</text>
<text class="text-gray-600">
{{ person.caseCode }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
身份证号
</text>
<text class="text-gray-600">
{{ person.partyCardNum }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
被执行人
</text>
<text class="text-gray-600">
{{ person.pname }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
立案日期
</text>
<text class="text-gray-600">
{{ person.caseCreateTime }}
</text>
</view>
<view v-if="person.execCourtName" class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
执行法院
</text>
<text class="text-gray-600">
{{ person.execCourtName }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
执行标的
</text>
<text class="text-gray-600">
{{ person.execMoney }}
</text>
</view>
</view>
</view>
<view v-if="item.dishonestExecutedPerson?.length > 0" class="pt-4">
<LTitle title="失信被执行人信息" type="blue-green" />
<view v-for="(person, didx) in item.dishonestExecutedPerson" :key="didx" class="border-b border-gray-400 border-b-dashed pb-4 pt-4 space-y-3">
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
失信人姓名
</text>
<text class="text-gray-600">
{{ person.iname }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
失信行为
</text>
<text class="text-gray-600">
{{ person.disrupttypename }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
案号
</text>
<text class="text-gray-600">
{{ person.casecode }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
身份证号
</text>
<text class="text-gray-600">
{{ person.cardnum }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
未履行部分
</text>
<text class="text-gray-600">
{{ person.unperformPart || '无' }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
已履行部分
</text>
<text class="text-gray-600">
{{ person.performedPart || '无' }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
履行情况
</text>
<text class="text-gray-600">
{{ person.performance }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
立案时间
</text>
<text class="text-gray-600">
{{ person.regdate }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
生效法律文书确定义务
</text>
<text class="text-gray-600">
{{ person.duty }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
执行依据文号
</text>
<text class="text-gray-600">
{{ person.gistid }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
执行法院
</text>
<text class="text-gray-600">
{{ person.courtname }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
发布时间
</text>
<text class="text-gray-600">
{{ person.publishdate }}
</text>
</view>
</view>
</view> -->
<view v-if="item.adminPenalty?.length > 0" class="pt-4">
<LTitle title="行政处罚信息" type="blue-green" />
<view v-for="(penalty, aidx) in item.adminPenalty" :key="aidx" class="border-b border-gray-400 border-b-dashed pb-4 pt-4 space-y-3">
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
处罚单位
</text>
<text class="text-gray-600">
{{ penalty.departmentName }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
处罚原因
</text>
<text class="text-gray-600">
{{ penalty.reason || '无' }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
处罚决定书文号
</text>
<text class="text-gray-600">
{{ penalty.punishNumber }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
处罚类别
</text>
<text class="text-gray-600">
{{ penalty.type }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
处罚结果
</text>
<text class="text-gray-600">
{{ penalty.content || '无' }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
处罚日期
</text>
<text class="text-gray-600">
{{ penalty.decisionDate }}
</text>
</view>
<view class="flex justify-between">
<text class="flex-shrink-0 text-gray-700 font-medium">
法人姓名
</text>
<text class="text-gray-600">
{{ penalty.legalPersonName }}
</text>
</view>
</view>
</view>
</wd-collapse-item>
</wd-collapse>
</template>
</view>
</template>
<style scoped lang="scss">
:deep(.wd-collapse-item__header){
padding: 0;
}
:deep(.wd-collapse-item__body){
padding: 0;
@apply text-sm
}
</style>

Some files were not shown because too many files have changed in this diff Show More