設(shè)計(jì)一個(gè)統(tǒng)一算費(fèi)流程

為什么我們需要一個(gè)統(tǒng)一的算費(fèi)流程醒第。

我在第二家公司的時(shí)候琐鲁,從從事的是醫(yī)療領(lǐng)域的電商韩玩,當(dāng)時(shí)我們的優(yōu)惠相關(guān)的計(jì)算嵌入在訂單的代碼里面剥槐。

public abstract class OrderSubmitHandler {

    /**
     * 1. 初始化訂單信息
     *    init: storeVO,orderMainDO朦乏,orderSubDOList,freeFlag
     */
    public abstract OrderSubmitDTO initOrder(OrderSubmitRequest request);

    /**
     * 2. 組裝優(yōu)惠券優(yōu)惠,同時(shí)初始化實(shí)物訂單的order_sub
     */
    public abstract void handleCoupon(OrderSubmitDTO result);

    /**
     * 3. DTC + VIP
     */
    public abstract void handleDTCAndVIP(OrderSubmitDTO result);

    /**
     * 4. 計(jì)算orderMain金額
     */
    public abstract void computeMainOrderPay(OrderSubmitDTO result);

    /**
     * 5. 插入訂單主表球及、子訂單、快照信息呻疹、支付單信息
     */
    public abstract void insertDB(OrderSubmitDTO result);

    /**
     * 6. 生成預(yù)約信息
     */
    public abstract void insertReserve(OrderSubmitDTO result);

    /**
     * 7. 生成返回值
     */
    public abstract OrderAddResponse getResponse(OrderSubmitDTO result);

    /**
     *  提交流程
     * */
    @Transactional
    public OrderAddResponse submitOrder(OrderSubmitRequest request){
        log.info("request:{}",JSON.toJSONString(request));

        //1. 初始化
        OrderSubmitDTO result = this.initOrder(request);
        log.info( "initOrder:{}", JSON.toJSONString(result) );

        //2. 組裝優(yōu)惠券優(yōu)惠
        this.handleCoupon(result);
        log.info( "handleCoupon:{}", JSON.toJSONString(result) );

        //先計(jì)算dtc吃引,vip只優(yōu)惠首次支持金額的88折,即7%的88折扣
        //3. DTC + vip的優(yōu)惠
        this.handleDTCAndVIP(result);
        log.info( "handleDTCAndVIP:{}", JSON.toJSONString(result) );

        //4. 計(jì)算order_main金額
        this.computeMainOrderPay(result);
        //this.handleVipCoupon(result);
        //5. 插入訂單主表、子訂單际歼、快照信息、支付單信息
        this.insertDB(result);

        //6. 如果免費(fèi)單姑蓝,生成預(yù)約信息
        this.insertReserve(result);

        OrderAddResponse response = this.getResponse(result);
        return response ;
    }

}

每當(dāng)優(yōu)惠擴(kuò)展的時(shí)候我們不得不增加流程或者增加優(yōu)惠計(jì)算的代碼鹅心,由于優(yōu)惠代碼又是平鋪式的編寫(xiě),導(dǎo)致后期復(fù)雜的代碼難以維護(hù)纺荧,可讀寫(xiě)性也大大降低旭愧。

于是我希望設(shè)計(jì)這樣一段代碼,每一個(gè)扣減邏輯是一個(gè)單獨(dú)的算子宙暇,可以分開(kāi)實(shí)現(xiàn)输枯,費(fèi)用的計(jì)算可以由多個(gè)算子組成,算子可以排序?qū)崿F(xiàn)任意流程的編排占贫。算子需要足夠的抽象桃熄,不止支持優(yōu)惠卷,還是支持其他抵扣的虛擬貨幣型奥。我希望可以保存每種計(jì)算方式的金額瞳收,這樣就可以在訂單里展示優(yōu)惠詳情,每一項(xiàng)抵扣了多少金額厢汹。

設(shè)計(jì)

首先我們需要設(shè)計(jì)一個(gè)算子接口

public interface FeeCalculate<O> {

