无标题文章

BlogVue

创建新项目

npm create vite

基于Vue3、Vite4、TypeScript

#安装依赖包

npm i

类型声明

TypeScript类型检查和自动补全功能,以增加代码的可读性和可维护性

vite-env.d.ts文件

/// <reference types="vite/client" />

declare module '*.vue' {

   import  { DefineComponent } from 'vue'

   const component: DefineComponent<{}, {}, any>

   export default component

}

有了上述文件 TypeScript 就能够正确地识别和检查 Vue.js 组件的 props、事件和组件实例等类型信息。

配置解析路径

配置模块路径别名

安装@types/node作为开发者依赖关系它是 Node.js 官方发布的类型声明文件,包含了 Node.js 标准库和常用模块的类型声明

npm install @types/node --save-dev

#实现方法

import path from 'path'

export const getRootPath = () => {

   return path.resolve(process.cwd())

}

export  const getSrcPath = (srcName = 'src') => {

   return path.resolve(getRootPath(), srcName)

}

vite.config.ts文件配置模块路径别名

   resolve: {

       alias: {

           '@': getSrcPath(),

           '~': getRootPath()

       }

   },

解析路径

tsconfig.json文件中 在compilerOptions对象加入

   "baseUrl": "./",  //指定了解析非相对路径模块时使用的基本目录路径

   "paths": {  //将路径缩写映射为具体的路径

     "@/*": ["src/*"],

     "~/*": ["./*"]

   },

安装Tailwind CSS框架

安装 Tailwind 以及其它依赖项:

npm install -D tailwindcss@latest postcss@latest autoprefixer@latest

创建配置文件

npx tailwindcss init -p

tailwind.config.js

/** @type {import('tailwindcss').Config} */

export default {

  content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],  //制定优化性能,扫描文件提取样式

  darkMode: 'class',  //class手动  media跟随浏览器

  theme: {  //用于指定自定义主题

   extend: {},

  },

  plugins: [], //用于指定一些插件

}

引入Tailwind

自定义一个样式文件

@tailwind base;

@tailwind components;

@tailwind utilities;

在main.ts引入

安装NaiveUI 前端框架

npm i -D naive-ui

全局引入NaiveUI

在main.ts引入

import naive from 'naive-ui'

app.use(naive)

NaiveUI全局挂载组件

挂载

组件包括 对话框、消息框,方便使用

在App.vue中包裹。

示例:

<template>

   <n-config-provider :theme="appStore.theme==='dark' ? darkTheme : undefined" :locale="locale" class="h-full">

       <n-loading-bar-provider>

           <n-message-provider>

               <n-dialog-provider>

                   <n-notification-provider>

                       <NaiveProviderContent></NaiveProviderContent>

                       <router-view></router-view>

                   </n-notification-provider>

               </n-dialog-provider>

           </n-message-provider>

       </n-loading-bar-provider>

   </n-config-provider>

</template>

<script setup lang="ts">

import {useDialog, useLoadingBar, useMessage, useNotification} from "naive-ui";

import {defineComponent, h, ref} from "vue";

import {darkTheme, zhCN} from 'naive-ui'

import {useAppStore} from "@/store";

const appStore = useAppStore()

const locale = ref(zhCN)

//定义新组建 实现挂载

const NaiveProviderContent = defineComponent({

   setup() {

       window.$message = useMessage();

       window.$dialog = useDialog();

       window.$notification = useNotification()

       window.$loadingBar = useLoadingBar()

   },

   render() {

       return h('div')

   },

})

</script>

<style scoped>

</style>

在模板中定义了一个名为 NaiveProviderContent 的组件,并在其中使用了 useDialog、useLoadingBar、useMessage 和 useNotification 四个 hook。

这四个 hook 返回了 Dialog、LoadingBar、Message 和 Notification 组件的实例,可以通过将其挂载在全局的 window 对象上,在全局范围内使用。

同时修改了 NaiveUI 的用户的语言环境为中文

类型声明

创建一个类型声明文件。只要是.d.ts结尾文件都可以

声明全局变量 $message、$dialog、$notification 和 $loadingBar 的类型

