Power BI企业级权限控制+页面控制部署终极方案

这篇文章筹备了很久,最近正好有一个合适的契机,终于可以和大家见面了。Power BI在权限控制和页面控制方面,对于大多数人而言并不是一个很好用的功能,结合自己的经历,准备直接给大家分享终极方案。

内容过多,有些细节可能照顾不到,有疑问的可以留言,我会迭代上去。
导航栏效果

背景

20年我开始搭建企业级的Power BI模型。和以前作为分析师以个人分析为目的并不相同,企业级的部署需要考虑的内容很多,我选择了使用Power BI报表服务器的部署方案。

首先面临的问题就是如何给用户做权限控制,如何让用户使用Power BI报表像使用网页一样,让有权限的人看到应该看到的报表页面。

在Power BI原有的功能中,虽然可以做行级别权限控制,但不够灵活。对于页面控制+权限控制更是无力。尤其是对于初入Power BI的新手,权限控制简直是个灾难。

后来经过不断的尝试和反复的摸索学习,最终找到了一套简单的维护方案。

方案的主体部分,参考了佐罗老师《BI真经》高级版的内容。

什么情况下使用该方案?

该权限控制方案,适合报表数量非常多,比如100+,权限控制要求非常复杂,比如使用几十个字段甚至更多字段进行权限控制,那么这个方案就是你要找的最好的方案。如果你仅仅只有几个账号,权限相对稳定,那么这个方案可能并没有那么优秀。

各种Power BI部署方案与该权限控制方案的配合

Power BI Rerpot Server

  • 报表服务器的配置服务账户,目前在报表服务器自身来说是三种:内置-虚拟服务账户内置-网络服务域账户。其中推荐使用的也就是大多数人都在使用的,使用域控制。
    Power BI Report Server部署与配置详解
  • 权限控制依然需要建立企业的域账号,通过预控管理账户和密码作为第一道权限控制。
  • 报表服务器的部署,一共有两道权限。第一道是域账号,也就是必须先拥有域账号才能登录报表服务器,然后是Power BI的权限控制,只有域账号访问Power BI是看不到任何数据了,全部是大叉子。咱们这个权限部署方案,指的是在你使用域账号登录到后台以后,点击查看Power BI某个模型的权限,控制范围在Power BI模型中。
  • 在以前的方案中,权限调整有2-3次,第一次是通过报表服务器后台的管理文件夹创建域用户账号。
    管理文件夹
  • 第二次是在报表服务器上,某个模型的设置中,选择模型的管理选项,可以看到安全性,安全性可以独立设置,也可以使用管理文件夹中维护的域账号。


    安全性
  • 第三次是行级别安全性,这个就是咱们本次方案涉及到的部分,正常是通过配置角色,在角色中对不用的维度表中的字段做权限控制,使用当前方案后,则在这一步不需要做任何操作。


    行级别安全性

创建域账号以后,将用户姓名、用户账号及对应的权限维护到权限配置表。然后按照后面的方法配置,就可以实现权限控制和页面控制了。

Power BI Pro

  • Power BI Pro和报表服务器的大同小异,区别在于如果使用了这个权限控制方案,报表发布到Pro账户之后,不需要再设置安全性。


    安全性
  • 也就是下面这个操作可以不用做,这样权限部署更加的灵活,而且部署的步骤也减少了。


    行级控制

SSAS + Power BI

  • 这个方案没有直接操作过,但是原理雷同。
  • 将Excel配置表加载到SSAS模型中,SSAS里面是可以写计算组的,通过计算组控制,完全绕过了角色配置。
  • 权限需要调整时,调整的是Excel文件,SSAS模型不用调整,只做刷新即可。

Power BI Preminum

和Power BI Pro雷同,但没有亲测过。

总结

  • 所有的权限对应关系都在Excel中提前做好,比如使用地区字段进行控制,分别给不同的人分配不同的地区权限,然后在Power BI模型中刷新,通过计算组判断度量值来做权限控制,包括页面控制。
  • Pro用了这个方案,不用在网页账号再配制一次权限,报表服务器,从原来的配置2-3次,减少到1-2次。
  • 该方案解决的是Power BI模型内部的权限

