1. Excel交互组件封装
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CI / CI OK (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
Lock Threads / action (push) Has been cancelled
Issue Close Require / close-issues (push) Has been cancelled
Close stale issues / stale (push) Has been cancelled

This commit is contained in:
李琦
2026-06-25 16:09:07 +08:00
parent 8cfef12a56
commit 69862cd982
51 changed files with 10673 additions and 22 deletions

View File

@@ -0,0 +1,140 @@
<script setup lang="ts">
import { useVModel } from '@vueuse/core';
defineOptions({
inheritAttrs: false,
});
const props = defineProps({
value: {
type: String,
default: '',
},
placeholder: {
type: String,
default: '选择颜色',
},
});
const emits = defineEmits(['update:value']);
const mValue = useVModel(props, 'value', emits, {
defaultValue: props.value,
passive: true,
});
// 预设颜色列表(来自岗位颜色配置)
const presetColors = [
{ color: '#3b82f6', name: '蓝色' },
{ color: '#8b5cf6', name: '紫色' },
{ color: '#10b981', name: '绿色' },
{ color: '#f59e0b', name: '橙色' },
{ color: '#ec4899', name: '粉色' },
{ color: '#06b6d4', name: '青色' },
{ color: '#ef4444', name: '红色' },
{ color: '#6b7280', name: '灰色' },
];
const handleClear = (e: Event) => {
e.preventDefault();
mValue.value = '';
};
const selectPresetColor = (color: string) => {
mValue.value = color;
};
const isSelected = (color: string) => {
return mValue.value?.toLowerCase() === color.toLowerCase();
};
</script>
<template>
<div
class="color-picker-container rounded-lg border border-gray-200 bg-gray-50 p-3 dark:border-gray-600 dark:bg-gray-800"
>
<!-- 主选择器 -->
<div class="color-picker-main flex items-center gap-2.5">
<label class="color-picker-label relative inline-block cursor-pointer">
<input v-model="mValue" type="color" class="color-input" />
<span
class="color-preview flex h-10 w-10 items-center justify-center rounded-lg border-2 border-gray-300 shadow-sm transition-all hover:scale-105 hover:border-blue-500 dark:border-gray-500 dark:hover:border-blue-400"
:style="{ backgroundColor: mValue || 'var(--color-placeholder-bg)' }"
>
<span
v-if="!mValue"
class="text-base font-bold text-gray-400 dark:text-gray-500"
>?</span
>
</span>
</label>
<span
class="color-value flex-1 rounded border border-gray-200 bg-white px-2.5 py-1.5 font-mono text-sm text-gray-700 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200"
>
{{ mValue || placeholder }}
</span>
<a
v-if="mValue"
class="cursor-pointer rounded px-2 py-1 text-xs text-red-500 transition-all hover:bg-red-50 hover:no-underline dark:text-red-400 dark:hover:bg-red-900/20"
@click="handleClear"
>
清除
</a>
</div>
<!-- 预设颜色 -->
<div class="color-presets mt-3">
<span class="presets-label mb-2 block text-xs text-gray-500 dark:text-gray-400">
推荐颜色
</span>
<div class="presets-grid flex flex-wrap gap-2">
<div
v-for="preset in presetColors"
:key="preset.color"
class="preset-item flex h-7 w-7 cursor-pointer items-center justify-center rounded-full border-2 border-transparent shadow-sm transition-all hover:scale-115 hover:shadow-md"
:class="{
'ring-2 ring-gray-800 ring-offset-2 dark:ring-gray-200 dark:ring-offset-gray-800':
isSelected(preset.color),
}"
:style="{ backgroundColor: preset.color }"
:title="preset.name"
@click="selectPresetColor(preset.color)"
>
<span
v-if="isSelected(preset.color)"
class="check-icon text-sm font-bold text-white drop-shadow"
>
</span>
</div>
</div>
</div>
</div>
</template>
<style lang="less" scoped>
.color-picker-container {
max-width: 320px;
--color-placeholder-bg: #e5e7eb;
.dark & {
--color-placeholder-bg: #374151;
}
}
.color-picker-label {
.color-input {
position: absolute;
width: 0;
height: 0;
opacity: 0;
cursor: pointer;
}
}
.preset-item {
&:hover {
transform: scale(1.15);
}
}
</style>