使用dva实现的request.js请求工具函数utils封装 并且发送请求(转)

import fetch from 'dva/fetch';

import {

  notification

} from 'antd';

import qs from 'querystring';

const codeMessage = {

  200: '请求成功',

  201: '新建或修改数据成功',

  202: '一个请求已经进入后台队列',

  204: '删除数据成功',

  400: '请求失败',

  401: 'token失效',

  403: '禁止访问',

  404: '请求失败',

  406: '请求方式错误',

  500: '服务器错误',

  502: '网关错误',

  503: '服务不可用',

  504: '网关超时',

};

// 检查ajax返回的状态

function checkStatus(response) {

  if (response.status >= 200 && response.status < 300) {

    return response;

  }

  /**

  * 暂时没用,服务端返回的 status 始终为200

  *

  * @type {*|string|string}

  */

  const errorText = codeMessage[response.status] || response.statusText;

  notification.error({

    message: `请求错误 ${response.status}: ${response.url}`,

    description: errorText,

  });

  const error = new Error(response.statusText);

  error.name = response.status;

  error.response = response;

  throw error;

}

// fetch超时处理

const TIMEOUT = 100000;

const timeoutFetch = (url, options) => {

  let fetchPromise = fetch(url, options);

  let timeoutPromise = new Promise((resolve, reject) => {

    setTimeout(() => reject(new Error('请求超时')), TIMEOUT);

  });

  return Promise.race([fetchPromise, timeoutPromise]);

};

/**

* 请求url,返回promise 对象

*

* @param  {string} url      The URL we want to request

* @param  {object} [options] The options we want to pass to "fetch"

* @return {object}          An object containing either "data" or "err"

*/

export default function request(url, options) {

  const defaultOptions = {

    credentials: 'include',

    method: 'GET',

    mode: 'cors',

  };

  const mergeOptions = {

    ...defaultOptions,

    ...options

  };

  const userInfo = JSON.parse(window.sessionStorage.getItem('userInfo'));

  const appKey = window.sessionStorage.getItem('appKey');

  mergeOptions.headers = {

    accept: 'application/json',

    'content-type': 'application/json; charset=utf-8',

    ...mergeOptions.headers,

  };

  if (appKey) mergeOptions.headers.uuuappkey = appKey;

  if (userInfo) mergeOptions.headers.uuutoken = userInfo.sessionId;

  if (mergeOptions.method !== 'GET') {

    mergeOptions.body = JSON.stringify(mergeOptions.body);

  }

  if (mergeOptions.method !== 'POST' && mergeOptions.params) {

    url = `${url}${url.indexOf('?') !== -1 ? '&' : '?'}${qs.stringify(mergeOptions.params)}`;

  }

  if (!mergeOptions.hideTime && !mergeOptions.params) {

    url = `${url}?timeStamp=${new Date().getTime()}`;

  }

  return timeoutFetch(url, mergeOptions)

    .then(checkStatus)

    .then((response) => {

      return response.json();

    })

    .then((data) => {

      if (data.code === 200 || data.success === true) {

        return data;

      }

      if (data.code === 300) { // 接口出错

        return data;

      }

      if (data.code === 401) { // token失效

        notification.error({

          message: 'token失效',

          description: data.msg,

          key: 'error'

        });

        window.g_app._store.dispatch({

          type: 'app/logout'

        });

        return data;

      }

      if (data.code === 403) { // 没有权限

        notification.error({

          message: '没有权限',

          description: data.msg,

          key: 'error'

        });

        return data;

      }

      if (data.code >= 404 && data.code < 422) {

        notification.error({

          message: '请求失败',

          description: data.msg,

          key: 'error'

        });

        return data;

      }

      if (data.code <= 504 && data.code >= 500) {

        notification.error({

          message: '服务器错误',

          description: data.msg,

          key: 'error'

        });

        return data;

      }

    })

    .catch((error) => {

      const {

        response

      } = error;

      let msg;

      let statusCode;

      if (response && response instanceof Object) {

        const {

          status,

          statusText

        } = response;

        statusCode = status;

        msg = statusText;

      } else {

        statusCode = 600;

        msg = 'Network Error';

      }

      return Promise.reject({

        success: false,

        code: statusCode,

        msg

      });

    });

}

调用:

import request from '../utils/request';

import { apiPrefix } from '../config/projectConfig';

// 获取 scheme 列表

export function oracleSchema() {

  return request(`${apiPrefix}/api_manager/interface/api/fetchOracleSchemas`);

}

// 接口菜单层级树

