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

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

查看文件

@@ -0,0 +1,272 @@
const PAGE_PATH = "/pages/API/location-change/location-change";
const platformInfo = process.env.uniTestPlatformInfo.toLocaleLowerCase()
const isAndroid = platformInfo.startsWith('android')
const isIos = platformInfo.startsWith('ios')
const isHarmony = platformInfo.startsWith('harmony')
const isHarmonySimulator = isHarmony && platformInfo.includes('模拟器')
const isWeb = platformInfo.startsWith('web')
const isMP = platformInfo.startsWith('mp')
describe("location-change", () => {
if (isMP || isWeb || isHarmonySimulator) {
// 微信、web harmony 上会有权限弹框,暂时屏蔽测试
it('not support', async () => {
expect(1).toBe(1)
})
return
}
let page;
beforeAll(async () => {
page = await program.reLaunch(PAGE_PATH)
await page.waitFor(600)
});
// 测试辅助函数
async function setPageData(newData) {
return await page.setData({ data: newData });
}
it("system+type=wgs84+success", async () => {
if (isAndroid) {
await program.adbCommand(
'pm grant io.dcloud.uniappx android.permission.ACCESS_FINE_LOCATION');
await program.adbCommand(
'pm grant io.dcloud.uniappx android.permission.ACCESS_COARSE_LOCATION');
await program.adbCommand(
'pm grant io.dcloud.uniappx android.permission.ACCESS_BACKGROUND_LOCATION');
}
await setPageData({
currentSelectedProvider: 0,
currentSelectedType: 0,
startSuccess: false,
logAble: false
})
const stopLocationUpdateBtn = await page.$('#stopLocationUpdate')
await stopLocationUpdateBtn.tap()
const startLocationUpdateBtn = await page.$('#startLocationUpdate')
await startLocationUpdateBtn.tap()
await page.waitFor(500)
let data = await page.data('data')
let startSuccess = data['startSuccess']
expect(startSuccess).toEqual(true);
if (!isHarmony) {
// NOTE 鸿蒙上需要在设置中允许,屏蔽该测试
await setPageData({
startSuccess: false
})
const startLocationUpdateBackgroundBtn = await page.$('#startLocationUpdateBackground')
await startLocationUpdateBackgroundBtn.tap()
data = await page.data('data')
startSuccess = data['startSuccess']
expect(startSuccess).toEqual(true);
}
});
it(`system+type=gcj02+${isHarmony ? 'success' : 'fail'}`, async () => {
await setPageData({
currentSelectedProvider: 0,
currentSelectedType: 1,
startSuccess: false,
errCode: 0,
logAble: false
})
const stopLocationUpdateBtn = await page.$('#stopLocationUpdate')
await stopLocationUpdateBtn.tap()
const startLocationUpdateBtn = await page.$('#startLocationUpdate')
await startLocationUpdateBtn.tap()
await page.waitFor(1000)
let data = await page.data('data')
let startSuccess = data['startSuccess']
if (!isHarmony) {
let errCode = data['errCode']
expect(startSuccess).toEqual(false);
expect(errCode).toEqual(1505601);
} else {
expect(startSuccess).toEqual(true);
}
if (!isHarmony) {
// NOTE 鸿蒙上需要在设置中允许,屏蔽该测试
await setPageData({
currentSelectedProvider: 0,
currentSelectedType: 1,
startSuccess: false,
errCode: 0
})
const startLocationUpdateBackgroundBtn = await page.$('#startLocationUpdateBackground')
await startLocationUpdateBackgroundBtn.tap()
await page.waitFor(1000)
data = await page.data('data')
startSuccess = data['startSuccess']
errCode = data['errCode']
expect(startSuccess).toEqual(false);
expect(errCode).toEqual(1505601);
}
});
if (!isHarmony) {
it("tencent+type=wgs84+fail", async () => {
await setPageData({
logAble: false,
currentSelectedProvider: 1,
currentSelectedType: 0,
startSuccess: false,
errCode: 0
})
await setPageData({
currentSelectedType: 0
})
const stopLocationUpdateBtn = await page.$('#stopLocationUpdate')
await stopLocationUpdateBtn.tap()
const startLocationUpdateBtn = await page.$('#startLocationUpdate')
await startLocationUpdateBtn.tap()
let data = await page.data('data')
let startSuccess = data['startSuccess']
let errCode = data['errCode']
expect(startSuccess).toEqual(false);
expect(errCode).toEqual(1505607);
await setPageData({
currentSelectedProvider: 1,
currentSelectedType: 0,
startSuccess: false,
errCode: 0
})
const startLocationUpdateBackgroundBtn = await page.$('#startLocationUpdateBackground')
await startLocationUpdateBackgroundBtn.tap()
data = await page.data('data')
startSuccess = data['startSuccess']
errCode = data['errCode']
expect(startSuccess).toEqual(false);
expect(errCode).toEqual(1505607);
});
it("tencent+type=gcj02+success", async () => {
await setPageData({
currentSelectedProvider: 1,
currentSelectedType: 1,
startSuccess: false,
errCode: 0,
logAble: false
})
const stopLocationUpdateBtn = await page.$('#stopLocationUpdate')
await stopLocationUpdateBtn.tap()
const startLocationUpdateBtn = await page.$('#startLocationUpdate')
await startLocationUpdateBtn.tap()
let data = await page.data('data')
let startSuccess = data['startSuccess']
expect(startSuccess).toEqual(true);
await setPageData({
currentSelectedProvider: 1,
currentSelectedType: 1,
startSuccess: false,
errCode: 0
})
const startLocationUpdateBackgroundBtn = await page.$('#startLocationUpdateBackground')
await startLocationUpdateBackgroundBtn.tap()
data = await page.data('data')
startSuccess = data['startSuccess']
expect(startSuccess).toEqual(true);
});
it("tencent+system+fail", async () => {
await setPageData({
currentSelectedProvider: 1,
currentSelectedType: 1,
startSuccess: false,
errCode: 0,
logAble: false
})
const stopLocationUpdateBtn = await page.$('#stopLocationUpdate')
await stopLocationUpdateBtn.tap()
const startLocationUpdateBtn = await page.$('#startLocationUpdate')
await startLocationUpdateBtn.tap()
let data = await page.data('data')
let startSuccess = data['startSuccess']
expect(startSuccess).toEqual(true);
await setPageData({
currentSelectedProvider: 0,
currentSelectedType: 0,
startSuccess: false,
errCode: 0
})
await startLocationUpdateBtn.tap()
data = await page.data('data')
startSuccess = data['startSuccess']
let errCode = data['errCode']
expect(startSuccess).toEqual(false);
expect(errCode).toEqual(1505608);
await stopLocationUpdateBtn.tap()
await setPageData({
currentSelectedProvider: 0,
currentSelectedType: 0,
startSuccess: false,
errCode: 0
})
await startLocationUpdateBtn.tap()
data = await page.data('data')
startSuccess = data['startSuccess']
expect(startSuccess).toEqual(true);
await setPageData({
currentSelectedProvider: 1,
currentSelectedType: 1,
startSuccess: false,
errCode: 0
})
await startLocationUpdateBtn.tap()
data = await page.data('data')
startSuccess = data['startSuccess']
errCode = data['errCode']
expect(startSuccess).toEqual(false);
expect(errCode).toEqual(1505608);
});
}
it("stopLocationUpdate", async () => {
await setPageData({
stopSuccess: false,
logAble: true
})
await page.callMethod('stopLocationUpdate')
let data = await page.data('data')
let stopSuccess = data['stopSuccess']
expect(stopSuccess).toEqual(true);
})
});