在声明这些全局变量之后,就可以在项目中直接使用它们,而无需在每个需要使用它们的文件中都进行导入。

import {MessageApiInjection} from "naive-ui/es/message/src/MessageProvider";

import {DialogApiInjection} from "naive-ui/es/dialog/src/DialogProvider";

import {NotificationApiInjection} from "naive-ui/es/notification/src/NotificationProvider";

import {LoadingBarApiInjection} from "naive-ui/es/loading-bar/src/LoadingBarProvider";

/**

* ts 添加定义 识别

*/

declare global{

   interface Window{

       $message:MessageApiInjection,

       $dialog:DialogApiInjection,

       $notification:NotificationApiInjection

       $loadingBar:LoadingBarApiInjection

   }

}

安装状态管理Pinia及持久化插件pinia-plugin-persistedstate

npm i pinia

npm i pinia-plugin-persistedstate

引入pinia及插件

在main.ts

import {createPinia} from "pinia";

import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

const pinia = createPinia()

pinia.use(piniaPluginPersistedstate)

app.use(pinia)

创建相应store

export const useAppStore = defineStore('app', {

   persist: true, //使用持久化插件

   state: () => {   //是一个函数,返回一个对象,用于存储状态

       return {

           collapsed: true,

           theme: 'dark',

       }

   },

   getters: {},  //用于存储计算属性

   actions: {  //用于封装业务逻辑

       switchCollapsed() {

           this.collapsed = !this.collapsed

       },

       switchTheme() {

           if (this.theme === 'light') this.theme = 'dark'

           else this.theme = 'light'

       }

   },

})

安装axios

npm i axios

请求拦截器

//设置请求拦截器

axios.interceptors.request.use((config) => {

   // 携带上token

   let token = userStore.token

   token && (config.headers.Authorization = token)

   return config

}, error => {

   return Promise.reject(error)

})

响应拦截器

//响应拦截器

axios.interceptors.response.use(

   (response) => {

       //未登录

       if(response.data.code===405){

           router.push({

               path:'/auth'

           })

       }

       if (response.data.code !== 0) {

           window.$message.error(response.data.msg)

           return Promise.reject(response.data.msg); // 返回拒绝状态的 Promise 对象,将错误信息传递给后续的 Promise 处理函数

       }

       window.$message.success(response.data.msg)

       return response;

   }, (error => {

       // 请求错误时做些事

       let res = "";

       if (error.request) {

           res = error.request;

       } else if (error.response) {

           res = error.response;

       }

       if (res) {

           //@ts-ignore

           const data = JSON.parse(res.response)

           window.$message.error(data.msg)

           return Promise.reject(data.msg); // 返回拒绝状态的 Promise 对象,将错误信息传递给后续的 Promise 处理函数

       } else {

           window.$message.error(`链接服务器失败`)

           return Promise.reject(error); // 返回拒绝状态的 Promise 对象,将错误信息传递给后续的 Promise 处理函数

       }

   })

)

安装vue-router

npm i vue-router

创建router文件

import {createRouter, createWebHistory} from "vue-router";

const routes = [

       path: '/',

       name: 'redis',

       component: () => import('@/layout/admin/index.vue'),

]

const routerOptions = {

   history: createWebHistory('/redis'),

   routes: routes,

}

const router = createRouter(routerOptions)

export default router

在main.ts文件引入

import router from "@/router";

app.use(router)

安装 jsencrypt

对数据进行加密解密

npm i jsencrypt

BlogAPI

数据库设计

-- 用户表

CREATETABLE`blog_user`(

`id`INT(11)NOTNULLAUTO_INCREMENTCOMMENT'主键',

`username`VARCHAR(50)NOTNULLCOMMENT'用户名',

`password`VARCHAR(255)NOTNULLCOMMENT'密码',

`email`VARCHAR(50)NOTNULLCOMMENT'电子邮件',

`role`VARCHAR(20)NOTNULLCOMMENT'角色',

`avatar`VARCHAR(255)NULLCOMMENT'头像地址',

`created_at`TIMESTAMPNOTNULLDEFAULTCURRENT_TIMESTAMPCOMMENT'创建时间',

PRIMARYKEY(`id`)

)ENGINE=INNODBDEFAULTCHARSET=utf8COMMENT='用户表';

