This commit is contained in:
oneao committed 2025-11-21 17:27:44 +08:00
1 parent bb780a42ab
commit d3145e3dc5
19 files changed
+15364 -416

No files matched your search

+71 -332
View File
@@ -1,337 +1,76 @@
<!doctype html>
<html lang="zh-CN">
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover" />
<title>共享空间 — 邀请 / 加入</title>
<style>
:root{
--bg: #f6f7fb;
--card: #ffffff;
--muted: #9aa4b2;
--accent: #5b8cff;
--danger: #ff6b6b;
--radius: 12px;
--gap: 12px;
--shadow: 0 6px 18px rgba(22,27,40,0.06);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial;
}
/* Reset / basic */
*{box-sizing:border-box}
html,body{height:100%}
body{
margin:0;
background:linear-gradient(180deg, var(--bg), #eef2ff 60%);
color:#0f1724;
-webkit-font-smoothing:antialiased;
-moz-osx-font-smoothing:grayscale;
padding:16px;
}
/* Container */
.screen{
max-width:480px;
margin:0 auto;
}
header.appbar{
display:flex;
align-items:center;
gap:12px;
padding:8px 4px;
margin-bottom:12px;
}
.title{
font-size:18px;
font-weight:600;
}
.subtitle{
display:block;
font-size:12px;
color:var(--muted);
margin-top:2px;
}
/* Cards */
.card{
background:var(--card);
border-radius:var(--radius);
box-shadow:var(--shadow);
padding:14px;
margin-bottom:var(--gap);
}
/* Invite area */
.invite-top{
display:flex;
gap:12px;
align-items:center;
}
.space-avatar{
width:56px;height:56px;border-radius:12px;background:linear-gradient(135deg,#7fb6ff,#5b8cff);
display:flex;align-items:center;justify-content:center;color:#fff;font-weight:700;font-size:20px;
}
.space-info{
flex:1;
}
.space-name{font-weight:600;font-size:16px}
.space-meta{font-size:12px;color:var(--muted);margin-top:4px}
.invite-row{
margin-top:12px;display:flex;gap:8px;
}
.btn{
flex:1;
border:0;padding:10px 12px;border-radius:10px;font-weight:600;
background:var(--accent);color:#fff;cursor:pointer;
box-shadow:0 6px 12px rgba(91,140,255,0.18);
}
.btn.ghost{background:transparent;color:var(--accent);border:1px solid rgba(91,140,255,0.12);box-shadow:none}
.btn.danger{background:var(--danger);box-shadow:0 6px 12px rgba(255,107,107,0.16)}
/* Invite code box */
.code-box{display:flex;align-items:center;justify-content:space-between;padding:10px;border-radius:10px;background:#f4f7ff;border:1px dashed rgba(91,140,255,0.18)}
.code-text{font-weight:700;letter-spacing:2px;font-size:16px}
.code-actions{display:flex;gap:8px}
/* Join section */
.join-input{
display:flex;gap:8px;margin-top:8px;
}
.input{
flex:1;padding:10px;border-radius:10px;border:1px solid #e6e9ef;background:#fff;
font-size:14px;
}
.help-line{font-size:12px;color:var(--muted);margin-top:8px}
/* Recent invites / list */
.list-row{display:flex;align-items:center;justify-content:space-between;padding:10px 0;border-top:1px solid #f2f4f8}
.list-left{display:flex;align-items:center;gap:10px}
.small-avatar{width:36px;height:36px;border-radius:8px;background:#eef4ff;display:flex;align-items:center;justify-content:center;color:#3759c8;font-weight:700}
.list-title{font-weight:600}
.list-sub{font-size:12px;color:var(--muted)}
/* Modal (simple) */
.overlay{position:fixed;left:0;right:0;top:0;bottom:0;background:rgba(8,10,15,0.45);display:flex;align-items:center;justify-content:center;padding:20px;z-index:80}
.modal{width:100%;max-width:420px;border-radius:14px;background:var(--card);padding:16px;box-shadow:var(--shadow)}
.modal .h1{font-weight:700;margin-bottom:8px}
.modal .muted{color:var(--muted);font-size:13px;margin-bottom:12px}
.share-grid{display:flex;gap:8px;flex-wrap:wrap}
.share-chip{flex:0 0 30%;min-width:84px;padding:10px;border-radius:10px;background:#f7f9ff;text-align:center;font-size:13px;color:#123;background:linear-gradient(180deg,#fff,#f7f9ff);cursor:pointer}
.copy-toast{position:fixed;left:50%;transform:translateX(-50%);bottom:22px;padding:8px 14px;background:rgba(0,0,0,0.7);color:#fff;border-radius:20px;font-size:13px;z-index:90}
/* Footer hint */
.hint{font-size:12px;color:var(--muted);text-align:center;margin-top:12px}
/* small screens */
@media (max-width:360px){
.btn{padding:10px}
.space-avatar{width:48px;height:48px;font-size:18px}
}
</style>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>DataGrid Virtual Scrolling - jQuery EasyUI Demo</title>
<link rel="stylesheet" type="text/css" href="https://www.jeasyui.com/easyui/themes/default/easyui.css">
<link rel="stylesheet" type="text/css" href="https://www.jeasyui.com/easyui/themes/icon.css">
<script type="text/javascript" src="https://www.jeasyui.com/easyui/jquery.min.js"></script>
<script type="text/javascript" src="https://www.jeasyui.com/easyui/jquery.easyui.min.js"></script>
<script type="text/javascript" src="https://www.jeasyui.com/easyui/datagrid-scrollview.js"></script>
</head>
<body>
<div class="screen">
<header class="appbar">
<div style="width:44px;"></div>
<div>
<div class="title">共享空间</div>
<div class="subtitle">邀请别人加入你的空间,或输入邀请码加入别人空间</div>
<h2>DataGrid Virtual Scroll View Demo</h2>
<p>Drag the vertical scroll and release it to navigate to the desired page.</p>
<div style="margin-bottom:10px">
<select onchange="load(this.value)">
<option value="remote">Load Remote Data</option>
<option value="local">Load Local Data</option>
</select>
</div>
</header>
<!-- Invite card -->
<section class="card">
<div class="invite-top">
<div class="space-avatar" id="spaceAvatar">A</div>
<div class="space-info">
<div class="space-name" id="spaceName">工作协作空间</div>
<div class="space-meta">成员 12 • 权限 管理者</div>
</div>
<div style="width:68px;text-align:right"><button class="btn ghost" id="manageBtn">管理</button></div>
</div>
<div style="margin-top:14px">
<div class="code-box" id="codeBox">
<div class="code-text" id="inviteCode">AB12-CD34</div>
<div class="code-actions">
<button class="btn ghost" id="copyBtn">复制</button>
<button class="btn" id="shareBtn">分享</button>
</div>
</div>
<div class="invite-row">
<button class="btn ghost" id="qrBtn">二维码</button>
<button class="btn ghost" id="linkBtn">链接</button>
<button class="btn danger" id="revokeBtn">撤销并重置</button>
</div>
</div>
<div class="hint">邀请码有效期:24小时 · 点击分享可选择渠道</div>
</section>
<!-- Join other -->
<section class="card" aria-label="加入他人空间">
<div style="display:flex;align-items:center;justify-content:space-between;">
<div style="font-weight:700">加入别人的空间</div>
<div class="list-sub">通过邀请码或扫码加入</div>
</div>
<div class="join-input">
<input class="input" id="joinInput" placeholder="输入邀请码或链接(例如:AB12-CD34)" />
<button class="btn" id="joinBtn">加入</button>
</div>
<div class="help-line">若对方使用链接邀请,可直接粘贴链接;扫码请使用 App 内相机。</div>
<div style="margin-top:12px">
<div style="font-weight:600;margin-bottom:8px">最近加入的空间</div>
<div class="list-row">
<div class="list-left">
<div class="small-avatar">P</div>
<div>
<div class="list-title">产品设计空间</div>
<div class="list-sub">邀请人:小李 · 2 天前</div>
</div>
</div>
<div style="text-align:right;">
<div class="list-sub">成员 8</div>
</div>
</div>
<div class="list-row">
<div class="list-left">
<div class="small-avatar">M</div>
<div>
<div class="list-title">市场推广</div>
<div class="list-sub">邀请人:小王 · 1 周前</div>
</div>
</div>
<div style="text-align:right;">
<div class="list-sub">成员 20</div>
</div>
</div>
</div>
</section>
<!-- footer actions -->
<div style="display:flex;gap:8px;margin-top:8px">
<button class="btn ghost" style="flex:1" id="createSpace">创建新空间</button>
<button class="btn" style="flex:1" id="explore">发现空间</button>
</div>
<div style="height:40px"></div>
</div>
<!-- Modal markup (hidden initially) -->
<div id="modalOverlay" class="overlay" style="display:none;">
<div class="modal" role="dialog" aria-modal="true">
<div class="h1">分享邀请</div>
<div class="muted">选择一种方式邀请你的成员</div>
<div class="share-grid" style="margin-bottom:12px;">
<div class="share-chip" data-action="wechat">微信</div>
<div class="share-chip" data-action="qq">QQ</div>
<div class="share-chip" data-action="link">复制链接</div>
<div class="share-chip" data-action="sms">短信</div>
<div class="share-chip" data-action="email">邮件</div>
<div class="share-chip" data-action="more">更多</div>
</div>
<div style="display:flex;gap:8px;justify-content:flex-end">
<button class="btn ghost" onclick="closeModal()">取消</button>
<button class="btn" id="modalShare">分享</button>
</div>
</div>
</div>
<!-- toast -->
<div id="copyToast" class="copy-toast" style="display:none;">已复制到剪贴板</div>
<script>
// demo interactions
const inviteCodeEl = document.getElementById('inviteCode');
const copyBtn = document.getElementById('copyBtn');
const shareBtn = document.getElementById('shareBtn');
const modal = document.getElementById('modalOverlay');
const copyToast = document.getElementById('copyToast');
const joinInput = document.getElementById('joinInput');
const joinBtn = document.getElementById('joinBtn');
// copy code
copyBtn.addEventListener('click', async () => {
const code = inviteCodeEl.textContent.trim();
try {
await navigator.clipboard.writeText(code);
showToast('已复制邀请码');
} catch (e) {
showToast('复制失败,请手动复制');
}
});
// open share modal
shareBtn.addEventListener('click', () => openModal());
document.getElementById('qrBtn').addEventListener('click', ()=> {
alert('打开二维码生成器(示例占位)');
});
document.getElementById('linkBtn').addEventListener('click', ()=> {
alert('打开链接分享(示例占位)');
});
document.getElementById('revokeBtn').addEventListener('click', ()=> {
const newCode = randomCode();
inviteCodeEl.textContent = newCode;
showToast('邀请码已重置');
});
// join
joinBtn.addEventListener('click', ()=> {
const v = (joinInput.value || '').trim();
if (!v) return showToast('请输入邀请码或链接');
// 简单验证格式示例
const matched = /^[A-Z0-9]{2,}-[A-Z0-9]{2,}$/.test(v) || v.includes('http');
if (!matched) return showToast('邀请码格式不正确');
showToast('加入请求已发送');
// TODO: 调用后端 API 加入空间
});
// modal actions
function openModal(){ modal.style.display='flex'; }
function closeModal(){ modal.style.display='none'; }
document.getElementById('modalShare').addEventListener('click', ()=>{
// 示例:复制链接并关闭
const fakeLink = location.href + '?invite=' + inviteCodeEl.textContent.trim();
navigator.clipboard.writeText(fakeLink).catch(()=>{});
showToast('邀请链接已复制');
closeModal();
});
// copy chips
document.querySelectorAll('.share-chip').forEach(el=>{
el.addEventListener('click', ()=> {
const action = el.getAttribute('data-action');
if (action === 'link') {
const fakeLink = location.href + '?invite=' + inviteCodeEl.textContent.trim();
navigator.clipboard.writeText(fakeLink).then(()=> showToast('链接已复制'));
} else {
showToast('已选择:' + action);
}
})
});
// small utilities
function showToast(text){
copyToast.textContent = text;
copyToast.style.display = 'block';
setTimeout(()=> copyToast.style.display='none', 1500);
}
function randomCode(){
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
const pick = (n)=> Array.from({length:n}).map(()=>chars[Math.floor(Math.random()*chars.length)]).join('');
return pick(2)+'-'+pick(4);
}
</script>
<table id="tt" title="DataGrid - VirtualScrollView" style="width:700px;height:300px" data-options="
view:scrollview,rownumbers:true,singleSelect:true,
url:'datagrid27_getdata.php',
idField:'inv',autoRowHeight:false,pageSize:50">
<thead>
<tr>
<th field="inv" width="80">Inv No</th>
<th field="date" width="100">Date</th>
<th field="name" width="80">Name</th>
<th field="amount" width="80" align="right">Amount</th>
<th field="price" width="80" align="right">Price</th>
<th field="cost" width="100" align="right">Cost</th>
<th field="note" width="110">Note</th>
</tr>
</thead>
</table>
<script type="text/javascript">
$(function(){
$('#tt').datagrid();
});
function loadLocal(){
var rows = [];
for(var i=1; i<=8000; i++){
var amount = Math.floor(Math.random()*1000);
var price = Math.floor(Math.random()*1000);
rows.push({
inv: 'Inv No '+i,
date: $.fn.datebox.defaults.formatter(new Date()),
name: 'Name '+i,
amount: amount,
price: price,
cost: amount*price,
note: 'Note '+i
});
}
$('#tt').datagrid('loadData', rows);
}
function load(mode){
if (mode == 'local'){
loadLocal();
} else {
$('#tt').datagrid({
url:'datagrid27_getdata.php'
});
}
}
</script>
<style type="text/css">
.datagrid-header-rownumber,.datagrid-cell-rownumber{
width:40px;
}
</style>
</body>
</html>
</html>