    /**
     * 根據(jù)費(fèi)用項(xiàng)計(jì)算每個(gè)費(fèi)用項(xiàng)明細(xì)
     *
     * @param list
     * @return
     */
    Map<FeeItemType, List<PayItem>> payItemList(List<FeeItem<O>> list);

    /**
     * 每個(gè)支付方式waitPay
     *
     * @param list
     * @return
     */
    Map<FeeItemType, BigDecimal> calculateWaitPay(List<FeeItem<O>> list);

    /**
     * 獲取計(jì)算器的唯一編碼
     *
     * @return
     */
    Unique getUnique();

}

其中FeeItem代表一個(gè)單獨(dú)的費(fèi)用項(xiàng)螟深,必須郵費(fèi),打包費(fèi)之類(lèi)的烫葬。

public interface FeeItem<O> {

    /**
     * 原始金額
     *
     * @return
     */
    BigDecimal getFeeItemOriginMoney();

    /**
     * 費(fèi)用類(lèi)型
     *
     * @return
     */
    FeeItemType getFeeItemType();

    /**
     * 獲取訂單原始信息
     *
     * @return
     */
    O getOrderInfo();

}

不用的費(fèi)用需要不同的計(jì)算方式,所以我們需要不同的type來(lái)表示

/**
 * 為了區(qū)分不同費(fèi)用不同計(jì)算方式
 */
public enum FeeItemType implements BaseEnum<FeeItemType> {

    SERVICE_FEE(1, "服務(wù)費(fèi)"),
    ELECTRIC_FEE(2, "電費(fèi)"),
    OVER_WEIGHT_FEE(3, "超重費(fèi)"),
    OVER_TIME_FEE(4, "超時(shí)費(fèi)");

    FeeItemType(Integer code, String name) {
        this.code = code;
        this.name = name;
    }

    private Integer code;
    private String name;

    @Override
    public Integer getCode() {
        return this.code;
    }

    @Override
    public String getName() {
        return this.name;
    }

    public static Optional<FeeItemType> of(Integer code) {
        return Optional.ofNullable(BaseEnum.parseByCode(FeeItemType.class, code));
    }

}

不同的費(fèi)用由不同的方式支付或者抵扣

public interface PayItem {

  BigDecimal getMoney();

  PayGroup getPayGroup();

  PayType getPayType();

}

PayGroup代表不同的支付方式

public enum PayGroup implements BaseEnum<PayGroup> {

    THIRD_PAY(1, "三方支付"),
    PLATFORM_PAY(2, "平臺(tái)支付"),
    VIRTUAL_PROPERTY(3, "虛擬資產(chǎn)"),
    BANK(4, "銀行卡支付"),
    COUPON(4, "優(yōu)惠劵");

    PayGroup(Integer code, String name) {
        this.code = code;
        this.name = name;
    }

    private Integer code;
    private String name;

    @Override
    public Integer getCode() {
        return this.code;
    }

    @Override
    public String getName() {
        return this.name;
    }

    public static Optional<PayGroup> of(Integer code) {
        return Optional.ofNullable(BaseEnum.parseByCode(PayGroup.class, code));
    }

}

PayType代表具體的支付類(lèi)型界弧,比如三方支付下的微信支付。

public enum PayType implements BaseEnum<PayType> {

  WECHAT(1, "微信支付"),
  ALIPAY(2,"支付寶"),
  COIN(3,"虛擬幣"),
  ACTIVITY(4,"活動(dòng)")
  ;

  PayType(Integer code, String name) {
    this.code = code;
    this.name = name;
  }

  private Integer code;
  private String name;

  @Override
  public Integer getCode() {
    return this.code;
  }

  @Override
  public String getName() {
    return this.name;
  }

  public static Optional<PayType> of(Integer code) {
    return Optional.ofNullable(BaseEnum.parseByCode(PayType.class, code));
  }

}

在上面的需求中搭综,我希望算子只需要實(shí)現(xiàn)自己的業(yè)務(wù)邏輯垢箕,不需要關(guān)注算子的編排和具體的執(zhí)行邏輯,當(dāng)前算子需要上一個(gè)算子的計(jì)算結(jié)果兑巾,所以我需要使用裝飾器模式來(lái)增強(qiáng)算子的能力舰讹,并使用責(zé)任鏈鏈接多個(gè)算子,規(guī)劃算子執(zhí)行的流程闪朱。

