init project

This commit is contained in:
Timi
2026-08-01 18:01:23 +08:00
parent 286fa1ba56
commit 11c48bf00c
107 changed files with 19350 additions and 1 deletions
+144
View File
@@ -0,0 +1,144 @@
<template>
<div class="photo-field" :class="{ compact: size === 'compact' }">
<t-button
v-if="!modelValue"
theme="primary"
variant="dashed"
class="add"
@click="$emit('add')"
>
<span v-text="addText" />
</t-button>
<div v-else class="card">
<t-button variant="text" class="preview-trigger" @click="handlePhotoClick">
<t-image
class="image"
:src="modelValue"
:alt="altText"
fit="cover"
/>
</t-button>
<t-button
v-if="showRemove"
class="remove"
theme="danger"
shape="circle"
size="extra-small"
@click="clearPhoto"
>
<t-icon name="close" size="1rem" />
</t-button>
</div>
<t-image-viewer
v-model:visible="photoViewerVisible"
:images="photoViewerImages"
show-index
/>
</div>
</template>
<script setup lang="ts">
interface Props {
addText?: string;
altText?: string;
modelValue: string;
preview?: boolean;
showRemove?: boolean;
size?: "normal" | "compact";
}
const props = withDefaults(defineProps<Props>(), {
addText: "拍照",
altText: "照片",
preview: true,
showRemove: true,
size: "normal"
});
defineOptions({
name: "PhotoField"
});
const emit = defineEmits<{
add: [];
clear: [];
"update:modelValue": [value: string];
}>();
const photoViewerVisible = ref(false);
const photoViewerImages = computed(() => props.modelValue ? [props.modelValue] : []);
function handlePhotoClick(): void {
if (!props.preview) {
emit("add");
return;
}
photoViewerVisible.value = true;
}
function clearPhoto(): void {
emit("update:modelValue", "");
emit("clear");
photoViewerVisible.value = false;
}
</script>
<style scoped lang="less">
.photo-field {
gap: .75rem;
display: grid;
.add {
--td-button-border-radius: .875rem;
width: 5rem;
height: 5rem;
padding: 0;
}
.card {
width: 5rem;
height: 5rem;
position: relative;
overflow: hidden;
border-radius: .875rem;
}
.preview-trigger {
padding: 0;
border: 0;
width: 100%;
height: 100%;
display: block;
background: transparent;
border-radius: .875rem;
}
.image {
width: 100%;
height: 100%;
display: block;
border-radius: .875rem;
}
.remove {
top: .375rem;
right: .375rem;
position: absolute;
:deep(.t-button__content) {
display: flex;
align-items: center;
}
}
&.compact {
.add,
.card {
width: 4rem;
height: 4rem;
}
}
}
</style>