vue+1x.antdv级联多选组件

image.png

1.实现多选级联样式表功能,根据自身情况 引入到自己的项目中

(借鉴doit-ui-web ,基于ant.design封装的功能组件,遇到很多坑已踩过,需要的直接拿走可以用复用~分享)

组件目录如图

image.png

Cascader.vue

<template>
  <div
    class="gb-ant-select-multiple-cascader"
    :class="{ 'multiple-cascader-outside': !isClickOutSide }"
    v-clickoutside="handleDropDownOutSide"
  >
    <a-select
      v-bind="$attrs"
      v-on="$listeners"
      mode="multiple"
      :maxTagTextLength="maxTagTextLength"
      :maxTagCount="maxTagCount"
      style="width:100%"
      :placeholder="placeholder"
      :value="selectedValueArr"
      :notFoundContent="null"
      :open="isOpen"
      showArrow
      :allowClear="allowClear"
      optionLabelProp="text"
      :dropdownMatchSelectWidth="false"
      :getPopupContainer="tirggerNode => tirggerNode.parentNode"
      @focus="handleFocus"
      @deselect="handleDeselect"
    >
      <a-icon
        type="close-circle"
        slot="clearIcon"
        theme="filled"
        @click="handleClearAll"
      />
      <template slot="dropdownRender" slot-scope="menu">
        <v-nodes :vnodes="menu" />
        <div :class="dropdownClassName">
          <div class="cascader-not-content" v-if="treeDataList.length <= 0">
            <a-empty :image="simpleImage" :description="noDataText"></a-empty>
          </div>
          <div class="cascader-content-wrap" v-else>
            <div class="cascader-content-container">
              <ul
                class="cascader-content-list"
                v-for="(itemList, levelIndex) in treeDataList"
                :key="levelIndex"
              >
                <li
                  class="cascader-content-item cascader-content-item-check-all"
                  @click="handleCascaderAllItemClick(isCheckAll)"
                  v-if="levelIndex === 0"
                >
                  <a-checkbox
                    :indeterminate="isIndeterminateAll"
                    v-model="isCheckAll"
                  />
                  <span class="checkbox-text">{{ allText }}</span>
                </li>
                <li
                  class="cascader-content-item"
                  v-for="(subItem, subIndex) in itemList"
                  :key="subItem[selectOptionsConfig.key]"
                  :title="subItem[selectOptionsConfig.text]"
                  :class="{ 'cascader-content-item-active': subItem.$active }"
                  @click="
                    handleCascaderItemClick(subItem, subIndex, levelIndex)
                  "
                >
                  <a-checkbox
                    :indeterminate="!!subItem.$indeterminate"
                    :checked="!!subItem.$checked"
                    @click.self="
                      e => handleCheckClick(e, subItem, subIndex, levelIndex)
                    "
                  />
                  <span class="checkbox-text">{{
                    subItem[selectOptionsConfig.text]
                  }}</span>
                  <a-icon
                    type="right"
                    style="font-size:10px;"
                    v-if="
                      subItem[selectOptionsConfig.children] &&
                        subItem[selectOptionsConfig.children].length > 0
                    "
                  />
                </li>
              </ul>
            </div>
          </div>
        </div>
      </template>
      <a-select-option
        v-for="item in treeToList"
        :key="item[selectOptionsConfig.key]"
        :value="item[selectOptionsConfig.value]"
        :text="item[selectOptionsConfig.text]"
      >
        {{ item[selectOptionsConfig.text] }}
      </a-select-option>
    </a-select>
  </div>
</template>

