ColorTimetable

repository·main·Indexed 41 days ago

https://github.com/nei1ee/colortimetable

A visual course timetable component for the uni-app framework, supporting Vue 3 and TypeScript. Version 2.1.0 features visual weekly selection, course management (deletion and pinning), and course detail cards. Built with Vite 2, Pinia for state management, and UnoCSS for styling.

Tokens
4.4K
Snippets
17
Records
19
Agent score
51%

What's inside ColorTimetable

  1. Overview of uni-app ColorTimetable component

    main

    The colortimetable component is a visual course timetable component designed for uni-app projects. It provides features such as:

    • Visual weekly selection.
    • Course management (deletion and pinning).
    • Course detail cards.

    Technical stack:

    • Vue 3 with <script setup> syntax.
    • Vite 2.
    • TypeScript for type checking.
    • Optimized with pnpm and ESBuild.
  2. Install and run ColorTimetable in a uni-app project

    main

    To use this component in a development environment, follow these steps to clone the repository, install dependencies, and run the project for WeChat Mini Program (mp-weixin).

    Note: Ensure your uni-app project supports Vue 3.0 before proceeding.

    # Clone the repository
    git clone https://github.com/zguolee/ColorTimetable.git
    
    # Install dependencies
    cd ColorTimetable
    pnpm install
    
    # Run for WeChat Mini Program
    pnpm run dev:mp-weixin
    
    # Build for WeChat Mini Program
    pnpm run build:mp-weixin
  3. Breaking changes in Version 2.1.0

    main

    When upgrading to version 2.1.0, be aware of the following breaking changes:

    • Course Data Structure: The internal structure of course data has changed. You must update your data models to match the new schema.
    • Course Card Display: The method used to display course cards has been updated.
  4. Configure UnoCSS for colortimetable

    main

    The project uses unocss with unocss-applet extensions to manage styling. The configuration defines custom shortcuts for base colors and borders, integrates icon presets, and uses specific transformers to handle directives and applet-specific syntax.

    Key configuration areas include:

    • Shortcuts: Predefined utility classes like bg-base, color-base, and bg-primary that combine multiple utility classes.
    • Presets: Includes presetIcons (with custom scale and alignment), presetApplet (conditional based on platform), presetAttributify, and presetRemToRpx.
    • Transformers: Uses transformerDirectives, transformerVariantGroup, transformerAttributify, and transformerApplet. Note that the order of transformerAttributify and transformerApplet is significant.
    • Rules: Custom utility rules for handling safe area insets (e.g., p-safe, pt-safe, pb-safe).
    • Safelist: Ensures dynamic color classes for course scheduling (e.g., bg-rose, text-pink-5) are not purged by the CSS engine.
    import { defineConfig, presetIcons, presetAttributify } from 'unocss'
    import { presetApplet, presetRemToRpx, transformerApplet, transformerAttributify } from 'unocss-applet'
    
    export default defineConfig({
      shortcuts: {
        'bg-base': 'bg-gray-100 dark:bg-dark',
        'bg-primary': 'bg-light-blue-500 dark:bg-light-blue-600/80',
        // ...
      },
      presets: [
        presetIcons({ scale: 1.2, extraProperties: { 'display': 'inline-block', 'vertical-align': 'middle' } }),
        presetApplet({ enable: !isH5 }),
        presetAttributify(),
        presetRemToRpx({ enable: !isH5 }),
      ],
      transformers: [
        transformerDirectives(),
        transformerVariantGroup(),
        transformerAttributify(),
        transformerApplet(),
      ],
      rules: [
        ['p-safe', { padding: 'env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left)' }],
      ],
      safelist: [
        // Dynamically generated color classes
      ]
    })
  5. Manage course state with useCourseStore

    main

    The useCourseStore is a Pinia store used to manage the timetable state, including the list of courses, the current week, and the semester start date.

    Key State & Actions:

    Initialization

    • setStartDay(someDate: string | Date): Sets the semester start date and calculates the current week index based on the current date.
    • setCourseList(newCourseList: CourseModel[]): Initializes the timetable with a list of courses. It automatically sorts them by week and start time and assigns colors.
    • setCurrentWeekIndex(weekIndex: number): Updates the view to a specific week index and recalculates the current month.

    Course Manipulation

    • deleteCourseItem(courseItem: CourseModel): Removes a specific course instance from the list.
    • deleteCourseItemByTitle(courseTitle: string): Removes all courses matching the provided title.
    • setCourseItemTop(courseItem: CourseModel): Moves a specific course to the top of the list (useful for resolving visual conflicts).

    Data Access (Computed)

    • courseList: The full list of CourseModel objects.
    • weekCourseList: A filtered list containing only the courses for the currently selected week.
    • currentWeekDayArray: An array of dates representing the days of the current week.
    • parsedCourseList: A 3D array structure used for rendering/processing course density across weeks, days, and time slots.
    import { useCourseStore } from '~/stores/course'
    
    const courseStore = useCourseStore()
    
    // Initialize with a start date
    courseStore.setStartDay('2023-09-01')
    
    // Add courses
    courseStore.setCourseList([
      {
        title: 'Mathematics',
        location: 'Room 101',
        start: 1,
        duration: 2,
        week: 1,
        weeks: [1, 2, 3, 4]
      }
    ])
  6. Check for course conflicts

    main

    To identify if multiple courses are scheduled at the same time and day, use getConflictCourse or hasConflictCourseByMap.

    • getConflictCourse(courseItem: CourseModel): Returns an array of CourseModel objects that overlap with the provided courseItem in the current week.
    • hasConflictCourseByMap(courseItem: CourseModel): A performance-optimized version that uses an internal cache to return conflicting courses.
    const courseStore = useCourseStore()
    const myCourse = { title: 'Math', week: 1, start: 1, ... }
    
    const conflicts = courseStore.getConflictCourse(myCourse)
    if (conflicts.length > 0) {
      console.log('Time conflict detected!')
    }
  7. Configure UToast options

    main

    When using the UToast component, you can pass an options object of type UToastOptions to control the toast's appearance and behavior.

    Supported options:

    • type: The visual style of the toast. Use one of the following values: 'default', 'success', 'error', 'warning', or 'primary'.
    • message: The string content to be displayed in the toast (required).
    • duration: The time in milliseconds before the toast automatically disappears.
    const options: UToastOptions = {
      type: 'success',
      message: 'Operation completed successfully!',
      duration: 3000
    };
  8. Use useCourseStoreWidthOut for non-component usage

    main

    If you need to access the course store outside of a Vue component setup (e.g., in a plain TypeScript file or a utility function where Pinia context is not automatically available), use useCourseStoreWidthOut to ensure the store is correctly linked to the Pinia instance.

    import { useCourseStoreWidthOut } from '~/stores/course'
    
    const courseStore = useCourseStoreWidthOut()
    // Now you can use courseStore as usual
  9. Trigger notifications and toasts via usePageStore

    main

    The usePageStore provides proxy methods to trigger UI notifications and toasts. These methods rely on internal references (notifyRef and toastRef) that must be initialized (typically by the page component rendering the corresponding UnoUI components).

    • showNotify(options: UNotifyOptions): Triggers a notification using the options provided.
    • showToast(options: UToastOptions): Triggers a toast using the options provided.
    import { usePageStore } from '~/stores/page'
    
    const pageStore = usePageStore()
    
    // Trigger a notification
    pageStore.showNotify({
      // ... UNotifyOptions
    })
    
    // Trigger a toast
    pageStore.showToast({
      // ... UToastOptions
    })
  10. Initialize the application with createApp()

    main

    The createApp function is the primary entrypoint for initializing the application. It creates a Vue SSR (Server-Side Rendering) application instance using createSSRApp and configures the necessary modules, such as Pinia for state management. This function returns an object containing the initialized app instance.

    import { createApp } from './src/main'
    
    const { app } = createApp()
    // Use the app instance for further configuration or mounting
  11. Manage page configuration with usePageStore

    main

    The usePageStore Pinia store manages the UI state for a specific page, including navigation bar visibility, back actions, custom actions, and the page title. You can configure these properties using setPageConfig.

    PageConfig Options

    KeyTypeDefaultDescription
    showNavBarbooleantrueControls whether the navigation bar is visible.
    showBackActionbooleanfalseControls whether a back action is visible.
    showCustomActionbooleanfalseControls whether a custom action is visible.
    pageTitlestring''The text displayed as the page title.

    Resetting State

    Call pageReset() to revert the page configuration to its default state and clear any attached notification or toast references.

    import { usePageStore } from '~/stores/page'
    
    const pageStore = usePageStore()
    
    // Configure the page UI
    pageStore.setPageConfig({
      showNavBar: true,
      showBackAction: true,
      pageTitle: 'My Timetable'
    })
    
    // Reset to defaults
    pageStore.pageReset()
  12. Access usePageStore outside of Vue setup

    main

    If you need to access the page store in a context where the standard usePageStore() (which relies on the current component instance) is unavailable (e.g., in a plain TypeScript file or a router guard), use usePageStoreWidthOut() to ensure the store is correctly linked to the global Pinia instance.

    import { usePageStoreWidthOut } from '~/stores/page'
    
    // Use this in non-component contexts
    const pageStore = usePageStoreWidthOut()
    
    pageStore.setPageConfig({ pageTitle: 'Global Context' })