You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

320 lines
7.7 KiB

4 months ago
  1. <template>
  2. <view class="u-steps-item" ref="u-steps-item" :class="[`u-steps-item--${parentData.direction}`]">
  3. <view class="u-steps-item__line" v-if="index + 1 < childLength"
  4. :class="[`u-steps-item__line--${parentData.direction}`]" :style="[lineStyle]"></view>
  5. <view class="u-steps-item__wrapper"
  6. :class="[`u-steps-item__wrapper--${parentData.direction}`, parentData.dot && `u-steps-item__wrapper--${parentData.direction}--dot`]">
  7. <slot name="icon">
  8. <view class="u-steps-item__wrapper__dot" v-if="parentData.dot" :style="{
  9. backgroundColor: statusColor
  10. }">
  11. </view>
  12. <view class="u-steps-item__wrapper__icon" v-else-if="parentData.activeIcon || parentData.inactiveIcon">
  13. <u-icon :name="index <= parentData.current ? parentData.activeIcon : parentData.inactiveIcon"
  14. :size="iconSize"
  15. :color="index <= parentData.current ? parentData.activeColor : parentData.inactiveColor">
  16. </u-icon>
  17. </view>
  18. <view v-else :style="{
  19. backgroundColor: statusClass === 'process' ? parentData.activeColor : 'transparent',
  20. borderColor: statusColor
  21. }" class="u-steps-item__wrapper__circle">
  22. <text v-if="statusClass === 'process' || statusClass === 'wait'"
  23. class="u-steps-item__wrapper__circle__text" :style="{
  24. color: index == parentData.current ? '#ffffff' : parentData.inactiveColor
  25. }">{{ index + 1}}</text>
  26. <u-icon v-else :color="statusClass === 'error' ? 'error' : parentData.activeColor" size="12"
  27. :name="statusClass === 'error' ? 'close' : 'checkmark'"></u-icon>
  28. </view>
  29. </slot>
  30. </view>
  31. <view class="u-steps-item__content" :class="[`u-steps-item__content--${parentData.direction}`]"
  32. :style="[contentStyle]">
  33. <up-text :text="title" :type="parentData.current == index ? 'main' : 'content'" lineHeight="20px"
  34. :size="parentData.current == index ? 14 : 13"></up-text>
  35. <slot name="desc">
  36. <up-text :text="desc" type="tips" size="12"></up-text>
  37. </slot>
  38. </view>
  39. <!-- <view
  40. class="u-steps-item__line"
  41. v-if="showLine && parentData.direction === 'column'"
  42. :class="[`u-steps-item__line--${parentData.direction}`]"
  43. :style="[lineStyle]"
  44. ></view> -->
  45. </view>
  46. </template>
  47. <script>
  48. import { props } from './props';
  49. import { mpMixin } from '../../libs/mixin/mpMixin';
  50. import { mixin } from '../../libs/mixin/mixin';
  51. import { sleep, error } from '../../libs/function/index';
  52. import color from '../../libs/config/color';
  53. // #ifdef APP-NVUE
  54. const dom = uni.requireNativePlugin('dom')
  55. // #endif
  56. /**
  57. * StepsItem 步骤条的子组件
  58. * @description 本组件需要和u-steps配合使用
  59. * @tutorial https://uview-plus.jiangruyi.com/components/steps.html
  60. * @property {String} title 标题文字
  61. * @property {String} current 描述文本
  62. * @property {String | Number} iconSize 图标大小 (默认 17 )
  63. * @property {Boolean} error 当前步骤是否处于失败状态 (默认 false )
  64. * @example <u-steps current="0"><u-steps-item title="已出库" desc="10:35" ></u-steps-item></u-steps>
  65. */
  66. export default {
  67. name: 'u-steps-item',
  68. mixins: [mpMixin, mixin, props],
  69. data() {
  70. return {
  71. index: 0,
  72. childLength: 0,
  73. showLine: false,
  74. size: {
  75. height: 0,
  76. width: 0
  77. },
  78. parentData: {
  79. direction: 'row',
  80. current: 0,
  81. activeColor: '',
  82. inactiveColor: '',
  83. activeIcon: '',
  84. inactiveIcon: '',
  85. dot: false
  86. }
  87. }
  88. },
  89. watch: {
  90. 'parentData'(newValue, oldValue) {
  91. }
  92. },
  93. created() {
  94. this.init()
  95. },
  96. computed: {
  97. lineStyle() {
  98. const style = {}
  99. if (this.parentData.direction === 'row') {
  100. style.width = this.size.width + 'px'
  101. style.left = this.size.width / 2 + 'px'
  102. } else {
  103. style.height = this.size.height + 'px'
  104. // style.top = this.size.height / 2 + 'px'
  105. }
  106. style.backgroundColor = this.parent.children?.[this.index + 1]?.error ? color.error : this.index <
  107. this
  108. .parentData
  109. .current ? this.parentData.activeColor : this.parentData.inactiveColor
  110. return style
  111. },
  112. statusClass() {
  113. const {
  114. index,
  115. error
  116. } = this
  117. const {
  118. current
  119. } = this.parentData
  120. if (current == index) {
  121. return error === true ? 'error' : 'process'
  122. } else if (error) {
  123. return 'error'
  124. } else if (current > index) {
  125. return 'finish'
  126. } else {
  127. return 'wait'
  128. }
  129. },
  130. statusColor() {
  131. let colorTmp = ''
  132. switch (this.statusClass) {
  133. case 'finish':
  134. colorTmp = this.parentData.activeColor
  135. break
  136. case 'error':
  137. colorTmp = color.error
  138. break
  139. case 'process':
  140. colorTmp = this.parentData.dot ? this.parentData.activeColor : 'transparent'
  141. break
  142. default:
  143. colorTmp = this.parentData.inactiveColor
  144. break
  145. }
  146. return colorTmp
  147. },
  148. contentStyle() {
  149. const style = {}
  150. if (this.parentData.direction === 'column') {
  151. style.marginLeft = this.parentData.dot ? '2px' : '6px'
  152. style.marginTop = this.parentData.dot ? '0px' : '6px'
  153. } else {
  154. style.marginTop = this.parentData.dot ? '2px' : '6px'
  155. style.marginLeft = this.parentData.dot ? '2px' : '6px'
  156. }
  157. return style
  158. }
  159. },
  160. mounted() {
  161. this.parent && this.parent.updateFromChild()
  162. sleep().then(() => {
  163. this.getStepsItemRect()
  164. })
  165. },
  166. methods: {
  167. init() {
  168. // 初始化数据
  169. this.updateParentData()
  170. if (!this.parent) {
  171. return error('u-steps-item必须要搭配u-steps组件使用')
  172. }
  173. this.index = this.parent.children.indexOf(this)
  174. this.childLength = this.parent.children.length
  175. },
  176. updateParentData() {
  177. // 此方法在mixin中
  178. this.getParentData('u-steps')
  179. },
  180. // 父组件数据发生变化
  181. updateFromParent() {
  182. this.init()
  183. },
  184. // 获取组件的尺寸,用于设置横线的位置
  185. getStepsItemRect() {
  186. // #ifndef APP-NVUE
  187. this.$uGetRect('.u-steps-item').then(size => {
  188. this.size = size
  189. })
  190. // #endif
  191. // #ifdef APP-NVUE
  192. dom.getComponentRect(this.$refs['u-steps-item'], res => {
  193. const {
  194. size
  195. } = res
  196. this.size = size
  197. })
  198. // #endif
  199. }
  200. }
  201. }
  202. </script>
  203. <style lang="scss" scoped>
  204. @import "../../libs/css/components.scss";
  205. .u-steps-item {
  206. flex: 1;
  207. @include flex;
  208. &--row {
  209. flex-direction: column;
  210. align-items: center;
  211. position: relative;
  212. }
  213. &--column {
  214. position: relative;
  215. flex-direction: row;
  216. justify-content: flex-start;
  217. padding-bottom: 5px;
  218. }
  219. &__wrapper {
  220. @include flex;
  221. justify-content: center;
  222. align-items: center;
  223. position: relative;
  224. background-color: #fff;
  225. &--column {
  226. width: 20px;
  227. height: 32px;
  228. &--dot {
  229. height: 20px;
  230. width: 20px;
  231. }
  232. }
  233. &--row {
  234. width: 32px;
  235. height: 20px;
  236. &--dot {
  237. width: 20px;
  238. height: 20px;
  239. }
  240. }
  241. &__circle {
  242. width: 20px;
  243. height: 20px;
  244. /* #ifndef APP-NVUE */
  245. box-sizing: border-box;
  246. flex-shrink: 0;
  247. /* #endif */
  248. border-radius: 100px;
  249. border-width: 1px;
  250. border-color: $u-tips-color;
  251. border-style: solid;
  252. @include flex(row);
  253. align-items: center;
  254. justify-content: center;
  255. transition: background-color 0.3s;
  256. &__text {
  257. color: $u-tips-color;
  258. font-size: 11px;
  259. @include flex(row);
  260. align-items: center;
  261. justify-content: center;
  262. text-align: center;
  263. line-height: 11px;
  264. }
  265. }
  266. &__dot {
  267. width: 10px;
  268. height: 10px;
  269. border-radius: 100px;
  270. background-color: $u-content-color;
  271. }
  272. }
  273. &__content {
  274. @include flex;
  275. flex: 1;
  276. &--row {
  277. flex-direction: column;
  278. align-items: center;
  279. }
  280. &--column {
  281. flex-direction: column;
  282. margin-left: 6px;
  283. }
  284. }
  285. &__line {
  286. position: absolute;
  287. background: $u-tips-color;
  288. &--row {
  289. top: 10px;
  290. height: 1px;
  291. }
  292. &--column {
  293. width: 1px;
  294. left: 10px;
  295. }
  296. }
  297. }
  298. </style>