edit.js 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313
  1. var ceshi = 'http://space3d.4dage.com/back';
  2. //新编辑界面
  3. var EditTools = function (n) {
  4. //main2018 里面的主要对象
  5. this.n = n;
  6. //当前状态
  7. this.atPanel = null;
  8. //场景信息
  9. this.sceneInformation = new SceneInformation();
  10. //热点
  11. this.hotpoint = new Hotpoint();
  12. //导览
  13. this.editGuide = new EditGuide();
  14. //音乐
  15. this.editMiuse = new EditMiuse();
  16. //初始化界面
  17. this.init();
  18. }
  19. EditTools.prototype.init = function () {
  20. this.hotpoint.init(this.n);
  21. var that = this;
  22. this.saveAll();
  23. this.active();
  24. //请求数据someData.js
  25. $.ajax(g_Prefix + "data/" + window.number + "/someData.json" + "?" + Date.now(), { dataType: "json" })
  26. .done(function (data) {
  27. //创建导览
  28. that.editMiuse.init(data);
  29. //请求完someData.js 之后再请求data2.js
  30. data2(data, that.sceneInformation.init);
  31. })
  32. //请求热点数据 data2.js
  33. function data2(data, callback) {
  34. $.ajax(g_Prefix + "data/" + window.number + "/data2.js" + "?" + Date.now(), { dataType: "json" })
  35. .done(function (data2) {
  36. callback(data, data2);
  37. // fyz 初始化导览需要两部分数据, 其中data2为data.js中的数据
  38. that.editGuide.init(data, data2);
  39. }).fail(
  40. callback(data, data2)
  41. )
  42. }
  43. $("body").on("click", function () {
  44. $(".DelConfirm").removeClass("active");
  45. })
  46. }
  47. //点击的时候激活状态
  48. EditTools.prototype.active = function () {
  49. var that = this;
  50. var confirmSnap = $(".confirmSnap.innerBtn");
  51. var snapshotGui = $(".snapshotGui.overlayGui");
  52. $('.toolBottom .toolLeft li').click(function () {
  53. var name = $(this).data("name");
  54. $('.toolLeft li[data-name=' + name + ']').addClass("active").siblings().removeClass("active");
  55. $('.toolRight .' + name).removeClass("hide").siblings().addClass("hide");
  56. that.atPanel = name;
  57. if (name === "screen") {
  58. confirmSnap.removeClass("hide");
  59. snapshotGui.show();
  60. } else {
  61. confirmSnap.addClass("hide");
  62. snapshotGui.hide();
  63. }
  64. })
  65. //滚动阻止事件
  66. $(".toolRight div.content").on("mousewheel", function (event) {
  67. event.stopPropagation()
  68. });
  69. // 输入框阻止事件
  70. $('.toolRight').on('keydown', function (ev) {
  71. ev.stopPropagation();
  72. })
  73. }
  74. //保存按钮
  75. EditTools.prototype.saveAll = function () {
  76. var that = this;
  77. $('#save').on('click', function () {
  78. $(".edit-loading").removeClass("hide");
  79. //导览的数据
  80. var guides = Array.from($('.tourList ul li')).map(function (dom) {
  81. return dom.data
  82. })
  83. var hots = {}
  84. Array.from($('.spotList ul li')).forEach(function (dom) {
  85. hots[dom.hotAttribute.belongHot.sid] = {
  86. position: {
  87. x: dom.hotAttribute.position.x,
  88. y: dom.hotAttribute.position.y,
  89. z: dom.hotAttribute.position.z
  90. },
  91. rotation: {
  92. x: dom.hotAttribute.rotation.x,
  93. y: dom.hotAttribute.rotation.y,
  94. z: dom.hotAttribute.rotation.z
  95. },
  96. infoAttribute: dom.infoAttribute
  97. }
  98. })
  99. var info = {
  100. name: $('#pjtName').val(),
  101. summary: $('#info-summary').val(),
  102. backgroundMusic: $('#query-bgm').attr('href'),
  103. hoticon: JSON.parse($(".hotStyle-item li.active").attr("data-val")),
  104. camera_start: $('#camera-start')[0].data,
  105. loadlogo: $("#loadlogo").is(':checked'),
  106. special: $("#g_specialScene").is(':checked'),
  107. vision_version: $("#twoData").is(':checked') ? "1.1.562.17209" : false,
  108. /************************************** 方奕卓 场景可配置项 ******************************************/
  109. hotImageScale: $("#hotImgScale").is(':checked'), // 热点图片可放大
  110. hideFloorMarker: $("#hideFloorMarker").is(':checked'), // 地面标记
  111. hideMouseMarker: $("#hideMouseMarker").is(':checked'), // 鼠标标记
  112. floorMarkerColor: $('#floorMarkerColor').val(), // 地面/导览标志颜色
  113. mouseMarkerColor: $('#mouseMarkerColor').val(), // 鼠标标志颜色
  114. momentTour: $('#tourSwitch input').is(':checked') ? 'black' : 'walk', // 导览瞬间过渡
  115. showHotListSta: $('#hotListSwitch input').is(':checked'), // 开启热点列表
  116. hotIconScale: $('#hotIconScale input').val(), // 热点缩放
  117. supportsVR: $('#VRSwitch input').is(':checked'), // 开启VR功能
  118. }
  119. info.weixinDesc = $('#weixin-summary').val();
  120. $.ajax({
  121. method: 'POST',
  122. url: ceshi + '/savesetting',
  123. data: {
  124. hots: hots,
  125. name: number,
  126. guides: guides,
  127. info: info,
  128. tourAudio: that.editGuide.tourAudio
  129. },
  130. success: function (data) {
  131. if (data.code === 200) {
  132. location.reload()
  133. }
  134. }
  135. })
  136. });
  137. }
  138. //场景信息编辑
  139. var SceneInformation = function () {
  140. }
  141. SceneInformation.prototype.init = function (data, data2) {
  142. var $options = $('.hotStyle-item li');
  143. var $loadlogo = $("#loadlogo");
  144. var $hotImageScale = $("#hotImgScale");
  145. var $hideFloorMarker = $("#hideFloorMarker");
  146. var $hideMouseMarker = $("#hideMouseMarker");
  147. var $g_specialScene = $("#g_specialScene");
  148. var $twoData = $("#twoData");
  149. /*******************方奕卓 其他项需要用到data来初始化, 故一并放到这里 ******************/
  150. let momentTour = $('#tourSwitch input'); // 导览瞬间过渡开关
  151. let hotListSwitch = $('#hotListSwitch input'); // 热点列表开关
  152. let hotIconScale = $('#hotIconScale input'); // 热点图标缩放
  153. let VRSwitch = $('#VRSwitch input'); // VR功能开启
  154. /***********************************************************************************/
  155. $(".model-title2").text(data.model.name);
  156. $('#pjtName').val(data.model.name);
  157. $('#info-summary').val(data.model.summary);
  158. if (data2) $('#weixin-summary').val(data2.weixinDesc);
  159. for (var i = 0; i < $options.length; i++) {
  160. if ($options.eq(i).attr('data-val') === JSON.stringify(data.hoticon)) {
  161. $options.eq(i).addClass("active").siblings().removeClass("active");
  162. }
  163. }
  164. $('#camera-start')[0].data = data.model.camera_start;
  165. /*************方奕卓 其他项的初始化操作 ************/
  166. initColorElem(data);
  167. addListener(); // 给其他元素绑定事件
  168. if (data.momentTour === 'black') {
  169. momentTour.prop('checked', true);
  170. }
  171. if (data.showHotListSta === 'true') {
  172. hotListSwitch.prop('checked', true);
  173. }
  174. if (data.hotIconScale && parseFloat(data.hotIconScale) < 1.5 && parseFloat(data.hotIconScale) > 0.3) {
  175. hotIconScale.val(parseFloat(data.hotIconScale));
  176. }
  177. if(data.supportsVR === 'true'){
  178. VRSwitch.prop('checked', true);
  179. }
  180. /************************************************/
  181. //隐藏公司logo
  182. if (data.loadlogo) {
  183. $loadlogo[0].checked = true
  184. showLogo();
  185. }
  186. // 热点图片放大
  187. if (data.hotImageScale === 'true') {
  188. $hotImageScale[0].checked = true
  189. }
  190. // 隐藏地面标记
  191. if (data.hideFloorMarker === 'true') {
  192. $hideFloorMarker[0].checked = true
  193. }
  194. // 隐藏鼠标标记
  195. if (data.hideMouseMarker === 'true') {
  196. $hideMouseMarker[0].checked = true
  197. }
  198. //特殊大场景
  199. if (data.special === "true" || data.model.special) {
  200. $g_specialScene[0].checked = true
  201. }
  202. //启动二代的数据
  203. if (data.vision_version === "1.1.562.17209" || data.model.vision_version) {
  204. $twoData[0].checked = true
  205. }
  206. }
  207. function initColorElem(data, elem) {
  208. let $floorMarkerColor = $('#floorMarkerColor');
  209. let $mouseMarkerColor = $('#mouseMarkerColor');
  210. let $floorMarkerColorTex = $('#floorMarkerColorTex');
  211. let $mouseMarkerColorTex = $('#mouseMarkerColorTex');
  212. var colorRe = /^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/;
  213. data.floorMarkerColor ? $floorMarkerColor.val(data.floorMarkerColor) : $floorMarkerColor.val('#4bcdfc');
  214. data.mouseMarkerColor ? $mouseMarkerColor.val(data.mouseMarkerColor) : $mouseMarkerColor.val('#4bcdfc');
  215. $floorMarkerColor.on('change', function (e) {
  216. $('#floorMarkerColorTex').attr('placeholder', e.target.value)
  217. })
  218. $floorMarkerColorTex.on('blur keydown', function (e) {
  219. (e.type === 'blur' || e.type === 'keydown' && e.keyCode === 13) && setColor(e, $floorMarkerColor, this);
  220. })
  221. $mouseMarkerColor.on('change', function (e) {
  222. $('#mouseMarkerColorTex').attr('placeholder', e.target.value)
  223. })
  224. $mouseMarkerColorTex.on('blur keydown', function (e) {
  225. (e.type === 'blur' || e.type === 'keydown' && e.keyCode === 13) && setColor(e, $mouseMarkerColor, this);
  226. })
  227. function setColor(e, colorElem, inputElem) {
  228. var isColor = colorRe.test(e.target.value);
  229. isColor && colorElem.val(e.target.value);
  230. // isColor ? colorElem.val(e.target.value): (inputElem.placeholder = colorElem.val());
  231. }
  232. }
  233. function addListener(){
  234. // let customizeHot = $('#customizeHot'); // 自定义热点
  235. // customizeHot.on('click', function(){
  236. // })
  237. }
  238. //设置初始界面
  239. function getSeft(seft) {
  240. $('#camera-start').on('click', function () {
  241. var snap = JSON.parse("{" + seft.getSnapAngleInfo() + "}")
  242. if(!this.data){
  243. this.data = {
  244. camera:{
  245. quaternion:''
  246. },
  247. pano:{
  248. uuid:''
  249. }
  250. }
  251. }
  252. this.data.camera.quaternion = snap.metadata.camera_quaternion;
  253. this.data.pano.uuid = snap.metadata.scan_id;
  254. var ev = document.createEvent("MouseEvent");//点击截取视图
  255. g_snapShotWidth = 240;
  256. g_snapShotHeight = 118;
  257. ev.initMouseEvent("snapshotBegin", true, true, document.defaultView, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
  258. ev.__callback = function (imgData, info) {
  259. initialPicture(imgData, info)
  260. }.bind(this);
  261. window.dispatchEvent(ev);
  262. });
  263. //上传图片
  264. function initialPicture(imgData) {
  265. uploadImg(imgData, function (rs) {
  266. if (rs.code === 200) {
  267. $(".shotImg.innerBtn").css("background-image", "url('//" + rs.content + "')")
  268. }
  269. })
  270. }
  271. }
  272. //热点编辑
  273. var Hotpoint = function () {
  274. this.spotList = $(".spotList");
  275. this.hotpointDetail = $("#hotpointDetail"); // fyz 导览编辑页面同样采取热点编辑的样式, 这里确保只查找到热点编辑
  276. }
  277. Hotpoint.prototype.init = function (n) {
  278. this.active();
  279. this.addmedia();
  280. this.addMusic();
  281. this.addModel();
  282. this.addwebPack();
  283. this.saveHot();
  284. var that = this;
  285. let hotIconScale = $('#hotIconScale');
  286. //点击添加热点按钮
  287. $('#addHotSpots').on("click", function () {//点击添加热点
  288. g_HotStatus = g_HotStatus === "add" ? null : "add";
  289. $("#player").css("cursor", "cell");
  290. });
  291. //点解热点列表删除按钮
  292. this.spotList.on("click", function (e) {
  293. var target = $(e.target);
  294. if (target.hasClass("del")) {
  295. e.stopPropagation();
  296. target.siblings(".DelConfirm").addClass("active");
  297. that.spotList.find("i").text(that.spotList.find("ul li").length);
  298. } else {
  299. if (target.hasClass("DelConfirm")) {
  300. e.stopPropagation();
  301. that.remHot(target, n);
  302. } else {
  303. //点击热点列表弹出编辑热点窗口
  304. if (target.hasClass("title") || target.hasClass("icon")) {
  305. that.editHot(target)
  306. }
  307. }
  308. }
  309. });
  310. //点击热点编辑窗口右上角的关闭按钮
  311. this.hotpointDetail.find("a.close, button.cancel").on("click", function () {
  312. that.hotpointDetail.addClass("atRight");
  313. });
  314. //遍历热点 初始话加载热点数据
  315. for (var i = 0; i < g_HotMeshes.length; i++) {
  316. this.spotList.children("ul").append(this.addHotList(g_HotMeshes[i], i));
  317. }
  318. this.spotList.find("i").text(g_HotMeshes.length);
  319. // 初始话的时候把热点信息添加到对应的热点中
  320. $.ajax(g_Prefix + "data/" + window.number + "/hot/js/data.js" + "?" + Date.now(), { dataType: "json" })
  321. .then(function (infos) {
  322. Object.keys(infos).forEach(function (key) {
  323. that.spotList.find("ul li[data-spid=" + key + "]")[0] && (that.spotList.find("ul li[data-spid=" + key + "]")[0].infoAttribute = infos[key])
  324. })
  325. })
  326. }
  327. //显示编辑热点的窗口和初始化热点窗口的数据
  328. Hotpoint.prototype.editHot = function (target) {
  329. this.hotpointDetail.removeClass("atRight");
  330. $("#hotpointDetail .audio.mediaUpload").find("input").val(''); // 点击编辑导览清空上一次文件
  331. var playIcon = '139.159.225.37:85/images/play.png';
  332. var $layout = $("#hotpointDetail")[0];
  333. $layout.targetDOM = target.closest("li")[0];
  334. var info = $layout.targetDOM.infoAttribute || {}
  335. info.title = info.title || '';
  336. info.content = info.content || '';
  337. info.iframe = info.iframe || [];
  338. info.model = info.model || [];
  339. info.images = info.images || [];
  340. info.video = info.video || [];
  341. var iframesHTML = info.iframe.map(function (iframe) {
  342. return this.inputList("请填写网页链接", iframe)
  343. }.bind(this))
  344. var modulesHTML = info.model.map(function (module) {
  345. return this.inputList("请填写网页链接", module)
  346. }.bind(this))
  347. var imagesHTML = info.images.map(function (image) {
  348. return '<div><a class=" result success"><span></span><img src="//' + image + '"></a></div>'
  349. })
  350. var videosHTML = info.video.map(function (ly) {
  351. var imgDom = (!ly.img || ly.img === "undefined") ? '' : 'success';
  352. var imgUrl = (!ly.img || ly.img === "undefined") ? playIcon : ly.img;
  353. return '<div><a class=" result success"><span></span><img class="play-video" videoURL="//' + ly.url + '" src="//' + imgUrl + '"></a ><span class="upload-thum ' + imgDom + ' result" attr-thum="' + ly.img + '">上传封面<i><input type="file"></i></span></div>'
  354. })
  355. this.hotpointDetail.find(".name > input").val(info.title);
  356. this.hotpointDetail.find(".editText").val(info.content);
  357. this.hotpointDetail.find(".photo .list").html(imagesHTML);
  358. this.hotpointDetail.find(".video .list").html(videosHTML);
  359. this.hotpointDetail.find(".model .list").html(modulesHTML);
  360. this.hotpointDetail.find(".webPage .list").html(iframesHTML);
  361. let bgName = info.bgName || '热点背景音乐';
  362. if (info.backgroundMusic) {
  363. this.hotpointDetail.find(".audio .playBox").removeClass("hide");
  364. this.hotpointDetail.find("#upload-hotBgm").attr('data-hotBgm', info.backgroundMusic)
  365. this.hotpointDetail.find(".audio .playBox a").attr("href", "//" + info.backgroundMusic);
  366. this.hotpointDetail.find('#hotBgName')[0].innerHTML = bgName;
  367. this.hotpointDetail.find(".audio .submit").text("替换");
  368. } else {
  369. this.hotpointDetail.find(".audio .playBox").addClass("hide");
  370. this.hotpointDetail.find("#upload-hotBgm").removeAttr('data-hotBgm') // 没有背景音乐,则移除该属性, 避免其他热点的干扰
  371. }
  372. }
  373. //添加图片和视频
  374. Hotpoint.prototype.addmedia = function () {
  375. // 视频预览控制
  376. var $videoLayout = $('.fun-view-video')
  377. $videoLayout.find('span').on('click', function () {
  378. $videoLayout.hide();
  379. $videoLayout.find('video').attr('src', '')[0].pause()
  380. });
  381. // 图片加载回调
  382. function imageSuccess(file) {
  383. if (!/image\/\w+/.test(file.type)) {
  384. alert("文件必须为图片!");
  385. return false;
  386. }
  387. if (!restrictedSize(file, 2)) {
  388. return false;
  389. }
  390. var img = new Image()
  391. img.src = URL.createObjectURL(file);
  392. return img
  393. }
  394. // 视频加载回调
  395. function videoSuccess(file, $elayout) {
  396. if (!/video\/\w+/.test(file.type)) {
  397. alert("视频必须为map4格式!");
  398. return false;
  399. }
  400. $elayout.append('<span class="upload-thum">上传封面<i><input type="file"></i></span>')
  401. return '<img src="./images/play.png" class="play-video" videoURL="' + URL.createObjectURL(file) + '">'
  402. }
  403. // 视频封面回调
  404. function thumSuccess(file, $elayout, $seft) {
  405. if (!/image\/\w+/.test(file.type)) {
  406. alert("文件必须为图片!");
  407. return false;
  408. }
  409. if (!restrictedSize(file, 2)) {
  410. return false;
  411. }
  412. $seft.closest('div').find('img').attr('src', URL.createObjectURL(file));
  413. }
  414. // 图片与视频加载
  415. function fileHandle() {
  416. var $seft = $(this)
  417. var $layout = $seft.closest("li");
  418. var type = $seft.parent().attr('data-type');
  419. var file = this.files[0];
  420. var $din = $(document.createElement('div'));
  421. var fnc = type === 'photo' ? imageSuccess :
  422. type === 'video' ? videoSuccess : thumSuccess
  423. var $dom = fnc(file, $din, $seft)
  424. if (type === 'photo' || type === 'video') {
  425. if (!$dom) return $seft.val('');
  426. var $addLayout = $(document.createElement('a'));
  427. var $addInput = $('<input type="file">')
  428. var $close = $(document.createElement('span'));
  429. $addInput[0].files = this.files;
  430. $addLayout.append($addInput)
  431. $addLayout.append($close);
  432. $addLayout.append($dom);
  433. $addLayout.addClass("result");
  434. $din.prepend($addLayout);
  435. $layout.find('.edit-fun-images').append($din);
  436. }
  437. };
  438. // 图片与视频加载
  439. $('.upload, .edit-fun-images').on('change', function (ev) {
  440. if (ev.target.tagName.toUpperCase() === 'INPUT') {
  441. fileHandle.call(ev.target)
  442. }
  443. })
  444. $('.edit-fun-images').on('click', function (ev) {
  445. var $tag = $(ev.target)
  446. var tagName = ev.target.tagName.toUpperCase()
  447. if (tagName === 'SPAN') {
  448. var $resf = $(ev.target)
  449. $resf.parent().parent().remove()
  450. } else if (tagName === 'IMG' && $tag.hasClass('play-video')) {
  451. $videoLayout
  452. .css('display', 'flex')
  453. .find('video')
  454. .attr('src', $tag.attr('videoURL'))[0]
  455. .play()
  456. }
  457. })
  458. }
  459. //选择热点的样式
  460. Hotpoint.prototype.active = function () {
  461. $(".hotStyle-item li").on('click', function () {
  462. $(this).addClass('active').siblings().removeClass('active');
  463. })
  464. }
  465. //当前处于的状态,比如是否是添加热点的状态
  466. Hotpoint.prototype.state = function (that, Hot) {
  467. if (g_HotStatus === "add") {
  468. this.addHot(that, Hot, function () {
  469. this.addHotList(g_HotMeshes, g_HotMeshes.length - 1);
  470. this.spotList.find("i").text(this.spotList.find("ul li").length);
  471. });
  472. }
  473. }
  474. //删除热点
  475. Hotpoint.prototype.remHot = function (that, thisScene) {
  476. var hotId = that.closest("li").attr("data-spid");
  477. for (var i = 0; i < g_HotMeshes.length; i++) {
  478. if (g_HotMeshes[i].belongHot.sid === hotId) {
  479. //在场景中删除这个热点模型
  480. thisScene.scene.remove(g_HotMeshes[i]);
  481. g_HotMeshes[i].visible = false;
  482. //如果热点数据中有这个热点数据就删除
  483. //g_HotMeshes.splice(i, 1);
  484. }
  485. }
  486. that.closest("li").remove();
  487. this.spotList.find(".hotNum").text(this.spotList.find("ul li").length);
  488. console.log("删除成功:" + hotId);
  489. }
  490. //添加热点模型
  491. Hotpoint.prototype.addHot = function (that, Hot, fn) {
  492. if (!window.hotPointPos) return; // 没有正确的热点位置, return
  493. // console.log(that.reticule.position);
  494. var position = that.reticule.position.toArray();
  495. // window.hotPointPos.z -= 0.05
  496. // var position = window.hotPointPos.toArray();
  497. var rotation = that.reticule.rotation.toArray().slice(0, 3);
  498. // var rotation = new THREE.Quaternion();
  499. // rotation.setFromAxisAngle( new THREE.Vector3( 0, 1, 0 ), Math.PI / 2 );
  500. // var rotation = [-3.1415914628953048, ]
  501. var sid = g_HotMeshes.length > 0 ? "sprite_" + (parseInt(g_HotMeshes[g_HotMeshes.length - 1].name.substring(7)) + 1) : "sprite_" + g_HotMeshes.length;
  502. var hot = new Hot(sid, { position: position, rotation: rotation, size: 1.05 }, that.model);
  503. that.model.hots[sid] = hot;
  504. g_HotStatus = false;
  505. that.mouseCouldBeClickToMove = false;
  506. $("#player").css("cursor", "");
  507. //添加完热点之后的回调函数
  508. if (g_HotMeshes && g_newHot.length === g_newHot.length++) {
  509. var thisScene = that;
  510. fn && fn.call(this, thisScene);
  511. }
  512. }
  513. //创建热点列表的dom
  514. Hotpoint.prototype.creatDom = function (data, index) {
  515. var _index = +index + 1;
  516. return "<li data-spid=" + data.name + " id=ggg_s" + index + ">" +
  517. "<div class=icon></div>" +
  518. "<div class=title>热点" + _index + "</div>" +
  519. "<div class=DelConfirm>确定删除</div>" +
  520. "<div class=del></div>" +
  521. "</li>";
  522. }
  523. //添加热点列表
  524. Hotpoint.prototype.addHotList = function (data, index) {
  525. if (!data) return;
  526. this.spotList.children("ul").append(this.creatDom(data, index));
  527. //保存热点信息到热点dom元素中
  528. var spotList = $(".spotList ul").children("#ggg_s" + index);
  529. spotList[0].hotAttribute = g_HotMeshes[index];
  530. spotList.attr('data-spid', g_HotMeshes[index].belongHot.sid);
  531. }
  532. //添加热点音乐
  533. Hotpoint.prototype.addMusic = function () {
  534. var mediaUpload = $("#hotpointDetail .audio.mediaUpload");
  535. mediaUpload.find("input").on("change", function () {
  536. var file = this.files[0];
  537. mediaUpload.find(".innerBtn").text("替换");
  538. mediaUpload.find(".playBox").removeClass("hide");
  539. mediaUpload.find(".title").text(file.name);
  540. mediaUpload.find('#query-bgm').attr('href', URL.createObjectURL(file));
  541. });
  542. //删除音乐
  543. mediaUpload.on("click", ".delete", function () {
  544. mediaUpload.find('#query-bgm').attr('href', "");
  545. mediaUpload.find(".playBox").addClass("hide");
  546. mediaUpload.find(".innerBtn").text("上传");
  547. mediaUpload.find("input").val("").removeAttr("data-hotbgm");
  548. })
  549. }
  550. //添加热点模型列表dom
  551. Hotpoint.prototype.inputList = function (text, val) {
  552. var _val = '';
  553. if (arguments[1]) {
  554. _val = 'value=' + val;
  555. }
  556. return '<div class="link"> <input class="text" type="text" placeholder=' + text + ' spellcheck="false" ' + _val + ' > </div>'
  557. }
  558. //添加热点模型
  559. Hotpoint.prototype.addModel = function () {
  560. var text = this.inputList("请填写模型链接");
  561. this.hotpointDetail.find(".model .add").on('click', function () {
  562. $(this).closest(".model").find(".list").append(text)
  563. });
  564. this.hotpointDetail.find(".model .delete").on('click', function () {
  565. $(this).closest(".model").find(".list > div:last").remove();
  566. });
  567. }
  568. //添加网页链接
  569. Hotpoint.prototype.addwebPack = function () {
  570. var text = this.inputList("请填写网页链接", "");
  571. this.hotpointDetail.find(".webPage .add").on('click', function () {
  572. $(this).closest(".webPage").find(".list").append(text)
  573. });
  574. this.hotpointDetail.find(".webPage .delete").on('click', function () {
  575. $(this).closest(".webPage").find(".list > div:last").remove();
  576. });
  577. }
  578. // 保存热点信息
  579. Hotpoint.prototype.saveHot = function () {
  580. var $layout = $(".edit-loading");
  581. var hotpointDetail = this.hotpointDetail;
  582. hotpointDetail.find(".tail .submit").on('click', function () {
  583. //显示loading
  584. $layout.removeClass('hide');
  585. var args = {};
  586. //热点标题
  587. var $title = hotpointDetail.find(".info input");
  588. //热点内容
  589. var $content = hotpointDetail.find(".info textarea");
  590. //热点图片
  591. var $images = hotpointDetail.find(".photo .edit-fun-images a.result");
  592. //热点视频
  593. var $videos = hotpointDetail.find(".video .edit-fun-images a.result");
  594. //热点视频的图片
  595. var $thums = hotpointDetail.find(".video .edit-fun-images .upload-thum");
  596. //热点模型
  597. var $modules = hotpointDetail.find(".model input");
  598. //热点内嵌网页
  599. var $iframes = hotpointDetail.find(".webPage input");
  600. //热点音乐
  601. var $miusc = hotpointDetail.find("#upload-hotBgm");
  602. let $bgName = hotpointDetail.find('.title');
  603. new Promise(function (resolve, reject) {
  604. //获取热点图片所有的路径
  605. upload($images, 'images', resolve)
  606. }).then(function (imgUrls) {
  607. args.images = imgUrls
  608. //获取热点视频所有的路径
  609. return new Promise(function (resolve, reject) {
  610. upload($videos, 'images', resolve)
  611. })
  612. }).then(function (videoUrls) {
  613. args.video = videoUrls
  614. //获取热点视频图片所有的路径
  615. return new Promise(function (resolve, reject) {
  616. upload($thums, 'images', resolve)
  617. })
  618. }).then(function (thums) {
  619. args.video = args.video.map(function (video, index) {
  620. return {
  621. url: video,
  622. img: thums[index]
  623. }
  624. })
  625. }).then(function () {
  626. //获取热点音乐所有的路径
  627. //console.log($miusc)
  628. if ($miusc[0].files.length > 0) {
  629. return new Promise(function (resolve) {
  630. upload($miusc, 'miusc', function (res) {
  631. resolve(res[0])
  632. })
  633. })
  634. } else {
  635. return $miusc.attr('data-hotBgm')
  636. }
  637. }).then(function (src) {
  638. args.backgroundMusic = src
  639. args.bgName = $bgName[0].innerHTML;
  640. }).then(function () {
  641. //获取热点标题、内容、内嵌网页、模型网页。
  642. args.title = $title.val()
  643. args.content = $content.val()
  644. var iframes = []
  645. for (var i = 0; i < $iframes.length; i++) {
  646. var iframe = $iframes.eq(i).val()
  647. iframe && iframes.push(iframe)
  648. }
  649. args.iframe = iframes
  650. var modules = []
  651. for (var i = 0; i < $modules.length; i++) {
  652. var module = $modules.eq(i).val()
  653. module && modules.push(module)
  654. }
  655. args.model = modules
  656. return args
  657. }).then(function (args) {
  658. //把获取的所有信息都保存在对应热点的dom元素里面
  659. hotpointDetail[0].targetDOM.infoAttribute = args;
  660. $layout.addClass('hide');
  661. hotpointDetail.addClass("atRight");
  662. })
  663. })
  664. }
  665. //背景音乐
  666. var EditMiuse = function () {
  667. this.mediaUpload = $(".music .audio.mediaUpload");
  668. this.success = function (text, url) {
  669. this.mediaUpload.find(".innerBtn").text("替换");
  670. this.mediaUpload.find(".playBox").removeClass("hide");
  671. this.mediaUpload.find(".title").text(text);
  672. this.mediaUpload.find('#query-bgm').attr('href', "//" + url)
  673. };
  674. this.delete = function () {
  675. this.mediaUpload.find('#query-bgm').attr('href', "");
  676. this.mediaUpload.find(".playBox").addClass("hide");
  677. this.mediaUpload.find(".innerBtn").text("上传");
  678. this.mediaUpload.find("input").val("");
  679. };
  680. var that = this;
  681. $('#upload-bgm').on('change', function () {
  682. var file = this.files[0];
  683. uploadMiuse(file, function (rs, file) {
  684. if (rs.code === 200) {
  685. that.success(file.name, rs.content)
  686. }
  687. })
  688. });
  689. //删除音乐
  690. this.mediaUpload.on("click", ".delete", function () {
  691. that.delete();
  692. })
  693. }
  694. EditMiuse.prototype.init = function (data) {
  695. if (!data.backgroundMusic) return;
  696. this.success("backgound", data.backgroundMusic);
  697. }
  698. //导览编辑
  699. var EditGuide = function () {
  700. this.$list = $('#guide-list')
  701. this.tourDetail = $('#tourEdit'); // 导览编辑
  702. this.targetTourPoint = null; // fyz 记录当前编辑的导览点
  703. // fyz 导览音乐队列
  704. this.tourAudio = {};
  705. }
  706. /**
  707. * @author fyz 2019.07.31
  708. * @description 新增参数data2, 表示data2.js中的数据
  709. */
  710. EditGuide.prototype.init = function (data, data2) {
  711. this.creatDom(data, data2);
  712. this.addTourMusic(); // 添加导览音乐
  713. this.tourAudio = data2.tourAudio || {};
  714. var that = this;
  715. //点击添加导览
  716. $('.addTour .innerBtn').on("click", function () {//点击截取视图
  717. addTour(this);
  718. }.bind(this));
  719. // 重新录制导览
  720. $('#renewTourBtn').on("click", function () {//点击截取视图
  721. addTour(this, true);
  722. }.bind(this));
  723. // 确认并保存导览信息
  724. $('#tourSubmit').on("click", function () {//点击截取视图
  725. this.saveGuide();
  726. }.bind(this));
  727. function addTour(that, renew) {
  728. var ev = document.createEvent("MouseEvent");//"MouseEvent"
  729. ev.initMouseEvent("snapshotBegin", true, true, document.defaultView, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
  730. g_snapShotWidth = 200;
  731. g_snapShotHeight = 140;
  732. ev.__callback = function (imgData, info) {
  733. that.uploadGuide(imgData, info, renew, that.targetTourPoint)
  734. }.bind(that);
  735. window.dispatchEvent(ev);
  736. }
  737. // fyz 点击导览名字, 对导览进行详细编辑
  738. $('.tourList ul').on('click', function (ev) {
  739. var $seft = $(ev.target)
  740. if ($seft.attr('data-oper') === 'tour-text') {
  741. // $seft.siblings('input').removeClass('hide').closest('li').siblings().find('input').addClass('hide');
  742. // $seft.siblings('input').focus();
  743. that.editGuideData($seft);
  744. }
  745. if ($seft.attr('data-oper') === 'tour-delete') {
  746. var choice = confirm("你确定删除吗?");
  747. if (choice) {
  748. $seft.closest('li').remove();
  749. }
  750. else {
  751. return false
  752. }
  753. }
  754. }).on("change", function (ev) {
  755. this.inputDone(ev)
  756. }.bind(this))
  757. $('.tourList ul input').on('blur', function (ev) {
  758. this.inputDone(ev)
  759. }.bind(this)).on('keydown', function (ev) {
  760. ev.stopPropagation()
  761. })
  762. //点击导览编辑窗口右上角的关闭按钮
  763. this.tourDetail.find("a.close, button.cancel").on("click", function () {
  764. that.targetTourPoint[0].musicSta = true; // 取消操作, 重置状态
  765. that.tourDetail.addClass("atRight");
  766. });
  767. /*fyz 导览列表拖拽以改变导览点的顺序 */
  768. let tourListNode = document.querySelector('#tourListWrap');
  769. let draging = null;
  770. tourListNode.ondragstart = function (event) {
  771. event.dataTransfer.setData("te", event.target.innerText); //不能使用text,firefox会打开新tab
  772. draging = event.target;
  773. }
  774. tourListNode.ondragover = function (event) {
  775. event.preventDefault();
  776. let target = event.target.parentNode.parentNode;
  777. let dragingIndex = draging.querySelector('#index');
  778. let targetIndex = target.querySelector('#index');
  779. // 判断dragover是否发生在LI元素上
  780. if (target.nodeName === 'LI' && target !== draging) {
  781. var targetRect = target.getBoundingClientRect();
  782. var dragingRect = draging.getBoundingClientRect();
  783. if (target && target.animated) {
  784. return;
  785. }
  786. let ulElem = target.parentNode; // 寻找到 ul节点
  787. if (getIndex(draging) < getIndex(target)) {
  788. dragingIndex.innerText = [targetIndex.innerText, targetIndex.innerText = dragingIndex.innerText][0]; // 交换两个节点的序号
  789. ulElem.insertBefore(draging, target.nextSibling);
  790. } else {
  791. dragingIndex.innerText = [targetIndex.innerText, targetIndex.innerText = dragingIndex.innerText][0];
  792. ulElem.insertBefore(draging, target);
  793. }
  794. _animate(dragingRect, draging);
  795. _animate(targetRect, target);
  796. }
  797. }
  798. }
  799. /**
  800. * @author fyz 编辑导览数据
  801. * @param {any} target 所点击的导览点
  802. */
  803. EditGuide.prototype.editGuideData = function (target) {
  804. this.targetTourPoint = target; // 记录当前编辑的导览点
  805. var that = this;
  806. $('#tourEdit').removeClass('atRight'); // 显示导览编辑的工具栏
  807. document.querySelector('#tourName input').value = target.context.textContent; // 显示已有的导览名字
  808. $("#tourEdit .audio.mediaUpload").find("input").val(''); // 点击编辑导览清空上一次文件
  809. target[0].musicSta = true;
  810. // 判断当前点是否有导览音频
  811. var audio = this.tourAudio[target.closest('li')[0].data.sid];
  812. var musicUrl = audio ? audio.music : null;
  813. if (musicUrl) {
  814. var musicName = audio.name || '导览音频.mp3' // 获取音频的文件名
  815. this.tourDetail.find(".audio .playBox").removeClass("hide");
  816. this.tourDetail.find("#upload-hotBgm").attr('data-hotBgm', musicUrl)
  817. this.tourDetail.find(".audio .playBox a").attr("href", "//" + musicUrl);
  818. this.tourDetail.find(".audio .submit").text("替换");
  819. this.tourDetail.find("#tourMusicName").text(musicName);
  820. } else {
  821. this.tourDetail.find(".audio .playBox").addClass("hide");
  822. this.tourDetail.find(".audio .submit").text("上传");
  823. }
  824. }
  825. /**
  826. * @author fyz 保存导览数据
  827. */
  828. EditGuide.prototype.saveGuide = function () {
  829. var $layout = $(".edit-loading");
  830. $layout.removeClass('hide');
  831. var that = this;
  832. var tourDetail = this.tourDetail;
  833. var tourName = tourDetail.find('#tourNameInput').val() || this.targetTourPoint.context.innerText;
  834. var curTourPoint = this.targetTourPoint.context.closest('li');
  835. this.targetTourPoint.text(tourName); // 输入框未输入数据则保留原来的值
  836. curTourPoint.data.name = tourName;
  837. // 导览音乐
  838. var tourAudio = this.tourDetail.find('#uploadTourBgm');
  839. var tourName = this.tourDetail.find("#tourMusicName").text(); // 记录音频名称
  840. var sid = curTourPoint.data.sid;
  841. // 判断当前编辑的导览点位是否已上传音乐
  842. if (tourAudio[0].files.length > 0 && this.targetTourPoint[0].musicSta) { // 已添加导览音乐
  843. new Promise(function (resolve, reject) {
  844. uploadMiuse(tourAudio[0].files[0], function (res) {
  845. resolve(res.content);
  846. })
  847. }).then(function (src) {
  848. var audio = new Audio();
  849. audio.src = '//' + src;
  850. audio.onloadedmetadata = function () {
  851. // 对返回的src进行处理, 去掉前面域名, 尽量避免修改main.js
  852. var srcArr = src.split('/');
  853. srcArr[0] = '';
  854. src = srcArr.join('/');
  855. that.tourAudio[sid] = {
  856. "name": tourName,
  857. "music": '/' + src,
  858. "time": Math.round(audio.duration * 1000 + 1000)
  859. }
  860. $layout.addClass('hide');
  861. $('#tourEdit').addClass('atRight'); // 显示导览编辑的工具栏
  862. }
  863. })
  864. } else if (!this.targetTourPoint[0].musicSta) { // 删除导览音乐, 将数据重置
  865. this.tourAudio[sid] = {
  866. "music": "",
  867. "time": 0
  868. }
  869. $layout.addClass('hide');
  870. $('#tourEdit').addClass('atRight'); // 显示导览编辑的工具栏
  871. } else { // 未添加导览音乐
  872. $layout.addClass('hide');
  873. $('#tourEdit').addClass('atRight'); // 显示导览编辑的工具栏
  874. }
  875. }
  876. //添加导览音乐
  877. EditGuide.prototype.addTourMusic = function () {
  878. var mediaUpload = $("#tourEdit .audio.mediaUpload");
  879. var that = this;
  880. mediaUpload.find("input").on("change", function () {
  881. var file = this.files[0];
  882. mediaUpload.find(".innerBtn").text("替换");
  883. mediaUpload.find(".playBox").removeClass("hide");
  884. mediaUpload.find(".title").text(file.name);
  885. mediaUpload.find('#query-bgm').attr('href', URL.createObjectURL(file));
  886. that.targetTourPoint[0].musicSta = true;
  887. });
  888. mediaUpload.find("input").on("click", function () {
  889. mediaUpload
  890. });
  891. //删除音乐
  892. mediaUpload.on("click", ".delete", function () {
  893. mediaUpload.find('#query-bgm').attr('href', "");
  894. mediaUpload.find(".playBox").addClass("hide");
  895. mediaUpload.find(".innerBtn").text("上传");
  896. mediaUpload.find("input").val("").removeAttr("data-hotbgm");
  897. that.targetTourPoint[0].musicSta = false;
  898. })
  899. }
  900. /**
  901. * @author fyz 2019.07.31
  902. * @description 新增参数data2
  903. * @param {object} data someData.js中的模型数据
  904. * @param {object} data2 data2.js中的导览和热点数据
  905. */
  906. EditGuide.prototype.creatDom = function (data, data2) {
  907. var $lis = [];
  908. var that = this;
  909. var tourAudio = data2.tourAudio || {};
  910. data.model.images.forEach(function (i, index) {
  911. if (i.thumbnail_signed_src) {
  912. var $li = $(that.dom(index, i.name, i.thumbnail_signed_src));
  913. $li[0].data = i
  914. // 挂载当前导览点对应的音频链接
  915. if (i.sid in tourAudio && tourAudio[i.sid].music && tourAudio[i.sid].music !== '') {
  916. $li[0].musicUrl = tourAudio[i.sid].music;
  917. }
  918. $lis.push($li)
  919. }
  920. })
  921. $(".tourList > ul").append($lis)
  922. }
  923. EditGuide.prototype.dom = function (index, title, img) {
  924. return '<li draggable="true">' +
  925. '<div>' +
  926. '<span id="index">' + index + '</span>' +
  927. '<div class="line"></div>' +
  928. '</div>' +
  929. '<div>' +
  930. '<span class="guide-name" data-oper=tour-text>' + title + '</span>' +
  931. '<input maxlength="14" class="hide" data-oper=tour-input>' +
  932. '</div>' +
  933. '<div class="preview" >' +
  934. '<div id="tourBg" style="background-image: url(//' + img + ');" data-oper=tour-delete>' +
  935. '</div>' +
  936. '</div>' +
  937. '</li >';
  938. }
  939. /**
  940. * @author fyz
  941. * @param target 当前导览点的父级li元素
  942. */
  943. EditGuide.prototype.inputDone = function (ev, target) {
  944. var $seft = $(ev.target)
  945. if ($seft.attr('data-oper') === 'tour-input') {
  946. // $seft.addClass('hide') // fyz 现有的实现方式不隐藏输入框
  947. var name = target.siblings('span').context.innerText;
  948. $seft.text($seft.val() || name); // fyz 如果未输入数据, 则保留原来的导览名字
  949. //更改导览横向列表的名字:
  950. target.siblings('span').context.innerText = $seft.val() || name;
  951. target.closest('li')[0].data.name = $seft.val() || name;
  952. }
  953. }
  954. /**
  955. * @author fyz 2019.07.31
  956. * @description uploadGuide方法新增参数renew状态码, 表示是否重新录制当前导览, 新增targetTourPoint, 记录当前的导览点元素
  957. */
  958. EditGuide.prototype.uploadGuide = function (urlData, guide, renew, target) {
  959. var that = this;
  960. uploadImg(urlData, function (rs) {
  961. if (rs.code === 200) {
  962. var editGuide = new EditGuide();
  963. var sid = rs.content.substring(rs.content.lastIndexOf('/') + 1, rs.content.lastIndexOf('.'));
  964. var thumbnail_signed_src = rs.content;
  965. var args = JSON.parse("{" + guide + "}");
  966. args.sid = sid;
  967. args.name = sid;
  968. args.thumbnail_signed_src = thumbnail_signed_src;
  969. args.metadata = JSON.stringify({
  970. camera_mode: 0,
  971. camera_position: {
  972. x: args.metadata.camera_position[0],
  973. y: args.metadata.camera_position[1],
  974. z: args.metadata.camera_position[2]
  975. },
  976. camera_quaternion: {
  977. x: args.metadata.camera_quaternion[0],
  978. y: args.metadata.camera_quaternion[1],
  979. z: args.metadata.camera_quaternion[2],
  980. w: args.metadata.camera_quaternion[3]
  981. },
  982. ortho_zoom: -1,
  983. scan_id: args.metadata.scan_id,
  984. final_angle: 110,
  985. is_ortho: false,
  986. zoom: args.metadata.zoom // fyz zoom是内部计算的zoomLevel, 乘以系数1.06才是实际缩放倍数
  987. })
  988. if (renew && target) { // 重新录制导览
  989. var oldId = target.closest('li')[0].data.sid;
  990. that.tourAudio[args.sid] = that.tourAudio[oldId]; // 新生成的id指向以前的导览音频
  991. delete that.tourAudio[oldId]; // 删除导览音频中的旧导览id
  992. target.closest('li')[0].data = args; // 更新数据
  993. target.closest('li').find('#tourBg')[0].style.backgroundImage = 'url(//' + args.thumbnail_signed_src + ')';
  994. target.text(args.name); // 更新导览列表中的导览名称
  995. $('#tourEdit').find('#tourNameInput').val(args.name); // 修改输入框内容
  996. } else {
  997. var index = $(".tourList ul li").length + 1;
  998. var $li = $(editGuide.dom(index, args.name, args.thumbnail_signed_src));
  999. $li[0].data = args;
  1000. $(".tourList ul").append($li);
  1001. }
  1002. }
  1003. })
  1004. }
  1005. /* -- 以下是一些公用的方法 -- */
  1006. //限制大小
  1007. var restrictedSize = function (file, _size) {
  1008. //限制大小不大于8m
  1009. var fileSize = 0;
  1010. var isIE = /msie/i.test(navigator.userAgent) && !window.opera;
  1011. if (isIE && !file) {
  1012. var fileSystem = new ActiveXObject("Scripting.FileSystemObject");
  1013. var _file = fileSystem.GetFile(filepath);
  1014. fileSize = _file.Size;
  1015. } else {
  1016. fileSize = file.size;
  1017. }
  1018. var size = fileSize / 1024;
  1019. var RSize = _size * 1024;
  1020. if (size > RSize) {
  1021. alert("文件不能大于" + _size + "M");
  1022. return false;
  1023. }
  1024. if (size <= 0) {
  1025. alert("文件大小不能为0M!");
  1026. return false;
  1027. }
  1028. return true
  1029. }
  1030. //上传音乐
  1031. var uploadMiuse = function (file, callback) {
  1032. if (!/audio\/\w+/.test(file.type)) {
  1033. alert("文件必须为音乐!");
  1034. return false;
  1035. }
  1036. //限制大小不大于8m
  1037. if (!restrictedSize(file, 8)) {
  1038. return false
  1039. }
  1040. uploadFile(file, 'audio', callback);
  1041. }
  1042. //上传图片
  1043. function uploadImg(urlData, callback) {
  1044. var bytes = window.atob(urlData.split(',')[1]); //去掉url的头,并转换为byte
  1045. //处理异常,将ascii码小于0的转换为大于0
  1046. var ab = new ArrayBuffer(bytes.length);
  1047. var ia = new Uint8Array(ab);
  1048. for (var i = 0; i < bytes.length; i++) {
  1049. ia[i] = bytes.charCodeAt(i);
  1050. }
  1051. var blob = new Blob([ab], { type: 'image/jpeg' });
  1052. uploadFile(blob, 'hot/images', callback);
  1053. }
  1054. //上传文件
  1055. function uploadFile(file, type, callback) {
  1056. $(".edit-loading").removeClass("hide");
  1057. var formData = new FormData()
  1058. formData.append('name', number)
  1059. formData.append('dir', type)
  1060. formData.append('random', true)
  1061. formData.append('file', file)
  1062. $.ajax({
  1063. url: ceshi + '/uploadFile',
  1064. data: formData,
  1065. dataType: 'json',
  1066. type: 'POST',
  1067. cache: false,//上传文件无需缓存
  1068. processData: false,//用于对data参数进行序列化处理 这里必须false
  1069. contentType: false, //必须
  1070. success: function (rs) {
  1071. callback(rs, file);
  1072. $(".edit-loading").addClass("hide");
  1073. }
  1074. })
  1075. }
  1076. function _animate(prevRect, target) {
  1077. var ms = 300;
  1078. if (ms) {
  1079. var currentRect = target.getBoundingClientRect();
  1080. if (prevRect.nodeType === 1) {
  1081. prevRect = prevRect.getBoundingClientRect();
  1082. }
  1083. _css(target, 'transition', 'none');
  1084. _css(target, 'transform', 'translate3d(' +
  1085. (prevRect.left - currentRect.left) + 'px,' +
  1086. (prevRect.top - currentRect.top) + 'px,0)'
  1087. );
  1088. target.offsetWidth; // 触发重绘
  1089. //放在timeout里面也可以
  1090. // setTimeout(function() {
  1091. // _css(target, 'transition', 'all ' + ms + 'ms');
  1092. // _css(target, 'transform', 'translate3d(0,0,0)');
  1093. // }, 0);
  1094. _css(target, 'transition', 'all ' + ms + 'ms');
  1095. _css(target, 'transform', 'translate3d(0,0,0)');
  1096. clearTimeout(target.animated);
  1097. target.animated = setTimeout(function () {
  1098. _css(target, 'transition', '');
  1099. _css(target, 'transform', '');
  1100. target.animated = false;
  1101. }, ms);
  1102. }
  1103. }
  1104. //给元素添加style
  1105. function _css(el, prop, val) {
  1106. var style = el && el.style;
  1107. if (style) {
  1108. if (val === void 0) {
  1109. if (document.defaultView && document.defaultView.getComputedStyle) {
  1110. val = document.defaultView.getComputedStyle(el, '');
  1111. } else if (el.currentStyle) {
  1112. val = el.currentStyle;
  1113. }
  1114. return prop === void 0 ? val : val[prop];
  1115. } else {
  1116. if (!(prop in style)) {
  1117. prop = '-webkit-' + prop;
  1118. }
  1119. style[prop] = val + (typeof val === 'string' ? '' : 'px');
  1120. }
  1121. }
  1122. }
  1123. function upload($files, type, cb) {
  1124. var length = $files.length
  1125. var rcount = 0
  1126. var result = []
  1127. Array.from($files).forEach(function (dFile) {
  1128. //a 标签的success 是用来判断是否是已经上传过的文件
  1129. //attr-thum 属性是视频的图片
  1130. //videoURL 是判断是否有视频
  1131. var $file = $(dFile)
  1132. var $image = $file.find('img')
  1133. if ($file.hasClass('success')) {
  1134. if ($file.attr('attr-thum')) {
  1135. result.push($file.attr('attr-thum'))
  1136. } else if ($image.attr('videoURL')) {
  1137. result.push($image.attr('videoURL'))
  1138. } else {
  1139. result.push($image.attr('src'))
  1140. }
  1141. return success(++rcount);
  1142. } else {
  1143. switch ($file[0].localName) {
  1144. case "input":
  1145. dFile = $file[0]
  1146. break;
  1147. case "span":
  1148. dFile = $file.find('input')[0];
  1149. break;
  1150. case "a":
  1151. dFile = $file.find('input')[0];
  1152. break;
  1153. default:
  1154. dFile = $file.closest("li").find('.upload input')[0];
  1155. break;
  1156. }
  1157. // dFile = $file[0].localName === "input" ? $file[0] : $file[0].localName === "span" ? $file.find('input')[0] : $file.closest("li").find('.upload input')[0];
  1158. }
  1159. var file = (dFile.files && dFile.files[0]) || '';
  1160. if (!file) return success(++rcount);
  1161. uploadFile(file, 'hot/' + type, function (rs) {
  1162. if (rs.code === 200) {
  1163. result.push(rs.content)
  1164. };
  1165. success(++rcount);
  1166. })
  1167. })
  1168. //判断当前队列元素是否处理成功
  1169. function success() {
  1170. if (rcount === length) {
  1171. cb(result)
  1172. }
  1173. }
  1174. success()
  1175. }
  1176. function getIndex(el) {
  1177. let index = 0;
  1178. if (!el || !el.parentNode) {
  1179. return -1;
  1180. }
  1181. while (el && (el = el.previousElementSibling)) {
  1182. index++;
  1183. }
  1184. return index;
  1185. }