vue_dreamfactory/src/views/protocol/Index.vue
2022-07-01 10:08:18 +08:00

490 lines
15 KiB
Vue

<template>
<v-container>
<v-card>
<v-card-title>
协议测试
</v-card-title>
<v-card-text>
<v-row justify="start">
<v-col cols="6">
<v-text-field v-model="ws_url"
label="服务端连接地址"
variant="outlined"
clearable
:error="error"
:error-messages="error_message"
:disabled="isconnect || connecting"
clear-icon="mdi-cancel"></v-text-field>
</v-col>
<v-col cols="3">
<v-btn flat
:loading="connecting"
@click="isconnect ? disconnect():connect()"
color="secondary">
{{isconnect ? '断开':'连接'}}
</v-btn>
</v-col>
</v-row>
<v-divider inset></v-divider>
<v-row class="mt-5">
<v-col cols="2">
<v-select v-model="mainSelect"
:items="proto_models"
item-title="mainType"
item-value="subs"
label="mainType"
:disabled="!isconnect"
@update:modelValue="mainSelectUpdate"
single-line
return-object></v-select>
</v-col>
<v-col cols="2">
<v-select v-model="subSelect"
:items="mainSelect.subs"
item-title="subType"
item-value="reqproto"
label="subType"
:disabled="!isconnect || mainSelect.disabled"
@update:modelValue="subSelectUpdate"
single-line
return-object></v-select>
</v-col>
</v-row>
<v-divider inset></v-divider>
<v-row v-if="reqproto.length > 0"
class="mt-5">
<v-col v-for="item in reqproto"
:key="item.FieldName"
cols="4">
<v-card>
<v-card-title>{{item.FieldName}}</v-card-title>
<v-card-text>
<v-text-field v-if="item.FieldType != 'Object'"
color="tertiary"
v-model="item.FieldValue"
:label="item.FieldName"
:type="item.FieldType"
:hint="item.FieldType"
:disabled="!isconnect"
outlined
clearable></v-text-field>
<Vue3JsonEditor v-else
v-model="item.FieldValue"
@json-change="(v)=>{item.FieldValue = v}"
:showBtns="false"
:mode="'code'"
lang="zh"
:expandedOnStart="false"></Vue3JsonEditor>
</v-card-text>
</v-card>
</v-col>
</v-row>
<v-row class="mt-5">
<v-col cols="3">
<v-btn flat
class="text-capitalize"
:disabled="subSelect == null"
@click="reqprotohandle"
color="secondary">
request
</v-btn>
</v-col>
</v-row>
</v-card-text>
</v-card>
<v-card class="mt-12">
<v-card-title>
<v-row justify="space-between">
<v-col>输出</v-col>
<v-col cols="auto">
<v-btn flat
prepend-icon="mdi-broom"
@click="logs=[]"
color="secondary">
Clear
</v-btn>
</v-col>
</v-row>
</v-card-title>
<v-divider></v-divider>
<v-responsive class="overflow-y-auto"
height="500">
<v-lazy :options="{threshold: .5}"
min-height="200"
transition="fade-transition">
<v-list>
<v-list-item v-for="log in logs"
:key="log">
<v-alert :type="log.type"
variant="outlined"
:title="log.title">
<template v-if="log.data"
v-slot:append>
<v-list-item-avatar end>
<v-btn variant="text"
size="x-large"
@click="log.isshow = !log.isshow"
:icon="log.isshow ? 'mdi-chevron-left':'mdi-chevron-down'"></v-btn>
</v-list-item-avatar>
</template>
<div v-if="log.data"
v-show="log.isshow">
<v-divider></v-divider>
<pre>{{log.data}}</pre>
</div>
</v-alert>
</v-list-item>
</v-list>
</v-lazy>
</v-responsive>
</v-card>
<v-snackbar v-model="error">
{{ error_message }}
<template v-slot:actions>
<v-btn color="pink"
variant="text"
@click="error = false">
Close
</v-btn>
</template>
</v-snackbar>
</v-container>
</template>
<script>
import { Base64 } from 'js-base64'
import md5 from 'js-md5'
import { reactive } from 'vue'
import proto from '@/pb/proto'
import { socket } from '@/utils/socket'
import { Vue3JsonEditor } from 'vue3-json-editor'
import { defineComponent } from 'vue'
export default defineComponent({
name: 'Protocol',
components: { Vue3JsonEditor },
data() {
return {
ws_url: 'ws://localhost:7891/gateway',
isconnect: false,
connecting: false,
error: false,
error_message: '',
proto_models: null,
mainSelect: { protoName: '', mainType: 'User', subs: [] },
subSelect: null,
reqproto: [],
reqloading: false,
islogin: false,
account: '',
serverId: 0,
logs: [],
isshow: true,
showdata: { name: 'liwei1dao', aog: 123 },
resultInfo: { li: 123 },
}
},
computed: {},
setup() {
const proto_models = reactive([
{ mainType: 'notify', disabled: true, subs: [] },
{ mainType: 'user', subs: [] },
{ mainType: 'items', subs: [] },
{ mainType: 'mail', subs: [] },
{ mainType: 'friend', subs: [] },
{ mainType: 'equipment', subs: [] },
{ mainType: 'hero', subs: [] },
])
for (const v of Object.keys(proto)) {
for (const v1 of proto_models) {
// console.log('protoName', v)
let protoName = v.toLowerCase()
//找到模块的消息对象
let index = protoName.indexOf(v1.mainType)
if (index == 0) {
let reqindex = protoName.indexOf('req')
let respindex = protoName.indexOf('resp')
let pushindex = protoName.indexOf('push')
if (reqindex != -1) {
let sub = protoName.substring(index + v1.mainType.length, reqindex)
let iskeep = false
for (const v2 of v1.subs) {
if (v2.subType == sub) {
v2.reqproto = proto[v]
iskeep = true
break
}
}
if (!iskeep) {
v1.subs.push({
reqName: v,
mainType: v1.mainType,
subType: sub,
reqproto: proto[v],
})
// console.log(sub + 'Req')
}
}
if (respindex != -1) {
let sub = protoName.substring(index + v1.mainType.length, respindex)
let iskeep = false
for (const v2 of v1.subs) {
if (v2.subType == sub) {
v2.respName = v
v2.respproto = proto[v]
iskeep = true
break
}
}
if (!iskeep) {
v1.subs.push({
respName: v,
mainType: v1.mainType,
subType: sub,
respproto: proto[v],
})
// console.log(sub + 'Resp')
}
}
if (pushindex != -1) {
let sub = protoName.substring(index + v1.mainType.length, pushindex)
let iskeep = false
for (const v2 of v1.subs) {
if (v2.subType == sub) {
v2.pushName = v
v2.pushproto = proto[v]
iskeep = true
break
}
}
if (!iskeep) {
v1.subs.push({
pushName: v,
mainType: v1.mainType,
subType: sub,
pushproto: proto[v],
})
// console.log(sub + 'Resp')
}
}
}
}
}
return { proto_models }
},
onBeforeUnmount() {
// 关闭连接
socket.close()
},
methods: {
connect() {
// 发起连接
this.connecting = true
socket.receivelisten = this.receivelisten
socket
.init(this.ws_url)
.then((value) => {
this.error = false
this.error_message = ''
this.isconnect = true
this.connecting = false
this.pushlog('success', `连接创建成功`)
socket.closelisten = this.closelisten
})
.catch((error) => {
this.error = true
this.error_message = error
this.isconnect = false
this.connecting = false
this.subSelect = null
this.reqproto = []
this.pushlog('error', `连接创建失败:${this.ws_url}`)
})
},
disconnect() {
socket.close()
this.isconnect = false
this.subSelect = null
this.reqproto = []
},
mainSelectUpdate(v) {
console.log(v)
this.subSelect = null
this.reqproto = []
},
subSelectUpdate(v) {
this.reqproto = []
let keys = Object.keys(this.subSelect.reqproto.fields)
for (const v of keys) {
let ftype = this.subSelect.reqproto.fields[v].type
console.log('ftype', ftype)
let fvalue = null
switch (this.subSelect.reqproto.fields[v].type) {
case 'int32':
case 'int64':
case 'uint32':
case 'uint64':
case 'float32':
case 'float64':
ftype = 'number'
fvalue = 0
break
case 'string':
ftype = 'text'
fvalue = ''
break
default:
ftype = 'Object'
fvalue = {}
break
}
this.reqproto.push({
FieldName: v,
FieldType: ftype,
FieldValue: fvalue,
})
}
console.log(this.reqproto)
},
closelisten() {
this.isconnect = false
this.subSelect = null
this.reqproto = []
console.log('closelisten!')
this.pushlog('error', `连接断开${this.ws_url}`)
},
//接收服务的消息
receivelisten(msg) {
// console.log('接收到消息', msg.data.arrayBuffer())
msg.data
.arrayBuffer()
.then((buf) => new Uint8Array(buf))
.then((bytes) => {
console.log('bytes', bytes)
let message = proto.lookup('UserMessage').decode(bytes)
console.log('接收到消息 message', message)
let mainType = message.MainType
let subType = message.SubType
let iskeep = false
for (const v of this.proto_models) {
if (v.mainType == mainType) {
for (const v1 of v.subs) {
if (subType == v1.subType) {
console.log('接收到消息 v1', v1)
//找到消息组
iskeep = true
let protoobj = null
let messageobj = null
if (v1.respName) {
console.log('接收到消息 respName', v1.respName)
protoobj = proto
.lookup(v1.respName)
.decode(message.data.value)
messageobj = proto.lookup(v1.respName).toObject(protoobj)
// console.log('接收回应到消息 protoobj', protoobj)
} else {
console.log('接收到消息 pushName', v1.pushName)
protoobj = proto
.lookup(v1.pushName)
.decode(message.data.value)
messageobj = proto.lookup(v1.pushName).toObject(protoobj)
}
if (v1.pushName && v1.pushName == 'NotifyErrorNotifyPush') {
this.pushlog(
'error',
`错误信息通知: ${mainType}-${subType}-resp`,
messageobj
)
} else {
this.pushlog(
'success',
`收到回应消息: ${mainType}-${subType}-resp`,
messageobj
)
}
}
}
}
if (iskeep) {
break
}
}
if (!iskeep) {
this.pushlog(
'error',
`接收消息错误 ${mainType}-${subType}`,
'未找到指定消息对象'
)
}
})
.catch((error) => {
console.log('接收到消息异常', error)
this.pushlog('error', '接收消息异常', { msg: msg, e: e })
})
},
//请求消息
reqprotohandle() {
console.log('protoName:', this.subSelect.reqName)
let protoobj = proto.lookup(this.subSelect.reqName)
for (const v of this.reqproto) {
protoobj[v.FieldName] = v.FieldValue
}
let message = proto.lookup('UserMessage')
let any = proto.lookup('google.protobuf.Any')
message.MainType = this.subSelect.mainType
message.SubType = this.subSelect.subType
message.data = any.create({
type_url: `type.googleapis.com/${this.subSelect.reqName}`,
value: proto.lookup(this.subSelect.reqName).encode(protoobj).finish(), // Or as packed buffer
})
if (this.subSelect.reqName == 'UserLoginReq') {
//登录协议特殊处理
message.sec = this.buildsecStr(protoobj.account, protoobj.sid)
} else {
message.sec = this.buildsecStr()
}
console.log('message:', message)
let buffer = proto.lookup('UserMessage').encode(message).finish()
console.log('req buff:', buffer)
socket.send(buffer)
this.pushlog(
'success',
`发送请求消息: ${message.MainType}-${message.SubType}-req`,
proto.lookup(this.subSelect.reqName).toObject(protoobj)
)
},
buildsecStr(_account, _serverId) {
_account = _account ? _account : this.account
_serverId = _serverId ? _serverId : this.serverId
let jsonStr = JSON.stringify({
account: _account,
serverId: _serverId,
timestamp: Date.parse(new Date()) / 1000,
})
let baseStr = Base64.encode(jsonStr)
let clientMd5key = md5(baseStr)
console.log('clientMd5key:', clientMd5key)
return `CE:${clientMd5key}${baseStr}`
},
pushlog(_type, _title, _data) {
this.logs.push({
type: _type,
title: _title,
data: _data,
isshow: false,
})
},
onJsonChange(value) {
console.log('value:', value)
},
},
})
</script>