wzx 8 hónapja
szülő
commit
ba64dc0368
28 módosított fájl, 3634 hozzáadás és 310 törlés
  1. 6 1
      actMgt/components/my-userlist/my-userlist.vue
  2. 2 2
      actMgt/manifest.json
  3. 1 1
      actMgt/pages.json
  4. 40 11
      actMgt/pages/actManage/actDetail.vue
  5. 356 224
      actMgt/pages/actManage/track.vue
  6. 1 1
      actMgt/pages/actManage/userList.vue
  7. 79 0
      actMgt/uni_modules/uni-data-picker/changelog.md
  8. 45 0
      actMgt/uni_modules/uni-data-picker/components/uni-data-picker/keypress.js
  9. 381 0
      actMgt/uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.uvue
  10. 551 0
      actMgt/uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue
  11. 622 0
      actMgt/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js
  12. 692 0
      actMgt/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.uts
  13. 76 0
      actMgt/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.css
  14. 69 0
      actMgt/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.uvue
  15. 323 0
      actMgt/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue
  16. 91 0
      actMgt/uni_modules/uni-data-picker/package.json
  17. 22 0
      actMgt/uni_modules/uni-data-picker/readme.md
  18. 25 0
      actMgt/uni_modules/uni-load-more/changelog.md
  19. 5 0
      actMgt/uni_modules/uni-load-more/components/uni-load-more/i18n/en.json
  20. 8 0
      actMgt/uni_modules/uni-load-more/components/uni-load-more/i18n/index.js
  21. 5 0
      actMgt/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hans.json
  22. 5 0
      actMgt/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hant.json
  23. 117 0
      actMgt/uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue
  24. 84 0
      actMgt/uni_modules/uni-load-more/package.json
  25. 14 0
      actMgt/uni_modules/uni-load-more/readme.md
  26. 4 60
      actMgt/utils/map/leafletHelper.js
  27. 8 8
      actMgt/utils/map/sub/player.js
  28. 2 2
      actMgt/utils/map/sub/route.js

+ 6 - 1
actMgt/components/my-userlist/my-userlist.vue

@@ -16,7 +16,8 @@
 					<image class="item-finish" v-else-if="item.isFinishGame == 1" mode="aspectFit"
 						src="/static/common/finishgame.png"></image>
 				</view>
-				<a class="item-phone" :href="'tel:' + item.phone" style='text-decoration: none;'>{{item.phone}}</a>
+				<a v-if="admin" class="item-phone" :href="'tel:' + item.phone" style='text-decoration: none;'>{{item.phone}}</a>
+				<text v-else class="item-phone">--</text>
 			</template>
 		</uni-list-item>
 	</uni-list>
