Răsfoiți Sursa

+ 用户隐私协议

chen.cheng 7 luni în urmă
părinte
comite
d791b379e6

+ 2 - 2
.env.dev

@@ -1,5 +1,5 @@
 //.env.dev
 
-VITE_BASE_URL=http://aiot.xt.wenhq.top:8083/api
+VITE_BASE_URL=https://www.lj-info.com:8090/aiot-api
 
-VITE_IMG_CDN=http://aiot.xt.wenhq.top:8083/
+VITE_IMG_CDN=https://www.lj-info.com:8090/

+ 6 - 1
src/api/workorder.js

@@ -49,6 +49,11 @@ export const handleWorkOrder = async (id) => {
 }
 
 export const assignWorkOrder = async (param) => {
-  return await post(`orderWork/assign`, param)
+  return await post(`/orderWork/assign`, param)
+}
+
+
+export const endWorkOrder = async (param) => {
+  return await post(`/orderWork/end`, param)
 }
 

+ 1 - 1
src/components/da-tree/utils.ts

@@ -47,7 +47,7 @@ export function getAllNodes(list, type, value, packDisabledkey = true) {
   for (let i = 0; i < list.length; i++) {
     const item = list[i]
     if (item[type] === value) {
-      if ((packDisabledkey && item.disabled) || !item.disabled) {
+      if (item.dataNode && ((packDisabledkey && item.disabled) || !item.disabled)) {
         res.push(item)
       }
     }

+ 1 - 0
src/manifest.json

@@ -102,6 +102,7 @@
   "quickapp": {},
   "mp-weixin": {
     "appid": "wxf385eefdd03327fd",
+    "__usePrivacyCheck__" : true,
     "setting": {
       "urlCheck": false,
       "es6": true,

+ 47 - 15
src/pages/login/index.vue

@@ -50,10 +50,17 @@
       <up-button @click="submit" style="margin-top: 20rpx;">登录</up-button>
     </view>
     <view class="buttom">
-      <view class="hint">
-        登录代表同意
-        <text class="link">用户协议、隐私政策,</text>
-        并授权使用您的账号信息(如昵称、头像、收获地址)以便您统一管理
+      <view class="checkbox">
+        <up-checkbox
+            :customStyle="{marginBottom: '8px'}"
+            name="agree"
+            usedAlone
+            v-model:checked="model.isChecked"
+        >
+        </up-checkbox>
+        <text>我已阅读并同意</text>
+        <text class="agreement-title" @click='openAgreement'>《用户隐私协议》</text>
+        <privacy v-if='visible' @getVisible='getVisible'/>
       </view>
     </view>
   </view>
@@ -62,17 +69,20 @@
 <script setup lang="ts">
 import login_bg from '@/static/aiot/login_bg.png'
 import {reactive, ref} from 'vue';
-import {iotLogin} from "@/api/usr";
+import {iotLogin} from "@/api/usr.js";
 import {Base64} from "js-base64";
-import {reloadPage, setToken, setUserInfo} from "@/util";
+import {reloadPage, setToken, setUserInfo} from "@/util/index.js";
+import Privacy from "@/pages/login/privacy.vue";
 
 // 使用 reactive 创建响应式状态
 const model = reactive({
   userInfo: {
     name: '',
     pwd: '',
-  }
+  },
+  isChecked: false,
 });
+const visible = ref(false);
 const rules = reactive({
   'userInfo.name': {
     type: 'string',
@@ -94,6 +104,11 @@ const uFormRef = ref(null);
 function submit() {
   uFormRef.value.validate().then(async valid => {
     if (valid) {
+      if (!model.isChecked) {
+        // uni.$u.toast('请阅读并同意用户协议')
+        visible.value = true;
+        return;
+      }
       const params = {
         "grant_type": "password_login",
         "username": model.userInfo.name,
@@ -119,6 +134,15 @@ function submit() {
     uni.$u.toast('校验失败')
   });
 }
+
+function openAgreement() {
+  uni.openPrivacyContract()
+}
+
+function getVisible(visib) {
+  visible.value = visib;
+  model.isChecked = true;
+}
 </script>
 
 <style lang="scss" scoped>
@@ -193,6 +217,20 @@ function submit() {
   }
 
   .buttom {
+    .checkbox {
+      display: flex;
+      align-items: center;
+      font-size: 24rpx;
+
+      .checkbox-box {
+        margin-right: 10rpx;
+      }
+
+      :deep(.u-checkbox__icon-wrap) {
+        border-radius: 19px;
+      }
+    }
+
     .loginType {
       display: flex;
       padding: 350rpx 150rpx 150rpx 150rpx;
@@ -207,14 +245,8 @@ function submit() {
       }
     }
 
-    .hint {
-      padding: 20rpx 40rpx;
-      font-size: 20rpx;
-      color: $u-tips-color;
-
-      .link {
-        color: $u-warning;
-      }
+    .agreement-title {
+      color: #007aff;
     }
   }
 }

+ 120 - 0
src/pages/login/privacy.vue

@@ -0,0 +1,120 @@
+<template>
+  <view class="comp-container">
+    <view class="dialog">
+      <view class="title">用户隐私保护提示</view>
+      <view class="desc">
+        感谢您使用本小程序,在使用前您应当阅读并同意
+        <text class="privacy" @click="handleOpenPrivacyContract">《用户隐私保护指引》</text>
+        ,当点击同意,即表示您已理解并同意该条款内容,该条款将对您产生法律约束力;如您不同意,将无法继续使用小程序相关功能。
+      </view>
+      <view class="footer">
+        <button type="default" class="btn disagree" @click="handleDisagree">不同意</button>
+        <button type="default" open-type="agreePrivacyAuthorization" class="btn agree"
+                @agreeprivacyauthorization="handleAgree">同意
+        </button>
+      </view>
+    </view>
+    <!--    https://juejin.cn/post/7376463238404227081-->
+  </view>
+</template>
+
+<script setup>
+import {defineEmits} from 'vue'
+
+const emit = defineEmits(['getVisible'])
+const visible = null;
+
+function handleDisagree() {
+  // 处理用户不同意隐私协议的逻辑
+  emit('getVisible', false);
+  uni.exitMiniProgram()
+}
+
+function handleAgree() {
+  // 处理用户同意隐私协议的逻辑
+  emit('getVisible', false);
+}
+
+function handleOpenPrivacyContract() {
+  uni.openPrivacyContract()
+}
+</script>
+<style lang="scss" scoped>
+.comp-container {
+  position: fixed;
+  top: 0;
+  right: 0;
+  left: 0;
+  bottom: 0;
+  background-color: rgba(0, 0, 0, 0.6);
+  z-index: 999;
+}
+
+.dialog {
+  color: #333;
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  background-color: #fff;
+  border-radius: 20rpx;
+  padding: 50rpx 40rpx;
+  width: 560rpx;
+  box-sizing: border-box;
+
+  .title {
+    width: 100%;
+    color: #000;
+    text-align: center;
+    font-size: 32rpx;
+    font-weight: 650;
+    box-sizing: border-box;
+  }
+
+  .desc {
+    line-height: 40rpx;
+    box-sizing: border-box;
+    margin-top: 50rpx;
+    font-size: 26rpx;
+
+    .privacy {
+      color: #2f80ed;
+    }
+  }
+
+  .footer {
+    width: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    margin-top: 30rpx;
+
+    .btn {
+      display: flex;
+      align-items: center;
+      color: #FFF;
+      font-size: 28rpx;
+      font-weight: 500;
+      line-height: 80rpx;
+      text-align: center;
+      height: 80rpx;
+      border-radius: 10rpx;
+      border: none;
+      background: #07c160;
+      flex: 1;
+      justify-content: center;
+
+      &:nth-last-child(1) {
+        margin-left: 30rpx;
+      }
+
+      &.disagree {
+        color: #333;
+        background: #f2f2f2;
+      }
+    }
+  }
+
+}
+
+</style>

+ 59 - 72
src/pages/my/index.vue

@@ -1,85 +1,72 @@
 <template>
-	<view>
-		<up-navbar :fixed="false" :is-back="true" title=" " :border-bottom="false">
-			<view class="u-flex u-row-right" style="width: 100%;">
-				<view class="camera u-flex u-row-center">
-					<up-icon name="camera-fill" color="#000000" size="48"></up-icon>
-				</view>
-			</view>
-		</up-navbar>
-		<view class="u-flex u-flex-y-center u-flex-around user-box u-p-l-30 u-p-r-20 u-p-b-30">
-			<view class="u-m-r-10">
-				<up-avatar :src="pic" size="140"></up-avatar>
-			</view>
-			<view class="u-flex-1">
-				<view class="u-font-18 u-p-b-20">uview plus</view>
-				<view class="u-font-14 u-tips-color">微信号:test</view>
-			</view>
-			<view class="u-m-l-10 u-p-10">
-				<up-icon name="scan" color="#969799" size="28"></up-icon>
-			</view>
-			<view class="u-m-l-10 u-p-10">
-				<up-icon name="arrow-right" color="#969799" size="28"></up-icon>
-			</view>
-		</view>
-		
-		<view class="u-m-t-20">
-			<up-cell-group>
-				<up-cell icon="rmb-circle" title="支付"></up-cell>
-			</up-cell-group>
-		</view>
-		
-		<view class="u-m-t-20">
-			<up-cell-group>
-				<up-cell icon="star" title="收藏"></up-cell>
-				<up-cell icon="photo" title="相册"></up-cell>
-				<up-cell icon="coupon" title="卡券"></up-cell>
-				<up-cell icon="heart" title="关注"></up-cell>
-			</up-cell-group>
-		</view>
-		
-		<view class="u-m-t-20">
-			<up-cell-group>
-				<up-cell icon="setting" title="设置"></up-cell>
-			</up-cell-group>
-		</view>
-	</view>
+  <view>
+    <view class="u-flex u-flex-y-center u-flex-around user-box u-p-l-30 u-p-r-20 u-p-b-30 u-m-t-30">
+      <view class="u-m-r-10">
+        <up-avatar :src="state.pic" size="70"></up-avatar>
+      </view>
+      <view class="u-flex-1">
+        <view class="u-font-18 u-p-b-20">{{ state.usr.nickname }}</view>
+      </view>
+      <view class="u-m-l-10 u-p-10" @click="exitApp">
+        <up-icon name="arrow-right" color="#969799" size="28"></up-icon>
+      </view>
+    </view>
+
+    <view class="u-m-t-20">
+      <up-cell-group>
+        <up-cell icon="heart" title="关注"></up-cell>
+      </up-cell-group>
+    </view>
+
+    <view class="u-m-t-20">
+      <up-cell-group>
+        <up-cell icon="setting" title="设置"></up-cell>
+      </up-cell-group>
+    </view>
+  </view>
 </template>
 
-<script>
-	export default {
-		data() {
-			return {
-				pic:'https://uviewui.com/common/logo.png',
-				show:true
-			}
-		},
-		onLoad() {
-			
-		},
-		methods: {
-			
-		}
-	}
+<script lang="ts" setup>
+import {reactive} from 'vue'
+import {onLoad} from '@dcloudio/uni-app'
+import {exit, getUserInfo} from "@/util/index.js";
+
+const state = reactive({
+  pic: 'https://uviewui.com/common/logo.png',
+  show: true,
+  usr: {}
+})
+onLoad(() => {
+  const usrInfo = getUserInfo()
+  state.usr = usrInfo
+})
+const exitApp = () => {
+  exit();
+  uni.reLaunch({
+    url: '/pages/login/index'
+  })
+}
 </script>
 
 <style lang="scss">
-page{
-	background-color: #ededed;
+page {
+  background-color: #ededed;
 }
 
-.camera{
-	width: 54px;
-	height: 44px;
-	
-	&:active{
-		background-color: #ededed;
-	}
+.camera {
+  width: 54px;
+  height: 44px;
+
+  &:active {
+    background-color: #ededed;
+  }
 }
-.user-box{
-	background-color: #fff;
+
+.user-box {
+  background-color: #fff;
 }
+
 .u-cell-group {
-	background-color: #fff;
+  background-color: #fff;
 }
 </style>

+ 6 - 3
src/pages/workbench/index.vue

@@ -35,7 +35,7 @@
         </view>
       </view>
       <appctl/>
-      <usrsubmit/>
+      <usrsubmit :tag="timestamp"/>
     </view>
   </view>
 </template>
@@ -54,6 +54,7 @@ export default {
     return {
       list,
       date: `${dayjs().format('MM月DD日')} ${formatWeekday(dayjs().format('d'))}`,
+      timestamp: Date.now()
     }
   },
   computed: {
@@ -67,9 +68,11 @@ export default {
     }
   },
   onPullDownRefresh() {
-    setTimeout(function () {
+    this.timestamp = Date.now();
+    console.log('onPullDownRefresh', Date.now());
+    setTimeout(() => {
       uni.stopPullDownRefresh();
-    }, 100);
+    }, 2000);
   },
   methods: {
     submit() {

+ 12 - 2
src/pages/workbench/usrsubmit.vue

@@ -68,13 +68,19 @@
 
 import Panel from "@/components/pannel/index.vue";
 import tag from "@/static/aiot/icon/tag.svg";
-import {ref} from 'vue';
+import {ref, watch} from 'vue';
 import {onLoad, onShow} from '@dcloudio/uni-app';
-import {getMyOrderWork, getMyOrderWorkTodo} from "@/api/workorder.js";
+import {getMyOrderWorkTodo} from "@/api/workorder.js";
 import {formatTxt, navigateTo} from "@/util/index.js";
 import {valueToConst} from "@/common/consts/CommonConst.js";
 import {WorkOrderLevel} from "@/common/consts/WorkOrderConst.js";
 
+const props = defineProps({
+  tag: {
+    type: String,
+    default: tag
+  }
+});
 const indexList = ref([]);
 onLoad(() => {
   loadmore();
@@ -92,12 +98,16 @@ const loadmore = () => {
     indexList.value = records;
   });
 };
+watch(() => props.tag, () => {
+  loadmore();
+})
 const handleWorkOrder = (item) => {
   navigateTo({
     url: "/pages/workbenchsub/workorder/detail",
     param: item
   })
 };
+
 </script>
 
 <script lang="ts">

+ 49 - 29
src/pages/workbenchsub/workorder/detail.vue

@@ -147,7 +147,7 @@
         <view
             class="def-btn"
             v-if="[WorkOrderStat.UN_HANDLE.value,WorkOrderStat.IN_HANDLE.value].includes(state.orderInfo.status )"
-            @click="state.toUsrShow=true"
+            @click="state.toUsrShow=true;state.toUsrCb = assignWorkOrderCb;"
         >
           指派
         </view>
@@ -238,7 +238,6 @@
                 border="none"
             ></up-input>
           </up-form-item>
-
           <up-form-item
               label="是否已解决"
               borderBottom
@@ -253,14 +252,14 @@
             <up-switch v-model="state.model.order.rewrite"></up-switch>
           </up-form-item>
           <up-form-item
-              label="报废时间"
-              prop="order.startDate"
+              label="处理人"
+              v-if="state.model.order.rewrite && !state.model.order.isSolve"
               borderBottom
-              :required="true"
-              @click="state.toUsrShow = true; hideKeyboard()"
+              @click="state.toUsrShow = true;state.toUsrCb = rewriteWorkOrderCb; hideKeyboard()"
           >
             <up-input
                 disabled
+                :modelValue="state.model.order.handleUser2"
                 disabledColor="#ffffff"
                 placeholder="其请选择处理人"
                 border="none"
@@ -272,7 +271,7 @@
             </template>
           </up-form-item>
           <up-form-item>
-            <text class="u-demo-block__title">问题图片</text>
+            <text class="u-demo-block__title">解决图片</text>
             <up-upload
                 :fileList="state.model.order.files"
                 @afterRead="afterRead"
@@ -283,8 +282,7 @@
                 :previewFullImage="true"
             ></up-upload>
           </up-form-item>
-
-          <up-button @click="submit" style="margin-top: 20rpx;">提交</up-button>
+          <up-button @click="endWorkOrderHandle" style="margin-top: 20rpx;">提交</up-button>
         </up-form>
       </view>
     </up-action-sheet>
@@ -303,10 +301,8 @@
             valueField="id"
             defaultExpandAll
             :defaultCheckedKeys="defaultCheckedKeysValue"
-            @change="handleTreeChange"
-            @expand="handleExpandChange"
         />
-        <up-button @click="confirmToUsr" style="margin-top: 20rpx;">指派</up-button>
+        <up-button @click="()=>confirmToUsr(state.toUsrCb)" style="margin-top: 20rpx;">指派</up-button>
       </view>
     </up-action-sheet>
     <overlay-tip ref="overlay"/>
@@ -325,6 +321,7 @@ import {onMounted, reactive, ref, watch} from 'vue';
 import {onLoad} from "@dcloudio/uni-app";
 import {
   assignWorkOrder,
+  endWorkOrder,
   getWorkOrderDetail,
   getWorkOrderSteps,
   handleWorkOrder,
@@ -345,14 +342,6 @@ const overlay = ref(null)
 const defaultCheckedKeysValue = ref(['211', '222'])
 const roomTreeData = ref([])
 
-function handleTreeChange(allSelectedKeys, currentItem) {
-  console.log('handleTreeChange ==>', allSelectedKeys, currentItem)
-}
-
-function handleExpandChange(expand, currentItem) {
-  console.log('handleExpandChange ==>', expand, currentItem)
-}
-
 const state = reactive({
   showDisableModal: false,
   showAcceptModal: false,
@@ -366,6 +355,7 @@ const state = reactive({
     order: {
       isSolve: true,
       rewrite: false,
+      files: []
     }
   },
   steps: []
@@ -422,17 +412,10 @@ const refresh = () => {
     state.steps = data
   })
 }
-const confirmToUsr = () => {
-  if (!DaTreeRef.value || !DaTreeRef.value.getCheckedKeys() || DaTreeRef.value.getCheckedKeys().length === 0) {
-    uToastRef.value.show({
-      type: 'warning',
-      message: "请选择处理人",
-    })
-    return;
-  }
+const assignWorkOrderCb = () => {
   overlay.value.load({})
   assignWorkOrder({
-    handleUser: DaTreeRef.value.getCheckedKeys()[0],
+    handleUser: DaTreeRef.value.getCheckedNodes()[0].key,
     id: order.value
   }).then(() => {
     state.toUsrShow = false;
@@ -450,6 +433,43 @@ const confirmToUsr = () => {
     overlay.value.end()
   })
 }
+
+const endWorkOrderHandle = () => {
+  debugger
+  endWorkOrder({
+    ...state.model.order,
+    img: JSON.stringify(state.model.order.files),
+    solveImg: JSON.stringify(state.model.order.files),
+    id: order.value
+  }).then(() => {
+    uToastRef.value.show({
+      type: 'default',
+      message: "操作成功",
+      complete() {
+        uni.$emit('refreshData', {refresh: true});
+        uni.navigateBack({
+          delta: 1
+        })
+      }
+    });
+  })
+}
+
+const rewriteWorkOrderCb = () => {
+  state.model.order.handleUser = DaTreeRef.value.getCheckedNodes()[0].key;
+  state.model.order.handleUser2 = DaTreeRef.value.getCheckedNodes()[0].name;
+}
+const confirmToUsr = (cb = () => {
+}) => {
+  if (!DaTreeRef.value || !DaTreeRef.value.getCheckedNodes() || DaTreeRef.value.getCheckedNodes().length === 0) {
+    uToastRef.value.show({
+      type: 'warning',
+      message: "请选择处理人",
+    })
+    return;
+  }
+  cb();
+}
 const getDeviceStatus = (dataDetail) => {
   let statusMsg = []
   if (dataDetail.status === 1 && isLessThanNow(dataDetail.estimatedStartTime)) {