fix bug
This commit is contained in:
@@ -48,6 +48,11 @@ export default {
|
||||
|
||||
&__card {
|
||||
width: 100%;
|
||||
background: none;
|
||||
|
||||
> .el-card__body {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<div class="cron-config-area">
|
||||
<!-- 每天模式 -->
|
||||
<div v-if="cronMode === 'daily'" class="mode-content">
|
||||
<el-form :model="dailyConfig" label-width="100px" size="default">
|
||||
<el-form :model="dailyConfig" label-width="auto" size="default">
|
||||
<el-form-item label="执行时间">
|
||||
<el-time-picker
|
||||
v-model="dailyConfig.time"
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
<!-- 每周模式 -->
|
||||
<div v-if="cronMode === 'weekly'" class="mode-content">
|
||||
<el-form :model="weeklyConfig" label-width="100px" size="default">
|
||||
<el-form :model="weeklyConfig" label-width="auto" size="default">
|
||||
<el-form-item label="星期选择">
|
||||
<el-checkbox-group v-model="weeklyConfig.weekDays" @change="generateCron" :disabled="disabled">
|
||||
<el-checkbox label="1">周一</el-checkbox>
|
||||
@@ -58,7 +58,7 @@
|
||||
|
||||
<!-- 每月模式 -->
|
||||
<div v-if="cronMode === 'monthly'" class="mode-content">
|
||||
<el-form :model="monthlyConfig" label-width="100px" size="default">
|
||||
<el-form :model="monthlyConfig" label-width="auto" size="default">
|
||||
<el-form-item label="日期选择">
|
||||
<el-select
|
||||
v-model="monthlyConfig.days"
|
||||
@@ -93,7 +93,7 @@
|
||||
|
||||
<!-- 自定义模式 -->
|
||||
<div v-if="cronMode === 'custom'" class="mode-content">
|
||||
<el-form :model="customConfig" label-width="100px" size="default">
|
||||
<el-form :model="customConfig" label-width="auto" size="default">
|
||||
<el-form-item label="秒">
|
||||
<el-input
|
||||
v-model="customConfig.second"
|
||||
@@ -161,7 +161,7 @@
|
||||
</div>
|
||||
|
||||
<div class="cron-result">
|
||||
<el-form label-width="120px">
|
||||
<el-form label-width="auto">
|
||||
<el-form-item label="Cron 表达式">
|
||||
<el-input
|
||||
v-model="cronExpression"
|
||||
@@ -567,7 +567,7 @@ export default {
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #409eff;
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
|
||||
:deep(.el-checkbox) {
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
<el-pagination
|
||||
background
|
||||
:current-page="page.currentPage"
|
||||
:page-size="page.pageSize"
|
||||
:page-size="pageSize"
|
||||
:page-sizes="pageSizes"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="0"
|
||||
:total="total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
@@ -27,9 +27,15 @@ export default {
|
||||
isEmptyTotal() {
|
||||
return Number(this.page.total || 0) === 0;
|
||||
},
|
||||
pageSize() {
|
||||
return this.page.pageSize || 10;
|
||||
},
|
||||
pageSizes() {
|
||||
return this.page.pageSizes || [10, 20, 50, 100];
|
||||
},
|
||||
total() {
|
||||
return Number(this.page.total || 0);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleSizeChange(pageSize) {
|
||||
@@ -51,7 +57,6 @@ export default {
|
||||
.empty-pagination {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 20px 0 0;
|
||||
background: #fff;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
:show-close="false"
|
||||
width="20%"
|
||||
>
|
||||
<el-form :model="form" ref="form" label-width="80px">
|
||||
<el-form :model="form" ref="form" label-width="auto">
|
||||
<el-form-item v-if="tenantMode" label="租户编号">
|
||||
<el-input v-model="form.tenantId" placeholder="请输入租户编号"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
364
src/components/vehicle-attachment-upload/main.vue
Normal file
364
src/components/vehicle-attachment-upload/main.vue
Normal file
@@ -0,0 +1,364 @@
|
||||
<template>
|
||||
<div class="vehicle-attachment-upload">
|
||||
<el-upload
|
||||
:action="uploadAction"
|
||||
name="file"
|
||||
:headers="uploadHeaders"
|
||||
:file-list="fileList"
|
||||
:accept="acceptText"
|
||||
:multiple="multiple"
|
||||
:limit="limit"
|
||||
:disabled="readonly"
|
||||
:show-file-list="true"
|
||||
:on-success="handleSuccess"
|
||||
:on-error="handleError"
|
||||
:on-remove="handleRemove"
|
||||
:on-preview="handlePreview"
|
||||
:before-upload="beforeUpload"
|
||||
>
|
||||
<el-button v-if="!readonly" type="primary" plain :icon="buttonIcon">
|
||||
{{ buttonText }}
|
||||
</el-button>
|
||||
<template #tip>
|
||||
<div v-if="showTip && tipText && !readonly" class="el-upload__tip">
|
||||
{{ tipText }}
|
||||
</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
<span v-if="readonly && fileList.length === 0" class="vehicle-attachment-upload__empty">
|
||||
-
|
||||
</span>
|
||||
|
||||
<el-dialog
|
||||
v-model="previewVisible"
|
||||
:title="previewFile.name || '附件预览'"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
width="90%"
|
||||
top="4vh"
|
||||
class="vehicle-attachment-upload__viewer-dialog"
|
||||
>
|
||||
<open-file-viewer
|
||||
v-if="previewVisible && previewSource"
|
||||
:file="previewSource"
|
||||
:file-name="previewFile.name"
|
||||
:mime-type="previewFile.mimeType"
|
||||
width="100%"
|
||||
height="72vh"
|
||||
fit="contain"
|
||||
theme="auto"
|
||||
locale="zh-CN"
|
||||
:toolbar="viewerToolbar"
|
||||
:plugins="viewerPlugins"
|
||||
@unsupported="handleUnsupported"
|
||||
@error="handleViewerError"
|
||||
/>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OpenFileViewer } from '@open-file-viewer/vue';
|
||||
import {
|
||||
fallbackPlugin,
|
||||
imagePlugin,
|
||||
officePlugin,
|
||||
pdfPlugin,
|
||||
textPlugin,
|
||||
} from '@open-file-viewer/core';
|
||||
import '@open-file-viewer/core/style.css';
|
||||
import pdfWorkerSrc from 'pdfjs-dist/build/pdf.worker.mjs?url';
|
||||
import { baseUrl } from '@/config/env';
|
||||
import website from '@/config/website';
|
||||
import { getToken } from '@/utils/auth';
|
||||
|
||||
const MIME_MAP = {
|
||||
jpg: 'image/jpeg',
|
||||
jpeg: 'image/jpeg',
|
||||
png: 'image/png',
|
||||
gif: 'image/gif',
|
||||
bmp: 'image/bmp',
|
||||
webp: 'image/webp',
|
||||
pdf: 'application/pdf',
|
||||
doc: 'application/msword',
|
||||
docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
xls: 'application/vnd.ms-excel',
|
||||
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
ppt: 'application/vnd.ms-powerpoint',
|
||||
pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||
txt: 'text/plain',
|
||||
};
|
||||
|
||||
const viewerPlugins = [
|
||||
imagePlugin(),
|
||||
pdfPlugin({
|
||||
workerSrc: pdfWorkerSrc,
|
||||
useFetchData: true,
|
||||
}),
|
||||
officePlugin({
|
||||
pdf: {
|
||||
workerSrc: pdfWorkerSrc,
|
||||
useFetchData: true,
|
||||
},
|
||||
}),
|
||||
textPlugin(),
|
||||
fallbackPlugin(),
|
||||
];
|
||||
|
||||
export default {
|
||||
name: 'VehicleAttachmentUpload',
|
||||
components: {
|
||||
OpenFileViewer,
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
type: [Array, String, Object],
|
||||
default: () => [],
|
||||
},
|
||||
action: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
accept: {
|
||||
type: [String, Array],
|
||||
default: '',
|
||||
},
|
||||
fileTypes: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
limit: {
|
||||
type: Number,
|
||||
default: 20,
|
||||
},
|
||||
maxSize: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
buttonText: {
|
||||
type: String,
|
||||
default: '上传附件',
|
||||
},
|
||||
buttonIcon: {
|
||||
type: String,
|
||||
default: 'el-icon-upload',
|
||||
},
|
||||
tip: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
showTip: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
emits: ['update:modelValue', 'change', 'success'],
|
||||
data() {
|
||||
return {
|
||||
fileList: [],
|
||||
previewVisible: false,
|
||||
previewFile: {},
|
||||
previewSource: '',
|
||||
viewerToolbar: {
|
||||
download: true,
|
||||
fullscreen: true,
|
||||
print: true,
|
||||
rotate: true,
|
||||
zoom: true,
|
||||
},
|
||||
viewerPlugins,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
uploadAction() {
|
||||
return this.action || `${baseUrl}/blade-resource/oss/endpoint/put-file`;
|
||||
},
|
||||
uploadHeaders() {
|
||||
return {
|
||||
[website.tokenHeader]: getToken(),
|
||||
};
|
||||
},
|
||||
acceptedList() {
|
||||
const types = this.fileTypes.length ? this.fileTypes : this.accept;
|
||||
if (Array.isArray(types)) {
|
||||
return types.map(item => String(item).trim()).filter(Boolean);
|
||||
}
|
||||
return String(types || '')
|
||||
.split(',')
|
||||
.map(item => item.trim())
|
||||
.filter(Boolean);
|
||||
},
|
||||
acceptText() {
|
||||
return this.acceptedList.join(',');
|
||||
},
|
||||
tipText() {
|
||||
if (this.tip) return this.tip;
|
||||
const typeText = this.acceptText || '所有类型';
|
||||
const sizeText = this.maxSize > 0 ? `,单文件不超过 ${this.maxSize}MB` : '';
|
||||
return `支持上传 ${typeText}${sizeText}`;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
modelValue: {
|
||||
handler(value) {
|
||||
this.fileList = this.toUploadList(value);
|
||||
},
|
||||
immediate: true,
|
||||
deep: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
toUploadList(value) {
|
||||
const list = this.parseValue(value);
|
||||
return list.map((item, index) => {
|
||||
const url = this.getFileUrl(item);
|
||||
return {
|
||||
...item,
|
||||
uid: item.uid || `${url || item.name || 'file'}-${index}`,
|
||||
name: item.name || this.getFileName(url) || '附件',
|
||||
url,
|
||||
status: 'success',
|
||||
};
|
||||
});
|
||||
},
|
||||
parseValue(value) {
|
||||
if (!value) return [];
|
||||
if (Array.isArray(value)) return value.filter(Boolean);
|
||||
if (typeof value === 'object') return [value];
|
||||
try {
|
||||
const list = JSON.parse(value);
|
||||
return Array.isArray(list) ? list : [];
|
||||
} catch (error) {
|
||||
return String(value)
|
||||
.split(',')
|
||||
.map(item => item.trim())
|
||||
.filter(Boolean)
|
||||
.map(item => ({
|
||||
name: this.getFileName(item),
|
||||
url: item,
|
||||
}));
|
||||
}
|
||||
},
|
||||
getFileUrl(file) {
|
||||
return file.url || file.link || file.src || file.domain || '';
|
||||
},
|
||||
getFileName(url) {
|
||||
if (!url) return '';
|
||||
const path = String(url).split('?')[0];
|
||||
return decodeURIComponent(path.substring(path.lastIndexOf('/') + 1));
|
||||
},
|
||||
getExtension(file) {
|
||||
const name = String(file.name || this.getFileUrl(file) || '').split('?')[0];
|
||||
const index = name.lastIndexOf('.');
|
||||
return index >= 0 ? name.substring(index + 1).toLowerCase() : '';
|
||||
},
|
||||
beforeUpload(file) {
|
||||
if (!this.validFileType(file)) {
|
||||
this.$message.warning('文件类型不符合上传要求');
|
||||
return false;
|
||||
}
|
||||
if (this.maxSize > 0 && file.size / 1024 / 1024 > this.maxSize) {
|
||||
this.$message.warning(`单文件大小不能超过 ${this.maxSize}MB`);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
validFileType(file) {
|
||||
if (!this.acceptedList.length) return true;
|
||||
const fileName = String(file.name || '').toLowerCase();
|
||||
const mimeType = String(file.type || '').toLowerCase();
|
||||
return this.acceptedList.some(type => {
|
||||
const value = String(type).toLowerCase();
|
||||
if (value === '*/*') return true;
|
||||
if (value.startsWith('.')) return fileName.endsWith(value);
|
||||
if (value.endsWith('/*')) return mimeType.startsWith(value.slice(0, -1));
|
||||
if (value.includes('/')) return mimeType === value;
|
||||
return fileName.endsWith(`.${value}`);
|
||||
});
|
||||
},
|
||||
handleSuccess(response, file, files) {
|
||||
if (!response || response.success === false || (response.code && response.code !== 200)) {
|
||||
this.$message.error((response && response.msg) || '上传失败');
|
||||
return;
|
||||
}
|
||||
this.emitUploadFiles(this.multiple ? files : [file]);
|
||||
this.$emit('success', this.normalizeUploadFile(file));
|
||||
this.$message.success('上传成功');
|
||||
},
|
||||
handleError() {
|
||||
this.$message.error('上传失败');
|
||||
},
|
||||
handleRemove(file, files) {
|
||||
if (this.readonly) return false;
|
||||
this.emitUploadFiles(files);
|
||||
return true;
|
||||
},
|
||||
emitUploadFiles(files) {
|
||||
const list = files
|
||||
.filter(file => file.status === 'success' || this.getFileUrl(file))
|
||||
.map(this.normalizeUploadFile)
|
||||
.filter(item => item.url);
|
||||
this.$emit('update:modelValue', list);
|
||||
this.$emit('change', list);
|
||||
},
|
||||
normalizeUploadFile(file) {
|
||||
const data = (file.response && file.response.data) || file.data || file;
|
||||
const url = data.link || data.url || data.domain || file.url || '';
|
||||
const name = data.name || data.originalName || file.name || this.getFileName(url) || '附件';
|
||||
const extension = this.getExtension({ name, url });
|
||||
return {
|
||||
...data,
|
||||
uid: file.uid || data.uid,
|
||||
name,
|
||||
url,
|
||||
link: data.link || url,
|
||||
size: data.size || data.attachSize || file.size || '',
|
||||
extension,
|
||||
mimeType: data.mimeType || data.contentType || file.raw?.type || MIME_MAP[extension] || '',
|
||||
};
|
||||
},
|
||||
handlePreview(file) {
|
||||
const previewFile = this.normalizeUploadFile(file);
|
||||
if (!previewFile.url) {
|
||||
this.$message.warning('附件地址为空,无法预览');
|
||||
return;
|
||||
}
|
||||
this.previewFile = previewFile;
|
||||
this.previewSource = previewFile.url;
|
||||
this.previewVisible = true;
|
||||
},
|
||||
handleUnsupported() {
|
||||
this.$message.warning('当前文件暂不支持在线预览');
|
||||
},
|
||||
handleViewerError() {
|
||||
this.$message.error('附件预览失败');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.vehicle-attachment-upload {
|
||||
width: 100%;
|
||||
|
||||
:deep(.el-upload-list__item-name) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&__empty {
|
||||
color: #909399;
|
||||
}
|
||||
}
|
||||
|
||||
:global(.vehicle-attachment-upload__viewer-dialog .el-dialog__body) {
|
||||
padding: 12px 16px 16px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user