master
tonkia 6 years ago
parent ae177a9d9e
commit 79fd3dba67
  1. 164
      app.js
  2. 68
      db.js
  3. 6
      static/js/createScheme.js
  4. 222
      static/js/share.js
  5. 15
      views/createScheme.html
  6. 23
      views/home.html
  7. 1
      views/login.html
  8. 57
      views/share.html

164
app.js

@ -6,8 +6,8 @@ var fs = require('fs');
var gm = require('gm'); var gm = require('gm');
var db = require('./db'); var db = require('./db');
var app = express();
var app = express();
var storage = multer.diskStorage({ var storage = multer.diskStorage({
destination: function (req, res, cb) { destination: function (req, res, cb) {
var fileType = req.params["fileType"]; var fileType = req.params["fileType"];
@ -17,7 +17,6 @@ var storage = multer.diskStorage({
}); });
var upload = multer({ storage: storage }); var upload = multer({ storage: storage });
//共享页面 //共享页面
var shareLink = '127.0.0.1/share'
app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json({ limit: '50mb' })); app.use(bodyParser.json({ limit: '50mb' }));
@ -30,33 +29,23 @@ app.use(session({
maxAge: 1000 * 60 * 60 * 24 * 30, // 设置 session 的有效时间,单位毫秒 maxAge: 1000 * 60 * 60 * 24 * 30, // 设置 session 的有效时间,单位毫秒
} }
})); }));
//权限判断:拦截器 //权限判断:拦截器
app.use(['/create', '/logout', '/home', '/saveScheme', '/getScheme'], function (req, res, next) { app.use(['/create', '/logout', '/home', '/saveScheme', '/getScheme', '/changeShareConfig'], function (req, res, next) {
if (req.session.user) if (req.session.user)
next(); next();
else else
res.redirect('/'); res.redirect('/');
}); });
//临时存储数据 //自定义数据--------------------------------------------------------------------------
//var data = { name: '默认方案', components: [], img: null }; var shareLink = '127.0.0.1/share'
//主页加载:登录页面 //主页加载:登录页面------------------------------------------------------------------
app.get('/', function (req, res) { app.get('/', function (req, res) {
res.sendFile(__dirname + "/views/login.html"); res.sendFile(__dirname + "/views/login.html");
}); });
//方案创建 //登录验证
app.get('/create', function (req, res) {
res.sendFile(__dirname + "/views/createScheme.html");
});
app.get('/create/:id', function (req, res) {
res.sendFile(__dirname + "/views/createScheme.html");
});
//登录
app.post('/', function (req, res) { app.post('/', function (req, res) {
var account = req.body.account; var account = req.body.account;
var password = req.body.password; var password = req.body.password;
@ -71,12 +60,7 @@ app.post('/', function (req, res) {
}); });
}); });
//用户注销 //主页请求----------------------------------------------------------------------------
app.get('/logout', function (req, res) {
req.session.user = null;
res.redirect('/');
});
//用户主页 //用户主页
app.get('/home', function (req, res) { app.get('/home', function (req, res) {
res.sendFile(__dirname + "/views/home.html"); res.sendFile(__dirname + "/views/home.html");
@ -98,13 +82,80 @@ app.post('/home', function (req, res) {
}); });
}); });
//用户注销
app.get('/logout', function (req, res) {
req.session.user = null;
res.redirect('/');
});
//方案创建
app.get('/create', function (req, res) {
res.sendFile(__dirname + "/views/createScheme.html");
});
app.get('/create/:id', function (req, res) {
res.sendFile(__dirname + "/views/createScheme.html");
});
// 方案分享配置
app.post('/changeShareConfig', function (req, res) {
var user = req.session.user;
var data = req.body;
db.changeShareConfig(data.id, user.id, data.share_password, data.share_state, function (row) {
if (row.affectedRows > 0) {
var returnData = {
affectedRows: row.affectedRows
}
res.send(returnData);
} else {
}
});
});
//方案创建页面--------------------------------------------------------------------------------
//初始数据获取
//未创建的方案:获取初始方案
app.post('/getScheme', function (req, res) {
var data = { name: '默认方案', components: [], img: null, id: null, maxHeight: 10, height: 2, maxDistance: 30, distance: 10 };
replyData = {
msg: 0,
data: data
}
res.send(replyData);
});
//已经创建的方案:根据局ID获取初始方案
app.post('/getScheme/:id', function (req, res) {
var id = req.params['id'];
var user = req.session.user;
if (id) {
db.getSchemeById(user.id, id, function (row) {
if (row.length > 0) {
var data = JSON.parse(row[0].data);
data.id = id;
replyData = {
msg: 0,
data: data
}
res.send(replyData);
} else {
replyData = {
msg: 1
}
res.send(replyData);
}
})
} else {
}
});
//文件上传:分为model文件,texture文件
//接受文件上传,并且返回文件名 //接受文件上传,并且返回文件名
app.post('/upload/:fileType', upload.single('file'), function (req, res) { app.post('/upload/:fileType', upload.single('file'), function (req, res) {
//console.info(req.file) //console.info(req.file)
res.send(req.file); res.send(req.file);
}); });
//文件返回
//返回缩略图 //贴图文件:返回缩略图
app.get('/files/thumbnail/:filename', function (req, res) { app.get('/files/thumbnail/:filename', function (req, res) {
var filename = req.params['filename']; var filename = req.params['filename'];
// fs.exists(__dirname + "/uploads/thumbnail/" + filename, function (exist) { // fs.exists(__dirname + "/uploads/thumbnail/" + filename, function (exist) {
@ -121,14 +172,14 @@ app.get('/files/thumbnail/:filename', function (req, res) {
res.sendFile(__dirname + "/uploads/texture/" + filename); res.sendFile(__dirname + "/uploads/texture/" + filename);
}); });
//返回文件 //其他文件(model文件,texture文件):返回文件
app.get('/files/:fileType/:fileName', function (req, res) { app.get('/files/:fileType/:fileName', function (req, res) {
//TODO 根据session判断是否有权限获取文件 //TODO 根据session判断是否有权限获取文件
var fileType = req.params['fileType']; var fileType = req.params['fileType'];
var fileName = req.params['fileName']; var fileName = req.params['fileName'];
res.sendFile(__dirname + "/uploads/" + fileType + "/" + fileName); res.sendFile(__dirname + "/uploads/" + fileType + "/" + fileName);
}); });
//------------------------------------------------------------------------------------------------
//保存方案 //保存方案
app.post('/saveScheme', function (req, res) { app.post('/saveScheme', function (req, res) {
var data = req.body; var data = req.body;
@ -163,26 +214,49 @@ app.post('/saveScheme', function (req, res) {
} }
// console.info(data); // console.info(data);
}); });
//------------------------------------------------------------------------------------------------
//获取初始方案
app.post('/getScheme', function (req, res) {
var data = { name: '默认方案', components: [], img: null, id: null, maxHeight: 10, height: 2, maxDistance: 30, distance: 10 };
replyData = {
msg: 0,
data: data
}
res.send(replyData);
});
//根据局ID获取初始方案
app.post('/getScheme/:id', function (req, res) { //分享页面------------------------------------------------------------------------------------------------
//页面返回
app.get('/share/:id', function (req, res) {
res.sendFile(__dirname + "/views/share.html");
});
//分享状态获取
app.post('/share/:id', function (req, res) {
var id = req.params['id']; var id = req.params['id'];
var user = req.session.user; db.getShareById(id, function (row) {
if (id) { if (row.length > 0)
db.getSchemeById(user.id, id, function (row) { res.send(row[0].share_state + "");
else
//如果没有则返回
res.send(3 + "");
});
});
//获取分享的data数据
app.post('/shareData/:id', function (req, res) {
var id = req.params['id'];
var reqData = req.body;
// console.info(reqData);
if (reqData.state == 1) {
db.getShareData(id, function (row) {
if (row.length > 0) {
var data = JSON.parse(row[0].data);
replyData = {
msg: 0,
data: data
}
res.send(replyData);
} else {
replyData = {
msg: 1
}
res.send(replyData);
}
})
} else if (reqData.state == 2) {
db.getShareDataByPassword(id, reqData.password, function (row) {
if (row.length > 0) { if (row.length > 0) {
var data = JSON.parse(row[0].data); var data = JSON.parse(row[0].data);
data.id = id;
replyData = { replyData = {
msg: 0, msg: 0,
data: data data: data
@ -195,9 +269,7 @@ app.post('/getScheme/:id', function (req, res) {
res.send(replyData); res.send(replyData);
} }
}) })
} else {
} }
}); });
//------------------------------------------------------------------------------------
app.listen(80); app.listen(80);

68
db.js

@ -106,3 +106,71 @@ module.exports.getSchemeById = function (uid, id, callback) {
}); });
}; };
module.exports.changeShareConfig = function (id, uid, share_password, share_state, callback) {
connection.getConnection(function (err, conn) {
if (err) {
console.info(err);
} else {
conn.query('UPDATE scheme SET share_password=?,share_state=? WHERE id =? AND uid =?', [share_password, share_state, id, uid], function (err, rows) {
if (err) {
console.log(err);
return;
}
callback(rows);
conn.release();
});
}
});
};
module.exports.getShareById = function (id, callback) {
connection.getConnection(function (err, conn) {
if (err) {
console.info(err);
} else {
conn.query('SELECT share_state FROM scheme WHERE id =?', [id], function (err, rows) {
if (err) {
console.log(err);
return;
}
callback(rows);
conn.release();
});
}
});
};
module.exports.getShareData = function (id, callback) {
connection.getConnection(function (err, conn) {
if (err) {
console.info(err);
} else {
conn.query('SELECT data FROM scheme WHERE id =? AND share_state=?', [id, 1], function (err, rows) {
if (err) {
console.log(err);
return;
}
callback(rows);
conn.release();
});
}
});
};
module.exports.getShareDataByPassword = function (id, password, callback) {
connection.getConnection(function (err, conn) {
if (err) {
console.info(err);
} else {
conn.query('SELECT data FROM scheme WHERE id =? AND share_state=? AND share_password=?', [id, 2, password], function (err, rows) {
if (err) {
console.log(err);
return;
}
callback(rows);
conn.release();
});
}
});
};

@ -338,8 +338,8 @@ function initEvent() {
var tWidth = sHeigth / 1.2; var tWidth = sHeigth / 1.2;
var tHeigth = sHeigth; var tHeigth = sHeigth;
//压缩后的像素 //压缩后的像素
$('#compress')[0].width = 200; $('#compress')[0].width = 500;
$('#compress')[0].height = 240; $('#compress')[0].height = 600;
//console.info(sWidth + ":" + sHeigth + ":" + tWidth + ":" + tHeigth); //console.info(sWidth + ":" + sHeigth + ":" + tWidth + ":" + tHeigth);
//压缩图片 //压缩图片
$('#compress')[0].getContext('2d').drawImage(image, (sWidth - tWidth) / 2, (sHeigth - tHeigth) / 2, tWidth, tHeigth, 0, 0, $('#compress')[0].width, $('#compress')[0].height); $('#compress')[0].getContext('2d').drawImage(image, (sWidth - tWidth) / 2, (sHeigth - tHeigth) / 2, tWidth, tHeigth, 0, 0, $('#compress')[0].width, $('#compress')[0].height);
@ -578,6 +578,8 @@ function addTexture(url, callBack) {
callBack(object); callBack(object);
}); });
} }
//公用方法:模型贴图替换
function replaceTexture(modelObj, textureObj) { function replaceTexture(modelObj, textureObj) {
modelObj.traverse(function (child) { modelObj.traverse(function (child) {
if (child instanceof THREE.Mesh) { if (child instanceof THREE.Mesh) {

@ -0,0 +1,222 @@
var data;
$().ready(function () {
init();
});
//获取数据 初始化data
function init() {
var url = document.location.toString();
var arrUrl = url.split("share");
var id = arrUrl[arrUrl.length - 1];
//ajax请求数据
$.post("/share" + id, function (reply) {
//拒绝访问
if (reply == 0)
alert('Sorry, you have no access to this page.');
//请求数据
else if (reply == 1) {
var reqData = {
state: 1
}
$.ajax({
type: "POST",
url: "/shareData" + id,
data: reqData,
async: false, //同步请求,不然data会出问题
success: function (remotaData) {
//给全局data赋值
if (remotaData.msg == 0) {
data = remotaData.data;
initUi();
initThree();
loadModel();
initEvent();
}
else
alert('Sorry, some problems have arisen.');
}
});
}
//密码访问
else if (reply == 2) {
$('#visitPasswordModal').modal('show');
$('#visitBtn').click(function () {
var password = $('#visitPassword').val().trim();
var reqData = {
state: 2,
password: password
}
$.ajax({
type: "POST",
url: "/shareData" + id,
data: reqData,
async: false, //同步请求,不然data会出问题
success: function (remotaData) {
//给全局data赋值
if (remotaData.msg == 0) {
data = remotaData.data;
$('#visitPassword').val('');
$('#visitPasswordModal').modal('hide');
initUi();
initThree();
loadModel();
initEvent();
}
else {
$('#visitPassword').val('');
alert('Sorry, some problems have arisen.');
}
}
});
});
} else {
alert('Sorry, some problems have arisen.');
}
});
}
//------------------------------------------------------------------------------
//界面初始化
function initUi() {
}
//------------------------------------------------------------------------------
//threejs配置
function initThree() {
initScene();
initCamera();
initRenderer();
render();
}
function initScene() {
//场景设置
scene = new THREE.Scene();
//设置天空盒
scene.background = new THREE.CubeTextureLoader()
.setPath('/img/skybox/')
.load(['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg']);
//场景灯光
//环境光
var light = new THREE.HemisphereLight(0xffffff, 0x444444);
light.position.set(0, 2, 0);
scene.add(light);
//直射光
light = new THREE.DirectionalLight(0xffffff);
light.position.set(0, 2, 1);
light.castShadow = true;
light.shadow.camera.top = 180;
light.shadow.camera.bottom = - 100;
light.shadow.camera.left = - 120;
light.shadow.camera.right = 120;
scene.add(light);
//grid
var grid = new THREE.GridHelper(20, 20, 0x0000ff, 0xff0000);
grid.material.opacity = 0.2;
grid.material.transparent = true;
scene.add(grid);
}
function initCamera() {
//相机设置
camera = new THREE.PerspectiveCamera(45, $('#viewField').innerWidth() / $('#viewField').innerHeight());
camera.position.y = data.height;
controls = new THREE.OrbitControls(camera, $('#viewField')[0]);
controls.target.set(0, data.height, 0);
controls.maxPolarAngle = Math.PI / 2;
controls.minPolarAngle = Math.PI / 2;
controls.minDistance = data.distance;
controls.maxDistance = data.distance;
controls.enablePan = false;
controls.enableKeys = false;
controls.update();
}
function initRenderer() {
//初始化渲染器
renderer = new THREE.WebGLRenderer({ antialias: true, preserveDrawingBuffer: true });
//设置像素值
renderer.setPixelRatio(window.devicePixelRatio);
//设置渲染范围为屏幕的大小
renderer.setSize($('#viewField').innerWidth(), $('#viewField').innerHeight());
//将渲染结果放到页面中
$('#viewField').append(renderer.domElement);
}
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
//------------------------------------------------------------------------------
//初始化模型
function loadModel() {
var manager = new THREE.LoadingManager();
manager.onLoad = function () {
initTexture();
};
//模型加载
var loader = new THREE.FBXLoader(manager);
for (var comIndex in data.components) {
for (var molIndex in data.components[comIndex].models) {
//异步加载问题
(function (comIndex, molIndex) {
var url = '/files/model/' + data.components[comIndex].models[molIndex].fileId;
loader.load(url, function (object) {
object.visible = (data.components[comIndex].modelIndex == molIndex);
data.components[comIndex].models[molIndex].modelObj = object;
scene.add(object);
}
);
})(comIndex, molIndex);
}
}
//贴图加载
var loader = new THREE.TextureLoader(manager);
for (var comIndex in data.components) {
for (var textureIndex in data.components[comIndex].textures) {
//异步加载问题
(function (comIndex, textureIndex) {
var url = '/files/texture/' + data.components[comIndex].textures[textureIndex].fileId;
loader.load(url, function (object) {
data.components[comIndex].textures[textureIndex].textureObj = object;
}
);
})(comIndex, textureIndex);
}
}
}
//当模型和贴图都加载结束后,给模型赋予默认贴图
function initTexture() {
for (var comIndex in data.components) {
var modelIndex = data.components[comIndex].modelIndex;
var textureIndex = data.components[comIndex].textureIndex;
//赋贴图
if (data.components[comIndex].models.length > 0 && data.components[comIndex].textures.length > 0)
replaceTexture(data.components[comIndex].models[modelIndex].modelObj, data.components[comIndex].textures[textureIndex].textureObj);
}
}
//------------------------------------------------------------------------------
//事件初始化
function initEvent() {
//当浏览器大小变化时
$(window).resize(function () {
camera.aspect = $('#viewField').innerWidth() / $('#viewField').innerHeight();
camera.updateProjectionMatrix();
renderer.setSize($('#viewField').innerWidth(), $('#viewField').innerHeight());
});
}
//------------------------------------------------------------------------------
//公用方法
function replaceTexture(modelObj, textureObj) {
modelObj.traverse(function (child) {
if (child instanceof THREE.Mesh) {
child.material.map = textureObj;
child.material.castShadow = true;
child.material.receiveShadow = true;
child.material.needsUpdate = true;
}
});
}

@ -54,10 +54,6 @@
#textureField>img{ #textureField>img{
margin-top:5px; margin-top:5px;
} }
#cameraConfig>*{
margin-top:5px;
margin-bottom:5px;
}
</style> </style>
</head> </head>
@ -78,11 +74,12 @@
<div class="panel"> <div class="panel">
<div class="panel-body"> <div class="panel-body">
<div id='cameraConfig'> <div id='cameraConfig'>
<label for="volume">相机高度最大值:</label><input type="number" id='cameraHeightMaxValue'><br /> <label for="volume">相机高度最大值:</label><input type="number" id='cameraHeightMaxValue' style="width:50px"><br />
<label for="volume">相机高度:</label><b id='cameraHeightValue'>xx</b><br /> <label for="volume">相机高度:</label><b id='cameraHeightValue'>xx</b><br />
<input type="range" id="cameraHeight" min="0" max="100" style="display: block;width: 100%"> <input type="range" id="cameraHeight" min="0" max="100" style="display: block;width: 100%">
<hr /> <hr />
<label for="volume">相机距离最大值:</label><input type="number" id='cameraDistanceMaxValue'><br /> <label for="volume">相机距离最大值:</label><input type="number" id='cameraDistanceMaxValue' style="width:50px"
size="5"><br />
<label for="volume">相机距离:</label><b id='cameraDistanceValue'>xx</b><br /> <label for="volume">相机距离:</label><b id='cameraDistanceValue'>xx</b><br />
<input type="range" id="cameraDistance" min="0" max="100" style="display: block;width: 100%"> <input type="range" id="cameraDistance" min="0" max="100" style="display: block;width: 100%">
</div> </div>
@ -104,9 +101,7 @@
</ul> </ul>
</div> </div>
<div> <div>
<div class="page-header"> <h4 id="componentTitle">请先选择部件</h4>
<h4 id="componentTitle">请先选择部件</h3>
</div>
<div class="list-group" id="modelList"> <div class="list-group" id="modelList">
</div> </div>
<button id="delComponent" class="btn btn-danger pull-right" style="display: none;margin-left:10px;">删除该组件</button> <button id="delComponent" class="btn btn-danger pull-right" style="display: none;margin-left:10px;">删除该组件</button>
@ -190,7 +185,7 @@
</div> </div>
</div> </div>
<!-- 图片裁切 --> <!-- 图片裁切 -->
<canvas style='z-index: 5;' id='compress' style='display: none'></canvas> <canvas id='compress' style='display: none'></canvas>
<script src="/js/createScheme.js"></script> <script src="/js/createScheme.js"></script>
</body> </body>

@ -150,6 +150,29 @@
$('#isShared').attr("checked", true); $('#isShared').attr("checked", true);
break; break;
} }
$('#changeShareConfig').click(function () {
var needPassword = $('#needPassword').is(":checked")
var isShared = $('#isShared').is(":checked")
var share_password = $('#sharePassword').val();
var share_state = 0;
if (isShared)
share_state = 1;
if (needPassword && share_state)
share_state = 2;
var sendData = {
id: data.schemeList[index].id,
share_password: share_password,
share_state: share_state
}
$.post('/changeShareConfig', sendData, function (reply) {
if (reply.affectedRows) {
data.schemeList[index].share_password = share_password;
data.schemeList[index].share_state = share_state;
$('#shareSchemeModal').modal('hide');
}
});
});
} }
</script> </script>
</body> </body>

@ -11,7 +11,6 @@
<!-- ZUI --> <!-- ZUI -->
<link rel="stylesheet" href="https://cdn.bootcss.com/zui/1.8.1/css/zui.min.css"> <link rel="stylesheet" href="https://cdn.bootcss.com/zui/1.8.1/css/zui.min.css">
<script src="https://cdn.bootcss.com/zui/1.8.1/js/zui.min.js"></script> <script src="https://cdn.bootcss.com/zui/1.8.1/js/zui.min.js"></script>
<script src="/js/vector.js"></script>
<!-- 3D背景动画 --> <!-- 3D背景动画 -->
<script src="/js/vector.js"></script> <script src="/js/vector.js"></script>
<style> <style>

@ -5,11 +5,66 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge"> <meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title> <title>3D MODELS SYSTEM - SHARE</title>
<!-- jquery -->
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<!-- three.js -->
<script src="/js/three/three.js"></script>
<script src="/js/three/OrbitControls.js"></script>
<!-- 加载器 -->
<script src="/js/three/OBJLoader.js"></script>
<script src="/js/three/FBXLoader.js"></script>
<script src="/js/three/TGALoader.js"></script>
<script src='/js/three/inflate.min.js'></script>
<!-- ZUI -->
<link rel="stylesheet" href="https://cdn.bootcss.com/zui/1.8.1/css/zui.min.css">
<script src="https://cdn.bootcss.com/zui/1.8.1/js/zui.min.js"></script>
<style>
* {
margin: 0px;
padding: 0px;
}
html,
body {
width: 100%;
height: 100%;
overflow: hidden;
}
#viewField {
width: 100%;
height: 100%;
}
</style>
</head> </head>
<body> <body>
<!-- threejs容器 -->
<div id="viewField">
</div>
<!-- 模态框:访问密码 -->
<div class="modal fade" id="visitPasswordModal">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span
class="sr-only">关闭</span></button>
<h4 class="modal-title">访问密码</h4>
</div>
<div class="modal-body">
<input type="password" class="form-control" id="visitPassword" placeholder="请输入访问密码">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
<button type="button" class="btn btn-primary" id="visitBtn">确定</button>
</div>
</div>
</div>
</div>
<script src="/js/share.js"></script>
</body> </body>
</html> </html>
Loading…
Cancel
Save