Power BI权限控制流程

整个权限控制是由两个大的部分构成:

  • 如何自动完成员工入职或离职账号。比如根据OA账号密码,自动创建域账号。
  • 如何自动根据已调整的账号配置相关的权限

本次重点讲的是第二个部分,第一个部分目前我尚未整理出更好的方法,这部分是需要有相关开发能力作为支持才可以完成。

进入正题

思路讲解

  • 先在Excel中做好页面、权限、角色的配置,然后加载到PBI进行权限控制的处理。这部分控制使用计算组来做控制,解决了使用角色配置繁琐的问题。
  • 除了导航页,其他全部隐藏,在导航页根据当前用户做页面权限的判断,进入页面后自动做行级别权限的判断,达到最终控制的目的。

技术拆解

如何制作配置表

配置表在Excel中完成,简单方便快捷,若定位于实现系统自动化,另当别论。配置完成后Power BI直接读取最新记录。需要三张Excel配置表,用于定义,页面配置用户权限角色权限,加载到模型里面的是页面配置用户权限两张表。

Excel配置表中的数据从何而来?
  • 页面配置 来源于你要做的Power BI看板,比如你想要做10个看板,并且10个看板分属3个部门,那么在页面配置表,就是将3个部门维护到[部门名称]字段,10个看板维护到后面的页面描述、页面标题、报表标题等做好对应即可。

  • 权限配置 用户权限配置来源于两部分,一部分是页面权限,另一部分是行级别权限,我将相关内容做到了一个权限表中。这里面的用户名称、用户账号,对应的就是报表服务器域账号或者Power BI RroPro账号。至于这些账号怎么进入到Excel中,目前的方案还只能是手工维护,如果有开发条件,是可以根据入职或离职的员工账号,直接自动写入到Excel表中的,或者可以将权限表直接维护到数据库中,直接用任务修改数据库里面的权限内容,道理是一样的。

对于域账号,可以根据入职或离职的员工信息,自动创建域账号,同时保持和OA的账号密码一致,实现单点登录,然后再将该域账号写入到权限表,这么Power BI的权限控制就可以实现全自动了。

  • 角色配置 角色的配置是我为了减少权限配置的成本增加的功能,因为实际维护会有很多人是一样的角色,开一样的权限,只需要选择角色,自动匹配到对应的权限即可,不用再为每一个人配置详细的权限。
页面配置

页面配置表,需要几个关键的字段,其他的根据自己的实际需求添加,参考了佐罗老师的方案,做了一些调整。

该配置表为“”,相关引用使用的引用,而非单元格,可以减少数据调整导致的错误。不了解的请补充下关于“”的知识后再继续。

页面权限表可以无限向下或向右拓展

