diff --git a/pages/register/register.vue b/pages/register/register.vue
new file mode 100644
index 0000000..94fcc9f
--- /dev/null
+++ b/pages/register/register.vue
@@ -0,0 +1,323 @@
+
+
+
+
+ 手机号:
+
+
+
+
+
+ 密码:
+
+
+
+
+
+ 确认密码:
+
+
+
+
+
+ 验证码:
+
+
+
+
+
+
+
+
+
+
+
+ 已有账号?点击登录
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/shop/detail.vue b/pages/shop/detail.vue
new file mode 100644
index 0000000..5074844
--- /dev/null
+++ b/pages/shop/detail.vue
@@ -0,0 +1,170 @@
+
+
+
+
+ {{ requiredPoints }}积分
+
+
+ {{ product.description }}
+
+
+ 数量
+
+ -
+ {{ quantity }}
+ +
+
+
+
+ 共需积分:{{ totalRequired }}
+
+
+
+
+
+
+
diff --git a/utils/assets.js b/utils/assets.js
new file mode 100644
index 0000000..7235baa
--- /dev/null
+++ b/utils/assets.js
@@ -0,0 +1,35 @@
+export async function ensureLocal(url) {
+ return new Promise((resolve) => {
+ try {
+ const cache = uni.getStorageSync('asset_cache_v1') || {}
+ const hit = cache[url]
+ if (hit && typeof hit === 'string' && hit) { resolve(hit); return }
+ uni.downloadFile({
+ url,
+ success: (res) => {
+ const tmp = res.tempFilePath || ''
+ if (!tmp) { resolve(url); return }
+ uni.saveFile({
+ tempFilePath: tmp,
+ success: (s) => {
+ const saved = s.savedFilePath || tmp
+ cache[url] = saved
+ uni.setStorageSync('asset_cache_v1', cache)
+ resolve(saved)
+ },
+ fail: () => { resolve(tmp) }
+ })
+ },
+ fail: () => { resolve(url) }
+ })
+ } catch (_) { resolve(url) }
+ })
+}
+
+export async function preloadAssets(urls) {
+ const tasks = urls.map(u => ensureLocal(u))
+ const results = await Promise.allSettled(tasks)
+ const map = {}
+ results.forEach((r, i) => { map[urls[i]] = r.status === 'fulfilled' ? r.value : urls[i] })
+ return map
+}