react权限---菜单的动态生成

前端权限控制一般有4种

1.菜单的控制

2.界面的控制

3.按钮的控制

4.请求和响应的控制

本文主要讲述如何使用react框架事件前端权限对菜单的控制。

第一步:

准备菜单数据,在该菜单数据中配置好路由跳转的路径和组件存在的路径。

菜单数据如下所示:

permissionList:[{
permission_no: 1
menu_name: "系统设置"
menu_url: "/index/sysIndex"
path_name: "systemIndex"
component_path: "user/Home/SystemIndex"
menu_imgClass: ""
menu_state: 0
menu_father: 0
menu_id: 1
chidPermissions:[
{
permission_no: 2
menu_name: "会员信息统计"
menu_url: "/index/sysIndex/userTotal"
path_name: "loginLog"
component_path: "user/Home/UserTotal"
menu_imgClass: null
menu_state: 0
menu_father: 1
menu_id: 11
chidPermissions: []},

{
permission_no: 2
menu_name: "登录日志"
menu_url: "/index/sysIndex/loginLog"
path_name: "loginLog"
component_path: "user/Home/LoginLog"
menu_imgClass: null
menu_state: 0
menu_father: 1
menu_id: 11
chidPermissions: []},

{
permission_no: 2
menu_name: "登录日志"
menu_url: "/index/sysIndex/loginLog"
path_name: "loginLog"
component_path: "user/Home/LoginLog"
menu_imgClass: null
menu_state: 0
menu_father: 1
menu_id: 11
chidPermissions: []},

{
permission_no: 3
menu_name: "个人中心"
menu_url: "/index/sysIndex/userSet"
path_name: "userSet"
component_path: "user/Home/UserSet"
menu_imgClass: null
menu_state: 0
menu_father: 1
menu_id: 12
chidPermissions: []}
]},
{
permission_no: 4
menu_name: "任务管理"
menu_url: "/index/task"
path_name: "task"
component_path: "user/Task/TaskManger"
menu_imgClass: null
menu_state: 0
menu_father: 0
menu_id: 2,
chidPermissions:[
{
permission_no: 5
menu_name: "任务完成记录"
menu_url: "/index/task/taskFinish"
path_name: "taskFinish"
component_path: "user/Task/TaskFinish"
menu_imgClass: null
menu_state: 0
menu_father: 2
menu_id: 21
chidPermissions: []
},{
permission_no: 6
menu_name: "任务列表"
menu_url: "/index/task/taskList"
path_name: "taskList"
component_path: "user/Task/TaskList"
menu_imgClass: null
menu_state: 0
menu_father: 2
menu_id: 22
chidPermissions: []
}
]
},
{
permission_no: 7
menu_name: "权限管理"
menu_url: "/index/permission"
path_name: "permission"
component_path: "user/UserRole/Permission"
menu_imgClass: null
menu_state: 0
menu_father: 0
menu_id: 3,
chidPermissions:[
{
permission_no: 8
menu_name: "角色管理"
menu_url: "/index/permission/roleMange"
path_name: "roleManger"
component_path: "user/UserRole/RoleMange"
menu_imgClass: null
menu_state: 0
menu_father: 3
menu_id: 31
chidPermissions: []
},
{
permission_no: 9
menu_name: "用户管理"
menu_url: "/index/permission/userMange"
path_name: "userMange"
component_path: "user/UserRole/UserMange"
menu_imgClass: null
menu_state: 0
menu_father: 3
menu_id: 32
chidPermissions: []
}
]
},

{
permission_no: 10
menu_name: "小程序管理"
menu_url: "/index/appMange"
path_name: "appMange"
component_path: "user/AppAs/AppMange"
menu_imgClass: null
menu_state: 0
menu_father: 0
menu_id: 4,
chidPermissions:[
{
permission_no: 11
menu_name: "客服管理"
menu_url: "/index/appMange/serviceMange"
path_name: "serviceMange"
component_path: "user/AppAs/ServiceMange"
menu_imgClass: null
menu_state: 0
menu_father: 4
menu_id: 41
chidPermissions: []
},
{
permission_no: 12
menu_name: "导航管理"
menu_url: "/index/appMange/navMange"
path_name: "navMange"
component_path: "user/AppAs/NavMange"
menu_imgClass: null
menu_state: 0
menu_father: 4
menu_id: 42
chidPermissions: []
}
]
},
{
permission_no: 13
menu_name: "会员管理"
menu_url: "/index/memberMange"
path_name: "memberMange"
component_path: "user/UserSet/MemberMange"
menu_imgClass: null
menu_state: 0
menu_father: 0
menu_id: 5,
chidPermissions: [
{
permission_no: 14
menu_name: "会员等级设置"
menu_url: "/index/memberMange/memberLevel"
path_name: "memberLevel"
component_path: "user/UserSet/MemberLevel"
menu_imgClass: null
menu_state: 0
menu_father: 5
menu_id: 51
chidPermissions: []
},
{
permission_no: 15
menu_name: "会员积分"
menu_url: "/index/memberMange/memberScores"
path_name: "memberScores"
component_path: "user/UserSet/MemberScores"
menu_imgClass: null
menu_state: 0
menu_father: 5
menu_id: 52
chidPermissions: []
},
{
permission_no: 16
menu_name: "会员管理列表"
menu_url: "/index/memberMange/memberList"
path_name: "memberList"
component_path: "user/UserSet/MemberList"
menu_imgClass: null
menu_state: 0
menu_father: 5
menu_id: 53
chidPermissions: []
}
]
},


{
permission_no: 17
menu_name: "文章管理"
menu_url: "/index/articleMange"
path_name: "articleMange"
component_path: "user/TxtAs/ArticleMange"
menu_imgClass: null
menu_state: 0
menu_father: 0
menu_id: 6,
chidPermissions: [
{
permission_no: 18
menu_name: "文章分类"
menu_url: "/index/articleMange/articleClass"
path_name: "articleClass"
component_path: "user/TxtAs/ArticleClass"
menu_imgClass: null
menu_state: 0
menu_father: 6
menu_id: 61
chidPermissions: []
},{
permission_no: 19
menu_name: "审核文章"
menu_url: "/index/articleMange/articleAudit"
path_name: "articleAudit"
component_path: "user/TxtAs/ArticleAudit"
menu_imgClass: null
menu_state: 0
menu_father: 6
menu_id: 62
chidPermissions: []
}
]
},
{
permission_no: 20
menu_name: "意见与建议"
menu_url: "/index/advise"
path_name: "advise"
component_path: "user/Opinion/Advise"
menu_imgClass: null
menu_state: 0
menu_father: 0
menu_id: 7
chidPermissions: [
{
permission_no: 21
menu_name: "意见与建议"
menu_url: "/index/advise/OpinionAs"
path_name: "advise"
component_path: "user/Opinion/OpinionAs"
menu_imgClass: null
menu_state: 0
menu_father: 7
menu_id: 71
chidPermissions: []
}
]
}

]

第二步搭建项目结构


TIM图片20200714150113.png

其中component的结构如下:


11.png

第三步动态生成菜单,写成一个组件:

 // 生成左边菜单
  bindMenu(menulist){
    let MenuList= menulist.map((item)=>{
      if(item.chidPermissions.length===0){  //没有子菜单
        return <Menu.Item key={item.permission_no} onClick={()=>this.add(item.menu_name,item.menu_url,item.menu_id)} ><Link to={item.menu_url}>{item.menu_name}</Link></Menu.Item>
      }
      else{
        return <SubMenu key={item.permission_no} icon={<UserOutlined />} title={item.menu_name}>
       {this.bindMenu(item.chidPermissions)}
        </SubMenu>
      }

    })
    return MenuList
  }
  componentWillMount() {
    console.log("will mount")
    // console.log(JSON.parse(this.props.user.user.permissionList))
    // let menuList = window.sessionStorage.getItem('user')?(JSON.parse(window.sessionStorage.getItem('user'))):[];
    // console.log('类相关',typeof menuList);
    let leftMenu = this.bindMenu(this.props.user.user.permissionList);
    this.setState({
      leftMenu:leftMenu
    })
  }

第四步
动态生成路由,写成一个组件

 // 动态生成路由
  bindRouter(list){
    let routerList = list.map((item)=>{
      if(item.chidPermissions.length === 0){
        return <Route key={item.permission_no} path={item.menu_url} component={loadable(()=>import(`./${item.component_path}`))}></Route>
      }else {
        return <Route key={item.permission_no} path={item.menu_url} render={()=>{
            let componentName = loadable(()=>import(`./${item.component_path}`));
            return <componentName>
              {this.bindRouter(item.chidPermissions)}
            </componentName>
        }}>
        </Route>

      }
    })
    return routerList
  }
  componentDidMount() {
    let routerList = this.bindRouter(this.props.user.user.permissionList)
    console.log('routerList',routerList);
    this.setState({
      routerList:routerList
    })
  }

第五步调用菜单组件和动态路由组件

第六步前端可勾选菜单向服务器发起请求(结合ant的树形控件)

先创建一个树形控件的组件名为TreeComponent.js

import React from 'react'
import { Tree } from 'antd';
import  treeStore from '../../../store/TreeStore'
const { TreeNode } = Tree;


class Demo extends React.Component {
  constructor(props){
    super(props)
    this.state={
      autoExpandParent:true,
      expandedKeys:[],  //展开指定的树节点
      checkedKeys:[],
      selectedKeys:[],//设置选中的树节点
      treeData:[],//数据
      menuData:[],
      children:[],
      isdata:false,
      isdisabled:true, //禁用子节点
      isLevel:[], //存取点击的一级选项
    }
  }

  componentDidMount() {
    new Promise((resolve, reject) =>{
      this.setState({

        menuData:JSON.parse(sessionStorage.getItem("user")).permissionList

      })
      resolve()
    } ).then(()=>{
      new Promise((resolve, reject) =>{
        this.setData(this.state.menuData)
        resolve()
      } ).then(()=>{
        console.log(this.state.treeData)
        this.setState({
          isdata:true
        })
      })
    })
  }
  setData(val){
    for (let i=0; i<val.length;i++) {
      this.setData({
        treeData: this.state.treeData.push({
          title: val[i].menu_name,
          key: val[i].permission_no,
          children: []
        })
      })

      if (val[i].chidPermissions && val[i].chidPermissions.length>0){
        for (let j=0 ;j<val[i].chidPermissions.length;j++){
          this.setState({
            'this.state.treeData[i].children':this.state.treeData[i].children.push({
              title: val[i].chidPermissions[j].menu_name,
              key: val[i].chidPermissions[j].permission_no,
              disabled: this.state.isdisabled,
              disableCheckbox:true
            })
          })
        }

      }
    }
  }

  // 展开/收起节点时触发
  onExpand =(expandedKeys) => {
    console.log('onExpand', expandedKeys);
    this.setState({
      expandedKeys:expandedKeys,
    })
  }
  onCheck = (checkedKeys,info )=> {
    new Promise((resolve, reject) => {
      this.setState({
        checkedKeys:this.uniq(this.state. checkedKeys.concat(checkedKeys.checked)),
        selectedKeys:this.uniq(this.state.selectedKeys.concat(checkedKeys.checked)),
      })
      this.childrenDisabled(info.node.children)

      // 判断一级选项是否被选中
      if(info.node.children){
        // 判断是否点击的是一级选项
        this.setState({
          isLevel:this.uniq(this.state.isLevel.concat(checkedKeys.checked))
        })

        if(this.checkArr(info.node.key,this.state.isLevel)){
          console.log(2)
          // 移除一级选项
          this.setState({
            checkedKeys:this.remove(this.state.checkedKeys,info.node.key),
            selectedKeys: this.remove(this.state.selectedKeys,info.node.key),
            isLevel: this.remove(this.state.isLevel,info.node.key)
          })
          // 移除二级选中状态
          new Promise(resolve1 => {
            let chilArr = this.getLevelChilKey(info.node.key,this.state.treeData)
            resolve1(chilArr)
          }).then((valArr)=>{
            for (let i=0; i<valArr.length;i++){
              this.setState({
                checkedKeys:   this.remove(this.state.checkedKeys,valArr[i].key),
                selectedKeys: this.remove(this.state.selectedKeys,valArr[i].key)
              })
            }
          })
          this.childeenIsDisabled(info.node.children)
        }
      }
      resolve()
    }).then(()=>{
      console.log('选中1',this.state.selectedKeys)
    })
  };
  onSelect = (selectedKeys, info) => {
    new Promise((resolve, reject) => {
      // 判断是否点击一级选项
      // 判断是否有children
      if (info.node.children){
        // 判断是否点击一级选项
        // 是
        if(this.checkLevelOne(selectedKeys)){
          // 设置它下面的子选项可用
          this.childrenDisabled(info.node.children)
        }

        // 判断isLevel是否从复选框选中
        if(this.checkArr(info.node.key,this.state.isLevel)){
          this.setState({
            isLevel: this.remove(this.state.isLevel,info.node.key)
          })

        }else {
          this.setState({
            isLevel:this.state.isLevel.concat(selectedKeys)
          })
        }

      }
      // 启用切换到禁用
      if(this.checkISLevelOne(info.node.key,this.state.isLevel)){
        let indexVal = this.getIndex(info.node.key,this.state.treeData)
        this.childeenIsDisabled(info.node.children)
        // 一级选项
        this.setState({
          isLevel: this.remove(this.state.isLevel,info.node.key)
        })
      }

      // 所有元素
      // 判断点击元素是否一点击
      if(this.checkArr(selectedKeys,this.state.checkedKeys)){
        // 已点击
        // 取消选中状态
        this.setState({
          checkedKeys:   this.remove(this.state.checkedKeys,selectedKeys),
          selectedKeys: this.remove(this.state.selectedKeys,info.selectedNodes[0].key)
        })
      }else { //没点击 添加选中状态
        this.setState({
          checkedKeys:this.state.checkedKeys.concat(selectedKeys),
        })

        if (info.selectedNodes.length==0){
          this.setState({
            selectedKeys:[],
            checkedKeys:[]
          })
        }else {
          this.setState({
            selectedKeys:this.state.selectedKeys.concat(info.selectedNodes[0].key)
          })

        }
      }

      resolve()
    }).then(()=>{
      console.log( '选择中2', this.state.selectedKeys)
      treeStore.addKey( this.state.selectedKeys)

    })

  };

  // 检查数组是否存在改值
  checkArr(val,arr){
    let istrue=false
    for (let i=0;i<arr.length;i++){
      if (val==arr[i]){
        istrue = true
      }
    }
    return istrue
  }
// 移除指定的元素
  remove(arr, item) {
    var result=[];
    for(var i=0; i<arr.length; i++){
      if(arr[i]!=item){
        result.push(arr[i]);
      }
    }
    return result;
  }
  获取两数组不同元素
  getArrDifference(arr1, arr2) {
    return arr1.concat(arr2).filter(function(v, i, arr) {
      return arr.indexOf(v) === arr.lastIndexOf(v);
    });
  }

  // 获取一级选项key
  getLevelOne(arr){
    var newArr=[]
    for (let i=0; i<arr.length;i++){
      newArr.push( arr[i].key)
    }
    return newArr
  }

  // 判断是否点了一级选项
  checkLevelOne(val){
    var istrue = true

    for (let i; i<this.getLevelOne(this.state.treeData).length;i++){
      if (val== this.getLevelOne()[i]){
        istrue = false
      }
    }
    return istrue

  }

  // 设置子节点是启用
  childrenDisabled(arr){
    for(let i=0; i<arr.length; i++){
      arr[i].disabled = false
    }
  }

  // 判断一级选项是否已点击
  checkISLevelOne(val,arr){
    var istrue = false
    for(let i=0;i<arr.length;i++){
      if(val==arr[i]){
        istrue = true
      }
    }
    return istrue
  }

  // 获取选项在数组的下标
  getIndex(val,arr){
    for (let i=0; i<arr.length;i++){
      if (val == arr[i].key){
        return i
      }
    }
  }

  // 设置子节点是禁用
  childeenIsDisabled(arr){
    for (let i=0; i<arr.length;i++){
      arr[i].disabled = true

    }
  }

  // 判断一级选项下有哪些子选项的key
  getLevelChilKey(LevelKey,arr){
    let newArr
    for(let i=0;i<arr.length;i++){
      if (LevelKey==arr[i].key){
        newArr=arr[i].children
      }
    }
    return newArr

  }

  // 数组去重
  uniq(array){
    var temp = []; //一个新的临时数组
    for(var i = 0; i < array.length; i++){
      if(temp.indexOf(array[i]) == -1){
        temp.push(array[i]);
      }
    }
    return temp;
  }

  render() {
    return (
        <Tree
            checkable
            onExpand={this.onExpand}
            expandedKeys={this.state.expandedKeys}
            autoExpandParent={this.state.autoExpandParent}  //是否自动展开父节点
            checkedKeys={this.state.checkedKeys}
            onCheck={this.onCheck}
            onSelect={this.onSelect}
            selectedKeys={this.state.selectedKeys}
            treeData={this.state.isdata?this.state.treeData:null}
            checkStrictly={true}

        />
    )
  }
}

export {Demo as default}

然后将树形控件中选中的菜单存储在mobx中
代码如下:


import { observable, action } from 'mobx'
class TreeStore {


@observable selectKey = [];  选中的状态key
@action
// 添加Key
      addKey(arr){
      console.log('接收',arr)
       this.selectKey.concat(arr)
       sessionStorage.setItem('menluList',JSON.stringify(arr))

    }
    // 获取selectKey
  get(){
    console.log('kkkkk', this.selectKey)
  return this.selectKey
  }

}

const treeStore = new TreeStore;

export default treeStore;

利用该属性控件给新角色赋予权限(即新角色可查看的菜单)

RoleMange.js 中部分代码如下
1.引入TreeComponet组件

import TreeDemo from './TreeComponet'

2.使用树形控件

 <Form.Item
                  label='权限'
                  name='user_pwd'
              >
               {/*树形控件*/}
                <TreeDemo getTreeData={this.handleOk}></TreeDemo>
              </Form.Item>

RoleMange.js 完整代码如下:

