Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 7, 2025

Per user requirements, enhances the JS Playground with loading indication, access control, and mobile support while maintaining minimal changes to existing codebase.

Loading Progress Indicator

  • Full-screen overlay with progress bar tracking initialization stages (0-100%)
  • Progress stages: Vue init → config loading → TypeScript compiler → Monaco Editor → complete
  • Stage-specific messages inform users during load

Password Protection

Backend configuration in app-dev.yml:

playground:
  public: false  # Default: requires password
  password: 'nfd_playground_2024'  # User-configurable
  • New endpoints: GET /v2/playground/status, POST /v2/playground/login
  • Session-based auth protects all playground APIs including /types.js
  • PlaygroundConfig singleton loads from config, logs security warnings for default password
  • Frontend shows lock UI with gradient background when auth required

Mobile Responsive Layout

  • Auto-detects viewport ≤768px, switches from horizontal to vertical split
  • Desktop: left-right editor/test panes with col-resize
  • Mobile: top-bottom layout with row-resize
  • Computed property shouldShowAuthUI simplifies conditional rendering

Documentation

  • PLAYGROUND_PASSWORD_PROTECTION.md: configuration guide, API endpoints, security recommendations
  • Updated README.md with documentation link

All endpoints now verify authentication via checkAuth(ctx) before processing. Public mode bypasses auth when playground.public: true.

Original prompt

下面先给你一个整体设计思路,然后按功能 1/2/3 分开说具体实现方案,保持尽量贴近你现有代码(前后端都要改),也方便后面继续在当前分支上编码。


总体说明

你现在的状态是:

  • 已经在 copilot/add-typescript-compiler-integration 分支上:
    • 前端 playground 已接入 TypeScript 编译(tsc.js / typescript.js)
    • 后端有 TS 表 + API
  • 打包已经在压缩 JS,但 /playground 页面因为要加载编译器和前端代码,在网慢时会有“白屏等待”的体验问题。

你新提的需求:

  1. /playground 页面需要加载动画 + 进度条,提升慢网环境体验。
  2. /playground 访问需要密码保护
    • 默认必须输入密码;
    • 可以通过配置文件切到 public 模式。
  3. playground 需要更好适配手机
    • 之前左右拖拽布局,移动端改成上下布局。
  4. 用户可以用 TS + 现代 JS 写解析器(tsc.js 已加入)——当前 PR 已经在做,后面只要完善体验和文档。

下面分点说实现方案(会以“怎么改前端/后端”为主)。


A. Playground 加载动画 + 进度条

你打包策略已经在压缩 JS,这部分不用改。我们主要在前端做:

1. 加载什么的时候显示?

Playground.vue 加载过程一般有几步:

  • Vue/JS 本身加载(这一步只能靠浏览器自带 loading + skeleton,没有太细颗粒进度)。
  • 首次访问时,tsc/TypeScript 编译器 JS 被加载(你的 9MB+ 文件);
  • 调 playground 初始化接口(加载示例、历史记录等)。

为了用户有感知,建议这样:

  • 页面一载入,就显示一个“全屏 loading 蒙层 + 进度条”;
  • 随着:
    1. Vue 初始化完成(0% → 20%)
    2. playground 基本 UI 渲染完成(20% → 40%)
    3. TypeScript 编译器加载成功(40% → 80%)
    4. 初始化数据加载完(80% → 100%)
  • 全部完成后,淡出 loading 层。

2. 前端实现要点(Vue)

Playground.vue 增加:

data() {
  return {
    loading: true,
    loadProgress: 0,
    // ... 原有数据
  };
},
created() {
  this.initPlayground();
},
methods: {
  async initPlayground() {
    try {
      this.setProgress(10);          // Vue 实例已创建
      // 1. 加载初始化数据(例如语言偏好、本地缓存)
      this.setProgress(20);

      // 2. 加载 TS 编译器(如果未加载)
      await this.ensureTsLoaded();   // 内部动态加载 typescript.js/tsc.js
      this.setProgress(70);

      // 3. 调后端 API 拉取初始脚本 / 示例
      await this.loadInitialScript();
      this.setProgress(100);
    } finally {
      setTimeout(() => { this.loading = false; }, 300);
    }
  },
  setProgress(p) {
    if (p > this.loadProgress) this.loadProgress = p;
  },
  async ensureTsLoaded() {
    if (window.ts) {
      return;
    }
    await this.loadScript('/static/ts/typescript.js', (p) => {
      // 如果能拿到下载进度可以合并到进度条上,这里可以先简单地分段
      this.setProgress(20 + Math.floor(p * 0.4)); // 20~60
    });
  },
  loadScript(src, onProgress) {
    return new Promise((resolve, reject) => {
      const script = document.createElement('script');
      script.src = src;
      script.onload = () => resolve(null);
      script.onerror = reject;
      document.head.appendChild(script);
    });
  }
}

