refactor: 确立独立子工程架构 (backend, admin, mpuniapp) 并同步更新 AGENTS.md 规范
这个提交包含在:
@@ -0,0 +1,36 @@
|
||||
const platformInfo = process.env.uniTestPlatformInfo.toLocaleLowerCase()
|
||||
const isIOS = platformInfo.startsWith('ios')
|
||||
const isMP = platformInfo.startsWith('mp')
|
||||
const isAndroid = platformInfo.startsWith('android')
|
||||
const isDom2 = process.env.UNI_APP_X_DOM2 === 'true'
|
||||
|
||||
describe('Api-createWorker', () => {
|
||||
if(isIOS || isMP || (isAndroid && isDom2)) {
|
||||
it('skip Api-createWorker', async () => {
|
||||
expect(1).toBe(1)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const PAGE_PATH = '/pages/API/create-worker/create-worker'
|
||||
let page;
|
||||
let res;
|
||||
beforeAll(async () => {
|
||||
page = await program.reLaunch(PAGE_PATH)
|
||||
await page.waitFor(1000);
|
||||
});
|
||||
|
||||
it('workerTask ', async () => {
|
||||
await page.callMethod('test_resetInputValue');
|
||||
await page.waitFor(500);
|
||||
await page.callMethod('create');
|
||||
await page.waitFor(500);
|
||||
await page.callMethod('onWorkerMsg');
|
||||
await page.callMethod('sendMessage');
|
||||
await page.waitFor(async () => {
|
||||
const taskResult = await page.data('taskResult.value')
|
||||
return taskResult.length > 0
|
||||
});
|
||||
expect(await page.data('taskResult.value')).toBe('2');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,298 @@
|
||||
<template>
|
||||
<scroll-view class="container">
|
||||
<view class="status-section">
|
||||
<text class="status-label">Worker状态: </text>
|
||||
<text class="status-text">{{statusText}}</text>
|
||||
</view>
|
||||
|
||||
<view class="button-group">
|
||||
<text class="description-text">操作步骤:1.创建Worker 2.添加消息监听 3.发送数据测试</text>
|
||||
<button class="btn" type="primary" :disabled="created_boolean" @click="create">创建Worker</button>
|
||||
<button class="btn" type="primary" @click="onWorkerMsg">添加消息监听</button>
|
||||
<button class="btn" type="primary" @click="onWorkerError">添加错误监听</button>
|
||||
<button class="btn" @click="destory" :disabled="workerStatus != 'created'">销毁Worker</button>
|
||||
</view>
|
||||
|
||||
<view class="input-section">
|
||||
<text class="section-title">输入测试值:</text>
|
||||
<text class="description-text">点击发送按钮后,会将输入值传给WorkerTask,在子线程执行+1操作后返回结果</text>
|
||||
<input class="input-field" v-model="inputValue" type="number" placeholder="请输入数字" />
|
||||
<button class="btn" type="primary" @click="sendMessage" :disabled="workerStatus != 'created'">发送到WorkerTask (值+1)</button>
|
||||
</view>
|
||||
|
||||
<view class="log-section">
|
||||
<text class="section-title">通信日志:</text>
|
||||
<scroll-view class="log-container">
|
||||
<view v-for="(log, index) in logs" :key="index" class="log-item">
|
||||
<text :class="['log-text', log.type]">{{log.message}}</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<button @click="clearLogs" class="btn clear-btn">清空日志</button>
|
||||
</view>
|
||||
|
||||
<!-- #ifdef APP-HARMONY || WEB -->
|
||||
<view class="uni-btn-v">
|
||||
<navigator url="/pages/API/create-worker/worker-sendable-transfer">
|
||||
<button type="primary">worker sendable transfer 示例</button>
|
||||
</navigator>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</scroll-view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
type TaskResultType = {
|
||||
value: string
|
||||
}
|
||||
|
||||
const created_boolean = ref<boolean>(false)
|
||||
const workerStatus = ref<string>('none') // none, created, destroyed
|
||||
const isListening = ref<boolean>(false)
|
||||
const logs = ref<Array<UTSJSONObject>>([])
|
||||
const inputValue = ref<string>('1') // 默认值为1
|
||||
const taskResult = reactive({ value: '' } as TaskResultType)
|
||||
const worker = ref<Worker | null>(null)
|
||||
|
||||
const statusText = computed(() : string => {
|
||||
switch (workerStatus.value) {
|
||||
case 'none': return '未创建';
|
||||
case 'created': return '已创建';
|
||||
case 'destroyed': return '已销毁';
|
||||
default: return '未知';
|
||||
}
|
||||
})
|
||||
|
||||
// 添加日志方法
|
||||
function addLog(message : string, type : string = 'info') {
|
||||
const now = new Date();
|
||||
const timeStr = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`;
|
||||
const logItem = {
|
||||
message: `[${timeStr}] ${message}`,
|
||||
type: type,
|
||||
time: timeStr
|
||||
} as UTSJSONObject;
|
||||
logs.value.unshift(logItem);
|
||||
// 限制日志数量
|
||||
if (logs.value.length > 50) {
|
||||
logs.value = logs.value.slice(0, 50);
|
||||
}
|
||||
}
|
||||
|
||||
// 创建Worker
|
||||
const create = () => {
|
||||
worker.value = uni.createWorker('workers/helloWorkerTask.uts');
|
||||
workerStatus.value = 'created';
|
||||
addLog('Worker创建成功', 'success');
|
||||
created_boolean.value = true;
|
||||
}
|
||||
|
||||
const onWorkerMsg = () => {
|
||||
if (worker.value == null) {
|
||||
addLog('请先创建worker', 'warning');
|
||||
return;
|
||||
}
|
||||
worker.value!.onMessage((result) => {
|
||||
// 处理Worker返回的消息
|
||||
console.log(`收到Worker消息:`, result);
|
||||
const res = result as UTSJSONObject;
|
||||
const resultData = res['data'] as string;
|
||||
taskResult.value = resultData;
|
||||
inputValue.value = taskResult.value
|
||||
addLog(`收到WorkerTask返回: ${resultData}`, 'receive');
|
||||
})
|
||||
}
|
||||
|
||||
const onWorkerError = () => {
|
||||
if (worker.value == null) {
|
||||
addLog('请先创建worker', 'warning');
|
||||
return;
|
||||
}
|
||||
worker.value!.onError((error) => {
|
||||
console.error('Worker发生错误:', error);
|
||||
// addLog(`Worker错误: ${error.message}`, 'error');
|
||||
})
|
||||
}
|
||||
|
||||
// 向workerTask发送消息
|
||||
const sendMessage = () => {
|
||||
// 检查输入值
|
||||
if (inputValue.value == '') {
|
||||
addLog('请输入有效的数字', 'warning');
|
||||
return;
|
||||
}
|
||||
const options = {
|
||||
data: inputValue.value,
|
||||
needReply: true
|
||||
};
|
||||
worker.value!.postMessage(options, null);
|
||||
addLog(`发送值到WorkerTask: ${inputValue.value}`, 'send');
|
||||
}
|
||||
|
||||
// 销毁Worker
|
||||
const destory = () => {
|
||||
if (worker.value == null) {
|
||||
addLog('没有创建worker,无法销毁', 'warning');
|
||||
return;
|
||||
}
|
||||
worker.value!.terminate();
|
||||
workerStatus.value = 'destroyed';
|
||||
isListening.value = false;
|
||||
addLog('Worker已销毁', 'warning');
|
||||
created_boolean.value = false;
|
||||
}
|
||||
|
||||
// 清空日志
|
||||
const clearLogs = () => {
|
||||
logs.value = [];
|
||||
}
|
||||
|
||||
const test_resetInputValue = () => {
|
||||
inputValue.value = '1'
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
destory();
|
||||
})
|
||||
|
||||
defineExpose({
|
||||
taskResult,
|
||||
test_resetInputValue,
|
||||
create,
|
||||
onWorkerMsg,
|
||||
sendMessage
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.container {
|
||||
flex: 1;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.status-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 20px;
|
||||
padding: 10px;
|
||||
background-color: #ffffff;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.status-label {
|
||||
font-size: 16px;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.status-text {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
|
||||
.button-group {
|
||||
flex-direction: column;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.input-section {
|
||||
margin-bottom: 20px;
|
||||
padding: 15px;
|
||||
background-color: #ffffff;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.input-field {
|
||||
/* #ifdef MP-WEIXIN */
|
||||
height: 3em;
|
||||
/* #endif */
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
border: 1px solid #dddddd;
|
||||
border-radius: 6px;
|
||||
font-size: 16px;
|
||||
margin: 10px 0;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.btn {
|
||||
/* height: 50px; */
|
||||
margin-bottom: 10px;
|
||||
padding: 5px 10px;
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.log-section {
|
||||
background-color: #ffffff;
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.log-container {
|
||||
height: 300px;
|
||||
border: 1px solid #dddddd;
|
||||
border-radius: 4px;
|
||||
padding: 10px;
|
||||
margin: 10px 0;
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.log-item {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.log-text {
|
||||
font-size: 12px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.log-text.info {
|
||||
color: #2196F3;
|
||||
}
|
||||
|
||||
.log-text.success {
|
||||
color: #4CAF50;
|
||||
}
|
||||
|
||||
.log-text.warning {
|
||||
color: #ff9800;
|
||||
}
|
||||
|
||||
.log-text.error {
|
||||
color: #f44336;
|
||||
}
|
||||
|
||||
.log-text.send {
|
||||
color: #9C27B0;
|
||||
}
|
||||
|
||||
.log-text.receive {
|
||||
color: #009688;
|
||||
}
|
||||
|
||||
.clear-btn {
|
||||
background-color: #ff9800;
|
||||
font-size: 12px;
|
||||
padding: 8px 12px;
|
||||
color: #ffffff;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.description-text {
|
||||
font-size: 14px;
|
||||
color: #666666;
|
||||
line-height: 1.4;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,46 @@
|
||||
const platformInfo = process.env.uniTestPlatformInfo.toLocaleLowerCase()
|
||||
const isIOS = platformInfo.startsWith('ios')
|
||||
const isMP = platformInfo.startsWith('mp')
|
||||
|
||||
describe('Api-uts-createWorker', () => {
|
||||
if (isMP) {
|
||||
it('skip', () => {
|
||||
expect(1).toBe(1)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (
|
||||
isIOS && (
|
||||
platformInfo.indexOf('14.5') != -1 ||
|
||||
platformInfo.indexOf('13.7') != -1 ||
|
||||
platformInfo.indexOf('12.4') != -1
|
||||
)
|
||||
) {
|
||||
it('iOS 14.5 13.7 12.4 不支持依赖uts插件测试', () => {
|
||||
expect(1).toBe(1)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const PAGE_PATH = '/pages/API/create-worker/uts-create-worker'
|
||||
let page;
|
||||
beforeAll(async () => {
|
||||
page = await program.reLaunch(PAGE_PATH)
|
||||
await page.waitFor(500);
|
||||
});
|
||||
|
||||
it('workerTask ', async () => {
|
||||
await page.callMethod('test_resetInputValue');
|
||||
await page.waitFor(500);
|
||||
await page.callMethod('create');
|
||||
await page.waitFor(500);
|
||||
await page.callMethod('sendMessage');
|
||||
await page.waitFor(500);
|
||||
await page.waitFor(async () => {
|
||||
const taskResult = await page.callMethod('test_taskResult')
|
||||
return taskResult.length > 0
|
||||
});
|
||||
expect(await page.callMethod('test_taskResult')).toBe('2');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,325 @@
|
||||
<template>
|
||||
<scroll-view class="container">
|
||||
<view class="status-section">
|
||||
<text class="status-label">Worker状态: </text>
|
||||
<text class="status-text">{{statusText}}</text>
|
||||
</view>
|
||||
|
||||
<!-- #ifdef APP-IOS -->
|
||||
<view class="ios-tip-section">
|
||||
<text class="ios-tip-text">⚠️ 提示:Windows系统标准基座iOS平台因平台限制无法运行本地UTS插件,需要自定义基座才能使用示例中的uts-worker插件</text>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
|
||||
<view class="button-group">
|
||||
<text class="description-text">操作步骤:1.创建Worker 2.发送数据测试(消息监听已在创建Worker时添加)</text>
|
||||
<button class="btn" type="primary" :disabled="created_boolean" @click="create">UTS插件中创建Worker</button>
|
||||
<button class="btn" @click="destory" :disabled="workerStatus != 'created'">UTS插件中销毁Worker</button>
|
||||
</view>
|
||||
|
||||
<view class="input-section">
|
||||
<text class="section-title">输入测试值:</text>
|
||||
<text class="description-text">点击发送按钮后,会将输入值传给WorkerTask,在子线程执行+1操作后返回结果</text>
|
||||
<input class="input-field" v-model="inputValue" type="number" placeholder="请输入数字" />
|
||||
<button class="btn" type="primary" @click="sendMessage" :disabled="workerStatus != 'created'">通过UTS插件发送到WorkerTask (值+1)</button>
|
||||
</view>
|
||||
|
||||
<view class="log-section">
|
||||
<text class="section-title">通信日志:</text>
|
||||
<scroll-view class="log-container">
|
||||
<view v-for="(log, index) in logs" :key="index" class="log-item">
|
||||
<text :class="['log-text', log.type]">{{log.message}}</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<button @click="clearLogs" class="btn clear-btn">清空日志</button>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { onWorkerError, createWorkers, sendWorkerMessage, onWorkerMessage, destroyWorker, UTSWorkerAddListenerOptions, UTSWorkerReceiveEventCallback, UTSWorkerSendWorkerMessageOptions, UTSWorkerErrorOptions } from "@/uni_modules/uts-worker";
|
||||
|
||||
const created_boolean = ref(false)
|
||||
const workerStatus = ref('none') // none, created, destroyed
|
||||
const isListening = ref(false)
|
||||
const logs = ref([] as Array<UTSJSONObject>)
|
||||
const inputValue = ref('1') // 默认值为1
|
||||
const taskResult = ref('')
|
||||
|
||||
const statusText = computed((): string => {
|
||||
switch(workerStatus.value) {
|
||||
case 'none': return '未创建';
|
||||
case 'created': return '已创建';
|
||||
case 'destroyed': return '已销毁';
|
||||
default: return '未知';
|
||||
}
|
||||
})
|
||||
|
||||
// 添加日志方法
|
||||
function addLog(message: string, type: string = 'info') {
|
||||
const now = new Date();
|
||||
const timeStr = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`;
|
||||
const logItem = {
|
||||
message: `[${timeStr}] ${message}`,
|
||||
type: type,
|
||||
time: timeStr
|
||||
} as UTSJSONObject;
|
||||
logs.value.unshift(logItem);
|
||||
// 限制日志数量
|
||||
if (logs.value.length > 50) {
|
||||
logs.value = logs.value.slice(0, 50);
|
||||
}
|
||||
}
|
||||
|
||||
// 创建Worker
|
||||
function create() {
|
||||
createWorkers();
|
||||
workerStatus.value = 'created';
|
||||
addLog('Worker创建成功', 'success');
|
||||
created_boolean.value = true;
|
||||
// #ifndef APP-IOS
|
||||
// 添加消息监听
|
||||
onWorkerMessage({
|
||||
success: (res : any) => {
|
||||
const result = (JSON.parse(JSON.stringify(res)) as UTSJSONObject).getAny('result') as UTSJSONObject;
|
||||
const resultData = result.getString('data');
|
||||
taskResult.value = resultData as string;
|
||||
inputValue.value = taskResult.value
|
||||
addLog(`收到WorkerTask返回: ${resultData}`, 'receive');
|
||||
}
|
||||
});
|
||||
|
||||
// 添加错误监听
|
||||
onWorkerError({
|
||||
success: (error : any) => {
|
||||
const errorMsg = (error as UTSJSONObject).getString('message');
|
||||
addLog(`Worker错误: ${errorMsg}`, 'error');
|
||||
console.log("Worker错误:", error);
|
||||
}
|
||||
} as UTSWorkerErrorOptions);
|
||||
// #endif
|
||||
}
|
||||
|
||||
// 向workerTask发送消息
|
||||
function sendMessage() {
|
||||
// 检查输入值
|
||||
if (inputValue.value == '') {
|
||||
addLog('请输入有效的数字', 'warning');
|
||||
return;
|
||||
}
|
||||
// #ifdef APP-IOS
|
||||
// 添加消息监听
|
||||
onWorkerMessage({
|
||||
success: (res : any) => {
|
||||
// 临时注释后续需要排查 原生Object转UTSJSONObject无效的问题
|
||||
// const result = (res as UTSJSONObject).getAny('result') as UTSJSONObject;
|
||||
// const resultData = result.getString('data');
|
||||
|
||||
const result = res["result"];
|
||||
const resultData = result["data"];
|
||||
taskResult.value = resultData as string;
|
||||
inputValue.value = taskResult.value
|
||||
addLog(`收到WorkerTask返回: ${resultData}`, 'receive');
|
||||
}
|
||||
});
|
||||
|
||||
// 添加错误监听
|
||||
onWorkerError({
|
||||
success: (error : any) => {
|
||||
const errorMsg = (error as UTSJSONObject).getString('message');
|
||||
addLog(`Worker错误: ${errorMsg}`, 'error');
|
||||
console.log("Worker错误:", error);
|
||||
}
|
||||
} as UTSWorkerErrorOptions);
|
||||
// #endif
|
||||
|
||||
const options = {
|
||||
data: inputValue.value,
|
||||
needReply: true
|
||||
} as UTSWorkerSendWorkerMessageOptions;
|
||||
|
||||
sendWorkerMessage(options);
|
||||
addLog(`发送值到WorkerTask: ${inputValue.value}`, 'send');
|
||||
}
|
||||
|
||||
// 销毁Worker
|
||||
function destory() {
|
||||
destroyWorker();
|
||||
workerStatus.value = 'destroyed';
|
||||
isListening.value = false;
|
||||
addLog('Worker已销毁', 'warning');
|
||||
created_boolean.value = false;
|
||||
}
|
||||
|
||||
// 清空日志
|
||||
function clearLogs() {
|
||||
logs.value = [];
|
||||
}
|
||||
|
||||
function test_resetInputValue() {
|
||||
inputValue.value = '1'
|
||||
}
|
||||
|
||||
function test_taskResult():string {
|
||||
return taskResult.value
|
||||
}
|
||||
|
||||
onUnload(() => {
|
||||
destory();
|
||||
})
|
||||
|
||||
defineExpose({
|
||||
test_resetInputValue,
|
||||
create,
|
||||
sendMessage,
|
||||
test_taskResult
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.container {
|
||||
flex: 1;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.status-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 20px;
|
||||
padding: 10px;
|
||||
background-color: #ffffff;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.status-label {
|
||||
font-size: 16px;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.status-text {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
|
||||
.button-group {
|
||||
flex-direction: column;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.input-section {
|
||||
margin-bottom: 20px;
|
||||
padding: 15px;
|
||||
background-color: #ffffff;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.input-field {
|
||||
/* #ifdef MP-WEIXIN */
|
||||
height: 3em;
|
||||
/* #endif */
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
border: 1px solid #dddddd;
|
||||
border-radius: 6px;
|
||||
font-size: 16px;
|
||||
margin: 10px 0;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.btn {
|
||||
margin-bottom: 10px;
|
||||
padding: 5px 10px;
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.log-section {
|
||||
background-color: #ffffff;
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.log-container {
|
||||
height: 300px;
|
||||
border: 1px solid #dddddd;
|
||||
border-radius: 4px;
|
||||
padding: 10px;
|
||||
margin: 10px 0;
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.log-item {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.log-text {
|
||||
font-size: 12px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.log-text.info {
|
||||
color: #2196F3;
|
||||
}
|
||||
|
||||
.log-text.success {
|
||||
color: #4CAF50;
|
||||
}
|
||||
|
||||
.log-text.warning {
|
||||
color: #ff9800;
|
||||
}
|
||||
|
||||
.log-text.error {
|
||||
color: #f44336;
|
||||
}
|
||||
|
||||
.log-text.send {
|
||||
color: #9C27B0;
|
||||
}
|
||||
|
||||
.log-text.receive {
|
||||
color: #009688;
|
||||
}
|
||||
|
||||
.clear-btn {
|
||||
background-color: #ff9800;
|
||||
font-size: 12px;
|
||||
padding: 8px 12px;
|
||||
color: #ffffff;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.description-text {
|
||||
font-size: 14px;
|
||||
color: #666666;
|
||||
line-height: 1.4;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.ios-tip-section {
|
||||
margin-bottom: 15px;
|
||||
padding: 12px;
|
||||
background-color: #fff3cd;
|
||||
border: 1px solid #ffeaa7;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.ios-tip-text {
|
||||
font-size: 14px;
|
||||
color: #856404;
|
||||
line-height: 1.4;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,36 @@
|
||||
const PAGE_PATH = '/pages/API/create-worker/worker-sendable-transfer'
|
||||
const platformInfo = process.env.uniTestPlatformInfo.toLocaleLowerCase()
|
||||
|
||||
const isWeb = platformInfo.startsWith('web')
|
||||
const isHarmony = platformInfo.startsWith('harmony')
|
||||
|
||||
describe('Api-uts-createWorker', () => {
|
||||
if (!isHarmony && !isWeb) {
|
||||
it('skip worker-sendable-transfer test', async () => {
|
||||
expect(1).toBe(1)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
let page;
|
||||
beforeAll(async () => {
|
||||
page = await program.reLaunch(PAGE_PATH)
|
||||
await page.waitFor(500);
|
||||
});
|
||||
|
||||
it('workerTask ', async () => {
|
||||
await page.callMethod('create');
|
||||
await page.waitFor(500);
|
||||
await page.callMethod('sendMessage');
|
||||
await page.waitFor(500);
|
||||
const myBufLength = await page.data('data.myBufLength')
|
||||
const sendableNumber = await page.data('data.sendableNumber')
|
||||
if (isHarmony) {
|
||||
expect(myBufLength).toBe(8);
|
||||
expect(sendableNumber).toBe(666);
|
||||
}
|
||||
if (isWeb) {
|
||||
expect(myBufLength).toBe(0);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,280 @@
|
||||
<template>
|
||||
<scroll-view class="container">
|
||||
<view class="status-section">
|
||||
<text class="status-label">Worker状态: </text>
|
||||
<text class="status-text">{{statusText}}</text>
|
||||
</view>
|
||||
|
||||
<view class="button-group">
|
||||
<text class="description-text">操作步骤:1.创建Worker 2.发送数据测试(消息监听已在创建Worker时添加)</text>
|
||||
<button class="btn" type="primary" :disabled="created_boolean" @click="create">UTS插件中创建Worker</button>
|
||||
<button class="btn" @click="destory" :disabled="workerStatus != 'created'">UTS插件中销毁Worker</button>
|
||||
</view>
|
||||
|
||||
<view class="input-section">
|
||||
<button class="btn" type="primary" @click="sendMessage"
|
||||
:disabled="workerStatus != 'created'">通过UTS插件发送到WorkerTask</button>
|
||||
</view>
|
||||
|
||||
<view class="log-section">
|
||||
<text class="section-title">通信日志:</text>
|
||||
<scroll-view class="log-container">
|
||||
<view v-for="(log, index) in logs" :key="index" class="log-item">
|
||||
<text :class="['log-text', log.type]">{{log.message}}</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<button @click="clearLogs" class="btn clear-btn">清空日志</button>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
|
||||
import { UTSWorkerAddListenerOptions, UTSWorkerReceiveEventCallback, UTSWorkerSendWorkerMessageOptions, UTSSendableWorkerImpl } from "@/uni_modules/uts-worker-sendable-transfer";
|
||||
|
||||
const sendableWorker = new UTSSendableWorkerImpl()
|
||||
|
||||
type DataType = {
|
||||
myBufLength: number,
|
||||
sendableNumber: number,
|
||||
}
|
||||
|
||||
const created_boolean = ref(false)
|
||||
const workerStatus = ref('none') // none, created, destroyed
|
||||
const isListening = ref(false)
|
||||
const logs = ref([] as Array<UTSJSONObject>)
|
||||
const myBuf = ref(new ArrayBuffer(8))
|
||||
const data = reactive({
|
||||
myBufLength: -1,
|
||||
sendableNumber: 0,
|
||||
} as DataType)
|
||||
|
||||
onUnload(() => {
|
||||
destory();
|
||||
})
|
||||
|
||||
const statusText = computed(() : string => {
|
||||
switch (workerStatus.value) {
|
||||
case 'none': return '未创建';
|
||||
case 'created': return '已创建';
|
||||
case 'destroyed': return '已销毁';
|
||||
default: return '未知';
|
||||
}
|
||||
})
|
||||
|
||||
// 添加日志方法
|
||||
function addLog(message : string, type : string = 'info') {
|
||||
const now = new Date();
|
||||
const timeStr = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`;
|
||||
const logItem = {
|
||||
message: `[${timeStr}] ${message}`,
|
||||
type: type,
|
||||
time: timeStr
|
||||
} as UTSJSONObject;
|
||||
logs.value.unshift(logItem);
|
||||
// 限制日志数量
|
||||
if (logs.value.length > 50) {
|
||||
logs.value = logs.value.slice(0, 50);
|
||||
}
|
||||
}
|
||||
|
||||
// 创建Worker
|
||||
function create() {
|
||||
sendableWorker.create()
|
||||
workerStatus.value = 'created';
|
||||
addLog('Worker创建成功', 'success');
|
||||
created_boolean.value = true;
|
||||
// 添加消息监听
|
||||
sendableWorker.onMessage({
|
||||
success: (res) => {
|
||||
const result = res.result;
|
||||
// #ifdef APP-HARMONY
|
||||
// 这里经过 worker 修改后,result.a 应该是 666
|
||||
data.sendableNumber = result.a
|
||||
// #endif
|
||||
addLog(`收到WorkerTask返回: ${JSON.stringify(result)}`, 'receive');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 向workerTask发送消息
|
||||
function sendMessage() {
|
||||
data.myBufLength = myBuf.value.byteLength
|
||||
addLog(`buf.byteLength in main BEFORE transfer to worker: ${data.myBufLength}`, 'send');
|
||||
sendableWorker.sendMessage({
|
||||
message: '这里是主线程发送的 message',
|
||||
harmonySendable: true,
|
||||
transfer: [myBuf.value]
|
||||
})
|
||||
// NOTE: HarmonyOS 长度不变,web 长度变为 0
|
||||
data.myBufLength = myBuf.value.byteLength
|
||||
addLog(`buf.byteLength in main AFTER transfer to worker: ${data.myBufLength}`, 'send');
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
data,
|
||||
create,
|
||||
sendMessage
|
||||
})
|
||||
|
||||
// 销毁Worker
|
||||
function destory() {
|
||||
sendableWorker.destroy()
|
||||
workerStatus.value = 'destroyed';
|
||||
isListening.value = false;
|
||||
addLog('Worker已销毁', 'warning');
|
||||
created_boolean.value = false;
|
||||
}
|
||||
|
||||
// 清空日志
|
||||
function clearLogs() {
|
||||
logs.value = [];
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.container {
|
||||
flex: 1;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.status-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 20px;
|
||||
padding: 10px;
|
||||
background-color: #ffffff;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.status-label {
|
||||
font-size: 16px;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.status-text {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
|
||||
.button-group {
|
||||
flex-direction: column;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.input-section {
|
||||
margin-bottom: 20px;
|
||||
padding: 15px;
|
||||
background-color: #ffffff;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.input-field {
|
||||
/* #ifdef MP-WEIXIN */
|
||||
height: 3em;
|
||||
/* #endif */
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
border: 1px solid #dddddd;
|
||||
border-radius: 6px;
|
||||
font-size: 16px;
|
||||
margin: 10px 0;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.btn {
|
||||
margin-bottom: 10px;
|
||||
padding: 5px 10px;
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.log-section {
|
||||
background-color: #ffffff;
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.log-container {
|
||||
height: 300px;
|
||||
border: 1px solid #dddddd;
|
||||
border-radius: 4px;
|
||||
padding: 10px;
|
||||
margin: 10px 0;
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.log-item {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.log-text {
|
||||
font-size: 12px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.log-text.info {
|
||||
color: #2196F3;
|
||||
}
|
||||
|
||||
.log-text.success {
|
||||
color: #4CAF50;
|
||||
}
|
||||
|
||||
.log-text.warning {
|
||||
color: #ff9800;
|
||||
}
|
||||
|
||||
.log-text.error {
|
||||
color: #f44336;
|
||||
}
|
||||
|
||||
.log-text.send {
|
||||
color: #9C27B0;
|
||||
}
|
||||
|
||||
.log-text.receive {
|
||||
color: #009688;
|
||||
}
|
||||
|
||||
.clear-btn {
|
||||
background-color: #ff9800;
|
||||
font-size: 12px;
|
||||
padding: 8px 12px;
|
||||
color: #ffffff;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.description-text {
|
||||
font-size: 14px;
|
||||
color: #666666;
|
||||
line-height: 1.4;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.ios-tip-section {
|
||||
margin-bottom: 15px;
|
||||
padding: 12px;
|
||||
background-color: #fff3cd;
|
||||
border: 1px solid #ffeaa7;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.ios-tip-text {
|
||||
font-size: 14px;
|
||||
color: #856404;
|
||||
line-height: 1.4;
|
||||
}
|
||||
</style>
|
||||
在新工单中引用
屏蔽一个用户