<script>
import { Empty } from "ant-design-vue";
import { cloneDeep } from "lodash";
const clickoutside = {
  // 初始化指令
  bind(el, binding) {
    function documentHandler(e) {
      if (el.contains(e.target)) {
        return false;
      }
      if (binding.expression) {
        binding.value(e);
      }
    }
    el.__vueClickOutside__ = documentHandler;
    document.addEventListener("click", documentHandler);
  },
  update() {},
  unbind(el) {
    document.removeEventListener("click", el.__vueClickOutside__);
    delete el.__vueClickOutside__;
  }
};
export default {
  name: "MultipleCascader",
  components: {
    VNodes: {
      functional: true,
      render: (h, ctx) => {
        return ctx.props.vnodes;
      }
    }
  },
  directives: { clickoutside },
  props: {
    allowClear: {
      type: Boolean,
      default: true
    },
    allText: {
      type: String,
      default: "全部"
    },
    noDataText: {
      type: String,
      default: "暂无数据"
    },
    treeData: {
      type: Array,
      default: () => {
        return [];
      }
    },
    dropdownClassName: {
      type: String
    },
    selectOptionsConfig: {
      type: Object,
      default: () => {
        return {
          key: "id",
          value: "value",
          text: "title",
          children: "children"
        };
      }
    },
    maxTagCount: {
      type: Number
    },
    maxTagTextLength: {
      type: Number
    },
    placeholder: {
      type: String,
      default: "请搜索"
    },
    checkAll: {
      type: Boolean,
      default: false
    },
    value: {
      type: Array
    },
  
  },
  beforeCreate() {
    this.simpleImage = Empty.PRESENTED_IMAGE_SIMPLE;
  },
  destroyed() {
    this.timer && clearInterval(this.timer);
  },
  data() {
    return {
      isOpen: false,
      isCheckAll: this.checkAll,
      isIndeterminateAll: false,
      isClickOutSide: true,
      selectedValueArr: this.value || undefined,
      treeDataList: cloneDeep(this.treeData),
      treeToList: [],
      selectedValueArrAll:[]
    };
  },
  watch: {
    checkAll: {
      handler(newVal) {
        if (newVal) {
          this.timer = setInterval(() => {
            if (this.treeDataList.length > 0) {
              clearInterval(this.timer);
              this.handleCascaderAllItemClick(!newVal);
            }
          }, 30);
        }
      },
      immediate: true
    },
    value: {
      handler(newVal) {
        console.log('6666selectedValueArr77777 :>> ', newVal);
        this.selectedValueArr = newVal;
        this.initDefaultKeys(newVal, this.treeDataList);
        return newVal;
      },
      immediate: true
    },
    selectedValueArrAll: {
      handler(newVal) {
        this.selectedValueArr = newVal;
        this.initDefaultKeys(newVal, this.treeDataList);
      
      },
      immediate: true
    },
    treeData(newVal) {
      this.treeListToArrList(newVal[0]);
      this.initDefaultKeys(this.selectedValueArr, newVal);
      this.treeDataList = newVal;
      return newVal;
    }
  },
  methods: {
    handleClearAll() {
      this.treeDataList = this.treeData;
      this.isOpen = false;
      this.isCheckAll = false;
      this.isClickOutSide = true;
      this.isIndeterminateAll = false;
      this.updatePostData();
    },
    initDefaultKeys(selectedArr, treeDataList) {
      if (
        selectedArr &&
        selectedArr.length > 0 &&
        treeDataList &&
        treeDataList.length > 0
      ) {
        const treeDataListClone = cloneDeep(treeDataList);
        const treeToListClone = cloneDeep(this.treeToList);
        selectedArr.forEach(item => {
          const curretnItemList = [];
          this.findKeysItem(treeDataListClone[0], item, curretnItemList);
          let currentItem = {};
          if (curretnItemList.length > 0) {
            currentItem = curretnItemList[0];
          }
          if (
            !treeToListClone.find(
              listItem =>
                listItem[this.selectOptionsConfig.value] ===
                currentItem[this.selectOptionsConfig.value]
            )
          ) {
            treeToListClone.push(currentItem);
          }
          currentItem.$checked = true;
          if (
            currentItem[this.selectOptionsConfig.children] &&
            currentItem[this.selectOptionsConfig.children].length > 0
          ) {
            this.setAllDataTreeChecked(
              currentItem[this.selectOptionsConfig.children],
              true
            );
          }
        });
        this.setCheckBoxIndeteriminate(treeDataListClone[0]);
        this.$nextTick(() => {
          this.treeToList = treeToListClone;
          this.treeDataList = treeDataListClone;
        });
      }
    },
    handleCascaderAllItemClick(checkAll) {
      const treeDataListClone = cloneDeep(this.treeDataList);
      // 触发事件的时候v-model中的数据还没有改变,所以要取反
      this.setAllDataTreeChecked(treeDataListClone[0], !checkAll);
      this.clearAllDataActive(treeDataListClone[0]);
      this.setCheckBoxIndeteriminate(treeDataListClone[0]);
      this.treeDataList = treeDataListClone;
      this.updatePostData();
    },
    handleDeselect(value) {
      const treeDataListClone = cloneDeep(this.treeDataList);
      const currentItemList = [];
      this.findKeysItem(treeDataListClone[0], value, currentItemList);
      let currentItem = {};
      if (currentItemList.length > 0) {
        currentItem = currentItemList[0];
      }
      currentItem.$checked = false;
      currentItem.$active = false;
      if (
        currentItem[this.selectOptionsConfig.children] &&
        currentItem[this.selectOptionsConfig.children].length > 0
      ) {
        this.setAllDataTreeChecked(
          currentItem[this.selectOptionsConfig.children],
          false
        );
      }
      this.setCheckBoxIndeteriminate(treeDataListClone[0]);
      this.treeDataList = treeDataListClone;
      this.updatePostData();
    },
    handleCheckClick(e, item, index, levelIndex) {
      const treeDataListClone = cloneDeep(this.treeDataList);
      const childrenTag = this.selectOptionsConfig.children;
      const valueTag = this.selectOptionsConfig.value;
      const currentItemList = [];
      this.findKeysItem(treeDataListClone[0], item[valueTag], currentItemList);
      let currentItem = {};
      if (currentItemList.length > 0) {
        currentItem = currentItemList[0];
      }
      e.stopPropagation();
      e.cancelBubble = true;
      const checked = e.target.checked;
      console.log('checked :>> ', checked);
      if (!currentItem.$active && levelIndex !== treeDataListClone.length - 1) {
      
        // 清空所有选中状态
        this.clearAllDataActive(treeDataListClone[0]);
      }
      if (currentItem[childrenTag] && currentItem[childrenTag].length > 0) {
        // 可展开
        if (!currentItem.$active) {
          const nextIndex = levelIndex + 1;
          if (treeDataListClone[nextIndex]) {
            treeDataListClone.splice(nextIndex);
          }
        }
      } else {
        // 不可展开
        const nextIndex = levelIndex + 1;
        if (treeDataListClone[nextIndex]) {
          treeDataListClone.splice(nextIndex);
        }
      }
      if (currentItem[childrenTag] && currentItem[childrenTag].length > 0) {
        console.log('777 :>> ', 7777);
        this.setAllDataTreeChecked(currentItem[childrenTag], checked);
      } else {
        currentItem.$checked = checked;
      }
      console.log('777 :>> ', treeDataListClone[0]);
      this.setCheckBoxIndeteriminate(treeDataListClone[0]);
      this.treeDataList = treeDataListClone;
      this.$emit("handleCheckboxChange", {
        event: e,
        item,
        index,
        levelIndex
      });
      this.updatePostData();
    },
    // 单个item点击事件
    handleCascaderItemClick(item, index, levelIndex) {
      const treeDataListClone = cloneDeep(this.treeDataList);
      const childrenTag = this.selectOptionsConfig.children;
      const valueTag = this.selectOptionsConfig.value;
      const currentItemList = [];
      this.findKeysItem(treeDataListClone[0], item[valueTag], currentItemList);
      let currentItem = {};
      if (currentItemList.length > 0) {
        currentItem = currentItemList[0];
      }
      const parentItemsList = [];
      this.findAllParentItems(
        currentItem[valueTag],
        treeDataListClone[0],
        treeDataListClone[0],
        parentItemsList
      );
      parentItemsList.push(currentItem);
      this.clearAllDataActive(treeDataListClone[0]);
      parentItemsList.forEach(activeItem => {
        if (activeItem[childrenTag] && activeItem[childrenTag].length > 0) {
          activeItem.$active = true;
        }
      });
      if (currentItem[childrenTag] && currentItem[childrenTag].length > 0) {
        const nextIndex = levelIndex + 1;
        if (treeDataListClone[nextIndex]) {
          treeDataListClone.splice(nextIndex);
          treeDataListClone[nextIndex] = currentItem[childrenTag];
        } else {
          treeDataListClone.push(currentItem[childrenTag]);
        }
        this.addHideSelectedList(currentItem[childrenTag]);
      } else {
        const nextIndex = levelIndex + 1;
        if (treeDataListClone[nextIndex]) {
          treeDataListClone.splice(nextIndex);
        }
        currentItem.$checked = !currentItem.$checked;
      }
      this.setCheckBoxIndeteriminate(treeDataListClone[0]);
      this.treeDataList = treeDataListClone;
      this.updatePostData();
    },
    handleFocus() {
      this.isOpen = true;
      this.isClickOutSide = false;
    },
    updatePostData() {
      const childrenTag = this.selectOptionsConfig.children;
      const valueTag = this.selectOptionsConfig.value;
      let selectedValueArr = [];
      _getAllItemChecked(this.treeDataList[0]);
      this.$emit("change", selectedValueArr)
      // console.log('currentCheckedAll :>> ', selectedValueArr);
       this.selectedValueArrAll=selectedValueArr
      // this.selectedValueArr=selectedValueArr
      function _getAllItemChecked(treeDataList) {
        let parentItem;
        treeDataList.forEach(item => {
          if (item[childrenTag] && item[childrenTag].length > 0) {
            parentItem = item;
            const currentCheckedAll = [];
            const currentCheckedAllItems = [];
            _getSubChecked(parentItem[childrenTag], currentCheckedAll);
            _getSubCheckedItems(
              parentItem[childrenTag],
              currentCheckedAllItems
            );
            if (currentCheckedAll.every(checkItem => checkItem === true)) {
              if (parentItem[valueTag]) {
              
                selectedValueArr.push(parentItem[valueTag]);
                
              }
            } else if (
              currentCheckedAll.some(checkItem => checkItem === true)
            ) {
              currentCheckedAllItems.forEach(selectedItem => {
                if (selectedItem[valueTag]) {
                  selectedValueArr.push(selectedItem[valueTag]);
                }
              });
            }
          } else {
            if (item.$checked) {
              selectedValueArr.push(item[valueTag]);
            }
          }
      
          
        });
      }
      function _getSubChecked(itemList, arr) {
        itemList.forEach(item => {
          arr.push(!!item.$checked);
          if (item[childrenTag] && item[childrenTag].length > 0) {
            _getSubChecked(item[childrenTag], arr);
          }
        });
      }
      function _getSubCheckedItems(itemList, arr) {
        itemList.forEach(item => {
          if (item.$checked) {
            arr.push(item);
          } else {
            if (item[childrenTag] && item[childrenTag].length > 0) {
              _getSubCheckedItems(item[childrenTag], arr);
            }
          }
        });
      }
      
    },
    // 点击组件外部区域
    handleDropDownOutSide() {
      this.isOpen = false;
      this.isClickOutSide = true;
    },
    // 设置当前的选中框的全选等状态
    setCheckBoxIndeteriminate(treeDataList) {
      const childrenTag = this.selectOptionsConfig.children;
      _getAllItemChecked(treeDataList);
      const checkedAllArr = [];
      _getAllItemCheckedAll(treeDataList, checkedAllArr);
      if (checkedAllArr.every(item => item === true)) {
        this.isCheckAll = true;
        this.isIndeterminateAll = false;
      } else if (checkedAllArr.some(item => item === true)) {
        this.isCheckAll = false;
        this.isIndeterminateAll = true;
      } else if (checkedAllArr.every(item => item === false)) {
        this.isCheckAll = false;
        this.isIndeterminateAll = false;
      }
      function _getAllItemCheckedAll(itemList, arr) {
        itemList.forEach(item => {
          arr.push(!!item.$checked);
          if (item[childrenTag] && item[childrenTag].length > 0) {
            _getAllItemCheckedAll(item[childrenTag], arr);
          }
        });
      }
      function _getAllItemChecked(treeDataList) {
        let parentItem;
        treeDataList.forEach(item => {
          if (item[childrenTag] && item[childrenTag].length > 0) {
            parentItem = item;
            _getAllItemChecked(item[childrenTag]);
            const currentCheckedAll = [];
            _getSubChecked(parentItem[childrenTag], currentCheckedAll);
            if (currentCheckedAll.every(checkItem => checkItem === true)) {
              parentItem.$checked = true;
              parentItem.$indeterminate = false;
            } else if (
              currentCheckedAll.some(checkItem => checkItem === true)
            ) {
              parentItem.$checked = false;
              parentItem.$indeterminate = true;
            } else if (
              currentCheckedAll.every(checkItem => checkItem === false)
            ) {
              parentItem.$checked = false;
              parentItem.$indeterminate = false;
            }
          }
        });
      }
      function _getSubChecked(itemList, arr) {
        itemList.forEach(item => {
          arr.push(!!item.$checked);
          if (item[childrenTag] && item[childrenTag].length > 0) {
            _getSubChecked(item[childrenTag], arr);
          }
        });
      }
    },
    // 设置所有选中和非选中
    setAllDataTreeChecked(treeList, checked) {
      const childrenTag = this.selectOptionsConfig.children;
      treeList.forEach(item => {
        item.$checked = checked;
        if (item[childrenTag] && item[childrenTag].length > 0) {
          this.setAllDataTreeChecked(item[childrenTag], checked);
        }
      });
    },
    // 清空所有的active状态
    clearAllDataActive(treeList) {
      const childrenTag = this.selectOptionsConfig.children;
      treeList.forEach(item => {
        item.$active = false;
        if (item[childrenTag] && item[childrenTag].length > 0) {
          this.clearAllDataActive(item[childrenTag]);
        }
      });
    },
    findKeysItem(treeDataList, currentKey, currentItem) {
      const childrenTag = this.selectOptionsConfig.children;
      treeDataList.forEach(item => {
        if (item[this.selectOptionsConfig.value] === currentKey) {
          currentItem.push(item);
        } else {
          if (item[childrenTag] && item[childrenTag].length > 0) {
            this.findKeysItem(item[childrenTag], currentKey, currentItem);
          }
        }
      });
    },
    findAllParentItems(
      currentKey,
      treeDataList,
      originTreeDataList,
      parentItemsList,
      parentItem,
      parentItemsHasKey
    ) {
      if (parentItem && parentItemsHasKey) {
        parentItemsList.unshift(parentItem);
        this.findAllParentItems(
          parentItem[this.selectOptionsConfig.value],
          treeDataList,
          originTreeDataList,
          parentItemsList
        );
      } else {
        this.findKeysAndParentItem(
          currentKey,
          treeDataList,
          originTreeDataList,
          parentItemsList,
          parentItem,
          parentItemsHasKey
        );
      }
    },
    findKeysAndParentItem(
      currentKey,
      treeDataList,
      originTreeDataList,
      parentItemsList,
      parentItem
    ) {
      const childrenTag = this.selectOptionsConfig.children;
      treeDataList.forEach(item => {
        if (item[this.selectOptionsConfig.value] === currentKey && parentItem) {
          this.findAllParentItems(
            parentItem[this.selectOptionsConfig.value],
            originTreeDataList,
            originTreeDataList,
            parentItemsList,
            parentItem,
            true
          );
        } else {
          if (item[childrenTag] && item[childrenTag].length > 0) {
            this.findKeysAndParentItem(
              currentKey,
              item[childrenTag],
              originTreeDataList,
              parentItemsList,
              item
            );
          }
        }
      });
    },
    // 将树形结构数据转换成平面结构
    treeListToArrList(treeList) {
      const arrList = [];
      if (treeList && treeList[0]) {
        treeList.forEach(item => {
          arrList.push(item);
        });
        this.treeToList = arrList;
      }
    },
    addHideSelectedList(treeList) {
      const treeToListClone = Array.from(this.treeToList);
      treeList.forEach(item => {
        if (
          !treeToListClone.find(
            listItem =>
              listItem[this.selectOptionsConfig.value] ===
              item[this.selectOptionsConfig.value]
          )
        ) {
          treeToListClone.push(item);
        }
      });
      this.treeToList = treeToListClone;
    }
  }
};
</script>
<style lang="less">
.gb-ant-select-multiple-cascader {
  .ant-select-dropdown-menu-item {
    display: none;
  }
  .cascader-content-item {
    .checkbox-text {
      padding-left: 8px;
      font-size: 12px;
      color: #4a4a4a;
      cursor: default;
      flex: 1;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      text-align: left;
    }
    &.cascader-content-item-active {
      background-color: rgba(66, 70, 86, 0.05);
      .checkbox-text {
        color: #1d47aa;
      }
    }
    .ant-checkbox-wrapper {
      .ant-checkbox-indeterminate {
        .ant-checkbox-inner {
          &:after {
            background-color: #1d47aa;
            left: 48%;
          }
        }
      }
      .ant-checkbox-inner {
        width: 14px;
        height: 14px;
        background-color: #fff;
        border-color: #7d8292;
        &:after {
          border-color: #1d47aa;
          left: 20%;
        }
      }
    }
  }
  .ant-select-dropdown--multiple {
    min-width: auto !important;
  }
  &.multiple-cascader-outside {
    .ant-select-arrow {
      transform: rotate(180deg);
    }
  }
  .ant-select-arrow {
    margin-top: -8px;
    transition: transform 0.3s;
  }
  .ant-select-dropdown-menu-root {
    display: none;
  }
  .cascader-content-right {
    .right-wrap {
      .ant-checkbox {
        top: 0;
      }
    }
  }
}
</style>
<style lang="less" scoped>
.gb-ant-select-multiple-cascader {
  position: relative;
  .cascader-content-wrap {
    height: 100%;
    .cascader-content-container {
      display: flex;
      flex-direction: row;
      .cascader-content-list {
        list-style: none;
        padding: 0;
        margin: 0;
        width: 153px;
        box-sizing: border-box;
        padding: 11px 0;
        max-height: 160px;
        overflow-y: auto;
        border-right: 1px solid rgba(222, 223, 226, 0.3);
        .cascader-content-item {
          padding: 5px 16px;
          margin-top: 5px;
          display: flex;
          flex-direction: row;
          align-items: center;
          line-height: 1;
          &:hover {
            background-color: rgba(66, 70, 86, 0.05);
          }
        }
      }
    }
  }
  .cascader-not-content {
    padding: 10px;
  }
}
</style>

