فهرست منبع

Merge branch 'feature/gemer' of http://face3d.4dage.com:7005/chenzhiguang/qjkankan_v1.1.1 into feature/gemer

gemercheung 2 سال پیش
والد
کامیت
42bd90d69b
31فایلهای تغییر یافته به همراه2029 افزوده شده و 1097 حذف شده
  1. 6 8
      packages/qjkankan-editor/public/static/lib/krpano/js/tour copy.js
  2. 14 0
      packages/qjkankan-editor/public/static/lib/krpano/js/tour-1.19-pr13.js
  3. 12 0
      packages/qjkankan-editor/public/static/lib/krpano/js/tour-1.20.11.js
  4. 5 5
      packages/qjkankan-editor/public/static/lib/krpano/js/tour.js
  5. BIN
      packages/qjkankan-editor/public/static/panoassets/images/hotspot/image_place_holder.png
  6. 539 0
      packages/qjkankan-editor/public/static/template/customTooltip.xml
  7. 23 0
      packages/qjkankan-editor/public/static/template/skin/customTooltip.json
  8. 358 401
      packages/qjkankan-editor/public/static/template/skin/vtourskin.xml
  9. 39 0
      packages/qjkankan-editor/public/static/template/test.xml
  10. 2 1
      packages/qjkankan-editor/src/core/angle.js
  11. 4 0
      packages/qjkankan-editor/src/core/getSerialFrame.js
  12. 145 0
      packages/qjkankan-editor/src/core/hotspot.js
  13. 64 44
      packages/qjkankan-editor/src/core/utils.js
  14. 1 0
      packages/qjkankan-editor/src/framework/core/index.vue
  15. 77 57
      packages/qjkankan-editor/src/views/hotspot/EditPanel.vue
  16. 25 20
      packages/qjkankan-editor/src/views/hotspot/HotSpotList.vue
  17. 243 199
      packages/qjkankan-editor/src/views/hotspot/hotspotIconType/personalized_tag.vue
  18. 110 82
      packages/qjkankan-editor/src/views/hotspot/hotspotIconType/serial_frame.vue
  19. 20 0
      packages/qjkankan-kankan-view/.env.testprod
  20. 21 0
      packages/qjkankan-kankan-view/.env.testserve
  21. 2 1
      packages/qjkankan-kankan-view/package.json
  22. 2 2
      packages/qjkankan-kankan-view/public/smg.html
  23. 2 2
      packages/qjkankan-kankan-view/public/spg.html
  24. 2 2
      packages/qjkankan-kankan-view/src/components/Tags/index.vue
  25. 4 2
      packages/qjkankan-kankan-view/src/pages/SMG.vue
  26. 1 0
      packages/qjkankan-kankan-view/src/pages/SPG.vue
  27. 1 2
      packages/qjkankan-view/.env.testdev
  28. 1 3
      packages/qjkankan-view/package.json
  29. 1 1
      packages/qjkankan-view/public/showviewer/lib/krpano/skin/vtourskin.xml
  30. 26 10
      packages/qjkankan-view/src/sdk/QJKanKan/modules/Tags.js
  31. 279 255
      yarn.lock

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 6 - 8
packages/qjkankan-editor/public/static/lib/krpano/js/tour copy.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 14 - 0
packages/qjkankan-editor/public/static/lib/krpano/js/tour-1.19-pr13.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 12 - 0
packages/qjkankan-editor/public/static/lib/krpano/js/tour-1.20.11.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 5 - 5
packages/qjkankan-editor/public/static/lib/krpano/js/tour.js


BIN
packages/qjkankan-editor/public/static/panoassets/images/hotspot/image_place_holder.png


+ 539 - 0
packages/qjkankan-editor/public/static/template/customTooltip.xml