public abstract class AbstractCalculator<O> implements FeeCalculate<O> {

    private final FeeCalculate<O> feeCalculate;

    private final Unique unique;

    protected AbstractCalculator(FeeCalculate<O> feeCalculate, Unique unique) {
        this.feeCalculate = feeCalculate;
        this.unique = unique;
    }

    @Override
    public Unique getUnique() {
        return unique;
    }

    /**
     * 當(dāng)前抵扣
     */
    protected abstract Map<FeeItemType, BigDecimal> currentPayItem(Map<FeeItemType, BigDecimal> left, O o);

    /**
     * 當(dāng)前抵扣的明細(xì)
     */
    protected abstract Map<FeeItemType, List<PayItem>> payItemList();

    @Override
    public Map<FeeItemType, List<PayItem>> payItemList(List<FeeItem<O>> list) {
        //初始化算子的支付項(xiàng)
        Map<FeeItemType, List<PayItem>> map;
        if (Objects.nonNull(feeCalculate) && Objects.nonNull(feeCalculate.payItemList(list))) {
            map = feeCalculate.payItemList(list);
        } else {
            map = Maps.newHashMap();
        }
        //獲取已經(jīng)存在的支付項(xiàng)
        Map<FeeItemType, List<PayItem>> currentList = payItemList();
        //合并算子付費(fèi)項(xiàng)
        if (Objects.nonNull(currentList) && !currentList.isEmpty()) {
            currentList.forEach((key, value) -> {
                List<PayItem> tempList = map.getOrDefault(key, Lists.newArrayList());
                tempList.addAll(value);
                map.put(key, tempList);
            });
        }
        return map;
    }

    @Override
    public Map<FeeItemType, BigDecimal> calculateWaitPay(List<FeeItem<O>> list) {
        //如果沒(méi)有上層包裝月匣,那么直接返回訂單的實(shí)際金額減去當(dāng)前抵扣的金額
        if (Iterables.isEmpty(list)) {
            //計(jì)費(fèi)項(xiàng)為空
            throw new RuntimeException(FeeEnum.FEE_ITEM_EMPTY.getName());
        }
        Map<FeeItemType, BigDecimal> leftMap = Maps.newHashMap();
        if (Objects.isNull(feeCalculate)) {
            for (FeeItem<O> item : list) {
                leftMap.put(item.getFeeItemType(), item.getFeeItemOriginMoney());
            }
            Map<FeeItemType, BigDecimal> currentDeduct = currentPayItem(leftMap,
                    list.get(0).getOrderInfo());
            //合并費(fèi)用
            currentDeduct.forEach(
                    (key, value) -> leftMap.put(key, NumberUtil.sub(leftMap.get(key), value))
            );
            return leftMap;
        } else {
            //存在下一個(gè)算子,流程未完
            Map<FeeItemType, BigDecimal> left = feeCalculate.calculateWaitPay(list);
            //如果有任何一個(gè)
            Optional<BigDecimal> greaterThanZero = left.values().stream()
                    .toList().stream()
                    //過(guò)濾出所有不為零的費(fèi)用
                    .filter(s -> NumberUtil.isGreater(s, BigDecimal.ZERO))
                    .findFirst();
            //算子無(wú)抵扣項(xiàng)直接返回
            if (greaterThanZero.isEmpty()) {
                return left;
            }
            Map<FeeItemType, BigDecimal> current = currentPayItem(left, list.get(0).getOrderInfo());
            Map<FeeItemType, BigDecimal> temp = Maps.newHashMap();
            for (FeeItem<O> item : list) {
                //如果當(dāng)前有抵扣
                if (Objects.nonNull(current.get(item.getFeeItemType()))) {
                    //超過(guò)剩余支付金額奋姿,拋出異常
                    if (NumberUtil.isGreater(current.get(item.getFeeItemType()),
                            left.get(item.getFeeItemType()))) {
                        throw new RuntimeException(FeeEnum.AMOUNT_GREATER_ERROR.getName());
                    }
                    //正常抵扣
                    temp.put(item.getFeeItemType(),
                            NumberUtil.sub(left.get(item.getFeeItemType()), current.get(item.getFeeItemType())));
                } else {
                    //如果當(dāng)前沒(méi)有抵扣锄开,直接返回剩余金額
                    temp.put(item.getFeeItemType(), left.get(item.getFeeItemType()));
                }
            }
            return temp;
        }
    }
}

