浏览代码

feat: tags on page fetch + pageLinks table schema

Nick 5 年之前
父节点
当前提交
ab463fcae1

+ 3 - 3
client/themes/default/components/page.vue

@@ -77,11 +77,11 @@
                   label
                   color='teal lighten-5'
                   v-for='(tag, idx) in tags'
-                  :href='`/t/` + tag.slug'
-                  :key='tag.slug'
+                  :href='`/t/` + tag.tag'
+                  :key='tag.tag'
                   )
                   v-icon(color='teal', left, small) mdi-label
-                  span.teal--text.text--darken-2 {{tag.text}}
+                  span.teal--text.text--darken-2 {{tag.title}}
 
             v-card.mb-5
               .pa-5

+ 13 - 0
server/db/migrations-sqlite/2.0.0-beta.293.js

@@ -0,0 +1,13 @@
+exports.up = knex => {
+  return knex.schema
+    .createTable('pageLinks', table => {
+      table.increments('id').primary()
+      table.integer('sourcePageId').unsigned().references('id').inTable('pages').onDelete('CASCADE')
+      table.integer('targetPageId').unsigned().references('id').inTable('pages').onDelete('CASCADE')
+    })
+}
+
+exports.down = knex => {
+  return knex.schema
+    .dropTableIfExists('pageLinks')
+}

+ 19 - 0
server/db/migrations/2.0.0-beta.293.js

@@ -0,0 +1,19 @@
+/* global WIKI */
+
+exports.up = knex => {
+  const dbCompat = {
+    charset: (WIKI.config.db.type === `mysql` || WIKI.config.db.type === `mariadb`)
+  }
+  return knex.schema
+    .createTable('pageLinks', table => {
+      if (dbCompat.charset) { table.charset('utf8mb4') }
+      table.increments('id').primary()
+      table.integer('sourcePageId').unsigned().references('id').inTable('pages').onDelete('CASCADE')
+      table.integer('targetPageId').unsigned().references('id').inTable('pages').onDelete('CASCADE')
+    })
+}
+
+exports.down = knex => {
+  return knex.schema
+    .dropTableIfExists('pageLinks')
+}

+ 66 - 36
server/models/pages.js

@@ -63,6 +63,18 @@ module.exports = class Page extends Model {
           to: 'tags.id'
         }
       },
+      links: {
+        relation: Model.ManyToManyRelation,
+        modelClass: Page,
+        join: {
+          from: 'pages.id',
+          through: {
+            from: 'pageLinks.sourcePageId',
+            to: 'pageLinks.targetPageId'
+          },
+          to: 'pages.id'
+        }
+      },
       author: {
         relation: Model.BelongsToOneRelation,
         modelClass: require('./users'),
@@ -120,6 +132,12 @@ module.exports = class Page extends Model {
       publishEndDate: 'string',
       publishStartDate: 'string',
       render: 'string',
+      tags: [
+        {
+          tag: 'string',
+          title: 'string'
+        }
+      ],
       title: 'string',
       toc: 'string',
       updatedAt: 'string'
@@ -349,42 +367,53 @@ module.exports = class Page extends Model {
 
   static async getPageFromDb(opts) {
     const queryModeID = _.isNumber(opts)
-    return WIKI.models.pages.query()
-      .column([
-        'pages.*',
-        {
-          authorName: 'author.name',
-          authorEmail: 'author.email',
-          creatorName: 'creator.name',
-          creatorEmail: 'creator.email'
-        }
-      ])
-      .joinRelation('author')
-      .joinRelation('creator')
-      .where(queryModeID ? {
-        'pages.id': opts
-      } : {
-        'pages.path': opts.path,
-        'pages.localeCode': opts.locale
-      })
-      // .andWhere(builder => {
-      //   if (queryModeID) return
-      //   builder.where({
-      //     'pages.isPublished': true
-      //   }).orWhere({
-      //     'pages.isPublished': false,
-      //     'pages.authorId': opts.userId
-      //   })
-      // })
-      // .andWhere(builder => {
-      //   if (queryModeID) return
-      //   if (opts.isPrivate) {
-      //     builder.where({ 'pages.isPrivate': true, 'pages.privateNS': opts.privateNS })
-      //   } else {
-      //     builder.where({ 'pages.isPrivate': false })
-      //   }
-      // })
-      .first()
+    try {
+      return WIKI.models.pages.query()
+        .column([
+          'pages.*',
+          {
+            authorName: 'author.name',
+            authorEmail: 'author.email',
+            creatorName: 'creator.name',
+            creatorEmail: 'creator.email'
+          }
+        ])
+        .joinRelation('author')
+        .joinRelation('creator')
+        .eagerAlgorithm(Model.JoinEagerAlgorithm)
+        .eager('tags(selectTags)', {
+          selectTags: builder => {
+            builder.select('tag', 'title')
+          }
+        })
+        .where(queryModeID ? {
+          'pages.id': opts
+        } : {
+          'pages.path': opts.path,
+          'pages.localeCode': opts.locale
+        })
+        // .andWhere(builder => {
+        //   if (queryModeID) return
+        //   builder.where({
+        //     'pages.isPublished': true
+        //   }).orWhere({
+        //     'pages.isPublished': false,
+        //     'pages.authorId': opts.userId
+        //   })
+        // })
+        // .andWhere(builder => {
+        //   if (queryModeID) return
+        //   if (opts.isPrivate) {
+        //     builder.where({ 'pages.isPrivate': true, 'pages.privateNS': opts.privateNS })
+        //   } else {
+        //     builder.where({ 'pages.isPrivate': false })
+        //   }
+        // })
+        .first()
+    } catch (err) {
+      WIKI.logger.warn(err)
+      throw err
+    }
   }
 
   static async savePageToCache(page) {
@@ -402,6 +431,7 @@ module.exports = class Page extends Model {
       publishEndDate: page.publishEndDate,
       publishStartDate: page.publishStartDate,
       render: page.render,
+      tags: page.tags.map(t => _.pick(t, ['tag', 'title'])),
       title: page.title,
       toc: _.isString(page.toc) ? page.toc : JSON.stringify(page.toc),
       updatedAt: page.updatedAt

+ 1 - 1
server/views/page.pug

@@ -13,7 +13,7 @@ block body
       path=page.path
       title=page.title
       description=page.description
-      tags=page.tags
+      :tags=page.tags
       created-at=page.createdAt
       updated-at=page.updatedAt
       author-name=page.authorName