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

683 lines
16 KiB

<template>
<BasicContainer :option="option">
<template #body>
<view class="main" :style="{'min-height': details.scrollheight}">
<view class="flex1">
<view class="pd20 flex-c-sb">
<view class="fwb">
预计完成时间
</view>
<view class="flex-c-c" @click="details.showTime = true">
<text class="mr10" style="">
{{details.form.estimated_finish_time || '请选择时间'}}
</text>
<u-icon name="arrow-right" size="36"></u-icon>
</view>
</view>
<view class="pd20 flex-c-sb" @click="()=> handleChooseWork('item')">
<view class="fwb">
项目组
</view>
<view class="flex-c-c">
<text class="mr10" style="">
{{details.form.item_name || '请选择'}}
</text>
<u-icon name="arrow-right" size="36"></u-icon>
</view>
</view>
<view class="pd20 flex-c-sb">
<view class="fwb">
工长
</view>
<view class="flex-c-c">
<text class="mr10" style="">
{{details.form.work_user_captain}}
</text>
<!-- <u-icon name="arrow-right" size="36"></u-icon> -->
</view>
</view>
<view class="pd20 flex" @click="handleChooseInstall">
<view class="fwb">
安装人员
</view>
<template v-if="details.chooseInstallList.length > 0">
<view class="input_box">
<block v-for="item in details.chooseInstallList">
<view class="input_box_item pd20 flex">
<text class="flex1">
{{item.name}}
</text>
<view @click.stop="()=> handleChooseInstallItem(item)" class="remove flex">
<u-icon name="trash" color="#f00" size="36"></u-icon>
<text class="ml10">
移除
</text>
</view>
</view>
</block>
</view>
</template>
<template v-else>
<view class="flex-c-sb flex1">
<view class=""></view>
<view class="align-center">
<text class="mr10" style="">
请选择
</text>
<u-icon name="arrow-right" size="36"></u-icon>
</view>
</view>
</template>
</view>
</view>
<view class="flex-c-c btn_conatiner mt20">
<view class="btn mr40" @click="handleback">
关 闭
</view>
<view class="btn mr40 errBtn" @click="handleTurnDown" v-if="details.pageType === 'installSales'">
驳 回
</view>
<view class="btn subBtn" @click="handleAssignATask">
指 派
</view>
</view>
</view>
</template>
</BasicContainer>
<l-calendar v-model:value="details.showTime" :isRange="false" @hide='showCalendar' @change="onConfirm"></l-calendar>
<tips ref="tip" />
<MyDrawer ref="myDrawerByTime">
<template #content>
<picker-view v-if="details.visible" :indicator-style="details.indicatorStyle" :immediate-change="true"
:value="details.value" @change="bindChangeByTime" class="picker-view">
<picker-view-column>
<view class="item" v-for="(item, index) in details.pickerArr" :key="index">
{{ item.label }}
</view>
</picker-view-column>
</picker-view>
</template>
</MyDrawer>
<MyDrawer ref="myDrawerByChooseItem">
<template #head>
<view class="header_search flex-c-c">
<view class="input flex1">
<MyInput clearable v-model="details.searchText" placeholder="请输入安装人员名称" />
</view>
<view class="header_search_btn flex-c-c" @click="handleSearch">
搜索
</view>
</view>
<view class="flex pl20">
<view class="btn subBtn mr20"
@click="()=> details.chooseInstallList = [...new Set([...details.chooseInstallList,...details.renderInstallList])]">
全选
</view>
<view class="btn" @click="() => details.chooseInstallList = []">
清空
</view>
</view>
</template>
<template #content>
<view class="flex-c-sb flex-wrap search_list">
<block v-for="item in details.renderInstallList">
<view @click="()=> handleChooseInstallItem(item)"
:class="{'search_list_item': true, 'mb20': true, 'active': details.chooseInstallList.includes(item)}">
{{item.name}}
</view>
</block>
</view>
</template>
</MyDrawer>
</template>
<script lang="ts" setup>
import { onLoad, onShow, onHide, onUnload, onPullDownRefresh } from '@dcloudio/uni-app'
// import Tabber from '@/compoment/Tabber/Tabber.vue'
import { nextTick, ref, reactive } from 'vue'
import utils from '@/utils/utils'
import { getMasterTaskList, getCommonGetItemData, getCneterSubordinates, postInstallSalesDesignate, postInstallDesignate } from '@/api/user.js'
// 组件实例
const tip = ref(null)
const myDrawerByTime = ref()
const myDrawerByChooseItem = ref()
const option = reactive({
// 标题
title: '指派',
// 下拉刷新回调函数
async pullDownRefreshInitPage() {
return null
},
// 触底加载回到函数
reachBottomInitPage: async () => { return null },
haveData: true,
isEnd: false,
pageLoading: false
})
const details = reactive({
/** 列表容器高度 */
scrollheight: '60vh',
/** picker被选中的索引位置 */
value: [0],
/** picker行高度 */
indicatorStyle: `height: 40px;`,
/** 当前picker使用的数组 */
pickerArr: [],
/** 项目组 */
itemArr: [],
visible: false,
pageType: 'install' as 'install' | 'installSales',
/** 渲染数据 */
renderData: [],
/** 输入框搜索的值 */
searchText: '',
/** 安装人员 */
installItemList: [],
/** 渲染的安装人员 */
renderInstallList: [],
/** 被选中的安装人员 */
chooseInstallList: [],
showTime: false,
form: {
// 预计时间
estimated_finish_time: '',
// 项目组
item_id: '',
item_name: '',
// 工长
work_user_captain: '',
work_user_captain_id: '',
// 安装ID
install_id: '',
// 售后ID
install_sales_id: '',
// install_sales_work_id, 修改指派时传入
id: ''
}
})
onShow(async () => {
await nextTick()
details.scrollheight = await utils.getViewDistanceFormTop('.main')
})
onLoad((e) => {
details.form.install_sales_id = e.id
details.form.install_id = e.id
details.pageType = e.pageType
})
onUnload(() => {
uni.removeStorageSync('installWork')
})
// 显示时间
function showCalendar() {
details.showTime = !details.showTime
}
// 选择时间
function onConfirm(e : any) {
console.log(e);
details.form.estimated_finish_time = e.result
}
// 初始化设置时间
/** 获取页面数据 */
const initPage = async () => {
try {
option.pageLoading = true
await Promise.all([
initItem(),
initItemData()
])
const _info = (uni.getStorageSync('installWork') || {})
details.form.estimated_finish_time = _info.estimated_finish_time
details.form.work_user_captain = _info.work_user_captain
details.form.work_user_captain_id = _info.work_user_captain_id
details.form.item_id = _info.item_id
details.form.id = _info.id
details.chooseInstallList = []
for (let i = 0; i < details.itemArr.length; i++) {
const _value = details.itemArr[i]
if (_value.id !== details.form.item_id) continue
details.form.item_name = _value.label
details.installItemList = _value.user
break
}
for (let i = 0; i < details.installItemList.length; i++) {
const _value = details.installItemList[i]
if (!_info.work_user_ids.includes(_value.id)) continue
details.chooseInstallList.push(_value)
}
console.log('_info :>> ', _info);
} catch (err) {
console.log('err :>> ', err)
//TODO handle the exception
} finally {
option.pageLoading = false
}
}
/** 获取项目组 */
const initItem = async () => {
const res = await getCommonGetItemData({})
const { code, data } = res
if (code !== 200) return
details.itemArr = data || []
}
/** 获取下属 */
const initItemData = async () => {
// const res = await getCneterSubordinates({})
// const { code, data } = res
// if (code !== 200) return
// details.installItemList = data || []
// details.searchText = ''
// handleSearch()
}
initPage()
/** picker切换时执行 -- 时间 */
const bindChangeByTime = function (e) {
details.value = e.detail.value
}
/** 选择项目组 */
const handleChooseWork = (key : 'work_user_captain' | 'item') => {
const _value = details.form[key + '_id']
console.log('_value :>> ', _value);
details.pickerArr = details[key + 'Arr']
console.log('details.pickerArr :>> ', details.pickerArr);
details.value = [0]
if (_value) {
for (let i = 0; i < details.pickerArr.length; i++) {
const item = details.pickerArr[i]
if (item.value !== _value) continue
details.value = [i]
break
}
}
details.visible = true
console.log('details.value :>> ', details.value);
myDrawerByTime.value.setDetails({
showPopUp: true,
title: '选择项目组',
async success() {
try {
const _value = details.pickerArr[details.value[0]]
if (details.form[key + '_id'] === _value.value) return
details.chooseInstallList = []
details.form[key + '_id'] = _value.value
details.form[key + '_name'] = _value.label
details.form.work_user_captain = ''
details.form.work_user_captain_id = ''
details.installItemList = _value.user || []
for (let i = 0; i < _value.user.length; i++) {
const item = _value.user[i]
if (!item.role.includes(2)) continue
details.form.work_user_captain = item.name
details.form.work_user_captain_id = item.id
break
}
} catch (err) {
console.log('err :>> ', err);
//TODO handle the exception
} finally {
myDrawerByTime.value.details.showPopUp = false
await nextTick()
details.visible = false
}
},
async close() {
myDrawerByTime.value.details.showPopUp = false
await nextTick()
details.visible = false
}
})
}
/** 开启选择弹窗 -- 安装人员 */
const handleChooseInstall = () => {
handleSearch()
myDrawerByChooseItem.value.setDetails({
showPopUp: true,
height: '50vh',
isShowButton: false
})
}
/** 选择安装人员 */
const handleChooseInstallItem = (item) => {
for (let i = 0; i < details.chooseInstallList.length; i++) {
const _value = details.chooseInstallList[i]
if (_value.id === item.id) return details.chooseInstallList.splice(i, 1)
}
details.chooseInstallList.push(item)
console.log('details.chooseInstallList :>> ', details.chooseInstallList);
}
/** 搜索 */
const handleSearch = () => {
if (!details.searchText) details.renderInstallList = details.installItemList
const _reg = new RegExp('^' + details.searchText)
const _arr = []
for (let i = 0; i < details.installItemList.length; i++) {
const _value = details.installItemList[i]
if (!_reg.test(_value.name)) continue
_arr.push(_value)
}
details.renderInstallList = _arr
}
/** 返回 */
const handleback = () => {
uni.navigateBack()
}
/** 驳回 */
const handleTurnDown = () => {
console.log('tip.value :>> ', tip.value);
tip.value.setdetails({
title: '提示',
isshow: true,
content: '确认驳回',
async success() {
try {
option.pageLoading = true
const submitData = {
result: 2,
install_sales_id: details.form.install_sales_id,
}
const res = await postInstallSalesDesignate(submitData)
const { code, data } = res
if (code !== 200) return
handleback()
} catch (err) {
console.log('err :>> ', err);
//TODO handle the exception
} finally {
tip.value.setisshow(false)
option.pageLoading = false
}
}
})
}
/** 指派 */
const handleAssignATask = () => {
if (!details.form.estimated_finish_time) return utils.handleToast('请选择时间')
if (!details.form.item_id) return utils.handleToast('请选择项目组')
if (!details.form.work_user_captain_id) return utils.handleToast('该项目组无工长,请切换项目组或维护')
if (details.chooseInstallList.length === 0) return utils.handleToast('请选择安装人员')
console.log('details.form :>> ', details.form);
tip.value.setdetails({
title: '提示',
isshow: true,
content: '确认指派',
async success() {
try {
option.pageLoading = true
const submitData = {
result: 1,
// install_sales_id: details.form.install_sales_id,
item_id: details.form.item_id,
estimated_finish_time: details.form.estimated_finish_time,
work_user_captain: details.form.work_user_captain,
work_user_captain_id: details.form.work_user_captain_id,
work_users: details.chooseInstallList.map(val => val.name).join(','),
work_user_ids: details.chooseInstallList.map(val => val.id)
}
details.form.id && (submitData.id = details.form.id)
details.pageType === 'install' ? (submitData.install_id = details.form.install_id) : (submitData.install_sales_id = details.form.install_sales_id)
const res = details.pageType === 'install' ? await postInstallDesignate(submitData) : await postInstallSalesDesignate(submitData)
const { code, data } = res
if (code !== 200) return
handleback()
} catch (err) {
console.log('err :>> ', err);
//TODO handle the exception
} finally {
tip.value.setisshow(false)
option.pageLoading = false
}
}
})
}
</script>
<style lang="scss" scoped>
@import url('@/utils/style/common.scss');
.main {
position: relative;
background-color: #fff;
display: flex;
flex-direction: column;
// 安装人员
.input_box {
flex: 1;
text-align: right;
margin-left: 20upx;
border-radius: 5upx;
.input_box_item {
background: #f5f5f5;
margin-bottom: 10upx;
}
.remove {
border-left: 4upx solid;
color: var(--errColor);
margin-left: 20upx;
padding: 0 10upx;
}
}
}
.header_search {
padding: 20upx;
height: 80upx;
.header_search_btn {
// height: 60upx;
color: #fff;
height: 100%;
padding: 0 60upx;
background: var(--subjectColor);
border-radius: 10upx;
}
.input {
background-color: #f5f5f5;
margin-right: 20upx;
height: 100%;
font-size: 1rem;
}
}
// 安装人员
.search_list {
.search_list_item {
width: 40%;
padding: 20upx;
background: #f5f5f5;
box-sizing: border-box;
position: relative;
margin: 0 20upx;
margin-bottom: 30upx;
transition: all 0.3s;
border-radius: 10upx;
word-break: break-all;
$width: 20upx;
$borderWidth: 4upx;
$activeSizing: calc(100% + 20upx);
&::before {
position: absolute;
content: '';
width: $width;
height: $width;
border-top: $borderWidth solid;
border-left: $borderWidth solid;
border-color: var(--subjectColor);
top: -10upx;
left: -10upx;
transition: all 0.3s;
box-sizing: border-box;
// border-top-left-radius: 10upx;
}
&::after {
position: absolute;
content: '';
width: $width;
height: $width;
border-bottom: $borderWidth solid;
border-right: $borderWidth solid;
border-color: var(--subjectColor);
bottom: -10upx;
right: -10upx;
transition: all 0.3s;
box-sizing: border-box;
// border-bottom-right-radius: 10upx;
}
&.active {
background: var(--subjectColor);
color: #fff;
&::before {
width: $activeSizing;
height: $activeSizing;
border-radius: 10upx;
}
&::after {
width: $activeSizing;
height: $activeSizing;
border-radius: 10upx;
}
}
}
}
// picker样式
.picker-view {
height: 40vh;
.item {
text-align: center;
line-height: 40px;
}
}
.btn_conatiner {
.mr40 {
margin-right: 40upx;
}
padding-bottom: 60upx;
}
.btn {
padding: 20upx 60upx;
border-radius: 10upx;
background-color: #f5f5f5;
color: #000;
&.errBtn {
color: #fff;
background-color: var(--errColor);
}
&.subBtn {
color: #fff;
background: var(--subjectColor);
}
}
</style>