Browse Source

refactor: steps

suzigang 4 years ago
parent
commit
06580e4f27

+ 1 - 0
.husky/.gitignore

@@ -0,0 +1 @@
+_

+ 4 - 0
.husky/commit-msg

@@ -0,0 +1,4 @@
+#!/bin/sh
+. "$(dirname "$0")/_/husky.sh"
+
+yarn commitlint --edit $1    

+ 5 - 0
.husky/pre-commit

@@ -0,0 +1,5 @@
+#!/bin/sh
+. "$(dirname "$0")/_/husky.sh"
+
+node ./../jd/verifymail.js
+yarn lint-staged

+ 5 - 9
package.json

@@ -49,7 +49,8 @@
     "publish:beta": "npm publish --tag=beta",
     "generate:file": "node jd/generate-nutui.js",
     "generate:types": "node jd/generate-types.js",
-    "generate:themes": "node jd/generate-themes.js"
+    "generate:themes": "node jd/generate-themes.js",
+    "prepare": "husky install"
   },
   "dependencies": {
     "axios": "^0.21.0",
@@ -72,7 +73,7 @@
     "front-matter": "^4.0.2",
     "fs-extra": "^9.1.0",
     "highlight.js": "^10.3.1",
-    "husky": "^4.3.0",
+    "husky": "^6.0.0",
     "lint-staged": "^10.5.0",
     "prettier": "^1.19.1",
     "transliteration": "^2.2.0",
@@ -100,14 +101,9 @@
       "no-debugger": "off"
     }
   },
