xiongzhu 2 سال پیش
والد
کامیت
20779c93f7

+ 31 - 5
app/Controllers/Http/OrdersController.ts

@@ -2,7 +2,7 @@ import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
 import Order from 'App/Models/Order'
 import PaginationService from 'App/Services/PaginationService'
 import { schema } from '@ioc:Adonis/Core/Validator'
-import { BadRequestException, InternalServerException } from 'App/Exceptions/Common'
+import { BadRequestException } from 'App/Exceptions/Common'
 import Series from 'App/Models/Series'
 import Episode from 'App/Models/Episode'
 import UserBalanceService from 'App/Services/UserBalanceService'
@@ -11,8 +11,34 @@ import { BalanceRecordType } from 'App/Models/BalanceRecord'
 
 export default class OrdersController {
     private paginationService = new PaginationService(Order)
-    public async index({ request }: HttpContextContract) {
-        return await this.paginationService.paginate(request.all())
+    public async index({ request, auth }: HttpContextContract) {
+        const page = await this.paginationService.paginate({
+            ...request.all(),
+            userId: auth.user!.id
+        })
+        const seriesIds = new Set(
+            page
+                .all()
+                .map((record) => record.seriesId)
+                .filter((id) => !!id)
+        )
+        const series = await Series.findMany(Array.from(seriesIds))
+        const episodeIds = new Set(
+            page
+                .all()
+                .map((record) => record.episodeId)
+                .filter((id) => !!id)
+        )
+        const episodes = await Episode.findMany(Array.from(episodeIds))
+        page.all().forEach((record) => {
+            if (record.seriesId) {
+                record.series = series.find((s) => s.id === record.seriesId)
+            }
+            if (record.episodeId) {
+                record.episode = episodes.find((e) => e.id === record.episodeId)
+            }
+        })
+        return page
     }
 
     public async store({ request, auth }: HttpContextContract) {
@@ -38,14 +64,14 @@ export default class OrdersController {
         if (data.seriesId) {
             const series = await Series.findOrFail(data.seriesId)
             if (series.price.comparedTo(userBalance.balance) > 0) {
-                throw new InternalServerException('not enough balance')
+                throw new Error('not enough balance')
             }
             data.price = series.price
             data.type = BalanceRecordType.Purchase
         } else {
             const episode = await Episode.findOrFail(data.episodeId)
             if (episode.price.comparedTo(userBalance.balance) > 0) {
-                throw new InternalServerException('not enough balance')
+                throw new Error('not enough balance')
             }
             data.seriesId = episode.seriesId
             data.price = episode.price

+ 53 - 0
app/Controllers/Http/SignInRecordsController.ts

@@ -0,0 +1,53 @@
+import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
+import SignInRecord from 'App/Models/SignInRecord'
+import { DateTime } from 'luxon'
+import { addDays, format } from 'date-fns'
+import Decimal from 'decimal.js'
+import UserBalanceService from 'App/Services/UserBalanceService'
+import { BalanceRecordType } from 'App/Models/BalanceRecord'
+
+export default class SignInRecordsController {
+    public async index({ auth }: HttpContextContract) {
+        const start = addDays(new Date(), -1)
+        const end = addDays(new Date(), 6)
+        const records = await SignInRecord.query()
+            .where('date', '>=', start)
+            .where('date', '<=', end)
+            .where('user_id', auth.user!.id)
+        const res: any[] = []
+        for (let i = 0; i < 7; i++) {
+            const date = addDays(start, i)
+            const record = records.find(
+                (record) => record.date.toISODate() === DateTime.fromJSDate(date).toISODate()
+            )
+            res.push({
+                date: format(date, 'yyyy-MM-dd'),
+                reward: record?.reward ?? new Decimal(10),
+                isSigned: !!record
+            })
+        }
+        return res
+    }
+
+    public async store({ request, auth }: HttpContextContract) {
+        const record = await SignInRecord.query()
+            .where('date', DateTime.now().toISODate())
+            .where('user_id', auth.user!.id)
+            .first()
+        if (record) {
+            throw new Error('今天已经签到过了')
+        }
+        const signInRecord = await SignInRecord.create({
+            date: DateTime.now(),
+            userId: auth.user!.id,
+            reward: new Decimal(10)
+        })
+        await UserBalanceService.modifiyBalance({
+            userId: auth.user!.id,
+            amount: signInRecord.reward,
+            type: BalanceRecordType.Reward,
+            description: '签到奖励'
+        })
+        return signInRecord
+    }
+}

+ 2 - 24
app/Models/BalanceRecord.ts

@@ -47,31 +47,9 @@ export default class BalanceRecord extends AppBaseModel {
     @column()
     public episodeId?: number
 
-    private _series?: Series
-
-    private _episode?: Episode
-
     @computed()
-    public get series(): Series | undefined {
-        if (this._series) {
-            return this._series
-        }
-        return undefined
-    }
-
-    public set series(series: Series | undefined) {
-        this._series = series
-    }
+    public series?: Series
 
     @computed()
-    public get episode(): Episode | undefined {
-        if (this._episode) {
-            return this._episode
-        }
-        return undefined
-    }
-
-    public set episode(episode: Episode | undefined) {
-        this._episode = episode
-    }
+    public episode?: Episode
 }

+ 9 - 1
app/Models/Order.ts

@@ -1,8 +1,10 @@
 import { DateTime } from 'luxon'
-import { column } from '@ioc:Adonis/Lucid/Orm'
+import { column, computed } from '@ioc:Adonis/Lucid/Orm'
 import { decimalConverter } from 'App/Helpers/db'
 import Decimal from 'decimal.js'
 import AppBaseModel from './AppBaseModel'
+import Series from 'App/Models/Series'
+import Episode from 'App/Models/Episode'
 
 export default class Order extends AppBaseModel {
     @column({ isPrimary: true })
@@ -28,4 +30,10 @@ export default class Order extends AppBaseModel {
 
     @column()
     public episodeId: number
+
+    @computed()
+    public series?: Series
+
+    @computed()
+    public episode?: Episode
 }

+ 24 - 0
app/Models/SignInRecord.ts

@@ -0,0 +1,24 @@
+import { decimalConverter } from 'App/Helpers/db'
+import { DateTime } from 'luxon'
+import { BaseModel, column } from '@ioc:Adonis/Lucid/Orm'
+import Decimal from 'decimal.js'
+
+export default class SignInRecord extends BaseModel {
+    @column({ isPrimary: true })
+    public id: number
+
+    @column.dateTime({ autoCreate: true })
+    public createdAt: DateTime
+
+    @column.dateTime({ autoCreate: true, autoUpdate: true })
+    public updatedAt: DateTime
+
+    @column.date()
+    public date: DateTime
+
+    @column()
+    public userId: number
+
+    @column({ ...decimalConverter })
+    public reward: Decimal
+}

+ 22 - 0
database/migrations/1701418847822_sign_in_records.ts

@@ -0,0 +1,22 @@
+import BaseSchema from '@ioc:Adonis/Lucid/Schema'
+
+export default class extends BaseSchema {
+    protected tableName = 'sign_in_records'
+
+    public async up() {
+        this.schema.createTable(this.tableName, (table) => {
+            table.increments('id')
+            table.datetime('created_at', { useTz: true })
+            table.datetime('updated_at', { useTz: true })
+            table.date('date').notNullable()
+            table.integer('user_id').unsigned().references('users.id').onDelete('CASCADE')
+            table.decimal('reward', 19, 4).notNullable()
+
+            table.unique(['date', 'user_id'])
+        })
+    }
+
+    public async down() {
+        this.schema.dropTable(this.tableName)
+    }
+}

+ 1 - 0
package.json

@@ -72,6 +72,7 @@
         "@aws-sdk/client-s3": "^3.458.0",
         "@aws-sdk/client-sts": "^3.458.0",
         "ali-oss": "^6.18.1",
+        "date-fns": "^2.30.0",
         "decimal.js": "^10.4.3",
         "lockfile": "^1.0.4",
         "luxon": "^3.4.4",

+ 1 - 0
start/routes.ts

@@ -88,5 +88,6 @@ Route.group(() => {
         Route.group(() => {
             Route.get('report', 'PlayHistoriesController.report')
         }).prefix('playHistories')
+        Route.resource('signInRecords', 'SignInRecordsController').apiOnly()
     }).middleware('auth:api')
 }).prefix('/api')

+ 3 - 1
tsconfig.json

@@ -34,6 +34,8 @@
       "@adonisjs/bouncer",
       "@adonisjs/drive-s3",
       "@adonisjs/ally"
-    ]
+    ],
+    "noUnusedParameters": false,
+    "noUnusedLocals": false
   }
 }

