版本更新

This commit is contained in:
phm1551 2026-06-27 18:30:14 +08:00
parent 02f2d8125c
commit 769ce650f2
22 changed files with 318 additions and 89 deletions

2
.gitignore vendored
View File

@ -18,5 +18,5 @@ bin-release/
# information for Eclipse / Flash Builder.
/.idea
/upgrade
niucloud/public/.htaccess
admin/.env.development

8
.htaccess Normal file
View File

@ -0,0 +1,8 @@
<ifModule mod_rewrite.c>
Options +FollowSymlinks -Multiviews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?/$1 [QSA,PT,L]
RewriteEngine on RewriteCond % !^$
</ifModule>

36
README.en.md Normal file
View File

@ -0,0 +1,36 @@
# niucloud-admin
#### Description
{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**}
#### Software Architecture
Software architecture description
#### Installation
1. xxxx
2. xxxx
3. xxxx
#### Instructions
1. xxxx
2. xxxx
3. xxxx
#### Contribution
1. Fork the repository
2. Create Feat_xxx branch
3. Commit your code
4. Create Pull Request
#### Gitee Feature
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
4. The most valuable open source project [GVP](https://gitee.com/gvp)
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

View File

@ -1,11 +1,11 @@
![输入图片说明](https://media.niucloud.com/1712133019020249f332e83457a01a6799472e0495_aliyun.png)
![输入图片说明](https://www.niucloud.com/img/readme/%E9%A1%B6%E9%83%A8%E5%B9%BF%E5%91%8A1.jpg)
### niucloud-admin是什么
### niucloud-admin是什么
niucloud-admin是一款快速开发通用管理后台框架前端采用最新的技术栈Vite+TypeScript+Vue3+ElementPlus最流行技术架构后台结合PHP8、Java SDK、Python等主流后端语言搭建内置集成用户权限、代码生成器、表单设计、云存储、短信发送、素材中心、微信及公众号、Api模块一系列开箱即用功能是一款快速可以开发企业级应用的软件系统。
### niucloud-admin采用的技术亮点
### niucloud-admin采用的技术亮点
- 后台php采用thinkphp8+php8+mysql,支持composer快速安装扩展支持redis缓存以及消息队列支持多语言设计开发同时开发采用严格的restful的api设计开发。
- 后台php采用thinkphp8+php8+mysql,支持composer快速安装扩展支持redis缓存以及消息队列支持多语言设计开发同时开发采用严格的restful的api设计开发。
- 后台前后端分离采用element-plus、vue3.0、typescript、vite、pina等前端技术,同时使用i18n支持国际化多语言开发。
@ -32,25 +32,20 @@ niucloud-admin是一款快速开发通用管理后台框架前端采用最新
### 操作指南
[官网地址](https://www.niucloud.com)
| [服务市场](https://www.niucloud.com)
| [使用手册](https://www.niucloud.com/doc)
| [二开手册](https://www.niucloud.com/doc)
| [开发视频](https://www.niucloud.com/doc)
| [API接口手册](https://api.niucloud.com/apidoc.html?target_id=001)
| [论坛地址](https://niucloud.com/bbs)
| [使用手册](https://www.kancloud.cn/niucloud/niucloud-admin-develop/3153336)
| [二开手册](https://www.kancloud.cn/niucloud/niucloud-admin-develop/3153336)
| [API接口手册](https://www.niucloud.com/apidoc.html)
| [论坛地址](https://www.niucloud.com/bbs)
### 演示地址
- 管理后台演示网址:[<a href='https://v6.site.niucloud.com/admin' target="_blank"> 查看 </a>]
<a href='https://v6.site.niucloud.com/admin' target="_blank">https://v6.site.niucloud.com/admin 账号admin 密码123456
- web端演示网址[<a href='https://v6.site.niucloud.com' target="_blank"> 查看 </a>]
<a href='https://v6.site.niucloud.com' target="_blank">https://v6.site.niucloud.com 账号admin 密码123456
- 管理后台演示网址:[<a href='http://v6.site.niucloud.com' target="_blank"> 查看 </a>]
<a href='http://v6.site.niucloud.com' target="_blank">http://v6.site.niucloud.com 账号admin 密码123456
- H5前端演示网址[<a href='https://v6.site.niucloud.com/wap/' target="_blank"> 查看 </a>]
<a href='https://v6.site.niucloud.com/wap/' target="_blank">https://v6.site.niucloud.com/wap/ 账号admin 密码123456
### 开源使用须知
### 开源使用须知
1.允许用于个人学习、毕业设计、教学案例、公益事业、商业使用;
1.允许用于个人学习、毕业设计、教学案例、公益事业、商业使用;
2.本框架应用源代码所有权和著作权归niucloud官方所有基于niucloud-admin框架开发的应用所有权和著作权归应用开发商所有。但必须明确声明是基于niucloud-admin框架开发请自觉遵守否则产生的一切任何后果责任由侵权者自负;
@ -62,12 +57,14 @@ niucloud-admin是一款快速开发通用管理后台框架前端采用最新
6.一切事物有个人喜好的标准,本开源代码意在分享,不喜勿喷。
### 版权信息
版权所有Copyright © 2015-2030 niucloud-admin 版权所有
All rights reserved。
杭州数字云动科技有限公司
杭州牛之云科技有限公司
提供技术支持
提供技术支持

View File

@ -0,0 +1,34 @@
// vite.config.ts
import { fileURLToPath, URL } from "node:url";
import { defineConfig } from "file:///G:/www/niucloud-admin-niushop-v6/admin/node_modules/vite/dist/node/index.js";
import vue from "file:///G:/www/niucloud-admin-niushop-v6/admin/node_modules/@vitejs/plugin-vue/dist/index.mjs";
import AutoImport from "file:///G:/www/niucloud-admin-niushop-v6/admin/node_modules/unplugin-auto-import/dist/vite.js";
import Components from "file:///G:/www/niucloud-admin-niushop-v6/admin/node_modules/unplugin-vue-components/dist/vite.mjs";
import { ElementPlusResolver } from "file:///G:/www/niucloud-admin-niushop-v6/admin/node_modules/unplugin-vue-components/dist/resolvers.mjs";
var __vite_injected_original_import_meta_url = "file:///G:/www/niucloud-admin-niushop-v6/admin/vite.config.ts";
var vite_config_default = defineConfig({
base: "",
server: {
host: "0.0.0.0"
},
plugins: [
vue(),
AutoImport({
resolvers: [ElementPlusResolver()]
}),
Components({
resolvers: [ElementPlusResolver()]
})
],
resolve: {
alias: {
"@": fileURLToPath(new URL("./src", __vite_injected_original_import_meta_url)),
"assets": fileURLToPath(new URL("./src/assets", __vite_injected_original_import_meta_url)),
"vue-i18n": "vue-i18n/dist/vue-i18n.cjs.js"
}
}
});
export {
vite_config_default as default
};
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJHOlxcXFx3d3dcXFxcbml1Y2xvdWQtYWRtaW4tbml1c2hvcC12NlxcXFxhZG1pblwiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiRzpcXFxcd3d3XFxcXG5pdWNsb3VkLWFkbWluLW5pdXNob3AtdjZcXFxcYWRtaW5cXFxcdml0ZS5jb25maWcudHNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfaW1wb3J0X21ldGFfdXJsID0gXCJmaWxlOi8vL0c6L3d3dy9uaXVjbG91ZC1hZG1pbi1uaXVzaG9wLXY2L2FkbWluL3ZpdGUuY29uZmlnLnRzXCI7aW1wb3J0IHsgZmlsZVVSTFRvUGF0aCwgVVJMIH0gZnJvbSBcIm5vZGU6dXJsXCJcclxuaW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSAndml0ZSdcclxuaW1wb3J0IHZ1ZSBmcm9tICdAdml0ZWpzL3BsdWdpbi12dWUnXHJcbmltcG9ydCBBdXRvSW1wb3J0IGZyb20gJ3VucGx1Z2luLWF1dG8taW1wb3J0L3ZpdGUnXHJcbmltcG9ydCBDb21wb25lbnRzIGZyb20gJ3VucGx1Z2luLXZ1ZS1jb21wb25lbnRzL3ZpdGUnXHJcbmltcG9ydCB7IEVsZW1lbnRQbHVzUmVzb2x2ZXIgfSBmcm9tICd1bnBsdWdpbi12dWUtY29tcG9uZW50cy9yZXNvbHZlcnMnXHJcblxyXG4vLyBodHRwczovL3ZpdGVqcy5kZXYvY29uZmlnL1xyXG5leHBvcnQgZGVmYXVsdCBkZWZpbmVDb25maWcoe1xyXG4gICAgYmFzZTogJycsXHJcbiAgICBzZXJ2ZXI6IHtcclxuICAgICAgICBob3N0OiAnMC4wLjAuMCdcclxuICAgIH0sXHJcbiAgICBwbHVnaW5zOiBbXHJcbiAgICAgICAgdnVlKCksXHJcbiAgICAgICAgQXV0b0ltcG9ydCh7XHJcbiAgICAgICAgICAgIHJlc29sdmVyczogW0VsZW1lbnRQbHVzUmVzb2x2ZXIoKV1cclxuICAgICAgICB9KSxcclxuICAgICAgICBDb21wb25lbnRzKHtcclxuICAgICAgICAgICAgcmVzb2x2ZXJzOiBbRWxlbWVudFBsdXNSZXNvbHZlcigpXVxyXG4gICAgICAgIH0pXHJcbiAgICBdLFxyXG4gICAgcmVzb2x2ZToge1xyXG4gICAgICAgIGFsaWFzOiB7XHJcbiAgICAgICAgICAgICdAJzogZmlsZVVSTFRvUGF0aChuZXcgVVJMKCcuL3NyYycsIGltcG9ydC5tZXRhLnVybCkpLFxyXG4gICAgICAgICAgICAnYXNzZXRzJzogZmlsZVVSTFRvUGF0aChuZXcgVVJMKCcuL3NyYy9hc3NldHMnLCBpbXBvcnQubWV0YS51cmwpKSxcclxuICAgICAgICAgICAgJ3Z1ZS1pMThuJzogJ3Z1ZS1pMThuL2Rpc3QvdnVlLWkxOG4uY2pzLmpzJ1xyXG4gICAgICAgIH1cclxuICAgIH1cclxufSlcclxuIl0sCiAgIm1hcHBpbmdzIjogIjtBQUE0UyxTQUFTLGVBQWUsV0FBVztBQUMvVSxTQUFTLG9CQUFvQjtBQUM3QixPQUFPLFNBQVM7QUFDaEIsT0FBTyxnQkFBZ0I7QUFDdkIsT0FBTyxnQkFBZ0I7QUFDdkIsU0FBUywyQkFBMkI7QUFMdUosSUFBTSwyQ0FBMkM7QUFRNU8sSUFBTyxzQkFBUSxhQUFhO0FBQUEsRUFDeEIsTUFBTTtBQUFBLEVBQ04sUUFBUTtBQUFBLElBQ0osTUFBTTtBQUFBLEVBQ1Y7QUFBQSxFQUNBLFNBQVM7QUFBQSxJQUNMLElBQUk7QUFBQSxJQUNKLFdBQVc7QUFBQSxNQUNQLFdBQVcsQ0FBQyxvQkFBb0IsQ0FBQztBQUFBLElBQ3JDLENBQUM7QUFBQSxJQUNELFdBQVc7QUFBQSxNQUNQLFdBQVcsQ0FBQyxvQkFBb0IsQ0FBQztBQUFBLElBQ3JDLENBQUM7QUFBQSxFQUNMO0FBQUEsRUFDQSxTQUFTO0FBQUEsSUFDTCxPQUFPO0FBQUEsTUFDSCxLQUFLLGNBQWMsSUFBSSxJQUFJLFNBQVMsd0NBQWUsQ0FBQztBQUFBLE1BQ3BELFVBQVUsY0FBYyxJQUFJLElBQUksZ0JBQWdCLHdDQUFlLENBQUM7QUFBQSxNQUNoRSxZQUFZO0FBQUEsSUFDaEI7QUFBQSxFQUNKO0FBQ0osQ0FBQzsiLAogICJuYW1lcyI6IFtdCn0K

0
nginx.htaccess Normal file
View File

View File

@ -1 +1 @@
APP_DEBUG = true [APP] DEFAULT_TIMEZONE = Asia/Shanghai AUTH_KEY = {auth_key} PRODUCT_KEY = {product_key} [DATABASE] TYPE = mysql HOSTNAME = {dbhost} DATABASE = {dbname} USERNAME = {dbuser} PASSWORD = {dbpwd} HOSTPORT = {dbport} PREFIX = {dbprefix} CHARSET = utf8mb4 DEBUG = false [REDIS] REDIS_HOSTNAME = 127.0.0.1 PORT = 6379 REDIS_PASSWORD = SELECT = 0 [QUEUE] state = false [LANG] default_lang = zh-cn [SYSTEM] ADMIN_TOKEN_NAME = token API_TOKEN_NAME = token ADMIN_TOKEN_EXPIRE_TIME = 604800 API_TOKEN_EXPIRE_TIME = 2592000 LANG_NAME = lang CHANNEL_NAME = channel ADMIN_DOMAIN = WAP_DOMAIN = WEB_DOMAIN = [NIUCLOUD] code = secret =
APP_DEBUG = false [APP] DEFAULT_TIMEZONE = Asia/Shanghai AUTH_KEY = {auth_key} PRODUCT_KEY = {product_key} [DATABASE] TYPE = mysql HOSTNAME = {dbhost} DATABASE = {dbname} USERNAME = {dbuser} PASSWORD = {dbpwd} HOSTPORT = {dbport} PREFIX = {dbprefix} CHARSET = utf8mb4 DEBUG = false [REDIS] REDIS_HOSTNAME = 127.0.0.1 PORT = 6379 REDIS_PASSWORD = SELECT = 0 [QUEUE] state = false [LANG] default_lang = zh-cn [SYSTEM] ADMIN_TOKEN_NAME = token API_TOKEN_NAME = token ADMIN_TOKEN_EXPIRE_TIME = 604800 API_TOKEN_EXPIRE_TIME = 2592000 LANG_NAME = lang CHANNEL_NAME = channel ADMIN_DOMAIN = WAP_DOMAIN = WEB_DOMAIN = [NIUCLOUD] code = secret =

View File

@ -1,5 +1,5 @@
<?php
return [
'version' => '1.6.2',
'code' => '202606060001'
'version' => '1.6.3',
'code' => '202606270001'
];

View File

@ -1,4 +1,7 @@
/.htaccess
upload
nginx.htaccess
.htaccess
.htaccess
admin
wap
web

View File

@ -1,8 +1,8 @@
<IfModule mod_rewrite.c>
Options +FollowSymlinks -Multiviews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?/$1 [QSA,PT,L]
RewriteEngine on RewriteCond % !^$
</IfModule>
<ifModule mod_rewrite.c>
Options +FollowSymlinks -Multiviews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?/$1 [QSA,PT,L]
RewriteEngine on RewriteCond % !^$
</ifModule>

View File

@ -5,7 +5,7 @@
<link rel="icon" type="image" href="/admin/niucloud.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title></title>
<script type="module" crossorigin src="/admin/assets/index-22b96767.js"></script>
<script type="module" crossorigin src="/admin/assets/index-60b5b21e.js"></script>
<link rel="stylesheet" href="/admin/assets/index-6e9046b8.css">
</head>
<body>

View File

@ -1,4 +1,4 @@
location /{
location / {
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php/$1 last; break;
}

View File

@ -870,9 +870,13 @@
window.postMessage({ type: 'tianmap:select', data: payload }, '*');
// alert('已选择坐标:' + selectedLongitude.toFixed(6) + ',' + selectedLatitude.toFixed(6));
}
document.addEventListener('DOMContentLoaded', function() {
setTimeout(onLoad, 100);
});
</script>
</head>
<body onLoad="onLoad()">
<body>
<div class="page">
<div class="map-wrap">
<div id="mapDiv"></div>

View File

@ -14,7 +14,7 @@
<title></title>
<!--preload-links-->
<!--app-context-->
<script type="module" crossorigin src="/wap/assets/index-a4393c74.js"></script>
<script type="module" crossorigin src="/wap/assets/index-1e2462dd.js"></script>
<link rel="stylesheet" href="/wap/assets/index-5143bf90.css">
</head>
<body>

View File

@ -16,4 +16,4 @@ VITE_REQUEST_HEADER_TOKEN_KEY='token'
VITE_REQUEST_HEADER_CHANNEL_KEY='channel'
# 应用版本
VITE_APP_VERSION='1.0.1'
VITE_APP_VERSION='1.0.1'

View File

@ -123,7 +123,6 @@
<template v-if="component.componentName == 'Text'">
<diy-text ref="diyTextRef" :component="component" :global="data.global" :index="index" :scrollBool="diyGroup.componentsScrollBool.Text" @update:componentIsShow="component.componentIsShow = $event" />
</template>
</view>
</view>
</template>

View File

@ -85,6 +85,8 @@ import useSystemStore from '@/stores/system';
import { useLocation } from '@/hooks/useLocation'
const systemStore = useSystemStore();
const { refresh: refreshLocation } = useLocation(true);
const formData: any = ref({
id: 0,
name: '',
@ -111,6 +113,7 @@ const isSelectMap = ref(2) // 值为1该地址需要有经纬度反之不
const wxPrivacyPopupRef: any = ref(null)
onLoad((data: any) => {
refreshLocation();
isSelectMap.value = data.isSelectMap || '';
const selectAddress = uni.getStorageSync('selectAddressCallback')
if (data.id) {
@ -260,8 +263,12 @@ const save = () => {
//
const chooseLocation = () => {
let latitude = systemStore.diyAddressInfo ? systemStore.diyAddressInfo.latitude : '';
let longitude = systemStore.diyAddressInfo ? systemStore.diyAddressInfo.longitude : '';
//
const latitude = systemStore.diyAddressInfo?.latitude ?? ''
const longitude = systemStore.diyAddressInfo?.longitude ?? ''
// let latitude = systemStore.diyAddressInfo ? systemStore.diyAddressInfo.latitude : '';
// let longitude = systemStore.diyAddressInfo ? systemStore.diyAddressInfo.longitude : '';
// #ifndef H5
uni.chooseLocation({
@ -276,6 +283,12 @@ const chooseLocation = () => {
if (res.latitude && res.longitude) {
let latng = res.latitude + ',' + res.longitude;
getAddress(latng);
// +
systemStore.setAddressInfo({
latitude: res.latitude,
longitude: res.longitude,
address: res.address
})
}
},
fail: (res) => {
@ -283,12 +296,15 @@ const chooseLocation = () => {
if (res.errMsg && res.errno) {
if (res.errno == 104) {
let msg = '用户未授权隐私权限,选择位置失败';
uni.showToast({ title: msg, icon: 'none' })
// uni.showToast({ title: msg, icon: 'none' })
console.log(msg)
} else if (res.errno == 112) {
let msg = '隐私协议中未声明,打开地图选择位置失败';
uni.showToast({ title: msg, icon: 'none' })
// uni.showToast({ title: msg, icon: 'none' })
console.log(msg)
} else {
uni.showToast({ title: res.errMsg, icon: 'none' })
// uni.showToast({ title: res.errMsg, icon: 'none' })
console.log(res.errMsg)
}
}
}
@ -385,7 +401,7 @@ const choosegAddress = () =>{
// idid
formData.value.city_id = findIdByNameAndParentId(areaTree.value, res.cityName, formData.value.province_id);
// idid
formData.value.district_id = findIdByNameAndParentId(areaTree.value, res.countyName, formData.value.cityId);
formData.value.district_id = findIdByNameAndParentId(areaTree.value, res.countyName, formData.value.city_id);
},
fail(err) {
loadingchoosegAddress.value = false
@ -393,7 +409,14 @@ const choosegAddress = () =>{
});
}
onMounted(()=>{
onMounted(async ()=>{
//
const cacheLocation = uni.getStorageSync('location_address')
if(cacheLocation && Object.keys(cacheLocation).length) {
//
systemStore.setAddressInfo(cacheLocation)
}
// #ifdef MP
uni.authorize({
scope: 'scope.userLocation',
@ -410,7 +433,7 @@ onMounted(()=>{
success: (settingRes) => {
if (settingRes.authSetting['scope.userLocation']) {
const locationVal = useLocation(true);
locationVal.init();
locationVal.refresh();
}
}
});

View File

@ -205,15 +205,19 @@ const savePoster = () => {
fail: (err) => {
if (err.errno == 104) {
let msg = '用户未授权隐私权限,将图像保存到相册失败';
uni.showToast({ title: msg, icon: 'none' })
// uni.showToast({ title: msg, icon: 'none' })
console.log(msg)
} else if (err.errMsg == "saveImageToPhotosAlbum:fail auth deny" ||
err.errMsg == "saveImageToPhotosAlbum:fail:auth denied") {
show.value = true;
console.log(err.errMsg)
} else if (err.errMsg == "saveImageToPhotosAlbum:fail cancel") {
let msg = '用户取消将图片保存到相册';
uni.showToast({ title: msg, icon: 'none' })
// uni.showToast({ title: msg, icon: 'none' })
console.log(msg)
} else {
uni.showToast({ title: err.errMsg, icon: 'none' })
// uni.showToast({ title: err.errMsg, icon: 'none' })
console.log(err.errMsg)
}
}
});

View File

@ -4,6 +4,10 @@ import { getAddressByLatlng } from '@/app/api/system';
import wechat from '@/utils/wechat'
import useSystemStore from '@/stores/system';
// 单例定位服务
// 使用全局 Promise 确保整个应用中只有一个定位请求在执行
let locationPromise: Promise<void> | null = null;
export function useLocation(isOpenLocation: any) {
const systemStore = useSystemStore();
@ -13,6 +17,80 @@ export function useLocation(isOpenLocation: any) {
isOpen = false;
}
const init = () => {
if (!isOpen) return false;
// 使用 locationPromise 作为唯一的锁源
if (locationPromise) {
return;
}
// 立即设置空 Promise 作为锁
locationPromise = new Promise<void>(() => {});
// 排除手动地图选择位置的情况
if (!uni.getStorageSync('manually_select_location_from_map')) {
// #ifdef H5
if (isWeixinBrowser() && systemStore.mapConfig.is_open && !uni.getStorageSync('location_address')) {
wechat.init(() => {
wechat.getLocation(res => {
locationPromise = null;
let latlng = res.latitude + ',' + res.longitude;
getAddressByLatlngFn(latlng);
});
});
} else {
locationPromise = null;
}
// #endif
// #ifndef H5
if (systemStore.mapConfig.is_open && !uni.getStorageSync('location_address')) {
uni.getLocation({
// #ifndef APP-PLUS
type: 'gcj02',
// #endif
success: res => {
locationPromise = null;
let latlng = res.latitude + ',' + res.longitude;
getAddressByLatlngFn(latlng);
},
fail: (res) => {
locationPromise = null;
// uni.showToast({ title: res.errMsg, icon: 'none', duration: 15000 });
systemStore.defaultPositionAddress = '定位失败';
if (res.errno) {
if (res.errno == 104) {
let msg = '用户未授权隐私权限,获取位置失败';
// uni.showToast({ title: msg, icon: 'none' });
console.log(msg)
} else if (res.errno == 112) {
let msg = '隐私协议中未声明,获取位置失败';
// uni.showToast({ title: msg, icon: 'none' });
console.log(msg)
}
}
if (res.errMsg) {
if (res.errMsg.indexOf('getLocation:fail') != -1 || res.errMsg.indexOf('deny') != -1 || res.errMsg.indexOf('denied') != -1) {
let msg = '用户未授权获取位置权限,将无法提供服务';
// uni.showToast({ title: msg, icon: 'none' });
console.log(msg)
} else {
// uni.showToast({ title: res.errMsg, icon: 'none' });
console.log(res.errMsg)
}
}
}
});
} else {
locationPromise = null;
}
// #endif
} else {
locationPromise = null;
}
};
// 监听页面加载
const onLoadLifeCycle = (callback: any = '') => {
onLoad((option: any) => {
@ -25,76 +103,112 @@ export function useLocation(isOpenLocation: any) {
});
}
const init = () => {
// 刷新页面时需要调用的
const refreshLocation = () => {
if (!isOpen) return false;
// 使用 locationPromise 作为唯一的锁源
// 如果已经有定位在进行,直接返回
if (locationPromise) {
return;
}
// 立即设置空 Promise 作为锁(这是关键!必须在任何检查之前设置)
// 第二个调用者会在上面的检查中看到 locationPromise 已存在,直接返回
locationPromise = new Promise<void>(() => {});
// 只读取一次本地缓存,减少重复存储调用
const locationCache = uni.getStorageSync('location_address');
const manualSelect = uni.getStorageSync('manually_select_location_from_map');
// 存在手动选点标记,直接终止逻辑
if (manualSelect) {
locationPromise = null;
return;
}
// 有定位缓存
if (locationCache) {
const cacheInfo = locationStorage();
// 缓存未过期,恢复定位信息
if (!cacheInfo.is_expired) {
// 检查经纬度是否有效非空且非0
const hasValidLatLng = locationCache.latitude && locationCache.longitude &&
locationCache.latitude !== 0 && locationCache.longitude !== 0;
if (hasValidLatLng) {
systemStore.setAddressInfo(locationCache);
locationPromise = null;
return; // 有有效缓存,直接返回,不触发定位
}
// 经纬度无效,继续往下走重新定位
}
// 缓存过期或经纬度无效,删除缓存
uni.removeStorageSync('location_address');
}
// 无缓存或缓存无效/过期,直接执行定位
// 排除手动地图选择位置的情况
if (!uni.getStorageSync('manually_select_location_from_map')) {
// #ifdef H5
if (isWeixinBrowser() && systemStore.mapConfig.is_open && !uni.getStorageSync('location_address')) {
if (isWeixinBrowser() && systemStore.mapConfig.is_open) {
wechat.init(() => {
wechat.getLocation(res => {
let latlng = res.latitude + ',' + res.longitude; // 纬度浮点数范围为90 ~ -90经度浮点数范围为180 ~ -180
getAddressByLatlngFn(latlng)
})
locationPromise = null;
let latlng = res.latitude + ',' + res.longitude;
getAddressByLatlngFn(latlng);
});
});
} else {
locationPromise = null;
}
// #endif
// #ifndef H5
if (systemStore.mapConfig.is_open && !uni.getStorageSync('location_address')) {
if (systemStore.mapConfig.is_open) {
uni.getLocation({
// #ifndef APP-PLUS
type: 'gcj02',
// #endif
success: res => {
let latlng = res.latitude + ',' + res.longitude; // 纬度浮点数范围为90 ~ -90经度浮点数范围为180 ~ -180
locationPromise = null;
let latlng = res.latitude + ',' + res.longitude;
getAddressByLatlngFn(latlng);
},
fail: (res) => {
uni.showToast({ title: res.errMsg, icon: 'none', duration: 15000 })
locationPromise = null;
// uni.showToast({ title: res.errMsg, icon: 'none', duration: 15000 });
systemStore.defaultPositionAddress = '定位失败';
if (res.errno) {
if (res.errno == 104) {
let msg = '用户未授权隐私权限,获取位置失败';
uni.showToast({ title: msg, icon: 'none' })
// uni.showToast({ title: msg, icon: 'none' });
console.log(msg)
} else if (res.errno == 112) {
let msg = '隐私协议中未声明,获取位置失败';
uni.showToast({ title: msg, icon: 'none' })
// uni.showToast({ title: msg, icon: 'none' });
console.log(msg)
}
}
if (res.errMsg) {
if (res.errMsg.indexOf('getLocation:fail') != -1 || res.errMsg.indexOf('deny') != -1 || res.errMsg.indexOf('denied') != -1) {
let msg = '用户未授权获取位置权限,将无法提供服务';
uni.showToast({ title: msg, icon: 'none' })
// uni.showToast({ title: msg, icon: 'none' });
console.log(msg)
} else {
uni.showToast({ title: res.errMsg, icon: 'none' })
// uni.showToast({ title: res.errMsg, icon: 'none' });
console.log(res.errMsg)
}
}
}
});
} else {
locationPromise = null;
}
// #endif
} else {
locationPromise = null;
}
}
// 刷新页面时需要调用的
const refreshLocation = () => {
if (!isOpen) return false;
if (!uni.getStorageSync('manually_select_location_from_map') && uni.getStorageSync('location_address')) {
if (locationStorage() && !locationStorage().is_expired) {
systemStore.setAddressInfo(uni.getStorageSync('location_address'))
} else {
uni.removeStorageSync('location_address');
}
}
// 定位信息过期后,重新获取定位
if (!uni.getStorageSync('manually_select_location_from_map') && locationStorage() && locationStorage().is_expired) {
init();
}
}
};
// 通过经纬度获取地址信息
const getAddressByLatlngFn = (latlng: any = '') => {
@ -161,12 +275,15 @@ export function useLocation(isOpenLocation: any) {
if (res.errMsg && res.errno) {
if (res.errno == 104) {
let msg = '用户未授权隐私权限,选择位置失败';
uni.showToast({ title: msg, icon: 'none' })
// uni.showToast({ title: msg, icon: 'none' })
console.log(msg)
} else if (res.errno == 112) {
let msg = '隐私协议中未声明,打开地图选择位置失败';
uni.showToast({ title: msg, icon: 'none' })
// uni.showToast({ title: msg, icon: 'none' })
console.log(msg)
} else {
uni.showToast({ title: res.errMsg, icon: 'none' })
// uni.showToast({ title: res.errMsg, icon: 'none' })
console.log(res.errMsg)
}
}
}

View File

@ -210,6 +210,7 @@
],
"subPackages": [
// {{ PAGE_BEGAIN }}
// {{ PAGE_END }}
{
"root": "app/components",

View File

@ -61,7 +61,7 @@ const useSystemStore = defineStore('system', {
},
shareCallback: null,
defaultPositionAddress: '定位中',
diyAddressInfo: null,
diyAddressInfo: {},
currTabbar: {
path: '',
query: {}

View File

@ -576,12 +576,15 @@ export function copy(value: any, callback: any) {
if (res.errMsg && res.errno) {
if (res.errno == 104) {
let msg = '用户未授权隐私权限,设置剪贴板数据失败';
uni.showToast({ title: msg, icon: 'none' })
// uni.showToast({ title: msg, icon: 'none' })
console.log(msg)
} else if (res.errno == 112) {
let msg = '隐私协议中未声明,设置剪贴板数据失败';
uni.showToast({ title: msg, icon: 'none' })
// uni.showToast({ title: msg, icon: 'none' })
console.log(msg)
} else {
uni.showToast({ title: res.errMsg, icon: 'none' })
// uni.showToast({ title: res.errMsg, icon: 'none' })
console.log(res.errMsg)
}
}
}
@ -845,7 +848,7 @@ export function openMapSelector(backurl: string, params = '') {
// 天地图的位置选择器URL
// 注意天地图的位置选择器API可能与腾讯地图不同需要根据实际API文档调整
const baseUrl = (import.meta.env.VITE_APP_BASE_URL || `${ location.origin }`).replace(/\/api\/$/, '')
const url = baseUrl + `/tianmap/index.html?search=1&type=0&backurl=${ encodeURIComponent(backurl) }&key=${ tiandituKey }` + (params ? '&' + params : '')
const url = baseUrl + `/tianmap/index.html?search=1&type=0&backurl=${ encodeURIComponent(backurl) }&key=${ tiandituKey }&t=${Date.now()}` + (params ? '&' + params : '')
window.location.href = url;
}
}