測(cè)試用例

1.當(dāng)前訂單是一個(gè)簡(jiǎn)單的服務(wù)費(fèi)支付訂單,用戶(hù)參加了一個(gè)活動(dòng)称诗,使用了一個(gè)優(yōu)惠券萍悴,希望計(jì)算出需要支付的實(shí)際金額.

初始化抵扣算子

/**
 * 服務(wù)費(fèi)抵扣活動(dòng)
 */
public class ActivityCalculator extends AbstractCalculator<OrderInfo> {

  public ActivityCalculator(FeeCalculate<OrderInfo> feeCalculate) {
    super(feeCalculate, CalculateType.ACTIVITY);
  }

  /**
   * 算子抵扣金額
   */
  @Override
  protected Map<FeeItemType, BigDecimal> currentPayItem(Map<FeeItemType, BigDecimal> left,
                                                        OrderInfo o) {
    Map<FeeItemType, BigDecimal> map = Maps.newHashMap();
    map.put(FeeItemType.SERVICE_FEE, new BigDecimal("4"));
    System.out.println("活動(dòng)抵扣了4元費(fèi)用");
    return map;
  }

  @Override
  protected Map<FeeItemType, List<PayItem>> payItemList() {
    Map<FeeItemType, List<PayItem>> map = Maps.newHashMap();
    List<PayItem> payItems = Lists.newArrayList();
    ActivityPayItem ap = new ActivityPayItem(new BigDecimal(4));
    ap.setActivityName("節(jié)日活動(dòng)");
    payItems.add(ap);
    map.put(FeeItemType.SERVICE_FEE, payItems);
    return map;
  }
}
/**
 * 付費(fèi)用優(yōu)惠券
 */
public class CouponCalculator extends AbstractCalculator<OrderInfo> {

  public CouponCalculator(FeeCalculate<OrderInfo> feeCalculate) {
    super(feeCalculate, CalculateType.COUPON);
  }

  @Override
  protected Map<FeeItemType, BigDecimal> currentPayItem(Map<FeeItemType, BigDecimal> left,
      OrderInfo o) {
    Map<FeeItemType, BigDecimal> map = Maps.newHashMap();
    map.put(FeeItemType.SERVICE_FEE, new BigDecimal("5"));
    System.out.println("劵抵扣了5元費(fèi)用");
    return map;
  }

  @Override
  protected Map<FeeItemType, List<PayItem>> payItemList() {
    Map<FeeItemType, List<PayItem>> map = Maps.newHashMap();
    List<PayItem> payItems = Lists.newArrayList();
    CouponPayItem cp = new CouponPayItem(new BigDecimal(5));
    cp.setCouponCode("C1234528");
    payItems.add(cp);
    map.put(FeeItemType.SERVICE_FEE, payItems);
    return map;
  }
}

初始化抵扣項(xiàng)

public class ActivityPayItem extends AbstractPayItem {

  public ActivityPayItem(BigDecimal money) {
    super(money, PayType.ACTIVITY, PayGroup.COUPON);
  }

  private String activityName;
}
public class CouponPayItem extends AbstractPayItem {

  public CouponPayItem(BigDecimal money) {
    super(money, PayType.COIN, PayGroup.COUPON);
  }

  private String couponCode;

  private String source;
}

一個(gè)普通的例子

public class CalculateTest {

