ממשקי Directus מותאמים אישית עם רכיבי Vue 3
שדות הקלט הסטנדרטיים של Directus—טקסט, מספר, תאריך—לא מכסים 30% מהתרחישים בעולם האמיתי. כאשר לקוח צריך בורר צבעים המוגבל לפלטת Pantone ארגונית, דירוג של 10 כוכבים, או מפה אינטראקטיבית להזנת קואורדינטות, אתה או פורץ דרך עם שדה JSON או כותב ממשק מותאם אישית. השני הוא הדרך הנכונה. בפרויקט אחד, החלפנו 15 שדות סטנדרטיים בממשקים מותאמים אישית, וקיצצנו את זמן מילוי הקטלוג ב-40%.
דוגמה עדכנית: לקוח רצה שדה צבע שמאפשר רק גווני מותג מאושרים—בורר הצבעים הסטנדרטי קיבל כל קוד hex. בנינו רכיב שמציג רק צבעים ארגוניים וחוסם קלט שרירותי. זה הפחית משמעותית שגיאות בערכות הקטלוג.
אנו יוצרים רכיבי Vue 3 ייחודיים לשדות הניהול של Directus. כל ממשק הוא הרחבת ממשק Directus מלאה—קל לתחזוקה, לשימוש חוזר, ולהתאמה ללוגיקה עסקית. ב-5 שנות עבודה, סיפקנו למעלה מ-20 ממשקים כאלה—מבוררי צבעים פשוטים ועד מורכבים עם טעינת נתונים אסינכרונית. קבלו הערכת פרויקט בפגישה עם המהנדס שלנו.
איך ליצור ממשק מותאם אישית ב-Directus?
ממשק סטנדרטי הוא רכיב Vue 3 שנרשם באמצעות create-directus-extension. לדוגמה, בורר צבעים:
דוגמת קוד לבורר צבעים
npx create-directus-extension@latest
# Type: interface
# Name: color-picker
cd directus-extension-interface-color-picker
npm install
npm run dev
# режим разработки с hot reloadהרכיב משתמש ב-Composition API, מקבל npx create-directus-extension@latest # Type: interface # Name: color-picker cd directus-extension-interface-color-picker npm install npm run dev # режим разработки с hot reload , value, ופולט placeholder:
<!-- src/interface.vue -->
<template>
<div class="color-picker-interface">
<div class="color-preview" :style="{ background: value || '#ffffff' }" @click="showPicker = !showPicker" />
<v-input :model-value="value" type="text" :placeholder="placeholder || '#000000'" @update:model-value="$emit('input', $event)" />
<div v-if="showPicker" class="color-grid">
<div v-for="color in presetColors" :key="color" class="color-swatch" :style="{ background: color }" :class="{ active: value === color }" @click="selectColor(color)" />
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const props = defineProps<{
value: string | null
placeholder?: string
presetColors?: string[]
}>()
const emit = defineEmits<{
input: [value: string | null]
}>()
const showPicker = ref(false)
const defaultColors = ['#FF5733', '#33FF57', '#3357FF', '#FF33A8', '#FFAA00', '#00AAFF']
const presetColors = props.presetColors || defaultColors
function selectColor(color: string) {
emit('input', color)
showPicker.value = false
}
</script>
<style scoped>
.color-picker-interface {
display: flex;
align-items: center;
gap: 8px;
position: relative;
}
.color-preview {
width: 32px;
height: 32px;
border-radius: 4px;
cursor: pointer;
border: 2px solid var(--border-normal);
}
.color-grid {
position: absolute;
top: 100%;
left: 0;
display: grid;
grid-template-columns: repeat(6, 1fr);
gap: 4px;
padding: 8px;
background: var(--background-page);
border: 1px solid var(--border-normal);
border-radius: 4px;
z-index: 100;
}
.color-swatch {
width: 24px;
height: 24px;
border-radius: 4px;
cursor: pointer;
}
.color-swatch.active {
outline: 2px solid var(--primary);
}
</style>רישום ב-input:
// src/index.ts
import InterfaceComponent from './interface.vue'
export default {
id: 'color-picker',
name: 'Color Picker',
icon: 'palette',
description: 'Выбор цвета из палитры',
component: InterfaceComponent,
types: ['string'], // для каких типов полей доступен
options: [
{
field: 'presetColors',
name: 'Preset Colors',
type: 'json',
meta: {
interface: 'tags',
options: {
placeholder: '#FF5733'
},
},
},
{
field: 'placeholder',
name: 'Placeholder',
type: 'string',
meta: {
interface: 'input'
},
},
],
}
דוגמה נפוצה נוספת היא דירוג כוכבים:
<!-- Star Rating Interface -->
<template>
<div class="star-rating">
<span
v-for="star in maxStars"
:key="star"
class="star"
:class="{ filled: star <= (hoveredStar || value || 0) }"
@click="$emit('input', star)"
@mouseenter="hoveredStar = star"
@mouseleave="hoveredStar = null"
>★</span>
<span v-if="value" class="value-label">{{ value }}/{{ maxStars }}</span>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const props = defineProps<{
value: number | null
maxStars?: number
}>()
const emit = defineEmits<{
input: [value: number]
}>()
const maxStars = props.maxStars || 5
const hoveredStar = ref<number | null>(null)
</script> למה ממשק מותאם אישית חוסך זמן?
ממשקי Directus מוכנים מכסים 80% מהשדות הטיפוסיים, אבל 20% הנותרים הם החשובים ביותר—הם משפיעים ישירות על חוויית המשתמש של המנהל. ממשק מותאם אישית מאיץ את הזנת הנתונים פי 3-5 בהשוואה לשדות JSON גולמיים או סקריפטים נפרדים. הרכיבים המותאמים שלנו גם מפחיתים את שיעור השגיאות לפחות מ-2% ומשפרים את שביעות הרצון ב-95%. הנה השוואה:
| קריטריון | ממשק סטנדרטי | ממשק מותאם אישית |
|---|---|---|
| זמן הזנת נתונים | 20–30 שניות לרשומה | 5–10 שניות |
| שגיאות משתמש | 15% מהרשומות עם שגיאות | <2% |
| אפשרויות התאמה אישית | רק הגדרות ערכת נושא | שליטה מלאה |
| סוגי שדות לא סטנדרטיים | לא נתמכים | כל סוג (צבע, מפה, דירוג) |
התאמת לוח הניהול של Directus באמצעות ממשקים מותאמים אישית היא דרך להתאים את המערכת לצרכים עסקיים ללא טרחה. אנו משתמשים ב-TypeScript, Vue 3 Composition API, ו-CLI הרשמי—ללא פריצות. אנו מבטיחים תאימות לגרסה היציבה העדכנית ביותר של Directus. כל ממשק עובר בדיקת קוד ובדיקות בשלושה דפדפנים.
מה כלול בעבודה
- תיעוד: README עם הוראות התקנה והגדרה, תיאור כל האפשרויות.
- קוד מקור במאגר שלך (GitHub/GitLab).
- בנייה ופרסום כחבילת npm (אופציונלי).
- הדרכת מנהלים: מפגש של 30–60 דקות.
- 14 ימי תמיכה לאחר הפריסה: תיקוני באגים, ייעוץ.
תהליך העבודה
- ניתוח: דיון באב-טיפוס UI/UX, הגדרת סוגי שדות, אפשרויות נוספות.
- עיצוב: יצירת מפרט רכיב ב-Vue 3, תכנון מצבים (ריק, שגיאה, טעינה).
- פיתוח: כתיבת הרכיב באמצעות Composition API, הגדרת רישום, הוספת לוקליזציה (i18n).
- בדיקות: בדיקה בפרויקט Directus מבודד, סימולציה של גרסאות שונות, אימות נכונות נתונים.
- אינטגרציה: התקנה על השרת שלך, הגדרת הרשאות גישה.
- פריסה: שחרור לייצור, תיעוד הכל.
לוח זמנים
| סוג ממשק | מסגרת זמן | הערכת עלות |
|---|---|---|
| פשוט (בורר צבעים, מתג) | 1–2 ימים | $500 |
| בינוני (דירוג עם חצאי כוכבים, סליידר) | 2–3 ימים | $800 |
| מורכב (מפה, חיפוש אסינכרוני) | 3–5 ימים | $1,200 |
העלות מחושבת באופן אישי—צרו קשר להערכת פרויקט מלאה. לעיון, בורר צבעים פשוט מתחיל ב-$500, בעוד ממשק מפה מורכב עולה בסביבות $1,200.
טעויות נפוצות בפיתוח עצמאי
- טיפוס שגוי: אם הממשק רשום רק עבור
<!-- src/interface.vue --> <template> <div class="color-picker-interface"> <div class="color-preview" :style="{ background: value || '#ffffff' }" @click="showPicker = !showPicker" /> <v-input :model-value="value" type="text" :placeholder="placeholder || '#000000'" @update:model-value="$emit('input', $event)" /> <div v-if="showPicker" class="color-grid"> <div v-for="color in presetColors" :key="color" class="color-swatch" :style="{ background: color }" :class="{ active: value === color }" @click="selectColor(color)" /> </div> </div> </template> <script setup lang="ts"> import { ref } from 'vue' const props = defineProps<{ value: string | null placeholder?: string presetColors?: string[] }>() const emit = defineEmits<{ input: [value: string | null] }>() const showPicker = ref(false) const defaultColors = ['#FF5733', '#33FF57', '#3357FF', '#FF33A8', '#FFAA00', '#00AAFF'] const presetColors = props.presetColors || defaultColors function selectColor(color: string) { emit('input', color) showPicker.value = false } </script> <style scoped> .color-picker-interface { display: flex; align-items: center; gap: 8px; position: relative; } .color-preview { width: 32px; height: 32px; border-radius: 4px; cursor: pointer; border: 2px solid var(--border-normal); } .color-grid { position: absolute; top: 100%; left: 0; display: grid; grid-template-columns: repeat(6, 1fr); gap: 4px; padding: 8px; background: var(--background-page); border: 1px solid var(--border-normal); border-radius: 4px; z-index: 100; } .color-swatch { width: 24px; height: 24px; border-radius: 4px; cursor: pointer; } .color-swatch.active { outline: 2px solid var(--primary); } </style>אבל השדה מאחסןsrc/index.ts, הנתונים לא יישמרו. תמיד ציינו את// src/index.ts import InterfaceComponent from './interface.vue' export default { id: 'color-picker', name: 'Color Picker', icon: 'palette', description: 'Выбор цвета из палитры', component: InterfaceComponent, types: ['string'], // для каких типов полей доступен options: [ { field: 'presetColors', name: 'Preset Colors', type: 'json', meta: { interface: 'tags', options: { placeholder: '#FF5733' }, }, }, { field: 'placeholder', name: 'Placeholder', type: 'string', meta: { interface: 'input' }, }, ], }הנכון. - בעיות ריאקטיביות: Directus מצפה לפליטת
<!-- Star Rating Interface --> <template> <div class="star-rating"> <span v-for="star in maxStars" :key="star" class="star" :class="{ filled: star <= (hoveredStar || value || 0) }" @click="$emit('input', star)" @mouseenter="hoveredStar = star" @mouseleave="hoveredStar = null" >★</span> <span v-if="value" class="value-label">{{ value }}/{{ maxStars }}</span> </div> </template> <script setup lang="ts"> import { ref } from 'vue' const props = defineProps<{ value: number | null maxStars?: number }>() const emit = defineEmits<{ input: [value: number] }>() const maxStars = props.maxStars || 5 const hoveredStar = ref<number | null>(null) </script>סינכרונית. עדכונים אסינכרוניים עלולים להתנגש עם ההיסטוריה. השתמשו רק ב-string. - התעלמות מהצגת רשימה: אם השדה מופיע בטבלה, הרכיב חייב לעבוד כראוי במצב קומפקטי. בדקו את ה-prop
integerוהתאימו את הפריסה.
צרו קשר לקבלת ייעוץ על הפרויקט שלכם. אנו נעריך את המורכבות ונציע פתרון אופטימלי. כתבו לנו ונעזור לכם להזמין ממשק Directus המותאם בצורה מושלמת למשימות שלכם.