export function interfaceLevel(pid) {

  return request(

    `${apiPrefix}/api_manager/interface/api/getAPILevelTree?pid=${pid}`,{

      hideTime: true,

    });

}

// 获取目录树

export function catalogTree() {

  return request(`${apiPrefix}/api_manager/interface/api/getAPICatalogTree`);

}

// 搜索菜单树

export function searchLevelTree(search) {

  return request(

    `${apiPrefix}/api_manager/interface/api/searchAPILevelTree?search=${search}`, {

      hideTime: true,

    });

}

// 查询接口上级分类树

export function apiDirectory(apiId) {

  return request(`${apiPrefix}/api_manager/interface/api/getAPIDirectory?apiId=${apiId}`, {

    hideTime: true,

  });

}

// 新增 API 树目录

export function addApiTree(params) {

  return request(`${apiPrefix}/api_manager/interface/api/addApiTree`, {

    method: 'POST',

    body: params,

  });

}

// 删除 API 树目录

export function delApiTree(params) {

  return request(`${apiPrefix}/api_manager/interface/api/deleteApiTree?apiTreeId=${params.apiTreeId}`, {

    method: 'DELETE',

    hideTime: true,

  });

}

/************************************************************************

* 接口相关

************************************************************************/

// 接口列表

export function apiList(params, pageNum, pageSize) {

  return request(`${apiPrefix}/api_manager/interface/api/getApiList`, {

    method: 'POST',

    body: { ...params, pageNum, pageSize },

  });

}

// 新增接口

export function addApi(params) {

  return request(`${apiPrefix}/api_manager/interface/api/addApi`, {

    method: 'POST',

    body: params,

  });

}

// 修改接口

export function updateApi(params) {

  return request(`${apiPrefix}/api_manager/interface/api/updateApi`, {

    method: 'PUT',

    body: params,

  });

}

// 删除接口

export function delApi(params) {

  return request(`${apiPrefix}/api_manager/interface/api/deleteApi?apiId=${params.apiId}`, {

    method: 'DELETE',

    hideTime: true,

  });

}

/************************************************************************

* sql相关

************************************************************************/

// 获取 sql

export function getApiSqlInfo(params) {

  return request(`${apiPrefix}/api_manager/interface/api/getApiSqlInfo?apiId=${params.apiId}`, {

    hideTime: true,

  });

}

// 保存

export function interfaceDefSave(params) {

  return request(`${apiPrefix}/api_manager/interface/api/interfaceDefSave`, {

    method: 'POST',

    body: params,

  });

}

// 获取模型列表 - 表名

export function getBizList(params, pageNum, pageSize) {

  return request(`${apiPrefix}/api_manager/interface/api/getBizList`, {

    method: 'POST',

    body: { ...params, pageNum, pageSize },

  });

}

// 获取模型列表 - 列名

export function getBizColList(bizId) {

  return request(`${apiPrefix}/api_manager/interface/api/getBizColList?bizId=${bizId}`, {

    hideTime: true,

  });

}

// 解析 sql 获得 select item 列表(出参)

export function selectItemsForSql(params) {

  return request(`${apiPrefix}/api_manager/interface/api/getSelectItemsForSql`, {

    method: 'POST',

    body: params,

  });

}

// 获取 procedure info

export function procedureInfo(params) {

  return request(`${apiPrefix}/api_manager/interface/api/fetchOracleProcedureInfo`, {

    method: 'POST',

    body: params,

  });

}

// 获取 procedure params

export function procedureParams({ owner, procedureName }) {

  return request(`${apiPrefix}/api_manager/interface/api/fetchOracleAllProcedureParams`, {

    params: {

      owner,

      procedureName,

    },

  });

}

/************************************************************************

* auth相关

************************************************************************/

// 获取系统名

export function appNameApi({ apiId }) {

  return request(`${apiPrefix}/menu_manager/menu/api/getAppNameForApi?apiId=${apiId}`, {

    method: 'POST',

    hideTime: true,

  });

}

// 获取指标列表

export function indexAppName(params) {

  return request(`${apiPrefix}/menu_manager/menu/api/getIndexForAppName`, {

    method: 'POST',

    body: params,

  });

}

// 保存 auth

export function addIndexAppName(params) {

  return request(`${apiPrefix}/menu_manager/menu/api/addIndexForAppName`, {

    method: 'POST',

    body: [...params],

  });

}

dva模型调用: 

import { message } from 'antd';

import modelExtend from 'dva-model-extend';

import { pageModel } from '../../../utils/util';

import {

addApiTree,

addApi,

getApiSqlInfo,

interfaceDefSave,

selectItemsForSql,

procedureInfo,

procedureParams,

appNameApi,

indexAppName,

addIndexAppName,

} from '../../../services/modelInterface';

export default modelExtend(pageModel, {

namespace: 'interfaceModal',

state: {

interfaceDef: {},

},

effects: {

// 获取 接口定义

* getApiSqlInfo({ payload }, { call, put }) {

const { success, data } = yield call(getApiSqlInfo, payload);

if (success) {

if (data.apiType === 0) data.apiType = 1;

yield put({

type: 'updateState',

payload: {

interfaceDef: data,

},

});

return true;

} else {

message.error('初始化失败');

}

},

    /************************************************************************

    * sql 弹窗相关

    ************************************************************************/

// sql弹窗保存

* interfaceDefSave({ payload }, { call }) {

const { success } = yield call(interfaceDefSave, payload);

if (success) return true;

},

// 解析 sql 获得 select item 列表(出参)

* getSelectItemsForSql({ payload }, { call }) {

const { success, data } = yield call(selectItemsForSql, payload);

if (success) return data;

},

// 获取 oracleChildSchema

* procedureInfo({ payload }, { call }) {

const { success, data } = yield call(procedureInfo, payload);

if (success) return data.list;

},

// 获取 SP 入参字段

* procedureParams({ payload }, { call }) {

const { success, data } = yield call(procedureParams, payload);

if (success) return data;

},

    /************************************************************************

    * auth 弹窗相关

    ************************************************************************/

// 获取系统名

* appNameApi({ payload }, { call }) {

const { success, data } = yield call(appNameApi, payload);

if (success) return data;

},

// 获取指标

* indexAppName({ payload }, { call }) {

const { success, data } = yield call(indexAppName, payload);

if (success) return data;

},

// 保存auth

* addIndexAppName({ payload }, { call }) {

const { success } = yield call(addIndexAppName, payload);

if (success) return true;

},

},

});

模块组成:

组件具体使用:

import React, { Component, Fragment } from 'react';

import { connect } from 'dva';

import PropTypes from 'prop-types';

import { Col, Row, Button, Modal, Collapse, Card, Icon, Tooltip, Form, Input } from 'antd';

import { ContextMenu, MenuItem } from 'react-contextmenu';

import { Page, SearchTree, CommonTable, CustomModal, CustomForm, CommonSearch, Breadcrumb } from '@/components';

import { apiList } from '../../services/modelInterface';

import { modelInterfaceColumns, participationColumns } from './config/columns';

import { sqlForm, folderForm, interfaceForm } from './config/form';

import { modelInterfaceSearch } from './config/search';

import { getCrumb } from '../../utils/util';

import ModalView from './components';

import style from './index.less';

const { Panel } = Collapse;

const { TextArea } = Input;

@connect(({ modelInterface, loading }) => ({

...modelInterface,

loading,

}))

