| @@ -27,8 +27,6 @@ declare module 'vue' { | |||
| NutEmpty: typeof import('@nutui/nutui-taro')['Empty'] | |||
| NutForm: typeof import('@nutui/nutui-taro')['Form'] | |||
| NutFormItem: typeof import('@nutui/nutui-taro')['FormItem'] | |||
| NutGrid: typeof import('@nutui/nutui-taro')['Grid'] | |||
| NutGridItem: typeof import('@nutui/nutui-taro')['GridItem'] | |||
| NutInput: typeof import('@nutui/nutui-taro')['Input'] | |||
| NutNavbar: typeof import('@nutui/nutui-taro')['Navbar'] | |||
| NutRow: typeof import('@nutui/nutui-taro')['Row'] | |||
| @@ -4,7 +4,7 @@ export default defineAppConfig({ | |||
| 'pages/contact/index', | |||
| 'pages/contact-new/index', | |||
| 'pages/contact-edit/index', | |||
| 'pages/invite/index', | |||
| 'pages/notifications/index', | |||
| 'pages/settings/index', | |||
| 'pages/login/index', | |||
| 'pages/web-view/index', | |||
| @@ -25,16 +25,16 @@ export default defineAppConfig({ | |||
| list: [ | |||
| { | |||
| pagePath: 'pages/index/index', | |||
| selectedIconPath: 'images/bell-solid-397ef5.png', | |||
| iconPath: 'images/bell-regular-797979.png', | |||
| text: '通知' | |||
| }, | |||
| { | |||
| pagePath: 'pages/invite/index', | |||
| selectedIconPath: 'images/calendar-plus-solid-397ef5.png', | |||
| iconPath: 'images/calendar-plus-regular-797979.png', | |||
| text: '邀约' | |||
| }, | |||
| { | |||
| pagePath: 'pages/notifications/index', | |||
| selectedIconPath: 'images/bell-solid-397ef5.png', | |||
| iconPath: 'images/bell-regular-797979.png', | |||
| text: '通知' | |||
| }, | |||
| { | |||
| pagePath: 'pages/contact/index', | |||
| selectedIconPath: 'images/address-book-solid-397ef5.png', | |||
| @@ -1,6 +1,6 @@ | |||
| export default definePageConfig({ | |||
| navigationBarTitleText: '', | |||
| navigationStyle: 'custom', | |||
| disableScroll: true, | |||
| usingComponents: {}, | |||
| navigationStyle: 'custom', | |||
| disableScroll: true | |||
| }) | |||
| @@ -11,8 +11,20 @@ page { | |||
| overflow: scroll; | |||
| } | |||
| .skeleton { | |||
| flex: 1; | |||
| overflow: hidden; | |||
| .nut-grid-item__content { | |||
| padding: 0; | |||
| display:unset; | |||
| } | |||
| .nut-grid-item__content--border { | |||
| border-right-width: unset; | |||
| border-bottom-width: unset; | |||
| } | |||
| .nut-grid-item__content--surround { | |||
| border-top-width: unset; | |||
| border-left-width: unset; | |||
| } | |||
| .skeleton-avatar .nut-skeleton-content__line { | |||
| visibility: hidden !important; | |||
| display: none !important; | |||
| } | |||
| @@ -1,176 +1,208 @@ | |||
| <script setup lang="ts"> | |||
| import { reactive } from 'vue' | |||
| import { View } from '@tarojs/components' | |||
| <script lang="ts" setup> | |||
| import Contact from "../../components/contact" | |||
| import { Router } from 'tarojs-router-next' | |||
| import {reactive, ref} from 'vue'; | |||
| import './index.scss' | |||
| import {weappAuth} from "../../utils"; | |||
| import {GroupedPassRecords, usePassRecordsStore} from "../../stores/pass-records"; | |||
| import {useContactsStore} from "../../stores/contacts"; | |||
| import { useContactsStore, ContactData } from '../../stores/contacts' | |||
| import { registerRouterBackListener } from 'tarojs-router-next' | |||
| import {BjxHelper} from "../../utils"; | |||
| import {gql} from "graphql-tag"; | |||
| import {PinyinHelper, GQLRequest, weappAuth} from "../../utils"; | |||
| import {useAuthStore} from "../../stores/auth"; | |||
| // defineExpose({ | |||
| // loadContactsFromServer, | |||
| // }); | |||
| const state = reactive<{ | |||
| isPageDataLoading: boolean, | |||
| isAuthError: boolean, | |||
| groupedPassRecords: GroupedPassRecords[], | |||
| isContactDataLoadError: boolean, | |||
| isContactDataLoading: boolean, | |||
| searchQuery: string, | |||
| normalContacts: ContactData[], | |||
| flexContacts: ContactData[], // Generic type for now | |||
| }>({ | |||
| isPageDataLoading: true, | |||
| isAuthError: false, | |||
| groupedPassRecords: [], | |||
| isContactDataLoadError: false, | |||
| isContactDataLoading: true, | |||
| searchQuery: "", | |||
| normalContacts: [], | |||
| flexContacts: [] | |||
| }) | |||
| const passRecords = usePassRecordsStore() | |||
| const contacts = useContactsStore() | |||
| init() | |||
| function init() { | |||
| state.isAuthError = false | |||
| state.isPageDataLoading = true | |||
| weappAuth().then(r => { | |||
| console.log(r) | |||
| passRecords.loadPassRecordsFromServer().then( passRecords => { | |||
| state.groupedPassRecords = passRecords | |||
| console.log("aaa",state.groupedPassRecords ) | |||
| // console.log(state.groupedPassRecords) | |||
| contacts.loadContactsFromServer().then( contacts => { | |||
| state.isPageDataLoading = false | |||
| state.isContactDataLoadError = false | |||
| state.isContactDataLoading = true | |||
| weappAuth() | |||
| .then(r => { | |||
| contacts.loadContactsFromServer().then( | |||
| contactList => { | |||
| console.log("contactList", contactList) | |||
| generateContactGroupList(contactList) | |||
| state.isContactDataLoading = false | |||
| }) | |||
| .catch(e => { | |||
| state.isAuthError = false | |||
| state.isContactDataLoadError = true | |||
| state.isContactDataLoading = false | |||
| }) | |||
| }) | |||
| .catch(contactError => { | |||
| console.log("error", contactError) | |||
| .catch(e=> { | |||
| console.log("error", e) | |||
| state.isAuthError = true | |||
| state.isPageDataLoading = false | |||
| state.isContactDataLoadError = false | |||
| state.isContactDataLoading = false | |||
| }) | |||
| }) | |||
| .catch(error => { | |||
| console.log("error", error) | |||
| state.isAuthError = true | |||
| state.isPageDataLoading = false | |||
| }) | |||
| }).catch(e => { | |||
| console.log("error", e) | |||
| state.isAuthError = true | |||
| state.isPageDataLoading = false | |||
| registerRouterBackListener((to, from) => { | |||
| if ((from.url === "/pages/contact-new/notifications" && to.url === "/pages/index/notifications") | |||
| || (from.url === "/pages/contact-edit/notifications" && to.url === "/pages/index/notifications") | |||
| ) { | |||
| generateContactGroupList(contacts.allContacts) | |||
| } | |||
| }) | |||
| } | |||
| const onAuthErrorRefresh = () => { | |||
| init() | |||
| } | |||
| // const onPullDownRefresh = () => { | |||
| // console.log("onPullDownRefresh") | |||
| // state.isRefresherTriggered = false | |||
| // } | |||
| function onPullDownRefresh (e) { | |||
| console.log("onPullDownRefresh", e) | |||
| // state.isRefresherTriggered = false | |||
| const onContactDataLoadErrorRefresh = () => { | |||
| state.isContactDataLoadError = false | |||
| state.isContactDataLoading = true | |||
| contacts.loadContactsFromServer().then( | |||
| contactList => { | |||
| console.log("contactList", contactList) | |||
| generateContactGroupList(contactList) | |||
| state.isContactDataLoading = false | |||
| }) | |||
| .catch(e => { | |||
| state.isContactDataLoadError = true | |||
| state.isContactDataLoading = false | |||
| }) | |||
| } | |||
| // | |||
| // | |||
| // const show = ref(false); | |||
| // | |||
| // const state = reactive({ | |||
| // msg: '欢迎使用 NutUI4.0 开发小程序', | |||
| // msg2: '你成功了~', | |||
| // isVisible1: false, | |||
| // val: '' | |||
| // }) | |||
| // | |||
| // const handleClick = msg => { | |||
| // state.msg = msg | |||
| // } | |||
| // | |||
| // useDidShow(() => { | |||
| // console.log("did show is run xxxxxxx.") | |||
| // }) | |||
| // | |||
| // useLoad(() => { | |||
| // console.log("use load is run xxxxxxx.") | |||
| // }) | |||
| const generateContactGroupList = (contactList: ContactData[]) => { | |||
| state.normalContacts = [] | |||
| state.flexContacts = [] | |||
| for (const item of contactList) { | |||
| if (item.flexVisit === true) state.flexContacts.push(item) | |||
| else state.normalContacts.push(item) | |||
| } | |||
| } | |||
| const goToContactNewPage = () => { | |||
| Router.toContactNew() | |||
| } | |||
| const goToContactEditPage = (item) => { | |||
| Router.toContactEdit({ data: item }) | |||
| } | |||
| </script> | |||
| <template> | |||
| <view class="h-100 d-flex flex-column"> | |||
| <BackgroundBasic/> | |||
| <NutNavbar title=""></NutNavbar> | |||
| <View class="w-100" style="overflow-x: hidden"> | |||
| <View class="pl-3 pt-3 pr-3 h3 d-flex"> | |||
| <View class="flex-grow-1"> | |||
| 来访记录 | |||
| <view class="pl-3 pt-3 pr-3 h3 d-flex"> | |||
| <view class="flex-grow-1"> | |||
| 我的邀约 | |||
| </view> | |||
| </view> | |||
| <View class="scroll 100vh"> | |||
| <View class="mt-3 p-3"> | |||
| <View class="border bg-white p-3 d-flex flex-column" hover-class="card-hover-gray" @tap="goToContactNewPage()" > | |||
| <View class="d-flex justify-content-center"> | |||
| <Image :src="require('./invite.jpeg')" class="p-3" mode='heightFix' style="height: 15vh"/> | |||
| </View> | |||
| <View class="d-flex justify-content-center"> | |||
| <View class="fas fa-plus-circle text-black-50" style="font-size: 120%"> 新邀约</View> | |||
| </View> | |||
| </View> | |||
| </View> | |||
| <View class="d-flex text-black-50 pb-2 pr-3"> | |||
| <View class="flex-grow-1"></View> | |||
| <View>最近30天的来访</View> | |||
| <View v-if="!state.isContactDataLoading"> | |||
| <View v-if="state.isAuthError"> | |||
| <nut-empty description="连接出现问题,请稍后重试"> | |||
| <div style="margin-top: 10px"> | |||
| <nut-button type="default" @tap="onAuthErrorRefresh">刷新</nut-button> | |||
| </div> | |||
| </nut-empty> | |||
| </View> | |||
| <View v-else-if="state.isContactDataLoadError"> | |||
| <nut-empty description="连接出现问题,请稍后重试"> | |||
| <div style="margin-top: 10px"> | |||
| <nut-button type="default" @tap="onContactDataLoadErrorRefresh">刷新</nut-button> | |||
| </div> | |||
| </nut-empty> | |||
| </View> | |||
| <View v-else> | |||
| <View class="h4 p-3">来访联系人</View> | |||
| <View class="container-fluid"> | |||
| <View class="row w-100"> | |||
| <View style="width: 25vw" v-for="item in state.normalContacts"> | |||
| <View class="m-2 p-3 border" hover-class="card-hover-gray" @tap="goToContactEditPage(item)"> | |||
| <View class="d-flex justify-content-center"> | |||
| <NutBadge :value="item.isVIP?'VIP':''"> | |||
| <NutAvatar size="normal" color="white" :bg-color="BjxHelper.mbString2RgbHex(item.name)" class="overflow-hidden"> | |||
| <img v-if="item.avatar" :src="item.avatar" /> | |||
| <view v-else-if="BjxHelper.getBJXFirstChar(item.name)">{{BjxHelper.getBJXFirstChar(item.name)}}</view> | |||
| <view v-else> | |||
| <Text className='fas fa-user fa-lg'/> | |||
| </view> | |||
| </NutAvatar> | |||
| </NutBadge> | |||
| </View> | |||
| <View class="d-flex justify-content-center small b pt-2 text-nowrap overflow-hidden"> | |||
| {{item.name}} | |||
| </View> | |||
| </View> | |||
| </View> | |||
| </View> | |||
| </View> | |||
| <View class="h4 p-3">可随时来访联系人</View> | |||
| <View class="container-fluid"> | |||
| <View class="row w-100"> | |||
| <View style="width: 25vw" v-for="item in state.flexContacts"> | |||
| <View class="m-2 p-3 border" hover-class="card-hover-gray" @tap="goToContactEditPage(item)"> | |||
| <View class="d-flex justify-content-center"> | |||
| <NutBadge :value="item.isVIP?'VIP':''"> | |||
| <NutAvatar size="normal" color="white" :bg-color="BjxHelper.mbString2RgbHex(item.name)" class="overflow-hidden"> | |||
| <img v-if="item.avatar" :src="item.avatar" /> | |||
| <view v-else-if="BjxHelper.getBJXFirstChar(item.name)">{{BjxHelper.getBJXFirstChar(item.name)}}</view> | |||
| <view v-else> | |||
| <Text className='fas fa-user fa-lg'/> | |||
| </view> | |||
| </NutAvatar> | |||
| </NutBadge> | |||
| </View> | |||
| <View class="d-flex justify-content-center small b pt-2 text-nowrap overflow-hidden"> | |||
| {{item.name}} | |||
| </View> | |||
| </View> | |||
| </View> | |||
| </View> | |||
| </View> | |||
| </View> | |||
| </View> | |||
| </View> | |||
| <View v-if="state.isAuthError"> | |||
| <nut-empty description="连接出现问题,请稍后重试"> | |||
| <div style="margin-top: 10px"> | |||
| <nut-button type="default" @tap="onAuthErrorRefresh">刷新</nut-button> | |||
| </div> | |||
| </nut-empty> | |||
| </View> | |||
| <View class="scroll 100vh" v-else> | |||
| <view class="scroll 100vh" v-if="!state.isPageDataLoading"> | |||
| <Scroll-View style="height: 100vh" :scrollY="true"> | |||
| <Notification v-for="item in state.groupedPassRecords" :item="item"/> | |||
| <view class="container pt-5 pb-3"> | |||
| <view class="row"> | |||
| <view class="col"/> | |||
| <view class="col text-center text-black-50"> | |||
| <nut-divider> 没有更多了 </nut-divider> | |||
| </view> | |||
| <view class="col"/> | |||
| </view> | |||
| </view> | |||
| </Scroll-View> | |||
| </view> | |||
| <View v-else class="skeleton"> | |||
| <NutSkeleton v-for="_ in 10" class="pl-4 pt-4 pb-4 pr-5" height="20px" width="60vw" animated avatar avatar-size="50px" row="2"/> | |||
| <View v-else class="d-flex flex-column"> | |||
| <NutSkeleton v-for="_ in 10" class="p-3" height="15px" animated avatar avatar-size="50px" row="1"/> | |||
| </View> | |||
| </View> | |||
| </view> | |||
| <!-- <view class="p-4">--> | |||
| <!-- <button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">使用电话号码登录</button>--> | |||
| <!-- </view>--> | |||
| <!-- <Counter/>--> | |||
| <!-- <nut-cell title="展示弹出层" is-link @click="show = true"></nut-cell>--> | |||
| <!-- <nut-popup :style="{ padding: '30px 50px' }" v-model:visible="show">正文</nut-popup>--> | |||
| <!-- <View><Text>{{state.msg}}</Text></View>--> | |||
| <!-- <nut-button type="primary" @click="handleClick(state.msg2)">点我</nut-button>--> | |||
| <!-- <Add color="red" />--> | |||
| <!-- <div class="alert alert-primary" role="alert">--> | |||
| <!-- A simple primary alert—check it out!--> | |||
| <!-- </div>--> | |||
| <!-- <h1>Example heading <span class="badge bg-secondary">New</span></h1>--> | |||
| <!-- <button type="button" class="btn btn-primary">--> | |||
| <!-- Notifications <span class="badge text-bg-secondary">4</span>--> | |||
| <!-- </button>--> | |||
| <!-- <button type="button" class="btn btn-primary position-relative">--> | |||
| <!-- Inbox--> | |||
| <!-- <span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">--> | |||
| <!-- 99+--> | |||
| <!-- <span class="visually-hidden">unread messages</span>--> | |||
| <!-- </span>--> | |||
| <!-- </button>--> | |||
| <!-- </view>--> | |||
| </view> | |||
| </template> | |||
| @@ -1,25 +0,0 @@ | |||
| page { | |||
| height: 100%; | |||
| } | |||
| .nut-navbar { | |||
| background: transparent; | |||
| } | |||
| .scroll { | |||
| flex: 1; | |||
| overflow: scroll; | |||
| } | |||
| .nut-grid-item__content { | |||
| padding: 0; | |||
| display:unset; | |||
| } | |||
| .nut-grid-item__content--border { | |||
| border-right-width: unset; | |||
| border-bottom-width: unset; | |||
| } | |||
| .nut-grid-item__content--surround { | |||
| border-top-width: unset; | |||
| border-left-width: unset; | |||
| } | |||
| @@ -1,208 +0,0 @@ | |||
| <script lang="ts" setup> | |||
| import Contact from "../../components/contact" | |||
| import { Router } from 'tarojs-router-next' | |||
| import {reactive, ref} from 'vue'; | |||
| import './index.scss' | |||
| import { useContactsStore, ContactData } from '../../stores/contacts' | |||
| import { registerRouterBackListener } from 'tarojs-router-next' | |||
| import {BjxHelper} from "../../utils"; | |||
| import {gql} from "graphql-tag"; | |||
| import {PinyinHelper, GQLRequest, weappAuth} from "../../utils"; | |||
| import {useAuthStore} from "../../stores/auth"; | |||
| // defineExpose({ | |||
| // loadContactsFromServer, | |||
| // }); | |||
| const state = reactive<{ | |||
| isAuthError: boolean, | |||
| isContactDataLoadError: boolean, | |||
| isContactDataLoading: boolean, | |||
| searchQuery: string, | |||
| normalContacts: ContactData[], | |||
| flexContacts: ContactData[], // Generic type for now | |||
| }>({ | |||
| isAuthError: false, | |||
| isContactDataLoadError: false, | |||
| isContactDataLoading: true, | |||
| searchQuery: "", | |||
| normalContacts: [], | |||
| flexContacts: [] | |||
| }) | |||
| const contacts = useContactsStore() | |||
| init() | |||
| function init() { | |||
| state.isAuthError = false | |||
| state.isContactDataLoadError = false | |||
| state.isContactDataLoading = true | |||
| weappAuth() | |||
| .then(r => { | |||
| contacts.loadContactsFromServer().then( | |||
| contactList => { | |||
| console.log("contactList", contactList) | |||
| generateContactGroupList(contactList) | |||
| state.isContactDataLoading = false | |||
| }) | |||
| .catch(e => { | |||
| state.isAuthError = false | |||
| state.isContactDataLoadError = true | |||
| state.isContactDataLoading = false | |||
| }) | |||
| }) | |||
| .catch(e=> { | |||
| console.log("error", e) | |||
| state.isAuthError = true | |||
| state.isContactDataLoadError = false | |||
| state.isContactDataLoading = false | |||
| }) | |||
| registerRouterBackListener((to, from) => { | |||
| if ((from.url === "/pages/contact-new/index" && to.url === "/pages/invite/index") | |||
| || (from.url === "/pages/contact-edit/index" && to.url === "/pages/invite/index") | |||
| ) { | |||
| generateContactGroupList(contacts.allContacts) | |||
| } | |||
| }) | |||
| } | |||
| const onAuthErrorRefresh = () => { | |||
| init() | |||
| } | |||
| const onContactDataLoadErrorRefresh = () => { | |||
| state.isContactDataLoadError = false | |||
| state.isContactDataLoading = true | |||
| contacts.loadContactsFromServer().then( | |||
| contactList => { | |||
| console.log("contactList", contactList) | |||
| generateContactGroupList(contactList) | |||
| state.isContactDataLoading = false | |||
| }) | |||
| .catch(e => { | |||
| state.isContactDataLoadError = true | |||
| state.isContactDataLoading = false | |||
| }) | |||
| } | |||
| const generateContactGroupList = (contactList: ContactData[]) => { | |||
| state.normalContacts = [] | |||
| state.flexContacts = [] | |||
| for (const item of contactList) { | |||
| if (item.flexVisit === true) state.flexContacts.push(item) | |||
| else state.normalContacts.push(item) | |||
| } | |||
| } | |||
| const goToContactNewPage = () => { | |||
| Router.toContactNew() | |||
| } | |||
| const goToContactEditPage = (item) => { | |||
| Router.toContactEdit({ data: item }) | |||
| } | |||
| </script> | |||
| <template> | |||
| <view class="h-100 d-flex flex-column"> | |||
| <BackgroundBasic/> | |||
| <NutNavbar title=""></NutNavbar> | |||
| <view class="pl-3 pt-3 pr-3 h3 d-flex"> | |||
| <view class="flex-grow-1"> | |||
| 我的邀约 | |||
| </view> | |||
| </view> | |||
| <View class="scroll 100vh"> | |||
| <View class="mt-3 p-3"> | |||
| <View class="border bg-white p-3 d-flex flex-column" hover-class="card-hover-gray" @tap="goToContactNewPage()" > | |||
| <View class="d-flex justify-content-center"> | |||
| <Image :src="require('./invite.jpeg')" class="p-3" mode='heightFix' style="height: 15vh"/> | |||
| </View> | |||
| <View class="d-flex justify-content-center"> | |||
| <View class="fas fa-plus-circle text-black-50" style="font-size: 120%"> 新邀约</View> | |||
| </View> | |||
| </View> | |||
| </View> | |||
| <View v-if="!state.isContactDataLoading"> | |||
| <View v-if="state.isAuthError"> | |||
| <nut-empty description="连接出现问题,请稍后重试"> | |||
| <div style="margin-top: 10px"> | |||
| <nut-button type="default" @tap="onAuthErrorRefresh">刷新</nut-button> | |||
| </div> | |||
| </nut-empty> | |||
| </View> | |||
| <View v-else-if="state.isContactDataLoadError"> | |||
| <nut-empty description="连接出现问题,请稍后重试"> | |||
| <div style="margin-top: 10px"> | |||
| <nut-button type="default" @tap="onContactDataLoadErrorRefresh">刷新</nut-button> | |||
| </div> | |||
| </nut-empty> | |||
| </View> | |||
| <View v-else> | |||
| <View class="h4 p-3">来访联系人</View> | |||
| <View class="container-fluid"> | |||
| <View class="row w-100"> | |||
| <View style="width: 25vw" v-for="item in state.normalContacts"> | |||
| <View class="m-2 p-3 border" hover-class="card-hover-gray" @tap="goToContactEditPage(item)"> | |||
| <View class="d-flex justify-content-center"> | |||
| <NutBadge :value="item.isVIP?'VIP':''"> | |||
| <NutAvatar size="normal" color="white" :bg-color="BjxHelper.mbString2RgbHex(item.name)" class="overflow-hidden"> | |||
| <img v-if="item.avatar" :src="item.avatar" /> | |||
| <view v-else-if="BjxHelper.getBJXFirstChar(item.name)">{{BjxHelper.getBJXFirstChar(item.name)}}</view> | |||
| <view v-else> | |||
| <Text className='fas fa-user fa-lg'/> | |||
| </view> | |||
| </NutAvatar> | |||
| </NutBadge> | |||
| </View> | |||
| <View class="d-flex justify-content-center small b pt-2 text-nowrap overflow-hidden"> | |||
| {{item.name}} | |||
| </View> | |||
| </View> | |||
| </View> | |||
| </View> | |||
| </View> | |||
| <View class="h4 p-3">可随时来访联系人</View> | |||
| <View class="container-fluid"> | |||
| <View class="row w-100"> | |||
| <View style="width: 25vw" v-for="item in state.flexContacts"> | |||
| <View class="m-2 p-3 border" hover-class="card-hover-gray" @tap="goToContactEditPage(item)"> | |||
| <View class="d-flex justify-content-center"> | |||
| <NutBadge :value="item.isVIP?'VIP':''"> | |||
| <NutAvatar size="normal" color="white" :bg-color="BjxHelper.mbString2RgbHex(item.name)" class="overflow-hidden"> | |||
| <img v-if="item.avatar" :src="item.avatar" /> | |||
| <view v-else-if="BjxHelper.getBJXFirstChar(item.name)">{{BjxHelper.getBJXFirstChar(item.name)}}</view> | |||
| <view v-else> | |||
| <Text className='fas fa-user fa-lg'/> | |||
| </view> | |||
| </NutAvatar> | |||
| </NutBadge> | |||
| </View> | |||
| <View class="d-flex justify-content-center small b pt-2 text-nowrap overflow-hidden"> | |||
| {{item.name}} | |||
| </View> | |||
| </View> | |||
| </View> | |||
| </View> | |||
| </View> | |||
| </View> | |||
| </View> | |||
| <View v-else class="d-flex flex-column"> | |||
| <NutSkeleton v-for="_ in 10" class="p-3" height="15px" animated avatar avatar-size="50px" row="1"/> | |||
| </View> | |||
| </View> | |||
| </view> | |||
| </template> | |||
| @@ -1,6 +1,6 @@ | |||
| export default definePageConfig({ | |||
| navigationBarTitleText: '', | |||
| usingComponents: {}, | |||
| navigationStyle: 'custom', | |||
| disableScroll: true | |||
| disableScroll: true, | |||
| usingComponents: {}, | |||
| }) | |||
| @@ -0,0 +1,18 @@ | |||
| page { | |||
| height: 100%; | |||
| } | |||
| .nut-navbar { | |||
| background: transparent; | |||
| } | |||
| .scroll { | |||
| flex: 1; | |||
| overflow: scroll; | |||
| } | |||
| .skeleton { | |||
| flex: 1; | |||
| overflow: hidden; | |||
| } | |||
| @@ -0,0 +1,169 @@ | |||
| <script setup lang="ts"> | |||
| import { reactive } from 'vue' | |||
| import { View } from '@tarojs/components' | |||
| import './index.scss' | |||
| import {weappAuth} from "../../utils"; | |||
| import {GroupedPassRecords, usePassRecordsStore} from "../../stores/pass-records"; | |||
| import {useContactsStore} from "../../stores/contacts"; | |||
| const state = reactive<{ | |||
| isPageDataLoading: boolean, | |||
| isAuthError: boolean, | |||
| groupedPassRecords: GroupedPassRecords[], | |||
| }>({ | |||
| isPageDataLoading: true, | |||
| isAuthError: false, | |||
| groupedPassRecords: [], | |||
| }) | |||
| const passRecords = usePassRecordsStore() | |||
| const contacts = useContactsStore() | |||
| init() | |||
| function init() { | |||
| state.isAuthError = false | |||
| state.isPageDataLoading = true | |||
| weappAuth().then(r => { | |||
| console.log(r) | |||
| passRecords.loadPassRecordsFromServer().then( passRecords => { | |||
| state.groupedPassRecords = passRecords | |||
| console.log("aaa",state.groupedPassRecords ) | |||
| // console.log(state.groupedPassRecords) | |||
| state.isPageDataLoading = false | |||
| }) | |||
| .catch(error => { | |||
| console.log("error", error) | |||
| state.isAuthError = true | |||
| state.isPageDataLoading = false | |||
| }) | |||
| }).catch(e => { | |||
| console.log("error", e) | |||
| state.isAuthError = true | |||
| state.isPageDataLoading = false | |||
| }) | |||
| } | |||
| const onAuthErrorRefresh = () => { | |||
| init() | |||
| } | |||
| // const onPullDownRefresh = () => { | |||
| // console.log("onPullDownRefresh") | |||
| // state.isRefresherTriggered = false | |||
| // } | |||
| function onPullDownRefresh (e) { | |||
| console.log("onPullDownRefresh", e) | |||
| // state.isRefresherTriggered = false | |||
| } | |||
| // | |||
| // | |||
| // const show = ref(false); | |||
| // | |||
| // const state = reactive({ | |||
| // msg: '欢迎使用 NutUI4.0 开发小程序', | |||
| // msg2: '你成功了~', | |||
| // isVisible1: false, | |||
| // val: '' | |||
| // }) | |||
| // | |||
| // const handleClick = msg => { | |||
| // state.msg = msg | |||
| // } | |||
| // | |||
| // useDidShow(() => { | |||
| // console.log("did show is run xxxxxxx.") | |||
| // }) | |||
| // | |||
| // useLoad(() => { | |||
| // console.log("use load is run xxxxxxx.") | |||
| // }) | |||
| </script> | |||
| <template> | |||
| <view class="h-100 d-flex flex-column"> | |||
| <BackgroundBasic/> | |||
| <NutNavbar title=""></NutNavbar> | |||
| <View class="w-100" style="overflow-x: hidden"> | |||
| <View class="pl-3 pt-3 pr-3 h3 d-flex"> | |||
| <View class="flex-grow-1"> | |||
| 来访记录 | |||
| </View> | |||
| </View> | |||
| <View class="d-flex text-black-50 pb-2 pr-3"> | |||
| <View class="flex-grow-1"></View> | |||
| <View>最近30天的来访</View> | |||
| </View> | |||
| </View> | |||
| <View v-if="state.isAuthError"> | |||
| <nut-empty description="连接出现问题,请稍后重试"> | |||
| <div style="margin-top: 10px"> | |||
| <nut-button type="default" @tap="onAuthErrorRefresh">刷新</nut-button> | |||
| </div> | |||
| </nut-empty> | |||
| </View> | |||
| <View class="scroll 100vh" v-else> | |||
| <view class="scroll 100vh" v-if="!state.isPageDataLoading"> | |||
| <Scroll-View style="height: 100vh" :scrollY="true"> | |||
| <Notification v-for="item in state.groupedPassRecords" :item="item"/> | |||
| <view class="container pt-5 pb-3"> | |||
| <view class="row"> | |||
| <view class="col"/> | |||
| <view class="col text-center text-black-50"> | |||
| <nut-divider> 没有更多了 </nut-divider> | |||
| </view> | |||
| <view class="col"/> | |||
| </view> | |||
| </view> | |||
| </Scroll-View> | |||
| </view> | |||
| <View v-else class="skeleton"> | |||
| <NutSkeleton v-for="_ in 10" class="pl-4 pt-4 pb-4 pr-5" height="20px" width="60vw" animated avatar avatar-size="50px" row="2"/> | |||
| </View> | |||
| </View> | |||
| </view> | |||
| <!-- <view class="p-4">--> | |||
| <!-- <button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">使用电话号码登录</button>--> | |||
| <!-- </view>--> | |||
| <!-- <Counter/>--> | |||
| <!-- <nut-cell title="展示弹出层" is-link @click="show = true"></nut-cell>--> | |||
| <!-- <nut-popup :style="{ padding: '30px 50px' }" v-model:visible="show">正文</nut-popup>--> | |||
| <!-- <View><Text>{{state.msg}}</Text></View>--> | |||
| <!-- <nut-button type="primary" @click="handleClick(state.msg2)">点我</nut-button>--> | |||
| <!-- <Add color="red" />--> | |||
| <!-- <div class="alert alert-primary" role="alert">--> | |||
| <!-- A simple primary alert—check it out!--> | |||
| <!-- </div>--> | |||
| <!-- <h1>Example heading <span class="badge bg-secondary">New</span></h1>--> | |||
| <!-- <button type="button" class="btn btn-primary">--> | |||
| <!-- Notifications <span class="badge text-bg-secondary">4</span>--> | |||
| <!-- </button>--> | |||
| <!-- <button type="button" class="btn btn-primary position-relative">--> | |||
| <!-- Inbox--> | |||
| <!-- <span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">--> | |||
| <!-- 99+--> | |||
| <!-- <span class="visually-hidden">unread messages</span>--> | |||
| <!-- </span>--> | |||
| <!-- </button>--> | |||
| <!-- </view>--> | |||
| </template> | |||