Browse Source

feat: 动作面板组件40%

zhangyufei1 5 years ago
parent
commit
574677a0f9

+ 1 - 0
cache/docs.cache

@@ -0,0 +1 @@
+{"design":"vcgLzZ0ctHqnqRhSMmxbHFPKHOk=","international":"48VFbFFji5XeQPSYVbEkhUXs9jw=","intro":"NzilpMOPGLKCi3NAacAUHKA5PM8=","joinus":"xe5bD6hZaxe0Xg0m4zCFnTb5JKY=","start":"hWB+R788ekxKa3Y8TItd8OEYnyE=","theme":"ul//vB9gvub+r0tmKQ0utENYGGY="}

+ 1 - 0
cache/mdToVue.cache

@@ -0,0 +1 @@
+{"mdToVue":"YyHHl228Lm/wkXcldAK2nCQ7hw8="}

File diff suppressed because it is too large
+ 1 - 0
cache/src.cache


+ 9 - 0
src/config.js

@@ -103,6 +103,15 @@ module.exports = {
           show: true,
           desc: '较长页面快捷回到顶部',
           author: 'liqiong43'
+        },
+        {
+          name: 'ActionSheet',
+          sort: '1',
+          cName: '动作面板',
+          type: 'component',
+          show: true,
+          desc: '底部弹出动作菜单面板',
+          author: 'zhangyufei'
         }
       ]
     },

+ 204 - 0
src/packages/actionsheet/demo.vue

@@ -0,0 +1,204 @@
+<template>
+  <div class="demo-list demo">
+    <h4>基本用法(选择类)</h4>
+    <div>
+      <nut-cell
+        :showIcon="true"
+        :isLink="true"
+        @click="switchActionSheet('isVisible1')"
+      >
+        <span><label>基础用法</label></span>
+        <div class="selected-option">{{ state.val1 }}</div>
+      </nut-cell>
+      <nut-cell
+        :showIcon="true"
+        :isLink="true"
+        @click="switchActionSheet('isVisible2')"
+      >
+        <span><label>展示取消按钮</label></span>
+        <div class="selected-option">{{ state.val2 }}</div>
+      </nut-cell>
+      <div>
+        <nut-cell :isLink="true" @click="switchActionSheet('isVisible4')">
+          <span><label>展示描述信息</label></span>
+        </nut-cell>
+      </div>
+      <h4>自定义面板</h4>
+
+      <nut-cell :isLink="true" @click="switchActionSheet('isVisible5')">
+        <span><label>自定义内容</label></span>
+        <!-- <div class="selected-option">打开</div> -->
+      </nut-cell>
+      <!-- <nut-cell
+        :showIcon="true"
+        :isLink="true"
+        @click="switchActionSheet('isVisible1')"
+      >
+        <span><label>展示取消按钮</label></span>
+      </nut-cell>
+      <nut-cell
+        :showIcon="true"
+        :isLink="true"
+        @click="switchActionSheet('isVisible2')"
+      >
+        <span><label>性别</label></span>
+        <span>高亮选中项~~~~</span>
+      </nut-cell>
+      <nut-cell
+        :showIcon="true"
+        :isLink="true"
+        @click="switchActionSheet('isVisible3')"
+      >
+        <span><label>性别</label></span>
+        <span>设置禁用状态~~~~</span>
+      </nut-cell>
+    </div>
+    <div>
+      <nut-cell :isLink="true" @click="switchActionSheet('isVisible4')">
+        <span><label>展示描述信息</label></span>
+        <span>我是描述~~~~</span>
+        <div class="selected-option">删除本条</div>
+      </nut-cell>
+    </div>
+    <h4>自定义面板</h4>
+    <div>
+      <nut-cell :isLink="true" @click="switchActionSheet('isVisible5')">
+        <span><label>自定义内容</label></span>
+        <div class="selected-option">打开</div>
+      </nut-cell> -->
+    </div>
+    <!-- demo -->
+    <nut-actionsheet
+      :is-visible="state.isVisible1"
+      @close="switchActionSheet('isVisible1')"
+      :menu-items="menuItems"
+      @choose="chooseItem"
+    ></nut-actionsheet>
+    <!-- demo(带取消按钮) -->
+    <nut-actionsheet
+      :is-visible="state.isVisible2"
+      @close="switchActionSheet('isVisible2')"
+      cancelTxt="取消"
+      :menu-items="menuItems"
+      @choose="chooseItemTwo"
+    ></nut-actionsheet>
+    <!-- demo(高亮选中)-->
+    <!-- <nut-actionsheet
+      :is-visible="isVisible2"
+      :menu-items="menuItems2"
+      :chooseTagValue="sex2"
+      @close="switchActionSheet('isVisible2')"
+      @choose="chooseItemAge"
+    ></nut-actionsheet> -->
+    <!-- demo(设置禁用状态)-->
+    <!-- <nut-actionsheet
+      :is-visible="isVisible3"
+      :menu-items="menuItems3"
+      @close="switchActionSheet('isVisible3')"
+      @choose="chooseItemConstellation"
+    ></nut-actionsheet> -->
+    <!-- demo 展示描述信息 -->
+    <nut-actionsheet
+      :is-visible="state.isVisible4"
+      :menu-items="menuItems"
+      :chooseTagValue="`确定`"
+      cancelTxt="取消"
+      @close="switchActionSheet('isVisible4')"
+    >
+      <span><label>确定删除吗?</label></span>
+      <span>删除之后不能,描述信息,删除之后不能,描述信息</span>
+    </nut-actionsheet>
+    <!-- demo 自定义类 -->
+    <nut-actionsheet
+      :is-visible="state.isVisible5"
+      @close="switchActionSheet('isVisible5')"
+    >
+      <div class="custom-wrap"><span>自定义</span></div>
+    </nut-actionsheet>
+  </div>
+</template>
+
+<script>
+import { reactive } from 'vue';
+import { createComponent } from '@/utils/create';
+const { createDemo } = createComponent('actionsheet');
+export default createDemo({
+  props: {},
+  setup() {
+    const state = reactive({
+      isVisible1: false,
+      isVisible2: false,
+      isVisible3: false,
+      isVisible4: false,
+      isVisible5: false,
+      val1: '',
+      val2: '',
+      val3: ''
+    });
+    const menuItems = [
+      {
+        name: '选项一',
+        value: 0
+      },
+      {
+        name: '选项二',
+        value: 1
+      },
+      {
+        name: '选项三',
+        value: 2
+      }
+    ];
+
+    const switchActionSheet = param => {
+      console.log(param);
+      state[`${param}`] = !state[`${param}`];
+    };
+
+    const chooseItem = itemParams => {
+      console.log(itemParams, 'itemParams');
+      state.val1 = itemParams.name;
+    };
+
+    function chooseItemTwo(itemParams) {
+      state.val2 = itemParams.name;
+    }
+
+    // function chooseItemAge(itemParams) {
+    //   sex2 = itemParams.name;
+    // }
+
+    // function chooseItemConstellation(itemParams) {
+    //   sex3 = itemParams.title;
+    // }
+    return {
+      state,
+      menuItems,
+      chooseItem,
+      chooseItemTwo,
+      switchActionSheet
+    };
+  }
+});
+</script>
+
+<style lang="scss" scoped>
+.demo {
+  height: 100%;
+  background: #f7f8fa;
+  overflow-x: hidden;
+  overflow-y: auto;
+  padding: 0 25px;
+  padding-top: 57px;
+  h4 {
+    height: 56px;
+    line-height: 56px;
+    font-size: 14px;
+    color: #909ca4;
+  }
+}
+.custom-wrap {
+  padding: 110px 0;
+  text-align: center;
+}
+</style>

