蓝鲸SaaS开发搭建Django+Vue前后端分离的开发框架

python manage.py migrate
python manage.py startapp task

获取用户名

#add redis for celery
redis==2.10.6
djangorestframework==3.11.0
Jinja2==2.11.2


    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': os.path.join(BASE_DIR, APP_CODE),
        }
    }
    login_user_data = client.bk_login.get_user({
        "bk_token": request.COOKIES.get("bk_token")
    })
    username = request.user.username
    if login_user_data['result']:
        username = login_user_data['data']['bk_username']
    sys_time = datetime.datetime.now()
    sys_time_str = sys_time.strftime('%Y-%m-%d %H:%M:%S')
   # python3 b64encode 需要转码
   data = client.job.fast_execute_script({
        "bk_biz_id": bk_biz_id,
        "task_name": task_name,
        "account": account,
        "script_content": str(base64.b64encode(script_content.encode('utf-8')), "utf-8"),
        "script_param": str(base64.b64encode(script_param.encode('utf-8')), "utf-8"),
        "script_type": script_type,
        "ip_list": ip_list,
    })
    ####
    job_detail = client.job.get_job_detail({
        'bk_biz_id': int(biz_id),
        'bk_job_id': int(job_id)
    })
    steps = []
    job_detail_steps = job_detail['data']['steps']
    i = 1
    for step in job_detail_steps:
        steps.append({"step_id": step['step_id'],
                      "script_param": str(base64.b64encode(key_word.encode('utf-8')), encoding='utf-8'),
                      "ip_list": [{"bk_cloud_id": 0, "ip": host_ip}]})
    job_log = client.job.execute_job({
        'bk_biz_id': int(biz_id),
        'bk_job_id': int(job_id),
        'steps': steps  # job_detail['data']['steps']
    })
    job_instance_id = job_log['data']['job_instance_id']


    ###
    log_info = client.job.get_job_instance_log({
        "bk_biz_id": bk_biz_id,
        "job_instance_id": job_instance_id
    })
    while not log_info['data'][0]["is_finished"]:
        # sleep(1)
        log_info = log_info = client.job.get_job_instance_log({
            "bk_biz_id": bk_biz_id,
            "job_instance_id": job_instance_id
        })
        if log_info['data'][0]["is_finished"]:
            return log_info
    return log_info

python celery note

@periodic_task(run_every=crontab(minute='*/1', hour='*', day_of_week="*", day_of_month='*', month_of_year='*'))
def task(**kwargs):
    pass

## 延迟执行
@task()
def start_task(client, to_user, key):
    pass
### call start task
start_task.apply_async(args=[client, to_user, key], eta=now + datetime.timedelta(seconds=10))
    
## create celery tasks with interval
    interval_schedule = {
        "every": 5,
        "period": 'seconds'
    }
    kwargs = dict(
        biz_id=biz_id,
        job_instance_id=job_instance_id,
    )
    interval = IntervalSchedule.objects.create(**interval_schedule)
    interval.save()
    now = datetime.datetime.now()
    task = PeriodicTask.objects.create(name='get_log_{}'.format(job_instance_id),
                                                       kwargs=json.dumps(kwargs),
                                                       interval=interval,
                                                       enabled=True,
                                                       expires=now + datetime.timedelta(minutes=1),
                                                       task="task.celery_tasks.get_instance_log")

django paginator 以及 serializers 使用

    qs = ScriptLog.objects.filter()
    page_num = request.GET.get('page')
    page_size = request.GET.get('page_size')
    paginator = Paginator(qs, page_size)  # 每页25条
    page = paginator.page(page_num)
    data = []
    obj_list = json.loads(serializers.serialize('json', page.object_list))
    for obj in obj_list:
        data.append(obj.get('fields'))

vue.config.js

var env = process.env.NODE_ENV
var isProduction = env === 'production'
let publicPath = '/'
if (isProduction) {
  publicPath = './static/build'
}

module.exports = {
  lintOnSave: 'error',
  publicPath: publicPath,
  indexPath: '../../templates/index.html',
  devServer: {
    proxy: 'http://127.0.0.1:8000',
    disableHostCheck: true,
    port: 8080
  }
}

pacakge.json   ../static/build

main.js


import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import axios from 'axios'

const http = axios.create({
  baseURL: process.env.NODE_ENV === 'production' ? window.site_url : '/',
  headers: { 'X-Requested-With': 'XMLHttpRequest' },
  xsrfCookieName: 'csrftoken',
  xsrfHeaderName: 'X-CSRFToken',
  withCredentials: true
})
Vue.prototype.$http = http
Vue.use(ElementUI);

index.html

<script>
    window.site_url = '{{ SITE_URL }}'
    window.username = '{{ USERNAME }}'
</script>

menu nav

    <div id="nav">
            <div class="logo-wrap">
                <img src="./assets/logo.png" alt="">
            </div>
            <div class="menu-wrap">
                <div class="menu-item">
                    <router-link to="/">进程查询</router-link>
                </div>
                <div class="menu-item">
                    <router-link to="/detail">查看详情</router-link>
                </div>
            </div>
            <div class="username-wrap">
                {{ username }}
            </div>
        </div>

json

{
    "module": "demo",
    "name": "snippet",
    "search_forms": [
          {"prop": "title", "label": "标题", "type": "input", "rules": [
              {"required": "true", "message": "请输入标题", "trigger": "blur"}
          ]},
    ],
    "forms": [
        {"prop": "title", "label": "标题", "type": "input", "rules": [
            {"required": "true", "message": "请输入标题", "trigger": "blur"}
        ]},
    ],
    "columns": [
        {"prop": "title", "label": "标题"}
    ]
}

data_list

<template>
    <div class="page-wrap">
        <div class="search-container">
            <el-form ref="searchForm" :rules="searchFormRule" :model="searchForm" label-position="left" label-width="180px">
                {% for formItem in searchForms %}
                 <el-form-item label="{{ formItem.label }}:"
                              prop="{{ formItem.prop }}">
                    {% if formItem.type == 'select' %}
                    <el-select v-model="searchForm.{{ formItem.prop }}" placeholder="请选择{{ formItem.label }}">
                        <el-option value="option1" label="选项1"></el-option>
                    </el-select>
                    {% endif %}
                    {% if formItem.type == 'input' %}
                    <el-input v-model="searchForm.{{ formItem.prop }}" placeholder="请输入{{ formItem.label }}"></el-input>
                    {% endif %}
                    {% if formItem.type == 'textarea' %}
                    <el-input type="textarea" :rows="3" v-model="searchForm.{{ formItem.prop }}" placeholder="请输入{{ formItem.label }}"></el-input>
                    {% endif %}
                    {% if formItem.type == 'datetime' %}
                    <el-date-picker type="datetime"
                                    placeholder="选择日期"
                                    value-format="timestamp"
                                    v-model="searchForm.{{ formItem.prop }}"></el-date-picker>
                    {% endif %}
                    {% if formItem.type == 'datetimerange' %}
                    <el-date-picker type="datetimerange"
                                    range-separator="至"
                                    start-placeholder="开始时间"
                                    end-placeholder="结束时间"
                                    value-format="timestamp"
                                    v-model="searchForm.{{ formItem.prop }}"></el-date-picker>
                    {% endif %}
                    {% if formItem.type == 'date' %}
                    <el-date-picker type="date"
                                    placeholder="选择日期"
                                    value-format="timestamp"
                                    v-model="searchForm.{{ formItem.prop }}"></el-date-picker>
                    {% endif %}
                    {% if formItem.type == 'daterange' %}
                    <el-date-picker type="daterange"
                                    range-separator="至"
                                    start-placeholder="开始日期"
                                    end-placeholder="结束日期"
                                    value-format="timestamp"
                                    v-model="searchForm.{{ formItem.prop }}"></el-date-picker>
                    {% endif %}
                    {% if formItem.type == 'time' %}
                    <el-time-picker placeholder="选择时间" v-model="searchForm.{{ formItem.prop }}"></el-time-picker>
                    {% endif %}
                    {% if formItem.type == 'timerange' %}
                    <el-time-picker is-range
                                    arrow-control
                                    range-separator="至"
                                    start-placeholder="开始时间"
                                    end-placeholder="结束时间"
                                    placeholder="选择时间范围"
                                    v-model="searchForm.{{ formItem.prop }}"></el-time-picker>
                    {% endif %}
                    {% if formItem.type == 'switch' %}
                    <el-switch v-model="searchForm.{{ formItem.prop }}"></el-switch>
                    {% endif %}
                </el-form-item>
                {% endfor %}
                <el-form-item>
                    <el-button type="primary" :disabled="loadingData" @click="onSearchSubmit('searchForm')">提交</el-button>
                    <el-button type="primary" @click="showCreate">创建</el-button>
                </el-form-item>
            </el-form>
        </div>
        <div class="result-container" v-loading="loadingData">
            <div class="result-title">列表</div>
            <el-table
                    :data="{{ name }}Data"
                    style="width: 100%"
                @selection-change="handleSelectionChange">
                <el-table-column
                  type="selection"
                  width="55">
                </el-table-column>
                <el-table-column
                        type="index"
                        :index="tableIndex"
                        label="序号"
                        width="55">
                </el-table-column>
                {% for col in tableColumns %}
                <el-table-column
                        prop="{{col.prop}}"
                        label="{{col.label}}">
                   <template slot-scope="scope">
                      <span>
                      {{ '{{' }}scope.row.{{col.prop}} || '--'{{ '}}' }}
                      </span>
                    </template>
                </el-table-column>
                {% endfor %}
                <el-table-column
                  fixed="right"
                  label="操作"
                  width="120">
                  <template slot-scope="scope">
                    <el-button
                      @click.native.prevent="edit{{name|capitalize}}(scope.row)"
                      type="text"
                      size="small">
                      编辑
                    </el-button>
                    <el-button
                      @click.native.prevent="delete{{name|capitalize}}(scope.row)"
                      type="text"
                      size="small">
                      删除
                    </el-button>
                  </template>
                </el-table-column>
            </el-table>
            <div class="page-container">
                <el-pagination
                        @size-change="handleSizeChange"
                        @current-change="handleCurrentChange"
                        :current-page="pageInfo.pageNum"
                        :page-sizes="[10, 20, 30]"
                        :page-size="pageInfo.pageSize"
                        layout="total, sizes, prev, pager, next, jumper"
                        :total="pageInfo.total">
                </el-pagination>
            </div>
        </div>
        <edit-{{name}} :show="dialog" :pk="pk" @on-updated="updated"></edit-{{name}}>
    </div>