@@ -0,0 +1,539 @@
+<krpano>
+    <!-- 1.20. 新热点模式 -->
+    <action name="addJQHotspot">
+        showlog();
+        set(hsp_name,%1); 
+        set(hsp_type,%2); 
+        txtadd(iconUrl,'',%4);
+        txtreplace(iconUrl,'|',',');
+                        <!-- trace('originName::',%1); -->
+        if(%2 LE 1,
+                                             <!-- trace('id==',get(hsp_name),"::",get(iconUrl)); -->
+             set(hotspot[get(hsp_name)].type,'image');
+             set(hotspot[get(hsp_name)].url,get(iconUrl));
+         );
+        ifnot(%2 LE 1, set(hotspot[get(hsp_name)].type, 'text'));
+
+        <!-- 其他标签 (0,1,2)-->
+    
+        set(hotspot[get(hsp_name)].name,%1);
+        set(hotspot[get(hsp_name)].hotspottype,%2);
+        set(hotspot[get(hsp_name)].hotspottitle,%3);
+        set(hotspot[get(hsp_name)].hotspotStyle,%10);
+        set(hotspot[get(hsp_name)].hotlink,%7);
+        set(hotspot[get(hsp_name)].ath,%5);
+        set(hotspot[get(hsp_name)].atv,%6);
+        set(hotspot[get(hsp_name)].visible,true);
+        set(hotspot[get(hsp_name)].alpha,1);
+        set(hotspot[get(hsp_name)].scale,1);
+        set(hotspot[get(hsp_name)].autoalpha,false);
+        set(hotspot[get(hsp_name)].distorted,false);
+        set(hotspot[get(hsp_name)].border,false);
+        set(hotspot[get(hsp_name)].onclick,'js(__krfn.utils.linkopen(%7,%1));');
+        set(hotspot[get(hsp_name)].ondown,dragJQhotspot(););
+        set(hotspot[get(hsp_name)].onup,js(console.log('0');__krfn.angle.updateHotSpotData(get(xml.scene),get(name),get(ath),get(atv))));
+
+        txtsplit(%10,'|',fontSize,pos,isHover,borderColor,fillColor,textColor,isShowLine,isTextWrap,lineDirection,textDirection,textNumPerLine,duration,frameNumber,framewidth);
+        set(hotspot[get(hsp_name)].pos,pos);
+        txtadd(hotspot[get(hsp_name)].onloaded,"add_tooltip_label();add_tooltip_dot();");
+
+       if(%2 LE 2,
+         set(hotspot[get(hsp_name)].height,%8);
+         set(hotspot[get(hsp_name)].width,%8);
+         set(hotspot[get(hsp_name)].crop,'');
+         <!-- txtadd(hotspot[get(hsp_name)].onloaded,"add_tooltip_label(get(%1));"); -->
+        if(%2 == 2,
+         trace('ser_frame::',get(framewidth));
+         set(hotspot[get(hsp_name)].url,get(iconUrl));
+         set(hotspot[get(hsp_name)].framewidth,get(framewidth));
+         set(hotspot[get(hsp_name)].frames,get(frameNumber));
+
+         crop_animation_r_stop(get(hsp_name));
+
+         txtadd(hotspot[get(hsp_name)].onloaded,"trace('onloaded::',get(frameNumber),get(framewidth));do_crop_animation(get(framewidth),get(framewidth),get(frameNumber));"););
+        );
+        
+        <!-- 个性化标签(3) -->
+        if(%2 == 3,    
+            set(hotspot[get(hsp_name)].height,80);
+            set(hotspot[get(hsp_name)].width,1);
+            set(hotspot[get(hsp_name)].padding,0);
+            set(hotspot[get(hsp_name)].background,false);
+            txtadd(line,'<div style="background-color: ',get(borderColor),';width:1px;height:80px;"></div>');
+            copy(hotspot[get(hsp_name)].html,line);
+            <!-- txtadd(hotspot[get(hsp_name)].onloaded,"add_tooltip_label();add_tooltip_dot();"); -->
+            set_label_dir(get(hsp_name),get(lineDirection),0);
+           
+        );
+
+        addhotspot(get(hsp_name));
+    </action>
+
+	<action name="do_crop_animation">
+        registerattribute(xframes, calc((imagewidth / %1) BOR 0));
+        registerattribute(yframes, calc((imageheight / %2) BOR 0)); 
+        registerattribute(frames, calc(xframes * yframes));
+        registerattribute(frame, 0); 
+        registerattribute(animatiedOn, 1); 
+        registerattribute(frameRate, calc(1.0 / %3)); 
+        set(crop, '0|0|%1|%2'); 
+        clearinterval(calc('crop_anim_' + name));
+        if(frameRate GE 0,
+        setinterval(
+            calc('crop_anim_' + name),
+            get(frameRate),
+            if(loaded, 
+                inc(frame); 
+                if(frame GE frames, if(onlastframe !== null, onlastframe() ); set(frame,0); );
+                mod(xpos,frame, xframes); 
+                div(ypos, frame, xframes);
+                <!-- trace('onging::',get(frames)); -->
+                Math.floor(ypos);
+                mul(xpos, %1);
+                mul(ypos, %2); 
+                calc(crop, xpos +'|' + ypos + '|%1|%2');
+             
+                if(animatiedOn == 0, 
+                 clearinterval(calc('crop_anim_' + name));
+                );
+,
+                clearinterval(calc('crop_anim_' + name));
+            );
+        );
+        );   
+	</action>
+    <action name="crop_animation_r_stop">
+      set(cur,%1);
+      tolower(cur, cur);
+      set(curIn,  calc('crop_anim_r_' + cur));
+      clearinterval(curIn); 
+    </action>
+    
+    <action name="crop_animation_reapply">
+        txtadd(cur,'',%1);
+        tolower(cur, cur);
+        txtadd(frameRate,'',%2);
+        txtadd(framewidth,'',%3);
+        txtadd(frameNumber,'',%4);
+        copy(frames, hotspot[get(cur)].frames);
+        copy(xframes, hotspot[get(cur)].xframes);
+        copy(yframes, hotspot[get(cur)].yframes);
+        copy(animatiedOn, hotspot[get(cur)].animatiedOn);
+        set(frame,0);
+        set(curIn,  calc('crop_anim_r_' + cur));
+
+        clearinterval(curIn); 
+        if(get(frameRate) GE 0,
+           setinterval(curIn,
+            get(frameRate),
+            inc(frame);
+            copy(on, hotspot[get(cur)].on);
+         
+            if(frame GE frames, set(frame,0); );
+            mod(xpos,frame, xframes); 
+            div(ypos, frame, xframes);
+            Math.floor(ypos);
+            mul(xpos, framewidth);
+            mul(ypos,framewidth); 
+            trace('frame-1::',get(animatiedOn));
+            calc(crop, xpos +'|' + ypos + '|'+framewidth +'|' + framewidth);
+            if(frames == -1, 
+                 copy(hotspot[get(hsp_name)].crop,'0|0|204|204');
+            );
+            <!-- trace('replaying::',get(frame));  -->
+            copy(hotspot[get(hsp_name)].crop,crop);
+        );
+        );
+    
+    </action>
+
+    <action name="add_tooltip_label">
+        txtadd(tooltipname, 'tooltip_', get(name)); 
+        txtsplit(hotspotStyle,'|',fontSize,pos,isHover,borderColor,fillColor,textColor,isShowLine,isTextWrap,lineDirection,textDirection,textNumPerLine,duration,frameNumber);
+        txtadd(pName, get(name)); 
+        addlayer(get(tooltipname));
+        txtadd(layer[get(tooltipname)].parent, 'hotspot[', get(name), ']');
+        set(layer[get(tooltipname)].autowidth, true);
+        set(layer[get(tooltipname)].width,'prop');
+        <!-- set(layer[get(tooltipname)].height,30);  -->
+        set(layer[get(tooltipname)].height,30); 
+        set(layer[get(tooltipname)].edge,center);
+        set(layer[get(tooltipname)].background,false);
+        set(layer[get(tooltipname)].pos,pos);
+        set(layer[get(tooltipname)].padding,0);
+        set(layer[get(tooltipname)].type,'html');
+        set(layer[get(tooltipname)].url,'%SWFPATH%/plugins/textfield.swf');
+        set(layer[get(tooltipname)].border,false);
+        set(layer[get(tooltipname)].align,center);
+        copy(layer[get(tooltipname)].hotlink, hotspot[get(name)].hotlink);
+        set(layer[get(tooltipname)].ondown,'dragJQlayer();');
+        
+        set(layer[get(tooltipname)].onclick,JQlayerClick);
+        set(layer[get(tooltipname)].onup,js(console.log('1');__krfn.angle.updateHotSpotData(get(xml.scene),get(hsName),get(ath),get(atv))));
+                                        <!-- set(hotspot[get(hsp_name)].onup,js(__krfn.angle.updateHotSpotData(get(xml.scene),get(name),get(ath),get(atv)))); -->
+        txtadd(labelCode, '<div style="display: flex; align-items: center; justify-content: center; position: relative; border: 1px solid ',get(borderColor),'; padding: 6px 10px; white-space: pre; border-radius: 5px; background: ',get(fillColor),'">','            <div style="text-align: left; font-size:',get(fontSize),'px; color: ',get(textColor),'; line-height: 1.4;">',get(hotspottitle),'</div>
+        </div>'); 
+        
+                                <!-- label方位 -->
+        if(get(hotspottype) LE 2,
+       <!-- trace('hotspottype::',get(hotspottype),'::tooltipname::',get(tooltipname),'pos::',get(pos)); -->
+        <!-- set_label_pos(get(tooltipname),get(pos)); -->
+        delayedcall(0.1,
+            txtadd(tooltipname, 'tooltip_', get(name)); 
+            set_label_pos(get(tooltipname),get(pos));
+         );
+       );
+
+        <!-- 个性化标签(3) -->
+        if(get(hotspottype) == 3,    
+            set(layer[get(tooltipname)].direction,get(lineDirection));
+            delayedcall(0.2,txtadd(tooltipname, 'tooltip_', get(name)); set_label_dir(get(tooltipname),get(layer[get(tooltipname)].direction),1); );
+      
+
+        );
+        copy(layer[get(tooltipname)].html, labelCode);
+            
+    </action>
+    <!-- <style name="tooltip_dot_bg" type="container" border-radius="50%" bgcolor="0xFFFFFF" bgalpha="0.9" height="20" width="20" keep="true" /> -->
+    <action name='add_tooltip_dot'>
+        txtadd(tooldot, 'tooldot_', get(name)); 
+        <!-- trace('hey::',get(borderColor)); -->
+        addlayer(get(tooldot));
+        txtadd(layer[get(tooldot)].parent, 'hotspot[', get(name), ']');
+        set(layer[get(tooldot)].width,10); 
+        set(layer[get(tooldot)].height,10); 
+        set(layer[get(tooldot)].padding,0); 
+       
+        set(layer[get(tooldot)].align,center);
+        set(layer[get(tooldot)].type,'text');
+        set(layer[get(tooldot)].background,false);
+        txtadd(dborderColor,'rgba(255,255,255,0.5)');
+        txtadd(dot,'<div style="background-color: ',get(borderColor),';width:10px;height:10px;"></div>');
+        copy(layer[get(tooldot)].html,dot);
+        set(layer[get(tooldot)].backgroundcolor,get(borderColor)); 
+        set(layer[get(tooldot)].backgroundalpha,0.9); 
+        set(layer[get(tooldot)].bgroundedge,5);
+        set(layer[get(tooldot)].onclick,JQlayerClick);
+        set(layer[get(tooldot)].ondown,'dragJQlayer();');
+        set(layer[get(tooldot)].visible,false);
+        set(layer[get(tooldot)].onup,js(console.log('2');__krfn.angle.updateHotSpotData(get(xml.scene),get(hsName),get(ath),get(atv))));
+
+        <!-- 个性化标签(3) -->
+        if(get(hotspottype) == 3,    
+            <!-- trace('lineDirection3::',lineDirection);  -->
+                            <!-- call(set_label_dir); -->
+            set(layer[get(tooldot)].visible,true);
+            set_label_dir(get(tooldot),get(lineDirection),2);            
+        );
+
+    </action>
+    <action name='set_label_dir'>
+     txtadd(dirItem,'',%1);
+     txtadd(lineDirection,'',%2);
+     txtadd(dir,'',%3);
+     <!-- trace('get-lineDirection::',%2); -->
+     <!-- trace('set_label_dir::1::',get(dirItem),'::2::',get(lineDirection),'::3::',get(dir)); -->
+     if(
+        get(dir)==1,
+        <!-- trace('set_label_dir::1::',get(dirItem),'::2::',get(lineDirection),'::3::',get(dir)); -->
+        copy(labelWidth,layer[get(dirItem)].width);
+        <!-- trace('dirItem::',get(layer[get(dirItem)].width)); -->
+     );
+
+        if(
+             get(lineDirection) == 'right-top',
+            if(get(dir)==0,set(hotspot[get(dirItem)].rotate,35));
+            if(get(dir)==1,set(layer[get(dirItem)].rotate,-35);set(layer[get(dirItem)].x,0);set(layer[get(dirItem)].y,-60););
+            if(get(dir)==2,set(layer[get(dirItem)].x,0);set(layer[get(dirItem)].y,40););
+        );
+        if(
+             get(lineDirection) == 'right-center',
+             if(get(dir)==0,set(hotspot[get(dirItem)].rotate,90););
+             <!-- if(get(dir)==1,set(layer[get(dirItem)].rotate,-90);set(layer[get(dirItem)].x,0);set(layer[get(dirItem)].y,-80)); -->
+             if(get(dir)==1,
+                trace('labelWidth::',labelWidth);
+                set(layer[get(dirItem)].rotate,-90);
+                set(layer[get(dirItem)].x,0);
+                sub(labelWidth,25);
+                mul(labelWidth,-1);
+                set(layer[get(dirItem)].y,get(labelWidth));
+                );
+           
+             if(get(dir)==2,set(layer[get(dirItem)].x,0);set(layer[get(dirItem)].y,40););
+        );
+        if(
+             get(lineDirection) == 'right-bottom',
+            if(get(dir)==0,set(hotspot[get(dirItem)].rotate,-35));
+            if(get(dir)==1,set(layer[get(dirItem)].rotate,35);set(layer[get(dirItem)].x,0);set(layer[get(dirItem)].y,60));
+            if(get(dir)==2,set(layer[get(dirItem)].x,0);set(layer[get(dirItem)].y,-40););
+        );
+        if(
+             get(lineDirection) == 'center-top',
+            if(get(dir)==0,set(hotspot[get(dirItem)].rotate,0));
+            if(get(dir)==1,set(layer[get(dirItem)].rotate,0);set(layer[get(dirItem)].x,0);set(layer[get(dirItem)].y,-60));
+            if(get(dir)==2,set(layer[get(dirItem)].x,0);set(layer[get(dirItem)].y,40););
+        );
+        if(get(lineDirection) == 'center-bottom',
+            if(get(dir)==0,set(hotspot[get(dirItem)].rotate,0));
+            if(get(dir)==1,set(layer[get(dirItem)].rotate,0);set(layer[get(dirItem)].x,0);set(layer[get(dirItem)].y,55));
+            if(get(dir)==2,set(layer[get(dirItem)].x,0);set(layer[get(dirItem)].y,-40););
+        );
+        if( get(lineDirection) == 'left-top',
+            if(get(dir)==0,set(hotspot[get(dirItem)].rotate,-35));
+   ;        if(get(dir)==1,set(layer[get(dirItem)].rotate,35);set(layer[get(dirItem)].x,0);set(layer[get(dirItem)].y,-60));
+            if(get(dir)==2,set(layer[get(dirItem)].x,0);set(layer[get(dirItem)].y,40););
+        );
+        if(
+             get(lineDirection) == 'left-center',
+             if(get(dir)==0,set(hotspot[get(dirItem)].rotate,90));
+             
+             if(get(dir)==1,
+                set(layer[get(dirItem)].rotate,-90);
+                set(layer[get(dirItem)].x,0);
+                sub(labelWidth,25);
+                set(layer[get(dirItem)].y,get(labelWidth));
+                );
+             if(get(dir)==2,set(layer[get(dirItem)].x,0);set(layer[get(dirItem)].y,-40););
+        );
+        if(
+            get(lineDirection) == 'left-bottom',
+            if(get(dir)==0,set(hotspot[get(dirItem)].rotate,35));
+            if(get(dir)==1,set(layer[get(dirItem)].rotate,-35);set(layer[get(dirItem)].x,0);set(layer[get(dirItem)].y,60));
+            if(get(dir)==2,set(layer[get(dirItem)].x,0);set(layer[get(dirItem)].y,-40););
+
+        );
+
+    </action>
+
+    <action name='set_label_pos'>
+        <!-- label方位 -->
+       set(posName,%1);
+       set(pos,%2);
+       copy(hp,posName);
+       txtreplace(hp,'tooltip_','');
+
+       copy(hwidth, hotspot[get(hp)].width);
+       copy(hheight, hotspot[get(hp)].height);
+   
+       copy(lwidth, layer[get(posName)].width);
+       copy(lheight, layer[get(posName)].height);
+   
+        if(
+            pos == 'top',
+            add(all,lheight,hheight);
+            div(dpy,all,2); 
+            add(lastPy,dpy,10);
+            mul(lastPy, -1);
+            set(layer[get(posName)].align,center);
+            set(layer[get(posName)].y,get(lastPy));
+            set(layer[get(posName)].x,0);
+        );
+         if(
+            pos == 'bottom',
+            add(all,lheight,hheight);
+            div(dpy,all,2); 
+            add(lastPy,dpy,10);
+            mul(lastPy, 1);
+            set(layer[get(posName)].align,center);
+            set(layer[get(posName)].y,get(lastPy));
+            set(layer[get(posName)].x,0);
+        );
+        if(
+            pos == 'left',
+            add(all,lwidth,hwidth);
+            div(dpx,all,2); 
+            add(lastPx,dpx,10);
+            mul(lastPx, -1);
+            set(layer[get(posName)].align,center);
+            set(layer[get(posName)].x,get(lastPx));
+            set(layer[get(posName)].y,0);
+        );
+        if(
+            pos == 'right',
+            add(all,lwidth,hwidth);
+            div(dpx,all,2); 
+            add(lastPx,dpx,10);
+            mul(lastPx, 1);
+            set(layer[get(posName)].align,center);
+            set(layer[get(posName)].x,get(lastPx));
+            set(layer[get(posName)].y,0);
+        );
+    </action>
+
+ 
+    <action name="removeJQHotspot">
+        set(delHotspot,%1);
+        removehotspot(%1,true);
+        txtadd(delHotspotLabel,'tooltip_',get(delHotspot));
+        txtadd(delHotspotdot,'tooldot_',get(delHotspot));
+        removelayer(get(delHotspotLabel));
+        removelayer(get(delHotspotdot));
+    </action>
+    
+    <action name="cancelJQHotspot">
+        set(canclHotspot,%1);
+        crop_animation_r_stop(%1);
+    </action>
+
+    <!-- 编辑热点 -->
+    <action name="editJQHotspot">
+      showlog();
+      set(hsp_name,%1); 
+      set(hsp_type,%2); 
+      set(dImage,'static/panoassets/images/hotspot/image_place_holder.png');
+      txtadd(hsLabel, 'tooltip_', %1); 
+      txtadd(hsDot, 'tooldot_', %1); 
+      set(hotspot[get(hsp_name)].hotspottitle,%3);
+      set(hotspot[get(hsp_name)].hotspotStyle,%10);
+      copy(hotspot[get(hsp_name)].borderWidth,false);
+      copy(layer[get(hsLabel)].borderWidth,false);
+      copy(layer[get(hsDot)].borderWidth,false);
+      set(hotspot[get(hsp_name)].background,false);
+      txtsplit(%10,'|',fontSize,pos,isHover,borderColor,fillColor,textColor,isShowLine,isTextWrap,lineDirection,textDirection,textNumPerLine,duration,frameNumber,framewidth);
+      txtadd(labelCode, '<div style="min-height:30px; display: flex; align-items: center; justify-content: center; position: relative; border: 1px solid ',get(borderColor) ,'; padding: 6px 10px; white-space: pre; border-radius: 5px; background: ',get(fillColor),'">','        <div style="text-align: left; font-size:',get(fontSize),'px; color: ',get(textColor),'; line-height: 1.4;">',%3,'</div>
+    </div>');     
+      copy(layer[get(hsLabel)].html, labelCode);
+      copy(layer[get(hsLabel)].pos, pos);
+      trace('editJQHotspot',%1,'::type::',%3);
+
+      if(%3 == '', 
+        trace('title-empty');
+        set(layer[get(hsLabel)].height,12));
+      
+        <!-- if(%3 == '', 
+         trace('title-empty');
+        set(layer[get(hsLabel)].height,12)
+         );
+        ifnot(%3 == '',trace('has-title'); set(layer[get(hsLabel)].height,30);); -->
+
+      if(get(hsp_type) == 3,
+  
+        set(hotspot[get(hsp_name)].rotate,0);
+        set(layer[get(hsLabel)].rotate,0)
+        set(hotspot[get(hsp_name)].type,'text');
+        set(hotspot[get(hsp_name)].width,1);
+        set(hotspot[get(hsp_name)].height,80);
+        set(hotspot[get(hsp_name)].padding,0);
+
+        
+        txtadd(line,'<div style="background-color: ',get(borderColor),';width:1px;height:80px;"></div>');
+        txtadd(dot,'<div style="background-color: ',get(borderColor),';width:10px;height:10px;"></div>');
+        copy(hotspot[get(hsp_name)].html,line);
+        copy(layer[get(hsDot)].html,dot);
+        set(layer[get(hsDot)].visible,true);
+
+        set_label_dir(get(hsp_name),get(lineDirection),0);
+        set_label_dir(get(hsLabel),get(lineDirection),1);
+        set_label_dir(get(hsDot),get(lineDirection),2);
+
+       );
+      if(get(hsp_type) LE 2,
+        trace('edit2::',get(hsp_name));
+        txtadd(iconUrl,'',%4);
+        txtreplace(iconUrl,'|',',');
+        trace('iconUrl::',iconUrl);
+        set(hotspot[get(hsp_name)].height,%8);
+        set(hotspot[get(hsp_name)].width,%8);
+
+       delayedcall(0.1,
+       txtadd(tooltipname, 'tooltip_', get(hsp_name)); 
+       set_label_pos(get(tooltipname),get(layer[get(tooltipname)].pos));
+       );
+       <!-- 序列化类型编辑 -->
+        if(get(hsp_type) == 2, 
+         indexoftxt(index, get(iconUrl), 'image_place_holder.png');
+ 
+         if(get(index) GT -1,trace('place-holder');
+          set(hotspot[get(hsp_name)].animatiedOn,0);
+          set(hotspot[get(hsp_name)].crop,'');
+          crop_animation_r_stop(get(hsp_name));
+          );
+
+         ifnot(get(index) GT -1, 
+          set(hotspot[get(hsp_name)].animatiedOn,0);
+          set(hotspot[get(hsp_name)].visible,true);
+          set(hotspot[get(hsp_name)].frames,get(frameNumber));
+          calc(frameRate, duration / frameNumber);
+
+          set(hotspot[get(hsp_name)].frameRate,get(frameRate));
+
+          trace('frameRate::',get(frameRate));
+          trace('frameNumber::',get(frameNumber));
+          trace('framewidth::',get(framewidth));
+          trace('duration::',get(duration));
+          set(hotspot[get(hsp_name)].xframes,1);
+          set(hotspot[get(hsp_name)].yframes,1,get(frameNumber));
+         crop_animation_reapply(get(hsp_name),get(frameRate),get(framewidth),get(frameNumber));
+          <!-- do_crop_animation(get(hsp_name),get(frameRate),get(frameNumber)); -->
+        <!-- do_crop_animation(get(framewidth),get(framewidth),get(frameNumber));"); -->
+         );
+        );
+     
+        set(hotspot[get(hsp_name)].url,get(iconUrl));
+        set(hotspot[get(hsp_name)].rotate,0);
+        set(layer[get(hsLabel)].rotate,0);
+        set(layer[get(hsDot)].visible,false);
+  
+       );
+      
+
+</action>
+
+<action name="dragJQlayer"> 
+       txtadd(hsName, '', get(name)); 
+       txtreplace(hsName, 'tooltip_', ''); 
+       txtreplace(hsName, 'tooldot_', ''); 
+                <!-- copy(drag_currentx, x);
+        copy(drag_currenty, y);
+        copy(drag_stagex, mouse.stagex); 
+        copy(drag_stagey, mouse.stagey);
+        indexoftxt(align_contains_right, get(align), 'right');
+        indexoftxt(align_contains_bottom, get(align), 'bottom'); 
+        calc(drag_align_x, align_contains_right GE 0 ? -1 : +1);
+        calc(drag_align_y, align_contains_bottom GE 0 ? -1 : +1);    
+        -->
+        
+        copy(hath, hotspot[get(hsName)].ath);
+        copy(hatv, hotspot[get(hsName)].atv);
+        spheretoscreen(hath, hatv, hotspotcenterx, hotspotcentery, 'l');
+        sub(drag_adjustx,mouse.stagex, hotspotcenterx);
+        sub(drag_adjusty,mouse.stagey, hotspotcentery); 
+    
+        asyncloop(
+                        <!-- 计算热点中心点 -->
+            pressed,
+            sub(dx, mouse.stagex, drag_adjustx);
+            sub(dy, mouse.stagey, drag_adjusty);
+            screentosphere(dx, dy, ath, atv); 
+                        <!-- 更新 -->
+            copy(hotspot[get(hsName)].ath, ath);
+            copy(hotspot[get(hsName)].atv, atv);,
+            set(global.ath,get(ath));
+            set(global.atv,get(atv));
+        );   
+
+</action>
+
+<action name='JQlayerClick'>
+       txtadd(clickName, '', get(name)); 
+       txtreplace(clickName, 'tooltip_', ''); 
+       txtreplace(clickName, 'tooldot_', ''); 
+               <!-- trace('JQlayerClick',get(clickName)); -->
+       js(__krfn.utils.linkopen(get(hotlink),get(clickName)));
+</action>
+
+<action name="dragJQhotspot">
+        trace('dragJQhotspot::',ath,atv);
+
+        spheretoscreen(ath, atv, hotspotcenterx, hotspotcentery, 'l');
+        sub(drag_adjustx,mouse.stagex, hotspotcenterx);
+        sub(drag_adjusty,mouse.stagey, hotspotcentery); 
+    
+        asyncloop(
+            pressed, 
+            sub(dx, mouse.stagex, drag_adjustx);
+            sub(dy, mouse.stagey, drag_adjusty);
+            screentosphere(dx, dy, ath, atv);
+        );
+</action>
+</krpano>

+ 23 - 0
packages/qjkankan-editor/public/static/template/skin/customTooltip.json

@@ -0,0 +1,23 @@
+{
+    "id": "",
+    "title": "",
+    "type": 0, 
+    "contentType": "",
+    "ath": 0,
+    "atv": 0,
+    "link": "",
+    "icon": "",
+    "visible": true,
+    "style": {
+        "fontSize": 12,
+        "positon": "top",
+        "isHover": false,
+        "borderColor": "",
+        "isShowLine": "",
+        "isTextWrap": "",
+        "lineDirection": "",
+        "textColor": "",
+        "textDirection": "",
+        "textNumPerLine": ""
+    }
+}

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 358 - 401
packages/qjkankan-editor/public/static/template/skin/vtourskin.xml


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 39 - 0
packages/qjkankan-editor/public/static/template/test.xml


+ 2 - 1
packages/qjkankan-editor/src/core/angle.js

@@ -17,9 +17,10 @@ export default class Angle {
    * @param {*} hotspotType 
    */
   updateHotSpotData(hsName, hpname, ath, atv) {
+    console.log('updateHotSpotData', arguments);
     this.ath = ath;
     this.atv = atv;
-    if (ath && atv ) {
+    if (ath && atv) {
       vue.$bus.emit('updateHotSpotHV', { hsName, hpname, ath, atv })
     }
   }

+ 4 - 0
packages/qjkankan-editor/src/core/getSerialFrame.js

@@ -0,0 +1,4 @@
+
+export const getSerialFrame = (imageId) => {
+     const image = doc
+}

+ 145 - 0
packages/qjkankan-editor/src/core/hotspot.js

@@ -0,0 +1,145 @@
+/**
+ * krpano 1.20 全景hotspot统一schema
+ *
+ * 
+ *  */
+import config from '../config'
+
+const initState = {
+    id: "",
+    title: "",
+    type: 0, // 热点大类型 
+    ath: 0,
+    atv: 0,
+    link: "",
+    icon: "",
+    visible: true,
+    size: 0,
+    style: {
+        fontSize: 12,
+        position: "top",
+        isHover: false,
+        borderColor: "",
+        fillColor: "",
+        textColor: "",
+        isShowLine: "",
+        isTextWrap: "",
+        lineDirection: "",
+        textDirection: "",
+        textNumPerLine: "",
+        duration: 0,
+        frameNumber: 0,
+        frameWidth: 0,
+    }
+}
+//基本样式汇总
+const convertBaseStyle = (dest, origin) => {
+    if (dest) {
+        // normal
+        dest.style.fontSize = origin.fontSize
+        dest.style.position = origin.titlePosition
+
+        if (origin && origin.titleDisplayMode == "always") {
+            dest.visible = true
+        }
+        if (origin && origin.titleDisplayMode == "never") {
+            dest.visible = false
+        }
+        dest.style.borderColor = '';
+        dest.style.fillColor = 'rgba(0,0,0,0.8)';
+        dest.style.textColor = 'rgba(255,255,255,1)';
+    }
+      //custom
+      if (origin && origin.hotspotIconType === 'serial_frame') {
+        dest.style.duration = origin.serialFrameInfo.duration
+        dest.style.frameNumber = origin.serialFrameInfo.frameNumber
+        dest.style.frameWidth = origin.serialFrameInfo.frameWidth
+    }
+    //custom
+    if (origin && origin.hotspotIconType === 'personalized_tag') {
+        dest.style.borderColor = origin.personalizedTagInfo.borderColor;
+        dest.style.fillColor = origin.personalizedTagInfo.fillColor
+        dest.style.isTextWrap = origin.personalizedTagInfo.isTextWrap
+        dest.style.lineDirection = origin.personalizedTagInfo.lineDirection
+        dest.style.textColor = origin.personalizedTagInfo.textColor
+        dest.style.textDirection = origin.personalizedTagInfo.textDirection
+        dest.style.textNumPerLine = origin.personalizedTagInfo.textNumPerLine
+    }
+
+}
+
+const coverSystemIconPart = (origin) => {
+    const duplicate = structuredClone(initState)
+    duplicate.id = origin.name;
+    duplicate.title = origin.hotspotTitle;
+    duplicate.ath = origin.ath;
+    duplicate.atv = origin.atv;
+    duplicate.type = 0;
+    duplicate.icon = origin.img || '';
+    duplicate.link = origin.link || '';
+    duplicate.size = origin.size;
+    convertBaseStyle(duplicate, origin)
+    return duplicate;
+}
+
+const coverImageconPart = (origin) => {
+    const defaultImage = config.getStaticResource('/panoassets/images/hotspot/image_place_holder.png');
+    const duplicate = structuredClone(initState)
+    duplicate.id = origin.name;
+    duplicate.title = origin.hotspotTitle;
+    duplicate.ath = origin.ath;
+    duplicate.atv = origin.atv;
+    duplicate.type = 1;
+    duplicate.icon = origin.customIconInfo.img || defaultImage;
+    duplicate.link = origin.link || '';
+    duplicate.size = origin.size;
+    convertBaseStyle(duplicate, origin)
+    return duplicate;
+}
+const coverSerialFrame = (origin) => {
+    const duplicate = structuredClone(initState);
+    const defaultImage = config.getStaticResource('/panoassets/images/hotspot/image_place_holder.png');
+    // console.log('defaultImage', defaultImage);
+    duplicate.id = origin.name;
+    duplicate.title = origin.hotspotTitle;
+    duplicate.ath = origin.ath;
+    duplicate.atv = origin.atv;
+    duplicate.type = 2;
+    duplicate.icon = origin.serialFrameInfo.img || defaultImage;
+    duplicate.link = origin.link || '';
+    duplicate.size = origin.size;
+    convertBaseStyle(duplicate, origin)
+    return duplicate;
+}
+
+
+const coverpersonalizedTag = (origin) => {
+    const duplicate = structuredClone(initState);
+    duplicate.id = origin.name;
+    duplicate.title = origin.hotspotTitle;
+    duplicate.ath = origin.ath;
+    duplicate.atv = origin.atv;
+    duplicate.type = 3;
+    duplicate.link = origin.link || '';
+    duplicate.size = origin.size;
+    convertBaseStyle(duplicate, origin)
+    return duplicate;
+}
+
+
+export const convertJQHotspot = (origin) => {
+    const type = origin.hotspotIconType
+    switch (type) {
+        case 'system_icon':
+            return coverSystemIconPart(origin);
+        case 'custom_image':
+            return coverImageconPart(origin);
+        case 'serial_frame':
+            return coverSerialFrame(origin);
+        case 'personalized_tag':
+            return coverpersonalizedTag(origin);
+        default:
+            return false;
+    }
+}
+

+ 64 - 44
packages/qjkankan-editor/src/core/utils.js

@@ -1,6 +1,5 @@
-
 import Vue from 'vue'
-
+import { convertJQHotspot } from './hotspot'
 let vue = new Vue()
 
 export default class Utils {
@@ -59,19 +58,29 @@ export default class Utils {
    */
 
   edithotspot(krpano, param) {
-    krpano.call(`editImgTextHotSpot(
-      ${param.img},
-      ${param.name},
-      ${param.hotspotTitle},
-      ${param.ath},
-      ${param.atv},
-      ${true},
-      ${true},
-      ${param.link},
-      ${true},
-      ${param.visible},
-      ${param.size || 1},
-      ${param.fontSize})`);
+    try {
+      const hotspot = convertJQHotspot(param);
+      const hotspotStyle = Object.values(hotspot.style);
+      const hotspotString = hotspotStyle.join('|');
+      const hotspotSize = (Number(hotspot.size) || 1) * 50;
+      let icon = hotspot.icon.replace(/,/g, '|');
+      const callString = `editJQHotspot(
+        ${hotspot.id},
+        ${hotspot.type},
+        ${hotspot.title},
+        "${icon}",
+        ${hotspot.ath},
+        ${hotspot.atv},
+        "${hotspot.link}",
+        ${hotspotSize},
+        ${hotspot.visible},
+        "${hotspotString}"
+        )`;
+      // krpano.stopcall(callString);
+      krpano.call(callString);
+    } catch (error) {
+      console.error('error', error);
+    }
   }
 
 
@@ -80,36 +89,46 @@ export default class Utils {
    */
 
   addhotspot(krpano, param, type) {
-    krpano.set("curscreen_x", krpano.get('stagewidth') / 2);
-    krpano.set("curscreen_y", krpano.get('stageheight') / 2);
-    krpano.call("screentosphere(curscreen_x, curscreen_y, curscreen_ath, curscreen_atv);");
-    let ath = krpano.get("curscreen_ath");
-    let atv = krpano.get("curscreen_atv");
-
-    krpano.call(`addImgTextHotSpot(
-      ${param.img},
-      ${param.name},
-      ${param.hotspotTitle},
-      ${param.ath != '' ? param.ath : ath},
-      ${param.atv != '' ? param.atv : atv},
-      ${true},
-      ${type},
-      ${param.link},
-      ${true},
-      ${param.visible},
-      ${(param.size * 50) || 1},
-      ${Number(param.fontSize)})`);
-
+    /**
+     * type: 0,系统图标 , 1.自定义图际. 2.序列帧  3.个性标签
+     */
+    try {
+      krpano.set("curscreen_x", krpano.get('stagewidth') / 2);
+      krpano.set("curscreen_y", krpano.get('stageheight') / 2);
+      krpano.call("screentosphere(curscreen_x, curscreen_y, curscreen_ath, curscreen_atv);");
+      const hotspot = convertJQHotspot(param);
+      const hotspotStyle = Object.values(hotspot.style);
+      const hotspotString = hotspotStyle.join('|');
+      const hotspotSize = (Number(hotspot.size) || 1) * 50;
+      const ath = hotspot.ath != '' ? hotspot.ath : krpano.get("curscreen_ath");
+      const atv = hotspot.atv != '' ? hotspot.atv : krpano.get("curscreen_atv");
+      let icon = hotspot.icon.replace(/,/g, '|');
+      const callString = `addJQHotspot(
+        ${hotspot.id},
+        ${hotspot.type},
+        ${hotspot.title},
+        "${icon}",
+        ${ath},
+        ${atv},
+        "${hotspot.link}",
+        ${hotspotSize},
+        ${hotspot.visible},
+        "${hotspotString}"
+        )`;
+      krpano.call(callString);
+    } catch (error) {
+      console.error('error', error);
+    }
 
     // 设置热点图片默认的偏移值
-    let offset = '-130%'
-    if (param.size < 1) {
-      offset = '-200%'
-    }
-    if (param.size > 1) {
-      offset = '-100%'
-    }
-    krpano.set('layer[tooltip_' + param.name + '].y', `${offset}`)
+    // let offset = '-130%'
+    // if (param.size < 1) {
+    //   offset = '-200%'
+    // }
+    // if (param.size > 1) {
+    //   offset = '-100%'
+    // }
+    // krpano.set('layer[tooltip_' + param.name + '].y', `${offset}`)
 
   }
 
@@ -173,6 +192,7 @@ export default class Utils {
    */
 
   linkopen(sceneCode, id) {
+    // debugger;
     if (window.location.pathname.indexOf('show') > -1) {
       vue.$bus.emit('clickHotspot', id)
     }
@@ -202,7 +222,7 @@ export default class Utils {
     if (typeof someData == 'string') {
       mysd = JSON.parse(someData)
     }
-  
+
     mysd.hotspots.forEach(item => {
       this.addhotspot(krpano, item, type)
     });

+ 1 - 0
packages/qjkankan-editor/src/framework/core/index.vue

@@ -151,6 +151,7 @@ export default {
     this.$bus.on("addhotspot", (data) => {
       this.addhotspot(data);
     });
+   
   },
 };
 </script>

+ 77 - 57
packages/qjkankan-editor/src/views/hotspot/EditPanel.vue

@@ -241,18 +241,23 @@ export default {
   watch: {
     hotspot: {
       handler(val) {
-        console.error("this.hotspot", val);
-      },
-      deep: true,
-    },
-    hotspotIcon: {
-      handler(val) {
-        console.error("this.hotspotIcon", val);
-        val.img.length > 0 &&
-          this.$getKrpano().set(`hotspot[${this.hotspot.name}].url`, val.img);
+        // console.error("this.hotspot", val);
+        console.error("hotspot", val);
+        this.$bus.emit("edithotspot", val);
+        console.log("this.$bus", this.$bus);
+        // this.$getKrpano().call("removeJQHotspot(" + val.name + ");");
+        // this.$bus.emit("addhotspot", val);
       },
       deep: true,
     },
+    // hotspotIcon: {
+    //   handler(val) {
+    //     console.error("this.hotspotIcon", val);
+    //     val.img.length > 0 &&
+    //       this.$getKrpano().set(`hotspot[${this.hotspot.name}].url`, val.img);
+    //   },
+    //   deep: true,
+    // },
     // "hotspot.img": function () {
     //   console.log("this.hotspot.img", this.hotspot.img);
     //   this.$getKrpano().set(
@@ -260,54 +265,54 @@ export default {
     //     this.hotspot.img
     //   );
     // },
-    "hotspot.titlePosition": function (val) {
-      console.log("111", val);
-      if (val === "bottom") {
-        this.$getKrpano().set("layer[tooltip_" + this.hotspot.name + "].css");
-      }
-    },
-    "hotspot.hotspotTitle": function () {
-      this.$getKrpano().set(
-        "layer[tooltip_" + this.hotspot.name + "].html",
-        `<span style="color:white">${this.hotspot.hotspotTitle}</span>`
-      );
-    },
+    // "hotspot.titlePosition": function (val) {
+    //   console.log("111", val);
+    //   if (val === "bottom") {
+    //     this.$getKrpano().set("layer[tooltip_" + this.hotspot.name + "].css");
+    //   }
+    // },
+    // "hotspot.hotspotTitle": function () {
+    //   this.$getKrpano().set(
+    //     "layer[tooltip_" + this.hotspot.name + "].html",
+    //     `<span style="color:white">${this.hotspot.hotspotTitle}</span>`
+    //   );
+    // },
     // 'hotspot.visible': function () {
     //   this.$getKrpano().set('layer[tooltip_' + this.hotspot.name + '].visible', this.hotspot.visible)
     // },
-    "hotspot.size": {
-      immediate: true,
-      handler: function (newVal) {
-        let h = 52;
-        let scaleH = h * newVal;
+    // "hotspot.size": {
+    //   immediate: true,
+    //   handler: function (newVal) {
+    //     let h = 52;
+    //     let scaleH = h * newVal;
 
-        let offset = "-130%";
+    //     let offset = "-130%";
 
-        this.rang = { ...this.rang, value: newVal };
-        this.$getKrpano().set(`hotspot[${this.hotspot.name}].height`, scaleH);
+    //     this.rang = { ...this.rang, value: newVal };
+    //     this.$getKrpano().set(`hotspot[${this.hotspot.name}].height`, scaleH);
 
-        if (newVal < 1) {
-          offset = "-200%";
-        }
+    //     if (newVal < 1) {
+    //       offset = "-200%";
+    //     }
 
-        if (newVal > 1) {
-          offset = "-100%";
-        }
-        this.$getKrpano().set(
-          "layer[tooltip_" + this.hotspot.name + "].y",
-          `${offset}`
-        );
-      },
-    },
-    "hotspot.fontSize": {
-      handler: function (newVal) {
-        this.$getKrpano().set(
-          "layer[tooltip_" + this.hotspot.name + "].css",
-          `text-align:center; color:#FFFFFF;
-          font-family:STXihei;font-size:${newVal}px;`
-        );
-      },
-    },
+    //     if (newVal > 1) {
+    //       offset = "-100%";
+    //     }
+    //     this.$getKrpano().set(
+    //       "layer[tooltip_" + this.hotspot.name + "].y",
+    //       `${offset}`
+    //     );
+    //   },
+    // },
+    // "hotspot.fontSize": {
+    //   handler: function (newVal) {
+    //     this.$getKrpano().set(
+    //       "layer[tooltip_" + this.hotspot.name + "].css",
+    //       `text-align:center; color:#FFFFFF;
+    //       font-family:STXihei;font-size:${newVal}px;`
+    //     );
+    //   },
+    // },
   },
   beforeDestroy() {
     this.$bus.removeListener("resethotspotTitle", this.listerFnReset);
@@ -429,10 +434,16 @@ export default {
           }
           break;
         case "serial_frame":
+          // if (
+          //   !this.hotspot.serialFrameInfo.img ||
+          //   this.hotspot.serialFrameInfo.frameNumber <= 0 ||
+          //   this.hotspot.serialFrameInfo <= 0
+          // ) {
+          //   return false;
+          // }
+  
           if (
-            !this.hotspot.serialFrameInfo.url ||
-            this.hotspot.serialFrameInfo.frameNumber <= 0 ||
-            this.hotspot.serialFrameInfo <= 0
+            !this.hotspot.serialFrameInfo.img
           ) {
             return false;
           }
@@ -462,12 +473,15 @@ export default {
       });
     },
   },
+  beforeDestroy() {
+    this.$bus.off("edithotspot", this.handleEditHotspot);
+    this.$bus.off("delhotspot", this.cancel);
+  },
   mounted() {
     this.$bus.on("resethotspotTitle", this.listerFnReset);
 
-    this.$bus.on("delhotspot", () => {
-      this.cancel();
-    });
+    this.$bus.on("delhotspot", this.cancel);
+    this.$bus.on("edithotspot", this.handleEditHotspot);
 
     setTimeout(() => {
       if (
@@ -481,6 +495,10 @@ export default {
   },
 
   methods: {
+    handleEditHotspot(data) {
+      const krpano = document.getElementById("krpanoSWFObject");
+      __krfn.utils.edithotspot(krpano, data);
+    },
     handleSceneSelect(data) {
       this.hotspot.secne = {
         ...data,
@@ -573,6 +591,8 @@ export default {
 
     cancel() {
       this.$store.commit("SetHotspot", this.backupHotSpot);
+      console.log('cancel',this.backupHotSpot);
+      this.$getKrpano().call("cancelJQHotspot(" + this.backupHotSpot.name + ");");
       this.$emit("close", {
         type: this.editTitle == this.$i18n.t("hotspot.edit") ? "edit" : "add",
         data: this.backupHotSpot,
@@ -581,7 +601,7 @@ export default {
     reset(data) {
       this.$bus.emit("edithotspotTitle", data);
       this.$bus.emit("edithotspotTitleisShow", data);
-      this.$getKrpano().set(`hotspot[${data.name}].url`, data.img);
+      // this.$getKrpano().set(`hotspot[${data.name}].url`, data.img);
     },
     save() {
       this.$store.commit("SetHotspot", this.hotspot);

+ 25 - 20
packages/qjkankan-editor/src/views/hotspot/HotSpotList.vue

@@ -170,14 +170,15 @@ export default {
       let hptarget = this.someData.hotspots.find(
         (item) => item.name.toLowerCase() == data.hpname.toLowerCase()
       );
-      console.log(hptarget);
+      console.log(" this.someData.hotspots", this.someData.hotspots);
+      console.log("hptarget", hptarget);
       hptarget.ath = data.ath;
       hptarget.atv = data.atv;
     });
 
     this.$bus.on("openHotspot", (data) => {
-      let idx = this.someData.hotspots.findIndex((item) => item.name == data);
-      console.log(data);
+      let idx = this.someData.hotspots.findIndex((item) => item.name.toLowerCase() == data.toLowerCase());
+      // console.log(data);
       if (data == this.hotspot.name) {
         window.__krfn.utils.looktohotspot(this.$getKrpano(), this.hotspot.name);
         if (!this.showPanel) {
@@ -205,10 +206,10 @@ export default {
   },
   methods: {
     deleteKRHotspot(data) {
-      this.$getKrpano().call("removehotspot(" + data.name + ",true);");
-      this.$getKrpano().call(
-        "removeplugin(" + ("tooltip_" + data.name) + ",true);"
-      );
+      this.$getKrpano().call("removeJQHotspot(" + data.name + ");");
+      // this.$getKrpano().call(
+      //   "removeplugin(" + ("tooltip_" + data.name) + ",true);"
+      // );
     },
     close(data) {
       if (data) {
@@ -307,9 +308,9 @@ export default {
             // 热点图标类型为个性标签时,个性标签的数据
             isShowLine: true,
             lineDirection: "left-top",
-            fillColor: "rgba(0, 0, 0, 1)",
-            borderColor: "rgba(0, 0, 0, 1)",
-            textColor: "rgba(0, 0, 0, 1)",
+            fillColor: "rgba(0, 0, 0, 0.5)",
+            borderColor: "rgba(255, 255, 255, 0.8)",
+            textColor: "rgba(255, 255, 255, 1)",
             textDirection: "left-right",
             isTextWrap: false,
             textNumPerLine: 10,
@@ -401,16 +402,20 @@ export default {
             duration: 0,
           };
         }
-        hotspotData.personalizedTagInfo = {
-          isShowLine: true,
-          lineDirection: "left-top",
-          fillColor: "rgba(0, 0, 0, 1)",
-          borderColor: "rgba(0, 0, 0, 1)",
-          textColor: "rgba(0, 0, 0, 1)",
-          textDirection: "left-right",
-          isTextWrap: false,
-          textNumPerLine: 10,
-        };
+        if (!hotspotData.personalizedTagInfo) {
+          hotspotData.personalizedTagInfo = {
+            isShowLine: true,
+            lineDirection: "left-top",
+            fillColor: "rgba(0, 0, 0, 1)",
+            borderColor: "rgba(0, 0, 0, 1)",
+            textColor: "rgba(0, 0, 0, 1)",
+            textDirection: "left-right",
+            isTextWrap: false,
+            textNumPerLine: 10,
+          };
+        }
+  
+
         // v1.3把visible: Boolean换成了titleDisplayMode
         if (hotspotData.visible) {
           hotspotData.titleDisplayMode = "always";

+ 243 - 199
packages/qjkankan-editor/src/views/hotspot/hotspotIconType/personalized_tag.vue

@@ -1,26 +1,28 @@
 <template>
   <div class="hotspot-icon-personalized-tag">
     <div class="line-show-setting switcher-wrap">
-      <span class="label">{{$i18n.t('hotspot.if_show_marking_line')}}</span>
-      <Switcher :value="hotspot.personalizedTagInfo.isShowLine" @change="onSwitcherChange"></Switcher>
+      <span class="label">{{ $i18n.t("hotspot.if_show_marking_line") }}</span>
+      <Switcher
+        :value="hotspot.personalizedTagInfo.isShowLine"
+        @change="onSwitcherChange"
+      ></Switcher>
     </div>
-    
+
     <div class="svg-wrapper"></div>
 
-    <div class="remark-highlight">{{ $i18n.t('hotspot.hotspot_title') }}</div>
+    <div class="remark-highlight">{{ $i18n.t("hotspot.hotspot_title") }}</div>
     <div class="title-input-wrapper">
       <input
         v-model.trim="hotspot.hotspotTitle"
-        type="text" maxlength="15"
+        type="text"
+        maxlength="15"
         :placeholder="$i18n.t('hotspot.title_placeholder')"
       />
       <span class="count">{{ hotspot.hotspotTitle.length }}/15</span>
     </div>
 
-    <div class="remark">{{ $i18n.t('hotspot.hotspot_title') }}</div>
-    <div
-      class="color-picker-wrap"
-    >
+    <div class="remark">{{ $i18n.t("hotspot.hotspot_title") }}</div>
+    <div class="color-picker-wrap">
       <div class="color-value">{{ hotspot.personalizedTagInfo.fillColor }}</div>
       <div
         class="color-preview"
@@ -34,11 +36,11 @@
       />
     </div>
 
-    <div class="remark">{{ $i18n.t('hotspot.shape_border_color') }}</div>
-    <div
-      class="color-picker-wrap"
-    >
-      <div class="color-value">{{ hotspot.personalizedTagInfo.borderColor }}</div>
+    <div class="remark">{{ $i18n.t("hotspot.shape_border_color") }}</div>
+    <div class="color-picker-wrap">
+      <div class="color-value">
+        {{ hotspot.personalizedTagInfo.borderColor }}
+      </div>
       <div
         class="color-preview"
         :style="`background-color: ${hotspot.personalizedTagInfo.borderColor};`"
@@ -51,10 +53,8 @@
       />
     </div>
 
-    <div class="remark">{{ $i18n.t('hotspot.text_color') }}</div>
-    <div
-      class="color-picker-wrap"
-    >
+    <div class="remark">{{ $i18n.t("hotspot.text_color") }}</div>
+    <div class="color-picker-wrap">
       <div class="color-value">{{ hotspot.personalizedTagInfo.textColor }}</div>
       <div
         class="color-preview"
@@ -68,7 +68,7 @@
       />
     </div>
 
-    <div class="remark">{{ $i18n.t('hotspot.text_direction') }}</div>
+    <div class="remark">{{ $i18n.t("hotspot.text_direction") }}</div>
     <TabbarSwitcherIcon
       class="text-direction-switcher"
       :tabList="[
@@ -86,17 +86,20 @@
     />
 
     <div class="text-wrap-setting switcher-wrap">
-      <span class="label">{{ $i18n.t('hotspot.if_wrap') }}</span>
-      <Switcher :value="hotspot.personalizedTagInfo.isTextWrap" @change="onTextWrapChange"></Switcher>
+      <span class="label">{{ $i18n.t("hotspot.if_wrap") }}</span>
+      <Switcher
+        :value="hotspot.personalizedTagInfo.isTextWrap"
+        @change="onTextWrapChange"
+      ></Switcher>
     </div>
 
     <div
       class="text-num-per-line-wrap"
       :class="{
-        disable: !hotspot.personalizedTagInfo.isTextWrap
+        disable: !hotspot.personalizedTagInfo.isTextWrap,
       }"
     >
-      <div class="remark">{{ $i18n.t('hotspot.text_num_per_line') }}</div>
+      <div class="remark">{{ $i18n.t("hotspot.text_num_per_line") }}</div>
       <div class="value-wrap">
         <input
           v-model.trim.number="hotspot.personalizedTagInfo.textNumPerLine"
@@ -104,11 +107,10 @@
           type="number"
           min="1"
           :disabled="!hotspot.personalizedTagInfo.isTextWrap"
-        >
-        <span class="remark">{{ $i18n.t('hotspot.words') }}</span>
+        />
+        <span class="remark">{{ $i18n.t("hotspot.words") }}</span>
       </div>
     </div>
-
   </div>
 </template>
 
@@ -131,103 +133,103 @@ export default {
 
       endpointListForShow: [
         {
-          id: 'left-top',
-          x: 'calc(0% + 7px)',
-          cx: 'calc(0% + 7px + (7px / 2))',
-          y: 'calc(0% + 7px)',
-          cy: 'calc(0% + 7px + (7px / 2))',
+          id: "left-top",
+          x: "calc(0% + 7px)",
+          cx: "calc(0% + 7px + (7px / 2))",
+          y: "calc(0% + 7px)",
+          cy: "calc(0% + 7px + (7px / 2))",
         },
         {
-          id: 'center-top',
-          x: 'calc(50% - 7px / 2)',
-          cx: '50%',
-          y: 'calc(0% + 7px)',
-          cy: 'calc(0% + 7px + (7px / 2))',
+          id: "center-top",
+          x: "calc(50% - 7px / 2)",
+          cx: "50%",
+          y: "calc(0% + 7px)",
+          cy: "calc(0% + 7px + (7px / 2))",
         },
         {
-          id: 'right-top',
-          x: 'calc(100% - 7px - 7px)',
-          cx: 'calc(100% - 7px - (7px / 2))',
-          y: 'calc(0% + 7px)',
-          cy: 'calc(0% + 7px + (7px / 2))',
+          id: "right-top",
+          x: "calc(100% - 7px - 7px)",
+          cx: "calc(100% - 7px - (7px / 2))",
+          y: "calc(0% + 7px)",
+          cy: "calc(0% + 7px + (7px / 2))",
         },
         {
-          id: 'right-center',
-          x: 'calc(100% - 7px - 7px)',
-          cx: 'calc(100% - 7px - (7px / 2))',
-          y: 'calc(50% - 7px / 2)',
-          cy: '50%',
+          id: "right-center",
+          x: "calc(100% - 7px - 7px)",
+          cx: "calc(100% - 7px - (7px / 2))",
+          y: "calc(50% - 7px / 2)",
+          cy: "50%",
         },
         {
-          id: 'right-bottom',
-          x: 'calc(100% - 7px - 7px)',
-          cx: 'calc(100% - 7px - (7px / 2))',
-          y: 'calc(100% - 7px - 7px)',
-          cy: 'calc(100% - 7px - (7px / 2))',
+          id: "right-bottom",
+          x: "calc(100% - 7px - 7px)",
+          cx: "calc(100% - 7px - (7px / 2))",
+          y: "calc(100% - 7px - 7px)",
+          cy: "calc(100% - 7px - (7px / 2))",
         },
         {
-          id: 'center-bottom',
-          x: 'calc(50% - 7px / 2)',
-          cx: '50%',
-          y: 'calc(100% - 7px - 7px)',
-          cy: 'calc(100% - 7px - (7px / 2))',
+          id: "center-bottom",
+          x: "calc(50% - 7px / 2)",
+          cx: "50%",
+          y: "calc(100% - 7px - 7px)",
+          cy: "calc(100% - 7px - (7px / 2))",
         },
         {
-          id: 'left-bottom',
-          x: 'calc(0% + 7px)',
-          cx: 'calc(0% + 7px + (7px / 2))',
-          y: 'calc(100% - 7px - 7px)',
-          cy: 'calc(100% - 7px - (7px / 2))',
+          id: "left-bottom",
+          x: "calc(0% + 7px)",
+          cx: "calc(0% + 7px + (7px / 2))",
+          y: "calc(100% - 7px - 7px)",
+          cy: "calc(100% - 7px - (7px / 2))",
         },
         {
-          id: 'left-center',
-          x: 'calc(0% + 7px)',
-          cx: 'calc(0% + 7px + (7px / 2))',
-          y: 'calc(50% - 7px / 2)',
-          cy: '50%',
+          id: "left-center",
+          x: "calc(0% + 7px)",
+          cx: "calc(0% + 7px + (7px / 2))",
+          y: "calc(50% - 7px / 2)",
+          cy: "50%",
         },
       ],
 
       endpointListForClick: [
         {
-          id: 'left-top',
-          x: '0%',
-          y: '0%',
+          id: "left-top",
+          x: "0%",
+          y: "0%",
         },
         {
-          id: 'center-top',
-          x: 'calc(50% - 21px / 2)',
-          y: '0%',
+          id: "center-top",
+          x: "calc(50% - 21px / 2)",
+          y: "0%",
         },
         {
-          id: 'right-top',
-          x: 'calc(100% - 21px)',
-          y: '0%',
+          id: "right-top",
+          x: "calc(100% - 21px)",
+          y: "0%",
         },
         {
-          id: 'right-center',
-          x: 'calc(100% - 21px)',
-          y: 'calc(50% - 21px / 2)',
+          id: "right-center",
+          x: "calc(100% - 21px)",
+          y: "calc(50% - 21px / 2)",
         },
         {
-          id: 'right-bottom',
-          x: 'calc(100% - 21px)',
-          y: 'calc(100% - 21px)',
+          id: "right-bottom",
+          x: "calc(100% - 21px)",
+          y: "calc(100% - 21px)",
         },
         {
-          id: 'center-bottom',
-          x: 'calc(50% - 21px / 2)',
-          y: 'calc(100% - 21px)',
+          id: "center-bottom",
+          x: "calc(50% - 21px / 2)",
+          y: "calc(100% - 21px)",
         },
         {
-          id: 'left-bottom',
-          x: '0%',
-          y: 'calc(100% - 21px)',
+          id: "left-bottom",
+          x: "0%",
+          y: "calc(100% - 21px)",
         },
         {
-          id: 'left-center',
-          x: '0%',
-          y: 'calc(50% - 21px / 2)',
+          id: "left-center",
+          x: "0%",
+          y: "calc(50% - 21px / 2)",
         },
       ],
 
@@ -248,164 +250,206 @@ export default {
         "rgba(155, 155, 155, 1)",
         "rgba(255, 255, 255, 1)",
       ],
-    }
+    };
+  },
+  watch: {
+    "hotspot.personalizedTagInfo.lineDirection": {
+      handler: function (value) {
+        this.selectLineClick(value);
+      },
+      // deep: true,
+      immediate: true,
+    },
   },
   computed: {
     ...mapGetters({
-      hotspot: 'hotspot',
+      hotspot: "hotspot",
     }),
     currentTextDirectionIdx() {
       switch (this.hotspot.personalizedTagInfo.textDirection) {
-        case 'left-right':
-          return 0
-        case 'top-bottom':
-          return 1
-        default: 
-          return 0
+        case "left-right":
+          return 0;
+        case "top-bottom":
+          return 1;
+        default:
+          return 0;
       }
     },
   },
   methods: {
     onSwitcherChange(v) {
-      this.hotspot.personalizedTagInfo.isShowLine = v
+      this.hotspot.personalizedTagInfo.isShowLine = v;
     },
     onFillColorActiveChange(e) {
-      this.hotspot.personalizedTagInfo.fillColor = e
+      this.hotspot.personalizedTagInfo.fillColor = e;
     },
     onBorderColorActiveChange(e) {
-      this.hotspot.personalizedTagInfo.borderColor = e
+      this.hotspot.personalizedTagInfo.borderColor = e;
     },
     onTextColorActiveChange(e) {
-      this.hotspot.personalizedTagInfo.textColor = e
+      this.hotspot.personalizedTagInfo.textColor = e;
     },
     onSelectTextDirection(idx) {
       switch (idx) {
         case 0:
-          this.hotspot.personalizedTagInfo.textDirection = 'left-right'
+          this.hotspot.personalizedTagInfo.textDirection = "left-right";
           break;
         case 1:
-          this.hotspot.personalizedTagInfo.textDirection = 'top-bottom'
+          this.hotspot.personalizedTagInfo.textDirection = "top-bottom";
           break;
         default:
           break;
       }
     },
     onTextWrapChange(v) {
-      this.hotspot.personalizedTagInfo.isTextWrap = v
+      this.hotspot.personalizedTagInfo.isTextWrap = v;
     },
     onTextNumPerLineInputBlur() {
       if (this.hotspot.personalizedTagInfo.textNumPerLine < 1) {
-        this.hotspot.personalizedTagInfo.textNumPerLine = 1
+        this.hotspot.personalizedTagInfo.textNumPerLine = 1;
       } else {
-        this.hotspot.personalizedTagInfo.textNumPerLine = Math.round(this.hotspot.personalizedTagInfo.textNumPerLine)
+        this.hotspot.personalizedTagInfo.textNumPerLine = Math.round(
+          this.hotspot.personalizedTagInfo.textNumPerLine
+        );
       }
     },
+    selectLineClick(id) {
+      setTimeout(() => {
+        if (this.svgNode) {
+          console.log("id",  id);
+          const selectNode = this.svgNode
+            .selectAll("rect.endpoint-for-click")
+            .filter((d) => {
+              return d.id === id;
+            });
+          // console.log("selectNode", selectNode);
+          selectNode.dispatch("click");
+        }
+      }, 300);
+    },
   },
   mounted() {
-    this.svgNode = d3.select('.svg-wrapper')
+    this.svgNode = d3
+      .select(".svg-wrapper")
       .append("svg")
-      .attr("width", '100%')
-      .attr('height', '100%')
-      
+      .attr("width", "100%")
+      .attr("height", "100%");
+
     setTimeout(() => {
-      const that = this
+      const that = this;
 
       // 大方框
-      this.svgNode.append('rect')
-        .attr('x', 'calc(7px + (7px / 2))')
-        .attr('y', 'calc(7px + (7px / 2)')
-        .attr('width', 'calc(100% - (7px + (7px / 2)) * 2)')
-        .attr('height', 'calc(100% - (7px + (7px / 2)) * 2)')
-        .attr('fill', 'none')
-        .attr('stroke-width', '1px')
-        .attr('stroke', '#404040')
+      this.svgNode
+        .append("rect")
+        .attr("x", "calc(7px + (7px / 2))")
+        .attr("y", "calc(7px + (7px / 2)")
+        .attr("width", "calc(100% - (7px + (7px / 2)) * 2)")
+        .attr("height", "calc(100% - (7px + (7px / 2)) * 2)")
+        .attr("fill", "none")
+        .attr("stroke-width", "1px")
+        .attr("stroke", "#404040");
 
       // 中心小圆
-      this.svgNode.append('circle')
-        .attr('cx', '50%')
-        .attr('cy', '50%')
-        .attr('r', '5px')
-        .attr('fill', '#fff')
+      this.svgNode
+        .append("circle")
+        .attr("cx", "50%")
+        .attr("cy", "50%")
+        .attr("r", "5px")
+        .attr("fill", "#fff");
 
       // 中心稍大的圈
-      this.svgNode.append('circle')
-        .attr('cx', '50%')
-        .attr('cy', '50%')
-        .attr('r', '7px')
-        .attr('fill', 'none')
-        .attr('stroke-width', '1px')
-        .attr('stroke', 'rgba(255, 255, 255, 0.2)')
+      this.svgNode
+        .append("circle")
+        .attr("cx", "50%")
+        .attr("cy", "50%")
+        .attr("r", "7px")
+        .attr("fill", "none")
+        .attr("stroke-width", "1px")
+        .attr("stroke", "rgba(255, 255, 255, 0.2)");
 
       // 中心到各端点的线
-      this.svgNode.selectAll('line')
+      this.svgNode
+        .selectAll("line")
         .data(this.endpointListForShow)
         .enter()
-        .append('line')
-        .attr('x1', '50%')
-        .attr('y1', '50%')
-        .attr('x2', (d) => d.cx)
-        .attr('y2', (d) => d.cy)
-        .attr('stroke-width', '1px')
-        .attr('stroke', 'none')
+        .append("line")
+        .attr("x1", "50%")
+        .attr("y1", "50%")
+        .attr("x2", (d) => d.cx)
+        .attr("y2", (d) => d.cy)
+        .attr("stroke-width", "1px")
+        .attr("stroke", "none");
 
       // 各端点-用于显示
-      this.svgNode.selectAll('rect.endpoint-for-show')
+      this.svgNode
+        .selectAll("rect.endpoint-for-show")
         .data(this.endpointListForShow)
         .enter()
-        .append('rect')
-        .classed('endpoint-for-show', true)
-        .attr('x', (d) => d.x)
-        .attr('y', (d) => d.y)
-        .attr('width', '7px')
-        .attr('height', '7px')
-        .attr('rx', '2px')
-        .attr('ry', '2px')
-        .attr('fill', '#1a1b1d')
-        .attr('stroke-width', '1px')
-        .attr('stroke', '#666')
-        .attr('idx', (d, i) => i)
-        .attr('cursor', 'pointer')
+        .append("rect")
+        .classed("endpoint-for-show", true)
+        .attr("x", (d) => d.x)
+        .attr("y", (d) => d.y)
+        .attr("width", "7px")
+        .attr("height", "7px")
+        .attr("rx", "2px")
+        .attr("ry", "2px")
+        .attr("fill", "#1a1b1d")
+        .attr("stroke-width", "1px")
+        .attr("stroke", "#666")
+        .attr("idx", (d, i) => i)
+        .attr("cursor", "pointer");
 
       // 各端点-用于点击
-      this.svgNode.selectAll('rect.endpoint-for-click')
+      this.svgNode
+        .selectAll("rect.endpoint-for-click")
         .data(this.endpointListForClick)
         .enter()
-        .append('rect')
-        .classed('endpoint-for-click', true)
-        .attr('x', (d) => d.x)
-        .attr('y', (d) => d.y)
-        .attr('width', '21px')
-        .attr('height', '21px')
-        .attr('rx', '2px')
-        .attr('ry', '2px')
-        .attr('fill', 'transparent')
-        .attr('idx', (d, i) => i)
-        .attr('cursor', 'pointer')
-        .on('click', function(e, datum) {
-          that.svgNode.selectAll('line').attr('stroke', 'none')
-          that.svgNode.selectAll('rect.endpoint-for-show')
-            .attr('fill', '#1a1b1d')
-            .attr('stroke', '#666')
-            
-          that.svgNode.selectAll('line').filter((d) => {
-            return d.id === datum.id
-          }).attr('stroke', '#fff')
-          that.svgNode.selectAll('rect.endpoint-for-show').filter((d) => {
-            return d.id === datum.id
-          }).attr('fill', '#0076F6')
-            .attr('stroke', '#fff')
+        .append("rect")
+        .classed("endpoint-for-click", true)
+        .attr("x", (d) => d.x)
+        .attr("y", (d) => d.y)
+        .attr("width", "21px")
+        .attr("height", "21px")
+        .attr("rx", "2px")
+        .attr("ry", "2px")
+        .attr("fill", "transparent")
+        .attr("idx", (d, i) => i)
+        .attr("cursor", "pointer")
+        .on("click", function (e, datum) {
+          that.svgNode.selectAll("line").attr("stroke", "none");
+          that.svgNode
+            .selectAll("rect.endpoint-for-show")
+            .attr("fill", "#1a1b1d")
+            .attr("stroke", "#666");
+
+          that.svgNode
+            .selectAll("line")
+            .filter((d) => {
+              return d.id === datum.id;
+            })
+            .attr("stroke", "#fff");
+          that.svgNode
+            .selectAll("rect.endpoint-for-show")
+            .filter((d) => {
+              return d.id === datum.id;
+            })
+            .attr("fill", "#0076F6")
+            .attr("stroke", "#fff");
 
-          that.hotspot.personalizedTagInfo.lineDirection = datum.id
-        })
+          that.hotspot.personalizedTagInfo.lineDirection = datum.id;
+        });
 
       // 初始状态
-      this.svgNode.selectAll('rect.endpoint-for-click').filter((d) => {
-        return d.id === that.hotspot.personalizedTagInfo.lineDirection
-      }).dispatch('click')
-      
+
+      // this.svgNode
+      //   .selectAll("rect.endpoint-for-click")
+      //   .filter((d) => {
+      //     return d.id === that.hotspot.personalizedTagInfo.lineDirection;
+      //   })
+      //   .dispatch("click");
     }, 100);
-  }
-}
+  },
+};
 </script>
 
 <style lang="less" scoped>
@@ -413,12 +457,12 @@ export default {
   .remark-highlight {
     margin-top: 16px;
     font-size: 18px;
-    color: #FFFFFF;
+    color: #ffffff;
   }
   .remark {
     margin-top: 16px;
     font-size: 14px;
-    color: #FFFFFF;
+    color: #ffffff;
     opacity: 0.6;
   }
 
@@ -436,24 +480,24 @@ export default {
   > .svg-wrapper {
     margin-top: 16px;
     height: 110px;
-    background: #1A1B1D;
+    background: #1a1b1d;
     border-radius: 2px;
     border: 1px solid #404040;
   }
 
-  >.title-input-wrapper {
+  > .title-input-wrapper {
     position: relative;
     border: 1px solid rgba(151, 151, 151, 0.2);
     padding: 0 16px;
-    background: #1A1B1D;
+    background: #1a1b1d;
     border-radius: 2px;
     height: 36px;
     width: 100%;
     margin-top: 18px;
     &:focus-within {
-      border-color: #0076F6;
+      border-color: #0076f6;
     }
-    >input {
+    > input {
       border: none;
       background: transparent;
       outline: none;
@@ -464,7 +508,7 @@ export default {
       letter-spacing: 1px;
       font-size: 14px;
     }
-    >.count {
+    > .count {
       position: absolute;
       top: 50%;
       transform: translateY(-50%);
@@ -487,7 +531,7 @@ export default {
     position: relative;
     .color-value {
       font-size: 14px;
-      color: #FFFFFF;
+      color: #ffffff;
     }
     .color-preview {
       width: 26px;
@@ -527,11 +571,11 @@ export default {
       > input {
         width: 60px;
         height: 36px;
-        background: #1A1B1D;
+        background: #1a1b1d;
         border-radius: 2px;
         border: 1px solid #404040;
         font-size: 14px;
-        color: #FFFFFF;
+        color: #ffffff;
         margin-right: 10px;
         padding-left: 16px;
         &:focus {
@@ -541,4 +585,4 @@ export default {
     }
   }
 }
-</style>
+</style>

+ 110 - 82
packages/qjkankan-editor/src/views/hotspot/hotspotIconType/serial_frame.vue

@@ -5,19 +5,13 @@
       class="add-icon"
       @click="isShowSelectionWindow = true"
     >
-      <img src="@/assets/images/default/hotspot_scene_add.png" alt="">
-      <div class="button-name">{{$i18n.t('hotspot.add_icon')}}</div>
-      <div class="tip">{{$i18n.t('hotspot.add_serial_frame_rule')}}</div>
+      <img src="@/assets/images/default/hotspot_scene_add.png" alt="" />
+      <div class="button-name">{{ $i18n.t("hotspot.add_icon") }}</div>
+      <div class="tip">{{ $i18n.t("hotspot.add_serial_frame_rule") }}</div>
     </button>
 
     <div v-if="hotspot.serialFrameInfo.img" class="icon-selected">
-      <div
-        class="icon-wrap"
-        :style="{
-          height: frameHeight ? frameHeight + 'px' : '',
-          width: frameWidth ? frameWidth + 'px' : '',
-        }"
-      >
+      <div class="icon-wrap">
         <img
           class="serial-frame-preview"
           ref="serial-frame-preview"
@@ -26,20 +20,33 @@
           :style="{
             top: -this.frameHeight * this.currentFrameIdx + 'px',
           }"
-        >
+        />
         <button class="delete-btn" @click="onClickDelete">
-          <img class="normal" src="@/assets/images/icons/close01_normal@2x.png" alt="">
-          <img class="hover" src="@/assets/images/icons/close01_hover@2x.png" alt="">
+          <img
+            class="normal"
+            src="@/assets/images/icons/close01_normal@2x.png"
+            alt=""
+          />
+          <img
+            class="hover"
+            src="@/assets/images/icons/close01_hover@2x.png"
+            alt=""
+          />
         </button>
       </div>
       <div class="right-wrap">
-        <button class="select-icon ui-button submit" @click="isShowSelectionWindow = true">{{$i18n.t('hotspot.select_icon')}}</button>
-        <div class="tip">{{$i18n.t('hotspot.add_serial_frame_rule')}}</div>
+        <div class="tip">{{ $i18n.t("hotspot.add_serial_frame_rule") }}</div>
+        <button
+          class="select-icon ui-button submit"
+          @click="isShowSelectionWindow = true"
+        >
+          {{ $i18n.t("hotspot.select_icon") }}
+        </button>
       </div>
     </div>
 
     <div class="frame-num-setting serial-setting-item">
-      <div class="remark">{{$i18n.t('hotspot.frame_total_number')}}</div>
+      <div class="remark">{{ $i18n.t("hotspot.frame_total_number") }}</div>
       <div class="right-wrap">
         <input
           v-model.trim.number="hotspot.serialFrameInfo.frameNumber"
@@ -48,12 +55,12 @@
           min="2"
           step="1"
         />
-        <span>{{$i18n.t('common.frame')}}</span>
+        <span>{{ $i18n.t("common.frame") }}</span>
       </div>
     </div>
 
     <div class="duration-setting serial-setting-item">
-      <div class="remark">{{$i18n.t('hotspot.frame_duration')}}</div>
+      <div class="remark">{{ $i18n.t("hotspot.frame_duration") }}</div>
       <div class="right-wrap">
         <input
           v-model.trim.number="hotspot.serialFrameInfo.duration"
@@ -61,7 +68,7 @@
           type="number"
           min="0"
         />
-        <span>{{$i18n.t('common.second')}}</span>
+        <span>{{ $i18n.t("common.second") }}</span>
       </div>
     </div>
 
@@ -88,36 +95,31 @@ export default {
   data() {
     return {
       isShowSelectionWindow: false,
-
       frameHeight: 0,
       frameWidth: 0,
       currentFrameIdx: 0,
       intervalId: null,
-    }
+    };
   },
   computed: {
     ...mapGetters({
-      hotspot: 'hotspot',
+      hotspot: "hotspot",
     }),
   },
   watch: {
-    'hotspot.serialFrameInfo.frameNumber': {
+    "hotspot.serialFrameInfo.img": {
       handler(vNew) {
-        if (vNew >= 2 && Number.isInteger(vNew)) {
-          this.computeFrameHeight()
+        console.error('vNew',vNew);   
+        if (vNew && vNew.length > 0) {
+          this.calcFrameData();
         }
       },
       immediate: true,
+      deep:true
     },
     frameHeight: {
       handler() {
-        this.playSerialFrame()
-      },
-      immediate: true,
-    },
-    'hotspot.serialFrameInfo.duration': {
-      handler() {
-        this.playSerialFrame()
+        // this.playSerialFrame()
       },
       immediate: true,
     },
@@ -125,68 +127,79 @@ export default {
   methods: {
     onFrameNumberInputBlur() {
       if (this.hotspot.serialFrameInfo.frameNumber < 2) {
-        this.hotspot.serialFrameInfo.frameNumber = 2
+        this.hotspot.serialFrameInfo.frameNumber = 2;
       } else {
-        this.hotspot.serialFrameInfo.frameNumber = Math.round(this.hotspot.serialFrameInfo.frameNumber)
+        this.hotspot.serialFrameInfo.frameNumber = Math.round(
+          this.hotspot.serialFrameInfo.frameNumber
+        );
       }
     },
     onDurationInputBlur() {
       if (this.hotspot.serialFrameInfo.duration < 0) {
-        this.hotspot.serialFrameInfo.duration = 0
+        this.hotspot.serialFrameInfo.duration = 0;
       }
     },
     handleSubmitFromMaterialSelector(data) {
-      this.isShowSelectionWindow = false
-      this.hotspot.serialFrameInfo.img = data[0].icon
-
-      this.computeFrameHeight()
+      this.isShowSelectionWindow = false;
+      this.hotspot.serialFrameInfo.img = data[0].icon;
+      this.calcFrameData();
     },
     computeFrameHeight() {
-      this.frameHeight = 0
-      this.frameWidth = 0
+      this.frameHeight = 0;
+      this.frameWidth = 0;
 
       setTimeout(() => {
         try {
-          this.frameHeight = this.$refs['serial-frame-preview'].clientHeight / this.hotspot.serialFrameInfo.frameNumber
-          if (this.frameHeight > 110) {
-            this.frameWidth = 110 * 110 / this.frameHeight
-            this.frameHeight = 110
-          }
-        } catch(e) {
-          this.frameHeight = 0
-          this.frameWidth = 0
+          this.frameHeight = this.$refs["serial-frame-preview"].clientHeight;
+          this.frameWidth = this.$refs["serial-frame-preview"].clientWidth;
+        } catch (e) {
+          this.frameHeight = 0;
+          this.frameWidth = 0;
         }
       }, 200);
     },
-    playSerialFrame() {
-      clearInterval(this.intervalId)
-      this.currentFrameIdx = 0
-      if (!this.hotspot.serialFrameInfo.img || this.frameHeight <= 0 || this.hotspot.serialFrameInfo.duration <= 0) {
-        return
-      }
-      this.intervalId = setInterval(() => {
-        this.currentFrameIdx++
-        if (this.currentFrameIdx >= this.hotspot.serialFrameInfo.frameNumber) {
-          this.currentFrameIdx = 0
+    calcFrameData() {
+      console.log('calcFrameData');
+      setTimeout(() => {
+        try {
+          this.frameHeight = this.$refs["serial-frame-preview"].naturalHeight;
+          this.frameWidth = this.$refs["serial-frame-preview"].naturalWidth;
+          console.log("this.frameWidth", this.frameWidth);
+          if (this.frameHeight && this.frameWidth) {
+            const frameNumber = Number(this.frameHeight / this.frameWidth);
+
+            if (!this.hotspot.serialFrameInfo.frameNumber) {
+              this.hotspot.serialFrameInfo.frameNumber =
+                Math.ceil(frameNumber) || 0;
+            }
+
+            console.log("frameNumber", Math.ceil(frameNumber));
+            this.hotspot.serialFrameInfo.duration = 1;
+            this.hotspot.serialFrameInfo.frameWidth = this.frameWidth;
+          }
+        } catch (e) {
+          this.frameHeight = 0;
+          this.frameWidth = 0;
         }
-      }, this.hotspot.serialFrameInfo.duration / this.hotspot.serialFrameInfo.frameNumber * 1000);
+      }, 200);
     },
     onClickDelete() {
-      this.hotspot.serialFrameInfo.img = ''
-      clearInterval(this.intervalId)
-      this.frameHeight = 0
-      this.frameWidth = 0
-    }
+      this.hotspot.serialFrameInfo.img = "";
+      clearInterval(this.intervalId);
+      this.frameHeight = 0;
+      this.frameWidth = 0;
+      this.hotspot.serialFrameInfo.duration = 0;
+      this.hotspot.serialFrameInfo.frameNumber = 0;
+    },
   },
-  mounted() {
-  }
-}
+  mounted() {},
+};
 </script>
 
 <style lang="less" scoped>
 .hotspot-icon-serial-frame {
   width: 100%;
-  
+
   > button.add-icon {
     width: 100%;
     height: 110px;
@@ -194,7 +207,7 @@ export default {
     flex-direction: column;
     justify-content: center;
     align-items: center;
-    background: #1A1B1D;
+    background: #1a1b1d;
     border-radius: 2px;
     border: 1px solid #404040;
     cursor: pointer;
@@ -205,7 +218,7 @@ export default {
     }
     > .button-name {
       font-size: 14px;
-      color: #0076F6;
+      color: #0076f6;
       margin-bottom: 4px;
     }
     > .tip {
@@ -216,16 +229,24 @@ export default {
 
   > .icon-selected {
     display: flex;
-    justify-content: space-between;
+    flex-direction: column;
+    justify-content: flex-start;
     > .icon-wrap {
-      width: 110px;
-      height: 110px;
+      width: 228px;
+      height: 180px;
       position: relative;
       overflow: hidden;
       border-radius: 2px;
+      display: flex;
+      justify-content: center;
+      border: 1px solid rgba(151, 151, 151, 0.2);
+      background: #1a1b1d;
+      margin-bottom: 10px;
       > .serial-frame-preview {
         position: absolute;
-        width: 100%;
+        width: auto;
+
+        height: 100%;
       }
       > .delete-btn {
         position: absolute;
@@ -258,13 +279,20 @@ export default {
       }
     }
     > .right-wrap {
-      width: 108px;
+      width: 100%;
+      display: flex;
+      justify-content: center;
+      flex-direction: row;
+
       > button.select-icon {
         margin-bottom: 14px;
+        font-size: 12px;
+        min-width: 60px;
+        padding: 0 12px;
       }
       > .tip {
-        font-size: 14px;
-        color: rgba(255,255,255,0.3);
+        font-size: 12px;
+        color: rgba(255, 255, 255, 0.3);
       }
     }
   }
@@ -275,7 +303,7 @@ export default {
     align-items: center;
     &:first-of-type {
       margin-top: 16px;
-      margin-bottom: 10px;;
+      margin-bottom: 10px;
     }
     > .remark {
       font-size: 14px;
@@ -288,11 +316,11 @@ export default {
       > input {
         width: 60px;
         height: 36px;
-        background: #1A1B1D;
+        background: #1a1b1d;
         border-radius: 2px;
         border: 1px solid #404040;
         font-size: 14px;
-        color: #FFFFFF;
+        color: #ffffff;
         margin-right: 10px;
         padding-left: 16px;
         &:focus {
@@ -306,4 +334,4 @@ export default {
     }
   }
 }
-</style>
+</style>

+ 20 - 0
packages/qjkankan-kankan-view/.env.testprod

@@ -0,0 +1,20 @@
+NODE_ENV=production
+# 场景资源地址
+VUE_APP_RESOURCE_URL=https://4dkk.4dage.com/
+# 静态资源地址
+VUE_APP_CDN_URL=https://4dkk.4dage.com/v4/www/
+# sdk文件地址
+VUE_APP_SDK_DIR=https://4dkk.4dage.com/v4/www/sdk/
+# VUE_APP_SDK_DIR=https://4dkk.4dage.com/v4-test/www/sdk/
+
+
+
+# 静态资源目录
+VUE_APP_STATIC_DIR=viewer
+
+
+# 云存储环境
+VUE_APP_REGION_URL=
+
+# 接口请求地址
+VUE_APP_APIS_URL=https://test.4dkankan.com/

+ 21 - 0
packages/qjkankan-kankan-view/.env.testserve

@@ -0,0 +1,21 @@
+
+# 场景资源地址
+VUE_APP_RESOURCE_URL=https://4dkk.4dage.com/
+# 静态资源地址
+VUE_APP_CDN_URL=https://4dkk.4dage.com/v4/www/
+# sdk文件地址
+VUE_APP_SDK_DIR=https://4dkk.4dage.com/v4/www/sdk/
+# VUE_APP_SDK_DIR=https://4dkk.4dage.com/v4-test/www/sdk/
+
+
+
+# 静态资源目录
+VUE_APP_STATIC_DIR=viewer
+
+
+# 云存储环境
+VUE_APP_REGION_URL=
+
+# 接口请求地址
+VUE_APP_APIS_URL=https://test.4dkankan.com/
+

+ 2 - 1
packages/qjkankan-kankan-view/package.json

@@ -3,8 +3,9 @@
   "version": "1.2.0",
   "private": true,
   "scripts": {
-    "serve": "vue-cli-service serve",
+    "serve": "vue-cli-service serve --mode testserve",
     "serve-prod": "vue-cli-service serve --mode prod",
+    "build-test-prod": "vue-cli-service build --mode testprod",
     "build": "vue-cli-service build --mode prod",
     "build-eurtestprod": "vue-cli-service build --mode eurtestprod",
     "build-eurprod": "vue-cli-service build --mode eurprod",

+ 2 - 2
packages/qjkankan-kankan-view/public/smg.html

@@ -28,8 +28,8 @@
 
         <script src="<%= BASE_URL %><%= VUE_APP_STATIC_DIR %>/static/lib/jweixin-1.6.0.js"></script>
         
-        <script src="<%= VUE_APP_SDK_DIR %>kankan-sdk-deps.js?v=4.6.2"></script>
-        <script src="<%= VUE_APP_SDK_DIR %>kankan-sdk.js?v=4.6.2"></script>
+        <script src="<%= VUE_APP_SDK_DIR %>kankan-sdk-deps.js?v=4.7.6"></script>
+        <script src="<%= VUE_APP_SDK_DIR %>kankan-sdk.js?v=4.7.6"></script>
 
         <!-- <script src="https://4dkk.4dage.com/v4/www/sdk/kankan-sdk-deps.js?v=4.0.0-alpha.44"></script>
         <script src="https://4dkk.4dage.com/v4/www/sdk/kankan-sdk.js?v=4.0.0-alpha.44"></script> -->

+ 2 - 2
packages/qjkankan-kankan-view/public/spg.html

@@ -17,8 +17,8 @@
         </noscript>
         <div id="app"></div>
         
-        <script src="<%= VUE_APP_SDK_DIR %>kankan-sdk-deps.js?v=4.6.2"></script>
-        <script src="<%= VUE_APP_SDK_DIR %>kankan-sdk.js?v=4.6.2"></script>
+        <script src="<%= VUE_APP_SDK_DIR %>kankan-sdk-deps.js?v=4.7.6"></script>
+        <script src="<%= VUE_APP_SDK_DIR %>kankan-sdk.js?v=4.7.6"></script>
 
         <!-- built files will be auto injected -->
     </body>

+ 2 - 2
packages/qjkankan-kankan-view/src/components/Tags/index.vue

@@ -1,7 +1,7 @@
 <template>
     <teleport :to="tags$" v-if="tags$">
         <template v-for="(tag, index) in tags">
-            <div @mouseleave="onMouseLeave($event, tag)" :style="{ left: tag.x + 'px', top: tag.y + 'px' }" :class="{ visible: tag.visible }">
+            <div :tag-sid="tag.sid" @mouseleave="onMouseLeave($event, tag)" :style="{ left: tag.x + 'px', top: tag.y + 'px' }" :class="{ visible: tag.visible }">
                 <span @click.stop="goTag(tag, index)" class="point zoom" @mouseenter.stop="onMouseEnter(tag, index)" :style="{ 'background-image': 'url(' + getUrl(tag.icon) + ')' }"></span>
                 <div class="content">
                     <div class="trans" :class="{ active: (isFixed && hotData && tag.sid == hotData.sid) || (showInfo && hotData && tag.sid == hotData.sid) }">
@@ -95,7 +95,7 @@ const closeTag = async () => {
     const player = await app.TourManager.player
     //关闭热点面板时候,继续播放之前暂停的音频
     if (!app.Scene.isCurrentPanoHasVideo && !player.isPlaying) {
-        if (hotData.value.type == 'audio' || hotData.value.type == 'video') {
+        if ( hotData.value && (hotData.value.type == 'audio' || hotData.value.type == 'video')) {
             // console.log('resume')
             window.parent.postMessage(
             {

+ 4 - 2
packages/qjkankan-kankan-view/src/pages/SMG.vue

@@ -45,7 +45,7 @@ import { useMusicPlayer } from "@/utils/sound";
 import UiTags from "@/components/Tags";
 
 import { listenMessage } from '@/utils/messageHandler'
-
+import {Dialog} from '@/global_components'
 
 import Information from "@/components/Information";
 import Control from "@/components/Controls/Control.Mobile.vue";
@@ -59,6 +59,8 @@ import { ref, onMounted, computed, nextTick, watch } from "vue";
 import { useStore } from "vuex";
 import browser from "@/utils/browser";
 import { useApp, getApp } from "@/app";
+import { useI18n, getLocale } from '@/i18n'
+const { t } = useI18n({ useScope: 'global' })
 
 const musicPlayer = useMusicPlayer();
 
@@ -385,7 +387,7 @@ onMounted(() => {
     });
   });
   app.store.on("floorcad", (floor) => store.commit("scene/loadFloorData", floor));
-
+  app.store.on('flooruser', floor => store.commit('scene/loadFloorData', floor)) //4.7以后新楼层方式
   app.render();
 });
 </script>

+ 1 - 0
packages/qjkankan-kankan-view/src/pages/SPG.vue

@@ -235,6 +235,7 @@ onMounted(() => {
         })
     })
     app.store.on('floorcad', floor => store.commit('scene/loadFloorData', floor))
+    app.store.on('flooruser', floor => store.commit('scene/loadFloorData', floor)) //4.7以后新楼层方式
     app.render()
 })
 </script>

+ 1 - 2
packages/qjkankan-view/.env.testdev

@@ -5,5 +5,4 @@ VUE_APP_PROXY_URL='https://test.4dkankan.com/qjkankan/'
 VUE_APP_URL_FILL=
 
 # 接口请求地址
-VUE_APP_APIS_URL=https://test.4dkankan.com/
-
+VUE_APP_APIS_URL=https://test.4dkankan.com/

+ 1 - 3
packages/qjkankan-view/package.json

@@ -3,11 +3,9 @@
   "version": "1.2.0",
   "private": true,
   "scripts": {
-    "serve": "vue-cli-service serve",
+    "serve": "vue-cli-service serve --mode testdev",
     "serve-eurtestdev": "vue-cli-service serve --mode eurtestdev",
     "serve-eurdev": "vue-cli-service serve --mode eurdev",
-    "serve-testdev": "vue-cli-service serve --mode testdev",
-    "build": "vue-cli-service build",
     "build-testprod": "vue-cli-service build --mode testprod",
     "build-eurtestprod": "vue-cli-service build --mode eurtestprod",
     "build-eurprod": "vue-cli-service build --mode eurprod",

+ 1 - 1
packages/qjkankan-view/public/showviewer/lib/krpano/skin/vtourskin.xml

@@ -1151,7 +1151,7 @@
         set(hotspot[get(schp_name)].onup,js(__sdk.Tags..updateHotSpotData(get(xml.scene),get(name),get(ath),get(atv),"imgtext")));
       );
 
-			txtadd(hotspot[get(schp_name)].onloaded,"do_crop_animation(84,84, 40);");
+	  txtadd(hotspot[get(schp_name)].onloaded,"do_crop_animation(84,84, 40);");
 			
       txtadd(hotspot[get(schp_name)].onloaded,"add_all_the_time_tooltip(hotspot[get(name)].hotspottitle);");
       set(hotspot[get(schp_name)].onhover,null);

+ 26 - 10
packages/qjkankan-view/src/sdk/QJKanKan/modules/Tags.js

@@ -15,6 +15,21 @@ export default class Tags extends Emiter {
     this.emit('clickHotspot', { sceneCode, id, hid })
   }
 
+
+  /**
+   * 编码转换
+   */
+  htmlEncode(str) {
+    var s = "";
+    if (str.length == 0) return "";
+    s = str.replace(/\'/g, "&#39;");
+    s = s.replace(/\"/g, "&quot;");
+    s = s.replace(/\(/g, "(");
+    s = s.replace(/\)/g, ")");
+    s = s.replace(/,/g, ",");
+    return s;
+  }
+
   /**
    * 添加热点
    */
@@ -25,7 +40,7 @@ export default class Tags extends Emiter {
     this.app.krpanoDom.call(`addImgTextHotSpot(
         ${param.img.replace('static/','showviewer/').replace('.svg','.png').replace('@2x','')},
         ${param.name},
-        ${param.hotspotTitle},
+        ${this.htmlEncode(param.hotspotTitle)},
         ${param.ath != '' ? param.ath : ath},
         ${param.atv != '' ? param.atv : atv},
         ${param.secne ? param.secne.sceneCode : 'notjump'},
@@ -37,19 +52,20 @@ export default class Tags extends Emiter {
         ${Number(param.fontSize)})`);
 
 
-    // 设置热点图片默认的偏移值
-    let offset = '-130%'
-    if (param.size < 1) {
-      offset = '-200%'
-    }
-    if (param.size > 1) {
-      offset = '-100%'
-    }
-    this.app.krpanoDom.set('layer[tooltip_' + param.name + '].y', `${offset}`)
+    // // 设置热点图片默认的偏移值
+    // let offset = '-130%'
+    // if (param.size < 1) {
+    //   offset = '-200%'
+    // }
+    // if (param.size > 1) {
+    //   offset = '-100%'
+    // }
+    // this.app.krpanoDom.set('layer[tooltip_' + param.name + '].y', `${offset}`)
 
   }
 
 
+
   /**
   * 初始化
   */

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 279 - 255
yarn.lock