ailu 4 年 前
コミット
e26278d3c3

+ 18 - 0
src/config.json

@@ -373,6 +373,24 @@
           "sort": 16,
           "show": true,
           "author": "Drjingfubo"
+        },
+        {
+          "name": "Steps",
+          "sort": 17,
+          "cName": "步骤条",
+          "type": "component",
+          "show": true,
+          "desc": "步骤条",
+          "author": "ailululu"
+        },
+        {
+          "name": "Step",
+          "sort": 17,
+          "cName": "步骤条子组件",
+          "type": "component",
+          "show": false,
+          "desc": "步骤条子组件",
+          "author": "ailululu"
         }
       ]
     },

+ 24 - 0
src/packages/step/demo.vue

@@ -0,0 +1,24 @@
+<template>
+  <div class="demo">
+    <h2>基本用法</h2>
+    <nut-steps> </nut-steps>
+  </div>
+</template>
+
+<script lang="ts">
+import { createComponent } from '@/utils/create';
+const { createDemo } = createComponent('steps');
+export default createDemo({
+  props: {},
+  setup() {
+    return {
+      // ...toRefs(state)
+    };
+  }
+});
+</script>
+
+<style lang="scss" scoped>
+.demo-box {
+}
+</style>

+ 124 - 0
src/packages/step/index.scss

@@ -0,0 +1,124 @@
+.nut-step {
+  flex-grow: 0;
+  flex-shrink: 0;
+  flex-basis: 33.34%;
+  text-align: center;
+  font-size: 0;
+  &-head {
+    position: relative;
+    display: block;
+    margin-bottom: 10px;
+  }
+  &-line {
+    position: absolute;
+    top: 11px;
+    left: 50%;
+    right: -50%;
+    display: inline-block;
+    height: 1px;
+    background: #909ca4;
+  }
+  &-icon {
+    position: relative;
+    display: inline-block;
+    width: 25px;
+    height: 25px;
+    line-height: 25px;
+    font-family: PingFangSC-Medium;
+    font-size: 13px;
+    // border-color: #909CA4;
+    z-index: 1;
+    &.is-text {
+      border-radius: 50%;
+      border-width: 1px;
+      border-style: solid;
+    }
+  }
+  &-inner {
+  }
+  &-main {
+    display: inline-block;
+    padding-left: 10%;
+    padding-right: 10%;
+    text-align: center;
+  }
+  &-title {
+    display: block;
+    margin-bottom: 10px;
+    font-size: 14px;
+    color: #909ca4;
+  }
+  &-content {
+    display: block;
+    font-size: 14px;
+    color: #666;
+  }
+  &:last-child {
+    .nut-step-line {
+      display: none;
+    }
+  }
+  &.nut-step-finish {
+    .nut-step-head {
+      color: #3790ff;
+      border-color: #3790ff;
+    }
+    .nut-step-icon.is-text {
+      background-color: #fff;
+    }
+    .nut-step-line {
+      background: #3790ff;
+    }
+  }
+  &.nut-step-process {
+    .nut-step-head {
+      color: #fff;
+      border-color: #3790ff;
+    }
+    .nut-step-icon.is-text {
+      background-color: #3790ff;
+    }
+    .nut-step-line {
+      background: #3790ff;
+    }
+  }
+  &.nut-step-wait {
+    .nut-step-head {
+      color: #909ca4;
+      border-color: #909ca4;
+    }
+    .nut-step-icon.is-text {
+      background-color: #fff;
+    }
+  }
+  &.nut-step-error {
+    .nut-step-head {
+      color: #fff;
+      border-color: #fa2c19;
+    }
+    .nut-step-icon.is-text {
+      background-color: #fa2c19;
+    }
+    .nut-step-line {
+      background: #3790ff;
+    }
+  }
+}
+.nut-steps-vertical {
+  .nut-step {
+    display: flex;
+    height: 33.34%;
+  }
+  .nut-step-line {
+    position: absolute;
+    display: inline-block;
+    width: 1px;
+    height: 100%;
+    background: #909ca4;
+  }
+  .nut-step-main {
+    display: inline-block;
+    padding-left: 10%;
+    text-align: left;
+  }
+}

+ 61 - 0
src/packages/step/index.vue

@@ -0,0 +1,61 @@
+<template>
+  <view :class="classes">
+    <view class="nut-step-head">
+      <view class="nut-step-line"></view>
+      <view class="nut-step-icon" :class="[icon ? 'is-icon' : 'is-text']">
+        <template v-if="icon">
+          <nut-icon class="nut-step-icon-inner" :class="icon" />
+        </template>
+        <template v-else>
+          <view class="nut-step-inner">11</view>
+        </template>
+      </view>
+    </view>
+    <view class="nut-step-main">
+      <view class="nut-step-title">
+        {{ title }}
+      </view>
+      <view class="nut-step-content">
+        {{ content }}
+      </view>
+    </view>
+  </view>
+</template>
+
+<script lang="ts">
+import { reactive, computed, nextTick, ref } from 'vue';
+import { createComponent } from '@/utils/create';
+const { create, componentName } = createComponent('step');
+
+export default create({
+  props: {
+    title: {
+      type: String,
+      default: ''
+    },
+    content: {
+      type: String,
+      default: ''
+    },
+    icon: {
+      type: String,
+      default: null
+    }
+  },
+  setup(props, { emit, slots }) {
+    const classes = computed(() => {
+      const prefixCls = componentName;
+      return {
+        [prefixCls]: true
+      };
+    });
+    return {
+      classes
+    };
+  }
+});
+</script>
+
+<style scoped lang="scss">
+@import 'index.scss';
+</style>

