騰訊云移動(dòng)直播微信小程序源碼解析(三)

關(guān)鍵字:騰訊云阀蒂、移動(dòng)直播沥邻、liveroom

本文只涉及騰訊云 <live-room> 標(biāo)簽代碼結(jié)構(gòu)講解,只需要有基本的程序結(jié)構(gòu)思維即可玖翅。

本文使用騰訊云最新公開(kāi)的小程序源碼1.2.639,這個(gè)版本的小程序頁(yè)面與訪問(wèn)騰訊云視頻小程序看到的頁(yè)面稍有不同割以,但不影響標(biāo)簽分析金度。


基本概念


<live-room> 是騰訊云基于微信小程序內(nèi)置的<live-pusher>和<live-player>標(biāo)簽開(kāi)發(fā)用于雙人和多人音視頻通話的自定義組件。

<live-room> 主要用于一對(duì)多音視頻通過(guò)場(chǎng)景下严沥。騰訊云視頻 小程序的 手機(jī)直播 和 PC直播使用的就是 <live-room> 標(biāo)簽猜极。

使用方法

登錄房間服務(wù)

第一步需要登錄房間服務(wù)。

調(diào)用 /utils/liveroom.js 的 login 方法進(jìn)行登錄消玄,登錄的目的是要連接后臺(tái)房間服務(wù)(RoomService)跟伏。

var liveroom = require('/utils/liveroom.js');
...
liveroom.login({
    serverDomain: '',
    userID: '',
    userSig: '',
    sdkAppID: '',
    accType: '',
  userName: '' //用戶昵稱,由客戶自定義
});

注意翩瓜,這里的 UserSig 需要通過(guò)請(qǐng)求《騰訊云移動(dòng)直播微信小程序源碼解析(一)》中講到的 Django 后臺(tái)獲取受扳。

小程序端

在小程序中,可以這樣實(shí)現(xiàn)后臺(tái)請(qǐng)求:

qcloud.request({
    // login:true,
    url: config.serverUrl + '/accounts/genesig',
    method: 'GET',
    header: {
      'content-type': 'application/json' // 默認(rèn)值
    },
    success: function (ret) {
      console.log('get user ');
      if (ret.data.code) {
        console.log('獲取登錄信息失敗兔跌,調(diào)試期間請(qǐng)點(diǎn)擊右上角三個(gè)點(diǎn)按鈕勘高,選擇打開(kāi)調(diào)試');
        options.fail && options.fail({
          errCode: ret.data.code,
          errMsg: ret.data.message + '[' + ret.data.code + ']'
          });
          return;
        }
        ret.data.serverDomain = config.roomServiceUrl + '/weapp/' + options.type + '/';
 
       liveroom.login({
              data: ret.data,
              success: options.success,
              fail: options.fail
            });
        }

邏輯是這樣的:
a) 向 django 后臺(tái)發(fā)送 GET 請(qǐng)求,請(qǐng)求地址為 config.serverUrl + '/accounts/genesig'坟桅;
b) 如果成功返回华望,檢查是否返回了錯(cuò)誤碼;
i. 如果返回錯(cuò)誤碼仅乓,則報(bào)錯(cuò)赖舟;
ii. 沒(méi)有沒(méi)有返回錯(cuò)誤碼,則登錄房間服務(wù)(RoomService)方灾;

Django 后臺(tái)

在 Django 后臺(tái)建蹄,可以這樣處理:

class GeneSigView(WeappMixin, View):
    def get(self, request, *args, **kwargs):
        self._get_openid(request)
        result = {}
        if self.openid is None:
            result = {'code': -1, 'message': 'get openid error'}
            return JsonResponse(data=result)
        try:
            tls_api = tls_sig.TLSSigAPI(settings.IM_SDKAPPID,
                                        settings.PRIVATEKEY)
            sig = tls_api.tls_gen_sig(self.openid)
            result.update({'userSig': sig.decode(), 'userID': self.openid,
                           'sdkAppID': settings.IM_SDKAPPID,
                           'accType': settings.IM_ACCOUNTTYPE})
            user = Account.objects.get(openid=self.openid)
            result.update(
                {'userName': user.nickname, 'userAvatar': user.avatarurl})
        except:
            result = {'code': -1, 'message': 'calc usersig error'}
        return JsonResponse(data=result)