-- 文章表

CREATETABLE`blog_post`(

`id`INT(11)NOTNULLAUTO_INCREMENTCOMMENT'主键',

`title`VARCHAR(255)NOTNULLCOMMENT'文章标题',

`content`TEXTNOTNULLCOMMENT'文章内容',

`user_id`INT(11)NOTNULLCOMMENT'作者id',

`category_id`INT(11)NOTNULLCOMMENT'分类id',

`created_at`TIMESTAMPNOTNULLDEFAULTCURRENT_TIMESTAMPCOMMENT'创建时间',

PRIMARYKEY(`id`),

FOREIGNKEY(`user_id`)REFERENCES`blog_user`(`id`),

FOREIGNKEY(`category_id`)REFERENCES`blog_category`(`id`)

)ENGINE=INNODBDEFAULTCHARSET=utf8COMMENT='文章表';

-- 分类表

CREATETABLE`blog_category`(

`id`INT(11)NOTNULLAUTO_INCREMENTCOMMENT'主键',

`name`VARCHAR(100)NOTNULLCOMMENT'分类名称',

`created_at`TIMESTAMPNOTNULLDEFAULTCURRENT_TIMESTAMPCOMMENT'创建时间',

PRIMARYKEY(`id`)

)ENGINE=INNODBDEFAULTCHARSET=utf8COMMENT='分类表';

-- 评论表

CREATETABLE`blog_comment`(

`id`INT(11)NOTNULLAUTO_INCREMENTCOMMENT'主键',

`content`TEXTNOTNULLCOMMENT'评论内容',

`user_id`INT(11)NOTNULLCOMMENT'评论者id',

`post_id`INT(11)NOTNULLCOMMENT'文章id',

`parent_id`INT(11)DEFAULTNULLCOMMENT'父级评论id,表示当前评论是对哪个评论的回复。如果不是回复,则为null',

`reply_to`INT(11)DEFAULTNULLCOMMENT'回复到哪条评论,表示该回复是针对哪个用户的回复。如果不是回复,为null',

`created_at`TIMESTAMPNOTNULLDEFAULTCURRENT_TIMESTAMPCOMMENT'创建时间',

PRIMARYKEY(`id`),

FOREIGNKEY(`user_id`)REFERENCES`blog_user`(`id`),

FOREIGNKEY(`post_id`)REFERENCES`blog_post`(`id`),

FOREIGNKEY(`parent_id`)REFERENCES`blog_comment`(`id`),

FOREIGNKEY(`reply_to`)REFERENCES`blog_user`(`id`)

)ENGINE=INNODBDEFAULTCHARSET=utf8COMMENT='评论表';

CREATETABLE`blog_reply`(

`id`INT(11)NOTNULLAUTO_INCREMENTCOMMENT'主键',

`content`TEXTNOTNULLCOMMENT'回复内容',

`user_id`INT(11)NOTNULLCOMMENT'回复者id',

`comment_id`INT(11)NOTNULLCOMMENT'评论id,表示回复是哪条评论的回复',

`parent_id`INT(11)DEFAULTNULLCOMMENT'父级回复id,表示当前回复是对哪个回复的回复。如果不是回复,则为null',

`reply_to`INT(11)DEFAULTNULLCOMMENT'回复到哪条评论,表示该回复是针对哪个用户的回复。如果不是回复,为null',

`created_at`TIMESTAMPNOTNULLDEFAULTCURRENT_TIMESTAMPCOMMENT'创建时间',

PRIMARYKEY(`id`),

FOREIGNKEY(`user_id`)REFERENCES`blog_user`(`id`),

FOREIGNKEY(`comment_id`)REFERENCES`blog_comment`(`id`),

FOREIGNKEY(`parent_id`)REFERENCES`blog_reply`(`id`),

FOREIGNKEY(`reply_to`)REFERENCES`blog_user`(`id`)

)ENGINE=INNODBDEFAULTCHARSET=utf8COMMENT='回复表';

创建新项目

npm create vite

基于Vue3、Vite4、TypeScript

#安装依赖包

npm i

类型声明

TypeScript类型检查和自动补全功能,以增加代码的可读性和可维护性

vite-env.d.ts文件

/// <reference types="vite/client" />

declare module '*.vue' {

   import  { DefineComponent } from 'vue'

   const component: DefineComponent<{}, {}, any>

   export default component

}

有了上述文件 TypeScript 就能够正确地识别和检查 Vue.js 组件的 props、事件和组件实例等类型信息。

配置解析路径

配置模块路径别名

安装@types/node作为开发者依赖关系它是 Node.js 官方发布的类型声明文件,包含了 Node.js 标准库和常用模块的类型声明

npm install @types/node --save-dev

#实现方法

import path from 'path'

export const getRootPath = () => {

   return path.resolve(process.cwd())

}

export  const getSrcPath = (srcName = 'src') => {

   return path.resolve(getRootPath(), srcName)

}

vite.config.ts文件配置模块路径别名

   resolve: {

       alias: {

           '@': getSrcPath(),

           '~': getRootPath()

       }

   },

解析路径

tsconfig.json文件中 在compilerOptions对象加入

   "baseUrl": "./",  //指定了解析非相对路径模块时使用的基本目录路径

   "paths": {  //将路径缩写映射为具体的路径

     "@/*": ["src/*"],

     "~/*": ["./*"]

   },

安装Tailwind CSS框架

安装 Tailwind 以及其它依赖项:

npm install -D tailwindcss@latest postcss@latest autoprefixer@latest

创建配置文件

npx tailwindcss init -p

tailwind.config.js

/** @type {import('tailwindcss').Config} */

export default {

  content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],  //制定优化性能,扫描文件提取样式

  darkMode: 'class',  //class手动  media跟随浏览器

  theme: {  //用于指定自定义主题

   extend: {},

  },

  plugins: [], //用于指定一些插件

}

引入Tailwind

自定义一个样式文件

@tailwind base;

@tailwind components;

@tailwind utilities;

在main.ts引入

安装NaiveUI 前端框架

npm i -D naive-ui

全局引入NaiveUI

在main.ts引入

import naive from 'naive-ui'

app.use(naive)

NaiveUI全局挂载组件

挂载

组件包括 对话框、消息框,方便使用

在App.vue中包裹。

示例:

<template>

   <n-config-provider :theme="appStore.theme==='dark' ? darkTheme : undefined" :locale="locale" class="h-full">

       <n-loading-bar-provider>

           <n-message-provider>

               <n-dialog-provider>

                   <n-notification-provider>

                       <NaiveProviderContent></NaiveProviderContent>

                       <router-view></router-view>

                   </n-notification-provider>

               </n-dialog-provider>

           </n-message-provider>

       </n-loading-bar-provider>

   </n-config-provider>

</template>

<script setup lang="ts">

import {useDialog, useLoadingBar, useMessage, useNotification} from "naive-ui";

import {defineComponent, h, ref} from "vue";

import {darkTheme, zhCN} from 'naive-ui'

import {useAppStore} from "@/store";

const appStore = useAppStore()

const locale = ref(zhCN)

//定义新组建 实现挂载

const NaiveProviderContent = defineComponent({

   setup() {

       window.$message = useMessage();

       window.$dialog = useDialog();

       window.$notification = useNotification()

       window.$loadingBar = useLoadingBar()

   },

   render() {

       return h('div')

   },

})

</script>

<style scoped>

</style>

在模板中定义了一个名为 NaiveProviderContent 的组件,并在其中使用了 useDialog、useLoadingBar、useMessage 和 useNotification 四个 hook。

这四个 hook 返回了 Dialog、LoadingBar、Message 和 Notification 组件的实例,可以通过将其挂载在全局的 window 对象上,在全局范围内使用。

同时修改了 NaiveUI 的用户的语言环境为中文

类型声明

创建一个类型声明文件。只要是.d.ts结尾文件都可以

声明全局变量 $message、$dialog、$notification 和 $loadingBar 的类型

