tm-steps.vue 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. <template>
  2. <view class="tm-steps" v-if="listLen>0">
  3. <block v-for="(item,index) in list" :key="index">
  4. <view class="tm-steps-item" :style="{
  5. width:(100/listLen)+'%'
  6. }">
  7. <view class="tm-steps-item-text flex-center flex-col ">
  8. <view :style="{
  9. width:sizePx + 'px',
  10. height:sizePx + 'px',
  11. lineHeight:0
  12. }" :class="[
  13. index < value ? color_tmeme:'grey-lighten-4',
  14. black_tmeme?'bk':'',
  15. index < value?`shadow-${color_tmeme}-3`:''
  16. ]" @click.stop="itemclick(index)" class="tm-steps-item-text-icon rounded text-size-s flex-center ">
  17. <block v-if="model=='number'">
  18. <slot name="number"
  19. :data="{icon:icon,activeIcon:activeIcon,index:index+1,active:index < value?true:false}">
  20. <text :class="index < value ? '':'text-'+fontColor">{{index+1}}</text>
  21. </slot>
  22. </block>
  23. <block v-if="model=='icon'">
  24. <slot name="icon"
  25. :data="{icon:icon,activeIcon:activeIcon,index:index+1,active:index < value?true:false}">
  26. <tm-icons style="line-height: 0;" :color="fontColor" size="22" v-if="index >= value" :name="icon"></tm-icons>
  27. <tm-icons style="line-height: 0;" color="white" size="22" v-if="index < value" :name="activeIcon"></tm-icons>
  28. </slot>
  29. </block>
  30. </view>
  31. <view :class="[
  32. index < value ? `text-${activeFontColor_theme}`:`text-${fontColor}`,
  33. ]" class="tm-steps-item-text-icon-label text-size-s text-align-center px-10 py-16">
  34. <slot name="default" :data="item">
  35. {{item[rangeKey]?item[rangeKey]:item}}
  36. </slot>
  37. </view>
  38. </view>
  39. <view :style="{
  40. width:` calc(100% - ${sizePx}px)`,
  41. height:sizePx+'px',
  42. top:`0`,
  43. left: `calc(50% + ${sizePx/2}px)`,
  44. }" v-if="index!==listLen-1" class="tm-steps-item-driver flex-center">
  45. <!-- <tm-icons color="white" size="22" name="icon-angle-right"></tm-icons> -->
  46. <view class="fulled flex-center"
  47. :style="{borderTopStyle:lineStyle,borderTopWidth:lineWidth+'rpx',height:'1px'}"
  48. :class="[index < value ? `border-${lineColor_theme}-t-1`:black_tmeme?'border-grey-darken-4-t-1':'border-grey-lighten-4-t-1']">
  49. <view style="line-height: 0;">
  50. <tm-icons v-if="lineInIcon" style="line-height: 0;" dense :color="index < value ? color_tmeme:'grey-lighten-4'" :black="black_tmeme" size="22" :name="lineInIcon"></tm-icons>
  51. </view>
  52. </view>
  53. </view>
  54. </view>
  55. </block>
  56. </view>
  57. </template>
  58. <script>
  59. /**
  60. * 步骤条
  61. * @description 只能搭配tm-stepsItem组件使用。内部需要放入:tm-stepsItem组件。
  62. * @property {Number} value = [] 默认:1,当前第几步同步需要valu.snyc 推荐使用v-model.
  63. * @property {Boolean} black = [true|false] 默认:false,暗黑模式。
  64. * @property {String} model = [number|icon] 默认:number,两种模式,number:数字,icon:图标模式。
  65. * @property {String} color = [] 默认:primary,主题色。
  66. * @property {String} range-key = [] 默认:text,数据为对象数组时,需要提供对应的文字key。
  67. * @property {String} size = [] 默认:42,节点大小。
  68. * @property {String} line-color = [] 默认:primary,激活时的线条主题色。
  69. * @property {String} font-color = [] 默认:grey,文字主题色。
  70. * @property {String} active-font-color = [] 默认:primary,激活后的文字主题色。
  71. * @property {String} active-icon = [] 默认:icon-check,激活后的图标。
  72. * @property {String} icon = [] 默认:icon-clock-fill,未激活的图标。
  73. * @property {String} lineInIcon = [] 默认:'',节点间线中间内部的图标,填写后显示,不填写不显示。
  74. * @property {String} lineStyle = [] 默认:solid,标准的css边线类型
  75. * @property {String} lineWidth = [] 默认:1,连接线的厚度,单位rpx
  76. * @property {Function} input 等同v-model参数
  77. * @property {Function} change 步骤变化时触发。等同input,v-model参数
  78. * @property {Function} click 点击步骤节点时触发,返回当前步骤位置。
  79. * @example <tm-steps v-model="star"><block v-for="(item,index) in 4" :key="index"><tm-stepsItem :fail="index+1==3" model="icon" :step="index+1"></tm-stepsItem><tm-divider :color="index > star-1 ? '#eeeeee':'#1976d2'" v-if="index!==3" ></tm-divider></block></tm-steps>
  80. */
  81. import tmIcons from "@/tm-vuetify/components/tm-icons/tm-icons.vue"
  82. export default {
  83. components: {
  84. tmIcons
  85. },
  86. name: "tm-steps",
  87. model: {
  88. prop: "value",
  89. event: "input"
  90. },
  91. props: {
  92. value: {
  93. type: Number,
  94. default: 1
  95. },
  96. list: {
  97. type: Array,
  98. default: () => {
  99. return []
  100. }
  101. },
  102. rangeKey: {
  103. type: String,
  104. default: 'text'
  105. },
  106. // 主题色。
  107. color: {
  108. type: String,
  109. default: 'primary'
  110. },
  111. // 激活时的颜色值,16进制。
  112. lineColor: {
  113. type: String,
  114. default: 'primary'
  115. },
  116. lineStyle:{
  117. type:String,
  118. default:'solid',//solid,dashed
  119. },
  120. lineWidth:{
  121. type:String|Number,
  122. default:1,
  123. },
  124. //显示线上面的图标
  125. lineInIcon:{
  126. type:String,
  127. default:'',
  128. },
  129. fontColor: {
  130. type: String,
  131. default: 'grey'
  132. },
  133. activeFontColor: {
  134. type: String,
  135. default: 'primary'
  136. },
  137. model: {
  138. type: String,
  139. default: 'icon'
  140. },
  141. black: {
  142. type: Boolean | String,
  143. default: null
  144. },
  145. size: {
  146. type: Number,
  147. default: 46
  148. },
  149. icon: {
  150. type: String,
  151. default: 'icon-clock-fill'
  152. },
  153. activeIcon: {
  154. type: String,
  155. default: 'icon-check'
  156. },
  157. // 跟随主题色的改变而改变。
  158. fllowTheme: {
  159. type: Boolean | String,
  160. default: true
  161. },
  162. },
  163. data() {
  164. return {
  165. };
  166. },
  167. computed: {
  168. black_tmeme: function() {
  169. if (this.black !== null) return this.black;
  170. return this.$tm.vx.state().tmVuetify.black;
  171. },
  172. color_tmeme: function() {
  173. if (this.$tm.vx.state().tmVuetify.color !== null && this.$tm.vx.state().tmVuetify.color && this
  174. .fllowTheme) {
  175. return this.$tm.vx.state().tmVuetify.color;
  176. }
  177. return this.color;
  178. },
  179. lineColor_theme: function() {
  180. if (this.$tm.vx.state().tmVuetify.color !== null && this.$tm.vx.state().tmVuetify.color && this
  181. .fllowTheme) {
  182. return this.$tm.vx.state().tmVuetify.color;
  183. }
  184. return this.lineColor;
  185. },
  186. activeFontColor_theme: function() {
  187. if (this.$tm.vx.state().tmVuetify.color !== null && this.$tm.vx.state().tmVuetify.color && this
  188. .fllowTheme) {
  189. return this.$tm.vx.state().tmVuetify.color;
  190. }
  191. return this.activeFontColor;
  192. },
  193. listLen: function() {
  194. if (!Array.isArray(this.list)) return 0;
  195. return this.list.length;
  196. },
  197. sizePx: function() {
  198. return uni.upx2px(this.size);
  199. }
  200. },
  201. watch: {
  202. value: async function() {
  203. let bz = this.value;
  204. if (this.value > this.listLen || this.value < 0) {
  205. bz = 0
  206. }
  207. if (this.value == this.listLen - 1) {
  208. bz = this.listLen - 1
  209. }
  210. await this.setActive(bz);
  211. }
  212. },
  213. async mounted() {
  214. this.UpdateItem();
  215. },
  216. methods: {
  217. //如果需要动态插入步骤,需要调用此函数更新。
  218. async UpdateItem() {
  219. await this.setActive(this.value)
  220. },
  221. async setActive(index) {
  222. this.$emit("input", index)
  223. this.$emit("change", index)
  224. this.$emit("update:value", index)
  225. },
  226. itemclick(index) {
  227. this.$emit('click', index + 1)
  228. }
  229. },
  230. }
  231. </script>
  232. <style lang="scss" scoped>
  233. .tm-steps {
  234. display: flex;
  235. justify-content: space-between;
  236. align-items: flex-start;
  237. // border-style: dashed;
  238. .tm-steps-item {
  239. position: relative;
  240. .tm-steps-item-text {
  241. .tm-steps-item-text-icon {}
  242. }
  243. .tm-steps-item-driver {
  244. position: absolute;
  245. }
  246. }
  247. }
  248. </style>