GeneSigView 即為實(shí)現(xiàn)視圖,它繼承的 WeappMixin 用戶獲取 openid :

class WeappMixin(object):
    openid = None

    def _get_openid(self, request):
        session_id = request.META.get('HTTP_X_WX_SKEY')
        try:
            self.openid = redis_api.get_str(session_id).decode().split(':')[0]
        except (ValueError, AttributeError):
            self.openid = None

代碼中的 tls_sig 為 騰訊云提供的 sig 生成器裕偿,代碼是這樣的:

#! /usr/bin/python
# coding:utf-8

__author__ = "tls@tencent.com"
__date__ = "$Mar 3, 2016 03:00:43 PM"

import OpenSSL
import base64
import zlib
import json
import time

ecdsa_pri_key = """
-----BEGIN EC PARAMETERS-----
BgUrgQQACg==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIEJDBDY4KVdj3dPBacADreB772ok45A57YWrUUvc5fMQoAcGBSuBBAAK
oUQDQgAEaPVFHhWqRDnKnVlyU5JIzXOUyOJd/pPUwhLUovf+PYBm7otRBptnvJ4E
oJ4qeSJNG0v4XdiqM3mtChkhUEFT3Q==
-----END EC PRIVATE KEY-----
"""

privateKey = '-----BEGIN PRIVATE KEY-----\r\n' + 'MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQga7O4tX0KQH/Bhbq5\r\n' + 'zfP5nBDeAiBs6R8wO7zpd7PIB+GhRANCAAQI0AnMVO1km7iAMatqV3FcVrAC3B8/\r\n' + '1OShs1hr3Envd+KlUHtcZZ780G3+yc0nCo2NPYPCEODUm36oQ+iIhU+h\r\n' + '-----END PRIVATE KEY-----\r\n'

def list_all_curves():
    list = OpenSSL.crypto.get_elliptic_curves()
    for element in list:
        print(element)


def get_secp256k1():
    print(OpenSSL.crypto.get_elliptic_curve('secp256k1'))


def base64_encode_url(data):
    base64_data = base64.b64encode(data)
    base64_data = base64_data.replace(b'+', b'*')
    base64_data = base64_data.replace(b'/', b'-')
    base64_data = base64_data.replace(b'=', b'_')
    return base64_data


def base64_decode_url(base64_data):
    base64_data = base64_data.replace(b'*', b'+')
    base64_data = base64_data.replace(b'-', b'/')
    base64_data = base64_data.replace(b'_', b'=')
    raw_data = base64.b64decode(base64_data)
    return raw_data


class TLSSigAPI:
    """"""
    __acctype = 0
    __identifier = ""
    __appid3rd = ""
    __sdkappid = 0
    __version = 20151204
    __expire = 3600 * 24 * 30  # 默認(rèn)一個(gè)月洞慎,需要調(diào)整請(qǐng)自行修改
    __pri_key = ""
    __pub_key = ""
    _err_msg = "ok"

    def __get_pri_key(self):
        return OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, self.__pri_key)

    def __init__(self, sdkappid, pri_key):
        self.__sdkappid = sdkappid
        self.__pri_key = pri_key

    def __create_dict(self):
        return {"TLS.account_type": "%d" % self.__acctype, "TLS.identifier": "%s" % self.__identifier,
                "TLS.appid_at_3rd": "%s" % self.__appid3rd, "TLS.sdk_appid": "%d" % self.__sdkappid,
                "TLS.expire_after": "%d" % self.__expire, "TLS.version": "%d" % self.__version,
                "TLS.time": "%d" % time.time()}

    def __encode_to_fix_str(self, m):
        fix_str = "TLS.appid_at_3rd:" + m["TLS.appid_at_3rd"] + "\n" \
                  + "TLS.account_type:" + m["TLS.account_type"] + "\n" \
                  + "TLS.identifier:" + m["TLS.identifier"] + "\n" \
                  + "TLS.sdk_appid:" + m["TLS.sdk_appid"] + "\n" \
                  + "TLS.time:" + m["TLS.time"] + "\n" \
                  + "TLS.expire_after:" + m["TLS.expire_after"] + "\n"
        return fix_str

    def tls_gen_sig(self, identifier):
        self.__identifier = identifier
        m = self.__create_dict()
        fix_str = self.__encode_to_fix_str(m)
        pk_loaded = self.__get_pri_key()
        sig_field = OpenSSL.crypto.sign(pk_loaded, fix_str, "sha256")
        sig_field_base64 = base64.b64encode(sig_field)
        m["TLS.sig"] = sig_field_base64.decode('utf-8')
        json_str = json.dumps(m)
        sig_compressed = zlib.compress(json_str.encode('utf-8'))
        base64_sig = base64_encode_url(sig_compressed)
        return base64_sig


