edit.js 47 KB

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