模板中加一个加载蒙层(不改原布局,只上一个绝对定位层):

<div v-if="loading" class="playground-loading-overlay">
  <div class="playground-loading-card">
    <div class="loading-text">正在加载编辑器和编译器...</div>
    <div class="loading-bar">
      <div class="loading-bar-inner" :style="{ width: loadProgress + '%' }"></div>
    </div>
    <div class="loading-percent">{{ loadProgress }}%</div>
  </div>
</div>

配套 CSS 放在 Playground.vue<style scoped> 或全局:

.playground-loading-overlay {
  position: fixed;
  inset: 0;
  background: rgba(255, 255, 255, 0.95);
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
}

.playground-loading-card {
  width: 260px;
  padding: 16px 20px;
  background: #fff;
  box-shadow: 0 2px 12px rgba(0,0,0,0.08);
  border-radius: 6px;
  text-align: center;
  font-size: 13px;
}

.loading-bar {
  width: 100%;
  height: 4px;
  background: #f0f0f0;
  border-radius: 2px;
  margin: 8px 0;
  overflow: hidden;
}
.loading-bar-inner {
  height: 100%;
  background: #409eff;
  transition: width 0.2s ease;
}
.loading-percent {
  font-size: 12px;
  color: #999;
}

以后如果要更真实的下载进度,可以改 loadScriptXMLHttpRequest/fetch + Blob + URL.createObjectURL,在 onprogress 回调里更新进度。


B. /playground 密码访问 & public 模式开关

1. 配置设计

在后端配置(例如 application.yml 或你现有的配置系统)增加:

playground:
  public: false        # 默认 false,即需要密码
  password: "xxxxxx"   # 默认密码,可自行设定

或如果你已有类似的 ParserConfig / WebConfig,可以放进去。

2. 后端访问控制(推荐“轻量级登录态”方式)

需求是“配置密码访问”,不是完整账号系统,可以做一个简单版:

方案

  • 提供一个后端接口,例如:
    • POST /api/playground/login,入参:password
    • 后端根据配置校验密码:
      • 如果 playground.public == true:直接返回成功,不需要密码。
      • 如果 false:密码不等则 401。
  • 成功后:
    • 返回一个短期 token(简单一点可以是签名字符串,不必 JWT),或者直接通过 HttpSession 记录状态。
  • 然后在:
    • /playground 页面对应后端渲染 / static controller;
    • /v2/playground/** REST 接口;
    • 校验当前会话是否已通过验证,如果未验证则:
      • 要么直接返回 401,由前端跳转到密码输入页。
      • 要么后端拦截 /playground GET 请求,返回一个简单的“输入密码”页面(你前端也可以自己实现这一层 Vue)。

从你项目现状看,你已经是前后端分离(web-front + web-service),更合适做法是:

  • web-service 控制 /v2/playground/** 等 API;
  • web-frontPlayground.vue 加一个“密码校验界面”,在调用任何 API 前先验证。

后端伪代码(PlaygroundApi 增加)

@PostMapping("/v2/playground/login")
public Response login(@RequestBody PlaygroundLoginRequest req, HttpServletRequest request) {
    if (playgroundConfig.isPublic()) {
        // 公共模式,直接通过
        request.getSession(true).setAttribute("playgroundAuthed", true);
        return Response.ok();
    }

    if (StringUtils.equals(req.getPassword(), playgroundConfig.getPassword())) {
        request.getSession(true).setAttribute("playgroundAuthed", true);
        return Response.ok();
    } else {
        return Response.fai...

</details>



<!-- START COPILOT CODING AGENT TIPS -->
---

✨ Let Copilot coding agent [set things up for you](https://github.com/qaiu/netdisk-fast-download/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot) — coding agent works faster and does higher quality work when set up for your repo.

…pport

Co-authored-by: qaiu <29825328+qaiu@users.noreply.github.com>
@gitguardian
Copy link

gitguardian bot commented Dec 7, 2025

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secret in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
23192782 Triggered Generic Password 5fbbe5b web-service/src/main/java/cn/qaiu/lz/web/config/PlaygroundConfig.java View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

1 similar comment
@gitguardian
Copy link

gitguardian bot commented Dec 7, 2025

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secret in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
23192782 Triggered Generic Password 5fbbe5b web-service/src/main/java/cn/qaiu/lz/web/config/PlaygroundConfig.java View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

Copilot AI and others added 2 commits December 7, 2025 05:24
Co-authored-by: qaiu <29825328+qaiu@users.noreply.github.com>
…ode readability

Co-authored-by: qaiu <29825328+qaiu@users.noreply.github.com>
Copilot AI changed the title [WIP] Add loading animation and progress bar to playground page Add Playground loading progress, password protection, and mobile responsive layout Dec 7, 2025
Copilot AI requested a review from qaiu December 7, 2025 05:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants