refactor: 确立独立子工程架构 (backend, admin, mpuniapp) 并同步更新 AGENTS.md 规范

这个提交包含在:
wikiboss
2026-09-20 17:05:22 +08:00
父节点 de3cf8b870
当前提交 9fa1d1fbd0
共有 1679 个文件被更改,包括 204798 次插入 和 16817 次删除

查看文件

@@ -0,0 +1,27 @@
const PAGE_PATH = '/pages/API/websocket/socketTask'
const platformInfo = process.env.uniTestPlatformInfo.toLocaleLowerCase()
const isMP = platformInfo.startsWith('mp')
describe('ExtApi-WebSocket', () => {
if(isMP) {
it('skip', async () => {
// 小程序平台开发工具只允许两个socket连接,uni-push、自动化测试个占据一个,此示例必然失败
expect(1).toBe(1)
})
return
}
let page;
let res;
beforeAll(async () => {
page = await program.reLaunch(PAGE_PATH)
await page.waitFor(600);
await page.callMethod('jest_connectSocket');
await page.waitFor(1500);
res = await page.data('data.jest_result');
});
it('Check ', async () => {
expect(res).toBe(2);
});
});

查看文件

@@ -0,0 +1,239 @@
<template>
<page-head title="websocket通讯示例"></page-head>
<view class="uni-padding-wrap">
<view class="uni-btn-v">
<text class="websocket-msg">{{ showMsg }}</text>
<button class="uni-btn-v" type="primary" @click="connect">
连接websocket服务
</button>
<button class="uni-btn-v" v-show="connected" type="primary" @click="send">
发送一条消息
</button>
<button class="uni-btn-v" v-show="connected" type="primary" @click="sendArrayBuffer">
发送一条ArrayBuffer消息,返回也是ArrayBuffer
</button>
<button class="uni-btn-v" type="primary" @click="close">
断开websocket服务
</button>
<text class="websocket-tips">发送消息后会收到一条服务器返回的消息(与发送的消息内容一致)</text>
</view>
</view>
</template>
<script setup lang="uts">
const connected = ref(false)
const connecting = ref(false)
const socketTask = ref(null as SocketTask | null)
const msg = ref('')
const platform = ref('')
type DataType = {
jest_result: number,
}
//自动化测试例专用
const data = reactive({
jest_result: 0,
} as DataType)
const showMsg = computed(() : string => {
if (connected.value) {
if (msg.value.length > 0) {
return '收到消息:' + msg.value
} else {
return '等待接收消息'
}
} else {
return '尚未连接'
}
})
function connect() {
if (connected.value || connecting.value) {
uni.showModal({
content: '正在连接或者已经连接,请勿重复连接',
showCancel: false,
})
return
}
connecting.value = true
uni.showLoading({
title: '连接中...',
})
socketTask.value = uni.connectSocket({
url: 'wss://websocket.dcloud.net.cn',
success: (res : any) => {
// 这里是接口调用成功的回调,不是连接成功的回调,请注意
console.log('uni.connectSocket success', res)
},
fail: (err : any) => {
// 这里是接口调用失败的回调,不是连接失败的回调,请注意
console.log('uni.connectSocket fail', err)
},
})
socketTask.value?.onOpen((res : any) => {
connecting.value = false
connected.value = true
uni.hideLoading()
uni.showToast({
icon: 'none',
title: '连接成功',
})
console.log('onOpen', res)
})
socketTask.value?.onError((err : any) => {
connecting.value = false
connected.value = false
uni.hideLoading()
uni.showModal({
content: '连接失败,可能是websocket服务不可用,请稍后再试',
showCancel: false,
})
console.log('onError', err)
})
socketTask.value?.onMessage((res : OnSocketMessageCallbackResult) => {
if(res.data instanceof ArrayBuffer){
var int8 = new Int8Array(res.data)
msg.value = int8.toString()
console.log('onMessage', res)
}else{
msg.value = res.data as string
console.log('onMessage', res)
}
})
socketTask.value?.onClose((res : any) => {
connected.value = false
socketTask.value = null
msg.value = ''
console.log('onClose', res)
})
}
function send() {
const data =
'from ' +
platform.value +
' : ' +
parseInt(Math.random() * 10000 + '').toString()
socketTask.value?.send({
data,
success: (res : any) => {
console.log(res)
},
fail: (err : any) => {
console.log(err)
},
} as SendSocketMessageOptions)
}
function sendArrayBuffer() {
const data = new ArrayBuffer(2)
let int8= new Int8Array(data)
int8[0]=1
int8[1]=2
socketTask.value?.send({
data,
success: (res : any) => {
console.log(res)
},
fail: (err : any) => {
console.log(err)
},
} as SendSocketMessageOptions)
}
function close() {
socketTask.value?.close({
code: 1000,
reason: 'close reason from client',
success: (res : any) => {
console.log('uni.closeSocket success', res)
},
fail: (err : any) => {
console.log('uni.closeSocket fail', err)
},
} as CloseSocketOptions)
}
//自动化测试例专用
function jest_connectSocket() {
socketTask.value = uni.connectSocket({
url: 'wss://websocket.dcloud.net.cn',
success: (_) => {
data.jest_result++
},
fail: (_) => {
data.jest_result = 0
},
})
socketTask.value?.onOpen((_) => {
const message =
'from ' +
platform.value +
' : ' +
parseInt(Math.random() * 10000 + '').toString()
socketTask.value?.send({
data: message,
success: (_) => {
data.jest_result++
},
fail: (_) => {
data.jest_result = 0
},
} as SendSocketMessageOptions)
})
socketTask.value?.onError((_) => {
data.jest_result = 0;
})
}
onLoad(() => {
platform.value = uni.getDeviceInfo().platform as string
})
onUnload(() => {
uni.hideLoading()
let task = socketTask.value
if (task != null) {
task.close({
code: 1000,
reason: 'close reason from client',
success: (res : any) => {
console.log('uni.closeSocket success', res)
},
fail: (err : any) => {
console.log('uni.closeSocket fail', err)
},
} as CloseSocketOptions)
}
})
defineExpose({
data,
jest_connectSocket
})
</script>
<style>
.uni-btn-v {
padding: 5px 0;
}
.uni-btn-v {
margin: 10px 0;
}
.websocket-msg {
padding: 40px 0px;
text-align: center;
font-size: 14px;
line-height: 40px;
color: #666666;
}
.websocket-tips {
padding: 40px 0px;
text-align: center;
font-size: 14px;
line-height: 24px;
color: #666666;
}
</style>