@@ -29,6 +30,10 @@
 		name: "my-userlist",
 		props: {
 			userRs: {},
+			admin: {
+				type: Boolean,
+				default: false
+			}
 		},
 		data() {
 			return {};

+ 2 - 2
actMgt/manifest.json

@@ -2,8 +2,8 @@
     "name" : "actMgt",
     "appid" : "__UNI__F804C11",
     "description" : "彩图奔跑 - 赛事管理端",
-    "versionName" : "1.0.6",
-    "versionCode" : 106,
+    "versionName" : "1.2.0",
+    "versionCode" : 120,
     "transformPx" : false,
     /* 5+App特有相关 */
     "app-plus" : {

+ 1 - 1
actMgt/pages.json

@@ -16,7 +16,7 @@
 			"path" : "pages/actManage/actDetail",
 			"style" : 
 			{
-				"navigationBarTitleText" : "活动详情"
+				"navigationBarTitleText" : "赛事详情"
 			}
 		},
 		{

+ 40 - 11
actMgt/pages/actManage/actDetail.vue

@@ -1,9 +1,14 @@
+<!-- 
+赛事详情
+http://localhost:5173/actMgt/#/pages/actManage/actDetail?compId=80 
+https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/actDetail?compId=80
+ -->
 <template>
 	<view class="body">
 		<view class="content uni-column">
 			<view class="uni-column top" :style="getBannerStyle()">
 				<my-topbar :title="actRs.config.matchInfo.compName" @btnBackClick="btnBack"
-					:showBack="userlevel > 0"></my-topbar>
+					:showBack="isSelfCreate && userlevel > 0"></my-topbar>
 				<view class="top-content uni-row">
 				</view>
 			</view>
@@ -11,12 +16,12 @@
 			<view class="main uni-column">
 				<view class="compBox uni-column">
 					<view class="compName">
-						<uni-tag :circle="true" :text="pubState[actRs.otherInfo.pubState]"
+						<uni-tag v-if="isSelfCreate && isMgt" :circle="true" :text="pubState[actRs.otherInfo.pubState]"
 							:type="actRs.otherInfo.pubState > 1 ? 'primary' : 'warning'" size="small" />
 						{{actRs.config.matchInfo.compName}}
 					</view>
 					<view class="comp_time">赛事日期:{{getActtime()}}</view>
-					<view v-if="userlevel > 0" class="comp_time">( 联系人:{{actRs.config.matchInfo.contactName}}
+					<view v-if="userlevel > 0 && isSelfCreate" class="comp_time">( 联系人:{{actRs.config.matchInfo.contactName}}
 						&nbsp;&nbsp; 电话:<a :href="'tel:' + actRs.config.matchInfo.phone"
 							style='color: #ff5500;'>{{actRs.config.matchInfo.phone}}</a> )</view>
 
@@ -36,21 +41,24 @@
 						<view class="qrMemo">(微信扫码)</view>
 						<view class="qrMemo">查看赛事详情</view>
 					</view>
-					<view v-if="userlevel > 0" class="uni-column">
+					<view v-if="isMgt" class="uni-column">
 						<image class="imgQrCode" :src="imgQrCodeApp"></image>
 						<view class="qrMemo">(彩图奔跑APP扫码)</view>
-						<view class="qrMemo">查看赛事卡片<text v-if="userlevel > 0" style="color: #ff5500;"
+						<view class="qrMemo">查看赛事卡片<text v-if="isMgt" style="color: #ff5500;"
 								@click="qrCodeReset"> [重置]</text></view>
 					</view>
 				</view>
+				
+				<view class="actButtonBox uni-row uni-jcc">
+					<button v-if="isSelfCreate && isMgt" class="actButton" @click="btnActEdit">赛事修改</button>
+					<button v-if="isSelfCreate && isMgt && actRs.otherInfo.pubState == 1" class="actButton" @click="btnActPublish">赛事发布</button>
+				</view>
 			</view>
 
 			<view class="bottom uni-row uni-jcc">
-				<button v-if="userlevel > 0" class="bottom-button" @click="btnActEdit">赛事修改</button>
-				<button v-if="userlevel > 0 && actRs.otherInfo.pubState == 1" class="bottom-button" @click="btnActPublish">赛事发布</button>
 				<button class="bottom-button" @click="btnRankList">排行榜</button>
-				<!-- <button v-if="userlevel > 0" class="bottom-button" @click="btnTrack">场地直播</button> -->
 				<button class="bottom-button" @click="btnUserList">玩家列表</button>
+				<button v-if="isMgt" class="bottom-button" @click="btnTrack">场地直播</button>
 			</view>
 		</view>
 
@@ -59,7 +67,7 @@
 				@complete="qrCodeWxComplete">
 			</uv-qrcode>
 
-			<uv-qrcode v-if="userlevel > 0" ref="qrCodeApp" class="qrCode" size="300px" :value="qrCodeApp"
+			<uv-qrcode v-if="isMgt" ref="qrCodeApp" class="qrCode" size="300px" :value="qrCodeApp"
 				:options="qrCodeOptApp" @complete="qrCodeAppComplete">
 			</uv-qrcode>
 		</view>
@@ -93,6 +101,9 @@
 				queryObj: {},
 				queryString: "",
 				compId: 0, // 赛事ID
+				
+				isMgt: false,	// 当前用户是否有赛事管理权
+				isSelfCreate: true,	// 是否自助开赛
 
 				qrCodeWx: "",
 				qrCodeOptWx: {
@@ -184,8 +195,10 @@
 						if (checkResCode(res)) {
 							const data = res.data.data;
 							this.actRs = data;
+							this.isSelfCreate = data.otherInfo.isSelfCreate;
+							this.isMgt = data.otherInfo.isMgt;
 
-							if (this.userlevel > 0) {
+							if (this.isMgt) {
 								this.getQrCodeApp();
 							}
 						}
@@ -428,6 +441,20 @@
 		line-height: 23px;
 		font-family: Source Han Sans CN;
 	}
+	
+	.actButtonBox {
+		width: 80%;
+		margin-top: 20px;
+		margin-bottom: 20px;
+	}
+
+	.actButton {
+		height: 30px;
+		background: #FFB40B;
+		font-size: 14px;
+		font-weight: 400;
+		line-height: 30px;
+	}
 
 	.bottom {
 		position: fixed;
@@ -439,8 +466,10 @@
 	}
 
 	.bottom-button {
+		width: 90px;
 		height: 30px;
-		background: #FFB40B;
+		color: #ffffff;
+		background: #2e85ec;
 		font-size: 14px;
 		font-weight: 400;
 		line-height: 30px;

+ 356 - 224
actMgt/pages/actManage/track.vue

@@ -19,25 +19,31 @@ https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/track?compId=80
 							:search="false" :inputClick="false" :clearable="false" @getText="getESelectText"
 							@change="selectMapChange"></e-select>
 					</view>
-					<view class="select">
+					<!-- <view class="select">
 						<e-select v-model="actionId" maxHeight="300px" :props="selectActionProps" :options="actionList"
 							:search="false" :inputClick="false" :clearable="false" @getText="getESelectText"
 							@change="selectActionChange"></e-select>
-					</view>
+					</view> -->
 				</view>
 
 				<view id="map" class="map"></view>
 
 				<view v-show="popupShow" class="popup"
 					:style="{ height: popupHeight + 'px', width: popupWidth + 'px' }">
-					<!-- <uni-section class="section" title="活动路线列表" type="line">
-						<uni-data-picker class="actionsTree" :style="{ width: popupWidth + 'px' }" placeholder="请选择活动" popup-title="请选择活动路线" :localdata="actionsTree"
-							v-model="sltActRoute" @change="onActionChange" @popupopened="onActionsTreePopupOpened" @popupclosed="onActionsTreePopupClosed"></uni-data-picker>
-					</uni-section> -->
-
-					<uni-section class="section" title="玩家列表" type="line">
-						<view class="norecord" v-if="players == null || players.length == 0">暂无记录</view>
-						<scroll-view :scroll-top="0" scroll-y="true" :style="{ height: popupHeight - 43 + 'px'}">
+					<uni-section class="section" title="活动路线列表" type="line">
+						<template v-slot:right>
+							<uni-icons @click="leafletHelper.elListClick(leafletHelper)" type="closeempty"
+								size="16"></uni-icons>
+						</template>
+						<uni-data-picker ref="actionsTree" class="actionsTree" :style="{ width: popupWidth + 'px' }" placeholder="请选择活动路线"
+							popup-title="请选择活动路线" :localdata="actionsTree" v-model="sltActRoute" :clear-icon="false"
+							@change="onActionChange" @popupopened="onActionsTreePopupOpened"
+							@popupclosed="onActionsTreePopupClosed"></uni-data-picker>
+					</uni-section>
+
+					<uni-section class="section" :title="'玩家列表 (' + playersNum + '人)'" type="line">
+						<view class="norecord" v-if="playersNum == 0">暂无记录</view>
+						<scroll-view v-else :scroll-top="0" scroll-y="true" :style="{ height: popupHeight - 122 + 'px'}">
 							<uni-list v-for="(item, index) in players" :key="index" :border="true" class="list">
 								<uni-list-item :clickable="true" @click="onPlayerListItemClick(item)" class="list-item"
 									:class="{ 
@@ -57,13 +63,14 @@ https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/track?compId=80
 													<uni-icons v-if="admin" type="phone" size="14"></uni-icons>
 												</span>
 												打点 {{item.EffectiveNum}}/{{item.TotalControlNum}} &nbsp; 目标点
-												{{item.nextControlPoint.orderNO}} &nbsp; 百味豆 {{item.sysPoint}}
+												{{item.nextControlPoint.orderNO}} &nbsp; <!-- 百味豆 {{item.sysPoint}} -->
 											</view>
 											<view class="slot-note">
 												距离 {{tools.fmtDistanctKm(item.distance)}}km &nbsp; 配速
 												{{tools.convertSecondsToHMS(item.pace, 2)}}
-												&nbsp; Cal {{Math.round(item.Calorie/1000)}} &nbsp; | &nbsp; 心率
-												{{item.lastHr}} &nbsp; 平均 {{item.avgHr}} &nbsp; 最大 {{item.maxHr}}
+												&nbsp; Cal {{Math.round(item.Calorie/1000)}} &nbsp; 
+												 百味豆 {{item.sysPoint}}
+												<!-- | &nbsp; 心率 {{item.lastHr}} &nbsp; 平均 {{item.avgHr}} &nbsp; 最大 {{item.maxHr}}-->
 												<!-- &nbsp; | &nbsp;  Ck {{item.Ck}} Ei {{Math.round(item.Ei*100)/100}}-->
 											</view>
 										</view>
@@ -76,7 +83,6 @@ https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/track?compId=80
 						</scroll-view>
 					</uni-section>
 				</view>
-
 			</view>
 		</view>
 	</view>
@@ -107,11 +113,15 @@ https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/track?compId=80
 	export default {
 		data() {
 			return {
+				leafletHelper: leafletHelper,
 				tools: tools,
 				queryObj: {},
 				queryString: "",
-				interval: null,
-				refreshTime: 300000, // 刷新时间 ms
+				interval_loadActionsTree: null,
+				interval_loadData: null,
+				actionsTreePopup: false,
+				refreshTime_loadData: 3000, // 刷新时间 ms
+				refreshTime_loadActionsTree: 10000, // 刷新时间 ms
 				admin: true, // 是否场控管理员
 
 				compId: 0, // 赛事ID
@@ -127,6 +137,7 @@ https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/track?compId=80
 				actionList: [], // 活动列表
 				actionId: 0, // (当前选中的)活动ID
 				actionDetail: {}, // (当前选中的)活动详情
+				courseId: 0, // (当前选中的)路线ID
 
 				selectMapProps: {
 					value: 'id',
@@ -146,6 +157,9 @@ https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/track?compId=80
 				focusPlayerId: 0,
 				trailTime: 0,
 
+				sltActRoute: '',
+				actionsTree: [],
+
 				popupHeight: 360,
 				popupWidth: 0,
 				popupType: 'bottom',
@@ -161,19 +175,71 @@ https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/track?compId=80
 			...mapGetters([
 				'metadata'
 			]),
+			playersNum() {
+				if (this.players && this.players.length > 0) {
+					return this.players.length;
+				} else {
+					return 0;
+				}
+			},
+			players_position_num() {
+				if (this.players_position && this.players_position.length > 0) {
+					return this.players_position.length;
+				} else {
+					return 0;
+				}
+			},
+			players_position_num_text() {
+				if (this.players_position_num > 0) {
+					return this.players_position_num;
+				} else {
+					return "";
+				}
+			}
 		},
-		onLoad(query) {
+		async onLoad(query) {
 			// console.log(query);
 			this.queryObj = query;
 			this.queryString = tools.objectToQueryString(this.queryObj);
 			// console.log(queryString);
 			this.compId = query["compId"] ?? 0;
 
-			this.compInfoDetail();
-			this.getMapList();
+			this.actRs = await this.compInfoDetail(this.compId);
+
+			this.mapList = await this.getMapList(this.compId);
+			this.mapId = this.mapList[0].id;
+			
+			await this.loadMap();
+
+			// this.actionList = await this.getActionList(this.compId, this.mapId);
+			// this.actionId = this.actionList[0].id;
+
+			// this.actionDetail = await this.getActionDetail(this.actionId);
+
+			// console.log("====> mapSltMapId:", this.$store.state.mapSltMapId);
+			if (this.mapId == this.$store.state.mapSltMapId) { // 页面重载
+				console.log("[onLoad] 页面重载 mapId:", this.mapId);
+				this.sltActRoute = this.$store.state.mapSltActRoute;
+				this.loadData(this.sltActRoute);
+			}
+
+			if (this.interval_loadActionsTree != null) {
+				clearInterval(this.interval_loadActionsTree)
+			}
+
+			let that = this
+			this.interval_loadActionsTree = setInterval(async function() {
+				if (!that.actionsTreePopup) {
+					await that.loadActionsTree()
+				}
+			}, that.refreshTime_loadActionsTree);
+
+			// 自动弹出活动路线列表窗口 供用户选择
+			leafletHelper.elListClick(leafletHelper);
+			this.$refs.actionsTree.show();
 		},
 		mounted() {
-			console.log("mounted");
+			// console.log("mounted");
 			this.$global.getWindowInfo();
 			uni.$on('windowResize', this.reLoad);
 			this.popupShow = this.$store.state.mapPopupShow;
@@ -181,14 +247,26 @@ https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/track?compId=80
 		},
 		beforeDestroy() {
 			console.log("beforeDestroy")
-			clearInterval(this.interval)
-			leafletHelper.free()
+			this.clear();
 		},
 		methods: {
+			clear() {
+				if (this.interval_loadActionsTree != null) {
+					clearInterval(this.interval_loadActionsTree);
+				}
+				if (this.interval_loadData != null) {
+					clearInterval(this.interval_loadData);
+				}
+				
+				leafletHelper.free();
+				uni.$off('windowResize', this.reLoad);
+			},
 			getBannerStyle() {
 				return card.getBannerStyle(this.actRs);
 			},
 			reLoad() {
+				this.clear();
+				this.$store.commit('setMapSltMapId', this.mapId)
 				this.savePlayersData()
 
 				var fullPath = this.$route.fullPath
@@ -200,24 +278,6 @@ https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/track?compId=80
 			// 布局初始化 设置地图高度
 			layoutInit() {
 				this.popupWidth = this.$global.windowWidth
-				/* this.windowHeight = this.$global.windowHeight
-				this.windowWidth = this.$global.windowWidth
-				if (this.$global.deviceOrientation == 'portrait') { // 竖屏
-					this.flexDirection = 'column'
-					this.mapWidth = this.$global.windowWidth
-					this.mapHeight = this.$global.windowHeight
-					
-					this.popupHeight = this.popupHeightPortrait
-					this.popupWidth = this.$global.windowWidth
-				} else { // 横屏
-					this.flexDirection = 'row'
-					this.mapHeight = this.$global.windowHeight
-					this.mapWidth = this.$global.windowWidth
-					
-					this.popupHeight = this.$global.windowHeight
-					this.popupWidth = this.popupWidthlandscape
-					// console.log("横屏 popupHeight", this.popupHeight)
-				} */
 			},
 			popupToggle() {
 				this.popupShow = !this.popupShow
@@ -225,9 +285,21 @@ https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/track?compId=80
 				// this.layoutInit()
 			},
 			async loadMap() {
+				await this.loadActionsTree();
+				/* uni.setNavigationBarTitle({
+					title: this.mapDetail.mapInfo.mapName
+				}); */
 				await mapHelper.handleMapInfo(this, this.mapInfo);
 				this.mapUrl = mapHelper.mapUrl;
 				this.mapConfig = mapHelper.mapConfig;
+
+				await this.initMap();
+				this.handleMapToggle();
+			},
+			async loadActionsTree() {
+				this.mapDetail = await this.getMapDetail(this.compId, this.mapId);
+				this.mapInfo = this.mapDetail.mapInfo;
+				this.makeActionsTree(this.mapDetail.actSelectRs);
 			},
 			async initMap() {
 				const zoomNum = this.mapInfo.DefScale;
@@ -239,37 +311,49 @@ https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/track?compId=80
 					await leafletHelper.init(this, 'map', this.mapUrl, this.mapConfig, mapOptions);
 				}
 			},
-			async loadData() {
-				await this.loadMap();
-
-				await this.initMap();
-				this.handleMapDrawRoute();
-				if (this.interval != null) {
-					clearInterval(this.interval);
+			async loadData(sltActRoute) {
+				// console.log("[loadData] sltActRoute: ", sltActRoute);
+				if (sltActRoute == null || sltActRoute.length == 0) {
+					console.log("[loadData] return: sltActRoute is null ");
+					return;
+				}
+				
+				var actRouteArr = sltActRoute[1].value.split('-');
+				this.actionId = actRouteArr[0];
+				this.courseId = actRouteArr[1];
+				
+				this.actionDetail = await this.getActionDetail(this.actionId, this.courseId);
+				/* uni.setNavigationBarTitle({
+					title: this.mapDetail.mapinfo.mapname + ' - ' + this.actionDetail.name
+				}); */
+				
+				if (this.interval_loadData != null) {
+					clearInterval(this.interval_loadData);
 				}
 
-				let that = this;
-				that.players = await that.getUsersInGameDetail();
-				console.log('players', that.players)
+				this.players = await this.getUsersInGameDetail();
+				// console.log('players', this.players)
 				// leafletHelper.global.setPlayers(this.players)
 
-				that.players_position = await that.usersInGameGpsQuery();
+				this.players_position = await this.usersInGameGpsQuery();
 				// leafletHelper.global.setPlayersPosition(this.players_position)
-
-				that.handleMapDrawPlayer();
-				that.handleMapDrawTrail();
-
-				this.interval = setInterval(async function() {
+				
+				this.handleMapDrawRoute();
+				this.handleMapDrawPlayer();
+				this.handleMapDrawTrail();
+				
+				let that = this;
+				this.interval_loadData = setInterval(async function() {
 					that.players = await that.getUsersInGameDetail();
 					that.players_position = await that.usersInGameGpsQuery();
 					//// leaflet.leafletHelper.global.setPlayers(that.players);
 					// leafletHelper.global.setPlayersPosition(that.players_position);
 					that.handleMapDrawPlayer();
 					that.handleMapDrawTrail();
-				}, that.refreshTime);
+				}, that.refreshTime_loadData);
 
 				// await mapHelper.handleMapInfo(this, this.mapInfo)
-				this.handleMapToggle();
+				// this.handleMapToggle(); // to del
 			},
 			handleWindowResize() {
 				leafletHelper.onWindowResize()
@@ -294,17 +378,10 @@ https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/track?compId=80
 			handleMapDrawTrail() {
 				this.trailTime = leafletHelper.config.trailTime
 				// leafletHelper.player.drawOneTrail(2, 10000)
-				// leafletHelper.player.drawOneTrail(3, 10000)
 				// leafletHelper.player.drawOneTrail(2, 0, false)
 				leafletHelper.player.drawAllTrails(this.trailTime)
 			},
 			handleMapToggle() {
-				// leafletHelper.checkPoint.toggle(true)
-				// leafletHelper.route.toggle(true)
-				// leafletHelper.player.togglePlayer(true)
-				// leafletHelper.player.toggleTooltip(true)
-				// leafletHelper.player.toggleTrail(true)
-
 				leafletHelper.route.toggle(this.$store.state.mapControlRoute)
 				leafletHelper.player.togglePlayer(this.$store.state.mapControlPlayer)
 				leafletHelper.player.toggleTooltip(this.$store.state.mapControlTooltip)
@@ -325,123 +402,129 @@ https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/track?compId=80
 				leafletHelper.global.savePlayersData()
 			},
 			// 自助赛事详情查询
-			compInfoDetail() {
-				uni.request({
-					url: apiCompInfoDetail,
-					header: this.metadata,
-					method: "POST",
-					data: {
-						compId: this.compId
-					},
-					success: (res) => {
-						// console.log("[compInfoDetail] res", res);
-						if (checkResCode(res)) {
-							const data = res.data.data;
-							this.actRs = data;
-						}
-					},
-					fail: (err) => {
-						console.log("[compInfoDetail] err", err);
-					},
-				});
+			async compInfoDetail(compId) {
+				try {
+					return new Promise((resolve, reject) => {
+						uni.request({
+							url: apiCompInfoDetail,
+							header: this.metadata,
+							method: "POST",
+							data: {
+								compId: compId
+							},
+							success: (res) => {
+								// console.log("[compInfoDetail] res", res);
+								if (checkResCode(res)) {
+									const data = res.data.data;
+									resolve(data);									
+								}
+							},
+							fail: (err) => {
+								console.log("[compInfoDetail] err", err);
+								reject(err);
+							},
+						});
+					});
+				} catch (e) {
+					console.log('[compInfoDetail] err', e)
+					reject(e)
+				}
 			},
 			// 自助赛事详情查询
-			getMapList() {
-				uni.request({
-					url: apiMapList,
-					header: this.metadata,
-					method: "POST",
-					data: {
-						compId: this.compId
-					},
-					success: (res) => {
-						console.log("[getMapList] res", res);
-						if (checkResCode(res)) {
-							const data = res.data.data;
-							this.mapList = data.list;
-							this.mapId = data.list[0].id;
-							this.selectMapChange();
-						}
-					},
-					fail: (err) => {
-						console.log("[getMapList] err", err);
-					},
-				});
+			async getMapList(compId) {
+				try {
+					return new Promise((resolve, reject) => {
+						uni.request({
+							url: apiMapList,
+							header: this.metadata,
+							method: "POST",
+							data: {
+								compId: compId
+							},
+							success: (res) => {
+								// console.log("[getMapList] res", res);
+								if (checkResCode(res)) {
+									const data = res.data.data;
+									resolve(data.list);
+								} else {
+									reject(res);
+								}
+							},
+							fail: (err) => {
+								console.log("[getMapList] err", err);
+								reject(err);
+							},
+						});
+					});
+				} catch (e) {
+					console.log('[getMapList] err', e)
+					reject(e)
+				}
 			},
 			// 赛事监控地图详情
-			getMapDetail() {
-				uni.request({
-					url: apiMapDetail,
-					header: this.metadata,
-					method: "POST",
-					data: {
-						compId: this.compId,
-						mapId: this.mapId
-					},
-					success: (res) => {
-						console.log("[getMapDetail] res", res);
-						if (checkResCode(res)) {
-							const data = res.data.data;
-							this.mapDetail = data;
-							this.mapInfo = data.mapInfo;
-							// this.mapUrl = data.mapInfo.mapUrl;
-							// console.log("[getMapDetail] mapInfo", this.mapInfo);
-						}
-					},
-					fail: (err) => {
-						console.log("[getMapDetail] err", err);
-					},
-				});
+			async getMapDetail(compId, mapId) {
+				try {
+					return new Promise((resolve, reject) => {
+						uni.request({
+							url: apiMapDetail,
+							header: this.metadata,
+							method: "POST",
+							data: {
+								compId: compId,
+								mapId: mapId
+							},
+							success: (res) => {
+								// console.log("[getMapDetail] res", res);
+								if (checkResCode(res)) {
+									const data = res.data.data;
+									resolve(data);
+								} else {
+									reject(res);
+								}
+							},
+							fail: (err) => {
+								console.log("[getMapDetail] err", err);
+								reject(err);
+							},
+						});
+					});
+				} catch (e) {
+					console.log('[getMapDetail] err', e)
+					reject(e)
+				}
 			},
 			// 赛事监控地图下的活动列表
-			getActionList() {
-				uni.request({
-					url: apiActionList,
-					header: this.metadata,
-					method: "POST",
-					data: {
-						compId: this.compId,
-						mapId: this.mapId
-					},
-					success: (res) => {
-						console.log("[getActionList] res", res);
-						if (checkResCode(res)) {
-							const data = res.data.data;
-							this.actionList = data.list;
-							this.actionId = data.list[0].id;
-							this.selectActionChange();
-						}
-					},
-					fail: (err) => {
-						console.log("[getActionList] err", err);
-					},
-				});
+			async getActionList(compId, mapId) {
+				try {
+					return new Promise((resolve, reject) => {
+						uni.request({
+							url: apiActionList,
+							header: this.metadata,
+							method: "POST",
+							data: {
+								compId: compId,
+								mapId: mapId
+							},
+							success: (res) => {
+								// console.log("[getActionList] res", res);
+								if (checkResCode(res)) {
+									const data = res.data.data;
+									resolve(data.list);
+								}
+							},
+							fail: (err) => {
+								console.log("[getActionList] err", err);
+								reject(err);
+							},
+						});
+					});
+				} catch (e) {
+					console.log('[getActionList] err', e)
+					reject(e)
+				}
 			},
 			// 赛事监控地图下的活动详情
-			getActionDetail() {
-				uni.request({
-					url: apiActionDetail,
-					header: this.metadata,
-					method: "POST",
-					data: {
-						actId: this.actionId
-					},
-					success: (res) => {
-						console.log("[getActionDetail] res", res);
-						if (checkResCode(res)) {
-							const data = res.data.data;
-							this.actionDetail = data;
-
-							this.loadData();
-						}
-					},
-					fail: (err) => {
-						console.log("[getActionDetail] err", err);
-					},
-				});
-			},
-			//场控端_活动详情
-			/* async getActionDetail() {
+			async getActionDetail(actionId, courseId) {
 				try {
 					return new Promise((resolve, reject) => {
 						uni.request({
@@ -449,18 +532,18 @@ https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/track?compId=80
 							header: this.metadata,
 							method: "POST",
 							data: {
-								actId: this.actionId
+								actId: actionId,
+								courseId: courseId
 							},
 							success: (res) => {
-								console.log("getActionDetail", res);
+								// console.log("[getActionDetail] res", res);
 								if (checkResCode(res)) {
-									resolve(res);
-								} else {
-									reject(res);
+									const data = res.data.data;
+									resolve(data);
 								}
 							},
 							fail: (err) => {
-								console.log("getActionDetail err", err);
+								console.log("[getActionDetail] err", err);
 								reject(err);
 							},
 						});
@@ -469,7 +552,7 @@ https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/track?compId=80
 					console.log('[getActionDetail] err', e)
 					reject(e)
 				}
-			}, */
+			},
 			//场控端_正在进行中所有用户实时信息
 			async getUsersInGameDetail() {
 				try {
@@ -479,10 +562,11 @@ https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/track?compId=80
 							header: this.metadata,
 							method: "POST",
 							data: {
-								actId: this.actionId
+								actId: this.actionId,
+								courseId: this.courseId
 							},
 							success: (res) => {
-								console.log("getUsersInGameDetail", res);
+								// console.log("[getUsersInGameDetail] res", res);
 								if (checkResCode(res)) {
 									resolve(res.data.data.users);
 								} else {
@@ -490,7 +574,7 @@ https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/track?compId=80
 								}
 							},
 							fail: (err) => {
-								console.log("getUsersInGameDetail err", err);
+								console.log("[getUsersInGameDetail] err", err);
 								reject(err);
 							},
 						});
@@ -509,10 +593,11 @@ https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/track?compId=80
 							header: this.metadata,
 							method: "POST",
 							data: {
-								actId: this.actionId
+								actId: this.actionId,
+								courseId: this.courseId
 							},
 							success: (res) => {
-								console.log("usersInGameGpsQuery", res);
+								// console.log("[usersInGameGpsQuery] res", res);
 								if (checkResCode(res)) {
 									resolve(res.data.data.gpsInfo);
 								} else {
@@ -520,7 +605,7 @@ https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/track?compId=80
 								}
 							},
 							fail: (err) => {
-								console.log("usersInGameGpsQuery err", err);
+								console.log("[usersInGameGpsQuery] err", err);
 								reject(err);
 							},
 						});
@@ -530,9 +615,56 @@ https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/track?compId=80
 					reject(e)
 				}
 			},
+			makeActionsTree(actSelectRs) {
+				this.actionsTree.length = 0 // 先清空数组
+				for (let i = 0; i < actSelectRs.length; i++) {
+					var act = actSelectRs[i]
+					var pushData = {
+						text: act.actName,
+						value: act.actId,
+						children: []
+					}
+
+					var actUserNum = 0
+					for (let j = 0; j < act.courseSelectRs.length; j++) {
+						var course = act.courseSelectRs[j]
+						const courseUserNum = course.courseUserNum > 0 ? course.courseUserNum : 0
+						actUserNum += courseUserNum
+						pushData.children.push({
+							text: course.courseName + ' (' + courseUserNum + '人)',
+							value: act.actId + '-' + course.courseId
+						})
+					}
+					if (actUserNum >= 0) {
+						pushData.children.unshift({
+							text: '全部 (' + actUserNum + '人)',
+							value: act.actId + '-' + 0
+						})
+					}
+
+					pushData.text += ' (' + actUserNum + '人)'
+					this.actionsTree.push(pushData)
+				}
+				// console.log("[makeActionsTree]" + JSON.stringify(this.actionsTree))
+			},
 			onActionChange(e) {
-				const value = e.detail.value
-				console.log("onActionChange", value)
+				const sltActRoute = e.detail.value
+				// console.log("onActionChange", sltActRoute)
+				this.$store.commit('setMapSltActRoute', sltActRoute)
+
+				if (sltActRoute == null || sltActRoute.length == 0) {
+					this.reLoad()
+					return
+				}
+				this.loadData(sltActRoute)
+			},
+			onActionsTreePopupOpened() {
+				// console.log("onActionsTreePopupOpened")
+				this.actionsTreePopup = true
+			},
+			onActionsTreePopupClosed() {
+				console.log("onActionsTreePopupClosed")
+				this.actionsTreePopup = false
 			},
 			onPlayerListItemClick(item) {
 				// console.log("onListItemClick", item)
@@ -561,16 +693,21 @@ https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/track?compId=80
 			getESelectText(data) {
 				// console.log("getESelectText:", data);
 			},
-			selectMapChange(data) {
+			async selectMapChange(data) {
 				// console.log("selectMapChange:", data);
-				this.getMapDetail();
-				this.getActionList();
+				this.mapId = data.id;
+				await loadActionsTree();
+				
+				this.actionList = await this.getActionList(this.compId, this.mapId);
+				this.actionId = this.actionList[0].id;
 			},
-			selectActionChange(data) {
+			/* async selectActionChange(data) {
 				// console.log("selectActionChange:", data);
-				this.getActionDetail();
-			},
+				this.actionId = data.id;
+				this.actionDetail = await this.getActionDetail(this.actionId);
+			}, */
 			btnBack() {
+				this.clear();
 				const url = "/pages/actManage/actDetail?" + this.queryString;
 				tools.appAction(url, "uni.navigateTo");
 			},
@@ -598,7 +735,8 @@ https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/track?compId=80
 	}
 
 	.select {
-		width: 48%;
+		/* width: 48%; */
+		width: 96%;
 	}
 
 	.map {
@@ -610,10 +748,11 @@ https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/track?compId=80
 
 	.popup {
 		display: flex;
+		height: 30vh;
+		overflow: scroll;
 		flex-direction: column;
 		align-items: center;
-		background-color: #f5f5f5;
-		/* border-left: #dedede solid 1px; */
+		background-color: #ffffff;
 		border-top: #dedede solid 1px;
 	}
 
@@ -621,8 +760,23 @@ https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/track?compId=80
 		width: 100%;
 	}
 
-	.scroll {
-		overflow: scroll;
+	.actionsTree {
+	}
+	
+	/deep/ .input-value-border {
+	    border-top: 1px solid #e5e5e5;
+	    border-bottom: 1px solid #e5e5e5;
+		border-left: 0;
+		border-right: 0;
+	    border-radius: 0px;
+	}
+	
+	/deep/ .uni-scroll-view {
+	    overflow: unset !important;
+	}
+	
+	/deep/ .uni-section-header {
+		padding-right: 7px !important;
 	}
 
 	.section-title {
@@ -637,25 +791,6 @@ https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/track?compId=80
 		height: 100%;
 	}
 
-	/* .section-content-item {
-		display: flex;
-		flex-direction: row;
-		align-items: center;
-		height: 46px;
-	} */
-
-	/* .actionsTree {
-		/deep/ .input-value-border {
-		    border-top: 1px solid #e5e5e5;
-		    border-bottom: 1px solid #e5e5e5;
-		    border-radius: 0px;
-		}
-		
-		/deep/ .uni-scroll-view {
-		    overflow: unset !important;
-		}
-	} */
-
 	.list {
 		margin-left: -6px;
 	}
@@ -688,7 +823,7 @@ https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/track?compId=80
 		font-size: 13px;
 		color: #424242;
 		line-height: 18px;
-		white-space: nowrap;
+		/* white-space: nowrap; */
 	}
 
 	.slot-sn {
@@ -700,7 +835,7 @@ https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/track?compId=80
 
 	.slot-note {
 		flex: 1;
-		margin-left: 20px;
+		margin-left: 25px;
 		font-size: 12px;
 		color: #7d8da7;
 		line-height: 18px;
@@ -721,7 +856,4 @@ https://oss-mbh5.colormaprun.com/actMgt/#/pages/actManage/track?compId=80
 		line-height: 50px;
 	}
 
-	/* /deep/ .uni-data-tree-dialog {
-		top: 39px;
-	} */
 </style>

+ 1 - 1
actMgt/pages/actManage/userList.vue

@@ -18,7 +18,7 @@
 					</template>
 				</view> -->
 				
-				<my-userlist :userRs="userList"></my-userlist>
+				<my-userlist :userRs="userList" :admin="userlevel > 0"></my-userlist>
 			</view>
 		</view>
 	</view>

+ 79 - 0
actMgt/uni_modules/uni-data-picker/changelog.md

@@ -0,0 +1,79 @@
+## 2.0.1(2024-08-22)
+- 修复 uni-app-x v-model 没有更新传入值的 bug
+## 2.0.0(2023-12-11)
+- 新增 支持 uni-app-x
+## 1.1.2(2023-04-11)
+- 修复 更改 modelValue 报错的 bug
+- 修复 v-for 未使用 key 值控制台 warning
+## 1.1.1(2023-02-21)
+- 修复代码合并时引发 value 属性为空时不渲染数据的问题
+## 1.1.0(2023-02-15)
+- 修复 localdata 不支持动态更新的bug
+## 1.0.9(2023-02-15)
+- 修复 localdata 不支持动态更新的bug
+## 1.0.8(2022-09-16)
+- 可以使用 uni-scss 控制主题色
+## 1.0.7(2022-07-06)
+- 优化 pc端图标位置不正确的问题
+## 1.0.6(2022-07-05)
+- 优化 显示样式
+## 1.0.5(2022-07-04)
+- 修复 uni-data-picker 在 uni-forms-item 中宽度不正确的bug
+## 1.0.4(2022-04-19)
+- 修复 字节小程序 本地数据无法选择下一级的Bug
+## 1.0.3(2022-02-25)
+- 修复 nvue 不支持的 v-show 的 bug
+## 1.0.2(2022-02-25)
+- 修复 条件编译 nvue 不支持的 css 样式
+## 1.0.1(2021-11-23)
+- 修复 由上个版本引发的map、v-model等属性不生效的bug
+## 1.0.0(2021-11-19)
+- 优化 组件 UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-data-picker](https://uniapp.dcloud.io/component/uniui/uni-data-picker)
+## 0.4.9(2021-10-28)
+- 修复 VUE2 v-model 概率无效的 bug
+## 0.4.8(2021-10-27)
+- 修复 v-model 概率无效的 bug
+## 0.4.7(2021-10-25)
+- 新增 属性 spaceInfo 服务空间配置 HBuilderX 3.2.11+
+- 修复 树型 uniCloud 数据类型为 int 时报错的 bug
+## 0.4.6(2021-10-19)
+- 修复 非 VUE3 v-model 为 0 时无法选中的 bug
+## 0.4.5(2021-09-26)
+- 新增 清除已选项的功能(通过 clearIcon 属性配置是否显示按钮),同时提供 clear 方法以供调用,二者等效
+- 修复 readonly 为 true 时报错的 bug
+## 0.4.4(2021-09-26)
+- 修复 上一版本造成的 map 属性失效的 bug
+- 新增 ellipsis 属性,支持配置 tab 选项长度过长时是否自动省略
+## 0.4.3(2021-09-24)
+- 修复 某些情况下级联未触发的 bug
+## 0.4.2(2021-09-23)
+- 新增 提供 show 和 hide 方法,开发者可以通过 ref 调用
+- 新增 选项内容过长自动添加省略号
+## 0.4.1(2021-09-15)
+- 新增 map 属性 字段映射,将 text/value 映射到数据中的其他字段
+## 0.4.0(2021-07-13)
+- 组件兼容 vue3,如何创建 vue3 项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 0.3.5(2021-06-04)
+- 修复 无法加载云端数据的问题
+## 0.3.4(2021-05-28)
+- 修复 v-model 无效问题
+- 修复 loaddata 为空数据组时加载时间过长问题
+- 修复 上个版本引出的本地数据无法选择带有 children 的 2 级节点
+## 0.3.3(2021-05-12)
+- 新增 组件示例地址
+## 0.3.2(2021-04-22)
+- 修复 非树形数据有 where 属性查询报错的问题
+## 0.3.1(2021-04-15)
+- 修复 本地数据概率无法回显时问题
+## 0.3.0(2021-04-07)
+- 新增 支持云端非树形表结构数据
+- 修复 根节点 parent_field 字段等于 null 时选择界面错乱问题
+## 0.2.0(2021-03-15)
+- 修复 nodeclick、popupopened、popupclosed 事件无法触发的问题
+## 0.1.9(2021-03-09)
+- 修复 微信小程序某些情况下无法选择的问题
+## 0.1.8(2021-02-05)
+- 优化 部分样式在 nvue 上的兼容表现
+## 0.1.7(2021-02-05)
+- 调整为 uni_modules 目录规范

+ 45 - 0
actMgt/uni_modules/uni-data-picker/components/uni-data-picker/keypress.js

@@ -0,0 +1,45 @@
+// #ifdef H5
+export default {
+  name: 'Keypress',
+  props: {
+    disable: {
+      type: Boolean,
+      default: false
+    }
+  },
+  mounted () {
+    const keyNames = {
+      esc: ['Esc', 'Escape'],
+      tab: 'Tab',
+      enter: 'Enter',
+      space: [' ', 'Spacebar'],
+      up: ['Up', 'ArrowUp'],
+      left: ['Left', 'ArrowLeft'],
+      right: ['Right', 'ArrowRight'],
+      down: ['Down', 'ArrowDown'],
+      delete: ['Backspace', 'Delete', 'Del']
+    }
+    const listener = ($event) => {
+      if (this.disable) {
+        return
+      }
+      const keyName = Object.keys(keyNames).find(key => {
+        const keyName = $event.key
+        const value = keyNames[key]
+        return value === keyName || (Array.isArray(value) && value.includes(keyName))
+      })
+      if (keyName) {
+        // 避免和其他按键事件冲突
+        setTimeout(() => {
+          this.$emit(keyName, {})
+        }, 0)
+      }
+    }
+    document.addEventListener('keyup', listener)
+    this.$once('hook:beforeDestroy', () => {
+      document.removeEventListener('keyup', listener)
+    })
+  },
+	render: () => {}
+}
+// #endif

+ 381 - 0
actMgt/uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.uvue

@@ -0,0 +1,381 @@
+<template>
+  <view class="uni-data-tree">
+    <view class="uni-data-tree-input" @click="handleInput">
+      <slot :data="selectedPaths" :error="error">
+        <view class="input-value" :class="{'input-value-border': border}">
+          <text v-if="error!=null" class="error-text">{{error!.errMsg}}</text>
+          <scroll-view v-if="selectedPaths.length" class="selected-path" scroll-x="true">
+            <view class="selected-list">
+              <template v-for="(item, index) in selectedPaths">
+                <text class="text-color">{{item[mappingTextName]}}</text>
+                <text v-if="index<selectedPaths.length-1" class="input-split-line">{{split}}</text>
+              </template>
+            </view>
+          </scroll-view>
+          <text v-else-if="error==null&&!loading" class="placeholder">{{placeholder}}</text>
+          <view v-if="!readonly" class="arrow-area">
+            <view class="input-arrow"></view>
+          </view>
+        </view>
+      </slot>
+      <view v-if="loading && !isOpened" class="selected-loading">
+        <slot name="picker-loading" :loading="loading"></slot>
+      </view>
+    </view>
+    <view class="uni-data-tree-cover" v-if="isOpened" @click="handleClose"></view>
+    <view class="uni-data-tree-dialog" v-if="isOpened">
+      <view class="uni-popper__arrow"></view>
+      <view class="dialog-caption">
+        <view class="dialog-title-view">
+          <text class="dialog-title">{{popupTitle}}</text>
+        </view>
+        <view class="dialog-close" @click="handleClose">
+          <view class="dialog-close-plus" data-id="close"></view>
+          <view class="dialog-close-plus dialog-close-rotate" data-id="close"></view>
+        </view>
+      </view>
+      <view ref="pickerView" class="uni-data-pickerview">
+        <view v-if="error!=null" class="error">
+          <text class="error-text">{{error!.errMsg}}</text>
+        </view>
+        <scroll-view v-if="!isCloudDataList" :scroll-x="true">
+          <view class="selected-node-list">
+            <template v-for="(item, index) in selectedNodes">
+              <text class="selected-node-item" :class="{'selected-node-item-active':index==selectedIndex}"
+                @click="onTabSelect(index)">
+                {{item[mappingTextName]}}
+              </text>
+            </template>
+          </view>
+        </scroll-view>
+        <list-view class="list-view" :scroll-y="true">
+          <list-item class="list-item" v-for="(item, _) in currentDataList" @click="onNodeClick(item)">
+            <text class="item-text" :class="{'item-text-disabled': item['disable']}">{{item[mappingTextName]}}</text>
+            <text class="check" v-if="item[mappingValueName] == selectedNodes[selectedIndex][mappingValueName]"></text>
+          </list-item>
+        </list-view>
+        <view class="loading-cover" v-if="loading">
+          <slot name="pickerview-loading" :loading="loading"></slot>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+  import { dataPicker } from "../uni-data-pickerview/uni-data-picker.uts"
+
+  /**
+   * DataPicker 级联选择
+   * @description 支持单列、和多列级联选择。列数没有限制,如果屏幕显示不全,顶部tab区域会左右滚动。
+   * @tutorial https://ext.dcloud.net.cn/plugin?id=3796
+   * @property {String} popup-title 弹出窗口标题
+   * @property {Array} localdata 本地数据,参考
+   * @property {Boolean} border = [true|false] 是否有边框
+   * @property {Boolean} readonly = [true|false] 是否仅读
+   * @property {Boolean} preload = [true|false] 是否预加载数据
+   * @value true 开启预加载数据,点击弹出窗口后显示已加载数据
+   * @value false 关闭预加载数据,点击弹出窗口后开始加载数据
+   * @property {Boolean} step-searh = [true|false] 是否分布查询
+   * @value true 启用分布查询,仅查询当前选中节点
+   * @value false 关闭分布查询,一次查询出所有数据
+   * @property {String|DBFieldString} self-field 分布查询当前字段名称
+   * @property {String|DBFieldString} parent-field 分布查询父字段名称
+   * @property {String|DBCollectionString} collection 表名
+   * @property {String|DBFieldString} field 查询字段,多个字段用 `,` 分割
+   * @property {String} orderby 排序字段及正序倒叙设置
+   * @property {String|JQLString} where 查询条件
+   * @event {Function} popupshow 弹出的选择窗口打开时触发此事件
+   * @event {Function} popuphide 弹出的选择窗口关闭时触发此事件
+   */
+  export default {
+    name: 'UniDataPicker',
+    emits: ['popupopened', 'popupclosed', 'nodeclick', 'change', 'input', 'update:modelValue', 'inputclick'],
+    mixins: [dataPicker],
+    props: {
+      popupTitle: {
+        type: String,
+        default: '请选择'
+      },
+      placeholder: {
+        type: String,
+        default: '请选择'
+      },
+      heightMobile: {
+        type: String,
+        default: ''
+      },
+      readonly: {
+        type: Boolean,
+        default: false
+      },
+      clearIcon: {
+        type: Boolean,
+        default: true
+      },
+      border: {
+        type: Boolean,
+        default: true
+      },
+      split: {
+        type: String,
+        default: '/'
+      },
+      ellipsis: {
+        type: Boolean,
+        default: true
+      }
+    },
+    data() {
+      return {
+        isOpened: false
+      }
+    },
+    computed: {
+      isShowClearIcon() : boolean {
+        if (this.readonly) {
+          return false
+        }
+
+        if (this.clearIcon && this.selectedPaths.length > 0) {
+          return true
+        }
+
+        return false
+      }
+    },
+    created() {
+      this.load()
+    },
+    methods: {
+      clear() {
+      },
+      load() {
+        if (this.isLocalData) {
+          this.loadLocalData()
+        } else if (this.isCloudDataList || this.isCloudDataTree) {
+          this.loadCloudDataPath()
+        }
+      },
+      show() {
+        this.isOpened = true
+        this.$emit('popupopened')
+        if (!this.hasCloudTreeData) {
+          this.loadData()
+        }
+      },
+      hide() {
+        this.isOpened = false
+        this.$emit('popupclosed')
+      },
+      handleInput() {
+        if (this.readonly) {
+          this.$emit('inputclick')
+        } else {
+          this.show()
+        }
+      },
+      handleClose() {
+        this.hide()
+      },
+      onFinish() {
+        this.selectedPaths = this.getChangeNodes()
+        this.$emit('update:modelValue', this.selectedPaths)
+        this.$emit('change', this.selectedPaths)
+        this.hide()
+      }
+    }
+  }
+</script>
+
+<style>
+  @import url("../uni-data-pickerview/uni-data-pickerview.css");
+
+  .uni-data-tree {
+    position: relative;
+  }
+
+  .uni-data-tree-input {
+    position: relative;
+  }
+
+  .selected-loading {
+    display: flex;
+    justify-content: center;
+    position: absolute;
+    left: 0;
+    top: 0;
+    right: 0;
+    bottom: 0;
+  }
+
+  .error-text {
+    flex: 1;
+    font-size: 12px;
+    color: #DD524D;
+  }
+
+  .input-value {
+    flex-direction: row;
+    align-items: center;
+    flex-wrap: nowrap;
+    padding: 5px 5px;
+    padding-right: 5px;
+    overflow: hidden;
+    min-height: 28px;
+  }
+
+  .input-value-border {
+    border: 1px solid #e5e5e5;
+    border-radius: 5px;
+  }
+
+  .selected-path {
+    flex: 1;
+    flex-direction: row;
+    overflow: hidden;
+  }
+
+  .load-more {
+    width: 40px;
+  }
+
+  .selected-list {
+    flex-direction: row;
+    flex-wrap: nowrap;
+  }
+
+  .selected-item {
+    flex-direction: row;
+    flex-wrap: nowrap;
+  }
+
+  .text-color {
+    font-size: 14px;
+    color: #333;
+  }
+
+  .placeholder {
+    color: grey;
+    font-size: 14px;
+  }
+
+  .input-split-line {
+    opacity: .5;
+    margin-left: 1px;
+    margin-right: 1px;
+  }
+
+  .arrow-area {
+    position: relative;
+    padding: 0 12px;
+    margin-left: auto;
+    justify-content: center;
+    transform: rotate(-45deg);
+    transform-origin: center;
+  }
+
+  .input-arrow {
+    width: 8px;
+    height: 8px;
+    border-left: 2px solid #999;
+    border-bottom: 2px solid #999;
+  }
+
+  .uni-data-tree-cover {
+    position: fixed;
+    left: 0;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    background-color: rgba(0, 0, 0, .4);
+    flex-direction: column;
+    z-index: 100;
+  }
+
+  .uni-data-tree-dialog {
+    position: fixed;
+    left: 0;
+    top: 20%;
+    right: 0;
+    bottom: 0;
+    background-color: #FFFFFF;
+    border-top-left-radius: 10px;
+    border-top-right-radius: 10px;
+    flex-direction: column;
+    z-index: 102;
+    overflow: hidden;
+  }
+
+  .dialog-caption {
+    position: relative;
+    flex-direction: row;
+  }
+
+  .dialog-title-view {
+    flex: 1;
+  }
+
+  .dialog-title {
+    align-self: center;
+    padding: 0 10px;
+    line-height: 44px;
+  }
+
+  .dialog-close {
+    position: absolute;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    flex-direction: row;
+    align-items: center;
+    padding: 0 15px;
+  }
+
+  .dialog-close-plus {
+    width: 16px;
+    height: 2px;
+    background-color: #666;
+    border-radius: 2px;
+    transform: rotate(45deg);
+  }
+
+  .dialog-close-rotate {
+    position: absolute;
+    transform: rotate(-45deg);
+  }
+
+  .uni-data-pickerview {
+    flex: 1;
+  }
+
+  .icon-clear {
+    display: flex;
+    align-items: center;
+  }
+
+  /* #ifdef H5 */
+  @media all and (min-width: 768px) {
+    .uni-data-tree-cover {
+      background-color: transparent;
+    }
+
+    .uni-data-tree-dialog {
+      position: absolute;
+      top: 55px;
+      height: auto;
+      min-height: 400px;
+      max-height: 50vh;
+      background-color: #fff;
+      border: 1px solid #EBEEF5;
+      box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+      border-radius: 4px;
+      overflow: unset;
+    }
+
+    .dialog-caption {
+      display: none;
+    }
+  }
+  /* #endif */
+</style>

+ 551 - 0
actMgt/uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue

@@ -0,0 +1,551 @@
+<template>
+  <view class="uni-data-tree">
+    <view class="uni-data-tree-input" @click="handleInput">
+      <slot :options="options" :data="inputSelected" :error="errorMessage">
+        <view class="input-value" :class="{'input-value-border': border}">
+          <text v-if="errorMessage" class="selected-area error-text">{{errorMessage}}</text>
+          <view v-else-if="loading && !isOpened" class="selected-area">
+            <uni-load-more class="load-more" :contentText="loadMore" status="loading"></uni-load-more>
+          </view>
+          <scroll-view v-else-if="inputSelected.length" class="selected-area" scroll-x="true">
+            <view class="selected-list">
+              <view class="selected-item" v-for="(item,index) in inputSelected" :key="index">
+                <text class="text-color">{{item.text}}</text><text v-if="index<inputSelected.length-1"
+                  class="input-split-line">{{split}}</text>
+              </view>
+            </view>
+          </scroll-view>
+          <text v-else class="selected-area placeholder">{{placeholder}}</text>
+          <view v-if="clearIcon && !readonly && inputSelected.length" class="icon-clear" @click.stop="clear">
+            <uni-icons type="clear" color="#c0c4cc" size="24"></uni-icons>
+          </view>
+          <view class="arrow-area" v-if="(!clearIcon || !inputSelected.length) && !readonly ">
+            <view class="input-arrow"></view>
+          </view>
+        </view>
+      </slot>
+    </view>
+    <view class="uni-data-tree-cover" v-if="isOpened" @click="handleClose"></view>
+    <view class="uni-data-tree-dialog" v-if="isOpened">
+      <view class="uni-popper__arrow"></view>
+      <view class="dialog-caption">
+        <view class="title-area">
+          <text class="dialog-title">{{popupTitle}}</text>
+        </view>
+        <view class="dialog-close" @click="handleClose">
+          <view class="dialog-close-plus" data-id="close"></view>
+          <view class="dialog-close-plus dialog-close-rotate" data-id="close"></view>
+        </view>
+      </view>
+      <data-picker-view class="picker-view" ref="pickerView" v-model="dataValue" :localdata="localdata"
+        :preload="preload" :collection="collection" :field="field" :orderby="orderby" :where="where"
+        :step-searh="stepSearh" :self-field="selfField" :parent-field="parentField" :managed-mode="true" :map="map"
+        :ellipsis="ellipsis" @change="onchange" @datachange="ondatachange" @nodeclick="onnodeclick">
+      </data-picker-view>
+    </view>
+  </view>
+</template>
+
+<script>
+  import dataPicker from "../uni-data-pickerview/uni-data-picker.js"
+  import DataPickerView from "../uni-data-pickerview/uni-data-pickerview.vue"
+
+  /**
+   * DataPicker 级联选择
+   * @description 支持单列、和多列级联选择。列数没有限制,如果屏幕显示不全,顶部tab区域会左右滚动。
+   * @tutorial https://ext.dcloud.net.cn/plugin?id=3796
+   * @property {String} popup-title 弹出窗口标题
+   * @property {Array} localdata 本地数据,参考
+   * @property {Boolean} border = [true|false] 是否有边框
+   * @property {Boolean} readonly = [true|false] 是否仅读
+   * @property {Boolean} preload = [true|false] 是否预加载数据
+   * @value true 开启预加载数据,点击弹出窗口后显示已加载数据
+   * @value false 关闭预加载数据,点击弹出窗口后开始加载数据
+   * @property {Boolean} step-searh = [true|false] 是否分布查询
+   * @value true 启用分布查询,仅查询当前选中节点
+   * @value false 关闭分布查询,一次查询出所有数据
+   * @property {String|DBFieldString} self-field 分布查询当前字段名称
+   * @property {String|DBFieldString} parent-field 分布查询父字段名称
+   * @property {String|DBCollectionString} collection 表名
+   * @property {String|DBFieldString} field 查询字段,多个字段用 `,` 分割
+   * @property {String} orderby 排序字段及正序倒叙设置
+   * @property {String|JQLString} where 查询条件
+   * @event {Function} popupshow 弹出的选择窗口打开时触发此事件
+   * @event {Function} popuphide 弹出的选择窗口关闭时触发此事件
+   */
+  export default {
+    name: 'UniDataPicker',
+    emits: ['popupopened', 'popupclosed', 'nodeclick', 'input', 'change', 'update:modelValue','inputclick'],
+    mixins: [dataPicker],
+    components: {
+      DataPickerView
+    },
+    props: {
+      options: {
+        type: [Object, Array],
+        default () {
+          return {}
+        }
+      },
+      popupTitle: {
+        type: String,
+        default: '请选择'
+      },
+      placeholder: {
+        type: String,
+        default: '请选择'
+      },
+      heightMobile: {
+        type: String,
+        default: ''
+      },
+      readonly: {
+        type: Boolean,
+        default: false
+      },
+      clearIcon: {
+        type: Boolean,
+        default: true
+      },
+      border: {
+        type: Boolean,
+        default: true
+      },
+      split: {
+        type: String,
+        default: '/'
+      },
+      ellipsis: {
+        type: Boolean,
+        default: true
+      }
+    },
+    data() {
+      return {
+        isOpened: false,
+        inputSelected: []
+      }
+    },
+    created() {
+      this.$nextTick(() => {
+        this.load();
+      })
+    },
+    watch: {
+			localdata: {
+				handler() {
+					this.load()
+				},
+        deep: true
+			},
+    },
+    methods: {
+      clear() {
+        this._dispatchEvent([]);
+      },
+      onPropsChange() {
+        this._treeData = [];
+        this.selectedIndex = 0;
+
+        this.load();
+      },
+      load() {
+        if (this.readonly) {
+          this._processReadonly(this.localdata, this.dataValue);
+          return;
+        }
+
+        // 回显本地数据
+        if (this.isLocalData) {
+          this.loadData();
+          this.inputSelected = this.selected.slice(0);
+        } else if (this.isCloudDataList || this.isCloudDataTree) { // 回显 Cloud 数据
+          this.loading = true;
+          this.getCloudDataValue().then((res) => {
+            this.loading = false;
+            this.inputSelected = res;
+          }).catch((err) => {
+            this.loading = false;
+            this.errorMessage = err;
+          })
+        }
+      },
+      show() {
+        this.isOpened = true
+        setTimeout(() => {
+          this.$refs.pickerView.updateData({
+            treeData: this._treeData,
+            selected: this.selected,
+            selectedIndex: this.selectedIndex
+          })
+        }, 200)
+        this.$emit('popupopened')
+      },
+      hide() {
+        this.isOpened = false
+        this.$emit('popupclosed')
+      },
+      handleInput() {
+        if (this.readonly) {
+					this.$emit('inputclick')
+          return
+        }
+        this.show()
+      },
+      handleClose(e) {
+        this.hide()
+      },
+      onnodeclick(e) {
+        this.$emit('nodeclick', e)
+      },
+      ondatachange(e) {
+        this._treeData = this.$refs.pickerView._treeData
+      },
+      onchange(e) {
+        this.hide()
+        this.$nextTick(() => {
+          this.inputSelected = e;
+        })
+        this._dispatchEvent(e)
+      },
+      _processReadonly(dataList, value) {
+        var isTree = dataList.findIndex((item) => {
+          return item.children
+        })
+        if (isTree > -1) {
+          let inputValue
+          if (Array.isArray(value)) {
+            inputValue = value[value.length - 1]
+            if (typeof inputValue === 'object' && inputValue.value) {
+              inputValue = inputValue.value
+            }
+          } else {
+            inputValue = value
+          }
+          this.inputSelected = this._findNodePath(inputValue, this.localdata)
+          return
+        }
+
+        if (!this.hasValue) {
+          this.inputSelected = []
+          return
+        }
+
+        let result = []
+        for (let i = 0; i < value.length; i++) {
+          var val = value[i]
+          var item = dataList.find((v) => {
+            return v.value == val
+          })
+          if (item) {
+            result.push(item)
+          }
+        }
+        if (result.length) {
+          this.inputSelected = result
+        }
+      },
+      _filterForArray(data, valueArray) {
+        var result = []
+        for (let i = 0; i < valueArray.length; i++) {
+          var value = valueArray[i]
+          var found = data.find((item) => {
+            return item.value == value
+          })
+          if (found) {
+            result.push(found)
+          }
+        }
+        return result
+      },
+      _dispatchEvent(selected) {
+        let item = {}
+        if (selected.length) {
+          var value = new Array(selected.length)
+          for (var i = 0; i < selected.length; i++) {
+            value[i] = selected[i].value
+          }
+          item = selected[selected.length - 1]
+        } else {
+          item.value = ''
+        }
+        if (this.formItem) {
+          this.formItem.setValue(item.value)
+        }
+
+        this.$emit('input', item.value)
+        this.$emit('update:modelValue', item.value)
+        this.$emit('change', {
+          detail: {
+            value: selected
+          }
+        })
+      }
+    }
+  }
+</script>
+
+<style>
+  .uni-data-tree {
+    flex: 1;
+    position: relative;
+    font-size: 14px;
+  }
+
+  .error-text {
+    color: #DD524D;
+  }
+
+  .input-value {
+    /* #ifndef APP-NVUE */
+    display: flex;
+    /* #endif */
+    flex-direction: row;
+    align-items: center;
+    flex-wrap: nowrap;
+    font-size: 14px;
+    /* line-height: 35px; */
+    padding: 0 10px;
+    padding-right: 5px;
+    overflow: hidden;
+    height: 35px;
+    /* #ifndef APP-NVUE */
+    box-sizing: border-box;
+    /* #endif */
+  }
+
+  .input-value-border {
+    border: 1px solid #e5e5e5;
+    border-radius: 5px;
+  }
+
+  .selected-area {
+    flex: 1;
+    overflow: hidden;
+    /* #ifndef APP-NVUE */
+    display: flex;
+    /* #endif */
+    flex-direction: row;
+  }
+
+  .load-more {
+    /* #ifndef APP-NVUE */
+    margin-right: auto;
+    /* #endif */
+    /* #ifdef APP-NVUE */
+    width: 40px;
+    /* #endif */
+  }
+
+  .selected-list {
+    /* #ifndef APP-NVUE */
+    display: flex;
+    /* #endif */
+    flex-direction: row;
+    flex-wrap: nowrap;
+    /* padding: 0 5px; */
+  }
+
+  .selected-item {
+    flex-direction: row;
+    /* padding: 0 1px; */
+    /* #ifndef APP-NVUE */
+    white-space: nowrap;
+    /* #endif */
+  }
+
+  .text-color {
+    color: #333;
+  }
+
+  .placeholder {
+    color: grey;
+    font-size: 12px;
+  }
+
+  .input-split-line {
+    opacity: .5;
+  }
+
+  .arrow-area {
+    position: relative;
+    width: 20px;
+    /* #ifndef APP-NVUE */
+    margin-bottom: 5px;
+    margin-left: auto;
+    display: flex;
+    /* #endif */
+    justify-content: center;
+    transform: rotate(-45deg);
+    transform-origin: center;
+  }
+
+  .input-arrow {
+    width: 7px;
+    height: 7px;
+    border-left: 1px solid #999;
+    border-bottom: 1px solid #999;
+  }
+
+  .uni-data-tree-cover {
+    position: fixed;
+    left: 0;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    background-color: rgba(0, 0, 0, .4);
+    /* #ifndef APP-NVUE */
+    display: flex;
+    /* #endif */
+    flex-direction: column;
+    z-index: 100;
+  }
+
+  .uni-data-tree-dialog {
+    position: fixed;
+    left: 0;
+    /* #ifndef APP-NVUE */
+    top: 20%;
+    /* #endif */
+    /* #ifdef APP-NVUE */
+    top: 200px;
+    /* #endif */
+    right: 0;
+    bottom: 0;
+    background-color: #FFFFFF;
+    border-top-left-radius: 10px;
+    border-top-right-radius: 10px;
+    /* #ifndef APP-NVUE */
+    display: flex;
+    /* #endif */
+    flex-direction: column;
+    z-index: 102;
+    overflow: hidden;
+    /* #ifdef APP-NVUE */
+    width: 750rpx;
+    /* #endif */
+  }
+
+  .dialog-caption {
+    position: relative;
+    /* #ifndef APP-NVUE */
+    display: flex;
+    /* #endif */
+    flex-direction: row;
+    /* border-bottom: 1px solid #f0f0f0; */
+  }
+
+  .title-area {
+    /* #ifndef APP-NVUE */
+    display: flex;
+    /* #endif */
+    align-items: center;
+    /* #ifndef APP-NVUE */
+    margin: auto;
+    /* #endif */
+    padding: 0 10px;
+  }
+
+  .dialog-title {
+    /* font-weight: bold; */
+    line-height: 44px;
+  }
+
+  .dialog-close {
+    position: absolute;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    /* #ifndef APP-NVUE */
+    display: flex;
+    /* #endif */
+    flex-direction: row;
+    align-items: center;
+    padding: 0 15px;
+  }
+
+  .dialog-close-plus {
+    width: 16px;
+    height: 2px;
+    background-color: #666;
+    border-radius: 2px;
+    transform: rotate(45deg);
+  }
+
+  .dialog-close-rotate {
+    position: absolute;
+    transform: rotate(-45deg);
+  }
+
+  .picker-view {
+    flex: 1;
+    overflow: hidden;
+  }
+
+  .icon-clear {
+    display: flex;
+    align-items: center;
+  }
+
+  /* #ifdef H5 */
+  @media all and (min-width: 768px) {
+    .uni-data-tree-cover {
+      background-color: transparent;
+    }
+
+    .uni-data-tree-dialog {
+      position: absolute;
+      top: 55px;
+      height: auto;
+      min-height: 400px;
+      max-height: 50vh;
+      background-color: #fff;
+      border: 1px solid #EBEEF5;
+      box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+      border-radius: 4px;
+      overflow: unset;
+    }
+
+    .dialog-caption {
+      display: none;
+    }
+
+    .icon-clear {
+      /* margin-right: 5px; */
+    }
+  }
+
+  /* #endif */
+
+  /* picker 弹出层通用的指示小三角, todo:扩展至上下左右方向定位 */
+  /* #ifndef APP-NVUE */
+  .uni-popper__arrow,
+  .uni-popper__arrow::after {
+    position: absolute;
+    display: block;
+    width: 0;
+    height: 0;
+    border-color: transparent;
+    border-style: solid;
+    border-width: 6px;
+  }
+
+  .uni-popper__arrow {
+    filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
+    top: -6px;
+    left: 10%;
+    margin-right: 3px;
+    border-top-width: 0;
+    border-bottom-color: #EBEEF5;
+  }
+
+  .uni-popper__arrow::after {
+    content: " ";
+    top: 1px;
+    margin-left: -6px;
+    border-top-width: 0;
+    border-bottom-color: #fff;
+  }
+
+  /* #endif */
+</style>

+ 622 - 0
actMgt/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js

@@ -0,0 +1,622 @@
+export default {
+  props: {
+    localdata: {
+      type: [Array, Object],
+      default () {
+        return []
+      }
+    },
+    spaceInfo: {
+      type: Object,
+      default () {
+        return {}
+      }
+    },
+    collection: {
+      type: String,
+      default: ''
+    },
+    action: {
+      type: String,
+      default: ''
+    },
+    field: {
+      type: String,
+      default: ''
+    },
+    orderby: {
+      type: String,
+      default: ''
+    },
+    where: {
+      type: [String, Object],
+      default: ''
+    },
+    pageData: {
+      type: String,
+      default: 'add'
+    },
+    pageCurrent: {
+      type: Number,
+      default: 1
+    },
+    pageSize: {
+      type: Number,
+      default: 500
+    },
+    getcount: {
+      type: [Boolean, String],
+      default: false
+    },
+    getone: {
+      type: [Boolean, String],
+      default: false
+    },
+    gettree: {
+      type: [Boolean, String],
+      default: false
+    },
+    manual: {
+      type: Boolean,
+      default: false
+    },
+    value: {
+      type: [Array, String, Number],
+      default () {
+        return []
+      }
+    },
+    modelValue: {
+      type: [Array, String, Number],
+      default () {
+        return []
+      }
+    },
+    preload: {
+      type: Boolean,
+      default: false
+    },
+    stepSearh: {
+      type: Boolean,
+      default: true
+    },
+    selfField: {
+      type: String,
+      default: ''
+    },
+    parentField: {
+      type: String,
+      default: ''
+    },
+    multiple: {
+      type: Boolean,
+      default: false
+    },
+    map: {
+      type: Object,
+      default () {
+        return {
+          text: "text",
+          value: "value"
+        }
+      }
+    }
+  },
+  data() {
+    return {
+      loading: false,
+      errorMessage: '',
+      loadMore: {
+        contentdown: '',
+        contentrefresh: '',
+        contentnomore: ''
+      },
+      dataList: [],
+      selected: [],
+      selectedIndex: 0,
+      page: {
+        current: this.pageCurrent,
+        size: this.pageSize,
+        count: 0
+      }
+    }
+  },
+  computed: {
+    isLocalData() {
+      return !this.collection.length;
+    },
+    isCloudData() {
+      return this.collection.length > 0;
+    },
+    isCloudDataList() {
+      return (this.isCloudData && (!this.parentField && !this.selfField));
+    },
+    isCloudDataTree() {
+      return (this.isCloudData && this.parentField && this.selfField);
+    },
+    dataValue() {
+      let isModelValue = Array.isArray(this.modelValue) ? (this.modelValue.length > 0) : (this.modelValue !== null ||
+        this.modelValue !== undefined);
+      return isModelValue ? this.modelValue : this.value;
+    },
+    hasValue() {
+      if (typeof this.dataValue === 'number') {
+        return true
+      }
+      return (this.dataValue != null) && (this.dataValue.length > 0)
+    }
+  },
+  created() {
+    this.$watch(() => {
+      var al = [];
+      ['pageCurrent',
+        'pageSize',
+        'spaceInfo',
+        'value',
+        'modelValue',
+        'localdata',
+        'collection',
+        'action',
+        'field',
+        'orderby',
+        'where',
+        'getont',
+        'getcount',
+        'gettree'
+      ].forEach(key => {
+        al.push(this[key])
+      });
+      return al
+    }, (newValue, oldValue) => {
+      let needReset = false
+      for (let i = 2; i < newValue.length; i++) {
+        if (newValue[i] != oldValue[i]) {
+          needReset = true
+          break
+        }
+      }
+      if (newValue[0] != oldValue[0]) {
+        this.page.current = this.pageCurrent
+      }
+      this.page.size = this.pageSize
+
+      this.onPropsChange()
+    })
+    this._treeData = []
+  },
+  methods: {
+    onPropsChange() {
+      this._treeData = [];
+    },
+
+    // 填充 pickview 数据
+    async loadData() {
+      if (this.isLocalData) {
+        this.loadLocalData();
+      } else if (this.isCloudDataList) {
+        this.loadCloudDataList();
+      } else if (this.isCloudDataTree) {
+        this.loadCloudDataTree();
+      }
+    },
+
+    // 加载本地数据
+    async loadLocalData() {
+      this._treeData = [];
+      this._extractTree(this.localdata, this._treeData);
+
+      let inputValue = this.dataValue;
+      if (inputValue === undefined) {
+        return;
+      }
+
+      if (Array.isArray(inputValue)) {
+        inputValue = inputValue[inputValue.length - 1];
+        if (typeof inputValue === 'object' && inputValue[this.map.value]) {
+          inputValue = inputValue[this.map.value];
+        }
+      }
+
+      this.selected = this._findNodePath(inputValue, this.localdata);
+    },
+
+    // 加载 Cloud 数据 (单列)
+    async loadCloudDataList() {
+      if (this.loading) {
+        return;
+      }
+      this.loading = true;
+
+      try {
+        let response = await this.getCommand();
+        let responseData = response.result.data;
+
+        this._treeData = responseData;
+
+        this._updateBindData();
+        this._updateSelected();
+
+        this.onDataChange();
+      } catch (e) {
+        this.errorMessage = e;
+      } finally {
+        this.loading = false;
+      }
+    },
+
+    // 加载 Cloud 数据 (树形)
+    async loadCloudDataTree() {
+      if (this.loading) {
+        return;
+      }
+      this.loading = true;
+
+      try {
+        let commandOptions = {
+          field: this._cloudDataPostField(),
+          where: this._cloudDataTreeWhere()
+        };
+        if (this.gettree) {
+          commandOptions.startwith = `${this.selfField}=='${this.dataValue}'`;
+        }
+
+        let response = await this.getCommand(commandOptions);
+        let responseData = response.result.data;
+
+        this._treeData = responseData;
+        this._updateBindData();
+        this._updateSelected();
+
+        this.onDataChange();
+      } catch (e) {
+        this.errorMessage = e;
+      } finally {
+        this.loading = false;
+      }
+    },
+
+    // 加载 Cloud 数据 (节点)
+    async loadCloudDataNode(callback) {
+      if (this.loading) {
+        return;
+      }
+      this.loading = true;
+
+      try {
+        let commandOptions = {
+          field: this._cloudDataPostField(),
+          where: this._cloudDataNodeWhere()
+        };
+
+        let response = await this.getCommand(commandOptions);
+        let responseData = response.result.data;
+
+        callback(responseData);
+      } catch (e) {
+        this.errorMessage = e;
+      } finally {
+        this.loading = false;
+      }
+    },
+
+    // 回显 Cloud 数据
+    getCloudDataValue() {
+      if (this.isCloudDataList) {
+        return this.getCloudDataListValue();
+      }
+
+      if (this.isCloudDataTree) {
+        return this.getCloudDataTreeValue();
+      }
+    },
+
+    // 回显 Cloud 数据 (单列)
+    getCloudDataListValue() {
+      // 根据 field's as value标识匹配 where 条件
+      let where = [];
+      let whereField = this._getForeignKeyByField();
+      if (whereField) {
+        where.push(`${whereField} == '${this.dataValue}'`)
+      }
+
+      where = where.join(' || ');
+
+      if (this.where) {
+        where = `(${this.where}) && (${where})`
+      }
+
+      return this.getCommand({
+        field: this._cloudDataPostField(),
+        where
+      }).then((res) => {
+        this.selected = res.result.data;
+        return res.result.data;
+      });
+    },
+
+    // 回显 Cloud 数据 (树形)
+    getCloudDataTreeValue() {
+      return this.getCommand({
+        field: this._cloudDataPostField(),
+        getTreePath: {
+          startWith: `${this.selfField}=='${this.dataValue}'`
+        }
+      }).then((res) => {
+        let treePath = [];
+        this._extractTreePath(res.result.data, treePath);
+        this.selected = treePath;
+        return treePath;
+      });
+    },
+
+    getCommand(options = {}) {
+      /* eslint-disable no-undef */
+      let db = uniCloud.database(this.spaceInfo)
+
+      const action = options.action || this.action
+      if (action) {
+        db = db.action(action)
+      }
+
+      const collection = options.collection || this.collection
+      db = db.collection(collection)
+
+      const where = options.where || this.where
+      if (!(!where || !Object.keys(where).length)) {
+        db = db.where(where)
+      }
+
+      const field = options.field || this.field
+      if (field) {
+        db = db.field(field)
+      }
+
+      const orderby = options.orderby || this.orderby
+      if (orderby) {
+        db = db.orderBy(orderby)
+      }
+
+      const current = options.pageCurrent !== undefined ? options.pageCurrent : this.page.current
+      const size = options.pageSize !== undefined ? options.pageSize : this.page.size
+      const getCount = options.getcount !== undefined ? options.getcount : this.getcount
+      const getTree = options.gettree !== undefined ? options.gettree : this.gettree
+
+      const getOptions = {
+        getCount,
+        getTree
+      }
+      if (options.getTreePath) {
+        getOptions.getTreePath = options.getTreePath
+      }
+
+      db = db.skip(size * (current - 1)).limit(size).get(getOptions)
+
+      return db
+    },
+
+    _cloudDataPostField() {
+      let fields = [this.field];
+      if (this.parentField) {
+        fields.push(`${this.parentField} as parent_value`);
+      }
+      return fields.join(',');
+    },
+
+    _cloudDataTreeWhere() {
+      let result = []
+      let selected = this.selected
+      let parentField = this.parentField
+      if (parentField) {
+        result.push(`${parentField} == null || ${parentField} == ""`)
+      }
+      if (selected.length) {
+        for (var i = 0; i < selected.length - 1; i++) {
+          result.push(`${parentField} == '${selected[i].value}'`)
+        }
+      }
+
+      let where = []
+      if (this.where) {
+        where.push(`(${this.where})`)
+      }
+
+      if (result.length) {
+        where.push(`(${result.join(' || ')})`)
+      }
+
+      return where.join(' && ')
+    },
+
+    _cloudDataNodeWhere() {
+      let where = []
+      let selected = this.selected;
+      if (selected.length) {
+        where.push(`${this.parentField} == '${selected[selected.length - 1].value}'`);
+      }
+
+      where = where.join(' || ');
+
+      if (this.where) {
+        return `(${this.where}) && (${where})`
+      }
+
+      return where
+    },
+
+    _getWhereByForeignKey() {
+      let result = []
+      let whereField = this._getForeignKeyByField();
+      if (whereField) {
+        result.push(`${whereField} == '${this.dataValue}'`)
+      }
+
+      if (this.where) {
+        return `(${this.where}) && (${result.join(' || ')})`
+      }
+
+      return result.join(' || ')
+    },
+
+    _getForeignKeyByField() {
+      let fields = this.field.split(',');
+      let whereField = null;
+      for (let i = 0; i < fields.length; i++) {
+        const items = fields[i].split('as');
+        if (items.length < 2) {
+          continue;
+        }
+        if (items[1].trim() === 'value') {
+          whereField = items[0].trim();
+          break;
+        }
+      }
+      return whereField;
+    },
+
+    _updateBindData(node) {
+      const {
+        dataList,
+        hasNodes
+      } = this._filterData(this._treeData, this.selected)
+
+      let isleaf = this._stepSearh === false && !hasNodes
+
+      if (node) {
+        node.isleaf = isleaf
+      }
+
+      this.dataList = dataList
+      this.selectedIndex = dataList.length - 1
+
+      if (!isleaf && this.selected.length < dataList.length) {
+        this.selected.push({
+          value: null,
+          text: "请选择"
+        })
+      }
+
+      return {
+        isleaf,
+        hasNodes
+      }
+    },
+
+    _updateSelected() {
+      let dl = this.dataList
+      let sl = this.selected
+      let textField = this.map.text
+      let valueField = this.map.value
+      for (let i = 0; i < sl.length; i++) {
+        let value = sl[i].value
+        let dl2 = dl[i]
+        for (let j = 0; j < dl2.length; j++) {
+          let item2 = dl2[j]
+          if (item2[valueField] === value) {
+            sl[i].text = item2[textField]
+            break
+          }
+        }
+      }
+    },
+
+    _filterData(data, paths) {
+      let dataList = []
+      let hasNodes = true
+
+      dataList.push(data.filter((item) => {
+        return (item.parent_value === null || item.parent_value === undefined || item.parent_value === '')
+      }))
+      for (let i = 0; i < paths.length; i++) {
+        let value = paths[i].value
+        let nodes = data.filter((item) => {
+          return item.parent_value === value
+        })
+
+        if (nodes.length) {
+          dataList.push(nodes)
+        } else {
+          hasNodes = false
+        }
+      }
+
+      return {
+        dataList,
+        hasNodes
+      }
+    },
+
+    _extractTree(nodes, result, parent_value) {
+      let list = result || []
+      let valueField = this.map.value
+      for (let i = 0; i < nodes.length; i++) {
+        let node = nodes[i]
+
+        let child = {}
+        for (let key in node) {
+          if (key !== 'children') {
+            child[key] = node[key]
+          }
+        }
+        if (parent_value !== null && parent_value !== undefined && parent_value !== '') {
+          child.parent_value = parent_value
+        }
+        result.push(child)
+
+        let children = node.children
+        if (children) {
+          this._extractTree(children, result, node[valueField])
+        }
+      }
+    },
+
+    _extractTreePath(nodes, result) {
+      let list = result || []
+      for (let i = 0; i < nodes.length; i++) {
+        let node = nodes[i]
+
+        let child = {}
+        for (let key in node) {
+          if (key !== 'children') {
+            child[key] = node[key]
+          }
+        }
+        result.push(child)
+
+        let children = node.children
+        if (children) {
+          this._extractTreePath(children, result)
+        }
+      }
+    },
+
+    _findNodePath(key, nodes, path = []) {
+      let textField = this.map.text
+      let valueField = this.map.value
+      for (let i = 0; i < nodes.length; i++) {
+        let node = nodes[i]
+        let children = node.children
+        let text = node[textField]
+        let value = node[valueField]
+
+        path.push({
+          value,
+          text
+        })
+
+        if (value === key) {
+          return path
+        }
+
+        if (children) {
+          const p = this._findNodePath(key, children, path)
+          if (p.length) {
+            return p
+          }
+        }
+
+        path.pop()
+      }
+      return []
+    }
+  }
+}

+ 692 - 0
actMgt/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.uts

@@ -0,0 +1,692 @@
+export type PaginationType = {
+  current : number,
+  size : number,
+  count : number
+}
+
+export type LoadMoreType = {
+  contentdown : string,
+  contentrefresh : string,
+  contentnomore : string
+}
+
+export type SelectedItemType = {
+  name : string,
+  value : string,
+}
+
+export type GetCommandOptions = {
+  collection ?: UTSJSONObject,
+  field ?: string,
+  orderby ?: string,
+  where ?: any,
+  pageData ?: string,
+  pageCurrent ?: number,
+  pageSize ?: number,
+  getCount ?: boolean,
+  getTree ?: any,
+  getTreePath ?: UTSJSONObject,
+  startwith ?: string,
+  limitlevel ?: number,
+  groupby ?: string,
+  groupField ?: string,
+  distinct ?: boolean,
+  pageIndistinct ?: boolean,
+  foreignKey ?: string,
+  loadtime ?: string,
+  manual ?: boolean
+}
+
+const DefaultSelectedNode = {
+  text: '请选择',
+  value: ''
+}
+
+export const dataPicker = defineMixin({
+  props: {
+    localdata: {
+      type: Array as PropType<Array<UTSJSONObject>>,
+      default: [] as Array<UTSJSONObject>
+    },
+    collection: {
+      type: Object,
+      default: ''
+    },
+    field: {
+      type: String,
+      default: ''
+    },
+    orderby: {
+      type: String,
+      default: ''
+    },
+    where: {
+      type: Object,
+      default: ''
+    },
+    pageData: {
+      type: String,
+      default: 'add'
+    },
+    pageCurrent: {
+      type: Number,
+      default: 1
+    },
+    pageSize: {
+      type: Number,
+      default: 20
+    },
+    getcount: {
+      type: Boolean,
+      default: false
+    },
+    gettree: {
+      type: Object,
+      default: ''
+    },
+    gettreepath: {
+      type: Object,
+      default: ''
+    },
+    startwith: {
+      type: String,
+      default: ''
+    },
+    limitlevel: {
+      type: Number,
+      default: 10
+    },
+    groupby: {
+      type: String,
+      default: ''
+    },
+    groupField: {
+      type: String,
+      default: ''
+    },
+    distinct: {
+      type: Boolean,
+      default: false
+    },
+    pageIndistinct: {
+      type: Boolean,
+      default: false
+    },
+    foreignKey: {
+      type: String,
+      default: ''
+    },
+    loadtime: {
+      type: String,
+      default: 'auto'
+    },
+    manual: {
+      type: Boolean,
+      default: false
+    },
+    preload: {
+      type: Boolean,
+      default: false
+    },
+    stepSearh: {
+      type: Boolean,
+      default: true
+    },
+    selfField: {
+      type: String,
+      default: ''
+    },
+    parentField: {
+      type: String,
+      default: ''
+    },
+    multiple: {
+      type: Boolean,
+      default: false
+    },
+    value: {
+      type: Object,
+      default: ''
+    },
+    modelValue: {
+      type: Object,
+      default: ''
+    },
+    defaultProps: {
+      type: Object as PropType<UTSJSONObject>,
+    }
+  },
+  data() {
+    return {
+      loading: false,
+      error: null as UniCloudError | null,
+      treeData: [] as Array<UTSJSONObject>,
+      selectedIndex: 0,
+      selectedNodes: [] as Array<UTSJSONObject>,
+      selectedPages: [] as Array<UTSJSONObject>[],
+      selectedValue: '',
+      selectedPaths: [] as Array<UTSJSONObject>,
+      pagination: {
+        current: 1,
+        size: 20,
+        count: 0
+      } as PaginationType
+    }
+  },
+  computed: {
+    mappingTextName() : string {
+      // TODO
+      return (this.defaultProps != null) ? this.defaultProps!.getString('text', 'text') : 'text'
+    },
+    mappingValueName() : string {
+      // TODO
+      return (this.defaultProps != null) ? this.defaultProps!.getString('value', 'value') : 'value'
+    },
+    currentDataList() : Array<UTSJSONObject> {
+      if (this.selectedIndex > this.selectedPages.length - 1) {
+        return [] as Array<UTSJSONObject>
+      }
+      return this.selectedPages[this.selectedIndex]
+    },
+    isLocalData() : boolean {
+      return this.localdata.length > 0
+    },
+    isCloudData() : boolean {
+      return this._checkIsNotNull(this.collection)
+    },
+    isCloudDataList() : boolean {
+      return (this.isCloudData && (this.parentField.length == 0 && this.selfField.length == 0))
+    },
+    isCloudDataTree() : boolean {
+      return (this.isCloudData && this.parentField.length > 0 && this.selfField.length > 0)
+    },
+    dataValue() : any {
+      return this.hasModelValue ? this.modelValue : this.value
+    },
+    hasCloudTreeData() : boolean {
+      return this.treeData.length > 0
+    },
+    hasModelValue() : boolean {
+      if (typeof this.modelValue == 'string') {
+        const valueString = this.modelValue as string
+        return (valueString.length > 0)
+      } else if (Array.isArray(this.modelValue)) {
+        const valueArray = this.modelValue as Array<string>
+        return (valueArray.length > 0)
+      }
+      return false
+    },
+    hasCloudDataValue() : boolean {
+      if (typeof this.dataValue == 'string') {
+        const valueString = this.dataValue as string
+        return (valueString.length > 0)
+      }
+      return false
+    }
+  },
+  created() {
+    this.pagination.current = this.pageCurrent
+    this.pagination.size = this.pageSize
+
+    this.$watch(
+      () : any => [
+        this.pageCurrent,
+        this.pageSize,
+        this.localdata,
+        this.value,
+        this.collection,
+        this.field,
+        this.getcount,
+        this.orderby,
+        this.where,
+        this.groupby,
+        this.groupField,
+        this.distinct
+      ],
+      (newValue : Array<any>, oldValue : Array<any>) => {
+        this.pagination.size = this.pageSize
+        if (newValue[0] !== oldValue[0]) {
+          this.pagination.current = this.pageCurrent
+        }
+
+        this.onPropsChange()
+      }
+    )
+  },
+  methods: {
+    onPropsChange() {
+      this.selectedIndex = 0
+      this.selectedNodes.length = 0
+      this.selectedPages.length = 0
+      this.selectedPaths.length = 0
+
+      // 加载数据
+      this.$nextTick(() => {
+        this.loadData()
+      })
+    },
+
+    onTabSelect(index : number) {
+      this.selectedIndex = index
+    },
+
+    onNodeClick(nodeData : UTSJSONObject) {
+      if (nodeData.getBoolean('disable', false)) {
+        return
+      }
+
+      const isLeaf = this._checkIsLeafNode(nodeData)
+
+      this._trimSelectedNodes(nodeData)
+
+      this.$emit('nodeclick', nodeData)
+
+      if (this.isLocalData) {
+        if (isLeaf || !this._checkHasChildren(nodeData)) {
+          this.onFinish()
+        }
+      } else if (this.isCloudDataList) {
+        this.onFinish()
+      } else if (this.isCloudDataTree) {
+        if (isLeaf) {
+          this.onFinish()
+        } else if (!this._checkHasChildren(nodeData)) {
+          // 尝试请求一次,如果没有返回数据标记为叶子节点
+          this.loadCloudDataNode(nodeData)
+        }
+      }
+    },
+
+    getChangeNodes(): Array<UTSJSONObject> {
+      const nodes: Array<UTSJSONObject> = []
+      this.selectedNodes.forEach((node : UTSJSONObject) => {
+        const newNode: UTSJSONObject = {}
+        newNode[this.mappingTextName] = node.getString(this.mappingTextName)
+        newNode[this.mappingValueName] = node.getString(this.mappingValueName)
+        nodes.push(newNode)
+      })
+      return nodes
+    },
+
+    onFinish() { },
+
+    // 加载数据(自动判定环境)
+    loadData() {
+      if (this.isLocalData) {
+        this.loadLocalData()
+      } else if (this.isCloudDataList) {
+        this.loadCloudDataList()
+      } else if (this.isCloudDataTree) {
+        this.loadCloudDataTree()
+      }
+    },
+
+    // 加载本地数据
+    loadLocalData() {
+      this.treeData = this.localdata
+      if (Array.isArray(this.dataValue)) {
+        const value = this.dataValue as Array<UTSJSONObject>
+        this.selectedPaths = value.slice(0)
+        this._pushSelectedTreeNodes(value, this.localdata)
+      } else {
+        this._pushSelectedNodes(this.localdata)
+      }
+    },
+
+    // 加载 Cloud 数据 (单列)
+    loadCloudDataList() {
+      this._loadCloudData(null, (data : Array<UTSJSONObject>) => {
+        this.treeData = data
+        this._pushSelectedNodes(data)
+      })
+    },
+
+    // 加载 Cloud 数据 (树形)
+    loadCloudDataTree() {
+      let commandOptions = {
+        field: this._cloudDataPostField(),
+        where: this._cloudDataTreeWhere(),
+        getTree: true
+      } as GetCommandOptions
+      if (this._checkIsNotNull(this.gettree)) {
+        commandOptions.startwith = `${this.selfField}=='${this.dataValue as string}'`
+      }
+      this._loadCloudData(commandOptions, (data : Array<UTSJSONObject>) => {
+        this.treeData = data
+        if (this.selectedPaths.length > 0) {
+          this._pushSelectedTreeNodes(this.selectedPaths, data)
+        } else {
+          this._pushSelectedNodes(data)
+        }
+      })
+    },
+
+    // 加载 Cloud 数据 (节点)
+    loadCloudDataNode(nodeData : UTSJSONObject) {
+      const commandOptions = {
+        field: this._cloudDataPostField(),
+        where: this._cloudDataNodeWhere()
+      } as GetCommandOptions
+      this._loadCloudData(commandOptions, (data : Array<UTSJSONObject>) => {
+        nodeData['children'] = data
+        if (data.length == 0) {
+          nodeData['isleaf'] = true
+          this.onFinish()
+        } else {
+          this._pushSelectedNodes(data)
+        }
+      })
+    },
+
+    // 回显 Cloud Tree Path
+    loadCloudDataPath() {
+      if (!this.hasCloudDataValue) {
+        return
+      }
+
+      const command : GetCommandOptions = {}
+
+      // 单列
+      if (this.isCloudDataList) {
+        // 根据 field's as value标识匹配 where 条件
+        let where : Array<string> = [];
+        let whereField = this._getForeignKeyByField();
+        if (whereField.length > 0) {
+          where.push(`${whereField} == '${this.dataValue as string}'`)
+        }
+
+        let whereString = where.join(' || ')
+        if (this._checkIsNotNull(this.where)) {
+          whereString = `(${this.where}) && (${whereString})`
+        }
+
+        command.field = this._cloudDataPostField()
+        command.where = whereString
+      }
+
+      // 树形
+      if (this.isCloudDataTree) {
+        command.field = this._cloudDataPostField()
+        command.getTreePath = {
+          startWith: `${this.selfField}=='${this.dataValue as string}'`
+        }
+      }
+
+      this._loadCloudData(command, (data : Array<UTSJSONObject>) => {
+        this._extractTreePath(data, this.selectedPaths)
+      })
+    },
+
+    _loadCloudData(options ?: GetCommandOptions, callback ?: ((data : Array<UTSJSONObject>) => void)) {
+      if (this.loading) {
+        return
+      }
+      this.loading = true
+
+      this.error = null
+
+      this._getCommand(options).then((response : UniCloudDBGetResult) => {
+        callback?.(response.data)
+      }).catch((err : any | null) => {
+        this.error = err as UniCloudError
+      }).finally(() => {
+        this.loading = false
+      })
+    },
+
+    _cloudDataPostField() : string {
+      let fields = [this.field];
+      if (this.parentField.length > 0) {
+        fields.push(`${this.parentField} as parent_value`)
+      }
+      return fields.join(',')
+    },
+
+    _cloudDataTreeWhere() : string {
+      let result : Array<string> = []
+      let selectedNodes = this.selectedNodes.length > 0 ? this.selectedNodes : this.selectedPaths
+      let parentField = this.parentField
+      if (parentField.length > 0) {
+        result.push(`${parentField} == null || ${parentField} == ""`)
+      }
+      if (selectedNodes.length > 0) {
+        for (var i = 0; i < selectedNodes.length - 1; i++) {
+          const parentFieldValue = selectedNodes[i].getString('value', '')
+          result.push(`${parentField} == '${parentFieldValue}'`)
+        }
+      }
+
+      let where : Array<string> = []
+      if (this._checkIsNotNull(this.where)) {
+        where.push(`(${this.where as string})`)
+      }
+
+      if (result.length > 0) {
+        where.push(`(${result.join(' || ')})`)
+      }
+
+      return where.join(' && ')
+    },
+
+    _cloudDataNodeWhere() : string {
+      const where : Array<string> = []
+      if (this.selectedNodes.length > 0) {
+        const value = this.selectedNodes[this.selectedNodes.length - 1].getString('value', '')
+        where.push(`${this.parentField} == '${value}'`)
+      }
+
+      let whereString = where.join(' || ')
+      if (this._checkIsNotNull(this.where)) {
+        return `(${this.where as string}) && (${whereString})`
+      }
+
+      return whereString
+    },
+
+    _getWhereByForeignKey() : string {
+      let result : Array<string> = []
+      let whereField = this._getForeignKeyByField();
+      if (whereField.length > 0) {
+        result.push(`${whereField} == '${this.dataValue as string}'`)
+      }
+
+      if (this._checkIsNotNull(this.where)) {
+        return `(${this.where}) && (${result.join(' || ')})`
+      }
+
+      return result.join(' || ')
+    },
+
+    _getForeignKeyByField() : string {
+      const fields = this.field.split(',')
+      let whereField = ''
+      for (let i = 0; i < fields.length; i++) {
+        const items = fields[i].split('as')
+        if (items.length < 2) {
+          continue
+        }
+        if (items[1].trim() === 'value') {
+          whereField = items[0].trim()
+          break
+        }
+      }
+      return whereField
+    },
+
+    _getCommand(options ?: GetCommandOptions) : Promise<UniCloudDBGetResult> {
+      let db = uniCloud.databaseForJQL()
+
+      let collection = Array.isArray(this.collection) ? db.collection(...(this.collection as Array<any>)) : db.collection(this.collection)
+
+      let filter : UniCloudDBFilter | null = null
+      if (this.foreignKey.length > 0) {
+        filter = collection.foreignKey(this.foreignKey)
+      }
+
+      const where : any = options?.where ?? this.where
+      if (typeof where == 'string') {
+        const whereString = where as string
+        if (whereString.length > 0) {
+          filter = (filter != null) ? filter.where(where) : collection.where(where)
+        }
+      } else {
+        filter = (filter != null) ? filter.where(where) : collection.where(where)
+      }
+
+      let query : UniCloudDBQuery | null = null
+      if (this.field.length > 0) {
+        query = (filter != null) ? filter.field(this.field) : collection.field(this.field)
+      }
+      if (this.groupby.length > 0) {
+        if (query != null) {
+          query = query.groupBy(this.groupby)
+        } else if (filter != null) {
+          query = filter.groupBy(this.groupby)
+        }
+      }
+      if (this.groupField.length > 0) {
+        if (query != null) {
+          query = query.groupField(this.groupField)
+        } else if (filter != null) {
+          query = filter.groupField(this.groupField)
+        }
+      }
+      if (this.distinct == true) {
+        if (query != null) {
+          query = query.distinct(this.field)
+        } else if (filter != null) {
+          query = filter.distinct(this.field)
+        }
+      }
+      if (this.orderby.length > 0) {
+        if (query != null) {
+          query = query.orderBy(this.orderby)
+        } else if (filter != null) {
+          query = filter.orderBy(this.orderby)
+        }
+      }
+
+      const size = this.pagination.size
+      const current = this.pagination.current
+      if (query != null) {
+        query = query.skip(size * (current - 1)).limit(size)
+      } else if (filter != null) {
+        query = filter.skip(size * (current - 1)).limit(size)
+      } else {
+        query = collection.skip(size * (current - 1)).limit(size)
+      }
+
+      const getOptions = {}
+      const treeOptions = {
+        limitLevel: this.limitlevel,
+        startWith: this.startwith
+      }
+      if (this.getcount == true) {
+        getOptions['getCount'] = this.getcount
+      }
+
+      const getTree : any = options?.getTree ?? this.gettree
+      if (typeof getTree == 'string') {
+        const getTreeString = getTree as string
+        if (getTreeString.length > 0) {
+          getOptions['getTree'] = treeOptions
+        }
+      } else if (typeof getTree == 'object') {
+        getOptions['getTree'] = treeOptions
+      } else {
+        getOptions['getTree'] = getTree
+      }
+
+      const getTreePath = options?.getTreePath ?? this.gettreepath
+      if (typeof getTreePath == 'string') {
+        const getTreePathString = getTreePath as string
+        if (getTreePathString.length > 0) {
+          getOptions['getTreePath'] = getTreePath
+        }
+      } else {
+        getOptions['getTreePath'] = getTreePath
+      }
+
+      return query.get(getOptions)
+    },
+
+    _checkIsNotNull(value : any) : boolean {
+      if (typeof value == 'string') {
+        const valueString = value as string
+        return (valueString.length > 0)
+      } else if (value instanceof UTSJSONObject) {
+        return true
+      }
+      return false
+    },
+
+    _checkIsLeafNode(nodeData : UTSJSONObject) : boolean {
+      if (this.selectedIndex >= this.limitlevel) {
+        return true
+      }
+
+      if (nodeData.getBoolean('isleaf', false)) {
+        return true
+      }
+
+      return false
+    },
+
+    _checkHasChildren(nodeData : UTSJSONObject) : boolean {
+      const children = nodeData.getArray('children') ?? ([] as Array<any>)
+      return children.length > 0
+    },
+
+    _pushSelectedNodes(nodes : Array<UTSJSONObject>) {
+      this.selectedNodes.push(DefaultSelectedNode)
+      this.selectedPages.push(nodes)
+      this.selectedIndex = this.selectedPages.length - 1
+    },
+
+    _trimSelectedNodes(nodeData : UTSJSONObject) {
+      this.selectedNodes.splice(this.selectedIndex)
+      this.selectedNodes.push(nodeData)
+
+      if (this.selectedPages.length > 0) {
+        this.selectedPages.splice(this.selectedIndex + 1)
+      }
+
+      const children = nodeData.getArray<UTSJSONObject>('children') ?? ([] as Array<UTSJSONObject>)
+      if (children.length > 0) {
+        this.selectedNodes.push(DefaultSelectedNode)
+        this.selectedPages.push(children)
+      }
+
+      this.selectedIndex = this.selectedPages.length - 1
+    },
+
+    _pushSelectedTreeNodes(paths : Array<UTSJSONObject>, nodes : Array<UTSJSONObject>) {
+      let children : Array<UTSJSONObject> = nodes
+      paths.forEach((node : UTSJSONObject) => {
+        const findNode = children.find((item : UTSJSONObject) : boolean => {
+          return (item.getString(this.mappingValueName) == node.getString(this.mappingValueName))
+        })
+        if (findNode != null) {
+          this.selectedPages.push(children)
+          this.selectedNodes.push(node)
+          children = findNode.getArray<UTSJSONObject>('children') ?? ([] as Array<UTSJSONObject>)
+        }
+      })
+      this.selectedIndex = this.selectedPages.length - 1
+    },
+
+    _extractTreePath(nodes : Array<UTSJSONObject>, result : Array<UTSJSONObject>) {
+      if (nodes.length == 0) {
+        return
+      }
+
+      const node = nodes[0]
+      result.push(node)
+
+      const children = node.getArray<UTSJSONObject>('children')
+      if (Array.isArray(children) && children!.length > 0) {
+        this._extractTreePath(children, result)
+      }
+    }
+  }
+})

+ 76 - 0
actMgt/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.css

@@ -0,0 +1,76 @@
+.uni-data-pickerview {
+  position: relative;
+  flex-direction: column;
+  overflow: hidden;
+}
+
+.loading-cover {
+  position: absolute;
+  left: 0;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  align-items: center;
+  justify-content: center;
+  background-color: rgba(150, 150, 150, .1);
+}
+
+.error {
+  background-color: #fff;
+  padding: 15px;
+}
+
+.error-text {
+  color: #DD524D;
+}
+
+.selected-node-list {
+  flex-direction: row;
+  flex-wrap: nowrap;
+}
+
+.selected-node-item {
+  margin-left: 10px;
+  margin-right: 10px;
+  padding: 8px 10px 8px 10px;
+  border-bottom: 2px solid transparent;
+}
+
+.selected-node-item-active {
+  color: #007aff;
+  border-bottom-color: #007aff;
+}
+
+.list-view {
+  flex: 1;
+}
+
+.list-item {
+  flex-direction: row;
+  justify-content: space-between;
+  padding: 12px 15px;
+  border-bottom: 1px solid #f0f0f0;
+}
+
+.item-text {
+  color: #333333;
+}
+
+.item-text-disabled {
+  opacity: .5;
+}
+
+.item-text-overflow {
+  overflow: hidden;
+}
+
+.check {
+  margin-right: 5px;
+  border: 2px solid #007aff;
+  border-left: 0;
+  border-top: 0;
+  height: 12px;
+  width: 6px;
+  transform-origin: center;
+  transform: rotate(45deg);
+}

+ 69 - 0
actMgt/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.uvue

@@ -0,0 +1,69 @@
+<template>
+  <view class="uni-data-pickerview">
+    <view v-if="error!=null" class="error">
+      <text class="error-text">{{error!.errMsg}}</text>
+    </view>
+    <scroll-view v-if="!isCloudDataList" :scroll-x="true">
+      <view class="selected-node-list">
+        <template v-for="(item, index) in selectedNodes">
+          <text class="selected-node-item" :class="{'selected-node-item-active':index==selectedIndex}"
+            @click="onTabSelect(index)">
+            {{item[mappingTextName]}}
+          </text>
+        </template>
+      </view>
+    </scroll-view>
+    <list-view class="list-view" :scroll-y="true">
+      <list-item class="list-item" v-for="(item, _) in currentDataList" @click="onNodeClick(item)">
+        <text class="item-text" :class="{'item-text-disabled': item['disable']}">{{item[mappingTextName]}}</text>
+        <text class="check" v-if="item[mappingValueName] == selectedNodes[selectedIndex][mappingValueName]"></text>
+      </list-item>
+    </list-view>
+    <view class="loading-cover" v-if="loading">
+      <slot name="pickerview-loading" :loading="loading"></slot>
+    </view>
+  </view>
+</template>
+
+<script>
+  import { dataPicker } from "./uni-data-picker.uts"
+
+  /**
+   * DataPickerview
+   * @description uni-data-pickerview
+   * @tutorial https://ext.dcloud.net.cn/plugin?id=3796
+   * @property {Array} localdata 本地数据,参考
+   * @property {Boolean} step-searh = [true|false] 是否分布查询
+   * @value true 启用分布查询,仅查询当前选中节点
+   * @value false 关闭分布查询,一次查询出所有数据
+   * @property {String|DBFieldString} self-field 分布查询当前字段名称
+   * @property {String|DBFieldString} parent-field 分布查询父字段名称
+   * @property {String|DBCollectionString} collection 表名
+   * @property {String|DBFieldString} field 查询字段,多个字段用 `,` 分割
+   * @property {String} orderby 排序字段及正序倒叙设置
+   * @property {String|JQLString} where 查询条件
+   */
+  export default {
+    name: 'UniDataPickerView',
+    emits: ['nodeclick', 'change', 'update:modelValue'],
+    mixins: [dataPicker],
+    props: {
+      ellipsis: {
+        type: Boolean,
+        default: true
+      }
+    },
+    created() {
+      this.loadData()
+    },
+    methods: {
+      onFinish() {
+        this.$emit('change', this.getChangeNodes())
+      }
+    }
+  }
+</script>
+
+<style>
+  @import url("uni-data-pickerview.css");
+</style>

+ 323 - 0
actMgt/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue

@@ -0,0 +1,323 @@
+<template>
+  <view class="uni-data-pickerview">
+    <scroll-view v-if="!isCloudDataList" class="selected-area" scroll-x="true">
+      <view class="selected-list">
+          <view 
+            class="selected-item"
+            v-for="(item,index) in selected"
+            :key="index"
+            :class="{
+              'selected-item-active':index == selectedIndex
+            }"
+            @click="handleSelect(index)"
+          >
+            <text>{{item.text || ''}}</text>
+          </view>
+      </view>
+    </scroll-view>
+    <view class="tab-c">
+      <scroll-view class="list" :scroll-y="true">
+        <view class="item" :class="{'is-disabled': !!item.disable}" v-for="(item, j) in dataList[selectedIndex]" :key="j"
+          @click="handleNodeClick(item, selectedIndex, j)">
+          <text class="item-text">{{item[map.text]}}</text>
+          <view class="check" v-if="selected.length > selectedIndex && item[map.value] == selected[selectedIndex].value"></view>
+        </view>
+      </scroll-view>
+
+      <view class="loading-cover" v-if="loading">
+        <uni-load-more class="load-more" :contentText="loadMore" status="loading"></uni-load-more>
+      </view>
+      <view class="error-message" v-if="errorMessage">
+        <text class="error-text">{{errorMessage}}</text>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+  import dataPicker from "./uni-data-picker.js"
+
+  /**
+   * DataPickerview
+   * @description uni-data-pickerview
+   * @tutorial https://ext.dcloud.net.cn/plugin?id=3796
+   * @property {Array} localdata 本地数据,参考
+   * @property {Boolean} step-searh = [true|false] 是否分布查询
+   * @value true 启用分布查询,仅查询当前选中节点
+   * @value false 关闭分布查询,一次查询出所有数据
+   * @property {String|DBFieldString} self-field 分布查询当前字段名称
+   * @property {String|DBFieldString} parent-field 分布查询父字段名称
+   * @property {String|DBCollectionString} collection 表名
+   * @property {String|DBFieldString} field 查询字段,多个字段用 `,` 分割
+   * @property {String} orderby 排序字段及正序倒叙设置
+   * @property {String|JQLString} where 查询条件
+   */
+  export default {
+    name: 'UniDataPickerView',
+    emits: ['nodeclick', 'change', 'datachange', 'update:modelValue'],
+    mixins: [dataPicker],
+    props: {
+      managedMode: {
+        type: Boolean,
+        default: false
+      },
+      ellipsis: {
+        type: Boolean,
+        default: true
+      }
+    },
+    created() {
+      if (!this.managedMode) {
+        this.$nextTick(() => {
+          this.loadData();
+        })
+      }
+    },
+    methods: {
+      onPropsChange() {
+        this._treeData = [];
+        this.selectedIndex = 0;
+        this.$nextTick(() => {
+          this.loadData();
+        })
+      },
+      handleSelect(index) {
+        this.selectedIndex = index;
+      },
+      handleNodeClick(item, i, j) {
+        if (item.disable) {
+          return;
+        }
+
+        const node = this.dataList[i][j];
+        const text = node[this.map.text];
+        const value = node[this.map.value];
+
+        if (i < this.selected.length - 1) {
+          this.selected.splice(i, this.selected.length - i)
+          this.selected.push({
+            text,
+            value
+          })
+        } else if (i === this.selected.length - 1) {
+          this.selected.splice(i, 1, {
+            text,
+            value
+          })
+        }
+
+        if (node.isleaf) {
+          this.onSelectedChange(node, node.isleaf)
+          return
+        }
+
+        const {
+          isleaf,
+          hasNodes
+        } = this._updateBindData()
+
+        // 本地数据
+        if (this.isLocalData) {
+          this.onSelectedChange(node, (!hasNodes || isleaf))
+        } else if (this.isCloudDataList) { // Cloud 数据 (单列)
+          this.onSelectedChange(node, true)
+        } else if (this.isCloudDataTree) { // Cloud 数据 (树形)
+          if (isleaf) {
+            this.onSelectedChange(node, node.isleaf)
+          } else if (!hasNodes) { // 请求一次服务器以确定是否为叶子节点
+            this.loadCloudDataNode((data) => {
+              if (!data.length) {
+                node.isleaf = true
+              } else {
+                this._treeData.push(...data)
+                this._updateBindData(node)
+              }
+              this.onSelectedChange(node, node.isleaf)
+            })
+          }
+        }
+      },
+      updateData(data) {
+        this._treeData = data.treeData
+        this.selected = data.selected
+        if (!this._treeData.length) {
+          this.loadData()
+        } else {
+          //this.selected = data.selected
+          this._updateBindData()
+        }
+      },
+      onDataChange() {
+        this.$emit('datachange');
+      },
+      onSelectedChange(node, isleaf) {
+        if (isleaf) {
+          this._dispatchEvent()
+        }
+
+        if (node) {
+          this.$emit('nodeclick', node)
+        }
+      },
+      _dispatchEvent() {
+        this.$emit('change', this.selected.slice(0))
+      }
+    }
+  }
+</script>
+
+<style lang="scss">
+	$uni-primary: #007aff !default;
+
+	.uni-data-pickerview {
+		flex: 1;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		overflow: hidden;
+		height: 100%;
+	}
+
+  .error-text {
+    color: #DD524D;
+  }
+
+  .loading-cover {
+    position: absolute;
+    left: 0;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    background-color: rgba(255, 255, 255, .5);
+    /* #ifndef APP-NVUE */
+    display: flex;
+    /* #endif */
+    flex-direction: column;
+    align-items: center;
+    z-index: 1001;
+  }
+
+  .load-more {
+    /* #ifndef APP-NVUE */
+    margin: auto;
+    /* #endif */
+  }
+
+  .error-message {
+    background-color: #fff;
+    position: absolute;
+    left: 0;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    padding: 15px;
+    opacity: .9;
+    z-index: 102;
+  }
+
+  /* #ifdef APP-NVUE */
+  .selected-area {
+    width: 750rpx;
+  }
+  /* #endif */
+
+  .selected-list {
+    /* #ifndef APP-NVUE */
+    display: flex;
+    flex-wrap: nowrap;
+    /* #endif */
+    flex-direction: row;
+    padding: 0 5px;
+    border-bottom: 1px solid #f8f8f8;
+  }
+
+  .selected-item {
+    margin-left: 10px;
+    margin-right: 10px;
+    padding: 12px 0;
+    text-align: center;
+    /* #ifndef APP-NVUE */
+    white-space: nowrap;
+    /* #endif */
+  }
+
+  .selected-item-text-overflow {
+    width: 168px;
+    /* fix nvue */
+    overflow: hidden;
+    /* #ifndef APP-NVUE */
+    width: 6em;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    -o-text-overflow: ellipsis;
+    /* #endif */
+  }
+
+	.selected-item-active {
+		border-bottom: 2px solid $uni-primary;
+	}
+
+	.selected-item-text {
+		color: $uni-primary;
+	}
+
+  .tab-c {
+    position: relative;
+    flex: 1;
+    /* #ifndef APP-NVUE */
+    display: flex;
+    /* #endif */
+    flex-direction: row;
+    overflow: hidden;
+  }
+
+  .list {
+    flex: 1;
+  }
+
+  .item {
+    padding: 12px 15px;
+    /* border-bottom: 1px solid #f0f0f0; */
+    /* #ifndef APP-NVUE */
+    display: flex;
+    /* #endif */
+    flex-direction: row;
+    justify-content: space-between;
+  }
+
+  .is-disabled {
+    opacity: .5;
+  }
+
+  .item-text {
+    /* flex: 1; */
+    color: #333333;
+  }
+
+  .item-text-overflow {
+    width: 280px;
+    /* fix nvue */
+    overflow: hidden;
+    /* #ifndef APP-NVUE */
+    width: 20em;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    -o-text-overflow: ellipsis;
+    /* #endif */
+  }
+
+	.check {
+		margin-right: 5px;
+		border: 2px solid $uni-primary;
+		border-left: 0;
+		border-top: 0;
+		height: 12px;
+		width: 6px;
+		transform-origin: center;
+		/* #ifndef APP-NVUE */
+		transition: all 0.3s;
+		/* #endif */
+		transform: rotate(45deg);
+	}
+</style>

+ 91 - 0
actMgt/uni_modules/uni-data-picker/package.json

@@ -0,0 +1,91 @@
+{
+  "id": "uni-data-picker",
+  "displayName": "uni-data-picker 数据驱动的picker选择器",
+  "version": "2.0.1",
+  "description": "单列、多列级联选择器,常用于省市区城市选择、公司部门选择、多级分类等场景",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "picker",
+    "级联",
+    "省市区",
+    ""
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+"dcloudext": {
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+    "type": "component-vue"
+  },
+  "uni_modules": {
+    "dependencies": [
+      "uni-load-more",
+			"uni-icons",
+			"uni-scss"
+    ],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y",
+        "alipay": "n"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+        "QQ": "y",
+        "京东": "u"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}

+ 22 - 0
actMgt/uni_modules/uni-data-picker/readme.md

@@ -0,0 +1,22 @@
+## DataPicker 级联选择
+> **组件名:uni-data-picker**
+> 代码块: `uDataPicker`
+> 关联组件:`uni-data-pickerview`、`uni-load-more`。
+
+
+`<uni-data-picker>` 是一个选择类[datacom组件](https://uniapp.dcloud.net.cn/component/datacom)。
+
+支持单列、和多列级联选择。列数没有限制,如果屏幕显示不全,顶部tab区域会左右滚动。
+
+候选数据支持一次性加载完毕,也支持懒加载,比如示例图中,选择了“北京”后,动态加载北京的区县数据。
+
+`<uni-data-picker>` 组件尤其适用于地址选择、分类选择等选择类。
+
+`<uni-data-picker>` 支持本地数据、云端静态数据(json),uniCloud云数据库数据。
+
+`<uni-data-picker>` 可以通过JQL直连uniCloud云数据库,配套[DB Schema](https://uniapp.dcloud.net.cn/uniCloud/schema),可在schema2code中自动生成前端页面,还支持服务器端校验。
+
+在uniCloud数据表中新建表“uni-id-address”和“opendb-city-china”,这2个表的schema自带foreignKey关联。在“uni-id-address”表的表结构页面使用schema2code生成前端页面,会自动生成地址管理的维护页面,自动从“opendb-city-china”表包含的中国所有省市区信息里选择地址。
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-data-picker)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839

+ 25 - 0
actMgt/uni_modules/uni-load-more/changelog.md

@@ -0,0 +1,25 @@
+## 1.3.6(2024-10-15)
+- 修复 微信小程序中的getSystemInfo警告
+## 1.3.5(2024-10-12)
+- 修复 微信小程序中的getSystemInfo警告
+## 1.3.4(2024-10-12)
+- 修复 微信小程序中的getSystemInfo警告
+## 1.3.3(2022-01-20)
+- 新增 showText属性 ,是否显示文本
+## 1.3.2(2022-01-19)
+- 修复 nvue 平台下不显示文本的bug
+## 1.3.1(2022-01-19)
+- 修复 微信小程序平台样式选择器报警告的问题
+## 1.3.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-load-more](https://uniapp.dcloud.io/component/uniui/uni-load-more)
+## 1.2.1(2021-08-24)
+- 新增 支持国际化
+## 1.2.0(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.1.8(2021-05-12)
+- 新增 组件示例地址
+## 1.1.7(2021-03-30)
+- 修复 uni-load-more 在首页使用时,h5 平台报 'uni is not defined' 的 bug
+## 1.1.6(2021-02-05)
+- 调整为uni_modules目录规范

+ 5 - 0
actMgt/uni_modules/uni-load-more/components/uni-load-more/i18n/en.json

@@ -0,0 +1,5 @@
+{
+	"uni-load-more.contentdown": "Pull up to show more",
+	"uni-load-more.contentrefresh": "loading...",
+	"uni-load-more.contentnomore": "No more data"
+}

+ 8 - 0
actMgt/uni_modules/uni-load-more/components/uni-load-more/i18n/index.js

@@ -0,0 +1,8 @@
+import en from './en.json'
+import zhHans from './zh-Hans.json'
+import zhHant from './zh-Hant.json'
+export default {
+	en,
+	'zh-Hans': zhHans,
+	'zh-Hant': zhHant
+}

+ 5 - 0
actMgt/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hans.json

@@ -0,0 +1,5 @@
+{
+	"uni-load-more.contentdown": "上拉显示更多",
+	"uni-load-more.contentrefresh": "正在加载...",
+	"uni-load-more.contentnomore": "没有更多数据了"
+}

+ 5 - 0
actMgt/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hant.json

@@ -0,0 +1,5 @@
+{
+	"uni-load-more.contentdown": "上拉顯示更多",
+	"uni-load-more.contentrefresh": "正在加載...",
+	"uni-load-more.contentnomore": "沒有更多數據了"
+}

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 117 - 0
actMgt/uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue


+ 84 - 0
actMgt/uni_modules/uni-load-more/package.json

@@ -0,0 +1,84 @@
+{
+  "id": "uni-load-more",
+  "displayName": "uni-load-more 加载更多",
+  "version": "1.3.6",
+  "description": "LoadMore 组件,常用在列表里面,做滚动加载使用。",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "加载更多",
+    "load-more"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+"dcloudext": {
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+    "type": "component-vue"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y",
+        "alipay": "n"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}

+ 14 - 0
actMgt/uni_modules/uni-load-more/readme.md

@@ -0,0 +1,14 @@
+
+
+### LoadMore 加载更多
+> **组件名:uni-load-more**
+> 代码块: `uLoadMore`
+
+
+用于列表中,做滚动加载使用,展示 loading 的各种状态。
+
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-load-more)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
+
+

+ 4 - 60
actMgt/utils/map/leafletHelper.js

@@ -36,34 +36,16 @@ export default {
 	// options <object> 地图选项
 	async init(caller, mapid, mapUrl, mapConfig, options) {
 		// console.log("mapUrl", mapUrl);
-		
 		// patch.run()
 
 		global.init()
 		global.setCaller(caller)
 		global.setMapUrl(mapUrl)
 		global.mapOptions = Object.assign(config.mapDefaultOptions, options)
-		// if (global.mapOptions.maxBounds != null) {
-		// 	global.setPreloadBounds(global.mapOptions.maxBounds)
-		// 	// console.log("preloadBounds: ", global.mapOptions.maxBounds)
-		// 	// global.mapOptions.maxBounds = L.latLngBounds(global.mapOptions.maxBounds).pad(0.3)
-		// 	global.mapOptions.maxBounds = null
-		// 	// console.log("maxBounds: ", global.mapOptions.maxBounds)
-		// }
 		
 		const mapImageInfo = await uni.getImageInfo({src: mapUrl});
 		// console.log(mapImageInfo);
 		
-		// let jgwUrl = "";
-		// let index= mapUrl.lastIndexOf("."); // 获取最后一个.的位置
-		// if (index >= 0) {
-		// 	jgwUrl = mapUrl.substring(0, index) + ".jgw";
-		// 	console.log("jgwUrl", jgwUrl);
-		// } else {
-		// 	console.error("jgwUrl err", jgwUrl);
-		// 	return;
-		// }
-		// const jgwData = await this.readJgwFile(jgwUrl);
 		const jgwData = await this.parseJgwContent(mapConfig);
 		const bounds = await this.getImageBoundsByJgw(jgwData, mapImageInfo.width, mapImageInfo.height);
 		const center = this.getImageCenterByBounds(bounds);
@@ -123,21 +105,19 @@ export default {
 
 		global.map.on('zoomend', (e) => {
 			// console.log("[zoomend] 地图缩放结束", e)
-			this.preLoadTile()
+			// this.preLoadTile()
 			player.onZoomEnd(e)
 			// checkPoint.onZoomEnd(e)
 			route.onZoomEnd(e)
 		});
 
-		// this.setToken(token)
 		this.addMapLayer(mapUrl, bounds);
 		
 		player.init()
 		// checkPoint.init()
 		route.init()
 
-		// this.preLoadTile()
-		console.log("init map success")
+		console.log("[init] 地图初始化成功")
 	},
 	
 	async readJgwFile(jgwUrl) {
@@ -212,16 +192,6 @@ export default {
 		};
 	},
 	
-	/* setMapServerUrl(url) {
-		console.log("[setMapServerUrl] url: " + url)
-		L.setMapServerUrl(url)
-	},
-
-	setToken(token) {
-		console.log("[setToken] token: " + token)
-		L.setToken(token)
-	}, */
-	
 	addMapLayer(mapUrl, bounds) {
 		// console.log('[addMapLayer] mapurl', mapurl)
 		global.map_layer = L.imageOverlay(mapUrl, bounds).addTo(global.map);
@@ -430,7 +400,7 @@ export default {
 	},
 
 	// 预加载地图瓦片
-	preLoadTile() {
+	/* preLoadTile() {
 		return
 		
 		var zoom = global.map.getZoom()
@@ -467,28 +437,6 @@ export default {
 
 		// console.log("[preLoadTile] 预加载地图瓦片", bounds, west, south, east, north, zoom)
 
-		// L.circleMarker([south, west], {
-		// 		radius: 18, // 圆的半径 px
-		// 		weight: 1.6, // 描边宽度 px
-		// 		opacity: 1.0, // 描边不透明度
-		// 		fill: true, // 是否填充
-		// 		fillColor: 'red', // 填充颜色
-		// 		fillOpacity: 1.0, // 填充不透明度
-		// 	})
-		// 	.addTo(global.map)
-		// console.log("[preLoadTile] circleMarker", [south, west])
-
-		// L.circleMarker([north, east], {
-		// 		radius: 18, // 圆的半径 px
-		// 		weight: 1.6, // 描边宽度 px
-		// 		opacity: 1.0, // 描边不透明度
-		// 		fill: true, // 是否填充
-		// 		fillColor: 'red', // 填充颜色
-		// 		fillOpacity: 1.0, // 填充不透明度
-		// 	})
-		// 	.addTo(global.map)
-		// console.log("[preLoadTile] circleMarker", [north, east])
-
 		// Determine which tile we need
 		var dataEast = this.long2tile(east, preloadZoom)
 		var dataWest = this.long2tile(west, preloadZoom)
@@ -511,11 +459,7 @@ export default {
 				// console.log("[preLoadTile] 预加载地图瓦片", url)
 			}
 		}
-	},
-
-	test() {
-		console.log("test ok")
-	},
+	}, */
 
 	free() {
 		console.log("[Leaflet] free()")

+ 8 - 8
actMgt/utils/map/sub/player.js

@@ -46,7 +46,7 @@ export default {
 		if (flag != null) {
 			togglePlayerFlag = !flag
 		}
-		console.log("[togglePlayer]", togglePlayerFlag)
+		// console.log("[togglePlayer]", togglePlayerFlag)
 
 		if (togglePlayerFlag) {
 			this.playerLayerGroup.removeFrom(global.map)
@@ -100,10 +100,10 @@ export default {
 
 	drawAllPlayers() {
 		if (global.players == null) {
-			console.log('[drawAllPlayers] 玩家列表为空')
+			// console.log('[drawAllPlayers] 玩家列表为空')
 			return
 		} else {
-			console.log('[drawAllPlayers]', global.players)
+			// console.log('[drawAllPlayers]', global.players)
 		}
 		// if (this.playerLayerGroup != null)
 		// 	this.playerLayerGroup.clearLayers()
@@ -249,14 +249,14 @@ export default {
 		var player = global.getPlayerById(playerId)
 		var player_position = global.getPlayerPositionById(playerId)
 		var storePlayer = global.getStorePlayersById(playerId)
-		console.log('[drawOnePlayer]', player, player_position)
+		// console.log('[drawOnePlayer]', player, player_position)
 
 		if (player == null) {
 			console.warn('[drawOnePlayer] 玩家数据为空', player)
 			return
 		}
 		if (player_position == null) {
-			console.log('[drawOnePlayer] 玩家位置数据为空', player_position)
+			console.warn('[drawOnePlayer] 玩家位置数据为空', player_position)
 			return
 		}
 
@@ -381,7 +381,7 @@ export default {
 	},
 	drawAllTrails(duration) {
 		if (global.players == null) {
-			console.log('[drawAllTrails] 玩家列表为空')
+			// console.log('[drawAllTrails] 玩家列表为空')
 			return
 		}
 		// if (this.trailLayerGroup != null)
@@ -396,7 +396,7 @@ export default {
 		var player = global.getPlayerById(playerId)
 		var player_position = global.getPlayerPositionById(playerId)
 		var storePlayer = global.getStorePlayersById(playerId)
-		console.log('[drawOneTrail] param', player, player_position, storePlayer)
+		// console.log('[drawOneTrail] param', player, player_position, storePlayer)
 
 		if (player == null) {
 			console.warn('[drawOneTrail] 玩家数据为空', player)
@@ -408,7 +408,7 @@ export default {
 		}
 
 		if (storePlayer == null || storePlayer.trail == null) {
-			console.warn('[drawOneTrail] 轨迹数据为空', player, storePlayer)
+			// console.warn('[drawOneTrail] 轨迹数据为空', player, storePlayer)
 
 			var trail = null
 			var trail2 = null

+ 2 - 2
actMgt/utils/map/sub/route.js

@@ -62,7 +62,7 @@ export default {
 		store.commit('setMapControlRoute', toggleFlag)
 	},
 	drawAllRoutes() {
-		console.log("[drawAllRoutes] routes", global.routes)
+		// console.log("[drawAllRoutes] routes", global.routes)
 		if (this.cpMarkLayerGroup != null)
 			this.cpMarkLayerGroup.clearLayers()
 		if (this.cpMemoLayerGroup != null)
@@ -80,7 +80,7 @@ export default {
 			console.warn('[drawOneRoute] 关键数据为空', cpList)
 			return
 		}
-		console.warn('[drawOneRoute] cpList', cpList)
+		// console.log('[drawOneRoute] cpList', cpList)
 
 		var type = ''
 		for (var i = 0; i < cpList.length; i++) {

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott