Просмотр исходного кода

✨ feat(日报): 系统消息钉钉消息进行日报审批

Zimo 4 недель назад
Родитель
Сommit
4372fef50c
9 измененных файлов с 834 добавлено и 711 удалено
  1. 1 1
      android/simpleDemo/build.gradle
  2. 8 0
      api/ruiDu.js
  3. 2 2
      config/env.prod.js
  4. 31 17
      pages.json
  5. 227 229
      pages/message/index.vue
  6. 162 0
      pages/ruiDu/approval.vue
  7. 108 150
      pages/ruiDu/compontents/report-info.vue
  8. 276 297
      pages/user/login.vue
  9. 19 15
      utils/navigate.js

+ 1 - 1
android/simpleDemo/build.gradle

@@ -11,7 +11,7 @@ android {
         // targetSdkVersion 33
         targetSdk 33
         versionCode 10206
-        versionName "1.2.6"
+        versionName "1.2.7"
         multiDexEnabled true
         compileOptions {
             sourceCompatibility JavaVersion.VERSION_1_8

+ 8 - 0
api/ruiDu.js

@@ -74,3 +74,11 @@ export function updateRuiDuReportBatch(data) {
     data,
   });
 }
+
+export function approveRdDailyReport(data) {
+  return request({
+    url: '/pms/iot-rd-daily-report/approval',
+    method: 'put',
+    data,
+  });
+}

+ 2 - 2
config/env.prod.js

@@ -1,7 +1,7 @@
 // 生产环境配置
 export default {
   // apiUrl: 'http://192.168.1.63:8888',
-  // apiUrl: 'https://iot.deepoil.cc',	//测试
+  // apiUrl: 'https://iot.deepoil.cc', //测试
   apiUrl: 'https://aims.deepoil.cc', //正式
   apiUrlSuffix: '/admin-api',
   // 其他开发环境配置...
@@ -11,4 +11,4 @@ export default {
   MiniAppId: '5000000006298501', //钉钉微应用的MiniAppID - 正式环境
   AppKey: 'dingmr9ez0ecgbmscfeb', //钉钉微应用的AppKey - 正式环境
   AppSecret: 'VhG_zMdTvIBwA_0Ef8FJ0foH3VYYo5T-kw0ukX_PBA8Ah1xl7AjDw5RVYCU0DTpe', //钉钉微应用的AppSecret - 正式环境
-};
+};

+ 31 - 17
pages.json

@@ -1,5 +1,6 @@
 {
-  "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
+  "pages": [
+    //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
     {
       // 登录
       "path": "pages/user/login",
@@ -103,7 +104,7 @@
       // 设备维修详情
       "path": "pages/repair/detail",
       "style": {
-       "navigationBarTitleText": "%equipmentMaintenance.viewWorkOrder%"
+        "navigationBarTitleText": "%equipmentMaintenance.viewWorkOrder%"
       }
     },
     {
@@ -176,6 +177,13 @@
         "navigationBarTitleText": "%ruiDu.indexTitle%"
       }
     },
+    {
+      // 瑞都日报-编辑
+      "path": "pages/ruiDu/approval",
+      "style": {
+        "navigationBarTitleText": "%ruiDu.editTitle%"
+      }
+    },
     {
       // 瑞都日报-详情
       "path": "pages/ruiDu/detail",
@@ -225,12 +233,14 @@
         "navigationBarTitleText": "%statusChange.title%",
         "app-plus": {
           "titleNView": {
-            "buttons": [{
-              "text": "%statusChange.insert%",
-              "color": "#004098",
-              "fontSize": "14px",
-              "width": "80px"
-            }]
+            "buttons": [
+              {
+                "text": "%statusChange.insert%",
+                "color": "#004098",
+                "fontSize": "14px",
+                "width": "80px"
+              }
+            ]
           }
         }
       }
@@ -256,12 +266,14 @@
         "navigationBarTitleText": "%deviceUser.title%",
         "app-plus": {
           "titleNView": {
-            "buttons": [{
-              "text": "%statusChange.insert%",
-              "color": "#004098",
-              "fontSize": "14px",
-              "width": "80px"
-            }]
+            "buttons": [
+              {
+                "text": "%statusChange.insert%",
+                "color": "#004098",
+                "fontSize": "14px",
+                "width": "80px"
+              }
+            ]
           }
         }
       }
@@ -347,7 +359,8 @@
     "backgroundColor": "white",
     "color": "#999999",
     "selectedColor": "#004098",
