!98 重构文件系统.

Merge pull request !98 from ChenX/fileServer
pull/98/MERGE
ChenX 6 years ago
parent 0c30a36467
commit 5162e3d5dd

@ -1,6 +1,7 @@
{ {
"version": "0.2.0", "version": "0.2.0",
"configurations": [{ "configurations": [
{
"type": "chrome", "type": "chrome",
"request": "launch", "request": "launch",
"name": "Launch Chrome against localhost", "name": "Launch Chrome against localhost",

22
package-lock.json generated

@ -362,7 +362,7 @@
}, },
"@types/webvr-api": { "@types/webvr-api": {
"version": "0.0.34", "version": "0.0.34",
"resolved": "http://r.cnpmjs.org/@types/webvr-api/download/@types/webvr-api-0.0.34.tgz", "resolved": "http://registry.npm.taobao.org/@types/webvr-api/download/@types/webvr-api-0.0.34.tgz",
"integrity": "sha1-j6SQKN6SXHuLzj1VnTN0ziyJ7ig=", "integrity": "sha1-j6SQKN6SXHuLzj1VnTN0ziyJ7ig=",
"dev": true "dev": true
}, },
@ -810,7 +810,7 @@
}, },
"anymatch": { "anymatch": {
"version": "1.3.2", "version": "1.3.2",
"resolved": "http://r.cnpmjs.org/anymatch/download/anymatch-1.3.2.tgz", "resolved": "http://registry.npm.taobao.org/anymatch/download/anymatch-1.3.2.tgz",
"integrity": "sha1-VT3Lj5HjyImEXf26NMd3IbkLnXo=", "integrity": "sha1-VT3Lj5HjyImEXf26NMd3IbkLnXo=",
"dev": true, "dev": true,
"requires": { "requires": {
@ -820,7 +820,7 @@
"dependencies": { "dependencies": {
"arr-diff": { "arr-diff": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "http://r.cnpmjs.org/arr-diff/download/arr-diff-2.0.0.tgz", "resolved": "http://registry.npm.taobao.org/arr-diff/download/arr-diff-2.0.0.tgz",
"integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
"dev": true, "dev": true,
"requires": { "requires": {
@ -829,13 +829,13 @@
}, },
"array-unique": { "array-unique": {
"version": "0.2.1", "version": "0.2.1",
"resolved": "http://r.cnpmjs.org/array-unique/download/array-unique-0.2.1.tgz", "resolved": "http://registry.npm.taobao.org/array-unique/download/array-unique-0.2.1.tgz",
"integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
"dev": true "dev": true
}, },
"braces": { "braces": {
"version": "1.8.5", "version": "1.8.5",
"resolved": "http://r.cnpmjs.org/braces/download/braces-1.8.5.tgz", "resolved": "http://registry.npm.taobao.org/braces/download/braces-1.8.5.tgz",
"integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
"dev": true, "dev": true,
"requires": { "requires": {
@ -846,7 +846,7 @@
}, },
"expand-brackets": { "expand-brackets": {
"version": "0.1.5", "version": "0.1.5",
"resolved": "http://r.cnpmjs.org/expand-brackets/download/expand-brackets-0.1.5.tgz", "resolved": "http://registry.npm.taobao.org/expand-brackets/download/expand-brackets-0.1.5.tgz",
"integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
"dev": true, "dev": true,
"requires": { "requires": {
@ -855,13 +855,13 @@
}, },
"is-extglob": { "is-extglob": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "http://r.cnpmjs.org/is-extglob/download/is-extglob-1.0.0.tgz", "resolved": "http://registry.npm.taobao.org/is-extglob/download/is-extglob-1.0.0.tgz",
"integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
"dev": true "dev": true
}, },
"kind-of": { "kind-of": {
"version": "3.2.2", "version": "3.2.2",
"resolved": "http://r.cnpmjs.org/kind-of/download/kind-of-3.2.2.tgz", "resolved": "http://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
"dev": true, "dev": true,
"requires": { "requires": {
@ -870,7 +870,7 @@
}, },
"micromatch": { "micromatch": {
"version": "2.3.11", "version": "2.3.11",
"resolved": "http://r.cnpmjs.org/micromatch/download/micromatch-2.3.11.tgz", "resolved": "http://registry.npm.taobao.org/micromatch/download/micromatch-2.3.11.tgz",
"integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
"dev": true, "dev": true,
"requires": { "requires": {
@ -1872,7 +1872,7 @@
}, },
"chokidar": { "chokidar": {
"version": "1.7.0", "version": "1.7.0",
"resolved": "http://r.cnpmjs.org/chokidar/download/chokidar-1.7.0.tgz", "resolved": "http://registry.npm.taobao.org/chokidar/download/chokidar-1.7.0.tgz",
"integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=",
"dev": true, "dev": true,
"requires": { "requires": {
@ -7221,7 +7221,7 @@
}, },
"jsonfile": { "jsonfile": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "http://r.cnpmjs.org/jsonfile/download/jsonfile-4.0.0.tgz", "resolved": "http://registry.npm.taobao.org/jsonfile/download/jsonfile-4.0.0.tgz",
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
"dev": true, "dev": true,
"requires": { "requires": {

@ -57,7 +57,7 @@
"typescript": "^3.0.1", "typescript": "^3.0.1",
"url-loader": "^1.0.1", "url-loader": "^1.0.1",
"wallaby-webpack": "^3.9.10", "wallaby-webpack": "^3.9.10",
"webpack": "^4.16.5", "webpack": "^4.16.4",
"webpack-cli": "^3.1.0", "webpack-cli": "^3.1.0",
"webpack-dev-server": "^3.1.5", "webpack-dev-server": "^3.1.5",
"webpack-merge": "^4.1.4" "webpack-merge": "^4.1.4"

@ -1,47 +1,36 @@
import { app } from '../ApplicationServices/Application'; import { app } from '../ApplicationServices/Application';
import { Singleton } from '../Common/Singleton';
import { formateDate } from '../Common/Utils'; import { formateDate } from '../Common/Utils';
import { FileInfo, FileServer } from '../DatabaseServices/FileServer';
import { Command } from '../Editor/CommandMachine'; import { Command } from '../Editor/CommandMachine';
import { IndexedDbStore, StoreName } from '../IndexedDb/IndexedDbStore';
import { FileInfo } from '../UI/Components/SourceManage/FilePanel';
import { fileStore } from '../UI/Store/FilePanelStore';
export class Save implements Command export class Save implements Command
{ {
async exec() async exec()
{ {
let cadFile = app.FileOut(); //生成预览图
let store = await IndexedDbStore.CADStore();
let fileId = store.m_CurrentFileId;
app.m_Viewer.onSize(120, 120); app.m_Viewer.onSize(120, 120);
app.m_Viewer.Render(); app.m_Viewer.Render();
let url = app.m_Viewer.m_Render.domElement.toDataURL("image/jpeg"); let url = app.m_Viewer.m_Render.domElement.toDataURL("image/jpeg");
app.m_Viewer.onSize(); app.m_Viewer.onSize();
app.m_Viewer.Render(); app.m_Viewer.Render();
let fileServer = Singleton.GetInstance(FileServer);
let fileInfo: FileInfo; let fileInfo: FileInfo;
if (!fileId) if (fileServer.m_CurFileId)
{ fileInfo = await fileServer.ReadFileInfo(fileServer.m_CurFileId);
let count = await store.Get(StoreName.FileId, "fileCount") as number || 0; if (!fileInfo)
fileId = "f" + count; fileInfo = await fileServer.CreateFile();
store.Put(StoreName.FileId, "fileCount", ++count);
fileInfo = {
fileId,
title: `新文件${count}`,
modifyTime: ""
}
}
else
fileInfo = await store.Get(StoreName.Data, fileId) as FileInfo;
//更新最后修改时间 //更新最后修改时间
fileInfo.modifyTime = formateDate(new Date(), "yyyy-MM-dd hh:mm:ss"); fileInfo.modifyTime = formateDate(new Date(), "yyyy-MM-dd hh:mm:ss");
fileInfo.pic = url; fileInfo.pic = url;
//储存文件数据和对应图纸
store.Put(StoreName.Data, fileId, fileInfo);
store.Put(StoreName.Dwg, fileId, cadFile.Data);
store.m_CurrentFileId = fileId; fileServer.UpdateFileInfo(fileInfo);
fileStore.SetCurFileId(fileId); fileServer.UpdateFile(fileInfo.fileId, app.FileOut().Data);
fileServer.m_CurFileId = fileInfo.fileId;
fileServer.SetLastOpenId(fileInfo.fileId);
} }
} }

@ -142,6 +142,8 @@ export class ApplicationService
{ {
f.Reset(); f.Reset();
this.m_Database.FileRead(f); this.m_Database.FileRead(f);
this.m_Viewer.m_CameraCtrl.ReadFile(new CADFile(f.Read())); let viewData = f.Read();
if (viewData)
this.m_Viewer.m_CameraCtrl.ReadFile(new CADFile(viewData));
} }
} }

@ -0,0 +1,155 @@
import { IndexedDbStore, StoreName } from "../IndexedDb/IndexedDbStore";
import { formateDate } from "../Common/Utils";
/**
* Store.Data FileInfo
* Store.Dwg
* Store.fileId
*/
export interface FileData
{
key: string;
data: FileInfo;
}
export interface FileInfo
{
fileId: string;
title: string;
pic?: string;
position?: string;
picCount?: number;
modifyTime: string;
}
/**
* File server
* CAD,CRUD
*/
export class FileServer
{
constructor()
{
this.GetLastOpenId();
}
//** CRUD Start */
//创建新的文件C
async CreateFile(): Promise<FileInfo>
{
let store = await IndexedDbStore.CADStore();
let fId = await store.Get(StoreName.FileId, "fileCount") as number || 1;
let fileInfo: FileInfo = {
fileId: `f${fId}`,
title: `新文件${fId}`,
modifyTime: formateDate(new Date(), "yyyy-MM-dd hh:mm:ss"),
};
//保存这个文件描述
store.Put(StoreName.Data, fileInfo.fileId, fileInfo);
//文件个数+1
store.Put(StoreName.FileId, "fileCount", fId + 1);
this.CreateFileEvent(fileInfo);
return fileInfo;
}
//打开文件R
async ReadFile(fid: string)
{
let store = await IndexedDbStore.CADStore();
return store.Get(StoreName.Dwg, fid);
}
//保存文件U
async UpdateFile(fileId: string, data: any)
{
let store = await IndexedDbStore.CADStore();
store.Put(StoreName.Dwg, fileId, data);
}
//删除文件D
async DeleteFile(fid: string)
{
let store = await IndexedDbStore.CADStore();
store.Delete(StoreName.Data, fid);
store.Delete(StoreName.Dwg, fid);
this.DeleteFileEvent(fid);
}
//** CRUP End */
//导出文件(下载)
DownloadFile()
{
}
//导入文件(上传)
ImportFile()
{
}
//读取文件列表
async ReadFileList(): Promise<FileInfo[]>
{
let store = await IndexedDbStore.CADStore();
let fileList = await store.GetDataList(StoreName.Data) as FileData[];;
fileList.sort((f1, f2) =>
{
if (f1.key.length !== f2.key.length) return f1.key.length - f2.key.length;
return f1.key.localeCompare(f2.key);
});
return fileList.map(f => f.data);
}
//读取文件的描述信息
async ReadFileInfo(fid: string)
{
if (!fid) return undefined;
let store = await IndexedDbStore.CADStore();
let fileInfo = await store.Get(StoreName.Data, fid) as FileInfo;
return fileInfo;
}
//更新文件的描述信息
async UpdateFileInfo(fileInfo: FileInfo)
{
let store = await IndexedDbStore.CADStore();
await store.Put(StoreName.Data, fileInfo.fileId, fileInfo);
this.UpdateFileInfoEvent(fileInfo);
}
//**Event*
CreateFileEvent(f: FileInfo)
{
}
DeleteFileEvent(fid: string)
{
}
UpdateFileInfoEvent(fileInfo: FileInfo)
{
}
//当前编辑的文件id
m_CurFileId: string;
//最后编辑的文件id
m_LastFileId: string;
async SetLastOpenId(id: string)
{
this.m_LastFileId = id;
let store = await IndexedDbStore.CADStore();
store.Put(StoreName.FileId, "lastOpen", id);
}
async GetLastOpenId()
{
let store = await IndexedDbStore.CADStore();
this.m_LastFileId = await store.Get(StoreName.FileId, "lastOpen");
return this.m_LastFileId;
}
}

@ -45,7 +45,6 @@ export class MouseControls
onDBMouseDown = (e) => onDBMouseDown = (e) =>
{ {
} }
private raycaster: THREE.Raycaster = new THREE.Raycaster();
updateWordPoint = (e: MouseEvent) => updateWordPoint = (e: MouseEvent) =>
{ {
this.m_CurMousePointVCS.set(e.offsetX, e.offsetY, 0); this.m_CurMousePointVCS.set(e.offsetX, e.offsetY, 0);

@ -4,6 +4,7 @@ import * as xaop from 'xaop';
import { end } from 'xaop'; import { end } from 'xaop';
import { Database } from '../DatabaseServices/Database'; import { Database } from '../DatabaseServices/Database';
import { Entity } from '../DatabaseServices/Entity'; import { Entity } from '../DatabaseServices/Entity';
import { GenerateRaycaster } from '../Editor/PointPick';
import { cZeroVec, GetBox, GetBoxArr } from '../Geometry/GeUtils'; import { cZeroVec, GetBox, GetBoxArr } from '../Geometry/GeUtils';
import { PlaneExt } from '../Geometry/Plane'; import { PlaneExt } from '../Geometry/Plane';
import { CameraUpdate } from './CameraUpdate'; import { CameraUpdate } from './CameraUpdate';
@ -168,15 +169,7 @@ export class Viewer
{ {
//变换和求交点 //变换和求交点
let plan = new PlaneExt(planVec || new THREE.Vector3(0, 0, 1)); let plan = new PlaneExt(planVec || new THREE.Vector3(0, 0, 1));
let raycaster = new THREE.Raycaster(); let raycaster = GenerateRaycaster(pt, this);
// 射线从相机射线向屏幕点位置
raycaster.setFromCamera(
{
x: (pt.x / this.Width) * 2 - 1,
y: - (pt.y / this.Height) * 2 + 1
}
, this.m_CameraCtrl.Camera
)
plan.intersectRay(raycaster.ray, pt, true); plan.intersectRay(raycaster.ray, pt, true);
} }
WorldToScreen(pt: Vector3): Vector3 WorldToScreen(pt: Vector3): Vector3

@ -10,8 +10,17 @@ enum DbMode
export enum StoreName export enum StoreName
{ {
Texture = "Texture", Texture = "Texture",
/**
*
*/
Dwg = "Dwg", Dwg = "Dwg",
/**
* FileInfo
*/
Data = "Data", Data = "Data",
/**
*
*/
FileId = "fileId", FileId = "fileId",
ConfigData = "configData" ConfigData = "configData"
} }
@ -36,10 +45,25 @@ export class IndexedDbStore
await this.cadStore.Open(); await this.cadStore.Open();
return this.cadStore; return this.cadStore;
} }
opening = false;
resFunctionList: Function[] = [];
Open(): Promise<boolean> Open(): Promise<boolean>
{ {
return new Promise<boolean>((res) => return new Promise<boolean>((res) =>
{ {
if (this.db)
{
res(true);
return;
}
this.resFunctionList.push(res);
if (this.opening)
{
return;
}
this.opening = true;
let funcs = this.InitStore(); let funcs = this.InitStore();
this.dbRequest = indexedDB.open("webCAD", funcs.length); this.dbRequest = indexedDB.open("webCAD", funcs.length);
@ -47,17 +71,13 @@ export class IndexedDbStore
this.dbRequest.onerror = () => this.dbRequest.onerror = () =>
{ {
console.log("打开数据库出错!"); console.log("打开数据库出错!");
res(false); this.resFunctionList.forEach(res => res(false));
} }
//连接成功 //连接成功
this.dbRequest.onsuccess = (event) => this.dbRequest.onsuccess = (event) =>
{ {
this.db = this.dbRequest.result; this.db = this.dbRequest.result;
this.db.onerror = () => this.resFunctionList.forEach(res => res(true));
{
res(false);
}
res(true);
} }
//需要升级版本号时触发该事件 //需要升级版本号时触发该事件

@ -2,6 +2,7 @@ import { Switch } from '@blueprintjs/core';
import { inject, observer } from 'mobx-react'; import { inject, observer } from 'mobx-react';
import * as React from 'react'; import * as React from 'react';
import { DownPanelStore } from '../Store/DownPanelStore'; import { DownPanelStore } from '../Store/DownPanelStore';
import { TopPanelStore } from '../Store/TopPanelStore';
import { SettingPanel } from './SettingPanel/SettingPanel'; import { SettingPanel } from './SettingPanel/SettingPanel';
import Login from './signComponent/login'; import Login from './signComponent/login';
import SoucePanel from './SourceManage/SoucePanel'; import SoucePanel from './SourceManage/SoucePanel';
@ -12,11 +13,13 @@ interface TopPanelState
isCollapse: boolean; isCollapse: boolean;
panelType: string; panelType: string;
} }
//顶部标题栏.
//TODO:Ajax请求获得登录状态 //顶部标题栏. TODO:Ajax请求获得登录状态
export class TopPanel extends React.Component<{}, {}> @inject("store")
@observer
export class TopPanel extends React.Component<{ store?: TopPanelStore }, {}>
{ {
state: TopPanelState state: TopPanelState;
constructor(props) constructor(props)
{ {
super(props); super(props);
@ -72,7 +75,7 @@ export class TopPanel extends React.Component<{}, {}>
</ button > </ button >
<button <button
className="bp3-button bp3-minimal bp3-icon-document" className="bp3-button bp3-minimal bp3-icon-document"
onClick={() => this.handleClick("file")} onClick={() => this.props.store.m_FileManageOpen = true}
> >
<span className="hidden"> <span className="hidden">
@ -106,15 +109,13 @@ export class TopPanel extends React.Component<{}, {}>
toggleDialog={this.handleCancel} toggleDialog={this.handleCancel}
toLogin={this.state.panelType === 'login'} toLogin={this.state.panelType === 'login'}
/> />
<SoucePanel <SoucePanel />
handleClose={this.handleCancel}
isOpen={this.state.panelType === 'file'}
/>
</ nav> </ nav>
); );
} }
} }
//底部状态栏
@inject("store") @inject("store")
@observer @observer
export class DownPanel extends React.Component<{ store?: DownPanelStore }, {}> export class DownPanel extends React.Component<{ store?: DownPanelStore }, {}>

@ -1,17 +1,17 @@
import { Button } from '@blueprintjs/core'; import { Button } from '@blueprintjs/core';
import * as React from 'react'; import * as React from 'react';
import { FileInfo } from '../../../DatabaseServices/FileServer';
import { FileInfo } from './FilePanel'; import { observer } from 'mobx-react';
interface FileItemProps interface FileItemProps
{ {
//文件信息 //文件信息
fileInfo: FileInfo, fileInfo: FileInfo;
callBack?: Function callBack?: Function;
} }
interface FileItemState interface FileItemState
{ {
title: string title: string;
} }
/** /**
* *
@ -20,6 +20,8 @@ interface FileItemState
* @class FileItem * @class FileItem
* @extends {React.Component<FileItemProps, {}>} * @extends {React.Component<FileItemProps, {}>}
*/ */
@observer
export class FileItem extends React.Component<FileItemProps, FileItemState>{ export class FileItem extends React.Component<FileItemProps, FileItemState>{
constructor(props) constructor(props)
{ {

@ -1,76 +1,38 @@
import { observable } from 'mobx'; import { observable } from 'mobx';
import { observer } from 'mobx-react'; import { inject, observer } from 'mobx-react';
import * as React from 'react'; import * as React from 'react';
import { app } from '../../../ApplicationServices/Application'; import { app } from '../../../ApplicationServices/Application';
import { FileSystem } from '../../../Common/FileSystem'; import { FileSystem } from '../../../Common/FileSystem';
import { formateDate } from '../../../Common/Utils'; import { Singleton } from '../../../Common/Singleton';
import { CADFile } from '../../../DatabaseServices/CADFile'; import { CADFile } from '../../../DatabaseServices/CADFile';
import { Database } from '../../../DatabaseServices/Database'; import { FileServer } from '../../../DatabaseServices/FileServer';
import { IndexedDbStore, StoreName } from '../../../IndexedDb/IndexedDbStore'; import { TopPanelStore } from '../../Store/TopPanelStore';
import { fileStore } from '../../Store/FilePanelStore';
import { FileItem } from './FileItem'; import { FileItem } from './FileItem';
interface FileProps
{
// isShow: boolean,
callback?: Function
}
export interface FileInfo
{
fileId: string;
title: string;
pic?: string;
position?: string;
picCount?: number;
modifyTime: string;
}
interface FileData
{
key: string,
data: FileInfo
}
interface FileState
{
fileList: FileData[]
}
/** /**
* *
* @export
* @class FilePanel
* @extends {React.Component<FileProps, {}>}
*/ */
@inject("store")
@observer @observer
export class FilePanel extends React.Component<FileProps, FileState> export class FilePanel extends React.Component<{ store?: TopPanelStore }, {}>
{ {
@observable seachString: string = ""; @observable seachString: string = "";
filesRef: React.RefObject<HTMLUListElement>; filesRef: React.RefObject<HTMLUListElement>;
constructor(props) constructor(props)
{ {
super(props); super(props);
this.state = {
fileList: []
}
this.filesRef = React.createRef(); this.filesRef = React.createRef();
} }
//添加新文件 //添加新文件
handleAddNewFile = async () => handleAddNewFile = async () =>
{ {
let store = await IndexedDbStore.CADStore(); let server = Singleton.GetInstance(FileServer);
let fId = await store.Get(StoreName.FileId, "fileCount") as number || 0; if (server.m_CurFileId)
let newFile: FileInfo = { {
fileId: "f" + fId, server.m_CurFileId = undefined;
title: "文件名" + fId, app.CreateDocument();
modifyTime: formateDate(new Date(), "yyyy-MM-dd hh:mm:ss"),
} }
this.props.store.m_FileManageOpen = false;
fileStore.SetCurFileId(newFile.fileId);;
store.Put(StoreName.Data, newFile.fileId, newFile);
store.Put(StoreName.FileId, "fileCount", fId + 1);
await this.handleUpdateList();
return fId;
} }
handleImportFile = async () => handleImportFile = async () =>
{ {
@ -81,102 +43,69 @@ export class FilePanel extends React.Component<FileProps, FileState>
let f = files[0]; let f = files[0];
let fileData = await FileSystem.readFileAsText(f); let fileData = await FileSystem.readFileAsText(f);
let fid = await this.handleAddNewFile(); let fserver = Singleton.GetInstance(FileServer);
let fileInfo = await fserver.CreateFile();
let store = await IndexedDbStore.CADStore(); fserver.UpdateFile(fileInfo.fileId, JSON.parse(fileData));
store.Put(StoreName.Dwg, "f" + fid, JSON.parse(fileData));
} }
}, ".json", false); }, ".json", false);
} }
handleFile = async (fid: string, fname: string, type: string) => handleFile = async (fid: string, fname: string, type: string) =>
{ {
let store = await IndexedDbStore.CADStore(); let fserver = Singleton.GetInstance(FileServer);
switch (type) switch (type)
{ {
case "delete": case "delete":
{ {
store.Delete(StoreName.Data, fid); fserver.DeleteFile(fid);
store.Delete(StoreName.Dwg, fid); if (fserver.m_CurFileId === fid)
this.handleUpdateList(); app.CreateDocument();
store.m_CurrentFileId = undefined;
fileStore.SetCurFileId(undefined);
//清屏
app.m_Viewer.Scene.children.length = 0;
app.m_Viewer.m_bNeedUpdate = true;
break; break;
} }
case "open": case "open":
{ {
// 修改当前文件名 if (fserver.m_CurFileId !== fid)
let fileData: FileInfo = await store.Get(StoreName.Data, fid);
fileData.title = fname;
//切换当前图纸id
store.m_CurrentFileId = fid;
fileStore.SetCurFileId(fid);
let file = await store.Get(StoreName.Dwg, fid);
if (!file)
{ {
app.CreateDocument(); let fserver = Singleton.GetInstance(FileServer);
app.OpenFile(new CADFile(await fserver.ReadFile(fid)));
fserver.m_CurFileId = fid;
fserver.SetLastOpenId(fid);
} }
else this.props.store.m_FileManageOpen = false;
{
let cadF = new CADFile(file);
app.OpenFile(cadF);
app.m_Editor.UpdateScreen();
}
store.Put(StoreName.Data, fid, fileData);
this.props.callback();
break; break;
} }
case "download": case "download":
{ {
let fileData: FileInfo = await store.Get(StoreName.Data, fid); let fInfo = await fserver.ReadFileInfo(fid);
let file = await store.Get(StoreName.Dwg, fid); let data = await fserver.ReadFile(fid);
FileSystem.writeFile(fileData.title + ".json", JSON.stringify(file)); FileSystem.writeFile(fInfo.title + ".json", JSON.stringify(data));
break; break;
} }
} }
} }
handleUpdateList = async () =>
{
let store = await IndexedDbStore.CADStore();
let fileList = await store.GetDataList(StoreName.Data) as FileData[];;
fileList.sort((f1, f2) =>
{
if (f1.key.length !== f2.key.length) return f1.key.length - f2.key.length;
return f1.key.localeCompare(f2.key);
})
this.setState({ fileList });
}
componentDidUpdate(prevProps, prevState) //将滚动条滚动到上次打开的文件的位置
scrollToLastFile()
{ {
if (fileStore.curFile) let fserver = Singleton.GetInstance(FileServer);
if (fserver.m_LastFileId)
{ {
let el = this.filesRef.current; let el = this.filesRef.current;
for (let i = 0; i < el.childNodes.length; i++) let elc = el.querySelector(`#${fserver.m_LastFileId}`) as HTMLElement;
{ if (elc)
let eln = el.childNodes.item(i) as HTMLElement; el.scrollTop = elc.offsetTop - elc.offsetHeight;
if (eln.id === fileStore.curFile)
{
el.scrollTop = eln.offsetTop - eln.offsetHeight;
break;
}
}
} }
} }
componentDidUpdate(prevProps?, prevState?)
{
this.scrollToLastFile();
}
componentDidMount() componentDidMount()
{ {
this.handleUpdateList(); this.props.store.UpdateFileList();
this.scrollToLastFile();
} }
render() render()
{ {
@ -244,20 +173,20 @@ export class FilePanel extends React.Component<FileProps, FileState>
} }
> >
{ {
this.state.fileList this.props.store.m_FileList
.filter(f => .filter(f =>
{ {
if (this.seachString) if (this.seachString)
{ {
return f.data.title.match(this.seachString); return f.title.match(this.seachString);
} }
else return true; else return true;
}) })
.map((file) => .map((file) =>
{ {
return <FileItem return <FileItem
key={file.key} key={file.fileId}
fileInfo={file.data} fileInfo={file}
callBack={this.handleFile} callBack={this.handleFile}
/> />
}) })

@ -2,11 +2,8 @@ import { Button, Dialog, Tab, Tabs, Classes } from '@blueprintjs/core';
import * as React from 'react'; import * as React from 'react';
import { MaterialPanel } from './MaterialPanel'; import { MaterialPanel } from './MaterialPanel';
import { FilePanel } from './FilePanel'; import { FilePanel } from './FilePanel';
export interface SoucePanelProps import { observer, inject } from 'mobx-react';
{ import { TopPanelStore } from '../../Store/TopPanelStore';
handleClose: Function,
isOpen: boolean
}
export interface SoucePanelState export interface SoucePanelState
{ {
@ -16,47 +13,27 @@ export interface SoucePanelState
const TexturePanel: React.SFC<{}> = () => ( const TexturePanel: React.SFC<{}> = () => (
//todo //todo
<h5></h5> <h5></h5>
); );
const ModelPanel: React.SFC<{}> = () => ( const ModelPanel: React.SFC<{}> = () => (
//todo //todo
<h5></h5> <h5></h5>
); );
/** /**
* *
* TODO: * TODO:
* TODO: * TODO:
* @export
* @class SoucePanel
* @extends {React.Component<SoucePanelProps, SoucePanelState>}
*/ */
export default class SoucePanel extends React.Component<SoucePanelProps, SoucePanelState> { @inject("store")
@observer
export default class SoucePanel extends React.Component<{ store?: TopPanelStore }, {}> {
ref: React.RefObject<HTMLDivElement>; ref: React.RefObject<HTMLDivElement>;
constructor(props: SoucePanelProps) constructor(p)
{ {
super(props); super(p);
this.state = {
showIndex: 0
}
this.ref = React.createRef(); this.ref = React.createRef();
} }
handleClick = (i: number) =>
{
this.setState({
showIndex: i
})
}
componentDidMount()
{
}
componentDidUpdate()
{
}
render() render()
{ {
@ -70,16 +47,12 @@ export default class SoucePanel extends React.Component<SoucePanelProps, SoucePa
return ( return (
<Dialog <Dialog
icon="inbox" icon="inbox"
isOpen={this.props.isOpen} isOpen={this.props.store.m_FileManageOpen}
onClose={() => this.props.handleClose()} onClose={() => this.props.store.m_FileManageOpen = false}
title="资源管理器" title="资源管理器"
style={DialogStyle} style={DialogStyle}
className={Classes.OVERLAY_SCROLL_CONTAINER} className={Classes.OVERLAY_SCROLL_CONTAINER}
onOpening={() => onOpening={() => this.ref.current.parentElement.className = "bp3-dark bp3-dialog"}
{
this.ref.current.parentElement.className = "bp3-dark bp3-dialog"
}}
> >
<div <div
ref={this.ref} ref={this.ref}
@ -93,7 +66,7 @@ export default class SoucePanel extends React.Component<SoucePanelProps, SoucePa
id="Tabs" id="Tabs"
vertical={true} vertical={true}
> >
<Tab id="fl" title="我的文件" panel={<FilePanel callback={this.props.handleClose} />} /> <Tab id="fl" title="我的文件" panel={<FilePanel />} />
<Tab id="mt" title="我的材质" panel={<MaterialPanel />} /> <Tab id="mt" title="我的材质" panel={<MaterialPanel />} />
<Tab id="tt" title="我的贴图" panel={<TexturePanel />} /> <Tab id="tt" title="我的贴图" panel={<TexturePanel />} />
<Tab id="md" title="我的模型" panel={<ModelPanel />} /> <Tab id="md" title="我的模型" panel={<ModelPanel />} />
@ -103,13 +76,12 @@ export default class SoucePanel extends React.Component<SoucePanelProps, SoucePa
<MaterialPanel isShow={this.state.showIndex === 1} /> */} <MaterialPanel isShow={this.state.showIndex === 1} /> */}
</div> </div>
<div className="bp3-dialog-footer"> <div className="bp3-dialog-footer">
<div className="bp3-dialog-footer-actions"> <div className="bp3-dialog-footer-actions">
<Button <Button
text="关闭" text="关闭"
className="bp3-intent-danger" className="bp3-intent-danger"
onClick={() => this.props.handleClose()} onClick={() => this.props.store.m_FileManageOpen = false}
/> />
</div> </div>
</div> </div>
@ -117,4 +89,3 @@ export default class SoucePanel extends React.Component<SoucePanelProps, SoucePa
); );
} }
} }

@ -6,6 +6,7 @@ import * as ReactDOM from 'react-dom';
import * as xaop from 'xaop'; import * as xaop from 'xaop';
import { app, ApplicationService } from '../../ApplicationServices/Application'; import { app, ApplicationService } from '../../ApplicationServices/Application';
import { WebSocketClientServer } from '../../ApplicationServices/WebSocketClientServer'; import { WebSocketClientServer } from '../../ApplicationServices/WebSocketClientServer';
import { Singleton } from '../../Common/Singleton';
import { ObjectId } from '../../DatabaseServices/ObjectId'; import { ObjectId } from '../../DatabaseServices/ObjectId';
import { DbPhysicalMaterial } from '../../DatabaseServices/PhysicalMaterial'; import { DbPhysicalMaterial } from '../../DatabaseServices/PhysicalMaterial';
import { registerCommand } from '../../Editor/CommandRegister'; import { registerCommand } from '../../Editor/CommandRegister';
@ -15,6 +16,7 @@ import { DownPanel, TopPanel } from '../Components/Panel';
import { SourceManage } from '../Components/SourceManage/SourceManage'; import { SourceManage } from '../Components/SourceManage/SourceManage';
import { ToolbarContainer } from '../Components/ToolBar/ToolbarContainer'; import { ToolbarContainer } from '../Components/ToolBar/ToolbarContainer';
import { DownPanelStore } from '../Store/DownPanelStore'; import { DownPanelStore } from '../Store/DownPanelStore';
import { TopPanelStore } from '../Store/TopPanelStore';
import { AppLayoutKey, applicationLayoutConfig } from './ApplicationLayout.config'; import { AppLayoutKey, applicationLayoutConfig } from './ApplicationLayout.config';
import { ContainerComponenName, LayoutRegisterContainerComponent } from './LayoutUtils'; import { ContainerComponenName, LayoutRegisterContainerComponent } from './LayoutUtils';
import { MaterialEditorLayout } from './MaterialEditorLayout'; import { MaterialEditorLayout } from './MaterialEditorLayout';
@ -139,7 +141,10 @@ export class WebCAD
{ {
let topPanelEl = document.getElementById("TopPanel"); let topPanelEl = document.getElementById("TopPanel");
ReactDOM.render( ReactDOM.render(
<TopPanel />, topPanelEl <Provider store={Singleton.GetInstance(TopPanelStore)}>
<TopPanel />
</Provider>,
topPanelEl
) )
} }

@ -3,7 +3,6 @@ import { Vector3 } from 'three';
import * as xaop from 'xaop'; import * as xaop from 'xaop';
import { app } from '../../ApplicationServices/Application'; import { app } from '../../ApplicationServices/Application';
//点转换为字符串. //点转换为字符串.
function PointToString(pt: Vector3): string function PointToString(pt: Vector3): string
{ {
@ -14,10 +13,7 @@ function PointToString(pt: Vector3): string
} }
/** /**
* . . * .
*
* @export
* @class DownPanelStore
*/ */
export class DownPanelStore export class DownPanelStore
{ {
@ -30,11 +26,11 @@ export class DownPanelStore
xaop.begin(app.m_Editor.m_MouseCtrl, app.m_Editor.m_MouseCtrl.updateWordPoint, () => xaop.begin(app.m_Editor.m_MouseCtrl, app.m_Editor.m_MouseCtrl.updateWordPoint, () =>
{ {
this.m_MousePostionPrompt = PointToString(app.m_Editor.m_MouseCtrl.m_CurMousePointWCS); this.m_MousePostionPrompt = PointToString(app.m_Editor.m_MouseCtrl.m_CurMousePointWCS);
}) });
autorun(() => autorun(() =>
{ {
app.m_Editor.m_GetpointServices.snapServices.m_Disabled = !this.useDynSnap; app.m_Editor.m_GetpointServices.snapServices.m_Disabled = !this.useDynSnap;
}) });
} }
private static _store: DownPanelStore; private static _store: DownPanelStore;

@ -1,19 +0,0 @@
import { observable } from "mobx";
class FilePanelStore
{
constructor()
{
this.curFile = window.sessionStorage.getItem("fid");
}
@observable
curFile: string;
SetCurFileId(id: string)
{
this.curFile = id;
window.sessionStorage.setItem("fid", id);
}
}
export let fileStore = new FilePanelStore();

@ -0,0 +1,42 @@
import { observable } from "mobx";
import { end } from "../../../node_modules/xaop";
import { arrayRemoveIf } from "../../Common/ArrayExt";
import { Singleton } from "../../Common/Singleton";
import { FileInfo, FileServer } from "../../DatabaseServices/FileServer";
export class TopPanelStore
{
@observable m_FileManageOpen: boolean = false;
@observable m_FileList: FileInfo[] = [];
async UpdateFileList()
{
if (this.m_FileList.length > 0) return;
let fileServer = Singleton.GetInstance(FileServer);
this.m_FileList.push(...await fileServer.ReadFileList());
end(fileServer, fileServer.CreateFileEvent, (f: FileInfo) =>
{
this.m_FileList.push(f);
});
end(fileServer, fileServer.DeleteFileEvent, (fid: string) =>
{
arrayRemoveIf(this.m_FileList, (f: FileInfo) =>
{
return f.fileId === fid;
});
});
end(fileServer, fileServer.UpdateFileInfo, (fn: FileInfo) =>
{
for (let f of this.m_FileList)
{
if (f.fileId === fn.fileId)
{
f.modifyTime = fn.modifyTime;
f.pic = fn.pic;
break;
}
}
})
}
}
Loading…
Cancel
Save