Merge branch 'master' of https://gitea.mjm-staging.developers-homelab.net/BIMS/BIMS
This commit is contained in:
		
						commit
						0aea9d189a
					
				@ -18,6 +18,7 @@
 | 
				
			|||||||
  </ItemGroup>
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <ItemGroup>
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <PackageReference Include="Autodesk.Forge" Version="1.9.7" />
 | 
				
			||||||
    <PackageReference Include="iTextSharp" Version="5.5.13.2" />
 | 
					    <PackageReference Include="iTextSharp" Version="5.5.13.2" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.21" />
 | 
					    <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.21" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="3.1.20" />
 | 
					    <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="3.1.20" />
 | 
				
			||||||
 | 
				
			|||||||
@ -104,22 +104,43 @@ namespace Backend.Controllers
 | 
				
			|||||||
                    //新增
 | 
					                    //新增
 | 
				
			||||||
                    //抓取當前的Priority
 | 
					                    //抓取當前的Priority
 | 
				
			||||||
                    var current_priority = await backendRepository.GetCurrentPriority("building");
 | 
					                    var current_priority = await backendRepository.GetCurrentPriority("building");
 | 
				
			||||||
                    var map_3d_guid = new Guid();
 | 
					                    var map_3d_guid = Guid.NewGuid();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    Dictionary<string, object> building = new Dictionary<string, object>();
 | 
					                    if (post.urn_3D != null)
 | 
				
			||||||
                    building = new Dictionary<string, object>()
 | 
					 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        { "@building_tag", post.building_tag},
 | 
					                        Dictionary<string, object> building = new Dictionary<string, object>();
 | 
				
			||||||
                        { "@full_name", post.Full_name},
 | 
					                        building = new Dictionary<string, object>()
 | 
				
			||||||
                        { "@ip_address", post.Ip_address},
 | 
					                        {
 | 
				
			||||||
                        { "@ip_port", post.Ip_port},
 | 
					                            { "@building_tag", post.building_tag},
 | 
				
			||||||
                        { "@priority", current_priority + 1},
 | 
					                            { "@full_name", post.Full_name},
 | 
				
			||||||
                        { "@orgName_3D", post.orgName_3D},
 | 
					                            { "@ip_address", post.Ip_address},
 | 
				
			||||||
                        { "@saveName_3D", map_3d_guid},
 | 
					                            { "@ip_port", post.Ip_port},
 | 
				
			||||||
                        { "@extName_3D", post.extName_3D},
 | 
					                            { "@priority", current_priority + 1},
 | 
				
			||||||
                        { "@created_by", myUserInfo.Userinfo_guid}
 | 
					                            { "@orgName_3D", post.orgName_3D},
 | 
				
			||||||
                    };
 | 
					                            { "@saveName_3D", map_3d_guid},
 | 
				
			||||||
                    await backendRepository.AddOneByCustomTable(building, "building");
 | 
					                            { "@extName_3D", post.extName_3D},
 | 
				
			||||||
 | 
					                            { "@urn_3D", post.urn_3D},
 | 
				
			||||||
 | 
					                            { "@created_by", myUserInfo.Userinfo_guid}
 | 
				
			||||||
 | 
					                        };
 | 
				
			||||||
 | 
					                        await backendRepository.AddOneByCustomTable(building, "building");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    else
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        Dictionary<string, object> building = new Dictionary<string, object>();
 | 
				
			||||||
 | 
					                        building = new Dictionary<string, object>()
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            { "@building_tag", post.building_tag},
 | 
				
			||||||
 | 
					                            { "@full_name", post.Full_name},
 | 
				
			||||||
 | 
					                            { "@ip_address", post.Ip_address},
 | 
				
			||||||
 | 
					                            { "@ip_port", post.Ip_port},
 | 
				
			||||||
 | 
					                            { "@priority", current_priority + 1},
 | 
				
			||||||
 | 
					                            { "@orgName_3D", post.orgName_3D},
 | 
				
			||||||
 | 
					                            { "@saveName_3D", map_3d_guid},
 | 
				
			||||||
 | 
					                            { "@extName_3D", post.extName_3D},
 | 
				
			||||||
 | 
					                            { "@created_by", myUserInfo.Userinfo_guid}
 | 
				
			||||||
 | 
					                        };
 | 
				
			||||||
 | 
					                        await backendRepository.AddOneByCustomTable(building, "building");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (post.orgName_3D != null && post.extName_3D != null)
 | 
					                    if (post.orgName_3D != null && post.extName_3D != null)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
@ -186,18 +207,38 @@ namespace Backend.Controllers
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                if (!judgeIPAddressRepeat)
 | 
					                if (!judgeIPAddressRepeat)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    Dictionary<string, object> building = new Dictionary<string, object>();
 | 
					                    if (post.urn_3D != null)
 | 
				
			||||||
                    building = new Dictionary<string, object>()
 | 
					 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        { "@full_name", post.Full_name},
 | 
					                        Dictionary<string, object> building = new Dictionary<string, object>();
 | 
				
			||||||
                        { "@ip_address", post.Ip_address},
 | 
					                        building = new Dictionary<string, object>()
 | 
				
			||||||
                        { "@ip_port", post.Ip_port},
 | 
					                        {
 | 
				
			||||||
                        { "@orgName_3D", post.orgName_3D},
 | 
					                            { "@full_name", post.Full_name},
 | 
				
			||||||
                        { "@extName_3D", post.extName_3D},
 | 
					                            { "@ip_address", post.Ip_address},
 | 
				
			||||||
                        { "@updated_by", myUserInfo.Userinfo_guid},
 | 
					                            { "@ip_port", post.Ip_port},
 | 
				
			||||||
                        { "@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}
 | 
					                            { "@orgName_3D", post.orgName_3D},
 | 
				
			||||||
                    };
 | 
					                            { "@extName_3D", post.extName_3D},
 | 
				
			||||||
                    await backendRepository.UpdateOneByCustomTable(building, "building", "building_tag='" + post.building_tag + "'");
 | 
					                            { "@urn_3D", post.urn_3D},
 | 
				
			||||||
 | 
					                            { "@updated_by", myUserInfo.Userinfo_guid},
 | 
				
			||||||
 | 
					                            { "@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}
 | 
				
			||||||
 | 
					                        };
 | 
				
			||||||
 | 
					                        await backendRepository.UpdateOneByCustomTable(building, "building", "building_tag='" + post.building_tag + "'");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    else
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        Dictionary<string, object> building = new Dictionary<string, object>();
 | 
				
			||||||
 | 
					                        building = new Dictionary<string, object>()
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            { "@full_name", post.Full_name},
 | 
				
			||||||
 | 
					                            { "@ip_address", post.Ip_address},
 | 
				
			||||||
 | 
					                            { "@ip_port", post.Ip_port},
 | 
				
			||||||
 | 
					                            { "@orgName_3D", post.orgName_3D},
 | 
				
			||||||
 | 
					                            { "@extName_3D", post.extName_3D},
 | 
				
			||||||
 | 
					                            { "@updated_by", myUserInfo.Userinfo_guid},
 | 
				
			||||||
 | 
					                            { "@updated_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}
 | 
				
			||||||
 | 
					                        };
 | 
				
			||||||
 | 
					                        await backendRepository.UpdateOneByCustomTable(building, "building", "building_tag='" + post.building_tag + "'");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (post.orgName_3D != null && post.extName_3D != null)
 | 
					                    if (post.orgName_3D != null && post.extName_3D != null)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										53
									
								
								Backend/Controllers/ModelDerivativeController.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								Backend/Controllers/ModelDerivativeController.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,53 @@
 | 
				
			|||||||
 | 
					using Autodesk.Forge;
 | 
				
			||||||
 | 
					using Autodesk.Forge.Model;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Mvc;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace forgeSample.Controllers
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    [ApiController]
 | 
				
			||||||
 | 
					    public class ModelDerivativeController : ControllerBase
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Start the translation job for a give bucketKey/objectName
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="objModel"></param>
 | 
				
			||||||
 | 
					        /// <returns></returns>
 | 
				
			||||||
 | 
					        [HttpPost]
 | 
				
			||||||
 | 
					        [Route("api/forge/modelderivative/jobs")]
 | 
				
			||||||
 | 
					        public async Task<dynamic> TranslateObject([FromBody] TranslateObjectModel objModel)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            dynamic oauth = await OAuthController.GetInternalAsync();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // prepare the payload
 | 
				
			||||||
 | 
					            List<JobPayloadItem> outputs = new List<JobPayloadItem>()
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					            new JobPayloadItem(
 | 
				
			||||||
 | 
					                JobPayloadItem.TypeEnum.Svf,
 | 
				
			||||||
 | 
					                new List<JobPayloadItem.ViewsEnum>()
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                JobPayloadItem.ViewsEnum._2d,
 | 
				
			||||||
 | 
					                JobPayloadItem.ViewsEnum._3d
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					            JobPayload job;
 | 
				
			||||||
 | 
					            job = new JobPayload(new JobPayloadInput(objModel.objectName), new JobPayloadOutput(outputs));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // start the translation
 | 
				
			||||||
 | 
					            DerivativesApi derivative = new DerivativesApi();
 | 
				
			||||||
 | 
					            derivative.Configuration.AccessToken = oauth.access_token;
 | 
				
			||||||
 | 
					            dynamic jobPosted = await derivative.TranslateAsync(job);
 | 
				
			||||||
 | 
					            return jobPosted;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Model for TranslateObject method
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public class TranslateObjectModel
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            public string bucketKey { get; set; }
 | 
				
			||||||
 | 
					            public string objectName { get; set; }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										70
									
								
								Backend/Controllers/OAuthController.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								Backend/Controllers/OAuthController.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,70 @@
 | 
				
			|||||||
 | 
					using Autodesk.Forge;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Mvc;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace forgeSample.Controllers
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    [ApiController]
 | 
				
			||||||
 | 
					    public class OAuthController : ControllerBase
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // As both internal & public tokens are used for all visitors
 | 
				
			||||||
 | 
					        // we don't need to request a new token on every request, so let's
 | 
				
			||||||
 | 
					        // cache them using static variables. Note we still need to refresh
 | 
				
			||||||
 | 
					        // them after the expires_in time (in seconds)
 | 
				
			||||||
 | 
					        private static dynamic InternalToken { get; set; }
 | 
				
			||||||
 | 
					        private static dynamic PublicToken { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Get access token with public (viewables:read) scope
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        [HttpGet]
 | 
				
			||||||
 | 
					        [Route("api/forge/oauth/token")]
 | 
				
			||||||
 | 
					        public async Task<dynamic> GetPublicAsync()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (PublicToken == null || PublicToken.ExpiresAt < DateTime.UtcNow)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                PublicToken = await Get2LeggedTokenAsync(new Scope[] { Scope.ViewablesRead });
 | 
				
			||||||
 | 
					                PublicToken.ExpiresAt = DateTime.UtcNow.AddSeconds(PublicToken.expires_in);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return PublicToken;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Get access token with internal (write) scope
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static async Task<dynamic> GetInternalAsync()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (InternalToken == null || InternalToken.ExpiresAt < DateTime.UtcNow)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                InternalToken = await Get2LeggedTokenAsync(new Scope[] { Scope.BucketCreate, Scope.BucketRead, Scope.BucketDelete, Scope.DataRead, Scope.DataWrite, Scope.DataCreate, Scope.CodeAll });
 | 
				
			||||||
 | 
					                InternalToken.ExpiresAt = DateTime.UtcNow.AddSeconds(InternalToken.expires_in);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return InternalToken;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Get the access token from Autodesk
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        private static async Task<dynamic> Get2LeggedTokenAsync(Scope[] scopes)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            TwoLeggedApi oauth = new TwoLeggedApi();
 | 
				
			||||||
 | 
					            string grantType = "client_credentials";
 | 
				
			||||||
 | 
					            dynamic bearer = await oauth.AuthenticateAsync(
 | 
				
			||||||
 | 
					              GetAppSetting("FORGE_CLIENT_ID"),
 | 
				
			||||||
 | 
					              GetAppSetting("FORGE_CLIENT_SECRET"),
 | 
				
			||||||
 | 
					              grantType,
 | 
				
			||||||
 | 
					              scopes);
 | 
				
			||||||
 | 
					            return bearer;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Reads appsettings from web.config
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string GetAppSetting(string settingKey)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return Environment.GetEnvironmentVariable(settingKey).Trim();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										150
									
								
								Backend/Controllers/OSSController.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								Backend/Controllers/OSSController.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,150 @@
 | 
				
			|||||||
 | 
					using Autodesk.Forge;
 | 
				
			||||||
 | 
					using Autodesk.Forge.Model;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Hosting;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Mvc;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.IO;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace forgeSample.Controllers
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    [ApiController]
 | 
				
			||||||
 | 
					    public class OSSController : ControllerBase
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private IWebHostEnvironment _env;
 | 
				
			||||||
 | 
					        public OSSController(IWebHostEnvironment env) { _env = env; }
 | 
				
			||||||
 | 
					        public string ClientId { get { return OAuthController.GetAppSetting("FORGE_CLIENT_ID").ToLower(); } }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Return list of buckets (id=#) or list of objects (id=bucketKey)
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        [HttpGet]
 | 
				
			||||||
 | 
					        [Route("api/forge/oss/buckets")]
 | 
				
			||||||
 | 
					        public async Task<IList<TreeNode>> GetOSSAsync(string id)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            IList<TreeNode> nodes = new List<TreeNode>();
 | 
				
			||||||
 | 
					            dynamic oauth = await OAuthController.GetInternalAsync();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (id == "#") // root
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // in this case, let's return all buckets
 | 
				
			||||||
 | 
					                BucketsApi appBckets = new BucketsApi();
 | 
				
			||||||
 | 
					                appBckets.Configuration.AccessToken = oauth.access_token;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // to simplify, let's return only the first 100 buckets
 | 
				
			||||||
 | 
					                dynamic buckets = await appBckets.GetBucketsAsync("US", 100);
 | 
				
			||||||
 | 
					                foreach (KeyValuePair<string, dynamic> bucket in new DynamicDictionaryItems(buckets.items))
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    nodes.Add(new TreeNode(bucket.Value.bucketKey, bucket.Value.bucketKey.Replace(ClientId + "-", string.Empty), "bucket", true));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // as we have the id (bucketKey), let's return all 
 | 
				
			||||||
 | 
					                ObjectsApi objects = new ObjectsApi();
 | 
				
			||||||
 | 
					                objects.Configuration.AccessToken = oauth.access_token;
 | 
				
			||||||
 | 
					                var objectsList = await objects.GetObjectsAsync(id, 100);
 | 
				
			||||||
 | 
					                foreach (KeyValuePair<string, dynamic> objInfo in new DynamicDictionaryItems(objectsList.items))
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    nodes.Add(new TreeNode(Base64Encode((string)objInfo.Value.objectId),
 | 
				
			||||||
 | 
					                      objInfo.Value.objectKey, "object", false));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return nodes;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Model data for jsTree used on GetOSSAsync
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public class TreeNode
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            public TreeNode(string id, string text, string type, bool children)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                this.id = id;
 | 
				
			||||||
 | 
					                this.text = text;
 | 
				
			||||||
 | 
					                this.type = type;
 | 
				
			||||||
 | 
					                this.children = children;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            public string id { get; set; }
 | 
				
			||||||
 | 
					            public string text { get; set; }
 | 
				
			||||||
 | 
					            public string type { get; set; }
 | 
				
			||||||
 | 
					            public bool children { get; set; }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Create a new bucket 
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        [HttpPost]
 | 
				
			||||||
 | 
					        [Route("api/forge/oss/buckets")]
 | 
				
			||||||
 | 
					        public async Task<dynamic> CreateBucket([FromBody] CreateBucketModel bucket)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            BucketsApi buckets = new BucketsApi();
 | 
				
			||||||
 | 
					            dynamic token = await OAuthController.GetInternalAsync();
 | 
				
			||||||
 | 
					            buckets.Configuration.AccessToken = token.access_token;
 | 
				
			||||||
 | 
					            PostBucketsPayload bucketPayload = new PostBucketsPayload(string.Format("{0}-{1}", ClientId, bucket.bucketKey.ToLower()), null,
 | 
				
			||||||
 | 
					              PostBucketsPayload.PolicyKeyEnum.Transient);
 | 
				
			||||||
 | 
					            return await buckets.CreateBucketAsync(bucketPayload, "US");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Input model for CreateBucket method
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public class CreateBucketModel
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            public string bucketKey { get; set; }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Receive a file from the client and upload to the bucket
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <returns></returns>
 | 
				
			||||||
 | 
					        [HttpPost]
 | 
				
			||||||
 | 
					        [Route("api/forge/oss/objects")]
 | 
				
			||||||
 | 
					        public async Task<string> UploadObject([FromForm] UploadFile input)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // save the file on the server
 | 
				
			||||||
 | 
					            var fileSavePath = Path.Combine(_env.WebRootPath, Path.GetFileName(input.fileToUpload.FileName));
 | 
				
			||||||
 | 
					            using (var stream = new FileStream(fileSavePath, FileMode.Create))
 | 
				
			||||||
 | 
					                await input.fileToUpload.CopyToAsync(stream);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // get the bucket...
 | 
				
			||||||
 | 
					            dynamic oauth = await OAuthController.GetInternalAsync();
 | 
				
			||||||
 | 
					            ObjectsApi objects = new ObjectsApi();
 | 
				
			||||||
 | 
					            objects.Configuration.AccessToken = oauth.access_token;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // upload the file/object, which will create a new object
 | 
				
			||||||
 | 
					            dynamic uploadedObj;
 | 
				
			||||||
 | 
					            using (StreamReader streamReader = new StreamReader(fileSavePath))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                uploadedObj = await objects.UploadObjectAsync(input.bucketKey,
 | 
				
			||||||
 | 
					                       Path.GetFileName(input.fileToUpload.FileName), (int)streamReader.BaseStream.Length, streamReader.BaseStream,
 | 
				
			||||||
 | 
					                       "application/octet-stream");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // cleanup
 | 
				
			||||||
 | 
					            System.IO.File.Delete(fileSavePath);
 | 
				
			||||||
 | 
					            string urn = Base64Encode((string)uploadedObj.objectId);
 | 
				
			||||||
 | 
					            string result = urn + "," + uploadedObj.objectKey;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return result;//uploadedObj;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public class UploadFile
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            public string bucketKey { get; set; }
 | 
				
			||||||
 | 
					            public IFormFile fileToUpload { get; set; }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Base64 enconde a string
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string Base64Encode(string plainText)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
 | 
				
			||||||
 | 
					            return System.Convert.ToBase64String(plainTextBytes);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -173,7 +173,7 @@ namespace Backend.Controllers
 | 
				
			|||||||
                        { "@message_content", sendContent}
 | 
					                        { "@message_content", sendContent}
 | 
				
			||||||
                    };
 | 
					                    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    await backendRepository.AddOneByCustomTable(insertNotify, "background_service_message_notification_task");
 | 
					                    //await backendRepository.AddOneByCustomTable(insertNotify, "background_service_message_notification_task");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    apiResult.Code = "0000";
 | 
					                    apiResult.Code = "0000";
 | 
				
			||||||
                    apiResult.Msg = "儲存成功";
 | 
					                    apiResult.Msg = "儲存成功";
 | 
				
			||||||
 | 
				
			|||||||
@ -20,6 +20,7 @@ namespace Backend.Models
 | 
				
			|||||||
        public string orgName_3D { get; set; }
 | 
					        public string orgName_3D { get; set; }
 | 
				
			||||||
        public string saveName_3D { get; set; }
 | 
					        public string saveName_3D { get; set; }
 | 
				
			||||||
        public string extName_3D { get; set; }
 | 
					        public string extName_3D { get; set; }
 | 
				
			||||||
 | 
					        public string urn_3D { get; set; }
 | 
				
			||||||
        //public string Created_at { get; set; }  //建立時間
 | 
					        //public string Created_at { get; set; }  //建立時間
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,10 @@
 | 
				
			|||||||
      "launchBrowser": true,
 | 
					      "launchBrowser": true,
 | 
				
			||||||
      "environmentVariables": {
 | 
					      "environmentVariables": {
 | 
				
			||||||
        "ASPNETCORE_ENVIRONMENT": "Development",
 | 
					        "ASPNETCORE_ENVIRONMENT": "Development",
 | 
				
			||||||
        "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation"
 | 
					        "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation",
 | 
				
			||||||
 | 
					        "FORGE_CALLBACK_URL": "http://localhost:3000/api/forge/callback/oauth",
 | 
				
			||||||
 | 
					        "FORGE_CLIENT_ID": "TA3hqsFfzQbNOUXKpldKUKSew4SJ21w5",
 | 
				
			||||||
 | 
					        "FORGE_CLIENT_SECRET": "D002f92d839144f8"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "Backend": {
 | 
					    "Backend": {
 | 
				
			||||||
 | 
				
			|||||||
@ -45,6 +45,7 @@
 | 
				
			|||||||
        var selected_build_guid_top = "";
 | 
					        var selected_build_guid_top = "";
 | 
				
			||||||
        var selected_build_guid_top_name;
 | 
					        var selected_build_guid_top_name;
 | 
				
			||||||
        var selected_floor_guid = "";
 | 
					        var selected_floor_guid = "";
 | 
				
			||||||
 | 
					        let input3Dfile = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //#region 區域基本資料 document ready
 | 
					        //#region 區域基本資料 document ready
 | 
				
			||||||
        $(function () {
 | 
					        $(function () {
 | 
				
			||||||
@ -261,121 +262,367 @@
 | 
				
			|||||||
                    maxlength: 50,
 | 
					                    maxlength: 50,
 | 
				
			||||||
                    filterspace: true
 | 
					                    filterspace: true
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
                file_3d_modal: {
 | 
					                build_file_3d_modal: {
 | 
				
			||||||
                    accept: "image/svg+xml"
 | 
					                    required: true, extension: "nwc|nwd"
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            },
 | 
				
			||||||
 | 
					            messages: { build_file_3d_modal: "File must be nwc, nwd" }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        //#endregion
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //#region 儲存區域基本資料
 | 
					        //#region 儲存區域基本資料
 | 
				
			||||||
        function SaveBuild() {
 | 
					        function SaveBuild() {
 | 
				
			||||||
            if ($("#build-form").valid()) {
 | 
					            if ($("#build-form").valid()) {
 | 
				
			||||||
                $("#save-building-btn").html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>').attr("disabled", true);
 | 
					                $("#save-building-btn").html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>').attr("disabled", true);
 | 
				
			||||||
                var url = "/BuildInfo/SaveBuildInfo";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                var formData = new FormData();
 | 
					                if(input3Dfile != undefined && input3Dfile != null) {//上傳3d檔案至forge平台
 | 
				
			||||||
                formData.append("building_tag", $('#build_name_tag').val());
 | 
					                    var file = input3Dfile;
 | 
				
			||||||
                formData.append("Full_name", $('#build_name_modal').val());
 | 
					                    var formData = new FormData();
 | 
				
			||||||
                formData.append("Ip_address", $('#ip_address_modal').val());
 | 
					                    formData.append('fileToUpload', file);
 | 
				
			||||||
                formData.append("Ip_port", $('#ip_port_modal').val());
 | 
					                    formData.append('bucketKey', "ta3hqsffzqbnouxkpldkuksew4sj21w5-bims_models");//forge上傳平台-資料夾
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                maps = $('#build_file_3d_modal')[0].files;
 | 
					                    $.ajax({
 | 
				
			||||||
                if (maps.length > 0) {
 | 
					                        url: '/api/forge/oss/objects',
 | 
				
			||||||
                    var file_names = maps[0].name.split(".");
 | 
					                        data: formData,
 | 
				
			||||||
 | 
					                        processData: false,
 | 
				
			||||||
 | 
					                        contentType: false,
 | 
				
			||||||
 | 
					                        type: 'POST',
 | 
				
			||||||
 | 
					                        success: function (data) {
 | 
				
			||||||
 | 
					                            var datas = data.split(",");
 | 
				
			||||||
 | 
					                            var urn = datas[0];
 | 
				
			||||||
 | 
					                            let m3d_names = datas[1].split(".");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    formData.append("Map3dFile", maps[0]);
 | 
					                            var url = "/BuildInfo/SaveBuildInfo";
 | 
				
			||||||
                    formData.append("orgName_3D", file_names[0]);
 | 
					
 | 
				
			||||||
                    formData.append("extName_3D", file_names[1]);
 | 
					                            var formData2 = new FormData();
 | 
				
			||||||
 | 
					                            formData2.append("building_tag", $('#build_name_tag').val());
 | 
				
			||||||
 | 
					                            formData2.append("Full_name", $('#build_name_modal').val());
 | 
				
			||||||
 | 
					                            formData2.append("Ip_address", $('#ip_address_modal').val());
 | 
				
			||||||
 | 
					                            formData2.append("Ip_port", $('#ip_port_modal').val());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            maps = $('#build_file_3d_modal')[0].files;
 | 
				
			||||||
 | 
					                            if (maps.length > 0) {
 | 
				
			||||||
 | 
					                                var file_names = maps[0].name.split(".");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                formData2.append("Map3dFile", maps[0]);
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                            formData2.append("urn_3D", urn);
 | 
				
			||||||
 | 
					                            formData2.append("orgName_3D", m3d_names[0]);
 | 
				
			||||||
 | 
					                            formData2.append("extName_3D", m3d_names[1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            $.ajax({
 | 
				
			||||||
 | 
					                                type: "POST",
 | 
				
			||||||
 | 
					                                url: url,
 | 
				
			||||||
 | 
					                                data: formData2,
 | 
				
			||||||
 | 
					                                cache: false,
 | 
				
			||||||
 | 
					                                contentType: false,
 | 
				
			||||||
 | 
					                                processData: false,
 | 
				
			||||||
 | 
					                                success: function (rel) {
 | 
				
			||||||
 | 
					                                    $("#save-building-btn").html('確定').attr("disabled", false);
 | 
				
			||||||
 | 
					                                    if (rel.code != "0000") {
 | 
				
			||||||
 | 
					                                        if (rel.code == "9999") {
 | 
				
			||||||
 | 
					                                            toast_error(rel.msg);
 | 
				
			||||||
 | 
					                                        }
 | 
				
			||||||
 | 
					                                        else {
 | 
				
			||||||
 | 
					                                            toast_warning(rel.msg);
 | 
				
			||||||
 | 
					                                        }
 | 
				
			||||||
 | 
					                                        return;
 | 
				
			||||||
 | 
					                                    }
 | 
				
			||||||
 | 
					                                    else {
 | 
				
			||||||
 | 
					                                        toast_ok(rel.msg);
 | 
				
			||||||
 | 
					                                        buildInfoTable.ajax.reload(null, false);
 | 
				
			||||||
 | 
					                                        $('#build-modal').modal('hide');
 | 
				
			||||||
 | 
					                                        return;
 | 
				
			||||||
 | 
					                                    }
 | 
				
			||||||
 | 
					                                },
 | 
				
			||||||
 | 
					                                fail: function (xhr, status, error) {
 | 
				
			||||||
 | 
					                                    $("#save-building-btn").html('確定').attr("disabled", false);
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                        fail: function (xhr, status, error) {
 | 
				
			||||||
 | 
					                            toast_error("上傳3d模型檔失敗!");
 | 
				
			||||||
 | 
					                            $("#save-building-btn").html('確定').attr("disabled", false);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					                else {
 | 
				
			||||||
 | 
					                    toast_warning("無3d模型檔案!");
 | 
				
			||||||
 | 
					                    var url = "/BuildInfo/SaveBuildInfo";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                $.ajax({
 | 
					                    var formData = new FormData();
 | 
				
			||||||
                    type: "POST",
 | 
					                    formData.append("building_tag", $('#build_name_tag').val());
 | 
				
			||||||
                    url: url,
 | 
					                    formData.append("Full_name", $('#build_name_modal').val());
 | 
				
			||||||
                    data: formData,
 | 
					                    formData.append("Ip_address", $('#ip_address_modal').val());
 | 
				
			||||||
                    cache: false,
 | 
					                    formData.append("Ip_port", $('#ip_port_modal').val());
 | 
				
			||||||
                    contentType: false,
 | 
					
 | 
				
			||||||
                    processData: false,
 | 
					                    maps = $('#build_file_3d_modal')[0].files;
 | 
				
			||||||
                    success: function (rel) {
 | 
					                    if (maps.length > 0) {
 | 
				
			||||||
                        $("#save-building-btn").html('確定').attr("disabled", false);
 | 
					                        var file_names = maps[0].name.split(".");
 | 
				
			||||||
                        if (rel.code != "0000") {
 | 
					
 | 
				
			||||||
                            if (rel.code == "9999") {
 | 
					                        formData.append("Map3dFile", maps[0]);
 | 
				
			||||||
                                toast_error(rel.msg);
 | 
					                        formData.append("orgName_3D", file_names[0]);
 | 
				
			||||||
 | 
					                        formData.append("extName_3D", file_names[1]);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    $.ajax({
 | 
				
			||||||
 | 
					                        type: "POST",
 | 
				
			||||||
 | 
					                        url: url,
 | 
				
			||||||
 | 
					                        data: formData,
 | 
				
			||||||
 | 
					                        cache: false,
 | 
				
			||||||
 | 
					                        contentType: false,
 | 
				
			||||||
 | 
					                        processData: false,
 | 
				
			||||||
 | 
					                        success: function (rel) {
 | 
				
			||||||
 | 
					                            $("#save-building-btn").html('確定').attr("disabled", false);
 | 
				
			||||||
 | 
					                            if (rel.code != "0000") {
 | 
				
			||||||
 | 
					                                if (rel.code == "9999") {
 | 
				
			||||||
 | 
					                                    toast_error(rel.msg);
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                                else {
 | 
				
			||||||
 | 
					                                    toast_warning(rel.msg);
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                                return;
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                            else {
 | 
					                            else {
 | 
				
			||||||
                                toast_warning(rel.msg);
 | 
					                                toast_ok(rel.msg);
 | 
				
			||||||
 | 
					                                buildInfoTable.ajax.reload(null, false);
 | 
				
			||||||
 | 
					                                $('#build-modal').modal('hide');
 | 
				
			||||||
 | 
					                                return;
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                            return;
 | 
					                        },
 | 
				
			||||||
 | 
					                        fail: function (xhr, status, error) {
 | 
				
			||||||
 | 
					                            $("#save-building-btn").html('確定').attr("disabled", false);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        else {
 | 
					                    });
 | 
				
			||||||
                            toast_ok(rel.msg);
 | 
					                }
 | 
				
			||||||
                            buildInfoTable.ajax.reload(null, false);
 | 
					
 | 
				
			||||||
                            $('#build-modal').modal('hide');
 | 
					                //var url = "/BuildInfo/SaveBuildInfo";
 | 
				
			||||||
                            return;
 | 
					
 | 
				
			||||||
                        }
 | 
					                //var formData = new FormData();
 | 
				
			||||||
                    },
 | 
					                //formData.append("building_tag", $('#build_name_tag').val());
 | 
				
			||||||
                    fail: function (xhr, status, error) {
 | 
					                //formData.append("Full_name", $('#build_name_modal').val());
 | 
				
			||||||
                        $("#save-building-btn").html('確定').attr("disabled", false);
 | 
					                //formData.append("Ip_address", $('#ip_address_modal').val());
 | 
				
			||||||
                    }
 | 
					                //formData.append("Ip_port", $('#ip_port_modal').val());
 | 
				
			||||||
                });
 | 
					
 | 
				
			||||||
 | 
					                //maps = $('#build_file_3d_modal')[0].files;
 | 
				
			||||||
 | 
					                //if (maps.length > 0) {
 | 
				
			||||||
 | 
					                //    var file_names = maps[0].name.split(".");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                //    formData.append("Map3dFile", maps[0]);
 | 
				
			||||||
 | 
					                //    formData.append("orgName_3D", file_names[0]);
 | 
				
			||||||
 | 
					                //    formData.append("extName_3D", file_names[1]);
 | 
				
			||||||
 | 
					                //}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                //$.ajax({
 | 
				
			||||||
 | 
					                //    type: "POST",
 | 
				
			||||||
 | 
					                //    url: url,
 | 
				
			||||||
 | 
					                //    data: formData,
 | 
				
			||||||
 | 
					                //    cache: false,
 | 
				
			||||||
 | 
					                //    contentType: false,
 | 
				
			||||||
 | 
					                //    processData: false,
 | 
				
			||||||
 | 
					                //    success: function (rel) {
 | 
				
			||||||
 | 
					                //        $("#save-building-btn").html('確定').attr("disabled", false);
 | 
				
			||||||
 | 
					                //        if (rel.code != "0000") {
 | 
				
			||||||
 | 
					                //            if (rel.code == "9999") {
 | 
				
			||||||
 | 
					                //                toast_error(rel.msg);
 | 
				
			||||||
 | 
					                //            }
 | 
				
			||||||
 | 
					                //            else {
 | 
				
			||||||
 | 
					                //                toast_warning(rel.msg);
 | 
				
			||||||
 | 
					                //            }
 | 
				
			||||||
 | 
					                //            return;
 | 
				
			||||||
 | 
					                //        }
 | 
				
			||||||
 | 
					                //        else {
 | 
				
			||||||
 | 
					                //            toast_ok(rel.msg);
 | 
				
			||||||
 | 
					                //            buildInfoTable.ajax.reload(null, false);
 | 
				
			||||||
 | 
					                //            $('#build-modal').modal('hide');
 | 
				
			||||||
 | 
					                //            return;
 | 
				
			||||||
 | 
					                //        }
 | 
				
			||||||
 | 
					                //    },
 | 
				
			||||||
 | 
					                //    fail: function (xhr, status, error) {
 | 
				
			||||||
 | 
					                //        $("#save-building-btn").html('確定').attr("disabled", false);
 | 
				
			||||||
 | 
					                //    }
 | 
				
			||||||
 | 
					                //});
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        function EditBuild() {
 | 
					        function EditBuild() {
 | 
				
			||||||
            if ($("#build-form").valid()) {
 | 
					            if ($("#build-form").valid()) {
 | 
				
			||||||
                $("#save-building-btn").html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>').attr("disabled", true);
 | 
					                $("#save-building-btn").html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>').attr("disabled", true);
 | 
				
			||||||
                var url = "/BuildInfo/EditBuildInfo";
 | 
					                if (input3Dfile != undefined && input3Dfile != null) {//上傳3d檔案至forge平台
 | 
				
			||||||
                var formData = new FormData();
 | 
					                    var file = input3Dfile;
 | 
				
			||||||
 | 
					                    var formData = new FormData();
 | 
				
			||||||
 | 
					                    formData.append('fileToUpload', file);
 | 
				
			||||||
 | 
					                    formData.append('bucketKey', "ta3hqsffzqbnouxkpldkuksew4sj21w5-bims_models");//forge上傳平台-資料夾
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                formData.append("building_tag", selected_build_guid);
 | 
					                    $.ajax({
 | 
				
			||||||
                formData.append("Full_name", $('#build_name_modal').val());
 | 
					                        url: '/api/forge/oss/objects',
 | 
				
			||||||
                formData.append("Ip_address", $('#ip_address_modal').val());
 | 
					                        data: formData,
 | 
				
			||||||
                formData.append("Ip_port", $('#ip_port_modal').val());
 | 
					                        processData: false,
 | 
				
			||||||
 | 
					                        contentType: false,
 | 
				
			||||||
 | 
					                        type: 'POST',
 | 
				
			||||||
 | 
					                        success: function (data) {
 | 
				
			||||||
 | 
					                            var datas = data.split(",");
 | 
				
			||||||
 | 
					                            var urn = datas[0];
 | 
				
			||||||
 | 
					                            let m3d_names = datas[1].split(".");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                maps = $('#build_file_3d_modal')[0].files;
 | 
					                            var url = "/BuildInfo/EditBuildInfo";
 | 
				
			||||||
                if (maps.length > 0) {
 | 
					                            var formData2 = new FormData();
 | 
				
			||||||
                    var file_names = maps[0].name.split(".");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    formData.append("Map3dFile", maps[0]);
 | 
					                            formData2.append("building_tag", selected_build_guid);
 | 
				
			||||||
                    formData.append("orgName_3D", file_names[0]);
 | 
					                            formData2.append("Full_name", $('#build_name_modal').val());
 | 
				
			||||||
                    formData.append("extName_3D", file_names[1]);
 | 
					                            formData2.append("Ip_address", $('#ip_address_modal').val());
 | 
				
			||||||
 | 
					                            formData2.append("Ip_port", $('#ip_port_modal').val());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            maps = $('#build_file_3d_modal')[0].files;
 | 
				
			||||||
 | 
					                            if (maps.length > 0) {
 | 
				
			||||||
 | 
					                                var file_names = maps[0].name.split(".");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                formData2.append("Map3dFile", maps[0]);
 | 
				
			||||||
 | 
					                                //formData2.append("orgName_3D", file_names[0]);
 | 
				
			||||||
 | 
					                                //formData2.append("extName_3D", file_names[1]);
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                            formData2.append("urn_3D", urn);
 | 
				
			||||||
 | 
					                            formData2.append("orgName_3D", m3d_names[0]);
 | 
				
			||||||
 | 
					                            formData2.append("extName_3D", m3d_names[1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            $.ajax({
 | 
				
			||||||
 | 
					                                type: "POST",
 | 
				
			||||||
 | 
					                                url: url,
 | 
				
			||||||
 | 
					                                data: formData2,
 | 
				
			||||||
 | 
					                                cache: false,
 | 
				
			||||||
 | 
					                                contentType: false,
 | 
				
			||||||
 | 
					                                processData: false,
 | 
				
			||||||
 | 
					                                success: function (rel) {
 | 
				
			||||||
 | 
					                                    $("#save-building-btn").html('確定').attr("disabled", false);
 | 
				
			||||||
 | 
					                                    if (rel.code != "0000") {
 | 
				
			||||||
 | 
					                                        if (rel.code == "9999") {
 | 
				
			||||||
 | 
					                                            toast_error(rel.msg);
 | 
				
			||||||
 | 
					                                        }
 | 
				
			||||||
 | 
					                                        else {
 | 
				
			||||||
 | 
					                                            toast_warning(rel.msg);
 | 
				
			||||||
 | 
					                                        }
 | 
				
			||||||
 | 
					                                        return;
 | 
				
			||||||
 | 
					                                    }
 | 
				
			||||||
 | 
					                                    else {
 | 
				
			||||||
 | 
					                                        toast_ok(rel.msg);
 | 
				
			||||||
 | 
					                                        buildInfoTable.ajax.reload(null, false);
 | 
				
			||||||
 | 
					                                        $('#build-modal').modal('hide');
 | 
				
			||||||
 | 
					                                        return;
 | 
				
			||||||
 | 
					                                    }
 | 
				
			||||||
 | 
					                                },
 | 
				
			||||||
 | 
					                                fail: function (xhr, status, error) {
 | 
				
			||||||
 | 
					                                    $("#save-building-btn").html('確定').attr("disabled", false);
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                        fail: function (xhr, status, error) {
 | 
				
			||||||
 | 
					                            toast_error("上傳3d模型檔失敗!");
 | 
				
			||||||
 | 
					                            $("#save-building-btn").html('確定').attr("disabled", false);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					                else {
 | 
				
			||||||
 | 
					                    var url = "/BuildInfo/EditBuildInfo";
 | 
				
			||||||
 | 
					                    var formData = new FormData();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                $.ajax({
 | 
					                    formData.append("building_tag", selected_build_guid);
 | 
				
			||||||
                    type: "POST",
 | 
					                    formData.append("Full_name", $('#build_name_modal').val());
 | 
				
			||||||
                    url: url,
 | 
					                    formData.append("Ip_address", $('#ip_address_modal').val());
 | 
				
			||||||
                    data: formData,
 | 
					                    formData.append("Ip_port", $('#ip_port_modal').val());
 | 
				
			||||||
                    cache: false,
 | 
					
 | 
				
			||||||
                    contentType: false,
 | 
					                    maps = $('#build_file_3d_modal')[0].files;
 | 
				
			||||||
                    processData: false,
 | 
					                    if (maps.length > 0) {
 | 
				
			||||||
                    success: function (rel) {
 | 
					                        var file_names = maps[0].name.split(".");
 | 
				
			||||||
                        $("#save-building-btn").html('確定').attr("disabled", false);
 | 
					
 | 
				
			||||||
                        if (rel.code != "0000") {
 | 
					                        formData.append("Map3dFile", maps[0]);
 | 
				
			||||||
                            if (rel.code == "9999") {
 | 
					                        formData.append("orgName_3D", file_names[0]);
 | 
				
			||||||
                                toast_error(rel.msg);
 | 
					                        formData.append("extName_3D", file_names[1]);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    $.ajax({
 | 
				
			||||||
 | 
					                        type: "POST",
 | 
				
			||||||
 | 
					                        url: url,
 | 
				
			||||||
 | 
					                        data: formData,
 | 
				
			||||||
 | 
					                        cache: false,
 | 
				
			||||||
 | 
					                        contentType: false,
 | 
				
			||||||
 | 
					                        processData: false,
 | 
				
			||||||
 | 
					                        success: function (rel) {
 | 
				
			||||||
 | 
					                            $("#save-building-btn").html('確定').attr("disabled", false);
 | 
				
			||||||
 | 
					                            if (rel.code != "0000") {
 | 
				
			||||||
 | 
					                                if (rel.code == "9999") {
 | 
				
			||||||
 | 
					                                    toast_error(rel.msg);
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                                else {
 | 
				
			||||||
 | 
					                                    toast_warning(rel.msg);
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                                return;
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                            else {
 | 
					                            else {
 | 
				
			||||||
                                toast_warning(rel.msg);
 | 
					                                toast_ok(rel.msg);
 | 
				
			||||||
 | 
					                                buildInfoTable.ajax.reload(null, false);
 | 
				
			||||||
 | 
					                                $('#build-modal').modal('hide');
 | 
				
			||||||
 | 
					                                return;
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                            return;
 | 
					                        },
 | 
				
			||||||
 | 
					                        fail: function (xhr, status, error) {
 | 
				
			||||||
 | 
					                            $("#save-building-btn").html('確定').attr("disabled", false);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        else {
 | 
					                    });
 | 
				
			||||||
                            toast_ok(rel.msg);
 | 
					                }
 | 
				
			||||||
                            buildInfoTable.ajax.reload(null, false);
 | 
					                
 | 
				
			||||||
                            $('#build-modal').modal('hide');
 | 
					                //var url = "/BuildInfo/EditBuildInfo";
 | 
				
			||||||
                            return;
 | 
					                //var formData = new FormData();
 | 
				
			||||||
                        }
 | 
					
 | 
				
			||||||
                    },
 | 
					                //formData.append("building_tag", selected_build_guid);
 | 
				
			||||||
                    fail: function (xhr, status, error) {
 | 
					                //formData.append("Full_name", $('#build_name_modal').val());
 | 
				
			||||||
                        $("#save-building-btn").html('確定').attr("disabled", false);
 | 
					                //formData.append("Ip_address", $('#ip_address_modal').val());
 | 
				
			||||||
                    }
 | 
					                //formData.append("Ip_port", $('#ip_port_modal').val());
 | 
				
			||||||
                });
 | 
					
 | 
				
			||||||
 | 
					                //maps = $('#build_file_3d_modal')[0].files;
 | 
				
			||||||
 | 
					                //if (maps.length > 0) {
 | 
				
			||||||
 | 
					                //    var file_names = maps[0].name.split(".");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                //    formData.append("Map3dFile", maps[0]);
 | 
				
			||||||
 | 
					                //    formData.append("orgName_3D", file_names[0]);
 | 
				
			||||||
 | 
					                //    formData.append("extName_3D", file_names[1]);
 | 
				
			||||||
 | 
					                //}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                //$.ajax({
 | 
				
			||||||
 | 
					                //    type: "POST",
 | 
				
			||||||
 | 
					                //    url: url,
 | 
				
			||||||
 | 
					                //    data: formData,
 | 
				
			||||||
 | 
					                //    cache: false,
 | 
				
			||||||
 | 
					                //    contentType: false,
 | 
				
			||||||
 | 
					                //    processData: false,
 | 
				
			||||||
 | 
					                //    success: function (rel) {
 | 
				
			||||||
 | 
					                //        $("#save-building-btn").html('確定').attr("disabled", false);
 | 
				
			||||||
 | 
					                //        if (rel.code != "0000") {
 | 
				
			||||||
 | 
					                //            if (rel.code == "9999") {
 | 
				
			||||||
 | 
					                //                toast_error(rel.msg);
 | 
				
			||||||
 | 
					                //            }
 | 
				
			||||||
 | 
					                //            else {
 | 
				
			||||||
 | 
					                //                toast_warning(rel.msg);
 | 
				
			||||||
 | 
					                //            }
 | 
				
			||||||
 | 
					                //            return;
 | 
				
			||||||
 | 
					                //        }
 | 
				
			||||||
 | 
					                //        else {
 | 
				
			||||||
 | 
					                //            toast_ok(rel.msg);
 | 
				
			||||||
 | 
					                //            buildInfoTable.ajax.reload(null, false);
 | 
				
			||||||
 | 
					                //            $('#build-modal').modal('hide');
 | 
				
			||||||
 | 
					                //            return;
 | 
				
			||||||
 | 
					                //        }
 | 
				
			||||||
 | 
					                //    },
 | 
				
			||||||
 | 
					                //    fail: function (xhr, status, error) {
 | 
				
			||||||
 | 
					                //        $("#save-building-btn").html('確定').attr("disabled", false);
 | 
				
			||||||
 | 
					                //    }
 | 
				
			||||||
 | 
					                //});
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        //#endregion
 | 
					        //#endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    </script>
 | 
					    
 | 
				
			||||||
    <script>
 | 
					 | 
				
			||||||
        //#region 樓層設定 document ready
 | 
					        //#region 樓層設定 document ready
 | 
				
			||||||
        $(function () {
 | 
					        $(function () {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -701,10 +948,13 @@
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        //#endregion
 | 
					        //#endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //#region 變更樓層平面圖
 | 
					        //#region 變更樓層平面圖 3d模型
 | 
				
			||||||
        function changeImage(input) {
 | 
					        function changeImage(input) {
 | 
				
			||||||
            $(`#map_file_preview_modal`).attr("data-src", window.URL.createObjectURL(input.files[0]));
 | 
					            $(`#map_file_preview_modal`).attr("data-src", window.URL.createObjectURL(input.files[0]));
 | 
				
			||||||
 | 
					            input3Dfile = input.files[0];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        //#endregion
 | 
					        //#endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    </script>
 | 
					    </script>
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -57,8 +57,8 @@
 | 
				
			|||||||
                            <input type="text" id="ip_port_modal" class="form-control" name="ip_port_modal">
 | 
					                            <input type="text" id="ip_port_modal" class="form-control" name="ip_port_modal">
 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                        <div class="form-group col-12">
 | 
					                        <div class="form-group col-12">
 | 
				
			||||||
                            <label class="form-label" for="build_file_3d_modal">3D檔(限制SVG格式)</label>
 | 
					                            <label class="form-label" for="build_file_3d_modal">3D檔(限制NWD、NWC格式)</label>
 | 
				
			||||||
                            <input type="file" id="build_file_3d_modal" class="form-control" name="build_file_3d_modal" onchange="changeImage(this)" accept="image/svg+xml">
 | 
					                            <input type="file" id="build_file_3d_modal" class="form-control" name="build_file_3d_modal" onchange="changeImage(this)">
 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                </form>
 | 
					                </form>
 | 
				
			||||||
 | 
				
			|||||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							@ -158,7 +158,7 @@
 | 
				
			|||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
                <div class="btn-group btn-group-lg col-lg-6 mb-4">
 | 
					                <div class="btn-group btn-group-lg col-lg-6 mb-4">
 | 
				
			||||||
                    <button type="button" class="btn btn-secondary"><i class="fal fa-car-battery fa-2x"></i></button>
 | 
					                    <button type="button" class="btn btn-secondary"><i class="fal fa-car-battery fa-2x"></i></button>
 | 
				
			||||||
                    <button type="button" class="btn btn-secondary">電錶系統  </button>
 | 
					                    <button type="button" class="btn btn-secondary" onclick="goElectricMeter()">電錶系統  </button>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
                <div class="btn-group btn-group-lg col-lg-6 mb-4">
 | 
					                <div class="btn-group btn-group-lg col-lg-6 mb-4">
 | 
				
			||||||
                    <button type="button" class="btn btn-secondary"><i class="fal fa-wind fa-2x"></i></button>
 | 
					                    <button type="button" class="btn btn-secondary"><i class="fal fa-wind fa-2x"></i></button>
 | 
				
			||||||
@ -705,4 +705,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function goElectricMeter() {
 | 
				
			||||||
 | 
					        pageAct.sysMainTag = $('#subSysBtnE4').data("subSysObj").main_system_tag;
 | 
				
			||||||
 | 
					        pageAct.sysSubTag = $('#subSysBtnE4').data("subSysObj").sub_system_tag;
 | 
				
			||||||
 | 
					        pageAct.sysSubName = $('#subSysBtnE4').data("subSysObj").full_name;
 | 
				
			||||||
 | 
					        pageAct.sysSubObj = $('#subSysBtnE4').data("subSysObj");
 | 
				
			||||||
 | 
					        $("#js-page-content").load("_sysMonAll.html", loadCallback);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
@ -1,9 +1,11 @@
 | 
				
			|||||||
<style>
 | 
					<style>
 | 
				
			||||||
    .elevator {
 | 
					    .elevator {
 | 
				
			||||||
        background-color: #fff;
 | 
					        background-color: #fff;
 | 
				
			||||||
        height: 520px;
 | 
					        min-height: 520px;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    .elevator-table-wrapper {
 | 
				
			||||||
 | 
					        padding:0.8rem;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    table.elevator-build {
 | 
					    table.elevator-build {
 | 
				
			||||||
        /*border: 1px double #000;*/
 | 
					        /*border: 1px double #000;*/
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -25,6 +27,20 @@
 | 
				
			|||||||
        height: 47px;
 | 
					        height: 47px;
 | 
				
			||||||
        border: 4px solid orange;
 | 
					        border: 4px solid orange;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .elevator-item-toup {
 | 
				
			||||||
 | 
					        border: 4px solid rgba(255,255,255,0);
 | 
				
			||||||
 | 
					        position: absolute;
 | 
				
			||||||
 | 
					        border-bottom: 0;
 | 
				
			||||||
 | 
					        z-index: 2;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .elevator-item-todown {
 | 
				
			||||||
 | 
					        border: 4px solid rgba(255,255,255,0);
 | 
				
			||||||
 | 
					        position: absolute;
 | 
				
			||||||
 | 
					        border-top: 0;
 | 
				
			||||||
 | 
					        z-index: 2;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div class="d-flex">
 | 
					<div class="d-flex">
 | 
				
			||||||
@ -35,19 +51,21 @@
 | 
				
			|||||||
            <div id="elevatorBlock" class="elevator">
 | 
					            <div id="elevatorBlock" class="elevator">
 | 
				
			||||||
                <div class="elevator-header">
 | 
					                <div class="elevator-header">
 | 
				
			||||||
                    <div class="row m-0 align-items-center p-2 gap-3 btn-group btn-group-toggle">
 | 
					                    <div class="row m-0 align-items-center p-2 gap-3 btn-group btn-group-toggle">
 | 
				
			||||||
                        <button class="btn btn-secondary btn-sm active" data-tabname="floShowType" data-target="#2dDiv">2D
 | 
					                        <button class="btn btn-secondary btn-sm" data-tabname="floShowType" data-target="#2dDiv">
 | 
				
			||||||
 | 
					                            2D
 | 
				
			||||||
                        </button>
 | 
					                        </button>
 | 
				
			||||||
                        <button class="btn btn-secondary btn-sm" data-tabname="floShowType" data-target="#3dDiv">3D
 | 
					                        <button class="btn btn-secondary btn-sm active" data-tabname="floShowType" data-target="#3dDiv" onclick="show3D()">
 | 
				
			||||||
 | 
					                            3D
 | 
				
			||||||
                        </button>
 | 
					                        </button>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
                <div class="elevator-body d-flex align-items-center justify-content-center yt-table-container">
 | 
					                <div class="elevator-body d-flex align-items-center justify-content-center">
 | 
				
			||||||
                    <div id="2dDiv" data-tabname="floShowType" data-tabrole="child">
 | 
					                    <div id="2dDiv" class="p-2" data-tabname="floShowType" data-tabrole="child">
 | 
				
			||||||
                        <table id="floorTable" class="elevator-build m-auto">
 | 
					                        <table id="floorTable" class="elevator-build m-auto">
 | 
				
			||||||
                        </table>
 | 
					                        </table>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                    <div id="3dDiv" data-tabname="floShowType" data-tabrole="child">
 | 
					                    <div id="3dDiv" class="w-100" data-tabname="floShowType" data-tabrole="child">
 | 
				
			||||||
 | 
					                        <div id="forgeViewer"></div>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
@ -481,7 +499,7 @@
 | 
				
			|||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                    <div id="detDevDiv" style="display:none">
 | 
					                    <div id="detDevDiv" style="display:none">
 | 
				
			||||||
                        <button class="btn btn-info" data-toggle="prevDiv"><i class="fas fa-angle-left mr-2"></i>上一頁</button>
 | 
					                        <button class="btn btn-info" data-toggle="prevDiv"><i class="fas fa-angle-left mr-2"></i>上一頁</button>
 | 
				
			||||||
                        <table class="table table-hover">
 | 
					                        <table id="eleManDevTable" class="table table-hover">
 | 
				
			||||||
                            <thead>
 | 
					                            <thead>
 | 
				
			||||||
                                <tr class="text-center">
 | 
					                                <tr class="text-center">
 | 
				
			||||||
                                    <th scope="col">號機</th>
 | 
					                                    <th scope="col">號機</th>
 | 
				
			||||||
@ -502,7 +520,7 @@
 | 
				
			|||||||
                                    <td>
 | 
					                                    <td>
 | 
				
			||||||
                                        <div class="d-flex justify-content-center align-items-center">
 | 
					                                        <div class="d-flex justify-content-center align-items-center">
 | 
				
			||||||
                                            <div class="row mr-2">
 | 
					                                            <div class="row mr-2">
 | 
				
			||||||
                                                <input name="preMea" type="checkbox" class="toggle" data-toggle="toggle">
 | 
					                                                <input name="preMea" type="checkbox" class="toggle" data-toggle="toggle" data-point="SP_DP" >
 | 
				
			||||||
                                            </div>
 | 
					                                            </div>
 | 
				
			||||||
                                            <i id="preMeaSche" data-point="DP" class="fas fa-calendar-alt fs-1-1 mr-2 cur-poi"></i>
 | 
					                                            <i id="preMeaSche" data-point="DP" class="fas fa-calendar-alt fs-1-1 mr-2 cur-poi"></i>
 | 
				
			||||||
                                        </div>
 | 
					                                        </div>
 | 
				
			||||||
@ -510,7 +528,7 @@
 | 
				
			|||||||
                                    <td>
 | 
					                                    <td>
 | 
				
			||||||
                                        <div class="d-flex justify-content-center align-items-center">
 | 
					                                        <div class="d-flex justify-content-center align-items-center">
 | 
				
			||||||
                                            <div class="row mr-2">
 | 
					                                            <div class="row mr-2">
 | 
				
			||||||
                                                <input name="stop" type="checkbox" class="toggle" data-toggle="toggle">
 | 
					                                                <input name="stop" type="checkbox" class="toggle" data-toggle="toggle" data-point="SP_RCS">
 | 
				
			||||||
                                            </div>
 | 
					                                            </div>
 | 
				
			||||||
                                            <i id="stopSche" data-point="RCS" class="fas fa-calendar-alt fs-1-1 mr-2 cur-poi"></i>
 | 
					                                            <i id="stopSche" data-point="RCS" class="fas fa-calendar-alt fs-1-1 mr-2 cur-poi"></i>
 | 
				
			||||||
                                        </div>
 | 
					                                        </div>
 | 
				
			||||||
@ -518,7 +536,7 @@
 | 
				
			|||||||
                                    <td>
 | 
					                                    <td>
 | 
				
			||||||
                                        <div class="d-flex justify-content-center align-items-center">
 | 
					                                        <div class="d-flex justify-content-center align-items-center">
 | 
				
			||||||
                                            <div class="row mr-2">
 | 
					                                            <div class="row mr-2">
 | 
				
			||||||
                                                <input name="onlyOpe" type="checkbox" class="toggle" data-toggle="toggle">
 | 
					                                                <input name="onlyOpe" type="checkbox" class="toggle" data-toggle="toggle" data-point="SP_IND">
 | 
				
			||||||
                                            </div>
 | 
					                                            </div>
 | 
				
			||||||
                                            <i id="onlyOpeSche" data-point="IND" class="fas fa-calendar-alt fs-1-1 mr-2 cur-poi"></i>
 | 
					                                            <i id="onlyOpeSche" data-point="IND" class="fas fa-calendar-alt fs-1-1 mr-2 cur-poi"></i>
 | 
				
			||||||
                                        </div>
 | 
					                                        </div>
 | 
				
			||||||
@ -526,7 +544,7 @@
 | 
				
			|||||||
                                    <td>
 | 
					                                    <td>
 | 
				
			||||||
                                        <div class="d-flex justify-content-center align-items-center">
 | 
					                                        <div class="d-flex justify-content-center align-items-center">
 | 
				
			||||||
                                            <div class="row mr-2">
 | 
					                                            <div class="row mr-2">
 | 
				
			||||||
                                                <input name="vip" type="checkbox" class="toggle" data-toggle="toggle">
 | 
					                                                <input name="vip" type="checkbox" class="toggle" data-toggle="toggle" data-point="SP_VIP">
 | 
				
			||||||
                                            </div>
 | 
					                                            </div>
 | 
				
			||||||
                                            <i id="vipSche" data-point="VIP" class="fas fa-calendar-alt fs-1-1 mr-2 cur-poi"></i>
 | 
					                                            <i id="vipSche" data-point="VIP" class="fas fa-calendar-alt fs-1-1 mr-2 cur-poi"></i>
 | 
				
			||||||
                                        </div>
 | 
					                                        </div>
 | 
				
			||||||
@ -534,7 +552,7 @@
 | 
				
			|||||||
                                    <td>
 | 
					                                    <td>
 | 
				
			||||||
                                        <div class="d-flex justify-content-center align-items-center">
 | 
					                                        <div class="d-flex justify-content-center align-items-center">
 | 
				
			||||||
                                            <div class="row mr-2">
 | 
					                                            <div class="row mr-2">
 | 
				
			||||||
                                                <input name="retOpe" type="checkbox" class="toggle" data-toggle="toggle">
 | 
					                                                <input name="retOpe" type="checkbox" class="toggle" data-toggle="toggle" data-point="SP_RET">
 | 
				
			||||||
                                            </div>
 | 
					                                            </div>
 | 
				
			||||||
                                            <i id="retOpeSche" data-point="RET" class="fas fa-calendar-alt fs-1-1 mr-2 cur-poi"></i>
 | 
					                                            <i id="retOpeSche" data-point="RET" class="fas fa-calendar-alt fs-1-1 mr-2 cur-poi"></i>
 | 
				
			||||||
                                        </div>
 | 
					                                        </div>
 | 
				
			||||||
@ -876,8 +894,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
    var eleManTable = null;
 | 
					    var eleManTable = null;
 | 
				
			||||||
    var allDevList = [];
 | 
					    var allDevList = [];       //每個設備
 | 
				
			||||||
    var subSeviceData = [];
 | 
					    var subSeviceData = [];    //每個設備訂閱點位值
 | 
				
			||||||
 | 
					    var floList = [];          //每個樓層
 | 
				
			||||||
 | 
					    var elevObj = null;        //左側 2D 電梯物件
 | 
				
			||||||
    var subOrdPath = {
 | 
					    var subOrdPath = {
 | 
				
			||||||
        "building_tag": pageAct.buiTag,
 | 
					        "building_tag": pageAct.buiTag,
 | 
				
			||||||
        "system_tag": pageAct.sysMainTag,
 | 
					        "system_tag": pageAct.sysMainTag,
 | 
				
			||||||
@ -889,13 +909,17 @@
 | 
				
			|||||||
    var allDeviceRowData = []; //所有設備原始資料
 | 
					    var allDeviceRowData = []; //所有設備原始資料
 | 
				
			||||||
    var global_emergency_alarm_device_number = [];
 | 
					    var global_emergency_alarm_device_number = [];
 | 
				
			||||||
    var zoomToggle = 3;
 | 
					    var zoomToggle = 3;
 | 
				
			||||||
 | 
					    var isFirstLoad3D = true;
 | 
				
			||||||
    $(function () {
 | 
					    $(function () {
 | 
				
			||||||
        initChart();
 | 
					        initChart();
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        setBuildFloor();
 | 
					        setBuildFloor();
 | 
				
			||||||
        setCards();
 | 
					        setCards();
 | 
				
			||||||
        subDeviceSetStatus();
 | 
					        subDeviceSetStatus();
 | 
				
			||||||
        setEleManTable();
 | 
					        setEleManTable();
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function getFloDevList() {
 | 
					    function getFloDevList() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -936,7 +960,7 @@
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            //現在樓層
 | 
					            //現在樓層
 | 
				
			||||||
            if (data.point_name == "CP") {
 | 
					            if (data.point_name == "CP") {
 | 
				
			||||||
                $(`#${matchDevice.device_number}_card [name=curFloor]`).text(data.value + "F");
 | 
					                $(`#${matchDevice.device_number}_card [name=curFloor]`).text(data.value);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            //往上或往下
 | 
					            //往上或往下
 | 
				
			||||||
            if (getValueByName("RD") == "UP") {
 | 
					            if (getValueByName("RD") == "UP") {
 | 
				
			||||||
@ -969,7 +993,9 @@
 | 
				
			|||||||
            if (subData) {
 | 
					            if (subData) {
 | 
				
			||||||
                subData[data.point_name] = data.value;
 | 
					                subData[data.point_name] = data.value;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            // 設置燈色、卡片閃爍
 | 
				
			||||||
            setLightColor();
 | 
					            setLightColor();
 | 
				
			||||||
 | 
					            // Card table 更新
 | 
				
			||||||
            subDeviceSetTable(matchDevice.device_number);
 | 
					            subDeviceSetTable(matchDevice.device_number);
 | 
				
			||||||
            // 重繪 電梯管理 列表
 | 
					            // 重繪 電梯管理 列表
 | 
				
			||||||
            reloadEleManTable(setEleManTabDataFromBaja());
 | 
					            reloadEleManTable(setEleManTabDataFromBaja());
 | 
				
			||||||
@ -990,6 +1016,12 @@
 | 
				
			|||||||
            let main = {};
 | 
					            let main = {};
 | 
				
			||||||
            // 匯入 Master 名稱`
 | 
					            // 匯入 Master 名稱`
 | 
				
			||||||
            main.devName = master;
 | 
					            main.devName = master;
 | 
				
			||||||
 | 
					            let subData = subSeviceData.filter(x => x.device_number.split("_")[5] == master)[0];
 | 
				
			||||||
 | 
					            $.each(Object.keys(subData), (idx3, subKey) => {
 | 
				
			||||||
 | 
					                if (subKey.startsWith("SP_FLS_")) { 
 | 
				
			||||||
 | 
					                    main[subKey] = subData[subKey];
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
            main._rowType = "master";
 | 
					            main._rowType = "master";
 | 
				
			||||||
            result.push(main);
 | 
					            result.push(main);
 | 
				
			||||||
            // 該 Master 底下的設備
 | 
					            // 該 Master 底下的設備
 | 
				
			||||||
@ -1008,7 +1040,6 @@
 | 
				
			|||||||
                result.push(main);
 | 
					                result.push(main);
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
        console.log("redraw", result)
 | 
					 | 
				
			||||||
        return result;
 | 
					        return result;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1023,16 +1054,28 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        function creLight(type = "trueText") {
 | 
					        function creLight(type = "trueText") {
 | 
				
			||||||
            let lightType = type == "trueText" ? "bg-success" : "bg-danger";
 | 
					            let lightType = type == "trueText" ? "bg-success" : "bg-danger";
 | 
				
			||||||
            return creEle("span", null, null, null, [lightType, "circle-light"]).outerHtml();
 | 
					            
 | 
				
			||||||
 | 
					            return $(creEle("span", null, null, null, [lightType, "circle-light"])).outerHtml();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let masterTag = devNum?.split("_")[5];
 | 
					        let masterTag = devNum?.split("_")[5];
 | 
				
			||||||
 | 
					 | 
				
			||||||
        let notSerFloors = Object.keys(subData).filter(x => x.startsWith("SP_FLS_") && subData[x] == "trueText").map(x => x?.split("SP_FLS_")[1]);
 | 
					        let notSerFloors = Object.keys(subData).filter(x => x.startsWith("SP_FLS_") && subData[x] == "trueText").map(x => x?.split("SP_FLS_")[1]);
 | 
				
			||||||
 | 
					        floList = Object.keys(subData).filter(x => x.startsWith("SP_FLS_")).map(x => x?.split("SP_FLS_")[1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //左側 2D 電梯物件 樓層資料更新
 | 
				
			||||||
 | 
					        if (elevObj.floors.length != floList.length) {
 | 
				
			||||||
 | 
					            elevObj.floors = floList.map((x, idx) => { return { id: x, name: x, sort: idx + 1 } });
 | 
				
			||||||
 | 
					            elevObj.elevators = allDevList.map((x) => { return { id: x.device_number } });
 | 
				
			||||||
 | 
					            elevObj.curElevFloor[matchDevice.device_number] = subData["CP"];
 | 
				
			||||||
 | 
					            elevObj.redraw();
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            elevObj.setElevFloor(matchDevice.device_number, subData["CP"]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        elevObj.setEleMovStatus(matchDevice.device_number, subData["RD"] == "UP" ? 1 : subData["RD"] == "DOWN" ? 2 : 0);
 | 
				
			||||||
        //現在樓層
 | 
					        //現在樓層
 | 
				
			||||||
        if (subData["CP"]) {
 | 
					        if (subData["CP"]) {
 | 
				
			||||||
            $(`#imdStaTable_${devNum} [name=curFloor]`).text(subData["CP"] + "F");
 | 
					            $(`#imdStaTable_${devNum} [name=curFloor]`).text(subData["CP"]);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        //往上或往下
 | 
					        //往上或往下
 | 
				
			||||||
        if (subData["RD"] == "UP") {
 | 
					        if (subData["RD"] == "UP") {
 | 
				
			||||||
@ -1073,11 +1116,20 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                let strHtml = ``;
 | 
					                let strHtml = ``;
 | 
				
			||||||
 | 
					                let masterArr = [];
 | 
				
			||||||
 | 
					                let masDiv = "";
 | 
				
			||||||
                $.each(res.data, (index, floObj) => {
 | 
					                $.each(res.data, (index, floObj) => {
 | 
				
			||||||
 | 
					                   
 | 
				
			||||||
                    $.each(floObj.device_list, (index2, devObj) => {
 | 
					                    $.each(floObj.device_list, (index2, devObj) => {
 | 
				
			||||||
                        allDevList.push(devObj);
 | 
					                        allDevList.push(devObj);
 | 
				
			||||||
 | 
					                        if (masterArr.indexOf(devObj?.device_number?.split("_")[5]) == -1) {
 | 
				
			||||||
                        strHtml += `<div id="${devObj.device_number}_card" class="card dev-card text-white mx-1 mb-3 col-4 " name="devItem" data-id="${devObj.device_guid}" data-number="${devObj.device_number}" data-name="${devObj.full_name}" style="max-width: 18rem;">
 | 
					                            let master = devObj?.device_number?.split("_")[5];
 | 
				
			||||||
 | 
					                            masDiv = creDiv(["col-12"]);
 | 
				
			||||||
 | 
					                            masDiv.append(creEle("h2", master, null, null))
 | 
				
			||||||
 | 
					                            masterArr.push(master);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        
 | 
				
			||||||
 | 
					                        strHtml += `<div id="${devObj.device_number}_card" class="card dev-card text-white mb-3 col-4 " name="devItem" data-id="${devObj.device_guid}" data-number="${devObj.device_number}" data-name="${devObj.full_name}" style="max-width: 18rem;">
 | 
				
			||||||
                                        <div type="button" class="card-body">
 | 
					                                        <div type="button" class="card-body">
 | 
				
			||||||
                                            <span class="d-flex">
 | 
					                                            <span class="d-flex">
 | 
				
			||||||
                                                <h5 class="card-title">號機別 : ${devObj.full_name}</h5>
 | 
					                                                <h5 class="card-title">號機別 : ${devObj.full_name}</h5>
 | 
				
			||||||
@ -1090,10 +1142,10 @@
 | 
				
			|||||||
                                            </span>
 | 
					                                            </span>
 | 
				
			||||||
                                        </div>
 | 
					                                        </div>
 | 
				
			||||||
                                    </div>`;
 | 
					                                    </div>`;
 | 
				
			||||||
 | 
					                        masDiv.append(strHtml)
 | 
				
			||||||
                    })
 | 
					                    })
 | 
				
			||||||
 | 
					 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
                $("#eleCards").html(strHtml);
 | 
					                $("#eleCards").html(masDiv);
 | 
				
			||||||
                initPopover();
 | 
					                initPopover();
 | 
				
			||||||
                //平面圖載入
 | 
					                //平面圖載入
 | 
				
			||||||
                chartHandler(`${baseImgUrl}/upload/floor_map/${res.data[0].floor_map_name}`);
 | 
					                chartHandler(`${baseImgUrl}/upload/floor_map/${res.data[0].floor_map_name}`);
 | 
				
			||||||
@ -1103,26 +1155,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    //左側 2D 樓層 Table
 | 
					    //左側 2D 樓層 Table
 | 
				
			||||||
    function setBuildFloor() {
 | 
					    function setBuildFloor() {
 | 
				
			||||||
        let options = {
 | 
					        elevObj = new ElevatorHandler("#floorTable");
 | 
				
			||||||
            floors: [
 | 
					 | 
				
			||||||
                { name: "B2F", sort: 0 },
 | 
					 | 
				
			||||||
                { name: "B1F", sort: 1 },
 | 
					 | 
				
			||||||
                { name: "1F", sort: 2 },
 | 
					 | 
				
			||||||
                { name: "2F", sort: 3 },
 | 
					 | 
				
			||||||
                { name: "3F", sort: 4 },
 | 
					 | 
				
			||||||
                { name: "4F", sort: 5 },
 | 
					 | 
				
			||||||
                { name: "5F", sort: 6 },
 | 
					 | 
				
			||||||
                { name: "6F", sort: 7 },
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let eleObj = new ElevatorHandler("#floorTable", options);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Card 即時狀態
 | 
				
			||||||
    function drawStateTabBlo(devNum) {
 | 
					    function drawStateTabBlo(devNum) {
 | 
				
			||||||
        let div = creDiv(["row"]);
 | 
					        let div = creDiv(["row"]);
 | 
				
			||||||
        div.append(creDiv(["col-xl-6"]).append(drawImdStaBlock(devNum)))
 | 
					        div.append(creDiv(["col-xl-6"]).append(drawImdStaBlock(devNum)))
 | 
				
			||||||
@ -1130,6 +1168,7 @@
 | 
				
			|||||||
        return div.outerHtml();
 | 
					        return div.outerHtml();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Card 即時狀態 - 左側 table
 | 
				
			||||||
    function drawImdStaBlock(devNum) {
 | 
					    function drawImdStaBlock(devNum) {
 | 
				
			||||||
        let tabEle = $(`<table id="imdStaTable_${devNum}" class="table table-bordered table-striped text-center m-0">`);
 | 
					        let tabEle = $(`<table id="imdStaTable_${devNum}" class="table table-bordered table-striped text-center m-0">`);
 | 
				
			||||||
        let tbody = tabEle.append("<tbody>");
 | 
					        let tbody = tabEle.append("<tbody>");
 | 
				
			||||||
@ -1184,6 +1223,7 @@
 | 
				
			|||||||
        return tabEle.outerHtml();
 | 
					        return tabEle.outerHtml();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Card 即時狀態 - 右側 table
 | 
				
			||||||
    function drawOpeModBlock(devNum) {
 | 
					    function drawOpeModBlock(devNum) {
 | 
				
			||||||
        let tabEle = $(`<table id="opeModTable_${devNum}" class="table table-bordered table-striped text-center m-0">`);
 | 
					        let tabEle = $(`<table id="opeModTable_${devNum}" class="table table-bordered table-striped text-center m-0">`);
 | 
				
			||||||
        let tbody = tabEle.append("<tbody>");
 | 
					        let tbody = tabEle.append("<tbody>");
 | 
				
			||||||
@ -1221,6 +1261,7 @@
 | 
				
			|||||||
        return tabEle.outerHtml();
 | 
					        return tabEle.outerHtml();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 電梯管理 Modal - 資料更新
 | 
				
			||||||
    function reloadEleManTable(datas) {
 | 
					    function reloadEleManTable(datas) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let tabCols = eleManTable.context[0].aoColumns.map(x => x.data);
 | 
					        let tabCols = eleManTable.context[0].aoColumns.map(x => x.data);
 | 
				
			||||||
@ -1235,6 +1276,7 @@
 | 
				
			|||||||
        eleManTable.clear().rows.add(datas).draw();
 | 
					        eleManTable.clear().rows.add(datas).draw();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 電梯管理 Modal - table 初始化
 | 
				
			||||||
    function setEleManTable() {
 | 
					    function setEleManTable() {
 | 
				
			||||||
        let tag = "#eleManTable";
 | 
					        let tag = "#eleManTable";
 | 
				
			||||||
        let datas = [];
 | 
					        let datas = [];
 | 
				
			||||||
@ -1271,7 +1313,7 @@
 | 
				
			|||||||
            },
 | 
					            },
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                "title": "休止",
 | 
					                "title": "休止",
 | 
				
			||||||
                "data": "RCS",
 | 
					                "data": "SP_RCS",
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                "title": "獨立運轉",
 | 
					                "title": "獨立運轉",
 | 
				
			||||||
@ -1279,17 +1321,21 @@
 | 
				
			|||||||
            },
 | 
					            },
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                "title": "VIP",
 | 
					                "title": "VIP",
 | 
				
			||||||
                "data": "VIP",
 | 
					                "data": "SP_VIP",
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                "title": "回歸",
 | 
					                "title": "回歸",
 | 
				
			||||||
                "data": "RET",
 | 
					                "data": "SP_RET",
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                "title": "不服務樓層",
 | 
					                "title": "不服務樓層",
 | 
				
			||||||
                "data": null,
 | 
					                "data": null,
 | 
				
			||||||
                "render": function (data, type, row) {
 | 
					                "render": function (data, type, row) {
 | 
				
			||||||
                    return Object.keys(row).filter(x => x.startsWith("SP_FLS_") && row[x] == "trueText").map(x => x?.split("SP_FLS_")[1]).join("、");
 | 
					                    let result = "";
 | 
				
			||||||
 | 
					                    if (row._rowType == "master") {
 | 
				
			||||||
 | 
					                        result = Object.keys(row).filter(x => x.startsWith("SP_FLS_") && row[x] == "trueText").map(x => x?.split("SP_FLS_")[1]).join("、");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    return result;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@ -1310,7 +1356,6 @@
 | 
				
			|||||||
        ];
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        eleManTable = new YourTeam.JqDataTables.getTableByStatic(tag, datas, columns, column_defs, null, null, null, null, "tpi");
 | 
					        eleManTable = new YourTeam.JqDataTables.getTableByStatic(tag, datas, columns, column_defs, null, null, null, null, "tpi");
 | 
				
			||||||
        console.log(eleManTable)
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // 電梯管理 Modal - 設置 Detail 訂閱內容
 | 
					    // 電梯管理 Modal - 設置 Detail 訂閱內容
 | 
				
			||||||
@ -1329,7 +1374,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $("#eleManModal #detDevDiv [name=devName]").text(matchDevice.full_name);
 | 
					        $("#eleManModal #detDevDiv [name=devName]").text(matchDevice.full_name);
 | 
				
			||||||
        $("#eleManModal #detDevDiv [name=status]").text(subData["ST"]);
 | 
					        $("#eleManModal #detDevDiv [name=status]").text(subData["ST"]);
 | 
				
			||||||
        $("#eleManModal #detDevDiv [name=curFloor]").text(subData["CP"] + "F");
 | 
					        $("#eleManModal #detDevDiv [name=curFloor]").text(subData["CP"]);
 | 
				
			||||||
        $("#eleManModal #detDevDiv [name=preMea]").prop("checked", bajaValToBool(subData["SP_DP"]));  //防疫對策
 | 
					        $("#eleManModal #detDevDiv [name=preMea]").prop("checked", bajaValToBool(subData["SP_DP"]));  //防疫對策
 | 
				
			||||||
        $("#eleManModal #detDevDiv [name=stop]").prop("checked", bajaValToBool(subData["SP_RCS"]));
 | 
					        $("#eleManModal #detDevDiv [name=stop]").prop("checked", bajaValToBool(subData["SP_RCS"]));
 | 
				
			||||||
        $("#eleManModal #detDevDiv [name=onlyOpe]").prop("checked", bajaValToBool(subData["SP_IND"]));
 | 
					        $("#eleManModal #detDevDiv [name=onlyOpe]").prop("checked", bajaValToBool(subData["SP_IND"]));
 | 
				
			||||||
@ -1347,6 +1392,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $("#notSerFloTable").html(setNotSerFloTable(allSerFloors));
 | 
					        $("#notSerFloTable").html(setNotSerFloTable(allSerFloors));
 | 
				
			||||||
        let notSerFloors = Object.keys(subData).filter(x => x.startsWith("SP_FLS_") && subData[x] == "trueText").map(x => x?.split("SP_FLS_")[1]);
 | 
					        let notSerFloors = Object.keys(subData).filter(x => x.startsWith("SP_FLS_") && subData[x] == "trueText").map(x => x?.split("SP_FLS_")[1]);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        $(`[name^=notSerChk]`).prop("checked", false);
 | 
					        $(`[name^=notSerChk]`).prop("checked", false);
 | 
				
			||||||
        $.each(notSerFloors, (idx, floor) => {
 | 
					        $.each(notSerFloors, (idx, floor) => {
 | 
				
			||||||
            $(`[name=notSerChk${floor}]`).prop("checked", true);
 | 
					            $(`[name=notSerChk${floor}]`).prop("checked", true);
 | 
				
			||||||
@ -1370,7 +1416,7 @@
 | 
				
			|||||||
            datas.push({
 | 
					            datas.push({
 | 
				
			||||||
                row: idx,
 | 
					                row: idx,
 | 
				
			||||||
                col: 1,
 | 
					                col: 1,
 | 
				
			||||||
                data: `<input name="notSerChk${row.text}" type="checkbox" class="toggle" data-toggle="toggle">`,
 | 
					                data: `<input name="notSerChk${row.text}" data-point="SP_FLS_${row.id}" type="checkbox" class="toggle" data-toggle="toggle">`,
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
        $.each(rows, (index, row) => {
 | 
					        $.each(rows, (index, row) => {
 | 
				
			||||||
@ -1402,6 +1448,7 @@
 | 
				
			|||||||
    onEvent("click", "#eleManTable [id^=eleManDevEdit]", function () {
 | 
					    onEvent("click", "#eleManTable [id^=eleManDevEdit]", function () {
 | 
				
			||||||
        let devNum = $(this).prop("id").split("eleManDevEdit")[1];
 | 
					        let devNum = $(this).prop("id").split("eleManDevEdit")[1];
 | 
				
			||||||
        let scheBtn = ["preMeaSche", "stopSche", "onlyOpeSche", "vipSche", "retOpeSche"];
 | 
					        let scheBtn = ["preMeaSche", "stopSche", "onlyOpeSche", "vipSche", "retOpeSche"];
 | 
				
			||||||
 | 
					        $("#detDevDiv").data("devnum", devNum);
 | 
				
			||||||
        $("#bajaSche").html("");
 | 
					        $("#bajaSche").html("");
 | 
				
			||||||
        // 電梯管理 Modal 切換到 detail 頁面
 | 
					        // 電梯管理 Modal 切換到 detail 頁面
 | 
				
			||||||
        modalTogDiv("#eleManModal", "#tabDiv", "#detDevDiv", "next", function () {
 | 
					        modalTogDiv("#eleManModal", "#tabDiv", "#detDevDiv", "next", function () {
 | 
				
			||||||
@ -1423,16 +1470,59 @@
 | 
				
			|||||||
        let master = $(this).prop("id").split("eleManMasEdit")[1];
 | 
					        let master = $(this).prop("id").split("eleManMasEdit")[1];
 | 
				
			||||||
        let subData = subSeviceData.filter(x => x.device_number.split("_")[5] == master)[0];
 | 
					        let subData = subSeviceData.filter(x => x.device_number.split("_")[5] == master)[0];
 | 
				
			||||||
        $("#bajaMasSche").html("");
 | 
					        $("#bajaMasSche").html("");
 | 
				
			||||||
 | 
					        $("#detMasDiv").data("devnum", subData.device_number);
 | 
				
			||||||
        // 電梯管理 Modal 切換到 detail 頁面
 | 
					        // 電梯管理 Modal 切換到 detail 頁面
 | 
				
			||||||
        modalTogDiv("#eleManModal", "#tabDiv", "#detMasDiv", "next", function () {
 | 
					        modalTogDiv("#eleManModal", "#tabDiv", "#detMasDiv", "next", function () {
 | 
				
			||||||
            subDeviceSetEleManNotSerFloor(master);
 | 
					            subDeviceSetEleManNotSerFloor(master);
 | 
				
			||||||
            let devNumPath = subData.device_number?.split("_").join("/");
 | 
					            let devNumPath = subData.device_number?.split("_").join("/");
 | 
				
			||||||
            let ifHtml = `<iframe src="/ord?station:%7Cslot:${devNumPath}/Sch_FLS|view:?fullScreen=true" width="100%" height="100%" style="height:30rem"></iframe>`
 | 
					            let ifHtml = `<iframe src="/ord?station:%7Cslot:${devNumPath}/Sch_FLS|view:?fullScreen=true" width="100%" height="100%" style="height:30rem"></iframe>`
 | 
				
			||||||
            $("#bajaMasSche").html(ifHtml);
 | 
					            $("#bajaMasSche").html(ifHtml);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 電梯管理 Modal 不服務樓層 設定不服務樓層(BAJA)
 | 
				
			||||||
 | 
					    onEvent("change", "#notSerFloTable [name^=notSerChk]", function () {
 | 
				
			||||||
 | 
					        let devNum = $("#detMasDiv").data("devnum");
 | 
				
			||||||
 | 
					        let devNumPath = devNum?.split("_").join("/");
 | 
				
			||||||
 | 
					        let checked = $(this).prop("checked");
 | 
				
			||||||
 | 
					        let tarPoint = $(this).data("point");
 | 
				
			||||||
 | 
					        require(['baja!'], function (baja) {
 | 
				
			||||||
 | 
					            baja.Ord.make(`local:|foxs:|station:|slot:/${devNumPath}`).get()
 | 
				
			||||||
 | 
					                .then(function (folder) {
 | 
				
			||||||
 | 
					                    folder.getSlots().isComponent().eachValue(function (point) {
 | 
				
			||||||
 | 
					                        if (point.getDisplayName() == tarPoint) {
 | 
				
			||||||
 | 
					                            point.set1({
 | 
				
			||||||
 | 
					                                value: checked
 | 
				
			||||||
 | 
					                            })
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 電梯管理 Modal 設備 設定點位(BAJA)
 | 
				
			||||||
 | 
					    onEvent("change", "#eleManDevTable input:checkbox", function () {
 | 
				
			||||||
 | 
					        let devNum = $("#detDevDiv").data("devnum");
 | 
				
			||||||
 | 
					        let tarPoint = $(this).data("point");
 | 
				
			||||||
 | 
					        let checked = $(this).prop("checked");
 | 
				
			||||||
 | 
					        let devNumPath = devNum?.split("_").join("/");
 | 
				
			||||||
 | 
					        require(['baja!'], function (baja) {
 | 
				
			||||||
 | 
					            baja.Ord.make(`local:|foxs:|station:|slot:/${devNumPath}`).get()
 | 
				
			||||||
 | 
					                .then(function (folder) {
 | 
				
			||||||
 | 
					                    folder.getSlots().isComponent().eachValue(function (point) {
 | 
				
			||||||
 | 
					                        if (point.getDisplayName() == tarPoint) {
 | 
				
			||||||
 | 
					                            point.set1({
 | 
				
			||||||
 | 
					                                value: checked
 | 
				
			||||||
 | 
					                            })
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // 切換 modal 內 div 頁面
 | 
					    // 切換 modal 內 div 頁面
 | 
				
			||||||
    function modalTogDiv(modal, div1, div2, type = "next", callback = null) {
 | 
					    function modalTogDiv(modal, div1, div2, type = "next", callback = null) {
 | 
				
			||||||
        $(modal).find(div1).parent("div").css("overflow", "hidden");
 | 
					        $(modal).find(div1).parent("div").css("overflow", "hidden");
 | 
				
			||||||
@ -1467,7 +1557,7 @@
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //=====================================================================
 | 
					    //=====================================================================
 | 
				
			||||||
    //                             樓層平面圖
 | 
					    //                         ↓  樓層平面圖  ↓
 | 
				
			||||||
    //=====================================================================
 | 
					    //=====================================================================
 | 
				
			||||||
    function getDevice(devList) {
 | 
					    function getDevice(devList) {
 | 
				
			||||||
        let selected_floor = devList[0];
 | 
					        let selected_floor = devList[0];
 | 
				
			||||||
@ -1543,7 +1633,7 @@
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            return item;
 | 
					            return item;
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        console.log(currentData)
 | 
					        
 | 
				
			||||||
        if (currentData == null || currentData.length == 0) {
 | 
					        if (currentData == null || currentData.length == 0) {
 | 
				
			||||||
            this.currentData = [];
 | 
					            this.currentData = [];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -1570,7 +1660,6 @@
 | 
				
			|||||||
        resetData();
 | 
					        resetData();
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    function initChart() {
 | 
					    function initChart() {
 | 
				
			||||||
        let chartDom = $("#floChart")[0];
 | 
					        let chartDom = $("#floChart")[0];
 | 
				
			||||||
        floChart = echarts.init(chartDom, null, { width: 'auto' });
 | 
					        floChart = echarts.init(chartDom, null, { width: 'auto' });
 | 
				
			||||||
@ -1590,7 +1679,7 @@
 | 
				
			|||||||
                // animationDurationUpdate: 1500,
 | 
					                // animationDurationUpdate: 1500,
 | 
				
			||||||
                tooltip: {
 | 
					                tooltip: {
 | 
				
			||||||
                    formatter: function (params) {
 | 
					                    formatter: function (params) {
 | 
				
			||||||
                        console.log("23", params)
 | 
					                        
 | 
				
			||||||
                        if (params.data.device_node_guid != undefined && params.data.device_node_guid != null && params.data.device_node_guid != "") {
 | 
					                        if (params.data.device_node_guid != undefined && params.data.device_node_guid != null && params.data.device_node_guid != "") {
 | 
				
			||||||
                            return `名稱:${params.data.device_node_full_name}<br>
 | 
					                            return `名稱:${params.data.device_node_full_name}<br>
 | 
				
			||||||
                                    Guid:${params.data.device_node_guid}`
 | 
					                                    Guid:${params.data.device_node_guid}`
 | 
				
			||||||
@ -2241,4 +2330,23 @@
 | 
				
			|||||||
            });
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
</script>
 | 
					
 | 
				
			||||||
 | 
					    //=====================================================================
 | 
				
			||||||
 | 
					    //                         ↑  樓層平面圖  ↑
 | 
				
			||||||
 | 
					    //=====================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //載入3D模型
 | 
				
			||||||
 | 
					    function load3DModel() {
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        launchViewer('dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6LW1vZGVsX3Rlc3QxMTIxLyVFMyU4MCU5MFRFU1QlRTMlODAlOTEubndk');
 | 
				
			||||||
 | 
					        setElevatorSpeed(0.2)
 | 
				
			||||||
 | 
					        setElevatorFloor(3)
 | 
				
			||||||
 | 
					        movElevator()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    function show3D() {
 | 
				
			||||||
 | 
					        if (isFirstLoad3D) {
 | 
				
			||||||
 | 
					            isFirstLoad3D = false;
 | 
				
			||||||
 | 
					            load3DModel();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
				
			|||||||
@ -55,6 +55,12 @@ label[id$='-error'].error {
 | 
				
			|||||||
    animation: flashing-c 0.5s linear infinite;
 | 
					    animation: flashing-c 0.5s linear infinite;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.light-flash-c-bd {
 | 
				
			||||||
 | 
					    --flash-color-1: #ffa100;
 | 
				
			||||||
 | 
					    --flash-color-2: #26272b;
 | 
				
			||||||
 | 
					    animation: flashing-c-bd 0.5s linear infinite;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* checkbox switch */
 | 
					/* checkbox switch */
 | 
				
			||||||
input.toggle:checked::before {
 | 
					input.toggle:checked::before {
 | 
				
			||||||
   content: '';
 | 
					   content: '';
 | 
				
			||||||
@ -131,6 +137,23 @@ input.toggle:checked {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@keyframes flashing-c-bd {
 | 
				
			||||||
 | 
					    0% {
 | 
				
			||||||
 | 
					        border-color: var(--flash-color-1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    49% {
 | 
				
			||||||
 | 
					        border-color: var(--flash-color-1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    50% {
 | 
				
			||||||
 | 
					        border-color: var(--flash-color-2);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    99% {
 | 
				
			||||||
 | 
					        border-color: var(--flash-color-2);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
/* ================================================================ */
 | 
					/* ================================================================ */
 | 
				
			||||||
/*                             單一方法                             */
 | 
					/*                             單一方法                             */
 | 
				
			||||||
/* ================================================================ */
 | 
					/* ================================================================ */
 | 
				
			||||||
 | 
				
			|||||||
@ -20,6 +20,7 @@
 | 
				
			|||||||
        <button id="1F1oor" onclick="move1Floor()">1 Floor</button>
 | 
					        <button id="1F1oor" onclick="move1Floor()">1 Floor</button>
 | 
				
			||||||
        <button id="2F1oor" onclick="move2Floor()">2 Floor</button>
 | 
					        <button id="2F1oor" onclick="move2Floor()">2 Floor</button>
 | 
				
			||||||
        <button id="3F1oor" onclick="move3Floor()">3 Floor</button>
 | 
					        <button id="3F1oor" onclick="move3Floor()">3 Floor</button>
 | 
				
			||||||
 | 
					        <input id="lightBar" type="range" min="0" max="100" step="5" onchange="changeLightPower()">亮度
 | 
				
			||||||
        <!-- <input type="range">Main Axis</input> -->
 | 
					        <!-- <input type="range">Main Axis</input> -->
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -55,8 +56,11 @@
 | 
				
			|||||||
        $(document).ready(function () {
 | 
					        $(document).ready(function () {
 | 
				
			||||||
            //launchViewer('dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6dnNjb2RlX2ZvcmdlX3Rlc3QvJUUzJTgwJTkwJUU2JUIwJUI4JUU2JTk4JUE1JUU2JUEzJUE3JUUzJTgwJTkxJUUzJTgwJTkwTUVQJUUzJTgwJTkxVjMubndk');
 | 
					            //launchViewer('dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6dnNjb2RlX2ZvcmdlX3Rlc3QvJUUzJTgwJTkwJUU2JUIwJUI4JUU2JTk4JUE1JUU2JUEzJUE3JUUzJTgwJTkxJUUzJTgwJTkwTUVQJUUzJTgwJTkxVjMubndk');
 | 
				
			||||||
            //launchViewer('dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6dnNjb2RlX2ZvcmdlX3Rlc3QvJUUzJTgwJTkwTUVQJUUzJTgwJTkxLm53Yw');//[TEST].nwd
 | 
					            //launchViewer('dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6dnNjb2RlX2ZvcmdlX3Rlc3QvJUUzJTgwJTkwTUVQJUUzJTgwJTkxLm53Yw');//[TEST].nwd
 | 
				
			||||||
            launchViewer('dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6LW1vZGVsX3Rlc3QxMTIxLyVFMyU4MCU5MFRFU1QlRTMlODAlOTEubndk');
 | 
					            //launchViewer('dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6LW1vZGVsX3Rlc3QxMTIxLyVFMyU4MCU5MFRFU1QlRTMlODAlOTEubndk');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            launchViewer('dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6dGEzaHFzZmZ6cWJub3V4a3BsZGt1a3NldzRzajIxdzUtYmltc19tb2RlbHMvJUUzJTgwJTkwTUVQJUUzJTgwJTkxLm53Yw==');
 | 
				
			||||||
 | 
					            //
 | 
				
			||||||
 | 
					            //launchViewer('dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6dGEzaHFzZmZ6cWJub3V4a3BsZGt1a3NldzRzajIxdzUtYmltc19tb2RlbHMvJUUzJTgwJTkwVEVTVCVFMyU4MCU5MS5ud2Q=');
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        function move1Floor() {
 | 
					        function move1Floor() {
 | 
				
			||||||
@ -74,6 +78,13 @@
 | 
				
			|||||||
            setElevatorFloor(2);
 | 
					            setElevatorFloor(2);
 | 
				
			||||||
            requestAnimationFrame(movElevator);
 | 
					            requestAnimationFrame(movElevator);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        function changeLightPower() {
 | 
				
			||||||
 | 
					            var value = document.getElementById('lightBar').value;
 | 
				
			||||||
 | 
					            console.log("power: " + value);
 | 
				
			||||||
 | 
					            setLightPower(value);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    </script>
 | 
					    </script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -37,6 +37,7 @@ License: You must have a valid license purchased only from wrapbootstrap.com (li
 | 
				
			|||||||
    <link rel="stylesheet" media="screen, print" href="https://cdn.datatables.net/1.10.21/css/dataTables.bootstrap4.min.css">
 | 
					    <link rel="stylesheet" media="screen, print" href="https://cdn.datatables.net/1.10.21/css/dataTables.bootstrap4.min.css">
 | 
				
			||||||
    <link rel="stylesheet" href="css/site.css" />
 | 
					    <link rel="stylesheet" href="css/site.css" />
 | 
				
			||||||
    <link rel="stylesheet" href="css/yourteam/plugins/yt-tooltip/yt-tooltip.css" />
 | 
					    <link rel="stylesheet" href="css/yourteam/plugins/yt-tooltip/yt-tooltip.css" />
 | 
				
			||||||
 | 
					    <link rel="stylesheet" href="https://developer.api.autodesk.com/modelderivative/v2/viewers/7.*/style.min.css" type="text/css">
 | 
				
			||||||
</head>
 | 
					</head>
 | 
				
			||||||
<!-- BEGIN Body -->
 | 
					<!-- BEGIN Body -->
 | 
				
			||||||
<!-- Possible Classes
 | 
					<!-- Possible Classes
 | 
				
			||||||
@ -2527,11 +2528,16 @@ License: You must have a valid license purchased only from wrapbootstrap.com (li
 | 
				
			|||||||
    <!--The order of scripts is irrelevant. Please check out the plugin pages for more details about these plugins below:-->
 | 
					    <!--The order of scripts is irrelevant. Please check out the plugin pages for more details about these plugins below:-->
 | 
				
			||||||
    <script src="lib/statistics/easypiechart/easypiechart.bundle.js"></script>
 | 
					    <script src="lib/statistics/easypiechart/easypiechart.bundle.js"></script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <!--Bajascript-->
 | 
					    <!--Bajascript-->
 | 
				
			||||||
    <script src="js/bajascript/bscriptReq.js"></script>
 | 
					    <script src="js/bajascript/bscriptReq.js"></script>
 | 
				
			||||||
    <!--<script type='text/javascript' src='/module/js/com/tridium/js/ext/require/require.min.js?version=1496767636459'></script>-->
 | 
					    <!--<script type='text/javascript' src='/module/js/com/tridium/js/ext/require/require.min.js?version=1496767636459'></script>-->
 | 
				
			||||||
    <script src='js/bajascript/require.js'></script>
 | 
					    <script src='js/bajascript/require.js'></script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <script src="https://developer.api.autodesk.com/modelderivative/v2/viewers/7.*/viewer3D.js"></script>
 | 
				
			||||||
 | 
					    <script src="js/forge/forgemodel.js"></script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <script type='text/javascript'>
 | 
					    <script type='text/javascript'>
 | 
				
			||||||
        define('niagaraSystemProperties', function () {
 | 
					        define('niagaraSystemProperties', function () {
 | 
				
			||||||
@ -2543,6 +2549,8 @@ License: You must have a valid license purchased only from wrapbootstrap.com (li
 | 
				
			|||||||
    <script src="js/bajascript/require.config.js"></script>
 | 
					    <script src="js/bajascript/require.config.js"></script>
 | 
				
			||||||
    <script src="js/FileSaver.js"></script>
 | 
					    <script src="js/FileSaver.js"></script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <script>
 | 
					    <script>
 | 
				
			||||||
        /*$('#js-page-content').smartPanel();*/
 | 
					        /*$('#js-page-content').smartPanel();*/
 | 
				
			||||||
        var jwt = localStorage.getItem("JWT-Authorization");
 | 
					        var jwt = localStorage.getItem("JWT-Authorization");
 | 
				
			||||||
@ -2552,6 +2560,10 @@ License: You must have a valid license purchased only from wrapbootstrap.com (li
 | 
				
			|||||||
            location.href = "login.html";
 | 
					            location.href = "login.html";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (location.href.indexOf("ord") != -1) {
 | 
				
			||||||
 | 
					            location.href = "/file/index.html"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $(function () {
 | 
					        $(function () {
 | 
				
			||||||
            // 二次引用 jquery.js
 | 
					            // 二次引用 jquery.js
 | 
				
			||||||
            // - 在 require 內部程序需要引用 jquery,由於 require 的套件需要依賴 jquery ,就算 HTML 已經引用 jquery, require 也無法參考
 | 
					            // - 在 require 內部程序需要引用 jquery,由於 require 的套件需要依賴 jquery ,就算 HTML 已經引用 jquery, require 也無法參考
 | 
				
			||||||
 | 
				
			|||||||
@ -1,53 +1,53 @@
 | 
				
			|||||||
var viewer;
 | 
					var viewer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const devices = [
 | 
					// const devices = [
 | 
				
			||||||
    {
 | 
					//     {
 | 
				
			||||||
        id: "Sensor 1",
 | 
					//         id: "Sensor 1",
 | 
				
			||||||
        position: {
 | 
					//         position: {
 | 
				
			||||||
            x: -22.779729106182415,
 | 
					//             x: -22.779729106182415,
 | 
				
			||||||
            y: 5.431043023608719,
 | 
					//             y: 5.431043023608719,
 | 
				
			||||||
            z: 4.553068469137088,
 | 
					//             z: 4.553068469137088,
 | 
				
			||||||
        },
 | 
					//         },
 | 
				
			||||||
        type: "combo",
 | 
					//         type: "combo",
 | 
				
			||||||
        sensorTypes: ["temperature", "co2"],
 | 
					//         sensorTypes: ["temperature", "co2"],
 | 
				
			||||||
        dbId: 1,
 | 
					//         dbId: 1,
 | 
				
			||||||
    },
 | 
					//     },
 | 
				
			||||||
    {
 | 
					//     {
 | 
				
			||||||
        id: "Sensor 2",
 | 
					//         id: "Sensor 2",
 | 
				
			||||||
        position: {
 | 
					//         position: {
 | 
				
			||||||
            x: 0.20752051811882666,
 | 
					//             x: 0.20752051811882666,
 | 
				
			||||||
            y: 5.431043023608719,
 | 
					//             y: 5.431043023608719,
 | 
				
			||||||
            z: 4.553068469137088,
 | 
					//             z: 4.553068469137088,
 | 
				
			||||||
        },
 | 
					//         },
 | 
				
			||||||
        type: "combo",
 | 
					//         type: "combo",
 | 
				
			||||||
        sensorTypes: ["temperature", "co2"],
 | 
					//         sensorTypes: ["temperature", "co2"],
 | 
				
			||||||
        dbId: 2,
 | 
					//         dbId: 2,
 | 
				
			||||||
    },
 | 
					//     },
 | 
				
			||||||
];
 | 
					// ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var sensorStyleDefinitions = {
 | 
					// var sensorStyleDefinitions = {
 | 
				
			||||||
    co2: {
 | 
					//     co2: {
 | 
				
			||||||
        url: "https://d2zqnmauvnpnnm.cloudfront.net/assets-1/images/co2.svg",
 | 
					//         url: "https://d2zqnmauvnpnnm.cloudfront.net/assets-1/images/co2.svg",
 | 
				
			||||||
        color: 0xffffff,
 | 
					//         color: 0xffffff,
 | 
				
			||||||
    },
 | 
					//     },
 | 
				
			||||||
    temperature: {
 | 
					//     temperature: {
 | 
				
			||||||
        url: "https://d2zqnmauvnpnnm.cloudfront.net/assets-1/images/thermometer.svg",
 | 
					//         url: "https://d2zqnmauvnpnnm.cloudfront.net/assets-1/images/thermometer.svg",
 | 
				
			||||||
        color: 0xffffff,
 | 
					//         color: 0xffffff,
 | 
				
			||||||
    },
 | 
					//     },
 | 
				
			||||||
    default: {
 | 
					//     default: {
 | 
				
			||||||
        url: "https://d2zqnmauvnpnnm.cloudfront.net/assets-1/images/circle.svg",
 | 
					//         url: "https://d2zqnmauvnpnnm.cloudfront.net/assets-1/images/circle.svg",
 | 
				
			||||||
        color: 0xffffff,
 | 
					//         color: 0xffffff,
 | 
				
			||||||
    },
 | 
					//     },
 | 
				
			||||||
};
 | 
					// };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Initialize sensor values
 | 
					// Initialize sensor values
 | 
				
			||||||
let sensorVals = [];
 | 
					//let sensorVals = [];
 | 
				
			||||||
let fragProxy;
 | 
					let fragProxy;
 | 
				
			||||||
var targetFloorZ;
 | 
					var targetFloorZ;
 | 
				
			||||||
var elevatorSpeed;
 | 
					var elevatorSpeed;
 | 
				
			||||||
for (let i = 0; i < devices.length; i++) {
 | 
					// for (let i = 0; i < devices.length; i++) {
 | 
				
			||||||
    sensorVals[i] = Math.random();
 | 
					//     sensorVals[i] = Math.random();
 | 
				
			||||||
}
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function launchViewer(urn) {
 | 
					function launchViewer(urn) {
 | 
				
			||||||
    var options = {
 | 
					    var options = {
 | 
				
			||||||
@ -57,6 +57,7 @@ function launchViewer(urn) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    Autodesk.Viewing.Initializer(options, () => {
 | 
					    Autodesk.Viewing.Initializer(options, () => {
 | 
				
			||||||
        viewer = new Autodesk.Viewing.GuiViewer3D(document.getElementById('forgeViewer'));
 | 
					        viewer = new Autodesk.Viewing.GuiViewer3D(document.getElementById('forgeViewer'));
 | 
				
			||||||
 | 
					        //viewer = new Autodesk.Viewing.Viewer3D(document.getElementById('forgeViewer'));
 | 
				
			||||||
        viewer.start();
 | 
					        viewer.start();
 | 
				
			||||||
        var documentId = 'urn:' + urn;
 | 
					        var documentId = 'urn:' + urn;
 | 
				
			||||||
        Autodesk.Viewing.Document.load(documentId, onDocumentLoadSuccess, onDocumentLoadFailure);
 | 
					        Autodesk.Viewing.Document.load(documentId, onDocumentLoadSuccess, onDocumentLoadFailure);
 | 
				
			||||||
@ -64,26 +65,26 @@ function launchViewer(urn) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //test 
 | 
					        //test 
 | 
				
			||||||
        for (let i = 0; i < urn.length; i++) {
 | 
					        // for (let i = 0; i < urn.length; i++) {
 | 
				
			||||||
            Autodesk.Viewing.Document.load(urn[i]["urn"], async (doc) => {
 | 
					        //     Autodesk.Viewing.Document.load(urn[i]["urn"], async (doc) => {
 | 
				
			||||||
                let viewables = doc.getRoot().getDefaultGeometry();
 | 
					        //         let viewables = doc.getRoot().getDefaultGeometry();
 | 
				
			||||||
                let model = await viewer.loadDocumentNode(doc, viewables, {
 | 
					        //         let model = await viewer.loadDocumentNode(doc, viewables, {
 | 
				
			||||||
                    preserveView: false,
 | 
					        //             preserveView: false,
 | 
				
			||||||
                    keepCurrentModels: true,
 | 
					        //             keepCurrentModels: true,
 | 
				
			||||||
                    placementTransform: (new THREE.Matrix4()).setPosition(urn[i]["xform"]),
 | 
					        //             placementTransform: (new THREE.Matrix4()).setPosition(urn[i]["xform"]),
 | 
				
			||||||
                    keepCurrentModels: true,
 | 
					        //             keepCurrentModels: true,
 | 
				
			||||||
                    globalOffset: {
 | 
					        //             globalOffset: {
 | 
				
			||||||
                        x: 0,
 | 
					        //                 x: 0,
 | 
				
			||||||
                        y: 0,
 | 
					        //                 y: 0,
 | 
				
			||||||
                        z: 0
 | 
					        //                 z: 0
 | 
				
			||||||
                    }
 | 
					        //             }
 | 
				
			||||||
                });
 | 
					        //         });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                await viewer.waitForLoadDone(); //!<<< Wait for loading materials, properties and geometries for this model (URN)
 | 
					        //         await viewer.waitForLoadDone(); //!<<< Wait for loading materials, properties and geometries for this model (URN)
 | 
				
			||||||
            });
 | 
					        //     });
 | 
				
			||||||
        }
 | 
					        // }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        loadHeatmaps(viewer.getAllModels()[0]); //!<<< equals to viewer.model
 | 
					        //loadHeatmaps(viewer.getAllModels()[0]); //!<<< equals to viewer.model
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -122,55 +123,34 @@ function onDocumentLoadSuccess(doc) {
 | 
				
			|||||||
    viewer.loadDocumentNode(doc, viewables).then(i => {
 | 
					    viewer.loadDocumentNode(doc, viewables).then(i => {
 | 
				
			||||||
        // documented loaded, any action?
 | 
					        // documented loaded, any action?
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    viewer.addEventListener(Autodesk.Viewing.AGGREGATE_SELECTION_CHANGED_EVENT, (args) => {
 | 
					    // viewer.addEventListener(Autodesk.Viewing.AGGREGATE_SELECTION_CHANGED_EVENT, (args) => {
 | 
				
			||||||
        var currSelection = viewer.getSelection();
 | 
					    //     var currSelection = viewer.getSelection();
 | 
				
			||||||
        var domElem = document.getElementById('id_printer');
 | 
					    //     var domElem = document.getElementById('id_printer');
 | 
				
			||||||
        domElem.innerText = currSelection[0];
 | 
					    //     domElem.innerText = currSelection[0];
 | 
				
			||||||
    });
 | 
					    // });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    viewer.addEventListener(Autodesk.Viewing.GEOMETRY_LOADED_EVENT, function () {
 | 
					    //viewer.addEventListener(Autodesk.Viewing.GEOMETRY_LOADED_EVENT, function () {
 | 
				
			||||||
        var instanceTree = viewer.model.getData().instanceTree;
 | 
					        // var instanceTree = viewer.model.getData().instanceTree;
 | 
				
			||||||
        var allDbIdsStr = Object.keys(instanceTree.nodeAccess.dbIdToIndex);
 | 
					        // var allDbIdsStr = Object.keys(instanceTree.nodeAccess.dbIdToIndex);
 | 
				
			||||||
        var domElem = document.getElementById('all_id');
 | 
					        // var domElem = document.getElementById('all_id');
 | 
				
			||||||
        domElem.innerText = allDbIdsStr;
 | 
					        // domElem.innerText = allDbIdsStr;
 | 
				
			||||||
        //allDbIdsStr.map(function (id) { return parseInt(id) });
 | 
					 | 
				
			||||||
        //getAllLeafComponents(viewer, function (jsonData) {
 | 
					 | 
				
			||||||
        //    console.log("data: " + jsonData);
 | 
					 | 
				
			||||||
        //});
 | 
					 | 
				
			||||||
        //var a = getAllDbIds(viewer);
 | 
					 | 
				
			||||||
        //console.log("a: " + a);//10952
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let tree = viewer.model.getData().instanceTree;
 | 
					        // let tree = viewer.model.getData().instanceTree;
 | 
				
			||||||
        let nodeId = 10952;
 | 
					        // let nodeId = 10952;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        tree.enumNodeFragments(nodeId, function (frag) {
 | 
					        // tree.enumNodeFragments(nodeId, function (frag) {
 | 
				
			||||||
            fragProxy = viewer.impl.getFragmentProxy(viewer.model, frag);
 | 
					        //     fragProxy = viewer.impl.getFragmentProxy(viewer.model, frag);
 | 
				
			||||||
            fragProxy.getAnimTransform();
 | 
					        //     fragProxy.getAnimTransform();
 | 
				
			||||||
            //fragProxy.quaternion = new THREE.Quaternion().setFromAxisAngle(
 | 
					        //     let fragPosition = new THREE.Vector3(0, 0, 0);// 一樓0 二樓15 三樓 26
 | 
				
			||||||
            //    new THREE.Vector3(0, 0.3, 0),
 | 
					 | 
				
			||||||
            //    -Math.PI / 2);
 | 
					 | 
				
			||||||
            //fragProxy.quaternion = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0));
 | 
					 | 
				
			||||||
            //fragProxy.quaternion = new THREE.Quaternion().setPosition(new THREE.Vector3(10, 5, 0), 5);
 | 
					 | 
				
			||||||
            //fragProxy.updateAnimTransform();
 | 
					 | 
				
			||||||
            //do some work with fragment proxy
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //     fragProxy.position = fragPosition
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            //var fragPosition = new THREE.Vector3(
 | 
					        //     fragProxy.updateAnimTransform()
 | 
				
			||||||
            //    10 - fragProxy.offset.x,
 | 
					 | 
				
			||||||
            //    10 - fragProxy.offset.y,
 | 
					 | 
				
			||||||
            //    10 - fragProxy.offset.z)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // });
 | 
				
			||||||
 | 
					        // viewer.impl.sceneUpdated(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let fragPosition = new THREE.Vector3(0, 0, 0);// 一樓0 二樓15 三樓 26
 | 
					    //});
 | 
				
			||||||
 | 
					 | 
				
			||||||
            fragProxy.position = fragPosition
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            fragProxy.updateAnimTransform()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        viewer.impl.sceneUpdated(true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -12,6 +12,39 @@ function addzero(num) {
 | 
				
			|||||||
 * @param {any} alarmClass
 | 
					 * @param {any} alarmClass
 | 
				
			||||||
 * @param {any} callback
 | 
					 * @param {any} callback
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					// function getAlarmByBaja(startDate_millisecond, endDate_millisecond, isRecover, isAck, alarmClass, callback) {
 | 
				
			||||||
 | 
					//     let _sourceTmp;
 | 
				
			||||||
 | 
					//     var _result = "";
 | 
				
			||||||
 | 
					//     var _ss = "";
 | 
				
			||||||
 | 
					//     var _bfName = "";
 | 
				
			||||||
 | 
					//     var _sourceName = "";
 | 
				
			||||||
 | 
					//     var _index = 0;
 | 
				
			||||||
 | 
					//     var _recoverState = isRecover ? "!= null" : "= null";
 | 
				
			||||||
 | 
					//     var _ackState = isAck ? "= 1" : "!= 1";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//     require(['baja!'], function (baja) {
 | 
				
			||||||
 | 
					//         baja.Ord.make("local:|foxs:|alarm:|bql:select timestamp, ackState, alarmClass, alarmClassDisplayName, alarmValue, alarmData, alarmData.sourceName, uuid, alarmData.msgText, alarmData.numericValue, alarmData.presentValue, alarmData.status, alarmData.toState, normalTime from openAlarms where alarmClass = '" + alarmClass + "' and timestamp.millis > " + startDate_millisecond + " and timestamp.millis < " + endDate_millisecond + " and normalTime " + _recoverState + " order by timestamp asc").get()
 | 
				
			||||||
 | 
					//             .then(function (table) {
 | 
				
			||||||
 | 
					//                 return table.cursor({
 | 
				
			||||||
 | 
					//                     each: function (record) {
 | 
				
			||||||
 | 
					//                         _sourceTmp = (record.get('alarmData').get('sourceName')).toString().split('_');
 | 
				
			||||||
 | 
					//                         _bfName = _sourceTmp[1] + "-" + _sourceTmp[4];
 | 
				
			||||||
 | 
					//                         _sourceName = _sourceTmp[7] + "-" + _sourceTmp[8];
 | 
				
			||||||
 | 
					//                         _ss += ', "' + _index + '": {"buildingFloorName_zh":"' + _bfName + '", "uuid":"' + record.get('uuid') + '", "timestamp":"' + record.get('timestamp') + '", "alarmClass":"' + record.get('alarmClass') + '", "sourceName_zh":"' + _sourceName + '", "msgText":"' + record.get('alarmData').get('msgText') + '", "ackState":"' + record.get('ackState') + '", "normalTime":"' + record.get('normalTime') + '"}';
 | 
				
			||||||
 | 
					//                         _index++;
 | 
				
			||||||
 | 
					//                     },
 | 
				
			||||||
 | 
					//                     after: function () {
 | 
				
			||||||
 | 
					//                         _result += '{' + '"count": ' + _index;
 | 
				
			||||||
 | 
					//                         _result += _ss;
 | 
				
			||||||
 | 
					//                         _result += '}';
 | 
				
			||||||
 | 
					//                         if (typeof callback === 'function') {
 | 
				
			||||||
 | 
					//                             callback(_result);
 | 
				
			||||||
 | 
					//                         }
 | 
				
			||||||
 | 
					//                     }
 | 
				
			||||||
 | 
					//                 });
 | 
				
			||||||
 | 
					//             });
 | 
				
			||||||
 | 
					//     });
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
function getAlarmByBaja(startDate_millisecond, endDate_millisecond, isRecover, isAck, alarmClass, callback) {
 | 
					function getAlarmByBaja(startDate_millisecond, endDate_millisecond, isRecover, isAck, alarmClass, callback) {
 | 
				
			||||||
    let _sourceTmp;
 | 
					    let _sourceTmp;
 | 
				
			||||||
    var _result = "";
 | 
					    var _result = "";
 | 
				
			||||||
@ -57,6 +90,35 @@ function getAlarmByBaja(startDate_millisecond, endDate_millisecond, isRecover, i
 | 
				
			|||||||
 * @param {any} devicePath
 | 
					 * @param {any} devicePath
 | 
				
			||||||
 * @param {any} callback
 | 
					 * @param {any} callback
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					// function getOneDeviceAlarmTop10ByBaja(devicePath, callback) {
 | 
				
			||||||
 | 
					//     var _result = "";
 | 
				
			||||||
 | 
					//     var _ss = "";
 | 
				
			||||||
 | 
					//     var _index = 0;
 | 
				
			||||||
 | 
					//     //{ "count":2,"data": [{ "time": "2022/11/14 15:00:00", "errId": "0001", "ackCheck": "未確認", "errReason": "燈泡故障" }, { "time": "2022/11/14 15:00:00", "errId": "0002", "ackCheck": "未確認", "errReason": "燈泡故障" }]}
 | 
				
			||||||
 | 
					//     require(['baja!'], function (baja) {
 | 
				
			||||||
 | 
					//         baja.Ord.make("local:|foxs:|alarm:|bql:select top 10 timestamp, ackState, alarmData, alarmData.sourceName, sourceState, uuid, alarmData.msgText, normalTime where alarmData.sourceName like '%" + devicePath + "%' order by timestamp desc").get()
 | 
				
			||||||
 | 
					//             .then(function (table) {
 | 
				
			||||||
 | 
					//                 return table.cursor({
 | 
				
			||||||
 | 
					//                     each: function (record) {
 | 
				
			||||||
 | 
					//                         if (_index == 0)
 | 
				
			||||||
 | 
					//                             _ss += '{"uuid":"' + record.get('uuid') + '", "msgText":"' + record.get('alarmData').get('msgText') + '", "ackState":"' + record.get('ackState') + '", "timestamp":"' + record.get('timestamp') + '"}';
 | 
				
			||||||
 | 
					//                         else
 | 
				
			||||||
 | 
					//                             _ss += ',{"uuid":"' + record.get('uuid') + '", "msgText":"' + record.get('alarmData').get('msgText') + '", "ackState":"' + record.get('ackState') + '", "timestamp":"' + record.get('timestamp') + '"}';
 | 
				
			||||||
 | 
					//                         _index++;
 | 
				
			||||||
 | 
					//                     },
 | 
				
			||||||
 | 
					//                     after: function () {
 | 
				
			||||||
 | 
					//                         _result += '{' + '"count": ' + _index +', "data":[';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//                         _result += _ss+']';
 | 
				
			||||||
 | 
					//                         _result += '}';
 | 
				
			||||||
 | 
					//                         if (typeof callback === 'function') {
 | 
				
			||||||
 | 
					//                             callback(_result);
 | 
				
			||||||
 | 
					//                         }
 | 
				
			||||||
 | 
					//                     }
 | 
				
			||||||
 | 
					//                 });
 | 
				
			||||||
 | 
					//             });
 | 
				
			||||||
 | 
					//     });
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
function getOneDeviceAlarmTop10ByBaja(devicePath, callback) {
 | 
					function getOneDeviceAlarmTop10ByBaja(devicePath, callback) {
 | 
				
			||||||
    var _result = "";
 | 
					    var _result = "";
 | 
				
			||||||
    var _ss = "";
 | 
					    var _ss = "";
 | 
				
			||||||
@ -109,6 +171,31 @@ function getOneDeviceAlarmTop10ByBaja(devicePath, callback) {
 | 
				
			|||||||
 * @param {any} systemPath
 | 
					 * @param {any} systemPath
 | 
				
			||||||
 * @param {any} callback
 | 
					 * @param {any} callback
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					// function getOneSystemAlarmStateByBaja(systemPath, callback) {
 | 
				
			||||||
 | 
					//     var _result = "";
 | 
				
			||||||
 | 
					//     var _ss = "";
 | 
				
			||||||
 | 
					//     var _index = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//     require(['baja!'], function (baja) {
 | 
				
			||||||
 | 
					//         baja.Ord.make("local:|foxs:|alarm:|bql:select alarmData, alarmData.sourceName, sourceState, uuid where alarmData.sourceName like '%" + systemPath + "%' order by timestamp desc").get()
 | 
				
			||||||
 | 
					//             .then(function (table) {
 | 
				
			||||||
 | 
					//                 return table.cursor({
 | 
				
			||||||
 | 
					//                     each: function (record) {
 | 
				
			||||||
 | 
					//                         _ss += ', "' + _index + '": {"uuid":"' + record.get('uuid') + '", "sourceName":"' + record.get('alarmData').get('sourceName') + '", "sourceState":"' + record.get('sourceState') + '"}';
 | 
				
			||||||
 | 
					//                         _index++;
 | 
				
			||||||
 | 
					//                     },
 | 
				
			||||||
 | 
					//                     after: function () {
 | 
				
			||||||
 | 
					//                         _result += '{' + '"count": ' + _index;
 | 
				
			||||||
 | 
					//                         _result += _ss;
 | 
				
			||||||
 | 
					//                         _result += '}';
 | 
				
			||||||
 | 
					//                         if (typeof callback === 'function') {
 | 
				
			||||||
 | 
					//                             callback(_result);
 | 
				
			||||||
 | 
					//                         }
 | 
				
			||||||
 | 
					//                     }
 | 
				
			||||||
 | 
					//                 });
 | 
				
			||||||
 | 
					//             });
 | 
				
			||||||
 | 
					//     });
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
function getOneSystemAlarmStateByBaja(systemPath, callback) {
 | 
					function getOneSystemAlarmStateByBaja(systemPath, callback) {
 | 
				
			||||||
    var _result = "";
 | 
					    var _result = "";
 | 
				
			||||||
    var _ss = "";
 | 
					    var _ss = "";
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,9 @@
 | 
				
			|||||||
let baja_subscribe_device_callback_func; //設定BQL訂閱之後要回傳的Function
 | 
					let baja_subscribe_device_callback_func; //設定BQL訂閱之後要回傳的Function
 | 
				
			||||||
 | 
					let baja_my_user_account_func;    //取得帳號資料要回傳的Function
 | 
				
			||||||
var ordPath; //當前點選選單的tag,用來抓出設備路徑,例如:旅館棟->H,消防偵煙器->F3
 | 
					var ordPath; //當前點選選單的tag,用來抓出設備路徑,例如:旅館棟->H,消防偵煙器->F3
 | 
				
			||||||
window.tolSubList = [];
 | 
					window.tolSubList = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var user_name = "";
 | 
				
			||||||
function subscriptionDevices() {
 | 
					function subscriptionDevices() {
 | 
				
			||||||
    // 用BQL的方式去訂閱
 | 
					    // 用BQL的方式去訂閱
 | 
				
			||||||
    this.setSubscribeDevicesByBql = function (tempOrdPath) {
 | 
					    this.setSubscribeDevicesByBql = function (tempOrdPath) {
 | 
				
			||||||
@ -13,6 +16,16 @@ function subscriptionDevices() {
 | 
				
			|||||||
            baja_subscribe_device_callback_func = callBackFunc;
 | 
					            baja_subscribe_device_callback_func = callBackFunc;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					   
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function MyBaja() {
 | 
				
			||||||
 | 
					    // 取得使用者帳號
 | 
				
			||||||
 | 
					    this.setMyUserAccount = function (callBackFunc) {
 | 
				
			||||||
 | 
					        if (callBackFunc != undefined && callBackFunc != null) {
 | 
				
			||||||
 | 
					            baja_my_user_account_func = callBackFunc;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -270,7 +283,12 @@ function getElevatorInfoByBaja(path, callback) {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					require(['baja!'], function (baja) {
 | 
				
			||||||
 | 
					    user_name = baja.getUserName();
 | 
				
			||||||
 | 
					    if (baja_my_user_account_func != undefined && baja_my_user_account_func != null) {
 | 
				
			||||||
 | 
					        baja_my_user_account_func(user_name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// baja.Ord.make('ip:greencloud.fic.com.tw|foxs:|station:|slot:/Arena/H/F3|bql:select name, displayname, slotPath, out.value, out from control:ControlPoint')
 | 
					// baja.Ord.make('ip:greencloud.fic.com.tw|foxs:|station:|slot:/Arena/H/F3|bql:select name, displayname, slotPath, out.value, out from control:ControlPoint')
 | 
				
			||||||
// // baja.Ord.make('ip:greencloud.fic.com.tw|foxs:|station:|slot:/Arena/H/E1/B1F/TestData/H_E1_B1F_TestData_Data|bql:select slotPath,out.value from control:NumericWritable')
 | 
					// // baja.Ord.make('ip:greencloud.fic.com.tw|foxs:|station:|slot:/Arena/H/E1/B1F/TestData/H_E1_B1F_TestData_Data|bql:select slotPath,out.value from control:NumericWritable')
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										37
									
								
								Frontend/js/n4js/electricmeterbaja.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								Frontend/js/n4js/electricmeterbaja.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 取得電表總計資料 by baja
 | 
				
			||||||
 | 
					 * @param {any} devicePath 
 | 
				
			||||||
 | 
					 * @param {any} timeType
 | 
				
			||||||
 | 
					 * @param {any} callback
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					function getElectricMeterTotalByBaja(devicePath, timeType, callback) {
 | 
				
			||||||
 | 
					    var _result = "";
 | 
				
			||||||
 | 
					    var _ss = "";
 | 
				
			||||||
 | 
					    var _index = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    require(['baja!'], function (baja) {
 | 
				
			||||||
 | 
					        console.log('transform:slot:/' + devicePath + '/History/' + timeType);
 | 
				
			||||||
 | 
					        baja.Ord.make('transform:slot:/' + devicePath + '/History/' + timeType).get()
 | 
				
			||||||
 | 
					            .then(function (table) {
 | 
				
			||||||
 | 
					                return table.cursor({
 | 
				
			||||||
 | 
					                    each: function (record) {
 | 
				
			||||||
 | 
					                        if (_index == 0)
 | 
				
			||||||
 | 
					                            _ss += '{"timestamp":"' + record.get('timestamp') + '", "MP1":' + record.get('MP1') + '"}';
 | 
				
			||||||
 | 
					                        else
 | 
				
			||||||
 | 
					                            _ss += ',{"timestamp":"' + record.get('timestamp') + '", "MP1":' + record.get('MP1') + '"}';
 | 
				
			||||||
 | 
					                        _index++;
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    after: function () {
 | 
				
			||||||
 | 
					                        _result += '{' + '"count": ' + _index + ', "data":[';
 | 
				
			||||||
 | 
					                        _result += _ss;
 | 
				
			||||||
 | 
					                        _result += ']}';
 | 
				
			||||||
 | 
					                        if (typeof callback === 'function') {
 | 
				
			||||||
 | 
					                            callback(_result);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    limit: -1,
 | 
				
			||||||
 | 
					                    offset: 0
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -8,6 +8,32 @@
 | 
				
			|||||||
 * @param {any} company
 | 
					 * @param {any} company
 | 
				
			||||||
 * @param {any} callback
 | 
					 * @param {any} callback
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					// function getHistoryDataByBaja(devicePath, startDate_millisecond, endDate_millisecond, deviceName, company, callback) {
 | 
				
			||||||
 | 
					//     var _result = "";
 | 
				
			||||||
 | 
					//     var _ss = "";
 | 
				
			||||||
 | 
					//     var _index = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//     require(['baja!'], function (baja) {
 | 
				
			||||||
 | 
					//         baja.Ord.make('local:|foxs:|history:/' + company + '/' + devicePath + '|bql:select * from control:ControlPoint where timestamp.millis > ' + startDate_millisecond + ' and timestamp.millis < ' + endDate_millisecond).get()
 | 
				
			||||||
 | 
					//             .then(function (table) {
 | 
				
			||||||
 | 
					//                 return table.cursor({
 | 
				
			||||||
 | 
					//                     each: function (record) {
 | 
				
			||||||
 | 
					//                         _ss += ', "' + _index + '": {"deviceName":"' + deviceName + '", "value":' + record.get('value') + ', "timestamp":"' + record.get('timestamp') + '"}';
 | 
				
			||||||
 | 
					//                         _index++;
 | 
				
			||||||
 | 
					//                     },
 | 
				
			||||||
 | 
					//                     after: function () {
 | 
				
			||||||
 | 
					//                         _result += '{' + '"count": ' + _index;
 | 
				
			||||||
 | 
					//                         _result += _ss;
 | 
				
			||||||
 | 
					//                         _result += '}';
 | 
				
			||||||
 | 
					//                         if (typeof callback === 'function') {
 | 
				
			||||||
 | 
					//                             callback(_result);
 | 
				
			||||||
 | 
					//                         }
 | 
				
			||||||
 | 
					//                     }
 | 
				
			||||||
 | 
					//                 });
 | 
				
			||||||
 | 
					//             });
 | 
				
			||||||
 | 
					//     });
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getHistoryDataByBaja(devicePath, startDate_millisecond, endDate_millisecond, deviceName, company, callback) {
 | 
					function getHistoryDataByBaja(devicePath, startDate_millisecond, endDate_millisecond, deviceName, company, callback) {
 | 
				
			||||||
    var _result = "";
 | 
					    var _result = "";
 | 
				
			||||||
    var _ss = "";
 | 
					    var _ss = "";
 | 
				
			||||||
 | 
				
			|||||||
@ -113,18 +113,25 @@ class ElevatorHandler {
 | 
				
			|||||||
        this.ele = ele;
 | 
					        this.ele = ele;
 | 
				
			||||||
        this.eleId = "";
 | 
					        this.eleId = "";
 | 
				
			||||||
        this.eleWra = $("<div></div>");
 | 
					        this.eleWra = $("<div></div>");
 | 
				
			||||||
        this.speed = 0;
 | 
					        this.speed = 0.3;
 | 
				
			||||||
        this.monStatus = 0;  // 0=no 1=up 2=down
 | 
					        this.movStatus = {};  // {id:elevator01,value:0} 0=no 1=up 2=down
 | 
				
			||||||
        this.floorHeight = typeof option.fHeight == "undefined" ? 50 : option.fHeight;
 | 
					        this.floorHeight = typeof option.fHeight == "undefined" ? 50 : option.fHeight;
 | 
				
			||||||
        this.floorWidth = typeof option.fWidth == "undefined" ? 45 : option.fWidth;
 | 
					        this.floorWidth = typeof option.fWidth == "undefined" ? 45 : option.fWidth;
 | 
				
			||||||
        this.floors = typeof option.floors == "undefined" ? [{}] : option.floors;
 | 
					        this.floors = typeof option.floors == "undefined" ? [{}] : option.floors;
 | 
				
			||||||
        this.eleCnt = typeof option.eleCnt == "undefined" ? 3 : option.eleCnt;
 | 
					        this.elevators = typeof option.elevators == "undefined" ? [{}] : option.elevators;  // {id:elevator01}
 | 
				
			||||||
 | 
					        this.curElevFloor = typeof option.curElevFloor == "undefined" ? {} : option.curElevFloor;
 | 
				
			||||||
 | 
					        this.setTimeout = null;
 | 
				
			||||||
        this.init();
 | 
					        this.init();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    init = function () {
 | 
					    init = function () {
 | 
				
			||||||
        this.setTabWra();
 | 
					        this.setTabWra();
 | 
				
			||||||
        this.setTabFloor();
 | 
					        this.setTabFloor();
 | 
				
			||||||
 | 
					        if (Object.keys(this.curElevFloor).length != 0) { 
 | 
				
			||||||
 | 
					            $.each(Object.keys(this.curElevFloor), (idx, elevKey) => {
 | 
				
			||||||
 | 
					                this.setElevFloor(elevKey,this.curElevFloor[elevKey]);
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // 設置 wrapper
 | 
					    // 設置 wrapper
 | 
				
			||||||
@ -143,19 +150,27 @@ class ElevatorHandler {
 | 
				
			|||||||
    setTabFloor = function () {
 | 
					    setTabFloor = function () {
 | 
				
			||||||
        let _w = this.floorWidth, _h = this.floorHeight;
 | 
					        let _w = this.floorWidth, _h = this.floorHeight;
 | 
				
			||||||
        let thead = creEle("thead"), tbody = creEle("tbody");
 | 
					        let thead = creEle("thead"), tbody = creEle("tbody");
 | 
				
			||||||
        let _floors = this.floors, _ele = this.ele, _eleCnt = this.eleCnt;
 | 
					        let _floors = this.floors, _ele = this.ele, _elevators = this.elevators;
 | 
				
			||||||
        //樓層從小到大
 | 
					        //樓層從小到大
 | 
				
			||||||
        _floors = _floors.oSort("sort").reverse().map(x => x.name);
 | 
					        _floors = _floors.oSort("sort").reverse().map(x => x.name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let theadTr = creEle("tr");
 | 
					        let theadTr = creEle("tr");
 | 
				
			||||||
        for (let e = 1; e <= _eleCnt + 2; e++) {
 | 
					     
 | 
				
			||||||
 | 
					        for (let e = 1; e <= _elevators.length + 2; e++) {
 | 
				
			||||||
            let th = creEle("th");
 | 
					            let th = creEle("th");
 | 
				
			||||||
            th.css({ "width": `${_w}px`, "height": `${_h}px` });
 | 
					            th.css({ "width": `${_w}px`, "height": `${_h}px` });
 | 
				
			||||||
            if (e != 1 && e != _eleCnt + 2) {
 | 
					            if (e != 1 && e != _elevators.length + 2) {
 | 
				
			||||||
 | 
					                let elevId = _elevators[e - 2]?.id;
 | 
				
			||||||
                // 電梯方框
 | 
					                // 電梯方框
 | 
				
			||||||
                let span = creEle("span", null, "elevator-item-" + (e - 1), null, ["elevator-item"]);
 | 
					                let span = creEle("span", null, "elevator-item-" + (elevId), null, ["elevator-item"]);
 | 
				
			||||||
                span.css({ "width": `${_w - 3}px`, "height": `${_h - 3}px`, "top": `1.5px`})
 | 
					                let spanUp = creEle("span", null, null, null, ["elevator-item-toup"]);
 | 
				
			||||||
 | 
					                let spanDown = creEle("span", null, null, null, ["elevator-item-todown"]);
 | 
				
			||||||
 | 
					                span.css({ "width": `${_w - 3}px`, "height": `${_h - 3}px`, "top": `1.5px`, "transition":`transform ${1 / this.speed}s cubic-bezier(0.43, 0.05, 0.62, 1) 0s`})
 | 
				
			||||||
 | 
					                spanUp.css({ "width": `${_w - 3}px`, "height": `${(_h - 3) / 2}px`, "top": `1.5px`, "transition":`transform ${1 / this.speed}s cubic-bezier(0.43, 0.05, 0.62, 1) 0s`})
 | 
				
			||||||
 | 
					                spanDown.css({ "width": `${_w - 3}px`, "height": `${(_h - 3) / 2}px`, "top": `1.5px`, "transition":`transform ${1 / this.speed}s cubic-bezier(0.43, 0.05, 0.62, 1) 0s`,"top":`${1.5 + (_h-3) / 2}px`})
 | 
				
			||||||
 | 
					                th.append(spanUp);
 | 
				
			||||||
                th.append(span);
 | 
					                th.append(span);
 | 
				
			||||||
 | 
					                th.append(spanDown);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            theadTr.append(th);
 | 
					            theadTr.append(th);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -165,13 +180,14 @@ class ElevatorHandler {
 | 
				
			|||||||
        //樓層表格建置 tbody
 | 
					        //樓層表格建置 tbody
 | 
				
			||||||
        for (let f = 1; f <= _floors.length; f++) {
 | 
					        for (let f = 1; f <= _floors.length; f++) {
 | 
				
			||||||
            let tr = creEle("tr");
 | 
					            let tr = creEle("tr");
 | 
				
			||||||
            for (let e = 1; e <= _eleCnt + 2; e++) {
 | 
					            
 | 
				
			||||||
 | 
					            for (let e = 1; e <= _elevators.length + 2; e++) {
 | 
				
			||||||
                let td = creEle("td");
 | 
					                let td = creEle("td");
 | 
				
			||||||
                td.css({ "width": `${_w}px`, "height": `${_h}px` });
 | 
					                td.css({ "width": `${_w}px`, "height": `${_h}px` });
 | 
				
			||||||
                if (e == 1) {
 | 
					                if (e == 1) {
 | 
				
			||||||
                    td.addClass("t-black")
 | 
					                    td.addClass("t-black")
 | 
				
			||||||
                    td.text(_floors[f - 1]);
 | 
					                    td.text(_floors[f - 1]);
 | 
				
			||||||
                } else if (e == _eleCnt + 2) {
 | 
					                } else if (e == _elevators.length + 2) {
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else {
 | 
					                else {
 | 
				
			||||||
                    let div = creDiv(["d-flex", "justify-content-center", "align-items-end", "h-100"]);
 | 
					                    let div = creDiv(["d-flex", "justify-content-center", "align-items-end", "h-100"]);
 | 
				
			||||||
@ -205,5 +221,64 @@ class ElevatorHandler {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    setElevFloor = function (elevId, floId) {
 | 
				
			||||||
 | 
					        let curFloId = this.curElevFloor[elevId];
 | 
				
			||||||
 | 
					        let curSort = this.floors.filter(x => x.id == curFloId).map(x => x.sort)[0];
 | 
				
			||||||
 | 
					        let tarSort = this.floors.filter(x => x.id == floId).map(x => x.sort)[0];
 | 
				
			||||||
 | 
					        let gapFloor = tarSort - curSort;
 | 
				
			||||||
 | 
					        let cssEle = [$(`#elevator-item-${elevId}`)[0], $(`#elevator-item-${elevId}`).prev("span.elevator-item-toup")[0], $(`#elevator-item-${elevId}`).next("span.elevator-item-todown")[0]]
 | 
				
			||||||
 | 
					        clearTimeout(this.setTimeout); 
 | 
				
			||||||
 | 
					        console.log("123",this.movStatus)
 | 
				
			||||||
 | 
					        if (this.movStatus[elevId] != 0) { 
 | 
				
			||||||
 | 
					            $(cssEle).css("transition", `transform ${1 / this.speed * Math.abs(gapFloor)}s cubic-bezier(0, 0, 0.62, 1) 0s`);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        //if (gapFloor < 0) {
 | 
				
			||||||
 | 
					        //    this.movStatus[elevId] = 2;
 | 
				
			||||||
 | 
					        //} else if (gapFloor > 0) {
 | 
				
			||||||
 | 
					        //    this.movStatus[elevId] = 1;
 | 
				
			||||||
 | 
					        //} else {
 | 
				
			||||||
 | 
					        //    this.movStatus[elevId] = 0;
 | 
				
			||||||
 | 
					        //}
 | 
				
			||||||
 | 
					        this.setTimeout = setTimeout(() => {
 | 
				
			||||||
 | 
					            /*this.movStatus[elevId] = 0;*/
 | 
				
			||||||
 | 
					            $(cssEle).css("transition", `transform ${1 / this.speed * Math.abs(gapFloor)}s cubic-bezier(0.43, 0.05, 0.62, 1) 0s`);
 | 
				
			||||||
 | 
					            this.setEleUpDownStyle(elevId);
 | 
				
			||||||
 | 
					        }, (1 / this.speed * Math.abs(gapFloor)) * 1000)
 | 
				
			||||||
 | 
					        this.setEleUpDownStyle(elevId);
 | 
				
			||||||
 | 
					        this.curElevFloor[elevId] = floId;
 | 
				
			||||||
 | 
					        $(cssEle).css("transition", `transform ${1 / this.speed * Math.abs(gapFloor)}s cubic-bezier(0.43, 0.05, 0.62, 1) 0s`)
 | 
				
			||||||
 | 
					        $(cssEle).css("transform", `translateY(${this.floorHeight * (this.floors.length - tarSort)}px)`);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    setEleMovStatus = function (elevId,status) {
 | 
				
			||||||
 | 
					        this.movStatus[elevId] = status;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    setEleUpDownStyle = function (elevId) {
 | 
				
			||||||
 | 
					        if (this.movStatus[elevId] == 1) {
 | 
				
			||||||
 | 
					            $(`#elevator-item-${elevId}`).prev("span.elevator-item-toup").addClass("light-flash-c-bd")
 | 
				
			||||||
 | 
					                .css("--flash-color-1", "#44ea8e").css("--flash-color-2", "rgba(255,255,255,0)");
 | 
				
			||||||
 | 
					        } else if (this.movStatus[elevId] == 2) {
 | 
				
			||||||
 | 
					            $(`#elevator-item-${elevId}`).next("span.elevator-item-todown").addClass("light-flash-c-bd")
 | 
				
			||||||
 | 
					                .css("--flash-color-1", "#44ea8e").css("--flash-color-2", "rgba(255,255,255,0)");
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            $(`#elevator-item-${elevId}`).prev("span.elevator-item-toup").removeClass("light-flash-c-bd");
 | 
				
			||||||
 | 
					            $(`#elevator-item-${elevId}`).next("span.elevator-item-todown").removeClass("light-flash-c-bd");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    setCurElevFloor = function (elevId,floId) {
 | 
				
			||||||
 | 
					        this.curElevFloor[elevId] = floId;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    redraw = function () {
 | 
				
			||||||
 | 
					        $(this.ele).empty();
 | 
				
			||||||
 | 
					        this.setTabFloor();
 | 
				
			||||||
 | 
					        if (Object.keys(this.curElevFloor).length != 0) {
 | 
				
			||||||
 | 
					            $.each(Object.keys(this.curElevFloor), (idx, elevKey) => {
 | 
				
			||||||
 | 
					                this.setElevFloor(elevKey, this.curElevFloor[elevKey]);
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -19,12 +19,13 @@ $(function () {
 | 
				
			|||||||
 * 初始全頁面 yt tab
 | 
					 * 初始全頁面 yt tab
 | 
				
			||||||
 * */
 | 
					 * */
 | 
				
			||||||
function initTabsByEle() {
 | 
					function initTabsByEle() {
 | 
				
			||||||
 | 
					    _ytTabInited = [];
 | 
				
			||||||
    $("[data-tabname][data-target]:not([data-tabrole=child])").each(function (index, value) {
 | 
					    $("[data-tabname][data-target]:not([data-tabrole=child])").each(function (index, value) {
 | 
				
			||||||
        let tabName = $(value).data("tabname");
 | 
					        let tabName = $(value).data("tabname");
 | 
				
			||||||
        if (_ytTabInited.indexOf(tabName) == -1) {
 | 
					        
 | 
				
			||||||
            var ytTab = new YT.Tab({ tabName: tabName })
 | 
					        var ytTab = new YT.Tab({ tabName: tabName })
 | 
				
			||||||
            _ytTabInited.push(tabName);
 | 
					        _ytTabInited.push(tabName);
 | 
				
			||||||
        }
 | 
					        
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -58,7 +58,7 @@ function fnInitJqDataTablesNoData(tag, dataSet = null, columns = null, columnDef
 | 
				
			|||||||
        "columns": columns,
 | 
					        "columns": columns,
 | 
				
			||||||
        "aoColumnDefs": columnDefs,
 | 
					        "aoColumnDefs": columnDefs,
 | 
				
			||||||
        "stateSave": true,
 | 
					        "stateSave": true,
 | 
				
			||||||
        "pagingType": "simple",
 | 
					        "pagingType": "full_numbers",
 | 
				
			||||||
        "destroy": false,
 | 
					        "destroy": false,
 | 
				
			||||||
        "initComplete": initComplete,
 | 
					        "initComplete": initComplete,
 | 
				
			||||||
        "drawCallback": fnDrawCallBack,
 | 
					        "drawCallback": fnDrawCallBack,
 | 
				
			||||||
 | 
				
			|||||||
@ -56,7 +56,7 @@
 | 
				
			|||||||
                        <label class="custom-control-label" for="rememberme"> 記住我</label>
 | 
					                        <label class="custom-control-label" for="rememberme"> 記住我</label>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
                <button type="submit" class="btn btn-default float-right" onclick="Login(event)">登入</button>
 | 
					                <button type="submit" class="btn btn-default float-right" onclick="Login(null,event)">登入</button>
 | 
				
			||||||
            </form>
 | 
					            </form>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div class="blankpage-footer text-center">
 | 
					        <div class="blankpage-footer text-center">
 | 
				
			||||||
@ -69,131 +69,190 @@
 | 
				
			|||||||
        <source src="media/video/cc.mp4" type="video/mp4">
 | 
					        <source src="media/video/cc.mp4" type="video/mp4">
 | 
				
			||||||
    </video>
 | 
					    </video>
 | 
				
			||||||
    <!--Base JS-->
 | 
					    <!--Base JS-->
 | 
				
			||||||
    <script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js'></script>
 | 
					    <!--<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js'></script>-->
 | 
				
			||||||
    <script src="lib/vendors.bundle.js"></script>
 | 
					    <script src="lib/vendors.bundle.js"></script>
 | 
				
			||||||
    <script src="lib/app.bundle.js"></script>
 | 
					 | 
				
			||||||
    <!-- JQuery Validate -->
 | 
					    <!-- JQuery Validate -->
 | 
				
			||||||
    <script src="lib/jquery-validation/dist/jquery.validate.js"></script>
 | 
					    <!--<script src="lib/jquery-validation/dist/jquery.validate.js"></script>
 | 
				
			||||||
    <script src="lib/jquery-validation/dist/additional-methods.min.js"></script>
 | 
					    <script src="lib/jquery-validation/dist/additional-methods.min.js"></script>
 | 
				
			||||||
    <script src="lib/jquery-validation/dist/localization/messages_zh_TW.js"></script>
 | 
					    <script src="lib/jquery-validation/dist/localization/messages_zh_TW.js"></script>
 | 
				
			||||||
    <script src="lib/notifications/sweetalert2/sweetalert2.bundle.js"></script>
 | 
					    <script src="lib/notifications/sweetalert2/sweetalert2.bundle.js"></script>-->
 | 
				
			||||||
    <script src="lib/notifications/toastr/toastr.min.js"></script>
 | 
					    <script src="lib/notifications/toastr/toastr.min.js"></script>
 | 
				
			||||||
    <script src="js/toast.js"></script>
 | 
					    <script src="js/toast.js"></script>
 | 
				
			||||||
    <script src="js/init.js"></script>
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <!--Bajascript-->
 | 
				
			||||||
 | 
					    <script src="js/bajascript/bscriptReq.js"></script>
 | 
				
			||||||
 | 
					    <!--<script type='text/javascript' src='/module/js/com/tridium/js/ext/require/require.min.js?version=1496767636459'></script>-->
 | 
				
			||||||
 | 
					    <script src='js/bajascript/require.js'></script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <script src="js/n4js/bajatest.js"></script>
 | 
				
			||||||
 | 
					    <script src="js/bajascript/require.config.js"></script>
 | 
				
			||||||
</body>
 | 
					</body>
 | 
				
			||||||
</html>
 | 
					</html>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
    var remember = false;
 | 
					    var remember = false;
 | 
				
			||||||
 | 
					    var myBaja = null;
 | 
				
			||||||
    $(function () {
 | 
					    $(function () {
 | 
				
			||||||
        if (localStorage.getItem('taipei-t') == 'true') {
 | 
					        require(["jquery"], loadedBasePack);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * jquery.js 二次引用後 Callback,載入第三方套件
 | 
				
			||||||
 | 
					    * */
 | 
				
			||||||
 | 
					    function loadedBasePack() {
 | 
				
			||||||
 | 
					        require(
 | 
				
			||||||
 | 
					            [
 | 
				
			||||||
 | 
					                "lib/app.bundle",
 | 
				
			||||||
 | 
					                "lib/app.menu",
 | 
				
			||||||
 | 
					                "lib/jquery-validation/dist/jquery.validate",
 | 
				
			||||||
 | 
					                "lib/jquery-validation/dist/additional-methods.min",
 | 
				
			||||||
 | 
					                "lib/jquery-validation/dist/localization/messages_zh_TW",
 | 
				
			||||||
 | 
					                /*"lib/notifications/sweetalert2/sweetalert2.bundle",*/
 | 
				
			||||||
 | 
					            ], loadedMasterPack);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * 第三方套件引用後 Callback,載入額外套件
 | 
				
			||||||
 | 
					    * */
 | 
				
			||||||
 | 
					    function loadedMasterPack() {
 | 
				
			||||||
 | 
					        require(
 | 
				
			||||||
 | 
					            [
 | 
				
			||||||
 | 
					                "init",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ], loadedJsPack);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function loadedJsPack() {
 | 
				
			||||||
 | 
					        if (location.href.indexOf("localhost:5966") == -1) {
 | 
				
			||||||
 | 
					            myBaja = new MyBaja();
 | 
				
			||||||
 | 
					            myBaja.setMyUserAccount(Login)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (localStorage.getItem('mitsubishi-t') == 'true') {
 | 
				
			||||||
            document.getElementById("rememberme").checked = true;
 | 
					            document.getElementById("rememberme").checked = true;
 | 
				
			||||||
            remember = true;
 | 
					            remember = true;
 | 
				
			||||||
            $("#account").val(atob(localStorage.getItem('taipei-a')));
 | 
					            $("#account").val(atob(localStorage.getItem('mitsubishi-a')));
 | 
				
			||||||
            $("#password").val(atob(localStorage.getItem('taipei-p')));
 | 
					            $("#password").val(atob(localStorage.getItem('mitsubishi-p')));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else {
 | 
					        else {
 | 
				
			||||||
            document.getElementById("rememberme").checked = false;
 | 
					            document.getElementById("rememberme").checked = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $("#rememberme").click(function () {
 | 
					        var loginValidate = $("#login-form").validate({
 | 
				
			||||||
        if (remember) {
 | 
					            rules: {
 | 
				
			||||||
            localStorage.setItem('taipei-t', 'false');
 | 
					                account: {
 | 
				
			||||||
            localStorage.removeItem('taipei-a');
 | 
					                    required: true,
 | 
				
			||||||
            localStorage.removeItem('taipei-p');
 | 
					                    maxlength: 50,
 | 
				
			||||||
            remember = false;
 | 
					                    filterspace: true
 | 
				
			||||||
        } else {
 | 
					                },
 | 
				
			||||||
            localStorage.setItem('taipei-t', 'true');
 | 
					                password: {
 | 
				
			||||||
            localStorage.setItem('taipei-a', btoa($("#account").val()));
 | 
					                    required: true,
 | 
				
			||||||
            localStorage.setItem('taipei-p', btoa($("#password").val()));
 | 
					                    maxlength: 50,
 | 
				
			||||||
            remember = true;
 | 
					                    filterspace: true
 | 
				
			||||||
        }
 | 
					                }
 | 
				
			||||||
    });
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $("#account").change(function () {
 | 
					        //驗證是否為空白
 | 
				
			||||||
        if (remember) {
 | 
					        jQuery.validator.addMethod("filterspace", function (value, element) {
 | 
				
			||||||
            localStorage.setItem('taipei-a', btoa($("#account").val()));
 | 
					            var str = value;
 | 
				
			||||||
        } else {
 | 
					            var result = false;
 | 
				
			||||||
            localStorage.removeItem('taipei-a');
 | 
					            if (str.length > 0) {
 | 
				
			||||||
        }
 | 
					                if ($.trim(str) != '') {
 | 
				
			||||||
    });
 | 
					                    result = true;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else {
 | 
				
			||||||
 | 
					                    result = false;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return result;
 | 
				
			||||||
 | 
					        }, "不可填入空白");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $("#password").change(function () {
 | 
					        $("#rememberme").click(function () {
 | 
				
			||||||
        if (remember) {
 | 
					            if (remember) {
 | 
				
			||||||
            localStorage.setItem('taipei-p', btoa($("#password").val()));
 | 
					                localStorage.setItem('mitsubishi-t', 'false');
 | 
				
			||||||
        } else {
 | 
					                localStorage.removeItem('mitsubishi-a');
 | 
				
			||||||
            localStorage.removeItem('taipei-p');
 | 
					                localStorage.removeItem('mitsubishi-p');
 | 
				
			||||||
 | 
					                remember = false;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                localStorage.setItem('mitsubishi-t', 'true');
 | 
				
			||||||
 | 
					                localStorage.setItem('mitsubishi-a', btoa($("#account").val()));
 | 
				
			||||||
 | 
					                localStorage.setItem('mitsubishi-p', btoa($("#password").val()));
 | 
				
			||||||
 | 
					                remember = true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $("#account").change(function () {
 | 
				
			||||||
 | 
					            if (remember) {
 | 
				
			||||||
 | 
					                localStorage.setItem('mitsubishi-a', btoa($("#account").val()));
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                localStorage.removeItem('mitsubishi-a');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $("#password").change(function () {
 | 
				
			||||||
 | 
					            if (remember) {
 | 
				
			||||||
 | 
					                localStorage.setItem('mitsubishi-p', btoa($("#password").val()));
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                localStorage.removeItem('mitsubishi-p');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $("#login-form").on("submit", function (e) {
 | 
				
			||||||
 | 
					            e.preventDefault();
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    function Login(account, e) {
 | 
				
			||||||
 | 
					        e ? e.preventDefault() : "";
 | 
				
			||||||
 | 
					        /*if ($("#login-form").valid()) {*/
 | 
				
			||||||
 | 
					        var url = baseApiUrl + "/api/Login/";
 | 
				
			||||||
 | 
					        var send_data = {
 | 
				
			||||||
 | 
					            account: account,
 | 
				
			||||||
 | 
					            password: "rJ2T5Kkj"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    });
 | 
					        if (location.href.indexOf("localhost:5966") != -1) {
 | 
				
			||||||
 | 
					            send_data = {
 | 
				
			||||||
 | 
					                account: $("#account").val(),
 | 
				
			||||||
 | 
					                password: $("#password").val()
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        $.ajax({
 | 
				
			||||||
 | 
					            method: "post",
 | 
				
			||||||
 | 
					            url: url,
 | 
				
			||||||
 | 
					            data: JSON.stringify(send_data),
 | 
				
			||||||
 | 
					            async: false,
 | 
				
			||||||
 | 
					            contentType: "application/json; charset=UTF-8",
 | 
				
			||||||
 | 
					            dataType: 'json',
 | 
				
			||||||
 | 
					            success: function (rel) {
 | 
				
			||||||
 | 
					                console.log(rel)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                //rel = JSON.stringify(rel);
 | 
				
			||||||
 | 
					                if (rel.code != "0000") {
 | 
				
			||||||
 | 
					                    toast_error(rel.msg || "系統內部發生錯誤,請聯絡系統管理員");
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else {
 | 
				
			||||||
 | 
					                    toast_ok(rel.msg);
 | 
				
			||||||
 | 
					                    localStorage.setItem('JWT-Authorization', rel.data.token);
 | 
				
			||||||
 | 
					                    location.href = "index.html";
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            error: function (xhr, textStatus, thrownError) {
 | 
				
			||||||
 | 
					                alert(textStatus);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script type="text/javascript">
 | 
					<script type="text/javascript">
 | 
				
			||||||
    //#region 登入表單驗證
 | 
					    //#region 登入表單驗證
 | 
				
			||||||
    var loginValidate = $("#login-form").validate({
 | 
					 | 
				
			||||||
        rules: {
 | 
					 | 
				
			||||||
            account: {
 | 
					 | 
				
			||||||
                required: true,
 | 
					 | 
				
			||||||
                maxlength: 50,
 | 
					 | 
				
			||||||
                filterspace: true
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            password: {
 | 
					 | 
				
			||||||
                required: true,
 | 
					 | 
				
			||||||
                maxlength: 50,
 | 
					 | 
				
			||||||
                filterspace: true
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //驗證是否為空白
 | 
					 | 
				
			||||||
    jQuery.validator.addMethod("filterspace", function (value, element) {
 | 
					 | 
				
			||||||
        var str = value;
 | 
					 | 
				
			||||||
        var result = false;
 | 
					 | 
				
			||||||
        if (str.length > 0) {
 | 
					 | 
				
			||||||
            if ($.trim(str) != '') {
 | 
					 | 
				
			||||||
                result = true;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else {
 | 
					 | 
				
			||||||
                result = false;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return result;
 | 
					 | 
				
			||||||
    }, "不可填入空白");
 | 
					 | 
				
			||||||
    //#endregion
 | 
					    //#endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function Login(e) {
 | 
					
 | 
				
			||||||
        e.preventDefault();
 | 
					 | 
				
			||||||
        if ($("#login-form").valid()) {
 | 
					 | 
				
			||||||
            var url = baseApiUrl + "/api/Login/";
 | 
					 | 
				
			||||||
            var send_data = {
 | 
					 | 
				
			||||||
                account: "admin",
 | 
					 | 
				
			||||||
                password: "123456"
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            $.ajax({
 | 
					 | 
				
			||||||
                method: "post",
 | 
					 | 
				
			||||||
                url: url,
 | 
					 | 
				
			||||||
                data: JSON.stringify(send_data),
 | 
					 | 
				
			||||||
                async: false,
 | 
					 | 
				
			||||||
                contentType:"application/json; charset=UTF-8",
 | 
					 | 
				
			||||||
                dataType: 'json',
 | 
					 | 
				
			||||||
                success: function (rel) {
 | 
					 | 
				
			||||||
                    //rel = JSON.stringify(rel);
 | 
					 | 
				
			||||||
                    if (rel.code != "0000") {
 | 
					 | 
				
			||||||
                        toast_error(rel.msg || "系統內部發生錯誤,請聯絡系統管理員");
 | 
					 | 
				
			||||||
                        return;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    else {
 | 
					 | 
				
			||||||
                        toast_ok(rel.msg);
 | 
					 | 
				
			||||||
                        localStorage.setItem('JWT-Authorization', rel.data.token);
 | 
					 | 
				
			||||||
                        location.href = "index.html";
 | 
					 | 
				
			||||||
                        return;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                error: function (xhr, textStatus, thrownError) {
 | 
					 | 
				
			||||||
                    toast_error(textStatus);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user