-    "list": [{
+    "list": [
+      {
         "pagePath": "pages/home/index",
         "iconPath": "/static/tabbar/shouye-weixuanzhong.png",
         "selectedIconPath": "/static/tabbar/shouye-xuanzhong.png",
@@ -374,9 +387,10 @@
   "easycom": {
     // 配置easycom组件自动引入
     "autoscan": true, // 是否开启easycom组件的自动扫描
-    "custom": { // 自定义扫描规则
+    "custom": {
+      // 自定义扫描规则
       // "^uni-(.*)": "uni_modules/uni-$1/uni-$1.vue"
       "^global-(.*)": "@/components/global/$1.vue"
     }
   }
-}
+}

+ 227 - 229
pages/message/index.vue

@@ -1,248 +1,246 @@
 <template>
-	<z-paging class="page" ref="paging" v-model="dataList" @query="loadData">
-		<template #top>
-			<uni-row style="padding-top: 8px">
-				<uni-badge v-for="(item, index) of tabs" :key="index" absolute="rightTop" :offset="[0, 4]"
-					:text="index === 2 ? unreadMessageCount : 0" style="margin-right: 20px">
-					<text :class="index === currentTab ? 'tab-selected' : 'tab-normal'" @click="onTabChanged(index)">
-						{{ item }}
-					</text>
-				</uni-badge>
-			</uni-row>
-		</template>
-		<view class="list">
-			<template v-if="currentTab === 0">
-				<view v-for="(item, index) of dataList">
-					<view class="todo-item flex-row align-center" @click="navigateToDetail(item)">
-						<view style="flex: 1">
-							<view class="flex-row align-center msg-title justify-between">
-								<view class="flex-row align-center">
-									<view class="dot" />
-									<view>{{ item.processInstance?.name }}</view>
-								</view>
-								<view class="msg-content">
-									{{ item.createTime ? dayjs(item.createTime).format('YYYY-MM-DD HH:mm') : '' }}
-								</view>
-							</view>
-							<view class="msg-content" style="margin-top: 5px">{{ $t('message.id') + ' ' + item.id }}
-							</view>
-						</view>
-					</view>
-					<view v-if="index !== dataList.length - 1" class="todo-divider" />
-				</view>
-			</template>
-			<template v-else-if="currentTab === 1">
-				<view v-for="(item, index) of dataList">
-					<view class="todo-item flex-row align-center" @click="navigateToDetail(item)">
-						<view style="flex: 1">
-							<view class="flex-row align-center msg-title justify-between">
-								<view style="margin-left: -8px">【{{ getStatusName(item.status) }}】</view>
-								<view class="msg-content">
-									{{ dayjs(item.startTime).format('YYYY-MM-DD HH:mm') }}
-								</view>
-							</view>
-							<view class="msg-content" style="margin-top: 5px">
-								{{ item.id + getApprovalUser(item) + getStatusName(item.status)  }}
-							</view>
-						</view>
-					</view>
-					<view v-if="index !== dataList.length - 1" class="todo-divider" />
-				</view>
-			</template>
-			<template v-else-if="currentTab === 2">
-				<view v-for="(item, index) of dataList" class="flex-col" @click="navigate(item)">
-					<view class="sys-msg-item flex-row" style="justify-content: center">
-						<image src="~@/static/message/system-message-logo.png"
-							style="width: 20px; height: 20px; margin-top: 5px" />
-						<div class="flex-col" style="flex: 1; margin-left: 10px">
-							<text class="msg-title">系统消息</text>
-							<text class="msg-content">{{ item.templateContent }}</text>
-						</div>
-						<text class="msg-content"
-							style="margin-top: 10px">{{ item.createTime ? dayjs(item.createTime).format('YYYY-MM-DD HH:mm') : '' }}</text>
-
-					</view>
-					<view v-if="index !== dataList.length - 1" class="divider" />
-				</view>
-			</template>
-		</view>
-	</z-paging>
+  <z-paging class="page" ref="paging" v-model="dataList" @query="loadData">
+    <template #top>
+      <uni-row style="padding-top: 8px">
+        <uni-badge
+          v-for="(item, index) of tabs"
+          :key="index"
+          absolute="rightTop"
+          :offset="[0, 4]"
+          :text="index === 2 ? unreadMessageCount : 0"
+          style="margin-right: 20px">
+          <text :class="index === currentTab ? 'tab-selected' : 'tab-normal'" @click="onTabChanged(index)">
+            {{ item }}
+          </text>
+        </uni-badge>
+      </uni-row>
+    </template>
+    <view class="list">
+      <template v-if="currentTab === 0">
+        <view v-for="(item, index) of dataList">
+          <view class="todo-item flex-row align-center" @click="navigateToDetail(item)">
+            <view style="flex: 1">
+              <view class="flex-row align-center msg-title justify-between">
+                <view class="flex-row align-center">
+                  <view class="dot" />
+                  <view>{{ item.processInstance?.name }}</view>
+                </view>
+                <view class="msg-content">
+                  {{ item.createTime ? dayjs(item.createTime).format('YYYY-MM-DD HH:mm') : '' }}
+                </view>
+              </view>
+              <view class="msg-content" style="margin-top: 5px">{{ $t('message.id') + ' ' + item.id }} </view>
+            </view>
+          </view>
+          <view v-if="index !== dataList.length - 1" class="todo-divider" />
+        </view>
+      </template>
+      <template v-else-if="currentTab === 1">
+        <view v-for="(item, index) of dataList">
+          <view class="todo-item flex-row align-center" @click="navigateToDetail(item)">
+            <view style="flex: 1">
+              <view class="flex-row align-center msg-title justify-between">
+                <view style="margin-left: -8px">【{{ getStatusName(item.status) }}】</view>
+                <view class="msg-content">
+                  {{ dayjs(item.startTime).format('YYYY-MM-DD HH:mm') }}
+                </view>
+              </view>
+              <view class="msg-content" style="margin-top: 5px">
+                {{ item.id + getApprovalUser(item) + getStatusName(item.status) }}
+              </view>
+            </view>
+          </view>
+          <view v-if="index !== dataList.length - 1" class="todo-divider" />
+        </view>
+      </template>
+      <template v-else-if="currentTab === 2">
+        <view v-for="(item, index) of dataList" class="flex-col" @click="navigate(item)">
+          <view class="sys-msg-item flex-row" style="justify-content: center">
+            <image src="~@/static/message/system-message-logo.png" style="width: 20px; height: 20px; margin-top: 5px" />
+            <div class="flex-col" style="flex: 1; margin-left: 10px">
+              <text class="msg-title">系统消息</text>
+              <text class="msg-content">{{ item.templateContent }}</text>
+            </div>
+            <text class="msg-content" style="margin-top: 10px">{{
+              item.createTime ? dayjs(item.createTime).format('YYYY-MM-DD HH:mm') : ''
+            }}</text>
+          </view>
+          <view v-if="index !== dataList.length - 1" class="divider" />
+        </view>
+      </template>
+    </view>
+  </z-paging>
 </template>
 
 <script setup>
-import {
-  getCurrentInstance, nextTick,
-  onMounted,
-  ref
-} from "vue"
-  import {
-    getMessageList, markReadMessage
-  } from "@/api/message"
-	import {
-		getTodoList,
-		getApprovalList
-	} from '@/api/task'
-	import dayjs from "dayjs";
-	import {
-		useDataDictStore
-	} from "@/store/modules/dataDict";
-  import { messageNavigate } from "@/utils/navigate";
-
-	const { appContext } = getCurrentInstance();
-	const t = appContext.config.globalProperties.$t;
-
-	const currentTab = ref(0)
-	const tabs = [t('message.tab1'), t('message.tab2'), t('message.tab3')]
-	const onTabChanged = (index) => {
-		currentTab.value = index
-		paging.value.reload()
-	}
-
-	const paging = ref(null)
-	const dataList = ref([])
-	const unreadMessageCount = ref(0)
-	const loadData = async (pageNo, pageSize) => {
-		try {
-			const params = {
-				pageNo,
-				pageSize
-			}
-			let response;
-			if (currentTab.value === 0) {
-				response = await getTodoList(params)
-			} else if (currentTab.value === 1) {
-				response = await getApprovalList(params)
-			} else {
-				response = await getMessageList(params)
-			}
-			unreadMessageCount.value = response.data.length
-			paging.value.complete(response.data.list)
-		} catch (e) {
-			console.log(e)
-			paging.value.complete(false)
-		}
-	}
-
-	const navigateToDetail = (item) => {
-		if (currentTab.value === 0) {
-			uni.navigateTo({
-				url: `/pages/message/detail/index?id=${item.id}&processInstanceId=${item.processInstanceId}`
-			})
-		} else {
-			uni.navigateTo({
-				url: `/pages/message/detail/index?processInstanceId=${item.id}`
-			})
-		}
-	}
+  import { getCurrentInstance, nextTick, onMounted, ref } from 'vue';
+  import { getMessageList, markReadMessage } from '@/api/message';
+  import { getTodoList, getApprovalList } from '@/api/task';
+  import dayjs from 'dayjs';
+  import { useDataDictStore } from '@/store/modules/dataDict';
+  import { messageNavigate } from '@/utils/navigate';
+  import { onLoad } from '@dcloudio/uni-app';
+
+  const { appContext } = getCurrentInstance();
+  const t = appContext.config.globalProperties.$t;
+
+  const currentTab = ref(0);
+  const tabs = [t('message.tab1'), t('message.tab2'), t('message.tab3')];
+  const onTabChanged = index => {
+    currentTab.value = index;
+    paging.value.reload();
+  };
+
+  const paging = ref(null);
+  const dataList = ref([]);
+  const unreadMessageCount = ref(0);
+  const loadData = async (pageNo, pageSize) => {
+    try {
+      const params = {
+        pageNo,
+        pageSize,
+      };
+      let response;
+      if (currentTab.value === 0) {
+        response = await getTodoList(params);
+      } else if (currentTab.value === 1) {
+        response = await getApprovalList(params);
+      } else {
+        response = await getMessageList(params);
+      }
+      unreadMessageCount.value = response.data.length;
+      paging.value.complete(response.data.list);
+    } catch (e) {
+      console.log(e);
+      paging.value.complete(false);
+    }
+  };
+
+  const navigateToDetail = item => {
+    if (currentTab.value === 0) {
+      uni.navigateTo({
+        url: `/pages/message/detail/index?id=${item.id}&processInstanceId=${item.processInstanceId}`,
+      });
+    } else {
+      uni.navigateTo({
+        url: `/pages/message/detail/index?processInstanceId=${item.id}`,
+      });
+    }
+  };
 
   // 根据 businessType 和 businessId 进行跳转
-  const navigate = (item) => {
-    markReadMessage(item.id)
+  const navigate = item => {
+    markReadMessage(item.id);
     messageNavigate({
       ...item.templateParams,
       id: item.templateParams.businessId,
       type: item.templateParams.businessType,
-    })
-  }
+    });
+  };
+
+  /**
+   * 获取当前审批人
+   * @param item
+   * @returns {string}
+   */
+  const getApprovalUser = item => {
+    if (item && item.tasks && item.tasks.length > 0 && item.tasks[0].assigneeUser) {
+      return item.tasks[0].assigneeUser.nickname;
+    } else {
+      return '';
+    }
+  };
 
-	/**
-	 * 获取当前审批人
-	 * @param item
-	 * @returns {string}
-	 */
-	const getApprovalUser = (item) => {
-		if (item && item.tasks && item.tasks.length > 0 && item.tasks[0].assigneeUser) {
-			return item.tasks[0].assigneeUser.nickname
-		} else {
-			return ''
-		}
-	}
-
-	const statusList = ref([]) // 审批状态列表
-	const getStatusName = (status) => {
+  const statusList = ref([]); // 审批状态列表
+  const getStatusName = status => {
     for (const item of statusList.value) {
       if (Number.parseInt(item.value) === Number.parseInt(status)) {
-        return item.label
+        return item.label;
       }
     }
-	}
+  };
+
+  const { getDataDictList } = useDataDictStore();
 
-	const { getDataDictList } = useDataDictStore()
-	onMounted(() => {
-		statusList.value = getDataDictList('bpm_process_instance_status')
-		uni.$once('update', () => nextTick(() => paging.value.reload()))
-	})
+  onLoad(options => {
+    currentTab.value = Number(options.currentTab) || 0;
+  });
+
+  onMounted(() => {
+    statusList.value = getDataDictList('bpm_process_instance_status');
+    uni.$once('update', () => nextTick(() => paging.value.reload()));
+  });
 </script>
 
 <style scoped lang="scss">
-	.page {
-		box-sizing: border-box;
-		padding: 10px !important;
-	}
-
-	.root {
-		width: 100%;
-		height: 100%;
-		position: relative;
-		box-sizing: border-box;
-		overflow: hidden;
-	}
-
-	.tab-selected {
-		color: #333333;
-		font-size: 18px;
-		font-weight: bold;
-	}
-
-	.tab-normal {
-		color: #666666;
-		font-size: 14px;
-	}
-
-	.list {
-		margin-top: 10px;
-		background-color: white;
-		border-radius: 6px;
-	}
-
-	.msg-title {
-		color: #333333;
-		font-size: 14px;
-		font-weight: 500;
-	}
-
-	.msg-content {
-		color: #999999;
-		font-size: 12px;
-	}
-
-	.sys-msg-item {
-		padding: 19px 20px 14px 15px;
-	}
-
-	.divider {
-		margin: 0 19px 0 45px;
-		height: 0.5px;
-		background-color: #CACCCF;
-	}
-
-	.dot {
-		width: 3px;
-		height: 3px;
-		border-radius: 2px;
-		background-color: #FF3B36;
-		margin-right: 6px;
-	}
-
-	.todo-item {
-		padding: 20px;
-		width: 100%;
-		height: auto;
-		box-sizing: border-box;
-	}
-
-	.todo-divider {
-		margin: 0 20px;
-		border-bottom: 0.5px solid #CACCCF;
-	}
-</style>
+  .page {
+    box-sizing: border-box;
+    padding: 10px !important;
+  }
+
+  .root {
+    width: 100%;
+    height: 100%;
+    position: relative;
+    box-sizing: border-box;
+    overflow: hidden;
+  }
+
+  .tab-selected {
+    color: #333333;
+    font-size: 18px;
+    font-weight: bold;
+  }
+
+  .tab-normal {
+    color: #666666;
+    font-size: 14px;
+  }
+
+  .list {
+    margin-top: 10px;
+    background-color: white;
+    border-radius: 6px;
+  }
+
+  .msg-title {
+    color: #333333;
+    font-size: 14px;
+    font-weight: 500;
+  }
+
+  .msg-content {
+    color: #999999;
+    font-size: 12px;
+  }
+
+  .sys-msg-item {
+    padding: 19px 20px 14px 15px;
+  }
+
+  .divider {
+    margin: 0 19px 0 45px;
+    height: 0.5px;
+    background-color: #cacccf;
+  }
+
+  .dot {
+    width: 3px;
+    height: 3px;
+    border-radius: 2px;
+    background-color: #ff3b36;
+    margin-right: 6px;
+  }
+
+  .todo-item {
+    padding: 20px;
+    width: 100%;
+    height: auto;
+    box-sizing: border-box;
+  }
+
+  .todo-divider {
+    margin: 0 20px;
+    border-bottom: 0.5px solid #cacccf;
+  }
+</style>

+ 162 - 0
pages/ruiDu/approval.vue

@@ -0,0 +1,162 @@
+<script setup>
+  import { onLoad } from '@dcloudio/uni-app';
+  import { ref, getCurrentInstance } from 'vue';
+  // -------------------------- 引入api接口 start--------------------------
+  import { getRuiDuReportDetail, approveRdDailyReport } from '@/api/ruiDu.js';
+  // -------------------------- 引入api接口 end--------------------------
+  // --------------------------引入组件----------------------------------
+  import reportInfo from './compontents/report-info.vue';
+  import reportForm from './compontents/report-form.vue';
+  // --------------------------引用全局变量$t-------------------------------
+  const { appContext } = getCurrentInstance();
+  const t = appContext.config.globalProperties.$t;
+  // ----------------------------选项卡----------------------------------
+  // 选项卡标题
+  const tabTitles = ref([t('ruiDu.taskInfo'), t('ruiDu.reportInfo')]);
+  const currentTab = ref(0);
+  const styleType = ref('text');
+  const activeColor = ref('#004098');
+  const onClickTabItem = e => {
+    currentTab.value = e.currentIndex;
+  };
+  // --------------------------页面变量----------------------------------
+  // 报告ID
+  const reportId = ref('');
+  // 报告详情数据
+  const detailData = ref({});
+  // 表单组件ref
+  const reportFormEditRef = ref(null);
+  // --------------------------生命周期函数----------------------------------
+  onLoad(option => {
+    // 页面加载
+    reportId.value = option.id; // 获取页面参数
+    // 获取日报详情
+    getReportDetail();
+  });
+  // -------------------------- 页面方法 --------------------------
+  // 获取日报详情
+  const getReportDetail = () => {
+    getRuiDuReportDetail({ id: reportId.value })
+      .then(res => {
+        if (res.code === 0) {
+          detailData.value = Object.assign(detailData.value, res.data || {});
+          console.log('🚀 ~ getReportDetail ~ detailData.value:', detailData.value);
+        }
+      })
+      .catch(res => {});
+  };
+
+  const infoRef = ref(null);
+
+  const loading = ref(false);
+
+  const handleApproval = async type => {
+    loading.value = true;
+
+    try {
+      const data = {
+        attachments: detailData.value.attachments || [],
+        opinion: infoRef.value.approvalOpinion,
+        auditStatus: type === 'pass' ? 20 : 30,
+        companyId: detailData.value.companyId,
+        costCenter: detailData.value.costCenter || '',
+        dynamicFields: detailData.value.dynamicFields || {},
+        deptId: detailData.value.deptId,
+        deviceIds: detailData.value.deviceIds,
+        startTime: `${detailData.value.startTime[0].toString().padStart(2, '0')}:${detailData.value.startTime[1]
+          .toString()
+          .padStart(2, '0')}`,
+        endTime: `${detailData.value.endTime[0].toString().padStart(2, '0')}:${detailData.value.endTime[1]
+          .toString()
+          .padStart(2, '0')}`,
+        externalRental: detailData.value.externalRental,
+        faultDowntime: detailData.value.faultDowntime || '',
+        malfunction: detailData.value.malfunction,
+        nextPlan: detailData.value.nextPlan,
+        id: detailData.value.id,
+        ...(detailData.value.platformId ? { platformId: detailData.value.platformId } : {}),
+        platformWell: detailData.value.platformWell,
+        productionStatus: detailData.value.productionStatus,
+        projectDepartment: detailData.value.projectDepartment || '',
+        rdStatus: detailData.value.rdStatus,
+        techniqueIds: detailData.value.techniqueIds,
+        taskId: detailData.value.taskId,
+        timeRange: ['1970-01-01T00:00:00.008Z', '1970-01-01T00:00:00.008Z'],
+      };
+
+      await approveRdDailyReport(data);
+
+      uni.showToast({
+        title: type === 'pass' ? '审批通过' : '审批驳回',
+        icon: 'success',
+      });
+
+      uni.reLaunch({ url: '/pages/home/index' });
+    } catch (error) {
+      console.log('🚀 ~ handleApproval ~ error:', error);
+      uni.showToast({ title: t('operation.failed'), icon: 'none' });
+    } finally {
+      loading.value = false;
+    }
+  };
+
+  // -------------------------- 页面方法 end --------------------------
+</script>
+
+<template>
+  <view class="page ridu-edit-page">
+    <view class="segmented-header">
+      <uni-segmented-control
+        :current="currentTab"
+        :values="tabTitles"
+        :style-type="styleType"
+        :active-color="activeColor"
+        @clickItem="onClickTabItem" />
+    </view>
+    <scroll-view scroll-y="true" class="segmented-content">
+      <!-- 工单信息 -->
+      <view class="work-order-info" v-show="currentTab === 0">
+        <report-info
+          ref="infoRef"
+          :report-id="reportId"
+          :report-data="detailData"
+          approval
+          :form-disable="detailData.auditStatus !== 10" />
+      </view>
+      <!-- 保养项列表 -->
+      <view class="work-order-bom-list" v-show="currentTab === 1">
+        <report-form ref="reportFormEditRef" :report-id="reportId" :report-data="detailData" :form-disable="true" />
+      </view>
+    </scroll-view>
+
+    <view class="segmented-footer" v-if="detailData.auditStatus === 10">
+      <view class="footer-btn">
+        <button :disabled="loading" :loading="loading" class="mini-btn" type="primary" @click="handleApproval('pass')">
+          审批通过
+        </button>
+        <button :disabled="loading" :loading="loading" class="mini-btn" type="warn" @click="handleApproval('reject')">
+          审批驳回
+        </button>
+      </view>
+    </view>
+  </view>
+</template>
+
+<style lang="scss" scoped>
+  @import '@/style/work-order-segmented.scss';
+  .page {
+    padding-bottom: 0;
+  }
+
+  .footer-btn {
+    display: flex;
+    justify-content: flex-end;
+    padding: 0 32px;
+
+    gap: 0 32px;
+
+    & > uni-button {
+      margin: 0;
+    }
+  }
+</style>

+ 108 - 150
pages/ruiDu/compontents/report-info.vue

@@ -4,11 +4,7 @@
     <view class="report-info-content form-content">
       <uni-forms ref="reportInfoRef" labelWidth="140px" :modelValue="reportData">
         <!-- 甲方 -->
-        <uni-forms-item
-          class="form-item"
-          :label="`${$t('ruiDu.firstParty')}:`"
-          name="manufactureName"
-        >
+        <uni-forms-item class="form-item" :label="`${$t('ruiDu.firstParty')}:`" name="manufactureName">
           <uni-easyinput
             style="text-align: right"
             type="textarea"
@@ -18,15 +14,10 @@
             :styles="{ disableColor: '#fff' }"
             :placeholder="selectPlaceholder"
             :disabled="props.formDisable"
-            :value="reportData.manufactureName"
-          />
+            :value="reportData.manufactureName" />
         </uni-forms-item>
         <!-- 合同号 -->
-        <uni-forms-item
-          class="form-item"
-          :label="`${$t('ruiDu.contractNo')}:`"
-          name="contractName"
-        >
+        <uni-forms-item class="form-item" :label="`${$t('ruiDu.contractNo')}:`" name="contractName">
           <uni-easyinput
             style="text-align: right"
             type="textarea"
@@ -36,15 +27,10 @@
             :styles="{ disableColor: '#fff' }"
             :placeholder="selectPlaceholder"
             :disabled="props.formDisable"
-            :value="reportData.contractName"
-          />
+            :value="reportData.contractName" />
         </uni-forms-item>
         <!-- 井号 -->
-        <uni-forms-item
-          class="form-item"
-          :label="`${$t('ruiDu.wellNo')}:`"
-          name="wellName"
-        >
+        <uni-forms-item class="form-item" :label="`${$t('ruiDu.wellNo')}:`" name="wellName">
           <uni-easyinput
             style="text-align: right"
             type="textarea"
@@ -54,15 +40,10 @@
             :styles="{ disableColor: '#fff' }"
             :placeholder="selectPlaceholder"
             :disabled="props.formDisable"
-            :value="reportData.wellName"
-          />
+            :value="reportData.wellName" />
         </uni-forms-item>
         <!-- 施工队伍 -->
-        <uni-forms-item
-          class="form-item"
-          :label="`${$t('ruiDu.constructionTeam')}:`"
-          name="constructionTeam"
-        >
+        <uni-forms-item class="form-item" :label="`${$t('ruiDu.constructionTeam')}:`" name="constructionTeam">
           <uni-easyinput
             style="text-align: right"
             type="textarea"
@@ -72,15 +53,10 @@
             :styles="{ disableColor: '#fff' }"
             :placeholder="selectPlaceholder"
             :disabled="props.formDisable"
-            :value="reportData.deptName"
-          />
+            :value="reportData.deptName" />
         </uni-forms-item>
         <!-- 施工地点 -->
-        <uni-forms-item
-          class="form-item"
-          :label="`${$t('ruiDu.constructionLocation')}:`"
-          name="location"
-        >
+        <uni-forms-item class="form-item" :label="`${$t('ruiDu.constructionLocation')}:`" name="location">
           <uni-easyinput
             style="text-align: right"
             type="textarea"
@@ -90,15 +66,10 @@
             :styles="{ disableColor: '#fff' }"
             :placeholder="selectPlaceholder"
             :disabled="props.formDisable"
-            :value="reportData.location"
-          />
+            :value="reportData.location" />
         </uni-forms-item>
         <!-- 工艺 -->
-        <uni-forms-item
-          class="form-item"
-          :label="`${$t('ruiDu.process')}:`"
-          name="techniqueNames"
-        >
+        <uni-forms-item class="form-item" :label="`${$t('ruiDu.process')}:`" name="techniqueNames">
           <uni-easyinput
             style="text-align: right"
             type="textarea"
@@ -108,15 +79,10 @@
             :styles="{ disableColor: '#fff' }"
             :placeholder="selectPlaceholder"
             :disabled="props.formDisable"
-            :value="reportData.techniqueNames"
-          />
+            :value="reportData.techniqueNames" />
         </uni-forms-item>
         <!-- 带班干部 -->
-        <uni-forms-item
-          class="form-item"
-          :label="`${$t('ruiDu.shiftLeader')}:`"
-          name="responsiblePersonNames"
-        >
+        <uni-forms-item class="form-item" :label="`${$t('ruiDu.shiftLeader')}:`" name="responsiblePersonNames">
           <uni-easyinput
             style="text-align: right"
             type="textarea"
@@ -126,63 +92,43 @@
             :styles="{ disableColor: '#fff' }"
             :placeholder="selectPlaceholder"
             :disabled="props.formDisable"
-            :value="reportData.responsiblePersonNames"
-          />
+            :value="reportData.responsiblePersonNames" />
         </uni-forms-item>
         <!-- 搬迁日期 -->
-        <uni-forms-item
-          class="form-item"
-          :label="`${$t('ruiDu.relocationDate')}:`"
-          name="relocationDate"
-        >
+        <uni-forms-item class="form-item" :label="`${$t('ruiDu.relocationDate')}:`" name="relocationDate">
           <uni-datetime-picker
             type="datetime"
             returnType="timestamp"
             :border="false"
             :placeholder="selectPlaceholder"
             :disabled="props.formDisable"
-            v-model="reportData.relocationDate"
-          >
+            v-model="reportData.relocationDate">
           </uni-datetime-picker>
         </uni-forms-item>
         <!-- 开工日期 -->
-        <uni-forms-item
-          class="form-item"
-          :label="`${$t('ruiDu.commencementDate')}:`"
-          name="commencementDate"
-        >
+        <uni-forms-item class="form-item" :label="`${$t('ruiDu.commencementDate')}:`" name="commencementDate">
           <uni-datetime-picker
             type="datetime"
             returnType="timestamp"
             :border="false"
             :placeholder="selectPlaceholder"
             :disabled="props.formDisable"
-            v-model="reportData.commencementDate"
-          >
+            v-model="reportData.commencementDate">
           </uni-datetime-picker>
         </uni-forms-item>
         <!-- 完工日期 -->
-        <uni-forms-item
-          class="form-item"
-          :label="`${$t('ruiDu.completionDate')}:`"
-          name="completionDate"
-        >
+        <uni-forms-item class="form-item" :label="`${$t('ruiDu.completionDate')}:`" name="completionDate">
           <uni-datetime-picker
             type="datetime"
             returnType="timestamp"
             :border="false"
             :placeholder="selectPlaceholder"
             :disabled="props.formDisable"
-            v-model="reportData.completionDate"
-          >
+            v-model="reportData.completionDate">
           </uni-datetime-picker>
         </uni-forms-item>
         <!-- 施工周期 -->
-        <uni-forms-item
-          class="form-item"
-          :label="`${$t('ruiDu.constructionCycle')}:`"
-          name="constructionPeriod"
-        >
+        <uni-forms-item class="form-item" :label="`${$t('ruiDu.constructionCycle')}:`" name="constructionPeriod">
           <uni-easyinput
             style="text-align: right"
             type="textarea"
@@ -192,15 +138,10 @@
             :styles="{ disableColor: '#fff' }"
             :placeholder="selectPlaceholder"
             :disabled="props.formDisable"
-            :value="reportData.constructionPeriod"
-          />
+            :value="reportData.constructionPeriod" />
         </uni-forms-item>
         <!-- 设备配置 -->
-        <uni-forms-item
-          class="form-item"
-          :label="`${$t('ruiDu.equipmentConfig')}:`"
-          name="deviceNames"
-        >
+        <uni-forms-item class="form-item" :label="`${$t('ruiDu.equipmentConfig')}:`" name="deviceNames">
           <uni-easyinput
             style="text-align: right"
             type="textarea"
@@ -210,8 +151,19 @@
             :styles="{ disableColor: '#fff' }"
             :placeholder="selectPlaceholder"
             :disabled="props.formDisable"
-            :value="reportData.deviceNames"
-          />
+            :value="reportData.deviceNames" />
+        </uni-forms-item>
+        <uni-forms-item class="form-item" :label="`审批意见:`" v-if="approval">
+          <uni-easyinput
+            style="text-align: right"
+            type="textarea"
+            :autoHeight="true"
+            :inputBorder="false"
+            :clearable="false"
+            :disabled="formDisable"
+            :styles="{ disableColor: '#fff' }"
+            :placeholder="inputPlaceholder"
+            v-model="approvalOpinion" />
         </uni-forms-item>
       </uni-forms>
     </view>
@@ -219,78 +171,84 @@
 </template>
 
 <script setup>
-import { onLoad, onReady, onBackPress } from "@dcloudio/uni-app";
-import {
-  ref,
-  reactive,
-  computed,
-  getCurrentInstance,
-  onMounted,
-  nextTick,
-} from "vue";
-import dayjs from "dayjs";
+  import { ref, computed, getCurrentInstance, onMounted, watch } from 'vue';
+
+  // -------------------------- 引入api接口 start--------------------------
+
+  // -------------------------- 引入api接口 end  --------------------------
+  // --------------------------引用组件-----start---------------------------
+  // --------------------------引用组件-----end-----------------------------
+  // --------------------------引用全局变量$t-------------------------------
+  const { appContext } = getCurrentInstance();
+  const t = appContext.config.globalProperties.$t;
+  // --------------------------引用字典项-----------------------------------
+  import { useDataDictStore } from '@/store/modules/dataDict';
+  const { getIntDictOptions, getStrDictOptions } = useDataDictStore();
+
+  // -------------------------接收父组件传递的参数--------------------------
+  const props = defineProps({
+    reportId: {
+      type: String,
+      default: '',
+    },
+    reportData: {
+      type: Object,
+      default: () => {},
+    },
+    formDisable: {
+      type: Boolean,
+      default: true, // 是否禁用表单
+    },
+    approval: {
+      type: Boolean,
+      default: false,
+    },
+  });
+  // -------------------------- 生命周期函数 --------------------------
+  onMounted(() => {
+    console.log('report-info mounted');
+  });
+  // -------------------------- 页面变量 --------------------------
+  // 表单ref
+  const formRef = ref(null);
+  // 选择占位符
+  const selectPlaceholder = computed(() => {
+    return props.formDisable ? ' ' : t('operation.PleaseSelect');
+  });
+
+  const inputPlaceholder = computed(() => {
+    return props.formDisable ? ' ' : t('operation.PleaseInput');
+  });
 
-// -------------------------- 引入api接口 start--------------------------
+  // -------------------------- 页面方法 --------------------------
 
-// -------------------------- 引入api接口 end  --------------------------
-// --------------------------引用组件-----start---------------------------
-import supplierChoose from "@/components/supplier/choose.vue";
-import deviceSingle from "@/components/device/single.vue";
-import localSearch from "@/components/local-search.vue";
-// --------------------------引用组件-----end-----------------------------
-// --------------------------引用全局变量$t-------------------------------
-const { appContext } = getCurrentInstance();
-const t = appContext.config.globalProperties.$t;
-// --------------------------引用字典项-----------------------------------
-import { useDataDictStore } from "@/store/modules/dataDict";
-const { getIntDictOptions, getStrDictOptions } = useDataDictStore();
+  const approvalOpinion = ref('');
 
-// -------------------------接收父组件传递的参数--------------------------
-const props = defineProps({
-  reportId: {
-    type: String,
-    default: "",
-  },
-  reportData: {
-    type: Object,
-    default: () => {},
-  },
-  formDisable: {
-    type: Boolean,
-    default: true, // 是否禁用表单
-  },
-});
-// -------------------------- 生命周期函数 --------------------------
-onMounted(() => {
-  console.log("report-info mounted");
-});
-// -------------------------- 页面变量 --------------------------
-// 表单ref
-const formRef = ref(null);
-// 选择占位符
-const selectPlaceholder = computed(() => {
-  return props.formDisable ? " " : t("operation.pleaseSelect");
-});
+  watch(
+    () => props.reportData.opinion,
+    newVal => {
+      approvalOpinion.value = newVal || '';
+    }
+  );
 
-// -------------------------- 页面方法 --------------------------
+  // -------------------------- 暴露给父组件的外部方法 --------------------------
+  defineExpose({ approvalOpinion });
 
-// -------------------------- 暴露给父组件的外部方法 --------------------------
-defineExpose({});
-// -------------------------- 事件派发 --------------------------
-const emit = defineEmits([]);
+  // -------------------------- 事件派发 --------------------------
+  const emit = defineEmits([]);
 </script>
 
 <style lang="scss" scoped>
-@import "@/style/work-order-detail.scss";
-.report-info {
-  height: 100%;
-  color: #333;
-}
-:deep(.uni-textarea-textarea:disabled),
-:deep(.uni-input-input:disabled) {
-  color: #333;
-}
-:deep(.uni-date-x) {
-  color: #333 ;
-}
+  @import '@/style/work-order-detail.scss';
+  .report-info {
+    height: 100%;
+    color: #333;
+  }
+  :deep(.uni-textarea-textarea:disabled),
+  :deep(.uni-input-input:disabled) {
+    color: #333;
+  }
+  :deep(.uni-date-x) {
+    color: #333;
+  }
 </style>

+ 276 - 297
pages/user/login.vue

@@ -4,20 +4,15 @@
       <image class="back-img" src="../../static/login/login-back.png"></image>
       <view class="login-text">
         <view class="text">
-          {{ $t("login.welcome") }}
+          {{ $t('login.welcome') }}
         </view>
         <view class="text">
-          {{ $t("app.appName") }}
+          {{ $t('app.appName') }}
         </view>
       </view>
     </view>
     <view class="login-form-wrap">
-      <uni-forms
-        class="login-form"
-        ref="formRef"
-        :modelValue="loginData"
-        :rules="loginRules"
-      >
+      <uni-forms class="login-form" ref="formRef" :modelValue="loginData" :rules="loginRules">
         <uni-forms-item name="username" class="margin-bt">
           <!-- type="number" -->
           <uni-easyinput
@@ -25,8 +20,7 @@
             v-model="loginData.username"
             :placeholder="$t('login.enterUsername')"
             :placeholderStyle="placeholderStyle"
-            :styles="inputStyles"
-          />
+            :styles="inputStyles" />
         </uni-forms-item>
         <uni-forms-item name="password" class="margin-bt">
           <uni-easyinput
@@ -34,19 +28,18 @@
             v-model="loginData.password"
             :placeholder="$t('login.enterPassword')"
             :placeholderStyle="placeholderStyle"
-            :styles="inputStyles"
-          />
+            :styles="inputStyles" />
         </uni-forms-item>
       </uni-forms>
       <button type="primary" @click="formSubmit(formRef)">
-        {{ $t("login.login") }}
+        {{ $t('login.login') }}
       </button>
       <view class="flex-row align-center justify-between">
         <view class="btn-text" @click="loginWithDingTalk">
-          {{ $t("login.loginWithDingTalk") }}
+          {{ $t('login.loginWithDingTalk') }}
         </view>
         <view class="btn-text" @click="openLanguagePopup">
-          {{ $t("login.languageChange") }}
+          {{ $t('login.languageChange') }}
         </view>
       </view>
     </view>
@@ -58,321 +51,307 @@
 </template>
 
 <script setup>
-import { reactive, ref, onMounted, nextTick, getCurrentInstance } from "vue";
-import { onLoad } from "@dcloudio/uni-app";
-// 引入接口api
-import {
-  appLogin,
-  dingTalkLogin,
-  dingTalkLoginH5,
-  getInfo,
-  getTokenByUserId,
-} from "@/api/login.js";
-// 引入配置文件
-import config from "@/utils/config";
-// 引入数据库操作
-import { saveUser } from "@/utils/appDb";
-// 引入本地存储操作
-import { setUserId, setToken, setDeptId, setUserInfo } from "@/utils/auth.js";
-// 引入组件
-import Upgrade from "@/components/upgrade.vue";
-import LanguagePopup from "@/components/language-popup.vue";
-// 引入钉钉JSAPI -- 仅在H5环境下使用
-let dd = null;
-// #ifdef H5
-import * as dingTalkJsApi from "dingtalk-jsapi";
-dd = dingTalkJsApi;
-// #endif
-
-const { appContext } = getCurrentInstance();
-const t = appContext.config.globalProperties.$t;
-const languagePopupRef = ref(null);
-
-const openLanguagePopup = () => {
-  languagePopupRef.value.open();
-};
+  import { reactive, ref, onMounted, nextTick, getCurrentInstance } from 'vue';
+  import { onLoad } from '@dcloudio/uni-app';
+  // 引入接口api
+  import { appLogin, dingTalkLogin, dingTalkLoginH5, getInfo, getTokenByUserId } from '@/api/login.js';
+  // 引入配置文件
+  import config from '@/utils/config';
+  // 引入数据库操作
+  import { saveUser } from '@/utils/appDb';
+  // 引入本地存储操作
+  import { setUserId, setToken, setDeptId, setUserInfo } from '@/utils/auth.js';
+  // 引入组件
+  import Upgrade from '@/components/upgrade.vue';
+  import LanguagePopup from '@/components/language-popup.vue';
+  // 引入钉钉JSAPI -- 仅在H5环境下使用
+  let dd = null;
+  // #ifdef H5
+  import * as dingTalkJsApi from 'dingtalk-jsapi';
+  dd = dingTalkJsApi;
+  // #endif
 
-// 判断当前环境是否在钉钉环境
-const isDingTalk = () => {
-  const ua = window.navigator.userAgent.toLowerCase();
-  console.log("🚀 ~ 当前环境 ~ ua:", ua);
-  return ua.includes("dingtalk") || ua.includes("dingtalkwork");
-};
+  const { appContext } = getCurrentInstance();
+  const t = appContext.config.globalProperties.$t;
+  const languagePopupRef = ref(null);
 
-const dingTalkAutoLogin = async () => {
-  // 判断是否在钉钉环境
-  if (!isDingTalk()) {
-    console.log("当前环境不是钉钉环境,无法自动登录");
-    return;
-  }
-  // 执行钉钉微应用免登逻辑
-  loginWithDingTalkH5();
+  const openLanguagePopup = () => {
+    languagePopupRef.value.open();
+  };
 
-}
+  // 判断当前环境是否在钉钉环境
+  const isDingTalk = () => {
+    const ua = window.navigator.userAgent.toLowerCase();
+    console.log('🚀 ~ 当前环境 ~ ua:', ua);
+    return ua.includes('dingtalk') || ua.includes('dingtalkwork');
+  };
 
-// 钉钉登录
-const loginWithDingTalk = async () => {
-  // #ifdef APP
-  const plugin = uni.requireNativePlugin("DingTalk");
-  // 钉钉登录,这里无法使用async,否则java端会报参数错误
-  plugin.login((res) => {
-    console.log(res);
-    if (res.success === 1) {
-      dingTalkLogin({
-        type: 20,
-        code: res.code,
-        state: res.state,
-      }).then((res) => {
-        console.log(res);
-        handleLoginSuccess(res);
-      });
-    } else if (res.success === 2) {
-      uni.showToast({ title: t("login.dingTalkError"), icon: "none" });
-      console.error("APP端钉钉登录失败:", res);
+  const dingTalkAutoLogin = async () => {
+    // 判断是否在钉钉环境
+    if (!isDingTalk()) {
+      console.log('当前环境不是钉钉环境,无法自动登录');
+      return;
     }
-  });
-  // #endif
-
-  // #ifdef H5
-  if (isDingTalk()) {
-    if (!dd) {
-    uni.showToast({ title: t("login.dingTalkJsapiMissing"), icon: "none" });
-    return;
-  }
+    // 执行钉钉微应用免登逻辑
     loginWithDingTalkH5();
-  } else {
-    console.log("当前是普通 H5 环境,无法使用钉钉登录");
-    uni.showToast({ title: t("login.h5DingTalk"), icon: "none" });
-  }
-  // #endif
-};
+  };
 
-const loginWithDingTalkH5 = async () => {
-  const corpId = config.default.corpId;
-  console.log("🚀 ~ loginWithDingTalkH5 ~ corpId:", corpId);
-  const clientId = config.default.clientId;
-  console.log("🚀 ~ loginWithDingTalkH5 ~ clientId:", clientId);
-
-  if (!corpId || !clientId) {
-    console.error("缺少必要参数");
-    return;
-  }
-  dd.requestAuthCode({
-    corpId,
-    clientId,
-    success: async (result) => {
-      console.log("🚀 ~ loginWithDingTalkH5 ~ result:", result);
-      const { code } = result;
-      dingTalkLoginH5({
-        type: 10,
-        state: new Date().getTime(),
-        code: code,
-      })
-        .then((res) => {
-          console.log("🚀 ~ loginWithDingTalkH5 ~ res:", res);
+  // 钉钉登录
+  const loginWithDingTalk = async () => {
+    // #ifdef APP
+    const plugin = uni.requireNativePlugin('DingTalk');
+    // 钉钉登录,这里无法使用async,否则java端会报参数错误
+    plugin.login(res => {
+      console.log(res);
+      if (res.success === 1) {
+        dingTalkLogin({
+          type: 20,
+          code: res.code,
+          state: res.state,
+        }).then(res => {
+          console.log(res);
           handleLoginSuccess(res);
-        })
-        .catch((err) => {
-          console.log("🚀 ~ loginWithDingTalkH5 ~ err:", err);
         });
-    },
-    fail: (err) => {
-      console.log("🚀 ~ loginWithDingTalkH5 ~ err:", err);
-      uni.showToast({
-        title: "获取code失败:" + JSON.stringify(err),
-        icon: "none",
-      });
-    },
-  });
-};
+      } else if (res.success === 2) {
+        uni.showToast({ title: t('login.dingTalkError'), icon: 'none' });
+        console.error('APP端钉钉登录失败:', res);
+      }
+    });
+    // #endif
 
-onLoad(async (options) => {
-  console.log(
-    "onLoad Login",
-    uni.getLocale(),
-    11,
-    uni.getStorageSync("language")
-  );
+    // #ifdef H5
+    if (isDingTalk()) {
+      if (!dd) {
+        uni.showToast({ title: t('login.dingTalkJsapiMissing'), icon: 'none' });
+        return;
+      }
+      loginWithDingTalkH5();
+    } else {
+      console.log('当前是普通 H5 环境,无法使用钉钉登录');
+      uni.showToast({ title: t('login.h5DingTalk'), icon: 'none' });
+    }
+    // #endif
+  };
 
-  console.log(options);
+  const loginWithDingTalkH5 = async () => {
+    const corpId = config.default.corpId;
+    console.log('🚀 ~ loginWithDingTalkH5 ~ corpId:', corpId);
+    const clientId = config.default.clientId;
+    console.log('🚀 ~ loginWithDingTalkH5 ~ clientId:', clientId);
 
-  // 保存钉钉消息传递的参数
-  if (options.userId) {
-    uni.setStorageSync("dingTalkJson", JSON.stringify(options));
-    const isLoggedIn = uni.getStorageSync("userId");
-    if (!isLoggedIn) {
-      const result = await getTokenByUserId(options.userId);
-      await handleLoginSuccess(result);
+    if (!corpId || !clientId) {
+      console.error('缺少必要参数');
+      return;
     }
-  }
-  // #ifdef H5
-  // 当前环境为H5时,判断是否是通过钉钉微应用打开的链接
-  // 获取当前Url地址
-  const url = window.location.href;
-  console.log("当前环境为H5时 当前Url地址:", url);
-  // 判断是否是通过钉钉微应用打开的链接
-  if (url.includes("/deepoil")) {
-    dingTalkAutoLogin();
-  }
-  // #endif
+    dd.requestAuthCode({
+      corpId,
+      clientId,
+      success: async result => {
+        console.log('🚀 ~ loginWithDingTalkH5 ~ result:', result);
+        const { code } = result;
+        dingTalkLoginH5({
+          type: 10,
+          state: new Date().getTime(),
+          code: code,
+        })
+          .then(res => {
+            console.log('🚀 ~ loginWithDingTalkH5 ~ res:', res);
+            handleLoginSuccess(res);
+          })
+          .catch(err => {
+            console.log('🚀 ~ loginWithDingTalkH5 ~ err:', err);
+          });
+      },
+      fail: err => {
+        console.log('🚀 ~ loginWithDingTalkH5 ~ err:', err);
+        uni.showToast({
+          title: '获取code失败:' + JSON.stringify(err),
+          icon: 'none',
+        });
+      },
+    });
+  };
 
+  onLoad(async options => {
+    console.log('onLoad Login', uni.getLocale(), 11, uni.getStorageSync('language'));
 
-});
+    console.log(options);
 
-onMounted(() => {
-  // console.log("onMounted");
-  // 检查是否需要显示语言选择弹窗
-  if (!uni.getStorageSync("language")) {
-    nextTick(() => {
-      openLanguagePopup();
-    });
-  }
-  // 检查是否已登录
-  const isLoggedIn = uni.getStorageSync("userId");
-  // console.log("isLoggedIn", isLoggedIn);
-  if (isLoggedIn) {
-    uni.switchTab({
-      url: "/pages/home/index",
-    });
-  }
-});
+    // 保存钉钉消息传递的参数
+    if (options.userId) {
+      uni.setStorageSync('dingTalkJson', JSON.stringify(options));
+      const isLoggedIn = uni.getStorageSync('userId');
+      if (!isLoggedIn) {
+        const result = await getTokenByUserId(options.userId);
+        await handleLoginSuccess(result);
+      }
+    }
+    // #ifdef H5
+    // 当前环境为H5时,判断是否是通过钉钉微应用打开的链接
+    // 获取当前Url地址
+    const url = window.location.href;
+    console.log('当前环境为H5时 当前Url地址:', url);
+    // 判断是否是通过钉钉微应用打开的链接
+    if (url.includes('/deepoil')) {
+      dingTalkAutoLogin();
+    }
+    // #endif
+  });
 
-const placeholderStyle = ref("color:#797979;font-weight:500;font-size:16px");
-const inputStyles = reactive({
-  backgroundColor: "#F0F3FB",
-  color: "#797979",
-});
-const loginData = reactive({
-  username: "",
-  password: "",
-});
-const loginRules = ref({
-  username: {
-    rules: [
-      {
-        required: true,
-        errorMessage: t("login.enterUsername"),
-      },
-    ],
-  },
-  password: {
-    rules: [
-      {
-        required: true,
-        errorMessage: t("login.enterPassword"),
-      },
-    ],
-  },
-});
+  onMounted(() => {
+    // console.log("onMounted");
+    // 检查是否需要显示语言选择弹窗
+    if (!uni.getStorageSync('language')) {
+      nextTick(() => {
+        openLanguagePopup();
+      });
+    }
+    // 检查是否已登录
+    const isLoggedIn = uni.getStorageSync('userId');
+    // console.log("isLoggedIn", isLoggedIn);
+    if (isLoggedIn) {
+      uni.switchTab({
+        url: '/pages/home/index',
+      });
+    }
+  });
 
-const formRef = ref();
-const formSubmit = async (formEl) => {
-  if (!formEl) return;
-  await formEl
-    .validate()
-    .then((res) => {
-      appLogin({
-        ...loginData,
-        // rememberMe: ,
-        // tenantName: ""
-      })
-        .then(async (result) => {
-          console.log("result,", result.data);
-          if (result) {
-            await saveUser({
-              name: loginData.username,
-              pwd: loginData.password,
-            });
-            await handleLoginSuccess(result);
-          }
-        })
-        .finally(() => {});
-    })
-    .catch((err) => {
-      console.log("err", err);
-    });
-};
+  const placeholderStyle = ref('color:#797979;font-weight:500;font-size:16px');
+  const inputStyles = reactive({
+    backgroundColor: '#F0F3FB',
+    color: '#797979',
+  });
+  const loginData = reactive({
+    username: '',
+    password: '',
+  });
+  const loginRules = ref({
+    username: {
+      rules: [
+        {
+          required: true,
+          errorMessage: t('login.enterUsername'),
+        },
+      ],
+    },
+    password: {
+      rules: [
+        {
+          required: true,
+          errorMessage: t('login.enterPassword'),
+        },
+      ],
+    },
+  });
 
-const handleLoginSuccess = async (result) => {
-  if (result) {
-    await setUserId(result.data.userId);
-    await setToken(result.data);
-    await getInfo().then(async (res) => {
-      // console.log('useres', res)
-      const data = JSON.stringify({
-        user: res.data.user,
-        roles: res.data.roles,
+  const formRef = ref();
+  const formSubmit = async formEl => {
+    if (!formEl) return;
+    await formEl
+      .validate()
+      .then(res => {
+        appLogin({
+          ...loginData,
+          // rememberMe: ,
+          // tenantName: ""
+        })
+          .then(async result => {
+            console.log('result,', result.data);
+            if (result) {
+              await saveUser({
+                name: loginData.username,
+                pwd: loginData.password,
+              });
+              await handleLoginSuccess(result);
+            }
+          })
+          .finally(() => {});
+      })
+      .catch(err => {
+        console.log('err', err);
       });
-      // console.log('data', data)
-      await setUserInfo(data);
-      await setDeptId(res.data.user.deptId);
+  };
 
-      await uni.switchTab({
-        url: "/pages/home/index",
+  const handleLoginSuccess = async result => {
+    if (result) {
+      await setUserId(result.data.userId);
+      await setToken(result.data);
+      await getInfo().then(async res => {
+        // console.log('useres', res)
+        const data = JSON.stringify({
+          user: res.data.user,
+          roles: res.data.roles,
+        });
+        // console.log('data', data)
+        await setUserInfo(data);
+        await setDeptId(res.data.user.deptId);
+
+        await uni.switchTab({
+          url: '/pages/home/index',
+        });
       });
-    });
-  }
-};
+    }
+  };
 </script>
 
 <style lang="scss" scoped>
-.login-top {
-  position: relative;
-  width: 100%;
-  height: 422rpx;
-}
-
-.back-img {
-  width: 100%;
-  height: 100%;
-}
+  .login-top {
+    position: relative;
+    width: 100%;
+    height: 422rpx;
+  }
 
-.login-text {
-  width: 100%;
-  height: 100%;
-  box-sizing: border-box;
-  position: absolute;
-  top: 0;
-  left: 0;
-  color: #ffffff;
-  font-size: 40rpx;
-  font-family: "Negreta,PingFang SC";
-  font-weight: 600;
-  padding: 0 56rpx;
-  display: flex;
-  justify-content: center;
-  flex-direction: column;
+  .back-img {
+    width: 100%;
+    height: 100%;
+  }
 
-  .text {
+  .login-text {
     width: 100%;
-    margin-bottom: 6rpx;
+    height: 100%;
+    box-sizing: border-box;
+    position: absolute;
+    top: 0;
+    left: 0;
+    color: #ffffff;
+    font-size: 40rpx;
+    font-family: 'Negreta,PingFang SC';
+    font-weight: 600;
+    padding: 0 56rpx;
+    display: flex;
+    justify-content: center;
+    flex-direction: column;
+
+    .text {
+      width: 100%;
+      margin-bottom: 6rpx;
+    }
   }
-}
 
-.margin-bt {
-  margin-bottom: 25px;
-}
+  .margin-bt {
+    margin-bottom: 25px;
+  }
 
-.login-form-wrap {
-  padding: 60rpx;
-}
+  .login-form-wrap {
+    padding: 60rpx;
+  }
 
-:deep(.uni-easyinput__content-input) {
-  height: 45px;
-}
+  :deep(.uni-easyinput__content-input) {
+    height: 45px;
+  }
 
-:deep(.uni-input-input) {
-  color: #999999 !important;
-}
+  :deep(.uni-input-input) {
+    color: #999999 !important;
+  }
 
-uni-button[type="primary"] {
-  background: #004098;
-}
+  uni-button[type='primary'] {
+    background: #004098;
+  }
 
-.btn-text {
-  color: #004098;
-  margin-top: 20px;
-  font-size: 14px;
-  font-weight: 500;
-}
+  .btn-text {
+    color: #004098;
+    margin-top: 20px;
+    font-size: 14px;
+    font-weight: 500;
+  }
 </style>

+ 19 - 15
utils/navigate.js

@@ -1,18 +1,18 @@
-import { getInspectOrderGet } from "@/api/inspection";
-import { getRepairDetail } from "@/api/repair";
+import { getInspectOrderGet } from '@/api/inspection';
+import { getRepairDetail } from '@/api/repair';
 
 /**
  * 根据不同类型的消息跳转目标页面
  * @param data
  */
-export const messageNavigate = async (data) => {
+export const messageNavigate = async data => {
   if (!data.userId) {
-    data.userId = "";
+    data.userId = '';
   }
-  if (data.type === "generateInspect") {
+  if (data.type === 'generateInspect') {
     // 巡检工单填写页面
     const detail = (await getInspectOrderGet({ id: data.id })).data;
-    if (detail.status === "finished") {
+    if (detail.status === 'finished') {
       uni.navigateTo({
         url: `/pages/inspection/detail?id=${data.id}&reloginUserId=${data.userId}`,
       });
@@ -21,15 +21,15 @@ export const messageNavigate = async (data) => {
         url: `/pages/inspection/edit?id=${data.id}&reloginUserId=${data.userId}`,
       });
     }
-  } else if (data.type === "failureReport") {
+  } else if (data.type === 'failureReport') {
     // 故障上报审批页面
     uni.navigateTo({
       url: `/pages/message/detail/index?processInstanceId=${data.id}&reloginUserId=${data.userId}`,
     });
-  } else if (data.type === "generateMaintain") {
+  } else if (data.type === 'generateMaintain') {
     // 维修工单填写页面
     const detail = (await getRepairDetail({ id: data.id })).data;
-    if (detail.status !== "tx") {
+    if (detail.status !== 'tx') {
       uni.navigateTo({
         url: `/pages/repair/detail?id=${data.id}&reloginUserId=${data.userId}`,
       });
@@ -38,17 +38,17 @@ export const messageNavigate = async (data) => {
         url: `/pages/repair/edit?id=${data.id}&reloginUserId=${data.userId}`,
       });
     }
-  } else if (data.type === "maintainOut") {
+  } else if (data.type === 'maintainOut') {
     // 维修工单委外流程审批页面
     uni.navigateTo({
       url: `/pages/message/detail/index?processInstanceId=${data.id}&reloginUserId=${data.userId}`,
     });
-  } else if (data.type === "generateMaintenance") {
+  } else if (data.type === 'generateMaintenance') {
     // 保养工单填写页面
     uni.navigateTo({
       url: `/pages/maintenance/edit?id=${data.id}&reloginUserId=${data.userId}`,
     });
-  } else if (data.type === "generateOperation") {
+  } else if (data.type === 'generateOperation') {
     // 运行记录填写页面
     const json = JSON.stringify({
       deptId: data.deptId,
@@ -61,9 +61,13 @@ export const messageNavigate = async (data) => {
     });
     // {0: '待填写', 1: '已完成', 2: '填写中', 3: '忽略'}
     uni.navigateTo({
-      url: `/pages/recordFilling/detail?view=${
-        data.orderStatus % 2 == 0 ? 1 : 0
-      }&param=${json}&reloginUserId=${data.userId}`,
+      url: `/pages/recordFilling/detail?view=${data.orderStatus % 2 == 0 ? 1 : 0}&param=${json}&reloginUserId=${
+        data.userId
+      }`,
+    });
+  } else if (data.type === 'rdReportApproval') {
+    uni.navigateTo({
+      url: `/pages/ruiDu/approval?id=${data.businessId}`,
     });
   }
 };