增加接口联调

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"
// 查询今日任务列表
export function taskTodayList(data) {
// 按日查询任务列表
export function taskList(data) {
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
})
}
@@ -11,7 +27,92 @@ export function taskTodayList(data) {
// 查询任务详情
export function taskDetail(data) {
return request.post({
url: '/acc/message/notify/detail',
url: '/patrol/patroltask/detail',
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-middle':true,'m-height':!title}">{{contents}}</view>
<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>
</view>
</view>

View File

@@ -43,7 +43,7 @@
</template>
<script setup>
import { onMounted, reactive, ref, defineExpose} from "vue";
import { onMounted, reactive, ref, defineExpose, watch} from "vue";
const props = defineProps({
// 是否显示全部清空按钮
@@ -108,10 +108,10 @@ const props = defineProps({
});
const emit = defineEmits(["change"]);
const active = ref(false); // 组件是否激活,
let changevalue = reactive([]);
let realValue = reactive([]);
let changevalue = ref([]);
let realValue = ref([]);
onMounted(() => {
// init();
init();
});
// 初始化函数
@@ -120,16 +120,16 @@ const init = () => {
props.options.forEach((item) => {
props.value.forEach((i) => {
if (item[props.svalue] === i) {
changevalue.push(item);
changevalue.value.push(item);
}
})
})
realValue = props.value;
console.log("props---", changevalue);
realValue.value = props.value;
// console.log("props---", changevalue.value);
} else {
changevalue = [];
realValue = [];
changevalue.value = [];
realValue.value = [];
}
};
// 点击展示选项
@@ -140,13 +140,13 @@ const handleSelect = () => {
// 移除数据
const handleRemove = (index) => {
if (index === null) {
realValue = [];
changevalue = [];
realValue.value = [];
changevalue.value = [];
} else {
realValue.splice(index, 1);
changevalue.splice(index, 1);
realValue.value.splice(index, 1);
changevalue.value.splice(index, 1);
}
emit("change", changevalue, realValue);
emit("change", changevalue.value, realValue.value);
};
// 点击组件某一项
const handleChange = (index, item) => {
@@ -154,26 +154,26 @@ const handleChange = (index, item) => {
// 如果是单选框,选中一项后直接关闭
if (!props.multiple) {
console.log("关闭下拉框");
changevalue.length = 0
changevalue.value.length = 0
realValue.length = 0
changevalue.push(item);
realValue.push(item[props.svalue])
changevalue.value.push(item);
realValue.value.push(item[props.svalue])
active.value = !active.value;
} else {
// 多选操作
const arrIndex = realValue.indexOf(item[props.svalue]);
const arrIndex = realValue.value.indexOf(item[props.svalue]);
if (arrIndex > -1) {
// 如果该选项已经选中,当点击后就不选中
changevalue.splice(arrIndex, 1);
realValue.splice(arrIndex, 1);
changevalue.value.splice(arrIndex, 1);
realValue.value.splice(arrIndex, 1);
} else {
// 否则选中该选项
changevalue.push(item);
realValue.push(item[props.svalue]);
changevalue.value.push(item);
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>
<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>
</view>
</view>
@@ -149,7 +152,11 @@ const handleCancel = ()=>{
}
const handleConfirm = ()=>{
if(isGreens.value){
loading.value=false;
}else{
loading.value=true;
}
emit('confirm')
}

View File

@@ -4,5 +4,8 @@ export const AGREEWELCOME_KEY="agreewelcome";
// clientId 默认写2
export const CLIENT_ID="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" : {
"Push" : {},
"Camera" : {},
"Barcode" : {}
"Barcode" : {},
"VideoPlayer" : {}
},
/* */
"distribute" : {

View File

@@ -14,7 +14,7 @@
</customHeader>
<!-- 高度来避免头部遮挡 -->
<view class="top-height"></view>
<view class="week">{{dateStr}}</view>
<!-- <view class="week">{{dateStr}}</view> -->
<!-- 列表 @up="upCallback" -->
<mescroll-uni ref="mescrollRef" @init="mescrollInit"
@@ -31,7 +31,7 @@
<!-- 任务(巡检)状态 1=未发布 2=已发布 3 进行中 4 已完成 5 已过期 -->
<!-- 状态为3进行中时 进度>0执行中 进度=0为待执行 -->
<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" />
</block>
<img v-else-if="item.taskStatus==4" :src="'static/images/polling/icon-complete.png'" class="img-complete" />
@@ -43,16 +43,16 @@
</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-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.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 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 class="r-list">
@@ -81,7 +81,7 @@
<!-- 任务(巡检)状态 1=未发布 2=已发布 3 进行中 4 已完成 5 已过期 -->
<!-- 状态为3进行中时 进度>0执行中 进度=0为待执行 -->
<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" />
</block>
<img v-else-if="item.taskStatus==4" :src="'static/images/polling/icon-complete.png'" class="img-complete" />
@@ -93,23 +93,23 @@
</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-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.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 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 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-if="item.groupFinishNum==0">待执行</block>
<block v-else>执行中</block>
</span>
<span class="r-gray" v-else>{{formatTaskStatus(item.taskStatus) }}</span>
@@ -128,7 +128,7 @@
<block v-if="list3.length>0">
<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-name">{{ item.problemDesc }}</view>
<view class="r-name">{{ item.groupName }}</view>
<view class="r-right">
<!-- 问题状态 1=追踪2=关闭 -->
<view v-if="item.problemStatus==1" class="btn-red">进行中</view>
@@ -137,8 +137,8 @@
</view>
<view class="r-list">
<view class="r-left">
<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.modifyTime,'{m}-{d} {h}:{i}') }}</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.lastLogTime,'{m}-{d} {h}:{i}') }}</span></view>
</view>
</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 { parseTime } from '@/utils/datetime.js';
import { formatTaskStatus } from '@/utils/status.js';
import { taskTodayList } from '@/api/polling.js'
import { taskList } from '@/api/polling.js'
// '2025-12-29 星期五'
let dateStr = ref('');
@@ -204,9 +204,9 @@ const downCallback = async (mescroll) => {
console.log("下拉刷新")
const res = await getList(1, upOption.value.page.size);
cssFlag.value = false;
list1.value = res.list1;
list2.value = res.list2;
list3.value = res.list3;
list1.value = res.list1 || [];
list2.value = res.list2 || [];
list3.value = res.list3 || [];
// mescroll.resetUpScroll();
} catch (error) {
mescroll.endErr();
@@ -220,9 +220,9 @@ const upCallback = async (mescroll) => {
console.log("上拉加载更多")
let res = await getList(mescroll.num, mescroll.size);
if (mescroll.num === 1) {
list1.value = res.list1;
list2.value = res.list2;
list3.value = res.list3;
list1.value = res.list1 || [];
list2.value = res.list2 || [];
list3.value = res.list3 || [];
} else {
// 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) => {
return new Promise(async (resolve) => {
let param = {
pageIndex,
pageSize,
// day:parseTime(new Date().getTime(),'{y}-{m}-{d}'),//今天
taskStatus:3,//进行中
}
// let res = await noticeList(param);
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||{};
let res = await taskList(param);
let data = res||{};
resolve({
...data,
// total: res.recordCount || 0
});
});
@@ -364,7 +263,7 @@ const handleDetail = (item,type) =>{
if(type==1){
url = '/pages/business/polling/taskDetail?id='+item.taskId;
}else{
url = '/pages/business/polling/problemDetail?id='+item.taskId;
url = '/pages/business/polling/problemDetail?problemId='+item.problemId;
}
uni.navigateTo({
url
@@ -383,10 +282,10 @@ const handleJump = (item)=>{
<style scoped>
.scroll-h{
/* #ifdef APP-PLUS */
height: calc(100vh - 108px);
height: calc(100vh - 78px);
/* #endif */
/* #ifndef APP-PLUS */
height: calc(100vh - 93px);
height: calc(100vh - 58px);
/* #endif */
}
.head-right{

View File

@@ -15,35 +15,41 @@
</customHeader>
<!-- 高度来避免头部遮挡 -->
<view class="top-height"></view>
<!-- 下拉刷新 -->
<mescroll-uni ref="mescrollRef" @init="mescrollInit"
:down="downOption" @down="downCallback"
:fixed="false" class="scroll-h"
>
<!-- 1 单选 2多选 3判断 4 问答 5 读卡 6 扫码 7 拍照 8 视频 9 定位暂时去掉了 -->
<view class="white-bg">
<view class="blue-title">{{optionObj.optionName}}</view>
<view class="blue-title">{{optionObj.groupName}}</view>
<view class="blue-sub-title" style="margin-bottom:20rpx;">
巡检日期<text>{{parseTime(optionObj.planTime,'{y}-{m}-{d} 星期{a}')}}</text>
巡检日期<text>{{parseTime(optionObj.lastCheckTime,'{y}-{m}-{d} 星期{a}')}}</text>
</view>
<view class="report-list" v-for="(item, index) in optionObj.list" :key="index">
<block v-if="optionObj.pointList">
<block v-if="optionObj.pointList.length>0">
<view class="report-list" v-for="(item, index) in optionObj.pointList" :key="index">
<!-- 单选 -->
<block v-if="item.pointType==1">
<view class="r-left">
<view class="r-left" style="width:100%">
<view>{{String(index+1).padStart(2, '0')+'.'}}</view>
<view>{{ item.pointName }}</view>
</view>
<multipleSelect :multiple="false" :value="item.chooseList" downInner
:options="item.optionList" @change="(...args) => changeCheck(...args, item)"
:slabel="'optionContent'" :svalue="'optionId'"
:slabel="'optionContent'" :svalue="'optionTitle'"
>
</multipleSelect>
</block>
<!-- 多选 -->
<block v-else-if="item.pointType==2">
<view class="r-left">
<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="'optionId'"
:slabel="'optionContent'" :svalue="'optionTitle'"
>
</multipleSelect>
</block>
@@ -56,11 +62,10 @@
</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"
<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>
@@ -70,13 +75,13 @@
</block>
<!-- 问答 -->
<block v-else-if="item.pointType==4">
<view class="r-left">
<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.result" auto-height placeholder="请输入" placeholder-class="place-input"></textarea>
<textarea class="textarea" v-model="item.resultContent" auto-height placeholder="请输入" placeholder-class="place-input"></textarea>
</view>
</block>
<!-- 读卡 -->
@@ -87,7 +92,7 @@
<view>{{ item.pointName }}</view>
</view>
<!-- #ifdef APP-PLUS -->
<view class="r-right" @click="initNFC">
<view class="r-right" @click.stop="initNFC">
<img :src="'static/images/polling/icon-NFCcode.png'" class="img-nfc" /> 开始识别
</view>
<!-- #endif -->
@@ -101,27 +106,33 @@
<view>{{ item.pointName }}</view>
</view>
<!-- #ifdef APP-PLUS -->
<view class="r-right r-active" v-if="scanStr" @click="handleScan">
<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">
<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">
<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="(item,index) in imgArr" :key="index">
<img :src="item" />
<view class="img-show" v-for="(item2,index) in imgArr2" :key="index">
<img :src="item2" />
</view>
<view class="img-con" @click="chooseImage">
<view class="img-con" @click="chooseImage(item)">
<img :src="'static/images/polling/icon-AddPic.png'" class="img-pic" />
<view>添加照片</view>
</view>
@@ -129,33 +140,35 @@
</block>
<!-- 视频 -->
<block v-else-if="item.pointType==8">
<view class="r-left">
<view class="r-left" style="width:100%">
<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 class="img-show" v-for="(item2,index) in videoArr2" :key="index">
<video :src="item2" controls></video>
</view>
<view class="img-con" @click="chooseVideo">
<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.list.length-1?'#E7E7E7':'#fff'}"></view>
<view class="report-border" :style="{borderColor:index<optionObj.pointList.length-1?'#E7E7E7':'#fff'}"></view>
</view>
<view class="btn-submit">
<button type="primary" @click="handleSubmit">提交</button>
<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>
</block>
<view v-else class="no-data">
<img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" />
</view>
</view>
</mescroll-uni>
</view>
<!-- 弹窗提示 -->
<pollingShowModal :visible="visible"
@@ -171,243 +184,223 @@
ref="showModel"
></pollingShowModal>
<!-- 普通弹窗提示 -->
<customShowModal
:title="''"
:content="content3"
:visible="visible3"
:btnFlag2="false"
@confirm="handleClose3"
ref="showModel3"
></customShowModal>
</view>
</template>
<script setup>
import { ref,onMounted,onUnmounted,nextTick,computed,reactive } from 'vue'
import { onLoad,onHide} from '@dcloudio/uni-app';
import { MINIO_KEY } from '@/enums/cacheEnums';
import customHeader from '@/components/customHeader.vue';
import MescrollUni from 'mescroll-uni/mescroll-uni.vue';
import multipleSelect from "@/components/multipleSelect.vue";
import pollingShowModal from "@/components/pollingShowModal.vue";
import customShowModal from "@/components/customShowModal.vue"
import { parseTime } from '@/utils/datetime.js';
import { formatTaskStatus } from '@/utils/status.js';
import { taskDetail } from '@/api/polling.js'
import {uploadFileMinio} from '@/utils/minio.js'
import { taskGroupDetail,submitResult,minioUpload } from '@/api/polling.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 checkList=[
{ value: 0, text: "答案1" },
{ value: 1, text: "答案2" },
{ value: 2, text: "答案3" },
{ value: 3, text: "答案4" },
{ value: 4, text: "答案5" },
{ value: 4, text: "答案6" }
];
let taskId = ref(undefined);
let groupId = ref(undefined);
let minioObj = ref({});
onLoad(option => {
// console.log(option)
workId.value = option.id;
getList();
taskId.value = option.taskId;
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 optionObj = ref({})
// 获取数据列表
const getList = () => {
// let res = await noticeList();
const getList = async() => {
let param = {
taskId:taskId.value,
groupId:groupId.value
}
// 1 单选 2多选 3判断 4问答 5 读卡 6 扫码 7 拍照 8 视频 9 定位
let res = {
"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 res = await taskGroupDetail(param);
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)
})
}
}
let data = res.data||{};
// data.list.forEach(item=>{
// item.chooseList
// })
})
// console.log(data.pointList)
optionObj.value = data
}
// 跳转问题上报页面
const handleQuestion=()=>{
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)=>{
// console.log(e,item)
// console.log("radioChange=>",e,item)
let radioValue = e.detail.value;
item['optionIds']=radioValue;
item['resultContent']=radioValue;
console.log("222判断radioChange=>",item)
}
// 单选多选处理
const changeCheck = (param,param2,item) => {
// console.log(param,param2,item)
item['optionIds'] = param2.join(",");
// console.log(item)
// console.log("111多选changeCheck=>",param,param2)
item['resultContent'] = param2.join(",");//JSON.stringify(param);
console.log("222多选changeCheck=>",item)
}
// 照片及拍照处理
const imgArr = ref([]);
const imgArr2=ref([]);
const chooseImage = () => {
imgArr.value = [];
const chooseImage = (item) => {
console.log("item=>",item)
try {
uni.chooseImage({
// count: 1, // 默认是9这里设置为1次只选1张
sizeType: ['compressed'], // 可以指定是原图还是压缩图,可选 'original' 或 'compressed'
// sizeType: ['compressed'], // 可以指定是原图还是压缩图,可选 'original' 或 'compressed'
sourceType: ['album', 'camera'], // 指定来源是相册还是相机,默认二者都有
// quality:80,
// width:'1920px',
// height:'1920px',
success: async (res) => {
// 选择成功,返回本地文件路径列表
let files = res.tempFilePaths;
// console.log('图片临时路径:', files, res.tempFiles);
// 显示本地图片
imgArr.value.push(...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=>{
console.log("上传成功后图片路径====>",res)
imgArr2.value = res;
let param = {
filePath: compressImg,
name: 'file',
formData: {
directory:'polling'
},
}
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 videoArr = ref([]);
const chooseVideo = () => {
const videoArr2 = ref([]);
const chooseVideo = (item) => {
uni.chooseVideo({
sourceType: ['album', 'camera'], // 来源:相册和相机
maxDuration: 60, // 最大时长(秒)
camera: 'back', // 使用后置摄像头
compressed: true, // 压缩视频
success: (res) => {
videoSrc.value=res.tempFilePath;
videoArr.value.push(res.tempFilePath)
console.log("res=>",res)
// videoSrc.value=res.tempFilePath;
// videoArr.value.push(res.tempFilePath)
console.log('视频路径:', res.tempFilePath);
console.log('视频时长:', res.duration);
console.log('视频大小:', res.size);
// console.log('视频时长:', res.duration);
// 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) => {
console.error('选择视频失败:', err);
@@ -418,35 +411,40 @@ const chooseVideo = () => {
// nfc 处理
let discoveryCallback = null
const initNFC = () => {
const initNFC = async(item) => {
// console.log("initNFC=>",plus)
//这里用异步获取读取到的NFC数据
const nfcId = await nfcUtil.listenNFCStatus();
console.log("initNFC=>",nfcId)
// 确保在 App 环境
if (typeof plus === 'undefined') {
showModel('此功能仅支持 App 端')
return
}
// if (typeof plus === 'undefined') {
// showModel3('此功能仅支持 App 端')
// return
// }
// 检查设备是否支持NFC
if (!plus.nfc) {
showModel('设备不支持 NFC')
return;
}
if (!plus.nfc.isSupportNFC()) {
showModel('设备不支持 NFC')
return;
}
// // 检查设备是否支持NFC
// if (!plus.nfc) {
// showModel3('设备不支持 NFC')
// return;
// }
// if (!plus.nfc.isSupportNFC()) {
// showModel3('设备不支持 NFC')
// return;
// }
// 检查NFC是否开启
plus.nfc.isNFCEnabled((enabled) => {
if (enabled) {
startDiscovery()
} else {
showModel('请先开启设备NFC功能')
}
},(error) => {
console.error('检查NFC状态失败:'+error.message);
showModel('检查NFC状态失败')
})
// // 检查NFC是否开启
// plus.nfc.isNFCEnabled((enabled) => {
// if (enabled) {
// startDiscovery()
// } else {
// showModel3('请先开启设备NFC功能')
// }
// },(error) => {
// console.error('检查NFC状态失败:'+error.message);
// showModel3('检查NFC状态失败')
// })
}
// 执行NFC扫描
const startDiscovery = () => {
@@ -479,27 +477,14 @@ const startDiscovery = () => {
// 扫二维码
const scanStr = ref(undefined);
const handleScan = () => {
const handleScan = (item) => {
// 调用扫码API
uni.scanCode({
success: (res) => {
scanStr.value = res.result;
console.log('扫码结果:', res.result); // 二维码内容
console.log('码类型:', res.scanType); // 码类型,如 QR_CODE
// ['optionIds'] = 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
// });
// }
item.resultContent = res.result
},
fail: (err) => {
console.error('扫码失败:', err);
@@ -508,9 +493,44 @@ const handleScan = () => {
}
// 提交
let submitParam = {}
let submitLoading = ref(false)
const handleSubmit=()=>{
submitLoading.value = true;
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('有未完成的巡检项');
// showModel2('此巡检项已完成');
}
// 循环处理给后台传值
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;
}
const showModel2=(str)=>{
visible.value = true;
content.value = str;
subContent.value='提交时间';
btnTxt.value='确定';
btnFlag2.value=false;
isGreen.value = true;
subTime.value = new Date().getTime();
visible.value = true;
}
//关闭
const handleClose=()=>{
visible.value = false;
submitLoading.value = false;
}
// 执行提交
const handleConfirm=()=>{
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;
})
}
// 组件卸载时停止监听
onUnmounted(() => {
// #ifdef APP-PLUS
if (discoveryCallback) {
plus.nfc.removeEventListener('discovered', discoveryCallback)
} catch (error) {
console.log("==========",error)
visible.value = false;
}
plus.nfc.stopDiscovery?.()
// #endif
}
// 基础弹窗
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(() => {
})
</script>
<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 .btn-yellow{
background-color: #FCC123;
@@ -609,7 +662,7 @@ onUnmounted(() => {
}
.report-list .r-left{
display: flex;
/* align-items: center; */
align-items: center;
width:70%;
font-size:28rpx;
}
@@ -715,6 +768,9 @@ onUnmounted(() => {
}
.r-left .r-l-right{
}
.no-data{
padding:200rpx 0 200rpx;
}
.no-data .no-pic{
display: block;

View File

@@ -16,6 +16,11 @@
<!-- 高度来避免头部遮挡 -->
<view class="top-height"></view>
<!-- 下拉刷新 -->
<mescroll-uni ref="mescrollRef" @init="mescrollInit"
:down="downOption" @down="downCallback"
:fixed="false" class="scroll-h"
>
<view class="white-bg">
<view class="red-title">问题{{problemObj.groupName}}</view>
<view class="report-list">
@@ -36,11 +41,11 @@
<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 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.planTime,'{y}-{m}-{d} {h}:{i}')}}</view>
<view class="report-right report-w">{{parseTime(problemObj.createTime,'{y}-{m}-{d} {h}:{i}')}}</view>
</view>
</view>
<view class="report-border"></view>
@@ -68,6 +73,8 @@
</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">
@@ -91,8 +98,10 @@
</view>
</view>
</view>
</block>
</block>
</view>
</mescroll-uni>
</view>
</view>
</template>
@@ -101,46 +110,75 @@
import { ref,onMounted,onUnmounted,nextTick,computed,reactive } from 'vue'
import { onLoad,onHide} from '@dcloudio/uni-app';
import customHeader from '@/components/customHeader.vue';
import MescrollUni from 'mescroll-uni/mescroll-uni.vue';
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 isToday = ref(false)
onLoad(option => {
// console.log(option)
id.value = option.id;
getList();
problemId.value = option.problemId;
})
// 下拉刷新
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();
}
}
// 获取数据列表
const getList = () => {
// let res = await noticeList();
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',
}
]
}
}
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.listFile=data.problemVedio.split(",") || [];
data.logList.forEach(item => {
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;
}
@@ -154,7 +192,7 @@ const handleQuestion=()=>{
// 修改
const handleUpdate=()=>{
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>
<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 .btn-yellow{
background-color: #FCC123;

View File

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

View File

@@ -8,12 +8,17 @@
<!-- 高度来避免头部遮挡 -->
<view class="top-height"></view>
<!-- 下拉刷新 -->
<mescroll-uni ref="mescrollRef" @init="mescrollInit"
:down="downOption" @down="downCallback"
:fixed="false" class="scroll-h"
>
<view class="white-bg">
<view class="red-title">问题{{optionObj.optionName}}</view>
<view class="red-title">问题{{optionObj.groupName}}</view>
<view class="report-list">
<view class="report-pro">问题项</view>
<view class="report-right">
<view class="r-list" v-for="(item, index) in optionObj.list" :key="index" @click="handleRound(item)">
<view class="r-list" v-for="(item, index) in optionObj.pointList" :key="index" @click="handleRound(item)">
<view class="r-left" :class="{'r-red':item.active}">
<view>{{String(index+1).padStart(2, '0')+'.'}}</view>
<view>{{ item.pointName }}</view>
@@ -27,12 +32,12 @@
<view class="report-border"></view>
<view class="report-list">
<view class="report-pro">提交人</view>
<view class="report-right">{{realname}}</view>
<view class="report-right">{{optionObj.createUserName?optionObj.createUserName:realname}}</view>
</view>
<view class="report-border"></view>
<view class="report-list" style="display:block;">
问题描述
<textarea class="r-input textarea" v-model="desc" auto-height
<textarea class="r-input textarea" v-model="optionObj.problemDesc" auto-height
placeholder="请输入问题项描述" placeholder-class="place-input"
></textarea>
</view>
@@ -46,15 +51,23 @@
<view class="img-show" v-for="(item,index) in videoArr" :key="index">
<video :src="item" controls></video>
</view>
<!-- #ifdef APP-PLUS -->
<view class="img-con" @click="chooseMedia">
<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 class="btn-submit">
<button type="primary" @click="handleSubmit">{{id?'修改问题跟踪表':'生成问题跟踪表'}}</button>
<button type="primary" @click="handleSubmit">{{problemId?'修改问题跟踪表':'生成问题跟踪表'}}</button>
</view>
</view>
</mescroll-uni>
</view>
</view>
</template>
@@ -65,71 +78,117 @@ import { onLoad,onHide} from '@dcloudio/uni-app';
import customHeader from '@/components/customHeader.vue';
import MescrollUni from 'mescroll-uni/mescroll-uni.vue';
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 desc = ref('');//描述
onLoad(async option => {
// console.log(option)
id.value = option.id;
taskId.value = option.taskId;
groupId.value = option.groupId;
problemId.value = option.problemId;
let userinfo = await getUserInfo({});
realname.value = userinfo.realname
getList();
})
// 查询列表
let list = ref([]);
let optionObj = ref({})
// 下拉刷新
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();
}
}
// 获取数据列表
const getList = () => {
// let res = await noticeList();
// 1 单选 2多选 3判断 4问答 5 读卡 6 扫码 7 拍照 8 视频 9 定位
let res = {
"code": 200,
"msg": "操作成功",
"data": {
optionName:'配电箱箱体和内部线路检查',
planTime:new Date().getTime(),
list:[
{ pointName:'技术中心机房总电源', optionId:202512297899, pointType:1},
{ pointName:'监控室消防设备阀门正常开启闭合', optionId:202512297899, pointType:2},
{ pointName:'监控室10组灭火器压力指针处于绿色区域', optionId:202512297899, pointType:3,active:true},
{ pointName:'库房灭火器压力指针处于绿色区', optionId:202512297899,pointType:4,active:true},
{ pointName:'技术中心机房总电源', optionId:202512297899,pointType:5},
{ pointName:'监控室消防设备阀门正常监控室消防设备阀门正常监控室消防设备阀门正常', optionId:202512297899,pointType:6},
{ pointName:'库房灭火器压力指针处于绿色区', optionId:202512297899,pointType:7},
{ pointName:'技术中心机房总电源', optionId:202512297899,pointType:8},
],
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 = res.data||{};
})
optionObj.value = data;
}
// 图片或视频
let imgArr = ref([]);//视频
let videoArr = ref([]);//视频
const imgArr2=ref([]);
let mediaArr = ref([]);//传给后台的地址
let imgArr=ref([]);//图片 后台返回的
let videoArr = ref([]);//视频 后台返回的
const chooseMedia = () => {
imgArr.value=[];
videoArr.value=[];
uni.chooseMedia({
count: 9,
mediaType: ['image', 'video'], // 指定可选择图片和视频
sourceType: ['album', 'camera'],
maxDuration: 30, // 拍摄视频最长拍摄时间
maxDuration: 60, // 拍摄视频最长拍摄时间
camera: 'back',
success: (res) => {
console.log(res)
res.tempFiles.forEach(file => {
res.tempFiles.forEach(async file => {
// tempFilePath
console.log(`文件类型: ${file.fileType}, 文件路径: ${file.tempFilePath}`);
let compressImg = file.tempFilePath;
// 图片进行压缩
if (file.fileType === 'image') {
// 显示本地图片
imgArr.value.push(file.tempFilePath)
} else if (file.type === 'video') {
// 处理视频
videoArr.value.push(file.tempFilePath)
// #ifdef APP-PLUS
// 压缩图片
compressImg = await compressImageUni(file.tempFilePath);
// #endif
}
// 执行上传
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=()=>{
// showModel('有未完成的巡检项');
// showModel2('此巡检项已完成');
let pointIds = [];
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>
<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{
width: 680rpx;
padding: 15rpx 30rpx 40rpx 40rpx;
@@ -211,7 +316,7 @@ const handleSubmit=()=>{
}
.report-list .r-left{
display: flex;
/* align-items: center; */
align-items: center;
width:90%;
font-size:28rpx;
color:#919191;

View File

@@ -39,15 +39,15 @@
<view class="calender-list">
<view class="calender-item">
<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>
<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="item-red">{{count3}}</view>
<view class="font28">未完成</view>
<view class="font28">已过期</view>
</view>
</view>
</view>
@@ -64,11 +64,12 @@
<block v-for="(row,index) in list" :key="index">
<!-- 日期展示 -->
<view class="date-title">{{parseTime(row.date,'{y}-{m}-{d} 星期{a}')}}</view>
<!-- 日期展示 parseTime(row.date,'{y}-{m}-{d} 星期{a}')-->
<view class="date-title">{{row.day}}</view>
<!-- 日常巡检 -->
<view class="blue-title">日常巡检</view>
<block v-if="row.list1">
<block v-if="row.list1.length>0">
<view class="report-list" v-for="(item, index) in row.list1" :key="index" @click="handleDetail(item,1)">
<view class="r-list" style="padding-bottom:0">
@@ -77,7 +78,7 @@
<!-- 任务(巡检)状态 1=未发布 2=已发布 3 进行中 4 已完成 5 已过期 -->
<!-- 状态为3进行中时 进度>0执行中 进度=0为待执行 -->
<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" />
</block>
<img v-else-if="item.taskStatus==4" :src="'static/images/polling/icon-complete.png'" class="img-complete" />
@@ -89,14 +90,14 @@
</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-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.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 class="r-l-right">完成比率<span class="r-blue">{{item.percentage}}</span></view>
</view>
@@ -105,7 +106,7 @@
<view class="r-left">
<view>任务状态
<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>
</span>
<span class="r-gray" v-else>{{formatTaskStatus(item.taskStatus) }}</span>
@@ -118,9 +119,14 @@
<view v-else class="no-data">
<img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" />
</view>
</block>
<view v-else class="no-data">
<img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" />
</view>
<!-- 临时巡检 -->
<view class="green-title" style="margin-top:60rpx">临时巡检</view>
<block v-if="row.list2">
<block v-if="row.list2.length>0">
<view class="report-list" v-for="(item, index) in row.list2" :key="index" @click="handleDetail(item,1)">
<view class="r-list" style="padding-bottom:0">
@@ -129,7 +135,7 @@
<!-- 任务(巡检)状态 1=未发布 2=已发布 3 进行中 4 已完成 5 已过期 -->
<!-- 状态为3进行中时 进度>0执行中 进度=0为待执行 -->
<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" />
</block>
<img v-else-if="item.taskStatus==4" :src="'static/images/polling/icon-complete.png'" class="img-complete" />
@@ -141,14 +147,14 @@
</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-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.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 class="r-l-right">完成比率<span class="r-blue">{{item.percentage}}</span></view>
</view>
@@ -157,7 +163,7 @@
<view class="r-left">
<view>任务状态
<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>
</span>
<span class="r-gray" v-else>{{formatTaskStatus(item.taskStatus) }}</span>
@@ -170,14 +176,20 @@
<view v-else class="no-data">
<img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" />
</view>
</block>
<view v-else class="no-data">
<img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" />
</view>
<!-- 问题跟踪 -->
<!-- 问题跟踪 按月没有问题跟踪-->
<block v-if="activeTab==0">
<view class="bg-border"></view>
<view class="red-title">问题跟踪</view>
<block v-if="row.list3">
<block v-if="row.list3.length>0">
<view class="report-list" v-for="(item, index) in row.list3" :key="index" @click="handleDetail(item,2)">
<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">
<!-- 问题状态 1=追踪2=关闭 -->
<view v-if="item.problemStatus==1" class="btn-red">进行中</view>
@@ -186,8 +198,8 @@
</view>
<view class="r-list">
<view class="r-left">
<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.modifyTime,'{m}-{d} {h}:{i}') }}</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.lastLogTime,'{m}-{d} {h}:{i}') }}</span></view>
</view>
</view>
<view class="report-border" v-if="index<row.list3.length-1"></view>
@@ -196,7 +208,11 @@
<view v-else class="no-data">
<img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" />
</view>
</block>
<view v-else class="no-data">
<img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" />
</view>
</block>
</block>
</view>
</mescroll-uni>
@@ -213,31 +229,39 @@ import calenderMonthSimple from '@/components/calenderMonthSimple.vue'
import customTabs from '@/components/customTabs.vue';
import { parseTime } from '@/utils/datetime.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 month=ref('');//默认月份
const activeTab = ref(0);//默认按天查看
const tabList = ['按天查看', '按月查看'];
let count1=ref(12);//巡检
let count2=ref(9);//巡检
let count3=ref(3);//已完成
let count1=ref(0);//巡检
let count2=ref(0);//巡检
let count3=ref(0);//已过期
onLoad(option => {
let date = new Date();
year.value = date.getFullYear();
month.value = date.getMonth()+1;
selectDate.value = parseTime(date,'{y}-{m}-{d}')//默认查今天
})
// tab切换 按日 or 按月 0-按日 1-按月
const handleTab = (index)=>{
const handleTab = async (index)=>{
activeTab.value = index;
isMonth.value=true;
// 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({
@@ -251,23 +275,22 @@ const monthSwitch=(e)=>{
console.log('monthSwitchs 返回:', e)
}
// 按日选择 日历change
const calendarChange=(e)=> {
console.log('按日选择 返回:', e.fulldate)
form.value.selectDate = e.fulldate
// 模拟动态打卡
// if (calendarInfo.value.selected.length > 5) return
// calendarInfo.value.selected.push({
// date: e.fulldate,
// info: '打卡'
// })
const calendarChange= async(e)=> {
// console.log('按日选择 返回:', e.fulldate)
selectDate.value = e.fulldate
const res = await getList();
list.value = res.list;
}
// 按月选择 日历change
const calendarChange2=(value)=> {
console.log("按月选择 选择具体月份=>",value)
form.value.selectDate = value.ymStr
const calendarChange2= async(value)=> {
// console.log("按月选择 选择具体月份=>",value)
selectDate.value = value.ymStr
year.value = value.year;
month.value = value.month;
const res = await getList();
list.value = res.list;
}
@@ -346,128 +369,48 @@ const upCallback = async (mescroll) => {
// 获取数据列表
const getList = (pageIndex, pageSize) => {
return new Promise(async (resolve) => {
let res ={};
if(activeTab.value==1){//月查询
let param = {
pageIndex,
pageSize,
month: selectDate.value
}
let response = await taskListMonth(param);
res ={
...response,
list:response.list || []
}
// 没数据时补值
if(res.list.length==0){
res.list.push({
list1: [],
list2: [],
});
}
// 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,
}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 || []
});
}
// console.log(res)
let data = res||{};
count1.value = data.finishNum;
count2.value = data.waitNum;
count3.value = data.expiredNum
}
]
}
]
}
}
let data = res.data||{};
resolve({
...data,
// total: res.recordCount || 0
});
});
@@ -495,7 +438,7 @@ const handleDetail = (item,type) =>{
if(type==1){
url = '/pages/business/polling/taskDetail?id='+item.taskId;
}else{
url = '/pages/business/polling/problemDetail?id='+item.taskId;
url = '/pages/business/polling/problemDetail?problemId='+item.problemId;
}
uni.navigateTo({
url

View File

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

View File

@@ -29,10 +29,10 @@
<mescroll-uni ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback"
:up="upOption" :down="downOption" :fixed="false" class="scroll-h" :class="{'loading-scroll':cssFlag}">
<view class="white-bg">
<block v-if="list">
<block v-if="list.length>0">
<block v-for="(obj, index) in list" :key="index">
<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="r-title">{{ parseTime(obj.dateStr,'{y}-{m}-{d} 星期{a}')}}</view> -->
<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-name">{{ item.taskName }}</view>
<view class="r-right">
@@ -54,32 +54,35 @@
</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-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>
</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>
完成进度<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 class="r-l-right">完成比率<span class="r-blue">{{(item.groupFinishNum/item.groupNum).toFixed()+'%'}}</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-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<obj.list.length-1"></view>
<view class="report-border" v-if="index<list.length-1"></view>
</view>
</block>
<view v-else class="no-data">
<img :src="'static/images/polling/pic-NoResult.png'" class="no-pic" />
</view>
</block>
<view v-else class="no-data">
<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 { parseTime,getDateRange,getDateRangeName } from '@/utils/datetime.js';
import { taskTypeOptions,formatTaskType,formatTaskStatus } from '@/utils/status.js';
import { noticeList } from '@/api/notice.js'
import { taskLists } from '@/api/polling.js'
const { proxy } = getCurrentInstance();
@@ -119,6 +122,9 @@ const dateConfirm=(dateObj)=>{
isShow.value = false;
dateStr.value = dateObj.startDate + ' 至 '+dateObj.endDate;
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');
dateStr.value = dateObj.startDate + ' 至 '+dateObj.endDate;
dateStrName.value="近3天"
form.value.startDate = dateObj.startDate;
form.value.endDate = dateObj.endDate
})
@@ -147,7 +157,7 @@ const changeTaskType = (e)=>{
// 查询列表
let list = ref([]);
let form = ref({
beginTime:''
startDate:''
})
const mescrollRef = ref(null);
const upOption = ref({
@@ -213,75 +223,14 @@ const getList = (pageIndex, pageSize) => {
let param = {
pageIndex,
pageSize,
timeBegin: form.value.startDate,
timeEnd: form.value.endDate,
}
// let res = await noticeList(param);
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||{};
let res = await taskLists(param);
let data = res ||{};
resolve({
...data,
total: res.recordCount || 0
// total: res.recordCount || 0
});
});
@@ -307,7 +256,7 @@ const handleDetail = (item,type) =>{
height: calc(100vh - 108px);
/* #endif */
/* #ifndef APP-PLUS */
height: calc(100vh - 130px);
height: calc(100vh - 135px);
/* #endif */
}
@@ -415,7 +364,7 @@ const handleDetail = (item,type) =>{
width:525rpx
}
.r-left .r-l-left{
width:350rpx;
width:370rpx;
}
.r-left .r-l-right{

View File

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

View File

@@ -266,7 +266,7 @@ const submitForm = () => {
//h5测试用 内网-sn123456
//公司外网 'f3fca83f-bf56-47f4-a98b-a602ed8bddee' 529a5543-6957-401e-b090-13df6dee5429
//友晟外网 '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);
userStore.login(res);
uni.switchTab({ url: '/pages/home/home' })

View File

@@ -139,7 +139,6 @@ const jumpAuthPermission=()=>{
// 跳转授权
const jumpAuthPermission2 = () => {
let main = plus.android.runtimeMainActivity();
let Intent = plus.android.importClass('android.content.Intent');
let Uri = plus.android.importClass('android.net.Uri');
@@ -228,3 +227,68 @@ export const getFileType = (filePathOrName) => {
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 { v4 as uuidv4 } from 'uuid'
@@ -14,21 +16,22 @@ import { v4 as uuidv4 } from 'uuid'
*/
export const uploadFileMinio = async (files,fileDir,tempFilePaths) => {
try {
if (!files.length){
uni.showToast({ title: '请选择要上传的文件', icon: 'none' })
return;
}
let bucketName="718ys-test";//'你的存储桶名称'
// 初始化 Minio 客户端
// #ifndef APP-PLUS
initMinio({
endPoint: '192.168.236.196', // 例如 'play.min.io'
port: 9000, // 端口,使用 SSL 通常是 443非 SSL 是 9000
useSSL: false, // 根据你的 Minio 服务器配置决定 将此值设置为“true”为HTTPS访问false为普通http访问
accessKey: 'cyLu4uv7mFErTWkx',//'你的AccessKey',
secretKey: 'XE9PYr3wt6MHveHn8kA008rebxtj2c7S' //'你的SecretKey'
});
// initMinio({
// endPoint: '192.168.236.196', // 例如 'play.min.io'
// port: 9000, // 端口,使用 SSL 通常是 443非 SSL 是 9000
// useSSL: false, // 根据你的 Minio 服务器配置决定 将此值设置为“true”为HTTPS访问false为普通http访问
// accessKey: 'cyLu4uv7mFErTWkx',//'你的AccessKey',
// secretKey: 'XE9PYr3wt6MHveHn8kA008rebxtj2c7S' //'你的SecretKey'
// });
// const minioClient = new Minio.Client({
// endPoint: '192.168.236.196', // 例如 'play.min.io'
@@ -37,65 +40,80 @@ export const uploadFileMinio = async (files,fileDir,tempFilePaths) => {
// accessKey: 'cyLu4uv7mFErTWkx',//'你的AccessKey',
// 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=[];
// 批量上传
const uploadPromises = files.map((file,index) => {
console.log("111uploadPromises=>",file)
return new Promise(async(resolve, reject) => {
// 1.图片路径
let fileName = uuidv4()+ "." + file.name.split(".").pop();
let imgDir = fileDir?(fileDir+'/'+fileName):'/'+fileName;
retrunFileArr.push(imgDir);
console.log(imgDir)
console.log(222,"uploadPromises=>",imgDir)
// minioUpload
// #ifdef APP-PLUS
uni.uploadFile({
url: 'http://192.168.236.196', //仅为示例,非真实的接口地址
filePath: tempFilePaths[index],
url: `http://192.168.236.196:9000/`+bucketName+"/",
filePath: imgDir,
name: 'file',
formData: {
'user': 'test'
},
success: (uploadFileRes) => {
console.log(uploadFileRes);
},
fail: (err)=> {
console.log("err=>",err)
}
});
// #endif
// #ifndef APP-PLUS
// 使用putObject方法上传文件[citation:3]
// minioClient.putObject(bucketName,imgDir, file, (err, etag) => {
// if (err) {
// console.error('上传失败:', err);
// reject(err);
// } else {
// console.log('上传成功Etag:', 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)
bucketName,
accessKey: "XE9PYr3wt6MHveHn8kA008rebxtj2c7S",
secretKey: "cyLu4uv7mFErTWkx",
},success: (res) => {
uni.hideLoading()
if (res.statusCode !== 204) {
reject()
} else {
console.log('上传成功Etag:', etag);
// 上传成功后的处理
resolve(etag)
resolve(aliyunKey)
}
});
// #endif
},fail: err => {
reject()
uni.hideLoading()
}
})
// const command = new PutObjectCommand({
// Bucket: bucketName,
// 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) {
// console.error('555上传失败:', err);
// // 处理错误
// reject(err)
// } else {
// console.log('666上传成功Etag:', etag);
// // 上传成功后的处理
// resolve(etag)
// }
// });
})
})
@@ -112,6 +130,7 @@ export const uploadFileMinio = async (files,fileDir,tempFilePaths) => {
// 将 File 对象读取为 ArrayBuffer 的辅助函数
const readFileAsArrayBuffer = (file) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
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 上传图片
*/
uploadFile(options, config) {
// console.log("uploadFile=>",options)
let mergeOptions = merge({}, this.options.requestOptions, options);
const mergeConfig = merge({}, this.options, config);
const {
@@ -65,6 +66,8 @@ export default class HttpRequest {
if (requestInterceptorsHook && isFunction(requestInterceptorsHook)) {
mergeOptions = requestInterceptorsHook(mergeOptions, mergeConfig);
}
// console.log("上传参数=>",mergeOptions)
return new Promise((resolve, reject) => {
uni.uploadFile({
...mergeOptions,