查看文件

@@ -0,0 +1,191 @@
<template>
<page-head title="websocket通讯示例"></page-head>
<view class="uni-padding-wrap">
<view class="uni-btn-v">
<text class="websocket-msg">{{ showMsg }}</text>
<button class="uni-btn-v" type="primary" @click="connect">
连接websocket服务
</button>
<button class="uni-btn-v" v-show="connected" type="primary" @click="send">
发送一条消息
</button>
<button class="uni-btn-v" type="primary" @click="close">
断开websocket服务
</button>
<text class="websocket-tips">发送消息后会收到一条服务器返回的消息(与发送的消息内容一致)</text>
<text
class="websocket-tips" style="color: red;">web端和小程序端uni-push功能、app-android端和app-ios端的web-view组件日志回显、app-harmony端的日志回显会占用一个socket链接,此时使用全局的socket
api会引发混乱。应使用socketTask操作websocket链接。</text>
<text class="websocket-tips">小程序端日志回显功能也会占用一个socket链接,如果不希望使用此功能可以在HBuilderX控制台关闭日志回显。</text>
<button class="uni-btn-v" type="primary" @click="goSocketTask">
跳转 socketTask 示例
</button>
</view>
</view>
</template>
<script setup lang="uts">
const connected = ref(false)
const connecting = ref(false)
const msg = ref('')
const roomId = ref('')
const platform = ref('')
const showMsg = computed(() : string => {
if (connected.value) {
if (msg.value.length > 0) {
return '收到消息:' + msg.value
} else {
return '等待接收消息'
}
} else {
return '尚未连接'
}
})
onLoad(() => {
platform.value = uni.getDeviceInfo().platform as string
})
onUnload(() => {
uni.closeSocket({
code: 1000,
reason: 'close reason from client',
success: (res : any) => {
console.log('uni.closeSocket success', res)
},
fail: (err : any) => {
console.log('uni.closeSocket fail', err)
},
} as CloseSocketOptions)
uni.hideLoading()
})
const connect = () => {
if (connected.value || connecting.value) {
uni.showModal({
content: '正在连接或者已经连接,请勿重复连接',
showCancel: false,
})
return
}
connecting.value = true
uni.showLoading({
title: '连接中...',
})
uni.connectSocket({
url: 'wss://websocket.dcloud.net.cn',
header:{
"test":"uniapp x"
},
protocols: null,
success: (res : any) => {
// 这里是接口调用成功的回调,不是连接成功的回调,请注意
console.log('uni.connectSocket success', res)
},
fail: (err : any) => {
// 这里是接口调用失败的回调,不是连接失败的回调,请注意
console.log('uni.connectSocket fail', err)
},
})
uni.onSocketOpen((res) => {
connecting.value = false
connected.value = true
uni.hideLoading()
uni.showToast({
icon: 'none',
title: '连接成功',
})
console.log('onOpen', res)
})
uni.onSocketError((err) => {
connecting.value = false
connected.value = false
uni.hideLoading()
uni.showModal({
content: '连接失败,可能是websocket服务不可用,请稍后再试',
showCancel: false,
})
console.log('onError', err)
})
uni.onSocketMessage((res) => {
if (res.data instanceof ArrayBuffer) {
var int8 = new Int8Array(res.data)
msg.value = int8.toString()
console.log('onMessage', res)
} else {
msg.value = res.data as string
console.log('onMessage', res)
}
})
uni.onSocketClose((res) => {
connected.value = false
msg.value = ''
console.log('onClose', res)
})
}
const send = () => {
uni.sendSocketMessage({
data:
'from ' +
platform.value +
' : ' +
parseInt((Math.random() * 10000).toString()).toString(),
success: (res : any) => {
console.log(res)
},
fail: (err : any) => {
console.log(err)
},
} as SendSocketMessageOptions)
}
const close = () => {
uni.closeSocket({
code: 1000,
reason: 'close reason from client',
success: (res : any) => {
console.log('uni.closeSocket success', res)
},
fail: (err : any) => {
console.log('uni.closeSocket fail', err)
},
} as CloseSocketOptions)
}
const goSocketTask = () => {
uni.navigateTo({
url: '/pages/API/websocket/socketTask',
})
}
</script>
<style>
.uni-btn-v {
padding: 5px 0;
}
.uni-btn-v {
margin: 10px 0;
}
.websocket-msg {
padding: 40px 0px;
text-align: center;
font-size: 14px;
line-height: 40px;
color: #666666;
}
.websocket-tips {
padding: 10px 0px;
text-align: center;
font-size: 14px;
line-height: 24px;
color: #666666;
}
</style>