</template>

<script>
    import Edit{{name|capitalize}} from "./components/Edit{{name|capitalize}}";

    export default {
        name: '{{name}}_page',
        components: {
          Edit{{name|capitalize}}
        },
        data() {
            return {
                saving: false,
                dialog: false,
                pk: null,
                multipleSelection: [],
                pageInfo: {
                    pageSize: 10,
                    pageNum: 1,
                    total: 0
                },
                {{ name }}Data: [],
                loadingData: false,
                searchForm: {
                {% for form in searchForms %}
                    {{ form.prop }} :  undefined,
                {% endfor %}
                },
                searchFormRule: {
                {% for form in searchForms %}
                    {{ form.prop }} : {{ form.rules }},
                {% endfor %}
                }
            }
        },
        created() {
            this.initData()
        },
        methods: {
            updated() {
                this.dialog = false
                this.getSnippetData()
            },
            showCreate() {
                this.dialog = true
            },
            edit{{name|capitalize}}(item) {
                this.dialog = true
                this.pk = item.id
            },
            tableIndex(index) {
              return (this.pageInfo.pageNum -1) * this.pageInfo.pageSize + index +1
            },
            handleSelectionChange(val) {
                this.multipleSelection = val;
                console.log('>> multipleSelection: ' + val)
            },
            delete{{name|capitalize}}(item){
                this.$confirm('此操作将永久删除该项, 是否继续?', '提示', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    type: 'warning'
                }).then(async () => {
                    const resp = await this.$http.delete(`{{ module }}/{{name}}/${item.id}`)
                    if(resp.data.result) {
                        this.get{{name|capitalize}}Data()
                        this.$message({
                            type:'success',
                            message: '删除成功'
                        })
                    }
                }).catch(() => {
                    this.$message({
                        type: 'info',
                        message: '已取消删除'
                    });
                });

            },

            async initData() {
                this.get{{ name | capitalize }}Data()
            },
            async get{{ name | capitalize }}Data() {
                this.loadingData = true
                const params = {
                    page: this.pageInfo.pageNum,
                    page_size: this.pageInfo.pageSize,
                {% for form in searchForms %}
                    {{ form.prop }} : this.searchForm.{{ form.prop }},
                {% endfor %}
                }
                const resp = await this.$http.get('{{ module }}/{{name}}', {params})
                this.loadingData = false
                if (resp.data.result) {
                    this.pageInfo.total = resp.data.count
                    this.{{ name }}Data = resp.data.data
                }
            },
            handleSizeChange (val) {
              this.pageInfo.pageSize = val
              this.pageInfo.pageNum = 1
              this.get{{ name | capitalize }}Data()
            },
            handleCurrentChange (val) {
              this.pageInfo.pageNum = val
              this.get{{ name | capitalize }}Data()
            },
            onSearchSubmit(formName) {
                this.$refs[formName].validate((valid) => {
                    if (valid) {
                        this.get{{ name | capitalize }}Data()
                    } else {
                        return false;
                    }
                });
            },
            resetForm(formName) {
                this.$refs[formName].resetFields();
            }
        }
    }
