refactor: move HarmonyOS project files from harmony/ to branch root

This commit is contained in:
root
2026-04-28 16:52:05 +08:00
parent 4c32dbb949
commit 11ee329943
120 changed files with 0 additions and 0 deletions

View File

@ -0,0 +1,8 @@
{
"color": [
{
"name": "start_window_background",
"value": "#FFFFFF"
}
]
}

View File

@ -0,0 +1,20 @@
{
"string": [
{
"name": "app_name",
"value": "TrulyMEM"
},
{
"name": "module_desc",
"value": "True Memory Engine"
},
{
"name": "EntryAbility_desc",
"value": "TrulyMEM Main Ability"
},
{
"name": "EntryAbility_label",
"value": "TrulyMEM"
}
]
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="200" height="200">
<rect width="200" height="200" rx="30" fill="#6366f1"/>
<text x="100" y="130" font-family="Arial" font-size="80" fill="white" text-anchor="middle" font-weight="bold">T</text>
</svg>

After

Width:  |  Height:  |  Size: 313 B

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="200" height="200">
<rect width="200" height="200" rx="20" fill="#6366f1"/>
<text x="100" y="130" font-family="Arial" font-size="60" fill="white" text-anchor="middle" font-weight="bold">TM</text>
</svg>

After

Width:  |  Height:  |  Size: 314 B

View File

@ -0,0 +1,5 @@
{
"src": [
"pages/Index"
]
}

View File

@ -0,0 +1,302 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>记忆星图 - TrulyMEM</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: 'Courier New', monospace; background: #0a0a1a; color: #ffffff; overflow: hidden; width: 100vw; height: 100vh; }
#canvas-container { width: 100%; height: 100%; position: relative; }
canvas { display: block; }
#stats { position: absolute; top: 20px; left: 20px; background: rgba(10, 10, 26, 0.8); padding: 15px 20px; border-radius: 8px; border: 1px solid rgba(100, 100, 255, 0.3); font-size: 14px; z-index: 100; backdrop-filter: blur(10px); }
#stats h3 { margin-bottom: 8px; color: #4488ff; font-size: 16px; }
#stats p { margin: 4px 0; color: #aaaacc; }
#stats span { color: #ffffff; font-weight: bold; }
#node-info { position: absolute; top: 20px; right: 20px; background: rgba(10, 10, 26, 0.9); padding: 15px 20px; border-radius: 8px; border: 1px solid rgba(100, 100, 255, 0.3); font-size: 14px; z-index: 100; display: none; backdrop-filter: blur(10px); max-width: 300px; }
#node-info h3 { color: #44ff88; margin-bottom: 8px; font-size: 16px; }
#node-info p { margin: 4px 0; color: #aaaacc; }
#node-info .label { color: #8888aa; }
#loading { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 20px; color: #4488ff; z-index: 200; }
#nav { position: absolute; bottom: 30px; left: 50%; transform: translateX(-50%); display: flex; gap: 20px; z-index: 100; }
.nav-btn { background: rgba(10, 10, 26, 0.8); border: 1px solid rgba(100, 100, 255, 0.3); color: #aaaacc; padding: 12px 24px; border-radius: 8px; cursor: pointer; font-family: 'Courier New', monospace; font-size: 14px; backdrop-filter: blur(10px); }
</style>
</head>
<body>
<div id="canvas-container">
<div id="loading">正在加载星图数据...</div>
<div id="stats">
<h3>🌌 记忆星图</h3>
<p>节点: <span id="node-count">0</span></p>
<p>边: <span id="edge-count">0</span></p>
<p>状态: <span id="status">初始化中...</span></p>
</div>
<div id="node-info">
<h3 id="info-name"></h3>
<p><span class="label">类型:</span> <span id="info-type"></span></p>
<p><span class="label">提及次数:</span> <span id="info-mentions"></span></p>
<p><span class="label">连接数:</span> <span id="info-links"></span></p>
</div>
<div id="nav">
<button class="nav-btn active">🌌 星图</button>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
let scene, camera, renderer, controls;
let nodes = [], edges = [];
let nodeMeshes = [], edgeLines = [];
let starField, nebulaParticles;
let raycaster, mouse;
let hoveredNode = null, selectedNode = null;
let animationId;
let highlightPulse = 0;
const typeColors = { 'person': 0x4488ff, 'task': 0xff8844, 'ai': 0xaa44ff, 'concept': 0x44ff88, 'object': 0xff4444 };
const defaultColor = 0xcccccc;
const edgeColors = { '喜欢': 0xff6b6b, '学习': 0x4ecdc4, '属于': 0x45b7d1, '相关': 0x96ceb4, '使用': 0xfeca57, '创建': 0xff9ff3 };
const defaultEdgeColor = 0x444466;
function init() {
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2(0x0a0a1a, 0.015);
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.set(0, 30, 60);
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setClearColor(0x0a0a1a, 1);
document.getElementById('canvas-container').appendChild(renderer.domElement);
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
const ambientLight = new THREE.AmbientLight(0x444466, 0.6);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(50, 100, 50);
scene.add(directionalLight);
raycaster = new THREE.Raycaster();
mouse = new THREE.Vector2();
createStarField();
createNebula();
window.addEventListener('resize', onWindowResize);
renderer.domElement.addEventListener('mousemove', onMouseMove);
renderer.domElement.addEventListener('click', onMouseClick);
window.addEventListener('message', (event) => {
if (event.data.type === 'graph_data') {
window.__graphData = event.data.payload;
loadGraphData();
}
});
window.parent.postMessage('request_graph_data', '*');
animate();
}
function createStarField() {
const starCount = 3000;
const positions = new Float32Array(starCount * 3);
const colors = new Float32Array(starCount * 3);
for (let i = 0; i < starCount; i++) {
const i3 = i * 3;
const radius = 400 + Math.random() * 600;
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos(2 * Math.random() - 1);
positions[i3] = radius * Math.sin(phi) * Math.cos(theta);
positions[i3 + 1] = radius * Math.sin(phi) * Math.sin(theta);
positions[i3 + 2] = radius * Math.cos(phi);
const colorChoice = Math.random();
if (colorChoice < 0.7) {
colors[i3] = 0.8 + Math.random() * 0.2;
colors[i3 + 1] = 0.8 + Math.random() * 0.2;
colors[i3 + 2] = 1.0;
} else {
colors[i3] = 1.0;
colors[i3 + 1] = 0.9 + Math.random() * 0.1;
colors[i3 + 2] = 0.8 + Math.random() * 0.2;
}
}
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({ size: 1.5, vertexColors: true, transparent: true, opacity: 0.8, sizeAttenuation: true });
starField = new THREE.Points(geometry, material);
scene.add(starField);
}
function createNebula() {
const nebulaCount = 500;
const positions = new Float32Array(nebulaCount * 3);
const colors = new Float32Array(nebulaCount * 3);
for (let i = 0; i < nebulaCount; i++) {
const i3 = i * 3;
positions[i3] = (Math.random() - 0.5) * 800;
positions[i3 + 1] = (Math.random() - 0.5) * 800;
positions[i3 + 2] = (Math.random() - 0.5) * 800;
const colorChoice = Math.random();
if (colorChoice < 0.33) {
colors[i3] = 0.5 + Math.random() * 0.3; colors[i3 + 1] = 0.2 + Math.random() * 0.2; colors[i3 + 2] = 0.7 + Math.random() * 0.3;
} else if (colorChoice < 0.66) {
colors[i3] = 0.2 + Math.random() * 0.2; colors[i3 + 1] = 0.3 + Math.random() * 0.3; colors[i3 + 2] = 0.8 + Math.random() * 0.2;
} else {
colors[i3] = 0.7 + Math.random() * 0.3; colors[i3 + 1] = 0.2 + Math.random() * 0.2; colors[i3 + 2] = 0.5 + Math.random() * 0.3;
}
}
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({ size: 8, vertexColors: true, transparent: true, opacity: 0.15, sizeAttenuation: true, blending: THREE.AdditiveBlending });
nebulaParticles = new THREE.Points(geometry, material);
scene.add(nebulaParticles);
}
window.loadGraphData = function(data) {
if (data && data.nodes && data.edges) {
nodes = data.nodes.map(n => ({ id: n.id, name: n.label || n.name, type: n.type, mention_count: n.mentions || 1 }));
edges = data.edges.map(e => ({ id: e.id, source: e.from || e.source, target: e.to || e.target, relation_type: e.label || e.relation }));
document.getElementById('node-count').textContent = nodes.length;
document.getElementById('edge-count').textContent = edges.length;
document.getElementById('status').textContent = '就绪';
createGraphVisualization();
document.getElementById('loading').style.display = 'none';
}
}
function createGraphVisualization() {
nodeMeshes.forEach(mesh => scene.remove(mesh));
edgeLines.forEach(line => scene.remove(line));
nodeMeshes = [];
edgeLines = [];
if (nodes.length === 0) return;
const nodeDegrees = {};
nodes.forEach(n => nodeDegrees[n.id] = 0);
edges.forEach(e => {
nodeDegrees[e.source] = (nodeDegrees[e.source] || 0) + 1;
nodeDegrees[e.target] = (nodeDegrees[e.target] || 0) + 1;
});
const positions = {};
const maxDegree = Math.max(...Object.values(nodeDegrees), 1);
nodes.forEach((node, i) => {
const angle = (i / nodes.length) * Math.PI * 2;
const radius = 15 + (nodeDegrees[node.id] / maxDegree) * 35;
positions[node.id] = { x: radius * Math.cos(angle), y: (Math.random() - 0.5) * 10, z: radius * Math.sin(angle) };
});
for (let iter = 0; iter < 50; iter++) {
Object.keys(positions).forEach(id1 => {
Object.keys(positions).forEach(id2 => {
if (id1 >= id2) return;
const pos1 = positions[id1], pos2 = positions[id2];
const dx = pos1.x - pos2.x, dy = pos1.y - pos2.y, dz = pos1.z - pos2.z;
const dist = Math.sqrt(dx*dx + dy*dy + dz*dz) + 0.1;
if (dist < 10) {
const force = 0.1 / dist;
pos1.x += (dx/dist)*force; pos1.y += (dy/dist)*force; pos1.z += (dz/dist)*force;
pos2.x -= (dx/dist)*force; pos2.y -= (dy/dist)*force; pos2.z -= (dz/dist)*force;
}
});
});
edges.forEach(edge => {
const pos1 = positions[edge.source], pos2 = positions[edge.target];
if (!pos1 || !pos2) return;
const dx = pos2.x - pos1.x, dy = pos2.y - pos1.y, dz = pos2.z - pos1.z;
const dist = Math.sqrt(dx*dx + dy*dy + dz*dz) + 0.1;
if (dist > 15) {
const force = 0.05;
pos1.x += (dx/dist)*force; pos1.y += (dy/dist)*force; pos1.z += (dz/dist)*force;
pos2.x -= (dx/dist)*force; pos2.y -= (dy/dist)*force; pos2.z -= (dz/dist)*force;
}
});
}
nodes.forEach(node => {
const pos = positions[node.id];
if (!pos) return;
const radius = 0.4 + Math.min(node.mention_count * 0.15, 1.5);
const color = typeColors[node.type] || defaultColor;
const geometry = new THREE.SphereGeometry(radius, 16, 12);
const material = new THREE.MeshPhongMaterial({ color: color, emissive: color, emissiveIntensity: 0.5 + Math.min(node.mention_count * 0.05, 0.3), shininess: 30 });
const sphere = new THREE.Mesh(geometry, material);
sphere.position.set(pos.x, pos.y, pos.z);
sphere.userData = { nodeId: node.id, nodeData: node };
scene.add(sphere);
nodeMeshes.push(sphere);
});
edges.forEach(edge => {
const pos1 = positions[edge.source], pos2 = positions[edge.target];
if (!pos1 || !pos2) return;
const color = edgeColors[edge.relation_type] || defaultEdgeColor;
const geometry = new THREE.BufferGeometry().setFromPoints([new THREE.Vector3(pos1.x, pos1.y, pos1.z), new THREE.Vector3(pos2.x, pos2.y, pos2.z)]);
const material = new THREE.LineBasicMaterial({ color: color, transparent: true, opacity: 0.4, linewidth: 1 });
const line = new THREE.Line(geometry, material);
line.userData = { edgeId: edge.id, edgeData: edge };
scene.add(line);
edgeLines.push(line);
});
const allPositions = Object.values(positions);
if (allPositions.length > 0) {
let maxDist = 0;
allPositions.forEach(pos => { maxDist = Math.max(maxDist, Math.sqrt(pos.x*pos.x + pos.y*pos.y + pos.z*pos.z)); });
camera.position.set(maxDist * 2.2, maxDist * 1.5, maxDist * 2.2);
controls.target.set(0, 0, 0);
}
}
function onMouseMove(event) {
const rect = renderer.domElement.getBoundingClientRect();
mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(nodeMeshes);
if (intersects.length > 0) {
const node = intersects[0].object;
if (hoveredNode !== node) {
if (hoveredNode) hoveredNode.scale.set(1, 1, 1);
hoveredNode = node;
node.scale.set(1.2, 1.2, 1.2);
showNodeInfo(node.userData.nodeData);
}
} else {
if (hoveredNode) { hoveredNode.scale.set(1, 1, 1); hoveredNode = null; hideNodeInfo(); }
}
}
function onMouseClick(event) {
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(nodeMeshes);
if (intersects.length > 0) {
const node = intersects[0].object;
if (selectedNode === node) { selectedNode = null; document.getElementById('node-info').style.display = 'none'; }
else { selectedNode = node; showNodeInfo(node.userData.nodeData, true); }
}
}
function showNodeInfo(nodeData, isClick = false) {
document.getElementById('info-name').textContent = nodeData.name;
document.getElementById('info-type').textContent = nodeData.type;
document.getElementById('info-mentions').textContent = nodeData.mention_count;
const linkCount = edges.filter(e => e.source === nodeData.id || e.target === nodeData.id).length;
document.getElementById('info-links').textContent = linkCount;
if (isClick) document.getElementById('node-info').style.display = 'block';
}
function hideNodeInfo() { if (!selectedNode) document.getElementById('node-info').style.display = 'none'; }
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
animationId = requestAnimationFrame(animate);
const time = Date.now() * 0.001;
highlightPulse = (highlightPulse + 0.02) % (Math.PI * 2);
controls.update();
if (starField) starField.rotation.y += 0.0001;
if (hoveredNode) { const pulse = 1 + Math.sin(highlightPulse * 3) * 0.05; hoveredNode.scale.set(pulse * 1.2, pulse * 1.2, pulse * 1.2); }
renderer.render(scene, camera);
}
init();
</script>
</body>
</html>