fix Bug or esLink formatting

This commit is contained in:
Ah jung
2021-07-22 13:47:44 +08:00
parent f6be8f521e
commit 7f81152793
172 changed files with 10553 additions and 9031 deletions

View File

@@ -2,42 +2,48 @@
<div class="w-full">
<div class="upload">
<div class="upload-card">
<!--图片列表-->
<div class="upload-card-item" :style="getCSSProperties" v-for="(item,index) in imgList">
<div
class="upload-card-item"
:style="getCSSProperties"
v-for="(item, index) in imgList"
:key="`img_${index}`"
>
<div class="upload-card-item-info">
<div class="img-box">
<img :src="item"/>
<img :src="item" />
</div>
<div class="img-box-actions">
<n-icon size="18" class="action-icon mx-2" @click="preview(item)">
<EyeOutlined/>
<EyeOutlined />
</n-icon>
<n-icon size="18" class="action-icon mx-2" @click="remove(index)">
<DeleteOutlined/>
<DeleteOutlined />
</n-icon>
</div>
</div>
</div>
<!--上传图片-->
<div class="upload-card-item upload-card-item-select-picture" :style="getCSSProperties"
v-if="imgList.length < maxNumber">
<div
class="upload-card-item upload-card-item-select-picture"
:style="getCSSProperties"
v-if="imgList.length < maxNumber"
>
<n-upload
v-bind="$props"
:file-list-style="{ display:'none'}"
@before-upload="beforeUpload"
@finish="finish"
v-bind="$props"
:file-list-style="{ display: 'none' }"
@before-upload="beforeUpload"
@finish="finish"
>
<div class="flex justify-center flex-col">
<n-icon size="18" class="m-auto">
<PlusOutlined/>
<PlusOutlined />
</n-icon>
<span class="upload-title">上传图片</span>
</div>
</n-upload>
</div>
</div>
</div>
@@ -47,267 +53,254 @@
{{ helpText }}
</n-alert>
</n-space>
</div>
<!--预览图片-->
<n-modal
v-model:show="showModal"
preset="card"
title="预览"
:bordered="false"
:style="{width: '520px'}"
v-model:show="showModal"
preset="card"
title="预览"
:bordered="false"
:style="{ width: '520px' }"
>
<img :src="previewUrl"/>
<img :src="previewUrl" />
</n-modal>
</template>
<script lang="ts">
import { defineComponent, toRefs, reactive, computed } from "vue";
import { EyeOutlined, DeleteOutlined, PlusOutlined } from "@vicons/antd";
import { NUpload } from 'naive-ui'
import { basicProps } from "./props";
import { useMessage, useDialog } from 'naive-ui'
import { ResultEnum } from '@/enums/httpEnum'
import componentSetting from '@/settings/componentSetting'
import { useGlobSetting } from '@/hooks/setting'
import { isString } from '@/utils/is'
import { defineComponent, toRefs, reactive, computed } from 'vue';
import { EyeOutlined, DeleteOutlined, PlusOutlined } from '@vicons/antd';
import { NUpload } from 'naive-ui';
import { basicProps } from './props';
import { useMessage, useDialog } from 'naive-ui';
import { ResultEnum } from '@/enums/httpEnum';
import componentSetting from '@/settings/componentSetting';
import { useGlobSetting } from '@/hooks/setting';
import { isString } from '@/utils/is';
const globSetting = useGlobSetting()
const globSetting = useGlobSetting();
export default defineComponent({
name: 'BasicUpload',
export default defineComponent({
name: 'BasicUpload',
components: { EyeOutlined, DeleteOutlined, PlusOutlined },
props: {
...NUpload.props, // 这里继承原 UI 组件的 props
...basicProps
},
emits: ['uploadChange', 'delete'],
setup(props, { emit }) {
const { value, width, height } = props
components: { EyeOutlined, DeleteOutlined, PlusOutlined },
props: {
...NUpload.props, // 这里继承原 UI 组件的 props
...basicProps,
},
emits: ['uploadChange', 'delete'],
setup(props, { emit }) {
const getCSSProperties = computed(() => {
return {
width: `${props.width}px`,
height: `${props.height}px`,
};
});
const getCSSProperties = computed(() => {
return {
width: `${ width }px`,
height: `${ height }px`,
const message = useMessage();
const dialog = useDialog();
const state = reactive({
showModal: false,
previewUrl: '',
originalImgList: [],
imgList: [],
});
//赋值默认图片显示
if (props.value.length) {
state.imgList = props.value.map((item) => {
return getImgUrl(item);
});
}
})
const message = useMessage()
const dialog = useDialog()
//预览
function preview(url: string) {
state.showModal = true;
state.previewUrl = url;
}
const state = reactive({
showModal: false,
previewUrl: '',
originalImgList: [],
imgList: []
})
//删除
function remove(index: number) {
dialog.info({
title: '提示',
content: '你确定要删除吗?',
positiveText: '确定',
negativeText: '取消',
onPositiveClick: () => {
state.imgList.splice(index, 1);
state.originalImgList.splice(index, 1);
emit('uploadChange', state.originalImgList);
emit('delete', state.originalImgList);
},
onNegativeClick: () => {},
});
}
//赋值默认图片显示
if (value.length) {
state.imgList = value.map(item => {
return getImgUrl(item)
})
}
//组装完整图片地址
function getImgUrl(url: string): string {
const { imgUrl } = globSetting;
return /(^http|https:\/\/)/g.test(url) ? url : `${imgUrl}${url}`;
}
//预览
function preview(url: string) {
state.showModal = true
state.previewUrl = url
}
function checkFileType(fileType: string) {
return componentSetting.upload.fileType.includes(fileType);
}
//删除
function remove(index: number) {
dialog.info({
title: '提示',
content: '你确定要删除吗?',
positiveText: '确定',
negativeText: '取消',
onPositiveClick: () => {
state.imgList.splice(index, 1)
state.originalImgList.splice(index, 1)
emit('uploadChange', state.originalImgList)
emit('delete', state.originalImgList)
},
onNegativeClick: () => {
//上传之前
function beforeUpload({ file }) {
const fileInfo = file.file;
const { maxSize, accept } = props;
const acceptRef = (isString(accept) && accept.split(',')) || [];
// 设置最大值,则判断
if (maxSize && fileInfo.size / 1024 / 1024 >= maxSize) {
message.error(`上传文件最大值不能超过${maxSize}M`);
return false;
}
})
}
//组装完整图片地址
function getImgUrl(url: string) {
const { imgUrl } = globSetting
return (/(^http|https:\/\/)/g).test(url) ? url : `${ imgUrl }${ url }`
}
// 设置类型,则判断
const fileType = componentSetting.upload.fileType;
if (acceptRef.length > 0 && !checkFileType(fileInfo.type)) {
message.error(`只能上传文件类型为${fileType.join(',')}`);
return false;
}
function checkFileType(fileType: string) {
return componentSetting.upload.fileType.includes(fileType)
}
//上传之前
function beforeUpload({ file, fileList }) {
const fileInfo = file.file;
const { maxSize, accept, maxNumber } = props;
const acceptRef = (isString(accept) && accept.split(',')) || [];
// 设置最大值,则判断
if (maxSize && fileInfo.size / 1024 / 1024 >= maxSize) {
message.error(`上传文件最大值不能超过${ maxSize }M`);
return false;
return true;
}
// 设置类型,则判断
const fileType = componentSetting.upload.fileType
if (acceptRef.length > 0 && !checkFileType(fileInfo.type)) {
message.error(`只能上传文件类型为${ fileType.join(',') }`);
return false;
//上传结束
function finish({ event: Event }) {
const res = eval('(' + Event.target.response + ')');
const infoField = componentSetting.upload.apiSetting.infoField;
const { code } = res;
const message = res.msg || res.message || '上传失败';
const result = res[infoField];
//成功
if (code === ResultEnum.SUCCESS) {
let imgUrl = getImgUrl(result.photo);
state.imgList.push(imgUrl);
state.originalImgList.push(result.photo);
emit('uploadChange', state.originalImgList);
} else message.error(message);
}
return true
}
//上传结束
function finish({ event: Event }) {
const res = eval('(' + Event.target.response + ')');
const infoField = componentSetting.upload.apiSetting.infoField
const { code } = res
const message = (res.msg || res.message) || '上传失败'
const result = res[infoField]
//成功
if (code === ResultEnum.SUCCESS) {
let imgUrl: string = getImgUrl(result.photo)
state.imgList.push(imgUrl)
state.originalImgList.push(result.photo)
emit('uploadChange', state.originalImgList)
} else message.error(message)
}
return {
...toRefs(state),
finish,
preview,
remove,
beforeUpload,
getCSSProperties
}
}
})
return {
...toRefs(state),
finish,
preview,
remove,
beforeUpload,
getCSSProperties,
};
},
});
</script>
<style lang="less">
.upload {
width: 100%;
overflow: hidden;
.upload {
width: 100%;
overflow: hidden;
&-card {
width: auto;
height: auto;
display: flex;
flex-wrap: wrap;
align-items: center;
&-item {
margin: 0 8px 8px 0;
position: relative;
padding: 8px;
border: 1px solid #d9d9d9;
border-radius: 2px;
&-card {
width: auto;
height: auto;
display: flex;
justify-content: center;
flex-direction: column;
flex-wrap: wrap;
align-items: center;
&:hover {
background: 0 0;
&-info::before {
opacity: 1
}
}
&-info {
&-item {
margin: 0 8px 8px 0;
position: relative;
height: 100%;
padding: 0;
overflow: hidden;
padding: 8px;
border: 1px solid #d9d9d9;
border-radius: 2px;
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
&:hover {
.img-box-actions {
background: 0 0;
.upload-card-item-info::before {
opacity: 1;
}
&-info::before {
opacity: 1;
}
}
&::before {
position: absolute;
z-index: 1;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, .5);
opacity: 0;
transition: all .3s;
content: ' ';
}
.img-box {
&-info {
position: relative;
//padding: 8px;
//border: 1px solid #d9d9d9;
border-radius: 2px;
}
.img-box-actions {
position: absolute;
top: 50%;
left: 50%;
z-index: 10;
white-space: nowrap;
transform: translate(-50%, -50%);
opacity: 0;
transition: all .3s;
display: flex;
align-items: center;
justify-content: space-between;
height: 100%;
padding: 0;
overflow: hidden;
&:hover {
background: 0 0;
.img-box-actions {
opacity: 1;
}
}
.action-icon {
color: rgba(255, 255, 255, .85);
&::before {
position: absolute;
z-index: 1;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
opacity: 0;
transition: all 0.3s;
content: ' ';
}
.img-box {
position: relative;
//padding: 8px;
//border: 1px solid #d9d9d9;
border-radius: 2px;
}
.img-box-actions {
position: absolute;
top: 50%;
left: 50%;
z-index: 10;
white-space: nowrap;
transform: translate(-50%, -50%);
opacity: 0;
transition: all 0.3s;
display: flex;
align-items: center;
justify-content: space-between;
&:hover {
cursor: pointer;
color: #fff
background: 0 0;
}
.action-icon {
color: rgba(255, 255, 255, 0.85);
&:hover {
cursor: pointer;
color: #fff;
}
}
}
}
}
}
&-item-select-picture {
border: 1px dashed #d9d9d9;
border-radius: 2px;
cursor: pointer;
background: #fafafa;
color: #666;
.upload-title {
&-item-select-picture {
border: 1px dashed #d9d9d9;
border-radius: 2px;
cursor: pointer;
background: #fafafa;
color: #666;
}
}
&-item:hover {
background: 0 0;
.upload-card-item-info::before {
opacity: 1
.upload-title {
color: #666;
}
}
}
}
}
</style>

View File

@@ -1,34 +1,34 @@
import type { PropType } from 'vue'
import { NUpload } from 'naive-ui'
import type { PropType } from 'vue';
import { NUpload } from 'naive-ui';
export const basicProps = {
...NUpload.props,
accept: {
type: String,
default: '.jpg,.png,.jpeg,.svg,.gif',
},
helpText: {
type: String as PropType<string>,
default: '',
},
maxSize: {
type: Number as PropType<number>,
default: 2
},
maxNumber: {
type: Number as PropType<number>,
default: Infinity
},
value: {
type: Array as PropType<string[]>,
default: () => []
},
width: {
type: Number as PropType<number>,
default: 104
},
height: {
type: Number as PropType<number>,
default: 104 //建议不小于这个尺寸 太小页面可能显示有异常
},
}
...NUpload.props,
accept: {
type: String,
default: '.jpg,.png,.jpeg,.svg,.gif',
},
helpText: {
type: String as PropType<string>,
default: '',
},
maxSize: {
type: Number as PropType<number>,
default: 2,
},
maxNumber: {
type: Number as PropType<number>,
default: Infinity,
},
value: {
type: Array as PropType<string[]>,
default: () => [],
},
width: {
type: Number as PropType<number>,
default: 104,
},
height: {
type: Number as PropType<number>,
default: 104, //建议不小于这个尺寸 太小页面可能显示有异常
},
};

View File

@@ -1,7 +1,7 @@
export interface BasicProps<T = any> {
title?: string,
dataSource: Function,
columns: any[],
pagination: object,
showPagination: boolean
export interface BasicProps {
title?: string;
dataSource: Function;
columns: any[];
pagination: object;
showPagination: boolean;
}