😇🤡😢MongoDB 日期查询目前可通过Date 和ISODate两种方式:
💩
asd as 😟岸上打死大萨达撒大萨达撒的啊啊啊啊🤑
- dsa
- asd
- asdasd
- asdasd
撒旦
// 删除文章
public async delete_articles(article_ids: string, token: string) {
try {
const ids = article_ids.split(',');
const { id } = this.jwt_service.verify(token);
// console.log(ids);
const { deletedCount } = await this.article_model.remove({
_id: { $in: ids },
target_user_id: id,
});
return success_response({
msg: deletedCount > 0 ? `删除完成` : `删除失败,请检查id传参`,
});
} catch (err) {
console.log(`删除文章失败`, err);
throw new NotImplementedException(`删除失败`);
}
}
asd | asdas | dasd | ||||
---|---|---|---|---|---|---|
asdasdasd | asd | |||||
as | asdasd | |||||
d | ||||||
das | asdasd | |||||
asdasdasdasd | ||||||
aasdsd | ||||||
sd |
<div class="articles-list ">
<!-- article-list -->
<div class="bg-white mt-4 rounded-lg overflow-hidden hover:shadow-md transition-all duration-300">
<!-- tag -->
<div class="py-2 border-mini select-none">
<div class="left-navigator text-header flex justify-between">
<ul class="w-8/12 flex justify-start text-sm items-center">
<a href="#" class="hover:text-headerActive text-headerActive">
<li class="px-3 border-r-2 last:border-0">最新</li>
</a>
<a @click="message(`未完善`)">
<li class="hover:text-headerActive px-3 border-r-2 last:border-0 cursor-not-allowed">推荐</li>
</a>
<a @click="message(`未完善`)">
<li class="hover:text-headerActive px-3 border-r-2 last:border-0 cursor-not-allowed">阅读量</li>
</a>
<a @click="message(`未完善`)">
<li class="hover:text-headerActive px-3 border-r-2 last:border-0 cursor-not-allowed">点赞量</li>
</a>
</ul>
<!-- search -->
<div class="w-4/12 pr-3">
<el-input @keyup.enter.native="to_search(search_content)" size="mini" placeholder="请输入搜索内容" clearable
v-model="search_content">
<el-button @click="to_search(search_content)" slot="append" icon="el-icon-search" size="mini"></el-button>
</el-input>
</div>
</div>
</div>
<!-- acticles-main -->
<div>
<nuxt-link v-for="(item, index) in articles" :key="item._id" :to="`/article/content?id=${item._id}`">
<div
class="article h-36 flex justify-between p-3 border-b hover:bg-blue-100 transition-all duration-300 hover:bg-opacity-20 cursor-pointer overflow-hidden bg-white">
<div :class="[item.cover ? 'w-3/4 pr-2' : 'w-full']">
<div class="article-header flex text-xs">
<!-- <p class="relative">{{author.nickname}}</p> -->
<p class="mr-4 relative flex items-center">{{ item.create_time }}</p>
<!-- <p class="mr-4 relative">{{item.create_time}}</p> -->
<div class="article-tag flex">
<el-tag class="" :type="item.status === 2 ? 'danger' : 'success'" size="mini">
{{ item.status === 2 ? '私密' : '公开' }}
</el-tag>
<el-tag size="mini" type="" v-for="(item, index) in item.tag" :key="item + index"
class="tag-hover ml-4 relative first:ml-0" href="#">{{ item }}</el-tag>
</div>
</div>
<div class="mt-2 font-bold overflow-hidden">
<h2 class="truncate">{{ item.title }}</h2>
</div>
<div class="my-1 overflow-hidden text-xs">
<h3 class="flex items-center h-12">
<span class="details ">
{{ item.introduce }}
</span>
</h3>
</div>
<div class="only flex text-xs mt-2">
<p class="flex items-center">
<i class="iconfont icon-invisible"></i> <span class="ml-1">{{ item.read }}</span>
</p>
<p class="flex items-center mx-3">
<i class="iconfont icon-dianzan"></i> <span class="ml-1">{{ item.good }}</span>
</p>
<p class="flex items-center">
<i class="iconfont icon-xiaoxizhongxin"></i> <span class="ml-1">{{ item.comment.length }}</span>
</p>
</div>
</div>
<div v-if="item.cover"
class="rounded-lg overflow-hidden w-4/12 md:w-4/12 h-full max-w-100 min-w-28 flex items-center ">
<img class="w-full h-full object-cover" :src="`${item.cover}?imageView2/3/w/500/h/250`" />
</div>
</div>
</nuxt-link>
</div>
</div>
<!-- loading all over mt-4-auto -->
<loadingOver :page_params="page_params" />
</div>
css
@import "../static/base/base.scss";
@import "../static/base/iconfont.scss";
$grey: #4e5969;
.main {
.main {
// background-color: rgb(241, 242, 248);
.main-container {
// min-width: 960px;
// max-width: 960px;
// max-width: 1920px;
.center {
max-width: 1024px;
// min-width: 702px;
.left-navigator {
font-size: 14px;
ul {
li {
// &::after {}
border-right: 1.5px solid rgb(244, 245, 245);
}
}
}
}
.left {}
.right {
// min-width: 240px;
// max-width: 240px;
}
}
}
.details {
color: #86909c;
}
.border-mini {
border-bottom: 1.5px solid rgb(244, 245, 245);
}
.tracking-tighter {
letter-spacing: -0.05em;
}
.tracking-tight {
letter-spacing: -0.025em;
}
}
.index-container {}
// element-ui
.el-collapse-item__header {
height: auto !important;
min-height: 48px !important;
line-height: 24px !important;
border: none !important;
}
// 跑马灯指示条
.el-carousel__arrow {
background: rgba(0, 0, 0, 0.4) !important;
}
//
.tag-hover {
transition: all 0.3s ease;
}
.tag-hover:hover {
// transform: translateY(-10px);
// color:cyan !important;
border: 1px solid rgba(0, 0, 0, 0.2);
}
.comment-html {
img {
display: inline-block;
// width: 20px;
height: 20px;
}
}
.comment-html-center {
@extend .comment-html;
display: flex;
justify-content: center;
}
javascript
import { mapState, mapActions, mapMutations } from "vuex";
import loadingOver from "@/components/loading_all_over/loadingOver";
import { read_token } from "@/localStorage";
export default {
props: {
articles: {
type: Array,
required: true
},
page_params: {
type: Object,
required: true
}
},
components: {
loadingOver,
},
data() {
return {
search_content: "",
};
},
//计算
computed: {
},
//挂载
mounted() {
if (read_token()) {
this.$store.dispatch('get_articles', {
is_init: true,
page: 1,
limit: 20,
}) // 文章
this.$store.dispatch('get_sentences', {
is_init: true,
page: 1,
limit: 7,
}) // 说说
}
},
watch: {
// 监听搜索框
search_content: {
handler: function (n_val) {
if (n_val.trim().length === 0) {
this.to_search(n_val)
}
}
}
},
//方法
methods: {
...mapMutations([
'save_search_content',
]),
...mapActions([
'get_articles'
]),
to_search(search_content) {
this.$message(`搜索中...`)
this.save_search_content(search_content)
this.get_articles({
page: 1,
limit: 20,
is_init: true
})
},
message(val) {
this.$message(val)
}
},
}
TS
import {
Body,
Controller,
Delete,
Get,
Post,
Query,
UseGuards,
Headers,
} from '@nestjs/common';
import { ApiOperation, ApiParam, ApiTags } from '@nestjs/swagger';
import { Token_guard } from 'src/routers/token.router';
import { Token_guard_admin } from 'src/routers/token.router_admin';
import { Gallery_service } from './gallery.service';
import {
Add_tag_params,
Delete_tag_params,
Modify_tag_params,
Get_tag_params,
Add_gallery_params,
Delete_gallery_params,
Modify_gallery_params,
Get_gallery_params,
} from './gallery.verify';
@ApiTags('画廊相关的接口')
@Controller('gallery')
export class Gallery_controller {
constructor(private readonly gallery_service: Gallery_service) {}
@Post('add')
@ApiParam({
name: 'gallerys',
description: 'xx,xx,xx以这种 形式提交url',
type: 'string',
})
@ApiParam({
name: 'is_private',
description: '0 私密 1公开',
type: 'number',
})
@ApiParam({
name: 'tag',
description: '画廊的标签',
type: 'string',
})
@ApiParam({
name: 'content',
description: '画廊的内容',
type: 'string',
})
@ApiParam({
name: 'painting_title',
description: '画廊的标题',
type: 'string',
})
@ApiParam({
name: 'cover',
description: '画廊的封面',
type: 'string',
})
@ApiOperation({
summary: '添加画的接口',
})
@UseGuards(Token_guard)
Add_paintin(@Body() body: Add_gallery_params, @Headers() headers) {
return this.gallery_service.add_painting(body, headers.authorzation);
}
@Delete('delete')
@ApiParam({
name: 'ids',
description: 'xx,xx,xx 以字符串形式提交,要删除的画廊的id',
type: 'string',
})
@ApiOperation({
summary: '删除画的接口',
})
@UseGuards(Token_guard)
Delete_paintin(@Body() body: Delete_gallery_params, @Headers() headers) {
return this.gallery_service.delete_painting(body.ids, headers.authorzation);
}
@Post('modify')
@ApiParam({
name: 'gallerys',
description: 'xx,xx,xx以这种 形式提交url',
type: 'string',
})
@ApiParam({
name: 'is_private',
description: '0 私密 1公开',
type: 'number',
})
@ApiParam({
name: 'tag',
description: '画廊的标签',
type: 'string',
})
@ApiParam({
name: 'content',
description: '画廊的内容',
type: 'string',
})
@ApiParam({
name: 'painting_title',
description: '画廊的标题',
type: 'string',
})
@ApiParam({
name: 'cover',
description: '画廊的封面',
type: 'string',
})
@ApiParam({
name: 'id',
description: '修改的画廊的_id',
type: 'string',
})
@ApiOperation({
summary: '修改画的接口',
})
@UseGuards(Token_guard)
Modify_paintin(@Body() body: Modify_gallery_params) {
return this.gallery_service.modify_painting(body);
}
@Get('get')
@ApiParam({
name: 'id',
description: '画廊的属于哪个作者的id 一般传自己的',
type: 'string',
})
@ApiParam({
name: 'limit',
description: '一页多少项',
type: 'string',
})
@ApiParam({
name: 'page',
description: '当前第几页',
type: 'string',
})
@ApiOperation({
summary: '获取画的接口',
})
Get_paintin(@Query() query: Get_gallery_params, @Headers() headers) {
return this.gallery_service.get_paintings(query, headers.authorzation);
}
@Get('get_content')
@ApiOperation({
summary: '获取画内容的接口',
})
Get_paintin_content(@Query() query, @Headers() headers) {
return this.gallery_service.get_paintings_content(
query.id,
headers.authorzation,
);
}
// ----------------------------------------------------------------
// 添加标签
@Post('add_tag')
@UseGuards(Token_guard_admin)
@ApiParam({
name: 'tag',
description: 'xx,xx,xx 这种方式提交',
type: 'string',
})
@ApiOperation({
summary: '添加画廊标签的接口',
})
Add_tag(@Body() body: Add_tag_params, @Headers() headers) {
return this.gallery_service.add_tag(body, headers.authorzation);
}
// 删除标签
@Delete('delete_tag')
@ApiParam({
name: 'ids',
description: 'xx,xx,xx 这种方式提交',
type: 'string',
})
@UseGuards(Token_guard)
@ApiOperation({
summary: '删除画廊标签的接口',
})
Delete_tag(@Body() body: Delete_tag_params, @Headers() headers) {
return this.gallery_service.delete_tag(body.ids, headers.authorzation);
}
// 修改标签
@Post('modify_tag')
@ApiParam({
name: 'tag',
description: 'xx,xx,xx 这种方式提交',
type: 'string',
})
@ApiParam({
name: 'id',
description: '提交id',
type: 'string',
})
@ApiOperation({
summary: '修改画廊标签的接口',
})
Modify_tag(@Body() body: Modify_tag_params, @Headers() headers) {
return this.gallery_service.modify_tag(body, headers.authorzation);
}
// 获取标签
@Get('get_tag')
// @UseGuards(Token_guard_admin)
@ApiParam({
name: 'id',
description: '作者的id 一般传自己的作者_id',
type: 'string',
})
@ApiOperation({
summary: '获取标签的接口',
})
Get_tag(@Query() querys: Get_tag_params) {
return this.gallery_service.get_tag(querys.id);
}
}
nuxt.js
Commands and deployment
Nuxt comes with a set of useful commands, both for development and production purpose.
Using in package.json
You should have these commands in your package.json
:
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate"
}
You can launch your commands via yarn <command>
or npm run <command>
(example: yarn dev
/ npm run dev
).
Development Environment
To launch Nuxt in development mode with hot module replacement on http://localhost:3000
:
YarnNPM
Yarn
yarn dev
List of Commands
You can run different commands depending on the target :
target: server
(default value)
- nuxt dev - Launch the development server.
- nuxt build - Build and optimize your application with webpack for production.
- nuxt start - Start the production server (after running
nuxt build
). Use it for Node.js hosting like Heroku, Digital Ocean, etc.
target: static
- nuxt dev - Launch the development server.
- nuxt generate - Build the application (if needed), generate every route as a HTML file and statically export to
dist/
directory (used for static hosting). - nuxt start - serve the
dist/
directory like your static hosting would do (Netlify, Vercel, Surge, etc), great for testing before deploying.
Webpack Config Inspection
You can inspect the webpack config used by Nuxt to build the project (similar to vue inspect ).
- nuxt webpack query...
Arguments:
--name
: Bundle name to inspect. (client, server, modern)--dev
: Inspect webpack config for dev mode--depth
: Inspection depth. Defaults to 2 to prevent verbose output.--no-colors
: Disable ANSI colors (disabled by default when TTY is not available or when piping to a file)
Examples:
nuxt webpack
nuxt webpack devtool
nuxt webpack resolve alias
nuxt webpack module rules
nuxt webpack module rules test=.jsx
nuxt webpack module rules test=.pug oneOf use.0=raw
nuxt webpack plugins constructor.name=WebpackBar options reporter
nuxt webpack module rules loader=vue-
nuxt webpack module rules "loader=.*-loader"
Production Deployment
Nuxt lets you choose between Server or Static deployments.
Server Deployment
To deploy a SSR application we use target: 'server'
, where server is the default value.
YarnNPM
Yarn
yarn build
Nuxt will create a .nuxt
directory with everything inside ready to be deployed on your server hosting.
We recommend putting .nuxt in .npmignore or .gitignore.
Once your application is built you can use the start
command to see a production version of your application.
NPM
Static Deployment (Pre-rendered)
Nuxt gives you the ability to host your web application on any static hosting.
To deploy a static generated site make sure you have target: 'static'
in your nuxt.config.js
(for Nuxt >= 2.13):
nuxt.config.js
export default {
target: 'static'
}
NPM
yarn generate
Nuxt will create a dist/
directory with everything inside ready to be deployed on a static hosting service.
As of Nuxt v2.13 there is a crawler installed that will now crawl your link tags and generate your routes when using the command nuxt generate
based on those links.
Warning: Dynamic routes are ignored by the generate command when using Nuxt <= v2.12: API Configuration generate
When generating your web application with nuxt generate, the context given to asyncData and fetch will not have req and res.
Fail on Error
To return a non-zero status code when a page error is encountered and let the CI/CD fail the deployment or build, you can use the --fail-on-error
argument.
YarnNPM
Yarn
yarn generate --fail-on-error
What's next?
Read our Deployment Guides to find examples for deployments to popular hosts.
nuxt.js2
Data Fetching
In Nuxt we have 2 ways of getting data from an API. We can use the fetch method or the asyncData method.
Nuxt supports traditional Vue patterns for loading data in your client-side app, such as fetching data in a component's mounted()
hook. Universal apps, however, need to use Nuxt-specific hooks to be able to render data during server-side rendering. This allows your page to render with all of its required data present.
Nuxt has two hooks for asynchronous data loading:
asyncData
. This hook can only be placed on page components. Unlikefetch
, this hook does not display a loading placeholder during client-side rendering: instead, this hook blocks route navigation until it is resolved, displaying a page error if it fails.fetch
(Nuxt 2.12+). This hook can be placed on any component, and provides shortcuts for rendering loading states (during client-side rendering) and errors.
These hooks can be used with any data fetching library you choose. We recommend using @nuxt/http or @nuxt/axios for making requests to HTTP APIs. More information about these libraries, such as guides for configuring authentication headers, can be found in their respective documentation.
If you define fetch or asyncData inside a mixin and also have it defined in a component/page, the mixin function will be overwritten instead of called.
The fetch hook
Before Nuxt 2.12, there was a different fetch hook that only worked for page components and didn't have access to the component instance.If your fetch() accepts a context argument, it will be treated like a legacy fetch hook. This functionality is deprecated, and should be replaced with either asyncData or an anonymous middleware.
fetch
is a hook called during server-side rendering after the component instance is created, and on the client when navigating. The fetch hook should return a promise (whether explicitly, or implicitly using async/await
) that will be resolved:
- On the server, before the initial page is rendered
- On the client, some time after the component is mounted
For static hosting , the fetch hook is only called during page generation, and the result is then cached for use on the client. To avoid cache conflicts, it may be necessary to specify a name for your component, or alternatively provide a unique fetchKey implementation.
Usage
Fetching data
Within the fetch hook, you will have access to the component instance via this
.
Make sure any properties you want to modify have already been declared in data(). Then the data that comes from the fetch can be assigned to these properties.
Changing fetch behavior
fetchOnServer
: Boolean
or Function
(default: true
), call fetch()
when server-rendering the page
fetchKey
: String
or Function
(defaults to the component scope ID or component name), a key (or a function that produces a unique key) that identifies the result of this component's fetch (available on Nuxt 2.15+). When hydrating a server-rendered page, this key is used to map the result of the server-side fetch()
to the client-side component data. More information available in original PR .
fetchDelay
: Integer
(default: 200
), set the minimum executing time in milliseconds (to avoid quick flashes)
When fetchOnServer
is falsy (false
or returns false
), fetch
will be called only on client-side and $fetchState.pending
will return true
when server-rendering the component.
export default {
data: () => ({
posts: []
}),
async fetch() {
this.posts = await this.$http.$get('https://api.nuxtjs.dev/posts')
},
fetchOnServer: false,
// multiple components can return the same `fetchKey` and Nuxt will track them both separately
fetchKey: 'site-sidebar',
// alternatively, for more control, a function can be passed with access to the component instance
// It will be called in `created` and must not depend on fetched data
fetchKey(getCounter) {
// getCounter is a method that can be called to get the next number in a sequence
// as part of generating a unique fetchKey.
return this.someOtherData + getCounter('sidebar')
}
}
Accessing the fetch state
The fetch
hook exposes this.$fetchState
at the component level with the following properties:
pending
is aBoolean
that allows you to display a placeholder whenfetch
is being called on client-side.error
is eithernull
or anError
thrown by the fetch hooktimestamp
is a timestamp of the last fetch, useful for caching withkeep-alive
In addition to fetch being called by Nuxt, you can manually call fetch in your component (to e.g. reload its async data) by calling this.$fetch()
.
components/NuxtMountains.vue
<template>
<div>
<p v-if="$fetchState.pending">Fetching mountains...</p>
<p v-else-if="$fetchState.error">An error occurred :(</p>
<div v-else>
<h1>Nuxt Mountains</h1>
<ul>
<li v-for="mountain of mountains">{{ mountain.title }}</li>
</ul>
<button @click="$fetch">Refresh</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
mountains: []
}
},
async fetch() {
this.mountains = await fetch(
'https://api.nuxtjs.dev/mountains'
).then(res => res.json())
}
}
</script>
You can access the Nuxt context within the fetch hook using this.$nuxt.context.
Listening to query string changes
The fetch
hook is not called on query string changes by default. To watch for query changes you can add a watcher on $route.query
and call $fetch
:
export default {
watch: {
'$route.query': '$fetch'
},
async fetch() {
// Called also on query changes
}
}
Caching
You can use keep-alive
directive in <nuxt/>
and <nuxt-child/>
component to save fetch
calls on pages you already visited:
layouts/default.vue
<template>
<nuxt keep-alive />
</template>
You can also specify the props passed to <keep-alive>
by passing a prop keep-alive-props
to the <nuxt>
component.
layouts/default.vue
<nuxt keep-alive :keep-alive-props="{ max: 10 }" />
Keeps only 10 page components in memory.
Error handling
If there is an error when fetching data, the normal Nuxt error page won't be loaded - and you should not use the Nuxt redirect or error methods within fetch(). Instead, you will need to handle it within your component using $fetchState.error.
We can check $fetchState.error
and show an error message if there is an error fetching the data.
components/MountainsList.vue
<template>
<div>
<p v-if="$fetchState.pending">Loading....</p>
<p v-else-if="$fetchState.error">Error while fetching mountains</p>
<ul v-else>
<li v-for="(mountain, index) in mountains" :key="index">
{{ mountain.title }}
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
mountains: []
}
},
async fetch() {
this.mountains = await fetch(
'https://api.nuxtjs.dev/mountains'
).then(res => res.json())
}
}
</script>
Using activated
hook
Nuxt will directly fill this.$fetchState.timestamp
(timestamp) of the last fetch
call (ssr included). You can use this property combined with activated
hook to add a 30 seconds cache to fetch
:
pages/posts/_id.vue
<template> ... </template>
<script>
export default {
data() {
return {
posts: []
}
},
activated() {
// Call fetch again if last fetch more than 30 sec ago
if (this.$fetchState.timestamp <= Date.now() - 30000) {
this.$fetch()
}
},
async fetch() {
this.posts = await fetch('https://api.nuxtjs.dev/posts').then(res =>
res.json()
)
}
}
</script>
The navigation to the same page will not call fetch
if last fetch
call was before 30 sec ago.
Async Data
asyncData is only available for pages and you don't have access to this inside the hook.
asyncData
is another hook for universal data fetching. Unlike fetch
, which requires you to set properties on the component instance (or dispatch Vuex actions) to save your async state, asyncData
simply merges its return value into your component's local state. Here's an example using the @nuxt/http library:
pages/posts/_id.vue
<template>
<div>
<h1>{{ post.title }}</h1>
<p>{{ post.description }}</p>
</div>
</template>
<script>
export default {
async asyncData({ params, $http }) {
const post = await $http.$get(`https://api.nuxtjs.dev/posts/${params.id}`)
return { post }
}
}
</script>
Unlike fetch
, the promise returned by the asyncData
hook is resolved during route transition. This means that no "loading placeholder" is visible during client-side transitions (although the loading bar can be used to indicate a loading state to the user). Nuxt will instead wait for the asyncData
hook to be finished before navigating to the next page or display the error page ).
This hook can only be used for page-level components. Unlike fetch
, asyncData
cannot access the component instance (this
). Instead, it receives the context as its argument. You can use it to fetch some data and Nuxt will automatically shallow merge the returned object with the component data.
In the upcoming examples, we are using @nuxt/http which we recommend for fetching data from an API.
Async data in components?
Because components do not have an asyncData
method, you cannot directly fetch async data server side within a component. In order to get around this limitation you have three basic options:
- Use the new
fetch
hook that is available in Nuxt 2.12 and later versions. - Make the API call in the
mounted
hook and set data properties when loaded. Downside: Won't work for server side rendering. - Make the API call in the
asyncData
method of the page component and pass the data as props to the sub components. Server rendering will work fine.Downside: the asyncData of the page might be less readable because it's loading the data for other components
.
Listening to query changes
The asyncData
method is not called on query string changes by default. If you want to change this behavior, for example when building a pagination component, you can set up parameters that should be listened to with the watchQuery
property of your page component.
欢迎来在文章评论唠叨,但请别发布违反道德或政治的相关言论
评论区暂无数据