def main():
    api = TLSSigAPI(1400001052, privateKey)
    sig = api.tls_gen_sig("xiaojun")
    print(sig)


if __name__ == "__main__":
    main()

在JSON 文件中進(jìn)行配置

在 page 目錄下的 json配置文件內(nèi)引用組件:

{
  "navigationBarTitleText": "在線課堂",
  "usingComponents": {
    "live-room": "/pages/components/live-room/liveroom"
  }
}

在 WXML 文件中使用

在 page 目錄下的 wxml 文件中使用標(biāo)簽 <live-room>:

<live-room id="id_liveroom" wx:if="{{showLiveRoom}}" roomid="{{roomID}}" role="{{role}}" roomname="{{roomName}}" pureaudio="{{pureAudio}}" debug="{{debug}}" muted="{{muted}}" beauty="{{beauty}}" template="vertical1v3" bindRoomEvent="onRoomEvent">

到這里,<live-room> 標(biāo)簽可以正常使用了嘿棘。

直播頁(yè)面

live-room 標(biāo)簽正常工作時(shí)劲腿,用戶分為三類:

  • 大主播:可以理解為直播間的主人,權(quán)限較高鸟妙;

  • 小主播:可以與大主播互動(dòng)的用戶焦人。

  • 觀眾:不可以與大主播互動(dòng)的用戶挥吵,只能觀看大主播的直播。

<live-room> 標(biāo)簽需要大主播創(chuàng)建直播間花椭,只有大主播進(jìn)入直播間忽匈,其它用戶才能進(jìn)入房間。

大主播矿辽、小主播看到的頁(yè)面如下圖所示丹允,其中大主播在左側(cè),小主播(最多3個(gè))在右側(cè)袋倔。

大主播雕蔽、小主播看到的頁(yè)面

觀眾看到的頁(yè)面如下圖所示,只能看到大主播宾娜。

觀眾看到的頁(yè)面

觀眾可以點(diǎn)擊頁(yè)面上的麥克圖標(biāo)向大主播申請(qǐng)連麥批狐,大主播端后顯示小主播的連麥請(qǐng)求,如果大主播同意連麥前塔,則該觀眾成為小主播嚣艇。如果存在多于3個(gè)小主播,目前只能顯示3個(gè)小主播嘱根。

大主播可以通過(guò)踢人操作將小主播踢出髓废,小主播此時(shí)變?yōu)橛^眾巷懈。

這樣该抒,我們可以順暢的使用 <live-room>標(biāo)簽了。下面的內(nèi)容只是為了了解 live-room 標(biāo)簽如何工作及進(jìn)一步定制代碼顶燕。

代碼結(jié)構(gòu)


<live-room>標(biāo)簽代碼位于 pages/components/live-room文件夾內(nèi)凑保,該文件夾用于創(chuàng)建live-room自定義組件。

自定義組件的詳細(xì)介紹見(jiàn)微信小程序文檔涌攻。

live-room 自定義組件包含 vertical1v3template 文件夾欧引、liveroom.js、liveroom.json恳谎、liveroom.wxml 及 liveroom.wxss芝此。從結(jié)構(gòu)來(lái)看,除了vertical1v3template 文件夾因痛,該自定義組件的結(jié)構(gòu)與微信小程序頁(yè)面類似婚苹。

vertical1v3template 為騰訊云的 live-room 模板。模板的代碼是這樣的:

