Ver código fonte

weapp auth 使用 promise

tags/AL.0.8.0_20240113_base
yuan 1 ano atrás
pai
commit
407624f59c
12 arquivos alterados com 271 adições e 160 exclusões
  1. +0
    -57
      src/components/Auth.vue
  2. +40
    -24
      src/components/contact-form/index.vue
  3. +5
    -3
      src/components/contact/index.vue
  4. +5
    -0
      src/pages/contact/index.scss
  5. +32
    -70
      src/pages/contact/index.vue
  6. +4
    -0
      src/pages/index/index.scss
  7. +15
    -4
      src/pages/index/index.vue
  8. +1
    -1
      src/pages/login/index.vue
  9. +1
    -1
      src/pages/settings/index.vue
  10. +113
    -0
      src/stores/contacts.ts
  11. +1
    -0
      src/utils/index.ts
  12. +54
    -0
      src/utils/weapp-auth.ts

+ 0
- 57
src/components/Auth.vue Ver arquivo

@@ -1,57 +0,0 @@
<template>
<View/>
</template>
<script>
import { useAuthStore } from '../stores/auth'
import {NavigateType, Router} from "tarojs-router-next";
import {Route, Session} from "../utils";
import Taro from "@tarojs/taro";

export default {
setup() {
const auth = useAuthStore()

if (Session.has('expires_in_timestamp')
&& Session.get('expires_in_timestamp') >= new Date().getTime()+60*60*1000) {
auth.isLoggedIn = true;
console.log(Session.all())
} else {
console.log(SERVER_URL+ '/system/api/weapp/login')
Taro.login({
success: function (res) {
Taro.request({
url: SERVER_URL + '/system/api/weapp/login',
data: {code: res.code},
success: result => {
// console.log(result)
for (const [key, value] of Object.entries(result.data.data)) {
Session.set(key, value);
if (key === 'expires_in') {
Session.set('expires_in_timestamp', new Date().getTime() + (value * 60 * 1000))
}
}
console.log(Session.all())
auth.isLoggedIn = true
if (!Session.has('access_token')) {
if (Taro.getCurrentPages().length > 0) {
Router.navigate( {url: '/pages/login/index'}, { data: {prevPage:"/" + Taro.getCurrentPages()[0].route}, type: NavigateType.reLaunch } )
}
else {
Router.navigate( {url: '/pages/login/index'}, { type: NavigateType.reLaunch } )
}
}
}
})
},
fail: function (res) {
console.log(res)

}
})
}

return {}
}

}
</script>

+ 40
- 24
src/components/contact-form/index.vue Ver arquivo

@@ -5,22 +5,24 @@ import { Router } from 'tarojs-router-next'


import { reactive, ref } from 'vue';
import {BjxHelper} from "../../utils";
import {useContactsStore} from "../../stores/contacts";

const props = defineProps(['data'])

// const isSuggestionsShow = ref(false)
const contacts = useContactsStore()

const state = reactive({
isSuggestionsShow: false,
name: props.data ? props.data.name : '',
company: props.data ? props.data.company : '',
avatar: props.data ? props.data.avatar : '',
isNickNameSuggestionsShow: false,
contactData: props.data ? props.data : contacts.getEmptyContactData(),
newAvatar: '',
number: '',
isFlexVisit: props.data ? props.data.isFlexVisit : true,
// lastName: BjxHelper.getBJXFirstChar(name),
date: '',
isDateSelectorVisible: false
});


const openSwitch = (param) => {
state[`${param}`] = true;
};
@@ -32,7 +34,7 @@ const setChooseValue = (param) => {
};

function setShowSuggestions(isShow: Boolean) {
state.isSuggestionsShow = isShow
state.isNickNameSuggestionsShow = isShow
}

const updateFacePhoto = () => {
@@ -41,12 +43,19 @@ const updateFacePhoto = () => {
sizeType: ['compressed'], // 可以指定是原图还是压缩图,默认二者都有
success: function (res) {
// 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片
state.avatar = res.tempFilePaths
console.log(state.avatar)
state.newAvatar = res.tempFilePaths
console.log(state.newAvatar)
},
})
}

