@quicktvui/tv-ad-unlock 1.1.1 → 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,13 +1,13 @@
1
1
  # @quicktvui/tv-ad-unlock
2
2
 
3
- TV广告解锁组件,用于QuickTVUI框架的电视端广告解锁功能。
3
+ TV 广告解锁组件 — 用于 QuickTVUI 框架的电视端广告解锁功能。
4
4
 
5
5
  ## 功能特性
6
6
 
7
- - 生成电视端广告二维码
8
- - 轮询广告观看状态
9
- - 自动管理解锁状态
10
- - 支持自定义配置
7
+ - 电视端扫码观看广告,自动解锁
8
+ - 内置广告弹窗页面(二维码 + 状态展示)
9
+ - 积分信用体系(每日解锁 / 永久解锁 / 按次扣费)
10
+ - 通过 Vue 插件注册,零配置路由
11
11
 
12
12
  ## 安装
13
13
 
@@ -15,139 +15,215 @@ TV广告解锁组件,用于QuickTVUI框架的电视端广告解锁功能。
15
15
  pnpm add @quicktvui/tv-ad-unlock
16
16
  ```
17
17
 
18
- ## 使用方法
18
+ **Peer Dependencies**(需项目已安装):
19
19
 
20
- ### 1. 基础使用
20
+ - `vue ^3.0.0`
21
+ - `@extscreen/es3-core >=3.0.0`
22
+ - `@extscreen/es3-router >=3.0.0`
21
23
 
22
- ```vue
23
- <template>
24
- <TVAdUnlock
25
- :config="adConfig"
26
- :storageKeys="storageKeys"
27
- :requestManager="requestManager"
28
- @unlockSuccess="onUnlockSuccess"
29
- @unlockFailed="onUnlockFailed"
30
- />
31
- </template>
32
-
33
- <script setup lang="ts">
34
- import { TVAdUnlock, useTVAdUnlockStorage } from '@quicktvui/tv-ad-unlock'
35
- import type { TVAdUnlockConfig, TVAdUnlockStorageKeys, RequestManager } from '@quicktvui/tv-ad-unlock'
36
-
37
- const adConfig: TVAdUnlockConfig = {
38
- packageName: 'com.example.app',
39
- superRequestBaseUrl: 'https://superapi.extscreen.com/extscreenapi/api',
40
- invalidTimeout: 300000,
41
- pollInterval: 1000
42
- }
24
+ ## 快速开始
43
25
 
44
- const storageKeys: TVAdUnlockStorageKeys = {
45
- playCountKey: 'app_play_count',
46
- unlockDateKey: 'app_ad_unlock_date',
47
- unlockedTodayKey: 'app_ad_unlocked_today'
48
- }
26
+ ### 1. 注册插件 & 路由(main-native.ts)
49
27
 
50
- const requestManager: RequestManager = {
51
- post: async (url, data) => { /* 实现请求逻辑 */ },
52
- get: async (url, data) => { /* 实现请求逻辑 */ }
53
- }
28
+ ```typescript
29
+ import { createESRouter } from '@extscreen/es3-router'
30
+ import { createESApp } from '@extscreen/es3-core'
31
+ import { tvAdUnlockPlugin, createTVAdRoute } from '@quicktvui/tv-ad-unlock'
32
+ import routes from './routes'
33
+
34
+ // 将广告路由加入路由表
35
+ const adRoute = createTVAdRoute()
36
+ routes.push({ ...adRoute, launchMode: 'standard' })
37
+
38
+ const router = createESRouter({ main: 'index', error: 'error', limit: 10, routes })
39
+ const app = createESApp(App, router)
40
+
41
+ // 注册广告解锁插件
42
+ app.use(tvAdUnlockPlugin, {
43
+ packageName: 'com.example.myapp', // 必填,应用包名,用于存储 key 隔离
44
+ requestManager: myRequestManager, // 必填,实现 post/get 的请求管理器
45
+ // superRequestBaseUrl: 'https://superapi.extscreen.com/extscreenapi/api', // 可选,这是默认值
46
+ pageConfig: {
47
+ scanTitle: '观看广告获得积分',
48
+ scanContent: '观看广告后可获得5积分,用于游戏提示',
49
+ scanToast: '积分已发放,请返回游戏'
50
+ }
51
+ })
52
+ ```
54
53
 
55
- function onUnlockSuccess() {
56
- console.log('解锁成功')
57
- }
54
+ ### 2. 在页面中使用(页面 setup 中调用)
58
55
 
59
- function onUnlockFailed(error: Error) {
60
- console.error('解锁失败', error)
61
- }
56
+ ```vue
57
+ <script lang="ts">
58
+ import { defineComponent } from 'vue'
59
+ import { useTVAdNavigator } from '@quicktvui/tv-ad-unlock'
60
+
61
+ export default defineComponent({
62
+ setup() {
63
+ const adNavigator = useTVAdNavigator({
64
+ packageName: 'com.example.myapp',
65
+ initialCredits: 0, // 初始积分(默认 5)
66
+ creditsPerAd: 5, // 每次看广告获得积分(默认 5)
67
+ dailyUnlockEnabled: true, // 每日解锁开关(默认 true)
68
+ permanentUnlockAfterTotalAds: 10 // 看满N次广告永久解锁(默认 10,设0关闭)
69
+ })
70
+
71
+ // 在需要弹广告的地方调用
72
+ async function onNeedFeature() {
73
+ const showedAd = await adNavigator.consumeAndNavigate()
74
+ if (!showedAd) {
75
+ // 未弹广告(有积分或已解锁),直接执行业务逻辑
76
+ }
77
+ // showedAd === true 表示已跳转广告页,广告观看完成后会自动返回
78
+ }
79
+
80
+ return { onNeedFeature }
81
+ }
82
+ })
62
83
  </script>
63
84
  ```
64
85
 
65
- ### 2. 使用 Composable
86
+ ## API 参考
66
87
 
67
- ```typescript
68
- import { useTVAdUnlock, useTVAdUnlockStorage } from '@quicktvui/tv-ad-unlock'
69
- import { useESLocalStorage } from '@extscreen/es3-core'
88
+ ### 插件选项 `TVAdUnlockPluginOptions`
70
89
 
71
- const storage = useESLocalStorage()
90
+ `app.use(tvAdUnlockPlugin, options)` 的第二个参数:
72
91
 
73
- const storageKeys = {
74
- playCountKey: 'app_play_count',
75
- unlockDateKey: 'app_ad_unlock_date',
76
- unlockedTodayKey: 'app_ad_unlocked_today'
77
- }
92
+ | 字段 | 类型 | 必填 | 默认值 | 说明 |
93
+ |------|------|------|--------|------|
94
+ | `packageName` | `string` | 是 | - | 应用包名,用于存储 key 隔离 |
95
+ | `requestManager` | `RequestManager` | 是 | - | 请求管理器,需实现 `post` 和 `get` |
96
+ | `superRequestBaseUrl` | `string` | 否 | `https://superapi.extscreen.com/extscreenapi/api` | 广告接口基地址 |
97
+ | `pageConfig` | `TVAdUnlockPageConfig` | 否 | 见下方 | 广告弹窗页面 UI 文案配置 |
98
+ | `trackEvent` | `(event) => void` | 否 | - | 埋点回调 |
78
99
 
79
- const adStorage = useTVAdUnlockStorage(storage, storageKeys, 32)
100
+ ### 页面文案配置 `TVAdUnlockPageConfig`
80
101
 