自然序号  = IF( [@部门名称] <> "", ROW()-ROW(页面配置表[#标题]), "" )
内容序号  = IF( [@自然序号] <> "", [@自然序号] - COUNTBLANK( OFFSET( 页面配置表[[#标题],[自然序号]], 0, 0, ROW( ) - ROW( 页面配置表[[#标题],[自然序号]] ) ) ), "" )
部门序号  = IF( [@部门名称] <> "", COUNTBLANK( OFFSET( 页面配置表[[#标题],[自然序号]], 0, 0, ROW( ) - ROW( 页面配置表[[#标题],[自然序号]] ) ) ), "" )
页面序号  = IF( [@部门名称] <> "", [@自然序号] - MINIFS( [自然序号], [部门名称], [@部门名称] ), "" )
部门编号  = IF( [@部门名称] <> "", [@部门序号]*1000+[@页面序号], "" )
部门名称  公司部门名称
页面描述  页面功能的描述
是否启用  是否启用对应的报表页
页面标题  报表页的名称
报表标题  报表页中,用于自动显示报表标题
......
页面配置表
角色权限

当用户特别多时,就需要使用角色进行配置,可以减少维护成本。相关内容以“;”做间隔。

角色权限表可以无限向右和向下拓展

角色编号  使用自然顺序创建角色编号
角色名称  增加角色的名称,自定义设置
快速配置  个人增加的一个快速配置页面权限的功能
页面权限  对应角色拥有的页面权限
城市      根据城市字段做权限控制
产品类别  根据产品类别做权限控制
......
角色配置

角色配置表中,页面权限部分,我做了两个中间表,可以快速方便的维护角色拥有的页面权限,当报表页面特别多时,该方式可以减少维护成本。该方式支持开通指定的页面。

该部分通过Power Query完成。

let
    源 = Excel.CurrentWorkbook(){[Name="页面配置表"]}[Content],
    筛选的行 = Table.SelectRows(源, each ([是否启用] = 1)),
    删除的其他列 = Table.SelectColumns(筛选的行,{"部门序号", "页面编号", "部门名称"}),
    更改的类型 = Table.TransformColumnTypes(删除的其他列,{{"页面编号", type text}, {"部门序号", type text}}),
    分组的行 = Table.Group(更改的类型, {"部门名称","部门序号"}, {{"页面权限", each Text.Combine([页面编号],";"), type nullable text}}),
    添加的后缀 = Table.TransformColumns(分组的行, {{"页面权限", each _ & ";", type text}})
in
    添加的后缀
部门名称权限
let
    源 = Excel.CurrentWorkbook(){[Name="角色配置表"]}[Content],
    删除的其他列 = Table.SelectColumns(源,{"角色编号", "角色名称", "快速配置"}),
    筛选的行 = Table.SelectRows(删除的其他列, each ([快速配置] <> null)),
    按分隔符拆分列 = Table.SplitColumn(Table.TransformColumnTypes(筛选的行, {{"快速配置", type text}}, "zh-CN"), "快速配置", Splitter.SplitTextByDelimiter("+", QuoteStyle.Csv), {"快速配置.1", "快速配置.2"}),
    用位置分列 = Table.SplitColumn(按分隔符拆分列, "快速配置.1", Splitter.SplitTextByRepeatedLengths(1), {"快速配置.1.1", "快速配置.1.2", "快速配置.1.3", "快速配置.1.4", "快速配置.1.5", "快速配置.1.6"}),
    按分隔符拆分列1 = Table.SplitColumn(用位置分列, "快速配置.2", Splitter.SplitTextByDelimiter(";", QuoteStyle.Csv), {"快速配置.2.1", "快速配置.2.2"}),
    逆透视的其他列 = Table.UnpivotOtherColumns(按分隔符拆分列1, {"角色编号","角色名称"}, "属性", "序号"),
    删除的列 = Table.RemoveColumns(逆透视的其他列,{"属性"}),
    合并的查询 = Table.NestedJoin(删除的列, {"序号"}, 部门名称权限, {"部门序号"}, "部门名称权限分组", JoinKind.LeftOuter),
    #"展开的“部门名称权限分组”" = Table.ExpandTableColumn(合并的查询, "部门名称权限分组", {"页面权限"}, {"页面权限"}),
    已添加自定义 = Table.AddColumn(#"展开的“部门名称权限分组”", "页面权限合并", each if [页面权限] = null then [序号] else [页面权限]),
    分组的行 = Table.Group(已添加自定义, {"角色编号","角色名称"}, {{"页面权限", each Text.Combine([页面权限合并],";"), type nullable text}}),
    替换的值 = Table.ReplaceValue(分组的行,";;",";",Replacer.ReplaceText,{"页面权限"})
in
    替换的值
角色页面权限

最后使用Vlookup函数,将不同角色名称对应的页面权限取值到角色表中即可。

用户权限

用户权限表可以无限向下或向右拓展,增加的列字段会在进入Power BI时,自动做转换处理。

需要给当前本地电脑,配置一个账户,使用UserPrincipalName()返回本地电脑的账户,并赋予所有权限。

用户名称  新增使用用户姓名
用户账号  用户使用账号
角色名称  角色名称 该部分可以通过做Excel数据有效性取值角色权限表中角色名称列  
页面权限  使用函数,通过角色名称匹配到该角色拥有的页面权限
城市      使用函数,通过角色名称匹配到该角色拥有的城市权限
产品类别  使用函数,通过角色名称匹配到该角色拥有的产品类别权限
用户权限
加载页面配置表

筛选保留是否启用字段中不是null的值,调整数字字段为整数,正常加载。
添加部门编号辅助列,为模型中关系建立做准备。

let
    源 = Excel.Workbook(File.Contents("D:\桌面\学习课程\权限控制\权限控制配置表.xlsx"), null, true),
    页面配置表_Table = 源{[Item="页面配置表",Kind="Table"]}[Data],
    更改的类型 = Table.TransformColumnTypes(页面配置表_Table,{{"自然序号", Int64.Type}, {"内容序号", Int64.Type}, {"部门序号", Int64.Type}, {"页面序号", Int64.Type}, {"页面编号", Int64.Type}, {"是否启用", Int64.Type}}),
    筛选的行 = Table.SelectRows(更改的类型, each ([是否启用] = 1)),
    复制的列 = Table.DuplicateColumn(筛选的行, "页面编号", "部门编号辅助"),
    更改的类型1 = Table.TransformColumnTypes(复制的列,{{"部门编号辅助", type text}})
in
    更改的类型1
加载结果
加载权限配置表

只要你做的配置表字段跟我一样,那么就可以根据M公式还原出操作步骤。

let
    源 = Excel.Workbook(File.Contents("D:\桌面\学习课程\权限控制\权限控制配置表.xlsx"), null, true),
    权限配置表_Table = 源{[Item="权限配置表",Kind="Table"]}[Data],
    更改的类型 = Table.TransformColumnTypes(权限配置表_Table,{{"用户名称", type text}, {"用户账号", type text}, {"角色名称", type text}, {"页面权限", type text}, {"地区", type text}, {"产品类别", type text}}),
    逆透视的其他列 = Table.UnpivotOtherColumns(更改的类型, {"用户名称", "用户账号", "角色名称"}, "权限类型", "拥有权限"),
    生成权限列表 = Table.TransformColumns(#"逆透视的其他列", {{"拥有权限", each List.RemoveItems( Text.Split( _ ,";" ) , {""} ) }}),
    #"展开的“拥有权限”" = Table.ExpandListColumn(生成权限列表, "拥有权限"),
    更改的类型1 = Table.TransformColumnTypes(#"展开的“拥有权限”",{{"拥有权限", type text}}),
    筛选的行 = Table.SelectRows(更改的类型1, each [拥有权限] <> null)
in
    筛选的行
加载结果
处理表关系

不需要做任何表关系处理,也不需要做角色配置。

计算组准备

需要使用Tabular Editor软件来完成。

连接需要操作的模型



在Tables文件夹上右击选择创建计算组
创建计算组

新建一个组,并根据自己的喜好命名,这里命名为启用

点击启用,右侧填写以下内容:

CALCULATE( 
    SELECTEDMEASURE() ,
    KEEPFILTERS( TREATAS( CALCULATETABLE( VALUES( '权限配置表'[拥有权限] ) , '权限配置表'[用户账号] = USERPRINCIPALNAME( ) , '权限配置表'[权限类型] = "地区" ) , '地理位置'[地区] ) ) ,
    KEEPFILTERS( TREATAS( CALCULATETABLE( VALUES( '权限配置表'[拥有权限] ) , '权限配置表'[用户账号] = USERPRINCIPALNAME( ) , '权限配置表'[权限类型] = "产品类别" ) , '产品'[产品类别] ) ) ,
    KEEPFILTERS( TREATAS( CALCULATETABLE( VALUES( '权限配置表'[拥有权限] ) , '权限配置表'[用户账号] = USERPRINCIPALNAME( ) , '权限配置表'[权限类型] = "页面权限" ) , '页面配置表'[部门编号辅助] ) ) ,
    { "可以添加其他筛选" }
)
BPI中看到的效果
制作导航页
导航栏

看不懂的需要补一下Power BI按钮的知识。

  • 1、左上角 当前用户 插入空白按钮,然后选择按钮文本使用度量值[用户 当前用户]
用户 当前用户 = "当前用户:" &  SELECTEDVALUE( '权限配置表'[用户名称], "管理员" )
  • 2、中间标题使用空白按钮赋予按钮文本或单独插入公司Logo
  • 3、右上角 模型日期 方法同当前用户按钮
模型日期 = MAXX( all( '订单' ), '订单'[订单日期] ) 
  • 4、使用切片器展示,将页面配置表[部门名称]字段,调整为横向展示;
  • 5、该部分导航和右侧的导航是两套方案;使用空白按钮制作,适合在特定场景使用,维护成本高,但可以直接点击跳转到对应页面。
    每个按钮需要四个度量值:按钮文本、字体颜色、边框颜色、导航目标、工具提示。其中字体颜色和边框颜色使用一个度量值。有多少个按钮就得配置多少套。
    这里利用了按钮可以使用度量值的特性。
首页 页面控制 导航目标 2000 = //页导航 目标
var t1 = SUMMARIZE( FILTER( '页面配置表', '页面配置表'[页面编号] = 2000 ),'页面配置表'[报表标题] )
var t2 = UserPrincipalName() in VALUES( '权限配置表'[用户账号] )
return if( t2, t1, BLANK() )

首页 页面控制 悬浮文字 2000 = //页导航 工具提示
var t1 = SUMMARIZE( FILTER( '页面配置表', '页面配置表'[页面编号] = 2000 ),'页面配置表'[页面标题] )
var t2 = UserPrincipalName() in VALUES( '权限配置表'[用户账号] )
return if( t2, t1, BLANK() )

首页 页面控制 按钮文本 2000 = //按钮文本
var t1 = SUMMARIZE( FILTER( '页面配置表', '页面配置表'[页面编号] = 2000 ),'页面配置表'[页面标题] )
var t2 = UserPrincipalName() in VALUES( '权限配置表'[用户账号] )
return if( t2, t1, BLANK() )

首页 页面控制 文本颜色 2000 = //边框颜色 或 字体颜色
var t1 = SUMMARIZE( FILTER( '页面配置表', '页面配置表'[页面编号] = 2000 ),'页面配置表'[页面标题] )
var t2 = UserPrincipalName() in VALUES( '权限配置表'[用户账号] )
var t3 = if( t1 <> BLANK() && t2, "#1a1a1a", "#cccccc" )
return t3

可以实现有权限的高亮显示,无权限的浅灰色显示的效果。

  • 6、获取更多视觉对象,搜索Text。需要Power BI账号才可以使用。


公告栏 = 
"<br>"&
"1、成功祝贺Test公司上市,股票代码 000000,欢迎关注!"&
"<br>"&
"<br>"&
"2、Test年销售额突破100亿,连续5年增长超30%,成为行业新星,获得独角兽企业提名;"&
"<br>"&
"<br>"&
"3、东北区连续3年出现下滑20%,建议重新评估市场前景!"
  • 7、使用矩阵,在行标题设置中,关闭渐变布局,将页面配置表[部门名称]、[页面描述]放到矩阵的行中,并拓展到下一级显示;
    关闭渐变布局

将度量值[导航栏 保留]放到值中,修改度量值展示名称为“_”,缩小字段宽度至最小,达到隐藏的效果。

特别注意:该步骤操作时,必须将本地电脑的用户账号放入Excel配置表中,否则将无权限查看任何数据。使用UserPrincipalName(),判断当前电脑本地用户账名,然后作为账号维护。

为了安全该处没有对没账号的用户赋予所有权限,而是必须维护本地账号才可以查看。

导航栏 保留 = //用于筛选出符合当前用户权限的页面,需要提前将本地电脑的用户账号添加到Excel配置表中,使用函数UserPrincipalName(),计算出当前电脑的账户。
COUNT( '页面配置表'[自然序号] )

这里讲下为何要增加这样一个操作,权限配置表中的权限是通过TREATAS函数与其他维度表挂在一起,其中页面控制部分也是一样,因为[部门名称]、[页面描述]都是在行上,本身无交互,只有当前用户页面权限和与页面相关的度量值交互时,才能产生筛选效果。

举例说明,比如使用地区做权限控制,如果只放地区到矩阵,则无法直接产生只有当前用户有权限的地区分类,若增加一个销售件数产生交互,则可以达到筛选的效果。

这个原因是因为计算组只能对度量值起作用,无法对表进行筛选。

  • 8、第7个部分和第8个部分是搭配使用,首先选择矩阵中的一行,当行唯一时,第8部分的按钮得到唯一的导航目标,并且颜色变为绿色,点击可以实现跳转效果。
导航栏 文本 = //显示文本
var t1 = SELECTEDVALUE( '页面配置表'[页面标题] )
return if( ISBLANK( t1 ), "🛑 请选择一个页面", "💡 点击进入" )

导航栏 显示 = //悬停提示
SELECTEDVALUE( '页面配置表'[页面描述] )

导航栏 目标 = //导航目标页名称
var t1 = SELECTEDVALUE( '页面配置表'[页面标题] )
var t2 = UserPrincipalName() in VALUES( '权限配置表'[用户账号] )
return if( ISBLANK( t1 ) || ISBLANK( t2 ), "", t1)

导航栏 颜色 = //符合选择条件和不符合选择条件的颜色调整,不唯一为红色,唯一为绿色。
var t1 = [导航栏 目标]
return if( ISBLANK( t1 ) || COUNTROWS( VALUES( '页面配置表'[页面描述] ) ) <> 1, "#FD625E", "#01B8AA" )
创建报表页

以上已经完成权限控制的部署,剩下的就是完成页面的调整。

  • 新建一个空白页,隐藏该页,插入空白按钮配置报表标题,并制作返回按钮,返回按钮的目标页和悬停提示使用度量值。

单击报表页面空白处,将页面配置表[报表标题],放入可视化-保留所有筛选器,筛选该页需要显示的标题。

然后,添加AOP设置.权限,选择设置权限控制+页面控制,加入筛选后,选择启用

权限配置
导航栏 报表标题 = SELECTEDVALUE( '页面配置表'[报表标题] ) 

导航页 返回提示 = "点击返回导航页" 

导航页 返回目标 = "导航页" 

复制该页,并对页面重命名为页面配置表[页面标题]字段包含的报表页名称,同时筛选该页对应的[报表标题]。

后续有新增页面直接复制原来的报表,然后做相应的调整。

这样一个成熟简单的Power BI方案就部署完成了。

配置表的使用

权限配置表,是在Excel中配置,可以直接加载Excel文件到Power BI模型,如果是报表服务器部署方案,建议是放到服务器上修改,或者也可以将权限配置表导入到数据库。

后记

历时两周,终于写完了,期间搭建模型花费了一周的时间,各种调试,写文章实在是太浪费时间了,尤其是这种文章,整体框架又大,不太容易写清楚,换了好几个方案,最终才定的这个。

这个方案解决的是在Power BI当中的权限控制,至于员工入职或离职新增的账号如何自动同步让Power BI加载,这又是另一个话题了,如果有机会,我会继续写这部分的内容。

原来是打算写的非常详细照顾一下初学者,但是有些知识如果无限拓展,可能会造成文章主题重点不突出,因此部分Power BI基本知识就一概而过了,如果很多内容还看不懂,可能还需要补充一些其他的知识。

  • Excel中什么是“
  • Power Query高级编辑器的使用
  • Power BI基本图表的使用,比如切片器、矩阵
  • 按钮的功能,熟悉按钮的特性及如何配合使用度量值
  • 什么是Power BI计算组
  • 会使用Tabular Editor操作Power BI
  • 能理解TREATAS的用法
  • 掌握Power BI基本操作

写之前特意找佐罗老师咨询了下,因为涉及到收费课程中的内容,得到佐罗老师允许后,才有了现在这篇文章,在此非常感谢佐罗老师。

个人水平有限,文章也有很多不足之处,忘不惜赐教。

参考资料来源:

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

推荐阅读更多精彩内容