+ 280 - 0
src/packages/actionsheet/doc.md

@@ -0,0 +1,280 @@
+# ActionSheet 动作面板
+
+从底部弹出的动作菜单面板。
+
+## 基本用法(选择类)
+
+默认
+```html
+<div @click.native="switchActionSheet">
+    <span class="title"><label>性别</label></span>
+    <span class="selected-option">{{sex}}</span>
+</div>
+<nut-actionsheet :is-visible="isVisible" 
+    @close="switchActionSheet"
+    :menu-items="menuItems"
+    @choose="chooseItem"
+></nut-actionsheet>
+```
+```javascript
+export default {
+    data() {
+        return {
+            sex: '请选择',
+            isVisible: false,
+            menuItems: [
+                {
+                    'name': '男',
+                    'value': 0
+                },
+                {
+                    'name': '女',
+                    'value': 1
+                }
+            ]
+        };
+    },
+    methods: {
+        switchActionSheet() {
+            this.isVisible = !this.isVisible;
+        },
+
+        chooseItem(itemParams) {
+            this.sex = itemParams.name;
+        }
+    }
+};
+```
+
+带取消按钮
+```html
+<div @click.native="switchActionSheet">
+    <span class="title"><label>性别</label></span>
+    <span class="selected-option">{{sex}}</span>
+</div>
+ <nut-actionsheet :is-visible="isVisible" 
+    @close="switchActionSheet"
+    :menu-items="menuItems"
+    @choose="chooseItem"
+    cancelTxt="取消"
+></nut-actionsheet>
+```
+```javascript
+export default {
+    data() {
+        return {
+            sex: '请选择',
+            isVisible: false,
+            menuItems: [
+                {
+                    'name': '男',
+                    'value': 0
+                },
+                {
+                    'name': '女',
+                    'value': 1
+                }
+            ]
+        };
+    },
+    methods: {
+        switchActionSheet() {
+            this.isVisible = !this.isVisible;
+        },
+
+        chooseItem(itemParams) {
+            this.sex = itemParams.name;
+        }
+    }
+};
+```
+
+高亮已选项
+```html
+<div @click.native="switchActionSheet">
+    <span class="title"><label>性别</label></span>
+    <span class="selected-option">{{sex}}</span>
+</div>
+<nut-actionsheet :is-visible="isVisible" 
+    @close="switchActionSheet"
+    :menu-items="menuItems"
+    @choose="chooseItem"
+    :chooseTagValue="sex"
+></nut-actionsheet>
+```
+```javascript
+export default {
+    data() {
+        return {
+            sex: '请选择',
+            isVisible: false,
+            menuItems: [
+                {
+                    'name': '男',
+                    'value': 0
+                },
+                {
+                    'name': '女',
+                    'value': 1
+                }
+            ]
+        };
+    },
+    methods: {
+        switchActionSheet() {
+            this.isVisible = !this.isVisible;
+        },
+
+        chooseItem(itemParams) {
+            this.sex = itemParams.name;
+        }
+    }
+};
+```
+
+设置禁用状态
+```html
+<div @click.native="switchActionSheet">
+    <span class="title"><label>性别</label></span>
+    <span class="selected-option">{{sex}}</span>
+</div>
+<nut-actionsheet :is-visible="isVisible" 
+    @close="switchActionSheet"
+    :menu-items="menuItems"
+    @choose="chooseItem"
+    :chooseTagValue="sex"
+></nut-actionsheet>
+```
+```javascript
+export default {
+    data() {
+        return {
+            sex: '请选择',
+            isVisible: false,
+            menuItems: [
+                {
+                    'name': '男',
+                    'value': 0,
+                    'disable': false
+                },
+                {
+                    'name': '女',
+                    'value': 1,
+                    'disable': true
+                }
+            ]
+        };
+    },
+    methods: {
+        switchActionSheet() {
+            this.isVisible = !this.isVisible;
+        },
+
+        chooseItem(itemParams) {
+            this.sex = itemParams.name;
+        }
+    }
+};
+```
+
+## 提示
+```html
+<div @click.native="switchActionSheet">
+    <span class="title"><label>我就列表测试数据</label></span>
+    <span class="sub-title">我是描述~~~~</span>
+    <div class="selected-option">删除本条</div>
+</div>
+<nut-actionsheet :is-visible="isVisible" 
+    :menu-items="menuItems4" 
+    chooseTagValue="确定"
+    cancelTxt="取消"
+    @close="switchActionSheet"
+    @choose="choose"
+>
+    <span slot="title"><label>确定删除吗?</label></span>
+    <span slot="sub-title">删除之后不能,描述信息,删除之后不能,描述信息</span>
+</nut-actionsheet>
+```
+```javascript
+export default {
+    data() {
+        return {
+            sex: '请选择',
+            isVisible: false,
+            menuItems: [
+                {
+                     'name': '确定'
+                }
+            ]
+        };
+    },
+    methods: {
+        switchActionSheet() {
+            this.isVisible = !this.isVisible;
+        },
+
+        choose(itemParams) {
+            
+        }
+    }
+};
+```
+
+## 自定义内容
+```html
+<div @click.native="switchActionSheet">
+    <span class="title"><label>内容自定义</label></span>
+    <div class="selected-option">打开</div>
+</div>
+<nut-actionsheet :is-visible="isVisible" 
+    @close="switchActionSheet"
+>
+    <div slot="custom" class="custom-wrap"><span>自定义</span></div>
+</nut-actionsheet>
+```
+```javascript
+
+export default {
+    data() {
+        return {
+            isVisible: false
+        }   
+    },
+    methods: {
+        switchActionSheet() {
+            this.isVisible = !this.isVisible;
+        }
+    }
+};
+```
+
+## Prop
+
+| 字段 | 说明 | 类型 | 默认值
+|----- | ----- | ----- | ----- 
+| is-animation | 是否开启动画 | Boolean | true
+| is-lock-bg-scroll | 是否锁定背景滚动 | Boolean | false
+| is-visible | 是否可见 | Boolean | false
+| is-show-mask | 是否显示背景遮罩 | Boolean | true
+| is-click-choose-close | 是否点击列表项后立即关闭 | Boolean | true
+| is-click-close-mask | 是否点击mask蒙层关闭 | Boolean | true
+| cancel-txt | 取消文案 | String | '取消'
+| choose-tag-value | 已选值,如果填写,高亮显示 | String | -
+| menu-items | 列表项 | Array | [ ]
+| option-tag | 设置列表项展示使用参数 | String | 'name'
+
+## Slot
+
+| 名称 | 说明 
+|----- | ----- 
+| custom | 自定义内容
+| title | 自定义标题
+| subTitle | 自定义副标题  
+
+## Event
+
+| 字段 | 说明 | 回调参数 
+|----- | ----- | ----- 
+| choose | 选择之后触发 | 选中列表项 
+| close | 关闭时触发 | 无 
+| cancel | 点击取消文案时触发 | 无 