<template name="vertical1v3">
    <view class="{{linkPusherInfo.url || isCaster ? 'v-full2': 'v-full'}}">
        <view wx:if="{{isCaster}}" class='v-main-video'>
            <live-pusher wx:if="{{isCaster&&mainPusherInfo.url}}" id="pusher" mode="RTC" url="{{mainPusherInfo.url}}" min-bitrate="850" min-bitrate="1200" beauty="{{beauty}}" enable-camera="{{!pureaudio}}" muted="{{muted}}" aspect="9:16" waiting-image="https://mc.qcloudimg.com/static/img/daeed8616ac5df256c0591c22a65c4d3/pause_publish.jpg"
                background-mute="{{true}}" debug="{{debug}}" bindstatechange="onMainPush" binderror="onMainError">
                 <cover-view class='character' style='padding: 0 5px;'>我({{userName}})</cover-view> 
                 <cover-view class="operate">
                    <cover-view class='img-box'>
                        <cover-image class='img-view' src='/pages/Resources/camera.png' bindtap="switchCamera"></cover-image>
                        <!-- <cover-view class='text-view'>翻轉(zhuǎn)</cover-view> -->
                    </cover-view>
                    <cover-view class='img-box'>
                        <cover-image class='img-view' src='/pages/Resources/{{beauty > 0? "beauty" : "beauty-dis"}}.png' bindtap="toggleBeauty"></cover-image>
                        <!-- <cover-view class='text-view'>美顏</cover-view> -->
                    </cover-view>
                    <!-- <cover-view class='img-box'>
                        <cover-image class='img-view' src='/pages/Resources/{{muted ? "mic-dis" : "mic"}}.png' bindtap="toggleMuted"></cover-image>
                         <cover-view class='text-view'>聲音</cover-view> 
                    </cover-view> -->
                   
                    <cover-view class='img-box'>
                        <cover-image class='img-view' src='/pages/Resources/{{debug? "log" : "log2"}}.png' bindtap="toggleDebug"></cover-image>
                        <!-- <cover-view class='text-view'>日志</cover-view> -->
                    </cover-view>
                </cover-view>
            </live-pusher>
        </view>

        <view wx:for="{{visualPlayers}}" wx:key="{{index}}" class="{{linkPusherInfo.url ? 'v-main-video' : 'v-full'}}">
            <live-player wx:if="{{item.url}}" autoplay id="player" mode="{{item.mode}}" min-cache="{{item.minCache}}" max-cache="{{item.maxCache}}" object-fit="{{item.objectFit}}" src="{{item.url}}" debug="{{debug}}" muted="{{muted}}" background-mute="{{item.mute}}" bindstatechange="onMainPlayState"
                binderror="onMainPlayError">
                <cover-view class="operate">
                    <cover-view  wx:if="{{linkPusherInfo.url}}" class='img-box'>
                        <cover-image class='img-view' src='/pages/Resources/camera.png' bindtap="switchCamera"></cover-image>
                        <!-- <cover-view class='text-view'>翻轉(zhuǎn)</cover-view> -->
                    </cover-view>
                    <cover-view wx:if="{{linkPusherInfo.url}}" class='img-box'>
                        <cover-image class='img-view' src='/pages/Resources/{{beauty > 0? "beauty" : "beauty-dis"}}.png' bindtap="toggleBeauty"></cover-image>
                        <!-- <cover-view class='text-view'>美顏</cover-view> -->
                    </cover-view>
                    <!-- <cover-view class='img-box'>
                        <cover-image class='img-view' src='/pages/Resources/{{muted ? "mic-dis" : "mic"}}.png' bindtap="toggleMuted"></cover-image>
                         <cover-view class='text-view'>聲音</cover-view> 
                    </cover-view> -->
                    <cover-view wx:if="{{!linkPusherInfo.url}}" class='img-box'>
                        <cover-image class='img-view' src='/pages/Resources/mic.png' bindtap="requestJionPusher"></cover-image>
                        <!-- <cover-view class='text-view'>連麥</cover-view> -->
                    </cover-view>
                    <cover-view class='img-box'>
                        <cover-image class='img-view' src='/pages/Resources/{{debug? "log" : "log2"}}.png' bindtap="toggleDebug"></cover-image>
                        <!-- <cover-view class='text-view'>日志</cover-view> -->
                    </cover-view>
                </cover-view>

            </live-player>
        </view>
    </view>

    <view wx:if="{{linkPusherInfo.url || isCaster}}" class='v-sub-video-list'>
        <view class='.v-sub-video' wx:if="{{!isCaster && linkPusherInfo.url}}">
            <live-pusher wx:if="{{!isCaster && linkPusherInfo.url}}" min-bitrate="400" min-bitrate="200" id="audience_pusher" mode="RTC" min-bitrate="900" url="{{linkPusherInfo.url}}" beauty="{{beauty}}" enable-camera="{{!pureaudio}}" muted="{{muted}}" aspect="9:16"
                waiting-image="https://mc.qcloudimg.com/static/img/daeed8616ac5df256c0591c22a65c4d3/pause_publish.jpg" background-mute="true" debug="{{debug}}" bindstatechange="onLinkPush" binderror="onLinkError">
                <cover-image class='character' src="/pages/Resources/mask.png"></cover-image>
                <cover-view class='character' style='padding: 0 5px;'>我({{userName}})</cover-view>
                <cover-view class='close-ico' bindtap="quitLink">x</cover-view>
            </live-pusher>
        </view>

        <view class='.v-sub-video' wx:for="{{members}}" wx:key="{{item.userID}}">
            <view class='poster'>
                <cover-image wx:if="{{ index < 4 }}" class='set' src="https://miniprogram-1252463788.file.myqcloud.com/roomset_{{index + 1}}.png"></cover-image>
            </view>
            <live-player wx:if="{{item.accelerateURL}}" id="{{item.userID}}" autoplay mode="RTC" object-fit="fillCrop" min-cache="0.1" max-cache="0.3" src="{{item.accelerateURL}}" debug="{{debug}}" background-mute="{{true}}">
                <cover-view class="close-ico" wx:if="{{item.userID == userID || isCaster}}" bindtap="kickoutSubPusher" data-userid="{{item.userID}}">x</cover-view>
                <cover-view class='loading' wx:if="{{false}}">
                    <cover-image src="/pages/Resources/loading_image0.png"></cover-image>
                </cover-view>
                <cover-image class='character' src="/pages/Resources/mask.png"></cover-image>
                <cover-view class='character' style='padding: 0 5px;'>{{item.userName}}</cover-view>
            </live-player>
        </view>
    </view>
</template>

模板的邏輯是這樣的:
對(duì)于整個(gè)頁(yè)面鸵膏,邏輯為:
判斷 linkPusherInfo.url 或 isCaster 是否為 true膊升,如果是,使用v-full2谭企,否則使用 v-full廓译。

其中小主播具有 linkPusherInfo.url 评肆,用戶為大主播時(shí) isCaster 為 true。
也就是說(shuō)非区,對(duì)于大主播和小主播 class = v-full2瓜挽;對(duì)于觀眾,class = v-full征绸。

即 我們上面看到的不同用戶角色對(duì)應(yīng)的不同頁(yè)面秸抚。

對(duì)于大主播、小主播的頁(yè)面歹垫,如下圖所示剥汤,左側(cè)紫色框部分 class = v-main-video,右側(cè)紅色框部分為 v-sub-video-list排惨。

live-room標(biāo)簽?zāi)0?/div>

頁(yè)面中通過(guò) isCaster&&mainPusherInfo.url 來(lái)區(qū)分大主播吭敢、小主播對(duì)應(yīng)的頁(yè)面。

大主播(isCaster=true)看到的頁(yè)面暮芭,大主播為live-pusher鹿驼,視頻影像在上圖中紫色框中。小主播為live-player辕宏,視頻影像在上圖中紅色框中的一個(gè)小框中畜晰。

小主播(members)看到的頁(yè)面,大主播為 liver-player(此時(shí)大主播變?yōu)榱?VisualPlayers)瑞筐,視頻影像仍在上圖中紫色框中凄鼻。小主播自己為 live-pusher ,視頻影像在上圖中紅色框的第一個(gè)小框中。下面兩個(gè)小框?yàn)槠渌≈鞑ァ?/p>

也就是說(shuō)聚假,大主播和小主播看到的右側(cè)紅色框中主播的順序是不一致的块蚌。

角色 大主播 小主播
位置 左側(cè)大框 右側(cè)小框中的一個(gè)
名稱 -- members

對(duì)于大主播來(lái)講:

角色 大主播 小主播
位置 左側(cè)大框 右側(cè)小框中的一個(gè)
名稱 -- members

對(duì)于小主播來(lái)將:

