@@ -1,5 +1,5 @@ | |||
# title | |||
VITE_APP_TITLE = '汤山林场巡检管理平台' | |||
VITE_APP_TITLE = '林场巡检管理平台' | |||
# 端口号 | |||
VITE_PORT = 3050 |
@@ -40,7 +40,7 @@ | |||
"eslint-plugin-vue": "^8.5.0", | |||
"esno": "^0.13.0", | |||
"fs-extra": "^10.0.1", | |||
"naive-ui": "^2.27.0", | |||
"naive-ui": "^2.34.3", | |||
"sass": "^1.49.11", | |||
"unocss": "^0.16.4", | |||
"unplugin-vue-components": "^0.18.5", |
@@ -63,3 +63,16 @@ export function handleOrder(data) { | |||
data | |||
}) | |||
} | |||
/** | |||
* @description: 问题详情 | |||
* @param {*} data | |||
* @return {*} | |||
*/ | |||
export function orderDetail(params) { | |||
return request({ | |||
url: '/workOrder/question/detail', | |||
method: 'GET', | |||
params | |||
}) | |||
} |
@@ -40,3 +40,18 @@ export function reportDownload(id) { | |||
}) | |||
} | |||
/** | |||
* @description: 下载报告 | |||
* @param {*} id | |||
* @return {*} | |||
*/ | |||
export function reportHandleDownload(id) { | |||
return request({ | |||
url: `report/${id}/handleWord`, | |||
method: 'GET', | |||
headers: { | |||
responseType: 'arraybuffer' | |||
} | |||
}) | |||
} | |||
@@ -1,11 +1,3 @@ | |||
/* | |||
* @Author: whyafterme | |||
* @Date: 2022-06-16 11:39:28 | |||
* @LastEditTime: 2022-06-29 13:51:40 | |||
* @LastEditors: whyafterme | |||
* @Description: | |||
* @FilePath: \web\src\components\IconBoard\tools\icon.js | |||
*/ | |||
import { | |||
EditOutlined, LogoutOutlined | |||
} from '@vicons/antd' |
@@ -2,7 +2,7 @@ const setting = { | |||
/* 布局模式 vertical / horizontal */ | |||
/* layoutMode: 'vertical', */ | |||
/* 导航模式 sidebar / header */ | |||
title: '汤山林场巡检管理平台', | |||
title: '林场巡检管理平台', | |||
menuMode: 'sidebar', | |||
headerSetting: { | |||
isReload: true |
@@ -33,7 +33,7 @@ export const ORDER_STATUS = [ | |||
{ label: '待生成', value: 0 }, | |||
{ label: '已生成', value: 1 }, | |||
{ label: '待分配', value: 5 }, | |||
{ label: '处理中', value: 10 }, | |||
{ label: '已分配', value: 10 }, | |||
{ label: '已完成', value: 15 } | |||
] | |||
@@ -43,6 +43,11 @@ export const ORDER_STATUS2 = [ | |||
{ label: '已完成', value: 15 } | |||
] | |||
export const ORDER_STATUS3 = [ | |||
{ label: '处理中', value: 10 }, | |||
{ label: '已完成', value: 15 } | |||
] | |||
export const QUES_STATUS = [ | |||
{ label: '待处理', value: 0 }, | |||
{ label: '已处理', value: 1 } |
@@ -3,7 +3,7 @@ | |||
<div class="login__container"> | |||
<div class="container__left" /> | |||
<div class="container__right"> | |||
<div class="right__title">汤山林场巡检管理平台</div> | |||
<div class="right__title">林场巡检管理平台</div> | |||
<div class="right__form"> | |||
<n-form | |||
ref="formRef" |
@@ -73,7 +73,7 @@ | |||
<script> | |||
import { QUESTION_TYPE } from '@/utils/dictionary.js' | |||
import { getReportDetail, reportDownload } from '@/api/report/index.js' | |||
import { getReportDetail, reportHandleDownload } from '@/api/report/index.js' | |||
import { defineComponent, reactive, toRefs, computed, watch } from 'vue' | |||
export default defineComponent({ | |||
@@ -145,7 +145,7 @@ export default defineComponent({ | |||
}) | |||
function handleDownload() { | |||
reportDownload(props.data.id) | |||
reportHandleDownload(props.data.id) | |||
.then((res) => { | |||
const download = document.createElement('iframe') | |||
download.src = res.data |
@@ -42,6 +42,7 @@ export default { | |||
const loadDataTable = async(res) => { | |||
const _params = { | |||
...unref(data.searchParams), | |||
handleFlag: 1, | |||
...res | |||
} | |||
return await getOrderList(_params) |
@@ -1,5 +1,5 @@ | |||
import { reactive } from 'vue' | |||
import { ORDER_STATUS2 } from '@/utils/dictionary.js' | |||
import { ORDER_STATUS3 } from '@/utils/dictionary.js' | |||
export const search = reactive([ | |||
{ | |||
@@ -10,12 +10,12 @@ export const search = reactive([ | |||
} | |||
}, | |||
{ | |||
label: '工单分配状态', | |||
label: '工单状态', | |||
key: 'status', | |||
type: 'select', | |||
props: { | |||
placeholder: '请选择工单分配状态', | |||
options: ORDER_STATUS2 | |||
placeholder: '请选择工单状态', | |||
options: ORDER_STATUS3 | |||
} | |||
}, | |||
{ |
@@ -1,4 +1,4 @@ | |||
import { ORDER_STATUS } from '@/utils/dictionary.js' | |||
import { ORDER_STATUS3 } from '@/utils/dictionary.js' | |||
import TableTags from '@/components/DataTable/tools/Tags.vue' | |||
import TableAction from '@/components/DataTable/tools/Action.vue' | |||
import { h, ref, reactive } from 'vue' | |||
@@ -8,8 +8,7 @@ const tableRef = ref() | |||
const searchParams = ref() | |||
function handleSearch(params) { | |||
console.log(params) | |||
searchParams.value = { ...params } | |||
searchParams.value = { ...params, handleFlag: 1 } | |||
if (params?.time?.length) { | |||
searchParams.value = { | |||
...params, | |||
@@ -76,7 +75,7 @@ const data = reactive({ | |||
render(row) { | |||
return h(TableTags, { | |||
data: row.status, | |||
filters: ORDER_STATUS | |||
filters: ORDER_STATUS3 | |||
}) | |||
} | |||
}, |
@@ -0,0 +1,122 @@ | |||
<template> | |||
<Modal | |||
:options="getModalOptions" | |||
:on-positive-click="handleConfirm" | |||
:on-negative-click="handleClose" | |||
:on-close="handleClose" | |||
> | |||
<template #Context> | |||
<n-form | |||
ref="formRef" | |||
:model="questionForm" | |||
:rules="questionRules" | |||
:label-width="120" | |||
label-placement="left" | |||
require-mark-placement="left" | |||
:disabled="disabled" | |||
> | |||
<template v-for="(item,index) in getFormOptions" :key="index"> | |||
<n-form-item :label="item.label" :path="item.key"> | |||
<n-input v-if="item.type === 'input'" v-model:value="questionForm[item.key]" v-bind="item.props" /> | |||
<n-select v-if="item.type === 'select'" v-model:value="questionForm[item.key]" v-bind="item.props" /> | |||
<n-image v-if="item.type === 'image'" v-model:src="questionForm[item.key]" v-bind="item.props" /> | |||
<UploadOss v-if="item.type === 'oss'" :limit="5" :default-list="questionForm[item.file]" /> | |||
</n-form-item> | |||
</template> | |||
</n-form> | |||
</template> | |||
</Modal> | |||
</template> | |||
<script> | |||
import { form } from '../tools/quesForm.js' | |||
import { defineComponent, ref, reactive, computed, toRefs } from 'vue' | |||
import Modal from '@/components/Modal/index.vue' | |||
import UploadOss from '@/components/UploadOss/index.vue' | |||
export default defineComponent({ | |||
name: 'UserModal', | |||
components: { Modal, UploadOss }, | |||
props: { | |||
visible: { | |||
type: Boolean, | |||
default: false | |||
}, | |||
type: { | |||
type: String, | |||
default: 'preview' | |||
}, | |||
orderId: { | |||
type: Number, | |||
default: null | |||
}, | |||
data: { | |||
type: Object, | |||
default: () => null | |||
} | |||
}, | |||
emits: { | |||
'update:visible': null, | |||
'reload': null | |||
}, | |||
setup(props, { emit }) { | |||
const MODAL_TYPE = { | |||
'preview': '问题详情', | |||
'update': '处理问题' | |||
} | |||
const { questionForm, questionRules } = form | |||
const formRef = ref() | |||
const data = reactive({ | |||
questionForm: { | |||
...questionForm, | |||
imageStatus: '', | |||
...props.data, | |||
position: `${props.data.lng},${props.data.lat}` | |||
}, | |||
questionRules: { | |||
...questionRules | |||
}, | |||
disabled: props.type === 'preview' | |||
}) | |||
const getModalOptions = computed(() => { | |||
return { | |||
show: props.visible, | |||
title: MODAL_TYPE[props.type], | |||
negativeText: '取消', | |||
positiveText: '确认' | |||
} | |||
}) | |||
const getFormOptions = computed(() => { | |||
if (props.type === 'preview' && props.data.status === 0) { | |||
const list = form.formItem.filter((item) => !item.mode) | |||
return { | |||
...list | |||
} | |||
} else { | |||
return { | |||
...form.formItem | |||
} | |||
} | |||
}) | |||
function handleConfirm() { | |||
handleClose() | |||
} | |||
/* 关闭弹窗 */ | |||
const handleClose = () => { | |||
emit('update:visible', false) | |||
} | |||
return { | |||
...toRefs(data), | |||
formRef, | |||
getModalOptions, | |||
getFormOptions, | |||
handleConfirm, | |||
handleClose | |||
} | |||
} | |||
}) | |||
</script> | |||
<style scoped lang='scss'> | |||
</style> |
@@ -19,6 +19,8 @@ | |||
<MapDrawer v-model:visible="mapDrawer" :data="rowData" /> | |||
<QuestionModal v-if="modalShow" v-model:visible="modalShow" :type="modalType" :data="rowData" /> | |||
<PreviewModal v-if="previewModal" v-model:visible="previewModal" :data="pageData" :select-row="rowData" /> | |||
</template> | |||
@@ -30,13 +32,14 @@ import HeadSearch from '@/components/Search/index.vue' | |||
import DataTable from '@/components/DataTable/index.vue' | |||
import MapDrawer from './components/MapDrawer.vue' | |||
import PreviewModal from './components/PreviewModal.vue' | |||
import QuestionModal from './components/QuestionModal.vue' | |||
import { reactive, ref, unref, toRefs, onUnmounted } from 'vue' | |||
import { getQuestionList } from '@/api/task/index.js' | |||
import { generateOrder } from '@/api/order/index.js' | |||
export default { | |||
name: 'QuestionList', | |||
components: { HeadSearch, DataTable, MapDrawer, PreviewModal }, | |||
components: { HeadSearch, DataTable, MapDrawer, PreviewModal, QuestionModal }, | |||
setup() { | |||
const data = reactive({ | |||
search, |
@@ -0,0 +1,21 @@ | |||
import { ref, reactive } from 'vue' | |||
import { QUESTION_TYPE_ALL, QUES_STATUS } from '@/utils/dictionary.js' | |||
export const form = reactive({ | |||
questionForm: { | |||
handlerResult: '' | |||
}, | |||
questionRules: { | |||
imageStatus: { required: true, message: '请选择图片', trigger: ['blur', 'change'] } | |||
}, | |||
formItem: [ | |||
{ type: 'select', key: 'type', label: '问题类型', props: { options: QUESTION_TYPE_ALL, disabled: true }}, | |||
{ type: 'input', key: 'position', label: '问题经纬度', props: { disabled: true }}, | |||
{ type: 'input', key: 'createTime', label: '问题发现时间', props: { disabled: true }}, | |||
{ type: 'image', key: 'fileMarkerUrl', label: '问题图片', props: { width: 100 }}, | |||
{ type: 'select', key: 'status', label: '问题状态', props: { options: QUES_STATUS, disabled: true }}, | |||
{ type: 'oss', refIndex: 0, key: 'imageStatus', file: 'handlerImage', label: '封面', mode: true }, | |||
{ type: 'input', key: 'handlerResult', label: '描述', props: { type: 'textarea', maxlength: 255 }, mode: true } | |||
] | |||
}) | |||
@@ -2,6 +2,7 @@ import { QUESTION_TYPE, ORDER_STATUS, QUES_STATUS } from '@/utils/dictionary.js' | |||
import TableImage from '@/components/DataTable/tools/Image.vue' | |||
import TableTags from '@/components/DataTable/tools/Tags.vue' | |||
import TableAction from '@/components/DataTable/tools/Action.vue' | |||
import { orderDetail } from '@/api/order/index.js' | |||
import { h, ref, reactive } from 'vue' | |||
/* 注册table */ | |||
@@ -21,9 +22,22 @@ function handleSearch(params) { | |||
tableRef.value.reFetch({ searchParams }) | |||
} | |||
function handlePreview(row) { | |||
data.orderModal = true | |||
data.rowData = row | |||
async function handlePreview(row) { | |||
if (row.handleStatus === 0) { | |||
data.rowData = { | |||
...row, | |||
status: 0 | |||
} | |||
} | |||
if (row.handleStatus === 1) { | |||
const res = await orderDetail({ questionId: row.id }) | |||
data.rowData = { | |||
...row, | |||
handlerImage: res.data.questionHandle.handlerImage, | |||
handlerResult: res.data.questionHandle.handlerResult | |||
} | |||
} | |||
data.modalShow = true | |||
} | |||
/* 位置 */ | |||
@@ -41,7 +55,7 @@ const data = reactive({ | |||
tableRef, | |||
searchParams, | |||
rowData: {}, | |||
orderModal: false, | |||
modalShow: false, | |||
mapDrawer: false, | |||
previewModal: false, | |||
handleSearch, |
@@ -59,8 +59,8 @@ | |||
<n-gi><span>{{ item.questionDesc ? item.questionDesc : '-' }}</span></n-gi> | |||
<n-gi><span>问题图片</span></n-gi> | |||
<n-gi><n-image :src="item.fileMarkerUrl" /></n-gi> | |||
<n-gi v-if="type === 'result' && item.questionHandleList"><span>处理结果</span></n-gi> | |||
<n-gi v-if="type === 'result' && item.questionHandleList"><n-image v-for="(cItem,cIndex) in item.questionHandleList" :key="cIndex" :src="cItem.handlerImage" /></n-gi> | |||
<n-gi v-if="type === 'result' && item.questionHandleList.length"><span>处理结果</span></n-gi> | |||
<n-gi v-if="type === 'result' && item.questionHandleList.length"><n-image v-for="(cItem,cIndex) in item.questionHandleList" :key="cIndex" :src="cItem.handlerImage" /></n-gi> | |||
</n-grid> | |||
</div> | |||
<!-- </n-image-group> --> | |||
@@ -75,7 +75,7 @@ | |||
<script> | |||
import { QUESTION_TYPE } from '@/utils/dictionary.js' | |||
import { getReportDetail, reportDownload } from '@/api/report/index.js' | |||
import { getReportDetail, reportDownload, reportHandleDownload } from '@/api/report/index.js' | |||
import { defineComponent, reactive, toRefs, computed, watch } from 'vue' | |||
export default defineComponent({ | |||
@@ -151,16 +151,30 @@ export default defineComponent({ | |||
}) | |||
function handleDownload() { | |||
reportDownload(props.data.id) | |||
.then((res) => { | |||
const download = document.createElement('iframe') | |||
download.src = res.data | |||
download.style.display = 'none' | |||
document.body.appendChild(download) | |||
setTimeout(() => { | |||
document.body.removeChild(download) | |||
}, 300) | |||
}) | |||
if (props.type === 'inspection') { | |||
reportDownload(props.data.id) | |||
.then((res) => { | |||
const download = document.createElement('iframe') | |||
download.src = res.data | |||
download.style.display = 'none' | |||
document.body.appendChild(download) | |||
setTimeout(() => { | |||
document.body.removeChild(download) | |||
}, 300) | |||
}) | |||
} | |||
if (props.type === 'result') { | |||
reportHandleDownload(props.data.id) | |||
.then((res) => { | |||
const download = document.createElement('iframe') | |||
download.src = res.data | |||
download.style.display = 'none' | |||
document.body.appendChild(download) | |||
setTimeout(() => { | |||
document.body.removeChild(download) | |||
}, 300) | |||
}) | |||
} | |||
} | |||
return { |