-  "husky": {
-    "hooks": {
-      "pre-commit": "node ./jd/verifymail.js && lint-staged",
-      "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
-    }
-  },
   "lint-staged": {
-    "*.{ts,js,vue,scss}": "prettier --write"
+    "*.md": "prettier --write",
+    "*.{ts,tsx,js,vue,scss}": "prettier --write"
   },
   "repository": {
     "type": "git",

+ 0 - 1
src/packages/datepicker/demo.vue

@@ -13,7 +13,6 @@
 
     <nut-datepicker
       v-model="currentDate"
-      title="日期选择"
       @confirm="
         val => {
           confirm(0, val);

+ 5 - 3
src/packages/picker/index.vue

@@ -40,8 +40,7 @@
             @change="
               dataIndex => {
                 changeHandler(columnIndex, dataIndex);
-              }
-            "
+              }"
           ></nut-picker-column>
         </view-block>
       </view-block>
@@ -63,7 +62,10 @@ import {
 const { create, componentName } = createComponent('picker');
 
 export default create({
-  children: [column, popup],
+  components: {
+    [column.name]: column,
+    [popup.name]: popup
+  },
   props: {
     visible: {
       type: Boolean,

+ 18 - 34
src/packages/step/index.scss

@@ -1,7 +1,7 @@
 .nut-step {
   flex-grow: 0;
   flex-shrink: 0;
-  flex-basis: 33.34%;
+  flex: 1;
   text-align: center;
   font-size: 0;
   &-head {
@@ -26,7 +26,6 @@
     line-height: 25px;
     font-family: PingFangSC-Medium;
     font-size: 13px;
-    // border-color: #909CA4;
     z-index: 1;
     .nut-icon {
       width: 100%;
@@ -68,35 +67,35 @@
   }
   &.nut-step-finish {
     .nut-step-head {
-      color: #3790ff;
-      border-color: #3790ff;
+      color: $primary-color;
+      border-color: $primary-color;
     }
     .nut-step-icon.is-text {
-      background-color: #fff;
+      background-color: $white;
     }
     .nut-step-icon.is-icon {
-      background-color: #fff;
+      background-color: $white;
     }
     .nut-step-line {
-      background: #3790ff;
+      background: $primary-color;
     }
     .nut-step-title {
-      color: #3790ff;
+      color: $primary-color;
     }
   }
   &.nut-step-process {
     .nut-step-head {
-      color: #fff;
-      border-color: #3790ff;
+      color: $white;
+      border-color: $primary-color;
     }
     .nut-step-icon.is-text {
-      background-color: #3790ff;
+      background-color: $primary-color;
     }
     .nut-step-icon.is-icon {
-      background-color: #3790ff;
+      background-color: $primary-color;
     }
     .nut-step-title {
-      color: #3790ff;
+      color: $primary-color;
     }
   }
   &.nut-step-wait {
@@ -105,30 +104,15 @@
       border-color: #909ca4;
     }
     .nut-step-icon.is-text {
-      background-color: #fff;
+      background-color: $white;
     }
     .nut-step-icon.is-icon {
-      background-color: #fff;
+      background-color: $white;
     }
     .nut-step-content {
       color: #909ca4;
     }
   }
-  &.nut-step-error {
-    .nut-step-head {
-      color: #fff;
-      border-color: #fa2c19;
-    }
-    .nut-step-icon.is-text {
-      background-color: #fa2c19;
-    }
-    .nut-step-icon.is-icon {
-      background-color: #fa2c19;
-    }
-    .nut-step-line {
-      background: #3790ff;
-    }
-  }
 }
 .nut-steps-vertical {
   .nut-step {
@@ -160,7 +144,7 @@
     .nut-step-icon {
       width: 8px;
       height: 8px;
-      background: #3790ff;
+      background: $primary-color;
       border-radius: 50%;
       box-sizing: content-box;
     }
@@ -174,13 +158,13 @@
     }
     .nut-step-finish {
       .nut-step-icon {
-        background-color: #3790ff;
+        background-color: $primary-color;
       }
     }
     .nut-step-process {
       .nut-step-icon {
         position: relative;
-        background-color: #3790ff;
+        background-color: $primary-color;
         &:before {
           content: '';
           display: inline-block;
@@ -191,7 +175,7 @@
           margin-top: -7px;
           width: 14px;
           height: 14px;
-          background-color: rgba(55, 144, 255, 0.23);
+          background-color: $primary-color-end;
           border-radius: 50%;
         }
       }

+ 29 - 28
src/packages/step/index.vue

@@ -4,14 +4,14 @@
       <view class="nut-step-line"></view>
       <view
         class="nut-step-icon"
-        :class="[!state.dot ? (icon ? 'is-icon' : 'is-text') : '']"
+        :class="[!dot ? (icon ? 'is-icon' : 'is-text') : '']"
       >
         <template v-if="icon">
           <nut-icon class="nut-step-icon-inner" :class="icon" />
         </template>
-        <template v-else-if="state.dot"></template>
+        <template v-else-if="dot"></template>
         <template v-else>
-          <view class="nut-step-inner">{{ state.index }}</view>
+          <view class="nut-step-inner">{{ index }}</view>
         </template>
       </view>
     </view>
@@ -19,15 +19,14 @@
       <view class="nut-step-title">
         {{ title }}
       </view>
-      <view class="nut-step-content">
-        {{ content }}
+      <view class="nut-step-content" v-html="content">
       </view>
     </view>
   </view>
 </template>
 
 <script lang="ts">
-import { reactive, computed, inject } from 'vue';
+import { reactive, computed, inject, toRefs, getCurrentInstance, ComponentInternalInstance } from 'vue';
 import { createComponent } from '@/utils/create';
 const { create, componentName } = createComponent('step');
 
@@ -44,39 +43,41 @@ export default create({
     icon: {
       type: String,
       default: null
-    },
-    status: {
-      type: String,
-      default: null
-    },
-    data: {
-      type: String,
-      default: null
     }
   },
-  setup(props, context) {
-    const steps: any = inject('stepsParent');
-    const defaults = context.slots?.default();
-    console.log('defaults', context.slots);
-    console.log('steps', steps.props.progressDot);
+
+  setup(props, {emit, slots}) {
+    const instance = getCurrentInstance() as ComponentInternalInstance;
+    const parent: any = inject('parent');
+    parent['relation'](instance);
+
     const state = reactive({
-      data: [],
-      index: context.slots.default()[0]?.children - 1,
-      dot: steps.props.progressDot
+      dot: parent.props.progressDot
     });
-    console.log('dot', state.dot);
-    // console.log('context', steps.state.steps[state.index])
+
+    const index = computed(() => parent.state.children.indexOf(instance) + 1);
+
+    const getCurrentStatus = () => {
+      const activeIndex = index.value;
+      if(activeIndex < +parent.props.current) return 'finish';
+      return activeIndex === +parent.props.current ? 'process' : 'wait';
+    };
+
+    const status = computed(() => {
+      return getCurrentStatus();
+    });
+
     const classes = computed(() => {
       const prefixCls = componentName;
       return {
         [prefixCls]: true,
-        [props.status
-          ? 'nut-step-' + props.status
-          : steps.state.steps[state.index].currentStatus]: true
+        [`${prefixCls}-${status.value}`]: true
       };
     });
+
     return {
-      state,
+      ...toRefs(state),
+      index,
       classes
     };
   }

+ 6 - 6
src/packages/steps/demo.vue

@@ -5,6 +5,7 @@
       <nut-step title="进行中">1</nut-step>
       <nut-step title="未开始">2</nut-step>
       <nut-step title="未开始">3</nut-step>
+      <nut-step title="未开始">4</nut-step>
     </nut-steps>
     <h2>标题和描述信息</h2>
     <nut-steps current="2">
@@ -14,15 +15,14 @@
         icon="nutui-iconfont nut-icon-wanshangshide"
         >1</nut-step
       >
-      <nut-step title="进行中" content="步骤描述">2</nut-step>
-      <nut-step title="未开始" content="步骤描述">3</nut-step>
+      <nut-step title="进行中" content="步骤描述"></nut-step>
+      <nut-step title="未开始" content="步骤描述"></nut-step>
     </nut-steps>
     <h2>自定义图标</h2>
     <nut-steps current="1">
       <nut-step
         title="已完成"
-        icon="nutui-iconfont nut-icon-wanshangshide"
-        status="error"
+        icon="nutui-iconfont nut-icon-notice"
         >1</nut-step
       >
       <nut-step title="进行中" icon="nutui-iconfont nut-icon-notice"
@@ -53,14 +53,14 @@
       </nut-steps>
     </div>
     <div style="height: 300px">
-      <nut-steps direction="vertical" progressDot current="2">
+      <nut-steps direction="vertical" progress-dot current="2">
         <nut-step title="已完成" content="您的订单已经打包完成,商品已发出"
           >1</nut-step
         >
         <nut-step title="进行中" content="您的订单正在配送途中">2</nut-step>
         <nut-step
           title="未开始"
-          content="收货地址为:北京市经济技术开发区科创十一街18号院京东大厦"
+          content="<p>收货地址为:</p><p>北京市经济技术开发区科创十一街18号院京东大厦</p>"
           >3</nut-step
         >
       </nut-steps>

+ 7 - 7
src/packages/steps/doc.md

@@ -23,6 +23,7 @@ app.use(Steps);
   <nut-step title="进行中">1</nut-step>
   <nut-step title="未开始">2</nut-step>
   <nut-step title="未开始">3</nut-step>
+  <nut-step title="未开始">4</nut-step>
 </nut-steps>
 ```
 
@@ -58,7 +59,7 @@ app.use(Steps);
 
 ### 点状步骤和垂直方向
 ```html
-<nut-steps direction="vertical" progressDot current="2">
+<nut-steps direction="vertical" progress-dot current="2">
   <nut-step title="已完成" content="您的订单已经打包完成,商品已发出" >1</nut-step>
   <nut-step title="进行中" content="您的订单正在配送途中">2</nut-step>
   <nut-step title="未开始" content="收货地址为:北京市经济技术开发区科创十一街18号院京东大厦">3</nut-step>
@@ -74,9 +75,9 @@ app.use(Steps);
 
 | 参数                   | 说明                                                        | 类型           | 默认值      |
 | ---------------------- | ----------------------------------------------------------- | -------------- | ----------- |
-| direction	             | 	显示方向,`horizontal`,`vertical`  | String        | horizontal  | 
-| current	               | 	当前所在的步骤           | Number、String        | 0       |
-| progressDot            |  点状步骤条     | Boolean | false         |
+| direction	             | 	显示方向,`horizontal`,`vertical`  | String        | 'horizontal'  | 
+| current	               | 	当前所在的步骤           | Number、String        | '0'      |
+| progress-dot            |  点状步骤条     | Boolean | false         |
 
 
 
@@ -85,6 +86,5 @@ app.use(Steps);
 | 参数           | 说明                   | 类型     | 默认值      |
 | ---------------- | ---------------------- | ------------ | ----------- |
 | title            | 流程步骤的标题         | String | 步骤 |
-| content          | 流程步骤的描述性文字       | String | 步骤描述 |
-| icon          | 图标       | String | - |
-| status           | 流程状态       | String | String、Number | "process"(可选值 "wait"、"process"、"finish"、"error" |
+| content          | 流程步骤的描述性文字(支持 html 结构)       | String | 步骤描述 |
+| icon          | 图标       | String | null |

+ 27 - 90
src/packages/steps/index.vue

@@ -1,38 +1,25 @@
-<template>
-  <view :class="classes">
-    <slot></slot>
-  </view>
-</template>
-
 <script lang="ts">
 import {
   provide,
   computed,
-  onMounted,
   reactive,
-  watch,
-  onBeforeMount
+  h,
+  ComponentInternalInstance
 } from 'vue';
-import step from '@/packages/step/index.vue';
+import Step from '@/packages/step/index.vue';
 import { createComponent } from '@/utils/create';
 const { create, componentName } = createComponent('steps');
 
 export default create({
-  children: [step],
+  children: [Step],
   props: {
     direction: {
       type: String,
       default: 'horizontal'
     },
     current: {
-      type: String,
-      default: 'false'
-    },
-    status: {
-      validator(value) {
-        return ['wait', 'process', 'finish', 'error'].includes(value);
-      },
-      default: 'process'
+      type: [String, Number],
+      default: '0'
     },
     progressDot: {
       type: Boolean,
@@ -41,87 +28,37 @@ export default create({
   },
   setup(props, { emit, slots }) {
     const state = reactive({
-      steps: {},
-      children: []
+      children: [] as ComponentInternalInstance[]
     });
+
     const classes = computed(() => {
       const prefixCls = componentName;
       return {
         [prefixCls]: true,
-        ['nut-steps-' + props.direction]: true,
-        [props.progressDot ? 'nut-steps-dot' : '']: true
+        [`${prefixCls}-${props.direction}`]: true,
+        [`${prefixCls}-dot`]: !!props.progressDot
       };
     });
-    onBeforeMount(() => {
-      console.log('onBeforeMount');
-      init();
-    });
-    onMounted(() => {
-      console.log('onMounted');
-      // init();
-    });
-    // watch(
-    //   () => props.current,
-    //   val => {
-    //     console.log()
-    //     states();
-    //   }
-    // );
-    // watch(
-    //   () =>  props.source,
-    //   val => {
-    //     init();
-    //   }
-    // )
-    const init = () => {
-      state.steps = (slots as any)?.default();
-      stepStates();
-    };
-    const stepStates = () => {
-      if (props.progressDot) {
-        console.log('state.steps', state.steps);
-        state.steps.dot = true;
-      }
-      const total = state.steps.length;
-      state.steps.forEach((child, index) => {
-        child.stepNumber = index + 1;
-
-        state.children = index;
-        // console.log('data', state.children)
 
-        if (props.direction === 'horizontal') {
-          child.total = total;
-        }
-        // console.log('父', child);
-        if (!child.currentStatus) {
-          if (index == props.current - 1) {
-            if (props.status != 'error') {
-              child.currentStatus = 'nut-step-process';
-            } else {
-              child.currentStatus = 'error';
-            }
-          } else if (index < props.current) {
-            child.currentStatus = 'nut-step-finish';
-          } else {
-            child.currentStatus = 'nut-step-wait';
-          }
-        }
-        if (index + 1 === total) {
-          child.currentStatus += ' nut-step-last';
-        }
-      });
+    const relation = (child: ComponentInternalInstance) => {
+      child && state.children.push(child);
     };
-    // provide('parent', {
-    //   slots
-    // });
-    provide('stepsParent', {
-      props,
-      state
+
+    provide('parent', {
+      relation,
+      state,
+      props
     });
-    return {
-      classes,
-      stepStates
-    };
+
+    return () => {
+      return h(
+        'view',
+        {
+          class: classes.value
+        },
+        slots.default?.()
+      )
+    }
   }
 });
 </script>

+ 3 - 0
src/styles/variables.scss

@@ -253,6 +253,9 @@ $address-region-tab-line: linear-gradient(
   $primary-color-end 100%
 );
 
+//steps
+
+
 // dialog
 $dialog-width: 296px;