Commit 38c0718d by wxl

更改

parent 75dcdad6
{ {
"volar.tsPlugin": false "volar.tsPlugin": true
} }
\ No newline at end of file
...@@ -4187,6 +4187,17 @@ ...@@ -4187,6 +4187,17 @@
"integrity": "sha1-ovSEN6LKqaIkNueUvwceyeYc7fY=", "integrity": "sha1-ovSEN6LKqaIkNueUvwceyeYc7fY=",
"dev": true "dev": true
}, },
"clipboard": {
"version": "2.0.6",
"resolved": "https://registry.npm.taobao.org/clipboard/download/clipboard-2.0.6.tgz",
"integrity": "sha1-UpISlu7A/fd+rRdJQhshyWhkc3Y=",
"optional": true,
"requires": {
"good-listener": "^1.2.2",
"select": "^1.1.2",
"tiny-emitter": "^2.0.0"
}
},
"cliui": { "cliui": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npm.taobao.org/cliui/download/cliui-5.0.0.tgz?cache=0&sync_timestamp=1604880226973&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcliui%2Fdownload%2Fcliui-5.0.0.tgz", "resolved": "https://registry.npm.taobao.org/cliui/download/cliui-5.0.0.tgz?cache=0&sync_timestamp=1604880226973&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcliui%2Fdownload%2Fcliui-5.0.0.tgz",
...@@ -5045,6 +5056,12 @@ ...@@ -5045,6 +5056,12 @@
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
"dev": true "dev": true
}, },
"delegate": {
"version": "3.2.0",
"resolved": "https://registry.npm.taobao.org/delegate/download/delegate-3.2.0.tgz",
"integrity": "sha1-tmtxwxWFIuirV0T3INjKDCr1kWY=",
"optional": true
},
"delegates": { "delegates": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npm.taobao.org/delegates/download/delegates-1.0.0.tgz", "resolved": "https://registry.npm.taobao.org/delegates/download/delegates-1.0.0.tgz",
...@@ -5316,6 +5333,18 @@ ...@@ -5316,6 +5333,18 @@
} }
} }
}, },
"eminent-ui": {
"version": "0.0.6",
"resolved": "https://registry.npm.taobao.org/eminent-ui/download/eminent-ui-0.0.6.tgz",
"integrity": "sha1-g4N+8bzwq03YONjW0giTxzjJMAk=",
"requires": {
"github-markdown-css": "^4.0.0",
"marked": "^1.1.1",
"prismjs": "^1.21.0",
"vue": "^3.0.0",
"vue-router": "4.0.0-beta.3"
}
},
"emoji-regex": { "emoji-regex": {
"version": "7.0.3", "version": "7.0.3",
"resolved": "https://registry.npm.taobao.org/emoji-regex/download/emoji-regex-7.0.3.tgz?cache=0&sync_timestamp=1611911444344&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Femoji-regex%2Fdownload%2Femoji-regex-7.0.3.tgz", "resolved": "https://registry.npm.taobao.org/emoji-regex/download/emoji-regex-7.0.3.tgz?cache=0&sync_timestamp=1611911444344&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Femoji-regex%2Fdownload%2Femoji-regex-7.0.3.tgz",
...@@ -6911,6 +6940,11 @@ ...@@ -6911,6 +6940,11 @@
"assert-plus": "^1.0.0" "assert-plus": "^1.0.0"
} }
}, },
"github-markdown-css": {
"version": "4.0.0",
"resolved": "https://registry.npm.taobao.org/github-markdown-css/download/github-markdown-css-4.0.0.tgz",
"integrity": "sha1-vp9Mr3o4kijUw2gzYmD/yQkGHzU="
},
"glob": { "glob": {
"version": "7.1.6", "version": "7.1.6",
"resolved": "https://registry.npm.taobao.org/glob/download/glob-7.1.6.tgz", "resolved": "https://registry.npm.taobao.org/glob/download/glob-7.1.6.tgz",
...@@ -7039,6 +7073,15 @@ ...@@ -7039,6 +7073,15 @@
"minimist": "^1.2.5" "minimist": "^1.2.5"
} }
}, },
"good-listener": {
"version": "1.2.2",
"resolved": "https://registry.npm.taobao.org/good-listener/download/good-listener-1.2.2.tgz",
"integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
"optional": true,
"requires": {
"delegate": "^3.1.2"
}
},
"graceful-fs": { "graceful-fs": {
"version": "4.2.4", "version": "4.2.4",
"resolved": "https://registry.npm.taobao.org/graceful-fs/download/graceful-fs-4.2.4.tgz", "resolved": "https://registry.npm.taobao.org/graceful-fs/download/graceful-fs-4.2.4.tgz",
...@@ -8826,6 +8869,11 @@ ...@@ -8826,6 +8869,11 @@
"integrity": "sha1-n8tpvP24cXv9A5jG7C2TA2743mA=", "integrity": "sha1-n8tpvP24cXv9A5jG7C2TA2743mA=",
"dev": true "dev": true
}, },
"marked": {
"version": "1.2.9",
"resolved": "https://registry.npm.taobao.org/marked/download/marked-1.2.9.tgz",
"integrity": "sha1-U3hviwXUwBoqWna30eyZQ9Kdctw="
},
"math-random": { "math-random": {
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npm.taobao.org/math-random/download/math-random-1.0.4.tgz", "resolved": "https://registry.npm.taobao.org/math-random/download/math-random-1.0.4.tgz",
...@@ -10706,6 +10754,14 @@ ...@@ -10706,6 +10754,14 @@
"renderkid": "^2.0.4" "renderkid": "^2.0.4"
} }
}, },
"prismjs": {
"version": "1.23.0",
"resolved": "https://registry.npm.taobao.org/prismjs/download/prismjs-1.23.0.tgz?cache=0&sync_timestamp=1609438547304&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fprismjs%2Fdownload%2Fprismjs-1.23.0.tgz",
"integrity": "sha1-07OWf31yRAaQSXZSqdQP8EYGfzM=",
"requires": {
"clipboard": "^2.0.0"
}
},
"process": { "process": {
"version": "0.11.10", "version": "0.11.10",
"resolved": "https://registry.npm.taobao.org/process/download/process-0.11.10.tgz", "resolved": "https://registry.npm.taobao.org/process/download/process-0.11.10.tgz",
...@@ -11744,6 +11800,12 @@ ...@@ -11744,6 +11800,12 @@
} }
} }
}, },
"select": {
"version": "1.1.2",
"resolved": "https://registry.npm.taobao.org/select/download/select-1.1.2.tgz",
"integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=",
"optional": true
},
"select-hose": { "select-hose": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npm.taobao.org/select-hose/download/select-hose-2.0.0.tgz", "resolved": "https://registry.npm.taobao.org/select-hose/download/select-hose-2.0.0.tgz",
...@@ -13525,6 +13587,12 @@ ...@@ -13525,6 +13587,12 @@
"setimmediate": "^1.0.4" "setimmediate": "^1.0.4"
} }
}, },
"tiny-emitter": {
"version": "2.1.0",
"resolved": "https://registry.npm.taobao.org/tiny-emitter/download/tiny-emitter-2.1.0.tgz",
"integrity": "sha1-HRpW7fxRxD6GPLtTgqcjMONVVCM=",
"optional": true
},
"tiny-invariant": { "tiny-invariant": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npm.taobao.org/tiny-invariant/download/tiny-invariant-1.1.0.tgz", "resolved": "https://registry.npm.taobao.org/tiny-invariant/download/tiny-invariant-1.1.0.tgz",
...@@ -14281,10 +14349,15 @@ ...@@ -14281,10 +14349,15 @@
} }
} }
}, },
"vue-router": {
"version": "4.0.0-beta.3",
"resolved": "https://registry.npm.taobao.org/vue-router/download/vue-router-4.0.0-beta.3.tgz?cache=0&sync_timestamp=1613740713323&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-router%2Fdownload%2Fvue-router-4.0.0-beta.3.tgz",
"integrity": "sha1-5G9FgHAjpLjOc6FDoha0yeo+skM="
},
"vue-vulcan": { "vue-vulcan": {
"version": "0.1.0", "version": "0.1.0",
"resolved": "https://registry.npmjs.org/vue-vulcan/-/vue-vulcan-0.1.0.tgz", "resolved": "https://registry.npm.taobao.org/vue-vulcan/download/vue-vulcan-0.1.0.tgz",
"integrity": "sha512-N+SUD/NmVPKR1Yop2S7rBtcL0iaIkOnUuag8/WqFNLzWsNLB3k4zd/KPAz1hy4rAvYrAUPB1KHvMvrneBL05NQ==", "integrity": "sha1-vBpvGRsRaEvxbQafeYC2Hh1fSWo=",
"requires": { "requires": {
"core-js": "^3.6.5", "core-js": "^3.6.5",
"vue": "^3.0.0" "vue": "^3.0.0"
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
"@tarojs/extend": "^3.0.26", "@tarojs/extend": "^3.0.26",
"@tarojs/runtime": "3.0.26", "@tarojs/runtime": "3.0.26",
"@tarojs/taro": "3.0.26", "@tarojs/taro": "3.0.26",
"eminent-ui": "0.0.6",
"rxjs": "^6.6.3", "rxjs": "^6.6.3",
"vue": "^3.0.0", "vue": "^3.0.0",
"vue-vulcan": "^0.1.0" "vue-vulcan": "^0.1.0"
......
...@@ -2,12 +2,32 @@ export default { ...@@ -2,12 +2,32 @@ export default {
pages: [ pages: [
'pages/index/index', 'pages/index/index',
'pages/login/index', 'pages/login/index',
'pages/meeting/index' 'pages/meeting/index',
'pages/mine/index',
'pages/calling/index'
], ],
window: { window: {
backgroundTextStyle: 'light', backgroundTextStyle: 'light',
navigationBarBackgroundColor: '#fff', navigationBarBackgroundColor: '#fff',
navigationBarTitleText: 'WeChat', navigationBarTitleText: 'WeChat',
navigationBarTextStyle: 'black' navigationBarTextStyle: 'black'
} },
tabBar: {
"selectedColor": "#40a9ff",
"borderStyle": "white",
"list": [
{
"pagePath": "pages/index/index",
"text": "联系人",
"iconPath": "assets/contacts.png",
"selectedIconPath": "assets/contacts_a.png"
},
{
"pagePath": "pages/mine/index",
"text": "我的",
"iconPath": "assets/user_center.png",
"selectedIconPath": "assets/user_center_a.png"
}
]
},
} }
import { authorize } from '@tarojs/taro'; import { authorize } from '@tarojs/taro';
import { createApp } from 'vue'; import { createApp } from 'vue';
import './app.less'; import './app.less';
import { useProviders } from './hooks/common/useProvider';
import { useCalling } from './hooks/store/video/useCalling';
import { useAuthCheck } from './hooks/user/useAuthCheck';
const App = createApp({ const App = createApp({
onShow () {}, onShow () {},
// 入口组件不需要实现 render 方法,即使实现了也会被 taro 所覆盖 // 入口组件不需要实现 render 方法,即使实现了也会被 taro 所覆盖
setup() { setup() {
useAuthCheck();
useProviders(useCalling);
authorize({ authorize({
scope: 'scope.camera' scope: 'scope.camera'
}) })
......
import Taro from '@tarojs/taro'; import Taro, { navigateTo } from '@tarojs/taro';
import { useState } from "./useState"; import { useState } from "./useState";
import { ResBody } from '../../types/https'; import { ResBody } from '../../types/https';
import { from } from 'rxjs'; import { from } from 'rxjs';
...@@ -38,6 +38,7 @@ export function useRequest<T>( ...@@ -38,6 +38,7 @@ export function useRequest<T>(
const [ status, setStatus ] = useState<HttpStatus>(null); const [ status, setStatus ] = useState<HttpStatus>(null);
const [ resData, setResData ] = useState<T>(null); const [ resData, setResData ] = useState<T>(null);
const opt = { ...defaultOption, ...options }; const opt = { ...defaultOption, ...options };
const { token } = useInjector(useAuthStore, 'root');
const authInfo = useInjector(useAuthStore, 'root'); const authInfo = useInjector(useAuthStore, 'root');
...@@ -68,6 +69,10 @@ export function useRequest<T>( ...@@ -68,6 +69,10 @@ export function useRequest<T>(
}) })
const doRequest = (data: any = {}) => { const doRequest = (data: any = {}) => {
if(!token) {
navigateTo({url: 'pages/login/index'});
return;
}
setStatus('pending') ; setStatus('pending') ;
from( from(
Taro.request({ Taro.request({
......
import { HttpIntercept } from 'vue-vulcan';
import { useAuthStore } from '../store/auth/useAuthStore';
export function useAuthIntercept(): HttpIntercept {
const { token } = useAuthStore()
export function useAuthIntercept() { const requestIntercept = (req: RequestInit) => {
return new Promise((resolve, reject) => {
if(token) {
req.body.token = token;
}
return req
})
}
const responseIntercept = () => {}
return {
requestIntercept,
responseIntercept
}
} }
\ No newline at end of file
import { watch } from "vue"; // import { watch } from "vue";
import { useInjector } from "../../../hooks/common/useInjector"; // import { useInjector } from "../../../hooks/common/useInjector";
import { useRequest } from "../../../hooks/common/useRequest"; // import { useRequest } from "../../../hooks/common/useRequest";
import { useState } from "../../../hooks/common/useState"; // import { useState } from "../../../hooks/common/useState";
import { useAuthStore } from "../auth/useAuthStore"; // import { useAuthStore } from "../auth/useAuthStore";
import { useAgoraClient } from "./useAgoraClient"; // import { useAgoraClient } from "./useAgoraClient";
export function useVideoCallStore() { // export function useVideoCallStore() {
const [isMini, setMiniState] = useState(false); // const [isMini, setMiniState] = useState(false);
const [channelInfo, getChannelInfo, status] = useRequest<any>('/getAgoraToken', {}, {auto: false}); // const [channelInfo, getChannelInfo, status] = useRequest<any>('/getAgoraToken', {}, {auto: false});
const { user } = useInjector(useAuthStore); // const { user } = useInjector(useAuthStore);
const agora = useAgoraClient(); // const agora = useAgoraClient();
const joinChannel = (channel_id?: string) => { // const joinChannel = (channel_id?: string) => {
getChannelInfo({channel_id}); // getChannelInfo({channel_id});
watch( status, val => { // watch( status, val => {
if(val === 'success') { // if(val === 'success') {
const token = channelInfo.value.agora_token; // const token = channelInfo.value.agora_token;
const cid = channelInfo.value.channel_id; // const cid = channelInfo.value.channel_id;
agora.joinChannel(token, cid, user.value.id); // agora.joinChannel(token, cid, user.value.id);
} // }
}) // })
} // }
return { // return {
isMini, // isMini,
streams: agora.streamList, // streams: agora.streamList,
action: { // action: {
setMiniState, // setMiniState,
joinChannel // joinChannel
} // }
} // }
} // }
...@@ -3,6 +3,9 @@ import { filter, tap } from 'rxjs/operators'; ...@@ -3,6 +3,9 @@ import { filter, tap } from 'rxjs/operators';
import { useState } from '../../../hooks/common/useState'; import { useState } from '../../../hooks/common/useState';
import { onMounted } from 'vue'; import { onMounted } from 'vue';
import * as AgoraMiniappSDK from '../../../libs/Agora_SDK_for_WeChat'; import * as AgoraMiniappSDK from '../../../libs/Agora_SDK_for_WeChat';
import { useInjector } from '../../common/useInjector';
import { useChannelInfo } from './useChannelInfo';
import { useAuthStore } from '../auth/useAuthStore';
interface VideoItemData { interface VideoItemData {
url: string; url: string;
...@@ -30,25 +33,27 @@ export function useAgoraClient() { ...@@ -30,25 +33,27 @@ export function useAgoraClient() {
const channelState$ = new BehaviorSubject<string>('leave'); const channelState$ = new BehaviorSubject<string>('leave');
const [streamList, setStreamList] = useState<VideoItemData[]>([]) const [streamList, setStreamList] = useState<VideoItemData[]>([]);
const { current, onReady } = useInjector(useChannelInfo, 'root');
const { user } = useInjector(useAuthStore, 'root');
onMounted( () => { onMounted( () => {
streamLog$.subscribe(console.log);
subscribeRemoteStream(); subscribeRemoteStream();
}) })
const joinChannel = (ctoken: string, cid: string, uid: string) => { onReady( () => {
agoraInit$ agoraInit$
.pipe(tap(_=>console.log('准备加入频道'))) .pipe(tap(_=>console.log('准备加入频道')))
.subscribe( .subscribe(
_ => client.join(ctoken, cid, uid, () => { _ => client.join(current.value.agora_token, current.value.channel_id, user.value.id, () => {
channelState$.next('joined'); channelState$.next('joined');
streamLog$.next('频道加入成功'+ctoken); streamLog$.next('频道加入成功'+current.value.agora_token);
pushLocalStream(); pushLocalStream();
}, console.log), }, console.log),
console.log console.log
) )
} })
const leaveChannel = () => { const leaveChannel = () => {
client.leave( () => channelState$.next('leave')) client.leave( () => channelState$.next('leave'))
...@@ -100,7 +105,6 @@ export function useAgoraClient() { ...@@ -100,7 +105,6 @@ export function useAgoraClient() {
return { return {
streamList, streamList,
joinChannel,
leaveChannel, leaveChannel,
pushLocalStream pushLocalStream
} }
......
import { onSocketMessage, sendSocketMessage, showModal } from "@tarojs/taro";
import { Subject } from "rxjs";
import { useInjector } from "../../common/useInjector";
import { onMounted } from "vue";
import { useAuthStore } from "../auth/useAuthStore";
import { useChannelInfo } from "./useChannelInfo";
import { useState } from "../../common/useState";
import { UserData } from "../../../types/auth";
import { useSocket } from "./useSocket";
interface CallingMessage {
fromID: string;
fromName: string;
toID: string;
toName:string;
companyID: string;
channelID: string;
msgMainFlag:string;
msgSubFlag: string;
}
export function useCalling() {
const [targetUser, setTarget] = useState<UserData>(null)
const { user } = useInjector(useAuthStore, 'root');
const channel = useInjector(useChannelInfo, 'root');
const ws = useSocket()
// 初始化websocket
onMounted( () => {
ws.init(`wss://www.if-ar.com:3009?fromID=${user.value.id}&fromName=${user.value.nickname}&signID=SA&companyID=${user.value.company_id}`)
onSocketMessage( res => {
console.log(res)
const data = JSON.parse(res.data)
if(data.msgMainFlag === 'CallOffer') {
switch(data.msgSubFlag) {
case '':
showModal({
title: `收到来自${data.fromName}的呼叫,是否同意?`,
success: () => answer(data, 'Connect'),
fail: () => answer(data, 'Hangup')
})
}
}
})
})
// 发出呼叫
const send = () => {
channel.createChannel();
channel.onReady( () => {
const data = JSON.stringify({
fromID: user.value.id,
fromName: user.value.nickname,
toID: targetUser.value.id,
toNmame: targetUser.value.nickname,
channelID: channel.current.value.channel_id,
msgMainFlag: 'CallOffer',
msgSubFlag: 'Request'
})
sendSocketMessage({ data })
});
}
// 回应呼叫
const answer = (sendData: CallingMessage, action: 'Hangup' | 'Connect') => {
if(action === 'Connect') channel.joinCallingChannel(sendData.channelID);
const data = JSON.stringify({
fromID: user.value.id,
fromName: user.value.nickname,
toID: sendData.fromID,
toName: sendData.fromName,
channelID: sendData.channelID,
msgMainFlag: 'CallAnswer',
msgSubFlag: action
})
sendSocketMessage({ data })
}
// 挂断
const hangup = () => {
const data = JSON.stringify({
fromID: user.value.id,
fromName: user.value.nickname,
toID: targetUser.value.id,
toNmame: targetUser.value.nickname,
channelID: channel.current.value.channel_id,
msgMainFlag: 'CallOffer',
msgSubFlag: 'Hangup'
})
}
const callingState$ = new Subject()
return {
send,
targetUser,
setTarget,
callingState$
}
}
\ No newline at end of file
import { useState } from "../../common/useState";
import { useRequest } from "../../common/useRequest"; import { useRequest } from "../../common/useRequest";
import { watch } from "vue";
import { BehaviorSubject } from "rxjs";
interface ChannelData {
channel_id: string;
agora_token: string;
members: string[];
}
export function useChannelInfo() { export function useChannelInfo() {
const [channelInfo, request] = useRequest<any>('/getAgoraToken'); const [current, setCurrent] = useState<ChannelData>(null);
const [channelInfo, request] = useRequest<ChannelData>('/getAgoraToken', {}, {auto: false});
const ready$ = new BehaviorSubject<boolean>(false);
const createChannel = () => {
request()
}
const joinCallingChannel = (id: string) => {
request({channel_id: id})
}
const onReady = ( callback: () => void) => {
ready$.subscribe( r => { r && callback() })
}
watch(channelInfo, val => {
console.log('channel', val)
setCurrent(val);
val && ready$.next(true);
})
return { return {
channelInfo, current,
request joinCallingChannel,
createChannel,
onReady
} }
} }
\ No newline at end of file
import { connectSocket, onSocketOpen, sendSocketMessage } from "@tarojs/taro"
import { timer } from "rxjs";
import { useInjector } from "../../common/useInjector";
import { useAuthStore } from "../auth/useAuthStore";
export function useSocket() {
const { user } = useInjector(useAuthStore);
const init = (url: string) => {
connectSocket({url});
startHeartConnect()
}
const startHeartConnect = () => {
const data = JSON.stringify({
msgMainFlag:"Heart",
fromID: user.value.id,
fromName: user.value.nickname,
toID: '0'
})
onSocketOpen( () => {
timer(0, 5000)
.subscribe( _ => {
sendSocketMessage({ data })
})
})
}
return {
init
}
}
\ No newline at end of file
import { onMounted } from "vue";
import { useAuthStore } from "../store/auth/useAuthStore";
import { navigateTo } from '@tarojs/taro'
export function useAuthCheck() {
const user = useAuthStore();
onMounted( () => {
console.log("check", user)
if(!user.token.value) {
navigateTo({url: '/pages/login/index'})
}
})
}
\ No newline at end of file
import { useRequest } from "../common/useRequest";
export function useContactList() {
const [ data ] = useRequest<any>('/getUserList');
return data
}
\ No newline at end of file
export default {
navigationBarTitleText: '呼叫联系人'
}
<script setup>
import { useInjector } from '../../hooks/common/useInjector';
import { computed, getCurrentInstance, onMounted } from 'vue';
import { useCalling } from '../../hooks/store/video/useCalling';
const calling = useInjector(useCalling);
const targetUser = computed( () => calling.targetUser.value );
onMounted( () => {
calling.send();
})
</script>
<template>
<view class="page">
<view class="call-box">
<image class="avatar" :src="targetUser?.avatar"></image>
<text class="tips">正在呼叫{{targetUser?.nickname}}...</text>
</view>
<image class="hangup" src="../../assets/hangup.png"></image>
</view>
</template>
<style lang="less">
page{
width: 100%;
height: 100%;
}
.page{
background:#333;
width:100%;
height:100%;
.call-box{
position: absolute;
top: 30%;
left:50%;
transform: translate(-50%, -50%);
.avatar{
width: 160px;
height: 160px;
overflow: hidden;
border-radius: 50%;
display: block;
margin: 20px auto;
}
.tips{
color: #fff;
font-size: 38px;
}
}
.hangup{
width: 120px;
height: 120px;
display: block;
left: 50%;
transform: translateX(-50%);
position: absolute;
bottom: 100px;
}
}
</style>
\ No newline at end of file
<template> <template>
<view class="index"> <view class="index">
<button @tap="gotoLogin()">登录</button> <view class="contact-list">
<button @tap="gotoMeeting()">进入会议</button> <view class="contact-item" v-for="(item, key) in contacts" :key="key">
<image class="avatar" :src="item.avatar" />
<view class="info">
<view>{{item.nickname}}</view>
<text>{{item.permission}}</text>
</view>
<image @tap="callContacter(item)" class="call" src="../../assets/call.png" />
</view>
</view>
</view> </view>
</template> </template>
<script setup> <script setup lang="ts">
import { navigateTo } from '@tarojs/taro'; import { navigateTo } from '@tarojs/taro';
import { UserData } from '../../types/auth';
import { useInjector } from '../../hooks/common/useInjector';
import { useCalling } from '../../hooks/store/video/useCalling';
import { useContactList } from '../../hooks/user/useContactsList';
import './index.less'; import './index.less';
const gotoMeeting = () => { const contacts = useContactList();
navigateTo({url: '/pages/meeting/index'}) const calling = useInjector(useCalling);
}
const gotoLogin = () => { const callContacter = (data: UserData) => {
navigateTo({url: '/pages/login/index'}) calling.setTarget(data);
navigateTo({url: '/pages/calling/index'});
} }
</script> </script>
<style lang="less">
.contact-list{
padding: 20px 30px;
.contact-item{
margin: 25px 0;
padding: 25px 0;
border-bottom: 1px solid #f7f7f7;
display: flex;
align-items: center;
.avatar{
width: 100px;
height: 100px;
border-radius: 50%;
overflow:hidden;
}
.info{
flex: 1;
padding: 0 30px;
}
.call{
width: 80px;
height: 80px;
}
}
}
</style>
export default {
navigationBarTitleText: '登录页'
}
<script setup> <script setup>
import { useFormModel } from '../../hooks/common/useFormModel';
import { useAuthStore } from '../../hooks/store/auth/useAuthStore';
import { watch } from 'vue';
import { navigateTo, navigateBack } from '@tarojs/taro';
const userInfo = useAuthStore()
const [formData, action, states, resData ] = useFormModel('/loginIn', {login_id: '', login_password: ''});
watch(states.httpStatus, status => {
if(status === 'success') {
console.log('登陆成功')
userInfo.saveToken(resData.value.token);
userInfo.saveUserInfo(resData.value);
navigateBack()
}
})
</script> </script>
<template> <template>
<view></view> <view>
</template> <view class="login-box">
\ No newline at end of file <input class="login-item" placeholder="请输入用户名" v-model="formData.login_id">
<input class="login-item" placeholder="请输入密码" v-model="formData.login_password">
<button @tap="action.submit()">登录</button>
</view>
</view>
</template>
<style lang="less">
.login-box{
background: #999;
border-radius: 10px;
padding: 10px;
width: 90%;
position: absolute;
top:50%;
left:50%;
transform: translate(-50%,-50%);
.login-item{
margin: 20px 0;
}
}
</style>
\ No newline at end of file
<script setup>
</script>
<template>
<view>个人中心</view>
</template>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment