Skip to content

Data Dictionary Documentation - Dictionary Management and Component Usage

Overview

This document details the data dictionary management system of the VJSP Vue3 framework. The data dictionary provides a unified enumeration value management solution, supporting centralized management and dynamic loading of status codes, type identifiers, and other data, ensuring data consistency and maintainability.

Dictionary Architecture

Core Features

  • Unified Management: All enumeration data is centrally managed to avoid hardcoding
  • Dynamic Loading: Supports runtime dynamic loading of dictionary data
  • Intelligent Caching: Automatic caching mechanism to improve performance
  • Type Safety: Complete TypeScript type definition support
  • Error Handling: Comprehensive error handling and retry mechanisms

Technology Stack

  • Pinia State Management: Dictionary data state management and caching
  • Asynchronous Loading: Supports asynchronous retrieval and updating of dictionary data
  • Component Integration: Deep integration with Element Plus component library

Dictionary Management Mechanism

Dictionary Data Storage

Dictionary data uses centralized storage management:

  • Memory Cache: Dictionary data is cached in memory for faster access
  • Automatic Expiration: Cached data automatically expires to ensure data timeliness
  • Force Refresh: Supports manual forced refresh of dictionary data

Dictionary Loading Process

  1. Application Startup: Check cache validity
  2. Data Loading: Retrieve dictionary data from backend API
  3. Cache Update: Update memory cache and timestamp
  4. Error Handling: Handle network errors and retry logic

Caching Strategy

The framework implements intelligent caching strategies:

  • Cache Duration: 5-minute automatic expiration
  • Retry Mechanism: Maximum 3 retries with exponential backoff delay
  • Concurrency Control: Prevent duplicate requests to avoid resource waste

Dictionary Utility Functions

Basic Dictionary Access

The framework provides safe dictionary access functions that automatically handle loading and errors:

  • getSafeDictLabel: Safely get dictionary label
  • getSafeDictValue: Safely get dictionary value
  • getSafeDictOptions: Safely get dictionary options list
  • batchGetDictLabels: Batch get dictionary labels
  • hasDictType: Check if dictionary type exists

Dictionary State Management

Manage dictionary data through the dictionary store module:

  • getDictData: Get dictionary data (automatically handles caching)
  • getDictByType: Get dictionary items by type
  • getDictLabel: Get dictionary label
  • getDictValue: Get dictionary value
  • refreshDictData: Refresh dictionary data
  • clearDictData: Clear dictionary cache

Dictionary Component Usage

Component Collection

The framework provides a complete dictionary component collection:

  • DictSelect: Dictionary selector
  • DictTag: Dictionary tag display
  • DictRadio: Dictionary radio component
  • DictCheckbox: Dictionary checkbox component
  • DictSwitch: Dictionary switch component
  • DictCascader: Dictionary cascader selector

Component Features

All dictionary components have the following features:

  • Auto Loading: Automatically loads corresponding dictionary type data
  • Error Handling: Handles dictionary data loading failures
  • Type Safety: Complete TypeScript type support
  • Style Consistency: Consistent with Element Plus component styling

Business Module Development Guide (Product Module)

1. Define Dictionary Types

Define product-related dictionary types in the dictionary management system:

  • product_status: Product status dictionary
  • product_category: Product category dictionary
  • product_type: Product type dictionary

2. Create Product Management Page

src/views/modules/product/list.vue

vue
<template>
  <div class="product-list">
    <!-- Search Form -->
    <el-form :model="queryParams" inline>
      <el-form-item label="Product Status">
        <DictSelect
          v-model="queryParams.status"
          dict-type="product_status"
          placeholder="Please select product status"
          clearable
        />
      </el-form-item>

      <el-form-item label="Product Category">
        <DictSelect
          v-model="queryParams.category"
          dict-type="product_category"
          placeholder="Please select product category"
          clearable
        />
      </el-form-item>

      <el-button type="primary" @click="handleQuery">Query</el-button>
      <el-button @click="resetQuery">Reset</el-button>
    </el-form>

    <!-- Data Table -->
    <el-table :data="productList" v-loading="loading">
      <el-table-column prop="productName" label="Product Name" />
      <el-table-column prop="productCode" label="Product Code" />
      <el-table-column prop="status" label="Product Status">
        <template #default="{ row }">
          <DictTag :value="row.status" dict-type="product_status" />
        </template>
      </el-table-column>
      <el-table-column prop="category" label="Product Category">
        <template #default="{ row }">
          <DictTag :value="row.category" dict-type="product_category" />
        </template>
      </el-table-column>
      <el-table-column prop="type" label="Product Type">
        <template #default="{ row }">
          <DictTag :value="row.type" dict-type="product_type" />
        </template>
      </el-table-column>
      <el-table-column label="Actions" width="200">
        <template #default="{ row }">
          <el-button size="small" @click="handleEdit(row)">Edit</el-button>
          <el-button size="small" type="danger" @click="handleDelete(row)">Delete</el-button>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useProductApi } from '@/api/modules/product'

const queryParams = ref({
  status: '',
  category: '',
  productName: '',
})

const productList = ref([])
const loading = ref(false)

const loadProductList = async () => {
  loading.value = true
  try {
    const response = await useProductApi().getList(queryParams.value)
    productList.value = response.data.list
  } finally {
    loading.value = false
  }
}

const handleQuery = () => {
  loadProductList()
}

const resetQuery = () => {
  queryParams.value = {
    status: '',
    category: '',
    productName: '',
  }
  loadProductList()
}

onMounted(() => {
  loadProductList()
})
</script>

3. Product Creation/Editing Form

src/views/modules/product/form.vue

vue
<template>
  <el-form :model="formData" :rules="rules" ref="formRef" label-width="120px">
    <el-form-item label="Product Name" prop="productName">
      <el-input v-model="formData.productName" placeholder="Enter product name" />
    </el-form-item>

    <el-form-item label="Product Status" prop="status">
      <DictRadio v-model="formData.status" dict-type="product_status" :options="statusOptions" />
    </el-form-item>

    <el-form-item label="Product Category" prop="category">
      <DictSelect
        v-model="formData.category"
        dict-type="product_category"
        placeholder="Select product category"
      />
    </el-form-item>

    <el-form-item label="Product Type" prop="type">
      <DictCheckbox v-model="formData.type" dict-type="product_type" :options="typeOptions" />
    </el-form-item>

    <el-form-item>
      <el-button type="primary" @click="handleSubmit">Submit</el-button>
      <el-button @click="handleCancel">Cancel</el-button>
    </el-form-item>
  </el-form>
</template>

<script setup lang="ts">
import { ref, reactive } from 'vue'
import { useRouter } from 'vue-router'

const router = useRouter()
const formRef = ref()

const formData = reactive({
  productName: '',
  status: '',
  category: '',
  type: [],
})

const rules = {
  productName: [{ required: true, message: 'Product name is required', trigger: 'blur' }],
  status: [{ required: true, message: 'Product status is required', trigger: 'change' }],
}

const handleSubmit = async () => {
  try {
    await formRef.value.validate()
    // Submit form data
    console.log('Form submitted:', formData)
    router.push('/product/list')
  } catch (error) {
    console.error('Form validation failed:', error)
  }
}

const handleCancel = () => {
  router.push('/product/list')
}
</script>

Advanced Dictionary Usage

Custom Dictionary Components

Create custom dictionary components for specific business needs:

vue
<!-- src/components/DictColorTag.vue -->
<template>
  <el-tag :color="getTagColor(value)" effect="dark">
    {{ getDictLabel(value, dictType) }}
  </el-tag>
</template>

<script setup lang="ts">
import { computed } from 'vue'
import { useDictStore } from '@/stores/dict'

interface Props {
  value: string | number
  dictType: string
}

