货无忧安装平台
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.
 
 
 
 
 

629 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()
initpage()
// basicContainer.value.startPullDownRefresh()
const _height = await utils.getViewDistanceFormTop('.scvmabx')
details.scrollheight = Number(_height.replace('px', '')) - 100 + 'px'
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)
}
})
onLoad((e) => {
details.pageInfo.install_id = e.id
})
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>