fs-cell.vue 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. <template>
  2. <view class="fs-cell" :class="[cls, { shadow }]" :style="{ backgroundColor: bgColor }" @click="handleClick">
  3. <view class="fs-cell-flex" :class="['fs-cell-align-' + align, justify, { reverse }]">
  4. <view class="fs-cell-title" :class="{ 'fs-cell-required': required }" :style="titleStyle">
  5. <template v-if="title">
  6. {{ title }}
  7. </template>
  8. <slot v-else name="title"></slot>
  9. </view>
  10. <view class="fs-cell-value">
  11. <template v-if="value">
  12. {{ value }}
  13. </template>
  14. <slot v-else name="value"></slot>
  15. </view>
  16. <view class="fs-cell-extra">
  17. <template v-if="extra">
  18. {{ extra }}
  19. </template>
  20. <slot v-else name="extra"></slot>
  21. </view>
  22. </view>
  23. <view class="fs-cell-label">
  24. <template v-if="label">
  25. {{ label }}
  26. </template>
  27. <slot v-else name="label"></slot>
  28. </view>
  29. <view class="arrow-icon">
  30. <fs-icon type="icon-d-down" rotate="-90" size="28rpx" :color="arrowColor" :colorType="arrowColorType"></fs-icon>
  31. </view>
  32. </view>
  33. </template>
  34. <script>
  35. /**
  36. * 单元格组件
  37. * @description 单元格组件
  38. * @property {String} title 标题
  39. * @property {String} titleWidth 标题宽度
  40. * @property {String} value 值
  41. * @property {String} label 描述信息
  42. * @property {String} extra 额外信息
  43. * @property {Boolean} arrow 是否显示箭头
  44. * @property {String} arrowColor 箭头颜色
  45. * @property {String} arrowColorType = [primary | danger | warning | info | success] 箭头颜色类型
  46. * @property {Boolean} border 是否显示边框
  47. * @property {Boolean} shadow 是否显示阴影
  48. * @property {Boolean} tighten 是否紧凑
  49. * @property {Boolean} gutter 是否显示间距
  50. * @property {Boolean} radius 是否带圆角
  51. * @property {Boolean} reverse 是否翻转
  52. * @property {Boolean} required 是否必填配合表单使用
  53. * @property {String} bgColor 背景颜色
  54. * @property {String} align = [top | center | bottom | stretch] 垂直对齐方式
  55. * @property {String} justify = [left | center | right] 水平对齐方式
  56. * @property {String} link 跳转地址
  57. * @property {String} linkType 跳转类型
  58. */
  59. export default {
  60. name: 'fs-cell'
  61. }
  62. </script>
  63. <script setup>
  64. import { computed, toRefs, inject } from 'vue'
  65. const props = defineProps({
  66. title: String,
  67. titleWidth: String,
  68. value: String,
  69. extra: String,
  70. label: String,
  71. arrow: Boolean,
  72. arrowColor: {
  73. type: String,
  74. default: '#E8EAF2'
  75. },
  76. arrowColorType: {
  77. type: String,
  78. validator(value) {
  79. return ['primary', 'success', 'info', 'warning', 'danger'].includes(value)
  80. }
  81. },
  82. border: Boolean,
  83. tighten: Boolean,
  84. gutter: Boolean,
  85. radius: Boolean,
  86. reverse: Boolean,
  87. required: Boolean,
  88. align: {
  89. type: String,
  90. default: 'center',
  91. validator(value) {
  92. return ['top', 'center', 'bottom', 'stretch'].includes(value)
  93. }
  94. },
  95. justify: {
  96. type: String,
  97. validator(value) {
  98. return ['left', 'center', 'right'].includes(value)
  99. }
  100. },
  101. bgColor: {
  102. type: String
  103. },
  104. shadow: Boolean,
  105. link: String,
  106. linkType: {
  107. type: String,
  108. default: 'navigateTo'
  109. }
  110. })
  111. const emits = defineEmits(['click'])
  112. const cellGroup = inject('cellGroup', {})
  113. const justify = props.justify || cellGroup.justify || 'left'
  114. const bgColor = props.bgColor || cellGroup.bgColor || '#fff'
  115. const arrowColor = props.arrowColor || cellGroup.arrowColor
  116. const arrowColorType = props.arrowColorType || cellGroup.arrowColorType
  117. const cls = computed(() => {
  118. const classNames = []
  119. ;(props.arrow || cellGroup.arrow) && classNames.push('arrow')
  120. ;(props.border || cellGroup.border) && classNames.push('border')
  121. ;(props.tighten || cellGroup.tighten) && classNames.push('tighten')
  122. props.gutter && classNames.push('gutter')
  123. props.radius && classNames.push('radius')
  124. return classNames.join(' ')
  125. })
  126. const titleStyle = computed(() => {
  127. const width = props.titleWidth || cellGroup.titleWidth
  128. return width ? `width: ${width}` : ''
  129. })
  130. const handleClick = () => {
  131. if (props.link) {
  132. uni[props.linkType]({
  133. url: props.link
  134. })
  135. }
  136. emits('click')
  137. }
  138. </script>
  139. <style lang="scss" scoped>
  140. .fs-cell {
  141. padding: 30rpx var(--gutter);
  142. position: relative;
  143. font-size: var(--content-size);
  144. background-color: #fff;
  145. line-height: 1.4;
  146. width: 100%;
  147. box-sizing: border-box;
  148. &-flex {
  149. display: flex;
  150. justify-content: space-between;
  151. }
  152. &-value {
  153. flex: 1;
  154. padding-left: 20rpx;
  155. text-align: right;
  156. }
  157. &-label {
  158. font-size: var(--sub-size);
  159. color: var(--sub);
  160. }
  161. &-align-top {
  162. align-items: flex-start;
  163. }
  164. &-align-center {
  165. align-items: center;
  166. }
  167. &-align-bottom {
  168. align-items: flex-end;
  169. }
  170. &.arrow {
  171. padding-right: 50rpx;
  172. .arrow-icon {
  173. display: block;
  174. }
  175. }
  176. &-required {
  177. position: relative;
  178. padding-left: 7px;
  179. &::before {
  180. position: absolute;
  181. content: '*';
  182. color: red;
  183. left: 0;
  184. }
  185. }
  186. &.gutter {
  187. margin-bottom: var(--gutter-v);
  188. }
  189. &.radius {
  190. border-radius: var(--radius);
  191. }
  192. &.reverse {
  193. flex-direction: row-reverse;
  194. }
  195. &.tighten {
  196. padding: var(--tighten-gutter);
  197. }
  198. &.border {
  199. border-bottom: 2rpx solid var(--border-color);
  200. }
  201. }
  202. .arrow-icon {
  203. display: none;
  204. position: absolute;
  205. right: 10rpx;
  206. top: 50%;
  207. transform: translateY(-50%);
  208. }
  209. .left .fs-cell-value {
  210. text-align: left;
  211. }
  212. .center .fs-cell-value {
  213. text-align: center;
  214. }
  215. .right .fs-cell-value {
  216. text-align: right;
  217. }
  218. </style>