@@ -0,0 +1,306 @@ | |||
<template> | |||
<div class="oss-filed"> | |||
<n-upload | |||
action="#" | |||
:max="limit" | |||
:file-list="data.fileList" | |||
:default-upload="false" | |||
:show-remove-button="remBtn" | |||
:list-type="fileType == 'img' ? 'image-card' : 'text'" | |||
@change="handleChange" | |||
@before-upload="beforeUpload" | |||
> | |||
<n-button v-if="fileType != 'img'"> | |||
<n-icon> | |||
<FileOutlined /> | |||
</n-icon> | |||
{{ btnName }} | |||
</n-button> | |||
<div v-if="fileType == 'img'" class="oss-upload-text" /> | |||
</n-upload> | |||
</div> | |||
</template> | |||
<script setup name="UploadOss"> | |||
import OSS from 'ali-oss' | |||
import { getOssAuth } from '@/api/common/upload.js' | |||
import { ref, reactive, watch, onMounted, toRefs } from 'vue' | |||
import { FileOutlined } from '@vicons/antd' | |||
const props = defineProps({ | |||
limit: { | |||
type: Number, | |||
default: 1 | |||
}, | |||
defaultList: { | |||
type: String, | |||
default: '' | |||
}, | |||
fileType: { | |||
type: String, | |||
default: 'img' | |||
}, | |||
btnName: { | |||
type: String, | |||
default: '选择文件' | |||
}, | |||
remBtn: { | |||
type: Boolean, | |||
default: false | |||
}, | |||
keyName: { | |||
type: String, | |||
default: 'src' | |||
} | |||
}) | |||
const emit = defineEmits(['uploadStatus']) | |||
const client = ref(null) // 上传实例 | |||
const data = reactive({ | |||
...props, | |||
client: null, | |||
fileList: [], | |||
hasUploadInfo: {} | |||
}) | |||
onMounted(() => { | |||
if (props.defaultList) { | |||
const list = props.defaultList.split(',') | |||
data.fileList = list.map((item) => { | |||
const objectName = item.split('/').slice(3).join('/') | |||
const obj = { | |||
name: objectName, | |||
id: objectName, | |||
// type: 'image/png', | |||
url: item, | |||
objectName: objectName, | |||
status: 'finished' | |||
} | |||
data.hasUploadInfo[obj.id] = { | |||
id: objectName, | |||
objectName: objectName | |||
} | |||
return obj | |||
}) | |||
emit('uploadStatus', 'upload') | |||
} else { | |||
data.fileList = [] | |||
} | |||
}) | |||
/* 监听默认文件列表 */ | |||
watch(() => props.defaultList, (value) => { | |||
if (value.length) { | |||
const list = value.split(',') | |||
const fileList = list.map((item) => { | |||
const objectName = item.split('/').slice(3).join('/') | |||
const obj = { | |||
name: objectName, | |||
id: objectName, | |||
type: 'image/png', | |||
url: item, | |||
objectName: objectName | |||
} | |||
data.hasUploadInfo[obj.id] = { | |||
id: objectName, | |||
objectName: objectName | |||
} | |||
return obj | |||
}) | |||
data.fileList = fileList | |||
emit('uploadStatus', 'upload') | |||
} else { | |||
data.fileList = [] | |||
// emit('uploadStatus', 'hasFile') | |||
} | |||
}) | |||
/** | |||
* @description: 上传前的判断文件类型 | |||
* @param {*} file 当前选择的文件 | |||
* @return {*} | |||
*/ | |||
const beforeUpload = ({ file }) => { | |||
if (props.fileType === 'img') { | |||
if (!file.type.match('image.*')) { | |||
$message.error('请选择正确的图片类型') | |||
/* 中断流程 */ | |||
return false | |||
} | |||
} | |||
if (props.fileType === 'srt') { | |||
const type = ['srt', 'SRT'] | |||
const temp = type.includes(file.name.split('.')[1]) | |||
if (!temp) { | |||
$message.error('请选择SRT类型文件') | |||
/* 中断流程 */ | |||
return false | |||
} | |||
} | |||
if (props.fileType === 'tif') { | |||
const type = ['tif', 'TIF'] | |||
const temp = type.includes(file.name.split('.')[1]) | |||
if (!temp) { | |||
$message.error('请选择tif类型文件') | |||
/* 中断流程 */ | |||
return false | |||
} | |||
} | |||
} | |||
/** | |||
* @description: 文件发生变化时 | |||
* @param {Array} fileList | |||
* @return {*} | |||
*/ | |||
const handleChange = async({ fileList }) => { | |||
data.fileList = fileList.map((item) => { | |||
if (Object.keys(data.hasUploadInfo).includes(item.id)) { | |||
item.objectName = data.hasUploadInfo[item.id].objectName | |||
} | |||
return item | |||
}) | |||
/* 判断是否存在文件 */ | |||
const status = fileList.length ? 'ready' : 'no-file' | |||
emit('uploadStatus', status) | |||
// await startUpload() | |||
} | |||
/** | |||
* @description: 上传文件 | |||
* @return {*} | |||
*/ | |||
const startUpload = () => { | |||
return new Promise((resolve, reject) => { | |||
/* 定义要上传文件 */ | |||
const uploads = [] | |||
/* 从待文件列表中获取没有上传过的文件 */ | |||
const uloadList = data.fileList.filter((item) => { | |||
return !item.url | |||
}) | |||
/* 如果待上传列表长度为0,则返回,否则获取上传鉴权 */ | |||
if (!uloadList.length) { | |||
/* 如果没有要上传的文件信息则返回oss的文件名 */ | |||
/* 不存在objectName的文件表示上传失败 */ | |||
const objectList = data.fileList.map((item) => item.objectName || 'error') | |||
resolve(objectList) | |||
} else { | |||
getOssAuth().then(res => { | |||
/* 初始化oss上传客户端 */ | |||
data.client = new OSS({ | |||
region: 'oss-cn-shanghai', | |||
secure: true, | |||
accessKeyId: res.data.accessKeyId, | |||
accessKeySecret: res.data.accessKeySecret, | |||
stsToken: res.data.securityToken, | |||
bucket: 'ta-tech-image' | |||
}) | |||
/* promise上传要上传的文件 */ | |||
uloadList.forEach(item => { | |||
uploads.push(uploadOss(item)) | |||
}) | |||
Promise.all(uploads).then((response) => { | |||
/* 获取fileList内的文件存储名称 */ | |||
const objectList = data.fileList.map((item) => item.objectName).filter(it => it) | |||
// resolve(objectList) | |||
resolve({ [props.keyName]: objectList.join() }) | |||
emit('uploadStatus', 'success') | |||
}).catch((error) => { | |||
console.log('error', error) | |||
resolve(error) | |||
}) | |||
}) | |||
} | |||
}) | |||
} | |||
/** | |||
* 上传到 OSS | |||
* @param {*} files | |||
*/ | |||
const uploadOss = (files) => { | |||
const file = files.file | |||
return new Promise((resolve, reject) => { | |||
/* 生成随机文件名称 */ | |||
const randomString = Math.random().toString(36).slice(2) | |||
const suffix = /\.[^\.]+/.exec(file.name) | |||
const timestamp = new Date().getTime() | |||
const objectName = `/imagedir/${randomString}_${timestamp}${suffix}` | |||
/* 上传文件至oss */ | |||
data.client.put(objectName, file) | |||
.then((res) => { | |||
const index = data.fileList.findIndex(list => list.id === files.id) | |||
data.fileList[index].url = res.url | |||
data.fileList[index].objectName = objectName | |||
const id = data.fileList[index].id | |||
data.hasUploadInfo[id] = { | |||
id: objectName, | |||
objectName: objectName | |||
} | |||
resolve(objectName) | |||
}) | |||
.catch((err) => { | |||
resolve('error') | |||
console.log(err) | |||
}) | |||
}) | |||
} | |||
defineExpose({ startUpload, ...toRefs(data) }) | |||
</script> | |||
<style lang="scss" scoped> | |||
.oss-filed { | |||
width: 100%; | |||
padding: 10px 20px; | |||
} | |||
.oss-upload-picture-card-wrapper { | |||
min-height: 122px; | |||
padding: 10px 0 0 10px; | |||
} | |||
.oss-upload-text { | |||
// width: 100px; | |||
// height: 100px; | |||
// cursor: pointer; | |||
// border: 1px solid #e1e1e1; | |||
// margin: 10px 0 0 10px; | |||
position: relative; | |||
} | |||
.oss-upload-text::before { | |||
content: ''; | |||
position: absolute; | |||
left: 50%; | |||
top: 50%; | |||
width: 30px; | |||
transform: translate(-50%, -50%); | |||
border-top: 2px solid #e1e1e1; | |||
} | |||
.oss-upload-text::after { | |||
content: ''; | |||
position: absolute; | |||
left: 50%; | |||
top: 50%; | |||
height: 30px; | |||
transform: translate(-50%, -50%); | |||
border-left: 2px solid #e1e1e1; | |||
} | |||
.n-image { | |||
img { | |||
overflow: hidden; | |||
} | |||
} | |||
.oss-upload-type { | |||
text-align: center; | |||
font-size: 14px; | |||
color: rgb(64, 152, 252); | |||
} | |||
</style> |
@@ -6,6 +6,7 @@ | |||
:file-list="fileList" | |||
:default-upload="false" | |||
list-type="image-card" | |||
:show-remove-button="remBtn" | |||
@change="handleChange" | |||
@before-upload="beforeUpload" | |||
> | |||
@@ -28,6 +29,10 @@ export default defineComponent({ | |||
defaultList: { | |||
type: String, | |||
default: '' | |||
}, | |||
remBtn: { | |||
type: Boolean, | |||
default: false | |||
} | |||
}, | |||
emits: ['uploadStatus'], |
@@ -12,24 +12,23 @@ | |||
<n-icon> | |||
<FileOutlined /> | |||
</n-icon> | |||
选择文件 | |||
{{ uploadName }} | |||
</n-button> | |||
</n-upload> | |||
<n-button | |||
<!-- <n-button | |||
v-if="!autoUpload" | |||
type="primary" | |||
:disabled="data.fileList.length === 0" | |||
style="margin-top: 16px" | |||
class="btn" | |||
@click="handleUploadStart" | |||
> | |||
<n-icon> | |||
<UploadOutlined /> | |||
</n-icon> | |||
{{ text }} | |||
</n-button> | |||
开始上传 | |||
</n-button> --> | |||
</template> | |||
@@ -47,9 +46,9 @@ const props = defineProps({ | |||
type: Boolean, | |||
default: false | |||
}, | |||
text: { | |||
uploadName: { | |||
type: String, | |||
default: '开始上传' | |||
default: '选择文件' | |||
} | |||
}) | |||
const emit = defineEmits(['uploadStatus']) | |||
@@ -77,18 +76,18 @@ const data = reactive({ | |||
* @return {*} | |||
*/ | |||
const beforeUpload = ({ file }) => { | |||
// if (!file.type.match('video.*')) { | |||
// $message.error('请选择正确的视频') | |||
// return false | |||
// } else { | |||
const hasSelect = data.fileList.some((item) => item.name === file.name) | |||
if (!hasSelect) { | |||
data.uploadFile.push(file.file) | |||
} else { | |||
$message.error('您已选择过该文件') | |||
if (!file.type.match('video.*')) { | |||
$message.error('请选择正确的视频') | |||
return false | |||
} else { | |||
const hasSelect = data.fileList.some((item) => item.name === file.name) | |||
if (!hasSelect) { | |||
data.uploadFile.push(file.file) | |||
} else { | |||
$message.error('您已选择过该文件') | |||
return false | |||
} | |||
} | |||
// } | |||
} | |||
/** | |||
@@ -127,11 +126,11 @@ const createUploader = () => { | |||
}, | |||
// 开始上传 | |||
onUploadstarted: function(uploadInfo) { | |||
console.log('uploader', uploader) | |||
if (uploadInfo.videoId) { | |||
// 如果uploadInfo.videoId存在,调用刷新视频上传凭证接口 | |||
refreshAuth(uploadInfo.videoId).then(res => { | |||
uploader.setUploadAuthAndAddress(uploadInfo, res.data.uploadAuth, res.data.uploadAddress, res.data.videoId) | |||
data.videoId = res.data.videoId | |||
}) | |||
} else { | |||
const params = { | |||
@@ -140,6 +139,7 @@ const createUploader = () => { | |||
} | |||
getAuth(params).then(res => { | |||
uploader.setUploadAuthAndAddress(uploadInfo, res.data.uploadAuth, res.data.uploadAddress, res.data.videoId) | |||
data.videoId = res.data.videoId | |||
}) | |||
} | |||
}, | |||
@@ -148,15 +148,14 @@ const createUploader = () => { | |||
onUploadSucceed: function(uploadInfo) { | |||
const fileName = uploadInfo.file.name | |||
data.fileList.forEach((item) => { | |||
console.log(item) | |||
if (item.name === fileName) { | |||
data.readyFile[item.uid].url = uploadInfo.object | |||
data.readyFile[item.uid].url = '/' + uploadInfo.object | |||
} | |||
}) | |||
}, | |||
// 文件上传失败 | |||
onUploadFailed: function(uploadInfo, code, message) { | |||
console.log('onUploadFailed: file:' + uploadInfo.file.name + ',code:' + code + ', message:' + message) | |||
// console.log('onUploadFailed: file:' + uploadInfo.file.name + ',code:' + code + ', message:' + message) | |||
}, | |||
// 取消文件上传 | |||
@@ -188,7 +187,7 @@ const createUploader = () => { | |||
// 全部文件上传结束 | |||
onUploadEnd: function(uploadInfo) { | |||
// console.log('onUploadEnd: uploaded all the files', uploadInfo) | |||
emit('uploadStatus', { status: 'success', list: data.readyFile }) | |||
emit('uploadStatus', { status: 'success', list: data.readyFile, videoIds: data.videoId }) | |||
} | |||
}) | |||
return uploader | |||
@@ -214,7 +213,6 @@ const handleUploadReady = () => { | |||
if (props.autoUpload) { // 判断是否自动上传 | |||
handleUploadStart() | |||
} | |||
// handleUploadStart() | |||
} | |||
/** | |||
@@ -228,6 +226,9 @@ const handleUploadStart = () => { | |||
emit('uploadStatus', { status: 'uploading', list: data.readyFile }) | |||
} | |||
} | |||
defineExpose({ data }) | |||
</script> | |||
<style lang="scss" scoped> | |||
@@ -241,9 +242,9 @@ const handleUploadStart = () => { | |||
} | |||
.btn { | |||
width: 120px; | |||
margin-left: calc(50% - 60px); | |||
margin-top: 10px; | |||
margin-bottom: 30px; | |||
} | |||
width: 120px; | |||
margin-left: calc(50% - 60px); | |||
margin-top: 10px; | |||
margin-bottom: 30px; | |||
} | |||
</style> |
@@ -85,14 +85,14 @@ export const TASK_STATUS = [ | |||
export const PHOTOGRAPHY_WAY = [ | |||
{ | |||
label: '普通巡检', | |||
value: '1' | |||
value: 1 | |||
}, | |||
{ | |||
label: '正射影像', | |||
value: '2' | |||
value: 2 | |||
}, | |||
{ | |||
label: '倾斜摄影', | |||
value: '3' | |||
value: 3 | |||
} | |||
] |
@@ -78,7 +78,7 @@ export default { | |||
emphasis: { | |||
focus: 'series' | |||
}, | |||
name: '', | |||
name: '任务数', | |||
smooth: true, // 平滑曲线 | |||
showSymbol: true, // 节点 | |||
symbolSize: 6, | |||
@@ -87,7 +87,12 @@ export default { | |||
width: 3 | |||
}, | |||
itemStyle: { | |||
color: 'rgba(32,204,255, 0.8)' | |||
color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [ | |||
{ offset: 0, color: 'rgba(32,204,255, 0.8)' }, | |||
{ offset: 0.5, color: 'rgba(32,204,255, 0.8)' }, | |||
{ offset: 0.7, color: 'rgba(32,204,255, 0.8)' }, | |||
{ offset: 1, color: '#483D8B' } | |||
]) | |||
}, | |||
areaStyle: { | |||
normal: { | |||
@@ -96,9 +101,13 @@ export default { | |||
offset: 0, | |||
color: 'rgba(32,204,255, 0.8)' | |||
}, | |||
{ | |||
offset: 0.5, | |||
color: 'rgba(32,204,255, 0.4)' | |||
}, | |||
{ | |||
offset: 1, | |||
color: 'rgba(60,212,191, 0.1)' | |||
color: 'rgba(60,212,191, 0.05)' | |||
} | |||
]) | |||
} | |||
@@ -199,7 +208,7 @@ export default { | |||
} | |||
}], | |||
series: [{ | |||
barWidth: 22, | |||
barWidth: 12, | |||
type: 'bar', | |||
emphasis: { | |||
focus: 'series' |
@@ -15,7 +15,12 @@ | |||
require-mark-placement="left" | |||
> | |||
<n-form-item label="横幅图片" path="cover"> | |||
<UploadOss ref="ossRefs" :default-list="initUpload" @upload-status="handleUploadStatus" /> | |||
<UploadOss | |||
ref="ossRefs" | |||
:rem-btn="type !== 'preview'" | |||
:default-list="initUpload" | |||
@upload-status="handleUploadStatus" | |||
/> | |||
</n-form-item> | |||
<!-- <n-form-item label="排序" path="sort"> | |||
<n-input-number v-model:value="form.sort" clearable /> | |||
@@ -26,9 +31,10 @@ | |||
</template> | |||
<script> | |||
import { defineComponent, ref, reactive, computed, toRefs, watch } from 'vue' | |||
import { defineComponent, ref, reactive, computed, toRefs, watch, getCurrentInstance } from 'vue' | |||
import Modal from '@/components/Modal/index.vue' | |||
import UploadOss from '@/components/UploadOss/index.vue' | |||
// import UploadOss from '@/components/UploadOss/index.vue' | |||
import UploadOss from '@/components/UploadOss/fileOss.vue' | |||
import { bannerCreate, bannerUpdate } from '@/api/system/banner.js' | |||
export default defineComponent({ | |||
name: 'BannerModal', | |||
@@ -73,7 +79,7 @@ export default defineComponent({ | |||
} else { | |||
data.initUpload = '' | |||
} | |||
}) | |||
}, { immediate: true }) | |||
const getModalOptions = computed(() => { | |||
return { | |||
@@ -91,54 +97,35 @@ export default defineComponent({ | |||
const formRef = ref() | |||
const ossRefs = ref() | |||
function handleConfirm() { | |||
if (props.type !== 'preview') { | |||
formRef.value?.validate((errors) => { | |||
if (!errors) { | |||
const uploads = ossRefs.value.map((item, index) => { | |||
return item.startUpload() | |||
}) | |||
Promise.all(uploads) | |||
.then(response => { | |||
const isError = response.map((item) => { | |||
return item.includes('error') | |||
}) | |||
if (!isError.includes(true)) { | |||
const imageStr = response.join() | |||
const params = { | |||
...data.form, | |||
cover: imageStr[0] | |||
} | |||
if (params.id) { | |||
/* 编辑 */ | |||
bannerUpdate(params) | |||
.then(res => { | |||
if (res.code === 0) { | |||
emit('reload') | |||
handleClose() | |||
} | |||
}) | |||
} else { | |||
/* 新增 */ | |||
bannerCreate(params) | |||
.then(res => { | |||
if (res.code === 0) { | |||
emit('reload') | |||
handleClose() | |||
} | |||
}) | |||
} | |||
} else { | |||
$message.error('图片上传失败,请稍后重试') | |||
formRef.value.validate().then(() => { | |||
ossRefs.value.startUpload().then(res => { | |||
const params = { | |||
...data.form, | |||
cover: res[0] | |||
} | |||
if (params.id) { | |||
/* 编辑 */ | |||
bannerUpdate(params) | |||
.then(({ code }) => { | |||
if (code === 0) { | |||
emit('reload') | |||
handleClose() | |||
} | |||
}) | |||
handleClose() | |||
} else { | |||
$message.error('请完善必填信息') | |||
/* 新增 */ | |||
bannerCreate(params) | |||
.then(({ code }) => { | |||
if (code === 0) { | |||
emit('reload') | |||
handleClose() | |||
} | |||
}) | |||
} | |||
}) | |||
} else { | |||
handleClose() | |||
} | |||
}).catch(e => { | |||
console.log('e:', e) | |||
}) | |||
} | |||
/* 关闭弹窗 */ | |||
@@ -151,7 +138,9 @@ export default defineComponent({ | |||
getModalOptions, | |||
handleUploadStatus, | |||
handleConfirm, | |||
handleClose | |||
handleClose, | |||
formRef, | |||
ossRefs | |||
} | |||
} | |||
}) |
@@ -50,6 +50,7 @@ const data = reactive({ | |||
{ | |||
title: '序号', | |||
key: 'key', | |||
width: 180, | |||
render: (_, index) => { | |||
return `${index + 1}` | |||
}, | |||
@@ -62,9 +63,10 @@ const data = reactive({ | |||
render(row) { | |||
return h(TableImage, { | |||
images: { | |||
width: 36, | |||
height: 36, | |||
width: 119, | |||
height: 51, | |||
src: row.cover | |||
// previewDisabled: true // 禁止点击预览 | |||
} | |||
}) | |||
} | |||
@@ -73,18 +75,18 @@ const data = reactive({ | |||
title: '上传人', | |||
key: 'updateUser', | |||
align: 'center', | |||
width: 160 | |||
width: 200 | |||
}, | |||
{ | |||
title: '上传时间', | |||
key: 'updateTime', | |||
key: 'createTime', | |||
align: 'center', | |||
width: 160 | |||
width: 220 | |||
}, | |||
{ | |||
title: '操作', | |||
align: 'center', | |||
width: 150, | |||
width: 220, | |||
fixed: 'right', | |||
render(row) { | |||
return h(TableAction, { |
@@ -40,7 +40,7 @@ | |||
<div v-if="current !== 1" class="cont"> | |||
<n-descriptions label-placement="left" label-align="right" :column="4" title="飞行信息"> | |||
<template v-for="(it, i) in flyInfo" :key="i + it.label"> | |||
<n-descriptions-item v-if="current !== it?.current" :label="it.label"> | |||
<n-descriptions-item v-if="!it?.current || current >= it?.current" :label="it.label"> | |||
{{ it.value }} | |||
</n-descriptions-item> | |||
</template> | |||
@@ -49,7 +49,7 @@ | |||
<!-- 设备/影响基本信息 - 飞手接单: 管理员 --> | |||
<div v-if="current == 2 && isAdmin" class="cont"> | |||
<n-descriptions label-placement="left" label-align="right" :column="4" title="设备/影响基本信息"> | |||
<n-descriptions label-placement="left" label-align="right" :column="4" title="设备/影像基本信息"> | |||
<template v-for="(it, i) in equipmentInfo" :key="i + it.label"> | |||
<n-descriptions-item v-if="it?.isLive !== data.isLive" :label="it.label"> | |||
{{ it.value }} | |||
@@ -80,7 +80,7 @@ | |||
<!-- 设备/影响基本信息 - 已接单 --> | |||
<div v-if="current === 3" class="cont"> | |||
<n-descriptions label-placement="left" label-align="right" :column="4" title="设备/影响基本信息"> | |||
<n-descriptions label-placement="left" label-align="right" :column="4" title="设备/影像基本信息"> | |||
<template v-for="(it, i) in executionInfo" :key="i + it.label"> | |||
<n-descriptions-item :label="it.label"> | |||
{{ it.value }} | |||
@@ -92,7 +92,7 @@ | |||
<!-- 设备/影响基本信息 - 执行中: 管理员 --> | |||
<div v-if="current === 4" class="cont"> | |||
<n-descriptions label-placement="left" label-align="right" :column="4" title="设备/影响基本信息"> | |||
<n-descriptions label-placement="left" label-align="right" :column="4" title="设备/影像基本信息"> | |||
<template v-for="(it, i) in executionInfo" :key="i + it.label"> | |||
<n-descriptions-item :label="it.label"> | |||
{{ it.value }} | |||
@@ -105,19 +105,30 @@ | |||
<div v-if="current === 5" class="cont"> | |||
<div class="title">飞行文件</div> | |||
<UploadVod @upload-status="vodStatus" /> | |||
<UploadVod v-if="data.photographyWay === 1" ref="videoRefs" :auto-upload="true" :upload-name="'选择【视频】'" :limit="1" @upload-status="vodStatusVideo" /> | |||
<fileOss v-if="data.photographyWay === 1" ref="srtRefs" :file-type="'srt'" :key-name="'srtUrl'" :btn-name="'选择【轨迹】'" :limit="1" :default-list="data.srtUrl" @upload-status="vodStatusSRT" /> | |||
<fileOss v-if="data.photographyWay === 2" ref="ortRefs" :file-type="'tif'" :key-name="'orthoUrl'" :btn-name="'选择【正射影像】'" :limit="9" :default-list="data.orthoUrl" @upload-status="vodStatusZS" /> | |||
<fileOss v-if="data.photographyWay === 3" ref="inclinedRefs" :file-type="'tif'" :key-name="'inclinedUrl'" :btn-name="'选择【倾斜影像】'" :limit="9" :default-list="data.inclinedUrl" @upload-status="vodStatusQX" /> | |||
<n-button v-if="isAdmin" type="primary" class="btn" :loading="loading" @click="submitFile"> | |||
<n-icon> | |||
<UploadOutlined /> | |||
</n-icon> | |||
开始上传 | |||
</n-button> | |||
</div> | |||
</template> | |||
<script setup name="DrawComp"> | |||
import { ref, defineProps, reactive, defineEmits } from 'vue' | |||
import { ref, defineProps, reactive, defineEmits, watchEffect } from 'vue' | |||
import { TASK_STATUS } from '@/utils/dictionary' | |||
import { distributionPilot, pilotOrder, pilotStart, pilotEnd, uploadFlightUrl } from '@/api/task/index.js' | |||
import { form, getPilotList, getEquipment, getEquipmentMount, getCloudMount } from '../tools/drawForm' | |||
import { basic, fly, equipment, execution } from '../hook/index' | |||
import UploadVod from '@/components/UploadVod/index.vue' | |||
import fileOss from '@/components/UploadOss/fileOss.vue' | |||
import { UploadOutlined } from '@vicons/antd' | |||
getPilotList() // 获取飞手列表 | |||
getEquipment() // 无人机列表 | |||
@@ -132,6 +143,7 @@ const props = defineProps({ | |||
}) | |||
const { detail: { data }} = props // 传来的详情数据 | |||
form.userForm = data | |||
const current = data.pilotStatus / 5 // 当前状态 | |||
@@ -146,6 +158,20 @@ const flyInfo = fly(data) // 飞行信息 | |||
const equipmentInfo = equipment(data) // 设备/影响基本信息 | |||
const executionInfo = execution(data) // 执行中信息 | |||
const videoUrl = ref('') // 视频文件 | |||
const videoId = ref('') // 视频文件 | |||
const srtUrl = ref('') // srt文件 | |||
// const inclinedUrl = ref('') // 倾斜摄影 | |||
// const orthoUrl = ref('') // 正射影像 | |||
const videoRefs = ref(null) // video refs | |||
const srtRefs = ref(null) // srt refs | |||
const ortRefs = ref(null) // 正射 refs | |||
const inclinedRefs = ref(null) // 倾斜 refs | |||
const loading = ref(false) | |||
const isBtn = ref(false) | |||
const emit = defineEmits(['close']) | |||
// 分配飞手 | |||
@@ -204,23 +230,83 @@ const endFly = () => { | |||
}) | |||
} | |||
// 视频上传 | |||
const vodStatus = ({ status, list }) => { | |||
console.log(status, list) | |||
const videoUrl = [] | |||
// 上传 - 视频 | |||
const vodStatusVideo = ({ status, list, videoIds }) => { | |||
console.log(status, list, videoIds) | |||
const arr = [] | |||
for (var key in list) { | |||
videoUrl.push(list[key].url) | |||
arr.push(list[key].url) | |||
} | |||
const videoList = videoUrl.join(',') | |||
console.log('videoList', videoList) | |||
return | |||
if (status === 'success') { | |||
// 视频上传 | |||
uploadFlightUrl({ | |||
id: data.id, | |||
videoUrl: videoList | |||
}).then(({ code }) => { | |||
console.log(code) | |||
videoUrl.value = arr.join(',') | |||
videoId.value = videoIds | |||
} | |||
} | |||
// 上传 - SRT | |||
const vodStatusSRT = async(status) => { | |||
srtUrl.value = status | |||
console.log('srtUrl: ---------------', srtUrl.value, status) | |||
// const res = await srtRefs.value.startUpload() | |||
// console.log('status: ', status) | |||
// console.log(res) | |||
// if (status === 'success' && res.includes('error')) { | |||
// $message.error('上传失败,请稍后重试') | |||
// } else if (status === 'success') { | |||
// srtUrl.value = res.join() | |||
// } | |||
} | |||
// watchEffect(() => [videoUrl, srtUrl], ([videoVal], [srtVal]) => { | |||
// console.log('watchEffect-videoVal:', videoVal) | |||
// console.log('watchEffect-srtVal:', srtVal) | |||
// if (videoUrl.value === 'success' && srtVal === 'success') { | |||
// console.log('watchEffect-success all') | |||
// isBtn.value = true | |||
// } | |||
// }) | |||
// 上传 | |||
const submitFile = () => { | |||
if (data.photographyWay === 1) { // 视频 和 srt | |||
// videoRefs.value.data.uploader.startUpload() | |||
srtRefs.value?.startUpload().then(res => { | |||
console.log('res:', res) | |||
if (!res.includes('error')) { | |||
uploadFlightUrl({ | |||
id: data.id, | |||
videoUrl: videoUrl.value, | |||
videoId: videoId.value, | |||
...res | |||
}).then(({ code }) => { | |||
if (code === 0) { | |||
emit('close') | |||
} | |||
}) | |||
} | |||
}) | |||
} else { | |||
loading.value = true | |||
const queue = [] | |||
// queue.push(videoRefs.value?.data.uploader.startUpload()) | |||
// queue.push(srtRefs.value?.startUpload()) | |||
queue.push(inclinedRefs.value?.startUpload()) | |||
queue.push(ortRefs.value?.startUpload()) | |||
Promise.all(queue).then(res => { | |||
loading.value = false | |||
const params = {} | |||
res.filter(it => it).forEach(el => { | |||
Object.keys(el).map(dom => { | |||
params[dom] = el[dom] | |||
}) | |||
}) | |||
uploadFlightUrl({ | |||
id: data.id, | |||
...params | |||
}).then(({ code }) => { | |||
if (code === 0) { | |||
emit('close') | |||
} | |||
}) | |||
}) | |||
} | |||
} | |||
@@ -246,8 +332,8 @@ const vodStatus = ({ status, list }) => { | |||
} | |||
.btn { | |||
width: 70px; | |||
margin-left: calc(50% - 30px); | |||
width: 110px; | |||
margin-left: calc(50% - 55px); | |||
margin-top: 10px; | |||
margin-bottom: 30px; | |||
} |
@@ -29,7 +29,7 @@ | |||
<n-input v-if="item.type === 'inputStart'" v-model:value="userForm[item.key]" disabled v-bind="item.props"> | |||
<template #suffix> | |||
<n-button quaternary type="info" @click="showStart = true">去标记 | |||
<n-button quaternary type="info" style="padding-right: 0;" @click="showStart = true">去标记 | |||
<n-icon size="20" color="rgba(42, 130, 228, 1)"> | |||
<LocationSharp /> | |||
</n-icon> | |||
@@ -39,7 +39,7 @@ | |||
<n-input v-if="item.type === 'inputEnd'" v-model:value="userForm[item.key]" disabled v-bind="item.props"> | |||
<template #suffix> | |||
<n-button quaternary type="info" @click="showEnd = true">去标记 | |||
<n-button quaternary type="info" style="padding-right: 0;" @click="showEnd = true">去标记 | |||
<n-icon size="20" color="rgba(42, 130, 228, 1)"> | |||
<LocationSharp /> | |||
</n-icon> | |||
@@ -54,6 +54,7 @@ | |||
type="datetime" | |||
value-format="yyyy-MM-dd HH:mm:ss" | |||
:is-date-disabled="isDateDisabled" | |||
style="width: 100%;" | |||
/> | |||
<n-radio-group v-if="item.type === 'radio'" v-model:value="userForm[item.key]" :name="item.key"> | |||
<n-space> | |||
@@ -314,12 +315,4 @@ export default defineComponent({ | |||
height: 155px; | |||
margin-bottom: 10px; | |||
} | |||
:deep(.n-form-item-blank) { | |||
width: 100%; | |||
} | |||
:deep(.__button-1jezgko-hlmmi) { | |||
padding-right: 0; | |||
} | |||
</style> |
@@ -1,6 +1,6 @@ | |||
import { customRef } from 'vue' | |||
const status = ['任务待分配', '任务已分配', '飞手已接单', '任务飞行中', '任务已完成'] // 摄影方式 | |||
const status = ['任务待分配', '任务已分配', '飞手已接单', '任务飞行中', '任务已完成'] | |||
export default function(data) { | |||
const list = [ |
@@ -26,7 +26,7 @@ | |||
<!-- 详情 - 抽屉 --> | |||
<n-drawer v-model:show="showDraw" :width="'calc(100vw - 210px)'" :placement="'right'" resizable> | |||
<n-drawer-content closable> | |||
<draw-comp :detail="detail" @close="showDraw = false" /> | |||
<draw-comp :detail="detail" @close="showDraw = false;handleSearch()" /> | |||
</n-drawer-content> | |||
</n-drawer> | |||
@@ -50,13 +50,19 @@ export default { | |||
...toRefs(table), | |||
...toRefs(search) | |||
}) | |||
const status = ['任务待分配', '任务已分配', '飞手已接单', '任务飞行中', '任务已完成'] | |||
const loadDataTable = async(res) => { | |||
const _params = { | |||
...unref(data.searchParams), | |||
...res | |||
} | |||
return await getTaskList(_params) | |||
const temp = await getTaskList(_params) | |||
// 将状态由数字改成文字 | |||
temp.data.records = temp.data.records.map(it => ({ | |||
...it, | |||
statusName: status[(it.status / 5) - 1] | |||
})) | |||
return temp | |||
} | |||
// 新增 | |||
function handleModal() { |
@@ -1,9 +1,5 @@ | |||
import { h, ref, reactive } from 'vue' | |||
import TableImage from '@/components/DataTable/tools/Image.vue' | |||
import TableTags from '@/components/DataTable/tools/Tags.vue' | |||
import TableSwitch from '@/components/DataTable/tools/Switch.vue' | |||
import TableAction from '@/components/DataTable/tools/Action.vue' | |||
import { resetPassword, deleteUser, setUserStatus } from '@/api/system/user/index.js' | |||
import { getTaskInfo, taskDel } from '@/api/task' | |||
/* 注册table */ | |||
@@ -28,7 +24,6 @@ async function getRowData(row, type) { | |||
data.showDraw = true | |||
} | |||
/** | |||
* @description: 编辑 | |||
* @return {*} | |||
@@ -90,17 +85,17 @@ const data = reactive({ | |||
{ | |||
title: '巡逻地点', | |||
key: 'patrolLocation', | |||
align: 'center', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '任务状态', | |||
key: 'status', | |||
align: 'center', | |||
key: 'statusName', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '飞手姓名', | |||
key: 'flightHandName', | |||
align: 'center', | |||
align: 'center' | |||
}, | |||
{ | |||
title: '操作', | |||
@@ -126,7 +121,10 @@ const data = reactive({ | |||
props: { | |||
type: 'primary', | |||
text: true, | |||
onClick: editHandle.bind(null, row, 'update') | |||
onClick: editHandle.bind(null, row, 'update'), | |||
style: { | |||
display: row.status > 10 ? 'none' : '' | |||
} | |||
}, | |||
auth: 'basic_list' | |||
}, | |||
@@ -140,7 +138,10 @@ const data = reactive({ | |||
}, | |||
ButtonProps: { | |||
text: true, | |||
type: 'primary' | |||
type: 'primary', | |||
style: { | |||
display: row.status > 10 ? 'none' : '' | |||
} | |||
} | |||
} | |||
], |
@@ -54,9 +54,9 @@ export default defineComponent({ | |||
}, | |||
setup(props, { emit }) { | |||
const MODAL_TYPE = { | |||
'create': '新建盒子信息', | |||
'preview': '盒子详情', | |||
'update': '编辑盒子信息' | |||
'create': '新建人员信息', | |||
'preview': '人员详情', | |||
'update': '编辑人员信息' | |||
} | |||
const { userForm, userRules } = form | |||
const formRef = ref() |
@@ -17,11 +17,11 @@ export const form = reactive({ | |||
{ required: true, message: '请输入正确的联系电话', pattern: /^(0|86|17951)?(13[0-9]|15[012356789]|166|17[3678]|18[0-9]|14[57])[0-9]{8}$/, trigger: 'blur' } | |||
], | |||
type: [{ required: true, type: 'number', message: '请选择身份', trigger: 'blur' }], | |||
username: [{ required: true, message: '请输入帐号', trigger: 'blur' }], | |||
password: [{ required: true, message: '请输入初始密码', trigger: 'blur' }] | |||
username: [{ required: true, message: '账号为英文和数字', pattern: /^[a-zA-Z0-9]+$/, trigger: 'blur' }], | |||
password: [{ required: true, message: '密码为6到20位的大小写英文和数字组成的', pattern: /^(?![\d]+$)(?![a-zA-Z]+$)(?![^\da-zA-Z]+$)([^\u4e00-\u9fa5\s]){6,20}$/, trigger: 'blur' }] | |||
}, | |||
formItem: [ | |||
{ type: 'input', key: 'realname', label: '姓名', props: { maxlength: '20', placeholder: '请输入姓名', clearable: true }}, | |||
{ type: 'input', key: 'realname', label: '姓名', props: { maxlength: '5', placeholder: '请输入姓名', clearable: true }}, | |||
{ type: 'input', key: 'mobile', label: '联系电话', props: { maxlength: '20', placeholder: '请输入联系电话', clearable: true }}, | |||
{ type: 'select', key: 'type', label: '身份选择', props: { options: ROLE_TYPE, clearable: true }}, | |||
{ type: 'input', key: 'username', label: '帐号', props: { maxlength: '20', placeholder: '请输入帐号', clearable: true }}, |
@@ -2,10 +2,10 @@ import { reactive } from 'vue' | |||
const data = reactive([ | |||
{ | |||
label: '设备名称', | |||
key: 'name', | |||
label: '人员名称', | |||
key: 'realname', | |||
props: { | |||
placeholder: '请输入设备名称' | |||
placeholder: '请输入人员名称' | |||
} | |||
} | |||
]) |