+ 76 - 0
src/packages/actionsheet/index.scss

@@ -0,0 +1,76 @@
+// @import '../../styles/animation/fade';
+// @import '../../styles/animation/slide-up';
+
+.nut-actionsheet-mask {
+  //   @include fix-fullscreen();
+}
+
+.nut-actionsheet-panel {
+  position: fixed;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  width: 100%;
+  max-height: 80%;
+  overflow: auto;
+  z-index: $zindex-actionsheet;
+  background-color: $body-background;
+}
+
+.nut-actionsheet-modal {
+  padding: 10px;
+  margin: 0;
+  text-align: center;
+  background-color: #fff;
+  border-bottom: 1px solid $light-color;
+
+  .nut-actionsheet-title,
+  .nut-actionsheet-sub-title {
+    padding: 5px 0;
+  }
+
+  .nut-actionsheet-title {
+    font-size: $font-size-base;
+    color: $title-color;
+  }
+
+  .nut-actionsheet-sub-title {
+    font-size: $font-size-small;
+    color: $title-color;
+    margin-inline-start: 0px;
+  }
+}
+
+.nut-actionsheet-menu {
+  list-style: none;
+  padding: 0;
+  margin: 0;
+}
+
+.nut-actionsheet-cancel,
+.nut-actionsheet-item {
+  height: 24px;
+  padding: 10px;
+  line-height: 24px;
+  font-size: $font-size-base;
+  color: $title-color;
+  text-align: center;
+  background-color: #fff;
+}
+
+.nut-actionsheet-item {
+  border-bottom: 1px solid $light-color;
+}
+
+.nut-actionsheet-item-active {
+  color: $primary-color;
+}
+
+.nut-actionsheet-item-disabled {
+  color: #e1e1e1;
+}
+
+.nut-actionsheet-cancel {
+  margin-top: 5px;
+  border-top: 1px solid $light-color;
+}

