消息
This commit is contained in:
122
AGENTS.md
Normal file
122
AGENTS.md
Normal file
@@ -0,0 +1,122 @@
|
||||
# AGENTS.md
|
||||
|
||||
Guidelines for AI agents working in this SeaTime (航海时代) codebase.
|
||||
|
||||
## Project Structure
|
||||
|
||||
Full-stack web game with two components:
|
||||
- **Web/**: Nuxt 4 (Vue 3 + TypeScript) frontend
|
||||
- **Service/**: .NET 10 Web API backend using Photon.Core framework
|
||||
|
||||
## Build Commands
|
||||
|
||||
### Web (Frontend)
|
||||
|
||||
```bash
|
||||
cd Web
|
||||
npm install # Install dependencies
|
||||
npm run dev # Start dev server on port 5068
|
||||
npm run build # Production build
|
||||
npm run generate # Static site generation
|
||||
npm run preview # Preview production build
|
||||
npm run postinstall # Nuxt prepare (runs automatically after install)
|
||||
```
|
||||
|
||||
### Service (Backend)
|
||||
|
||||
```bash
|
||||
cd Service
|
||||
dotnet build # Build solution
|
||||
dotnet run --project Application.Web # Run web API
|
||||
dotnet watch --project Application.Web # Run with hot reload
|
||||
```
|
||||
|
||||
## Testing Commands
|
||||
|
||||
**No test framework configured yet.** To add tests:
|
||||
|
||||
- **Web**: Install Vitest or Jest for unit tests
|
||||
- **Service**: Use `dotnet test` after adding xUnit/NUnit test projects
|
||||
|
||||
When tests are added, run them with:
|
||||
```bash
|
||||
# Web (Vitest example)
|
||||
npm run test # Run all tests
|
||||
npm run test:unit # Run unit tests only
|
||||
npm run test -- <file> # Run single test file
|
||||
|
||||
# Service
|
||||
dotnet test # Run all tests
|
||||
dotnet test --filter "FullyQualifiedName~ClassName" # Run specific test class
|
||||
```
|
||||
|
||||
## Code Style Guidelines
|
||||
|
||||
### TypeScript / Vue (Web)
|
||||
|
||||
- **Imports**: Use `~/` alias for src directory imports (e.g., `import type { IUserInfo } from '~/types/user'`)
|
||||
- **Vue SFCs**: Use `<script setup lang="ts">` composition API
|
||||
- **Naming Conventions**:
|
||||
- Stores: `useXxxStore` in `stores/` (e.g., `useUserStore`)
|
||||
- Composables: `useXxx` in `composables/` (e.g., `useAuth`)
|
||||
- Services: `XxxSERVICE` class in `services/` (e.g., `UserSERVICE`)
|
||||
- Extends: `xxxEXTEND` class in `extends/` (e.g., `RequestEXTEND`)
|
||||
- Types: `IXxx` interface in `types/` (e.g., `IUserInfo`)
|
||||
- Pages: kebab-case in `pages/` (e.g., `auth/login.vue`)
|
||||
- **Auto-imports**: stores, composables, extends, services are auto-imported (see nuxt.config.ts)
|
||||
- **TypeScript**: Strict mode enabled, always define return types for public functions
|
||||
- **Comments**: Use Chinese for business logic documentation
|
||||
- **API Pattern**: Services check `response.code !== 200 && response.code !== 0` for errors
|
||||
- **State Management**: Pinia stores use `state`/`getters`/`actions` pattern with `persist` for localStorage
|
||||
- **Persistence**: Only persist `token` and `userInfo` to localStorage via `piniaPluginPersistedstate.localStorage()`
|
||||
|
||||
### C# (Service)
|
||||
|
||||
- Target framework: .NET 10
|
||||
- Nullable reference types enabled
|
||||
- Implicit usings enabled
|
||||
- Standard C# naming: PascalCase for classes/methods, camelCase for locals
|
||||
- Controllers use `[ApiExplorerSettings(GroupName = "...")]` for Swagger grouping
|
||||
- Route pattern: `[Route("[controller]/[action]")]`
|
||||
- Return `IPoAction` / `PoAction.Ok()` from controllers
|
||||
- Request params in `Application.Domain/RequestParms/` folder
|
||||
- Global usings defined in `Application.Web/GlobalUsings.cs`
|
||||
- Uses Photon.Core framework (DI via `Inject*`, JWT, SqlSugar, Timer)
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Web
|
||||
|
||||
- Services: Wrap API calls in try-catch, log errors with `console.error`, re-throw or return false
|
||||
- Components: Use `showToast`/`showFailToast`/`showSuccessToast` from Vant for user feedback
|
||||
- Always check `typeof window !== 'undefined'` for client-side only code
|
||||
- Navigation: Use `navigateTo()` for programmatic navigation
|
||||
|
||||
### Service
|
||||
|
||||
- Use standard .NET exception handling middleware
|
||||
- Return consistent response models with code/message/data structure
|
||||
- CORS policy "all" configured for cross-origin requests
|
||||
|
||||
## Key Technologies
|
||||
|
||||
- **Frontend**: Nuxt 4, Vue 3, Pinia, Vant UI, TypeScript
|
||||
- **Backend**: .NET 10 Web API, Photon.Core framework
|
||||
- **State Management**: Pinia with pinia-plugin-persistedstate (localStorage)
|
||||
- **HTTP Client**: Custom RequestEXTEND class based on native fetch
|
||||
- **Auth**: JWT with custom JwtHandle validator
|
||||
- **Timer**: AutoJob hosted service with TimerJobManager
|
||||
|
||||
## Project Conventions
|
||||
|
||||
- Source directory: `Web/src/`
|
||||
- Pages use file-based routing (Nuxt convention)
|
||||
- Layouts in `Web/src/layouts/`
|
||||
- Layout constants in `composables/layout.ts` as `layout` object (e.g., `layout.empty`)
|
||||
- Use `definePageMeta({ layout: layout.empty })` for page layout configuration
|
||||
- Store persistence: Only token and userInfo are persisted to localStorage
|
||||
- No ESLint/Prettier configured yet - follow existing code patterns
|
||||
|
||||
## Existing Rules
|
||||
|
||||
No Cursor rules (.cursorrules or .cursor/rules/) or Copilot instructions (.github/copilot-instructions.md) found in this repository.
|
||||
@@ -13,9 +13,11 @@
|
||||
|
||||
// 可以在这里进行全局初始化
|
||||
const appStore = useAppStore()
|
||||
|
||||
import { Loading } from 'vant'
|
||||
// 初始化应用配置
|
||||
onMounted(() => {
|
||||
|
||||
|
||||
// 初始化屏幕尺寸
|
||||
if (typeof window !== 'undefined') {
|
||||
appStore.updateScreenSize(window.innerWidth, window.innerHeight)
|
||||
|
||||
@@ -507,4 +507,127 @@ a {
|
||||
.maxname {
|
||||
max-height: 150px;
|
||||
max-width: 250px;
|
||||
}
|
||||
|
||||
/* ========== 自定义通知队列 ========== */
|
||||
#custom-notify-container {
|
||||
position: fixed;
|
||||
top: 10px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
z-index: 9999;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.custom-notify-item {
|
||||
box-sizing: border-box;
|
||||
max-width: 90%;
|
||||
padding: 8px 16px;
|
||||
margin-bottom: 8px;
|
||||
border-radius: 8px;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
text-align: center;
|
||||
word-wrap: break-word;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||||
pointer-events: auto;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
transform: translateY(-20px);
|
||||
animation: notify-slide-in 300ms ease-out forwards;
|
||||
}
|
||||
|
||||
.custom-notify-item.leaving {
|
||||
animation: notify-fade-out 200ms ease-in forwards;
|
||||
}
|
||||
|
||||
@keyframes notify-slide-in {
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes notify-fade-out {
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
}
|
||||
|
||||
/* ========== 顶部通告栏 ========== */
|
||||
.custom-notice-bar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 16px;
|
||||
box-sizing: border-box;
|
||||
z-index: 9998;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.custom-notice-bar .notice-icon {
|
||||
flex-shrink: 0;
|
||||
margin-right: 8px;
|
||||
font-size: 16px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.custom-notice-bar .notice-wrap {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 40px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.custom-notice-bar .notice-text {
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
padding-right: 50px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.custom-notice-bar .notice-wrap.scrolling {
|
||||
animation: notice-scroll var(--scroll-duration, 10s) linear infinite;
|
||||
}
|
||||
|
||||
@keyframes notice-scroll {
|
||||
0% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
100% {
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
.custom-notice-bar .notice-close {
|
||||
flex-shrink: 0;
|
||||
margin-left: 8px;
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
line-height: 1;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
102
Web/src/extends/MessageExtend.ts
Normal file
102
Web/src/extends/MessageExtend.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* 消息提示工具
|
||||
*/
|
||||
export class MessageExtend {
|
||||
// 消息通知
|
||||
static notify(type: 'primary' | 'success' | 'danger' | 'warning', message: any) {
|
||||
showNotify({ type, message })
|
||||
}
|
||||
|
||||
// 提示弹窗
|
||||
static dialog(
|
||||
title: string,
|
||||
message: string,
|
||||
theme: 'round-button' | 'default',
|
||||
onConfirm?: () => void,
|
||||
onCancel?: () => void,
|
||||
confirmButtonText: string = '确认',
|
||||
) {
|
||||
showConfirmDialog({
|
||||
title: title,
|
||||
message: message,
|
||||
theme: theme || 'default',
|
||||
confirmButtonText: confirmButtonText || '确认',
|
||||
})
|
||||
.then(() => {
|
||||
onConfirm?.()
|
||||
})
|
||||
.catch(() => {
|
||||
onCancel?.()
|
||||
})
|
||||
}
|
||||
|
||||
// 成功失败默认提示
|
||||
static showToast(type: 'success' | 'fail' | 'default', text: any) {
|
||||
if (type == 'success') {
|
||||
showSuccessToast(text)
|
||||
} else if (type == 'fail') {
|
||||
showFailToast(text)
|
||||
} else {
|
||||
showToast(text)
|
||||
}
|
||||
}
|
||||
|
||||
// 自定义图标提示
|
||||
static showIconToast(icon: any, text: any) {
|
||||
showToast({
|
||||
message: text,
|
||||
icon: icon,
|
||||
})
|
||||
}
|
||||
|
||||
// 多条消息通知(堆叠展示)
|
||||
static notifyList(type: 'primary' | 'success' | 'danger' | 'warning', messages: string[], duration: number = 3000) {
|
||||
if (typeof window === 'undefined') return
|
||||
if (!messages || messages.length === 0) return
|
||||
|
||||
const colorMap = {
|
||||
primary: '#1989fa',
|
||||
success: '#07c160',
|
||||
danger: '#ee0a24',
|
||||
warning: '#ff976a',
|
||||
}
|
||||
|
||||
let container = document.getElementById('custom-notify-container')
|
||||
if (!container) {
|
||||
container = document.createElement('div')
|
||||
container.id = 'custom-notify-container'
|
||||
document.body.appendChild(container)
|
||||
}
|
||||
|
||||
messages.forEach((message, index) => {
|
||||
const item = document.createElement('div')
|
||||
item.className = 'custom-notify-item'
|
||||
item.style.backgroundColor = colorMap[type]
|
||||
item.textContent = String(message)
|
||||
item.style.animationDelay = `${index * 100}ms`
|
||||
|
||||
item.addEventListener('click', () => {
|
||||
this.closeNotifyItem(item)
|
||||
})
|
||||
|
||||
container!.appendChild(item)
|
||||
|
||||
setTimeout(() => {
|
||||
this.closeNotifyItem(item)
|
||||
}, duration)
|
||||
})
|
||||
}
|
||||
|
||||
// 关闭单条通知
|
||||
private static closeNotifyItem(item: HTMLElement) {
|
||||
if (!item || item.classList.contains('leaving')) return
|
||||
item.classList.add('leaving')
|
||||
item.addEventListener('animationend', () => {
|
||||
item.remove()
|
||||
const container = document.getElementById('custom-notify-container')
|
||||
if (container && container.children.length === 0) {
|
||||
container.remove()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -48,16 +48,8 @@
|
||||
<label class="field-label" for="login-username">账号</label>
|
||||
<div class="field-box" :class="{ 'is-error': !!errors.username }">
|
||||
<span class="field-marker">A</span>
|
||||
<input
|
||||
id="login-username"
|
||||
v-model.trim="form.username"
|
||||
class="field-input"
|
||||
type="text"
|
||||
inputmode="text"
|
||||
autocomplete="username"
|
||||
placeholder="请输入账号"
|
||||
@input="clearFieldError('username')"
|
||||
/>
|
||||
<input id="login-username" v-model.trim="form.username" class="field-input" type="text" inputmode="text"
|
||||
autocomplete="username" placeholder="请输入账号" @input="clearFieldError('username')" />
|
||||
</div>
|
||||
<p v-if="errors.username" class="field-error">{{ errors.username }}</p>
|
||||
</div>
|
||||
@@ -66,15 +58,8 @@
|
||||
<label class="field-label" for="login-password">密码</label>
|
||||
<div class="field-box" :class="{ 'is-error': !!errors.password }">
|
||||
<span class="field-marker">P</span>
|
||||
<input
|
||||
id="login-password"
|
||||
v-model.trim="form.password"
|
||||
class="field-input"
|
||||
type="password"
|
||||
autocomplete="current-password"
|
||||
placeholder="请输入密码"
|
||||
@input="clearFieldError('password')"
|
||||
/>
|
||||
<input id="login-password" v-model.trim="form.password" class="field-input" type="password"
|
||||
autocomplete="current-password" placeholder="请输入密码" @input="clearFieldError('password')" />
|
||||
</div>
|
||||
<p v-if="errors.password" class="field-error">{{ errors.password }}</p>
|
||||
</div>
|
||||
@@ -92,12 +77,8 @@
|
||||
|
||||
<div class="login-agreement">
|
||||
<label class="check-row">
|
||||
<input
|
||||
v-model="form.agreement"
|
||||
class="check-input"
|
||||
type="checkbox"
|
||||
@change="clearFieldError('agreement')"
|
||||
/>
|
||||
<input v-model="form.agreement" class="check-input" type="checkbox"
|
||||
@change="clearFieldError('agreement')" />
|
||||
<span class="check-box"></span>
|
||||
<span class="check-text">我已阅读并同意演示使用说明</span>
|
||||
</label>
|
||||
@@ -105,16 +86,10 @@
|
||||
</div>
|
||||
|
||||
<div class="login-actions">
|
||||
<van-button
|
||||
block
|
||||
round
|
||||
type="primary"
|
||||
native-type="submit"
|
||||
:loading="isSubmitting"
|
||||
:disabled="submitDisabled"
|
||||
>
|
||||
<van-button block round type="primary" native-type="submit" :loading="isSubmitting"
|
||||
:disabled="submitDisabled">
|
||||
模拟登录
|
||||
</van-button>
|
||||
</van-button>
|
||||
<van-button block round plain type="primary" native-type="button" @click="clearForm">
|
||||
清空输入
|
||||
</van-button>
|
||||
@@ -133,7 +108,7 @@
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
@@ -393,7 +368,7 @@ const handleSubmit = async () => {
|
||||
margin-top: 18px;
|
||||
}
|
||||
|
||||
.field-group + .field-group {
|
||||
.field-group+.field-group {
|
||||
margin-top: 14px;
|
||||
}
|
||||
|
||||
@@ -521,12 +496,12 @@ const handleSubmit = async () => {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.check-input:checked + .check-box {
|
||||
.check-input:checked+.check-box {
|
||||
border-color: #2563eb;
|
||||
background: #2563eb;
|
||||
}
|
||||
|
||||
.check-input:checked + .check-box::after {
|
||||
.check-input:checked+.check-box::after {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,93 +1,101 @@
|
||||
<template>
|
||||
<div class="head">
|
||||
<img src="http://gree.pccsh.com/images/site/logo.png" class="logo" /><br />
|
||||
【驰骋四海·社区版】
|
||||
</div>
|
||||
<div>
|
||||
|
||||
✧当前在线<strong> 139 </strong>位玩家在驰骋四海✧
|
||||
</div>
|
||||
<div class="content" style="font-size:17px">
|
||||
<div>
|
||||
亲爱的 <strong style="color:red">探玩玩家</strong>,欢迎来到驰骋四海·社区版!
|
||||
</div>
|
||||
<div style="margin-top:5px;">
|
||||
<div>
|
||||
➢<a href="http://m.twbar.cn/Home/Index?sid=KrWxKypJuDO0zFKrTig0bG">返回探玩驿站</a>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
➸<a href="http://m.twbar.cn/b/1145?sid=KrWxKypJuDO0zFKrTig0bG">游戏论坛</a> ➸<a class="" href="/Login/LoginOut?sid=klxy7ADn96CBYGWQ9AG4xPqFC2Ib6Ty1Kx">退出游戏</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="common">
|
||||
<div class="title">
|
||||
=====☆<a class="" href="/Pallet/GameOpen/GameUser?sid=klxy7ADn96CBYGWQ9AG4xPqFC2Ib6Ty1Kx">我的区服</a>☆=====
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="item">
|
||||
<a href="/LoginGame/LoginOk?sid=W6Wg8iH9gY7wIBNSEdtFcQ3KbI5YiKDo">✧【1区】新手村✰村长(男)</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="common">
|
||||
<div class="title">
|
||||
=====☆其他区服☆=====
|
||||
</div>
|
||||
<div class="content">
|
||||
<span>暂无区服.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="head">
|
||||
<img src="http://gree.pccsh.com/images/site/logo.png" class="logo" /><br />
|
||||
【驰骋四海·社区版】
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<div class="title">
|
||||
=====☆<a class="" href="/Pallet/Notice/Index?sid=klxy7ADn96CBYGWQ9AG4xPqFC2Ib6Ty1Kx">官方公告</a>☆=====
|
||||
</div>
|
||||
✧当前在线<strong> 139 </strong>位玩家在驰骋四海✧
|
||||
</div>
|
||||
<div class="content" style="font-size:17px">
|
||||
<div>
|
||||
<div class="item">
|
||||
1.
|
||||
<a class="" href="/Pallet/Notice/Detail?nt=2026041901&sid=klxy7ADn96CBYGWQ9AG4xPqFC2Ib6Ty1Kx">[招募令]航海时代2设计专员招募</a>
|
||||
</div>
|
||||
<div class="item">
|
||||
2.
|
||||
<a class="" href="/Pallet/Notice/Detail?nt=2026041701&sid=klxy7ADn96CBYGWQ9AG4xPqFC2Ib6Ty1Kx">[活动]4月份活动集锦</a>
|
||||
</div>
|
||||
<div class="item">
|
||||
3.
|
||||
<a class="" href="/Pallet/Notice/Detail?nt=2026040901&sid=klxy7ADn96CBYGWQ9AG4xPqFC2Ib6Ty1Kx">[推广] 4月份推广</a>
|
||||
</div>
|
||||
<div class="item">
|
||||
4.
|
||||
<a class="" href="/Pallet/Notice/Detail?nt=2026030101&sid=klxy7ADn96CBYGWQ9AG4xPqFC2Ib6Ty1Kx">[推广] 3月份推广</a>
|
||||
</div>
|
||||
<div class="item">
|
||||
5.
|
||||
<a class="" href="/Pallet/Notice/Detail?nt=2025080002&sid=klxy7ADn96CBYGWQ9AG4xPqFC2Ib6Ty1Kx">【驰骋四海】卡片の攻略(2.24)</a>
|
||||
</div>
|
||||
亲爱的 <strong style="color:red">探玩玩家</strong>,欢迎来到驰骋四海·社区版!
|
||||
</div>
|
||||
<div style="margin-top:5px;">
|
||||
<div>
|
||||
➢<a href="http://m.twbar.cn/Home/Index?sid=KrWxKypJuDO0zFKrTig0bG">返回探玩驿站</a>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
➸<a href="http://m.twbar.cn/b/1145?sid=KrWxKypJuDO0zFKrTig0bG">游戏论坛</a> ➸<a class=""
|
||||
href="/Login/LoginOut?sid=klxy7ADn96CBYGWQ9AG4xPqFC2Ib6Ty1Kx">退出游戏</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="common">
|
||||
<div class="title">
|
||||
=====☆服务导航☆=====
|
||||
=====☆<a class="" href="/Pallet/GameOpen/GameUser?sid=klxy7ADn96CBYGWQ9AG4xPqFC2Ib6Ty1Kx">我的区服</a>☆=====
|
||||
</div>
|
||||
<div class="content">
|
||||
<a class="" href="/Index/Kefu?sid=klxy7ADn96CBYGWQ9AG4xPqFC2Ib6Ty1Kx">客服</a>.<a class="" href="/Index/About?sid=klxy7ADn96CBYGWQ9AG4xPqFC2Ib6Ty1Kx">关于</a>.<a class="" href="/Index/Cooperation?sid=klxy7ADn96CBYGWQ9AG4xPqFC2Ib6Ty1Kx">合作</a>
|
||||
<div class="item">
|
||||
<a href="/LoginGame/LoginOk?sid=W6Wg8iH9gY7wIBNSEdtFcQ3KbI5YiKDo">✧【1区】新手村✰村长(男)</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="common">
|
||||
<div class="title">
|
||||
=====☆其他区服☆=====
|
||||
</div>
|
||||
<div class="content">
|
||||
切换线路:
|
||||
<span class="game_line">
|
||||
<a class="" href="http://g.pccsh.com:5016/Index/Index?sid=klxy7ADn96CBYGWQ9AG4xPqFC2Ib6Ty1Kx">1</a>
|
||||
</span>
|
||||
<span>暂无区服.</span>
|
||||
</div>
|
||||
<div class="foot">
|
||||
<div class="timeService">
|
||||
小G报时(18:33)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="title">
|
||||
=====☆<a class="" href="/Pallet/Notice/Index?sid=klxy7ADn96CBYGWQ9AG4xPqFC2Ib6Ty1Kx">官方公告</a>☆=====
|
||||
</div>
|
||||
<div>
|
||||
<div class="item">
|
||||
1.
|
||||
<a class=""
|
||||
href="/Pallet/Notice/Detail?nt=2026041901&sid=klxy7ADn96CBYGWQ9AG4xPqFC2Ib6Ty1Kx">[招募令]航海时代2设计专员招募</a>
|
||||
</div>
|
||||
<div class="item">
|
||||
2.
|
||||
<a class="" href="/Pallet/Notice/Detail?nt=2026041701&sid=klxy7ADn96CBYGWQ9AG4xPqFC2Ib6Ty1Kx">[活动]4月份活动集锦</a>
|
||||
</div>
|
||||
<div class="item">
|
||||
3.
|
||||
<a class="" href="/Pallet/Notice/Detail?nt=2026040901&sid=klxy7ADn96CBYGWQ9AG4xPqFC2Ib6Ty1Kx">[推广] 4月份推广</a>
|
||||
</div>
|
||||
<div class="item">
|
||||
4.
|
||||
<a class="" href="/Pallet/Notice/Detail?nt=2026030101&sid=klxy7ADn96CBYGWQ9AG4xPqFC2Ib6Ty1Kx">[推广] 3月份推广</a>
|
||||
</div>
|
||||
<div class="item">
|
||||
5.
|
||||
<a class=""
|
||||
href="/Pallet/Notice/Detail?nt=2025080002&sid=klxy7ADn96CBYGWQ9AG4xPqFC2Ib6Ty1Kx">【驰骋四海】卡片の攻略(2.24)</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="title">
|
||||
=====☆服务导航☆=====
|
||||
</div>
|
||||
<div class="content">
|
||||
<a class="" href="/Index/Kefu?sid=klxy7ADn96CBYGWQ9AG4xPqFC2Ib6Ty1Kx">客服</a>.<a class=""
|
||||
href="/Index/About?sid=klxy7ADn96CBYGWQ9AG4xPqFC2Ib6Ty1Kx">关于</a>.<a class=""
|
||||
href="/Index/Cooperation?sid=klxy7ADn96CBYGWQ9AG4xPqFC2Ib6Ty1Kx">合作</a>
|
||||
</div>
|
||||
<div class="content">
|
||||
切换线路:
|
||||
<span class="game_line">
|
||||
<a class="" href="http://g.pccsh.com:5016/Index/Index?sid=klxy7ADn96CBYGWQ9AG4xPqFC2Ib6Ty1Kx">1</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="foot">
|
||||
<div class="timeService">
|
||||
小G报时(18:33)
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
// MessageExtend.showToast('success', '更新成功!')
|
||||
MessageExtend.notifyList('primary', ['获取装备'])
|
||||
|
||||
definePageMeta({
|
||||
layout: layout.empty
|
||||
})
|
||||
showNotify({ message: '提示' });
|
||||
// await navigateTo('/auth/login', { replace: true })
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user