    public static void main(String[] args) {
        //初始化一個(gè)簡(jiǎn)單的訂單
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setTradeFlowNo("T0323423432");
        orderInfo.setOrderType("普通訂單");
        orderInfo.setPayAmount(new BigDecimal(0));
        orderInfo.setServiceFee(new BigDecimal(20));
        //初始化服務(wù)費(fèi)用
        List<FeeItem<OrderInfo>> list = Lists.newArrayList();
        list.add(new ServiceFeeItem(orderInfo, FeeItemType.SERVICE_FEE, orderInfo.getServiceFee()));
        //編排算子
        FeeCalculate<OrderInfo> feeCalculate = new ActivityCalculator(new CouponCalculator(null));
        //獲取待支付金額
        Map<FeeItemType, BigDecimal> leftPay = feeCalculate.calculateWaitPay(list);
        leftPay.forEach((k, v) -> {
            System.out.println("待支付項(xiàng):" + k.getName() + v.toPlainString() + "元");
        });
        //抵扣項(xiàng)展示
        Map<FeeItemType, List<PayItem>> payItemList = feeCalculate.payItemList(list);
        payItemList.forEach((k, v) -> {
            StringBuffer sb = new StringBuffer();
            v.forEach(p -> {
                sb.append("支付類(lèi)型:").append(p.getPayType().getName());
                sb.append("支付金額:").append(p.getMoney()).append("元");
                sb.append(" ! ").append("\n");
            });
            System.out.println("已經(jīng)抵扣:\n" + k.getName()+"\n" + sb);
        });
    }

}

一個(gè)復(fù)雜的例子

當(dāng)我們希望把一些計(jì)算的規(guī)則配置暴露給運(yùn)營(yíng)人員,當(dāng)運(yùn)營(yíng)配置好規(guī)則然后查詢(xún)出來(lái)生成算子。

規(guī)則相關(guān)

public interface FeeRule {

  /**
   * 獲取配置的數(shù)值
   * @return
   */
  BigDecimal getConfigValue();

  /**
   * 獲取規(guī)則類(lèi)型
   * @return
   */
  FeeRuleType getRuleType();

  /**
   * 規(guī)則的順序
   * @return
   */
  Integer getOrder();

}

一個(gè)簡(jiǎn)單的工廠類(lèi)用來(lái)生成算子

public class CalculatorFactory {

  public static FeeCalculate<OrderInfo> getFeeCalculateByRuleType(FeeCalculate<OrderInfo> calculate, FeeRule rule) {
    if (Objects.equals(FeeRuleType.FREE_TIME, rule.getRuleType())) {
      FreeTimeRule time = (FreeTimeRule) rule;//這里可以強(qiáng)制轉(zhuǎn)化
      return new FreeTimeCalculator(calculate, CalculatorType.FREE_TIME, time.getConfigValue().intValue());
    } else if (Objects.equals(FeeRuleType.FREE_TIMES, rule.getRuleType())) {
      FreeTimesRule timesRule = (FreeTimesRule) rule;
      return new FreeTimesCalculator(calculate, CalculatorType.FREE_TIMES, timesRule.getConfigValue().intValue());
    } else if (Objects.equals(FeeRuleType.PLUS_RULE, rule.getRuleType())) {
      //不需要可以不轉(zhuǎn)
      return new PlusRuleCalculator(calculate, CalculatorType.PLUS_DISCOUNT, rule.getConfigValue());
    } else if (Objects.equals(FeeRuleType.MAX_LIMIT, rule.getRuleType())) {
      return new MaxLimitCalculator(calculate, CalculatorType.MAX_LIMIT, rule.getConfigValue());
    }
    return null;
  }


}

編寫(xiě)流程

public class FeeCalculateTest {


