Skip to content

Commit

Permalink
feat(projects): 图片预览,SuspenseWithError,operate-row组件重构为setup语法以及引入day…
Browse files Browse the repository at this point in the history
…js中文包
  • Loading branch information
yanbowe authored and buqiyuan committed Dec 15, 2021
1 parent 7dcec87 commit f7aceff
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 169 deletions.
20 changes: 7 additions & 13 deletions src/components/SuspenseWithError.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,12 @@
</Suspense>
</template>

<script lang="ts">
import { ref, defineComponent, onErrorCaptured } from 'vue';
export default defineComponent({
name: 'SuspenseWithError',
setup() {
const error = ref<any>(null);
onErrorCaptured((e) => {
// error.value = '(⊙o⊙)…出了点问题。'
console.error(e);
return true;
});
return { error };
},
<script lang="ts" setup>
import { ref, onErrorCaptured } from 'vue';
const error = ref<any>(null);
onErrorCaptured((e) => {
// error.value = '(⊙o⊙)…出了点问题。'
console.error(e);
return true;
});
</script>
47 changes: 21 additions & 26 deletions src/components/operate-row/operate-row.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,38 @@
<div class="actions">
<slot name="before"></slot>
<template v-if="!hideDel">
<a-popconfirm title="您确定要删除该节点吗?" @confirm="() => $emit('delete')">
<Popconfirm title="您确定要删除该节点吗?" @confirm="() => $emit('delete')">
<delete-outlined @click.stop />
</a-popconfirm>
</Popconfirm>
</template>
<form-outlined v-if="!hideEdit" @click="$emit('edit')" />
<plus-outlined v-if="!hideAdd" @click="$emit('add')" />
<slot name="after"></slot>
</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
<script lang="ts" setup>
import { DeleteOutlined, FormOutlined, PlusOutlined } from '@ant-design/icons-vue';
import { Popconfirm } from 'ant-design-vue';
export default defineComponent({
name: 'OperateRow',
components: { DeleteOutlined, PlusOutlined, FormOutlined, [Popconfirm.name]: Popconfirm },
props: {
hideAdd: {
type: Boolean,
default: false,
},
hideDel: {
type: Boolean,
default: false,
},
hideEdit: {
type: Boolean,
default: false,
},
},
emits: ['delete', 'edit', 'add'],
setup() {
return {};
},
interface Props {
hideAdd: boolean;
hideDel: boolean;
hideEdit: boolean;
}
interface Emits {
(e: 'delete'): void;
(e: 'edit'): void;
(e: 'add'): void;
}
withDefaults(defineProps<Props>(), {
hideAdd: false,
hideDel: false,
hideEdit: false,
});
defineEmits<Emits>();
</script>

<style lang="less" scoped>
Expand Down
235 changes: 105 additions & 130 deletions src/components/preview-modal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
<teleport to="body">
<div v-if="isVisible" class="preview-modal" @click.self="isVisible = false">
<close-circle-outlined class="close-icon" @click="isVisible = false" />
<div class="preview-content" :style="contentStyle">
<a-spin :spinning="loading">
<div class="preview-content" :style="state.contentStyle">
<Spin :spinning="state.loading">
<img
v-if="type === 'image'"
ref="img"
:style="imgStyle"
:style="state.imgStyle"
:src="url"
alt=""
@load.stop="imgLoaded"
Expand All @@ -18,13 +18,13 @@
:src="url"
controls
autoplay
@canplay="loading = false"
@loadstart="loading = true"
@canplay="state.loading = false"
@loadstart="state.loading = true"
></video>
<div ref="imgScaleMask" class="img-scale-mask">
{{ ~~(imgScale * 100) + '%' }}
{{ ~~(state.imgScale * 100) + '%' }}
</div>
</a-spin>
</Spin>
</div>
<div v-if="type === 'image'" class="toolbar">
<zoom-in-outlined title="放大" @click="zoomInImg" />
Expand All @@ -36,9 +36,8 @@
</div>
</teleport>
</template>

<script lang="ts">
import { defineComponent, PropType, reactive, toRefs, ref, computed } from 'vue';
<script lang="ts" setup>
import { reactive, ref, computed } from 'vue';
import { Spin } from 'ant-design-vue';
import {
ZoomInOutlined,
Expand All @@ -50,131 +49,107 @@
} from '@ant-design/icons-vue';
import { downloadByUrl } from '@/utils/downloadFile';
export default defineComponent({
name: 'PreviewModal',
components: {
ZoomInOutlined,
ZoomOutOutlined,
RedoOutlined,
DownloadOutlined,
CloseCircleOutlined,
OneToOneOutlined,
[Spin.name]: Spin,
},
props: {
visible: {
type: Boolean as PropType<boolean>,
default: false,
},
type: {
type: String as PropType<string>,
default: 'image',
},
url: {
type: String as PropType<string>,
default: '',
},
},
emits: ['update:visible'],
setup(props, { emit }) {
// 图片蒙层
const imgScaleMask = ref<HTMLDivElement>();
let timer;
const state = reactive({
timer: null,
loading: false, // 视频加载动画
rotateDeg: 0,
imgScale: 1, // 图片缩放比
scaleCV: 0.07, // 缩放的系数
initWidth: 0, // 图片初始宽高
initHeight: 0, // 图片初始宽高
contentStyle: {
// 默认大小
width: '60vw',
height: '60vh',
} as any,
imgStyle: {
width: '',
height: '',
transform: 'rotate(0)',
} as any,
});
interface Props {
visible: boolean;
type: string;
url: string;
}
const isVisible = computed({
get: () => props.visible,
set: (val) => emit('update:visible', val),
});
interface Emits {
(e: 'update:visible', val: boolean): void;
}
// 旋转图片
const rotateImg = () => {
state.rotateDeg -= 90;
state.imgStyle.transform = `rotate(${state.rotateDeg}deg)`;
};
// 保存图片
const saveImg = (url) => {
downloadByUrl({ url });
};
// 处理图片缩放比
const handZoom = (type = 'scale') => {
console.log(state.imgScale);
state.imgStyle.width = state.initWidth * state.imgScale + 'px';
state.imgStyle.height = state.initHeight * state.imgScale + 'px';
if (type === 'init') {
state.imgStyle.maxWidth = '';
state.imgStyle.maxHeight = '';
} else {
state.imgStyle.maxWidth = 'none!important';
state.imgStyle.maxHeight = 'none!important';
}
clearTimeout(timer);
timer = setTimeout(() => imgScaleMask.value?.classList.remove('active'), 1400);
imgScaleMask.value?.classList.add('active');
state.contentStyle = {};
};
// 恢复原来的比例
const resetImg = () => {
state.imgScale = 1;
handZoom();
};
// 图片放大
const zoomInImg = () => {
state.imgScale += state.scaleCV;
handZoom();
};
// 图片缩放
const zoomOutImg = () => {
state.imgScale -= state.scaleCV;
handZoom();
};
const props = withDefaults(defineProps<Props>(), {
visible: false,
type: 'image',
url: '',
});
// 图片加载完成后获取初始宽高
const imgLoaded = (e) => {
if (e.currentTarget?.complete) {
const { width, height } = getComputedStyle(e.currentTarget);
state.imgStyle.width = width;
state.imgStyle.height = height;
state.initWidth = parseFloat(width);
state.initHeight = parseFloat(height);
console.log(state.imgStyle, '图片加载完毕');
}
};
const emit = defineEmits<Emits>();
// 图片蒙层
const imgScaleMask = ref<HTMLDivElement>();
let timer;
const state = reactive({
timer: null,
loading: false, // 视频加载动画
rotateDeg: 0,
imgScale: 1, // 图片缩放比
scaleCV: 0.07, // 缩放的系数
initWidth: 0, // 图片初始宽高
initHeight: 0, // 图片初始宽高
contentStyle: {
// 默认大小
width: '60vw',
height: '60vh',
} as any,
imgStyle: {
width: '',
height: '',
transform: 'rotate(0)',
} as any,
});
return {
...toRefs(state),
imgScaleMask,
isVisible,
rotateImg,
saveImg,
zoomInImg,
zoomOutImg,
handZoom,
imgLoaded,
resetImg,
};
},
const isVisible = computed({
get: () => props.visible,
set: (val) => emit('update:visible', val),
});
// 旋转图片
const rotateImg = () => {
state.rotateDeg -= 90;
state.imgStyle.transform = `rotate(${state.rotateDeg}deg)`;
};
// 保存图片
const saveImg = (url) => {
downloadByUrl({ url });
};
// 处理图片缩放比
const handZoom = (type = 'scale') => {
console.log(state.imgScale);
state.imgStyle.width = state.initWidth * state.imgScale + 'px';
state.imgStyle.height = state.initHeight * state.imgScale + 'px';
if (type === 'init') {
state.imgStyle.maxWidth = '';
state.imgStyle.maxHeight = '';
} else {
state.imgStyle.maxWidth = 'none!important';
state.imgStyle.maxHeight = 'none!important';
}
clearTimeout(timer);
timer = setTimeout(() => imgScaleMask.value?.classList.remove('active'), 1400);
imgScaleMask.value?.classList.add('active');
state.contentStyle = {};
};
// 恢复原来的比例
const resetImg = () => {
state.imgScale = 1;
handZoom();
};
// 图片放大
const zoomInImg = () => {
state.imgScale += state.scaleCV;
handZoom();
};
// 图片缩放
const zoomOutImg = () => {
state.imgScale -= state.scaleCV;
handZoom();
};
// 图片加载完成后获取初始宽高
const imgLoaded = (e) => {
if (e.currentTarget?.complete) {
const { width, height } = getComputedStyle(e.currentTarget);
state.imgStyle.width = width;
state.imgStyle.height = height;
state.initWidth = parseFloat(width);
state.initHeight = parseFloat(height);
console.log(state.imgStyle, '图片加载完毕');
}
};
</script>

<style lang="less">
Expand Down
1 change: 1 addition & 0 deletions src/plugins/antd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
} from 'ant-design-vue';

import 'ant-design-vue/dist/antd.css';
import 'dayjs/locale/zh-cn';

export function setupAntd(app: App<Element>) {
app.component('AButton', AButton);
Expand Down

0 comments on commit f7aceff

Please sign in to comment.