页面使用

<template>
                <CascaderSelect
                   allowClear
                    style="width:450px;"
                    :maxTagCount="3"
                    :maxTagTextLength="4"
                    placeholder="请选择"
                    :selectOptionsConfig="{
                      key: 'fullPath',
                      value: 'fullPath',
                      text: 'name',
                      children: 'children'
                    }"
                    allText="全选"
                    noDataText="暂无数据"
                    dropdownClassName="customer-multiple-cascader"
                    :treeData="[multipleTreeData]"
                    @handleCheckboxChange="handleCheckboxChange"
                        />  
</template>
<script>
 export default {
    name: "PayOrderModal",
    components: {
      CascaderSelect
    },
    data() {
     return {
        multipleTreeData: [
              {
                fullPath: '01',
                name: '广东省',
                children: [
                  {
                    fullPath: '0101',
                    name: '广州市',
                    children: [
                      { fullPath: '010101', name: '南沙区', children: [] },
                      { fullPath: '010102', name: '越秀区', children: [] },
                    ],
                  },
                  {
                    fullPath: '0102',
                    name: '深圳市',
                    children: [
                      { fullPath: '010201', name: '南山区', children: [] },
                      { fullPath: '010202', name: '福田区', children: [] },
                      { fullPath: '010203', name: '宝安区', children: [] },
                      { fullPath: '010204', name: '龙华区', children: [] },
                      { fullPath: '010205', name: '龙岗区', children: [] },
                      { fullPath: '010206', name: '盐田区', children: [] },
                      { fullPath: '010207', name: '光明新区', children: [] },
                      { fullPath: '010208', name: '罗湖区', children: [] },
                    ],
                  },
                ],
              },
              {
                fullPath: '02',
                name: '江西省',
                children: [
                  {
                    fullPath: '0201',
                    name: '南昌市',
                    children: [
                      { fullPath: '020101', name: '南昌县', children: [] },
                    ],
                  },
                  {
                    fullPath: '0202',
                    name: '宜春市',
                    children: [
                      { fullPath: '020201', name: '铜鼓县', children: [] },
                      { fullPath: '020202', name: '宜丰县', children: [] },
                      { fullPath: '020203', name: '上高县', children: [] },
                      { fullPath: '020204', name: '万载县', children: [] },
                    ],
                  },
                ],
              },
            ],
     }
    
    },
    methods:{
        handleCheckboxChange(val){
            console.log(555, val)
            // this.currentProd = value;
            // this.form.receivableMoney = value.price
        },
    }
 }
</script>
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351

推荐阅读更多精彩内容