    public void testFee() {
        //初始化規(guī)則
        List<FeeRule> ruleList = Lists.newArrayList();
        FreeTimesRule freeTimesRule = new FreeTimesRule(new BigDecimal(0), FeeRuleType.FREE_TIMES, 3);
        FreeTimeRule freeTimeRule = new FreeTimeRule(new BigDecimal(1), FeeRuleType.FREE_TIME, 1);
        PlusRule plusRule = new PlusRule(new BigDecimal("0.95"), FeeRuleType.PLUS_RULE, 4);
        MaxLimitRule maxLimitRule = new MaxLimitRule(new BigDecimal("1.4"), FeeRuleType.MAX_LIMIT, 5);

        ruleList.add(freeTimesRule);
        ruleList.add(freeTimeRule);
        ruleList.add(plusRule);
        ruleList.add(maxLimitRule);

        //排序規(guī)則
        List<FeeRule> sortRules = ruleList.stream().sorted(Comparator.comparingInt(FeeRule::getOrder))
                .toList();

        //初始化支付項(xiàng)
        List<FeeItem<OrderInfo>> payItemList = Lists.newArrayList();
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setCarNo("dddd");
        orderInfo.setParkTimes(3);
        orderInfo.setUserId(4L);
        orderInfo.setTotalMoney(new BigDecimal("30"));
        ParkingFeeItem parkingFeeItem = new ParkingFeeItem(orderInfo);
        payItemList.add(parkingFeeItem);

        //核心流程
        FeeCalculate<OrderInfo> calculate = null;
        for (FeeRule feeRule : sortRules) {
            //根據(jù)規(guī)則類(lèi)型獲取對(duì)應(yīng)的計(jì)算器類(lèi)型癣诱,生成FeeCalculate
            calculate = CalculatorFactory.getFeeCalculateByRuleType(calculate, feeRule);
        }
        //計(jì)算費(fèi)用
        assert calculate != null;
        Map<FeeItemType, BigDecimal> waitPay = calculate.calculateWaitPay(payItemList);

        BigDecimal waitPayMoney = waitPay.get(FeeItemType.SERVICE_FEE);
        System.out.println("待支付金額" + waitPayMoney);

        Map<FeeItemType, List<PayItem>> map = calculate.payItemList(payItemList);

        MapUtils.debugPrint(System.out, "console", map);
        List<PayItem> payList = map.get(FeeItemType.SERVICE_FEE);
        payList.forEach(payItem -> {
                    System.out.println(payItem.getMoney());
                    System.out.println(payItem.getPayType());
                    System.out.println(payItem.getPayGroup());
                });
    }

    public static void main(String[] args) {
        FeeCalculateTest test = new FeeCalculateTest();
        test.testFee();
    }

}

寫(xiě)在最后

  1. 完整代碼
    MyTest/src/main/java/com/fee at master · wty4427300/MyTest (github.com)

  2. 使用的設(shè)計(jì)模式
    裝飾器
    工廠
    責(zé)任鏈

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末计维,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子撕予,更是在濱河造成了極大的恐慌鲫惶,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,651評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件实抡,死亡現(xiàn)場(chǎng)離奇詭異欠母,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)吆寨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)赏淌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人啄清,你說(shuō)我怎么就攤上這事六水。” “怎么了辣卒?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,931評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵缩擂,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我添寺,道長(zhǎng)胯盯,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,218評(píng)論 1 292
  • 正文 為了忘掉前任计露,我火速辦了婚禮博脑,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘票罐。我一直安慰自己叉趣,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布该押。 她就那樣靜靜地躺著疗杉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蚕礼。 梳的紋絲不亂的頭發(fā)上烟具,一...
    開(kāi)封第一講書(shū)人閱讀 51,198評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音奠蹬,去河邊找鬼朝聋。 笑死,一個(gè)胖子當(dāng)著我的面吹牛囤躁,可吹牛的內(nèi)容都是我干的冀痕。 我是一名探鬼主播荔睹,決...
    沈念sama閱讀 40,084評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼言蛇!你這毒婦竟也來(lái)了僻他?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,926評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤腊尚,失蹤者是張志新(化名)和其女友劉穎吨拗,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體跟伏,經(jīng)...
    沈念sama閱讀 45,341評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評(píng)論 2 333
  • 正文 我和宋清朗相戀三年翩瓜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了受扳。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,731評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡兔跌,死狀恐怖勘高,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情坟桅,我是刑警寧澤华望,帶...
    沈念sama閱讀 35,430評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站仅乓,受9級(jí)特大地震影響赖舟,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜夸楣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評(píng)論 3 326
  • 文/蒙蒙 一宾抓、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧豫喧,春花似錦石洗、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,676評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至孵班,卻和暖如春涉兽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背篙程。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,829評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工花椭, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人房午。 一個(gè)月前我還...
    沈念sama閱讀 47,743評(píng)論 2 368
  • 正文 我出身青樓矿辽,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子袋倔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評(píng)論 2 354

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