add query page
This commit is contained in:
1 parent
c2ae07be06
commit
3bc2a943bd
31 files changed
+379
-163
No files matched your search
+4
-1
@@ -14,5 +14,8 @@
|
|||||||
"url": "https://github.com/patarapolw/zhdiary"
|
"url": "https://github.com/patarapolw/zhdiary"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"fullUrl": "https://zhdiary.polvcode.dev"
|
"fullUrl": "https://zhdiary.polvcode.dev",
|
||||||
|
"author": {
|
||||||
|
"name": "Pacharapol Withayasakpunt"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -37,13 +37,7 @@ tag:
|
|||||||
figcaption.text-center zhang1
|
figcaption.text-center zhang1
|
||||||
```
|
```
|
||||||
|
|
||||||
<!-- excerpt_separator -->
|
|
||||||
|
|
||||||
```css parsed
|
```css parsed
|
||||||
table td:first-child {
|
|
||||||
width: 10em;
|
|
||||||
}
|
|
||||||
|
|
||||||
figure {
|
figure {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
}
|
}
|
||||||
@@ -55,6 +49,14 @@ figure {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<!-- excerpt_separator -->
|
||||||
|
|
||||||
|
```css parsed
|
||||||
|
table td:first-child {
|
||||||
|
width: 10em;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
盈利 | yínglì | profit / gain
|
盈利 | yínglì | profit / gain
|
||||||
轻盈 | qīngyíng | graceful / lithe / light and graceful / lighthearted / relaxed
|
轻盈 | qīngyíng | graceful / lithe / light and graceful / lighthearted / relaxed
|
||||||
盈亏 | yíngkuī | profit and loss / waxing and waning
|
盈亏 | yíngkuī | profit and loss / waxing and waning
|
||||||
|
|||||||
@@ -37,13 +37,7 @@ tag:
|
|||||||
figcaption.text-center yang2
|
figcaption.text-center yang2
|
||||||
```
|
```
|
||||||
|
|
||||||
<!-- excerpt_separator -->
|
|
||||||
|
|
||||||
```css parsed
|
```css parsed
|
||||||
table td:first-child {
|
|
||||||
width: 10em;
|
|
||||||
}
|
|
||||||
|
|
||||||
figure {
|
figure {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
}
|
}
|
||||||
@@ -55,6 +49,14 @@ figure {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<!-- excerpt_separator -->
|
||||||
|
|
||||||
|
```css parsed
|
||||||
|
table td:first-child {
|
||||||
|
width: 10em;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
闰年 | rùnnián | leap year / (lunar calendar) year with a thirteen intercalary month
|
闰年 | rùnnián | leap year / (lunar calendar) year with a thirteen intercalary month
|
||||||
闰月 | rùnyuè | intercalary month in the lunar calendar / leap month
|
闰月 | rùnyuè | intercalary month in the lunar calendar / leap month
|
||||||
敖闰 | Áorùn | Dragon King of the West Sea, Ao Run, also Ao Ji (敖吉)
|
敖闰 | Áorùn | Dragon King of the West Sea, Ao Run, also Ao Ji (敖吉)
|
||||||
|
|||||||
@@ -37,13 +37,7 @@ tag:
|
|||||||
figcaption.text-center gang1
|
figcaption.text-center gang1
|
||||||
```
|
```
|
||||||
|
|
||||||
<!-- excerpt_separator -->
|
|
||||||
|
|
||||||
```css parsed
|
```css parsed
|
||||||
table td:first-child {
|
|
||||||
width: 10em;
|
|
||||||
}
|
|
||||||
|
|
||||||
figure {
|
figure {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
}
|
}
|
||||||
@@ -55,6 +49,14 @@ figure {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<!-- excerpt_separator -->
|
||||||
|
|
||||||
|
```css parsed
|
||||||
|
table td:first-child {
|
||||||
|
width: 10em;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
资金 | zījīn | funds / funding / capital
|
资金 | zījīn | funds / funding / capital
|
||||||
基金 | jījīn | fund
|
基金 | jījīn | fund
|
||||||
黄金 (黃金) | huángjīn | gold / golden (opportunity) / prime (time)
|
黄金 (黃金) | huángjīn | gold / golden (opportunity) / prime (time)
|
||||||
|
|||||||
@@ -37,13 +37,7 @@ tag:
|
|||||||
figcaption.text-center guang1
|
figcaption.text-center guang1
|
||||||
```
|
```
|
||||||
|
|
||||||
<!-- excerpt_separator -->
|
|
||||||
|
|
||||||
```css parsed
|
```css parsed
|
||||||
table td:first-child {
|
|
||||||
width: 10em;
|
|
||||||
}
|
|
||||||
|
|
||||||
figure {
|
figure {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
}
|
}
|
||||||
@@ -55,6 +49,14 @@ figure {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<!-- excerpt_separator -->
|
||||||
|
|
||||||
|
```css parsed
|
||||||
|
table td:first-child {
|
||||||
|
width: 10em;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
刀剑 (刀劍) | dāojiàn | sword
|
刀剑 (刀劍) | dāojiàn | sword
|
||||||
剑桥 (劍橋) | Jiànqiáo | Cambridge
|
剑桥 (劍橋) | Jiànqiáo | Cambridge
|
||||||
利剑 (利劍) | lìjiàn | sharp sword
|
利剑 (利劍) | lìjiàn | sharp sword
|
||||||
|
|||||||
@@ -37,13 +37,7 @@ tag:
|
|||||||
figcaption.text-center jiang1
|
figcaption.text-center jiang1
|
||||||
```
|
```
|
||||||
|
|
||||||
<!-- excerpt_separator -->
|
|
||||||
|
|
||||||
```css parsed
|
```css parsed
|
||||||
table td:first-child {
|
|
||||||
width: 10em;
|
|
||||||
}
|
|
||||||
|
|
||||||
figure {
|
figure {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
}
|
}
|
||||||
@@ -55,6 +49,14 @@ figure {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<!-- excerpt_separator -->
|
||||||
|
|
||||||
|
```css parsed
|
||||||
|
table td:first-child {
|
||||||
|
width: 10em;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
如果 | rúguǒ | if / in case / in the event that
|
如果 | rúguǒ | if / in case / in the event that
|
||||||
结果 (結果) | jiēguǒ | to bear fruit / CL: 個|个
|
结果 (結果) | jiēguǒ | to bear fruit / CL: 個|个
|
||||||
结果 (結果) | jiéguǒ | outcome / result / conclusion / in the end / as a result / to kill / to dispatch
|
结果 (結果) | jiéguǒ | outcome / result / conclusion / in the end / as a result / to kill / to dispatch
|
||||||
|
|||||||
@@ -37,13 +37,7 @@ tag:
|
|||||||
figcaption.text-center xiang2
|
figcaption.text-center xiang2
|
||||||
```
|
```
|
||||||
|
|
||||||
<!-- excerpt_separator -->
|
|
||||||
|
|
||||||
```css parsed
|
```css parsed
|
||||||
table td:first-child {
|
|
||||||
width: 10em;
|
|
||||||
}
|
|
||||||
|
|
||||||
figure {
|
figure {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
}
|
}
|
||||||
@@ -55,6 +49,14 @@ figure {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<!-- excerpt_separator -->
|
||||||
|
|
||||||
|
```css parsed
|
||||||
|
table td:first-child {
|
||||||
|
width: 10em;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
海报 (海報) | hǎibào | poster / playbill / notice
|
海报 (海報) | hǎibào | poster / playbill / notice
|
||||||
海外 | hǎiwài | overseas / abroad
|
海外 | hǎiwài | overseas / abroad
|
||||||
海洋 | hǎiyáng | ocean / CL: 個|个
|
海洋 | hǎiyáng | ocean / CL: 個|个
|
||||||
|
|||||||
@@ -37,13 +37,7 @@ tag:
|
|||||||
figcaption.text-center tang2
|
figcaption.text-center tang2
|
||||||
```
|
```
|
||||||
|
|
||||||
<!-- excerpt_separator -->
|
|
||||||
|
|
||||||
```css parsed
|
```css parsed
|
||||||
table td:first-child {
|
|
||||||
width: 10em;
|
|
||||||
}
|
|
||||||
|
|
||||||
figure {
|
figure {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
}
|
}
|
||||||
@@ -55,6 +49,14 @@ figure {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<!-- excerpt_separator -->
|
||||||
|
|
||||||
|
```css parsed
|
||||||
|
table td:first-child {
|
||||||
|
width: 10em;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
推荐 (推薦) | tuījiàn | to recommend / recommendation
|
推荐 (推薦) | tuījiàn | to recommend / recommendation
|
||||||
推广 (推廣) | tuīguǎng | to extend / to spread / to popularize / generalization / promotion (of a product etc)
|
推广 (推廣) | tuīguǎng | to extend / to spread / to popularize / generalization / promotion (of a product etc)
|
||||||
推动 (推動) | tuīdòng | to push (for acceptance of a plan) / to push forward / to promote / to actuate / CL: 個|个
|
推动 (推動) | tuīdòng | to push (for acceptance of a plan) / to push forward / to promote / to actuate / CL: 個|个
|
||||||
|
|||||||
@@ -37,13 +37,7 @@ tag:
|
|||||||
figcaption.text-center wang2
|
figcaption.text-center wang2
|
||||||
```
|
```
|
||||||
|
|
||||||
<!-- excerpt_separator -->
|
|
||||||
|
|
||||||
```css parsed
|
```css parsed
|
||||||
table td:first-child {
|
|
||||||
width: 10em;
|
|
||||||
}
|
|
||||||
|
|
||||||
figure {
|
figure {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
}
|
}
|
||||||
@@ -55,6 +49,14 @@ figure {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<!-- excerpt_separator -->
|
||||||
|
|
||||||
|
```css parsed
|
||||||
|
table td:first-child {
|
||||||
|
width: 10em;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
遐想 | xiáxiǎng | reverie / daydream / to be lost in wild and fanciful thoughts
|
遐想 | xiáxiǎng | reverie / daydream / to be lost in wild and fanciful thoughts
|
||||||
闻名遐迩 (聞名遐邇) | wénmíngxiá'ěr | to be famous far and wide (idiom)
|
闻名遐迩 (聞名遐邇) | wénmíngxiá'ěr | to be famous far and wide (idiom)
|
||||||
遐 | xiá | distant / long-lasting / to abandon
|
遐 | xiá | distant / long-lasting / to abandon
|
||||||
|
|||||||
@@ -37,13 +37,7 @@ tag:
|
|||||||
figcaption.text-center chang2
|
figcaption.text-center chang2
|
||||||
```
|
```
|
||||||
|
|
||||||
<!-- excerpt_separator -->
|
|
||||||
|
|
||||||
```css parsed
|
```css parsed
|
||||||
table td:first-child {
|
|
||||||
width: 10em;
|
|
||||||
}
|
|
||||||
|
|
||||||
figure {
|
figure {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
}
|
}
|
||||||
@@ -55,6 +49,14 @@ figure {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<!-- excerpt_separator -->
|
||||||
|
|
||||||
|
```css parsed
|
||||||
|
table td:first-child {
|
||||||
|
width: 10em;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
鸣 (鳴) | míng | to cry (of birds, animals and insects)
|
鸣 (鳴) | míng | to cry (of birds, animals and insects)
|
||||||
共鸣 (共鳴) | gòngmíng | resonance (physics) / sympathetic response to sth
|
共鸣 (共鳴) | gòngmíng | resonance (physics) / sympathetic response to sth
|
||||||
争鸣 (爭鳴) | zhēngmíng | to contend
|
争鸣 (爭鳴) | zhēngmíng | to contend
|
||||||
|
|||||||
@@ -37,13 +37,7 @@ tag:
|
|||||||
figcaption.text-center shang1
|
figcaption.text-center shang1
|
||||||
```
|
```
|
||||||
|
|
||||||
<!-- excerpt_separator -->
|
|
||||||
|
|
||||||
```css parsed
|
```css parsed
|
||||||
table td:first-child {
|
|
||||||
width: 10em;
|
|
||||||
}
|
|
||||||
|
|
||||||
figure {
|
figure {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
}
|
}
|
||||||
@@ -55,6 +49,14 @@ figure {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<!-- excerpt_separator -->
|
||||||
|
|
||||||
|
```css parsed
|
||||||
|
table td:first-child {
|
||||||
|
width: 10em;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
恭喜 | gōngxǐ | congratulations / greetings
|
恭喜 | gōngxǐ | congratulations / greetings
|
||||||
恭 | gōng | respectful
|
恭 | gōng | respectful
|
||||||
恭贺 (恭賀) | gōnghè | to congratulate respectfully / to express good wishes
|
恭贺 (恭賀) | gōnghè | to congratulate respectfully / to express good wishes
|
||||||
|
|||||||
@@ -37,13 +37,7 @@ tag:
|
|||||||
figcaption.text-center liang2
|
figcaption.text-center liang2
|
||||||
```
|
```
|
||||||
|
|
||||||
<!-- excerpt_separator -->
|
|
||||||
|
|
||||||
```css parsed
|
```css parsed
|
||||||
table td:first-child {
|
|
||||||
width: 10em;
|
|
||||||
}
|
|
||||||
|
|
||||||
figure {
|
figure {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
}
|
}
|
||||||
@@ -55,6 +49,14 @@ figure {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<!-- excerpt_separator -->
|
||||||
|
|
||||||
|
```css parsed
|
||||||
|
table td:first-child {
|
||||||
|
width: 10em;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
女性 | nǚxìng | woman / the female sex
|
女性 | nǚxìng | woman / the female sex
|
||||||
女子 | nǚzǐ | woman / female
|
女子 | nǚzǐ | woman / female
|
||||||
女孩 | nǚhái | girl / lass
|
女孩 | nǚhái | girl / lass
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@patarapolw/qsearch": "^1.1.1",
|
"@patarapolw/qsearch": "^1.1.1",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
|
"dayjs": "^1.8.21",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"fast-glob": "^3.2.2",
|
"fast-glob": "^3.2.2",
|
||||||
"gray-matter": "^4.0.2",
|
"gray-matter": "^4.0.2",
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import crypto from 'crypto'
|
|||||||
import matter from 'gray-matter'
|
import matter from 'gray-matter'
|
||||||
import glob from 'fast-glob'
|
import glob from 'fast-glob'
|
||||||
import DataStore from 'nedb-promises'
|
import DataStore from 'nedb-promises'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
|
|
||||||
import MakeHtml from '../src/utils/make-html'
|
import MakeHtml from '../src/utils/make-html'
|
||||||
|
|
||||||
@@ -44,6 +45,7 @@ const db = new DataStore('assets/data.nedb')
|
|||||||
|
|
||||||
await db.insert({
|
await db.insert({
|
||||||
...data,
|
...data,
|
||||||
|
date: formatDate(data.date),
|
||||||
filename: f,
|
filename: f,
|
||||||
h,
|
h,
|
||||||
excerpt: computedExcerpt,
|
excerpt: computedExcerpt,
|
||||||
@@ -64,8 +66,13 @@ const db = new DataStore('assets/data.nedb')
|
|||||||
computedContent = computedContent.substr(computedExcerpt.length)
|
computedContent = computedContent.substr(computedExcerpt.length)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.date) {
|
||||||
|
console.log(formatDate(data.date))
|
||||||
|
}
|
||||||
|
|
||||||
await db.insert({
|
await db.insert({
|
||||||
...data,
|
...data,
|
||||||
|
date: formatDate(data.date),
|
||||||
filename: f,
|
filename: f,
|
||||||
h,
|
h,
|
||||||
excerpt: computedExcerpt,
|
excerpt: computedExcerpt,
|
||||||
@@ -77,3 +84,17 @@ const db = new DataStore('assets/data.nedb')
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
})().catch(console.error)
|
})().catch(console.error)
|
||||||
|
|
||||||
|
const tzOffset = new Date().getTimezoneOffset()
|
||||||
|
|
||||||
|
function formatDate (d?: string | Date) {
|
||||||
|
if (d) {
|
||||||
|
if (typeof d === 'string') {
|
||||||
|
return dayjs(d).toDate()
|
||||||
|
} else {
|
||||||
|
return dayjs(d).add(tzOffset, 'minute').toDate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return d
|
||||||
|
}
|
||||||
@@ -26,26 +26,29 @@ dataRouter.get('/*', (req, res) => {
|
|||||||
|
|
||||||
dataRouter.post('/', async (req, res, next) => {
|
dataRouter.post('/', async (req, res, next) => {
|
||||||
try {
|
try {
|
||||||
const { q, project, offset, limit } = req.body
|
const { q, cond = {}, project, offset, limit } = req.body
|
||||||
let cond = q
|
const $and = [
|
||||||
if (typeof q === 'string') {
|
{ filename: { $regex: /^posts\// } },
|
||||||
|
cond
|
||||||
|
] as any[]
|
||||||
|
|
||||||
|
if (q) {
|
||||||
const parser = new QSearch({
|
const parser = new QSearch({
|
||||||
dialect: 'nedb',
|
dialect: 'nedb',
|
||||||
schema: {
|
schema: {
|
||||||
|
title: {},
|
||||||
filename: {},
|
filename: {},
|
||||||
excerpt: {},
|
excerpt: {},
|
||||||
date: { type: 'date' }
|
date: { type: 'date' }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
cond = parser.parse(q)
|
$and.push(parser.parse(q))
|
||||||
}
|
}
|
||||||
|
|
||||||
const count = await db.count(cond)
|
const count = await db.count({ $and })
|
||||||
|
|
||||||
|
let c = db.find({ $and }, project).skip(offset || 0)
|
||||||
|
|
||||||
let c = db.find(cond).skip(offset || 0)
|
|
||||||
if (project) {
|
|
||||||
c = c.projection(project)
|
|
||||||
}
|
|
||||||
if (limit !== null) {
|
if (limit !== null) {
|
||||||
c = c.limit(limit || 5)
|
c = c.limit(limit || 5)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -420,6 +420,11 @@ dateformat@~1.0.4-1.2.3:
|
|||||||
get-stdin "^4.0.1"
|
get-stdin "^4.0.1"
|
||||||
meow "^3.3.0"
|
meow "^3.3.0"
|
||||||
|
|
||||||
|
dayjs@^1.8.21:
|
||||||
|
version "1.8.21"
|
||||||
|
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.8.21.tgz#98299185b72b9b679f31c7ed987b63923c961552"
|
||||||
|
integrity sha512-1kbWK0hziklUHkGgiKr7xm59KwAg/K3Tp7H/8X+f58DnNCwY3pKYjOCJpIlVs125FRBukGVZdKZojC073D0IeQ==
|
||||||
|
|
||||||
debounce@^1.0.0:
|
debounce@^1.0.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.0.tgz#44a540abc0ea9943018dc0eaa95cce87f65cd131"
|
resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.0.tgz#44a540abc0ea9943018dc0eaa95cce87f65cd131"
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
"axios": "^0.19.2",
|
"axios": "^0.19.2",
|
||||||
"buefy": "^0.8.12",
|
"buefy": "^0.8.12",
|
||||||
"core-js": "^3.6.4",
|
"core-js": "^3.6.4",
|
||||||
|
"dayjs": "^1.8.21",
|
||||||
"vue": "^2.6.11",
|
"vue": "^2.6.11",
|
||||||
"vue-class-component": "^7.2.2",
|
"vue-class-component": "^7.2.2",
|
||||||
"vue-extend-layout": "^2.0.6",
|
"vue-extend-layout": "^2.0.6",
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
<link rel="icon" href="/api/favicon.ico">
|
<link rel="icon" href="/api/favicon.ico">
|
||||||
|
<link rel="stylesheet" href="https://cdn.materialdesignicons.com/2.5.94/css/materialdesignicons.min.css">
|
||||||
<title>ZhDiary</title>
|
<title>ZhDiary</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -11,3 +11,9 @@ export default {
|
|||||||
components: { VueExtendLayouts }
|
components: { VueExtendLayouts }
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.d-inline-block {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Whitespace-only changes.
Binary file not shown.
|
Before Width: | Height: | Size: 6.7 KiB |
@@ -1,59 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="hello">
|
|
||||||
<h1>{{ msg }}</h1>
|
|
||||||
<p>
|
|
||||||
For a guide and recipes on how to configure / customize this project,<br>
|
|
||||||
check out the
|
|
||||||
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
|
|
||||||
</p>
|
|
||||||
<h3>Installed CLI Plugins</h3>
|
|
||||||
<ul>
|
|
||||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
|
|
||||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-typescript" target="_blank" rel="noopener">typescript</a></li>
|
|
||||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router" target="_blank" rel="noopener">router</a></li>
|
|
||||||
</ul>
|
|
||||||
<h3>Essential Links</h3>
|
|
||||||
<ul>
|
|
||||||
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
|
|
||||||
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
|
|
||||||
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
|
|
||||||
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
|
|
||||||
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
|
|
||||||
</ul>
|
|
||||||
<h3>Ecosystem</h3>
|
|
||||||
<ul>
|
|
||||||
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
|
|
||||||
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
|
|
||||||
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
|
|
||||||
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
|
|
||||||
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { Component, Prop, Vue } from 'vue-property-decorator';
|
|
||||||
|
|
||||||
@Component
|
|
||||||
export default class HelloWorld extends Vue {
|
|
||||||
@Prop() private msg!: string;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
|
||||||
<style scoped lang="scss">
|
|
||||||
h3 {
|
|
||||||
margin: 40px 0 0;
|
|
||||||
}
|
|
||||||
ul {
|
|
||||||
list-style-type: none;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
li {
|
|
||||||
display: inline-block;
|
|
||||||
margin: 0 10px;
|
|
||||||
}
|
|
||||||
a {
|
|
||||||
color: #42b983;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<template lang="pug">
|
||||||
|
.post-meta.mb-sm
|
||||||
|
.post-meta-author
|
||||||
|
a.mr-md(:href="author.link" style="width: 24px; min-width: 24px"): img(:src="author.avatar" style="border-radius: 50%;")
|
||||||
|
a.mr-md(:href="author.link") {{author.login}}
|
||||||
|
div(style="flex-grow: 1")
|
||||||
|
div {{dateString}}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Vue, Component, Prop } from 'vue-property-decorator'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
|
|
||||||
|
import { config } from '../global'
|
||||||
|
|
||||||
|
@Component
|
||||||
|
export default class PostHeader extends Vue {
|
||||||
|
@Prop({ required: true }) header!: any
|
||||||
|
|
||||||
|
author = config.author || {}
|
||||||
|
|
||||||
|
get dateString () {
|
||||||
|
return this.header.date ? dayjs(this.header.date).format("ddd D MMMM YYYY") : ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
<template lang="pug">
|
||||||
|
.card.my-lg.blog-post
|
||||||
|
.card-content
|
||||||
|
PostHeader(:header="header")
|
||||||
|
.post-content
|
||||||
|
.image-teaser(v-if="header.image")
|
||||||
|
img(:src="header.image")
|
||||||
|
h2.title {{header.title}}
|
||||||
|
.content(v-html="header.excerpt")
|
||||||
|
div(style="display: flex; justify-content: flex-end")
|
||||||
|
router-link.button.is-danger.is-outlined(:to="url") Read more
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Vue, Component, Prop } from 'vue-property-decorator'
|
||||||
|
|
||||||
|
import PostHeader from './PostHeader.vue'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
components: {
|
||||||
|
PostHeader
|
||||||
|
}
|
||||||
|
})
|
||||||
|
export default class PostTeaser extends Vue {
|
||||||
|
@Prop({ required: true }) header!: any
|
||||||
|
|
||||||
|
get url () {
|
||||||
|
return this.header.filename.replace(/\.md$/, '')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.content {
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
max-width: 80vw;
|
||||||
|
}
|
||||||
|
.post-content {
|
||||||
|
width: 100%;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
.image-teaser {
|
||||||
|
width: calc(100% + 3rem);
|
||||||
|
margin-top: 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
margin-left: -1.5rem;
|
||||||
|
margin-right: -1.5rem;
|
||||||
|
}
|
||||||
|
@media only screen and (min-width: 800px) {
|
||||||
|
.image-teaser {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 300px;
|
||||||
|
max-height: 300px;
|
||||||
|
float: right;
|
||||||
|
margin: 1rem;
|
||||||
|
}
|
||||||
|
.post-content {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -6,7 +6,9 @@ section
|
|||||||
b-navbar-item(tag="router-link" to="/")
|
b-navbar-item(tag="router-link" to="/")
|
||||||
h1.bold {{config.banner}}
|
h1.bold {{config.banner}}
|
||||||
template(slot="start")
|
template(slot="start")
|
||||||
b-navbar-item(v-for="t in config.tabs"
|
b-navbar-item(
|
||||||
|
v-for="t in config.tabs"
|
||||||
|
:key="t.name"
|
||||||
:tag="t.to ? 'router-link' : 'a'"
|
:tag="t.to ? 'router-link' : 'a'"
|
||||||
:href="t.to ? '' : t.url"
|
:href="t.to ? '' : t.url"
|
||||||
:to="t.to ? t.to : ''"
|
:to="t.to ? t.to : ''"
|
||||||
@@ -20,7 +22,7 @@ section
|
|||||||
fa(icon="search")
|
fa(icon="search")
|
||||||
section(style="margin-top: 3.25rem")
|
section(style="margin-top: 3.25rem")
|
||||||
.columns
|
.columns
|
||||||
.column.column.is-10-desktop.is-offset-1-desktop
|
.column.column.is-three-fifths-desktop.is-offset-one-fifth-desktop
|
||||||
router-view
|
router-view
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -44,7 +46,7 @@ import { normalizeArray } from '../utils'
|
|||||||
{
|
{
|
||||||
hid: 'og:url',
|
hid: 'og:url',
|
||||||
property: 'og:url',
|
property: 'og:url',
|
||||||
content: this.fullUrl
|
content: url
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,10 +6,33 @@ Vue.use(VueRouter)
|
|||||||
const router = new VueRouter({
|
const router = new VueRouter({
|
||||||
mode: 'history',
|
mode: 'history',
|
||||||
routes: [
|
routes: [
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
component: () => import('../views/QueryView.vue'),
|
||||||
|
meta: {
|
||||||
|
layout: 'default'
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/:page',
|
path: '/:page',
|
||||||
alias: '/',
|
component: () => import('../views/QueryView.vue'),
|
||||||
component: () => import('../views/Home.vue')
|
meta: {
|
||||||
|
layout: 'default'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/tag/:tag',
|
||||||
|
component: () => import('../views/QueryView.vue'),
|
||||||
|
meta: {
|
||||||
|
layout: 'default'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/tag/:tag/:page',
|
||||||
|
component: () => import('../views/QueryView.vue'),
|
||||||
|
meta: {
|
||||||
|
layout: 'default'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
export function normalizeArray<T> (a: T | T[]): T | undefined {
|
export function normalizeArray<T> (a: T | T[]): T | undefined {
|
||||||
return Array.isArray(a) ? a[0] : a
|
return Array.isArray(a) ? a[0] : a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const isRendered = !!document.getElementById('app')!.getAttribute('data-server-rendered')
|
||||||
|
|
||||||
|
export const api = axios.create({
|
||||||
|
baseURL: isRendered ? '/api' : 'http://localhost:48000/api'
|
||||||
|
})
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="about">
|
|
||||||
<h1>This is an about page</h1>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="home">
|
|
||||||
<img alt="Vue logo" src="../assets/logo.png">
|
|
||||||
<HelloWorld msg="Welcome to Your Vue.js App"/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// @ is an alias to /src
|
|
||||||
import HelloWorld from '@/components/HelloWorld.vue'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'Home',
|
|
||||||
components: {
|
|
||||||
HelloWorld
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
<template lang="pug">
|
||||||
|
section
|
||||||
|
section.m-lg(v-if="tag")
|
||||||
|
h2.title.is-2
|
||||||
|
span.mr-sm Tag:
|
||||||
|
span(style="font-weight: 400") {{tag}}
|
||||||
|
section(v-if="posts.length > 0")
|
||||||
|
PostTeaser(v-for="p in posts" :header="p" :key="p.filename")
|
||||||
|
b-pagination.my-lg.mx-sm(:current.sync="page" :total="count" :per-page="5"
|
||||||
|
size="default" rounded)
|
||||||
|
div(v-else)
|
||||||
|
Empty
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Vue, Component } from 'vue-property-decorator'
|
||||||
|
|
||||||
|
import PostTeaser from '../components/PostTeaser.vue'
|
||||||
|
import { api, normalizeArray } from '../utils'
|
||||||
|
|
||||||
|
@Component<QueryView>({
|
||||||
|
components: {
|
||||||
|
PostTeaser
|
||||||
|
},
|
||||||
|
beforeRouteEnter (to, from, next) {
|
||||||
|
console.log(to)
|
||||||
|
const { query, params } = to
|
||||||
|
|
||||||
|
api.post('/data/', {
|
||||||
|
q: query.q,
|
||||||
|
cond: params.tag ? {
|
||||||
|
tag: params.tag
|
||||||
|
} : undefined,
|
||||||
|
offset: (parseInt(params.page || '1') - 1) * 5,
|
||||||
|
limit: 5,
|
||||||
|
project: {
|
||||||
|
title: 1,
|
||||||
|
filename: 1,
|
||||||
|
excerpt: 1,
|
||||||
|
date: 1,
|
||||||
|
tag: 1
|
||||||
|
}
|
||||||
|
}).then(({ data }) => {
|
||||||
|
next((vm) => {
|
||||||
|
vm.posts = data.data
|
||||||
|
vm.count = data.count
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
beforeRouteUpdate ({ query, params }, from, next) {
|
||||||
|
api.post('/data/', {
|
||||||
|
q: query.q,
|
||||||
|
cond: params.tag ? {
|
||||||
|
tag: params.tag
|
||||||
|
} : undefined,
|
||||||
|
offset: (parseInt(params.page || '1') - 1) * 5,
|
||||||
|
limit: 5,
|
||||||
|
project: {
|
||||||
|
title: 1,
|
||||||
|
filename: 1,
|
||||||
|
excerpt: 1,
|
||||||
|
date: 1,
|
||||||
|
tag: 1
|
||||||
|
}
|
||||||
|
}).then(({ data }) => {
|
||||||
|
this.$set(this, 'posts', data.data)
|
||||||
|
this.$set(this, 'count', data.count)
|
||||||
|
next()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
export default class QueryView extends Vue {
|
||||||
|
posts: any[] = []
|
||||||
|
count: number = 0
|
||||||
|
|
||||||
|
get tag () {
|
||||||
|
return this.$route.params.tag
|
||||||
|
}
|
||||||
|
|
||||||
|
get page () {
|
||||||
|
return parseInt(this.$route.params.page || '1')
|
||||||
|
}
|
||||||
|
|
||||||
|
set page (page: number) {
|
||||||
|
const { tag } = this.$route.params
|
||||||
|
const { q } = this.$route.query
|
||||||
|
|
||||||
|
if (page > 1) {
|
||||||
|
this.$router.push({
|
||||||
|
path: (q || !tag) ? `/${page}` : `/tag/${tag}/${page}`,
|
||||||
|
query: {
|
||||||
|
q
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.$router.push({
|
||||||
|
path: (q || !tag) ? '/' : `/tag/${tag}`,
|
||||||
|
query: {
|
||||||
|
q
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get q () {
|
||||||
|
return normalizeArray(this.$route.query.q)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -2794,6 +2794,11 @@ dashdash@^1.12.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
assert-plus "^1.0.0"
|
assert-plus "^1.0.0"
|
||||||
|
|
||||||
|
dayjs@^1.8.21:
|
||||||
|
version "1.8.21"
|
||||||
|
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.8.21.tgz#98299185b72b9b679f31c7ed987b63923c961552"
|
||||||
|
integrity sha512-1kbWK0hziklUHkGgiKr7xm59KwAg/K3Tp7H/8X+f58DnNCwY3pKYjOCJpIlVs125FRBukGVZdKZojC073D0IeQ==
|
||||||
|
|
||||||
de-indent@^1.0.2:
|
de-indent@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
|
resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
|
||||||
|
|||||||
Reference in new issue
Block a user