查看文件

@@ -0,0 +1,304 @@
<template>
<!-- #ifdef APP -->
<text>显示简易操作日志(可滚动查看)</text><button size="mini" @click="data.log=''">清空日志</button>
<scroll-view style="max-height: 300px;">
<text style="margin: 2px; padding: 2px; border: 1px solid #000000;">{{ data.log }}</text>
</scroll-view>
<view class="uni-list">
<text style="margin-bottom: 4px"> 请选择定位服务提供商:</text>
<radio-group class="uni-row" @change="providerChange" style="flex-wrap: wrap">
<radio class="uni-list-cell" style="margin-right: 15px" v-for="(item, index) in data.providerList" :key="item.id"
:value="item.id" :checked="index === data.currentSelectedProvider">
{{ item.name }}
</radio>
</radio-group>
</view>
<view class="uni-list">
<text style="margin-bottom: 4px"> 请选择坐标系:</text>
<radio-group class="uni-row" @change="typeChange" style="flex-wrap: wrap">
<radio class="uni-list-cell" style="margin-right: 15px" v-for="(item, index) in types" :key="item.value"
:value="item.value" :checked="index === data.currentSelectedType">
{{ item.name }}
</radio>
</radio-group>
</view>
<scroll-view style="flex:1">
<!-- #endif -->
<button class="btnstyle" type="primary" @tap="startLocationUpdate" id="startLocationUpdate">点击连续定位</button>
<button class="btnstyle" type="primary" @tap="startLocationUpdateBackground"
id="startLocationUpdateBackground">后台点击连续定位</button>
<button class="btnstyle" type="primary" @tap="stopLocationUpdate" id="stopLocationUpdate">点击关闭定位</button>
<button class="btnstyle" type="primary" @tap="onLocationChange" id="onLocationChange">onLocationChange</button>
<button class="btnstyle" type="primary" @tap="offLocationChange" id="offLocationChange">offLocationChange</button>
<button class="btnstyle" type="primary" @tap="onLocationChangeError"
id="onLocationChangeError">onLocationChangeError</button>
<button class="btnstyle" type="primary" @tap="offLocationChangeError"
id="offLocationChangeError">offLocationChangeError</button>
<!-- #ifdef APP -->
</scroll-view>
<!-- #endif -->
</template>
<script setup lang="uts">
type LocationType = 'wgs84' | 'gcj02'
export type ItemType = { value : LocationType, name : LocationType }
export type LocationItem = { id : string, name : string, provider ?: UniProvider }
export type DataType = {
log: string
logAble: boolean
providerList: LocationItem[]
currentSelectedProvider: number
currentSelectedType: number
startSuccess: boolean
stopSuccess: boolean
errCode: number
}
const data = reactive({
log: "",
logAble: true,
providerList: [],
currentSelectedProvider: 0,
currentSelectedType: 0,
startSuccess: false,
stopSuccess: false,
errCode: 0
} as DataType)
const types = ref<ItemType[]>([
{
value: 'wgs84',
name: 'wgs84'
},
{
value: 'gcj02',
name: 'gcj02'
}
])
const getProvider = () => {
// #ifdef APP
let provider = uni.getProviderSync({
service: "location",
} as GetProviderSyncOptions)
console.log(provider)
provider.providerObjects.forEach((value : UniProvider) => {
var currentProvider = value
data.providerList.push({
name: currentProvider.description,
id: currentProvider.id,
provider: currentProvider
} as LocationItem);
})
data.providerList.forEach((value, index) => {
if (value.id == "system") {
data.currentSelectedProvider = index
}
})
// #endif
}
const providerChange = (e : UniRadioGroupChangeEvent) => {
for (let i = 0; i < data.providerList.length; i++) {
if (data.providerList[i].id === e.detail.value) {
data.currentSelectedProvider = i;
break;
}
}
if (e.detail.value == "system") {
data.currentSelectedType = 0
} else if (e.detail.value == "tencent") {
data.currentSelectedType = 1
}
}
const typeChange = (e : UniRadioGroupChangeEvent) => {
for (let i = 0; i < types.value.length; i++) {
if (types.value[i].value === e.detail.value) {
data.currentSelectedType = i;
break;
}
}
}
const offLocationChangeError = () => {
if (data.logAble) {
data.log += "关闭offLocationChangeError监听" + '\n\n'
}
console.log("关闭onLocationChangeError监听")
uni.offLocationChangeError(null)
}
const onLocationChangeError = () => {
uni.offLocationChangeError(null)
if (data.logAble) {
data.log += "开启onLocationChangeError监听" + '\n\n'
}
console.log("开启onLocationChangeError监听")
uni.onLocationChangeError((e) => {
console.log("onLocationChangeError回调: ", e)
if (data.logAble) {
data.log += JSON.stringify(e) + '\n\n'
}
})
}
const onLocationChange = () => {
uni.offLocationChange(null)
console.log("开启onLocationChange监听")
if (data.logAble) {
data.log += "开启onLocationChange监听" + '\n\n'
}
uni.onLocationChange((e) => {
console.log("onLocationChange持续监听回调: ", e)
if (data.logAble) {
data.log += "provider= " + data.providerList[data.currentSelectedProvider].id + '\n' + JSON.stringify(e) + '\n\n'
}
})
}
const offLocationChange = () => {
if (data.logAble) {
data.log += "关闭offLocationChange监听" + '\n\n'
}
console.log("关闭offLocationChange监听")
uni.offLocationChange(null)
}
const startLocationUpdate = () => {
// #ifdef APP
if (data.providerList.length == 0) {
uni.showToast({
title: '未获取到provider,请确定基座中包含location功能',
icon: "error"
})
console.log("未获取到provider,请确定基座中包含location功能")
return
}
// #endif
const currentProvider = data.providerList[data.currentSelectedProvider]
// #ifdef WEB
if (currentProvider == null) {
data.log += `currentSelectedProvider = ${data.currentSelectedProvider} is undefined\n\n`
return
}
// #endif
uni.startLocationUpdate({
provider: currentProvider.id,
type: types.value[data.currentSelectedType].value,
success: () => {
if (data.logAble) {
data.log += "开启startLocationUpdate成功, provider= " + currentProvider.id + '\n\n'
}
console.log("持续定位启动成功")
data.startSuccess = true
},
fail: (err) => {
if (data.logAble) {
data.log += "启动startLocationUpdate失败:erroCode=" + err.errCode + '\n\n'
}
console.log("持续定位启动失败")
data.startSuccess = false
data.errCode = err.errCode
}
})
}
const startLocationUpdateBackground = () => {
// #ifdef APP
if (data.providerList.length == 0) {
uni.showToast({
title: '未获取到provider,请确定基座中包含location功能',
icon: "error"
})
console.log("未获取到provider,请确定基座中包含location功能")
return
}
// #endif
const currentProvider = data.providerList[data.currentSelectedProvider]
// #ifdef WEB
if (currentProvider == null) {
data.log += `currentSelectedProvider = ${data.currentSelectedProvider} is undefined\n\n`
return
}
// #endif
uni.startLocationUpdateBackground({
provider: currentProvider.id,
type: types.value[data.currentSelectedType].value,
success: () => {
if (data.logAble) {
data.log += "开启startLocationUpdateBackground成功, provider= " + currentProvider.id + '\n\n'
}
console.log("后台持续定位api启动成功")
data.startSuccess = true
}, fail: (err) => {
if (data.logAble) {
data.log += "启动startLocationUpdateBackground失败:erroCode=" + err.errCode + '\n\n'
}
console.log("后台持续定位启动失败")
data.startSuccess = false
data.errCode = err.errCode
}
})
}
const stopLocationUpdate = () => {
uni.stopLocationUpdate({
success: () => {
if (data.logAble) {
data.log += "成功关闭stopLocationUpdate定位" + '\n\n'
}
console.log("成功关闭stopLocationUpdate定位")
data.stopSuccess = true
}
})
}
onLoad(() => {
// #ifdef APP
getProvider()
// #endif
})
onUnload(() => {
uni.stopLocationUpdate({})
uni.offLocationChange(null)
uni.offLocationChangeError(null)
})
defineExpose({
data,
stopLocationUpdate
})
</script>
<style>
.uni-list {
border-bottom: 0px;
background-color: transparent;
margin-left: 10px;
margin-right: 10px;
margin-top: 4px;
margin-bottom: 4px;
}
.uni-list-cell {
position: relative;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.btnstyle {
margin: 4px;
}
</style>