fix(avatar): fix default style and click event

This commit is contained in:
Sagi 2022-10-01 09:55:38 +08:00
parent a1e6a28668
commit d361650012
8 changed files with 208 additions and 115 deletions

View File

@ -1,10 +1,13 @@
import { defineComponent, computed, ref, SetupContext } from 'vue';
import { avatarProps, AvatarProps } from './avatar.props';
import { useImage } from './composition/use-image';
import './avatar.scss';
export default defineComponent({
name: 'Avatar',
props: avatarProps,
emits: ['change'],
emits: ['change', 'update:modelValue'],
setup(props: AvatarProps, context: SetupContext) {
const avatarClass = computed(() => ({
'f-avatar': true,
@ -13,6 +16,8 @@ export default defineComponent({
'f-avatar-square': props.shape === 'square'
}));
const modelValue = ref(props.modelValue);
const avatarStyle = computed(() => ({
width: props.avatarWidth + 'px',
height: props.avatarHeight + 'px'
@ -29,32 +34,30 @@ export default defineComponent({
function getfiledata() {}
const defaultImgSrc =
'data:image/jpeg;base64,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';
const errorImgSrc =
'data:image/jpeg;base64,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';
const file=ref(null);
const imageType = computed(() => props.type.join());
const { acceptTypes, imageSource,onClickImage } = useImage(props, context, file, modelValue);
return () => {
return (
<div class={avatarClass.value} style={avatarStyle.value}>
<div class={avatarClass.value} style={avatarStyle.value} onClick={onClickImage}>
{showLoading && (
<div class="f-avatar-upload-loading">
<div class="loading-inner"></div>
</div>
)}
<img title={props.tile} class="f-avatar-image" src={imgSrc} onError={errorSrc()} />
<img title={props.tile} class="f-avatar-image" src={imageSource.value} onError={errorSrc()} />
{!props.readonly && (
<div class="f-avatar-icon">
<span class="f-icon f-icon-camera"></span>
</div>
)}
<input
ref="file"
name="file-input"
type="file"
class="f-avatar-upload"
accept={imageType.value}
accept={acceptTypes.value}
onChange={getfiledata}
style="display: none;"
/>

View File

@ -27,6 +27,10 @@ export const avatarProps = {
* , MB
*/
maxSize: { type: Number, default: 1 },
/**
*
*/
modelValue: { type: String, default: '' },
/**
*
*/
@ -34,7 +38,7 @@ export const avatarProps = {
/**
*
*/
type: { type: Array<string>, default: [] },
type: { type: Array<string>, default: [] }
};
export type AvatarProps = ExtractPropTypes<typeof avatarProps>;

View File

@ -0,0 +1,69 @@
.f-avatar{
position: relative;
// width: 100%;
// height: 100%;
cursor: pointer;
overflow: hidden;
&.f-avatar-readonly{
cursor: default;
}
&.f-avatar-circle{
border-radius: 100%;
overflow: hidden;
}
&.f-avatar-square{
border-radius: 0;
}
.f-avatar-image,.f-avatar-defult{
display: inline-block;
width: 100%;
height: 100%;
}
.f-avatar-icon{
display: none;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, 0.3);
.f-icon{
font-size: 24px;
color: #fff;
}
}
&.f-avatar-circle .f-avatar-icon{
border-radius: 100%;
}
&.f-avatar-square .f-avatar-icon{
border-radius: 0;
}
.f-avatar-upload-loading{
position: absolute;
left: 0;
top: 0;
display: inline-block;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.15);
.loading-inner{
position: absolute;
width: 100%;
left: 0;
top: 50%;
margin-top: -25px;
height: 50px;
line-height: 50px;
text-align: center;
font-size: 16px;
color: #fff;
}
}
&:hover{
.f-avatar-icon{
display: flex;
}
}
}

View File

@ -3,9 +3,11 @@ import { ComputedRef } from 'vue';
export interface UseImage {
acceptTypes: ComputedRef<string>;
imageSrc: ComputedRef<string>;
imageSource: ComputedRef<string>;
imageTitle: ComputedRef<string>;
onClickImage: () => void;
}
export interface ImageFile {

View File

@ -1,10 +1,15 @@
import { computed, SetupContext } from 'vue';
import { vue } from '@vitejs/plugin-vue';
import { computed, ref, Ref, SetupContext } from 'vue';
import { AvatarProps } from '../avatar.props';
import { UseImage } from './types';
export function useImage(props: AvatarProps, context: SetupContext, fileInput: HTMLInputElement): UseImage {
const defaultImage = '';
const errorImage = '';
export function useImage(props: AvatarProps, context: SetupContext, fileInput: any, modelValue: Ref<string>): UseImage {
const defaultImage =
'data:image/jpeg;base64,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';
const errorImage =
'data:image/jpeg;base64,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';
const readonly = ref(props.readonly);
// 判断是否是图片路径
function isUrl(url: string) {
@ -39,33 +44,28 @@ export function useImage(props: AvatarProps, context: SetupContext, fileInput: H
return imageTypesArray.join(',');
});
const imageSrc = computed(() => {
if (!props.cover) {
return defaultImage;
const imageSource = computed(() => {
const image = modelValue.value || props.cover || defaultImage;
if (isUrl(image) || isBase64Image(image)) {
return image;
}
if (isUrl(props.cover)) {
return props.cover;
}
if (isBase64Image(props.cover)) {
return props.cover;
}
return appendBase64ImageHeader(props.cover);
return appendBase64ImageHeader(image);
});
const imageTitle = computed(() => {
return props.readonly ? '' : props.tile;
return readonly.value ? '' : props.tile;
});
function onClickImage() {
if (this.readonly) {
if (readonly.value) {
return;
}
fileInput.click();
fileInput && fileInput.value && fileInput.value.click();
}
function getImageFile() {
return this.imgFileObj;
}
return { acceptTypes, imageSrc, imageTitle };
return { acceptTypes, imageSource, imageTitle, onClickImage };
}

View File

@ -3,103 +3,104 @@ import { ButtonEditProps } from '../button-edit.props';
import { UseTextBox } from './types';
export function useTextBox(props: ButtonEditProps, context: SetupContext, modelValue: Ref<string>, displayText: Ref<string>): UseTextBox {
const textBoxTitle = computed(() => (props.enableTitle ? modelValue.value : ''));
const textBoxTitle = computed(() => (props.enableTitle ? modelValue.value : ''));
const textBoxPlaceholder = computed(() => ((props.disable || props.readonly) && !props.forcePlaceholder ? '' : props.placeholder));
const textBoxPlaceholder = computed(() => ((props.disable || props.readonly) && !props.forcePlaceholder ? '' : props.placeholder));
const isTextBoxReadonly = computed(() => props.readonly || !props.editable);
const isTextBoxReadonly = computed(() => props.readonly || !props.editable);
let focusState = false;
let focusState = false;
const hasFocusedTextBox = computed(() => focusState);
const hasFocusedTextBox = computed(() => focusState);
const textBoxClass = computed(() => ({
'text-left': props.textAlign === 'left',
'text-center': props.textAlign === 'center',
'text-right': props.textAlign === 'right',
'form-control': true,
'f-utils-fill': true,
}));
const textBoxClass = computed(() => ({
'text-left': props.textAlign === 'left',
'text-center': props.textAlign === 'center',
'text-right': props.textAlign === 'right',
'form-control': true,
'f-utils-fill': true
}));
function changeTextBoxValue(newValue: string, showEmitChangeEmit = true) {
if (modelValue.value !== newValue) {
modelValue.value = newValue;
if (showEmitChangeEmit) {
context.emit('change', newValue);
}
function changeTextBoxValue(newValue: string, showEmitChangeEmit = true) {
if (modelValue.value !== newValue) {
modelValue.value = newValue;
if (showEmitChangeEmit) {
context.emit('change', newValue);
}
context.emit('update:modelValue', newValue);
}
}
}
watch(
() => props.modelValue,
(value: string) => context.emit('change', value)
);
watch(
() => props.modelValue,
(value: string) => context.emit('change', value)
);
function onBlurTextBox($event: Event) {
focusState = false;
context.emit('blur', $event);
$event.stopPropagation();
}
function onClickTextBox($event: Event) {
context.emit('click', $event);
}
function onFocusTextBox($event: Event) {
if (props.disable) {
return;
function onBlurTextBox($event: Event) {
focusState = false;
context.emit('blur', $event);
$event.stopPropagation();
}
focusState = true;
if (!isTextBoxReadonly.value) {
context.emit('focus', $event);
function onClickTextBox($event: Event) {
context.emit('click', $event);
}
}
function onInput($event: Event) {
context.emit('input', ($event.target as HTMLInputElement).value);
const newValue = ($event.target as HTMLInputElement).value;
displayText.value = newValue;
if (modelValue.value !== newValue) {
changeTextBoxValue(newValue, false);
context.emit('update:modelValue', ($event.target as HTMLInputElement).value);
function onFocusTextBox($event: Event) {
if (props.disable) {
return;
}
focusState = true;
if (!isTextBoxReadonly.value) {
context.emit('focus', $event);
}
}
}
function onMouseDownTextBox($event: MouseEvent) {
const target = $event.target as HTMLElement;
if (target.tagName !== 'INPUT') {
$event.preventDefault();
function onInput($event: Event) {
context.emit('input', ($event.target as HTMLInputElement).value);
const newValue = ($event.target as HTMLInputElement).value;
displayText.value = newValue;
if (modelValue.value !== newValue) {
changeTextBoxValue(newValue, false);
// context.emit('update:modelValue', ($event.target as HTMLInputElement).value);
}
}
$event.stopPropagation();
}
function onKeyDownTextBox($event: Event) {
context.emit('keydown', $event);
}
function onMouseDownTextBox($event: MouseEvent) {
const target = $event.target as HTMLElement;
if (target.tagName !== 'INPUT') {
$event.preventDefault();
}
$event.stopPropagation();
}
function onKeyUpTextBox($event: Event) {
context.emit('keyup', $event);
}
function onKeyDownTextBox($event: Event) {
context.emit('keydown', $event);
}
function onTextBoxValueChange($event: Event) {
const newValue = ($event.target as HTMLInputElement).value;
changeTextBoxValue(newValue);
}
function onKeyUpTextBox($event: Event) {
context.emit('keyup', $event);
}
return {
hasFocusedTextBox,
isTextBoxReadonly,
textBoxClass,
textBoxPlaceholder,
textBoxTitle,
changeTextBoxValue,
onBlurTextBox,
onClickTextBox,
onFocusTextBox,
onInput,
onKeyDownTextBox,
onKeyUpTextBox,
onMouseDownTextBox,
onTextBoxValueChange,
};
function onTextBoxValueChange($event: Event) {
const newValue = ($event.target as HTMLInputElement).value;
changeTextBoxValue(newValue);
}
return {
hasFocusedTextBox,
isTextBoxReadonly,
textBoxClass,
textBoxPlaceholder,
textBoxTitle,
changeTextBoxValue,
onBlurTextBox,
onClickTextBox,
onFocusTextBox,
onInput,
onKeyDownTextBox,
onKeyUpTextBox,
onMouseDownTextBox,
onTextBoxValueChange
};
}

View File

@ -3,8 +3,8 @@
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
import { ref } from "vue";
import HelloWorld from './components/hello-world.vue';
import ButtonEdit from "../components/button-edit/src/button-edit.component";
import Avatar from './components/avatar.vue';
import ButtonEdit from './components/button-edit.vue';
const canEdit = ref(true);
const canAutoComplete = ref(false);
@ -20,12 +20,8 @@ const canAutoComplete = ref(false);
<img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
</a>
</div>
<input type="checkbox" id="checkbox" v-model="canEdit" />
<label for="checkbox">editable:{{ canEdit }}</label>
<input type="checkbox" id="checkbox" v-model="canAutoComplete" />
<label for="checkbox">auto complete:{{ canAutoComplete }}</label>
<HelloWorld msg="Vite + Vue" />
<ButtonEdit :editable="canEdit" :auto-complete="canAutoComplete" :enable-clear="true"></ButtonEdit>
<ButtonEdit></ButtonEdit>
<Avatar></Avatar>
</template>

View File

@ -0,0 +1,18 @@
<script setup lang="ts">
import { ref } from 'vue';
import ButtonEdit from '../../components/button-edit/src/button-edit.component';
const canEdit = ref(true);
const canAutoComplete = ref(false);
const text = ref('');
</script>
<template>
<input type="checkbox" id="checkbox" v-model="canEdit" />
<label for="checkbox">editable:{{ canEdit }}</label>
<input type="checkbox" id="checkbox" v-model="canAutoComplete" />
<label for="checkbox">auto complete:{{ canAutoComplete }}</label>
<ButtonEdit :editable="canEdit" :auto-complete="canAutoComplete" :enable-clear="true" v-model="text"></ButtonEdit>
Text: {{text}}
</template>