增加接口联调

This commit is contained in:
xuli
2025-11-27 18:18:19 +08:00
parent 9b4ccd7811
commit c8ad7a076c
20 changed files with 1745 additions and 1380 deletions

View File

@@ -1,9 +1,25 @@
import request from "@/utils/request" import request from "@/utils/request"
// 查询今日任务列表 // 按日查询任务列表
export function taskTodayList(data) { export function taskList(data) {
return request.post({ return request.post({
url: '/acc/message/notify/detail', url: '/patrol/patroltask/list',
data
})
}
// 按月查询任务表列表
export function taskListMonth(data) {
return request.post({
url: '/patrol/patroltask/listm',
data
})
}
// 按条件搜索任务列表
export function taskLists(data) {
return request.post({
url: '/patrol/patroltask/lists',
data data
}) })
} }
@@ -11,7 +27,92 @@ export function taskTodayList(data) {
// 查询任务详情 // 查询任务详情
export function taskDetail(data) { export function taskDetail(data) {
return request.post({ return request.post({
url: '/acc/message/notify/detail', url: '/patrol/patroltask/detail',
data data
}) })
} }
// 批量提交检查点的结果
export function submitResult(data) {
return request.post({
url: '/patrol/patroltask/submitresult',
data
})
}
// 提交任务
export function submitTask(data) {
return request.post({
url: '/patrol/patroltask/submittask',
data
})
}
// 查询任务检查项详情
export function taskGroupDetail(data) {
return request.post({
url: '/patrol/patroltask/taskgroup',
data
})
}
// 异常上报表管理
export function problemDetail(data) {
return request.post({
url: '/patrol/patrolproblem/detail',
data
})
}
// 查询异常上报表列表
export function problemList(data) {
return request.post({
url: '/patrol/patrolproblem/list',
data
})
}
// 添加问题上报
export function problemAdd(data) {
return request.post({
url: '/patrol/patrolproblem/addproblem',
data
})
}
// 编辑问题
export function problemEdit(data) {
return request.post({
url: '/patrol/patrolproblem/editproblem',
data
})
}
// 删除问题
export function problemDel(data) {
return request.post({
url: '/patrol/patrolproblem/delproblem',
data
})
}
// 添加追踪记录
export function problemAddLog(data) {
return request.post({
url: '/patrol/patrolproblem/addproblemlog',
data
})
}
// 图片上传
export function minioUpload(data) {
return request.uploadFile({
url: '/patrol/minio/upload',
...data
})
}
// 获取minio参数
export function minioParam(data) {
return request.post({
url: '/patrol/minio/param',
...data
})
}

View File

@@ -4,7 +4,7 @@
<view class="model-top" v-if="title">{{title}}</view> <view class="model-top" v-if="title">{{title}}</view>
<view :class="{'model-middle':true,'m-height':!title}">{{contents}}</view> <view :class="{'model-middle':true,'m-height':!title}">{{contents}}</view>
<view class="model-bottom"> <view class="model-bottom">
<button type="primary" class="btn-cancel" @click="handleCancel" v-if="btnFlag2">Cancel</button> <button type="primary" class="btn-cancel" @click="handleCancel" v-if="btnFlag2">取消</button>
<button type="default" class="btn-green" @click="handleConfirm" v-if="btnFlag" :loading="loading" :disabled="loading">{{btnTxt}}</button> <button type="default" class="btn-green" @click="handleConfirm" v-if="btnFlag" :loading="loading" :disabled="loading">{{btnTxt}}</button>
</view> </view>
</view> </view>

View File

@@ -10,7 +10,7 @@
</view> </view>
<!-- 显示框 --> <!-- 显示框 -->
<view class="uni-select-multiple" v-show="realValue.length"> <view class="uni-select-multiple" v-show="realValue.length">
<block v-if="multiple" > <block v-if="multiple">
<view class="uni-select-multiple-item" v-for="(item, index) in changevalue" :key="index"> <view class="uni-select-multiple-item" v-for="(item, index) in changevalue" :key="index">
{{ item[slabel] }} {{ item[slabel] }}
<view class="close-icon" v-if="showValueClear"> <view class="close-icon" v-if="showValueClear">
@@ -43,7 +43,7 @@
</template> </template>
<script setup> <script setup>
import { onMounted, reactive, ref, defineExpose} from "vue"; import { onMounted, reactive, ref, defineExpose, watch} from "vue";
const props = defineProps({ const props = defineProps({
// 是否显示全部清空按钮 // 是否显示全部清空按钮
@@ -108,10 +108,10 @@ const props = defineProps({
}); });
const emit = defineEmits(["change"]); const emit = defineEmits(["change"]);
const active = ref(false); // 组件是否激活, const active = ref(false); // 组件是否激活,
let changevalue = reactive([]); let changevalue = ref([]);
let realValue = reactive([]); let realValue = ref([]);
onMounted(() => { onMounted(() => {
// init(); init();
}); });
// 初始化函数 // 初始化函数
@@ -120,16 +120,16 @@ const init = () => {
props.options.forEach((item) => { props.options.forEach((item) => {
props.value.forEach((i) => { props.value.forEach((i) => {
if (item[props.svalue] === i) { if (item[props.svalue] === i) {
changevalue.push(item); changevalue.value.push(item);
} }
}) })
}) })
realValue = props.value; realValue.value = props.value;
console.log("props---", changevalue); // console.log("props---", changevalue.value);
} else { } else {
changevalue = []; changevalue.value = [];
realValue = []; realValue.value = [];
} }
}; };
// 点击展示选项 // 点击展示选项
@@ -140,13 +140,13 @@ const handleSelect = () => {
// 移除数据 // 移除数据
const handleRemove = (index) => { const handleRemove = (index) => {
if (index === null) { if (index === null) {
realValue = []; realValue.value = [];
changevalue = []; changevalue.value = [];
} else { } else {
realValue.splice(index, 1); realValue.value.splice(index, 1);
changevalue.splice(index, 1); changevalue.value.splice(index, 1);
} }
emit("change", changevalue, realValue); emit("change", changevalue.value, realValue.value);
}; };
// 点击组件某一项 // 点击组件某一项
const handleChange = (index, item) => { const handleChange = (index, item) => {
@@ -154,26 +154,26 @@ const handleChange = (index, item) => {
// 如果是单选框,选中一项后直接关闭 // 如果是单选框,选中一项后直接关闭
if (!props.multiple) { if (!props.multiple) {
console.log("关闭下拉框"); console.log("关闭下拉框");
changevalue.length = 0 changevalue.value.length = 0
realValue.length = 0 realValue.length = 0
changevalue.push(item); changevalue.value.push(item);
realValue.push(item[props.svalue]) realValue.value.push(item[props.svalue])
active.value = !active.value; active.value = !active.value;
} else { } else {
// 多选操作 // 多选操作
const arrIndex = realValue.indexOf(item[props.svalue]); const arrIndex = realValue.value.indexOf(item[props.svalue]);
if (arrIndex > -1) { if (arrIndex > -1) {
// 如果该选项已经选中,当点击后就不选中 // 如果该选项已经选中,当点击后就不选中
changevalue.splice(arrIndex, 1); changevalue.value.splice(arrIndex, 1);
realValue.splice(arrIndex, 1); realValue.value.splice(arrIndex, 1);
} else { } else {
// 否则选中该选项 // 否则选中该选项
changevalue.push(item); changevalue.value.push(item);
realValue.push(item[props.svalue]); realValue.value.push(item[props.svalue]);
} }
} }
// 触发回调函数 // 触发回调函数
emit("change", changevalue, realValue); emit("change", changevalue.value, realValue.value);
}; };
// 失去焦点时关闭选项列表 // 失去焦点时关闭选项列表

View File

@@ -14,7 +14,10 @@
<view v-if="subTimes">{{parseTime(subTimes,'{y}{m}{d} 星期{a} {h}:{i}')}}</view> <view v-if="subTimes">{{parseTime(subTimes,'{y}{m}{d} 星期{a} {h}:{i}')}}</view>
</view> </view>
<view class="model-bottom"> <view class="model-bottom">
<button type="default" class="btn-green" @click="handleConfirm" v-if="btnFlags" :loading="loading" :disabled="loading">{{btnTxts}}</button> <button type="default" class="btn-green" @click="handleConfirm"
v-if="btnFlags" :loading="!isGreens?false:loading"
:disabled="!isGreens?false:loading"
>{{btnTxts}}</button>
<button type="primary" class="btn-cancel" @click="handleCancel" v-if="btnFlags2">{{btnCancelTxts}}</button> <button type="primary" class="btn-cancel" @click="handleCancel" v-if="btnFlags2">{{btnCancelTxts}}</button>
</view> </view>
</view> </view>
@@ -149,7 +152,11 @@ const handleCancel = ()=>{
} }
const handleConfirm = ()=>{ const handleConfirm = ()=>{
loading.value=true; if(isGreens.value){
loading.value=false;
}else{
loading.value=true;
}
emit('confirm') emit('confirm')
} }

View File

@@ -4,5 +4,8 @@ export const AGREEWELCOME_KEY="agreewelcome";
// clientId 默认写2 // clientId 默认写2
export const CLIENT_ID="2"; export const CLIENT_ID="2";
// #区分内外网 //1-内网2-外网 // #区分内外网 //1-内网2-外网
export const NETWORK_ENV=2; export const NETWORK_ENV=1;
// miniIo 参数对象
export const MINIO_KEY="minioKey"

View File

@@ -24,7 +24,8 @@
"modules" : { "modules" : {
"Push" : {}, "Push" : {},
"Camera" : {}, "Camera" : {},
"Barcode" : {} "Barcode" : {},
"VideoPlayer" : {}
}, },
/* */ /* */
"distribute" : { "distribute" : {
@@ -60,7 +61,7 @@
"<uses-permission android:name=\"android.permission.BROADCAST_PACKAGE_REPLACED\" />", "<uses-permission android:name=\"android.permission.BROADCAST_PACKAGE_REPLACED\" />",
"<uses-permission android:name=\"android.permission.RESTART_PACKAGES\" />", "<uses-permission android:name=\"android.permission.RESTART_PACKAGES\" />",
"<uses-permission android:name=\"android.permission.REQUEST_INSTALL_PACKAGES\" />", "<uses-permission android:name=\"android.permission.REQUEST_INSTALL_PACKAGES\" />",
"<uses-permission android:name=\"android.permission.NFC\"/>" "<uses-permission android:name=\"android.permission.NFC\" />"
], ],
"abiFilters" : [ "armeabi-v7a", "arm64-v8a" ], "abiFilters" : [ "armeabi-v7a", "arm64-v8a" ],
"minSdkVersion" : 23, "minSdkVersion" : 23,

View File

@@ -14,7 +14,7 @@
</customHeader> </customHeader>
<!-- 高度来避免头部遮挡 --> <!-- 高度来避免头部遮挡 -->
<view class="top-height"></view> <view class="top-height"></view>
<view class="week">{{dateStr}}</view> <!-- <view class="week">{{dateStr}}</view> -->
<!-- 列表 @up="upCallback" --> <!-- 列表 @up="upCallback" -->
<mescroll-uni ref="mescrollRef" @init="mescrollInit" <mescroll-uni ref="mescrollRef" @init="mescrollInit"
@@ -31,7 +31,7 @@
<!-- 任务(巡检)状态 1=未发布 2=已发布 3 进行中 4 已完成 5 已过期 --> <!-- 任务(巡检)状态 1=未发布 2=已发布 3 进行中 4 已完成 5 已过期 -->
<!-- 状态为3进行中时 进度>0执行中 进度=0为待执行 --> <!-- 状态为3进行中时 进度>0执行中 进度=0为待执行 -->
<block v-if="item.taskStatus==3"> <block v-if="item.taskStatus==3">
<img v-if="item.count==0" :src="'static/images/polling/icon-start.png'" class="img-w" /> <img v-if="item.groupFinishNum==0" :src="'static/images/polling/icon-start.png'" class="img-w" />
<img v-else :src="'static/images/polling/icon-pending.png'" class="img-w" /> <img v-else :src="'static/images/polling/icon-pending.png'" class="img-w" />
</block> </block>
<img v-else-if="item.taskStatus==4" :src="'static/images/polling/icon-complete.png'" class="img-complete" /> <img v-else-if="item.taskStatus==4" :src="'static/images/polling/icon-complete.png'" class="img-complete" />
@@ -43,16 +43,16 @@
</view> </view>
<view class="r-list"> <view class="r-list">
<view class="r-left"> <view class="r-left">
<view class="r-l-left">开始时间<span class="r-gray">{{ item.planTime }}</span></view> <view class="r-l-left">开始时间<span class="r-gray">{{ parseTime(item.planTime,'{h}:{i}') }}</span></view>
<view class="r-l-right">任务时长<span class="r-gray">{{ item.workHour }}小时</span></view> <view class="r-l-right">任务时长<span class="r-gray">{{ item.workHour }}小时</span></view>
</view> </view>
</view> </view>
<view class="r-list"> <view class="r-list">
<view class="r-left"> <view class="r-left">
<view class="r-l-left"> <view class="r-l-left">
完成进度<span class="r-gray"><span :class="{'r-red':item.count<item.total}">{{item.count}}</span>/{{item.total}}</span> 完成进度<span class="r-gray"><span :class="{'r-red':item.groupFinishNum<item.groupNum}">{{item.groupFinishNum}}</span>/{{item.groupNum}}</span>
</view> </view>
<view class="r-l-right">完成比率<span class="r-blue">{{item.percentage}}</span></view> <view class="r-l-right">完成比率<span class="r-blue">{{(item.groupFinishNum/item.groupNum).toFixed()+'%'}}</span></view>
</view> </view>
</view> </view>
<view class="r-list"> <view class="r-list">
@@ -81,7 +81,7 @@
<!-- 任务(巡检)状态 1=未发布 2=已发布 3 进行中 4 已完成 5 已过期 --> <!-- 任务(巡检)状态 1=未发布 2=已发布 3 进行中 4 已完成 5 已过期 -->
<!-- 状态为3进行中时 进度>0执行中 进度=0为待执行 --> <!-- 状态为3进行中时 进度>0执行中 进度=0为待执行 -->
<block v-if="item.taskStatus==3"> <block v-if="item.taskStatus==3">
<img v-if="item.count==0" :src="'static/images/polling/icon-start.png'" class="img-w" /> <img v-if="item.groupFinishNum==0" :src="'static/images/polling/icon-start.png'" class="img-w" />
<img v-else :src="'static/images/polling/icon-pending.png'" class="img-w" /> <img v-else :src="'static/images/polling/icon-pending.png'" class="img-w" />
</block> </block>
<img v-else-if="item.taskStatus==4" :src="'static/images/polling/icon-complete.png'" class="img-complete" /> <img v-else-if="item.taskStatus==4" :src="'static/images/polling/icon-complete.png'" class="img-complete" />
@@ -93,23 +93,23 @@
</view> </view>
<view class="r-list"> <view class="r-list">
<view class="r-left"> <view class="r-left">
<view class="r-l-left">开始时间<span class="r-gray">{{ item.planTime }}</span></view> <view class="r-l-left">开始时间<span class="r-gray">{{ parseTime(item.planTime,'{h}:{i}') }}</span></view>
<view class="r-l-right">任务时长<span class="r-gray">{{ item.workHour }}小时</span></view> <view class="r-l-right">任务时长<span class="r-gray">{{ item.workHour }}小时</span></view>
</view> </view>
</view> </view>
<view class="r-list"> <view class="r-list">
<view class="r-left"> <view class="r-left">
<view class="r-l-left"> <view class="r-l-left">
完成进度<span class="r-gray"><span :class="{'r-red':item.count<item.total}">{{item.count}}</span>/{{item.total}}</span> 完成进度<span class="r-gray"><span :class="{'r-red':item.groupFinishNum<item.groupNum}">{{item.groupFinishNum}}</span>/{{item.groupNum}}</span>
</view> </view>
<view class="r-l-right">完成比率<span class="r-blue">{{item.percentage}}</span></view> <view class="r-l-right">完成比率<span class="r-blue">{{(item.groupFinishNum/item.groupNum).toFixed()+'%'}}</span></view>
</view> </view>
</view> </view>
<view class="r-list"> <view class="r-list">
<view class="r-left"> <view class="r-left">
<view>任务状态 <view>任务状态
<span class="r-gray" v-if="item.taskStatus==3"> <span class="r-gray" v-if="item.taskStatus==3">
<block v-if="item.count==0">待执行</block> <block v-if="item.groupFinishNum==0">待执行</block>
<block v-else>执行中</block> <block v-else>执行中</block>
</span> </span>
<span class="r-gray" v-else>{{formatTaskStatus(item.taskStatus) }}</span> <span class="r-gray" v-else>{{formatTaskStatus(item.taskStatus) }}</span>
@@ -128,7 +128,7 @@
<block v-if="list3.length>0"> <block v-if="list3.length>0">
<view class="report-list" v-for="(item, index) in list3" :key="index" @click="handleDetail(item,2)"> <view class="report-list" v-for="(item, index) in list3" :key="index" @click="handleDetail(item,2)">
<view class="r-list" style="padding-bottom:0"> <view class="r-list" style="padding-bottom:0">
<view class="r-name">{{ item.problemDesc }}</view> <view class="r-name">{{ item.groupName }}</view>
<view class="r-right"> <view class="r-right">
<!-- 问题状态 1=追踪2=关闭 --> <!-- 问题状态 1=追踪2=关闭 -->
<view v-if="item.problemStatus==1" class="btn-red">进行中</view> <view v-if="item.problemStatus==1" class="btn-red">进行中</view>
@@ -137,8 +137,8 @@
</view> </view>
<view class="r-list"> <view class="r-list">
<view class="r-left"> <view class="r-left">
<view class="r-l-left" style="width:220rpx">跟踪次数<span class="r-gray">{{ item.count }}</span></view> <view class="r-l-left" style="width:220rpx">跟踪次数<span class="r-gray">{{ item.logNum }}</span></view>
<view class="r-l-right">最近跟踪时间<span class="r-gray">{{ parseTime(item.modifyTime,'{m}-{d} {h}:{i}') }}</span></view> <view class="r-l-right">最近跟踪时间<span class="r-gray">{{ parseTime(item.lastLogTime,'{m}-{d} {h}:{i}') }}</span></view>
</view> </view>
</view> </view>
<view class="report-border" v-if="index<list3.length-1"></view> <view class="report-border" v-if="index<list3.length-1"></view>
@@ -159,7 +159,7 @@ import customHeader from '@/components/customHeader.vue';
import MescrollUni from 'mescroll-uni/mescroll-uni.vue'; import MescrollUni from 'mescroll-uni/mescroll-uni.vue';
import { parseTime } from '@/utils/datetime.js'; import { parseTime } from '@/utils/datetime.js';
import { formatTaskStatus } from '@/utils/status.js'; import { formatTaskStatus } from '@/utils/status.js';
import { taskTodayList } from '@/api/polling.js' import { taskList } from '@/api/polling.js'
// '2025-12-29 星期五' // '2025-12-29 星期五'
let dateStr = ref(''); let dateStr = ref('');
@@ -204,9 +204,9 @@ const downCallback = async (mescroll) => {
console.log("下拉刷新") console.log("下拉刷新")
const res = await getList(1, upOption.value.page.size); const res = await getList(1, upOption.value.page.size);
cssFlag.value = false; cssFlag.value = false;
list1.value = res.list1; list1.value = res.list1 || [];
list2.value = res.list2; list2.value = res.list2 || [];
list3.value = res.list3; list3.value = res.list3 || [];
// mescroll.resetUpScroll(); // mescroll.resetUpScroll();
} catch (error) { } catch (error) {
mescroll.endErr(); mescroll.endErr();
@@ -220,9 +220,9 @@ const upCallback = async (mescroll) => {
console.log("上拉加载更多") console.log("上拉加载更多")
let res = await getList(mescroll.num, mescroll.size); let res = await getList(mescroll.num, mescroll.size);
if (mescroll.num === 1) { if (mescroll.num === 1) {
list1.value = res.list1; list1.value = res.list1 || [];
list2.value = res.list2; list2.value = res.list2 || [];
list3.value = res.list3; list3.value = res.list3 || [];
} else { } else {
// list.value.push(...res.list); // list.value.push(...res.list);
} }
@@ -233,126 +233,25 @@ const upCallback = async (mescroll) => {
} }
// 获取数据列表 // 获取数据列表
/**
* {
"day": "",查询日期格式yyyy-mm-dd
"month": "",查询日期格式yyyy-mm
"taskType": 0, //1 日常任务 2 临时任务
"taskStatus": 0//1=未发布、2=已发布 3 进行中 4 已完成 5 已过期
}
*/
const getList = (pageIndex, pageSize) => { const getList = (pageIndex, pageSize) => {
return new Promise(async (resolve) => { return new Promise(async (resolve) => {
let param = { let param = {
pageIndex, // day:parseTime(new Date().getTime(),'{y}-{m}-{d}'),//今天
pageSize, taskStatus:3,//进行中
} }
let res = await taskList(param);
// let res = await noticeList(param); let data = res||{};
let res = {
"code": 200,
"msg": "操作成功",
"data": {
list1:[
{
taskName:'日常巡检任务AAA日常巡检任务111',
taskId:202512297899,
taskStatus:3,
planTime:'10:25',
workHour:1,
count:0,
total:70,
percentage:'30%'
},
{
taskName:'日常巡检任务AAA日常巡检任务222',
taskId:202512297899,
taskStatus:3,
planTime:'10:25',
workHour:1,
count:20,
total:70,
percentage:'40%'
},
{
taskName:'日常巡检任务BBB任务名称过长时可折行 行距35px',
taskId:202512297899,
taskStatus:4,
planTime:'10:25',
workHour:1,
count:70,
total:70,
percentage:'100%'
},
{
taskName:'日常巡检任务ccc任务名称',
taskId:202512297899,
taskStatus:5,
planTime:'10:25',
workHour:1,
count:70,
total:70,
percentage:'100%'
},
],
list2:[
{
taskName:'日常巡检任务AAA日常巡检任务111',
taskId:202512297899,
taskStatus:3,
planTime:'10:25',
workHour:1,
count:0,
total:70,
percentage:'30%'
},
{
taskName:'日常巡检任务AAA日常巡检任务222',
taskId:202512297899,
taskStatus:3,
planTime:'10:25',
workHour:1,
count:20,
total:70,
percentage:'40%'
},
{
taskName:'日常巡检任务BBB任务名称过长时可折行 行距35px',
taskId:202512297899,
taskStatus:4,
planTime:'10:25',
workHour:1,
count:70,
total:70,
percentage:'100%'
},
{
taskName:'日常巡检任务ccc任务名称',
taskId:202512297899,
taskStatus:5,
planTime:'10:25',
workHour:1,
count:70,
total:70,
percentage:'100%'
},
],
list3:[
{
problemDesc:'西区地下车库入口防汛物资摆放',
problemId:202512297899,
problemStatus:1,
modifyTime:new Date().getTime(),
count:0,
},
{
problemDesc:'监控室消防设备阀门确保正常开启闭合',
problemId:202512297899,
problemStatus:2,
modifyTime:new Date().getTime(),
count:20,
}
]
}
}
let data = res.data||{};
resolve({ resolve({
...data, ...data,
// total: res.recordCount || 0
}); });
}); });
@@ -364,7 +263,7 @@ const handleDetail = (item,type) =>{
if(type==1){ if(type==1){
url = '/pages/business/polling/taskDetail?id='+item.taskId; url = '/pages/business/polling/taskDetail?id='+item.taskId;
}else{ }else{
url = '/pages/business/polling/problemDetail?id='+item.taskId; url = '/pages/business/polling/problemDetail?problemId='+item.problemId;
} }
uni.navigateTo({ uni.navigateTo({
url url
@@ -383,10 +282,10 @@ const handleJump = (item)=>{
<style scoped> <style scoped>
.scroll-h{ .scroll-h{
/* #ifdef APP-PLUS */ /* #ifdef APP-PLUS */
height: calc(100vh - 108px); height: calc(100vh - 78px);
/* #endif */ /* #endif */
/* #ifndef APP-PLUS */ /* #ifndef APP-PLUS */
height: calc(100vh - 93px); height: calc(100vh - 58px);
/* #endif */ /* #endif */
} }
.head-right{ .head-right{

View File

@@ -15,147 +15,160 @@
</customHeader> </customHeader>
<!-- 高度来避免头部遮挡 --> <!-- 高度来避免头部遮挡 -->
<view class="top-height"></view> <view class="top-height"></view>
<!-- 下拉刷新 -->
<!-- 1 单选 2多选 3判断 4 问答 5 读卡 6 扫码 7 拍照 8 视频 9 定位暂时去掉了 --> <mescroll-uni ref="mescrollRef" @init="mescrollInit"
<view class="white-bg"> :down="downOption" @down="downCallback"
<view class="blue-title">{{optionObj.optionName}}</view> :fixed="false" class="scroll-h"
<view class="blue-sub-title" style="margin-bottom:20rpx;"> >
巡检日期<text>{{parseTime(optionObj.planTime,'{y}-{m}-{d} 星期{a}')}}</text> <!-- 1 单选 2多选 3判断 4 问答 5 读卡 6 扫码 7 拍照 8 视频 9 定位暂时去掉了 -->
</view> <view class="white-bg">
<view class="report-list" v-for="(item, index) in optionObj.list" :key="index"> <view class="blue-title">{{optionObj.groupName}}</view>
<!-- 单选 --> <view class="blue-sub-title" style="margin-bottom:20rpx;">
<block v-if="item.pointType==1"> 巡检日期<text>{{parseTime(optionObj.lastCheckTime,'{y}-{m}-{d} 星期{a}')}}</text>
<view class="r-left"> </view>
<view>{{String(index+1).padStart(2, '0')+'.'}}</view> <block v-if="optionObj.pointList">
<view>{{ item.pointName }}</view> <block v-if="optionObj.pointList.length>0">
</view> <view class="report-list" v-for="(item, index) in optionObj.pointList" :key="index">
<multipleSelect :multiple="false" :value="item.chooseList" downInner <!-- 单选 -->
:options="item.optionList" @change="(...args) => changeCheck(...args, item)" <block v-if="item.pointType==1">
:slabel="'optionContent'" :svalue="'optionId'" <view class="r-left" style="width:100%">
> <view>{{String(index+1).padStart(2, '0')+'.'}}</view>
</multipleSelect> <view>{{ item.pointName }}</view>
</block> </view>
<!-- 多选 --> <multipleSelect :multiple="false" :value="item.chooseList" downInner
<block v-else-if="item.pointType==2"> :options="item.optionList" @change="(...args) => changeCheck(...args, item)"
<view class="r-left"> :slabel="'optionContent'" :svalue="'optionTitle'"
<view>{{String(index+1).padStart(2, '0')+'.'}}</view>
<view>{{ item.pointName }}</view>
</view>
<multipleSelect :multiple="true" :value="item.chooseList" downInner
:options="item.optionList" @change="(...args) => changeCheck(...args, item)"
:slabel="'optionContent'" :svalue="'optionId'"
>
</multipleSelect>
</block>
<!-- 判断 -->
<block v-if="item.pointType==3">
<view class="r-list">
<view class="r-left">
<view>{{String(index+1).padStart(2, '0')+'.'}}</view>
<view>{{ item.pointName }}</view>
</view>
<view class="r-right">
<radio-group @change="radioChange($event,item)" style="transform:scale(0.9)">
<!-- <radio value="1" color="#02C74C" style="margin-right:30rpx;" ></radio>
<radio value="2" color="#02C74C"></radio> -->
<radio :value="item2.optionId+''" color="#02C74C"
v-for="(item2,index) in item.optionList" :key="index"
:style="{marginRight:index==0?'30rpx':'0'}"
> >
{{item2.optionContent}} </multipleSelect>
</radio> </block>
</radio-group> <!-- 多选 -->
<block v-else-if="item.pointType==2">
<view class="r-left" style="width:100%">
<view>{{String(index+1).padStart(2, '0')+'.'}}</view>
<view>{{ item.pointName }}</view>
</view>
<multipleSelect :multiple="true" :value="item.chooseList" downInner
:options="item.optionList" @change="(...args) => changeCheck(...args, item)"
:slabel="'optionContent'" :svalue="'optionTitle'"
>
</multipleSelect>
</block>
<!-- 判断 -->
<block v-if="item.pointType==3">
<view class="r-list">
<view class="r-left">
<view>{{String(index+1).padStart(2, '0')+'.'}}</view>
<view>{{ item.pointName }}</view>
</view>
<view class="r-right">
<radio-group @change="radioChange($event,item)" style="transform:scale(0.9)">
<radio :value="item2.optionTitle" color="#02C74C"
v-for="(item2,index) in item.optionList" :key="index"
:style="{marginRight:index==0?'30rpx':'0'}"
:checked="item2.optionTitle === item.resultContent"
>
{{item2.optionContent}}
</radio>
</radio-group>
</view>
</view>
</block>
<!-- 问答 -->
<block v-else-if="item.pointType==4">
<view class="r-left" style="width:100%">
<view>{{String(index+1).padStart(2, '0')+'.'}}</view>
<view>{{ item.pointName }}</view>
</view>
<view class="r-input">
<!-- <input class="uni-input" placeholder="请输入" placeholder-class="place-input" /> -->
<textarea class="textarea" v-model="item.resultContent" auto-height placeholder="请输入" placeholder-class="place-input"></textarea>
</view>
</block>
<!-- 读卡 -->
<block v-else-if="item.pointType==5">
<view class="r-list" >
<view class="r-left">
<view>{{String(index+1).padStart(2, '0')+'.'}}</view>
<view>{{ item.pointName }}</view>
</view>
<!-- #ifdef APP-PLUS -->
<view class="r-right" @click.stop="initNFC">
<img :src="'static/images/polling/icon-NFCcode.png'" class="img-nfc" /> 开始识别
</view>
<!-- #endif -->
</view>
</block>
<!-- 扫码 -->
<block v-else-if="item.pointType==6">
<view class="r-list">
<view class="r-left">
<view>{{String(index+1).padStart(2, '0')+'.'}}</view>
<view>{{ item.pointName }}</view>
</view>
<!-- #ifdef APP-PLUS -->
<view class="r-right r-active" v-if="item.resultContent" @click="handleScan(item)">
<img :src="'static/images/polling/icon-QRcode-b.png'" class="img-nfc" />
<view>扫码成功<view class="r-font">点击再次扫码</view></view>
</view>
<view class="r-right" v-else @click="handleScan(item)">
<img :src="'static/images/polling/icon-QRcode.png'" class="img-nfc" /> 开始扫码
</view>
<!-- #endif -->
<!-- #ifndef APP-PLUS -->
<view class="r-right r-active">
<img :src="'static/images/polling/icon-QRcode-b.png'" class="img-nfc" />
<view>扫码成功</view>
</view>
<!-- #endif -->
</view>
</block>
<!-- 拍照 -->
<block v-else-if="item.pointType==7">
<view class="r-left" style="width:100%">
<view>{{String(index+1).padStart(2, '0')+'.'}}</view>
<view>{{ item.pointName }}</view>
</view>
<view class="img-flex">
<view class="img-show" v-for="(item2,index) in imgArr2" :key="index">
<img :src="item2" />
</view>
<view class="img-con" @click="chooseImage(item)">
<img :src="'static/images/polling/icon-AddPic.png'" class="img-pic" />
<view>添加照片</view>
</view>
</view>
</block>
<!-- 视频 -->
<block v-else-if="item.pointType==8">
<view class="r-left" style="width:100%">
<view>{{String(index+1).padStart(2, '0')+'.'}}</view>
<view>{{ item.pointName }}</view>
</view>
<view class="img-flex">
<view class="img-show" v-for="(item2,index) in videoArr2" :key="index">
<video :src="item2" controls></video>
</view>
<view class="img-con" @click="chooseVideo(item)">
<img :src="'static/images/polling/icon-AddVideo.png'" class="img-pic" />
<view>添加视频</view>
</view>
</view>
</block>
<view class="report-border" :style="{borderColor:index<optionObj.pointList.length-1?'#E7E7E7':'#fff'}"></view>
</view> </view>
<view class="btn-submit">
<button type="primary" @click="handleSubmit" :loading="submitLoading">提交</button>
</view>
</block>
<view v-else class="no-data">
<img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" />
</view> </view>
</block> </block>
<!-- 问答 --> <view v-else class="no-data">
<block v-else-if="item.pointType==4"> <img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" />
<view class="r-left"> </view>
<view>{{String(index+1).padStart(2, '0')+'.'}}</view>
<view>{{ item.pointName }}</view>
</view>
<view class="r-input">
<!-- <input class="uni-input" placeholder="请输入" placeholder-class="place-input" /> -->
<textarea class="textarea" v-model="item.result" auto-height placeholder="请输入" placeholder-class="place-input"></textarea>
</view>
</block>
<!-- 读卡 -->
<block v-else-if="item.pointType==5">
<view class="r-list">
<view class="r-left">
<view>{{String(index+1).padStart(2, '0')+'.'}}</view>
<view>{{ item.pointName }}</view>
</view>
<!-- #ifdef APP-PLUS -->
<view class="r-right" @click="initNFC">
<img :src="'static/images/polling/icon-NFCcode.png'" class="img-nfc" /> 开始识别
</view>
<!-- #endif -->
</view>
</block>
<!-- 扫码 -->
<block v-else-if="item.pointType==6">
<view class="r-list">
<view class="r-left">
<view>{{String(index+1).padStart(2, '0')+'.'}}</view>
<view>{{ item.pointName }}</view>
</view>
<!-- #ifdef APP-PLUS -->
<view class="r-right r-active" v-if="scanStr" @click="handleScan">
<img :src="'static/images/polling/icon-QRcode-b.png'" class="img-nfc" />
<view>扫码成功<view class="r-font">点击再次扫码</view></view>
</view>
<view class="r-right" v-else @click="handleScan">
<img :src="'static/images/polling/icon-QRcode.png'" class="img-nfc" /> 开始扫码
</view>
<!-- #endif -->
</view>
</block>
<!-- 拍照 -->
<block v-else-if="item.pointType==7">
<view class="r-left">
<view>{{String(index+1).padStart(2, '0')+'.'}}</view>
<view>{{ item.pointName }}</view>
</view>
<view class="img-flex">
<view class="img-show" v-for="(item,index) in imgArr" :key="index">
<img :src="item" />
</view>
<view class="img-con" @click="chooseImage">
<img :src="'static/images/polling/icon-AddPic.png'" class="img-pic" />
<view>添加照片</view>
</view>
</view>
</block>
<!-- 视频 -->
<block v-else-if="item.pointType==8">
<view class="r-left">
<view>{{String(index+1).padStart(2, '0')+'.'}}</view>
<view>{{ item.pointName }}</view>
</view>
<view class="img-flex">
<!-- v-for="(item,index) in videoArr" :key="index" -->
<view class="img-show" v-for="(item,index) in videoArr" :key="index">
<!-- @error="videoErrorCallback"
:danmu-list="danmuList" -->
<!-- <video id="myVideo" :src="videoArr"
enable-danmu danmu-btn controls
></video> -->
<video :src="item" controls></video>
</view>
<view class="img-con" @click="chooseVideo">
<img :src="'static/images/polling/icon-AddVideo.png'" class="img-pic" />
<view>添加视频</view>
</view>
</view>
</block>
<view class="report-border" :style="{borderColor:index<optionObj.list.length-1?'#E7E7E7':'#fff'}"></view>
</view> </view>
</mescroll-uni>
<view class="btn-submit">
<button type="primary" @click="handleSubmit">提交</button>
</view>
</view>
</view> </view>
<!-- 弹窗提示 --> <!-- 弹窗提示 -->
<pollingShowModal :visible="visible" <pollingShowModal :visible="visible"
@@ -170,244 +183,224 @@
@confirm="handleConfirm" @confirm="handleConfirm"
ref="showModel" ref="showModel"
></pollingShowModal> ></pollingShowModal>
<!-- 普通弹窗提示 -->
<customShowModal
:title="''"
:content="content3"
:visible="visible3"
:btnFlag2="false"
@confirm="handleClose3"
ref="showModel3"
></customShowModal>
</view> </view>
</template> </template>
<script setup> <script setup>
import { ref,onMounted,onUnmounted,nextTick,computed,reactive } from 'vue' import { ref,onMounted,onUnmounted,nextTick,computed,reactive } from 'vue'
import { onLoad,onHide} from '@dcloudio/uni-app'; import { onLoad,onHide} from '@dcloudio/uni-app';
import { MINIO_KEY } from '@/enums/cacheEnums';
import customHeader from '@/components/customHeader.vue'; import customHeader from '@/components/customHeader.vue';
import MescrollUni from 'mescroll-uni/mescroll-uni.vue'; import MescrollUni from 'mescroll-uni/mescroll-uni.vue';
import multipleSelect from "@/components/multipleSelect.vue"; import multipleSelect from "@/components/multipleSelect.vue";
import pollingShowModal from "@/components/pollingShowModal.vue"; import pollingShowModal from "@/components/pollingShowModal.vue";
import customShowModal from "@/components/customShowModal.vue"
import { parseTime } from '@/utils/datetime.js'; import { parseTime } from '@/utils/datetime.js';
import { formatTaskStatus } from '@/utils/status.js'; import { formatTaskStatus } from '@/utils/status.js';
import { taskDetail } from '@/api/polling.js' import { taskGroupDetail,submitResult,minioUpload } from '@/api/polling.js'
import {uploadFileMinio} from '@/utils/minio.js' import {compressImageUni,getMinioThumbUrl} from '@/utils/common.js'
// import {uploadFileMinio} from '@/utils/minio.js'
// #ifdef APP-PLUS
import nfcUtil from "@/utils/nfcUtil.js"
// #endif
let workId = ref(undefined); let taskId = ref(undefined);
let checkList=[ let groupId = ref(undefined);
{ value: 0, text: "答案1" }, let minioObj = ref({});
{ value: 1, text: "答案2" },
{ value: 2, text: "答案3" },
{ value: 3, text: "答案4" },
{ value: 4, text: "答案5" },
{ value: 4, text: "答案6" }
];
onLoad(option => { onLoad(option => {
// console.log(option) // console.log(option)
workId.value = option.id; taskId.value = option.taskId;
getList(); groupId.value = option.groupId;
minioObj.value = JSON.parse(uni.getStorageSync(MINIO_KEY) || "\{\}")
// console.log(minioObj.value)
}) })
// 下拉刷新
const mescrollRef = ref(null);
const mescrollInit = (mescroll) => {
mescrollRef.value = mescroll;
};
const downOption = ref({
auto: true,
textInOffset: '下拉刷新',
textOutOffset: '释放更新',
textLoading: '刷新中...'
});
// 下拉刷新
const downCallback = async (mescroll) => {
try {
getList();
} catch (error) {
mescroll.endErr();
} finally {
mescroll.endSuccess();
}
}
// 查询列表 // 查询列表
let list = ref([]); let list = ref([]);
let optionObj = ref({}) let optionObj = ref({})
// 获取数据列表 // 获取数据列表
const getList = () => { const getList = async() => {
// let res = await noticeList(); let param = {
// 1 单选 2多选 3判断 4问答 5 读卡 6 扫码 7 拍照 8 视频 9 定位 taskId:taskId.value,
let res = { groupId:groupId.value
"code": 200,
"msg": "操作成功",
"data": {
optionName:'配电箱箱体和内部线路检查',
planTime:new Date().getTime(),
list:[
{
pointName:'技术中心机房总电源', pointId:202512297899, pointType:1,
optionList:[
{
"optionId": 189,
"pointId": 188,
"optionTitle": "A",
"optionContent": "卫生检查1",
"createTime": "2025-11-11 11:48:43",
"createUser": "SSEYS1695",
"modifyTime": "2025-11-11 11:48:43",
"modifyUser": "SSEYS1695"
},
{
"optionId": 190,
"pointId": 188,
"optionTitle": "B",
"optionContent": "卫生检查2",
"createTime": "2025-11-11 11:48:43",
"createUser": "SSEYS1695",
"modifyTime": "2025-11-11 11:48:43",
"modifyUser": "SSEYS1695"
},
{
"optionId": 191,
"pointId": 188,
"optionTitle": "C",
"optionContent": "卫生检查3",
"createTime": "2025-11-11 11:48:43",
"createUser": "SSEYS1695",
"modifyTime": "2025-11-11 11:48:43",
"modifyUser": "SSEYS1695"
},
{
"optionId": 192,
"pointId": 188,
"optionTitle": "D",
"optionContent": "卫生检查4",
"createTime": "2025-11-11 11:48:43",
"createUser": "SSEYS1695",
"modifyTime": "2025-11-11 11:48:43",
"modifyUser": "SSEYS1695"
}
]
},
{ pointName:'监控室消防设备阀门正常开启闭合', pointId:202512297899, pointType:2,
optionList:[
{
"optionId": 182,
"pointId": 122,
"optionTitle": "A",
"optionContent": "区域一",
"createTime": "2025-11-11 11:40:52",
"createUser": "SSEYS1695",
"modifyTime": "2025-11-11 11:40:52",
"modifyUser": "SSEYS1695"
},
{
"optionId": 183,
"pointId": 122,
"optionTitle": "B",
"optionContent": "区域二",
"createTime": "2025-11-11 11:40:52",
"createUser": "SSEYS1695",
"modifyTime": "2025-11-11 11:40:52",
"modifyUser": "SSEYS1695"
},
{
"optionId": 184,
"pointId": 122,
"optionTitle": "C",
"optionContent": "区域三",
"createTime": "2025-11-11 11:40:52",
"createUser": "SSEYS1695",
"modifyTime": "2025-11-11 11:40:52",
"modifyUser": "SSEYS1695"
},
{
"optionId": 185,
"pointId": 122,
"optionTitle": "D",
"optionContent": "区域四",
"createTime": "2025-11-11 11:40:52",
"createUser": "SSEYS1695",
"modifyTime": "2025-11-11 11:40:52",
"modifyUser": "SSEYS1695"
}
]
},
{ pointName:'监控室10组灭火器压力指针处于绿色区域', pointId:202512297899, pointType:3,
optionList:[
{
"optionId": 154,
"pointId": 127,
"optionTitle": "A",
"optionContent": "是",
"createTime": "2025-11-11 09:56:34",
"createUser": "SSEYS1695",
"modifyTime": "2025-11-11 09:56:34",
"modifyUser": "SSEYS1695"
},
{
"optionId": 155,
"pointId": 127,
"optionTitle": "B",
"optionContent": "否",
"createTime": "2025-11-11 09:56:34",
"createUser": "SSEYS1695",
"modifyTime": "2025-11-11 09:56:34",
"modifyUser": "SSEYS1695"
}
]
},
{ pointName:'库房灭火器压力指针处于绿色区', pointId:202512297899,pointType:4,},
{ pointName:'技术中心机房总电源', pointId:202512297899,pointType:5,},
{ pointName:'监控室消防设备阀门正常监控室消防设备阀门正常监控室消防设备阀门正常', pointId:202512297899,pointType:6,},
{ pointName:'库房灭火器压力指针处于绿色区', pointId:202512297899,pointType:7,},
{ pointName:'技术中心机房总电源', pointId:202512297899,pointType:8,},
],
}
} }
let data = res.data||{}; // 1 单选 2多选 3判断 4问答 5 读卡 6 扫码 7 拍照 8 视频 9 定位
// data.list.forEach(item=>{ let res = await taskGroupDetail(param);
// item.chooseList let data = res||{};
// }) data.pointList.forEach(item=>{
if(item.resultContent){
if(item.pointType==2 ||item.pointType==1){
item['chooseList'] = item.resultContent.split(",") //JSON.parse(item.resultContent)
}else if(item.pointType==7){
imgArr.value=[];
imgArr2.value=[];
let imgList = item.resultContent.split(",");
imgList.forEach(imgUrl=>{
imgArr.value.push(imgUrl);
let urlNew = minioObj.value.endpoint + "/thumb/"+minioObj.value.bucketName +"/"+imgUrl
imgArr2.value.push(urlNew)
})
}else if(item.pointType==8){
videoArr.value=[];
videoArr2.value=[]
let videoList = item.resultContent.split(",");
videoList.forEach(videoUrl=>{
videoArr.value.push(videoUrl);
let urlNew = minioObj.value.endpoint + "/"+minioObj.value.bucketName +"/"+videoUrl
videoArr2.value.push(urlNew)
})
}
}
})
// console.log(data.pointList)
optionObj.value = data optionObj.value = data
} }
// 跳转问题上报页面 // 跳转问题上报页面
const handleQuestion=()=>{ const handleQuestion=()=>{
uni.navigateTo({ uni.navigateTo({
url: '/pages/business/polling/problemReport?id='+workId.value url: '/pages/business/polling/problemReport?taskId='+taskId.value+"&groupId="+groupId.value
}); });
} }
// radio 单选选择 // radio 判断选择
const radioChange=(e,item)=>{ const radioChange=(e,item)=>{
// console.log(e,item) // console.log("radioChange=>",e,item)
let radioValue = e.detail.value; let radioValue = e.detail.value;
item['optionIds']=radioValue; item['resultContent']=radioValue;
console.log("222判断radioChange=>",item)
} }
// 单选多选处理 // 单选多选处理
const changeCheck = (param,param2,item) => { const changeCheck = (param,param2,item) => {
// console.log(param,param2,item) // console.log("111多选changeCheck=>",param,param2)
item['optionIds'] = param2.join(","); item['resultContent'] = param2.join(",");//JSON.stringify(param);
// console.log(item) console.log("222多选changeCheck=>",item)
} }
// 照片及拍照处理 // 照片及拍照处理
const imgArr = ref([]); const imgArr = ref([]);
const imgArr2=ref([]); const imgArr2=ref([]);
const chooseImage = () => { const chooseImage = (item) => {
imgArr.value = []; console.log("item=>",item)
uni.chooseImage({ try {
// count: 1, // 默认是9这里设置为1次只选1张 uni.chooseImage({
sizeType: ['compressed'], // 可以指定是原图还是压缩图,可选 'original' 或 'compressed' // count: 1, // 默认是9这里设置为1次只选1张
sourceType: ['album', 'camera'], // 指定来源是相册还是相机,默认二者都有 // sizeType: ['compressed'], // 可以指定是原图还是压缩图,可选 'original' 或 'compressed'
success: async (res) => { sourceType: ['album', 'camera'], // 指定来源是相册还是相机,默认二者都有
// 选择成功,返回本地文件路径列表 // quality:80,
let files = res.tempFilePaths; // width:'1920px',
// console.log('图片临时路径:', files, res.tempFiles); // height:'1920px',
// 显示本地图片 success: async (res) => {
imgArr.value.push(...res.tempFilePaths) // 选择成功,返回本地文件路径列表
let files = res.tempFilePaths;
// console.log('111图片临时路径:', files, res.tempFiles);
files.forEach(async file=>{
let compressImg = file;
// #ifdef APP-PLUS
// 压缩图片
compressImg = await compressImageUni(file);
// console.log("333压缩图片返回=>",compressImg)
// #endif
// 执行上传 // 执行上传
uploadFileMinio(res.tempFiles,'/polling',files).then(res=>{ let param = {
console.log("上传成功后图片路径====>",res) filePath: compressImg,
imgArr2.value = res; name: 'file',
}) formData: {
}, directory:'polling'
fail: (err) => { },
console.log('选择图片失败', err); }
} minioUpload(param).then(res=>{
}); let data = res.data;
// console.log("444图片上传成功=>",data)
imgArr2.value.push(data.fileUrl)
imgArr.value.push(data.fileName)//传给后台的路径
item.resultContent = imgArr.value.join(",")
})
})
},
fail: (err) => {
console.log('选择图片失败', err);
}
});
} catch (error) {
console.log(error)
}
}; };
// 视频处理 // 视频处理
const videoSrc = ref(''); const videoSrc = ref('');
const videoArr = ref([]); const videoArr = ref([]);
const chooseVideo = () => { const videoArr2 = ref([]);
const chooseVideo = (item) => {
uni.chooseVideo({ uni.chooseVideo({
sourceType: ['album', 'camera'], // 来源:相册和相机 sourceType: ['album', 'camera'], // 来源:相册和相机
maxDuration: 60, // 最大时长(秒) maxDuration: 60, // 最大时长(秒)
camera: 'back', // 使用后置摄像头 camera: 'back', // 使用后置摄像头
compressed: true, // 压缩视频 compressed: true, // 压缩视频
success: (res) => { success: (res) => {
videoSrc.value=res.tempFilePath; console.log("res=>",res)
videoArr.value.push(res.tempFilePath) // videoSrc.value=res.tempFilePath;
// videoArr.value.push(res.tempFilePath)
console.log('视频路径:', res.tempFilePath); console.log('视频路径:', res.tempFilePath);
console.log('视频时长:', res.duration); // console.log('视频时长:', res.duration);
console.log('视频大小:', res.size); // console.log('视频大小:', res.size);
// 执行上传
let param = {
filePath: res.tempFilePath,
name: 'file',
formData: {
directory:'polling'
},
}
minioUpload(param).then(uploadRes=>{
let data = uploadRes.data;
videoArr.value.push(data.fileName)//传给后台的路径
videoArr2.value.push(data.fileUrl)
item.resultContent = videoArr.value.join(",")
}).finally(()=>{
})
}, },
fail: (err) => { fail: (err) => {
console.error('选择视频失败:', err); console.error('选择视频失败:', err);
@@ -418,35 +411,40 @@ const chooseVideo = () => {
// nfc 处理 // nfc 处理
let discoveryCallback = null let discoveryCallback = null
const initNFC = () => { const initNFC = async(item) => {
// console.log("initNFC=>",plus)
//这里用异步获取读取到的NFC数据
const nfcId = await nfcUtil.listenNFCStatus();
console.log("initNFC=>",nfcId)
// 确保在 App 环境 // 确保在 App 环境
if (typeof plus === 'undefined') { // if (typeof plus === 'undefined') {
showModel('此功能仅支持 App 端') // showModel3('此功能仅支持 App 端')
return // return
} // }
// 检查设备是否支持NFC // // 检查设备是否支持NFC
if (!plus.nfc) { // if (!plus.nfc) {
showModel('设备不支持 NFC') // showModel3('设备不支持 NFC')
return; // return;
} // }
if (!plus.nfc.isSupportNFC()) { // if (!plus.nfc.isSupportNFC()) {
showModel('设备不支持 NFC') // showModel3('设备不支持 NFC')
return; // return;
} // }
// 检查NFC是否开启 // // 检查NFC是否开启
plus.nfc.isNFCEnabled((enabled) => { // plus.nfc.isNFCEnabled((enabled) => {
if (enabled) { // if (enabled) {
startDiscovery() // startDiscovery()
} else { // } else {
showModel('请先开启设备NFC功能') // showModel3('请先开启设备NFC功能')
} // }
},(error) => { // },(error) => {
console.error('检查NFC状态失败:'+error.message); // console.error('检查NFC状态失败:'+error.message);
showModel('检查NFC状态失败') // showModel3('检查NFC状态失败')
}) // })
} }
// 执行NFC扫描 // 执行NFC扫描
const startDiscovery = () => { const startDiscovery = () => {
@@ -479,27 +477,14 @@ const startDiscovery = () => {
// 扫二维码 // 扫二维码
const scanStr = ref(undefined); const scanStr = ref(undefined);
const handleScan = () => { const handleScan = (item) => {
// 调用扫码API // 调用扫码API
uni.scanCode({ uni.scanCode({
success: (res) => { success: (res) => {
scanStr.value = res.result; scanStr.value = res.result;
console.log('扫码结果:', res.result); // 二维码内容 console.log('扫码结果:', res.result); // 二维码内容
console.log('码类型:', res.scanType); // 码类型,如 QR_CODE console.log('码类型:', res.scanType); // 码类型,如 QR_CODE
// ['optionIds'] = res.result; item.resultContent = res.result
// 处理扫码结果,例如跳转页面
// 如果是URL可以跳转
// if (res.result.startsWith('http')) {
// uni.navigateTo({
// url: '/pages/webview/webview?url=' + encodeURIComponent(res.result)
// });
// } else {
// // 其他内容,如文本,可以展示或处理
// uni.showModal({
// content: `扫描到内容:${res.result}`,
// showCancel: false
// });
// }
}, },
fail: (err) => { fail: (err) => {
console.error('扫码失败:', err); console.error('扫码失败:', err);
@@ -508,9 +493,44 @@ const handleScan = () => {
} }
// 提交 // 提交
let submitParam = {}
let submitLoading = ref(false)
const handleSubmit=()=>{ const handleSubmit=()=>{
showModel('有未完成的巡检项'); submitLoading.value = true;
// showModel2('此巡检项已完成'); let list = optionObj.value.pointList;
let flag = false;
for (let i = 0; i < list.length; i++) {
const item = list[i];
if(!item.resultContent){
flag = true;
break;
}
}
// 如果有未完成的项提示
if(flag){
showModel('有未完成的巡检项');
}
// 循环处理给后台传值
let arr = [];
list.forEach(item => {
arr.push({
pointId:item.pointId,
resultContent:item.resultContent||'',
resultId: item.resultId || undefined
})
});
submitParam = {
taskId:taskId.value,
groupId:groupId.value,
resultList:arr
}
console.log(flag)
// 都答好了直接提交
if(!flag){
handleConfirm();
}
} }
// 自定义弹窗 // 自定义弹窗
@@ -532,37 +552,70 @@ const showModel=(str)=>{
subTime.value=undefined; subTime.value=undefined;
} }
const showModel2=(str)=>{ const showModel2=(str)=>{
visible.value = true;
content.value = str; content.value = str;
subContent.value='提交时间'; subContent.value='提交时间';
btnTxt.value='确定'; btnTxt.value='确定';
btnFlag2.value=false; btnFlag2.value=false;
isGreen.value = true; isGreen.value = true;
subTime.value = new Date().getTime(); visible.value = true;
} }
//关闭 //关闭
const handleClose=()=>{ const handleClose=()=>{
visible.value = false; visible.value = false;
submitLoading.value = false;
} }
// 执行提交 // 执行提交
const handleConfirm=()=>{ const handleConfirm=()=>{
if(isGreen.value){ try {
if(isGreen.value){
visible.value = false;
isGreen.value=false;
}else{
// 执行提交
submitResult(submitParam).then(res=>{
subTime.value = res;
visible.value = false;
console.log("submitResult=>",visible.value)
showModel2('此巡检项已完成');
}).finally(() => {
submitLoading.value = false;
})
}
} catch (error) {
console.log("==========",error)
visible.value = false; visible.value = false;
} }
} }
// 组件卸载时停止监听 // 基础弹窗
const visible3 = ref(false);
const content3 = ref('');
const showModel3=(str)=>{
visible3.value = true;
content3.value = str;
}
const handleClose3=()=>{
visible3.value = false;
submitLoading.value = false;
}
onUnmounted(() => { onUnmounted(() => {
// #ifdef APP-PLUS
if (discoveryCallback) {
plus.nfc.removeEventListener('discovered', discoveryCallback)
}
plus.nfc.stopDiscovery?.()
// #endif
}) })
</script> </script>
<style scoped> <style scoped>
.scroll-h{
/* #ifdef APP-PLUS */
height:calc(100vh - 78px) !important;
/* #endif */
/* #ifndef APP-PLUS */
height: calc(100vh - 60px) !important;
/* #endif */
}
.head-right{} .head-right{}
.head-right .btn-yellow{ .head-right .btn-yellow{
background-color: #FCC123; background-color: #FCC123;
@@ -609,7 +662,7 @@ onUnmounted(() => {
} }
.report-list .r-left{ .report-list .r-left{
display: flex; display: flex;
/* align-items: center; */ align-items: center;
width:70%; width:70%;
font-size:28rpx; font-size:28rpx;
} }
@@ -715,6 +768,9 @@ onUnmounted(() => {
} }
.r-left .r-l-right{ .r-left .r-l-right{
}
.no-data{
padding:200rpx 0 200rpx;
} }
.no-data .no-pic{ .no-data .no-pic{
display: block; display: block;

View File

@@ -16,83 +16,92 @@
<!-- 高度来避免头部遮挡 --> <!-- 高度来避免头部遮挡 -->
<view class="top-height"></view> <view class="top-height"></view>
<view class="white-bg"> <!-- 下拉刷新 -->
<view class="red-title">问题{{problemObj.groupName}}</view> <mescroll-uni ref="mescrollRef" @init="mescrollInit"
<view class="report-list"> :down="downOption" @down="downCallback"
<view class="report-pro">问题项</view> :fixed="false" class="scroll-h"
<view class="report-right"> >
<view class="r-list" v-for="(item, index) in problemObj.list" :key="index"> <view class="white-bg">
<view class="r-left" :class="{'r-red':item.active}"> <view class="red-title">问题{{problemObj.groupName}}</view>
<view>{{String(index+1).padStart(2, '0')+'.'}}</view>
<view>{{ item }}</view>
</view>
<view class="r-right">
<view class="r-r-round" :class="{active:item.active}"></view>
</view>
</view>
</view>
</view>
<view class="report-border"></view>
<view class="report-list">
<view style="width:45%;display:flex;">
<view class="report-pro report-w" style="margin-right:20rpx;">提交人</view>
<view class="report-right report-w">{{problemObj.realname}}</view>
</view>
<view style="width:55%;display:flex;">
<view class="report-pro report-w" style="margin-right:20rpx;">提交时间</view>
<view class="report-right report-w">{{parseTime(problemObj.planTime,'{y}-{m}-{d} {h}:{i}')}}</view>
</view>
</view>
<view class="report-border"></view>
<view class="report-list">问题描述</view>
<view class="report-list report-gray">{{problemObj.problemDesc}}</view>
<view class="report-border"></view>
<view class="report-list">问题点位照片或视频</view>
<view class="report-list">
<block v-for="(item,index) in problemObj.listFile" :key="index">
<view class="img-flex">
<view class="img-show" v-if="getFileType(item)=='image'">
<img :src="item" />
</view>
<view class="img-show" v-else-if="getFileType(item)=='video'">
<video :src="item" controls></video>
</view>
</view>
</block>
</view>
<!-- 当天提的 增加按钮 修改和删除 -->
<view class="btn-con" v-if="isToday">
<button type="primary" @click="handleUpdate" size="mini" style="margin-right:50rpx;" class="btn-primary">修改</button>
<button type="primary" @click="handleDelete" size="mini">删除</button>
</view>
<!-- 追踪列表 -->
<view class="bg-border"></view>
<view v-for="(item,index) in problemObj.logList" :key="index" class="log-con">
<view class="blue-title">
{{parseTime(item.createTime,'{y}-{m}-{d} {h}:{i}')}}
<text style="margin-left:20rpx;">巡检人{{item.modifyUserName}}</text>
</view>
<view class="report-list">检查点跟踪情况描述</view>
<view class="report-list report-gray">{{item.logDesc}}</view>
<view class="report-border"></view>
<view class="report-list">检查点位照片或视频</view>
<view class="report-list"> <view class="report-list">
<view class="img-flex"> <view class="report-pro">问题项</view>
<block v-for="(item,index) in item.listFile" :key="index"> <view class="report-right">
<view class="r-list" v-for="(item, index) in problemObj.list" :key="index">
<view class="r-left" :class="{'r-red':item.active}">
<view>{{String(index+1).padStart(2, '0')+'.'}}</view>
<view>{{ item }}</view>
</view>
<view class="r-right">
<view class="r-r-round" :class="{active:item.active}"></view>
</view>
</view>
</view>
</view>
<view class="report-border"></view>
<view class="report-list">
<view style="width:45%;display:flex;">
<view class="report-pro report-w" style="margin-right:20rpx;">提交人</view>
<view class="report-right report-w">{{problemObj.createUserName}}</view>
</view>
<view style="width:55%;display:flex;">
<view class="report-pro report-w" style="margin-right:20rpx;">提交时间</view>
<view class="report-right report-w">{{parseTime(problemObj.createTime,'{y}-{m}-{d} {h}:{i}')}}</view>
</view>
</view>
<view class="report-border"></view>
<view class="report-list">问题描述</view>
<view class="report-list report-gray">{{problemObj.problemDesc}}</view>
<view class="report-border"></view>
<view class="report-list">问题点位照片或视频</view>
<view class="report-list">
<block v-for="(item,index) in problemObj.listFile" :key="index">
<view class="img-flex">
<view class="img-show" v-if="getFileType(item)=='image'"> <view class="img-show" v-if="getFileType(item)=='image'">
<img :src="item" /> <img :src="item" />
</view> </view>
<view class="img-show" v-else-if="getFileType(item)=='video'"> <view class="img-show" v-else-if="getFileType(item)=='video'">
<video :src="item" controls></video> <video :src="item" controls></video>
</view> </view>
</block> </view>
</view> </block>
</view> </view>
<!-- 当天提的 增加按钮 修改和删除 -->
<view class="btn-con" v-if="isToday">
<button type="primary" @click="handleUpdate" size="mini" style="margin-right:50rpx;" class="btn-primary">修改</button>
<button type="primary" @click="handleDelete" size="mini">删除</button>
</view>
<!-- 追踪列表 -->
<block v-if="problemObj.logList">
<block v-if="problemObj.logList.length>0">
<view class="bg-border"></view>
<view v-for="(item,index) in problemObj.logList" :key="index" class="log-con">
<view class="blue-title">
{{parseTime(item.createTime,'{y}-{m}-{d} {h}:{i}')}}
<text style="margin-left:20rpx;">巡检人{{item.modifyUserName}}</text>
</view>
<view class="report-list">检查点跟踪情况描述</view>
<view class="report-list report-gray">{{item.logDesc}}</view>
<view class="report-border"></view>
<view class="report-list">检查点位照片或视频</view>
<view class="report-list">
<view class="img-flex">
<block v-for="(item,index) in item.listFile" :key="index">
<view class="img-show" v-if="getFileType(item)=='image'">
<img :src="item" />
</view>
<view class="img-show" v-else-if="getFileType(item)=='video'">
<video :src="item" controls></video>
</view>
</block>
</view>
</view>
</view>
</block>
</block>
</view> </view>
</mescroll-uni>
</view>
</view> </view>
</view> </view>
</template> </template>
@@ -101,46 +110,75 @@
import { ref,onMounted,onUnmounted,nextTick,computed,reactive } from 'vue' import { ref,onMounted,onUnmounted,nextTick,computed,reactive } from 'vue'
import { onLoad,onHide} from '@dcloudio/uni-app'; import { onLoad,onHide} from '@dcloudio/uni-app';
import customHeader from '@/components/customHeader.vue'; import customHeader from '@/components/customHeader.vue';
import MescrollUni from 'mescroll-uni/mescroll-uni.vue';
import { parseTime } from '@/utils/datetime.js'; import { parseTime } from '@/utils/datetime.js';
import {getFileType} from '@/utils/common.js' import {getFileType} from '@/utils/common.js';
import { problemDetail } from '@/api/polling.js'
let id=ref(''); let problemId=ref('');
let problemObj = ref({}); let problemObj = ref({});
let isToday = ref(false) let isToday = ref(false)
onLoad(option => { onLoad(option => {
// console.log(option) // console.log(option)
id.value = option.id; problemId.value = option.problemId;
getList();
}) })
// 获取数据列表 // 下拉刷新
const getList = () => { const mescrollRef = ref(null);
// let res = await noticeList(); const mescrollInit = (mescroll) => {
let res = { mescrollRef.value = mescroll;
"code": 200, };
"msg": "操作成功", const downOption = ref({
"data": { auto: true,
groupName:'配电箱箱体和内部线路检查', textInOffset: '下拉刷新',
problemDesc:'电箱右侧箱体有锈蚀,需要及时修补;电箱前门关闭不严,缝隙过大;箱门密封条出现老化痕迹;显示屏出现若干像素坏点。', textOutOffset: '释放更新',
planTime:new Date().getTime(), textLoading: '刷新中...'
realname:'张三', });
pointName:'技术中心机房总电源,监控室消防设备阀门正常开启闭合,监控室10组灭火器压力指针处于绿色区域', // 下拉刷新
problemVedio:'http://192.168.236.196:9000/718ys-test/polling/rotate_2.jpg,http://192.168.236.196:9000/718ys-test/polling/mov_bbb.mp4', const downCallback = async (mescroll) => {
logList:[ try {
{ getList();
logId:1,logDesc:'配电箱箱体和内部线路检查',createTime:new Date().getTime(),modifyUserName:'张三', } catch (error) {
logVedio:'http://192.168.236.196:9000/718ys-test/polling/mov_bbb.mp4,http://192.168.236.196:9000/718ys-test/polling/rotate_2.jpg,http://192.168.236.196:9000/718ys-test/polling/mov_bbb.mp4,http://192.168.236.196:9000/718ys-test/polling/rotate_2.jpg,http://192.168.236.196:9000/718ys-test/polling/mov_bbb.mp4,http://192.168.236.196:9000/718ys-test/polling/rotate_2.jpg', mescroll.endErr();
} } finally {
] mescroll.endSuccess();
}
} }
let data = res.data || {}; }
// 获取数据列表
const getList = async() => {
isToday.value = false;
let data = await problemDetail({problemId:problemId.value});
// let res = {
// "code": 200,
// "msg": "操作成功",
// "data": {
// groupName:'配电箱箱体和内部线路检查',
// problemDesc:'电箱右侧箱体有锈蚀,需要及时修补;电箱前门关闭不严,缝隙过大;箱门密封条出现老化痕迹;显示屏出现若干像素坏点。',
// planTime:new Date().getTime(),
// realname:'张三',
// pointName:'技术中心机房总电源,监控室消防设备阀门正常开启闭合,监控室10组灭火器压力指针处于绿色区域',
// problemVedio:'http://192.168.236.196:9000/718ys-test/polling/rotate_2.jpg,http://192.168.236.196:9000/718ys-test/polling/mov_bbb.mp4',
// logList:[
// {
// logId:1,logDesc:'配电箱箱体和内部线路检查',createTime:new Date().getTime(),modifyUserName:'张三',
// logVedio:'http://192.168.236.196:9000/718ys-test/polling/mov_bbb.mp4,http://192.168.236.196:9000/718ys-test/polling/rotate_2.jpg,http://192.168.236.196:9000/718ys-test/polling/mov_bbb.mp4,http://192.168.236.196:9000/718ys-test/polling/rotate_2.jpg,http://192.168.236.196:9000/718ys-test/polling/mov_bbb.mp4,http://192.168.236.196:9000/718ys-test/polling/rotate_2.jpg',
// }
// ]
// }
// }
data.list = data.pointName.split(",") || []; data.list = data.pointName.split(",") || [];
data.listFile=data.problemVedio.split(",") || []; data.listFile=data.problemVedio.split(",") || [];
data.logList.forEach(item => { data.logList.forEach(item => {
item.listFile = item.logVedio.split(",")||[] item.listFile = item.logVedio.split(",")||[]
}); });
// 判断是否当天创建的,显示按钮
let createTime = parseTime(data.createTime,'{y}-{m}-{d}');
let dateNow = parseTime(new Date().getTime(),'{y}-{m}-{d}');
if(createTime == dateNow){
isToday.value = true;
}
problemObj.value = data; problemObj.value = data;
} }
@@ -154,7 +192,7 @@ const handleQuestion=()=>{
// 修改 // 修改
const handleUpdate=()=>{ const handleUpdate=()=>{
uni.navigateTo({ uni.navigateTo({
url: '/pages/business/polling/problemReport?id='+id.value url: '/pages/business/polling/problemReport?problemId='+problemId.value
}); });
} }
@@ -165,6 +203,17 @@ const handleDelete=()=>{
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.scroll-h{
/* #ifdef APP-PLUS */
height:calc(100vh - 78px) !important;
/* #endif */
/* #ifndef APP-PLUS */
height: calc(100vh - 58px) !important;
/* #endif */
}
:deep(.mescroll-upwarp){
display: none !important;
}
.head-right{} .head-right{}
.head-right .btn-yellow{ .head-right .btn-yellow{
background-color: #FCC123; background-color: #FCC123;

View File

@@ -34,9 +34,9 @@
:up="upOption" :down="downOption" :fixed="false" class="scroll-h" :class="{'loading-scroll':cssFlag}"> :up="upOption" :down="downOption" :fixed="false" class="scroll-h" :class="{'loading-scroll':cssFlag}">
<view class="white-bg" :class="{'bg-height':list.length<8}"> <view class="white-bg" :class="{'bg-height':list.length<8}">
<block v-if="list.length>0"> <block v-if="list.length>0">
<view class="report-list" v-for="(item, index) in list" :key="index" @click="handleDetail(item,2)"> <view class="report-list" v-for="(item, index) in list" :key="index" @click="handleDetail(item)">
<view class="r-list" style="padding-bottom:0"> <view class="r-list" style="padding-bottom:0">
<view class="r-name">{{ item.problemDesc }}</view> <view class="r-name">{{ item.groupName }}</view>
<view class="r-right"> <view class="r-right">
<!-- 问题状态 1=追踪2=关闭 --> <!-- 问题状态 1=追踪2=关闭 -->
<view v-if="item.problemStatus==1" class="btn-red">进行中</view> <view v-if="item.problemStatus==1" class="btn-red">进行中</view>
@@ -45,8 +45,8 @@
</view> </view>
<view class="r-list"> <view class="r-list">
<view class="r-left"> <view class="r-left">
<view class="r-l-left" style="width:220rpx">跟踪次数<span class="r-gray">{{ item.count }}</span></view> <view class="r-l-left" style="width:220rpx">跟踪次数<span class="r-gray">{{ item.logNum }}</span></view>
<view class="r-l-right">最近跟踪时间<span class="r-gray">{{parseTime(item.modifyTime,'{m}-{d} {h}:{i}') }}</span></view> <view class="r-l-right">最近跟踪时间<span class="r-gray">{{parseTime(item.lastLogTime,'{m}-{d} {h}:{i}') }}</span></view>
</view> </view>
</view> </view>
<view class="report-border" v-if="index<list.length-1"></view> <view class="report-border" v-if="index<list.length-1"></view>
@@ -70,6 +70,7 @@ import MescrollUni from 'mescroll-uni/mescroll-uni.vue';
import { getNavBarPaddingTop } from '@/utils/system.js' import { getNavBarPaddingTop } from '@/utils/system.js'
import { noticeList } from '@/api/notice.js' import { noticeList } from '@/api/notice.js'
import { parseTime } from '@/utils/datetime.js' import { parseTime } from '@/utils/datetime.js'
import { problemList } from '@/api/polling.js'
onLoad(async(opt) => { onLoad(async(opt) => {
uni.setStorageSync('page_cache',true); uni.setStorageSync('page_cache',true);
@@ -149,7 +150,7 @@ const mescrollInit = (mescroll) => {
const downCallback = async (mescroll) => { const downCallback = async (mescroll) => {
try { try {
console.log("下拉刷新") console.log("下拉刷新")
const res = await getNoticeList(1, upOption.value.page.size); const res = await getList(1, upOption.value.page.size);
cssFlag.value = false; cssFlag.value = false;
list.value = res.list; list.value = res.list;
mescroll.resetUpScroll(); mescroll.resetUpScroll();
@@ -165,7 +166,7 @@ const downCallback = async (mescroll) => {
const upCallback = async (mescroll) => { const upCallback = async (mescroll) => {
try { try {
console.log("上拉加载更多") console.log("上拉加载更多")
let res = await getNoticeList(mescroll.num, mescroll.size); let res = await getList(mescroll.num, mescroll.size);
if (mescroll.num === 1) { if (mescroll.num === 1) {
list.value = res.list; list.value = res.list;
} else { } else {
@@ -178,95 +179,95 @@ const upCallback = async (mescroll) => {
} }
// 获取数据列表 // 获取数据列表
const getNoticeList = (pageIndex, pageSize) => { const getList = (pageIndex, pageSize) => {
return new Promise(async (resolve) => { return new Promise(async (resolve) => {
let param = { let param = {
pageIndex, pageIndex,
pageSize, pageSize,
searchValue:searchText.value?searchText.value:undefined, key:searchText.value?searchText.value:undefined,
taskType:notictTypeCheck.value.id taskType:notictTypeCheck.value.id
} }
// let res = await noticeList(param); let res = await problemList(param);
let res={ // let res={
"code": 200, // "code": 200,
"msg": "操作成功", // "msg": "操作成功",
"data": { // "data": {
list:[ // list:[
{ // {
problemDesc:'西区地下车库入口防汛物资摆放', // problemDesc:'西区地下车库入口防汛物资摆放',
problemId:202512297899, // problemId:202512297899,
problemStatus:1, // problemStatus:1,
modifyTime:new Date().getTime(), // modifyTime:new Date().getTime(),
count:0, // count:0,
}, // },
{ // {
problemDesc:'监控室消防设备阀门确保正常开启闭合', // problemDesc:'监控室消防设备阀门确保正常开启闭合',
problemId:202512297899, // problemId:202512297899,
problemStatus:2, // problemStatus:2,
modifyTime:new Date().getTime(), // modifyTime:new Date().getTime(),
count:20, // count:20,
}, // },
{ // {
problemDesc:'西区地下车库入口防汛物资摆放', // problemDesc:'西区地下车库入口防汛物资摆放',
problemId:202512297899, // problemId:202512297899,
problemStatus:1, // problemStatus:1,
modifyTime:new Date().getTime(), // modifyTime:new Date().getTime(),
count:0, // count:0,
}, // },
{ // {
problemDesc:'监控室消防设备阀门确保正常开启闭合', // problemDesc:'监控室消防设备阀门确保正常开启闭合',
problemId:202512297899, // problemId:202512297899,
problemStatus:2, // problemStatus:2,
modifyTime:new Date().getTime(), // modifyTime:new Date().getTime(),
count:20, // count:20,
},{ // },{
problemDesc:'西区地下车库入口防汛物资摆放', // problemDesc:'西区地下车库入口防汛物资摆放',
problemId:202512297899, // problemId:202512297899,
problemStatus:1, // problemStatus:1,
modifyTime:new Date().getTime(), // modifyTime:new Date().getTime(),
count:0, // count:0,
}, // },
{ // {
problemDesc:'监控室消防设备阀门确保正常开启闭合', // problemDesc:'监控室消防设备阀门确保正常开启闭合',
problemId:202512297899, // problemId:202512297899,
problemStatus:2, // problemStatus:2,
modifyTime:new Date().getTime(), // modifyTime:new Date().getTime(),
count:20, // count:20,
}, // },
{ // {
problemDesc:'监控室消防设备阀门确保正常开启闭合', // problemDesc:'监控室消防设备阀门确保正常开启闭合',
problemId:202512297899, // problemId:202512297899,
problemStatus:2, // problemStatus:2,
modifyTime:new Date().getTime(), // modifyTime:new Date().getTime(),
count:20, // count:20,
}, // },
{ // {
problemDesc:'监控室消防设备阀门确保正常开启闭合', // problemDesc:'监控室消防设备阀门确保正常开启闭合',
problemId:202512297899, // problemId:202512297899,
problemStatus:2, // problemStatus:2,
modifyTime:new Date().getTime(), // modifyTime:new Date().getTime(),
count:20, // count:20,
}, // },
{ // {
problemDesc:'监控室消防设备阀门确保正常开启闭合', // problemDesc:'监控室消防设备阀门确保正常开启闭合',
problemId:202512297899, // problemId:202512297899,
problemStatus:2, // problemStatus:2,
modifyTime:new Date().getTime(), // modifyTime:new Date().getTime(),
count:20, // count:20,
}, // },
{ // {
problemDesc:'监控室消防设备阀门确保正常开启闭合', // problemDesc:'监控室消防设备阀门确保正常开启闭合',
problemId:202512297899, // problemId:202512297899,
problemStatus:2, // problemStatus:2,
modifyTime:new Date().getTime(), // modifyTime:new Date().getTime(),
count:20, // count:20,
} // }
], // ],
recordCount:2 // recordCount:2
} // }
} // }
let list = res.data.list || []; let list = res.list || [];
resolve({ resolve({
list, list,
@@ -277,8 +278,8 @@ const getNoticeList = (pageIndex, pageSize) => {
} }
// 查看详情 // 查看详情
const handleDetail = (item,type) =>{ const handleDetail = (item) =>{
let url= '/pages/business/polling/problemDetail?id='+item.taskId; let url= '/pages/business/polling/problemDetail?problemId='+item.problemId;
uni.navigateTo({ uni.navigateTo({
url url
}); });

View File

@@ -8,53 +8,66 @@
<!-- 高度来避免头部遮挡 --> <!-- 高度来避免头部遮挡 -->
<view class="top-height"></view> <view class="top-height"></view>
<view class="white-bg"> <!-- 下拉刷新 -->
<view class="red-title">问题{{optionObj.optionName}}</view> <mescroll-uni ref="mescrollRef" @init="mescrollInit"
<view class="report-list"> :down="downOption" @down="downCallback"
<view class="report-pro">问题项</view> :fixed="false" class="scroll-h"
<view class="report-right"> >
<view class="r-list" v-for="(item, index) in optionObj.list" :key="index" @click="handleRound(item)"> <view class="white-bg">
<view class="r-left" :class="{'r-red':item.active}"> <view class="red-title">问题{{optionObj.groupName}}</view>
<view>{{String(index+1).padStart(2, '0')+'.'}}</view> <view class="report-list">
<view>{{ item.pointName }}</view> <view class="report-pro">问题项</view>
</view> <view class="report-right">
<view class="r-right"> <view class="r-list" v-for="(item, index) in optionObj.pointList" :key="index" @click="handleRound(item)">
<view class="r-r-round" :class="{active:item.active}"></view> <view class="r-left" :class="{'r-red':item.active}">
<view>{{String(index+1).padStart(2, '0')+'.'}}</view>
<view>{{ item.pointName }}</view>
</view>
<view class="r-right">
<view class="r-r-round" :class="{active:item.active}"></view>
</view>
</view> </view>
</view> </view>
</view> </view>
</view> <view class="report-border"></view>
<view class="report-border"></view> <view class="report-list">
<view class="report-list"> <view class="report-pro">提交人</view>
<view class="report-pro">提交人</view> <view class="report-right">{{optionObj.createUserName?optionObj.createUserName:realname}}</view>
<view class="report-right">{{realname}}</view> </view>
</view> <view class="report-border"></view>
<view class="report-border"></view> <view class="report-list" style="display:block;">
<view class="report-list" style="display:block;"> 问题描述
问题描述 <textarea class="r-input textarea" v-model="optionObj.problemDesc" auto-height
<textarea class="r-input textarea" v-model="desc" auto-height placeholder="请输入问题项描述" placeholder-class="place-input"
placeholder="请输入问题项描述" placeholder-class="place-input" ></textarea>
></textarea> </view>
</view> <view class="report-border"></view>
<view class="report-border"></view> <view class="report-list" style="display:block;">
<view class="report-list" style="display:block;"> <view class="r-title">问题点位照片或视频 <text>*</text></view>
<view class="r-title">问题点位照片或视频 <text>*</text></view> <view class="img-flex">
<view class="img-flex"> <view class="img-show" v-for="(item,index) in imgArr" :key="index">
<view class="img-show" v-for="(item,index) in imgArr" :key="index"> <img :src="item" />
<img :src="item" /> </view>
</view> <view class="img-show" v-for="(item,index) in videoArr" :key="index">
<view class="img-show" v-for="(item,index) in videoArr" :key="index"> <video :src="item" controls></video>
<video :src="item" controls></video> </view>
</view> <!-- #ifdef APP-PLUS -->
<view class="img-con" @click="chooseMedia"> <view class="img-con" @click="chooseMedia">
<img :src="'static/images/polling/icon-AddPorV.png'" class="img-pic" /> <img :src="'static/images/polling/icon-AddPorV.png'" class="img-pic" />
</view>
<!-- #endif -->
<!-- #ifndef APP-PLUS -->
<view class="img-con">
<img :src="'static/images/polling/icon-AddPorV.png'" class="img-pic" />
</view>
<!-- #endif -->
</view> </view>
</view> </view>
<view class="btn-submit">
<button type="primary" @click="handleSubmit">{{problemId?'修改问题跟踪表':'生成问题跟踪表'}}</button>
</view>
</view> </view>
<view class="btn-submit"> </mescroll-uni>
<button type="primary" @click="handleSubmit">{{id?'修改问题跟踪表':'生成问题跟踪表'}}</button>
</view>
</view>
</view> </view>
</view> </view>
</template> </template>
@@ -65,71 +78,117 @@ import { onLoad,onHide} from '@dcloudio/uni-app';
import customHeader from '@/components/customHeader.vue'; import customHeader from '@/components/customHeader.vue';
import MescrollUni from 'mescroll-uni/mescroll-uni.vue'; import MescrollUni from 'mescroll-uni/mescroll-uni.vue';
import { getUserInfo } from '@/api/auth.js' import { getUserInfo } from '@/api/auth.js'
import { problemDetail,problemAdd,problemEdit,minioUpload } from '@/api/polling.js'
import {compressImageUni,getMinioThumbUrl} from '@/utils/common.js'
import {showAlert,showLoading,hideLoading} from '@/utils/message.js'
let id = ref(''); let taskId = ref('');//任务id
let groupId = ref('');//组id
let problemId = ref('');//问题id
let realname = ref(''); let realname = ref('');
let desc = ref('');//描述 let desc = ref('');//描述
onLoad(async option => { onLoad(async option => {
// console.log(option) // console.log(option)
id.value = option.id; taskId.value = option.taskId;
groupId.value = option.groupId;
problemId.value = option.problemId;
let userinfo = await getUserInfo({}); let userinfo = await getUserInfo({});
realname.value = userinfo.realname realname.value = userinfo.realname
getList();
}) })
// 查询列表 // 查询列表
let list = ref([]); let list = ref([]);
let optionObj = ref({}) let optionObj = ref({})
// 获取数据列表 // 下拉刷新
const getList = () => { const mescrollRef = ref(null);
// let res = await noticeList(); const mescrollInit = (mescroll) => {
// 1 单选 2多选 3判断 4问答 5 读卡 6 扫码 7 拍照 8 视频 9 定位 mescrollRef.value = mescroll;
let res = { };
"code": 200, const downOption = ref({
"msg": "操作成功", auto: true,
"data": { textInOffset: '下拉刷新',
optionName:'配电箱箱体和内部线路检查', textOutOffset: '释放更新',
planTime:new Date().getTime(), textLoading: '刷新中...'
list:[ });
{ pointName:'技术中心机房总电源', optionId:202512297899, pointType:1}, // 下拉刷新
{ pointName:'监控室消防设备阀门正常开启闭合', optionId:202512297899, pointType:2}, const downCallback = async (mescroll) => {
{ pointName:'监控室10组灭火器压力指针处于绿色区域', optionId:202512297899, pointType:3,active:true}, try {
{ pointName:'库房灭火器压力指针处于绿色区', optionId:202512297899,pointType:4,active:true}, getList();
{ pointName:'技术中心机房总电源', optionId:202512297899,pointType:5}, } catch (error) {
{ pointName:'监控室消防设备阀门正常监控室消防设备阀门正常监控室消防设备阀门正常', optionId:202512297899,pointType:6}, mescroll.endErr();
{ pointName:'库房灭火器压力指针处于绿色区', optionId:202512297899,pointType:7}, } finally {
{ pointName:'技术中心机房总电源', optionId:202512297899,pointType:8}, mescroll.endSuccess();
],
}
} }
optionObj.value = res.data||{}; }
// 获取数据列表
const getList = async () => {
let param = {
taskId:problemId.value?undefined:taskId.value,
groupId:problemId.value?undefined:groupId.value,
problemId:problemId.value
}
let res = await problemDetail(param);
let data = res||{};
let pointIds = data.pointId.split(",");
data.pointList.forEach(item2=>{
item2.active=false;
for (let i = 0; i < pointIds.length; i++) {
if(item2.pointId == pointIds[i]){
item2.active=true;
break;
}
}
})
optionObj.value = data;
} }
// 图片或视频 // 图片或视频
let imgArr = ref([]);//视频 let mediaArr = ref([]);//传给后台的地址
let videoArr = ref([]);//视频 let imgArr=ref([]);//图片 后台返回的
const imgArr2=ref([]); let videoArr = ref([]);//视频 后台返回的
const chooseMedia = () => { const chooseMedia = () => {
imgArr.value=[];
videoArr.value=[];
uni.chooseMedia({ uni.chooseMedia({
count: 9, count: 9,
mediaType: ['image', 'video'], // 指定可选择图片和视频 mediaType: ['image', 'video'], // 指定可选择图片和视频
sourceType: ['album', 'camera'], sourceType: ['album', 'camera'],
maxDuration: 30, // 拍摄视频最长拍摄时间 maxDuration: 60, // 拍摄视频最长拍摄时间
camera: 'back', camera: 'back',
success: (res) => { success: (res) => {
console.log(res) console.log(res)
res.tempFiles.forEach(file => { res.tempFiles.forEach(async file => {
// tempFilePath
console.log(`文件类型: ${file.fileType}, 文件路径: ${file.tempFilePath}`); console.log(`文件类型: ${file.fileType}, 文件路径: ${file.tempFilePath}`);
let compressImg = file.tempFilePath;
// 图片进行压缩
if (file.fileType === 'image') { if (file.fileType === 'image') {
// 显示本地图片 // #ifdef APP-PLUS
imgArr.value.push(file.tempFilePath) // 压缩图片
} else if (file.type === 'video') { compressImg = await compressImageUni(file.tempFilePath);
// 处理视频 // #endif
videoArr.value.push(file.tempFilePath)
} }
// 执行上传
let param = {
filePath: compressImg,
name: 'file',
formData: {
directory:'polling'
},
}
minioUpload(param).then(res=>{
let data = res.data;
mediaArr.value.push(data.fileName);
if (file.fileType === 'image') {// 图片
imgArr.value.push(data.fileUrl)
} else if (file.type === 'video') {// 视频
videoArr.value.push(data.fileUrl)
}
})
}); });
} }
}); });
@@ -142,12 +201,58 @@ const handleRound=(item)=>{
// 提交 // 提交
const handleSubmit=()=>{ const handleSubmit=()=>{
// showModel('有未完成的巡检项'); let pointIds = [];
// showModel2('此巡检项已完成'); optionObj.value.pointList.forEach(item => {
if(item.active){
pointIds.push(item.pointId)
}
});
showLoading("加载中...")
if(problemId.value){
let param = {
problemId:problemId.value,
pointId:pointIds.join(","),
problemVedio:mediaArr.value.join(","),
problemDesc:optionObj.problemDesc
}
console.log("problemEdit=>",param)
problemEdit(param).then(res=>{
showAlert("新增上报问题成功")
}).finally(()=>{
hideLoading();
})
}else{
let param = {
taskId:taskId.value,
groupId:groupId.value,
pointId:pointIds.join(","),
problemVedio:mediaArr.value.join(","),
problemDesc:optionObj.problemDesc
}
console.log("problemAdd=>",param)
problemAdd(param).then(res=>{
showAlert("编辑上报问题成功")
}).finally(()=>{
hideLoading();
})
}
} }
</script> </script>
<style scoped> <style scoped>
.scroll-h{
/* #ifdef APP-PLUS */
height:calc(100vh - 78px) !important;
/* #endif */
/* #ifndef APP-PLUS */
height: calc(100vh - 58px) !important;
/* #endif */
}
:deep(.mescroll-upwarp){
display: none !important;
}
.white-bg{ .white-bg{
width: 680rpx; width: 680rpx;
padding: 15rpx 30rpx 40rpx 40rpx; padding: 15rpx 30rpx 40rpx 40rpx;
@@ -211,7 +316,7 @@ const handleSubmit=()=>{
} }
.report-list .r-left{ .report-list .r-left{
display: flex; display: flex;
/* align-items: center; */ align-items: center;
width:90%; width:90%;
font-size:28rpx; font-size:28rpx;
color:#919191; color:#919191;

View File

@@ -39,15 +39,15 @@
<view class="calender-list"> <view class="calender-list">
<view class="calender-item"> <view class="calender-item">
<view class="item-blue">{{count1}}</view> <view class="item-blue">{{count1}}</view>
<view class="font28">待巡检</view>
</view>
<view class="calender-item">
<view class="item-blue">{{count2}}</view>
<view class="font28">已巡检</view> <view class="font28">已巡检</view>
</view> </view>
<view class="calender-item">
<view :class="{'item-red':count2>0,'item-blue':count2==0}">{{count2}}</view>
<view class="font28">待巡检</view>
</view>
<view class="calender-item"> <view class="calender-item">
<view class="item-red">{{count3}}</view> <view class="item-red">{{count3}}</view>
<view class="font28">未完成</view> <view class="font28">已过期</view>
</view> </view>
</view> </view>
</view> </view>
@@ -64,55 +64,60 @@
<block v-for="(row,index) in list" :key="index"> <block v-for="(row,index) in list" :key="index">
<!-- 日期展示 --> <!-- 日期展示 parseTime(row.date,'{y}-{m}-{d} 星期{a}')-->
<view class="date-title">{{parseTime(row.date,'{y}-{m}-{d} 星期{a}')}}</view> <view class="date-title">{{row.day}}</view>
<!-- 日常巡检 --> <!-- 日常巡检 -->
<view class="blue-title">日常巡检</view> <view class="blue-title">日常巡检</view>
<block v-if="row.list1.length>0"> <block v-if="row.list1">
<view class="report-list" v-for="(item, index) in row.list1" :key="index" @click="handleDetail(item,1)"> <block v-if="row.list1.length>0">
<view class="r-list" style="padding-bottom:0"> <view class="report-list" v-for="(item, index) in row.list1" :key="index" @click="handleDetail(item,1)">
<view class="r-name">{{ item.taskName }}</view> <view class="r-list" style="padding-bottom:0">
<view class="r-right"> <view class="r-name">{{ item.taskName }}</view>
<!-- 任务(巡检)状态 1=未发布 2=已发布 3 进行中 4 已完成 5 已过期 --> <view class="r-right">
<!-- 状态为3进行中时 进度>0执行中 进度=0为待执行 --> <!-- 任务(巡检)状态 1=未发布 2=已发布 3 进行中 4 已完成 5 已过期 -->
<block v-if="item.taskStatus==3"> <!-- 状态为3进行中时 进度>0执行中 进度=0为待执行 -->
<img v-if="item.count==0" :src="'static/images/polling/icon-start.png'" class="img-w" /> <block v-if="item.taskStatus==3">
<img v-else :src="'static/images/polling/icon-pending.png'" class="img-w" /> <img v-if="item.groupFinishNum==0" :src="'static/images/polling/icon-start.png'" class="img-w" />
</block> <img v-else :src="'static/images/polling/icon-pending.png'" class="img-w" />
<img v-else-if="item.taskStatus==4" :src="'static/images/polling/icon-complete.png'" class="img-complete" /> </block>
<img v-else-if="item.taskStatus==5" :src="'static/images/polling/icon-Expired.png'" class="img-w" /> <img v-else-if="item.taskStatus==4" :src="'static/images/polling/icon-complete.png'" class="img-complete" />
</view> <img v-else-if="item.taskStatus==5" :src="'static/images/polling/icon-Expired.png'" class="img-w" />
</view>
<view class="r-list">
<view class="r-left">巡检单号<span class="r-gray">{{ item.taskId }}</span></view>
</view>
<view class="r-list">
<view class="r-left">
<view class="r-l-left">开始时间<span class="r-gray">{{ item.planTime }}</span></view>
<view class="r-l-right">任务时长<span class="r-gray">{{ item.workHour }}小时</span></view>
</view>
</view>
<view class="r-list">
<view class="r-left">
<view class="r-l-left">
完成进度<span class="r-gray"><span :class="{'r-red':item.count<item.total}">{{item.count}}</span>/{{item.total}}</span>
</view>
<view class="r-l-right">完成比率<span class="r-blue">{{item.percentage}}</span></view>
</view>
</view>
<view class="r-list">
<view class="r-left">
<view>任务状态
<span class="r-gray" v-if="item.taskStatus==3">
<block v-if="item.count==0">待执行</block>
<block v-else>执行中</block>
</span>
<span class="r-gray" v-else>{{formatTaskStatus(item.taskStatus) }}</span>
</view> </view>
</view> </view>
<view class="r-list">
<view class="r-left">巡检单号<span class="r-gray">{{ item.taskId }}</span></view>
</view>
<view class="r-list">
<view class="r-left">
<view class="r-l-left">开始时间<span class="r-gray">{{ parseTime(item.planTime,'{h}:{i}') }}</span></view>
<view class="r-l-right">任务时长<span class="r-gray">{{ item.workHour }}小时</span></view>
</view>
</view>
<view class="r-list">
<view class="r-left">
<view class="r-l-left">
完成进度<span class="r-gray"><span :class="{'r-red':item.groupFinishNum<item.groupNum}">{{item.groupFinishNum}}</span>/{{item.groupNum}}</span>
</view>
<view class="r-l-right">完成比率<span class="r-blue">{{item.percentage}}</span></view>
</view>
</view>
<view class="r-list">
<view class="r-left">
<view>任务状态
<span class="r-gray" v-if="item.taskStatus==3">
<block v-if="item.groupFinishNum==0">待执行</block>
<block v-else>执行中</block>
</span>
<span class="r-gray" v-else>{{formatTaskStatus(item.taskStatus) }}</span>
</view>
</view>
</view>
<view class="report-border" v-if="index<row.list1.length-1"></view>
</view> </view>
<view class="report-border" v-if="index<row.list1.length-1"></view> </block>
<view v-else class="no-data">
<img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" />
</view> </view>
</block> </block>
<view v-else class="no-data"> <view v-else class="no-data">
@@ -121,82 +126,93 @@
<!-- 临时巡检 --> <!-- 临时巡检 -->
<view class="green-title" style="margin-top:60rpx">临时巡检</view> <view class="green-title" style="margin-top:60rpx">临时巡检</view>
<block v-if="row.list2.length>0"> <block v-if="row.list2">
<view class="report-list" v-for="(item, index) in row.list2" :key="index" @click="handleDetail(item,1)"> <block v-if="row.list2.length>0">
<view class="r-list" style="padding-bottom:0"> <view class="report-list" v-for="(item, index) in row.list2" :key="index" @click="handleDetail(item,1)">
<view class="r-name">{{ item.taskName }}</view> <view class="r-list" style="padding-bottom:0">
<view class="r-right"> <view class="r-name">{{ item.taskName }}</view>
<!-- 任务(巡检)状态 1=未发布 2=已发布 3 进行中 4 已完成 5 已过期 --> <view class="r-right">
<!-- 状态为3进行中时 进度>0执行中 进度=0为待执行 --> <!-- 任务(巡检)状态 1=未发布 2=已发布 3 进行中 4 已完成 5 已过期 -->
<block v-if="item.taskStatus==3"> <!-- 状态为3进行中时 进度>0执行中 进度=0为待执行 -->
<img v-if="item.count==0" :src="'static/images/polling/icon-start.png'" class="img-w" /> <block v-if="item.taskStatus==3">
<img v-else :src="'static/images/polling/icon-pending.png'" class="img-w" /> <img v-if="item.groupFinishNum==0" :src="'static/images/polling/icon-start.png'" class="img-w" />
</block> <img v-else :src="'static/images/polling/icon-pending.png'" class="img-w" />
<img v-else-if="item.taskStatus==4" :src="'static/images/polling/icon-complete.png'" class="img-complete" /> </block>
<img v-else-if="item.taskStatus==5" :src="'static/images/polling/icon-Expired.png'" class="img-w" /> <img v-else-if="item.taskStatus==4" :src="'static/images/polling/icon-complete.png'" class="img-complete" />
</view> <img v-else-if="item.taskStatus==5" :src="'static/images/polling/icon-Expired.png'" class="img-w" />
</view>
<view class="r-list">
<view class="r-left">巡检单号<span class="r-gray">{{ item.taskId }}</span></view>
</view>
<view class="r-list">
<view class="r-left">
<view class="r-l-left">开始时间<span class="r-gray">{{ item.planTime }}</span></view>
<view class="r-l-right">任务时长<span class="r-gray">{{ item.workHour }}小时</span></view>
</view>
</view>
<view class="r-list">
<view class="r-left">
<view class="r-l-left">
完成进度<span class="r-gray"><span :class="{'r-red':item.count<item.total}">{{item.count}}</span>/{{item.total}}</span>
</view>
<view class="r-l-right">完成比率<span class="r-blue">{{item.percentage}}</span></view>
</view>
</view>
<view class="r-list">
<view class="r-left">
<view>任务状态
<span class="r-gray" v-if="item.taskStatus==3">
<block v-if="item.count==0">待执行</block>
<block v-else>执行中</block>
</span>
<span class="r-gray" v-else>{{formatTaskStatus(item.taskStatus) }}</span>
</view> </view>
</view> </view>
<view class="r-list">
<view class="r-left">巡检单号<span class="r-gray">{{ item.taskId }}</span></view>
</view>
<view class="r-list">
<view class="r-left">
<view class="r-l-left">开始时间<span class="r-gray">{{ parseTime(item.planTime,'{h}:{i}') }}</span></view>
<view class="r-l-right">任务时长<span class="r-gray">{{ item.workHour }}小时</span></view>
</view>
</view>
<view class="r-list">
<view class="r-left">
<view class="r-l-left">
完成进度<span class="r-gray"><span :class="{'r-red':item.groupFinishNum<item.groupNum}">{{item.groupFinishNum}}</span>/{{item.groupNum}}</span>
</view>
<view class="r-l-right">完成比率<span class="r-blue">{{item.percentage}}</span></view>
</view>
</view>
<view class="r-list">
<view class="r-left">
<view>任务状态
<span class="r-gray" v-if="item.taskStatus==3">
<block v-if="item.groupFinishNum==0">待执行</block>
<block v-else>执行中</block>
</span>
<span class="r-gray" v-else>{{formatTaskStatus(item.taskStatus) }}</span>
</view>
</view>
</view>
<view class="report-border" v-if="index<row.list2.length-1"></view>
</view> </view>
<view class="report-border" v-if="index<row.list2.length-1"></view> </block>
<view v-else class="no-data">
<img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" />
</view> </view>
</block> </block>
<view v-else class="no-data"> <view v-else class="no-data">
<img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" /> <img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" />
</view> </view>
<!-- 问题跟踪 --> <!-- 问题跟踪 按月没有问题跟踪-->
<view class="bg-border"></view> <block v-if="activeTab==0">
<view class="red-title">问题跟踪</view> <view class="bg-border"></view>
<block v-if="row.list3.length>0"> <view class="red-title">问题跟踪</view>
<view class="report-list" v-for="(item, index) in row.list3" :key="index" @click="handleDetail(item,2)"> <block v-if="row.list3">
<view class="r-list" style="padding-bottom:0"> <block v-if="row.list3.length>0">
<view class="r-name">{{ item.problemDesc }}</view> <view class="report-list" v-for="(item, index) in row.list3" :key="index" @click="handleDetail(item,2)">
<view class="r-right"> <view class="r-list" style="padding-bottom:0">
<!-- 问题状态 1=追踪2=关闭 --> <view class="r-name">{{ item.groupName }}</view>
<view v-if="item.problemStatus==1" class="btn-red">进行中</view> <view class="r-right">
<view v-if="item.problemStatus==2" class="btn-green">已解决</view> <!-- 问题状态 1=追踪2=关闭 -->
<view v-if="item.problemStatus==1" class="btn-red">进行中</view>
<view v-if="item.problemStatus==2" class="btn-green">已解决</view>
</view>
</view>
<view class="r-list">
<view class="r-left">
<view class="r-l-left" style="width:220rpx">跟踪次数<span class="r-gray">{{ item.logNum }}</span></view>
<view class="r-l-right">最近跟踪时间<span class="r-gray">{{ parseTime(item.lastLogTime,'{m}-{d} {h}:{i}') }}</span></view>
</view>
</view>
<view class="report-border" v-if="index<row.list3.length-1"></view>
</view> </view>
</block>
<view v-else class="no-data">
<img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" />
</view> </view>
<view class="r-list"> </block>
<view class="r-left"> <view v-else class="no-data">
<view class="r-l-left" style="width:220rpx">跟踪次数<span class="r-gray">{{ item.count }}</span></view> <img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" />
<view class="r-l-right">最近跟踪时间<span class="r-gray">{{ parseTime(item.modifyTime,'{m}-{d} {h}:{i}') }}</span></view>
</view>
</view>
<view class="report-border" v-if="index<row.list3.length-1"></view>
</view> </view>
</block> </block>
<view v-else class="no-data">
<img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" />
</view>
</block> </block>
</view> </view>
</mescroll-uni> </mescroll-uni>
@@ -213,31 +229,39 @@ import calenderMonthSimple from '@/components/calenderMonthSimple.vue'
import customTabs from '@/components/customTabs.vue'; import customTabs from '@/components/customTabs.vue';
import { parseTime } from '@/utils/datetime.js'; import { parseTime } from '@/utils/datetime.js';
import { formatTaskStatus } from '@/utils/status.js'; import { formatTaskStatus } from '@/utils/status.js';
import { noticeList } from '@/api/notice.js' import { taskList,taskListMonth } from '@/api/polling.js'
const form = ref({});//查询条件 const selectDate = ref({});//查询条件
const year=ref('');//默认月份 const year=ref('');//默认月份
const month=ref('');//默认月份 const month=ref('');//默认月份
const activeTab = ref(0);//默认按天查看 const activeTab = ref(0);//默认按天查看
const tabList = ['按天查看', '按月查看']; const tabList = ['按天查看', '按月查看'];
let count1=ref(12);//巡检 let count1=ref(0);//巡检
let count2=ref(9);//巡检 let count2=ref(0);//巡检
let count3=ref(3);//已完成 let count3=ref(0);//已过期
onLoad(option => { onLoad(option => {
let date = new Date(); let date = new Date();
year.value = date.getFullYear(); year.value = date.getFullYear();
month.value = date.getMonth()+1; month.value = date.getMonth()+1;
selectDate.value = parseTime(date,'{y}-{m}-{d}')//默认查今天
}) })
// tab切换 按日 or 按月 0-按日 1-按月 // tab切换 按日 or 按月 0-按日 1-按月
const handleTab = (index)=>{ const handleTab = async (index)=>{
activeTab.value = index; activeTab.value = index;
isMonth.value=true; isMonth.value=true;
// scrollToPosition(); // scrollToPosition();
if(index==1){
selectDate.value = parseTime(new Date(),'{y}-{m}')
}else{
selectDate.value = parseTime(new Date(),'{y}-{m}-{d}')
}
const res = await getList();
list.value = res.list;
} }
// 日历初始化 // 日历初始化
const calendarInfo = ref({ const calendarInfo = ref({
@@ -251,23 +275,22 @@ const monthSwitch=(e)=>{
console.log('monthSwitchs 返回:', e) console.log('monthSwitchs 返回:', e)
} }
// 按日选择 日历change // 按日选择 日历change
const calendarChange=(e)=> { const calendarChange= async(e)=> {
console.log('按日选择 返回:', e.fulldate) // console.log('按日选择 返回:', e.fulldate)
form.value.selectDate = e.fulldate selectDate.value = e.fulldate
// 模拟动态打卡 const res = await getList();
// if (calendarInfo.value.selected.length > 5) return list.value = res.list;
// calendarInfo.value.selected.push({
// date: e.fulldate,
// info: '打卡'
// })
} }
// 按月选择 日历change // 按月选择 日历change
const calendarChange2=(value)=> { const calendarChange2= async(value)=> {
console.log("按月选择 选择具体月份=>",value) // console.log("按月选择 选择具体月份=>",value)
form.value.selectDate = value.ymStr selectDate.value = value.ymStr
year.value = value.year; year.value = value.year;
month.value = value.month; month.value = value.month;
const res = await getList();
list.value = res.list;
} }
@@ -346,128 +369,48 @@ const upCallback = async (mescroll) => {
// 获取数据列表 // 获取数据列表
const getList = (pageIndex, pageSize) => { const getList = (pageIndex, pageSize) => {
return new Promise(async (resolve) => { return new Promise(async (resolve) => {
let param = { let res ={};
pageIndex, if(activeTab.value==1){//月查询
pageSize, let param = {
} month: selectDate.value
// let res = await noticeList(param);
let res = {
"code": 200,
"msg": "操作成功",
"data": {
list:[
{
date:new Date(),
list1:[
{
taskName:'日常巡检任务AAA日常巡检任务111',
taskId:202512297899,
taskStatus:3,
planTime:'10:25',
workHour:1,
count:0,
total:70,
percentage:'30%'
},
{
taskName:'日常巡检任务AAA日常巡检任务222',
taskId:202512297899,
taskStatus:3,
planTime:'10:25',
workHour:1,
count:20,
total:70,
percentage:'40%'
},
{
taskName:'日常巡检任务BBB任务名称过长时可折行 行距35px',
taskId:202512297899,
taskStatus:4,
planTime:'10:25',
workHour:1,
count:70,
total:70,
percentage:'100%'
},
{
taskName:'日常巡检任务ccc任务名称',
taskId:202512297899,
taskStatus:5,
planTime:'10:25',
workHour:1,
count:70,
total:70,
percentage:'100%'
},
],
list2:[
{
taskName:'日常巡检任务AAA日常巡检任务111',
taskId:202512297899,
taskStatus:3,
planTime:'10:25',
workHour:1,
count:0,
total:70,
percentage:'30%'
},
{
taskName:'日常巡检任务AAA日常巡检任务222',
taskId:202512297899,
taskStatus:3,
planTime:'10:25',
workHour:1,
count:20,
total:70,
percentage:'40%'
},
{
taskName:'日常巡检任务BBB任务名称过长时可折行 行距35px',
taskId:202512297899,
taskStatus:4,
planTime:'10:25',
workHour:1,
count:70,
total:70,
percentage:'100%'
},
{
taskName:'日常巡检任务ccc任务名称',
taskId:202512297899,
taskStatus:5,
planTime:'10:25',
workHour:1,
count:70,
total:70,
percentage:'100%'
},
],
list3:[
{
problemDesc:'西区地下车库入口防汛物资摆放',
problemId:202512297899,
problemStatus:1,
modifyTime:new Date().getTime(),
count:0,
},
{
problemDesc:'监控室消防设备阀门确保正常开启闭合',
problemId:202512297899,
problemStatus:2,
modifyTime:new Date().getTime(),
count:20,
}
]
}
]
} }
let response = await taskListMonth(param);
res ={
...response,
list:response.list || []
}
// 没数据时补值
if(res.list.length==0){
res.list.push({
list1: [],
list2: [],
});
}
}else{//天查询
let param = {
day:selectDate.value
}
let response = await taskList(param);
res ={
...response,
list:[]
}
res.list.push({
list1:response.list1 || [],
list2:response.list2 || [],
list3:response.list3 || []
});
} }
let data = res.data||{}; // console.log(res)
let data = res||{};
count1.value = data.finishNum;
count2.value = data.waitNum;
count3.value = data.expiredNum
resolve({ resolve({
...data, ...data,
// total: res.recordCount || 0
}); });
}); });
@@ -495,7 +438,7 @@ const handleDetail = (item,type) =>{
if(type==1){ if(type==1){
url = '/pages/business/polling/taskDetail?id='+item.taskId; url = '/pages/business/polling/taskDetail?id='+item.taskId;
}else{ }else{
url = '/pages/business/polling/problemDetail?id='+item.taskId; url = '/pages/business/polling/problemDetail?problemId='+item.problemId;
} }
uni.navigateTo({ uni.navigateTo({
url url

View File

@@ -12,11 +12,11 @@
<view class="bg-progress"> <view class="bg-progress">
<view class="progress-container"> <view class="progress-container">
<circleTemplate :progress="progress"></circleTemplate> <circleTemplate :progress="progress"></circleTemplate>
<span>{{ taskObj.progress }}%</span> <span>{{ (taskObj.groupFinishNum / taskObj.groupNum).toFixed() }}%</span>
</view> </view>
<view class="polling"> <view class="polling">
<view class="p-title p-border">巡检单号<text>{{taskObj.taskId}}</text></view> <view class="p-title p-border">巡检单号<text>{{taskObj.taskNo}}</text></view>
<view class="p-title">完成进度<text class="p-blue">{{taskObj.count}}</text>/{{taskObj.total}}</view> <view class="p-title">完成进度<text class="p-blue">{{taskObj.groupFinishNum}}</text>/{{taskObj.groupNum}}</view>
<view class="btn-primary"> <view class="btn-primary">
<button type="primary" size="mini" @click="handleConfirm">任务提交</button> <button type="primary" size="mini" @click="handleConfirm">任务提交</button>
</view> </view>
@@ -33,19 +33,24 @@
> >
<view class="white-bg"> <view class="white-bg">
<view class="blue-title">{{taskObj.taskName}}</view> <view class="blue-title">{{taskObj.taskName}}</view>
<block v-if="taskObj.list.length>0"> <block v-if="taskObj.groupList">
<view class="report-list" v-for="(item, index) in taskObj.list" :key="index" @click="handleDetail(item,1)"> <block v-if="taskObj.groupList.length>0">
<view class="r-list"> <view class="report-list" v-for="(item, index) in taskObj.groupList" :key="index" @click="handleDetail(item,1)">
<view class="r-left">{{ item.workName }}</view> <view class="r-list">
<view class="r-right"> <view class="r-left">{{ item.groupName }}</view>
<block v-if="item.count<item.total"> <view class="r-right">
<text class="r-orange">{{item.count}}</text>/{{item.total}} <block v-if="item.pointFinishNum<item.pointNum">
</block> <text class="r-orange">{{item.pointFinishNum}}</text>/{{item.pointNum}}
<block v-else>{{item.count}}/{{item.total}}</block> </block>
<uni-icons type="right" size="20" color="#A0A0A0"></uni-icons> <block v-else>{{item.pointFinishNum}}/{{item.pointNum}}</block>
<uni-icons type="right" size="20" color="#A0A0A0"></uni-icons>
</view>
</view> </view>
<view class="report-border" :style="{borderColor:index<taskObj.groupList.length-1?'#E7E7E7':'#fff'}"></view>
</view> </view>
<view class="report-border" :style="{borderColor:index<taskObj.list.length-1?'#E7E7E7':'#fff'}"></view> </block>
<view v-else class="no-data">
<img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" />
</view> </view>
</block> </block>
<view v-else class="no-data"> <view v-else class="no-data">
@@ -55,23 +60,28 @@
<!-- 问题跟踪 --> <!-- 问题跟踪 -->
<view class="bg-border"></view> <view class="bg-border"></view>
<view class="red-title">问题跟踪</view> <view class="red-title">问题跟踪</view>
<block v-if="taskObj.questList.length>0"> <block v-if="taskObj.problemList">
<view class="report-list" v-for="(item, index) in taskObj.questList" :key="index" @click="handleDetail(item,2)"> <block v-if="taskObj.problemList.length>0">
<view class="r-list" style="padding-bottom:0"> <view class="report-list" v-for="(item, index) in taskObj.problemList" :key="index" @click="handleDetail(item,2)">
<view class="r-name">{{ item.problemDesc }}</view> <view class="r-list" style="padding-bottom:0">
<view class="r-right"> <view class="r-name">{{ item.groupName }}</view>
<!-- 问题状态 1=追踪2=关闭 --> <view class="r-right">
<view v-if="item.problemStatus==1" class="btn-red">进行中</view> <!-- 问题状态 1=追踪2=关闭 -->
<view v-if="item.problemStatus==2" class="btn-green">已解决</view> <view v-if="item.problemStatus==1" class="btn-red">进行中</view>
<view v-if="item.problemStatus==2" class="btn-green">已解决</view>
</view>
</view> </view>
</view> <view class="r-list">
<view class="r-list"> <view class="r-left">
<view class="r-left"> <view class="r-l-left" style="width:220rpx">跟踪次数<span class="r-gray">{{ item.logNum }}</span></view>
<view class="r-l-left" style="width:220rpx">跟踪次数<span class="r-gray">{{ item.count }}</span></view> <view class="r-l-right">最近跟踪时间<span class="r-gray">{{ parseTime(item.lastLogTime,'{m}-{d} {h}:{i}') }}</span></view>
<view class="r-l-right">最近跟踪时间<span class="r-gray">{{ parseTime(item.modifyTime,'{m}-{d} {h}:{i}') }}</span></view> </view>
</view> </view>
<view class="report-border" v-if="index<taskObj.problemList.length-1"></view>
</view> </view>
<view class="report-border" v-if="index<taskObj.questList.length-1"></view> </block>
<view v-else class="no-data">
<img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" />
</view> </view>
</block> </block>
<view v-else class="no-data"> <view v-else class="no-data">
@@ -106,7 +116,9 @@ onLoad(option => {
// 查询列表 // 查询列表
let taskObj = ref({ let taskObj = ref({
list:[], list:[],
questList:[] questList:[],
groupFinishNum:0,
groupNum:1
}); });
const mescrollRef = ref(null); const mescrollRef = ref(null);
const upOption = ref({ const upOption = ref({
@@ -170,167 +182,165 @@ const upCallback = async (mescroll) => {
const getList = (pageIndex, pageSize) => { const getList = (pageIndex, pageSize) => {
return new Promise(async (resolve) => { return new Promise(async (resolve) => {
let param = { let param = {
pageIndex, taskId:taskId.value
pageSize,
} }
// let res = await taskDetail(param); let res = await taskDetail(param);
let res = { // let res = {
"code": 200, // "code": 200,
"msg": "操作成功", // "msg": "操作成功",
"data": { // "data": {
taskId:236, // taskId:236,
taskName:'日常巡检任务AAA', // taskName:'日常巡检任务AAA',
planTime:new Date().getTime(), // planTime:new Date().getTime(),
progress:62, // progress:62,
count:3, // count:3,
total:9, // total:9,
workHour:1, // workHour:1,
list:[ // list:[
{ // {
workName:'技术中心机房总电源', // workName:'技术中心机房总电源',
pointId:202512297899, // pointId:202512297899,
workStatus:3, // workStatus:3,
planTime:'10:25', // planTime:'10:25',
workHour:1, // workHour:1,
count:0, // count:0,
total:70, // total:70,
percentage:'30%' // percentage:'30%'
}, // },
{ // {
workName:'监控室消防设备阀门正常开启闭合', // workName:'监控室消防设备阀门正常开启闭合',
workId:202512297899, // workId:202512297899,
workStatus:3, // workStatus:3,
planTime:'10:25', // planTime:'10:25',
workHour:1, // workHour:1,
count:20, // count:20,
total:70, // total:70,
percentage:'40%' // percentage:'40%'
}, // },
{ // {
workName:'监控室10组灭火器压力指针处于绿色区域', // workName:'监控室10组灭火器压力指针处于绿色区域',
workId:202512297899, // workId:202512297899,
workStatus:4, // workStatus:4,
planTime:'10:25', // planTime:'10:25',
workHour:1, // workHour:1,
count:70, // count:70,
total:70, // total:70,
percentage:'100%' // percentage:'100%'
}, // },
{ // {
workName:'库房灭火器压力指针处于绿色区', // workName:'库房灭火器压力指针处于绿色区',
workId:202512297899, // workId:202512297899,
workStatus:5, // workStatus:5,
planTime:'10:25', // planTime:'10:25',
workHour:1, // workHour:1,
count:70, // count:70,
total:70, // total:70,
percentage:'100%' // percentage:'100%'
}, // },
{ // {
workName:'技术中心机房总电源', // workName:'技术中心机房总电源',
pointId:202512297899, // pointId:202512297899,
workStatus:3, // workStatus:3,
planTime:'10:25', // planTime:'10:25',
workHour:1, // workHour:1,
count:0, // count:0,
total:70, // total:70,
percentage:'30%' // percentage:'30%'
}, // },
{ // {
workName:'监控室消防设备阀门正常开启闭合', // workName:'监控室消防设备阀门正常开启闭合',
workId:202512297899, // workId:202512297899,
workStatus:3, // workStatus:3,
planTime:'10:25', // planTime:'10:25',
workHour:1, // workHour:1,
count:20, // count:20,
total:70, // total:70,
percentage:'40%' // percentage:'40%'
}, // },
{ // {
workName:'监控室10组灭火器压力指针处于绿色区域', // workName:'监控室10组灭火器压力指针处于绿色区域',
workId:202512297899, // workId:202512297899,
workStatus:4, // workStatus:4,
planTime:'10:25', // planTime:'10:25',
workHour:1, // workHour:1,
count:70, // count:70,
total:70, // total:70,
percentage:'100%' // percentage:'100%'
}, // },
{ // {
workName:'库房灭火器压力指针处于绿色区', // workName:'库房灭火器压力指针处于绿色区',
workId:202512297899, // workId:202512297899,
workStatus:5, // workStatus:5,
planTime:'10:25', // planTime:'10:25',
workHour:1, // workHour:1,
count:70, // count:70,
total:70, // total:70,
percentage:'100%' // percentage:'100%'
}, // },
{ // {
workName:'技术中心机房总电源', // workName:'技术中心机房总电源',
pointId:202512297899, // pointId:202512297899,
workStatus:3, // workStatus:3,
planTime:'10:25', // planTime:'10:25',
workHour:1, // workHour:1,
count:0, // count:0,
total:70, // total:70,
percentage:'30%' // percentage:'30%'
}, // },
{ // {
workName:'监控室消防设备阀门正常开启闭合', // workName:'监控室消防设备阀门正常开启闭合',
workId:202512297899, // workId:202512297899,
workStatus:3, // workStatus:3,
planTime:'10:25', // planTime:'10:25',
workHour:1, // workHour:1,
count:20, // count:20,
total:70, // total:70,
percentage:'40%' // percentage:'40%'
}, // },
{ // {
workName:'监控室10组灭火器压力指针处于绿色区域', // workName:'监控室10组灭火器压力指针处于绿色区域',
workId:202512297899, // workId:202512297899,
workStatus:4, // workStatus:4,
planTime:'10:25', // planTime:'10:25',
workHour:1, // workHour:1,
count:70, // count:70,
total:70, // total:70,
percentage:'100%' // percentage:'100%'
}, // },
{ // {
workName:'库房灭火器压力指针处于绿色区', // workName:'库房灭火器压力指针处于绿色区',
workId:202512297899, // workId:202512297899,
workStatus:5, // workStatus:5,
planTime:'10:25', // planTime:'10:25',
workHour:1, // workHour:1,
count:70, // count:70,
total:70, // total:70,
percentage:'100%' // percentage:'100%'
}, // },
], // ],
questList:[ // questList:[
{ // {
problemDesc:'西区地下车库入口防汛物资摆放', // problemDesc:'西区地下车库入口防汛物资摆放',
problemId:202512297899, // problemId:202512297899,
problemStatus:1, // problemStatus:1,
modifyTime:new Date().getTime(), // modifyTime:new Date().getTime(),
count:0, // count:0,
}, // },
{ // {
problemDesc:'监控室消防设备阀门确保正常开启闭合', // problemDesc:'监控室消防设备阀门确保正常开启闭合',
problemId:202512297899, // problemId:202512297899,
problemStatus:2, // problemStatus:2,
modifyTime:new Date().getTime(), // modifyTime:new Date().getTime(),
count:20, // count:20,
} // }
] // ]
} // }
} // }
let data = res.data||{}; let data = res||{};
progress.value = data.progress progress.value = data.progress
resolve({ resolve({
...data, ...data,
// total: res.recordCount || 0
}); });
}); });
@@ -345,9 +355,9 @@ const handleConfirm=()=>{
const handleDetail = (item,type) =>{ const handleDetail = (item,type) =>{
let url='' let url=''
if(type==1){ if(type==1){
url = '/pages/business/polling/optionDetail?id='+item.pointId; url = '/pages/business/polling/optionDetail?taskId='+taskId.value+"&groupId="+item.groupId;
}else{ }else{
url = '/pages/business/polling/problemDetail?id='+item.taskId; url = '/pages/business/polling/problemDetail?problemId='+item.problemId;
} }
uni.navigateTo({ uni.navigateTo({
url url
@@ -418,7 +428,7 @@ const handleDetail = (item,type) =>{
.scroll-h{ .scroll-h{
/* #ifdef APP-PLUS */ /* #ifdef APP-PLUS */
height: calc(100vh - 258px); height: calc(100vh - 253px);
/* #endif */ /* #endif */
/* #ifndef APP-PLUS */ /* #ifndef APP-PLUS */
height: calc(100vh - 253px); height: calc(100vh - 253px);
@@ -454,6 +464,7 @@ const handleDetail = (item,type) =>{
} }
.report-list .r-list .r-right{ .report-list .r-list .r-right{
display: flex; display: flex;
align-items: center;
} }
.report-list .r-list .r-right .r-orange{ .report-list .r-list .r-right .r-orange{
color:#FF9638 color:#FF9638

View File

@@ -29,10 +29,10 @@
<mescroll-uni ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback" <mescroll-uni ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback"
:up="upOption" :down="downOption" :fixed="false" class="scroll-h" :class="{'loading-scroll':cssFlag}"> :up="upOption" :down="downOption" :fixed="false" class="scroll-h" :class="{'loading-scroll':cssFlag}">
<view class="white-bg"> <view class="white-bg">
<block v-if="list.length>0"> <block v-if="list">
<block v-for="(obj, index) in list" :key="index"> <block v-if="list.length>0">
<view class="r-title">{{ parseTime(obj.dateStr,'{y}-{m}-{d} 星期{a}')}}</view> <!-- <view class="r-title">{{ parseTime(obj.dateStr,'{y}-{m}-{d} 星期{a}')}}</view> -->
<view class="report-list" v-for="(item, index) in obj.list" :key="index" @click="handleDetail(item)"> <view class="report-list" v-for="(item, index) in list" :key="index" @click="handleDetail(item)">
<view class="r-list" style="padding-bottom:0"> <view class="r-list" style="padding-bottom:0">
<view class="r-name">{{ item.taskName }}</view> <view class="r-name">{{ item.taskName }}</view>
<view class="r-right"> <view class="r-right">
@@ -54,32 +54,35 @@
</view> </view>
<view class="r-list"> <view class="r-list">
<view class="r-left"> <view class="r-left">
<view class="r-l-left">开始时间<span class="r-gray">{{ item.planTime }}</span></view> <view class="r-l-left">开始时间<span class="r-gray">{{ parseTime(item.planTime,'{y}-{m}-{d} {h}:{i}') }}</span></view>
<view class="r-l-right">任务时长<span class="r-gray">{{ item.workHour }}小时</span></view> <view class="r-l-right">任务时长<span class="r-gray">{{ item.workHour }}小时</span></view>
</view> </view>
</view> </view>
<view class="r-list"> <view class="r-list">
<view class="r-left"> <view class="r-left">
<view class="r-l-left"> <view class="r-l-left">
完成进度<span class="r-gray"><span :class="{'r-red':item.count<item.total}">{{item.count}}</span>/{{item.total}}</span> 完成进度<span class="r-gray"><span :class="{'r-red':item.groupFinishNum<item.groupNum}">{{item.groupFinishNum}}</span>/{{item.groupNum}}</span>
</view> </view>
<view class="r-l-right">完成比率<span class="r-blue">{{item.percentage}}</span></view> <view class="r-l-right">完成比率<span class="r-blue">{{(item.groupFinishNum/item.groupNum).toFixed()+'%'}}</span></view>
</view> </view>
</view> </view>
<view class="r-list"> <view class="r-list">
<view class="r-left"> <view class="r-left">
<view>任务状态 <view>任务状态
<span class="r-gray" v-if="item.taskStatus==3"> <span class="r-gray" v-if="item.taskStatus==3">
<block v-if="item.count==0">待执行</block> <block v-if="item.groupFinishNum==0">待执行</block>
<block v-else>执行中</block> <block v-else>执行中</block>
</span> </span>
<span class="r-gray" v-else>{{formatTaskStatus(item.taskStatus) }}</span> <span class="r-gray" v-else>{{formatTaskStatus(item.taskStatus) }}</span>
</view> </view>
</view> </view>
</view> </view>
<view class="report-border" v-if="index<obj.list.length-1"></view> <view class="report-border" v-if="index<list.length-1"></view>
</view> </view>
</block> </block>
<view v-else class="no-data">
<img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" />
</view>
</block> </block>
<view v-else class="no-data"> <view v-else class="no-data">
<img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" /> <img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" />
@@ -101,7 +104,7 @@ import MescrollUni from 'mescroll-uni/mescroll-uni.vue';
import searchDate from '@/components/searchDate.vue'; import searchDate from '@/components/searchDate.vue';
import { parseTime,getDateRange,getDateRangeName } from '@/utils/datetime.js'; import { parseTime,getDateRange,getDateRangeName } from '@/utils/datetime.js';
import { taskTypeOptions,formatTaskType,formatTaskStatus } from '@/utils/status.js'; import { taskTypeOptions,formatTaskType,formatTaskStatus } from '@/utils/status.js';
import { noticeList } from '@/api/notice.js' import { taskLists } from '@/api/polling.js'
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
@@ -119,6 +122,9 @@ const dateConfirm=(dateObj)=>{
isShow.value = false; isShow.value = false;
dateStr.value = dateObj.startDate + ' 至 '+dateObj.endDate; dateStr.value = dateObj.startDate + ' 至 '+dateObj.endDate;
dateStrName.value = getDateRangeName(dateObj.lastType) dateStrName.value = getDateRangeName(dateObj.lastType)
form.value.startDate = dateObj.startDate;
form.value.endDate = dateObj.endDate
} }
// 类型索引 // 类型索引
@@ -134,6 +140,10 @@ onLoad(option => {
let dateObj = getDateRange('3days'); let dateObj = getDateRange('3days');
dateStr.value = dateObj.startDate + ' 至 '+dateObj.endDate; dateStr.value = dateObj.startDate + ' 至 '+dateObj.endDate;
dateStrName.value="近3天" dateStrName.value="近3天"
form.value.startDate = dateObj.startDate;
form.value.endDate = dateObj.endDate
}) })
@@ -147,7 +157,7 @@ const changeTaskType = (e)=>{
// 查询列表 // 查询列表
let list = ref([]); let list = ref([]);
let form = ref({ let form = ref({
beginTime:'' startDate:''
}) })
const mescrollRef = ref(null); const mescrollRef = ref(null);
const upOption = ref({ const upOption = ref({
@@ -213,75 +223,14 @@ const getList = (pageIndex, pageSize) => {
let param = { let param = {
pageIndex, pageIndex,
pageSize, pageSize,
timeBegin: form.value.startDate,
timeEnd: form.value.endDate,
} }
let res = await taskLists(param);
// let res = await noticeList(param); let data = res ||{};
let res = {
"code": 200,
"msg": "操作成功",
"data": {
list:[
{
dateStr:new Date().getTime(),
list:[
{
taskName:'日常巡检任务AAA日常巡检任务111',
taskId:202512297899,
taskStatus:3,
taskType:1,
planTime:'10:25',
workHour:1,
count:0,
total:70,
percentage:'30%'
},
{
taskName:'日常巡检任务AAA日常巡检任务222',
taskId:202512297899,
taskStatus:3,
taskType:2,
planTime:'10:25',
workHour:1,
count:20,
total:70,
percentage:'40%'
},
{
taskName:'日常巡检任务BBB任务名称过长时可折行 行距35px',
taskId:202512297899,
taskStatus:4,
taskType:1,
planTime:'10:25',
workHour:1,
count:70,
total:70,
percentage:'100%'
},
{
taskName:'日常巡检任务ccc任务名称',
taskId:202512297899,
taskStatus:5,
taskType:2,
planTime:'10:25',
workHour:1,
count:70,
total:70,
percentage:'100%'
},
],
},
],
recordCount:10,
}
}
let data = res.data||{};
resolve({ resolve({
...data, ...data,
total: res.recordCount || 0 // total: res.recordCount || 0
}); });
}); });
@@ -307,7 +256,7 @@ const handleDetail = (item,type) =>{
height: calc(100vh - 108px); height: calc(100vh - 108px);
/* #endif */ /* #endif */
/* #ifndef APP-PLUS */ /* #ifndef APP-PLUS */
height: calc(100vh - 130px); height: calc(100vh - 135px);
/* #endif */ /* #endif */
} }
@@ -415,7 +364,7 @@ const handleDetail = (item,type) =>{
width:525rpx width:525rpx
} }
.r-left .r-l-left{ .r-left .r-l-left{
width:350rpx; width:370rpx;
} }
.r-left .r-l-right{ .r-left .r-l-right{

View File

@@ -24,14 +24,17 @@
<script setup> <script setup>
import { ref,getCurrentInstance } from 'vue'; import { ref,getCurrentInstance } from 'vue';
import { onLoad } from '@dcloudio/uni-app'; import { onLoad } from '@dcloudio/uni-app';
import { MINIO_KEY } from '@/enums/cacheEnums';
import { versionCheck,getBindStatus } from '@/api/auth.js'; import { versionCheck,getBindStatus } from '@/api/auth.js';
import { formatIOS } from '@/utils/status.js' import { formatIOS } from '@/utils/status.js'
import { requestAndroidPermissionAsync,requestAndroidPermission } from '@/utils/common.js' // import { requestAndroidPermissionAsync,requestAndroidPermission } from '@/utils/common.js'
import {showAlert} from '@/utils/message.js' import {showAlert} from '@/utils/message.js'
import { minioParam } from '@/api/polling.js'
import { useUserStore } from '@/stores/user'; import { useUserStore } from '@/stores/user';
const userStore = useUserStore(); const userStore = useUserStore();
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
const networkEnv = ref(proxy.$NETWORK_ENV);//1-内网 2-外网 const networkEnv = ref(proxy.$NETWORK_ENV);//1-内网 2-外网
console.log(111,networkEnv.value)
// #ifdef APP-PLUS // #ifdef APP-PLUS
// 获取 存储手机的module // 获取 存储手机的module
@@ -48,7 +51,6 @@ let versionData = ref({}); //版本参数
// 初始load页面 // 初始load页面
onLoad(async(opt) => { onLoad(async(opt) => {
console.log("onLoad"); console.log("onLoad");
// uni.preloadPage({url: "/pages/login/login"}); // uni.preloadPage({url: "/pages/login/login"});
// uni.preloadPage({url: "/pages/deviceAuth/deviceAuth"}); // uni.preloadPage({url: "/pages/deviceAuth/deviceAuth"});
// uni.preloadPage({url: "/pages/home/home"}); // uni.preloadPage({url: "/pages/home/home"});
@@ -89,8 +91,19 @@ onLoad(async(opt) => {
// },1000) // },1000)
// #endif // #endif
// 内网才有minio参数
if(networkEnv.value==1){
getMinioParam();
}
}); });
// 获取minio参数
const getMinioParam=async ()=>{
let data = await minioParam({});
uni.setStorageSync(MINIO_KEY,JSON.stringify(data))
}
// 检查版本是否是最新的s // 检查版本是否是最新的s
const getOSVesion = async()=>{ const getOSVesion = async()=>{
let networkEnv = proxy.$NETWORK_ENV;//1-内网 2-外网 let networkEnv = proxy.$NETWORK_ENV;//1-内网 2-外网

View File

@@ -266,7 +266,7 @@ const submitForm = () => {
//h5测试用 内网-sn123456 //h5测试用 内网-sn123456
//公司外网 'f3fca83f-bf56-47f4-a98b-a602ed8bddee' 529a5543-6957-401e-b090-13df6dee5429 //公司外网 'f3fca83f-bf56-47f4-a98b-a602ed8bddee' 529a5543-6957-401e-b090-13df6dee5429
//友晟外网 'b97527c8-2ad4-493c-a01c-5f9d0aabaff2' //友晟外网 'b97527c8-2ad4-493c-a01c-5f9d0aabaff2'
param.uniqCode ='1af78c0a-b878-425f-9dc5-bee42146860a' //'4d8489b7-78cd-4db2-9227-d7c2ab2093d8'; param.uniqCode ='9a41dec6-536f-443f-9d98-8dc5c0b18332';//'1af78c0a-b878-425f-9dc5-bee42146860a'
let res = await login(param); let res = await login(param);
userStore.login(res); userStore.login(res);
uni.switchTab({ url: '/pages/home/home' }) uni.switchTab({ url: '/pages/home/home' })

View File

@@ -139,7 +139,6 @@ const jumpAuthPermission=()=>{
// 跳转授权 // 跳转授权
const jumpAuthPermission2 = () => { const jumpAuthPermission2 = () => {
let main = plus.android.runtimeMainActivity(); let main = plus.android.runtimeMainActivity();
let Intent = plus.android.importClass('android.content.Intent'); let Intent = plus.android.importClass('android.content.Intent');
let Uri = plus.android.importClass('android.net.Uri'); let Uri = plus.android.importClass('android.net.Uri');
@@ -227,4 +226,69 @@ export const getFileType = (filePathOrName) => {
} else { } else {
return 'other'; return 'other';
} }
} }
// 计算图片的新尺寸
const calculateNewSize = (originalWidth, originalHeight)=>{
const MAX_SIZE = 1920;
let newWidth = originalWidth;
let newHeight = originalHeight;
// 如果宽或高超过最大尺寸,进行等比缩放
if (originalWidth > MAX_SIZE || originalHeight > MAX_SIZE) {
if (originalWidth > originalHeight) {
// 宽图
newWidth = MAX_SIZE;
newHeight = Math.round((originalHeight * MAX_SIZE) / originalWidth);
} else {
// 高图或方图
newHeight = MAX_SIZE;
newWidth = Math.round((originalWidth * MAX_SIZE) / originalHeight);
}
}
// console.log('调整后尺寸:', newWidth, 'x', newHeight);
return {
width: newWidth,
height: newHeight
};
}
// 图片压缩处理tempFilePaths
export const compressImageUni = (file) => {
return new Promise((resolve, reject) => {
try {
console.log("compressImageUni=>file=>",file)
uni.getImageInfo({
src: file,
success: function (image) {
const newSize = calculateNewSize(image.width, image.height);
console.log("调整后的尺寸=>",newSize)
uni.compressImage({
src: file,
compressedWidth:newSize.width,
compressedHeight:newSize.height,
quality: 100, // 压缩质量 (0-100)
success: (res) => {
// console.log('压缩成功,临时路径:', res.tempFilePath);
resolve(res.tempFilePath)
},
fail: (err) => {
console.log('压缩失败:', err);
reject(err)
}
});
}
});
} catch (error) {
console.log('压缩失败:', error);
}
})
}
// 获取minio缩略图地址
export function getMinioThumbUrl(ossObj,path){
let baseUrl = process.env.VUE_APP_MINIO?process.env.VUE_APP_MINIO:'';
// let replaceStr="http://"+ossObj.clientObj.url+":"+ossObj.clientObj.port+"/new-gd-manager"
// let thumbUrl = path.replace(replaceStr,baseUrl+'/thumb/new-gd-manager');
return {baseUrl}
}

View File

@@ -1,3 +1,5 @@
// import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
import { initMinio, putObject } from 'minio-js' import { initMinio, putObject } from 'minio-js'
import { v4 as uuidv4 } from 'uuid' import { v4 as uuidv4 } from 'uuid'
@@ -14,21 +16,22 @@ import { v4 as uuidv4 } from 'uuid'
*/ */
export const uploadFileMinio = async (files,fileDir,tempFilePaths) => { export const uploadFileMinio = async (files,fileDir,tempFilePaths) => {
try { try {
if (!files.length){ if (!files.length){
uni.showToast({ title: '请选择要上传的文件', icon: 'none' }) uni.showToast({ title: '请选择要上传的文件', icon: 'none' })
return; return;
} }
let bucketName="718ys-test";//'你的存储桶名称' let bucketName="718ys-test";//'你的存储桶名称'
// 初始化 Minio 客户端 // 初始化 Minio 客户端
// #ifndef APP-PLUS // initMinio({
initMinio({ // endPoint: '192.168.236.196', // 例如 'play.min.io'
endPoint: '192.168.236.196', // 例如 'play.min.io' // port: 9000, // 端口,使用 SSL 通常是 443非 SSL 是 9000
port: 9000, // 端口,使用 SSL 通常是 443非 SSL 是 9000 // useSSL: false, // 根据你的 Minio 服务器配置决定 将此值设置为“true”为HTTPS访问false为普通http访问
useSSL: false, // 根据你的 Minio 服务器配置决定 将此值设置为“true”为HTTPS访问false为普通http访问 // accessKey: 'cyLu4uv7mFErTWkx',//'你的AccessKey',
accessKey: 'cyLu4uv7mFErTWkx',//'你的AccessKey', // secretKey: 'XE9PYr3wt6MHveHn8kA008rebxtj2c7S' //'你的SecretKey'
secretKey: 'XE9PYr3wt6MHveHn8kA008rebxtj2c7S' //'你的SecretKey' // });
});
// const minioClient = new Minio.Client({ // const minioClient = new Minio.Client({
// endPoint: '192.168.236.196', // 例如 'play.min.io' // endPoint: '192.168.236.196', // 例如 'play.min.io'
@@ -37,65 +40,80 @@ export const uploadFileMinio = async (files,fileDir,tempFilePaths) => {
// accessKey: 'cyLu4uv7mFErTWkx',//'你的AccessKey', // accessKey: 'cyLu4uv7mFErTWkx',//'你的AccessKey',
// secretKey: 'XE9PYr3wt6MHveHn8kA008rebxtj2c7S' //'你的SecretKey' // secretKey: 'XE9PYr3wt6MHveHn8kA008rebxtj2c7S' //'你的SecretKey'
// }) // })
// #endif
// const s3Client = new S3Client({
// region: "1-1", // 或其他区域与MinIO配置一致
// endpoint: "http://192.168.236.196:9000", // MinIO的端点
// credentials: {
// accessKeyId: "cyLu4uv7mFErTWkx", // MinIO的Access Key
// secretAccessKey: "XE9PYr3wt6MHveHn8kA008rebxtj2c7S", // MinIO的Secret Key
// },
// s3ForcePathStyle: true, // MinIO需要设置为true
// signatureVersion: "v4",
// });
let retrunFileArr=[]; let retrunFileArr=[];
// 批量上传 // 批量上传
const uploadPromises = files.map((file,index) => { const uploadPromises = files.map((file,index) => {
console.log("111uploadPromises=>",file)
return new Promise(async(resolve, reject) => { return new Promise(async(resolve, reject) => {
// 1.图片路径 // 1.图片路径
let fileName = uuidv4()+ "." + file.name.split(".").pop(); let fileName = uuidv4()+ "." + file.name.split(".").pop();
let imgDir = fileDir?(fileDir+'/'+fileName):'/'+fileName; let imgDir = fileDir?(fileDir+'/'+fileName):'/'+fileName;
retrunFileArr.push(imgDir); retrunFileArr.push(imgDir);
console.log(imgDir) console.log(222,"uploadPromises=>",imgDir)
// minioUpload
// #ifdef APP-PLUS
uni.uploadFile({ uni.uploadFile({
url: 'http://192.168.236.196', //仅为示例,非真实的接口地址 url: `http://192.168.236.196:9000/`+bucketName+"/",
filePath: tempFilePaths[index], filePath: imgDir,
name: 'file', name: 'file',
formData: { formData: {
'user': 'test' bucketName,
}, accessKey: "XE9PYr3wt6MHveHn8kA008rebxtj2c7S",
success: (uploadFileRes) => { secretKey: "cyLu4uv7mFErTWkx",
console.log(uploadFileRes); },success: (res) => {
}, uni.hideLoading()
fail: (err)=> { if (res.statusCode !== 204) {
console.log("err=>",err) reject()
} else {
resolve(aliyunKey)
}
},fail: err => {
reject()
uni.hideLoading()
} }
}); })
// #endif
// #ifndef APP-PLUS // const command = new PutObjectCommand({
// 使用putObject方法上传文件[citation:3] // Bucket: bucketName,
// minioClient.putObject(bucketName,imgDir, file, (err, etag) => { // Key: imgDir, // 文件名
// // ContentType: "text/plain", // 文件类型
// });
// const data = await s3Client.send(command);
// console.log("S3 Buckets:",data);
// resolve(data)
// // 2. 读取文件
// const arrayBuffer = await readFileAsArrayBuffer(file);
// console.log("333执行上传=>",arrayBuffer)
// // 3. 执行上传
// putObject(bucketName, arrayBuffer, imgDir, function (err, etag) {
// console.log("444执行上传=>",err,etag)
// if (err) { // if (err) {
// console.error('上传失败:', err); // console.error('555上传失败:', err);
// reject(err); // // 处理错误
// reject(err)
// } else { // } else {
// console.log('上传成功Etag:', etag); // console.log('666上传成功Etag:', etag);
// resolve(etag); // // 上传成功后的处理
// resolve(etag)
// } // }
// }) // });
// 2. 读取文件
const arrayBuffer = await readFileAsArrayBuffer(file);
// 3. 执行上传
putObject(bucketName, arrayBuffer, imgDir, function (err, etag) {
console.log("执行上传=>",err,etag)
if (err) {
console.error('上传失败:', err);
// 处理错误
reject(err)
} else {
console.log('上传成功Etag:', etag);
// 上传成功后的处理
resolve(etag)
}
});
// #endif
}) })
}) })
@@ -112,6 +130,7 @@ export const uploadFileMinio = async (files,fileDir,tempFilePaths) => {
// 将 File 对象读取为 ArrayBuffer 的辅助函数 // 将 File 对象读取为 ArrayBuffer 的辅助函数
const readFileAsArrayBuffer = (file) => { const readFileAsArrayBuffer = (file) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const reader = new FileReader(); const reader = new FileReader();
reader.onload = () => resolve(reader.result); reader.onload = () => resolve(reader.result);

141
src/utils/nfcUtil.js Normal file
View File

@@ -0,0 +1,141 @@
// 包路径
const package_NdefRecord = 'android.nfc.NdefRecord';
const package_NdefMessage = 'android.nfc.NdefMessage';
const package_TECH_DISCOVERED = 'android.nfc.action.TECH_DISCOVERED';
const package_Intent = 'android.content.Intent';
const package_Activity = 'android.app.Activity';
const package_PendingIntent = 'android.app.PendingIntent';
const package_IntentFilter = 'android.content.IntentFilter';
const package_NfcAdapter = 'android.nfc.NfcAdapter';
const package_Ndef = 'android.nfc.tech.Ndef';
const package_NdefFormatable = 'android.nfc.tech.NdefFormatable';
const package_Parcelable = 'android.os.Parcelable';
const package_String = 'java.lang.String';
let NfcAdapter;
let NdefRecord;
let NdefMessage;
let readyRead = true; //开启读
let noNFC = false;
let techListsArray = [
['android.nfc.tech.IsoDep'],
['android.nfc.tech.NfcA'],
['android.nfc.tech.NfcB'],
['android.nfc.tech.NfcF'],
['android.nfc.tech.Nfcf'],
['android.nfc.tech.NfcV'],
['android.nfc.tech.NdefFormatable'],
['android.nfc.tech.MifareClassi'],
['android.nfc.tech.MifareUltralight']
];
// 要写入的数据
// let text = '{id:8888,name:nfc,stie:wangqin.com}';
// let readResult = '';
export default {
listenNFCStatus() {
console.log("---------listenNFCStatus--------------")
let that = this;
try {
let main = plus.android.runtimeMainActivity();
let Intent = plus.android.importClass('android.content.Intent');
let Activity = plus.android.importClass('android.app.Activity');
let PendingIntent = plus.android.importClass('android.app.PendingIntent');
let IntentFilter = plus.android.importClass('android.content.IntentFilter');
NfcAdapter = plus.android.importClass('android.nfc.NfcAdapter');
let nfcAdapter = NfcAdapter.getDefaultAdapter(main);
console.log("nfcAdapter=>",nfcAdapter)
if (nfcAdapter == null) {
uni.showToast({
title: '设备不支持NFC',
icon: 'none'
})
noNFC = true;
return;
}
if (!nfcAdapter.isEnabled()) {
uni.showToast({
title: '请在系统设置中先启用NFC功能',
icon: 'none'
});
noNFC = true;
return;
} else {
noNFC = false;
}
console.log("nfcAdapter=>noNFC=>",noNFC)
let intent = new Intent(main, main.getClass());
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
let pendingIntent = PendingIntent.getActivity(main, 0, intent, 0);
let ndef = new IntentFilter("android.nfc.action.TECH_DISCOVERED");
ndef.addDataType("*/*");
let intentFiltersArray = [ndef];
//重点部分代码
const promise = new Promise((resolve, reject) => {
plus.globalEvent.addEventListener('newintent', function () {
// 轮询调用 NFC
// setTimeout(that.nfcRuning(resolve), 1000);
setTimeout(() => {
that.nfcRuning(resolve)
}, 1000);
});
})
nfcAdapter.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray);
return promise
} catch (e) {
console.log(e)
}
},
nfcRuning(resolve){
console.log("--------------nfcRuning---------------")
NdefRecord = plus.android.importClass("android.nfc.NdefRecord");
NdefMessage = plus.android.importClass("android.nfc.NdefMessage");
let main = plus.android.runtimeMainActivity();
let intent = main.getIntent(); console.log("intent=>",intent)
let that = this;
if (package_TECH_DISCOVERED == intent.getAction()) {
if (readyRead) {
//这里通过read方法拿到NFC数据
const id = that.read(intent);
console.log("nfcRuning=>",id)
// readyRead = false;
//将数据返回出去
resolve(id)
}
}
},
read(intent) {
// toast('请勿移开标签正在读取数据');
let that = this;
// NFC id
let bytesId = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID);
let nfc_id = that.byteArrayToHexString(bytesId);
return nfc_id;
},
byteArrayToHexString(inarray){ // converts byte arrays to string
let i, j, inn;
let hex = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"];
let out = "";
for (j = 0; j < inarray.length; ++j) {
inn = inarray[j] & 0xff;
i = (inn >>> 4) & 0x0f;
out += hex[i];
i = inn & 0x0f;
out += hex[i];
}
return out;
},
}
function toast(content) {
uni.showToast({
title: content,
icon: 'none'
})
}

View File

@@ -54,6 +54,7 @@ export default class HttpRequest {
* @description 上传图片 * @description 上传图片
*/ */
uploadFile(options, config) { uploadFile(options, config) {
// console.log("uploadFile=>",options)
let mergeOptions = merge({}, this.options.requestOptions, options); let mergeOptions = merge({}, this.options.requestOptions, options);
const mergeConfig = merge({}, this.options, config); const mergeConfig = merge({}, this.options, config);
const { const {
@@ -65,6 +66,8 @@ export default class HttpRequest {
if (requestInterceptorsHook && isFunction(requestInterceptorsHook)) { if (requestInterceptorsHook && isFunction(requestInterceptorsHook)) {
mergeOptions = requestInterceptorsHook(mergeOptions, mergeConfig); mergeOptions = requestInterceptorsHook(mergeOptions, mergeConfig);
} }
// console.log("上传参数=>",mergeOptions)
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
uni.uploadFile({ uni.uploadFile({
...mergeOptions, ...mergeOptions,