+ 159 - 0
src/packages/actionsheet/index.vue

@@ -0,0 +1,159 @@
+<template>
+  <view class="nut-actionsheet">
+    <transition :name="isAnimation ? 'nutFade' : ''" v-if="isShowMask">
+      <view
+        class="nut-actionsheet-mask"
+        @click="clickActionSheetMask"
+        v-show="isVisible"
+      ></view>
+    </transition>
+    <transition :name="isAnimation ? 'nutSlideUp' : ''">
+      <view class="nut-actionsheet-panel" v-show="isVisible">
+        <view class="nut-actionsheet-custom">
+          <slot name="custom"></slot>
+        </view>
+        <dl
+          class="nut-actionsheet-modal"
+          v-if="$slots.title || $slots.subTitle"
+        >
+          <dt class="nut-actionsheet-title"><slot name="title"></slot></dt>
+          <dd class="nut-actionsheet-sub-title"
+            ><slot name="sub-title"></slot
+          ></dd>
+        </dl>
+        <ul class="nut-actionsheet-menu">
+          <li
+            class="nut-actionsheet-item"
+            :class="{
+              'nut-actionsheet-item-active': isHighlight(item),
+              'nut-actionsheet-item-disabled': item.disable
+            }"
+            v-for="(item, index) of menuItems"
+            :key="index"
+            @click="chooseItem(item, index)"
+            >{{ item[optionTag] }}</li
+          >
+        </ul>
+        <view
+          class="nut-actionsheet-cancel"
+          v-if="cancelTxt"
+          @click="cancelActionSheet"
+          >{{ cancelTxt }}</view
+        >
+      </view>
+    </transition>
+  </view>
+</template>
+<script>
+import { createComponent } from '@/utils/create';
+import { watch, onDeactivated, onUnmounted } from 'vue';
+const { create } = createComponent('actionsheet');
+export default create({
+  props: {
+    isAnimation: {
+      type: Boolean,
+      default: true
+    },
+    isLockBgScroll: {
+      type: Boolean,
+      default: false
+    },
+    isVisible: {
+      type: Boolean,
+      default: false
+    },
+    isShowMask: {
+      type: Boolean,
+      default: true
+    },
+    isClickChooseClose: {
+      type: Boolean,
+      default: true
+    },
+    isClickCloseMask: {
+      type: Boolean,
+      default: true
+    },
+    cancelTxt: {
+      type: String,
+      default: ''
+    },
+    optionTag: {
+      type: String,
+      default: 'name'
+    },
+    chooseTagValue: {
+      type: String,
+      default: ''
+    },
+    menuItems: {
+      type: Array,
+      default: () => []
+    }
+  },
+  emits: ['click', 'close', 'cancel', 'choose', 'open'],
+  setup(props, { emit }) {
+    console.log(props.isVisible, 'isVisible');
+    const removeLockScroll = () => {
+      document.body.classList.remove('nut-overflow-hidden');
+    };
+    const isHighlight = item => {
+      return (
+        (props.chooseTagValue &&
+          props.chooseTagValue == item[props.optionTag]) ||
+        props.chooseTagValue === 0
+      );
+    };
+
+    const closeActionSheet = () => {
+      emit('close');
+    };
+
+    const cancelActionSheet = () => {
+      closeActionSheet();
+      emit('cancel');
+    };
+
+    const clickActionSheetMask = () => {
+      props.isClickCloseMask && closeActionSheet();
+    };
+
+    const chooseItem = (item, index) => {
+      if (!item.disable) {
+        if (props.isClickChooseClose) {
+          closeActionSheet();
+        }
+        emit('choose', item, index);
+      }
+    };
+    watch(function isVisible(value) {
+      console.log(value, 'val');
+      !!value && emit('open');
+      if (props.isLockBgScroll) {
+        if (value) {
+          document.body.classList.add('nut-overflow-hidden');
+        } else {
+          removeLockScroll();
+        }
+      }
+    }),
+      onDeactivated(() => {
+        removeLockScroll();
+      });
+    onUnmounted(() => {
+      removeLockScroll();
+    });
+    return {
+      removeLockScroll,
+      isHighlight,
+      closeActionSheet,
+      clickActionSheetMask,
+      cancelActionSheet,
+      chooseItem
+    };
+  }
+});
+</script>
+<style lang="scss">
+@import 'index.scss';
+</style>

