Commit 6bce1057ce854466f1603a2e297fc3421b85f04d

Authored by 刘淇
1 parent d6406a70

ai 大区经理

common/utils/common.js
... ... @@ -25,7 +25,8 @@ export const nextStepMap = {
25 25 },
26 26 ylInspector: {
27 27 name: '巡查员验收',
28   - btnText: '验收',
  28 + // btnText: '验收',
  29 + ysShow:true,
29 30 operateTypePass: 140, //巡查员验收通过: 140
30 31 operateTypeNoPass: 240, // 巡查员验收不通过:240
31 32 backShow: false,
... ... @@ -56,6 +57,27 @@ export const nextStepMap = {
56 57 backShow: true,
57 58 renewShow: false
58 59 },
  60 +
  61 + aiRegionManager: {
  62 + name: 'ai单子大区经理分配',
  63 + btnText: '分配',
  64 + operateTypePass: 40, // 大区经理分配:40
  65 + operateTypeNoPass: 50, // 大区经理退回:50
  66 + backShow: true,
  67 + renewShow: false
  68 + },
  69 +
  70 + ylAiInspectorStart: {
  71 + name: 'AI工单派发人员',
  72 + ysShow:false,
  73 + btnText: '',
  74 + operateTypePass: 40, // 大区经理分配:40
  75 + operateTypeNoPass: 50, // 大区经理退回:50
  76 + backShow: false,
  77 + renewShow: false
  78 + },
  79 +
  80 +
59 81 }
60 82  
61 83 export const buzStatusMap = {
... ... @@ -74,6 +96,8 @@ export const buzStatusMap = {
74 96 '80': '分配',
75 97 '70': '退回',
76 98 '60': '分配',
  99 + '50':'退回',
  100 + '40':'分配',
77 101 }
78 102  
79 103 /**
... ...
manifest.json
... ... @@ -48,17 +48,17 @@
48 48 },
49 49 /* 快应用特有相关 */
50 50 "quickapp" : {},
51   - "uni-app": {
52   - "vue3": true,
53   - "compilerOptions": {}
  51 + "uni-app" : {
  52 + "vue3" : true,
  53 + "compilerOptions" : {}
54 54 },
55 55 /* 小程序特有相关 */
56 56 "mp-weixin" : {
57   - "appid" : "wxcb4cd34066b97d82",
  57 + "appid" : "wx64368a9b9e799172",
58 58 "setting" : {
59 59 "urlCheck" : false
60 60 },
61   - "lazyCodeLoading": "requiredComponents",
  61 + "lazyCodeLoading" : "requiredComponents",
62 62 "usingComponents" : true,
63 63 "permission" : {
64 64 "scope.userLocation" : {
... ...
pages-sub/daily/maintain-manage/finish-plan-detail.vue
... ... @@ -45,23 +45,32 @@
45 45 <up-cell title="照片">
46 46 <template #value>
47 47 <view class="cell-content-wrap">
48   - <!-- 修复1:手动渲染图片,兼容WebP + 强制尺寸 -->
49   - <view v-if="!!i.beginImgList?.length" class="album-container">
50   - <view
51   - class="album-item"
52   - v-for="(imgUrl, imgIndex) in formatImageUrls(i.beginImgList)"
53   - :key="imgIndex"
54   - @click="previewImage(imgUrl, formatImageUrls(i.beginImgList))"
55   - >
56   - <image
57   - :src="imgUrl"
58   - mode="widthFix"
59   - class="album-image"
60   - :style="{width: '70px', height: '70px', objectFit: 'cover'}"
61   - ></image>
62   - </view>
63   - </view>
64   - <text v-else class="empty-text">暂无问题照片</text>
  48 +
  49 + <up-album
  50 + :urls="i.beginImgList "
  51 + singleSize="70"
  52 + multipleSize="70"
  53 + :preview-full-image="true"
  54 +
  55 + ></up-album>
  56 +
  57 +<!-- &lt;!&ndash; 修复1:手动渲染图片,兼容WebP + 强制尺寸 &ndash;&gt;-->
  58 +<!-- <view v-if="!!i.beginImgList?.length" class="album-container">-->
  59 +<!-- <view-->
  60 +<!-- class="album-item"-->
  61 +<!-- v-for="(imgUrl, imgIndex) in formatImageUrls(i.beginImgList)"-->
  62 +<!-- :key="imgIndex"-->
  63 +<!-- @click="previewImage(imgUrl, formatImageUrls(i.beginImgList))"-->
  64 +<!-- >-->
  65 +<!-- <image-->
  66 +<!-- :src="imgUrl"-->
  67 +<!-- mode="widthFix"-->
  68 +<!-- class="album-image"-->
  69 +<!-- :style="{width: '70px', height: '70px', objectFit: 'cover'}"-->
  70 +<!-- ></image>-->
  71 +<!-- </view>-->
  72 +<!-- </view>-->
  73 +<!-- <text v-else class="empty-text">暂无问题照片</text>-->
65 74 </view>
66 75 </template>
67 76 </up-cell>
... ... @@ -188,30 +197,30 @@ onLoad((options) =&gt; {
188 197  
189 198 // 图片容器样式
190 199 .cell-content-wrap {
191   - padding: 10rpx 0;
192   -}
193   -
194   -// 自定义相册容器
195   -.album-container {
196   - display: flex;
197   - flex-wrap: wrap;
198   - gap: 10rpx; // 图片间距
  200 + //padding: 10rpx 0;
199 201 }
200 202  
201   -// 单张图片样式
202   -.album-item {
203   - width: 70px;
204   - height: 70px;
205   - border-radius: 4rpx;
206   - overflow: hidden;
207   -}
208   -
209   -// 图片样式(强制尺寸 + 覆盖)
210   -.album-image {
211   - width: 100%;
212   - height: 100%;
213   - object-fit: cover; // 保持比例裁剪,避免拉伸
214   -}
  203 +//// 自定义相册容器
  204 +//.album-container {
  205 +// display: flex;
  206 +// flex-wrap: wrap;
  207 +// gap: 10rpx; // 图片间距
  208 +//}
  209 +//
  210 +//// 单张图片样式
  211 +//.album-item {
  212 +// width: 70px;
  213 +// height: 70px;
  214 +// border-radius: 4rpx;
  215 +// overflow: hidden;
  216 +//}
  217 +//
  218 +//// 图片样式(强制尺寸 + 覆盖)
  219 +//.album-image {
  220 +// width: 70px;
  221 +// height: 70px;
  222 +// object-fit: cover; // 保持比例裁剪,避免拉伸
  223 +//}
215 224  
216 225 // 空文本样式
217 226 .empty-text {
... ...
pages-sub/daily/maintain-manage/index.vue
... ... @@ -84,6 +84,10 @@
84 84 <view class="common-custom-btn " style="--btn-top: 68px;" @click="goToDetail(item)">
85 85 计划明细
86 86 </view>
  87 +<!-- <view class="u-body-item u-flex">-->
  88 +<!-- <view class="u-body-item-title">批次号:</view>-->
  89 +<!-- <view class="u-line-1 u-body-value">{{ item.batchNo || '-' }}</view>-->
  90 +<!-- </view>-->
87 91 <view class="u-body-item u-flex">
88 92 <view class="u-body-item-title">道路名称:</view>
89 93 <view class="u-line-1 u-body-value">{{ item.roadName || '-' }}</view>
... ...
pages-sub/daily/patrol-manage/pending-plan-detail.vue
... ... @@ -11,9 +11,7 @@
11 11 <!-- 自定义标题区域 -->
12 12 <template #head>
13 13 <view class="card-header">
14   - <view class="common-card-title common-name">{{ item.planName || '无计划名称' }}{{
15   - item.planName || '无计划名称'
16   - }}
  14 + <view class="common-card-title common-name">{{ item.planName || '无计划名称' }}
17 15 </view>
18 16 <!-- 已失效标识 -->
19 17 <view v-show="item.finishState == 3 " class="common-invalid-tag">已失效</view>
... ...
pages-sub/daily/quick-order/order-detail.vue
... ... @@ -128,14 +128,14 @@ import { ref } from &#39;vue&#39;;
128 128 import { inspectionPlanDetail } from "@/api/quick-order/quick-order";
129 129 import { onLoad } from '@dcloudio/uni-app';
130 130  
131   -// 修复1:给orderDetail指定类型,明确图片数组的类型(关键)
  131 +// 给orderDetail指定类型,明确图片数组的类型
132 132 interface OrderDetail {
133 133 problemsImgs?: string[];
134 134 endImgs?: string[];
135 135 [key: string]: any; // 兼容其他属性
136 136 }
137 137  
138   -// 修复2:初始化时给图片数组赋空数组,避免模板解析时访问undefined
  138 +// 初始化时给图片数组赋空数组,避免模板解析时访问undefined
139 139 const orderDetail = ref<OrderDetail>({
140 140 problemsImgs: [],
141 141 endImgs: []
... ...
pages-sub/problem/ai-manage/index.vue
... ... @@ -96,9 +96,14 @@
96 96 </view>
97 97 <!-- 操作按钮行 -->
98 98 <view class="u-body-item u-flex common-justify-between common-item-center mt-20">
99   - <up-button type="warning" size="mini" @click="handleReject(item)" v-show="nextStepMap[item.taskKey].backShow">回退</up-button>
100   - <up-button type="success" size="mini" @click="handleRenew(item)" v-show="nextStepMap[item.taskKey].renewShow">重新提交</up-button>
101   - <up-button type="primary" size="mini" @click="handleProcess(item)">{{ nextStepMap[item.taskKey].btnText }}</up-button>
  99 +<!-- <up-button type="warning" size="mini" @click="handleReject(item)" v-show="nextStepMap[item.taskKey].backShow">回退</up-button>-->
  100 +<!-- <up-button type="success" size="mini" @click="handleRenew(item)" v-show="nextStepMap[item.taskKey].renewShow">重新提交</up-button>-->
  101 +<!-- <up-button type="primary" size="mini" @click="handleProcess(item)">{{ nextStepMap[item.taskKey].btnText }}</up-button>-->
  102 + <up-button type="primary" size="mini" @click="handleProcess(item)" v-show="nextStepMap[item.taskKey].ysShow">验收</up-button>
  103 +
  104 +
  105 +
  106 +
102 107 <up-button type="info" size="mini" @click="handleDetail(item)">详情</up-button>
103 108 </view>
104 109 </view>
... ... @@ -265,8 +270,8 @@ const USER_ROLES = userStore.userInfo?.roles || [];
265 270  
266 271 // ========== 基础状态 (按模块分组,语义化更强) ==========
267 272 // tab切换
268   -const activeTab = ref(0); // 0-待办 1-我发起的 2-已办
269   -const tabList = ref([{name: '待办'}, {name: '我发起的'}, {name: '已办'}]);
  273 +const activeTab = ref(0); // 0-待办 1-已办 2-我发起的
  274 +const tabList = ref([{name: '待办'}, {name: '已办'}, {name: '我发起的'}]);
270 275 // 排序与搜索
271 276 const selectedSortValue = ref(1);
272 277 const sortOptions = ref([
... ... @@ -384,7 +389,7 @@ const queryList = async (pageNo, pageSize) =&gt; {
384 389 const params = getQueryParams(pageNo, pageSize);
385 390 let res;
386 391 if (activeTab.value === 0) res = await todoBuzSimplePage(params);
387   - else if (activeTab.value === 1) res = await myBuzSimplePage(params);
  392 + else if (activeTab.value === 2) res = await myBuzSimplePage(params);
388 393 else res = await doneBuzSimplePage(params);
389 394 pagingRef.value.complete(res?.list || [], res?.total || 0);
390 395 } catch (error) {
... ... @@ -547,7 +552,8 @@ const handleAcceptModalCancel = () =&gt; {
547 552 // 验收提交
548 553 const handleAcceptModalConfirm = async () => {
549 554 const reason = acceptReason.value.trim();
550   - if (!reason) return uni.showToast({title: '请填写验收原因', icon: 'none'});
  555 + console.log(acceptRadioValue.value)
  556 + if (!reason&&acceptRadioValue.value==1) return uni.showToast({title: '请填写验收原因', icon: 'none'});
551 557 if (reason.length > 200) return uni.showToast({title: '验收原因最多200字', icon: 'none'});
552 558  
553 559 const item = currentAcceptItem.value;
... ...
pages-sub/problem/regional-order-manage/index.vue
... ... @@ -218,7 +218,8 @@ import {
218 218 doneBuzSimplePage,
219 219 qyUniversalApproval,
220 220 daquUniversalApproval,
221   - dcyUniversalApproval
  221 + dcyUniversalApproval,
  222 + aiUniversalApproval
222 223 } from '@/api/regional-order-manage/regional-order-manage'
223 224 import { useUserStore } from '@/pinia/user';
224 225 import { nextStepMap, buzStatusMap } from '@/common/utils/common'
... ... @@ -323,11 +324,13 @@ const getQueryParams = (pageNo, pageSize) =&gt; {
323 324 * 统一调用审批接口
324 325 */
325 326 const callApprovalApi = async (params, taskKey) => {
  327 + if (taskKey === 'aiRegionManager') return await aiUniversalApproval(params);
326 328 if (taskKey === 'shRegionManager') return await dcyUniversalApproval(params);
327 329 if (taskKey === 'regionManager') return await qyUniversalApproval(params);
328 330 if (USER_ROLES.includes('regional_manager')) return await daquUniversalApproval(params);
329 331 if (USER_ROLES.includes('Inspector_global')) return await dcyUniversalApproval(params);
330 332 if (USER_ROLES.includes('patrol_global')) return await qyUniversalApproval(params);
  333 + // if (USER_ROLES.includes('AI_dispatcher')) return await aiUniversalApproval(params);
331 334 throw new Error('未匹配到对应的审批接口,请检查角色或工单taskKey');
332 335 };
333 336  
... ... @@ -428,11 +431,37 @@ const handleProcess = async (item) =&gt; {
428 431 }
429 432 // 督察员单子大区经理分配
430 433 else if (stepName === '督察员单子大区经理分配') {
431   - const postData = { taskKey: item.taskKey, taskId: item.taskId, operateType:60, workerDataId:item.id, agree:0, reason:item.remark, roadId:item.roadId, roadName:item.roadName, pressingType:item.pressingType, orderName:item.orderName, expectedFinishDate: item.expectedFinishDate, busiLine:item.busiLine };
432   - await dcyUniversalApproval(postData);
433   - showToast('分配成功', 'success');
434   - refreshOrderList();
  434 + uni.showModal({
  435 + title: "分配工单",
  436 + content: "请确定是否分配工单?",
  437 + success: async (res) => {
  438 + if (res.confirm) {
  439 + const postData = { taskKey: item.taskKey, taskId: item.taskId, operateType:60, workerDataId:item.id, agree:0, reason:item.remark, roadId:item.roadId, roadName:item.roadName, pressingType:item.pressingType, orderName:item.orderName, expectedFinishDate: item.expectedFinishDate, busiLine:item.busiLine };
  440 + await dcyUniversalApproval(postData);
  441 + showToast('分配成功', 'success');
  442 + refreshOrderList();
  443 + }
  444 + }
  445 + });
  446 +
435 447 }
  448 + // ai单子大区经理分配
  449 + else if (stepName === 'ai单子大区经理分配') {
  450 + uni.showModal({
  451 + title: "分配工单",
  452 + content: "请确定是否分配工单?",
  453 + success: async (res) => {
  454 + if (res.confirm) {
  455 + const postData = { taskKey: 'shRegionManager', taskId: item.taskId, operateType:40, workerDataId:item.id, agree:0, reason:item.remark, roadId:item.roadId, roadName:item.roadName, pressingType:item.pressingType, orderName:item.orderName, expectedFinishDate: item.expectedFinishDate, busiLine:item.busiLine };
  456 + await aiUniversalApproval(postData);
  457 + showToast('分配成功', 'success');
  458 + refreshOrderList();
  459 + }
  460 + }
  461 + });
  462 + }
  463 +
  464 +
436 465 // 验收弹窗
437 466 else if (['巡查员验收', '养护组长验收'].includes(stepName)) {
438 467 currentAcceptItem.value = item;
... ...
pages-sub/problem/regional-order-manage/order-detail.vue
... ... @@ -198,7 +198,7 @@
198 198 <view class="step-content-wrap">
199 199 <!-- 1. 原标题内容:节点名称 + 操作人 -->
200 200 <view class="step-title">
201   - {{ item.name }}
  201 + {{ item.name ? item.name.replace('大区经理', '业务调度员') : item.name }}
202 202 </view>
203 203  
204 204 <!-- 2. 原描述内容:时间 + 处理说明(最多200字) -->
... ... @@ -420,12 +420,13 @@ const setOrderStorage = (item: any, prefix: string) =&gt; {
420 420 * 统一调用审批接口 (角色+taskKey匹配)
421 421 */
422 422 const callApprovalApi = async (params: any, taskKey: string) => {
  423 + if (taskKey === 'aiRegionManager') return await aiUniversalApproval(params);
423 424 if (taskKey === 'shRegionManager') return await dcyUniversalApproval(params);
424 425 if (taskKey === 'regionManager') return await qyUniversalApproval(params);
425 426 if (USER_ROLES.includes('regional_manager')) return await daquUniversalApproval(params);
426 427 if (USER_ROLES.includes('Inspector_global')) return await dcyUniversalApproval(params);
427 428 if (USER_ROLES.includes('patrol_global')) return await qyUniversalApproval(params);
428   - if (USER_ROLES.includes('AI_dispatcher')) return await aiUniversalApproval(params);
  429 + // if (USER_ROLES.includes('AI_dispatcher')) return await aiUniversalApproval(params);
429 430 throw new Error('未匹配到对应的审批接口,请检查角色或工单taskKey');
430 431 };
431 432  
... ... @@ -595,9 +596,10 @@ const activeTopTabClick = async (item: any) =&gt; {
595 596 }
596 597 const res = await getApprovalDetail(getData)
597 598 if (res && res.activityNodes && res.activityNodes.length) {
598   - const filteredActivityNodes = res.activityNodes.filter(node => {
599   - return node.name !== '结束';
600   - });
  599 + // const filteredActivityNodes = res.activityNodes.filter(node => {
  600 + // return node.name !== '结束';
  601 + // });
  602 + const filteredActivityNodes = res.activityNodes
601 603 const formatActivityNodes = filteredActivityNodes.map(node => ({
602 604 ...node,
603 605 title: node.name
... ... @@ -721,16 +723,41 @@ const handleProcess = async (item: any) =&gt; {
721 723 }
722 724 // 督察员单子大区经理分配
723 725 else if (stepName === '督察员单子大区经理分配') {
724   - const postData = {
725   - taskKey: item.taskKey, taskId: item.taskId, operateType:60, workerDataId:item.id,
726   - agree:0, reason:item.remark, roadId:item.roadId, roadName:item.roadName,
727   - pressingType:item.pressingType, orderName:item.orderName,
728   - expectedFinishDate: item.expectedFinishDate, busiLine:item.busiLine
729   - };
730   - await dcyUniversalApproval(postData);
731   - showToast('分配成功', 'success');
732   - eventChannel.value.emit('needRefresh');
733   - uni.navigateBack({ delta: 1 });
  726 +
  727 + uni.showModal({
  728 + title: "分配工单",
  729 + content: "请确定是否分配工单?",
  730 + success: async (res) => {
  731 + const postData = {
  732 + taskKey: item.taskKey, taskId: item.taskId, operateType:60, workerDataId:item.id,
  733 + agree:0, reason:item.remark, roadId:item.roadId, roadName:item.roadName,
  734 + pressingType:item.pressingType, orderName:item.orderName,
  735 + expectedFinishDate: item.expectedFinishDate, busiLine:item.busiLine
  736 + };
  737 + await dcyUniversalApproval(postData);
  738 + showToast('分配成功', 'success');
  739 + eventChannel.value.emit('needRefresh');
  740 + uni.navigateBack({ delta: 1 });
  741 + }
  742 + });
  743 +
  744 + }
  745 +
  746 + // ai单子大区经理分配
  747 + else if (stepName === 'ai单子大区经理分配') {
  748 + uni.showModal({
  749 + title: "分配工单",
  750 + content: "请确定是否分配工单?",
  751 + success: async (res) => {
  752 + if (res.confirm) {
  753 + const postData = { taskKey: item.taskKey, taskId: item.taskId, operateType:40, workerDataId:item.id, agree:0, reason:item.remark, roadId:item.roadId, roadName:item.roadName, pressingType:item.pressingType, orderName:item.orderName, expectedFinishDate: item.expectedFinishDate, busiLine:item.busiLine };
  754 + await aiUniversalApproval(postData);
  755 + showToast('分配成功', 'success');
  756 + eventChannel.value.emit('needRefresh');
  757 + uni.navigateBack({ delta: 1 });
  758 + }
  759 + }
  760 + });
734 761 }
735 762 // 验收弹窗
736 763 else if (['养护组长验收', '巡查员验收'].includes(stepName)) {
... ...
pages-sub/problem/work-order-manage/distribution-order.vue
... ... @@ -254,6 +254,8 @@ const submitWorkOrder = async () =&gt; {
254 254 icon: 'success',
255 255 duration: 1000
256 256 })
  257 + // ========== 核心修改:触发全局刷新事件 ==========
  258 + uni.$emit('refreshWorkOrderList'); // 触发全局自定义事件
257 259 // 7. 提交成功后返回上一页
258 260 setTimeout(() => {
259 261 uni.navigateTo({
... ...
pages-sub/problem/work-order-manage/index.vue
... ... @@ -277,7 +277,7 @@
277 277  
278 278 <script setup>
279 279 import { ref, computed, watch } from 'vue';
280   -import { onShow, onLoad } from '@dcloudio/uni-app';
  280 +import { onShow, onLoad, onUnload } from '@dcloudio/uni-app';
281 281 import { timeFormat } from '@/uni_modules/uview-plus';
282 282 import {
283 283 myBuzSimplePage,
... ... @@ -668,6 +668,15 @@ const handleAcceptModalConfirm = async () =&gt; {
668 668 onLoad(() => {
669 669 // 初始化加载列表
670 670 paging.value?.reload();
  671 + uni.$on('refreshWorkOrderList', () => {
  672 + console.log('监听到工单刷新事件,执行列表刷新');
  673 + if (paging.value) {
  674 + paging.value.reload(); // 刷新z-paging列表
  675 + }
  676 + });
  677 +});
  678 +onUnload(() => {
  679 + uni.$off('refreshWorkOrderList');
671 680 });
672 681 </script>
673 682  
... ... @@ -716,6 +725,7 @@ onLoad(() =&gt; {
716 725 box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
717 726 }
718 727 .u-body-item-btn-wrap :deep(.u-button--large){
  728 +
719 729 height: 28px;
720 730 }
721 731  
... ...
pages-sub/problem/work-order-manage/order-detail.vue
... ... @@ -197,7 +197,7 @@
197 197 <view class="step-content-wrap">
198 198 <!-- 1. 原标题内容:节点名称 + 操作人 -->
199 199 <view class="step-title">
200   - {{ item.name }}
  200 + {{ item.name ? item.name.replace('大区经理', '业务调度员') : item.name }}
201 201 </view>
202 202  
203 203 <!-- 2. 原描述内容:时间 + 处理说明(最多200字) -->
... ...
pages/index/index.vue
... ... @@ -5,7 +5,7 @@
5 5 <view class="user-info">
6 6 <view class="user-text">
7 7 <view class="username">你好{{ userName }},欢迎登录</view>
8   - <view class="login-desc">全域智能运营管理平台</view>
  8 + <view class="login-desc">蓟城山水智慧园林养护平台</view>
9 9 </view>
10 10 </view>
11 11 <view class="msg-icon" @click="handleMsgClick" hover-class="msg-icon--hover">
... ... @@ -165,7 +165,7 @@ const klineChartData = ref([
165 165 color: '#25AF69'
166 166 },
167 167 {
168   - name: '待完成总任务数',
  168 + name: '总任务数',
169 169 data: [],
170 170 color: '#B34C17'
171 171 }
... ...
pages/login/index.vue
... ... @@ -3,7 +3,9 @@
3 3 <!-- 顶部标题区 -->
4 4 <view class="top-title">
5 5 <text class="welcome-text">你好,欢迎光临</text>
6   - <text class="platform-name">全域智能运营管理平台</text>
  6 +<!-- <text class="platform-name">全域智能运营管理平台</text>-->
  7 + <text class="platform-name">蓟城山水智慧园林养护平台</text>
  8 +
7 9 </view>
8 10  
9 11 <!-- 登录表单区域 -->
... ...
pages/workbench/index.vue
... ... @@ -11,7 +11,7 @@
11 11 <!-- 蓝色装饰块 -->
12 12 <view class="blue-decor-block" v-show="!loading">
13 13 <text class="welcome-text u-line-1">你好{{ userInfo?.user?.nickname || '' }},欢迎登录</text>
14   - <text class="platform-name">全域智能运营管理平台</text>
  14 + <text class="platform-name">蓟城山水智慧园林养护平台</text>
15 15 </view>
16 16  
17 17 <!-- 内容容器 -->
... ...