81
- async function checkNeedShowAd() {
82
- const needAd = await adStorage.checkNeedAd()
83
- if (needAd) {
84
- router.push({ name: 'ad' })
85
- }
86
- }
102
+ | 字段 | 默认值 | 说明 |
103
+ |------|--------|------|
104
+ | `title` | `'观看30秒广告 当日解锁'` | 弹窗标题 |
105
+ | `subTitle` | `'手机打开【微信】扫码'` | 弹窗副标题 |
106
+ | `scanTitle` | `'观看奖励'` | 手机端扫码页标题 |
107
+ | `scanContent` | `'观看广告后可获得奖励'` | 手机端扫码页内容 |
108
+ | `scanToast` | `'奖励已获得,请前往电视端观看'` | 手机端观看后提示 |
109
+ | `invalidCodeImage` | 内置图片 | 二维码失效时展示的图片 URL |
110
+ | `scannedCodeImage` | 内置图片 | 已扫码状态展示的图片 URL |
111
+
112
+ ### 路由配置 `createTVAdRoute()`
113
+
114
+ 返回一条广告弹窗路由对象,需推入路由表:
115
+
116
+ ```typescript
117
+ const adRoute = createTVAdRoute()
118
+ // 返回: { path: '/ad', name: 'ad', component: TVAdUnlockView, type: 1 }
119
+ routes.push({ ...adRoute, launchMode: 'standard' })
87
120
  ```
88
121
 
89
- ### 3. 路由配置
122
+ ### 导航器 `useTVAdNavigator(config)`
123
+
124
+ 在页面 `setup()` 中调用,按规则自动判断是否需要弹广告:
90
125
 
91
126
  ```typescript
92
- import { ESRouteType } from '@extscreen/es3-router'
93
-
94
- const routes = [
95
- {
96
- path: '/ad',
97
- name: 'ad',
98
- component: () => import('./views/ad/index.vue'),
99
- type: ESRouteType.ES_ROUTE_TYPE_DIALOG
100
- }
101
- ]
127
+ const adNavigator = useTVAdNavigator({
128
+ packageName: string // 必填,应用包名
129
+ initialCredits?: number // 初始积分,默认 5
130
+ creditsPerAd?: number // 每次广告获得积分,默认 5
131
+ dailyUnlockEnabled?: boolean // 每日解锁,默认 true
132
+ permanentUnlockAfterTotalAds?: number // 永久解锁阈值,默认 10
133
+ })
102
134
  ```
103
135
 
104
- ## API
136
+ **判断规则(按优先级)**:
105
137
 
106
- ### Props
138
+ 1. 永久解锁 → 放行(不弹广告)
139
+ 2. 今日已解锁 → 放行
140
+ 3. 积分 > 0 → 扣 1 分,放行
141
+ 4. 兜底 → 跳转广告页
107
142
 
108
- | 属性 | 类型 | 必填 | 默认值 | 说明 |
109
- |------|------|------|--------|------|
110
- | config | TVAdUnlockConfig | 是 | - | 广告配置 |
111
- | storageKeys | TVAdUnlockStorageKeys | 是 | - | 存储键名配置 |
112
- | requestManager | RequestManager | 是 | - | 请求管理器 |
113
- | title | string | 否 | '观看30秒广告 当日解锁' | 标题文字 |
114
- | subTitle | string | 否 | '手机打开【微信】扫码' | 副标题文字 |
115
- | invalidCodeImage | string | 否 | '' | 二维码失效图片 |
116
- | scannedCodeImage | string | 否 | '' | 已扫码图片 |
117
- | scanTitle | string | 否 | '观看奖励' | 扫码标题 |
118
- | scanContent | string | 否 | '观看广告后可获得奖励' | 扫码内容 |
119
- | scanToast | string | 否 | '奖励已获得,请前往电视端观看' | 扫码提示 |
120
-
121
- ### Events
122
-
123
- | 事件名 | 参数 | 说明 |
124
- |--------|------|------|
125
- | unlockSuccess | - | 解锁成功 |
126
- | unlockFailed | error: Error | 解锁失败 |
127
- | qrCodeInvalid | - | 二维码失效 |
128
- | qrCodeScanned | - | 二维码已扫码 |
129
-
130
- ### Types
143
+ **返回方法**:
131
144
 
