Source: stores/modules/themeStore.js

/**
 * @file stores/modules/themeStore.js
 * @description Pinia Store,用于管理应用程序的亮/暗主题模式。
 * 该 Store 会自动同步主题状态到 `<html>` 元素的 class 列表,并支持持久化。
 * @module ThemeStore
 */

import { defineStore } from 'pinia'
import { ref, watch } from 'vue'

/**
 * @function useThemeStore
 * @description Pinia Store,用于管理应用程序的亮/暗主题模式。
 * 它可以检测系统偏好,支持手动切换主题,并持久化主题状态。
 * @returns {{
 * isDarkMode: Ref<boolean>,
 * toggleTheme: Function,
 * initTheme: Function
 * }}
 * @property {Ref<boolean>} isDarkMode - 响应式布尔值,表示当前是否处于黑暗模式。
 * @property {Function} toggleTheme - 切换 `isDarkMode` 状态的函数。
 * @property {Function} initTheme - 初始化主题模式的函数,会检查 localStorage 和系统偏好。
 */
export const useThemeStore = defineStore(
  'theme',
  () => {
    // --- 状态 (State) ---
    /**
     * @type {Ref<boolean>}
     * @description 当前是否处于黑暗模式。
     */
    const isDarkMode = ref(false)

    // --- 监听器 (Watchers) ---

    /**
     * @watch isDarkMode
     * @description 监听 `isDarkMode` 状态的变化,并自动切换 `<html>` 元素的 'dark' class。
     * 这使得 CSS 可以根据这个 class 应用不同的主题样式。
     * `immediate: true` 确保在 Store 初始化时立即执行一次。
     * @param {boolean} val - `isDarkMode` 的新值。
     * @returns {void}
     */
    watch(
      isDarkMode,
      (val) => {
        document.documentElement.classList.toggle('dark', val)
      },
      { immediate: true }
    )

    // --- 操作 (Actions) ---

    /**
     * @function toggleTheme
     * @description 切换 `isDarkMode` 状态。
     * 如果当前是亮模式,则切换到暗模式;反之亦然。
     * @returns {void}
     */
    function toggleTheme() {
      isDarkMode.value = !isDarkMode.value
    }

    /**
     * @function initTheme
     * @description 初始化主题模式。
     * 如果 `localStorage` 中没有 'theme' 的值,则会检查用户的系统颜色偏好( prefers-color-scheme: dark )来设置初始主题。
     * 如果 `persist: true` 已启用,此函数通常会在 Pinia 恢复状态后运行。
     * @returns {void}
     */
    function initTheme() {
      // 检查 localStorage 是否有主题设置,如果没有则根据系统偏好设置
      if (
        typeof localStorage !== 'undefined' &&
        !localStorage.getItem('theme') // Pinia persist 会将 'theme' 存储在 'theme' key 下
      ) {
        isDarkMode.value = window.matchMedia(
          '(prefers-color-scheme: dark)'
        ).matches // 根据系统偏好设置初始模式
      }
    }

    // --- 返回 Store 的状态和操作 ---
    return { isDarkMode, toggleTheme, initTheme }
  },
  {
    // Pinia 持久化配置,将 Store 状态保存到 localStorage
    persist: true // 自动将 Store 状态持久化到本地存储
  }
)