角色 大主播 小主播
位置 左側(cè)大框 右側(cè)小框第一個(gè)
名稱 VisualPlayers members
角色 大主播 小主播
位置 整個(gè)頁(yè)面 無(wú)
名稱 VisualPlayers 無(wú)

對(duì)于觀眾來(lái)講:

角色 大主播 小主播
位置 整個(gè)頁(yè)面 無(wú)
名稱 VisualPlayers 無(wú)

未完待續(xù)...

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市膘格,隨后出現(xiàn)的幾起案子峭范,更是在濱河造成了極大的恐慌,老刑警劉巖瘪贱,帶你破解...
    沈念sama閱讀 218,036評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件纱控,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡菜秦,警方通過(guò)查閱死者的電腦和手機(jī)甜害,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)喷户,“玉大人唾那,你說(shuō)我怎么就攤上這事。” “怎么了闹获?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,411評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵期犬,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我避诽,道長(zhǎng)龟虎,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,622評(píng)論 1 293
  • 正文 為了忘掉前任沙庐,我火速辦了婚禮鲤妥,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘拱雏。我一直安慰自己棉安,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布铸抑。 她就那樣靜靜地躺著贡耽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鹊汛。 梳的紋絲不亂的頭發(fā)上蒲赂,一...
    開(kāi)封第一講書(shū)人閱讀 51,521評(píng)論 1 304
  • 那天,我揣著相機(jī)與錄音刁憋,去河邊找鬼滥嘴。 笑死,一個(gè)胖子當(dāng)著我的面吹牛至耻,可吹牛的內(nèi)容都是我干的若皱。 我是一名探鬼主播,決...
    沈念sama閱讀 40,288評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼有梆,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼是尖!你這毒婦竟也來(lái)了意系?” 一聲冷哼從身側(cè)響起泥耀,我...
    開(kāi)封第一講書(shū)人閱讀 39,200評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蛔添,沒(méi)想到半個(gè)月后痰催,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,644評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡迎瞧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評(píng)論 3 336
  • 正文 我和宋清朗相戀三年夸溶,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凶硅。...
    茶點(diǎn)故事閱讀 39,953評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡缝裁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出足绅,到底是詐尸還是另有隱情捷绑,我是刑警寧澤韩脑,帶...
    沈念sama閱讀 35,673評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站粹污,受9級(jí)特大地震影響段多,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜壮吩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評(píng)論 3 329
  • 文/蒙蒙 一进苍、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鸭叙,春花似錦觉啊、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,889評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至缀程,卻和暖如春搜吧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背杨凑。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,011評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工滤奈, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人撩满。 一個(gè)月前我還...
    沈念sama閱讀 48,119評(píng)論 3 370
  • 正文 我出身青樓蜒程,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親伺帘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子昭躺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)載鏈接 注:本文轉(zhuǎn)載知乎上的回答 作者:初雪 鏈接:https://www.zhihu.com/question...
    pengshuangta閱讀 28,540評(píng)論 9 295
  • 筆名:秋水 1 公司有一位員工要離職领炫。 員工離職本是再平常不過(guò)的事兒,少有人會(huì)像A一樣情緒如此失控张咳。 淚如雨下帝洪,半...
    天地一蒼鷹閱讀 502評(píng)論 0 4
  • 工作臺(tái)上擺放的筆記和訂單,以老舊的古董秤砣為鎮(zhèn)紙脚猾,它們整齊擺放的樣子很符合一個(gè)強(qiáng)迫癥患者的審美
    CNBLUEone閱讀 228評(píng)論 0 0
  • 今天看了《感動(dòng)中國(guó)》葱峡,其實(shí)每年都要看,每年都有不一樣的感動(dòng)龙助。今年印象最深刻的是那個(gè)村官大學(xué)生砰奕,耶魯大學(xué)生甘愿當(dāng)大學(xué)...
    最喜不過(guò)淡雅閱讀 246評(píng)論 2 1
  • 摘自《瓦爾登湖》第四頁(yè)军援。 我怕常空,在美的季候里,我沒(méi)有收到通知盖溺,就開(kāi)始丟失自己漓糙。我怕,在時(shí)代的波瀾里烘嘱,我連呼救的機(jī)會(huì)...
    翔于閱讀 757評(píng)論 0 1