commit 931b4a9ad509f70226682d365ec04372ff7535a3 Author: youpaishidifu Date: Sat Jun 20 11:25:36 2026 +0800 草原探险用户端 v1.0 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eca30cd --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +node_modules/ +unpackage/ +.hbuilderx/ +.DS_Store +git仓库.txt diff --git a/App.vue b/App.vue new file mode 100644 index 0000000..8c2b732 --- /dev/null +++ b/App.vue @@ -0,0 +1,17 @@ + + + diff --git a/css/style.css b/css/style.css new file mode 100644 index 0000000..8047b11 --- /dev/null +++ b/css/style.css @@ -0,0 +1,257 @@ +/* ============================================ + SDF1 App Shell — Gold & Obsidian Theme + ============================================ */ + +:root { + --bg-deep: #06060b; + --bg-surface: #0e0e18; + --bg-card: #14141f; + --gold: #c9a44a; + --gold-dim: #a08339; + --gold-glow: rgba(201, 164, 74, 0.15); + --text-primary: #e8e4dc; + --text-muted: #6b6878; + --safe-top: env(safe-area-inset-top, 0px); + --safe-bottom: env(safe-area-inset-bottom, 0px); +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; + -webkit-tap-highlight-color: transparent; +} + +html, body { + width: 100%; + height: 100%; + overflow: hidden; + background: var(--bg-deep); + font-family: 'Noto Sans SC', 'Outfit', sans-serif; + color: var(--text-primary); + -webkit-font-smoothing: antialiased; +} + +/* ---- Utilities ---- */ +.hidden { display: none !important; } + +/* ---- Splash Screen ---- */ +.splash { + position: fixed; + inset: 0; + z-index: 9999; + background: var(--bg-deep); + display: flex; + align-items: center; + justify-content: center; + transition: opacity 0.5s ease, visibility 0.5s ease; +} + +.splash.fade-out { + opacity: 0; + visibility: hidden; +} + +.splash-inner { + text-align: center; + animation: splashReveal 0.8s ease forwards; +} + +@keyframes splashReveal { + from { + opacity: 0; + transform: translateY(16px) scale(0.95); + } + to { + opacity: 1; + transform: translateY(0) scale(1); + } +} + +.splash-icon { + width: 80px; + height: 80px; + margin: 0 auto 24px; + animation: iconPulse 2s ease-in-out infinite; +} + +@keyframes iconPulse { + 0%, 100% { transform: scale(1); filter: drop-shadow(0 0 8px var(--gold-glow)); } + 50% { transform: scale(1.05); filter: drop-shadow(0 0 20px var(--gold-glow)); } +} + +.splash-title { + font-family: 'Outfit', sans-serif; + font-size: 32px; + font-weight: 700; + letter-spacing: 0.15em; + color: var(--gold); + margin-bottom: 4px; +} + +.splash-sub { + font-size: 14px; + font-weight: 300; + color: var(--text-muted); + letter-spacing: 0.3em; + text-transform: uppercase; +} + +.splash-loader { + width: 140px; + height: 2px; + background: rgba(201, 164, 74, 0.12); + border-radius: 2px; + margin: 36px auto 0; + overflow: hidden; +} + +.loader-bar { + width: 0%; + height: 100%; + background: linear-gradient(90deg, var(--gold-dim), var(--gold)); + border-radius: 2px; + animation: loaderGrow 2.5s ease forwards; +} + +@keyframes loaderGrow { + 0% { width: 0%; } + 60% { width: 70%; } + 100% { width: 100%; } +} + +/* ---- WebView Container ---- */ +.webview-container { + position: fixed; + inset: 0; + z-index: 1; +} + +.webview-container web-view, +.webview-container iframe { + width: 100%; + height: 100%; + border: none; +} + +/* ---- Error Page ---- */ +.error-page { + position: fixed; + inset: 0; + z-index: 100; + background: var(--bg-deep); + display: flex; + align-items: center; + justify-content: center; +} + +.error-inner { + text-align: center; + padding: 40px; + animation: fadeUp 0.5s ease forwards; +} + +@keyframes fadeUp { + from { opacity: 0; transform: translateY(20px); } + to { opacity: 1; transform: translateY(0); } +} + +.error-icon { + width: 64px; + height: 64px; + margin-bottom: 24px; +} + +.error-inner h2 { + font-family: 'Outfit', sans-serif; + font-size: 22px; + font-weight: 500; + color: var(--text-primary); + margin-bottom: 8px; +} + +.error-inner p { + font-size: 14px; + color: var(--text-muted); + margin-bottom: 36px; +} + +.retry-btn { + display: inline-block; + padding: 14px 48px; + border: 1px solid var(--gold-dim); + background: transparent; + color: var(--gold); + font-family: 'Noto Sans SC', sans-serif; + font-size: 15px; + font-weight: 400; + letter-spacing: 0.08em; + border-radius: 6px; + cursor: pointer; + transition: all 0.25s ease; +} + +.retry-btn:active { + background: var(--gold); + color: var(--bg-deep); + transform: scale(0.97); +} + +/* ---- Bottom Bar ---- */ +.bottom-bar { + position: fixed; + bottom: 0; + left: 0; + right: 0; + z-index: 500; + display: flex; + justify-content: space-around; + align-items: center; + height: 56px; + padding-bottom: var(--safe-bottom); + background: linear-gradient(180deg, rgba(14,14,24,0.92) 0%, rgba(14,14,24,0.98) 100%); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + border-top: 1px solid rgba(201, 164, 74, 0.1); +} + +.bar-btn { + display: flex; + flex-direction: column; + align-items: center; + gap: 3px; + background: none; + border: none; + color: var(--text-muted); + font-family: 'Noto Sans SC', sans-serif; + font-size: 10px; + cursor: pointer; + padding: 6px 16px; + transition: color 0.2s ease; + -webkit-tap-highlight-color: transparent; +} + +.bar-btn svg { + width: 22px; + height: 22px; +} + +.bar-btn.active { + color: var(--gold); +} + +.bar-btn:active { + transform: scale(0.9); +} + +/* ---- 纹理叠加 ---- */ +body::after { + content: ''; + position: fixed; + inset: 0; + z-index: 0; + pointer-events: none; + background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='1'/%3E%3C/svg%3E"); + background-size: 128px 128px; + opacity: 0.025; +} \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..1b45856 --- /dev/null +++ b/index.html @@ -0,0 +1,81 @@ + + + + + + + + SDF1玩家商城 + + + + + + + +
+
+
+ + + + + + + + + +
+

SDF1

+

玩家商城

+
+
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/js/app.js b/js/app.js new file mode 100644 index 0000000..a8e5ff2 --- /dev/null +++ b/js/app.js @@ -0,0 +1,240 @@ +/** + * SDF1 App Shell + * — 启动 → 闪屏 → 加载 WebView → 错误重试 + */ + +(function () { + 'use strict'; + + var MAIN_URL = 'https://caoyuan.ypshidifu.cn/plugin/player.php'; + var SPLASH_MIN_DURATION = 2800; // 闪屏最少展示 2.8 秒 + + var splash = document.getElementById('splash'); + var errorPage = document.getElementById('error-page'); + var retryBtn = document.getElementById('retry-btn'); + var webview = document.getElementById('main-webview'); + var bottomBar = document.getElementById('bottom-bar'); + + var appReady = false; + var startTime = Date.now(); + + /* ------------------------------------------- + 1. 检测网络 + ------------------------------------------- */ + function checkNetwork(callback) { + if (navigator.connection) { + var conn = navigator.connection; + if (conn.type === 'none' || conn.effectiveType === 'none') { + return callback(false); + } + } + // 简易 fetch 探测 + fetch(MAIN_URL, { method: 'HEAD', mode: 'no-cors', cache: 'no-store' }) + .then(function () { callback(true); }) + .catch(function () { callback(false); }); + } + + /* ------------------------------------------- + 2. 初始化 WebView(HTML5+ 环境) + ------------------------------------------- */ + function initPlusWebView() { + if (typeof plus === 'undefined') { + // 浏览器调试模式:用 iframe 代替 + var iframe = document.createElement('iframe'); + iframe.src = MAIN_URL; + iframe.style.cssText = 'width:100%;height:100%;border:none;'; + iframe.onload = onContentLoad; + iframe.onerror = function () { showError(); }; + webview.innerHTML = ''; + webview.appendChild(iframe); + return; + } + + // ---- Plus 真机环境 ---- + var wv = plus.webview.create(MAIN_URL, 'main', { + top: 0, + bottom: 0, + bounce: 'none', + progress: { color: '#c9a44a', height: '2px' }, + useragent: { value: 'SDF1App/1.0', concat: true } + }); + + wv.addEventListener('loaded', onContentLoad); + wv.addEventListener('loadError', function (e) { + console.error('WebView load error:', e); + showError(); + }); + + webview.appendChild(wv); + + // 保持页面不被系统回收 + plus.globalEvent.addEventListener('pause', function () {}); + } + + /* ------------------------------------------- + 3. 内容加载完成 → 隐藏闪屏 + ------------------------------------------- */ + function onContentLoad() { + appReady = true; + var elapsed = Date.now() - startTime; + var remaining = Math.max(0, SPLASH_MIN_DURATION - elapsed); + + setTimeout(function () { + splash.classList.add('fade-out'); + errorPage.classList.add('hidden'); + bottomBar.classList.remove('hidden'); + + setTimeout(function () { + splash.style.display = 'none'; + }, 600); + }, remaining); + } + + /* ------------------------------------------- + 4. 错误处理 + ------------------------------------------- */ + function showError() { + splash.classList.add('fade-out'); + setTimeout(function () { + splash.style.display = 'none'; + }, 500); + errorPage.classList.remove('hidden'); + bottomBar.classList.add('hidden'); + } + + function hideError() { + errorPage.classList.add('hidden'); + } + + /* ------------------------------------------- + 5. 底部导航事件 + ------------------------------------------- */ + function setupBottomBar() { + var btns = bottomBar.querySelectorAll('.bar-btn'); + btns.forEach(function (btn) { + btn.addEventListener('click', function () { + var action = btn.getAttribute('data-action'); + + // 切换 active 状态 + btns.forEach(function (b) { b.classList.remove('active'); }); + btn.classList.add('active'); + + if (action === 'refresh') { + reloadWebView(); + } else if (action === 'back') { + goBack(); + } else if (action === 'home') { + goHome(); + } + }); + }); + } + + function reloadWebView() { + if (typeof plus !== 'undefined') { + var wv = webview.children[0]; + if (wv && wv.reload) { + wv.reload(); + } + } else { + var iframe = webview.querySelector('iframe'); + if (iframe) iframe.src = MAIN_URL; + } + } + + function goBack() { + if (typeof plus !== 'undefined') { + var wv = webview.children[0]; + if (wv && wv.canBack) { + wv.canBack(function (e) { + if (e.canBack) { + wv.back(); + } + }); + } + } + } + + function goHome() { + if (typeof plus !== 'undefined') { + var wv = webview.children[0]; + if (wv) { + wv.loadURL(MAIN_URL); + } + } else { + var iframe = webview.querySelector('iframe'); + if (iframe) iframe.src = MAIN_URL; + } + } + + /* ------------------------------------------- + 6. 物理返回键拦截(Android) + ------------------------------------------- */ + function setupBackButton() { + if (typeof plus === 'undefined') return; + + plus.key.addEventListener('backbutton', function () { + var wv = webview.children[0]; + if (wv && wv.canBack) { + wv.canBack(function (e) { + if (e.canBack) { + wv.back(); + } else { + // 已在首页,按两次退出 + confirmExit(); + } + }); + } else { + confirmExit(); + } + }); + } + + function confirmExit() { + if (typeof plus === 'undefined') return; + plus.nativeUI.confirm( + '确定要退出应用吗?', + function (e) { + if (e.index === 0) { + plus.runtime.quit(); + } + }, + '退出提示', + ['确定', '取消'] + ); + } + + /* ------------------------------------------- + 7. 启动流程 + ------------------------------------------- */ + function boot() { + checkNetwork(function (online) { + if (!online) { + showError(); + return; + } + initPlusWebView(); + }); + + setupBottomBar(); + setupBackButton(); + + retryBtn.addEventListener('click', function () { + hideError(); + splash.style.display = ''; + splash.classList.remove('fade-out'); + startTime = Date.now(); + boot(); + }); + } + + // ---- 入口 ---- + if (typeof plus !== 'undefined') { + // HTML5+ ready + plus.ready(function () { boot(); }); + } else if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', boot); + } else { + boot(); + } +})(); \ No newline at end of file diff --git a/main.js b/main.js new file mode 100644 index 0000000..c1caf36 --- /dev/null +++ b/main.js @@ -0,0 +1,22 @@ +import App from './App' + +// #ifndef VUE3 +import Vue from 'vue' +import './uni.promisify.adaptor' +Vue.config.productionTip = false +App.mpType = 'app' +const app = new Vue({ + ...App +}) +app.$mount() +// #endif + +// #ifdef VUE3 +import { createSSRApp } from 'vue' +export function createApp() { + const app = createSSRApp(App) + return { + app + } +} +// #endif \ No newline at end of file diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..a4a62df --- /dev/null +++ b/manifest.json @@ -0,0 +1,70 @@ +{ + "name" : "草原探险用户端", + "appid" : "__UNI__307F77D", + "description" : "SDF1玩家商城客户端", + "versionName" : "1.0", + "versionCode" : 100, + "app-plus" : { + "useragent" : { + "value" : "SDF1App/1.0", + "concatenate" : true + }, + "splashscreen" : { + "alwaysShowBeforeRender" : true, + "autoclose" : false, + "waiting" : false, + "background" : "#0a0a0a" + }, + "screenOrientation" : [ "portrait-primary" ], + "modules" : {}, + "distribute" : { + "android" : { + "permissions" : [ + "", + "", + "" + ], + "targetSdkVersion" : 30, + "minSdkVersion" : 21 + }, + "ios" : { + "UIBackgroundModes" : [], + "dSYMs" : false + }, + "icons" : { + "android" : { + "hdpi" : "unpackage/res/icons/72x72.png", + "xhdpi" : "unpackage/res/icons/96x96.png", + "xxhdpi" : "unpackage/res/icons/144x144.png", + "xxxhdpi" : "unpackage/res/icons/192x192.png" + }, + "ios" : { + "appstore" : "unpackage/res/icons/1024x1024.png", + "ipad" : { + "app" : "unpackage/res/icons/76x76.png", + "app@2x" : "unpackage/res/icons/152x152.png", + "notification" : "unpackage/res/icons/20x20.png", + "notification@2x" : "unpackage/res/icons/40x40.png", + "proapp@2x" : "unpackage/res/icons/167x167.png", + "settings" : "unpackage/res/icons/29x29.png", + "settings@2x" : "unpackage/res/icons/58x58.png", + "spotlight" : "unpackage/res/icons/40x40.png", + "spotlight@2x" : "unpackage/res/icons/80x80.png" + }, + "iphone" : { + "app@2x" : "unpackage/res/icons/120x120.png", + "app@3x" : "unpackage/res/icons/180x180.png", + "notification@2x" : "unpackage/res/icons/40x40.png", + "notification@3x" : "unpackage/res/icons/60x60.png", + "settings@2x" : "unpackage/res/icons/58x58.png", + "settings@3x" : "unpackage/res/icons/87x87.png", + "spotlight@2x" : "unpackage/res/icons/80x80.png", + "spotlight@3x" : "unpackage/res/icons/120x120.png" + } + } + } + } + }, + "vueVersion" : "3", + "fallbackLocale" : "zh-Hans" +} diff --git a/pages.json b/pages.json new file mode 100644 index 0000000..869105d --- /dev/null +++ b/pages.json @@ -0,0 +1,17 @@ +{ + "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages + { + "path": "pages/index/index", + "style": { + "navigationBarTitleText": "uni-app" + } + } + ], + "globalStyle": { + "navigationBarTextStyle": "black", + "navigationBarTitleText": "uni-app", + "navigationBarBackgroundColor": "#F8F8F8", + "backgroundColor": "#F8F8F8" + }, + "uniIdRouter": {} +} diff --git a/pages/index/index.vue b/pages/index/index.vue new file mode 100644 index 0000000..68c2244 --- /dev/null +++ b/pages/index/index.vue @@ -0,0 +1,13 @@ + + + \ No newline at end of file diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..dad5f92 --- /dev/null +++ b/readme.md @@ -0,0 +1,21 @@ +## 草原探险用户端app + +### 1. 项目介绍 +草原探险app是为草原探险服务器全体玩家打造的一款移动app,您可以在这里查看您的账号信息、兑换奖励等。 + +## 2. 项目构造 +项目使用vue3构造 + +## 3.下载地址: +| 开源平台 | 下载地址 | 版本 | +| :----: | :----: | :----: | +| git.ypshidifu.cn | [https://git.ypshidifu.cn/youpaishidifu/caoyuanapp/releases/tag/1.0](https://git.ypshidifu.cn/youpaishidifu/caoyuanapp/releases/tag/1.0) | Android | +| gitcode | [https://gitcode.com/ypsdf1/caoyuanapp/releases/1.0](https://gitcode.com/ypsdf1/caoyuanapp/releases/1.0) | Android | +| github | [https://github.com/ypsdf1/caoyuanapp/releases/tag/1.0](https://github.com/ypsdf1/caoyuanapp/releases/tag/1.0) | Android | +| gitee | [https://gitee.com/nihaoshidifu/caoyuanapp/releases/tag/1.0](https://gitee.com/nihaoshidifu/caoyuanapp/releases/tag/1.0) | Android | + +## 4. 使用说明 +1. 下载app
+2. 输入你的游戏昵称和密码
+3. 点击登录
+ diff --git a/static/logo.png b/static/logo.png new file mode 100644 index 0000000..b5771e2 Binary files /dev/null and b/static/logo.png differ diff --git a/uni.promisify.adaptor.js b/uni.promisify.adaptor.js new file mode 100644 index 0000000..5fec4f3 --- /dev/null +++ b/uni.promisify.adaptor.js @@ -0,0 +1,13 @@ +uni.addInterceptor({ + returnValue (res) { + if (!(!!res && (typeof res === "object" || typeof res === "function") && typeof res.then === "function")) { + return res; + } + return new Promise((resolve, reject) => { + res.then((res) => { + if (!res) return resolve(res) + return res[0] ? reject(res[0]) : resolve(res[1]) + }); + }); + }, +}); \ No newline at end of file diff --git a/uni.scss b/uni.scss new file mode 100644 index 0000000..b9249e9 --- /dev/null +++ b/uni.scss @@ -0,0 +1,76 @@ +/** + * 这里是uni-app内置的常用样式变量 + * + * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量 + * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App + * + */ + +/** + * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能 + * + * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件 + */ + +/* 颜色变量 */ + +/* 行为相关颜色 */ +$uni-color-primary: #007aff; +$uni-color-success: #4cd964; +$uni-color-warning: #f0ad4e; +$uni-color-error: #dd524d; + +/* 文字基本颜色 */ +$uni-text-color:#333;//基本色 +$uni-text-color-inverse:#fff;//反色 +$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息 +$uni-text-color-placeholder: #808080; +$uni-text-color-disable:#c0c0c0; + +/* 背景颜色 */ +$uni-bg-color:#ffffff; +$uni-bg-color-grey:#f8f8f8; +$uni-bg-color-hover:#f1f1f1;//点击状态颜色 +$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色 + +/* 边框颜色 */ +$uni-border-color:#c8c7cc; + +/* 尺寸变量 */ + +/* 文字尺寸 */ +$uni-font-size-sm:12px; +$uni-font-size-base:14px; +$uni-font-size-lg:16px; + +/* 图片尺寸 */ +$uni-img-size-sm:20px; +$uni-img-size-base:26px; +$uni-img-size-lg:40px; + +/* Border Radius */ +$uni-border-radius-sm: 2px; +$uni-border-radius-base: 3px; +$uni-border-radius-lg: 6px; +$uni-border-radius-circle: 50%; + +/* 水平间距 */ +$uni-spacing-row-sm: 5px; +$uni-spacing-row-base: 10px; +$uni-spacing-row-lg: 15px; + +/* 垂直间距 */ +$uni-spacing-col-sm: 4px; +$uni-spacing-col-base: 8px; +$uni-spacing-col-lg: 12px; + +/* 透明度 */ +$uni-opacity-disabled: 0.3; // 组件禁用态的透明度 + +/* 文章场景相关 */ +$uni-color-title: #2C405A; // 文章标题颜色 +$uni-font-size-title:20px; +$uni-color-subtitle: #555555; // 二级标题颜色 +$uni-font-size-subtitle:26px; +$uni-color-paragraph: #3F536E; // 文章段落颜色 +$uni-font-size-paragraph:15px;