</script>
<style lang="scss">
    .page-wrap {
        .result-title {
            background: #e7e7e7;
            height: 48px;
            line-height: 48px;
            padding: 0 16px;
            text-align: left;
            font-size: 16px;
        }
        .page-container{
            padding-top: 8px;
        }
    }
</style>

edit

<template>
    <div class="component-wrap">
        <el-drawer
                :with-header="false"
                :before-close="handleClose"
                :show-close="false"
                :visible.sync="show"
                size="46%"
                direction="rtl"
                custom-class="demo-drawer"
                ref="drawer"
        >
            <div class="demo-drawer__title">
                编辑{{name|capitalize}}
            </div>
            <div class="demo-drawer__content">
                <el-form ref="snippetForm" :rules="{{name}}FormRule" :model="{{name}}Form" label-position="left" label-width="120px">
                    {% for formItem in forms %}
                    <el-form-item label="{{ formItem.label }}:"
                                  prop="{{ formItem.prop }}">
                        {% if formItem.type == 'select' %}
                        <el-select v-model="{{name}}Form.{{ formItem.prop }}" placeholder="请选择{{ formItem.label }}">
                            <el-option value="option1" label="选项1"></el-option>
                        </el-select>
                        {% endif %}
                        {% if formItem.type == 'input' %}
                        <el-input v-model="{{name}}Form.{{ formItem.prop }}" placeholder="请输入{{ formItem.label }}"></el-input>
                        {% endif %}
                        {% if formItem.type == 'textarea' %}
                        <el-input type="textarea" :rows="3" v-model="{{name}}Form.{{ formItem.prop }}" placeholder="请输入{{ formItem.label }}"></el-input>
                        {% endif %}
                        {% if formItem.type == 'datetime' %}
                        <el-date-picker type="datetime"
                                        placeholder="选择日期"
                                        value-format="timestamp"
                                        v-model="{{name}}Form.{{ formItem.prop }}"></el-date-picker>
                        {% endif %}
                        {% if formItem.type == 'datetimerange' %}
                        <el-date-picker type="datetimerange"
                                        range-separator="至"
                                        start-placeholder="开始时间"
                                        end-placeholder="结束时间"
                                        value-format="timestamp"
                                        v-model="{{name}}Form.{{ formItem.prop }}"></el-date-picker>
                        {% endif %}
                        {% if formItem.type == 'date' %}
                        <el-date-picker type="date"
                                        placeholder="选择日期"
                                        value-format="timestamp"
                                        v-model="{{name}}Form.{{ formItem.prop }}"></el-date-picker>
                        {% endif %}
                        {% if formItem.type == 'daterange' %}
                        <el-date-picker type="daterange"
                                        range-separator="至"
                                        start-placeholder="开始日期"
                                        end-placeholder="结束日期"
                                        value-format="timestamp"
                                        v-model="{{name}}Form.{{ formItem.prop }}"></el-date-picker>
                        {% endif %}
                        {% if formItem.type == 'time' %}
                        <el-time-picker placeholder="选择时间" v-model="{{name}}Form.{{ formItem.prop }}"></el-time-picker>
                        {% endif %}
                        {% if formItem.type == 'timerange' %}
                        <el-time-picker is-range
                                        arrow-control
                                        range-separator="至"
                                        start-placeholder="开始时间"
                                        end-placeholder="结束时间"
                                        placeholder="选择时间范围"
                                        v-model="{{name}}Form.{{ formItem.prop }}"></el-time-picker>
                        {% endif %}
                        {% if formItem.type == 'switch' %}
                        <el-switch v-model="{{name}}Form.{{ formItem.prop }}"></el-switch>
                        {% endif %}
                    </el-form-item>
                    {% endfor %}
                </el-form>
                <div class="demo-drawer__footer">
                    <el-button type="primary" @click="$refs.drawer.closeDrawer()" :loading="saving">
                        <span v-if="saving">提交中...</span>
                        <span v-else>确定</span>
                    </el-button>
                    <el-button @click="cancelForm">取 消</el-button>
                </div>
            </div>
        </el-drawer>
    </div>