const updateNickName = (value) => {
if (value === null) {
state.isNickNameSuggestionsShow = false
}
else {
state.contactData.nickName = BjxHelper.getBJXFirstChar(state.contactData.name) + value;
}
}
</script>

<template>
@@ -56,52 +65,59 @@ const updateFacePhoto = () => {
<view>
<view class="d-flex justify-content-center">
<nut-avatar size="192" @click="updateFacePhoto" class="overflow-hidden">
<img v-if="state.avatar" :src="state.avatar" />
<img v-if="state.contactData.avatar" :src="state.contactData.avatar" />
<view v-else class="d-flex align-items-center justify-content-center h-100 w-100">
<Text class="fas fa-user fa-6x"></Text>
</view>
</nut-avatar>
</view>
<view class="d-flex justify-content-center pt-3">
<view class="btn btn-secondary badge-pill" @tap="updateFacePhoto">{{state.avatar?'更换':'添加'}}面部识别照片</view>
<view class="btn btn-secondary badge-pill" @tap="updateFacePhoto">{{state.contactData.avatar || state.newAvatar ?'更换':'添加'}}面部识别照片</view>
</view>
</view>
</nut-form-item>
<nut-form-item label="姓名">
<nut-input v-model="state.name" class="nut-input-text" />
<nut-input v-model="state.contactData.name" class="nut-input-text" />
</nut-form-item>
<nut-form-item label="称呼">
<nut-input v-model="state.nickName" class="nut-input-text" @focus="setShowSuggestions(true)" @blur="setShowSuggestions(false)" />
<nut-input v-model="state.contactData.nickName" @change="state.isNickNameSuggestionsShow = false" class="nut-input-text" @focus="setShowSuggestions(true)" @blur="setShowSuggestions(false)" />
</nut-form-item>
<view class="suggestions" v-show="state.isSuggestionsShow">
<view>先生</view>
<view>女士</view>
<view>小姐</view>
<view><Text className="fas fa-info-circle text-info"/> 您可以从列表中选择或直接填写</view>
<view class="suggestions" style="background-color: #EEE" v-show="state.isNickNameSuggestionsShow">
<view @tap="updateNickName('先生')">{{BjxHelper.getBJXFirstChar(state.contactData.name)}}先生</view>
<view @tap="updateNickName('女士')">{{BjxHelper.getBJXFirstChar(state.contactData.name)}}女士</view>
<view @tap="updateNickName('小姐')">{{BjxHelper.getBJXFirstChar(state.contactData.name)}}小姐</view>
<view @tap="updateNickName(null)">
<View class="d-flex">
<View class="flex-grow-1">
<Text className="fas fa-info-circle text-info"/> 您可以从列表中选择或直接填写
</View>
<View class="text-primary pr-3">关闭</View>
</View>
</view>
</view>

<nut-form-item label="电话">
<nut-input v-model="state.phone" class="nut-input-text" />
<nut-input v-model="state.contactData.phone" class="nut-input-text" />
</nut-form-item>
<nut-form-item label="公司">
<nut-input v-model="state.company" class="nut-input-text" />
<nut-input v-model="state.contactData.company" class="nut-input-text" />
</nut-form-item>

<nut-form-item label="VIP">
<view class="d-flex">
<view class="flex-grow-1"></view>
<nut-switch v-model="state.isVIP" active-color="blue" />
<nut-switch v-model="state.contactData.isVIP" active-color="blue" />
</view>
</nut-form-item>

<nut-form-item label="可随时来访">
<view class="d-flex">
<view class="flex-grow-1"></view>
<nut-switch v-model="state.isFlexVisit" active-color="blue" />
<nut-switch v-model="state.contactData.flexVisit" active-color="blue" />
</view>
</nut-form-item>

<nut-form-item label="下次到访日期" v-show="!state.isFlexVisit">
<nut-form-item label="下次到访日期" v-show="!state.contactData.flexVisit">
<view class="d-flex calendar">
<view class="flex-grow-1"></view>
<view class="text-dark" @tap="openSwitch('isDateSelectorVisible')">


+ 5
- 3
src/components/contact/index.vue Ver arquivo

@@ -4,11 +4,12 @@ import { Router } from 'tarojs-router-next'
import {BjxHelper, ScreenHelper} from "../../utils";
import "./index.scss";
import {ref} from "vue";
import {ContactData} from "../../stores/contacts";

const props = defineProps(['items'])
// const elevatorHeight = ref(ScreenHelper.getScreenHeight() - ScreenHelper.getStatusBarHeight() - ScreenHelper.getWindowBarHeight())

const clickItem = (key: string, item: any) => {
const clickItem = (key: string, item: ContactData) => {
console.log(key);
console.log(item.name);

@@ -28,8 +29,9 @@ const clickItem = (key: string, item: any) => {
<template #default="{ item }">
<view class="d-flex flex-row pb-2">
<view class="pr-4 pt-2 h6">
<nut-avatar size="normal" color="white" :bg-color="BjxHelper.mbString2RgbHex(item.name)">
<view v-if="BjxHelper.getBJXFirstChar(item.name)">{{BjxHelper.getBJXFirstChar(item.name)}}</view>
<nut-avatar 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>


+ 5
- 0
src/pages/contact/index.scss Ver arquivo

@@ -10,3 +10,8 @@ page {
flex: 1;
overflow: scroll;
}

.skeleton {
flex: 1;
overflow: hidden;
}

+ 32
- 70
src/pages/contact/index.vue Ver arquivo

@@ -3,89 +3,53 @@ 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 {gql} from "graphql-tag";
import {PinyinHelper, GQLRequest} from "../../utils";

interface ContactData {
id: number
name: string
isVIP: boolean
flexVisit: boolean
isBlock: boolean
nickName: string
avatar: string
phone: string
company: string
nextVisitDate?: string
firstCharPinyin: string
}
import {PinyinHelper, GQLRequest, weappAuth} from "../../utils";
import {useAuthStore} from "../../stores/auth";

// defineExpose({
// loadContactsFromServer,
// });

const state = reactive<{
isContactDataLoading: boolean;
searchQuery: string;
contactFullList: ContactData[]; // Using the ContactData interface
contactList: ContactData[]; // Generic type for now
contactGroupedList: any[]; // Generic type for now
}>({
isContactDataLoading: true,
searchQuery: "",
contactFullList: [],
contactList: [],
contactGroupedList: [],
})
const contacts = useContactsStore()

const val = ref('');

const GQL_QUERY_ALL_CONTACT = gql`
query {
visitors {
id
name
nickname
type
visitorCompany
avatar
phone
}
}
`

GQLRequest.query(GQL_QUERY_ALL_CONTACT, {})
.then( result => {
// console.log(result)
for(let item of result.data.visitors) {
state.contactFullList.push({
id: item.id,
name: item.name,
nickName: item.nickname,
avatar: item.avatar,
company: item.visitorCompany,
phone: item.phone,
flexVisit: "",
isBlock: "",
isVIP: "",
firstCharPinyin: PinyinHelper.getPinyinGroupName(item.name)
} as ContactData)
}
console.log(state.contactFullList)
state.isContactDataLoading = false
state.contactList = state.contactFullList
generateContactGroupList()
})

asyncInit()

async function asyncInit() {
state.isContactDataLoading = true
weappAuth()
.then(r => {
contacts.loadContactsFromServer().then(
contactList => {
console.log("contactList", contactList)
generateContactGroupList(contactList)
state.isContactDataLoading = false
})
})
}

const onSearchValueChange = (value) => {
state.contactList = []
for(const item of state.contactFullList) {
if (item.name.match(value)) {
state.contactList.push(item)
}
}
generateContactGroupList()
console.log(state.contactList)
let contactList = contacts.searchContacts(value)
generateContactGroupList(contactList)
// console.log(state.contactGroupedList)
}
const generateContactGroupList = () => {

const generateContactGroupList = (contactList: ContactData[]) => {
let contactGroupedList = []
for (const item of state.contactList) {
for (const item of contactList) {
const firstChar = item.firstCharPinyin;
if (!contactGroupedList[firstChar]) {
contactGroupedList[firstChar] = { title: firstChar, list: [] };
@@ -125,9 +89,7 @@ const generateContactGroupList = () => {
<Contact :items="state.contactGroupedList"/>
</view>
<View v-else class="d-flex flex-column">
<NutSkeleton class="p-3" height="15px" animated avatar avatar-size="45px" row="1"/>
<NutSkeleton class="p-3" height="15px" animated avatar avatar-size="45px" row="1"/>
<NutSkeleton class="p-3" height="15px" animated avatar avatar-size="45px" row="1"/>
<NutSkeleton v-for="_ in 10" class="p-3" height="15px" animated avatar avatar-size="50px" row="1"/>
</View>
</view>



+ 4
- 0
src/pages/index/index.scss Ver arquivo

@@ -11,4 +11,8 @@ page {
overflow: scroll;
}

.skeleton {
flex: 1;
overflow: hidden;
}


+ 15
- 4
src/pages/index/index.vue Ver arquivo

@@ -4,15 +4,24 @@ import { View, Text } from '@tarojs/components'

import './index.scss'
import Counter from '../../components/Counter.vue'
import Auth from "../../components/Auth"
import { ref } from 'vue'
import {useDidShow, useLoad} from "@tarojs/taro";
import { Date } from '@nutui/icons-vue-taro';
import Notification from "../../components/notification";
import {weappAuth} from "../../utils";

const state = reactive<{
isPageDataLoading: boolean,
}>({
isPageDataLoading: true,
})

asyncInit()


async function asyncInit() {
await weappAuth()
state.isPageDataLoading = false
}
//
//
// const show = ref(false);
@@ -43,7 +52,6 @@ import Notification from "../../components/notification";


<template>
<Auth/>
<!-- <view class="h-25 bg-danger">22222222</view>-->
<view class="h-100 d-flex flex-column">
<BackgroundBasic/>
@@ -60,7 +68,7 @@ import Notification from "../../components/notification";
</View>
</View>

<view class="scroll">
<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='[]'/>
@@ -87,6 +95,9 @@ import Notification from "../../components/notification";
</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>




+ 1
- 1
src/pages/login/index.vue Ver arquivo

@@ -89,7 +89,7 @@ const getPhoneNumber = (e) => {
服务器错误,请稍后重试
</View>
<View class="text-center text-black-50 p-5" v-show="isWxUserNotStaff">
您还不是数字人产品中注册的企业员工,请联系您的公司管理员开通,或<ExternalLink class="text-primary" href="https://www.digimeta.com.cn/">与缔智元联系</ExternalLink>。
您还不是数字人产品中注册的企业员工,请联系您的公司管理员开通,或<ExternalLink class="text-primary" href="https://www.digimeta.com.cn/contact">与缔智元联系</ExternalLink>。
</View>
<View class="w-100 d-flex justify-content-center position-absolute">
<NutButton type="success" @click="clickPhoneNumberButton" openType='getPhoneNumber' @getphonenumber="getPhoneNumber">


+ 1
- 1
src/pages/settings/index.vue Ver arquivo

@@ -39,7 +39,7 @@ const onExitLoginButtonClicked = () => {
}

const onAboutUsClicked = () => {
Route.navigateTo({url: '/pages/web-view/index'}, {data: {href: "https://www.digimeta.com.cn/"}})
Route.navigateTo({url: '/pages/web-view/index'}, {data: {href: "https://www.digimeta.com.cn/contact"}})
console.log("onAboutUsClicked")

}


+ 113
- 0
src/stores/contacts.ts Ver arquivo

@@ -0,0 +1,113 @@
// https://pinia.esm.dev/introduction.html
import { defineStore } from 'pinia'
import {GQLRequest, PinyinHelper, Session} from "../utils";
import Taro from "@tarojs/taro";
import {gql} from "graphql-tag";
import {Ref, ref, UnwrapRef} from "vue";
import {rejects} from "assert";

export interface ContactData {
id?: number
name: string
isVIP: boolean
flexVisit: boolean
isBlock: boolean
nickName: string
avatar: string
phone: string
company: string
nextVisitDate?: string
firstCharPinyin: string
}

export const useContactsStore = defineStore('contacts', () => {

const isContactsLoaded: Ref<UnwrapRef<boolean>> = ref(false)
const allContacts: Ref<UnwrapRef<ContactData[]>> = ref([])

const GQL_QUERY_ALL_CONTACT = gql`
query {
visitors {
id
name
nickname
type
visitorCompany
avatar
phone
}
}
`

function loadContactsFromServer () {
return new Promise((resolve, reject) => {
isContactsLoaded.value = false
const items: ContactData[] = []
return GQLRequest.query(GQL_QUERY_ALL_CONTACT, {})
.then(result => {
if (result.code == 500) {
reject("Network Error")
} else {
// console.log(result)
for (let item of result.data.visitors) {
items.push({
id: item.id,
name: item.name,
nickName: item.nickname,
avatar: item.avatar,
company: item.visitorCompany,
phone: item.phone,
flexVisit: "",
isBlock: "",
isVIP: "",
firstCharPinyin: PinyinHelper.getPinyinGroupName(item.name)
} as ContactData)
}
allContacts.value = items.sort((a, b) => a.firstCharPinyin.localeCompare(b.firstCharPinyin));

console.log(allContacts.value)
isContactsLoaded.value = true
resolve(allContacts.value)
}
})
})
}

function searchContacts(searchQuery: string) {
const searchedContacts: ContactData[] = []
for(const item of allContacts.value) {
if (item.name.match(searchQuery)) {
searchedContacts.push(item)
}
}
return searchedContacts
}

function getEmptyContactData(): ContactData {
return {
id: undefined,
name: "",
isVIP: false,
flexVisit: false,
isBlock: false,
nickName: "",
avatar: "",
phone: "",
company: "",
nextVisitDate: undefined,
firstCharPinyin: ""
}
}
return { allContacts , isContactsLoaded, loadContactsFromServer, searchContacts, getEmptyContactData}
})

// You can even use a function (similar to a component setup()) to define a Store for more advanced use cases:
// export const useCounterStore = defineStore('counter', () => {
// const count = ref(0)
//
// function increment() {
// count.value++
// }
//
// return {count, increment}
// })

+ 1
- 0
src/utils/index.ts Ver arquivo

@@ -5,3 +5,4 @@ export { Route } from './route';
export { ScreenHelper } from './screen-helper';
export { Session } from './session'
export { PinyinHelper } from './pinyin-helper'
export { weappAuth } from './weapp-auth'

+ 54
- 0
src/utils/weapp-auth.ts Ver arquivo

@@ -0,0 +1,54 @@
import {useAuthStore} from "../stores/auth";
import {Session} from "./session";
import Taro from "@tarojs/taro";
import {NavigateType, Router} from "tarojs-router-next";

export async function weappAuth () {
return new Promise((resolve, reject) => {
const auth = useAuthStore()
if (Session.has('expires_in_timestamp')
&& Session.get('expires_in_timestamp') >= new Date().getTime() + 60 * 60 * 1000) {
auth.isLoggedIn = true;
console.log(Session.all())
resolve()
} else {
console.log(SERVER_URL + '/system/api/weapp/login')
return Taro.login({
success: function (res) {
Taro.request({
url: SERVER_URL + '/system/api/weapp/login',
data: {code: res.code},
success: result => {
if (result.data.code != 200) {
reject(result)
} else {
for (const [key, value] of Object.entries(result.data.data)) {
Session.set(key, value);
if (key === 'expires_in') {
Session.set('expires_in_timestamp', new Date().getTime() + (value * 60 * 1000))
}
}
console.log(Session.all())
auth.isLoggedIn = true
resolve(result.data)
if (!Session.has('access_token')) {
if (Taro.getCurrentPages().length > 0) {
Router.navigate({url: '/pages/login/index'}, {
data: {prevPage: "/" + Taro.getCurrentPages()[0].route},
type: NavigateType.reLaunch
})
} else {
Router.navigate({url: '/pages/login/index'}, {type: NavigateType.reLaunch})
}
}
}},
fail: res => reject(res)
})
},
fail: function (res) {
console.log(res)
}
})
}
})
}

Carregando…
Cancelar
Salvar