+ 76 - 0
src/packages/steps/demo.vue

@@ -0,0 +1,76 @@
+<template>
+  <div class="demo">
+    <h2>基本用法</h2>
+    <nut-steps current="1">
+      <nut-step
+        class="nut-step-finish"
+        title="已完成"
+        content="这是一段很长很长很长的描述性文字"
+        >1</nut-step
+      >
+      <nut-step
+        class="nut-step-process"
+        title="进行中"
+        content="这是一段很长很长很长的描述性文字"
+        >2</nut-step
+      >
+      <nut-step class="nut-step-wait" title="未开始">3</nut-step>
+    </nut-steps>
+    <h2>自定义图标和颜色</h2>
+    <div class="" style="height: 300px">
+      <nut-steps>
+        <nut-step
+          class="nut-step-finish"
+          title="已完成"
+          icon="nutui-iconfont nut-icon-wanshangshide"
+        ></nut-step>
+        <nut-step
+          class="nut-step-process"
+          title="进行中"
+          icon="nutui-iconfont nut-icon-notice"
+          >2</nut-step
+        >
+        <nut-step class="nut-step-wait" title="未开始" content="">3</nut-step>
+      </nut-steps>
+    </div>
+    <h2>竖向步骤条</h2>
+    <div class="" style="height: 300px">
+      <nut-steps direction="vertical">
+        <nut-step
+          class="nut-step-error"
+          title="已完成"
+          content="您的订单已经打包完成,商品已发出"
+          >1</nut-step
+        >
+        <nut-step
+          class="nut-step-process"
+          title="进行中"
+          content="您的订单正在配送途中"
+          >2</nut-step
+        >
+        <nut-step
+          class="nut-step-wait"
+          title="未开始"
+          content="收货地址为:北京市经济技术开发区科创十一街18号院京东大厦"
+          >3</nut-step
+        >
+      </nut-steps>
+    </div>
+  </div>
+</template>
+
+<script lang="ts">
+import { createComponent } from '@/utils/create';
+const { createDemo } = createComponent('steps');
+export default createDemo({
+  props: {},
+  setup() {
+    return {};
+  }
+});
+</script>
+
+<style lang="scss" scoped>
+.demo-box {
+}
+</style>

+ 7 - 0
src/packages/steps/index.scss

@@ -0,0 +1,7 @@
+.nut-steps {
+  display: flex;
+}
+.nut-steps-vertical {
+  height: 100%;
+  flex-flow: column;
+}

+ 78 - 0
src/packages/steps/index.vue

@@ -0,0 +1,78 @@
+<template>
+  <view :class="classes">
+    <slot></slot>
+  </view>
+</template>
+
+<script lang="ts">
+import { toRefs, computed, onMounted } from 'vue';
+import step from '@/packages/step/index.vue';
+import { createComponent } from '@/utils/create';
+const { create, componentName } = createComponent('steps');
+
+export default create({
+  children: [step],
+  props: {
+    direction: {
+      type: String,
+      default: 'horizontal'
+    },
+    current: {
+      type: String,
+      default: ''
+    }
+  },
+  setup(props, { emit, slots }) {
+    const classes = computed(() => {
+      const prefixCls = componentName;
+      return {
+        [prefixCls]: true,
+        ['nut-steps-' + props.direction]: true
+      };
+    });
+    onMounted(() => {
+      console.log('slots', slots);
+      console.log('slots', slots.children);
+    });
+    const states = computed(() => {
+      console.log('slots', slots);
+      this.steps = this.$slots.default
+        .filter(vnode => !!vnode.componentInstance)
+        .map(node => node.componentInstance);
+      const total = this.steps.length;
+      this.steps.forEach((child, index) => {
+        child.stepNumber = index + 1;
+        if (this.direction === 'horizontal') {
+          child.total = total;
+        }
+        // 如果已存在status,且在初始化时,则略过
+        // todo 如果当前是error,在current改变时需要处理
+        if (!(isInit && child.currentStatus)) {
+          if (index == this.current - 1) {
+            if (this.status != 'error') {
+              child.currentStatus = 'process';
+            } else {
+              child.currentStatus = 'error';
+            }
+          } else if (index < this.current) {
+            child.currentStatus = 'finish';
+          } else {
+            child.currentStatus = 'wait';
+          }
+        }
+        if (index + 1 === total) {
+          child.currentStatus += ' nut-step-last';
+        }
+      });
+    });
+    return {
+      classes,
+      states
+    };
+  }
+});
+</script>
+
+<style scoped lang="scss">
+@import 'index.scss';
+</style>