useWidgetStyle.ts 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. import componentMap from '..'
  2. import { getImageByPath } from '@/utils'
  3. import { useProjectStore } from '@/store/modules/project'
  4. import { assign } from 'lodash-es'
  5. import { ref, watch } from 'vue'
  6. import type { IStyleConfig } from '../type'
  7. import type { CSSProperties } from 'vue'
  8. type StyleParam = {
  9. widget: keyof typeof componentMap
  10. props: {
  11. part?: string
  12. state?: string
  13. styles: IStyleConfig[]
  14. [key: string]: any
  15. }
  16. }
  17. type StyleMap = Record<
  18. string,
  19. CSSProperties & { imageSrc?: string; imageColorStyle?: CSSProperties }
  20. >
  21. /**
  22. * 获取样式
  23. * @param key
  24. * @param value
  25. * @returns
  26. */
  27. export const getStyle = (key, value) => {
  28. const style: CSSProperties = {}
  29. switch (key) {
  30. // 背景样式
  31. case 'background': {
  32. style.backgroundColor = value?.color
  33. break
  34. }
  35. // 文字样式
  36. case 'text': {
  37. style.color = value?.color
  38. style.fontSize = `${value?.size}px`
  39. style.fontFamily = value?.family
  40. style.textAlign = value?.align
  41. style.fontWeight = value?.weight === 'bold' ? 'bold' : 'normal'
  42. style.fontStyle = value?.italic ? 'italic' : 'normal'
  43. style.textDecoration = value?.strike
  44. ? 'line-through'
  45. : value?.underline
  46. ? 'underline'
  47. : 'none'
  48. break
  49. }
  50. // 边框样式
  51. case 'border': {
  52. style.borderColor = 'transparent'
  53. style.borderWidth = 0
  54. style.borderRadius = `${value?.radius}px`
  55. style.borderStyle = 'solid'
  56. if (value?.side?.includes('all') || value?.side?.includes('top')) {
  57. style.borderTopColor = value?.color
  58. style.borderTopWidth = `${value?.width || 0}px`
  59. }
  60. if (value?.side?.includes('all') || value?.side?.includes('right')) {
  61. style.borderRightColor = value?.color
  62. style.borderRightWidth = `${value?.width || 0}px`
  63. }
  64. if (value?.side?.includes('all') || value?.side?.includes('bottom')) {
  65. style.borderBottomColor = value?.color
  66. style.borderBottomWidth = `${value?.width || 0}px`
  67. }
  68. if (value?.side?.includes('all') || value?.side?.includes('left')) {
  69. style.borderLeftColor = value?.color
  70. style.borderLeftWidth = `${value?.width || 0}px`
  71. }
  72. break
  73. }
  74. // 外边框样式
  75. case 'outline': {
  76. style.outlineColor = value?.color
  77. style.outlineWidth = `${value?.width}px`
  78. style.outlineStyle = 'solid'
  79. break
  80. }
  81. // 阴影样式
  82. case 'shadow': {
  83. style.boxShadow = `${value?.x}px ${value?.y}px ${value?.width}px ${value?.spread}px ${value?.color}`
  84. break
  85. }
  86. // 内边距样式
  87. case 'padding': {
  88. style.padding = `${value?.top || 0}px ${value?.right || 0}px ${value?.bottom || 0}px ${value?.left || 0}px`
  89. if (value?.row) {
  90. style.rowGap = `${value?.row}px`
  91. }
  92. if (value?.column) {
  93. style.columnGap = `${value?.column}px`
  94. }
  95. break
  96. }
  97. // 外边距样式
  98. case 'margin': {
  99. style.margin = `${value?.top || 0}px ${value?.right || 0}px ${value?.bottom || 0}px ${value?.left || 0}px`
  100. break
  101. }
  102. // 间距样式
  103. case 'spacer': {
  104. style.letterSpacing = `${value?.letterSpacing}px`
  105. break
  106. }
  107. }
  108. return style
  109. }
  110. /**
  111. * 根据控件part、state获取控件样式
  112. * @param param - StyleParam
  113. * @returns
  114. */
  115. export const useWidgetStyle = (param: StyleParam) => {
  116. const projectStore = useProjectStore()
  117. const widget = param.widget
  118. // 全局默认样式
  119. const defaultStyle = componentMap[widget]?.defaultStyle
  120. // 控件模块状态
  121. const parts = componentMap[widget].parts
  122. // 控件样式集合
  123. const styleMap = ref<StyleMap>({})
  124. const handleStyle = () => {
  125. const { part, state, styles = [] } = param.props
  126. parts.forEach((partItem) => {
  127. styleMap.value[`${partItem.name}Style`] = {}
  128. // 从控件配置的样式列表查找对应样式
  129. let style = styles.find(
  130. // part为当前part时,根据state获取 否则取第一个state样式
  131. (s) =>
  132. s.part?.name === partItem.name &&
  133. s.part?.state === (part === partItem.name ? state : partItem.stateList?.[0])
  134. )
  135. // 配置样式未配置时,从默认样式中获取
  136. if (!style) {
  137. style = defaultStyle?.part
  138. ?.find((item) => item.partName === partItem.name)
  139. ?.state?.find(
  140. (s) => s.state === (part === partItem.name ? state : partItem.stateList?.[0])
  141. )?.style
  142. }
  143. // 遍历style 获取样式
  144. Object.keys(style || {}).forEach((key) => {
  145. // 合并样式
  146. assign(styleMap.value[`${partItem.name}Style`], getStyle(key, style?.[key]))
  147. // 获取背景图片src及颜色
  148. if (key === 'background' && style?.[key]?.image?.imgId) {
  149. const basePath = projectStore?.project?.meta.path
  150. const imagePath = projectStore?.project?.resources.images.find(
  151. (item) => item.id === style?.[key]?.image?.imgId
  152. )?.path
  153. if (basePath && imagePath) {
  154. getImageByPath(basePath + imagePath).then((res) => {
  155. if (res?.base64) {
  156. styleMap.value[`${partItem.name}Style`].imageSrc = res.base64
  157. styleMap.value[`${partItem.name}Style`].imageColorStyle = {
  158. background: style?.[key]?.image?.color
  159. }
  160. }
  161. })
  162. }
  163. }
  164. })
  165. // 处理行高 默认行高为1.2倍
  166. if (style?.spacer?.lineHeight && style?.text?.size) {
  167. const baseHeight = style.text.size * 1.2
  168. styleMap.value[`${partItem.name}Style`].lineHeight =
  169. `${baseHeight + style.spacer.lineHeight}px`
  170. }
  171. })
  172. }
  173. watch(() => param.props, handleStyle, {
  174. deep: true,
  175. immediate: true
  176. })
  177. return styleMap
  178. }