132
- ```typescript
133
- interface TVAdUnlockConfig {
134
- packageName: string
135
- superRequestBaseUrl: string
136
- trackBaseUrl?: string
137
- invalidTimeout?: number
138
- pollInterval?: number
139
- }
145
+ | 方法 | 返回类型 | 说明 |
146
+ |------|----------|------|
147
+ | `consumeAndNavigate()` | `Promise<boolean>` | 核心方法。返回 `true` 表示已跳转广告页,`false` 表示放行 |
148
+ | `consume(amount)` | `Promise<{success, consumed}>` | 手动扣减指定积分 |
149
+ | `consumeAll()` | `Promise<number>` | 扣减全部积分,返回扣减值 |
150
+ | `addCredits(amount)` | `Promise<void>` | 增加积分 |
151
+ | `getCredits()` | `Promise<number>` | 查询当前积分 |
152
+ | `isPermanentlyUnlocked()` | `Promise<boolean>` | 是否已永久解锁 |
153
+ | `getTodayAdCount()` | `Promise<number>` | 今日已看广告次数 |
140
154
 
141
- interface TVAdUnlockStorageKeys {
142
- playCountKey: string
143
- unlockDateKey: string
144
- unlockedTodayKey: string
145
- }
155
+ ### 存储管理 `useTVAdUnlockStorage(storage, keys, initialCredits?)`
156
+
157
+ 底层存储操作,一般不直接使用。高级场景可通过 `createStorageKeys(packageName)` 生成 key 集合后手动操作。
158
+
159
+ ### 类型定义
146
160
 
161
+ ```typescript
147
162
  interface RequestManager {
148
163
  post(url: string, data: Record<string, any>): Promise<any>
149
164
  get(url: string, data: string): Promise<any>
150
165
  }
166
+
167
+ interface TVAdUnlockTrackEvent {
168
+ type: 'page' | 'click'
169
+ name: string
170
+ assetId?: string
171
+ assetName?: string
172
+ fromId?: string
173
+ fromName?: string
174
+ }
175
+ ```
176
+
177
+ ## 完整示例
178
+
179
+ ```typescript
180
+ // main-native.ts
181
+ import { tvAdUnlockPlugin, createTVAdRoute } from '@quicktvui/tv-ad-unlock'
182
+ import { createRequestManager } from './api/request/RequestManager'
183
+ import routes from './routes'
184
+
185
+ const adRoute = createTVAdRoute()
186
+ routes.push({ ...adRoute, launchMode: 'standard' })
187
+
188
+ const requestManager = createRequestManager()
189
+ app.use(tvAdUnlockPlugin, {
190
+ packageName: 'com.example.app',
191
+ requestManager,
192
+ pageConfig: {
193
+ title: '观看广告 解锁功能',
194
+ scanTitle: '观看广告获得积分',
195
+ scanContent: '观看广告后可获得5积分',
196
+ scanToast: '积分已发放,请返回游戏'
197
+ }
198
+ })
199
+ ```
200
+
201
+ ```vue
202
+ <!-- 页面中使用 -->
203
+ <script lang="ts">
204
+ import { defineComponent } from 'vue'
205
+ import { useTVAdNavigator } from '@quicktvui/tv-ad-unlock'
206
+
207
+ export default defineComponent({
208
+ setup() {
209
+ const adNavigator = useTVAdNavigator({
210
+ packageName: 'com.example.app',
211
+ initialCredits: 0,
212
+ creditsPerAd: 5
213
+ })
214
+
215
+ function onShowHint() {
216
+ adNavigator.consumeAndNavigate().then(showedAd => {
217
+ if (!showedAd) {
218
+ // 直接显示提示
219
+ }
220
+ })
221
+ }
222
+
223
+ return { onShowHint }
224
+ }
225
+ })
226
+ </script>
151
227
  ```
152
228
 
153
229
  ## License
@@ -0,0 +1,4 @@
1
+ import type { InjectionKey } from 'vue';
2
+ import type { TVAdUnlockPluginProvided } from './types';
3
+ export declare const TV_AD_UNLOCK_KEY: InjectionKey<TVAdUnlockPluginProvided>;
4
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,KAAK,CAAA;AACvC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAA;AAEvD,eAAO,MAAM,gBAAgB,EAAE,YAAY,CAAC,wBAAwB,CAAwB,CAAA"}