+ 19 - 0
yarn.lock

@@ -1246,6 +1246,13 @@
   dependencies:
     tslib "^2.5.0"
 
+"@babel/runtime@^7.21.0":
+  version "7.23.5"
+  resolved "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.23.5.tgz#11edb98f8aeec529b82b211028177679144242db"
+  integrity sha512-NdUTHcPe4C99WxPub+K9l9tK5/lV4UXIoaHSYgzco9BCyjKAAwzdBI+wWtYqHt7LJdbo74ZjRPJgzVweq1sz0w==
+  dependencies:
+    regenerator-runtime "^0.14.0"
+
 "@colors/colors@1.5.0":
   version "1.5.0"
   resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
@@ -3326,6 +3333,13 @@ data-uri-to-buffer@^2.0.0:
   resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz#d296973d5a4897a5dbe31716d118211921f04770"
   integrity sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==
 
+date-fns@^2.30.0:
+  version "2.30.0"
+  resolved "https://registry.npmmirror.com/date-fns/-/date-fns-2.30.0.tgz#f367e644839ff57894ec6ac480de40cae4b0f4d0"
+  integrity sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==
+  dependencies:
+    "@babel/runtime" "^7.21.0"
+
 dateformat@^2.0.0:
   version "2.2.0"
   resolved "https://registry.npmmirror.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062"
@@ -6179,6 +6193,11 @@ reflect-metadata@^0.1.13:
   resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08"
   integrity sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==
 
+regenerator-runtime@^0.14.0:
+  version "0.14.0"
+  resolved "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz#5e19d68eb12d486f797e15a3c6a918f7cec5eb45"
+  integrity sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==
+
 regex-not@^1.0.0, regex-not@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c"