</template>

<script>
    export default {
        name: "Edit{{name|capitalize}}",
        props: {
            show: {
                type: Boolean,
                default: false
            },
            pk: {
                default: null
            }
        },
        data() {
            return {
                saving: false,
                {{name}}Form: {
                {% for form in forms %}
                    {{ form.prop }} :  undefined,
                {% endfor %}
                },
                {{name}}FormRule: {
                {% for form in forms %}
                    {{ form.prop }} : {{ form.rules }},
                {% endfor %}
                }
            }
        },
        methods: {

            handleClose() {
                if (this.saving) {
                    return;
                }
                this.$refs['{{name}}Form'].validate((valid) => {
                    if (valid) {
                        this.$confirm('确定要提交表单吗?').then(async () => {
                            const resp = await this.$http.post('{{module}}/{{name}}/', this.{{name}}Form)
                            if (resp.data.result) {
                                this.saving = true;
                                this.$message({
                                    type: 'success',
                                    message: `操作成功`
                                })
                                this.$emit('on-updated')
                            }
                        })
                    } else {
                        console.log('error submit!!');
                        return false;
                    }
                });
            },
            cancelForm() {
                this.saving = false;
                this.$emit('on-updated')
            },
        }

    }
</script>

<style scoped>

</style>

viewset

# -*- coding: utf-8 -*-
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response
from blueapps.utils.logger import logger
from config.default import PROJECT_CONFIG
from {{ app_name }}.models import {{ name }}
from {{ app_name }}.serializers import {{ name }}Serializer


class {{ name }}ViewSet(viewsets.ModelViewSet):
    """
    此视图自动提供`list`,`create`,`retrieve`,`update`和`destroy`操作。

    另外我们还提供了一个额外的`execute`操作。
    """
    # queryset = {{ name }}.objects.all()
    serializer_class = {{ name }}Serializer

    @action(methods=['get'], detail=False)
    def execute(self, request, *args, **kwargs):
        logger.info('>>> execute start ')
        result = {"result": True}
        return Response(result)

    def list(self, request, *args, **kwargs):
        logger.info('>>>> {{ name }}ViewSet list')
        page_queryset = {{ name }}.objects.filter()
        page_size = PROJECT_CONFIG['PAGE_SIZE']
        if request.query_params.get("page_size"):
            page_size = int(request.query_params.get("page_size"))
        # 实例化产生一个加密分页对象
        pagination = PageNumberPagination()
        pagination.page_size = page_size  # 每页显示的个数
        pagination.max_page_size = 50  # 每页最多显示多少条
        page_list = pagination.paginate_queryset(page_queryset, request)
        ser = {{ name }}Serializer(instance=page_list, many=True)
        result = {"result": True,
                  'count': pagination.page.paginator.count,
                  'data': ser.data}
        return Response(result)

    def create(self, request, *args, **kwargs):
        logger.info('>>>> {{ name }}ViewSet create')
        ser = {{ name }}Serializer(data=request.data)
        if ser.is_valid():
            ser.save()
            result = {"result": True, 'data': ser.data}
            return Response(result)
        result = {"result": False}
        return Response(result)

    def retrieve(self, request, pk=None, **kwargs):
        logger.info('>>> {{ name }}ViewSet retrieve by pk = {} '.format(pk))
        obj ={{ name }}.objects.get(pk=pk)
        ser ={{ name }}Serializer(instance=obj)
        result = {"result": True, 'data': ser.data}
        return Response(result)

    def update(self, request, pk=None, **kwargs):
        logger.info('>>>> update')
        result = {"result": True}
        obj ={{ name }}.objects.get(pk=pk)
        ser ={{ name }}Serializer(instance=obj)
        ser.is_valid(raise_exception=True)
        ser.save()
        return Response(result)

    def destroy(self, request, pk=None, **kwargs):
        logger.info('>>>> {{ name }}ViewSet update pk {pk}'.format(pk=pk))
        obj ={{ name }}.objects.get(pk=pk)
        ser ={{ name }}Serializer(instance=obj)
        obj.delete()
        result = {"result": True, 'data': ser.data}
        return Response(result)