import React, { useState } from 'react';
import {Button, Col, Input, Layout, Modal, Radio, Row, Select, Space, Switch, Table, Upload,Form,Tree} from "antd";
import Axios from "../../../util/axios";
import Api from '../../../api/index'
import TreeDemo from './TreeComponet'
import {inject,observer} from "mobx-react";
import  treeStore from '../../../store/TreeStore'
const { TreeNode } = Tree;
@inject('user')
@observer
class RoleMange extends React.Component {
  //获得登录管理员的编号
  userLoginNo = JSON.parse(sessionStorage.getItem('user')).mgr_no
  //通过ref获取表单数据域
  formRef = React.createRef();//添加表单
  constructor(){
    super()
    this.state = {
      visible:false,//添加表单的显示隐藏
      tableData:[],//表格数据
    }
  }
  // 获得所有数据
  getAllData(){
    // const token = window.localStorage.getItem("token")
    Axios.post(Api.user.roleData,{
      mgr_no:this.userLoginNo,
      page:1,
      pageSize:10},
    ).then((res)=>{
      console.log('角色列表',res);
      if(res.data.code == 200 ){
        this.setState({
          tableData:res.data.data
        })
      }
     else {
        console.log(res);
      }
      console.log(res);
    })
        .catch((err)=>{
      console.log('角色列表出错',err);
    })
  }
  componentWillMount() {
    this.getAllData()
  }
  // 添加表单成功
  handleOk = val => {
    console.log('hahaha',val);
    console.log('获得mobx中的值',[...this.props.user.menuList]);
    this.setState({
      visible: false,
    });
    // 获得表单里面的值
    let roleName = this.formRef.current.getFieldsValue().role
    let roleState = this.formRef.current.getFieldsValue().user_state
    let menuList = [...this.props.user.menuList]
    console.log(roleName,roleState)
    console.log('get',treeStore.get())
    console.log('get1',JSON.parse(sessionStorage.getItem('menluList')))
    // 发起请求
    Axios.post(Api.user.addRole,{
      role_name:roleName,
      role_status:parseInt(roleState),
      menuList:JSON.parse(sessionStorage.getItem('menluList'))
    }).then((res)=>{
      console.log('添加返回',res);
      if(res.data.code == 200){
           this.getAllData();
      }
    }).catch((err)=>{
      console.log('添加出错',err);
    })

  };
  // 添加表单模态框消失
  handleCancel = e => {
    console.log(e);
    this.setState({
      visible: false,
    });
  };
  // 显示添加角色菜单
  editRole=()=>{
    this.setState({
      visible: true,
    })
  }
  render() {
    const columns = [
      {
        title: '角色ID',
        dataIndex: 'role_no',
        // render: text => <a>{text}</a>,
      },
      {
        title: '角色名称',
        dataIndex: 'role_name',
      },
      {
        title: '角色状态',
        dataIndex: 'role_status',
        render: (text, record,index) => (
            <Space size="middle">
              {function(txt){
                if(txt == 1){
                  return '启用'
                }else if(txt == 0){
                  return '禁用'
                }
              }
              (text)}
            </Space>
        ),
      },
    ];//表格的列名
    return (
        <div>
          {/*搜索*/}
          <Layout>
            <Row className='searchRow'>
              <Col span={2} offset={22}>
                <Row style={{display:'flex',justifyContent:'space-between',marginBottom:'10px'}}>

                  <Button type="primary" size={this.state.btnSize} onClick={this.editRole}>
                    添加角色
                  </Button>
                </Row>
              </Col>
            </Row>
          </Layout>
          {/*表格*/}
          <Table columns={columns} dataSource={this.state.tableData} />
          {/*添加用户*/}
          <Modal
              title="添加角色"
              visible={this.state.visible}
              onOk={this.handleOk}
              onCancel={this.handleCancel}
          >
            <Form
                labelCol={{ span: 4 }}
                wrapperCol={{ span: 14 }}
                layout="horizontal"
                onFinish={this.handleOk}
                ref={this.formRef}
                initialValues={{
                  user_name:'',
                  user_role:'',
                  user_state:-1
                }}

            >
              <Form.Item
                  label='角色'
                  name='role'
              >
                <Input/>
              </Form.Item>
              <Form.Item
                  label='权限'
                  name='user_pwd'
              >
               {/*树形控件*/}
                <TreeDemo getTreeData={this.handleOk}></TreeDemo>
              </Form.Item>
              <Form.Item
                  label='角色状态'
                  name='user_state'
              >
                <Radio.Group onChange={this.getFormRadio} value={this.state.formRadioVal}>
                  <Radio value={1}>正常</Radio>
                  <Radio value={2}>禁用</Radio>
                </Radio.Group>
              </Form.Item>
            </Form>
          </Modal>
        </div>
    )
  }
}

export {RoleMange as default}
最后编辑于
?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,029评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,238评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事?!?“怎么了?”我有些...
    开封第一讲书人阅读 159,576评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,214评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,324评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,392评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,416评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,196评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,631评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,919评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,090评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,767评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,410评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,090评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,328评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,952评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,979评论 2 351