<template>
|
<div class="add-work" ref="workContainer">
|
<div id="taslMap"></div>
|
<div class="task-form">
|
<van-form>
|
<div class="card">
|
<label class="label">
|
<span>*</span>
|
工单名称
|
</label>
|
<van-field
|
v-model="formParams.eventName"
|
placeholder="请输入"
|
:rules="[{ required: true, message: '请输入工单名称' }]"
|
/>
|
</div>
|
<div class="card">
|
<label class="label">
|
<span>*</span>
|
工单类型
|
</label>
|
<van-field
|
v-model="formParams.type"
|
is-link
|
readonly
|
name="picker"
|
placeholder="请选择"
|
@click="typeShow = true"
|
:rules="[{ required: true, message: '请选择工单类型' }]"
|
/>
|
<van-popup v-model:show="typeShow" destroy-on-close position="bottom">
|
<van-picker :columns="types" :model-value="typeValue" @confirm="onTypeConfirm" @cancel="typeShow = false" />
|
</van-popup>
|
</div>
|
<div class="card">
|
<label class="label">
|
<span>*</span>
|
关联算法
|
</label>
|
<van-field
|
v-model="sfValue"
|
is-link
|
readonly
|
name="picker"
|
placeholder="请选择"
|
@click="sfShow = true"
|
:rules="[{ required: true, message: '请选择关联算法' }]"
|
/>
|
<van-popup v-model:show="sfShow" destroy-on-close position="bottom">
|
<van-picker
|
:columns="taskAlgorithm"
|
:model-value="aiTypeValue"
|
@confirm="onSfConfirm"
|
@cancel="sfShow = false"
|
/>
|
</van-popup>
|
</div>
|
|
<div class="card">
|
<label class="label">
|
<span>*</span>
|
处理部门
|
</label>
|
<van-field
|
v-model="formParams.departmentName"
|
is-link
|
readonly
|
name="picker"
|
placeholder="请选择"
|
@click="departmentShow = true"
|
:rules="[{ required: true, message: '请选择处理部门' }]"
|
/>
|
<van-popup v-model:show="departmentShow" destroy-on-close position="bottom">
|
<van-picker
|
:columns="departments"
|
:model-value="createDeptValue"
|
@confirm="onDepartmentConfirm"
|
@cancel="departmentShow = false"
|
/>
|
</van-popup>
|
</div>
|
<div class="card">
|
<label class="label">
|
<span>*</span>
|
处理人员
|
</label>
|
<van-field
|
v-model="formParams.handlerName"
|
is-link
|
readonly
|
name="picker"
|
placeholder="请选择"
|
@click="processorShow = true"
|
:disabled="!formParams.createDept"
|
:rules="[{ required: true, message: '请选择处理人员' }]"
|
/>
|
<van-popup v-model:show="processorShow" destroy-on-close position="bottom">
|
<van-picker
|
:model-value="updateUserValue"
|
:columns="availableDispatchHandlers"
|
@confirm="onProcessorConfirm"
|
@cancel="processorShow = false"
|
/>
|
</van-popup>
|
</div>
|
<div class="card">
|
<label class="label">
|
<span>*</span>
|
事件位置
|
</label>
|
<div class="addMap">
|
<WorkMap
|
:weatherShow="false"
|
:layerShow="false"
|
:locationShow="false"
|
:createWorkShow="true"
|
@location-selected="handleLocationSelected"
|
:clear-marker="clearMapMarker"
|
></WorkMap>
|
</div>
|
</div>
|
<div class="card">
|
<label class="label">
|
<span>*</span>
|
事件图片
|
<span class="imgdisable">(只能上传jpg、jpeg、png照片且不超过5M)</span>
|
</label>
|
<van-field name="uploader">
|
<template #input>
|
<van-uploader
|
v-model="fileList"
|
:after-read="afterRead"
|
:max-count="1"
|
:max-size="5 * 1024 * 1024"
|
@oversize="onOversize"
|
:before-read="beforeRead"
|
@delete="handleDelete"
|
accept="image/jpeg,image/jpg,image/png"
|
/>
|
</template>
|
</van-field>
|
</div>
|
|
<div class="card">
|
<label class="label">
|
<span>*</span>
|
工单内容
|
</label>
|
<van-field
|
rows="1"
|
autosize
|
type="textarea"
|
show-word-limit
|
maxlength="200"
|
v-model="formParams.content"
|
placeholder="请输入"
|
:rules="[{ required: true, message: '请输入工单内容' }]"
|
/>
|
</div>
|
</van-form>
|
|
<div class="task-btn">
|
<van-button
|
round
|
block
|
type="primary"
|
:loading="loading"
|
loading-text="发布中..."
|
color="#1D6FE9"
|
@click="handleSubmit"
|
>
|
发布
|
</van-button>
|
</div>
|
</div>
|
</div>
|
</template>
|
<script setup>
|
import { getTicketInfo, createTicket } from '/src/api/work/index.js'
|
import WorkMap from '@/appComponents/workMap/index.vue'
|
import _ from 'lodash'
|
import { showToast, showNotify } from 'vant'
|
const clearMapMarker = ref(false)
|
const workContainer = ref(null)
|
const loading = ref(false)
|
const departmentShow = ref(false)
|
const processorShow = ref(false)
|
const selectedDepartment = ref([])
|
const selectedProcessor = ref([])
|
const departments = ref([]) //部门
|
const createDeptValue = ref([]) // 回选值
|
const departmentUsers = ref({})
|
const types = ref([]) //工单类型
|
const typeValue = ref([]) // 工单类型选中值
|
const typeShow = ref(false)
|
const lineName = ref('')
|
const allAlgorithms = ref([])
|
const algorithms = ref([])
|
const formParams = ref({
|
eventName: '',
|
type: '',
|
|
departmentName: '', // 显示部门名称 (text)
|
|
handlerName: '', // 显示处理人名称 (text)
|
content: '',
|
|
longitude: '',
|
latitude: '',
|
address: '',
|
workOrderTypeDictKey: '',
|
aiType: '',
|
updateUser: '',
|
createDept: '', // 存储部门ID (value)
|
|
photos: [],
|
})
|
|
const sfValue = ref('')
|
const sfShow = ref(false)
|
const lineShow = ref(false)
|
|
// 请求算法字典字段
|
const taskAlgorithm = ref([])
|
const aiTypeValue = ref([])
|
|
function onSfConfirm({ selectedValues, selectedOptions }) {
|
aiTypeValue.value = selectedValues
|
sfValue.value = selectedOptions[0].text
|
formParams.value.aiType = selectedOptions[0].value
|
sfShow.value = false
|
}
|
// 处理人,处理部门,工单类型
|
const getTicketInfoData = async () => {
|
const response = await getTicketInfo()
|
const { dept_data, event_type, ai_type, info } = response.data.data
|
allAlgorithms.value = info
|
types.value = Object.entries(event_type).map(([key, value]) => ({
|
text: value,
|
value: key,
|
}))
|
departments.value = dept_data.map(item => ({
|
text: item.dept_name,
|
value: item.id,
|
}))
|
departmentUsers.value = dept_data.reduce((acc, dept) => {
|
acc[dept.id] = dept.user_data || []
|
return acc
|
}, {})
|
}
|
// 处理人
|
const updateUserValue = ref([])
|
const availableDispatchHandlers = computed(() => {
|
if (!formParams.value.createDept) return []
|
const users = departmentUsers.value[formParams.value.createDept]
|
if (!users) return []
|
return users.map(user => ({
|
text: user.name,
|
value: user.id,
|
}))
|
})
|
// 部门确认事件
|
const onDepartmentConfirm = ({ selectedValues, selectedOptions }) => {
|
createDeptValue.value = selectedValues
|
formParams.value.createDept = selectedValues[0]
|
formParams.value.departmentName = selectedOptions[0].text
|
formParams.value.handlerName = ''
|
formParams.value.updateUser = ''
|
departmentShow.value = false
|
}
|
|
// 处理人确认事件
|
const onProcessorConfirm = ({ selectedValues, selectedOptions }) => {
|
updateUserValue.value = selectedValues
|
const selectedOption = selectedOptions[0]
|
if (selectedOption && !selectedOption.disabled) {
|
formParams.value.updateUser = selectedOption.value
|
formParams.value.handlerName = selectedOption.text
|
}
|
|
processorShow.value = false
|
}
|
// 工单类型
|
const onTypeConfirm = ({ selectedValues, selectedOptions }) => {
|
typeValue.value = selectedValues
|
formParams.value.workOrderTypeDictKey = selectedValues[0]
|
formParams.value.type = selectedOptions[0].text
|
sfValue.value = ''
|
formParams.value.aiType = ''
|
typeShow.value = false
|
handleTypeChange(formParams.value.workOrderTypeDictKey)
|
}
|
// 关联算法选择
|
const handleTypeChange = typeValue => {
|
const matchedCategory = allAlgorithms.value.find(category => category.dict_key === typeValue)
|
if (!matchedCategory || !matchedCategory.algorithms || matchedCategory.algorithms.length === 0) {
|
// 无匹配的算法时清空
|
algorithms.value = []
|
return
|
}
|
algorithms.value = matchedCategory.algorithms.map(algo => ({
|
label: algo.dict_value,
|
value: algo.dict_key,
|
dict_key: algo.dict_key,
|
dict_value: algo.dict_value,
|
}))
|
taskAlgorithm.value = algorithms.value.map(item => ({
|
text: item.label,
|
value: item.value,
|
}))
|
}
|
// 图片
|
const fileList = ref([]) // 用于存储上传的文件列表
|
// 文件上传前的校验
|
const beforeRead = file => {
|
const ext = file.name.split('.').pop().toLowerCase()
|
const allowedExts = ['jpg', 'jpeg', 'png']
|
if (!allowedExts.includes(ext)) {
|
showToast('请上传 jpg/jpeg/png 格式图片')
|
return false
|
}
|
return true
|
}
|
// 文件大小超过限制时的回调
|
const onOversize = file => {
|
showToast('文件大小不能超过 5MB')
|
}
|
|
// 文件读取完成后的回调
|
const afterRead = file => {
|
formParams.value.photos = [file.file]
|
console.log('2222', formParams.value.photos)
|
}
|
// 处理图片删除
|
const handleDelete = () => {
|
formParams.value.photos = []
|
console.log('1111', formParams.value.photos)
|
}
|
const handleLocationSelected = location => {
|
formParams.value.latitude = location.latitude
|
formParams.value.longitude = location.longitude
|
formParams.value.address = location.address
|
}
|
const resetFormData = () => {
|
formParams.value = {
|
eventName: '',
|
type: '',
|
departmentName: '',
|
handlerName: '',
|
content: '',
|
longitude: '',
|
latitude: '',
|
address: '',
|
workOrderTypeDictKey: '',
|
aiType: '',
|
updateUser: '',
|
createDept: '',
|
photos: [],
|
}
|
|
typeValue.value = []
|
aiTypeValue.value = []
|
createDeptValue.value = []
|
updateUserValue.value = []
|
sfValue.value = ''
|
|
fileList.value = []
|
|
typeShow.value = false
|
sfShow.value = false
|
departmentShow.value = false
|
processorShow.value = false
|
clearMapMarker.value = true
|
nextTick(() => {
|
clearMapMarker.value = false
|
})
|
}
|
function handleSubmit() {
|
if (!formParams.value.eventName) {
|
showToast('请输入工单名称')
|
return
|
}
|
if (!formParams.value.type) {
|
showToast('请选择工单类型')
|
return
|
}
|
if (!formParams.value.aiType) {
|
showToast('请选择算法')
|
return
|
}
|
if (!formParams.value.departmentName) {
|
showToast('请选择处理部门')
|
return
|
}
|
if (!formParams.value.handlerName) {
|
showToast('请选择处理人')
|
return
|
}
|
if (!formParams.value.photos[0]) {
|
showToast('请选择图片')
|
return
|
}
|
|
if (!formParams.value.longitude || !formParams.value.latitude) {
|
showToast('请选择事件位置')
|
return
|
}
|
if (!formParams.value.content || !formParams.value.content) {
|
showToast('请输入工单内容')
|
return
|
}
|
const submitData = {
|
eventName: formParams.value.eventName,
|
content: formParams.value.content,
|
workType: '1',
|
longitude: formParams.value.longitude,
|
latitude: formParams.value.latitude,
|
address: formParams.value.address,
|
workOrderTypeDictKey: formParams.value.workOrderTypeDictKey,
|
aiType: formParams.value.aiType, // 传数组
|
updateUser: formParams.value.updateUser,
|
createDept: formParams.value.createDept,
|
isDraft: 0,
|
}
|
|
const file = formParams.value.photos[0] || null
|
loading.value = true
|
createTicket(submitData, file)
|
.then(res => {
|
if (res.data.code === 0) {
|
showToast('新建工单成功')
|
resetFormData()
|
loading.value = false
|
|
const transmitData = { data: { type: 'submitSuccess', fun: 'add' } }
|
wx.miniProgram.switchTab({ url: `/pages/work/index?addLog=111` })
|
wx.miniProgram.postMessage(transmitData)
|
uni.postMessage(transmitData)
|
|
workContainer.value.scrollTop = 0
|
}
|
})
|
.finally(() => {
|
loading.value = false
|
})
|
}
|
onMounted(() => {
|
getTicketInfoData()
|
})
|
</script>
|
<style scoped lang="scss">
|
.add-work {
|
width: 100%;
|
height: 100vh;
|
overflow: auto;
|
.task-form {
|
font-family: Source Han Sans CN, Source Han Sans CN;
|
.task-title {
|
height: 32px;
|
line-height: 32px;
|
font-weight: bold;
|
font-size: 16px;
|
color: #222324;
|
padding-left: 12px;
|
}
|
.card {
|
margin: 12px;
|
background: #ffffff;
|
border-radius: 6px 6px 6px 6px;
|
padding-top: 8px;
|
|
.label {
|
padding-left: 12px;
|
color: #222324;
|
font-size: 14px;
|
span {
|
color: red;
|
}
|
}
|
.van-cell {
|
border-radius: 6px 6px 6px 6px;
|
}
|
:deep(.van-field__value) {
|
border-bottom: 1px solid #efefef;
|
}
|
:deep(.van-cell__right-icon) {
|
margin-left: 0px;
|
border-bottom: 1px solid #efefef;
|
}
|
|
.imgdisable {
|
font-family: Source Han Sans CN, Source Han Sans CN;
|
font-weight: 400;
|
font-size: 10px;
|
color: #3a3a3a !important;
|
}
|
}
|
|
.active {
|
background: #1d6fe9;
|
color: white;
|
}
|
.task-btn {
|
text-align: center;
|
margin: 10px auto;
|
margin-bottom: 20px;
|
height: 38px;
|
width: 60%;
|
:deep(.van-button) {
|
height: 38px;
|
line-height: 38px;
|
}
|
}
|
}
|
.addMap {
|
width: 100%;
|
height: 183px;
|
border-radius: 6px 6px 6px 6px;
|
|
:deep() {
|
.page-container {
|
padding: 12px;
|
}
|
}
|
}
|
:deep(.van-field__value) {
|
border-bottom: 1px solid #efefef;
|
}
|
}
|
</style>
|