You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
631 lines
13 KiB
631 lines
13 KiB
<template> |
|
<BasicContainer ref='basicContainer' :option="option"> |
|
<!-- 头部 --> |
|
<template #head> |
|
</template> |
|
|
|
<!-- 主体 --> |
|
<template #body> |
|
<view class="main"> |
|
<scroll-view class="scvmabx" :style="{height: details.scrollheight}" @scrolltolower="()=>{}" scroll-y="true" |
|
@touchmove.stop> |
|
<block v-for="(item,index) in details.pageArr" :key="item.title"> |
|
<view :class="{mt20: index !== 0}"> |
|
<PullDownBox ref="imgPullDownRefList"> |
|
<template #title> |
|
<view class="server_list_container_header"> |
|
<view class="row flex-c-sb border-none"> |
|
<view class="title"> |
|
{{item.title}} |
|
</view> |
|
|
|
<view class="addBtn flex" @click.stop="() => handleAdd(item)"> |
|
<u-icon name="plus-circle" color="#2979ff" size="36"></u-icon> |
|
|
|
<view class="ml10 mr10"> |
|
添加 |
|
</view> |
|
</view> |
|
</view> |
|
</view> |
|
</template> |
|
|
|
<template #content> |
|
<view class="server_list_container_info"> |
|
<block v-for="(val, i) in item.list"> |
|
<view :class="{'info_item': true, 'mt20': i !== 0}"> |
|
<view class="title info_item_title flex-c-sb"> |
|
<view class="flex-c-c"> |
|
<view class="fwb mr20"> |
|
<text> |
|
{{item.title + ' - '}} |
|
</text> |
|
<text> |
|
{{ (i + 1)}} |
|
</text> |
|
</view> |
|
</view> |
|
|
|
<view class="flex"> |
|
|
|
<view class="flex mr20" @click.stop="() => handleAdd(item, i)"> |
|
<u-icon name="plus-circle" color="#fff" size="36"></u-icon> |
|
|
|
<view class="ml10 mr10"> |
|
添加 |
|
</view> |
|
</view> |
|
|
|
<view class="flex-c-c" @click="()=> handleRemove(item, i)"> |
|
<u-icon name="trash" color="#fff" size="36"></u-icon> |
|
|
|
<view class="ml10"> |
|
删除 |
|
</view> |
|
</view> |
|
</view> |
|
</view> |
|
|
|
<view class="info_item_container imgList flex"> |
|
<block v-for="(value, j) in val.imgList"> |
|
<!-- 单个图片 --> |
|
<view class="image_conatiner mr20 mb20"> |
|
<view class=""> |
|
<image :src="value.url" mode=""></image> |
|
|
|
<!-- 删除 --> |
|
<view class="removeIcon" @click="()=> handleRemoveImg(val.imgList, j)"> |
|
<u-icon name="close-circle-fill" color="#666" size="50"></u-icon> |
|
</view> |
|
</view> |
|
|
|
</view> |
|
</block> |
|
<!-- 添加图片 --> |
|
<view class="image_conatiner addImg flex-c-c mr20 mb20" |
|
@click="() => handleUploadFile(val.imgList)"> |
|
<u-icon name="photo-fill" color="#999" size="100"></u-icon> |
|
</view> |
|
</view> |
|
</view> |
|
</block> |
|
</view> |
|
</template> |
|
</PullDownBox> |
|
</view> |
|
</block> |
|
|
|
<view class="pd20 mt20 row"> |
|
<view class="mb20">备注</view> |
|
|
|
<u-textarea v-model="details.form.remark" placeholder="请输入"></u-textarea> |
|
</view> |
|
</scroll-view> |
|
|
|
<view class="footer"> |
|
<!-- <view class="button"> |
|
保存 |
|
</view> --> |
|
|
|
<view class="button subColor" @click="handleSubmit"> |
|
确认完工 |
|
</view> |
|
</view> |
|
</view> |
|
|
|
</template> |
|
</BasicContainer> |
|
|
|
<tips ref="tip"></tips> |
|
<!-- #ifdef APP --> |
|
<!-- <saomiao2 :ishidestop="scanState !== 0"></saomiao2> --> |
|
<!-- #endif --> |
|
</template> |
|
|
|
<script lang="ts" setup> |
|
import { |
|
postInstallComplete, |
|
postInstallWorkingInfo |
|
} from '@/api/user.js' |
|
import { |
|
onLoad, |
|
onShow, |
|
onHide, |
|
} from '@dcloudio/uni-app' |
|
import { nextTick, reactive, ref, toRefs } from "vue"; |
|
import utils from '@/utils/utils.js' |
|
import useSystemSettingsStore from '@/store/useSystemSettingsStore'; |
|
import { storeToRefs } from 'pinia'; |
|
const { scanState } = storeToRefs(useSystemSettingsStore()) |
|
// 组件配置 |
|
const option = reactive({ |
|
// 标题 |
|
title: '完工详情', |
|
// 下拉刷新回调函数 |
|
async pullDownRefreshInitPage() { |
|
|
|
return null |
|
}, |
|
// 触底加载回到函数 |
|
reachBottomInitPage: async () => { return null }, |
|
haveData: true, |
|
isEnd: false, |
|
pageLoading: false |
|
}) |
|
|
|
// 组件实例 |
|
const basicContainer = ref() |
|
const tip = ref() // 提示弹窗 |
|
const imgPullDownRefList = ref() |
|
|
|
let details = reactive({ |
|
show: false, |
|
/** 时间 */ |
|
datatime: '', |
|
/** 当前页码 */ |
|
pageNum: 1, |
|
/** 页数 */ |
|
pageSize: 20, |
|
/** 渲染列表数据 */ |
|
datalist: [], |
|
/** 扫描的码值 */ |
|
scancode: '', |
|
scrollheight: '80vh', |
|
/** tabbar激活code */ |
|
tabbarCode: 0, |
|
pageArr: [ |
|
{ |
|
title: '客厅', |
|
prop: 'parlor', |
|
tag: '1', |
|
list: [ |
|
{ |
|
imgList: [] |
|
} |
|
] |
|
}, |
|
{ |
|
title: '卧室', |
|
tag: '2', |
|
list: [ |
|
{ |
|
imgList: [] |
|
} |
|
] |
|
}, |
|
{ |
|
title: '厨房', |
|
prop: 'kitchen', |
|
tag: '3', |
|
list: [ |
|
{ |
|
imgList: [] |
|
} |
|
] |
|
}, |
|
{ |
|
title: '卫生间', |
|
prop: 'toilet', |
|
tag: '4', |
|
list: [ |
|
{ |
|
imgList: [] |
|
} |
|
] |
|
}, |
|
{ |
|
title: '书房', |
|
prop: 'study', |
|
tag: '5', |
|
list: [ |
|
{ |
|
imgList: [] |
|
} |
|
] |
|
}, |
|
{ |
|
title: '阳台', |
|
prop: 'balcony', |
|
tag: '6', |
|
list: [ |
|
{ |
|
imgList: [] |
|
} |
|
] |
|
}, |
|
{ |
|
title: '其它', |
|
tag: '7', |
|
prop: 'other', |
|
list: [ |
|
{ |
|
imgList: [] |
|
} |
|
] |
|
} |
|
] |
|
, form: { |
|
remark: '' |
|
}, |
|
/** 页面数据 */ |
|
pageInfo: { |
|
install_id: '' |
|
} |
|
}) |
|
|
|
onShow(async () => { |
|
// // #ifdef APP |
|
// // 初始化关闭监听 |
|
// uni.$off('scancodedate') |
|
// // init() |
|
// uni.$on('scancodedate', function (code) { |
|
// console.log('code :>> ', code); |
|
// if (code) { |
|
// console.log(code); |
|
// details.scancode = code |
|
// scandata() |
|
// } |
|
// }) |
|
// // #endif |
|
|
|
await nextTick() |
|
const _height = await utils.getViewDistanceFormTop('.scvmabx') |
|
|
|
details.scrollheight = Number(_height.replace('px', '')) - 100 + 'px' |
|
}) |
|
|
|
onLoad(async (e) => { |
|
details.pageInfo.install_id = e.id |
|
|
|
await initpage() |
|
// basicContainer.value.startPullDownRefresh() |
|
|
|
await nextTick() |
|
|
|
if (utils.getObjType(imgPullDownRefList.value) !== 'array') return |
|
for (let i = 0; i < imgPullDownRefList.value.length; i++) { |
|
const value = imgPullDownRefList.value[i] |
|
value.handleShowPullDown && value.handleShowPullDown(true) |
|
} |
|
}) |
|
|
|
const scandata = () => { } |
|
|
|
const initpage = async () => { |
|
try { |
|
option.pageLoading = true |
|
const res = await postInstallWorkingInfo({ install_id: details.pageInfo.install_id }) |
|
|
|
const { code, data } = res |
|
if (code !== 200) return |
|
console.log('data :>> ', data); |
|
|
|
if (utils.getObjType(data) !== 'object') return |
|
|
|
const { reamrk, workImages } = data |
|
|
|
details.form.remark = reamrk |
|
|
|
if (utils.getObjType(workImages) !== 'array') return |
|
|
|
for (let i = 0; i < workImages.length; i++) { |
|
const value = workImages[i] |
|
|
|
let _item : any |
|
|
|
for (let i = 0; i < details.pageArr.length; i++) { |
|
const _value = details.pageArr[i] |
|
|
|
if (_value.tag !== (value.room_tag + '')) continue |
|
_item = _value |
|
break |
|
} |
|
|
|
if (!_item) continue |
|
|
|
console.log('_item :>> ', _item); |
|
|
|
const _index = Number(value.room_name.split(' - ')[1]) - 1 |
|
|
|
_item.list.splice(_index, 1, { |
|
...value, |
|
imgList: value.images |
|
}) |
|
} |
|
} catch (err) { |
|
console.log('err :>> ', err); |
|
//TODO handle the exception |
|
} finally { |
|
option.pageLoading = false |
|
} |
|
} |
|
|
|
/** 新增子项 */ |
|
const handleAdd = (item : any, index ?: number) => { |
|
console.log('index :>> ', index); |
|
const addItem = { imgList: [] } |
|
index === undefined ? item.list.push(addItem) : item.list.splice(index, 0, addItem) |
|
} |
|
|
|
/** 移除子项 */ |
|
const handleRemove = (item, index) => { |
|
tip.value.setdetails({ |
|
isshow: true, |
|
content: '确认移除', |
|
cancelTxt: '取消', |
|
confirmTxt: '确认', |
|
success() { |
|
// 关闭弹窗 |
|
tip.value.setdetails({ isshow: false }) |
|
|
|
item.list.splice(index, 1) |
|
}, |
|
cancel() { |
|
// 关闭弹窗 |
|
tip.value.setdetails({ isshow: false }) |
|
} |
|
}) |
|
} |
|
|
|
/** 上传图片 */ |
|
const handleUploadFile = (imgList) => { |
|
const beforeUpload = (files) => { |
|
option.pageLoading = true |
|
} |
|
|
|
const successByUpload = (res) => { |
|
console.log('res :>> ', res); |
|
const { data } = res |
|
const _data = JSON.parse(data) |
|
|
|
console.log('_data :>> ', _data); |
|
const { code, data: img } = _data |
|
|
|
if (code !== 200) return |
|
|
|
imgList.push({ url: img, name: img }) |
|
} |
|
|
|
const allSuccess = () => { |
|
option.pageLoading = false |
|
} |
|
|
|
utils.handleUploadFile({ |
|
successByUpload, |
|
beforeUpload, |
|
allSuccess |
|
}) |
|
} |
|
|
|
/** 移除图片 */ |
|
const handleRemoveImg = (imgList, index) => { |
|
tip.value.setdetails({ |
|
isshow: true, |
|
content: '确认移除', |
|
cancelTxt: '取消', |
|
confirmTxt: '确认', |
|
success() { |
|
// 关闭弹窗 |
|
tip.value.setdetails({ isshow: false }) |
|
|
|
imgList.splice(index, 1) |
|
}, |
|
cancel() { |
|
// 关闭弹窗 |
|
tip.value.setdetails({ isshow: false }) |
|
} |
|
}) |
|
} |
|
|
|
/** 提交 */ |
|
const handleSubmit = () => { |
|
const submitData = { |
|
install_id: details.pageInfo.install_id, |
|
images: [] as { |
|
// 图片归属类型 例: 1 -- 客厅 |
|
room_tag : string, |
|
// 分组名称 例: 客厅1 |
|
room_name : string, |
|
// 图片数据 |
|
images : { name : string, url : string }[] |
|
}[], |
|
remark: details.form.remark |
|
} |
|
|
|
for (let i = 0; i < details.pageArr.length; i++) { |
|
const value = details.pageArr[i] |
|
|
|
for (let j = 0; j < value.list.length; j++) { |
|
const item = value.list[j] |
|
|
|
if (item.imgList.length > 0) { |
|
const _addItem = { |
|
room_name: value.title + ' - ' + (j + 1), |
|
room_tag: value.tag, |
|
images: [ |
|
...item.imgList |
|
] |
|
} |
|
|
|
item.id && (_addItem.id = item.id) |
|
|
|
submitData.images.push(_addItem) |
|
} |
|
} |
|
} |
|
|
|
if (submitData.images.length === 0) return utils.handleToast('最少上传一张图片') |
|
|
|
tip.value.setdetails({ |
|
isshow: true, |
|
content: '确认完工提交', |
|
cancelTxt: '取消', |
|
confirmTxt: '确认', |
|
async success() { |
|
try { |
|
option.pageLoading = true |
|
|
|
console.log('submitData :>> ', submitData); |
|
|
|
const res = await postInstallComplete(submitData) |
|
|
|
const { code, data } = res |
|
|
|
if (code !== 200) return |
|
|
|
uni.navigateBack() |
|
} catch (err) { |
|
console.log('err :>> ', err); |
|
//TODO handle the exception |
|
} finally { |
|
option.pageLoading = false |
|
} |
|
|
|
// 关闭弹窗 |
|
tip.value.setdetails({ isshow: false }) |
|
}, |
|
cancel() { |
|
// 关闭弹窗 |
|
tip.value.setdetails({ isshow: false }) |
|
} |
|
}) |
|
} |
|
</script> |
|
|
|
<style lang="scss" scoped> |
|
@import url("@/utils/style/common.scss"); |
|
|
|
// 主体内容 |
|
.main { |
|
font-family: 黑体; |
|
position: relative; |
|
border-top-right-radius: 20upx; |
|
border-top-left-radius: 20upx; |
|
background-color: #fff; |
|
|
|
.scvmabx { |
|
background-color: #F5F5F6; |
|
|
|
:deep(.Pulldown-title-container) { |
|
padding: 20upx; |
|
} |
|
|
|
:deep(.Pulldown_content) { |
|
padding: 20upx; |
|
padding-bottom: 0; |
|
background: #F5F5F6; |
|
} |
|
|
|
:deep(.PullDownBox) { |
|
border-radius: 0; |
|
} |
|
} |
|
|
|
.info_item { |
|
border-radius: 20upx; |
|
overflow: hidden; |
|
|
|
.info_item_title { |
|
background-color: var(--subjectColor); |
|
color: #fff; |
|
padding: 25upx 20upx; |
|
} |
|
|
|
.info_item_container { |
|
background-color: #fff; |
|
padding: 20upx; |
|
padding-bottom: 0; |
|
} |
|
|
|
} |
|
|
|
.addBtn { |
|
color: #2F8DFF; |
|
} |
|
|
|
// 图片列表 |
|
.imgList { |
|
flex-wrap: wrap; |
|
|
|
.image_conatiner { |
|
width: fit-content; |
|
flex: none; |
|
position: relative; |
|
|
|
.removeIcon { |
|
position: absolute; |
|
top: 0; |
|
right: 0; |
|
transform: translate(40%, -40%); |
|
opacity: 0.9; |
|
} |
|
} |
|
|
|
.addImg { |
|
width: 160upx; |
|
height: 160upx; |
|
border-radius: 20upx; |
|
box-sizing: border-box; |
|
border: 2upx solid #eee; |
|
} |
|
|
|
image { |
|
width: 160upx; |
|
height: 160upx; |
|
border-radius: 20upx; |
|
} |
|
} |
|
} |
|
|
|
// 底部 |
|
.footer { |
|
box-sizing: border-box; |
|
height: 100px; |
|
padding-top: 30upx; |
|
display: flex; |
|
justify-content: space-between; |
|
|
|
.button { |
|
height: 80upx; |
|
display: flex; |
|
align-items: center; |
|
justify-content: center; |
|
flex: 1; |
|
// margin: 10upx; |
|
border: 2upx solid #b5babf; |
|
border-radius: 80upx; |
|
margin: 0 10upx; |
|
padding: 0 10upx; |
|
font-size: 0.9rem; |
|
font-weight: bold; |
|
|
|
&.subColor { |
|
// border-color: var(--subjectColor); |
|
// color: var(--subjectColor); |
|
background-color: var(--subjectColor); |
|
color: #fff; |
|
border: none; |
|
} |
|
|
|
&.primaryColor { |
|
// border-color: var(--primaryColor); |
|
// color: var(--primaryColor); |
|
background-color: var(--primaryColor); |
|
color: #fff; |
|
border: none; |
|
} |
|
|
|
&.errColor { |
|
// border-color: var(--errColor); |
|
// color: var(--errColor); |
|
background-color: var(--errColor); |
|
color: #fff; |
|
border: none; |
|
} |
|
} |
|
} |
|
|
|
.row { |
|
background-color: #fff; |
|
} |
|
</style> |