uno.config.ts 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*
  2. * @Author: wjc
  3. * @Date: 2023-05-07 20:59:28
  4. * @LastEditors: LiZhiWei
  5. * @LastEditTime: 2026-01-19 09:29:31
  6. * @Description:
  7. */
  8. import {
  9. defineConfig,
  10. presetUno,
  11. presetIcons,
  12. transformerDirectives,
  13. transformerVariantGroup,
  14. } from 'unocss'
  15. import { FileSystemIconLoader } from '@iconify/utils/lib/loader/node-loaders'
  16. import iconList from './app/utils/icons'
  17. export default defineConfig({
  18. presets: [
  19. presetUno(),
  20. presetIcons({
  21. scale: 1.2,
  22. extraProperties: {
  23. display: 'inline-block',
  24. },
  25. // cdn: 'https://esm.sh/'
  26. collections: {
  27. custom: FileSystemIconLoader('./app/assets/icons'),
  28. ep: () => import('@iconify-json/ep/icons.json').then((i) => i.default),
  29. },
  30. }),
  31. ],
  32. postprocess: (util) => {
  33. const pxRE = /(-?[\d.]+px)/g
  34. // 检查选择器是否包含移动端变体(lt-sm, lt-xs)
  35. const isMobile = util.selector.includes('lt-sm') || util.selector.includes('lt-xs')
  36. if (isMobile) {
  37. util.entries.forEach((i) => {
  38. const value = i[1]
  39. if (typeof value === 'string' && pxRE.test(value)) {
  40. // 移动端:按 750px 设计稿转换 (px / 7.5)
  41. i[1] = value.replace(pxRE, (match) => {
  42. const px = parseFloat(match)
  43. if (isNaN(px)) return match
  44. return `${(px / 7.5).toFixed(5)}vw`
  45. })
  46. }
  47. })
  48. }
  49. },
  50. transformers: [transformerDirectives(), transformerVariantGroup()],
  51. postprocess: (util) => {
  52. const pxRE = /(-?[\d.]+px)/g
  53. // 检查是否属于移动端变体(通过选择器或媒体查询父级判断)
  54. const isMobile =
  55. util.selector.includes('lt-sm') ||
  56. util.selector.includes('lt-xs') ||
  57. (util.parent?.includes('max-width: 767') ?? false) ||
  58. (util.parent?.includes('max-width: 479') ?? false)
  59. if (isMobile) {
  60. util.entries.forEach((i) => {
  61. const value = i[1]
  62. if (typeof value === 'string' && pxRE.test(value)) {
  63. // 移动端:强制按 750px 设计稿转换 (px / 7.5)
  64. i[1] = value.replace(pxRE, (match) => {
  65. const px = parseFloat(match)
  66. if (isNaN(px)) return match
  67. return `${(px / 7.5).toFixed(5)}vw`
  68. })
  69. }
  70. })
  71. } else {
  72. // PC 端逻辑:如果你希望 PC 端也转换(按 1920),取消下面注释
  73. /*
  74. util.entries.forEach((i) => {
  75. const value = i[1]
  76. if (typeof value === 'string' && pxRE.test(value)) {
  77. i[1] = value.replace(pxRE, (match) => {
  78. const px = parseFloat(match)
  79. return `${(px / 19.2).toFixed(5)}vw`
  80. })
  81. }
  82. })
  83. */
  84. }
  85. },
  86. rules: [
  87. [/^m-h-(.+)$/, ([, d]) => ({ 'margin-left': `${d}`, 'margin-right': `${d}` })],
  88. [/^m-v-(.+)$/, ([, d]) => ({ 'margin-top': `${d}`, 'margin-bottom': `${d}` })],
  89. [/^p-h-(.+)$/, ([, d]) => ({ 'padding-left': `${d}`, 'padding-right': `${d}` })],
  90. [/^p-v-(.+)$/, ([, d]) => ({ 'padding-top': `${d}`, 'padding-bottom': `${d}` })],
  91. [/^max-w-(\s+)$/, ([, d]) => ({ 'max-width': `${d}` })],
  92. [/^min-w-(\s+)$/, ([, d]) => ({ 'min-width': `${d}` })],
  93. [/^max-h-[(\s+)]$/, ([, d]) => ({ 'max-height': `${d}` })],
  94. [/^min-h-[(\s+)]$/, ([, d]) => ({ 'min-height': `${d}` })],
  95. [/^font-s-(\d+(\.\d+)?\w+)$/, ([, d]) => ({ 'font-size': `${d}` })],
  96. [/^wh-(.+)$/, ([, d]) => ({ width: `${d}`, height: `${d}` })],
  97. [/^bg-color-(\d+)$/, ([, d]) => ({ 'background-color': `${d}` })],
  98. ],
  99. safelist: iconList,
  100. shortcuts: {
  101. 'wh-full': 'w-full h-full',
  102. 'mp-0': 'm-0 p-0',
  103. 'ma-x': 'mt-0 mb-0 ml-auto mr-auto',
  104. 'inline-flex-center': 'inline-flex justify-center items-center',
  105. 'flex-center': 'flex justify-center items-center',
  106. 'flex-x-center': 'flex justify-center',
  107. 'flex-y-center': 'flex items-center',
  108. // 文本溢出显示省略号
  109. 'text-overflow': 'overflow-hidden whitespace-nowrap text-ellipsis',
  110. // 文本溢出换行
  111. 'text-break': 'whitespace-normal break-all break-words',
  112. },
  113. theme: {
  114. breakpoints: {
  115. xs: '480px',
  116. sm: '768px',
  117. md: '992px',
  118. lg: '1200px',
  119. xl: '1920px',
  120. xxl: '3840px',
  121. },
  122. colors: {
  123. primary: 'var(--primary-color)',
  124. 'primary-2': 'var(--primary-color-2)',
  125. success: 'var(--success-color)',
  126. warning: 'var(--warning-color)',
  127. danger: 'var(--danger-color)',
  128. error: 'var(--error-color)',
  129. info: 'var(--info-color)',
  130. color: {
  131. '1': 'var(--text-color-1)',
  132. '2': 'var(--text-color-2)',
  133. '3': 'var(--text-color-3)',
  134. 4: 'var(--bg-color-4)',
  135. place: 'var(--text-color-place)',
  136. disabled: 'var(--text-color-disabled)',
  137. whiter: 'var(--text-color-whiter)',
  138. },
  139. bg: {
  140. color: 'var(--bg-color)',
  141. 1: 'var(--bg-color-1)',
  142. 2: 'var(--bg-color-2)',
  143. 3: 'var(--bg-color-3)',
  144. 4: 'var(--bg-color-4)',
  145. page: 'var(--bg-page)',
  146. place: 'var(--text-color-place)',
  147. divider: 'var(--bg-divider)',
  148. overlay: 'var(--bg-overlay)',
  149. primary: 'var(--primary-color)',
  150. },
  151. },
  152. },
  153. })