| @@ -2,15 +2,17 @@ | |||
| import './index.scss' | |||
| import { BjxHelper } from "../../utils"; | |||
| /** | |||
| * props: todayPassTime: Json Array | |||
| * example: [["YYYY-MM-DD hh:mm:ss"], ["YYYY-MM-DD hh:mm:ss"]] | |||
| */ | |||
| const props = defineProps(['avatar', 'name', 'company', 'is-vip', 'pass-date', 'pass-time', 'today-pass-time']) | |||
| let lastName = BjxHelper.getBJXFirstChar(props.name) | |||
| let isVIP = JSON.parse(props.isVip) | |||
| let todayPassJsonObject = JSON.parse(props.todayPassTime) | |||
| const props = defineProps(['item']) | |||
| const item = props.item.passRecords[0] | |||
| const otherItems = props.item.passRecords.slice(1) | |||
| console.log(item.userName, otherItems.length , otherItems) | |||
| let lastName = BjxHelper.getBJXFirstChar(item.userName) | |||
| // let isVIP = props.isVip | |||
| // let todayPassJsonObject = JSON.parse(props.todayPassTime) | |||
| </script> | |||
| @@ -21,61 +23,67 @@ let todayPassJsonObject = JSON.parse(props.todayPassTime) | |||
| <view class="card-body"> | |||
| <view class="d-flex flex-row"> | |||
| <view class="pr-3 h6"> | |||
| <nut-avatar size="normal" color="white" :bg-color="BjxHelper.mbString2RgbHex(lastName)"> | |||
| <view> | |||
| <view v-if="lastName">{{lastName}}</view> | |||
| <NutBadge :value="item.isVIP?'VIP':''"> | |||
| <NutAvatar size="normal" color="white" :bg-color="BjxHelper.mbString2RgbHex(item.userName)" class="overflow-hidden"> | |||
| <img v-if="item.faceUrl" :src="item.faceUrl" /> | |||
| <view v-else-if="BjxHelper.getBJXFirstChar(item.userName)">{{BjxHelper.getBJXFirstChar(item.userName)}}</view> | |||
| <view v-else> | |||
| <Text className='fa fa-user'/> | |||
| <Text className='fas fa-user fa-lg'/> | |||
| </view> | |||
| </view> | |||
| </nut-avatar> | |||
| </NutAvatar> | |||
| </NutBadge> | |||
| </view> | |||
| <view> | |||
| <view class="flex-grow-1"> | |||
| <view class="d-flex flex-row"> | |||
| <view v-if="props.name" class="name">{{props.name}}</view> | |||
| <view v-if="item.userName" class="name">{{item.userName}}</view> | |||
| <view v-else> | |||
| <view class="text-black-50 name"> | |||
| <Text className='text-info fas fa-exclamation-circle'/> 无姓名 | |||
| </view> | |||
| </view> | |||
| <view class="pl-2"> | |||
| <view v-if="isVIP" class="badge badge-pill badge-danger">VIP</view> | |||
| <view v-else></view> | |||
| </view> | |||
| </view> | |||
| <view class="company text-black-50"> | |||
| <view v-if="props.company">{{props.company}}</view> | |||
| <view v-if="item.company">{{item.company}}</view> | |||
| <view v-else> | |||
| <Text className='text-info fas fa-exclamation-circle'/> 无公司信息 | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <view class="pr-4 d-flex justify-content-end"> | |||
| <h5 class="pt-3" v-if="item.isBlock" style="line-height: unset !important;"> | |||
| <view class="badge badge-pill badge-light text-danger"> | |||
| <Text className="fas fa-ban text-danger"></Text> | |||
| 被阻止人员 | |||
| </view> | |||
| </h5> | |||
| <view v-else></view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <view class="card-footer bg-white"> | |||
| <view v-if="todayPassJsonObject.length === 0"> | |||
| <view v-if="otherItems.length === 0"> | |||
| <nut-collapse> | |||
| <nut-collapse-item name="name1" :title="'来访时间:'+ props.passDate" :value="props.passTime" :border=false> | |||
| <nut-collapse-item name="name1" :title="'来访时间:'+ item.date" :value="item.time" :border=false> | |||
| <template #icon> </template> | |||
| </nut-collapse-item> | |||
| </nut-collapse> | |||
| </view> | |||
| <view v-else> | |||
| <nut-collapse> | |||
| <nut-collapse-item name="name1" :title="'来访时间:'+ props.passDate" :value="props.passTime" :border=false> | |||
| <view v-for="(passTime, index) in todayPassJsonObject" :key="passTime"> | |||
| <nut-collapse-item name="name1" :title="'来访时间:'+ item.date" :value="item.time" :border=false> | |||
| <view v-for="(passTime, index) in otherItems" :key="passTime.id"> | |||
| <view class="d-flex"> | |||
| <view class="flex-grow-1"> | |||
| <view v-if="index === 0">当日还有 {{todayPassJsonObject.length}} 次记录</view> | |||
| <view v-if="index === 0">当日还有 {{otherItems.length}} 次记录</view> | |||
| <view v-else></view> | |||
| </view> | |||
| <view> {{ passTime }} </view> | |||
| <view> {{ passTime.time }} </view> | |||
| </view> | |||
| </view> | |||
| </nut-collapse-item> | |||
| </nut-collapse> | |||
| </view> | |||
| </view> | |||
| @@ -1,4 +1,4 @@ | |||
| <script setup> | |||
| <script setup lang="ts"> | |||
| import { reactive } from 'vue' | |||
| import { View, Text } from '@tarojs/components' | |||
| @@ -9,14 +9,20 @@ import {useDidShow, useLoad} from "@tarojs/taro"; | |||
| import { Date } from '@nutui/icons-vue-taro'; | |||
| import Notification from "../../components/notification"; | |||
| import {weappAuth} from "../../utils"; | |||
| import {useContactsStore} from "../../stores/contacts"; | |||
| import {GroupedPassRecords, usePassRecordsStore} from "../../stores/pass-records"; | |||
| const state = reactive<{ | |||
| isPageDataLoading: boolean, | |||
| isAuthError: boolean, | |||
| groupedPassRecords: GroupedPassRecords[], | |||
| }>({ | |||
| isPageDataLoading: true, | |||
| isAuthError: false | |||
| isAuthError: false, | |||
| groupedPassRecords: [] | |||
| }) | |||
| const passRecords = usePassRecordsStore() | |||
| init() | |||
| @@ -25,7 +31,17 @@ function init() { | |||
| state.isPageDataLoading = true | |||
| weappAuth().then(r => { | |||
| console.log(r) | |||
| state.isPageDataLoading = false | |||
| passRecords.loadPassRecordsFromServer().then( passRecords => { | |||
| state.isPageDataLoading = false | |||
| state.groupedPassRecords = passRecords | |||
| console.log("aaa",state.groupedPassRecords ) | |||
| // console.log(state.groupedPassRecords) | |||
| }) | |||
| .catch(error => { | |||
| console.log("error", error) | |||
| state.isAuthError = true | |||
| state.isPageDataLoading = false | |||
| }) | |||
| }).catch(e => { | |||
| console.log("error", e) | |||
| state.isAuthError = true | |||
| @@ -92,19 +108,19 @@ const onAuthErrorRefresh = () => { | |||
| <View class="scroll 100vh" v-else> | |||
| <view class="scroll 100vh" v-if="!state.isPageDataLoading"> | |||
| <Scroll-View :scroll-y="true"> | |||
| <Notification name="" company="小明科技2" is-vip="true" pass-date="2023-12-25" pass-time="22:22:22" today-pass-time='["22:22:21","22:22:20"]'/> | |||
| <Notification name="王远" company="joydata科技" is-vip="true" pass-date="2023-12-25" pass-time="22:22:22" today-pass-time='[]'/> | |||
| <Notification name="华雨" company="joydata科技" is-vip="false" pass-date="2023-12-25" pass-time="22:22:22" today-pass-time='["22:22:21"]'/> | |||
| <Notification name="邸为荣" company="" is-vip="false" pass-date="2023-12-25" pass-time="22:22:22" today-pass-time='["22:22:21","22:22:20"]'/> | |||
| <Notification v-for="item in state.groupedPassRecords" :item="item"/> | |||
| <!-- <Notification name="王远" company="joydata科技" is-vip="true" pass-date="2023-12-25" pass-time="22:22:22" today-pass-time='[]'/>--> | |||
| <!-- <Notification name="华雨" company="joydata科技" is-vip="false" pass-date="2023-12-25" pass-time="22:22:22" today-pass-time='["22:22:21"]'/>--> | |||
| <!-- <Notification name="邸为荣" company="" is-vip="false" pass-date="2023-12-25" pass-time="22:22:22" today-pass-time='["22:22:21","22:22:20"]'/>--> | |||
| <Notification name="邸为荣" company="" is-vip="false" pass-date="2023-12-25" pass-time="22:22:22" today-pass-time='["22:22:21","22:22:20"]'/> | |||
| <Notification name="邸为荣" company="" is-vip="false" pass-date="2023-12-25" pass-time="22:22:22" today-pass-time='["22:22:21","22:22:20"]'/> | |||
| <Notification name="邸为荣" company="" is-vip="false" pass-date="2023-12-25" pass-time="22:22:22" today-pass-time='["22:22:21","22:22:20"]'/> | |||
| <!-- <Notification name="邸为荣" company="" is-vip="false" pass-date="2023-12-25" pass-time="22:22:22" today-pass-time='["22:22:21","22:22:20"]'/>--> | |||
| <!-- <Notification name="邸为荣" company="" is-vip="false" pass-date="2023-12-25" pass-time="22:22:22" today-pass-time='["22:22:21","22:22:20"]'/>--> | |||
| <!-- <Notification name="邸为荣" company="" is-vip="false" pass-date="2023-12-25" pass-time="22:22:22" today-pass-time='["22:22:21","22:22:20"]'/>--> | |||
| <Notification name="邸为荣" company="" is-vip="false" pass-date="2023-12-25" pass-time="22:22:22" today-pass-time='["22:22:21","22:22:20"]'/> | |||
| <Notification name="邸为荣" company="" is-vip="false" pass-date="2023-12-25" pass-time="22:22:22" today-pass-time='["22:22:21","22:22:20"]'/> | |||
| <Notification name="邸为荣" company="" is-vip="false" pass-date="2023-12-25" pass-time="22:22:22" today-pass-time='["22:22:21","22:22:20"]'/> | |||
| <!-- <Notification name="邸为荣" company="" is-vip="false" pass-date="2023-12-25" pass-time="22:22:22" today-pass-time='["22:22:21","22:22:20"]'/>--> | |||
| <!-- <Notification name="邸为荣" company="" is-vip="false" pass-date="2023-12-25" pass-time="22:22:22" today-pass-time='["22:22:21","22:22:20"]'/>--> | |||
| <!-- <Notification name="邸为荣" company="" is-vip="false" pass-date="2023-12-25" pass-time="22:22:22" today-pass-time='["22:22:21","22:22:20"]'/>--> | |||
| <view class="container pt-5 pb-3"> | |||
| <view class="row"> | |||
| @@ -0,0 +1,131 @@ | |||
| // https://pinia.esm.dev/introduction.html | |||
| import { defineStore } from 'pinia' | |||
| import {GQLRequest, PinyinHelper, Session} from "../utils"; | |||
| import {gql} from "graphql-tag"; | |||
| import {ref, Ref, UnwrapRef} from "vue"; | |||
| import Taro from "@tarojs/taro"; | |||
| import moment from "moment"; | |||
| export interface PassRecords { | |||
| key: string | |||
| id: number | |||
| userName: string | |||
| userId: number | |||
| faceUrl: string | |||
| recognizedTime: string | |||
| createTime: Date | |||
| type: number | |||
| company: string | |||
| isVIP: boolean | |||
| isBlock: boolean | |||
| date: string | |||
| time: string | |||
| } | |||
| export interface GroupedPassRecords { | |||
| key: string | |||
| passRecords: PassRecords[] | |||
| } | |||
| export const usePassRecordsStore = defineStore('pass-records', () => { | |||
| const passRecords: Ref<UnwrapRef<PassRecords[]>> = ref([]) | |||
| const groupedPassRecords: Ref<UnwrapRef<GroupedPassRecords[]>> = ref([]) | |||
| const GQL_QUERY_30_DAYS_PASS_RECORDS = gql` | |||
| query ($startDate: Date, $endDate: Date ) { | |||
| passRecords8: visitorPassRecords(type: 8, startDate: $startDate, endDate: $endDate) { | |||
| id | |||
| userName | |||
| userId | |||
| faceUrl | |||
| recognizedTime | |||
| createTime | |||
| type | |||
| visitor { | |||
| isVip | |||
| isBlock | |||
| visitorCompany | |||
| } | |||
| } | |||
| passRecords9: visitorPassRecords(type: 9, startDate: $startDate, endDate: $endDate) { | |||
| id | |||
| userName | |||
| userId | |||
| faceUrl | |||
| recognizedTime | |||
| createTime | |||
| type | |||
| visitor { | |||
| isVip | |||
| isBlock | |||
| visitorCompany | |||
| } | |||
| } | |||
| } | |||
| ` | |||
| function loadPassRecordsFromServer () { | |||
| return new Promise((resolve, reject) => { | |||
| const items: PassRecords[] = [] | |||
| const startDate = moment().subtract(30, "days" ).format("YYYY-MM-DD") | |||
| const endDate = moment().add(1, "days").format("YYYY-MM-DD") | |||
| console.log(startDate, endDate) | |||
| return GQLRequest.query(GQL_QUERY_30_DAYS_PASS_RECORDS, {startDate, endDate}) | |||
| .then(result => { | |||
| if (result.code == 500) { | |||
| reject("Network Error") | |||
| } else { | |||
| console.log(result) | |||
| const resultGroups = ['passRecords8', 'passRecords9'] | |||
| for (let groupName of resultGroups) { | |||
| for (let item of result.data[groupName]) { | |||
| // console.log(item) | |||
| items.push({ | |||
| key: moment(item.recognizedTime, "YYYY-MM-DDTHH:mm:ss").format("YYYY-MM-DD")+item.userId, | |||
| id: item.id, | |||
| userName: item.userName, | |||
| userId: item.userId, | |||
| faceUrl: item.faceUrl, | |||
| recognizedTime: item.recognizedTime, | |||
| createTime: item.createTime, | |||
| type: item.type, | |||
| company: item.visitor ? item.visitor.visitorCompany : "", | |||
| isVIP: item.visitor ? item.visitor.isVip: false, | |||
| isBlock: item.visitor ? item.visitor.isBlock : false, | |||
| date: moment(item.recognizedTime, "YYYY-MM-DDTHH:mm:ss").format("YYYY-MM-DD"), | |||
| time: moment(item.recognizedTime, "YYYY-MM-DDTHH:mm:ss").format("HH:mm:ss"), | |||
| } as PassRecords) | |||
| } | |||
| } | |||
| passRecords.value = items.sort((a, b) => a.recognizedTime.localeCompare(b.recognizedTime)).reverse(); | |||
| // console.log(passRecords.value) | |||
| generatePassRecordsGroupList(passRecords.value) | |||
| console.log(groupedPassRecords.value) | |||
| resolve(groupedPassRecords.value) | |||
| } | |||
| }).catch(e => { | |||
| reject(e) | |||
| }) | |||
| }) | |||
| } | |||
| const generatePassRecordsGroupList = (passRecords: PassRecords[]) => { | |||
| let passRecordsGroupedList = [] | |||
| for (const item of passRecords) { | |||
| const key = item.key; | |||
| if (!passRecordsGroupedList[key]) { | |||
| passRecordsGroupedList[key] = { key: key, passRecords: [] }; | |||
| } | |||
| passRecordsGroupedList[key].passRecords.push(item); | |||
| } | |||
| groupedPassRecords.value = Object.values(passRecordsGroupedList) | |||
| } | |||
| const getGroupedList = () => { | |||
| return groupedPassRecords.value | |||
| } | |||
| return { loadPassRecordsFromServer, getGroupedList} | |||
| }) | |||