+ 20 - 4
src/packages/cell/index.vue

@@ -1,7 +1,11 @@
 <template>
   <view :class="classes" @click="handleClick">
     <slot>
-      <view class="nut-cell__title" :class="{ icon: icon }" v-if="title || subTitle || icon">
+      <view
+        class="nut-cell__title"
+        :class="{ icon: icon }"
+        v-if="title || subTitle || icon"
+      >
         <nut-icon v-if="icon" class="icon" :name="icon"></nut-icon>
         <template v-if="subTitle">
           <view class="title">{{ title }}</view>
@@ -11,8 +15,18 @@
           {{ title }}
         </template>
       </view>
-      <view v-if="desc" class="nut-cell__value" :style="{ 'text-align': descTextAlign }">{{ desc }}</view>
-      <nut-icon v-if="isLink || to" size="14px" color="#979797" name="right"></nut-icon>
+      <view
+        v-if="desc"
+        class="nut-cell__value"
+        :style="{ 'text-align': descTextAlign }"
+        >{{ desc }}</view
+      >
+      <nut-icon
+        v-if="isLink || to"
+        size="14px"
+        color="#979797"
+        name="right"
+      ></nut-icon>
     </slot>
   </view>
 </template>
@@ -54,7 +68,9 @@ export default create({
       if (props.to && router) {
         router[props.replace ? 'replace' : 'push'](props.to);
       } else if (props.url) {
-        props.replace ? location.replace(props.url) : (location.href = props.url);
+        props.replace
+          ? location.replace(props.url)
+          : (location.href = props.url);
       }
     };
 

+ 7 - 0
src/styles/variables.scss

@@ -109,3 +109,10 @@ $inputnumber-input-background-color: $help-color;
 $inputnumber-input-border-radius: 8px;
 $inputnumber-input-width: 40px;
 $inputnumber-input-height: 20px;
+
+// actionsheet
+$zindex-actionsheet: 10001 !default;
+$body-background: #f6f6f6 !default;
+$light-color: #f6f6f6 !default;
+$font-size-base: 14px !default;
+$font-size-small: 12px !default;