@ -0,0 +1,5 @@ |
||||
[*.{js,jsx,ts,tsx,vue}] |
||||
indent_style = space |
||||
indent_size = 2 |
||||
trim_trailing_whitespace = true |
||||
insert_final_newline = true |
@ -0,0 +1,21 @@ |
||||
.DS_Store |
||||
node_modules |
||||
/dist |
||||
|
||||
# local env files |
||||
.env.local |
||||
.env.*.local |
||||
|
||||
# Log files |
||||
npm-debug.log* |
||||
yarn-debug.log* |
||||
yarn-error.log* |
||||
|
||||
# Editor directories and files |
||||
.idea |
||||
.vscode |
||||
*.suo |
||||
*.ntvs* |
||||
*.njsproj |
||||
*.sln |
||||
*.sw? |
@ -0,0 +1,29 @@ |
||||
# v3dmodel |
||||
|
||||
## Project setup |
||||
``` |
||||
npm install |
||||
``` |
||||
|
||||
### Compiles and hot-reloads for development |
||||
``` |
||||
npm run serve |
||||
``` |
||||
|
||||
### Compiles and minifies for production |
||||
``` |
||||
npm run build |
||||
``` |
||||
|
||||
### Run your tests |
||||
``` |
||||
npm run test |
||||
``` |
||||
|
||||
### Lints and fixes files |
||||
``` |
||||
npm run lint |
||||
``` |
||||
|
||||
### Customize configuration |
||||
See [Configuration Reference](https://cli.vuejs.org/config/). |
@ -0,0 +1,5 @@ |
||||
module.exports = { |
||||
presets: [ |
||||
'@vue/app' |
||||
] |
||||
} |
@ -0,0 +1,57 @@ |
||||
{ |
||||
"name": "v3dmodel", |
||||
"version": "0.1.0", |
||||
"private": true, |
||||
"scripts": { |
||||
"serve": "vue-cli-service serve", |
||||
"build": "vue-cli-service build", |
||||
"lint": "vue-cli-service lint" |
||||
}, |
||||
"dependencies": { |
||||
"core-js": "^2.6.5", |
||||
"qrious": "^4.0.2", |
||||
"three": "^0.103.0", |
||||
"vue": "^2.6.10", |
||||
"vue-resource": "^1.5.1", |
||||
"vue-router": "^3.0.3", |
||||
"vuetify": "^1.5.5", |
||||
"vuex": "^3.0.1" |
||||
}, |
||||
"devDependencies": { |
||||
"@vue/cli-plugin-babel": "^3.6.0", |
||||
"@vue/cli-plugin-eslint": "^3.6.0", |
||||
"@vue/cli-service": "^3.6.0", |
||||
"@vue/eslint-config-standard": "^4.0.0", |
||||
"babel-eslint": "^10.0.1", |
||||
"eslint": "^5.16.0", |
||||
"eslint-plugin-vue": "^5.0.0", |
||||
"stylus": "^0.54.5", |
||||
"stylus-loader": "^3.0.1", |
||||
"vue-cli-plugin-vuetify": "^0.5.0", |
||||
"vue-template-compiler": "^2.5.21", |
||||
"vuetify-loader": "^1.0.5" |
||||
}, |
||||
"eslintConfig": { |
||||
"root": true, |
||||
"env": { |
||||
"node": true |
||||
}, |
||||
"extends": [ |
||||
"plugin:vue/essential", |
||||
"@vue/standard" |
||||
], |
||||
"parserOptions": { |
||||
"parser": "babel-eslint" |
||||
} |
||||
}, |
||||
"postcss": { |
||||
"plugins": { |
||||
"autoprefixer": {} |
||||
} |
||||
}, |
||||
"browserslist": [ |
||||
"> 1%", |
||||
"last 2 versions", |
||||
"not ie <= 8" |
||||
] |
||||
} |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 54 KiB |
After Width: | Height: | Size: 225 KiB |
After Width: | Height: | Size: 449 KiB |
After Width: | Height: | Size: 306 KiB |
After Width: | Height: | Size: 268 KiB |
After Width: | Height: | Size: 153 KiB |
After Width: | Height: | Size: 370 KiB |
After Width: | Height: | Size: 3.0 MiB |
After Width: | Height: | Size: 3.0 MiB |
After Width: | Height: | Size: 3.0 MiB |
After Width: | Height: | Size: 3.0 MiB |
After Width: | Height: | Size: 3.0 MiB |
After Width: | Height: | Size: 3.0 MiB |
@ -0,0 +1,20 @@ |
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
<head> |
||||
<meta charset="utf-8"> |
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0"> |
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico"> |
||||
<title>V3D</title> |
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900"> |
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Material+Icons"> |
||||
<script src="./js/inflate.min.js"></script> |
||||
</head> |
||||
<body> |
||||
<noscript> |
||||
<strong>We're sorry but v3dmodel doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> |
||||
</noscript> |
||||
<div id="app"></div> |
||||
<!-- built files will be auto injected --> |
||||
</body> |
||||
</html> |
@ -0,0 +1,15 @@ |
||||
/** @license zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */(function() {'use strict';var l=void 0,aa=this;function r(c,d){var a=c.split("."),b=aa;!(a[0]in b)&&b.execScript&&b.execScript("var "+a[0]);for(var e;a.length&&(e=a.shift());)!a.length&&d!==l?b[e]=d:b=b[e]?b[e]:b[e]={}};var t="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array&&"undefined"!==typeof DataView;function v(c){var d=c.length,a=0,b=Number.POSITIVE_INFINITY,e,f,g,h,k,m,n,p,s,x;for(p=0;p<d;++p)c[p]>a&&(a=c[p]),c[p]<b&&(b=c[p]);e=1<<a;f=new (t?Uint32Array:Array)(e);g=1;h=0;for(k=2;g<=a;){for(p=0;p<d;++p)if(c[p]===g){m=0;n=h;for(s=0;s<g;++s)m=m<<1|n&1,n>>=1;x=g<<16|p;for(s=m;s<e;s+=k)f[s]=x;++h}++g;h<<=1;k<<=1}return[f,a,b]};function w(c,d){this.g=[];this.h=32768;this.d=this.f=this.a=this.l=0;this.input=t?new Uint8Array(c):c;this.m=!1;this.i=y;this.r=!1;if(d||!(d={}))d.index&&(this.a=d.index),d.bufferSize&&(this.h=d.bufferSize),d.bufferType&&(this.i=d.bufferType),d.resize&&(this.r=d.resize);switch(this.i){case A:this.b=32768;this.c=new (t?Uint8Array:Array)(32768+this.h+258);break;case y:this.b=0;this.c=new (t?Uint8Array:Array)(this.h);this.e=this.z;this.n=this.v;this.j=this.w;break;default:throw Error("invalid inflate mode"); |
||||
}}var A=0,y=1,B={t:A,s:y}; |
||||
w.prototype.k=function(){for(;!this.m;){var c=C(this,3);c&1&&(this.m=!0);c>>>=1;switch(c){case 0:var d=this.input,a=this.a,b=this.c,e=this.b,f=d.length,g=l,h=l,k=b.length,m=l;this.d=this.f=0;if(a+1>=f)throw Error("invalid uncompressed block header: LEN");g=d[a++]|d[a++]<<8;if(a+1>=f)throw Error("invalid uncompressed block header: NLEN");h=d[a++]|d[a++]<<8;if(g===~h)throw Error("invalid uncompressed block header: length verify");if(a+g>d.length)throw Error("input buffer is broken");switch(this.i){case A:for(;e+ |
||||
g>b.length;){m=k-e;g-=m;if(t)b.set(d.subarray(a,a+m),e),e+=m,a+=m;else for(;m--;)b[e++]=d[a++];this.b=e;b=this.e();e=this.b}break;case y:for(;e+g>b.length;)b=this.e({p:2});break;default:throw Error("invalid inflate mode");}if(t)b.set(d.subarray(a,a+g),e),e+=g,a+=g;else for(;g--;)b[e++]=d[a++];this.a=a;this.b=e;this.c=b;break;case 1:this.j(ba,ca);break;case 2:for(var n=C(this,5)+257,p=C(this,5)+1,s=C(this,4)+4,x=new (t?Uint8Array:Array)(D.length),S=l,T=l,U=l,u=l,M=l,F=l,z=l,q=l,V=l,q=0;q<s;++q)x[D[q]]= |
||||
C(this,3);if(!t){q=s;for(s=x.length;q<s;++q)x[D[q]]=0}S=v(x);u=new (t?Uint8Array:Array)(n+p);q=0;for(V=n+p;q<V;)switch(M=E(this,S),M){case 16:for(z=3+C(this,2);z--;)u[q++]=F;break;case 17:for(z=3+C(this,3);z--;)u[q++]=0;F=0;break;case 18:for(z=11+C(this,7);z--;)u[q++]=0;F=0;break;default:F=u[q++]=M}T=t?v(u.subarray(0,n)):v(u.slice(0,n));U=t?v(u.subarray(n)):v(u.slice(n));this.j(T,U);break;default:throw Error("unknown BTYPE: "+c);}}return this.n()}; |
||||
var G=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],D=t?new Uint16Array(G):G,H=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258],I=t?new Uint16Array(H):H,J=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0],K=t?new Uint8Array(J):J,L=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],da=t?new Uint16Array(L):L,ea=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12, |
||||
13,13],N=t?new Uint8Array(ea):ea,O=new (t?Uint8Array:Array)(288),P,fa;P=0;for(fa=O.length;P<fa;++P)O[P]=143>=P?8:255>=P?9:279>=P?7:8;var ba=v(O),Q=new (t?Uint8Array:Array)(30),R,ga;R=0;for(ga=Q.length;R<ga;++R)Q[R]=5;var ca=v(Q);function C(c,d){for(var a=c.f,b=c.d,e=c.input,f=c.a,g=e.length,h;b<d;){if(f>=g)throw Error("input buffer is broken");a|=e[f++]<<b;b+=8}h=a&(1<<d)-1;c.f=a>>>d;c.d=b-d;c.a=f;return h} |
||||
function E(c,d){for(var a=c.f,b=c.d,e=c.input,f=c.a,g=e.length,h=d[0],k=d[1],m,n;b<k&&!(f>=g);)a|=e[f++]<<b,b+=8;m=h[a&(1<<k)-1];n=m>>>16;if(n>b)throw Error("invalid code length: "+n);c.f=a>>n;c.d=b-n;c.a=f;return m&65535} |
||||
w.prototype.j=function(c,d){var a=this.c,b=this.b;this.o=c;for(var e=a.length-258,f,g,h,k;256!==(f=E(this,c));)if(256>f)b>=e&&(this.b=b,a=this.e(),b=this.b),a[b++]=f;else{g=f-257;k=I[g];0<K[g]&&(k+=C(this,K[g]));f=E(this,d);h=da[f];0<N[f]&&(h+=C(this,N[f]));b>=e&&(this.b=b,a=this.e(),b=this.b);for(;k--;)a[b]=a[b++-h]}for(;8<=this.d;)this.d-=8,this.a--;this.b=b}; |
||||
w.prototype.w=function(c,d){var a=this.c,b=this.b;this.o=c;for(var e=a.length,f,g,h,k;256!==(f=E(this,c));)if(256>f)b>=e&&(a=this.e(),e=a.length),a[b++]=f;else{g=f-257;k=I[g];0<K[g]&&(k+=C(this,K[g]));f=E(this,d);h=da[f];0<N[f]&&(h+=C(this,N[f]));b+k>e&&(a=this.e(),e=a.length);for(;k--;)a[b]=a[b++-h]}for(;8<=this.d;)this.d-=8,this.a--;this.b=b}; |
||||
w.prototype.e=function(){var c=new (t?Uint8Array:Array)(this.b-32768),d=this.b-32768,a,b,e=this.c;if(t)c.set(e.subarray(32768,c.length));else{a=0;for(b=c.length;a<b;++a)c[a]=e[a+32768]}this.g.push(c);this.l+=c.length;if(t)e.set(e.subarray(d,d+32768));else for(a=0;32768>a;++a)e[a]=e[d+a];this.b=32768;return e}; |
||||
w.prototype.z=function(c){var d,a=this.input.length/this.a+1|0,b,e,f,g=this.input,h=this.c;c&&("number"===typeof c.p&&(a=c.p),"number"===typeof c.u&&(a+=c.u));2>a?(b=(g.length-this.a)/this.o[2],f=258*(b/2)|0,e=f<h.length?h.length+f:h.length<<1):e=h.length*a;t?(d=new Uint8Array(e),d.set(h)):d=h;return this.c=d}; |
||||
w.prototype.n=function(){var c=0,d=this.c,a=this.g,b,e=new (t?Uint8Array:Array)(this.l+(this.b-32768)),f,g,h,k;if(0===a.length)return t?this.c.subarray(32768,this.b):this.c.slice(32768,this.b);f=0;for(g=a.length;f<g;++f){b=a[f];h=0;for(k=b.length;h<k;++h)e[c++]=b[h]}f=32768;for(g=this.b;f<g;++f)e[c++]=d[f];this.g=[];return this.buffer=e}; |
||||
w.prototype.v=function(){var c,d=this.b;t?this.r?(c=new Uint8Array(d),c.set(this.c.subarray(0,d))):c=this.c.subarray(0,d):(this.c.length>d&&(this.c.length=d),c=this.c);return this.buffer=c};function W(c,d){var a,b;this.input=c;this.a=0;if(d||!(d={}))d.index&&(this.a=d.index),d.verify&&(this.A=d.verify);a=c[this.a++];b=c[this.a++];switch(a&15){case ha:this.method=ha;break;default:throw Error("unsupported compression method");}if(0!==((a<<8)+b)%31)throw Error("invalid fcheck flag:"+((a<<8)+b)%31);if(b&32)throw Error("fdict flag is not supported");this.q=new w(c,{index:this.a,bufferSize:d.bufferSize,bufferType:d.bufferType,resize:d.resize})} |
||||
W.prototype.k=function(){var c=this.input,d,a;d=this.q.k();this.a=this.q.a;if(this.A){a=(c[this.a++]<<24|c[this.a++]<<16|c[this.a++]<<8|c[this.a++])>>>0;var b=d;if("string"===typeof b){var e=b.split(""),f,g;f=0;for(g=e.length;f<g;f++)e[f]=(e[f].charCodeAt(0)&255)>>>0;b=e}for(var h=1,k=0,m=b.length,n,p=0;0<m;){n=1024<m?1024:m;m-=n;do h+=b[p++],k+=h;while(--n);h%=65521;k%=65521}if(a!==(k<<16|h)>>>0)throw Error("invalid adler-32 checksum");}return d};var ha=8;r("Zlib.Inflate",W);r("Zlib.Inflate.prototype.decompress",W.prototype.k);var X={ADAPTIVE:B.s,BLOCK:B.t},Y,Z,$,ia;if(Object.keys)Y=Object.keys(X);else for(Z in Y=[],$=0,X)Y[$++]=Z;$=0;for(ia=Y.length;$<ia;++$)Z=Y[$],r("Zlib.Inflate.BufferType."+Z,X[Z]);}).call(this); |
@ -0,0 +1,22 @@ |
||||
<template> |
||||
<transition mode="out-in"> |
||||
<router-view></router-view> |
||||
</transition> |
||||
</template> |
||||
|
||||
<style> |
||||
.v-enter { |
||||
opacity: 0; |
||||
transform: translateX(300px); |
||||
} |
||||
|
||||
.v-leave-to { |
||||
opacity: 0; |
||||
transform: translateX(-300px); |
||||
} |
||||
|
||||
.v-enter-active, |
||||
.v-leave-active { |
||||
transition: all 0.3s ease; |
||||
} |
||||
</style> |
@ -0,0 +1,202 @@ |
||||
<template> |
||||
<!-- 挂载点 --> |
||||
<div style="width: 100%; height: 100%; margin: 0; border: 0; padding: 0;"> |
||||
<canvas v-if="suportWebGL" ref="stage" style="width: 100%; height: 100%;"></canvas> |
||||
<div v-else> |
||||
<slot>浏览器不支持WebGL</slot> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import "./plugins/OrbitControls"; |
||||
import "./plugins/OBJLoader"; |
||||
import "./plugins/FBXLoader"; |
||||
|
||||
import { |
||||
CubeTextureLoader, |
||||
Scene, |
||||
WebGLRenderer, |
||||
PerspectiveCamera, |
||||
AmbientLight, |
||||
DirectionalLight, |
||||
OrbitControls |
||||
} from "three"; |
||||
|
||||
//判断浏览器是否支持WebGL |
||||
const suportWebGL = (() => { |
||||
try { |
||||
var canvas = document.createElement("canvas"); |
||||
return !!( |
||||
window.WebGLRenderingContext && |
||||
(canvas.getContext("webgl") || canvas.getContext("experimental-webgl")) |
||||
); |
||||
} catch (e) { |
||||
return false; |
||||
} |
||||
})(); |
||||
|
||||
export default { |
||||
props: ["componentsInfo", "cameraControll"], |
||||
data() { |
||||
return { |
||||
//requestAnimationFrame ID |
||||
reqId: null, |
||||
//浏览器是否支持WebGL |
||||
suportWebGL, |
||||
//相机 |
||||
camera: null, |
||||
//场景 |
||||
scene: new Scene(), |
||||
//相机控制器 |
||||
control: null |
||||
}; |
||||
}, |
||||
//在DOM上树后进行初始化 |
||||
mounted() { |
||||
//相机设置 |
||||
this.camera = new PerspectiveCamera( |
||||
45, |
||||
this.$el.offsetWidth / this.$el.offsetHeight, |
||||
0.01, |
||||
100000 |
||||
); |
||||
//灯光 |
||||
this.scene.add(new AmbientLight(0xffffff)); |
||||
//天空盒 |
||||
this.scene.background = new CubeTextureLoader() |
||||
.setPath("/img/skybox/") |
||||
.load(["px.jpg", "nx.jpg", "py.jpg", "ny.jpg", "pz.jpg", "nz.jpg"]); |
||||
//相机控制器 |
||||
this.control = new OrbitControls(this.camera, this.$refs.stage); |
||||
//固定视角 |
||||
this.camera.position.y = this.cameraControll.height; |
||||
this.control.target.set(0, this.cameraControll.height, 0); |
||||
this.control.minDistance = this.cameraControll.distance; |
||||
this.control.maxDistance = this.cameraControll.distance; |
||||
// this.control.maxPolarAngle = Math.PI / 2; |
||||
// this.control.minPolarAngle = Math.PI / 2; |
||||
this.control.enablePan = false; |
||||
this.control.enableKeys = false; |
||||
this.control.update(); |
||||
//初始化渲染器 |
||||
this.renderer = new WebGLRenderer({ |
||||
antialias: true, |
||||
preserveDrawingBuffer: true, |
||||
alpha: true, |
||||
canvas: this.$refs.stage |
||||
}); |
||||
this.onResize(); |
||||
//浏览器自动重绘 |
||||
this.animate(); |
||||
//窗口进行拉伸需要更新 |
||||
window.addEventListener("resize", this.onResize, false); |
||||
|
||||
// var grid = new GridHelper(20, 20, 0x0000ff, 0xff0000); |
||||
// grid.material.opacity = 0.2; |
||||
// grid.material.transparent = true; |
||||
// this.scene.add(grid); |
||||
}, |
||||
//在组件销毁前要取消各种监听 |
||||
beforeDestroy() { |
||||
//取消窗口拉伸监听 |
||||
window.removeEventListener("resize", this.onResize, false); |
||||
//取消浏览器自动重绘 |
||||
cancelAnimationFrame(this.reqId); |
||||
}, |
||||
methods: { |
||||
//窗口拉伸触发事件 |
||||
onResize() { |
||||
let width = this.$el.offsetWidth, |
||||
height = this.$el.offsetHeight; |
||||
//相机更新 |
||||
this.camera.aspect = width / height; |
||||
this.camera.updateProjectionMatrix(); |
||||
//渲染器更新 |
||||
this.renderer.setSize(width, height); |
||||
this.renderer.setPixelRatio(window.devicePixelRatio || 1); |
||||
}, |
||||
//页面刷新重绘方法 |
||||
animate() { |
||||
this.reqId = requestAnimationFrame(this.animate); |
||||
this.renderer.render(this.scene, this.camera); |
||||
}, |
||||
updateScene() { |
||||
if (this.componentsInfo != null) { |
||||
this.componentsInfo.map(item => { |
||||
let modelIndex = item.modelSelected; |
||||
let textureIndex = item.textureSelected; |
||||
let modelObj = null; |
||||
if (item.models[modelIndex] != null) { |
||||
modelObj = item.models[modelIndex].obj; |
||||
} |
||||
let textureObj = null; |
||||
if (item.textures[textureIndex] != null) { |
||||
textureObj = item.textures[textureIndex].obj; |
||||
} |
||||
if (modelObj != null) { |
||||
if (textureObj != null) { |
||||
modelObj.traverse(child => { |
||||
if (child.isMesh) { |
||||
//贴图放大 |
||||
textureObj.repeat.set( |
||||
this.cameraControll.textureSize, |
||||
this.cameraControll.textureSize |
||||
); |
||||
child.material.map = textureObj; |
||||
} |
||||
}); |
||||
} |
||||
item.models.map((subItem, index) => { |
||||
if (subItem.obj != null) { |
||||
// if (subItem.obj.parent == null) { |
||||
// this.scene.add(subItem.obj); |
||||
// } |
||||
this.scene.add(subItem.obj); |
||||
if (index == modelIndex) { |
||||
subItem.obj.visible = true; |
||||
} else { |
||||
subItem.obj.visible = false; |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
}); |
||||
} |
||||
}, |
||||
//获取当前的缩略图,并且返回为File |
||||
getCover() { |
||||
var dataurl = this.$refs.stage.toDataURL("image/jpeg", 0.2); |
||||
var arr = dataurl.split(","), |
||||
mime = arr[0].match(/:(.*?);/)[1], |
||||
bstr = atob(arr[1]), |
||||
n = bstr.length, |
||||
u8arr = new Uint8Array(n); |
||||
while (n--) { |
||||
u8arr[n] = bstr.charCodeAt(n); |
||||
} |
||||
return new File([u8arr], "cover.jpg", { type: mime }); |
||||
} |
||||
}, |
||||
watch: { |
||||
cameraControll: { |
||||
handler() { |
||||
if (!isNaN(this.cameraControll.height)) { |
||||
this.camera.position.y = this.cameraControll.height; |
||||
this.control.target.set(0, this.cameraControll.height, 0); |
||||
this.control.update(); |
||||
} |
||||
if (!isNaN(this.cameraControll.distance)) { |
||||
this.control.minDistance = this.cameraControll.distance; |
||||
this.control.maxDistance = this.cameraControll.distance; |
||||
this.control.update(); |
||||
} |
||||
if (!isNaN(this.cameraControll.textureSize)) { |
||||
this.updateScene(); |
||||
} |
||||
}, |
||||
deep: true |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
@ -0,0 +1,799 @@ |
||||
|
||||
import * as THREE from "three"; |
||||
/** |
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/ |
||||
|
||||
THREE.OBJLoader = ( function () { |
||||
|
||||
// o object_name | g group_name
|
||||
var object_pattern = /^[og]\s*(.+)?/; |
||||
// mtllib file_reference
|
||||
var material_library_pattern = /^mtllib /; |
||||
// usemtl material_name
|
||||
var material_use_pattern = /^usemtl /; |
||||
|
||||
function ParserState() { |
||||
|
||||
var state = { |
||||
objects: [], |
||||
object: {}, |
||||
|
||||
vertices: [], |
||||
normals: [], |
||||
colors: [], |
||||
uvs: [], |
||||
|
||||
materialLibraries: [], |
||||
|
||||
startObject: function ( name, fromDeclaration ) { |
||||
|
||||
// If the current object (initial from reset) is not from a g/o declaration in the parsed
|
||||
// file. We need to use it for the first parsed g/o to keep things in sync.
|
||||
if ( this.object && this.object.fromDeclaration === false ) { |
||||
|
||||
this.object.name = name; |
||||
this.object.fromDeclaration = ( fromDeclaration !== false ); |
||||
return; |
||||
|
||||
} |
||||
|
||||
var previousMaterial = ( this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined ); |
||||
|
||||
if ( this.object && typeof this.object._finalize === 'function' ) { |
||||
|
||||
this.object._finalize( true ); |
||||
|
||||
} |
||||
|
||||
this.object = { |
||||
name: name || '', |
||||
fromDeclaration: ( fromDeclaration !== false ), |
||||
|
||||
geometry: { |
||||
vertices: [], |
||||
normals: [], |
||||
colors: [], |
||||
uvs: [] |
||||
}, |
||||
materials: [], |
||||
smooth: true, |
||||
|
||||
startMaterial: function ( name, libraries ) { |
||||
|
||||
var previous = this._finalize( false ); |
||||
|
||||
// New usemtl declaration overwrites an inherited material, except if faces were declared
|
||||
// after the material, then it must be preserved for proper MultiMaterial continuation.
|
||||
if ( previous && ( previous.inherited || previous.groupCount <= 0 ) ) { |
||||
|
||||
this.materials.splice( previous.index, 1 ); |
||||
|
||||
} |
||||
|
||||
var material = { |
||||
index: this.materials.length, |
||||
name: name || '', |
||||
mtllib: ( Array.isArray( libraries ) && libraries.length > 0 ? libraries[ libraries.length - 1 ] : '' ), |
||||
smooth: ( previous !== undefined ? previous.smooth : this.smooth ), |
||||
groupStart: ( previous !== undefined ? previous.groupEnd : 0 ), |
||||
groupEnd: - 1, |
||||
groupCount: - 1, |
||||
inherited: false, |
||||
|
||||
clone: function ( index ) { |
||||
|
||||
var cloned = { |
||||
index: ( typeof index === 'number' ? index : this.index ), |
||||
name: this.name, |
||||
mtllib: this.mtllib, |
||||
smooth: this.smooth, |
||||
groupStart: 0, |
||||
groupEnd: - 1, |
||||
groupCount: - 1, |
||||
inherited: false |
||||
}; |
||||
cloned.clone = this.clone.bind( cloned ); |
||||
return cloned; |
||||
|
||||
} |
||||
}; |
||||
|
||||
this.materials.push( material ); |
||||
|
||||
return material; |
||||
|
||||
}, |
||||
|
||||
currentMaterial: function () { |
||||
|
||||
if ( this.materials.length > 0 ) { |
||||
|
||||
return this.materials[ this.materials.length - 1 ]; |
||||
|
||||
} |
||||
|
||||
return undefined; |
||||
|
||||
}, |
||||
|
||||
_finalize: function ( end ) { |
||||
|
||||
var lastMultiMaterial = this.currentMaterial(); |
||||
if ( lastMultiMaterial && lastMultiMaterial.groupEnd === - 1 ) { |
||||
|
||||
lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3; |
||||
lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart; |
||||
lastMultiMaterial.inherited = false; |
||||
|
||||
} |
||||
|
||||
// Ignore objects tail materials if no face declarations followed them before a new o/g started.
|
||||
if ( end && this.materials.length > 1 ) { |
||||
|
||||
for ( var mi = this.materials.length - 1; mi >= 0; mi -- ) { |
||||
|
||||
if ( this.materials[ mi ].groupCount <= 0 ) { |
||||
|
||||
this.materials.splice( mi, 1 ); |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
// Guarantee at least one empty material, this makes the creation later more straight forward.
|
||||
if ( end && this.materials.length === 0 ) { |
||||
|
||||
this.materials.push( { |
||||
name: '', |
||||
smooth: this.smooth |
||||
} ); |
||||
|
||||
} |
||||
|
||||
return lastMultiMaterial; |
||||
|
||||
} |
||||
}; |
||||
|
||||
// Inherit previous objects material.
|
||||
// Spec tells us that a declared material must be set to all objects until a new material is declared.
|
||||
// If a usemtl declaration is encountered while this new object is being parsed, it will
|
||||
// overwrite the inherited material. Exception being that there was already face declarations
|
||||
// to the inherited material, then it will be preserved for proper MultiMaterial continuation.
|
||||
|
||||
if ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function' ) { |
||||
|
||||
var declared = previousMaterial.clone( 0 ); |
||||
declared.inherited = true; |
||||
this.object.materials.push( declared ); |
||||
|
||||
} |
||||
|
||||
this.objects.push( this.object ); |
||||
|
||||
}, |
||||
|
||||
finalize: function () { |
||||
|
||||
if ( this.object && typeof this.object._finalize === 'function' ) { |
||||
|
||||
this.object._finalize( true ); |
||||
|
||||
} |
||||
|
||||
}, |
||||
|
||||
parseVertexIndex: function ( value, len ) { |
||||
|
||||
var index = parseInt( value, 10 ); |
||||
return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; |
||||
|
||||
}, |
||||
|
||||
parseNormalIndex: function ( value, len ) { |
||||
|
||||
var index = parseInt( value, 10 ); |
||||
return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; |
||||
|
||||
}, |
||||
|
||||
parseUVIndex: function ( value, len ) { |
||||
|
||||
var index = parseInt( value, 10 ); |
||||
return ( index >= 0 ? index - 1 : index + len / 2 ) * 2; |
||||
|
||||
}, |
||||
|
||||
addVertex: function ( a, b, c ) { |
||||
|
||||
var src = this.vertices; |
||||
var dst = this.object.geometry.vertices; |
||||
|
||||
dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); |
||||
dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); |
||||
dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); |
||||
|
||||
}, |
||||
|
||||
addVertexPoint: function ( a ) { |
||||
|
||||
var src = this.vertices; |
||||
var dst = this.object.geometry.vertices; |
||||
|
||||
dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); |
||||
|
||||
}, |
||||
|
||||
addVertexLine: function ( a ) { |
||||
|
||||
var src = this.vertices; |
||||
var dst = this.object.geometry.vertices; |
||||
|
||||
dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); |
||||
|
||||
}, |
||||
|
||||
addNormal: function ( a, b, c ) { |
||||
|
||||
var src = this.normals; |
||||
var dst = this.object.geometry.normals; |
||||
|
||||
dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); |
||||
dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); |
||||
dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); |
||||
|
||||
}, |
||||
|
||||
addColor: function ( a, b, c ) { |
||||
|
||||
var src = this.colors; |
||||
var dst = this.object.geometry.colors; |
||||
|
||||
dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); |
||||
dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); |
||||
dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); |
||||
|
||||
}, |
||||
|
||||
addUV: function ( a, b, c ) { |
||||
|
||||
var src = this.uvs; |
||||
var dst = this.object.geometry.uvs; |
||||
|
||||
dst.push( src[ a + 0 ], src[ a + 1 ] ); |
||||
dst.push( src[ b + 0 ], src[ b + 1 ] ); |
||||
dst.push( src[ c + 0 ], src[ c + 1 ] ); |
||||
|
||||
}, |
||||
|
||||
addUVLine: function ( a ) { |
||||
|
||||
var src = this.uvs; |
||||
var dst = this.object.geometry.uvs; |
||||
|
||||
dst.push( src[ a + 0 ], src[ a + 1 ] ); |
||||
|
||||
}, |
||||
|
||||
addFace: function ( a, b, c, ua, ub, uc, na, nb, nc ) { |
||||
|
||||
var vLen = this.vertices.length; |
||||
|
||||
var ia = this.parseVertexIndex( a, vLen ); |
||||
var ib = this.parseVertexIndex( b, vLen ); |
||||
var ic = this.parseVertexIndex( c, vLen ); |
||||
|
||||
this.addVertex( ia, ib, ic ); |
||||
|
||||
if ( ua !== undefined && ua !== '' ) { |
||||
|
||||
var uvLen = this.uvs.length; |
||||
ia = this.parseUVIndex( ua, uvLen ); |
||||
ib = this.parseUVIndex( ub, uvLen ); |
||||
ic = this.parseUVIndex( uc, uvLen ); |
||||
this.addUV( ia, ib, ic ); |
||||
|
||||
} |
||||
|
||||
if ( na !== undefined && na !== '' ) { |
||||
|
||||
// Normals are many times the same. If so, skip function call and parseInt.
|
||||
var nLen = this.normals.length; |
||||
ia = this.parseNormalIndex( na, nLen ); |
||||
|
||||
ib = na === nb ? ia : this.parseNormalIndex( nb, nLen ); |
||||
ic = na === nc ? ia : this.parseNormalIndex( nc, nLen ); |
||||
|
||||
this.addNormal( ia, ib, ic ); |
||||
|
||||
} |
||||
|
||||
if ( this.colors.length > 0 ) { |
||||
|
||||
this.addColor( ia, ib, ic ); |
||||
|
||||
} |
||||
|
||||
}, |
||||
|
||||
addPointGeometry: function ( vertices ) { |
||||
|
||||
this.object.geometry.type = 'Points'; |
||||
|
||||
var vLen = this.vertices.length; |
||||
|
||||
for ( var vi = 0, l = vertices.length; vi < l; vi ++ ) { |
||||
|
||||
this.addVertexPoint( this.parseVertexIndex( vertices[ vi ], vLen ) ); |
||||
|
||||
} |
||||
|
||||
}, |
||||
|
||||
addLineGeometry: function ( vertices, uvs ) { |
||||
|
||||
this.object.geometry.type = 'Line'; |
||||
|
||||
var vLen = this.vertices.length; |
||||
var uvLen = this.uvs.length; |
||||
|
||||
for ( var vi = 0, l = vertices.length; vi < l; vi ++ ) { |
||||
|
||||
this.addVertexLine( this.parseVertexIndex( vertices[ vi ], vLen ) ); |
||||
|
||||
} |
||||
|
||||
for ( var uvi = 0, l = uvs.length; uvi < l; uvi ++ ) { |
||||
|
||||
this.addUVLine( this.parseUVIndex( uvs[ uvi ], uvLen ) ); |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
}; |
||||
|
||||
state.startObject( '', false ); |
||||
|
||||
return state; |
||||
|
||||
} |
||||
|
||||
//
|
||||
|
||||
function OBJLoader( manager ) { |
||||
|
||||
this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; |
||||
|
||||
this.materials = null; |
||||
|
||||
} |
||||
|
||||
OBJLoader.prototype = { |
||||
|
||||
constructor: OBJLoader, |
||||
|
||||
load: function ( url, onLoad, onProgress, onError ) { |
||||
|
||||
var scope = this; |
||||
|
||||
var loader = new THREE.FileLoader( scope.manager ); |
||||
loader.setPath( this.path ); |
||||
loader.load( url, function ( text ) { |
||||
|
||||
onLoad( scope.parse( text ) ); |
||||
|
||||
}, onProgress, onError ); |
||||
|
||||
}, |
||||
|
||||
setPath: function ( value ) { |
||||
|
||||
this.path = value; |
||||
|
||||
return this; |
||||
|
||||
}, |
||||
|
||||
setMaterials: function ( materials ) { |
||||
|
||||
this.materials = materials; |
||||
|
||||
return this; |
||||
|
||||
}, |
||||
|
||||
parse: function ( text ) { |
||||
|
||||
console.time( 'OBJLoader' ); |
||||
|
||||
var state = new ParserState(); |
||||
|
||||
if ( text.indexOf( '\r\n' ) !== - 1 ) { |
||||
|
||||
// This is faster than String.split with regex that splits on both
|
||||
text = text.replace( /\r\n/g, '\n' ); |
||||
|
||||
} |
||||
|
||||
if ( text.indexOf( '\\\n' ) !== - 1 ) { |
||||
|
||||
// join lines separated by a line continuation character (\)
|
||||
text = text.replace( /\\\n/g, '' ); |
||||
|
||||
} |
||||
|
||||
var lines = text.split( '\n' ); |
||||
var line = '', lineFirstChar = ''; |
||||
var lineLength = 0; |
||||
var result = []; |
||||
|
||||
// Faster to just trim left side of the line. Use if available.
|
||||
var trimLeft = ( typeof ''.trimLeft === 'function' ); |
||||
|
||||
for ( var i = 0, l = lines.length; i < l; i ++ ) { |
||||
|
||||
line = lines[ i ]; |
||||
|
||||
line = trimLeft ? line.trimLeft() : line.trim(); |
||||
|
||||
lineLength = line.length; |
||||
|
||||
if ( lineLength === 0 ) continue; |
||||
|
||||
lineFirstChar = line.charAt( 0 ); |
||||
|
||||
// @todo invoke passed in handler if any
|
||||
if ( lineFirstChar === '#' ) continue; |
||||
|
||||
if ( lineFirstChar === 'v' ) { |
||||
|
||||
var data = line.split( /\s+/ ); |
||||
|
||||
switch ( data[ 0 ] ) { |
||||
|
||||
case 'v': |
||||
state.vertices.push( |
||||
parseFloat( data[ 1 ] ), |
||||
parseFloat( data[ 2 ] ), |
||||
parseFloat( data[ 3 ] ) |
||||
); |
||||
if ( data.length === 8 ) { |
||||
|
||||
state.colors.push( |
||||
parseFloat( data[ 4 ] ), |
||||
parseFloat( data[ 5 ] ), |
||||
parseFloat( data[ 6 ] ) |
||||
|
||||
); |
||||
|
||||
} |
||||
break; |
||||
case 'vn': |
||||
state.normals.push( |
||||
parseFloat( data[ 1 ] ), |
||||
parseFloat( data[ 2 ] ), |
||||
parseFloat( data[ 3 ] ) |
||||
); |
||||
break; |
||||
case 'vt': |
||||
state.uvs.push( |
||||
parseFloat( data[ 1 ] ), |
||||
parseFloat( data[ 2 ] ) |
||||
); |
||||
break; |
||||
|
||||
} |
||||
|
||||
} else if ( lineFirstChar === 'f' ) { |
||||
|
||||
var lineData = line.substr( 1 ).trim(); |
||||
var vertexData = lineData.split( /\s+/ ); |
||||
var faceVertices = []; |
||||
|
||||
// Parse the face vertex data into an easy to work with format
|
||||
|
||||
for ( var j = 0, jl = vertexData.length; j < jl; j ++ ) { |
||||
|
||||
var vertex = vertexData[ j ]; |
||||
|
||||
if ( vertex.length > 0 ) { |
||||
|
||||
var vertexParts = vertex.split( '/' ); |
||||
faceVertices.push( vertexParts ); |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
// Draw an edge between the first vertex and all subsequent vertices to form an n-gon
|
||||
|
||||
var v1 = faceVertices[ 0 ]; |
||||
|
||||
for ( var j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) { |
||||
|
||||
var v2 = faceVertices[ j ]; |
||||
var v3 = faceVertices[ j + 1 ]; |
||||
|
||||
state.addFace( |
||||
v1[ 0 ], v2[ 0 ], v3[ 0 ], |
||||
v1[ 1 ], v2[ 1 ], v3[ 1 ], |
||||
v1[ 2 ], v2[ 2 ], v3[ 2 ] |
||||
); |
||||
|
||||
} |
||||
|
||||
} else if ( lineFirstChar === 'l' ) { |
||||
|
||||
var lineParts = line.substring( 1 ).trim().split( " " ); |
||||
var lineVertices = [], lineUVs = []; |
||||
|
||||
if ( line.indexOf( "/" ) === - 1 ) { |
||||
|
||||
lineVertices = lineParts; |
||||
|
||||
} else { |
||||
|
||||
for ( var li = 0, llen = lineParts.length; li < llen; li ++ ) { |
||||
|
||||
var parts = lineParts[ li ].split( "/" ); |
||||
|
||||
if ( parts[ 0 ] !== "" ) lineVertices.push( parts[ 0 ] ); |
||||
if ( parts[ 1 ] !== "" ) lineUVs.push( parts[ 1 ] ); |
||||
|
||||
} |
||||
|
||||
} |
||||
state.addLineGeometry( lineVertices, lineUVs ); |
||||
|
||||
} else if ( lineFirstChar === 'p' ) { |
||||
|
||||
var lineData = line.substr( 1 ).trim(); |
||||
var pointData = lineData.split( " " ); |
||||
|
||||
state.addPointGeometry( pointData ); |
||||
|
||||
} else if ( ( result = object_pattern.exec( line ) ) !== null ) { |
||||
|
||||
// o object_name
|
||||
// or
|
||||
// g group_name
|
||||
|
||||
// WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869
|
||||
// var name = result[ 0 ].substr( 1 ).trim();
|
||||
var name = ( " " + result[ 0 ].substr( 1 ).trim() ).substr( 1 ); |
||||
|
||||
state.startObject( name ); |
||||
|
||||
} else if ( material_use_pattern.test( line ) ) { |
||||
|
||||
// material
|
||||
|
||||
state.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries ); |
||||
|
||||
} else if ( material_library_pattern.test( line ) ) { |
||||
|
||||
// mtl file
|
||||
|
||||
state.materialLibraries.push( line.substring( 7 ).trim() ); |
||||
|
||||
} else if ( lineFirstChar === 's' ) { |
||||
|
||||
result = line.split( ' ' ); |
||||
|
||||
// smooth shading
|
||||
|
||||
// @todo Handle files that have varying smooth values for a set of faces inside one geometry,
|
||||
// but does not define a usemtl for each face set.
|
||||
// This should be detected and a dummy material created (later MultiMaterial and geometry groups).
|
||||
// This requires some care to not create extra material on each smooth value for "normal" obj files.
|
||||
// where explicit usemtl defines geometry groups.
|
||||
// Example asset: examples/models/obj/cerberus/Cerberus.obj
|
||||
|
||||
/* |
||||
* http://paulbourke.net/dataformats/obj/
|
||||
* or |
||||
* http://www.cs.utah.edu/~boulos/cs3505/obj_spec.pdf
|
||||
* |
||||
* From chapter "Grouping" Syntax explanation "s group_number": |
||||
* "group_number is the smoothing group number. To turn off smoothing groups, use a value of 0 or off. |
||||
* Polygonal elements use group numbers to put elements in different smoothing groups. For free-form |
||||
* surfaces, smoothing groups are either turned on or off; there is no difference between values greater |
||||
* than 0." |
||||
*/ |
||||
if ( result.length > 1 ) { |
||||
|
||||
var value = result[ 1 ].trim().toLowerCase(); |
||||
state.object.smooth = ( value !== '0' && value !== 'off' ); |
||||
|
||||
} else { |
||||
|
||||
// ZBrush can produce "s" lines #11707
|
||||
state.object.smooth = true; |
||||
|
||||
} |
||||
var material = state.object.currentMaterial(); |
||||
if ( material ) material.smooth = state.object.smooth; |
||||
|
||||
} else { |
||||
|
||||
// Handle null terminated files without exception
|
||||
if ( line === '\0' ) continue; |
||||
|
||||
throw new Error( 'THREE.OBJLoader: Unexpected line: "' + line + '"' ); |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
state.finalize(); |
||||
|
||||
var container = new THREE.Group(); |
||||
container.materialLibraries = [].concat( state.materialLibraries ); |
||||
|
||||
for ( var i = 0, l = state.objects.length; i < l; i ++ ) { |
||||
|
||||
var object = state.objects[ i ]; |
||||
var geometry = object.geometry; |
||||
var materials = object.materials; |
||||
var isLine = ( geometry.type === 'Line' ); |
||||
var isPoints = ( geometry.type === 'Points' ); |
||||
var hasVertexColors = false; |
||||
|
||||
// Skip o/g line declarations that did not follow with any faces
|
||||
if ( geometry.vertices.length === 0 ) continue; |
||||
|
||||
var buffergeometry = new THREE.BufferGeometry(); |
||||
|
||||
buffergeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( geometry.vertices, 3 ) ); |
||||
|
||||
if ( geometry.normals.length > 0 ) { |
||||
|
||||
buffergeometry.addAttribute( 'normal', new THREE.Float32BufferAttribute( geometry.normals, 3 ) ); |
||||
|
||||
} else { |
||||
|
||||
buffergeometry.computeVertexNormals(); |
||||
|
||||
} |
||||
|
||||
if ( geometry.colors.length > 0 ) { |
||||
|
||||
hasVertexColors = true; |
||||
buffergeometry.addAttribute( 'color', new THREE.Float32BufferAttribute( geometry.colors, 3 ) ); |
||||
|
||||
} |
||||
|
||||
if ( geometry.uvs.length > 0 ) { |
||||
|
||||
buffergeometry.addAttribute( 'uv', new THREE.Float32BufferAttribute( geometry.uvs, 2 ) ); |
||||
|
||||
} |
||||
|
||||
// Create materials
|
||||
|
||||
var createdMaterials = []; |
||||
|
||||
for ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { |
||||
|
||||
var sourceMaterial = materials[ mi ]; |
||||
var material = undefined; |
||||
|
||||
if ( this.materials !== null ) { |
||||
|
||||
material = this.materials.create( sourceMaterial.name ); |
||||
|
||||
// mtl etc. loaders probably can't create line materials correctly, copy properties to a line material.
|
||||
if ( isLine && material && ! ( material instanceof THREE.LineBasicMaterial ) ) { |
||||
|
||||
var materialLine = new THREE.LineBasicMaterial(); |
||||
THREE.Material.prototype.copy.call( materialLine, material ); |
||||
materialLine.color.copy( material.color ); |
||||
materialLine.lights = false; |
||||
material = materialLine; |
||||
|
||||
} else if ( isPoints && material && ! ( material instanceof THREE.PointsMaterial ) ) { |
||||
|
||||
var materialPoints = new THREE.PointsMaterial( { size: 10, sizeAttenuation: false } ); |
||||
THREE.Material.prototype.copy.call( materialPoints, material ); |
||||
materialPoints.color.copy( material.color ); |
||||
materialPoints.map = material.map; |
||||
materialPoints.lights = false; |
||||
material = materialPoints; |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
if ( ! material ) { |
||||
|
||||
if ( isLine ) { |
||||
|
||||
material = new THREE.LineBasicMaterial(); |
||||
|
||||
} else if ( isPoints ) { |
||||
|
||||
material = new THREE.PointsMaterial( { size: 1, sizeAttenuation: false } ); |
||||
|
||||
} else { |
||||
|
||||
material = new THREE.MeshPhongMaterial(); |
||||
|
||||
} |
||||
|
||||
material.name = sourceMaterial.name; |
||||
|
||||
} |
||||
|
||||
material.flatShading = sourceMaterial.smooth ? false : true; |
||||
material.vertexColors = hasVertexColors ? THREE.VertexColors : THREE.NoColors; |
||||
|
||||
createdMaterials.push( material ); |
||||
|
||||
} |
||||
|
||||
// Create mesh
|
||||
|
||||
var mesh; |
||||
|
||||
if ( createdMaterials.length > 1 ) { |
||||
|
||||
for ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { |
||||
|
||||
var sourceMaterial = materials[ mi ]; |
||||
buffergeometry.addGroup( sourceMaterial.groupStart, sourceMaterial.groupCount, mi ); |
||||
|
||||
} |
||||
|
||||
if ( isLine ) { |
||||
|
||||
mesh = new THREE.LineSegments( buffergeometry, createdMaterials ); |
||||
|
||||
} else if ( isPoints ) { |
||||
|
||||
mesh = new THREE.Points( buffergeometry, createdMaterials ); |
||||
|
||||
} else { |
||||
|
||||
mesh = new THREE.Mesh( buffergeometry, createdMaterials ); |
||||
|
||||
} |
||||
|
||||
} else { |
||||
|
||||
if ( isLine ) { |
||||
|
||||
mesh = new THREE.LineSegments( buffergeometry, createdMaterials[ 0 ] ); |
||||
|
||||
} else if ( isPoints ) { |
||||
|
||||
mesh = new THREE.Points( buffergeometry, createdMaterials[ 0 ] ); |
||||
|
||||
} else { |
||||
|
||||
mesh = new THREE.Mesh( buffergeometry, createdMaterials[ 0 ] ); |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
mesh.name = object.name; |
||||
|
||||
container.add( mesh ); |
||||
|
||||
} |
||||
|
||||
console.timeEnd( 'OBJLoader' ); |
||||
|
||||
return container; |
||||
|
||||
} |
||||
|
||||
}; |
||||
|
||||
return OBJLoader; |
||||
|
||||
} )(); |
@ -0,0 +1,17 @@ |
||||
import Vue from 'vue' |
||||
import './plugins/vuetify' |
||||
import App from './App.vue' |
||||
import router from './router' |
||||
import store from './store' |
||||
import VueResource from 'vue-resource' |
||||
|
||||
Vue.config.productionTip = false |
||||
Vue.use(VueResource) |
||||
Vue.http.options.emulateJSON = true; |
||||
Vue.http.options.emulateHTTP = true; |
||||
|
||||
new Vue({ |
||||
router, |
||||
store, |
||||
render: h => h(App) |
||||
}).$mount('#app') |
@ -0,0 +1,799 @@ |
||||
|
||||
import * as THREE from "three"; |
||||
/** |
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/ |
||||
|
||||
THREE.OBJLoader = ( function () { |
||||
|
||||
// o object_name | g group_name
|
||||
var object_pattern = /^[og]\s*(.+)?/; |
||||
// mtllib file_reference
|
||||
var material_library_pattern = /^mtllib /; |
||||
// usemtl material_name
|
||||
var material_use_pattern = /^usemtl /; |
||||
|
||||
function ParserState() { |
||||
|
||||
var state = { |
||||
objects: [], |
||||
object: {}, |
||||
|
||||
vertices: [], |
||||
normals: [], |
||||
colors: [], |
||||
uvs: [], |
||||
|
||||
materialLibraries: [], |
||||
|
||||
startObject: function ( name, fromDeclaration ) { |
||||
|
||||
// If the current object (initial from reset) is not from a g/o declaration in the parsed
|
||||
// file. We need to use it for the first parsed g/o to keep things in sync.
|
||||
if ( this.object && this.object.fromDeclaration === false ) { |
||||
|
||||
this.object.name = name; |
||||
this.object.fromDeclaration = ( fromDeclaration !== false ); |
||||
return; |
||||
|
||||
} |
||||
|
||||
var previousMaterial = ( this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined ); |
||||
|
||||
if ( this.object && typeof this.object._finalize === 'function' ) { |
||||
|
||||
this.object._finalize( true ); |
||||
|
||||
} |
||||
|
||||
this.object = { |
||||
name: name || '', |
||||
fromDeclaration: ( fromDeclaration !== false ), |
||||
|
||||
geometry: { |
||||
vertices: [], |
||||
normals: [], |
||||
colors: [], |
||||
uvs: [] |
||||
}, |
||||
materials: [], |
||||
smooth: true, |
||||
|
||||
startMaterial: function ( name, libraries ) { |
||||
|
||||
var previous = this._finalize( false ); |
||||
|
||||
// New usemtl declaration overwrites an inherited material, except if faces were declared
|
||||
// after the material, then it must be preserved for proper MultiMaterial continuation.
|
||||
if ( previous && ( previous.inherited || previous.groupCount <= 0 ) ) { |
||||
|
||||
this.materials.splice( previous.index, 1 ); |
||||
|
||||
} |
||||
|
||||
var material = { |
||||
index: this.materials.length, |
||||
name: name || '', |
||||
mtllib: ( Array.isArray( libraries ) && libraries.length > 0 ? libraries[ libraries.length - 1 ] : '' ), |
||||
smooth: ( previous !== undefined ? previous.smooth : this.smooth ), |
||||
groupStart: ( previous !== undefined ? previous.groupEnd : 0 ), |
||||
groupEnd: - 1, |
||||
groupCount: - 1, |
||||
inherited: false, |
||||
|
||||
clone: function ( index ) { |
||||
|
||||
var cloned = { |
||||
index: ( typeof index === 'number' ? index : this.index ), |
||||
name: this.name, |
||||
mtllib: this.mtllib, |
||||
smooth: this.smooth, |
||||
groupStart: 0, |
||||
groupEnd: - 1, |
||||
groupCount: - 1, |
||||
inherited: false |
||||
}; |
||||
cloned.clone = this.clone.bind( cloned ); |
||||
return cloned; |
||||
|
||||
} |
||||
}; |
||||
|
||||
this.materials.push( material ); |
||||
|
||||
return material; |
||||
|
||||
}, |
||||
|
||||
currentMaterial: function () { |
||||
|
||||
if ( this.materials.length > 0 ) { |
||||
|
||||
return this.materials[ this.materials.length - 1 ]; |
||||
|
||||
} |
||||
|
||||
return undefined; |
||||
|
||||
}, |
||||
|
||||
_finalize: function ( end ) { |
||||
|
||||
var lastMultiMaterial = this.currentMaterial(); |
||||
if ( lastMultiMaterial && lastMultiMaterial.groupEnd === - 1 ) { |
||||
|
||||
lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3; |
||||
lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart; |
||||
lastMultiMaterial.inherited = false; |
||||
|
||||
} |
||||
|
||||
// Ignore objects tail materials if no face declarations followed them before a new o/g started.
|
||||
if ( end && this.materials.length > 1 ) { |
||||
|
||||
for ( var mi = this.materials.length - 1; mi >= 0; mi -- ) { |
||||
|
||||
if ( this.materials[ mi ].groupCount <= 0 ) { |
||||
|
||||
this.materials.splice( mi, 1 ); |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
// Guarantee at least one empty material, this makes the creation later more straight forward.
|
||||
if ( end && this.materials.length === 0 ) { |
||||
|
||||
this.materials.push( { |
||||
name: '', |
||||
smooth: this.smooth |
||||
} ); |
||||
|
||||
} |
||||
|
||||
return lastMultiMaterial; |
||||
|
||||
} |
||||
}; |
||||
|
||||
// Inherit previous objects material.
|
||||
// Spec tells us that a declared material must be set to all objects until a new material is declared.
|
||||
// If a usemtl declaration is encountered while this new object is being parsed, it will
|
||||
// overwrite the inherited material. Exception being that there was already face declarations
|
||||
// to the inherited material, then it will be preserved for proper MultiMaterial continuation.
|
||||
|
||||
if ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function' ) { |
||||
|
||||
var declared = previousMaterial.clone( 0 ); |
||||
declared.inherited = true; |
||||
this.object.materials.push( declared ); |
||||
|
||||
} |
||||
|
||||
this.objects.push( this.object ); |
||||
|
||||
}, |
||||
|
||||
finalize: function () { |
||||
|
||||
if ( this.object && typeof this.object._finalize === 'function' ) { |
||||
|
||||
this.object._finalize( true ); |
||||
|
||||
} |
||||
|
||||
}, |
||||
|
||||
parseVertexIndex: function ( value, len ) { |
||||
|
||||
var index = parseInt( value, 10 ); |
||||
return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; |
||||
|
||||
}, |
||||
|
||||
parseNormalIndex: function ( value, len ) { |
||||
|
||||
var index = parseInt( value, 10 ); |
||||
return ( index >= 0 ? index - 1 : index + len / 3 ) * 3; |
||||
|
||||
}, |
||||
|
||||
parseUVIndex: function ( value, len ) { |
||||
|
||||
var index = parseInt( value, 10 ); |
||||
return ( index >= 0 ? index - 1 : index + len / 2 ) * 2; |
||||
|
||||
}, |
||||
|
||||
addVertex: function ( a, b, c ) { |
||||
|
||||
var src = this.vertices; |
||||
var dst = this.object.geometry.vertices; |
||||
|
||||
dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); |
||||
dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); |
||||
dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); |
||||
|
||||
}, |
||||
|
||||
addVertexPoint: function ( a ) { |
||||
|
||||
var src = this.vertices; |
||||
var dst = this.object.geometry.vertices; |
||||
|
||||
dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); |
||||
|
||||
}, |
||||
|
||||
addVertexLine: function ( a ) { |
||||
|
||||
var src = this.vertices; |
||||
var dst = this.object.geometry.vertices; |
||||
|
||||
dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); |
||||
|
||||
}, |
||||
|
||||
addNormal: function ( a, b, c ) { |
||||
|
||||
var src = this.normals; |
||||
var dst = this.object.geometry.normals; |
||||
|
||||
dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); |
||||
dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); |
||||
dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); |
||||
|
||||
}, |
||||
|
||||
addColor: function ( a, b, c ) { |
||||
|
||||
var src = this.colors; |
||||
var dst = this.object.geometry.colors; |
||||
|
||||
dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] ); |
||||
dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] ); |
||||
dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] ); |
||||
|
||||
}, |
||||
|
||||
addUV: function ( a, b, c ) { |
||||
|
||||
var src = this.uvs; |
||||
var dst = this.object.geometry.uvs; |
||||
|
||||
dst.push( src[ a + 0 ], src[ a + 1 ] ); |
||||
dst.push( src[ b + 0 ], src[ b + 1 ] ); |
||||
dst.push( src[ c + 0 ], src[ c + 1 ] ); |
||||
|
||||
}, |
||||
|
||||
addUVLine: function ( a ) { |
||||
|
||||
var src = this.uvs; |
||||
var dst = this.object.geometry.uvs; |
||||
|
||||
dst.push( src[ a + 0 ], src[ a + 1 ] ); |
||||
|
||||
}, |
||||
|
||||
addFace: function ( a, b, c, ua, ub, uc, na, nb, nc ) { |
||||
|
||||
var vLen = this.vertices.length; |
||||
|
||||
var ia = this.parseVertexIndex( a, vLen ); |
||||
var ib = this.parseVertexIndex( b, vLen ); |
||||
var ic = this.parseVertexIndex( c, vLen ); |
||||
|
||||
this.addVertex( ia, ib, ic ); |
||||
|
||||
if ( ua !== undefined && ua !== '' ) { |
||||
|
||||
var uvLen = this.uvs.length; |
||||
ia = this.parseUVIndex( ua, uvLen ); |
||||
ib = this.parseUVIndex( ub, uvLen ); |
||||
ic = this.parseUVIndex( uc, uvLen ); |
||||
this.addUV( ia, ib, ic ); |
||||
|
||||
} |
||||
|
||||
if ( na !== undefined && na !== '' ) { |
||||
|
||||
// Normals are many times the same. If so, skip function call and parseInt.
|
||||
var nLen = this.normals.length; |
||||
ia = this.parseNormalIndex( na, nLen ); |
||||
|
||||
ib = na === nb ? ia : this.parseNormalIndex( nb, nLen ); |
||||
ic = na === nc ? ia : this.parseNormalIndex( nc, nLen ); |
||||
|
||||
this.addNormal( ia, ib, ic ); |
||||
|
||||
} |
||||
|
||||
if ( this.colors.length > 0 ) { |
||||
|
||||
this.addColor( ia, ib, ic ); |
||||
|
||||
} |
||||
|
||||
}, |
||||
|
||||
addPointGeometry: function ( vertices ) { |
||||
|
||||
this.object.geometry.type = 'Points'; |
||||
|
||||
var vLen = this.vertices.length; |
||||
|
||||
for ( var vi = 0, l = vertices.length; vi < l; vi ++ ) { |
||||
|
||||
this.addVertexPoint( this.parseVertexIndex( vertices[ vi ], vLen ) ); |
||||
|
||||
} |
||||
|
||||
}, |
||||
|
||||
addLineGeometry: function ( vertices, uvs ) { |
||||
|
||||
this.object.geometry.type = 'Line'; |
||||
|
||||
var vLen = this.vertices.length; |
||||
var uvLen = this.uvs.length; |
||||
|
||||
for ( var vi = 0, l = vertices.length; vi < l; vi ++ ) { |
||||
|
||||
this.addVertexLine( this.parseVertexIndex( vertices[ vi ], vLen ) ); |
||||
|
||||
} |
||||
|
||||
for ( var uvi = 0, l = uvs.length; uvi < l; uvi ++ ) { |
||||
|
||||
this.addUVLine( this.parseUVIndex( uvs[ uvi ], uvLen ) ); |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
}; |
||||
|
||||
state.startObject( '', false ); |
||||
|
||||
return state; |
||||
|
||||
} |
||||
|
||||
//
|
||||
|
||||
function OBJLoader( manager ) { |
||||
|
||||
this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; |
||||
|
||||
this.materials = null; |
||||
|
||||
} |
||||
|
||||
OBJLoader.prototype = { |
||||
|
||||
constructor: OBJLoader, |
||||
|
||||
load: function ( url, onLoad, onProgress, onError ) { |
||||
|
||||
var scope = this; |
||||
|
||||
var loader = new THREE.FileLoader( scope.manager ); |
||||
loader.setPath( this.path ); |
||||
loader.load( url, function ( text ) { |
||||
|
||||
onLoad( scope.parse( text ) ); |
||||
|
||||
}, onProgress, onError ); |
||||
|
||||
}, |
||||
|
||||
setPath: function ( value ) { |
||||
|
||||
this.path = value; |
||||
|
||||
return this; |
||||
|
||||
}, |
||||
|
||||
setMaterials: function ( materials ) { |
||||
|
||||
this.materials = materials; |
||||
|
||||
return this; |
||||
|
||||
}, |
||||
|
||||
parse: function ( text ) { |
||||
|
||||
console.time( 'OBJLoader' ); |
||||
|
||||
var state = new ParserState(); |
||||
|
||||
if ( text.indexOf( '\r\n' ) !== - 1 ) { |
||||
|
||||
// This is faster than String.split with regex that splits on both
|
||||
text = text.replace( /\r\n/g, '\n' ); |
||||
|
||||
} |
||||
|
||||
if ( text.indexOf( '\\\n' ) !== - 1 ) { |
||||
|
||||
// join lines separated by a line continuation character (\)
|
||||
text = text.replace( /\\\n/g, '' ); |
||||
|
||||
} |
||||
|
||||
var lines = text.split( '\n' ); |
||||
var line = '', lineFirstChar = ''; |
||||
var lineLength = 0; |
||||
var result = []; |
||||
|
||||
// Faster to just trim left side of the line. Use if available.
|
||||
var trimLeft = ( typeof ''.trimLeft === 'function' ); |
||||
|
||||
for ( var i = 0, l = lines.length; i < l; i ++ ) { |
||||
|
||||
line = lines[ i ]; |
||||
|
||||
line = trimLeft ? line.trimLeft() : line.trim(); |
||||
|
||||
lineLength = line.length; |
||||
|
||||
if ( lineLength === 0 ) continue; |
||||
|
||||
lineFirstChar = line.charAt( 0 ); |
||||
|
||||
// @todo invoke passed in handler if any
|
||||
if ( lineFirstChar === '#' ) continue; |
||||
|
||||
if ( lineFirstChar === 'v' ) { |
||||
|
||||
var data = line.split( /\s+/ ); |
||||
|
||||
switch ( data[ 0 ] ) { |
||||
|
||||
case 'v': |
||||
state.vertices.push( |
||||
parseFloat( data[ 1 ] ), |
||||
parseFloat( data[ 2 ] ), |
||||
parseFloat( data[ 3 ] ) |
||||
); |
||||
if ( data.length === 8 ) { |
||||
|
||||
state.colors.push( |
||||
parseFloat( data[ 4 ] ), |
||||
parseFloat( data[ 5 ] ), |
||||
parseFloat( data[ 6 ] ) |
||||
|
||||
); |
||||
|
||||
} |
||||
break; |
||||
case 'vn': |
||||
state.normals.push( |
||||
parseFloat( data[ 1 ] ), |
||||
parseFloat( data[ 2 ] ), |
||||
parseFloat( data[ 3 ] ) |
||||
); |
||||
break; |
||||
case 'vt': |
||||
state.uvs.push( |
||||
parseFloat( data[ 1 ] ), |
||||
parseFloat( data[ 2 ] ) |
||||
); |
||||
break; |
||||
|
||||
} |
||||
|
||||
} else if ( lineFirstChar === 'f' ) { |
||||
|
||||
var lineData = line.substr( 1 ).trim(); |
||||
var vertexData = lineData.split( /\s+/ ); |
||||
var faceVertices = []; |
||||
|
||||
// Parse the face vertex data into an easy to work with format
|
||||
|
||||
for ( var j = 0, jl = vertexData.length; j < jl; j ++ ) { |
||||
|
||||
var vertex = vertexData[ j ]; |
||||
|
||||
if ( vertex.length > 0 ) { |
||||
|
||||
var vertexParts = vertex.split( '/' ); |
||||
faceVertices.push( vertexParts ); |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
// Draw an edge between the first vertex and all subsequent vertices to form an n-gon
|
||||
|
||||
var v1 = faceVertices[ 0 ]; |
||||
|
||||
for ( var j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) { |
||||
|
||||
var v2 = faceVertices[ j ]; |
||||
var v3 = faceVertices[ j + 1 ]; |
||||
|
||||
state.addFace( |
||||
v1[ 0 ], v2[ 0 ], v3[ 0 ], |
||||
v1[ 1 ], v2[ 1 ], v3[ 1 ], |
||||
v1[ 2 ], v2[ 2 ], v3[ 2 ] |
||||
); |
||||
|
||||
} |
||||
|
||||
} else if ( lineFirstChar === 'l' ) { |
||||
|
||||
var lineParts = line.substring( 1 ).trim().split( " " ); |
||||
var lineVertices = [], lineUVs = []; |
||||
|
||||
if ( line.indexOf( "/" ) === - 1 ) { |
||||
|
||||
lineVertices = lineParts; |
||||
|
||||
} else { |
||||
|
||||
for ( var li = 0, llen = lineParts.length; li < llen; li ++ ) { |
||||
|
||||
var parts = lineParts[ li ].split( "/" ); |
||||
|
||||
if ( parts[ 0 ] !== "" ) lineVertices.push( parts[ 0 ] ); |
||||
if ( parts[ 1 ] !== "" ) lineUVs.push( parts[ 1 ] ); |
||||
|
||||
} |
||||
|
||||
} |
||||
state.addLineGeometry( lineVertices, lineUVs ); |
||||
|
||||
} else if ( lineFirstChar === 'p' ) { |
||||
|
||||
var lineData = line.substr( 1 ).trim(); |
||||
var pointData = lineData.split( " " ); |
||||
|
||||
state.addPointGeometry( pointData ); |
||||
|
||||
} else if ( ( result = object_pattern.exec( line ) ) !== null ) { |
||||
|
||||
// o object_name
|
||||
// or
|
||||
// g group_name
|
||||
|
||||
// WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869
|
||||
// var name = result[ 0 ].substr( 1 ).trim();
|
||||
var name = ( " " + result[ 0 ].substr( 1 ).trim() ).substr( 1 ); |
||||
|
||||
state.startObject( name ); |
||||
|
||||
} else if ( material_use_pattern.test( line ) ) { |
||||
|
||||
// material
|
||||
|
||||
state.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries ); |
||||
|
||||
} else if ( material_library_pattern.test( line ) ) { |
||||
|
||||
// mtl file
|
||||
|
||||
state.materialLibraries.push( line.substring( 7 ).trim() ); |
||||
|
||||
} else if ( lineFirstChar === 's' ) { |
||||
|
||||
result = line.split( ' ' ); |
||||
|
||||
// smooth shading
|
||||
|
||||
// @todo Handle files that have varying smooth values for a set of faces inside one geometry,
|
||||
// but does not define a usemtl for each face set.
|
||||
// This should be detected and a dummy material created (later MultiMaterial and geometry groups).
|
||||
// This requires some care to not create extra material on each smooth value for "normal" obj files.
|
||||
// where explicit usemtl defines geometry groups.
|
||||
// Example asset: examples/models/obj/cerberus/Cerberus.obj
|
||||
|
||||
/* |
||||
* http://paulbourke.net/dataformats/obj/
|
||||
* or |
||||
* http://www.cs.utah.edu/~boulos/cs3505/obj_spec.pdf
|
||||
* |
||||
* From chapter "Grouping" Syntax explanation "s group_number": |
||||
* "group_number is the smoothing group number. To turn off smoothing groups, use a value of 0 or off. |
||||
* Polygonal elements use group numbers to put elements in different smoothing groups. For free-form |
||||
* surfaces, smoothing groups are either turned on or off; there is no difference between values greater |
||||
* than 0." |
||||
*/ |
||||
if ( result.length > 1 ) { |
||||
|
||||
var value = result[ 1 ].trim().toLowerCase(); |
||||
state.object.smooth = ( value !== '0' && value !== 'off' ); |
||||
|
||||
} else { |
||||
|
||||
// ZBrush can produce "s" lines #11707
|
||||
state.object.smooth = true; |
||||
|
||||
} |
||||
var material = state.object.currentMaterial(); |
||||
if ( material ) material.smooth = state.object.smooth; |
||||
|
||||
} else { |
||||
|
||||
// Handle null terminated files without exception
|
||||
if ( line === '\0' ) continue; |
||||
|
||||
throw new Error( 'THREE.OBJLoader: Unexpected line: "' + line + '"' ); |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
state.finalize(); |
||||
|
||||
var container = new THREE.Group(); |
||||
container.materialLibraries = [].concat( state.materialLibraries ); |
||||
|
||||
for ( var i = 0, l = state.objects.length; i < l; i ++ ) { |
||||
|
||||
var object = state.objects[ i ]; |
||||
var geometry = object.geometry; |
||||
var materials = object.materials; |
||||
var isLine = ( geometry.type === 'Line' ); |
||||
var isPoints = ( geometry.type === 'Points' ); |
||||
var hasVertexColors = false; |
||||
|
||||
// Skip o/g line declarations that did not follow with any faces
|
||||
if ( geometry.vertices.length === 0 ) continue; |
||||
|
||||
var buffergeometry = new THREE.BufferGeometry(); |
||||
|
||||
buffergeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( geometry.vertices, 3 ) ); |
||||
|
||||
if ( geometry.normals.length > 0 ) { |
||||
|
||||
buffergeometry.addAttribute( 'normal', new THREE.Float32BufferAttribute( geometry.normals, 3 ) ); |
||||
|
||||
} else { |
||||
|
||||
buffergeometry.computeVertexNormals(); |
||||
|
||||
} |
||||
|
||||
if ( geometry.colors.length > 0 ) { |
||||
|
||||
hasVertexColors = true; |
||||
buffergeometry.addAttribute( 'color', new THREE.Float32BufferAttribute( geometry.colors, 3 ) ); |
||||
|
||||
} |
||||
|
||||
if ( geometry.uvs.length > 0 ) { |
||||
|
||||
buffergeometry.addAttribute( 'uv', new THREE.Float32BufferAttribute( geometry.uvs, 2 ) ); |
||||
|
||||
} |
||||
|
||||
// Create materials
|
||||
|
||||
var createdMaterials = []; |
||||
|
||||
for ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { |
||||
|
||||
var sourceMaterial = materials[ mi ]; |
||||
var material = undefined; |
||||
|
||||
if ( this.materials !== null ) { |
||||
|
||||
material = this.materials.create( sourceMaterial.name ); |
||||
|
||||
// mtl etc. loaders probably can't create line materials correctly, copy properties to a line material.
|
||||
if ( isLine && material && ! ( material instanceof THREE.LineBasicMaterial ) ) { |
||||
|
||||
var materialLine = new THREE.LineBasicMaterial(); |
||||
THREE.Material.prototype.copy.call( materialLine, material ); |
||||
materialLine.color.copy( material.color ); |
||||
materialLine.lights = false; |
||||
material = materialLine; |
||||
|
||||
} else if ( isPoints && material && ! ( material instanceof THREE.PointsMaterial ) ) { |
||||
|
||||
var materialPoints = new THREE.PointsMaterial( { size: 10, sizeAttenuation: false } ); |
||||
THREE.Material.prototype.copy.call( materialPoints, material ); |
||||
materialPoints.color.copy( material.color ); |
||||
materialPoints.map = material.map; |
||||
materialPoints.lights = false; |
||||
material = materialPoints; |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
if ( ! material ) { |
||||
|
||||
if ( isLine ) { |
||||
|
||||
material = new THREE.LineBasicMaterial(); |
||||
|
||||
} else if ( isPoints ) { |
||||
|
||||
material = new THREE.PointsMaterial( { size: 1, sizeAttenuation: false } ); |
||||
|
||||
} else { |
||||
|
||||
material = new THREE.MeshPhongMaterial(); |
||||
|
||||
} |
||||
|
||||
material.name = sourceMaterial.name; |
||||
|
||||
} |
||||
|
||||
material.flatShading = sourceMaterial.smooth ? false : true; |
||||
material.vertexColors = hasVertexColors ? THREE.VertexColors : THREE.NoColors; |
||||
|
||||
createdMaterials.push( material ); |
||||
|
||||
} |
||||
|
||||
// Create mesh
|
||||
|
||||
var mesh; |
||||
|
||||
if ( createdMaterials.length > 1 ) { |
||||
|
||||
for ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) { |
||||
|
||||
var sourceMaterial = materials[ mi ]; |
||||
buffergeometry.addGroup( sourceMaterial.groupStart, sourceMaterial.groupCount, mi ); |
||||
|
||||
} |
||||
|
||||
if ( isLine ) { |
||||
|
||||
mesh = new THREE.LineSegments( buffergeometry, createdMaterials ); |
||||
|
||||
} else if ( isPoints ) { |
||||
|
||||
mesh = new THREE.Points( buffergeometry, createdMaterials ); |
||||
|
||||
} else { |
||||
|
||||
mesh = new THREE.Mesh( buffergeometry, createdMaterials ); |
||||
|
||||
} |
||||
|
||||
} else { |
||||
|
||||
if ( isLine ) { |
||||
|
||||
mesh = new THREE.LineSegments( buffergeometry, createdMaterials[ 0 ] ); |
||||
|
||||
} else if ( isPoints ) { |
||||
|
||||
mesh = new THREE.Points( buffergeometry, createdMaterials[ 0 ] ); |
||||
|
||||
} else { |
||||
|
||||
mesh = new THREE.Mesh( buffergeometry, createdMaterials[ 0 ] ); |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
mesh.name = object.name; |
||||
|
||||
container.add( mesh ); |
||||
|
||||
} |
||||
|
||||
console.timeEnd( 'OBJLoader' ); |
||||
|
||||
return container; |
||||
|
||||
} |
||||
|
||||
}; |
||||
|
||||
return OBJLoader; |
||||
|
||||
} )(); |
@ -0,0 +1,7 @@ |
||||
import Vue from 'vue' |
||||
import Vuetify from 'vuetify/lib' |
||||
import 'vuetify/src/stylus/app.styl' |
||||
|
||||
Vue.use(Vuetify, { |
||||
iconfont: 'md', |
||||
}) |
@ -0,0 +1,36 @@ |
||||
import Vue from 'vue' |
||||
import Router from 'vue-router' |
||||
import Home from './views/Home.vue' |
||||
import Login from './views/Login' |
||||
import Create from './views/Create' |
||||
import Show from './views/Show' |
||||
import Refuse from './views/Refuse' |
||||
|
||||
Vue.use(Router) |
||||
|
||||
export default new Router({ |
||||
routes: [ |
||||
{ |
||||
path: '/', |
||||
component: Login |
||||
}, |
||||
{ |
||||
path: '/home', |
||||
component: Home |
||||
}, |
||||
{ |
||||
path: '/create/:sid', |
||||
component: Create, |
||||
props: true |
||||
}, |
||||
{ |
||||
path: '/show/:sid', |
||||
component: Show, |
||||
props: true |
||||
}, |
||||
{ |
||||
path: '/refuse', |
||||
component: Refuse |
||||
}, |
||||
] |
||||
}) |
@ -0,0 +1,16 @@ |
||||
import Vue from 'vue' |
||||
import Vuex from 'vuex' |
||||
|
||||
Vue.use(Vuex) |
||||
|
||||
export default new Vuex.Store({ |
||||
state: { |
||||
|
||||
}, |
||||
mutations: { |
||||
|
||||
}, |
||||
actions: { |
||||
|
||||
} |
||||
}) |
@ -0,0 +1,841 @@ |
||||
<template> |
||||
<v-app dark id="keep"> |
||||
<!-- 侧边栏开始 --> |
||||
<v-navigation-drawer v-model="mainDrawer" absolute fixed clipped app> |
||||
<v-list dense> |
||||
<v-layout row align-center> |
||||
<v-flex xs6> |
||||
<v-subheader>所有部件</v-subheader> |
||||
</v-flex> |
||||
<v-flex xs6 class="text-xs-right"> |
||||
<v-btn small flat @click="componentDialog=true">编辑</v-btn> |
||||
</v-flex> |
||||
</v-layout> |
||||
<!-- 部件列表开始 --> |
||||
<v-list-group v-for="(item,index) in componentsInfo" :key="index"> |
||||
<template v-slot:activator> |
||||
<v-list-tile> |
||||
<v-list-tile-content> |
||||
<v-list-tile-title>{{ item.componentName }}</v-list-tile-title> |
||||
</v-list-tile-content> |
||||
</v-list-tile> |
||||
</template> |
||||
<v-list-tile |
||||
color="amber lighten-1" |
||||
v-for="(subItem,subIndex) in item.models" |
||||
:key="subItem.fid" |
||||
@click="modelChange(index,subIndex)" |
||||
> |
||||
<v-list-tile-content> |
||||
<v-list-tile-title> |
||||
{{ subItem.name }} |
||||
<v-icon small v-if="subIndex==item.modelSelected">arrow_left</v-icon> |
||||
</v-list-tile-title> |
||||
</v-list-tile-content> |
||||
</v-list-tile> |
||||
<v-divider/> |
||||
<v-container grid-list-sm fluid v-if="item.textures.length>0"> |
||||
<v-layout row wrap> |
||||
<v-flex v-for="(subItem,subIndex) in item.textures" :key="subItem.fid" xs2 d-flex> |
||||
<v-card flat tile class="d-flex" @click="textureChange(index,subIndex)"> |
||||
<v-img :src="subItem.path+'?size=60'" aspect-ratio="1" class="grey lighten-2"> |
||||
<template v-slot:placeholder> |
||||
<v-layout fill-height align-center justify-center ma-0> |
||||
<v-progress-circular indeterminate color="grey lighten-5"></v-progress-circular> |
||||
</v-layout> |
||||
</template> |
||||
</v-img> |
||||
</v-card> |
||||
</v-flex> |
||||
</v-layout> |
||||
</v-container> |
||||
<v-list-tile @click="componentIndex=index;waitUploadList=[];uploadDrawer = true"> |
||||
<v-list-tile-action> |
||||
<v-icon>cloud_upload</v-icon> |
||||
</v-list-tile-action> |
||||
<v-list-tile-content> |
||||
<v-list-tile-title>上传模型文件</v-list-tile-title> |
||||
</v-list-tile-content> |
||||
</v-list-tile> |
||||
<v-list-tile @click="componentIndex=index;textureDialog=true"> |
||||
<v-list-tile-action> |
||||
<v-icon>picture_in_picture</v-icon> |
||||
</v-list-tile-action> |
||||
<v-list-tile-content> |
||||
<v-list-tile-title>贴图文件管理</v-list-tile-title> |
||||
</v-list-tile-content> |
||||
</v-list-tile> |
||||
</v-list-group> |
||||
<!-- 部件列表结束 --> |
||||
<v-list-tile @click="addComponentDialog=true"> |
||||
<v-list-tile-action> |
||||
<v-icon>add</v-icon> |
||||
</v-list-tile-action> |
||||
<v-list-tile-content> |
||||
<v-list-tile-title>添加新部件</v-list-tile-title> |
||||
</v-list-tile-content> |
||||
</v-list-tile> |
||||
</v-list> |
||||
<!-- 相机参数 --> |
||||
<v-list two-line> |
||||
<v-list-tile> |
||||
<v-layout row> |
||||
<v-flex class="pr-3"> |
||||
<v-slider |
||||
label="相机高度" |
||||
v-model="cameraControll.height" |
||||
:max="cameraControll.heightMax" |
||||
min="0" |
||||
></v-slider> |
||||
</v-flex> |
||||
</v-layout> |
||||
</v-list-tile> |
||||
<v-list-tile> |
||||
<v-layout row> |
||||
<v-flex class="pr-3"> |
||||
<v-slider |
||||
label="相机距离" |
||||
v-model="cameraControll.distance" |
||||
:max="cameraControll.distanceMax" |
||||
min="0" |
||||
></v-slider> |
||||
</v-flex> |
||||
</v-layout> |
||||
</v-list-tile> |
||||
<v-list-tile> |
||||
<v-layout row> |
||||
<v-flex class="pr-3"> |
||||
<v-slider |
||||
label="贴图缩放" |
||||
v-model="cameraControll.textureSize" |
||||
max="100" |
||||
min="1" |
||||
></v-slider> |
||||
</v-flex> |
||||
</v-layout> |
||||
</v-list-tile> |
||||
</v-list> |
||||
</v-navigation-drawer> |
||||
<!-- 侧边栏结束 --> |
||||
<!-- 工具栏开始 --> |
||||
<v-toolbar dark color="red" app clipped-left> |
||||
<v-toolbar-side-icon @click="mainDrawer = !mainDrawer"></v-toolbar-side-icon> |
||||
<span class="title ml-3 mr-5"> |
||||
V3D |
||||
<span class="font-weight-light">创建方案</span> |
||||
</span> |
||||
<v-spacer/> |
||||
<v-text-field v-model="name" solo-inverted flat hide-details class="hidden-sm-and-down"></v-text-field> |
||||
<v-spacer/> |
||||
<v-toolbar-items> |
||||
<v-btn icon> |
||||
<v-icon @click="settingDialog=true">settings</v-icon> |
||||
</v-btn> |
||||
<v-btn icon> |
||||
<v-icon @click="refresh">refresh</v-icon> |
||||
</v-btn> |
||||
<v-tooltip bottom> |
||||
<template v-slot:activator="{ on }"> |
||||
<v-btn icon v-on="on" @click="saveScheme"> |
||||
<v-icon>save</v-icon> |
||||
</v-btn> |
||||
</template> |
||||
<span>保存方案</span> |
||||
</v-tooltip> |
||||
<v-btn icon @click="exitDialog = true"> |
||||
<v-icon>exit_to_app</v-icon> |
||||
</v-btn> |
||||
</v-toolbar-items> |
||||
</v-toolbar> |
||||
<!-- 工具栏结束 --> |
||||
<!-- 诡异的样式问题 --> |
||||
<v-content style="height:0px;background-color:#ddd"> |
||||
<ThreeStage |
||||
:components-info="componentsInfo" |
||||
:camera-controll="cameraControll" |
||||
ref="threeStage" |
||||
/> |
||||
</v-content> |
||||
<!-- 右侧drawer开始 --> |
||||
<v-navigation-drawer v-model="uploadDrawer" right temporary fixed> |
||||
<input |
||||
type="file" |
||||
multiple="multiple" |
||||
ref="file" |
||||
style="display:none" |
||||
accept=".fbx, .obj" |
||||
@change="fileChange" |
||||
> |
||||
<v-list> |
||||
<v-subheader |
||||
v-if="componentsInfo[componentIndex]" |
||||
>{{componentsInfo[componentIndex].componentName}} - 待上传文件</v-subheader> |
||||
<div v-for="(item,index) in waitUploadList" :key="index"> |
||||
<v-list-tile> |
||||
<v-list-tile-content> |
||||
<v-list-tile-title v-text="item.name"></v-list-tile-title> |
||||
<v-list-tile-sub-title>{{item.size|fileSize}}</v-list-tile-sub-title> |
||||
</v-list-tile-content> |
||||
<v-list-tile-action> |
||||
<v-btn icon ripple @click="waitUploadList.splice(index, 1)"> |
||||
<v-icon color="grey lighten-1">cancel</v-icon> |
||||
</v-btn> |
||||
</v-list-tile-action> |
||||
</v-list-tile> |
||||
<v-divider></v-divider> |
||||
</div> |
||||
<v-list-tile> |
||||
<v-list-tile-content> |
||||
<v-btn block dark color="blue" @click="$refs.file.click()"> |
||||
选择文件 |
||||
<v-icon right dark>folder_open</v-icon> |
||||
</v-btn> |
||||
</v-list-tile-content> |
||||
</v-list-tile> |
||||
<v-list-tile> |
||||
<v-list-tile-content> |
||||
<v-btn block dark color="red" @click="uploadModel"> |
||||
开始上传 |
||||
<v-icon right dark>cloud_upload</v-icon> |
||||
</v-btn> |
||||
</v-list-tile-content> |
||||
</v-list-tile> |
||||
</v-list> |
||||
</v-navigation-drawer> |
||||
<!-- 右侧drawer结束 --> |
||||
<!-- 贴图管理 开始 --> |
||||
<v-dialog v-model="textureDialog" persistent max-width="600px"> |
||||
<input |
||||
type="file" |
||||
multiple="multiple" |
||||
ref="textureFile" |
||||
style="display:none" |
||||
accept=".jpg, .png" |
||||
@change="textureFileChange" |
||||
> |
||||
<v-card light> |
||||
<v-card-title> |
||||
<span |
||||
class="headline" |
||||
v-if="componentsInfo[componentIndex]" |
||||
>{{componentsInfo[componentIndex].componentName}} - 贴图管理</span> |
||||
</v-card-title> |
||||
<v-card-text> |
||||
<v-container grid-list-sm fluid v-if="componentsInfo[componentIndex]"> |
||||
<v-layout row wrap> |
||||
<v-flex |
||||
v-for="(item,index) in componentsInfo[componentIndex].textures" |
||||
:key="item.name" |
||||
xs1 |
||||
d-flex |
||||
@click="delTexture(componentIndex,index)" |
||||
> |
||||
<v-card flat tile class="d-flex elevation-1"> |
||||
<v-img :src="item.path+'?size=40'" aspect-ratio="1" class="grey lighten-2"> |
||||
<template v-slot:placeholder> |
||||
<v-layout fill-height align-center justify-center ma-0> |
||||
<v-progress-circular indeterminate color="grey lighten-5"></v-progress-circular> |
||||
</v-layout> |
||||
</template> |
||||
</v-img> |
||||
</v-card> |
||||
</v-flex> |
||||
</v-layout> |
||||
</v-container> |
||||
<small style="display:block;text-align:right;color:#aaa" class="pr-4">*单击可删除贴图</small> |
||||
</v-card-text> |
||||
<v-card-actions> |
||||
<v-btn color="blue" flat @click="$refs.textureFile.click()">添加贴图</v-btn> |
||||
<v-spacer></v-spacer> |
||||
<v-btn color="red" flat @click="textureDialog = false">确定</v-btn> |
||||
</v-card-actions> |
||||
</v-card> |
||||
</v-dialog> |
||||
<!-- 贴图管理 结束 --> |
||||
<!-- 部件管理 开始 --> |
||||
<v-dialog v-model="componentDialog" max-width="600px"> |
||||
<v-card light> |
||||
<v-card-text> |
||||
<v-tabs v-model="tabActive" color="red" dark slider-color="yellow"> |
||||
<v-tab v-for="(item,index) in componentsInfo" :key="index" ripple>{{item.componentName}}</v-tab> |
||||
<v-tab-item v-for="(item,index) in componentsInfo" :key="index"> |
||||
<v-card flat> |
||||
<v-card-text> |
||||
<v-list> |
||||
<div v-for="(subItem,subIndex) in item.models" :key="subItem.fid"> |
||||
<v-list-tile> |
||||
<v-list-tile-content> |
||||
<v-text-field |
||||
v-model="componentsInfo[index].models[subIndex].name" |
||||
single-line |
||||
full-width |
||||
hide-details |
||||
></v-text-field> |
||||
</v-list-tile-content> |
||||
<v-list-tile-content class="align-end"> |
||||
<v-btn icon ripple @click="delModel(index, subIndex)"> |
||||
<v-icon color="grey lighten-1">cancel</v-icon> |
||||
</v-btn> |
||||
</v-list-tile-content> |
||||
</v-list-tile> |
||||
<v-divider/> |
||||
</div> |
||||
</v-list> |
||||
</v-card-text> |
||||
</v-card> |
||||
<div class="text-xs-center"> |
||||
<v-btn round color="primary" outline @click="delComponent(index)">删除该部件</v-btn> |
||||
</div> |
||||
</v-tab-item> |
||||
</v-tabs> |
||||
</v-card-text> |
||||
<v-card-actions> |
||||
<v-spacer></v-spacer> |
||||
<v-btn |
||||
color="red" |
||||
flat |
||||
@click="componentDialog = false" |
||||
item-text="componentName" |
||||
item-children="models" |
||||
>确定</v-btn> |
||||
</v-card-actions> |
||||
</v-card> |
||||
</v-dialog> |
||||
<!-- 部件管理 结束 --> |
||||
<!-- 添加部件模态框 开始--> |
||||
<v-dialog v-model="addComponentDialog" width="500"> |
||||
<v-card> |
||||
<v-toolbar dark color="red"> |
||||
<v-toolbar-title>添加新部件</v-toolbar-title> |
||||
<v-spacer></v-spacer> |
||||
<v-btn icon dark @click="addComponentDialog = false"> |
||||
<v-icon>close</v-icon> |
||||
</v-btn> |
||||
</v-toolbar> |
||||
<v-card-text> |
||||
<v-text-field label="部件名称" color="red" v-model="componentName"></v-text-field> |
||||
</v-card-text> |
||||
<v-divider></v-divider> |
||||
<v-card-actions> |
||||
<v-spacer></v-spacer> |
||||
<v-btn dark flat @click="addComponent">添加</v-btn> |
||||
</v-card-actions> |
||||
</v-card> |
||||
</v-dialog> |
||||
<!-- 添加部件模态框 结束 --> |
||||
<!-- 文件上传进度模态框 开始 --> |
||||
<v-dialog v-model="uploadingDialog" persistent width="300"> |
||||
<v-card color="red" dark> |
||||
<v-card-text> |
||||
文件上传中 |
||||
<v-progress-linear indeterminate color="white" class="mb-0"></v-progress-linear> |
||||
</v-card-text> |
||||
</v-card> |
||||
</v-dialog> |
||||
<!-- 文件上传进度模态框 结束--> |
||||
<!-- 文件加载进度模态框 开始 --> |
||||
<v-dialog v-model="downloadingDialog" persistent width="300"> |
||||
<v-card color="red" dark> |
||||
<v-card-text> |
||||
文件加载中 |
||||
<v-progress-linear indeterminate color="white" class="mb-0"></v-progress-linear> |
||||
</v-card-text> |
||||
</v-card> |
||||
</v-dialog> |
||||
<!-- 文件加载进度模态框 结束--> |
||||
<!-- 退出保存模态框 开始 --> |
||||
<v-dialog v-model="exitDialog" width="300"> |
||||
<v-card> |
||||
<v-card-text>是否保存当前修改?</v-card-text> |
||||
<v-card-actions> |
||||
<v-spacer></v-spacer> |
||||
<v-btn flat @click="$router.push('/home')">直接退出</v-btn> |
||||
<v-btn flat @click="saveScheme();$router.push('/home')">保存退出</v-btn> |
||||
</v-card-actions> |
||||
</v-card> |
||||
</v-dialog> |
||||
<!-- 退出保存模态框 结束 --> |
||||
<!-- 设置开始 --> |
||||
<v-dialog v-model="settingDialog" fullscreen hide-overlay transition="dialog-bottom-transition"> |
||||
<v-card light> |
||||
<v-toolbar dark color="primary"> |
||||
<v-btn icon dark @click="settingDialog = false"> |
||||
<v-icon>close</v-icon> |
||||
</v-btn> |
||||
<v-toolbar-title>设置</v-toolbar-title> |
||||
<v-spacer></v-spacer> |
||||
<v-toolbar-items> |
||||
<v-btn dark flat @click="saveSetting">确定</v-btn> |
||||
</v-toolbar-items> |
||||
</v-toolbar> |
||||
<v-list three-line subheader> |
||||
<v-subheader>相机参数</v-subheader> |
||||
<v-list-tile avatar> |
||||
<v-list-tile-content> |
||||
<v-list-tile-title>相机最大高度</v-list-tile-title> |
||||
<v-list-tile-sub-title> |
||||
<v-flex shrink style="width: 60px"> |
||||
<v-text-field |
||||
v-model="cameraControll.heightMax" |
||||
class="mt-0" |
||||
hide-details |
||||
single-line |
||||
type="number" |
||||
></v-text-field> |
||||
</v-flex> |
||||
</v-list-tile-sub-title> |
||||
</v-list-tile-content> |
||||
</v-list-tile> |
||||
<v-list-tile avatar> |
||||
<v-list-tile-content> |
||||
<v-list-tile-title>相机最远距离</v-list-tile-title> |
||||
<v-list-tile-sub-title> |
||||
<v-flex shrink style="width: 60px"> |
||||
<v-text-field |
||||
v-model="cameraControll.distanceMax" |
||||
class="mt-0" |
||||
hide-details |
||||
single-line |
||||
type="number" |
||||
></v-text-field> |
||||
</v-flex> |
||||
</v-list-tile-sub-title> |
||||
</v-list-tile-content> |
||||
</v-list-tile> |
||||
<v-divider></v-divider> |
||||
<v-subheader>方案分享</v-subheader> |
||||
<v-layout wrap class="ma-3"> |
||||
<v-flex xs12 sm8 class="pr-5"> |
||||
<v-switch label="开启分享" color="red" v-model="isShared"></v-switch> |
||||
<v-text-field label="访问地址" outline readonly :value="shareLink"></v-text-field> |
||||
<input :value="shareLink" ref="shareLink" style="display:none"> |
||||
<input |
||||
:value="`<iframe src='${shareLink}' scrolling='no' frameborder='0' width='100%' height='100%'></iframe>`" |
||||
ref="iframLink" |
||||
style="display:none" |
||||
> |
||||
<v-switch label="使用密码" color="red" v-model="hasPassword"></v-switch> |
||||
<v-text-field |
||||
v-model="sharePassword" |
||||
label="访问密码" |
||||
:type="hasPassword&&showPassword ? 'text' : 'password'" |
||||
:disabled="!hasPassword" |
||||
:append-icon="hasPassword&&showPassword? 'visibility' : 'visibility_off'" |
||||
@click:append="showPassword = !showPassword" |
||||
></v-text-field> |
||||
</v-flex> |
||||
<v-flex xs12 sm4> |
||||
<v-layout justify-end fill-height> |
||||
<v-flex align-self-end> |
||||
<canvas ref="qr"></canvas> |
||||
</v-flex> |
||||
<v-spacer/> |
||||
<v-layout column justify-end class="mb-3"> |
||||
<a style="text-align:right" class="ma-2"> |
||||
关于IFrames地址的使用 |
||||
<v-icon small>help</v-icon> |
||||
</a> |
||||
<v-btn color="blue" dark @click="copyIframe">iframe地址</v-btn> |
||||
<v-btn color="blue" dark @click="copyLink">复制访问地址</v-btn> |
||||
<v-btn color="green" dark @click="saveQR">保存二维码</v-btn> |
||||
</v-layout> |
||||
</v-layout> |
||||
</v-flex> |
||||
</v-layout> |
||||
</v-list> |
||||
</v-card> |
||||
</v-dialog> |
||||
<!-- 设置结束 --> |
||||
</v-app> |
||||
</template> |
||||
<script> |
||||
import "../plugins/OBJLoader"; |
||||
import "../plugins/FBXLoader"; |
||||
import { |
||||
LoadingManager, |
||||
TextureLoader, |
||||
OBJLoader, |
||||
FBXLoader, |
||||
DoubleSide |
||||
} from "three"; |
||||
import ThreeStage from "../components/ThreeStage"; |
||||
import QRious from "qrious"; |
||||
|
||||
export default { |
||||
components: { |
||||
ThreeStage |
||||
}, |
||||
props: ["sid"], |
||||
data: () => ({ |
||||
//tab |
||||
tabActive: null, |
||||
//drawer |
||||
mainDrawer: false, |
||||
uploadDrawer: false, |
||||
//dialog |
||||
addComponentDialog: null, |
||||
uploadingDialog: null, |
||||
downloadingDialog: null, |
||||
exitDialog: null, |
||||
textureDialog: null, |
||||
settingDialog: null, |
||||
componentDialog: null, |
||||
//方案临时数据 |
||||
componentIndex: null, |
||||
componentName: "", |
||||
waitUploadList: [], |
||||
//方案保存数据 |
||||
name: "", |
||||
cameraControll: { |
||||
height: 10, |
||||
distance: 40, |
||||
textureSize:1, |
||||
heightMax: 200, |
||||
distanceMax: 200 |
||||
}, |
||||
componentsInfo: [], |
||||
//share |
||||
shareLink: "", |
||||
isShared: false, |
||||
hasPassword: false, |
||||
showPassword: false, |
||||
sharePassword: "" |
||||
}), |
||||
watch: { |
||||
//当创建dialog退出时候清空文本栏 |
||||
addComponentDialog() { |
||||
this.componentName = ""; |
||||
} |
||||
}, |
||||
filters: { |
||||
fileSize: function(value) { |
||||
return (value / 1024 / 1024).toFixed(2) + " MB"; |
||||
} |
||||
}, |
||||
methods: { |
||||
saveSetting() { |
||||
let share = 0; |
||||
if (this.isShared) { |
||||
if (this.hasPassword) { |
||||
share = 2; |
||||
} else { |
||||
share = 1; |
||||
} |
||||
} |
||||
this.$http |
||||
.post( |
||||
"/scheme/share", |
||||
{ |
||||
sid: this.sid, |
||||
share: share, |
||||
password: this.sharePassword |
||||
}, |
||||
{} |
||||
) |
||||
.then( |
||||
data => { |
||||
console.info(data); |
||||
}, |
||||
error => { |
||||
console.info(error); |
||||
} |
||||
); |
||||
this.settingDialog = false; |
||||
}, |
||||
copyLink() { |
||||
this.$refs.shareLink.style.display = "inline"; |
||||
this.$refs.shareLink.select(); |
||||
document.execCommand("Copy"); |
||||
this.$refs.shareLink.style.display = "none"; |
||||
}, |
||||
copyIframe() { |
||||
this.$refs.iframLink.style.display = "inline"; |
||||
this.$refs.iframLink.select(); |
||||
document.execCommand("Copy"); |
||||
this.$refs.iframLink.style.display = "none"; |
||||
}, |
||||
saveQR() { |
||||
let a = document.createElement("a"); |
||||
a.href = this.$refs.qr.toDataURL("image/png"); |
||||
a.download = "qr.png"; |
||||
let event = document.createEvent("MouseEvents"); |
||||
event.initEvent("click", true, false); |
||||
a.dispatchEvent(event); |
||||
}, |
||||
addComponent() { |
||||
let componentName = this.componentName.replace(/\s+/g, ""); |
||||
if (componentName.length > 0) |
||||
this.componentsInfo.push({ |
||||
componentName, |
||||
modelSelected: -1, |
||||
textureSelected: -1, |
||||
models: [], |
||||
textures: [] |
||||
}); |
||||
this.addComponentDialog = false; |
||||
}, |
||||
fileChange() { |
||||
for (var i = 0, j = this.$refs.file.files.length; i < j; i++) { |
||||
this.waitUploadList.push(this.$refs.file.files[i]); |
||||
} |
||||
//重置file input |
||||
this.$refs.file.value = ""; |
||||
}, |
||||
textureFileChange() { |
||||
if (this.$refs.textureFile.files.length > 0) { |
||||
this.uploadingDialog = true; |
||||
var formData = new FormData(); |
||||
formData.append("sid", this.sid); |
||||
for (var i = 0, j = this.$refs.textureFile.files.length; i < j; i++) { |
||||
formData.append("files", this.$refs.textureFile.files[i]); |
||||
} |
||||
this.$http |
||||
.post("/file/uploadTexture", formData, { |
||||
headers: { "Content-Type": "multipart/form-data" } |
||||
}) |
||||
.then( |
||||
data => { |
||||
console.info(data); |
||||
if (data.body.code == 0) { |
||||
data.body.data.uploadReply.map(item => { |
||||
this.componentsInfo[this.componentIndex].textures.push(item); |
||||
}); |
||||
} |
||||
this.uploadingDialog = false; |
||||
}, |
||||
error => { |
||||
console.info(error); |
||||
} |
||||
); |
||||
//重置file input |
||||
this.$refs.textureFile.value = ""; |
||||
} |
||||
}, |
||||
uploadModel() { |
||||
if (this.waitUploadList.length > 0) { |
||||
this.uploadDrawer = false; |
||||
this.uploadingDialog = true; |
||||
var formData = new FormData(); |
||||
formData.append("sid", this.sid); |
||||
this.waitUploadList.map(item => { |
||||
formData.append("files", item); |
||||
}); |
||||
this.$http |
||||
.post("/file/uploadModel", formData, { |
||||
headers: { "Content-Type": "multipart/form-data" } |
||||
}) |
||||
.then( |
||||
data => { |
||||
console.info(data); |
||||
if (data.body.code == 0) { |
||||
data.body.data.uploadReply.map(item => { |
||||
this.componentsInfo[this.componentIndex].models.push(item); |
||||
}); |
||||
} |
||||
this.uploadingDialog = false; |
||||
}, |
||||
error => { |
||||
console.info(error); |
||||
} |
||||
); |
||||
} |
||||
}, |
||||
refresh() { |
||||
this.$http.get("/scheme/" + this.sid, {}, {}).then( |
||||
data => { |
||||
console.info(data); |
||||
if (data.body.code == 0) { |
||||
this.name = data.body.data.name; |
||||
this.shareLink = data.body.data.shareLink; |
||||
this.sharePassword = data.body.data.password; |
||||
var qr = new QRious({ |
||||
element: this.$refs.qr, |
||||
size: 250, |
||||
level: "L", |
||||
foreground: "#424242", |
||||
background: "#fff", |
||||
value: this.shareLink |
||||
}); |
||||
switch (data.body.data.share) { |
||||
case 0: |
||||
this.isShared = false; |
||||
this.hasPassword = false; |
||||
break; |
||||
case 1: |
||||
this.isShared = true; |
||||
this.hasPassword = false; |
||||
break; |
||||
case 2: |
||||
this.isShared = true; |
||||
this.hasPassword = true; |
||||
break; |
||||
} |
||||
let componentsInfo = JSON.parse(data.body.data.data); |
||||
let cameraControll = JSON.parse(data.body.data.camera); |
||||
if (componentsInfo) this.componentsInfo = componentsInfo; |
||||
if (cameraControll) this.cameraControll = cameraControll; |
||||
let manager = new LoadingManager(() => { |
||||
this.downloadingDialog = false; |
||||
}); |
||||
this.componentsInfo.map((item, index) => { |
||||
let modelIndex = item.modelSelected; |
||||
let textureIndex = item.textureSelected; |
||||
|
||||
if (item.models[modelIndex] != null) { |
||||
this.downloadingDialog = true; |
||||
this.modelChange(index, modelIndex, manager); |
||||
} |
||||
if (item.textures[textureIndex] != null) { |
||||
this.downloadingDialog = true; |
||||
this.textureChange(index, textureIndex, manager); |
||||
} |
||||
}); |
||||
} else if (data.body.code == 2) { |
||||
this.$router.push("/"); |
||||
} else { |
||||
this.$router.push("/home"); |
||||
} |
||||
}, |
||||
error => { |
||||
console.info(error); |
||||
} |
||||
); |
||||
}, |
||||
saveScheme() { |
||||
var formData = new FormData(); |
||||
formData.append("sid", this.sid); |
||||
formData.append("name", this.name); |
||||
formData.append("file", this.$refs.threeStage.getCover()); |
||||
//清空缓存的obj |
||||
formData.append( |
||||
"data", |
||||
JSON.stringify(this.componentsInfo, (key, value) => { |
||||
if (key == "obj") { |
||||
return null; |
||||
} else { |
||||
return value; |
||||
} |
||||
}) |
||||
); |
||||
formData.append("camera", JSON.stringify(this.cameraControll)); |
||||
this.$http |
||||
.post("/scheme/save", formData, { |
||||
headers: { "Content-Type": "multipart/form-data" } |
||||
}) |
||||
.then( |
||||
data => { |
||||
console.info(data); |
||||
}, |
||||
error => { |
||||
console.info(error); |
||||
} |
||||
); |
||||
}, |
||||
modelChange(componentIndex, modelIndex, manager) { |
||||
if (manager == null) { |
||||
this.downloadingDialog = true; |
||||
manager = new LoadingManager(() => { |
||||
this.downloadingDialog = false; |
||||
}); |
||||
} |
||||
let model = this.componentsInfo[componentIndex].models[modelIndex]; |
||||
if (model.obj == null) { |
||||
//obj |
||||
if ( |
||||
model.path |
||||
.split(".") |
||||
.pop() |
||||
.toLowerCase() === "obj" |
||||
) { |
||||
new OBJLoader(manager).load( |
||||
model.path, |
||||
//success回调 |
||||
obj => { |
||||
obj.traverse(child => { |
||||
if (child.isMesh) { |
||||
child.material.side = DoubleSide; |
||||
} |
||||
}); |
||||
model.obj = obj; |
||||
this.componentsInfo[componentIndex].modelSelected = modelIndex; |
||||
this.$refs.threeStage.updateScene(); |
||||
} |
||||
); |
||||
//fbx |
||||
} else if ( |
||||
model.path |
||||
.split(".") |
||||
.pop() |
||||
.toLowerCase() === "fbx" |
||||
) { |
||||
new FBXLoader(manager).load( |
||||
model.path, |
||||
obj => { |
||||
obj.traverse(child => { |
||||
if (child.isMesh) { |
||||
child.material.side = DoubleSide; |
||||
} |
||||
}); |
||||
model.obj = obj; |
||||
this.componentsInfo[componentIndex].modelSelected = modelIndex; |
||||
this.$refs.threeStage.updateScene(); |
||||
}, |
||||
xhr => { |
||||
if (xhr.lengthComputable) { |
||||
// console.info((xhr.loaded / xhr.total) * 100); |
||||
} |
||||
} |
||||
); |
||||
} |
||||
} else { |
||||
this.componentsInfo[componentIndex].modelSelected = modelIndex; |
||||
this.$refs.threeStage.updateScene(); |
||||
this.downloadingDialog = false; |
||||
} |
||||
}, |
||||
textureChange(componentIndex, textureIndex, manager) { |
||||
if (manager == null) { |
||||
this.downloadingDialog = true; |
||||
manager = new LoadingManager(() => { |
||||
this.downloadingDialog = false; |
||||
}); |
||||
} |
||||
let texture = this.componentsInfo[componentIndex].textures[textureIndex]; |
||||
if (texture.obj == null) { |
||||
new TextureLoader(manager).load(texture.path, obj => { |
||||
texture.obj = obj; |
||||
this.componentsInfo[componentIndex].textureSelected = textureIndex; |
||||
this.$refs.threeStage.updateScene(); |
||||
}); |
||||
} else { |
||||
this.componentsInfo[componentIndex].textureSelected = textureIndex; |
||||
this.$refs.threeStage.updateScene(); |
||||
this.downloadingDialog = false; |
||||
} |
||||
}, |
||||
delTexture(componentIndex, textureIndex) { |
||||
this.componentsInfo[componentIndex].textures.splice(textureIndex, 1); |
||||
}, |
||||
delModel(componentIndex, modelIndex) { |
||||
let model = this.componentsInfo[componentIndex].models[modelIndex].obj; |
||||
if (model != null) { |
||||
model.parent.remove(model); |
||||
} |
||||
this.componentsInfo[componentIndex].models.splice(modelIndex, 1); |
||||
}, |
||||
delComponent(componentIndex) { |
||||
for (let component of this.componentsInfo[componentIndex].models) { |
||||
if (component.obj != null) { |
||||
component.obj.parent.remove(component.obj); |
||||
} |
||||
} |
||||
this.componentsInfo.splice(componentIndex, 1); |
||||
} |
||||
}, |
||||
created() { |
||||
this.refresh(); |
||||
} |
||||
}; |
||||
</script> |
||||
<style > |
||||
</style> |
@ -0,0 +1,514 @@ |
||||
<template> |
||||
<v-app dark id="inspire"> |
||||
<!-- drawer开始 --> |
||||
<v-navigation-drawer v-model="drawer" fixed app> |
||||
<v-list class="pa-1"> |
||||
<v-list-tile avatar> |
||||
<v-list-tile-avatar @click="avatarUpload=true"> |
||||
<img :src="avatar"> |
||||
</v-list-tile-avatar> |
||||
<v-list-tile-content> |
||||
<v-list-tile-title v-text="userName"></v-list-tile-title> |
||||
</v-list-tile-content> |
||||
</v-list-tile> |
||||
</v-list> |
||||
<v-list class="pt-0" dense> |
||||
<v-divider></v-divider> |
||||
<v-list-tile @click="userDialog=true"> |
||||
<v-list-tile-action> |
||||
<v-icon>account_box</v-icon> |
||||
</v-list-tile-action> |
||||
<v-list-tile-content> |
||||
<v-list-tile-title>修改用户信息</v-list-tile-title> |
||||
</v-list-tile-content> |
||||
</v-list-tile> |
||||
<v-list-tile @click> |
||||
<v-list-tile-action> |
||||
<v-icon>info</v-icon> |
||||
</v-list-tile-action> |
||||
<v-list-tile-content> |
||||
<v-list-tile-title>关于V3D</v-list-tile-title> |
||||
</v-list-tile-content> |
||||
</v-list-tile> |
||||
<v-list-tile @click="logout"> |
||||
<v-list-tile-action> |
||||
<v-icon>exit_to_app</v-icon> |
||||
</v-list-tile-action> |
||||
<v-list-tile-content> |
||||
<v-list-tile-title>退出系统</v-list-tile-title> |
||||
</v-list-tile-content> |
||||
</v-list-tile> |
||||
</v-list> |
||||
</v-navigation-drawer> |
||||
<!-- drawer结束 --> |
||||
|
||||
<!-- 工具栏开始 --> |
||||
<v-toolbar color="red" dark fixed app> |
||||
<v-toolbar-side-icon @click.stop="drawer = !drawer"></v-toolbar-side-icon> |
||||
<v-toolbar-title>V3D</v-toolbar-title> |
||||
<v-spacer/> |
||||
<v-text-field |
||||
clearable |
||||
v-model="keyword" |
||||
solo-inverted |
||||
flat |
||||
hide-details |
||||
label="搜索" |
||||
prepend-inner-icon="search" |
||||
class="hidden-sm-and-down" |
||||
></v-text-field> |
||||
<v-spacer/> |
||||
<v-toolbar-items class="hidden-sm-and-down"> |
||||
<v-btn flat @click="createDialog=true"> |
||||
<v-icon>add</v-icon>创建方案 |
||||
</v-btn> |
||||
</v-toolbar-items> |
||||
</v-toolbar> |
||||
<!-- 工具栏结束 --> |
||||
|
||||
<!-- 内容开始 --> |
||||
<v-content> |
||||
<v-container fluid fill-height v-if="schemeList.length==0"> |
||||
<v-layout justify-center align-center> |
||||
<v-flex text-xs-center class="headline font-weight-light">还没有方案,请先创建方案</v-flex> |
||||
</v-layout> |
||||
</v-container> |
||||
<v-container fluid grid-list-md v-else> |
||||
<v-layout row wrap> |
||||
<v-flex |
||||
v-for="(item,index) in schemeList" |
||||
:key="item.sid" |
||||
xs12 |
||||
sm6 |
||||
md3 |
||||
v-if="keyword==null||item.name.indexOf(keyword)!=-1" |
||||
> |
||||
<v-card> |
||||
<v-img :src="item.cover" height="200px"> |
||||
<v-container fill-height fluid pa-2> |
||||
<v-layout fill-height> |
||||
<v-flex xs12 align-end flexbox> |
||||
<span class="headline white--text" v-text="item.name"></span> |
||||
</v-flex> |
||||
</v-layout> |
||||
</v-container> |
||||
</v-img> |
||||
<v-card-actions> |
||||
<v-spacer></v-spacer> |
||||
<v-btn icon @click="edit(item.sid)"> |
||||
<v-icon>edit</v-icon> |
||||
</v-btn> |
||||
<v-btn icon @click="share(index)"> |
||||
<v-icon>share</v-icon> |
||||
</v-btn> |
||||
<v-btn icon @click="del(index)"> |
||||
<v-icon>delete</v-icon> |
||||
</v-btn> |
||||
</v-card-actions> |
||||
</v-card> |
||||
</v-flex> |
||||
</v-layout> |
||||
</v-container> |
||||
</v-content> |
||||
<!-- 内容结束 --> |
||||
|
||||
<!-- 底部开始 --> |
||||
<v-footer color="red" app> |
||||
<v-flex py-3 text-xs-center white--text xs12> |
||||
<span class="white--text">© 2019 TONKIA V3D</span> |
||||
</v-flex> |
||||
</v-footer> |
||||
<!-- 底部结束 --> |
||||
|
||||
<!-- 创建方案模态框 开始--> |
||||
<v-dialog v-model="createDialog" width="500"> |
||||
<v-card> |
||||
<v-toolbar dark color="red"> |
||||
<v-toolbar-title>创建新方案</v-toolbar-title> |
||||
<v-spacer></v-spacer> |
||||
<v-btn icon dark @click="createDialog = false"> |
||||
<v-icon>close</v-icon> |
||||
</v-btn> |
||||
</v-toolbar> |
||||
<v-card-text> |
||||
<v-text-field label="方案名称" color="red" v-model="schemeName"></v-text-field> |
||||
</v-card-text> |
||||
<v-divider></v-divider> |
||||
<v-card-actions> |
||||
<v-spacer></v-spacer> |
||||
<v-btn dark flat @click="createScheme">确定</v-btn> |
||||
</v-card-actions> |
||||
</v-card> |
||||
</v-dialog> |
||||
<!-- 创建方案模态框 结束 --> |
||||
|
||||
<!-- 方案分享 开始 --> |
||||
<v-dialog v-model="shareDialog" persistent max-width="600px"> |
||||
<v-card light> |
||||
<v-card-title> |
||||
<span class="headline">方案分享</span> |
||||
</v-card-title> |
||||
<v-divider/> |
||||
<v-card-text> |
||||
<v-container grid-list-md> |
||||
<v-layout wrap> |
||||
<v-flex xs12> |
||||
<v-switch label="开启分享" color="red" v-model="isShared"></v-switch> |
||||
<v-text-field label="访问地址" outline readonly :value="shareLink"></v-text-field> |
||||
<input :value="shareLink" ref="shareLink" style="display:none"> |
||||
<input |
||||
:value="`<iframe src='${shareLink}' scrolling='no' frameborder='0' width='100%' height='100%'></iframe>`" |
||||
ref="iframLink" |
||||
style="display:none" |
||||
> |
||||
</v-flex> |
||||
<v-layout class="ma-3"> |
||||
<canvas ref="qr"></canvas> |
||||
<v-spacer/> |
||||
<v-layout column justify-end> |
||||
<a style="text-align:right" class="ma-2"> |
||||
关于IFrames地址的使用 |
||||
<v-icon small>help</v-icon> |
||||
</a> |
||||
<v-btn color="blue" dark @click="copyIframe">iframe地址</v-btn> |
||||
<v-btn color="blue" dark @click="copyLink">复制访问地址</v-btn> |
||||
<v-btn color="green" dark @click="saveQR">保存二维码</v-btn> |
||||
</v-layout> |
||||
</v-layout> |
||||
<v-flex xs12> |
||||
<v-divider/> |
||||
</v-flex> |
||||
<v-flex xs12> |
||||
<v-switch label="使用密码" color="red" v-model="hasPassword"></v-switch> |
||||
<v-text-field |
||||
v-model="sharePassword" |
||||
label="访问密码" |
||||
:type="hasPassword&&showPassword ? 'text' : 'password'" |
||||
:disabled="!hasPassword" |
||||
:append-icon="hasPassword&&showPassword? 'visibility' : 'visibility_off'" |
||||
@click:append="showPassword = !showPassword" |
||||
></v-text-field> |
||||
</v-flex> |
||||
</v-layout> |
||||
</v-container> |
||||
</v-card-text> |
||||
<v-divider/> |
||||
<v-card-actions> |
||||
<v-spacer></v-spacer> |
||||
<v-btn color="blue darken-1" flat @click="shareDialog = false">取消</v-btn> |
||||
<v-btn color="blue darken-1" flat @click="saveShare">保存</v-btn> |
||||
</v-card-actions> |
||||
</v-card> |
||||
</v-dialog> |
||||
<!-- 方案分享 结束 --> |
||||
|
||||
<!-- 用户信息修改 开始 --> |
||||
<v-dialog v-model="userDialog" persistent max-width="600px"> |
||||
<v-card light> |
||||
<v-card-title> |
||||
<span class="headline">用户信息修改</span> |
||||
</v-card-title> |
||||
<v-divider/> |
||||
<v-card-text> |
||||
<v-container> |
||||
<v-layout row wrap> |
||||
<v-flex xs9> |
||||
<v-text-field box label="用户名" v-model="newName"></v-text-field> |
||||
</v-flex> |
||||
<v-flex xs3> |
||||
<v-btn large flat color="blue" @click="changeName">修改用户名</v-btn> |
||||
</v-flex> |
||||
<v-flex xs12> |
||||
<v-text-field box label="修改密码" v-model="pwd" type="password"></v-text-field> |
||||
</v-flex> |
||||
<v-flex xs12> |
||||
<v-text-field box label="确认密码" v-model="repwd" type="password"></v-text-field> |
||||
</v-flex> |
||||
<v-flex xs12> |
||||
<v-btn block color="blue" dark @click="changePwd">修改密码</v-btn> |
||||
</v-flex> |
||||
</v-layout> |
||||
</v-container> |
||||
</v-card-text> |
||||
<v-divider/> |
||||
<v-card-actions> |
||||
<v-spacer></v-spacer> |
||||
<v-btn color="blue darken-1" flat @click="userDialog = false">确认</v-btn> |
||||
</v-card-actions> |
||||
</v-card> |
||||
</v-dialog> |
||||
<!-- 用户信息修改 结束 --> |
||||
|
||||
<!-- 图片上传组件 --> |
||||
<avatar-upload |
||||
@crop-upload-success="cropUploadSuccess" |
||||
field="file" |
||||
v-model="avatarUpload" |
||||
:width="300" |
||||
:height="300" |
||||
url="/user/avatar" |
||||
img-format="png" |
||||
></avatar-upload> |
||||
<!-- 图片上传组件 --> |
||||
</v-app> |
||||
</template> |
||||
|
||||
<script> |
||||
import QRious from "qrious"; |
||||
import avatarUpload from "vue-image-crop-upload"; |
||||
|
||||
export default { |
||||
components: { |
||||
"avatar-upload": avatarUpload |
||||
}, |
||||
data: () => ({ |
||||
//方案数据 |
||||
schemeList: [], |
||||
//临时数据 |
||||
schemeName: "", |
||||
keyword: "", |
||||
shareLink: "", |
||||
isShared: false, |
||||
hasPassword: false, |
||||
showPassword: false, |
||||
sharePassword: "", |
||||
shareIndex: 0, |
||||
//用户 |
||||
avatar: null, |
||||
userName: null, |
||||
//ui |
||||
drawer: null, |
||||
createDialog: null, |
||||
shareDialog: null, |
||||
userDialog: null, |
||||
//crop image |
||||
avatarUpload: false, |
||||
//update userinfo |
||||
newName: "", |
||||
pwd: "", |
||||
repwd: "" |
||||
}), |
||||
methods: { |
||||
changeName() { |
||||
this.$http |
||||
.post( |
||||
"/user/changeInfo", |
||||
{ |
||||
userName: this.newName |
||||
}, |
||||
{} |
||||
) |
||||
.then( |
||||
data => { |
||||
console.info(data); |
||||
if (data.body.code == 0) { |
||||
this.userName = this.newName; |
||||
this.newName = ""; |
||||
} |
||||
}, |
||||
error => { |
||||
console.info(error); |
||||
} |
||||
); |
||||
}, |
||||
changePwd() { |
||||
if (this.pwd == this.repwd) { |
||||
this.$http |
||||
.post( |
||||
"/user/changeInfo", |
||||
{ |
||||
password: this.pwd |
||||
}, |
||||
{} |
||||
) |
||||
.then( |
||||
data => { |
||||
console.info(data); |
||||
if (data.body.code == 0) { |
||||
this.pwd = ""; |
||||
this.repwd = ""; |
||||
} |
||||
}, |
||||
error => { |
||||
console.info(error); |
||||
} |
||||
); |
||||
} |
||||
}, |
||||
cropUploadSuccess(data, field) { |
||||
if (data.code == 0) { |
||||
this.avatar = data.data.avatar; |
||||
} |
||||
}, |
||||
del(index) { |
||||
this.$http |
||||
.post( |
||||
"/scheme/delete", |
||||
{ |
||||
sid: this.schemeList[index].sid |
||||
}, |
||||
{} |
||||
) |
||||
.then( |
||||
data => { |
||||
console.info(data); |
||||
if (data.body.code == 0) { |
||||
this.schemeList.splice(index, 1); |
||||
} |
||||
}, |
||||
error => { |
||||
console.info(error); |
||||
} |
||||
); |
||||
}, |
||||
edit(sid) { |
||||
this.$router.push("create/" + sid); |
||||
}, |
||||
share(index) { |
||||
this.shareIndex = index; |
||||
let scheme = this.schemeList[index]; |
||||
var qr = new QRious({ |
||||
element: this.$refs.qr, |
||||
size: 250, |
||||
level: "L", |
||||
foreground: "#424242", |
||||
background: "#fff", |
||||
value: scheme.shareLink |
||||
}); |
||||
this.shareLink = scheme.shareLink; |
||||
this.sharePassword = scheme.password; |
||||
switch (scheme.share) { |
||||
case 0: |
||||
this.isShared = false; |
||||
this.hasPassword = false; |
||||
break; |
||||
case 1: |
||||
this.isShared = true; |
||||
this.hasPassword = false; |
||||
break; |
||||
case 2: |
||||
this.isShared = true; |
||||
this.hasPassword = true; |
||||
break; |
||||
} |
||||
this.shareDialog = true; |
||||
}, |
||||
copyLink() { |
||||
this.$refs.shareLink.style.display = "inline"; |
||||
this.$refs.shareLink.select(); |
||||
document.execCommand("Copy"); |
||||
this.$refs.shareLink.style.display = "none"; |
||||
}, |
||||
copyIframe() { |
||||
this.$refs.iframLink.style.display = "inline"; |
||||
this.$refs.iframLink.select(); |
||||
document.execCommand("Copy"); |
||||
this.$refs.iframLink.style.display = "none"; |
||||
}, |
||||
saveQR() { |
||||
let a = document.createElement("a"); |
||||
a.href = this.$refs.qr.toDataURL("image/png"); |
||||
a.download = "qr.png"; |
||||
let event = document.createEvent("MouseEvents"); |
||||
event.initEvent("click", true, false); |
||||
a.dispatchEvent(event); |
||||
}, |
||||
saveShare() { |
||||
let index = this.shareIndex; |
||||
let share = 0; |
||||
if (this.isShared) { |
||||
if (this.hasPassword) { |
||||
share = 2; |
||||
} else { |
||||
share = 1; |
||||
} |
||||
} |
||||
this.schemeList[index].share = share; |
||||
this.schemeList[index].password = this.sharePassword; |
||||
this.$http |
||||
.post( |
||||
"/scheme/share", |
||||
{ |
||||
sid: this.schemeList[index].sid, |
||||
share: this.schemeList[index].share, |
||||
password: this.schemeList[index].password |
||||
}, |
||||
{} |
||||
) |
||||
.then( |
||||
data => { |
||||
console.info(data); |
||||
}, |
||||
error => { |
||||
console.info(error); |
||||
} |
||||
); |
||||
this.shareDialog = false; |
||||
}, |
||||
createScheme() { |
||||
this.$http |
||||
.post( |
||||
"/scheme/create", |
||||
{ |
||||
name: this.schemeName |
||||
}, |
||||
{} |
||||
) |
||||
.then( |
||||
data => { |
||||
console.info(data); |
||||
if (data.body.code == 0) { |
||||
this.$router.push("create/" + data.body.data.sid); |
||||
} |
||||
}, |
||||
error => { |
||||
console.info(error); |
||||
} |
||||
); |
||||
}, |
||||
logout() { |
||||
this.$http.get("/user/logout").then( |
||||
data => { |
||||
console.info(data); |
||||
if (data.body.code == 0) { |
||||
this.$router.push("/"); |
||||
} |
||||
}, |
||||
error => { |
||||
console.info(error); |
||||
} |
||||
); |
||||
} |
||||
}, |
||||
watch: { |
||||
//当创建dialog推出时候清空文本栏 |
||||
createDialog() { |
||||
this.schemeName = ""; |
||||
}, |
||||
userDialog() { |
||||
this.newName = ""; |
||||
this.pwd = ""; |
||||
this.repwd = ""; |
||||
} |
||||
}, |
||||
created() { |
||||
this.$http.get("/home/getHomeInfo").then( |
||||
data => { |
||||
console.info(data); |
||||
if (data.body.code == 0) { |
||||
//初始化主页数据 |
||||
this.avatar = data.body.data.userInfo.avatar; |
||||
this.userName = data.body.data.userInfo.userName; |
||||
this.schemeList = data.body.data.schemeList; |
||||
} else { |
||||
//初始化数据失败 |
||||
this.$router.push("/"); |
||||
} |
||||
}, |
||||
error => { |
||||
console.info(error); |
||||
} |
||||
); |
||||
} |
||||
}; |
||||
</script> |
@ -0,0 +1,116 @@ |
||||
<template> |
||||
<v-app dark> |
||||
<v-content> |
||||
<v-alert |
||||
dismissible |
||||
v-model="alert" |
||||
type="error" |
||||
transition="scale-transition" |
||||
style="position:absolute;width:100%;margin:0px" |
||||
>{{msg}}</v-alert> |
||||
<v-container fluid fill-height> |
||||
<v-layout align-center justify-center> |
||||
<v-flex sm12 md4> |
||||
<v-card light class="elevation-12"> |
||||
<v-toolbar dark color="red"> |
||||
<v-toolbar-title>用户登录</v-toolbar-title> |
||||
<v-spacer></v-spacer> |
||||
<!-- 提示的方向 --> |
||||
<v-tooltip bottom> |
||||
<!-- 这是需要提示的部件,任意 --> |
||||
<!-- on 是 v-tooltip 传递过来的事件处理方法 --> |
||||
<template v-slot:activator="{on}"> |
||||
<v-btn icon large v-on="on"> |
||||
<v-icon large>info</v-icon> |
||||
</v-btn> |
||||
</template> |
||||
<!-- 这是默认插槽,即提示的内容 --> |
||||
<span>关于V3D</span> |
||||
</v-tooltip> |
||||
</v-toolbar> |
||||
<v-card-text> |
||||
<v-form> |
||||
<v-text-field |
||||
prepend-icon="phone" |
||||
name="phoneNumber" |
||||
label="手机号" |
||||
type="tel" |
||||
color="red" |
||||
v-model="phoneNumber" |
||||
mask="###########" |
||||
/> |
||||
<v-text-field |
||||
prepend-icon="lock" |
||||
name="password" |
||||
label="密码" |
||||
type="password" |
||||
color="red" |
||||
v-model="password" |
||||
/> |
||||
</v-form> |
||||
</v-card-text> |
||||
<v-card-actions> |
||||
<v-spacer></v-spacer> |
||||
<v-btn dark color="red" @click="login">登 录</v-btn> |
||||
</v-card-actions> |
||||
</v-card> |
||||
</v-flex> |
||||
</v-layout> |
||||
</v-container> |
||||
</v-content> |
||||
</v-app> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
data: () => ({ |
||||
alert: false, |
||||
msg: "", |
||||
phoneNumber: "", |
||||
password: "" |
||||
}), |
||||
methods: { |
||||
login() { |
||||
this.$http |
||||
.post( |
||||
"/user/login", |
||||
{ |
||||
phoneNumber: this.phoneNumber, |
||||
password: this.password |
||||
}, |
||||
{} |
||||
) |
||||
.then( |
||||
data => { |
||||
console.info(data); |
||||
if (data.body.code == 0) { |
||||
this.$router.push("home"); |
||||
} else { |
||||
this.alert = true; |
||||
this.msg = data.body.msg; |
||||
} |
||||
}, |
||||
error => { |
||||
console.info(error); |
||||
} |
||||
); |
||||
} |
||||
}, |
||||
beforeCreate() { |
||||
this.$http.get("/user/hasLogin").then( |
||||
data => { |
||||
console.info(data); |
||||
if (data.body.code == 0) { |
||||
this.$router.push("home"); |
||||
} |
||||
}, |
||||
error => { |
||||
console.info(error); |
||||
} |
||||
); |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style> |
||||
</style> |
@ -0,0 +1,12 @@ |
||||
<template> |
||||
<v-app dark> |
||||
<v-content class="body-2 text-xs-center">无法获取数据!</v-content> |
||||
</v-app> |
||||
</template> |
||||
|
||||
<script> |
||||
export default {}; |
||||
</script> |
||||
|
||||
<style> |
||||
</style> |
@ -0,0 +1,415 @@ |
||||
<template> |
||||
<v-app> |
||||
<v-toolbar color="red" dark app clipped-left> |
||||
<v-toolbar-side-icon @click="mainDrawer = !mainDrawer"></v-toolbar-side-icon> |
||||
<v-toolbar-title>{{name}}</v-toolbar-title> |
||||
</v-toolbar> |
||||
<v-content style="height:0px;background-color:#ddd"> |
||||
<ThreeStage |
||||
:components-info="componentsInfo" |
||||
:camera-controll="cameraControll" |
||||
ref="threeStage" |
||||
/> |
||||
<v-speed-dial |
||||
v-model="fab" |
||||
bottom |
||||
right |
||||
direction="top" |
||||
transition="slide-y-reverse-transition" |
||||
> |
||||
<template v-slot:activator> |
||||
<v-btn v-model="fab" color="red" dark fab> |
||||
<v-icon>add</v-icon> |
||||
<v-icon>close</v-icon> |
||||
</v-btn> |
||||
</template> |
||||
<v-btn fab dark small color="blue" @click="pulishDialog=true"> |
||||
<v-icon>edit</v-icon> |
||||
</v-btn> |
||||
<v-btn fab dark small color="green" @click="getComment();commentDialog=true"> |
||||
<v-icon>comment</v-icon> |
||||
</v-btn> |
||||
</v-speed-dial> |
||||
</v-content> |
||||
<!-- 文件加载进度模态框 开始 --> |
||||
<v-dialog v-model="downloadingDialog" persistent width="300"> |
||||
<v-card color="red" dark> |
||||
<v-card-text> |
||||
文件加载中 |
||||
<v-progress-linear indeterminate color="white" class="mb-0"></v-progress-linear> |
||||
</v-card-text> |
||||
</v-card> |
||||
</v-dialog> |
||||
<!-- 文件加载进度模态框 结束--> |
||||
<!-- 密码 开始--> |
||||
<v-dialog v-model="passwordDialog" persistent max-width="290"> |
||||
<v-card> |
||||
<v-card-title class="headline">该项目需要密码访问</v-card-title> |
||||
<v-card-text> |
||||
<v-text-field label="密码" outline v-model="password" type="password"></v-text-field> |
||||
</v-card-text> |
||||
<v-card-actions> |
||||
<v-spacer></v-spacer> |
||||
<v-btn color="green darken-1" flat @click="customer">确定</v-btn> |
||||
</v-card-actions> |
||||
</v-card> |
||||
</v-dialog> |
||||
<!-- 密码 结束--> |
||||
<!-- 发表评论 开始 --> |
||||
<v-dialog v-model="pulishDialog" max-width="500px"> |
||||
<v-card> |
||||
<v-card-title>发表评论</v-card-title> |
||||
<v-divider/> |
||||
<v-card-text> |
||||
<v-text-field single-line outline v-model="text"></v-text-field> |
||||
</v-card-text> |
||||
<v-divider/> |
||||
<v-card-actions> |
||||
<v-spacer></v-spacer> |
||||
<v-btn color="green darken-1" flat @click="pulish">发表</v-btn> |
||||
</v-card-actions> |
||||
</v-card> |
||||
</v-dialog> |
||||
<!-- 发表评论 结束 --> |
||||
<!-- 评论区 开始 --> |
||||
<v-dialog v-model="commentDialog" scrollable max-width="800px"> |
||||
<v-card> |
||||
<v-card-title class="font-weight-bold headline">评论区</v-card-title> |
||||
<v-divider></v-divider> |
||||
<v-card-text style="height: 300px;"> |
||||
<v-list two-line> |
||||
<div v-for="item in commentList" :key="item.time"> |
||||
<v-list-tile> |
||||
<v-list-tile-content> |
||||
<v-list-tile-title>{{ item.text }}</v-list-tile-title> |
||||
<v-list-tile-sub-title |
||||
class="text--primary text-xs-right" |
||||
>{{ item.time|timeFilter }}</v-list-tile-sub-title> |
||||
</v-list-tile-content> |
||||
</v-list-tile> |
||||
<v-divider/> |
||||
</div> |
||||
</v-list> |
||||
</v-card-text> |
||||
</v-card> |
||||
</v-dialog> |
||||
<!-- 评论区 结束 --> |
||||
<v-navigation-drawer v-model="mainDrawer" absolute fixed clipped app> |
||||
<v-tabs v-model="tab" color="red" dark align-with-title show-arrows> |
||||
<v-tabs-slider color="yellow"></v-tabs-slider> |
||||
<v-tab v-for="(item,index) in componentsInfo" :key="index" ripple>{{item.componentName}}</v-tab> |
||||
</v-tabs> |
||||
<v-tabs-items v-model="tab" style="position:absolute;buttom:0px;width:100%"> |
||||
<v-tab-item v-for="(item,index) in componentsInfo" :key="index"> |
||||
<v-card flat> |
||||
<v-card-text> |
||||
<v-list-tile |
||||
color="amber lighten-1" |
||||
v-for="(subItem,subIndex) in item.models" |
||||
:key="subItem.fid" |
||||
@click="modelChange(index,subIndex)" |
||||
> |
||||
<v-list-tile-content> |
||||
<v-list-tile-title> |
||||
{{ subItem.name }} |
||||
<v-icon small v-if="subIndex==item.modelSelected">arrow_left</v-icon> |
||||
</v-list-tile-title> |
||||
</v-list-tile-content> |
||||
</v-list-tile> |
||||
<v-divider/> |
||||
<v-container grid-list-sm fluid v-if="item.textures.length>0"> |
||||
<v-layout row wrap> |
||||
<v-flex v-for="(subItem,subIndex) in item.textures" :key="subItem.fid" xs2 d-flex> |
||||
<v-card flat tile class="d-flex" @click="textureChange(index,subIndex)"> |
||||
<v-img :src="subItem.path+'?size=60'" aspect-ratio="1" class="grey lighten-2"> |
||||
<template v-slot:placeholder> |
||||
<v-layout fill-height align-center justify-center ma-0> |
||||
<v-progress-circular indeterminate color="grey lighten-5"></v-progress-circular> |
||||
</v-layout> |
||||
</template> |
||||
</v-img> |
||||
</v-card> |
||||
</v-flex> |
||||
</v-layout> |
||||
</v-container> |
||||
</v-card-text> |
||||
</v-card> |
||||
</v-tab-item> |
||||
</v-tabs-items> |
||||
</v-navigation-drawer> |
||||
</v-app> |
||||
</template> |
||||
<script> |
||||
import "../plugins/OBJLoader"; |
||||
import "../plugins/FBXLoader"; |
||||
import { |
||||
LoadingManager, |
||||
TextureLoader, |
||||
OBJLoader, |
||||
FBXLoader, |
||||
DoubleSide |
||||
} from "three"; |
||||
import ThreeStage from "../components/ThreeStage"; |
||||
export default { |
||||
components: { |
||||
ThreeStage |
||||
}, |
||||
props: ["sid"], |
||||
data() { |
||||
return { |
||||
commentList: null, |
||||
text: "", |
||||
mainDrawer: false, |
||||
tab: null, |
||||
fab: false, |
||||
pulishDialog: null, |
||||
commentDialog: null, |
||||
downloadingDialog: null, |
||||
passwordDialog: null, |
||||
password: "", |
||||
name: "", |
||||
cameraControll: { |
||||
height: 10, |
||||
distance: 40, |
||||
heightMax: 200, |
||||
distanceMax: 200 |
||||
}, |
||||
componentsInfo: [] |
||||
}; |
||||
}, |
||||
methods: { |
||||
getComment() { |
||||
this.$http.post("/show/getComment", { sid: this.sid }, {}).then( |
||||
data => { |
||||
console.info(data); |
||||
if (data.body.code == 0) { |
||||
this.commentList = data.body.data; |
||||
} |
||||
}, |
||||
error => { |
||||
console.info(error); |
||||
} |
||||
); |
||||
}, |
||||
pulish() { |
||||
this.$http |
||||
.post("/show/comment", { sid: this.sid, text: this.text }, {}) |
||||
.then( |
||||
data => { |
||||
console.info(data); |
||||
if (data.body.code == 0) { |
||||
this.pulishDialog = false; |
||||
} |
||||
}, |
||||
error => { |
||||
console.info(error); |
||||
} |
||||
); |
||||
}, |
||||
getSchemeInfo() { |
||||
this.$http.get("/scheme/" + this.sid, {}, {}).then( |
||||
data => { |
||||
console.info(data); |
||||
if (data.body.code == 0) { |
||||
this.name = data.body.data.name; |
||||
let componentsInfo = JSON.parse(data.body.data.data); |
||||
let cameraControll = JSON.parse(data.body.data.camera); |
||||
if (componentsInfo) this.componentsInfo = componentsInfo; |
||||
if (cameraControll) this.cameraControll = cameraControll; |
||||
let manager = new LoadingManager(() => { |
||||
this.downloadingDialog = false; |
||||
}); |
||||
this.componentsInfo.map((item, index) => { |
||||
let modelIndex = item.modelSelected; |
||||
let textureIndex = item.textureSelected; |
||||
if (item.models[modelIndex] != null) { |
||||
this.downloadingDialog = true; |
||||
this.modelChange(index, modelIndex, manager); |
||||
} |
||||
if (item.textures[textureIndex] != null) { |
||||
this.downloadingDialog = true; |
||||
this.textureChange(index, textureIndex, manager); |
||||
} |
||||
}); |
||||
} else if (data.body.code == 2) { |
||||
this.$router.push("/"); |
||||
} else { |
||||
this.$router.push("/home"); |
||||
} |
||||
}, |
||||
error => { |
||||
console.info(error); |
||||
} |
||||
); |
||||
}, |
||||
modelChange(componentIndex, modelIndex, manager) { |
||||
if (manager == null) { |
||||
this.downloadingDialog = true; |
||||
manager = new LoadingManager(() => { |
||||
this.downloadingDialog = false; |
||||
}); |
||||
} |
||||
let model = this.componentsInfo[componentIndex].models[modelIndex]; |
||||
if (model.obj == null) { |
||||
//obj |
||||
if ( |
||||
model.path |
||||
.split(".") |
||||
.pop() |
||||
.toLowerCase() === "obj" |
||||
) { |
||||
new OBJLoader(manager).load( |
||||
model.path, |
||||
//success回调 |
||||
obj => { |
||||
obj.traverse(child => { |
||||
if (child.isMesh) { |
||||
child.material.side = DoubleSide; |
||||
} |
||||
}); |
||||
model.obj = obj; |
||||
this.componentsInfo[componentIndex].modelSelected = modelIndex; |
||||
this.$refs.threeStage.updateScene(); |
||||
} |
||||
); |
||||
//fbx |
||||
} else if ( |
||||
model.path |
||||
.split(".") |
||||
.pop() |
||||
.toLowerCase() === "fbx" |
||||
) { |
||||
new FBXLoader(manager).load( |
||||
model.path, |
||||
obj => { |
||||
obj.traverse(child => { |
||||
if (child.isMesh) { |
||||
child.material.side = DoubleSide; |
||||
} |
||||
}); |
||||
model.obj = obj; |
||||
this.componentsInfo[componentIndex].modelSelected = modelIndex; |
||||
this.$refs.threeStage.updateScene(); |
||||
}, |
||||
xhr => { |
||||
if (xhr.lengthComputable) { |
||||
// console.info((xhr.loaded / xhr.total) * 100); |
||||
} |
||||
} |
||||
); |
||||
} |
||||
} else { |
||||
this.componentsInfo[componentIndex].modelSelected = modelIndex; |
||||
this.$refs.threeStage.updateScene(); |
||||
this.downloadingDialog = false; |
||||
} |
||||
}, |
||||
textureChange(componentIndex, textureIndex, manager) { |
||||
if (manager == null) { |
||||
this.downloadingDialog = true; |
||||
manager = new LoadingManager(() => { |
||||
this.downloadingDialog = false; |
||||
}); |
||||
} |
||||
let texture = this.componentsInfo[componentIndex].textures[textureIndex]; |
||||
if (texture.obj == null) { |
||||
new TextureLoader(manager).load(texture.path, obj => { |
||||
texture.obj = obj; |
||||
this.componentsInfo[componentIndex].textureSelected = textureIndex; |
||||
this.$refs.threeStage.updateScene(); |
||||
}); |
||||
} else { |
||||
this.componentsInfo[componentIndex].textureSelected = textureIndex; |
||||
this.$refs.threeStage.updateScene(); |
||||
this.downloadingDialog = false; |
||||
} |
||||
}, |
||||
customer() { |
||||
this.$http |
||||
.post( |
||||
"/show/customer", |
||||
{ |
||||
sid: this.sid, |
||||
password: this.password |
||||
}, |
||||
{} |
||||
) |
||||
.then( |
||||
data => { |
||||
console.info(data); |
||||
if (data.body.code == 0) { |
||||
this.passwordDialog = false; |
||||
this.password = ""; |
||||
this.getSchemeInfo(); |
||||
} else { |
||||
this.password = ""; |
||||
} |
||||
}, |
||||
error => { |
||||
console.info(error); |
||||
} |
||||
); |
||||
} |
||||
}, |
||||
watch: { |
||||
pulishDialog() { |
||||
this.text = ""; |
||||
} |
||||
}, |
||||
filters: { |
||||
timeFilter: function(value) { |
||||
var date = new Date(); |
||||
date.setTime(value); |
||||
var month = |
||||
date.getMonth().toString().length > 1 |
||||
? date.getMonth() |
||||
: "0" + date.getMonth(); |
||||
var day = |
||||
date.getDate().toString().length > 1 |
||||
? date.getDate() |
||||
: "0" + date.getDate(); |
||||
var hour = |
||||
date.getHours().toString().length > 1 |
||||
? date.getHours() |
||||
: "0" + date.getHours(); |
||||
var min = |
||||
date.getMinutes().toString().length > 1 |
||||
? date.getMinutes() |
||||
: "0" + date.getMinutes(); |
||||
return ( |
||||
date.getFullYear() + "-" + month + "-" + day + " " + hour + ":" + min |
||||
); |
||||
} |
||||
}, |
||||
created() { |
||||
this.$http.get("/show/" + this.sid, {}, {}).then( |
||||
data => { |
||||
if (data.body.code == 0) { |
||||
console.info(data); |
||||
let share = data.body.data.share; |
||||
if (share == 1) { |
||||
this.getSchemeInfo(); |
||||
} else if (share == 2) { |
||||
this.passwordDialog = true; |
||||
}else{ |
||||
this.$router.push("/refuse") |
||||
} |
||||
} |
||||
}, |
||||
error => { |
||||
console.info(error); |
||||
} |
||||
); |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style> |
||||
.v-speed-dial { |
||||
position: absolute; |
||||
} |
||||
|
||||
.v-btn--floating { |
||||
position: relative; |
||||
} |
||||
</style> |
@ -0,0 +1,10 @@ |
||||
module.exports = { |
||||
devServer: { |
||||
host: "localhost", |
||||
port: 8080, // 端口号
|
||||
https: false, // https:{type:Boolean}
|
||||
open: true, //配置自动启动浏览器
|
||||
proxy: 'http://localhost' |
||||
}, |
||||
lintOnSave: false |
||||
} |
@ -0,0 +1,13 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project version="4"> |
||||
<component name="CompilerConfiguration"> |
||||
<annotationProcessing> |
||||
<profile name="Maven default annotation processors profile" enabled="true"> |
||||
<sourceOutputDir name="target/generated-sources/annotations" /> |
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" /> |
||||
<outputRelativeToContentRoot value="true" /> |
||||
<module name="v3dmodel" /> |
||||
</profile> |
||||
</annotationProcessing> |
||||
</component> |
||||
</project> |
@ -0,0 +1,7 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project version="4"> |
||||
<component name="Encoding" native2AsciiForPropertiesFiles="true" addBOMForNewFiles="with NO BOM"> |
||||
<file url="file://$PROJECT_DIR$" charset="UTF-8" /> |
||||
<file url="PROJECT" charset="UTF-8" /> |
||||
</component> |
||||
</project> |
@ -0,0 +1,46 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project version="4"> |
||||
<component name="ExternalStorageConfigurationManager" enabled="true" /> |
||||
<component name="FrameworkDetectionExcludesConfiguration"> |
||||
<file type="web" url="file://$PROJECT_DIR$" /> |
||||
</component> |
||||
<component name="MavenProjectsManager"> |
||||
<option name="originalFiles"> |
||||
<list> |
||||
<option value="$PROJECT_DIR$/pom.xml" /> |
||||
</list> |
||||
</option> |
||||
</component> |
||||
<component name="ProjectInspectionProfilesVisibleTreeState"> |
||||
<entry key="Project Default"> |
||||
<profile-state> |
||||
<expanded-state> |
||||
<State /> |
||||
<State> |
||||
<id>Java</id> |
||||
</State> |
||||
<State> |
||||
<id>Probable bugsJava</id> |
||||
</State> |
||||
<State> |
||||
<id>RELAX NG</id> |
||||
</State> |
||||
<State> |
||||
<id>XPath</id> |
||||
</State> |
||||
<State> |
||||
<id>XSLT</id> |
||||
</State> |
||||
</expanded-state> |
||||
<selected-state> |
||||
<State> |
||||
<id>CSS</id> |
||||
</State> |
||||
</selected-state> |
||||
</profile-state> |
||||
</entry> |
||||
</component> |
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="11" project-jdk-type="JavaSDK"> |
||||
<output url="file://$PROJECT_DIR$/out" /> |
||||
</component> |
||||
</project> |
@ -0,0 +1,124 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project version="4"> |
||||
<component name="Palette2"> |
||||
<group name="Swing"> |
||||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false"> |
||||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" /> |
||||
</item> |
||||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false"> |
||||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" /> |
||||
</item> |
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false"> |
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" /> |
||||
</item> |
||||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true"> |
||||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" /> |
||||
</item> |
||||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false"> |
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" /> |
||||
<initial-values> |
||||
<property name="text" value="Button" /> |
||||
</initial-values> |
||||
</item> |
||||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false"> |
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" /> |
||||
<initial-values> |
||||
<property name="text" value="RadioButton" /> |
||||
</initial-values> |
||||
</item> |
||||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false"> |
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" /> |
||||
<initial-values> |
||||
<property name="text" value="CheckBox" /> |
||||
</initial-values> |
||||
</item> |
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false"> |
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" /> |
||||
<initial-values> |
||||
<property name="text" value="Label" /> |
||||
</initial-values> |
||||
</item> |
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true"> |
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1"> |
||||
<preferred-size width="150" height="-1" /> |
||||
</default-constraints> |
||||
</item> |
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true"> |
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1"> |
||||
<preferred-size width="150" height="-1" /> |
||||
</default-constraints> |
||||
</item> |
||||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true"> |
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1"> |
||||
<preferred-size width="150" height="-1" /> |
||||
</default-constraints> |
||||
</item> |
||||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true"> |
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3"> |
||||
<preferred-size width="150" height="50" /> |
||||
</default-constraints> |
||||
</item> |
||||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true"> |
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3"> |
||||
<preferred-size width="150" height="50" /> |
||||
</default-constraints> |
||||
</item> |
||||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true"> |
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3"> |
||||
<preferred-size width="150" height="50" /> |
||||
</default-constraints> |
||||
</item> |
||||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true"> |
||||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" /> |
||||
</item> |
||||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false"> |
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3"> |
||||
<preferred-size width="150" height="50" /> |
||||
</default-constraints> |
||||
</item> |
||||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false"> |
||||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3"> |
||||
<preferred-size width="150" height="50" /> |
||||
</default-constraints> |
||||
</item> |
||||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false"> |
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3"> |
||||
<preferred-size width="150" height="50" /> |
||||
</default-constraints> |
||||
</item> |
||||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false"> |
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3"> |
||||
<preferred-size width="200" height="200" /> |
||||
</default-constraints> |
||||
</item> |
||||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false"> |
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3"> |
||||
<preferred-size width="200" height="200" /> |
||||
</default-constraints> |
||||
</item> |
||||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true"> |
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" /> |
||||
</item> |
||||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false"> |
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" /> |
||||
</item> |
||||
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false"> |
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" /> |
||||
</item> |
||||
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false"> |
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" /> |
||||
</item> |
||||
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false"> |
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1"> |
||||
<preferred-size width="-1" height="20" /> |
||||
</default-constraints> |
||||
</item> |
||||
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false"> |
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" /> |
||||
</item> |
||||
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false"> |
||||
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" /> |
||||
</item> |
||||
</group> |
||||
</component> |
||||
</project> |
@ -0,0 +1,6 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project version="4"> |
||||
<component name="VcsDirectoryMappings"> |
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" /> |
||||
</component> |
||||
</project> |
@ -0,0 +1,219 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
<modelVersion>4.0.0</modelVersion> |
||||
|
||||
<groupId>com.tonkia</groupId> |
||||
<artifactId>v3dmodel</artifactId> |
||||
<version>1.0-SNAPSHOT</version> |
||||
<packaging>war</packaging> |
||||
|
||||
<name>v3dmodel Maven Webapp</name> |
||||
|
||||
<properties> |
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
||||
<maven.compiler.source>1.7</maven.compiler.source> |
||||
<maven.compiler.target>1.7</maven.compiler.target> |
||||
<!--<spring-version>4.3.20.RELEASE</spring-version>--> |
||||
<spring-version>5.1.3.RELEASE</spring-version> |
||||
</properties> |
||||
|
||||
<dependencies> |
||||
<dependency> |
||||
<groupId>junit</groupId> |
||||
<artifactId>junit</artifactId> |
||||
<version>4.11</version> |
||||
<scope>test</scope> |
||||
</dependency> |
||||
<!--servlet-api--> |
||||
<dependency> |
||||
<groupId>javax.servlet</groupId> |
||||
<artifactId>javax.servlet-api</artifactId> |
||||
<version>4.0.1</version> |
||||
<scope>provided</scope> |
||||
</dependency> |
||||
<!--jsp-api --> |
||||
<dependency> |
||||
<groupId>javax.servlet</groupId> |
||||
<artifactId>jsp-api</artifactId> |
||||
<version>2.0</version> |
||||
<scope>provided</scope> |
||||
</dependency> |
||||
<!--jstl--> |
||||
<dependency> |
||||
<groupId>jstl</groupId> |
||||
<artifactId>jstl</artifactId> |
||||
<version>1.2</version> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>taglibs</groupId> |
||||
<artifactId>standard</artifactId> |
||||
<version>1.1.2</version> |
||||
</dependency> |
||||
<!--spring framework--> |
||||
<dependency> |
||||
<groupId>org.springframework</groupId> |
||||
<artifactId>spring-webmvc</artifactId> |
||||
<version>${spring-version}</version> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.springframework</groupId> |
||||
<artifactId>spring-jdbc</artifactId> |
||||
<version>${spring-version}</version> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.aspectj</groupId> |
||||
<artifactId>aspectjweaver</artifactId> |
||||
<version>1.9.2</version> |
||||
</dependency> |
||||
<!--mybatis--> |
||||
<dependency> |
||||
<groupId>org.mybatis</groupId> |
||||
<artifactId>mybatis</artifactId> |
||||
<version>3.4.6</version> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.mybatis</groupId> |
||||
<artifactId>mybatis-spring</artifactId> |
||||
<version>1.3.2</version> |
||||
</dependency> |
||||
<!--mysql--> |
||||
<dependency> |
||||
<groupId>mysql</groupId> |
||||
<artifactId>mysql-connector-java</artifactId> |
||||
<version>6.0.6</version> |
||||
</dependency> |
||||
<!--druid--> |
||||
<dependency> |
||||
<groupId>com.alibaba</groupId> |
||||
<artifactId>druid</artifactId> |
||||
<version>1.1.10</version> |
||||
</dependency> |
||||
<!--log4j--> |
||||
<dependency> |
||||
<groupId>log4j</groupId> |
||||
<artifactId>log4j</artifactId> |
||||
<version>1.2.17</version> |
||||
</dependency> |
||||
<!--jsckson--> |
||||
<dependency> |
||||
<groupId>com.fasterxml.jackson.core</groupId> |
||||
<artifactId>jackson-databind</artifactId> |
||||
<version>2.9.8</version> |
||||
</dependency> |
||||
<!--apache commons fileupload--> |
||||
<dependency> |
||||
<groupId>commons-fileupload</groupId> |
||||
<artifactId>commons-fileupload</artifactId> |
||||
<version>1.3.3</version> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.junit.jupiter</groupId> |
||||
<artifactId>junit-jupiter-api</artifactId> |
||||
<version>RELEASE</version> |
||||
<scope>compile</scope> |
||||
</dependency> |
||||
<!--短信--> |
||||
<dependency> |
||||
<groupId>com.github.qcloudsms</groupId> |
||||
<artifactId>qcloudsms</artifactId> |
||||
<version>1.0.6</version> |
||||
<scope>system</scope> |
||||
<systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/qcloudsms-1.0.6.jar</systemPath> |
||||
</dependency> |
||||
<!--ueditor--> |
||||
<dependency> |
||||
<groupId>com.baidu</groupId> |
||||
<artifactId>ueditor</artifactId> |
||||
<version>1.1.2</version> |
||||
<scope>system</scope> |
||||
<systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/ueditor-1.1.2.jar</systemPath> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>com.json</groupId> |
||||
<artifactId>json</artifactId> |
||||
<version>1.1.2</version> |
||||
<scope>system</scope> |
||||
<systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/json.jar</systemPath> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>com.commons</groupId> |
||||
<artifactId>codec</artifactId> |
||||
<version>1.9</version> |
||||
<scope>system</scope> |
||||
<systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/commons-codec-1.9.jar</systemPath> |
||||
</dependency> |
||||
<!--ftpclient--> |
||||
<dependency> |
||||
<groupId>commons-net</groupId> |
||||
<artifactId>commons-net</artifactId> |
||||
<version>3.3</version> |
||||
</dependency> |
||||
<!--shiro--> |
||||
<dependency> |
||||
<groupId>org.apache.shiro</groupId> |
||||
<artifactId>shiro-spring</artifactId> |
||||
<version>1.4.0</version> |
||||
</dependency> |
||||
<!--图片压缩缩略图--> |
||||
<dependency> |
||||
<groupId>net.coobird</groupId> |
||||
<artifactId>thumbnailator</artifactId> |
||||
<version>0.4.8</version> |
||||
</dependency> |
||||
</dependencies> |
||||
|
||||
<build> |
||||
<finalName>v3dmodel</finalName> |
||||
<pluginManagement> |
||||
<plugins> |
||||
<plugin> |
||||
<artifactId>maven-clean-plugin</artifactId> |
||||
<version>3.1.0</version> |
||||
</plugin> |
||||
<plugin> |
||||
<artifactId>maven-resources-plugin</artifactId> |
||||
<version>3.0.2</version> |
||||
</plugin> |
||||
<plugin> |
||||
<artifactId>maven-compiler-plugin</artifactId> |
||||
<version>3.8.0</version> |
||||
</plugin> |
||||
<plugin> |
||||
<artifactId>maven-surefire-plugin</artifactId> |
||||
<version>2.22.1</version> |
||||
</plugin> |
||||
<plugin> |
||||
<artifactId>maven-war-plugin</artifactId> |
||||
<version>3.2.2</version> |
||||
</plugin> |
||||
<plugin> |
||||
<artifactId>maven-install-plugin</artifactId> |
||||
<version>2.5.2</version> |
||||
</plugin> |
||||
<plugin> |
||||
<artifactId>maven-deploy-plugin</artifactId> |
||||
<version>2.8.2</version> |
||||
</plugin> |
||||
</plugins> |
||||
</pluginManagement> |
||||
|
||||
<plugins> |
||||
<plugin> |
||||
<groupId>org.apache.tomcat.maven</groupId> |
||||
<artifactId>tomcat7-maven-plugin</artifactId> |
||||
<version>2.2</version> |
||||
<configuration> |
||||
<uriEncoding>UTF-8</uriEncoding> |
||||
<port>80</port> |
||||
<path>/</path> |
||||
<url>http://v3d.tonkia.xyz/manager/text</url> |
||||
<update>true</update> |
||||
<username>tonkia</username> |
||||
<password>tonkia</password> |
||||
</configuration> |
||||
</plugin> |
||||
</plugins> |
||||
</build> |
||||
</project> |
@ -0,0 +1,101 @@ |
||||
package com.tonkia.v3dmodel.controller; |
||||
|
||||
import com.tonkia.v3dmodel.pojo.*; |
||||
import com.tonkia.v3dmodel.service.FileService; |
||||
import com.tonkia.v3dmodel.service.SchemeService; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Controller; |
||||
import org.springframework.web.bind.annotation.PathVariable; |
||||
import org.springframework.web.bind.annotation.RequestMapping; |
||||
import org.springframework.web.bind.annotation.ResponseBody; |
||||
import org.springframework.web.multipart.MultipartFile; |
||||
|
||||
import javax.servlet.http.HttpServletRequest; |
||||
import javax.servlet.http.HttpServletResponse; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
@Controller |
||||
@RequestMapping("file") |
||||
public class FileController { |
||||
|
||||
@Autowired |
||||
FileService fileService; |
||||
@Autowired |
||||
SchemeService schemeService; |
||||
|
||||
/** |
||||
* 上传模型 |
||||
* |
||||
* @param request |
||||
* @param files |
||||
* @param sid |
||||
* @return |
||||
*/ |
||||
@RequestMapping("uploadModel") |
||||
@ResponseBody |
||||
public ResponseData uploadModel(HttpServletRequest request, MultipartFile[] files, String sid) { |
||||
UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo"); |
||||
if (userInfo != null) { |
||||
if (schemeService.hasPermission(sid, userInfo)) { |
||||
List<FileRely> fileInfoList = fileService.insertModelFile(userInfo, sid, files); |
||||
Map data = new HashMap<>(); |
||||
data.put("uploadReply", fileInfoList); |
||||
return new ResponseData(ResponseData.SUCCEED, "文件上传成功", data); |
||||
} |
||||
return new ResponseData(ResponseData.FAILURE, "该用户没有当前方案权限", null); |
||||
} |
||||
return new ResponseData(ResponseData.FAILURE_UNLOGIN, "用户未登录", null); |
||||
} |
||||
|
||||
/** |
||||
* 上传贴图 |
||||
* |
||||
* @param request |
||||
* @param files |
||||
* @param sid |
||||
* @return |
||||
*/ |
||||
@RequestMapping("uploadTexture") |
||||
@ResponseBody |
||||
public ResponseData uploadTexture(HttpServletRequest request, MultipartFile[] files, String sid) { |
||||
UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo"); |
||||
if (userInfo != null) { |
||||
if (schemeService.hasPermission(sid, userInfo)) { |
||||
List<FileRely> fileInfoList = fileService.insertTextureFile(userInfo, sid, files); |
||||
Map data = new HashMap<>(); |
||||
data.put("uploadReply", fileInfoList); |
||||
return new ResponseData(ResponseData.SUCCEED, "文件上传成功", data); |
||||
} |
||||
return new ResponseData(ResponseData.FAILURE, "该用户没有当前方案权限", null); |
||||
} |
||||
return new ResponseData(ResponseData.FAILURE_UNLOGIN, "用户未登录", null); |
||||
} |
||||
|
||||
/** |
||||
* 资源请求 |
||||
* |
||||
* @param request |
||||
* @param response |
||||
* @param type 资源类型 |
||||
* @param sid 所属方案 |
||||
* @param fileName 文件名 |
||||
* @param size 图片压缩的大小 |
||||
*/ |
||||
//后缀名的匹配规则
|
||||
@RequestMapping("download/{type}/{sid}/{fileName:.+}") |
||||
public void download(HttpServletRequest request, HttpServletResponse response, @PathVariable("type") String type, @PathVariable("sid") String sid, @PathVariable("fileName") String fileName, Integer size) { |
||||
UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo"); |
||||
CustomerInfo customerInfo = (CustomerInfo) request.getSession().getAttribute("customerInfo"); |
||||
fileService.download(userInfo, customerInfo, type, sid, fileName, response, size); |
||||
} |
||||
|
||||
@RequestMapping("avatar/{fileName:.+}") |
||||
public void avatar(HttpServletRequest request, HttpServletResponse response, @PathVariable("fileName") String fileName) { |
||||
UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo"); |
||||
if (userInfo != null) { |
||||
fileService.avatar(userInfo.getUid(), fileName, response); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,47 @@ |
||||
package com.tonkia.v3dmodel.controller; |
||||
|
||||
import com.tonkia.v3dmodel.pojo.ResponseData; |
||||
|
||||
import com.tonkia.v3dmodel.pojo.SchemeInfo; |
||||
import com.tonkia.v3dmodel.pojo.UserInfo; |
||||
import com.tonkia.v3dmodel.service.SchemeService; |
||||
import com.tonkia.v3dmodel.service.UserService; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Controller; |
||||
import org.springframework.web.bind.annotation.RequestMapping; |
||||
import org.springframework.web.bind.annotation.ResponseBody; |
||||
|
||||
import javax.servlet.http.HttpServletRequest; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
@Controller |
||||
@RequestMapping("home") |
||||
public class HomeController { |
||||
@Autowired |
||||
UserService userService; |
||||
@Autowired |
||||
SchemeService schemeService; |
||||
|
||||
/** |
||||
* 主页信息请求 |
||||
* @param request |
||||
* @return |
||||
*/ |
||||
@RequestMapping("getHomeInfo") |
||||
@ResponseBody |
||||
public ResponseData getHomeInfo(HttpServletRequest request) { |
||||
UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo"); |
||||
if (userInfo != null) { |
||||
UserInfo ui = userService.getHomeUserInfo(userInfo.getUid()); |
||||
List<SchemeInfo> schemeList = schemeService.getHomeSchemeList(userInfo.getUid()); |
||||
Map data = new HashMap<>(); |
||||
data.put("userInfo", ui); |
||||
data.put("schemeList", schemeList); |
||||
return new ResponseData(ResponseData.SUCCEED, "主页信息获取成功", data); |
||||
} |
||||
return new ResponseData(ResponseData.FAILURE_UNLOGIN, "用户未登录", null); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,148 @@ |
||||
package com.tonkia.v3dmodel.controller; |
||||
|
||||
import com.tonkia.v3dmodel.pojo.CustomerInfo; |
||||
import com.tonkia.v3dmodel.pojo.ResponseData; |
||||
import com.tonkia.v3dmodel.pojo.SchemeInfo; |
||||
import com.tonkia.v3dmodel.pojo.UserInfo; |
||||
import com.tonkia.v3dmodel.service.FileService; |
||||
import com.tonkia.v3dmodel.service.SchemeService; |
||||
import org.apache.http.util.TextUtils; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Controller; |
||||
import org.springframework.web.bind.annotation.PathVariable; |
||||
import org.springframework.web.bind.annotation.RequestMapping; |
||||
import org.springframework.web.bind.annotation.ResponseBody; |
||||
import org.springframework.web.multipart.MultipartFile; |
||||
|
||||
import javax.servlet.http.HttpServletRequest; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
@Controller |
||||
@RequestMapping("scheme") |
||||
public class SchemeController { |
||||
@Autowired |
||||
SchemeService schemeService; |
||||
@Autowired |
||||
FileService fileService; |
||||
|
||||
/** |
||||
* 创建一个新的方案 |
||||
* |
||||
* @param request |
||||
* @param name |
||||
* @return |
||||
*/ |
||||
@RequestMapping("create") |
||||
@ResponseBody |
||||
public ResponseData create(HttpServletRequest request, String name) { |
||||
UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo"); |
||||
//对于插入操作为了安全,不能把对象暴露给前端啊,是不是?自己再封装一层,只插入name字段
|
||||
SchemeInfo schemeInfo = new SchemeInfo(); |
||||
schemeInfo.setName(name); |
||||
if (userInfo != null) { |
||||
if (!TextUtils.isEmpty(schemeInfo.getName())) { |
||||
String sid = schemeService.insertScheme(schemeInfo, userInfo); |
||||
if (sid != null) { |
||||
Map data = new HashMap<>(); |
||||
data.put("sid", sid); |
||||
return new ResponseData(ResponseData.SUCCEED, "创建方案成功", data); |
||||
} |
||||
return new ResponseData(ResponseData.FAILURE, "新建方案失败", null); |
||||
} |
||||
return new ResponseData(ResponseData.FAILURE, "方案名称不能为空", null); |
||||
} |
||||
return new ResponseData(ResponseData.FAILURE_UNLOGIN, "用户未登录", null); |
||||
} |
||||
|
||||
/** |
||||
* 保存方案 |
||||
* |
||||
* @param request |
||||
* @param schemeInfo |
||||
* @param file |
||||
* @return |
||||
*/ |
||||
@RequestMapping("save") |
||||
@ResponseBody |
||||
public ResponseData save(HttpServletRequest request, SchemeInfo schemeInfo, MultipartFile file) { |
||||
UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo"); |
||||
if (userInfo != null) { |
||||
if (!TextUtils.isEmpty(schemeInfo.getName())) { |
||||
String cover = fileService.insertCoverFile(schemeInfo.getSid(), file); |
||||
if (cover != null) { |
||||
schemeInfo.setCover(cover); |
||||
schemeInfo.setUid(userInfo.getUid()); |
||||
if (schemeService.updateScheme(schemeInfo)) { |
||||
return new ResponseData(ResponseData.SUCCEED, "保存方案成功", null); |
||||
} |
||||
return new ResponseData(ResponseData.FAILURE, "保存方案失败", null); |
||||
} |
||||
return new ResponseData(ResponseData.FAILURE, "缩略图上传失败", null); |
||||
} |
||||
return new ResponseData(ResponseData.FAILURE, "方案名称不能为空", null); |
||||
} |
||||
return new ResponseData(ResponseData.FAILURE_UNLOGIN, "用户未登录", null); |
||||
} |
||||
|
||||
/** |
||||
* 获取方案 |
||||
* |
||||
* @param request |
||||
* @param sid |
||||
* @return |
||||
*/ |
||||
@RequestMapping("/{sid}") |
||||
@ResponseBody |
||||
public ResponseData getSchemeInfo(HttpServletRequest request, @PathVariable("sid") String sid) { |
||||
int share = schemeService.getShareBySid(sid); |
||||
UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo"); |
||||
CustomerInfo customerInfo = (CustomerInfo) request.getSession().getAttribute("customerInfo"); |
||||
if (userInfo != null) { |
||||
SchemeInfo schemeInfo = schemeService.getSchemeInfo(userInfo.getUid(), sid); |
||||
if (schemeInfo != null) { |
||||
return new ResponseData(ResponseData.SUCCEED, "方案数据获取成功", schemeInfo); |
||||
} |
||||
} |
||||
if (share == 1) { |
||||
SchemeInfo schemeInfo = schemeService.getSchemeInfo(sid); |
||||
if (schemeInfo != null) { |
||||
return new ResponseData(ResponseData.SUCCEED, "方案数据获取成功", schemeInfo); |
||||
} |
||||
} else if (share == 2 && customerInfo != null && customerInfo.getSid().equals(sid)) { |
||||
SchemeInfo schemeInfo = schemeService.getSchemeInfo(sid); |
||||
if (schemeInfo != null) { |
||||
return new ResponseData(ResponseData.SUCCEED, "方案数据获取成功", schemeInfo); |
||||
} |
||||
} |
||||
return new ResponseData(ResponseData.FAILURE, "方案数据获取失败", null); |
||||
} |
||||
|
||||
@RequestMapping("/share") |
||||
@ResponseBody |
||||
public ResponseData share(HttpServletRequest request, SchemeInfo schemeInfo) { |
||||
UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo"); |
||||
if (userInfo != null) { |
||||
schemeInfo.setUid(userInfo.getUid()); |
||||
if (schemeService.updateShareInfo(schemeInfo)) { |
||||
return new ResponseData(ResponseData.SUCCEED, "更新分享数据成功", null); |
||||
} |
||||
return new ResponseData(ResponseData.FAILURE, "更新分享数据失败", null); |
||||
} |
||||
return new ResponseData(ResponseData.FAILURE_UNLOGIN, "用户未登录", null); |
||||
} |
||||
|
||||
@RequestMapping("/delete") |
||||
@ResponseBody |
||||
public ResponseData delete(HttpServletRequest request, String sid) { |
||||
UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo"); |
||||
if (userInfo != null) { |
||||
if (schemeService.deleteScheme(userInfo.getUid(), sid)) { |
||||
return new ResponseData(ResponseData.SUCCEED, "删除方案成功", null); |
||||
} |
||||
return new ResponseData(ResponseData.FAILURE, "删除方案失败", null); |
||||
} |
||||
return new ResponseData(ResponseData.FAILURE_UNLOGIN, "用户未登录", null); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,97 @@ |
||||
package com.tonkia.v3dmodel.controller; |
||||
|
||||
import com.tonkia.v3dmodel.pojo.*; |
||||
import com.tonkia.v3dmodel.service.CommentService; |
||||
import com.tonkia.v3dmodel.service.SchemeService; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Controller; |
||||
import org.springframework.web.bind.annotation.PathVariable; |
||||
import org.springframework.web.bind.annotation.RequestMapping; |
||||
import org.springframework.web.bind.annotation.ResponseBody; |
||||
|
||||
import javax.servlet.http.HttpServletRequest; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
@Controller |
||||
@RequestMapping("show") |
||||
public class ShowController { |
||||
@Autowired |
||||
SchemeService schemeService; |
||||
@Autowired |
||||
CommentService commentService; |
||||
|
||||
@RequestMapping("/{sid}") |
||||
@ResponseBody |
||||
public ResponseData getShareType(@PathVariable("sid") String sid) { |
||||
Integer code = schemeService.getShareBySid(sid); |
||||
if (code != null) { |
||||
Map data = new HashMap<>(); |
||||
data.put("share", code); |
||||
return new ResponseData(ResponseData.SUCCEED, "获取方案分享类型成功", data); |
||||
} |
||||
return new ResponseData(ResponseData.FAILURE, "获取方案分享类型失败", null); |
||||
} |
||||
|
||||
@RequestMapping("customer") |
||||
@ResponseBody |
||||
public ResponseData customer(HttpServletRequest request, String sid, String password) { |
||||
if (schemeService.getCustomer(sid, password)) { |
||||
CustomerInfo customerInfo = new CustomerInfo(); |
||||
customerInfo.setSid(sid); |
||||
request.getSession().setAttribute("customerInfo", customerInfo); |
||||
return new ResponseData(ResponseData.SUCCEED, "密码有效", null); |
||||
} |
||||
return new ResponseData(ResponseData.FAILURE, "验证无效", null); |
||||
} |
||||
|
||||
@RequestMapping("getComment") |
||||
@ResponseBody |
||||
public ResponseData getComment(HttpServletRequest request, String sid) { |
||||
int share = schemeService.getShareBySid(sid); |
||||
UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo"); |
||||
CustomerInfo customerInfo = (CustomerInfo) request.getSession().getAttribute("customerInfo"); |
||||
if (userInfo != null && schemeService.hasPermission(sid, userInfo)) { |
||||
List<CommentInfo> list = commentService.getAllComment(sid); |
||||
if (list != null) { |
||||
return new ResponseData(ResponseData.SUCCEED, "方案评论获取成功", list); |
||||
} |
||||
} |
||||
if (share == 1) { |
||||
List<CommentInfo> list = commentService.getAllComment(sid); |
||||
if (list != null) { |
||||
return new ResponseData(ResponseData.SUCCEED, "方案评论获取成功", list); |
||||
} |
||||
} else if (share == 2 && customerInfo != null && customerInfo.getSid().equals(sid)) { |
||||
List<CommentInfo> list = commentService.getAllComment(sid); |
||||
if (list != null) { |
||||
return new ResponseData(ResponseData.SUCCEED, "方案评论获取成功", list); |
||||
} |
||||
} |
||||
return new ResponseData(ResponseData.FAILURE, "方案评论获取失败", null); |
||||
} |
||||
|
||||
@RequestMapping("comment") |
||||
@ResponseBody |
||||
public ResponseData comment(HttpServletRequest request, String sid,String text) { |
||||
int share = schemeService.getShareBySid(sid); |
||||
UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo"); |
||||
CustomerInfo customerInfo = (CustomerInfo) request.getSession().getAttribute("customerInfo"); |
||||
if (userInfo != null && schemeService.hasPermission(sid, userInfo)) { |
||||
if (commentService.insertComment(sid,text)) { |
||||
return new ResponseData(ResponseData.SUCCEED, "方案评论成功", null); |
||||
} |
||||
} |
||||
if (share == 1) { |
||||
if (commentService.insertComment(sid,text)) { |
||||
return new ResponseData(ResponseData.SUCCEED, "方案评论成功", null); |
||||
} |
||||
} else if (share == 2 && customerInfo != null && customerInfo.getSid().equals(sid)) { |
||||
if (commentService.insertComment(sid,text)) { |
||||
return new ResponseData(ResponseData.SUCCEED, "方案评论成功", null); |
||||
} |
||||
} |
||||
return new ResponseData(ResponseData.FAILURE, "方案评论失败", null); |
||||
} |
||||
} |
@ -0,0 +1,93 @@ |
||||
package com.tonkia.v3dmodel.controller; |
||||
|
||||
import com.tonkia.v3dmodel.pojo.ResponseData; |
||||
import com.tonkia.v3dmodel.pojo.UserInfo; |
||||
import com.tonkia.v3dmodel.service.FileService; |
||||
import com.tonkia.v3dmodel.service.UserService; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Controller; |
||||
import org.springframework.web.bind.annotation.RequestMapping; |
||||
import org.springframework.web.bind.annotation.ResponseBody; |
||||
import org.springframework.web.multipart.MultipartFile; |
||||
|
||||
import javax.servlet.http.HttpServletRequest; |
||||
import java.io.File; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
@Controller |
||||
@RequestMapping("user") |
||||
public class UserController { |
||||
|
||||
@Autowired |
||||
UserService userService; |
||||
@Autowired |
||||
FileService fileService; |
||||
|
||||
//验证登录
|
||||
@RequestMapping("hasLogin") |
||||
@ResponseBody |
||||
public ResponseData hasLogin(HttpServletRequest request) { |
||||
UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo"); |
||||
if (userInfo != null) { |
||||
return new ResponseData(ResponseData.SUCCEED, "登录成功", null); |
||||
} |
||||
return new ResponseData(ResponseData.FAILURE_UNLOGIN, "用户未登录", null); |
||||
} |
||||
|
||||
//登录请求
|
||||
@RequestMapping("login") |
||||
@ResponseBody |
||||
public ResponseData login(HttpServletRequest request, UserInfo userInfo) { |
||||
UserInfo ui = userService.getUserInfo(userInfo); |
||||
if (ui == null) { |
||||
//用户不存在
|
||||
return new ResponseData(ResponseData.FAILURE, "用户不存在", null); |
||||
} |
||||
if (!ui.getPassword().equals(userInfo.getPassword())) { |
||||
//密码错误
|
||||
return new ResponseData(ResponseData.FAILURE, "密码错误", null); |
||||
} |
||||
request.getSession().setAttribute("userInfo", ui); |
||||
return new ResponseData(ResponseData.SUCCEED, "登录成功", null); |
||||
} |
||||
|
||||
//用户注销
|
||||
@RequestMapping("logout") |
||||
@ResponseBody |
||||
public ResponseData logout(HttpServletRequest request) { |
||||
request.getSession().setAttribute("userInfo", null); |
||||
return new ResponseData(ResponseData.SUCCEED, "注销成功", null); |
||||
} |
||||
|
||||
//修改头像
|
||||
@RequestMapping("avatar") |
||||
@ResponseBody |
||||
public ResponseData avatar(HttpServletRequest request, MultipartFile file) { |
||||
UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo"); |
||||
if (userInfo != null) { |
||||
String path = fileService.uploadAvatar(userInfo.getUid(), file); |
||||
if (userService.updateAvatar(userInfo.getUid(), path)) { |
||||
Map data = new HashMap(); |
||||
data.put("avatar", path); |
||||
return new ResponseData(ResponseData.SUCCEED, "头像修改成功", data); |
||||
} |
||||
return new ResponseData(ResponseData.FAILURE, "头像修改失败", null); |
||||
} |
||||
return new ResponseData(ResponseData.FAILURE_UNLOGIN, "用户未登录", null); |
||||
} |
||||
|
||||
//修改头像
|
||||
@RequestMapping("changeInfo") |
||||
@ResponseBody |
||||
public ResponseData changeInfo(HttpServletRequest request, String userName, String password) { |
||||
UserInfo userInfo = (UserInfo) request.getSession().getAttribute("userInfo"); |
||||
if (userInfo != null) { |
||||
if (userService.updateInfo(userInfo.getUid(),userName,password)) { |
||||
return new ResponseData(ResponseData.SUCCEED, "用户信息修改成功", null); |
||||
} |
||||
return new ResponseData(ResponseData.FAILURE, "用户信息修改失败", null); |
||||
} |
||||
return new ResponseData(ResponseData.FAILURE_UNLOGIN, "用户未登录", null); |
||||
} |
||||
} |
@ -0,0 +1,16 @@ |
||||
package com.tonkia.v3dmodel.mapper; |
||||
|
||||
import com.tonkia.v3dmodel.pojo.CommentInfo; |
||||
import org.apache.ibatis.annotations.Insert; |
||||
import org.apache.ibatis.annotations.Select; |
||||
|
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
public interface CommentMapper { |
||||
@Select("select text,time from tb_comment where sid = #{sid} order by time desc") |
||||
List<CommentInfo> getAllComment(String sid); |
||||
|
||||
@Insert("insert into tb_comment(text,sid) values (#{text},#{sid})") |
||||
boolean insertComment(Map para); |
||||
} |
@ -0,0 +1,9 @@ |
||||
package com.tonkia.v3dmodel.mapper; |
||||
|
||||
import com.tonkia.v3dmodel.pojo.FileInfo; |
||||
import org.apache.ibatis.annotations.Insert; |
||||
|
||||
public interface FileMapper { |
||||
@Insert("insert into tb_file(fid,uid,sid,type,path,name) values(#{fid},#{uid},#{sid},#{type},#{path},#{name})") |
||||
boolean insertFile(FileInfo fi); |
||||
} |
@ -0,0 +1,42 @@ |
||||
package com.tonkia.v3dmodel.mapper; |
||||
|
||||
import com.tonkia.v3dmodel.pojo.SchemeInfo; |
||||
import org.apache.ibatis.annotations.Delete; |
||||
import org.apache.ibatis.annotations.Insert; |
||||
import org.apache.ibatis.annotations.Select; |
||||
import org.apache.ibatis.annotations.Update; |
||||
|
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
public interface SchemeMapper { |
||||
@Insert("insert into tb_scheme(sid,uid,name,createTime) values(#{sid},#{uid},#{name},#{createTime})") |
||||
boolean insertScheme(SchemeInfo schemeInfo); |
||||
|
||||
@Select("select sid,name,cover,share,password from tb_scheme where uid = #{0} and state = 0 order by createTime desc") |
||||
List<SchemeInfo> getHomeSchemeList(Integer uid); |
||||
|
||||
@Select("select count(*) from tb_scheme where uid = #{uid} and sid = #{sid}") |
||||
int hasPermission(Map para); |
||||
|
||||
@Update("update tb_scheme set name=#{name},cover=#{cover},data=#{data},camera=#{camera} where uid = #{uid} and sid = #{sid}") |
||||
boolean updateScheme(SchemeInfo schemeInfo); |
||||
|
||||
@Select("select name,data,camera,share,password from tb_scheme where uid = #{uid} and sid = #{sid}") |
||||
SchemeInfo getSchemeInfo(Map para); |
||||
|
||||
@Update("update tb_scheme set share = #{share} ,password = #{password} where uid = #{uid} and sid = #{sid}") |
||||
boolean updateShareInfo(SchemeInfo schemeInfo); |
||||
|
||||
@Select("select share from tb_scheme where sid = #{sid}") |
||||
Integer getShareBySid(String sid); |
||||
|
||||
@Select("select name,data,camera from tb_scheme where sid = #{sid}") |
||||
SchemeInfo getSchemeInfoBySid(String sid); |
||||
|
||||
@Select("select count(*) from tb_scheme where sid = #{sid} and password = #{password} and share = 2") |
||||
int getCustomer(Map para); |
||||
|
||||
@Delete("delete from tb_scheme where sid = #{sid} and uid = #{uid}") |
||||
boolean deleteScheme(Map para); |
||||
} |
@ -0,0 +1,24 @@ |
||||
package com.tonkia.v3dmodel.mapper; |
||||
|
||||
import com.tonkia.v3dmodel.pojo.UserInfo; |
||||
import org.apache.ibatis.annotations.Select; |
||||
import org.apache.ibatis.annotations.Update; |
||||
|
||||
import java.util.Map; |
||||
|
||||
public interface UserMapper { |
||||
@Select("select * from tb_user where phoneNumber = #{phoneNumber}") |
||||
UserInfo getUserInfo(UserInfo userInfo); |
||||
|
||||
@Select("select userName, avatar from tb_user where uid = #{uid}") |
||||
UserInfo getHomeUserInfo(Integer uid); |
||||
|
||||
@Update("update tb_user set avatar =#{avatar} where uid = #{uid} ") |
||||
boolean updateAvatar(Map para); |
||||
|
||||
@Update("update tb_user set userName =#{userName} where uid = #{uid} ") |
||||
boolean updateUserName(Map para); |
||||
|
||||
@Update("update tb_user set password =#{password} where uid = #{uid} ") |
||||
boolean updatePassword(Map para); |
||||
} |
@ -0,0 +1,24 @@ |
||||
package com.tonkia.v3dmodel.pojo; |
||||
|
||||
import java.util.Date; |
||||
|
||||
public class CommentInfo { |
||||
private String text; |
||||
private Date time; |
||||
|
||||
public String getText() { |
||||
return text; |
||||
} |
||||
|
||||
public void setText(String text) { |
||||
this.text = text; |
||||
} |
||||
|
||||
public Date getTime() { |
||||
return time; |
||||
} |
||||
|
||||
public void setTime(Date time) { |
||||
this.time = time; |
||||
} |
||||
} |
@ -0,0 +1,13 @@ |
||||
package com.tonkia.v3dmodel.pojo; |
||||
|
||||
public class CustomerInfo { |
||||
private String sid; |
||||
|
||||
public String getSid() { |
||||
return sid; |
||||
} |
||||
|
||||
public void setSid(String sid) { |
||||
this.sid = sid; |
||||
} |
||||
} |
@ -0,0 +1,78 @@ |
||||
package com.tonkia.v3dmodel.pojo; |
||||
|
||||
import java.util.Date; |
||||
|
||||
public class FileInfo { |
||||
private String fid; |
||||
private String sid; |
||||
private Integer uid; |
||||
private String name; |
||||
private String path; |
||||
private Date uploadTime; |
||||
private Integer state; |
||||
private String type; |
||||
|
||||
public String getType() { |
||||
return type; |
||||
} |
||||
|
||||
public void setType(String type) { |
||||
this.type = type; |
||||
} |
||||
|
||||
public String getFid() { |
||||
return fid; |
||||
} |
||||
|
||||
public void setFid(String fid) { |
||||
this.fid = fid; |
||||
} |
||||
|
||||
public String getSid() { |
||||
return sid; |
||||
} |
||||
|
||||
public void setSid(String sid) { |
||||
this.sid = sid; |
||||
} |
||||
|
||||
public Integer getUid() { |
||||
return uid; |
||||
} |
||||
|
||||
public void setUid(Integer uid) { |
||||
this.uid = uid; |
||||
} |
||||
|
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
public void setName(String name) { |
||||
this.name = name; |
||||
} |
||||
|
||||
public String getPath() { |
||||
return path; |
||||
} |
||||
|
||||
public void setPath(String path) { |
||||
this.path = path; |
||||
} |
||||
|
||||
public Date getUploadTime() { |
||||
return uploadTime; |
||||
} |
||||
|
||||
public void setUploadTime(Date uploadTime) { |
||||
this.uploadTime = uploadTime; |
||||
} |
||||
|
||||
public Integer getState() { |
||||
return state; |
||||
} |
||||
|
||||
public void setState(Integer state) { |
||||
this.state = state; |
||||
} |
||||
} |
@ -0,0 +1,31 @@ |
||||
package com.tonkia.v3dmodel.pojo; |
||||
|
||||
public class FileRely { |
||||
private String fid; |
||||
private String name; |
||||
private String path; |
||||
|
||||
public String getFid() { |
||||
return fid; |
||||
} |
||||
|
||||
public void setFid(String fid) { |
||||
this.fid = fid; |
||||
} |
||||
|
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
public void setName(String name) { |
||||
this.name = name; |
||||
} |
||||
|
||||
public String getPath() { |
||||
return path; |
||||
} |
||||
|
||||
public void setPath(String path) { |
||||
this.path = path; |
||||
} |
||||
} |
@ -0,0 +1,43 @@ |
||||
package com.tonkia.v3dmodel.pojo; |
||||
|
||||
public class ResponseData { |
||||
//code编码
|
||||
public static int SUCCEED=0; |
||||
public static int FAILURE=1; |
||||
public static int FAILURE_UNLOGIN=2; |
||||
|
||||
//返回格式
|
||||
private int code; |
||||
private String msg; |
||||
private Object data; |
||||
|
||||
public int getCode() { |
||||
return code; |
||||
} |
||||
|
||||
public void setCode(int code) { |
||||
this.code = code; |
||||
} |
||||
|
||||
public String getMsg() { |
||||
return msg; |
||||
} |
||||
|
||||
public void setMsg(String msg) { |
||||
this.msg = msg; |
||||
} |
||||
|
||||
public Object getData() { |
||||
return data; |
||||
} |
||||
|
||||
public void setData(Object data) { |
||||
this.data = data; |
||||
} |
||||
|
||||
public ResponseData(int code, String msg, Object data) { |
||||
this.code = code; |
||||
this.msg = msg; |
||||
this.data = data; |
||||
} |
||||
} |
@ -0,0 +1,105 @@ |
||||
package com.tonkia.v3dmodel.pojo; |
||||
|
||||
import java.util.Date; |
||||
|
||||
public class SchemeInfo { |
||||
private String sid; |
||||
private Integer uid; |
||||
private String name; |
||||
private String cover; |
||||
private Integer state; |
||||
private Date createTime; |
||||
private Object data; |
||||
private Object camera; |
||||
private Integer share; |
||||
private String password; |
||||
private String shareLink; |
||||
|
||||
public String getSid() { |
||||
return sid; |
||||
} |
||||
|
||||
public void setSid(String sid) { |
||||
this.sid = sid; |
||||
} |
||||
|
||||
public Integer getUid() { |
||||
return uid; |
||||
} |
||||
|
||||
public void setUid(Integer uid) { |
||||
this.uid = uid; |
||||
} |
||||
|
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
public void setName(String name) { |
||||
this.name = name; |
||||
} |
||||
|
||||
public String getCover() { |
||||
return cover; |
||||
} |
||||
|
||||
public void setCover(String cover) { |
||||
this.cover = cover; |
||||
} |
||||
|
||||
public Integer getState() { |
||||
return state; |
||||
} |
||||
|
||||
public void setState(Integer state) { |
||||
this.state = state; |
||||
} |
||||
|
||||
public Date getCreateTime() { |
||||
return createTime; |
||||
} |
||||
|
||||
public void setCreateTime(Date createTime) { |
||||
this.createTime = createTime; |
||||
} |
||||
|
||||
public Object getData() { |
||||
return data; |
||||
} |
||||
|
||||
public void setData(Object data) { |
||||
this.data = data; |
||||
} |
||||
|
||||
public Object getCamera() { |
||||
return camera; |
||||
} |
||||
|
||||
public void setCamera(Object camera) { |
||||
this.camera = camera; |
||||
} |
||||
|
||||
public Integer getShare() { |
||||
return share; |
||||
} |
||||
|
||||
public void setShare(Integer share) { |
||||
this.share = share; |
||||
} |
||||
|
||||
public String getPassword() { |
||||
return password; |
||||
} |
||||
|
||||
public void setPassword(String password) { |
||||
this.password = password; |
||||
} |
||||
|
||||
public String getShareLink() { |
||||
return shareLink; |
||||
} |
||||
|
||||
public void setShareLink(String shareLink) { |
||||
this.shareLink = shareLink; |
||||
} |
||||
} |
@ -0,0 +1,69 @@ |
||||
package com.tonkia.v3dmodel.pojo; |
||||
|
||||
import java.util.Date; |
||||
|
||||
public class UserInfo { |
||||
private Integer uid; |
||||
private String phoneNumber; |
||||
private String userName; |
||||
private String password; |
||||
private Integer state; |
||||
private Date regTime; |
||||
private String avatar; |
||||
|
||||
public Integer getUid() { |
||||
return uid; |
||||
} |
||||
|
||||
public void setUid(Integer uid) { |
||||
this.uid = uid; |
||||
} |
||||
|
||||
public String getPhoneNumber() { |
||||
return phoneNumber; |
||||
} |
||||
|
||||
public void setPhoneNumber(String phoneNumber) { |
||||
this.phoneNumber = phoneNumber; |
||||
} |
||||
|
||||
public String getUserName() { |
||||
return userName; |
||||
} |
||||
|
||||
public void setUserName(String userName) { |
||||
this.userName = userName; |
||||
} |
||||
|
||||
public String getPassword() { |
||||
return password; |
||||
} |
||||
|
||||
public void setPassword(String password) { |
||||
this.password = password; |
||||
} |
||||
|
||||
public Integer getState() { |
||||
return state; |
||||
} |
||||
|
||||
public void setState(Integer state) { |
||||
this.state = state; |
||||
} |
||||
|
||||
public Date getRegTime() { |
||||
return regTime; |
||||
} |
||||
|
||||
public void setRegTime(Date regTime) { |
||||
this.regTime = regTime; |
||||
} |
||||
|
||||
public String getAvatar() { |
||||
return avatar; |
||||
} |
||||
|
||||
public void setAvatar(String avatar) { |
||||
this.avatar = avatar; |
||||
} |
||||
} |
@ -0,0 +1,11 @@ |
||||
package com.tonkia.v3dmodel.service; |
||||
|
||||
import com.tonkia.v3dmodel.pojo.CommentInfo; |
||||
|
||||
import java.util.List; |
||||
|
||||
public interface CommentService { |
||||
List<CommentInfo> getAllComment(String sid); |
||||
|
||||
boolean insertComment(String sid, String text); |
||||
} |
@ -0,0 +1,25 @@ |
||||
package com.tonkia.v3dmodel.service; |
||||
|
||||
import com.tonkia.v3dmodel.pojo.CustomerInfo; |
||||
import com.tonkia.v3dmodel.pojo.FileInfo; |
||||
import com.tonkia.v3dmodel.pojo.FileRely; |
||||
import com.tonkia.v3dmodel.pojo.UserInfo; |
||||
import org.springframework.web.multipart.MultipartFile; |
||||
|
||||
import javax.servlet.http.HttpServletResponse; |
||||
import java.io.OutputStream; |
||||
import java.util.List; |
||||
|
||||
public interface FileService { |
||||
void download(UserInfo userInfo, CustomerInfo customerInfo, String type, String sid, String fileName, HttpServletResponse response, Integer size); |
||||
|
||||
List<FileRely> insertModelFile(UserInfo userInfo, String sid, MultipartFile[] files); |
||||
|
||||
List<FileRely> insertTextureFile(UserInfo userInfo, String sid, MultipartFile[] files); |
||||
|
||||
String insertCoverFile(String sid,MultipartFile file); |
||||
|
||||
String uploadAvatar(int uid ,MultipartFile file); |
||||
|
||||
void avatar(Integer uid, String fileName, HttpServletResponse response); |
||||
} |
@ -0,0 +1,29 @@ |
||||
package com.tonkia.v3dmodel.service; |
||||
|
||||
import com.tonkia.v3dmodel.pojo.SchemeInfo; |
||||
import com.tonkia.v3dmodel.pojo.UserInfo; |
||||
import org.springframework.web.multipart.MultipartFile; |
||||
|
||||
import java.util.List; |
||||
|
||||
public interface SchemeService { |
||||
String insertScheme(SchemeInfo schemeInfo, UserInfo userInfo); |
||||
|
||||
List<SchemeInfo> getHomeSchemeList(Integer uid); |
||||
|
||||
boolean hasPermission(String sid, UserInfo userInfo); |
||||
|
||||
boolean updateScheme(SchemeInfo schemeInfo); |
||||
|
||||
SchemeInfo getSchemeInfo(Integer uid, String sid); |
||||
|
||||
boolean updateShareInfo(SchemeInfo schemeInfo); |
||||
|
||||
Integer getShareBySid(String sid); |
||||
|
||||
SchemeInfo getSchemeInfo(String sid); |
||||
|
||||
boolean getCustomer(String sid, String password); |
||||
|
||||
boolean deleteScheme(Integer uid, String sid); |
||||
} |
@ -0,0 +1,13 @@ |
||||
package com.tonkia.v3dmodel.service; |
||||
|
||||
import com.tonkia.v3dmodel.pojo.UserInfo; |
||||
|
||||
public interface UserService { |
||||
UserInfo getUserInfo(UserInfo userInfo); |
||||
|
||||
UserInfo getHomeUserInfo(Integer uid); |
||||
|
||||
boolean updateAvatar(Integer uid, String path); |
||||
|
||||
boolean updateInfo(Integer uid, String userName, String password); |
||||
} |
@ -0,0 +1,31 @@ |
||||
package com.tonkia.v3dmodel.service.impl; |
||||
|
||||
import com.tonkia.v3dmodel.mapper.CommentMapper; |
||||
import com.tonkia.v3dmodel.pojo.CommentInfo; |
||||
import com.tonkia.v3dmodel.service.CommentService; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
import javax.xml.stream.events.Comment; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
@Service |
||||
public class CommentServiceImpl implements CommentService { |
||||
@Autowired |
||||
CommentMapper commentMapper; |
||||
|
||||
@Override |
||||
public List<CommentInfo> getAllComment(String sid) { |
||||
return commentMapper.getAllComment(sid); |
||||
} |
||||
|
||||
@Override |
||||
public boolean insertComment(String sid, String text) { |
||||
Map para = new HashMap<>(); |
||||
para.put("sid", sid); |
||||
para.put("text", text); |
||||
return commentMapper.insertComment(para); |
||||
} |
||||
} |
@ -0,0 +1,196 @@ |
||||
package com.tonkia.v3dmodel.service.impl; |
||||
|
||||
import com.tonkia.v3dmodel.mapper.FileMapper; |
||||
import com.tonkia.v3dmodel.mapper.SchemeMapper; |
||||
import com.tonkia.v3dmodel.pojo.CustomerInfo; |
||||
import com.tonkia.v3dmodel.pojo.FileInfo; |
||||
import com.tonkia.v3dmodel.pojo.FileRely; |
||||
import com.tonkia.v3dmodel.pojo.UserInfo; |
||||
import com.tonkia.v3dmodel.service.FileService; |
||||
import com.tonkia.v3dmodel.utils.FtpUtil; |
||||
import com.tonkia.v3dmodel.utils.ThumbUtil; |
||||
import com.tonkia.v3dmodel.utils.UUIDUtil; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.beans.factory.annotation.Value; |
||||
import org.springframework.stereotype.Service; |
||||
import org.springframework.web.multipart.MultipartFile; |
||||
|
||||
import javax.servlet.http.HttpServletResponse; |
||||
import java.io.*; |
||||
import java.util.ArrayList; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
@Service |
||||
public class FileServiceImpl implements FileService { |
||||
@Autowired |
||||
FileMapper fileMapper; |
||||
@Autowired |
||||
SchemeMapper schemeMapper; |
||||
|
||||
@Value("${ftpclient.host}") |
||||
private String host; |
||||
@Value("${ftpclient.port}") |
||||
private int port; |
||||
@Value("${ftpclient.username}") |
||||
private String username; |
||||
@Value("${ftpclient.password}") |
||||
private String password; |
||||
@Value("${ftpclient.basePath}") |
||||
private String basePath; |
||||
@Value("${ftpclient.filePath}") |
||||
private String filePath; |
||||
@Value("${ftpclient.downloadPathPrefix}") |
||||
private String downloadPathPrefix; |
||||
|
||||
@Override |
||||
public List<FileRely> insertModelFile(UserInfo userInfo, String sid, MultipartFile[] files) { |
||||
int uid = userInfo.getUid(); |
||||
List<FileRely> list = new ArrayList<>(); |
||||
for (MultipartFile file : files) { |
||||
//判断是否是 .obj 或者 .fbx
|
||||
String subfix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf('.')); |
||||
if (subfix.toLowerCase().equals(".obj") || subfix.toLowerCase().equals(".fbx")) { |
||||
String fileName = UUIDUtil.generate() + subfix; |
||||
boolean isSucceed = false; |
||||
try { |
||||
isSucceed = FtpUtil.uploadFile(host, port, username, password, basePath, filePath + "/models/" + sid, fileName, file.getInputStream()); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
if (isSucceed) { |
||||
FileRely fr = new FileRely(); |
||||
FileInfo fi = new FileInfo(); |
||||
String name = file.getOriginalFilename().substring(0, file.getOriginalFilename().lastIndexOf('.')); |
||||
String fid = UUIDUtil.generate(); |
||||
String path = downloadPathPrefix + "/models/" + sid + "/" + fileName; |
||||
fi.setFid(fid); |
||||
fi.setUid(uid); |
||||
fi.setSid(sid); |
||||
fi.setName(name); |
||||
fi.setPath(path); |
||||
fi.setType(file.getContentType()); |
||||
if (fileMapper.insertFile(fi)) { |
||||
fr.setFid(fid); |
||||
fr.setName(name); |
||||
fr.setPath(path); |
||||
list.add(fr); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return list; |
||||
} |
||||
|
||||
@Override |
||||
public List<FileRely> insertTextureFile(UserInfo userInfo, String sid, MultipartFile[] files) { |
||||
int uid = userInfo.getUid(); |
||||
List<FileRely> list = new ArrayList<>(); |
||||
for (MultipartFile file : files) { |
||||
//判断是否是 .jpg 或者 .png
|
||||
String subfix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf('.')); |
||||
if (subfix.toLowerCase().equals(".jpg") || subfix.toLowerCase().equals(".png")) { |
||||
String fileName = UUIDUtil.generate() + subfix; |
||||
boolean isSucceed = false; |
||||
try { |
||||
isSucceed = FtpUtil.uploadFile(host, port, username, password, basePath, filePath + "/textures/" + sid, fileName, file.getInputStream()); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
if (isSucceed) { |
||||
FileRely fr = new FileRely(); |
||||
FileInfo fi = new FileInfo(); |
||||
String name = file.getOriginalFilename().substring(0, file.getOriginalFilename().lastIndexOf('.')); |
||||
String fid = UUIDUtil.generate(); |
||||
String path = downloadPathPrefix + "/textures/" + sid + "/" + fileName; |
||||
fi.setFid(fid); |
||||
fi.setUid(uid); |
||||
fi.setSid(sid); |
||||
fi.setName(name); |
||||
fi.setPath(path); |
||||
fi.setType(file.getContentType()); |
||||
if (fileMapper.insertFile(fi)) { |
||||
fr.setFid(fid); |
||||
fr.setName(name); |
||||
fr.setPath(path); |
||||
list.add(fr); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return list; |
||||
} |
||||
|
||||
@Override |
||||
public String insertCoverFile(String sid, MultipartFile file) { |
||||
|
||||
String subfix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf('.')); |
||||
String fileName = UUIDUtil.generate() + subfix; |
||||
boolean isSucceed = false; |
||||
try { |
||||
isSucceed = FtpUtil.uploadFile(host, port, username, password, basePath, filePath + "/cover/" + sid, fileName, file.getInputStream()); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
if (isSucceed) { |
||||
String path = downloadPathPrefix + "/cover/" + sid + "/" + fileName; |
||||
return path; |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public String uploadAvatar(int uid, MultipartFile file) { |
||||
String fileName = UUIDUtil.generate(); |
||||
boolean isSucceed = false; |
||||
try { |
||||
isSucceed = FtpUtil.uploadFile(host, port, username, password, basePath, filePath + "/avatar/" + uid, fileName, file.getInputStream()); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
if (isSucceed) { |
||||
String path = "/file/avatar/" + fileName; |
||||
return path; |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public void avatar(Integer uid, String fileName, HttpServletResponse response) { |
||||
FtpUtil.downloadFileWithProgress(host, port, username, password, basePath + filePath + "/avatar/" + uid, fileName, response); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void download(UserInfo userInfo, CustomerInfo customerInfo, String type, String sid, String fileName, HttpServletResponse response, Integer size) { |
||||
boolean hasRight = false; |
||||
int share = schemeMapper.getShareBySid(sid); |
||||
if (share == 1) { |
||||
hasRight = true; |
||||
} else if (userInfo != null) { |
||||
Map para = new HashMap<>(); |
||||
para.put("uid", userInfo.getUid()); |
||||
para.put("sid", sid); |
||||
hasRight = schemeMapper.hasPermission(para) > 0; |
||||
} else if (share == 2 && customerInfo != null && customerInfo.getSid().equals(sid)) { |
||||
hasRight = customerInfo.getSid().equals(sid); |
||||
} |
||||
if (hasRight) { |
||||
try { |
||||
if (size == null) |
||||
FtpUtil.downloadFileWithProgress(host, port, username, password, basePath + filePath + "/" + type + "/" + sid, fileName, response); |
||||
else { |
||||
//如果指定了size返回压缩缩略图
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
||||
FtpUtil.downloadFile(host, port, username, password, basePath + filePath + "/" + type + "/" + sid, fileName, baos); |
||||
ByteArrayInputStream swapStream = new ByteArrayInputStream(baos.toByteArray()); |
||||
ThumbUtil.thumb(swapStream, response.getOutputStream(), size); |
||||
} |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,101 @@ |
||||
package com.tonkia.v3dmodel.service.impl; |
||||
|
||||
import com.tonkia.v3dmodel.mapper.SchemeMapper; |
||||
import com.tonkia.v3dmodel.pojo.SchemeInfo; |
||||
import com.tonkia.v3dmodel.pojo.UserInfo; |
||||
import com.tonkia.v3dmodel.service.SchemeService; |
||||
import com.tonkia.v3dmodel.utils.UUIDUtil; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.beans.factory.annotation.Value; |
||||
import org.springframework.stereotype.Service; |
||||
import org.springframework.web.multipart.MultipartFile; |
||||
|
||||
import java.util.Date; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
|
||||
@Service |
||||
public class SchemeServiceImpl implements SchemeService { |
||||
|
||||
@Autowired |
||||
SchemeMapper schemeMapper; |
||||
@Value("${shareLink.prefix}") |
||||
String shareLinkPrefix; |
||||
|
||||
@Override |
||||
public String insertScheme(SchemeInfo schemeInfo, UserInfo userInfo) { |
||||
String sid = UUIDUtil.generate(); |
||||
schemeInfo.setSid(sid); |
||||
schemeInfo.setCreateTime(new Date()); |
||||
schemeInfo.setUid(userInfo.getUid()); |
||||
return schemeMapper.insertScheme(schemeInfo) ? sid : null; |
||||
} |
||||
|
||||
@Override |
||||
public List<SchemeInfo> getHomeSchemeList(Integer uid) { |
||||
List<SchemeInfo> list = schemeMapper.getHomeSchemeList(uid); |
||||
for (SchemeInfo schemeInfo : list) { |
||||
schemeInfo.setShareLink(shareLinkPrefix + schemeInfo.getSid()); |
||||
} |
||||
return list; |
||||
} |
||||
|
||||
@Override |
||||
public boolean hasPermission(String sid, UserInfo userInfo) { |
||||
Map para = new HashMap<>(); |
||||
para.put("uid", userInfo.getUid()); |
||||
para.put("sid", sid); |
||||
return schemeMapper.hasPermission(para) > 0; |
||||
} |
||||
|
||||
@Override |
||||
public boolean updateScheme(SchemeInfo schemeInfo) { |
||||
return schemeMapper.updateScheme(schemeInfo); |
||||
} |
||||
|
||||
@Override |
||||
public SchemeInfo getSchemeInfo(Integer uid, String sid) { |
||||
Map para = new HashMap<>(); |
||||
para.put("uid", uid); |
||||
para.put("sid", sid); |
||||
SchemeInfo schemeInfo = schemeMapper.getSchemeInfo(para); |
||||
if (schemeInfo != null) |
||||
schemeInfo.setShareLink(shareLinkPrefix + sid); |
||||
return schemeInfo; |
||||
} |
||||
|
||||
@Override |
||||
public boolean updateShareInfo(SchemeInfo schemeInfo) { |
||||
return schemeMapper.updateShareInfo(schemeInfo); |
||||
} |
||||
|
||||
@Override |
||||
public Integer getShareBySid(String sid) { |
||||
return schemeMapper.getShareBySid(sid); |
||||
} |
||||
|
||||
@Override |
||||
public SchemeInfo getSchemeInfo(String sid) { |
||||
return schemeMapper.getSchemeInfoBySid(sid); |
||||
} |
||||
|
||||
@Override |
||||
public boolean getCustomer(String sid, String password) { |
||||
Map para = new HashMap<>(); |
||||
para.put("password", password); |
||||
para.put("sid", sid); |
||||
return schemeMapper.getCustomer(para)>0; |
||||
} |
||||
|
||||
@Override |
||||
public boolean deleteScheme(Integer uid, String sid) { |
||||
Map para = new HashMap<>(); |
||||
para.put("uid", uid); |
||||
para.put("sid", sid); |
||||
return schemeMapper.deleteScheme(para); |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,61 @@ |
||||
package com.tonkia.v3dmodel.service.impl; |
||||
|
||||
import com.tonkia.v3dmodel.mapper.UserMapper; |
||||
import com.tonkia.v3dmodel.pojo.UserInfo; |
||||
import com.tonkia.v3dmodel.service.UserService; |
||||
import org.apache.http.util.TextUtils; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
@Service |
||||
public class UserServiceImpl implements UserService { |
||||
@Autowired |
||||
UserMapper userMapper; |
||||
|
||||
@Override |
||||
public UserInfo getUserInfo(UserInfo userInfo) { |
||||
return userMapper.getUserInfo(userInfo); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 获取主页的用户信息,关键信息需要保留 |
||||
* |
||||
* @param uid |
||||
* @return |
||||
*/ |
||||
@Override |
||||
public UserInfo getHomeUserInfo(Integer uid) { |
||||
return userMapper.getHomeUserInfo(uid); |
||||
} |
||||
|
||||
@Override |
||||
public boolean updateAvatar(Integer uid, String path) { |
||||
Map para = new HashMap(); |
||||
para.put("uid", uid); |
||||
para.put("avatar", path); |
||||
return userMapper.updateAvatar(para); |
||||
} |
||||
|
||||
@Override |
||||
public boolean updateInfo(Integer uid, String userName, String password) { |
||||
boolean res = false; |
||||
if (!TextUtils.isEmpty(userName)) { |
||||
Map para = new HashMap(); |
||||
para.put("uid", uid); |
||||
para.put("userName", userName); |
||||
res = res || userMapper.updateUserName(para); |
||||
} |
||||
|
||||
if (!TextUtils.isEmpty(password)) { |
||||
Map para = new HashMap(); |
||||
para.put("uid", uid); |
||||
para.put("password", password); |
||||
res = res || userMapper.updatePassword(para); |
||||
} |
||||
return res; |
||||
} |
||||
} |
@ -0,0 +1,13 @@ |
||||
package com.tonkia.v3dmodel.utils; |
||||
|
||||
import java.io.FileInputStream; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
|
||||
public class Test { |
||||
public static void main(String[] args) throws IOException { |
||||
InputStream is = new FileInputStream("d:/web.png"); |
||||
boolean res = FtpUtil.uploadFile("192.168.226.128", 21, "ftpuser", "123456", "/home/ftpuser", "/v3d", "target", is); |
||||
System.out.println(res); |
||||
} |
||||
} |
@ -0,0 +1,17 @@ |
||||
package com.tonkia.v3dmodel.utils; |
||||
|
||||
import net.coobird.thumbnailator.Thumbnails; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.OutputStream; |
||||
|
||||
public class ThumbUtil { |
||||
public static void thumb(InputStream is, OutputStream os, int size) { |
||||
try { |
||||
Thumbnails.of(is).size(size, size).outputQuality(0.5).toOutputStream(os); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,13 @@ |
||||
package com.tonkia.v3dmodel.utils; |
||||
|
||||
import java.util.UUID; |
||||
|
||||
public class UUIDUtil { |
||||
public static String generate() { |
||||
return UUID.randomUUID().toString().replaceAll("-", ""); |
||||
} |
||||
|
||||
public static void main(String[] args) { |
||||
System.out.println(generate()); |
||||
} |
||||
} |
@ -0,0 +1,12 @@ |
||||
#ftpclient.host=134.175.111.158 |
||||
ftpclient.host=192.168.226.129 |
||||
ftpclient.port=21 |
||||
ftpclient.username=ftpuser |
||||
#ftpclient.password=41509060104 |
||||
ftpclient.password=123456 |
||||
ftpclient.basePath=/home/ftpuser |
||||
ftpclient.filePath=/v3d |
||||
ftpclient.downloadPathPrefix=/file/download |
||||
|
||||
shareLink.prefix=http://192.168.43.208/#/show/ |
||||
#shareLink.prefix=http://v3d.tonkia.xyz/#/show/ |
@ -0,0 +1,4 @@ |
||||
jdbc.driverClassName=com.mysql.cj.jdbc.Driver |
||||
jdbc.url=jdbc:mysql://localhost:3306/v3dmodel?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false |
||||
jdbc.username=root |
||||
jdbc.password=123456 |
@ -0,0 +1,5 @@ |
||||
log4j.rootLogger=DEBUG,Console |
||||
#Console |
||||
log4j.appender.Console=org.apache.log4j.ConsoleAppender |
||||
log4j.appender.Console.layout=org.apache.log4j.PatternLayout |
||||
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n |
@ -0,0 +1,131 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<beans xmlns="http://www.springframework.org/schema/beans" |
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xmlns:context="http://www.springframework.org/schema/context" |
||||
xmlns:mvc="http://www.springframework.org/schema/mvc" |
||||
xmlns:aop="http://www.springframework.org/schema/aop" |
||||
xmlns:tx="http://www.springframework.org/schema/tx" |
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans |
||||
http://www.springframework.org/schema/beans/spring-beans.xsd |
||||
http://www.springframework.org/schema/context |
||||
http://www.springframework.org/schema/context/spring-context.xsd |
||||
http://www.springframework.org/schema/mvc |
||||
http://www.springframework.org/schema/mvc/spring-mvc.xsd |
||||
http://www.springframework.org/schema/aop |
||||
http://www.springframework.org/schema/aop/spring-aop.xsd |
||||
http://www.springframework.org/schema/tx |
||||
http://www.springframework.org/schema/tx/spring-tx.xsd"> |
||||
|
||||
<!--引入配置文件,多个用逗号隔开--> |
||||
<context:property-placeholder location="classpath:db.properties,classpath:cfg.properties"/> |
||||
|
||||
<!-- 启用springmvc注解--> |
||||
<mvc:annotation-driven/> |
||||
|
||||
<!-- 设置使用注解的类路径 --> |
||||
<context:component-scan base-package="com.tonkia.v3dmodel.controller,com.tonkia.v3dmodel.service.impl"/> |
||||
<!--<context:annotation-config/>--> |
||||
|
||||
<!-- 静态文件处理 --> |
||||
<mvc:resources location="/css/" mapping="/css/**/"/> |
||||
<mvc:resources location="/js/" mapping="/js/**/"/> |
||||
<mvc:resources location="/img/" mapping="/img/**/"/> |
||||
<mvc:resources location="/ueditor/" mapping="/ueditor/**/"/> |
||||
|
||||
<!-- 文件上传--> |
||||
<bean id="multipartResolver" |
||||
class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> |
||||
<property name="defaultEncoding" value="utf-8"/> |
||||
<property name="maxUploadSize" value="10240000"/> |
||||
<property name="maxInMemorySize" value="10240000"/> |
||||
<property name="resolveLazily" value="true"/> |
||||
</bean> |
||||
|
||||
<!-- druid数据源 --> |
||||
<bean id="ds" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> |
||||
<property name="driverClassName" value="${jdbc.driverClassName}"/> |
||||
<property name="url" value="${jdbc.url}"/> |
||||
<property name="username" value="${jdbc.username}"/> |
||||
<property name="password" value="${jdbc.password}"/> |
||||
<property name="initialSize" value="2"/> |
||||
<property name="minIdle" value="1"/> |
||||
<property name="maxActive" value="20"/> |
||||
<property name="maxWait" value="60000"/> |
||||
<property name="timeBetweenEvictionRunsMillis" value="60000"/> |
||||
<property name="minEvictableIdleTimeMillis" value="300000"/> |
||||
<property name="validationQuery" value="SELECT 'x' from dual "/> |
||||
<property name="testWhileIdle" value="true"/> |
||||
<property name="testOnBorrow" value="false"/> |
||||
<property name="testOnReturn" value="false"/> |
||||
<property name="poolPreparedStatements" value="true"/> |
||||
<property name="maxPoolPreparedStatementPerConnectionSize" value="20"/> |
||||
</bean> |
||||
|
||||
<!-- 配置mybatis --> |
||||
<bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> |
||||
<property name="dataSource" ref="ds"/> |
||||
</bean> |
||||
|
||||
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> |
||||
<property name="sqlSessionFactoryBeanName" value="sessionFactory"/> |
||||
<property name="basePackage" value="com.tonkia.v3dmodel.mapper"/> |
||||
</bean> |
||||
|
||||
<!-- 事务管理器 --> |
||||
<bean id="tm" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> |
||||
<property name="dataSource" ref="ds"/> |
||||
</bean> |
||||
<tx:advice id="txAdvice" transaction-manager="tm"> |
||||
<tx:attributes> |
||||
<tx:method name="insert*"/> |
||||
<tx:method name="delete*"/> |
||||
<tx:method name="update*"/> |
||||
<tx:method name="*" read-only="true"/> |
||||
</tx:attributes> |
||||
</tx:advice> |
||||
<aop:config> |
||||
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.tonkia.v3dmodel.service.impl.*.*(..))"/> |
||||
</aop:config> |
||||
|
||||
<!--shiro--> |
||||
<!--<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">--> |
||||
<!--<property name="securityManager" ref="securityManager"/>--> |
||||
<!--<property name="loginUrl" value="/login"/>--> |
||||
<!--<property name="unauthorizedUrl" value="/refuse"/>--> |
||||
<!--<property name="filterChainDefinitions">--> |
||||
<!--<value>--> |
||||
<!--/test/**=anon--> |
||||
<!--/=user--> |
||||
<!--/logout=logout--> |
||||
<!--/**=authc--> |
||||
<!--</value>--> |
||||
<!--</property>--> |
||||
<!--</bean>--> |
||||
<!--<!–securityManager–>--> |
||||
<!--<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">--> |
||||
<!--<property name="realm" ref="userRealm"/>--> |
||||
<!--<property name="sessionManager" ref="sessionManager"/>--> |
||||
<!--<!–<property name="cacheManager" ref="cacheManager"/>–>--> |
||||
<!--</bean>--> |
||||
<!--<bean id="userRealm" class="com.tonkia.v3dmodel.realm.UserRealm"/>--> |
||||
<!--<!–sessionManager–>--> |
||||
<!--<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">--> |
||||
<!--<property name="sessionIdUrlRewritingEnabled" value="false"/>--> |
||||
<!--<property name="deleteInvalidSessions" value="true"/>--> |
||||
<!--<property name="globalSessionTimeout" value="600000"/>--> |
||||
<!--</bean>--> |
||||
<!--<!– Ehcache缓存–>--> |
||||
<!--<!–<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"/>–>--> |
||||
<!--<!–启用注解–>--> |
||||
<!--<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>--> |
||||
<!--<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"--> |
||||
<!--depends-on="lifecycleBeanPostProcessor">--> |
||||
<!--<property name="proxyTargetClass" value="true"/>--> |
||||
<!--</bean>--> |
||||
<!--<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">--> |
||||
<!--<property name="securityManager" ref="securityManager"/>--> |
||||
<!--</bean>--> |
||||
|
||||
</beans> |
||||
|
||||
|
@ -0,0 +1,55 @@ |
||||
<!DOCTYPE web-app PUBLIC |
||||
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" |
||||
"http://java.sun.com/dtd/web-app_2_3.dtd" > |
||||
|
||||
<web-app> |
||||
<welcome-file-list> |
||||
<welcome-file>index.jsp</welcome-file> |
||||
</welcome-file-list> |
||||
<!--字符编码过滤器--> |
||||
<filter> |
||||
<filter-name>encodingFilter</filter-name> |
||||
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> |
||||
<init-param> |
||||
<param-name>encoding</param-name> |
||||
<param-value>UTF-8</param-value> |
||||
</init-param> |
||||
</filter> |
||||
<!--shiro--> |
||||
<!--<filter>--> |
||||
<!--<filter-name>shiroFilter</filter-name>--> |
||||
<!--<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>--> |
||||
<!--<init-param>--> |
||||
<!--<param-name>targetFilterLifecycle</param-name>--> |
||||
<!--<param-value>true</param-value>--> |
||||
<!--</init-param>--> |
||||
<!--</filter>--> |
||||
<filter-mapping> |
||||
<filter-name>encodingFilter</filter-name> |
||||
<url-pattern>/*</url-pattern> |
||||
</filter-mapping> |
||||
<!--<filter-mapping>--> |
||||
<!--<filter-name>shiroFilter</filter-name>--> |
||||
<!--<url-pattern>/*</url-pattern>--> |
||||
<!--</filter-mapping>--> |
||||
<!--springmvc--> |
||||
|
||||
<servlet> |
||||
<servlet-name>springmvc</servlet-name> |
||||
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> |
||||
<init-param> |
||||
<param-name>contextConfigLocation</param-name> |
||||
<param-value>classpath:/springmvc.xml</param-value> |
||||
</init-param> |
||||
<load-on-startup>1</load-on-startup> |
||||
</servlet> |
||||
<servlet-mapping> |
||||
<servlet-name>default</servlet-name> |
||||
<url-pattern>*.ico</url-pattern> |
||||
</servlet-mapping> |
||||
<servlet-mapping> |
||||
<servlet-name>springmvc</servlet-name> |
||||
<url-pattern>/</url-pattern> |
||||
</servlet-mapping> |
||||
|
||||
</web-app> |
@ -0,0 +1 @@ |
||||
.v-enter{opacity:0;-webkit-transform:translateX(300px);transform:translateX(300px)}.v-leave-to{opacity:0;-webkit-transform:translateX(-300px);transform:translateX(-300px)}.v-enter-active,.v-leave-active{-webkit-transition:all .3s ease;transition:all .3s ease}.v-speed-dial{position:absolute}.v-btn--floating{position:relative} |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 54 KiB |
After Width: | Height: | Size: 225 KiB |
After Width: | Height: | Size: 449 KiB |
After Width: | Height: | Size: 306 KiB |
After Width: | Height: | Size: 268 KiB |
After Width: | Height: | Size: 153 KiB |
After Width: | Height: | Size: 370 KiB |
@ -0,0 +1,27 @@ |
||||
<%@ page contentType="text/html;charset=UTF-8" language="java" %> |
||||
<!DOCTYPE html> |
||||
<html lang=en> |
||||
<head> |
||||
<meta charset=utf-8> |
||||
<meta http-equiv=X-UA-Compatible content="IE=edge"> |
||||
<meta name=viewport content="width=device-width,initial-scale=1"> |
||||
<link rel=icon href=/favicon.ico> |
||||
<title>V3D</title> |
||||
<link rel=stylesheet href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900"> |
||||
<link rel=stylesheet href="https://fonts.googleapis.com/css?family=Material+Icons"> |
||||
<script src=./js/inflate.min.js></script> |
||||
<link href=/css/app.a0a149c8.css rel=preload as=style> |
||||
<link href=/css/chunk-vendors.504cc259.css rel=preload as=style> |
||||
<link href=/js/app.f155bb4f.js rel=preload as=script> |
||||
<link href=/js/chunk-vendors.af4edcc5.js rel=preload as=script> |
||||
<link href=/css/chunk-vendors.504cc259.css rel=stylesheet> |
||||
<link href=/css/app.a0a149c8.css rel=stylesheet> |
||||
</head> |
||||
<body> |
||||
<noscript><strong>We're sorry but v3dmodel doesn't work properly without JavaScript enabled. Please enable it to |
||||
continue.</strong></noscript> |
||||
<div id=app></div> |
||||
<script src=/js/chunk-vendors.af4edcc5.js></script> |
||||
<script src=/js/app.f155bb4f.js></script> |
||||
</body> |
||||
</html> |
@ -0,0 +1,15 @@ |
||||
/** @license zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */(function() {'use strict';var l=void 0,aa=this;function r(c,d){var a=c.split("."),b=aa;!(a[0]in b)&&b.execScript&&b.execScript("var "+a[0]);for(var e;a.length&&(e=a.shift());)!a.length&&d!==l?b[e]=d:b=b[e]?b[e]:b[e]={}};var t="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array&&"undefined"!==typeof DataView;function v(c){var d=c.length,a=0,b=Number.POSITIVE_INFINITY,e,f,g,h,k,m,n,p,s,x;for(p=0;p<d;++p)c[p]>a&&(a=c[p]),c[p]<b&&(b=c[p]);e=1<<a;f=new (t?Uint32Array:Array)(e);g=1;h=0;for(k=2;g<=a;){for(p=0;p<d;++p)if(c[p]===g){m=0;n=h;for(s=0;s<g;++s)m=m<<1|n&1,n>>=1;x=g<<16|p;for(s=m;s<e;s+=k)f[s]=x;++h}++g;h<<=1;k<<=1}return[f,a,b]};function w(c,d){this.g=[];this.h=32768;this.d=this.f=this.a=this.l=0;this.input=t?new Uint8Array(c):c;this.m=!1;this.i=y;this.r=!1;if(d||!(d={}))d.index&&(this.a=d.index),d.bufferSize&&(this.h=d.bufferSize),d.bufferType&&(this.i=d.bufferType),d.resize&&(this.r=d.resize);switch(this.i){case A:this.b=32768;this.c=new (t?Uint8Array:Array)(32768+this.h+258);break;case y:this.b=0;this.c=new (t?Uint8Array:Array)(this.h);this.e=this.z;this.n=this.v;this.j=this.w;break;default:throw Error("invalid inflate mode"); |
||||
}}var A=0,y=1,B={t:A,s:y}; |
||||
w.prototype.k=function(){for(;!this.m;){var c=C(this,3);c&1&&(this.m=!0);c>>>=1;switch(c){case 0:var d=this.input,a=this.a,b=this.c,e=this.b,f=d.length,g=l,h=l,k=b.length,m=l;this.d=this.f=0;if(a+1>=f)throw Error("invalid uncompressed block header: LEN");g=d[a++]|d[a++]<<8;if(a+1>=f)throw Error("invalid uncompressed block header: NLEN");h=d[a++]|d[a++]<<8;if(g===~h)throw Error("invalid uncompressed block header: length verify");if(a+g>d.length)throw Error("input buffer is broken");switch(this.i){case A:for(;e+ |
||||
g>b.length;){m=k-e;g-=m;if(t)b.set(d.subarray(a,a+m),e),e+=m,a+=m;else for(;m--;)b[e++]=d[a++];this.b=e;b=this.e();e=this.b}break;case y:for(;e+g>b.length;)b=this.e({p:2});break;default:throw Error("invalid inflate mode");}if(t)b.set(d.subarray(a,a+g),e),e+=g,a+=g;else for(;g--;)b[e++]=d[a++];this.a=a;this.b=e;this.c=b;break;case 1:this.j(ba,ca);break;case 2:for(var n=C(this,5)+257,p=C(this,5)+1,s=C(this,4)+4,x=new (t?Uint8Array:Array)(D.length),S=l,T=l,U=l,u=l,M=l,F=l,z=l,q=l,V=l,q=0;q<s;++q)x[D[q]]= |
||||
C(this,3);if(!t){q=s;for(s=x.length;q<s;++q)x[D[q]]=0}S=v(x);u=new (t?Uint8Array:Array)(n+p);q=0;for(V=n+p;q<V;)switch(M=E(this,S),M){case 16:for(z=3+C(this,2);z--;)u[q++]=F;break;case 17:for(z=3+C(this,3);z--;)u[q++]=0;F=0;break;case 18:for(z=11+C(this,7);z--;)u[q++]=0;F=0;break;default:F=u[q++]=M}T=t?v(u.subarray(0,n)):v(u.slice(0,n));U=t?v(u.subarray(n)):v(u.slice(n));this.j(T,U);break;default:throw Error("unknown BTYPE: "+c);}}return this.n()}; |
||||
var G=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],D=t?new Uint16Array(G):G,H=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258],I=t?new Uint16Array(H):H,J=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0],K=t?new Uint8Array(J):J,L=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],da=t?new Uint16Array(L):L,ea=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12, |
||||
13,13],N=t?new Uint8Array(ea):ea,O=new (t?Uint8Array:Array)(288),P,fa;P=0;for(fa=O.length;P<fa;++P)O[P]=143>=P?8:255>=P?9:279>=P?7:8;var ba=v(O),Q=new (t?Uint8Array:Array)(30),R,ga;R=0;for(ga=Q.length;R<ga;++R)Q[R]=5;var ca=v(Q);function C(c,d){for(var a=c.f,b=c.d,e=c.input,f=c.a,g=e.length,h;b<d;){if(f>=g)throw Error("input buffer is broken");a|=e[f++]<<b;b+=8}h=a&(1<<d)-1;c.f=a>>>d;c.d=b-d;c.a=f;return h} |
||||
function E(c,d){for(var a=c.f,b=c.d,e=c.input,f=c.a,g=e.length,h=d[0],k=d[1],m,n;b<k&&!(f>=g);)a|=e[f++]<<b,b+=8;m=h[a&(1<<k)-1];n=m>>>16;if(n>b)throw Error("invalid code length: "+n);c.f=a>>n;c.d=b-n;c.a=f;return m&65535} |
||||
w.prototype.j=function(c,d){var a=this.c,b=this.b;this.o=c;for(var e=a.length-258,f,g,h,k;256!==(f=E(this,c));)if(256>f)b>=e&&(this.b=b,a=this.e(),b=this.b),a[b++]=f;else{g=f-257;k=I[g];0<K[g]&&(k+=C(this,K[g]));f=E(this,d);h=da[f];0<N[f]&&(h+=C(this,N[f]));b>=e&&(this.b=b,a=this.e(),b=this.b);for(;k--;)a[b]=a[b++-h]}for(;8<=this.d;)this.d-=8,this.a--;this.b=b}; |
||||
w.prototype.w=function(c,d){var a=this.c,b=this.b;this.o=c;for(var e=a.length,f,g,h,k;256!==(f=E(this,c));)if(256>f)b>=e&&(a=this.e(),e=a.length),a[b++]=f;else{g=f-257;k=I[g];0<K[g]&&(k+=C(this,K[g]));f=E(this,d);h=da[f];0<N[f]&&(h+=C(this,N[f]));b+k>e&&(a=this.e(),e=a.length);for(;k--;)a[b]=a[b++-h]}for(;8<=this.d;)this.d-=8,this.a--;this.b=b}; |
||||
w.prototype.e=function(){var c=new (t?Uint8Array:Array)(this.b-32768),d=this.b-32768,a,b,e=this.c;if(t)c.set(e.subarray(32768,c.length));else{a=0;for(b=c.length;a<b;++a)c[a]=e[a+32768]}this.g.push(c);this.l+=c.length;if(t)e.set(e.subarray(d,d+32768));else for(a=0;32768>a;++a)e[a]=e[d+a];this.b=32768;return e}; |
||||
w.prototype.z=function(c){var d,a=this.input.length/this.a+1|0,b,e,f,g=this.input,h=this.c;c&&("number"===typeof c.p&&(a=c.p),"number"===typeof c.u&&(a+=c.u));2>a?(b=(g.length-this.a)/this.o[2],f=258*(b/2)|0,e=f<h.length?h.length+f:h.length<<1):e=h.length*a;t?(d=new Uint8Array(e),d.set(h)):d=h;return this.c=d}; |
||||
w.prototype.n=function(){var c=0,d=this.c,a=this.g,b,e=new (t?Uint8Array:Array)(this.l+(this.b-32768)),f,g,h,k;if(0===a.length)return t?this.c.subarray(32768,this.b):this.c.slice(32768,this.b);f=0;for(g=a.length;f<g;++f){b=a[f];h=0;for(k=b.length;h<k;++h)e[c++]=b[h]}f=32768;for(g=this.b;f<g;++f)e[c++]=d[f];this.g=[];return this.buffer=e}; |
||||
w.prototype.v=function(){var c,d=this.b;t?this.r?(c=new Uint8Array(d),c.set(this.c.subarray(0,d))):c=this.c.subarray(0,d):(this.c.length>d&&(this.c.length=d),c=this.c);return this.buffer=c};function W(c,d){var a,b;this.input=c;this.a=0;if(d||!(d={}))d.index&&(this.a=d.index),d.verify&&(this.A=d.verify);a=c[this.a++];b=c[this.a++];switch(a&15){case ha:this.method=ha;break;default:throw Error("unsupported compression method");}if(0!==((a<<8)+b)%31)throw Error("invalid fcheck flag:"+((a<<8)+b)%31);if(b&32)throw Error("fdict flag is not supported");this.q=new w(c,{index:this.a,bufferSize:d.bufferSize,bufferType:d.bufferType,resize:d.resize})} |
||||
W.prototype.k=function(){var c=this.input,d,a;d=this.q.k();this.a=this.q.a;if(this.A){a=(c[this.a++]<<24|c[this.a++]<<16|c[this.a++]<<8|c[this.a++])>>>0;var b=d;if("string"===typeof b){var e=b.split(""),f,g;f=0;for(g=e.length;f<g;f++)e[f]=(e[f].charCodeAt(0)&255)>>>0;b=e}for(var h=1,k=0,m=b.length,n,p=0;0<m;){n=1024<m?1024:m;m-=n;do h+=b[p++],k+=h;while(--n);h%=65521;k%=65521}if(a!==(k<<16|h)>>>0)throw Error("invalid adler-32 checksum");}return d};var ha=8;r("Zlib.Inflate",W);r("Zlib.Inflate.prototype.decompress",W.prototype.k);var X={ADAPTIVE:B.s,BLOCK:B.t},Y,Z,$,ia;if(Object.keys)Y=Object.keys(X);else for(Z in Y=[],$=0,X)Y[$++]=Z;$=0;for(ia=Y.length;$<ia;++$)Z=Y[$],r("Zlib.Inflate.BufferType."+Z,X[Z]);}).call(this); |
@ -0,0 +1,12 @@ |
||||
#ftpclient.host=134.175.111.158 |
||||
ftpclient.host=192.168.226.129 |
||||
ftpclient.port=21 |
||||
ftpclient.username=ftpuser |
||||
#ftpclient.password=41509060104 |
||||
ftpclient.password=123456 |
||||
ftpclient.basePath=/home/ftpuser |
||||
ftpclient.filePath=/v3d |
||||
ftpclient.downloadPathPrefix=/file/download |
||||
|
||||
shareLink.prefix=http://192.168.43.208/#/show/ |
||||
#shareLink.prefix=http://v3d.tonkia.xyz/#/show/ |