ggg templates

# -*- coding: utf-8 -*-
import json
import os
import re

from jinja2 import Environment, PackageLoader

from config import BASE_DIR


def get_jinjia_env():
    env = Environment(loader=PackageLoader('common.generator'))
    return env

def get_json_obj(config_file):
    with open('./config/{json_file}'.format(json_file=config_file), 'r', encoding='utf-8') as f:
        json_data = f.read()
        json_obj = json.loads(json_data)
    return json_obj

def gen_vue_file(config_file, override=False):
    json_obj = get_json_obj(config_file)
    template = get_jinjia_env().get_template('data_list.j2')
    template_form = get_jinjia_env().get_template('edit_form.j2')
    gen_vue_comp(json_obj, override=override, template=template)
    gen_vue_comp(json_obj, override=override, template=template_form, is_edit=True)


def gen_vue_comp(json_obj, override, template, is_edit=False):
    searchForms = json_obj['search_forms']
    forms = json_obj['forms']
    tableColumns = json_obj['columns']
    module = json_obj['module']
    name = json_obj['name']
    content = template.render(module=module,
                              name=name,
                              searchForms=searchForms,
                              forms=forms,
                              tableColumns=tableColumns)
    blank_line_re = re.compile('\\s+\\n')
    content = blank_line_re.sub('\n', content)
    folder = os.path.join(BASE_DIR, 'vue_app') + '/src/views/{module}'.format(module=module)
    if is_edit:
        folder = os.path.join(BASE_DIR, 'vue_app') + '/src/views/{module}/components'.format(module=module)
    if not os.path.exists(folder):
        os.makedirs(name=folder)
    file_path = '{folder}/{name}.vue'.format(folder=folder, name=name)
    if is_edit:
        file_path = '{folder}/Edit{name}.vue'.format(folder=folder, name=name.capitalize())
    if override:
        with open(file_path, 'w', encoding='utf-8') as fp:
            fp.write(content)
        print('>>> gen vue success!!!')
    else:
        print('>>> file already exists, you can pass extra arg: override = True, to override exists file...')


def gen_view_set(app_name, name, override=False):
    template = get_jinjia_env().get_template('SampleViewSet.j2')
    content = template.render(app_name=app_name, name=name)
    folder = os.path.join(BASE_DIR, app_name) + '/views'
    file_path = '{folder}/{name}ViewSet.py'.format(folder=folder, name=name)
    if not os.path.exists(folder):
        os.makedirs(name=folder)
    if override:
        with open(file_path, 'w', encoding='utf-8') as fp:
            fp.write(content)
        print('>>> gen view set success!!!')
    else:
        print('>>> file already exists, you can pass extra arg: override = True, to override exists file...')


urls

# -*- coding: utf-8 -*-

from django.conf.urls import url
from django.urls import include
from rest_framework.routers import DefaultRouter

from .views import views
from .views.BogViewSet import BLogViewSet

router = DefaultRouter()
router.register(r'blog', BLogViewSet, basename='blog')

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