次卡+道具卡 道具卡不生效

This commit is contained in:
win 2026-02-27 20:57:24 +08:00
parent 4fe3ecb571
commit 16076f2eb8
102 changed files with 154 additions and 206 deletions

0
.gitignore vendored Normal file → Executable file
View File

View File

@ -1,46 +0,0 @@
## 接口梳理App 用户相关)
- 登录与绑定:
- `POST /api/app/users/weixin/login`,请求含 `code``invite_code`;响应含 `token``user_id``avatar``nickname``invite_code`.trae/documents/基于 Swagger 的 App 用户 API 汇总与 Uni-App 微信登录页面实现方案.md:5-10
- `POST /api/app/users/{user_id}/phone/bind`,请求含微信手机号 `code`;响应为标准成功(.trae/documents/基于 Swagger 的 App 用户 API 汇总与 Uni-App 微信登录页面实现方案.md:11-16
- 用户资料与地址:
- `PUT /api/app/users/{user_id}`(修改头像/昵称,`avatar``nickname`:19-22
- 地址列表/新增/删除/设默认(`:23-27`),新增请求含基本地址字段(`:25-27`
- 积分与统计:
- `GET /api/app/users/{user_id}/points/balance` 响应 `balance``:31-34`
- `GET /api/app/users/{user_id}/stats` 响应 `coupon_count``item_card_count``points_balance``:35-37`
- 订单与卡券/道具:
- 订单列表、优惠券、邀请、道具卡与使用记录(`:40-48`
## 技术方案
- 网络层:
- 方案A推荐复用 `alova` 客户端与生成器,统一 `Authorization` 与错误处理(`:51`
- 方案B 以 `uni.request` 封装最小所需接口(登录/绑定/统计),在请求头注入 `Bearer` token`:71-72`
- 平台与配置:
- `baseURL` 指向后端 `http://127.0.0.1:9991`;在微信小程序后台配置合法域名与 HTTPS 证书(`:75`
- 状态与路由:
- `pages.json` 添加 `pages/login/index`;登录成功后 `uni.reLaunch` 到首页;用 `pinia` 管理 `isLogin``userInfo``points``:79`
- 错误处理:
- 按既有分类提示与重试策略覆盖网络错误、超时、404/500、参数错误`:83`
## 页面实现Uni-App Vue3
- 结构Logo/说明、`「微信登录」`按钮、`open-type="getPhoneNumber"` 授权按钮、加载与错误提示(`:57-58`
- 流程:
- 触发 `uni.login({ provider: 'weixin' })` 获取 `code` → 调用 `POST /api/app/users/weixin/login` → 持久化 `token``user_id``:61-62`
- 可选手机号绑定:`onGetPhoneNumber``code``POST /api/app/users/{user_id}/phone/bind``:63-64`
- 登录后拉取统计与积分余额更新首页(`:65-66`
## 交付内容
- 新增 `pages/login/index.vue`Composition API含完整登录/绑定流程与错误提示(`:91-94`
- 接入并配置网络层(复用 `alova` 或最小 `uni.request` 封装)
- 路由与 `pinia` 状态的最小接入
## 验证方法
- 在开发者工具/真机验证:`code` 获取、接口返回、`token/user_id` 存储、后续接口成功(`:87-88`
- 输出必要的调试日志(不含敏感信息),观察错误分支与重试入口
## 执行步骤
1. 接入 Swagger JSON`http://127.0.0.1:9991/swagger/v1/swagger.json`)同步生成或确认接口(`:99-101`
2. 选定网络层方案并落地调用
3. 新增登录页面与交互逻辑
4. 调整路由与状态管理
5. 自测与联调,完成交付

View File

@ -1,102 +0,0 @@
## API 文档汇总App 用户相关)
* 登录与绑定:
* `POST /api/app/users/weixin/login`miniapp/src/api/apis/apiDefinitions.js:106
* 请求: `App_weixin_login_request`code、invite\_code可选
* 响应: `App_weixin_login_response`token、user\_id、avatar、nickname、invite\_codeminiapp/src/api/apis/globals.d.ts:760
* `POST /api/app/users/{user_id}/phone/bind`apiDefinitions.js:123
* 请求: `App_bind_phone_request`code来源于微信手机号授权globals.d.ts:376
* 响应: 成功布尔或标准成功结构(项目统一在 `responded` 钩子返回 `response.data``response.data.data`miniapp/src/api/apis/index.js:59
* 用户资料与地址:
* `PUT /api/app/users/{user_id}` 修改头像/昵称apiDefinitions.js:107
* 请求: `App_modify_user_request`avatar、nickname可选globals.d.ts:363
* `GET /api/app/users/{user_id}/addresses` 列表apiDefinitions.js:108/ `POST` 新增apiDefinitions.js:109/ `DELETE` 删除apiDefinitions.js:110/ `PUT .../default` 设默认apiDefinitions.js:114
* 新增请求: `App_add_address_request`姓名、手机号、省市区、详细地址、是否默认globals.d.ts:367
* 响应: 列表返回数组,新增/删除/设默认返回标准成功结构(项目统一 `responded` 处理)
* 积分与统计:
* `GET /api/app/users/{user_id}/points`apiDefinitions.js:124/ `GET .../points/balance`apiDefinitions.js:125
* 响应: `App_points_balance_response`balanceglobals.d.ts:773
* `GET /api/app/users/{user_id}/stats`apiDefinitions.js:126
* 响应: `App_user_stats_response`coupon\_count、item\_card\_count、points\_balanceglobals.d.ts:776
* 订单与卡券/道具:
* `GET /api/app/users/{user_id}/orders`apiDefinitions.js:122→ 订单列表(类型包含 `Model_order_items` 等)
* `GET /api/app/users/{user_id}/coupons`apiDefinitions.js:118/ `GET .../invites`apiDefinitions.js:119
* `GET /api/app/users/{user_id}/item_cards`apiDefinitions.js:120/ `GET .../item_cards/uses`apiDefinitions.js:121
* 响应: `User_item_card_with_template[]`globals.d.ts:978
## 现有代码要点(可复用)
* API 客户端:`alova` + 生成器miniapp/src/api/apis/index.js:35、112miniapp/alova.config.js:6已封装 `Authorization`、401 刷新登录index.js:9-33
* 登录页Taro版`miniapp/src/pages/login/index.vue`,逻辑封装在 `Apis.login.WechatAppLogin`index.js:122-421
## 登录页面实现Uni-App Vue3
* 页面结构Logo/说明文案、按钮`「微信登录」``open-type="getPhoneNumber"`的手机号授权按钮,加载与错误提示。
* 流程:
* `uni.login({ provider: 'weixin' })` 获取 `code` → 调用 `POST /api/app/users/weixin/login` → 存储 `token``user_id``uni.setStorageSync`
* 可选:用户点击手机号授权后触发 `onGetPhoneNumber`,拿到 `code` 调用 `POST /api/app/users/{user_id}/phone/bind` 绑定手机号。
* 登录完成后拉取 `GET /api/app/users/{user_id}/stats``.../points/balance` 更新首页状态。
* 网络层:
* 方案A推荐复用现有在 Uni-App 中引入与复用 `alova` 生成的 `Apis`(保持统一的拦截器与基址、响应处理)。
* 方案B轻量使用 `uni.request` 封装最小调用(登录/绑定/统计),按现有 `Authorization: Bearer <token>` 规则注入。
* 配置与安全:
* `baseURL` 指向后端地址(如 `http://127.0.0.1:9991`),并在微信小程序后台配置合法域名/证书;避免在日志中输出明文 token/手机号等敏感信息。
* 路由与状态:
* 在 `pages.json` 新增 `pages/login/index`,登录成功后 `uni.reLaunch` 到首页;使用 `pinia` 存储 `isLogin``userInfo``points` 等(参考 miniapp/src/store/index.js
* 错误处理:
* 按当前项目的分类提示连接被拒绝、超时、域名未配置、SSL 错误、404、500、参数错误进行用户级文案与重试入口参考 index.js:221-253
## 验证与交付
* 验证:真机或开发者工具下,观察 `code` 获取、接口返回、`token/user_id` 存储与后续接口成功;埋点或日志控制台输出关键步骤。
* 交付:
* 新增 `pages/login/index.vue`Uni-App Vue3 Composition API 实现)。
* 复用或新增 API 封装A/B 二选一)。
* 配置/路由调整与最小 `pinia` 状态接入。
## 后续执行步骤
* 接入 Swagger 源:将生成器输入指向 `http://127.0.0.1:9991/swagger/v1/swagger.json`(或项目后端的 Swagger JSON生成/更新 `Apis` 并对齐 `baseURL`
* 按上述方案完成页面与调用接入,并保持与现有 `alova` 响应处理一致性。

View File

@ -1,35 +0,0 @@
## 目标
- 首页 UI 始终可见轮播图在无数据时也显示占位滑块通知始终滚动显示Marquee
- 接口路径统一为 `/api/app/*`,兼容返回 `{list: [...]}` 与字段 `snake_case`(如 `image_url`)。
## 变更范围
- 文件:`pages/index/index.vue`
- 保留现有登录弹窗,但不阻断首页数据加载;完善数据清洗与空态展示。
## 轮播图(无数据也展示)
- 始终渲染 `swiper.banner-swiper`,不再用 `v-if` 隐藏容器。
- 数据存在:按 `banners` 渲染;字段映射 `id``image_url|imageUrl|image``link_url|linkUrl|link|url`
- 数据为空:渲染 3 个占位滑块(`swiper-item` 内用 `<view>` 纯色/渐变背景 + 文案“敬请期待”),避免依赖静态图片资源。
- URL 清洗:移除反引号与空格,保证 `image_url` 可用。
## 通知滚动Marquee
- 始终渲染通知条。
- 有数据横向无缝滚动CSS `@keyframes` + `transform: translateX`),将所有通知拼接为一条长文本,重复一份以实现循环滚动。
- 无数据:使用默认文案(如“欢迎光临”“最新活动敬请期待”)参与滚动,保证始终有动效。
## 活动区
- 保持当前两列栅格布局;无数据时显示“暂无活动”占位文案;点击仅在 `link` 为内部路径时跳转。
## 数据与接口
- 请求入口统一:`/api/app/notices``/api/app/banners``/api/app/activities`
- 解包:支持 `list|items|data`
- 映射:通知 `content|text|title`;轮播图 `image_url|imageUrl|image|img|pic``link_url|linkUrl|link|url`;活动 `cover_url|coverUrl|image|img|pic``title|name``sub_title|subTitle|subtitle|desc|description`
## 交互与空态
- 未登录/未绑定:弹窗提醒,但首页照常加载并显示占位内容。
- 点击跳转:内部路径以 `/` 开头才触发 `navigateTo`;避免空链接导致错误。
## 验证
- 模拟后端返回 `{list:[...]}` 含反引号的 `image_url`,确认轮播图正常显示。
- 清空 `banners``notices`,确认占位滑块与默认滚动文案显示。
- 在微信小程序/浏览器预览,验证滚动流畅度与样式适配。

0
App.vue Normal file → Executable file
View File

0
api/appUser.js Normal file → Executable file
View File

0
components/BoxReveal.vue Normal file → Executable file
View File

0
components/ClayButton.vue Normal file → Executable file
View File

0
components/ClayCard.vue Normal file → Executable file
View File

0
components/ClayInput.vue Normal file → Executable file
View File

0
components/ElCard.vue Normal file → Executable file
View File

0
components/FlipGrid.vue Normal file → Executable file
View File

0
components/GamePassPurchasePopup.vue Normal file → Executable file
View File

0
components/GamePassPurchasePopup.vue.backup Normal file → Executable file
View File

0
components/MatchingGame.vue Normal file → Executable file
View File

2
components/PaymentPopup.vue Normal file → Executable file
View File

@ -304,7 +304,7 @@ function handleClose() {
function handleConfirm() {
emit('confirm', {
coupon: useGamePass.value ? null : selectedCoupon.value,
card: (props.showCards && !useGamePass.value) ? selectedCard.value : null,
card: props.showCards ? selectedCard.value : null, // 使
useGamePass: useGamePass.value
})
}

0
components/SplashScreen.vue Normal file → Executable file
View File

0
components/YifanSelector.vue Normal file → Executable file
View File

0
components/activity/ActivityHeader.vue Normal file → Executable file
View File

0
components/activity/ActivityPageLayout.vue Normal file → Executable file
View File

0
components/activity/ActivityTabs.vue Normal file → Executable file
View File

0
components/activity/CabinetPreviewPopup.vue Normal file → Executable file
View File

0
components/activity/DrawLoadingPopup.vue Normal file → Executable file
View File

0
components/activity/LotteryResultPopup.vue Normal file → Executable file
View File

0
components/activity/RecordsList.vue Normal file → Executable file
View File

0
components/activity/RewardsPopup.vue Normal file → Executable file
View File

0
components/activity/RewardsPreview.vue Normal file → Executable file
View File

0
components/activity/RulesPopup.vue Normal file → Executable file
View File

0
components/activity/index.js Normal file → Executable file
View File

0
components/app-tab-bar-toutiao.vue Normal file → Executable file
View File

0
components/app-tab-bar.vue Normal file → Executable file
View File

0
components/clay-components.js Normal file → Executable file
View File

0
docs/CLAYMORPHISM.md Normal file → Executable file
View File

View File

0
docs/代码重构分析/DESIGN_组件化重构.md Normal file → Executable file
View File

0
index.html Normal file → Executable file
View File

0
main.js Normal file → Executable file
View File

0
manifest.json Normal file → Executable file
View File

0
pages-activity/activity/duiduipeng/index.vue Normal file → Executable file
View File

0
pages-activity/activity/list/index.vue Normal file → Executable file
View File

0
pages-activity/activity/pata/index.vue Normal file → Executable file
View File

0
pages-activity/activity/wuxianshang/index.vue Normal file → Executable file
View File

0
pages-activity/activity/yifanshang/index.vue Normal file → Executable file
View File

0
pages-activity/composables/index.js Normal file → Executable file
View File

0
pages-activity/composables/useActivity.js Normal file → Executable file
View File

0
pages-activity/composables/useIssues.js Normal file → Executable file
View File

0
pages-activity/composables/useRecords.js Normal file → Executable file
View File

0
pages-activity/composables/useRewards.js Normal file → Executable file
View File

0
pages-game/game/minesweeper/index.vue Normal file → Executable file
View File

0
pages-game/game/minesweeper/play.scss Normal file → Executable file
View File

0
pages-game/game/minesweeper/play.vue Normal file → Executable file
View File

0
pages-game/game/minesweeper/room-list.vue Normal file → Executable file
View File

0
pages-game/game/webview.vue Normal file → Executable file
View File

0
pages-shop/shop/detail.vue Normal file → Executable file
View File

0
pages-user/address/edit.vue Normal file → Executable file
View File

0
pages-user/address/index.vue Normal file → Executable file
View File

0
pages-user/address/submit.vue Normal file → Executable file
View File

0
pages-user/agreement/purchase.vue Normal file → Executable file
View File

0
pages-user/agreement/user.vue Normal file → Executable file
View File

0
pages-user/coupons/index.vue Normal file → Executable file
View File

0
pages-user/help/index.vue Normal file → Executable file
View File

0
pages-user/invite/landing.vue Normal file → Executable file
View File

0
pages-user/invites/index.vue Normal file → Executable file
View File

0
pages-user/item-cards/index.vue Normal file → Executable file
View File

0
pages-user/orders/detail.vue Normal file → Executable file
View File

0
pages-user/orders/index.vue Normal file → Executable file
View File

0
pages-user/points/index.vue Normal file → Executable file
View File

0
pages-user/settings/index.vue Normal file → Executable file
View File

171
pages-user/tasks/index.vue Normal file → Executable file
View File

@ -74,14 +74,14 @@
<view class="sub-progress-list" v-if="taskProgress[task.id]?.subProgress?.length > 0">
<view
v-for="sub in taskProgress[task.id].subProgress"
:key="sub.activity_id"
:key="sub.activity_id ?? sub.label"
class="sub-progress-item"
>
<text class="sub-label">活动 {{ sub.activity_id }}</text>
<text class="sub-label">{{ getSubProgressLabel(sub) }}</text>
<view class="sub-bar-bg">
<view class="sub-bar-fill" :style="{ width: getSubProgressWidth(sub, task) }"></view>
</view>
<text class="sub-value">¥{{ sub.order_amount / 100 }}</text>
<text class="sub-value">{{ getSubProgressValue(sub, task) }}</text>
</view>
</view>
</view>
@ -138,6 +138,10 @@
<!-- 进度中 -->
<view v-else class="tier-progress">
<text class="progress-text">{{ getTierProgressText(task, tier) }}</text>
<!-- 普通档位进度条 first_order 类型才显示 -->
<view class="tier-bar-bg" v-if="getTierProgressPercent(task, tier) !== ''">
<view class="tier-bar-fill" :style="{ width: getTierProgressPercent(task, tier) }"></view>
</view>
<!-- 限量进度提示 -->
<text class="quota-text" v-if="tier.quota > 0">剩余 {{ tier.remaining }} </text>
</view>
@ -156,7 +160,7 @@
</template>
<script setup>
import { ref, reactive, computed } from 'vue'
import { ref, reactive } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { getTasks, getTaskProgress, claimTaskReward } from '../../api/appUser'
import { vibrateShort } from '@/utils/vibrate.js'
@ -177,7 +181,7 @@ const userProgress = reactive({
})
// BUG
const taskProgress = reactive({}) // { taskId: { orderCount, orderAmount, inviteCount, firstOrder } }
const taskProgress = reactive({}) // { taskId: { orderCount, orderAmount, inviteCount, firstOrder, subProgress } }
// ID
function getUserId() {
@ -215,6 +219,51 @@ function getTaskIcon(task) {
return '⭐'
}
function normalizeSubProgress(task, progressData) {
const rawList = Array.isArray(progressData?.sub_progress)
? progressData.sub_progress.map(item => ({
activity_id: item.activity_id,
order_amount: item.order_amount || 0,
order_count: item.order_count || 0
}))
: []
const hasGlobalTier = (task?.tiers || []).some(
t => (t.activity_id || 0) === 0 && (t.metric === 'order_amount' || t.metric === 'order_count')
)
const hasGlobalEntry = rawList.some(item => !item.activity_id)
if (hasGlobalTier && !hasGlobalEntry) {
rawList.unshift({
activity_id: 0,
order_amount: progressData?.order_amount || 0,
order_count: progressData?.order_count || 0,
label: '累计进度'
})
}
return rawList
}
function getSubProgressLabel(sub) {
if (!sub) return ''
if (sub.label) return sub.label
if (sub.activity_id > 0) return `活动 ${sub.activity_id}`
return '整体进度'
}
function getSubProgressValue(sub, task) {
if (!sub) return ''
const activityId = sub.activity_id || 0
if (hasTierMetric(task, activityId, 'order_amount')) {
return `¥${formatAmount(sub.order_amount || 0)}`
}
if (hasTierMetric(task, activityId, 'order_count')) {
return `${sub.order_count || 0}`
}
if ((sub.order_amount || 0) > 0) {
return `¥${formatAmount(sub.order_amount)}`
}
return `${sub.order_count || 0}`
}
//
function getTaskStatusClass(task) {
const progress = userProgress.claimedTiers[task.id] || []
@ -504,13 +553,15 @@ async function fetchData() {
const p = result.value
const taskId = list[index].id
const currentTask = list[index]
const normalizedSubProgress = normalizeSubProgress(currentTask, p)
// BUG
taskProgress[taskId] = {
orderCount: p.order_count || 0,
orderAmount: p.order_amount || 0,
inviteCount: p.invite_count || 0,
firstOrder: p.first_order || false,
subProgress: p.sub_progress || [] //
subProgress: normalizedSubProgress //
}
// ( - )
@ -536,24 +587,88 @@ onLoad(() => {
fetchData()
})
//
function getSubProgressWidth(sub, task) {
//
let maxThreshold = 0
if (task.tiers && task.tiers.length > 0) {
//
const amountTiers = task.tiers.filter(t => t.metric === 'order_amount')
if (amountTiers.length > 0) {
maxThreshold = Math.max(...amountTiers.map(t => t.threshold || 0))
//
function getTierProgressPercent(task, tier) {
const metric = tier.metric || ''
// first_order
if (metric === 'first_order') return ''
const threshold = tier.threshold || 0
if (threshold <= 0) return ''
const progress = taskProgress[task.id] || {}
let current = 0
// subProgress
if (tier.activity_id > 0 && progress.subProgress) {
const sub = progress.subProgress.find(s => s.activity_id === tier.activity_id)
if (sub) {
if (metric === 'order_amount') {
current = sub.order_amount || 0
} else if (metric === 'order_count') {
current = sub.order_count || 0
}
} else {
current = 0
}
} else {
// 使
if (metric === 'order_count') {
current = progress.orderCount || 0
} else if (metric === 'order_amount') {
current = progress.orderAmount || 0
} else if (metric === 'invite_count') {
current = progress.inviteCount || 0
}
}
// 100% ( 200)
if (maxThreshold === 0) maxThreshold = 20000 // 200
const percent = Math.min((sub.order_amount || 0) / maxThreshold * 100, 100)
return Math.min(current / threshold * 100, 100).toFixed(0) + '%'
}
//
function getSubProgressWidth(sub, task) {
if (!sub || !task) return '0%'
const activityId = sub.activity_id || 0
let metric = null
if (hasTierMetric(task, activityId, 'order_amount')) {
metric = 'order_amount'
} else if (hasTierMetric(task, activityId, 'order_count')) {
metric = 'order_count'
} else if ((sub.order_amount || 0) > 0) {
metric = 'order_amount'
} else {
metric = 'order_count'
}
const maxThreshold = getMaxThresholdByMetric(task, metric, activityId)
let denominator = maxThreshold
if (denominator <= 0) {
denominator = metric === 'order_count' ? Math.max(sub.order_count || 0, 100) : Math.max(sub.order_amount || 0, 20000)
}
const current = metric === 'order_count' ? (sub.order_count || 0) : (sub.order_amount || 0)
const percent = denominator === 0 ? 0 : Math.min((current / denominator) * 100, 100)
return `${percent}%`
}
function hasTierMetric(task, activityId, metric) {
if (!task?.tiers || !metric) return false
const target = activityId || 0
return task.tiers.some(t => (t.activity_id || 0) === target && t.metric === metric)
}
function getMaxThresholdByMetric(task, metric, activityId) {
if (!task?.tiers || !metric) return 0
const target = activityId || 0
const related = task.tiers.filter(t => (t.activity_id || 0) === target && t.metric === metric)
if (related.length === 0) return 0
return Math.max(...related.map(t => t.threshold || 0))
}
function formatAmount(cents) {
const value = Number(cents || 0) / 100
if (Number.isNaN(value)) return '0'
return Number.isInteger(value) ? value.toString() : value.toFixed(2)
}
</script>
<style lang="scss" scoped>
@ -969,6 +1084,22 @@ function getSubProgressWidth(sub, task) {
font-weight: 600;
}
.tier-bar-bg {
width: 120rpx;
height: 8rpx;
background: #f0f0f0;
border-radius: 4rpx;
margin-top: 8rpx;
overflow: hidden;
}
.tier-bar-fill {
height: 100%;
background: $brand-primary;
border-radius: 4rpx;
transition: width 0.3s ease;
}
.quota-text {
font-size: 18rpx;
color: $brand-primary;

0
pages.json Normal file → Executable file
View File

0
pages/cabinet/index.vue Normal file → Executable file
View File

0
pages/index/index.vue Normal file → Executable file
View File

0
pages/login/index.vue Normal file → Executable file
View File

0
pages/mine/index.vue Normal file → Executable file
View File

0
pages/shop/index.vue Normal file → Executable file
View File

0
project.config.json Normal file → Executable file
View File

0
project.private.config.json Normal file → Executable file
View File

0
static/logo.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 92 KiB

0
static/share_invite.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

0
static/tab/box.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 373 B

After

Width:  |  Height:  |  Size: 373 B

0
static/tab/box_active.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 651 B

After

Width:  |  Height:  |  Size: 651 B

0
static/tab/home.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

0
static/tab/home_active.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

0
static/tab/profile.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

0
static/tab/profile_active.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

0
static/tab/shop.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

0
static/tab/shop_active.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

0
uni.promisify.adaptor.js Normal file → Executable file
View File

0
uni.scss Normal file → Executable file
View File

0
utils/activity.js Normal file → Executable file
View File

0
utils/cache.js Normal file → Executable file
View File

0
utils/checkPhone.js Normal file → Executable file
View File

0
utils/format.js Normal file → Executable file
View File

0
utils/nakama-adapter.js Normal file → Executable file
View File

0
utils/nakama-js/nakama-js.js Normal file → Executable file
View File

0
utils/nakamaManager.js Normal file → Executable file
View File

0
utils/payment.js Normal file → Executable file
View File

4
utils/request.js Normal file → Executable file
View File

@ -1,5 +1,5 @@
// const BASE_URL = 'http://127.0.0.1:9991'
const BASE_URL = 'https://kdy.1024tool.vip'
const BASE_URL = 'http://127.0.0.1:9991'
// const BASE_URL = 'https://kdy.1024tool.vip'
let authModalShown = false
function handleAuthExpired() {

0
utils/subscribe.js Normal file → Executable file
View File

0
utils/vibrate.js Normal file → Executable file
View File

Some files were not shown because too many files have changed in this diff Show More