const props = defineProps<Props>()
const dictStore = useDictStore()

const getTagColor = (value: string | number) => {
  const colorMap = {
    active: '#67C23A',
    inactive: '#909399',
    pending: '#E6A23C',
    rejected: '#F56C6C',
  }
  return colorMap[value] || '#909399'
}

const getDictLabel = computed(() => {
  return (value: string | number, type: string) => {
    return dictStore.getDictLabel(type, value) || value
  }
})
</script>

Dictionary Data Validation

Implement dictionary-based form validation:

typescript
// src/utils/validation.ts
import { useDictStore } from '@/stores/dict'

export const createDictValidator = (dictType: string) => {
  return (value: any) => {
    const dictStore = useDictStore()
    const dictOptions = dictStore.getDictByType(dictType)
    const validValues = dictOptions.map(item => item.value)

    if (!validValues.includes(value)) {
      return new Error(`Invalid value for dictionary type: ${dictType}`)
    }
    return true
  }
}

// Usage in form validation
const rules = {
  status: [
    { required: true, message: 'Status is required' },
    { validator: createDictValidator('product_status'), trigger: 'change' },
  ],
}

Performance Optimization

Lazy Loading Dictionaries

Load dictionaries on-demand to improve initial load performance:

typescript
// src/hooks/useLazyDict.ts
import { ref } from 'vue'
import { useDictStore } from '@/stores/dict'

export function useLazyDict(dictType: string) {
  const dictStore = useDictStore()
  const loading = ref(false)
  const loaded = ref(false)

  const loadDict = async () => {
    if (loaded.value || dictStore.hasDictType(dictType)) {
      return
    }

    loading.value = true
    try {
      await dictStore.loadDictData(dictType)
      loaded.value = true
    } finally {
      loading.value = false
    }
  }

  return {
    loading,
    loaded,
    loadDict,
  }
}

Dictionary Preloading

Preload commonly used dictionaries during application initialization:

typescript
// src/utils/dictPreloader.ts
import { useDictStore } from '@/stores/dict'

export const preloadCommonDicts = async () => {
  const dictStore = useDictStore()
  const commonDictTypes = ['product_status', 'product_category', 'user_status', 'order_status']

  await Promise.allSettled(commonDictTypes.map(type => dictStore.loadDictData(type)))
}

Error Handling and Debugging

Dictionary Error Monitoring

Monitor dictionary loading errors and provide fallback mechanisms:

typescript
// src/utils/dictErrorHandler.ts
export class DictErrorHandler {
  static handleLoadError(error: Error, dictType: string) {
    console.error(`Failed to load dictionary: ${dictType}`, error)

    // Send to error tracking service
    if (import.meta.env.PROD) {
      // Send to monitoring service
    }

    // Provide fallback data
    return this.getFallbackDict(dictType)
  }

  static getFallbackDict(dictType: string) {
    const fallbackDicts = {
      product_status: [
        { label: 'Active', value: 'active' },
        { label: 'Inactive', value: 'inactive' },
      ],
      // Add more fallback dictionaries
    }

    return fallbackDicts[dictType] || []
  }
}

Debugging Tools

Add debugging tools for dictionary development:

typescript
// src/utils/dictDebug.ts
export const dictDebug = {
  logDictState: (dictType: string) => {
    const dictStore = useDictStore()
    console.log(`Dictionary [${dictType}]:`, dictStore.getDictByType(dictType))
  },

  monitorDictChanges: (dictType: string) => {
    const dictStore = useDictStore()
    watch(
      () => dictStore.getDictByType(dictType),
      (newDict, oldDict) => {
        console.log(`Dictionary [${dictType}] changed:`, { old: oldDict, new: newDict })
      }
    )
  },
}

This comprehensive dictionary management system provides a robust foundation for handling enumeration data in the VJSP Vue3 framework, ensuring data consistency, type safety, and optimal performance across all business modules.