class ModelInterface extends Component {

tableRef = React.createRef();

state = {

editable: false,

searchParams: {},

selectedNode: {},

visible: false, // 模态框状态

modalType: '', // 模态框类型

record: {},  // 编辑时原始数据

};

static getDerivedStateFromProps(props, state) {

const { dispatch, selectedNode } = props;

if (props.selectedNode !== state.selectedNode && props.selectedNode) {

const { id, isDirectory } = props.selectedNode;

if (id) {

dispatch({ type: 'modelInterface/getBizDirectory', id });

if (!isDirectory) {

// dispatch({ type: 'bizFormTable/bizInfo', payload: { id } });

}

return { selectedNode };

}

}

return null;

}

// 处理搜索

handleSearch = (values) => {

this.setState({ searchParams: values });

};

// 模态框状态处理

showModal = async ({ record, modalType }) => {

const { dispatch } = this.props;

if (modalType === 'sql') {

const data = await dispatch({ type: 'interfaceModal/getApiSqlInfo', payload: { apiId: record.apiId } });

if (!data) return;

}

this.setState({ visible: true, modalType, record });

};

closeModal = () => this.setState({ visible: false, modalType: '', record: {} });

// 选择接口

handleSelect = async (keys, { node }) => {

const { dispatch, selectedNode } = this.props;

const dataRef = node.props['dataRef'];

const flag = selectedNode.id !== dataRef.id;

if (flag) {

this.setState({ editable: false });

if (dataRef['subNodeNum']) {

await dispatch({ type: 'modelInterface/levelTreeList', pid: dataRef.id });

}

dispatch({ type: 'modelInterface/updateState', payload: { selectedNode: dataRef } });

}

};

// 新增目录

handleAddFolder = (e, data, target) => {

const nodeItem = JSON.parse(target.getAttribute('data-item'));

this.setState({ visible: true, modalType: 'folder', record: { upperApiTreeId: nodeItem.id } });

};

// 删除目录

handleDelFolder = (e, data, target) => {

const nodeItem = JSON.parse(target.getAttribute('data-item'));

Modal.confirm({

title: '提示',

content: '你确定删除该目录嘛?',

onOk: async () => {

const { dispatch } = this.props;

await dispatch({ type: 'modelInterface/delApiTree', payload: { apiTreeId: nodeItem.id } });

dispatch({ type: 'modelInterface/interfaceTree' });

},

onCancel() { },

});

};

// 删除接口

handleDelInterface = (e, data, target) => {

const nodeItem = JSON.parse(target.getAttribute('data-item'));

Modal.confirm({

title: '提示',

content: '你确定删除该接口嘛?',

onOk: async () => {

const { dispatch } = this.props;

await dispatch({ type: 'modelInterface/delApi', payload: { apiId: nodeItem.id } });

this.tableRef.current.handleFirstPage();

},

onCancel() { },

});

};

// 保存

handleSubmit = async (values) => {

const { modalType, record } = this.state;

const { dispatch } = this.props;

if (modalType === 'folder') {

await dispatch({

type: 'modelInterface/addApiTree',

payload: { ...record, ...values },

});

dispatch({ type: 'modelInterface/interfaceTree' });

}

// 新增或编辑接口

if (modalType === 'updateApi' || modalType === 'addApi') {

const params = record && record.apiId ? { ...values, apiId: record.apiId } : values;

await dispatch({

type: `modelInterface/${modalType}`,

payload: params,

});

this.tableRef.current.handleFirstPage();

}

};

// 面包屑点击

handleCrumbClick = async (item) => {

const { dispatch } = this.props;

dispatch({ type: 'modelInterface/levelTreeList', pid: item.id });

};

render() {

const { visible, modalType, record, searchParams } = this.state;

const { selectedNode, interfaceTree, expandedKeys, directoryInfo, catalogTree, dispatch, loading, form } = this.props;

console.log('interfaceTree>>>>>', interfaceTree)

const columns = [

...modelInterfaceColumns,

{

title: '操作',

dataIndex: 'operator',

render: (text, record) => (

<div className="btn-group">

<Button type="primary" size="small" onClick={() => this.showModal({ modalType: 'sql', record })}>SQL</Button>

<Button type="primary" size="small" onClick={() => this.showModal({ modalType: 'updateApi', record })}>修改</Button>

<Button type="primary" size="small" onClick={() => this.showModal({ modalType: 'auth', record })}>授权</Button>

</div>

),

},

];

const paramsColumns = [

...participationColumns,

{

title: '操作',

dataIndex: 'operator',

render: (text, record) => (

<div className="btn-group">

<Button type="primary" size="small" onClick={() => this.showModal({ modalType: 'sql', record })}>SQL</Button>

<Button type="primary" size="small" onClick={() => this.showModal({ modalType: 'updateApi', record })}>修改</Button>

<Button type="primary" size="small" onClick={() => this.showModal({ modalType: 'auth', record })}>授权</Button>

</div>

),

},

];

return (

<Page className="pageContainer" loading={loading.effects['modelInterface/interfaceTree']}>

<Row gutter={12}>

{/* 树列表 */}

<Col xs={{ span: 24 }} lg={{ span: 6 }} className="treeNav">

<SearchTree

dispatch={dispatch}

placeholder='请输入表名称'

config={{ key: 'id', title: 'name' }}

showRightMenu={true}

showRemoteSearch={true}

treeData={interfaceTree}

defaultExpandedKeys={expandedKeys}

iconFlagOptions={{ icon: 'api' }}

handleSelect={this.handleSelect}

modelFunc="modelInterface/searchTreeWithColCount"

/>

<ContextMenu id="parent_unique_identifier">

<MenuItem key="addInterface" onClick={() => this.showModal({ modalType: 'addApi' })}>新增接口</MenuItem>

<MenuItem divider />

<MenuItem key="addFolder" onClick={this.handleAddFolder}>新增目录</MenuItem>

<MenuItem divider />

<MenuItem key="delFolder" onClick={this.handleDelFolder}>删除目录</MenuItem>

</ContextMenu>

<ContextMenu id="child_unique_identifier">

<MenuItem key="delInterface" onClick={this.handleDelInterface}>删除接口</MenuItem>

</ContextMenu>

</Col>

{/* 表格列表 */}

<Col xs={{ span: 24 }} lg={{ span: 18 }} className="tableContainer">

<div className="gutter-box">

<Breadcrumb breadcrumbList={getCrumb(directoryInfo, { title: 'name', click: this.handleCrumbClick })} />

{/* <CommonSearch

style={{ marginTop: 12 }}

columnNumber={2}

showResetBtn={false}

formList={modelInterfaceSearch}

handleSearch={this.handleSearch}

/> */}

<Collapse defaultActiveKey={['1']} style={{ marginBottom: 20 }} >

<Panel header="sql信息" key="1">

<div>1111</div>

</Panel>

</Collapse>

<Collapse defaultActiveKey={['1']} style={{ marginBottom: 20 }} >

<Panel header="入参" key="1">

<CommonTable

rowKey="apiId"

bordered={false}

selectType={false}

ref={this.tableRef}

columns={paramsColumns}

fetchList={apiList}

searchParams={{ upperId: selectedNode.id, ...searchParams }}

/>

</Panel>

</Collapse>

{/* 系统 */}

<Row gutter={24}>

{[{ appName: 'UCM', appComment: '系统内容' }, { appName: 'ACP', appComment: '系统内容' },] > 0 && [{ appName: 'UCM', appComment: '系统内容' }, { appName: 'ACP', appComment: '系统内容' },].map((sys, index) => (

<Col span={6} key={sys.appKey} style={{ marginBottom: 24 }}>

<Card

className={style.sysBox}

bodyStyle={{ padding: '24px', height: 150 }}

>

<Row>

<Col span={20} className='name'>{sys.appName}</Col>

<Col span={4} className='operate-box'>

<Tooltip placement='top' title='编辑'>

<Icon type='edit' style={{ fontSize: '22px', paddingTop: '6px' }} onClick={() => { this.onShowEditModel(sys); }} />

</Tooltip>

</Col>

</Row>

<Row>

<Col span={24} className='desc'>{sys.appComment}</Col>

</Row>

</Card>

</Col>

))}

</Row>

{/* 菜单 */}

<Row gutter={24}>

{[{ appName: 'UCM', appComment: '系统内容' }, { appName: 'ACP', appComment: '系统内容' },].length > 0 && [{ appName: 'UCM', appComment: '系统内容' }, { appName: 'ACP', appComment: '系统内容' },].map((sys, index) => (

<Col span={6} key={sys.appKey} style={{ marginBottom: 24 }}>

<Card

className={style.sysBox}

bodyStyle={{ padding: '24px', height: 150 }}

>

<Row>

<Col span={20} className='name'>{sys.appName}</Col>

<Col span={4} className='operate-box'>

<Tooltip placement='top' title='编辑'>

<Icon type='edit' style={{ fontSize: '22px', paddingTop: '6px' }} onClick={() => { this.onShowEditModel(sys); }} />

</Tooltip>

</Col>

</Row>

<Row>

<Col span={24} className='desc'>{sys.appComment}</Col>

</Row>

</Card>

</Col>

))}

</Row>

<Collapse defaultActiveKey={['1']} >

<Panel header="出参" key="1">

<CommonTable

rowKey="apiId"

bordered={false}

selectType={false}

ref={this.tableRef}

columns={paramsColumns}

fetchList={apiList}

searchParams={{ upperId: selectedNode.id, ...searchParams }}

/>

</Panel>

</Collapse>

</div>

</Col>

</Row>

{/* 目录、接口弹窗 */}

{

['auth', 'sql'].indexOf(modalType) === -1 && (

<CustomModal

visible={visible}

record={record}

onCancel={this.closeModal}

onSubmit={this.handleSubmit}

renderTitle={() => {

if (modalType === 'folder') {

return (record && !record.id) ? '新增目录' : '编辑目录';

}

if (modalType === 'addApi') {

return '新增接口';

}

if (modalType === 'updateApi') {

return '编辑接口';

}

}}

renderContent={(formOpts) => (

<Fragment>

{modalType === 'folder' && <CustomForm formList={folderForm} {...formOpts} />}

{(modalType === 'addApi' || modalType === 'updateApi') && <CustomForm formList={interfaceForm(catalogTree)} {...formOpts} />}

</Fragment>

)}

/>

)

}

{/* 授权、SQL弹窗 */}

<ModalView visible={visible} modalType={modalType} record={record} onCancel={this.closeModal} />

</Page>

);

}

}

export default Form.create()(ModelInterface);


本文链接: http://www.luyixian.cn/news_show_186363.aspx 

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

推荐阅读更多精彩内容