在声明这些全局变量之后,就可以在项目中直接使用它们,而无需在每个需要使用它们的文件中都进行导入。

import {MessageApiInjection} from "naive-ui/es/message/src/MessageProvider";

import {DialogApiInjection} from "naive-ui/es/dialog/src/DialogProvider";

import {NotificationApiInjection} from "naive-ui/es/notification/src/NotificationProvider";

import {LoadingBarApiInjection} from "naive-ui/es/loading-bar/src/LoadingBarProvider";

/**

* ts 添加定义 识别

*/

declare global{

   interface Window{

       $message:MessageApiInjection,

       $dialog:DialogApiInjection,

       $notification:NotificationApiInjection

       $loadingBar:LoadingBarApiInjection

   }

}

安装状态管理Pinia及持久化插件pinia-plugin-persistedstate

npm i pinia

npm i pinia-plugin-persistedstate

引入pinia及插件

在main.ts

import {createPinia} from "pinia";

import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

const pinia = createPinia()

pinia.use(piniaPluginPersistedstate)

app.use(pinia)

创建相应store

export const useAppStore = defineStore('app', {

   persist: true, //使用持久化插件

   state: () => {   //是一个函数,返回一个对象,用于存储状态

       return {

           collapsed: true,

           theme: 'dark',

       }

   },

   getters: {},  //用于存储计算属性

   actions: {  //用于封装业务逻辑

       switchCollapsed() {

           this.collapsed = !this.collapsed

       },

       switchTheme() {

           if (this.theme === 'light') this.theme = 'dark'

           else this.theme = 'light'

       }

   },

})

安装axios

npm i axios

请求拦截器

//设置请求拦截器

axios.interceptors.request.use((config) => {

   // 携带上token

   let token = userStore.token

   token && (config.headers.Authorization = token)

   return config

}, error => {

   return Promise.reject(error)

})

响应拦截器

//响应拦截器

axios.interceptors.response.use(

   (response) => {

       //未登录

       if(response.data.code===405){

           router.push({

               path:'/auth'

           })

       }

       if (response.data.code !== 0) {

           window.$message.error(response.data.msg)

           return Promise.reject(response.data.msg); // 返回拒绝状态的 Promise 对象,将错误信息传递给后续的 Promise 处理函数

       }

       window.$message.success(response.data.msg)

       return response;

   }, (error => {

       // 请求错误时做些事

       let res = "";

       if (error.request) {

           res = error.request;

       } else if (error.response) {

           res = error.response;

       }

       if (res) {

           //@ts-ignore

           const data = JSON.parse(res.response)

           window.$message.error(data.msg)

           return Promise.reject(data.msg); // 返回拒绝状态的 Promise 对象,将错误信息传递给后续的 Promise 处理函数

       } else {

           window.$message.error(`链接服务器失败`)

           return Promise.reject(error); // 返回拒绝状态的 Promise 对象,将错误信息传递给后续的 Promise 处理函数

       }

   })

)

安装vue-router

npm i vue-router

创建router文件

import {createRouter, createWebHistory} from "vue-router";

const routes = [

       path: '/',

       name: 'redis',

       component: () => import('@/layout/admin/index.vue'),

]

const routerOptions = {

   history: createWebHistory('/redis'),

   routes: routes,

}

const router = createRouter(routerOptions)

export default router

在main.ts文件引入

import router from "@/router";

app.use(router)

安装 jsencrypt

对数据进行加密解密

npm i jsencrypt

BlogAPI

数据库设计

-- 用户表

CREATETABLE`blog_user`(

`id`INT(11)NOTNULLAUTO_INCREMENTCOMMENT'主键',

`username`VARCHAR(50)NOTNULLCOMMENT'用户名',

`password`VARCHAR(255)NOTNULLCOMMENT'密码',

`email`VARCHAR(50)NOTNULLCOMMENT'电子邮件',

`role`VARCHAR(20)NOTNULLCOMMENT'角色',

`avatar`VARCHAR(255)NULLCOMMENT'头像地址',

`created_at`TIMESTAMPNOTNULLDEFAULTCURRENT_TIMESTAMPCOMMENT'创建时间',

PRIMARYKEY(`id`)

)ENGINE=INNODBDEFAULTCHARSET=utf8COMMENT='用户表';

-- 文章表

CREATETABLE`blog_post`(

`id`INT(11)NOTNULLAUTO_INCREMENTCOMMENT'主键',

`title`VARCHAR(255)NOTNULLCOMMENT'文章标题',

`content`TEXTNOTNULLCOMMENT'文章内容',

`user_id`INT(11)NOTNULLCOMMENT'作者id',

`category_id`INT(11)NOTNULLCOMMENT'分类id',

`created_at`TIMESTAMPNOTNULLDEFAULTCURRENT_TIMESTAMPCOMMENT'创建时间',

PRIMARYKEY(`id`),

FOREIGNKEY(`user_id`)REFERENCES`blog_user`(`id`),

FOREIGNKEY(`category_id`)REFERENCES`blog_category`(`id`)

)ENGINE=INNODBDEFAULTCHARSET=utf8COMMENT='文章表';

-- 分类表

CREATETABLE`blog_category`(

`id`INT(11)NOTNULLAUTO_INCREMENTCOMMENT'主键',

`name`VARCHAR(100)NOTNULLCOMMENT'分类名称',

`created_at`TIMESTAMPNOTNULLDEFAULTCURRENT_TIMESTAMPCOMMENT'创建时间',

PRIMARYKEY(`id`)

)ENGINE=INNODBDEFAULTCHARSET=utf8COMMENT='分类表';

-- 评论表

CREATETABLE`blog_comment`(

`id`INT(11)NOTNULLAUTO_INCREMENTCOMMENT'主键',

`content`TEXTNOTNULLCOMMENT'评论内容',

`user_id`INT(11)NOTNULLCOMMENT'评论者id',

`post_id`INT(11)NOTNULLCOMMENT'文章id',

`parent_id`INT(11)DEFAULTNULLCOMMENT'父级评论id,表示当前评论是对哪个评论的回复。如果不是回复,则为null',

`reply_to`INT(11)DEFAULTNULLCOMMENT'回复到哪条评论,表示该回复是针对哪个用户的回复。如果不是回复,为null',

`created_at`TIMESTAMPNOTNULLDEFAULTCURRENT_TIMESTAMPCOMMENT'创建时间',

PRIMARYKEY(`id`),

FOREIGNKEY(`user_id`)REFERENCES`blog_user`(`id`),

FOREIGNKEY(`post_id`)REFERENCES`blog_post`(`id`),

FOREIGNKEY(`parent_id`)REFERENCES`blog_comment`(`id`),

FOREIGNKEY(`reply_to`)REFERENCES`blog_user`(`id`)

)ENGINE=INNODBDEFAULTCHARSET=utf8COMMENT='评论表';

CREATETABLE`blog_reply`(

`id`INT(11)NOTNULLAUTO_INCREMENTCOMMENT'主键',

`content`TEXTNOTNULLCOMMENT'回复内容',

`user_id`INT(11)NOTNULLCOMMENT'回复者id',

`comment_id`INT(11)NOTNULLCOMMENT'评论id,表示回复是哪条评论的回复',

`parent_id`INT(11)DEFAULTNULLCOMMENT'父级回复id,表示当前回复是对哪个回复的回复。如果不是回复,则为null',

`reply_to`INT(11)DEFAULTNULLCOMMENT'回复到哪条评论,表示该回复是针对哪个用户的回复。如果不是回复,为null',

`created_at`TIMESTAMPNOTNULLDEFAULTCURRENT_TIMESTAMPCOMMENT'创建时间',

PRIMARYKEY(`id`),

FOREIGNKEY(`user_id`)REFERENCES`blog_user`(`id`),

FOREIGNKEY(`comment_id`)REFERENCES`blog_comment`(`id`),

FOREIGNKEY(`parent_id`)REFERENCES`blog_reply`(`id`),

FOREIGNKEY(`reply_to`)REFERENCES`blog_user`(`id`)

)ENGINE=INNODBDEFAULTCHARSET=utf8COMMENT='回复表';

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

推荐阅读更多精彩内容